| ... | ... | @@ -1549,43 +1549,31 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1549 | 1549 | |
| 1550 | 1550 | fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 1551 | 1551 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1552 | | if (self.liveness.isUnused(inst)) |
| 1553 | | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1554 | | |
| 1555 | | const src_ty = self.air.typeOf(ty_op.operand); |
| 1556 | | const dst_ty = self.air.typeOfIndex(inst); |
| 1557 | | const operand = try self.resolveInst(ty_op.operand); |
| 1558 | | |
| 1559 | | const src_ty_size = src_ty.abiSize(self.target.*); |
| 1560 | | const dst_ty_size = dst_ty.abiSize(self.target.*); |
| 1552 | const result = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1553 | const dst_ty = self.air.typeOfIndex(inst); |
| 1554 | const dst_abi_size = dst_ty.abiSize(self.target.*); |
| 1555 | if (dst_abi_size > 8) { |
| 1556 | return self.fail("TODO implement trunc for abi sizes larger than 8", .{}); |
| 1557 | } |
| 1561 | 1558 | |
| 1562 | | if (src_ty_size > 8 or dst_ty_size > 8) { |
| 1563 | | return self.fail("TODO implement trunc for abi sizes larger than 8", .{}); |
| 1564 | | } |
| 1559 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 1560 | const src_lock = switch (src_mcv) { |
| 1561 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 1562 | else => null, |
| 1563 | }; |
| 1564 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 1565 | 1565 | |
| 1566 | | const operand_lock: ?RegisterLock = switch (operand) { |
| 1567 | | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 1568 | | else => null, |
| 1569 | | }; |
| 1570 | | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); |
| 1566 | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 1567 | src_mcv |
| 1568 | else |
| 1569 | try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv); |
| 1571 | 1570 | |
| 1572 | | const reg: Register = blk: { |
| 1573 | | if (operand.isRegister()) { |
| 1574 | | if (self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 1575 | | break :blk operand.register.to64(); |
| 1576 | | } |
| 1577 | | } |
| 1578 | | const mcv = try self.copyToRegisterWithInstTracking(inst, src_ty, operand); |
| 1579 | | break :blk mcv.register.to64(); |
| 1571 | // when truncating a `u16` to `u5`, for example, those top 3 bits in the result |
| 1572 | // have to be removed. this only happens if the dst if not a power-of-two size. |
| 1573 | if (self.regExtraBits(dst_ty) > 0) try self.truncateRegister(dst_ty, dst_mcv.register.to64()); |
| 1574 | break :result dst_mcv; |
| 1580 | 1575 | }; |
| 1581 | | |
| 1582 | | // when truncating a `u16` to `u5`, for example, those top 3 bits in the result |
| 1583 | | // have to be removed. this only happens if the dst if not a power-of-two size. |
| 1584 | | if (self.regExtraBits(dst_ty) > 0) { |
| 1585 | | try self.truncateRegister(dst_ty, reg); |
| 1586 | | } |
| 1587 | | |
| 1588 | | return self.finishAir(inst, .{ .register = reg }, .{ ty_op.operand, .none, .none }); |
| 1576 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1589 | 1577 | } |
| 1590 | 1578 | |
| 1591 | 1579 | fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -3499,23 +3487,21 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3499 | 3487 | const elem_ty = self.air.typeOfIndex(inst); |
| 3500 | 3488 | const elem_size = elem_ty.abiSize(self.target.*); |
| 3501 | 3489 | const result: MCValue = result: { |
| 3502 | | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) |
| 3503 | | break :result MCValue.none; |
| 3490 | if (!elem_ty.hasRuntimeBitsIgnoreComptime()) break :result .none; |
| 3491 | |
| 3492 | try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); |
| 3493 | const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); |
| 3494 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| 3504 | 3495 | |
| 3505 | 3496 | const ptr = try self.resolveInst(ty_op.operand); |
| 3506 | 3497 | const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr(); |
| 3507 | | if (self.liveness.isUnused(inst) and !is_volatile) |
| 3508 | | break :result MCValue.dead; |
| 3498 | if (self.liveness.isUnused(inst) and !is_volatile) break :result .dead; |
| 3509 | 3499 | |
| 3510 | | const dst_mcv: MCValue = blk: { |
| 3511 | | if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) { |
| 3512 | | // The MCValue that holds the pointer can be re-used as the value. |
| 3513 | | break :blk ptr; |
| 3514 | | } else { |
| 3515 | | break :blk try self.allocRegOrMem(inst, true); |
| 3516 | | } |
| 3517 | | }; |
| 3518 | | log.debug("airLoad(%{d}): {} <- {}", .{ inst, dst_mcv, ptr }); |
| 3500 | const dst_mcv: MCValue = if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) |
| 3501 | // The MCValue that holds the pointer can be re-used as the value. |
| 3502 | ptr |
| 3503 | else |
| 3504 | try self.allocRegOrMem(inst, true); |
| 3519 | 3505 | try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand)); |
| 3520 | 3506 | break :result dst_mcv; |
| 3521 | 3507 | }; |