Commit 05431d7c4a
Changed files (2)
src
arch
x86_64
test
behavior
src/arch/x86_64/CodeGen.zig
@@ -1738,14 +1738,22 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
}
const err_union_ty = self.air.typeOf(ty_op.operand);
+ const err_ty = err_union_ty.errorUnionSet();
const payload_ty = err_union_ty.errorUnionPayload();
const operand = try self.resolveInst(ty_op.operand);
+ operand.freezeIfRegister(&self.register_manager);
+ defer operand.unfreezeIfRegister(&self.register_manager);
+
const result: MCValue = result: {
if (!payload_ty.hasRuntimeBits()) break :result operand;
switch (operand) {
.stack_offset => |off| {
break :result MCValue{ .stack_offset = off };
},
+ .register => {
+ // TODO reuse operand
+ break :result try self.copyToRegisterWithInstTracking(inst, err_ty, operand);
+ },
else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),
}
};
@@ -1763,13 +1771,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
const operand = try self.resolveInst(ty_op.operand);
+ operand.freezeIfRegister(&self.register_manager);
+ defer operand.unfreezeIfRegister(&self.register_manager);
+
const err_ty = err_union_ty.errorUnionSet();
- const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
switch (operand) {
.stack_offset => |off| {
+ const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
const offset = off - @intCast(i32, err_abi_size);
break :result MCValue{ .stack_offset = offset };
},
+ .register => {
+ // TODO reuse operand
+ const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand);
+ try self.shiftRegister(result.register.to64(), @intCast(u6, err_ty.bitSize(self.target.*)));
+ break :result MCValue{
+ .register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))),
+ };
+ },
else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}),
}
};
@@ -2686,27 +2705,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
};
// Shift by struct_field_offset.
- const shift_amount = @intCast(u8, struct_field_offset * 8);
- if (shift_amount > 0) {
- if (shift_amount == 1) {
- _ = try self.addInst(.{
- .tag = .shr,
- .ops = (Mir.Ops{
- .reg1 = dst_mcv.register,
- }).encode(),
- .data = undefined,
- });
- } else {
- _ = try self.addInst(.{
- .tag = .shr,
- .ops = (Mir.Ops{
- .reg1 = dst_mcv.register,
- .flags = 0b10,
- }).encode(),
- .data = .{ .imm = shift_amount },
- });
- }
- }
+ const shift = @intCast(u8, struct_field_offset * 8);
+ try self.shiftRegister(dst_mcv.register, shift);
// Mask with reg.size() - struct_field_size
const mask_shift = @intCast(u6, (64 - struct_field_ty.bitSize(self.target.*)));
@@ -5768,3 +5768,25 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
unreachable; // TODO handle floating-point registers
}
}
+
+fn shiftRegister(self: *Self, reg: Register, shift: u8) !void {
+ if (shift == 0) return;
+ if (shift == 1) {
+ _ = try self.addInst(.{
+ .tag = .shr,
+ .ops = (Mir.Ops{
+ .reg1 = reg,
+ }).encode(),
+ .data = undefined,
+ });
+ } else {
+ _ = try self.addInst(.{
+ .tag = .shr,
+ .ops = (Mir.Ops{
+ .reg1 = reg,
+ .flags = 0b10,
+ }).encode(),
+ .data = .{ .imm = shift },
+ });
+ }
+}
test/behavior/error.zig
@@ -78,7 +78,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
}
test "error return in assignment" {
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
@@ -121,7 +120,6 @@ test "widen cast integer payload of error union function call" {
}
test "debug info for optional error set" {
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
@@ -173,7 +171,6 @@ fn bar2() (error{}!void) {}
test "error union type " {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
try testErrorUnionType();
@@ -191,7 +188,6 @@ fn testErrorUnionType() !void {
test "error set type" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
try testErrorSetType();