authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-03-23 14:55:33-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-11 02:17:11-07:00
logf1fe5c937e5587064dde4ab357e9efe277a5ea49
tree609c02e73d4409cd1da7f32d409518f33c3444b5
parent92293214009cbf5d8aede56a5f54f533173324d5

riscv: pointer work

lots of thinking later, ive begun to grasp my head around how the pointers should work. this commit allows basic pointer loading and storing to happen.

3 files changed, 88 insertions(+), 39 deletions(-)

src/arch/riscv64/CodeGen.zig+85-37
...@@ -1666,28 +1666,6 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind...@@ -1666,28 +1666,6 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
1666 return true;1666 return true;
1667}1667}
16681668
1669fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerError!void {
1670 const mod = self.bin_file.comp.module.?;
1671 const elem_ty = ptr_ty.childType(mod);
1672
1673 switch (src_ptr) {
1674 .none => unreachable,
1675 .undef => unreachable,
1676 .unreach => unreachable,
1677 .dead => unreachable,
1678 .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }),
1679 .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }),
1680 .stack_offset,
1681 .register,
1682 => try self.setValue(elem_ty, dst_mcv, src_ptr),
1683 .memory => return self.fail("TODO: load memory", .{}),
1684 .load_symbol => {
1685 const reg = try self.copyToTmpRegister(ptr_ty, src_ptr);
1686 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
1687 },
1688 }
1689}
1690
1691fn airLoad(self: *Self, inst: Air.Inst.Index) !void {1669fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1692 const mod = self.bin_file.comp.module.?;1670 const mod = self.bin_file.comp.module.?;
1693 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1671 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
...@@ -1706,8 +1684,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -1706,8 +1684,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1706 // The MCValue that holds the pointer can be re-used as the value.1684 // The MCValue that holds the pointer can be re-used as the value.
1707 break :blk ptr;1685 break :blk ptr;
1708 } else {1686 } else {
1709 // TODO: set this to true, will need to implement register version of arrays and structs1687 break :blk try self.allocRegOrMem(inst, true);
1710 break :blk try self.allocRegOrMem(inst, false);
1711 }1688 }
1712 };1689 };
1713 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));1690 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));
...@@ -1716,18 +1693,27 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -1716,18 +1693,27 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1716 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1693 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1717}1694}
17181695
1719fn store(self: *Self, dst_ptr: MCValue, src_val: MCValue, ptr_ty: Type, value_ty: Type) !void {1696fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerError!void {
1720 _ = ptr_ty;1697 const mod = self.bin_file.comp.module.?;
17211698 const elem_ty = ptr_ty.childType(mod);
1722 log.debug("storing {s}", .{@tagName(dst_ptr)});
17231699
1724 switch (dst_ptr) {1700 switch (src_ptr) {
1725 .none => unreachable,1701 .none => unreachable,
1726 .undef => unreachable,1702 .undef => unreachable,
1727 .unreach => unreachable,1703 .unreach => unreachable,
1728 .dead => unreachable,1704 .dead => unreachable,
1729 .ptr_stack_offset => |off| try self.genSetStack(value_ty, off, src_val),1705 .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }),
1730 else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(dst_ptr)}),1706 .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }),
1707
1708 .stack_offset,
1709 .register,
1710 .memory,
1711 => try self.setValue(elem_ty, dst_mcv, src_ptr),
1712
1713 .load_symbol => {
1714 const reg = try self.copyToTmpRegister(ptr_ty, src_ptr);
1715 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
1716 },
1731 }1717 }
1732}1718}
17331719
...@@ -1748,6 +1734,50 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {...@@ -1748,6 +1734,50 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1748 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });1734 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1749}1735}
17501736
1737/// Loads `value` into the "payload" of `pointer`.
1738fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void {
1739 _ = ptr_ty;
1740 const mod = self.bin_file.comp.module.?;
1741 const value_size = value_ty.abiSize(mod);
1742
1743 log.debug("storing {s}", .{@tagName(pointer)});
1744
1745 switch (pointer) {
1746 .none => unreachable,
1747 .undef => unreachable,
1748 .unreach => unreachable,
1749 .dead => unreachable,
1750 .ptr_stack_offset => |off| try self.genSetStack(value_ty, off, value),
1751
1752 .register => |reg| {
1753 const value_reg = try self.copyToTmpRegister(value_ty, value);
1754
1755 switch (value_size) {
1756 1, 2, 4, 8 => {
1757 const tag: Mir.Inst.Tag = switch (value_size) {
1758 1 => .sb,
1759 2 => .sh,
1760 4 => .sw,
1761 8 => .sd,
1762 else => unreachable,
1763 };
1764
1765 _ = try self.addInst(.{
1766 .tag = tag,
1767 .data = .{ .i_type = .{
1768 .rd = value_reg,
1769 .rs1 = reg,
1770 .imm12 = 0,
1771 } },
1772 });
1773 },
1774 else => return self.fail("TODO: genSetStack for size={d}", .{value_size}),
1775 }
1776 },
1777 else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(pointer)}),
1778 }
1779}
1780
1751fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {1781fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
1752 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;1782 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
1753 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;1783 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
...@@ -2693,10 +2723,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner...@@ -2693,10 +2723,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
2693 if (!self.wantSafety()) return;2723 if (!self.wantSafety()) return;
2694 try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa });2724 try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
2695 },2725 },
2696 .immediate => {2726 .immediate,
2727 .ptr_stack_offset,
2728 => {
2729 // TODO: remove this lock in favor of a copyToTmpRegister when we load 64 bit immediates with
2730 // a register allocation.
2697 const reg = try self.register_manager.allocReg(null, gp);2731 const reg = try self.register_manager.allocReg(null, gp);
2698 const reg_lock = self.register_manager.lockReg(reg);2732 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
2699 defer if (reg_lock) |lock| self.register_manager.unlockReg(lock);2733 defer self.register_manager.unlockReg(reg_lock);
27002734
2701 try self.genSetReg(ty, reg, src_val);2735 try self.genSetReg(ty, reg, src_val);
27022736
...@@ -2849,7 +2883,18 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError!...@@ -2849,7 +2883,18 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError!
28492883
2850 switch (src_val) {2884 switch (src_val) {
2851 .dead => unreachable,2885 .dead => unreachable,
2852 .ptr_stack_offset => |off| try self.genSetReg(ty, reg, .{ .stack_offset = off }),2886 .ptr_stack_offset => |off| {
2887 _ = try self.addInst(.{
2888 .tag = .addi,
2889 .data = .{ .i_type = .{
2890 .rd = reg,
2891 .rs1 = .s0,
2892 .imm12 = math.cast(i12, off) orelse {
2893 return self.fail("TODO: bigger stack sizes", .{});
2894 },
2895 } },
2896 });
2897 },
2853 .unreach, .none => return, // Nothing to do.2898 .unreach, .none => return, // Nothing to do.
2854 .undef => {2899 .undef => {
2855 if (!self.wantSafety())2900 if (!self.wantSafety())
...@@ -3166,6 +3211,8 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -3166,6 +3211,8 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
31663211
3167fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {3212fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
3168 const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;3213 const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;
3214 // TODO: RISC-V does have prefetch instruction variants.
3215 // see here: https://raw.githubusercontent.com/riscv/riscv-CMOs/master/specifications/cmobase-v1.0.1.pdf
3169 return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });3216 return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
3170}3217}
31713218
...@@ -3205,12 +3252,13 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -3205,12 +3252,13 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
32053252
3206fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {3253fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
3207 const mod = self.bin_file.comp.module.?;3254 const mod = self.bin_file.comp.module.?;
3208 const mcv: MCValue = switch (try codegen.genTypedValue(3255 const result = try codegen.genTypedValue(
3209 self.bin_file,3256 self.bin_file,
3210 self.src_loc,3257 self.src_loc,
3211 val,3258 val,
3212 mod.funcOwnerDeclIndex(self.func_index),3259 mod.funcOwnerDeclIndex(self.func_index),
3213 )) {3260 );
3261 const mcv: MCValue = switch (result) {
3214 .mcv => |mcv| switch (mcv) {3262 .mcv => |mcv| switch (mcv) {
3215 .none => .none,3263 .none => .none,
3216 .undef => .undef,3264 .undef => .undef,
src/arch/riscv64/Emit.zig+1
...@@ -442,6 +442,7 @@ fn isStore(tag: Mir.Inst.Tag) bool {...@@ -442,6 +442,7 @@ fn isStore(tag: Mir.Inst.Tag) bool {
442 .sh => true,442 .sh => true,
443 .sw => true,443 .sw => true,
444 .sd => true,444 .sd => true,
445 .addi => true, // needed for ptr_stack_offset stores
445 else => false,446 else => false,
446 };447 };
447}448}
src/arch/riscv64/Mir.zig+2-2
...@@ -72,9 +72,9 @@ pub const Inst = struct {...@@ -72,9 +72,9 @@ pub const Inst = struct {
72 /// allocate a register for temporary use.72 /// allocate a register for temporary use.
73 cmp_imm_gte,73 cmp_imm_gte,
7474
75 /// Branch if equal Uses b_type75 /// Branch if equal, Uses b_type
76 beq,76 beq,
77 /// Branch if not eql Uses b_type77 /// Branch if not equal, Uses b_type
78 bne,78 bne,
7979
80 nop,80 nop,