From 91d8b7b8dc04aecea1a4fa7c6c6bc0696ebdada4 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 31 Aug 2026 05:42:43 -0400 Subject: [PATCH] Zcu: notify the linker once source files have been scanned --- src/Zcu/PerThread.zig | 2 ++ src/link.zig | 48 +++++++++++++++++++++++++++++++------------ src/link/Elf2.zig | 4 ++++ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 0e4962985a566aa611a326ea1aeb2b61e9928ae4..9a34d3ebdbf7be956d066caf98a71933afabf137 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -258,6 +258,8 @@ pub fn update( return; } + try comp.link_queue.enqueueZcu(comp, pt.tid, .files_ready); + if (comp.config.incremental) { const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); defer update_zir_refs_node.end(); diff --git a/src/link.zig b/src/link.zig index d5c0759bfc353ca7982f3aa94546b7ae431975b1..d084cd7e41f53cdf4854b556b545c985ecf812bd 100644 --- a/src/link.zig +++ b/src/link.zig @@ -794,6 +794,28 @@ pub const File = struct { } } + /// When there is a ZCU, this is called exactly once per update, to indicate that all per-file + /// state (e.g. `Zcu.alive_files`) has been populated by the frontend, so can now be safely + /// accessed by the linker. + /// + /// This call occurs before any call to any of these functions: + /// * `updateNav` + /// * `updateFunc` + /// * `updateContainerType` + /// * `updateLineNumber` + /// + /// Asserts that the ZCU is not using the LLVM backend. + fn zcuFilesReady(base: *File) Error!void { + assert(base.comp.zcu.?.llvm_object == null); + switch (base.tag) { + else => {}, + inline .elf2 => |tag| { + dev.check(tag.devFeature()); + return @as(*tag.Type(), @fieldParentPtr("base", base)).zcuFilesReady(); + }, + } + } + /// Asserts that the ZCU is not using the LLVM backend. fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void { assert(base.comp.zcu.?.llvm_object == null); @@ -823,19 +845,6 @@ pub const File = struct { } } - /// Never called when LLVM is codegenning the ZCU. - fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) Error!void { - assert(base.comp.zcu.?.llvm_object == null); - switch (base.tag) { - .lld => unreachable, - else => {}, - inline .elf => |tag| { - dev.check(tag.devFeature()); - return @as(*tag.Type(), @fieldParentPtr("base", base)).clearContainerType(pt, ty); - }, - } - } - /// The active tag of `mir` is determined by the backend used for the module this function is in. /// Never called when LLVM is codegenning the ZCU. fn updateFunc( @@ -1417,6 +1426,9 @@ pub const PrelinkTask = union(enum) { load_dso: Path, }; pub const ZcuTask = union(enum) { + /// Sent once per update, as the very first `ZcuTask` in the update. Indicates that all per-file + /// state (e.g. `Zcu.alive_files`) is populated so can now be safely accessed by the linker. + files_ready, /// Write the constant value for a Decl to the output file. link_nav: InternPool.Nav.Index, /// Write the machine code for a function to the output file. @@ -1620,6 +1632,16 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void var timer = comp.startTimer(); const maybe_nav: ?InternPool.Nav.Index = switch (task) { + .files_ready => { + if (zcu.llvm_object != null) return; + const lf = comp.bin_file orelse return; + lf.zcuFilesReady() catch |err| switch (err) { + error.Canceled => io.recancel(), + error.AlreadyReported => return, + error.OutOfMemory => return diags.setAllocFailure(), + }; + return; + }, .link_nav => |nav_index| nav: { const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 4c5071fad3768f6123121295d5eeacd2c5b5443a..5dfb87ceb014d82837c13d1910612d6f059a06f7 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -7148,6 +7148,10 @@ fn prelinkInner(elf: *Elf) Error!void { } } +pub fn zcuFilesReady(elf: *Elf) link.Error!void { + _ = elf; // TODO jacobly +} + fn prepareDynamic(elf: *Elf) Error!void { const comp = elf.base.comp; -- 2.54.0