authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-16 20:23:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-17 16:38:59-07:00
log5cd548e53081428d0e6b4a6b5a305317052c133a
tree4beb45ef87a73007a11e004a2fc52e35d8a6dc8e
parentb4f3e69342d176ad7a2572cf4fee704094faaada

Compilation: multi-thread compiler-rt

compiler_rt_lib and compiler_rt_obj are extracted from the generic JobQueue into simple boolean flags, and then handled explicitly inside performAllTheWork(). Introduced generic handling of allocation failure and made setMiscFailure not return a possible error. Building the compiler-rt static library now takes advantage of Compilation's ThreadPool. This introduced a problem, however, because now each of the object files of compiler-rt all perform AstGen for the full standard library and compiler-rt files. Even though all of them end up being cache hits except for the first ones, this is wasteful - O(N*M) where N is number of compilation units inside compiler-rt and M is the number of .zig files in the standard library and compiler-rt combined. More importantly, however, it causes a deadlock, because each thread interacts with a file system lock for doing AstGen on files, and threads end up waiting for each other. This will need to be handled with a process-level file caching system, or some other creative solution.

4 files changed, 528 insertions(+), 390 deletions(-)

src/Compilation.zig+115-78
......@@ -93,6 +93,9 @@ unwind_tables: bool,
9393test_evented_io: bool,
9494debug_compiler_runtime_libs: bool,
9595debug_compile_errors: bool,
96job_queued_compiler_rt_lib: bool = false,
97job_queued_compiler_rt_obj: bool = false,
98alloc_failure_occurred: bool = false,
9699
97100c_source_files: []const CSourceFile,
98101clang_argv: []const []const u8,
......@@ -130,11 +133,11 @@ libssp_static_lib: ?CRTFile = null,
130133/// Populated when we build the libc static library. A Job to build this is placed in the queue
131134/// and resolved before calling linker.flush().
132135libc_static_lib: ?CRTFile = null,
133/// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue
134/// and resolved before calling linker.flush().
136/// Populated when we build the libcompiler_rt static library. A Job to build this is indicated
137/// by setting `job_queued_compiler_rt_lib` and resolved before calling linker.flush().
135138compiler_rt_lib: ?CRTFile = null,
136/// Populated when we build the compiler_rt_obj object. A Job to build this is placed in the queue
137/// and resolved before calling linker.flush().
139/// Populated when we build the compiler_rt_obj object. A Job to build this is indicated
140/// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush().
138141compiler_rt_obj: ?CRTFile = null,
139142
140143glibc_so_files: ?glibc.BuiltSharedObjects = null,
......@@ -224,8 +227,6 @@ const Job = union(enum) {
224227 libcxxabi: void,
225228 libtsan: void,
226229 libssp: void,
227 compiler_rt_lib: void,
228 compiler_rt_obj: void,
229230 /// needed when not linking libc and using LLVM for code generation because it generates
230231 /// calls to, for example, memcpy and memset.
231232 zig_libc: void,
......@@ -1925,13 +1926,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
19251926 if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) {
19261927 if (is_exe_or_dyn_lib) {
19271928 log.debug("queuing a job to build compiler_rt_lib", .{});
1928 try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} });
1929 comp.job_queued_compiler_rt_lib = true;
19291930 } else if (options.output_mode != .Obj) {
19301931 log.debug("queuing a job to build compiler_rt_obj", .{});
19311932 // If build-obj with -fcompiler-rt is requested, that is handled specially
19321933 // elsewhere. In this case we are making a static library, so we ask
19331934 // for a compiler-rt object to put in it.
1934 try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} });
1935 comp.job_queued_compiler_rt_obj = true;
19351936 }
19361937 }
19371938 if (needs_c_symbols) {
......@@ -2021,6 +2022,7 @@ pub fn destroy(self: *Compilation) void {
20212022}
20222023
20232024pub fn clearMiscFailures(comp: *Compilation) void {
2025 comp.alloc_failure_occurred = false;
20242026 for (comp.misc_failures.values()) |*value| {
20252027 value.deinit(comp.gpa);
20262028 }
......@@ -2533,8 +2535,10 @@ pub fn makeBinFileWritable(self: *Compilation) !void {
25332535 return self.bin_file.makeWritable();
25342536}
25352537
2538/// This function is temporally single-threaded.
25362539pub fn totalErrorCount(self: *Compilation) usize {
2537 var total: usize = self.failed_c_objects.count() + self.misc_failures.count();
2540 var total: usize = self.failed_c_objects.count() + self.misc_failures.count() +
2541 @boolToInt(self.alloc_failure_occurred);
25382542
25392543 if (self.bin_file.options.module) |module| {
25402544 total += module.failed_exports.count();
......@@ -2591,6 +2595,7 @@ pub fn totalErrorCount(self: *Compilation) usize {
25912595 return total;
25922596}
25932597
2598/// This function is temporally single-threaded.
25942599pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
25952600 var arena = std.heap.ArenaAllocator.init(self.gpa);
25962601 errdefer arena.deinit();
......@@ -2623,6 +2628,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
26232628 for (self.misc_failures.values()) |*value| {
26242629 try AllErrors.addPlainWithChildren(&arena, &errors, value.msg, value.children);
26252630 }
2631 if (self.alloc_failure_occurred) {
2632 try AllErrors.addPlain(&arena, &errors, "memory allocation failure");
2633 }
26262634 if (self.bin_file.options.module) |module| {
26272635 {
26282636 var it = module.failed_files.iterator();
......@@ -2737,9 +2745,15 @@ pub fn performAllTheWork(
27372745 var embed_file_prog_node = main_progress_node.start("Detect @embedFile updates", comp.embed_file_work_queue.count);
27382746 defer embed_file_prog_node.end();
27392747
2748 // +1 for the link step
2749 var compiler_rt_prog_node = main_progress_node.start("compiler_rt", compiler_rt.sources.len + 1);
2750 defer compiler_rt_prog_node.end();
2751
27402752 comp.work_queue_wait_group.reset();
27412753 defer comp.work_queue_wait_group.wait();
27422754
2755 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;
2756
27432757 {
27442758 const astgen_frame = tracy.namedFrame("astgen");
27452759 defer astgen_frame.end();
......@@ -2782,9 +2796,28 @@ pub fn performAllTheWork(
27822796 comp, c_object, &c_obj_prog_node, &comp.work_queue_wait_group,
27832797 });
27842798 }
2799
2800 if (comp.job_queued_compiler_rt_lib) {
2801 comp.job_queued_compiler_rt_lib = false;
2802
2803 if (use_stage1) {
2804 // stage1 LLVM backend uses the global context and thus cannot be used in
2805 // a multi-threaded context.
2806 buildCompilerRtOneShot(comp, .Lib, &comp.compiler_rt_lib);
2807 } else {
2808 comp.work_queue_wait_group.start();
2809 try comp.thread_pool.spawn(workerBuildCompilerRtLib, .{
2810 comp, &compiler_rt_prog_node, &comp.work_queue_wait_group,
2811 });
2812 }
2813 }
2814
2815 if (comp.job_queued_compiler_rt_obj) {
2816 comp.job_queued_compiler_rt_obj = false;
2817 buildCompilerRtOneShot(comp, .Obj, &comp.compiler_rt_obj);
2818 }
27852819 }
27862820
2787 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;
27882821 if (!use_stage1) {
27892822 const outdated_and_deleted_decls_frame = tracy.namedFrame("outdated_and_deleted_decls");
27902823 defer outdated_and_deleted_decls_frame.end();
......@@ -2997,7 +3030,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
29973030 module.semaPkg(pkg) catch |err| switch (err) {
29983031 error.CurrentWorkingDirectoryUnlinked,
29993032 error.Unexpected,
3000 => try comp.setMiscFailure(
3033 => comp.lockAndSetMiscFailure(
30013034 .analyze_pkg,
30023035 "unexpected problem analyzing package '{s}'",
30033036 .{pkg.root_src_path},
......@@ -3012,7 +3045,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30123045
30133046 glibc.buildCRTFile(comp, crt_file) catch |err| {
30143047 // TODO Surface more error details.
3015 try comp.setMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{
3048 comp.lockAndSetMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{
30163049 @errorName(err),
30173050 });
30183051 };
......@@ -3023,7 +3056,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30233056
30243057 glibc.buildSharedObjects(comp) catch |err| {
30253058 // TODO Surface more error details.
3026 try comp.setMiscFailure(
3059 comp.lockAndSetMiscFailure(
30273060 .glibc_shared_objects,
30283061 "unable to build glibc shared objects: {s}",
30293062 .{@errorName(err)},
......@@ -3036,7 +3069,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30363069
30373070 musl.buildCRTFile(comp, crt_file) catch |err| {
30383071 // TODO Surface more error details.
3039 try comp.setMiscFailure(
3072 comp.lockAndSetMiscFailure(
30403073 .musl_crt_file,
30413074 "unable to build musl CRT file: {s}",
30423075 .{@errorName(err)},
......@@ -3049,7 +3082,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30493082
30503083 mingw.buildCRTFile(comp, crt_file) catch |err| {
30513084 // TODO Surface more error details.
3052 try comp.setMiscFailure(
3085 comp.lockAndSetMiscFailure(
30533086 .mingw_crt_file,
30543087 "unable to build mingw-w64 CRT file: {s}",
30553088 .{@errorName(err)},
......@@ -3063,7 +3096,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30633096 const link_lib = comp.bin_file.options.system_libs.keys()[index];
30643097 mingw.buildImportLib(comp, link_lib) catch |err| {
30653098 // TODO Surface more error details.
3066 try comp.setMiscFailure(
3099 comp.lockAndSetMiscFailure(
30673100 .windows_import_lib,
30683101 "unable to generate DLL import .lib file: {s}",
30693102 .{@errorName(err)},
......@@ -3076,7 +3109,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30763109
30773110 libunwind.buildStaticLib(comp) catch |err| {
30783111 // TODO Surface more error details.
3079 try comp.setMiscFailure(
3112 comp.lockAndSetMiscFailure(
30803113 .libunwind,
30813114 "unable to build libunwind: {s}",
30823115 .{@errorName(err)},
......@@ -3089,7 +3122,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30893122
30903123 libcxx.buildLibCXX(comp) catch |err| {
30913124 // TODO Surface more error details.
3092 try comp.setMiscFailure(
3125 comp.lockAndSetMiscFailure(
30933126 .libcxx,
30943127 "unable to build libcxx: {s}",
30953128 .{@errorName(err)},
......@@ -3102,7 +3135,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31023135
31033136 libcxx.buildLibCXXABI(comp) catch |err| {
31043137 // TODO Surface more error details.
3105 try comp.setMiscFailure(
3138 comp.lockAndSetMiscFailure(
31063139 .libcxxabi,
31073140 "unable to build libcxxabi: {s}",
31083141 .{@errorName(err)},
......@@ -3115,7 +3148,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31153148
31163149 libtsan.buildTsan(comp) catch |err| {
31173150 // TODO Surface more error details.
3118 try comp.setMiscFailure(
3151 comp.lockAndSetMiscFailure(
31193152 .libtsan,
31203153 "unable to build TSAN library: {s}",
31213154 .{@errorName(err)},
......@@ -3128,49 +3161,13 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31283161
31293162 wasi_libc.buildCRTFile(comp, crt_file) catch |err| {
31303163 // TODO Surface more error details.
3131 try comp.setMiscFailure(
3164 comp.lockAndSetMiscFailure(
31323165 .wasi_libc_crt_file,
31333166 "unable to build WASI libc CRT file: {s}",
31343167 .{@errorName(err)},
31353168 );
31363169 };
31373170 },
3138 .compiler_rt_lib => {
3139 const named_frame = tracy.namedFrame("compiler_rt_lib");
3140 defer named_frame.end();
3141
3142 compiler_rt.buildCompilerRtLib(
3143 comp,
3144 &comp.compiler_rt_lib,
3145 ) catch |err| switch (err) {
3146 error.OutOfMemory => return error.OutOfMemory,
3147 error.SubCompilationFailed => return, // error reported already
3148 else => try comp.setMiscFailure(
3149 .compiler_rt,
3150 "unable to build compiler_rt: {s}",
3151 .{@errorName(err)},
3152 ),
3153 };
3154 },
3155 .compiler_rt_obj => {
3156 const named_frame = tracy.namedFrame("compiler_rt_obj");
3157 defer named_frame.end();
3158
3159 comp.buildOutputFromZig(
3160 "compiler_rt.zig",
3161 .Obj,
3162 &comp.compiler_rt_obj,
3163 .compiler_rt,
3164 ) catch |err| switch (err) {
3165 error.OutOfMemory => return error.OutOfMemory,
3166 error.SubCompilationFailed => return, // error reported already
3167 else => try comp.setMiscFailure(
3168 .compiler_rt,
3169 "unable to build compiler_rt: {s}",
3170 .{@errorName(err)},
3171 ),
3172 };
3173 },
31743171 .libssp => {
31753172 const named_frame = tracy.namedFrame("libssp");
31763173 defer named_frame.end();
......@@ -3183,7 +3180,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31833180 ) catch |err| switch (err) {
31843181 error.OutOfMemory => return error.OutOfMemory,
31853182 error.SubCompilationFailed => return, // error reported already
3186 else => try comp.setMiscFailure(
3183 else => comp.lockAndSetMiscFailure(
31873184 .libssp,
31883185 "unable to build libssp: {s}",
31893186 .{@errorName(err)},
......@@ -3202,7 +3199,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
32023199 ) catch |err| switch (err) {
32033200 error.OutOfMemory => return error.OutOfMemory,
32043201 error.SubCompilationFailed => return, // error reported already
3205 else => try comp.setMiscFailure(
3202 else => comp.lockAndSetMiscFailure(
32063203 .zig_libc,
32073204 "unable to build zig's multitarget libc: {s}",
32083205 .{@errorName(err)},
......@@ -3306,11 +3303,7 @@ fn workerUpdateBuiltinZigFile(
33063303
33073304 comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{
33083305 dir_path, @errorName(err),
3309 }) catch |oom| switch (oom) {
3310 error.OutOfMemory => log.err("unable to write builtin.zig to {s}: {s}", .{
3311 dir_path, @errorName(err),
3312 }),
3313 };
3306 });
33143307 };
33153308}
33163309
......@@ -3524,6 +3517,38 @@ fn workerUpdateCObject(
35243517 };
35253518}
35263519
3520fn buildCompilerRtOneShot(
3521 comp: *Compilation,
3522 output_mode: std.builtin.OutputMode,
3523 out: *?CRTFile,
3524) void {
3525 comp.buildOutputFromZig("compiler_rt.zig", output_mode, out, .compiler_rt) catch |err| switch (err) {
3526 error.SubCompilationFailed => return, // error reported already
3527 else => comp.lockAndSetMiscFailure(
3528 .compiler_rt,
3529 "unable to build compiler_rt: {s}",
3530 .{@errorName(err)},
3531 ),
3532 };
3533}
3534
3535fn workerBuildCompilerRtLib(
3536 comp: *Compilation,
3537 progress_node: *std.Progress.Node,
3538 wg: *WaitGroup,
3539) void {
3540 defer wg.finish();
3541
3542 compiler_rt.buildCompilerRtLib(comp, progress_node) catch |err| switch (err) {
3543 error.SubCompilationFailed => return, // error reported already
3544 else => comp.lockAndSetMiscFailure(
3545 .compiler_rt,
3546 "unable to build compiler_rt: {s}",
3547 .{@errorName(err)},
3548 ),
3549 };
3550}
3551
35273552fn reportRetryableCObjectError(
35283553 comp: *Compilation,
35293554 c_object: *CObject,
......@@ -4622,14 +4647,21 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
46224647 comp.bin_file.options.object_format != .c;
46234648}
46244649
4625fn setMiscFailure(
4650fn setAllocFailure(comp: *Compilation) void {
4651 log.debug("memory allocation failure", .{});
4652 comp.alloc_failure_occurred = true;
4653}
4654
4655/// Assumes that Compilation mutex is locked.
4656/// See also `lockAndSetMiscFailure`.
4657pub fn setMiscFailure(
46264658 comp: *Compilation,
46274659 tag: MiscTask,
46284660 comptime format: []const u8,
46294661 args: anytype,
4630) Allocator.Error!void {
4631 try comp.misc_failures.ensureUnusedCapacity(comp.gpa, 1);
4632 const msg = try std.fmt.allocPrint(comp.gpa, format, args);
4662) void {
4663 comp.misc_failures.ensureUnusedCapacity(comp.gpa, 1) catch return comp.setAllocFailure();
4664 const msg = std.fmt.allocPrint(comp.gpa, format, args) catch return comp.setAllocFailure();
46334665 const gop = comp.misc_failures.getOrPutAssumeCapacity(tag);
46344666 if (gop.found_existing) {
46354667 gop.value_ptr.deinit(comp.gpa);
......@@ -4637,6 +4669,19 @@ fn setMiscFailure(
46374669 gop.value_ptr.* = .{ .msg = msg };
46384670}
46394671
4672/// See also `setMiscFailure`.
4673pub fn lockAndSetMiscFailure(
4674 comp: *Compilation,
4675 tag: MiscTask,
4676 comptime format: []const u8,
4677 args: anytype,
4678) void {
4679 comp.mutex.lock();
4680 defer comp.mutex.unlock();
4681
4682 return setMiscFailure(comp, tag, format, args);
4683}
4684
46404685pub fn dump_argv(argv: []const []const u8) void {
46414686 for (argv[0 .. argv.len - 1]) |arg| {
46424687 std.debug.print("{s} ", .{arg});
......@@ -4896,7 +4941,7 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void {
48964941 }
48974942}
48984943
4899pub fn buildOutputFromZig(
4944fn buildOutputFromZig(
49004945 comp: *Compilation,
49014946 src_basename: []const u8,
49024947 output_mode: std.builtin.OutputMode,
......@@ -4913,15 +4958,7 @@ pub fn buildOutputFromZig(
49134958 .root_src_path = src_basename,
49144959 };
49154960 defer main_pkg.deinitTable(comp.gpa);
4916
4917 const root_name = root_name: {
4918 const basename = if (std.fs.path.dirname(src_basename)) |dirname|
4919 src_basename[dirname.len + 1 ..]
4920 else
4921 src_basename;
4922 const root_name = basename[0 .. basename.len - std.fs.path.extension(basename).len];
4923 break :root_name root_name;
4924 };
4961 const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];
49254962 const target = comp.getTarget();
49264963 const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{
49274964 .root_name = root_name,
src/ThreadPool.zig+49-32
......@@ -1,6 +1,7 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const ThreadPool = @This();
4const WaitGroup = @import("WaitGroup.zig");
45
56mutex: std.Thread.Mutex = .{},
67cond: std.Thread.Condition = .{},
......@@ -19,8 +20,8 @@ const RunProto = switch (builtin.zig_backend) {
1920 else => *const fn (*Runnable) void,
2021};
2122
22pub fn init(self: *ThreadPool, allocator: std.mem.Allocator) !void {
23 self.* = .{
23pub fn init(pool: *ThreadPool, allocator: std.mem.Allocator) !void {
24 pool.* = .{
2425 .allocator = allocator,
2526 .threads = &[_]std.Thread{},
2627 };
......@@ -30,48 +31,48 @@ pub fn init(self: *ThreadPool, allocator: std.mem.Allocator) !void {
3031 }
3132
3233 const thread_count = std.math.max(1, std.Thread.getCpuCount() catch 1);
33 self.threads = try allocator.alloc(std.Thread, thread_count);
34 errdefer allocator.free(self.threads);
34 pool.threads = try allocator.alloc(std.Thread, thread_count);
35 errdefer allocator.free(pool.threads);
3536
3637 // kill and join any threads we spawned previously on error.
3738 var spawned: usize = 0;
38 errdefer self.join(spawned);
39 errdefer pool.join(spawned);
3940
40 for (self.threads) |*thread| {
41 thread.* = try std.Thread.spawn(.{}, worker, .{self});
41 for (pool.threads) |*thread| {
42 thread.* = try std.Thread.spawn(.{}, worker, .{pool});
4243 spawned += 1;
4344 }
4445}
4546
46pub fn deinit(self: *ThreadPool) void {
47 self.join(self.threads.len); // kill and join all threads.
48 self.* = undefined;
47pub fn deinit(pool: *ThreadPool) void {
48 pool.join(pool.threads.len); // kill and join all threads.
49 pool.* = undefined;
4950}
5051
51fn join(self: *ThreadPool, spawned: usize) void {
52fn join(pool: *ThreadPool, spawned: usize) void {
5253 if (builtin.single_threaded) {
5354 return;
5455 }
5556
5657 {
57 self.mutex.lock();
58 defer self.mutex.unlock();
58 pool.mutex.lock();
59 defer pool.mutex.unlock();
5960
6061 // ensure future worker threads exit the dequeue loop
61 self.is_running = false;
62 pool.is_running = false;
6263 }
6364
6465 // wake up any sleeping threads (this can be done outside the mutex)
6566 // then wait for all the threads we know are spawned to complete.
66 self.cond.broadcast();
67 for (self.threads[0..spawned]) |thread| {
67 pool.cond.broadcast();
68 for (pool.threads[0..spawned]) |thread| {
6869 thread.join();
6970 }
7071
71 self.allocator.free(self.threads);
72 pool.allocator.free(pool.threads);
7273}
7374
74pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void {
75pub fn spawn(pool: *ThreadPool, comptime func: anytype, args: anytype) !void {
7576 if (builtin.single_threaded) {
7677 @call(.{}, func, args);
7778 return;
......@@ -98,41 +99,57 @@ pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void {
9899 };
99100
100101 {
101 self.mutex.lock();
102 defer self.mutex.unlock();
102 pool.mutex.lock();
103 defer pool.mutex.unlock();
103104
104 const closure = try self.allocator.create(Closure);
105 const closure = try pool.allocator.create(Closure);
105106 closure.* = .{
106107 .arguments = args,
107 .pool = self,
108 .pool = pool,
108109 };
109110
110 self.run_queue.prepend(&closure.run_node);
111 pool.run_queue.prepend(&closure.run_node);
111112 }
112113
113114 // Notify waiting threads outside the lock to try and keep the critical section small.
114 self.cond.signal();
115 pool.cond.signal();
115116}
116117
117fn worker(self: *ThreadPool) void {
118 self.mutex.lock();
119 defer self.mutex.unlock();
118fn worker(pool: *ThreadPool) void {
119 pool.mutex.lock();
120 defer pool.mutex.unlock();
120121
121122 while (true) {
122 while (self.run_queue.popFirst()) |run_node| {
123 while (pool.run_queue.popFirst()) |run_node| {
123124 // Temporarily unlock the mutex in order to execute the run_node
124 self.mutex.unlock();
125 defer self.mutex.lock();
125 pool.mutex.unlock();
126 defer pool.mutex.lock();
126127
127128 const runFn = run_node.data.runFn;
128129 runFn(&run_node.data);
129130 }
130131
131132 // Stop executing instead of waiting if the thread pool is no longer running.
132 if (self.is_running) {
133 self.cond.wait(&self.mutex);
133 if (pool.is_running) {
134 pool.cond.wait(&pool.mutex);
134135 } else {
135136 break;
136137 }
137138 }
138139}
140
141pub fn waitAndWork(pool: *ThreadPool, wait_group: *WaitGroup) void {
142 while (!wait_group.isDone()) {
143 if (blk: {
144 pool.mutex.lock();
145 defer pool.mutex.unlock();
146 break :blk pool.run_queue.popFirst();
147 }) |run_node| {
148 run_node.data.runFn(&run_node.data);
149 continue;
150 }
151
152 wait_group.wait();
153 return;
154 }
155}
src/WaitGroup.zig+7
......@@ -37,3 +37,10 @@ pub fn reset(self: *WaitGroup) void {
3737 self.state.store(0, .Monotonic);
3838 self.event.reset();
3939}
40
41pub fn isDone(wg: *WaitGroup) bool {
42 const state = wg.state.load(.Acquire);
43 assert(state & is_waiting == 0);
44
45 return (state / one_pending) == 0;
46}
src/compiler_rt.zig+357-280
......@@ -12,316 +12,393 @@ const Compilation = @import("Compilation.zig");
1212const CRTFile = Compilation.CRTFile;
1313const LinkObject = Compilation.LinkObject;
1414const Package = @import("Package.zig");
15const WaitGroup = @import("WaitGroup.zig");
1516
16pub fn buildCompilerRtLib(comp: *Compilation, compiler_rt_lib: *?CRTFile) !void {
17 const tracy_trace = trace(@src());
18 defer tracy_trace.end();
19
17pub fn buildCompilerRtLib(comp: *Compilation, progress_node: *std.Progress.Node) !void {
2018 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
2119 defer arena_allocator.deinit();
2220 const arena = arena_allocator.allocator();
2321
2422 const target = comp.getTarget();
2523
26 // Use the global cache directory.
27 var cache_parent: Cache = .{
28 .gpa = comp.gpa,
29 .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}),
24 const root_name = "compiler_rt";
25 const basename = try std.zig.binNameAlloc(arena, .{
26 .root_name = root_name,
27 .target = target,
28 .output_mode = .Lib,
29 });
30
31 var link_objects: [sources.len]LinkObject = undefined;
32 var crt_files = [1]?CRTFile{null} ** sources.len;
33 defer deinitCrtFiles(comp, crt_files);
34
35 {
36 var wg: WaitGroup = .{};
37 defer comp.thread_pool.waitAndWork(&wg);
38
39 for (sources) |source, i| {
40 wg.start();
41 try comp.thread_pool.spawn(workerBuildObject, .{
42 comp, progress_node, &wg, source, &crt_files[i],
43 });
44 }
45 }
46
47 for (link_objects) |*link_object, i| {
48 link_object.* = .{
49 .path = crt_files[i].?.full_object_path,
50 };
51 }
52
53 var link_progress_node = progress_node.start("link", 0);
54 link_progress_node.activate();
55 defer link_progress_node.end();
56
57 // TODO: This is extracted into a local variable to work around a stage1 miscompilation.
58 const emit_bin = Compilation.EmitLoc{
59 .directory = null, // Put it in the cache directory.
60 .basename = basename,
61 };
62 const sub_compilation = try Compilation.create(comp.gpa, .{
63 .local_cache_directory = comp.global_cache_directory,
64 .global_cache_directory = comp.global_cache_directory,
65 .zig_lib_directory = comp.zig_lib_directory,
66 .cache_mode = .whole,
67 .target = target,
68 .root_name = root_name,
69 .main_pkg = null,
70 .output_mode = .Lib,
71 .link_mode = .Static,
72 .thread_pool = comp.thread_pool,
73 .libc_installation = comp.bin_file.options.libc_installation,
74 .emit_bin = emit_bin,
75 .optimize_mode = comp.compilerRtOptMode(),
76 .want_sanitize_c = false,
77 .want_stack_check = false,
78 .want_red_zone = comp.bin_file.options.red_zone,
79 .omit_frame_pointer = comp.bin_file.options.omit_frame_pointer,
80 .want_valgrind = false,
81 .want_tsan = false,
82 .want_pic = comp.bin_file.options.pic,
83 .want_pie = comp.bin_file.options.pie,
84 .want_lto = comp.bin_file.options.lto,
85 .emit_h = null,
86 .strip = comp.compilerRtStrip(),
87 .is_native_os = comp.bin_file.options.is_native_os,
88 .is_native_abi = comp.bin_file.options.is_native_abi,
89 .self_exe_path = comp.self_exe_path,
90 .link_objects = &link_objects,
91 .verbose_cc = comp.verbose_cc,
92 .verbose_link = comp.bin_file.options.verbose_link,
93 .verbose_air = comp.verbose_air,
94 .verbose_llvm_ir = comp.verbose_llvm_ir,
95 .verbose_cimport = comp.verbose_cimport,
96 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
97 .clang_passthrough_mode = comp.clang_passthrough_mode,
98 .skip_linker_dependencies = true,
99 .parent_compilation_link_libc = comp.bin_file.options.link_libc,
100 });
101 defer sub_compilation.destroy();
102
103 try sub_compilation.updateSubCompilation();
104
105 assert(comp.compiler_rt_lib == null);
106 comp.compiler_rt_lib = .{
107 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(comp.gpa, &[_][]const u8{
108 sub_compilation.bin_file.options.emit.?.sub_path,
109 }),
110 .lock = sub_compilation.bin_file.toOwnedLock(),
30111 };
31 defer cache_parent.manifest_dir.close();
112}
32113
33 var cache = cache_parent.obtain();
34 defer cache.deinit();
114fn deinitCrtFiles(comp: *Compilation, crt_files: [sources.len]?CRTFile) void {
115 const gpa = comp.gpa;
35116
36 cache.hash.add(sources.len);
37 for (sources) |source| {
38 const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{source});
39 _ = try cache.addFile(full_path, null);
117 for (crt_files) |opt_crt_file| {
118 var crt_file = opt_crt_file orelse continue;
119 crt_file.deinit(gpa);
40120 }
121}
41122
42 cache.hash.addBytes(build_options.version);
43 cache.hash.addBytes(comp.zig_lib_directory.path orelse ".");
44 cache.hash.add(target.cpu.arch);
45 cache.hash.add(target.os.tag);
46 cache.hash.add(target.abi);
123fn workerBuildObject(
124 comp: *Compilation,
125 progress_node: *std.Progress.Node,
126 wg: *WaitGroup,
127 src_basename: []const u8,
128 out: *?CRTFile,
129) void {
130 defer wg.finish();
47131
48 const hit = try cache.hit();
49 const digest = cache.final();
50 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
132 var obj_progress_node = progress_node.start(src_basename, 0);
133 obj_progress_node.activate();
134 defer obj_progress_node.end();
51135
52 var o_directory: Compilation.Directory = .{
53 .handle = try comp.global_cache_directory.handle.makeOpenPath(o_sub_path, .{}),
54 .path = try std.fs.path.join(arena, &[_][]const u8{ comp.global_cache_directory.path.?, o_sub_path }),
136 buildObject(comp, src_basename, out) catch |err| switch (err) {
137 error.SubCompilationFailed => return, // error reported already
138 else => comp.lockAndSetMiscFailure(
139 .compiler_rt,
140 "unable to build compiler_rt: {s}",
141 .{@errorName(err)},
142 ),
55143 };
56 defer o_directory.handle.close();
144}
57145
58 const ok_basename = "ok";
59 const actual_hit = if (hit) blk: {
60 o_directory.handle.access(ok_basename, .{}) catch |err| switch (err) {
61 error.FileNotFound => break :blk false,
62 else => |e| return e,
63 };
64 break :blk true;
65 } else false;
146fn buildObject(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void {
147 const gpa = comp.gpa;
66148
67 const root_name = "compiler_rt";
68 const basename = try std.zig.binNameAlloc(arena, .{
149 var root_src_path_buf: [64]u8 = undefined;
150 const root_src_path = std.fmt.bufPrint(
151 &root_src_path_buf,
152 "compiler_rt" ++ std.fs.path.sep_str ++ "{s}",
153 .{src_basename},
154 ) catch unreachable;
155
156 var main_pkg: Package = .{
157 .root_src_directory = comp.zig_lib_directory,
158 .root_src_path = root_src_path,
159 };
160 defer main_pkg.deinitTable(gpa);
161 const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];
162 const target = comp.getTarget();
163 const output_mode: std.builtin.OutputMode = .Obj;
164 const bin_basename = try std.zig.binNameAlloc(gpa, .{
69165 .root_name = root_name,
70166 .target = target,
71 .output_mode = .Lib,
167 .output_mode = output_mode,
72168 });
169 defer gpa.free(bin_basename);
73170
74 if (!actual_hit) {
75 var progress: std.Progress = .{ .dont_print_on_dumb = true };
76 var progress_node = progress.start("Compile Compiler-RT", sources.len + 1);
77 defer progress_node.end();
78 if (comp.color == .off) progress.terminal = null;
79
80 progress_node.activate();
171 const emit_bin = Compilation.EmitLoc{
172 .directory = null, // Put it in the cache directory.
173 .basename = bin_basename,
174 };
175 const sub_compilation = try Compilation.create(gpa, .{
176 .global_cache_directory = comp.global_cache_directory,
177 .local_cache_directory = comp.global_cache_directory,
178 .zig_lib_directory = comp.zig_lib_directory,
179 .cache_mode = .whole,
180 .target = target,
181 .root_name = root_name,
182 .main_pkg = &main_pkg,
183 .output_mode = output_mode,
184 .thread_pool = comp.thread_pool,
185 .libc_installation = comp.bin_file.options.libc_installation,
186 .emit_bin = emit_bin,
187 .optimize_mode = comp.compilerRtOptMode(),
188 .link_mode = .Static,
189 .want_sanitize_c = false,
190 .want_stack_check = false,
191 .want_red_zone = comp.bin_file.options.red_zone,
192 .omit_frame_pointer = comp.bin_file.options.omit_frame_pointer,
193 .want_valgrind = false,
194 .want_tsan = false,
195 .want_pic = comp.bin_file.options.pic,
196 .want_pie = comp.bin_file.options.pie,
197 .emit_h = null,
198 .strip = comp.compilerRtStrip(),
199 .is_native_os = comp.bin_file.options.is_native_os,
200 .is_native_abi = comp.bin_file.options.is_native_abi,
201 .self_exe_path = comp.self_exe_path,
202 .verbose_cc = comp.verbose_cc,
203 .verbose_link = comp.bin_file.options.verbose_link,
204 .verbose_air = comp.verbose_air,
205 .verbose_llvm_ir = comp.verbose_llvm_ir,
206 .verbose_cimport = comp.verbose_cimport,
207 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
208 .clang_passthrough_mode = comp.clang_passthrough_mode,
209 .skip_linker_dependencies = true,
210 .parent_compilation_link_libc = comp.bin_file.options.link_libc,
211 });
212 defer sub_compilation.destroy();
81213
82 var link_objects: [sources.len]LinkObject = undefined;
83 for (sources) |source, i| {
84 var obj_progress_node = progress_node.start(source, 0);
85 obj_progress_node.activate();
86 defer obj_progress_node.end();
214 try sub_compilation.update();
215 // Look for compilation errors in this sub_compilation.
216 var keep_errors = false;
217 var errors = try sub_compilation.getAllErrorsAlloc();
218 defer if (!keep_errors) errors.deinit(sub_compilation.gpa);
87219
88 var tmp_crt_file: ?CRTFile = null;
89 defer if (tmp_crt_file) |*crt| crt.deinit(comp.gpa);
90 try comp.buildOutputFromZig(source, .Obj, &tmp_crt_file, .compiler_rt);
91 link_objects[i] = .{
92 .path = try arena.dupe(u8, tmp_crt_file.?.full_object_path),
93 .must_link = true,
94 };
95 }
220 if (errors.list.len != 0) {
221 const misc_task_tag: Compilation.MiscTask = .compiler_rt;
96222
97 var lib_progress_node = progress_node.start(root_name, 0);
98 lib_progress_node.activate();
99 defer lib_progress_node.end();
223 comp.mutex.lock();
224 defer comp.mutex.unlock();
100225
101 // TODO: This is extracted into a local variable to work around a stage1 miscompilation.
102 const emit_bin = Compilation.EmitLoc{
103 .directory = o_directory, // Put it in the cache directory.
104 .basename = basename,
105 };
106 const sub_compilation = try Compilation.create(comp.gpa, .{
107 .local_cache_directory = comp.global_cache_directory,
108 .global_cache_directory = comp.global_cache_directory,
109 .zig_lib_directory = comp.zig_lib_directory,
110 .cache_mode = .whole,
111 .target = target,
112 .root_name = root_name,
113 .main_pkg = null,
114 .output_mode = .Lib,
115 .link_mode = .Static,
116 .thread_pool = comp.thread_pool,
117 .libc_installation = comp.bin_file.options.libc_installation,
118 .emit_bin = emit_bin,
119 .optimize_mode = comp.compilerRtOptMode(),
120 .want_sanitize_c = false,
121 .want_stack_check = false,
122 .want_red_zone = comp.bin_file.options.red_zone,
123 .omit_frame_pointer = comp.bin_file.options.omit_frame_pointer,
124 .want_valgrind = false,
125 .want_tsan = false,
126 .want_pic = comp.bin_file.options.pic,
127 .want_pie = comp.bin_file.options.pie,
128 .want_lto = comp.bin_file.options.lto,
129 .emit_h = null,
130 .strip = comp.compilerRtStrip(),
131 .is_native_os = comp.bin_file.options.is_native_os,
132 .is_native_abi = comp.bin_file.options.is_native_abi,
133 .self_exe_path = comp.self_exe_path,
134 .link_objects = &link_objects,
135 .verbose_cc = comp.verbose_cc,
136 .verbose_link = comp.bin_file.options.verbose_link,
137 .verbose_air = comp.verbose_air,
138 .verbose_llvm_ir = comp.verbose_llvm_ir,
139 .verbose_cimport = comp.verbose_cimport,
140 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
141 .clang_passthrough_mode = comp.clang_passthrough_mode,
142 .skip_linker_dependencies = true,
143 .parent_compilation_link_libc = comp.bin_file.options.link_libc,
226 try comp.misc_failures.ensureUnusedCapacity(gpa, 1);
227 comp.misc_failures.putAssumeCapacityNoClobber(misc_task_tag, .{
228 .msg = try std.fmt.allocPrint(gpa, "sub-compilation of {s} failed", .{
229 @tagName(misc_task_tag),
230 }),
231 .children = errors,
144232 });
145 defer sub_compilation.destroy();
146
147 try sub_compilation.updateSubCompilation();
148
149 if (o_directory.handle.createFile(ok_basename, .{})) |file| {
150 file.close();
151 } else |err| {
152 std.log.warn("compiler-rt lib: failed to mark completion: {s}", .{@errorName(err)});
153 }
233 keep_errors = true;
234 return error.SubCompilationFailed;
154235 }
155236
156 try cache.writeManifest();
157
158 assert(compiler_rt_lib.* == null);
159 compiler_rt_lib.* = .{
160 .full_object_path = try std.fs.path.join(comp.gpa, &[_][]const u8{
161 comp.global_cache_directory.path.?,
162 o_sub_path,
163 basename,
237 assert(out.* == null);
238 out.* = Compilation.CRTFile{
239 .full_object_path = try sub_compilation.bin_file.options.emit.?.directory.join(gpa, &[_][]const u8{
240 sub_compilation.bin_file.options.emit.?.sub_path,
164241 }),
165 .lock = cache.toOwnedLock(),
242 .lock = sub_compilation.bin_file.toOwnedLock(),
166243 };
167244}
168245
169const sources = &[_][]const u8{
170 "compiler_rt/absvdi2.zig",
171 "compiler_rt/absvsi2.zig",
172 "compiler_rt/absvti2.zig",
173 "compiler_rt/adddf3.zig",
174 "compiler_rt/addo.zig",
175 "compiler_rt/addsf3.zig",
176 "compiler_rt/addtf3.zig",
177 "compiler_rt/addxf3.zig",
178 "compiler_rt/arm.zig",
179 "compiler_rt/atomics.zig",
180 "compiler_rt/aulldiv.zig",
181 "compiler_rt/aullrem.zig",
182 "compiler_rt/bswap.zig",
183 "compiler_rt/ceil.zig",
184 "compiler_rt/clear_cache.zig",
185 "compiler_rt/cmp.zig",
186 "compiler_rt/cmpdf2.zig",
187 "compiler_rt/cmpsf2.zig",
188 "compiler_rt/cmptf2.zig",
189 "compiler_rt/cmpxf2.zig",
190 "compiler_rt/cos.zig",
191 "compiler_rt/count0bits.zig",
192 "compiler_rt/divdf3.zig",
193 "compiler_rt/divsf3.zig",
194 "compiler_rt/divtf3.zig",
195 "compiler_rt/divti3.zig",
196 "compiler_rt/divxf3.zig",
197 "compiler_rt/emutls.zig",
198 "compiler_rt/exp.zig",
199 "compiler_rt/exp2.zig",
200 "compiler_rt/extenddftf2.zig",
201 "compiler_rt/extenddfxf2.zig",
202 "compiler_rt/extendhfsf2.zig",
203 "compiler_rt/extendhftf2.zig",
204 "compiler_rt/extendhfxf2.zig",
205 "compiler_rt/extendsfdf2.zig",
206 "compiler_rt/extendsftf2.zig",
207 "compiler_rt/extendsfxf2.zig",
208 "compiler_rt/extendxftf2.zig",
209 "compiler_rt/fabs.zig",
210 "compiler_rt/fixdfdi.zig",
211 "compiler_rt/fixdfsi.zig",
212 "compiler_rt/fixdfti.zig",
213 "compiler_rt/fixhfdi.zig",
214 "compiler_rt/fixhfsi.zig",
215 "compiler_rt/fixhfti.zig",
216 "compiler_rt/fixsfdi.zig",
217 "compiler_rt/fixsfsi.zig",
218 "compiler_rt/fixsfti.zig",
219 "compiler_rt/fixtfdi.zig",
220 "compiler_rt/fixtfsi.zig",
221 "compiler_rt/fixtfti.zig",
222 "compiler_rt/fixunsdfdi.zig",
223 "compiler_rt/fixunsdfsi.zig",
224 "compiler_rt/fixunsdfti.zig",
225 "compiler_rt/fixunshfdi.zig",
226 "compiler_rt/fixunshfsi.zig",
227 "compiler_rt/fixunshfti.zig",
228 "compiler_rt/fixunssfdi.zig",
229 "compiler_rt/fixunssfsi.zig",
230 "compiler_rt/fixunssfti.zig",
231 "compiler_rt/fixunstfdi.zig",
232 "compiler_rt/fixunstfsi.zig",
233 "compiler_rt/fixunstfti.zig",
234 "compiler_rt/fixunsxfdi.zig",
235 "compiler_rt/fixunsxfsi.zig",
236 "compiler_rt/fixunsxfti.zig",
237 "compiler_rt/fixxfdi.zig",
238 "compiler_rt/fixxfsi.zig",
239 "compiler_rt/fixxfti.zig",
240 "compiler_rt/floatdidf.zig",
241 "compiler_rt/floatdihf.zig",
242 "compiler_rt/floatdisf.zig",
243 "compiler_rt/floatditf.zig",
244 "compiler_rt/floatdixf.zig",
245 "compiler_rt/floatsidf.zig",
246 "compiler_rt/floatsihf.zig",
247 "compiler_rt/floatsisf.zig",
248 "compiler_rt/floatsitf.zig",
249 "compiler_rt/floatsixf.zig",
250 "compiler_rt/floattidf.zig",
251 "compiler_rt/floattihf.zig",
252 "compiler_rt/floattisf.zig",
253 "compiler_rt/floattitf.zig",
254 "compiler_rt/floattixf.zig",
255 "compiler_rt/floatundidf.zig",
256 "compiler_rt/floatundihf.zig",
257 "compiler_rt/floatundisf.zig",
258 "compiler_rt/floatunditf.zig",
259 "compiler_rt/floatundixf.zig",
260 "compiler_rt/floatunsidf.zig",
261 "compiler_rt/floatunsihf.zig",
262 "compiler_rt/floatunsisf.zig",
263 "compiler_rt/floatunsitf.zig",
264 "compiler_rt/floatunsixf.zig",
265 "compiler_rt/floatuntidf.zig",
266 "compiler_rt/floatuntihf.zig",
267 "compiler_rt/floatuntisf.zig",
268 "compiler_rt/floatuntitf.zig",
269 "compiler_rt/floatuntixf.zig",
270 "compiler_rt/floor.zig",
271 "compiler_rt/fma.zig",
272 "compiler_rt/fmax.zig",
273 "compiler_rt/fmin.zig",
274 "compiler_rt/fmod.zig",
275 "compiler_rt/gedf2.zig",
276 "compiler_rt/gesf2.zig",
277 "compiler_rt/getf2.zig",
278 "compiler_rt/gexf2.zig",
279 "compiler_rt/int.zig",
280 "compiler_rt/log.zig",
281 "compiler_rt/log10.zig",
282 "compiler_rt/log2.zig",
283 "compiler_rt/modti3.zig",
284 "compiler_rt/muldf3.zig",
285 "compiler_rt/muldi3.zig",
286 "compiler_rt/mulf3.zig",
287 "compiler_rt/mulo.zig",
288 "compiler_rt/mulsf3.zig",
289 "compiler_rt/multf3.zig",
290 "compiler_rt/multi3.zig",
291 "compiler_rt/mulxf3.zig",
292 "compiler_rt/negXf2.zig",
293 "compiler_rt/negXi2.zig",
294 "compiler_rt/negv.zig",
295 "compiler_rt/os_version_check.zig",
296 "compiler_rt/parity.zig",
297 "compiler_rt/popcount.zig",
298 "compiler_rt/round.zig",
299 "compiler_rt/shift.zig",
300 "compiler_rt/sin.zig",
301 "compiler_rt/sincos.zig",
302 "compiler_rt/sqrt.zig",
303 "compiler_rt/stack_probe.zig",
304 "compiler_rt/subdf3.zig",
305 "compiler_rt/subo.zig",
306 "compiler_rt/subsf3.zig",
307 "compiler_rt/subtf3.zig",
308 "compiler_rt/subxf3.zig",
309 "compiler_rt/tan.zig",
310 "compiler_rt/trunc.zig",
311 "compiler_rt/truncdfhf2.zig",
312 "compiler_rt/truncdfsf2.zig",
313 "compiler_rt/truncsfhf2.zig",
314 "compiler_rt/trunctfdf2.zig",
315 "compiler_rt/trunctfhf2.zig",
316 "compiler_rt/trunctfsf2.zig",
317 "compiler_rt/trunctfxf2.zig",
318 "compiler_rt/truncxfdf2.zig",
319 "compiler_rt/truncxfhf2.zig",
320 "compiler_rt/truncxfsf2.zig",
321 "compiler_rt/udivmodti4.zig",
322 "compiler_rt/udivti3.zig",
323 "compiler_rt/umodti3.zig",
324 "compiler_rt/unorddf2.zig",
325 "compiler_rt/unordsf2.zig",
326 "compiler_rt/unordtf2.zig",
246pub const sources = &[_][]const u8{
247 "absvdi2.zig",
248 "absvsi2.zig",
249 "absvti2.zig",
250 "adddf3.zig",
251 "addo.zig",
252 "addsf3.zig",
253 "addtf3.zig",
254 "addxf3.zig",
255 "arm.zig",
256 "atomics.zig",
257 "aulldiv.zig",
258 "aullrem.zig",
259 "bswap.zig",
260 "ceil.zig",
261 "clear_cache.zig",
262 "cmp.zig",
263 "cmpdf2.zig",
264 "cmpsf2.zig",
265 "cmptf2.zig",
266 "cmpxf2.zig",
267 "cos.zig",
268 "count0bits.zig",
269 "divdf3.zig",
270 "divsf3.zig",
271 "divtf3.zig",
272 "divti3.zig",
273 "divxf3.zig",
274 "emutls.zig",
275 "exp.zig",
276 "exp2.zig",
277 "extenddftf2.zig",
278 "extenddfxf2.zig",
279 "extendhfsf2.zig",
280 "extendhftf2.zig",
281 "extendhfxf2.zig",
282 "extendsfdf2.zig",
283 "extendsftf2.zig",
284 "extendsfxf2.zig",
285 "extendxftf2.zig",
286 "fabs.zig",
287 "fixdfdi.zig",
288 "fixdfsi.zig",
289 "fixdfti.zig",
290 "fixhfdi.zig",
291 "fixhfsi.zig",
292 "fixhfti.zig",
293 "fixsfdi.zig",
294 "fixsfsi.zig",
295 "fixsfti.zig",
296 "fixtfdi.zig",
297 "fixtfsi.zig",
298 "fixtfti.zig",
299 "fixunsdfdi.zig",
300 "fixunsdfsi.zig",
301 "fixunsdfti.zig",
302 "fixunshfdi.zig",
303 "fixunshfsi.zig",
304 "fixunshfti.zig",
305 "fixunssfdi.zig",
306 "fixunssfsi.zig",
307 "fixunssfti.zig",
308 "fixunstfdi.zig",
309 "fixunstfsi.zig",
310 "fixunstfti.zig",
311 "fixunsxfdi.zig",
312 "fixunsxfsi.zig",
313 "fixunsxfti.zig",
314 "fixxfdi.zig",
315 "fixxfsi.zig",
316 "fixxfti.zig",
317 "floatdidf.zig",
318 "floatdihf.zig",
319 "floatdisf.zig",
320 "floatditf.zig",
321 "floatdixf.zig",
322 "floatsidf.zig",
323 "floatsihf.zig",
324 "floatsisf.zig",
325 "floatsitf.zig",
326 "floatsixf.zig",
327 "floattidf.zig",
328 "floattihf.zig",
329 "floattisf.zig",
330 "floattitf.zig",
331 "floattixf.zig",
332 "floatundidf.zig",
333 "floatundihf.zig",
334 "floatundisf.zig",
335 "floatunditf.zig",
336 "floatundixf.zig",
337 "floatunsidf.zig",
338 "floatunsihf.zig",
339 "floatunsisf.zig",
340 "floatunsitf.zig",
341 "floatunsixf.zig",
342 "floatuntidf.zig",
343 "floatuntihf.zig",
344 "floatuntisf.zig",
345 "floatuntitf.zig",
346 "floatuntixf.zig",
347 "floor.zig",
348 "fma.zig",
349 "fmax.zig",
350 "fmin.zig",
351 "fmod.zig",
352 "gedf2.zig",
353 "gesf2.zig",
354 "getf2.zig",
355 "gexf2.zig",
356 "int.zig",
357 "log.zig",
358 "log10.zig",
359 "log2.zig",
360 "modti3.zig",
361 "muldf3.zig",
362 "muldi3.zig",
363 "mulf3.zig",
364 "mulo.zig",
365 "mulsf3.zig",
366 "multf3.zig",
367 "multi3.zig",
368 "mulxf3.zig",
369 "negXf2.zig",
370 "negXi2.zig",
371 "negv.zig",
372 "os_version_check.zig",
373 "parity.zig",
374 "popcount.zig",
375 "round.zig",
376 "shift.zig",
377 "sin.zig",
378 "sincos.zig",
379 "sqrt.zig",
380 "stack_probe.zig",
381 "subdf3.zig",
382 "subo.zig",
383 "subsf3.zig",
384 "subtf3.zig",
385 "subxf3.zig",
386 "tan.zig",
387 "trunc.zig",
388 "truncdfhf2.zig",
389 "truncdfsf2.zig",
390 "truncsfhf2.zig",
391 "trunctfdf2.zig",
392 "trunctfhf2.zig",
393 "trunctfsf2.zig",
394 "trunctfxf2.zig",
395 "truncxfdf2.zig",
396 "truncxfhf2.zig",
397 "truncxfsf2.zig",
398 "udivmodti4.zig",
399 "udivti3.zig",
400 "umodti3.zig",
401 "unorddf2.zig",
402 "unordsf2.zig",
403 "unordtf2.zig",
327404};