diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index d9f31b4a14..de866b7964 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/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| { diff --git a/src/arch/riscv64/abi.zig b/src/arch/riscv64/abi.zig index 468fede917..9fbb63638e 100644 --- a/src/arch/riscv64/abi.zig +++ b/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)}), } diff --git a/src/arch/riscv64/bits.zig b/src/arch/riscv64/bits.zig index d3dd78cf3e..eef0828cdb 100644 --- a/src/arch/riscv64/bits.zig +++ b/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, }; diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 883540d31c..337cc5eb5a 100644 --- a/test/behavior/basic.zig +++ b/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;