From da878dc0776b56c1e2c251857a40415a35e9535a Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 5 May 2023 14:56:10 -0400 Subject: [PATCH 1/2] AstGen: fix branch on undefined `isAlwaysVoid` was being called with the undefined tag added by `addOne`, causing non-deterministic behavior failures with release builds of the compiler. Prevents the following random failure: test/behavior/defer.zig:120:40: error: expected type 'error{One}', found 'void' --- src/AstGen.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/AstGen.zig b/src/AstGen.zig index 2568b89980..000151a2cc 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -2905,7 +2905,10 @@ fn deferStmt( const sub_scope = if (!have_err_code) &defer_gen.base else blk: { try gz.addDbgBlockBegin(); const ident_name = try gz.astgen.identAsString(payload_token); - remapped_err_code = @intCast(u32, try gz.astgen.instructions.addOne(gz.astgen.gpa)); + remapped_err_code = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); + // Use a placeholder tag of .as to allow querying things that depend on the tag, + // but undefined data to prevent querying of data.bin. + try gz.astgen.instructions.append(gz.astgen.gpa, .{ .tag = .as, .data = undefined }); const remapped_err_code_ref = Zir.indexToRef(remapped_err_code); local_val_scope = .{ .parent = &defer_gen.base, From df4849c4f5aafc7eb80fd7b2299b49162fa2aa79 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 5 May 2023 16:07:27 -0400 Subject: [PATCH 2/2] AstGen: cleanup previous fix Allocating an extended tag is much cleaner and easier to reason about than reusing an existing tag. The previous `.data = undefined` was a clear indication that we don't have any data to store, and so might as well store an extended tag in that space almost for free. --- src/AstGen.zig | 11 ++++++++--- src/Sema.zig | 1 + src/Zir.zig | 7 +++++-- src/print_zir.zig | 1 + 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/AstGen.zig b/src/AstGen.zig index 000151a2cc..749e3d28c4 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -2906,9 +2906,14 @@ fn deferStmt( try gz.addDbgBlockBegin(); const ident_name = try gz.astgen.identAsString(payload_token); remapped_err_code = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); - // Use a placeholder tag of .as to allow querying things that depend on the tag, - // but undefined data to prevent querying of data.bin. - try gz.astgen.instructions.append(gz.astgen.gpa, .{ .tag = .as, .data = undefined }); + try gz.astgen.instructions.append(gz.astgen.gpa, .{ + .tag = .extended, + .data = .{ .extended = .{ + .opcode = .errdefer_err_code, + .small = undefined, + .operand = undefined, + } }, + }); const remapped_err_code_ref = Zir.indexToRef(remapped_err_code); local_val_scope = .{ .parent = &defer_gen.base, diff --git a/src/Sema.zig b/src/Sema.zig index 13f4d684a1..b2387dfe12 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1198,6 +1198,7 @@ fn analyzeBodyInner( i += 1; continue; }, + .errdefer_err_code => unreachable, // never appears in a body }; }, diff --git a/src/Zir.zig b/src/Zir.zig index 51c90c61cb..7f9681e533 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -1979,7 +1979,7 @@ pub const Inst = struct { /// `operand` is `src_node: i32`. breakpoint, /// Implements the `@select` builtin. - /// operand` is payload index to `Select`. + /// `operand` is payload index to `Select`. select, /// Implement builtin `@errToInt`. /// `operand` is payload index to `UnNode`. @@ -1999,7 +1999,7 @@ pub const Inst = struct { /// `operand` is payload index to `Cmpxchg`. cmpxchg, /// Implement the builtin `@addrSpaceCast` - /// `Operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. + /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. addrspace_cast, /// Implement builtin `@cVaArg`. /// `operand` is payload index to `BinNode`. @@ -2031,6 +2031,9 @@ pub const Inst = struct { /// Implements the `@inComptime` builtin. /// `operand` is `src_node: i32`. in_comptime, + /// Used as a placeholder for the capture of an `errdefer`. + /// This is replaced by Sema with the captured value. + errdefer_err_code, pub const InstData = struct { opcode: Extended, diff --git a/src/print_zir.zig b/src/print_zir.zig index 4e4f13641c..f228adc7ea 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -467,6 +467,7 @@ const Writer = struct { .breakpoint, .c_va_start, .in_comptime, + .errdefer_err_code, => try self.writeExtNode(stream, extended), .builtin_src => {