| ... | @@ -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 | } |
| 1668 | | 1668 | |
| 1669 | fn 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 | | | |
| 1691 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 1669 | fn 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 structs | 1687 | 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 | } |
| 1718 | | 1695 | |
| 1719 | fn store(self: *Self, dst_ptr: MCValue, src_val: MCValue, ptr_ty: Type, value_ty: Type) !void { | 1696 | fn 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.?; |
| 1721 | | 1698 | const elem_ty = ptr_ty.childType(mod); |
| 1722 | log.debug("storing {s}", .{@tagName(dst_ptr)}); | | |
| 1723 | | 1699 | |
| 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 | } |
| 1733 | | 1719 | |
| ... | @@ -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 | } |
| 1750 | | 1736 | |
| | 1737 | /// Loads `value` into the "payload" of `pointer`. |
| | 1738 | fn 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 | |
| 1751 | fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void { | 1781 | fn 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); |
| 2700 | | 2734 | |
| 2701 | try self.genSetReg(ty, reg, src_val); | 2735 | try self.genSetReg(ty, reg, src_val); |
| 2702 | | 2736 | |
| ... | @@ -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! |
| 2849 | | 2883 | |
| 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 { |
| 3166 | | 3211 | |
| 3167 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { | 3212 | fn 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 | } |
| 3171 | | 3218 | |
| ... | @@ -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 { |
| 3205 | | 3252 | |
| 3206 | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { | 3253 | fn 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, |