diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2023-03-27 04:05:19 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2023-03-27 05:58:00 -0400 |
| commit | 6c5442841565196ddeb90735496aad04db3ecdfd (patch) | |
| tree | 1341d3296e497ef8f692d4f0b1a8da8bd083b530 /src/arch | |
| parent | 587eacefec7d00c60cb32a10f7084dd7e61a970a (diff) | |
| download | zig-6c5442841565196ddeb90735496aad04db3ecdfd.tar.gz zig-6c5442841565196ddeb90735496aad04db3ecdfd.zip | |
x86_64: implement trunc with large source
Diffstat (limited to 'src/arch')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 78 |
1 files changed, 32 insertions, 46 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 9128d6ce22..a3615611ba 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1549,43 +1549,31 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; - if (self.liveness.isUnused(inst)) - return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); - - const src_ty = self.air.typeOf(ty_op.operand); - const dst_ty = self.air.typeOfIndex(inst); - const operand = try self.resolveInst(ty_op.operand); - - const src_ty_size = src_ty.abiSize(self.target.*); - const dst_ty_size = dst_ty.abiSize(self.target.*); + const result = if (self.liveness.isUnused(inst)) .dead else result: { + const dst_ty = self.air.typeOfIndex(inst); + const dst_abi_size = dst_ty.abiSize(self.target.*); + if (dst_abi_size > 8) { + return self.fail("TODO implement trunc for abi sizes larger than 8", .{}); + } - if (src_ty_size > 8 or dst_ty_size > 8) { - return self.fail("TODO implement trunc for abi sizes larger than 8", .{}); - } + const src_mcv = try self.resolveInst(ty_op.operand); + const src_lock = switch (src_mcv) { + .register => |reg| self.register_manager.lockRegAssumeUnused(reg), + else => null, + }; + defer if (src_lock) |lock| self.register_manager.unlockReg(lock); - const operand_lock: ?RegisterLock = switch (operand) { - .register => |reg| self.register_manager.lockRegAssumeUnused(reg), - else => null, - }; - defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); + const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) + src_mcv + else + try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv); - const reg: Register = blk: { - if (operand.isRegister()) { - if (self.reuseOperand(inst, ty_op.operand, 0, operand)) { - break :blk operand.register.to64(); - } - } - const mcv = try self.copyToRegisterWithInstTracking(inst, src_ty, operand); - break :blk mcv.register.to64(); + // when truncating a `u16` to `u5`, for example, those top 3 bits in the result + // have to be removed. this only happens if the dst if not a power-of-two size. + if (self.regExtraBits(dst_ty) > 0) try self.truncateRegister(dst_ty, dst_mcv.register.to64()); + break :result dst_mcv; }; - - // when truncating a `u16` to `u5`, for example, those top 3 bits in the result - // have to be removed. this only happens if the dst if not a power-of-two size. - if (self.regExtraBits(dst_ty) > 0) { - try self.truncateRegister(dst_ty, reg); - } - - return self.finishAir(inst, .{ .register = reg }, .{ ty_op.operand, .none, .none }); + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void { @@ -3499,23 +3487,21 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { const elem_ty = self.air.typeOfIndex(inst); const elem_size = elem_ty.abiSize(self.target.*); const result: MCValue = result: { - if (!elem_ty.hasRuntimeBitsIgnoreComptime()) - break :result MCValue.none; + if (!elem_ty.hasRuntimeBitsIgnoreComptime()) break :result .none; + + try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); + const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); + defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); const ptr = try self.resolveInst(ty_op.operand); const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr(); - if (self.liveness.isUnused(inst) and !is_volatile) - break :result MCValue.dead; + if (self.liveness.isUnused(inst) and !is_volatile) break :result .dead; - const dst_mcv: MCValue = blk: { - if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) { - // The MCValue that holds the pointer can be re-used as the value. - break :blk ptr; - } else { - break :blk try self.allocRegOrMem(inst, true); - } - }; - log.debug("airLoad(%{d}): {} <- {}", .{ inst, dst_mcv, ptr }); + const dst_mcv: MCValue = if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) + // The MCValue that holds the pointer can be re-used as the value. + ptr + else + try self.allocRegOrMem(inst, true); try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand)); break :result dst_mcv; }; |
