authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-12-06 15:27:57+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-12-22 12:55:16+00:00
log18bc7e802f8b4460216ae2169f81abddd108599f
treee0ae2276660fd37218bd4c66c4f33b8aabe10f7d
parent9ae4e38ca27e1b14e84f58594b8be4513f1fcfbe
signaturelock-open Commit is signed but in an unrecognized format.

compiler: replace thread pool with `std.Io`

Eliminate the `std.Thread.Pool` used in the compiler for concurrency and asynchrony, in favour of the new `std.Io.async` and `std.Io.concurrent` primitives. This removes the last usage of `std.Thread.Pool` in the Zig repository.

33 files changed, 2234 insertions(+), 1701 deletions(-)

src/Compilation.zig+421-466
...@@ -10,8 +10,6 @@ const Allocator = std.mem.Allocator;...@@ -10,8 +10,6 @@ const Allocator = std.mem.Allocator;
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const log = std.log.scoped(.compilation);11const log = std.log.scoped(.compilation);
12const Target = std.Target;12const Target = std.Target;
13const ThreadPool = std.Thread.Pool;
14const WaitGroup = std.Thread.WaitGroup;
15const ErrorBundle = std.zig.ErrorBundle;13const ErrorBundle = std.zig.ErrorBundle;
16const fatal = std.process.fatal;14const fatal = std.process.fatal;
1715
...@@ -56,6 +54,7 @@ gpa: Allocator,...@@ -56,6 +54,7 @@ gpa: Allocator,
56/// threads at once.54/// threads at once.
57arena: Allocator,55arena: Allocator,
58io: Io,56io: Io,
57thread_limit: usize,
59/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.58/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
60zcu: ?*Zcu,59zcu: ?*Zcu,
61/// Contains different state depending on the `CacheMode` used by this `Compilation`.60/// Contains different state depending on the `CacheMode` used by this `Compilation`.
...@@ -110,7 +109,14 @@ win32_resource_table: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMa...@@ -110,7 +109,14 @@ win32_resource_table: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMa
110} = .{},109} = .{},
111110
112link_diags: link.Diags,111link_diags: link.Diags,
113link_task_queue: link.Queue = .empty,112link_queue: link.Queue = .empty,
113
114/// This is populated during `Compilation.create` with a set of prelink tasks which need to be
115/// queued on the first update. In `update`, we will send these tasks to the linker, and clear
116/// them from this list.
117///
118/// Allocated into `gpa`.
119oneshot_prelink_tasks: std.ArrayList(link.PrelinkTask),
114120
115/// Set of work that can be represented by only flags to determine whether the121/// Set of work that can be represented by only flags to determine whether the
116/// work is queued or not.122/// work is queued or not.
...@@ -198,7 +204,6 @@ libc_include_dir_list: []const []const u8,...@@ -198,7 +204,6 @@ libc_include_dir_list: []const []const u8,
198libc_framework_dir_list: []const []const u8,204libc_framework_dir_list: []const []const u8,
199rc_includes: std.zig.RcIncludes,205rc_includes: std.zig.RcIncludes,
200mingw_unicode_entry_point: bool,206mingw_unicode_entry_point: bool,
201thread_pool: *ThreadPool,
202207
203/// Populated when we build the libc++ static library. A Job to build this is placed in the queue208/// Populated when we build the libc++ static library. A Job to build this is placed in the queue
204/// and resolved before calling linker.flush().209/// and resolved before calling linker.flush().
...@@ -248,16 +253,10 @@ crt_files: std.StringHashMapUnmanaged(CrtFile) = .empty,...@@ -248,16 +253,10 @@ crt_files: std.StringHashMapUnmanaged(CrtFile) = .empty,
248reference_trace: ?u32 = null,253reference_trace: ?u32 = null,
249254
250/// This mutex guards all `Compilation` mutable state.255/// This mutex guards all `Compilation` mutable state.
251/// Disabled in single-threaded mode because the thread pool spawns in the same thread.256mutex: std.Io.Mutex = .init,
252mutex: if (builtin.single_threaded) struct {
253 pub inline fn tryLock(_: @This()) void {}
254 pub inline fn lock(_: @This()) void {}
255 pub inline fn unlock(_: @This()) void {}
256} else std.Thread.Mutex = .{},
257257
258test_filters: []const []const u8,258test_filters: []const []const u8,
259259
260link_task_wait_group: WaitGroup = .{},
261link_prog_node: std.Progress.Node = .none,260link_prog_node: std.Progress.Node = .none,
262261
263llvm_opt_bisect_limit: c_int,262llvm_opt_bisect_limit: c_int,
...@@ -1568,7 +1567,7 @@ pub const CacheMode = enum {...@@ -1568,7 +1567,7 @@ pub const CacheMode = enum {
15681567
1569pub const ParentWholeCache = struct {1568pub const ParentWholeCache = struct {
1570 manifest: *Cache.Manifest,1569 manifest: *Cache.Manifest,
1571 mutex: *std.Thread.Mutex,1570 mutex: *std.Io.Mutex,
1572 prefix_map: [4]u8,1571 prefix_map: [4]u8,
1573};1572};
15741573
...@@ -1596,7 +1595,7 @@ const CacheUse = union(CacheMode) {...@@ -1596,7 +1595,7 @@ const CacheUse = union(CacheMode) {
1596 lf_open_opts: link.File.OpenOptions,1595 lf_open_opts: link.File.OpenOptions,
1597 /// This is a pointer to a local variable inside `update`.1596 /// This is a pointer to a local variable inside `update`.
1598 cache_manifest: ?*Cache.Manifest,1597 cache_manifest: ?*Cache.Manifest,
1599 cache_manifest_mutex: std.Thread.Mutex,1598 cache_manifest_mutex: std.Io.Mutex,
1600 /// This is non-`null` for most of the body of `update`. It is the temporary directory which1599 /// This is non-`null` for most of the body of `update`. It is the temporary directory which
1601 /// we initially emit our artifacts to. After the main part of the update is done, it will1600 /// we initially emit our artifacts to. After the main part of the update is done, it will
1602 /// be closed and moved to its final location, and this field set to `null`.1601 /// be closed and moved to its final location, and this field set to `null`.
...@@ -1636,7 +1635,7 @@ const CacheUse = union(CacheMode) {...@@ -1636,7 +1635,7 @@ const CacheUse = union(CacheMode) {
16361635
1637pub const CreateOptions = struct {1636pub const CreateOptions = struct {
1638 dirs: Directories,1637 dirs: Directories,
1639 thread_pool: *ThreadPool,1638 thread_limit: usize,
1640 self_exe_path: ?[]const u8 = null,1639 self_exe_path: ?[]const u8 = null,
16411640
1642 /// Options that have been resolved by calling `resolveDefaults`.1641 /// Options that have been resolved by calling `resolveDefaults`.
...@@ -2211,8 +2210,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2211,8 +2210,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2211 .llvm_object = null,2210 .llvm_object = null,
2212 .analysis_roots_buffer = undefined,2211 .analysis_roots_buffer = undefined,
2213 .analysis_roots_len = 0,2212 .analysis_roots_len = 0,
2213 .codegen_task_pool = try .init(arena),
2214 };2214 };
2215 try zcu.init(options.thread_pool.getIdCount());2215 try zcu.init(gpa, io, options.thread_limit);
2216 break :blk zcu;2216 break :blk zcu;
2217 } else blk: {2217 } else blk: {
2218 if (options.emit_h != .no) return diag.fail(.emit_h_without_zcu);2218 if (options.emit_h != .no) return diag.fail(.emit_h_without_zcu);
...@@ -2224,6 +2224,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2224,6 +2224,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2224 .gpa = gpa,2224 .gpa = gpa,
2225 .arena = arena,2225 .arena = arena,
2226 .io = io,2226 .io = io,
2227 .thread_limit = options.thread_limit,
2227 .zcu = opt_zcu,2228 .zcu = opt_zcu,
2228 .cache_use = undefined, // populated below2229 .cache_use = undefined, // populated below
2229 .bin_file = null, // populated below if necessary2230 .bin_file = null, // populated below if necessary
...@@ -2241,7 +2242,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2241,7 +2242,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2241 .libc_framework_dir_list = libc_dirs.libc_framework_dir_list,2242 .libc_framework_dir_list = libc_dirs.libc_framework_dir_list,
2242 .rc_includes = options.rc_includes,2243 .rc_includes = options.rc_includes,
2243 .mingw_unicode_entry_point = options.mingw_unicode_entry_point,2244 .mingw_unicode_entry_point = options.mingw_unicode_entry_point,
2244 .thread_pool = options.thread_pool,
2245 .clang_passthrough_mode = options.clang_passthrough_mode,2245 .clang_passthrough_mode = options.clang_passthrough_mode,
2246 .clang_preprocessor_mode = options.clang_preprocessor_mode,2246 .clang_preprocessor_mode = options.clang_preprocessor_mode,
2247 .verbose_cc = options.verbose_cc,2247 .verbose_cc = options.verbose_cc,
...@@ -2282,7 +2282,8 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2282,7 +2282,8 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2282 .global_cc_argv = options.global_cc_argv,2282 .global_cc_argv = options.global_cc_argv,
2283 .file_system_inputs = options.file_system_inputs,2283 .file_system_inputs = options.file_system_inputs,
2284 .parent_whole_cache = options.parent_whole_cache,2284 .parent_whole_cache = options.parent_whole_cache,
2285 .link_diags = .init(gpa),2285 .link_diags = .init(gpa, io),
2286 .oneshot_prelink_tasks = .empty,
2286 .emit_bin = try options.emit_bin.resolve(arena, &options, .bin),2287 .emit_bin = try options.emit_bin.resolve(arena, &options, .bin),
2287 .emit_asm = try options.emit_asm.resolve(arena, &options, .@"asm"),2288 .emit_asm = try options.emit_asm.resolve(arena, &options, .@"asm"),
2288 .emit_implib = try options.emit_implib.resolve(arena, &options, .implib),2289 .emit_implib = try options.emit_implib.resolve(arena, &options, .implib),
...@@ -2468,7 +2469,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2468,7 +2469,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2468 whole.* = .{2469 whole.* = .{
2469 .lf_open_opts = lf_open_opts,2470 .lf_open_opts = lf_open_opts,
2470 .cache_manifest = null,2471 .cache_manifest = null,
2471 .cache_manifest_mutex = .{},2472 .cache_manifest_mutex = .init,
2472 .tmp_artifact_directory = null,2473 .tmp_artifact_directory = null,
2473 .lock = null,2474 .lock = null,
2474 };2475 };
...@@ -2553,14 +2554,14 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2553,14 +2554,14 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2553 };2554 };
25542555
2555 const fields = @typeInfo(@TypeOf(paths)).@"struct".fields;2556 const fields = @typeInfo(@TypeOf(paths)).@"struct".fields;
2556 try comp.link_task_queue.queued_prelink.ensureUnusedCapacity(gpa, fields.len + 1);2557 try comp.oneshot_prelink_tasks.ensureUnusedCapacity(gpa, fields.len + 1);
2557 inline for (fields) |field| {2558 inline for (fields) |field| {
2558 if (@field(paths, field.name)) |path| {2559 if (@field(paths, field.name)) |path| {
2559 comp.link_task_queue.queued_prelink.appendAssumeCapacity(.{ .load_object = path });2560 comp.oneshot_prelink_tasks.appendAssumeCapacity(.{ .load_object = path });
2560 }2561 }
2561 }2562 }
2562 // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`.2563 // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`.
2563 comp.link_task_queue.queued_prelink.appendAssumeCapacity(.load_host_libc);2564 comp.oneshot_prelink_tasks.appendAssumeCapacity(.load_host_libc);
2564 } else if (target.isMuslLibC()) {2565 } else if (target.isMuslLibC()) {
2565 if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable);2566 if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable);
25662567
...@@ -2629,10 +2630,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2629,10 +2630,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2629 for (0..count) |i| {2630 for (0..count) |i| {
2630 try comp.queueJob(.{ .windows_import_lib = i });2631 try comp.queueJob(.{ .windows_import_lib = i });
2631 }2632 }
2632 // when integrating coff linker with prelink, the above2633 // when integrating coff linker with prelink, the above `queueJob` will need to move
2633 // queueJob will need to change into something else since those2634 // to something in `dispatchPrelinkWork`, which must queue all prelink link tasks
2634 // jobs are dispatched *after* the link_task_wait_group.wait()2635 // *before* we begin working on the main job queue.
2635 // that happens when separateCodegenThreadOk() is false.
2636 }2636 }
2637 if (comp.wantBuildLibUnwindFromSource()) {2637 if (comp.wantBuildLibUnwindFromSource()) {
2638 comp.queued_jobs.libunwind = true;2638 comp.queued_jobs.libunwind = true;
...@@ -2681,19 +2681,15 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2681,19 +2681,15 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2681 }2681 }
2682 }2682 }
26832683
2684 try comp.link_task_queue.queued_prelink.append(gpa, .load_explicitly_provided);2684 try comp.oneshot_prelink_tasks.append(gpa, .load_explicitly_provided);
2685 }2685 }
2686 log.debug("queued prelink tasks: {d}", .{comp.link_task_queue.queued_prelink.items.len});2686 log.debug("queued oneshot prelink tasks: {d}", .{comp.oneshot_prelink_tasks.items.len});
2687 return comp;2687 return comp;
2688}2688}
26892689
2690pub fn destroy(comp: *Compilation) void {2690pub fn destroy(comp: *Compilation) void {
2691 const gpa = comp.gpa;2691 const gpa = comp.gpa;
26922692
2693 // This needs to be destroyed first, because it might contain MIR which we only know
2694 // how to interpret (which kind of MIR it is) from `comp.bin_file`.
2695 comp.link_task_queue.deinit(comp);
2696
2697 if (comp.bin_file) |lf| lf.destroy();2693 if (comp.bin_file) |lf| lf.destroy();
2698 if (comp.zcu) |zcu| zcu.deinit();2694 if (comp.zcu) |zcu| zcu.deinit();
2699 comp.cache_use.deinit();2695 comp.cache_use.deinit();
...@@ -2760,6 +2756,7 @@ pub fn destroy(comp: *Compilation) void {...@@ -2760,6 +2756,7 @@ pub fn destroy(comp: *Compilation) void {
2760 if (comp.time_report) |*tr| tr.deinit(gpa);2756 if (comp.time_report) |*tr| tr.deinit(gpa);
27612757
2762 comp.link_diags.deinit();2758 comp.link_diags.deinit();
2759 comp.oneshot_prelink_tasks.deinit(gpa);
27632760
2764 comp.clearMiscFailures();2761 comp.clearMiscFailures();
27652762
...@@ -2865,8 +2862,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -2865,8 +2862,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
2865 const tracy_trace = trace(@src());2862 const tracy_trace = trace(@src());
2866 defer tracy_trace.end();2863 defer tracy_trace.end();
28672864
2868 // This arena is scoped to this one update.
2869 const gpa = comp.gpa;2865 const gpa = comp.gpa;
2866 const io = comp.io;
2867
2868 // This arena is scoped to this one update.
2870 var arena_allocator = std.heap.ArenaAllocator.init(gpa);2869 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
2871 defer arena_allocator.deinit();2870 defer arena_allocator.deinit();
2872 const arena = arena_allocator.allocator();2871 const arena = arena_allocator.allocator();
...@@ -2946,8 +2945,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -2946,8 +2945,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
2946 // In this case the cache hit contains the full set of file system inputs. Nice!2945 // In this case the cache hit contains the full set of file system inputs. Nice!
2947 if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);2946 if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
2948 if (comp.parent_whole_cache) |pwc| {2947 if (comp.parent_whole_cache) |pwc| {
2949 pwc.mutex.lock();2948 try pwc.mutex.lock(io);
2950 defer pwc.mutex.unlock();2949 defer pwc.mutex.unlock(io);
2951 try man.populateOtherManifest(pwc.manifest, pwc.prefix_map);2950 try man.populateOtherManifest(pwc.manifest, pwc.prefix_map);
2952 }2951 }
29532952
...@@ -3066,7 +3065,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -3066,7 +3065,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
3066 comp.link_prog_node = .none;3065 comp.link_prog_node = .none;
3067 };3066 };
30683067
3069 try comp.performAllTheWork(main_progress_node);3068 try comp.performAllTheWork(main_progress_node, arena);
30703069
3071 if (comp.zcu) |zcu| {3070 if (comp.zcu) |zcu| {
3072 const pt: Zcu.PerThread = .activate(zcu, .main);3071 const pt: Zcu.PerThread = .activate(zcu, .main);
...@@ -3132,8 +3131,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -3132,8 +3131,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
3132 .whole => |whole| {3131 .whole => |whole| {
3133 if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);3132 if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
3134 if (comp.parent_whole_cache) |pwc| {3133 if (comp.parent_whole_cache) |pwc| {
3135 pwc.mutex.lock();3134 try pwc.mutex.lock(io);
3136 defer pwc.mutex.unlock();3135 defer pwc.mutex.unlock(io);
3137 try man.populateOtherManifest(pwc.manifest, pwc.prefix_map);3136 try man.populateOtherManifest(pwc.manifest, pwc.prefix_map);
3138 }3137 }
31393138
...@@ -3234,6 +3233,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -3234,6 +3233,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
3234/// Thread-safe. Assumes that `comp.mutex` is *not* already held by the caller.3233/// Thread-safe. Assumes that `comp.mutex` is *not* already held by the caller.
3235pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocator.Error!void {3234pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocator.Error!void {
3236 const gpa = comp.gpa;3235 const gpa = comp.gpa;
3236 const io = comp.io;
3237 const fsi = comp.file_system_inputs orelse return;3237 const fsi = comp.file_system_inputs orelse return;
3238 const prefixes = comp.cache_parent.prefixes();3238 const prefixes = comp.cache_parent.prefixes();
32393239
...@@ -3253,8 +3253,8 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat...@@ -3253,8 +3253,8 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat
3253 );3253 );
32543254
3255 // There may be concurrent calls to this function from C object workers and/or the main thread.3255 // There may be concurrent calls to this function from C object workers and/or the main thread.
3256 comp.mutex.lock();3256 comp.mutex.lockUncancelable(io);
3257 defer comp.mutex.unlock();3257 defer comp.mutex.unlock(io);
32583258
3259 try fsi.ensureUnusedCapacity(gpa, path.sub_path.len + 3);3259 try fsi.ensureUnusedCapacity(gpa, path.sub_path.len + 3);
3260 if (fsi.items.len > 0) fsi.appendAssumeCapacity(0);3260 if (fsi.items.len > 0) fsi.appendAssumeCapacity(0);
...@@ -3305,6 +3305,7 @@ fn flush(...@@ -3305,6 +3305,7 @@ fn flush(
3305 arena: Allocator,3305 arena: Allocator,
3306 tid: Zcu.PerThread.Id,3306 tid: Zcu.PerThread.Id,
3307) Allocator.Error!void {3307) Allocator.Error!void {
3308 const io = comp.io;
3308 if (comp.zcu) |zcu| {3309 if (comp.zcu) |zcu| {
3309 if (zcu.llvm_object) |llvm_object| {3310 if (zcu.llvm_object) |llvm_object| {
3310 const pt: Zcu.PerThread = .activate(zcu, tid);3311 const pt: Zcu.PerThread = .activate(zcu, tid);
...@@ -3317,8 +3318,8 @@ fn flush(...@@ -3317,8 +3318,8 @@ fn flush(
33173318
3318 var timer = comp.startTimer();3319 var timer = comp.startTimer();
3319 defer if (timer.finish()) |ns| {3320 defer if (timer.finish()) |ns| {
3320 comp.mutex.lock();3321 comp.mutex.lockUncancelable(io);
3321 defer comp.mutex.unlock();3322 defer comp.mutex.unlock(io);
3322 comp.time_report.?.stats.real_ns_llvm_emit = ns;3323 comp.time_report.?.stats.real_ns_llvm_emit = ns;
3323 };3324 };
33243325
...@@ -3362,8 +3363,8 @@ fn flush(...@@ -3362,8 +3363,8 @@ fn flush(
3362 if (comp.bin_file) |lf| {3363 if (comp.bin_file) |lf| {
3363 var timer = comp.startTimer();3364 var timer = comp.startTimer();
3364 defer if (timer.finish()) |ns| {3365 defer if (timer.finish()) |ns| {
3365 comp.mutex.lock();3366 comp.mutex.lockUncancelable(io);
3366 defer comp.mutex.unlock();3367 defer comp.mutex.unlock(io);
3367 comp.time_report.?.stats.real_ns_link_flush = ns;3368 comp.time_report.?.stats.real_ns_link_flush = ns;
3368 };3369 };
3369 // This is needed before reading the error flags.3370 // This is needed before reading the error flags.
...@@ -4575,44 +4576,277 @@ pub fn unableToLoadZcuFile(...@@ -4575,44 +4576,277 @@ pub fn unableToLoadZcuFile(
4575fn performAllTheWork(4576fn performAllTheWork(
4576 comp: *Compilation,4577 comp: *Compilation,
4577 main_progress_node: std.Progress.Node,4578 main_progress_node: std.Progress.Node,
4579 update_arena: Allocator,
4578) JobError!void {4580) JobError!void {
4579 // Regardless of errors, `comp.zcu` needs to update its generation number.
4580 defer if (comp.zcu) |zcu| {4581 defer if (comp.zcu) |zcu| {
4582 zcu.codegen_task_pool.cancel(zcu);
4583 // Regardless of errors, `comp.zcu` needs to update its generation number.
4581 zcu.generation += 1;4584 zcu.generation += 1;
4582 };4585 };
45834586
4587 const io = comp.io;
4588
4584 // This is awkward: we don't want to start the timer until later, but we won't want to stop it4589 // This is awkward: we don't want to start the timer until later, but we won't want to stop it
4585 // until the wait groups finish. That means we need do do this.4590 // until the wait groups finish. That means we need do do this.
4586 var decl_work_timer: ?Timer = null;4591 var decl_work_timer: ?Timer = null;
4587 defer commit_timer: {4592 defer commit_timer: {
4588 const t = &(decl_work_timer orelse break :commit_timer);4593 const t = &(decl_work_timer orelse break :commit_timer);
4589 const ns = t.finish() orelse break :commit_timer;4594 const ns = t.finish() orelse break :commit_timer;
4590 comp.mutex.lock();4595 comp.mutex.lockUncancelable(io);
4591 defer comp.mutex.unlock();4596 defer comp.mutex.unlock(io);
4592 comp.time_report.?.stats.real_ns_decls = ns;4597 comp.time_report.?.stats.real_ns_decls = ns;
4593 }4598 }
45944599
4595 // Here we queue up all the AstGen tasks first, followed by C object compilation.4600 var misc_group: Io.Group = .init;
4596 // We wait until the AstGen tasks are all completed before proceeding to the4601 defer misc_group.cancel(io);
4597 // (at least for now) single-threaded main work queue. However, C object compilation
4598 // only needs to be finished by the end of this function.
4599
4600 var work_queue_wait_group: WaitGroup = .{};
4601 defer work_queue_wait_group.wait();
46024602
4603 comp.link_task_wait_group.reset();4603 try comp.link_queue.start(comp, update_arena);
4604 defer comp.link_task_wait_group.wait();4604 defer comp.link_queue.cancel(io);
46054605
4606 // Already-queued prelink tasks4606 misc_group.concurrent(io, dispatchPrelinkWork, .{ comp, main_progress_node }) catch |err| switch (err) {
4607 comp.link_prog_node.increaseEstimatedTotalItems(comp.link_task_queue.queued_prelink.items.len);4607 error.ConcurrencyUnavailable => {
4608 comp.link_task_queue.start(comp);4608 // Do it immediately so that the link queue isn't blocked
4609 dispatchPrelinkWork(comp, main_progress_node);
4610 },
4611 };
46094612
4610 if (comp.emit_docs != null) {4613 if (comp.emit_docs != null) {
4611 dev.check(.docs_emit);4614 dev.check(.docs_emit);
4612 comp.thread_pool.spawnWg(&work_queue_wait_group, workerDocsCopy, .{comp});4615 misc_group.async(io, workerDocsCopy, .{comp});
4613 work_queue_wait_group.spawnManager(workerDocsWasm, .{ comp, main_progress_node });4616 misc_group.async(io, workerDocsWasm, .{ comp, main_progress_node });
4617 }
4618
4619 if (comp.zcu) |zcu| {
4620 const astgen_frame = tracy.namedFrame("astgen");
4621 defer astgen_frame.end();
4622
4623 const zir_prog_node = main_progress_node.start("AST Lowering", 0);
4624 defer zir_prog_node.end();
4625
4626 var timer = comp.startTimer();
4627 defer if (timer.finish()) |ns| {
4628 comp.mutex.lockUncancelable(io);
4629 defer comp.mutex.unlock(io);
4630 comp.time_report.?.stats.real_ns_files = ns;
4631 };
4632
4633 const gpa = comp.gpa;
4634
4635 var astgen_group: Io.Group = .init;
4636 defer astgen_group.cancel(io);
4637
4638 // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs,
4639 // because on single-threaded targets the worker will be run eagerly, meaning the
4640 // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So,
4641 // build up a list of the files to update *before* we spawn any jobs.
4642 var astgen_work_items: std.MultiArrayList(struct {
4643 file_index: Zcu.File.Index,
4644 file: *Zcu.File,
4645 }) = .empty;
4646 defer astgen_work_items.deinit(gpa);
4647 // Not every item in `import_table` will need updating, because some are builtin.zig
4648 // files. However, most will, so let's just reserve sufficient capacity upfront.
4649 try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count());
4650 for (zcu.import_table.keys()) |file_index| {
4651 const file = zcu.fileByIndex(file_index);
4652 if (file.is_builtin) {
4653 // This is a `builtin.zig`, so updating is redundant. However, we want to make
4654 // sure the file contents are still correct on disk, since it can improve the
4655 // debugging experience better. That job only needs `file`, so we can kick it
4656 // off right now.
4657 astgen_group.async(io, workerUpdateBuiltinFile, .{ comp, file });
4658 continue;
4659 }
4660 astgen_work_items.appendAssumeCapacity(.{
4661 .file_index = file_index,
4662 .file = file,
4663 });
4664 }
4665
4666 // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs.
4667 for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| {
4668 astgen_group.async(io, workerUpdateFile, .{
4669 comp, file, file_index, zir_prog_node, &astgen_group,
4670 });
4671 }
4672
4673 // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here
4674 // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one
4675 // `@embedFile` can't trigger analysis of a new `@embedFile`!
4676 for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| {
4677 const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize);
4678 astgen_group.async(io, workerUpdateEmbedFile, .{
4679 comp, ef_index, ef,
4680 });
4681 }
4682
4683 astgen_group.wait(io);
4684 }
4685
4686 if (comp.zcu) |zcu| {
4687 const pt: Zcu.PerThread = .activate(zcu, .main);
4688 defer pt.deactivate();
4689
4690 const gpa = zcu.gpa;
4691
4692 // On an incremental update, a source file might become "dead", in that all imports of
4693 // the file were removed. This could even change what module the file belongs to! As such,
4694 // we do a traversal over the files, to figure out which ones are alive and the modules
4695 // they belong to.
4696 const any_fatal_files = try pt.computeAliveFiles();
4697
4698 // If the cache mode is `whole`, add every alive source file to the manifest.
4699 switch (comp.cache_use) {
4700 .whole => |whole| if (whole.cache_manifest) |man| {
4701 for (zcu.alive_files.keys()) |file_index| {
4702 const file = zcu.fileByIndex(file_index);
4703
4704 switch (file.status) {
4705 .never_loaded => unreachable, // AstGen tried to load it
4706 .retryable_failure => continue, // the file cannot be read; this is a guaranteed error
4707 .astgen_failure, .success => {}, // the file was read successfully
4708 }
4709
4710 const path = try file.path.toAbsolute(comp.dirs, gpa);
4711 defer gpa.free(path);
4712
4713 const result = res: {
4714 try whole.cache_manifest_mutex.lock(io);
4715 defer whole.cache_manifest_mutex.unlock(io);
4716 if (file.source) |source| {
4717 break :res man.addFilePostContents(path, source, file.stat);
4718 } else {
4719 break :res man.addFilePost(path);
4720 }
4721 };
4722 result catch |err| switch (err) {
4723 error.OutOfMemory => |e| return e,
4724 else => {
4725 try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)});
4726 continue;
4727 },
4728 };
4729 }
4730 },
4731 .none, .incremental => {},
4732 }
4733
4734 if (any_fatal_files or
4735 zcu.multi_module_err != null or
4736 zcu.failed_imports.items.len > 0 or
4737 comp.alloc_failure_occurred)
4738 {
4739 // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents
4740 // us from invalidating lots of incremental dependencies due to files with e.g. parse errors.
4741 // However, this means our analysis data is invalid, so we want to omit all analysis errors.
4742 zcu.skip_analysis_this_update = true;
4743 // Since we're skipping analysis, there are no ZCU link tasks.
4744 comp.link_queue.finishZcuQueue(comp);
4745 // Let other compilation work finish to collect as many errors as possible.
4746 misc_group.wait(io);
4747 comp.link_queue.wait(io);
4748 return;
4749 }
4750
4751 if (comp.time_report) |*tr| {
4752 tr.stats.n_reachable_files = @intCast(zcu.alive_files.count());
4753 }
4754
4755 if (comp.config.incremental) {
4756 const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0);
4757 defer update_zir_refs_node.end();
4758 try pt.updateZirRefs();
4759 }
4760 try zcu.flushRetryableFailures();
4761
4762 // It's analysis time! Queue up our initial analysis.
4763 for (zcu.analysisRoots()) |mod| {
4764 try comp.queueJob(.{ .analyze_mod = mod });
4765 }
4766
4767 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
4768 if (comp.bin_file != null) {
4769 zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
4770 }
4771 // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes.
4772 // That prevents the "Code Generation" node from constantly disappearing and reappearing when
4773 // we're probably going to analyze more functions at some point.
4774 assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes
4775 }
4776 // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation".
4777 defer if (comp.zcu) |zcu| {
4778 zcu.sema_prog_node.end();
4779 zcu.sema_prog_node = .none;
4780 if (zcu.pending_codegen_jobs.fetchSub(1, .monotonic) == 1) {
4781 // Decremented to 0, so all done.
4782 zcu.codegen_prog_node.end();
4783 zcu.codegen_prog_node = .none;
4784 }
4785 };
4786
4787 if (comp.zcu) |zcu| {
4788 if (!zcu.backendSupportsFeature(.separate_thread)) {
4789 // Close the ZCU task queue. Prelink may still be running, but the closed
4790 // queue will cause the linker task to exit once prelink finishes. The
4791 // closed queue also communicates to `enqueueZcu` that it should wait for
4792 // the linker task to finish and then run ZCU tasks serially.
4793 comp.link_queue.finishZcuQueue(comp);
4794 }
4795 }
4796
4797 if (comp.zcu != null) {
4798 // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link).
4799 decl_work_timer = comp.startTimer();
4614 }4800 }
46154801
4802 work: while (true) {
4803 for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| {
4804 try processOneJob(
4805 @intFromEnum(Zcu.PerThread.Id.main),
4806 comp,
4807 job,
4808 );
4809 continue :work;
4810 };
4811 if (comp.zcu) |zcu| {
4812 // If there's no work queued, check if there's anything outdated
4813 // which we need to work on, and queue it if so.
4814 if (try zcu.findOutdatedToAnalyze()) |outdated| {
4815 try comp.queueJob(switch (outdated.unwrap()) {
4816 .func => |f| .{ .analyze_func = f },
4817 .memoized_state,
4818 .@"comptime",
4819 .nav_ty,
4820 .nav_val,
4821 .type,
4822 => .{ .analyze_comptime_unit = outdated },
4823 });
4824 continue;
4825 }
4826 zcu.sema_prog_node.end();
4827 zcu.sema_prog_node = .none;
4828 }
4829 break;
4830 }
4831
4832 comp.link_queue.finishZcuQueue(comp);
4833
4834 // Main thread work is all done, now just wait for all async work.
4835 misc_group.wait(io);
4836 comp.link_queue.wait(io);
4837}
4838
4839fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node) void {
4840 const io = comp.io;
4841
4842 var prelink_group: Io.Group = .init;
4843 defer prelink_group.cancel(io);
4844
4845 comp.queuePrelinkTasks(comp.oneshot_prelink_tasks.items) catch |err| switch (err) {
4846 error.Canceled => return,
4847 };
4848 comp.oneshot_prelink_tasks.clearRetainingCapacity();
4849
4616 // In case it failed last time, try again. `clearMiscFailures` was already4850 // In case it failed last time, try again. `clearMiscFailures` was already
4617 // called at the start of `update`.4851 // called at the start of `update`.
4618 if (comp.queued_jobs.compiler_rt_lib and comp.compiler_rt_lib == null) {4852 if (comp.queued_jobs.compiler_rt_lib and comp.compiler_rt_lib == null) {
...@@ -4620,8 +4854,7 @@ fn performAllTheWork(...@@ -4620,8 +4854,7 @@ fn performAllTheWork(
4620 // compiler-rt due to LLD bugs as well, e.g.:4854 // compiler-rt due to LLD bugs as well, e.g.:
4621 //4855 //
4622 // https://github.com/llvm/llvm-project/issues/43698#issuecomment-25426606114856 // https://github.com/llvm/llvm-project/issues/43698#issuecomment-2542660611
4623 comp.link_task_queue.startPrelinkItem();4857 prelink_group.async(io, buildRt, .{
4624 comp.link_task_wait_group.spawnManager(buildRt, .{
4625 comp,4858 comp,
4626 "compiler_rt.zig",4859 "compiler_rt.zig",
4627 "compiler_rt",4860 "compiler_rt",
...@@ -4638,8 +4871,7 @@ fn performAllTheWork(...@@ -4638,8 +4871,7 @@ fn performAllTheWork(
4638 }4871 }
46394872
4640 if (comp.queued_jobs.compiler_rt_obj and comp.compiler_rt_obj == null) {4873 if (comp.queued_jobs.compiler_rt_obj and comp.compiler_rt_obj == null) {
4641 comp.link_task_queue.startPrelinkItem();4874 prelink_group.async(io, buildRt, .{
4642 comp.link_task_wait_group.spawnManager(buildRt, .{
4643 comp,4875 comp,
4644 "compiler_rt.zig",4876 "compiler_rt.zig",
4645 "compiler_rt",4877 "compiler_rt",
...@@ -4657,8 +4889,7 @@ fn performAllTheWork(...@@ -4657,8 +4889,7 @@ fn performAllTheWork(
46574889
4658 // hack for stage2_x86_64 + coff4890 // hack for stage2_x86_64 + coff
4659 if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) {4891 if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) {
4660 comp.link_task_queue.startPrelinkItem();4892 prelink_group.async(io, buildRt, .{
4661 comp.link_task_wait_group.spawnManager(buildRt, .{
4662 comp,4893 comp,
4663 "compiler_rt.zig",4894 "compiler_rt.zig",
4664 "compiler_rt",4895 "compiler_rt",
...@@ -4675,8 +4906,7 @@ fn performAllTheWork(...@@ -4675,8 +4906,7 @@ fn performAllTheWork(
4675 }4906 }
46764907
4677 if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) {4908 if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) {
4678 comp.link_task_queue.startPrelinkItem();4909 prelink_group.async(io, buildRt, .{
4679 comp.link_task_wait_group.spawnManager(buildRt, .{
4680 comp,4910 comp,
4681 "fuzzer.zig",4911 "fuzzer.zig",
4682 "fuzzer",4912 "fuzzer",
...@@ -4690,8 +4920,7 @@ fn performAllTheWork(...@@ -4690,8 +4920,7 @@ fn performAllTheWork(
4690 }4920 }
46914921
4692 if (comp.queued_jobs.ubsan_rt_lib and comp.ubsan_rt_lib == null) {4922 if (comp.queued_jobs.ubsan_rt_lib and comp.ubsan_rt_lib == null) {
4693 comp.link_task_queue.startPrelinkItem();4923 prelink_group.async(io, buildRt, .{
4694 comp.link_task_wait_group.spawnManager(buildRt, .{
4695 comp,4924 comp,
4696 "ubsan_rt.zig",4925 "ubsan_rt.zig",
4697 "ubsan_rt",4926 "ubsan_rt",
...@@ -4707,8 +4936,7 @@ fn performAllTheWork(...@@ -4707,8 +4936,7 @@ fn performAllTheWork(
4707 }4936 }
47084937
4709 if (comp.queued_jobs.ubsan_rt_obj and comp.ubsan_rt_obj == null) {4938 if (comp.queued_jobs.ubsan_rt_obj and comp.ubsan_rt_obj == null) {
4710 comp.link_task_queue.startPrelinkItem();4939 prelink_group.async(io, buildRt, .{
4711 comp.link_task_wait_group.spawnManager(buildRt, .{
4712 comp,4940 comp,
4713 "ubsan_rt.zig",4941 "ubsan_rt.zig",
4714 "ubsan_rt",4942 "ubsan_rt",
...@@ -4724,310 +4952,93 @@ fn performAllTheWork(...@@ -4724,310 +4952,93 @@ fn performAllTheWork(
4724 }4952 }
47254953
4726 if (comp.queued_jobs.glibc_shared_objects) {4954 if (comp.queued_jobs.glibc_shared_objects) {
4727 comp.link_task_queue.startPrelinkItem();4955 prelink_group.async(io, buildGlibcSharedObjects, .{ comp, main_progress_node });
4728 comp.link_task_wait_group.spawnManager(buildGlibcSharedObjects, .{ comp, main_progress_node });
4729 }4956 }
47304957
4731 if (comp.queued_jobs.freebsd_shared_objects) {4958 if (comp.queued_jobs.freebsd_shared_objects) {
4732 comp.link_task_queue.startPrelinkItem();4959 prelink_group.async(io, buildFreeBSDSharedObjects, .{ comp, main_progress_node });
4733 comp.link_task_wait_group.spawnManager(buildFreeBSDSharedObjects, .{ comp, main_progress_node });
4734 }4960 }
47354961
4736 if (comp.queued_jobs.netbsd_shared_objects) {4962 if (comp.queued_jobs.netbsd_shared_objects) {
4737 comp.link_task_queue.startPrelinkItem();4963 prelink_group.async(io, buildNetBSDSharedObjects, .{ comp, main_progress_node });
4738 comp.link_task_wait_group.spawnManager(buildNetBSDSharedObjects, .{ comp, main_progress_node });
4739 }4964 }
47404965
4741 if (comp.queued_jobs.libunwind) {4966 if (comp.queued_jobs.libunwind) {
4742 comp.link_task_queue.startPrelinkItem();4967 prelink_group.async(io, buildLibUnwind, .{ comp, main_progress_node });
4743 comp.link_task_wait_group.spawnManager(buildLibUnwind, .{ comp, main_progress_node });
4744 }4968 }
47454969
4746 if (comp.queued_jobs.libcxx) {4970 if (comp.queued_jobs.libcxx) {
4747 comp.link_task_queue.startPrelinkItem();4971 prelink_group.async(io, buildLibCxx, .{ comp, main_progress_node });
4748 comp.link_task_wait_group.spawnManager(buildLibCxx, .{ comp, main_progress_node });
4749 }4972 }
47504973
4751 if (comp.queued_jobs.libcxxabi) {4974 if (comp.queued_jobs.libcxxabi) {
4752 comp.link_task_queue.startPrelinkItem();4975 prelink_group.async(io, buildLibCxxAbi, .{ comp, main_progress_node });
4753 comp.link_task_wait_group.spawnManager(buildLibCxxAbi, .{ comp, main_progress_node });
4754 }4976 }
47554977
4756 if (comp.queued_jobs.libtsan) {4978 if (comp.queued_jobs.libtsan) {
4757 comp.link_task_queue.startPrelinkItem();4979 prelink_group.async(io, buildLibTsan, .{ comp, main_progress_node });
4758 comp.link_task_wait_group.spawnManager(buildLibTsan, .{ comp, main_progress_node });
4759 }4980 }
47604981
4761 if (comp.queued_jobs.zigc_lib and comp.zigc_static_lib == null) {4982 if (comp.queued_jobs.zigc_lib and comp.zigc_static_lib == null) {
4762 comp.link_task_queue.startPrelinkItem();4983 prelink_group.async(io, buildLibZigC, .{ comp, main_progress_node });
4763 comp.link_task_wait_group.spawnManager(buildLibZigC, .{ comp, main_progress_node });
4764 }4984 }
47654985
4766 for (0..@typeInfo(musl.CrtFile).@"enum".fields.len) |i| {4986 for (0..@typeInfo(musl.CrtFile).@"enum".fields.len) |i| {
4767 if (comp.queued_jobs.musl_crt_file[i]) {4987 if (comp.queued_jobs.musl_crt_file[i]) {
4768 const tag: musl.CrtFile = @enumFromInt(i);4988 const tag: musl.CrtFile = @enumFromInt(i);
4769 comp.link_task_queue.startPrelinkItem();4989 prelink_group.async(io, buildMuslCrtFile, .{ comp, tag, main_progress_node });
4770 comp.link_task_wait_group.spawnManager(buildMuslCrtFile, .{ comp, tag, main_progress_node });
4771 }4990 }
4772 }4991 }
47734992
4774 for (0..@typeInfo(glibc.CrtFile).@"enum".fields.len) |i| {4993 for (0..@typeInfo(glibc.CrtFile).@"enum".fields.len) |i| {
4775 if (comp.queued_jobs.glibc_crt_file[i]) {4994 if (comp.queued_jobs.glibc_crt_file[i]) {
4776 const tag: glibc.CrtFile = @enumFromInt(i);4995 const tag: glibc.CrtFile = @enumFromInt(i);
4777 comp.link_task_queue.startPrelinkItem();4996 prelink_group.async(io, buildGlibcCrtFile, .{ comp, tag, main_progress_node });
4778 comp.link_task_wait_group.spawnManager(buildGlibcCrtFile, .{ comp, tag, main_progress_node });
4779 }4997 }
4780 }4998 }
47814999
4782 for (0..@typeInfo(freebsd.CrtFile).@"enum".fields.len) |i| {5000 for (0..@typeInfo(freebsd.CrtFile).@"enum".fields.len) |i| {
4783 if (comp.queued_jobs.freebsd_crt_file[i]) {5001 if (comp.queued_jobs.freebsd_crt_file[i]) {
4784 const tag: freebsd.CrtFile = @enumFromInt(i);5002 const tag: freebsd.CrtFile = @enumFromInt(i);
4785 comp.link_task_queue.startPrelinkItem();5003 prelink_group.async(io, buildFreeBSDCrtFile, .{ comp, tag, main_progress_node });
4786 comp.link_task_wait_group.spawnManager(buildFreeBSDCrtFile, .{ comp, tag, main_progress_node });
4787 }5004 }
4788 }5005 }
47895006
4790 for (0..@typeInfo(netbsd.CrtFile).@"enum".fields.len) |i| {5007 for (0..@typeInfo(netbsd.CrtFile).@"enum".fields.len) |i| {
4791 if (comp.queued_jobs.netbsd_crt_file[i]) {5008 if (comp.queued_jobs.netbsd_crt_file[i]) {
4792 const tag: netbsd.CrtFile = @enumFromInt(i);5009 const tag: netbsd.CrtFile = @enumFromInt(i);
4793 comp.link_task_queue.startPrelinkItem();5010 prelink_group.async(io, buildNetBSDCrtFile, .{ comp, tag, main_progress_node });
4794 comp.link_task_wait_group.spawnManager(buildNetBSDCrtFile, .{ comp, tag, main_progress_node });
4795 }5011 }
4796 }5012 }
47975013
4798 for (0..@typeInfo(wasi_libc.CrtFile).@"enum".fields.len) |i| {5014 for (0..@typeInfo(wasi_libc.CrtFile).@"enum".fields.len) |i| {
4799 if (comp.queued_jobs.wasi_libc_crt_file[i]) {5015 if (comp.queued_jobs.wasi_libc_crt_file[i]) {
4800 const tag: wasi_libc.CrtFile = @enumFromInt(i);5016 const tag: wasi_libc.CrtFile = @enumFromInt(i);
4801 comp.link_task_queue.startPrelinkItem();5017 prelink_group.async(io, buildWasiLibcCrtFile, .{ comp, tag, main_progress_node });
4802 comp.link_task_wait_group.spawnManager(buildWasiLibcCrtFile, .{ comp, tag, main_progress_node });
4803 }5018 }
4804 }5019 }
48055020
4806 for (0..@typeInfo(mingw.CrtFile).@"enum".fields.len) |i| {5021 for (0..@typeInfo(mingw.CrtFile).@"enum".fields.len) |i| {
4807 if (comp.queued_jobs.mingw_crt_file[i]) {5022 if (comp.queued_jobs.mingw_crt_file[i]) {
4808 const tag: mingw.CrtFile = @enumFromInt(i);5023 const tag: mingw.CrtFile = @enumFromInt(i);
4809 comp.link_task_queue.startPrelinkItem();5024 prelink_group.async(io, buildMingwCrtFile, .{ comp, tag, main_progress_node });
4810 comp.link_task_wait_group.spawnManager(buildMingwCrtFile, .{ comp, tag, main_progress_node });
4811 }
4812 }
4813
4814 {
4815 const astgen_frame = tracy.namedFrame("astgen");
4816 defer astgen_frame.end();
4817
4818 const zir_prog_node = main_progress_node.start("AST Lowering", 0);
4819 defer zir_prog_node.end();
4820
4821 var timer = comp.startTimer();
4822 defer if (timer.finish()) |ns| {
4823 comp.mutex.lock();
4824 defer comp.mutex.unlock();
4825 comp.time_report.?.stats.real_ns_files = ns;
4826 };
4827
4828 var astgen_wait_group: WaitGroup = .{};
4829 defer astgen_wait_group.wait();
4830
4831 if (comp.zcu) |zcu| {
4832 const gpa = zcu.gpa;
4833
4834 // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs,
4835 // because on single-threaded targets the worker will be run eagerly, meaning the
4836 // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So,
4837 // build up a list of the files to update *before* we spawn any jobs.
4838 var astgen_work_items: std.MultiArrayList(struct {
4839 file_index: Zcu.File.Index,
4840 file: *Zcu.File,
4841 }) = .empty;
4842 defer astgen_work_items.deinit(gpa);
4843 // Not every item in `import_table` will need updating, because some are builtin.zig
4844 // files. However, most will, so let's just reserve sufficient capacity upfront.
4845 try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count());
4846 for (zcu.import_table.keys()) |file_index| {
4847 const file = zcu.fileByIndex(file_index);
4848 if (file.is_builtin) {
4849 // This is a `builtin.zig`, so updating is redundant. However, we want to make
4850 // sure the file contents are still correct on disk, since it can improve the
4851 // debugging experience better. That job only needs `file`, so we can kick it
4852 // off right now.
4853 comp.thread_pool.spawnWg(&astgen_wait_group, workerUpdateBuiltinFile, .{ comp, file });
4854 continue;
4855 }
4856 astgen_work_items.appendAssumeCapacity(.{
4857 .file_index = file_index,
4858 .file = file,
4859 });
4860 }
4861
4862 // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs.
4863 for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| {
4864 comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateFile, .{
4865 comp, file, file_index, zir_prog_node, &astgen_wait_group,
4866 });
4867 }
4868
4869 // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here
4870 // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one
4871 // `@embedFile` can't trigger analysis of a new `@embedFile`!
4872 for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| {
4873 const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize);
4874 comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateEmbedFile, .{
4875 comp, ef_index, ef,
4876 });
4877 }
4878 }
4879
4880 while (comp.c_object_work_queue.popFront()) |c_object| {
4881 comp.link_task_queue.startPrelinkItem();
4882 comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateCObject, .{
4883 comp, c_object, main_progress_node,
4884 });
4885 }
4886
4887 while (comp.win32_resource_work_queue.popFront()) |win32_resource| {
4888 comp.link_task_queue.startPrelinkItem();
4889 comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateWin32Resource, .{
4890 comp, win32_resource, main_progress_node,
4891 });
4892 }
4893 }
4894
4895 if (comp.zcu) |zcu| {
4896 const pt: Zcu.PerThread = .activate(zcu, .main);
4897 defer pt.deactivate();
4898
4899 const gpa = zcu.gpa;
4900
4901 // On an incremental update, a source file might become "dead", in that all imports of
4902 // the file were removed. This could even change what module the file belongs to! As such,
4903 // we do a traversal over the files, to figure out which ones are alive and the modules
4904 // they belong to.
4905 const any_fatal_files = try pt.computeAliveFiles();
4906
4907 // If the cache mode is `whole`, add every alive source file to the manifest.
4908 switch (comp.cache_use) {
4909 .whole => |whole| if (whole.cache_manifest) |man| {
4910 for (zcu.alive_files.keys()) |file_index| {
4911 const file = zcu.fileByIndex(file_index);
4912
4913 switch (file.status) {
4914 .never_loaded => unreachable, // AstGen tried to load it
4915 .retryable_failure => continue, // the file cannot be read; this is a guaranteed error
4916 .astgen_failure, .success => {}, // the file was read successfully
4917 }
4918
4919 const path = try file.path.toAbsolute(comp.dirs, gpa);
4920 defer gpa.free(path);
4921
4922 const result = res: {
4923 whole.cache_manifest_mutex.lock();
4924 defer whole.cache_manifest_mutex.unlock();
4925 if (file.source) |source| {
4926 break :res man.addFilePostContents(path, source, file.stat);
4927 } else {
4928 break :res man.addFilePost(path);
4929 }
4930 };
4931 result catch |err| switch (err) {
4932 error.OutOfMemory => |e| return e,
4933 else => {
4934 try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)});
4935 continue;
4936 },
4937 };
4938 }
4939 },
4940 .none, .incremental => {},
4941 }
4942
4943 if (any_fatal_files or
4944 zcu.multi_module_err != null or
4945 zcu.failed_imports.items.len > 0 or
4946 comp.alloc_failure_occurred)
4947 {
4948 // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents
4949 // us from invalidating lots of incremental dependencies due to files with e.g. parse errors.
4950 // However, this means our analysis data is invalid, so we want to omit all analysis errors.
4951 zcu.skip_analysis_this_update = true;
4952 return;
4953 }
4954
4955 if (comp.time_report) |*tr| {
4956 tr.stats.n_reachable_files = @intCast(zcu.alive_files.count());
4957 }
4958
4959 if (comp.config.incremental) {
4960 const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0);
4961 defer update_zir_refs_node.end();
4962 try pt.updateZirRefs();
4963 }
4964 try zcu.flushRetryableFailures();
4965
4966 // It's analysis time! Queue up our initial analysis.
4967 for (zcu.analysisRoots()) |mod| {
4968 try comp.queueJob(.{ .analyze_mod = mod });
4969 }
4970
4971 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
4972 if (comp.bin_file != null) {
4973 zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
4974 }5025 }
4975 // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes.
4976 // That prevents the "Code Generation" node from constantly disappearing and reappearing when
4977 // we're probably going to analyze more functions at some point.
4978 assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes
4979 }5026 }
4980 // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation".
4981 defer if (comp.zcu) |zcu| {
4982 zcu.sema_prog_node.end();
4983 zcu.sema_prog_node = .none;
4984 if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) {
4985 // Decremented to 0, so all done.
4986 zcu.codegen_prog_node.end();
4987 zcu.codegen_prog_node = .none;
4988 }
4989 };
4990
4991 // We aren't going to queue any more prelink tasks.
4992 comp.link_task_queue.finishPrelinkItem(comp);
49935027
4994 if (!comp.separateCodegenThreadOk()) {5028 while (comp.c_object_work_queue.popFront()) |c_object| {
4995 // Waits until all input files have been parsed.5029 prelink_group.async(io, workerUpdateCObject, .{
4996 comp.link_task_wait_group.wait();5030 comp, c_object, main_progress_node,
4997 comp.link_task_wait_group.reset();5031 });
4998 std.log.scoped(.link).debug("finished waiting for link_task_wait_group", .{});
4999 }5032 }
50005033
5001 if (comp.zcu != null) {5034 while (comp.win32_resource_work_queue.popFront()) |win32_resource| {
5002 // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link).5035 prelink_group.async(io, workerUpdateWin32Resource, .{
5003 decl_work_timer = comp.startTimer();5036 comp, win32_resource, main_progress_node,
5037 });
5004 }5038 }
50055039
5006 work: while (true) {5040 prelink_group.wait(io);
5007 for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| {5041 comp.link_queue.finishPrelinkQueue(comp);
5008 try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, job);
5009 continue :work;
5010 };
5011 if (comp.zcu) |zcu| {
5012 // If there's no work queued, check if there's anything outdated
5013 // which we need to work on, and queue it if so.
5014 if (try zcu.findOutdatedToAnalyze()) |outdated| {
5015 try comp.queueJob(switch (outdated.unwrap()) {
5016 .func => |f| .{ .analyze_func = f },
5017 .memoized_state,
5018 .@"comptime",
5019 .nav_ty,
5020 .nav_val,
5021 .type,
5022 => .{ .analyze_comptime_unit = outdated },
5023 });
5024 continue;
5025 }
5026 zcu.sema_prog_node.end();
5027 zcu.sema_prog_node = .none;
5028 }
5029 break;
5030 }
5031}5042}
50325043
5033const JobError = Allocator.Error || Io.Cancelable;5044const JobError = Allocator.Error || Io.Cancelable;
...@@ -5040,58 +5051,38 @@ pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void {...@@ -5040,58 +5051,38 @@ pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void {
5040 for (jobs) |job| try comp.queueJob(job);5051 for (jobs) |job| try comp.queueJob(job);
5041}5052}
50425053
5043fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {5054fn processOneJob(
5055 tid: usize,
5056 comp: *Compilation,
5057 job: Job,
5058) JobError!void {
5044 switch (job) {5059 switch (job) {
5045 .codegen_func => |func| {5060 .codegen_func => |func| {
5046 const zcu = comp.zcu.?;5061 const zcu = comp.zcu.?;
5047 const gpa = zcu.gpa;5062 const gpa = zcu.gpa;
5048 var air = func.air;5063 var owned_air: ?Air = func.air;
5049 errdefer {5064 defer if (owned_air) |*air| air.deinit(gpa);
5050 zcu.codegen_prog_node.completeOne();5065
5051 comp.link_prog_node.completeOne();5066 if (!owned_air.?.typesFullyResolved(zcu)) {
5052 air.deinit(gpa);
5053 }
5054 if (!air.typesFullyResolved(zcu)) {
5055 // Type resolution failed in a way which affects this function. This is a transitive5067 // Type resolution failed in a way which affects this function. This is a transitive
5056 // failure, but it doesn't need recording, because this function semantically depends5068 // failure, but it doesn't need recording, because this function semantically depends
5057 // on the failed type, so when it is changed the function is updated.5069 // on the failed type, so when it is changed the function is updated.
5058 zcu.codegen_prog_node.completeOne();5070 zcu.codegen_prog_node.completeOne();
5059 comp.link_prog_node.completeOne();5071 comp.link_prog_node.completeOne();
5060 air.deinit(gpa);
5061 return;5072 return;
5062 }5073 }
5063 const shared_mir = try gpa.create(link.ZcuTask.LinkFunc.SharedMir);5074
5064 shared_mir.* = .{5075 // Some linkers need to refer to the AIR. In that case, the linker is not running
5065 .status = .init(.pending),5076 // concurrently, so we'll just keep ownership of the AIR for ourselves instead of
5066 .value = undefined,5077 // letting the codegen job destroy it.
5067 };5078 const disown_air = zcu.backendSupportsFeature(.separate_thread);
5068 assert(zcu.pending_codegen_jobs.rmw(.Add, 1, .monotonic) > 0); // the "Code Generation" node hasn't been ended5079
5069 // This value is used as a heuristic to avoid queueing too much AIR/MIR at once (hence5080 // Begin the codegen task. If the codegen/link queue is backed up, this might
5070 // using a lot of memory). If this would cause too many AIR bytes to be in-flight, we5081 // block until the linker is able to process some tasks.
5071 // will block on the `dispatchZcuLinkTask` call below.5082 const codegen_task = try zcu.codegen_task_pool.start(zcu, func.func, &owned_air.?, disown_air);
5072 const air_bytes: u32 = @intCast(air.instructions.len * 5 + air.extra.items.len * 4);5083 if (disown_air) owned_air = null;
5073 if (comp.separateCodegenThreadOk()) {5084
5074 // `workerZcuCodegen` takes ownership of `air`.5085 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_func = codegen_task });
5075 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, workerZcuCodegen, .{ comp, func.func, air, shared_mir });
5076 comp.dispatchZcuLinkTask(tid, .{ .link_func = .{
5077 .func = func.func,
5078 .mir = shared_mir,
5079 .air_bytes = air_bytes,
5080 } });
5081 } else {
5082 {
5083 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
5084 defer pt.deactivate();
5085 pt.runCodegen(func.func, &air, shared_mir);
5086 }
5087 assert(shared_mir.status.load(.monotonic) != .pending);
5088 comp.dispatchZcuLinkTask(tid, .{ .link_func = .{
5089 .func = func.func,
5090 .mir = shared_mir,
5091 .air_bytes = air_bytes,
5092 } });
5093 air.deinit(gpa);
5094 }
5095 },5086 },
5096 .link_nav => |nav_index| {5087 .link_nav => |nav_index| {
5097 const zcu = comp.zcu.?;5088 const zcu = comp.zcu.?;
...@@ -5111,7 +5102,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -5111,7 +5102,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
5111 comp.link_prog_node.completeOne();5102 comp.link_prog_node.completeOne();
5112 return;5103 return;
5113 }5104 }
5114 comp.dispatchZcuLinkTask(tid, .{ .link_nav = nav_index });5105 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index });
5115 },5106 },
5116 .link_type => |ty| {5107 .link_type => |ty| {
5117 const zcu = comp.zcu.?;5108 const zcu = comp.zcu.?;
...@@ -5123,10 +5114,10 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -5123,10 +5114,10 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
5123 comp.link_prog_node.completeOne();5114 comp.link_prog_node.completeOne();
5124 return;5115 return;
5125 }5116 }
5126 comp.dispatchZcuLinkTask(tid, .{ .link_type = ty });5117 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_type = ty });
5127 },5118 },
5128 .update_line_number => |ti| {5119 .update_line_number => |tracked_inst| {
5129 comp.dispatchZcuLinkTask(tid, .{ .update_line_number = ti });5120 try comp.link_queue.enqueueZcu(comp, tid, .{ .update_line_number = tracked_inst });
5130 },5121 },
5131 .analyze_func => |func| {5122 .analyze_func => |func| {
5132 const named_frame = tracy.namedFrame("analyze_func");5123 const named_frame = tracy.namedFrame("analyze_func");
...@@ -5220,12 +5211,6 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -5220,12 +5211,6 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
5220 }5211 }
5221}5212}
52225213
5223pub fn separateCodegenThreadOk(comp: *const Compilation) bool {
5224 if (InternPool.single_threaded) return false;
5225 const zcu = comp.zcu orelse return true;
5226 return zcu.backendSupportsFeature(.separate_thread);
5227}
5228
5229fn createDepFile(5214fn createDepFile(
5230 comp: *Compilation,5215 comp: *Compilation,
5231 depfile: []const u8,5216 depfile: []const u8,
...@@ -5480,6 +5465,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU...@@ -5480,6 +5465,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU
54805465
5481 var sub_create_diag: CreateDiagnostic = undefined;5466 var sub_create_diag: CreateDiagnostic = undefined;
5482 const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{5467 const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{
5468 .thread_limit = comp.thread_limit,
5483 .dirs = dirs,5469 .dirs = dirs,
5484 .self_exe_path = comp.self_exe_path,5470 .self_exe_path = comp.self_exe_path,
5485 .config = config,5471 .config = config,
...@@ -5487,7 +5473,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU...@@ -5487,7 +5473,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU
5487 .entry = .disabled,5473 .entry = .disabled,
5488 .cache_mode = .whole,5474 .cache_mode = .whole,
5489 .root_name = root_name,5475 .root_name = root_name,
5490 .thread_pool = comp.thread_pool,
5491 .libc_installation = comp.libc_installation,5476 .libc_installation = comp.libc_installation,
5492 .emit_bin = .yes_cache,5477 .emit_bin = .yes_cache,
5493 .verbose_cc = comp.verbose_cc,5478 .verbose_cc = comp.verbose_cc,
...@@ -5541,13 +5526,15 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU...@@ -5541,13 +5526,15 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU
5541}5526}
55425527
5543fn workerUpdateFile(5528fn workerUpdateFile(
5544 tid: usize,
5545 comp: *Compilation,5529 comp: *Compilation,
5546 file: *Zcu.File,5530 file: *Zcu.File,
5547 file_index: Zcu.File.Index,5531 file_index: Zcu.File.Index,
5548 prog_node: std.Progress.Node,5532 prog_node: std.Progress.Node,
5549 wg: *WaitGroup,5533 group: *Io.Group,
5550) void {5534) void {
5535 const tid = Compilation.getTid();
5536 const io = comp.io;
5537
5551 const child_prog_node = prog_node.start(fs.path.basename(file.path.sub_path), 0);5538 const child_prog_node = prog_node.start(fs.path.basename(file.path.sub_path), 0);
5552 defer child_prog_node.end();5539 defer child_prog_node.end();
55535540
...@@ -5556,8 +5543,8 @@ fn workerUpdateFile(...@@ -5556,8 +5543,8 @@ fn workerUpdateFile(
5556 pt.updateFile(file_index, file) catch |err| {5543 pt.updateFile(file_index, file) catch |err| {
5557 pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {5544 pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {
5558 error.OutOfMemory => {5545 error.OutOfMemory => {
5559 comp.mutex.lock();5546 comp.mutex.lockUncancelable(io);
5560 defer comp.mutex.unlock();5547 defer comp.mutex.unlock(io);
5561 comp.setAllocFailure();5548 comp.setAllocFailure();
5562 },5549 },
5563 };5550 };
...@@ -5587,14 +5574,14 @@ fn workerUpdateFile(...@@ -5587,14 +5574,14 @@ fn workerUpdateFile(
5587 if (pt.discoverImport(file.path, import_path)) |res| switch (res) {5574 if (pt.discoverImport(file.path, import_path)) |res| switch (res) {
5588 .module, .existing_file => {},5575 .module, .existing_file => {},
5589 .new_file => |new| {5576 .new_file => |new| {
5590 comp.thread_pool.spawnWgId(wg, workerUpdateFile, .{5577 group.async(io, workerUpdateFile, .{
5591 comp, new.file, new.index, prog_node, wg,5578 comp, new.file, new.index, prog_node, group,
5592 });5579 });
5593 },5580 },
5594 } else |err| switch (err) {5581 } else |err| switch (err) {
5595 error.OutOfMemory => {5582 error.OutOfMemory => {
5596 comp.mutex.lock();5583 comp.mutex.lockUncancelable(io);
5597 defer comp.mutex.unlock();5584 defer comp.mutex.unlock(io);
5598 comp.setAllocFailure();5585 comp.setAllocFailure();
5599 },5586 },
5600 }5587 }
...@@ -5610,17 +5597,20 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void {...@@ -5610,17 +5597,20 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void {
5610 );5597 );
5611}5598}
56125599
5613fn workerUpdateEmbedFile(tid: usize, comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void {5600fn workerUpdateEmbedFile(comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void {
5601 const tid = Compilation.getTid();
5602 const io = comp.io;
5614 comp.detectEmbedFileUpdate(@enumFromInt(tid), ef_index, ef) catch |err| switch (err) {5603 comp.detectEmbedFileUpdate(@enumFromInt(tid), ef_index, ef) catch |err| switch (err) {
5615 error.OutOfMemory => {5604 error.OutOfMemory => {
5616 comp.mutex.lock();5605 comp.mutex.lockUncancelable(io);
5617 defer comp.mutex.unlock();5606 defer comp.mutex.unlock(io);
5618 comp.setAllocFailure();5607 comp.setAllocFailure();
5619 },5608 },
5620 };5609 };
5621}5610}
56225611
5623fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void {5612fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void {
5613 const io = comp.io;
5624 const zcu = comp.zcu.?;5614 const zcu = comp.zcu.?;
5625 const pt: Zcu.PerThread = .activate(zcu, tid);5615 const pt: Zcu.PerThread = .activate(zcu, tid);
5626 defer pt.deactivate();5616 defer pt.deactivate();
...@@ -5633,8 +5623,8 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc...@@ -5633,8 +5623,8 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc
5633 if (ef.val != .none and ef.val == old_val) return; // success, value unchanged5623 if (ef.val != .none and ef.val == old_val) return; // success, value unchanged
5634 if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged5624 if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged
56355625
5636 comp.mutex.lock();5626 comp.mutex.lockUncancelable(io);
5637 defer comp.mutex.unlock();5627 defer comp.mutex.unlock(io);
56385628
5639 try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index });5629 try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index });
5640}5630}
...@@ -5777,8 +5767,8 @@ pub fn translateC(...@@ -5777,8 +5767,8 @@ pub fn translateC(
57775767
5778 switch (comp.cache_use) {5768 switch (comp.cache_use) {
5779 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {5769 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {
5780 whole.cache_manifest_mutex.lock();5770 try whole.cache_manifest_mutex.lock(io);
5781 defer whole.cache_manifest_mutex.unlock();5771 defer whole.cache_manifest_mutex.unlock(io);
5782 try whole_cache_manifest.addDepFilePost(cache_tmp_dir, dep_basename);5772 try whole_cache_manifest.addDepFilePost(cache_tmp_dir, dep_basename);
5783 },5773 },
5784 .incremental, .none => {},5774 .incremental, .none => {},
...@@ -5879,7 +5869,6 @@ fn workerUpdateCObject(...@@ -5879,7 +5869,6 @@ fn workerUpdateCObject(
5879 c_object: *CObject,5869 c_object: *CObject,
5880 progress_node: std.Progress.Node,5870 progress_node: std.Progress.Node,
5881) void {5871) void {
5882 defer comp.link_task_queue.finishPrelinkItem(comp);
5883 comp.updateCObject(c_object, progress_node) catch |err| switch (err) {5872 comp.updateCObject(c_object, progress_node) catch |err| switch (err) {
5884 error.AnalysisFail => return,5873 error.AnalysisFail => return,
5885 else => {5874 else => {
...@@ -5897,7 +5886,6 @@ fn workerUpdateWin32Resource(...@@ -5897,7 +5886,6 @@ fn workerUpdateWin32Resource(
5897 win32_resource: *Win32Resource,5886 win32_resource: *Win32Resource,
5898 progress_node: std.Progress.Node,5887 progress_node: std.Progress.Node,
5899) void {5888) void {
5900 defer comp.link_task_queue.finishPrelinkItem(comp);
5901 comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) {5889 comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) {
5902 error.AnalysisFail => return,5890 error.AnalysisFail => return,
5903 else => {5891 else => {
...@@ -5915,21 +5903,6 @@ pub const RtOptions = struct {...@@ -5915,21 +5903,6 @@ pub const RtOptions = struct {
5915 allow_lto: bool = true,5903 allow_lto: bool = true,
5916};5904};
59175905
5918fn workerZcuCodegen(
5919 tid: usize,
5920 comp: *Compilation,
5921 func_index: InternPool.Index,
5922 orig_air: Air,
5923 out: *link.ZcuTask.LinkFunc.SharedMir,
5924) void {
5925 var air = orig_air;
5926 // We own `air` now, so we are responsbile for freeing it.
5927 defer air.deinit(comp.gpa);
5928 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
5929 defer pt.deactivate();
5930 pt.runCodegen(func_index, &air, out);
5931}
5932
5933fn buildRt(5906fn buildRt(
5934 comp: *Compilation,5907 comp: *Compilation,
5935 root_source_name: []const u8,5908 root_source_name: []const u8,
...@@ -5941,7 +5914,6 @@ fn buildRt(...@@ -5941,7 +5914,6 @@ fn buildRt(
5941 options: RtOptions,5914 options: RtOptions,
5942 out: *?CrtFile,5915 out: *?CrtFile,
5943) void {5916) void {
5944 defer comp.link_task_queue.finishPrelinkItem(comp);
5945 comp.buildOutputFromZig(5917 comp.buildOutputFromZig(
5946 root_source_name,5918 root_source_name,
5947 root_name,5919 root_name,
...@@ -5960,7 +5932,6 @@ fn buildRt(...@@ -5960,7 +5932,6 @@ fn buildRt(
5960}5932}
59615933
5962fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.Progress.Node) void {5934fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.Progress.Node) void {
5963 defer comp.link_task_queue.finishPrelinkItem(comp);
5964 if (musl.buildCrtFile(comp, crt_file, prog_node)) |_| {5935 if (musl.buildCrtFile(comp, crt_file, prog_node)) |_| {
5965 comp.queued_jobs.musl_crt_file[@intFromEnum(crt_file)] = false;5936 comp.queued_jobs.musl_crt_file[@intFromEnum(crt_file)] = false;
5966 } else |err| switch (err) {5937 } else |err| switch (err) {
...@@ -5972,7 +5943,6 @@ fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.P...@@ -5972,7 +5943,6 @@ fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.P
5972}5943}
59735944
5974fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std.Progress.Node) void {5945fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std.Progress.Node) void {
5975 defer comp.link_task_queue.finishPrelinkItem(comp);
5976 if (glibc.buildCrtFile(comp, crt_file, prog_node)) |_| {5946 if (glibc.buildCrtFile(comp, crt_file, prog_node)) |_| {
5977 comp.queued_jobs.glibc_crt_file[@intFromEnum(crt_file)] = false;5947 comp.queued_jobs.glibc_crt_file[@intFromEnum(crt_file)] = false;
5978 } else |err| switch (err) {5948 } else |err| switch (err) {
...@@ -5984,7 +5954,6 @@ fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std...@@ -5984,7 +5954,6 @@ fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std
5984}5954}
59855955
5986fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {5956fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
5987 defer comp.link_task_queue.finishPrelinkItem(comp);
5988 if (glibc.buildSharedObjects(comp, prog_node)) |_| {5957 if (glibc.buildSharedObjects(comp, prog_node)) |_| {
5989 // The job should no longer be queued up since it succeeded.5958 // The job should no longer be queued up since it succeeded.
5990 comp.queued_jobs.glibc_shared_objects = false;5959 comp.queued_jobs.glibc_shared_objects = false;
...@@ -5995,7 +5964,6 @@ fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) voi...@@ -5995,7 +5964,6 @@ fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) voi
5995}5964}
59965965
5997fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: std.Progress.Node) void {5966fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: std.Progress.Node) void {
5998 defer comp.link_task_queue.finishPrelinkItem(comp);
5999 if (freebsd.buildCrtFile(comp, crt_file, prog_node)) |_| {5967 if (freebsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
6000 comp.queued_jobs.freebsd_crt_file[@intFromEnum(crt_file)] = false;5968 comp.queued_jobs.freebsd_crt_file[@intFromEnum(crt_file)] = false;
6001 } else |err| switch (err) {5969 } else |err| switch (err) {
...@@ -6007,7 +5975,6 @@ fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node:...@@ -6007,7 +5975,6 @@ fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node:
6007}5975}
60085976
6009fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {5977fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
6010 defer comp.link_task_queue.finishPrelinkItem(comp);
6011 if (freebsd.buildSharedObjects(comp, prog_node)) |_| {5978 if (freebsd.buildSharedObjects(comp, prog_node)) |_| {
6012 // The job should no longer be queued up since it succeeded.5979 // The job should no longer be queued up since it succeeded.
6013 comp.queued_jobs.freebsd_shared_objects = false;5980 comp.queued_jobs.freebsd_shared_objects = false;
...@@ -6020,7 +5987,6 @@ fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) v...@@ -6020,7 +5987,6 @@ fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) v
6020}5987}
60215988
6022fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: std.Progress.Node) void {5989fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: std.Progress.Node) void {
6023 defer comp.link_task_queue.finishPrelinkItem(comp);
6024 if (netbsd.buildCrtFile(comp, crt_file, prog_node)) |_| {5990 if (netbsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
6025 comp.queued_jobs.netbsd_crt_file[@intFromEnum(crt_file)] = false;5991 comp.queued_jobs.netbsd_crt_file[@intFromEnum(crt_file)] = false;
6026 } else |err| switch (err) {5992 } else |err| switch (err) {
...@@ -6032,7 +5998,6 @@ fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: s...@@ -6032,7 +5998,6 @@ fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: s
6032}5998}
60335999
6034fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {6000fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
6035 defer comp.link_task_queue.finishPrelinkItem(comp);
6036 if (netbsd.buildSharedObjects(comp, prog_node)) |_| {6001 if (netbsd.buildSharedObjects(comp, prog_node)) |_| {
6037 // The job should no longer be queued up since it succeeded.6002 // The job should no longer be queued up since it succeeded.
6038 comp.queued_jobs.netbsd_shared_objects = false;6003 comp.queued_jobs.netbsd_shared_objects = false;
...@@ -6045,7 +6010,6 @@ fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) vo...@@ -6045,7 +6010,6 @@ fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) vo
6045}6010}
60466011
6047fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std.Progress.Node) void {6012fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std.Progress.Node) void {
6048 defer comp.link_task_queue.finishPrelinkItem(comp);
6049 if (mingw.buildCrtFile(comp, crt_file, prog_node)) |_| {6013 if (mingw.buildCrtFile(comp, crt_file, prog_node)) |_| {
6050 comp.queued_jobs.mingw_crt_file[@intFromEnum(crt_file)] = false;6014 comp.queued_jobs.mingw_crt_file[@intFromEnum(crt_file)] = false;
6051 } else |err| switch (err) {6015 } else |err| switch (err) {
...@@ -6057,7 +6021,6 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std...@@ -6057,7 +6021,6 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std
6057}6021}
60586022
6059fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void {6023fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void {
6060 defer comp.link_task_queue.finishPrelinkItem(comp);
6061 if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| {6024 if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| {
6062 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false;6025 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false;
6063 } else |err| switch (err) {6026 } else |err| switch (err) {
...@@ -6069,7 +6032,6 @@ fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_no...@@ -6069,7 +6032,6 @@ fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_no
6069}6032}
60706033
6071fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void {6034fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void {
6072 defer comp.link_task_queue.finishPrelinkItem(comp);
6073 if (libunwind.buildStaticLib(comp, prog_node)) |_| {6035 if (libunwind.buildStaticLib(comp, prog_node)) |_| {
6074 comp.queued_jobs.libunwind = false;6036 comp.queued_jobs.libunwind = false;
6075 } else |err| switch (err) {6037 } else |err| switch (err) {
...@@ -6079,7 +6041,6 @@ fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void {...@@ -6079,7 +6041,6 @@ fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void {
6079}6041}
60806042
6081fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void {6043fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void {
6082 defer comp.link_task_queue.finishPrelinkItem(comp);
6083 if (libcxx.buildLibCxx(comp, prog_node)) |_| {6044 if (libcxx.buildLibCxx(comp, prog_node)) |_| {
6084 comp.queued_jobs.libcxx = false;6045 comp.queued_jobs.libcxx = false;
6085 } else |err| switch (err) {6046 } else |err| switch (err) {
...@@ -6089,7 +6050,6 @@ fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void {...@@ -6089,7 +6050,6 @@ fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void {
6089}6050}
60906051
6091fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void {6052fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void {
6092 defer comp.link_task_queue.finishPrelinkItem(comp);
6093 if (libcxx.buildLibCxxAbi(comp, prog_node)) |_| {6053 if (libcxx.buildLibCxxAbi(comp, prog_node)) |_| {
6094 comp.queued_jobs.libcxxabi = false;6054 comp.queued_jobs.libcxxabi = false;
6095 } else |err| switch (err) {6055 } else |err| switch (err) {
...@@ -6099,7 +6059,6 @@ fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void {...@@ -6099,7 +6059,6 @@ fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void {
6099}6059}
61006060
6101fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void {6061fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void {
6102 defer comp.link_task_queue.finishPrelinkItem(comp);
6103 if (libtsan.buildTsan(comp, prog_node)) |_| {6062 if (libtsan.buildTsan(comp, prog_node)) |_| {
6104 comp.queued_jobs.libtsan = false;6063 comp.queued_jobs.libtsan = false;
6105 } else |err| switch (err) {6064 } else |err| switch (err) {
...@@ -6109,7 +6068,6 @@ fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void {...@@ -6109,7 +6068,6 @@ fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void {
6109}6068}
61106069
6111fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void {6070fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void {
6112 defer comp.link_task_queue.finishPrelinkItem(comp);
6113 comp.buildOutputFromZig(6071 comp.buildOutputFromZig(
6114 "c.zig",6072 "c.zig",
6115 "zigc",6073 "zigc",
...@@ -6139,6 +6097,8 @@ fn reportRetryableWin32ResourceError(...@@ -6139,6 +6097,8 @@ fn reportRetryableWin32ResourceError(
6139 win32_resource: *Win32Resource,6097 win32_resource: *Win32Resource,
6140 err: anyerror,6098 err: anyerror,
6141) error{OutOfMemory}!void {6099) error{OutOfMemory}!void {
6100 const io = comp.io;
6101
6142 win32_resource.status = .failure_retryable;6102 win32_resource.status = .failure_retryable;
61436103
6144 var bundle: ErrorBundle.Wip = undefined;6104 var bundle: ErrorBundle.Wip = undefined;
...@@ -6160,8 +6120,8 @@ fn reportRetryableWin32ResourceError(...@@ -6160,8 +6120,8 @@ fn reportRetryableWin32ResourceError(
6160 });6120 });
6161 const finished_bundle = try bundle.toOwnedBundle("");6121 const finished_bundle = try bundle.toOwnedBundle("");
6162 {6122 {
6163 comp.mutex.lock();6123 comp.mutex.lockUncancelable(io);
6164 defer comp.mutex.unlock();6124 defer comp.mutex.unlock(io);
6165 try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, finished_bundle);6125 try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, finished_bundle);
6166 }6126 }
6167}6127}
...@@ -6186,8 +6146,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -6186,8 +6146,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
61866146
6187 if (c_object.clearStatus(gpa)) {6147 if (c_object.clearStatus(gpa)) {
6188 // There was previous failure.6148 // There was previous failure.
6189 comp.mutex.lock();6149 comp.mutex.lockUncancelable(io);
6190 defer comp.mutex.unlock();6150 defer comp.mutex.unlock(io);
6191 // If the failure was OOM, there will not be an entry here, so we do6151 // If the failure was OOM, there will not be an entry here, so we do
6192 // not assert discard.6152 // not assert discard.
6193 _ = comp.failed_c_objects.swapRemove(c_object);6153 _ = comp.failed_c_objects.swapRemove(c_object);
...@@ -6457,8 +6417,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -6457,8 +6417,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
6457 switch (comp.cache_use) {6417 switch (comp.cache_use) {
6458 .whole => |whole| {6418 .whole => |whole| {
6459 if (whole.cache_manifest) |whole_cache_manifest| {6419 if (whole.cache_manifest) |whole_cache_manifest| {
6460 whole.cache_manifest_mutex.lock();6420 try whole.cache_manifest_mutex.lock(io);
6461 defer whole.cache_manifest_mutex.unlock();6421 defer whole.cache_manifest_mutex.unlock(io);
6462 try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);6422 try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename);
6463 }6423 }
6464 },6424 },
...@@ -6503,7 +6463,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -6503,7 +6463,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
6503 },6463 },
6504 };6464 };
65056465
6506 comp.queuePrelinkTasks(&.{.{ .load_object = c_object.status.success.object_path }});6466 try comp.queuePrelinkTasks(&.{.{ .load_object = c_object.status.success.object_path }});
6507}6467}
65086468
6509fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32_resource_prog_node: std.Progress.Node) !void {6469fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32_resource_prog_node: std.Progress.Node) !void {
...@@ -6517,6 +6477,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6517,6 +6477,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
6517 const tracy_trace = trace(@src());6477 const tracy_trace = trace(@src());
6518 defer tracy_trace.end();6478 defer tracy_trace.end();
65196479
6480 const io = comp.io;
6481
6520 const src_path = switch (win32_resource.src) {6482 const src_path = switch (win32_resource.src) {
6521 .rc => |rc_src| rc_src.src_path,6483 .rc => |rc_src| rc_src.src_path,
6522 .manifest => |src_path| src_path,6484 .manifest => |src_path| src_path,
...@@ -6531,8 +6493,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6531,8 +6493,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
65316493
6532 if (win32_resource.clearStatus(comp.gpa)) {6494 if (win32_resource.clearStatus(comp.gpa)) {
6533 // There was previous failure.6495 // There was previous failure.
6534 comp.mutex.lock();6496 comp.mutex.lockUncancelable(io);
6535 defer comp.mutex.unlock();6497 defer comp.mutex.unlock(io);
6536 // If the failure was OOM, there will not be an entry here, so we do6498 // If the failure was OOM, there will not be an entry here, so we do
6537 // not assert discard.6499 // not assert discard.
6538 _ = comp.failed_win32_resources.swapRemove(win32_resource);6500 _ = comp.failed_win32_resources.swapRemove(win32_resource);
...@@ -6706,8 +6668,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -6706,8 +6668,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
6706 try man.addFilePost(dep_file_path);6668 try man.addFilePost(dep_file_path);
6707 switch (comp.cache_use) {6669 switch (comp.cache_use) {
6708 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {6670 .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {
6709 whole.cache_manifest_mutex.lock();6671 try whole.cache_manifest_mutex.lock(io);
6710 defer whole.cache_manifest_mutex.unlock();6672 defer whole.cache_manifest_mutex.unlock(io);
6711 try whole_cache_manifest.addFilePost(dep_file_path);6673 try whole_cache_manifest.addFilePost(dep_file_path);
6712 },6674 },
6713 .incremental, .none => {},6675 .incremental, .none => {},
...@@ -7428,8 +7390,9 @@ fn failCObjWithOwnedDiagBundle(...@@ -7428,8 +7390,9 @@ fn failCObjWithOwnedDiagBundle(
7428 @branchHint(.cold);7390 @branchHint(.cold);
7429 assert(diag_bundle.diags.len > 0);7391 assert(diag_bundle.diags.len > 0);
7430 {7392 {
7431 comp.mutex.lock();7393 const io = comp.io;
7432 defer comp.mutex.unlock();7394 comp.mutex.lockUncancelable(io);
7395 defer comp.mutex.unlock(io);
7433 {7396 {
7434 errdefer diag_bundle.destroy(comp.gpa);7397 errdefer diag_bundle.destroy(comp.gpa);
7435 try comp.failed_c_objects.ensureUnusedCapacity(comp.gpa, 1);7398 try comp.failed_c_objects.ensureUnusedCapacity(comp.gpa, 1);
...@@ -7470,8 +7433,9 @@ fn failWin32ResourceWithOwnedBundle(...@@ -7470,8 +7433,9 @@ fn failWin32ResourceWithOwnedBundle(
7470) error{ OutOfMemory, AnalysisFail } {7433) error{ OutOfMemory, AnalysisFail } {
7471 @branchHint(.cold);7434 @branchHint(.cold);
7472 {7435 {
7473 comp.mutex.lock();7436 const io = comp.io;
7474 defer comp.mutex.unlock();7437 comp.mutex.lockUncancelable(io);
7438 defer comp.mutex.unlock(io);
7475 try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, err_bundle);7439 try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, err_bundle);
7476 }7440 }
7477 win32_resource.status = .failure;7441 win32_resource.status = .failure;
...@@ -7795,9 +7759,9 @@ pub fn lockAndSetMiscFailure(...@@ -7795,9 +7759,9 @@ pub fn lockAndSetMiscFailure(
7795 comptime format: []const u8,7759 comptime format: []const u8,
7796 args: anytype,7760 args: anytype,
7797) void {7761) void {
7798 comp.mutex.lock();7762 const io = comp.io;
7799 defer comp.mutex.unlock();7763 comp.mutex.lockUncancelable(io);
78007764 defer comp.mutex.unlock(io);
7801 return setMiscFailure(comp, tag, format, args);7765 return setMiscFailure(comp, tag, format, args);
7802}7766}
78037767
...@@ -7840,8 +7804,8 @@ pub fn updateSubCompilation(...@@ -7840,8 +7804,8 @@ pub fn updateSubCompilation(
7840 defer errors.deinit(gpa);7804 defer errors.deinit(gpa);
78417805
7842 if (errors.errorMessageCount() > 0) {7806 if (errors.errorMessageCount() > 0) {
7843 parent_comp.mutex.lock();7807 parent_comp.mutex.lockUncancelable(parent_comp.io);
7844 defer parent_comp.mutex.unlock();7808 defer parent_comp.mutex.unlock(parent_comp.io);
7845 try parent_comp.misc_failures.ensureUnusedCapacity(gpa, 1);7809 try parent_comp.misc_failures.ensureUnusedCapacity(gpa, 1);
7846 parent_comp.misc_failures.putAssumeCapacityNoClobber(misc_task, .{7810 parent_comp.misc_failures.putAssumeCapacityNoClobber(misc_task, .{
7847 .msg = try std.fmt.allocPrint(gpa, "sub-compilation of {t} failed", .{misc_task}),7811 .msg = try std.fmt.allocPrint(gpa, "sub-compilation of {t} failed", .{misc_task}),
...@@ -7942,6 +7906,7 @@ fn buildOutputFromZig(...@@ -7942,6 +7906,7 @@ fn buildOutputFromZig(
79427906
7943 var sub_create_diag: CreateDiagnostic = undefined;7907 var sub_create_diag: CreateDiagnostic = undefined;
7944 const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{7908 const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{
7909 .thread_limit = comp.thread_limit,
7945 .dirs = comp.dirs.withoutLocalCache(),7910 .dirs = comp.dirs.withoutLocalCache(),
7946 .cache_mode = .whole,7911 .cache_mode = .whole,
7947 .parent_whole_cache = parent_whole_cache,7912 .parent_whole_cache = parent_whole_cache,
...@@ -7949,7 +7914,6 @@ fn buildOutputFromZig(...@@ -7949,7 +7914,6 @@ fn buildOutputFromZig(
7949 .config = config,7914 .config = config,
7950 .root_mod = root_mod,7915 .root_mod = root_mod,
7951 .root_name = root_name,7916 .root_name = root_name,
7952 .thread_pool = comp.thread_pool,
7953 .libc_installation = comp.libc_installation,7917 .libc_installation = comp.libc_installation,
7954 .emit_bin = .yes_cache,7918 .emit_bin = .yes_cache,
7955 .function_sections = true,7919 .function_sections = true,
...@@ -7980,7 +7944,7 @@ fn buildOutputFromZig(...@@ -7980,7 +7944,7 @@ fn buildOutputFromZig(
7980 assert(out.* == null);7944 assert(out.* == null);
7981 out.* = crt_file;7945 out.* = crt_file;
79827946
7983 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);7947 try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
7984}7948}
79857949
7986pub const CrtFileOptions = struct {7950pub const CrtFileOptions = struct {
...@@ -8079,13 +8043,13 @@ pub fn build_crt_file(...@@ -8079,13 +8043,13 @@ pub fn build_crt_file(
80798043
8080 var sub_create_diag: CreateDiagnostic = undefined;8044 var sub_create_diag: CreateDiagnostic = undefined;
8081 const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{8045 const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{
8046 .thread_limit = comp.thread_limit,
8082 .dirs = comp.dirs.withoutLocalCache(),8047 .dirs = comp.dirs.withoutLocalCache(),
8083 .self_exe_path = comp.self_exe_path,8048 .self_exe_path = comp.self_exe_path,
8084 .cache_mode = .whole,8049 .cache_mode = .whole,
8085 .config = config,8050 .config = config,
8086 .root_mod = root_mod,8051 .root_mod = root_mod,
8087 .root_name = root_name,8052 .root_name = root_name,
8088 .thread_pool = comp.thread_pool,
8089 .libc_installation = comp.libc_installation,8053 .libc_installation = comp.libc_installation,
8090 .emit_bin = .yes_cache,8054 .emit_bin = .yes_cache,
8091 .function_sections = options.function_sections orelse false,8055 .function_sections = options.function_sections orelse false,
...@@ -8114,18 +8078,18 @@ pub fn build_crt_file(...@@ -8114,18 +8078,18 @@ pub fn build_crt_file(
8114 try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node);8078 try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node);
81158079
8116 const crt_file = try sub_compilation.toCrtFile();8080 const crt_file = try sub_compilation.toCrtFile();
8117 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);8081 try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
81188082
8119 {8083 {
8120 comp.mutex.lock();8084 comp.mutex.lockUncancelable(io);
8121 defer comp.mutex.unlock();8085 defer comp.mutex.unlock(io);
8122 try comp.crt_files.ensureUnusedCapacity(gpa, 1);8086 try comp.crt_files.ensureUnusedCapacity(gpa, 1);
8123 comp.crt_files.putAssumeCapacityNoClobber(basename, crt_file);8087 comp.crt_files.putAssumeCapacityNoClobber(basename, crt_file);
8124 }8088 }
8125}8089}
81268090
8127pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) void {8091pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) Io.Cancelable!void {
8128 comp.queuePrelinkTasks(switch (config.output_mode) {8092 try comp.queuePrelinkTasks(switch (config.output_mode) {
8129 .Exe => unreachable,8093 .Exe => unreachable,
8130 .Obj => &.{.{ .load_object = path }},8094 .Obj => &.{.{ .load_object = path }},
8131 .Lib => &.{switch (config.link_mode) {8095 .Lib => &.{switch (config.link_mode) {
...@@ -8135,33 +8099,10 @@ pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const...@@ -8135,33 +8099,10 @@ pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const
8135 });8099 });
8136}8100}
81378101
8138/// Only valid to call during `update`. Automatically handles queuing up a8102/// Only valid to call during `update`.
8139/// linker worker task if there is not already one.8103pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) Io.Cancelable!void {
8140pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) void {
8141 comp.link_prog_node.increaseEstimatedTotalItems(tasks.len);8104 comp.link_prog_node.increaseEstimatedTotalItems(tasks.len);
8142 comp.link_task_queue.enqueuePrelink(comp, tasks) catch |err| switch (err) {8105 try comp.link_queue.enqueuePrelink(comp, tasks);
8143 error.OutOfMemory => return comp.setAllocFailure(),
8144 };
8145}
8146
8147/// The reason for the double-queue here is that the first queue ensures any
8148/// resolve_type_fully tasks are complete before this dispatch function is called.
8149fn dispatchZcuLinkTask(comp: *Compilation, tid: usize, task: link.ZcuTask) void {
8150 if (!comp.separateCodegenThreadOk()) {
8151 assert(tid == 0);
8152 if (task == .link_func) {
8153 assert(task.link_func.mir.status.load(.monotonic) != .pending);
8154 }
8155 link.doZcuTask(comp, tid, task);
8156 task.deinit(comp.zcu.?);
8157 return;
8158 }
8159 comp.link_task_queue.enqueueZcu(comp, task) catch |err| switch (err) {
8160 error.OutOfMemory => {
8161 task.deinit(comp.zcu.?);
8162 comp.setAllocFailure();
8163 },
8164 };
8165}8106}
81668107
8167pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {8108pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {
...@@ -8251,3 +8192,17 @@ pub fn compilerRtOptMode(comp: Compilation) std.builtin.OptimizeMode {...@@ -8251,3 +8192,17 @@ pub fn compilerRtOptMode(comp: Compilation) std.builtin.OptimizeMode {
8251pub fn compilerRtStrip(comp: Compilation) bool {8192pub fn compilerRtStrip(comp: Compilation) bool {
8252 return comp.root_mod.strip;8193 return comp.root_mod.strip;
8253}8194}
8195
8196/// This is a temporary workaround put in place to migrate from `std.Thread.Pool`
8197/// to `std.Io.Threaded` for asynchronous/concurrent work. The eventual solution
8198/// will likely involve significant changes to the `InternPool` implementation.
8199pub fn getTid() usize {
8200 if (my_tid == null) my_tid = next_tid.fetchAdd(1, .monotonic);
8201 return my_tid.?;
8202}
8203pub fn setMainThread() void {
8204 my_tid = 0;
8205}
8206/// TID 0 is reserved for the main thread.
8207var next_tid: std.atomic.Value(usize) = .init(1);
8208threadlocal var my_tid: ?usize = null;
src/IncrementalDebugServer.zig+109-39
...@@ -14,57 +14,122 @@ comptime {...@@ -14,57 +14,122 @@ comptime {
14}14}
1515
16zcu: *Zcu,16zcu: *Zcu,
17thread: ?std.Thread,17future: ?Io.Future(void),
18running: std.atomic.Value(bool),
19/// Held by our owner when an update is in-progress, and held by us when responding to a command.18/// Held by our owner when an update is in-progress, and held by us when responding to a command.
20/// So, essentially guards all access to `Compilation`, including `Zcu`.19/// So, essentially guards all access to `Compilation`, including `Zcu`.
21mutex: std.Thread.Mutex,20mutex: std.Io.Mutex,
2221
23pub fn init(zcu: *Zcu) IncrementalDebugServer {22pub fn init(zcu: *Zcu) IncrementalDebugServer {
24 return .{23 return .{
25 .zcu = zcu,24 .zcu = zcu,
26 .thread = null,25 .future = null,
27 .running = .init(true),26 .mutex = .init,
28 .mutex = .{},
29 };27 };
30}28}
3129
32pub fn deinit(ids: *IncrementalDebugServer) void {30pub fn deinit(ids: *IncrementalDebugServer) void {
33 if (ids.thread) |t| {31 const io = ids.zcu.comp.io;
34 ids.running.store(false, .monotonic);32 if (ids.future) |*f| f.cancel(io);
35 t.join();
36 }
37}33}
3834
39const port = 7623;35const port = 7623;
40pub fn spawn(ids: *IncrementalDebugServer) void {36pub fn spawn(ids: *IncrementalDebugServer) void {
37 const io = ids.zcu.comp.io;
41 std.debug.print("spawning incremental debug server on port {d}\n", .{port});38 std.debug.print("spawning incremental debug server on port {d}\n", .{port});
42 ids.thread = std.Thread.spawn(.{ .allocator = ids.zcu.comp.arena }, runThread, .{ids}) catch |err|39 ids.future = io.concurrent(runServer, .{ids}) catch |err|
43 std.process.fatal("failed to spawn incremental debug server: {s}", .{@errorName(err)});40 std.process.fatal("failed to start incremental debug server: {s}", .{@errorName(err)});
44}41}
45fn runThread(ids: *IncrementalDebugServer) void {42fn runServer(ids: *IncrementalDebugServer) void {
46 const gpa = ids.zcu.gpa;
47 const io = ids.zcu.comp.io;43 const io = ids.zcu.comp.io;
4844
49 var cmd_buf: [1024]u8 = undefined;45 const addr: Io.net.IpAddress = .{ .ip6 = .loopback(port) };
50 var text_out: std.ArrayList(u8) = .empty;46 var server = addr.listen(io, .{}) catch |err| switch (err) {
51 defer text_out.deinit(gpa);47 error.Canceled => return,
5248 else => |e| {
53 const addr: std.Io.net.IpAddress = .{ .ip6 = .loopback(port) };49 log.err("listen failed ({t}); closing server", .{e});
54 var server = addr.listen(io, .{}) catch @panic("IncrementalDebugServer: failed to listen");50 return;
51 },
52 };
55 defer server.deinit(io);53 defer server.deinit(io);
56 var stream = server.accept(io) catch @panic("IncrementalDebugServer: failed to accept");
57 defer stream.close(io);
5854
59 var stream_reader = stream.reader(io, &cmd_buf);55 while (true) {
60 var stream_writer = stream.writer(io, &.{});56 var stream = server.accept(io) catch |err| switch (err) {
57 error.Canceled => return,
58 error.ConnectionAborted => {
59 log.warn("client disconnected during accept", .{});
60 continue;
61 },
62 else => |e| {
63 log.err("accept failed ({t})", .{e});
64 return;
65 },
66 };
67 defer stream.close(io);
68 log.info("client '{f}' connected", .{stream.socket.address});
69 var cmd_buf: [1024]u8 = undefined;
70 var reader = stream.reader(io, &cmd_buf);
71 var writer = stream.writer(io, &.{});
72 ids.serveStream(&reader.interface, &writer.interface) catch |orig_err| {
73 const actual_err = switch (orig_err) {
74 error.Canceled,
75 error.OutOfMemory,
76 error.EndOfStream,
77 error.StreamTooLong,
78 => |e| e,
79
80 error.ReadFailed => reader.err.?,
81 error.WriteFailed => writer.err.?,
82 };
83 switch (actual_err) {
84 error.Canceled => return,
85
86 error.OutOfMemory,
87 error.Unexpected,
88 error.SystemResources,
89 error.Timeout,
90 error.NetworkDown,
91 error.NetworkUnreachable,
92 error.HostUnreachable,
93 error.FastOpenAlreadyInProgress,
94 error.ConnectionRefused,
95 error.StreamTooLong,
96 => |e| log.err("failed to serve '{f}' ({t})", .{ stream.socket.address, e }),
97
98 error.EndOfStream,
99 error.ConnectionResetByPeer,
100 => log.info("client '{f}' disconnected", .{stream.socket.address}),
61101
62 while (ids.running.load(.monotonic)) {102 error.AddressFamilyUnsupported,
63 stream_writer.interface.writeAll("zig> ") catch @panic("IncrementalDebugServer: failed to write");103 error.SocketUnconnected,
64 const untrimmed = stream_reader.interface.takeSentinel('\n') catch |err| switch (err) {104 error.SocketNotBound,
65 error.EndOfStream => break,105 error.AccessDenied,
66 else => @panic("IncrementalDebugServer: failed to read command"),106 => unreachable,
107 }
67 };108 };
109 }
110}
111
112fn serveStream(
113 ids: *IncrementalDebugServer,
114 stream_reader: *Io.Reader,
115 stream_writer: *Io.Writer,
116) error{
117 Canceled,
118 OutOfMemory,
119 EndOfStream,
120 StreamTooLong,
121 ReadFailed,
122 WriteFailed,
123}!noreturn {
124 const gpa = ids.zcu.gpa;
125 const io = ids.zcu.comp.io;
126
127 var text_out: std.ArrayList(u8) = .empty;
128 defer text_out.deinit(gpa);
129
130 while (true) {
131 try stream_writer.writeAll("zig> ");
132 const untrimmed = try stream_reader.takeSentinel('\n');
68 const cmd_and_arg = std.mem.trim(u8, untrimmed, " \t\r\n");133 const cmd_and_arg = std.mem.trim(u8, untrimmed, " \t\r\n");
69 const cmd: []const u8, const arg: []const u8 = if (std.mem.indexOfScalar(u8, cmd_and_arg, ' ')) |i|134 const cmd: []const u8, const arg: []const u8 = if (std.mem.indexOfScalar(u8, cmd_and_arg, ' ')) |i|
70 .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] }135 .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] }
...@@ -74,18 +139,21 @@ fn runThread(ids: *IncrementalDebugServer) void {...@@ -74,18 +139,21 @@ fn runThread(ids: *IncrementalDebugServer) void {
74 text_out.clearRetainingCapacity();139 text_out.clearRetainingCapacity();
75 {140 {
76 if (!ids.mutex.tryLock()) {141 if (!ids.mutex.tryLock()) {
77 stream_writer.interface.writeAll("waiting for in-progress update to finish...\n") catch @panic("IncrementalDebugServer: failed to write");142 try stream_writer.writeAll("waiting for in-progress update to finish...\n");
78 ids.mutex.lock();143 try ids.mutex.lock(io);
79 }144 }
80 defer ids.mutex.unlock();145 defer ids.mutex.unlock(io);
81 var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &text_out);146 var allocating: Io.Writer.Allocating = .fromArrayList(gpa, &text_out);
82 defer text_out = allocating.toArrayList();147 defer text_out = allocating.toArrayList();
83 handleCommand(ids.zcu, &allocating.writer, cmd, arg) catch @panic("IncrementalDebugServer: out of memory");148 handleCommand(ids.zcu, &allocating.writer, cmd, arg) catch |err| switch (err) {
149 error.OutOfMemory,
150 error.WriteFailed,
151 => return error.OutOfMemory,
152 };
84 }153 }
85 text_out.append(gpa, '\n') catch @panic("IncrementalDebugServer: out of memory");154 try text_out.append(gpa, '\n');
86 stream_writer.interface.writeAll(text_out.items) catch @panic("IncrementalDebugServer: failed to write");155 try stream_writer.writeAll(text_out.items);
87 }156 }
88 std.debug.print("closing incremental debug server\n", .{});
89}157}
90158
91const help_str: []const u8 =159const help_str: []const u8 =
...@@ -123,7 +191,7 @@ const help_str: []const u8 =...@@ -123,7 +191,7 @@ const help_str: []const u8 =
123 \\191 \\
124;192;
125193
126fn handleCommand(zcu: *Zcu, w: *std.Io.Writer, cmd_str: []const u8, arg_str: []const u8) error{ WriteFailed, OutOfMemory }!void {194fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const u8) error{ WriteFailed, OutOfMemory }!void {
127 const ip = &zcu.intern_pool;195 const ip = &zcu.intern_pool;
128 if (std.mem.eql(u8, cmd_str, "help")) {196 if (std.mem.eql(u8, cmd_str, "help")) {
129 try w.writeAll(help_str);197 try w.writeAll(help_str);
...@@ -328,7 +396,8 @@ fn printAnalUnit(unit: AnalUnit, buf: *[32]u8) []const u8 {...@@ -328,7 +396,8 @@ fn printAnalUnit(unit: AnalUnit, buf: *[32]u8) []const u8 {
328 };396 };
329 return std.fmt.bufPrint(buf, "{s} {d}", .{ @tagName(unit.unwrap()), idx }) catch unreachable;397 return std.fmt.bufPrint(buf, "{s} {d}", .{ @tagName(unit.unwrap()), idx }) catch unreachable;
330}398}
331fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void {399
400fn printType(ty: Type, zcu: *const Zcu, w: *Io.Writer) Io.Writer.Error!void {
332 const ip = &zcu.intern_pool;401 const ip = &zcu.intern_pool;
333 switch (ip.indexToKey(ty.toIntern())) {402 switch (ip.indexToKey(ty.toIntern())) {
334 .int_type => |int| try w.print("{c}{d}", .{403 .int_type => |int| try w.print("{c}{d}", .{
...@@ -377,6 +446,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void {...@@ -377,6 +446,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void {
377const std = @import("std");446const std = @import("std");
378const Io = std.Io;447const Io = std.Io;
379const Allocator = std.mem.Allocator;448const Allocator = std.mem.Allocator;
449const log = std.log.scoped(.incremental_debug_server);
380450
381const Compilation = @import("Compilation.zig");451const Compilation = @import("Compilation.zig");
382const Zcu = @import("Zcu.zig");452const Zcu = @import("Zcu.zig");
src/InternPool.zig+441-331
...@@ -8,6 +8,7 @@ const assert = std.debug.assert;...@@ -8,6 +8,7 @@ const assert = std.debug.assert;
8const BigIntConst = std.math.big.int.Const;8const BigIntConst = std.math.big.int.Const;
9const BigIntMutable = std.math.big.int.Mutable;9const BigIntMutable = std.math.big.int.Mutable;
10const Cache = std.Build.Cache;10const Cache = std.Build.Cache;
11const Io = std.Io;
11const Limb = std.math.big.Limb;12const Limb = std.math.big.Limb;
12const Hash = std.hash.Wyhash;13const Hash = std.hash.Wyhash;
1314
...@@ -214,6 +215,7 @@ pub const TrackedInst = extern struct {...@@ -214,6 +215,7 @@ pub const TrackedInst = extern struct {
214pub fn trackZir(215pub fn trackZir(
215 ip: *InternPool,216 ip: *InternPool,
216 gpa: Allocator,217 gpa: Allocator,
218 io: Io,
217 tid: Zcu.PerThread.Id,219 tid: Zcu.PerThread.Id,
218 key: TrackedInst,220 key: TrackedInst,
219) Allocator.Error!TrackedInst.Index {221) Allocator.Error!TrackedInst.Index {
...@@ -235,8 +237,8 @@ pub fn trackZir(...@@ -235,8 +237,8 @@ pub fn trackZir(
235 if (entry.hash != hash) continue;237 if (entry.hash != hash) continue;
236 if (std.meta.eql(index.resolveFull(ip) orelse continue, key)) return index;238 if (std.meta.eql(index.resolveFull(ip) orelse continue, key)) return index;
237 }239 }
238 shard.mutate.tracked_inst_map.mutex.lock();240 shard.mutate.tracked_inst_map.mutex.lock(io, tid);
239 defer shard.mutate.tracked_inst_map.mutex.unlock();241 defer shard.mutate.tracked_inst_map.mutex.unlock(io);
240 if (map.entries != shard.shared.tracked_inst_map.entries) {242 if (map.entries != shard.shared.tracked_inst_map.entries) {
241 map = shard.shared.tracked_inst_map;243 map = shard.shared.tracked_inst_map;
242 map_mask = map.header().mask();244 map_mask = map.header().mask();
...@@ -251,7 +253,7 @@ pub fn trackZir(...@@ -251,7 +253,7 @@ pub fn trackZir(
251 }253 }
252 defer shard.mutate.tracked_inst_map.len += 1;254 defer shard.mutate.tracked_inst_map.len += 1;
253 const local = ip.getLocal(tid);255 const local = ip.getLocal(tid);
254 const list = local.getMutableTrackedInsts(gpa);256 const list = local.getMutableTrackedInsts(gpa, io);
255 try list.ensureUnusedCapacity(1);257 try list.ensureUnusedCapacity(1);
256 const map_header = map.header().*;258 const map_header = map.header().*;
257 if (shard.mutate.tracked_inst_map.len < map_header.capacity * 3 / 5) {259 if (shard.mutate.tracked_inst_map.len < map_header.capacity * 3 / 5) {
...@@ -317,6 +319,7 @@ pub fn trackZir(...@@ -317,6 +319,7 @@ pub fn trackZir(
317pub fn rehashTrackedInsts(319pub fn rehashTrackedInsts(
318 ip: *InternPool,320 ip: *InternPool,
319 gpa: Allocator,321 gpa: Allocator,
322 io: Io,
320 tid: Zcu.PerThread.Id,323 tid: Zcu.PerThread.Id,
321) Allocator.Error!void {324) Allocator.Error!void {
322 assert(tid == .main); // we shouldn't have any other threads active right now325 assert(tid == .main); // we shouldn't have any other threads active right now
...@@ -333,7 +336,7 @@ pub fn rehashTrackedInsts(...@@ -333,7 +336,7 @@ pub fn rehashTrackedInsts(
333 for (ip.locals) |*local| {336 for (ip.locals) |*local| {
334 // `getMutableTrackedInsts` is okay only because no other thread is currently active.337 // `getMutableTrackedInsts` is okay only because no other thread is currently active.
335 // We need the `mutate` for the len.338 // We need the `mutate` for the len.
336 for (local.getMutableTrackedInsts(gpa).viewAllowEmpty().items(.@"0")) |tracked_inst| {339 for (local.getMutableTrackedInsts(gpa, io).viewAllowEmpty().items(.@"0")) |tracked_inst| {
337 if (tracked_inst.inst == .lost) continue; // we can ignore this one!340 if (tracked_inst.inst == .lost) continue; // we can ignore this one!
338 const full_hash = Hash.hash(0, std.mem.asBytes(&tracked_inst));341 const full_hash = Hash.hash(0, std.mem.asBytes(&tracked_inst));
339 const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))];342 const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))];
...@@ -379,7 +382,7 @@ pub fn rehashTrackedInsts(...@@ -379,7 +382,7 @@ pub fn rehashTrackedInsts(
379 for (ip.locals, 0..) |*local, local_tid| {382 for (ip.locals, 0..) |*local, local_tid| {
380 // `getMutableTrackedInsts` is okay only because no other thread is currently active.383 // `getMutableTrackedInsts` is okay only because no other thread is currently active.
381 // We need the `mutate` for the len.384 // We need the `mutate` for the len.
382 for (local.getMutableTrackedInsts(gpa).viewAllowEmpty().items(.@"0"), 0..) |tracked_inst, local_inst_index| {385 for (local.getMutableTrackedInsts(gpa, io).viewAllowEmpty().items(.@"0"), 0..) |tracked_inst, local_inst_index| {
383 if (tracked_inst.inst == .lost) continue; // we can ignore this one!386 if (tracked_inst.inst == .lost) continue; // we can ignore this one!
384 const full_hash = Hash.hash(0, std.mem.asBytes(&tracked_inst));387 const full_hash = Hash.hash(0, std.mem.asBytes(&tracked_inst));
385 const hash: u32 = @truncate(full_hash >> 32);388 const hash: u32 = @truncate(full_hash >> 32);
...@@ -1113,11 +1116,11 @@ const Local = struct {...@@ -1113,11 +1116,11 @@ const Local = struct {
1113 const Namespaces = List(struct { *[1 << namespaces_bucket_width]Zcu.Namespace });1116 const Namespaces = List(struct { *[1 << namespaces_bucket_width]Zcu.Namespace });
11141117
1115 const ListMutate = struct {1118 const ListMutate = struct {
1116 mutex: std.Thread.Mutex,1119 mutex: Io.Mutex,
1117 len: u32,1120 len: u32,
11181121
1119 const empty: ListMutate = .{1122 const empty: ListMutate = .{
1120 .mutex = .{},1123 .mutex = .init,
1121 .len = 0,1124 .len = 0,
1122 };1125 };
1123 };1126 };
...@@ -1144,6 +1147,7 @@ const Local = struct {...@@ -1144,6 +1147,7 @@ const Local = struct {
1144 const ListSelf = @This();1147 const ListSelf = @This();
1145 const Mutable = struct {1148 const Mutable = struct {
1146 gpa: Allocator,1149 gpa: Allocator,
1150 io: Io,
1147 arena: *std.heap.ArenaAllocator.State,1151 arena: *std.heap.ArenaAllocator.State,
1148 mutate: *ListMutate,1152 mutate: *ListMutate,
1149 list: *ListSelf,1153 list: *ListSelf,
...@@ -1296,6 +1300,7 @@ const Local = struct {...@@ -1296,6 +1300,7 @@ const Local = struct {
1296 }1300 }
12971301
1298 fn setCapacity(mutable: Mutable, capacity: u32) Allocator.Error!void {1302 fn setCapacity(mutable: Mutable, capacity: u32) Allocator.Error!void {
1303 const io = mutable.io;
1299 var arena = mutable.arena.promote(mutable.gpa);1304 var arena = mutable.arena.promote(mutable.gpa);
1300 defer mutable.arena.* = arena.state;1305 defer mutable.arena.* = arena.state;
1301 const buf = try arena.allocator().alignedAlloc(1306 const buf = try arena.allocator().alignedAlloc(
...@@ -1313,8 +1318,8 @@ const Local = struct {...@@ -1313,8 +1318,8 @@ const Local = struct {
1313 const new_slice = new_list.view().slice();1318 const new_slice = new_list.view().slice();
1314 inline for (fields) |field| @memcpy(new_slice.items(field)[0..len], old_slice.items(field)[0..len]);1319 inline for (fields) |field| @memcpy(new_slice.items(field)[0..len], old_slice.items(field)[0..len]);
1315 }1320 }
1316 mutable.mutate.mutex.lock();1321 mutable.mutate.mutex.lockUncancelable(io);
1317 defer mutable.mutate.mutex.unlock();1322 defer mutable.mutate.mutex.unlock(io);
1318 mutable.list.release(new_list);1323 mutable.list.release(new_list);
1319 }1324 }
13201325
...@@ -1375,18 +1380,20 @@ const Local = struct {...@@ -1375,18 +1380,20 @@ const Local = struct {
1375 };1380 };
1376 }1381 }
13771382
1378 pub fn getMutableItems(local: *Local, gpa: Allocator) List(Item).Mutable {1383 pub fn getMutableItems(local: *Local, gpa: Allocator, io: Io) List(Item).Mutable {
1379 return .{1384 return .{
1380 .gpa = gpa,1385 .gpa = gpa,
1386 .io = io,
1381 .arena = &local.mutate.arena,1387 .arena = &local.mutate.arena,
1382 .mutate = &local.mutate.items,1388 .mutate = &local.mutate.items,
1383 .list = &local.shared.items,1389 .list = &local.shared.items,
1384 };1390 };
1385 }1391 }
13861392
1387 pub fn getMutableExtra(local: *Local, gpa: Allocator) Extra.Mutable {1393 pub fn getMutableExtra(local: *Local, gpa: Allocator, io: Io) Extra.Mutable {
1388 return .{1394 return .{
1389 .gpa = gpa,1395 .gpa = gpa,
1396 .io = io,
1390 .arena = &local.mutate.arena,1397 .arena = &local.mutate.arena,
1391 .mutate = &local.mutate.extra,1398 .mutate = &local.mutate.extra,
1392 .list = &local.shared.extra,1399 .list = &local.shared.extra,
...@@ -1397,11 +1404,12 @@ const Local = struct {...@@ -1397,11 +1404,12 @@ const Local = struct {
1397 /// On 64-bit systems, this array is used for big integers and associated metadata.1404 /// On 64-bit systems, this array is used for big integers and associated metadata.
1398 /// Use the helper methods instead of accessing this directly in order to not1405 /// Use the helper methods instead of accessing this directly in order to not
1399 /// violate the above mechanism.1406 /// violate the above mechanism.
1400 pub fn getMutableLimbs(local: *Local, gpa: Allocator) Limbs.Mutable {1407 pub fn getMutableLimbs(local: *Local, gpa: Allocator, io: Io) Limbs.Mutable {
1401 return switch (@sizeOf(Limb)) {1408 return switch (@sizeOf(Limb)) {
1402 @sizeOf(u32) => local.getMutableExtra(gpa),1409 @sizeOf(u32) => local.getMutableExtra(gpa, io),
1403 @sizeOf(u64) => .{1410 @sizeOf(u64) => .{
1404 .gpa = gpa,1411 .gpa = gpa,
1412 .io = io,
1405 .arena = &local.mutate.arena,1413 .arena = &local.mutate.arena,
1406 .mutate = &local.mutate.limbs,1414 .mutate = &local.mutate.limbs,
1407 .list = &local.shared.limbs,1415 .list = &local.shared.limbs,
...@@ -1411,9 +1419,10 @@ const Local = struct {...@@ -1411,9 +1419,10 @@ const Local = struct {
1411 }1419 }
14121420
1413 /// A list of offsets into `string_bytes` for each string.1421 /// A list of offsets into `string_bytes` for each string.
1414 pub fn getMutableStrings(local: *Local, gpa: Allocator) Strings.Mutable {1422 pub fn getMutableStrings(local: *Local, gpa: Allocator, io: Io) Strings.Mutable {
1415 return .{1423 return .{
1416 .gpa = gpa,1424 .gpa = gpa,
1425 .io = io,
1417 .arena = &local.mutate.arena,1426 .arena = &local.mutate.arena,
1418 .mutate = &local.mutate.strings,1427 .mutate = &local.mutate.strings,
1419 .list = &local.shared.strings,1428 .list = &local.shared.strings,
...@@ -1425,9 +1434,10 @@ const Local = struct {...@@ -1425,9 +1434,10 @@ const Local = struct {
1425 /// is referencing the data here whether they want to store both index and length,1434 /// is referencing the data here whether they want to store both index and length,
1426 /// thus allowing null bytes, or store only index, and use null-termination. The1435 /// thus allowing null bytes, or store only index, and use null-termination. The
1427 /// `strings_bytes` array is agnostic to either usage.1436 /// `strings_bytes` array is agnostic to either usage.
1428 pub fn getMutableStringBytes(local: *Local, gpa: Allocator) StringBytes.Mutable {1437 pub fn getMutableStringBytes(local: *Local, gpa: Allocator, io: Io) StringBytes.Mutable {
1429 return .{1438 return .{
1430 .gpa = gpa,1439 .gpa = gpa,
1440 .io = io,
1431 .arena = &local.mutate.arena,1441 .arena = &local.mutate.arena,
1432 .mutate = &local.mutate.string_bytes,1442 .mutate = &local.mutate.string_bytes,
1433 .list = &local.shared.string_bytes,1443 .list = &local.shared.string_bytes,
...@@ -1436,9 +1446,10 @@ const Local = struct {...@@ -1436,9 +1446,10 @@ const Local = struct {
14361446
1437 /// An index into `tracked_insts` gives a reference to a single ZIR instruction which1447 /// An index into `tracked_insts` gives a reference to a single ZIR instruction which
1438 /// persists across incremental updates.1448 /// persists across incremental updates.
1439 pub fn getMutableTrackedInsts(local: *Local, gpa: Allocator) TrackedInsts.Mutable {1449 pub fn getMutableTrackedInsts(local: *Local, gpa: Allocator, io: Io) TrackedInsts.Mutable {
1440 return .{1450 return .{
1441 .gpa = gpa,1451 .gpa = gpa,
1452 .io = io,
1442 .arena = &local.mutate.arena,1453 .arena = &local.mutate.arena,
1443 .mutate = &local.mutate.tracked_insts,1454 .mutate = &local.mutate.tracked_insts,
1444 .list = &local.shared.tracked_insts,1455 .list = &local.shared.tracked_insts,
...@@ -1452,9 +1463,10 @@ const Local = struct {...@@ -1452,9 +1463,10 @@ const Local = struct {
1452 ///1463 ///
1453 /// Key is the hash of the path to this file, used to store1464 /// Key is the hash of the path to this file, used to store
1454 /// `InternPool.TrackedInst`.1465 /// `InternPool.TrackedInst`.
1455 pub fn getMutableFiles(local: *Local, gpa: Allocator) List(File).Mutable {1466 pub fn getMutableFiles(local: *Local, gpa: Allocator, io: Io) List(File).Mutable {
1456 return .{1467 return .{
1457 .gpa = gpa,1468 .gpa = gpa,
1469 .io = io,
1458 .arena = &local.mutate.arena,1470 .arena = &local.mutate.arena,
1459 .mutate = &local.mutate.files,1471 .mutate = &local.mutate.files,
1460 .list = &local.shared.files,1472 .list = &local.shared.files,
...@@ -1466,27 +1478,30 @@ const Local = struct {...@@ -1466,27 +1478,30 @@ const Local = struct {
1466 /// field names and values directly, relying on one of these maps, stored separately,1478 /// field names and values directly, relying on one of these maps, stored separately,
1467 /// to provide lookup.1479 /// to provide lookup.
1468 /// These are not serialized; it is computed upon deserialization.1480 /// These are not serialized; it is computed upon deserialization.
1469 pub fn getMutableMaps(local: *Local, gpa: Allocator) Maps.Mutable {1481 pub fn getMutableMaps(local: *Local, gpa: Allocator, io: Io) Maps.Mutable {
1470 return .{1482 return .{
1471 .gpa = gpa,1483 .gpa = gpa,
1484 .io = io,
1472 .arena = &local.mutate.arena,1485 .arena = &local.mutate.arena,
1473 .mutate = &local.mutate.maps,1486 .mutate = &local.mutate.maps,
1474 .list = &local.shared.maps,1487 .list = &local.shared.maps,
1475 };1488 };
1476 }1489 }
14771490
1478 pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable {1491 pub fn getMutableNavs(local: *Local, gpa: Allocator, io: Io) Navs.Mutable {
1479 return .{1492 return .{
1480 .gpa = gpa,1493 .gpa = gpa,
1494 .io = io,
1481 .arena = &local.mutate.arena,1495 .arena = &local.mutate.arena,
1482 .mutate = &local.mutate.navs,1496 .mutate = &local.mutate.navs,
1483 .list = &local.shared.navs,1497 .list = &local.shared.navs,
1484 };1498 };
1485 }1499 }
14861500
1487 pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator) ComptimeUnits.Mutable {1501 pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator, io: Io) ComptimeUnits.Mutable {
1488 return .{1502 return .{
1489 .gpa = gpa,1503 .gpa = gpa,
1504 .io = io,
1490 .arena = &local.mutate.arena,1505 .arena = &local.mutate.arena,
1491 .mutate = &local.mutate.comptime_units,1506 .mutate = &local.mutate.comptime_units,
1492 .list = &local.shared.comptime_units,1507 .list = &local.shared.comptime_units,
...@@ -1503,9 +1518,10 @@ const Local = struct {...@@ -1503,9 +1518,10 @@ const Local = struct {
1503 /// serialization trivial.1518 /// serialization trivial.
1504 /// * It provides a unique integer to be used for anonymous symbol names, avoiding1519 /// * It provides a unique integer to be used for anonymous symbol names, avoiding
1505 /// multi-threaded contention on an atomic counter.1520 /// multi-threaded contention on an atomic counter.
1506 pub fn getMutableNamespaces(local: *Local, gpa: Allocator) Namespaces.Mutable {1521 pub fn getMutableNamespaces(local: *Local, gpa: Allocator, io: Io) Namespaces.Mutable {
1507 return .{1522 return .{
1508 .gpa = gpa,1523 .gpa = gpa,
1524 .io = io,
1509 .arena = &local.mutate.arena,1525 .arena = &local.mutate.arena,
1510 .mutate = &local.mutate.namespaces.buckets_list,1526 .mutate = &local.mutate.namespaces.buckets_list,
1511 .list = &local.shared.namespaces,1527 .list = &local.shared.namespaces,
...@@ -1535,11 +1551,63 @@ const Shard = struct {...@@ -1535,11 +1551,63 @@ const Shard = struct {
1535 },1551 },
15361552
1537 const Mutate = struct {1553 const Mutate = struct {
1538 mutex: std.Thread.Mutex.Recursive,1554 /// This mutex needs to be recursive because `getFuncDeclIes` interns multiple things at
1555 /// once (the function, its IES, the corresponding error union, and the resulting function
1556 /// type), so calls `getOrPutKeyEnsuringAdditionalCapacity` multiple times. Each of these
1557 /// calls acquires a lock which will only be released when the whole operation is finalized,
1558 /// and these different items could be in the same shard, in which case that shard's lock
1559 /// will be acquired multiple times.
1560 mutex: RecursiveMutex,
1539 len: u32,1561 len: u32,
15401562
1563 const RecursiveMutex = struct {
1564 const OptionalTid = if (single_threaded) enum(u8) {
1565 null,
1566 main,
1567 fn unwrap(ot: OptionalTid) ?Zcu.PerThread.Id {
1568 return switch (ot) {
1569 .null => null,
1570 .main => .main,
1571 };
1572 }
1573 fn wrap(tid: Zcu.PerThread.Id) OptionalTid {
1574 comptime assert(tid == .main);
1575 return .main;
1576 }
1577 } else packed struct(u8) {
1578 non_null: bool,
1579 value: Zcu.PerThread.Id,
1580 const @"null": OptionalTid = .{ .non_null = false, .value = .main };
1581 fn unwrap(ot: OptionalTid) ?Zcu.PerThread.Id {
1582 return if (ot.non_null) ot.value else null;
1583 }
1584 fn wrap(tid: Zcu.PerThread.Id) OptionalTid {
1585 return .{ .non_null = true, .value = tid };
1586 }
1587 };
1588 mutex: Io.Mutex,
1589 tid: std.atomic.Value(OptionalTid),
1590 lock_count: u32,
1591 const init: RecursiveMutex = .{ .mutex = .init, .tid = .init(.null), .lock_count = 0 };
1592 fn lock(r: *RecursiveMutex, io: Io, tid: Zcu.PerThread.Id) void {
1593 if (r.tid.load(.monotonic) != OptionalTid.wrap(tid)) {
1594 r.mutex.lockUncancelable(io);
1595 assert(r.lock_count == 0);
1596 r.tid.store(.wrap(tid), .monotonic);
1597 }
1598 r.lock_count += 1;
1599 }
1600 fn unlock(r: *RecursiveMutex, io: Io) void {
1601 r.lock_count -= 1;
1602 if (r.lock_count == 0) {
1603 r.tid.store(.null, .monotonic);
1604 r.mutex.unlock(io);
1605 }
1606 }
1607 };
1608
1541 const empty: Mutate = .{1609 const empty: Mutate = .{
1542 .mutex = std.Thread.Mutex.Recursive.init,1610 .mutex = .init,
1543 .len = 0,1611 .len = 0,
1544 };1612 };
1545 };1613 };
...@@ -1896,7 +1964,7 @@ pub const NullTerminatedString = enum(u32) {...@@ -1896,7 +1964,7 @@ pub const NullTerminatedString = enum(u32) {
1896 ip: *const InternPool,1964 ip: *const InternPool,
1897 id: bool,1965 id: bool,
1898 };1966 };
1899 fn format(data: FormatData, writer: *std.Io.Writer) std.Io.Writer.Error!void {1967 fn format(data: FormatData, writer: *Io.Writer) Io.Writer.Error!void {
1900 const slice = data.string.toSlice(data.ip);1968 const slice = data.string.toSlice(data.ip);
1901 if (!data.id) {1969 if (!data.id) {
1902 try writer.writeAll(slice);1970 try writer.writeAll(slice);
...@@ -2323,10 +2391,10 @@ pub const Key = union(enum) {...@@ -2323,10 +2391,10 @@ pub const Key = union(enum) {
2323 return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered);2391 return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered);
2324 }2392 }
23252393
2326 pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void {2394 pub fn setBranchHint(func: Func, ip: *InternPool, io: Io, hint: std.builtin.BranchHint) void {
2327 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;2395 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2328 extra_mutex.lock();2396 extra_mutex.lockUncancelable(io);
2329 defer extra_mutex.unlock();2397 defer extra_mutex.unlock(io);
23302398
2331 const analysis_ptr = func.analysisPtr(ip);2399 const analysis_ptr = func.analysisPtr(ip);
2332 var analysis = analysis_ptr.*;2400 var analysis = analysis_ptr.*;
...@@ -2334,10 +2402,10 @@ pub const Key = union(enum) {...@@ -2334,10 +2402,10 @@ pub const Key = union(enum) {
2334 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);2402 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
2335 }2403 }
23362404
2337 pub fn setAnalyzed(func: Func, ip: *InternPool) void {2405 pub fn setAnalyzed(func: Func, ip: *InternPool, io: Io) void {
2338 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;2406 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2339 extra_mutex.lock();2407 extra_mutex.lockUncancelable(io);
2340 defer extra_mutex.unlock();2408 defer extra_mutex.unlock(io);
23412409
2342 const analysis_ptr = func.analysisPtr(ip);2410 const analysis_ptr = func.analysisPtr(ip);
2343 var analysis = analysis_ptr.*;2411 var analysis = analysis_ptr.*;
...@@ -2365,10 +2433,10 @@ pub const Key = union(enum) {...@@ -2365,10 +2433,10 @@ pub const Key = union(enum) {
2365 return @atomicLoad(u32, func.branchQuotaPtr(ip), .unordered);2433 return @atomicLoad(u32, func.branchQuotaPtr(ip), .unordered);
2366 }2434 }
23672435
2368 pub fn maxBranchQuota(func: Func, ip: *InternPool, new_branch_quota: u32) void {2436 pub fn maxBranchQuota(func: Func, ip: *InternPool, io: Io, new_branch_quota: u32) void {
2369 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;2437 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2370 extra_mutex.lock();2438 extra_mutex.lockUncancelable(io);
2371 defer extra_mutex.unlock();2439 defer extra_mutex.unlock(io);
23722440
2373 const branch_quota_ptr = func.branchQuotaPtr(ip);2441 const branch_quota_ptr = func.branchQuotaPtr(ip);
2374 @atomicStore(u32, branch_quota_ptr, @max(branch_quota_ptr.*, new_branch_quota), .release);2442 @atomicStore(u32, branch_quota_ptr, @max(branch_quota_ptr.*, new_branch_quota), .release);
...@@ -2385,10 +2453,10 @@ pub const Key = union(enum) {...@@ -2385,10 +2453,10 @@ pub const Key = union(enum) {
2385 return @atomicLoad(Index, func.resolvedErrorSetPtr(ip), .unordered);2453 return @atomicLoad(Index, func.resolvedErrorSetPtr(ip), .unordered);
2386 }2454 }
23872455
2388 pub fn setResolvedErrorSet(func: Func, ip: *InternPool, ies: Index) void {2456 pub fn setResolvedErrorSet(func: Func, ip: *InternPool, io: Io, ies: Index) void {
2389 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;2457 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex;
2390 extra_mutex.lock();2458 extra_mutex.lockUncancelable(io);
2391 defer extra_mutex.unlock();2459 defer extra_mutex.unlock(io);
23922460
2393 @atomicStore(Index, func.resolvedErrorSetPtr(ip), ies, .release);2461 @atomicStore(Index, func.resolvedErrorSetPtr(ip), ies, .release);
2394 }2462 }
...@@ -3349,10 +3417,10 @@ pub const LoadedUnionType = struct {...@@ -3349,10 +3417,10 @@ pub const LoadedUnionType = struct {
3349 return @atomicLoad(Index, u.tagTypePtr(ip), .unordered);3417 return @atomicLoad(Index, u.tagTypePtr(ip), .unordered);
3350 }3418 }
33513419
3352 pub fn setTagType(u: LoadedUnionType, ip: *InternPool, tag_type: Index) void {3420 pub fn setTagType(u: LoadedUnionType, ip: *InternPool, io: Io, tag_type: Index) void {
3353 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3421 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3354 extra_mutex.lock();3422 extra_mutex.lockUncancelable(io);
3355 defer extra_mutex.unlock();3423 defer extra_mutex.unlock(io);
33563424
3357 @atomicStore(Index, u.tagTypePtr(ip), tag_type, .release);3425 @atomicStore(Index, u.tagTypePtr(ip), tag_type, .release);
3358 }3426 }
...@@ -3368,10 +3436,10 @@ pub const LoadedUnionType = struct {...@@ -3368,10 +3436,10 @@ pub const LoadedUnionType = struct {
3368 return @atomicLoad(Tag.TypeUnion.Flags, u.flagsPtr(ip), .unordered);3436 return @atomicLoad(Tag.TypeUnion.Flags, u.flagsPtr(ip), .unordered);
3369 }3437 }
33703438
3371 pub fn setStatus(u: LoadedUnionType, ip: *InternPool, status: Status) void {3439 pub fn setStatus(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void {
3372 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3440 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3373 extra_mutex.lock();3441 extra_mutex.lockUncancelable(io);
3374 defer extra_mutex.unlock();3442 defer extra_mutex.unlock(io);
33753443
3376 const flags_ptr = u.flagsPtr(ip);3444 const flags_ptr = u.flagsPtr(ip);
3377 var flags = flags_ptr.*;3445 var flags = flags_ptr.*;
...@@ -3379,10 +3447,10 @@ pub const LoadedUnionType = struct {...@@ -3379,10 +3447,10 @@ pub const LoadedUnionType = struct {
3379 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);3447 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3380 }3448 }
33813449
3382 pub fn setStatusIfLayoutWip(u: LoadedUnionType, ip: *InternPool, status: Status) void {3450 pub fn setStatusIfLayoutWip(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void {
3383 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3451 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3384 extra_mutex.lock();3452 extra_mutex.lockUncancelable(io);
3385 defer extra_mutex.unlock();3453 defer extra_mutex.unlock(io);
33863454
3387 const flags_ptr = u.flagsPtr(ip);3455 const flags_ptr = u.flagsPtr(ip);
3388 var flags = flags_ptr.*;3456 var flags = flags_ptr.*;
...@@ -3390,10 +3458,10 @@ pub const LoadedUnionType = struct {...@@ -3390,10 +3458,10 @@ pub const LoadedUnionType = struct {
3390 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);3458 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3391 }3459 }
33923460
3393 pub fn setAlignment(u: LoadedUnionType, ip: *InternPool, alignment: Alignment) void {3461 pub fn setAlignment(u: LoadedUnionType, ip: *InternPool, io: Io, alignment: Alignment) void {
3394 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3462 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3395 extra_mutex.lock();3463 extra_mutex.lockUncancelable(io);
3396 defer extra_mutex.unlock();3464 defer extra_mutex.unlock(io);
33973465
3398 const flags_ptr = u.flagsPtr(ip);3466 const flags_ptr = u.flagsPtr(ip);
3399 var flags = flags_ptr.*;3467 var flags = flags_ptr.*;
...@@ -3401,10 +3469,10 @@ pub const LoadedUnionType = struct {...@@ -3401,10 +3469,10 @@ pub const LoadedUnionType = struct {
3401 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);3469 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3402 }3470 }
34033471
3404 pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool) bool {3472 pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io) bool {
3405 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3473 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3406 extra_mutex.lock();3474 extra_mutex.lockUncancelable(io);
3407 defer extra_mutex.unlock();3475 defer extra_mutex.unlock(io);
34083476
3409 const flags_ptr = u.flagsPtr(ip);3477 const flags_ptr = u.flagsPtr(ip);
3410 var flags = flags_ptr.*;3478 var flags = flags_ptr.*;
...@@ -3419,10 +3487,10 @@ pub const LoadedUnionType = struct {...@@ -3419,10 +3487,10 @@ pub const LoadedUnionType = struct {
3419 return u.flagsUnordered(ip).requires_comptime;3487 return u.flagsUnordered(ip).requires_comptime;
3420 }3488 }
34213489
3422 pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool) RequiresComptime {3490 pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool, io: Io) RequiresComptime {
3423 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3491 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3424 extra_mutex.lock();3492 extra_mutex.lockUncancelable(io);
3425 defer extra_mutex.unlock();3493 defer extra_mutex.unlock(io);
34263494
3427 const flags_ptr = u.flagsPtr(ip);3495 const flags_ptr = u.flagsPtr(ip);
3428 var flags = flags_ptr.*;3496 var flags = flags_ptr.*;
...@@ -3433,12 +3501,12 @@ pub const LoadedUnionType = struct {...@@ -3433,12 +3501,12 @@ pub const LoadedUnionType = struct {
3433 return flags.requires_comptime;3501 return flags.requires_comptime;
3434 }3502 }
34353503
3436 pub fn setRequiresComptime(u: LoadedUnionType, ip: *InternPool, requires_comptime: RequiresComptime) void {3504 pub fn setRequiresComptime(u: LoadedUnionType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void {
3437 assert(requires_comptime != .wip); // see setRequiresComptimeWip3505 assert(requires_comptime != .wip); // see setRequiresComptimeWip
34383506
3439 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3507 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3440 extra_mutex.lock();3508 extra_mutex.lockUncancelable(io);
3441 defer extra_mutex.unlock();3509 defer extra_mutex.unlock(io);
34423510
3443 const flags_ptr = u.flagsPtr(ip);3511 const flags_ptr = u.flagsPtr(ip);
3444 var flags = flags_ptr.*;3512 var flags = flags_ptr.*;
...@@ -3446,10 +3514,10 @@ pub const LoadedUnionType = struct {...@@ -3446,10 +3514,10 @@ pub const LoadedUnionType = struct {
3446 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);3514 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3447 }3515 }
34483516
3449 pub fn assumePointerAlignedIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, ptr_align: Alignment) bool {3517 pub fn assumePointerAlignedIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io, ptr_align: Alignment) bool {
3450 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3518 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3451 extra_mutex.lock();3519 extra_mutex.lockUncancelable(io);
3452 defer extra_mutex.unlock();3520 defer extra_mutex.unlock(io);
34533521
3454 const flags_ptr = u.flagsPtr(ip);3522 const flags_ptr = u.flagsPtr(ip);
3455 var flags = flags_ptr.*;3523 var flags = flags_ptr.*;
...@@ -3495,10 +3563,10 @@ pub const LoadedUnionType = struct {...@@ -3495,10 +3563,10 @@ pub const LoadedUnionType = struct {
3495 return self.flagsUnordered(ip).status.haveLayout();3563 return self.flagsUnordered(ip).status.haveLayout();
3496 }3564 }
34973565
3498 pub fn setHaveLayout(u: LoadedUnionType, ip: *InternPool, size: u32, padding: u32, alignment: Alignment) void {3566 pub fn setHaveLayout(u: LoadedUnionType, ip: *InternPool, io: Io, size: u32, padding: u32, alignment: Alignment) void {
3499 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;3567 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3500 extra_mutex.lock();3568 extra_mutex.lockUncancelable(io);
3501 defer extra_mutex.unlock();3569 defer extra_mutex.unlock(io);
35023570
3503 @atomicStore(u32, u.sizePtr(ip), size, .unordered);3571 @atomicStore(u32, u.sizePtr(ip), size, .unordered);
3504 @atomicStore(u32, u.paddingPtr(ip), padding, .unordered);3572 @atomicStore(u32, u.paddingPtr(ip), padding, .unordered);
...@@ -3767,10 +3835,10 @@ pub const LoadedStructType = struct {...@@ -3767,10 +3835,10 @@ pub const LoadedStructType = struct {
3767 return s.flagsUnordered(ip).requires_comptime;3835 return s.flagsUnordered(ip).requires_comptime;
3768 }3836 }
37693837
3770 pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool) RequiresComptime {3838 pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool, io: Io) RequiresComptime {
3771 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3839 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3772 extra_mutex.lock();3840 extra_mutex.lockUncancelable(io);
3773 defer extra_mutex.unlock();3841 defer extra_mutex.unlock(io);
37743842
3775 const flags_ptr = s.flagsPtr(ip);3843 const flags_ptr = s.flagsPtr(ip);
3776 var flags = flags_ptr.*;3844 var flags = flags_ptr.*;
...@@ -3781,12 +3849,12 @@ pub const LoadedStructType = struct {...@@ -3781,12 +3849,12 @@ pub const LoadedStructType = struct {
3781 return flags.requires_comptime;3849 return flags.requires_comptime;
3782 }3850 }
37833851
3784 pub fn setRequiresComptime(s: LoadedStructType, ip: *InternPool, requires_comptime: RequiresComptime) void {3852 pub fn setRequiresComptime(s: LoadedStructType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void {
3785 assert(requires_comptime != .wip); // see setRequiresComptimeWip3853 assert(requires_comptime != .wip); // see setRequiresComptimeWip
37863854
3787 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3855 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3788 extra_mutex.lock();3856 extra_mutex.lockUncancelable(io);
3789 defer extra_mutex.unlock();3857 defer extra_mutex.unlock(io);
37903858
3791 const flags_ptr = s.flagsPtr(ip);3859 const flags_ptr = s.flagsPtr(ip);
3792 var flags = flags_ptr.*;3860 var flags = flags_ptr.*;
...@@ -3794,12 +3862,12 @@ pub const LoadedStructType = struct {...@@ -3794,12 +3862,12 @@ pub const LoadedStructType = struct {
3794 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);3862 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3795 }3863 }
37963864
3797 pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool) bool {3865 pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3798 if (s.layout == .@"packed") return false;3866 if (s.layout == .@"packed") return false;
37993867
3800 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3868 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3801 extra_mutex.lock();3869 extra_mutex.lockUncancelable(io);
3802 defer extra_mutex.unlock();3870 defer extra_mutex.unlock(io);
38033871
3804 const flags_ptr = s.flagsPtr(ip);3872 const flags_ptr = s.flagsPtr(ip);
3805 var flags = flags_ptr.*;3873 var flags = flags_ptr.*;
...@@ -3810,12 +3878,12 @@ pub const LoadedStructType = struct {...@@ -3810,12 +3878,12 @@ pub const LoadedStructType = struct {
3810 return flags.field_types_wip;3878 return flags.field_types_wip;
3811 }3879 }
38123880
3813 pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool) bool {3881 pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3814 if (s.layout == .@"packed") return false;3882 if (s.layout == .@"packed") return false;
38153883
3816 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3884 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3817 extra_mutex.lock();3885 extra_mutex.lockUncancelable(io);
3818 defer extra_mutex.unlock();3886 defer extra_mutex.unlock(io);
38193887
3820 const flags_ptr = s.flagsPtr(ip);3888 const flags_ptr = s.flagsPtr(ip);
3821 var flags = flags_ptr.*;3889 var flags = flags_ptr.*;
...@@ -3826,12 +3894,12 @@ pub const LoadedStructType = struct {...@@ -3826,12 +3894,12 @@ pub const LoadedStructType = struct {
3826 return flags.field_types_wip;3894 return flags.field_types_wip;
3827 }3895 }
38283896
3829 pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool) void {3897 pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) void {
3830 if (s.layout == .@"packed") return;3898 if (s.layout == .@"packed") return;
38313899
3832 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3900 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3833 extra_mutex.lock();3901 extra_mutex.lockUncancelable(io);
3834 defer extra_mutex.unlock();3902 defer extra_mutex.unlock(io);
38353903
3836 const flags_ptr = s.flagsPtr(ip);3904 const flags_ptr = s.flagsPtr(ip);
3837 var flags = flags_ptr.*;3905 var flags = flags_ptr.*;
...@@ -3839,12 +3907,12 @@ pub const LoadedStructType = struct {...@@ -3839,12 +3907,12 @@ pub const LoadedStructType = struct {
3839 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);3907 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3840 }3908 }
38413909
3842 pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool) bool {3910 pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3843 if (s.layout == .@"packed") return false;3911 if (s.layout == .@"packed") return false;
38443912
3845 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3913 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3846 extra_mutex.lock();3914 extra_mutex.lockUncancelable(io);
3847 defer extra_mutex.unlock();3915 defer extra_mutex.unlock(io);
38483916
3849 const flags_ptr = s.flagsPtr(ip);3917 const flags_ptr = s.flagsPtr(ip);
3850 var flags = flags_ptr.*;3918 var flags = flags_ptr.*;
...@@ -3855,12 +3923,12 @@ pub const LoadedStructType = struct {...@@ -3855,12 +3923,12 @@ pub const LoadedStructType = struct {
3855 return flags.layout_wip;3923 return flags.layout_wip;
3856 }3924 }
38573925
3858 pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool) void {3926 pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) void {
3859 if (s.layout == .@"packed") return;3927 if (s.layout == .@"packed") return;
38603928
3861 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3929 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3862 extra_mutex.lock();3930 extra_mutex.lockUncancelable(io);
3863 defer extra_mutex.unlock();3931 defer extra_mutex.unlock(io);
38643932
3865 const flags_ptr = s.flagsPtr(ip);3933 const flags_ptr = s.flagsPtr(ip);
3866 var flags = flags_ptr.*;3934 var flags = flags_ptr.*;
...@@ -3868,10 +3936,10 @@ pub const LoadedStructType = struct {...@@ -3868,10 +3936,10 @@ pub const LoadedStructType = struct {
3868 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);3936 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3869 }3937 }
38703938
3871 pub fn setAlignment(s: LoadedStructType, ip: *InternPool, alignment: Alignment) void {3939 pub fn setAlignment(s: LoadedStructType, ip: *InternPool, io: Io, alignment: Alignment) void {
3872 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3940 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3873 extra_mutex.lock();3941 extra_mutex.lockUncancelable(io);
3874 defer extra_mutex.unlock();3942 defer extra_mutex.unlock(io);
38753943
3876 const flags_ptr = s.flagsPtr(ip);3944 const flags_ptr = s.flagsPtr(ip);
3877 var flags = flags_ptr.*;3945 var flags = flags_ptr.*;
...@@ -3879,10 +3947,10 @@ pub const LoadedStructType = struct {...@@ -3879,10 +3947,10 @@ pub const LoadedStructType = struct {
3879 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);3947 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3880 }3948 }
38813949
3882 pub fn assumePointerAlignedIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, ptr_align: Alignment) bool {3950 pub fn assumePointerAlignedIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool {
3883 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3951 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3884 extra_mutex.lock();3952 extra_mutex.lockUncancelable(io);
3885 defer extra_mutex.unlock();3953 defer extra_mutex.unlock(io);
38863954
3887 const flags_ptr = s.flagsPtr(ip);3955 const flags_ptr = s.flagsPtr(ip);
3888 var flags = flags_ptr.*;3956 var flags = flags_ptr.*;
...@@ -3894,10 +3962,10 @@ pub const LoadedStructType = struct {...@@ -3894,10 +3962,10 @@ pub const LoadedStructType = struct {
3894 return flags.field_types_wip;3962 return flags.field_types_wip;
3895 }3963 }
38963964
3897 pub fn assumePointerAlignedIfWip(s: LoadedStructType, ip: *InternPool, ptr_align: Alignment) bool {3965 pub fn assumePointerAlignedIfWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool {
3898 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3966 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3899 extra_mutex.lock();3967 extra_mutex.lockUncancelable(io);
3900 defer extra_mutex.unlock();3968 defer extra_mutex.unlock(io);
39013969
3902 const flags_ptr = s.flagsPtr(ip);3970 const flags_ptr = s.flagsPtr(ip);
3903 var flags = flags_ptr.*;3971 var flags = flags_ptr.*;
...@@ -3911,12 +3979,12 @@ pub const LoadedStructType = struct {...@@ -3911,12 +3979,12 @@ pub const LoadedStructType = struct {
3911 return flags.alignment_wip;3979 return flags.alignment_wip;
3912 }3980 }
39133981
3914 pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool) void {3982 pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool, io: Io) void {
3915 if (s.layout == .@"packed") return;3983 if (s.layout == .@"packed") return;
39163984
3917 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3985 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3918 extra_mutex.lock();3986 extra_mutex.lockUncancelable(io);
3919 defer extra_mutex.unlock();3987 defer extra_mutex.unlock(io);
39203988
3921 const flags_ptr = s.flagsPtr(ip);3989 const flags_ptr = s.flagsPtr(ip);
3922 var flags = flags_ptr.*;3990 var flags = flags_ptr.*;
...@@ -3924,10 +3992,10 @@ pub const LoadedStructType = struct {...@@ -3924,10 +3992,10 @@ pub const LoadedStructType = struct {
3924 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);3992 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3925 }3993 }
39263994
3927 pub fn setInitsWip(s: LoadedStructType, ip: *InternPool) bool {3995 pub fn setInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3928 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;3996 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3929 extra_mutex.lock();3997 extra_mutex.lockUncancelable(io);
3930 defer extra_mutex.unlock();3998 defer extra_mutex.unlock(io);
39313999
3932 switch (s.layout) {4000 switch (s.layout) {
3933 .@"packed" => {4001 .@"packed" => {
...@@ -3951,10 +4019,10 @@ pub const LoadedStructType = struct {...@@ -3951,10 +4019,10 @@ pub const LoadedStructType = struct {
3951 }4019 }
3952 }4020 }
39534021
3954 pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool) void {4022 pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) void {
3955 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;4023 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3956 extra_mutex.lock();4024 extra_mutex.lockUncancelable(io);
3957 defer extra_mutex.unlock();4025 defer extra_mutex.unlock(io);
39584026
3959 switch (s.layout) {4027 switch (s.layout) {
3960 .@"packed" => {4028 .@"packed" => {
...@@ -3972,12 +4040,12 @@ pub const LoadedStructType = struct {...@@ -3972,12 +4040,12 @@ pub const LoadedStructType = struct {
3972 }4040 }
3973 }4041 }
39744042
3975 pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool) bool {4043 pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3976 if (s.layout == .@"packed") return true;4044 if (s.layout == .@"packed") return true;
39774045
3978 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;4046 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3979 extra_mutex.lock();4047 extra_mutex.lockUncancelable(io);
3980 defer extra_mutex.unlock();4048 defer extra_mutex.unlock(io);
39814049
3982 const flags_ptr = s.flagsPtr(ip);4050 const flags_ptr = s.flagsPtr(ip);
3983 var flags = flags_ptr.*;4051 var flags = flags_ptr.*;
...@@ -3988,10 +4056,10 @@ pub const LoadedStructType = struct {...@@ -3988,10 +4056,10 @@ pub const LoadedStructType = struct {
3988 return flags.fully_resolved;4056 return flags.fully_resolved;
3989 }4057 }
39904058
3991 pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool) void {4059 pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) void {
3992 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;4060 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3993 extra_mutex.lock();4061 extra_mutex.lockUncancelable(io);
3994 defer extra_mutex.unlock();4062 defer extra_mutex.unlock(io);
39954063
3996 const flags_ptr = s.flagsPtr(ip);4064 const flags_ptr = s.flagsPtr(ip);
3997 var flags = flags_ptr.*;4065 var flags = flags_ptr.*;
...@@ -4027,10 +4095,10 @@ pub const LoadedStructType = struct {...@@ -4027,10 +4095,10 @@ pub const LoadedStructType = struct {
4027 return @atomicLoad(Index, s.backingIntTypePtr(ip), .unordered);4095 return @atomicLoad(Index, s.backingIntTypePtr(ip), .unordered);
4028 }4096 }
40294097
4030 pub fn setBackingIntType(s: LoadedStructType, ip: *InternPool, backing_int_ty: Index) void {4098 pub fn setBackingIntType(s: LoadedStructType, ip: *InternPool, io: Io, backing_int_ty: Index) void {
4031 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;4099 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4032 extra_mutex.lock();4100 extra_mutex.lockUncancelable(io);
4033 defer extra_mutex.unlock();4101 defer extra_mutex.unlock(io);
40344102
4035 @atomicStore(Index, s.backingIntTypePtr(ip), backing_int_ty, .release);4103 @atomicStore(Index, s.backingIntTypePtr(ip), backing_int_ty, .release);
4036 }4104 }
...@@ -4054,10 +4122,10 @@ pub const LoadedStructType = struct {...@@ -4054,10 +4122,10 @@ pub const LoadedStructType = struct {
4054 };4122 };
4055 }4123 }
40564124
4057 pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool) void {4125 pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool, io: Io) void {
4058 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;4126 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4059 extra_mutex.lock();4127 extra_mutex.lockUncancelable(io);
4060 defer extra_mutex.unlock();4128 defer extra_mutex.unlock(io);
40614129
4062 switch (s.layout) {4130 switch (s.layout) {
4063 .@"packed" => {4131 .@"packed" => {
...@@ -4082,10 +4150,10 @@ pub const LoadedStructType = struct {...@@ -4082,10 +4150,10 @@ pub const LoadedStructType = struct {
4082 };4150 };
4083 }4151 }
40844152
4085 pub fn setLayoutResolved(s: LoadedStructType, ip: *InternPool, size: u32, alignment: Alignment) void {4153 pub fn setLayoutResolved(s: LoadedStructType, ip: *InternPool, io: Io, size: u32, alignment: Alignment) void {
4086 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;4154 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4087 extra_mutex.lock();4155 extra_mutex.lockUncancelable(io);
4088 defer extra_mutex.unlock();4156 defer extra_mutex.unlock(io);
40894157
4090 @atomicStore(u32, s.sizePtr(ip), size, .unordered);4158 @atomicStore(u32, s.sizePtr(ip), size, .unordered);
4091 const flags_ptr = s.flagsPtr(ip);4159 const flags_ptr = s.flagsPtr(ip);
...@@ -6826,8 +6894,8 @@ pub const MemoizedCall = struct {...@@ -6826,8 +6894,8 @@ pub const MemoizedCall = struct {
6826 branch_count: u32,6894 branch_count: u32,
6827};6895};
68286896
6829pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {6897pub fn init(ip: *InternPool, gpa: Allocator, io: Io, available_threads: usize) !void {
6830 errdefer ip.deinit(gpa);6898 errdefer ip.deinit(gpa, io);
6831 assert(ip.locals.len == 0 and ip.shards.len == 0);6899 assert(ip.locals.len == 0 and ip.shards.len == 0);
6832 assert(available_threads > 0 and available_threads <= std.math.maxInt(u8));6900 assert(available_threads > 0 and available_threads <= std.math.maxInt(u8));
68336901
...@@ -6865,7 +6933,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -6865,7 +6933,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
6865 .namespaces = .empty,6933 .namespaces = .empty,
6866 },6934 },
6867 });6935 });
6868 for (ip.locals) |*local| try local.getMutableStrings(gpa).append(.{0});6936 for (ip.locals) |*local| try local.getMutableStrings(gpa, io).append(.{0});
68696937
6870 ip.tid_width = @intCast(std.math.log2_int_ceil(usize, used_threads));6938 ip.tid_width = @intCast(std.math.log2_int_ceil(usize, used_threads));
6871 ip.tid_shift_30 = if (single_threaded) 0 else 30 - ip.tid_width;6939 ip.tid_shift_30 = if (single_threaded) 0 else 30 - ip.tid_width;
...@@ -6874,28 +6942,28 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -6874,28 +6942,28 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
6874 ip.shards = try gpa.alloc(Shard, @as(usize, 1) << ip.tid_width);6942 ip.shards = try gpa.alloc(Shard, @as(usize, 1) << ip.tid_width);
6875 @memset(ip.shards, .{6943 @memset(ip.shards, .{
6876 .shared = .{6944 .shared = .{
6877 .map = Shard.Map(Index).empty,6945 .map = .empty,
6878 .string_map = Shard.Map(OptionalNullTerminatedString).empty,6946 .string_map = .empty,
6879 .tracked_inst_map = Shard.Map(TrackedInst.Index.Optional).empty,6947 .tracked_inst_map = .empty,
6880 },6948 },
6881 .mutate = .{6949 .mutate = .{
6882 .map = Shard.Mutate.empty,6950 .map = .empty,
6883 .string_map = Shard.Mutate.empty,6951 .string_map = .empty,
6884 .tracked_inst_map = Shard.Mutate.empty,6952 .tracked_inst_map = .empty,
6885 },6953 },
6886 });6954 });
68876955
6888 // Reserve string index 0 for an empty string.6956 // Reserve string index 0 for an empty string.
6889 assert((try ip.getOrPutString(gpa, .main, "", .no_embedded_nulls)) == .empty);6957 assert((try ip.getOrPutString(gpa, io, .main, "", .no_embedded_nulls)) == .empty);
68906958
6891 // This inserts all the statically-known values into the intern pool in the6959 // This inserts all the statically-known values into the intern pool in the
6892 // order expected.6960 // order expected.
6893 for (&static_keys, 0..) |key, key_index| switch (@as(Index, @enumFromInt(key_index))) {6961 for (&static_keys, 0..) |key, key_index| switch (@as(Index, @enumFromInt(key_index))) {
6894 .empty_tuple_type => assert(try ip.getTupleType(gpa, .main, .{6962 .empty_tuple_type => assert(try ip.getTupleType(gpa, io, .main, .{
6895 .types = &.{},6963 .types = &.{},
6896 .values = &.{},6964 .values = &.{},
6897 }) == .empty_tuple_type),6965 }) == .empty_tuple_type),
6898 else => |expected_index| assert(try ip.get(gpa, .main, key) == expected_index),6966 else => |expected_index| assert(try ip.get(gpa, io, .main, key) == expected_index),
6899 };6967 };
69006968
6901 if (std.debug.runtime_safety) {6969 if (std.debug.runtime_safety) {
...@@ -6905,7 +6973,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -6905,7 +6973,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
6905 }6973 }
6906}6974}
69076975
6908pub fn deinit(ip: *InternPool, gpa: Allocator) void {6976pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void {
6909 if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null);6977 if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null);
69106978
6911 ip.src_hash_deps.deinit(gpa);6979 ip.src_hash_deps.deinit(gpa);
...@@ -6940,7 +7008,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -6940,7 +7008,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
6940 namespace.test_decls.deinit(gpa);7008 namespace.test_decls.deinit(gpa);
6941 }7009 }
6942 };7010 };
6943 const maps = local.getMutableMaps(gpa);7011 const maps = local.getMutableMaps(gpa, io);
6944 if (maps.mutate.len > 0) for (maps.view().items(.@"0")) |*map| map.deinit(gpa);7012 if (maps.mutate.len > 0) for (maps.view().items(.@"0")) |*map| map.deinit(gpa);
6945 local.mutate.arena.promote(gpa).deinit();7013 local.mutate.arena.promote(gpa).deinit();
6946 }7014 }
...@@ -7645,6 +7713,7 @@ const GetOrPutKey = union(enum) {...@@ -7645,6 +7713,7 @@ const GetOrPutKey = union(enum) {
7645 new: struct {7713 new: struct {
7646 ip: *InternPool,7714 ip: *InternPool,
7647 tid: Zcu.PerThread.Id,7715 tid: Zcu.PerThread.Id,
7716 io: Io,
7648 shard: *Shard,7717 shard: *Shard,
7649 map_index: u32,7718 map_index: u32,
7650 },7719 },
...@@ -7679,7 +7748,7 @@ const GetOrPutKey = union(enum) {...@@ -7679,7 +7748,7 @@ const GetOrPutKey = union(enum) {
7679 .new => |info| {7748 .new => |info| {
7680 assert(info.shard.shared.map.entries[info.map_index].value == index);7749 assert(info.shard.shared.map.entries[info.map_index].value == index);
7681 info.shard.mutate.map.len += 1;7750 info.shard.mutate.map.len += 1;
7682 info.shard.mutate.map.mutex.unlock();7751 info.shard.mutate.map.mutex.unlock(info.io);
7683 gop.* = .{ .existing = index };7752 gop.* = .{ .existing = index };
7684 },7753 },
7685 }7754 }
...@@ -7688,7 +7757,7 @@ const GetOrPutKey = union(enum) {...@@ -7688,7 +7757,7 @@ const GetOrPutKey = union(enum) {
7688 fn cancel(gop: *GetOrPutKey) void {7757 fn cancel(gop: *GetOrPutKey) void {
7689 switch (gop.*) {7758 switch (gop.*) {
7690 .existing => {},7759 .existing => {},
7691 .new => |info| info.shard.mutate.map.mutex.unlock(),7760 .new => |info| info.shard.mutate.map.mutex.unlock(info.io),
7692 }7761 }
7693 gop.* = .{ .existing = undefined };7762 gop.* = .{ .existing = undefined };
7694 }7763 }
...@@ -7705,14 +7774,16 @@ const GetOrPutKey = union(enum) {...@@ -7705,14 +7774,16 @@ const GetOrPutKey = union(enum) {
7705fn getOrPutKey(7774fn getOrPutKey(
7706 ip: *InternPool,7775 ip: *InternPool,
7707 gpa: Allocator,7776 gpa: Allocator,
7777 io: Io,
7708 tid: Zcu.PerThread.Id,7778 tid: Zcu.PerThread.Id,
7709 key: Key,7779 key: Key,
7710) Allocator.Error!GetOrPutKey {7780) Allocator.Error!GetOrPutKey {
7711 return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, key, 0);7781 return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, key, 0);
7712}7782}
7713fn getOrPutKeyEnsuringAdditionalCapacity(7783fn getOrPutKeyEnsuringAdditionalCapacity(
7714 ip: *InternPool,7784 ip: *InternPool,
7715 gpa: Allocator,7785 gpa: Allocator,
7786 io: Io,
7716 tid: Zcu.PerThread.Id,7787 tid: Zcu.PerThread.Id,
7717 key: Key,7788 key: Key,
7718 additional_capacity: u32,7789 additional_capacity: u32,
...@@ -7733,8 +7804,8 @@ fn getOrPutKeyEnsuringAdditionalCapacity(...@@ -7733,8 +7804,8 @@ fn getOrPutKeyEnsuringAdditionalCapacity(
7733 if (index.unwrap(ip).getTag(ip) == .removed) continue;7804 if (index.unwrap(ip).getTag(ip) == .removed) continue;
7734 if (ip.indexToKey(index).eql(key, ip)) return .{ .existing = index };7805 if (ip.indexToKey(index).eql(key, ip)) return .{ .existing = index };
7735 }7806 }
7736 shard.mutate.map.mutex.lock();7807 shard.mutate.map.mutex.lock(io, tid);
7737 errdefer shard.mutate.map.mutex.unlock();7808 errdefer shard.mutate.map.mutex.unlock(io);
7738 if (map.entries != shard.shared.map.entries) {7809 if (map.entries != shard.shared.map.entries) {
7739 map = shard.shared.map;7810 map = shard.shared.map;
7740 map_mask = map.header().mask();7811 map_mask = map.header().mask();
...@@ -7747,7 +7818,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity(...@@ -7747,7 +7818,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity(
7747 if (index == .none) break;7818 if (index == .none) break;
7748 if (entry.hash != hash) continue;7819 if (entry.hash != hash) continue;
7749 if (ip.indexToKey(index).eql(key, ip)) {7820 if (ip.indexToKey(index).eql(key, ip)) {
7750 defer shard.mutate.map.mutex.unlock();7821 defer shard.mutate.map.mutex.unlock(io);
7751 return .{ .existing = index };7822 return .{ .existing = index };
7752 }7823 }
7753 }7824 }
...@@ -7801,6 +7872,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity(...@@ -7801,6 +7872,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity(
7801 return .{ .new = .{7872 return .{ .new = .{
7802 .ip = ip,7873 .ip = ip,
7803 .tid = tid,7874 .tid = tid,
7875 .io = io,
7804 .shard = shard,7876 .shard = shard,
7805 .map_index = map_index,7877 .map_index = map_index,
7806 } };7878 } };
...@@ -7815,14 +7887,15 @@ fn getOrPutKeyEnsuringAdditionalCapacity(...@@ -7815,14 +7887,15 @@ fn getOrPutKeyEnsuringAdditionalCapacity(
7815/// will be cleaned up when the `Zcu` undergoes garbage collection.7887/// will be cleaned up when the `Zcu` undergoes garbage collection.
7816fn putKeyReplace(7888fn putKeyReplace(
7817 ip: *InternPool,7889 ip: *InternPool,
7890 io: Io,
7818 tid: Zcu.PerThread.Id,7891 tid: Zcu.PerThread.Id,
7819 key: Key,7892 key: Key,
7820) GetOrPutKey {7893) GetOrPutKey {
7821 const full_hash = key.hash64(ip);7894 const full_hash = key.hash64(ip);
7822 const hash: u32 = @truncate(full_hash >> 32);7895 const hash: u32 = @truncate(full_hash >> 32);
7823 const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))];7896 const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))];
7824 shard.mutate.map.mutex.lock();7897 shard.mutate.map.mutex.lock(io, tid);
7825 errdefer shard.mutate.map.mutex.unlock();7898 errdefer shard.mutate.map.mutex.unlock(io);
7826 const map = shard.shared.map;7899 const map = shard.shared.map;
7827 const map_mask = map.header().mask();7900 const map_mask = map.header().mask();
7828 var map_index = hash;7901 var map_index = hash;
...@@ -7838,18 +7911,19 @@ fn putKeyReplace(...@@ -7838,18 +7911,19 @@ fn putKeyReplace(
7838 return .{ .new = .{7911 return .{ .new = .{
7839 .ip = ip,7912 .ip = ip,
7840 .tid = tid,7913 .tid = tid,
7914 .io = io,
7841 .shard = shard,7915 .shard = shard,
7842 .map_index = map_index,7916 .map_index = map_index,
7843 } };7917 } };
7844}7918}
78457919
7846pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index {7920pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index {
7847 var gop = try ip.getOrPutKey(gpa, tid, key);7921 var gop = try ip.getOrPutKey(gpa, io, tid, key);
7848 defer gop.deinit();7922 defer gop.deinit();
7849 if (gop == .existing) return gop.existing;7923 if (gop == .existing) return gop.existing;
7850 const local = ip.getLocal(tid);7924 const local = ip.getLocal(tid);
7851 const items = local.getMutableItems(gpa);7925 const items = local.getMutableItems(gpa, io);
7852 const extra = local.getMutableExtra(gpa);7926 const extra = local.getMutableExtra(gpa, io);
7853 try items.ensureUnusedCapacity(1);7927 try items.ensureUnusedCapacity(1);
7854 switch (key) {7928 switch (key) {
7855 .int_type => |int_type| {7929 .int_type => |int_type| {
...@@ -7870,8 +7944,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7870,8 +7944,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7870 gop.cancel();7944 gop.cancel();
7871 var new_key = key;7945 var new_key = key;
7872 new_key.ptr_type.flags.size = .many;7946 new_key.ptr_type.flags.size = .many;
7873 const ptr_type_index = try ip.get(gpa, tid, new_key);7947 const ptr_type_index = try ip.get(gpa, io, tid, new_key);
7874 gop = try ip.getOrPutKey(gpa, tid, key);7948 gop = try ip.getOrPutKey(gpa, io, tid, key);
78757949
7876 try items.ensureUnusedCapacity(1);7950 try items.ensureUnusedCapacity(1);
7877 items.appendAssumeCapacity(.{7951 items.appendAssumeCapacity(.{
...@@ -7953,7 +8027,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7953,7 +8027,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7953 assert(error_set_type.names_map == .none);8027 assert(error_set_type.names_map == .none);
7954 assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan));8028 assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan));
7955 const names = error_set_type.names.get(ip);8029 const names = error_set_type.names.get(ip);
7956 const names_map = try ip.addMap(gpa, tid, names.len);8030 const names_map = try ip.addMap(gpa, io, tid, names.len);
7957 ip.addStringsToMap(names_map, names);8031 ip.addStringsToMap(names_map, names);
7958 const names_len = error_set_type.names.len;8032 const names_len = error_set_type.names.len;
7959 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).@"struct".fields.len + names_len);8033 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).@"struct".fields.len + names_len);
...@@ -8051,7 +8125,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -8051,7 +8125,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
8051 gop.cancel();8125 gop.cancel();
8052 var new_key = key;8126 var new_key = key;
8053 new_key.ptr.base_addr.uav.orig_ty = ptr.ty;8127 new_key.ptr.base_addr.uav.orig_ty = ptr.ty;
8054 gop = try ip.getOrPutKey(gpa, tid, new_key);8128 gop = try ip.getOrPutKey(gpa, io, tid, new_key);
8055 if (gop == .existing) return gop.existing;8129 if (gop == .existing) return gop.existing;
8056 }8130 }
8057 break :item .{8131 break :item .{
...@@ -8123,11 +8197,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -8123,11 +8197,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
8123 else => unreachable,8197 else => unreachable,
8124 }8198 }
8125 gop.cancel();8199 gop.cancel();
8126 const index_index = try ip.get(gpa, tid, .{ .int = .{8200 const index_index = try ip.get(gpa, io, tid, .{ .int = .{
8127 .ty = .usize_type,8201 .ty = .usize_type,
8128 .storage = .{ .u64 = base_index.index },8202 .storage = .{ .u64 = base_index.index },
8129 } });8203 } });
8130 gop = try ip.getOrPutKey(gpa, tid, key);8204 gop = try ip.getOrPutKey(gpa, io, tid, key);
8131 try items.ensureUnusedCapacity(1);8205 try items.ensureUnusedCapacity(1);
8132 items.appendAssumeCapacity(.{8206 items.appendAssumeCapacity(.{
8133 .tag = switch (ptr.base_addr) {8207 .tag = switch (ptr.base_addr) {
...@@ -8318,7 +8392,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -8318,7 +8392,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
8318 } else |_| {}8392 } else |_| {}
83198393
8320 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;8394 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
8321 try addInt(ip, gpa, tid, int.ty, tag, big_int.limbs);8395 try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs);
8322 },8396 },
8323 inline .u64, .i64 => |x| {8397 inline .u64, .i64 => |x| {
8324 if (std.math.cast(u32, x)) |casted| {8398 if (std.math.cast(u32, x)) |casted| {
...@@ -8335,7 +8409,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -8335,7 +8409,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
8335 var buf: [2]Limb = undefined;8409 var buf: [2]Limb = undefined;
8336 const big_int = BigIntMutable.init(&buf, x).toConst();8410 const big_int = BigIntMutable.init(&buf, x).toConst();
8337 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;8411 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
8338 try addInt(ip, gpa, tid, int.ty, tag, big_int.limbs);8412 try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs);
8339 },8413 },
8340 .lazy_align, .lazy_size => unreachable,8414 .lazy_align, .lazy_size => unreachable,
8341 }8415 }
...@@ -8546,11 +8620,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -8546,11 +8620,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
8546 const elem = switch (aggregate.storage) {8620 const elem = switch (aggregate.storage) {
8547 .bytes => |bytes| elem: {8621 .bytes => |bytes| elem: {
8548 gop.cancel();8622 gop.cancel();
8549 const elem = try ip.get(gpa, tid, .{ .int = .{8623 const elem = try ip.get(gpa, io, tid, .{ .int = .{
8550 .ty = .u8_type,8624 .ty = .u8_type,
8551 .storage = .{ .u64 = bytes.at(0, ip) },8625 .storage = .{ .u64 = bytes.at(0, ip) },
8552 } });8626 } });
8553 gop = try ip.getOrPutKey(gpa, tid, key);8627 gop = try ip.getOrPutKey(gpa, io, tid, key);
8554 try items.ensureUnusedCapacity(1);8628 try items.ensureUnusedCapacity(1);
8555 break :elem elem;8629 break :elem elem;
8556 },8630 },
...@@ -8570,7 +8644,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -8570,7 +8644,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
8570 }8644 }
85718645
8572 if (child == .u8_type) bytes: {8646 if (child == .u8_type) bytes: {
8573 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa);8647 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io);
8574 const start = string_bytes.mutate.len;8648 const start = string_bytes.mutate.len;
8575 try string_bytes.ensureUnusedCapacity(@intCast(len_including_sentinel + 1));8649 try string_bytes.ensureUnusedCapacity(@intCast(len_including_sentinel + 1));
8576 try extra.ensureUnusedCapacity(@typeInfo(Bytes).@"struct".fields.len);8650 try extra.ensureUnusedCapacity(@typeInfo(Bytes).@"struct".fields.len);
...@@ -8598,6 +8672,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -8598,6 +8672,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
8598 });8672 });
8599 const string = try ip.getOrPutTrailingString(8673 const string = try ip.getOrPutTrailingString(
8600 gpa,8674 gpa,
8675 io,
8601 tid,8676 tid,
8602 @intCast(len_including_sentinel),8677 @intCast(len_including_sentinel),
8603 .maybe_embedded_nulls,8678 .maybe_embedded_nulls,
...@@ -8647,15 +8722,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -8647,15 +8722,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
8647pub fn getUnion(8722pub fn getUnion(
8648 ip: *InternPool,8723 ip: *InternPool,
8649 gpa: Allocator,8724 gpa: Allocator,
8725 io: Io,
8650 tid: Zcu.PerThread.Id,8726 tid: Zcu.PerThread.Id,
8651 un: Key.Union,8727 un: Key.Union,
8652) Allocator.Error!Index {8728) Allocator.Error!Index {
8653 var gop = try ip.getOrPutKey(gpa, tid, .{ .un = un });8729 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un });
8654 defer gop.deinit();8730 defer gop.deinit();
8655 if (gop == .existing) return gop.existing;8731 if (gop == .existing) return gop.existing;
8656 const local = ip.getLocal(tid);8732 const local = ip.getLocal(tid);
8657 const items = local.getMutableItems(gpa);8733 const items = local.getMutableItems(gpa, io);
8658 const extra = local.getMutableExtra(gpa);8734 const extra = local.getMutableExtra(gpa, io);
8659 try items.ensureUnusedCapacity(1);8735 try items.ensureUnusedCapacity(1);
86608736
8661 assert(un.ty != .none);8737 assert(un.ty != .none);
...@@ -8706,6 +8782,7 @@ pub const UnionTypeInit = struct {...@@ -8706,6 +8782,7 @@ pub const UnionTypeInit = struct {
8706pub fn getUnionType(8782pub fn getUnionType(
8707 ip: *InternPool,8783 ip: *InternPool,
8708 gpa: Allocator,8784 gpa: Allocator,
8785 io: Io,
8709 tid: Zcu.PerThread.Id,8786 tid: Zcu.PerThread.Id,
8710 ini: UnionTypeInit,8787 ini: UnionTypeInit,
8711 /// If it is known that there is an existing type with this key which is outdated,8788 /// If it is known that there is an existing type with this key which is outdated,
...@@ -8727,16 +8804,16 @@ pub fn getUnionType(...@@ -8727,16 +8804,16 @@ pub fn getUnionType(
8727 } },8804 } },
8728 } };8805 } };
8729 var gop = if (replace_existing)8806 var gop = if (replace_existing)
8730 ip.putKeyReplace(tid, key)8807 ip.putKeyReplace(io, tid, key)
8731 else8808 else
8732 try ip.getOrPutKey(gpa, tid, key);8809 try ip.getOrPutKey(gpa, io, tid, key);
8733 defer gop.deinit();8810 defer gop.deinit();
8734 if (gop == .existing) return .{ .existing = gop.existing };8811 if (gop == .existing) return .{ .existing = gop.existing };
87358812
8736 const local = ip.getLocal(tid);8813 const local = ip.getLocal(tid);
8737 const items = local.getMutableItems(gpa);8814 const items = local.getMutableItems(gpa, io);
8738 try items.ensureUnusedCapacity(1);8815 try items.ensureUnusedCapacity(1);
8739 const extra = local.getMutableExtra(gpa);8816 const extra = local.getMutableExtra(gpa, io);
87408817
8741 const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0;8818 const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0;
8742 const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4);8819 const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4);
...@@ -8903,6 +8980,7 @@ pub const StructTypeInit = struct {...@@ -8903,6 +8980,7 @@ pub const StructTypeInit = struct {
8903pub fn getStructType(8980pub fn getStructType(
8904 ip: *InternPool,8981 ip: *InternPool,
8905 gpa: Allocator,8982 gpa: Allocator,
8983 io: Io,
8906 tid: Zcu.PerThread.Id,8984 tid: Zcu.PerThread.Id,
8907 ini: StructTypeInit,8985 ini: StructTypeInit,
8908 /// If it is known that there is an existing type with this key which is outdated,8986 /// If it is known that there is an existing type with this key which is outdated,
...@@ -8924,17 +9002,17 @@ pub fn getStructType(...@@ -8924,17 +9002,17 @@ pub fn getStructType(
8924 } },9002 } },
8925 } };9003 } };
8926 var gop = if (replace_existing)9004 var gop = if (replace_existing)
8927 ip.putKeyReplace(tid, key)9005 ip.putKeyReplace(io, tid, key)
8928 else9006 else
8929 try ip.getOrPutKey(gpa, tid, key);9007 try ip.getOrPutKey(gpa, io, tid, key);
8930 defer gop.deinit();9008 defer gop.deinit();
8931 if (gop == .existing) return .{ .existing = gop.existing };9009 if (gop == .existing) return .{ .existing = gop.existing };
89329010
8933 const local = ip.getLocal(tid);9011 const local = ip.getLocal(tid);
8934 const items = local.getMutableItems(gpa);9012 const items = local.getMutableItems(gpa, io);
8935 const extra = local.getMutableExtra(gpa);9013 const extra = local.getMutableExtra(gpa, io);
89369014
8937 const names_map = try ip.addMap(gpa, tid, ini.fields_len);9015 const names_map = try ip.addMap(gpa, io, tid, ini.fields_len);
8938 errdefer local.mutate.maps.len -= 1;9016 errdefer local.mutate.maps.len -= 1;
89399017
8940 const zir_index = switch (ini.key) {9018 const zir_index = switch (ini.key) {
...@@ -9109,6 +9187,7 @@ pub const TupleTypeInit = struct {...@@ -9109,6 +9187,7 @@ pub const TupleTypeInit = struct {
9109pub fn getTupleType(9187pub fn getTupleType(
9110 ip: *InternPool,9188 ip: *InternPool,
9111 gpa: Allocator,9189 gpa: Allocator,
9190 io: Io,
9112 tid: Zcu.PerThread.Id,9191 tid: Zcu.PerThread.Id,
9113 ini: TupleTypeInit,9192 ini: TupleTypeInit,
9114) Allocator.Error!Index {9193) Allocator.Error!Index {
...@@ -9116,8 +9195,8 @@ pub fn getTupleType(...@@ -9116,8 +9195,8 @@ pub fn getTupleType(
9116 for (ini.types) |elem| assert(elem != .none);9195 for (ini.types) |elem| assert(elem != .none);
91179196
9118 const local = ip.getLocal(tid);9197 const local = ip.getLocal(tid);
9119 const items = local.getMutableItems(gpa);9198 const items = local.getMutableItems(gpa, io);
9120 const extra = local.getMutableExtra(gpa);9199 const extra = local.getMutableExtra(gpa, io);
91219200
9122 const prev_extra_len = extra.mutate.len;9201 const prev_extra_len = extra.mutate.len;
9123 const fields_len: u32 = @intCast(ini.types.len);9202 const fields_len: u32 = @intCast(ini.types.len);
...@@ -9134,7 +9213,7 @@ pub fn getTupleType(...@@ -9134,7 +9213,7 @@ pub fn getTupleType(
9134 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)});9213 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)});
9135 errdefer extra.mutate.len = prev_extra_len;9214 errdefer extra.mutate.len = prev_extra_len;
91369215
9137 var gop = try ip.getOrPutKey(gpa, tid, .{ .tuple_type = extraTypeTuple(tid, extra.list.*, extra_index) });9216 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .tuple_type = extraTypeTuple(tid, extra.list.*, extra_index) });
9138 defer gop.deinit();9217 defer gop.deinit();
9139 if (gop == .existing) {9218 if (gop == .existing) {
9140 extra.mutate.len = prev_extra_len;9219 extra.mutate.len = prev_extra_len;
...@@ -9166,6 +9245,7 @@ pub const GetFuncTypeKey = struct {...@@ -9166,6 +9245,7 @@ pub const GetFuncTypeKey = struct {
9166pub fn getFuncType(9245pub fn getFuncType(
9167 ip: *InternPool,9246 ip: *InternPool,
9168 gpa: Allocator,9247 gpa: Allocator,
9248 io: Io,
9169 tid: Zcu.PerThread.Id,9249 tid: Zcu.PerThread.Id,
9170 key: GetFuncTypeKey,9250 key: GetFuncTypeKey,
9171) Allocator.Error!Index {9251) Allocator.Error!Index {
...@@ -9174,9 +9254,9 @@ pub fn getFuncType(...@@ -9174,9 +9254,9 @@ pub fn getFuncType(
9174 for (key.param_types) |param_type| assert(param_type != .none);9254 for (key.param_types) |param_type| assert(param_type != .none);
91759255
9176 const local = ip.getLocal(tid);9256 const local = ip.getLocal(tid);
9177 const items = local.getMutableItems(gpa);9257 const items = local.getMutableItems(gpa, io);
9178 try items.ensureUnusedCapacity(1);9258 try items.ensureUnusedCapacity(1);
9179 const extra = local.getMutableExtra(gpa);9259 const extra = local.getMutableExtra(gpa, io);
91809260
9181 // The strategy here is to add the function type unconditionally, then to9261 // The strategy here is to add the function type unconditionally, then to
9182 // ask if it already exists, and if so, revert the lengths of the mutated9262 // ask if it already exists, and if so, revert the lengths of the mutated
...@@ -9207,7 +9287,7 @@ pub fn getFuncType(...@@ -9207,7 +9287,7 @@ pub fn getFuncType(
9207 extra.appendSliceAssumeCapacity(.{@ptrCast(key.param_types)});9287 extra.appendSliceAssumeCapacity(.{@ptrCast(key.param_types)});
9208 errdefer extra.mutate.len = prev_extra_len;9288 errdefer extra.mutate.len = prev_extra_len;
92099289
9210 var gop = try ip.getOrPutKey(gpa, tid, .{9290 var gop = try ip.getOrPutKey(gpa, io, tid, .{
9211 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),9291 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),
9212 });9292 });
9213 defer gop.deinit();9293 defer gop.deinit();
...@@ -9228,6 +9308,7 @@ pub fn getFuncType(...@@ -9228,6 +9308,7 @@ pub fn getFuncType(
9228pub fn getExtern(9308pub fn getExtern(
9229 ip: *InternPool,9309 ip: *InternPool,
9230 gpa: Allocator,9310 gpa: Allocator,
9311 io: Io,
9231 tid: Zcu.PerThread.Id,9312 tid: Zcu.PerThread.Id,
9232 /// `key.owner_nav` is ignored.9313 /// `key.owner_nav` is ignored.
9233 key: Key.Extern,9314 key: Key.Extern,
...@@ -9236,7 +9317,7 @@ pub fn getExtern(...@@ -9236,7 +9317,7 @@ pub fn getExtern(
9236 /// Only set if the `Nav` was newly created.9317 /// Only set if the `Nav` was newly created.
9237 new_nav: Nav.Index.Optional,9318 new_nav: Nav.Index.Optional,
9238} {9319} {
9239 var gop = try ip.getOrPutKey(gpa, tid, .{ .@"extern" = key });9320 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .@"extern" = key });
9240 defer gop.deinit();9321 defer gop.deinit();
9241 if (gop == .existing) return .{9322 if (gop == .existing) return .{
9242 .index = gop.existing,9323 .index = gop.existing,
...@@ -9244,18 +9325,18 @@ pub fn getExtern(...@@ -9244,18 +9325,18 @@ pub fn getExtern(
9244 };9325 };
92459326
9246 const local = ip.getLocal(tid);9327 const local = ip.getLocal(tid);
9247 const items = local.getMutableItems(gpa);9328 const items = local.getMutableItems(gpa, io);
9248 const extra = local.getMutableExtra(gpa);9329 const extra = local.getMutableExtra(gpa, io);
9249 try items.ensureUnusedCapacity(1);9330 try items.ensureUnusedCapacity(1);
9250 try extra.ensureUnusedCapacity(@typeInfo(Tag.Extern).@"struct".fields.len);9331 try extra.ensureUnusedCapacity(@typeInfo(Tag.Extern).@"struct".fields.len);
9251 try local.getMutableNavs(gpa).ensureUnusedCapacity(1);9332 try local.getMutableNavs(gpa, io).ensureUnusedCapacity(1);
92529333
9253 // Predict the index the `@"extern" will live at, so we can construct the owner `Nav` before releasing the shard's mutex.9334 // Predict the index the `@"extern" will live at, so we can construct the owner `Nav` before releasing the shard's mutex.
9254 const extern_index = Index.Unwrapped.wrap(.{9335 const extern_index = Index.Unwrapped.wrap(.{
9255 .tid = tid,9336 .tid = tid,
9256 .index = items.mutate.len,9337 .index = items.mutate.len,
9257 }, ip);9338 }, ip);
9258 const owner_nav = ip.createNav(gpa, tid, .{9339 const owner_nav = ip.createNav(gpa, io, tid, .{
9259 .name = key.name,9340 .name = key.name,
9260 .fqn = key.name,9341 .fqn = key.name,
9261 .val = extern_index,9342 .val = extern_index,
...@@ -9305,13 +9386,14 @@ pub const GetFuncDeclKey = struct {...@@ -9305,13 +9386,14 @@ pub const GetFuncDeclKey = struct {
9305pub fn getFuncDecl(9386pub fn getFuncDecl(
9306 ip: *InternPool,9387 ip: *InternPool,
9307 gpa: Allocator,9388 gpa: Allocator,
9389 io: Io,
9308 tid: Zcu.PerThread.Id,9390 tid: Zcu.PerThread.Id,
9309 key: GetFuncDeclKey,9391 key: GetFuncDeclKey,
9310) Allocator.Error!Index {9392) Allocator.Error!Index {
9311 const local = ip.getLocal(tid);9393 const local = ip.getLocal(tid);
9312 const items = local.getMutableItems(gpa);9394 const items = local.getMutableItems(gpa, io);
9313 try items.ensureUnusedCapacity(1);9395 try items.ensureUnusedCapacity(1);
9314 const extra = local.getMutableExtra(gpa);9396 const extra = local.getMutableExtra(gpa, io);
93159397
9316 // The strategy here is to add the function type unconditionally, then to9398 // The strategy here is to add the function type unconditionally, then to
9317 // ask if it already exists, and if so, revert the lengths of the mutated9399 // ask if it already exists, and if so, revert the lengths of the mutated
...@@ -9340,7 +9422,7 @@ pub fn getFuncDecl(...@@ -9340,7 +9422,7 @@ pub fn getFuncDecl(
9340 });9422 });
9341 errdefer extra.mutate.len = prev_extra_len;9423 errdefer extra.mutate.len = prev_extra_len;
93429424
9343 var gop = try ip.getOrPutKey(gpa, tid, .{9425 var gop = try ip.getOrPutKey(gpa, io, tid, .{
9344 .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index),9426 .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index),
9345 });9427 });
9346 defer gop.deinit();9428 defer gop.deinit();
...@@ -9387,6 +9469,7 @@ pub const GetFuncDeclIesKey = struct {...@@ -9387,6 +9469,7 @@ pub const GetFuncDeclIesKey = struct {
9387pub fn getFuncDeclIes(9469pub fn getFuncDeclIes(
9388 ip: *InternPool,9470 ip: *InternPool,
9389 gpa: Allocator,9471 gpa: Allocator,
9472 io: Io,
9390 tid: Zcu.PerThread.Id,9473 tid: Zcu.PerThread.Id,
9391 key: GetFuncDeclIesKey,9474 key: GetFuncDeclIesKey,
9392) Allocator.Error!Index {9475) Allocator.Error!Index {
...@@ -9395,9 +9478,9 @@ pub fn getFuncDeclIes(...@@ -9395,9 +9478,9 @@ pub fn getFuncDeclIes(
9395 for (key.param_types) |param_type| assert(param_type != .none);9478 for (key.param_types) |param_type| assert(param_type != .none);
93969479
9397 const local = ip.getLocal(tid);9480 const local = ip.getLocal(tid);
9398 const items = local.getMutableItems(gpa);9481 const items = local.getMutableItems(gpa, io);
9399 try items.ensureUnusedCapacity(4);9482 try items.ensureUnusedCapacity(4);
9400 const extra = local.getMutableExtra(gpa);9483 const extra = local.getMutableExtra(gpa, io);
94019484
9402 // The strategy here is to add the function decl unconditionally, then to9485 // The strategy here is to add the function decl unconditionally, then to
9403 // ask if it already exists, and if so, revert the lengths of the mutated9486 // ask if it already exists, and if so, revert the lengths of the mutated
...@@ -9488,7 +9571,7 @@ pub fn getFuncDeclIes(...@@ -9488,7 +9571,7 @@ pub fn getFuncDeclIes(
9488 extra.mutate.len = prev_extra_len;9571 extra.mutate.len = prev_extra_len;
9489 }9572 }
94909573
9491 var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{9574 var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{
9492 .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index),9575 .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index),
9493 }, 3);9576 }, 3);
9494 defer func_gop.deinit();9577 defer func_gop.deinit();
...@@ -9509,18 +9592,18 @@ pub fn getFuncDeclIes(...@@ -9509,18 +9592,18 @@ pub fn getFuncDeclIes(
9509 return func_gop.existing;9592 return func_gop.existing;
9510 }9593 }
9511 func_gop.putTentative(func_index);9594 func_gop.putTentative(func_index);
9512 var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ .error_union_type = .{9595 var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .error_union_type = .{
9513 .error_set_type = error_set_type,9596 .error_set_type = error_set_type,
9514 .payload_type = key.bare_return_type,9597 .payload_type = key.bare_return_type,
9515 } }, 2);9598 } }, 2);
9516 defer error_union_type_gop.deinit();9599 defer error_union_type_gop.deinit();
9517 error_union_type_gop.putTentative(error_union_type);9600 error_union_type_gop.putTentative(error_union_type);
9518 var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{9601 var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{
9519 .inferred_error_set_type = func_index,9602 .inferred_error_set_type = func_index,
9520 }, 1);9603 }, 1);
9521 defer error_set_type_gop.deinit();9604 defer error_set_type_gop.deinit();
9522 error_set_type_gop.putTentative(error_set_type);9605 error_set_type_gop.putTentative(error_set_type);
9523 var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{9606 var func_ty_gop = try ip.getOrPutKey(gpa, io, tid, .{
9524 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),9607 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),
9525 });9608 });
9526 defer func_ty_gop.deinit();9609 defer func_ty_gop.deinit();
...@@ -9536,17 +9619,18 @@ pub fn getFuncDeclIes(...@@ -9536,17 +9619,18 @@ pub fn getFuncDeclIes(
9536pub fn getErrorSetType(9619pub fn getErrorSetType(
9537 ip: *InternPool,9620 ip: *InternPool,
9538 gpa: Allocator,9621 gpa: Allocator,
9622 io: Io,
9539 tid: Zcu.PerThread.Id,9623 tid: Zcu.PerThread.Id,
9540 names: []const NullTerminatedString,9624 names: []const NullTerminatedString,
9541) Allocator.Error!Index {9625) Allocator.Error!Index {
9542 assert(std.sort.isSorted(NullTerminatedString, names, {}, NullTerminatedString.indexLessThan));9626 assert(std.sort.isSorted(NullTerminatedString, names, {}, NullTerminatedString.indexLessThan));
95439627
9544 const local = ip.getLocal(tid);9628 const local = ip.getLocal(tid);
9545 const items = local.getMutableItems(gpa);9629 const items = local.getMutableItems(gpa, io);
9546 const extra = local.getMutableExtra(gpa);9630 const extra = local.getMutableExtra(gpa, io);
9547 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).@"struct".fields.len + names.len);9631 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).@"struct".fields.len + names.len);
95489632
9549 const names_map = try ip.addMap(gpa, tid, names.len);9633 const names_map = try ip.addMap(gpa, io, tid, names.len);
9550 errdefer local.mutate.maps.len -= 1;9634 errdefer local.mutate.maps.len -= 1;
95519635
9552 // The strategy here is to add the type unconditionally, then to ask if it9636 // The strategy here is to add the type unconditionally, then to ask if it
...@@ -9562,7 +9646,7 @@ pub fn getErrorSetType(...@@ -9562,7 +9646,7 @@ pub fn getErrorSetType(
9562 extra.appendSliceAssumeCapacity(.{@ptrCast(names)});9646 extra.appendSliceAssumeCapacity(.{@ptrCast(names)});
9563 errdefer extra.mutate.len = prev_extra_len;9647 errdefer extra.mutate.len = prev_extra_len;
95649648
9565 var gop = try ip.getOrPutKey(gpa, tid, .{9649 var gop = try ip.getOrPutKey(gpa, io, tid, .{
9566 .error_set_type = extraErrorSet(tid, extra.list.*, error_set_extra_index),9650 .error_set_type = extraErrorSet(tid, extra.list.*, error_set_extra_index),
9567 });9651 });
9568 defer gop.deinit();9652 defer gop.deinit();
...@@ -9599,16 +9683,17 @@ pub const GetFuncInstanceKey = struct {...@@ -9599,16 +9683,17 @@ pub const GetFuncInstanceKey = struct {
9599pub fn getFuncInstance(9683pub fn getFuncInstance(
9600 ip: *InternPool,9684 ip: *InternPool,
9601 gpa: Allocator,9685 gpa: Allocator,
9686 io: Io,
9602 tid: Zcu.PerThread.Id,9687 tid: Zcu.PerThread.Id,
9603 arg: GetFuncInstanceKey,9688 arg: GetFuncInstanceKey,
9604) Allocator.Error!Index {9689) Allocator.Error!Index {
9605 if (arg.inferred_error_set)9690 if (arg.inferred_error_set)
9606 return getFuncInstanceIes(ip, gpa, tid, arg);9691 return getFuncInstanceIes(ip, gpa, io, tid, arg);
96079692
9608 const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);9693 const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);
9609 const generic_owner_ty = ip.indexToKey(ip.funcDeclInfo(generic_owner).ty).func_type;9694 const generic_owner_ty = ip.indexToKey(ip.funcDeclInfo(generic_owner).ty).func_type;
96109695
9611 const func_ty = try ip.getFuncType(gpa, tid, .{9696 const func_ty = try ip.getFuncType(gpa, io, tid, .{
9612 .param_types = arg.param_types,9697 .param_types = arg.param_types,
9613 .return_type = arg.bare_return_type,9698 .return_type = arg.bare_return_type,
9614 .noalias_bits = arg.noalias_bits,9699 .noalias_bits = arg.noalias_bits,
...@@ -9617,8 +9702,8 @@ pub fn getFuncInstance(...@@ -9617,8 +9702,8 @@ pub fn getFuncInstance(
9617 });9702 });
96189703
9619 const local = ip.getLocal(tid);9704 const local = ip.getLocal(tid);
9620 const items = local.getMutableItems(gpa);9705 const items = local.getMutableItems(gpa, io);
9621 const extra = local.getMutableExtra(gpa);9706 const extra = local.getMutableExtra(gpa, io);
9622 try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncInstance).@"struct".fields.len +9707 try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncInstance).@"struct".fields.len +
9623 arg.comptime_args.len);9708 arg.comptime_args.len);
96249709
...@@ -9646,7 +9731,7 @@ pub fn getFuncInstance(...@@ -9646,7 +9731,7 @@ pub fn getFuncInstance(
9646 });9731 });
9647 extra.appendSliceAssumeCapacity(.{@ptrCast(arg.comptime_args)});9732 extra.appendSliceAssumeCapacity(.{@ptrCast(arg.comptime_args)});
96489733
9649 var gop = try ip.getOrPutKey(gpa, tid, .{9734 var gop = try ip.getOrPutKey(gpa, io, tid, .{
9650 .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index),9735 .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index),
9651 });9736 });
9652 defer gop.deinit();9737 defer gop.deinit();
...@@ -9664,6 +9749,7 @@ pub fn getFuncInstance(...@@ -9664,6 +9749,7 @@ pub fn getFuncInstance(
9664 try finishFuncInstance(9749 try finishFuncInstance(
9665 ip,9750 ip,
9666 gpa,9751 gpa,
9752 io,
9667 tid,9753 tid,
9668 extra,9754 extra,
9669 generic_owner,9755 generic_owner,
...@@ -9676,9 +9762,10 @@ pub fn getFuncInstance(...@@ -9676,9 +9762,10 @@ pub fn getFuncInstance(
9676/// This function exists separately than `getFuncInstance` because it needs to9762/// This function exists separately than `getFuncInstance` because it needs to
9677/// create 4 new items in the InternPool atomically before it can look for an9763/// create 4 new items in the InternPool atomically before it can look for an
9678/// existing item in the map.9764/// existing item in the map.
9679pub fn getFuncInstanceIes(9765fn getFuncInstanceIes(
9680 ip: *InternPool,9766 ip: *InternPool,
9681 gpa: Allocator,9767 gpa: Allocator,
9768 io: Io,
9682 tid: Zcu.PerThread.Id,9769 tid: Zcu.PerThread.Id,
9683 arg: GetFuncInstanceKey,9770 arg: GetFuncInstanceKey,
9684) Allocator.Error!Index {9771) Allocator.Error!Index {
...@@ -9688,8 +9775,8 @@ pub fn getFuncInstanceIes(...@@ -9688,8 +9775,8 @@ pub fn getFuncInstanceIes(
9688 for (arg.param_types) |param_type| assert(param_type != .none);9775 for (arg.param_types) |param_type| assert(param_type != .none);
96899776
9690 const local = ip.getLocal(tid);9777 const local = ip.getLocal(tid);
9691 const items = local.getMutableItems(gpa);9778 const items = local.getMutableItems(gpa, io);
9692 const extra = local.getMutableExtra(gpa);9779 const extra = local.getMutableExtra(gpa, io);
9693 try items.ensureUnusedCapacity(4);9780 try items.ensureUnusedCapacity(4);
96949781
9695 const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);9782 const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);
...@@ -9784,7 +9871,7 @@ pub fn getFuncInstanceIes(...@@ -9784,7 +9871,7 @@ pub fn getFuncInstanceIes(
9784 extra.mutate.len = prev_extra_len;9871 extra.mutate.len = prev_extra_len;
9785 }9872 }
97869873
9787 var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{9874 var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{
9788 .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index),9875 .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index),
9789 }, 3);9876 }, 3);
9790 defer func_gop.deinit();9877 defer func_gop.deinit();
...@@ -9795,18 +9882,18 @@ pub fn getFuncInstanceIes(...@@ -9795,18 +9882,18 @@ pub fn getFuncInstanceIes(
9795 return func_gop.existing;9882 return func_gop.existing;
9796 }9883 }
9797 func_gop.putTentative(func_index);9884 func_gop.putTentative(func_index);
9798 var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ .error_union_type = .{9885 var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .error_union_type = .{
9799 .error_set_type = error_set_type,9886 .error_set_type = error_set_type,
9800 .payload_type = arg.bare_return_type,9887 .payload_type = arg.bare_return_type,
9801 } }, 2);9888 } }, 2);
9802 defer error_union_type_gop.deinit();9889 defer error_union_type_gop.deinit();
9803 error_union_type_gop.putTentative(error_union_type);9890 error_union_type_gop.putTentative(error_union_type);
9804 var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{9891 var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{
9805 .inferred_error_set_type = func_index,9892 .inferred_error_set_type = func_index,
9806 }, 1);9893 }, 1);
9807 defer error_set_type_gop.deinit();9894 defer error_set_type_gop.deinit();
9808 error_set_type_gop.putTentative(error_set_type);9895 error_set_type_gop.putTentative(error_set_type);
9809 var func_ty_gop = try ip.getOrPutKey(gpa, tid, .{9896 var func_ty_gop = try ip.getOrPutKey(gpa, io, tid, .{
9810 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),9897 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),
9811 });9898 });
9812 defer func_ty_gop.deinit();9899 defer func_ty_gop.deinit();
...@@ -9814,6 +9901,7 @@ pub fn getFuncInstanceIes(...@@ -9814,6 +9901,7 @@ pub fn getFuncInstanceIes(
9814 try finishFuncInstance(9901 try finishFuncInstance(
9815 ip,9902 ip,
9816 gpa,9903 gpa,
9904 io,
9817 tid,9905 tid,
9818 extra,9906 extra,
9819 generic_owner,9907 generic_owner,
...@@ -9831,6 +9919,7 @@ pub fn getFuncInstanceIes(...@@ -9831,6 +9919,7 @@ pub fn getFuncInstanceIes(
9831fn finishFuncInstance(9919fn finishFuncInstance(
9832 ip: *InternPool,9920 ip: *InternPool,
9833 gpa: Allocator,9921 gpa: Allocator,
9922 io: Io,
9834 tid: Zcu.PerThread.Id,9923 tid: Zcu.PerThread.Id,
9835 extra: Local.Extra.Mutable,9924 extra: Local.Extra.Mutable,
9836 generic_owner: Index,9925 generic_owner: Index,
...@@ -9841,12 +9930,12 @@ fn finishFuncInstance(...@@ -9841,12 +9930,12 @@ fn finishFuncInstance(
9841 const fn_namespace = fn_owner_nav.analysis.?.namespace;9930 const fn_namespace = fn_owner_nav.analysis.?.namespace;
98429931
9843 // TODO: improve this name9932 // TODO: improve this name
9844 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{f}__anon_{d}", .{9933 const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{
9845 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),9934 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),
9846 }, .no_embedded_nulls);9935 }, .no_embedded_nulls);
9847 const nav_index = try ip.createNav(gpa, tid, .{9936 const nav_index = try ip.createNav(gpa, io, tid, .{
9848 .name = nav_name,9937 .name = nav_name,
9849 .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name),9938 .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name),
9850 .val = func_index,9939 .val = func_index,
9851 .is_const = fn_owner_nav.status.fully_resolved.is_const,9940 .is_const = fn_owner_nav.status.fully_resolved.is_const,
9852 .alignment = fn_owner_nav.status.fully_resolved.alignment,9941 .alignment = fn_owner_nav.status.fully_resolved.alignment,
...@@ -9967,6 +10056,7 @@ pub const WipEnumType = struct {...@@ -9967,6 +10056,7 @@ pub const WipEnumType = struct {
9967pub fn getEnumType(10056pub fn getEnumType(
9968 ip: *InternPool,10057 ip: *InternPool,
9969 gpa: Allocator,10058 gpa: Allocator,
10059 io: Io,
9970 tid: Zcu.PerThread.Id,10060 tid: Zcu.PerThread.Id,
9971 ini: EnumTypeInit,10061 ini: EnumTypeInit,
9972 /// If it is known that there is an existing type with this key which is outdated,10062 /// If it is known that there is an existing type with this key which is outdated,
...@@ -9988,18 +10078,18 @@ pub fn getEnumType(...@@ -9988,18 +10078,18 @@ pub fn getEnumType(
9988 } },10078 } },
9989 } };10079 } };
9990 var gop = if (replace_existing)10080 var gop = if (replace_existing)
9991 ip.putKeyReplace(tid, key)10081 ip.putKeyReplace(io, tid, key)
9992 else10082 else
9993 try ip.getOrPutKey(gpa, tid, key);10083 try ip.getOrPutKey(gpa, io, tid, key);
9994 defer gop.deinit();10084 defer gop.deinit();
9995 if (gop == .existing) return .{ .existing = gop.existing };10085 if (gop == .existing) return .{ .existing = gop.existing };
999610086
9997 const local = ip.getLocal(tid);10087 const local = ip.getLocal(tid);
9998 const items = local.getMutableItems(gpa);10088 const items = local.getMutableItems(gpa, io);
9999 try items.ensureUnusedCapacity(1);10089 try items.ensureUnusedCapacity(1);
10000 const extra = local.getMutableExtra(gpa);10090 const extra = local.getMutableExtra(gpa, io);
1000110091
10002 const names_map = try ip.addMap(gpa, tid, ini.fields_len);10092 const names_map = try ip.addMap(gpa, io, tid, ini.fields_len);
10003 errdefer local.mutate.maps.len -= 1;10093 errdefer local.mutate.maps.len -= 1;
1000410094
10005 switch (ini.tag_mode) {10095 switch (ini.tag_mode) {
...@@ -10056,7 +10146,7 @@ pub fn getEnumType(...@@ -10056,7 +10146,7 @@ pub fn getEnumType(
10056 },10146 },
10057 .explicit, .nonexhaustive => {10147 .explicit, .nonexhaustive => {
10058 const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: {10148 const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: {
10059 const values_map = try ip.addMap(gpa, tid, ini.fields_len);10149 const values_map = try ip.addMap(gpa, io, tid, ini.fields_len);
10060 break :m values_map.toOptional();10150 break :m values_map.toOptional();
10061 };10151 };
10062 errdefer if (ini.has_values) {10152 errdefer if (ini.has_values) {
...@@ -10141,6 +10231,7 @@ const GeneratedTagEnumTypeInit = struct {...@@ -10141,6 +10231,7 @@ const GeneratedTagEnumTypeInit = struct {
10141pub fn getGeneratedTagEnumType(10231pub fn getGeneratedTagEnumType(
10142 ip: *InternPool,10232 ip: *InternPool,
10143 gpa: Allocator,10233 gpa: Allocator,
10234 io: Io,
10144 tid: Zcu.PerThread.Id,10235 tid: Zcu.PerThread.Id,
10145 ini: GeneratedTagEnumTypeInit,10236 ini: GeneratedTagEnumTypeInit,
10146) Allocator.Error!Index {10237) Allocator.Error!Index {
...@@ -10149,11 +10240,11 @@ pub fn getGeneratedTagEnumType(...@@ -10149,11 +10240,11 @@ pub fn getGeneratedTagEnumType(
10149 for (ini.values) |val| assert(ip.typeOf(val) == ini.tag_ty);10240 for (ini.values) |val| assert(ip.typeOf(val) == ini.tag_ty);
1015010241
10151 const local = ip.getLocal(tid);10242 const local = ip.getLocal(tid);
10152 const items = local.getMutableItems(gpa);10243 const items = local.getMutableItems(gpa, io);
10153 try items.ensureUnusedCapacity(1);10244 try items.ensureUnusedCapacity(1);
10154 const extra = local.getMutableExtra(gpa);10245 const extra = local.getMutableExtra(gpa, io);
1015510246
10156 const names_map = try ip.addMap(gpa, tid, ini.names.len);10247 const names_map = try ip.addMap(gpa, io, tid, ini.names.len);
10157 errdefer local.mutate.maps.len -= 1;10248 errdefer local.mutate.maps.len -= 1;
10158 ip.addStringsToMap(names_map, ini.names);10249 ip.addStringsToMap(names_map, ini.names);
1015910250
...@@ -10165,7 +10256,7 @@ pub fn getGeneratedTagEnumType(...@@ -10165,7 +10256,7 @@ pub fn getGeneratedTagEnumType(
10165 .index = items.mutate.len,10256 .index = items.mutate.len,
10166 }, ip);10257 }, ip);
10167 const parent_namespace = ip.namespacePtr(ini.parent_namespace);10258 const parent_namespace = ip.namespacePtr(ini.parent_namespace);
10168 const namespace = try ip.createNamespace(gpa, tid, .{10259 const namespace = try ip.createNamespace(gpa, io, tid, .{
10169 .parent = ini.parent_namespace.toOptional(),10260 .parent = ini.parent_namespace.toOptional(),
10170 .owner_type = enum_index,10261 .owner_type = enum_index,
10171 .file_scope = parent_namespace.file_scope,10262 .file_scope = parent_namespace.file_scope,
...@@ -10202,7 +10293,7 @@ pub fn getGeneratedTagEnumType(...@@ -10202,7 +10293,7 @@ pub fn getGeneratedTagEnumType(
10202 ini.values.len); // field values10293 ini.values.len); // field values
1020310294
10204 const values_map: OptionalMapIndex = if (ini.values.len != 0) m: {10295 const values_map: OptionalMapIndex = if (ini.values.len != 0) m: {
10205 const map = try ip.addMap(gpa, tid, ini.values.len);10296 const map = try ip.addMap(gpa, io, tid, ini.values.len);
10206 ip.addIndexesToMap(map, ini.values);10297 ip.addIndexesToMap(map, ini.values);
10207 break :m map.toOptional();10298 break :m map.toOptional();
10208 } else .none;10299 } else .none;
...@@ -10240,7 +10331,7 @@ pub fn getGeneratedTagEnumType(...@@ -10240,7 +10331,7 @@ pub fn getGeneratedTagEnumType(
10240 },10331 },
10241 };10332 };
1024210333
10243 var gop = try ip.getOrPutKey(gpa, tid, .{ .enum_type = .{10334 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{
10244 .generated_tag = .{ .union_type = ini.owner_union_ty },10335 .generated_tag = .{ .union_type = ini.owner_union_ty },
10245 } });10336 } });
10246 defer gop.deinit();10337 defer gop.deinit();
...@@ -10256,10 +10347,11 @@ pub const OpaqueTypeInit = struct {...@@ -10256,10 +10347,11 @@ pub const OpaqueTypeInit = struct {
10256pub fn getOpaqueType(10347pub fn getOpaqueType(
10257 ip: *InternPool,10348 ip: *InternPool,
10258 gpa: Allocator,10349 gpa: Allocator,
10350 io: Io,
10259 tid: Zcu.PerThread.Id,10351 tid: Zcu.PerThread.Id,
10260 ini: OpaqueTypeInit,10352 ini: OpaqueTypeInit,
10261) Allocator.Error!WipNamespaceType.Result {10353) Allocator.Error!WipNamespaceType.Result {
10262 var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = .{ .declared = .{10354 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{
10263 .zir_index = ini.zir_index,10355 .zir_index = ini.zir_index,
10264 .captures = .{ .external = ini.captures },10356 .captures = .{ .external = ini.captures },
10265 } } });10357 } } });
...@@ -10267,8 +10359,8 @@ pub fn getOpaqueType(...@@ -10267,8 +10359,8 @@ pub fn getOpaqueType(
10267 if (gop == .existing) return .{ .existing = gop.existing };10359 if (gop == .existing) return .{ .existing = gop.existing };
1026810360
10269 const local = ip.getLocal(tid);10361 const local = ip.getLocal(tid);
10270 const items = local.getMutableItems(gpa);10362 const items = local.getMutableItems(gpa, io);
10271 const extra = local.getMutableExtra(gpa);10363 const extra = local.getMutableExtra(gpa, io);
10272 try items.ensureUnusedCapacity(1);10364 try items.ensureUnusedCapacity(1);
1027310365
10274 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len);10366 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len);
...@@ -10338,8 +10430,8 @@ fn addIndexesToMap(...@@ -10338,8 +10430,8 @@ fn addIndexesToMap(
10338 }10430 }
10339}10431}
1034010432
10341fn addMap(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, cap: usize) Allocator.Error!MapIndex {10433fn addMap(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, cap: usize) Allocator.Error!MapIndex {
10342 const maps = ip.getLocal(tid).getMutableMaps(gpa);10434 const maps = ip.getLocal(tid).getMutableMaps(gpa, io);
10343 const unwrapped: MapIndex.Unwrapped = .{ .tid = tid, .index = maps.mutate.len };10435 const unwrapped: MapIndex.Unwrapped = .{ .tid = tid, .index = maps.mutate.len };
10344 const ptr = try maps.addOne();10436 const ptr = try maps.addOne();
10345 errdefer maps.mutate.len = unwrapped.index;10437 errdefer maps.mutate.len = unwrapped.index;
...@@ -10373,14 +10465,15 @@ pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {...@@ -10373,14 +10465,15 @@ pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {
10373fn addInt(10465fn addInt(
10374 ip: *InternPool,10466 ip: *InternPool,
10375 gpa: Allocator,10467 gpa: Allocator,
10468 io: Io,
10376 tid: Zcu.PerThread.Id,10469 tid: Zcu.PerThread.Id,
10377 ty: Index,10470 ty: Index,
10378 tag: Tag,10471 tag: Tag,
10379 limbs: []const Limb,10472 limbs: []const Limb,
10380) !void {10473) !void {
10381 const local = ip.getLocal(tid);10474 const local = ip.getLocal(tid);
10382 const items_list = local.getMutableItems(gpa);10475 const items_list = local.getMutableItems(gpa, io);
10383 const limbs_list = local.getMutableLimbs(gpa);10476 const limbs_list = local.getMutableLimbs(gpa, io);
10384 const limbs_len: u32 = @intCast(limbs.len);10477 const limbs_len: u32 = @intCast(limbs.len);
10385 try limbs_list.ensureUnusedCapacity(Int.limbs_items_len + limbs_len);10478 try limbs_list.ensureUnusedCapacity(Int.limbs_items_len + limbs_len);
10386 items_list.appendAssumeCapacity(.{10479 items_list.appendAssumeCapacity(.{
...@@ -10510,28 +10603,29 @@ fn extraData(extra: Local.Extra, comptime T: type, index: u32) T {...@@ -10510,28 +10603,29 @@ fn extraData(extra: Local.Extra, comptime T: type, index: u32) T {
1051010603
10511test "basic usage" {10604test "basic usage" {
10512 const gpa = std.testing.allocator;10605 const gpa = std.testing.allocator;
10606 const io = std.testing.io;
1051310607
10514 var ip: InternPool = .empty;10608 var ip: InternPool = .empty;
10515 try ip.init(gpa, 1);10609 try ip.init(gpa, io, 1);
10516 defer ip.deinit(gpa);10610 defer ip.deinit(gpa, io);
1051710611
10518 const i32_type = try ip.get(gpa, .main, .{ .int_type = .{10612 const i32_type = try ip.get(gpa, io, .main, .{ .int_type = .{
10519 .signedness = .signed,10613 .signedness = .signed,
10520 .bits = 32,10614 .bits = 32,
10521 } });10615 } });
10522 const array_i32 = try ip.get(gpa, .main, .{ .array_type = .{10616 const array_i32 = try ip.get(gpa, io, .main, .{ .array_type = .{
10523 .len = 10,10617 .len = 10,
10524 .child = i32_type,10618 .child = i32_type,
10525 .sentinel = .none,10619 .sentinel = .none,
10526 } });10620 } });
1052710621
10528 const another_i32_type = try ip.get(gpa, .main, .{ .int_type = .{10622 const another_i32_type = try ip.get(gpa, io, .main, .{ .int_type = .{
10529 .signedness = .signed,10623 .signedness = .signed,
10530 .bits = 32,10624 .bits = 32,
10531 } });10625 } });
10532 try std.testing.expect(another_i32_type == i32_type);10626 try std.testing.expect(another_i32_type == i32_type);
1053310627
10534 const another_array_i32 = try ip.get(gpa, .main, .{ .array_type = .{10628 const another_array_i32 = try ip.get(gpa, io, .main, .{ .array_type = .{
10535 .len = 10,10629 .len = 10,
10536 .child = i32_type,10630 .child = i32_type,
10537 .sentinel = .none,10631 .sentinel = .none,
...@@ -10608,6 +10702,7 @@ pub fn sliceLen(ip: *const InternPool, index: Index) Index {...@@ -10608,6 +10702,7 @@ pub fn sliceLen(ip: *const InternPool, index: Index) Index {
10608pub fn getCoerced(10702pub fn getCoerced(
10609 ip: *InternPool,10703 ip: *InternPool,
10610 gpa: Allocator,10704 gpa: Allocator,
10705 io: Io,
10611 tid: Zcu.PerThread.Id,10706 tid: Zcu.PerThread.Id,
10612 val: Index,10707 val: Index,
10613 new_ty: Index,10708 new_ty: Index,
...@@ -10616,22 +10711,22 @@ pub fn getCoerced(...@@ -10616,22 +10711,22 @@ pub fn getCoerced(
10616 if (old_ty == new_ty) return val;10711 if (old_ty == new_ty) return val;
1061710712
10618 switch (val) {10713 switch (val) {
10619 .undef => return ip.get(gpa, tid, .{ .undef = new_ty }),10714 .undef => return ip.get(gpa, io, tid, .{ .undef = new_ty }),
10620 .null_value => {10715 .null_value => {
10621 if (ip.isOptionalType(new_ty)) return ip.get(gpa, tid, .{ .opt = .{10716 if (ip.isOptionalType(new_ty)) return ip.get(gpa, io, tid, .{ .opt = .{
10622 .ty = new_ty,10717 .ty = new_ty,
10623 .val = .none,10718 .val = .none,
10624 } });10719 } });
1062510720
10626 if (ip.isPointerType(new_ty)) switch (ip.indexToKey(new_ty).ptr_type.flags.size) {10721 if (ip.isPointerType(new_ty)) switch (ip.indexToKey(new_ty).ptr_type.flags.size) {
10627 .one, .many, .c => return ip.get(gpa, tid, .{ .ptr = .{10722 .one, .many, .c => return ip.get(gpa, io, tid, .{ .ptr = .{
10628 .ty = new_ty,10723 .ty = new_ty,
10629 .base_addr = .int,10724 .base_addr = .int,
10630 .byte_offset = 0,10725 .byte_offset = 0,
10631 } }),10726 } }),
10632 .slice => return ip.get(gpa, tid, .{ .slice = .{10727 .slice => return ip.get(gpa, io, tid, .{ .slice = .{
10633 .ty = new_ty,10728 .ty = new_ty,
10634 .ptr = try ip.get(gpa, tid, .{ .ptr = .{10729 .ptr = try ip.get(gpa, io, tid, .{ .ptr = .{
10635 .ty = ip.slicePtrType(new_ty),10730 .ty = ip.slicePtrType(new_ty),
10636 .base_addr = .int,10731 .base_addr = .int,
10637 .byte_offset = 0,10732 .byte_offset = 0,
...@@ -10644,15 +10739,15 @@ pub fn getCoerced(...@@ -10644,15 +10739,15 @@ pub fn getCoerced(
10644 const unwrapped_val = val.unwrap(ip);10739 const unwrapped_val = val.unwrap(ip);
10645 const val_item = unwrapped_val.getItem(ip);10740 const val_item = unwrapped_val.getItem(ip);
10646 switch (val_item.tag) {10741 switch (val_item.tag) {
10647 .func_decl => return getCoercedFuncDecl(ip, gpa, tid, val, new_ty),10742 .func_decl => return getCoercedFuncDecl(ip, gpa, io, tid, val, new_ty),
10648 .func_instance => return getCoercedFuncInstance(ip, gpa, tid, val, new_ty),10743 .func_instance => return getCoercedFuncInstance(ip, gpa, io, tid, val, new_ty),
10649 .func_coerced => {10744 .func_coerced => {
10650 const func: Index = @enumFromInt(unwrapped_val.getExtra(ip).view().items(.@"0")[10745 const func: Index = @enumFromInt(unwrapped_val.getExtra(ip).view().items(.@"0")[
10651 val_item.data + std.meta.fieldIndex(Tag.FuncCoerced, "func").?10746 val_item.data + std.meta.fieldIndex(Tag.FuncCoerced, "func").?
10652 ]);10747 ]);
10653 switch (func.unwrap(ip).getTag(ip)) {10748 switch (func.unwrap(ip).getTag(ip)) {
10654 .func_decl => return getCoercedFuncDecl(ip, gpa, tid, val, new_ty),10749 .func_decl => return getCoercedFuncDecl(ip, gpa, io, tid, val, new_ty),
10655 .func_instance => return getCoercedFuncInstance(ip, gpa, tid, val, new_ty),10750 .func_instance => return getCoercedFuncInstance(ip, gpa, io, tid, val, new_ty),
10656 else => unreachable,10751 else => unreachable,
10657 }10752 }
10658 },10753 },
...@@ -10662,16 +10757,16 @@ pub fn getCoerced(...@@ -10662,16 +10757,16 @@ pub fn getCoerced(
10662 }10757 }
1066310758
10664 switch (ip.indexToKey(val)) {10759 switch (ip.indexToKey(val)) {
10665 .undef => return ip.get(gpa, tid, .{ .undef = new_ty }),10760 .undef => return ip.get(gpa, io, tid, .{ .undef = new_ty }),
10666 .func => unreachable,10761 .func => unreachable,
1066710762
10668 .int => |int| switch (ip.indexToKey(new_ty)) {10763 .int => |int| switch (ip.indexToKey(new_ty)) {
10669 .enum_type => return ip.get(gpa, tid, .{ .enum_tag = .{10764 .enum_type => return ip.get(gpa, io, tid, .{ .enum_tag = .{
10670 .ty = new_ty,10765 .ty = new_ty,
10671 .int = try ip.getCoerced(gpa, tid, val, ip.loadEnumType(new_ty).tag_ty),10766 .int = try ip.getCoerced(gpa, io, tid, val, ip.loadEnumType(new_ty).tag_ty),
10672 } }),10767 } }),
10673 .ptr_type => switch (int.storage) {10768 .ptr_type => switch (int.storage) {
10674 inline .u64, .i64 => |int_val| return ip.get(gpa, tid, .{ .ptr = .{10769 inline .u64, .i64 => |int_val| return ip.get(gpa, io, tid, .{ .ptr = .{
10675 .ty = new_ty,10770 .ty = new_ty,
10676 .base_addr = .int,10771 .base_addr = .int,
10677 .byte_offset = @intCast(int_val),10772 .byte_offset = @intCast(int_val),
...@@ -10680,7 +10775,7 @@ pub fn getCoerced(...@@ -10680,7 +10775,7 @@ pub fn getCoerced(
10680 .lazy_align, .lazy_size => {},10775 .lazy_align, .lazy_size => {},
10681 },10776 },
10682 else => if (ip.isIntegerType(new_ty))10777 else => if (ip.isIntegerType(new_ty))
10683 return ip.getCoercedInts(gpa, tid, int, new_ty),10778 return ip.getCoercedInts(gpa, io, tid, int, new_ty),
10684 },10779 },
10685 .float => |float| switch (ip.indexToKey(new_ty)) {10780 .float => |float| switch (ip.indexToKey(new_ty)) {
10686 .simple_type => |simple| switch (simple) {10781 .simple_type => |simple| switch (simple) {
...@@ -10691,7 +10786,7 @@ pub fn getCoerced(...@@ -10691,7 +10786,7 @@ pub fn getCoerced(
10691 .f128,10786 .f128,
10692 .c_longdouble,10787 .c_longdouble,
10693 .comptime_float,10788 .comptime_float,
10694 => return ip.get(gpa, tid, .{ .float = .{10789 => return ip.get(gpa, io, tid, .{ .float = .{
10695 .ty = new_ty,10790 .ty = new_ty,
10696 .storage = float.storage,10791 .storage = float.storage,
10697 } }),10792 } }),
...@@ -10700,17 +10795,17 @@ pub fn getCoerced(...@@ -10700,17 +10795,17 @@ pub fn getCoerced(
10700 else => {},10795 else => {},
10701 },10796 },
10702 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))10797 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
10703 return ip.getCoercedInts(gpa, tid, ip.indexToKey(enum_tag.int).int, new_ty),10798 return ip.getCoercedInts(gpa, io, tid, ip.indexToKey(enum_tag.int).int, new_ty),
10704 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {10799 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
10705 .enum_type => {10800 .enum_type => {
10706 const enum_type = ip.loadEnumType(new_ty);10801 const enum_type = ip.loadEnumType(new_ty);
10707 const index = enum_type.nameIndex(ip, enum_literal).?;10802 const index = enum_type.nameIndex(ip, enum_literal).?;
10708 return ip.get(gpa, tid, .{ .enum_tag = .{10803 return ip.get(gpa, io, tid, .{ .enum_tag = .{
10709 .ty = new_ty,10804 .ty = new_ty,
10710 .int = if (enum_type.values.len != 0)10805 .int = if (enum_type.values.len != 0)
10711 enum_type.values.get(ip)[index]10806 enum_type.values.get(ip)[index]
10712 else10807 else
10713 try ip.get(gpa, tid, .{ .int = .{10808 try ip.get(gpa, io, tid, .{ .int = .{
10714 .ty = enum_type.tag_ty,10809 .ty = enum_type.tag_ty,
10715 .storage = .{ .u64 = index },10810 .storage = .{ .u64 = index },
10716 } }),10811 } }),
...@@ -10719,22 +10814,22 @@ pub fn getCoerced(...@@ -10719,22 +10814,22 @@ pub fn getCoerced(
10719 else => {},10814 else => {},
10720 },10815 },
10721 .slice => |slice| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size == .slice)10816 .slice => |slice| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size == .slice)
10722 return ip.get(gpa, tid, .{ .slice = .{10817 return ip.get(gpa, io, tid, .{ .slice = .{
10723 .ty = new_ty,10818 .ty = new_ty,
10724 .ptr = try ip.getCoerced(gpa, tid, slice.ptr, ip.slicePtrType(new_ty)),10819 .ptr = try ip.getCoerced(gpa, io, tid, slice.ptr, ip.slicePtrType(new_ty)),
10725 .len = slice.len,10820 .len = slice.len,
10726 } })10821 } })
10727 else if (ip.isIntegerType(new_ty))10822 else if (ip.isIntegerType(new_ty))
10728 return ip.getCoerced(gpa, tid, slice.ptr, new_ty),10823 return ip.getCoerced(gpa, io, tid, slice.ptr, new_ty),
10729 .ptr => |ptr| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size != .slice)10824 .ptr => |ptr| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size != .slice)
10730 return ip.get(gpa, tid, .{ .ptr = .{10825 return ip.get(gpa, io, tid, .{ .ptr = .{
10731 .ty = new_ty,10826 .ty = new_ty,
10732 .base_addr = ptr.base_addr,10827 .base_addr = ptr.base_addr,
10733 .byte_offset = ptr.byte_offset,10828 .byte_offset = ptr.byte_offset,
10734 } })10829 } })
10735 else if (ip.isIntegerType(new_ty))10830 else if (ip.isIntegerType(new_ty))
10736 switch (ptr.base_addr) {10831 switch (ptr.base_addr) {
10737 .int => return ip.get(gpa, tid, .{ .int = .{10832 .int => return ip.get(gpa, io, tid, .{ .int = .{
10738 .ty = .usize_type,10833 .ty = .usize_type,
10739 .storage = .{ .u64 = @intCast(ptr.byte_offset) },10834 .storage = .{ .u64 = @intCast(ptr.byte_offset) },
10740 } }),10835 } }),
...@@ -10743,14 +10838,14 @@ pub fn getCoerced(...@@ -10743,14 +10838,14 @@ pub fn getCoerced(
10743 .opt => |opt| switch (ip.indexToKey(new_ty)) {10838 .opt => |opt| switch (ip.indexToKey(new_ty)) {
10744 .ptr_type => |ptr_type| return switch (opt.val) {10839 .ptr_type => |ptr_type| return switch (opt.val) {
10745 .none => switch (ptr_type.flags.size) {10840 .none => switch (ptr_type.flags.size) {
10746 .one, .many, .c => try ip.get(gpa, tid, .{ .ptr = .{10841 .one, .many, .c => try ip.get(gpa, io, tid, .{ .ptr = .{
10747 .ty = new_ty,10842 .ty = new_ty,
10748 .base_addr = .int,10843 .base_addr = .int,
10749 .byte_offset = 0,10844 .byte_offset = 0,
10750 } }),10845 } }),
10751 .slice => try ip.get(gpa, tid, .{ .slice = .{10846 .slice => try ip.get(gpa, io, tid, .{ .slice = .{
10752 .ty = new_ty,10847 .ty = new_ty,
10753 .ptr = try ip.get(gpa, tid, .{ .ptr = .{10848 .ptr = try ip.get(gpa, io, tid, .{ .ptr = .{
10754 .ty = ip.slicePtrType(new_ty),10849 .ty = ip.slicePtrType(new_ty),
10755 .base_addr = .int,10850 .base_addr = .int,
10756 .byte_offset = 0,10851 .byte_offset = 0,
...@@ -10758,29 +10853,29 @@ pub fn getCoerced(...@@ -10758,29 +10853,29 @@ pub fn getCoerced(
10758 .len = .undef_usize,10853 .len = .undef_usize,
10759 } }),10854 } }),
10760 },10855 },
10761 else => |payload| try ip.getCoerced(gpa, tid, payload, new_ty),10856 else => |payload| try ip.getCoerced(gpa, io, tid, payload, new_ty),
10762 },10857 },
10763 .opt_type => |child_type| return try ip.get(gpa, tid, .{ .opt = .{10858 .opt_type => |child_type| return try ip.get(gpa, io, tid, .{ .opt = .{
10764 .ty = new_ty,10859 .ty = new_ty,
10765 .val = switch (opt.val) {10860 .val = switch (opt.val) {
10766 .none => .none,10861 .none => .none,
10767 else => try ip.getCoerced(gpa, tid, opt.val, child_type),10862 else => try ip.getCoerced(gpa, io, tid, opt.val, child_type),
10768 },10863 },
10769 } }),10864 } }),
10770 else => {},10865 else => {},
10771 },10866 },
10772 .err => |err| if (ip.isErrorSetType(new_ty))10867 .err => |err| if (ip.isErrorSetType(new_ty))
10773 return ip.get(gpa, tid, .{ .err = .{10868 return ip.get(gpa, io, tid, .{ .err = .{
10774 .ty = new_ty,10869 .ty = new_ty,
10775 .name = err.name,10870 .name = err.name,
10776 } })10871 } })
10777 else if (ip.isErrorUnionType(new_ty))10872 else if (ip.isErrorUnionType(new_ty))
10778 return ip.get(gpa, tid, .{ .error_union = .{10873 return ip.get(gpa, io, tid, .{ .error_union = .{
10779 .ty = new_ty,10874 .ty = new_ty,
10780 .val = .{ .err_name = err.name },10875 .val = .{ .err_name = err.name },
10781 } }),10876 } }),
10782 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))10877 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
10783 return ip.get(gpa, tid, .{ .error_union = .{10878 return ip.get(gpa, io, tid, .{ .error_union = .{
10784 .ty = new_ty,10879 .ty = new_ty,
10785 .val = error_union.val,10880 .val = error_union.val,
10786 } }),10881 } }),
...@@ -10799,20 +10894,20 @@ pub fn getCoerced(...@@ -10799,20 +10894,20 @@ pub fn getCoerced(
10799 };10894 };
10800 if (old_ty_child != new_ty_child) break :direct;10895 if (old_ty_child != new_ty_child) break :direct;
10801 switch (aggregate.storage) {10896 switch (aggregate.storage) {
10802 .bytes => |bytes| return ip.get(gpa, tid, .{ .aggregate = .{10897 .bytes => |bytes| return ip.get(gpa, io, tid, .{ .aggregate = .{
10803 .ty = new_ty,10898 .ty = new_ty,
10804 .storage = .{ .bytes = bytes },10899 .storage = .{ .bytes = bytes },
10805 } }),10900 } }),
10806 .elems => |elems| {10901 .elems => |elems| {
10807 const elems_copy = try gpa.dupe(Index, elems[0..new_len]);10902 const elems_copy = try gpa.dupe(Index, elems[0..new_len]);
10808 defer gpa.free(elems_copy);10903 defer gpa.free(elems_copy);
10809 return ip.get(gpa, tid, .{ .aggregate = .{10904 return ip.get(gpa, io, tid, .{ .aggregate = .{
10810 .ty = new_ty,10905 .ty = new_ty,
10811 .storage = .{ .elems = elems_copy },10906 .storage = .{ .elems = elems_copy },
10812 } });10907 } });
10813 },10908 },
10814 .repeated_elem => |elem| {10909 .repeated_elem => |elem| {
10815 return ip.get(gpa, tid, .{ .aggregate = .{10910 return ip.get(gpa, io, tid, .{ .aggregate = .{
10816 .ty = new_ty,10911 .ty = new_ty,
10817 .storage = .{ .repeated_elem = elem },10912 .storage = .{ .repeated_elem = elem },
10818 } });10913 } });
...@@ -10830,7 +10925,7 @@ pub fn getCoerced(...@@ -10830,7 +10925,7 @@ pub fn getCoerced(
10830 // We have to intern each value here, so unfortunately we can't easily avoid10925 // We have to intern each value here, so unfortunately we can't easily avoid
10831 // the repeated indexToKey calls.10926 // the repeated indexToKey calls.
10832 for (agg_elems, 0..) |*elem, index| {10927 for (agg_elems, 0..) |*elem, index| {
10833 elem.* = try ip.get(gpa, tid, .{ .int = .{10928 elem.* = try ip.get(gpa, io, tid, .{ .int = .{
10834 .ty = .u8_type,10929 .ty = .u8_type,
10835 .storage = .{ .u64 = bytes.at(index, ip) },10930 .storage = .{ .u64 = bytes.at(index, ip) },
10836 } });10931 } });
...@@ -10847,27 +10942,27 @@ pub fn getCoerced(...@@ -10847,27 +10942,27 @@ pub fn getCoerced(
10847 .struct_type => ip.loadStructType(new_ty).field_types.get(ip)[i],10942 .struct_type => ip.loadStructType(new_ty).field_types.get(ip)[i],
10848 else => unreachable,10943 else => unreachable,
10849 };10944 };
10850 elem.* = try ip.getCoerced(gpa, tid, elem.*, new_elem_ty);10945 elem.* = try ip.getCoerced(gpa, io, tid, elem.*, new_elem_ty);
10851 }10946 }
10852 return ip.get(gpa, tid, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } });10947 return ip.get(gpa, io, tid, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } });
10853 },10948 },
10854 else => {},10949 else => {},
10855 }10950 }
1085610951
10857 switch (ip.indexToKey(new_ty)) {10952 switch (ip.indexToKey(new_ty)) {
10858 .opt_type => |child_type| switch (val) {10953 .opt_type => |child_type| switch (val) {
10859 .null_value => return ip.get(gpa, tid, .{ .opt = .{10954 .null_value => return ip.get(gpa, io, tid, .{ .opt = .{
10860 .ty = new_ty,10955 .ty = new_ty,
10861 .val = .none,10956 .val = .none,
10862 } }),10957 } }),
10863 else => return ip.get(gpa, tid, .{ .opt = .{10958 else => return ip.get(gpa, io, tid, .{ .opt = .{
10864 .ty = new_ty,10959 .ty = new_ty,
10865 .val = try ip.getCoerced(gpa, tid, val, child_type),10960 .val = try ip.getCoerced(gpa, io, tid, val, child_type),
10866 } }),10961 } }),
10867 },10962 },
10868 .error_union_type => |error_union_type| return ip.get(gpa, tid, .{ .error_union = .{10963 .error_union_type => |error_union_type| return ip.get(gpa, io, tid, .{ .error_union = .{
10869 .ty = new_ty,10964 .ty = new_ty,
10870 .val = .{ .payload = try ip.getCoerced(gpa, tid, val, error_union_type.payload_type) },10965 .val = .{ .payload = try ip.getCoerced(gpa, io, tid, val, error_union_type.payload_type) },
10871 } }),10966 } }),
10872 else => {},10967 else => {},
10873 }10968 }
...@@ -10884,6 +10979,7 @@ pub fn getCoerced(...@@ -10884,6 +10979,7 @@ pub fn getCoerced(
10884fn getCoercedFuncDecl(10979fn getCoercedFuncDecl(
10885 ip: *InternPool,10980 ip: *InternPool,
10886 gpa: Allocator,10981 gpa: Allocator,
10982 io: Io,
10887 tid: Zcu.PerThread.Id,10983 tid: Zcu.PerThread.Id,
10888 val: Index,10984 val: Index,
10889 new_ty: Index,10985 new_ty: Index,
...@@ -10893,12 +10989,13 @@ fn getCoercedFuncDecl(...@@ -10893,12 +10989,13 @@ fn getCoercedFuncDecl(
10893 unwrapped_val.getData(ip) + std.meta.fieldIndex(Tag.FuncDecl, "ty").?10989 unwrapped_val.getData(ip) + std.meta.fieldIndex(Tag.FuncDecl, "ty").?
10894 ]);10990 ]);
10895 if (new_ty == prev_ty) return val;10991 if (new_ty == prev_ty) return val;
10896 return getCoercedFunc(ip, gpa, tid, val, new_ty);10992 return getCoercedFunc(ip, gpa, io, tid, val, new_ty);
10897}10993}
1089810994
10899fn getCoercedFuncInstance(10995fn getCoercedFuncInstance(
10900 ip: *InternPool,10996 ip: *InternPool,
10901 gpa: Allocator,10997 gpa: Allocator,
10998 io: Io,
10902 tid: Zcu.PerThread.Id,10999 tid: Zcu.PerThread.Id,
10903 val: Index,11000 val: Index,
10904 new_ty: Index,11001 new_ty: Index,
...@@ -10908,20 +11005,21 @@ fn getCoercedFuncInstance(...@@ -10908,20 +11005,21 @@ fn getCoercedFuncInstance(
10908 unwrapped_val.getData(ip) + std.meta.fieldIndex(Tag.FuncInstance, "ty").?11005 unwrapped_val.getData(ip) + std.meta.fieldIndex(Tag.FuncInstance, "ty").?
10909 ]);11006 ]);
10910 if (new_ty == prev_ty) return val;11007 if (new_ty == prev_ty) return val;
10911 return getCoercedFunc(ip, gpa, tid, val, new_ty);11008 return getCoercedFunc(ip, gpa, io, tid, val, new_ty);
10912}11009}
1091311010
10914fn getCoercedFunc(11011fn getCoercedFunc(
10915 ip: *InternPool,11012 ip: *InternPool,
10916 gpa: Allocator,11013 gpa: Allocator,
11014 io: Io,
10917 tid: Zcu.PerThread.Id,11015 tid: Zcu.PerThread.Id,
10918 func: Index,11016 func: Index,
10919 ty: Index,11017 ty: Index,
10920) Allocator.Error!Index {11018) Allocator.Error!Index {
10921 const local = ip.getLocal(tid);11019 const local = ip.getLocal(tid);
10922 const items = local.getMutableItems(gpa);11020 const items = local.getMutableItems(gpa, io);
10923 try items.ensureUnusedCapacity(1);11021 try items.ensureUnusedCapacity(1);
10924 const extra = local.getMutableExtra(gpa);11022 const extra = local.getMutableExtra(gpa, io);
1092511023
10926 const prev_extra_len = extra.mutate.len;11024 const prev_extra_len = extra.mutate.len;
10927 try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncCoerced).@"struct".fields.len);11025 try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncCoerced).@"struct".fields.len);
...@@ -10932,7 +11030,7 @@ fn getCoercedFunc(...@@ -10932,7 +11030,7 @@ fn getCoercedFunc(
10932 });11030 });
10933 errdefer extra.mutate.len = prev_extra_len;11031 errdefer extra.mutate.len = prev_extra_len;
1093411032
10935 var gop = try ip.getOrPutKey(gpa, tid, .{11033 var gop = try ip.getOrPutKey(gpa, io, tid, .{
10936 .func = ip.extraFuncCoerced(extra.list.*, extra_index),11034 .func = ip.extraFuncCoerced(extra.list.*, extra_index),
10937 });11035 });
10938 defer gop.deinit();11036 defer gop.deinit();
...@@ -10950,8 +11048,15 @@ fn getCoercedFunc(...@@ -10950,8 +11048,15 @@ fn getCoercedFunc(
1095011048
10951/// Asserts `val` has an integer type.11049/// Asserts `val` has an integer type.
10952/// Assumes `new_ty` is an integer type.11050/// Assumes `new_ty` is an integer type.
10953pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, int: Key.Int, new_ty: Index) Allocator.Error!Index {11051pub fn getCoercedInts(
10954 return ip.get(gpa, tid, .{ .int = .{11052 ip: *InternPool,
11053 gpa: Allocator,
11054 io: Io,
11055 tid: Zcu.PerThread.Id,
11056 int: Key.Int,
11057 new_ty: Index,
11058) Allocator.Error!Index {
11059 return ip.get(gpa, io, tid, .{ .int = .{
10955 .ty = new_ty,11060 .ty = new_ty,
10956 .storage = int.storage,11061 .storage = int.storage,
10957 } });11062 } });
...@@ -11047,12 +11152,12 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index {...@@ -11047,12 +11152,12 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index {
11047}11152}
1104811153
11049/// The is only legal because the initializer is not part of the hash.11154/// The is only legal because the initializer is not part of the hash.
11050pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void {11155pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) void {
11051 const unwrapped_index = index.unwrap(ip);11156 const unwrapped_index = index.unwrap(ip);
1105211157
11053 const local = ip.getLocal(unwrapped_index.tid);11158 const local = ip.getLocal(unwrapped_index.tid);
11054 local.mutate.extra.mutex.lock();11159 local.mutate.extra.mutex.lockUncancelable(io);
11055 defer local.mutate.extra.mutex.unlock();11160 defer local.mutate.extra.mutex.unlock(io);
1105611161
11057 const extra_items = local.shared.extra.view().items(.@"0");11162 const extra_items = local.shared.extra.view().items(.@"0");
11058 const item = unwrapped_index.getItem(ip);11163 const item = unwrapped_index.getItem(ip);
...@@ -11508,11 +11613,12 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names...@@ -11508,11 +11613,12 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names
11508pub fn createComptimeUnit(11613pub fn createComptimeUnit(
11509 ip: *InternPool,11614 ip: *InternPool,
11510 gpa: Allocator,11615 gpa: Allocator,
11616 io: Io,
11511 tid: Zcu.PerThread.Id,11617 tid: Zcu.PerThread.Id,
11512 zir_index: TrackedInst.Index,11618 zir_index: TrackedInst.Index,
11513 namespace: NamespaceIndex,11619 namespace: NamespaceIndex,
11514) Allocator.Error!ComptimeUnit.Id {11620) Allocator.Error!ComptimeUnit.Id {
11515 const comptime_units = ip.getLocal(tid).getMutableComptimeUnits(gpa);11621 const comptime_units = ip.getLocal(tid).getMutableComptimeUnits(gpa, io);
11516 const id_unwrapped: ComptimeUnit.Id.Unwrapped = .{11622 const id_unwrapped: ComptimeUnit.Id.Unwrapped = .{
11517 .tid = tid,11623 .tid = tid,
11518 .index = comptime_units.mutate.len,11624 .index = comptime_units.mutate.len,
...@@ -11532,9 +11638,10 @@ pub fn getComptimeUnit(ip: *const InternPool, id: ComptimeUnit.Id) ComptimeUnit...@@ -11532,9 +11638,10 @@ pub fn getComptimeUnit(ip: *const InternPool, id: ComptimeUnit.Id) ComptimeUnit
1153211638
11533/// Create a `Nav` which does not undergo semantic analysis.11639/// Create a `Nav` which does not undergo semantic analysis.
11534/// Since it is never analyzed, the `Nav`'s value must be known at creation time.11640/// Since it is never analyzed, the `Nav`'s value must be known at creation time.
11535pub fn createNav(11641fn createNav(
11536 ip: *InternPool,11642 ip: *InternPool,
11537 gpa: Allocator,11643 gpa: Allocator,
11644 io: Io,
11538 tid: Zcu.PerThread.Id,11645 tid: Zcu.PerThread.Id,
11539 opts: struct {11646 opts: struct {
11540 name: NullTerminatedString,11647 name: NullTerminatedString,
...@@ -11546,7 +11653,7 @@ pub fn createNav(...@@ -11546,7 +11653,7 @@ pub fn createNav(
11546 @"addrspace": std.builtin.AddressSpace,11653 @"addrspace": std.builtin.AddressSpace,
11547 },11654 },
11548) Allocator.Error!Nav.Index {11655) Allocator.Error!Nav.Index {
11549 const navs = ip.getLocal(tid).getMutableNavs(gpa);11656 const navs = ip.getLocal(tid).getMutableNavs(gpa, io);
11550 const index_unwrapped: Nav.Index.Unwrapped = .{11657 const index_unwrapped: Nav.Index.Unwrapped = .{
11551 .tid = tid,11658 .tid = tid,
11552 .index = navs.mutate.len,11659 .index = navs.mutate.len,
...@@ -11571,13 +11678,14 @@ pub fn createNav(...@@ -11571,13 +11678,14 @@ pub fn createNav(
11571pub fn createDeclNav(11678pub fn createDeclNav(
11572 ip: *InternPool,11679 ip: *InternPool,
11573 gpa: Allocator,11680 gpa: Allocator,
11681 io: Io,
11574 tid: Zcu.PerThread.Id,11682 tid: Zcu.PerThread.Id,
11575 name: NullTerminatedString,11683 name: NullTerminatedString,
11576 fqn: NullTerminatedString,11684 fqn: NullTerminatedString,
11577 zir_index: TrackedInst.Index,11685 zir_index: TrackedInst.Index,
11578 namespace: NamespaceIndex,11686 namespace: NamespaceIndex,
11579) Allocator.Error!Nav.Index {11687) Allocator.Error!Nav.Index {
11580 const navs = ip.getLocal(tid).getMutableNavs(gpa);11688 const navs = ip.getLocal(tid).getMutableNavs(gpa, io);
1158111689
11582 try navs.ensureUnusedCapacity(1);11690 try navs.ensureUnusedCapacity(1);
1158311691
...@@ -11603,6 +11711,7 @@ pub fn createDeclNav(...@@ -11603,6 +11711,7 @@ pub fn createDeclNav(
11603/// If its status is already `resolved`, the old value is discarded.11711/// If its status is already `resolved`, the old value is discarded.
11604pub fn resolveNavType(11712pub fn resolveNavType(
11605 ip: *InternPool,11713 ip: *InternPool,
11714 io: Io,
11606 nav: Nav.Index,11715 nav: Nav.Index,
11607 resolved: struct {11716 resolved: struct {
11608 type: InternPool.Index,11717 type: InternPool.Index,
...@@ -11617,8 +11726,8 @@ pub fn resolveNavType(...@@ -11617,8 +11726,8 @@ pub fn resolveNavType(
11617 const unwrapped = nav.unwrap(ip);11726 const unwrapped = nav.unwrap(ip);
1161811727
11619 const local = ip.getLocal(unwrapped.tid);11728 const local = ip.getLocal(unwrapped.tid);
11620 local.mutate.extra.mutex.lock();11729 local.mutate.extra.mutex.lockUncancelable(io);
11621 defer local.mutate.extra.mutex.unlock();11730 defer local.mutate.extra.mutex.unlock(io);
1162211731
11623 const navs = local.shared.navs.view();11732 const navs = local.shared.navs.view();
1162411733
...@@ -11647,6 +11756,7 @@ pub fn resolveNavType(...@@ -11647,6 +11756,7 @@ pub fn resolveNavType(
11647/// If its status is already `resolved`, the old value is discarded.11756/// If its status is already `resolved`, the old value is discarded.
11648pub fn resolveNavValue(11757pub fn resolveNavValue(
11649 ip: *InternPool,11758 ip: *InternPool,
11759 io: Io,
11650 nav: Nav.Index,11760 nav: Nav.Index,
11651 resolved: struct {11761 resolved: struct {
11652 val: InternPool.Index,11762 val: InternPool.Index,
...@@ -11659,8 +11769,8 @@ pub fn resolveNavValue(...@@ -11659,8 +11769,8 @@ pub fn resolveNavValue(
11659 const unwrapped = nav.unwrap(ip);11769 const unwrapped = nav.unwrap(ip);
1166011770
11661 const local = ip.getLocal(unwrapped.tid);11771 const local = ip.getLocal(unwrapped.tid);
11662 local.mutate.extra.mutex.lock();11772 local.mutate.extra.mutex.lockUncancelable(io);
11663 defer local.mutate.extra.mutex.unlock();11773 defer local.mutate.extra.mutex.unlock(io);
1166411774
11665 const navs = local.shared.navs.view();11775 const navs = local.shared.navs.view();
1166611776
...@@ -11687,6 +11797,7 @@ pub fn resolveNavValue(...@@ -11687,6 +11797,7 @@ pub fn resolveNavValue(
11687pub fn createNamespace(11797pub fn createNamespace(
11688 ip: *InternPool,11798 ip: *InternPool,
11689 gpa: Allocator,11799 gpa: Allocator,
11800 io: Io,
11690 tid: Zcu.PerThread.Id,11801 tid: Zcu.PerThread.Id,
11691 initialization: Zcu.Namespace,11802 initialization: Zcu.Namespace,
11692) Allocator.Error!NamespaceIndex {11803) Allocator.Error!NamespaceIndex {
...@@ -11700,7 +11811,7 @@ pub fn createNamespace(...@@ -11700,7 +11811,7 @@ pub fn createNamespace(
11700 reused_namespace.* = initialization;11811 reused_namespace.* = initialization;
11701 return reused_namespace_index;11812 return reused_namespace_index;
11702 }11813 }
11703 const namespaces = local.getMutableNamespaces(gpa);11814 const namespaces = local.getMutableNamespaces(gpa, io);
11704 const last_bucket_len = local.mutate.namespaces.last_bucket_len & Local.namespaces_bucket_mask;11815 const last_bucket_len = local.mutate.namespaces.last_bucket_len & Local.namespaces_bucket_mask;
11705 if (last_bucket_len == 0) {11816 if (last_bucket_len == 0) {
11706 try namespaces.ensureUnusedCapacity(1);11817 try namespaces.ensureUnusedCapacity(1);
...@@ -11748,10 +11859,11 @@ pub fn filePtr(ip: *const InternPool, file_index: FileIndex) *Zcu.File {...@@ -11748,10 +11859,11 @@ pub fn filePtr(ip: *const InternPool, file_index: FileIndex) *Zcu.File {
11748pub fn createFile(11859pub fn createFile(
11749 ip: *InternPool,11860 ip: *InternPool,
11750 gpa: Allocator,11861 gpa: Allocator,
11862 io: Io,
11751 tid: Zcu.PerThread.Id,11863 tid: Zcu.PerThread.Id,
11752 file: File,11864 file: File,
11753) Allocator.Error!FileIndex {11865) Allocator.Error!FileIndex {
11754 const files = ip.getLocal(tid).getMutableFiles(gpa);11866 const files = ip.getLocal(tid).getMutableFiles(gpa, io);
11755 const file_index_unwrapped: FileIndex.Unwrapped = .{11867 const file_index_unwrapped: FileIndex.Unwrapped = .{
11756 .tid = tid,11868 .tid = tid,
11757 .index = files.mutate.len,11869 .index = files.mutate.len,
...@@ -11782,20 +11894,22 @@ const EmbeddedNulls = enum {...@@ -11782,20 +11894,22 @@ const EmbeddedNulls = enum {
11782pub fn getOrPutString(11894pub fn getOrPutString(
11783 ip: *InternPool,11895 ip: *InternPool,
11784 gpa: Allocator,11896 gpa: Allocator,
11897 io: Io,
11785 tid: Zcu.PerThread.Id,11898 tid: Zcu.PerThread.Id,
11786 slice: []const u8,11899 slice: []const u8,
11787 comptime embedded_nulls: EmbeddedNulls,11900 comptime embedded_nulls: EmbeddedNulls,
11788) Allocator.Error!embedded_nulls.StringType() {11901) Allocator.Error!embedded_nulls.StringType() {
11789 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa);11902 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io);
11790 try string_bytes.ensureUnusedCapacity(slice.len + 1);11903 try string_bytes.ensureUnusedCapacity(slice.len + 1);
11791 string_bytes.appendSliceAssumeCapacity(.{slice});11904 string_bytes.appendSliceAssumeCapacity(.{slice});
11792 string_bytes.appendAssumeCapacity(.{0});11905 string_bytes.appendAssumeCapacity(.{0});
11793 return ip.getOrPutTrailingString(gpa, tid, @intCast(slice.len + 1), embedded_nulls);11906 return ip.getOrPutTrailingString(gpa, io, tid, @intCast(slice.len + 1), embedded_nulls);
11794}11907}
1179511908
11796pub fn getOrPutStringFmt(11909pub fn getOrPutStringFmt(
11797 ip: *InternPool,11910 ip: *InternPool,
11798 gpa: Allocator,11911 gpa: Allocator,
11912 io: Io,
11799 tid: Zcu.PerThread.Id,11913 tid: Zcu.PerThread.Id,
11800 comptime format: []const u8,11914 comptime format: []const u8,
11801 args: anytype,11915 args: anytype,
...@@ -11804,20 +11918,21 @@ pub fn getOrPutStringFmt(...@@ -11804,20 +11918,21 @@ pub fn getOrPutStringFmt(
11804 // ensure that references to strings in args do not get invalidated11918 // ensure that references to strings in args do not get invalidated
11805 const format_z = format ++ .{0};11919 const format_z = format ++ .{0};
11806 const len: u32 = @intCast(std.fmt.count(format_z, args));11920 const len: u32 = @intCast(std.fmt.count(format_z, args));
11807 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa);11921 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io);
11808 const slice = try string_bytes.addManyAsSlice(len);11922 const slice = try string_bytes.addManyAsSlice(len);
11809 assert((std.fmt.bufPrint(slice[0], format_z, args) catch unreachable).len == len);11923 assert((std.fmt.bufPrint(slice[0], format_z, args) catch unreachable).len == len);
11810 return ip.getOrPutTrailingString(gpa, tid, len, embedded_nulls);11924 return ip.getOrPutTrailingString(gpa, io, tid, len, embedded_nulls);
11811}11925}
1181211926
11813pub fn getOrPutStringOpt(11927pub fn getOrPutStringOpt(
11814 ip: *InternPool,11928 ip: *InternPool,
11815 gpa: Allocator,11929 gpa: Allocator,
11930 io: Io,
11816 tid: Zcu.PerThread.Id,11931 tid: Zcu.PerThread.Id,
11817 slice: ?[]const u8,11932 slice: ?[]const u8,
11818 comptime embedded_nulls: EmbeddedNulls,11933 comptime embedded_nulls: EmbeddedNulls,
11819) Allocator.Error!embedded_nulls.OptionalStringType() {11934) Allocator.Error!embedded_nulls.OptionalStringType() {
11820 const string = try getOrPutString(ip, gpa, tid, slice orelse return .none, embedded_nulls);11935 const string = try getOrPutString(ip, gpa, io, tid, slice orelse return .none, embedded_nulls);
11821 return string.toOptional();11936 return string.toOptional();
11822}11937}
1182311938
...@@ -11825,14 +11940,15 @@ pub fn getOrPutStringOpt(...@@ -11825,14 +11940,15 @@ pub fn getOrPutStringOpt(
11825pub fn getOrPutTrailingString(11940pub fn getOrPutTrailingString(
11826 ip: *InternPool,11941 ip: *InternPool,
11827 gpa: Allocator,11942 gpa: Allocator,
11943 io: Io,
11828 tid: Zcu.PerThread.Id,11944 tid: Zcu.PerThread.Id,
11829 len: u32,11945 len: u32,
11830 comptime embedded_nulls: EmbeddedNulls,11946 comptime embedded_nulls: EmbeddedNulls,
11831) Allocator.Error!embedded_nulls.StringType() {11947) Allocator.Error!embedded_nulls.StringType() {
11832 const local = ip.getLocal(tid);11948 const local = ip.getLocal(tid);
11833 const strings = local.getMutableStrings(gpa);11949 const strings = local.getMutableStrings(gpa, io);
11834 try strings.ensureUnusedCapacity(1);11950 try strings.ensureUnusedCapacity(1);
11835 const string_bytes = local.getMutableStringBytes(gpa);11951 const string_bytes = local.getMutableStringBytes(gpa, io);
11836 const start: u32 = @intCast(string_bytes.mutate.len - len);11952 const start: u32 = @intCast(string_bytes.mutate.len - len);
11837 if (len > 0 and string_bytes.view().items(.@"0")[string_bytes.mutate.len - 1] == 0) {11953 if (len > 0 and string_bytes.view().items(.@"0")[string_bytes.mutate.len - 1] == 0) {
11838 string_bytes.mutate.len -= 1;11954 string_bytes.mutate.len -= 1;
...@@ -11870,8 +11986,8 @@ pub fn getOrPutTrailingString(...@@ -11870,8 +11986,8 @@ pub fn getOrPutTrailingString(
11870 string_bytes.shrinkRetainingCapacity(start);11986 string_bytes.shrinkRetainingCapacity(start);
11871 return @enumFromInt(@intFromEnum(index));11987 return @enumFromInt(@intFromEnum(index));
11872 }11988 }
11873 shard.mutate.string_map.mutex.lock();11989 shard.mutate.string_map.mutex.lock(io, tid);
11874 defer shard.mutate.string_map.mutex.unlock();11990 defer shard.mutate.string_map.mutex.unlock(io);
11875 if (map.entries != shard.shared.string_map.entries) {11991 if (map.entries != shard.shared.string_map.entries) {
11876 map = shard.shared.string_map;11992 map = shard.shared.string_map;
11877 map_mask = map.header().mask();11993 map_mask = map.header().mask();
...@@ -12590,11 +12706,11 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {...@@ -12590,11 +12706,11 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis {
12590 return @atomicLoad(FuncAnalysis, ip.funcAnalysisPtr(func), .unordered);12706 return @atomicLoad(FuncAnalysis, ip.funcAnalysisPtr(func), .unordered);
12591}12707}
1259212708
12593pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool) void {12709pub fn funcSetHasErrorTrace(ip: *InternPool, io: Io, func: Index, has_error_trace: bool) void {
12594 const unwrapped_func = func.unwrap(ip);12710 const unwrapped_func = func.unwrap(ip);
12595 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;12711 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
12596 extra_mutex.lock();12712 extra_mutex.lockUncancelable(io);
12597 defer extra_mutex.unlock();12713 defer extra_mutex.unlock(io);
1259812714
12599 const analysis_ptr = ip.funcAnalysisPtr(func);12715 const analysis_ptr = ip.funcAnalysisPtr(func);
12600 var analysis = analysis_ptr.*;12716 var analysis = analysis_ptr.*;
...@@ -12602,11 +12718,11 @@ pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool)...@@ -12602,11 +12718,11 @@ pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool)
12602 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);12718 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
12603}12719}
1260412720
12605pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void {12721pub fn funcSetDisableInstrumentation(ip: *InternPool, io: Io, func: Index) void {
12606 const unwrapped_func = func.unwrap(ip);12722 const unwrapped_func = func.unwrap(ip);
12607 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;12723 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
12608 extra_mutex.lock();12724 extra_mutex.lockUncancelable(io);
12609 defer extra_mutex.unlock();12725 defer extra_mutex.unlock(io);
1261012726
12611 const analysis_ptr = ip.funcAnalysisPtr(func);12727 const analysis_ptr = ip.funcAnalysisPtr(func);
12612 var analysis = analysis_ptr.*;12728 var analysis = analysis_ptr.*;
...@@ -12614,11 +12730,11 @@ pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void {...@@ -12614,11 +12730,11 @@ pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void {
12614 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);12730 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release);
12615}12731}
1261612732
12617pub fn funcSetDisableIntrinsics(ip: *InternPool, func: Index) void {12733pub fn funcSetDisableIntrinsics(ip: *InternPool, io: Io, func: Index) void {
12618 const unwrapped_func = func.unwrap(ip);12734 const unwrapped_func = func.unwrap(ip);
12619 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;12735 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
12620 extra_mutex.lock();12736 extra_mutex.lockUncancelable(io);
12621 defer extra_mutex.unlock();12737 defer extra_mutex.unlock(io);
1262212738
12623 const analysis_ptr = ip.funcAnalysisPtr(func);12739 const analysis_ptr = ip.funcAnalysisPtr(func);
12624 var analysis = analysis_ptr.*;12740 var analysis = analysis_ptr.*;
...@@ -12663,15 +12779,6 @@ pub fn iesFuncIndex(ip: *const InternPool, ies_index: Index) Index {...@@ -12663,15 +12779,6 @@ pub fn iesFuncIndex(ip: *const InternPool, ies_index: Index) Index {
12663 return func_index;12779 return func_index;
12664}12780}
1266512781
12666/// Returns a mutable pointer to the resolved error set type of an inferred
12667/// error set function. The returned pointer is invalidated when anything is
12668/// added to `ip`.
12669fn iesResolvedPtr(ip: *InternPool, ies_index: Index) *Index {
12670 const ies_item = ies_index.getItem(ip);
12671 assert(ies_item.tag == .type_inferred_error_set);
12672 return ip.funcIesResolvedPtr(ies_item.data);
12673}
12674
12675/// Returns a mutable pointer to the resolved error set type of an inferred12782/// Returns a mutable pointer to the resolved error set type of an inferred
12676/// error set function. The returned pointer is invalidated when anything is12783/// error set function. The returned pointer is invalidated when anything is
12677/// added to `ip`.12784/// added to `ip`.
...@@ -12706,11 +12813,11 @@ pub fn funcIesResolvedUnordered(ip: *const InternPool, index: Index) Index {...@@ -12706,11 +12813,11 @@ pub fn funcIesResolvedUnordered(ip: *const InternPool, index: Index) Index {
12706 return @atomicLoad(Index, ip.funcIesResolvedPtr(index), .unordered);12813 return @atomicLoad(Index, ip.funcIesResolvedPtr(index), .unordered);
12707}12814}
1270812815
12709pub fn funcSetIesResolved(ip: *InternPool, index: Index, ies: Index) void {12816pub fn funcSetIesResolved(ip: *InternPool, io: Io, index: Index, ies: Index) void {
12710 const unwrapped_func = index.unwrap(ip);12817 const unwrapped_func = index.unwrap(ip);
12711 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;12818 const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex;
12712 extra_mutex.lock();12819 extra_mutex.lockUncancelable(io);
12713 defer extra_mutex.unlock();12820 defer extra_mutex.unlock(io);
1271412821
12715 @atomicStore(Index, ip.funcIesResolvedPtr(index), ies, .release);12822 @atomicStore(Index, ip.funcIesResolvedPtr(index), ies, .release);
12716}12823}
...@@ -12777,19 +12884,19 @@ const GlobalErrorSet = struct {...@@ -12777,19 +12884,19 @@ const GlobalErrorSet = struct {
12777 } align(std.atomic.cache_line),12884 } align(std.atomic.cache_line),
12778 mutate: struct {12885 mutate: struct {
12779 names: Local.ListMutate,12886 names: Local.ListMutate,
12780 map: struct { mutex: std.Thread.Mutex },12887 map: struct { mutex: Io.Mutex },
12781 } align(std.atomic.cache_line),12888 } align(std.atomic.cache_line),
1278212889
12783 const Names = Local.List(struct { NullTerminatedString });12890 const Names = Local.List(struct { NullTerminatedString });
1278412891
12785 const empty: GlobalErrorSet = .{12892 const empty: GlobalErrorSet = .{
12786 .shared = .{12893 .shared = .{
12787 .names = Names.empty,12894 .names = .empty,
12788 .map = Shard.Map(GlobalErrorSet.Index).empty,12895 .map = .empty,
12789 },12896 },
12790 .mutate = .{12897 .mutate = .{
12791 .names = Local.ListMutate.empty,12898 .names = .empty,
12792 .map = .{ .mutex = .{} },12899 .map = .{ .mutex = .init },
12793 },12900 },
12794 };12901 };
1279512902
...@@ -12807,6 +12914,7 @@ const GlobalErrorSet = struct {...@@ -12807,6 +12914,7 @@ const GlobalErrorSet = struct {
12807 fn getErrorValue(12914 fn getErrorValue(
12808 ges: *GlobalErrorSet,12915 ges: *GlobalErrorSet,
12809 gpa: Allocator,12916 gpa: Allocator,
12917 io: Io,
12810 arena_state: *std.heap.ArenaAllocator.State,12918 arena_state: *std.heap.ArenaAllocator.State,
12811 name: NullTerminatedString,12919 name: NullTerminatedString,
12812 ) Allocator.Error!GlobalErrorSet.Index {12920 ) Allocator.Error!GlobalErrorSet.Index {
...@@ -12825,8 +12933,8 @@ const GlobalErrorSet = struct {...@@ -12825,8 +12933,8 @@ const GlobalErrorSet = struct {
12825 if (entry.hash != hash) continue;12933 if (entry.hash != hash) continue;
12826 if (names.view().items(.@"0")[@intFromEnum(index) - 1] == name) return index;12934 if (names.view().items(.@"0")[@intFromEnum(index) - 1] == name) return index;
12827 }12935 }
12828 ges.mutate.map.mutex.lock();12936 ges.mutate.map.mutex.lockUncancelable(io);
12829 defer ges.mutate.map.mutex.unlock();12937 defer ges.mutate.map.mutex.unlock(io);
12830 if (map.entries != ges.shared.map.entries) {12938 if (map.entries != ges.shared.map.entries) {
12831 map = ges.shared.map;12939 map = ges.shared.map;
12832 map_mask = map.header().mask();12940 map_mask = map.header().mask();
...@@ -12842,6 +12950,7 @@ const GlobalErrorSet = struct {...@@ -12842,6 +12950,7 @@ const GlobalErrorSet = struct {
12842 }12950 }
12843 const mutable_names: Names.Mutable = .{12951 const mutable_names: Names.Mutable = .{
12844 .gpa = gpa,12952 .gpa = gpa,
12953 .io = io,
12845 .arena = arena_state,12954 .arena = arena_state,
12846 .mutate = &ges.mutate.names,12955 .mutate = &ges.mutate.names,
12847 .list = &ges.shared.names,12956 .list = &ges.shared.names,
...@@ -12923,10 +13032,11 @@ const GlobalErrorSet = struct {...@@ -12923,10 +13032,11 @@ const GlobalErrorSet = struct {
12923pub fn getErrorValue(13032pub fn getErrorValue(
12924 ip: *InternPool,13033 ip: *InternPool,
12925 gpa: Allocator,13034 gpa: Allocator,
13035 io: Io,
12926 tid: Zcu.PerThread.Id,13036 tid: Zcu.PerThread.Id,
12927 name: NullTerminatedString,13037 name: NullTerminatedString,
12928) Allocator.Error!Zcu.ErrorInt {13038) Allocator.Error!Zcu.ErrorInt {
12929 return @intFromEnum(try ip.global_error_set.getErrorValue(gpa, &ip.getLocal(tid).mutate.arena, name));13039 return @intFromEnum(try ip.global_error_set.getErrorValue(gpa, io, &ip.getLocal(tid).mutate.arena, name));
12930}13040}
1293113041
12932pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt {13042pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt {
src/Sema.zig+461-202
...@@ -853,8 +853,9 @@ pub const Block = struct {...@@ -853,8 +853,9 @@ pub const Block = struct {
853853
854 fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index {854 fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index {
855 const pt = block.sema.pt;855 const pt = block.sema.pt;
856 const comp = pt.zcu.comp;
856 block.sema.code.assertTrackable(inst);857 block.sema.code.assertTrackable(inst);
857 return pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{858 return pt.zcu.intern_pool.trackZir(comp.gpa, comp.io, pt.tid, .{
858 .file = block.getFileScopeIndex(pt.zcu),859 .file = block.getFileScopeIndex(pt.zcu),
859 .inst = inst,860 .inst = inst,
860 });861 });
...@@ -2205,10 +2206,11 @@ fn analyzeAsType(...@@ -2205,10 +2206,11 @@ fn analyzeAsType(
22052206
2206pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void {2207pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void {
2207 const pt = sema.pt;2208 const pt = sema.pt;
2208 const zcu = pt.zcu;2209 const comp = pt.zcu.comp;
2209 const comp = zcu.comp;2210 const gpa = comp.gpa;
2210 const gpa = sema.gpa;2211 const io = comp.io;
2211 const ip = &zcu.intern_pool;2212 const ip = &pt.zcu.intern_pool;
2213
2212 if (!comp.config.any_error_tracing) return;2214 if (!comp.config.any_error_tracing) return;
22132215
2214 assert(!block.isComptime());2216 assert(!block.isComptime());
...@@ -2231,12 +2233,12 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)...@@ -2231,12 +2233,12 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
2231 const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));2233 const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));
22322234
2233 // st.instruction_addresses = &addrs;2235 // st.instruction_addresses = &addrs;
2234 const instruction_addresses_field_name = try ip.getOrPutString(gpa, pt.tid, "instruction_addresses", .no_embedded_nulls);2236 const instruction_addresses_field_name = try ip.getOrPutString(gpa, io, pt.tid, "instruction_addresses", .no_embedded_nulls);
2235 const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, instruction_addresses_field_name, src, true);2237 const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, instruction_addresses_field_name, src, true);
2236 try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store);2238 try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store);
22372239
2238 // st.index = 0;2240 // st.index = 0;
2239 const index_field_name = try ip.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);2241 const index_field_name = try ip.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
2240 const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, index_field_name, src, true);2242 const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, index_field_name, src, true);
2241 try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store);2243 try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store);
22422244
...@@ -2828,9 +2830,12 @@ fn zirTupleDecl(...@@ -2828,9 +2830,12 @@ fn zirTupleDecl(
2828 block: *Block,2830 block: *Block,
2829 extended: Zir.Inst.Extended.InstData,2831 extended: Zir.Inst.Extended.InstData,
2830) CompileError!Air.Inst.Ref {2832) CompileError!Air.Inst.Ref {
2831 const gpa = sema.gpa;
2832 const pt = sema.pt;2833 const pt = sema.pt;
2833 const zcu = pt.zcu;2834 const zcu = pt.zcu;
2835 const comp = zcu.comp;
2836 const gpa = comp.gpa;
2837 const io = comp.io;
2838
2834 const fields_len = extended.small;2839 const fields_len = extended.small;
2835 const extra = sema.code.extraData(Zir.Inst.TupleDecl, extended.operand);2840 const extra = sema.code.extraData(Zir.Inst.TupleDecl, extended.operand);
2836 var extra_index = extra.end;2841 var extra_index = extra.end;
...@@ -2863,7 +2868,7 @@ fn zirTupleDecl(...@@ -2863,7 +2868,7 @@ fn zirTupleDecl(
2863 const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src);2868 const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src);
2864 const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value });2869 const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value });
2865 if (field_init_val.canMutateComptimeVarState(zcu)) {2870 if (field_init_val.canMutateComptimeVarState(zcu)) {
2866 const field_name = try zcu.intern_pool.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);2871 const field_name = try zcu.intern_pool.getOrPutStringFmt(gpa, io, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
2867 return sema.failWithContainsReferenceToComptimeVar(block, init_src, field_name, "field default value", field_init_val);2872 return sema.failWithContainsReferenceToComptimeVar(block, init_src, field_name, "field default value", field_init_val);
2868 }2873 }
2869 break :init field_init_val.toIntern();2874 break :init field_init_val.toIntern();
...@@ -2872,7 +2877,7 @@ fn zirTupleDecl(...@@ -2872,7 +2877,7 @@ fn zirTupleDecl(
2872 };2877 };
2873 }2878 }
28742879
2875 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{2880 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{
2876 .types = types,2881 .types = types,
2877 .values = inits,2882 .values = inits,
2878 }));2883 }));
...@@ -2911,7 +2916,11 @@ fn validateTupleFieldType(...@@ -2911,7 +2916,11 @@ fn validateTupleFieldType(
2911fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {2916fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {
2912 const pt = sema.pt;2917 const pt = sema.pt;
2913 const zcu = pt.zcu;2918 const zcu = pt.zcu;
2919 const comp = zcu.comp;
2920 const gpa = comp.gpa;
2921 const io = comp.io;
2914 const ip = &zcu.intern_pool;2922 const ip = &zcu.intern_pool;
2923
2915 const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type);2924 const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type);
2916 const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu);2925 const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu);
29172926
...@@ -2934,7 +2943,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us...@@ -2934,7 +2943,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
2934 };2943 };
2935 const loaded_val = try sema.resolveLazyValue(unresolved_loaded_val);2944 const loaded_val = try sema.resolveLazyValue(unresolved_loaded_val);
2936 if (loaded_val.canMutateComptimeVarState(zcu)) {2945 if (loaded_val.canMutateComptimeVarState(zcu)) {
2937 const field_name = try ip.getOrPutString(zcu.gpa, pt.tid, zir_name_slice, .no_embedded_nulls);2946 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls);
2938 return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", loaded_val);2947 return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", loaded_val);
2939 }2948 }
2940 break :capture .{ .@"comptime" = loaded_val.toIntern() };2949 break :capture .{ .@"comptime" = loaded_val.toIntern() };
...@@ -2943,7 +2952,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us...@@ -2943,7 +2952,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
2943 const air_ref = try sema.resolveInst(inst.toRef());2952 const air_ref = try sema.resolveInst(inst.toRef());
2944 if (try sema.resolveValueResolveLazy(air_ref)) |val| {2953 if (try sema.resolveValueResolveLazy(air_ref)) |val| {
2945 if (val.canMutateComptimeVarState(zcu)) {2954 if (val.canMutateComptimeVarState(zcu)) {
2946 const field_name = try ip.getOrPutString(zcu.gpa, pt.tid, zir_name_slice, .no_embedded_nulls);2955 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls);
2947 return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val);2956 return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val);
2948 }2957 }
2949 break :capture .{ .@"comptime" = val.toIntern() };2958 break :capture .{ .@"comptime" = val.toIntern() };
...@@ -2952,7 +2961,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us...@@ -2952,7 +2961,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
2952 }),2961 }),
2953 .decl_val => |str| capture: {2962 .decl_val => |str| capture: {
2954 const decl_name = try ip.getOrPutString(2963 const decl_name = try ip.getOrPutString(
2955 sema.gpa,2964 gpa,
2965 io,
2956 pt.tid,2966 pt.tid,
2957 sema.code.nullTerminatedString(str),2967 sema.code.nullTerminatedString(str),
2958 .no_embedded_nulls,2968 .no_embedded_nulls,
...@@ -2962,7 +2972,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us...@@ -2962,7 +2972,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
2962 },2972 },
2963 .decl_ref => |str| capture: {2973 .decl_ref => |str| capture: {
2964 const decl_name = try ip.getOrPutString(2974 const decl_name = try ip.getOrPutString(
2965 sema.gpa,2975 gpa,
2976 io,
2966 pt.tid,2977 pt.tid,
2967 sema.code.nullTerminatedString(str),2978 sema.code.nullTerminatedString(str),
2968 .no_embedded_nulls,2979 .no_embedded_nulls,
...@@ -2984,8 +2995,11 @@ fn zirStructDecl(...@@ -2984,8 +2995,11 @@ fn zirStructDecl(
2984) CompileError!Air.Inst.Ref {2995) CompileError!Air.Inst.Ref {
2985 const pt = sema.pt;2996 const pt = sema.pt;
2986 const zcu = pt.zcu;2997 const zcu = pt.zcu;
2987 const gpa = sema.gpa;2998 const comp = zcu.comp;
2999 const gpa = comp.gpa;
3000 const io = comp.io;
2988 const ip = &zcu.intern_pool;3001 const ip = &zcu.intern_pool;
3002
2989 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);3003 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
2990 const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand);3004 const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand);
29913005
...@@ -3040,7 +3054,7 @@ fn zirStructDecl(...@@ -3040,7 +3054,7 @@ fn zirStructDecl(
3040 .captures = captures,3054 .captures = captures,
3041 } },3055 } },
3042 };3056 };
3043 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) {3057 const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, struct_init, false)) {
3044 .existing => |ty| {3058 .existing => |ty| {
3045 const new_ty = try pt.ensureTypeUpToDate(ty);3059 const new_ty = try pt.ensureTypeUpToDate(ty);
30463060
...@@ -3108,7 +3122,9 @@ pub fn createTypeName(...@@ -3108,7 +3122,9 @@ pub fn createTypeName(
3108} {3122} {
3109 const pt = sema.pt;3123 const pt = sema.pt;
3110 const zcu = pt.zcu;3124 const zcu = pt.zcu;
3111 const gpa = zcu.gpa;3125 const comp = zcu.comp;
3126 const gpa = comp.gpa;
3127 const io = comp.io;
3112 const ip = &zcu.intern_pool;3128 const ip = &zcu.intern_pool;
31133129
3114 switch (name_strategy) {3130 switch (name_strategy) {
...@@ -3158,7 +3174,7 @@ pub fn createTypeName(...@@ -3158,7 +3174,7 @@ pub fn createTypeName(
31583174
3159 w.writeByte(')') catch return error.OutOfMemory;3175 w.writeByte(')') catch return error.OutOfMemory;
3160 return .{3176 return .{
3161 .name = try ip.getOrPutString(gpa, pt.tid, aw.written(), .no_embedded_nulls),3177 .name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls),
3162 .nav = .none,3178 .nav = .none,
3163 };3179 };
3164 },3180 },
...@@ -3170,7 +3186,7 @@ pub fn createTypeName(...@@ -3170,7 +3186,7 @@ pub fn createTypeName(
3170 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {3186 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {
3171 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {3187 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {
3172 return .{3188 return .{
3173 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.{s}", .{3189 .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{
3174 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),3190 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
3175 }, .no_embedded_nulls),3191 }, .no_embedded_nulls),
3176 .nav = .none,3192 .nav = .none,
...@@ -3193,7 +3209,7 @@ pub fn createTypeName(...@@ -3193,7 +3209,7 @@ pub fn createTypeName(
3193 // that builtin from the language, we can consider this.3209 // that builtin from the language, we can consider this.
31943210
3195 return .{3211 return .{
3196 .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}__{s}_{d}", .{3212 .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}__{s}_{d}", .{
3197 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),3213 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
3198 }, .no_embedded_nulls),3214 }, .no_embedded_nulls),
3199 .nav = .none,3215 .nav = .none,
...@@ -3211,8 +3227,11 @@ fn zirEnumDecl(...@@ -3211,8 +3227,11 @@ fn zirEnumDecl(
32113227
3212 const pt = sema.pt;3228 const pt = sema.pt;
3213 const zcu = pt.zcu;3229 const zcu = pt.zcu;
3214 const gpa = sema.gpa;3230 const comp = zcu.comp;
3231 const gpa = comp.gpa;
3232 const io = comp.io;
3215 const ip = &zcu.intern_pool;3233 const ip = &zcu.intern_pool;
3234
3216 const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small);3235 const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small);
3217 const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand);3236 const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand);
3218 var extra_index: usize = extra.end;3237 var extra_index: usize = extra.end;
...@@ -3281,7 +3300,7 @@ fn zirEnumDecl(...@@ -3281,7 +3300,7 @@ fn zirEnumDecl(
3281 .captures = captures,3300 .captures = captures,
3282 } },3301 } },
3283 };3302 };
3284 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) {3303 const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, enum_init, false)) {
3285 .existing => |ty| {3304 .existing => |ty| {
3286 const new_ty = try pt.ensureTypeUpToDate(ty);3305 const new_ty = try pt.ensureTypeUpToDate(ty);
32873306
...@@ -3380,8 +3399,11 @@ fn zirUnionDecl(...@@ -3380,8 +3399,11 @@ fn zirUnionDecl(
33803399
3381 const pt = sema.pt;3400 const pt = sema.pt;
3382 const zcu = pt.zcu;3401 const zcu = pt.zcu;
3383 const gpa = sema.gpa;3402 const comp = zcu.comp;
3403 const gpa = comp.gpa;
3404 const io = comp.io;
3384 const ip = &zcu.intern_pool;3405 const ip = &zcu.intern_pool;
3406
3385 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);3407 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
3386 const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand);3408 const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand);
3387 var extra_index: usize = extra.end;3409 var extra_index: usize = extra.end;
...@@ -3438,7 +3460,7 @@ fn zirUnionDecl(...@@ -3438,7 +3460,7 @@ fn zirUnionDecl(
3438 .captures = captures,3460 .captures = captures,
3439 } },3461 } },
3440 };3462 };
3441 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) {3463 const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, union_init, false)) {
3442 .existing => |ty| {3464 .existing => |ty| {
3443 const new_ty = try pt.ensureTypeUpToDate(ty);3465 const new_ty = try pt.ensureTypeUpToDate(ty);
34443466
...@@ -3503,7 +3525,9 @@ fn zirOpaqueDecl(...@@ -3503,7 +3525,9 @@ fn zirOpaqueDecl(
35033525
3504 const pt = sema.pt;3526 const pt = sema.pt;
3505 const zcu = pt.zcu;3527 const zcu = pt.zcu;
3506 const gpa = sema.gpa;3528 const comp = zcu.comp;
3529 const gpa = comp.gpa;
3530 const io = comp.io;
3507 const ip = &zcu.intern_pool;3531 const ip = &zcu.intern_pool;
35083532
3509 const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small);3533 const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small);
...@@ -3532,7 +3556,7 @@ fn zirOpaqueDecl(...@@ -3532,7 +3556,7 @@ fn zirOpaqueDecl(
3532 .zir_index = tracked_inst,3556 .zir_index = tracked_inst,
3533 .captures = captures,3557 .captures = captures,
3534 };3558 };
3535 const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) {3559 const wip_ty = switch (try ip.getOpaqueType(gpa, io, pt.tid, opaque_init)) {
3536 .existing => |ty| {3560 .existing => |ty| {
3537 // Make sure we update the namespace if the declaration is re-analyzed, to pick3561 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3538 // up on e.g. changed comptime decls.3562 // up on e.g. changed comptime decls.
...@@ -3587,7 +3611,10 @@ fn zirErrorSetDecl(...@@ -3587,7 +3611,10 @@ fn zirErrorSetDecl(
35873611
3588 const pt = sema.pt;3612 const pt = sema.pt;
3589 const zcu = pt.zcu;3613 const zcu = pt.zcu;
3590 const gpa = sema.gpa;3614 const comp = zcu.comp;
3615 const gpa = comp.gpa;
3616 const io = comp.io;
3617
3591 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;3618 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
3592 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);3619 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
35933620
...@@ -3599,7 +3626,7 @@ fn zirErrorSetDecl(...@@ -3599,7 +3626,7 @@ fn zirErrorSetDecl(
3599 while (extra_index < extra_index_end) : (extra_index += 1) {3626 while (extra_index < extra_index_end) : (extra_index += 1) {
3600 const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);3627 const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
3601 const name = sema.code.nullTerminatedString(name_index);3628 const name = sema.code.nullTerminatedString(name_index);
3602 const name_ip = try zcu.intern_pool.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);3629 const name_ip = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls);
3603 _ = try pt.getErrorValue(name_ip);3630 _ = try pt.getErrorValue(name_ip);
3604 const result = names.getOrPutAssumeCapacity(name_ip);3631 const result = names.getOrPutAssumeCapacity(name_ip);
3605 assert(!result.found_existing); // verified in AstGen3632 assert(!result.found_existing); // verified in AstGen
...@@ -3761,11 +3788,14 @@ fn indexablePtrLen(...@@ -3761,11 +3788,14 @@ fn indexablePtrLen(
3761) CompileError!Air.Inst.Ref {3788) CompileError!Air.Inst.Ref {
3762 const pt = sema.pt;3789 const pt = sema.pt;
3763 const zcu = pt.zcu;3790 const zcu = pt.zcu;
3791 const comp = zcu.comp;
3792 const gpa = comp.gpa;
3793 const io = comp.io;
3764 const object_ty = sema.typeOf(object);3794 const object_ty = sema.typeOf(object);
3765 const is_pointer_to = object_ty.isSinglePointer(zcu);3795 const is_pointer_to = object_ty.isSinglePointer(zcu);
3766 const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty;3796 const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty;
3767 try sema.checkIndexable(block, src, indexable_ty);3797 try sema.checkIndexable(block, src, indexable_ty);
3768 const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "len", .no_embedded_nulls);3798 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls);
3769 return sema.fieldVal(block, src, object, field_name, src);3799 return sema.fieldVal(block, src, object, field_name, src);
3770}3800}
37713801
...@@ -3777,13 +3807,16 @@ fn indexablePtrLenOrNone(...@@ -3777,13 +3807,16 @@ fn indexablePtrLenOrNone(
3777) CompileError!Air.Inst.Ref {3807) CompileError!Air.Inst.Ref {
3778 const pt = sema.pt;3808 const pt = sema.pt;
3779 const zcu = pt.zcu;3809 const zcu = pt.zcu;
3810 const comp = zcu.comp;
3811 const gpa = comp.gpa;
3812 const io = comp.io;
3780 const operand_ty = sema.typeOf(operand);3813 const operand_ty = sema.typeOf(operand);
3781 try checkMemOperand(sema, block, src, operand_ty);3814 try checkMemOperand(sema, block, src, operand_ty);
3782 switch (operand_ty.ptrSize(zcu)) {3815 switch (operand_ty.ptrSize(zcu)) {
3783 .many, .c => return .none,3816 .many, .c => return .none,
3784 .one, .slice => {},3817 .one, .slice => {},
3785 }3818 }
3786 const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "len", .no_embedded_nulls);3819 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls);
3787 return sema.fieldVal(block, src, operand, field_name, src);3820 return sema.fieldVal(block, src, operand, field_name, src);
3788}3821}
37893822
...@@ -3961,6 +3994,9 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -3961,6 +3994,9 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
3961fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, resolved_alloc_ty: ?Type) CompileError!?InternPool.Index {3994fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, resolved_alloc_ty: ?Type) CompileError!?InternPool.Index {
3962 const pt = sema.pt;3995 const pt = sema.pt;
3963 const zcu = pt.zcu;3996 const zcu = pt.zcu;
3997 const comp = zcu.comp;
3998 const gpa = comp.gpa;
3999 const io = comp.io;
39644000
3965 const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc);4001 const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc);
3966 const ptr_info = alloc_ty.ptrInfo(zcu);4002 const ptr_info = alloc_ty.ptrInfo(zcu);
...@@ -4108,7 +4144,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,...@@ -4108,7 +4144,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
4108 };4144 };
4109 const new_ptr_ty = tmp_air.typeOfIndex(air_ptr, &zcu.intern_pool).toIntern();4145 const new_ptr_ty = tmp_air.typeOfIndex(air_ptr, &zcu.intern_pool).toIntern();
4110 const new_ptr = switch (method) {4146 const new_ptr = switch (method) {
4111 .same_addr => try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, decl_parent_ptr, new_ptr_ty),4147 .same_addr => try zcu.intern_pool.getCoerced(gpa, io, pt.tid, decl_parent_ptr, new_ptr_ty),
4112 .opt_payload => ptr: {4148 .opt_payload => ptr: {
4113 // Set the optional to non-null at comptime.4149 // Set the optional to non-null at comptime.
4114 // If the payload is OPV, we must use that value instead of undef.4150 // If the payload is OPV, we must use that value instead of undef.
...@@ -4523,8 +4559,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4523,8 +4559,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4523fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4559fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
4524 const pt = sema.pt;4560 const pt = sema.pt;
4525 const zcu = pt.zcu;4561 const zcu = pt.zcu;
4526 const gpa = sema.gpa;4562 const comp = zcu.comp;
4563 const gpa = comp.gpa;
4564 const io = comp.io;
4527 const ip = &zcu.intern_pool;4565 const ip = &zcu.intern_pool;
4566
4528 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;4567 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
4529 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);4568 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
4530 const all_args = sema.code.refSlice(extra.end, extra.data.operands_len);4569 const all_args = sema.code.refSlice(extra.end, extra.data.operands_len);
...@@ -4570,7 +4609,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -4570,7 +4609,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
4570 return sema.failWithOwnedErrorMsg(block, msg);4609 return sema.failWithOwnedErrorMsg(block, msg);
4571 }4610 }
4572 if (!object_ty.indexableHasLen(zcu)) continue;4611 if (!object_ty.indexableHasLen(zcu)) continue;
4573 break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls), arg_src);4612 break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), arg_src);
4574 } else l: {4613 } else l: {
4575 // This argument is a range.4614 // This argument is a range.
4576 const range_start = try sema.resolveInst(zir_arg_pair[0]);4615 const range_start = try sema.resolveInst(zir_arg_pair[0]);
...@@ -4733,6 +4772,10 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -4733,6 +4772,10 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
4733fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref {4772fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref {
4734 const pt = sema.pt;4773 const pt = sema.pt;
4735 const zcu = pt.zcu;4774 const zcu = pt.zcu;
4775 const comp = zcu.comp;
4776 const gpa = comp.gpa;
4777 const io = comp.io;
4778
4736 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;4779 const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
4737 const src = block.nodeOffset(un_node.src_node);4780 const src = block.nodeOffset(un_node.src_node);
47384781
...@@ -4758,7 +4801,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo...@@ -4758,7 +4801,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo
4758 // This function cannot return an error.4801 // This function cannot return an error.
4759 // `try` is still valid if the error case is impossible, i.e. no error is returned.4802 // `try` is still valid if the error case is impossible, i.e. no error is returned.
4760 // So, the result type has an error set of `error{}`.4803 // So, the result type has an error set of `error{}`.
4761 break :err_set .fromInterned(try zcu.intern_pool.getErrorSetType(zcu.gpa, pt.tid, &.{}));4804 break :err_set .fromInterned(try zcu.intern_pool.getErrorSetType(gpa, io, pt.tid, &.{}));
4762 },4805 },
4763 }4806 }
4764 }4807 }
...@@ -5003,7 +5046,9 @@ fn validateStructInit(...@@ -5003,7 +5046,9 @@ fn validateStructInit(
5003) CompileError!void {5046) CompileError!void {
5004 const pt = sema.pt;5047 const pt = sema.pt;
5005 const zcu = pt.zcu;5048 const zcu = pt.zcu;
5006 const gpa = sema.gpa;5049 const comp = zcu.comp;
5050 const gpa = comp.gpa;
5051 const io = comp.io;
5007 const ip = &zcu.intern_pool;5052 const ip = &zcu.intern_pool;
50085053
5009 // Tracks whether each field was explicitly initialized.5054 // Tracks whether each field was explicitly initialized.
...@@ -5017,6 +5062,7 @@ fn validateStructInit(...@@ -5017,6 +5062,7 @@ fn validateStructInit(
5017 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;5062 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
5018 const field_name = try ip.getOrPutString(5063 const field_name = try ip.getOrPutString(
5019 gpa,5064 gpa,
5065 io,
5020 pt.tid,5066 pt.tid,
5021 sema.code.nullTerminatedString(field_ptr_extra.field_name_start),5067 sema.code.nullTerminatedString(field_ptr_extra.field_name_start),
5022 .no_embedded_nulls,5068 .no_embedded_nulls,
...@@ -5461,9 +5507,15 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v...@@ -5461,9 +5507,15 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
5461}5507}
54625508
5463fn zirStr(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5509fn zirStr(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
5510 const pt = sema.pt;
5511 const zcu = pt.zcu;
5512 const comp = zcu.comp;
5513 const gpa = comp.gpa;
5514 const io = comp.io;
5515 const ip = &zcu.intern_pool;
5464 const bytes = sema.code.instructions.items(.data)[@intFromEnum(inst)].str.get(sema.code);5516 const bytes = sema.code.instructions.items(.data)[@intFromEnum(inst)].str.get(sema.code);
5465 return sema.addStrLit(5517 return sema.addStrLit(
5466 try sema.pt.zcu.intern_pool.getOrPutString(sema.gpa, sema.pt.tid, bytes, .maybe_embedded_nulls),5518 try ip.getOrPutString(gpa, io, pt.tid, bytes, .maybe_embedded_nulls),
5467 bytes.len,5519 bytes.len,
5468 );5520 );
5469}5521}
...@@ -5555,7 +5607,9 @@ fn zirCompileLog(...@@ -5555,7 +5607,9 @@ fn zirCompileLog(
5555) CompileError!Air.Inst.Ref {5607) CompileError!Air.Inst.Ref {
5556 const pt = sema.pt;5608 const pt = sema.pt;
5557 const zcu = pt.zcu;5609 const zcu = pt.zcu;
5558 const gpa = zcu.gpa;5610 const comp = zcu.comp;
5611 const gpa = comp.gpa;
5612 const io = comp.io;
55595613
5560 var aw: std.Io.Writer.Allocating = .init(gpa);5614 var aw: std.Io.Writer.Allocating = .init(gpa);
5561 defer aw.deinit();5615 defer aw.deinit();
...@@ -5579,7 +5633,7 @@ fn zirCompileLog(...@@ -5579,7 +5633,7 @@ fn zirCompileLog(
5579 }5633 }
5580 }5634 }
55815635
5582 const line_data = try zcu.intern_pool.getOrPutString(gpa, pt.tid, aw.written(), .no_embedded_nulls);5636 const line_data = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls);
55835637
5584 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {5638 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: {
5585 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{5639 zcu.compile_log_lines.items[@intFromEnum(idx)] = .{
...@@ -5757,7 +5811,9 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -5757,7 +5811,9 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
5757 const pt = sema.pt;5811 const pt = sema.pt;
5758 const zcu = pt.zcu;5812 const zcu = pt.zcu;
5759 const comp = zcu.comp;5813 const comp = zcu.comp;
5760 const gpa = sema.gpa;5814 const gpa = comp.gpa;
5815 const io = comp.io;
5816
5761 const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;5817 const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
5762 const src = parent_block.nodeOffset(pl_node.src_node);5818 const src = parent_block.nodeOffset(pl_node.src_node);
5763 const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index);5819 const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index);
...@@ -5846,7 +5902,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -5846,7 +5902,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
5846 errdefer c_import_file_path.deinit(gpa);5902 errdefer c_import_file_path.deinit(gpa);
5847 const c_import_file = try gpa.create(Zcu.File);5903 const c_import_file = try gpa.create(Zcu.File);
5848 errdefer gpa.destroy(c_import_file);5904 errdefer gpa.destroy(c_import_file);
5849 const c_import_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{5905 const c_import_file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{
5850 .bin_digest = c_import_file_path.digest(),5906 .bin_digest = c_import_file_path.digest(),
5851 .file = c_import_file,5907 .file = c_import_file,
5852 .root_type = .none,5908 .root_type = .none,
...@@ -6350,6 +6406,7 @@ pub fn analyzeExport(...@@ -6350,6 +6406,7 @@ pub fn analyzeExport(
6350fn zirDisableInstrumentation(sema: *Sema) CompileError!void {6406fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
6351 const pt = sema.pt;6407 const pt = sema.pt;
6352 const zcu = pt.zcu;6408 const zcu = pt.zcu;
6409 const io = zcu.comp.io;
6353 const ip = &zcu.intern_pool;6410 const ip = &zcu.intern_pool;
6354 const func = switch (sema.owner.unwrap()) {6411 const func = switch (sema.owner.unwrap()) {
6355 .func => |func| func,6412 .func => |func| func,
...@@ -6360,13 +6417,14 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {...@@ -6360,13 +6417,14 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
6360 .memoized_state,6417 .memoized_state,
6361 => return, // does nothing outside a function6418 => return, // does nothing outside a function
6362 };6419 };
6363 ip.funcSetDisableInstrumentation(func);6420 ip.funcSetDisableInstrumentation(io, func);
6364 sema.allow_memoize = false;6421 sema.allow_memoize = false;
6365}6422}
63666423
6367fn zirDisableIntrinsics(sema: *Sema) CompileError!void {6424fn zirDisableIntrinsics(sema: *Sema) CompileError!void {
6368 const pt = sema.pt;6425 const pt = sema.pt;
6369 const zcu = pt.zcu;6426 const zcu = pt.zcu;
6427 const io = zcu.comp.io;
6370 const ip = &zcu.intern_pool;6428 const ip = &zcu.intern_pool;
6371 const func = switch (sema.owner.unwrap()) {6429 const func = switch (sema.owner.unwrap()) {
6372 .func => |func| func,6430 .func => |func| func,
...@@ -6377,7 +6435,7 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void {...@@ -6377,7 +6435,7 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void {
6377 .memoized_state,6435 .memoized_state,
6378 => return, // does nothing outside a function6436 => return, // does nothing outside a function
6379 };6437 };
6380 ip.funcSetDisableIntrinsics(func);6438 ip.funcSetDisableIntrinsics(io, func);
6381 sema.allow_memoize = false;6439 sema.allow_memoize = false;
6382}6440}
63836441
...@@ -6576,10 +6634,15 @@ pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!Air.NullTer...@@ -6576,10 +6634,15 @@ pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!Air.NullTer
6576fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6634fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6577 const pt = sema.pt;6635 const pt = sema.pt;
6578 const zcu = pt.zcu;6636 const zcu = pt.zcu;
6637 const comp = zcu.comp;
6638 const gpa = comp.gpa;
6639 const io = comp.io;
6640
6579 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;6641 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
6580 const src = block.tokenOffset(inst_data.src_tok);6642 const src = block.tokenOffset(inst_data.src_tok);
6581 const decl_name = try zcu.intern_pool.getOrPutString(6643 const decl_name = try zcu.intern_pool.getOrPutString(
6582 sema.gpa,6644 gpa,
6645 io,
6583 pt.tid,6646 pt.tid,
6584 inst_data.get(sema.code),6647 inst_data.get(sema.code),
6585 .no_embedded_nulls,6648 .no_embedded_nulls,
...@@ -6591,10 +6654,15 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -6591,10 +6654,15 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
6591fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6654fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6592 const pt = sema.pt;6655 const pt = sema.pt;
6593 const zcu = pt.zcu;6656 const zcu = pt.zcu;
6657 const comp = zcu.comp;
6658 const gpa = comp.gpa;
6659 const io = comp.io;
6660
6594 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;6661 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
6595 const src = block.tokenOffset(inst_data.src_tok);6662 const src = block.tokenOffset(inst_data.src_tok);
6596 const decl_name = try zcu.intern_pool.getOrPutString(6663 const decl_name = try zcu.intern_pool.getOrPutString(
6597 sema.gpa,6664 gpa,
6665 io,
6598 pt.tid,6666 pt.tid,
6599 inst_data.get(sema.code),6667 inst_data.get(sema.code),
6600 .no_embedded_nulls,6668 .no_embedded_nulls,
...@@ -6683,7 +6751,9 @@ fn funcDeclSrcInst(sema: *Sema, func_inst: Air.Inst.Ref) !?InternPool.TrackedIns...@@ -6683,7 +6751,9 @@ fn funcDeclSrcInst(sema: *Sema, func_inst: Air.Inst.Ref) !?InternPool.TrackedIns
6683pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {6751pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {
6684 const pt = sema.pt;6752 const pt = sema.pt;
6685 const zcu = pt.zcu;6753 const zcu = pt.zcu;
6686 const gpa = sema.gpa;6754 const comp = zcu.comp;
6755 const gpa = comp.gpa;
6756 const io = comp.io;
66876757
6688 if (block.isComptime() or block.is_typeof) {6758 if (block.isComptime() or block.is_typeof) {
6689 const index_val = try pt.intValue_u64(.usize, sema.comptime_err_ret_trace.items.len);6759 const index_val = try pt.intValue_u64(.usize, sema.comptime_err_ret_trace.items.len);
...@@ -6694,7 +6764,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref...@@ -6694,7 +6764,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
66946764
6695 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);6765 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
6696 try stack_trace_ty.resolveFields(pt);6766 try stack_trace_ty.resolveFields(pt);
6697 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);6767 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
6698 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {6768 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
6699 error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),6769 error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),
6700 error.ComptimeReturn, error.ComptimeBreak => unreachable,6770 error.ComptimeReturn, error.ComptimeBreak => unreachable,
...@@ -6721,7 +6791,9 @@ fn popErrorReturnTrace(...@@ -6721,7 +6791,9 @@ fn popErrorReturnTrace(
6721) CompileError!void {6791) CompileError!void {
6722 const pt = sema.pt;6792 const pt = sema.pt;
6723 const zcu = pt.zcu;6793 const zcu = pt.zcu;
6724 const gpa = sema.gpa;6794 const comp = zcu.comp;
6795 const gpa = comp.gpa;
6796 const io = comp.io;
6725 var is_non_error: ?bool = null;6797 var is_non_error: ?bool = null;
6726 var is_non_error_inst: Air.Inst.Ref = undefined;6798 var is_non_error_inst: Air.Inst.Ref = undefined;
6727 if (operand != .none) {6799 if (operand != .none) {
...@@ -6738,7 +6810,7 @@ fn popErrorReturnTrace(...@@ -6738,7 +6810,7 @@ fn popErrorReturnTrace(
6738 try stack_trace_ty.resolveFields(pt);6810 try stack_trace_ty.resolveFields(pt);
6739 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);6811 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
6740 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);6812 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
6741 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);6813 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
6742 const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true);6814 const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true);
6743 try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store);6815 try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store);
6744 } else if (is_non_error == null) {6816 } else if (is_non_error == null) {
...@@ -6764,7 +6836,7 @@ fn popErrorReturnTrace(...@@ -6764,7 +6836,7 @@ fn popErrorReturnTrace(
6764 try stack_trace_ty.resolveFields(pt);6836 try stack_trace_ty.resolveFields(pt);
6765 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);6837 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
6766 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);6838 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
6767 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);6839 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
6768 const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true);6840 const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true);
6769 try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store);6841 try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store);
6770 _ = try then_block.addBr(cond_block_inst, .void_value);6842 _ = try then_block.addBr(cond_block_inst, .void_value);
...@@ -6818,6 +6890,10 @@ fn zirCall(...@@ -6818,6 +6890,10 @@ fn zirCall(
68186890
6819 const pt = sema.pt;6891 const pt = sema.pt;
6820 const zcu = pt.zcu;6892 const zcu = pt.zcu;
6893 const comp = zcu.comp;
6894 const gpa = comp.gpa;
6895 const io = comp.io;
6896
6821 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;6897 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
6822 const callee_src = block.src(.{ .node_offset_call_func = inst_data.src_node });6898 const callee_src = block.src(.{ .node_offset_call_func = inst_data.src_node });
6823 const call_src = block.nodeOffset(inst_data.src_node);6899 const call_src = block.nodeOffset(inst_data.src_node);
...@@ -6837,7 +6913,8 @@ fn zirCall(...@@ -6837,7 +6913,8 @@ fn zirCall(
6837 .field => blk: {6913 .field => blk: {
6838 const object_ptr = try sema.resolveInst(extra.data.obj_ptr);6914 const object_ptr = try sema.resolveInst(extra.data.obj_ptr);
6839 const field_name = try zcu.intern_pool.getOrPutString(6915 const field_name = try zcu.intern_pool.getOrPutString(
6840 sema.gpa,6916 gpa,
6917 io,
6841 pt.tid,6918 pt.tid,
6842 sema.code.nullTerminatedString(extra.data.field_name_start),6919 sema.code.nullTerminatedString(extra.data.field_name_start),
6843 .no_embedded_nulls,6920 .no_embedded_nulls,
...@@ -6897,7 +6974,7 @@ fn zirCall(...@@ -6897,7 +6974,7 @@ fn zirCall(
6897 if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) {6974 if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) {
6898 const stack_trace_ty = try sema.getBuiltinType(call_src, .StackTrace);6975 const stack_trace_ty = try sema.getBuiltinType(call_src, .StackTrace);
6899 try stack_trace_ty.resolveFields(pt);6976 try stack_trace_ty.resolveFields(pt);
6900 const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "index", .no_embedded_nulls);6977 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
6901 const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);6978 const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);
69026979
6903 // Insert a save instruction before the arg resolution + call instructions we just generated6980 // Insert a save instruction before the arg resolution + call instructions we just generated
...@@ -7232,7 +7309,9 @@ fn analyzeCall(...@@ -7232,7 +7309,9 @@ fn analyzeCall(
7232) CompileError!Air.Inst.Ref {7309) CompileError!Air.Inst.Ref {
7233 const pt = sema.pt;7310 const pt = sema.pt;
7234 const zcu = pt.zcu;7311 const zcu = pt.zcu;
7235 const gpa = zcu.gpa;7312 const comp = zcu.comp;
7313 const gpa = comp.gpa;
7314 const io = comp.io;
7236 const ip = &zcu.intern_pool;7315 const ip = &zcu.intern_pool;
7237 const arena = sema.arena;7316 const arena = sema.arena;
72387317
...@@ -7544,7 +7623,7 @@ fn analyzeCall(...@@ -7544,7 +7623,7 @@ fn analyzeCall(
7544 if (func_ty_info.cc == .auto) {7623 if (func_ty_info.cc == .auto) {
7545 switch (sema.owner.unwrap()) {7624 switch (sema.owner.unwrap()) {
7546 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},7625 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
7547 .func => |owner_func| ip.funcSetHasErrorTrace(owner_func, true),7626 .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true),
7548 }7627 }
7549 }7628 }
7550 for (args, 0..) |arg, arg_idx| {7629 for (args, 0..) |arg, arg_idx| {
...@@ -7596,7 +7675,7 @@ fn analyzeCall(...@@ -7596,7 +7675,7 @@ fn analyzeCall(
7596 } else resolved_ret_ty;7675 } else resolved_ret_ty;
75977676
7598 // We now need to actually create the function instance.7677 // We now need to actually create the function instance.
7599 const func_instance = try ip.getFuncInstance(gpa, pt.tid, .{7678 const func_instance = try ip.getFuncInstance(gpa, io, pt.tid, .{
7600 .param_types = runtime_param_tys.items,7679 .param_types = runtime_param_tys.items,
7601 .noalias_bits = noalias_bits,7680 .noalias_bits = noalias_bits,
7602 .bare_return_type = bare_ret_ty.toIntern(),7681 .bare_return_type = bare_ret_ty.toIntern(),
...@@ -7614,7 +7693,7 @@ fn analyzeCall(...@@ -7614,7 +7693,7 @@ fn analyzeCall(
7614 // This call is problematic as it breaks guarantees about order-independency of semantic analysis.7693 // This call is problematic as it breaks guarantees about order-independency of semantic analysis.
7615 // These guarantees are necessary for incremental compilation and parallel semantic analysis.7694 // These guarantees are necessary for incremental compilation and parallel semantic analysis.
7616 // See: #224107695 // See: #22410
7617 zcu.funcInfo(func_instance).maxBranchQuota(ip, sema.branch_quota);7696 zcu.funcInfo(func_instance).maxBranchQuota(ip, io, sema.branch_quota);
76187697
7619 break :func .{ Air.internedToRef(func_instance), runtime_args.items };7698 break :func .{ Air.internedToRef(func_instance), runtime_args.items };
7620 };7699 };
...@@ -8102,6 +8181,9 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -8102,6 +8181,9 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
81028181
8103 const pt = sema.pt;8182 const pt = sema.pt;
8104 const zcu = pt.zcu;8183 const zcu = pt.zcu;
8184 const comp = zcu.comp;
8185 const gpa = comp.gpa;
8186 const io = comp.io;
8105 const ip = &zcu.intern_pool;8187 const ip = &zcu.intern_pool;
81068188
8107 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;8189 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
...@@ -8116,7 +8198,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -8116,7 +8198,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
8116 const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src);8198 const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src);
8117 const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel });8199 const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel });
8118 if (sentinel_val.canMutateComptimeVarState(zcu)) {8200 if (sentinel_val.canMutateComptimeVarState(zcu)) {
8119 const sentinel_name = try ip.getOrPutString(sema.gpa, pt.tid, "sentinel", .no_embedded_nulls);8201 const sentinel_name = try ip.getOrPutString(gpa, io, pt.tid, "sentinel", .no_embedded_nulls);
8120 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel_val);8202 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel_val);
8121 }8203 }
8122 const array_ty = try pt.arrayType(.{8204 const array_ty = try pt.arrayType(.{
...@@ -8194,10 +8276,17 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p...@@ -8194,10 +8276,17 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p
81948276
8195fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8277fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8196 _ = block;8278 _ = block;
8279
8197 const pt = sema.pt;8280 const pt = sema.pt;
8281 const zcu = pt.zcu;
8282 const comp = zcu.comp;
8283 const gpa = comp.gpa;
8284 const io = comp.io;
8285
8198 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;8286 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
8199 const name = try pt.zcu.intern_pool.getOrPutString(8287 const name = try pt.zcu.intern_pool.getOrPutString(
8200 sema.gpa,8288 gpa,
8289 io,
8201 pt.tid,8290 pt.tid,
8202 inst_data.get(sema.code),8291 inst_data.get(sema.code),
8203 .no_embedded_nulls,8292 .no_embedded_nulls,
...@@ -8259,7 +8348,9 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8259,7 +8348,9 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
82598348
8260 const pt = sema.pt;8349 const pt = sema.pt;
8261 const zcu = pt.zcu;8350 const zcu = pt.zcu;
8351 const io = zcu.comp.io;
8262 const ip = &zcu.intern_pool;8352 const ip = &zcu.intern_pool;
8353
8263 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;8354 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
8264 const src = block.nodeOffset(extra.node);8355 const src = block.nodeOffset(extra.node);
8265 const operand_src = block.builtinCallArgSrc(extra.node, 0);8356 const operand_src = block.builtinCallArgSrc(extra.node, 0);
...@@ -8271,8 +8362,8 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8271,8 +8362,8 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8271 const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt));8362 const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt));
8272 if (int > len: {8363 if (int > len: {
8273 const mutate = &ip.global_error_set.mutate;8364 const mutate = &ip.global_error_set.mutate;
8274 mutate.map.mutex.lock();8365 mutate.map.mutex.lockUncancelable(io);
8275 defer mutate.map.mutex.unlock();8366 defer mutate.map.mutex.unlock(io);
8276 break :len mutate.names.len;8367 break :len mutate.names.len;
8277 } or int == 0)8368 } or int == 0)
8278 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});8369 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
...@@ -8361,10 +8452,14 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8361,10 +8452,14 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
83618452
8362 const pt = sema.pt;8453 const pt = sema.pt;
8363 const zcu = pt.zcu;8454 const zcu = pt.zcu;
8455 const comp = zcu.comp;
8456 const gpa = comp.gpa;
8457 const io = comp.io;
8458
8364 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;8459 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
8365 const name = inst_data.get(sema.code);8460 const name = inst_data.get(sema.code);
8366 return Air.internedToRef((try pt.intern(.{8461 return Air.internedToRef((try pt.intern(.{
8367 .enum_literal = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, name, .no_embedded_nulls),8462 .enum_literal = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls),
8368 })));8463 })));
8369}8464}
83708465
...@@ -8374,11 +8469,16 @@ fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: b...@@ -8374,11 +8469,16 @@ fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: b
83748469
8375 const pt = sema.pt;8470 const pt = sema.pt;
8376 const zcu = pt.zcu;8471 const zcu = pt.zcu;
8472 const comp = zcu.comp;
8473 const gpa = comp.gpa;
8474 const io = comp.io;
8475
8377 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;8476 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
8378 const src = block.nodeOffset(inst_data.src_node);8477 const src = block.nodeOffset(inst_data.src_node);
8379 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;8478 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
8380 const name = try zcu.intern_pool.getOrPutString(8479 const name = try zcu.intern_pool.getOrPutString(
8381 sema.gpa,8480 gpa,
8481 io,
8382 pt.tid,8482 pt.tid,
8383 sema.code.nullTerminatedString(extra.field_name_start),8483 sema.code.nullTerminatedString(extra.field_name_start),
8384 .no_embedded_nulls,8484 .no_embedded_nulls,
...@@ -8915,7 +9015,11 @@ fn zirFunc(...@@ -8915,7 +9015,11 @@ fn zirFunc(
8915) CompileError!Air.Inst.Ref {9015) CompileError!Air.Inst.Ref {
8916 const pt = sema.pt;9016 const pt = sema.pt;
8917 const zcu = pt.zcu;9017 const zcu = pt.zcu;
9018 const comp = zcu.comp;
9019 const gpa = comp.gpa;
9020 const io = comp.io;
8918 const ip = &zcu.intern_pool;9021 const ip = &zcu.intern_pool;
9022
8919 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;9023 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
8920 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);9024 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
8921 const target = zcu.getTarget();9025 const target = zcu.getTarget();
...@@ -8970,7 +9074,7 @@ fn zirFunc(...@@ -8970,7 +9074,7 @@ fn zirFunc(
8970 block,9074 block,
8971 LazySrcLoc.unneeded,9075 LazySrcLoc.unneeded,
8972 cc_type.getNamespaceIndex(zcu),9076 cc_type.getNamespaceIndex(zcu),
8973 try ip.getOrPutString(sema.gpa, pt.tid, "c", .no_embedded_nulls),9077 try ip.getOrPutString(gpa, io, pt.tid, "c", .no_embedded_nulls),
8974 );9078 );
8975 // The above should have errored.9079 // The above should have errored.
8976 @panic("std.builtin is corrupt");9080 @panic("std.builtin is corrupt");
...@@ -9443,8 +9547,11 @@ fn funcCommon(...@@ -9443,8 +9547,11 @@ fn funcCommon(
9443) CompileError!Air.Inst.Ref {9547) CompileError!Air.Inst.Ref {
9444 const pt = sema.pt;9548 const pt = sema.pt;
9445 const zcu = pt.zcu;9549 const zcu = pt.zcu;
9446 const gpa = sema.gpa;9550 const comp = zcu.comp;
9551 const gpa = comp.gpa;
9552 const io = comp.io;
9447 const ip = &zcu.intern_pool;9553 const ip = &zcu.intern_pool;
9554
9448 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset });9555 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset });
9449 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });9556 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });
9450 const func_src = block.nodeOffset(src_node_offset);9557 const func_src = block.nodeOffset(src_node_offset);
...@@ -9563,7 +9670,7 @@ fn funcCommon(...@@ -9563,7 +9670,7 @@ fn funcCommon(
95639670
9564 if (inferred_error_set) {9671 if (inferred_error_set) {
9565 assert(has_body);9672 assert(has_body);
9566 return .fromIntern(try ip.getFuncDeclIes(gpa, pt.tid, .{9673 return .fromIntern(try ip.getFuncDeclIes(gpa, io, pt.tid, .{
9567 .owner_nav = sema.owner.unwrap().nav_val,9674 .owner_nav = sema.owner.unwrap().nav_val,
95689675
9569 .param_types = param_types,9676 .param_types = param_types,
...@@ -9583,7 +9690,7 @@ fn funcCommon(...@@ -9583,7 +9690,7 @@ fn funcCommon(
9583 }));9690 }));
9584 }9691 }
95859692
9586 const func_ty = try ip.getFuncType(gpa, pt.tid, .{9693 const func_ty = try ip.getFuncType(gpa, io, pt.tid, .{
9587 .param_types = param_types,9694 .param_types = param_types,
9588 .noalias_bits = noalias_bits,9695 .noalias_bits = noalias_bits,
9589 .comptime_bits = comptime_bits,9696 .comptime_bits = comptime_bits,
...@@ -9595,7 +9702,7 @@ fn funcCommon(...@@ -9595,7 +9702,7 @@ fn funcCommon(
9595 });9702 });
95969703
9597 if (has_body) {9704 if (has_body) {
9598 return .fromIntern(try ip.getFuncDecl(gpa, pt.tid, .{9705 return .fromIntern(try ip.getFuncDecl(gpa, io, pt.tid, .{
9599 .owner_nav = sema.owner.unwrap().nav_val,9706 .owner_nav = sema.owner.unwrap().nav_val,
9600 .ty = func_ty,9707 .ty = func_ty,
9601 .cc = cc,9708 .cc = cc,
...@@ -9778,12 +9885,17 @@ fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -9778,12 +9885,17 @@ fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
97789885
9779 const pt = sema.pt;9886 const pt = sema.pt;
9780 const zcu = pt.zcu;9887 const zcu = pt.zcu;
9888 const comp = zcu.comp;
9889 const gpa = comp.gpa;
9890 const io = comp.io;
9891
9781 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;9892 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
9782 const src = block.nodeOffset(inst_data.src_node);9893 const src = block.nodeOffset(inst_data.src_node);
9783 const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node });9894 const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node });
9784 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;9895 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
9785 const field_name = try zcu.intern_pool.getOrPutString(9896 const field_name = try zcu.intern_pool.getOrPutString(
9786 sema.gpa,9897 gpa,
9898 io,
9787 pt.tid,9899 pt.tid,
9788 sema.code.nullTerminatedString(extra.field_name_start),9900 sema.code.nullTerminatedString(extra.field_name_start),
9789 .no_embedded_nulls,9901 .no_embedded_nulls,
...@@ -9798,12 +9910,17 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -9798,12 +9910,17 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
97989910
9799 const pt = sema.pt;9911 const pt = sema.pt;
9800 const zcu = pt.zcu;9912 const zcu = pt.zcu;
9913 const comp = zcu.comp;
9914 const gpa = comp.gpa;
9915 const io = comp.io;
9916
9801 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;9917 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
9802 const src = block.nodeOffset(inst_data.src_node);9918 const src = block.nodeOffset(inst_data.src_node);
9803 const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node });9919 const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node });
9804 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;9920 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
9805 const field_name = try zcu.intern_pool.getOrPutString(9921 const field_name = try zcu.intern_pool.getOrPutString(
9806 sema.gpa,9922 gpa,
9923 io,
9807 pt.tid,9924 pt.tid,
9808 sema.code.nullTerminatedString(extra.field_name_start),9925 sema.code.nullTerminatedString(extra.field_name_start),
9809 .no_embedded_nulls,9926 .no_embedded_nulls,
...@@ -9818,12 +9935,17 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi...@@ -9818,12 +9935,17 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
98189935
9819 const pt = sema.pt;9936 const pt = sema.pt;
9820 const zcu = pt.zcu;9937 const zcu = pt.zcu;
9938 const comp = zcu.comp;
9939 const gpa = comp.gpa;
9940 const io = comp.io;
9941
9821 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;9942 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
9822 const src = block.nodeOffset(inst_data.src_node);9943 const src = block.nodeOffset(inst_data.src_node);
9823 const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node });9944 const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node });
9824 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;9945 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
9825 const field_name = try zcu.intern_pool.getOrPutString(9946 const field_name = try zcu.intern_pool.getOrPutString(
9826 sema.gpa,9947 gpa,
9948 io,
9827 pt.tid,9949 pt.tid,
9828 sema.code.nullTerminatedString(extra.field_name_start),9950 sema.code.nullTerminatedString(extra.field_name_start),
9829 .no_embedded_nulls,9951 .no_embedded_nulls,
...@@ -13941,9 +14063,14 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -13941,9 +14063,14 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
13941fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {14063fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13942 const pt = sema.pt;14064 const pt = sema.pt;
13943 const zcu = pt.zcu;14065 const zcu = pt.zcu;
14066 const comp = zcu.comp;
14067 const gpa = comp.gpa;
14068 const io = comp.io;
14069
13944 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;14070 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
13945 const name = try zcu.intern_pool.getOrPutString(14071 const name = try zcu.intern_pool.getOrPutString(
13946 sema.gpa,14072 gpa,
14073 io,
13947 pt.tid,14074 pt.tid,
13948 inst_data.get(sema.code),14075 inst_data.get(sema.code),
13949 .no_embedded_nulls,14076 .no_embedded_nulls,
...@@ -14379,6 +14506,10 @@ fn analyzeTupleCat(...@@ -14379,6 +14506,10 @@ fn analyzeTupleCat(
14379) CompileError!Air.Inst.Ref {14506) CompileError!Air.Inst.Ref {
14380 const pt = sema.pt;14507 const pt = sema.pt;
14381 const zcu = pt.zcu;14508 const zcu = pt.zcu;
14509 const comp = zcu.comp;
14510 const gpa = comp.gpa;
14511 const io = comp.io;
14512
14382 const lhs_ty = sema.typeOf(lhs);14513 const lhs_ty = sema.typeOf(lhs);
14383 const rhs_ty = sema.typeOf(rhs);14514 const rhs_ty = sema.typeOf(rhs);
14384 const src = block.nodeOffset(src_node);14515 const src = block.nodeOffset(src_node);
...@@ -14434,7 +14565,7 @@ fn analyzeTupleCat(...@@ -14434,7 +14565,7 @@ fn analyzeTupleCat(
14434 break :rs runtime_src;14565 break :rs runtime_src;
14435 };14566 };
1443614567
14437 const tuple_ty: Type = .fromInterned(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{14568 const tuple_ty: Type = .fromInterned(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{
14438 .types = types,14569 .types = types,
14439 .values = values,14570 .values = values,
14440 }));14571 }));
...@@ -14821,6 +14952,10 @@ fn analyzeTupleMul(...@@ -14821,6 +14952,10 @@ fn analyzeTupleMul(
14821) CompileError!Air.Inst.Ref {14952) CompileError!Air.Inst.Ref {
14822 const pt = sema.pt;14953 const pt = sema.pt;
14823 const zcu = pt.zcu;14954 const zcu = pt.zcu;
14955 const comp = zcu.comp;
14956 const gpa = comp.gpa;
14957 const io = comp.io;
14958
14824 const operand_ty = sema.typeOf(operand);14959 const operand_ty = sema.typeOf(operand);
14825 const src = block.nodeOffset(src_node);14960 const src = block.nodeOffset(src_node);
14826 const len_src = block.src(.{ .node_offset_bin_rhs = src_node });14961 const len_src = block.src(.{ .node_offset_bin_rhs = src_node });
...@@ -14856,7 +14991,7 @@ fn analyzeTupleMul(...@@ -14856,7 +14991,7 @@ fn analyzeTupleMul(
14856 break :rs runtime_src;14991 break :rs runtime_src;
14857 };14992 };
1485814993
14859 const tuple_ty: Type = .fromInterned(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{14994 const tuple_ty: Type = .fromInterned(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{
14860 .types = types,14995 .types = types,
14861 .values = values,14996 .values = values,
14862 }));14997 }));
...@@ -16388,7 +16523,11 @@ fn zirAsm(...@@ -16388,7 +16523,11 @@ fn zirAsm(
1638816523
16389 const pt = sema.pt;16524 const pt = sema.pt;
16390 const zcu = pt.zcu;16525 const zcu = pt.zcu;
16526 const comp = zcu.comp;
16527 const gpa = comp.gpa;
16528 const io = comp.io;
16391 const ip = &zcu.intern_pool;16529 const ip = &zcu.intern_pool;
16530
16392 const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand);16531 const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand);
16393 const src = block.nodeOffset(extra.data.src_node);16532 const src = block.nodeOffset(extra.data.src_node);
16394 const ret_ty_src = block.src(.{ .node_offset_asm_ret_ty = extra.data.src_node });16533 const ret_ty_src = block.src(.{ .node_offset_asm_ret_ty = extra.data.src_node });
...@@ -16445,7 +16584,7 @@ fn zirAsm(...@@ -16445,7 +16584,7 @@ fn zirAsm(
16445 } else {16584 } else {
16446 const inst = try sema.resolveInst(output.data.operand);16585 const inst = try sema.resolveInst(output.data.operand);
16447 if (!sema.checkRuntimeValue(inst)) {16586 if (!sema.checkRuntimeValue(inst)) {
16448 const output_name = try ip.getOrPutString(sema.gpa, pt.tid, name, .no_embedded_nulls);16587 const output_name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls);
16449 return sema.failWithContainsReferenceToComptimeVar(block, output_src, output_name, "assembly output", .fromInterned(inst.toInterned().?));16588 return sema.failWithContainsReferenceToComptimeVar(block, output_src, output_name, "assembly output", .fromInterned(inst.toInterned().?));
16450 }16589 }
16451 arg.* = inst;16590 arg.* = inst;
...@@ -16476,7 +16615,7 @@ fn zirAsm(...@@ -16476,7 +16615,7 @@ fn zirAsm(
16476 const uncasted_arg = try sema.resolveInst(input.data.operand);16615 const uncasted_arg = try sema.resolveInst(input.data.operand);
16477 const name = sema.code.nullTerminatedString(input.data.name);16616 const name = sema.code.nullTerminatedString(input.data.name);
16478 if (!sema.checkRuntimeValue(uncasted_arg)) {16617 if (!sema.checkRuntimeValue(uncasted_arg)) {
16479 const input_name = try ip.getOrPutString(sema.gpa, pt.tid, name, .no_embedded_nulls);16618 const input_name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls);
16480 return sema.failWithContainsReferenceToComptimeVar(block, input_src, input_name, "assembly input", .fromInterned(uncasted_arg.toInterned().?));16619 return sema.failWithContainsReferenceToComptimeVar(block, input_src, input_name, "assembly input", .fromInterned(uncasted_arg.toInterned().?));
16481 }16620 }
16482 const uncasted_arg_ty = sema.typeOf(uncasted_arg);16621 const uncasted_arg_ty = sema.typeOf(uncasted_arg);
...@@ -16500,7 +16639,6 @@ fn zirAsm(...@@ -16500,7 +16639,6 @@ fn zirAsm(
16500 const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber });16639 const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber });
16501 needed_capacity += asm_source.len / 4 + 1;16640 needed_capacity += asm_source.len / 4 + 1;
1650216641
16503 const gpa = sema.gpa;
16504 try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity);16642 try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity);
16505 const asm_air = try block.addInst(.{16643 const asm_air = try block.addInst(.{
16506 .tag = .assembly,16644 .tag = .assembly,
...@@ -17060,10 +17198,13 @@ fn zirBuiltinSrc(...@@ -17060,10 +17198,13 @@ fn zirBuiltinSrc(
1706017198
17061 const pt = sema.pt;17199 const pt = sema.pt;
17062 const zcu = pt.zcu;17200 const zcu = pt.zcu;
17201 const comp = zcu.comp;
17202 const gpa = comp.gpa;
17203 const io = comp.io;
17063 const ip = &zcu.intern_pool;17204 const ip = &zcu.intern_pool;
17205
17064 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;17206 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;
17065 const fn_name = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).name;17207 const fn_name = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).name;
17066 const gpa = sema.gpa;
17067 const file_scope = block.getFileScope(zcu);17208 const file_scope = block.getFileScope(zcu);
1706817209
17069 const func_name_val = v: {17210 const func_name_val = v: {
...@@ -17106,7 +17247,7 @@ fn zirBuiltinSrc(...@@ -17106,7 +17247,7 @@ fn zirBuiltinSrc(
17106 .val = try pt.intern(.{ .aggregate = .{17247 .val = try pt.intern(.{ .aggregate = .{
17107 .ty = array_ty,17248 .ty = array_ty,
17108 .storage = .{17249 .storage = .{
17109 .bytes = try ip.getOrPutString(gpa, pt.tid, module_name, .maybe_embedded_nulls),17250 .bytes = try ip.getOrPutString(gpa, io, pt.tid, module_name, .maybe_embedded_nulls),
17110 },17251 },
17111 } }),17252 } }),
17112 } },17253 } },
...@@ -17132,7 +17273,7 @@ fn zirBuiltinSrc(...@@ -17132,7 +17273,7 @@ fn zirBuiltinSrc(
17132 .val = try pt.intern(.{ .aggregate = .{17273 .val = try pt.intern(.{ .aggregate = .{
17133 .ty = array_ty,17274 .ty = array_ty,
17134 .storage = .{17275 .storage = .{
17135 .bytes = try ip.getOrPutString(gpa, pt.tid, file_name, .maybe_embedded_nulls),17276 .bytes = try ip.getOrPutString(gpa, io, pt.tid, file_name, .maybe_embedded_nulls),
17136 },17277 },
17137 } }),17278 } }),
17138 } },17279 } },
...@@ -17161,8 +17302,11 @@ fn zirBuiltinSrc(...@@ -17161,8 +17302,11 @@ fn zirBuiltinSrc(
17161fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {17302fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
17162 const pt = sema.pt;17303 const pt = sema.pt;
17163 const zcu = pt.zcu;17304 const zcu = pt.zcu;
17164 const gpa = sema.gpa;17305 const comp = zcu.comp;
17306 const gpa = comp.gpa;
17307 const io = comp.io;
17165 const ip = &zcu.intern_pool;17308 const ip = &zcu.intern_pool;
17309
17166 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;17310 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
17167 const src = block.nodeOffset(inst_data.src_node);17311 const src = block.nodeOffset(inst_data.src_node);
17168 const ty = try sema.resolveType(block, src, inst_data.operand);17312 const ty = try sema.resolveType(block, src, inst_data.operand);
...@@ -17511,7 +17655,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17511,7 +17655,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17511 const enum_type = ip.loadEnumType(ty.toIntern());17655 const enum_type = ip.loadEnumType(ty.toIntern());
17512 const value_val = if (enum_type.values.len > 0)17656 const value_val = if (enum_type.values.len > 0)
17513 try ip.getCoercedInts(17657 try ip.getCoercedInts(
17514 zcu.gpa,17658 gpa,
17659 io,
17515 pt.tid,17660 pt.tid,
17516 ip.indexToKey(enum_type.values.get(ip)[tag_index]).int,17661 ip.indexToKey(enum_type.values.get(ip)[tag_index]).int,
17517 .comptime_int_type,17662 .comptime_int_type,
...@@ -17729,7 +17874,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17729,7 +17874,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17729 const field_ty = tuple_type.types.get(ip)[field_index];17874 const field_ty = tuple_type.types.get(ip)[field_index];
17730 const field_val = tuple_type.values.get(ip)[field_index];17875 const field_val = tuple_type.values.get(ip)[field_index];
17731 const name_val = v: {17876 const name_val = v: {
17732 const field_name = try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);17877 const field_name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
17733 const field_name_len = field_name.length(ip);17878 const field_name_len = field_name.length(ip);
17734 const new_decl_ty = try pt.arrayType(.{17879 const new_decl_ty = try pt.arrayType(.{
17735 .len = field_name_len,17880 .len = field_name_len,
...@@ -18752,10 +18897,15 @@ fn zirRetErrValue(...@@ -18752,10 +18897,15 @@ fn zirRetErrValue(
18752) CompileError!void {18897) CompileError!void {
18753 const pt = sema.pt;18898 const pt = sema.pt;
18754 const zcu = pt.zcu;18899 const zcu = pt.zcu;
18900 const comp = zcu.comp;
18901 const gpa = comp.gpa;
18902 const io = comp.io;
18903
18755 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;18904 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
18756 const src = block.tokenOffset(inst_data.src_tok);18905 const src = block.tokenOffset(inst_data.src_tok);
18757 const err_name = try zcu.intern_pool.getOrPutString(18906 const err_name = try zcu.intern_pool.getOrPutString(
18758 sema.gpa,18907 gpa,
18908 io,
18759 pt.tid,18909 pt.tid,
18760 inst_data.get(sema.code),18910 inst_data.get(sema.code),
18761 .no_embedded_nulls,18911 .no_embedded_nulls,
...@@ -19121,6 +19271,9 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19121,6 +19271,9 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1912119271
19122 const pt = sema.pt;19272 const pt = sema.pt;
19123 const zcu = pt.zcu;19273 const zcu = pt.zcu;
19274 const comp = zcu.comp;
19275 const gpa = comp.gpa;
19276 const io = comp.io;
19124 const ip = &zcu.intern_pool;19277 const ip = &zcu.intern_pool;
1912519278
19126 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;19279 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;
...@@ -19158,7 +19311,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19158,7 +19311,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19158 const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .simple = .pointer_sentinel });19311 const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .simple = .pointer_sentinel });
19159 try checkSentinelType(sema, block, sentinel_src, elem_ty);19312 try checkSentinelType(sema, block, sentinel_src, elem_ty);
19160 if (val.canMutateComptimeVarState(zcu)) {19313 if (val.canMutateComptimeVarState(zcu)) {
19161 const sentinel_name = try ip.getOrPutString(sema.gpa, pt.tid, "sentinel", .no_embedded_nulls);19314 const sentinel_name = try ip.getOrPutString(gpa, io, pt.tid, "sentinel", .no_embedded_nulls);
19162 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", val);19315 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", val);
19163 }19316 }
19164 break :blk val.toIntern();19317 break :blk val.toIntern();
...@@ -19463,15 +19616,18 @@ fn zirStructInit(...@@ -19463,15 +19616,18 @@ fn zirStructInit(
19463 inst: Zir.Inst.Index,19616 inst: Zir.Inst.Index,
19464 is_ref: bool,19617 is_ref: bool,
19465) CompileError!Air.Inst.Ref {19618) CompileError!Air.Inst.Ref {
19466 const gpa = sema.gpa;19619 const pt = sema.pt;
19620 const zcu = pt.zcu;
19621 const comp = zcu.comp;
19622 const gpa = comp.gpa;
19623 const io = comp.io;
19624 const ip = &zcu.intern_pool;
19625
19467 const zir_datas = sema.code.instructions.items(.data);19626 const zir_datas = sema.code.instructions.items(.data);
19468 const inst_data = zir_datas[@intFromEnum(inst)].pl_node;19627 const inst_data = zir_datas[@intFromEnum(inst)].pl_node;
19469 const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);19628 const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
19470 const src = block.nodeOffset(inst_data.src_node);19629 const src = block.nodeOffset(inst_data.src_node);
1947119630
19472 const pt = sema.pt;
19473 const zcu = pt.zcu;
19474 const ip = &zcu.intern_pool;
19475 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;19631 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
19476 const first_field_type_data = zir_datas[@intFromEnum(first_item.field_type)].pl_node;19632 const first_field_type_data = zir_datas[@intFromEnum(first_item.field_type)].pl_node;
19477 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;19633 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;
...@@ -19513,6 +19669,7 @@ fn zirStructInit(...@@ -19513,6 +19669,7 @@ fn zirStructInit(
19513 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;19669 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
19514 const field_name = try ip.getOrPutString(19670 const field_name = try ip.getOrPutString(
19515 gpa,19671 gpa,
19672 io,
19516 pt.tid,19673 pt.tid,
19517 sema.code.nullTerminatedString(field_type_extra.name_start),19674 sema.code.nullTerminatedString(field_type_extra.name_start),
19518 .no_embedded_nulls,19675 .no_embedded_nulls,
...@@ -19554,6 +19711,7 @@ fn zirStructInit(...@@ -19554,6 +19711,7 @@ fn zirStructInit(
19554 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;19711 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
19555 const field_name = try ip.getOrPutString(19712 const field_name = try ip.getOrPutString(
19556 gpa,19713 gpa,
19714 io,
19557 pt.tid,19715 pt.tid,
19558 sema.code.nullTerminatedString(field_type_extra.name_start),19716 sema.code.nullTerminatedString(field_type_extra.name_start),
19559 .no_embedded_nulls,19717 .no_embedded_nulls,
...@@ -19797,8 +19955,11 @@ fn structInitAnon(...@@ -19797,8 +19955,11 @@ fn structInitAnon(
19797) CompileError!Air.Inst.Ref {19955) CompileError!Air.Inst.Ref {
19798 const pt = sema.pt;19956 const pt = sema.pt;
19799 const zcu = pt.zcu;19957 const zcu = pt.zcu;
19800 const gpa = sema.gpa;19958 const comp = zcu.comp;
19959 const gpa = comp.gpa;
19960 const io = comp.io;
19801 const ip = &zcu.intern_pool;19961 const ip = &zcu.intern_pool;
19962
19802 const zir_datas = sema.code.instructions.items(.data);19963 const zir_datas = sema.code.instructions.items(.data);
1980319964
19804 const types = try sema.arena.alloc(InternPool.Index, extra_data.fields_len);19965 const types = try sema.arena.alloc(InternPool.Index, extra_data.fields_len);
...@@ -19828,7 +19989,7 @@ fn structInitAnon(...@@ -19828,7 +19989,7 @@ fn structInitAnon(
19828 },19989 },
19829 };19990 };
1983019991
19831 field_name.* = try zcu.intern_pool.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);19992 field_name.* = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls);
1983219993
19833 const init = try sema.resolveInst(item.data.init);19994 const init = try sema.resolveInst(item.data.init);
19834 field_ty.* = sema.typeOf(init).toIntern();19995 field_ty.* = sema.typeOf(init).toIntern();
...@@ -19871,7 +20032,7 @@ fn structInitAnon(...@@ -19871,7 +20032,7 @@ fn structInitAnon(
19871 break :hash hasher.final();20032 break :hash hasher.final();
19872 };20033 };
19873 const tracked_inst = try block.trackZir(inst);20034 const tracked_inst = try block.trackZir(inst);
19874 const struct_ty = switch (try ip.getStructType(gpa, pt.tid, .{20035 const struct_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{
19875 .layout = .auto,20036 .layout = .auto,
19876 .fields_len = extra_data.fields_len,20037 .fields_len = extra_data.fields_len,
19877 .known_non_opv = false,20038 .known_non_opv = false,
...@@ -20131,7 +20292,9 @@ fn arrayInitAnon(...@@ -20131,7 +20292,9 @@ fn arrayInitAnon(
20131) CompileError!Air.Inst.Ref {20292) CompileError!Air.Inst.Ref {
20132 const pt = sema.pt;20293 const pt = sema.pt;
20133 const zcu = pt.zcu;20294 const zcu = pt.zcu;
20134 const gpa = sema.gpa;20295 const comp = zcu.comp;
20296 const gpa = comp.gpa;
20297 const io = comp.io;
20135 const ip = &zcu.intern_pool;20298 const ip = &zcu.intern_pool;
2013620299
20137 const types = try sema.arena.alloc(InternPool.Index, operands.len);20300 const types = try sema.arena.alloc(InternPool.Index, operands.len);
...@@ -20180,7 +20343,7 @@ fn arrayInitAnon(...@@ -20180,7 +20343,7 @@ fn arrayInitAnon(
20180 break :blk new_values;20343 break :blk new_values;
20181 };20344 };
2018220345
20183 const tuple_ty: Type = .fromInterned(try ip.getTupleType(gpa, pt.tid, .{20346 const tuple_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{
20184 .types = types,20347 .types = types,
20185 .values = values_no_comptime,20348 .values = values_no_comptime,
20186 }));20349 }));
...@@ -20247,7 +20410,11 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -20247,7 +20410,11 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
20247fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20410fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20248 const pt = sema.pt;20411 const pt = sema.pt;
20249 const zcu = pt.zcu;20412 const zcu = pt.zcu;
20413 const comp = zcu.comp;
20414 const gpa = comp.gpa;
20415 const io = comp.io;
20250 const ip = &zcu.intern_pool;20416 const ip = &zcu.intern_pool;
20417
20251 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;20418 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
20252 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;20419 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
20253 const ty_src = block.nodeOffset(inst_data.src_node);20420 const ty_src = block.nodeOffset(inst_data.src_node);
...@@ -20255,7 +20422,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -20255,7 +20422,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
20255 const wrapped_aggregate_ty = try sema.resolveTypeOrPoison(block, ty_src, extra.container_type) orelse return .generic_poison_type;20422 const wrapped_aggregate_ty = try sema.resolveTypeOrPoison(block, ty_src, extra.container_type) orelse return .generic_poison_type;
20256 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu);20423 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu);
20257 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);20424 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
20258 const field_name = try ip.getOrPutString(sema.gpa, pt.tid, zir_field_name, .no_embedded_nulls);20425 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls);
20259 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);20426 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);
20260}20427}
2026120428
...@@ -20669,6 +20836,9 @@ fn zirReifyTuple(...@@ -20669,6 +20836,9 @@ fn zirReifyTuple(
20669) CompileError!Air.Inst.Ref {20836) CompileError!Air.Inst.Ref {
20670 const pt = sema.pt;20837 const pt = sema.pt;
20671 const zcu = pt.zcu;20838 const zcu = pt.zcu;
20839 const comp = zcu.comp;
20840 const gpa = comp.gpa;
20841 const io = comp.io;
2067220842
20673 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;20843 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20674 const operand_src = block.builtinCallArgSrc(extra.node, 0);20844 const operand_src = block.builtinCallArgSrc(extra.node, 0);
...@@ -20691,7 +20861,7 @@ fn zirReifyTuple(...@@ -20691,7 +20861,7 @@ fn zirReifyTuple(
20691 const field_values = try sema.arena.alloc(InternPool.Index, fields_len);20861 const field_values = try sema.arena.alloc(InternPool.Index, fields_len);
20692 @memset(field_values, .none);20862 @memset(field_values, .none);
2069320863
20694 return .fromIntern(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{20864 return .fromIntern(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{
20695 .types = field_types,20865 .types = field_types,
20696 .values = field_values,20866 .values = field_values,
20697 }));20867 }));
...@@ -20704,7 +20874,9 @@ fn zirReifyPointer(...@@ -20704,7 +20874,9 @@ fn zirReifyPointer(
20704) CompileError!Air.Inst.Ref {20874) CompileError!Air.Inst.Ref {
20705 const pt = sema.pt;20875 const pt = sema.pt;
20706 const zcu = pt.zcu;20876 const zcu = pt.zcu;
20707 const gpa = zcu.gpa;20877 const comp = zcu.comp;
20878 const gpa = comp.gpa;
20879 const io = comp.io;
20708 const ip = &zcu.intern_pool;20880 const ip = &zcu.intern_pool;
2070920881
20710 const extra = sema.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;20882 const extra = sema.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;
...@@ -20772,7 +20944,7 @@ fn zirReifyPointer(...@@ -20772,7 +20944,7 @@ fn zirReifyPointer(
20772 }20944 }
20773 try checkSentinelType(sema, block, sentinel_src, elem_ty);20945 try checkSentinelType(sema, block, sentinel_src, elem_ty);
20774 if (sentinel.canMutateComptimeVarState(zcu)) {20946 if (sentinel.canMutateComptimeVarState(zcu)) {
20775 const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel", .no_embedded_nulls);20947 const sentinel_name = try ip.getOrPutString(gpa, io, pt.tid, "sentinel", .no_embedded_nulls);
20776 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel);20948 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel);
20777 }20949 }
20778 }20950 }
...@@ -20801,7 +20973,9 @@ fn zirReifyFn(...@@ -20801,7 +20973,9 @@ fn zirReifyFn(
20801) CompileError!Air.Inst.Ref {20973) CompileError!Air.Inst.Ref {
20802 const pt = sema.pt;20974 const pt = sema.pt;
20803 const zcu = pt.zcu;20975 const zcu = pt.zcu;
20804 const gpa = zcu.gpa;20976 const comp = zcu.comp;
20977 const gpa = comp.gpa;
20978 const io = comp.io;
20805 const ip = &zcu.intern_pool;20979 const ip = &zcu.intern_pool;
2080620980
20807 const extra = sema.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;20981 const extra = sema.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;
...@@ -20884,7 +21058,7 @@ fn zirReifyFn(...@@ -20884,7 +21058,7 @@ fn zirReifyFn(
20884 return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)});21058 return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)});
20885 }21059 }
2088621060
20887 return .fromIntern(try ip.getFuncType(gpa, pt.tid, .{21061 return .fromIntern(try ip.getFuncType(gpa, io, pt.tid, .{
20888 .param_types = param_types_ip,21062 .param_types = param_types_ip,
20889 .noalias_bits = noalias_bits,21063 .noalias_bits = noalias_bits,
20890 .comptime_bits = 0,21064 .comptime_bits = 0,
...@@ -20904,7 +21078,9 @@ fn zirReifyStruct(...@@ -20904,7 +21078,9 @@ fn zirReifyStruct(
20904) CompileError!Air.Inst.Ref {21078) CompileError!Air.Inst.Ref {
20905 const pt = sema.pt;21079 const pt = sema.pt;
20906 const zcu = pt.zcu;21080 const zcu = pt.zcu;
20907 const gpa = sema.gpa;21081 const comp = zcu.comp;
21082 const gpa = comp.gpa;
21083 const io = comp.io;
20908 const ip = &zcu.intern_pool;21084 const ip = &zcu.intern_pool;
2090921085
20910 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);21086 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
...@@ -21079,7 +21255,7 @@ fn zirReifyStruct(...@@ -21079,7 +21255,7 @@ fn zirReifyStruct(
21079 return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout});21255 return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout});
21080 }21256 }
2108121257
21082 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{21258 const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{
21083 .layout = layout,21259 .layout = layout,
21084 .fields_len = @intCast(fields_len),21260 .fields_len = @intCast(fields_len),
21085 .known_non_opv = false,21261 .known_non_opv = false,
...@@ -21223,10 +21399,10 @@ fn zirReifyStruct(...@@ -21223,10 +21399,10 @@ fn zirReifyStruct(
21223 }21399 }
21224 if (backing_int_ty) |ty| {21400 if (backing_int_ty) |ty| {
21225 try sema.checkBackingIntType(block, src, ty, fields_bit_sum);21401 try sema.checkBackingIntType(block, src, ty, fields_bit_sum);
21226 wip_struct_type.setBackingIntType(ip, ty.toIntern());21402 wip_struct_type.setBackingIntType(ip, io, ty.toIntern());
21227 } else {21403 } else {
21228 const ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));21404 const ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
21229 wip_struct_type.setBackingIntType(ip, ty.toIntern());21405 wip_struct_type.setBackingIntType(ip, io, ty.toIntern());
21230 }21406 }
21231 }21407 }
2123221408
...@@ -21259,7 +21435,9 @@ fn zirReifyUnion(...@@ -21259,7 +21435,9 @@ fn zirReifyUnion(
21259) CompileError!Air.Inst.Ref {21435) CompileError!Air.Inst.Ref {
21260 const pt = sema.pt;21436 const pt = sema.pt;
21261 const zcu = pt.zcu;21437 const zcu = pt.zcu;
21262 const gpa = sema.gpa;21438 const comp = zcu.comp;
21439 const gpa = comp.gpa;
21440 const io = comp.io;
21263 const ip = &zcu.intern_pool;21441 const ip = &zcu.intern_pool;
2126421442
21265 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);21443 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
...@@ -21400,7 +21578,7 @@ fn zirReifyUnion(...@@ -21400,7 +21578,7 @@ fn zirReifyUnion(
21400 return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{});21578 return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{});
21401 }21579 }
2140221580
21403 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{21581 const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{
21404 .flags = .{21582 .flags = .{
21405 .layout = layout,21583 .layout = layout,
21406 .status = .none,21584 .status = .none,
...@@ -21558,8 +21736,8 @@ fn zirReifyUnion(...@@ -21558,8 +21736,8 @@ fn zirReifyUnion(
21558 }21736 }
21559 }21737 }
2156021738
21561 loaded_union.setTagType(ip, enum_tag_ty);21739 loaded_union.setTagType(ip, io, enum_tag_ty);
21562 loaded_union.setStatus(ip, .have_field_types);21740 loaded_union.setStatus(ip, io, .have_field_types);
2156321741
21564 const new_namespace_index = try pt.createNamespace(.{21742 const new_namespace_index = try pt.createNamespace(.{
21565 .parent = block.namespace.toOptional(),21743 .parent = block.namespace.toOptional(),
...@@ -21590,7 +21768,9 @@ fn zirReifyEnum(...@@ -21590,7 +21768,9 @@ fn zirReifyEnum(
21590) CompileError!Air.Inst.Ref {21768) CompileError!Air.Inst.Ref {
21591 const pt = sema.pt;21769 const pt = sema.pt;
21592 const zcu = pt.zcu;21770 const zcu = pt.zcu;
21593 const gpa = sema.gpa;21771 const comp = zcu.comp;
21772 const gpa = comp.gpa;
21773 const io = comp.io;
21594 const ip = &zcu.intern_pool;21774 const ip = &zcu.intern_pool;
2159521775
21596 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);21776 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
...@@ -21688,7 +21868,7 @@ fn zirReifyEnum(...@@ -21688,7 +21868,7 @@ fn zirReifyEnum(
21688 std.hash.autoHash(&hasher, field_name);21868 std.hash.autoHash(&hasher, field_name);
21689 }21869 }
2169021870
21691 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{21871 const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{
21692 .has_values = true,21872 .has_values = true,
21693 .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit,21873 .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit,
21694 .fields_len = @intCast(fields_len),21874 .fields_len = @intCast(fields_len),
...@@ -21844,13 +22024,16 @@ fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)...@@ -21844,13 +22024,16 @@ fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
21844fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {22024fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
21845 const pt = sema.pt;22025 const pt = sema.pt;
21846 const zcu = pt.zcu;22026 const zcu = pt.zcu;
22027 const comp = zcu.comp;
22028 const gpa = comp.gpa;
22029 const io = comp.io;
21847 const ip = &zcu.intern_pool;22030 const ip = &zcu.intern_pool;
2184822031
21849 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;22032 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
21850 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);22033 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
21851 const ty = try sema.resolveType(block, ty_src, inst_data.operand);22034 const ty = try sema.resolveType(block, ty_src, inst_data.operand);
2185222035
21853 const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{f}", .{ty.fmt(pt)}, .no_embedded_nulls);22036 const type_name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}", .{ty.fmt(pt)}, .no_embedded_nulls);
21854 return sema.addNullTerminatedStrLit(type_name);22037 return sema.addNullTerminatedStrLit(type_name);
21855}22038}
2185622039
...@@ -22281,6 +22464,10 @@ fn ptrCastFull(...@@ -22281,6 +22464,10 @@ fn ptrCastFull(
22281) CompileError!Air.Inst.Ref {22464) CompileError!Air.Inst.Ref {
22282 const pt = sema.pt;22465 const pt = sema.pt;
22283 const zcu = pt.zcu;22466 const zcu = pt.zcu;
22467 const comp = zcu.comp;
22468 const gpa = comp.gpa;
22469 const io = comp.io;
22470
22284 const operand_ty = sema.typeOf(operand);22471 const operand_ty = sema.typeOf(operand);
2228522472
22286 try sema.checkPtrType(block, src, dest_ty, true);22473 try sema.checkPtrType(block, src, dest_ty, true);
...@@ -22452,14 +22639,14 @@ fn ptrCastFull(...@@ -22452,14 +22639,14 @@ fn ptrCastFull(
22452 if (dest_info.sentinel == .none) break :check_sent;22639 if (dest_info.sentinel == .none) break :check_sent;
22453 if (src_info.flags.size == .c) break :check_sent;22640 if (src_info.flags.size == .c) break :check_sent;
22454 if (src_info.sentinel != .none) {22641 if (src_info.sentinel != .none) {
22455 const coerced_sent = try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, src_info.sentinel, dest_info.child);22642 const coerced_sent = try zcu.intern_pool.getCoerced(gpa, io, pt.tid, src_info.sentinel, dest_info.child);
22456 if (dest_info.sentinel == coerced_sent) break :check_sent;22643 if (dest_info.sentinel == coerced_sent) break :check_sent;
22457 }22644 }
22458 if (is_array_ptr_to_slice) {22645 if (is_array_ptr_to_slice) {
22459 // [*]nT -> []T22646 // [*]nT -> []T
22460 const arr_ty: Type = .fromInterned(src_info.child);22647 const arr_ty: Type = .fromInterned(src_info.child);
22461 if (arr_ty.sentinel(zcu)) |src_sentinel| {22648 if (arr_ty.sentinel(zcu)) |src_sentinel| {
22462 const coerced_sent = try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, src_sentinel.toIntern(), dest_info.child);22649 const coerced_sent = try zcu.intern_pool.getCoerced(gpa, io, pt.tid, src_sentinel.toIntern(), dest_info.child);
22463 if (dest_info.sentinel == coerced_sent) break :check_sent;22650 if (dest_info.sentinel == coerced_sent) break :check_sent;
22464 }22651 }
22465 }22652 }
...@@ -23577,8 +23764,11 @@ fn resolveExportOptions(...@@ -23577,8 +23764,11 @@ fn resolveExportOptions(
23577) CompileError!Zcu.Export.Options {23764) CompileError!Zcu.Export.Options {
23578 const pt = sema.pt;23765 const pt = sema.pt;
23579 const zcu = pt.zcu;23766 const zcu = pt.zcu;
23580 const gpa = sema.gpa;23767 const comp = zcu.comp;
23768 const gpa = comp.gpa;
23769 const io = comp.io;
23581 const ip = &zcu.intern_pool;23770 const ip = &zcu.intern_pool;
23771
23582 const export_options_ty = try sema.getBuiltinType(src, .ExportOptions);23772 const export_options_ty = try sema.getBuiltinType(src, .ExportOptions);
23583 const air_ref = try sema.resolveInst(zir_ref);23773 const air_ref = try sema.resolveInst(zir_ref);
23584 const options = try sema.coerce(block, export_options_ty, air_ref, src);23774 const options = try sema.coerce(block, export_options_ty, air_ref, src);
...@@ -23588,21 +23778,21 @@ fn resolveExportOptions(...@@ -23588,21 +23778,21 @@ fn resolveExportOptions(
23588 const section_src = block.src(.{ .init_field_section = src.offset.node_offset_builtin_call_arg.builtin_call_node });23778 const section_src = block.src(.{ .init_field_section = src.offset.node_offset_builtin_call_arg.builtin_call_node });
23589 const visibility_src = block.src(.{ .init_field_visibility = src.offset.node_offset_builtin_call_arg.builtin_call_node });23779 const visibility_src = block.src(.{ .init_field_visibility = src.offset.node_offset_builtin_call_arg.builtin_call_node });
2359023780
23591 const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src);23781 const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "name", .no_embedded_nulls), name_src);
23592 const name = try sema.toConstString(block, name_src, name_operand, .{ .simple = .export_options });23782 const name = try sema.toConstString(block, name_src, name_operand, .{ .simple = .export_options });
2359323783
23594 const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "linkage", .no_embedded_nulls), linkage_src);23784 const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "linkage", .no_embedded_nulls), linkage_src);
23595 const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{ .simple = .export_options });23785 const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{ .simple = .export_options });
23596 const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage);23786 const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage);
2359723787
23598 const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "section", .no_embedded_nulls), section_src);23788 const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "section", .no_embedded_nulls), section_src);
23599 const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{ .simple = .export_options });23789 const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{ .simple = .export_options });
23600 const section = if (section_opt_val.optionalValue(zcu)) |section_val|23790 const section = if (section_opt_val.optionalValue(zcu)) |section_val|
23601 try sema.toConstString(block, section_src, Air.internedToRef(section_val.toIntern()), .{ .simple = .export_options })23791 try sema.toConstString(block, section_src, Air.internedToRef(section_val.toIntern()), .{ .simple = .export_options })
23602 else23792 else
23603 null;23793 null;
2360423794
23605 const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "visibility", .no_embedded_nulls), visibility_src);23795 const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "visibility", .no_embedded_nulls), visibility_src);
23606 const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_operand, .{ .simple = .export_options });23796 const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_operand, .{ .simple = .export_options });
23607 const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility);23797 const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility);
2360823798
...@@ -23617,9 +23807,9 @@ fn resolveExportOptions(...@@ -23617,9 +23807,9 @@ fn resolveExportOptions(
23617 }23807 }
2361823808
23619 return .{23809 return .{
23620 .name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls),23810 .name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls),
23621 .linkage = linkage,23811 .linkage = linkage,
23622 .section = try ip.getOrPutStringOpt(gpa, pt.tid, section, .no_embedded_nulls),23812 .section = try ip.getOrPutStringOpt(gpa, io, pt.tid, section, .no_embedded_nulls),
23623 .visibility = visibility,23813 .visibility = visibility,
23624 };23814 };
23625}23815}
...@@ -25345,8 +25535,11 @@ fn zirMemcpy(...@@ -25345,8 +25535,11 @@ fn zirMemcpy(
25345fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {25535fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
25346 const pt = sema.pt;25536 const pt = sema.pt;
25347 const zcu = pt.zcu;25537 const zcu = pt.zcu;
25348 const gpa = sema.gpa;25538 const comp = zcu.comp;
25539 const gpa = comp.gpa;
25540 const io = comp.io;
25349 const ip = &zcu.intern_pool;25541 const ip = &zcu.intern_pool;
25542
25350 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;25543 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
25351 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;25544 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
25352 const src = block.nodeOffset(inst_data.src_node);25545 const src = block.nodeOffset(inst_data.src_node);
...@@ -25385,7 +25578,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25385,7 +25578,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25385 const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src);25578 const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src);
2538625579
25387 const runtime_src = rs: {25580 const runtime_src = rs: {
25388 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls), dest_src);25581 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src);
25389 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src;25582 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src;
25390 const len_u64 = try len_val.toUnsignedIntSema(pt);25583 const len_u64 = try len_val.toUnsignedIntSema(pt);
25391 const len = try sema.usizeCast(block, dest_src, len_u64);25584 const len = try sema.usizeCast(block, dest_src, len_u64);
...@@ -25438,7 +25631,11 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -25438,7 +25631,11 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2543825631
25439 const pt = sema.pt;25632 const pt = sema.pt;
25440 const zcu = pt.zcu;25633 const zcu = pt.zcu;
25634 const comp = zcu.comp;
25635 const gpa = comp.gpa;
25636 const io = comp.io;
25441 const ip = &zcu.intern_pool;25637 const ip = &zcu.intern_pool;
25638
25442 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;25639 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
25443 const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);25640 const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
25444 const target = zcu.getTarget();25641 const target = zcu.getTarget();
...@@ -25482,7 +25679,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -25482,7 +25679,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
25482 block,25679 block,
25483 LazySrcLoc.unneeded,25680 LazySrcLoc.unneeded,
25484 cc_type.getNamespaceIndex(zcu),25681 cc_type.getNamespaceIndex(zcu),
25485 try ip.getOrPutString(sema.gpa, pt.tid, "c", .no_embedded_nulls),25682 try ip.getOrPutString(gpa, io, pt.tid, "c", .no_embedded_nulls),
25486 );25683 );
25487 // The above should have errored.25684 // The above should have errored.
25488 @panic("std.builtin is corrupt");25685 @panic("std.builtin is corrupt");
...@@ -25648,8 +25845,11 @@ fn resolvePrefetchOptions(...@@ -25648,8 +25845,11 @@ fn resolvePrefetchOptions(
25648) CompileError!std.builtin.PrefetchOptions {25845) CompileError!std.builtin.PrefetchOptions {
25649 const pt = sema.pt;25846 const pt = sema.pt;
25650 const zcu = pt.zcu;25847 const zcu = pt.zcu;
25651 const gpa = sema.gpa;25848 const comp = zcu.comp;
25849 const gpa = comp.gpa;
25850 const io = comp.io;
25652 const ip = &zcu.intern_pool;25851 const ip = &zcu.intern_pool;
25852
25653 const options_ty = try sema.getBuiltinType(src, .PrefetchOptions);25853 const options_ty = try sema.getBuiltinType(src, .PrefetchOptions);
25654 const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);25854 const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);
2565525855
...@@ -25657,13 +25857,13 @@ fn resolvePrefetchOptions(...@@ -25657,13 +25857,13 @@ fn resolvePrefetchOptions(
25657 const locality_src = block.src(.{ .init_field_locality = src.offset.node_offset_builtin_call_arg.builtin_call_node });25857 const locality_src = block.src(.{ .init_field_locality = src.offset.node_offset_builtin_call_arg.builtin_call_node });
25658 const cache_src = block.src(.{ .init_field_cache = src.offset.node_offset_builtin_call_arg.builtin_call_node });25858 const cache_src = block.src(.{ .init_field_cache = src.offset.node_offset_builtin_call_arg.builtin_call_node });
2565925859
25660 const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "rw", .no_embedded_nulls), rw_src);25860 const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "rw", .no_embedded_nulls), rw_src);
25661 const rw_val = try sema.resolveConstDefinedValue(block, rw_src, rw, .{ .simple = .prefetch_options });25861 const rw_val = try sema.resolveConstDefinedValue(block, rw_src, rw, .{ .simple = .prefetch_options });
2566225862
25663 const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "locality", .no_embedded_nulls), locality_src);25863 const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "locality", .no_embedded_nulls), locality_src);
25664 const locality_val = try sema.resolveConstDefinedValue(block, locality_src, locality, .{ .simple = .prefetch_options });25864 const locality_val = try sema.resolveConstDefinedValue(block, locality_src, locality, .{ .simple = .prefetch_options });
2566525865
25666 const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "cache", .no_embedded_nulls), cache_src);25866 const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "cache", .no_embedded_nulls), cache_src);
25667 const cache_val = try sema.resolveConstDefinedValue(block, cache_src, cache, .{ .simple = .prefetch_options });25867 const cache_val = try sema.resolveConstDefinedValue(block, cache_src, cache, .{ .simple = .prefetch_options });
2566825868
25669 return std.builtin.PrefetchOptions{25869 return std.builtin.PrefetchOptions{
...@@ -25717,8 +25917,11 @@ fn resolveExternOptions(...@@ -25717,8 +25917,11 @@ fn resolveExternOptions(
25717} {25917} {
25718 const pt = sema.pt;25918 const pt = sema.pt;
25719 const zcu = pt.zcu;25919 const zcu = pt.zcu;
25720 const gpa = sema.gpa;25920 const comp = zcu.comp;
25921 const gpa = comp.gpa;
25922 const io = comp.io;
25721 const ip = &zcu.intern_pool;25923 const ip = &zcu.intern_pool;
25924
25722 const options_inst = try sema.resolveInst(zir_ref);25925 const options_inst = try sema.resolveInst(zir_ref);
25723 const extern_options_ty = try sema.getBuiltinType(src, .ExternOptions);25926 const extern_options_ty = try sema.getBuiltinType(src, .ExternOptions);
25724 const options = try sema.coerce(block, extern_options_ty, options_inst, src);25927 const options = try sema.coerce(block, extern_options_ty, options_inst, src);
...@@ -25731,21 +25934,21 @@ fn resolveExternOptions(...@@ -25731,21 +25934,21 @@ fn resolveExternOptions(
25731 const dll_import_src = block.src(.{ .init_field_dll_import = src.offset.node_offset_builtin_call_arg.builtin_call_node });25934 const dll_import_src = block.src(.{ .init_field_dll_import = src.offset.node_offset_builtin_call_arg.builtin_call_node });
25732 const relocation_src = block.src(.{ .init_field_relocation = src.offset.node_offset_builtin_call_arg.builtin_call_node });25935 const relocation_src = block.src(.{ .init_field_relocation = src.offset.node_offset_builtin_call_arg.builtin_call_node });
2573325936
25734 const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src);25937 const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "name", .no_embedded_nulls), name_src);
25735 const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options });25938 const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options });
2573625939
25737 const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "library_name", .no_embedded_nulls), library_src);25940 const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "library_name", .no_embedded_nulls), library_src);
25738 const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{ .simple = .extern_options });25941 const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{ .simple = .extern_options });
2573925942
25740 const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "linkage", .no_embedded_nulls), linkage_src);25943 const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "linkage", .no_embedded_nulls), linkage_src);
25741 const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{ .simple = .extern_options });25944 const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{ .simple = .extern_options });
25742 const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage);25945 const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage);
2574325946
25744 const visibility_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "visibility", .no_embedded_nulls), visibility_src);25947 const visibility_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "visibility", .no_embedded_nulls), visibility_src);
25745 const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_ref, .{ .simple = .extern_options });25948 const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_ref, .{ .simple = .extern_options });
25746 const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility);25949 const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility);
2574725950
25748 const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_thread_local", .no_embedded_nulls), thread_local_src);25951 const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "is_thread_local", .no_embedded_nulls), thread_local_src);
25749 const is_thread_local_val = try sema.resolveConstDefinedValue(block, thread_local_src, is_thread_local, .{ .simple = .extern_options });25952 const is_thread_local_val = try sema.resolveConstDefinedValue(block, thread_local_src, is_thread_local, .{ .simple = .extern_options });
2575025953
25751 const library_name = if (library_name_val.optionalValue(zcu)) |library_name_payload| library_name: {25954 const library_name = if (library_name_val.optionalValue(zcu)) |library_name_payload| library_name: {
...@@ -25757,10 +25960,10 @@ fn resolveExternOptions(...@@ -25757,10 +25960,10 @@ fn resolveExternOptions(
25757 break :library_name library_name;25960 break :library_name library_name;
25758 } else null;25961 } else null;
2575925962
25760 const is_dll_import_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_dll_import", .no_embedded_nulls), dll_import_src);25963 const is_dll_import_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "is_dll_import", .no_embedded_nulls), dll_import_src);
25761 const is_dll_import_val = try sema.resolveConstDefinedValue(block, dll_import_src, is_dll_import_ref, .{ .simple = .extern_options });25964 const is_dll_import_val = try sema.resolveConstDefinedValue(block, dll_import_src, is_dll_import_ref, .{ .simple = .extern_options });
2576225965
25763 const relocation_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "relocation", .no_embedded_nulls), relocation_src);25966 const relocation_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, io, pt.tid, "relocation", .no_embedded_nulls), relocation_src);
25764 const relocation_val = try sema.resolveConstDefinedValue(block, relocation_src, relocation_ref, .{ .simple = .extern_options });25967 const relocation_val = try sema.resolveConstDefinedValue(block, relocation_src, relocation_ref, .{ .simple = .extern_options });
25765 const relocation = try sema.interpretBuiltinType(block, relocation_src, relocation_val, std.builtin.ExternOptions.Relocation);25968 const relocation = try sema.interpretBuiltinType(block, relocation_src, relocation_val, std.builtin.ExternOptions.Relocation);
2576625969
...@@ -25773,8 +25976,8 @@ fn resolveExternOptions(...@@ -25773,8 +25976,8 @@ fn resolveExternOptions(
25773 }25976 }
2577425977
25775 return .{25978 return .{
25776 .name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls),25979 .name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls),
25777 .library_name = try ip.getOrPutStringOpt(gpa, pt.tid, library_name, .no_embedded_nulls),25980 .library_name = try ip.getOrPutStringOpt(gpa, io, pt.tid, library_name, .no_embedded_nulls),
25778 .linkage = linkage,25981 .linkage = linkage,
25779 .visibility = visibility,25982 .visibility = visibility,
25780 .is_thread_local = is_thread_local_val.toBool(),25983 .is_thread_local = is_thread_local_val.toBool(),
...@@ -25919,7 +26122,9 @@ fn zirInComptime(...@@ -25919,7 +26122,9 @@ fn zirInComptime(
25919fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {26122fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
25920 const pt = sema.pt;26123 const pt = sema.pt;
25921 const zcu = pt.zcu;26124 const zcu = pt.zcu;
25922 const gpa = zcu.gpa;26125 const comp = zcu.comp;
26126 const gpa = comp.gpa;
26127 const io = comp.io;
25923 const ip = &zcu.intern_pool;26128 const ip = &zcu.intern_pool;
2592426129
25925 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));26130 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
...@@ -25955,7 +26160,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -25955,7 +26160,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
25955 block,26160 block,
25956 src,26161 src,
25957 callconv_ty.getNamespaceIndex(zcu),26162 callconv_ty.getNamespaceIndex(zcu),
25958 try ip.getOrPutString(gpa, pt.tid, "c", .no_embedded_nulls),26163 try ip.getOrPutString(gpa, io, pt.tid, "c", .no_embedded_nulls),
25959 ) orelse @panic("std.builtin is corrupt");26164 ) orelse @panic("std.builtin is corrupt");
25960 },26165 },
25961 .calling_convention_inline => {26166 .calling_convention_inline => {
...@@ -26492,11 +26697,12 @@ fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !vo...@@ -26492,11 +26697,12 @@ fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !vo
2649226697
26493fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index {26698fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index {
26494 const zcu = sema.pt.zcu;26699 const zcu = sema.pt.zcu;
26700 const io = zcu.comp.io;
26495 try sema.ensureMemoizedStateResolved(src, .panic);26701 try sema.ensureMemoizedStateResolved(src, .panic);
26496 const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin());26702 const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin());
26497 switch (sema.owner.unwrap()) {26703 switch (sema.owner.unwrap()) {
26498 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},26704 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
26499 .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true),26705 .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true),
26500 }26706 }
26501 return panic_fn_index;26707 return panic_fn_index;
26502}26708}
...@@ -28539,10 +28745,15 @@ fn coerceExtra(...@@ -28539,10 +28745,15 @@ fn coerceExtra(
28539 inst_src: LazySrcLoc,28745 inst_src: LazySrcLoc,
28540 opts: CoerceOpts,28746 opts: CoerceOpts,
28541) CoersionError!Air.Inst.Ref {28747) CoersionError!Air.Inst.Ref {
28542 if (dest_ty.isGenericPoison()) return inst;
28543 const pt = sema.pt;28748 const pt = sema.pt;
28544 const zcu = pt.zcu;28749 const zcu = pt.zcu;
28750 const comp = zcu.comp;
28751 const gpa = comp.gpa;
28752 const io = comp.io;
28545 const ip = &zcu.intern_pool;28753 const ip = &zcu.intern_pool;
28754
28755 if (dest_ty.isGenericPoison()) return inst;
28756
28546 const dest_ty_src = inst_src; // TODO better source location28757 const dest_ty_src = inst_src; // TODO better source location
28547 try dest_ty.resolveFields(pt);28758 try dest_ty.resolveFields(pt);
28548 const inst_ty = sema.typeOf(inst);28759 const inst_ty = sema.typeOf(inst);
...@@ -28904,7 +29115,7 @@ fn coerceExtra(...@@ -28904,7 +29115,7 @@ fn coerceExtra(
28904 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {29115 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
28905 .undef => try pt.undefRef(dest_ty),29116 .undef => try pt.undefRef(dest_ty),
28906 .int => |int| Air.internedToRef(29117 .int => |int| Air.internedToRef(
28907 try zcu.intern_pool.getCoercedInts(zcu.gpa, pt.tid, int, dest_ty.toIntern()),29118 try zcu.intern_pool.getCoercedInts(gpa, io, pt.tid, int, dest_ty.toIntern()),
28908 ),29119 ),
28909 else => unreachable,29120 else => unreachable,
28910 };29121 };
...@@ -30070,6 +30281,10 @@ fn coerceInMemoryAllowedPtrs(...@@ -30070,6 +30281,10 @@ fn coerceInMemoryAllowedPtrs(
30070) !InMemoryCoercionResult {30281) !InMemoryCoercionResult {
30071 const pt = sema.pt;30282 const pt = sema.pt;
30072 const zcu = pt.zcu;30283 const zcu = pt.zcu;
30284 const comp = zcu.comp;
30285 const gpa = comp.gpa;
30286 const io = comp.io;
30287
30073 const dest_info = dest_ptr_ty.ptrInfo(zcu);30288 const dest_info = dest_ptr_ty.ptrInfo(zcu);
30074 const src_info = src_ptr_ty.ptrInfo(zcu);30289 const src_info = src_ptr_ty.ptrInfo(zcu);
3007530290
...@@ -30175,7 +30390,7 @@ fn coerceInMemoryAllowedPtrs(...@@ -30175,7 +30390,7 @@ fn coerceInMemoryAllowedPtrs(
30175 const ds = dest_info.sentinel;30390 const ds = dest_info.sentinel;
30176 if (ss == .none and ds == .none) break :ok true;30391 if (ss == .none and ds == .none) break :ok true;
30177 if (ss != .none and ds != .none) {30392 if (ss != .none and ds != .none) {
30178 if (ds == try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, ss, dest_info.child)) break :ok true;30393 if (ds == try zcu.intern_pool.getCoerced(gpa, io, pt.tid, ss, dest_info.child)) break :ok true;
30179 }30394 }
30180 if (src_info.flags.size == .c) break :ok true;30395 if (src_info.flags.size == .c) break :ok true;
30181 if (!dest_is_mut and dest_info.sentinel == .none) break :ok true;30396 if (!dest_is_mut and dest_info.sentinel == .none) break :ok true;
...@@ -33086,6 +33301,9 @@ fn resolvePeerTypesInner(...@@ -33086,6 +33301,9 @@ fn resolvePeerTypesInner(
33086) !PeerResolveResult {33301) !PeerResolveResult {
33087 const pt = sema.pt;33302 const pt = sema.pt;
33088 const zcu = pt.zcu;33303 const zcu = pt.zcu;
33304 const comp = zcu.comp;
33305 const gpa = comp.gpa;
33306 const io = comp.io;
33089 const ip = &zcu.intern_pool;33307 const ip = &zcu.intern_pool;
3309033308
33091 var strat_reason: usize = 0;33309 var strat_reason: usize = 0;
...@@ -33412,8 +33630,8 @@ fn resolvePeerTypesInner(...@@ -33412,8 +33630,8 @@ fn resolvePeerTypesInner(
33412 }).toIntern();33630 }).toIntern();
3341333631
33414 if (ptr_info.sentinel != .none and peer_info.sentinel != .none) {33632 if (ptr_info.sentinel != .none and peer_info.sentinel != .none) {
33415 const peer_sent = try ip.getCoerced(sema.gpa, pt.tid, ptr_info.sentinel, ptr_info.child);33633 const peer_sent = try ip.getCoerced(gpa, io, pt.tid, ptr_info.sentinel, ptr_info.child);
33416 const ptr_sent = try ip.getCoerced(sema.gpa, pt.tid, peer_info.sentinel, ptr_info.child);33634 const ptr_sent = try ip.getCoerced(gpa, io, pt.tid, peer_info.sentinel, ptr_info.child);
33417 if (ptr_sent == peer_sent) {33635 if (ptr_sent == peer_sent) {
33418 ptr_info.sentinel = ptr_sent;33636 ptr_info.sentinel = ptr_sent;
33419 } else {33637 } else {
...@@ -33715,8 +33933,8 @@ fn resolvePeerTypesInner(...@@ -33715,8 +33933,8 @@ fn resolvePeerTypesInner(
33715 no_sentinel: {33933 no_sentinel: {
33716 if (peer_sentinel == .none) break :no_sentinel;33934 if (peer_sentinel == .none) break :no_sentinel;
33717 if (cur_sentinel == .none) break :no_sentinel;33935 if (cur_sentinel == .none) break :no_sentinel;
33718 const peer_sent_coerced = try ip.getCoerced(sema.gpa, pt.tid, peer_sentinel, sentinel_ty);33936 const peer_sent_coerced = try ip.getCoerced(gpa, io, pt.tid, peer_sentinel, sentinel_ty);
33719 const cur_sent_coerced = try ip.getCoerced(sema.gpa, pt.tid, cur_sentinel, sentinel_ty);33937 const cur_sent_coerced = try ip.getCoerced(gpa, io, pt.tid, cur_sentinel, sentinel_ty);
33720 if (peer_sent_coerced != cur_sent_coerced) break :no_sentinel;33938 if (peer_sent_coerced != cur_sent_coerced) break :no_sentinel;
33721 // Sentinels match33939 // Sentinels match
33722 if (ptr_info.flags.size == .one) switch (ip.indexToKey(ptr_info.child)) {33940 if (ptr_info.flags.size == .one) switch (ip.indexToKey(ptr_info.child)) {
...@@ -34081,7 +34299,7 @@ fn resolvePeerTypesInner(...@@ -34081,7 +34299,7 @@ fn resolvePeerTypesInner(
34081 else => |result| {34299 else => |result| {
34082 const result_buf = try sema.arena.create(PeerResolveResult);34300 const result_buf = try sema.arena.create(PeerResolveResult);
34083 result_buf.* = result;34301 result_buf.* = result;
34084 const field_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);34302 const field_name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
3408534303
34086 // The error info needs the field types, but we can't reuse sub_peer_tys34304 // The error info needs the field types, but we can't reuse sub_peer_tys
34087 // since the recursive call may have clobbered it.34305 // since the recursive call may have clobbered it.
...@@ -34136,7 +34354,7 @@ fn resolvePeerTypesInner(...@@ -34136,7 +34354,7 @@ fn resolvePeerTypesInner(
34136 field_val.* = if (comptime_val) |v| v.toIntern() else .none;34354 field_val.* = if (comptime_val) |v| v.toIntern() else .none;
34137 }34355 }
3413834356
34139 const final_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{34357 const final_ty = try ip.getTupleType(gpa, io, pt.tid, .{
34140 .types = field_types,34358 .types = field_types,
34141 .values = field_vals,34359 .values = field_vals,
34142 });34360 });
...@@ -34274,6 +34492,7 @@ pub fn resolveStructAlignment(...@@ -34274,6 +34492,7 @@ pub fn resolveStructAlignment(
34274) SemaError!void {34492) SemaError!void {
34275 const pt = sema.pt;34493 const pt = sema.pt;
34276 const zcu = pt.zcu;34494 const zcu = pt.zcu;
34495 const io = zcu.comp.io;
34277 const ip = &zcu.intern_pool;34496 const ip = &zcu.intern_pool;
34278 const target = zcu.getTarget();34497 const target = zcu.getTarget();
3427934498
...@@ -34287,15 +34506,15 @@ pub fn resolveStructAlignment(...@@ -34287,15 +34506,15 @@ pub fn resolveStructAlignment(
34287 // We'll guess "pointer-aligned", if the struct has an34506 // We'll guess "pointer-aligned", if the struct has an
34288 // underaligned pointer field then some allocations34507 // underaligned pointer field then some allocations
34289 // might require explicit alignment.34508 // might require explicit alignment.
34290 if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, ptr_align)) return;34509 if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return;
3429134510
34292 try sema.resolveStructFieldTypes(ty, struct_type);34511 try sema.resolveStructFieldTypes(ty, struct_type);
3429334512
34294 // We'll guess "pointer-aligned", if the struct has an34513 // We'll guess "pointer-aligned", if the struct has an
34295 // underaligned pointer field then some allocations34514 // underaligned pointer field then some allocations
34296 // might require explicit alignment.34515 // might require explicit alignment.
34297 if (struct_type.assumePointerAlignedIfWip(ip, ptr_align)) return;34516 if (struct_type.assumePointerAlignedIfWip(ip, io, ptr_align)) return;
34298 defer struct_type.clearAlignmentWip(ip);34517 defer struct_type.clearAlignmentWip(ip, io);
3429934518
34300 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.34519 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34301 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.34520 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
...@@ -34314,13 +34533,14 @@ pub fn resolveStructAlignment(...@@ -34314,13 +34533,14 @@ pub fn resolveStructAlignment(
34314 alignment = alignment.maxStrict(field_align);34533 alignment = alignment.maxStrict(field_align);
34315 }34534 }
3431634535
34317 struct_type.setAlignment(ip, alignment);34536 struct_type.setAlignment(ip, io, alignment);
34318}34537}
3431934538
34320pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {34539pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
34321 const pt = sema.pt;34540 const pt = sema.pt;
34322 const zcu = pt.zcu;34541 const zcu = pt.zcu;
34323 const ip = &zcu.intern_pool;34542 const ip = &zcu.intern_pool;
34543 const io = zcu.comp.io;
34324 const struct_type = zcu.typeToStruct(ty) orelse return;34544 const struct_type = zcu.typeToStruct(ty) orelse return;
3432534545
34326 assert(sema.owner.unwrap().type == ty.toIntern());34546 assert(sema.owner.unwrap().type == ty.toIntern());
...@@ -34341,7 +34561,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34341,7 +34561,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
34341 return;34561 return;
34342 }34562 }
3434334563
34344 if (struct_type.setLayoutWip(ip)) {34564 if (struct_type.setLayoutWip(ip, io)) {
34345 const msg = try sema.errMsg(34565 const msg = try sema.errMsg(
34346 ty.srcLoc(zcu),34566 ty.srcLoc(zcu),
34347 "struct '{f}' depends on itself",34567 "struct '{f}' depends on itself",
...@@ -34349,7 +34569,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34349,7 +34569,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
34349 );34569 );
34350 return sema.failWithOwnedErrorMsg(null, msg);34570 return sema.failWithOwnedErrorMsg(null, msg);
34351 }34571 }
34352 defer struct_type.clearLayoutWip(ip);34572 defer struct_type.clearLayoutWip(ip, io);
3435334573
34354 const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len);34574 const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len);
34355 const sizes = try sema.arena.alloc(u64, struct_type.field_types.len);34575 const sizes = try sema.arena.alloc(u64, struct_type.field_types.len);
...@@ -34468,7 +34688,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34468,7 +34688,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
34468 );34688 );
34469 return sema.failWithOwnedErrorMsg(null, msg);34689 return sema.failWithOwnedErrorMsg(null, msg);
34470 };34690 };
34471 struct_type.setLayoutResolved(ip, size, big_align);34691 struct_type.setLayoutResolved(ip, io, size, big_align);
34472 _ = try ty.comptimeOnlySema(pt);34692 _ = try ty.comptimeOnlySema(pt);
34473}34693}
3447434694
...@@ -34478,7 +34698,9 @@ fn backingIntType(...@@ -34478,7 +34698,9 @@ fn backingIntType(
34478) CompileError!void {34698) CompileError!void {
34479 const pt = sema.pt;34699 const pt = sema.pt;
34480 const zcu = pt.zcu;34700 const zcu = pt.zcu;
34481 const gpa = zcu.gpa;34701 const comp = zcu.comp;
34702 const gpa = comp.gpa;
34703 const io = comp.io;
34482 const ip = &zcu.intern_pool;34704 const ip = &zcu.intern_pool;
3448334705
34484 var analysis_arena = std.heap.ArenaAllocator.init(gpa);34706 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
...@@ -34546,13 +34768,13 @@ fn backingIntType(...@@ -34546,13 +34768,13 @@ fn backingIntType(
34546 };34768 };
3454734769
34548 try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);34770 try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);
34549 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());34771 struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern());
34550 } else {34772 } else {
34551 if (fields_bit_sum > std.math.maxInt(u16)) {34773 if (fields_bit_sum > std.math.maxInt(u16)) {
34552 return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});34774 return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
34553 }34775 }
34554 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));34776 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
34555 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());34777 struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern());
34556 }34778 }
3455734779
34558 try sema.flushExports();34780 try sema.flushExports();
...@@ -34620,6 +34842,7 @@ pub fn resolveUnionAlignment(...@@ -34620,6 +34842,7 @@ pub fn resolveUnionAlignment(
34620) SemaError!void {34842) SemaError!void {
34621 const pt = sema.pt;34843 const pt = sema.pt;
34622 const zcu = pt.zcu;34844 const zcu = pt.zcu;
34845 const io = zcu.comp.io;
34623 const ip = &zcu.intern_pool;34846 const ip = &zcu.intern_pool;
34624 const target = zcu.getTarget();34847 const target = zcu.getTarget();
3462534848
...@@ -34632,7 +34855,7 @@ pub fn resolveUnionAlignment(...@@ -34632,7 +34855,7 @@ pub fn resolveUnionAlignment(
34632 // We'll guess "pointer-aligned", if the union has an34855 // We'll guess "pointer-aligned", if the union has an
34633 // underaligned pointer field then some allocations34856 // underaligned pointer field then some allocations
34634 // might require explicit alignment.34857 // might require explicit alignment.
34635 if (union_type.assumePointerAlignedIfFieldTypesWip(ip, ptr_align)) return;34858 if (union_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return;
3463634859
34637 try sema.resolveUnionFieldTypes(ty, union_type);34860 try sema.resolveUnionFieldTypes(ty, union_type);
3463834861
...@@ -34653,12 +34876,13 @@ pub fn resolveUnionAlignment(...@@ -34653,12 +34876,13 @@ pub fn resolveUnionAlignment(
34653 max_align = max_align.max(field_align);34876 max_align = max_align.max(field_align);
34654 }34877 }
3465534878
34656 union_type.setAlignment(ip, max_align);34879 union_type.setAlignment(ip, io, max_align);
34657}34880}
3465834881
34659/// This logic must be kept in sync with `Type.getUnionLayout`.34882/// This logic must be kept in sync with `Type.getUnionLayout`.
34660pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {34883pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
34661 const pt = sema.pt;34884 const pt = sema.pt;
34885 const io = pt.zcu.comp.io;
34662 const ip = &pt.zcu.intern_pool;34886 const ip = &pt.zcu.intern_pool;
3466334887
34664 try sema.resolveUnionFieldTypes(ty, ip.loadUnionType(ty.ip_index));34888 try sema.resolveUnionFieldTypes(ty, ip.loadUnionType(ty.ip_index));
...@@ -34682,9 +34906,9 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34682,9 +34906,9 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
34682 .have_layout, .fully_resolved_wip, .fully_resolved => return,34906 .have_layout, .fully_resolved_wip, .fully_resolved => return,
34683 }34907 }
3468434908
34685 errdefer union_type.setStatusIfLayoutWip(ip, old_flags.status);34909 errdefer union_type.setStatusIfLayoutWip(ip, io, old_flags.status);
3468634910
34687 union_type.setStatus(ip, .layout_wip);34911 union_type.setStatus(ip, io, .layout_wip);
3468834912
34689 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.34913 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34690 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.34914 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
...@@ -34765,7 +34989,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -34765,7 +34989,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
34765 );34989 );
34766 return sema.failWithOwnedErrorMsg(null, msg);34990 return sema.failWithOwnedErrorMsg(null, msg);
34767 };34991 };
34768 union_type.setHaveLayout(ip, casted_size, padding, alignment);34992 union_type.setHaveLayout(ip, io, casted_size, padding, alignment);
3476934993
34770 if (union_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) {34994 if (union_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) {
34771 const msg = try sema.errMsg(34995 const msg = try sema.errMsg(
...@@ -34797,13 +35021,14 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {...@@ -34797,13 +35021,14 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {
3479735021
34798 const pt = sema.pt;35022 const pt = sema.pt;
34799 const zcu = pt.zcu;35023 const zcu = pt.zcu;
35024 const io = zcu.comp.io;
34800 const ip = &zcu.intern_pool;35025 const ip = &zcu.intern_pool;
34801 const struct_type = zcu.typeToStruct(ty).?;35026 const struct_type = zcu.typeToStruct(ty).?;
3480235027
34803 assert(sema.owner.unwrap().type == ty.toIntern());35028 assert(sema.owner.unwrap().type == ty.toIntern());
3480435029
34805 if (struct_type.setFullyResolved(ip)) return;35030 if (struct_type.setFullyResolved(ip, io)) return;
34806 errdefer struct_type.clearFullyResolved(ip);35031 errdefer struct_type.clearFullyResolved(ip, io);
3480735032
34808 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.35033 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34809 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.35034 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
...@@ -34823,6 +35048,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {...@@ -34823,6 +35048,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
3482335048
34824 const pt = sema.pt;35049 const pt = sema.pt;
34825 const zcu = pt.zcu;35050 const zcu = pt.zcu;
35051 const io = zcu.comp.io;
34826 const ip = &zcu.intern_pool;35052 const ip = &zcu.intern_pool;
34827 const union_obj = zcu.typeToUnion(ty).?;35053 const union_obj = zcu.typeToUnion(ty).?;
3482835054
...@@ -34841,14 +35067,14 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {...@@ -34841,14 +35067,14 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
34841 // make sure pointer fields get their child types resolved as well.35067 // make sure pointer fields get their child types resolved as well.
34842 // See also similar code for structs.35068 // See also similar code for structs.
34843 const prev_status = union_obj.flagsUnordered(ip).status;35069 const prev_status = union_obj.flagsUnordered(ip).status;
34844 errdefer union_obj.setStatus(ip, prev_status);35070 errdefer union_obj.setStatus(ip, io, prev_status);
3484535071
34846 union_obj.setStatus(ip, .fully_resolved_wip);35072 union_obj.setStatus(ip, io, .fully_resolved_wip);
34847 for (0..union_obj.field_types.len) |field_index| {35073 for (0..union_obj.field_types.len) |field_index| {
34848 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);35074 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
34849 try field_ty.resolveFully(pt);35075 try field_ty.resolveFully(pt);
34850 }35076 }
34851 union_obj.setStatus(ip, .fully_resolved);35077 union_obj.setStatus(ip, io, .fully_resolved);
34852 }35078 }
3485335079
34854 // And let's not forget comptime-only status.35080 // And let's not forget comptime-only status.
...@@ -34862,13 +35088,14 @@ pub fn resolveStructFieldTypes(...@@ -34862,13 +35088,14 @@ pub fn resolveStructFieldTypes(
34862) SemaError!void {35088) SemaError!void {
34863 const pt = sema.pt;35089 const pt = sema.pt;
34864 const zcu = pt.zcu;35090 const zcu = pt.zcu;
35091 const io = zcu.comp.io;
34865 const ip = &zcu.intern_pool;35092 const ip = &zcu.intern_pool;
3486635093
34867 assert(sema.owner.unwrap().type == ty);35094 assert(sema.owner.unwrap().type == ty);
3486835095
34869 if (struct_type.haveFieldTypes(ip)) return;35096 if (struct_type.haveFieldTypes(ip)) return;
3487035097
34871 if (struct_type.setFieldTypesWip(ip)) {35098 if (struct_type.setFieldTypesWip(ip, io)) {
34872 const msg = try sema.errMsg(35099 const msg = try sema.errMsg(
34873 Type.fromInterned(ty).srcLoc(zcu),35100 Type.fromInterned(ty).srcLoc(zcu),
34874 "struct '{f}' depends on itself",35101 "struct '{f}' depends on itself",
...@@ -34876,7 +35103,7 @@ pub fn resolveStructFieldTypes(...@@ -34876,7 +35103,7 @@ pub fn resolveStructFieldTypes(
34876 );35103 );
34877 return sema.failWithOwnedErrorMsg(null, msg);35104 return sema.failWithOwnedErrorMsg(null, msg);
34878 }35105 }
34879 defer struct_type.clearFieldTypesWip(ip);35106 defer struct_type.clearFieldTypesWip(ip, io);
3488035107
34881 // can't happen earlier than this because we only want the progress node if not already resolved35108 // can't happen earlier than this because we only want the progress node if not already resolved
34882 const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null);35109 const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null);
...@@ -34891,6 +35118,7 @@ pub fn resolveStructFieldTypes(...@@ -34891,6 +35118,7 @@ pub fn resolveStructFieldTypes(
34891pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {35118pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
34892 const pt = sema.pt;35119 const pt = sema.pt;
34893 const zcu = pt.zcu;35120 const zcu = pt.zcu;
35121 const io = zcu.comp.io;
34894 const ip = &zcu.intern_pool;35122 const ip = &zcu.intern_pool;
34895 const struct_type = zcu.typeToStruct(ty) orelse return;35123 const struct_type = zcu.typeToStruct(ty) orelse return;
3489635124
...@@ -34901,7 +35129,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -34901,7 +35129,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
3490135129
34902 try sema.resolveStructLayout(ty);35130 try sema.resolveStructLayout(ty);
3490335131
34904 if (struct_type.setInitsWip(ip)) {35132 if (struct_type.setInitsWip(ip, io)) {
34905 const msg = try sema.errMsg(35133 const msg = try sema.errMsg(
34906 ty.srcLoc(zcu),35134 ty.srcLoc(zcu),
34907 "struct '{f}' depends on itself",35135 "struct '{f}' depends on itself",
...@@ -34909,7 +35137,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -34909,7 +35137,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
34909 );35137 );
34910 return sema.failWithOwnedErrorMsg(null, msg);35138 return sema.failWithOwnedErrorMsg(null, msg);
34911 }35139 }
34912 defer struct_type.clearInitsWip(ip);35140 defer struct_type.clearInitsWip(ip, io);
3491335141
34914 // can't happen earlier than this because we only want the progress node if not already resolved35142 // can't happen earlier than this because we only want the progress node if not already resolved
34915 const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null);35143 const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null);
...@@ -34919,12 +35147,13 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -34919,12 +35147,13 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
34919 error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e,35147 error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e,
34920 error.ComptimeBreak, error.ComptimeReturn => unreachable,35148 error.ComptimeBreak, error.ComptimeReturn => unreachable,
34921 };35149 };
34922 struct_type.setHaveFieldInits(ip);35150 struct_type.setHaveFieldInits(ip, io);
34923}35151}
3492435152
34925pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) SemaError!void {35153pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) SemaError!void {
34926 const pt = sema.pt;35154 const pt = sema.pt;
34927 const zcu = pt.zcu;35155 const zcu = pt.zcu;
35156 const io = zcu.comp.io;
34928 const ip = &zcu.intern_pool;35157 const ip = &zcu.intern_pool;
3492935158
34930 assert(sema.owner.unwrap().type == ty.toIntern());35159 assert(sema.owner.unwrap().type == ty.toIntern());
...@@ -34947,13 +35176,13 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load...@@ -34947,13 +35176,13 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
34947 const tracked_unit = zcu.trackUnitSema(union_type.name.toSlice(ip), null);35176 const tracked_unit = zcu.trackUnitSema(union_type.name.toSlice(ip), null);
34948 defer tracked_unit.end(zcu);35177 defer tracked_unit.end(zcu);
3494935178
34950 union_type.setStatus(ip, .field_types_wip);35179 union_type.setStatus(ip, io, .field_types_wip);
34951 errdefer union_type.setStatus(ip, .none);35180 errdefer union_type.setStatus(ip, io, .none);
34952 sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) {35181 sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) {
34953 error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e,35182 error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e,
34954 error.ComptimeBreak, error.ComptimeReturn => unreachable,35183 error.ComptimeBreak, error.ComptimeReturn => unreachable,
34955 };35184 };
34956 union_type.setStatus(ip, .have_field_types);35185 union_type.setStatus(ip, io, .have_field_types);
34957}35186}
3495835187
34959/// Returns a normal error set corresponding to the fully populated inferred35188/// Returns a normal error set corresponding to the fully populated inferred
...@@ -35055,11 +35284,14 @@ fn resolveAdHocInferredErrorSet(...@@ -35055,11 +35284,14 @@ fn resolveAdHocInferredErrorSet(
35055) CompileError!InternPool.Index {35284) CompileError!InternPool.Index {
35056 const pt = sema.pt;35285 const pt = sema.pt;
35057 const zcu = pt.zcu;35286 const zcu = pt.zcu;
35058 const gpa = sema.gpa;35287 const comp = zcu.comp;
35288 const gpa = comp.gpa;
35289 const io = comp.io;
35059 const ip = &zcu.intern_pool;35290 const ip = &zcu.intern_pool;
35291
35060 const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value));35292 const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value));
35061 if (new_ty == .none) return value;35293 if (new_ty == .none) return value;
35062 return ip.getCoerced(gpa, pt.tid, value, new_ty);35294 return ip.getCoerced(gpa, io, pt.tid, value, new_ty);
35063}35295}
3506435296
35065fn resolveAdHocInferredErrorSetTy(35297fn resolveAdHocInferredErrorSetTy(
...@@ -35159,8 +35391,11 @@ fn structFields(...@@ -35159,8 +35391,11 @@ fn structFields(
35159) CompileError!void {35391) CompileError!void {
35160 const pt = sema.pt;35392 const pt = sema.pt;
35161 const zcu = pt.zcu;35393 const zcu = pt.zcu;
35162 const gpa = zcu.gpa;35394 const comp = zcu.comp;
35395 const gpa = comp.gpa;
35396 const io = comp.io;
35163 const ip = &zcu.intern_pool;35397 const ip = &zcu.intern_pool;
35398
35164 const namespace_index = struct_type.namespace;35399 const namespace_index = struct_type.namespace;
35165 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?;35400 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?;
35166 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;35401 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
...@@ -35173,7 +35408,7 @@ fn structFields(...@@ -35173,7 +35408,7 @@ fn structFields(
35173 return;35408 return;
35174 },35409 },
35175 .auto, .@"extern" => {35410 .auto, .@"extern" => {
35176 struct_type.setLayoutResolved(ip, 0, .none);35411 struct_type.setLayoutResolved(ip, io, 0, .none);
35177 return;35412 return;
35178 },35413 },
35179 };35414 };
...@@ -35245,7 +35480,7 @@ fn structFields(...@@ -35245,7 +35480,7 @@ fn structFields(
35245 extra_index += 1;35480 extra_index += 1;
3524635481
35247 // This string needs to outlive the ZIR code.35482 // This string needs to outlive the ZIR code.
35248 const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls);35483 const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls);
35249 assert(struct_type.addFieldName(ip, field_name) == null);35484 assert(struct_type.addFieldName(ip, field_name) == null);
3525035485
35251 if (has_align) {35486 if (has_align) {
...@@ -35345,8 +35580,8 @@ fn structFields(...@@ -35345,8 +35580,8 @@ fn structFields(
35345 extra_index += zir_field.init_body_len;35580 extra_index += zir_field.init_body_len;
35346 }35581 }
3534735582
35348 struct_type.clearFieldTypesWip(ip);35583 struct_type.clearFieldTypesWip(ip, io);
35349 if (!any_inits) struct_type.setHaveFieldInits(ip);35584 if (!any_inits) struct_type.setHaveFieldInits(ip, io);
3535035585
35351 try sema.flushExports();35586 try sema.flushExports();
35352}35587}
...@@ -35485,8 +35720,11 @@ fn unionFields(...@@ -35485,8 +35720,11 @@ fn unionFields(
3548535720
35486 const pt = sema.pt;35721 const pt = sema.pt;
35487 const zcu = pt.zcu;35722 const zcu = pt.zcu;
35488 const gpa = zcu.gpa;35723 const comp = zcu.comp;
35724 const gpa = comp.gpa;
35725 const io = comp.io;
35489 const ip = &zcu.intern_pool;35726 const ip = &zcu.intern_pool;
35727
35490 const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir.?;35728 const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir.?;
35491 const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail;35729 const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
35492 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;35730 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
...@@ -35595,7 +35833,7 @@ fn unionFields(...@@ -35595,7 +35833,7 @@ fn unionFields(
35595 .enum_type => ip.loadEnumType(provided_ty.toIntern()),35833 .enum_type => ip.loadEnumType(provided_ty.toIntern()),
35596 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}),35834 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}),
35597 };35835 };
35598 union_type.setTagType(ip, provided_ty.toIntern());35836 union_type.setTagType(ip, io, provided_ty.toIntern());
35599 // The fields of the union must match the enum exactly.35837 // The fields of the union must match the enum exactly.
35600 // A flag per field is used to check for missing and extraneous fields.35838 // A flag per field is used to check for missing and extraneous fields.
35601 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);35839 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
...@@ -35727,7 +35965,7 @@ fn unionFields(...@@ -35727,7 +35965,7 @@ fn unionFields(
35727 }35965 }
3572835966
35729 // This string needs to outlive the ZIR code.35967 // This string needs to outlive the ZIR code.
35730 const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls);35968 const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls);
35731 if (enum_field_names.len != 0) {35969 if (enum_field_names.len != 0) {
35732 enum_field_names[field_i] = field_name;35970 enum_field_names[field_i] = field_name;
35733 }35971 }
...@@ -35871,10 +36109,10 @@ fn unionFields(...@@ -35871,10 +36109,10 @@ fn unionFields(
35871 }36109 }
35872 } else if (enum_field_vals.count() > 0) {36110 } else if (enum_field_vals.count() > 0) {
35873 const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_ty, union_type.name);36111 const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_ty, union_type.name);
35874 union_type.setTagType(ip, enum_ty);36112 union_type.setTagType(ip, io, enum_ty);
35875 } else {36113 } else {
35876 const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_ty, union_type.name);36114 const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_ty, union_type.name);
35877 union_type.setTagType(ip, enum_ty);36115 union_type.setTagType(ip, io, enum_ty);
35878 }36116 }
3587936117
35880 try sema.flushExports();36118 try sema.flushExports();
...@@ -35890,18 +36128,21 @@ fn generateUnionTagTypeNumbered(...@@ -35890,18 +36128,21 @@ fn generateUnionTagTypeNumbered(
35890) !InternPool.Index {36128) !InternPool.Index {
35891 const pt = sema.pt;36129 const pt = sema.pt;
35892 const zcu = pt.zcu;36130 const zcu = pt.zcu;
35893 const gpa = sema.gpa;36131 const comp = zcu.comp;
36132 const gpa = comp.gpa;
36133 const io = comp.io;
35894 const ip = &zcu.intern_pool;36134 const ip = &zcu.intern_pool;
3589536135
35896 const name = try ip.getOrPutStringFmt(36136 const name = try ip.getOrPutStringFmt(
35897 gpa,36137 gpa,
36138 io,
35898 pt.tid,36139 pt.tid,
35899 "@typeInfo({f}).@\"union\".tag_type.?",36140 "@typeInfo({f}).@\"union\".tag_type.?",
35900 .{union_name.fmt(ip)},36141 .{union_name.fmt(ip)},
35901 .no_embedded_nulls,36142 .no_embedded_nulls,
35902 );36143 );
3590336144
35904 const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{36145 const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{
35905 .name = name,36146 .name = name,
35906 .owner_union_ty = union_type,36147 .owner_union_ty = union_type,
35907 .tag_ty = if (enum_field_vals.len == 0)36148 .tag_ty = if (enum_field_vals.len == 0)
...@@ -35926,18 +36167,21 @@ fn generateUnionTagTypeSimple(...@@ -35926,18 +36167,21 @@ fn generateUnionTagTypeSimple(
35926) !InternPool.Index {36167) !InternPool.Index {
35927 const pt = sema.pt;36168 const pt = sema.pt;
35928 const zcu = pt.zcu;36169 const zcu = pt.zcu;
36170 const comp = zcu.comp;
36171 const gpa = comp.gpa;
36172 const io = comp.io;
35929 const ip = &zcu.intern_pool;36173 const ip = &zcu.intern_pool;
35930 const gpa = sema.gpa;
3593136174
35932 const name = try ip.getOrPutStringFmt(36175 const name = try ip.getOrPutStringFmt(
35933 gpa,36176 gpa,
36177 io,
35934 pt.tid,36178 pt.tid,
35935 "@typeInfo({f}).@\"union\".tag_type.?",36179 "@typeInfo({f}).@\"union\".tag_type.?",
35936 .{union_name.fmt(ip)},36180 .{union_name.fmt(ip)},
35937 .no_embedded_nulls,36181 .no_embedded_nulls,
35938 );36182 );
3593936183
35940 const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{36184 const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{
35941 .name = name,36185 .name = name,
35942 .owner_union_ty = union_type,36186 .owner_union_ty = union_type,
35943 .tag_ty = (try pt.smallestUnsignedInt(enum_field_names.len -| 1)).toIntern(),36187 .tag_ty = (try pt.smallestUnsignedInt(enum_field_names.len -| 1)).toIntern(),
...@@ -35958,7 +36202,11 @@ fn generateUnionTagTypeSimple(...@@ -35958,7 +36202,11 @@ fn generateUnionTagTypeSimple(
35958pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {36202pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35959 const pt = sema.pt;36203 const pt = sema.pt;
35960 const zcu = pt.zcu;36204 const zcu = pt.zcu;
36205 const comp = zcu.comp;
36206 const gpa = comp.gpa;
36207 const io = comp.io;
35961 const ip = &zcu.intern_pool;36208 const ip = &zcu.intern_pool;
36209
35962 return switch (ty.toIntern()) {36210 return switch (ty.toIntern()) {
35963 .u0_type,36211 .u0_type,
35964 .i0_type,36212 .i0_type,
...@@ -36302,7 +36550,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36302,7 +36550,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36302 (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern()36550 (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern()
36303 else36551 else
36304 try ip.getCoercedInts(36552 try ip.getCoercedInts(
36305 zcu.gpa,36553 gpa,
36554 io,
36306 pt.tid,36555 pt.tid,
36307 ip.indexToKey(enum_type.values.get(ip)[0]).int,36556 ip.indexToKey(enum_type.values.get(ip)[0]).int,
36308 enum_type.tag_ty,36557 enum_type.tag_ty,
...@@ -36936,12 +37185,16 @@ fn checkRuntimeValue(sema: *Sema, ptr: Air.Inst.Ref) bool {...@@ -36936,12 +37185,16 @@ fn checkRuntimeValue(sema: *Sema, ptr: Air.Inst.Ref) bool {
36936fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Air.Inst.Ref) CompileError!void {37185fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Air.Inst.Ref) CompileError!void {
36937 if (sema.checkRuntimeValue(val)) return;37186 if (sema.checkRuntimeValue(val)) return;
36938 return sema.failWithOwnedErrorMsg(block, msg: {37187 return sema.failWithOwnedErrorMsg(block, msg: {
36939 const msg = try sema.errMsg(val_src, "runtime value contains reference to comptime var", .{});
36940 errdefer msg.destroy(sema.gpa);
36941 try sema.errNote(val_src, msg, "comptime var pointers are not available at runtime", .{});
36942 const pt = sema.pt;37188 const pt = sema.pt;
36943 const zcu = pt.zcu;37189 const zcu = pt.zcu;
36944 const val_str = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, "runtime_value", .no_embedded_nulls);37190 const comp = zcu.comp;
37191 const gpa = comp.gpa;
37192 const io = comp.io;
37193
37194 const msg = try sema.errMsg(val_src, "runtime value contains reference to comptime var", .{});
37195 errdefer msg.destroy(gpa);
37196 try sema.errNote(val_src, msg, "comptime var pointers are not available at runtime", .{});
37197 const val_str = try pt.zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "runtime_value", .no_embedded_nulls);
36945 try sema.explainWhyValueContainsReferenceToComptimeVar(msg, val_src, val_str, .fromInterned(val.toInterned().?));37198 try sema.explainWhyValueContainsReferenceToComptimeVar(msg, val_src, val_str, .fromInterned(val.toInterned().?));
36946 break :msg msg;37199 break :msg msg;
36947 });37200 });
...@@ -37385,7 +37638,9 @@ fn resolveDeclaredEnumInner(...@@ -37385,7 +37638,9 @@ fn resolveDeclaredEnumInner(
37385) Zcu.CompileError!void {37638) Zcu.CompileError!void {
37386 const pt = sema.pt;37639 const pt = sema.pt;
37387 const zcu = pt.zcu;37640 const zcu = pt.zcu;
37388 const gpa = zcu.gpa;37641 const comp = zcu.comp;
37642 const gpa = comp.gpa;
37643 const io = comp.io;
37389 const ip = &zcu.intern_pool;37644 const ip = &zcu.intern_pool;
3739037645
37391 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;37646 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
...@@ -37430,7 +37685,7 @@ fn resolveDeclaredEnumInner(...@@ -37430,7 +37685,7 @@ fn resolveDeclaredEnumInner(
37430 const field_name_zir = zir.nullTerminatedString(field_name_index);37685 const field_name_zir = zir.nullTerminatedString(field_name_index);
37431 extra_index += 1; // field name37686 extra_index += 1; // field name
3743237687
37433 const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls);37688 const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls);
3743437689
37435 const value_src: LazySrcLoc = .{37690 const value_src: LazySrcLoc = .{
37436 .base_node_inst = tracked_inst,37691 .base_node_inst = tracked_inst,
...@@ -37541,7 +37796,9 @@ pub fn resolveNavPtrModifiers(...@@ -37541,7 +37796,9 @@ pub fn resolveNavPtrModifiers(
37541) CompileError!NavPtrModifiers {37796) CompileError!NavPtrModifiers {
37542 const pt = sema.pt;37797 const pt = sema.pt;
37543 const zcu = pt.zcu;37798 const zcu = pt.zcu;
37544 const gpa = zcu.gpa;37799 const comp = zcu.comp;
37800 const gpa = comp.gpa;
37801 const io = comp.io;
37545 const ip = &zcu.intern_pool;37802 const ip = &zcu.intern_pool;
3754637803
37547 const align_src = block.src(.{ .node_offset_var_decl_align = .zero });37804 const align_src = block.src(.{ .node_offset_var_decl_align = .zero });
...@@ -37563,7 +37820,7 @@ pub fn resolveNavPtrModifiers(...@@ -37563,7 +37820,7 @@ pub fn resolveNavPtrModifiers(
37563 } else if (bytes.len == 0) {37820 } else if (bytes.len == 0) {
37564 return sema.fail(block, section_src, "linksection cannot be empty", .{});37821 return sema.fail(block, section_src, "linksection cannot be empty", .{});
37565 }37822 }
37566 break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);37823 break :ls try ip.getOrPutStringOpt(gpa, io, pt.tid, bytes, .no_embedded_nulls);
37567 };37824 };
3756837825
37569 const @"addrspace": std.builtin.AddressSpace = as: {37826 const @"addrspace": std.builtin.AddressSpace = as: {
...@@ -37595,8 +37852,10 @@ pub fn resolveNavPtrModifiers(...@@ -37595,8 +37852,10 @@ pub fn resolveNavPtrModifiers(
37595pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool {37852pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool {
37596 const pt = sema.pt;37853 const pt = sema.pt;
37597 const zcu = pt.zcu;37854 const zcu = pt.zcu;
37855 const comp = zcu.comp;
37856 const gpa = comp.gpa;
37857 const io = comp.io;
37598 const ip = &zcu.intern_pool;37858 const ip = &zcu.intern_pool;
37599 const gpa = zcu.gpa;
3760037859
37601 var any_changed = false;37860 var any_changed = false;
3760237861
...@@ -37613,7 +37872,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,...@@ -37613,7 +37872,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
37613 },37872 },
37614 };37873 };
3761537874
37616 const name_nts = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);37875 const name_nts = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls);
37617 const nav = try sema.namespaceLookup(block, simple_src, parent_ns, name_nts) orelse37876 const nav = try sema.namespaceLookup(block, simple_src, parent_ns, name_nts) orelse
37618 return sema.fail(block, simple_src, "{s} missing {s}", .{ parent_name, name });37877 return sema.fail(block, simple_src, "{s} missing {s}", .{ parent_name, name });
3761937878
src/Sema/LowerZon.zig+51-24
...@@ -38,8 +38,11 @@ pub fn run(...@@ -38,8 +38,11 @@ pub fn run(
38 block: *Sema.Block,38 block: *Sema.Block,
39) CompileError!InternPool.Index {39) CompileError!InternPool.Index {
40 const pt = sema.pt;40 const pt = sema.pt;
41 const comp = pt.zcu.comp;
42 const gpa = comp.gpa;
43 const io = comp.io;
4144
42 const tracked_inst = try pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{45 const tracked_inst = try pt.zcu.intern_pool.trackZir(gpa, io, pt.tid, .{
43 .file = file_index,46 .file = file_index,
44 .inst = .main_struct_inst, // this is the only trackable instruction in a ZON file47 .inst = .main_struct_inst, // this is the only trackable instruction in a ZON file
45 });48 });
...@@ -63,8 +66,10 @@ pub fn run(...@@ -63,8 +66,10 @@ pub fn run(
63}66}
6467
65fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!InternPool.Index {68fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!InternPool.Index {
66 const gpa = self.sema.gpa;
67 const pt = self.sema.pt;69 const pt = self.sema.pt;
70 const comp = pt.zcu.comp;
71 const gpa = comp.gpa;
72 const io = comp.io;
68 const ip = &pt.zcu.intern_pool;73 const ip = &pt.zcu.intern_pool;
69 switch (node.get(self.file.zoir.?)) {74 switch (node.get(self.file.zoir.?)) {
70 .true => return .bool_true,75 .true => return .bool_true,
...@@ -94,13 +99,14 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter...@@ -94,13 +99,14 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
94 .enum_literal => |val| return pt.intern(.{99 .enum_literal => |val| return pt.intern(.{
95 .enum_literal = try ip.getOrPutString(100 .enum_literal = try ip.getOrPutString(
96 gpa,101 gpa,
102 io,
97 pt.tid,103 pt.tid,
98 val.get(self.file.zoir.?),104 val.get(self.file.zoir.?),
99 .no_embedded_nulls,105 .no_embedded_nulls,
100 ),106 ),
101 }),107 }),
102 .string_literal => |val| {108 .string_literal => |val| {
103 const ip_str = try ip.getOrPutString(gpa, pt.tid, val, .maybe_embedded_nulls);109 const ip_str = try ip.getOrPutString(gpa, io, pt.tid, val, .maybe_embedded_nulls);
104 const result = try self.sema.addStrLit(ip_str, val.len);110 const result = try self.sema.addStrLit(ip_str, val.len);
105 return result.toInterned().?;111 return result.toInterned().?;
106 },112 },
...@@ -112,14 +118,10 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter...@@ -112,14 +118,10 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
112 values[i] = try self.lowerExprAnonResTy(nodes.at(@intCast(i)));118 values[i] = try self.lowerExprAnonResTy(nodes.at(@intCast(i)));
113 types[i] = Value.fromInterned(values[i]).typeOf(pt.zcu).toIntern();119 types[i] = Value.fromInterned(values[i]).typeOf(pt.zcu).toIntern();
114 }120 }
115 const ty = try ip.getTupleType(121 const ty = try ip.getTupleType(gpa, io, pt.tid, .{
116 gpa,122 .types = types,
117 pt.tid,123 .values = values,
118 .{124 });
119 .types = types,
120 .values = values,
121 },
122 );
123 return (try pt.aggregateValue(.fromInterned(ty), values)).toIntern();125 return (try pt.aggregateValue(.fromInterned(ty), values)).toIntern();
124 },126 },
125 .struct_literal => |init| {127 .struct_literal => |init| {
...@@ -129,6 +131,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter...@@ -129,6 +131,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
129 }131 }
130 const struct_ty = switch (try ip.getStructType(132 const struct_ty = switch (try ip.getStructType(
131 gpa,133 gpa,
134 io,
132 pt.tid,135 pt.tid,
133 .{136 .{
134 .layout = .auto,137 .layout = .auto,
...@@ -168,6 +171,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter...@@ -168,6 +171,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
168 for (init.names, 0..) |name, field_idx| {171 for (init.names, 0..) |name, field_idx| {
169 const name_interned = try ip.getOrPutString(172 const name_interned = try ip.getOrPutString(
170 gpa,173 gpa,
174 io,
171 pt.tid,175 pt.tid,
172 name.get(self.file.zoir.?),176 name.get(self.file.zoir.?),
173 .no_embedded_nulls,177 .no_embedded_nulls,
...@@ -636,11 +640,16 @@ fn lowerArray(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -636,11 +640,16 @@ fn lowerArray(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
636}640}
637641
638fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index {642fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index {
639 const ip = &self.sema.pt.zcu.intern_pool;643 const pt = self.sema.pt;
644 const comp = pt.zcu.comp;
645 const gpa = comp.gpa;
646 const io = comp.io;
647 const ip = &pt.zcu.intern_pool;
640 switch (node.get(self.file.zoir.?)) {648 switch (node.get(self.file.zoir.?)) {
641 .enum_literal => |field_name| {649 .enum_literal => |field_name| {
642 const field_name_interned = try ip.getOrPutString(650 const field_name_interned = try ip.getOrPutString(
643 self.sema.gpa,651 gpa,
652 io,
644 self.sema.pt.tid,653 self.sema.pt.tid,
645 field_name.get(self.file.zoir.?),654 field_name.get(self.file.zoir.?),
646 .no_embedded_nulls,655 .no_embedded_nulls,
...@@ -665,11 +674,16 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I...@@ -665,11 +674,16 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I
665}674}
666675
667fn lowerEnumLiteral(self: *LowerZon, node: Zoir.Node.Index) !InternPool.Index {676fn lowerEnumLiteral(self: *LowerZon, node: Zoir.Node.Index) !InternPool.Index {
668 const ip = &self.sema.pt.zcu.intern_pool;677 const pt = self.sema.pt;
678 const comp = pt.zcu.comp;
679 const gpa = comp.gpa;
680 const io = comp.io;
681 const ip = &pt.zcu.intern_pool;
669 switch (node.get(self.file.zoir.?)) {682 switch (node.get(self.file.zoir.?)) {
670 .enum_literal => |field_name| {683 .enum_literal => |field_name| {
671 const field_name_interned = try ip.getOrPutString(684 const field_name_interned = try ip.getOrPutString(
672 self.sema.gpa,685 gpa,
686 io,
673 self.sema.pt.tid,687 self.sema.pt.tid,
674 field_name.get(self.file.zoir.?),688 field_name.get(self.file.zoir.?),
675 .no_embedded_nulls,689 .no_embedded_nulls,
...@@ -747,8 +761,11 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -747,8 +761,11 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
747}761}
748762
749fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index {763fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index {
750 const ip = &self.sema.pt.zcu.intern_pool;764 const pt = self.sema.pt;
751 const gpa = self.sema.gpa;765 const comp = pt.zcu.comp;
766 const gpa = comp.gpa;
767 const io = comp.io;
768 const ip = &pt.zcu.intern_pool;
752769
753 try res_ty.resolveFields(self.sema.pt);770 try res_ty.resolveFields(self.sema.pt);
754 try res_ty.resolveStructFieldInits(self.sema.pt);771 try res_ty.resolveStructFieldInits(self.sema.pt);
...@@ -772,6 +789,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool...@@ -772,6 +789,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
772 for (0..fields.names.len) |i| {789 for (0..fields.names.len) |i| {
773 const field_name = try ip.getOrPutString(790 const field_name = try ip.getOrPutString(
774 gpa,791 gpa,
792 io,
775 self.sema.pt.tid,793 self.sema.pt.tid,
776 fields.names[i].get(self.file.zoir.?),794 fields.names[i].get(self.file.zoir.?),
777 .no_embedded_nulls,795 .no_embedded_nulls,
...@@ -807,8 +825,11 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool...@@ -807,8 +825,11 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
807}825}
808826
809fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index {827fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index {
810 const ip = &self.sema.pt.zcu.intern_pool;828 const pt = self.sema.pt;
811 const gpa = self.sema.gpa;829 const comp = pt.zcu.comp;
830 const gpa = comp.gpa;
831 const io = comp.io;
832 const ip = &pt.zcu.intern_pool;
812833
813 const ptr_info = res_ty.ptrInfo(self.sema.pt.zcu);834 const ptr_info = res_ty.ptrInfo(self.sema.pt.zcu);
814835
...@@ -820,7 +841,7 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -820,7 +841,7 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
820 if (string_alignment and ptr_info.child == .u8_type and string_sentinel) {841 if (string_alignment and ptr_info.child == .u8_type and string_sentinel) {
821 switch (node.get(self.file.zoir.?)) {842 switch (node.get(self.file.zoir.?)) {
822 .string_literal => |val| {843 .string_literal => |val| {
823 const ip_str = try ip.getOrPutString(gpa, self.sema.pt.tid, val, .maybe_embedded_nulls);844 const ip_str = try ip.getOrPutString(gpa, io, self.sema.pt.tid, val, .maybe_embedded_nulls);
824 const str_ref = try self.sema.addStrLit(ip_str, val.len);845 const str_ref = try self.sema.addStrLit(ip_str, val.len);
825 return (try self.sema.coerce(846 return (try self.sema.coerce(
826 self.block,847 self.block,
...@@ -892,7 +913,11 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -892,7 +913,11 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
892}913}
893914
894fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index {915fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index {
895 const ip = &self.sema.pt.zcu.intern_pool;916 const pt = self.sema.pt;
917 const comp = pt.zcu.comp;
918 const gpa = comp.gpa;
919 const io = comp.io;
920 const ip = &pt.zcu.intern_pool;
896 try res_ty.resolveFields(self.sema.pt);921 try res_ty.resolveFields(self.sema.pt);
897 const union_info = self.sema.pt.zcu.typeToUnion(res_ty).?;922 const union_info = self.sema.pt.zcu.typeToUnion(res_ty).?;
898 const enum_tag_info = union_info.loadTagType(ip);923 const enum_tag_info = union_info.loadTagType(ip);
...@@ -900,7 +925,8 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -900,7 +925,8 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
900 const field_name, const maybe_field_node = switch (node.get(self.file.zoir.?)) {925 const field_name, const maybe_field_node = switch (node.get(self.file.zoir.?)) {
901 .enum_literal => |name| b: {926 .enum_literal => |name| b: {
902 const field_name = try ip.getOrPutString(927 const field_name = try ip.getOrPutString(
903 self.sema.gpa,928 gpa,
929 io,
904 self.sema.pt.tid,930 self.sema.pt.tid,
905 name.get(self.file.zoir.?),931 name.get(self.file.zoir.?),
906 .no_embedded_nulls,932 .no_embedded_nulls,
...@@ -916,7 +942,8 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -916,7 +942,8 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
916 return error.WrongType;942 return error.WrongType;
917 }943 }
918 const field_name = try ip.getOrPutString(944 const field_name = try ip.getOrPutString(
919 self.sema.gpa,945 gpa,
946 io,
920 self.sema.pt.tid,947 self.sema.pt.tid,
921 fields.names[0].get(self.file.zoir.?),948 fields.names[0].get(self.file.zoir.?),
922 .no_embedded_nulls,949 .no_embedded_nulls,
...@@ -942,7 +969,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool....@@ -942,7 +969,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
942 }969 }
943 break :b .void_value;970 break :b .void_value;
944 };971 };
945 return ip.getUnion(self.sema.pt.zcu.gpa, self.sema.pt.tid, .{972 return ip.getUnion(gpa, io, self.sema.pt.tid, .{
946 .ty = res_ty.toIntern(),973 .ty = res_ty.toIntern(),
947 .tag = tag.toIntern(),974 .tag = tag.toIntern(),
948 .val = val,975 .val = val,
src/Type.zig+20-14
...@@ -486,6 +486,7 @@ pub fn hasRuntimeBitsInner(...@@ -486,6 +486,7 @@ pub fn hasRuntimeBitsInner(
486 tid: strat.Tid(),486 tid: strat.Tid(),
487) RuntimeBitsError!bool {487) RuntimeBitsError!bool {
488 const ip = &zcu.intern_pool;488 const ip = &zcu.intern_pool;
489 const io = zcu.comp.io;
489 return switch (ty.toIntern()) {490 return switch (ty.toIntern()) {
490 .empty_tuple_type => false,491 .empty_tuple_type => false,
491 else => switch (ip.indexToKey(ty.toIntern())) {492 else => switch (ip.indexToKey(ty.toIntern())) {
...@@ -571,7 +572,7 @@ pub fn hasRuntimeBitsInner(...@@ -571,7 +572,7 @@ pub fn hasRuntimeBitsInner(
571 },572 },
572 .struct_type => {573 .struct_type => {
573 const struct_type = ip.loadStructType(ty.toIntern());574 const struct_type = ip.loadStructType(ty.toIntern());
574 if (strat != .eager and struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) {575 if (strat != .eager and struct_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) {
575 // In this case, we guess that hasRuntimeBits() for this type is true,576 // In this case, we guess that hasRuntimeBits() for this type is true,
576 // and then later if our guess was incorrect, we emit a compile error.577 // and then later if our guess was incorrect, we emit a compile error.
577 return true;578 return true;
...@@ -610,7 +611,7 @@ pub fn hasRuntimeBitsInner(...@@ -610,7 +611,7 @@ pub fn hasRuntimeBitsInner(
610 .none => if (strat != .eager) {611 .none => if (strat != .eager) {
611 // In this case, we guess that hasRuntimeBits() for this type is true,612 // In this case, we guess that hasRuntimeBits() for this type is true,
612 // and then later if our guess was incorrect, we emit a compile error.613 // and then later if our guess was incorrect, we emit a compile error.
613 if (union_type.assumeRuntimeBitsIfFieldTypesWip(ip)) return true;614 if (union_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) return true;
614 },615 },
615 .safety, .tagged => {},616 .safety, .tagged => {},
616 }617 }
...@@ -2491,8 +2492,11 @@ pub fn isNumeric(ty: Type, zcu: *const Zcu) bool {...@@ -2491,8 +2492,11 @@ pub fn isNumeric(ty: Type, zcu: *const Zcu) bool {
2491/// resolves field types rather than asserting they are already resolved.2492/// resolves field types rather than asserting they are already resolved.
2492pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {2493pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
2493 const zcu = pt.zcu;2494 const zcu = pt.zcu;
2494 var ty = starting_type;2495 const comp = zcu.comp;
2496 const gpa = comp.gpa;
2497 const io = comp.io;
2495 const ip = &zcu.intern_pool;2498 const ip = &zcu.intern_pool;
2499 var ty = starting_type;
2496 while (true) switch (ty.toIntern()) {2500 while (true) switch (ty.toIntern()) {
2497 .empty_tuple_type => return Value.empty_tuple,2501 .empty_tuple_type => return Value.empty_tuple,
24982502
...@@ -2664,7 +2668,8 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {...@@ -2664,7 +2668,8 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
2664 (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern()2668 (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern()
2665 else2669 else
2666 try ip.getCoercedInts(2670 try ip.getCoercedInts(
2667 zcu.gpa,2671 gpa,
2672 io,
2668 pt.tid,2673 pt.tid,
2669 ip.indexToKey(enum_type.values.get(ip)[0]).int,2674 ip.indexToKey(enum_type.values.get(ip)[0]).int,
2670 enum_type.tag_ty,2675 enum_type.tag_ty,
...@@ -2720,6 +2725,7 @@ pub fn comptimeOnlyInner(...@@ -2720,6 +2725,7 @@ pub fn comptimeOnlyInner(
2720 tid: strat.Tid(),2725 tid: strat.Tid(),
2721) SemaError!bool {2726) SemaError!bool {
2722 const ip = &zcu.intern_pool;2727 const ip = &zcu.intern_pool;
2728 const io = zcu.comp.io;
2723 return switch (ty.toIntern()) {2729 return switch (ty.toIntern()) {
2724 .empty_tuple_type => false,2730 .empty_tuple_type => false,
27252731
...@@ -2798,16 +2804,16 @@ pub fn comptimeOnlyInner(...@@ -2798,16 +2804,16 @@ pub fn comptimeOnlyInner(
2798 .yes => true,2804 .yes => true,
2799 .unknown => unreachable,2805 .unknown => unreachable,
2800 },2806 },
2801 .sema => switch (struct_type.setRequiresComptimeWip(ip)) {2807 .sema => switch (struct_type.setRequiresComptimeWip(ip, io)) {
2802 .no, .wip => false,2808 .no, .wip => false,
2803 .yes => true,2809 .yes => true,
2804 .unknown => {2810 .unknown => {
2805 if (struct_type.flagsUnordered(ip).field_types_wip) {2811 if (struct_type.flagsUnordered(ip).field_types_wip) {
2806 struct_type.setRequiresComptime(ip, .unknown);2812 struct_type.setRequiresComptime(ip, io, .unknown);
2807 return false;2813 return false;
2808 }2814 }
28092815
2810 errdefer struct_type.setRequiresComptime(ip, .unknown);2816 errdefer struct_type.setRequiresComptime(ip, io, .unknown);
28112817
2812 const pt = strat.pt(zcu, tid);2818 const pt = strat.pt(zcu, tid);
2813 try ty.resolveFields(pt);2819 try ty.resolveFields(pt);
...@@ -2821,12 +2827,12 @@ pub fn comptimeOnlyInner(...@@ -2821,12 +2827,12 @@ pub fn comptimeOnlyInner(
2821 // be considered resolved. Comptime-only types2827 // be considered resolved. Comptime-only types
2822 // still maintain a layout of their2828 // still maintain a layout of their
2823 // runtime-known fields.2829 // runtime-known fields.
2824 struct_type.setRequiresComptime(ip, .yes);2830 struct_type.setRequiresComptime(ip, io, .yes);
2825 return true;2831 return true;
2826 }2832 }
2827 }2833 }
28282834
2829 struct_type.setRequiresComptime(ip, .no);2835 struct_type.setRequiresComptime(ip, io, .no);
2830 return false;2836 return false;
2831 },2837 },
2832 },2838 },
...@@ -2850,16 +2856,16 @@ pub fn comptimeOnlyInner(...@@ -2850,16 +2856,16 @@ pub fn comptimeOnlyInner(
2850 .yes => true,2856 .yes => true,
2851 .unknown => unreachable,2857 .unknown => unreachable,
2852 },2858 },
2853 .sema => switch (union_type.setRequiresComptimeWip(ip)) {2859 .sema => switch (union_type.setRequiresComptimeWip(ip, io)) {
2854 .no, .wip => return false,2860 .no, .wip => return false,
2855 .yes => return true,2861 .yes => return true,
2856 .unknown => {2862 .unknown => {
2857 if (union_type.flagsUnordered(ip).status == .field_types_wip) {2863 if (union_type.flagsUnordered(ip).status == .field_types_wip) {
2858 union_type.setRequiresComptime(ip, .unknown);2864 union_type.setRequiresComptime(ip, io, .unknown);
2859 return false;2865 return false;
2860 }2866 }
28612867
2862 errdefer union_type.setRequiresComptime(ip, .unknown);2868 errdefer union_type.setRequiresComptime(ip, io, .unknown);
28632869
2864 const pt = strat.pt(zcu, tid);2870 const pt = strat.pt(zcu, tid);
2865 try ty.resolveFields(pt);2871 try ty.resolveFields(pt);
...@@ -2867,12 +2873,12 @@ pub fn comptimeOnlyInner(...@@ -2867,12 +2873,12 @@ pub fn comptimeOnlyInner(
2867 for (0..union_type.field_types.len) |field_idx| {2873 for (0..union_type.field_types.len) |field_idx| {
2868 const field_ty = union_type.field_types.get(ip)[field_idx];2874 const field_ty = union_type.field_types.get(ip)[field_idx];
2869 if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) {2875 if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) {
2870 union_type.setRequiresComptime(ip, .yes);2876 union_type.setRequiresComptime(ip, io, .yes);
2871 return true;2877 return true;
2872 }2878 }
2873 }2879 }
28742880
2875 union_type.setRequiresComptime(ip, .no);2881 union_type.setRequiresComptime(ip, io, .no);
2876 return false;2882 return false;
2877 },2883 },
2878 },2884 },
src/Value.zig+18-9
...@@ -60,18 +60,21 @@ pub fn fmtValueSemaFull(ctx: print_value.FormatContext) std.fmt.Alt(print_value....@@ -60,18 +60,21 @@ pub fn fmtValueSemaFull(ctx: print_value.FormatContext) std.fmt.Alt(print_value.
60/// Asserts `val` is an array of `u8`60/// Asserts `val` is an array of `u8`
61pub fn toIpString(val: Value, ty: Type, pt: Zcu.PerThread) !InternPool.NullTerminatedString {61pub fn toIpString(val: Value, ty: Type, pt: Zcu.PerThread) !InternPool.NullTerminatedString {
62 const zcu = pt.zcu;62 const zcu = pt.zcu;
63 const comp = zcu.comp;
64 const gpa = comp.gpa;
65 const io = comp.io;
66 const ip = &zcu.intern_pool;
63 assert(ty.zigTypeTag(zcu) == .array);67 assert(ty.zigTypeTag(zcu) == .array);
64 assert(ty.childType(zcu).toIntern() == .u8_type);68 assert(ty.childType(zcu).toIntern() == .u8_type);
65 const ip = &zcu.intern_pool;
66 switch (zcu.intern_pool.indexToKey(val.toIntern()).aggregate.storage) {69 switch (zcu.intern_pool.indexToKey(val.toIntern()).aggregate.storage) {
67 .bytes => |bytes| return bytes.toNullTerminatedString(ty.arrayLen(zcu), ip),70 .bytes => |bytes| return bytes.toNullTerminatedString(ty.arrayLen(zcu), ip),
68 .elems => return arrayToIpString(val, ty.arrayLen(zcu), pt),71 .elems => return arrayToIpString(val, ty.arrayLen(zcu), pt),
69 .repeated_elem => |elem| {72 .repeated_elem => |elem| {
70 const byte: u8 = @intCast(Value.fromInterned(elem).toUnsignedInt(zcu));73 const byte: u8 = @intCast(Value.fromInterned(elem).toUnsignedInt(zcu));
71 const len: u32 = @intCast(ty.arrayLen(zcu));74 const len: u32 = @intCast(ty.arrayLen(zcu));
72 const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(zcu.gpa);75 const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa, io);
73 try string_bytes.appendNTimes(.{byte}, len);76 try string_bytes.appendNTimes(.{byte}, len);
74 return ip.getOrPutTrailingString(zcu.gpa, pt.tid, len, .no_embedded_nulls);77 return ip.getOrPutTrailingString(gpa, io, pt.tid, len, .no_embedded_nulls);
75 },78 },
76 }79 }
77}80}
...@@ -109,10 +112,12 @@ fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, pt: Zcu.Per...@@ -109,10 +112,12 @@ fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, pt: Zcu.Per
109112
110fn arrayToIpString(val: Value, len_u64: u64, pt: Zcu.PerThread) !InternPool.NullTerminatedString {113fn arrayToIpString(val: Value, len_u64: u64, pt: Zcu.PerThread) !InternPool.NullTerminatedString {
111 const zcu = pt.zcu;114 const zcu = pt.zcu;
112 const gpa = zcu.gpa;115 const comp = zcu.comp;
116 const gpa = comp.gpa;
117 const io = comp.io;
113 const ip = &zcu.intern_pool;118 const ip = &zcu.intern_pool;
114 const len: u32 = @intCast(len_u64);119 const len: u32 = @intCast(len_u64);
115 const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa);120 const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa, io);
116 try string_bytes.ensureUnusedCapacity(len);121 try string_bytes.ensureUnusedCapacity(len);
117 for (0..len) |i| {122 for (0..len) |i| {
118 // I don't think elemValue has the possibility to affect ip.string_bytes. Let's123 // I don't think elemValue has the possibility to affect ip.string_bytes. Let's
...@@ -123,7 +128,7 @@ fn arrayToIpString(val: Value, len_u64: u64, pt: Zcu.PerThread) !InternPool.Null...@@ -123,7 +128,7 @@ fn arrayToIpString(val: Value, len_u64: u64, pt: Zcu.PerThread) !InternPool.Null
123 const byte: u8 = @intCast(elem_val.toUnsignedInt(zcu));128 const byte: u8 = @intCast(elem_val.toUnsignedInt(zcu));
124 string_bytes.appendAssumeCapacity(.{byte});129 string_bytes.appendAssumeCapacity(.{byte});
125 }130 }
126 return ip.getOrPutTrailingString(gpa, pt.tid, len, .no_embedded_nulls);131 return ip.getOrPutTrailingString(gpa, io, pt.tid, len, .no_embedded_nulls);
127}132}
128133
129pub fn fromInterned(i: InternPool.Index) Value {134pub fn fromInterned(i: InternPool.Index) Value {
...@@ -1141,6 +1146,7 @@ pub fn sliceArray(...@@ -1141,6 +1146,7 @@ pub fn sliceArray(
1141) error{OutOfMemory}!Value {1146) error{OutOfMemory}!Value {
1142 const pt = sema.pt;1147 const pt = sema.pt;
1143 const ip = &pt.zcu.intern_pool;1148 const ip = &pt.zcu.intern_pool;
1149 const io = pt.zcu.comp.io;
1144 return Value.fromInterned(try pt.intern(.{1150 return Value.fromInterned(try pt.intern(.{
1145 .aggregate = .{1151 .aggregate = .{
1146 .ty = switch (pt.zcu.intern_pool.indexToKey(pt.zcu.intern_pool.typeOf(val.toIntern()))) {1152 .ty = switch (pt.zcu.intern_pool.indexToKey(pt.zcu.intern_pool.typeOf(val.toIntern()))) {
...@@ -1160,6 +1166,7 @@ pub fn sliceArray(...@@ -1160,6 +1166,7 @@ pub fn sliceArray(
1160 try ip.string_bytes.ensureUnusedCapacity(sema.gpa, end - start + 1);1166 try ip.string_bytes.ensureUnusedCapacity(sema.gpa, end - start + 1);
1161 break :storage .{ .bytes = try ip.getOrPutString(1167 break :storage .{ .bytes = try ip.getOrPutString(
1162 sema.gpa,1168 sema.gpa,
1169 io,
1163 bytes.toSlice(end, ip)[start..],1170 bytes.toSlice(end, ip)[start..],
1164 .maybe_embedded_nulls,1171 .maybe_embedded_nulls,
1165 ) };1172 ) };
...@@ -2874,6 +2881,7 @@ const interpret_mode: InterpretMode = @field(InterpretMode, @tagName(build_optio...@@ -2874,6 +2881,7 @@ const interpret_mode: InterpretMode = @field(InterpretMode, @tagName(build_optio
2874/// `val` must be fully resolved.2881/// `val` must be fully resolved.
2875pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T {2882pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T {
2876 const zcu = pt.zcu;2883 const zcu = pt.zcu;
2884 const io = zcu.comp.io;
2877 const ip = &zcu.intern_pool;2885 const ip = &zcu.intern_pool;
2878 const ty = val.typeOf(zcu);2886 const ty = val.typeOf(zcu);
2879 if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch;2887 if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch;
...@@ -2960,7 +2968,7 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe...@@ -2960,7 +2968,7 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe
2960 const struct_obj = zcu.typeToStruct(ty) orelse return error.TypeMismatch;2968 const struct_obj = zcu.typeToStruct(ty) orelse return error.TypeMismatch;
2961 var result: T = undefined;2969 var result: T = undefined;
2962 inline for (@"struct".fields) |field| {2970 inline for (@"struct".fields) |field| {
2963 const field_name_ip = try ip.getOrPutString(zcu.gpa, pt.tid, field.name, .no_embedded_nulls);2971 const field_name_ip = try ip.getOrPutString(zcu.gpa, io, pt.tid, field.name, .no_embedded_nulls);
2964 @field(result, field.name) = if (struct_obj.nameIndex(ip, field_name_ip)) |field_idx| f: {2972 @field(result, field.name) = if (struct_obj.nameIndex(ip, field_name_ip)) |field_idx| f: {
2965 const field_val = try val.fieldValue(pt, field_idx);2973 const field_val = try val.fieldValue(pt, field_idx);
2966 break :f try field_val.interpret(field.type, pt);2974 break :f try field_val.interpret(field.type, pt);
...@@ -2979,6 +2987,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory...@@ -2979,6 +2987,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory
2979 const T = @TypeOf(val);2987 const T = @TypeOf(val);
29802988
2981 const zcu = pt.zcu;2989 const zcu = pt.zcu;
2990 const io = zcu.comp.io;
2982 const ip = &zcu.intern_pool;2991 const ip = &zcu.intern_pool;
2983 if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch;2992 if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch;
29842993
...@@ -3022,7 +3031,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory...@@ -3022,7 +3031,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory
3022 .@"enum" => switch (interpret_mode) {3031 .@"enum" => switch (interpret_mode) {
3023 .direct => try pt.enumValue(ty, (try uninterpret(@intFromEnum(val), ty.intTagType(zcu), pt)).toIntern()),3032 .direct => try pt.enumValue(ty, (try uninterpret(@intFromEnum(val), ty.intTagType(zcu), pt)).toIntern()),
3024 .by_name => {3033 .by_name => {
3025 const field_name_ip = try ip.getOrPutString(zcu.gpa, pt.tid, @tagName(val), .no_embedded_nulls);3034 const field_name_ip = try ip.getOrPutString(zcu.gpa, io, pt.tid, @tagName(val), .no_embedded_nulls);
3026 const field_idx = ty.enumFieldIndex(field_name_ip, zcu) orelse return error.TypeMismatch;3035 const field_idx = ty.enumFieldIndex(field_name_ip, zcu) orelse return error.TypeMismatch;
3027 return pt.enumValueFieldIndex(ty, field_idx);3036 return pt.enumValueFieldIndex(ty, field_idx);
3028 },3037 },
...@@ -3059,7 +3068,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory...@@ -3059,7 +3068,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory
3059 defer zcu.gpa.free(field_vals);3068 defer zcu.gpa.free(field_vals);
3060 @memset(field_vals, .none);3069 @memset(field_vals, .none);
3061 inline for (@"struct".fields) |field| {3070 inline for (@"struct".fields) |field| {
3062 const field_name_ip = try ip.getOrPutString(zcu.gpa, pt.tid, field.name, .no_embedded_nulls);3071 const field_name_ip = try ip.getOrPutString(zcu.gpa, io, pt.tid, field.name, .no_embedded_nulls);
3063 if (struct_obj.nameIndex(ip, field_name_ip)) |field_idx| {3072 if (struct_obj.nameIndex(ip, field_name_ip)) |field_idx| {
3064 const field_ty = ty.fieldType(field_idx, zcu);3073 const field_ty = ty.fieldType(field_idx, zcu);
3065 field_vals[field_idx] = (try uninterpret(@field(val, field.name), field_ty, pt)).toIntern();3074 field_vals[field_idx] = (try uninterpret(@field(val, field.name), field_ty, pt)).toIntern();
src/Zcu.zig+196-17
...@@ -37,6 +37,7 @@ const InternPool = @import("InternPool.zig");...@@ -37,6 +37,7 @@ const InternPool = @import("InternPool.zig");
37const Alignment = InternPool.Alignment;37const Alignment = InternPool.Alignment;
38const AnalUnit = InternPool.AnalUnit;38const AnalUnit = InternPool.AnalUnit;
39const BuiltinFn = std.zig.BuiltinFn;39const BuiltinFn = std.zig.BuiltinFn;
40const codegen = @import("codegen.zig");
40const LlvmObject = @import("codegen/llvm.zig").Object;41const LlvmObject = @import("codegen/llvm.zig").Object;
41const dev = @import("dev.zig");42const dev = @import("dev.zig");
42const Zoir = std.zig.Zoir;43const Zoir = std.zig.Zoir;
...@@ -317,6 +318,8 @@ incremental_debug_state: if (build_options.enable_debug_extensions) IncrementalD...@@ -317,6 +318,8 @@ incremental_debug_state: if (build_options.enable_debug_extensions) IncrementalD
317/// this timer must be temporarily paused and resumed later.318/// this timer must be temporarily paused and resumed later.
318cur_analysis_timer: ?Compilation.Timer = null,319cur_analysis_timer: ?Compilation.Timer = null,
319320
321codegen_task_pool: CodegenTaskPool,
322
320generation: u32 = 0,323generation: u32 = 0,
321324
322pub const IncrementalDebugState = struct {325pub const IncrementalDebugState = struct {
...@@ -895,12 +898,13 @@ pub const Namespace = struct {...@@ -895,12 +898,13 @@ pub const Namespace = struct {
895 ns: Namespace,898 ns: Namespace,
896 ip: *InternPool,899 ip: *InternPool,
897 gpa: Allocator,900 gpa: Allocator,
901 io: Io,
898 tid: Zcu.PerThread.Id,902 tid: Zcu.PerThread.Id,
899 name: InternPool.NullTerminatedString,903 name: InternPool.NullTerminatedString,
900 ) !InternPool.NullTerminatedString {904 ) !InternPool.NullTerminatedString {
901 const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip);905 const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip);
902 if (name == .empty) return ns_name;906 if (name == .empty) return ns_name;
903 return ip.getOrPutStringFmt(gpa, tid, "{f}.{f}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls);907 return ip.getOrPutStringFmt(gpa, io, tid, "{f}.{f}", .{ ns_name.fmt(ip), name.fmt(ip) }, .no_embedded_nulls);
904 }908 }
905};909};
906910
...@@ -1139,13 +1143,15 @@ pub const File = struct {...@@ -1139,13 +1143,15 @@ pub const File = struct {
1139 }1143 }
11401144
1141 pub fn internFullyQualifiedName(file: File, pt: Zcu.PerThread) !InternPool.NullTerminatedString {1145 pub fn internFullyQualifiedName(file: File, pt: Zcu.PerThread) !InternPool.NullTerminatedString {
1142 const gpa = pt.zcu.gpa;
1143 const ip = &pt.zcu.intern_pool;1146 const ip = &pt.zcu.intern_pool;
1144 const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa);1147 const comp = pt.zcu.comp;
1148 const gpa = comp.gpa;
1149 const io = comp.io;
1150 const string_bytes = ip.getLocal(pt.tid).getMutableStringBytes(gpa, io);
1145 var w: Writer = .fixed((try string_bytes.addManyAsSlice(file.fullyQualifiedNameLen()))[0]);1151 var w: Writer = .fixed((try string_bytes.addManyAsSlice(file.fullyQualifiedNameLen()))[0]);
1146 file.renderFullyQualifiedName(&w) catch unreachable;1152 file.renderFullyQualifiedName(&w) catch unreachable;
1147 assert(w.end == w.buffer.len);1153 assert(w.end == w.buffer.len);
1148 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(w.end), .no_embedded_nulls);1154 return ip.getOrPutTrailingString(gpa, io, pt.tid, @intCast(w.end), .no_embedded_nulls);
1149 }1155 }
11501156
1151 pub const Index = InternPool.FileIndex;1157 pub const Index = InternPool.FileIndex;
...@@ -2801,13 +2807,14 @@ pub const CompileError = error{...@@ -2801,13 +2807,14 @@ pub const CompileError = error{
2801 ComptimeBreak,2807 ComptimeBreak,
2802};2808};
28032809
2804pub fn init(zcu: *Zcu, thread_count: usize) !void {2810pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void {
2805 const gpa = zcu.gpa;2811 try zcu.intern_pool.init(gpa, io, thread_count);
2806 try zcu.intern_pool.init(gpa, thread_count);
2807}2812}
28082813
2809pub fn deinit(zcu: *Zcu) void {2814pub fn deinit(zcu: *Zcu) void {
2810 const gpa = zcu.gpa;2815 const comp = zcu.comp;
2816 const gpa = comp.gpa;
2817 const io = comp.io;
2811 {2818 {
2812 const pt: Zcu.PerThread = .activate(zcu, .main);2819 const pt: Zcu.PerThread = .activate(zcu, .main);
2813 defer pt.deactivate();2820 defer pt.deactivate();
...@@ -2897,7 +2904,7 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2897,7 +2904,7 @@ pub fn deinit(zcu: *Zcu) void {
2897 zcu.incremental_debug_state.deinit(gpa);2904 zcu.incremental_debug_state.deinit(gpa);
2898 }2905 }
2899 }2906 }
2900 zcu.intern_pool.deinit(gpa);2907 zcu.intern_pool.deinit(gpa, io);
2901}2908}
29022909
2903pub fn namespacePtr(zcu: *Zcu, index: Namespace.Index) *Namespace {2910pub fn namespacePtr(zcu: *Zcu, index: Namespace.Index) *Namespace {
...@@ -4442,7 +4449,7 @@ pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void {...@@ -4442,7 +4449,7 @@ pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void {
4442 try zcu.outdated_ready.put(gpa, unit, {});4449 try zcu.outdated_ready.put(gpa, unit, {});
4443 }4450 }
4444 }4451 }
4445 zcu.intern_pool.funcSetIesResolved(func_index, .none);4452 zcu.intern_pool.funcSetIesResolved(zcu.comp.io, func_index, .none);
4446 }4453 }
4447}4454}
44484455
...@@ -4620,10 +4627,12 @@ pub fn codegenFail(...@@ -4620,10 +4627,12 @@ pub fn codegenFail(
46204627
4621/// Takes ownership of `msg`, even on OOM.4628/// Takes ownership of `msg`, even on OOM.
4622pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg) CodegenFailError {4629pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg) CodegenFailError {
4623 const gpa = zcu.gpa;4630 const comp = zcu.comp;
4631 const gpa = comp.gpa;
4632 const io = comp.io;
4624 {4633 {
4625 zcu.comp.mutex.lock();4634 comp.mutex.lockUncancelable(io);
4626 defer zcu.comp.mutex.unlock();4635 defer comp.mutex.unlock(io);
4627 errdefer msg.deinit(gpa);4636 errdefer msg.deinit(gpa);
4628 try zcu.failed_codegen.putNoClobber(gpa, nav_index, msg);4637 try zcu.failed_codegen.putNoClobber(gpa, nav_index, msg);
4629 }4638 }
...@@ -4632,8 +4641,10 @@ pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg...@@ -4632,8 +4641,10 @@ pub fn codegenFailMsg(zcu: *Zcu, nav_index: InternPool.Nav.Index, msg: *ErrorMsg
46324641
4633/// Asserts that `zcu.failed_codegen` contains the key `nav`, with the necessary lock held.4642/// Asserts that `zcu.failed_codegen` contains the key `nav`, with the necessary lock held.
4634pub fn assertCodegenFailed(zcu: *Zcu, nav: InternPool.Nav.Index) void {4643pub fn assertCodegenFailed(zcu: *Zcu, nav: InternPool.Nav.Index) void {
4635 zcu.comp.mutex.lock();4644 const comp = zcu.comp;
4636 defer zcu.comp.mutex.unlock();4645 const io = comp.io;
4646 comp.mutex.lockUncancelable(io);
4647 defer comp.mutex.unlock(io);
4637 assert(zcu.failed_codegen.contains(nav));4648 assert(zcu.failed_codegen.contains(nav));
4638}4649}
46394650
...@@ -4794,8 +4805,9 @@ const TrackedUnitSema = struct {...@@ -4794,8 +4805,9 @@ const TrackedUnitSema = struct {
4794 report_time: {4805 report_time: {
4795 const sema_ns = zcu.cur_analysis_timer.?.finish() orelse break :report_time;4806 const sema_ns = zcu.cur_analysis_timer.?.finish() orelse break :report_time;
4796 const zir_decl = tus.analysis_timer_decl orelse break :report_time;4807 const zir_decl = tus.analysis_timer_decl orelse break :report_time;
4797 comp.mutex.lock();4808 const io = comp.io;
4798 defer comp.mutex.unlock();4809 comp.mutex.lockUncancelable(io);
4810 defer comp.mutex.unlock(io);
4799 comp.time_report.?.stats.cpu_ns_sema += sema_ns;4811 comp.time_report.?.stats.cpu_ns_sema += sema_ns;
4800 const gop = comp.time_report.?.decl_sema_info.getOrPut(comp.gpa, zir_decl) catch |err| switch (err) {4812 const gop = comp.time_report.?.decl_sema_info.getOrPut(comp.gpa, zir_decl) catch |err| switch (err) {
4801 error.OutOfMemory => {4813 error.OutOfMemory => {
...@@ -4830,3 +4842,170 @@ pub fn trackUnitSema(zcu: *Zcu, name: []const u8, zir_inst: ?InternPool.TrackedI...@@ -4830,3 +4842,170 @@ pub fn trackUnitSema(zcu: *Zcu, name: []const u8, zir_inst: ?InternPool.TrackedI
4830 .analysis_timer_decl = zir_inst,4842 .analysis_timer_decl = zir_inst,
4831 };4843 };
4832}4844}
4845
4846pub const CodegenTaskPool = struct {
4847 const CodegenResult = PerThread.RunCodegenError!codegen.AnyMir;
4848
4849 /// In the worst observed case, MIR is around 50 times as large as AIR. More typically, the ratio is
4850 /// around 20. Going by that 50x multiplier, and assuming we want to consume no more than 500 MiB of
4851 /// memory on AIR/MIR, we see a limit of around 10 MiB of AIR in-flight.
4852 const max_air_bytes_in_flight = 10 * 1024 * 1024;
4853
4854 const max_funcs_in_flight = @import("link.zig").Queue.buffer_size;
4855
4856 available_air_bytes: u32,
4857
4858 /// Locks the freelist and `available_air_bytes`.
4859 mutex: Io.Mutex,
4860
4861 /// Signaled when an item is added to the freelist.
4862 free_cond: Io.Condition,
4863 /// Pre-allocated with enough capacity for all indices.
4864 free: std.ArrayList(Index),
4865
4866 /// `.none` means this task is in the freelist. The `task_air_bytes` and
4867 /// `task_futures` entries are `undefined`.
4868 task_funcs: []InternPool.Index,
4869 task_air_bytes: []u32,
4870 task_futures: []Io.Future(CodegenResult),
4871
4872 pub fn init(arena: Allocator) Allocator.Error!CodegenTaskPool {
4873 const task_funcs = try arena.alloc(InternPool.Index, max_funcs_in_flight);
4874 const task_air_bytes = try arena.alloc(u32, max_funcs_in_flight);
4875 const task_futures = try arena.alloc(Io.Future(CodegenResult), max_funcs_in_flight);
4876 @memset(task_funcs, .none);
4877
4878 var free: std.ArrayList(Index) = try .initCapacity(arena, max_funcs_in_flight);
4879 for (0..max_funcs_in_flight) |index| free.appendAssumeCapacity(@enumFromInt(index));
4880
4881 return .{
4882 .available_air_bytes = max_air_bytes_in_flight,
4883 .mutex = .init,
4884 .free_cond = .init,
4885 .free = free,
4886 .task_funcs = task_funcs,
4887 .task_air_bytes = task_air_bytes,
4888 .task_futures = task_futures,
4889 };
4890 }
4891
4892 pub fn cancel(pool: *CodegenTaskPool, zcu: *const Zcu) void {
4893 const io = zcu.comp.io;
4894 for (
4895 pool.task_funcs,
4896 pool.task_air_bytes,
4897 pool.task_futures,
4898 ) |func, effective_air_bytes, *future| {
4899 if (func == .none) continue;
4900 pool.available_air_bytes += effective_air_bytes;
4901 var mir = future.cancel(io) catch continue;
4902 mir.deinit(zcu);
4903 }
4904 assert(pool.available_air_bytes == max_air_bytes_in_flight);
4905 }
4906
4907 pub fn start(
4908 pool: *CodegenTaskPool,
4909 zcu: *Zcu,
4910 func_index: InternPool.Index,
4911 air: *Air,
4912 /// If `true`, this function will take ownership of `air`, freeing it after codegen
4913 /// completes; it is not assumed that `air` will outlive this function. If `false`,
4914 /// codegen will operate on `air` via the given pointer, which it is assumed will
4915 /// outline the codegen task.
4916 move_air: bool,
4917 ) Io.Cancelable!Index {
4918 const io = zcu.comp.io;
4919
4920 // To avoid consuming an excessive amount of memory, there is a limit on the total number of AIR
4921 // bytes which can be in the codegen/link pipeline at one time. If we exceed this limit, we must
4922 // wait for codegen/link to finish some WIP functions so they catch up with us.
4923 const actual_air_bytes: u32 = @intCast(air.instructions.len * 5 + air.extra.items.len * 4);
4924 // We need to let all AIR through eventually, even if one function exceeds `max_air_bytes_in_flight`.
4925 const effective_air_bytes: u32 = @min(actual_air_bytes, max_air_bytes_in_flight);
4926 assert(effective_air_bytes > 0);
4927
4928 const index: Index = index: {
4929 try pool.mutex.lock(io);
4930 defer pool.mutex.unlock(io);
4931
4932 while (pool.free.items.len == 0 or pool.available_air_bytes < effective_air_bytes) {
4933 // The linker thread needs to catch up!
4934 try pool.free_cond.wait(io, &pool.mutex);
4935 }
4936
4937 pool.available_air_bytes -= effective_air_bytes;
4938 break :index pool.free.pop().?;
4939 };
4940
4941 // No turning back now: we're incrementing `pending_codegen_jobs` and starting the worker.
4942 errdefer comptime unreachable;
4943
4944 assert(zcu.pending_codegen_jobs.fetchAdd(1, .monotonic) > 0); // the "Code Generation" node is still active
4945 assert(pool.task_funcs[@intFromEnum(index)] == .none);
4946 pool.task_funcs[@intFromEnum(index)] = func_index;
4947 pool.task_air_bytes[@intFromEnum(index)] = actual_air_bytes;
4948 pool.task_futures[@intFromEnum(index)] = if (move_air) io.async(
4949 workerCodegenOwnedAir,
4950 .{ zcu, func_index, air.* },
4951 ) else io.async(
4952 workerCodegenExternalAir,
4953 .{ zcu, func_index, air },
4954 );
4955
4956 return index;
4957 }
4958 pub const Index = enum(u32) {
4959 _,
4960
4961 /// Blocks until codegen has completed, successfully or otherwise.
4962 /// The returned MIR is owned by the caller.
4963 pub fn wait(
4964 index: Index,
4965 pool: *CodegenTaskPool,
4966 io: Io,
4967 ) PerThread.RunCodegenError!struct { InternPool.Index, codegen.AnyMir } {
4968 const func = pool.task_funcs[@intFromEnum(index)];
4969 assert(func != .none);
4970 const effective_air_bytes = pool.task_air_bytes[@intFromEnum(index)];
4971 const result = pool.task_futures[@intFromEnum(index)].await(io);
4972
4973 pool.task_funcs[@intFromEnum(index)] = .none;
4974 pool.task_air_bytes[@intFromEnum(index)] = undefined;
4975 pool.task_futures[@intFromEnum(index)] = undefined;
4976
4977 {
4978 pool.mutex.lockUncancelable(io);
4979 defer pool.mutex.unlock(io);
4980 pool.available_air_bytes += effective_air_bytes;
4981 pool.free.appendAssumeCapacity(index);
4982 pool.free_cond.signal(io);
4983 }
4984
4985 return .{ func, try result };
4986 }
4987 };
4988 fn workerCodegenOwnedAir(
4989 zcu: *Zcu,
4990 func_index: InternPool.Index,
4991 orig_air: Air,
4992 ) CodegenResult {
4993 // We own `air` now, so we are responsbile for freeing it.
4994 var air = orig_air;
4995 defer air.deinit(zcu.comp.gpa);
4996 const tid = Compilation.getTid();
4997 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
4998 defer pt.deactivate();
4999 return pt.runCodegen(func_index, &air);
5000 }
5001 fn workerCodegenExternalAir(
5002 zcu: *Zcu,
5003 func_index: InternPool.Index,
5004 air: *Air,
5005 ) CodegenResult {
5006 const tid = Compilation.getTid();
5007 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
5008 defer pt.deactivate();
5009 return pt.runCodegen(func_index, air);
5010 }
5011};
src/Zcu/PerThread.zig+177-121
...@@ -269,8 +269,8 @@ pub fn updateFile(...@@ -269,8 +269,8 @@ pub fn updateFile(
269 // Any potential AST errors are converted to ZIR errors when we run AstGen/ZonGen.269 // Any potential AST errors are converted to ZIR errors when we run AstGen/ZonGen.
270 file.tree = try Ast.parse(gpa, source, file.getMode());270 file.tree = try Ast.parse(gpa, source, file.getMode());
271 if (timer.finish()) |ns_parse| {271 if (timer.finish()) |ns_parse| {
272 comp.mutex.lock();272 comp.mutex.lockUncancelable(io);
273 defer comp.mutex.unlock();273 defer comp.mutex.unlock(io);
274 comp.time_report.?.stats.cpu_ns_parse += ns_parse;274 comp.time_report.?.stats.cpu_ns_parse += ns_parse;
275 }275 }
276276
...@@ -295,8 +295,8 @@ pub fn updateFile(...@@ -295,8 +295,8 @@ pub fn updateFile(
295 },295 },
296 }296 }
297 if (timer.finish()) |ns_astgen| {297 if (timer.finish()) |ns_astgen| {
298 comp.mutex.lock();298 comp.mutex.lockUncancelable(io);
299 defer comp.mutex.unlock();299 defer comp.mutex.unlock(io);
300 comp.time_report.?.stats.cpu_ns_astgen += ns_astgen;300 comp.time_report.?.stats.cpu_ns_astgen += ns_astgen;
301 }301 }
302302
...@@ -315,8 +315,8 @@ pub fn updateFile(...@@ -315,8 +315,8 @@ pub fn updateFile(
315 switch (file.getMode()) {315 switch (file.getMode()) {
316 .zig => {316 .zig => {
317 if (file.zir.?.hasCompileErrors()) {317 if (file.zir.?.hasCompileErrors()) {
318 comp.mutex.lock();318 comp.mutex.lockUncancelable(io);
319 defer comp.mutex.unlock();319 defer comp.mutex.unlock(io);
320 try zcu.failed_files.putNoClobber(gpa, file_index, null);320 try zcu.failed_files.putNoClobber(gpa, file_index, null);
321 }321 }
322 if (file.zir.?.loweringFailed()) {322 if (file.zir.?.loweringFailed()) {
...@@ -328,8 +328,8 @@ pub fn updateFile(...@@ -328,8 +328,8 @@ pub fn updateFile(
328 .zon => {328 .zon => {
329 if (file.zoir.?.hasCompileErrors()) {329 if (file.zoir.?.hasCompileErrors()) {
330 file.status = .astgen_failure;330 file.status = .astgen_failure;
331 comp.mutex.lock();331 comp.mutex.lockUncancelable(io);
332 defer comp.mutex.unlock();332 defer comp.mutex.unlock(io);
333 try zcu.failed_files.putNoClobber(gpa, file_index, null);333 try zcu.failed_files.putNoClobber(gpa, file_index, null);
334 } else {334 } else {
335 file.status = .success;335 file.status = .success;
...@@ -415,7 +415,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -415,7 +415,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
415 const zcu = pt.zcu;415 const zcu = pt.zcu;
416 const comp = zcu.comp;416 const comp = zcu.comp;
417 const ip = &zcu.intern_pool;417 const ip = &zcu.intern_pool;
418 const gpa = zcu.gpa;418 const gpa = comp.gpa;
419 const io = comp.io;
419420
420 // We need to visit every updated File for every TrackedInst in InternPool.421 // We need to visit every updated File for every TrackedInst in InternPool.
421 // This only includes Zig files; ZON files are omitted.422 // This only includes Zig files; ZON files are omitted.
...@@ -459,7 +460,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -459,7 +460,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
459 return;460 return;
460461
461 for (ip.locals, 0..) |*local, tid| {462 for (ip.locals, 0..) |*local, tid| {
462 const tracked_insts_list = local.getMutableTrackedInsts(gpa);463 const tracked_insts_list = local.getMutableTrackedInsts(gpa, io);
463 for (tracked_insts_list.viewAllowEmpty().items(.@"0"), 0..) |*tracked_inst, tracked_inst_unwrapped_index| {464 for (tracked_insts_list.viewAllowEmpty().items(.@"0"), 0..) |*tracked_inst, tracked_inst_unwrapped_index| {
464 const file_index = tracked_inst.file;465 const file_index = tracked_inst.file;
465 const updated_file = updated_files.get(file_index) orelse continue;466 const updated_file = updated_files.get(file_index) orelse continue;
...@@ -530,6 +531,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -530,6 +531,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
530 if (old_decl.name == .empty) continue;531 if (old_decl.name == .empty) continue;
531 const name_ip = try zcu.intern_pool.getOrPutString(532 const name_ip = try zcu.intern_pool.getOrPutString(
532 zcu.gpa,533 zcu.gpa,
534 io,
533 pt.tid,535 pt.tid,
534 old_zir.nullTerminatedString(old_decl.name),536 old_zir.nullTerminatedString(old_decl.name),
535 .no_embedded_nulls,537 .no_embedded_nulls,
...@@ -545,6 +547,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -545,6 +547,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
545 if (new_decl.name == .empty) continue;547 if (new_decl.name == .empty) continue;
546 const name_ip = try zcu.intern_pool.getOrPutString(548 const name_ip = try zcu.intern_pool.getOrPutString(
547 zcu.gpa,549 zcu.gpa,
550 io,
548 pt.tid,551 pt.tid,
549 new_zir.nullTerminatedString(new_decl.name),552 new_zir.nullTerminatedString(new_decl.name),
550 .no_embedded_nulls,553 .no_embedded_nulls,
...@@ -575,7 +578,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -575,7 +578,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
575 }578 }
576 }579 }
577580
578 try ip.rehashTrackedInsts(gpa, pt.tid);581 try ip.rehashTrackedInsts(gpa, io, pt.tid);
579582
580 for (updated_files.keys(), updated_files.values()) |file_index, updated_file| {583 for (updated_files.keys(), updated_files.values()) |file_index, updated_file| {
581 const file = updated_file.file;584 const file = updated_file.file;
...@@ -700,7 +703,9 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized...@@ -700,7 +703,9 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized
700fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.CompileError!bool {703fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.CompileError!bool {
701 const zcu = pt.zcu;704 const zcu = pt.zcu;
702 const ip = &zcu.intern_pool;705 const ip = &zcu.intern_pool;
703 const gpa = zcu.gpa;706 const comp = zcu.comp;
707 const gpa = comp.gpa;
708 const io = comp.io;
704709
705 const unit: AnalUnit = .wrap(.{ .memoized_state = stage });710 const unit: AnalUnit = .wrap(.{ .memoized_state = stage });
706711
...@@ -716,7 +721,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)...@@ -716,7 +721,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)
716 const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index));721 const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index));
717 const std_namespace = std_type.getNamespaceIndex(zcu);722 const std_namespace = std_type.getNamespaceIndex(zcu);
718 try pt.ensureNamespaceUpToDate(std_namespace);723 try pt.ensureNamespaceUpToDate(std_namespace);
719 const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);724 const builtin_str = try ip.getOrPutString(gpa, io, pt.tid, "builtin", .no_embedded_nulls);
720 const builtin_nav = zcu.namespacePtr(std_namespace).pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse725 const builtin_nav = zcu.namespacePtr(std_namespace).pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse
721 @panic("lib/std.zig is corrupt and missing 'builtin'");726 @panic("lib/std.zig is corrupt and missing 'builtin'");
722 try pt.ensureNavValUpToDate(builtin_nav);727 try pt.ensureNavValUpToDate(builtin_nav);
...@@ -857,8 +862,10 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -857,8 +862,10 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
857/// to `transitive_failed_analysis` if necessary.862/// to `transitive_failed_analysis` if necessary.
858fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {863fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {
859 const zcu = pt.zcu;864 const zcu = pt.zcu;
860 const gpa = zcu.gpa;
861 const ip = &zcu.intern_pool;865 const ip = &zcu.intern_pool;
866 const comp = zcu.comp;
867 const gpa = comp.gpa;
868 const io = comp.io;
862869
863 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });870 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
864 const comptime_unit = ip.getComptimeUnit(cu_id);871 const comptime_unit = ip.getComptimeUnit(cu_id);
...@@ -909,7 +916,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu...@@ -909,7 +916,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
909 .r = .{ .simple = .comptime_keyword },916 .r = .{ .simple = .comptime_keyword },
910 } },917 } },
911 .src_base_inst = comptime_unit.zir_index,918 .src_base_inst = comptime_unit.zir_index,
912 .type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.comptime", .{919 .type_name_ctx = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.comptime", .{
913 Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),920 Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),
914 }, .no_embedded_nulls),921 }, .no_embedded_nulls),
915 };922 };
...@@ -1087,8 +1094,10 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu...@@ -1087,8 +1094,10 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
10871094
1088fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { val_changed: bool } {1095fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { val_changed: bool } {
1089 const zcu = pt.zcu;1096 const zcu = pt.zcu;
1090 const gpa = zcu.gpa;
1091 const ip = &zcu.intern_pool;1097 const ip = &zcu.intern_pool;
1098 const comp = zcu.comp;
1099 const gpa = comp.gpa;
1100 const io = comp.io;
10921101
1093 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });1102 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
1094 const old_nav = ip.getNav(nav_id);1103 const old_nav = ip.getNav(nav_id);
...@@ -1253,7 +1262,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1253,7 +1262,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1253 break :val .fromInterned(try pt.getExtern(.{1262 break :val .fromInterned(try pt.getExtern(.{
1254 .name = old_nav.name,1263 .name = old_nav.name,
1255 .ty = nav_ty.toIntern(),1264 .ty = nav_ty.toIntern(),
1256 .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls),1265 .lib_name = try ip.getOrPutStringOpt(gpa, io, pt.tid, lib_name, .no_embedded_nulls),
1257 .is_threadlocal = zir_decl.is_threadlocal,1266 .is_threadlocal = zir_decl.is_threadlocal,
1258 .linkage = .strong,1267 .linkage = .strong,
1259 .visibility = .default,1268 .visibility = .default,
...@@ -1310,7 +1319,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1310,7 +1319,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1310 }1319 }
1311 }1320 }
13121321
1313 ip.resolveNavValue(nav_id, .{1322 ip.resolveNavValue(io, nav_id, .{
1314 .val = nav_val.toIntern(),1323 .val = nav_val.toIntern(),
1315 .is_const = is_const,1324 .is_const = is_const,
1316 .alignment = modifiers.alignment,1325 .alignment = modifiers.alignment,
...@@ -1327,7 +1336,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1327,7 +1336,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1327 if (zir_decl.linkage == .@"export") {1336 if (zir_decl.linkage == .@"export") {
1328 const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) });1337 const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) });
1329 const name_slice = zir.nullTerminatedString(zir_decl.name);1338 const name_slice = zir.nullTerminatedString(zir_decl.name);
1330 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);1339 const name_ip = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls);
1331 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id);1340 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id);
1332 }1341 }
13331342
...@@ -1472,7 +1481,9 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc...@@ -1472,7 +1481,9 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
14721481
1473fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { type_changed: bool } {1482fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { type_changed: bool } {
1474 const zcu = pt.zcu;1483 const zcu = pt.zcu;
1475 const gpa = zcu.gpa;1484 const comp = zcu.comp;
1485 const gpa = comp.gpa;
1486 const io = comp.io;
1476 const ip = &zcu.intern_pool;1487 const ip = &zcu.intern_pool;
14771488
1478 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });1489 const anal_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });
...@@ -1579,7 +1590,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr...@@ -1579,7 +1590,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
15791590
1580 if (!changed) return .{ .type_changed = false };1591 if (!changed) return .{ .type_changed = false };
15811592
1582 ip.resolveNavType(nav_id, .{1593 ip.resolveNavType(io, nav_id, .{
1583 .type = resolved_ty.toIntern(),1594 .type = resolved_ty.toIntern(),
1584 .is_const = is_const,1595 .is_const = is_const,
1585 .alignment = modifiers.alignment,1596 .alignment = modifiers.alignment,
...@@ -1775,6 +1786,7 @@ fn createFileRootStruct(...@@ -1775,6 +1786,7 @@ fn createFileRootStruct(
1775) Allocator.Error!InternPool.Index {1786) Allocator.Error!InternPool.Index {
1776 const zcu = pt.zcu;1787 const zcu = pt.zcu;
1777 const gpa = zcu.gpa;1788 const gpa = zcu.gpa;
1789 const io = zcu.comp.io;
1778 const ip = &zcu.intern_pool;1790 const ip = &zcu.intern_pool;
1779 const file = zcu.fileByIndex(file_index);1791 const file = zcu.fileByIndex(file_index);
1780 const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended;1792 const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended;
...@@ -1797,11 +1809,11 @@ fn createFileRootStruct(...@@ -1797,11 +1809,11 @@ fn createFileRootStruct(
1797 const decls = file.zir.?.bodySlice(extra_index, decls_len);1809 const decls = file.zir.?.bodySlice(extra_index, decls_len);
1798 extra_index += decls_len;1810 extra_index += decls_len;
17991811
1800 const tracked_inst = try ip.trackZir(gpa, pt.tid, .{1812 const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{
1801 .file = file_index,1813 .file = file_index,
1802 .inst = .main_struct_inst,1814 .inst = .main_struct_inst,
1803 });1815 });
1804 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{1816 const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{
1805 .layout = .auto,1817 .layout = .auto,
1806 .fields_len = fields_len,1818 .fields_len = fields_len,
1807 .known_non_opv = small.known_non_opv,1819 .known_non_opv = small.known_non_opv,
...@@ -1916,7 +1928,9 @@ pub fn discoverImport(...@@ -1916,7 +1928,9 @@ pub fn discoverImport(
1916 },1928 },
1917} {1929} {
1918 const zcu = pt.zcu;1930 const zcu = pt.zcu;
1919 const gpa = zcu.gpa;1931 const comp = zcu.comp;
1932 const io = comp.io;
1933 const gpa = comp.gpa;
19201934
1921 if (!mem.endsWith(u8, import_string, ".zig") and !mem.endsWith(u8, import_string, ".zon")) {1935 if (!mem.endsWith(u8, import_string, ".zig") and !mem.endsWith(u8, import_string, ".zon")) {
1922 return .module;1936 return .module;
...@@ -1926,8 +1940,8 @@ pub fn discoverImport(...@@ -1926,8 +1940,8 @@ pub fn discoverImport(
1926 errdefer new_path.deinit(gpa);1940 errdefer new_path.deinit(gpa);
19271941
1928 // We're about to do a GOP on `import_table`, so we need the mutex.1942 // We're about to do a GOP on `import_table`, so we need the mutex.
1929 zcu.comp.mutex.lock();1943 comp.mutex.lockUncancelable(io);
1930 defer zcu.comp.mutex.unlock();1944 defer comp.mutex.unlock(io);
19311945
1932 const gop = try zcu.import_table.getOrPutAdapted(gpa, new_path, Zcu.ImportTableAdapter{ .zcu = zcu });1946 const gop = try zcu.import_table.getOrPutAdapted(gpa, new_path, Zcu.ImportTableAdapter{ .zcu = zcu });
1933 errdefer _ = zcu.import_table.pop();1947 errdefer _ = zcu.import_table.pop();
...@@ -1942,7 +1956,7 @@ pub fn discoverImport(...@@ -1942,7 +1956,7 @@ pub fn discoverImport(
1942 const new_file = try gpa.create(Zcu.File);1956 const new_file = try gpa.create(Zcu.File);
1943 errdefer gpa.destroy(new_file);1957 errdefer gpa.destroy(new_file);
19441958
1945 const new_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{1959 const new_file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{
1946 .bin_digest = new_path.digest(),1960 .bin_digest = new_path.digest(),
1947 .file = new_file,1961 .file = new_file,
1948 .root_type = .none,1962 .root_type = .none,
...@@ -2027,7 +2041,9 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{...@@ -2027,7 +2041,9 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{
2027 IllegalZigImport,2041 IllegalZigImport,
2028}!void {2042}!void {
2029 const zcu = pt.zcu;2043 const zcu = pt.zcu;
2030 const gpa = zcu.gpa;2044 const comp = zcu.comp;
2045 const gpa = comp.gpa;
2046 const io = comp.io;
20312047
2032 // We'll initially add [mod, undefined] pairs, and when we reach the pair while2048 // We'll initially add [mod, undefined] pairs, and when we reach the pair while
2033 // iterating, rewrite the undefined value.2049 // iterating, rewrite the undefined value.
...@@ -2085,7 +2101,7 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{...@@ -2085,7 +2101,7 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{
2085 const new_file = try gpa.create(Zcu.File);2101 const new_file = try gpa.create(Zcu.File);
2086 errdefer gpa.destroy(new_file);2102 errdefer gpa.destroy(new_file);
20872103
2088 const new_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{2104 const new_file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{
2089 .bin_digest = path.digest(),2105 .bin_digest = path.digest(),
2090 .file = new_file,2106 .file = new_file,
2091 .root_type = .none,2107 .root_type = .none,
...@@ -2291,7 +2307,8 @@ pub fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool {...@@ -2291,7 +2307,8 @@ pub fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool {
2291pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!void {2307pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!void {
2292 const zcu = pt.zcu;2308 const zcu = pt.zcu;
2293 const comp = zcu.comp;2309 const comp = zcu.comp;
2294 const gpa = zcu.gpa;2310 const gpa = comp.gpa;
2311 const io = comp.io;
22952312
2296 const gop = try zcu.builtin_modules.getOrPut(gpa, opts.hash());2313 const gop = try zcu.builtin_modules.getOrPut(gpa, opts.hash());
2297 if (gop.found_existing) return; // the `File` is up-to-date2314 if (gop.found_existing) return; // the `File` is up-to-date
...@@ -2330,7 +2347,7 @@ pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!voi...@@ -2330,7 +2347,7 @@ pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!voi
2330 .zoir_invalidated = false,2347 .zoir_invalidated = false,
2331 };2348 };
23322349
2333 const file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{2350 const file_index = try zcu.intern_pool.createFile(gpa, io, pt.tid, .{
2334 .bin_digest = path.digest(),2351 .bin_digest = path.digest(),
2335 .file = file,2352 .file = file,
2336 .root_type = .none,2353 .root_type = .none,
...@@ -2469,7 +2486,7 @@ fn updateEmbedFileInner(...@@ -2469,7 +2486,7 @@ fn updateEmbedFileInner(
24692486
2470 // The loaded bytes of the file, including a sentinel 0 byte.2487 // The loaded bytes of the file, including a sentinel 0 byte.
2471 const ip_str: InternPool.String = str: {2488 const ip_str: InternPool.String = str: {
2472 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa);2489 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io);
2473 const old_len = string_bytes.mutate.len;2490 const old_len = string_bytes.mutate.len;
2474 errdefer string_bytes.shrinkRetainingCapacity(old_len);2491 errdefer string_bytes.shrinkRetainingCapacity(old_len);
2475 const bytes = (try string_bytes.addManyAsSlice(size_plus_one))[0];2492 const bytes = (try string_bytes.addManyAsSlice(size_plus_one))[0];
...@@ -2480,7 +2497,7 @@ fn updateEmbedFileInner(...@@ -2480,7 +2497,7 @@ fn updateEmbedFileInner(
2480 error.EndOfStream => return error.UnexpectedEof,2497 error.EndOfStream => return error.UnexpectedEof,
2481 };2498 };
2482 bytes[size] = 0;2499 bytes[size] = 0;
2483 break :str try ip.getOrPutTrailingString(gpa, tid, @intCast(bytes.len), .maybe_embedded_nulls);2500 break :str try ip.getOrPutTrailingString(gpa, io, tid, @intCast(bytes.len), .maybe_embedded_nulls);
2484 };2501 };
2485 if (ip_str_out) |p| p.* = ip_str;2502 if (ip_str_out) |p| p.* = ip_str;
24862503
...@@ -2516,7 +2533,8 @@ fn newEmbedFile(...@@ -2516,7 +2533,8 @@ fn newEmbedFile(
2516) !*Zcu.EmbedFile {2533) !*Zcu.EmbedFile {
2517 const zcu = pt.zcu;2534 const zcu = pt.zcu;
2518 const comp = zcu.comp;2535 const comp = zcu.comp;
2519 const gpa = zcu.gpa;2536 const io = comp.io;
2537 const gpa = comp.gpa;
2520 const ip = &zcu.intern_pool;2538 const ip = &zcu.intern_pool;
25212539
2522 const new_file = try gpa.create(Zcu.EmbedFile);2540 const new_file = try gpa.create(Zcu.EmbedFile);
...@@ -2549,8 +2567,8 @@ fn newEmbedFile(...@@ -2549,8 +2567,8 @@ fn newEmbedFile(
2549 const path_str = try path.toAbsolute(comp.dirs, gpa);2567 const path_str = try path.toAbsolute(comp.dirs, gpa);
2550 defer gpa.free(path_str);2568 defer gpa.free(path_str);
25512569
2552 whole.cache_manifest_mutex.lock();2570 try whole.cache_manifest_mutex.lock(io);
2553 defer whole.cache_manifest_mutex.unlock();2571 defer whole.cache_manifest_mutex.unlock(io);
25542572
2555 man.addFilePostContents(path_str, contents, new_file.stat) catch |err| switch (err) {2573 man.addFilePostContents(path_str, contents, new_file.stat) catch |err| switch (err) {
2556 error.Unexpected => unreachable,2574 error.Unexpected => unreachable,
...@@ -2647,13 +2665,15 @@ const ScanDeclIter = struct {...@@ -2647,13 +2665,15 @@ const ScanDeclIter = struct {
26472665
2648 fn avoidNameConflict(iter: *ScanDeclIter, comptime fmt: []const u8, args: anytype) !InternPool.NullTerminatedString {2666 fn avoidNameConflict(iter: *ScanDeclIter, comptime fmt: []const u8, args: anytype) !InternPool.NullTerminatedString {
2649 const pt = iter.pt;2667 const pt = iter.pt;
2650 const gpa = pt.zcu.gpa;
2651 const ip = &pt.zcu.intern_pool;2668 const ip = &pt.zcu.intern_pool;
2652 var name = try ip.getOrPutStringFmt(gpa, pt.tid, fmt, args, .no_embedded_nulls);2669 const comp = pt.zcu.comp;
2670 const gpa = comp.gpa;
2671 const io = comp.io;
2672 var name = try ip.getOrPutStringFmt(gpa, io, pt.tid, fmt, args, .no_embedded_nulls);
2653 var gop = try iter.seen_decls.getOrPut(gpa, name);2673 var gop = try iter.seen_decls.getOrPut(gpa, name);
2654 var next_suffix: u32 = 0;2674 var next_suffix: u32 = 0;
2655 while (gop.found_existing) {2675 while (gop.found_existing) {
2656 name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls);2676 name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls);
2657 gop = try iter.seen_decls.getOrPut(gpa, name);2677 gop = try iter.seen_decls.getOrPut(gpa, name);
2658 next_suffix += 1;2678 next_suffix += 1;
2659 }2679 }
...@@ -2669,7 +2689,8 @@ const ScanDeclIter = struct {...@@ -2669,7 +2689,8 @@ const ScanDeclIter = struct {
2669 const comp = zcu.comp;2689 const comp = zcu.comp;
2670 const namespace_index = iter.namespace_index;2690 const namespace_index = iter.namespace_index;
2671 const namespace = zcu.namespacePtr(namespace_index);2691 const namespace = zcu.namespacePtr(namespace_index);
2672 const gpa = zcu.gpa;2692 const gpa = comp.gpa;
2693 const io = comp.io;
2673 const file = namespace.fileScope(zcu);2694 const file = namespace.fileScope(zcu);
2674 const zir = file.zir.?;2695 const zir = file.zir.?;
2675 const ip = &zcu.intern_pool;2696 const ip = &zcu.intern_pool;
...@@ -2697,6 +2718,7 @@ const ScanDeclIter = struct {...@@ -2697,6 +2718,7 @@ const ScanDeclIter = struct {
2697 if (iter.pass != .named) return;2718 if (iter.pass != .named) return;
2698 const name = try ip.getOrPutString(2719 const name = try ip.getOrPutString(
2699 gpa,2720 gpa,
2721 io,
2700 pt.tid,2722 pt.tid,
2701 zir.nullTerminatedString(decl.name),2723 zir.nullTerminatedString(decl.name),
2702 .no_embedded_nulls,2724 .no_embedded_nulls,
...@@ -2706,7 +2728,7 @@ const ScanDeclIter = struct {...@@ -2706,7 +2728,7 @@ const ScanDeclIter = struct {
2706 },2728 },
2707 };2729 };
27082730
2709 const tracked_inst = try ip.trackZir(gpa, pt.tid, .{2731 const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{
2710 .file = namespace.file_scope,2732 .file = namespace.file_scope,
2711 .inst = decl_inst,2733 .inst = decl_inst,
2712 });2734 });
...@@ -2718,7 +2740,7 @@ const ScanDeclIter = struct {...@@ -2718,7 +2740,7 @@ const ScanDeclIter = struct {
2718 const cu = if (existing_unit) |eu|2740 const cu = if (existing_unit) |eu|
2719 eu.unwrap().@"comptime"2741 eu.unwrap().@"comptime"
2720 else2742 else
2721 try ip.createComptimeUnit(gpa, pt.tid, tracked_inst, namespace_index);2743 try ip.createComptimeUnit(gpa, io, pt.tid, tracked_inst, namespace_index);
27222744
2723 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });2745 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
27242746
...@@ -2737,9 +2759,9 @@ const ScanDeclIter = struct {...@@ -2737,9 +2759,9 @@ const ScanDeclIter = struct {
2737 },2759 },
2738 else => unit: {2760 else => unit: {
2739 const name = maybe_name.unwrap().?;2761 const name = maybe_name.unwrap().?;
2740 const fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, name);2762 const fqn = try namespace.internFullyQualifiedName(ip, gpa, io, pt.tid, name);
2741 const nav = if (existing_unit) |eu| eu.unwrap().nav_val else nav: {2763 const nav = if (existing_unit) |eu| eu.unwrap().nav_val else nav: {
2742 const nav = try ip.createDeclNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index);2764 const nav = try ip.createDeclNav(gpa, io, pt.tid, name, fqn, tracked_inst, namespace_index);
2743 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav);2765 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav);
2744 break :nav nav;2766 break :nav nav;
2745 };2767 };
...@@ -2798,7 +2820,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2798,7 +2820,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2798 defer tracy.end();2820 defer tracy.end();
27992821
2800 const zcu = pt.zcu;2822 const zcu = pt.zcu;
2801 const gpa = zcu.gpa;2823 const comp = zcu.comp;
2824 const gpa = comp.gpa;
2825 const io = comp.io;
2802 const ip = &zcu.intern_pool;2826 const ip = &zcu.intern_pool;
28032827
2804 const anal_unit = AnalUnit.wrap(.{ .func = func_index });2828 const anal_unit = AnalUnit.wrap(.{ .func = func_index });
...@@ -2810,9 +2834,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2810,9 +2834,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2810 try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {});2834 try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {});
2811 errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);2835 errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
28122836
2813 func.setAnalyzed(ip);2837 func.setAnalyzed(ip, io);
2814 if (func.analysisUnordered(ip).inferred_error_set) {2838 if (func.analysisUnordered(ip).inferred_error_set) {
2815 func.setResolvedErrorSet(ip, .none);2839 func.setResolvedErrorSet(ip, io, .none);
2816 }2840 }
28172841
2818 if (zcu.comp.time_report) |*tr| {2842 if (zcu.comp.time_report) |*tr| {
...@@ -2872,7 +2896,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2872,7 +2896,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2872 }2896 }
28732897
2874 // reset in case calls to errorable functions are removed.2898 // reset in case calls to errorable functions are removed.
2875 ip.funcSetHasErrorTrace(func_index, fn_ty_info.cc == .auto);2899 ip.funcSetHasErrorTrace(io, func_index, fn_ty_info.cc == .auto);
28762900
2877 // First few indexes of extra are reserved and set at the end.2901 // First few indexes of extra are reserved and set at the end.
2878 const reserved_count = @typeInfo(Air.ExtraIndex).@"enum".fields.len;2902 const reserved_count = @typeInfo(Air.ExtraIndex).@"enum".fields.len;
...@@ -2971,7 +2995,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2971,7 +2995,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2971 });2995 });
2972 }2996 }
29732997
2974 func.setBranchHint(ip, sema.branch_hint orelse .none);2998 func.setBranchHint(ip, io, sema.branch_hint orelse .none);
29752999
2976 if (zcu.comp.config.any_error_tracing and func.analysisUnordered(ip).has_error_trace and fn_ty_info.cc != .auto) {3000 if (zcu.comp.config.any_error_tracing and func.analysisUnordered(ip).has_error_trace and fn_ty_info.cc != .auto) {
2977 // We're using an error trace, but didn't start out with one from the caller.3001 // We're using an error trace, but didn't start out with one from the caller.
...@@ -3005,7 +3029,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -3005,7 +3029,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
3005 else => |e| return e,3029 else => |e| return e,
3006 };3030 };
3007 assert(ies.resolved != .none);3031 assert(ies.resolved != .none);
3008 func.setResolvedErrorSet(ip, ies.resolved);3032 func.setResolvedErrorSet(ip, io, ies.resolved);
3009 }3033 }
30103034
3011 assert(zcu.analysis_in_progress.swapRemove(anal_unit));3035 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
...@@ -3036,7 +3060,8 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -3036,7 +3060,8 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
3036}3060}
30373061
3038pub fn createNamespace(pt: Zcu.PerThread, initialization: Zcu.Namespace) !Zcu.Namespace.Index {3062pub fn createNamespace(pt: Zcu.PerThread, initialization: Zcu.Namespace) !Zcu.Namespace.Index {
3039 return pt.zcu.intern_pool.createNamespace(pt.zcu.gpa, pt.tid, initialization);3063 const comp = pt.zcu.comp;
3064 return pt.zcu.intern_pool.createNamespace(comp.gpa, comp.io, pt.tid, initialization);
3040}3065}
30413066
3042pub fn destroyNamespace(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) void {3067pub fn destroyNamespace(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) void {
...@@ -3047,11 +3072,15 @@ pub fn getErrorValue(...@@ -3047,11 +3072,15 @@ pub fn getErrorValue(
3047 pt: Zcu.PerThread,3072 pt: Zcu.PerThread,
3048 name: InternPool.NullTerminatedString,3073 name: InternPool.NullTerminatedString,
3049) Allocator.Error!Zcu.ErrorInt {3074) Allocator.Error!Zcu.ErrorInt {
3050 return pt.zcu.intern_pool.getErrorValue(pt.zcu.gpa, pt.tid, name);3075 const comp = pt.zcu.comp;
3076 return pt.zcu.intern_pool.getErrorValue(comp.gpa, comp.io, pt.tid, name);
3051}3077}
30523078
3053pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Zcu.ErrorInt {3079pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Zcu.ErrorInt {
3054 return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, name));3080 const comp = pt.zcu.comp;
3081 const gpa = comp.gpa;
3082 const io = comp.io;
3083 return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(gpa, io, name));
3055}3084}
30563085
3057/// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed.3086/// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed.
...@@ -3078,8 +3107,10 @@ fn lockAndClearFileCompileError(pt: Zcu.PerThread, file_index: Zcu.File.Index, f...@@ -3078,8 +3107,10 @@ fn lockAndClearFileCompileError(pt: Zcu.PerThread, file_index: Zcu.File.Index, f
3078 return;3107 return;
3079 }3108 }
30803109
3081 pt.zcu.comp.mutex.lock();3110 const comp = pt.zcu.comp;
3082 defer pt.zcu.comp.mutex.unlock();3111 const io = comp.io;
3112 comp.mutex.lockUncancelable(io);
3113 defer comp.mutex.unlock(io);
3083 if (pt.zcu.failed_files.fetchSwapRemove(file_index)) |kv| {3114 if (pt.zcu.failed_files.fetchSwapRemove(file_index)) |kv| {
3084 assert(maybe_has_error); // the runtime safety case above3115 assert(maybe_has_error); // the runtime safety case above
3085 if (kv.value) |msg| pt.zcu.gpa.free(msg); // delete previous error message3116 if (kv.value) |msg| pt.zcu.gpa.free(msg); // delete previous error message
...@@ -3266,7 +3297,9 @@ fn processExportsInner(...@@ -3266,7 +3297,9 @@ fn processExportsInner(
32663297
3267pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {3298pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
3268 const zcu = pt.zcu;3299 const zcu = pt.zcu;
3269 const gpa = zcu.gpa;3300 const comp = zcu.comp;
3301 const gpa = comp.gpa;
3302 const io = comp.io;
3270 const ip = &zcu.intern_pool;3303 const ip = &zcu.intern_pool;
32713304
3272 // Our job is to correctly set the value of the `test_functions` declaration if it has been3305 // Our job is to correctly set the value of the `test_functions` declaration if it has been
...@@ -3284,7 +3317,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {...@@ -3284,7 +3317,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
3284 const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?;3317 const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?;
3285 // We know that the namespace has a `test_functions`...3318 // We know that the namespace has a `test_functions`...
3286 const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted(3319 const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted(
3287 try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls),3320 try ip.getOrPutString(gpa, io, pt.tid, "test_functions", .no_embedded_nulls),
3288 Zcu.Namespace.NameAdapter{ .zcu = zcu },3321 Zcu.Namespace.NameAdapter{ .zcu = zcu },
3289 ).?;3322 ).?;
3290 // ...but it might not be populated, so let's check that!3323 // ...but it might not be populated, so let's check that!
...@@ -3392,7 +3425,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {...@@ -3392,7 +3425,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
3392 } }),3425 } }),
3393 .len = (try pt.intValue(Type.usize, zcu.test_functions.count())).toIntern(),3426 .len = (try pt.intValue(Type.usize, zcu.test_functions.count())).toIntern(),
3394 } });3427 } });
3395 ip.mutateVarInit(test_fns_val.toIntern(), new_init);3428 ip.mutateVarInit(io, test_fns_val.toIntern(), new_init);
3396 }3429 }
3397 // The linker thread is not running, so we actually need to dispatch this task directly.3430 // The linker thread is not running, so we actually need to dispatch this task directly.
3398 @import("../link.zig").linkTestFunctionsNav(pt, nav_index);3431 @import("../link.zig").linkTestFunctionsNav(pt, nav_index);
...@@ -3407,7 +3440,9 @@ pub fn reportRetryableFileError(...@@ -3407,7 +3440,9 @@ pub fn reportRetryableFileError(
3407 args: anytype,3440 args: anytype,
3408) error{OutOfMemory}!void {3441) error{OutOfMemory}!void {
3409 const zcu = pt.zcu;3442 const zcu = pt.zcu;
3410 const gpa = zcu.gpa;3443 const comp = zcu.comp;
3444 const io = comp.io;
3445 const gpa = comp.gpa;
34113446
3412 const file = zcu.fileByIndex(file_index);3447 const file = zcu.fileByIndex(file_index);
34133448
...@@ -3417,8 +3452,8 @@ pub fn reportRetryableFileError(...@@ -3417,8 +3452,8 @@ pub fn reportRetryableFileError(
3417 errdefer gpa.free(msg);3452 errdefer gpa.free(msg);
34183453
3419 const old_msg: ?[]u8 = old_msg: {3454 const old_msg: ?[]u8 = old_msg: {
3420 zcu.comp.mutex.lock();3455 comp.mutex.lockUncancelable(io);
3421 defer zcu.comp.mutex.unlock();3456 defer comp.mutex.unlock(io);
34223457
3423 const gop = try zcu.failed_files.getOrPut(gpa, file_index);3458 const gop = try zcu.failed_files.getOrPut(gpa, file_index);
3424 const old: ?[]u8 = if (gop.found_existing) old: {3459 const old: ?[]u8 = if (gop.found_existing) old: {
...@@ -3433,12 +3468,8 @@ pub fn reportRetryableFileError(...@@ -3433,12 +3468,8 @@ pub fn reportRetryableFileError(
34333468
3434/// Shortcut for calling `intern_pool.get`.3469/// Shortcut for calling `intern_pool.get`.
3435pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool.Index {3470pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool.Index {
3436 return pt.zcu.intern_pool.get(pt.zcu.gpa, pt.tid, key);3471 const comp = pt.zcu.comp;
3437}3472 return pt.zcu.intern_pool.get(comp.gpa, comp.io, pt.tid, key);
3438
3439/// Shortcut for calling `intern_pool.getUnion`.
3440pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error!InternPool.Index {
3441 return pt.zcu.intern_pool.getUnion(pt.zcu.gpa, pt.tid, un);
3442}3473}
34433474
3444/// Essentially a shortcut for calling `intern_pool.getCoerced`.3475/// Essentially a shortcut for calling `intern_pool.getCoerced`.
...@@ -3446,6 +3477,9 @@ pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error!...@@ -3446,6 +3477,9 @@ pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error!
3446/// this because it requires potentially pushing to the job queue.3477/// this because it requires potentially pushing to the job queue.
3447pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!Value {3478pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!Value {
3448 const ip = &pt.zcu.intern_pool;3479 const ip = &pt.zcu.intern_pool;
3480 const comp = pt.zcu.comp;
3481 const gpa = comp.gpa;
3482 const io = comp.io;
3449 switch (ip.indexToKey(val.toIntern())) {3483 switch (ip.indexToKey(val.toIntern())) {
3450 .@"extern" => |e| {3484 .@"extern" => |e| {
3451 const coerced = try pt.getExtern(.{3485 const coerced = try pt.getExtern(.{
...@@ -3468,7 +3502,7 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V...@@ -3468,7 +3502,7 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V
3468 },3502 },
3469 else => {},3503 else => {},
3470 }3504 }
3471 return Value.fromInterned(try ip.getCoerced(pt.zcu.gpa, pt.tid, val.toIntern(), new_ty.toIntern()));3505 return Value.fromInterned(try ip.getCoerced(gpa, io, pt.tid, val.toIntern(), new_ty.toIntern()));
3472}3506}
34733507
3474pub fn intType(pt: Zcu.PerThread, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type {3508pub fn intType(pt: Zcu.PerThread, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type {
...@@ -3566,7 +3600,8 @@ pub fn adjustPtrTypeChild(pt: Zcu.PerThread, ptr_ty: Type, new_child: Type) Allo...@@ -3566,7 +3600,8 @@ pub fn adjustPtrTypeChild(pt: Zcu.PerThread, ptr_ty: Type, new_child: Type) Allo
3566}3600}
35673601
3568pub fn funcType(pt: Zcu.PerThread, key: InternPool.GetFuncTypeKey) Allocator.Error!Type {3602pub fn funcType(pt: Zcu.PerThread, key: InternPool.GetFuncTypeKey) Allocator.Error!Type {
3569 return Type.fromInterned(try pt.zcu.intern_pool.getFuncType(pt.zcu.gpa, pt.tid, key));3603 const comp = pt.zcu.comp;
3604 return .fromInterned(try pt.zcu.intern_pool.getFuncType(comp.gpa, comp.io, pt.tid, key));
3570}3605}
35713606
3572/// Use this for `anyframe->T` only.3607/// Use this for `anyframe->T` only.
...@@ -3584,7 +3619,8 @@ pub fn errorUnionType(pt: Zcu.PerThread, error_set_ty: Type, payload_ty: Type) A...@@ -3584,7 +3619,8 @@ pub fn errorUnionType(pt: Zcu.PerThread, error_set_ty: Type, payload_ty: Type) A
35843619
3585pub fn singleErrorSetType(pt: Zcu.PerThread, name: InternPool.NullTerminatedString) Allocator.Error!Type {3620pub fn singleErrorSetType(pt: Zcu.PerThread, name: InternPool.NullTerminatedString) Allocator.Error!Type {
3586 const names: *const [1]InternPool.NullTerminatedString = &name;3621 const names: *const [1]InternPool.NullTerminatedString = &name;
3587 return Type.fromInterned(try pt.zcu.intern_pool.getErrorSetType(pt.zcu.gpa, pt.tid, names));3622 const comp = pt.zcu.comp;
3623 return Type.fromInterned(try pt.zcu.intern_pool.getErrorSetType(comp.gpa, comp.io, pt.tid, names));
3588}3624}
35893625
3590/// Sorts `names` in place.3626/// Sorts `names` in place.
...@@ -3598,7 +3634,8 @@ pub fn errorSetFromUnsortedNames(...@@ -3598,7 +3634,8 @@ pub fn errorSetFromUnsortedNames(
3598 {},3634 {},
3599 InternPool.NullTerminatedString.indexLessThan,3635 InternPool.NullTerminatedString.indexLessThan,
3600 );3636 );
3601 const new_ty = try pt.zcu.intern_pool.getErrorSetType(pt.zcu.gpa, pt.tid, names);3637 const comp = pt.zcu.comp;
3638 const new_ty = try pt.zcu.intern_pool.getErrorSetType(comp.gpa, comp.io, pt.tid, names);
3602 return Type.fromInterned(new_ty);3639 return Type.fromInterned(new_ty);
3603}3640}
36043641
...@@ -3709,9 +3746,17 @@ pub fn intValue_i64(pt: Zcu.PerThread, ty: Type, x: i64) Allocator.Error!Value {...@@ -3709,9 +3746,17 @@ pub fn intValue_i64(pt: Zcu.PerThread, ty: Type, x: i64) Allocator.Error!Value {
3709 } }));3746 } }));
3710}3747}
37113748
3749/// Shortcut for calling `intern_pool.getUnion`.
3750/// TODO: remove either this or `unionValue`.
3751pub fn internUnion(pt: Zcu.PerThread, un: InternPool.Key.Union) Allocator.Error!InternPool.Index {
3752 const comp = pt.zcu.comp;
3753 return pt.zcu.intern_pool.getUnion(comp.gpa, comp.io, pt.tid, un);
3754}
3755
3756/// TODO: remove either this or `internUnion`.
3712pub fn unionValue(pt: Zcu.PerThread, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value {3757pub fn unionValue(pt: Zcu.PerThread, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value {
3713 const zcu = pt.zcu;3758 const comp = pt.zcu.comp;
3714 return Value.fromInterned(try zcu.intern_pool.getUnion(zcu.gpa, pt.tid, .{3759 return Value.fromInterned(try pt.zcu.intern_pool.getUnion(comp.gpa, comp.io, pt.tid, .{
3715 .ty = union_ty.toIntern(),3760 .ty = union_ty.toIntern(),
3716 .tag = tag.toIntern(),3761 .tag = tag.toIntern(),
3717 .val = val.toIntern(),3762 .val = val.toIntern(),
...@@ -3771,12 +3816,12 @@ pub fn nullValue(pt: Zcu.PerThread, opt_ty: Type) Allocator.Error!Value {...@@ -3771,12 +3816,12 @@ pub fn nullValue(pt: Zcu.PerThread, opt_ty: Type) Allocator.Error!Value {
3771/// `ty` is an integer or a vector of integers.3816/// `ty` is an integer or a vector of integers.
3772pub fn overflowArithmeticTupleType(pt: Zcu.PerThread, ty: Type) !Type {3817pub fn overflowArithmeticTupleType(pt: Zcu.PerThread, ty: Type) !Type {
3773 const zcu = pt.zcu;3818 const zcu = pt.zcu;
3774 const ip = &zcu.intern_pool;3819 const comp = zcu.comp;
3775 const ov_ty: Type = if (ty.zigTypeTag(zcu) == .vector) try pt.vectorType(.{3820 const ov_ty: Type = if (ty.zigTypeTag(zcu) == .vector) try pt.vectorType(.{
3776 .len = ty.vectorLen(zcu),3821 .len = ty.vectorLen(zcu),
3777 .child = .u1_type,3822 .child = .u1_type,
3778 }) else .u1;3823 }) else .u1;
3779 const tuple_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{3824 const tuple_ty = try zcu.intern_pool.getTupleType(comp.gpa, comp.io, pt.tid, .{
3780 .types = &.{ ty.toIntern(), ov_ty.toIntern() },3825 .types = &.{ ty.toIntern(), ov_ty.toIntern() },
3781 .values = &.{ .none, .none },3826 .values = &.{ .none, .none },
3782 });3827 });
...@@ -3872,12 +3917,14 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err...@@ -3872,12 +3917,14 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err
3872/// If necessary, the new `Nav` is queued for codegen.3917/// If necessary, the new `Nav` is queued for codegen.
3873/// `key.owner_nav` is ignored and may be `undefined`.3918/// `key.owner_nav` is ignored and may be `undefined`.
3874pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!InternPool.Index {3919pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!InternPool.Index {
3875 const result = try pt.zcu.intern_pool.getExtern(pt.zcu.gpa, pt.tid, key);3920 const zcu = pt.zcu;
3921 const comp = zcu.comp;
3922 const result = try zcu.intern_pool.getExtern(comp.gpa, comp.io, pt.tid, key);
3876 if (result.new_nav.unwrap()) |nav| {3923 if (result.new_nav.unwrap()) |nav| {
3877 // This job depends on any resolve_type_fully jobs queued up before it.3924 // This job depends on any resolve_type_fully jobs queued up before it.
3878 pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);3925 comp.link_prog_node.increaseEstimatedTotalItems(1);
3879 try pt.zcu.comp.queueJob(.{ .link_nav = nav });3926 try comp.queueJob(.{ .link_nav = nav });
3880 if (pt.zcu.comp.debugIncremental()) try pt.zcu.incremental_debug_state.newNav(pt.zcu, nav);3927 if (comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav);
3881 }3928 }
3882 return result.index;3929 return result.index;
3883}3930}
...@@ -3966,7 +4013,9 @@ fn recreateStructType(...@@ -3966,7 +4013,9 @@ fn recreateStructType(
3966 key: InternPool.Key.NamespaceType.Declared,4013 key: InternPool.Key.NamespaceType.Declared,
3967) Allocator.Error!InternPool.Index {4014) Allocator.Error!InternPool.Index {
3968 const zcu = pt.zcu;4015 const zcu = pt.zcu;
3969 const gpa = zcu.gpa;4016 const comp = zcu.comp;
4017 const gpa = comp.gpa;
4018 const io = comp.io;
3970 const ip = &zcu.intern_pool;4019 const ip = &zcu.intern_pool;
39714020
3972 const inst_info = key.zir_index.resolveFull(ip).?;4021 const inst_info = key.zir_index.resolveFull(ip).?;
...@@ -3995,7 +4044,7 @@ fn recreateStructType(...@@ -3995,7 +4044,7 @@ fn recreateStructType(
39954044
3996 const struct_obj = ip.loadStructType(old_ty);4045 const struct_obj = ip.loadStructType(old_ty);
39974046
3998 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{4047 const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{
3999 .layout = small.layout,4048 .layout = small.layout,
4000 .fields_len = fields_len,4049 .fields_len = fields_len,
4001 .known_non_opv = small.known_non_opv,4050 .known_non_opv = small.known_non_opv,
...@@ -4042,7 +4091,9 @@ fn recreateUnionType(...@@ -4042,7 +4091,9 @@ fn recreateUnionType(
4042 key: InternPool.Key.NamespaceType.Declared,4091 key: InternPool.Key.NamespaceType.Declared,
4043) Allocator.Error!InternPool.Index {4092) Allocator.Error!InternPool.Index {
4044 const zcu = pt.zcu;4093 const zcu = pt.zcu;
4045 const gpa = zcu.gpa;4094 const comp = zcu.comp;
4095 const gpa = comp.gpa;
4096 const io = comp.io;
4046 const ip = &zcu.intern_pool;4097 const ip = &zcu.intern_pool;
40474098
4048 const inst_info = key.zir_index.resolveFull(ip).?;4099 const inst_info = key.zir_index.resolveFull(ip).?;
...@@ -4075,7 +4126,7 @@ fn recreateUnionType(...@@ -4075,7 +4126,7 @@ fn recreateUnionType(
40754126
4076 const namespace_index = union_obj.namespace;4127 const namespace_index = union_obj.namespace;
40774128
4078 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{4129 const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{
4079 .flags = .{4130 .flags = .{
4080 .layout = small.layout,4131 .layout = small.layout,
4081 .status = .none,4132 .status = .none,
...@@ -4133,7 +4184,9 @@ fn recreateEnumType(...@@ -4133,7 +4184,9 @@ fn recreateEnumType(
4133 key: InternPool.Key.NamespaceType.Declared,4184 key: InternPool.Key.NamespaceType.Declared,
4134) (Allocator.Error || Io.Cancelable)!InternPool.Index {4185) (Allocator.Error || Io.Cancelable)!InternPool.Index {
4135 const zcu = pt.zcu;4186 const zcu = pt.zcu;
4136 const gpa = zcu.gpa;4187 const comp = zcu.comp;
4188 const gpa = comp.gpa;
4189 const io = comp.io;
4137 const ip = &zcu.intern_pool;4190 const ip = &zcu.intern_pool;
41384191
4139 const inst_info = key.zir_index.resolveFull(ip).?;4192 const inst_info = key.zir_index.resolveFull(ip).?;
...@@ -4197,7 +4250,7 @@ fn recreateEnumType(...@@ -4197,7 +4250,7 @@ fn recreateEnumType(
41974250
4198 const namespace_index = enum_obj.namespace;4251 const namespace_index = enum_obj.namespace;
41994252
4200 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{4253 const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{
4201 .has_values = any_values,4254 .has_values = any_values,
4202 .tag_mode = if (small.nonexhaustive)4255 .tag_mode = if (small.nonexhaustive)
4203 .nonexhaustive4256 .nonexhaustive
...@@ -4404,7 +4457,7 @@ pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPo...@@ -4404,7 +4457,7 @@ pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPo
44044457
4405pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dependee) Allocator.Error!void {4458pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dependee) Allocator.Error!void {
4406 const zcu = pt.zcu;4459 const zcu = pt.zcu;
4407 const gpa = zcu.gpa;4460 const gpa = zcu.comp.gpa;
4408 try zcu.intern_pool.addDependency(gpa, unit, dependee);4461 try zcu.intern_pool.addDependency(gpa, unit, dependee);
4409 if (zcu.comp.debugIncremental()) {4462 if (zcu.comp.debugIncremental()) {
4410 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, unit);4463 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, unit);
...@@ -4412,50 +4465,38 @@ pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dep...@@ -4412,50 +4465,38 @@ pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dep
4412 }4465 }
4413}4466}
44144467
4415/// Performs code generation, which comes after `Sema` but before `link` in the pipeline.4468pub const RunCodegenError = Io.Cancelable || error{AlreadyReported};
4416/// This part of the pipeline is self-contained/"pure", so can be run in parallel with most4469
4417/// other code. This function is currently run either on the main thread, or on a separate4470/// Performs code generation, which comes after `Sema` but before `link` in the pipeline. This part
4418/// codegen thread, depending on whether the backend supports `Zcu.Feature.separate_thread`.4471/// of the pipeline is self-contained and can usually be run concurrently with other components.
4419pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, out: *@import("../link.zig").ZcuTask.LinkFunc.SharedMir) void {4472///
4473/// This function is called asynchronously by `Zcu.CodegenTaskPool.start` and awaited by the linker.
4474/// However, if the codegen backend does not support `Zcu.Feature.separate_thread`, then
4475/// `Compilation.processOneJob` will immediately await the result of the linker task, meaning the
4476/// pipeline becomes effectively single-threaded.
4477pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) RunCodegenError!codegen.AnyMir {
4420 const zcu = pt.zcu;4478 const zcu = pt.zcu;
4479 const comp = zcu.comp;
4480 const io = comp.io;
44214481
4422 crash_report.CodegenFunc.start(zcu, func_index);4482 crash_report.CodegenFunc.start(zcu, func_index);
4423 defer crash_report.CodegenFunc.stop(func_index);4483 defer crash_report.CodegenFunc.stop(func_index);
44244484
4425 var timer = zcu.comp.startTimer();4485 var timer = comp.startTimer();
44264486
4427 const success: bool = if (runCodegenInner(pt, func_index, air)) |mir| success: {4487 const codegen_result = runCodegenInner(pt, func_index, air);
4428 out.value = mir;
4429 break :success true;
4430 } else |err| success: {
4431 switch (err) {
4432 error.OutOfMemory => zcu.comp.setAllocFailure(),
4433 error.CodegenFail => zcu.assertCodegenFailed(zcu.funcInfo(func_index).owner_nav),
4434 error.NoLinkFile => assert(zcu.comp.bin_file == null),
4435 error.BackendDoesNotProduceMir => switch (target_util.zigBackend(
4436 &zcu.root_mod.resolved_target.result,
4437 zcu.comp.config.use_llvm,
4438 )) {
4439 else => unreachable, // assertion failure
4440 .stage2_spirv,
4441 .stage2_llvm,
4442 => {},
4443 },
4444 }
4445 break :success false;
4446 };
44474488
4448 if (timer.finish()) |ns_codegen| report_time: {4489 if (timer.finish()) |ns_codegen| report_time: {
4449 const ip = &zcu.intern_pool;4490 const ip = &zcu.intern_pool;
4450 const nav = ip.indexToKey(func_index).func.owner_nav;4491 const nav = ip.indexToKey(func_index).func.owner_nav;
4451 const zir_decl = ip.getNav(nav).srcInst(ip);4492 const zir_decl = ip.getNav(nav).srcInst(ip);
4452 zcu.comp.mutex.lock();4493 comp.mutex.lockUncancelable(io);
4453 defer zcu.comp.mutex.unlock();4494 defer comp.mutex.unlock(io);
4454 const tr = &zcu.comp.time_report.?;4495 const tr = &zcu.comp.time_report.?;
4455 tr.stats.cpu_ns_codegen += ns_codegen;4496 tr.stats.cpu_ns_codegen += ns_codegen;
4456 const gop = tr.decl_codegen_ns.getOrPut(zcu.gpa, zir_decl) catch |err| switch (err) {4497 const gop = tr.decl_codegen_ns.getOrPut(comp.gpa, zir_decl) catch |err| switch (err) {
4457 error.OutOfMemory => {4498 error.OutOfMemory => {
4458 zcu.comp.setAllocFailure();4499 comp.setAllocFailure();
4459 break :report_time;4500 break :report_time;
4460 },4501 },
4461 };4502 };
...@@ -4463,14 +4504,29 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, ou...@@ -4463,14 +4504,29 @@ pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, ou
4463 gop.value_ptr.* += ns_codegen;4504 gop.value_ptr.* += ns_codegen;
4464 }4505 }
44654506
4466 // release `out.value` with this store; synchronizes with acquire loads in `link`
4467 out.status.store(if (success) .ready else .failed, .release);
4468 zcu.comp.link_task_queue.mirReady(zcu.comp, func_index, out);
4469 if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) {4507 if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) {
4470 // Decremented to 0, so all done.4508 // Decremented to 0, so all done.
4471 zcu.codegen_prog_node.end();4509 zcu.codegen_prog_node.end();
4472 zcu.codegen_prog_node = .none;4510 zcu.codegen_prog_node = .none;
4473 }4511 }
4512
4513 return codegen_result catch |err| {
4514 switch (err) {
4515 error.OutOfMemory => comp.setAllocFailure(),
4516 error.CodegenFail => zcu.assertCodegenFailed(zcu.funcInfo(func_index).owner_nav),
4517 error.NoLinkFile => assert(comp.bin_file == null),
4518 error.BackendDoesNotProduceMir => switch (target_util.zigBackend(
4519 &zcu.root_mod.resolved_target.result,
4520 comp.config.use_llvm,
4521 )) {
4522 else => unreachable, // assertion failure
4523 .stage2_spirv,
4524 .stage2_llvm,
4525 => {},
4526 },
4527 }
4528 return error.AlreadyReported;
4529 };
4474}4530}
4475fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{4531fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{
4476 OutOfMemory,4532 OutOfMemory,
...@@ -4527,7 +4583,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4527,7 +4583,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
4527 // "emit" step because LLVM does not support incremental linking. Our linker (LLD or self-hosted)4583 // "emit" step because LLVM does not support incremental linking. Our linker (LLD or self-hosted)
4528 // will just see the ZCU object file which LLVM ultimately emits.4584 // will just see the ZCU object file which LLVM ultimately emits.
4529 if (zcu.llvm_object) |llvm_object| {4585 if (zcu.llvm_object) |llvm_object| {
4530 assert(pt.tid == .main); // LLVM has a lot of shared state4586 assert(zcu.pending_codegen_jobs.load(.monotonic) == 2); // only one codegen at a time (but the value is 2 because 1 is the base)
4531 try llvm_object.updateFunc(pt, func_index, air, &liveness);4587 try llvm_object.updateFunc(pt, func_index, air, &liveness);
4532 return error.BackendDoesNotProduceMir;4588 return error.BackendDoesNotProduceMir;
4533 }4589 }
...@@ -4536,7 +4592,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4536,7 +4592,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
45364592
4537 // Just like LLVM, the SPIR-V backend can't multi-threaded due to SPIR-V design limitations.4593 // Just like LLVM, the SPIR-V backend can't multi-threaded due to SPIR-V design limitations.
4538 if (lf.cast(.spirv)) |spirv_file| {4594 if (lf.cast(.spirv)) |spirv_file| {
4539 assert(pt.tid == .main); // SPIR-V has a lot of shared state4595 assert(zcu.pending_codegen_jobs.load(.monotonic) == 2); // only one codegen at a time (but the value is 2 because 1 is the base)
4540 spirv_file.updateFunc(pt, func_index, air, &liveness) catch |err| {4596 spirv_file.updateFunc(pt, func_index, air, &liveness) catch |err| {
4541 switch (err) {4597 switch (err) {
4542 error.OutOfMemory => comp.link_diags.setAllocFailure(),4598 error.OutOfMemory => comp.link_diags.setAllocFailure(),
src/codegen/spirv/CodeGen.zig+9-6
...@@ -2270,6 +2270,9 @@ fn buildWideMul(...@@ -2270,6 +2270,9 @@ fn buildWideMul(
2270) !struct { Temporary, Temporary } {2270) !struct { Temporary, Temporary } {
2271 const pt = cg.pt;2271 const pt = cg.pt;
2272 const zcu = cg.module.zcu;2272 const zcu = cg.module.zcu;
2273 const comp = zcu.comp;
2274 const gpa = comp.gpa;
2275 const io = comp.io;
2273 const target = cg.module.zcu.getTarget();2276 const target = cg.module.zcu.getTarget();
2274 const ip = &zcu.intern_pool;2277 const ip = &zcu.intern_pool;
22752278
...@@ -2297,14 +2300,14 @@ fn buildWideMul(...@@ -2297,14 +2300,14 @@ fn buildWideMul(
2297 };2300 };
22982301
2299 for (0..ops) |i| {2302 for (0..ops) |i| {
2300 try cg.body.emit(cg.module.gpa, .OpIMul, .{2303 try cg.body.emit(gpa, .OpIMul, .{
2301 .id_result_type = arith_op_ty_id,2304 .id_result_type = arith_op_ty_id,
2302 .id_result = value_results.at(i),2305 .id_result = value_results.at(i),
2303 .operand_1 = lhs_op.at(i),2306 .operand_1 = lhs_op.at(i),
2304 .operand_2 = rhs_op.at(i),2307 .operand_2 = rhs_op.at(i),
2305 });2308 });
23062309
2307 try cg.body.emit(cg.module.gpa, .OpExtInst, .{2310 try cg.body.emit(gpa, .OpExtInst, .{
2308 .id_result_type = arith_op_ty_id,2311 .id_result_type = arith_op_ty_id,
2309 .id_result = overflow_results.at(i),2312 .id_result = overflow_results.at(i),
2310 .set = set,2313 .set = set,
...@@ -2316,7 +2319,7 @@ fn buildWideMul(...@@ -2316,7 +2319,7 @@ fn buildWideMul(
2316 .vulkan, .opengl => {2319 .vulkan, .opengl => {
2317 // Operations return a struct{T, T}2320 // Operations return a struct{T, T}
2318 // where T is maybe vectorized.2321 // where T is maybe vectorized.
2319 const op_result_ty: Type = .fromInterned(try ip.getTupleType(zcu.gpa, pt.tid, .{2322 const op_result_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{
2320 .types = &.{ arith_op_ty.toIntern(), arith_op_ty.toIntern() },2323 .types = &.{ arith_op_ty.toIntern(), arith_op_ty.toIntern() },
2321 .values = &.{ .none, .none },2324 .values = &.{ .none, .none },
2322 }));2325 }));
...@@ -2330,7 +2333,7 @@ fn buildWideMul(...@@ -2330,7 +2333,7 @@ fn buildWideMul(
2330 for (0..ops) |i| {2333 for (0..ops) |i| {
2331 const op_result = cg.module.allocId();2334 const op_result = cg.module.allocId();
23322335
2333 try cg.body.emitRaw(cg.module.gpa, opcode, 4);2336 try cg.body.emitRaw(gpa, opcode, 4);
2334 cg.body.writeOperand(Id, op_result_ty_id);2337 cg.body.writeOperand(Id, op_result_ty_id);
2335 cg.body.writeOperand(Id, op_result);2338 cg.body.writeOperand(Id, op_result);
2336 cg.body.writeOperand(Id, lhs_op.at(i));2339 cg.body.writeOperand(Id, lhs_op.at(i));
...@@ -2340,14 +2343,14 @@ fn buildWideMul(...@@ -2340,14 +2343,14 @@ fn buildWideMul(
2340 // Temporary to deal with the fact that these are structs eventually,2343 // Temporary to deal with the fact that these are structs eventually,
2341 // but for now, take the struct apart and return two separate vectors.2344 // but for now, take the struct apart and return two separate vectors.
23422345
2343 try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{2346 try cg.body.emit(gpa, .OpCompositeExtract, .{
2344 .id_result_type = arith_op_ty_id,2347 .id_result_type = arith_op_ty_id,
2345 .id_result = value_results.at(i),2348 .id_result = value_results.at(i),
2346 .composite = op_result,2349 .composite = op_result,
2347 .indexes = &.{0},2350 .indexes = &.{0},
2348 });2351 });
23492352
2350 try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{2353 try cg.body.emit(gpa, .OpCompositeExtract, .{
2351 .id_result_type = arith_op_ty_id,2354 .id_result_type = arith_op_ty_id,
2352 .id_result = overflow_results.at(i),2355 .id_result = overflow_results.at(i),
2353 .composite = op_result,2356 .composite = op_result,
src/codegen/x86_64/CodeGen.zig+10-8
...@@ -180204,6 +180204,7 @@ fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -180204,6 +180204,7 @@ fn airSplat(self: *CodeGen, inst: Air.Inst.Index) !void {
180204fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {180204fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
180205 const pt = self.pt;180205 const pt = self.pt;
180206 const zcu = pt.zcu;180206 const zcu = pt.zcu;
180207 const io = zcu.comp.io;
180207 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;180208 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
180208 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;180209 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
180209 const ty = self.typeOfIndex(inst);180210 const ty = self.typeOfIndex(inst);
...@@ -180477,7 +180478,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -180477,7 +180478,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
180477 for (mask_elems, 0..) |*elem, bit| elem.* = @intCast(bit / elem_bits);180478 for (mask_elems, 0..) |*elem, bit| elem.* = @intCast(bit / elem_bits);
180478 const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{180479 const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{
180479 .ty = mask_ty.toIntern(),180480 .ty = mask_ty.toIntern(),
180480 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, mask_elems, .maybe_embedded_nulls) },180481 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, mask_elems, .maybe_embedded_nulls) },
180481 } })));180482 } })));
180482 const mask_mem: Memory = .{180483 const mask_mem: Memory = .{
180483 .base = .{ .reg = try self.copyToTmpRegister(.usize, mask_mcv.address()) },180484 .base = .{ .reg = try self.copyToTmpRegister(.usize, mask_mcv.address()) },
...@@ -188476,6 +188477,7 @@ const Select = struct {...@@ -188476,6 +188477,7 @@ const Select = struct {
188476 fn create(spec: TempSpec, s: *const Select) InnerError!struct { Temp, bool } {188477 fn create(spec: TempSpec, s: *const Select) InnerError!struct { Temp, bool } {
188477 const cg = s.cg;188478 const cg = s.cg;
188478 const pt = cg.pt;188479 const pt = cg.pt;
188480 const io = pt.zcu.comp.io;
188479 return switch (spec.kind) {188481 return switch (spec.kind) {
188480 .unused => .{ undefined, false },188482 .unused => .{ undefined, false },
188481 .any => .{ try cg.tempAlloc(spec.type), true },188483 .any => .{ try cg.tempAlloc(spec.type), true },
...@@ -188693,7 +188695,7 @@ const Select = struct {...@@ -188693,7 +188695,7 @@ const Select = struct {
188693 };188695 };
188694 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{188696 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
188695 .ty = spec.type.toIntern(),188697 .ty = spec.type.toIntern(),
188696 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) },188698 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
188697 } }))), true };188699 } }))), true };
188698 },188700 },
188699 .pshufb_trunc_mem => |trunc_spec| {188701 .pshufb_trunc_mem => |trunc_spec| {
...@@ -188720,7 +188722,7 @@ const Select = struct {...@@ -188720,7 +188722,7 @@ const Select = struct {
188720 };188722 };
188721 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{188723 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
188722 .ty = spec.type.toIntern(),188724 .ty = spec.type.toIntern(),
188723 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) },188725 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
188724 } }))), true };188726 } }))), true };
188725 },188727 },
188726 .pand_trunc_mem => |trunc_spec| {188728 .pand_trunc_mem => |trunc_spec| {
...@@ -188734,7 +188736,7 @@ const Select = struct {...@@ -188734,7 +188736,7 @@ const Select = struct {
188734 while (index < elems.len) : (index += from_bytes) @memset(elems[index..][0..to_bytes], std.math.maxInt(u8));188736 while (index < elems.len) : (index += from_bytes) @memset(elems[index..][0..to_bytes], std.math.maxInt(u8));
188735 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{188737 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
188736 .ty = spec.type.toIntern(),188738 .ty = spec.type.toIntern(),
188737 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) },188739 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
188738 } }))), true };188740 } }))), true };
188739 },188741 },
188740 .pand_mask_mem => |mask_spec| {188742 .pand_mask_mem => |mask_spec| {
...@@ -188753,7 +188755,7 @@ const Select = struct {...@@ -188753,7 +188755,7 @@ const Select = struct {
188753 @memset(elems[mask_len..], invert_mask);188755 @memset(elems[mask_len..], invert_mask);
188754 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{188756 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
188755 .ty = spec.type.toIntern(),188757 .ty = spec.type.toIntern(),
188756 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) },188758 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
188757 } }))), true };188759 } }))), true };
188758 },188760 },
188759 .ptest_mask_mem => |mask_ref| {188761 .ptest_mask_mem => |mask_ref| {
...@@ -188778,7 +188780,7 @@ const Select = struct {...@@ -188778,7 +188780,7 @@ const Select = struct {
188778 }188780 }
188779 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{188781 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
188780 .ty = spec.type.toIntern(),188782 .ty = spec.type.toIntern(),
188781 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) },188783 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
188782 } }))), true };188784 } }))), true };
188783 },188785 },
188784 .pshufb_bswap_mem => |bswap_spec| {188786 .pshufb_bswap_mem => |bswap_spec| {
...@@ -188794,7 +188796,7 @@ const Select = struct {...@@ -188794,7 +188796,7 @@ const Select = struct {
188794 };188796 };
188795 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{188797 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
188796 .ty = spec.type.toIntern(),188798 .ty = spec.type.toIntern(),
188797 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) },188799 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
188798 } }))), true };188800 } }))), true };
188799 },188801 },
188800 .bits_mem => |direction| {188802 .bits_mem => |direction| {
...@@ -188808,7 +188810,7 @@ const Select = struct {...@@ -188808,7 +188810,7 @@ const Select = struct {
188808 };188810 };
188809 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{188811 return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{
188810 .ty = spec.type.toIntern(),188812 .ty = spec.type.toIntern(),
188811 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, elems, .maybe_embedded_nulls) },188813 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(zcu.gpa, io, pt.tid, elems, .maybe_embedded_nulls) },
188812 } }))), true };188814 } }))), true };
188813 },188815 },
188814 .splat_int_mem => |splat_spec| {188816 .splat_int_mem => |splat_spec| {
src/libs/freebsd.zig+6-5
...@@ -991,7 +991,8 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -991,7 +991,8 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
991 });991 });
992}992}
993993
994fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {994fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void {
995 const io = comp.io;
995 const target = comp.getTarget();996 const target = comp.getTarget();
996 const target_os_version = target.os.version_range.semver.min;997 const target_os_version = target.os.version_range.semver.min;
997998
...@@ -1002,8 +1003,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {...@@ -1002,8 +1003,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
1002 var task_buffer_i: usize = 0;1003 var task_buffer_i: usize = 0;
10031004
1004 {1005 {
1005 comp.mutex.lock(); // protect comp.arena1006 comp.mutex.lockUncancelable(io); // protect comp.arena
1006 defer comp.mutex.unlock();1007 defer comp.mutex.unlock(io);
10071008
1008 for (libs) |lib| {1009 for (libs) |lib| {
1009 if (lib.added_in) |add_in| {1010 if (lib.added_in) |add_in| {
...@@ -1021,7 +1022,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {...@@ -1021,7 +1022,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
1021 }1022 }
1022 }1023 }
10231024
1024 comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);1025 try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
1025}1026}
10261027
1027fn buildSharedLib(1028fn buildSharedLib(
...@@ -1094,8 +1095,8 @@ fn buildSharedLib(...@@ -1094,8 +1095,8 @@ fn buildSharedLib(
10941095
1095 var sub_create_diag: Compilation.CreateDiagnostic = undefined;1096 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
1096 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{1097 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{
1098 .thread_limit = comp.thread_limit,
1097 .dirs = comp.dirs.withoutLocalCache(),1099 .dirs = comp.dirs.withoutLocalCache(),
1098 .thread_pool = comp.thread_pool,
1099 .self_exe_path = comp.self_exe_path,1100 .self_exe_path = comp.self_exe_path,
1100 // Because we manually cache the whole set of objects, we don't cache the individual objects1101 // Because we manually cache the whole set of objects, we don't cache the individual objects
1101 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.1102 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
src/libs/glibc.zig+6-5
...@@ -1135,7 +1135,8 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -1135,7 +1135,8 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
1135 });1135 });
1136}1136}
11371137
1138fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {1138fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void {
1139 const io = comp.io;
1139 const target_version = comp.getTarget().os.versionRange().gnuLibCVersion().?;1140 const target_version = comp.getTarget().os.versionRange().gnuLibCVersion().?;
11401141
1141 assert(comp.glibc_so_files == null);1142 assert(comp.glibc_so_files == null);
...@@ -1145,8 +1146,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {...@@ -1145,8 +1146,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
1145 var task_buffer_i: usize = 0;1146 var task_buffer_i: usize = 0;
11461147
1147 {1148 {
1148 comp.mutex.lock(); // protect comp.arena1149 comp.mutex.lockUncancelable(io); // protect comp.arena
1149 defer comp.mutex.unlock();1150 defer comp.mutex.unlock(io);
11501151
1151 for (libs) |lib| {1152 for (libs) |lib| {
1152 if (lib.removed_in) |rem_in| {1153 if (lib.removed_in) |rem_in| {
...@@ -1163,7 +1164,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {...@@ -1163,7 +1164,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
1163 }1164 }
1164 }1165 }
11651166
1166 comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);1167 try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
1167}1168}
11681169
1169fn buildSharedLib(1170fn buildSharedLib(
...@@ -1233,8 +1234,8 @@ fn buildSharedLib(...@@ -1233,8 +1234,8 @@ fn buildSharedLib(
12331234
1234 var sub_create_diag: Compilation.CreateDiagnostic = undefined;1235 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
1235 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{1236 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{
1237 .thread_limit = comp.thread_limit,
1236 .dirs = comp.dirs.withoutLocalCache(),1238 .dirs = comp.dirs.withoutLocalCache(),
1237 .thread_pool = comp.thread_pool,
1238 .self_exe_path = comp.self_exe_path,1239 .self_exe_path = comp.self_exe_path,
1239 // Because we manually cache the whole set of objects, we don't cache the individual objects1240 // Because we manually cache the whole set of objects, we don't cache the individual objects
1240 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.1241 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
src/libs/libcxx.zig+5-5
...@@ -106,7 +106,7 @@ pub const BuildError = error{...@@ -106,7 +106,7 @@ pub const BuildError = error{
106 OutOfMemory,106 OutOfMemory,
107 AlreadyReported,107 AlreadyReported,
108 ZigCompilerNotBuiltWithLLVMExtensions,108 ZigCompilerNotBuiltWithLLVMExtensions,
109};109} || std.Io.Cancelable;
110110
111pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {111pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {
112 if (!build_options.have_llvm) {112 if (!build_options.have_llvm) {
...@@ -256,13 +256,13 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!...@@ -256,13 +256,13 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
256256
257 var sub_create_diag: Compilation.CreateDiagnostic = undefined;257 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
258 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{258 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{
259 .thread_limit = comp.thread_limit,
259 .dirs = comp.dirs.withoutLocalCache(),260 .dirs = comp.dirs.withoutLocalCache(),
260 .self_exe_path = comp.self_exe_path,261 .self_exe_path = comp.self_exe_path,
261 .cache_mode = .whole,262 .cache_mode = .whole,
262 .config = config,263 .config = config,
263 .root_mod = root_mod,264 .root_mod = root_mod,
264 .root_name = root_name,265 .root_name = root_name,
265 .thread_pool = comp.thread_pool,
266 .libc_installation = comp.libc_installation,266 .libc_installation = comp.libc_installation,
267 .emit_bin = .yes_cache,267 .emit_bin = .yes_cache,
268 .c_source_files = c_source_files.items,268 .c_source_files = c_source_files.items,
...@@ -295,7 +295,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!...@@ -295,7 +295,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
295 assert(comp.libcxx_static_lib == null);295 assert(comp.libcxx_static_lib == null);
296 const crt_file = try sub_compilation.toCrtFile();296 const crt_file = try sub_compilation.toCrtFile();
297 comp.libcxx_static_lib = crt_file;297 comp.libcxx_static_lib = crt_file;
298 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);298 try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
299}299}
300300
301pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {301pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {
...@@ -449,13 +449,13 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -449,13 +449,13 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
449449
450 var sub_create_diag: Compilation.CreateDiagnostic = undefined;450 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
451 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{451 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{
452 .thread_limit = comp.thread_limit,
452 .dirs = comp.dirs.withoutLocalCache(),453 .dirs = comp.dirs.withoutLocalCache(),
453 .self_exe_path = comp.self_exe_path,454 .self_exe_path = comp.self_exe_path,
454 .cache_mode = .whole,455 .cache_mode = .whole,
455 .config = config,456 .config = config,
456 .root_mod = root_mod,457 .root_mod = root_mod,
457 .root_name = root_name,458 .root_name = root_name,
458 .thread_pool = comp.thread_pool,
459 .libc_installation = comp.libc_installation,459 .libc_installation = comp.libc_installation,
460 .emit_bin = .yes_cache,460 .emit_bin = .yes_cache,
461 .c_source_files = c_source_files.items,461 .c_source_files = c_source_files.items,
...@@ -492,7 +492,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -492,7 +492,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
492 assert(comp.libcxxabi_static_lib == null);492 assert(comp.libcxxabi_static_lib == null);
493 const crt_file = try sub_compilation.toCrtFile();493 const crt_file = try sub_compilation.toCrtFile();
494 comp.libcxxabi_static_lib = crt_file;494 comp.libcxxabi_static_lib = crt_file;
495 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);495 try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
496}496}
497497
498pub fn addCxxArgs(498pub fn addCxxArgs(
src/libs/libtsan.zig+3-3
...@@ -11,7 +11,7 @@ pub const BuildError = error{...@@ -11,7 +11,7 @@ pub const BuildError = error{
11 AlreadyReported,11 AlreadyReported,
12 ZigCompilerNotBuiltWithLLVMExtensions,12 ZigCompilerNotBuiltWithLLVMExtensions,
13 TSANUnsupportedCPUArchitecture,13 TSANUnsupportedCPUArchitecture,
14};14} || std.Io.Cancelable;
1515
16pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {16pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {
17 if (!build_options.have_llvm) {17 if (!build_options.have_llvm) {
...@@ -279,8 +279,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -279,8 +279,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
279279
280 var sub_create_diag: Compilation.CreateDiagnostic = undefined;280 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
281 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{281 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{
282 .thread_limit = comp.thread_limit,
282 .dirs = comp.dirs.withoutLocalCache(),283 .dirs = comp.dirs.withoutLocalCache(),
283 .thread_pool = comp.thread_pool,
284 .self_exe_path = comp.self_exe_path,284 .self_exe_path = comp.self_exe_path,
285 .cache_mode = .whole,285 .cache_mode = .whole,
286 .config = config,286 .config = config,
...@@ -319,7 +319,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -319,7 +319,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
319 };319 };
320320
321 const crt_file = try sub_compilation.toCrtFile();321 const crt_file = try sub_compilation.toCrtFile();
322 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);322 try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
323 assert(comp.tsan_lib == null);323 assert(comp.tsan_lib == null);
324 comp.tsan_lib = crt_file;324 comp.tsan_lib = crt_file;
325}325}
src/libs/libunwind.zig+3-3
...@@ -12,7 +12,7 @@ pub const BuildError = error{...@@ -12,7 +12,7 @@ pub const BuildError = error{
12 OutOfMemory,12 OutOfMemory,
13 AlreadyReported,13 AlreadyReported,
14 ZigCompilerNotBuiltWithLLVMExtensions,14 ZigCompilerNotBuiltWithLLVMExtensions,
15};15} || std.Io.Cancelable;
1616
17pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {17pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {
18 if (!build_options.have_llvm) {18 if (!build_options.have_llvm) {
...@@ -145,6 +145,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -145,6 +145,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
145145
146 var sub_create_diag: Compilation.CreateDiagnostic = undefined;146 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
147 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{147 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{
148 .thread_limit = comp.thread_limit,
148 .dirs = comp.dirs.withoutLocalCache(),149 .dirs = comp.dirs.withoutLocalCache(),
149 .self_exe_path = comp.self_exe_path,150 .self_exe_path = comp.self_exe_path,
150 .config = config,151 .config = config,
...@@ -152,7 +153,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -152,7 +153,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
152 .cache_mode = .whole,153 .cache_mode = .whole,
153 .root_name = root_name,154 .root_name = root_name,
154 .main_mod = null,155 .main_mod = null,
155 .thread_pool = comp.thread_pool,
156 .libc_installation = comp.libc_installation,156 .libc_installation = comp.libc_installation,
157 .emit_bin = .yes_cache,157 .emit_bin = .yes_cache,
158 .function_sections = comp.function_sections,158 .function_sections = comp.function_sections,
...@@ -184,7 +184,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -184,7 +184,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
184 };184 };
185185
186 const crt_file = try sub_compilation.toCrtFile();186 const crt_file = try sub_compilation.toCrtFile();
187 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);187 try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
188 assert(comp.libunwind_static_lib == null);188 assert(comp.libunwind_static_lib == null);
189 comp.libunwind_static_lib = crt_file;189 comp.libunwind_static_lib = crt_file;
190}190}
src/libs/mingw.zig+4-4
...@@ -281,8 +281,8 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -281,8 +281,8 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
281 const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });281 const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });
282 errdefer gpa.free(sub_path);282 errdefer gpa.free(sub_path);
283283
284 comp.mutex.lock();284 comp.mutex.lockUncancelable(io);
285 defer comp.mutex.unlock();285 defer comp.mutex.unlock(io);
286 try comp.crt_files.ensureUnusedCapacity(gpa, 1);286 try comp.crt_files.ensureUnusedCapacity(gpa, 1);
287 comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{287 comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{
288 .full_object_path = .{288 .full_object_path = .{
...@@ -388,8 +388,8 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -388,8 +388,8 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
388 log.warn("failed to write cache manifest for DLL import {s}.lib: {s}", .{ lib_name, @errorName(err) });388 log.warn("failed to write cache manifest for DLL import {s}.lib: {s}", .{ lib_name, @errorName(err) });
389 };389 };
390390
391 comp.mutex.lock();391 comp.mutex.lockUncancelable(io);
392 defer comp.mutex.unlock();392 defer comp.mutex.unlock(io);
393 try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{393 try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{
394 .full_object_path = .{394 .full_object_path = .{
395 .root_dir = comp.dirs.global_cache,395 .root_dir = comp.dirs.global_cache,
src/libs/musl.zig+4-4
...@@ -248,12 +248,12 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -248,12 +248,12 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
248248
249 var sub_create_diag: Compilation.CreateDiagnostic = undefined;249 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
250 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{250 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{
251 .thread_limit = comp.thread_limit,
251 .dirs = comp.dirs.withoutLocalCache(),252 .dirs = comp.dirs.withoutLocalCache(),
252 .self_exe_path = comp.self_exe_path,253 .self_exe_path = comp.self_exe_path,
253 .cache_mode = .whole,254 .cache_mode = .whole,
254 .config = config,255 .config = config,
255 .root_mod = root_mod,256 .root_mod = root_mod,
256 .thread_pool = comp.thread_pool,
257 .root_name = "c",257 .root_name = "c",
258 .libc_installation = comp.libc_installation,258 .libc_installation = comp.libc_installation,
259 .emit_bin = .yes_cache,259 .emit_bin = .yes_cache,
...@@ -287,10 +287,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -287,10 +287,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
287 errdefer comp.gpa.free(basename);287 errdefer comp.gpa.free(basename);
288288
289 const crt_file = try sub_compilation.toCrtFile();289 const crt_file = try sub_compilation.toCrtFile();
290 comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);290 try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config);
291 {291 {
292 comp.mutex.lock();292 comp.mutex.lockUncancelable(io);
293 defer comp.mutex.unlock();293 defer comp.mutex.unlock(io);
294 try comp.crt_files.ensureUnusedCapacity(comp.gpa, 1);294 try comp.crt_files.ensureUnusedCapacity(comp.gpa, 1);
295 comp.crt_files.putAssumeCapacityNoClobber(basename, crt_file);295 comp.crt_files.putAssumeCapacityNoClobber(basename, crt_file);
296 }296 }
src/libs/netbsd.zig+6-5
...@@ -645,7 +645,8 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -645,7 +645,8 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
645 });645 });
646}646}
647647
648fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {648fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void {
649 const io = comp.io;
649 assert(comp.netbsd_so_files == null);650 assert(comp.netbsd_so_files == null);
650 comp.netbsd_so_files = so_files;651 comp.netbsd_so_files = so_files;
651652
...@@ -653,8 +654,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {...@@ -653,8 +654,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
653 var task_buffer_i: usize = 0;654 var task_buffer_i: usize = 0;
654655
655 {656 {
656 comp.mutex.lock(); // protect comp.arena657 comp.mutex.lockUncancelable(io); // protect comp.arena
657 defer comp.mutex.unlock();658 defer comp.mutex.unlock(io);
658659
659 for (libs) |lib| {660 for (libs) |lib| {
660 const so_path: Path = .{661 const so_path: Path = .{
...@@ -668,7 +669,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {...@@ -668,7 +669,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
668 }669 }
669 }670 }
670671
671 comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);672 try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]);
672}673}
673674
674fn buildSharedLib(675fn buildSharedLib(
...@@ -737,8 +738,8 @@ fn buildSharedLib(...@@ -737,8 +738,8 @@ fn buildSharedLib(
737738
738 var sub_create_diag: Compilation.CreateDiagnostic = undefined;739 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
739 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{740 const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{
741 .thread_limit = comp.thread_limit,
740 .dirs = comp.dirs.withoutLocalCache(),742 .dirs = comp.dirs.withoutLocalCache(),
741 .thread_pool = comp.thread_pool,
742 .self_exe_path = comp.self_exe_path,743 .self_exe_path = comp.self_exe_path,
743 // Because we manually cache the whole set of objects, we don't cache the individual objects744 // Because we manually cache the whole set of objects, we don't cache the individual objects
744 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.745 // within it. In fact, we *can't* do that, because we need `emit_bin` to specify the path.
src/link.zig+64-93
...@@ -34,7 +34,8 @@ pub const Diags = struct {...@@ -34,7 +34,8 @@ pub const Diags = struct {
34 /// Stored here so that function definitions can distinguish between34 /// Stored here so that function definitions can distinguish between
35 /// needing an allocator for things besides error reporting.35 /// needing an allocator for things besides error reporting.
36 gpa: Allocator,36 gpa: Allocator,
37 mutex: std.Thread.Mutex,37 io: Io,
38 mutex: Io.Mutex,
38 msgs: std.ArrayList(Msg),39 msgs: std.ArrayList(Msg),
39 flags: Flags,40 flags: Flags,
40 lld: std.ArrayList(Lld),41 lld: std.ArrayList(Lld),
...@@ -126,10 +127,11 @@ pub const Diags = struct {...@@ -126,10 +127,11 @@ pub const Diags = struct {
126 }127 }
127 };128 };
128129
129 pub fn init(gpa: Allocator) Diags {130 pub fn init(gpa: Allocator, io: Io) Diags {
130 return .{131 return .{
131 .gpa = gpa,132 .gpa = gpa,
132 .mutex = .{},133 .io = io,
134 .mutex = .init,
133 .msgs = .empty,135 .msgs = .empty,
134 .flags = .{},136 .flags = .{},
135 .lld = .empty,137 .lld = .empty,
...@@ -153,8 +155,10 @@ pub const Diags = struct {...@@ -153,8 +155,10 @@ pub const Diags = struct {
153 }155 }
154156
155 pub fn lockAndParseLldStderr(diags: *Diags, prefix: []const u8, stderr: []const u8) void {157 pub fn lockAndParseLldStderr(diags: *Diags, prefix: []const u8, stderr: []const u8) void {
156 diags.mutex.lock();158 const io = diags.io;
157 defer diags.mutex.unlock();159
160 diags.mutex.lockUncancelable(io);
161 defer diags.mutex.unlock(io);
158162
159 diags.parseLldStderr(prefix, stderr) catch diags.setAllocFailure();163 diags.parseLldStderr(prefix, stderr) catch diags.setAllocFailure();
160 }164 }
...@@ -226,9 +230,10 @@ pub const Diags = struct {...@@ -226,9 +230,10 @@ pub const Diags = struct {
226 pub fn addErrorSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) void {230 pub fn addErrorSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) void {
227 @branchHint(.cold);231 @branchHint(.cold);
228 const gpa = diags.gpa;232 const gpa = diags.gpa;
233 const io = diags.io;
229 const eu_main_msg = std.fmt.allocPrint(gpa, format, args);234 const eu_main_msg = std.fmt.allocPrint(gpa, format, args);
230 diags.mutex.lock();235 diags.mutex.lockUncancelable(io);
231 defer diags.mutex.unlock();236 defer diags.mutex.unlock(io);
232 addErrorLockedFallible(diags, sl, eu_main_msg) catch |err| switch (err) {237 addErrorLockedFallible(diags, sl, eu_main_msg) catch |err| switch (err) {
233 error.OutOfMemory => diags.setAllocFailureLocked(),238 error.OutOfMemory => diags.setAllocFailureLocked(),
234 };239 };
...@@ -247,8 +252,9 @@ pub const Diags = struct {...@@ -247,8 +252,9 @@ pub const Diags = struct {
247 pub fn addErrorWithNotes(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes {252 pub fn addErrorWithNotes(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes {
248 @branchHint(.cold);253 @branchHint(.cold);
249 const gpa = diags.gpa;254 const gpa = diags.gpa;
250 diags.mutex.lock();255 const io = diags.io;
251 defer diags.mutex.unlock();256 diags.mutex.lockUncancelable(io);
257 defer diags.mutex.unlock(io);
252 try diags.msgs.ensureUnusedCapacity(gpa, 1);258 try diags.msgs.ensureUnusedCapacity(gpa, 1);
253 return addErrorWithNotesAssumeCapacity(diags, note_count);259 return addErrorWithNotesAssumeCapacity(diags, note_count);
254 }260 }
...@@ -276,9 +282,10 @@ pub const Diags = struct {...@@ -276,9 +282,10 @@ pub const Diags = struct {
276 ) void {282 ) void {
277 @branchHint(.cold);283 @branchHint(.cold);
278 const gpa = diags.gpa;284 const gpa = diags.gpa;
285 const io = diags.io;
279 const eu_main_msg = std.fmt.allocPrint(gpa, format, args);286 const eu_main_msg = std.fmt.allocPrint(gpa, format, args);
280 diags.mutex.lock();287 diags.mutex.lockUncancelable(io);
281 defer diags.mutex.unlock();288 defer diags.mutex.unlock(io);
282 addMissingLibraryErrorLockedFallible(diags, checked_paths, eu_main_msg) catch |err| switch (err) {289 addMissingLibraryErrorLockedFallible(diags, checked_paths, eu_main_msg) catch |err| switch (err) {
283 error.OutOfMemory => diags.setAllocFailureLocked(),290 error.OutOfMemory => diags.setAllocFailureLocked(),
284 };291 };
...@@ -312,9 +319,10 @@ pub const Diags = struct {...@@ -312,9 +319,10 @@ pub const Diags = struct {
312 ) void {319 ) void {
313 @branchHint(.cold);320 @branchHint(.cold);
314 const gpa = diags.gpa;321 const gpa = diags.gpa;
322 const io = diags.io;
315 const eu_main_msg = std.fmt.allocPrint(gpa, format, args);323 const eu_main_msg = std.fmt.allocPrint(gpa, format, args);
316 diags.mutex.lock();324 diags.mutex.lockUncancelable(io);
317 defer diags.mutex.unlock();325 defer diags.mutex.unlock(io);
318 addParseErrorLockedFallible(diags, path, eu_main_msg) catch |err| switch (err) {326 addParseErrorLockedFallible(diags, path, eu_main_msg) catch |err| switch (err) {
319 error.OutOfMemory => diags.setAllocFailureLocked(),327 error.OutOfMemory => diags.setAllocFailureLocked(),
320 };328 };
...@@ -349,8 +357,9 @@ pub const Diags = struct {...@@ -349,8 +357,9 @@ pub const Diags = struct {
349357
350 pub fn setAllocFailure(diags: *Diags) void {358 pub fn setAllocFailure(diags: *Diags) void {
351 @branchHint(.cold);359 @branchHint(.cold);
352 diags.mutex.lock();360 const io = diags.io;
353 defer diags.mutex.unlock();361 diags.mutex.lockUncancelable(io);
362 defer diags.mutex.unlock(io);
354 setAllocFailureLocked(diags);363 setAllocFailureLocked(diags);
355 }364 }
356365
...@@ -1101,6 +1110,7 @@ pub const File = struct {...@@ -1101,6 +1110,7 @@ pub const File = struct {
1101 const comp = base.comp;1110 const comp = base.comp;
1102 const diags = &comp.link_diags;1111 const diags = &comp.link_diags;
1103 const gpa = comp.gpa;1112 const gpa = comp.gpa;
1113 const io = comp.io;
1104 const stat = try file.stat();1114 const stat = try file.stat();
1105 const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig;1115 const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig;
1106 const buf = try gpa.alloc(u8, size);1116 const buf = try gpa.alloc(u8, size);
...@@ -1123,8 +1133,8 @@ pub const File = struct {...@@ -1123,8 +1133,8 @@ pub const File = struct {
1123 } else {1133 } else {
1124 if (fs.path.isAbsolute(arg.path)) {1134 if (fs.path.isAbsolute(arg.path)) {
1125 const new_path = Path.initCwd(path: {1135 const new_path = Path.initCwd(path: {
1126 comp.mutex.lock();1136 comp.mutex.lockUncancelable(io);
1127 defer comp.mutex.unlock();1137 defer comp.mutex.unlock(io);
1128 break :path try comp.arena.dupe(u8, arg.path);1138 break :path try comp.arena.dupe(u8, arg.path);
1129 });1139 });
1130 switch (Compilation.classifyFileExt(arg.path)) {1140 switch (Compilation.classifyFileExt(arg.path)) {
...@@ -1309,61 +1319,13 @@ pub const ZcuTask = union(enum) {...@@ -1309,61 +1319,13 @@ pub const ZcuTask = union(enum) {
1309 /// Write the constant value for a Decl to the output file.1319 /// Write the constant value for a Decl to the output file.
1310 link_nav: InternPool.Nav.Index,1320 link_nav: InternPool.Nav.Index,
1311 /// Write the machine code for a function to the output file.1321 /// Write the machine code for a function to the output file.
1312 link_func: LinkFunc,1322 link_func: Zcu.CodegenTaskPool.Index,
1313 link_type: InternPool.Index,1323 link_type: InternPool.Index,
1314 update_line_number: InternPool.TrackedInst.Index,1324 update_line_number: InternPool.TrackedInst.Index,
1315 pub fn deinit(task: ZcuTask, zcu: *const Zcu) void {
1316 switch (task) {
1317 .link_nav,
1318 .link_type,
1319 .update_line_number,
1320 => {},
1321 .link_func => |link_func| {
1322 switch (link_func.mir.status.load(.acquire)) {
1323 .pending => unreachable, // cannot deinit until MIR done
1324 .failed => {}, // MIR not populated so doesn't need freeing
1325 .ready => link_func.mir.value.deinit(zcu),
1326 }
1327 zcu.gpa.destroy(link_func.mir);
1328 },
1329 }
1330 }
1331 pub const LinkFunc = struct {
1332 /// This will either be a non-generic `func_decl` or a `func_instance`.
1333 func: InternPool.Index,
1334 /// This pointer is allocated into `gpa` and must be freed when the `ZcuTask` is processed.
1335 /// The pointer is shared with the codegen worker, which will populate the MIR inside once
1336 /// it has been generated. It's important that the `link_func` is queued at the same time as
1337 /// the codegen job to ensure that the linker receives functions in a deterministic order,
1338 /// allowing reproducible builds.
1339 mir: *SharedMir,
1340 /// This is not actually used by `doZcuTask`. Instead, `Queue` uses this value as a heuristic
1341 /// to avoid queueing too much AIR/MIR for codegen/link at a time. Essentially, we cap the
1342 /// total number of AIR bytes which are being processed at once, preventing unbounded memory
1343 /// usage when AIR is produced faster than it is processed.
1344 air_bytes: u32,
1345
1346 pub const SharedMir = struct {
1347 /// This is initially `.pending`. When `value` is populated, the codegen thread will set
1348 /// this to `.ready`, and alert the queue if needed. It could also end up `.failed`.
1349 /// The action of storing a value (other than `.pending`) to this atomic transfers
1350 /// ownership of memory assoicated with `value` to this `ZcuTask`.
1351 status: std.atomic.Value(enum(u8) {
1352 /// We are waiting on codegen to generate MIR (or die trying).
1353 pending,
1354 /// `value` is not populated and will not be populated. Just drop the task from the queue and move on.
1355 failed,
1356 /// `value` is populated with the MIR from the backend in use, which is not LLVM.
1357 ready,
1358 }),
1359 /// This is `undefined` until `ready` is set to `true`. Once populated, this MIR belongs
1360 /// to the `ZcuTask`, and must be `deinit`ed when it is processed. Allocated into `gpa`.
1361 value: codegen.AnyMir,
1362 };
1363 };
1364};1325};
13651326
1366pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {1327pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1328 const io = comp.io;
1367 const diags = &comp.link_diags;1329 const diags = &comp.link_diags;
1368 const base = comp.bin_file orelse {1330 const base = comp.bin_file orelse {
1369 comp.link_prog_node.completeOne();1331 comp.link_prog_node.completeOne();
...@@ -1372,8 +1334,8 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1372,8 +1334,8 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
13721334
1373 var timer = comp.startTimer();1335 var timer = comp.startTimer();
1374 defer if (timer.finish()) |ns| {1336 defer if (timer.finish()) |ns| {
1375 comp.mutex.lock();1337 comp.mutex.lockUncancelable(io);
1376 defer comp.mutex.unlock();1338 defer comp.mutex.unlock(io);
1377 comp.time_report.?.stats.cpu_ns_link += ns;1339 comp.time_report.?.stats.cpu_ns_link += ns;
1378 };1340 };
13791341
...@@ -1484,6 +1446,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {...@@ -1484,6 +1446,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void {
1484 }1446 }
1485}1447}
1486pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {1448pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {
1449 const io = comp.io;
1487 const diags = &comp.link_diags;1450 const diags = &comp.link_diags;
1488 const zcu = comp.zcu.?;1451 const zcu = comp.zcu.?;
1489 const ip = &zcu.intern_pool;1452 const ip = &zcu.intern_pool;
...@@ -1492,8 +1455,8 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {...@@ -1492,8 +1455,8 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {
14921455
1493 var timer = comp.startTimer();1456 var timer = comp.startTimer();
14941457
1495 switch (task) {1458 const maybe_nav: ?InternPool.Nav.Index = switch (task) {
1496 .link_nav => |nav_index| {1459 .link_nav => |nav_index| nav: {
1497 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);1460 const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
1498 const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);1461 const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);
1499 defer nav_prog_node.end();1462 defer nav_prog_node.end();
...@@ -1514,21 +1477,25 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {...@@ -1514,21 +1477,25 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {
1514 },1477 },
1515 };1478 };
1516 }1479 }
1480 break :nav nav_index;
1517 },1481 },
1518 .link_func => |func| {1482 .link_func => |codegen_task| nav: {
1519 const nav = zcu.funcInfo(func.func).owner_nav;1483 timer.pause();
1484 const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) {
1485 error.Canceled, error.AlreadyReported => return,
1486 };
1487 defer mir.deinit(zcu);
1488 timer.@"resume"();
1489
1490 const nav = zcu.funcInfo(func).owner_nav;
1520 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);1491 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);
1492
1521 const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);1493 const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0);
1522 defer nav_prog_node.end();1494 defer nav_prog_node.end();
1523 switch (func.mir.status.load(.acquire)) {1495
1524 .pending => unreachable,
1525 .ready => {},
1526 .failed => return,
1527 }
1528 assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR1496 assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR
1529 const mir = &func.mir.value;
1530 if (comp.bin_file) |lf| {1497 if (comp.bin_file) |lf| {
1531 lf.updateFunc(pt, func.func, mir) catch |err| switch (err) {1498 lf.updateFunc(pt, func, &mir) catch |err| switch (err) {
1532 error.OutOfMemory => return diags.setAllocFailure(),1499 error.OutOfMemory => return diags.setAllocFailure(),
1533 error.CodegenFail => return zcu.assertCodegenFailed(nav),1500 error.CodegenFail => return zcu.assertCodegenFailed(nav),
1534 error.Overflow, error.RelocationNotByteAligned => {1501 error.Overflow, error.RelocationNotByteAligned => {
...@@ -1539,8 +1506,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {...@@ -1539,8 +1506,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {
1539 },1506 },
1540 };1507 };
1541 }1508 }
1509 break :nav ip.indexToKey(func).func.owner_nav;
1542 },1510 },
1543 .link_type => |ty| {1511 .link_type => |ty| nav: {
1544 const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip);1512 const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip);
1545 const nav_prog_node = comp.link_prog_node.start(name, 0);1513 const nav_prog_node = comp.link_prog_node.start(name, 0);
1546 defer nav_prog_node.end();1514 defer nav_prog_node.end();
...@@ -1552,8 +1520,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {...@@ -1552,8 +1520,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {
1552 };1520 };
1553 }1521 }
1554 }1522 }
1523 break :nav null;
1555 },1524 },
1556 .update_line_number => |ti| {1525 .update_line_number => |ti| nav: {
1557 const nav_prog_node = comp.link_prog_node.start("Update line number", 0);1526 const nav_prog_node = comp.link_prog_node.start("Update line number", 0);
1558 defer nav_prog_node.end();1527 defer nav_prog_node.end();
1559 if (pt.zcu.llvm_object == null) {1528 if (pt.zcu.llvm_object == null) {
...@@ -1564,21 +1533,18 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {...@@ -1564,21 +1533,18 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void {
1564 };1533 };
1565 }1534 }
1566 }1535 }
1536 break :nav null;
1567 },1537 },
1568 }1538 };
15691539
1570 if (timer.finish()) |ns_link| report_time: {1540 if (timer.finish()) |ns_link| report_time: {
1571 const zir_decl: ?InternPool.TrackedInst.Index = switch (task) {1541 comp.mutex.lockUncancelable(io);
1572 .link_type, .update_line_number => null,1542 defer comp.mutex.unlock(io);
1573 .link_nav => |nav| ip.getNav(nav).srcInst(ip),
1574 .link_func => |f| ip.getNav(ip.indexToKey(f.func).func.owner_nav).srcInst(ip),
1575 };
1576 comp.mutex.lock();
1577 defer comp.mutex.unlock();
1578 const tr = &zcu.comp.time_report.?;1543 const tr = &zcu.comp.time_report.?;
1579 tr.stats.cpu_ns_link += ns_link;1544 tr.stats.cpu_ns_link += ns_link;
1580 if (zir_decl) |inst| {1545 if (maybe_nav) |nav| {
1581 const gop = tr.decl_link_ns.getOrPut(zcu.gpa, inst) catch |err| switch (err) {1546 const zir_decl = ip.getNav(nav).srcInst(ip);
1547 const gop = tr.decl_link_ns.getOrPut(zcu.gpa, zir_decl) catch |err| switch (err) {
1582 error.OutOfMemory => {1548 error.OutOfMemory => {
1583 zcu.comp.setAllocFailure();1549 zcu.comp.setAllocFailure();
1584 break :report_time;1550 break :report_time;
...@@ -2208,8 +2174,13 @@ fn resolvePathInputLib(...@@ -2208,8 +2174,13 @@ fn resolvePathInputLib(
2208 const n2 = file.preadAll(buf2, n) catch |err|2174 const n2 = file.preadAll(buf2, n) catch |err|
2209 fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) });2175 fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) });
2210 if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path});2176 if (n2 != buf2.len) fatal("failed to read {f}: unexpected end of file", .{test_path});
2211 var diags = Diags.init(gpa);2177
2178 // This `Io` is only used for a mutex, and we know we aren't doing anything async/concurrent.
2179 var threaded: Io.Threaded = .init_single_threaded;
2180 defer threaded.deinit();
2181 var diags: Diags = .init(gpa, threaded.io());
2212 defer diags.deinit();2182 defer diags.deinit();
2183
2213 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);2184 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);
2214 if (diags.hasErrors()) {2185 if (diags.hasErrors()) {
2215 var wip_errors: std.zig.ErrorBundle.Wip = undefined;2186 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
src/link/Elf.zig+3-2
...@@ -713,6 +713,7 @@ pub fn allocateChunk(self: *Elf, args: struct {...@@ -713,6 +713,7 @@ pub fn allocateChunk(self: *Elf, args: struct {
713pub fn loadInput(self: *Elf, input: link.Input) !void {713pub fn loadInput(self: *Elf, input: link.Input) !void {
714 const comp = self.base.comp;714 const comp = self.base.comp;
715 const gpa = comp.gpa;715 const gpa = comp.gpa;
716 const io = comp.io;
716 const diags = &comp.link_diags;717 const diags = &comp.link_diags;
717 const target = self.getTarget();718 const target = self.getTarget();
718 const debug_fmt_strip = comp.config.debug_format == .strip;719 const debug_fmt_strip = comp.config.debug_format == .strip;
...@@ -720,8 +721,8 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {...@@ -720,8 +721,8 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
720 const is_static_lib = self.base.isStaticLib();721 const is_static_lib = self.base.isStaticLib();
721722
722 if (comp.verbose_link) {723 if (comp.verbose_link) {
723 comp.mutex.lock(); // protect comp.arena724 comp.mutex.lockUncancelable(io); // protect comp.arena
724 defer comp.mutex.unlock();725 defer comp.mutex.unlock(io);
725726
726 const argv = &self.dump_argv_list;727 const argv = &self.dump_argv_list;
727 switch (input) {728 switch (input) {
src/link/MachO.zig+2-2
...@@ -29,9 +29,9 @@ resolver: SymbolResolver = .{},...@@ -29,9 +29,9 @@ resolver: SymbolResolver = .{},
29/// This table will be populated after `scanRelocs` has run.29/// This table will be populated after `scanRelocs` has run.
30/// Key is symbol index.30/// Key is symbol index.
31undefs: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, UndefRefs) = .empty,31undefs: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, UndefRefs) = .empty,
32undefs_mutex: std.Thread.Mutex = .{},32undefs_mutex: std.Io.Mutex = .init,
33dupes: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayList(File.Index)) = .empty,33dupes: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayList(File.Index)) = .empty,
34dupes_mutex: std.Thread.Mutex = .{},34dupes_mutex: std.Io.Mutex = .init,
3535
36dyld_info_cmd: macho.dyld_info_command = .{},36dyld_info_cmd: macho.dyld_info_command = .{},
37symtab_cmd: macho.symtab_command = .{},37symtab_cmd: macho.symtab_command = .{},
src/link/MachO/Atom.zig+3-2
...@@ -555,9 +555,10 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool {...@@ -555,9 +555,10 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool {
555 const file = self.getFile(macho_file);555 const file = self.getFile(macho_file);
556 const ref = file.getSymbolRef(rel.target, macho_file);556 const ref = file.getSymbolRef(rel.target, macho_file);
557 if (ref.getFile(macho_file) == null) {557 if (ref.getFile(macho_file) == null) {
558 macho_file.undefs_mutex.lock();
559 defer macho_file.undefs_mutex.unlock();
560 const gpa = macho_file.base.comp.gpa;558 const gpa = macho_file.base.comp.gpa;
559 const io = macho_file.base.comp.io;
560 macho_file.undefs_mutex.lockUncancelable(io);
561 defer macho_file.undefs_mutex.unlock(io);
561 const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]);562 const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]);
562 if (!gop.found_existing) {563 if (!gop.found_existing) {
563 gop.value_ptr.* = .{ .refs = .{} };564 gop.value_ptr.* = .{ .refs = .{} };
src/link/MachO/CodeSignature.zig+1-1
...@@ -289,7 +289,7 @@ pub fn writeAdhocSignature(...@@ -289,7 +289,7 @@ pub fn writeAdhocSignature(
289 self.code_directory.inner.nCodeSlots = total_pages;289 self.code_directory.inner.nCodeSlots = total_pages;
290290
291 // Calculate hash for each page (in file) and write it to the buffer291 // Calculate hash for each page (in file) and write it to the buffer
292 var hasher = Hasher(Sha256){ .allocator = allocator, .thread_pool = macho_file.base.comp.thread_pool };292 var hasher = Hasher(Sha256){ .allocator = allocator, .io = macho_file.base.comp.io };
293 try hasher.hash(opts.file, self.code_directory.code_slots.items, .{293 try hasher.hash(opts.file, self.code_directory.code_slots.items, .{
294 .chunk_size = self.page_size,294 .chunk_size = self.page_size,
295 .max_file_size = opts.file_size,295 .max_file_size = opts.file_size,
src/link/MachO/InternalObject.zig+3-2
...@@ -512,8 +512,9 @@ pub fn checkUndefs(self: InternalObject, macho_file: *MachO) !void {...@@ -512,8 +512,9 @@ pub fn checkUndefs(self: InternalObject, macho_file: *MachO) !void {
512 const addUndef = struct {512 const addUndef = struct {
513 fn addUndef(mf: *MachO, index: MachO.SymbolResolver.Index, tag: anytype) !void {513 fn addUndef(mf: *MachO, index: MachO.SymbolResolver.Index, tag: anytype) !void {
514 const gpa = mf.base.comp.gpa;514 const gpa = mf.base.comp.gpa;
515 mf.undefs_mutex.lock();515 const io = mf.base.comp.io;
516 defer mf.undefs_mutex.unlock();516 mf.undefs_mutex.lockUncancelable(io);
517 defer mf.undefs_mutex.unlock(io);
517 const gop = try mf.undefs.getOrPut(gpa, index);518 const gop = try mf.undefs.getOrPut(gpa, index);
518 if (!gop.found_existing) {519 if (!gop.found_existing) {
519 gop.value_ptr.* = tag;520 gop.value_ptr.* = tag;
src/link/MachO/file.zig+3-2
...@@ -242,6 +242,7 @@ pub const File = union(enum) {...@@ -242,6 +242,7 @@ pub const File = union(enum) {
242 const tracy = trace(@src());242 const tracy = trace(@src());
243 defer tracy.end();243 defer tracy.end();
244244
245 const io = macho_file.base.comp.io;
245 const gpa = macho_file.base.comp.gpa;246 const gpa = macho_file.base.comp.gpa;
246247
247 for (file.getSymbols(), file.getNlists(), 0..) |sym, nlist, i| {248 for (file.getSymbols(), file.getNlists(), 0..) |sym, nlist, i| {
...@@ -252,8 +253,8 @@ pub const File = union(enum) {...@@ -252,8 +253,8 @@ pub const File = union(enum) {
252 const ref_file = ref.getFile(macho_file) orelse continue;253 const ref_file = ref.getFile(macho_file) orelse continue;
253 if (ref_file.getIndex() == file.getIndex()) continue;254 if (ref_file.getIndex() == file.getIndex()) continue;
254255
255 macho_file.dupes_mutex.lock();256 macho_file.dupes_mutex.lockUncancelable(io);
256 defer macho_file.dupes_mutex.unlock();257 defer macho_file.dupes_mutex.unlock(io);
257258
258 const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]);259 const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]);
259 if (!gop.found_existing) {260 if (!gop.found_existing) {
src/link/MachO/hasher.zig+7-7
...@@ -3,7 +3,7 @@ pub fn ParallelHasher(comptime Hasher: type) type {...@@ -3,7 +3,7 @@ pub fn ParallelHasher(comptime Hasher: type) type {
33
4 return struct {4 return struct {
5 allocator: Allocator,5 allocator: Allocator,
6 thread_pool: *ThreadPool,6 io: std.Io,
77
8 pub fn hash(self: Self, file: fs.File, out: [][hash_size]u8, opts: struct {8 pub fn hash(self: Self, file: fs.File, out: [][hash_size]u8, opts: struct {
9 chunk_size: u64 = 0x4000,9 chunk_size: u64 = 0x4000,
...@@ -12,7 +12,7 @@ pub fn ParallelHasher(comptime Hasher: type) type {...@@ -12,7 +12,7 @@ pub fn ParallelHasher(comptime Hasher: type) type {
12 const tracy = trace(@src());12 const tracy = trace(@src());
13 defer tracy.end();13 defer tracy.end();
1414
15 var wg: WaitGroup = .{};15 const io = self.io;
1616
17 const file_size = blk: {17 const file_size = blk: {
18 const file_size = opts.max_file_size orelse try file.getEndPos();18 const file_size = opts.max_file_size orelse try file.getEndPos();
...@@ -27,8 +27,8 @@ pub fn ParallelHasher(comptime Hasher: type) type {...@@ -27,8 +27,8 @@ pub fn ParallelHasher(comptime Hasher: type) type {
27 defer self.allocator.free(results);27 defer self.allocator.free(results);
2828
29 {29 {
30 wg.reset();30 var group: std.Io.Group = .init;
31 defer wg.wait();31 errdefer group.cancel(io);
3232
33 for (out, results, 0..) |*out_buf, *result, i| {33 for (out, results, 0..) |*out_buf, *result, i| {
34 const fstart = i * chunk_size;34 const fstart = i * chunk_size;
...@@ -36,7 +36,7 @@ pub fn ParallelHasher(comptime Hasher: type) type {...@@ -36,7 +36,7 @@ pub fn ParallelHasher(comptime Hasher: type) type {
36 file_size - fstart36 file_size - fstart
37 else37 else
38 chunk_size;38 chunk_size;
39 self.thread_pool.spawnWg(&wg, worker, .{39 group.async(io, worker, .{
40 file,40 file,
41 fstart,41 fstart,
42 buffer[fstart..][0..fsize],42 buffer[fstart..][0..fsize],
...@@ -44,6 +44,8 @@ pub fn ParallelHasher(comptime Hasher: type) type {...@@ -44,6 +44,8 @@ pub fn ParallelHasher(comptime Hasher: type) type {
44 &(result.*),44 &(result.*),
45 });45 });
46 }46 }
47
48 group.wait(io);
47 }49 }
48 for (results) |result| _ = try result;50 for (results) |result| _ = try result;
49 }51 }
...@@ -72,5 +74,3 @@ const std = @import("std");...@@ -72,5 +74,3 @@ const std = @import("std");
72const trace = @import("../../tracy.zig").trace;74const trace = @import("../../tracy.zig").trace;
7375
74const Allocator = mem.Allocator;76const Allocator = mem.Allocator;
75const ThreadPool = std.Thread.Pool;
76const WaitGroup = std.Thread.WaitGroup;
src/link/MachO/relocatable.zig-1
...@@ -773,7 +773,6 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {...@@ -773,7 +773,6 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void {
773773
774const std = @import("std");774const std = @import("std");
775const Path = std.Build.Cache.Path;775const Path = std.Build.Cache.Path;
776const WaitGroup = std.Thread.WaitGroup;
777const assert = std.debug.assert;776const assert = std.debug.assert;
778const log = std.log.scoped(.link);777const log = std.log.scoped(.link);
779const macho = std.macho;778const macho = std.macho;
src/link/MachO/uuid.zig+1-2
...@@ -15,7 +15,7 @@ pub fn calcUuid(comp: *const Compilation, file: fs.File, file_size: u64, out: *[...@@ -15,7 +15,7 @@ pub fn calcUuid(comp: *const Compilation, file: fs.File, file_size: u64, out: *[
15 const hashes = try comp.gpa.alloc([Md5.digest_length]u8, actual_num_chunks);15 const hashes = try comp.gpa.alloc([Md5.digest_length]u8, actual_num_chunks);
16 defer comp.gpa.free(hashes);16 defer comp.gpa.free(hashes);
1717
18 var hasher = Hasher(Md5){ .allocator = comp.gpa, .thread_pool = comp.thread_pool };18 var hasher = Hasher(Md5){ .allocator = comp.gpa, .io = comp.io };
19 try hasher.hash(file, hashes, .{19 try hasher.hash(file, hashes, .{
20 .chunk_size = chunk_size,20 .chunk_size = chunk_size,
21 .max_file_size = file_size,21 .max_file_size = file_size,
...@@ -46,4 +46,3 @@ const trace = @import("../../tracy.zig").trace;...@@ -46,4 +46,3 @@ const trace = @import("../../tracy.zig").trace;
46const Compilation = @import("../../Compilation.zig");46const Compilation = @import("../../Compilation.zig");
47const Md5 = std.crypto.hash.Md5;47const Md5 = std.crypto.hash.Md5;
48const Hasher = @import("hasher.zig").ParallelHasher;48const Hasher = @import("hasher.zig").ParallelHasher;
49const ThreadPool = std.Thread.Pool;
src/link/Queue.zig+154-279
...@@ -1,254 +1,171 @@...@@ -1,254 +1,171 @@
1//! Stores and manages the queue of link tasks. Each task is either a `PrelinkTask` or a `ZcuTask`.1//! Stores and manages the queue of link tasks. Each task is either a `PrelinkTask` or a `ZcuTask`.
2//!2//!
3//! There must be at most one link thread (the thread processing these tasks) active at a time. If3//! There are two `std.Io.Queue`s, for prelink and ZCU tasks respectively. The compiler writes tasks
4//! `!comp.separateCodegenThreadOk()`, then ZCU tasks will be run on the main thread, bypassing this4//! to these queues, and a single concurrent linker task receives and processes them. `Compilation`
5//! queue entirely.5//! is responsible for calling `finishPrelinkQueue` and `finishZcuQueue` once all relevant tasks
6//! have been queued. All prelink tasks must be queued and completed before any ZCU tasks can be
7//! processed.
6//!8//!
7//! All prelink tasks must be processed before any ZCU tasks are processed. After all prelink tasks9//! If concurrency is unavailable, the `enqueuePrelink` and `enqueueZcu` functions will instead run
8//! are run, but before any ZCU tasks are run, `prelink` must be called on the `link.File`.10//! the given tasks immediately---the queues are unused.
9//!11//!
10//! There will sometimes be a `ZcuTask` in the queue which is not yet ready because it depends on12//! If the codegen backend does not permit concurrency, then `Compilation` will call `finishZcuQueue`
11//! MIR which has not yet been generated by any codegen thread. In this case, we must pause13//! early so that the concurrent linker task exists after prelink and ZCU tasks will run
12//! processing of linker tasks until the MIR is ready. It would be incorrect to run any other link14//! non-concurrently in `enqueueZcu`.
13//! tasks first, since this would make builds unreproducible.
1415
15mutex: std.Thread.Mutex,16/// This is the concurrent call to `runLinkTasks`. It may be set to non-`null` in `start`, and is
16/// Validates that only one `flushTaskQueue` thread is running at a time.17/// set to `null` by the main thread after it is canceled. It is not otherwise modified; as such, it
17flush_safety: std.debug.SafetyLock,18/// may be checked non-atomically. If a task is being queued and this is `null`, tasks must be run
19/// eagerly.
20future: ?std.Io.Future(void),
1821
19/// This value is positive while there are still prelink tasks yet to be queued. Once they are22/// This is only used if `future == null` during prelink. In that case, it is used to ensure that
20/// all queued, this value becomes 0, and ZCU tasks can be run. Guarded by `mutex`.23/// only one prelink task is run at a time.
21prelink_wait_count: u32,24prelink_mutex: std.Io.Mutex,
2225
23/// Prelink tasks which have been enqueued and are not yet owned by the worker thread.26/// Only valid if `future != null`.
24/// Allocated into `gpa`, guarded by `mutex`.27prelink_queue: std.Io.Queue(PrelinkTask),
25queued_prelink: std.ArrayList(PrelinkTask),28/// Only valid if `future != null`.
26/// The worker thread moves items from `queued_prelink` into this array in order to process them.29zcu_queue: std.Io.Queue(ZcuTask),
27/// Allocated into `gpa`, accessed only by the worker thread.
28wip_prelink: std.ArrayList(PrelinkTask),
2930
30/// Like `queued_prelink`, but for ZCU tasks.31/// The capacity of the task queue buffers.
31/// Allocated into `gpa`, guarded by `mutex`.32pub const buffer_size = 512;
32queued_zcu: std.ArrayList(ZcuTask),
33/// Like `wip_prelink`, but for ZCU tasks.
34/// Allocated into `gpa`, accessed only by the worker thread.
35wip_zcu: std.ArrayList(ZcuTask),
36
37/// When processing ZCU link tasks, we might have to block due to unpopulated MIR. When this
38/// happens, some tasks in `wip_zcu` have been run, and some are still pending. This is the
39/// index into `wip_zcu` which we have reached.
40wip_zcu_idx: usize,
41
42/// The sum of all `air_bytes` for all currently-queued `ZcuTask.link_func` tasks. Because
43/// MIR bytes are approximately proportional to AIR bytes, this acts to limit the amount of
44/// AIR and MIR which is queued for codegen and link respectively, to prevent excessive
45/// memory usage if analysis produces AIR faster than it can be processed by codegen/link.
46/// The cap is `max_air_bytes_in_flight`.
47/// Guarded by `mutex`.
48air_bytes_in_flight: u32,
49/// If nonzero, then a call to `enqueueZcu` is blocked waiting to add a `link_func` task, but
50/// cannot until `air_bytes_in_flight` is no greater than this value.
51/// Guarded by `mutex`.
52air_bytes_waiting: u32,
53/// After setting `air_bytes_waiting`, `enqueueZcu` will wait on this condition (with `mutex`).
54/// When `air_bytes_waiting` many bytes can be queued, this condition should be signaled.
55air_bytes_cond: std.Thread.Condition,
56
57/// Guarded by `mutex`.
58state: union(enum) {
59 /// The link thread is currently running or queued to run.
60 running,
61 /// The link thread is not running or queued, because it has exhausted all immediately available
62 /// tasks. It should be spawned when more tasks are enqueued. If `prelink_wait_count` is not
63 /// zero, we are specifically waiting for prelink tasks.
64 finished,
65 /// The link thread is not running or queued, because it is waiting for this MIR to be populated.
66 /// Once codegen completes, it must call `mirReady` which will restart the link thread.
67 wait_for_mir: InternPool.Index,
68},
69
70/// In the worst observed case, MIR is around 50 times as large as AIR. More typically, the ratio is
71/// around 20. Going by that 50x multiplier, and assuming we want to consume no more than 500 MiB of
72/// memory on AIR/MIR, we see a limit of around 10 MiB of AIR in-flight.
73const max_air_bytes_in_flight = 10 * 1024 * 1024;
7433
75/// The initial `Queue` state, containing no tasks, expecting no prelink tasks, and with no running worker thread.34/// The initial `Queue` state, containing no tasks, expecting no prelink tasks, and with no running worker thread.
76/// The `queued_prelink` field may be appended to before calling `start`.35/// The `queued_prelink` field may be appended to before calling `start`.
77pub const empty: Queue = .{36pub const empty: Queue = .{
78 .mutex = .{},37 .future = null,
79 .flush_safety = .{},38 .prelink_mutex = .init,
80 .prelink_wait_count = undefined, // set in `start`39 .prelink_queue = undefined, // set in `start` if needed
81 .queued_prelink = .empty,40 .zcu_queue = undefined, // set in `start` if needed
82 .wip_prelink = .empty,
83 .queued_zcu = .empty,
84 .wip_zcu = .empty,
85 .wip_zcu_idx = 0,
86 .state = .finished,
87 .air_bytes_in_flight = 0,
88 .air_bytes_waiting = 0,
89 .air_bytes_cond = .{},
90};41};
91/// `lf` is needed to correctly deinit any pending `ZcuTask`s.42
92pub fn deinit(q: *Queue, comp: *Compilation) void {43pub fn cancel(q: *Queue, io: Io) void {
93 const gpa = comp.gpa;44 if (q.future) |*f| {
94 for (q.queued_zcu.items) |t| t.deinit(comp.zcu.?);45 f.cancel(io);
95 for (q.wip_zcu.items[q.wip_zcu_idx..]) |t| t.deinit(comp.zcu.?);46 q.future = null;
96 q.queued_prelink.deinit(gpa);47 }
97 q.wip_prelink.deinit(gpa);48}
98 q.queued_zcu.deinit(gpa);49
99 q.wip_zcu.deinit(gpa);50pub fn wait(q: *Queue, io: Io) void {
51 if (q.future) |*f| {
52 f.await(io);
53 q.future = null;
54 }
100}55}
10156
102/// This is expected to be called exactly once, after which the caller must not directly access57/// This is expected to be called exactly once, after which the caller must not directly access
103/// `queued_prelink` any longer. This will spawn the link thread if necessary.58/// `queued_prelink` any longer. This will spawn the link thread if necessary.
104pub fn start(q: *Queue, comp: *Compilation) void {59pub fn start(
105 assert(q.state == .finished);60 q: *Queue,
106 assert(q.queued_zcu.items.len == 0);61 comp: *Compilation,
107 // Reset this to 1. We can't init it to 1 in `empty`, because it would fall to 0 on successive62 arena: Allocator,
108 // incremental updates, but we still need the initial 1.63) Allocator.Error!void {
109 q.prelink_wait_count = 1;64 assert(q.future == null);
110 if (q.queued_prelink.items.len != 0) {65 q.prelink_queue = .init(try arena.alloc(PrelinkTask, buffer_size));
111 q.state = .running;66 q.zcu_queue = .init(try arena.alloc(ZcuTask, buffer_size));
112 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });67 if (comp.io.concurrent(runLinkTasks, .{ q, comp })) |future| {
68 // We will run link tasks concurrently.
69 q.future = future;
70 } else |err| switch (err) {
71 error.ConcurrencyUnavailable => {
72 // We will run link tasks on the main thread.
73 q.prelink_queue = undefined;
74 q.zcu_queue = undefined;
75 },
113 }76 }
114}77}
11578
116/// Every call to this must be paired with a call to `finishPrelinkItem`.79/// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that
117pub fn startPrelinkItem(q: *Queue) void {80/// the queue is not yet closed. Also asserts that `tasks.len` is not 0.
118 q.mutex.lock();81pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Io.Cancelable!void {
119 defer q.mutex.unlock();82 const io = comp.io;
120 assert(q.prelink_wait_count > 0); // must not have finished everything already83
121 q.prelink_wait_count += 1;84 if (q.future != null) {
122}85 q.prelink_queue.putAll(io, tasks) catch |err| switch (err) {
123/// This function must be called exactly one more time than `startPrelinkItem` is. The final call86 error.Canceled => |e| return e,
124/// indicates that we have finished calling `startPrelinkItem`, so once all pending items finish,87 error.Closed => unreachable,
125/// we are ready to move on to ZCU tasks.88 };
126pub fn finishPrelinkItem(q: *Queue, comp: *Compilation) void {89 } else {
127 {90 try q.prelink_mutex.lock(io);
128 q.mutex.lock();91 defer q.prelink_mutex.unlock(io);
129 defer q.mutex.unlock();92 for (tasks) |task| link.doPrelinkTask(comp, task);
130 q.prelink_wait_count -= 1;
131 if (q.prelink_wait_count != 0) return;
132 // The prelink task count dropped to 0; restart the linker thread if necessary.
133 switch (q.state) {
134 .wait_for_mir => unreachable, // we've not started zcu tasks yet
135 .running => return,
136 .finished => {},
137 }
138 assert(q.queued_prelink.items.len == 0);
139 // Even if there are no ZCU tasks, we must restart the linker thread to make sure
140 // that `link.File.prelink()` is called.
141 q.state = .running;
142 }93 }
143 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
144}94}
14595
146/// Called by codegen workers after they have populated a `ZcuTask.LinkFunc.SharedMir`. If the link96pub fn enqueueZcu(
147/// thread was waiting for this MIR, it can resume.97 q: *Queue,
148pub fn mirReady(q: *Queue, comp: *Compilation, func_index: InternPool.Index, mir: *ZcuTask.LinkFunc.SharedMir) void {98 comp: *Compilation,
149 // We would like to assert that `mir` is not pending, but that would race with a worker thread99 tid: usize,
150 // potentially freeing it.100 task: ZcuTask,
151 {101) Io.Cancelable!void {
152 q.mutex.lock();102 const io = comp.io;
153 defer q.mutex.unlock();103
154 switch (q.state) {104 assert(tid == 0);
155 .finished, .running => return,105
156 .wait_for_mir => |wait_for| if (wait_for != func_index) return,106 if (q.future != null) {
107 if (q.zcu_queue.putOne(io, task)) |_| {
108 return;
109 } else |err| switch (err) {
110 error.Canceled => |e| return e,
111 error.Closed => {
112 // The linker is still processing prelink tasks. Wait for those
113 // to finish, after which the linker task will exist, and ZCU
114 // tasks will be run non-concurrently. This logic exists for
115 // backends which do not support `Zcu.Feature.separate_thread`.
116 q.wait(io);
117 },
157 }118 }
158 // We were waiting for `mir`, so we will restart the linker thread.
159 q.state = .running;
160 }119 }
161 assert(mir.status.load(.acquire) != .pending);120
162 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });121 link.doZcuTask(comp, tid, task);
163}122}
164123
165/// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that124pub fn finishPrelinkQueue(q: *Queue, comp: *Compilation) void {
166/// `prelink_wait_count` is not yet 0. Also asserts that `tasks.len` is not 0.125 if (q.future != null) {
167pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Allocator.Error!void {126 q.prelink_queue.close(comp.io);
168 {127 return;
169 q.mutex.lock();128 }
170 defer q.mutex.unlock();129 // If linking non-concurrently, we must run prelink.
171 assert(q.prelink_wait_count > 0);130 prelink: {
172 try q.queued_prelink.appendSlice(comp.gpa, tasks);131 const lf = comp.bin_file orelse break :prelink;
173 switch (q.state) {132 if (lf.post_prelink) break :prelink;
174 .wait_for_mir => unreachable, // we've not started zcu tasks yet133
175 .running => return,134 if (lf.prelink()) |_| {
176 .finished => {},135 lf.post_prelink = true;
136 } else |err| switch (err) {
137 error.OutOfMemory => comp.link_diags.setAllocFailure(),
138 error.LinkFailure => {},
177 }139 }
178 // Restart the linker thread, because it was waiting for a task
179 q.state = .running;
180 }140 }
181 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
182}141}
183142
184pub fn enqueueZcu(q: *Queue, comp: *Compilation, task: ZcuTask) Allocator.Error!void {143pub fn finishZcuQueue(q: *Queue, comp: *Compilation) void {
185 assert(comp.separateCodegenThreadOk());144 if (q.future != null) {
186 {145 q.zcu_queue.close(comp.io);
187 q.mutex.lock();
188 defer q.mutex.unlock();
189 // If this is a `link_func` task, we might need to wait for `air_bytes_in_flight` to fall.
190 if (task == .link_func) {
191 const max_in_flight = max_air_bytes_in_flight -| task.link_func.air_bytes;
192 while (q.air_bytes_in_flight > max_in_flight) {
193 q.air_bytes_waiting = task.link_func.air_bytes;
194 q.air_bytes_cond.wait(&q.mutex);
195 q.air_bytes_waiting = 0;
196 }
197 q.air_bytes_in_flight += task.link_func.air_bytes;
198 }
199 try q.queued_zcu.append(comp.gpa, task);
200 switch (q.state) {
201 .running, .wait_for_mir => return,
202 .finished => if (q.prelink_wait_count > 0) return,
203 }
204 // Restart the linker thread, unless it would immediately be blocked
205 if (task == .link_func and task.link_func.mir.status.load(.acquire) == .pending) {
206 q.state = .{ .wait_for_mir = task.link_func.func };
207 return;
208 }
209 q.state = .running;
210 }146 }
211 comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp });
212}147}
213148
214fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void {149fn runLinkTasks(q: *Queue, comp: *Compilation) void {
215 q.flush_safety.lock(); // every `return` site should unlock this before unlocking `q.mutex`150 const tid = Compilation.getTid();
216 if (std.debug.runtime_safety) {151 const io = comp.io;
217 q.mutex.lock();
218 defer q.mutex.unlock();
219 assert(q.state == .running);
220 }
221152
222 var have_idle_tasks = true;153 var have_idle_tasks = true;
223 prelink: while (true) {154
224 assert(q.wip_prelink.items.len == 0);155 prelink_tasks: while (true) {
225 swap_queues: while (true) {156 var task_buf: [128]PrelinkTask = undefined;
226 {157 const limit: usize = if (have_idle_tasks) 0 else 1;
227 q.mutex.lock();158 const n = q.prelink_queue.get(io, &task_buf, limit) catch |err| switch (err) {
228 defer q.mutex.unlock();159 error.Canceled => return,
229 std.mem.swap(std.ArrayList(PrelinkTask), &q.queued_prelink, &q.wip_prelink);160 error.Closed => break :prelink_tasks,
230 if (q.wip_prelink.items.len > 0) break :swap_queues;161 };
231 if (q.prelink_wait_count == 0) break :prelink; // prelink is done162 if (n == 0) {
232 if (!have_idle_tasks) {163 assert(have_idle_tasks);
233 // We're expecting more prelink tasks so can't move on to ZCU tasks.164 have_idle_tasks = runIdleTask(comp, tid);
234 q.state = .finished;165 } else for (task_buf[0..n]) |task| {
235 q.flush_safety.unlock();
236 return;
237 }
238 }
239 have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) {
240 error.OutOfMemory => have_idle_tasks: {
241 comp.link_diags.setAllocFailure();
242 break :have_idle_tasks false;
243 },
244 error.LinkFailure => false,
245 };
246 }
247 for (q.wip_prelink.items) |task| {
248 link.doPrelinkTask(comp, task);166 link.doPrelinkTask(comp, task);
167 have_idle_tasks = true;
249 }168 }
250 have_idle_tasks = true;
251 q.wip_prelink.clearRetainingCapacity();
252 }169 }
253170
254 // We've finished the prelink tasks, so run prelink if necessary.171 // We've finished the prelink tasks, so run prelink if necessary.
...@@ -263,79 +180,37 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void {...@@ -263,79 +180,37 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void {
263 }180 }
264 }181 }
265182
266 // Now we can run ZCU tasks.183 zcu_tasks: while (true) {
267 while (true) {184 var task_buf: [128]ZcuTask = undefined;
268 if (q.wip_zcu.items.len == q.wip_zcu_idx) swap_queues: {185 const limit: usize = if (have_idle_tasks) 0 else 1;
269 q.wip_zcu.clearRetainingCapacity();186 const n = q.zcu_queue.get(io, &task_buf, limit) catch |err| switch (err) {
270 q.wip_zcu_idx = 0;187 error.Canceled => return,
271 while (true) {188 error.Closed => break :zcu_tasks,
272 {189 };
273 q.mutex.lock();190 if (n == 0) {
274 defer q.mutex.unlock();191 assert(have_idle_tasks);
275 std.mem.swap(std.ArrayList(ZcuTask), &q.queued_zcu, &q.wip_zcu);192 have_idle_tasks = runIdleTask(comp, tid);
276 if (q.wip_zcu.items.len > 0) break :swap_queues;193 } else for (task_buf[0..n]) |task| {
277 if (!have_idle_tasks) {194 link.doZcuTask(comp, tid, task);
278 // We've exhausted all available tasks.195 have_idle_tasks = true;
279 q.state = .finished;
280 q.flush_safety.unlock();
281 return;
282 }
283 }
284 have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) {
285 error.OutOfMemory => have_idle_tasks: {
286 comp.link_diags.setAllocFailure();
287 break :have_idle_tasks false;
288 },
289 error.LinkFailure => false,
290 };
291 }
292 }
293 const task = q.wip_zcu.items[q.wip_zcu_idx];
294 // If the task is a `link_func`, we might have to stop until its MIR is populated.
295 pending: {
296 if (task != .link_func) break :pending;
297 const status_ptr = &task.link_func.mir.status;
298 while (true) {
299 // First check without the mutex to optimize for the common case where MIR is ready.
300 if (status_ptr.load(.acquire) != .pending) break :pending;
301 if (have_idle_tasks) have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) {
302 error.OutOfMemory => have_idle_tasks: {
303 comp.link_diags.setAllocFailure();
304 break :have_idle_tasks false;
305 },
306 error.LinkFailure => false,
307 };
308 if (!have_idle_tasks) break;
309 }
310 q.mutex.lock();
311 defer q.mutex.unlock();
312 if (status_ptr.load(.acquire) != .pending) break :pending;
313 // We will stop for now, and get restarted once this MIR is ready.
314 q.state = .{ .wait_for_mir = task.link_func.func };
315 q.flush_safety.unlock();
316 return;
317 }196 }
318 link.doZcuTask(comp, tid, task);
319 task.deinit(comp.zcu.?);
320 if (task == .link_func) {
321 // Decrease `air_bytes_in_flight`, since we've finished processing this MIR.
322 q.mutex.lock();
323 defer q.mutex.unlock();
324 q.air_bytes_in_flight -= task.link_func.air_bytes;
325 if (q.air_bytes_waiting != 0 and
326 q.air_bytes_in_flight <= max_air_bytes_in_flight -| q.air_bytes_waiting)
327 {
328 q.air_bytes_cond.signal();
329 }
330 }
331 q.wip_zcu_idx += 1;
332 have_idle_tasks = true;
333 }197 }
334}198}
199fn runIdleTask(comp: *Compilation, tid: usize) bool {
200 return link.doIdleTask(comp, tid) catch |err| switch (err) {
201 error.OutOfMemory => have_more: {
202 comp.link_diags.setAllocFailure();
203 break :have_more false;
204 },
205 error.LinkFailure => false,
206 };
207}
335208
336const std = @import("std");209const std = @import("std");
337const assert = std.debug.assert;210const assert = std.debug.assert;
338const Allocator = std.mem.Allocator;211const Allocator = std.mem.Allocator;
212const Io = std.Io;
213
339const Compilation = @import("../Compilation.zig");214const Compilation = @import("../Compilation.zig");
340const InternPool = @import("../InternPool.zig");215const InternPool = @import("../InternPool.zig");
341const link = @import("../link.zig");216const link = @import("../link.zig");
src/link/Wasm.zig+3-2
...@@ -3393,10 +3393,11 @@ pub fn updateExports(...@@ -3393,10 +3393,11 @@ pub fn updateExports(
3393pub fn loadInput(wasm: *Wasm, input: link.Input) !void {3393pub fn loadInput(wasm: *Wasm, input: link.Input) !void {
3394 const comp = wasm.base.comp;3394 const comp = wasm.base.comp;
3395 const gpa = comp.gpa;3395 const gpa = comp.gpa;
3396 const io = comp.io;
33963397
3397 if (comp.verbose_link) {3398 if (comp.verbose_link) {
3398 comp.mutex.lock(); // protect comp.arena3399 comp.mutex.lockUncancelable(io); // protect comp.arena
3399 defer comp.mutex.unlock();3400 defer comp.mutex.unlock(io);
34003401
3401 const argv = &wasm.dump_argv_list;3402 const argv = &wasm.dump_argv_list;
3402 switch (input) {3403 switch (input) {
src/main.zig+36-34
...@@ -11,7 +11,6 @@ const Allocator = mem.Allocator;...@@ -11,7 +11,6 @@ const Allocator = mem.Allocator;
11const Ast = std.zig.Ast;11const Ast = std.zig.Ast;
12const Color = std.zig.Color;12const Color = std.zig.Color;
13const warn = std.log.warn;13const warn = std.log.warn;
14const ThreadPool = std.Thread.Pool;
15const cleanExit = std.process.cleanExit;14const cleanExit = std.process.cleanExit;
16const Cache = std.Build.Cache;15const Cache = std.Build.Cache;
17const Path = std.Build.Cache.Path;16const Path = std.Build.Cache.Path;
...@@ -200,6 +199,8 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -200,6 +199,8 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
200 const tr = tracy.trace(@src());199 const tr = tracy.trace(@src());
201 defer tr.end();200 defer tr.end();
202201
202 Compilation.setMainThread();
203
203 if (args.len <= 1) {204 if (args.len <= 1) {
204 std.log.info("{s}", .{usage});205 std.log.info("{s}", .{usage});
205 fatal("expected command argument", .{});206 fatal("expected command argument", .{});
...@@ -239,6 +240,8 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -239,6 +240,8 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
239240
240 var threaded: Io.Threaded = .init(gpa);241 var threaded: Io.Threaded = .init(gpa);
241 defer threaded.deinit();242 defer threaded.deinit();
243 threaded_impl_ptr = &threaded;
244 threaded.stack_size = thread_stack_size;
242 const io = threaded.io();245 const io = threaded.io();
243246
244 const cmd = args[1];247 const cmd = args[1];
...@@ -3361,14 +3364,11 @@ fn buildOutputType(...@@ -3361,14 +3364,11 @@ fn buildOutputType(
3361 },3364 },
3362 };3365 };
33633366
3364 var thread_pool: ThreadPool = undefined;3367 const thread_limit = @min(
3365 try thread_pool.init(.{3368 @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1),
3366 .allocator = gpa,3369 std.math.maxInt(Zcu.PerThread.IdBacking),
3367 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),3370 );
3368 .track_ids = true,3371 setThreadLimit(thread_limit);
3369 .stack_size = thread_stack_size,
3370 });
3371 defer thread_pool.deinit();
33723372
3373 for (create_module.c_source_files.items) |*src| {3373 for (create_module.c_source_files.items) |*src| {
3374 dev.check(.c_compiler);3374 dev.check(.c_compiler);
...@@ -3461,7 +3461,7 @@ fn buildOutputType(...@@ -3461,7 +3461,7 @@ fn buildOutputType(
3461 var create_diag: Compilation.CreateDiagnostic = undefined;3461 var create_diag: Compilation.CreateDiagnostic = undefined;
3462 const comp = Compilation.create(gpa, arena, io, &create_diag, .{3462 const comp = Compilation.create(gpa, arena, io, &create_diag, .{
3463 .dirs = dirs,3463 .dirs = dirs,
3464 .thread_pool = &thread_pool,3464 .thread_limit = thread_limit,
3465 .self_exe_path = switch (native_os) {3465 .self_exe_path = switch (native_os) {
3466 .wasi => null,3466 .wasi => null,
3467 else => self_exe_path,3467 else => self_exe_path,
...@@ -4150,6 +4150,7 @@ fn serve(...@@ -4150,6 +4150,7 @@ fn serve(
4150 runtime_args_start: ?usize,4150 runtime_args_start: ?usize,
4151) !void {4151) !void {
4152 const gpa = comp.gpa;4152 const gpa = comp.gpa;
4153 const io = comp.io;
41534154
4154 var server = try Server.init(.{4155 var server = try Server.init(.{
4155 .in = in,4156 .in = in,
...@@ -4178,8 +4179,8 @@ fn serve(...@@ -4178,8 +4179,8 @@ fn serve(
4178 const hdr = try server.receiveMessage();4179 const hdr = try server.receiveMessage();
41794180
4180 // Lock the debug server while handling the message.4181 // Lock the debug server while handling the message.
4181 if (comp.debugIncremental()) ids.mutex.lock();4182 if (comp.debugIncremental()) try ids.mutex.lock(io);
4182 defer if (comp.debugIncremental()) ids.mutex.unlock();4183 defer if (comp.debugIncremental()) ids.mutex.unlock(io);
41834184
4184 switch (hdr.tag) {4185 switch (hdr.tag) {
4185 .exit => return cleanExit(),4186 .exit => return cleanExit(),
...@@ -5140,14 +5141,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)...@@ -5140,14 +5141,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
5140 child_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path;5141 child_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path;
5141 child_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path;5142 child_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path;
51425143
5143 var thread_pool: ThreadPool = undefined;5144 const thread_limit = @min(
5144 try thread_pool.init(.{5145 @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1),
5145 .allocator = gpa,5146 std.math.maxInt(Zcu.PerThread.IdBacking),
5146 .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),5147 );
5147 .track_ids = true,5148 setThreadLimit(thread_limit);
5148 .stack_size = thread_stack_size,
5149 });
5150 defer thread_pool.deinit();
51515149
5152 // Dummy http client that is not actually used when fetch_command is unsupported.5150 // Dummy http client that is not actually used when fetch_command is unsupported.
5153 // Prevents bootstrap from depending on a bunch of unnecessary stuff.5151 // Prevents bootstrap from depending on a bunch of unnecessary stuff.
...@@ -5376,7 +5374,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)...@@ -5376,7 +5374,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
5376 .main_mod = build_mod,5374 .main_mod = build_mod,
5377 .emit_bin = .yes_cache,5375 .emit_bin = .yes_cache,
5378 .self_exe_path = self_exe_path,5376 .self_exe_path = self_exe_path,
5379 .thread_pool = &thread_pool,5377 .thread_limit = thread_limit,
5380 .verbose_cc = verbose_cc,5378 .verbose_cc = verbose_cc,
5381 .verbose_link = verbose_link,5379 .verbose_link = verbose_link,
5382 .verbose_air = verbose_air,5380 .verbose_air = verbose_air,
...@@ -5548,14 +5546,11 @@ fn jitCmd(...@@ -5548,14 +5546,11 @@ fn jitCmd(
5548 );5546 );
5549 defer dirs.deinit();5547 defer dirs.deinit();
55505548
5551 var thread_pool: ThreadPool = undefined;5549 const thread_limit = @min(
5552 try thread_pool.init(.{5550 @max(std.Thread.getCpuCount() catch 1, 1),
5553 .allocator = gpa,5551 std.math.maxInt(Zcu.PerThread.IdBacking),
5554 .n_jobs = @min(@max(std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)),5552 );
5555 .track_ids = true,5553 setThreadLimit(thread_limit);
5556 .stack_size = thread_stack_size,
5557 });
5558 defer thread_pool.deinit();
55595554
5560 var child_argv: std.ArrayList([]const u8) = .empty;5555 var child_argv: std.ArrayList([]const u8) = .empty;
5561 try child_argv.ensureUnusedCapacity(arena, args.len + 4);5556 try child_argv.ensureUnusedCapacity(arena, args.len + 4);
...@@ -5619,7 +5614,7 @@ fn jitCmd(...@@ -5619,7 +5614,7 @@ fn jitCmd(
5619 .main_mod = root_mod,5614 .main_mod = root_mod,
5620 .emit_bin = .yes_cache,5615 .emit_bin = .yes_cache,
5621 .self_exe_path = self_exe_path,5616 .self_exe_path = self_exe_path,
5622 .thread_pool = &thread_pool,5617 .thread_limit = thread_limit,
5623 .cache_mode = .whole,5618 .cache_mode = .whole,
5624 }) catch |err| switch (err) {5619 }) catch |err| switch (err) {
5625 error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}),5620 error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}),
...@@ -6946,10 +6941,6 @@ fn cmdFetch(...@@ -6946,10 +6941,6 @@ fn cmdFetch(
69466941
6947 const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{});6942 const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{});
69486943
6949 var thread_pool: ThreadPool = undefined;
6950 try thread_pool.init(.{ .allocator = gpa });
6951 defer thread_pool.deinit();
6952
6953 var http_client: std.http.Client = .{ .allocator = gpa, .io = io };6944 var http_client: std.http.Client = .{ .allocator = gpa, .io = io };
6954 defer http_client.deinit();6945 defer http_client.deinit();
69556946
...@@ -7601,3 +7592,14 @@ fn addLibDirectoryWarn2(...@@ -7601,3 +7592,14 @@ fn addLibDirectoryWarn2(
7601 .path = path,7592 .path = path,
7602 });7593 });
7603}7594}
7595
7596var threaded_impl_ptr: *Io.Threaded = undefined;
7597fn setThreadLimit(n: usize) void {
7598 // We want a maximum of n total threads to keep the InternPool happy, but
7599 // the main thread doesn't count towards the limits, so use n-1. Also, the
7600 // linker can run concurrently, so we need to set both the async *and* the
7601 // concurrency limit.
7602 const limit: Io.Limit = .limited(n - 1);
7603 threaded_impl_ptr.setAsyncLimit(limit);
7604 threaded_impl_ptr.concurrent_limit = limit;
7605}
src/mutable_value.zig+4-1
...@@ -55,6 +55,9 @@ pub const MutableValue = union(enum) {...@@ -55,6 +55,9 @@ pub const MutableValue = union(enum) {
55 };55 };
5656
57 pub fn intern(mv: MutableValue, pt: Zcu.PerThread, arena: Allocator) Allocator.Error!Value {57 pub fn intern(mv: MutableValue, pt: Zcu.PerThread, arena: Allocator) Allocator.Error!Value {
58 const zcu = pt.zcu;
59 const comp = zcu.comp;
60 const io = comp.io;
58 return Value.fromInterned(switch (mv) {61 return Value.fromInterned(switch (mv) {
59 .interned => |ip_index| ip_index,62 .interned => |ip_index| ip_index,
60 .eu_payload => |sv| try pt.intern(.{ .error_union = .{63 .eu_payload => |sv| try pt.intern(.{ .error_union = .{
...@@ -68,7 +71,7 @@ pub const MutableValue = union(enum) {...@@ -68,7 +71,7 @@ pub const MutableValue = union(enum) {
68 .repeated => |sv| return pt.aggregateSplatValue(.fromInterned(sv.ty), try sv.child.intern(pt, arena)),71 .repeated => |sv| return pt.aggregateSplatValue(.fromInterned(sv.ty), try sv.child.intern(pt, arena)),
69 .bytes => |b| try pt.intern(.{ .aggregate = .{72 .bytes => |b| try pt.intern(.{ .aggregate = .{
70 .ty = b.ty,73 .ty = b.ty,
71 .storage = .{ .bytes = try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, pt.tid, b.data, .maybe_embedded_nulls) },74 .storage = .{ .bytes = try zcu.intern_pool.getOrPutString(comp.gpa, io, pt.tid, b.data, .maybe_embedded_nulls) },
72 } }),75 } }),
73 .aggregate => |a| {76 .aggregate => |a| {
74 const elems = try arena.alloc(InternPool.Index, a.elems.len);77 const elems = try arena.alloc(InternPool.Index, a.elems.len);