| author | |
| committer | |
| log | 65ced4a33436fa762de75e22a986ae08a8c0d9cc |
| tree | d19b6b0cdb71a7e0f6bc65379441992753979a4a |
| parent | c36e2bb9802ab4317980a98ea518483010fe2c80 |
(There are no supported backends.)7 files changed, 173 insertions(+), 65 deletions(-)
lib/std/Progress.zig+1-1| ... | ... | @@ -282,7 +282,7 @@ pub const Node = struct { |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | 284 | fn init(free_index: Index, parent: Parent, name: []const u8, estimated_total_items: usize) Node { |
| 285 | assert(parent != .unused); | |
| 285 | assert(parent == .none or @intFromEnum(parent) < node_storage_buffer_len); | |
| 286 | 286 | |
| 287 | 287 | const storage = storageByIndex(free_index); |
| 288 | 288 | storage.* = .{ |
lib/std/Thread/Pool.zig+10-13| ... | ... | @@ -21,11 +21,11 @@ const Runnable = struct { |
| 21 | 21 | runFn: RunProto, |
| 22 | 22 | }; |
| 23 | 23 | |
| 24 | const RunProto = *const fn (*Runnable, id: ?u32) void; | |
| 24 | const RunProto = *const fn (*Runnable, id: ?usize) void; | |
| 25 | 25 | |
| 26 | 26 | pub const Options = struct { |
| 27 | 27 | allocator: std.mem.Allocator, |
| 28 | n_jobs: ?u32 = null, | |
| 28 | n_jobs: ?usize = null, | |
| 29 | 29 | track_ids: bool = false, |
| 30 | 30 | }; |
| 31 | 31 | |
| ... | ... | @@ -109,7 +109,7 @@ pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args |
| 109 | 109 | run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } }, |
| 110 | 110 | wait_group: *WaitGroup, |
| 111 | 111 | |
| 112 | fn runFn(runnable: *Runnable, _: ?u32) void { | |
| 112 | fn runFn(runnable: *Runnable, _: ?usize) void { | |
| 113 | 113 | const run_node: *RunQueue.Node = @fieldParentPtr("data", runnable); |
| 114 | 114 | const closure: *@This() = @alignCast(@fieldParentPtr("run_node", run_node)); |
| 115 | 115 | @call(.auto, func, closure.arguments); |
| ... | ... | @@ -150,7 +150,7 @@ pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args |
| 150 | 150 | /// Runs `func` in the thread pool, calling `WaitGroup.start` beforehand, and |
| 151 | 151 | /// `WaitGroup.finish` after it returns. |
| 152 | 152 | /// |
| 153 | /// The first argument passed to `func` is a dense `u32` thread id, the rest | |
| 153 | /// The first argument passed to `func` is a dense `usize` thread id, the rest | |
| 154 | 154 | /// of the arguments are passed from `args`. Requires the pool to have been |
| 155 | 155 | /// initialized with `.track_ids = true`. |
| 156 | 156 | /// |
| ... | ... | @@ -172,7 +172,7 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar |
| 172 | 172 | run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } }, |
| 173 | 173 | wait_group: *WaitGroup, |
| 174 | 174 | |
| 175 | fn runFn(runnable: *Runnable, id: ?u32) void { | |
| 175 | fn runFn(runnable: *Runnable, id: ?usize) void { | |
| 176 | 176 | const run_node: *RunQueue.Node = @fieldParentPtr("data", runnable); |
| 177 | 177 | const closure: *@This() = @alignCast(@fieldParentPtr("run_node", run_node)); |
| 178 | 178 | @call(.auto, func, .{id.?} ++ closure.arguments); |
| ... | ... | @@ -191,7 +191,7 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar |
| 191 | 191 | pool.mutex.lock(); |
| 192 | 192 | |
| 193 | 193 | const closure = pool.allocator.create(Closure) catch { |
| 194 | const id = pool.ids.getIndex(std.Thread.getCurrentId()); | |
| 194 | const id: ?usize = pool.ids.getIndex(std.Thread.getCurrentId()); | |
| 195 | 195 | pool.mutex.unlock(); |
| 196 | 196 | @call(.auto, func, .{id.?} ++ args); |
| 197 | 197 | wait_group.finish(); |
| ... | ... | @@ -258,7 +258,7 @@ fn worker(pool: *Pool) void { |
| 258 | 258 | pool.mutex.lock(); |
| 259 | 259 | defer pool.mutex.unlock(); |
| 260 | 260 | |
| 261 | const id: ?u32 = if (pool.ids.count() > 0) @intCast(pool.ids.count()) else null; | |
| 261 | const id: ?usize = if (pool.ids.count() > 0) @intCast(pool.ids.count()) else null; | |
| 262 | 262 | if (id) |_| pool.ids.putAssumeCapacityNoClobber(std.Thread.getCurrentId(), {}); |
| 263 | 263 | |
| 264 | 264 | while (true) { |
| ... | ... | @@ -280,15 +280,12 @@ fn worker(pool: *Pool) void { |
| 280 | 280 | } |
| 281 | 281 | |
| 282 | 282 | pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { |
| 283 | var id: ?u32 = null; | |
| 283 | var id: ?usize = null; | |
| 284 | 284 | |
| 285 | 285 | while (!wait_group.isDone()) { |
| 286 | 286 | pool.mutex.lock(); |
| 287 | 287 | if (pool.run_queue.popFirst()) |run_node| { |
| 288 | id = id orelse if (pool.ids.getIndex(std.Thread.getCurrentId())) |index| | |
| 289 | @intCast(index) | |
| 290 | else | |
| 291 | null; | |
| 288 | id = id orelse pool.ids.getIndex(std.Thread.getCurrentId()); | |
| 292 | 289 | pool.mutex.unlock(); |
| 293 | 290 | run_node.data.runFn(&run_node.data, id); |
| 294 | 291 | continue; |
| ... | ... | @@ -300,6 +297,6 @@ pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { |
| 300 | 297 | } |
| 301 | 298 | } |
| 302 | 299 | |
| 303 | pub fn getIdCount(pool: *Pool) u32 { | |
| 300 | pub fn getIdCount(pool: *Pool) usize { | |
| 304 | 301 | return @intCast(1 + pool.threads.len); |
| 305 | 302 | } |
src/Compilation.zig+115-22| ... | ... | @@ -103,6 +103,14 @@ lld_errors: std.ArrayListUnmanaged(LldError) = .{}, |
| 103 | 103 | |
| 104 | 104 | work_queue: std.fifo.LinearFifo(Job, .Dynamic), |
| 105 | 105 | |
| 106 | codegen_work: if (InternPool.single_threaded) void else struct { | |
| 107 | mutex: std.Thread.Mutex, | |
| 108 | cond: std.Thread.Condition, | |
| 109 | queue: std.fifo.LinearFifo(CodegenJob, .Dynamic), | |
| 110 | job_error: ?JobError, | |
| 111 | done: bool, | |
| 112 | }, | |
| 113 | ||
| 106 | 114 | /// These jobs are to invoke the Clang compiler to create an object file, which |
| 107 | 115 | /// gets linked with the Compilation. |
| 108 | 116 | c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic), |
| ... | ... | @@ -362,6 +370,16 @@ const Job = union(enum) { |
| 362 | 370 | windows_import_lib: usize, |
| 363 | 371 | }; |
| 364 | 372 | |
| 373 | const CodegenJob = union(enum) { | |
| 374 | decl: InternPool.DeclIndex, | |
| 375 | func: struct { | |
| 376 | func: InternPool.Index, | |
| 377 | /// This `Air` is owned by the `Job` and allocated with `gpa`. | |
| 378 | /// It must be deinited when the job is processed. | |
| 379 | air: Air, | |
| 380 | }, | |
| 381 | }; | |
| 382 | ||
| 365 | 383 | pub const CObject = struct { |
| 366 | 384 | /// Relative to cwd. Owned by arena. |
| 367 | 385 | src: CSourceFile, |
| ... | ... | @@ -1429,6 +1447,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1429 | 1447 | .emit_llvm_ir = options.emit_llvm_ir, |
| 1430 | 1448 | .emit_llvm_bc = options.emit_llvm_bc, |
| 1431 | 1449 | .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), |
| 1450 | .codegen_work = if (InternPool.single_threaded) {} else .{ | |
| 1451 | .mutex = .{}, | |
| 1452 | .cond = .{}, | |
| 1453 | .queue = std.fifo.LinearFifo(CodegenJob, .Dynamic).init(gpa), | |
| 1454 | .job_error = null, | |
| 1455 | .done = false, | |
| 1456 | }, | |
| 1432 | 1457 | .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa), |
| 1433 | 1458 | .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa), |
| 1434 | 1459 | .astgen_work_queue = std.fifo.LinearFifo(Zcu.File.Index, .Dynamic).init(gpa), |
| ... | ... | @@ -3310,7 +3335,21 @@ pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void { |
| 3310 | 3335 | pub fn performAllTheWork( |
| 3311 | 3336 | comp: *Compilation, |
| 3312 | 3337 | main_progress_node: std.Progress.Node, |
| 3313 | ) error{ TimerUnsupported, OutOfMemory }!void { | |
| 3338 | ) JobError!void { | |
| 3339 | defer if (comp.module) |mod| { | |
| 3340 | mod.sema_prog_node.end(); | |
| 3341 | mod.sema_prog_node = std.Progress.Node.none; | |
| 3342 | mod.codegen_prog_node.end(); | |
| 3343 | mod.codegen_prog_node = std.Progress.Node.none; | |
| 3344 | }; | |
| 3345 | try comp.performAllTheWorkInner(main_progress_node); | |
| 3346 | if (!InternPool.single_threaded) if (comp.codegen_work.job_error) |job_error| return job_error; | |
| 3347 | } | |
| 3348 | ||
| 3349 | fn performAllTheWorkInner( | |
| 3350 | comp: *Compilation, | |
| 3351 | main_progress_node: std.Progress.Node, | |
| 3352 | ) JobError!void { | |
| 3314 | 3353 | // Here we queue up all the AstGen tasks first, followed by C object compilation. |
| 3315 | 3354 | // We wait until the AstGen tasks are all completed before proceeding to the |
| 3316 | 3355 | // (at least for now) single-threaded main work queue. However, C object compilation |
| ... | ... | @@ -3410,16 +3449,20 @@ pub fn performAllTheWork( |
| 3410 | 3449 | mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); |
| 3411 | 3450 | mod.codegen_prog_node = main_progress_node.start("Code Generation", 0); |
| 3412 | 3451 | } |
| 3413 | defer if (comp.module) |mod| { | |
| 3414 | mod.sema_prog_node.end(); | |
| 3415 | mod.sema_prog_node = undefined; | |
| 3416 | mod.codegen_prog_node.end(); | |
| 3417 | mod.codegen_prog_node = undefined; | |
| 3452 | ||
| 3453 | if (!InternPool.single_threaded) comp.thread_pool.spawnWgId(&comp.work_queue_wait_group, codegenThread, .{comp}); | |
| 3454 | defer if (!InternPool.single_threaded) { | |
| 3455 | { | |
| 3456 | comp.codegen_work.mutex.lock(); | |
| 3457 | defer comp.codegen_work.mutex.unlock(); | |
| 3458 | comp.codegen_work.done = true; | |
| 3459 | } | |
| 3460 | comp.codegen_work.cond.signal(); | |
| 3418 | 3461 | }; |
| 3419 | 3462 | |
| 3420 | 3463 | while (true) { |
| 3421 | 3464 | if (comp.work_queue.readItem()) |work_item| { |
| 3422 | try processOneJob(0, comp, work_item, main_progress_node); | |
| 3465 | try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, work_item, main_progress_node); | |
| 3423 | 3466 | continue; |
| 3424 | 3467 | } |
| 3425 | 3468 | if (comp.module) |zcu| { |
| ... | ... | @@ -3447,11 +3490,12 @@ pub fn performAllTheWork( |
| 3447 | 3490 | } |
| 3448 | 3491 | } |
| 3449 | 3492 | |
| 3450 | fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progress.Node) !void { | |
| 3493 | const JobError = Allocator.Error; | |
| 3494 | ||
| 3495 | fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progress.Node) JobError!void { | |
| 3451 | 3496 | switch (job) { |
| 3452 | 3497 | .codegen_decl => |decl_index| { |
| 3453 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; | |
| 3454 | const decl = pt.zcu.declPtr(decl_index); | |
| 3498 | const decl = comp.module.?.declPtr(decl_index); | |
| 3455 | 3499 | |
| 3456 | 3500 | switch (decl.analysis) { |
| 3457 | 3501 | .unreferenced => unreachable, |
| ... | ... | @@ -3461,26 +3505,20 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3461 | 3505 | .sema_failure, |
| 3462 | 3506 | .codegen_failure, |
| 3463 | 3507 | .dependency_failure, |
| 3464 | => return, | |
| 3508 | => {}, | |
| 3465 | 3509 | |
| 3466 | 3510 | .complete => { |
| 3467 | const named_frame = tracy.namedFrame("codegen_decl"); | |
| 3468 | defer named_frame.end(); | |
| 3469 | ||
| 3470 | 3511 | assert(decl.has_tv); |
| 3471 | ||
| 3472 | try pt.linkerUpdateDecl(decl_index); | |
| 3473 | return; | |
| 3512 | try comp.queueCodegenJob(tid, .{ .decl = decl_index }); | |
| 3474 | 3513 | }, |
| 3475 | 3514 | } |
| 3476 | 3515 | }, |
| 3477 | 3516 | .codegen_func => |func| { |
| 3478 | const named_frame = tracy.namedFrame("codegen_func"); | |
| 3479 | defer named_frame.end(); | |
| 3480 | ||
| 3481 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; | |
| 3482 | 3517 | // This call takes ownership of `func.air`. |
| 3483 | try pt.linkerUpdateFunc(func.func, func.air); | |
| 3518 | try comp.queueCodegenJob(tid, .{ .func = .{ | |
| 3519 | .func = func.func, | |
| 3520 | .air = func.air, | |
| 3521 | } }); | |
| 3484 | 3522 | }, |
| 3485 | 3523 | .analyze_func => |func| { |
| 3486 | 3524 | const named_frame = tracy.namedFrame("analyze_func"); |
| ... | ... | @@ -3772,6 +3810,61 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3772 | 3810 | } |
| 3773 | 3811 | } |
| 3774 | 3812 | |
| 3813 | fn queueCodegenJob(comp: *Compilation, tid: usize, codegen_job: CodegenJob) !void { | |
| 3814 | if (InternPool.single_threaded or | |
| 3815 | !comp.module.?.backendSupportsFeature(.separate_thread)) | |
| 3816 | return processOneCodegenJob(tid, comp, codegen_job); | |
| 3817 | ||
| 3818 | { | |
| 3819 | comp.codegen_work.mutex.lock(); | |
| 3820 | defer comp.codegen_work.mutex.unlock(); | |
| 3821 | try comp.codegen_work.queue.writeItem(codegen_job); | |
| 3822 | } | |
| 3823 | comp.codegen_work.cond.signal(); | |
| 3824 | } | |
| 3825 | ||
| 3826 | fn codegenThread(tid: usize, comp: *Compilation) void { | |
| 3827 | comp.codegen_work.mutex.lock(); | |
| 3828 | defer comp.codegen_work.mutex.unlock(); | |
| 3829 | ||
| 3830 | while (true) { | |
| 3831 | if (comp.codegen_work.queue.readItem()) |codegen_job| { | |
| 3832 | comp.codegen_work.mutex.unlock(); | |
| 3833 | defer comp.codegen_work.mutex.lock(); | |
| 3834 | ||
| 3835 | processOneCodegenJob(tid, comp, codegen_job) catch |job_error| { | |
| 3836 | comp.codegen_work.job_error = job_error; | |
| 3837 | break; | |
| 3838 | }; | |
| 3839 | continue; | |
| 3840 | } | |
| 3841 | ||
| 3842 | if (comp.codegen_work.done) break; | |
| 3843 | ||
| 3844 | comp.codegen_work.cond.wait(&comp.codegen_work.mutex); | |
| 3845 | } | |
| 3846 | } | |
| 3847 | ||
| 3848 | fn processOneCodegenJob(tid: usize, comp: *Compilation, codegen_job: CodegenJob) JobError!void { | |
| 3849 | switch (codegen_job) { | |
| 3850 | .decl => |decl_index| { | |
| 3851 | const named_frame = tracy.namedFrame("codegen_decl"); | |
| 3852 | defer named_frame.end(); | |
| 3853 | ||
| 3854 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; | |
| 3855 | try pt.linkerUpdateDecl(decl_index); | |
| 3856 | }, | |
| 3857 | .func => |func| { | |
| 3858 | const named_frame = tracy.namedFrame("codegen_func"); | |
| 3859 | defer named_frame.end(); | |
| 3860 | ||
| 3861 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; | |
| 3862 | // This call takes ownership of `func.air`. | |
| 3863 | try pt.linkerUpdateFunc(func.func, func.air); | |
| 3864 | }, | |
| 3865 | } | |
| 3866 | } | |
| 3867 | ||
| 3775 | 3868 | fn workerDocsCopy(comp: *Compilation) void { |
| 3776 | 3869 | docsCopyFallible(comp) catch |err| { |
| 3777 | 3870 | return comp.lockAndSetMiscFailure( |
src/Compilation/Config.zig+2-6| ... | ... | @@ -440,12 +440,8 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 440 | 440 | }; |
| 441 | 441 | }; |
| 442 | 442 | |
| 443 | const backend_supports_error_tracing = target_util.backendSupportsFeature( | |
| 444 | target.cpu.arch, | |
| 445 | target.ofmt, | |
| 446 | use_llvm, | |
| 447 | .error_return_trace, | |
| 448 | ); | |
| 443 | const backend = target_util.zigBackend(target, use_llvm); | |
| 444 | const backend_supports_error_tracing = target_util.backendSupportsFeature(backend, .error_return_trace); | |
| 449 | 445 | |
| 450 | 446 | const root_error_tracing = b: { |
| 451 | 447 | if (options.root_error_tracing) |x| break :b x; |
src/Zcu.zig+7-7| ... | ... | @@ -64,8 +64,8 @@ root_mod: *Package.Module, |
| 64 | 64 | /// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests. |
| 65 | 65 | main_mod: *Package.Module, |
| 66 | 66 | std_mod: *Package.Module, |
| 67 | sema_prog_node: std.Progress.Node = undefined, | |
| 68 | codegen_prog_node: std.Progress.Node = undefined, | |
| 67 | sema_prog_node: std.Progress.Node = std.Progress.Node.none, | |
| 68 | codegen_prog_node: std.Progress.Node = std.Progress.Node.none, | |
| 69 | 69 | |
| 70 | 70 | /// Used by AstGen worker to load and store ZIR cache. |
| 71 | 71 | global_zir_cache: Compilation.Directory, |
| ... | ... | @@ -3557,13 +3557,13 @@ pub const Feature = enum { |
| 3557 | 3557 | /// to generate better machine code in the backends. All backends should migrate to |
| 3558 | 3558 | /// enabling this feature. |
| 3559 | 3559 | safety_checked_instructions, |
| 3560 | /// If the backend supports running from another thread. | |
| 3561 | separate_thread, | |
| 3560 | 3562 | }; |
| 3561 | 3563 | |
| 3562 | pub fn backendSupportsFeature(zcu: Module, feature: Feature) bool { | |
| 3563 | const cpu_arch = zcu.root_mod.resolved_target.result.cpu.arch; | |
| 3564 | const ofmt = zcu.root_mod.resolved_target.result.ofmt; | |
| 3565 | const use_llvm = zcu.comp.config.use_llvm; | |
| 3566 | return target_util.backendSupportsFeature(cpu_arch, ofmt, use_llvm, feature); | |
| 3564 | pub fn backendSupportsFeature(zcu: Module, comptime feature: Feature) bool { | |
| 3565 | const backend = target_util.zigBackend(zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm); | |
| 3566 | return target_util.backendSupportsFeature(backend, feature); | |
| 3567 | 3567 | } |
| 3568 | 3568 | |
| 3569 | 3569 | pub const AtomicPtrAlignmentError = error{ |
src/Zcu/PerThread.zig+2-2| ... | ... | @@ -2129,7 +2129,7 @@ pub fn populateTestFunctions( |
| 2129 | 2129 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); |
| 2130 | 2130 | defer { |
| 2131 | 2131 | zcu.sema_prog_node.end(); |
| 2132 | zcu.sema_prog_node = undefined; | |
| 2132 | zcu.sema_prog_node = std.Progress.Node.none; | |
| 2133 | 2133 | } |
| 2134 | 2134 | try pt.ensureDeclAnalyzed(decl_index); |
| 2135 | 2135 | } |
| ... | ... | @@ -2238,7 +2238,7 @@ pub fn populateTestFunctions( |
| 2238 | 2238 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); |
| 2239 | 2239 | defer { |
| 2240 | 2240 | zcu.codegen_prog_node.end(); |
| 2241 | zcu.codegen_prog_node = undefined; | |
| 2241 | zcu.codegen_prog_node = std.Progress.Node.none; | |
| 2242 | 2242 | } |
| 2243 | 2243 | |
| 2244 | 2244 | try pt.linkerUpdateDecl(decl_index); |
src/target.zig+36-14| ... | ... | @@ -537,20 +537,42 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken |
| 537 | 537 | }; |
| 538 | 538 | } |
| 539 | 539 | |
| 540 | pub fn backendSupportsFeature( | |
| 541 | cpu_arch: std.Target.Cpu.Arch, | |
| 542 | ofmt: std.Target.ObjectFormat, | |
| 543 | use_llvm: bool, | |
| 544 | feature: Feature, | |
| 545 | ) bool { | |
| 540 | pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool { | |
| 546 | 541 | return switch (feature) { |
| 547 | .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64 or cpu_arch == .riscv64, | |
| 548 | .panic_unwrap_error => ofmt == .c or use_llvm, | |
| 549 | .safety_check_formatted => ofmt == .c or use_llvm, | |
| 550 | .error_return_trace => use_llvm, | |
| 551 | .is_named_enum_value => use_llvm, | |
| 552 | .error_set_has_value => use_llvm or cpu_arch.isWasm(), | |
| 553 | .field_reordering => ofmt == .c or use_llvm, | |
| 554 | .safety_checked_instructions => use_llvm, | |
| 542 | .panic_fn => switch (backend) { | |
| 543 | .stage2_c, .stage2_llvm, .stage2_x86_64, .stage2_riscv64 => true, | |
| 544 | else => false, | |
| 545 | }, | |
| 546 | .panic_unwrap_error => switch (backend) { | |
| 547 | .stage2_c, .stage2_llvm => true, | |
| 548 | else => false, | |
| 549 | }, | |
| 550 | .safety_check_formatted => switch (backend) { | |
| 551 | .stage2_c, .stage2_llvm => true, | |
| 552 | else => false, | |
| 553 | }, | |
| 554 | .error_return_trace => switch (backend) { | |
| 555 | .stage2_llvm => true, | |
| 556 | else => false, | |
| 557 | }, | |
| 558 | .is_named_enum_value => switch (backend) { | |
| 559 | .stage2_llvm => true, | |
| 560 | else => false, | |
| 561 | }, | |
| 562 | .error_set_has_value => switch (backend) { | |
| 563 | .stage2_llvm, .stage2_wasm => true, | |
| 564 | else => false, | |
| 565 | }, | |
| 566 | .field_reordering => switch (backend) { | |
| 567 | .stage2_c, .stage2_llvm => true, | |
| 568 | else => false, | |
| 569 | }, | |
| 570 | .safety_checked_instructions => switch (backend) { | |
| 571 | .stage2_llvm => true, | |
| 572 | else => false, | |
| 573 | }, | |
| 574 | .separate_thread => switch (backend) { | |
| 575 | else => false, | |
| 576 | }, | |
| 555 | 577 | }; |
| 556 | 578 | } |