authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-03-24 19:39:37-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-11 02:17:11-07:00
logc96989aa4b283c5d386c5f19e2b12a6b13dd521a
tree5febf790a416e5168cb9d0a08c6a2c6360b59528
parent09b7aabe094c11d7e4772c2e0c67ec7c28672266

riscv: correctly index struct field access

when the struct is in stack memory, we access it using a byte-offset, because that's how the stack works. on the other hand when the struct is in a register, we are working with bits and the field offset should be a bit offset.

1 files changed, 24 insertions(+), 15 deletions(-)

src/arch/riscv64/CodeGen.zig+24-15
...@@ -1184,28 +1184,36 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1184,28 +1184,36 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1184 const lhs_ty = self.typeOf(extra.lhs);1184 const lhs_ty = self.typeOf(extra.lhs);
1185 const rhs_ty = self.typeOf(extra.rhs);1185 const rhs_ty = self.typeOf(extra.rhs);
11861186
1187 const partial_mcv = try self.binOp(.add, null, lhs, rhs, lhs_ty, rhs_ty);1187 const add_result_mcv = try self.binOp(.add, null, lhs, rhs, lhs_ty, rhs_ty);
11881188
1189 const tuple_ty = self.typeOfIndex(inst);1189 const tuple_ty = self.typeOfIndex(inst);
1190 const int_info = lhs_ty.intInfo(mod);
11901191
1191 // TODO: optimization, set this to true. needs the other struct access stuff to support1192 // TODO: optimization, set this to true. needs the other struct access stuff to support
1192 // accessing registers.1193 // accessing registers.
1193 const result_mcv = try self.allocRegOrMem(inst, false);1194 const result_mcv = try self.allocRegOrMem(inst, false);
1194 const offset = result_mcv.stack_offset;1195 const offset = result_mcv.stack_offset;
11951196
1196 const overflow_offset = tuple_ty.structFieldOffset(1, mod) + offset;
1197 const result_offset = tuple_ty.structFieldOffset(0, mod) + offset;1197 const result_offset = tuple_ty.structFieldOffset(0, mod) + offset;
11981198
1199 const overflow_mcv = try self.binOp(.cmp_lt, null, partial_mcv, lhs, lhs_ty, lhs_ty);1199 // set the result first as we don't have a lock on the add_result_mcv register and it will
1200 // get clobbered in the next binOp.
1201 try self.genSetStack(lhs_ty, @intCast(result_offset), add_result_mcv);
12001202
1201 const overflow_reg, const overflow_lock = try self.allocReg();1203 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
1202 defer self.register_manager.unlockReg(overflow_lock);1204 if (int_info.signedness == .unsigned) {
1205 const overflow_offset = tuple_ty.structFieldOffset(1, mod) + offset;
12031206
1204 try self.genSetReg(lhs_ty, overflow_reg, overflow_mcv);1207 const overflow_mcv = try self.binOp(.cmp_lt, null, add_result_mcv, lhs, lhs_ty, lhs_ty);
1208 try self.genSetStack(Type.u1, @intCast(overflow_offset), overflow_mcv);
12051209
1206 try self.genSetStack(Type.u1, @intCast(overflow_offset), overflow_mcv);1210 break :result result_mcv;
1207 try self.genSetStack(lhs_ty, @intCast(result_offset), partial_mcv);1211 } else {
1208 break :result result_mcv;1212 return self.fail("TODO: airAddWithOverFlow calculate carry for signed addition", .{});
1213 }
1214 } else {
1215 return self.fail("TODO: airAddWithOverflow with < 8 bits or non-pow of 2", .{});
1216 }
1209 };1217 };
12101218
1211 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });1219 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
...@@ -1716,9 +1724,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -1716,9 +1724,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
17161724
1717/// Loads `value` into the "payload" of `pointer`.1725/// Loads `value` into the "payload" of `pointer`.
1718fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void {1726fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void {
1719 _ = ptr_ty;
1720 const mod = self.bin_file.comp.module.?;1727 const mod = self.bin_file.comp.module.?;
1721 const value_size = value_ty.abiSize(mod);1728 const value_abi_size = value_ty.abiSize(mod);
17221729
1723 log.debug("storing {s}", .{@tagName(pointer)});1730 log.debug("storing {s}", .{@tagName(pointer)});
17241731
...@@ -1741,9 +1748,9 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty:...@@ -1741,9 +1748,9 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty:
1741 .register => |reg| {1748 .register => |reg| {
1742 const value_reg = try self.copyToTmpRegister(value_ty, value);1749 const value_reg = try self.copyToTmpRegister(value_ty, value);
17431750
1744 switch (value_size) {1751 switch (value_abi_size) {
1745 1, 2, 4, 8 => {1752 1, 2, 4, 8 => {
1746 const tag: Mir.Inst.Tag = switch (value_size) {1753 const tag: Mir.Inst.Tag = switch (value_abi_size) {
1747 1 => .sb,1754 1 => .sb,
1748 2 => .sh,1755 2 => .sh,
1749 4 => .sw,1756 4 => .sw,
...@@ -1760,7 +1767,7 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty:...@@ -1760,7 +1767,7 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty:
1760 } },1767 } },
1761 });1768 });
1762 },1769 },
1763 else => return self.fail("TODO: genSetStack for size={d}", .{value_size}),1770 else => return self.fail("TODO: genSetStack for size={d}", .{value_abi_size}),
1764 }1771 }
1765 },1772 },
1766 else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(pointer)}),1773 else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(pointer)}),
...@@ -1842,7 +1849,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1842,7 +1849,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
1842 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);1849 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);
1843 },1850 },
1844 .stack_offset => |off| {1851 .stack_offset => |off| {
1845 break :result MCValue{ .stack_offset = off + field_off };1852 log.debug("airStructFieldVal off: {}", .{field_off});
1853 const field_byte_off: u32 = @divExact(field_off, 8);
1854 break :result MCValue{ .stack_offset = off + field_byte_off };
1846 },1855 },
1847 else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),1856 else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),
1848 }1857 }