aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-03-27 04:05:19 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2023-03-27 05:58:00 -0400
commit6c5442841565196ddeb90735496aad04db3ecdfd (patch)
tree1341d3296e497ef8f692d4f0b1a8da8bd083b530 /src/arch
parent587eacefec7d00c60cb32a10f7084dd7e61a970a (diff)
downloadzig-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.zig78
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;
};