authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-31 05:42:43-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-09-03 11:00:54-04:00
log91d8b7b8dc04aecea1a4fa7c6c6bc0696ebdada4
tree242ab4f7fec35e9bedded349068ba8edbfac2699
parentc5c037808e30d2c632bd3bd08ed17eef7fdd373e

Zcu: notify the linker once source files have been scanned


3 files changed, 41 insertions(+), 13 deletions(-)

src/Zcu/PerThread.zig+2
......@@ -258,6 +258,8 @@ pub fn update(
258258 return;
259259 }
260260
261 try comp.link_queue.enqueueZcu(comp, pt.tid, .files_ready);
262
261263 if (comp.config.incremental) {
262264 const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0);
263265 defer update_zir_refs_node.end();
src/link.zig+35-13
......@@ -794,6 +794,28 @@ pub const File = struct {
794794 }
795795 }
796796
797 /// When there is a ZCU, this is called exactly once per update, to indicate that all per-file
798 /// state (e.g. `Zcu.alive_files`) has been populated by the frontend, so can now be safely
799 /// accessed by the linker.
800 ///
801 /// This call occurs before any call to any of these functions:
802 /// * `updateNav`
803 /// * `updateFunc`
804 /// * `updateContainerType`
805 /// * `updateLineNumber`
806 ///
807 /// Asserts that the ZCU is not using the LLVM backend.
808 fn zcuFilesReady(base: *File) Error!void {
809 assert(base.comp.zcu.?.llvm_object == null);
810 switch (base.tag) {
811 else => {},
812 inline .elf2 => |tag| {
813 dev.check(tag.devFeature());
814 return @as(*tag.Type(), @fieldParentPtr("base", base)).zcuFilesReady();
815 },
816 }
817 }
818
797819 /// Asserts that the ZCU is not using the LLVM backend.
798820 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Error!void {
799821 assert(base.comp.zcu.?.llvm_object == null);
......@@ -823,19 +845,6 @@ pub const File = struct {
823845 }
824846 }
825847
826 /// Never called when LLVM is codegenning the ZCU.
827 fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) Error!void {
828 assert(base.comp.zcu.?.llvm_object == null);
829 switch (base.tag) {
830 .lld => unreachable,
831 else => {},
832 inline .elf => |tag| {
833 dev.check(tag.devFeature());
834 return @as(*tag.Type(), @fieldParentPtr("base", base)).clearContainerType(pt, ty);
835 },
836 }
837 }
838
839848 /// The active tag of `mir` is determined by the backend used for the module this function is in.
840849 /// Never called when LLVM is codegenning the ZCU.
841850 fn updateFunc(
......@@ -1417,6 +1426,9 @@ pub const PrelinkTask = union(enum) {
14171426 load_dso: Path,
14181427};
14191428pub const ZcuTask = union(enum) {
1429 /// Sent once per update, as the very first `ZcuTask` in the update. Indicates that all per-file
1430 /// state (e.g. `Zcu.alive_files`) is populated so can now be safely accessed by the linker.
1431 files_ready,
14201432 /// Write the constant value for a Decl to the output file.
14211433 link_nav: InternPool.Nav.Index,
14221434 /// 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
16201632 var timer = comp.startTimer();
16211633
16221634 const maybe_nav: ?InternPool.Nav.Index = switch (task) {
1635 .files_ready => {
1636 if (zcu.llvm_object != null) return;
1637 const lf = comp.bin_file orelse return;
1638 lf.zcuFilesReady() catch |err| switch (err) {
1639 error.Canceled => io.recancel(),
1640 error.AlreadyReported => return,
1641 error.OutOfMemory => return diags.setAllocFailure(),
1642 };
1643 return;
1644 },
16231645 .link_nav => |nav_index| nav: {
16241646 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
16251647 const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);
src/link/Elf2.zig+4
......@@ -7148,6 +7148,10 @@ fn prelinkInner(elf: *Elf) Error!void {
71487148 }
71497149}
71507150
7151pub fn zcuFilesReady(elf: *Elf) link.Error!void {
7152 _ = elf; // TODO jacobly
7153}
7154
71517155fn prepareDynamic(elf: *Elf) Error!void {
71527156 const comp = elf.base.comp;
71537157