| ... | @@ -1685,6 +1685,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1685,6 +1685,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1685 | | 1685 | |
| 1686 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { | 1686 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { |
| 1687 | _ = ptr_ty; | 1687 | _ = ptr_ty; |
| | 1688 | const abi_size = value_ty.abiSize(self.target.*); |
| 1688 | switch (ptr) { | 1689 | switch (ptr) { |
| 1689 | .none => unreachable, | 1690 | .none => unreachable, |
| 1690 | .undef => unreachable, | 1691 | .undef => unreachable, |
| ... | @@ -1705,6 +1706,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -1705,6 +1706,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1705 | return self.fail("TODO implement storing to MCValue.embedded_in_code", .{}); | 1706 | return self.fail("TODO implement storing to MCValue.embedded_in_code", .{}); |
| 1706 | }, | 1707 | }, |
| 1707 | .register => |reg| { | 1708 | .register => |reg| { |
| | 1709 | self.register_manager.freezeRegs(&.{reg}); |
| | 1710 | defer self.register_manager.unfreezeRegs(&.{reg}); |
| | 1711 | |
| 1708 | switch (value) { | 1712 | switch (value) { |
| 1709 | .none => unreachable, | 1713 | .none => unreachable, |
| 1710 | .undef => unreachable, | 1714 | .undef => unreachable, |
| ... | @@ -1713,7 +1717,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -1713,7 +1717,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1713 | .compare_flags_unsigned => unreachable, | 1717 | .compare_flags_unsigned => unreachable, |
| 1714 | .compare_flags_signed => unreachable, | 1718 | .compare_flags_signed => unreachable, |
| 1715 | .immediate => |imm| { | 1719 | .immediate => |imm| { |
| 1716 | const abi_size = value_ty.abiSize(self.target.*); | | |
| 1717 | switch (abi_size) { | 1720 | switch (abi_size) { |
| 1718 | 1, 2, 4 => { | 1721 | 1, 2, 4 => { |
| 1719 | // TODO this is wasteful! | 1722 | // TODO this is wasteful! |
| ... | @@ -1760,7 +1763,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -1760,7 +1763,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1760 | } | 1763 | } |
| 1761 | }, | 1764 | }, |
| 1762 | .register => |src_reg| { | 1765 | .register => |src_reg| { |
| 1763 | const abi_size = value_ty.abiSize(self.target.*); | | |
| 1764 | _ = try self.addInst(.{ | 1766 | _ = try self.addInst(.{ |
| 1765 | .tag = .mov, | 1767 | .tag = .mov, |
| 1766 | .ops = (Mir.Ops{ | 1768 | .ops = (Mir.Ops{ |
| ... | @@ -1777,9 +1779,16 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -1777,9 +1779,16 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1777 | } | 1779 | } |
| 1778 | }, | 1780 | }, |
| 1779 | .memory => |addr| { | 1781 | .memory => |addr| { |
| | 1782 | if (self.bin_file.options.pie) { |
| | 1783 | return self.fail("TODO implement storing to memory when targeting PIE", .{}); |
| | 1784 | } |
| | 1785 | |
| 1780 | // TODO: in case the address fits in an imm32 we can use [ds:imm32] | 1786 | // TODO: in case the address fits in an imm32 we can use [ds:imm32] |
| 1781 | // instead of wasting an instruction copying the address to a register | 1787 | // instead of wasting an instruction copying the address to a register |
| 1782 | | 1788 | |
| | 1789 | if (value.isRegister()) self.register_manager.freezeRegs(&.{value.register}); |
| | 1790 | defer if (value.isRegister()) self.register_manager.unfreezeRegs(&.{value.register}); |
| | 1791 | |
| 1783 | const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr }); | 1792 | const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr }); |
| 1784 | // to get the actual address of the value we want to modify we have to go through the GOT | 1793 | // to get the actual address of the value we want to modify we have to go through the GOT |
| 1785 | // mov reg, [reg] | 1794 | // mov reg, [reg] |
| ... | @@ -1793,37 +1802,39 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -1793,37 +1802,39 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1793 | .data = .{ .imm = 0 }, | 1802 | .data = .{ .imm = 0 }, |
| 1794 | }); | 1803 | }); |
| 1795 | | 1804 | |
| 1796 | const abi_size = value_ty.abiSize(self.target.*); | | |
| 1797 | switch (value) { | 1805 | switch (value) { |
| 1798 | .immediate => |imm| { | 1806 | .immediate => |imm| { |
| | 1807 | if (abi_size > 8) { |
| | 1808 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); |
| | 1809 | } |
| | 1810 | |
| 1799 | const payload = try self.addExtra(Mir.ImmPair{ | 1811 | const payload = try self.addExtra(Mir.ImmPair{ |
| 1800 | .dest_off = 0, | 1812 | .dest_off = 0, |
| 1801 | .operand = @intCast(u32, imm), | 1813 | .operand = @intCast(u32, imm), |
| 1802 | }); | 1814 | }); |
| | 1815 | const flags: u2 = switch (abi_size) { |
| | 1816 | 1 => 0b00, |
| | 1817 | 2 => 0b01, |
| | 1818 | 4 => 0b10, |
| | 1819 | 8 => 0b11, |
| | 1820 | else => unreachable, |
| | 1821 | }; |
| | 1822 | if (flags == 0b11) { |
| | 1823 | const top_bits: u32 = @intCast(u32, imm >> 32); |
| | 1824 | const can_extend = if (value_ty.isUnsignedInt()) |
| | 1825 | (top_bits == 0) and (imm & 0x8000_0000) == 0 |
| | 1826 | else |
| | 1827 | top_bits == 0xffff_ffff; |
| | 1828 | |
| | 1829 | if (!can_extend) { |
| | 1830 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); |
| | 1831 | } |
| | 1832 | } |
| 1803 | _ = try self.addInst(.{ | 1833 | _ = try self.addInst(.{ |
| 1804 | .tag = .mov_mem_imm, | 1834 | .tag = .mov_mem_imm, |
| 1805 | .ops = (Mir.Ops{ | 1835 | .ops = (Mir.Ops{ |
| 1806 | .reg1 = addr_reg.to64(), | 1836 | .reg1 = addr_reg.to64(), |
| 1807 | .flags = switch (abi_size) { | 1837 | .flags = flags, |
| 1808 | 1 => 0b00, | | |
| 1809 | 2 => 0b01, | | |
| 1810 | 4 => 0b10, | | |
| 1811 | 8 => flag: { | | |
| 1812 | const top_bits: u32 = @intCast(u32, imm >> 32); | | |
| 1813 | const can_extend = if (value_ty.isUnsignedInt()) | | |
| 1814 | (top_bits == 0) and (imm & 0x8000_0000) == 0 | | |
| 1815 | else | | |
| 1816 | top_bits == 0xffff_ffff; | | |
| 1817 | | | |
| 1818 | if (!can_extend) { | | |
| 1819 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); | | |
| 1820 | } | | |
| 1821 | break :flag 0b11; | | |
| 1822 | }, | | |
| 1823 | else => { | | |
| 1824 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); | | |
| 1825 | }, | | |
| 1826 | }, | | |
| 1827 | }).encode(), | 1838 | }).encode(), |
| 1828 | .data = .{ .payload = payload }, | 1839 | .data = .{ .payload = payload }, |
| 1829 | }); | 1840 | }); |