authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-03-17 23:18:48-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-11 02:17:11-07:00
log2cbd8e1deb88e3e23ec3ca34393b824c0d76e5b0
tree84f20399255ade0be34839f00f881c98926bccb3
parent9b2a4582c983a4171de9ab9843d0af1d807ddbff

riscv: progress toward arrays

- implement `airArrayElemVal` for arrays on the stack. This is really easy as we can just move the offset by the bytes into the array. This only works when the index access is comptime-known though, this won't work for runtime access.

1 files changed, 42 insertions(+), 17 deletions(-)

src/arch/riscv64/CodeGen.zig+42-17
......@@ -1442,8 +1442,29 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
14421442}
14431443
14441444fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
1445 const mod = self.bin_file.comp.module.?;
14451446 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
1446 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement array_elem_val for {}", .{self.target.cpu.arch});
1447 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1448 const array_ty = self.typeOf(bin_op.lhs);
1449 const array_mcv = try self.resolveInst(bin_op.lhs);
1450
1451 const index_mcv = try self.resolveInst(bin_op.rhs);
1452
1453 const elem_ty = array_ty.childType(mod);
1454 const elem_abi_size = elem_ty.abiSize(mod);
1455
1456 switch (array_mcv) {
1457 // all we need to do is calculate the offset that the elem exits at.
1458 .stack_offset => |off| {
1459 if (index_mcv == .immediate) {
1460 const true_offset: u32 = @intCast(index_mcv.immediate * elem_abi_size);
1461 break :result MCValue{ .stack_offset = off + true_offset };
1462 }
1463 return self.fail("TODO: airArrayElemVal with runtime index", .{});
1464 },
1465 else => return self.fail("TODO: airArrayElemVal {s}", .{@tagName(array_mcv)}),
1466 }
1467 };
14471468 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
14481469}
14491470
......@@ -1639,17 +1660,10 @@ fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerErro
16391660 .dead => unreachable,
16401661 .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }),
16411662 .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }),
1642 .register => try self.setValue(elem_ty, dst_mcv, src_ptr),
1643 .memory,
16441663 .stack_offset,
1645 => {
1646 const reg = try self.register_manager.allocReg(null, gp);
1647 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
1648 errdefer self.register_manager.unlockReg(reg_lock);
1649
1650 try self.genSetReg(ptr_ty, reg, src_ptr);
1651 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
1652 },
1664 .register,
1665 => try self.setValue(elem_ty, dst_mcv, src_ptr),
1666 .memory => return self.fail("TODO: load memory", .{}),
16531667 .load_symbol => {
16541668 const reg = try self.copyToTmpRegister(ptr_ty, src_ptr);
16551669 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
......@@ -1675,7 +1689,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
16751689 // The MCValue that holds the pointer can be re-used as the value.
16761690 break :blk ptr;
16771691 } else {
1678 break :blk try self.allocRegOrMem(inst, true);
1692 // TODO: set this to true, will need to implement register version of arrays and structs
1693 break :blk try self.allocRegOrMem(inst, false);
16791694 }
16801695 };
16811696 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));
......@@ -1750,7 +1765,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
17501765 const field_ty = struct_ty.structFieldType(index, mod);
17511766 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
17521767
1753 const field_off = @as(u32, @intCast(struct_ty.structFieldOffset(index, mod)));
1768 const field_off: u32 = switch (struct_ty.containerLayout(mod)) {
1769 .Auto, .Extern => @intCast(struct_ty.structFieldOffset(index, mod) * 8),
1770 .Packed => if (mod.typeToStruct(struct_ty)) |struct_type|
1771 mod.structPackedFieldBitOffset(struct_type, index)
1772 else
1773 0,
1774 };
17541775
17551776 switch (src_mcv) {
17561777 .dead, .unreach => unreachable,
......@@ -1778,10 +1799,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
17781799 },
17791800 },
17801801 });
1802
1803 return self.fail("TODO: airStructFieldVal register with field_off > 0", .{});
17811804 }
17821805
17831806 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);
17841807 },
1808 .stack_offset => |off| {
1809 break :result MCValue{ .stack_offset = off + field_off };
1810 },
17851811 else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),
17861812 }
17871813 };
......@@ -2435,7 +2461,8 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index, target: Mir.Inst.Index) !void
24352461 .bne,
24362462 .beq,
24372463 => self.mir_instructions.items(.data)[inst].b_type.inst = target,
2438 .jal => self.mir_instructions.items(.data)[inst].j_type.inst = target,
2464 .jal,
2465 => self.mir_instructions.items(.data)[inst].j_type.inst = target,
24392466 else => return self.fail("TODO: performReloc {s}", .{@tagName(tag)}),
24402467 }
24412468}
......@@ -2614,6 +2641,7 @@ fn setValue(self: *Self, ty: Type, dst_val: MCValue, src_val: MCValue) !void {
26142641 if (dst_val == .none) return;
26152642
26162643 if (!dst_val.isMutable()) {
2644 // panic so we can see the trace
26172645 return std.debug.panic("tried to setValue immutable: {s}", .{@tagName(dst_val)});
26182646 }
26192647
......@@ -2649,8 +2677,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
26492677 .register => |reg| {
26502678 switch (abi_size) {
26512679 1, 2, 4, 8 => {
2652 assert(std.mem.isAlignedGeneric(u32, stack_offset, abi_size));
2653
26542680 const tag: Mir.Inst.Tag = switch (abi_size) {
26552681 1 => .sb,
26562682 2 => .sh,
......@@ -2733,7 +2759,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
27332759 // memcpy(src, dst, len)
27342760 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
27352761 },
2736
27372762 else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}),
27382763 }
27392764}