Commit a615fbc1f8

David Rubin <daviru007@icloud.com>
2024-04-15 00:07:02
riscv: mutable globals
1 parent d9e0caf
Changed files (4)
src
test
behavior
src/arch/riscv64/abi.zig
@@ -4,6 +4,7 @@ const Register = bits.Register;
 const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
 const Type = @import("../../type.zig").Type;
 const Module = @import("../../Module.zig");
+const assert = std.debug.assert;
 
 pub const Class = enum { memory, byval, integer, double_integer, fields, none };
 
@@ -93,14 +94,16 @@ pub fn classifyType(ty: Type, mod: *Module) Class {
 
 /// There are a maximum of 8 possible return slots. Returned values are in
 /// the beginning of the array; unused slots are filled with .none.
-pub fn classifySystem(ty: Type, mod: *Module) [8]Class {
+pub fn classifySystem(ty: Type, zcu: *Module) [8]Class {
+    const ip = zcu.intern_pool;
     var result = [1]Class{.none} ** 8;
-    switch (ty.zigTypeTag(mod)) {
+
+    switch (ty.zigTypeTag(zcu)) {
         .Bool, .Void, .NoReturn => {
             result[0] = .integer;
             return result;
         },
-        .Pointer => switch (ty.ptrSize(mod)) {
+        .Pointer => switch (ty.ptrSize(zcu)) {
             .Slice => {
                 result[0] = .integer;
                 result[1] = .integer;
@@ -112,7 +115,7 @@ pub fn classifySystem(ty: Type, mod: *Module) [8]Class {
             },
         },
         .Optional => {
-            if (ty.isPtrLikeOptional(mod)) {
+            if (ty.isPtrLikeOptional(zcu)) {
                 result[0] = .integer;
                 return result;
             }
@@ -121,7 +124,7 @@ pub fn classifySystem(ty: Type, mod: *Module) [8]Class {
             return result;
         },
         .Int, .Enum, .ErrorSet => {
-            const int_bits = ty.intInfo(mod).bits;
+            const int_bits = ty.intInfo(zcu).bits;
             if (int_bits <= 64) {
                 result[0] = .integer;
                 return result;
@@ -134,8 +137,8 @@ pub fn classifySystem(ty: Type, mod: *Module) [8]Class {
             unreachable; // support > 128 bit int arguments
         },
         .ErrorUnion => {
-            const payload_ty = ty.errorUnionPayload(mod);
-            const payload_bits = payload_ty.bitSize(mod);
+            const payload_ty = ty.errorUnionPayload(zcu);
+            const payload_bits = payload_ty.bitSize(zcu);
 
             // the error union itself
             result[0] = .integer;
@@ -143,7 +146,20 @@ pub fn classifySystem(ty: Type, mod: *Module) [8]Class {
             // anyerror!void can fit into one register
             if (payload_bits == 0) return result;
 
-            std.debug.panic("support ErrorUnion payload {}", .{payload_ty.fmt(mod)});
+            std.debug.panic("support ErrorUnion payload {}", .{payload_ty.fmt(zcu)});
+        },
+        .Struct => {
+            const loaded_struct = ip.loadStructType(ty.toIntern());
+            const ty_size = ty.abiSize(zcu);
+
+            if (loaded_struct.layout == .@"packed") {
+                assert(ty_size <= 16);
+                result[0] = .integer;
+                if (ty_size > 8) result[1] = .integer;
+                return result;
+            }
+
+            std.debug.panic("support Struct in classifySystem", .{});
         },
         else => |bad_ty| std.debug.panic("classifySystem {s}", .{@tagName(bad_ty)}),
     }
src/arch/riscv64/bits.zig
@@ -20,7 +20,7 @@ pub const Memory = struct {
             size: Size,
             disp: i32 = 0,
         },
-        off: u64,
+        off: i32,
     };
 
     pub const Size = enum(u4) {
@@ -33,7 +33,7 @@ pub const Memory = struct {
         /// Double word, 8 Bytes
         dword,
 
-        pub fn fromSize(size: u32) Size {
+        pub fn fromByteSize(size: u64) Size {
             return switch (size) {
                 1 => .byte,
                 2 => .hword,
@@ -66,7 +66,7 @@ pub const Memory = struct {
     /// Asserts `mem` can be represented as a `FrameLoc`.
     pub fn toFrameLoc(mem: Memory, mir: Mir) Mir.FrameLoc {
         const offset: i32 = switch (mem.mod) {
-            .off => |off| @intCast(off),
+            .off => |off| off,
             .rm => |rm| rm.disp,
         };
 
src/arch/riscv64/CodeGen.zig
@@ -1452,7 +1452,7 @@ fn computeFrameLayout(self: *Self) !FrameLayout {
     const spill_frame_size = frame_size[@intFromEnum(FrameIndex.spill_frame)];
     const call_frame_size = frame_size[@intFromEnum(FrameIndex.call_frame)];
 
-    // TODO: this 24 should be a 16, but we were clobbering the top and bottom of the frame.
+    // TODO: this 64 should be a 16, but we were clobbering the top and bottom of the frame.
     // maybe everything can go from the bottom?
     const acc_frame_size: i32 = std.mem.alignForward(
         i32,
@@ -1497,7 +1497,7 @@ fn memSize(self: *Self, ty: Type) Memory.Size {
     const mod = self.bin_file.comp.module.?;
     return switch (ty.zigTypeTag(mod)) {
         .Float => Memory.Size.fromBitSize(ty.floatBits(self.target.*)),
-        else => Memory.Size.fromSize(@intCast(ty.abiSize(mod))),
+        else => Memory.Size.fromByteSize(ty.abiSize(mod)),
     };
 }
 
@@ -4318,6 +4318,21 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
                 .off = -dst_reg_off.off,
             } },
         }),
+        .indirect => |ro| {
+            const src_reg = try self.copyToTmpRegister(ty, src_mcv);
+
+            _ = try self.addInst(.{
+                .tag = .pseudo,
+                .ops = .pseudo_store_rm,
+                .data = .{ .rm = .{
+                    .r = src_reg,
+                    .m = .{
+                        .base = .{ .reg = ro.reg },
+                        .mod = .{ .rm = .{ .disp = ro.off, .size = self.memSize(ty) } },
+                    },
+                } },
+            });
+        },
         .load_frame => |frame| return self.genSetStack(ty, frame, src_mcv),
         .memory => return self.fail("TODO: genCopy memory", .{}),
         .register_pair => |dst_regs| {
test/behavior/basic.zig
@@ -67,7 +67,6 @@ var g2: i32 = 0;
 
 test "global variables" {
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
 
     try expect(g2 == 0);
     g2 = g1;