Commit 12cdb36c5b

Jakub Konka <kubkon@jakubkonka.com>
2022-02-28 18:19:25
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
1 parent 05431d7
Changed files (3)
src
test
behavior
src/arch/x86_64/CodeGen.zig
@@ -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];
src/codegen.zig
@@ -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 = {} };
test/behavior/error.zig
@@ -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);