| author | |
| committer | |
| log | 5cd548e53081428d0e6b4a6b5a305317052c133a |
| tree | 4beb45ef87a73007a11e004a2fc52e35d8a6dc8e |
| parent | b4f3e69342d176ad7a2572cf4fee704094faaada |
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, |
| 93 | 93 | test_evented_io: bool, |
| 94 | 94 | debug_compiler_runtime_libs: bool, |
| 95 | 95 | debug_compile_errors: bool, |
| 96 | job_queued_compiler_rt_lib: bool = false, | |
| 97 | job_queued_compiler_rt_obj: bool = false, | |
| 98 | alloc_failure_occurred: bool = false, | |
| 96 | 99 | |
| 97 | 100 | c_source_files: []const CSourceFile, |
| 98 | 101 | clang_argv: []const []const u8, |
| ... | ... | @@ -130,11 +133,11 @@ libssp_static_lib: ?CRTFile = null, |
| 130 | 133 | /// Populated when we build the libc static library. A Job to build this is placed in the queue |
| 131 | 134 | /// and resolved before calling linker.flush(). |
| 132 | 135 | libc_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(). | |
| 135 | 138 | compiler_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(). | |
| 138 | 141 | compiler_rt_obj: ?CRTFile = null, |
| 139 | 142 | |
| 140 | 143 | glibc_so_files: ?glibc.BuiltSharedObjects = null, |
| ... | ... | @@ -224,8 +227,6 @@ const Job = union(enum) { |
| 224 | 227 | libcxxabi: void, |
| 225 | 228 | libtsan: void, |
| 226 | 229 | libssp: void, |
| 227 | compiler_rt_lib: void, | |
| 228 | compiler_rt_obj: void, | |
| 229 | 230 | /// needed when not linking libc and using LLVM for code generation because it generates |
| 230 | 231 | /// calls to, for example, memcpy and memset. |
| 231 | 232 | zig_libc: void, |
| ... | ... | @@ -1925,13 +1926,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1925 | 1926 | if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) { |
| 1926 | 1927 | if (is_exe_or_dyn_lib) { |
| 1927 | 1928 | 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; | |
| 1929 | 1930 | } else if (options.output_mode != .Obj) { |
| 1930 | 1931 | log.debug("queuing a job to build compiler_rt_obj", .{}); |
| 1931 | 1932 | // If build-obj with -fcompiler-rt is requested, that is handled specially |
| 1932 | 1933 | // elsewhere. In this case we are making a static library, so we ask |
| 1933 | 1934 | // 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; | |
| 1935 | 1936 | } |
| 1936 | 1937 | } |
| 1937 | 1938 | if (needs_c_symbols) { |
| ... | ... | @@ -2021,6 +2022,7 @@ pub fn destroy(self: *Compilation) void { |
| 2021 | 2022 | } |
| 2022 | 2023 | |
| 2023 | 2024 | pub fn clearMiscFailures(comp: *Compilation) void { |
| 2025 | comp.alloc_failure_occurred = false; | |
| 2024 | 2026 | for (comp.misc_failures.values()) |*value| { |
| 2025 | 2027 | value.deinit(comp.gpa); |
| 2026 | 2028 | } |
| ... | ... | @@ -2533,8 +2535,10 @@ pub fn makeBinFileWritable(self: *Compilation) !void { |
| 2533 | 2535 | return self.bin_file.makeWritable(); |
| 2534 | 2536 | } |
| 2535 | 2537 | |
| 2538 | /// This function is temporally single-threaded. | |
| 2536 | 2539 | pub 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); | |
| 2538 | 2542 | |
| 2539 | 2543 | if (self.bin_file.options.module) |module| { |
| 2540 | 2544 | total += module.failed_exports.count(); |
| ... | ... | @@ -2591,6 +2595,7 @@ pub fn totalErrorCount(self: *Compilation) usize { |
| 2591 | 2595 | return total; |
| 2592 | 2596 | } |
| 2593 | 2597 | |
| 2598 | /// This function is temporally single-threaded. | |
| 2594 | 2599 | pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2595 | 2600 | var arena = std.heap.ArenaAllocator.init(self.gpa); |
| 2596 | 2601 | errdefer arena.deinit(); |
| ... | ... | @@ -2623,6 +2628,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2623 | 2628 | for (self.misc_failures.values()) |*value| { |
| 2624 | 2629 | try AllErrors.addPlainWithChildren(&arena, &errors, value.msg, value.children); |
| 2625 | 2630 | } |
| 2631 | if (self.alloc_failure_occurred) { | |
| 2632 | try AllErrors.addPlain(&arena, &errors, "memory allocation failure"); | |
| 2633 | } | |
| 2626 | 2634 | if (self.bin_file.options.module) |module| { |
| 2627 | 2635 | { |
| 2628 | 2636 | var it = module.failed_files.iterator(); |
| ... | ... | @@ -2737,9 +2745,15 @@ pub fn performAllTheWork( |
| 2737 | 2745 | var embed_file_prog_node = main_progress_node.start("Detect @embedFile updates", comp.embed_file_work_queue.count); |
| 2738 | 2746 | defer embed_file_prog_node.end(); |
| 2739 | 2747 | |
| 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 | ||
| 2740 | 2752 | comp.work_queue_wait_group.reset(); |
| 2741 | 2753 | defer comp.work_queue_wait_group.wait(); |
| 2742 | 2754 | |
| 2755 | const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1; | |
| 2756 | ||
| 2743 | 2757 | { |
| 2744 | 2758 | const astgen_frame = tracy.namedFrame("astgen"); |
| 2745 | 2759 | defer astgen_frame.end(); |
| ... | ... | @@ -2782,9 +2796,28 @@ pub fn performAllTheWork( |
| 2782 | 2796 | comp, c_object, &c_obj_prog_node, &comp.work_queue_wait_group, |
| 2783 | 2797 | }); |
| 2784 | 2798 | } |
| 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 | } | |
| 2785 | 2819 | } |
| 2786 | 2820 | |
| 2787 | const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1; | |
| 2788 | 2821 | if (!use_stage1) { |
| 2789 | 2822 | const outdated_and_deleted_decls_frame = tracy.namedFrame("outdated_and_deleted_decls"); |
| 2790 | 2823 | defer outdated_and_deleted_decls_frame.end(); |
| ... | ... | @@ -2997,7 +3030,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 2997 | 3030 | module.semaPkg(pkg) catch |err| switch (err) { |
| 2998 | 3031 | error.CurrentWorkingDirectoryUnlinked, |
| 2999 | 3032 | error.Unexpected, |
| 3000 | => try comp.setMiscFailure( | |
| 3033 | => comp.lockAndSetMiscFailure( | |
| 3001 | 3034 | .analyze_pkg, |
| 3002 | 3035 | "unexpected problem analyzing package '{s}'", |
| 3003 | 3036 | .{pkg.root_src_path}, |
| ... | ... | @@ -3012,7 +3045,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3012 | 3045 | |
| 3013 | 3046 | glibc.buildCRTFile(comp, crt_file) catch |err| { |
| 3014 | 3047 | // 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}", .{ | |
| 3016 | 3049 | @errorName(err), |
| 3017 | 3050 | }); |
| 3018 | 3051 | }; |
| ... | ... | @@ -3023,7 +3056,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3023 | 3056 | |
| 3024 | 3057 | glibc.buildSharedObjects(comp) catch |err| { |
| 3025 | 3058 | // TODO Surface more error details. |
| 3026 | try comp.setMiscFailure( | |
| 3059 | comp.lockAndSetMiscFailure( | |
| 3027 | 3060 | .glibc_shared_objects, |
| 3028 | 3061 | "unable to build glibc shared objects: {s}", |
| 3029 | 3062 | .{@errorName(err)}, |
| ... | ... | @@ -3036,7 +3069,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3036 | 3069 | |
| 3037 | 3070 | musl.buildCRTFile(comp, crt_file) catch |err| { |
| 3038 | 3071 | // TODO Surface more error details. |
| 3039 | try comp.setMiscFailure( | |
| 3072 | comp.lockAndSetMiscFailure( | |
| 3040 | 3073 | .musl_crt_file, |
| 3041 | 3074 | "unable to build musl CRT file: {s}", |
| 3042 | 3075 | .{@errorName(err)}, |
| ... | ... | @@ -3049,7 +3082,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3049 | 3082 | |
| 3050 | 3083 | mingw.buildCRTFile(comp, crt_file) catch |err| { |
| 3051 | 3084 | // TODO Surface more error details. |
| 3052 | try comp.setMiscFailure( | |
| 3085 | comp.lockAndSetMiscFailure( | |
| 3053 | 3086 | .mingw_crt_file, |
| 3054 | 3087 | "unable to build mingw-w64 CRT file: {s}", |
| 3055 | 3088 | .{@errorName(err)}, |
| ... | ... | @@ -3063,7 +3096,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3063 | 3096 | const link_lib = comp.bin_file.options.system_libs.keys()[index]; |
| 3064 | 3097 | mingw.buildImportLib(comp, link_lib) catch |err| { |
| 3065 | 3098 | // TODO Surface more error details. |
| 3066 | try comp.setMiscFailure( | |
| 3099 | comp.lockAndSetMiscFailure( | |
| 3067 | 3100 | .windows_import_lib, |
| 3068 | 3101 | "unable to generate DLL import .lib file: {s}", |
| 3069 | 3102 | .{@errorName(err)}, |
| ... | ... | @@ -3076,7 +3109,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3076 | 3109 | |
| 3077 | 3110 | libunwind.buildStaticLib(comp) catch |err| { |
| 3078 | 3111 | // TODO Surface more error details. |
| 3079 | try comp.setMiscFailure( | |
| 3112 | comp.lockAndSetMiscFailure( | |
| 3080 | 3113 | .libunwind, |
| 3081 | 3114 | "unable to build libunwind: {s}", |
| 3082 | 3115 | .{@errorName(err)}, |
| ... | ... | @@ -3089,7 +3122,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3089 | 3122 | |
| 3090 | 3123 | libcxx.buildLibCXX(comp) catch |err| { |
| 3091 | 3124 | // TODO Surface more error details. |
| 3092 | try comp.setMiscFailure( | |
| 3125 | comp.lockAndSetMiscFailure( | |
| 3093 | 3126 | .libcxx, |
| 3094 | 3127 | "unable to build libcxx: {s}", |
| 3095 | 3128 | .{@errorName(err)}, |
| ... | ... | @@ -3102,7 +3135,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3102 | 3135 | |
| 3103 | 3136 | libcxx.buildLibCXXABI(comp) catch |err| { |
| 3104 | 3137 | // TODO Surface more error details. |
| 3105 | try comp.setMiscFailure( | |
| 3138 | comp.lockAndSetMiscFailure( | |
| 3106 | 3139 | .libcxxabi, |
| 3107 | 3140 | "unable to build libcxxabi: {s}", |
| 3108 | 3141 | .{@errorName(err)}, |
| ... | ... | @@ -3115,7 +3148,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3115 | 3148 | |
| 3116 | 3149 | libtsan.buildTsan(comp) catch |err| { |
| 3117 | 3150 | // TODO Surface more error details. |
| 3118 | try comp.setMiscFailure( | |
| 3151 | comp.lockAndSetMiscFailure( | |
| 3119 | 3152 | .libtsan, |
| 3120 | 3153 | "unable to build TSAN library: {s}", |
| 3121 | 3154 | .{@errorName(err)}, |
| ... | ... | @@ -3128,49 +3161,13 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3128 | 3161 | |
| 3129 | 3162 | wasi_libc.buildCRTFile(comp, crt_file) catch |err| { |
| 3130 | 3163 | // TODO Surface more error details. |
| 3131 | try comp.setMiscFailure( | |
| 3164 | comp.lockAndSetMiscFailure( | |
| 3132 | 3165 | .wasi_libc_crt_file, |
| 3133 | 3166 | "unable to build WASI libc CRT file: {s}", |
| 3134 | 3167 | .{@errorName(err)}, |
| 3135 | 3168 | ); |
| 3136 | 3169 | }; |
| 3137 | 3170 | }, |
| 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 | }, | |
| 3174 | 3171 | .libssp => { |
| 3175 | 3172 | const named_frame = tracy.namedFrame("libssp"); |
| 3176 | 3173 | defer named_frame.end(); |
| ... | ... | @@ -3183,7 +3180,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3183 | 3180 | ) catch |err| switch (err) { |
| 3184 | 3181 | error.OutOfMemory => return error.OutOfMemory, |
| 3185 | 3182 | error.SubCompilationFailed => return, // error reported already |
| 3186 | else => try comp.setMiscFailure( | |
| 3183 | else => comp.lockAndSetMiscFailure( | |
| 3187 | 3184 | .libssp, |
| 3188 | 3185 | "unable to build libssp: {s}", |
| 3189 | 3186 | .{@errorName(err)}, |
| ... | ... | @@ -3202,7 +3199,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3202 | 3199 | ) catch |err| switch (err) { |
| 3203 | 3200 | error.OutOfMemory => return error.OutOfMemory, |
| 3204 | 3201 | error.SubCompilationFailed => return, // error reported already |
| 3205 | else => try comp.setMiscFailure( | |
| 3202 | else => comp.lockAndSetMiscFailure( | |
| 3206 | 3203 | .zig_libc, |
| 3207 | 3204 | "unable to build zig's multitarget libc: {s}", |
| 3208 | 3205 | .{@errorName(err)}, |
| ... | ... | @@ -3306,11 +3303,7 @@ fn workerUpdateBuiltinZigFile( |
| 3306 | 3303 | |
| 3307 | 3304 | comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{ |
| 3308 | 3305 | 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 | }); | |
| 3314 | 3307 | }; |
| 3315 | 3308 | } |
| 3316 | 3309 | |
| ... | ... | @@ -3524,6 +3517,38 @@ fn workerUpdateCObject( |
| 3524 | 3517 | }; |
| 3525 | 3518 | } |
| 3526 | 3519 | |
| 3520 | fn 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 | ||
| 3535 | fn 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 | ||
| 3527 | 3552 | fn reportRetryableCObjectError( |
| 3528 | 3553 | comp: *Compilation, |
| 3529 | 3554 | c_object: *CObject, |
| ... | ... | @@ -4622,14 +4647,21 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { |
| 4622 | 4647 | comp.bin_file.options.object_format != .c; |
| 4623 | 4648 | } |
| 4624 | 4649 | |
| 4625 | fn setMiscFailure( | |
| 4650 | fn 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`. | |
| 4657 | pub fn setMiscFailure( | |
| 4626 | 4658 | comp: *Compilation, |
| 4627 | 4659 | tag: MiscTask, |
| 4628 | 4660 | comptime format: []const u8, |
| 4629 | 4661 | 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(); | |
| 4633 | 4665 | const gop = comp.misc_failures.getOrPutAssumeCapacity(tag); |
| 4634 | 4666 | if (gop.found_existing) { |
| 4635 | 4667 | gop.value_ptr.deinit(comp.gpa); |
| ... | ... | @@ -4637,6 +4669,19 @@ fn setMiscFailure( |
| 4637 | 4669 | gop.value_ptr.* = .{ .msg = msg }; |
| 4638 | 4670 | } |
| 4639 | 4671 | |
| 4672 | /// See also `setMiscFailure`. | |
| 4673 | pub 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 | ||
| 4640 | 4685 | pub fn dump_argv(argv: []const []const u8) void { |
| 4641 | 4686 | for (argv[0 .. argv.len - 1]) |arg| { |
| 4642 | 4687 | std.debug.print("{s} ", .{arg}); |
| ... | ... | @@ -4896,7 +4941,7 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void { |
| 4896 | 4941 | } |
| 4897 | 4942 | } |
| 4898 | 4943 | |
| 4899 | pub fn buildOutputFromZig( | |
| 4944 | fn buildOutputFromZig( | |
| 4900 | 4945 | comp: *Compilation, |
| 4901 | 4946 | src_basename: []const u8, |
| 4902 | 4947 | output_mode: std.builtin.OutputMode, |
| ... | ... | @@ -4913,15 +4958,7 @@ pub fn buildOutputFromZig( |
| 4913 | 4958 | .root_src_path = src_basename, |
| 4914 | 4959 | }; |
| 4915 | 4960 | 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]; | |
| 4925 | 4962 | const target = comp.getTarget(); |
| 4926 | 4963 | const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ |
| 4927 | 4964 | .root_name = root_name, |
src/ThreadPool.zig+49-32| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const ThreadPool = @This(); |
| 4 | const WaitGroup = @import("WaitGroup.zig"); | |
| 4 | 5 | |
| 5 | 6 | mutex: std.Thread.Mutex = .{}, |
| 6 | 7 | cond: std.Thread.Condition = .{}, |
| ... | ... | @@ -19,8 +20,8 @@ const RunProto = switch (builtin.zig_backend) { |
| 19 | 20 | else => *const fn (*Runnable) void, |
| 20 | 21 | }; |
| 21 | 22 | |
| 22 | pub fn init(self: *ThreadPool, allocator: std.mem.Allocator) !void { | |
| 23 | self.* = .{ | |
| 23 | pub fn init(pool: *ThreadPool, allocator: std.mem.Allocator) !void { | |
| 24 | pool.* = .{ | |
| 24 | 25 | .allocator = allocator, |
| 25 | 26 | .threads = &[_]std.Thread{}, |
| 26 | 27 | }; |
| ... | ... | @@ -30,48 +31,48 @@ pub fn init(self: *ThreadPool, allocator: std.mem.Allocator) !void { |
| 30 | 31 | } |
| 31 | 32 | |
| 32 | 33 | 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); | |
| 35 | 36 | |
| 36 | 37 | // kill and join any threads we spawned previously on error. |
| 37 | 38 | var spawned: usize = 0; |
| 38 | errdefer self.join(spawned); | |
| 39 | errdefer pool.join(spawned); | |
| 39 | 40 | |
| 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}); | |
| 42 | 43 | spawned += 1; |
| 43 | 44 | } |
| 44 | 45 | } |
| 45 | 46 | |
| 46 | pub fn deinit(self: *ThreadPool) void { | |
| 47 | self.join(self.threads.len); // kill and join all threads. | |
| 48 | self.* = undefined; | |
| 47 | pub fn deinit(pool: *ThreadPool) void { | |
| 48 | pool.join(pool.threads.len); // kill and join all threads. | |
| 49 | pool.* = undefined; | |
| 49 | 50 | } |
| 50 | 51 | |
| 51 | fn join(self: *ThreadPool, spawned: usize) void { | |
| 52 | fn join(pool: *ThreadPool, spawned: usize) void { | |
| 52 | 53 | if (builtin.single_threaded) { |
| 53 | 54 | return; |
| 54 | 55 | } |
| 55 | 56 | |
| 56 | 57 | { |
| 57 | self.mutex.lock(); | |
| 58 | defer self.mutex.unlock(); | |
| 58 | pool.mutex.lock(); | |
| 59 | defer pool.mutex.unlock(); | |
| 59 | 60 | |
| 60 | 61 | // ensure future worker threads exit the dequeue loop |
| 61 | self.is_running = false; | |
| 62 | pool.is_running = false; | |
| 62 | 63 | } |
| 63 | 64 | |
| 64 | 65 | // wake up any sleeping threads (this can be done outside the mutex) |
| 65 | 66 | // 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| { | |
| 68 | 69 | thread.join(); |
| 69 | 70 | } |
| 70 | 71 | |
| 71 | self.allocator.free(self.threads); | |
| 72 | pool.allocator.free(pool.threads); | |
| 72 | 73 | } |
| 73 | 74 | |
| 74 | pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void { | |
| 75 | pub fn spawn(pool: *ThreadPool, comptime func: anytype, args: anytype) !void { | |
| 75 | 76 | if (builtin.single_threaded) { |
| 76 | 77 | @call(.{}, func, args); |
| 77 | 78 | return; |
| ... | ... | @@ -98,41 +99,57 @@ pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void { |
| 98 | 99 | }; |
| 99 | 100 | |
| 100 | 101 | { |
| 101 | self.mutex.lock(); | |
| 102 | defer self.mutex.unlock(); | |
| 102 | pool.mutex.lock(); | |
| 103 | defer pool.mutex.unlock(); | |
| 103 | 104 | |
| 104 | const closure = try self.allocator.create(Closure); | |
| 105 | const closure = try pool.allocator.create(Closure); | |
| 105 | 106 | closure.* = .{ |
| 106 | 107 | .arguments = args, |
| 107 | .pool = self, | |
| 108 | .pool = pool, | |
| 108 | 109 | }; |
| 109 | 110 | |
| 110 | self.run_queue.prepend(&closure.run_node); | |
| 111 | pool.run_queue.prepend(&closure.run_node); | |
| 111 | 112 | } |
| 112 | 113 | |
| 113 | 114 | // Notify waiting threads outside the lock to try and keep the critical section small. |
| 114 | self.cond.signal(); | |
| 115 | pool.cond.signal(); | |
| 115 | 116 | } |
| 116 | 117 | |
| 117 | fn worker(self: *ThreadPool) void { | |
| 118 | self.mutex.lock(); | |
| 119 | defer self.mutex.unlock(); | |
| 118 | fn worker(pool: *ThreadPool) void { | |
| 119 | pool.mutex.lock(); | |
| 120 | defer pool.mutex.unlock(); | |
| 120 | 121 | |
| 121 | 122 | while (true) { |
| 122 | while (self.run_queue.popFirst()) |run_node| { | |
| 123 | while (pool.run_queue.popFirst()) |run_node| { | |
| 123 | 124 | // 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(); | |
| 126 | 127 | |
| 127 | 128 | const runFn = run_node.data.runFn; |
| 128 | 129 | runFn(&run_node.data); |
| 129 | 130 | } |
| 130 | 131 | |
| 131 | 132 | // 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); | |
| 134 | 135 | } else { |
| 135 | 136 | break; |
| 136 | 137 | } |
| 137 | 138 | } |
| 138 | 139 | } |
| 140 | ||
| 141 | pub 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 { |
| 37 | 37 | self.state.store(0, .Monotonic); |
| 38 | 38 | self.event.reset(); |
| 39 | 39 | } |
| 40 | ||
| 41 | pub 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"); |
| 12 | 12 | const CRTFile = Compilation.CRTFile; |
| 13 | 13 | const LinkObject = Compilation.LinkObject; |
| 14 | 14 | const Package = @import("Package.zig"); |
| 15 | const WaitGroup = @import("WaitGroup.zig"); | |
| 15 | 16 | |
| 16 | pub fn buildCompilerRtLib(comp: *Compilation, compiler_rt_lib: *?CRTFile) !void { | |
| 17 | const tracy_trace = trace(@src()); | |
| 18 | defer tracy_trace.end(); | |
| 19 | ||
| 17 | pub fn buildCompilerRtLib(comp: *Compilation, progress_node: *std.Progress.Node) !void { | |
| 20 | 18 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); |
| 21 | 19 | defer arena_allocator.deinit(); |
| 22 | 20 | const arena = arena_allocator.allocator(); |
| 23 | 21 | |
| 24 | 22 | const target = comp.getTarget(); |
| 25 | 23 | |
| 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(), | |
| 30 | 111 | }; |
| 31 | defer cache_parent.manifest_dir.close(); | |
| 112 | } | |
| 32 | 113 | |
| 33 | var cache = cache_parent.obtain(); | |
| 34 | defer cache.deinit(); | |
| 114 | fn deinitCrtFiles(comp: *Compilation, crt_files: [sources.len]?CRTFile) void { | |
| 115 | const gpa = comp.gpa; | |
| 35 | 116 | |
| 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); | |
| 40 | 120 | } |
| 121 | } | |
| 41 | 122 | |
| 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); | |
| 123 | fn 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(); | |
| 47 | 131 | |
| 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(); | |
| 51 | 135 | |
| 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 | ), | |
| 55 | 143 | }; |
| 56 | defer o_directory.handle.close(); | |
| 144 | } | |
| 57 | 145 | |
| 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; | |
| 146 | fn buildObject(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void { | |
| 147 | const gpa = comp.gpa; | |
| 66 | 148 | |
| 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, .{ | |
| 69 | 165 | .root_name = root_name, |
| 70 | 166 | .target = target, |
| 71 | .output_mode = .Lib, | |
| 167 | .output_mode = output_mode, | |
| 72 | 168 | }); |
| 169 | defer gpa.free(bin_basename); | |
| 73 | 170 | |
| 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(); | |
| 81 | 213 | |
| 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); | |
| 87 | 219 | |
| 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; | |
| 96 | 222 | |
| 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(); | |
| 100 | 225 | |
| 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, | |
| 144 | 232 | }); |
| 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; | |
| 154 | 235 | } |
| 155 | 236 | |
| 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, | |
| 164 | 241 | }), |
| 165 | .lock = cache.toOwnedLock(), | |
| 242 | .lock = sub_compilation.bin_file.toOwnedLock(), | |
| 166 | 243 | }; |
| 167 | 244 | } |
| 168 | 245 | |
| 169 | const 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", | |
| 246 | pub 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", | |
| 327 | 404 | }; |