From 350bf9db131dd5573da0d06d38e40746c99a8a34 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 2 Mar 2022 14:29:48 +0100 Subject: [PATCH] x64: fix intCast to properly clear out dest register --- src/arch/x86_64/CodeGen.zig | 26 ++++++++++++++++++-------- test/behavior/cast.zig | 10 +--------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 3ecf4a70aa..8efb1042ef 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -981,7 +981,10 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { operand.freezeIfRegister(&self.register_manager); defer operand.unfreezeIfRegister(&self.register_manager); - break :blk try self.copyToRegisterWithInstTracking(inst, dest_ty, operand); + const reg = try self.register_manager.allocReg(inst); + try self.genSetReg(dest_ty, reg, .{ .immediate = 0 }); + try self.genSetReg(operand_ty, reg, operand); + break :blk MCValue{ .register = reg }; }; return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); @@ -1851,22 +1854,29 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { - const payload_ty = self.air.typeOf(ty_op.operand); + if (self.liveness.isUnused(inst)) { + return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); + } + + const payload_ty = self.air.typeOf(ty_op.operand); + const result: MCValue = result: { if (!payload_ty.hasRuntimeBits()) { break :result MCValue{ .immediate = 1 }; } const optional_ty = self.air.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); - if (optional_ty.isPtrLikeOptional()) { - // TODO should we check if we can reuse the operand? - break :result operand; - } - operand.freezeIfRegister(&self.register_manager); defer operand.unfreezeIfRegister(&self.register_manager); + if (optional_ty.isPtrLikeOptional()) { + // TODO should we check if we can reuse the operand? + if (self.reuseOperand(inst, ty_op.operand, 0, operand)) { + break :result operand; + } + break :result try self.copyToRegisterWithInstTracking(inst, payload_ty, operand); + } + const optional_abi_size = @intCast(u32, optional_ty.abiSize(self.target.*)); const optional_abi_align = optional_ty.abiAlignment(self.target.*); const payload_abi_size = @intCast(u32, payload_ty.abiSize(self.target.*)); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 39c142f3f0..30c3e12ce0 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -302,7 +302,7 @@ fn implicitIntLitToOptional() void { test "return u8 coercing into ?u32 return type" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -373,7 +373,6 @@ fn testPeerResolveArrayConstSlice(b: bool) !void { test "implicitly cast from T to anyerror!?T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; try castToOptionalTypeError(1); comptime try castToOptionalTypeError(1); @@ -1036,7 +1035,6 @@ test "implicit cast from [*]T to ?*anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO var a = [_]u8{ 3, 2, 1 }; var runtime_zero: usize = 0; @@ -1073,7 +1071,6 @@ test "implicit ptr to *anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO var a: u32 = 1; var ptr: *align(@alignOf(u32)) anyopaque = &a; @@ -1087,7 +1084,6 @@ test "implicit ptr to *anyopaque" { test "return null from fn() anyerror!?&T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO const a = returnNullFromOptionalTypeErrorRef(); const b = returnNullLitFromOptionalTypeErrorRef(); @@ -1125,7 +1121,6 @@ test "implicitly cast from [N]T to ?[]const T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); @@ -1177,7 +1172,6 @@ test "implicit cast from *T to ?*anyopaque" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO var a: u8 = 1; incrementVoidPtrValue(&a); @@ -1213,7 +1207,6 @@ test "*const [N]null u8 to ?[]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { @@ -1249,7 +1242,6 @@ test "assignment to optional pointer result loc" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct }; try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct));