| ... | ... | @@ -1666,28 +1666,6 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind |
| 1666 | 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 | 1669 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1692 | 1670 | const mod = self.bin_file.comp.module.?; |
| 1693 | 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 | 1684 | // The MCValue that holds the pointer can be re-used as the value. |
| 1707 | 1685 | break :blk ptr; |
| 1708 | 1686 | } else { |
| 1709 | | // TODO: set this to true, will need to implement register version of arrays and structs |
| 1710 | | break :blk try self.allocRegOrMem(inst, false); |
| 1687 | break :blk try self.allocRegOrMem(inst, true); |
| 1711 | 1688 | } |
| 1712 | 1689 | }; |
| 1713 | 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 | 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 { |
| 1720 | | _ = ptr_ty; |
| 1721 | | |
| 1722 | | log.debug("storing {s}", .{@tagName(dst_ptr)}); |
| 1696 | fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 1697 | const mod = self.bin_file.comp.module.?; |
| 1698 | const elem_ty = ptr_ty.childType(mod); |
| 1723 | 1699 | |
| 1724 | | switch (dst_ptr) { |
| 1700 | switch (src_ptr) { |
| 1725 | 1701 | .none => unreachable, |
| 1726 | 1702 | .undef => unreachable, |
| 1727 | 1703 | .unreach => unreachable, |
| 1728 | 1704 | .dead => unreachable, |
| 1729 | | .ptr_stack_offset => |off| try self.genSetStack(value_ty, off, src_val), |
| 1730 | | else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(dst_ptr)}), |
| 1705 | .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }), |
| 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 | 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 | 1781 | fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1752 | 1782 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 1753 | 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 | 2723 | if (!self.wantSafety()) return; |
| 2694 | 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 | 2731 | const reg = try self.register_manager.allocReg(null, gp); |
| 2698 | | const reg_lock = self.register_manager.lockReg(reg); |
| 2699 | | defer if (reg_lock) |lock| self.register_manager.unlockReg(lock); |
| 2732 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 2733 | defer self.register_manager.unlockReg(reg_lock); |
| 2700 | 2734 | |
| 2701 | 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 | 2883 | |
| 2850 | 2884 | switch (src_val) { |
| 2851 | 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 | 2898 | .unreach, .none => return, // Nothing to do. |
| 2854 | 2899 | .undef => { |
| 2855 | 2900 | if (!self.wantSafety()) |
| ... | ... | @@ -3166,6 +3211,8 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 3166 | 3211 | |
| 3167 | 3212 | fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void { |
| 3168 | 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 | 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 | 3252 | |
| 3206 | 3253 | fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { |
| 3207 | 3254 | const mod = self.bin_file.comp.module.?; |
| 3208 | | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 3255 | const result = try codegen.genTypedValue( |
| 3209 | 3256 | self.bin_file, |
| 3210 | 3257 | self.src_loc, |
| 3211 | 3258 | val, |
| 3212 | 3259 | mod.funcOwnerDeclIndex(self.func_index), |
| 3213 | | )) { |
| 3260 | ); |
| 3261 | const mcv: MCValue = switch (result) { |
| 3214 | 3262 | .mcv => |mcv| switch (mcv) { |
| 3215 | 3263 | .none => .none, |
| 3216 | 3264 | .undef => .undef, |