diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-15 18:28:39 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-15 18:28:39 +0100 |
| commit | 4d4bbd76240e155151d0bf964debe09ea05fc7ef (patch) | |
| tree | 38b7fe11d8f3547e3f92e63cec2ed9910b523ae2 /src/arch | |
| parent | a5c7742ba6fc793608b8bb7ba058e33eccd9cfec (diff) | |
| download | zig-4d4bbd76240e155151d0bf964debe09ea05fc7ef.tar.gz zig-4d4bbd76240e155151d0bf964debe09ea05fc7ef.zip | |
stage2: refactor handling of immediates in x86_64 backend
Fixes issues with incorrect operand sizes in a handful of cases
and allows for usage of differently sized integers in Zig sources.
Diffstat (limited to 'src/arch')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 56 | ||||
| -rw-r--r-- | src/arch/x86_64/Isel.zig | 157 | ||||
| -rw-r--r-- | src/arch/x86_64/Mir.zig | 6 |
3 files changed, 112 insertions, 107 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 9f4feb56e6..0525a4689b 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -497,14 +497,14 @@ fn gen(self: *Self) InnerError!void { .ops = (Mir.Ops{ .reg1 = .rsp, }).encode(), - .data = .{ .imm = @intCast(i32, aligned_stack_end) + stack_adjustment }, + .data = .{ .imm = @bitCast(u32, @intCast(i32, aligned_stack_end) + stack_adjustment) }, }); self.mir_instructions.set(backpatch_stack_add, .{ .tag = .add, .ops = (Mir.Ops{ .reg1 = .rsp, }).encode(), - .data = .{ .imm = @intCast(i32, aligned_stack_end) + stack_adjustment }, + .data = .{ .imm = @bitCast(u32, @intCast(i32, aligned_stack_end) + stack_adjustment) }, }); } } else { @@ -1347,7 +1347,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { .reg2 = .rbp, .flags = 0b01, }).encode(), - .data = .{ .imm = -@intCast(i32, off + 16) }, + .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) }, }); // add addr, offset _ = try self.addInst(.{ @@ -1555,7 +1555,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) }); return self.genInlineMemcpy( - -@intCast(i32, off + abi_size), + @bitCast(u32, -@intCast(i32, off + abi_size)), registerAlias(addr_reg, @divExact(reg.size(), 8)), count_reg.to64(), tmp_reg.to8(), @@ -1637,7 +1637,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type // introduce new MIR tag specifically for mov [reg + 0], imm const payload = try self.addExtra(Mir.ImmPair{ .dest_off = 0, - .operand = @bitCast(i32, @intCast(u32, imm)), + .operand = @truncate(u32, imm), }); _ = try self.addInst(.{ .tag = .mov_mem_imm, @@ -1872,7 +1872,7 @@ fn genBinMathOpMir( .ops = (Mir.Ops{ .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)), }).encode(), - .data = .{ .imm = @intCast(i32, imm) }, + .data = .{ .imm = @truncate(u32, imm) }, }); }, .embedded_in_code, .memory => { @@ -1891,7 +1891,7 @@ fn genBinMathOpMir( .reg2 = .rbp, .flags = 0b01, }).encode(), - .data = .{ .imm = -@intCast(i32, adj_off) }, + .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) }, }); }, .compare_flags_unsigned => { @@ -1926,7 +1926,7 @@ fn genBinMathOpMir( .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), .flags = 0b10, }).encode(), - .data = .{ .imm = -@intCast(i32, adj_off) }, + .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) }, }); }, .immediate => |imm| { @@ -1947,8 +1947,8 @@ fn genBinMathOpMir( else => unreachable, }; const payload = try self.addExtra(Mir.ImmPair{ - .dest_off = -@intCast(i32, adj_off), - .operand = @bitCast(i32, @intCast(u32, imm)), + .dest_off = @bitCast(u32, -@intCast(i32, adj_off)), + .operand = @truncate(u32, imm), }); _ = try self.addInst(.{ .tag = tag, @@ -2015,7 +2015,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) ! .reg2 = dst_reg.to32(), .flags = 0b10, }).encode(), - .data = .{ .imm = @intCast(i32, imm) }, + .data = .{ .imm = @truncate(u32, imm) }, }); } else { // TODO verify we don't spill and assign to the same register as dst_mcv @@ -2088,7 +2088,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { const mcv = self.args[arg_index]; const payload = try self.addExtra(Mir.ArgDbgInfo{ .air_inst = inst, - .arg_index = @intCast(u32, arg_index), // TODO can arg_index: u32? + .arg_index = @truncate(u32, arg_index), // TODO can arg_index: u32? }); _ = try self.addInst(.{ .tag = .arg_dbg_info, @@ -2196,7 +2196,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { .ops = (Mir.Ops{ .flags = 0b01, }).encode(), - .data = .{ .imm = @bitCast(i32, got_addr) }, + .data = .{ .imm = @truncate(u32, got_addr) }, }); } else if (func_value.castTag(.extern_fn)) |_| { return self.fail("TODO implement calling extern functions", .{}); @@ -3121,8 +3121,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro // offset from rbp, which is at the top of the stack frame. // mov [rbp+offset], immediate const payload = try self.addExtra(Mir.ImmPair{ - .dest_off = -@intCast(i32, adj_off), - .operand = @bitCast(i32, @intCast(u32, x_big)), + .dest_off = @bitCast(u32, -@intCast(i32, adj_off)), + .operand = @truncate(u32, x_big), }); _ = try self.addInst(.{ .tag = .mov_mem_imm, @@ -3147,8 +3147,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro // insted just use two 32 bit writes to avoid register allocation { const payload = try self.addExtra(Mir.ImmPair{ - .dest_off = negative_offset + 4, - .operand = @bitCast(i32, @truncate(u32, x_big >> 32)), + .dest_off = @bitCast(u32, negative_offset + 4), + .operand = @truncate(u32, x_big >> 32), }); _ = try self.addInst(.{ .tag = .mov_mem_imm, @@ -3161,8 +3161,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro } { const payload = try self.addExtra(Mir.ImmPair{ - .dest_off = negative_offset, - .operand = @bitCast(i32, @truncate(u32, x_big)), + .dest_off = @bitCast(u32, negative_offset), + .operand = @truncate(u32, x_big), }); _ = try self.addInst(.{ .tag = .mov_mem_imm, @@ -3192,7 +3192,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro .reg2 = registerAlias(reg, @intCast(u32, abi_size)), .flags = 0b10, }).encode(), - .data = .{ .imm = -@intCast(i32, adj_off) }, + .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) }, }); }, .memory, .embedded_in_code => { @@ -3228,14 +3228,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro .reg1 = addr_reg.to64(), .reg2 = .rbp, }).encode(), - .data = .{ .imm = -@intCast(i32, off + abi_size) }, + .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + abi_size)) }, }); // TODO allow for abi_size to be u64 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) }); return self.genInlineMemcpy( - -@intCast(i32, stack_offset + abi_size), + @bitCast(u32, -@intCast(i32, stack_offset + abi_size)), addr_reg.to64(), count_reg.to64(), tmp_reg.to8(), @@ -3246,7 +3246,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro fn genInlineMemcpy( self: *Self, - stack_offset: i32, + stack_offset: u32, addr_reg: Register, count_reg: Register, tmp_reg: Register, @@ -3361,7 +3361,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void .reg1 = registerAlias(reg, @intCast(u32, ptr_abi_size)), .reg2 = .rbp, }).encode(), - .data = .{ .imm = -@intCast(i32, off) }, + .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) }, }); }, .ptr_embedded_in_code => unreachable, @@ -3426,7 +3426,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void .ops = (Mir.Ops{ .reg1 = registerAlias(reg, @intCast(u32, abi_size)), }).encode(), - .data = .{ .imm = @intCast(i32, x) }, + .data = .{ .imm = @truncate(u32, x) }, }); return; } @@ -3482,7 +3482,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void .reg1 = reg, .flags = 0b10, }).encode(), - .data = .{ .got_entry = @intCast(u32, x) }, + .data = .{ .got_entry = @truncate(u32, x) }, }); // MOV reg, [reg] _ = try self.addInst(.{ @@ -3502,7 +3502,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void .reg1 = reg, .flags = 0b01, }).encode(), - .data = .{ .imm = @intCast(i32, x) }, + .data = .{ .imm = @truncate(u32, x) }, }); } else { // If this is RAX, we can use a direct load. @@ -3561,7 +3561,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void .reg2 = .rbp, .flags = 0b01, }).encode(), - .data = .{ .imm = -@intCast(i32, off) }, + .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) }, }); }, } diff --git a/src/arch/x86_64/Isel.zig b/src/arch/x86_64/Isel.zig index acae794563..d7f4087d0d 100644 --- a/src/arch/x86_64/Isel.zig +++ b/src/arch/x86_64/Isel.zig @@ -483,17 +483,26 @@ inline fn setRexWRegister(reg: Register) bool { }; } -inline fn immOpSize(imm: i64) u8 { - blk: { - _ = math.cast(i8, imm) catch break :blk; +inline fn immOpSize(u_imm: u32) u8 { + const imm = @bitCast(i32, u_imm); + if (math.minInt(i8) <= imm and imm <= math.maxInt(i8)) { return 8; } - blk: { - _ = math.cast(i16, imm) catch break :blk; + if (math.minInt(i16) <= imm and imm <= math.maxInt(i16)) { return 16; } - blk: { - _ = math.cast(i32, imm) catch break :blk; + return 32; +} + +inline fn imm64OpSize(u_imm: u64) u8 { + const imm = @bitCast(i64, u_imm); + if (math.minInt(i8) <= imm and imm <= math.maxInt(i8)) { + return 8; + } + if (math.minInt(i16) <= imm and imm <= math.maxInt(i16)) { + return 16; + } + if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) { return 32; } return 64; @@ -560,10 +569,10 @@ fn mirMovabs(isel: *Isel, inst: Mir.Inst.Index) InnerError!void { const tag = isel.mir.instructions.items(.tag)[inst]; assert(tag == .movabs); const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]); - const imm: i64 = if (ops.reg1.size() == 64) blk: { + const imm: u64 = if (ops.reg1.size() == 64) blk: { const payload = isel.mir.instructions.items(.data)[inst].payload; const imm = isel.mir.extraData(Mir.Imm64, payload).data; - break :blk @bitCast(i64, imm.decode()); + break :blk imm.decode(); } else isel.mir.instructions.items(.data)[inst].imm; if (ops.flags == 0b00) { // movabs reg, imm64 @@ -1233,7 +1242,7 @@ const ScaleIndex = struct { const Memory = struct { base: ?Register, rip: bool = false, - disp: i32, + disp: u32, ptr_size: PtrSize, scale_index: ?ScaleIndex = null, @@ -1283,7 +1292,7 @@ const Memory = struct { } else { encoder.sib_baseDisp8(dst); } - encoder.disp8(@intCast(i8, mem_op.disp)); + encoder.disp8(@bitCast(i8, @truncate(u8, mem_op.disp))); } else { encoder.modRm_SIBDisp32(src); if (mem_op.scale_index) |si| { @@ -1291,17 +1300,17 @@ const Memory = struct { } else { encoder.sib_baseDisp32(dst); } - encoder.disp32(mem_op.disp); + encoder.disp32(@bitCast(i32, mem_op.disp)); } } else { if (mem_op.disp == 0) { encoder.modRm_indirectDisp0(src, dst); } else if (immOpSize(mem_op.disp) == 8) { encoder.modRm_indirectDisp8(src, dst); - encoder.disp8(@intCast(i8, mem_op.disp)); + encoder.disp8(@bitCast(i8, @truncate(u8, mem_op.disp))); } else { encoder.modRm_indirectDisp32(src, dst); - encoder.disp32(mem_op.disp); + encoder.disp32(@bitCast(i32, mem_op.disp)); } } } else { @@ -1315,16 +1324,16 @@ const Memory = struct { encoder.sib_disp32(); } } - encoder.disp32(mem_op.disp); + encoder.disp32(@bitCast(i32, mem_op.disp)); } } }; -fn encodeImm(encoder: Encoder, imm: i32, size: u64) void { +fn encodeImm(encoder: Encoder, imm: u32, size: u64) void { switch (size) { - 8 => encoder.imm8(@intCast(i8, imm)), - 16 => encoder.imm16(@intCast(i16, imm)), - 32, 64 => encoder.imm32(imm), + 8 => encoder.imm8(@bitCast(i8, @truncate(u8, imm))), + 16 => encoder.imm16(@bitCast(i16, @truncate(u16, imm))), + 32, 64 => encoder.imm32(@bitCast(i32, imm)), else => unreachable, } } @@ -1338,7 +1347,7 @@ const RegisterOrMemory = union(enum) { } fn mem(ptr_size: Memory.PtrSize, args: struct { - disp: i32, + disp: u32, base: ?Register = null, scale_index: ?ScaleIndex = null, }) RegisterOrMemory { @@ -1352,7 +1361,7 @@ const RegisterOrMemory = union(enum) { }; } - fn rip(ptr_size: Memory.PtrSize, disp: i32) RegisterOrMemory { + fn rip(ptr_size: Memory.PtrSize, disp: u32) RegisterOrMemory { return .{ .memory = .{ .base = null, @@ -1377,12 +1386,12 @@ fn lowerToZoEnc(tag: Tag, code: *std.ArrayList(u8)) LoweringError!void { opc.encode(encoder); } -fn lowerToIEnc(tag: Tag, imm: i32, code: *std.ArrayList(u8)) LoweringError!void { +fn lowerToIEnc(tag: Tag, imm: u32, code: *std.ArrayList(u8)) LoweringError!void { if (tag == .ret_far or tag == .ret_near) { const encoder = try Encoder.init(code, 3); const opc = getOpCode(tag, .i, false).?; opc.encode(encoder); - encoder.imm16(@intCast(i16, imm)); + encoder.imm16(@bitCast(i16, @truncate(u16, imm))); return; } const opc = getOpCode(tag, .i, immOpSize(imm) == 8).?; @@ -1410,11 +1419,11 @@ fn lowerToOEnc(tag: Tag, reg: Register, code: *std.ArrayList(u8)) LoweringError! opc.encodeWithReg(encoder, reg); } -fn lowerToDEnc(tag: Tag, imm: i32, code: *std.ArrayList(u8)) LoweringError!void { +fn lowerToDEnc(tag: Tag, imm: u32, code: *std.ArrayList(u8)) LoweringError!void { const opc = getOpCode(tag, .d, false).?; const encoder = try Encoder.init(code, 6); opc.encode(encoder); - encoder.imm32(imm); + encoder.imm32(@bitCast(i32, imm)); } fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8)) LoweringError!void { @@ -1467,19 +1476,19 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8)) } } -fn lowerToTdEnc(tag: Tag, moffs: i64, reg: Register, code: *std.ArrayList(u8)) LoweringError!void { +fn lowerToTdEnc(tag: Tag, moffs: u64, reg: Register, code: *std.ArrayList(u8)) LoweringError!void { return lowerToTdFdEnc(tag, reg, moffs, code, true); } -fn lowerToFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8)) LoweringError!void { +fn lowerToFdEnc(tag: Tag, reg: Register, moffs: u64, code: *std.ArrayList(u8)) LoweringError!void { return lowerToTdFdEnc(tag, reg, moffs, code, false); } -fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8), td: bool) LoweringError!void { +fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: u64, code: *std.ArrayList(u8), td: bool) LoweringError!void { if (reg.lowId() != Register.rax.lowId()) { return error.RaxOperandExpected; } - if (reg.size() != immOpSize(moffs)) { + if (reg.size() != imm64OpSize(moffs)) { return error.OperandSizeMismatch; } const opc = if (td) @@ -1495,27 +1504,16 @@ fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8), }); opc.encode(encoder); switch (reg.size()) { - 8 => { - const moffs8 = try math.cast(i8, moffs); - encoder.imm8(moffs8); - }, - 16 => { - const moffs16 = try math.cast(i16, moffs); - encoder.imm16(moffs16); - }, - 32 => { - const moffs32 = try math.cast(i32, moffs); - encoder.imm32(moffs32); - }, - 64 => { - encoder.imm64(@bitCast(u64, moffs)); - }, + 8 => encoder.imm8(@bitCast(i8, @truncate(u8, moffs))), + 16 => encoder.imm16(@bitCast(i16, @truncate(u16, moffs))), + 32 => encoder.imm32(@bitCast(i32, @truncate(u32, moffs))), + 64 => encoder.imm64(moffs), else => unreachable, } } -fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) LoweringError!void { - if (reg.size() != immOpSize(imm)) { +fn lowerToOiEnc(tag: Tag, reg: Register, imm: u64, code: *std.ArrayList(u8)) LoweringError!void { + if (reg.size() != imm64OpSize(imm)) { return error.OperandSizeMismatch; } const opc = getOpCode(tag, .oi, reg.size() == 8).?; @@ -1529,26 +1527,15 @@ fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) Low }); opc.encodeWithReg(encoder, reg); switch (reg.size()) { - 8 => { - const imm8 = try math.cast(i8, imm); - encoder.imm8(imm8); - }, - 16 => { - const imm16 = try math.cast(i16, imm); - encoder.imm16(imm16); - }, - 32 => { - const imm32 = try math.cast(i32, imm); - encoder.imm32(imm32); - }, - 64 => { - encoder.imm64(@bitCast(u64, imm)); - }, + 8 => encoder.imm8(@bitCast(i8, @truncate(u8, imm))), + 16 => encoder.imm16(@bitCast(i16, @truncate(u16, imm))), + 32 => encoder.imm32(@bitCast(i32, @truncate(u32, imm))), + 64 => encoder.imm64(imm), else => unreachable, } } -fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: i32, code: *std.ArrayList(u8)) LoweringError!void { +fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: u32, code: *std.ArrayList(u8)) LoweringError!void { const modrm_ext = getModRmExt(tag).?; switch (reg_or_mem) { .register => |dst_reg| { @@ -1700,7 +1687,7 @@ fn lowerToRmiEnc( tag: Tag, reg: Register, reg_or_mem: RegisterOrMemory, - imm: i32, + imm: u32, code: *std.ArrayList(u8), ) LoweringError!void { if (reg.size() == 8) { @@ -1804,7 +1791,10 @@ test "lower MI encoding" { try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", isel.lowered(), "mov rax, 0x10"); try lowerToMiEnc(.mov, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0, .base = .r11 }), 0x10, isel.code()); try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", isel.lowered(), "mov dword ptr [r11 + 0], 0x10"); - try lowerToMiEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{ .disp = -8, .base = .rdx }), 0x10, isel.code()); + try lowerToMiEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{ + .disp = @bitCast(u32, @as(i32, -8)), + .base = .rdx, + }), 0x10, isel.code()); try expectEqualHexStrings("\x81\x42\xF8\x10\x00\x00\x00", isel.lowered(), "add dword ptr [rdx - 8], 0x10"); try lowerToMiEnc(.sub, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0x10000000, @@ -1836,15 +1826,24 @@ test "lower MI encoding" { isel.lowered(), "mov qword ptr [rip + 0x10], 0x10", ); - try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -8, .base = .rbp }), 0x10, isel.code()); + try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ + .disp = @bitCast(u32, @as(i32, -8)), + .base = .rbp, + }), 0x10, isel.code()); try expectEqualHexStrings( "\x48\xc7\x45\xf8\x10\x00\x00\x00", isel.lowered(), "mov qword ptr [rbp - 8], 0x10", ); - try lowerToMiEnc(.mov, RegisterOrMemory.mem(.word_ptr, .{ .disp = -2, .base = .rbp }), 0x10, isel.code()); + try lowerToMiEnc(.mov, RegisterOrMemory.mem(.word_ptr, .{ + .disp = @bitCast(u32, @as(i32, -2)), + .base = .rbp, + }), 0x10, isel.code()); try expectEqualHexStrings("\x66\xC7\x45\xFE\x10\x00", isel.lowered(), "mov word ptr [rbp - 2], 0x10"); - try lowerToMiEnc(.mov, RegisterOrMemory.mem(.byte_ptr, .{ .disp = -1, .base = .rbp }), 0x10, isel.code()); + try lowerToMiEnc(.mov, RegisterOrMemory.mem(.byte_ptr, .{ + .disp = @bitCast(u32, @as(i32, -1)), + .base = .rbp, + }), 0x10, isel.code()); try expectEqualHexStrings("\xC6\x45\xFF\x10", isel.lowered(), "mov byte ptr [rbp - 1], 0x10"); try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ .disp = 0x10000000, @@ -1897,12 +1896,15 @@ test "lower RM encoding" { isel.lowered(), "sub r11, qword ptr [r12 + 0x10000000]", ); - try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -4, .base = .rbp }), isel.code()); + try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{ + .disp = @bitCast(u32, @as(i32, -4)), + .base = .rbp, + }), isel.code()); try expectEqualHexStrings("\x48\x8B\x45\xFC", isel.lowered(), "mov rax, qword ptr [rbp - 4]"); try lowerToRmEnc(.lea, .rax, RegisterOrMemory.rip(.qword_ptr, 0x10), isel.code()); try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", isel.lowered(), "lea rax, [rip + 0x10]"); try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{ - .disp = -8, + .disp = @bitCast(u32, @as(i32, -8)), .base = .rbp, .scale_index = .{ .scale = 0, @@ -1911,7 +1913,7 @@ test "lower RM encoding" { }), isel.code()); try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*1 - 8]"); try lowerToRmEnc(.mov, .eax, RegisterOrMemory.mem(.dword_ptr, .{ - .disp = -4, + .disp = @bitCast(u32, @as(i32, -4)), .base = .rbp, .scale_index = .{ .scale = 2, @@ -1920,7 +1922,7 @@ test "lower RM encoding" { }), isel.code()); try expectEqualHexStrings("\x8B\x44\x95\xFC", isel.lowered(), "mov eax, dword ptr [rbp + rdx*4 - 4]"); try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{ - .disp = -8, + .disp = @bitCast(u32, @as(i32, -8)), .base = .rbp, .scale_index = .{ .scale = 3, @@ -1929,7 +1931,7 @@ test "lower RM encoding" { }), isel.code()); try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*8 - 8]"); try lowerToRmEnc(.mov, .r8b, RegisterOrMemory.mem(.byte_ptr, .{ - .disp = -24, + .disp = @bitCast(u32, @as(i32, -24)), .base = .rsi, .scale_index = .{ .scale = 0, @@ -1953,7 +1955,10 @@ test "lower MR encoding" { defer isel.deinit(); try lowerToMrEnc(.mov, RegisterOrMemory.reg(.rax), .rbx, isel.code()); try expectEqualHexStrings("\x48\x89\xd8", isel.lowered(), "mov rax, rbx"); - try lowerToMrEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -4, .base = .rbp }), .r11, isel.code()); + try lowerToMrEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ + .disp = @bitCast(u32, @as(i32, -4)), + .base = .rbp, + }), .r11, isel.code()); try expectEqualHexStrings("\x4c\x89\x5d\xfc", isel.lowered(), "mov qword ptr [rbp - 4], r11"); try lowerToMrEnc(.add, RegisterOrMemory.mem(.byte_ptr, .{ .disp = 0x10000000 }), .r12b, isel.code()); try expectEqualHexStrings( @@ -2063,7 +2068,7 @@ test "lower RMI encoding" { var isel = TestIsel.init(); defer isel.deinit(); try lowerToRmiEnc(.imul, .rax, RegisterOrMemory.mem(.qword_ptr, .{ - .disp = -8, + .disp = @bitCast(u32, @as(i32, -8)), .base = .rbp, }), 0x10, isel.code()); try expectEqualHexStrings( @@ -2072,12 +2077,12 @@ test "lower RMI encoding" { "imul rax, qword ptr [rbp - 8], 0x10", ); try lowerToRmiEnc(.imul, .eax, RegisterOrMemory.mem(.dword_ptr, .{ - .disp = -4, + .disp = @bitCast(u32, @as(i32, -4)), .base = .rbp, }), 0x10, isel.code()); try expectEqualHexStrings("\x69\x45\xFC\x10\x00\x00\x00", isel.lowered(), "imul eax, dword ptr [rbp - 4], 0x10"); try lowerToRmiEnc(.imul, .ax, RegisterOrMemory.mem(.word_ptr, .{ - .disp = -2, + .disp = @bitCast(u32, @as(i32, -2)), .base = .rbp, }), 0x10, isel.code()); try expectEqualHexStrings("\x66\x69\x45\xFE\x10\x00", isel.lowered(), "imul ax, word ptr [rbp - 2], 0x10"); diff --git a/src/arch/x86_64/Mir.zig b/src/arch/x86_64/Mir.zig index c5f595a86e..5ea4646c64 100644 --- a/src/arch/x86_64/Mir.zig +++ b/src/arch/x86_64/Mir.zig @@ -302,7 +302,7 @@ pub const Inst = struct { /// Another instruction. inst: Index, /// A 32-bit immediate value. - imm: i32, + imm: u32, /// An extern function. /// Index into the linker's string table. extern_fn: u32, @@ -324,8 +324,8 @@ pub const Inst = struct { }; pub const ImmPair = struct { - dest_off: i32, - operand: i32, + dest_off: u32, + operand: u32, }; pub const Imm64 = struct { |
