aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-03-02 14:29:48 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-03-02 14:34:43 +0100
commit350bf9db131dd5573da0d06d38e40746c99a8a34 (patch)
tree386bed9ea764d82d76468dac1253be0975a62ee6
parentd35cae551ed5f3e6082b2e599f9c258af9d2630e (diff)
downloadzig-350bf9db131dd5573da0d06d38e40746c99a8a34.tar.gz
zig-350bf9db131dd5573da0d06d38e40746c99a8a34.zip
x64: fix intCast to properly clear out dest register
-rw-r--r--src/arch/x86_64/CodeGen.zig24
-rw-r--r--test/behavior/cast.zig10
2 files changed, 18 insertions, 16 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);
+ 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?
- break :result operand;
+ if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
+ break :result operand;
+ }
+ break :result try self.copyToRegisterWithInstTracking(inst, payload_ty, operand);
}
- operand.freezeIfRegister(&self.register_manager);
- defer operand.unfreezeIfRegister(&self.register_manager);
-
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));