authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-12 22:02:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-12 22:02:44-07:00
log344dc0cc0ffcd32ffb07c43ca7123b8564f2a506
treebbe151e35981f21e26030494422e1958a43afac7
parent417b5b1daae800ef423f65154c40a513a73485e8

stage2: fix handling of "prev successful ZIR"

Before this change, the attempt to save the most recent successful ZIR code only worked in some cases; this reworks the code to be more robust, thereby fixing a crash when running the stage2 "enums" CBE test cases.

1 files changed, 52 insertions(+), 50 deletions(-)

src/Module.zig+52-50
......@@ -2428,13 +2428,21 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
24282428
24292429 mod.lockAndClearFileCompileError(file);
24302430
2431 // Move previous ZIR to a local variable so we can compare it with the new one.
2432 var prev_zir = file.zir;
2433 var prev_zir_loaded = file.zir_loaded;
2434 file.zir_loaded = false;
2435 file.zir = undefined;
2436 defer if (prev_zir_loaded) prev_zir.deinit(gpa);
2437
2431 // If the previous ZIR does not have compile errors, keep it around
2432 // in case parsing or new ZIR fails. In case of successful ZIR update
2433 // at the end of this function we will free it.
2434 // We keep the previous ZIR loaded so that we can use it
2435 // for the update next time it does not have any compile errors. This avoids
2436 // needlessly tossing out semantic analysis work when an error is
2437 // temporarily introduced.
2438 if (file.zir_loaded and !file.zir.hasCompileErrors()) {
2439 assert(file.prev_zir == null);
2440 const prev_zir_ptr = try gpa.create(Zir);
2441 file.prev_zir = prev_zir_ptr;
2442 prev_zir_ptr.* = file.zir;
2443 file.zir = undefined;
2444 file.zir_loaded = false;
2445 }
24382446 file.unload(gpa);
24392447
24402448 if (stat.size > std.math.maxInt(u32))
......@@ -2546,7 +2554,17 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
25462554 });
25472555 };
25482556
2549 if (prev_zir_loaded) {
2557 if (file.zir.hasCompileErrors()) {
2558 {
2559 const lock = comp.mutex.acquire();
2560 defer lock.release();
2561 try mod.failed_files.putNoClobber(gpa, file, null);
2562 }
2563 file.status = .astgen_failure;
2564 return error.AnalysisFail;
2565 }
2566
2567 if (file.prev_zir) |prev_zir| {
25502568 // Iterate over all Namespace objects contained within this File, looking at the
25512569 // previous and new ZIR together and update the references to point
25522570 // to the new one. For example, Decl name, Decl zir_decl_index, and Namespace
......@@ -2555,47 +2573,19 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
25552573 // We do not need to hold any locks at this time because all the Decl and Namespace
25562574 // objects being touched are specific to this File, and the only other concurrent
25572575 // tasks are touching other File objects.
2558 if (file.zir.hasCompileErrors()) {
2559 // In this case, we keep the previous ZIR loaded so that we can use it
2560 // for the update next time it does not have any compile errors. This avoids
2561 // needlessly tossing out semantic analysis work when a ZIR error is
2562 // temporarily introduced.
2563 if (!prev_zir.hasCompileErrors()) {
2564 assert(file.prev_zir == null);
2565 const prev_zir_ptr = try gpa.create(Zir);
2566 file.prev_zir = prev_zir_ptr;
2567 prev_zir_ptr.* = prev_zir;
2568 prev_zir_loaded = false;
2569 }
2570 } else if (prev_zir.hasCompileErrors()) {
2571 if (file.prev_zir) |file_prev_zir| {
2572 prev_zir.deinit(gpa);
2573 prev_zir = file_prev_zir.*;
2574 gpa.destroy(file_prev_zir);
2575 file.prev_zir = null;
2576 try updateZirRefs(gpa, file, prev_zir);
2577 } else if (file.root_decl) |root_decl| {
2578 // First time the File has succeeded ZIR. We must mark it outdated since
2579 // we have already tried to semantically analyze it.
2580 try file.outdated_decls.resize(gpa, 1);
2581 file.outdated_decls.items[0] = root_decl;
2582 }
2583 } else {
2584 try updateZirRefs(gpa, file, prev_zir);
2585 }
2576 try updateZirRefs(gpa, file, prev_zir.*);
25862577 // At this point, `file.outdated_decls` and `file.deleted_decls` are populated,
25872578 // and semantic analysis will deal with them properly.
2588 }
2589
2590 // TODO don't report compile errors until Sema @importFile
2591 if (file.zir.hasCompileErrors()) {
2592 {
2593 const lock = comp.mutex.acquire();
2594 defer lock.release();
2595 try mod.failed_files.putNoClobber(gpa, file, null);
2596 }
2597 file.status = .astgen_failure;
2598 return error.AnalysisFail;
2579 // No need to keep previous ZIR.
2580 prev_zir.deinit(gpa);
2581 gpa.destroy(prev_zir);
2582 file.prev_zir = null;
2583 } else if (file.root_decl) |root_decl| {
2584 // This is an update, but it is the first time the File has succeeded
2585 // ZIR. We must mark it outdated since we have already tried to
2586 // semantically analyze it.
2587 try file.outdated_decls.resize(gpa, 1);
2588 file.outdated_decls.items[0] = root_decl;
25992589 }
26002590}
26012591
......@@ -2640,14 +2630,26 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void {
26402630 // Anonymous decls should not be marked outdated. They will be re-generated
26412631 // if their owner decl is marked outdated.
26422632 if (decl.zir_decl_index != 0) {
2643 const old_hash = decl.contentsHashZir(old_zir);
2644 decl.zir_decl_index = extra_map.get(decl.zir_decl_index) orelse {
2633 const old_zir_decl_index = decl.zir_decl_index;
2634 const new_zir_decl_index = extra_map.get(old_zir_decl_index) orelse {
2635 log.debug("updateZirRefs {s}: delete {*} ({s})", .{
2636 file.sub_file_path, decl, decl.name,
2637 });
26452638 try file.deleted_decls.append(gpa, decl);
26462639 continue;
26472640 };
2641 const old_hash = decl.contentsHashZir(old_zir);
2642 decl.zir_decl_index = new_zir_decl_index;
26482643 const new_hash = decl.contentsHashZir(new_zir);
26492644 if (!std.zig.srcHashEql(old_hash, new_hash)) {
2645 log.debug("updateZirRefs {s}: outdated {*} ({s}) {d} => {d}", .{
2646 file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index,
2647 });
26502648 try file.outdated_decls.append(gpa, decl);
2649 } else {
2650 log.debug("updateZirRefs {s}: unchanged {*} ({s}) {d} => {d}", .{
2651 file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index,
2652 });
26512653 }
26522654 }
26532655
......@@ -3376,7 +3378,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
33763378 }
33773379 gpa.free(decl_name);
33783380 const decl = gop.entry.value;
3379 log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl_name, namespace });
3381 log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl.name, namespace });
33803382 // Update the AST node of the decl; even if its contents are unchanged, it may
33813383 // have been re-ordered.
33823384 const prev_src_node = decl.src_node;