authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-11 11:28:58-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-13 04:47:38-04:00
log2ff49751aa932a6c0a0a09b8fd15e05ca6288c9b
tree063c28d109180173532a5318fae2428675242030
parenta1053e8e1d961ba92ce83a8ef5470ac7f7e92e60

Compilation: introduce work stages for better work distribution


11 files changed, 114 insertions(+), 57 deletions(-)

src/Compilation.zig+93-34
...@@ -101,7 +101,15 @@ link_error_flags: link.File.ErrorFlags = .{},...@@ -101,7 +101,15 @@ link_error_flags: link.File.ErrorFlags = .{},
101link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{},101link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{},
102lld_errors: std.ArrayListUnmanaged(LldError) = .{},102lld_errors: std.ArrayListUnmanaged(LldError) = .{},
103103
104work_queue: std.fifo.LinearFifo(Job, .Dynamic),104work_queues: [
105 len: {
106 var len: usize = 0;
107 for (std.enums.values(Job.Tag)) |tag| {
108 len = @max(Job.stage(tag) + 1, len);
109 }
110 break :len len;
111 }
112]std.fifo.LinearFifo(Job, .Dynamic),
105113
106codegen_work: if (InternPool.single_threaded) void else struct {114codegen_work: if (InternPool.single_threaded) void else struct {
107 mutex: std.Thread.Mutex,115 mutex: std.Thread.Mutex,
...@@ -370,6 +378,20 @@ const Job = union(enum) {...@@ -370,6 +378,20 @@ const Job = union(enum) {
370378
371 /// The value is the index into `system_libs`.379 /// The value is the index into `system_libs`.
372 windows_import_lib: usize,380 windows_import_lib: usize,
381
382 const Tag = @typeInfo(Job).Union.tag_type.?;
383 fn stage(tag: Tag) usize {
384 return switch (tag) {
385 // Prioritize functions so that codegen can get to work on them on a
386 // separate thread, while Sema goes back to its own work.
387 .resolve_type_fully, .analyze_func, .codegen_func => 0,
388 else => 1,
389 };
390 }
391 comptime {
392 // Job dependencies
393 assert(stage(.resolve_type_fully) <= stage(.codegen_func));
394 }
373};395};
374396
375const CodegenJob = union(enum) {397const CodegenJob = union(enum) {
...@@ -1452,7 +1474,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1452,7 +1474,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1452 .emit_asm = options.emit_asm,1474 .emit_asm = options.emit_asm,
1453 .emit_llvm_ir = options.emit_llvm_ir,1475 .emit_llvm_ir = options.emit_llvm_ir,
1454 .emit_llvm_bc = options.emit_llvm_bc,1476 .emit_llvm_bc = options.emit_llvm_bc,
1455 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),1477 .work_queues = .{std.fifo.LinearFifo(Job, .Dynamic).init(gpa)} ** @typeInfo(std.meta.FieldType(Compilation, .work_queues)).Array.len,
1456 .codegen_work = if (InternPool.single_threaded) {} else .{1478 .codegen_work = if (InternPool.single_threaded) {} else .{
1457 .mutex = .{},1479 .mutex = .{},
1458 .cond = .{},1480 .cond = .{},
...@@ -1760,12 +1782,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1760,12 +1782,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1760 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;1782 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
17611783
1762 if (glibc.needsCrtiCrtn(target)) {1784 if (glibc.needsCrtiCrtn(target)) {
1763 try comp.work_queue.write(&[_]Job{1785 try comp.queueJobs(&[_]Job{
1764 .{ .glibc_crt_file = .crti_o },1786 .{ .glibc_crt_file = .crti_o },
1765 .{ .glibc_crt_file = .crtn_o },1787 .{ .glibc_crt_file = .crtn_o },
1766 });1788 });
1767 }1789 }
1768 try comp.work_queue.write(&[_]Job{1790 try comp.queueJobs(&[_]Job{
1769 .{ .glibc_crt_file = .scrt1_o },1791 .{ .glibc_crt_file = .scrt1_o },
1770 .{ .glibc_crt_file = .libc_nonshared_a },1792 .{ .glibc_crt_file = .libc_nonshared_a },
1771 .{ .glibc_shared_objects = {} },1793 .{ .glibc_shared_objects = {} },
...@@ -1774,14 +1796,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1774,14 +1796,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1774 if (comp.wantBuildMuslFromSource()) {1796 if (comp.wantBuildMuslFromSource()) {
1775 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;1797 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
17761798
1777 try comp.work_queue.ensureUnusedCapacity(6);
1778 if (musl.needsCrtiCrtn(target)) {1799 if (musl.needsCrtiCrtn(target)) {
1779 comp.work_queue.writeAssumeCapacity(&[_]Job{1800 try comp.queueJobs(&[_]Job{
1780 .{ .musl_crt_file = .crti_o },1801 .{ .musl_crt_file = .crti_o },
1781 .{ .musl_crt_file = .crtn_o },1802 .{ .musl_crt_file = .crtn_o },
1782 });1803 });
1783 }1804 }
1784 comp.work_queue.writeAssumeCapacity(&[_]Job{1805 try comp.queueJobs(&[_]Job{
1785 .{ .musl_crt_file = .crt1_o },1806 .{ .musl_crt_file = .crt1_o },
1786 .{ .musl_crt_file = .scrt1_o },1807 .{ .musl_crt_file = .scrt1_o },
1787 .{ .musl_crt_file = .rcrt1_o },1808 .{ .musl_crt_file = .rcrt1_o },
...@@ -1795,15 +1816,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1795,15 +1816,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1795 if (comp.wantBuildWasiLibcFromSource()) {1816 if (comp.wantBuildWasiLibcFromSource()) {
1796 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;1817 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
17971818
1798 // worst-case we need all components
1799 try comp.work_queue.ensureUnusedCapacity(comp.wasi_emulated_libs.len + 2);
1800
1801 for (comp.wasi_emulated_libs) |crt_file| {1819 for (comp.wasi_emulated_libs) |crt_file| {
1802 comp.work_queue.writeItemAssumeCapacity(.{1820 try comp.queueJob(.{
1803 .wasi_libc_crt_file = crt_file,1821 .wasi_libc_crt_file = crt_file,
1804 });1822 });
1805 }1823 }
1806 comp.work_queue.writeAssumeCapacity(&[_]Job{1824 try comp.queueJobs(&[_]Job{
1807 .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(comp.config.wasi_exec_model) },1825 .{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(comp.config.wasi_exec_model) },
1808 .{ .wasi_libc_crt_file = .libc_a },1826 .{ .wasi_libc_crt_file = .libc_a },
1809 });1827 });
...@@ -1813,9 +1831,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1813,9 +1831,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1813 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;1831 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
18141832
1815 const crt_job: Job = .{ .mingw_crt_file = if (is_dyn_lib) .dllcrt2_o else .crt2_o };1833 const crt_job: Job = .{ .mingw_crt_file = if (is_dyn_lib) .dllcrt2_o else .crt2_o };
1816 try comp.work_queue.ensureUnusedCapacity(2);1834 try comp.queueJobs(&.{
1817 comp.work_queue.writeItemAssumeCapacity(.{ .mingw_crt_file = .mingw32_lib });1835 .{ .mingw_crt_file = .mingw32_lib },
1818 comp.work_queue.writeItemAssumeCapacity(crt_job);1836 crt_job,
1837 });
18191838
1820 // When linking mingw-w64 there are some import libs we always need.1839 // When linking mingw-w64 there are some import libs we always need.
1821 for (mingw.always_link_libs) |name| {1840 for (mingw.always_link_libs) |name| {
...@@ -1829,20 +1848,19 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1829,20 +1848,19 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1829 // Generate Windows import libs.1848 // Generate Windows import libs.
1830 if (target.os.tag == .windows) {1849 if (target.os.tag == .windows) {
1831 const count = comp.system_libs.count();1850 const count = comp.system_libs.count();
1832 try comp.work_queue.ensureUnusedCapacity(count);
1833 for (0..count) |i| {1851 for (0..count) |i| {
1834 comp.work_queue.writeItemAssumeCapacity(.{ .windows_import_lib = i });1852 try comp.queueJob(.{ .windows_import_lib = i });
1835 }1853 }
1836 }1854 }
1837 if (comp.wantBuildLibUnwindFromSource()) {1855 if (comp.wantBuildLibUnwindFromSource()) {
1838 try comp.work_queue.writeItem(.{ .libunwind = {} });1856 try comp.queueJob(.{ .libunwind = {} });
1839 }1857 }
1840 if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) {1858 if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) {
1841 try comp.work_queue.writeItem(.libcxx);1859 try comp.queueJob(.libcxx);
1842 try comp.work_queue.writeItem(.libcxxabi);1860 try comp.queueJob(.libcxxabi);
1843 }1861 }
1844 if (build_options.have_llvm and comp.config.any_sanitize_thread) {1862 if (build_options.have_llvm and comp.config.any_sanitize_thread) {
1845 try comp.work_queue.writeItem(.libtsan);1863 try comp.queueJob(.libtsan);
1846 }1864 }
18471865
1848 if (target.isMinGW() and comp.config.any_non_single_threaded) {1866 if (target.isMinGW() and comp.config.any_non_single_threaded) {
...@@ -1872,7 +1890,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1872,7 +1890,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1872 if (!comp.skip_linker_dependencies and is_exe_or_dyn_lib and1890 if (!comp.skip_linker_dependencies and is_exe_or_dyn_lib and
1873 !comp.config.link_libc and capable_of_building_zig_libc)1891 !comp.config.link_libc and capable_of_building_zig_libc)
1874 {1892 {
1875 try comp.work_queue.writeItem(.{ .zig_libc = {} });1893 try comp.queueJob(.{ .zig_libc = {} });
1876 }1894 }
1877 }1895 }
18781896
...@@ -1883,7 +1901,7 @@ pub fn destroy(comp: *Compilation) void {...@@ -1883,7 +1901,7 @@ pub fn destroy(comp: *Compilation) void {
1883 if (comp.bin_file) |lf| lf.destroy();1901 if (comp.bin_file) |lf| lf.destroy();
1884 if (comp.module) |zcu| zcu.deinit();1902 if (comp.module) |zcu| zcu.deinit();
1885 comp.cache_use.deinit();1903 comp.cache_use.deinit();
1886 comp.work_queue.deinit();1904 for (comp.work_queues) |work_queue| work_queue.deinit();
1887 if (!InternPool.single_threaded) comp.codegen_work.queue.deinit();1905 if (!InternPool.single_threaded) comp.codegen_work.queue.deinit();
1888 comp.c_object_work_queue.deinit();1906 comp.c_object_work_queue.deinit();
1889 if (!build_options.only_core_functionality) {1907 if (!build_options.only_core_functionality) {
...@@ -2199,13 +2217,13 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2199,13 +2217,13 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2199 }2217 }
2200 }2218 }
22012219
2202 try comp.work_queue.writeItem(.{ .analyze_mod = std_mod });2220 try comp.queueJob(.{ .analyze_mod = std_mod });
2203 if (comp.config.is_test) {2221 if (comp.config.is_test) {
2204 try comp.work_queue.writeItem(.{ .analyze_mod = zcu.main_mod });2222 try comp.queueJob(.{ .analyze_mod = zcu.main_mod });
2205 }2223 }
22062224
2207 if (zcu.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| {2225 if (zcu.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| {
2208 try comp.work_queue.writeItem(.{ .analyze_mod = compiler_rt_mod });2226 try comp.queueJob(.{ .analyze_mod = compiler_rt_mod });
2209 }2227 }
2210 }2228 }
22112229
...@@ -3095,6 +3113,39 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3095,6 +3113,39 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3095 for (zcu.failed_embed_files.values()) |error_msg| {3113 for (zcu.failed_embed_files.values()) |error_msg| {
3096 try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);3114 try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
3097 }3115 }
3116 {
3117 const SortOrder = struct {
3118 zcu: *Zcu,
3119 err: *?Error,
3120
3121 const Error = @typeInfo(
3122 @typeInfo(@TypeOf(Zcu.SrcLoc.span)).Fn.return_type.?,
3123 ).ErrorUnion.error_set;
3124
3125 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
3126 if (ctx.err.*) |_| return lhs_index < rhs_index;
3127 const errors = ctx.zcu.failed_analysis.values();
3128 const lhs_src_loc = errors[lhs_index].src_loc.upgrade(ctx.zcu);
3129 const rhs_src_loc = errors[rhs_index].src_loc.upgrade(ctx.zcu);
3130 return if (lhs_src_loc.file_scope != rhs_src_loc.file_scope) std.mem.order(
3131 u8,
3132 lhs_src_loc.file_scope.sub_file_path,
3133 rhs_src_loc.file_scope.sub_file_path,
3134 ).compare(.lt) else (lhs_src_loc.span(ctx.zcu.gpa) catch |e| {
3135 ctx.err.* = e;
3136 return lhs_index < rhs_index;
3137 }).main < (rhs_src_loc.span(ctx.zcu.gpa) catch |e| {
3138 ctx.err.* = e;
3139 return lhs_index < rhs_index;
3140 }).main;
3141 }
3142 };
3143 var err: ?SortOrder.Error = null;
3144 // This leaves `zcu.failed_analysis` an invalid state, but we do not
3145 // need lookups anymore anyway.
3146 zcu.failed_analysis.entries.sort(SortOrder{ .zcu = zcu, .err = &err });
3147 if (err) |e| return e;
3148 }
3098 for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| {3149 for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| {
3099 const decl_index = switch (anal_unit.unwrap()) {3150 const decl_index = switch (anal_unit.unwrap()) {
3100 .decl => |d| d,3151 .decl => |d| d,
...@@ -3543,18 +3594,18 @@ fn performAllTheWorkInner(...@@ -3543,18 +3594,18 @@ fn performAllTheWorkInner(
3543 comp.codegen_work.cond.signal();3594 comp.codegen_work.cond.signal();
3544 };3595 };
35453596
3546 while (true) {3597 work: while (true) {
3547 if (comp.work_queue.readItem()) |work_item| {3598 for (&comp.work_queues) |*work_queue| if (work_queue.readItem()) |job| {
3548 try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, work_item, main_progress_node);3599 try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, job, main_progress_node);
3549 continue;3600 continue :work;
3550 }3601 };
3551 if (comp.module) |zcu| {3602 if (comp.module) |zcu| {
3552 // If there's no work queued, check if there's anything outdated3603 // If there's no work queued, check if there's anything outdated
3553 // which we need to work on, and queue it if so.3604 // which we need to work on, and queue it if so.
3554 if (try zcu.findOutdatedToAnalyze()) |outdated| {3605 if (try zcu.findOutdatedToAnalyze()) |outdated| {
3555 switch (outdated.unwrap()) {3606 switch (outdated.unwrap()) {
3556 .decl => |decl| try comp.work_queue.writeItem(.{ .analyze_decl = decl }),3607 .decl => |decl| try comp.queueJob(.{ .analyze_decl = decl }),
3557 .func => |func| try comp.work_queue.writeItem(.{ .analyze_func = func }),3608 .func => |func| try comp.queueJob(.{ .analyze_func = func }),
3558 }3609 }
3559 continue;3610 continue;
3560 }3611 }
...@@ -3575,6 +3626,14 @@ fn performAllTheWorkInner(...@@ -3575,6 +3626,14 @@ fn performAllTheWorkInner(
35753626
3576const JobError = Allocator.Error;3627const JobError = Allocator.Error;
35773628
3629pub fn queueJob(comp: *Compilation, job: Job) !void {
3630 try comp.work_queues[Job.stage(job)].writeItem(job);
3631}
3632
3633pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void {
3634 for (jobs) |job| try comp.queueJob(job);
3635}
3636
3578fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progress.Node) JobError!void {3637fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progress.Node) JobError!void {
3579 switch (job) {3638 switch (job) {
3580 .codegen_decl => |decl_index| {3639 .codegen_decl => |decl_index| {
...@@ -6478,7 +6537,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -6478,7 +6537,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {
6478 };6537 };
6479 const target = comp.root_mod.resolved_target.result;6538 const target = comp.root_mod.resolved_target.result;
6480 if (target.os.tag == .windows and target.ofmt != .c) {6539 if (target.os.tag == .windows and target.ofmt != .c) {
6481 try comp.work_queue.writeItem(.{6540 try comp.queueJob(.{
6482 .windows_import_lib = comp.system_libs.count() - 1,6541 .windows_import_lib = comp.system_libs.count() - 1,
6483 });6542 });
6484 }6543 }
src/Sema.zig+4-4
...@@ -2853,7 +2853,7 @@ fn zirStructDecl(...@@ -2853,7 +2853,7 @@ fn zirStructDecl(
2853 }2853 }
28542854
2855 try pt.finalizeAnonDecl(new_decl_index);2855 try pt.finalizeAnonDecl(new_decl_index);
2856 try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });2856 try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
2857 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));2857 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
2858 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));2858 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));
2859}2859}
...@@ -3358,7 +3358,7 @@ fn zirUnionDecl(...@@ -3358,7 +3358,7 @@ fn zirUnionDecl(
3358 }3358 }
33593359
3360 try pt.finalizeAnonDecl(new_decl_index);3360 try pt.finalizeAnonDecl(new_decl_index);
3361 try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });3361 try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
3362 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));3362 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
3363 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));3363 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));
3364}3364}
...@@ -22203,7 +22203,7 @@ fn reifyUnion(...@@ -22203,7 +22203,7 @@ fn reifyUnion(
22203 loaded_union.setStatus(ip, .have_field_types);22203 loaded_union.setStatus(ip, .have_field_types);
2220422204
22205 try pt.finalizeAnonDecl(new_decl_index);22205 try pt.finalizeAnonDecl(new_decl_index);
22206 try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });22206 try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
22207 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));22207 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
22208 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));22208 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));
22209}22209}
...@@ -22470,7 +22470,7 @@ fn reifyStruct(...@@ -22470,7 +22470,7 @@ fn reifyStruct(
22470 }22470 }
2247122471
22472 try pt.finalizeAnonDecl(new_decl_index);22472 try pt.finalizeAnonDecl(new_decl_index);
22473 try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });22473 try mod.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
22474 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));22474 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
22475 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));22475 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));
22476}22476}
src/Zcu.zig+2-2
...@@ -2983,11 +2983,11 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)...@@ -2983,11 +2983,11 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)
29832983
2984 // Decl itself is safely analyzed, and body analysis is not yet queued2984 // Decl itself is safely analyzed, and body analysis is not yet queued
29852985
2986 try mod.comp.work_queue.writeItem(.{ .analyze_func = func_index });2986 try mod.comp.queueJob(.{ .analyze_func = func_index });
2987 if (mod.emit_h != null) {2987 if (mod.emit_h != null) {
2988 // TODO: we ideally only want to do this if the function's type changed2988 // TODO: we ideally only want to do this if the function's type changed
2989 // since the last update2989 // since the last update
2990 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });2990 try mod.comp.queueJob(.{ .emit_h_decl = decl_index });
2991 }2991 }
2992 func.setAnalysisState(ip, .queued);2992 func.setAnalysisState(ip, .queued);
2993}2993}
src/Zcu/PerThread.zig+7-9
...@@ -729,7 +729,7 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -729,7 +729,7 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
729 return;729 return;
730 }730 }
731731
732 try comp.work_queue.writeItem(.{ .codegen_func = .{732 try comp.queueJob(.{ .codegen_func = .{
733 .func = func_index,733 .func = func_index,
734 .air = air,734 .air = air,
735 } });735 } });
...@@ -903,7 +903,7 @@ fn getFileRootStruct(...@@ -903,7 +903,7 @@ fn getFileRootStruct(
903 decl.analysis = .complete;903 decl.analysis = .complete;
904904
905 try pt.scanNamespace(namespace_index, decls, decl);905 try pt.scanNamespace(namespace_index, decls, decl);
906 try zcu.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });906 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
907 return wip_ty.finish(ip, decl_index, namespace_index.toOptional());907 return wip_ty.finish(ip, decl_index, namespace_index.toOptional());
908}908}
909909
...@@ -1311,10 +1311,10 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {...@@ -1311,10 +1311,10 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
1311 // codegen backend wants full access to the Decl Type.1311 // codegen backend wants full access to the Decl Type.
1312 try decl_ty.resolveFully(pt);1312 try decl_ty.resolveFully(pt);
13131313
1314 try zcu.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });1314 try zcu.comp.queueJob(.{ .codegen_decl = decl_index });
13151315
1316 if (result.invalidate_decl_ref and zcu.emit_h != null) {1316 if (result.invalidate_decl_ref and zcu.emit_h != null) {
1317 try zcu.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });1317 try zcu.comp.queueJob(.{ .emit_h_decl = decl_index });
1318 }1318 }
1319 }1319 }
13201320
...@@ -1740,8 +1740,6 @@ pub fn scanNamespace(...@@ -1740,8 +1740,6 @@ pub fn scanNamespace(
1740 var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};1740 var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
1741 defer seen_decls.deinit(gpa);1741 defer seen_decls.deinit(gpa);
17421742
1743 try zcu.comp.work_queue.ensureUnusedCapacity(decls.len);
1744
1745 namespace.decls.clearRetainingCapacity();1743 namespace.decls.clearRetainingCapacity();
1746 try namespace.decls.ensureTotalCapacity(gpa, decls.len);1744 try namespace.decls.ensureTotalCapacity(gpa, decls.len);
17471745
...@@ -1967,7 +1965,7 @@ const ScanDeclIter = struct {...@@ -1967,7 +1965,7 @@ const ScanDeclIter = struct {
1967 log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{}' decl_index={d}", .{1965 log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{}' decl_index={d}", .{
1968 namespace.fileScope(zcu).sub_file_path, decl_name.fmt(ip), decl_index,1966 namespace.fileScope(zcu).sub_file_path, decl_name.fmt(ip), decl_index,
1969 });1967 });
1970 comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = decl_index });1968 try comp.queueJob(.{ .analyze_decl = decl_index });
1971 }1969 }
1972 }1970 }
19731971
...@@ -1976,7 +1974,7 @@ const ScanDeclIter = struct {...@@ -1976,7 +1974,7 @@ const ScanDeclIter = struct {
1976 // updated line numbers. Look into this!1974 // updated line numbers. Look into this!
1977 // TODO Look into detecting when this would be unnecessary by storing enough state1975 // TODO Look into detecting when this would be unnecessary by storing enough state
1978 // in `Decl` to notice that the line number did not change.1976 // in `Decl` to notice that the line number did not change.
1979 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });1977 try comp.queueJob(.{ .update_line_number = decl_index });
1980 }1978 }
1981 }1979 }
1982};1980};
...@@ -1991,7 +1989,7 @@ pub fn abortAnonDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) void {...@@ -1991,7 +1989,7 @@ pub fn abortAnonDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) void {
1991/// Finalize the creation of an anon decl.1989/// Finalize the creation of an anon decl.
1992pub fn finalizeAnonDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Allocator.Error!void {1990pub fn finalizeAnonDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Allocator.Error!void {
1993 if (pt.zcu.declPtr(decl_index).typeOf(pt.zcu).isFnOrHasRuntimeBits(pt)) {1991 if (pt.zcu.declPtr(decl_index).typeOf(pt.zcu).isFnOrHasRuntimeBits(pt)) {
1994 try pt.zcu.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });1992 try pt.zcu.comp.queueJob(.{ .codegen_decl = decl_index });
1995 }1993 }
1996}1994}
19971995
src/codegen/llvm.zig+1-1
...@@ -1625,7 +1625,7 @@ pub const Object = struct {...@@ -1625,7 +1625,7 @@ pub const Object = struct {
1625 llvm_arg_i += 1;1625 llvm_arg_i += 1;
16261626
1627 const alignment = param_ty.abiAlignment(pt).toLlvm();1627 const alignment = param_ty.abiAlignment(pt).toLlvm();
1628 const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target);1628 const arg_ptr = try buildAllocaInner(&wip, param.typeOfWip(&wip), alignment, target);
1629 _ = try wip.store(.normal, param, arg_ptr, alignment);1629 _ = try wip.store(.normal, param, arg_ptr, alignment);
16301630
1631 args.appendAssumeCapacity(if (isByRef(param_ty, pt))1631 args.appendAssumeCapacity(if (isByRef(param_ty, pt))
test/cases/compile_errors/bogus_method_call_on_slice.zig+1-1
...@@ -16,6 +16,6 @@ pub export fn entry2() void {...@@ -16,6 +16,6 @@ pub export fn entry2() void {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
19// :3:6: error: no field or member function named 'copy' in '[]const u8'
19// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'20// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
20// :12:18: error: no field or member function named 'bar' in 'struct{comptime foo: comptime_int = 1}'21// :12:18: error: no field or member function named 'bar' in 'struct{comptime foo: comptime_int = 1}'
21// :3:6: error: no field or member function named 'copy' in '[]const u8'
test/cases/compile_errors/compile_log.zig+2-2
...@@ -17,14 +17,14 @@ export fn baz() void {...@@ -17,14 +17,14 @@ export fn baz() void {
17// target=native17// target=native
18//18//
19// :6:5: error: found compile log statement19// :6:5: error: found compile log statement
20// :12:5: note: also here
21// :6:5: note: also here20// :6:5: note: also here
21// :12:5: note: also here
22//22//
23// Compile Log Output:23// Compile Log Output:
24// @as(*const [5:0]u8, "begin")24// @as(*const [5:0]u8, "begin")
25// @as(*const [1:0]u8, "a"), @as(i32, 12), @as(*const [1:0]u8, "b"), @as([]const u8, "hi"[0..2])25// @as(*const [1:0]u8, "a"), @as(i32, 12), @as(*const [1:0]u8, "b"), @as([]const u8, "hi"[0..2])
26// @as(*const [3:0]u8, "end")26// @as(*const [3:0]u8, "end")
27// @as(comptime_int, 4)
28// @as(*const [5:0]u8, "begin")27// @as(*const [5:0]u8, "begin")
29// @as(*const [1:0]u8, "a"), @as(i32, [runtime value]), @as(*const [1:0]u8, "b"), @as([]const u8, [runtime value])28// @as(*const [1:0]u8, "a"), @as(i32, [runtime value]), @as(*const [1:0]u8, "b"), @as([]const u8, [runtime value])
30// @as(*const [3:0]u8, "end")29// @as(*const [3:0]u8, "end")
30// @as(comptime_int, 4)
test/cases/compile_errors/extern_function_with_comptime_parameter.zig+1-1
...@@ -18,6 +18,6 @@ comptime {...@@ -18,6 +18,6 @@ comptime {
18// backend=stage218// backend=stage2
19// target=native19// target=native
20//20//
21// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
21// :5:30: error: comptime parameters not allowed in function with calling convention 'C'22// :5:30: error: comptime parameters not allowed in function with calling convention 'C'
22// :6:30: error: generic parameters not allowed in function with calling convention 'C'23// :6:30: error: generic parameters not allowed in function with calling convention 'C'
23// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
test/cases/compile_errors/invalid_store_to_comptime_field.zig+1-1
...@@ -82,6 +82,6 @@ pub export fn entry8() void {...@@ -82,6 +82,6 @@ pub export fn entry8() void {
82// :36:29: note: default value set here82// :36:29: note: default value set here
83// :46:12: error: value stored in comptime field does not match the default value of the field83// :46:12: error: value stored in comptime field does not match the default value of the field
84// :55:25: error: value stored in comptime field does not match the default value of the field84// :55:25: error: value stored in comptime field does not match the default value of the field
85// :68:36: error: value stored in comptime field does not match the default value of the field
86// :61:30: error: value stored in comptime field does not match the default value of the field85// :61:30: error: value stored in comptime field does not match the default value of the field
87// :59:29: note: default value set here86// :59:29: note: default value set here
87// :68:36: error: value stored in comptime field does not match the default value of the field
test/cases/compile_errors/invalid_variadic_function.zig+1-1
...@@ -18,6 +18,6 @@ comptime {...@@ -18,6 +18,6 @@ comptime {
18//18//
19// :1:1: error: variadic function does not support '.Unspecified' calling convention19// :1:1: error: variadic function does not support '.Unspecified' calling convention
20// :1:1: note: supported calling conventions: '.C'20// :1:1: note: supported calling conventions: '.C'
21// :2:1: error: generic function cannot be variadic
22// :1:1: error: variadic function does not support '.Inline' calling convention21// :1:1: error: variadic function does not support '.Inline' calling convention
23// :1:1: note: supported calling conventions: '.C'22// :1:1: note: supported calling conventions: '.C'
23// :2:1: error: generic function cannot be variadic
test/cases/error_in_nested_declaration.zig+1-1
...@@ -26,6 +26,6 @@ pub export fn entry2() void {...@@ -26,6 +26,6 @@ pub export fn entry2() void {
26// backend=llvm26// backend=llvm
27// target=native27// target=native
28//28//
29// :17:12: error: C pointers cannot point to opaque types
30// :6:20: error: cannot @bitCast to '[]i32'29// :6:20: error: cannot @bitCast to '[]i32'
31// :6:20: note: use @ptrCast to cast from '[]u32'30// :6:20: note: use @ptrCast to cast from '[]u32'
31// :17:12: error: C pointers cannot point to opaque types