Commit c6842b58d4
Changed files (3)
src/Compilation.zig
@@ -3076,15 +3076,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
});
}
- var all_references: ?std.AutoHashMapUnmanaged(InternPool.AnalUnit, ?Zcu.ResolvedReference) = null;
- defer if (all_references) |*a| a.deinit(gpa);
-
if (comp.zcu) |zcu| {
const ip = &zcu.intern_pool;
for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {
if (error_msg) |msg| {
- try addModuleErrorMsg(zcu, &bundle, msg.*, &all_references);
+ try addModuleErrorMsg(zcu, &bundle, msg.*);
} else {
// Must be ZIR errors. Note that this may include AST errors.
// addZirErrorMessages asserts that the tree is loaded.
@@ -3093,7 +3090,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
}
}
for (zcu.failed_embed_files.values()) |error_msg| {
- try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
+ try addModuleErrorMsg(zcu, &bundle, error_msg.*);
}
{
const SortOrder = struct {
@@ -3136,10 +3133,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
}
for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| {
if (comp.incremental) {
- if (all_references == null) {
- all_references = try zcu.resolveReferences();
- }
- if (!all_references.?.contains(anal_unit)) continue;
+ const refs = try zcu.resolveReferences();
+ if (!refs.contains(anal_unit)) continue;
}
const file_index = switch (anal_unit.unwrap()) {
@@ -3151,7 +3146,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
// We'll try again once parsing succeeds.
if (!zcu.fileByIndex(file_index).okToReportErrors()) continue;
- try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
+ try addModuleErrorMsg(zcu, &bundle, error_msg.*);
if (zcu.cimport_errors.get(anal_unit)) |errors| {
for (errors.getMessages()) |err_msg_index| {
const err_msg = errors.getErrorMessage(err_msg_index);
@@ -3175,10 +3170,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
}
for (zcu.failed_codegen.keys(), zcu.failed_codegen.values()) |nav, error_msg| {
if (!zcu.navFileScope(nav).okToReportErrors()) continue;
- try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
+ try addModuleErrorMsg(zcu, &bundle, error_msg.*);
}
for (zcu.failed_exports.values()) |value| {
- try addModuleErrorMsg(zcu, &bundle, value.*, &all_references);
+ try addModuleErrorMsg(zcu, &bundle, value.*);
}
const actual_error_count = zcu.intern_pool.global_error_set.getNamesFromMainThread().len;
@@ -3252,17 +3247,15 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
};
}
- try addModuleErrorMsg(zcu, &bundle, err_msg, &all_references);
+ try addModuleErrorMsg(zcu, &bundle, err_msg);
}
}
if (comp.zcu) |zcu| {
if (comp.incremental and bundle.root_list.items.len == 0) {
const should_have_error = for (zcu.transitive_failed_analysis.keys()) |failed_unit| {
- if (all_references == null) {
- all_references = try zcu.resolveReferences();
- }
- if (all_references.?.contains(failed_unit)) break true;
+ const refs = try zcu.resolveReferences();
+ if (refs.contains(failed_unit)) break true;
} else false;
if (should_have_error) {
@panic("referenced transitive analysis errors, but none actually emitted");
@@ -3331,14 +3324,13 @@ pub const ErrorNoteHashContext = struct {
};
pub fn addModuleErrorMsg(
- mod: *Zcu,
+ zcu: *Zcu,
eb: *ErrorBundle.Wip,
module_err_msg: Zcu.ErrorMsg,
- all_references: *?std.AutoHashMapUnmanaged(InternPool.AnalUnit, ?Zcu.ResolvedReference),
) !void {
const gpa = eb.gpa;
- const ip = &mod.intern_pool;
- const err_src_loc = module_err_msg.src_loc.upgrade(mod);
+ const ip = &zcu.intern_pool;
+ const err_src_loc = module_err_msg.src_loc.upgrade(zcu);
const err_source = err_src_loc.file_scope.getSource(gpa) catch |err| {
const file_path = try err_src_loc.file_scope.fullPath(gpa);
defer gpa.free(file_path);
@@ -3358,22 +3350,20 @@ pub fn addModuleErrorMsg(
defer ref_traces.deinit(gpa);
if (module_err_msg.reference_trace_root.unwrap()) |rt_root| {
- if (all_references.* == null) {
- all_references.* = try mod.resolveReferences();
- }
+ const all_references = try zcu.resolveReferences();
var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty;
defer seen.deinit(gpa);
- const max_references = mod.comp.reference_trace orelse Sema.default_reference_trace_len;
+ const max_references = zcu.comp.reference_trace orelse Sema.default_reference_trace_len;
var referenced_by = rt_root;
- while (all_references.*.?.get(referenced_by)) |maybe_ref| {
+ while (all_references.get(referenced_by)) |maybe_ref| {
const ref = maybe_ref orelse break;
const gop = try seen.getOrPut(gpa, ref.referencer);
if (gop.found_existing) break;
if (ref_traces.items.len < max_references) {
- const src = ref.src.upgrade(mod);
+ const src = ref.src.upgrade(zcu);
const source = try src.file_scope.getSource(gpa);
const span = try src.span(gpa);
const loc = std.zig.findLineColumn(source.bytes, span.main);
@@ -3385,7 +3375,7 @@ pub fn addModuleErrorMsg(
.type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
.none => "comptime",
},
- .func => |f| ip.getNav(mod.funcInfo(f).owner_nav).name.toSlice(ip),
+ .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
};
try ref_traces.append(gpa, .{
.decl_name = try eb.addString(name),
@@ -3435,7 +3425,7 @@ pub fn addModuleErrorMsg(
defer notes.deinit(gpa);
for (module_err_msg.notes) |module_note| {
- const note_src_loc = module_note.src_loc.upgrade(mod);
+ const note_src_loc = module_note.src_loc.upgrade(zcu);
const source = try note_src_loc.file_scope.getSource(gpa);
const span = try note_src_loc.span(gpa);
const loc = std.zig.findLineColumn(source.bytes, span.main);
@@ -3488,13 +3478,13 @@ pub fn performAllTheWork(
comp: *Compilation,
main_progress_node: std.Progress.Node,
) JobError!void {
- defer if (comp.zcu) |mod| {
- mod.sema_prog_node.end();
- mod.sema_prog_node = std.Progress.Node.none;
- mod.codegen_prog_node.end();
- mod.codegen_prog_node = std.Progress.Node.none;
+ defer if (comp.zcu) |zcu| {
+ zcu.sema_prog_node.end();
+ zcu.sema_prog_node = std.Progress.Node.none;
+ zcu.codegen_prog_node.end();
+ zcu.codegen_prog_node = std.Progress.Node.none;
- mod.generation += 1;
+ zcu.generation += 1;
};
try comp.performAllTheWorkInner(main_progress_node);
if (!InternPool.single_threaded) if (comp.codegen_work.job_error) |job_error| return job_error;
src/Sema.zig
@@ -2559,10 +2559,9 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
const zcu = sema.pt.zcu;
if (build_options.enable_debug_extensions and zcu.comp.debug_compile_errors) {
- var all_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?Zcu.ResolvedReference) = null;
var wip_errors: std.zig.ErrorBundle.Wip = undefined;
wip_errors.init(gpa) catch @panic("out of memory");
- Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, &all_references) catch @panic("out of memory");
+ Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*) catch @panic("out of memory");
std.debug.print("compile error during Sema:\n", .{});
var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");
error_bundle.renderToStdErr(.{ .ttyconf = .no_color });
src/Zcu.zig
@@ -173,6 +173,10 @@ retryable_failures: std.ArrayListUnmanaged(AnalUnit) = .empty,
/// These are the modules which we initially queue for analysis in `Compilation.update`.
/// `resolveReferences` will use these as the root of its reachability traversal.
analysis_roots: std.BoundedArray(*Package.Module, 3) = .{},
+/// This is the cached result of `Zcu.resolveReferences`. It is computed on-demand, and
+/// reset to `null` when any semantic analysis occurs (since this invalidates the data).
+/// Allocated into `gpa`.
+resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = null,
stage1_flags: packed struct {
have_winmain: bool = false,
@@ -2192,6 +2196,8 @@ pub fn deinit(zcu: *Zcu) void {
zcu.all_type_references.deinit(gpa);
zcu.free_type_references.deinit(gpa);
+ if (zcu.resolved_references) |*r| r.deinit(gpa);
+
zcu.intern_pool.deinit(gpa);
}
@@ -2760,6 +2766,8 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {
pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void {
const gpa = zcu.gpa;
+ zcu.clearCachedResolvedReferences();
+
unit_refs: {
const kv = zcu.reference_table.fetchSwapRemove(anal_unit) orelse break :unit_refs;
var idx = kv.value;
@@ -2792,6 +2800,8 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void {
pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit, ref_src: LazySrcLoc) Allocator.Error!void {
const gpa = zcu.gpa;
+ zcu.clearCachedResolvedReferences();
+
try zcu.reference_table.ensureUnusedCapacity(gpa, 1);
const ref_idx = zcu.free_references.popOrNull() orelse idx: {
@@ -2815,6 +2825,8 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit
pub fn addTypeReference(zcu: *Zcu, src_unit: AnalUnit, referenced_type: InternPool.Index, ref_src: LazySrcLoc) Allocator.Error!void {
const gpa = zcu.gpa;
+ zcu.clearCachedResolvedReferences();
+
try zcu.type_reference_table.ensureUnusedCapacity(gpa, 1);
const ref_idx = zcu.free_type_references.popOrNull() orelse idx: {
@@ -2835,6 +2847,11 @@ pub fn addTypeReference(zcu: *Zcu, src_unit: AnalUnit, referenced_type: InternPo
gop.value_ptr.* = @intCast(ref_idx);
}
+fn clearCachedResolvedReferences(zcu: *Zcu) void {
+ if (zcu.resolved_references) |*r| r.deinit(zcu.gpa);
+ zcu.resolved_references = null;
+}
+
pub fn errorSetBits(zcu: *const Zcu) u16 {
if (zcu.error_limit == 0) return 0;
return @as(u16, std.math.log2_int(ErrorInt, zcu.error_limit)) + 1;
@@ -3138,7 +3155,15 @@ pub const ResolvedReference = struct {
/// Returns a mapping from an `AnalUnit` to where it is referenced.
/// If the value is `null`, the `AnalUnit` is a root of analysis.
/// If an `AnalUnit` is not in the returned map, it is unreferenced.
-pub fn resolveReferences(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) {
+/// The returned hashmap is owned by the `Zcu`, so should not be freed by the caller.
+/// This hashmap is cached, so repeated calls to this function are cheap.
+pub fn resolveReferences(zcu: *Zcu) !*const std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) {
+ if (zcu.resolved_references == null) {
+ zcu.resolved_references = try zcu.resolveReferencesInner();
+ }
+ return &zcu.resolved_references.?;
+}
+fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) {
const gpa = zcu.gpa;
const comp = zcu.comp;
const ip = &zcu.intern_pool;