codegen: fix padding calculation for error unions when lowering

* do not track `rdi` register before `call` inst, but instead freeze
  it from further use, until `call` has been realised
* pass more error union tests
This commit is contained in:
Jakub Konka 2022-02-28 18:19:25 +01:00
parent 05431d7c4a
commit 12cdb36c5b
3 changed files with 21 additions and 33 deletions

View File

@ -3167,11 +3167,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
const stack_offset = @intCast(i32, try self.allocMem(inst, ret_abi_size, ret_abi_align));
try self.register_manager.getReg(.rdi, inst);
try self.register_manager.getReg(.rdi, null);
self.register_manager.freezeRegs(&.{.rdi});
try self.genSetReg(Type.usize, .rdi, .{ .ptr_stack_offset = stack_offset });
info.return_value.stack_offset = stack_offset;
}
defer if (info.return_value == .stack_offset) self.register_manager.unfreezeRegs(&.{.rdi});
for (args) |arg, arg_i| {
const mc_arg = info.args[arg_i];

View File

@ -553,31 +553,21 @@ pub fn generateSymbol(
const target = bin_file.options.target;
const abi_align = typed_value.ty.abiAlignment(target);
{
const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
const begin = code.items.len;
switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = error_ty,
.val = error_val,
}, code, debug_output)) {
.appended => {},
.externally_managed => |external_slice| {
code.appendSliceAssumeCapacity(external_slice);
},
.fail => |em| return Result{ .fail = em },
}
const unpadded_end = code.items.len - begin;
const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
const padding = try math.cast(usize, padded_end - unpadded_end);
if (padding > 0) {
try code.writer().writeByteNTimes(0, padding);
}
const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
const begin = code.items.len;
switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = error_ty,
.val = error_val,
}, code, debug_output)) {
.appended => {},
.externally_managed => |external_slice| {
code.appendSliceAssumeCapacity(external_slice);
},
.fail => |em| return Result{ .fail = em },
}
if (payload_ty.hasRuntimeBits()) {
const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);
const begin = code.items.len;
switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = payload_ty,
.val = payload_val,
@ -588,13 +578,14 @@ pub fn generateSymbol(
},
.fail => |em| return Result{ .fail = em },
}
const unpadded_end = code.items.len - begin;
const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
const padding = try math.cast(usize, padded_end - unpadded_end);
}
if (padding > 0) {
try code.writer().writeByteNTimes(0, padding);
}
const unpadded_end = code.items.len - begin;
const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
const padding = try math.cast(usize, padded_end - unpadded_end);
if (padding > 0) {
try code.writer().writeByteNTimes(0, padding);
}
return Result{ .appended = {} };

View File

@ -23,7 +23,6 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
}
test "error binary operator" {
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;
@ -58,7 +57,6 @@ pub fn baz() anyerror!i32 {
}
test "error wrapping" {
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;
@ -66,7 +64,6 @@ test "error wrapping" {
}
test "unwrap simple value from error" {
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;
@ -102,7 +99,6 @@ test "syntax: optional operator in front of error union operator" {
}
test "widen cast integer payload of error union function call" {
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;
@ -307,7 +303,6 @@ test "error: Infer error set from literals" {
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
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
_ = nullLiteral("n") catch |err| handleErrors(err);