authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-04 12:37:12+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-06 09:54:33+01:00
log2b77775cbb6990e24578f5f9c6bf32ad1da12f76
tree0653b8fc4efa1ae9732e55fa878dcd15dd49402e
parentb3f70db43899740c790b5118c2d420448191fd77

stage2: fix loading pointer value from register

Fix accessing optional payload.

2 files changed, 86 insertions(+), 30 deletions(-)

src/arch/x86_64/CodeGen.zig+61-14
...@@ -1150,17 +1150,10 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -1150,17 +1150,10 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
1150 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1150 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1151 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1151 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1152 const operand = try self.resolveInst(ty_op.operand);1152 const operand = try self.resolveInst(ty_op.operand);
1153 const dst_mcv: MCValue = blk: {1153 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1154 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {1154 break :result operand;
1155 break :blk operand;1155 }
1156 } else {1156 break :result try self.copyToNewRegister(inst, operand);
1157 break :blk try self.allocRegOrMem(inst, true);
1158 }
1159 };
1160 const ty = self.air.typeOf(ty_op.operand);
1161 var buf: Type.Payload.ElemType = undefined;
1162 try self.load(dst_mcv, operand, ty.optionalChild(&buf));
1163 break :result dst_mcv;
1164 };1157 };
1165 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1158 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1166}1159}
...@@ -1471,6 +1464,7 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind...@@ -1471,6 +1464,7 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
14711464
1472fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {1465fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
1473 const elem_ty = ptr_ty.elemType();1466 const elem_ty = ptr_ty.elemType();
1467 const abi_size = elem_ty.abiSize(self.target.*);
1474 switch (ptr) {1468 switch (ptr) {
1475 .none => unreachable,1469 .none => unreachable,
1476 .undef => unreachable,1470 .undef => unreachable,
...@@ -1478,7 +1472,9 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1478,7 +1472,9 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1478 .dead => unreachable,1472 .dead => unreachable,
1479 .compare_flags_unsigned => unreachable,1473 .compare_flags_unsigned => unreachable,
1480 .compare_flags_signed => unreachable,1474 .compare_flags_signed => unreachable,
1481 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),1475 .immediate => |imm| {
1476 try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm });
1477 },
1482 .ptr_stack_offset => |off| {1478 .ptr_stack_offset => |off| {
1483 try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off });1479 try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off });
1484 },1480 },
...@@ -1488,7 +1484,58 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1488,7 +1484,58 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1488 .embedded_in_code => {1484 .embedded_in_code => {
1489 return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});1485 return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});
1490 },1486 },
1491 .register => |reg| try self.setRegOrMem(ptr_ty, dst_mcv, .{ .register = reg }),1487 .register => |reg| {
1488 switch (dst_mcv) {
1489 .dead => unreachable,
1490 .undef => unreachable,
1491 .compare_flags_unsigned => unreachable,
1492 .compare_flags_signed => unreachable,
1493 .embedded_in_code => unreachable,
1494 .register => |dst_reg| {
1495 // mov dst_reg, [reg]
1496 _ = try self.addInst(.{
1497 .tag = .mov,
1498 .ops = (Mir.Ops{
1499 .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)),
1500 .reg2 = reg,
1501 .flags = 0b01,
1502 }).encode(),
1503 .data = .{ .imm = 0 },
1504 });
1505 },
1506 .stack_offset => |unadjusted_off| {
1507 if (abi_size <= 8) {
1508 const tmp_reg = try self.register_manager.allocReg(null, &.{reg});
1509 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
1510 return self.genSetStack(elem_ty, unadjusted_off, MCValue{ .register = tmp_reg });
1511 }
1512
1513 const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{ reg, .rax, .rcx });
1514 const addr_reg = regs[0];
1515 const len_reg = regs[1];
1516
1517 const off = unadjusted_off + abi_size;
1518 _ = try self.addInst(.{
1519 .tag = .mov,
1520 .ops = (Mir.Ops{
1521 .reg1 = registerAlias(addr_reg, @divExact(reg.size(), 8)),
1522 .reg2 = reg,
1523 }).encode(),
1524 .data = undefined,
1525 });
1526
1527 // TODO allow for abi size to be u64
1528 try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) });
1529
1530 return self.genInlineMemcpy(
1531 -@intCast(i32, off),
1532 registerAlias(addr_reg, @divExact(reg.size(), 8)),
1533 len_reg.to64(),
1534 );
1535 },
1536 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
1537 }
1538 },
1492 .memory => |addr| {1539 .memory => |addr| {
1493 const reg = try self.copyToTmpRegister(ptr_ty, .{ .memory = addr });1540 const reg = try self.copyToTmpRegister(ptr_ty, .{ .memory = addr });
1494 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);1541 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
...@@ -3071,7 +3118,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3071,7 +3118,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3071 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3118 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3072 }3119 }
30733120
3074 const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{});3121 const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{ .rax, .rcx });
3075 const addr_reg = regs[0];3122 const addr_reg = regs[0];
3076 const len_reg = regs[1];3123 const len_reg = regs[1];
30773124
src/arch/x86_64/Isel.zig+25-16
...@@ -493,13 +493,14 @@ fn mirArithScaleSrc(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void...@@ -493,13 +493,14 @@ fn mirArithScaleSrc(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void
493 const scale = ops.flags;493 const scale = ops.flags;
494 const imm = isel.mir.instructions.items(.data)[inst].imm;494 const imm = isel.mir.instructions.items(.data)[inst].imm;
495 // OP reg1, [reg2 + scale*rcx + imm32]495 // OP reg1, [reg2 + scale*rcx + imm32]
496 const scale_index = ScaleIndex{
497 .scale = scale,
498 .index = .rcx,
499 };
496 return lowerToRmEnc(tag, ops.reg1, RegisterOrMemory.mem(Memory.PtrSize.fromBits(ops.reg1.size()), .{500 return lowerToRmEnc(tag, ops.reg1, RegisterOrMemory.mem(Memory.PtrSize.fromBits(ops.reg1.size()), .{
497 .disp = imm,501 .disp = imm,
498 .base = ops.reg2,502 .base = ops.reg2,
499 .scale_index = .{503 .scale_index = scale_index,
500 .scale = scale,
501 .index = .rcx,
502 },
503 }), isel.code) catch |err| isel.failWithLoweringError(err);504 }), isel.code) catch |err| isel.failWithLoweringError(err);
504}505}
505506
...@@ -507,25 +508,23 @@ fn mirArithScaleDst(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void...@@ -507,25 +508,23 @@ fn mirArithScaleDst(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void
507 const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);508 const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
508 const scale = ops.flags;509 const scale = ops.flags;
509 const imm = isel.mir.instructions.items(.data)[inst].imm;510 const imm = isel.mir.instructions.items(.data)[inst].imm;
511 const scale_index = ScaleIndex{
512 .scale = scale,
513 .index = .rax,
514 };
510 if (ops.reg2 == .none) {515 if (ops.reg2 == .none) {
511 // OP qword ptr [reg1 + scale*rax + 0], imm32516 // OP qword ptr [reg1 + scale*rax + 0], imm32
512 return lowerToMiEnc(tag, RegisterOrMemory.mem(.qword_ptr, .{517 return lowerToMiEnc(tag, RegisterOrMemory.mem(.qword_ptr, .{
513 .disp = 0,518 .disp = 0,
514 .base = ops.reg1,519 .base = ops.reg1,
515 .scale_index = .{520 .scale_index = scale_index,
516 .scale = scale,
517 .index = .rax,
518 },
519 }), imm, isel.code) catch |err| isel.failWithLoweringError(err);521 }), imm, isel.code) catch |err| isel.failWithLoweringError(err);
520 }522 }
521 // OP [reg1 + scale*rax + imm32], reg2523 // OP [reg1 + scale*rax + imm32], reg2
522 return lowerToMrEnc(tag, RegisterOrMemory.mem(Memory.PtrSize.fromBits(ops.reg2.size()), .{524 return lowerToMrEnc(tag, RegisterOrMemory.mem(Memory.PtrSize.fromBits(ops.reg2.size()), .{
523 .disp = imm,525 .disp = imm,
524 .base = ops.reg1,526 .base = ops.reg1,
525 .scale_index = .{527 .scale_index = scale_index,
526 .scale = scale,
527 .index = .rax,
528 },
529 }), ops.reg2, isel.code) catch |err| isel.failWithLoweringError(err);528 }), ops.reg2, isel.code) catch |err| isel.failWithLoweringError(err);
530}529}
531530
...@@ -534,14 +533,15 @@ fn mirArithScaleImm(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void...@@ -534,14 +533,15 @@ fn mirArithScaleImm(isel: *Isel, tag: Tag, inst: Mir.Inst.Index) InnerError!void
534 const scale = ops.flags;533 const scale = ops.flags;
535 const payload = isel.mir.instructions.items(.data)[inst].payload;534 const payload = isel.mir.instructions.items(.data)[inst].payload;
536 const imm_pair = isel.mir.extraData(Mir.ImmPair, payload).data;535 const imm_pair = isel.mir.extraData(Mir.ImmPair, payload).data;
536 const scale_index = ScaleIndex{
537 .scale = scale,
538 .index = .rax,
539 };
537 // OP qword ptr [reg1 + scale*rax + imm32], imm32540 // OP qword ptr [reg1 + scale*rax + imm32], imm32
538 return lowerToMiEnc(tag, RegisterOrMemory.mem(.qword_ptr, .{541 return lowerToMiEnc(tag, RegisterOrMemory.mem(.qword_ptr, .{
539 .disp = imm_pair.dest_off,542 .disp = imm_pair.dest_off,
540 .base = ops.reg1,543 .base = ops.reg1,
541 .scale_index = .{544 .scale_index = scale_index,
542 .scale = scale,
543 .index = .rax,
544 },
545 }), imm_pair.operand, isel.code) catch |err| isel.failWithLoweringError(err);545 }), imm_pair.operand, isel.code) catch |err| isel.failWithLoweringError(err);
546}546}
547547
...@@ -1907,6 +1907,15 @@ test "lower RM encoding" {...@@ -1907,6 +1907,15 @@ test "lower RM encoding" {
1907 },1907 },
1908 }), isel.code());1908 }), isel.code());
1909 try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*8 - 8]");1909 try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*8 - 8]");
1910 try lowerToRmEnc(.mov, .r8b, RegisterOrMemory.mem(.byte_ptr, .{
1911 .disp = -24,
1912 .base = .rsi,
1913 .scale_index = .{
1914 .scale = 0,
1915 .index = .rcx,
1916 },
1917 }), isel.code());
1918 try expectEqualHexStrings("\x44\x8A\x44\x0E\xE8", isel.lowered(), "mov r8b, byte ptr [rsi + rcx*1 - 24]");
1910}1919}
19111920
1912test "lower MR encoding" {1921test "lower MR encoding" {