| ... | @@ -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 |
| 1471 | | 1464 | |
| 1472 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { | 1465 | fn 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 | } |
| 3073 | | 3120 | |
| 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]; |
| 3077 | | 3124 | |