authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-15 18:28:39+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-15 18:28:39+01:00
log4d4bbd76240e155151d0bf964debe09ea05fc7ef
tree38b7fe11d8f3547e3f92e63cec2ed9910b523ae2
parenta5c7742ba6fc793608b8bb7ba058e33eccd9cfec

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.

4 files changed, 142 insertions(+), 107 deletions(-)

src/arch/x86_64/CodeGen.zig+28-28
......@@ -497,14 +497,14 @@ fn gen(self: *Self) InnerError!void {
497497 .ops = (Mir.Ops{
498498 .reg1 = .rsp,
499499 }).encode(),
500 .data = .{ .imm = @intCast(i32, aligned_stack_end) + stack_adjustment },
500 .data = .{ .imm = @bitCast(u32, @intCast(i32, aligned_stack_end) + stack_adjustment) },
501501 });
502502 self.mir_instructions.set(backpatch_stack_add, .{
503503 .tag = .add,
504504 .ops = (Mir.Ops{
505505 .reg1 = .rsp,
506506 }).encode(),
507 .data = .{ .imm = @intCast(i32, aligned_stack_end) + stack_adjustment },
507 .data = .{ .imm = @bitCast(u32, @intCast(i32, aligned_stack_end) + stack_adjustment) },
508508 });
509509 }
510510 } else {
......@@ -1347,7 +1347,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
13471347 .reg2 = .rbp,
13481348 .flags = 0b01,
13491349 }).encode(),
1350 .data = .{ .imm = -@intCast(i32, off + 16) },
1350 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) },
13511351 });
13521352 // add addr, offset
13531353 _ = try self.addInst(.{
......@@ -1555,7 +1555,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
15551555 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
15561556
15571557 return self.genInlineMemcpy(
1558 -@intCast(i32, off + abi_size),
1558 @bitCast(u32, -@intCast(i32, off + abi_size)),
15591559 registerAlias(addr_reg, @divExact(reg.size(), 8)),
15601560 count_reg.to64(),
15611561 tmp_reg.to8(),
......@@ -1637,7 +1637,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
16371637 // introduce new MIR tag specifically for mov [reg + 0], imm
16381638 const payload = try self.addExtra(Mir.ImmPair{
16391639 .dest_off = 0,
1640 .operand = @bitCast(i32, @intCast(u32, imm)),
1640 .operand = @truncate(u32, imm),
16411641 });
16421642 _ = try self.addInst(.{
16431643 .tag = .mov_mem_imm,
......@@ -1872,7 +1872,7 @@ fn genBinMathOpMir(
18721872 .ops = (Mir.Ops{
18731873 .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)),
18741874 }).encode(),
1875 .data = .{ .imm = @intCast(i32, imm) },
1875 .data = .{ .imm = @truncate(u32, imm) },
18761876 });
18771877 },
18781878 .embedded_in_code, .memory => {
......@@ -1891,7 +1891,7 @@ fn genBinMathOpMir(
18911891 .reg2 = .rbp,
18921892 .flags = 0b01,
18931893 }).encode(),
1894 .data = .{ .imm = -@intCast(i32, adj_off) },
1894 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },
18951895 });
18961896 },
18971897 .compare_flags_unsigned => {
......@@ -1926,7 +1926,7 @@ fn genBinMathOpMir(
19261926 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
19271927 .flags = 0b10,
19281928 }).encode(),
1929 .data = .{ .imm = -@intCast(i32, adj_off) },
1929 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },
19301930 });
19311931 },
19321932 .immediate => |imm| {
......@@ -1947,8 +1947,8 @@ fn genBinMathOpMir(
19471947 else => unreachable,
19481948 };
19491949 const payload = try self.addExtra(Mir.ImmPair{
1950 .dest_off = -@intCast(i32, adj_off),
1951 .operand = @bitCast(i32, @intCast(u32, imm)),
1950 .dest_off = @bitCast(u32, -@intCast(i32, adj_off)),
1951 .operand = @truncate(u32, imm),
19521952 });
19531953 _ = try self.addInst(.{
19541954 .tag = tag,
......@@ -2015,7 +2015,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !
20152015 .reg2 = dst_reg.to32(),
20162016 .flags = 0b10,
20172017 }).encode(),
2018 .data = .{ .imm = @intCast(i32, imm) },
2018 .data = .{ .imm = @truncate(u32, imm) },
20192019 });
20202020 } else {
20212021 // 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 {
20882088 const mcv = self.args[arg_index];
20892089 const payload = try self.addExtra(Mir.ArgDbgInfo{
20902090 .air_inst = inst,
2091 .arg_index = @intCast(u32, arg_index), // TODO can arg_index: u32?
2091 .arg_index = @truncate(u32, arg_index), // TODO can arg_index: u32?
20922092 });
20932093 _ = try self.addInst(.{
20942094 .tag = .arg_dbg_info,
......@@ -2196,7 +2196,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
21962196 .ops = (Mir.Ops{
21972197 .flags = 0b01,
21982198 }).encode(),
2199 .data = .{ .imm = @bitCast(i32, got_addr) },
2199 .data = .{ .imm = @truncate(u32, got_addr) },
22002200 });
22012201 } else if (func_value.castTag(.extern_fn)) |_| {
22022202 return self.fail("TODO implement calling extern functions", .{});
......@@ -3121,8 +3121,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
31213121 // offset from rbp, which is at the top of the stack frame.
31223122 // mov [rbp+offset], immediate
31233123 const payload = try self.addExtra(Mir.ImmPair{
3124 .dest_off = -@intCast(i32, adj_off),
3125 .operand = @bitCast(i32, @intCast(u32, x_big)),
3124 .dest_off = @bitCast(u32, -@intCast(i32, adj_off)),
3125 .operand = @truncate(u32, x_big),
31263126 });
31273127 _ = try self.addInst(.{
31283128 .tag = .mov_mem_imm,
......@@ -3147,8 +3147,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
31473147 // insted just use two 32 bit writes to avoid register allocation
31483148 {
31493149 const payload = try self.addExtra(Mir.ImmPair{
3150 .dest_off = negative_offset + 4,
3151 .operand = @bitCast(i32, @truncate(u32, x_big >> 32)),
3150 .dest_off = @bitCast(u32, negative_offset + 4),
3151 .operand = @truncate(u32, x_big >> 32),
31523152 });
31533153 _ = try self.addInst(.{
31543154 .tag = .mov_mem_imm,
......@@ -3161,8 +3161,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
31613161 }
31623162 {
31633163 const payload = try self.addExtra(Mir.ImmPair{
3164 .dest_off = negative_offset,
3165 .operand = @bitCast(i32, @truncate(u32, x_big)),
3164 .dest_off = @bitCast(u32, negative_offset),
3165 .operand = @truncate(u32, x_big),
31663166 });
31673167 _ = try self.addInst(.{
31683168 .tag = .mov_mem_imm,
......@@ -3192,7 +3192,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
31923192 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
31933193 .flags = 0b10,
31943194 }).encode(),
3195 .data = .{ .imm = -@intCast(i32, adj_off) },
3195 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },
31963196 });
31973197 },
31983198 .memory, .embedded_in_code => {
......@@ -3228,14 +3228,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
32283228 .reg1 = addr_reg.to64(),
32293229 .reg2 = .rbp,
32303230 }).encode(),
3231 .data = .{ .imm = -@intCast(i32, off + abi_size) },
3231 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + abi_size)) },
32323232 });
32333233
32343234 // TODO allow for abi_size to be u64
32353235 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
32363236
32373237 return self.genInlineMemcpy(
3238 -@intCast(i32, stack_offset + abi_size),
3238 @bitCast(u32, -@intCast(i32, stack_offset + abi_size)),
32393239 addr_reg.to64(),
32403240 count_reg.to64(),
32413241 tmp_reg.to8(),
......@@ -3246,7 +3246,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
32463246
32473247fn genInlineMemcpy(
32483248 self: *Self,
3249 stack_offset: i32,
3249 stack_offset: u32,
32503250 addr_reg: Register,
32513251 count_reg: Register,
32523252 tmp_reg: Register,
......@@ -3361,7 +3361,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
33613361 .reg1 = registerAlias(reg, @intCast(u32, ptr_abi_size)),
33623362 .reg2 = .rbp,
33633363 }).encode(),
3364 .data = .{ .imm = -@intCast(i32, off) },
3364 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) },
33653365 });
33663366 },
33673367 .ptr_embedded_in_code => unreachable,
......@@ -3426,7 +3426,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
34263426 .ops = (Mir.Ops{
34273427 .reg1 = registerAlias(reg, @intCast(u32, abi_size)),
34283428 }).encode(),
3429 .data = .{ .imm = @intCast(i32, x) },
3429 .data = .{ .imm = @truncate(u32, x) },
34303430 });
34313431 return;
34323432 }
......@@ -3482,7 +3482,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
34823482 .reg1 = reg,
34833483 .flags = 0b10,
34843484 }).encode(),
3485 .data = .{ .got_entry = @intCast(u32, x) },
3485 .data = .{ .got_entry = @truncate(u32, x) },
34863486 });
34873487 // MOV reg, [reg]
34883488 _ = try self.addInst(.{
......@@ -3502,7 +3502,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
35023502 .reg1 = reg,
35033503 .flags = 0b01,
35043504 }).encode(),
3505 .data = .{ .imm = @intCast(i32, x) },
3505 .data = .{ .imm = @truncate(u32, x) },
35063506 });
35073507 } else {
35083508 // 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
35613561 .reg2 = .rbp,
35623562 .flags = 0b01,
35633563 }).encode(),
3564 .data = .{ .imm = -@intCast(i32, off) },
3564 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) },
35653565 });
35663566 },
35673567 }
src/arch/x86_64/Isel.zig+81-76
......@@ -483,17 +483,26 @@ inline fn setRexWRegister(reg: Register) bool {
483483 };
484484}
485485
486inline fn immOpSize(imm: i64) u8 {
487 blk: {
488 _ = math.cast(i8, imm) catch break :blk;
486inline fn immOpSize(u_imm: u32) u8 {
487 const imm = @bitCast(i32, u_imm);
488 if (math.minInt(i8) <= imm and imm <= math.maxInt(i8)) {
489489 return 8;
490490 }
491 blk: {
492 _ = math.cast(i16, imm) catch break :blk;
491 if (math.minInt(i16) <= imm and imm <= math.maxInt(i16)) {
493492 return 16;
494493 }
495 blk: {
496 _ = math.cast(i32, imm) catch break :blk;
494 return 32;
495}
496
497inline fn imm64OpSize(u_imm: u64) u8 {
498 const imm = @bitCast(i64, u_imm);
499 if (math.minInt(i8) <= imm and imm <= math.maxInt(i8)) {
500 return 8;
501 }
502 if (math.minInt(i16) <= imm and imm <= math.maxInt(i16)) {
503 return 16;
504 }
505 if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) {
497506 return 32;
498507 }
499508 return 64;
......@@ -560,10 +569,10 @@ fn mirMovabs(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
560569 const tag = isel.mir.instructions.items(.tag)[inst];
561570 assert(tag == .movabs);
562571 const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
563 const imm: i64 = if (ops.reg1.size() == 64) blk: {
572 const imm: u64 = if (ops.reg1.size() == 64) blk: {
564573 const payload = isel.mir.instructions.items(.data)[inst].payload;
565574 const imm = isel.mir.extraData(Mir.Imm64, payload).data;
566 break :blk @bitCast(i64, imm.decode());
575 break :blk imm.decode();
567576 } else isel.mir.instructions.items(.data)[inst].imm;
568577 if (ops.flags == 0b00) {
569578 // movabs reg, imm64
......@@ -1233,7 +1242,7 @@ const ScaleIndex = struct {
12331242const Memory = struct {
12341243 base: ?Register,
12351244 rip: bool = false,
1236 disp: i32,
1245 disp: u32,
12371246 ptr_size: PtrSize,
12381247 scale_index: ?ScaleIndex = null,
12391248
......@@ -1283,7 +1292,7 @@ const Memory = struct {
12831292 } else {
12841293 encoder.sib_baseDisp8(dst);
12851294 }
1286 encoder.disp8(@intCast(i8, mem_op.disp));
1295 encoder.disp8(@bitCast(i8, @truncate(u8, mem_op.disp)));
12871296 } else {
12881297 encoder.modRm_SIBDisp32(src);
12891298 if (mem_op.scale_index) |si| {
......@@ -1291,17 +1300,17 @@ const Memory = struct {
12911300 } else {
12921301 encoder.sib_baseDisp32(dst);
12931302 }
1294 encoder.disp32(mem_op.disp);
1303 encoder.disp32(@bitCast(i32, mem_op.disp));
12951304 }
12961305 } else {
12971306 if (mem_op.disp == 0) {
12981307 encoder.modRm_indirectDisp0(src, dst);
12991308 } else if (immOpSize(mem_op.disp) == 8) {
13001309 encoder.modRm_indirectDisp8(src, dst);
1301 encoder.disp8(@intCast(i8, mem_op.disp));
1310 encoder.disp8(@bitCast(i8, @truncate(u8, mem_op.disp)));
13021311 } else {
13031312 encoder.modRm_indirectDisp32(src, dst);
1304 encoder.disp32(mem_op.disp);
1313 encoder.disp32(@bitCast(i32, mem_op.disp));
13051314 }
13061315 }
13071316 } else {
......@@ -1315,16 +1324,16 @@ const Memory = struct {
13151324 encoder.sib_disp32();
13161325 }
13171326 }
1318 encoder.disp32(mem_op.disp);
1327 encoder.disp32(@bitCast(i32, mem_op.disp));
13191328 }
13201329 }
13211330};
13221331
1323fn encodeImm(encoder: Encoder, imm: i32, size: u64) void {
1332fn encodeImm(encoder: Encoder, imm: u32, size: u64) void {
13241333 switch (size) {
1325 8 => encoder.imm8(@intCast(i8, imm)),
1326 16 => encoder.imm16(@intCast(i16, imm)),
1327 32, 64 => encoder.imm32(imm),
1334 8 => encoder.imm8(@bitCast(i8, @truncate(u8, imm))),
1335 16 => encoder.imm16(@bitCast(i16, @truncate(u16, imm))),
1336 32, 64 => encoder.imm32(@bitCast(i32, imm)),
13281337 else => unreachable,
13291338 }
13301339}
......@@ -1338,7 +1347,7 @@ const RegisterOrMemory = union(enum) {
13381347 }
13391348
13401349 fn mem(ptr_size: Memory.PtrSize, args: struct {
1341 disp: i32,
1350 disp: u32,
13421351 base: ?Register = null,
13431352 scale_index: ?ScaleIndex = null,
13441353 }) RegisterOrMemory {
......@@ -1352,7 +1361,7 @@ const RegisterOrMemory = union(enum) {
13521361 };
13531362 }
13541363
1355 fn rip(ptr_size: Memory.PtrSize, disp: i32) RegisterOrMemory {
1364 fn rip(ptr_size: Memory.PtrSize, disp: u32) RegisterOrMemory {
13561365 return .{
13571366 .memory = .{
13581367 .base = null,
......@@ -1377,12 +1386,12 @@ fn lowerToZoEnc(tag: Tag, code: *std.ArrayList(u8)) LoweringError!void {
13771386 opc.encode(encoder);
13781387}
13791388
1380fn lowerToIEnc(tag: Tag, imm: i32, code: *std.ArrayList(u8)) LoweringError!void {
1389fn lowerToIEnc(tag: Tag, imm: u32, code: *std.ArrayList(u8)) LoweringError!void {
13811390 if (tag == .ret_far or tag == .ret_near) {
13821391 const encoder = try Encoder.init(code, 3);
13831392 const opc = getOpCode(tag, .i, false).?;
13841393 opc.encode(encoder);
1385 encoder.imm16(@intCast(i16, imm));
1394 encoder.imm16(@bitCast(i16, @truncate(u16, imm)));
13861395 return;
13871396 }
13881397 const opc = getOpCode(tag, .i, immOpSize(imm) == 8).?;
......@@ -1410,11 +1419,11 @@ fn lowerToOEnc(tag: Tag, reg: Register, code: *std.ArrayList(u8)) LoweringError!
14101419 opc.encodeWithReg(encoder, reg);
14111420}
14121421
1413fn lowerToDEnc(tag: Tag, imm: i32, code: *std.ArrayList(u8)) LoweringError!void {
1422fn lowerToDEnc(tag: Tag, imm: u32, code: *std.ArrayList(u8)) LoweringError!void {
14141423 const opc = getOpCode(tag, .d, false).?;
14151424 const encoder = try Encoder.init(code, 6);
14161425 opc.encode(encoder);
1417 encoder.imm32(imm);
1426 encoder.imm32(@bitCast(i32, imm));
14181427}
14191428
14201429fn 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))
14671476 }
14681477}
14691478
1470fn lowerToTdEnc(tag: Tag, moffs: i64, reg: Register, code: *std.ArrayList(u8)) LoweringError!void {
1479fn lowerToTdEnc(tag: Tag, moffs: u64, reg: Register, code: *std.ArrayList(u8)) LoweringError!void {
14711480 return lowerToTdFdEnc(tag, reg, moffs, code, true);
14721481}
14731482
1474fn lowerToFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8)) LoweringError!void {
1483fn lowerToFdEnc(tag: Tag, reg: Register, moffs: u64, code: *std.ArrayList(u8)) LoweringError!void {
14751484 return lowerToTdFdEnc(tag, reg, moffs, code, false);
14761485}
14771486
1478fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8), td: bool) LoweringError!void {
1487fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: u64, code: *std.ArrayList(u8), td: bool) LoweringError!void {
14791488 if (reg.lowId() != Register.rax.lowId()) {
14801489 return error.RaxOperandExpected;
14811490 }
1482 if (reg.size() != immOpSize(moffs)) {
1491 if (reg.size() != imm64OpSize(moffs)) {
14831492 return error.OperandSizeMismatch;
14841493 }
14851494 const opc = if (td)
......@@ -1495,27 +1504,16 @@ fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8),
14951504 });
14961505 opc.encode(encoder);
14971506 switch (reg.size()) {
1498 8 => {
1499 const moffs8 = try math.cast(i8, moffs);
1500 encoder.imm8(moffs8);
1501 },
1502 16 => {
1503 const moffs16 = try math.cast(i16, moffs);
1504 encoder.imm16(moffs16);
1505 },
1506 32 => {
1507 const moffs32 = try math.cast(i32, moffs);
1508 encoder.imm32(moffs32);
1509 },
1510 64 => {
1511 encoder.imm64(@bitCast(u64, moffs));
1512 },
1507 8 => encoder.imm8(@bitCast(i8, @truncate(u8, moffs))),
1508 16 => encoder.imm16(@bitCast(i16, @truncate(u16, moffs))),
1509 32 => encoder.imm32(@bitCast(i32, @truncate(u32, moffs))),
1510 64 => encoder.imm64(moffs),
15131511 else => unreachable,
15141512 }
15151513}
15161514
1517fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) LoweringError!void {
1518 if (reg.size() != immOpSize(imm)) {
1515fn lowerToOiEnc(tag: Tag, reg: Register, imm: u64, code: *std.ArrayList(u8)) LoweringError!void {
1516 if (reg.size() != imm64OpSize(imm)) {
15191517 return error.OperandSizeMismatch;
15201518 }
15211519 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
15291527 });
15301528 opc.encodeWithReg(encoder, reg);
15311529 switch (reg.size()) {
1532 8 => {
1533 const imm8 = try math.cast(i8, imm);
1534 encoder.imm8(imm8);
1535 },
1536 16 => {
1537 const imm16 = try math.cast(i16, imm);
1538 encoder.imm16(imm16);
1539 },
1540 32 => {
1541 const imm32 = try math.cast(i32, imm);
1542 encoder.imm32(imm32);
1543 },
1544 64 => {
1545 encoder.imm64(@bitCast(u64, imm));
1546 },
1530 8 => encoder.imm8(@bitCast(i8, @truncate(u8, imm))),
1531 16 => encoder.imm16(@bitCast(i16, @truncate(u16, imm))),
1532 32 => encoder.imm32(@bitCast(i32, @truncate(u32, imm))),
1533 64 => encoder.imm64(imm),
15471534 else => unreachable,
15481535 }
15491536}
15501537
1551fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: i32, code: *std.ArrayList(u8)) LoweringError!void {
1538fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: u32, code: *std.ArrayList(u8)) LoweringError!void {
15521539 const modrm_ext = getModRmExt(tag).?;
15531540 switch (reg_or_mem) {
15541541 .register => |dst_reg| {
......@@ -1700,7 +1687,7 @@ fn lowerToRmiEnc(
17001687 tag: Tag,
17011688 reg: Register,
17021689 reg_or_mem: RegisterOrMemory,
1703 imm: i32,
1690 imm: u32,
17041691 code: *std.ArrayList(u8),
17051692) LoweringError!void {
17061693 if (reg.size() == 8) {
......@@ -1804,7 +1791,10 @@ test "lower MI encoding" {
18041791 try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", isel.lowered(), "mov rax, 0x10");
18051792 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0, .base = .r11 }), 0x10, isel.code());
18061793 try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", isel.lowered(), "mov dword ptr [r11 + 0], 0x10");
1807 try lowerToMiEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{ .disp = -8, .base = .rdx }), 0x10, isel.code());
1794 try lowerToMiEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{
1795 .disp = @bitCast(u32, @as(i32, -8)),
1796 .base = .rdx,
1797 }), 0x10, isel.code());
18081798 try expectEqualHexStrings("\x81\x42\xF8\x10\x00\x00\x00", isel.lowered(), "add dword ptr [rdx - 8], 0x10");
18091799 try lowerToMiEnc(.sub, RegisterOrMemory.mem(.dword_ptr, .{
18101800 .disp = 0x10000000,
......@@ -1836,15 +1826,24 @@ test "lower MI encoding" {
18361826 isel.lowered(),
18371827 "mov qword ptr [rip + 0x10], 0x10",
18381828 );
1839 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -8, .base = .rbp }), 0x10, isel.code());
1829 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
1830 .disp = @bitCast(u32, @as(i32, -8)),
1831 .base = .rbp,
1832 }), 0x10, isel.code());
18401833 try expectEqualHexStrings(
18411834 "\x48\xc7\x45\xf8\x10\x00\x00\x00",
18421835 isel.lowered(),
18431836 "mov qword ptr [rbp - 8], 0x10",
18441837 );
1845 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.word_ptr, .{ .disp = -2, .base = .rbp }), 0x10, isel.code());
1838 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.word_ptr, .{
1839 .disp = @bitCast(u32, @as(i32, -2)),
1840 .base = .rbp,
1841 }), 0x10, isel.code());
18461842 try expectEqualHexStrings("\x66\xC7\x45\xFE\x10\x00", isel.lowered(), "mov word ptr [rbp - 2], 0x10");
1847 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.byte_ptr, .{ .disp = -1, .base = .rbp }), 0x10, isel.code());
1843 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.byte_ptr, .{
1844 .disp = @bitCast(u32, @as(i32, -1)),
1845 .base = .rbp,
1846 }), 0x10, isel.code());
18481847 try expectEqualHexStrings("\xC6\x45\xFF\x10", isel.lowered(), "mov byte ptr [rbp - 1], 0x10");
18491848 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
18501849 .disp = 0x10000000,
......@@ -1897,12 +1896,15 @@ test "lower RM encoding" {
18971896 isel.lowered(),
18981897 "sub r11, qword ptr [r12 + 0x10000000]",
18991898 );
1900 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -4, .base = .rbp }), isel.code());
1899 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
1900 .disp = @bitCast(u32, @as(i32, -4)),
1901 .base = .rbp,
1902 }), isel.code());
19011903 try expectEqualHexStrings("\x48\x8B\x45\xFC", isel.lowered(), "mov rax, qword ptr [rbp - 4]");
19021904 try lowerToRmEnc(.lea, .rax, RegisterOrMemory.rip(.qword_ptr, 0x10), isel.code());
19031905 try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", isel.lowered(), "lea rax, [rip + 0x10]");
19041906 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
1905 .disp = -8,
1907 .disp = @bitCast(u32, @as(i32, -8)),
19061908 .base = .rbp,
19071909 .scale_index = .{
19081910 .scale = 0,
......@@ -1911,7 +1913,7 @@ test "lower RM encoding" {
19111913 }), isel.code());
19121914 try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*1 - 8]");
19131915 try lowerToRmEnc(.mov, .eax, RegisterOrMemory.mem(.dword_ptr, .{
1914 .disp = -4,
1916 .disp = @bitCast(u32, @as(i32, -4)),
19151917 .base = .rbp,
19161918 .scale_index = .{
19171919 .scale = 2,
......@@ -1920,7 +1922,7 @@ test "lower RM encoding" {
19201922 }), isel.code());
19211923 try expectEqualHexStrings("\x8B\x44\x95\xFC", isel.lowered(), "mov eax, dword ptr [rbp + rdx*4 - 4]");
19221924 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
1923 .disp = -8,
1925 .disp = @bitCast(u32, @as(i32, -8)),
19241926 .base = .rbp,
19251927 .scale_index = .{
19261928 .scale = 3,
......@@ -1929,7 +1931,7 @@ test "lower RM encoding" {
19291931 }), isel.code());
19301932 try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*8 - 8]");
19311933 try lowerToRmEnc(.mov, .r8b, RegisterOrMemory.mem(.byte_ptr, .{
1932 .disp = -24,
1934 .disp = @bitCast(u32, @as(i32, -24)),
19331935 .base = .rsi,
19341936 .scale_index = .{
19351937 .scale = 0,
......@@ -1953,7 +1955,10 @@ test "lower MR encoding" {
19531955 defer isel.deinit();
19541956 try lowerToMrEnc(.mov, RegisterOrMemory.reg(.rax), .rbx, isel.code());
19551957 try expectEqualHexStrings("\x48\x89\xd8", isel.lowered(), "mov rax, rbx");
1956 try lowerToMrEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -4, .base = .rbp }), .r11, isel.code());
1958 try lowerToMrEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
1959 .disp = @bitCast(u32, @as(i32, -4)),
1960 .base = .rbp,
1961 }), .r11, isel.code());
19571962 try expectEqualHexStrings("\x4c\x89\x5d\xfc", isel.lowered(), "mov qword ptr [rbp - 4], r11");
19581963 try lowerToMrEnc(.add, RegisterOrMemory.mem(.byte_ptr, .{ .disp = 0x10000000 }), .r12b, isel.code());
19591964 try expectEqualHexStrings(
......@@ -2063,7 +2068,7 @@ test "lower RMI encoding" {
20632068 var isel = TestIsel.init();
20642069 defer isel.deinit();
20652070 try lowerToRmiEnc(.imul, .rax, RegisterOrMemory.mem(.qword_ptr, .{
2066 .disp = -8,
2071 .disp = @bitCast(u32, @as(i32, -8)),
20672072 .base = .rbp,
20682073 }), 0x10, isel.code());
20692074 try expectEqualHexStrings(
......@@ -2072,12 +2077,12 @@ test "lower RMI encoding" {
20722077 "imul rax, qword ptr [rbp - 8], 0x10",
20732078 );
20742079 try lowerToRmiEnc(.imul, .eax, RegisterOrMemory.mem(.dword_ptr, .{
2075 .disp = -4,
2080 .disp = @bitCast(u32, @as(i32, -4)),
20762081 .base = .rbp,
20772082 }), 0x10, isel.code());
20782083 try expectEqualHexStrings("\x69\x45\xFC\x10\x00\x00\x00", isel.lowered(), "imul eax, dword ptr [rbp - 4], 0x10");
20792084 try lowerToRmiEnc(.imul, .ax, RegisterOrMemory.mem(.word_ptr, .{
2080 .disp = -2,
2085 .disp = @bitCast(u32, @as(i32, -2)),
20812086 .base = .rbp,
20822087 }), 0x10, isel.code());
20832088 try expectEqualHexStrings("\x66\x69\x45\xFE\x10\x00", isel.lowered(), "imul ax, word ptr [rbp - 2], 0x10");
src/arch/x86_64/Mir.zig+3-3
......@@ -302,7 +302,7 @@ pub const Inst = struct {
302302 /// Another instruction.
303303 inst: Index,
304304 /// A 32-bit immediate value.
305 imm: i32,
305 imm: u32,
306306 /// An extern function.
307307 /// Index into the linker's string table.
308308 extern_fn: u32,
......@@ -324,8 +324,8 @@ pub const Inst = struct {
324324};
325325
326326pub const ImmPair = struct {
327 dest_off: i32,
328 operand: i32,
327 dest_off: u32,
328 operand: u32,
329329};
330330
331331pub const Imm64 = struct {
test/stage2/x86_64.zig+30
......@@ -1700,6 +1700,36 @@ pub fn addCases(ctx: *TestContext) !void {
17001700 \\ if (!ok) unreachable;
17011701 \\}
17021702 , "");
1703 case.addCompareOutput(
1704 \\pub fn main() void {
1705 \\ var x: u16 = undefined;
1706 \\ set(&x);
1707 \\ assert(x == 123);
1708 \\}
1709 \\
1710 \\fn set(x: *u16) void {
1711 \\ x.* = 123;
1712 \\}
1713 \\
1714 \\fn assert(ok: bool) void {
1715 \\ if (!ok) unreachable;
1716 \\}
1717 , "");
1718 case.addCompareOutput(
1719 \\pub fn main() void {
1720 \\ var x: u8 = undefined;
1721 \\ set(&x);
1722 \\ assert(x == 123);
1723 \\}
1724 \\
1725 \\fn set(x: *u8) void {
1726 \\ x.* = 123;
1727 \\}
1728 \\
1729 \\fn assert(ok: bool) void {
1730 \\ if (!ok) unreachable;
1731 \\}
1732 , "");
17031733 }
17041734
17051735 {