diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-04-20 03:43:02 +0100 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2025-04-20 18:11:53 +0100 |
| commit | 8c9c24e09b8a1e1ea92a16edd654a4b27e9ecf94 (patch) | |
| tree | ca9b15c23345a9ed82e0d8f25b28510583cf1b8e /src/Zcu.zig | |
| parent | 6561a98a61bb54c9d6c868f788da3eaa6f48d2c3 (diff) | |
| download | zig-8c9c24e09b8a1e1ea92a16edd654a4b27e9ecf94.tar.gz zig-8c9c24e09b8a1e1ea92a16edd654a4b27e9ecf94.zip | |
compiler: integrate `@compileLog` with incremental compilation
Compile log output is now separated based on the `AnalUnit` which
perfomred the `@compileLog` call, so that we can omit the output for
unreferenced ("dead") units. The units are also sorted when collecting
the `ErrorBundle`, so that compile logs are always printed in a
consistent order, like compile errors are. This is important not only
for incremental compilation, but also for parallel analysis.
Resolves: #23609
Diffstat (limited to 'src/Zcu.zig')
| -rw-r--r-- | src/Zcu.zig | 86 |
1 files changed, 77 insertions, 9 deletions
diff --git a/src/Zcu.zig b/src/Zcu.zig index 1486be6746..f9fbe0b652 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -130,18 +130,23 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty, failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empty, -/// Keep track of one `@compileLog` callsite per `AnalUnit`. -/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`. -compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct { +/// Keep track of `@compileLog`s per `AnalUnit`. +/// We track the source location of the first `@compileLog` call, and all logged lines as a linked list. +/// The list is singly linked, but we do track its tail for fast appends (optimizing many logs in one unit). +compile_logs: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct { base_node_inst: InternPool.TrackedInst.Index, node_offset: Ast.Node.Offset, + first_line: CompileLogLine.Index, + last_line: CompileLogLine.Index, pub fn src(self: @This()) LazySrcLoc { return .{ .base_node_inst = self.base_node_inst, .offset = LazySrcLoc.Offset.nodeOffset(self.node_offset), }; } -}) = .{}, +}) = .empty, +compile_log_lines: std.ArrayListUnmanaged(CompileLogLine) = .empty, +free_compile_log_lines: std.ArrayListUnmanaged(CompileLogLine.Index) = .empty, /// Using a map here for consistency with the other fields here. /// The ErrorMsg memory is owned by the `File`, using Module's general purpose allocator. failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .empty, @@ -196,8 +201,6 @@ stage1_flags: packed struct { reserved: u2 = 0, } = .{}, -compile_log_text: std.ArrayListUnmanaged(u8) = .empty, - test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty, global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty, @@ -547,6 +550,31 @@ pub const Export = struct { }; }; +pub const CompileLogLine = struct { + next: Index.Optional, + /// Does *not* include the trailing newline. + data: InternPool.NullTerminatedString, + pub const Index = enum(u32) { + _, + pub fn get(idx: Index, zcu: *Zcu) *CompileLogLine { + return &zcu.compile_log_lines.items[@intFromEnum(idx)]; + } + pub fn toOptional(idx: Index) Optional { + return @enumFromInt(@intFromEnum(idx)); + } + pub const Optional = enum(u32) { + none = std.math.maxInt(u32), + _, + pub fn unwrap(opt: Optional) ?Index { + return switch (opt) { + .none => null, + _ => @enumFromInt(@intFromEnum(opt)), + }; + } + }; + }; +}; + pub const Reference = struct { /// The `AnalUnit` whose semantic analysis was triggered by this reference. referenced: AnalUnit, @@ -2464,6 +2492,30 @@ pub const LazySrcLoc = struct { .lazy = lazy.offset, }; } + + /// Used to sort error messages, so that they're printed in a consistent order. + /// If an error is returned, that error makes sorting impossible. + pub fn lessThan(lhs_lazy: LazySrcLoc, rhs_lazy: LazySrcLoc, zcu: *Zcu) !bool { + const lhs_src = lhs_lazy.upgradeOrLost(zcu) orelse { + // LHS source location lost, so should never be referenced. Just sort it to the end. + return false; + }; + const rhs_src = rhs_lazy.upgradeOrLost(zcu) orelse { + // RHS source location lost, so should never be referenced. Just sort it to the end. + return true; + }; + if (lhs_src.file_scope != rhs_src.file_scope) { + return std.mem.order( + u8, + lhs_src.file_scope.sub_file_path, + rhs_src.file_scope.sub_file_path, + ).compare(.lt); + } + + const lhs_span = try lhs_src.span(zcu.gpa); + const rhs_span = try rhs_src.span(zcu.gpa); + return lhs_span.main < rhs_span.main; + } }; pub const SemaError = error{ OutOfMemory, AnalysisFail }; @@ -2506,8 +2558,6 @@ pub fn deinit(zcu: *Zcu) void { } zcu.embed_table.deinit(gpa); - zcu.compile_log_text.deinit(gpa); - zcu.local_zir_cache.handle.close(); zcu.global_zir_cache.handle.close(); @@ -2535,7 +2585,9 @@ pub fn deinit(zcu: *Zcu) void { } zcu.cimport_errors.deinit(gpa); - zcu.compile_log_sources.deinit(gpa); + zcu.compile_logs.deinit(gpa); + zcu.compile_log_lines.deinit(gpa); + zcu.free_compile_log_lines.deinit(gpa); zcu.all_exports.deinit(gpa); zcu.free_exports.deinit(gpa); @@ -3412,6 +3464,22 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { } } +/// Delete all compile logs performed by this `AnalUnit`. +/// Re-analysis of the `AnalUnit` will cause logs to be rediscovered. +pub fn deleteUnitCompileLogs(zcu: *Zcu, anal_unit: AnalUnit) void { + const kv = zcu.compile_logs.fetchSwapRemove(anal_unit) orelse return; + const gpa = zcu.gpa; + var opt_line_idx = kv.value.first_line.toOptional(); + while (opt_line_idx.unwrap()) |line_idx| { + zcu.free_compile_log_lines.append(gpa, line_idx) catch { + // This space will be reused eventually, so we need not propagate this error. + // Just leak it for now, and let GC reclaim it later on. + return; + }; + opt_line_idx = line_idx.get(zcu).next; + } +} + pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit, ref_src: LazySrcLoc) Allocator.Error!void { const gpa = zcu.gpa; |
