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 {...@@ -1442,8 +1442,29 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
1442}1442}
14431443
1444fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {1444fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
1445 const mod = self.bin_file.comp.module.?;
1445 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;1446 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 };
1447 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1468 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1448}1469}
14491470
...@@ -1639,17 +1660,10 @@ fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerErro...@@ -1639,17 +1660,10 @@ fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerErro
1639 .dead => unreachable,1660 .dead => unreachable,
1640 .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }),1661 .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }),
1641 .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }),1662 .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,
1644 .stack_offset,1663 .stack_offset,
1645 => {1664 .register,
1646 const reg = try self.register_manager.allocReg(null, gp);1665 => try self.setValue(elem_ty, dst_mcv, src_ptr),
1647 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);1666 .memory => return self.fail("TODO: load memory", .{}),
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 },
1653 .load_symbol => {1667 .load_symbol => {
1654 const reg = try self.copyToTmpRegister(ptr_ty, src_ptr);1668 const reg = try self.copyToTmpRegister(ptr_ty, src_ptr);
1655 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);1669 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
...@@ -1675,7 +1689,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -1675,7 +1689,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1675 // The MCValue that holds the pointer can be re-used as the value.1689 // The MCValue that holds the pointer can be re-used as the value.
1676 break :blk ptr;1690 break :blk ptr;
1677 } else {1691 } 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);
1679 }1694 }
1680 };1695 };
1681 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));1696 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));
...@@ -1750,7 +1765,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1750,7 +1765,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
1750 const field_ty = struct_ty.structFieldType(index, mod);1765 const field_ty = struct_ty.structFieldType(index, mod);
1751 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;1766 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
1755 switch (src_mcv) {1776 switch (src_mcv) {
1756 .dead, .unreach => unreachable,1777 .dead, .unreach => unreachable,
...@@ -1778,10 +1799,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1778,10 +1799,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
1778 },1799 },
1779 },1800 },
1780 });1801 });
1802
1803 return self.fail("TODO: airStructFieldVal register with field_off > 0", .{});
1781 }1804 }
17821805
1783 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);1806 break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv);
1784 },1807 },
1808 .stack_offset => |off| {
1809 break :result MCValue{ .stack_offset = off + field_off };
1810 },
1785 else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),1811 else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}),
1786 }1812 }
1787 };1813 };
...@@ -2435,7 +2461,8 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index, target: Mir.Inst.Index) !void...@@ -2435,7 +2461,8 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index, target: Mir.Inst.Index) !void
2435 .bne,2461 .bne,
2436 .beq,2462 .beq,
2437 => self.mir_instructions.items(.data)[inst].b_type.inst = target,2463 => 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,
2439 else => return self.fail("TODO: performReloc {s}", .{@tagName(tag)}),2466 else => return self.fail("TODO: performReloc {s}", .{@tagName(tag)}),
2440 }2467 }
2441}2468}
...@@ -2614,6 +2641,7 @@ fn setValue(self: *Self, ty: Type, dst_val: MCValue, src_val: MCValue) !void {...@@ -2614,6 +2641,7 @@ fn setValue(self: *Self, ty: Type, dst_val: MCValue, src_val: MCValue) !void {
2614 if (dst_val == .none) return;2641 if (dst_val == .none) return;
26152642
2616 if (!dst_val.isMutable()) {2643 if (!dst_val.isMutable()) {
2644 // panic so we can see the trace
2617 return std.debug.panic("tried to setValue immutable: {s}", .{@tagName(dst_val)});2645 return std.debug.panic("tried to setValue immutable: {s}", .{@tagName(dst_val)});
2618 }2646 }
26192647
...@@ -2649,8 +2677,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner...@@ -2649,8 +2677,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
2649 .register => |reg| {2677 .register => |reg| {
2650 switch (abi_size) {2678 switch (abi_size) {
2651 1, 2, 4, 8 => {2679 1, 2, 4, 8 => {
2652 assert(std.mem.isAlignedGeneric(u32, stack_offset, abi_size));
2653
2654 const tag: Mir.Inst.Tag = switch (abi_size) {2680 const tag: Mir.Inst.Tag = switch (abi_size) {
2655 1 => .sb,2681 1 => .sb,
2656 2 => .sh,2682 2 => .sh,
...@@ -2733,7 +2759,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner...@@ -2733,7 +2759,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
2733 // memcpy(src, dst, len)2759 // memcpy(src, dst, len)
2734 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);2760 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
2735 },2761 },
2736
2737 else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}),2762 else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}),
2738 }2763 }
2739}2764}