| 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,7 +282,7 @@ pub const Node = struct { |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | fn init(free_index: Index, parent: Parent, name: []const u8, estimated_total_items: usize) Node { | 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 | const storage = storageByIndex(free_index); | 287 | const storage = storageByIndex(free_index); |
| 288 | storage.* = .{ | 288 | storage.* = .{ |
lib/std/Thread/Pool.zig+10-13| ... | @@ -21,11 +21,11 @@ const Runnable = struct { | ... | @@ -21,11 +21,11 @@ const Runnable = struct { |
| 21 | runFn: RunProto, | 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 | pub const Options = struct { | 26 | pub const Options = struct { |
| 27 | allocator: std.mem.Allocator, | 27 | allocator: std.mem.Allocator, |
| 28 | n_jobs: ?u32 = null, | 28 | n_jobs: ?usize = null, |
| 29 | track_ids: bool = false, | 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,7 +109,7 @@ pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args |
| 109 | run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } }, | 109 | run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } }, |
| 110 | wait_group: *WaitGroup, | 110 | wait_group: *WaitGroup, |
| 111 | 111 | ||
| 112 | fn runFn(runnable: *Runnable, _: ?u32) void { | 112 | fn runFn(runnable: *Runnable, _: ?usize) void { |
| 113 | const run_node: *RunQueue.Node = @fieldParentPtr("data", runnable); | 113 | const run_node: *RunQueue.Node = @fieldParentPtr("data", runnable); |
| 114 | const closure: *@This() = @alignCast(@fieldParentPtr("run_node", run_node)); | 114 | const closure: *@This() = @alignCast(@fieldParentPtr("run_node", run_node)); |
| 115 | @call(.auto, func, closure.arguments); | 115 | @call(.auto, func, closure.arguments); |
| ... | @@ -150,7 +150,7 @@ pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args | ... | @@ -150,7 +150,7 @@ pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args |
| 150 | /// Runs `func` in the thread pool, calling `WaitGroup.start` beforehand, and | 150 | /// Runs `func` in the thread pool, calling `WaitGroup.start` beforehand, and |
| 151 | /// `WaitGroup.finish` after it returns. | 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 | /// of the arguments are passed from `args`. Requires the pool to have been | 154 | /// of the arguments are passed from `args`. Requires the pool to have been |
| 155 | /// initialized with `.track_ids = true`. | 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,7 +172,7 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar |
| 172 | run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } }, | 172 | run_node: RunQueue.Node = .{ .data = .{ .runFn = runFn } }, |
| 173 | wait_group: *WaitGroup, | 173 | wait_group: *WaitGroup, |
| 174 | 174 | ||
| 175 | fn runFn(runnable: *Runnable, id: ?u32) void { | 175 | fn runFn(runnable: *Runnable, id: ?usize) void { |
| 176 | const run_node: *RunQueue.Node = @fieldParentPtr("data", runnable); | 176 | const run_node: *RunQueue.Node = @fieldParentPtr("data", runnable); |
| 177 | const closure: *@This() = @alignCast(@fieldParentPtr("run_node", run_node)); | 177 | const closure: *@This() = @alignCast(@fieldParentPtr("run_node", run_node)); |
| 178 | @call(.auto, func, .{id.?} ++ closure.arguments); | 178 | @call(.auto, func, .{id.?} ++ closure.arguments); |
| ... | @@ -191,7 +191,7 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar | ... | @@ -191,7 +191,7 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar |
| 191 | pool.mutex.lock(); | 191 | pool.mutex.lock(); |
| 192 | 192 | ||
| 193 | const closure = pool.allocator.create(Closure) catch { | 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 | pool.mutex.unlock(); | 195 | pool.mutex.unlock(); |
| 196 | @call(.auto, func, .{id.?} ++ args); | 196 | @call(.auto, func, .{id.?} ++ args); |
| 197 | wait_group.finish(); | 197 | wait_group.finish(); |
| ... | @@ -258,7 +258,7 @@ fn worker(pool: *Pool) void { | ... | @@ -258,7 +258,7 @@ fn worker(pool: *Pool) void { |
| 258 | pool.mutex.lock(); | 258 | pool.mutex.lock(); |
| 259 | defer pool.mutex.unlock(); | 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 | if (id) |_| pool.ids.putAssumeCapacityNoClobber(std.Thread.getCurrentId(), {}); | 262 | if (id) |_| pool.ids.putAssumeCapacityNoClobber(std.Thread.getCurrentId(), {}); |
| 263 | 263 | ||
| 264 | while (true) { | 264 | while (true) { |
| ... | @@ -280,15 +280,12 @@ fn worker(pool: *Pool) void { | ... | @@ -280,15 +280,12 @@ fn worker(pool: *Pool) void { |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { | 282 | pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { |
| 283 | var id: ?u32 = null; | 283 | var id: ?usize = null; |
| 284 | 284 | ||
| 285 | while (!wait_group.isDone()) { | 285 | while (!wait_group.isDone()) { |
| 286 | pool.mutex.lock(); | 286 | pool.mutex.lock(); |
| 287 | if (pool.run_queue.popFirst()) |run_node| { | 287 | if (pool.run_queue.popFirst()) |run_node| { |
| 288 | id = id orelse if (pool.ids.getIndex(std.Thread.getCurrentId())) |index| | 288 | id = id orelse pool.ids.getIndex(std.Thread.getCurrentId()); |
| 289 | @intCast(index) | ||
| 290 | else | ||
| 291 | null; | ||
| 292 | pool.mutex.unlock(); | 289 | pool.mutex.unlock(); |
| 293 | run_node.data.runFn(&run_node.data, id); | 290 | run_node.data.runFn(&run_node.data, id); |
| 294 | continue; | 291 | continue; |
| ... | @@ -300,6 +297,6 @@ pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { | ... | @@ -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 | return @intCast(1 + pool.threads.len); | 301 | return @intCast(1 + pool.threads.len); |
| 305 | } | 302 | } |
src/Compilation.zig+115-22| ... | @@ -103,6 +103,14 @@ lld_errors: std.ArrayListUnmanaged(LldError) = .{}, | ... | @@ -103,6 +103,14 @@ lld_errors: std.ArrayListUnmanaged(LldError) = .{}, |
| 103 | 103 | ||
| 104 | work_queue: std.fifo.LinearFifo(Job, .Dynamic), | 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 | /// These jobs are to invoke the Clang compiler to create an object file, which | 114 | /// These jobs are to invoke the Clang compiler to create an object file, which |
| 107 | /// gets linked with the Compilation. | 115 | /// gets linked with the Compilation. |
| 108 | c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic), | 116 | c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic), |
| ... | @@ -362,6 +370,16 @@ const Job = union(enum) { | ... | @@ -362,6 +370,16 @@ const Job = union(enum) { |
| 362 | windows_import_lib: usize, | 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 | pub const CObject = struct { | 383 | pub const CObject = struct { |
| 366 | /// Relative to cwd. Owned by arena. | 384 | /// Relative to cwd. Owned by arena. |
| 367 | src: CSourceFile, | 385 | src: CSourceFile, |
| ... | @@ -1429,6 +1447,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil | ... | @@ -1429,6 +1447,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1429 | .emit_llvm_ir = options.emit_llvm_ir, | 1447 | .emit_llvm_ir = options.emit_llvm_ir, |
| 1430 | .emit_llvm_bc = options.emit_llvm_bc, | 1448 | .emit_llvm_bc = options.emit_llvm_bc, |
| 1431 | .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), | 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 | .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa), | 1457 | .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa), |
| 1433 | .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa), | 1458 | .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa), |
| 1434 | .astgen_work_queue = std.fifo.LinearFifo(Zcu.File.Index, .Dynamic).init(gpa), | 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,7 +3335,21 @@ pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void { |
| 3310 | pub fn performAllTheWork( | 3335 | pub fn performAllTheWork( |
| 3311 | comp: *Compilation, | 3336 | comp: *Compilation, |
| 3312 | main_progress_node: std.Progress.Node, | 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 | // Here we queue up all the AstGen tasks first, followed by C object compilation. | 3353 | // Here we queue up all the AstGen tasks first, followed by C object compilation. |
| 3315 | // We wait until the AstGen tasks are all completed before proceeding to the | 3354 | // We wait until the AstGen tasks are all completed before proceeding to the |
| 3316 | // (at least for now) single-threaded main work queue. However, C object compilation | 3355 | // (at least for now) single-threaded main work queue. However, C object compilation |
| ... | @@ -3410,16 +3449,20 @@ pub fn performAllTheWork( | ... | @@ -3410,16 +3449,20 @@ pub fn performAllTheWork( |
| 3410 | mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); | 3449 | mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); |
| 3411 | mod.codegen_prog_node = main_progress_node.start("Code Generation", 0); | 3450 | mod.codegen_prog_node = main_progress_node.start("Code Generation", 0); |
| 3412 | } | 3451 | } |
| 3413 | defer if (comp.module) |mod| { | 3452 | |
| 3414 | mod.sema_prog_node.end(); | 3453 | if (!InternPool.single_threaded) comp.thread_pool.spawnWgId(&comp.work_queue_wait_group, codegenThread, .{comp}); |
| 3415 | mod.sema_prog_node = undefined; | 3454 | defer if (!InternPool.single_threaded) { |
| 3416 | mod.codegen_prog_node.end(); | 3455 | { |
| 3417 | mod.codegen_prog_node = undefined; | 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 | while (true) { | 3463 | while (true) { |
| 3421 | if (comp.work_queue.readItem()) |work_item| { | 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 | continue; | 3466 | continue; |
| 3424 | } | 3467 | } |
| 3425 | if (comp.module) |zcu| { | 3468 | if (comp.module) |zcu| { |
| ... | @@ -3447,11 +3490,12 @@ pub fn performAllTheWork( | ... | @@ -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 | switch (job) { | 3496 | switch (job) { |
| 3452 | .codegen_decl => |decl_index| { | 3497 | .codegen_decl => |decl_index| { |
| 3453 | const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) }; | 3498 | const decl = comp.module.?.declPtr(decl_index); |
| 3454 | const decl = pt.zcu.declPtr(decl_index); | ||
| 3455 | 3499 | ||
| 3456 | switch (decl.analysis) { | 3500 | switch (decl.analysis) { |
| 3457 | .unreferenced => unreachable, | 3501 | .unreferenced => unreachable, |
| ... | @@ -3461,26 +3505,20 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre | ... | @@ -3461,26 +3505,20 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre |
| 3461 | .sema_failure, | 3505 | .sema_failure, |
| 3462 | .codegen_failure, | 3506 | .codegen_failure, |
| 3463 | .dependency_failure, | 3507 | .dependency_failure, |
| 3464 | => return, | 3508 | => {}, |
| 3465 | 3509 | ||
| 3466 | .complete => { | 3510 | .complete => { |
| 3467 | const named_frame = tracy.namedFrame("codegen_decl"); | ||
| 3468 | defer named_frame.end(); | ||
| 3469 | |||
| 3470 | assert(decl.has_tv); | 3511 | assert(decl.has_tv); |
| 3471 | 3512 | try comp.queueCodegenJob(tid, .{ .decl = decl_index }); | |
| 3472 | try pt.linkerUpdateDecl(decl_index); | ||
| 3473 | return; | ||
| 3474 | }, | 3513 | }, |
| 3475 | } | 3514 | } |
| 3476 | }, | 3515 | }, |
| 3477 | .codegen_func => |func| { | 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 | // This call takes ownership of `func.air`. | 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 | .analyze_func => |func| { | 3523 | .analyze_func => |func| { |
| 3486 | const named_frame = tracy.namedFrame("analyze_func"); | 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,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 | fn workerDocsCopy(comp: *Compilation) void { | 3868 | fn workerDocsCopy(comp: *Compilation) void { |
| 3776 | docsCopyFallible(comp) catch |err| { | 3869 | docsCopyFallible(comp) catch |err| { |
| 3777 | return comp.lockAndSetMiscFailure( | 3870 | return comp.lockAndSetMiscFailure( |
src/Compilation/Config.zig+2-6| ... | @@ -440,12 +440,8 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -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( | 443 | const backend = target_util.zigBackend(target, use_llvm); |
| 444 | target.cpu.arch, | 444 | const backend_supports_error_tracing = target_util.backendSupportsFeature(backend, .error_return_trace); |
| 445 | target.ofmt, | ||
| 446 | use_llvm, | ||
| 447 | .error_return_trace, | ||
| 448 | ); | ||
| 449 | 445 | ||
| 450 | const root_error_tracing = b: { | 446 | const root_error_tracing = b: { |
| 451 | if (options.root_error_tracing) |x| break :b x; | 447 | if (options.root_error_tracing) |x| break :b x; |
src/Zcu.zig+7-7| ... | @@ -64,8 +64,8 @@ root_mod: *Package.Module, | ... | @@ -64,8 +64,8 @@ root_mod: *Package.Module, |
| 64 | /// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests. | 64 | /// `root_mod` is the test runner, and `main_mod` is the user's source file which has the tests. |
| 65 | main_mod: *Package.Module, | 65 | main_mod: *Package.Module, |
| 66 | std_mod: *Package.Module, | 66 | std_mod: *Package.Module, |
| 67 | sema_prog_node: std.Progress.Node = undefined, | 67 | sema_prog_node: std.Progress.Node = std.Progress.Node.none, |
| 68 | codegen_prog_node: std.Progress.Node = undefined, | 68 | codegen_prog_node: std.Progress.Node = std.Progress.Node.none, |
| 69 | 69 | ||
| 70 | /// Used by AstGen worker to load and store ZIR cache. | 70 | /// Used by AstGen worker to load and store ZIR cache. |
| 71 | global_zir_cache: Compilation.Directory, | 71 | global_zir_cache: Compilation.Directory, |
| ... | @@ -3557,13 +3557,13 @@ pub const Feature = enum { | ... | @@ -3557,13 +3557,13 @@ pub const Feature = enum { |
| 3557 | /// to generate better machine code in the backends. All backends should migrate to | 3557 | /// to generate better machine code in the backends. All backends should migrate to |
| 3558 | /// enabling this feature. | 3558 | /// enabling this feature. |
| 3559 | safety_checked_instructions, | 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 { | 3564 | pub fn backendSupportsFeature(zcu: Module, comptime feature: Feature) bool { |
| 3563 | const cpu_arch = zcu.root_mod.resolved_target.result.cpu.arch; | 3565 | const backend = target_util.zigBackend(zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm); |
| 3564 | const ofmt = zcu.root_mod.resolved_target.result.ofmt; | 3566 | return target_util.backendSupportsFeature(backend, feature); |
| 3565 | const use_llvm = zcu.comp.config.use_llvm; | ||
| 3566 | return target_util.backendSupportsFeature(cpu_arch, ofmt, use_llvm, feature); | ||
| 3567 | } | 3567 | } |
| 3568 | 3568 | ||
| 3569 | pub const AtomicPtrAlignmentError = error{ | 3569 | pub const AtomicPtrAlignmentError = error{ |
src/Zcu/PerThread.zig+2-2| ... | @@ -2129,7 +2129,7 @@ pub fn populateTestFunctions( | ... | @@ -2129,7 +2129,7 @@ pub fn populateTestFunctions( |
| 2129 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); | 2129 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); |
| 2130 | defer { | 2130 | defer { |
| 2131 | zcu.sema_prog_node.end(); | 2131 | zcu.sema_prog_node.end(); |
| 2132 | zcu.sema_prog_node = undefined; | 2132 | zcu.sema_prog_node = std.Progress.Node.none; |
| 2133 | } | 2133 | } |
| 2134 | try pt.ensureDeclAnalyzed(decl_index); | 2134 | try pt.ensureDeclAnalyzed(decl_index); |
| 2135 | } | 2135 | } |
| ... | @@ -2238,7 +2238,7 @@ pub fn populateTestFunctions( | ... | @@ -2238,7 +2238,7 @@ pub fn populateTestFunctions( |
| 2238 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); | 2238 | zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); |
| 2239 | defer { | 2239 | defer { |
| 2240 | zcu.codegen_prog_node.end(); | 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 | try pt.linkerUpdateDecl(decl_index); | 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,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( | 540 | pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool { |
| 541 | cpu_arch: std.Target.Cpu.Arch, | ||
| 542 | ofmt: std.Target.ObjectFormat, | ||
| 543 | use_llvm: bool, | ||
| 544 | feature: Feature, | ||
| 545 | ) bool { | ||
| 546 | return switch (feature) { | 541 | return switch (feature) { |
| 547 | .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64 or cpu_arch == .riscv64, | 542 | .panic_fn => switch (backend) { |
| 548 | .panic_unwrap_error => ofmt == .c or use_llvm, | 543 | .stage2_c, .stage2_llvm, .stage2_x86_64, .stage2_riscv64 => true, |
| 549 | .safety_check_formatted => ofmt == .c or use_llvm, | 544 | else => false, |
| 550 | .error_return_trace => use_llvm, | 545 | }, |
| 551 | .is_named_enum_value => use_llvm, | 546 | .panic_unwrap_error => switch (backend) { |
| 552 | .error_set_has_value => use_llvm or cpu_arch.isWasm(), | 547 | .stage2_c, .stage2_llvm => true, |
| 553 | .field_reordering => ofmt == .c or use_llvm, | 548 | else => false, |
| 554 | .safety_checked_instructions => use_llvm, | 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 | } |