authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 18:19:25+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 23:20:05+01:00
log12cdb36c5ba1fd9dfa5985d36a2f5955528c2de7
treeb28b98a8c43ad1a81eeac26e2a07d7acbb38ebf9
parent05431d7c4a8cb20a3a70553ef0d0f8ed00a05402

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

3 files changed, 21 insertions(+), 33 deletions(-)

src/arch/x86_64/CodeGen.zig+3-1
...@@ -3167,11 +3167,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -3167,11 +3167,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
3167 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));3167 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
3168 const stack_offset = @intCast(i32, try self.allocMem(inst, ret_abi_size, ret_abi_align));3168 const stack_offset = @intCast(i32, try self.allocMem(inst, ret_abi_size, ret_abi_align));
31693169
3170 try self.register_manager.getReg(.rdi, inst);3170 try self.register_manager.getReg(.rdi, null);
3171 self.register_manager.freezeRegs(&.{.rdi});
3171 try self.genSetReg(Type.usize, .rdi, .{ .ptr_stack_offset = stack_offset });3172 try self.genSetReg(Type.usize, .rdi, .{ .ptr_stack_offset = stack_offset });
31723173
3173 info.return_value.stack_offset = stack_offset;3174 info.return_value.stack_offset = stack_offset;
3174 }3175 }
3176 defer if (info.return_value == .stack_offset) self.register_manager.unfreezeRegs(&.{.rdi});
31753177
3176 for (args) |arg, arg_i| {3178 for (args) |arg, arg_i| {
3177 const mc_arg = info.args[arg_i];3179 const mc_arg = info.args[arg_i];
src/codegen.zig+18-27
...@@ -553,31 +553,21 @@ pub fn generateSymbol(...@@ -553,31 +553,21 @@ pub fn generateSymbol(
553 const target = bin_file.options.target;553 const target = bin_file.options.target;
554 const abi_align = typed_value.ty.abiAlignment(target);554 const abi_align = typed_value.ty.abiAlignment(target);
555555
556 {556 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
557 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);557 const begin = code.items.len;
558 const begin = code.items.len;558 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
559 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{559 .ty = error_ty,
560 .ty = error_ty,560 .val = error_val,
561 .val = error_val,561 }, code, debug_output)) {
562 }, code, debug_output)) {562 .appended => {},
563 .appended => {},563 .externally_managed => |external_slice| {
564 .externally_managed => |external_slice| {564 code.appendSliceAssumeCapacity(external_slice);
565 code.appendSliceAssumeCapacity(external_slice);565 },
566 },566 .fail => |em| return Result{ .fail = em },
567 .fail => |em| return Result{ .fail = em },
568 }
569 const unpadded_end = code.items.len - begin;
570 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
571 const padding = try math.cast(usize, padded_end - unpadded_end);
572
573 if (padding > 0) {
574 try code.writer().writeByteNTimes(0, padding);
575 }
576 }567 }
577568
578 if (payload_ty.hasRuntimeBits()) {569 if (payload_ty.hasRuntimeBits()) {
579 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);570 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);
580 const begin = code.items.len;
581 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{571 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
582 .ty = payload_ty,572 .ty = payload_ty,
583 .val = payload_val,573 .val = payload_val,
...@@ -588,13 +578,14 @@ pub fn generateSymbol(...@@ -588,13 +578,14 @@ pub fn generateSymbol(
588 },578 },
589 .fail => |em| return Result{ .fail = em },579 .fail => |em| return Result{ .fail = em },
590 }580 }
591 const unpadded_end = code.items.len - begin;581 }
592 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
593 const padding = try math.cast(usize, padded_end - unpadded_end);
594582
595 if (padding > 0) {583 const unpadded_end = code.items.len - begin;
596 try code.writer().writeByteNTimes(0, padding);584 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
597 }585 const padding = try math.cast(usize, padded_end - unpadded_end);
586
587 if (padding > 0) {
588 try code.writer().writeByteNTimes(0, padding);
598 }589 }
599590
600 return Result{ .appended = {} };591 return Result{ .appended = {} };
test/behavior/error.zig-5
...@@ -23,7 +23,6 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {...@@ -23,7 +23,6 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
23}23}
2424
25test "error binary operator" {25test "error binary operator" {
26 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
27 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;26 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2928
...@@ -58,7 +57,6 @@ pub fn baz() anyerror!i32 {...@@ -58,7 +57,6 @@ pub fn baz() anyerror!i32 {
58}57}
5958
60test "error wrapping" {59test "error wrapping" {
61 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
62 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
63 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;61 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
6462
...@@ -66,7 +64,6 @@ test "error wrapping" {...@@ -66,7 +64,6 @@ test "error wrapping" {
66}64}
6765
68test "unwrap simple value from error" {66test "unwrap simple value from error" {
69 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
70 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;67 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;68 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7269
...@@ -102,7 +99,6 @@ test "syntax: optional operator in front of error union operator" {...@@ -102,7 +99,6 @@ test "syntax: optional operator in front of error union operator" {
102}99}
103100
104test "widen cast integer payload of error union function call" {101test "widen cast integer payload of error union function call" {
105 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
106 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
108104
...@@ -307,7 +303,6 @@ test "error: Infer error set from literals" {...@@ -307,7 +303,6 @@ test "error: Infer error set from literals" {
307 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
308 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO304 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
309 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO305 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
310 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
311 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO306 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
312307
313 _ = nullLiteral("n") catch |err| handleErrors(err);308 _ = nullLiteral("n") catch |err| handleErrors(err);