aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/mips
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-07-02 15:01:50 -0700
committerAndrew Kelley <andrew@ziglang.org>2025-07-02 15:01:50 -0700
commit5ae2428d52da3211ee7b1577fe01894dc10f0619 (patch)
tree1cafa007289566834d110de803788c5c9cb8a908 /src/codegen/mips
parenta13f0d40eb0109e993d37ef4be9107a57e821bc9 (diff)
downloadzig-5ae2428d52da3211ee7b1577fe01894dc10f0619.tar.gz
zig-5ae2428d52da3211ee7b1577fe01894dc10f0619.zip
compiler: change canonical path for backend ABI source files
Diffstat (limited to 'src/codegen/mips')
-rw-r--r--src/codegen/mips/abi.zig84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/codegen/mips/abi.zig b/src/codegen/mips/abi.zig
new file mode 100644
index 0000000000..02c4c637a4
--- /dev/null
+++ b/src/codegen/mips/abi.zig
@@ -0,0 +1,84 @@
+const std = @import("std");
+const Type = @import("../../Type.zig");
+const Zcu = @import("../../Zcu.zig");
+const assert = std.debug.assert;
+
+pub const Class = union(enum) {
+ memory,
+ byval,
+ i32_array: u8,
+};
+
+pub const Context = enum { ret, arg };
+
+pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
+ const target = zcu.getTarget();
+ std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
+
+ const max_direct_size = target.ptrBitWidth() * 2;
+ switch (ty.zigTypeTag(zcu)) {
+ .@"struct" => {
+ const bit_size = ty.bitSize(zcu);
+ if (ty.containerLayout(zcu) == .@"packed") {
+ if (bit_size > max_direct_size) return .memory;
+ return .byval;
+ }
+ if (bit_size > max_direct_size) return .memory;
+ // TODO: for bit_size <= 32 using byval is more correct, but that needs inreg argument attribute
+ const count = @as(u8, @intCast(std.mem.alignForward(u64, bit_size, 32) / 32));
+ return .{ .i32_array = count };
+ },
+ .@"union" => {
+ const bit_size = ty.bitSize(zcu);
+ if (ty.containerLayout(zcu) == .@"packed") {
+ if (bit_size > max_direct_size) return .memory;
+ return .byval;
+ }
+ if (bit_size > max_direct_size) return .memory;
+
+ return .byval;
+ },
+ .bool => return .byval,
+ .float => return .byval,
+ .int, .@"enum", .error_set => {
+ return .byval;
+ },
+ .vector => {
+ const elem_type = ty.elemType2(zcu);
+ switch (elem_type.zigTypeTag(zcu)) {
+ .bool, .int => {
+ const bit_size = ty.bitSize(zcu);
+ if (ctx == .ret and bit_size > 128) return .memory;
+ if (bit_size > 512) return .memory;
+ // TODO: byval vector arguments with non power of 2 size need inreg attribute
+ return .byval;
+ },
+ .float => return .memory,
+ else => unreachable,
+ }
+ },
+ .optional => {
+ std.debug.assert(ty.isPtrLikeOptional(zcu));
+ return .byval;
+ },
+ .pointer => {
+ std.debug.assert(!ty.isSlice(zcu));
+ return .byval;
+ },
+ .error_union,
+ .frame,
+ .@"anyframe",
+ .noreturn,
+ .void,
+ .type,
+ .comptime_float,
+ .comptime_int,
+ .undefined,
+ .null,
+ .@"fn",
+ .@"opaque",
+ .enum_literal,
+ .array,
+ => unreachable,
+ }
+}