authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-01 23:45:11+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-01 23:54:31+00:00
log6a87e42c2ea070a6273317bbb005029d95ceae49
tree2b484cdc2b5f8d25a81e67f6bb8df8f0d2b0600a
parent36d0afbf2871ddaa6717807ae0050cb06cb2cd0d
signaturelock-open Commit is signed but in an unrecognized format.

AstGen: fix latent bug causing incorrect elision of `dbg_stmt` instructions

Thanks to jacobly0 for figuring this out. The chain of events causing the failure this triggered is as follows. * As of a recent commit, certain bodies no longer emit a redundant `block`, meaning there are more likely to be "interesting" instructions (i.e. not blocks) at the end of parent GenZir scopes. * When emitting the first `dbg_stmt` in such a body, the elision logic incorrectly looks at a tag from an instruction in an enclosing scope. * The tag of this instruction may be `undefined`, meaning that in unsafe builds it may be incorrectly identified as a `dbg_stmt` instruction. * This instruction from another body is clobbered rather than emitting an actual `dbg_stmt` instruction. Note that this does not produce invalid ZIR, since the creator of the undefined instruction replaces the previously-undefined payload later.

1 files changed, 2 insertions(+), 2 deletions(-)

lib/std/zig/AstGen.zig+2-2
...@@ -13550,7 +13550,7 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {...@@ -13550,7 +13550,7 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
1355013550
13551fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {13551fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {
13552 if (gz.is_comptime) return;13552 if (gz.is_comptime) return;
13553 if (gz.instructions.items.len > 0) {13553 if (gz.instructions.items.len > gz.instructions_top) {
13554 const astgen = gz.astgen;13554 const astgen = gz.astgen;
13555 const last = gz.instructions.items[gz.instructions.items.len - 1];13555 const last = gz.instructions.items[gz.instructions.items.len - 1];
13556 if (astgen.instructions.items(.tag)[@intFromEnum(last)] == .dbg_stmt) {13556 if (astgen.instructions.items(.tag)[@intFromEnum(last)] == .dbg_stmt) {
...@@ -13576,7 +13576,7 @@ fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {...@@ -13576,7 +13576,7 @@ fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {
13576/// instructions; fix up Sema so we don't need it!13576/// instructions; fix up Sema so we don't need it!
13577fn emitDbgStmtForceCurrentIndex(gz: *GenZir, lc: LineColumn) !void {13577fn emitDbgStmtForceCurrentIndex(gz: *GenZir, lc: LineColumn) !void {
13578 const astgen = gz.astgen;13578 const astgen = gz.astgen;
13579 if (gz.instructions.items.len > 0 and13579 if (gz.instructions.items.len > gz.instructions_top and
13580 @intFromEnum(gz.instructions.items[gz.instructions.items.len - 1]) == astgen.instructions.len - 1)13580 @intFromEnum(gz.instructions.items[gz.instructions.items.len - 1]) == astgen.instructions.len - 1)
13581 {13581 {
13582 const last = astgen.instructions.len - 1;13582 const last = astgen.instructions.len - 1;