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.
This commit is contained in:
mlugg 2024-03-01 23:45:11 +00:00
parent 36d0afbf28
commit 6a87e42c2e
No known key found for this signature in database
GPG Key ID: 58978E823BDE3EF9

View File

@ -13550,7 +13550,7 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {
if (gz.is_comptime) return;
if (gz.instructions.items.len > 0) {
if (gz.instructions.items.len > gz.instructions_top) {
const astgen = gz.astgen;
const last = gz.instructions.items[gz.instructions.items.len - 1];
if (astgen.instructions.items(.tag)[@intFromEnum(last)] == .dbg_stmt) {
@ -13576,7 +13576,7 @@ fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {
/// instructions; fix up Sema so we don't need it!
fn emitDbgStmtForceCurrentIndex(gz: *GenZir, lc: LineColumn) !void {
const astgen = gz.astgen;
if (gz.instructions.items.len > 0 and
if (gz.instructions.items.len > gz.instructions_top and
@intFromEnum(gz.instructions.items[gz.instructions.items.len - 1]) == astgen.instructions.len - 1)
{
const last = astgen.instructions.len - 1;