diff options
| author | David Rubin <daviru007@icloud.com> | 2024-03-23 14:55:33 -0700 |
|---|---|---|
| committer | David Rubin <daviru007@icloud.com> | 2024-05-11 02:17:11 -0700 |
| commit | f1fe5c937e5587064dde4ab357e9efe277a5ea49 (patch) | |
| tree | 609c02e73d4409cd1da7f32d409518f33c3444b5 /src | |
| parent | 92293214009cbf5d8aede56a5f54f533173324d5 (diff) | |
| download | zig-f1fe5c937e5587064dde4ab357e9efe277a5ea49.tar.gz zig-f1fe5c937e5587064dde4ab357e9efe277a5ea49.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 122 | ||||
| -rw-r--r-- | src/arch/riscv64/Emit.zig | 1 | ||||
| -rw-r--r-- | src/arch/riscv64/Mir.zig | 4 |
3 files changed, 88 insertions, 39 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index bc844f1b5f..bdf42e10c7 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1666,28 +1666,6 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind return true; } -fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerError!void { - const mod = self.bin_file.comp.module.?; - const elem_ty = ptr_ty.childType(mod); - - switch (src_ptr) { - .none => unreachable, - .undef => unreachable, - .unreach => unreachable, - .dead => unreachable, - .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }), - .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }), - .stack_offset, - .register, - => try self.setValue(elem_ty, dst_mcv, src_ptr), - .memory => return self.fail("TODO: load memory", .{}), - .load_symbol => { - const reg = try self.copyToTmpRegister(ptr_ty, src_ptr); - try self.load(dst_mcv, .{ .register = reg }, ptr_ty); - }, - } -} - fn airLoad(self: *Self, inst: Air.Inst.Index) !void { const mod = self.bin_file.comp.module.?; 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 { // The MCValue that holds the pointer can be re-used as the value. break :blk ptr; } else { - // TODO: set this to true, will need to implement register version of arrays and structs - break :blk try self.allocRegOrMem(inst, false); + break :blk try self.allocRegOrMem(inst, true); } }; try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand)); @@ -1716,18 +1693,27 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } -fn store(self: *Self, dst_ptr: MCValue, src_val: MCValue, ptr_ty: Type, value_ty: Type) !void { - _ = ptr_ty; - - log.debug("storing {s}", .{@tagName(dst_ptr)}); +fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerError!void { + const mod = self.bin_file.comp.module.?; + const elem_ty = ptr_ty.childType(mod); - switch (dst_ptr) { + switch (src_ptr) { .none => unreachable, .undef => unreachable, .unreach => unreachable, .dead => unreachable, - .ptr_stack_offset => |off| try self.genSetStack(value_ty, off, src_val), - else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(dst_ptr)}), + .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }), + .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }), + + .stack_offset, + .register, + .memory, + => try self.setValue(elem_ty, dst_mcv, src_ptr), + + .load_symbol => { + const reg = try self.copyToTmpRegister(ptr_ty, src_ptr); + try self.load(dst_mcv, .{ .register = reg }, ptr_ty); + }, } } @@ -1748,6 +1734,50 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); } +/// Loads `value` into the "payload" of `pointer`. +fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void { + _ = ptr_ty; + const mod = self.bin_file.comp.module.?; + const value_size = value_ty.abiSize(mod); + + log.debug("storing {s}", .{@tagName(pointer)}); + + switch (pointer) { + .none => unreachable, + .undef => unreachable, + .unreach => unreachable, + .dead => unreachable, + .ptr_stack_offset => |off| try self.genSetStack(value_ty, off, value), + + .register => |reg| { + const value_reg = try self.copyToTmpRegister(value_ty, value); + + switch (value_size) { + 1, 2, 4, 8 => { + const tag: Mir.Inst.Tag = switch (value_size) { + 1 => .sb, + 2 => .sh, + 4 => .sw, + 8 => .sd, + else => unreachable, + }; + + _ = try self.addInst(.{ + .tag = tag, + .data = .{ .i_type = .{ + .rd = value_reg, + .rs1 = reg, + .imm12 = 0, + } }, + }); + }, + else => return self.fail("TODO: genSetStack for size={d}", .{value_size}), + } + }, + else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(pointer)}), + } +} + fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; 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 if (!self.wantSafety()) return; try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }); }, - .immediate => { + .immediate, + .ptr_stack_offset, + => { + // TODO: remove this lock in favor of a copyToTmpRegister when we load 64 bit immediates with + // a register allocation. const reg = try self.register_manager.allocReg(null, gp); - const reg_lock = self.register_manager.lockReg(reg); - defer if (reg_lock) |lock| self.register_manager.unlockReg(lock); + const reg_lock = self.register_manager.lockRegAssumeUnused(reg); + defer self.register_manager.unlockReg(reg_lock); try self.genSetReg(ty, reg, src_val); @@ -2849,7 +2883,18 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError! switch (src_val) { .dead => unreachable, - .ptr_stack_offset => |off| try self.genSetReg(ty, reg, .{ .stack_offset = off }), + .ptr_stack_offset => |off| { + _ = try self.addInst(.{ + .tag = .addi, + .data = .{ .i_type = .{ + .rd = reg, + .rs1 = .s0, + .imm12 = math.cast(i12, off) orelse { + return self.fail("TODO: bigger stack sizes", .{}); + }, + } }, + }); + }, .unreach, .none => return, // Nothing to do. .undef => { if (!self.wantSafety()) @@ -3166,6 +3211,8 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; + // TODO: RISC-V does have prefetch instruction variants. + // see here: https://raw.githubusercontent.com/riscv/riscv-CMOs/master/specifications/cmobase-v1.0.1.pdf return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none }); } @@ -3205,12 +3252,13 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { const mod = self.bin_file.comp.module.?; - const mcv: MCValue = switch (try codegen.genTypedValue( + const result = try codegen.genTypedValue( self.bin_file, self.src_loc, val, mod.funcOwnerDeclIndex(self.func_index), - )) { + ); + const mcv: MCValue = switch (result) { .mcv => |mcv| switch (mcv) { .none => .none, .undef => .undef, diff --git a/src/arch/riscv64/Emit.zig b/src/arch/riscv64/Emit.zig index 6c98fca7b9..f6205cd4ab 100644 --- a/src/arch/riscv64/Emit.zig +++ b/src/arch/riscv64/Emit.zig @@ -442,6 +442,7 @@ fn isStore(tag: Mir.Inst.Tag) bool { .sh => true, .sw => true, .sd => true, + .addi => true, // needed for ptr_stack_offset stores else => false, }; } diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig index 68b314bd12..26f3b355c9 100644 --- a/src/arch/riscv64/Mir.zig +++ b/src/arch/riscv64/Mir.zig @@ -72,9 +72,9 @@ pub const Inst = struct { /// allocate a register for temporary use. cmp_imm_gte, - /// Branch if equal Uses b_type + /// Branch if equal, Uses b_type beq, - /// Branch if not eql Uses b_type + /// Branch if not equal, Uses b_type bne, nop, |
