authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-08-18 15:59:24+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-08-18 18:10:59+01:00
logb745fee1f8dddd92c7d112cd7440e6b540458051
tree160dd2df9b2b4b94bc978aaae5689a772e3ff6f7
parent93a5bd262defe4c09a617a4ecc68340e20a2b20b
signaturelock-open Commit is signed but in an unrecognized format.

frontend: handle incremental updates of replaced runtime functions


2 files changed, 19 insertions(+), 29 deletions(-)

src/InternPool.zig+1-5
......@@ -7108,7 +7108,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity(
71087108 const index = entry.acquire();
71097109 if (index == .none) break;
71107110 if (entry.hash != hash) continue;
7111 if (ip.isRemoved(index)) continue;
7111 if (index.unwrap(ip).getTag(ip) == .removed) continue;
71127112 if (ip.indexToKey(index).eql(key, ip)) return .{ .existing = index };
71137113 }
71147114 shard.mutate.map.mutex.lock();
......@@ -12311,7 +12311,3 @@ pub fn getErrorValue(
1231112311pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt {
1231212312 return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null);
1231312313}
12314
12315pub fn isRemoved(ip: *const InternPool, ty: Index) bool {
12316 return ty.unwrap(ip).getTag(ip) == .removed;
12317}
src/Zcu/PerThread.zig+18-24
......@@ -734,31 +734,25 @@ fn ensureFuncBodyAnalyzedInner(
734734 const func = zcu.funcInfo(func_index);
735735 const anal_unit = AnalUnit.wrap(.{ .func = func_index });
736736
737 // Here's an interesting question: is this function actually valid?
738 // Maybe the signature changed, so we'll end up creating a whole different `func`
739 // in the InternPool, and this one is a waste of time to analyze. Worse, we'd be
740 // analyzing new ZIR with old data, and get bogus errors. They would be unused,
741 // but they would still hang around internally! So, let's detect this case.
742 // For function decls, we must ensure the declaration's `Cau` is up-to-date, and
743 // check if `func_index` was removed by that update.
744 // For function instances, we do that process on the generic owner.
745
746 try pt.ensureCauAnalyzed(cau: {
747 const func_nav = if (func.generic_owner == .none)
748 func.owner_nav
749 else
750 zcu.funcInfo(func.generic_owner).owner_nav;
751
752 break :cau ip.getNav(func_nav).analysis_owner.unwrap().?;
753 });
754
755 if (ip.isRemoved(func_index) or (func.generic_owner != .none and ip.isRemoved(func.generic_owner))) {
756 if (func_outdated) {
757 try zcu.markDependeeOutdated(.marked_po, .{ .interned = func_index }); // IES
737 // Make sure that this function is still owned by the same `Nav`. Otherwise, analyzing
738 // it would be a waste of time in the best case, and could cause codegen to give bogus
739 // results in the worst case.
740
741 if (func.generic_owner == .none) {
742 try pt.ensureCauAnalyzed(ip.getNav(func.owner_nav).analysis_owner.unwrap().?);
743 if (ip.getNav(func.owner_nav).status.resolved.val != func_index) {
744 // This function is no longer referenced! There's no point in re-analyzing it.
745 // Just mark a transitive failure and move on.
746 return error.AnalysisFail;
747 }
748 } else {
749 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
750 try pt.ensureCauAnalyzed(ip.getNav(go_nav).analysis_owner.unwrap().?);
751 if (ip.getNav(go_nav).status.resolved.val != func.generic_owner) {
752 // The generic owner is no longer referenced, so this function is also unreferenced.
753 // There's no point in re-analyzing it. Just mark a transitive failure and move on.
754 return error.AnalysisFail;
758755 }
759 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .func = func_index }));
760 ip.remove(pt.tid, func_index);
761 @panic("TODO: remove orphaned function from binary");
762756 }
763757
764758 // We'll want to remember what the IES used to be before the update for