authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-18 17:02:39-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-20 20:59:52-08:00
logce00e91aa51f05925a297c7d6dc16c37a41fc151
tree866c0e72bf95bd98de8e2d3b6553a5cf12172ebe
parent160445ef316f76dfddfa17b11c4919a3e14f486d

Compilation pipeline: do musl jobs earlier

This means doing more work in parallel which is already good, but it's also a correctnes fix because we need link_task_wait_group.wait() to ensure that no more linker inputs will be generated.

1 files changed, 59 insertions(+), 43 deletions(-)

src/Compilation.zig+59-43
......@@ -122,6 +122,10 @@ link_task_queue_postponed: std.ArrayListUnmanaged(link.Task) = .empty,
122122/// the linker task thread.
123123remaining_prelink_tasks: u32,
124124
125/// Set of work that can be represented by only flags to determine whether the
126/// work is queued or not.
127queued_jobs: QueuedJobs,
128
125129work_queues: [
126130 len: {
127131 var len: usize = 0;
......@@ -193,10 +197,6 @@ stack_report: bool,
193197debug_compiler_runtime_libs: bool,
194198debug_compile_errors: bool,
195199incremental: bool,
196job_queued_compiler_rt_lib: bool = false,
197job_queued_compiler_rt_obj: bool = false,
198job_queued_fuzzer_lib: bool = false,
199job_queued_update_builtin_zig: bool,
200200alloc_failure_occurred: bool = false,
201201last_update_was_cache_hit: bool = false,
202202
......@@ -234,13 +234,13 @@ tsan_lib: ?CrtFile = null,
234234/// and resolved before calling linker.flush().
235235libc_static_lib: ?CrtFile = null,
236236/// Populated when we build the libcompiler_rt static library. A Job to build this is indicated
237/// by setting `job_queued_compiler_rt_lib` and resolved before calling linker.flush().
237/// by setting `queued_jobs.compiler_rt_lib` and resolved before calling linker.flush().
238238compiler_rt_lib: ?CrtFile = null,
239239/// Populated when we build the compiler_rt_obj object. A Job to build this is indicated
240/// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush().
240/// by setting `queued_jobs.compiler_rt_obj` and resolved before calling linker.flush().
241241compiler_rt_obj: ?CrtFile = null,
242242/// Populated when we build the libfuzzer static library. A Job to build this
243/// is indicated by setting `job_queued_fuzzer_lib` and resolved before
243/// is indicated by setting `queued_jobs.fuzzer_lib` and resolved before
244244/// calling linker.flush().
245245fuzzer_lib: ?CrtFile = null,
246246
......@@ -284,6 +284,14 @@ file_system_inputs: ?*std.ArrayListUnmanaged(u8),
284284/// This digest will be known after update() is called.
285285digest: ?[Cache.bin_digest_len]u8 = null,
286286
287const QueuedJobs = struct {
288 compiler_rt_lib: bool = false,
289 compiler_rt_obj: bool = false,
290 fuzzer_lib: bool = false,
291 update_builtin_zig: bool,
292 musl_crt_file: [@typeInfo(musl.CrtFile).@"enum".fields.len]bool = [1]bool{false} ** @typeInfo(musl.CrtFile).@"enum".fields.len,
293};
294
287295pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size;
288296pub const SemaError = Zcu.SemaError;
289297
......@@ -381,8 +389,6 @@ const Job = union(enum) {
381389 glibc_crt_file: glibc.CrtFile,
382390 /// all of the glibc shared objects
383391 glibc_shared_objects,
384 /// one of the musl static objects
385 musl_crt_file: musl.CrtFile,
386392 /// one of the mingw-w64 static objects
387393 mingw_crt_file: mingw.CrtFile,
388394
......@@ -1512,7 +1518,9 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
15121518 .framework_dirs = options.framework_dirs,
15131519 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
15141520 .skip_linker_dependencies = options.skip_linker_dependencies,
1515 .job_queued_update_builtin_zig = have_zcu,
1521 .queued_jobs = .{
1522 .update_builtin_zig = have_zcu,
1523 },
15161524 .function_sections = options.function_sections,
15171525 .data_sections = options.data_sections,
15181526 .native_system_include_paths = options.native_system_include_paths,
......@@ -1805,20 +1813,18 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18051813 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
18061814
18071815 if (musl.needsCrtiCrtn(target)) {
1808 try comp.queueJobs(&[_]Job{
1809 .{ .musl_crt_file = .crti_o },
1810 .{ .musl_crt_file = .crtn_o },
1811 });
1816 comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.crti_o)] = true;
1817 comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.crtn_o)] = true;
18121818 comp.remaining_prelink_tasks += 2;
18131819 }
18141820 if (musl.needsCrt0(comp.config.output_mode, comp.config.link_mode, comp.config.pie)) |f| {
1815 try comp.queueJobs(&.{.{ .musl_crt_file = f }});
1821 comp.queued_jobs.musl_crt_file[@intFromEnum(f)] = true;
18161822 comp.remaining_prelink_tasks += 1;
18171823 }
1818 try comp.queueJobs(&.{.{ .musl_crt_file = switch (comp.config.link_mode) {
1819 .static => .libc_a,
1820 .dynamic => .libc_so,
1821 } }});
1824 switch (comp.config.link_mode) {
1825 .static => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_a)] = true,
1826 .dynamic => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_so)] = true,
1827 }
18221828 comp.remaining_prelink_tasks += 1;
18231829 } else if (target.isGnuLibC()) {
18241830 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
......@@ -1916,20 +1922,20 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19161922 if (comp.include_compiler_rt and capable_of_building_compiler_rt) {
19171923 if (is_exe_or_dyn_lib) {
19181924 log.debug("queuing a job to build compiler_rt_lib", .{});
1919 comp.job_queued_compiler_rt_lib = true;
1925 comp.queued_jobs.compiler_rt_lib = true;
19201926 comp.remaining_prelink_tasks += 1;
19211927 } else if (output_mode != .Obj) {
19221928 log.debug("queuing a job to build compiler_rt_obj", .{});
19231929 // In this case we are making a static library, so we ask
19241930 // for a compiler-rt object to put in it.
1925 comp.job_queued_compiler_rt_obj = true;
1931 comp.queued_jobs.compiler_rt_obj = true;
19261932 comp.remaining_prelink_tasks += 1;
19271933 }
19281934 }
19291935
19301936 if (is_exe_or_dyn_lib and comp.config.any_fuzz and capable_of_building_compiler_rt) {
19311937 log.debug("queuing a job to build libfuzzer", .{});
1932 comp.job_queued_fuzzer_lib = true;
1938 comp.queued_jobs.fuzzer_lib = true;
19331939 comp.remaining_prelink_tasks += 1;
19341940 }
19351941 }
......@@ -3712,21 +3718,24 @@ fn performAllTheWorkInner(
37123718 work_queue_wait_group.spawnManager(workerDocsWasm, .{ comp, main_progress_node });
37133719 }
37143720
3715 if (comp.job_queued_compiler_rt_lib) {
3716 comp.job_queued_compiler_rt_lib = false;
3721 if (testAndClear(&comp.queued_jobs.compiler_rt_lib)) {
37173722 comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "compiler_rt.zig", .compiler_rt, .Lib, &comp.compiler_rt_lib, main_progress_node });
37183723 }
37193724
3720 if (comp.job_queued_compiler_rt_obj) {
3721 comp.job_queued_compiler_rt_obj = false;
3725 if (testAndClear(&comp.queued_jobs.compiler_rt_obj)) {
37223726 comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "compiler_rt.zig", .compiler_rt, .Obj, &comp.compiler_rt_obj, main_progress_node });
37233727 }
37243728
3725 if (comp.job_queued_fuzzer_lib) {
3726 comp.job_queued_fuzzer_lib = false;
3729 if (testAndClear(&comp.queued_jobs.fuzzer_lib)) {
37273730 comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "fuzzer.zig", .libfuzzer, .Lib, &comp.fuzzer_lib, main_progress_node });
37283731 }
37293732
3733 inline for (@typeInfo(musl.CrtFile).@"enum".fields) |field| {
3734 const tag = @field(musl.CrtFile, field.name);
3735 if (testAndClear(&comp.queued_jobs.musl_crt_file[@intFromEnum(tag)]))
3736 comp.link_task_wait_group.spawnManager(buildMuslCrtFile, .{ comp, tag, main_progress_node });
3737 }
3738
37303739 {
37313740 const astgen_frame = tracy.namedFrame("astgen");
37323741 defer astgen_frame.end();
......@@ -3741,8 +3750,8 @@ fn performAllTheWorkInner(
37413750 // 1. to avoid race condition of zig processes truncating each other's builtin.zig files
37423751 // 2. optimization; in the hot path it only incurs a stat() syscall, which happens
37433752 // in the `astgen_wait_group`.
3744 if (comp.job_queued_update_builtin_zig) b: {
3745 comp.job_queued_update_builtin_zig = false;
3753 if (comp.queued_jobs.update_builtin_zig) b: {
3754 comp.queued_jobs.update_builtin_zig = false;
37463755 if (comp.zcu == null) break :b;
37473756 // TODO put all the modules in a flat array to make them easy to iterate.
37483757 var seen: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .empty;
......@@ -3821,6 +3830,7 @@ fn performAllTheWorkInner(
38213830 comp.link_task_wait_group.wait();
38223831 comp.link_task_wait_group.reset();
38233832 std.log.scoped(.link).debug("finished waiting for link_task_wait_group", .{});
3833 assert(comp.remaining_prelink_tasks == 0);
38243834 }
38253835
38263836 work: while (true) {
......@@ -3980,19 +3990,6 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
39803990 );
39813991 };
39823992 },
3983 .musl_crt_file => |crt_file| {
3984 const named_frame = tracy.namedFrame("musl_crt_file");
3985 defer named_frame.end();
3986
3987 musl.buildCrtFile(comp, crt_file, prog_node) catch |err| {
3988 // TODO Surface more error details.
3989 comp.lockAndSetMiscFailure(
3990 .musl_crt_file,
3991 "unable to build musl CRT file: {s}",
3992 .{@errorName(err)},
3993 );
3994 };
3995 },
39963993 .mingw_crt_file => |crt_file| {
39973994 const named_frame = tracy.namedFrame("mingw_crt_file");
39983995 defer named_frame.end();
......@@ -4761,6 +4758,19 @@ fn buildRt(
47614758 };
47624759}
47634760
4761fn buildMuslCrtFile(
4762 comp: *Compilation,
4763 crt_file: musl.CrtFile,
4764 prog_node: std.Progress.Node,
4765) void {
4766 musl.buildCrtFile(comp, crt_file, prog_node) catch |err| switch (err) {
4767 error.SubCompilationFailed => return, // error reported already
4768 else => comp.lockAndSetMiscFailure(.musl_crt_file, "unable to build musl {s}: {s}", .{
4769 @tagName(crt_file), @errorName(err),
4770 }),
4771 };
4772}
4773
47644774fn reportRetryableCObjectError(
47654775 comp: *Compilation,
47664776 c_object: *CObject,
......@@ -6805,3 +6815,9 @@ pub fn compilerRtOptMode(comp: Compilation) std.builtin.OptimizeMode {
68056815pub fn compilerRtStrip(comp: Compilation) bool {
68066816 return comp.root_mod.strip;
68076817}
6818
6819fn testAndClear(b: *bool) bool {
6820 const result = b.*;
6821 b.* = false;
6822 return result;
6823}