| ... | ... | @@ -1150,17 +1150,10 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1150 | 1150 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1151 | 1151 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1152 | 1152 | const operand = try self.resolveInst(ty_op.operand); |
| 1153 | | const dst_mcv: MCValue = blk: { |
| 1154 | | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 1155 | | break :blk operand; |
| 1156 | | } else { |
| 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; |
| 1153 | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 1154 | break :result operand; |
| 1155 | } |
| 1156 | break :result try self.copyToNewRegister(inst, operand); |
| 1164 | 1157 | }; |
| 1165 | 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 | 1464 | |
| 1472 | 1465 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 1473 | 1466 | const elem_ty = ptr_ty.elemType(); |
| 1467 | const abi_size = elem_ty.abiSize(self.target.*); |
| 1474 | 1468 | switch (ptr) { |
| 1475 | 1469 | .none => unreachable, |
| 1476 | 1470 | .undef => unreachable, |
| ... | ... | @@ -1478,7 +1472,9 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1478 | 1472 | .dead => unreachable, |
| 1479 | 1473 | .compare_flags_unsigned => unreachable, |
| 1480 | 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 | 1478 | .ptr_stack_offset => |off| { |
| 1483 | 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 | 1484 | .embedded_in_code => { |
| 1489 | 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 | 1539 | .memory => |addr| { |
| 1493 | 1540 | const reg = try self.copyToTmpRegister(ptr_ty, .{ .memory = addr }); |
| 1494 | 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 | 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 | 3122 | const addr_reg = regs[0]; |
| 3076 | 3123 | const len_reg = regs[1]; |
| 3077 | 3124 | |