diff options
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 57 | ||||
| -rw-r--r-- | test/behavior/bugs/1486.zig | 3 |
2 files changed, 34 insertions, 26 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index c6a2d3f23b..14aebc3724 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1685,6 +1685,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { _ = ptr_ty; + const abi_size = value_ty.abiSize(self.target.*); switch (ptr) { .none => unreachable, .undef => unreachable, @@ -1705,6 +1706,9 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type return self.fail("TODO implement storing to MCValue.embedded_in_code", .{}); }, .register => |reg| { + self.register_manager.freezeRegs(&.{reg}); + defer self.register_manager.unfreezeRegs(&.{reg}); + switch (value) { .none => unreachable, .undef => unreachable, @@ -1713,7 +1717,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type .compare_flags_unsigned => unreachable, .compare_flags_signed => unreachable, .immediate => |imm| { - const abi_size = value_ty.abiSize(self.target.*); switch (abi_size) { 1, 2, 4 => { // TODO this is wasteful! @@ -1760,7 +1763,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type } }, .register => |src_reg| { - const abi_size = value_ty.abiSize(self.target.*); _ = try self.addInst(.{ .tag = .mov, .ops = (Mir.Ops{ @@ -1777,9 +1779,16 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type } }, .memory => |addr| { + if (self.bin_file.options.pie) { + return self.fail("TODO implement storing to memory when targeting PIE", .{}); + } + // TODO: in case the address fits in an imm32 we can use [ds:imm32] // instead of wasting an instruction copying the address to a register + if (value.isRegister()) self.register_manager.freezeRegs(&.{value.register}); + defer if (value.isRegister()) self.register_manager.unfreezeRegs(&.{value.register}); + const addr_reg = try self.copyToTmpRegister(ptr_ty, .{ .immediate = addr }); // to get the actual address of the value we want to modify we have to go through the GOT // mov reg, [reg] @@ -1793,37 +1802,39 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type .data = .{ .imm = 0 }, }); - const abi_size = value_ty.abiSize(self.target.*); switch (value) { .immediate => |imm| { + if (abi_size > 8) { + return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); + } + const payload = try self.addExtra(Mir.ImmPair{ .dest_off = 0, .operand = @intCast(u32, imm), }); + const flags: u2 = switch (abi_size) { + 1 => 0b00, + 2 => 0b01, + 4 => 0b10, + 8 => 0b11, + else => unreachable, + }; + if (flags == 0b11) { + const top_bits: u32 = @intCast(u32, imm >> 32); + const can_extend = if (value_ty.isUnsignedInt()) + (top_bits == 0) and (imm & 0x8000_0000) == 0 + else + top_bits == 0xffff_ffff; + + if (!can_extend) { + return self.fail("TODO imm64 would get incorrectly sign extended", .{}); + } + } _ = try self.addInst(.{ .tag = .mov_mem_imm, .ops = (Mir.Ops{ .reg1 = addr_reg.to64(), - .flags = switch (abi_size) { - 1 => 0b00, - 2 => 0b01, - 4 => 0b10, - 8 => flag: { - const top_bits: u32 = @intCast(u32, imm >> 32); - const can_extend = if (value_ty.isUnsignedInt()) - (top_bits == 0) and (imm & 0x8000_0000) == 0 - else - top_bits == 0xffff_ffff; - - if (!can_extend) { - return self.fail("TODO imm64 would get incorrectly sign extended", .{}); - } - break :flag 0b11; - }, - else => { - return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); - }, - }, + .flags = flags, }).encode(), .data = .{ .payload = payload }, }); diff --git a/test/behavior/bugs/1486.zig b/test/behavior/bugs/1486.zig index 53309f5553..8f954a3600 100644 --- a/test/behavior/bugs/1486.zig +++ b/test/behavior/bugs/1486.zig @@ -1,13 +1,10 @@ const std = @import("std"); -const builtin = @import("builtin"); const expect = std.testing.expect; const ptr = &global; var global: usize = 123; test "constant pointer to global variable causes runtime load" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - global = 1234; try expect(&global == ptr); try expect(ptr.* == 1234); |
