| author | |
| committer | |
| log | db5d85b8c89b755bd8865def3bd7114d5d9d4867 |
| tree | 266fb0e6bea6977a76bb67047c69495dabb148ca |
| parent | ba53b140288b4518de38a8174ab7ad402607b8d4 |
| signature |
* "Flush" nodes ("LLVM Emit Object", "ELF Flush") appear under "Linking"
* "Code Generation" disappears when all analysis and codegen is done
* We only show one node under "Semantic Analysis" to accurately convey
that analysis isn't happening in parallel, but rather that we're
pausing one task to do another7 files changed, 126 insertions(+), 41 deletions(-)
lib/std/Progress.zig+22| ... | @@ -234,6 +234,28 @@ pub const Node = struct { | ... | @@ -234,6 +234,28 @@ pub const Node = struct { |
| 234 | _ = @atomicRmw(u32, &storage.completed_count, .Add, 1, .monotonic); | 234 | _ = @atomicRmw(u32, &storage.completed_count, .Add, 1, .monotonic); |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | /// Thread-safe. Bytes after '0' in `new_name` are ignored. | ||
| 238 | pub fn setName(n: Node, new_name: []const u8) void { | ||
| 239 | const index = n.index.unwrap() orelse return; | ||
| 240 | const storage = storageByIndex(index); | ||
| 241 | |||
| 242 | const name_len = @min(max_name_len, std.mem.indexOfScalar(u8, new_name, 0) orelse new_name.len); | ||
| 243 | |||
| 244 | copyAtomicStore(storage.name[0..name_len], new_name[0..name_len]); | ||
| 245 | if (name_len < storage.name.len) | ||
| 246 | @atomicStore(u8, &storage.name[name_len], 0, .monotonic); | ||
| 247 | } | ||
| 248 | |||
| 249 | /// Gets the name of this `Node`. | ||
| 250 | /// A pointer to this array can later be passed to `setName` to restore the name. | ||
| 251 | pub fn getName(n: Node) [max_name_len]u8 { | ||
| 252 | var dest: [max_name_len]u8 align(@alignOf(usize)) = undefined; | ||
| 253 | if (n.index.unwrap()) |index| { | ||
| 254 | copyAtomicLoad(&dest, &storageByIndex(index).name); | ||
| 255 | } | ||
| 256 | return dest; | ||
| 257 | } | ||
| 258 | |||
| 237 | /// Thread-safe. | 259 | /// Thread-safe. |
| 238 | pub fn setCompletedItems(n: Node, completed_items: usize) void { | 260 | pub fn setCompletedItems(n: Node, completed_items: usize) void { |
| 239 | const index = n.index.unwrap() orelse return; | 261 | const index = n.index.unwrap() orelse return; |
src/Compilation.zig+36-22| ... | @@ -255,7 +255,7 @@ test_filters: []const []const u8, | ... | @@ -255,7 +255,7 @@ test_filters: []const []const u8, |
| 255 | test_name_prefix: ?[]const u8, | 255 | test_name_prefix: ?[]const u8, |
| 256 | 256 | ||
| 257 | link_task_wait_group: WaitGroup = .{}, | 257 | link_task_wait_group: WaitGroup = .{}, |
| 258 | work_queue_progress_node: std.Progress.Node = .none, | 258 | link_prog_node: std.Progress.Node = std.Progress.Node.none, |
| 259 | 259 | ||
| 260 | llvm_opt_bisect_limit: c_int, | 260 | llvm_opt_bisect_limit: c_int, |
| 261 | 261 | ||
| ... | @@ -2795,6 +2795,17 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { | ... | @@ -2795,6 +2795,17 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2795 | } | 2795 | } |
| 2796 | } | 2796 | } |
| 2797 | 2797 | ||
| 2798 | // The linker progress node is set up here instead of in `performAllTheWork`, because | ||
| 2799 | // we also want it around during `flush`. | ||
| 2800 | const have_link_node = comp.bin_file != null; | ||
| 2801 | if (have_link_node) { | ||
| 2802 | comp.link_prog_node = main_progress_node.start("Linking", 0); | ||
| 2803 | } | ||
| 2804 | defer if (have_link_node) { | ||
| 2805 | comp.link_prog_node.end(); | ||
| 2806 | comp.link_prog_node = .none; | ||
| 2807 | }; | ||
| 2808 | |||
| 2798 | try comp.performAllTheWork(main_progress_node); | 2809 | try comp.performAllTheWork(main_progress_node); |
| 2799 | 2810 | ||
| 2800 | if (comp.zcu) |zcu| { | 2811 | if (comp.zcu) |zcu| { |
| ... | @@ -2843,7 +2854,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { | ... | @@ -2843,7 +2854,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2843 | 2854 | ||
| 2844 | switch (comp.cache_use) { | 2855 | switch (comp.cache_use) { |
| 2845 | .none, .incremental => { | 2856 | .none, .incremental => { |
| 2846 | try flush(comp, arena, .main, main_progress_node); | 2857 | try flush(comp, arena, .main); |
| 2847 | }, | 2858 | }, |
| 2848 | .whole => |whole| { | 2859 | .whole => |whole| { |
| 2849 | if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf); | 2860 | if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf); |
| ... | @@ -2919,7 +2930,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { | ... | @@ -2919,7 +2930,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2919 | } | 2930 | } |
| 2920 | } | 2931 | } |
| 2921 | 2932 | ||
| 2922 | try flush(comp, arena, .main, main_progress_node); | 2933 | try flush(comp, arena, .main); |
| 2923 | 2934 | ||
| 2924 | // Calling `flush` may have produced errors, in which case the | 2935 | // Calling `flush` may have produced errors, in which case the |
| 2925 | // cache manifest must not be written. | 2936 | // cache manifest must not be written. |
| ... | @@ -3009,13 +3020,12 @@ fn flush( | ... | @@ -3009,13 +3020,12 @@ fn flush( |
| 3009 | comp: *Compilation, | 3020 | comp: *Compilation, |
| 3010 | arena: Allocator, | 3021 | arena: Allocator, |
| 3011 | tid: Zcu.PerThread.Id, | 3022 | tid: Zcu.PerThread.Id, |
| 3012 | prog_node: std.Progress.Node, | ||
| 3013 | ) !void { | 3023 | ) !void { |
| 3014 | if (comp.zcu) |zcu| { | 3024 | if (comp.zcu) |zcu| { |
| 3015 | if (zcu.llvm_object) |llvm_object| { | 3025 | if (zcu.llvm_object) |llvm_object| { |
| 3016 | // Emit the ZCU object from LLVM now; it's required to flush the output file. | 3026 | // Emit the ZCU object from LLVM now; it's required to flush the output file. |
| 3017 | // If there's an output file, it wants to decide where the LLVM object goes! | 3027 | // If there's an output file, it wants to decide where the LLVM object goes! |
| 3018 | const sub_prog_node = prog_node.start("LLVM Emit Object", 0); | 3028 | const sub_prog_node = comp.link_prog_node.start("LLVM Emit Object", 0); |
| 3019 | defer sub_prog_node.end(); | 3029 | defer sub_prog_node.end(); |
| 3020 | try llvm_object.emit(.{ | 3030 | try llvm_object.emit(.{ |
| 3021 | .pre_ir_path = comp.verbose_llvm_ir, | 3031 | .pre_ir_path = comp.verbose_llvm_ir, |
| ... | @@ -3053,7 +3063,7 @@ fn flush( | ... | @@ -3053,7 +3063,7 @@ fn flush( |
| 3053 | } | 3063 | } |
| 3054 | if (comp.bin_file) |lf| { | 3064 | if (comp.bin_file) |lf| { |
| 3055 | // This is needed before reading the error flags. | 3065 | // This is needed before reading the error flags. |
| 3056 | lf.flush(arena, tid, prog_node) catch |err| switch (err) { | 3066 | lf.flush(arena, tid, comp.link_prog_node) catch |err| switch (err) { |
| 3057 | error.LinkFailure => {}, // Already reported. | 3067 | error.LinkFailure => {}, // Already reported. |
| 3058 | error.OutOfMemory => return error.OutOfMemory, | 3068 | error.OutOfMemory => return error.OutOfMemory, |
| 3059 | }; | 3069 | }; |
| ... | @@ -4172,28 +4182,15 @@ pub fn addWholeFileError( | ... | @@ -4172,28 +4182,15 @@ pub fn addWholeFileError( |
| 4172 | } | 4182 | } |
| 4173 | } | 4183 | } |
| 4174 | 4184 | ||
| 4175 | pub fn performAllTheWork( | 4185 | fn performAllTheWork( |
| 4176 | comp: *Compilation, | 4186 | comp: *Compilation, |
| 4177 | main_progress_node: std.Progress.Node, | 4187 | main_progress_node: std.Progress.Node, |
| 4178 | ) JobError!void { | 4188 | ) JobError!void { |
| 4179 | comp.work_queue_progress_node = main_progress_node; | 4189 | // Regardless of errors, `comp.zcu` needs to update its generation number. |
| 4180 | defer comp.work_queue_progress_node = .none; | ||
| 4181 | |||
| 4182 | defer if (comp.zcu) |zcu| { | 4190 | defer if (comp.zcu) |zcu| { |
| 4183 | zcu.sema_prog_node.end(); | ||
| 4184 | zcu.sema_prog_node = .none; | ||
| 4185 | zcu.codegen_prog_node.end(); | ||
| 4186 | zcu.codegen_prog_node = .none; | ||
| 4187 | |||
| 4188 | zcu.generation += 1; | 4191 | zcu.generation += 1; |
| 4189 | }; | 4192 | }; |
| 4190 | try comp.performAllTheWorkInner(main_progress_node); | ||
| 4191 | } | ||
| 4192 | 4193 | ||
| 4193 | fn performAllTheWorkInner( | ||
| 4194 | comp: *Compilation, | ||
| 4195 | main_progress_node: std.Progress.Node, | ||
| 4196 | ) JobError!void { | ||
| 4197 | // Here we queue up all the AstGen tasks first, followed by C object compilation. | 4194 | // Here we queue up all the AstGen tasks first, followed by C object compilation. |
| 4198 | // We wait until the AstGen tasks are all completed before proceeding to the | 4195 | // We wait until the AstGen tasks are all completed before proceeding to the |
| 4199 | // (at least for now) single-threaded main work queue. However, C object compilation | 4196 | // (at least for now) single-threaded main work queue. However, C object compilation |
| ... | @@ -4513,8 +4510,24 @@ fn performAllTheWorkInner( | ... | @@ -4513,8 +4510,24 @@ fn performAllTheWorkInner( |
| 4513 | } | 4510 | } |
| 4514 | 4511 | ||
| 4515 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); | 4512 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); |
| 4516 | zcu.codegen_prog_node = if (comp.bin_file != null) main_progress_node.start("Code Generation", 0) else .none; | 4513 | if (comp.bin_file != null) { |
| 4514 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); | ||
| 4515 | } | ||
| 4516 | // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes. | ||
| 4517 | // That prevents the "Code Generation" node from constantly disappearing and reappearing when | ||
| 4518 | // we're probably going to analyze more functions at some point. | ||
| 4519 | assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes | ||
| 4517 | } | 4520 | } |
| 4521 | // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation". | ||
| 4522 | defer if (comp.zcu) |zcu| { | ||
| 4523 | zcu.sema_prog_node.end(); | ||
| 4524 | zcu.sema_prog_node = .none; | ||
| 4525 | if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) { | ||
| 4526 | // Decremented to 0, so all done. | ||
| 4527 | zcu.codegen_prog_node.end(); | ||
| 4528 | zcu.codegen_prog_node = .none; | ||
| 4529 | } | ||
| 4530 | }; | ||
| 4518 | 4531 | ||
| 4519 | if (!comp.separateCodegenThreadOk()) { | 4532 | if (!comp.separateCodegenThreadOk()) { |
| 4520 | // Waits until all input files have been parsed. | 4533 | // Waits until all input files have been parsed. |
| ... | @@ -4583,6 +4596,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { | ... | @@ -4583,6 +4596,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { |
| 4583 | .status = .init(.pending), | 4596 | .status = .init(.pending), |
| 4584 | .value = undefined, | 4597 | .value = undefined, |
| 4585 | }; | 4598 | }; |
| 4599 | assert(zcu.pending_codegen_jobs.rmw(.Add, 1, .monotonic) > 0); // the "Code Generation" node hasn't been ended | ||
| 4586 | if (comp.separateCodegenThreadOk()) { | 4600 | if (comp.separateCodegenThreadOk()) { |
| 4587 | // `workerZcuCodegen` takes ownership of `air`. | 4601 | // `workerZcuCodegen` takes ownership of `air`. |
| 4588 | comp.thread_pool.spawnWgId(&comp.link_task_wait_group, workerZcuCodegen, .{ comp, func.func, air, shared_mir }); | 4602 | comp.thread_pool.spawnWgId(&comp.link_task_wait_group, workerZcuCodegen, .{ comp, func.func, air, shared_mir }); |
src/Zcu.zig+36-2| ... | @@ -66,8 +66,18 @@ root_mod: *Package.Module, | ... | @@ -66,8 +66,18 @@ root_mod: *Package.Module, |
| 66 | /// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests. | 66 | /// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests. |
| 67 | main_mod: *Package.Module, | 67 | main_mod: *Package.Module, |
| 68 | std_mod: *Package.Module, | 68 | std_mod: *Package.Module, |
| 69 | sema_prog_node: std.Progress.Node = std.Progress.Node.none, | 69 | sema_prog_node: std.Progress.Node = .none, |
| 70 | codegen_prog_node: std.Progress.Node = std.Progress.Node.none, | 70 | codegen_prog_node: std.Progress.Node = .none, |
| 71 | /// The number of codegen jobs which are pending or in-progress. Whichever thread drops this value | ||
| 72 | /// to 0 is responsible for ending `codegen_prog_node`. While semantic analysis is happening, this | ||
| 73 | /// value bottoms out at 1 instead of 0, to ensure that it can only drop to 0 after analysis is | ||
| 74 | /// completed (since semantic analysis could trigger more codegen work). | ||
| 75 | pending_codegen_jobs: std.atomic.Value(u32) = .init(0), | ||
| 76 | |||
| 77 | /// This is the progress node *under* `sema_prog_node` which is currently running. | ||
| 78 | /// When we have to pause to analyze something else, we just temporarily rename this node. | ||
| 79 | /// Eventually, when we thread semantic analysis, we will want one of these per thread. | ||
| 80 | cur_sema_prog_node: std.Progress.Node = .none, | ||
| 71 | 81 | ||
| 72 | /// Used by AstGen worker to load and store ZIR cache. | 82 | /// Used by AstGen worker to load and store ZIR cache. |
| 73 | global_zir_cache: Cache.Directory, | 83 | global_zir_cache: Cache.Directory, |
| ... | @@ -4753,3 +4763,27 @@ fn explainWhyFileIsInModule( | ... | @@ -4753,3 +4763,27 @@ fn explainWhyFileIsInModule( |
| 4753 | import = importer_ref.import; | 4763 | import = importer_ref.import; |
| 4754 | } | 4764 | } |
| 4755 | } | 4765 | } |
| 4766 | |||
| 4767 | const SemaProgNode = struct { | ||
| 4768 | /// `null` means we created the node, so should end it. | ||
| 4769 | old_name: ?[std.Progress.Node.max_name_len]u8, | ||
| 4770 | pub fn end(spn: SemaProgNode, zcu: *Zcu) void { | ||
| 4771 | if (spn.old_name) |old_name| { | ||
| 4772 | zcu.sema_prog_node.completeOne(); // we're just renaming, but it's effectively completion | ||
| 4773 | zcu.cur_sema_prog_node.setName(&old_name); | ||
| 4774 | } else { | ||
| 4775 | zcu.cur_sema_prog_node.end(); | ||
| 4776 | zcu.cur_sema_prog_node = .none; | ||
| 4777 | } | ||
| 4778 | } | ||
| 4779 | }; | ||
| 4780 | pub fn startSemaProgNode(zcu: *Zcu, name: []const u8) SemaProgNode { | ||
| 4781 | if (zcu.cur_sema_prog_node.index != .none) { | ||
| 4782 | const old_name = zcu.cur_sema_prog_node.getName(); | ||
| 4783 | zcu.cur_sema_prog_node.setName(name); | ||
| 4784 | return .{ .old_name = old_name }; | ||
| 4785 | } else { | ||
| 4786 | zcu.cur_sema_prog_node = zcu.sema_prog_node.start(name, 0); | ||
| 4787 | return .{ .old_name = null }; | ||
| 4788 | } | ||
| 4789 | } |
src/Zcu/PerThread.zig+14-8| ... | @@ -796,8 +796,8 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU | ... | @@ -796,8 +796,8 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 796 | info.deps.clearRetainingCapacity(); | 796 | info.deps.clearRetainingCapacity(); |
| 797 | } | 797 | } |
| 798 | 798 | ||
| 799 | const unit_prog_node = zcu.sema_prog_node.start("comptime", 0); | 799 | const unit_prog_node = zcu.startSemaProgNode("comptime"); |
| 800 | defer unit_prog_node.end(); | 800 | defer unit_prog_node.end(zcu); |
| 801 | 801 | ||
| 802 | return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) { | 802 | return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) { |
| 803 | error.AnalysisFail => { | 803 | error.AnalysisFail => { |
| ... | @@ -976,8 +976,8 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu | ... | @@ -976,8 +976,8 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 976 | info.deps.clearRetainingCapacity(); | 976 | info.deps.clearRetainingCapacity(); |
| 977 | } | 977 | } |
| 978 | 978 | ||
| 979 | const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0); | 979 | const unit_prog_node = zcu.startSemaProgNode(nav.fqn.toSlice(ip)); |
| 980 | defer unit_prog_node.end(); | 980 | defer unit_prog_node.end(zcu); |
| 981 | 981 | ||
| 982 | const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id)) |result| res: { | 982 | const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id)) |result| res: { |
| 983 | break :res .{ | 983 | break :res .{ |
| ... | @@ -1396,8 +1396,8 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc | ... | @@ -1396,8 +1396,8 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc |
| 1396 | info.deps.clearRetainingCapacity(); | 1396 | info.deps.clearRetainingCapacity(); |
| 1397 | } | 1397 | } |
| 1398 | 1398 | ||
| 1399 | const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0); | 1399 | const unit_prog_node = zcu.startSemaProgNode(nav.fqn.toSlice(ip)); |
| 1400 | defer unit_prog_node.end(); | 1400 | defer unit_prog_node.end(zcu); |
| 1401 | 1401 | ||
| 1402 | const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id)) |result| res: { | 1402 | const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id)) |result| res: { |
| 1403 | break :res .{ | 1403 | break :res .{ |
| ... | @@ -1617,8 +1617,8 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter | ... | @@ -1617,8 +1617,8 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: Inter |
| 1617 | info.deps.clearRetainingCapacity(); | 1617 | info.deps.clearRetainingCapacity(); |
| 1618 | } | 1618 | } |
| 1619 | 1619 | ||
| 1620 | const func_prog_node = zcu.sema_prog_node.start(ip.getNav(func.owner_nav).fqn.toSlice(ip), 0); | 1620 | const func_prog_node = zcu.startSemaProgNode(ip.getNav(func.owner_nav).fqn.toSlice(ip)); |
| 1621 | defer func_prog_node.end(); | 1621 | defer func_prog_node.end(zcu); |
| 1622 | 1622 | ||
| 1623 | const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index)) |result| | 1623 | const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index)) |result| |
| 1624 | .{ prev_failed or result.ies_outdated, false } | 1624 | .{ prev_failed or result.ies_outdated, false } |
| ... | @@ -3360,6 +3360,7 @@ pub fn populateTestFunctions( | ... | @@ -3360,6 +3360,7 @@ pub fn populateTestFunctions( |
| 3360 | ip.mutateVarInit(test_fns_val.toIntern(), new_init); | 3360 | ip.mutateVarInit(test_fns_val.toIntern(), new_init); |
| 3361 | } | 3361 | } |
| 3362 | { | 3362 | { |
| 3363 | assert(zcu.codegen_prog_node.index == .none); | ||
| 3363 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); | 3364 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); |
| 3364 | defer { | 3365 | defer { |
| 3365 | zcu.codegen_prog_node.end(); | 3366 | zcu.codegen_prog_node.end(); |
| ... | @@ -4393,6 +4394,11 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, ou | ... | @@ -4393,6 +4394,11 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, ou |
| 4393 | }, | 4394 | }, |
| 4394 | } | 4395 | } |
| 4395 | zcu.comp.link_task_queue.mirReady(zcu.comp, out); | 4396 | zcu.comp.link_task_queue.mirReady(zcu.comp, out); |
| 4397 | if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) { | ||
| 4398 | // Decremented to 0, so all done. | ||
| 4399 | zcu.codegen_prog_node.end(); | ||
| 4400 | zcu.codegen_prog_node = .none; | ||
| 4401 | } | ||
| 4396 | } | 4402 | } |
| 4397 | fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{ | 4403 | fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{ |
| 4398 | OutOfMemory, | 4404 | OutOfMemory, |
src/link.zig+14-8| ... | @@ -1074,7 +1074,7 @@ pub const File = struct { | ... | @@ -1074,7 +1074,7 @@ pub const File = struct { |
| 1074 | 1074 | ||
| 1075 | /// Called when all linker inputs have been sent via `loadInput`. After | 1075 | /// Called when all linker inputs have been sent via `loadInput`. After |
| 1076 | /// this, `loadInput` will not be called anymore. | 1076 | /// this, `loadInput` will not be called anymore. |
| 1077 | pub fn prelink(base: *File, prog_node: std.Progress.Node) FlushError!void { | 1077 | pub fn prelink(base: *File) FlushError!void { |
| 1078 | assert(!base.post_prelink); | 1078 | assert(!base.post_prelink); |
| 1079 | 1079 | ||
| 1080 | // In this case, an object file is created by the LLVM backend, so | 1080 | // In this case, an object file is created by the LLVM backend, so |
| ... | @@ -1085,7 +1085,7 @@ pub const File = struct { | ... | @@ -1085,7 +1085,7 @@ pub const File = struct { |
| 1085 | switch (base.tag) { | 1085 | switch (base.tag) { |
| 1086 | inline .wasm => |tag| { | 1086 | inline .wasm => |tag| { |
| 1087 | dev.check(tag.devFeature()); | 1087 | dev.check(tag.devFeature()); |
| 1088 | return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(prog_node); | 1088 | return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node); |
| 1089 | }, | 1089 | }, |
| 1090 | else => {}, | 1090 | else => {}, |
| 1091 | } | 1091 | } |
| ... | @@ -1293,7 +1293,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1293,7 +1293,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1293 | const base = comp.bin_file orelse return; | 1293 | const base = comp.bin_file orelse return; |
| 1294 | switch (task) { | 1294 | switch (task) { |
| 1295 | .load_explicitly_provided => { | 1295 | .load_explicitly_provided => { |
| 1296 | const prog_node = comp.work_queue_progress_node.start("Parse Linker Inputs", comp.link_inputs.len); | 1296 | const prog_node = comp.link_prog_node.start("Parse Inputs", comp.link_inputs.len); |
| 1297 | defer prog_node.end(); | 1297 | defer prog_node.end(); |
| 1298 | for (comp.link_inputs) |input| { | 1298 | for (comp.link_inputs) |input| { |
| 1299 | base.loadInput(input) catch |err| switch (err) { | 1299 | base.loadInput(input) catch |err| switch (err) { |
| ... | @@ -1310,7 +1310,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1310,7 +1310,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1310 | } | 1310 | } |
| 1311 | }, | 1311 | }, |
| 1312 | .load_host_libc => { | 1312 | .load_host_libc => { |
| 1313 | const prog_node = comp.work_queue_progress_node.start("Linker Parse Host libc", 0); | 1313 | const prog_node = comp.link_prog_node.start("Parse Host libc", 0); |
| 1314 | defer prog_node.end(); | 1314 | defer prog_node.end(); |
| 1315 | 1315 | ||
| 1316 | const target = comp.root_mod.resolved_target.result; | 1316 | const target = comp.root_mod.resolved_target.result; |
| ... | @@ -1369,7 +1369,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1369,7 +1369,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1369 | } | 1369 | } |
| 1370 | }, | 1370 | }, |
| 1371 | .load_object => |path| { | 1371 | .load_object => |path| { |
| 1372 | const prog_node = comp.work_queue_progress_node.start("Linker Parse Object", 0); | 1372 | const prog_node = comp.link_prog_node.start("Parse Object", 0); |
| 1373 | defer prog_node.end(); | 1373 | defer prog_node.end(); |
| 1374 | base.openLoadObject(path) catch |err| switch (err) { | 1374 | base.openLoadObject(path) catch |err| switch (err) { |
| 1375 | error.LinkFailure => return, // error reported via diags | 1375 | error.LinkFailure => return, // error reported via diags |
| ... | @@ -1377,7 +1377,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1377,7 +1377,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1377 | }; | 1377 | }; |
| 1378 | }, | 1378 | }, |
| 1379 | .load_archive => |path| { | 1379 | .load_archive => |path| { |
| 1380 | const prog_node = comp.work_queue_progress_node.start("Linker Parse Archive", 0); | 1380 | const prog_node = comp.link_prog_node.start("Parse Archive", 0); |
| 1381 | defer prog_node.end(); | 1381 | defer prog_node.end(); |
| 1382 | base.openLoadArchive(path, null) catch |err| switch (err) { | 1382 | base.openLoadArchive(path, null) catch |err| switch (err) { |
| 1383 | error.LinkFailure => return, // error reported via link_diags | 1383 | error.LinkFailure => return, // error reported via link_diags |
| ... | @@ -1385,7 +1385,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1385,7 +1385,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1385 | }; | 1385 | }; |
| 1386 | }, | 1386 | }, |
| 1387 | .load_dso => |path| { | 1387 | .load_dso => |path| { |
| 1388 | const prog_node = comp.work_queue_progress_node.start("Linker Parse Shared Library", 0); | 1388 | const prog_node = comp.link_prog_node.start("Parse Shared Library", 0); |
| 1389 | defer prog_node.end(); | 1389 | defer prog_node.end(); |
| 1390 | base.openLoadDso(path, .{ | 1390 | base.openLoadDso(path, .{ |
| 1391 | .preferred_mode = .dynamic, | 1391 | .preferred_mode = .dynamic, |
| ... | @@ -1396,7 +1396,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { | ... | @@ -1396,7 +1396,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1396 | }; | 1396 | }; |
| 1397 | }, | 1397 | }, |
| 1398 | .load_input => |input| { | 1398 | .load_input => |input| { |
| 1399 | const prog_node = comp.work_queue_progress_node.start("Linker Parse Input", 0); | 1399 | const prog_node = comp.link_prog_node.start("Parse Input", 0); |
| 1400 | defer prog_node.end(); | 1400 | defer prog_node.end(); |
| 1401 | base.loadInput(input) catch |err| switch (err) { | 1401 | base.loadInput(input) catch |err| switch (err) { |
| 1402 | error.LinkFailure => return, // error reported via link_diags | 1402 | error.LinkFailure => return, // error reported via link_diags |
| ... | @@ -1418,6 +1418,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { | ... | @@ -1418,6 +1418,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { |
| 1418 | const zcu = comp.zcu.?; | 1418 | const zcu = comp.zcu.?; |
| 1419 | const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); | 1419 | const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); |
| 1420 | defer pt.deactivate(); | 1420 | defer pt.deactivate(); |
| 1421 | const fqn_slice = zcu.intern_pool.getNav(nav_index).fqn.toSlice(&zcu.intern_pool); | ||
| 1422 | const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); | ||
| 1423 | defer nav_prog_node.end(); | ||
| 1421 | if (zcu.llvm_object) |llvm_object| { | 1424 | if (zcu.llvm_object) |llvm_object| { |
| 1422 | llvm_object.updateNav(pt, nav_index) catch |err| switch (err) { | 1425 | llvm_object.updateNav(pt, nav_index) catch |err| switch (err) { |
| 1423 | error.OutOfMemory => diags.setAllocFailure(), | 1426 | error.OutOfMemory => diags.setAllocFailure(), |
| ... | @@ -1441,6 +1444,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { | ... | @@ -1441,6 +1444,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { |
| 1441 | const nav = zcu.funcInfo(func.func).owner_nav; | 1444 | const nav = zcu.funcInfo(func.func).owner_nav; |
| 1442 | const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); | 1445 | const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); |
| 1443 | defer pt.deactivate(); | 1446 | defer pt.deactivate(); |
| 1447 | const fqn_slice = zcu.intern_pool.getNav(nav).fqn.toSlice(&zcu.intern_pool); | ||
| 1448 | const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); | ||
| 1449 | defer nav_prog_node.end(); | ||
| 1444 | switch (func.mir.status.load(.monotonic)) { | 1450 | switch (func.mir.status.load(.monotonic)) { |
| 1445 | .pending => unreachable, | 1451 | .pending => unreachable, |
| 1446 | .ready => {}, | 1452 | .ready => {}, |
src/link/Lld.zig+3| ... | @@ -267,6 +267,9 @@ pub fn flush( | ... | @@ -267,6 +267,9 @@ pub fn flush( |
| 267 | 267 | ||
| 268 | const comp = lld.base.comp; | 268 | const comp = lld.base.comp; |
| 269 | const result = if (comp.config.output_mode == .Lib and comp.config.link_mode == .static) r: { | 269 | const result = if (comp.config.output_mode == .Lib and comp.config.link_mode == .static) r: { |
| 270 | if (!@import("build_options").have_llvm or !comp.config.use_lib_llvm) { | ||
| 271 | return lld.base.comp.link_diags.fail("using lld without libllvm not implemented", .{}); | ||
| 272 | } | ||
| 270 | break :r linkAsArchive(lld, arena); | 273 | break :r linkAsArchive(lld, arena); |
| 271 | } else switch (lld.ofmt) { | 274 | } else switch (lld.ofmt) { |
| 272 | .coff => coffLink(lld, arena), | 275 | .coff => coffLink(lld, arena), |
src/link/Queue.zig+1-1| ... | @@ -180,7 +180,7 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { | ... | @@ -180,7 +180,7 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { |
| 180 | // We've finished the prelink tasks, so run prelink if necessary. | 180 | // We've finished the prelink tasks, so run prelink if necessary. |
| 181 | if (comp.bin_file) |lf| { | 181 | if (comp.bin_file) |lf| { |
| 182 | if (!lf.post_prelink) { | 182 | if (!lf.post_prelink) { |
| 183 | if (lf.prelink(comp.work_queue_progress_node)) |_| { | 183 | if (lf.prelink()) |_| { |
| 184 | lf.post_prelink = true; | 184 | lf.post_prelink = true; |
| 185 | } else |err| switch (err) { | 185 | } else |err| switch (err) { |
| 186 | error.OutOfMemory => comp.link_diags.setAllocFailure(), | 186 | error.OutOfMemory => comp.link_diags.setAllocFailure(), |