| author | |
| committer | |
| log | 985a3565c6130c7279319e9c36642f0b958e6944 |
| tree | 30f4a6bed794330daefb4d3d7ef6f900e21d24b9 |
| parent | 3af842f0e89125e65a87e5752234bf7e0051aa12 |
| parent | 23e5a17187dc3a1f61dcb40b681f6730334d3667 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30557
Reviewed-by: Andrew Kelley <andrewrk@noreply.codeberg.org>41 files changed, 2318 insertions(+), 2096 deletions(-)
CMakeLists.txt-1| ... | ... | @@ -411,7 +411,6 @@ set(ZIG_STAGE2_SOURCES |
| 411 | 411 | lib/std/Thread.zig |
| 412 | 412 | lib/std/Thread/Futex.zig |
| 413 | 413 | lib/std/Thread/Mutex.zig |
| 414 | lib/std/Thread/Pool.zig | |
| 415 | 414 | lib/std/Thread/WaitGroup.zig |
| 416 | 415 | lib/std/array_hash_map.zig |
| 417 | 416 | lib/std/array_list.zig |
lib/std/Io.zig+19-6| ... | ... | @@ -1016,9 +1016,14 @@ pub fn Future(Result: type) type { |
| 1016 | 1016 | pub const Group = struct { |
| 1017 | 1017 | state: usize, |
| 1018 | 1018 | context: ?*anyopaque, |
| 1019 | token: ?*anyopaque, | |
| 1019 | /// This value indicates whether or not a group has pending tasks. `null` | |
| 1020 | /// means there are no pending tasks, and no resources associated with the | |
| 1021 | /// group, so `await` and `cancel` return immediately without calling the | |
| 1022 | /// implementation. This means that `token` must be accessed atomically to | |
| 1023 | /// avoid racing with the check in `await` and `cancel`. | |
| 1024 | token: std.atomic.Value(?*anyopaque), | |
| 1020 | 1025 | |
| 1021 | pub const init: Group = .{ .state = 0, .context = null, .token = null }; | |
| 1026 | pub const init: Group = .{ .state = 0, .context = null, .token = .init(null) }; | |
| 1022 | 1027 | |
| 1023 | 1028 | /// Calls `function` with `args` asynchronously. The resource spawned is |
| 1024 | 1029 | /// owned by the group. |
| ... | ... | @@ -1081,10 +1086,14 @@ pub const Group = struct { |
| 1081 | 1086 | /// cancellation requests propagate to all members of the group. |
| 1082 | 1087 | /// |
| 1083 | 1088 | /// Idempotent. Not threadsafe. |
| 1089 | /// | |
| 1090 | /// It is safe to call this function concurrently with `Group.async` or | |
| 1091 | /// `Group.concurrent`, provided that the group does not complete until | |
| 1092 | /// the call to `Group.async` or `Group.concurrent` returns. | |
| 1084 | 1093 | pub fn wait(g: *Group, io: Io) void { |
| 1085 | const token = g.token orelse return; | |
| 1086 | g.token = null; | |
| 1094 | const token = g.token.load(.acquire) orelse return; | |
| 1087 | 1095 | io.vtable.groupWait(io.userdata, g, token); |
| 1096 | assert(g.token.raw == null); | |
| 1088 | 1097 | } |
| 1089 | 1098 | |
| 1090 | 1099 | /// Equivalent to `wait` but immediately requests cancellation on all |
| ... | ... | @@ -1093,10 +1102,14 @@ pub const Group = struct { |
| 1093 | 1102 | /// For a description of cancelation and cancelation points, see `Future.cancel`. |
| 1094 | 1103 | /// |
| 1095 | 1104 | /// Idempotent. Not threadsafe. |
| 1105 | /// | |
| 1106 | /// It is safe to call this function concurrently with `Group.async` or | |
| 1107 | /// `Group.concurrent`, provided that the group does not complete until | |
| 1108 | /// the call to `Group.async` or `Group.concurrent` returns. | |
| 1096 | 1109 | pub fn cancel(g: *Group, io: Io) void { |
| 1097 | const token = g.token orelse return; | |
| 1098 | g.token = null; | |
| 1110 | const token = g.token.load(.acquire) orelse return; | |
| 1099 | 1111 | io.vtable.groupCancel(io.userdata, g, token); |
| 1112 | assert(g.token.raw == null); | |
| 1100 | 1113 | } |
| 1101 | 1114 | }; |
| 1102 | 1115 |
lib/std/Io/Dir.zig+1-1| ... | ... | @@ -322,7 +322,7 @@ pub fn makePathStatus(dir: Dir, io: Io, sub_path: []const u8) MakePathError!Make |
| 322 | 322 | var status: MakePathStatus = .existed; |
| 323 | 323 | var component = it.last() orelse return error.BadPathName; |
| 324 | 324 | while (true) { |
| 325 | if (makeDir(dir, io, component.path)) |_| { | |
| 325 | if (makeDir(dir, io, component.path)) { | |
| 326 | 326 | status = .created; |
| 327 | 327 | } else |err| switch (err) { |
| 328 | 328 | error.PathAlreadyExists => { |
lib/std/Io/File.zig+1-1| ... | ... | @@ -419,7 +419,7 @@ pub const Reader = struct { |
| 419 | 419 | }, |
| 420 | 420 | .streaming, .streaming_reading => { |
| 421 | 421 | const seek_err = r.seek_err orelse e: { |
| 422 | if (io.vtable.fileSeekBy(io.userdata, r.file, offset)) |_| { | |
| 422 | if (io.vtable.fileSeekBy(io.userdata, r.file, offset)) { | |
| 423 | 423 | setLogicalPos(r, @intCast(@as(i64, @intCast(logicalPos(r))) + offset)); |
| 424 | 424 | return; |
| 425 | 425 | } else |err| { |
lib/std/Io/Threaded.zig+32-26| ... | ... | @@ -1117,8 +1117,8 @@ fn groupAsync( |
| 1117 | 1117 | } |
| 1118 | 1118 | |
| 1119 | 1119 | // Append to the group linked list inside the mutex to make `Io.Group.async` thread-safe. |
| 1120 | gc.node = .{ .next = @ptrCast(@alignCast(group.token)) }; | |
| 1121 | group.token = &gc.node; | |
| 1120 | gc.node = .{ .next = @ptrCast(@alignCast(group.token.load(.monotonic))) }; | |
| 1121 | group.token.store(&gc.node, .monotonic); | |
| 1122 | 1122 | |
| 1123 | 1123 | t.run_queue.prepend(&gc.closure.node); |
| 1124 | 1124 | |
| ... | ... | @@ -1169,8 +1169,8 @@ fn groupConcurrent( |
| 1169 | 1169 | } |
| 1170 | 1170 | |
| 1171 | 1171 | // Append to the group linked list inside the mutex to make `Io.Group.concurrent` thread-safe. |
| 1172 | gc.node = .{ .next = @ptrCast(@alignCast(group.token)) }; | |
| 1173 | group.token = &gc.node; | |
| 1172 | gc.node = .{ .next = @ptrCast(@alignCast(group.token.load(.monotonic))) }; | |
| 1173 | group.token.store(&gc.node, .monotonic); | |
| 1174 | 1174 | |
| 1175 | 1175 | t.run_queue.prepend(&gc.closure.node); |
| 1176 | 1176 | |
| ... | ... | @@ -1183,11 +1183,13 @@ fn groupConcurrent( |
| 1183 | 1183 | t.cond.signal(); |
| 1184 | 1184 | } |
| 1185 | 1185 | |
| 1186 | fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { | |
| 1186 | fn groupWait(userdata: ?*anyopaque, group: *Io.Group, initial_token: *anyopaque) void { | |
| 1187 | 1187 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1188 | 1188 | const gpa = t.allocator; |
| 1189 | 1189 | |
| 1190 | if (builtin.single_threaded) return; | |
| 1190 | _ = initial_token; // we need to load `token` *after* the group finishes | |
| 1191 | ||
| 1192 | if (builtin.single_threaded) unreachable; // we never set `group.token` to non-`null` | |
| 1191 | 1193 | |
| 1192 | 1194 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); |
| 1193 | 1195 | const event: *Io.Event = @ptrCast(&group.context); |
| ... | ... | @@ -1195,37 +1197,40 @@ fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { |
| 1195 | 1197 | assert(prev_state & GroupClosure.sync_is_waiting == 0); |
| 1196 | 1198 | if ((prev_state / GroupClosure.sync_one_pending) > 0) event.wait(ioBasic(t)) catch |err| switch (err) { |
| 1197 | 1199 | error.Canceled => { |
| 1198 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); | |
| 1199 | while (true) { | |
| 1200 | var it: ?*std.SinglyLinkedList.Node = @ptrCast(@alignCast(group.token.load(.monotonic))); | |
| 1201 | while (it) |node| : (it = node.next) { | |
| 1200 | 1202 | const gc: *GroupClosure = @fieldParentPtr("node", node); |
| 1201 | 1203 | gc.closure.requestCancel(t); |
| 1202 | node = node.next orelse break; | |
| 1203 | 1204 | } |
| 1204 | 1205 | event.waitUncancelable(ioBasic(t)); |
| 1205 | 1206 | }, |
| 1206 | 1207 | }; |
| 1207 | 1208 | |
| 1208 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); | |
| 1209 | while (true) { | |
| 1209 | // Since the group has now finished, it's illegal to add more tasks to it until we return. It's | |
| 1210 | // also illegal for us to race with another `await` or `cancel`. Therefore, we must be the only | |
| 1211 | // thread who can access `group` right now. | |
| 1212 | var it: ?*std.SinglyLinkedList.Node = @ptrCast(@alignCast(group.token.raw)); | |
| 1213 | group.token.raw = null; | |
| 1214 | while (it) |node| { | |
| 1215 | it = node.next; // update `it` now, because `deinit` will invalidate `node` | |
| 1210 | 1216 | const gc: *GroupClosure = @fieldParentPtr("node", node); |
| 1211 | const node_next = node.next; | |
| 1212 | 1217 | gc.deinit(gpa); |
| 1213 | node = node_next orelse break; | |
| 1214 | 1218 | } |
| 1215 | 1219 | } |
| 1216 | 1220 | |
| 1217 | fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { | |
| 1221 | fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, initial_token: *anyopaque) void { | |
| 1218 | 1222 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1219 | 1223 | const gpa = t.allocator; |
| 1220 | 1224 | |
| 1221 | if (builtin.single_threaded) return; | |
| 1225 | _ = initial_token; // we need to load `token` *after* the group finishes | |
| 1226 | ||
| 1227 | if (builtin.single_threaded) unreachable; // we never set `group.token` to non-`null` | |
| 1222 | 1228 | |
| 1223 | 1229 | { |
| 1224 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); | |
| 1225 | while (true) { | |
| 1230 | var it: ?*std.SinglyLinkedList.Node = @ptrCast(@alignCast(group.token.load(.monotonic))); | |
| 1231 | while (it) |node| : (it = node.next) { | |
| 1226 | 1232 | const gc: *GroupClosure = @fieldParentPtr("node", node); |
| 1227 | 1233 | gc.closure.requestCancel(t); |
| 1228 | node = node.next orelse break; | |
| 1229 | 1234 | } |
| 1230 | 1235 | } |
| 1231 | 1236 | |
| ... | ... | @@ -1235,14 +1240,15 @@ fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void |
| 1235 | 1240 | assert(prev_state & GroupClosure.sync_is_waiting == 0); |
| 1236 | 1241 | if ((prev_state / GroupClosure.sync_one_pending) > 0) event.waitUncancelable(ioBasic(t)); |
| 1237 | 1242 | |
| 1238 | { | |
| 1239 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); | |
| 1240 | while (true) { | |
| 1241 | const gc: *GroupClosure = @fieldParentPtr("node", node); | |
| 1242 | const node_next = node.next; | |
| 1243 | gc.deinit(gpa); | |
| 1244 | node = node_next orelse break; | |
| 1245 | } | |
| 1243 | // Since the group has now finished, it's illegal to add more tasks to it until we return. It's | |
| 1244 | // also illegal for us to race with another `await` or `cancel`. Therefore, we must be the only | |
| 1245 | // thread who can access `group` right now. | |
| 1246 | var it: ?*std.SinglyLinkedList.Node = @ptrCast(@alignCast(group.token.raw)); | |
| 1247 | group.token.raw = null; | |
| 1248 | while (it) |node| { | |
| 1249 | it = node.next; // update `it` now, because `deinit` will invalidate `node` | |
| 1250 | const gc: *GroupClosure = @fieldParentPtr("node", node); | |
| 1251 | gc.deinit(gpa); | |
| 1246 | 1252 | } |
| 1247 | 1253 | } |
| 1248 | 1254 |
lib/std/Thread.zig+2-2| ... | ... | @@ -18,9 +18,10 @@ pub const Mutex = @import("Thread/Mutex.zig"); |
| 18 | 18 | pub const Semaphore = @import("Thread/Semaphore.zig"); |
| 19 | 19 | pub const Condition = @import("Thread/Condition.zig"); |
| 20 | 20 | pub const RwLock = @import("Thread/RwLock.zig"); |
| 21 | pub const Pool = @import("Thread/Pool.zig"); | |
| 22 | 21 | pub const WaitGroup = @import("Thread/WaitGroup.zig"); |
| 23 | 22 | |
| 23 | pub const Pool = @compileError("deprecated; consider using 'std.Io.Group' with 'std.Io.Threaded'"); | |
| 24 | ||
| 24 | 25 | pub const use_pthreads = native_os != .windows and native_os != .wasi and builtin.link_libc; |
| 25 | 26 | |
| 26 | 27 | /// A thread-safe logical boolean value which can be `set` and `unset`. |
| ... | ... | @@ -1754,7 +1755,6 @@ test { |
| 1754 | 1755 | _ = Semaphore; |
| 1755 | 1756 | _ = Condition; |
| 1756 | 1757 | _ = RwLock; |
| 1757 | _ = Pool; | |
| 1758 | 1758 | } |
| 1759 | 1759 | |
| 1760 | 1760 | fn testIncrementNotify(value: *usize, event: *ResetEvent) void { |
lib/std/Thread/Pool.zig deleted-326| ... | ... | @@ -1,326 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const Pool = @This(); | |
| 4 | const WaitGroup = @import("WaitGroup.zig"); | |
| 5 | ||
| 6 | mutex: std.Thread.Mutex = .{}, | |
| 7 | cond: std.Thread.Condition = .{}, | |
| 8 | run_queue: std.SinglyLinkedList = .{}, | |
| 9 | is_running: bool = true, | |
| 10 | allocator: std.mem.Allocator, | |
| 11 | threads: if (builtin.single_threaded) [0]std.Thread else []std.Thread, | |
| 12 | ids: if (builtin.single_threaded) struct { | |
| 13 | inline fn deinit(_: @This(), _: std.mem.Allocator) void {} | |
| 14 | fn getIndex(_: @This(), _: std.Thread.Id) usize { | |
| 15 | return 0; | |
| 16 | } | |
| 17 | } else std.AutoArrayHashMapUnmanaged(std.Thread.Id, void), | |
| 18 | ||
| 19 | const Runnable = struct { | |
| 20 | runFn: RunProto, | |
| 21 | node: std.SinglyLinkedList.Node = .{}, | |
| 22 | }; | |
| 23 | ||
| 24 | const RunProto = *const fn (*Runnable, id: ?usize) void; | |
| 25 | ||
| 26 | pub const Options = struct { | |
| 27 | allocator: std.mem.Allocator, | |
| 28 | n_jobs: ?usize = null, | |
| 29 | track_ids: bool = false, | |
| 30 | stack_size: usize = std.Thread.SpawnConfig.default_stack_size, | |
| 31 | }; | |
| 32 | ||
| 33 | pub fn init(pool: *Pool, options: Options) !void { | |
| 34 | const allocator = options.allocator; | |
| 35 | ||
| 36 | pool.* = .{ | |
| 37 | .allocator = allocator, | |
| 38 | .threads = if (builtin.single_threaded) .{} else &.{}, | |
| 39 | .ids = .{}, | |
| 40 | }; | |
| 41 | ||
| 42 | if (builtin.single_threaded) { | |
| 43 | return; | |
| 44 | } | |
| 45 | ||
| 46 | const thread_count = options.n_jobs orelse @max(1, std.Thread.getCpuCount() catch 1); | |
| 47 | if (options.track_ids) { | |
| 48 | try pool.ids.ensureTotalCapacity(allocator, 1 + thread_count); | |
| 49 | pool.ids.putAssumeCapacityNoClobber(std.Thread.getCurrentId(), {}); | |
| 50 | } | |
| 51 | ||
| 52 | // kill and join any threads we spawned and free memory on error. | |
| 53 | pool.threads = try allocator.alloc(std.Thread, thread_count); | |
| 54 | var spawned: usize = 0; | |
| 55 | errdefer pool.join(spawned); | |
| 56 | ||
| 57 | for (pool.threads) |*thread| { | |
| 58 | thread.* = try std.Thread.spawn(.{ | |
| 59 | .stack_size = options.stack_size, | |
| 60 | .allocator = allocator, | |
| 61 | }, worker, .{pool}); | |
| 62 | spawned += 1; | |
| 63 | } | |
| 64 | } | |
| 65 | ||
| 66 | pub fn deinit(pool: *Pool) void { | |
| 67 | pool.join(pool.threads.len); // kill and join all threads. | |
| 68 | pool.ids.deinit(pool.allocator); | |
| 69 | pool.* = undefined; | |
| 70 | } | |
| 71 | ||
| 72 | fn join(pool: *Pool, spawned: usize) void { | |
| 73 | if (builtin.single_threaded) { | |
| 74 | return; | |
| 75 | } | |
| 76 | ||
| 77 | { | |
| 78 | pool.mutex.lock(); | |
| 79 | defer pool.mutex.unlock(); | |
| 80 | ||
| 81 | // ensure future worker threads exit the dequeue loop | |
| 82 | pool.is_running = false; | |
| 83 | } | |
| 84 | ||
| 85 | // wake up any sleeping threads (this can be done outside the mutex) | |
| 86 | // then wait for all the threads we know are spawned to complete. | |
| 87 | pool.cond.broadcast(); | |
| 88 | for (pool.threads[0..spawned]) |thread| { | |
| 89 | thread.join(); | |
| 90 | } | |
| 91 | ||
| 92 | pool.allocator.free(pool.threads); | |
| 93 | } | |
| 94 | ||
| 95 | /// Runs `func` in the thread pool, calling `WaitGroup.start` beforehand, and | |
| 96 | /// `WaitGroup.finish` after it returns. | |
| 97 | /// | |
| 98 | /// In the case that queuing the function call fails to allocate memory, or the | |
| 99 | /// target is single-threaded, the function is called directly. | |
| 100 | pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args: anytype) void { | |
| 101 | wait_group.start(); | |
| 102 | ||
| 103 | if (builtin.single_threaded) { | |
| 104 | @call(.auto, func, args); | |
| 105 | wait_group.finish(); | |
| 106 | return; | |
| 107 | } | |
| 108 | ||
| 109 | const Args = @TypeOf(args); | |
| 110 | const Closure = struct { | |
| 111 | arguments: Args, | |
| 112 | pool: *Pool, | |
| 113 | runnable: Runnable = .{ .runFn = runFn }, | |
| 114 | wait_group: *WaitGroup, | |
| 115 | ||
| 116 | fn runFn(runnable: *Runnable, _: ?usize) void { | |
| 117 | const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); | |
| 118 | @call(.auto, func, closure.arguments); | |
| 119 | closure.wait_group.finish(); | |
| 120 | ||
| 121 | // The thread pool's allocator is protected by the mutex. | |
| 122 | const mutex = &closure.pool.mutex; | |
| 123 | mutex.lock(); | |
| 124 | defer mutex.unlock(); | |
| 125 | ||
| 126 | closure.pool.allocator.destroy(closure); | |
| 127 | } | |
| 128 | }; | |
| 129 | ||
| 130 | { | |
| 131 | pool.mutex.lock(); | |
| 132 | ||
| 133 | const closure = pool.allocator.create(Closure) catch { | |
| 134 | pool.mutex.unlock(); | |
| 135 | @call(.auto, func, args); | |
| 136 | wait_group.finish(); | |
| 137 | return; | |
| 138 | }; | |
| 139 | closure.* = .{ | |
| 140 | .arguments = args, | |
| 141 | .pool = pool, | |
| 142 | .wait_group = wait_group, | |
| 143 | }; | |
| 144 | ||
| 145 | pool.run_queue.prepend(&closure.runnable.node); | |
| 146 | pool.mutex.unlock(); | |
| 147 | } | |
| 148 | ||
| 149 | // Notify waiting threads outside the lock to try and keep the critical section small. | |
| 150 | pool.cond.signal(); | |
| 151 | } | |
| 152 | ||
| 153 | /// Runs `func` in the thread pool, calling `WaitGroup.start` beforehand, and | |
| 154 | /// `WaitGroup.finish` after it returns. | |
| 155 | /// | |
| 156 | /// The first argument passed to `func` is a dense `usize` thread id, the rest | |
| 157 | /// of the arguments are passed from `args`. Requires the pool to have been | |
| 158 | /// initialized with `.track_ids = true`. | |
| 159 | /// | |
| 160 | /// In the case that queuing the function call fails to allocate memory, or the | |
| 161 | /// target is single-threaded, the function is called directly. | |
| 162 | pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args: anytype) void { | |
| 163 | wait_group.start(); | |
| 164 | ||
| 165 | if (builtin.single_threaded) { | |
| 166 | @call(.auto, func, .{0} ++ args); | |
| 167 | wait_group.finish(); | |
| 168 | return; | |
| 169 | } | |
| 170 | ||
| 171 | const Args = @TypeOf(args); | |
| 172 | const Closure = struct { | |
| 173 | arguments: Args, | |
| 174 | pool: *Pool, | |
| 175 | runnable: Runnable = .{ .runFn = runFn }, | |
| 176 | wait_group: *WaitGroup, | |
| 177 | ||
| 178 | fn runFn(runnable: *Runnable, id: ?usize) void { | |
| 179 | const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); | |
| 180 | @call(.auto, func, .{id.?} ++ closure.arguments); | |
| 181 | closure.wait_group.finish(); | |
| 182 | ||
| 183 | // The thread pool's allocator is protected by the mutex. | |
| 184 | const mutex = &closure.pool.mutex; | |
| 185 | mutex.lock(); | |
| 186 | defer mutex.unlock(); | |
| 187 | ||
| 188 | closure.pool.allocator.destroy(closure); | |
| 189 | } | |
| 190 | }; | |
| 191 | ||
| 192 | { | |
| 193 | pool.mutex.lock(); | |
| 194 | ||
| 195 | const closure = pool.allocator.create(Closure) catch { | |
| 196 | const id: ?usize = pool.ids.getIndex(std.Thread.getCurrentId()); | |
| 197 | pool.mutex.unlock(); | |
| 198 | @call(.auto, func, .{id.?} ++ args); | |
| 199 | wait_group.finish(); | |
| 200 | return; | |
| 201 | }; | |
| 202 | closure.* = .{ | |
| 203 | .arguments = args, | |
| 204 | .pool = pool, | |
| 205 | .wait_group = wait_group, | |
| 206 | }; | |
| 207 | ||
| 208 | pool.run_queue.prepend(&closure.runnable.node); | |
| 209 | pool.mutex.unlock(); | |
| 210 | } | |
| 211 | ||
| 212 | // Notify waiting threads outside the lock to try and keep the critical section small. | |
| 213 | pool.cond.signal(); | |
| 214 | } | |
| 215 | ||
| 216 | pub fn spawn(pool: *Pool, comptime func: anytype, args: anytype) !void { | |
| 217 | if (builtin.single_threaded) { | |
| 218 | @call(.auto, func, args); | |
| 219 | return; | |
| 220 | } | |
| 221 | ||
| 222 | const Args = @TypeOf(args); | |
| 223 | const Closure = struct { | |
| 224 | arguments: Args, | |
| 225 | pool: *Pool, | |
| 226 | runnable: Runnable = .{ .runFn = runFn }, | |
| 227 | ||
| 228 | fn runFn(runnable: *Runnable, _: ?usize) void { | |
| 229 | const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); | |
| 230 | @call(.auto, func, closure.arguments); | |
| 231 | ||
| 232 | // The thread pool's allocator is protected by the mutex. | |
| 233 | const mutex = &closure.pool.mutex; | |
| 234 | mutex.lock(); | |
| 235 | defer mutex.unlock(); | |
| 236 | ||
| 237 | closure.pool.allocator.destroy(closure); | |
| 238 | } | |
| 239 | }; | |
| 240 | ||
| 241 | { | |
| 242 | pool.mutex.lock(); | |
| 243 | defer pool.mutex.unlock(); | |
| 244 | ||
| 245 | const closure = try pool.allocator.create(Closure); | |
| 246 | closure.* = .{ | |
| 247 | .arguments = args, | |
| 248 | .pool = pool, | |
| 249 | }; | |
| 250 | ||
| 251 | pool.run_queue.prepend(&closure.runnable.node); | |
| 252 | } | |
| 253 | ||
| 254 | // Notify waiting threads outside the lock to try and keep the critical section small. | |
| 255 | pool.cond.signal(); | |
| 256 | } | |
| 257 | ||
| 258 | test spawn { | |
| 259 | const TestFn = struct { | |
| 260 | fn checkRun(completed: *bool) void { | |
| 261 | completed.* = true; | |
| 262 | } | |
| 263 | }; | |
| 264 | ||
| 265 | var completed: bool = false; | |
| 266 | ||
| 267 | { | |
| 268 | var pool: Pool = undefined; | |
| 269 | try pool.init(.{ | |
| 270 | .allocator = std.testing.allocator, | |
| 271 | }); | |
| 272 | defer pool.deinit(); | |
| 273 | try pool.spawn(TestFn.checkRun, .{&completed}); | |
| 274 | } | |
| 275 | ||
| 276 | try std.testing.expectEqual(true, completed); | |
| 277 | } | |
| 278 | ||
| 279 | fn worker(pool: *Pool) void { | |
| 280 | pool.mutex.lock(); | |
| 281 | defer pool.mutex.unlock(); | |
| 282 | ||
| 283 | const id: ?usize = if (pool.ids.count() > 0) @intCast(pool.ids.count()) else null; | |
| 284 | if (id) |_| pool.ids.putAssumeCapacityNoClobber(std.Thread.getCurrentId(), {}); | |
| 285 | ||
| 286 | while (true) { | |
| 287 | while (pool.run_queue.popFirst()) |run_node| { | |
| 288 | // Temporarily unlock the mutex in order to execute the run_node | |
| 289 | pool.mutex.unlock(); | |
| 290 | defer pool.mutex.lock(); | |
| 291 | ||
| 292 | const runnable: *Runnable = @fieldParentPtr("node", run_node); | |
| 293 | runnable.runFn(runnable, id); | |
| 294 | } | |
| 295 | ||
| 296 | // Stop executing instead of waiting if the thread pool is no longer running. | |
| 297 | if (pool.is_running) { | |
| 298 | pool.cond.wait(&pool.mutex); | |
| 299 | } else { | |
| 300 | break; | |
| 301 | } | |
| 302 | } | |
| 303 | } | |
| 304 | ||
| 305 | pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { | |
| 306 | var id: ?usize = null; | |
| 307 | ||
| 308 | while (!wait_group.isDone()) { | |
| 309 | pool.mutex.lock(); | |
| 310 | if (pool.run_queue.popFirst()) |run_node| { | |
| 311 | id = id orelse pool.ids.getIndex(std.Thread.getCurrentId()); | |
| 312 | pool.mutex.unlock(); | |
| 313 | const runnable: *Runnable = @fieldParentPtr("node", run_node); | |
| 314 | runnable.runFn(runnable, id); | |
| 315 | continue; | |
| 316 | } | |
| 317 | ||
| 318 | pool.mutex.unlock(); | |
| 319 | wait_group.wait(); | |
| 320 | return; | |
| 321 | } | |
| 322 | } | |
| 323 | ||
| 324 | pub fn getIdCount(pool: *Pool) usize { | |
| 325 | return @intCast(1 + pool.threads.len); | |
| 326 | } |
src/Compilation.zig+421-466| ... | ... | @@ -10,8 +10,6 @@ const Allocator = std.mem.Allocator; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | const log = std.log.scoped(.compilation); |
| 12 | 12 | const Target = std.Target; |
| 13 | const ThreadPool = std.Thread.Pool; | |
| 14 | const WaitGroup = std.Thread.WaitGroup; | |
| 15 | 13 | const ErrorBundle = std.zig.ErrorBundle; |
| 16 | 14 | const fatal = std.process.fatal; |
| 17 | 15 | |
| ... | ... | @@ -56,6 +54,7 @@ gpa: Allocator, |
| 56 | 54 | /// threads at once. |
| 57 | 55 | arena: Allocator, |
| 58 | 56 | io: Io, |
| 57 | thread_limit: usize, | |
| 59 | 58 | /// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`. |
| 60 | 59 | zcu: ?*Zcu, |
| 61 | 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 | 109 | } = .{}, |
| 111 | 110 | |
| 112 | 111 | link_diags: link.Diags, |
| 113 | link_task_queue: link.Queue = .empty, | |
| 112 | link_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`. | |
| 119 | oneshot_prelink_tasks: std.ArrayList(link.PrelinkTask), | |
| 114 | 120 | |
| 115 | 121 | /// Set of work that can be represented by only flags to determine whether the |
| 116 | 122 | /// work is queued or not. |
| ... | ... | @@ -198,7 +204,6 @@ libc_include_dir_list: []const []const u8, |
| 198 | 204 | libc_framework_dir_list: []const []const u8, |
| 199 | 205 | rc_includes: std.zig.RcIncludes, |
| 200 | 206 | mingw_unicode_entry_point: bool, |
| 201 | thread_pool: *ThreadPool, | |
| 202 | 207 | |
| 203 | 208 | /// Populated when we build the libc++ static library. A Job to build this is placed in the queue |
| 204 | 209 | /// and resolved before calling linker.flush(). |
| ... | ... | @@ -248,16 +253,10 @@ crt_files: std.StringHashMapUnmanaged(CrtFile) = .empty, |
| 248 | 253 | reference_trace: ?u32 = null, |
| 249 | 254 | |
| 250 | 255 | /// This mutex guards all `Compilation` mutable state. |
| 251 | /// Disabled in single-threaded mode because the thread pool spawns in the same thread. | |
| 252 | mutex: 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 = .{}, | |
| 256 | mutex: std.Io.Mutex = .init, | |
| 257 | 257 | |
| 258 | 258 | test_filters: []const []const u8, |
| 259 | 259 | |
| 260 | link_task_wait_group: WaitGroup = .{}, | |
| 261 | 260 | link_prog_node: std.Progress.Node = .none, |
| 262 | 261 | |
| 263 | 262 | llvm_opt_bisect_limit: c_int, |
| ... | ... | @@ -1568,7 +1567,7 @@ pub const CacheMode = enum { |
| 1568 | 1567 | |
| 1569 | 1568 | pub const ParentWholeCache = struct { |
| 1570 | 1569 | manifest: *Cache.Manifest, |
| 1571 | mutex: *std.Thread.Mutex, | |
| 1570 | mutex: *std.Io.Mutex, | |
| 1572 | 1571 | prefix_map: [4]u8, |
| 1573 | 1572 | }; |
| 1574 | 1573 | |
| ... | ... | @@ -1596,7 +1595,7 @@ const CacheUse = union(CacheMode) { |
| 1596 | 1595 | lf_open_opts: link.File.OpenOptions, |
| 1597 | 1596 | /// This is a pointer to a local variable inside `update`. |
| 1598 | 1597 | cache_manifest: ?*Cache.Manifest, |
| 1599 | cache_manifest_mutex: std.Thread.Mutex, | |
| 1598 | cache_manifest_mutex: std.Io.Mutex, | |
| 1600 | 1599 | /// This is non-`null` for most of the body of `update`. It is the temporary directory which |
| 1601 | 1600 | /// we initially emit our artifacts to. After the main part of the update is done, it will |
| 1602 | 1601 | /// be closed and moved to its final location, and this field set to `null`. |
| ... | ... | @@ -1636,7 +1635,7 @@ const CacheUse = union(CacheMode) { |
| 1636 | 1635 | |
| 1637 | 1636 | pub const CreateOptions = struct { |
| 1638 | 1637 | dirs: Directories, |
| 1639 | thread_pool: *ThreadPool, | |
| 1638 | thread_limit: usize, | |
| 1640 | 1639 | self_exe_path: ?[]const u8 = null, |
| 1641 | 1640 | |
| 1642 | 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 | 2210 | .llvm_object = null, |
| 2212 | 2211 | .analysis_roots_buffer = undefined, |
| 2213 | 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 | 2216 | break :blk zcu; |
| 2217 | 2217 | } else blk: { |
| 2218 | 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 | 2224 | .gpa = gpa, |
| 2225 | 2225 | .arena = arena, |
| 2226 | 2226 | .io = io, |
| 2227 | .thread_limit = options.thread_limit, | |
| 2227 | 2228 | .zcu = opt_zcu, |
| 2228 | 2229 | .cache_use = undefined, // populated below |
| 2229 | 2230 | .bin_file = null, // populated below if necessary |
| ... | ... | @@ -2241,7 +2242,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2241 | 2242 | .libc_framework_dir_list = libc_dirs.libc_framework_dir_list, |
| 2242 | 2243 | .rc_includes = options.rc_includes, |
| 2243 | 2244 | .mingw_unicode_entry_point = options.mingw_unicode_entry_point, |
| 2244 | .thread_pool = options.thread_pool, | |
| 2245 | 2245 | .clang_passthrough_mode = options.clang_passthrough_mode, |
| 2246 | 2246 | .clang_preprocessor_mode = options.clang_preprocessor_mode, |
| 2247 | 2247 | .verbose_cc = options.verbose_cc, |
| ... | ... | @@ -2282,7 +2282,8 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2282 | 2282 | .global_cc_argv = options.global_cc_argv, |
| 2283 | 2283 | .file_system_inputs = options.file_system_inputs, |
| 2284 | 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 | 2287 | .emit_bin = try options.emit_bin.resolve(arena, &options, .bin), |
| 2287 | 2288 | .emit_asm = try options.emit_asm.resolve(arena, &options, .@"asm"), |
| 2288 | 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 | 2469 | whole.* = .{ |
| 2469 | 2470 | .lf_open_opts = lf_open_opts, |
| 2470 | 2471 | .cache_manifest = null, |
| 2471 | .cache_manifest_mutex = .{}, | |
| 2472 | .cache_manifest_mutex = .init, | |
| 2472 | 2473 | .tmp_artifact_directory = null, |
| 2473 | 2474 | .lock = null, |
| 2474 | 2475 | }; |
| ... | ... | @@ -2553,14 +2554,14 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2553 | 2554 | }; |
| 2554 | 2555 | |
| 2555 | 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 | 2558 | inline for (fields) |field| { |
| 2558 | 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 | 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 | 2565 | } else if (target.isMuslLibC()) { |
| 2565 | 2566 | if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable); |
| 2566 | 2567 | |
| ... | ... | @@ -2629,10 +2630,9 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2629 | 2630 | for (0..count) |i| { |
| 2630 | 2631 | try comp.queueJob(.{ .windows_import_lib = i }); |
| 2631 | 2632 | } |
| 2632 | // when integrating coff linker with prelink, the above | |
| 2633 | // queueJob will need to change into something else since those | |
| 2634 | // jobs are dispatched *after* the link_task_wait_group.wait() | |
| 2635 | // that happens when separateCodegenThreadOk() is false. | |
| 2633 | // when integrating coff linker with prelink, the above `queueJob` will need to move | |
| 2634 | // to something in `dispatchPrelinkWork`, which must queue all prelink link tasks | |
| 2635 | // *before* we begin working on the main job queue. | |
| 2636 | 2636 | } |
| 2637 | 2637 | if (comp.wantBuildLibUnwindFromSource()) { |
| 2638 | 2638 | comp.queued_jobs.libunwind = true; |
| ... | ... | @@ -2681,19 +2681,15 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2681 | 2681 | } |
| 2682 | 2682 | } |
| 2683 | 2683 | |
| 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 | 2687 | return comp; |
| 2688 | 2688 | } |
| 2689 | 2689 | |
| 2690 | 2690 | pub fn destroy(comp: *Compilation) void { |
| 2691 | 2691 | const gpa = comp.gpa; |
| 2692 | 2692 | |
| 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 | 2693 | if (comp.bin_file) |lf| lf.destroy(); |
| 2698 | 2694 | if (comp.zcu) |zcu| zcu.deinit(); |
| 2699 | 2695 | comp.cache_use.deinit(); |
| ... | ... | @@ -2760,6 +2756,7 @@ pub fn destroy(comp: *Compilation) void { |
| 2760 | 2756 | if (comp.time_report) |*tr| tr.deinit(gpa); |
| 2761 | 2757 | |
| 2762 | 2758 | comp.link_diags.deinit(); |
| 2759 | comp.oneshot_prelink_tasks.deinit(gpa); | |
| 2763 | 2760 | |
| 2764 | 2761 | comp.clearMiscFailures(); |
| 2765 | 2762 | |
| ... | ... | @@ -2865,8 +2862,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2865 | 2862 | const tracy_trace = trace(@src()); |
| 2866 | 2863 | defer tracy_trace.end(); |
| 2867 | 2864 | |
| 2868 | // This arena is scoped to this one update. | |
| 2869 | 2865 | const gpa = comp.gpa; |
| 2866 | const io = comp.io; | |
| 2867 | ||
| 2868 | // This arena is scoped to this one update. | |
| 2870 | 2869 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| 2871 | 2870 | defer arena_allocator.deinit(); |
| 2872 | 2871 | const arena = arena_allocator.allocator(); |
| ... | ... | @@ -2946,8 +2945,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 2946 | 2945 | // In this case the cache hit contains the full set of file system inputs. Nice! |
| 2947 | 2946 | if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf); |
| 2948 | 2947 | if (comp.parent_whole_cache) |pwc| { |
| 2949 | pwc.mutex.lock(); | |
| 2950 | defer pwc.mutex.unlock(); | |
| 2948 | try pwc.mutex.lock(io); | |
| 2949 | defer pwc.mutex.unlock(io); | |
| 2951 | 2950 | try man.populateOtherManifest(pwc.manifest, pwc.prefix_map); |
| 2952 | 2951 | } |
| 2953 | 2952 | |
| ... | ... | @@ -3066,7 +3065,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 3066 | 3065 | comp.link_prog_node = .none; |
| 3067 | 3066 | }; |
| 3068 | 3067 | |
| 3069 | try comp.performAllTheWork(main_progress_node); | |
| 3068 | try comp.performAllTheWork(main_progress_node, arena); | |
| 3070 | 3069 | |
| 3071 | 3070 | if (comp.zcu) |zcu| { |
| 3072 | 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 | 3131 | .whole => |whole| { |
| 3133 | 3132 | if (comp.file_system_inputs) |buf| try man.populateFileSystemInputs(buf); |
| 3134 | 3133 | if (comp.parent_whole_cache) |pwc| { |
| 3135 | pwc.mutex.lock(); | |
| 3136 | defer pwc.mutex.unlock(); | |
| 3134 | try pwc.mutex.lock(io); | |
| 3135 | defer pwc.mutex.unlock(io); | |
| 3137 | 3136 | try man.populateOtherManifest(pwc.manifest, pwc.prefix_map); |
| 3138 | 3137 | } |
| 3139 | 3138 | |
| ... | ... | @@ -3234,6 +3233,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 3234 | 3233 | /// Thread-safe. Assumes that `comp.mutex` is *not* already held by the caller. |
| 3235 | 3234 | pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocator.Error!void { |
| 3236 | 3235 | const gpa = comp.gpa; |
| 3236 | const io = comp.io; | |
| 3237 | 3237 | const fsi = comp.file_system_inputs orelse return; |
| 3238 | 3238 | const prefixes = comp.cache_parent.prefixes(); |
| 3239 | 3239 | |
| ... | ... | @@ -3253,8 +3253,8 @@ pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocat |
| 3253 | 3253 | ); |
| 3254 | 3254 | |
| 3255 | 3255 | // There may be concurrent calls to this function from C object workers and/or the main thread. |
| 3256 | comp.mutex.lock(); | |
| 3257 | defer comp.mutex.unlock(); | |
| 3256 | comp.mutex.lockUncancelable(io); | |
| 3257 | defer comp.mutex.unlock(io); | |
| 3258 | 3258 | |
| 3259 | 3259 | try fsi.ensureUnusedCapacity(gpa, path.sub_path.len + 3); |
| 3260 | 3260 | if (fsi.items.len > 0) fsi.appendAssumeCapacity(0); |
| ... | ... | @@ -3305,6 +3305,7 @@ fn flush( |
| 3305 | 3305 | arena: Allocator, |
| 3306 | 3306 | tid: Zcu.PerThread.Id, |
| 3307 | 3307 | ) Allocator.Error!void { |
| 3308 | const io = comp.io; | |
| 3308 | 3309 | if (comp.zcu) |zcu| { |
| 3309 | 3310 | if (zcu.llvm_object) |llvm_object| { |
| 3310 | 3311 | const pt: Zcu.PerThread = .activate(zcu, tid); |
| ... | ... | @@ -3317,8 +3318,8 @@ fn flush( |
| 3317 | 3318 | |
| 3318 | 3319 | var timer = comp.startTimer(); |
| 3319 | 3320 | defer if (timer.finish()) |ns| { |
| 3320 | comp.mutex.lock(); | |
| 3321 | defer comp.mutex.unlock(); | |
| 3321 | comp.mutex.lockUncancelable(io); | |
| 3322 | defer comp.mutex.unlock(io); | |
| 3322 | 3323 | comp.time_report.?.stats.real_ns_llvm_emit = ns; |
| 3323 | 3324 | }; |
| 3324 | 3325 | |
| ... | ... | @@ -3362,8 +3363,8 @@ fn flush( |
| 3362 | 3363 | if (comp.bin_file) |lf| { |
| 3363 | 3364 | var timer = comp.startTimer(); |
| 3364 | 3365 | defer if (timer.finish()) |ns| { |
| 3365 | comp.mutex.lock(); | |
| 3366 | defer comp.mutex.unlock(); | |
| 3366 | comp.mutex.lockUncancelable(io); | |
| 3367 | defer comp.mutex.unlock(io); | |
| 3367 | 3368 | comp.time_report.?.stats.real_ns_link_flush = ns; |
| 3368 | 3369 | }; |
| 3369 | 3370 | // This is needed before reading the error flags. |
| ... | ... | @@ -4575,44 +4576,277 @@ pub fn unableToLoadZcuFile( |
| 4575 | 4576 | fn performAllTheWork( |
| 4576 | 4577 | comp: *Compilation, |
| 4577 | 4578 | main_progress_node: std.Progress.Node, |
| 4579 | update_arena: Allocator, | |
| 4578 | 4580 | ) JobError!void { |
| 4579 | // Regardless of errors, `comp.zcu` needs to update its generation number. | |
| 4580 | 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 | 4584 | zcu.generation += 1; |
| 4582 | 4585 | }; |
| 4583 | 4586 | |
| 4587 | const io = comp.io; | |
| 4588 | ||
| 4584 | 4589 | // This is awkward: we don't want to start the timer until later, but we won't want to stop it |
| 4585 | 4590 | // until the wait groups finish. That means we need do do this. |
| 4586 | 4591 | var decl_work_timer: ?Timer = null; |
| 4587 | 4592 | defer commit_timer: { |
| 4588 | 4593 | const t = &(decl_work_timer orelse break :commit_timer); |
| 4589 | 4594 | const ns = t.finish() orelse break :commit_timer; |
| 4590 | comp.mutex.lock(); | |
| 4591 | defer comp.mutex.unlock(); | |
| 4595 | comp.mutex.lockUncancelable(io); | |
| 4596 | defer comp.mutex.unlock(io); | |
| 4592 | 4597 | comp.time_report.?.stats.real_ns_decls = ns; |
| 4593 | 4598 | } |
| 4594 | 4599 | |
| 4595 | // Here we queue up all the AstGen tasks first, followed by C object compilation. | |
| 4596 | // We wait until the AstGen tasks are all completed before proceeding to the | |
| 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(); | |
| 4600 | var misc_group: Io.Group = .init; | |
| 4601 | defer misc_group.cancel(io); | |
| 4602 | 4602 | |
| 4603 | comp.link_task_wait_group.reset(); | |
| 4604 | defer comp.link_task_wait_group.wait(); | |
| 4603 | try comp.link_queue.start(comp, update_arena); | |
| 4604 | defer comp.link_queue.cancel(io); | |
| 4605 | 4605 | |
| 4606 | // Already-queued prelink tasks | |
| 4607 | comp.link_prog_node.increaseEstimatedTotalItems(comp.link_task_queue.queued_prelink.items.len); | |
| 4608 | comp.link_task_queue.start(comp); | |
| 4606 | misc_group.concurrent(io, dispatchPrelinkWork, .{ comp, main_progress_node }) catch |err| switch (err) { | |
| 4607 | error.ConcurrencyUnavailable => { | |
| 4608 | // Do it immediately so that the link queue isn't blocked | |
| 4609 | dispatchPrelinkWork(comp, main_progress_node); | |
| 4610 | }, | |
| 4611 | }; | |
| 4609 | 4612 | |
| 4610 | 4613 | if (comp.emit_docs != null) { |
| 4611 | 4614 | dev.check(.docs_emit); |
| 4612 | comp.thread_pool.spawnWg(&work_queue_wait_group, workerDocsCopy, .{comp}); | |
| 4613 | work_queue_wait_group.spawnManager(workerDocsWasm, .{ comp, main_progress_node }); | |
| 4615 | misc_group.async(io, workerDocsCopy, .{comp}); | |
| 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 | } |
| 4615 | 4801 | |
| 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 | ||
| 4839 | fn 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 | 4850 | // In case it failed last time, try again. `clearMiscFailures` was already |
| 4617 | 4851 | // called at the start of `update`. |
| 4618 | 4852 | if (comp.queued_jobs.compiler_rt_lib and comp.compiler_rt_lib == null) { |
| ... | ... | @@ -4620,8 +4854,7 @@ fn performAllTheWork( |
| 4620 | 4854 | // compiler-rt due to LLD bugs as well, e.g.: |
| 4621 | 4855 | // |
| 4622 | 4856 | // https://github.com/llvm/llvm-project/issues/43698#issuecomment-2542660611 |
| 4623 | comp.link_task_queue.startPrelinkItem(); | |
| 4624 | comp.link_task_wait_group.spawnManager(buildRt, .{ | |
| 4857 | prelink_group.async(io, buildRt, .{ | |
| 4625 | 4858 | comp, |
| 4626 | 4859 | "compiler_rt.zig", |
| 4627 | 4860 | "compiler_rt", |
| ... | ... | @@ -4638,8 +4871,7 @@ fn performAllTheWork( |
| 4638 | 4871 | } |
| 4639 | 4872 | |
| 4640 | 4873 | if (comp.queued_jobs.compiler_rt_obj and comp.compiler_rt_obj == null) { |
| 4641 | comp.link_task_queue.startPrelinkItem(); | |
| 4642 | comp.link_task_wait_group.spawnManager(buildRt, .{ | |
| 4874 | prelink_group.async(io, buildRt, .{ | |
| 4643 | 4875 | comp, |
| 4644 | 4876 | "compiler_rt.zig", |
| 4645 | 4877 | "compiler_rt", |
| ... | ... | @@ -4657,8 +4889,7 @@ fn performAllTheWork( |
| 4657 | 4889 | |
| 4658 | 4890 | // hack for stage2_x86_64 + coff |
| 4659 | 4891 | if (comp.queued_jobs.compiler_rt_dyn_lib and comp.compiler_rt_dyn_lib == null) { |
| 4660 | comp.link_task_queue.startPrelinkItem(); | |
| 4661 | comp.link_task_wait_group.spawnManager(buildRt, .{ | |
| 4892 | prelink_group.async(io, buildRt, .{ | |
| 4662 | 4893 | comp, |
| 4663 | 4894 | "compiler_rt.zig", |
| 4664 | 4895 | "compiler_rt", |
| ... | ... | @@ -4675,8 +4906,7 @@ fn performAllTheWork( |
| 4675 | 4906 | } |
| 4676 | 4907 | |
| 4677 | 4908 | if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) { |
| 4678 | comp.link_task_queue.startPrelinkItem(); | |
| 4679 | comp.link_task_wait_group.spawnManager(buildRt, .{ | |
| 4909 | prelink_group.async(io, buildRt, .{ | |
| 4680 | 4910 | comp, |
| 4681 | 4911 | "fuzzer.zig", |
| 4682 | 4912 | "fuzzer", |
| ... | ... | @@ -4690,8 +4920,7 @@ fn performAllTheWork( |
| 4690 | 4920 | } |
| 4691 | 4921 | |
| 4692 | 4922 | if (comp.queued_jobs.ubsan_rt_lib and comp.ubsan_rt_lib == null) { |
| 4693 | comp.link_task_queue.startPrelinkItem(); | |
| 4694 | comp.link_task_wait_group.spawnManager(buildRt, .{ | |
| 4923 | prelink_group.async(io, buildRt, .{ | |
| 4695 | 4924 | comp, |
| 4696 | 4925 | "ubsan_rt.zig", |
| 4697 | 4926 | "ubsan_rt", |
| ... | ... | @@ -4707,8 +4936,7 @@ fn performAllTheWork( |
| 4707 | 4936 | } |
| 4708 | 4937 | |
| 4709 | 4938 | if (comp.queued_jobs.ubsan_rt_obj and comp.ubsan_rt_obj == null) { |
| 4710 | comp.link_task_queue.startPrelinkItem(); | |
| 4711 | comp.link_task_wait_group.spawnManager(buildRt, .{ | |
| 4939 | prelink_group.async(io, buildRt, .{ | |
| 4712 | 4940 | comp, |
| 4713 | 4941 | "ubsan_rt.zig", |
| 4714 | 4942 | "ubsan_rt", |
| ... | ... | @@ -4724,310 +4952,93 @@ fn performAllTheWork( |
| 4724 | 4952 | } |
| 4725 | 4953 | |
| 4726 | 4954 | if (comp.queued_jobs.glibc_shared_objects) { |
| 4727 | comp.link_task_queue.startPrelinkItem(); | |
| 4728 | comp.link_task_wait_group.spawnManager(buildGlibcSharedObjects, .{ comp, main_progress_node }); | |
| 4955 | prelink_group.async(io, buildGlibcSharedObjects, .{ comp, main_progress_node }); | |
| 4729 | 4956 | } |
| 4730 | 4957 | |
| 4731 | 4958 | if (comp.queued_jobs.freebsd_shared_objects) { |
| 4732 | comp.link_task_queue.startPrelinkItem(); | |
| 4733 | comp.link_task_wait_group.spawnManager(buildFreeBSDSharedObjects, .{ comp, main_progress_node }); | |
| 4959 | prelink_group.async(io, buildFreeBSDSharedObjects, .{ comp, main_progress_node }); | |
| 4734 | 4960 | } |
| 4735 | 4961 | |
| 4736 | 4962 | if (comp.queued_jobs.netbsd_shared_objects) { |
| 4737 | comp.link_task_queue.startPrelinkItem(); | |
| 4738 | comp.link_task_wait_group.spawnManager(buildNetBSDSharedObjects, .{ comp, main_progress_node }); | |
| 4963 | prelink_group.async(io, buildNetBSDSharedObjects, .{ comp, main_progress_node }); | |
| 4739 | 4964 | } |
| 4740 | 4965 | |
| 4741 | 4966 | if (comp.queued_jobs.libunwind) { |
| 4742 | comp.link_task_queue.startPrelinkItem(); | |
| 4743 | comp.link_task_wait_group.spawnManager(buildLibUnwind, .{ comp, main_progress_node }); | |
| 4967 | prelink_group.async(io, buildLibUnwind, .{ comp, main_progress_node }); | |
| 4744 | 4968 | } |
| 4745 | 4969 | |
| 4746 | 4970 | if (comp.queued_jobs.libcxx) { |
| 4747 | comp.link_task_queue.startPrelinkItem(); | |
| 4748 | comp.link_task_wait_group.spawnManager(buildLibCxx, .{ comp, main_progress_node }); | |
| 4971 | prelink_group.async(io, buildLibCxx, .{ comp, main_progress_node }); | |
| 4749 | 4972 | } |
| 4750 | 4973 | |
| 4751 | 4974 | if (comp.queued_jobs.libcxxabi) { |
| 4752 | comp.link_task_queue.startPrelinkItem(); | |
| 4753 | comp.link_task_wait_group.spawnManager(buildLibCxxAbi, .{ comp, main_progress_node }); | |
| 4975 | prelink_group.async(io, buildLibCxxAbi, .{ comp, main_progress_node }); | |
| 4754 | 4976 | } |
| 4755 | 4977 | |
| 4756 | 4978 | if (comp.queued_jobs.libtsan) { |
| 4757 | comp.link_task_queue.startPrelinkItem(); | |
| 4758 | comp.link_task_wait_group.spawnManager(buildLibTsan, .{ comp, main_progress_node }); | |
| 4979 | prelink_group.async(io, buildLibTsan, .{ comp, main_progress_node }); | |
| 4759 | 4980 | } |
| 4760 | 4981 | |
| 4761 | 4982 | if (comp.queued_jobs.zigc_lib and comp.zigc_static_lib == null) { |
| 4762 | comp.link_task_queue.startPrelinkItem(); | |
| 4763 | comp.link_task_wait_group.spawnManager(buildLibZigC, .{ comp, main_progress_node }); | |
| 4983 | prelink_group.async(io, buildLibZigC, .{ comp, main_progress_node }); | |
| 4764 | 4984 | } |
| 4765 | 4985 | |
| 4766 | 4986 | for (0..@typeInfo(musl.CrtFile).@"enum".fields.len) |i| { |
| 4767 | 4987 | if (comp.queued_jobs.musl_crt_file[i]) { |
| 4768 | 4988 | const tag: musl.CrtFile = @enumFromInt(i); |
| 4769 | comp.link_task_queue.startPrelinkItem(); | |
| 4770 | comp.link_task_wait_group.spawnManager(buildMuslCrtFile, .{ comp, tag, main_progress_node }); | |
| 4989 | prelink_group.async(io, buildMuslCrtFile, .{ comp, tag, main_progress_node }); | |
| 4771 | 4990 | } |
| 4772 | 4991 | } |
| 4773 | 4992 | |
| 4774 | 4993 | for (0..@typeInfo(glibc.CrtFile).@"enum".fields.len) |i| { |
| 4775 | 4994 | if (comp.queued_jobs.glibc_crt_file[i]) { |
| 4776 | 4995 | const tag: glibc.CrtFile = @enumFromInt(i); |
| 4777 | comp.link_task_queue.startPrelinkItem(); | |
| 4778 | comp.link_task_wait_group.spawnManager(buildGlibcCrtFile, .{ comp, tag, main_progress_node }); | |
| 4996 | prelink_group.async(io, buildGlibcCrtFile, .{ comp, tag, main_progress_node }); | |
| 4779 | 4997 | } |
| 4780 | 4998 | } |
| 4781 | 4999 | |
| 4782 | 5000 | for (0..@typeInfo(freebsd.CrtFile).@"enum".fields.len) |i| { |
| 4783 | 5001 | if (comp.queued_jobs.freebsd_crt_file[i]) { |
| 4784 | 5002 | const tag: freebsd.CrtFile = @enumFromInt(i); |
| 4785 | comp.link_task_queue.startPrelinkItem(); | |
| 4786 | comp.link_task_wait_group.spawnManager(buildFreeBSDCrtFile, .{ comp, tag, main_progress_node }); | |
| 5003 | prelink_group.async(io, buildFreeBSDCrtFile, .{ comp, tag, main_progress_node }); | |
| 4787 | 5004 | } |
| 4788 | 5005 | } |
| 4789 | 5006 | |
| 4790 | 5007 | for (0..@typeInfo(netbsd.CrtFile).@"enum".fields.len) |i| { |
| 4791 | 5008 | if (comp.queued_jobs.netbsd_crt_file[i]) { |
| 4792 | 5009 | const tag: netbsd.CrtFile = @enumFromInt(i); |
| 4793 | comp.link_task_queue.startPrelinkItem(); | |
| 4794 | comp.link_task_wait_group.spawnManager(buildNetBSDCrtFile, .{ comp, tag, main_progress_node }); | |
| 5010 | prelink_group.async(io, buildNetBSDCrtFile, .{ comp, tag, main_progress_node }); | |
| 4795 | 5011 | } |
| 4796 | 5012 | } |
| 4797 | 5013 | |
| 4798 | 5014 | for (0..@typeInfo(wasi_libc.CrtFile).@"enum".fields.len) |i| { |
| 4799 | 5015 | if (comp.queued_jobs.wasi_libc_crt_file[i]) { |
| 4800 | 5016 | const tag: wasi_libc.CrtFile = @enumFromInt(i); |
| 4801 | comp.link_task_queue.startPrelinkItem(); | |
| 4802 | comp.link_task_wait_group.spawnManager(buildWasiLibcCrtFile, .{ comp, tag, main_progress_node }); | |
| 5017 | prelink_group.async(io, buildWasiLibcCrtFile, .{ comp, tag, main_progress_node }); | |
| 4803 | 5018 | } |
| 4804 | 5019 | } |
| 4805 | 5020 | |
| 4806 | 5021 | for (0..@typeInfo(mingw.CrtFile).@"enum".fields.len) |i| { |
| 4807 | 5022 | if (comp.queued_jobs.mingw_crt_file[i]) { |
| 4808 | 5023 | const tag: mingw.CrtFile = @enumFromInt(i); |
| 4809 | comp.link_task_queue.startPrelinkItem(); | |
| 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); | |
| 5024 | prelink_group.async(io, buildMingwCrtFile, .{ comp, tag, main_progress_node }); | |
| 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); | |
| 4993 | 5027 | |
| 4994 | if (!comp.separateCodegenThreadOk()) { | |
| 4995 | // Waits until all input files have been parsed. | |
| 4996 | comp.link_task_wait_group.wait(); | |
| 4997 | comp.link_task_wait_group.reset(); | |
| 4998 | std.log.scoped(.link).debug("finished waiting for link_task_wait_group", .{}); | |
| 5028 | while (comp.c_object_work_queue.popFront()) |c_object| { | |
| 5029 | prelink_group.async(io, workerUpdateCObject, .{ | |
| 5030 | comp, c_object, main_progress_node, | |
| 5031 | }); | |
| 4999 | 5032 | } |
| 5000 | 5033 | |
| 5001 | if (comp.zcu != null) { | |
| 5002 | // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link). | |
| 5003 | decl_work_timer = comp.startTimer(); | |
| 5034 | while (comp.win32_resource_work_queue.popFront()) |win32_resource| { | |
| 5035 | prelink_group.async(io, workerUpdateWin32Resource, .{ | |
| 5036 | comp, win32_resource, main_progress_node, | |
| 5037 | }); | |
| 5004 | 5038 | } |
| 5005 | 5039 | |
| 5006 | work: while (true) { | |
| 5007 | for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| { | |
| 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 | } | |
| 5040 | prelink_group.wait(io); | |
| 5041 | comp.link_queue.finishPrelinkQueue(comp); | |
| 5031 | 5042 | } |
| 5032 | 5043 | |
| 5033 | 5044 | const JobError = Allocator.Error || Io.Cancelable; |
| ... | ... | @@ -5040,58 +5051,38 @@ pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void { |
| 5040 | 5051 | for (jobs) |job| try comp.queueJob(job); |
| 5041 | 5052 | } |
| 5042 | 5053 | |
| 5043 | fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { | |
| 5054 | fn processOneJob( | |
| 5055 | tid: usize, | |
| 5056 | comp: *Compilation, | |
| 5057 | job: Job, | |
| 5058 | ) JobError!void { | |
| 5044 | 5059 | switch (job) { |
| 5045 | 5060 | .codegen_func => |func| { |
| 5046 | 5061 | const zcu = comp.zcu.?; |
| 5047 | 5062 | const gpa = zcu.gpa; |
| 5048 | var air = func.air; | |
| 5049 | errdefer { | |
| 5050 | zcu.codegen_prog_node.completeOne(); | |
| 5051 | comp.link_prog_node.completeOne(); | |
| 5052 | air.deinit(gpa); | |
| 5053 | } | |
| 5054 | if (!air.typesFullyResolved(zcu)) { | |
| 5063 | var owned_air: ?Air = func.air; | |
| 5064 | defer if (owned_air) |*air| air.deinit(gpa); | |
| 5065 | ||
| 5066 | if (!owned_air.?.typesFullyResolved(zcu)) { | |
| 5055 | 5067 | // Type resolution failed in a way which affects this function. This is a transitive |
| 5056 | 5068 | // failure, but it doesn't need recording, because this function semantically depends |
| 5057 | 5069 | // on the failed type, so when it is changed the function is updated. |
| 5058 | 5070 | zcu.codegen_prog_node.completeOne(); |
| 5059 | 5071 | comp.link_prog_node.completeOne(); |
| 5060 | air.deinit(gpa); | |
| 5061 | 5072 | return; |
| 5062 | 5073 | } |
| 5063 | const shared_mir = try gpa.create(link.ZcuTask.LinkFunc.SharedMir); | |
| 5064 | shared_mir.* = .{ | |
| 5065 | .status = .init(.pending), | |
| 5066 | .value = undefined, | |
| 5067 | }; | |
| 5068 | assert(zcu.pending_codegen_jobs.rmw(.Add, 1, .monotonic) > 0); // the "Code Generation" node hasn't been ended | |
| 5069 | // This value is used as a heuristic to avoid queueing too much AIR/MIR at once (hence | |
| 5070 | // using a lot of memory). If this would cause too many AIR bytes to be in-flight, we | |
| 5071 | // will block on the `dispatchZcuLinkTask` call below. | |
| 5072 | const air_bytes: u32 = @intCast(air.instructions.len * 5 + air.extra.items.len * 4); | |
| 5073 | if (comp.separateCodegenThreadOk()) { | |
| 5074 | // `workerZcuCodegen` takes ownership of `air`. | |
| 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 | } | |
| 5074 | ||
| 5075 | // Some linkers need to refer to the AIR. In that case, the linker is not running | |
| 5076 | // concurrently, so we'll just keep ownership of the AIR for ourselves instead of | |
| 5077 | // letting the codegen job destroy it. | |
| 5078 | const disown_air = zcu.backendSupportsFeature(.separate_thread); | |
| 5079 | ||
| 5080 | // Begin the codegen task. If the codegen/link queue is backed up, this might | |
| 5081 | // block until the linker is able to process some tasks. | |
| 5082 | const codegen_task = try zcu.codegen_task_pool.start(zcu, func.func, &owned_air.?, disown_air); | |
| 5083 | if (disown_air) owned_air = null; | |
| 5084 | ||
| 5085 | try comp.link_queue.enqueueZcu(comp, tid, .{ .link_func = codegen_task }); | |
| 5095 | 5086 | }, |
| 5096 | 5087 | .link_nav => |nav_index| { |
| 5097 | 5088 | const zcu = comp.zcu.?; |
| ... | ... | @@ -5111,7 +5102,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { |
| 5111 | 5102 | comp.link_prog_node.completeOne(); |
| 5112 | 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 | 5107 | .link_type => |ty| { |
| 5117 | 5108 | const zcu = comp.zcu.?; |
| ... | ... | @@ -5123,10 +5114,10 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { |
| 5123 | 5114 | comp.link_prog_node.completeOne(); |
| 5124 | 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| { | |
| 5129 | comp.dispatchZcuLinkTask(tid, .{ .update_line_number = ti }); | |
| 5119 | .update_line_number => |tracked_inst| { | |
| 5120 | try comp.link_queue.enqueueZcu(comp, tid, .{ .update_line_number = tracked_inst }); | |
| 5130 | 5121 | }, |
| 5131 | 5122 | .analyze_func => |func| { |
| 5132 | 5123 | const named_frame = tracy.namedFrame("analyze_func"); |
| ... | ... | @@ -5220,12 +5211,6 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void { |
| 5220 | 5211 | } |
| 5221 | 5212 | } |
| 5222 | 5213 | |
| 5223 | pub 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 | ||
| 5229 | 5214 | fn createDepFile( |
| 5230 | 5215 | comp: *Compilation, |
| 5231 | 5216 | depfile: []const u8, |
| ... | ... | @@ -5480,6 +5465,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU |
| 5480 | 5465 | |
| 5481 | 5466 | var sub_create_diag: CreateDiagnostic = undefined; |
| 5482 | 5467 | const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{ |
| 5468 | .thread_limit = comp.thread_limit, | |
| 5483 | 5469 | .dirs = dirs, |
| 5484 | 5470 | .self_exe_path = comp.self_exe_path, |
| 5485 | 5471 | .config = config, |
| ... | ... | @@ -5487,7 +5473,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU |
| 5487 | 5473 | .entry = .disabled, |
| 5488 | 5474 | .cache_mode = .whole, |
| 5489 | 5475 | .root_name = root_name, |
| 5490 | .thread_pool = comp.thread_pool, | |
| 5491 | 5476 | .libc_installation = comp.libc_installation, |
| 5492 | 5477 | .emit_bin = .yes_cache, |
| 5493 | 5478 | .verbose_cc = comp.verbose_cc, |
| ... | ... | @@ -5541,13 +5526,15 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU |
| 5541 | 5526 | } |
| 5542 | 5527 | |
| 5543 | 5528 | fn workerUpdateFile( |
| 5544 | tid: usize, | |
| 5545 | 5529 | comp: *Compilation, |
| 5546 | 5530 | file: *Zcu.File, |
| 5547 | 5531 | file_index: Zcu.File.Index, |
| 5548 | 5532 | prog_node: std.Progress.Node, |
| 5549 | wg: *WaitGroup, | |
| 5533 | group: *Io.Group, | |
| 5550 | 5534 | ) void { |
| 5535 | const tid = Compilation.getTid(); | |
| 5536 | const io = comp.io; | |
| 5537 | ||
| 5551 | 5538 | const child_prog_node = prog_node.start(fs.path.basename(file.path.sub_path), 0); |
| 5552 | 5539 | defer child_prog_node.end(); |
| 5553 | 5540 | |
| ... | ... | @@ -5556,8 +5543,8 @@ fn workerUpdateFile( |
| 5556 | 5543 | pt.updateFile(file_index, file) catch |err| { |
| 5557 | 5544 | pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) { |
| 5558 | 5545 | error.OutOfMemory => { |
| 5559 | comp.mutex.lock(); | |
| 5560 | defer comp.mutex.unlock(); | |
| 5546 | comp.mutex.lockUncancelable(io); | |
| 5547 | defer comp.mutex.unlock(io); | |
| 5561 | 5548 | comp.setAllocFailure(); |
| 5562 | 5549 | }, |
| 5563 | 5550 | }; |
| ... | ... | @@ -5587,14 +5574,14 @@ fn workerUpdateFile( |
| 5587 | 5574 | if (pt.discoverImport(file.path, import_path)) |res| switch (res) { |
| 5588 | 5575 | .module, .existing_file => {}, |
| 5589 | 5576 | .new_file => |new| { |
| 5590 | comp.thread_pool.spawnWgId(wg, workerUpdateFile, .{ | |
| 5591 | comp, new.file, new.index, prog_node, wg, | |
| 5577 | group.async(io, workerUpdateFile, .{ | |
| 5578 | comp, new.file, new.index, prog_node, group, | |
| 5592 | 5579 | }); |
| 5593 | 5580 | }, |
| 5594 | 5581 | } else |err| switch (err) { |
| 5595 | 5582 | error.OutOfMemory => { |
| 5596 | comp.mutex.lock(); | |
| 5597 | defer comp.mutex.unlock(); | |
| 5583 | comp.mutex.lockUncancelable(io); | |
| 5584 | defer comp.mutex.unlock(io); | |
| 5598 | 5585 | comp.setAllocFailure(); |
| 5599 | 5586 | }, |
| 5600 | 5587 | } |
| ... | ... | @@ -5610,17 +5597,20 @@ fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void { |
| 5610 | 5597 | ); |
| 5611 | 5598 | } |
| 5612 | 5599 | |
| 5613 | fn workerUpdateEmbedFile(tid: usize, comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { | |
| 5600 | fn workerUpdateEmbedFile(comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { | |
| 5601 | const tid = Compilation.getTid(); | |
| 5602 | const io = comp.io; | |
| 5614 | 5603 | comp.detectEmbedFileUpdate(@enumFromInt(tid), ef_index, ef) catch |err| switch (err) { |
| 5615 | 5604 | error.OutOfMemory => { |
| 5616 | comp.mutex.lock(); | |
| 5617 | defer comp.mutex.unlock(); | |
| 5605 | comp.mutex.lockUncancelable(io); | |
| 5606 | defer comp.mutex.unlock(io); | |
| 5618 | 5607 | comp.setAllocFailure(); |
| 5619 | 5608 | }, |
| 5620 | 5609 | }; |
| 5621 | 5610 | } |
| 5622 | 5611 | |
| 5623 | 5612 | fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void { |
| 5613 | const io = comp.io; | |
| 5624 | 5614 | const zcu = comp.zcu.?; |
| 5625 | 5615 | const pt: Zcu.PerThread = .activate(zcu, tid); |
| 5626 | 5616 | defer pt.deactivate(); |
| ... | ... | @@ -5633,8 +5623,8 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc |
| 5633 | 5623 | if (ef.val != .none and ef.val == old_val) return; // success, value unchanged |
| 5634 | 5624 | if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged |
| 5635 | 5625 | |
| 5636 | comp.mutex.lock(); | |
| 5637 | defer comp.mutex.unlock(); | |
| 5626 | comp.mutex.lockUncancelable(io); | |
| 5627 | defer comp.mutex.unlock(io); | |
| 5638 | 5628 | |
| 5639 | 5629 | try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index }); |
| 5640 | 5630 | } |
| ... | ... | @@ -5777,8 +5767,8 @@ pub fn translateC( |
| 5777 | 5767 | |
| 5778 | 5768 | switch (comp.cache_use) { |
| 5779 | 5769 | .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { |
| 5780 | whole.cache_manifest_mutex.lock(); | |
| 5781 | defer whole.cache_manifest_mutex.unlock(); | |
| 5770 | try whole.cache_manifest_mutex.lock(io); | |
| 5771 | defer whole.cache_manifest_mutex.unlock(io); | |
| 5782 | 5772 | try whole_cache_manifest.addDepFilePost(cache_tmp_dir, dep_basename); |
| 5783 | 5773 | }, |
| 5784 | 5774 | .incremental, .none => {}, |
| ... | ... | @@ -5879,7 +5869,6 @@ fn workerUpdateCObject( |
| 5879 | 5869 | c_object: *CObject, |
| 5880 | 5870 | progress_node: std.Progress.Node, |
| 5881 | 5871 | ) void { |
| 5882 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 5883 | 5872 | comp.updateCObject(c_object, progress_node) catch |err| switch (err) { |
| 5884 | 5873 | error.AnalysisFail => return, |
| 5885 | 5874 | else => { |
| ... | ... | @@ -5897,7 +5886,6 @@ fn workerUpdateWin32Resource( |
| 5897 | 5886 | win32_resource: *Win32Resource, |
| 5898 | 5887 | progress_node: std.Progress.Node, |
| 5899 | 5888 | ) void { |
| 5900 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 5901 | 5889 | comp.updateWin32Resource(win32_resource, progress_node) catch |err| switch (err) { |
| 5902 | 5890 | error.AnalysisFail => return, |
| 5903 | 5891 | else => { |
| ... | ... | @@ -5915,21 +5903,6 @@ pub const RtOptions = struct { |
| 5915 | 5903 | allow_lto: bool = true, |
| 5916 | 5904 | }; |
| 5917 | 5905 | |
| 5918 | fn 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 | ||
| 5933 | 5906 | fn buildRt( |
| 5934 | 5907 | comp: *Compilation, |
| 5935 | 5908 | root_source_name: []const u8, |
| ... | ... | @@ -5941,7 +5914,6 @@ fn buildRt( |
| 5941 | 5914 | options: RtOptions, |
| 5942 | 5915 | out: *?CrtFile, |
| 5943 | 5916 | ) void { |
| 5944 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 5945 | 5917 | comp.buildOutputFromZig( |
| 5946 | 5918 | root_source_name, |
| 5947 | 5919 | root_name, |
| ... | ... | @@ -5960,7 +5932,6 @@ fn buildRt( |
| 5960 | 5932 | } |
| 5961 | 5933 | |
| 5962 | 5934 | fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.Progress.Node) void { |
| 5963 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 5964 | 5935 | if (musl.buildCrtFile(comp, crt_file, prog_node)) |_| { |
| 5965 | 5936 | comp.queued_jobs.musl_crt_file[@intFromEnum(crt_file)] = false; |
| 5966 | 5937 | } else |err| switch (err) { |
| ... | ... | @@ -5972,7 +5943,6 @@ fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.P |
| 5972 | 5943 | } |
| 5973 | 5944 | |
| 5974 | 5945 | fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std.Progress.Node) void { |
| 5975 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 5976 | 5946 | if (glibc.buildCrtFile(comp, crt_file, prog_node)) |_| { |
| 5977 | 5947 | comp.queued_jobs.glibc_crt_file[@intFromEnum(crt_file)] = false; |
| 5978 | 5948 | } else |err| switch (err) { |
| ... | ... | @@ -5984,7 +5954,6 @@ fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std |
| 5984 | 5954 | } |
| 5985 | 5955 | |
| 5986 | 5956 | fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 5987 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 5988 | 5957 | if (glibc.buildSharedObjects(comp, prog_node)) |_| { |
| 5989 | 5958 | // The job should no longer be queued up since it succeeded. |
| 5990 | 5959 | comp.queued_jobs.glibc_shared_objects = false; |
| ... | ... | @@ -5995,7 +5964,6 @@ fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) voi |
| 5995 | 5964 | } |
| 5996 | 5965 | |
| 5997 | 5966 | fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: std.Progress.Node) void { |
| 5998 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 5999 | 5967 | if (freebsd.buildCrtFile(comp, crt_file, prog_node)) |_| { |
| 6000 | 5968 | comp.queued_jobs.freebsd_crt_file[@intFromEnum(crt_file)] = false; |
| 6001 | 5969 | } else |err| switch (err) { |
| ... | ... | @@ -6007,7 +5975,6 @@ fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: |
| 6007 | 5975 | } |
| 6008 | 5976 | |
| 6009 | 5977 | fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6010 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6011 | 5978 | if (freebsd.buildSharedObjects(comp, prog_node)) |_| { |
| 6012 | 5979 | // The job should no longer be queued up since it succeeded. |
| 6013 | 5980 | comp.queued_jobs.freebsd_shared_objects = false; |
| ... | ... | @@ -6020,7 +5987,6 @@ fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) v |
| 6020 | 5987 | } |
| 6021 | 5988 | |
| 6022 | 5989 | fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: std.Progress.Node) void { |
| 6023 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6024 | 5990 | if (netbsd.buildCrtFile(comp, crt_file, prog_node)) |_| { |
| 6025 | 5991 | comp.queued_jobs.netbsd_crt_file[@intFromEnum(crt_file)] = false; |
| 6026 | 5992 | } else |err| switch (err) { |
| ... | ... | @@ -6032,7 +5998,6 @@ fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: s |
| 6032 | 5998 | } |
| 6033 | 5999 | |
| 6034 | 6000 | fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6035 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6036 | 6001 | if (netbsd.buildSharedObjects(comp, prog_node)) |_| { |
| 6037 | 6002 | // The job should no longer be queued up since it succeeded. |
| 6038 | 6003 | comp.queued_jobs.netbsd_shared_objects = false; |
| ... | ... | @@ -6045,7 +6010,6 @@ fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) vo |
| 6045 | 6010 | } |
| 6046 | 6011 | |
| 6047 | 6012 | fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std.Progress.Node) void { |
| 6048 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6049 | 6013 | if (mingw.buildCrtFile(comp, crt_file, prog_node)) |_| { |
| 6050 | 6014 | comp.queued_jobs.mingw_crt_file[@intFromEnum(crt_file)] = false; |
| 6051 | 6015 | } else |err| switch (err) { |
| ... | ... | @@ -6057,7 +6021,6 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std |
| 6057 | 6021 | } |
| 6058 | 6022 | |
| 6059 | 6023 | fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_node: std.Progress.Node) void { |
| 6060 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6061 | 6024 | if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| { |
| 6062 | 6025 | comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false; |
| 6063 | 6026 | } else |err| switch (err) { |
| ... | ... | @@ -6069,7 +6032,6 @@ fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_no |
| 6069 | 6032 | } |
| 6070 | 6033 | |
| 6071 | 6034 | fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6072 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6073 | 6035 | if (libunwind.buildStaticLib(comp, prog_node)) |_| { |
| 6074 | 6036 | comp.queued_jobs.libunwind = false; |
| 6075 | 6037 | } else |err| switch (err) { |
| ... | ... | @@ -6079,7 +6041,6 @@ fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6079 | 6041 | } |
| 6080 | 6042 | |
| 6081 | 6043 | fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6082 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6083 | 6044 | if (libcxx.buildLibCxx(comp, prog_node)) |_| { |
| 6084 | 6045 | comp.queued_jobs.libcxx = false; |
| 6085 | 6046 | } else |err| switch (err) { |
| ... | ... | @@ -6089,7 +6050,6 @@ fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6089 | 6050 | } |
| 6090 | 6051 | |
| 6091 | 6052 | fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6092 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6093 | 6053 | if (libcxx.buildLibCxxAbi(comp, prog_node)) |_| { |
| 6094 | 6054 | comp.queued_jobs.libcxxabi = false; |
| 6095 | 6055 | } else |err| switch (err) { |
| ... | ... | @@ -6099,7 +6059,6 @@ fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6099 | 6059 | } |
| 6100 | 6060 | |
| 6101 | 6061 | fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6102 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6103 | 6062 | if (libtsan.buildTsan(comp, prog_node)) |_| { |
| 6104 | 6063 | comp.queued_jobs.libtsan = false; |
| 6105 | 6064 | } else |err| switch (err) { |
| ... | ... | @@ -6109,7 +6068,6 @@ fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6109 | 6068 | } |
| 6110 | 6069 | |
| 6111 | 6070 | fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void { |
| 6112 | defer comp.link_task_queue.finishPrelinkItem(comp); | |
| 6113 | 6071 | comp.buildOutputFromZig( |
| 6114 | 6072 | "c.zig", |
| 6115 | 6073 | "zigc", |
| ... | ... | @@ -6139,6 +6097,8 @@ fn reportRetryableWin32ResourceError( |
| 6139 | 6097 | win32_resource: *Win32Resource, |
| 6140 | 6098 | err: anyerror, |
| 6141 | 6099 | ) error{OutOfMemory}!void { |
| 6100 | const io = comp.io; | |
| 6101 | ||
| 6142 | 6102 | win32_resource.status = .failure_retryable; |
| 6143 | 6103 | |
| 6144 | 6104 | var bundle: ErrorBundle.Wip = undefined; |
| ... | ... | @@ -6160,8 +6120,8 @@ fn reportRetryableWin32ResourceError( |
| 6160 | 6120 | }); |
| 6161 | 6121 | const finished_bundle = try bundle.toOwnedBundle(""); |
| 6162 | 6122 | { |
| 6163 | comp.mutex.lock(); | |
| 6164 | defer comp.mutex.unlock(); | |
| 6123 | comp.mutex.lockUncancelable(io); | |
| 6124 | defer comp.mutex.unlock(io); | |
| 6165 | 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 | 6146 | |
| 6187 | 6147 | if (c_object.clearStatus(gpa)) { |
| 6188 | 6148 | // There was previous failure. |
| 6189 | comp.mutex.lock(); | |
| 6190 | defer comp.mutex.unlock(); | |
| 6149 | comp.mutex.lockUncancelable(io); | |
| 6150 | defer comp.mutex.unlock(io); | |
| 6191 | 6151 | // If the failure was OOM, there will not be an entry here, so we do |
| 6192 | 6152 | // not assert discard. |
| 6193 | 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 | 6417 | switch (comp.cache_use) { |
| 6458 | 6418 | .whole => |whole| { |
| 6459 | 6419 | if (whole.cache_manifest) |whole_cache_manifest| { |
| 6460 | whole.cache_manifest_mutex.lock(); | |
| 6461 | defer whole.cache_manifest_mutex.unlock(); | |
| 6420 | try whole.cache_manifest_mutex.lock(io); | |
| 6421 | defer whole.cache_manifest_mutex.unlock(io); | |
| 6462 | 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 | 6463 | }, |
| 6504 | 6464 | }; |
| 6505 | 6465 | |
| 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 | } |
| 6508 | 6468 | |
| 6509 | 6469 | fn 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 | 6477 | const tracy_trace = trace(@src()); |
| 6518 | 6478 | defer tracy_trace.end(); |
| 6519 | 6479 | |
| 6480 | const io = comp.io; | |
| 6481 | ||
| 6520 | 6482 | const src_path = switch (win32_resource.src) { |
| 6521 | 6483 | .rc => |rc_src| rc_src.src_path, |
| 6522 | 6484 | .manifest => |src_path| src_path, |
| ... | ... | @@ -6531,8 +6493,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 6531 | 6493 | |
| 6532 | 6494 | if (win32_resource.clearStatus(comp.gpa)) { |
| 6533 | 6495 | // There was previous failure. |
| 6534 | comp.mutex.lock(); | |
| 6535 | defer comp.mutex.unlock(); | |
| 6496 | comp.mutex.lockUncancelable(io); | |
| 6497 | defer comp.mutex.unlock(io); | |
| 6536 | 6498 | // If the failure was OOM, there will not be an entry here, so we do |
| 6537 | 6499 | // not assert discard. |
| 6538 | 6500 | _ = comp.failed_win32_resources.swapRemove(win32_resource); |
| ... | ... | @@ -6706,8 +6668,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 6706 | 6668 | try man.addFilePost(dep_file_path); |
| 6707 | 6669 | switch (comp.cache_use) { |
| 6708 | 6670 | .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { |
| 6709 | whole.cache_manifest_mutex.lock(); | |
| 6710 | defer whole.cache_manifest_mutex.unlock(); | |
| 6671 | try whole.cache_manifest_mutex.lock(io); | |
| 6672 | defer whole.cache_manifest_mutex.unlock(io); | |
| 6711 | 6673 | try whole_cache_manifest.addFilePost(dep_file_path); |
| 6712 | 6674 | }, |
| 6713 | 6675 | .incremental, .none => {}, |
| ... | ... | @@ -7428,8 +7390,9 @@ fn failCObjWithOwnedDiagBundle( |
| 7428 | 7390 | @branchHint(.cold); |
| 7429 | 7391 | assert(diag_bundle.diags.len > 0); |
| 7430 | 7392 | { |
| 7431 | comp.mutex.lock(); | |
| 7432 | defer comp.mutex.unlock(); | |
| 7393 | const io = comp.io; | |
| 7394 | comp.mutex.lockUncancelable(io); | |
| 7395 | defer comp.mutex.unlock(io); | |
| 7433 | 7396 | { |
| 7434 | 7397 | errdefer diag_bundle.destroy(comp.gpa); |
| 7435 | 7398 | try comp.failed_c_objects.ensureUnusedCapacity(comp.gpa, 1); |
| ... | ... | @@ -7470,8 +7433,9 @@ fn failWin32ResourceWithOwnedBundle( |
| 7470 | 7433 | ) error{ OutOfMemory, AnalysisFail } { |
| 7471 | 7434 | @branchHint(.cold); |
| 7472 | 7435 | { |
| 7473 | comp.mutex.lock(); | |
| 7474 | defer comp.mutex.unlock(); | |
| 7436 | const io = comp.io; | |
| 7437 | comp.mutex.lockUncancelable(io); | |
| 7438 | defer comp.mutex.unlock(io); | |
| 7475 | 7439 | try comp.failed_win32_resources.putNoClobber(comp.gpa, win32_resource, err_bundle); |
| 7476 | 7440 | } |
| 7477 | 7441 | win32_resource.status = .failure; |
| ... | ... | @@ -7795,9 +7759,9 @@ pub fn lockAndSetMiscFailure( |
| 7795 | 7759 | comptime format: []const u8, |
| 7796 | 7760 | args: anytype, |
| 7797 | 7761 | ) void { |
| 7798 | comp.mutex.lock(); | |
| 7799 | defer comp.mutex.unlock(); | |
| 7800 | ||
| 7762 | const io = comp.io; | |
| 7763 | comp.mutex.lockUncancelable(io); | |
| 7764 | defer comp.mutex.unlock(io); | |
| 7801 | 7765 | return setMiscFailure(comp, tag, format, args); |
| 7802 | 7766 | } |
| 7803 | 7767 | |
| ... | ... | @@ -7840,8 +7804,8 @@ pub fn updateSubCompilation( |
| 7840 | 7804 | defer errors.deinit(gpa); |
| 7841 | 7805 | |
| 7842 | 7806 | if (errors.errorMessageCount() > 0) { |
| 7843 | parent_comp.mutex.lock(); | |
| 7844 | defer parent_comp.mutex.unlock(); | |
| 7807 | parent_comp.mutex.lockUncancelable(parent_comp.io); | |
| 7808 | defer parent_comp.mutex.unlock(parent_comp.io); | |
| 7845 | 7809 | try parent_comp.misc_failures.ensureUnusedCapacity(gpa, 1); |
| 7846 | 7810 | parent_comp.misc_failures.putAssumeCapacityNoClobber(misc_task, .{ |
| 7847 | 7811 | .msg = try std.fmt.allocPrint(gpa, "sub-compilation of {t} failed", .{misc_task}), |
| ... | ... | @@ -7942,6 +7906,7 @@ fn buildOutputFromZig( |
| 7942 | 7906 | |
| 7943 | 7907 | var sub_create_diag: CreateDiagnostic = undefined; |
| 7944 | 7908 | const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{ |
| 7909 | .thread_limit = comp.thread_limit, | |
| 7945 | 7910 | .dirs = comp.dirs.withoutLocalCache(), |
| 7946 | 7911 | .cache_mode = .whole, |
| 7947 | 7912 | .parent_whole_cache = parent_whole_cache, |
| ... | ... | @@ -7949,7 +7914,6 @@ fn buildOutputFromZig( |
| 7949 | 7914 | .config = config, |
| 7950 | 7915 | .root_mod = root_mod, |
| 7951 | 7916 | .root_name = root_name, |
| 7952 | .thread_pool = comp.thread_pool, | |
| 7953 | 7917 | .libc_installation = comp.libc_installation, |
| 7954 | 7918 | .emit_bin = .yes_cache, |
| 7955 | 7919 | .function_sections = true, |
| ... | ... | @@ -7980,7 +7944,7 @@ fn buildOutputFromZig( |
| 7980 | 7944 | assert(out.* == null); |
| 7981 | 7945 | out.* = crt_file; |
| 7982 | 7946 | |
| 7983 | comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); | |
| 7947 | try comp.queuePrelinkTaskMode(crt_file.full_object_path, &config); | |
| 7984 | 7948 | } |
| 7985 | 7949 | |
| 7986 | 7950 | pub const CrtFileOptions = struct { |
| ... | ... | @@ -8079,13 +8043,13 @@ pub fn build_crt_file( |
| 8079 | 8043 | |
| 8080 | 8044 | var sub_create_diag: CreateDiagnostic = undefined; |
| 8081 | 8045 | const sub_compilation = Compilation.create(gpa, arena, io, &sub_create_diag, .{ |
| 8046 | .thread_limit = comp.thread_limit, | |
| 8082 | 8047 | .dirs = comp.dirs.withoutLocalCache(), |
| 8083 | 8048 | .self_exe_path = comp.self_exe_path, |
| 8084 | 8049 | .cache_mode = .whole, |
| 8085 | 8050 | .config = config, |
| 8086 | 8051 | .root_mod = root_mod, |
| 8087 | 8052 | .root_name = root_name, |
| 8088 | .thread_pool = comp.thread_pool, | |
| 8089 | 8053 | .libc_installation = comp.libc_installation, |
| 8090 | 8054 | .emit_bin = .yes_cache, |
| 8091 | 8055 | .function_sections = options.function_sections orelse false, |
| ... | ... | @@ -8114,18 +8078,18 @@ pub fn build_crt_file( |
| 8114 | 8078 | try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node); |
| 8115 | 8079 | |
| 8116 | 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); | |
| 8118 | 8082 | |
| 8119 | 8083 | { |
| 8120 | comp.mutex.lock(); | |
| 8121 | defer comp.mutex.unlock(); | |
| 8084 | comp.mutex.lockUncancelable(io); | |
| 8085 | defer comp.mutex.unlock(io); | |
| 8122 | 8086 | try comp.crt_files.ensureUnusedCapacity(gpa, 1); |
| 8123 | 8087 | comp.crt_files.putAssumeCapacityNoClobber(basename, crt_file); |
| 8124 | 8088 | } |
| 8125 | 8089 | } |
| 8126 | 8090 | |
| 8127 | pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) void { | |
| 8128 | comp.queuePrelinkTasks(switch (config.output_mode) { | |
| 8091 | pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) Io.Cancelable!void { | |
| 8092 | try comp.queuePrelinkTasks(switch (config.output_mode) { | |
| 8129 | 8093 | .Exe => unreachable, |
| 8130 | 8094 | .Obj => &.{.{ .load_object = path }}, |
| 8131 | 8095 | .Lib => &.{switch (config.link_mode) { |
| ... | ... | @@ -8135,33 +8099,10 @@ pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const |
| 8135 | 8099 | }); |
| 8136 | 8100 | } |
| 8137 | 8101 | |
| 8138 | /// Only valid to call during `update`. Automatically handles queuing up a | |
| 8139 | /// linker worker task if there is not already one. | |
| 8140 | pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) void { | |
| 8102 | /// Only valid to call during `update`. | |
| 8103 | pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) Io.Cancelable!void { | |
| 8141 | 8104 | comp.link_prog_node.increaseEstimatedTotalItems(tasks.len); |
| 8142 | comp.link_task_queue.enqueuePrelink(comp, tasks) catch |err| switch (err) { | |
| 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. | |
| 8149 | fn 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 | }; | |
| 8105 | try comp.link_queue.enqueuePrelink(comp, tasks); | |
| 8165 | 8106 | } |
| 8166 | 8107 | |
| 8167 | 8108 | pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile { |
| ... | ... | @@ -8251,3 +8192,17 @@ pub fn compilerRtOptMode(comp: Compilation) std.builtin.OptimizeMode { |
| 8251 | 8192 | pub fn compilerRtStrip(comp: Compilation) bool { |
| 8252 | 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. | |
| 8199 | pub fn getTid() usize { | |
| 8200 | if (my_tid == null) my_tid = next_tid.fetchAdd(1, .monotonic); | |
| 8201 | return my_tid.?; | |
| 8202 | } | |
| 8203 | pub fn setMainThread() void { | |
| 8204 | my_tid = 0; | |
| 8205 | } | |
| 8206 | /// TID 0 is reserved for the main thread. | |
| 8207 | var next_tid: std.atomic.Value(usize) = .init(1); | |
| 8208 | threadlocal var my_tid: ?usize = null; |
src/IncrementalDebugServer.zig+109-39| ... | ... | @@ -14,57 +14,122 @@ comptime { |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | zcu: *Zcu, |
| 17 | thread: ?std.Thread, | |
| 18 | running: std.atomic.Value(bool), | |
| 17 | future: ?Io.Future(void), | |
| 19 | 18 | /// Held by our owner when an update is in-progress, and held by us when responding to a command. |
| 20 | 19 | /// So, essentially guards all access to `Compilation`, including `Zcu`. |
| 21 | mutex: std.Thread.Mutex, | |
| 20 | mutex: std.Io.Mutex, | |
| 22 | 21 | |
| 23 | 22 | pub fn init(zcu: *Zcu) IncrementalDebugServer { |
| 24 | 23 | return .{ |
| 25 | 24 | .zcu = zcu, |
| 26 | .thread = null, | |
| 27 | .running = .init(true), | |
| 28 | .mutex = .{}, | |
| 25 | .future = null, | |
| 26 | .mutex = .init, | |
| 29 | 27 | }; |
| 30 | 28 | } |
| 31 | 29 | |
| 32 | 30 | pub fn deinit(ids: *IncrementalDebugServer) void { |
| 33 | if (ids.thread) |t| { | |
| 34 | ids.running.store(false, .monotonic); | |
| 35 | t.join(); | |
| 36 | } | |
| 31 | const io = ids.zcu.comp.io; | |
| 32 | if (ids.future) |*f| f.cancel(io); | |
| 37 | 33 | } |
| 38 | 34 | |
| 39 | 35 | const port = 7623; |
| 40 | 36 | pub fn spawn(ids: *IncrementalDebugServer) void { |
| 37 | const io = ids.zcu.comp.io; | |
| 41 | 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| | |
| 43 | std.process.fatal("failed to spawn incremental debug server: {s}", .{@errorName(err)}); | |
| 39 | ids.future = io.concurrent(runServer, .{ids}) catch |err| | |
| 40 | std.process.fatal("failed to start incremental debug server: {s}", .{@errorName(err)}); | |
| 44 | 41 | } |
| 45 | fn runThread(ids: *IncrementalDebugServer) void { | |
| 46 | const gpa = ids.zcu.gpa; | |
| 42 | fn runServer(ids: *IncrementalDebugServer) void { | |
| 47 | 43 | const io = ids.zcu.comp.io; |
| 48 | 44 | |
| 49 | var cmd_buf: [1024]u8 = undefined; | |
| 50 | var text_out: std.ArrayList(u8) = .empty; | |
| 51 | defer text_out.deinit(gpa); | |
| 52 | ||
| 53 | const addr: std.Io.net.IpAddress = .{ .ip6 = .loopback(port) }; | |
| 54 | var server = addr.listen(io, .{}) catch @panic("IncrementalDebugServer: failed to listen"); | |
| 45 | const addr: Io.net.IpAddress = .{ .ip6 = .loopback(port) }; | |
| 46 | var server = addr.listen(io, .{}) catch |err| switch (err) { | |
| 47 | error.Canceled => return, | |
| 48 | else => |e| { | |
| 49 | log.err("listen failed ({t}); closing server", .{e}); | |
| 50 | return; | |
| 51 | }, | |
| 52 | }; | |
| 55 | 53 | defer server.deinit(io); |
| 56 | var stream = server.accept(io) catch @panic("IncrementalDebugServer: failed to accept"); | |
| 57 | defer stream.close(io); | |
| 58 | 54 | |
| 59 | var stream_reader = stream.reader(io, &cmd_buf); | |
| 60 | var stream_writer = stream.writer(io, &.{}); | |
| 55 | while (true) { | |
| 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}), | |
| 61 | 101 | |
| 62 | while (ids.running.load(.monotonic)) { | |
| 63 | stream_writer.interface.writeAll("zig> ") catch @panic("IncrementalDebugServer: failed to write"); | |
| 64 | const untrimmed = stream_reader.interface.takeSentinel('\n') catch |err| switch (err) { | |
| 65 | error.EndOfStream => break, | |
| 66 | else => @panic("IncrementalDebugServer: failed to read command"), | |
| 102 | error.AddressFamilyUnsupported, | |
| 103 | error.SocketUnconnected, | |
| 104 | error.SocketNotBound, | |
| 105 | error.AccessDenied, | |
| 106 | => unreachable, | |
| 107 | } | |
| 67 | 108 | }; |
| 109 | } | |
| 110 | } | |
| 111 | ||
| 112 | fn 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 | 133 | const cmd_and_arg = std.mem.trim(u8, untrimmed, " \t\r\n"); |
| 69 | 134 | const cmd: []const u8, const arg: []const u8 = if (std.mem.indexOfScalar(u8, cmd_and_arg, ' ')) |i| |
| 70 | 135 | .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] } |
| ... | ... | @@ -74,18 +139,21 @@ fn runThread(ids: *IncrementalDebugServer) void { |
| 74 | 139 | text_out.clearRetainingCapacity(); |
| 75 | 140 | { |
| 76 | 141 | if (!ids.mutex.tryLock()) { |
| 77 | stream_writer.interface.writeAll("waiting for in-progress update to finish...\n") catch @panic("IncrementalDebugServer: failed to write"); | |
| 78 | ids.mutex.lock(); | |
| 142 | try stream_writer.writeAll("waiting for in-progress update to finish...\n"); | |
| 143 | try ids.mutex.lock(io); | |
| 79 | 144 | } |
| 80 | defer ids.mutex.unlock(); | |
| 81 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &text_out); | |
| 145 | defer ids.mutex.unlock(io); | |
| 146 | var allocating: Io.Writer.Allocating = .fromArrayList(gpa, &text_out); | |
| 82 | 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"); | |
| 86 | stream_writer.interface.writeAll(text_out.items) catch @panic("IncrementalDebugServer: failed to write"); | |
| 154 | try text_out.append(gpa, '\n'); | |
| 155 | try stream_writer.writeAll(text_out.items); | |
| 87 | 156 | } |
| 88 | std.debug.print("closing incremental debug server\n", .{}); | |
| 89 | 157 | } |
| 90 | 158 | |
| 91 | 159 | const help_str: []const u8 = |
| ... | ... | @@ -123,7 +191,7 @@ const help_str: []const u8 = |
| 123 | 191 | \\ |
| 124 | 192 | ; |
| 125 | 193 | |
| 126 | fn handleCommand(zcu: *Zcu, w: *std.Io.Writer, cmd_str: []const u8, arg_str: []const u8) error{ WriteFailed, OutOfMemory }!void { | |
| 194 | fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const u8) error{ WriteFailed, OutOfMemory }!void { | |
| 127 | 195 | const ip = &zcu.intern_pool; |
| 128 | 196 | if (std.mem.eql(u8, cmd_str, "help")) { |
| 129 | 197 | try w.writeAll(help_str); |
| ... | ... | @@ -328,7 +396,8 @@ fn printAnalUnit(unit: AnalUnit, buf: *[32]u8) []const u8 { |
| 328 | 396 | }; |
| 329 | 397 | return std.fmt.bufPrint(buf, "{s} {d}", .{ @tagName(unit.unwrap()), idx }) catch unreachable; |
| 330 | 398 | } |
| 331 | fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void { | |
| 399 | ||
| 400 | fn printType(ty: Type, zcu: *const Zcu, w: *Io.Writer) Io.Writer.Error!void { | |
| 332 | 401 | const ip = &zcu.intern_pool; |
| 333 | 402 | switch (ip.indexToKey(ty.toIntern())) { |
| 334 | 403 | .int_type => |int| try w.print("{c}{d}", .{ |
| ... | ... | @@ -377,6 +446,7 @@ fn printType(ty: Type, zcu: *const Zcu, w: anytype) !void { |
| 377 | 446 | const std = @import("std"); |
| 378 | 447 | const Io = std.Io; |
| 379 | 448 | const Allocator = std.mem.Allocator; |
| 449 | const log = std.log.scoped(.incremental_debug_server); | |
| 380 | 450 | |
| 381 | 451 | const Compilation = @import("Compilation.zig"); |
| 382 | 452 | const Zcu = @import("Zcu.zig"); |
src/InternPool.zig+441-331| ... | ... | @@ -8,6 +8,7 @@ const assert = std.debug.assert; |
| 8 | 8 | const BigIntConst = std.math.big.int.Const; |
| 9 | 9 | const BigIntMutable = std.math.big.int.Mutable; |
| 10 | 10 | const Cache = std.Build.Cache; |
| 11 | const Io = std.Io; | |
| 11 | 12 | const Limb = std.math.big.Limb; |
| 12 | 13 | const Hash = std.hash.Wyhash; |
| 13 | 14 | |
| ... | ... | @@ -214,6 +215,7 @@ pub const TrackedInst = extern struct { |
| 214 | 215 | pub fn trackZir( |
| 215 | 216 | ip: *InternPool, |
| 216 | 217 | gpa: Allocator, |
| 218 | io: Io, | |
| 217 | 219 | tid: Zcu.PerThread.Id, |
| 218 | 220 | key: TrackedInst, |
| 219 | 221 | ) Allocator.Error!TrackedInst.Index { |
| ... | ... | @@ -235,8 +237,8 @@ pub fn trackZir( |
| 235 | 237 | if (entry.hash != hash) continue; |
| 236 | 238 | if (std.meta.eql(index.resolveFull(ip) orelse continue, key)) return index; |
| 237 | 239 | } |
| 238 | shard.mutate.tracked_inst_map.mutex.lock(); | |
| 239 | defer shard.mutate.tracked_inst_map.mutex.unlock(); | |
| 240 | shard.mutate.tracked_inst_map.mutex.lock(io, tid); | |
| 241 | defer shard.mutate.tracked_inst_map.mutex.unlock(io); | |
| 240 | 242 | if (map.entries != shard.shared.tracked_inst_map.entries) { |
| 241 | 243 | map = shard.shared.tracked_inst_map; |
| 242 | 244 | map_mask = map.header().mask(); |
| ... | ... | @@ -251,7 +253,7 @@ pub fn trackZir( |
| 251 | 253 | } |
| 252 | 254 | defer shard.mutate.tracked_inst_map.len += 1; |
| 253 | 255 | const local = ip.getLocal(tid); |
| 254 | const list = local.getMutableTrackedInsts(gpa); | |
| 256 | const list = local.getMutableTrackedInsts(gpa, io); | |
| 255 | 257 | try list.ensureUnusedCapacity(1); |
| 256 | 258 | const map_header = map.header().*; |
| 257 | 259 | if (shard.mutate.tracked_inst_map.len < map_header.capacity * 3 / 5) { |
| ... | ... | @@ -317,6 +319,7 @@ pub fn trackZir( |
| 317 | 319 | pub fn rehashTrackedInsts( |
| 318 | 320 | ip: *InternPool, |
| 319 | 321 | gpa: Allocator, |
| 322 | io: Io, | |
| 320 | 323 | tid: Zcu.PerThread.Id, |
| 321 | 324 | ) Allocator.Error!void { |
| 322 | 325 | assert(tid == .main); // we shouldn't have any other threads active right now |
| ... | ... | @@ -333,7 +336,7 @@ pub fn rehashTrackedInsts( |
| 333 | 336 | for (ip.locals) |*local| { |
| 334 | 337 | // `getMutableTrackedInsts` is okay only because no other thread is currently active. |
| 335 | 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 | 340 | if (tracked_inst.inst == .lost) continue; // we can ignore this one! |
| 338 | 341 | const full_hash = Hash.hash(0, std.mem.asBytes(&tracked_inst)); |
| 339 | 342 | const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))]; |
| ... | ... | @@ -379,7 +382,7 @@ pub fn rehashTrackedInsts( |
| 379 | 382 | for (ip.locals, 0..) |*local, local_tid| { |
| 380 | 383 | // `getMutableTrackedInsts` is okay only because no other thread is currently active. |
| 381 | 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 | 386 | if (tracked_inst.inst == .lost) continue; // we can ignore this one! |
| 384 | 387 | const full_hash = Hash.hash(0, std.mem.asBytes(&tracked_inst)); |
| 385 | 388 | const hash: u32 = @truncate(full_hash >> 32); |
| ... | ... | @@ -1113,11 +1116,11 @@ const Local = struct { |
| 1113 | 1116 | const Namespaces = List(struct { *[1 << namespaces_bucket_width]Zcu.Namespace }); |
| 1114 | 1117 | |
| 1115 | 1118 | const ListMutate = struct { |
| 1116 | mutex: std.Thread.Mutex, | |
| 1119 | mutex: Io.Mutex, | |
| 1117 | 1120 | len: u32, |
| 1118 | 1121 | |
| 1119 | 1122 | const empty: ListMutate = .{ |
| 1120 | .mutex = .{}, | |
| 1123 | .mutex = .init, | |
| 1121 | 1124 | .len = 0, |
| 1122 | 1125 | }; |
| 1123 | 1126 | }; |
| ... | ... | @@ -1144,6 +1147,7 @@ const Local = struct { |
| 1144 | 1147 | const ListSelf = @This(); |
| 1145 | 1148 | const Mutable = struct { |
| 1146 | 1149 | gpa: Allocator, |
| 1150 | io: Io, | |
| 1147 | 1151 | arena: *std.heap.ArenaAllocator.State, |
| 1148 | 1152 | mutate: *ListMutate, |
| 1149 | 1153 | list: *ListSelf, |
| ... | ... | @@ -1296,6 +1300,7 @@ const Local = struct { |
| 1296 | 1300 | } |
| 1297 | 1301 | |
| 1298 | 1302 | fn setCapacity(mutable: Mutable, capacity: u32) Allocator.Error!void { |
| 1303 | const io = mutable.io; | |
| 1299 | 1304 | var arena = mutable.arena.promote(mutable.gpa); |
| 1300 | 1305 | defer mutable.arena.* = arena.state; |
| 1301 | 1306 | const buf = try arena.allocator().alignedAlloc( |
| ... | ... | @@ -1313,8 +1318,8 @@ const Local = struct { |
| 1313 | 1318 | const new_slice = new_list.view().slice(); |
| 1314 | 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(); | |
| 1317 | defer mutable.mutate.mutex.unlock(); | |
| 1321 | mutable.mutate.mutex.lockUncancelable(io); | |
| 1322 | defer mutable.mutate.mutex.unlock(io); | |
| 1318 | 1323 | mutable.list.release(new_list); |
| 1319 | 1324 | } |
| 1320 | 1325 | |
| ... | ... | @@ -1375,18 +1380,20 @@ const Local = struct { |
| 1375 | 1380 | }; |
| 1376 | 1381 | } |
| 1377 | 1382 | |
| 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 | 1384 | return .{ |
| 1380 | 1385 | .gpa = gpa, |
| 1386 | .io = io, | |
| 1381 | 1387 | .arena = &local.mutate.arena, |
| 1382 | 1388 | .mutate = &local.mutate.items, |
| 1383 | 1389 | .list = &local.shared.items, |
| 1384 | 1390 | }; |
| 1385 | 1391 | } |
| 1386 | 1392 | |
| 1387 | pub fn getMutableExtra(local: *Local, gpa: Allocator) Extra.Mutable { | |
| 1393 | pub fn getMutableExtra(local: *Local, gpa: Allocator, io: Io) Extra.Mutable { | |
| 1388 | 1394 | return .{ |
| 1389 | 1395 | .gpa = gpa, |
| 1396 | .io = io, | |
| 1390 | 1397 | .arena = &local.mutate.arena, |
| 1391 | 1398 | .mutate = &local.mutate.extra, |
| 1392 | 1399 | .list = &local.shared.extra, |
| ... | ... | @@ -1397,11 +1404,12 @@ const Local = struct { |
| 1397 | 1404 | /// On 64-bit systems, this array is used for big integers and associated metadata. |
| 1398 | 1405 | /// Use the helper methods instead of accessing this directly in order to not |
| 1399 | 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 | 1408 | return switch (@sizeOf(Limb)) { |
| 1402 | @sizeOf(u32) => local.getMutableExtra(gpa), | |
| 1409 | @sizeOf(u32) => local.getMutableExtra(gpa, io), | |
| 1403 | 1410 | @sizeOf(u64) => .{ |
| 1404 | 1411 | .gpa = gpa, |
| 1412 | .io = io, | |
| 1405 | 1413 | .arena = &local.mutate.arena, |
| 1406 | 1414 | .mutate = &local.mutate.limbs, |
| 1407 | 1415 | .list = &local.shared.limbs, |
| ... | ... | @@ -1411,9 +1419,10 @@ const Local = struct { |
| 1411 | 1419 | } |
| 1412 | 1420 | |
| 1413 | 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 | 1423 | return .{ |
| 1416 | 1424 | .gpa = gpa, |
| 1425 | .io = io, | |
| 1417 | 1426 | .arena = &local.mutate.arena, |
| 1418 | 1427 | .mutate = &local.mutate.strings, |
| 1419 | 1428 | .list = &local.shared.strings, |
| ... | ... | @@ -1425,9 +1434,10 @@ const Local = struct { |
| 1425 | 1434 | /// is referencing the data here whether they want to store both index and length, |
| 1426 | 1435 | /// thus allowing null bytes, or store only index, and use null-termination. The |
| 1427 | 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 | 1438 | return .{ |
| 1430 | 1439 | .gpa = gpa, |
| 1440 | .io = io, | |
| 1431 | 1441 | .arena = &local.mutate.arena, |
| 1432 | 1442 | .mutate = &local.mutate.string_bytes, |
| 1433 | 1443 | .list = &local.shared.string_bytes, |
| ... | ... | @@ -1436,9 +1446,10 @@ const Local = struct { |
| 1436 | 1446 | |
| 1437 | 1447 | /// An index into `tracked_insts` gives a reference to a single ZIR instruction which |
| 1438 | 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 | 1450 | return .{ |
| 1441 | 1451 | .gpa = gpa, |
| 1452 | .io = io, | |
| 1442 | 1453 | .arena = &local.mutate.arena, |
| 1443 | 1454 | .mutate = &local.mutate.tracked_insts, |
| 1444 | 1455 | .list = &local.shared.tracked_insts, |
| ... | ... | @@ -1452,9 +1463,10 @@ const Local = struct { |
| 1452 | 1463 | /// |
| 1453 | 1464 | /// Key is the hash of the path to this file, used to store |
| 1454 | 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 | 1467 | return .{ |
| 1457 | 1468 | .gpa = gpa, |
| 1469 | .io = io, | |
| 1458 | 1470 | .arena = &local.mutate.arena, |
| 1459 | 1471 | .mutate = &local.mutate.files, |
| 1460 | 1472 | .list = &local.shared.files, |
| ... | ... | @@ -1466,27 +1478,30 @@ const Local = struct { |
| 1466 | 1478 | /// field names and values directly, relying on one of these maps, stored separately, |
| 1467 | 1479 | /// to provide lookup. |
| 1468 | 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 | 1482 | return .{ |
| 1471 | 1483 | .gpa = gpa, |
| 1484 | .io = io, | |
| 1472 | 1485 | .arena = &local.mutate.arena, |
| 1473 | 1486 | .mutate = &local.mutate.maps, |
| 1474 | 1487 | .list = &local.shared.maps, |
| 1475 | 1488 | }; |
| 1476 | 1489 | } |
| 1477 | 1490 | |
| 1478 | pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable { | |
| 1491 | pub fn getMutableNavs(local: *Local, gpa: Allocator, io: Io) Navs.Mutable { | |
| 1479 | 1492 | return .{ |
| 1480 | 1493 | .gpa = gpa, |
| 1494 | .io = io, | |
| 1481 | 1495 | .arena = &local.mutate.arena, |
| 1482 | 1496 | .mutate = &local.mutate.navs, |
| 1483 | 1497 | .list = &local.shared.navs, |
| 1484 | 1498 | }; |
| 1485 | 1499 | } |
| 1486 | 1500 | |
| 1487 | pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator) ComptimeUnits.Mutable { | |
| 1501 | pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator, io: Io) ComptimeUnits.Mutable { | |
| 1488 | 1502 | return .{ |
| 1489 | 1503 | .gpa = gpa, |
| 1504 | .io = io, | |
| 1490 | 1505 | .arena = &local.mutate.arena, |
| 1491 | 1506 | .mutate = &local.mutate.comptime_units, |
| 1492 | 1507 | .list = &local.shared.comptime_units, |
| ... | ... | @@ -1503,9 +1518,10 @@ const Local = struct { |
| 1503 | 1518 | /// serialization trivial. |
| 1504 | 1519 | /// * It provides a unique integer to be used for anonymous symbol names, avoiding |
| 1505 | 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 | 1522 | return .{ |
| 1508 | 1523 | .gpa = gpa, |
| 1524 | .io = io, | |
| 1509 | 1525 | .arena = &local.mutate.arena, |
| 1510 | 1526 | .mutate = &local.mutate.namespaces.buckets_list, |
| 1511 | 1527 | .list = &local.shared.namespaces, |
| ... | ... | @@ -1535,11 +1551,63 @@ const Shard = struct { |
| 1535 | 1551 | }, |
| 1536 | 1552 | |
| 1537 | 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 | 1561 | len: u32, |
| 1540 | 1562 | |
| 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 | 1609 | const empty: Mutate = .{ |
| 1542 | .mutex = std.Thread.Mutex.Recursive.init, | |
| 1610 | .mutex = .init, | |
| 1543 | 1611 | .len = 0, |
| 1544 | 1612 | }; |
| 1545 | 1613 | }; |
| ... | ... | @@ -1896,7 +1964,7 @@ pub const NullTerminatedString = enum(u32) { |
| 1896 | 1964 | ip: *const InternPool, |
| 1897 | 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 | 1968 | const slice = data.string.toSlice(data.ip); |
| 1901 | 1969 | if (!data.id) { |
| 1902 | 1970 | try writer.writeAll(slice); |
| ... | ... | @@ -2323,10 +2391,10 @@ pub const Key = union(enum) { |
| 2323 | 2391 | return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered); |
| 2324 | 2392 | } |
| 2325 | 2393 | |
| 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 | 2395 | const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; |
| 2328 | extra_mutex.lock(); | |
| 2329 | defer extra_mutex.unlock(); | |
| 2396 | extra_mutex.lockUncancelable(io); | |
| 2397 | defer extra_mutex.unlock(io); | |
| 2330 | 2398 | |
| 2331 | 2399 | const analysis_ptr = func.analysisPtr(ip); |
| 2332 | 2400 | var analysis = analysis_ptr.*; |
| ... | ... | @@ -2334,10 +2402,10 @@ pub const Key = union(enum) { |
| 2334 | 2402 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); |
| 2335 | 2403 | } |
| 2336 | 2404 | |
| 2337 | pub fn setAnalyzed(func: Func, ip: *InternPool) void { | |
| 2405 | pub fn setAnalyzed(func: Func, ip: *InternPool, io: Io) void { | |
| 2338 | 2406 | const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; |
| 2339 | extra_mutex.lock(); | |
| 2340 | defer extra_mutex.unlock(); | |
| 2407 | extra_mutex.lockUncancelable(io); | |
| 2408 | defer extra_mutex.unlock(io); | |
| 2341 | 2409 | |
| 2342 | 2410 | const analysis_ptr = func.analysisPtr(ip); |
| 2343 | 2411 | var analysis = analysis_ptr.*; |
| ... | ... | @@ -2365,10 +2433,10 @@ pub const Key = union(enum) { |
| 2365 | 2433 | return @atomicLoad(u32, func.branchQuotaPtr(ip), .unordered); |
| 2366 | 2434 | } |
| 2367 | 2435 | |
| 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 | 2437 | const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; |
| 2370 | extra_mutex.lock(); | |
| 2371 | defer extra_mutex.unlock(); | |
| 2438 | extra_mutex.lockUncancelable(io); | |
| 2439 | defer extra_mutex.unlock(io); | |
| 2372 | 2440 | |
| 2373 | 2441 | const branch_quota_ptr = func.branchQuotaPtr(ip); |
| 2374 | 2442 | @atomicStore(u32, branch_quota_ptr, @max(branch_quota_ptr.*, new_branch_quota), .release); |
| ... | ... | @@ -2385,10 +2453,10 @@ pub const Key = union(enum) { |
| 2385 | 2453 | return @atomicLoad(Index, func.resolvedErrorSetPtr(ip), .unordered); |
| 2386 | 2454 | } |
| 2387 | 2455 | |
| 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 | 2457 | const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; |
| 2390 | extra_mutex.lock(); | |
| 2391 | defer extra_mutex.unlock(); | |
| 2458 | extra_mutex.lockUncancelable(io); | |
| 2459 | defer extra_mutex.unlock(io); | |
| 2392 | 2460 | |
| 2393 | 2461 | @atomicStore(Index, func.resolvedErrorSetPtr(ip), ies, .release); |
| 2394 | 2462 | } |
| ... | ... | @@ -3349,10 +3417,10 @@ pub const LoadedUnionType = struct { |
| 3349 | 3417 | return @atomicLoad(Index, u.tagTypePtr(ip), .unordered); |
| 3350 | 3418 | } |
| 3351 | 3419 | |
| 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 | 3421 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3354 | extra_mutex.lock(); | |
| 3355 | defer extra_mutex.unlock(); | |
| 3422 | extra_mutex.lockUncancelable(io); | |
| 3423 | defer extra_mutex.unlock(io); | |
| 3356 | 3424 | |
| 3357 | 3425 | @atomicStore(Index, u.tagTypePtr(ip), tag_type, .release); |
| 3358 | 3426 | } |
| ... | ... | @@ -3368,10 +3436,10 @@ pub const LoadedUnionType = struct { |
| 3368 | 3436 | return @atomicLoad(Tag.TypeUnion.Flags, u.flagsPtr(ip), .unordered); |
| 3369 | 3437 | } |
| 3370 | 3438 | |
| 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 | 3440 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3373 | extra_mutex.lock(); | |
| 3374 | defer extra_mutex.unlock(); | |
| 3441 | extra_mutex.lockUncancelable(io); | |
| 3442 | defer extra_mutex.unlock(io); | |
| 3375 | 3443 | |
| 3376 | 3444 | const flags_ptr = u.flagsPtr(ip); |
| 3377 | 3445 | var flags = flags_ptr.*; |
| ... | ... | @@ -3379,10 +3447,10 @@ pub const LoadedUnionType = struct { |
| 3379 | 3447 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); |
| 3380 | 3448 | } |
| 3381 | 3449 | |
| 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 | 3451 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3384 | extra_mutex.lock(); | |
| 3385 | defer extra_mutex.unlock(); | |
| 3452 | extra_mutex.lockUncancelable(io); | |
| 3453 | defer extra_mutex.unlock(io); | |
| 3386 | 3454 | |
| 3387 | 3455 | const flags_ptr = u.flagsPtr(ip); |
| 3388 | 3456 | var flags = flags_ptr.*; |
| ... | ... | @@ -3390,10 +3458,10 @@ pub const LoadedUnionType = struct { |
| 3390 | 3458 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); |
| 3391 | 3459 | } |
| 3392 | 3460 | |
| 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 | 3462 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3395 | extra_mutex.lock(); | |
| 3396 | defer extra_mutex.unlock(); | |
| 3463 | extra_mutex.lockUncancelable(io); | |
| 3464 | defer extra_mutex.unlock(io); | |
| 3397 | 3465 | |
| 3398 | 3466 | const flags_ptr = u.flagsPtr(ip); |
| 3399 | 3467 | var flags = flags_ptr.*; |
| ... | ... | @@ -3401,10 +3469,10 @@ pub const LoadedUnionType = struct { |
| 3401 | 3469 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); |
| 3402 | 3470 | } |
| 3403 | 3471 | |
| 3404 | pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool) bool { | |
| 3472 | pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io) bool { | |
| 3405 | 3473 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3406 | extra_mutex.lock(); | |
| 3407 | defer extra_mutex.unlock(); | |
| 3474 | extra_mutex.lockUncancelable(io); | |
| 3475 | defer extra_mutex.unlock(io); | |
| 3408 | 3476 | |
| 3409 | 3477 | const flags_ptr = u.flagsPtr(ip); |
| 3410 | 3478 | var flags = flags_ptr.*; |
| ... | ... | @@ -3419,10 +3487,10 @@ pub const LoadedUnionType = struct { |
| 3419 | 3487 | return u.flagsUnordered(ip).requires_comptime; |
| 3420 | 3488 | } |
| 3421 | 3489 | |
| 3422 | pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool) RequiresComptime { | |
| 3490 | pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool, io: Io) RequiresComptime { | |
| 3423 | 3491 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3424 | extra_mutex.lock(); | |
| 3425 | defer extra_mutex.unlock(); | |
| 3492 | extra_mutex.lockUncancelable(io); | |
| 3493 | defer extra_mutex.unlock(io); | |
| 3426 | 3494 | |
| 3427 | 3495 | const flags_ptr = u.flagsPtr(ip); |
| 3428 | 3496 | var flags = flags_ptr.*; |
| ... | ... | @@ -3433,12 +3501,12 @@ pub const LoadedUnionType = struct { |
| 3433 | 3501 | return flags.requires_comptime; |
| 3434 | 3502 | } |
| 3435 | 3503 | |
| 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 | 3505 | assert(requires_comptime != .wip); // see setRequiresComptimeWip |
| 3438 | 3506 | |
| 3439 | 3507 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3440 | extra_mutex.lock(); | |
| 3441 | defer extra_mutex.unlock(); | |
| 3508 | extra_mutex.lockUncancelable(io); | |
| 3509 | defer extra_mutex.unlock(io); | |
| 3442 | 3510 | |
| 3443 | 3511 | const flags_ptr = u.flagsPtr(ip); |
| 3444 | 3512 | var flags = flags_ptr.*; |
| ... | ... | @@ -3446,10 +3514,10 @@ pub const LoadedUnionType = struct { |
| 3446 | 3514 | @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); |
| 3447 | 3515 | } |
| 3448 | 3516 | |
| 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 | 3518 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3451 | extra_mutex.lock(); | |
| 3452 | defer extra_mutex.unlock(); | |
| 3519 | extra_mutex.lockUncancelable(io); | |
| 3520 | defer extra_mutex.unlock(io); | |
| 3453 | 3521 | |
| 3454 | 3522 | const flags_ptr = u.flagsPtr(ip); |
| 3455 | 3523 | var flags = flags_ptr.*; |
| ... | ... | @@ -3495,10 +3563,10 @@ pub const LoadedUnionType = struct { |
| 3495 | 3563 | return self.flagsUnordered(ip).status.haveLayout(); |
| 3496 | 3564 | } |
| 3497 | 3565 | |
| 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 | 3567 | const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; |
| 3500 | extra_mutex.lock(); | |
| 3501 | defer extra_mutex.unlock(); | |
| 3568 | extra_mutex.lockUncancelable(io); | |
| 3569 | defer extra_mutex.unlock(io); | |
| 3502 | 3570 | |
| 3503 | 3571 | @atomicStore(u32, u.sizePtr(ip), size, .unordered); |
| 3504 | 3572 | @atomicStore(u32, u.paddingPtr(ip), padding, .unordered); |
| ... | ... | @@ -3767,10 +3835,10 @@ pub const LoadedStructType = struct { |
| 3767 | 3835 | return s.flagsUnordered(ip).requires_comptime; |
| 3768 | 3836 | } |
| 3769 | 3837 | |
| 3770 | pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool) RequiresComptime { | |
| 3838 | pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool, io: Io) RequiresComptime { | |
| 3771 | 3839 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3772 | extra_mutex.lock(); | |
| 3773 | defer extra_mutex.unlock(); | |
| 3840 | extra_mutex.lockUncancelable(io); | |
| 3841 | defer extra_mutex.unlock(io); | |
| 3774 | 3842 | |
| 3775 | 3843 | const flags_ptr = s.flagsPtr(ip); |
| 3776 | 3844 | var flags = flags_ptr.*; |
| ... | ... | @@ -3781,12 +3849,12 @@ pub const LoadedStructType = struct { |
| 3781 | 3849 | return flags.requires_comptime; |
| 3782 | 3850 | } |
| 3783 | 3851 | |
| 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 | 3853 | assert(requires_comptime != .wip); // see setRequiresComptimeWip |
| 3786 | 3854 | |
| 3787 | 3855 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3788 | extra_mutex.lock(); | |
| 3789 | defer extra_mutex.unlock(); | |
| 3856 | extra_mutex.lockUncancelable(io); | |
| 3857 | defer extra_mutex.unlock(io); | |
| 3790 | 3858 | |
| 3791 | 3859 | const flags_ptr = s.flagsPtr(ip); |
| 3792 | 3860 | var flags = flags_ptr.*; |
| ... | ... | @@ -3794,12 +3862,12 @@ pub const LoadedStructType = struct { |
| 3794 | 3862 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); |
| 3795 | 3863 | } |
| 3796 | 3864 | |
| 3797 | pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool) bool { | |
| 3865 | pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3798 | 3866 | if (s.layout == .@"packed") return false; |
| 3799 | 3867 | |
| 3800 | 3868 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3801 | extra_mutex.lock(); | |
| 3802 | defer extra_mutex.unlock(); | |
| 3869 | extra_mutex.lockUncancelable(io); | |
| 3870 | defer extra_mutex.unlock(io); | |
| 3803 | 3871 | |
| 3804 | 3872 | const flags_ptr = s.flagsPtr(ip); |
| 3805 | 3873 | var flags = flags_ptr.*; |
| ... | ... | @@ -3810,12 +3878,12 @@ pub const LoadedStructType = struct { |
| 3810 | 3878 | return flags.field_types_wip; |
| 3811 | 3879 | } |
| 3812 | 3880 | |
| 3813 | pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool) bool { | |
| 3881 | pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3814 | 3882 | if (s.layout == .@"packed") return false; |
| 3815 | 3883 | |
| 3816 | 3884 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3817 | extra_mutex.lock(); | |
| 3818 | defer extra_mutex.unlock(); | |
| 3885 | extra_mutex.lockUncancelable(io); | |
| 3886 | defer extra_mutex.unlock(io); | |
| 3819 | 3887 | |
| 3820 | 3888 | const flags_ptr = s.flagsPtr(ip); |
| 3821 | 3889 | var flags = flags_ptr.*; |
| ... | ... | @@ -3826,12 +3894,12 @@ pub const LoadedStructType = struct { |
| 3826 | 3894 | return flags.field_types_wip; |
| 3827 | 3895 | } |
| 3828 | 3896 | |
| 3829 | pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool) void { | |
| 3897 | pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 3830 | 3898 | if (s.layout == .@"packed") return; |
| 3831 | 3899 | |
| 3832 | 3900 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3833 | extra_mutex.lock(); | |
| 3834 | defer extra_mutex.unlock(); | |
| 3901 | extra_mutex.lockUncancelable(io); | |
| 3902 | defer extra_mutex.unlock(io); | |
| 3835 | 3903 | |
| 3836 | 3904 | const flags_ptr = s.flagsPtr(ip); |
| 3837 | 3905 | var flags = flags_ptr.*; |
| ... | ... | @@ -3839,12 +3907,12 @@ pub const LoadedStructType = struct { |
| 3839 | 3907 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); |
| 3840 | 3908 | } |
| 3841 | 3909 | |
| 3842 | pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool) bool { | |
| 3910 | pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3843 | 3911 | if (s.layout == .@"packed") return false; |
| 3844 | 3912 | |
| 3845 | 3913 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3846 | extra_mutex.lock(); | |
| 3847 | defer extra_mutex.unlock(); | |
| 3914 | extra_mutex.lockUncancelable(io); | |
| 3915 | defer extra_mutex.unlock(io); | |
| 3848 | 3916 | |
| 3849 | 3917 | const flags_ptr = s.flagsPtr(ip); |
| 3850 | 3918 | var flags = flags_ptr.*; |
| ... | ... | @@ -3855,12 +3923,12 @@ pub const LoadedStructType = struct { |
| 3855 | 3923 | return flags.layout_wip; |
| 3856 | 3924 | } |
| 3857 | 3925 | |
| 3858 | pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool) void { | |
| 3926 | pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 3859 | 3927 | if (s.layout == .@"packed") return; |
| 3860 | 3928 | |
| 3861 | 3929 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3862 | extra_mutex.lock(); | |
| 3863 | defer extra_mutex.unlock(); | |
| 3930 | extra_mutex.lockUncancelable(io); | |
| 3931 | defer extra_mutex.unlock(io); | |
| 3864 | 3932 | |
| 3865 | 3933 | const flags_ptr = s.flagsPtr(ip); |
| 3866 | 3934 | var flags = flags_ptr.*; |
| ... | ... | @@ -3868,10 +3936,10 @@ pub const LoadedStructType = struct { |
| 3868 | 3936 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); |
| 3869 | 3937 | } |
| 3870 | 3938 | |
| 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 | 3940 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3873 | extra_mutex.lock(); | |
| 3874 | defer extra_mutex.unlock(); | |
| 3941 | extra_mutex.lockUncancelable(io); | |
| 3942 | defer extra_mutex.unlock(io); | |
| 3875 | 3943 | |
| 3876 | 3944 | const flags_ptr = s.flagsPtr(ip); |
| 3877 | 3945 | var flags = flags_ptr.*; |
| ... | ... | @@ -3879,10 +3947,10 @@ pub const LoadedStructType = struct { |
| 3879 | 3947 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); |
| 3880 | 3948 | } |
| 3881 | 3949 | |
| 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 | 3951 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3884 | extra_mutex.lock(); | |
| 3885 | defer extra_mutex.unlock(); | |
| 3952 | extra_mutex.lockUncancelable(io); | |
| 3953 | defer extra_mutex.unlock(io); | |
| 3886 | 3954 | |
| 3887 | 3955 | const flags_ptr = s.flagsPtr(ip); |
| 3888 | 3956 | var flags = flags_ptr.*; |
| ... | ... | @@ -3894,10 +3962,10 @@ pub const LoadedStructType = struct { |
| 3894 | 3962 | return flags.field_types_wip; |
| 3895 | 3963 | } |
| 3896 | 3964 | |
| 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 | 3966 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3899 | extra_mutex.lock(); | |
| 3900 | defer extra_mutex.unlock(); | |
| 3967 | extra_mutex.lockUncancelable(io); | |
| 3968 | defer extra_mutex.unlock(io); | |
| 3901 | 3969 | |
| 3902 | 3970 | const flags_ptr = s.flagsPtr(ip); |
| 3903 | 3971 | var flags = flags_ptr.*; |
| ... | ... | @@ -3911,12 +3979,12 @@ pub const LoadedStructType = struct { |
| 3911 | 3979 | return flags.alignment_wip; |
| 3912 | 3980 | } |
| 3913 | 3981 | |
| 3914 | pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool) void { | |
| 3982 | pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 3915 | 3983 | if (s.layout == .@"packed") return; |
| 3916 | 3984 | |
| 3917 | 3985 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3918 | extra_mutex.lock(); | |
| 3919 | defer extra_mutex.unlock(); | |
| 3986 | extra_mutex.lockUncancelable(io); | |
| 3987 | defer extra_mutex.unlock(io); | |
| 3920 | 3988 | |
| 3921 | 3989 | const flags_ptr = s.flagsPtr(ip); |
| 3922 | 3990 | var flags = flags_ptr.*; |
| ... | ... | @@ -3924,10 +3992,10 @@ pub const LoadedStructType = struct { |
| 3924 | 3992 | @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); |
| 3925 | 3993 | } |
| 3926 | 3994 | |
| 3927 | pub fn setInitsWip(s: LoadedStructType, ip: *InternPool) bool { | |
| 3995 | pub fn setInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3928 | 3996 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3929 | extra_mutex.lock(); | |
| 3930 | defer extra_mutex.unlock(); | |
| 3997 | extra_mutex.lockUncancelable(io); | |
| 3998 | defer extra_mutex.unlock(io); | |
| 3931 | 3999 | |
| 3932 | 4000 | switch (s.layout) { |
| 3933 | 4001 | .@"packed" => { |
| ... | ... | @@ -3951,10 +4019,10 @@ pub const LoadedStructType = struct { |
| 3951 | 4019 | } |
| 3952 | 4020 | } |
| 3953 | 4021 | |
| 3954 | pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool) void { | |
| 4022 | pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 3955 | 4023 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3956 | extra_mutex.lock(); | |
| 3957 | defer extra_mutex.unlock(); | |
| 4024 | extra_mutex.lockUncancelable(io); | |
| 4025 | defer extra_mutex.unlock(io); | |
| 3958 | 4026 | |
| 3959 | 4027 | switch (s.layout) { |
| 3960 | 4028 | .@"packed" => { |
| ... | ... | @@ -3972,12 +4040,12 @@ pub const LoadedStructType = struct { |
| 3972 | 4040 | } |
| 3973 | 4041 | } |
| 3974 | 4042 | |
| 3975 | pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool) bool { | |
| 4043 | pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) bool { | |
| 3976 | 4044 | if (s.layout == .@"packed") return true; |
| 3977 | 4045 | |
| 3978 | 4046 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3979 | extra_mutex.lock(); | |
| 3980 | defer extra_mutex.unlock(); | |
| 4047 | extra_mutex.lockUncancelable(io); | |
| 4048 | defer extra_mutex.unlock(io); | |
| 3981 | 4049 | |
| 3982 | 4050 | const flags_ptr = s.flagsPtr(ip); |
| 3983 | 4051 | var flags = flags_ptr.*; |
| ... | ... | @@ -3988,10 +4056,10 @@ pub const LoadedStructType = struct { |
| 3988 | 4056 | return flags.fully_resolved; |
| 3989 | 4057 | } |
| 3990 | 4058 | |
| 3991 | pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool) void { | |
| 4059 | pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 3992 | 4060 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 3993 | extra_mutex.lock(); | |
| 3994 | defer extra_mutex.unlock(); | |
| 4061 | extra_mutex.lockUncancelable(io); | |
| 4062 | defer extra_mutex.unlock(io); | |
| 3995 | 4063 | |
| 3996 | 4064 | const flags_ptr = s.flagsPtr(ip); |
| 3997 | 4065 | var flags = flags_ptr.*; |
| ... | ... | @@ -4027,10 +4095,10 @@ pub const LoadedStructType = struct { |
| 4027 | 4095 | return @atomicLoad(Index, s.backingIntTypePtr(ip), .unordered); |
| 4028 | 4096 | } |
| 4029 | 4097 | |
| 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 | 4099 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 4032 | extra_mutex.lock(); | |
| 4033 | defer extra_mutex.unlock(); | |
| 4100 | extra_mutex.lockUncancelable(io); | |
| 4101 | defer extra_mutex.unlock(io); | |
| 4034 | 4102 | |
| 4035 | 4103 | @atomicStore(Index, s.backingIntTypePtr(ip), backing_int_ty, .release); |
| 4036 | 4104 | } |
| ... | ... | @@ -4054,10 +4122,10 @@ pub const LoadedStructType = struct { |
| 4054 | 4122 | }; |
| 4055 | 4123 | } |
| 4056 | 4124 | |
| 4057 | pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool) void { | |
| 4125 | pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool, io: Io) void { | |
| 4058 | 4126 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 4059 | extra_mutex.lock(); | |
| 4060 | defer extra_mutex.unlock(); | |
| 4127 | extra_mutex.lockUncancelable(io); | |
| 4128 | defer extra_mutex.unlock(io); | |
| 4061 | 4129 | |
| 4062 | 4130 | switch (s.layout) { |
| 4063 | 4131 | .@"packed" => { |
| ... | ... | @@ -4082,10 +4150,10 @@ pub const LoadedStructType = struct { |
| 4082 | 4150 | }; |
| 4083 | 4151 | } |
| 4084 | 4152 | |
| 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 | 4154 | const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; |
| 4087 | extra_mutex.lock(); | |
| 4088 | defer extra_mutex.unlock(); | |
| 4155 | extra_mutex.lockUncancelable(io); | |
| 4156 | defer extra_mutex.unlock(io); | |
| 4089 | 4157 | |
| 4090 | 4158 | @atomicStore(u32, s.sizePtr(ip), size, .unordered); |
| 4091 | 4159 | const flags_ptr = s.flagsPtr(ip); |
| ... | ... | @@ -6826,8 +6894,8 @@ pub const MemoizedCall = struct { |
| 6826 | 6894 | branch_count: u32, |
| 6827 | 6895 | }; |
| 6828 | 6896 | |
| 6829 | pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { | |
| 6830 | errdefer ip.deinit(gpa); | |
| 6897 | pub fn init(ip: *InternPool, gpa: Allocator, io: Io, available_threads: usize) !void { | |
| 6898 | errdefer ip.deinit(gpa, io); | |
| 6831 | 6899 | assert(ip.locals.len == 0 and ip.shards.len == 0); |
| 6832 | 6900 | assert(available_threads > 0 and available_threads <= std.math.maxInt(u8)); |
| 6833 | 6901 | |
| ... | ... | @@ -6865,7 +6933,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 6865 | 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}); | |
| 6869 | 6937 | |
| 6870 | 6938 | ip.tid_width = @intCast(std.math.log2_int_ceil(usize, used_threads)); |
| 6871 | 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 | 6942 | ip.shards = try gpa.alloc(Shard, @as(usize, 1) << ip.tid_width); |
| 6875 | 6943 | @memset(ip.shards, .{ |
| 6876 | 6944 | .shared = .{ |
| 6877 | .map = Shard.Map(Index).empty, | |
| 6878 | .string_map = Shard.Map(OptionalNullTerminatedString).empty, | |
| 6879 | .tracked_inst_map = Shard.Map(TrackedInst.Index.Optional).empty, | |
| 6945 | .map = .empty, | |
| 6946 | .string_map = .empty, | |
| 6947 | .tracked_inst_map = .empty, | |
| 6880 | 6948 | }, |
| 6881 | 6949 | .mutate = .{ |
| 6882 | .map = Shard.Mutate.empty, | |
| 6883 | .string_map = Shard.Mutate.empty, | |
| 6884 | .tracked_inst_map = Shard.Mutate.empty, | |
| 6950 | .map = .empty, | |
| 6951 | .string_map = .empty, | |
| 6952 | .tracked_inst_map = .empty, | |
| 6885 | 6953 | }, |
| 6886 | 6954 | }); |
| 6887 | 6955 | |
| 6888 | 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); | |
| 6890 | 6958 | |
| 6891 | 6959 | // This inserts all the statically-known values into the intern pool in the |
| 6892 | 6960 | // order expected. |
| 6893 | 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 | 6963 | .types = &.{}, |
| 6896 | 6964 | .values = &.{}, |
| 6897 | 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 | }; |
| 6900 | 6968 | |
| 6901 | 6969 | if (std.debug.runtime_safety) { |
| ... | ... | @@ -6905,7 +6973,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 6905 | 6973 | } |
| 6906 | 6974 | } |
| 6907 | 6975 | |
| 6908 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { | |
| 6976 | pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void { | |
| 6909 | 6977 | if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null); |
| 6910 | 6978 | |
| 6911 | 6979 | ip.src_hash_deps.deinit(gpa); |
| ... | ... | @@ -6940,7 +7008,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 6940 | 7008 | namespace.test_decls.deinit(gpa); |
| 6941 | 7009 | } |
| 6942 | 7010 | }; |
| 6943 | const maps = local.getMutableMaps(gpa); | |
| 7011 | const maps = local.getMutableMaps(gpa, io); | |
| 6944 | 7012 | if (maps.mutate.len > 0) for (maps.view().items(.@"0")) |*map| map.deinit(gpa); |
| 6945 | 7013 | local.mutate.arena.promote(gpa).deinit(); |
| 6946 | 7014 | } |
| ... | ... | @@ -7645,6 +7713,7 @@ const GetOrPutKey = union(enum) { |
| 7645 | 7713 | new: struct { |
| 7646 | 7714 | ip: *InternPool, |
| 7647 | 7715 | tid: Zcu.PerThread.Id, |
| 7716 | io: Io, | |
| 7648 | 7717 | shard: *Shard, |
| 7649 | 7718 | map_index: u32, |
| 7650 | 7719 | }, |
| ... | ... | @@ -7679,7 +7748,7 @@ const GetOrPutKey = union(enum) { |
| 7679 | 7748 | .new => |info| { |
| 7680 | 7749 | assert(info.shard.shared.map.entries[info.map_index].value == index); |
| 7681 | 7750 | info.shard.mutate.map.len += 1; |
| 7682 | info.shard.mutate.map.mutex.unlock(); | |
| 7751 | info.shard.mutate.map.mutex.unlock(info.io); | |
| 7683 | 7752 | gop.* = .{ .existing = index }; |
| 7684 | 7753 | }, |
| 7685 | 7754 | } |
| ... | ... | @@ -7688,7 +7757,7 @@ const GetOrPutKey = union(enum) { |
| 7688 | 7757 | fn cancel(gop: *GetOrPutKey) void { |
| 7689 | 7758 | switch (gop.*) { |
| 7690 | 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 | 7762 | gop.* = .{ .existing = undefined }; |
| 7694 | 7763 | } |
| ... | ... | @@ -7705,14 +7774,16 @@ const GetOrPutKey = union(enum) { |
| 7705 | 7774 | fn getOrPutKey( |
| 7706 | 7775 | ip: *InternPool, |
| 7707 | 7776 | gpa: Allocator, |
| 7777 | io: Io, | |
| 7708 | 7778 | tid: Zcu.PerThread.Id, |
| 7709 | 7779 | key: Key, |
| 7710 | 7780 | ) Allocator.Error!GetOrPutKey { |
| 7711 | return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, key, 0); | |
| 7781 | return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, key, 0); | |
| 7712 | 7782 | } |
| 7713 | 7783 | fn getOrPutKeyEnsuringAdditionalCapacity( |
| 7714 | 7784 | ip: *InternPool, |
| 7715 | 7785 | gpa: Allocator, |
| 7786 | io: Io, | |
| 7716 | 7787 | tid: Zcu.PerThread.Id, |
| 7717 | 7788 | key: Key, |
| 7718 | 7789 | additional_capacity: u32, |
| ... | ... | @@ -7733,8 +7804,8 @@ fn getOrPutKeyEnsuringAdditionalCapacity( |
| 7733 | 7804 | if (index.unwrap(ip).getTag(ip) == .removed) continue; |
| 7734 | 7805 | if (ip.indexToKey(index).eql(key, ip)) return .{ .existing = index }; |
| 7735 | 7806 | } |
| 7736 | shard.mutate.map.mutex.lock(); | |
| 7737 | errdefer shard.mutate.map.mutex.unlock(); | |
| 7807 | shard.mutate.map.mutex.lock(io, tid); | |
| 7808 | errdefer shard.mutate.map.mutex.unlock(io); | |
| 7738 | 7809 | if (map.entries != shard.shared.map.entries) { |
| 7739 | 7810 | map = shard.shared.map; |
| 7740 | 7811 | map_mask = map.header().mask(); |
| ... | ... | @@ -7747,7 +7818,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity( |
| 7747 | 7818 | if (index == .none) break; |
| 7748 | 7819 | if (entry.hash != hash) continue; |
| 7749 | 7820 | if (ip.indexToKey(index).eql(key, ip)) { |
| 7750 | defer shard.mutate.map.mutex.unlock(); | |
| 7821 | defer shard.mutate.map.mutex.unlock(io); | |
| 7751 | 7822 | return .{ .existing = index }; |
| 7752 | 7823 | } |
| 7753 | 7824 | } |
| ... | ... | @@ -7801,6 +7872,7 @@ fn getOrPutKeyEnsuringAdditionalCapacity( |
| 7801 | 7872 | return .{ .new = .{ |
| 7802 | 7873 | .ip = ip, |
| 7803 | 7874 | .tid = tid, |
| 7875 | .io = io, | |
| 7804 | 7876 | .shard = shard, |
| 7805 | 7877 | .map_index = map_index, |
| 7806 | 7878 | } }; |
| ... | ... | @@ -7815,14 +7887,15 @@ fn getOrPutKeyEnsuringAdditionalCapacity( |
| 7815 | 7887 | /// will be cleaned up when the `Zcu` undergoes garbage collection. |
| 7816 | 7888 | fn putKeyReplace( |
| 7817 | 7889 | ip: *InternPool, |
| 7890 | io: Io, | |
| 7818 | 7891 | tid: Zcu.PerThread.Id, |
| 7819 | 7892 | key: Key, |
| 7820 | 7893 | ) GetOrPutKey { |
| 7821 | 7894 | const full_hash = key.hash64(ip); |
| 7822 | 7895 | const hash: u32 = @truncate(full_hash >> 32); |
| 7823 | 7896 | const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))]; |
| 7824 | shard.mutate.map.mutex.lock(); | |
| 7825 | errdefer shard.mutate.map.mutex.unlock(); | |
| 7897 | shard.mutate.map.mutex.lock(io, tid); | |
| 7898 | errdefer shard.mutate.map.mutex.unlock(io); | |
| 7826 | 7899 | const map = shard.shared.map; |
| 7827 | 7900 | const map_mask = map.header().mask(); |
| 7828 | 7901 | var map_index = hash; |
| ... | ... | @@ -7838,18 +7911,19 @@ fn putKeyReplace( |
| 7838 | 7911 | return .{ .new = .{ |
| 7839 | 7912 | .ip = ip, |
| 7840 | 7913 | .tid = tid, |
| 7914 | .io = io, | |
| 7841 | 7915 | .shard = shard, |
| 7842 | 7916 | .map_index = map_index, |
| 7843 | 7917 | } }; |
| 7844 | 7918 | } |
| 7845 | 7919 | |
| 7846 | pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index { | |
| 7847 | var gop = try ip.getOrPutKey(gpa, tid, key); | |
| 7920 | pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index { | |
| 7921 | var gop = try ip.getOrPutKey(gpa, io, tid, key); | |
| 7848 | 7922 | defer gop.deinit(); |
| 7849 | 7923 | if (gop == .existing) return gop.existing; |
| 7850 | 7924 | const local = ip.getLocal(tid); |
| 7851 | const items = local.getMutableItems(gpa); | |
| 7852 | const extra = local.getMutableExtra(gpa); | |
| 7925 | const items = local.getMutableItems(gpa, io); | |
| 7926 | const extra = local.getMutableExtra(gpa, io); | |
| 7853 | 7927 | try items.ensureUnusedCapacity(1); |
| 7854 | 7928 | switch (key) { |
| 7855 | 7929 | .int_type => |int_type| { |
| ... | ... | @@ -7870,8 +7944,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 7870 | 7944 | gop.cancel(); |
| 7871 | 7945 | var new_key = key; |
| 7872 | 7946 | new_key.ptr_type.flags.size = .many; |
| 7873 | const ptr_type_index = try ip.get(gpa, tid, new_key); | |
| 7874 | gop = try ip.getOrPutKey(gpa, tid, key); | |
| 7947 | const ptr_type_index = try ip.get(gpa, io, tid, new_key); | |
| 7948 | gop = try ip.getOrPutKey(gpa, io, tid, key); | |
| 7875 | 7949 | |
| 7876 | 7950 | try items.ensureUnusedCapacity(1); |
| 7877 | 7951 | items.appendAssumeCapacity(.{ |
| ... | ... | @@ -7953,7 +8027,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 7953 | 8027 | assert(error_set_type.names_map == .none); |
| 7954 | 8028 | assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan)); |
| 7955 | 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 | 8031 | ip.addStringsToMap(names_map, names); |
| 7958 | 8032 | const names_len = error_set_type.names.len; |
| 7959 | 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 | 8125 | gop.cancel(); |
| 8052 | 8126 | var new_key = key; |
| 8053 | 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 | 8129 | if (gop == .existing) return gop.existing; |
| 8056 | 8130 | } |
| 8057 | 8131 | break :item .{ |
| ... | ... | @@ -8123,11 +8197,11 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 8123 | 8197 | else => unreachable, |
| 8124 | 8198 | } |
| 8125 | 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 | 8201 | .ty = .usize_type, |
| 8128 | 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 | 8205 | try items.ensureUnusedCapacity(1); |
| 8132 | 8206 | items.appendAssumeCapacity(.{ |
| 8133 | 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 | 8392 | } else |_| {} |
| 8319 | 8393 | |
| 8320 | 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 | 8397 | inline .u64, .i64 => |x| { |
| 8324 | 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 | 8409 | var buf: [2]Limb = undefined; |
| 8336 | 8410 | const big_int = BigIntMutable.init(&buf, x).toConst(); |
| 8337 | 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 | 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 | 8620 | const elem = switch (aggregate.storage) { |
| 8547 | 8621 | .bytes => |bytes| elem: { |
| 8548 | 8622 | gop.cancel(); |
| 8549 | const elem = try ip.get(gpa, tid, .{ .int = .{ | |
| 8623 | const elem = try ip.get(gpa, io, tid, .{ .int = .{ | |
| 8550 | 8624 | .ty = .u8_type, |
| 8551 | 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 | 8628 | try items.ensureUnusedCapacity(1); |
| 8555 | 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 | 8644 | } |
| 8571 | 8645 | |
| 8572 | 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 | 8648 | const start = string_bytes.mutate.len; |
| 8575 | 8649 | try string_bytes.ensureUnusedCapacity(@intCast(len_including_sentinel + 1)); |
| 8576 | 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 | 8672 | }); |
| 8599 | 8673 | const string = try ip.getOrPutTrailingString( |
| 8600 | 8674 | gpa, |
| 8675 | io, | |
| 8601 | 8676 | tid, |
| 8602 | 8677 | @intCast(len_including_sentinel), |
| 8603 | 8678 | .maybe_embedded_nulls, |
| ... | ... | @@ -8647,15 +8722,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 8647 | 8722 | pub fn getUnion( |
| 8648 | 8723 | ip: *InternPool, |
| 8649 | 8724 | gpa: Allocator, |
| 8725 | io: Io, | |
| 8650 | 8726 | tid: Zcu.PerThread.Id, |
| 8651 | 8727 | un: Key.Union, |
| 8652 | 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 | 8730 | defer gop.deinit(); |
| 8655 | 8731 | if (gop == .existing) return gop.existing; |
| 8656 | 8732 | const local = ip.getLocal(tid); |
| 8657 | const items = local.getMutableItems(gpa); | |
| 8658 | const extra = local.getMutableExtra(gpa); | |
| 8733 | const items = local.getMutableItems(gpa, io); | |
| 8734 | const extra = local.getMutableExtra(gpa, io); | |
| 8659 | 8735 | try items.ensureUnusedCapacity(1); |
| 8660 | 8736 | |
| 8661 | 8737 | assert(un.ty != .none); |
| ... | ... | @@ -8706,6 +8782,7 @@ pub const UnionTypeInit = struct { |
| 8706 | 8782 | pub fn getUnionType( |
| 8707 | 8783 | ip: *InternPool, |
| 8708 | 8784 | gpa: Allocator, |
| 8785 | io: Io, | |
| 8709 | 8786 | tid: Zcu.PerThread.Id, |
| 8710 | 8787 | ini: UnionTypeInit, |
| 8711 | 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 | 8804 | } }, |
| 8728 | 8805 | } }; |
| 8729 | 8806 | var gop = if (replace_existing) |
| 8730 | ip.putKeyReplace(tid, key) | |
| 8807 | ip.putKeyReplace(io, tid, key) | |
| 8731 | 8808 | else |
| 8732 | try ip.getOrPutKey(gpa, tid, key); | |
| 8809 | try ip.getOrPutKey(gpa, io, tid, key); | |
| 8733 | 8810 | defer gop.deinit(); |
| 8734 | 8811 | if (gop == .existing) return .{ .existing = gop.existing }; |
| 8735 | 8812 | |
| 8736 | 8813 | const local = ip.getLocal(tid); |
| 8737 | const items = local.getMutableItems(gpa); | |
| 8814 | const items = local.getMutableItems(gpa, io); | |
| 8738 | 8815 | try items.ensureUnusedCapacity(1); |
| 8739 | const extra = local.getMutableExtra(gpa); | |
| 8816 | const extra = local.getMutableExtra(gpa, io); | |
| 8740 | 8817 | |
| 8741 | 8818 | const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0; |
| 8742 | 8819 | const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4); |
| ... | ... | @@ -8903,6 +8980,7 @@ pub const StructTypeInit = struct { |
| 8903 | 8980 | pub fn getStructType( |
| 8904 | 8981 | ip: *InternPool, |
| 8905 | 8982 | gpa: Allocator, |
| 8983 | io: Io, | |
| 8906 | 8984 | tid: Zcu.PerThread.Id, |
| 8907 | 8985 | ini: StructTypeInit, |
| 8908 | 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 | 9002 | } }, |
| 8925 | 9003 | } }; |
| 8926 | 9004 | var gop = if (replace_existing) |
| 8927 | ip.putKeyReplace(tid, key) | |
| 9005 | ip.putKeyReplace(io, tid, key) | |
| 8928 | 9006 | else |
| 8929 | try ip.getOrPutKey(gpa, tid, key); | |
| 9007 | try ip.getOrPutKey(gpa, io, tid, key); | |
| 8930 | 9008 | defer gop.deinit(); |
| 8931 | 9009 | if (gop == .existing) return .{ .existing = gop.existing }; |
| 8932 | 9010 | |
| 8933 | 9011 | const local = ip.getLocal(tid); |
| 8934 | const items = local.getMutableItems(gpa); | |
| 8935 | const extra = local.getMutableExtra(gpa); | |
| 9012 | const items = local.getMutableItems(gpa, io); | |
| 9013 | const extra = local.getMutableExtra(gpa, io); | |
| 8936 | 9014 | |
| 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 | 9016 | errdefer local.mutate.maps.len -= 1; |
| 8939 | 9017 | |
| 8940 | 9018 | const zir_index = switch (ini.key) { |
| ... | ... | @@ -9109,6 +9187,7 @@ pub const TupleTypeInit = struct { |
| 9109 | 9187 | pub fn getTupleType( |
| 9110 | 9188 | ip: *InternPool, |
| 9111 | 9189 | gpa: Allocator, |
| 9190 | io: Io, | |
| 9112 | 9191 | tid: Zcu.PerThread.Id, |
| 9113 | 9192 | ini: TupleTypeInit, |
| 9114 | 9193 | ) Allocator.Error!Index { |
| ... | ... | @@ -9116,8 +9195,8 @@ pub fn getTupleType( |
| 9116 | 9195 | for (ini.types) |elem| assert(elem != .none); |
| 9117 | 9196 | |
| 9118 | 9197 | const local = ip.getLocal(tid); |
| 9119 | const items = local.getMutableItems(gpa); | |
| 9120 | const extra = local.getMutableExtra(gpa); | |
| 9198 | const items = local.getMutableItems(gpa, io); | |
| 9199 | const extra = local.getMutableExtra(gpa, io); | |
| 9121 | 9200 | |
| 9122 | 9201 | const prev_extra_len = extra.mutate.len; |
| 9123 | 9202 | const fields_len: u32 = @intCast(ini.types.len); |
| ... | ... | @@ -9134,7 +9213,7 @@ pub fn getTupleType( |
| 9134 | 9213 | extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)}); |
| 9135 | 9214 | errdefer extra.mutate.len = prev_extra_len; |
| 9136 | 9215 | |
| 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 | 9217 | defer gop.deinit(); |
| 9139 | 9218 | if (gop == .existing) { |
| 9140 | 9219 | extra.mutate.len = prev_extra_len; |
| ... | ... | @@ -9166,6 +9245,7 @@ pub const GetFuncTypeKey = struct { |
| 9166 | 9245 | pub fn getFuncType( |
| 9167 | 9246 | ip: *InternPool, |
| 9168 | 9247 | gpa: Allocator, |
| 9248 | io: Io, | |
| 9169 | 9249 | tid: Zcu.PerThread.Id, |
| 9170 | 9250 | key: GetFuncTypeKey, |
| 9171 | 9251 | ) Allocator.Error!Index { |
| ... | ... | @@ -9174,9 +9254,9 @@ pub fn getFuncType( |
| 9174 | 9254 | for (key.param_types) |param_type| assert(param_type != .none); |
| 9175 | 9255 | |
| 9176 | 9256 | const local = ip.getLocal(tid); |
| 9177 | const items = local.getMutableItems(gpa); | |
| 9257 | const items = local.getMutableItems(gpa, io); | |
| 9178 | 9258 | try items.ensureUnusedCapacity(1); |
| 9179 | const extra = local.getMutableExtra(gpa); | |
| 9259 | const extra = local.getMutableExtra(gpa, io); | |
| 9180 | 9260 | |
| 9181 | 9261 | // The strategy here is to add the function type unconditionally, then to |
| 9182 | 9262 | // ask if it already exists, and if so, revert the lengths of the mutated |
| ... | ... | @@ -9207,7 +9287,7 @@ pub fn getFuncType( |
| 9207 | 9287 | extra.appendSliceAssumeCapacity(.{@ptrCast(key.param_types)}); |
| 9208 | 9288 | errdefer extra.mutate.len = prev_extra_len; |
| 9209 | 9289 | |
| 9210 | var gop = try ip.getOrPutKey(gpa, tid, .{ | |
| 9290 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ | |
| 9211 | 9291 | .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index), |
| 9212 | 9292 | }); |
| 9213 | 9293 | defer gop.deinit(); |
| ... | ... | @@ -9228,6 +9308,7 @@ pub fn getFuncType( |
| 9228 | 9308 | pub fn getExtern( |
| 9229 | 9309 | ip: *InternPool, |
| 9230 | 9310 | gpa: Allocator, |
| 9311 | io: Io, | |
| 9231 | 9312 | tid: Zcu.PerThread.Id, |
| 9232 | 9313 | /// `key.owner_nav` is ignored. |
| 9233 | 9314 | key: Key.Extern, |
| ... | ... | @@ -9236,7 +9317,7 @@ pub fn getExtern( |
| 9236 | 9317 | /// Only set if the `Nav` was newly created. |
| 9237 | 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 | 9321 | defer gop.deinit(); |
| 9241 | 9322 | if (gop == .existing) return .{ |
| 9242 | 9323 | .index = gop.existing, |
| ... | ... | @@ -9244,18 +9325,18 @@ pub fn getExtern( |
| 9244 | 9325 | }; |
| 9245 | 9326 | |
| 9246 | 9327 | const local = ip.getLocal(tid); |
| 9247 | const items = local.getMutableItems(gpa); | |
| 9248 | const extra = local.getMutableExtra(gpa); | |
| 9328 | const items = local.getMutableItems(gpa, io); | |
| 9329 | const extra = local.getMutableExtra(gpa, io); | |
| 9249 | 9330 | try items.ensureUnusedCapacity(1); |
| 9250 | 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); | |
| 9252 | 9333 | |
| 9253 | 9334 | // Predict the index the `@"extern" will live at, so we can construct the owner `Nav` before releasing the shard's mutex. |
| 9254 | 9335 | const extern_index = Index.Unwrapped.wrap(.{ |
| 9255 | 9336 | .tid = tid, |
| 9256 | 9337 | .index = items.mutate.len, |
| 9257 | 9338 | }, ip); |
| 9258 | const owner_nav = ip.createNav(gpa, tid, .{ | |
| 9339 | const owner_nav = ip.createNav(gpa, io, tid, .{ | |
| 9259 | 9340 | .name = key.name, |
| 9260 | 9341 | .fqn = key.name, |
| 9261 | 9342 | .val = extern_index, |
| ... | ... | @@ -9305,13 +9386,14 @@ pub const GetFuncDeclKey = struct { |
| 9305 | 9386 | pub fn getFuncDecl( |
| 9306 | 9387 | ip: *InternPool, |
| 9307 | 9388 | gpa: Allocator, |
| 9389 | io: Io, | |
| 9308 | 9390 | tid: Zcu.PerThread.Id, |
| 9309 | 9391 | key: GetFuncDeclKey, |
| 9310 | 9392 | ) Allocator.Error!Index { |
| 9311 | 9393 | const local = ip.getLocal(tid); |
| 9312 | const items = local.getMutableItems(gpa); | |
| 9394 | const items = local.getMutableItems(gpa, io); | |
| 9313 | 9395 | try items.ensureUnusedCapacity(1); |
| 9314 | const extra = local.getMutableExtra(gpa); | |
| 9396 | const extra = local.getMutableExtra(gpa, io); | |
| 9315 | 9397 | |
| 9316 | 9398 | // The strategy here is to add the function type unconditionally, then to |
| 9317 | 9399 | // ask if it already exists, and if so, revert the lengths of the mutated |
| ... | ... | @@ -9340,7 +9422,7 @@ pub fn getFuncDecl( |
| 9340 | 9422 | }); |
| 9341 | 9423 | errdefer extra.mutate.len = prev_extra_len; |
| 9342 | 9424 | |
| 9343 | var gop = try ip.getOrPutKey(gpa, tid, .{ | |
| 9425 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ | |
| 9344 | 9426 | .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index), |
| 9345 | 9427 | }); |
| 9346 | 9428 | defer gop.deinit(); |
| ... | ... | @@ -9387,6 +9469,7 @@ pub const GetFuncDeclIesKey = struct { |
| 9387 | 9469 | pub fn getFuncDeclIes( |
| 9388 | 9470 | ip: *InternPool, |
| 9389 | 9471 | gpa: Allocator, |
| 9472 | io: Io, | |
| 9390 | 9473 | tid: Zcu.PerThread.Id, |
| 9391 | 9474 | key: GetFuncDeclIesKey, |
| 9392 | 9475 | ) Allocator.Error!Index { |
| ... | ... | @@ -9395,9 +9478,9 @@ pub fn getFuncDeclIes( |
| 9395 | 9478 | for (key.param_types) |param_type| assert(param_type != .none); |
| 9396 | 9479 | |
| 9397 | 9480 | const local = ip.getLocal(tid); |
| 9398 | const items = local.getMutableItems(gpa); | |
| 9481 | const items = local.getMutableItems(gpa, io); | |
| 9399 | 9482 | try items.ensureUnusedCapacity(4); |
| 9400 | const extra = local.getMutableExtra(gpa); | |
| 9483 | const extra = local.getMutableExtra(gpa, io); | |
| 9401 | 9484 | |
| 9402 | 9485 | // The strategy here is to add the function decl unconditionally, then to |
| 9403 | 9486 | // ask if it already exists, and if so, revert the lengths of the mutated |
| ... | ... | @@ -9488,7 +9571,7 @@ pub fn getFuncDeclIes( |
| 9488 | 9571 | extra.mutate.len = prev_extra_len; |
| 9489 | 9572 | } |
| 9490 | 9573 | |
| 9491 | var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ | |
| 9574 | var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ | |
| 9492 | 9575 | .func = extraFuncDecl(tid, extra.list.*, func_decl_extra_index), |
| 9493 | 9576 | }, 3); |
| 9494 | 9577 | defer func_gop.deinit(); |
| ... | ... | @@ -9509,18 +9592,18 @@ pub fn getFuncDeclIes( |
| 9509 | 9592 | return func_gop.existing; |
| 9510 | 9593 | } |
| 9511 | 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 | 9596 | .error_set_type = error_set_type, |
| 9514 | 9597 | .payload_type = key.bare_return_type, |
| 9515 | 9598 | } }, 2); |
| 9516 | 9599 | defer error_union_type_gop.deinit(); |
| 9517 | 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 | 9602 | .inferred_error_set_type = func_index, |
| 9520 | 9603 | }, 1); |
| 9521 | 9604 | defer error_set_type_gop.deinit(); |
| 9522 | 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 | 9607 | .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index), |
| 9525 | 9608 | }); |
| 9526 | 9609 | defer func_ty_gop.deinit(); |
| ... | ... | @@ -9536,17 +9619,18 @@ pub fn getFuncDeclIes( |
| 9536 | 9619 | pub fn getErrorSetType( |
| 9537 | 9620 | ip: *InternPool, |
| 9538 | 9621 | gpa: Allocator, |
| 9622 | io: Io, | |
| 9539 | 9623 | tid: Zcu.PerThread.Id, |
| 9540 | 9624 | names: []const NullTerminatedString, |
| 9541 | 9625 | ) Allocator.Error!Index { |
| 9542 | 9626 | assert(std.sort.isSorted(NullTerminatedString, names, {}, NullTerminatedString.indexLessThan)); |
| 9543 | 9627 | |
| 9544 | 9628 | const local = ip.getLocal(tid); |
| 9545 | const items = local.getMutableItems(gpa); | |
| 9546 | const extra = local.getMutableExtra(gpa); | |
| 9629 | const items = local.getMutableItems(gpa, io); | |
| 9630 | const extra = local.getMutableExtra(gpa, io); | |
| 9547 | 9631 | try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).@"struct".fields.len + names.len); |
| 9548 | 9632 | |
| 9549 | const names_map = try ip.addMap(gpa, tid, names.len); | |
| 9633 | const names_map = try ip.addMap(gpa, io, tid, names.len); | |
| 9550 | 9634 | errdefer local.mutate.maps.len -= 1; |
| 9551 | 9635 | |
| 9552 | 9636 | // The strategy here is to add the type unconditionally, then to ask if it |
| ... | ... | @@ -9562,7 +9646,7 @@ pub fn getErrorSetType( |
| 9562 | 9646 | extra.appendSliceAssumeCapacity(.{@ptrCast(names)}); |
| 9563 | 9647 | errdefer extra.mutate.len = prev_extra_len; |
| 9564 | 9648 | |
| 9565 | var gop = try ip.getOrPutKey(gpa, tid, .{ | |
| 9649 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ | |
| 9566 | 9650 | .error_set_type = extraErrorSet(tid, extra.list.*, error_set_extra_index), |
| 9567 | 9651 | }); |
| 9568 | 9652 | defer gop.deinit(); |
| ... | ... | @@ -9599,16 +9683,17 @@ pub const GetFuncInstanceKey = struct { |
| 9599 | 9683 | pub fn getFuncInstance( |
| 9600 | 9684 | ip: *InternPool, |
| 9601 | 9685 | gpa: Allocator, |
| 9686 | io: Io, | |
| 9602 | 9687 | tid: Zcu.PerThread.Id, |
| 9603 | 9688 | arg: GetFuncInstanceKey, |
| 9604 | 9689 | ) Allocator.Error!Index { |
| 9605 | 9690 | if (arg.inferred_error_set) |
| 9606 | return getFuncInstanceIes(ip, gpa, tid, arg); | |
| 9691 | return getFuncInstanceIes(ip, gpa, io, tid, arg); | |
| 9607 | 9692 | |
| 9608 | 9693 | const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner); |
| 9609 | 9694 | const generic_owner_ty = ip.indexToKey(ip.funcDeclInfo(generic_owner).ty).func_type; |
| 9610 | 9695 | |
| 9611 | const func_ty = try ip.getFuncType(gpa, tid, .{ | |
| 9696 | const func_ty = try ip.getFuncType(gpa, io, tid, .{ | |
| 9612 | 9697 | .param_types = arg.param_types, |
| 9613 | 9698 | .return_type = arg.bare_return_type, |
| 9614 | 9699 | .noalias_bits = arg.noalias_bits, |
| ... | ... | @@ -9617,8 +9702,8 @@ pub fn getFuncInstance( |
| 9617 | 9702 | }); |
| 9618 | 9703 | |
| 9619 | 9704 | const local = ip.getLocal(tid); |
| 9620 | const items = local.getMutableItems(gpa); | |
| 9621 | const extra = local.getMutableExtra(gpa); | |
| 9705 | const items = local.getMutableItems(gpa, io); | |
| 9706 | const extra = local.getMutableExtra(gpa, io); | |
| 9622 | 9707 | try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncInstance).@"struct".fields.len + |
| 9623 | 9708 | arg.comptime_args.len); |
| 9624 | 9709 | |
| ... | ... | @@ -9646,7 +9731,7 @@ pub fn getFuncInstance( |
| 9646 | 9731 | }); |
| 9647 | 9732 | extra.appendSliceAssumeCapacity(.{@ptrCast(arg.comptime_args)}); |
| 9648 | 9733 | |
| 9649 | var gop = try ip.getOrPutKey(gpa, tid, .{ | |
| 9734 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ | |
| 9650 | 9735 | .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index), |
| 9651 | 9736 | }); |
| 9652 | 9737 | defer gop.deinit(); |
| ... | ... | @@ -9664,6 +9749,7 @@ pub fn getFuncInstance( |
| 9664 | 9749 | try finishFuncInstance( |
| 9665 | 9750 | ip, |
| 9666 | 9751 | gpa, |
| 9752 | io, | |
| 9667 | 9753 | tid, |
| 9668 | 9754 | extra, |
| 9669 | 9755 | generic_owner, |
| ... | ... | @@ -9676,9 +9762,10 @@ pub fn getFuncInstance( |
| 9676 | 9762 | /// This function exists separately than `getFuncInstance` because it needs to |
| 9677 | 9763 | /// create 4 new items in the InternPool atomically before it can look for an |
| 9678 | 9764 | /// existing item in the map. |
| 9679 | pub fn getFuncInstanceIes( | |
| 9765 | fn getFuncInstanceIes( | |
| 9680 | 9766 | ip: *InternPool, |
| 9681 | 9767 | gpa: Allocator, |
| 9768 | io: Io, | |
| 9682 | 9769 | tid: Zcu.PerThread.Id, |
| 9683 | 9770 | arg: GetFuncInstanceKey, |
| 9684 | 9771 | ) Allocator.Error!Index { |
| ... | ... | @@ -9688,8 +9775,8 @@ pub fn getFuncInstanceIes( |
| 9688 | 9775 | for (arg.param_types) |param_type| assert(param_type != .none); |
| 9689 | 9776 | |
| 9690 | 9777 | const local = ip.getLocal(tid); |
| 9691 | const items = local.getMutableItems(gpa); | |
| 9692 | const extra = local.getMutableExtra(gpa); | |
| 9778 | const items = local.getMutableItems(gpa, io); | |
| 9779 | const extra = local.getMutableExtra(gpa, io); | |
| 9693 | 9780 | try items.ensureUnusedCapacity(4); |
| 9694 | 9781 | |
| 9695 | 9782 | const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner); |
| ... | ... | @@ -9784,7 +9871,7 @@ pub fn getFuncInstanceIes( |
| 9784 | 9871 | extra.mutate.len = prev_extra_len; |
| 9785 | 9872 | } |
| 9786 | 9873 | |
| 9787 | var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, tid, .{ | |
| 9874 | var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ | |
| 9788 | 9875 | .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index), |
| 9789 | 9876 | }, 3); |
| 9790 | 9877 | defer func_gop.deinit(); |
| ... | ... | @@ -9795,18 +9882,18 @@ pub fn getFuncInstanceIes( |
| 9795 | 9882 | return func_gop.existing; |
| 9796 | 9883 | } |
| 9797 | 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 | 9886 | .error_set_type = error_set_type, |
| 9800 | 9887 | .payload_type = arg.bare_return_type, |
| 9801 | 9888 | } }, 2); |
| 9802 | 9889 | defer error_union_type_gop.deinit(); |
| 9803 | 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 | 9892 | .inferred_error_set_type = func_index, |
| 9806 | 9893 | }, 1); |
| 9807 | 9894 | defer error_set_type_gop.deinit(); |
| 9808 | 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 | 9897 | .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index), |
| 9811 | 9898 | }); |
| 9812 | 9899 | defer func_ty_gop.deinit(); |
| ... | ... | @@ -9814,6 +9901,7 @@ pub fn getFuncInstanceIes( |
| 9814 | 9901 | try finishFuncInstance( |
| 9815 | 9902 | ip, |
| 9816 | 9903 | gpa, |
| 9904 | io, | |
| 9817 | 9905 | tid, |
| 9818 | 9906 | extra, |
| 9819 | 9907 | generic_owner, |
| ... | ... | @@ -9831,6 +9919,7 @@ pub fn getFuncInstanceIes( |
| 9831 | 9919 | fn finishFuncInstance( |
| 9832 | 9920 | ip: *InternPool, |
| 9833 | 9921 | gpa: Allocator, |
| 9922 | io: Io, | |
| 9834 | 9923 | tid: Zcu.PerThread.Id, |
| 9835 | 9924 | extra: Local.Extra.Mutable, |
| 9836 | 9925 | generic_owner: Index, |
| ... | ... | @@ -9841,12 +9930,12 @@ fn finishFuncInstance( |
| 9841 | 9930 | const fn_namespace = fn_owner_nav.analysis.?.namespace; |
| 9842 | 9931 | |
| 9843 | 9932 | // 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 | 9934 | fn_owner_nav.name.fmt(ip), @intFromEnum(func_index), |
| 9846 | 9935 | }, .no_embedded_nulls); |
| 9847 | const nav_index = try ip.createNav(gpa, tid, .{ | |
| 9936 | const nav_index = try ip.createNav(gpa, io, tid, .{ | |
| 9848 | 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 | 9939 | .val = func_index, |
| 9851 | 9940 | .is_const = fn_owner_nav.status.fully_resolved.is_const, |
| 9852 | 9941 | .alignment = fn_owner_nav.status.fully_resolved.alignment, |
| ... | ... | @@ -9967,6 +10056,7 @@ pub const WipEnumType = struct { |
| 9967 | 10056 | pub fn getEnumType( |
| 9968 | 10057 | ip: *InternPool, |
| 9969 | 10058 | gpa: Allocator, |
| 10059 | io: Io, | |
| 9970 | 10060 | tid: Zcu.PerThread.Id, |
| 9971 | 10061 | ini: EnumTypeInit, |
| 9972 | 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 | 10078 | } }, |
| 9989 | 10079 | } }; |
| 9990 | 10080 | var gop = if (replace_existing) |
| 9991 | ip.putKeyReplace(tid, key) | |
| 10081 | ip.putKeyReplace(io, tid, key) | |
| 9992 | 10082 | else |
| 9993 | try ip.getOrPutKey(gpa, tid, key); | |
| 10083 | try ip.getOrPutKey(gpa, io, tid, key); | |
| 9994 | 10084 | defer gop.deinit(); |
| 9995 | 10085 | if (gop == .existing) return .{ .existing = gop.existing }; |
| 9996 | 10086 | |
| 9997 | 10087 | const local = ip.getLocal(tid); |
| 9998 | const items = local.getMutableItems(gpa); | |
| 10088 | const items = local.getMutableItems(gpa, io); | |
| 9999 | 10089 | try items.ensureUnusedCapacity(1); |
| 10000 | const extra = local.getMutableExtra(gpa); | |
| 10090 | const extra = local.getMutableExtra(gpa, io); | |
| 10001 | 10091 | |
| 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 | 10093 | errdefer local.mutate.maps.len -= 1; |
| 10004 | 10094 | |
| 10005 | 10095 | switch (ini.tag_mode) { |
| ... | ... | @@ -10056,7 +10146,7 @@ pub fn getEnumType( |
| 10056 | 10146 | }, |
| 10057 | 10147 | .explicit, .nonexhaustive => { |
| 10058 | 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 | 10150 | break :m values_map.toOptional(); |
| 10061 | 10151 | }; |
| 10062 | 10152 | errdefer if (ini.has_values) { |
| ... | ... | @@ -10141,6 +10231,7 @@ const GeneratedTagEnumTypeInit = struct { |
| 10141 | 10231 | pub fn getGeneratedTagEnumType( |
| 10142 | 10232 | ip: *InternPool, |
| 10143 | 10233 | gpa: Allocator, |
| 10234 | io: Io, | |
| 10144 | 10235 | tid: Zcu.PerThread.Id, |
| 10145 | 10236 | ini: GeneratedTagEnumTypeInit, |
| 10146 | 10237 | ) Allocator.Error!Index { |
| ... | ... | @@ -10149,11 +10240,11 @@ pub fn getGeneratedTagEnumType( |
| 10149 | 10240 | for (ini.values) |val| assert(ip.typeOf(val) == ini.tag_ty); |
| 10150 | 10241 | |
| 10151 | 10242 | const local = ip.getLocal(tid); |
| 10152 | const items = local.getMutableItems(gpa); | |
| 10243 | const items = local.getMutableItems(gpa, io); | |
| 10153 | 10244 | try items.ensureUnusedCapacity(1); |
| 10154 | const extra = local.getMutableExtra(gpa); | |
| 10245 | const extra = local.getMutableExtra(gpa, io); | |
| 10155 | 10246 | |
| 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 | 10248 | errdefer local.mutate.maps.len -= 1; |
| 10158 | 10249 | ip.addStringsToMap(names_map, ini.names); |
| 10159 | 10250 | |
| ... | ... | @@ -10165,7 +10256,7 @@ pub fn getGeneratedTagEnumType( |
| 10165 | 10256 | .index = items.mutate.len, |
| 10166 | 10257 | }, ip); |
| 10167 | 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 | 10260 | .parent = ini.parent_namespace.toOptional(), |
| 10170 | 10261 | .owner_type = enum_index, |
| 10171 | 10262 | .file_scope = parent_namespace.file_scope, |
| ... | ... | @@ -10202,7 +10293,7 @@ pub fn getGeneratedTagEnumType( |
| 10202 | 10293 | ini.values.len); // field values |
| 10203 | 10294 | |
| 10204 | 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 | 10297 | ip.addIndexesToMap(map, ini.values); |
| 10207 | 10298 | break :m map.toOptional(); |
| 10208 | 10299 | } else .none; |
| ... | ... | @@ -10240,7 +10331,7 @@ pub fn getGeneratedTagEnumType( |
| 10240 | 10331 | }, |
| 10241 | 10332 | }; |
| 10242 | 10333 | |
| 10243 | var gop = try ip.getOrPutKey(gpa, tid, .{ .enum_type = .{ | |
| 10334 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ | |
| 10244 | 10335 | .generated_tag = .{ .union_type = ini.owner_union_ty }, |
| 10245 | 10336 | } }); |
| 10246 | 10337 | defer gop.deinit(); |
| ... | ... | @@ -10256,10 +10347,11 @@ pub const OpaqueTypeInit = struct { |
| 10256 | 10347 | pub fn getOpaqueType( |
| 10257 | 10348 | ip: *InternPool, |
| 10258 | 10349 | gpa: Allocator, |
| 10350 | io: Io, | |
| 10259 | 10351 | tid: Zcu.PerThread.Id, |
| 10260 | 10352 | ini: OpaqueTypeInit, |
| 10261 | 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 | 10355 | .zir_index = ini.zir_index, |
| 10264 | 10356 | .captures = .{ .external = ini.captures }, |
| 10265 | 10357 | } } }); |
| ... | ... | @@ -10267,8 +10359,8 @@ pub fn getOpaqueType( |
| 10267 | 10359 | if (gop == .existing) return .{ .existing = gop.existing }; |
| 10268 | 10360 | |
| 10269 | 10361 | const local = ip.getLocal(tid); |
| 10270 | const items = local.getMutableItems(gpa); | |
| 10271 | const extra = local.getMutableExtra(gpa); | |
| 10362 | const items = local.getMutableItems(gpa, io); | |
| 10363 | const extra = local.getMutableExtra(gpa, io); | |
| 10272 | 10364 | try items.ensureUnusedCapacity(1); |
| 10273 | 10365 | |
| 10274 | 10366 | try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len); |
| ... | ... | @@ -10338,8 +10430,8 @@ fn addIndexesToMap( |
| 10338 | 10430 | } |
| 10339 | 10431 | } |
| 10340 | 10432 | |
| 10341 | fn addMap(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, cap: usize) Allocator.Error!MapIndex { | |
| 10342 | const maps = ip.getLocal(tid).getMutableMaps(gpa); | |
| 10433 | fn addMap(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, cap: usize) Allocator.Error!MapIndex { | |
| 10434 | const maps = ip.getLocal(tid).getMutableMaps(gpa, io); | |
| 10343 | 10435 | const unwrapped: MapIndex.Unwrapped = .{ .tid = tid, .index = maps.mutate.len }; |
| 10344 | 10436 | const ptr = try maps.addOne(); |
| 10345 | 10437 | errdefer maps.mutate.len = unwrapped.index; |
| ... | ... | @@ -10373,14 +10465,15 @@ pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void { |
| 10373 | 10465 | fn addInt( |
| 10374 | 10466 | ip: *InternPool, |
| 10375 | 10467 | gpa: Allocator, |
| 10468 | io: Io, | |
| 10376 | 10469 | tid: Zcu.PerThread.Id, |
| 10377 | 10470 | ty: Index, |
| 10378 | 10471 | tag: Tag, |
| 10379 | 10472 | limbs: []const Limb, |
| 10380 | 10473 | ) !void { |
| 10381 | 10474 | const local = ip.getLocal(tid); |
| 10382 | const items_list = local.getMutableItems(gpa); | |
| 10383 | const limbs_list = local.getMutableLimbs(gpa); | |
| 10475 | const items_list = local.getMutableItems(gpa, io); | |
| 10476 | const limbs_list = local.getMutableLimbs(gpa, io); | |
| 10384 | 10477 | const limbs_len: u32 = @intCast(limbs.len); |
| 10385 | 10478 | try limbs_list.ensureUnusedCapacity(Int.limbs_items_len + limbs_len); |
| 10386 | 10479 | items_list.appendAssumeCapacity(.{ |
| ... | ... | @@ -10510,28 +10603,29 @@ fn extraData(extra: Local.Extra, comptime T: type, index: u32) T { |
| 10510 | 10603 | |
| 10511 | 10604 | test "basic usage" { |
| 10512 | 10605 | const gpa = std.testing.allocator; |
| 10606 | const io = std.testing.io; | |
| 10513 | 10607 | |
| 10514 | 10608 | var ip: InternPool = .empty; |
| 10515 | try ip.init(gpa, 1); | |
| 10516 | defer ip.deinit(gpa); | |
| 10609 | try ip.init(gpa, io, 1); | |
| 10610 | defer ip.deinit(gpa, io); | |
| 10517 | 10611 | |
| 10518 | const i32_type = try ip.get(gpa, .main, .{ .int_type = .{ | |
| 10612 | const i32_type = try ip.get(gpa, io, .main, .{ .int_type = .{ | |
| 10519 | 10613 | .signedness = .signed, |
| 10520 | 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 | 10617 | .len = 10, |
| 10524 | 10618 | .child = i32_type, |
| 10525 | 10619 | .sentinel = .none, |
| 10526 | 10620 | } }); |
| 10527 | 10621 | |
| 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 | 10623 | .signedness = .signed, |
| 10530 | 10624 | .bits = 32, |
| 10531 | 10625 | } }); |
| 10532 | 10626 | try std.testing.expect(another_i32_type == i32_type); |
| 10533 | 10627 | |
| 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 | 10629 | .len = 10, |
| 10536 | 10630 | .child = i32_type, |
| 10537 | 10631 | .sentinel = .none, |
| ... | ... | @@ -10608,6 +10702,7 @@ pub fn sliceLen(ip: *const InternPool, index: Index) Index { |
| 10608 | 10702 | pub fn getCoerced( |
| 10609 | 10703 | ip: *InternPool, |
| 10610 | 10704 | gpa: Allocator, |
| 10705 | io: Io, | |
| 10611 | 10706 | tid: Zcu.PerThread.Id, |
| 10612 | 10707 | val: Index, |
| 10613 | 10708 | new_ty: Index, |
| ... | ... | @@ -10616,22 +10711,22 @@ pub fn getCoerced( |
| 10616 | 10711 | if (old_ty == new_ty) return val; |
| 10617 | 10712 | |
| 10618 | 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 | 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 | 10717 | .ty = new_ty, |
| 10623 | 10718 | .val = .none, |
| 10624 | 10719 | } }); |
| 10625 | 10720 | |
| 10626 | 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 | 10723 | .ty = new_ty, |
| 10629 | 10724 | .base_addr = .int, |
| 10630 | 10725 | .byte_offset = 0, |
| 10631 | 10726 | } }), |
| 10632 | .slice => return ip.get(gpa, tid, .{ .slice = .{ | |
| 10727 | .slice => return ip.get(gpa, io, tid, .{ .slice = .{ | |
| 10633 | 10728 | .ty = new_ty, |
| 10634 | .ptr = try ip.get(gpa, tid, .{ .ptr = .{ | |
| 10729 | .ptr = try ip.get(gpa, io, tid, .{ .ptr = .{ | |
| 10635 | 10730 | .ty = ip.slicePtrType(new_ty), |
| 10636 | 10731 | .base_addr = .int, |
| 10637 | 10732 | .byte_offset = 0, |
| ... | ... | @@ -10644,15 +10739,15 @@ pub fn getCoerced( |
| 10644 | 10739 | const unwrapped_val = val.unwrap(ip); |
| 10645 | 10740 | const val_item = unwrapped_val.getItem(ip); |
| 10646 | 10741 | switch (val_item.tag) { |
| 10647 | .func_decl => return getCoercedFuncDecl(ip, gpa, tid, val, new_ty), | |
| 10648 | .func_instance => return getCoercedFuncInstance(ip, gpa, tid, val, new_ty), | |
| 10742 | .func_decl => return getCoercedFuncDecl(ip, gpa, io, tid, val, new_ty), | |
| 10743 | .func_instance => return getCoercedFuncInstance(ip, gpa, io, tid, val, new_ty), | |
| 10649 | 10744 | .func_coerced => { |
| 10650 | 10745 | const func: Index = @enumFromInt(unwrapped_val.getExtra(ip).view().items(.@"0")[ |
| 10651 | 10746 | val_item.data + std.meta.fieldIndex(Tag.FuncCoerced, "func").? |
| 10652 | 10747 | ]); |
| 10653 | 10748 | switch (func.unwrap(ip).getTag(ip)) { |
| 10654 | .func_decl => return getCoercedFuncDecl(ip, gpa, tid, val, new_ty), | |
| 10655 | .func_instance => return getCoercedFuncInstance(ip, gpa, tid, val, new_ty), | |
| 10749 | .func_decl => return getCoercedFuncDecl(ip, gpa, io, tid, val, new_ty), | |
| 10750 | .func_instance => return getCoercedFuncInstance(ip, gpa, io, tid, val, new_ty), | |
| 10656 | 10751 | else => unreachable, |
| 10657 | 10752 | } |
| 10658 | 10753 | }, |
| ... | ... | @@ -10662,16 +10757,16 @@ pub fn getCoerced( |
| 10662 | 10757 | } |
| 10663 | 10758 | |
| 10664 | 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 | 10761 | .func => unreachable, |
| 10667 | 10762 | |
| 10668 | 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 | 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 | 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 | 10770 | .ty = new_ty, |
| 10676 | 10771 | .base_addr = .int, |
| 10677 | 10772 | .byte_offset = @intCast(int_val), |
| ... | ... | @@ -10680,7 +10775,7 @@ pub fn getCoerced( |
| 10680 | 10775 | .lazy_align, .lazy_size => {}, |
| 10681 | 10776 | }, |
| 10682 | 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 | 10780 | .float => |float| switch (ip.indexToKey(new_ty)) { |
| 10686 | 10781 | .simple_type => |simple| switch (simple) { |
| ... | ... | @@ -10691,7 +10786,7 @@ pub fn getCoerced( |
| 10691 | 10786 | .f128, |
| 10692 | 10787 | .c_longdouble, |
| 10693 | 10788 | .comptime_float, |
| 10694 | => return ip.get(gpa, tid, .{ .float = .{ | |
| 10789 | => return ip.get(gpa, io, tid, .{ .float = .{ | |
| 10695 | 10790 | .ty = new_ty, |
| 10696 | 10791 | .storage = float.storage, |
| 10697 | 10792 | } }), |
| ... | ... | @@ -10700,17 +10795,17 @@ pub fn getCoerced( |
| 10700 | 10795 | else => {}, |
| 10701 | 10796 | }, |
| 10702 | 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 | 10799 | .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) { |
| 10705 | 10800 | .enum_type => { |
| 10706 | 10801 | const enum_type = ip.loadEnumType(new_ty); |
| 10707 | 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 | 10804 | .ty = new_ty, |
| 10710 | 10805 | .int = if (enum_type.values.len != 0) |
| 10711 | 10806 | enum_type.values.get(ip)[index] |
| 10712 | 10807 | else |
| 10713 | try ip.get(gpa, tid, .{ .int = .{ | |
| 10808 | try ip.get(gpa, io, tid, .{ .int = .{ | |
| 10714 | 10809 | .ty = enum_type.tag_ty, |
| 10715 | 10810 | .storage = .{ .u64 = index }, |
| 10716 | 10811 | } }), |
| ... | ... | @@ -10719,22 +10814,22 @@ pub fn getCoerced( |
| 10719 | 10814 | else => {}, |
| 10720 | 10815 | }, |
| 10721 | 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 | 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 | 10820 | .len = slice.len, |
| 10726 | 10821 | } }) |
| 10727 | 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 | 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 | 10826 | .ty = new_ty, |
| 10732 | 10827 | .base_addr = ptr.base_addr, |
| 10733 | 10828 | .byte_offset = ptr.byte_offset, |
| 10734 | 10829 | } }) |
| 10735 | 10830 | else if (ip.isIntegerType(new_ty)) |
| 10736 | 10831 | switch (ptr.base_addr) { |
| 10737 | .int => return ip.get(gpa, tid, .{ .int = .{ | |
| 10832 | .int => return ip.get(gpa, io, tid, .{ .int = .{ | |
| 10738 | 10833 | .ty = .usize_type, |
| 10739 | 10834 | .storage = .{ .u64 = @intCast(ptr.byte_offset) }, |
| 10740 | 10835 | } }), |
| ... | ... | @@ -10743,14 +10838,14 @@ pub fn getCoerced( |
| 10743 | 10838 | .opt => |opt| switch (ip.indexToKey(new_ty)) { |
| 10744 | 10839 | .ptr_type => |ptr_type| return switch (opt.val) { |
| 10745 | 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 | 10842 | .ty = new_ty, |
| 10748 | 10843 | .base_addr = .int, |
| 10749 | 10844 | .byte_offset = 0, |
| 10750 | 10845 | } }), |
| 10751 | .slice => try ip.get(gpa, tid, .{ .slice = .{ | |
| 10846 | .slice => try ip.get(gpa, io, tid, .{ .slice = .{ | |
| 10752 | 10847 | .ty = new_ty, |
| 10753 | .ptr = try ip.get(gpa, tid, .{ .ptr = .{ | |
| 10848 | .ptr = try ip.get(gpa, io, tid, .{ .ptr = .{ | |
| 10754 | 10849 | .ty = ip.slicePtrType(new_ty), |
| 10755 | 10850 | .base_addr = .int, |
| 10756 | 10851 | .byte_offset = 0, |
| ... | ... | @@ -10758,29 +10853,29 @@ pub fn getCoerced( |
| 10758 | 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 | 10859 | .ty = new_ty, |
| 10765 | 10860 | .val = switch (opt.val) { |
| 10766 | 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 | 10865 | else => {}, |
| 10771 | 10866 | }, |
| 10772 | 10867 | .err => |err| if (ip.isErrorSetType(new_ty)) |
| 10773 | return ip.get(gpa, tid, .{ .err = .{ | |
| 10868 | return ip.get(gpa, io, tid, .{ .err = .{ | |
| 10774 | 10869 | .ty = new_ty, |
| 10775 | 10870 | .name = err.name, |
| 10776 | 10871 | } }) |
| 10777 | 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 | 10874 | .ty = new_ty, |
| 10780 | 10875 | .val = .{ .err_name = err.name }, |
| 10781 | 10876 | } }), |
| 10782 | 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 | 10879 | .ty = new_ty, |
| 10785 | 10880 | .val = error_union.val, |
| 10786 | 10881 | } }), |
| ... | ... | @@ -10799,20 +10894,20 @@ pub fn getCoerced( |
| 10799 | 10894 | }; |
| 10800 | 10895 | if (old_ty_child != new_ty_child) break :direct; |
| 10801 | 10896 | switch (aggregate.storage) { |
| 10802 | .bytes => |bytes| return ip.get(gpa, tid, .{ .aggregate = .{ | |
| 10897 | .bytes => |bytes| return ip.get(gpa, io, tid, .{ .aggregate = .{ | |
| 10803 | 10898 | .ty = new_ty, |
| 10804 | 10899 | .storage = .{ .bytes = bytes }, |
| 10805 | 10900 | } }), |
| 10806 | 10901 | .elems => |elems| { |
| 10807 | 10902 | const elems_copy = try gpa.dupe(Index, elems[0..new_len]); |
| 10808 | 10903 | defer gpa.free(elems_copy); |
| 10809 | return ip.get(gpa, tid, .{ .aggregate = .{ | |
| 10904 | return ip.get(gpa, io, tid, .{ .aggregate = .{ | |
| 10810 | 10905 | .ty = new_ty, |
| 10811 | 10906 | .storage = .{ .elems = elems_copy }, |
| 10812 | 10907 | } }); |
| 10813 | 10908 | }, |
| 10814 | 10909 | .repeated_elem => |elem| { |
| 10815 | return ip.get(gpa, tid, .{ .aggregate = .{ | |
| 10910 | return ip.get(gpa, io, tid, .{ .aggregate = .{ | |
| 10816 | 10911 | .ty = new_ty, |
| 10817 | 10912 | .storage = .{ .repeated_elem = elem }, |
| 10818 | 10913 | } }); |
| ... | ... | @@ -10830,7 +10925,7 @@ pub fn getCoerced( |
| 10830 | 10925 | // We have to intern each value here, so unfortunately we can't easily avoid |
| 10831 | 10926 | // the repeated indexToKey calls. |
| 10832 | 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 | 10929 | .ty = .u8_type, |
| 10835 | 10930 | .storage = .{ .u64 = bytes.at(index, ip) }, |
| 10836 | 10931 | } }); |
| ... | ... | @@ -10847,27 +10942,27 @@ pub fn getCoerced( |
| 10847 | 10942 | .struct_type => ip.loadStructType(new_ty).field_types.get(ip)[i], |
| 10848 | 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 | 10949 | else => {}, |
| 10855 | 10950 | } |
| 10856 | 10951 | |
| 10857 | 10952 | switch (ip.indexToKey(new_ty)) { |
| 10858 | 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 | 10955 | .ty = new_ty, |
| 10861 | 10956 | .val = .none, |
| 10862 | 10957 | } }), |
| 10863 | else => return ip.get(gpa, tid, .{ .opt = .{ | |
| 10958 | else => return ip.get(gpa, io, tid, .{ .opt = .{ | |
| 10864 | 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 | 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 | 10967 | else => {}, |
| 10873 | 10968 | } |
| ... | ... | @@ -10884,6 +10979,7 @@ pub fn getCoerced( |
| 10884 | 10979 | fn getCoercedFuncDecl( |
| 10885 | 10980 | ip: *InternPool, |
| 10886 | 10981 | gpa: Allocator, |
| 10982 | io: Io, | |
| 10887 | 10983 | tid: Zcu.PerThread.Id, |
| 10888 | 10984 | val: Index, |
| 10889 | 10985 | new_ty: Index, |
| ... | ... | @@ -10893,12 +10989,13 @@ fn getCoercedFuncDecl( |
| 10893 | 10989 | unwrapped_val.getData(ip) + std.meta.fieldIndex(Tag.FuncDecl, "ty").? |
| 10894 | 10990 | ]); |
| 10895 | 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 | } |
| 10898 | 10994 | |
| 10899 | 10995 | fn getCoercedFuncInstance( |
| 10900 | 10996 | ip: *InternPool, |
| 10901 | 10997 | gpa: Allocator, |
| 10998 | io: Io, | |
| 10902 | 10999 | tid: Zcu.PerThread.Id, |
| 10903 | 11000 | val: Index, |
| 10904 | 11001 | new_ty: Index, |
| ... | ... | @@ -10908,20 +11005,21 @@ fn getCoercedFuncInstance( |
| 10908 | 11005 | unwrapped_val.getData(ip) + std.meta.fieldIndex(Tag.FuncInstance, "ty").? |
| 10909 | 11006 | ]); |
| 10910 | 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 | } |
| 10913 | 11010 | |
| 10914 | 11011 | fn getCoercedFunc( |
| 10915 | 11012 | ip: *InternPool, |
| 10916 | 11013 | gpa: Allocator, |
| 11014 | io: Io, | |
| 10917 | 11015 | tid: Zcu.PerThread.Id, |
| 10918 | 11016 | func: Index, |
| 10919 | 11017 | ty: Index, |
| 10920 | 11018 | ) Allocator.Error!Index { |
| 10921 | 11019 | const local = ip.getLocal(tid); |
| 10922 | const items = local.getMutableItems(gpa); | |
| 11020 | const items = local.getMutableItems(gpa, io); | |
| 10923 | 11021 | try items.ensureUnusedCapacity(1); |
| 10924 | const extra = local.getMutableExtra(gpa); | |
| 11022 | const extra = local.getMutableExtra(gpa, io); | |
| 10925 | 11023 | |
| 10926 | 11024 | const prev_extra_len = extra.mutate.len; |
| 10927 | 11025 | try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncCoerced).@"struct".fields.len); |
| ... | ... | @@ -10932,7 +11030,7 @@ fn getCoercedFunc( |
| 10932 | 11030 | }); |
| 10933 | 11031 | errdefer extra.mutate.len = prev_extra_len; |
| 10934 | 11032 | |
| 10935 | var gop = try ip.getOrPutKey(gpa, tid, .{ | |
| 11033 | var gop = try ip.getOrPutKey(gpa, io, tid, .{ | |
| 10936 | 11034 | .func = ip.extraFuncCoerced(extra.list.*, extra_index), |
| 10937 | 11035 | }); |
| 10938 | 11036 | defer gop.deinit(); |
| ... | ... | @@ -10950,8 +11048,15 @@ fn getCoercedFunc( |
| 10950 | 11048 | |
| 10951 | 11049 | /// Asserts `val` has an integer type. |
| 10952 | 11050 | /// Assumes `new_ty` is an integer type. |
| 10953 | pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, int: Key.Int, new_ty: Index) Allocator.Error!Index { | |
| 10954 | return ip.get(gpa, tid, .{ .int = .{ | |
| 11051 | pub fn getCoercedInts( | |
| 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 | 11060 | .ty = new_ty, |
| 10956 | 11061 | .storage = int.storage, |
| 10957 | 11062 | } }); |
| ... | ... | @@ -11047,12 +11152,12 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index { |
| 11047 | 11152 | } |
| 11048 | 11153 | |
| 11049 | 11154 | /// The is only legal because the initializer is not part of the hash. |
| 11050 | pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void { | |
| 11155 | pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) void { | |
| 11051 | 11156 | const unwrapped_index = index.unwrap(ip); |
| 11052 | 11157 | |
| 11053 | 11158 | const local = ip.getLocal(unwrapped_index.tid); |
| 11054 | local.mutate.extra.mutex.lock(); | |
| 11055 | defer local.mutate.extra.mutex.unlock(); | |
| 11159 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 11160 | defer local.mutate.extra.mutex.unlock(io); | |
| 11056 | 11161 | |
| 11057 | 11162 | const extra_items = local.shared.extra.view().items(.@"0"); |
| 11058 | 11163 | const item = unwrapped_index.getItem(ip); |
| ... | ... | @@ -11508,11 +11613,12 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names |
| 11508 | 11613 | pub fn createComptimeUnit( |
| 11509 | 11614 | ip: *InternPool, |
| 11510 | 11615 | gpa: Allocator, |
| 11616 | io: Io, | |
| 11511 | 11617 | tid: Zcu.PerThread.Id, |
| 11512 | 11618 | zir_index: TrackedInst.Index, |
| 11513 | 11619 | namespace: NamespaceIndex, |
| 11514 | 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 | 11622 | const id_unwrapped: ComptimeUnit.Id.Unwrapped = .{ |
| 11517 | 11623 | .tid = tid, |
| 11518 | 11624 | .index = comptime_units.mutate.len, |
| ... | ... | @@ -11532,9 +11638,10 @@ pub fn getComptimeUnit(ip: *const InternPool, id: ComptimeUnit.Id) ComptimeUnit |
| 11532 | 11638 | |
| 11533 | 11639 | /// Create a `Nav` which does not undergo semantic analysis. |
| 11534 | 11640 | /// Since it is never analyzed, the `Nav`'s value must be known at creation time. |
| 11535 | pub fn createNav( | |
| 11641 | fn createNav( | |
| 11536 | 11642 | ip: *InternPool, |
| 11537 | 11643 | gpa: Allocator, |
| 11644 | io: Io, | |
| 11538 | 11645 | tid: Zcu.PerThread.Id, |
| 11539 | 11646 | opts: struct { |
| 11540 | 11647 | name: NullTerminatedString, |
| ... | ... | @@ -11546,7 +11653,7 @@ pub fn createNav( |
| 11546 | 11653 | @"addrspace": std.builtin.AddressSpace, |
| 11547 | 11654 | }, |
| 11548 | 11655 | ) Allocator.Error!Nav.Index { |
| 11549 | const navs = ip.getLocal(tid).getMutableNavs(gpa); | |
| 11656 | const navs = ip.getLocal(tid).getMutableNavs(gpa, io); | |
| 11550 | 11657 | const index_unwrapped: Nav.Index.Unwrapped = .{ |
| 11551 | 11658 | .tid = tid, |
| 11552 | 11659 | .index = navs.mutate.len, |
| ... | ... | @@ -11571,13 +11678,14 @@ pub fn createNav( |
| 11571 | 11678 | pub fn createDeclNav( |
| 11572 | 11679 | ip: *InternPool, |
| 11573 | 11680 | gpa: Allocator, |
| 11681 | io: Io, | |
| 11574 | 11682 | tid: Zcu.PerThread.Id, |
| 11575 | 11683 | name: NullTerminatedString, |
| 11576 | 11684 | fqn: NullTerminatedString, |
| 11577 | 11685 | zir_index: TrackedInst.Index, |
| 11578 | 11686 | namespace: NamespaceIndex, |
| 11579 | 11687 | ) Allocator.Error!Nav.Index { |
| 11580 | const navs = ip.getLocal(tid).getMutableNavs(gpa); | |
| 11688 | const navs = ip.getLocal(tid).getMutableNavs(gpa, io); | |
| 11581 | 11689 | |
| 11582 | 11690 | try navs.ensureUnusedCapacity(1); |
| 11583 | 11691 | |
| ... | ... | @@ -11603,6 +11711,7 @@ pub fn createDeclNav( |
| 11603 | 11711 | /// If its status is already `resolved`, the old value is discarded. |
| 11604 | 11712 | pub fn resolveNavType( |
| 11605 | 11713 | ip: *InternPool, |
| 11714 | io: Io, | |
| 11606 | 11715 | nav: Nav.Index, |
| 11607 | 11716 | resolved: struct { |
| 11608 | 11717 | type: InternPool.Index, |
| ... | ... | @@ -11617,8 +11726,8 @@ pub fn resolveNavType( |
| 11617 | 11726 | const unwrapped = nav.unwrap(ip); |
| 11618 | 11727 | |
| 11619 | 11728 | const local = ip.getLocal(unwrapped.tid); |
| 11620 | local.mutate.extra.mutex.lock(); | |
| 11621 | defer local.mutate.extra.mutex.unlock(); | |
| 11729 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 11730 | defer local.mutate.extra.mutex.unlock(io); | |
| 11622 | 11731 | |
| 11623 | 11732 | const navs = local.shared.navs.view(); |
| 11624 | 11733 | |
| ... | ... | @@ -11647,6 +11756,7 @@ pub fn resolveNavType( |
| 11647 | 11756 | /// If its status is already `resolved`, the old value is discarded. |
| 11648 | 11757 | pub fn resolveNavValue( |
| 11649 | 11758 | ip: *InternPool, |
| 11759 | io: Io, | |
| 11650 | 11760 | nav: Nav.Index, |
| 11651 | 11761 | resolved: struct { |
| 11652 | 11762 | val: InternPool.Index, |
| ... | ... | @@ -11659,8 +11769,8 @@ pub fn resolveNavValue( |
| 11659 | 11769 | const unwrapped = nav.unwrap(ip); |
| 11660 | 11770 | |
| 11661 | 11771 | const local = ip.getLocal(unwrapped.tid); |
| 11662 | local.mutate.extra.mutex.lock(); | |
| 11663 | defer local.mutate.extra.mutex.unlock(); | |
| 11772 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 11773 | defer local.mutate.extra.mutex.unlock(io); | |
| 11664 | 11774 | |
| 11665 | 11775 | const navs = local.shared.navs.view(); |
| 11666 | 11776 | |
| ... | ... | @@ -11687,6 +11797,7 @@ pub fn resolveNavValue( |
| 11687 | 11797 | pub fn createNamespace( |
| 11688 | 11798 | ip: *InternPool, |
| 11689 | 11799 | gpa: Allocator, |
| 11800 | io: Io, | |
| 11690 | 11801 | tid: Zcu.PerThread.Id, |
| 11691 | 11802 | initialization: Zcu.Namespace, |
| 11692 | 11803 | ) Allocator.Error!NamespaceIndex { |
| ... | ... | @@ -11700,7 +11811,7 @@ pub fn createNamespace( |
| 11700 | 11811 | reused_namespace.* = initialization; |
| 11701 | 11812 | return reused_namespace_index; |
| 11702 | 11813 | } |
| 11703 | const namespaces = local.getMutableNamespaces(gpa); | |
| 11814 | const namespaces = local.getMutableNamespaces(gpa, io); | |
| 11704 | 11815 | const last_bucket_len = local.mutate.namespaces.last_bucket_len & Local.namespaces_bucket_mask; |
| 11705 | 11816 | if (last_bucket_len == 0) { |
| 11706 | 11817 | try namespaces.ensureUnusedCapacity(1); |
| ... | ... | @@ -11748,10 +11859,11 @@ pub fn filePtr(ip: *const InternPool, file_index: FileIndex) *Zcu.File { |
| 11748 | 11859 | pub fn createFile( |
| 11749 | 11860 | ip: *InternPool, |
| 11750 | 11861 | gpa: Allocator, |
| 11862 | io: Io, | |
| 11751 | 11863 | tid: Zcu.PerThread.Id, |
| 11752 | 11864 | file: File, |
| 11753 | 11865 | ) Allocator.Error!FileIndex { |
| 11754 | const files = ip.getLocal(tid).getMutableFiles(gpa); | |
| 11866 | const files = ip.getLocal(tid).getMutableFiles(gpa, io); | |
| 11755 | 11867 | const file_index_unwrapped: FileIndex.Unwrapped = .{ |
| 11756 | 11868 | .tid = tid, |
| 11757 | 11869 | .index = files.mutate.len, |
| ... | ... | @@ -11782,20 +11894,22 @@ const EmbeddedNulls = enum { |
| 11782 | 11894 | pub fn getOrPutString( |
| 11783 | 11895 | ip: *InternPool, |
| 11784 | 11896 | gpa: Allocator, |
| 11897 | io: Io, | |
| 11785 | 11898 | tid: Zcu.PerThread.Id, |
| 11786 | 11899 | slice: []const u8, |
| 11787 | 11900 | comptime embedded_nulls: EmbeddedNulls, |
| 11788 | 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 | 11903 | try string_bytes.ensureUnusedCapacity(slice.len + 1); |
| 11791 | 11904 | string_bytes.appendSliceAssumeCapacity(.{slice}); |
| 11792 | 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 | } |
| 11795 | 11908 | |
| 11796 | 11909 | pub fn getOrPutStringFmt( |
| 11797 | 11910 | ip: *InternPool, |
| 11798 | 11911 | gpa: Allocator, |
| 11912 | io: Io, | |
| 11799 | 11913 | tid: Zcu.PerThread.Id, |
| 11800 | 11914 | comptime format: []const u8, |
| 11801 | 11915 | args: anytype, |
| ... | ... | @@ -11804,20 +11918,21 @@ pub fn getOrPutStringFmt( |
| 11804 | 11918 | // ensure that references to strings in args do not get invalidated |
| 11805 | 11919 | const format_z = format ++ .{0}; |
| 11806 | 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 | 11922 | const slice = try string_bytes.addManyAsSlice(len); |
| 11809 | 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 | } |
| 11812 | 11926 | |
| 11813 | 11927 | pub fn getOrPutStringOpt( |
| 11814 | 11928 | ip: *InternPool, |
| 11815 | 11929 | gpa: Allocator, |
| 11930 | io: Io, | |
| 11816 | 11931 | tid: Zcu.PerThread.Id, |
| 11817 | 11932 | slice: ?[]const u8, |
| 11818 | 11933 | comptime embedded_nulls: EmbeddedNulls, |
| 11819 | 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 | 11936 | return string.toOptional(); |
| 11822 | 11937 | } |
| 11823 | 11938 | |
| ... | ... | @@ -11825,14 +11940,15 @@ pub fn getOrPutStringOpt( |
| 11825 | 11940 | pub fn getOrPutTrailingString( |
| 11826 | 11941 | ip: *InternPool, |
| 11827 | 11942 | gpa: Allocator, |
| 11943 | io: Io, | |
| 11828 | 11944 | tid: Zcu.PerThread.Id, |
| 11829 | 11945 | len: u32, |
| 11830 | 11946 | comptime embedded_nulls: EmbeddedNulls, |
| 11831 | 11947 | ) Allocator.Error!embedded_nulls.StringType() { |
| 11832 | 11948 | const local = ip.getLocal(tid); |
| 11833 | const strings = local.getMutableStrings(gpa); | |
| 11949 | const strings = local.getMutableStrings(gpa, io); | |
| 11834 | 11950 | try strings.ensureUnusedCapacity(1); |
| 11835 | const string_bytes = local.getMutableStringBytes(gpa); | |
| 11951 | const string_bytes = local.getMutableStringBytes(gpa, io); | |
| 11836 | 11952 | const start: u32 = @intCast(string_bytes.mutate.len - len); |
| 11837 | 11953 | if (len > 0 and string_bytes.view().items(.@"0")[string_bytes.mutate.len - 1] == 0) { |
| 11838 | 11954 | string_bytes.mutate.len -= 1; |
| ... | ... | @@ -11870,8 +11986,8 @@ pub fn getOrPutTrailingString( |
| 11870 | 11986 | string_bytes.shrinkRetainingCapacity(start); |
| 11871 | 11987 | return @enumFromInt(@intFromEnum(index)); |
| 11872 | 11988 | } |
| 11873 | shard.mutate.string_map.mutex.lock(); | |
| 11874 | defer shard.mutate.string_map.mutex.unlock(); | |
| 11989 | shard.mutate.string_map.mutex.lock(io, tid); | |
| 11990 | defer shard.mutate.string_map.mutex.unlock(io); | |
| 11875 | 11991 | if (map.entries != shard.shared.string_map.entries) { |
| 11876 | 11992 | map = shard.shared.string_map; |
| 11877 | 11993 | map_mask = map.header().mask(); |
| ... | ... | @@ -12590,11 +12706,11 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis { |
| 12590 | 12706 | return @atomicLoad(FuncAnalysis, ip.funcAnalysisPtr(func), .unordered); |
| 12591 | 12707 | } |
| 12592 | 12708 | |
| 12593 | pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool) void { | |
| 12709 | pub fn funcSetHasErrorTrace(ip: *InternPool, io: Io, func: Index, has_error_trace: bool) void { | |
| 12594 | 12710 | const unwrapped_func = func.unwrap(ip); |
| 12595 | 12711 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; |
| 12596 | extra_mutex.lock(); | |
| 12597 | defer extra_mutex.unlock(); | |
| 12712 | extra_mutex.lockUncancelable(io); | |
| 12713 | defer extra_mutex.unlock(io); | |
| 12598 | 12714 | |
| 12599 | 12715 | const analysis_ptr = ip.funcAnalysisPtr(func); |
| 12600 | 12716 | var analysis = analysis_ptr.*; |
| ... | ... | @@ -12602,11 +12718,11 @@ pub fn funcSetHasErrorTrace(ip: *InternPool, func: Index, has_error_trace: bool) |
| 12602 | 12718 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); |
| 12603 | 12719 | } |
| 12604 | 12720 | |
| 12605 | pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void { | |
| 12721 | pub fn funcSetDisableInstrumentation(ip: *InternPool, io: Io, func: Index) void { | |
| 12606 | 12722 | const unwrapped_func = func.unwrap(ip); |
| 12607 | 12723 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; |
| 12608 | extra_mutex.lock(); | |
| 12609 | defer extra_mutex.unlock(); | |
| 12724 | extra_mutex.lockUncancelable(io); | |
| 12725 | defer extra_mutex.unlock(io); | |
| 12610 | 12726 | |
| 12611 | 12727 | const analysis_ptr = ip.funcAnalysisPtr(func); |
| 12612 | 12728 | var analysis = analysis_ptr.*; |
| ... | ... | @@ -12614,11 +12730,11 @@ pub fn funcSetDisableInstrumentation(ip: *InternPool, func: Index) void { |
| 12614 | 12730 | @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); |
| 12615 | 12731 | } |
| 12616 | 12732 | |
| 12617 | pub fn funcSetDisableIntrinsics(ip: *InternPool, func: Index) void { | |
| 12733 | pub fn funcSetDisableIntrinsics(ip: *InternPool, io: Io, func: Index) void { | |
| 12618 | 12734 | const unwrapped_func = func.unwrap(ip); |
| 12619 | 12735 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; |
| 12620 | extra_mutex.lock(); | |
| 12621 | defer extra_mutex.unlock(); | |
| 12736 | extra_mutex.lockUncancelable(io); | |
| 12737 | defer extra_mutex.unlock(io); | |
| 12622 | 12738 | |
| 12623 | 12739 | const analysis_ptr = ip.funcAnalysisPtr(func); |
| 12624 | 12740 | var analysis = analysis_ptr.*; |
| ... | ... | @@ -12663,15 +12779,6 @@ pub fn iesFuncIndex(ip: *const InternPool, ies_index: Index) Index { |
| 12663 | 12779 | return func_index; |
| 12664 | 12780 | } |
| 12665 | 12781 | |
| 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`. | |
| 12669 | fn 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 | 12782 | /// Returns a mutable pointer to the resolved error set type of an inferred |
| 12676 | 12783 | /// error set function. The returned pointer is invalidated when anything is |
| 12677 | 12784 | /// added to `ip`. |
| ... | ... | @@ -12706,11 +12813,11 @@ pub fn funcIesResolvedUnordered(ip: *const InternPool, index: Index) Index { |
| 12706 | 12813 | return @atomicLoad(Index, ip.funcIesResolvedPtr(index), .unordered); |
| 12707 | 12814 | } |
| 12708 | 12815 | |
| 12709 | pub fn funcSetIesResolved(ip: *InternPool, index: Index, ies: Index) void { | |
| 12816 | pub fn funcSetIesResolved(ip: *InternPool, io: Io, index: Index, ies: Index) void { | |
| 12710 | 12817 | const unwrapped_func = index.unwrap(ip); |
| 12711 | 12818 | const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; |
| 12712 | extra_mutex.lock(); | |
| 12713 | defer extra_mutex.unlock(); | |
| 12819 | extra_mutex.lockUncancelable(io); | |
| 12820 | defer extra_mutex.unlock(io); | |
| 12714 | 12821 | |
| 12715 | 12822 | @atomicStore(Index, ip.funcIesResolvedPtr(index), ies, .release); |
| 12716 | 12823 | } |
| ... | ... | @@ -12777,19 +12884,19 @@ const GlobalErrorSet = struct { |
| 12777 | 12884 | } align(std.atomic.cache_line), |
| 12778 | 12885 | mutate: struct { |
| 12779 | 12886 | names: Local.ListMutate, |
| 12780 | map: struct { mutex: std.Thread.Mutex }, | |
| 12887 | map: struct { mutex: Io.Mutex }, | |
| 12781 | 12888 | } align(std.atomic.cache_line), |
| 12782 | 12889 | |
| 12783 | 12890 | const Names = Local.List(struct { NullTerminatedString }); |
| 12784 | 12891 | |
| 12785 | 12892 | const empty: GlobalErrorSet = .{ |
| 12786 | 12893 | .shared = .{ |
| 12787 | .names = Names.empty, | |
| 12788 | .map = Shard.Map(GlobalErrorSet.Index).empty, | |
| 12894 | .names = .empty, | |
| 12895 | .map = .empty, | |
| 12789 | 12896 | }, |
| 12790 | 12897 | .mutate = .{ |
| 12791 | .names = Local.ListMutate.empty, | |
| 12792 | .map = .{ .mutex = .{} }, | |
| 12898 | .names = .empty, | |
| 12899 | .map = .{ .mutex = .init }, | |
| 12793 | 12900 | }, |
| 12794 | 12901 | }; |
| 12795 | 12902 | |
| ... | ... | @@ -12807,6 +12914,7 @@ const GlobalErrorSet = struct { |
| 12807 | 12914 | fn getErrorValue( |
| 12808 | 12915 | ges: *GlobalErrorSet, |
| 12809 | 12916 | gpa: Allocator, |
| 12917 | io: Io, | |
| 12810 | 12918 | arena_state: *std.heap.ArenaAllocator.State, |
| 12811 | 12919 | name: NullTerminatedString, |
| 12812 | 12920 | ) Allocator.Error!GlobalErrorSet.Index { |
| ... | ... | @@ -12825,8 +12933,8 @@ const GlobalErrorSet = struct { |
| 12825 | 12933 | if (entry.hash != hash) continue; |
| 12826 | 12934 | if (names.view().items(.@"0")[@intFromEnum(index) - 1] == name) return index; |
| 12827 | 12935 | } |
| 12828 | ges.mutate.map.mutex.lock(); | |
| 12829 | defer ges.mutate.map.mutex.unlock(); | |
| 12936 | ges.mutate.map.mutex.lockUncancelable(io); | |
| 12937 | defer ges.mutate.map.mutex.unlock(io); | |
| 12830 | 12938 | if (map.entries != ges.shared.map.entries) { |
| 12831 | 12939 | map = ges.shared.map; |
| 12832 | 12940 | map_mask = map.header().mask(); |
| ... | ... | @@ -12842,6 +12950,7 @@ const GlobalErrorSet = struct { |
| 12842 | 12950 | } |
| 12843 | 12951 | const mutable_names: Names.Mutable = .{ |
| 12844 | 12952 | .gpa = gpa, |
| 12953 | .io = io, | |
| 12845 | 12954 | .arena = arena_state, |
| 12846 | 12955 | .mutate = &ges.mutate.names, |
| 12847 | 12956 | .list = &ges.shared.names, |
| ... | ... | @@ -12923,10 +13032,11 @@ const GlobalErrorSet = struct { |
| 12923 | 13032 | pub fn getErrorValue( |
| 12924 | 13033 | ip: *InternPool, |
| 12925 | 13034 | gpa: Allocator, |
| 13035 | io: Io, | |
| 12926 | 13036 | tid: Zcu.PerThread.Id, |
| 12927 | 13037 | name: NullTerminatedString, |
| 12928 | 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 | } |
| 12931 | 13041 | |
| 12932 | 13042 | pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt { |
src/Sema.zig+466-207| ... | ... | @@ -853,8 +853,9 @@ pub const Block = struct { |
| 853 | 853 | |
| 854 | 854 | fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index { |
| 855 | 855 | const pt = block.sema.pt; |
| 856 | const comp = pt.zcu.comp; | |
| 856 | 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 | 859 | .file = block.getFileScopeIndex(pt.zcu), |
| 859 | 860 | .inst = inst, |
| 860 | 861 | }); |
| ... | ... | @@ -1061,7 +1062,7 @@ fn analyzeInlineBody( |
| 1061 | 1062 | /// The index which a break instruction can target to break from this body. |
| 1062 | 1063 | break_target: Zir.Inst.Index, |
| 1063 | 1064 | ) CompileError!?Air.Inst.Ref { |
| 1064 | if (sema.analyzeBodyInner(block, body)) |_| { | |
| 1065 | if (sema.analyzeBodyInner(block, body)) { | |
| 1065 | 1066 | return null; |
| 1066 | 1067 | } else |err| switch (err) { |
| 1067 | 1068 | error.ComptimeBreak => {}, |
| ... | ... | @@ -1808,7 +1809,7 @@ fn analyzeBodyInner( |
| 1808 | 1809 | child_block.instructions = block.instructions; |
| 1809 | 1810 | defer block.instructions = child_block.instructions; |
| 1810 | 1811 | |
| 1811 | const break_result: ?BreakResult = if (sema.analyzeBodyInner(&child_block, inline_body)) |_| r: { | |
| 1812 | const break_result: ?BreakResult = if (sema.analyzeBodyInner(&child_block, inline_body)) r: { | |
| 1812 | 1813 | break :r null; |
| 1813 | 1814 | } else |err| switch (err) { |
| 1814 | 1815 | error.ComptimeBreak => brk_res: { |
| ... | ... | @@ -1956,7 +1957,7 @@ fn analyzeBodyInner( |
| 1956 | 1957 | .@"defer" => blk: { |
| 1957 | 1958 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"defer"; |
| 1958 | 1959 | const defer_body = sema.code.bodySlice(inst_data.index, inst_data.len); |
| 1959 | if (sema.analyzeBodyInner(block, defer_body)) |_| { | |
| 1960 | if (sema.analyzeBodyInner(block, defer_body)) { | |
| 1960 | 1961 | // The defer terminated noreturn - no more analysis needed. |
| 1961 | 1962 | break; |
| 1962 | 1963 | } else |err| switch (err) { |
| ... | ... | @@ -1975,7 +1976,7 @@ fn analyzeBodyInner( |
| 1975 | 1976 | const err_code = try sema.resolveInst(inst_data.err_code); |
| 1976 | 1977 | try map.ensureSpaceForInstructions(sema.gpa, defer_body); |
| 1977 | 1978 | map.putAssumeCapacity(extra.remapped_err_code, err_code); |
| 1978 | if (sema.analyzeBodyInner(block, defer_body)) |_| { | |
| 1979 | if (sema.analyzeBodyInner(block, defer_body)) { | |
| 1979 | 1980 | // The defer terminated noreturn - no more analysis needed. |
| 1980 | 1981 | break; |
| 1981 | 1982 | } else |err| switch (err) { |
| ... | ... | @@ -2205,10 +2206,11 @@ fn analyzeAsType( |
| 2205 | 2206 | |
| 2206 | 2207 | pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void { |
| 2207 | 2208 | const pt = sema.pt; |
| 2208 | const zcu = pt.zcu; | |
| 2209 | const comp = zcu.comp; | |
| 2210 | const gpa = sema.gpa; | |
| 2211 | const ip = &zcu.intern_pool; | |
| 2209 | const comp = pt.zcu.comp; | |
| 2210 | const gpa = comp.gpa; | |
| 2211 | const io = comp.io; | |
| 2212 | const ip = &pt.zcu.intern_pool; | |
| 2213 | ||
| 2212 | 2214 | if (!comp.config.any_error_tracing) return; |
| 2213 | 2215 | |
| 2214 | 2216 | assert(!block.isComptime()); |
| ... | ... | @@ -2231,12 +2233,12 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) |
| 2231 | 2233 | const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty)); |
| 2232 | 2234 | |
| 2233 | 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 | 2237 | const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, instruction_addresses_field_name, src, true); |
| 2236 | 2238 | try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store); |
| 2237 | 2239 | |
| 2238 | 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 | 2242 | const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, index_field_name, src, true); |
| 2241 | 2243 | try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store); |
| 2242 | 2244 | |
| ... | ... | @@ -2828,9 +2830,12 @@ fn zirTupleDecl( |
| 2828 | 2830 | block: *Block, |
| 2829 | 2831 | extended: Zir.Inst.Extended.InstData, |
| 2830 | 2832 | ) CompileError!Air.Inst.Ref { |
| 2831 | const gpa = sema.gpa; | |
| 2832 | 2833 | const pt = sema.pt; |
| 2833 | 2834 | const zcu = pt.zcu; |
| 2835 | const comp = zcu.comp; | |
| 2836 | const gpa = comp.gpa; | |
| 2837 | const io = comp.io; | |
| 2838 | ||
| 2834 | 2839 | const fields_len = extended.small; |
| 2835 | 2840 | const extra = sema.code.extraData(Zir.Inst.TupleDecl, extended.operand); |
| 2836 | 2841 | var extra_index = extra.end; |
| ... | ... | @@ -2863,7 +2868,7 @@ fn zirTupleDecl( |
| 2863 | 2868 | const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src); |
| 2864 | 2869 | const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value }); |
| 2865 | 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 | 2872 | return sema.failWithContainsReferenceToComptimeVar(block, init_src, field_name, "field default value", field_init_val); |
| 2868 | 2873 | } |
| 2869 | 2874 | break :init field_init_val.toIntern(); |
| ... | ... | @@ -2872,7 +2877,7 @@ fn zirTupleDecl( |
| 2872 | 2877 | }; |
| 2873 | 2878 | } |
| 2874 | 2879 | |
| 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 | 2881 | .types = types, |
| 2877 | 2882 | .values = inits, |
| 2878 | 2883 | })); |
| ... | ... | @@ -2911,7 +2916,11 @@ fn validateTupleFieldType( |
| 2911 | 2916 | fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { |
| 2912 | 2917 | const pt = sema.pt; |
| 2913 | 2918 | const zcu = pt.zcu; |
| 2919 | const comp = zcu.comp; | |
| 2920 | const gpa = comp.gpa; | |
| 2921 | const io = comp.io; | |
| 2914 | 2922 | const ip = &zcu.intern_pool; |
| 2923 | ||
| 2915 | 2924 | const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type); |
| 2916 | 2925 | const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu); |
| 2917 | 2926 | |
| ... | ... | @@ -2934,7 +2943,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2934 | 2943 | }; |
| 2935 | 2944 | const loaded_val = try sema.resolveLazyValue(unresolved_loaded_val); |
| 2936 | 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 | 2947 | return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", loaded_val); |
| 2939 | 2948 | } |
| 2940 | 2949 | break :capture .{ .@"comptime" = loaded_val.toIntern() }; |
| ... | ... | @@ -2943,7 +2952,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2943 | 2952 | const air_ref = try sema.resolveInst(inst.toRef()); |
| 2944 | 2953 | if (try sema.resolveValueResolveLazy(air_ref)) |val| { |
| 2945 | 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 | 2956 | return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val); |
| 2948 | 2957 | } |
| 2949 | 2958 | break :capture .{ .@"comptime" = val.toIntern() }; |
| ... | ... | @@ -2952,7 +2961,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2952 | 2961 | }), |
| 2953 | 2962 | .decl_val => |str| capture: { |
| 2954 | 2963 | const decl_name = try ip.getOrPutString( |
| 2955 | sema.gpa, | |
| 2964 | gpa, | |
| 2965 | io, | |
| 2956 | 2966 | pt.tid, |
| 2957 | 2967 | sema.code.nullTerminatedString(str), |
| 2958 | 2968 | .no_embedded_nulls, |
| ... | ... | @@ -2962,7 +2972,8 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2962 | 2972 | }, |
| 2963 | 2973 | .decl_ref => |str| capture: { |
| 2964 | 2974 | const decl_name = try ip.getOrPutString( |
| 2965 | sema.gpa, | |
| 2975 | gpa, | |
| 2976 | io, | |
| 2966 | 2977 | pt.tid, |
| 2967 | 2978 | sema.code.nullTerminatedString(str), |
| 2968 | 2979 | .no_embedded_nulls, |
| ... | ... | @@ -2984,8 +2995,11 @@ fn zirStructDecl( |
| 2984 | 2995 | ) CompileError!Air.Inst.Ref { |
| 2985 | 2996 | const pt = sema.pt; |
| 2986 | 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 | 3001 | const ip = &zcu.intern_pool; |
| 3002 | ||
| 2989 | 3003 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 2990 | 3004 | const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand); |
| 2991 | 3005 | |
| ... | ... | @@ -3040,7 +3054,7 @@ fn zirStructDecl( |
| 3040 | 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 | 3058 | .existing => |ty| { |
| 3045 | 3059 | const new_ty = try pt.ensureTypeUpToDate(ty); |
| 3046 | 3060 | |
| ... | ... | @@ -3108,7 +3122,9 @@ pub fn createTypeName( |
| 3108 | 3122 | } { |
| 3109 | 3123 | const pt = sema.pt; |
| 3110 | 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 | 3128 | const ip = &zcu.intern_pool; |
| 3113 | 3129 | |
| 3114 | 3130 | switch (name_strategy) { |
| ... | ... | @@ -3158,7 +3174,7 @@ pub fn createTypeName( |
| 3158 | 3174 | |
| 3159 | 3175 | w.writeByte(')') catch return error.OutOfMemory; |
| 3160 | 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 | 3178 | .nav = .none, |
| 3163 | 3179 | }; |
| 3164 | 3180 | }, |
| ... | ... | @@ -3170,7 +3186,7 @@ pub fn createTypeName( |
| 3170 | 3186 | for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) { |
| 3171 | 3187 | .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { |
| 3172 | 3188 | return .{ |
| 3173 | .name = try ip.getOrPutStringFmt(gpa, pt.tid, "{f}.{s}", .{ | |
| 3189 | .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ | |
| 3174 | 3190 | block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), |
| 3175 | 3191 | }, .no_embedded_nulls), |
| 3176 | 3192 | .nav = .none, |
| ... | ... | @@ -3193,7 +3209,7 @@ pub fn createTypeName( |
| 3193 | 3209 | // that builtin from the language, we can consider this. |
| 3194 | 3210 | |
| 3195 | 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 | 3213 | block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index), |
| 3198 | 3214 | }, .no_embedded_nulls), |
| 3199 | 3215 | .nav = .none, |
| ... | ... | @@ -3211,8 +3227,11 @@ fn zirEnumDecl( |
| 3211 | 3227 | |
| 3212 | 3228 | const pt = sema.pt; |
| 3213 | 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 | 3233 | const ip = &zcu.intern_pool; |
| 3234 | ||
| 3216 | 3235 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); |
| 3217 | 3236 | const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand); |
| 3218 | 3237 | var extra_index: usize = extra.end; |
| ... | ... | @@ -3281,7 +3300,7 @@ fn zirEnumDecl( |
| 3281 | 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 | 3304 | .existing => |ty| { |
| 3286 | 3305 | const new_ty = try pt.ensureTypeUpToDate(ty); |
| 3287 | 3306 | |
| ... | ... | @@ -3380,8 +3399,11 @@ fn zirUnionDecl( |
| 3380 | 3399 | |
| 3381 | 3400 | const pt = sema.pt; |
| 3382 | 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 | 3405 | const ip = &zcu.intern_pool; |
| 3406 | ||
| 3385 | 3407 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); |
| 3386 | 3408 | const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand); |
| 3387 | 3409 | var extra_index: usize = extra.end; |
| ... | ... | @@ -3438,7 +3460,7 @@ fn zirUnionDecl( |
| 3438 | 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 | 3464 | .existing => |ty| { |
| 3443 | 3465 | const new_ty = try pt.ensureTypeUpToDate(ty); |
| 3444 | 3466 | |
| ... | ... | @@ -3503,7 +3525,9 @@ fn zirOpaqueDecl( |
| 3503 | 3525 | |
| 3504 | 3526 | const pt = sema.pt; |
| 3505 | 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 | 3531 | const ip = &zcu.intern_pool; |
| 3508 | 3532 | |
| 3509 | 3533 | const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); |
| ... | ... | @@ -3532,7 +3556,7 @@ fn zirOpaqueDecl( |
| 3532 | 3556 | .zir_index = tracked_inst, |
| 3533 | 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 | 3560 | .existing => |ty| { |
| 3537 | 3561 | // Make sure we update the namespace if the declaration is re-analyzed, to pick |
| 3538 | 3562 | // up on e.g. changed comptime decls. |
| ... | ... | @@ -3587,7 +3611,10 @@ fn zirErrorSetDecl( |
| 3587 | 3611 | |
| 3588 | 3612 | const pt = sema.pt; |
| 3589 | 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 | 3618 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 3592 | 3619 | const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); |
| 3593 | 3620 | |
| ... | ... | @@ -3599,7 +3626,7 @@ fn zirErrorSetDecl( |
| 3599 | 3626 | while (extra_index < extra_index_end) : (extra_index += 1) { |
| 3600 | 3627 | const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]); |
| 3601 | 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 | 3630 | _ = try pt.getErrorValue(name_ip); |
| 3604 | 3631 | const result = names.getOrPutAssumeCapacity(name_ip); |
| 3605 | 3632 | assert(!result.found_existing); // verified in AstGen |
| ... | ... | @@ -3761,11 +3788,14 @@ fn indexablePtrLen( |
| 3761 | 3788 | ) CompileError!Air.Inst.Ref { |
| 3762 | 3789 | const pt = sema.pt; |
| 3763 | 3790 | const zcu = pt.zcu; |
| 3791 | const comp = zcu.comp; | |
| 3792 | const gpa = comp.gpa; | |
| 3793 | const io = comp.io; | |
| 3764 | 3794 | const object_ty = sema.typeOf(object); |
| 3765 | 3795 | const is_pointer_to = object_ty.isSinglePointer(zcu); |
| 3766 | 3796 | const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty; |
| 3767 | 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 | 3799 | return sema.fieldVal(block, src, object, field_name, src); |
| 3770 | 3800 | } |
| 3771 | 3801 | |
| ... | ... | @@ -3777,13 +3807,16 @@ fn indexablePtrLenOrNone( |
| 3777 | 3807 | ) CompileError!Air.Inst.Ref { |
| 3778 | 3808 | const pt = sema.pt; |
| 3779 | 3809 | const zcu = pt.zcu; |
| 3810 | const comp = zcu.comp; | |
| 3811 | const gpa = comp.gpa; | |
| 3812 | const io = comp.io; | |
| 3780 | 3813 | const operand_ty = sema.typeOf(operand); |
| 3781 | 3814 | try checkMemOperand(sema, block, src, operand_ty); |
| 3782 | 3815 | switch (operand_ty.ptrSize(zcu)) { |
| 3783 | 3816 | .many, .c => return .none, |
| 3784 | 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 | 3820 | return sema.fieldVal(block, src, operand, field_name, src); |
| 3788 | 3821 | } |
| 3789 | 3822 | |
| ... | ... | @@ -3961,6 +3994,9 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3961 | 3994 | fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, resolved_alloc_ty: ?Type) CompileError!?InternPool.Index { |
| 3962 | 3995 | const pt = sema.pt; |
| 3963 | 3996 | const zcu = pt.zcu; |
| 3997 | const comp = zcu.comp; | |
| 3998 | const gpa = comp.gpa; | |
| 3999 | const io = comp.io; | |
| 3964 | 4000 | |
| 3965 | 4001 | const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc); |
| 3966 | 4002 | const ptr_info = alloc_ty.ptrInfo(zcu); |
| ... | ... | @@ -4108,7 +4144,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4108 | 4144 | }; |
| 4109 | 4145 | const new_ptr_ty = tmp_air.typeOfIndex(air_ptr, &zcu.intern_pool).toIntern(); |
| 4110 | 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 | 4148 | .opt_payload => ptr: { |
| 4113 | 4149 | // Set the optional to non-null at comptime. |
| 4114 | 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 | 4559 | fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 4524 | 4560 | const pt = sema.pt; |
| 4525 | 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 | 4565 | const ip = &zcu.intern_pool; |
| 4566 | ||
| 4528 | 4567 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 4529 | 4568 | const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); |
| 4530 | 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 | 4609 | return sema.failWithOwnedErrorMsg(block, msg); |
| 4571 | 4610 | } |
| 4572 | 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 | 4613 | } else l: { |
| 4575 | 4614 | // This argument is a range. |
| 4576 | 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 | 4772 | fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { |
| 4734 | 4773 | const pt = sema.pt; |
| 4735 | 4774 | const zcu = pt.zcu; |
| 4775 | const comp = zcu.comp; | |
| 4776 | const gpa = comp.gpa; | |
| 4777 | const io = comp.io; | |
| 4778 | ||
| 4736 | 4779 | const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 4737 | 4780 | const src = block.nodeOffset(un_node.src_node); |
| 4738 | 4781 | |
| ... | ... | @@ -4758,7 +4801,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo |
| 4758 | 4801 | // This function cannot return an error. |
| 4759 | 4802 | // `try` is still valid if the error case is impossible, i.e. no error is returned. |
| 4760 | 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 | 5046 | ) CompileError!void { |
| 5004 | 5047 | const pt = sema.pt; |
| 5005 | 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 | 5052 | const ip = &zcu.intern_pool; |
| 5008 | 5053 | |
| 5009 | 5054 | // Tracks whether each field was explicitly initialized. |
| ... | ... | @@ -5017,6 +5062,7 @@ fn validateStructInit( |
| 5017 | 5062 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; |
| 5018 | 5063 | const field_name = try ip.getOrPutString( |
| 5019 | 5064 | gpa, |
| 5065 | io, | |
| 5020 | 5066 | pt.tid, |
| 5021 | 5067 | sema.code.nullTerminatedString(field_ptr_extra.field_name_start), |
| 5022 | 5068 | .no_embedded_nulls, |
| ... | ... | @@ -5461,9 +5507,15 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v |
| 5461 | 5507 | } |
| 5462 | 5508 | |
| 5463 | 5509 | fn 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 | 5516 | const bytes = sema.code.instructions.items(.data)[@intFromEnum(inst)].str.get(sema.code); |
| 5465 | 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 | 5519 | bytes.len, |
| 5468 | 5520 | ); |
| 5469 | 5521 | } |
| ... | ... | @@ -5555,7 +5607,9 @@ fn zirCompileLog( |
| 5555 | 5607 | ) CompileError!Air.Inst.Ref { |
| 5556 | 5608 | const pt = sema.pt; |
| 5557 | 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; | |
| 5559 | 5613 | |
| 5560 | 5614 | var aw: std.Io.Writer.Allocating = .init(gpa); |
| 5561 | 5615 | defer aw.deinit(); |
| ... | ... | @@ -5579,7 +5633,7 @@ fn zirCompileLog( |
| 5579 | 5633 | } |
| 5580 | 5634 | } |
| 5581 | 5635 | |
| 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); | |
| 5583 | 5637 | |
| 5584 | 5638 | const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: { |
| 5585 | 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 | 5811 | const pt = sema.pt; |
| 5758 | 5812 | const zcu = pt.zcu; |
| 5759 | 5813 | const comp = zcu.comp; |
| 5760 | const gpa = sema.gpa; | |
| 5814 | const gpa = comp.gpa; | |
| 5815 | const io = comp.io; | |
| 5816 | ||
| 5761 | 5817 | const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 5762 | 5818 | const src = parent_block.nodeOffset(pl_node.src_node); |
| 5763 | 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 | 5902 | errdefer c_import_file_path.deinit(gpa); |
| 5847 | 5903 | const c_import_file = try gpa.create(Zcu.File); |
| 5848 | 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 | 5906 | .bin_digest = c_import_file_path.digest(), |
| 5851 | 5907 | .file = c_import_file, |
| 5852 | 5908 | .root_type = .none, |
| ... | ... | @@ -5959,7 +6015,7 @@ fn resolveBlockBody( |
| 5959 | 6015 | assert(sema.air_instructions.items(.tag)[@intFromEnum(merges.block_inst)] == .block); |
| 5960 | 6016 | var need_debug_scope = false; |
| 5961 | 6017 | child_block.need_debug_scope = &need_debug_scope; |
| 5962 | if (sema.analyzeBodyInner(child_block, body)) |_| { | |
| 6018 | if (sema.analyzeBodyInner(child_block, body)) { | |
| 5963 | 6019 | return sema.resolveAnalyzedBlock(parent_block, src, child_block, merges, need_debug_scope); |
| 5964 | 6020 | } else |err| switch (err) { |
| 5965 | 6021 | error.ComptimeBreak => { |
| ... | ... | @@ -6350,6 +6406,7 @@ pub fn analyzeExport( |
| 6350 | 6406 | fn zirDisableInstrumentation(sema: *Sema) CompileError!void { |
| 6351 | 6407 | const pt = sema.pt; |
| 6352 | 6408 | const zcu = pt.zcu; |
| 6409 | const io = zcu.comp.io; | |
| 6353 | 6410 | const ip = &zcu.intern_pool; |
| 6354 | 6411 | const func = switch (sema.owner.unwrap()) { |
| 6355 | 6412 | .func => |func| func, |
| ... | ... | @@ -6360,13 +6417,14 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void { |
| 6360 | 6417 | .memoized_state, |
| 6361 | 6418 | => return, // does nothing outside a function |
| 6362 | 6419 | }; |
| 6363 | ip.funcSetDisableInstrumentation(func); | |
| 6420 | ip.funcSetDisableInstrumentation(io, func); | |
| 6364 | 6421 | sema.allow_memoize = false; |
| 6365 | 6422 | } |
| 6366 | 6423 | |
| 6367 | 6424 | fn zirDisableIntrinsics(sema: *Sema) CompileError!void { |
| 6368 | 6425 | const pt = sema.pt; |
| 6369 | 6426 | const zcu = pt.zcu; |
| 6427 | const io = zcu.comp.io; | |
| 6370 | 6428 | const ip = &zcu.intern_pool; |
| 6371 | 6429 | const func = switch (sema.owner.unwrap()) { |
| 6372 | 6430 | .func => |func| func, |
| ... | ... | @@ -6377,7 +6435,7 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void { |
| 6377 | 6435 | .memoized_state, |
| 6378 | 6436 | => return, // does nothing outside a function |
| 6379 | 6437 | }; |
| 6380 | ip.funcSetDisableIntrinsics(func); | |
| 6438 | ip.funcSetDisableIntrinsics(io, func); | |
| 6381 | 6439 | sema.allow_memoize = false; |
| 6382 | 6440 | } |
| 6383 | 6441 | |
| ... | ... | @@ -6576,10 +6634,15 @@ pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!Air.NullTer |
| 6576 | 6634 | fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 6577 | 6635 | const pt = sema.pt; |
| 6578 | 6636 | const zcu = pt.zcu; |
| 6637 | const comp = zcu.comp; | |
| 6638 | const gpa = comp.gpa; | |
| 6639 | const io = comp.io; | |
| 6640 | ||
| 6579 | 6641 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; |
| 6580 | 6642 | const src = block.tokenOffset(inst_data.src_tok); |
| 6581 | 6643 | const decl_name = try zcu.intern_pool.getOrPutString( |
| 6582 | sema.gpa, | |
| 6644 | gpa, | |
| 6645 | io, | |
| 6583 | 6646 | pt.tid, |
| 6584 | 6647 | inst_data.get(sema.code), |
| 6585 | 6648 | .no_embedded_nulls, |
| ... | ... | @@ -6591,10 +6654,15 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 6591 | 6654 | fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 6592 | 6655 | const pt = sema.pt; |
| 6593 | 6656 | const zcu = pt.zcu; |
| 6657 | const comp = zcu.comp; | |
| 6658 | const gpa = comp.gpa; | |
| 6659 | const io = comp.io; | |
| 6660 | ||
| 6594 | 6661 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; |
| 6595 | 6662 | const src = block.tokenOffset(inst_data.src_tok); |
| 6596 | 6663 | const decl_name = try zcu.intern_pool.getOrPutString( |
| 6597 | sema.gpa, | |
| 6664 | gpa, | |
| 6665 | io, | |
| 6598 | 6666 | pt.tid, |
| 6599 | 6667 | inst_data.get(sema.code), |
| 6600 | 6668 | .no_embedded_nulls, |
| ... | ... | @@ -6683,7 +6751,9 @@ fn funcDeclSrcInst(sema: *Sema, func_inst: Air.Inst.Ref) !?InternPool.TrackedIns |
| 6683 | 6751 | pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref { |
| 6684 | 6752 | const pt = sema.pt; |
| 6685 | 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; | |
| 6687 | 6757 | |
| 6688 | 6758 | if (block.isComptime() or block.is_typeof) { |
| 6689 | 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 | 6764 | |
| 6695 | 6765 | const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); |
| 6696 | 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 | 6768 | const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) { |
| 6699 | 6769 | error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"), |
| 6700 | 6770 | error.ComptimeReturn, error.ComptimeBreak => unreachable, |
| ... | ... | @@ -6721,7 +6791,9 @@ fn popErrorReturnTrace( |
| 6721 | 6791 | ) CompileError!void { |
| 6722 | 6792 | const pt = sema.pt; |
| 6723 | 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 | 6797 | var is_non_error: ?bool = null; |
| 6726 | 6798 | var is_non_error_inst: Air.Inst.Ref = undefined; |
| 6727 | 6799 | if (operand != .none) { |
| ... | ... | @@ -6738,7 +6810,7 @@ fn popErrorReturnTrace( |
| 6738 | 6810 | try stack_trace_ty.resolveFields(pt); |
| 6739 | 6811 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 6740 | 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 | 6814 | const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true); |
| 6743 | 6815 | try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store); |
| 6744 | 6816 | } else if (is_non_error == null) { |
| ... | ... | @@ -6764,7 +6836,7 @@ fn popErrorReturnTrace( |
| 6764 | 6836 | try stack_trace_ty.resolveFields(pt); |
| 6765 | 6837 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 6766 | 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 | 6840 | const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true); |
| 6769 | 6841 | try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store); |
| 6770 | 6842 | _ = try then_block.addBr(cond_block_inst, .void_value); |
| ... | ... | @@ -6818,6 +6890,10 @@ fn zirCall( |
| 6818 | 6890 | |
| 6819 | 6891 | const pt = sema.pt; |
| 6820 | 6892 | const zcu = pt.zcu; |
| 6893 | const comp = zcu.comp; | |
| 6894 | const gpa = comp.gpa; | |
| 6895 | const io = comp.io; | |
| 6896 | ||
| 6821 | 6897 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 6822 | 6898 | const callee_src = block.src(.{ .node_offset_call_func = inst_data.src_node }); |
| 6823 | 6899 | const call_src = block.nodeOffset(inst_data.src_node); |
| ... | ... | @@ -6837,7 +6913,8 @@ fn zirCall( |
| 6837 | 6913 | .field => blk: { |
| 6838 | 6914 | const object_ptr = try sema.resolveInst(extra.data.obj_ptr); |
| 6839 | 6915 | const field_name = try zcu.intern_pool.getOrPutString( |
| 6840 | sema.gpa, | |
| 6916 | gpa, | |
| 6917 | io, | |
| 6841 | 6918 | pt.tid, |
| 6842 | 6919 | sema.code.nullTerminatedString(extra.data.field_name_start), |
| 6843 | 6920 | .no_embedded_nulls, |
| ... | ... | @@ -6897,7 +6974,7 @@ fn zirCall( |
| 6897 | 6974 | if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) { |
| 6898 | 6975 | const stack_trace_ty = try sema.getBuiltinType(call_src, .StackTrace); |
| 6899 | 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 | 6978 | const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src); |
| 6902 | 6979 | |
| 6903 | 6980 | // Insert a save instruction before the arg resolution + call instructions we just generated |
| ... | ... | @@ -7232,7 +7309,9 @@ fn analyzeCall( |
| 7232 | 7309 | ) CompileError!Air.Inst.Ref { |
| 7233 | 7310 | const pt = sema.pt; |
| 7234 | 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 | 7315 | const ip = &zcu.intern_pool; |
| 7237 | 7316 | const arena = sema.arena; |
| 7238 | 7317 | |
| ... | ... | @@ -7544,7 +7623,7 @@ fn analyzeCall( |
| 7544 | 7623 | if (func_ty_info.cc == .auto) { |
| 7545 | 7624 | switch (sema.owner.unwrap()) { |
| 7546 | 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 | 7629 | for (args, 0..) |arg, arg_idx| { |
| ... | ... | @@ -7596,7 +7675,7 @@ fn analyzeCall( |
| 7596 | 7675 | } else resolved_ret_ty; |
| 7597 | 7676 | |
| 7598 | 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 | 7679 | .param_types = runtime_param_tys.items, |
| 7601 | 7680 | .noalias_bits = noalias_bits, |
| 7602 | 7681 | .bare_return_type = bare_ret_ty.toIntern(), |
| ... | ... | @@ -7614,7 +7693,7 @@ fn analyzeCall( |
| 7614 | 7693 | // This call is problematic as it breaks guarantees about order-independency of semantic analysis. |
| 7615 | 7694 | // These guarantees are necessary for incremental compilation and parallel semantic analysis. |
| 7616 | 7695 | // See: #22410 |
| 7617 | zcu.funcInfo(func_instance).maxBranchQuota(ip, sema.branch_quota); | |
| 7696 | zcu.funcInfo(func_instance).maxBranchQuota(ip, io, sema.branch_quota); | |
| 7618 | 7697 | |
| 7619 | 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 | 8181 | |
| 8103 | 8182 | const pt = sema.pt; |
| 8104 | 8183 | const zcu = pt.zcu; |
| 8184 | const comp = zcu.comp; | |
| 8185 | const gpa = comp.gpa; | |
| 8186 | const io = comp.io; | |
| 8105 | 8187 | const ip = &zcu.intern_pool; |
| 8106 | 8188 | |
| 8107 | 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 | 8198 | const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src); |
| 8117 | 8199 | const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel }); |
| 8118 | 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 | 8202 | return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel_val); |
| 8121 | 8203 | } |
| 8122 | 8204 | const array_ty = try pt.arrayType(.{ |
| ... | ... | @@ -8194,10 +8276,17 @@ fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, p |
| 8194 | 8276 | |
| 8195 | 8277 | fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 8196 | 8278 | _ = block; |
| 8279 | ||
| 8197 | 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 | 8286 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; |
| 8199 | 8287 | const name = try pt.zcu.intern_pool.getOrPutString( |
| 8200 | sema.gpa, | |
| 8288 | gpa, | |
| 8289 | io, | |
| 8201 | 8290 | pt.tid, |
| 8202 | 8291 | inst_data.get(sema.code), |
| 8203 | 8292 | .no_embedded_nulls, |
| ... | ... | @@ -8259,7 +8348,9 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 8259 | 8348 | |
| 8260 | 8349 | const pt = sema.pt; |
| 8261 | 8350 | const zcu = pt.zcu; |
| 8351 | const io = zcu.comp.io; | |
| 8262 | 8352 | const ip = &zcu.intern_pool; |
| 8353 | ||
| 8263 | 8354 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 8264 | 8355 | const src = block.nodeOffset(extra.node); |
| 8265 | 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 | 8362 | const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt)); |
| 8272 | 8363 | if (int > len: { |
| 8273 | 8364 | const mutate = &ip.global_error_set.mutate; |
| 8274 | mutate.map.mutex.lock(); | |
| 8275 | defer mutate.map.mutex.unlock(); | |
| 8365 | mutate.map.mutex.lockUncancelable(io); | |
| 8366 | defer mutate.map.mutex.unlock(io); | |
| 8276 | 8367 | break :len mutate.names.len; |
| 8277 | 8368 | } or int == 0) |
| 8278 | 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 | 8452 | |
| 8362 | 8453 | const pt = sema.pt; |
| 8363 | 8454 | const zcu = pt.zcu; |
| 8455 | const comp = zcu.comp; | |
| 8456 | const gpa = comp.gpa; | |
| 8457 | const io = comp.io; | |
| 8458 | ||
| 8364 | 8459 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; |
| 8365 | 8460 | const name = inst_data.get(sema.code); |
| 8366 | 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 | } |
| 8370 | 8465 | |
| ... | ... | @@ -8374,11 +8469,16 @@ fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: b |
| 8374 | 8469 | |
| 8375 | 8470 | const pt = sema.pt; |
| 8376 | 8471 | const zcu = pt.zcu; |
| 8472 | const comp = zcu.comp; | |
| 8473 | const gpa = comp.gpa; | |
| 8474 | const io = comp.io; | |
| 8475 | ||
| 8377 | 8476 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 8378 | 8477 | const src = block.nodeOffset(inst_data.src_node); |
| 8379 | 8478 | const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; |
| 8380 | 8479 | const name = try zcu.intern_pool.getOrPutString( |
| 8381 | sema.gpa, | |
| 8480 | gpa, | |
| 8481 | io, | |
| 8382 | 8482 | pt.tid, |
| 8383 | 8483 | sema.code.nullTerminatedString(extra.field_name_start), |
| 8384 | 8484 | .no_embedded_nulls, |
| ... | ... | @@ -8915,7 +9015,11 @@ fn zirFunc( |
| 8915 | 9015 | ) CompileError!Air.Inst.Ref { |
| 8916 | 9016 | const pt = sema.pt; |
| 8917 | 9017 | const zcu = pt.zcu; |
| 9018 | const comp = zcu.comp; | |
| 9019 | const gpa = comp.gpa; | |
| 9020 | const io = comp.io; | |
| 8918 | 9021 | const ip = &zcu.intern_pool; |
| 9022 | ||
| 8919 | 9023 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 8920 | 9024 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); |
| 8921 | 9025 | const target = zcu.getTarget(); |
| ... | ... | @@ -8970,7 +9074,7 @@ fn zirFunc( |
| 8970 | 9074 | block, |
| 8971 | 9075 | LazySrcLoc.unneeded, |
| 8972 | 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 | 9079 | // The above should have errored. |
| 8976 | 9080 | @panic("std.builtin is corrupt"); |
| ... | ... | @@ -9443,8 +9547,11 @@ fn funcCommon( |
| 9443 | 9547 | ) CompileError!Air.Inst.Ref { |
| 9444 | 9548 | const pt = sema.pt; |
| 9445 | 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 | 9553 | const ip = &zcu.intern_pool; |
| 9554 | ||
| 9448 | 9555 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); |
| 9449 | 9556 | const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); |
| 9450 | 9557 | const func_src = block.nodeOffset(src_node_offset); |
| ... | ... | @@ -9563,7 +9670,7 @@ fn funcCommon( |
| 9563 | 9670 | |
| 9564 | 9671 | if (inferred_error_set) { |
| 9565 | 9672 | assert(has_body); |
| 9566 | return .fromIntern(try ip.getFuncDeclIes(gpa, pt.tid, .{ | |
| 9673 | return .fromIntern(try ip.getFuncDeclIes(gpa, io, pt.tid, .{ | |
| 9567 | 9674 | .owner_nav = sema.owner.unwrap().nav_val, |
| 9568 | 9675 | |
| 9569 | 9676 | .param_types = param_types, |
| ... | ... | @@ -9583,7 +9690,7 @@ fn funcCommon( |
| 9583 | 9690 | })); |
| 9584 | 9691 | } |
| 9585 | 9692 | |
| 9586 | const func_ty = try ip.getFuncType(gpa, pt.tid, .{ | |
| 9693 | const func_ty = try ip.getFuncType(gpa, io, pt.tid, .{ | |
| 9587 | 9694 | .param_types = param_types, |
| 9588 | 9695 | .noalias_bits = noalias_bits, |
| 9589 | 9696 | .comptime_bits = comptime_bits, |
| ... | ... | @@ -9595,7 +9702,7 @@ fn funcCommon( |
| 9595 | 9702 | }); |
| 9596 | 9703 | |
| 9597 | 9704 | if (has_body) { |
| 9598 | return .fromIntern(try ip.getFuncDecl(gpa, pt.tid, .{ | |
| 9705 | return .fromIntern(try ip.getFuncDecl(gpa, io, pt.tid, .{ | |
| 9599 | 9706 | .owner_nav = sema.owner.unwrap().nav_val, |
| 9600 | 9707 | .ty = func_ty, |
| 9601 | 9708 | .cc = cc, |
| ... | ... | @@ -9778,12 +9885,17 @@ fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 9778 | 9885 | |
| 9779 | 9886 | const pt = sema.pt; |
| 9780 | 9887 | const zcu = pt.zcu; |
| 9888 | const comp = zcu.comp; | |
| 9889 | const gpa = comp.gpa; | |
| 9890 | const io = comp.io; | |
| 9891 | ||
| 9781 | 9892 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 9782 | 9893 | const src = block.nodeOffset(inst_data.src_node); |
| 9783 | 9894 | const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); |
| 9784 | 9895 | const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; |
| 9785 | 9896 | const field_name = try zcu.intern_pool.getOrPutString( |
| 9786 | sema.gpa, | |
| 9897 | gpa, | |
| 9898 | io, | |
| 9787 | 9899 | pt.tid, |
| 9788 | 9900 | sema.code.nullTerminatedString(extra.field_name_start), |
| 9789 | 9901 | .no_embedded_nulls, |
| ... | ... | @@ -9798,12 +9910,17 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9798 | 9910 | |
| 9799 | 9911 | const pt = sema.pt; |
| 9800 | 9912 | const zcu = pt.zcu; |
| 9913 | const comp = zcu.comp; | |
| 9914 | const gpa = comp.gpa; | |
| 9915 | const io = comp.io; | |
| 9916 | ||
| 9801 | 9917 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 9802 | 9918 | const src = block.nodeOffset(inst_data.src_node); |
| 9803 | 9919 | const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); |
| 9804 | 9920 | const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; |
| 9805 | 9921 | const field_name = try zcu.intern_pool.getOrPutString( |
| 9806 | sema.gpa, | |
| 9922 | gpa, | |
| 9923 | io, | |
| 9807 | 9924 | pt.tid, |
| 9808 | 9925 | sema.code.nullTerminatedString(extra.field_name_start), |
| 9809 | 9926 | .no_embedded_nulls, |
| ... | ... | @@ -9818,12 +9935,17 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 9818 | 9935 | |
| 9819 | 9936 | const pt = sema.pt; |
| 9820 | 9937 | const zcu = pt.zcu; |
| 9938 | const comp = zcu.comp; | |
| 9939 | const gpa = comp.gpa; | |
| 9940 | const io = comp.io; | |
| 9941 | ||
| 9821 | 9942 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 9822 | 9943 | const src = block.nodeOffset(inst_data.src_node); |
| 9823 | 9944 | const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node }); |
| 9824 | 9945 | const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; |
| 9825 | 9946 | const field_name = try zcu.intern_pool.getOrPutString( |
| 9826 | sema.gpa, | |
| 9947 | gpa, | |
| 9948 | io, | |
| 9827 | 9949 | pt.tid, |
| 9828 | 9950 | sema.code.nullTerminatedString(extra.field_name_start), |
| 9829 | 9951 | .no_embedded_nulls, |
| ... | ... | @@ -13941,9 +14063,14 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 13941 | 14063 | fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13942 | 14064 | const pt = sema.pt; |
| 13943 | 14065 | const zcu = pt.zcu; |
| 14066 | const comp = zcu.comp; | |
| 14067 | const gpa = comp.gpa; | |
| 14068 | const io = comp.io; | |
| 14069 | ||
| 13944 | 14070 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; |
| 13945 | 14071 | const name = try zcu.intern_pool.getOrPutString( |
| 13946 | sema.gpa, | |
| 14072 | gpa, | |
| 14073 | io, | |
| 13947 | 14074 | pt.tid, |
| 13948 | 14075 | inst_data.get(sema.code), |
| 13949 | 14076 | .no_embedded_nulls, |
| ... | ... | @@ -14379,6 +14506,10 @@ fn analyzeTupleCat( |
| 14379 | 14506 | ) CompileError!Air.Inst.Ref { |
| 14380 | 14507 | const pt = sema.pt; |
| 14381 | 14508 | const zcu = pt.zcu; |
| 14509 | const comp = zcu.comp; | |
| 14510 | const gpa = comp.gpa; | |
| 14511 | const io = comp.io; | |
| 14512 | ||
| 14382 | 14513 | const lhs_ty = sema.typeOf(lhs); |
| 14383 | 14514 | const rhs_ty = sema.typeOf(rhs); |
| 14384 | 14515 | const src = block.nodeOffset(src_node); |
| ... | ... | @@ -14434,7 +14565,7 @@ fn analyzeTupleCat( |
| 14434 | 14565 | break :rs runtime_src; |
| 14435 | 14566 | }; |
| 14436 | 14567 | |
| 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 | 14569 | .types = types, |
| 14439 | 14570 | .values = values, |
| 14440 | 14571 | })); |
| ... | ... | @@ -14821,6 +14952,10 @@ fn analyzeTupleMul( |
| 14821 | 14952 | ) CompileError!Air.Inst.Ref { |
| 14822 | 14953 | const pt = sema.pt; |
| 14823 | 14954 | const zcu = pt.zcu; |
| 14955 | const comp = zcu.comp; | |
| 14956 | const gpa = comp.gpa; | |
| 14957 | const io = comp.io; | |
| 14958 | ||
| 14824 | 14959 | const operand_ty = sema.typeOf(operand); |
| 14825 | 14960 | const src = block.nodeOffset(src_node); |
| 14826 | 14961 | const len_src = block.src(.{ .node_offset_bin_rhs = src_node }); |
| ... | ... | @@ -14856,7 +14991,7 @@ fn analyzeTupleMul( |
| 14856 | 14991 | break :rs runtime_src; |
| 14857 | 14992 | }; |
| 14858 | 14993 | |
| 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 | 14995 | .types = types, |
| 14861 | 14996 | .values = values, |
| 14862 | 14997 | })); |
| ... | ... | @@ -16388,7 +16523,11 @@ fn zirAsm( |
| 16388 | 16523 | |
| 16389 | 16524 | const pt = sema.pt; |
| 16390 | 16525 | const zcu = pt.zcu; |
| 16526 | const comp = zcu.comp; | |
| 16527 | const gpa = comp.gpa; | |
| 16528 | const io = comp.io; | |
| 16391 | 16529 | const ip = &zcu.intern_pool; |
| 16530 | ||
| 16392 | 16531 | const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand); |
| 16393 | 16532 | const src = block.nodeOffset(extra.data.src_node); |
| 16394 | 16533 | const ret_ty_src = block.src(.{ .node_offset_asm_ret_ty = extra.data.src_node }); |
| ... | ... | @@ -16445,7 +16584,7 @@ fn zirAsm( |
| 16445 | 16584 | } else { |
| 16446 | 16585 | const inst = try sema.resolveInst(output.data.operand); |
| 16447 | 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 | 16588 | return sema.failWithContainsReferenceToComptimeVar(block, output_src, output_name, "assembly output", .fromInterned(inst.toInterned().?)); |
| 16450 | 16589 | } |
| 16451 | 16590 | arg.* = inst; |
| ... | ... | @@ -16476,7 +16615,7 @@ fn zirAsm( |
| 16476 | 16615 | const uncasted_arg = try sema.resolveInst(input.data.operand); |
| 16477 | 16616 | const name = sema.code.nullTerminatedString(input.data.name); |
| 16478 | 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 | 16619 | return sema.failWithContainsReferenceToComptimeVar(block, input_src, input_name, "assembly input", .fromInterned(uncasted_arg.toInterned().?)); |
| 16481 | 16620 | } |
| 16482 | 16621 | const uncasted_arg_ty = sema.typeOf(uncasted_arg); |
| ... | ... | @@ -16500,7 +16639,6 @@ fn zirAsm( |
| 16500 | 16639 | const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber }); |
| 16501 | 16640 | needed_capacity += asm_source.len / 4 + 1; |
| 16502 | 16641 | |
| 16503 | const gpa = sema.gpa; | |
| 16504 | 16642 | try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity); |
| 16505 | 16643 | const asm_air = try block.addInst(.{ |
| 16506 | 16644 | .tag = .assembly, |
| ... | ... | @@ -17060,10 +17198,13 @@ fn zirBuiltinSrc( |
| 17060 | 17198 | |
| 17061 | 17199 | const pt = sema.pt; |
| 17062 | 17200 | const zcu = pt.zcu; |
| 17201 | const comp = zcu.comp; | |
| 17202 | const gpa = comp.gpa; | |
| 17203 | const io = comp.io; | |
| 17063 | 17204 | const ip = &zcu.intern_pool; |
| 17205 | ||
| 17064 | 17206 | const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data; |
| 17065 | 17207 | const fn_name = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).name; |
| 17066 | const gpa = sema.gpa; | |
| 17067 | 17208 | const file_scope = block.getFileScope(zcu); |
| 17068 | 17209 | |
| 17069 | 17210 | const func_name_val = v: { |
| ... | ... | @@ -17106,7 +17247,7 @@ fn zirBuiltinSrc( |
| 17106 | 17247 | .val = try pt.intern(.{ .aggregate = .{ |
| 17107 | 17248 | .ty = array_ty, |
| 17108 | 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 | 17273 | .val = try pt.intern(.{ .aggregate = .{ |
| 17133 | 17274 | .ty = array_ty, |
| 17134 | 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 | 17302 | fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 17162 | 17303 | const pt = sema.pt; |
| 17163 | 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 | 17308 | const ip = &zcu.intern_pool; |
| 17309 | ||
| 17166 | 17310 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 17167 | 17311 | const src = block.nodeOffset(inst_data.src_node); |
| 17168 | 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 | 17655 | const enum_type = ip.loadEnumType(ty.toIntern()); |
| 17512 | 17656 | const value_val = if (enum_type.values.len > 0) |
| 17513 | 17657 | try ip.getCoercedInts( |
| 17514 | zcu.gpa, | |
| 17658 | gpa, | |
| 17659 | io, | |
| 17515 | 17660 | pt.tid, |
| 17516 | 17661 | ip.indexToKey(enum_type.values.get(ip)[tag_index]).int, |
| 17517 | 17662 | .comptime_int_type, |
| ... | ... | @@ -17729,7 +17874,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17729 | 17874 | const field_ty = tuple_type.types.get(ip)[field_index]; |
| 17730 | 17875 | const field_val = tuple_type.values.get(ip)[field_index]; |
| 17731 | 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 | 17878 | const field_name_len = field_name.length(ip); |
| 17734 | 17879 | const new_decl_ty = try pt.arrayType(.{ |
| 17735 | 17880 | .len = field_name_len, |
| ... | ... | @@ -18752,10 +18897,15 @@ fn zirRetErrValue( |
| 18752 | 18897 | ) CompileError!void { |
| 18753 | 18898 | const pt = sema.pt; |
| 18754 | 18899 | const zcu = pt.zcu; |
| 18900 | const comp = zcu.comp; | |
| 18901 | const gpa = comp.gpa; | |
| 18902 | const io = comp.io; | |
| 18903 | ||
| 18755 | 18904 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; |
| 18756 | 18905 | const src = block.tokenOffset(inst_data.src_tok); |
| 18757 | 18906 | const err_name = try zcu.intern_pool.getOrPutString( |
| 18758 | sema.gpa, | |
| 18907 | gpa, | |
| 18908 | io, | |
| 18759 | 18909 | pt.tid, |
| 18760 | 18910 | inst_data.get(sema.code), |
| 18761 | 18911 | .no_embedded_nulls, |
| ... | ... | @@ -19121,6 +19271,9 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19121 | 19271 | |
| 19122 | 19272 | const pt = sema.pt; |
| 19123 | 19273 | const zcu = pt.zcu; |
| 19274 | const comp = zcu.comp; | |
| 19275 | const gpa = comp.gpa; | |
| 19276 | const io = comp.io; | |
| 19124 | 19277 | const ip = &zcu.intern_pool; |
| 19125 | 19278 | |
| 19126 | 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 | 19311 | const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .simple = .pointer_sentinel }); |
| 19159 | 19312 | try checkSentinelType(sema, block, sentinel_src, elem_ty); |
| 19160 | 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 | 19315 | return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", val); |
| 19163 | 19316 | } |
| 19164 | 19317 | break :blk val.toIntern(); |
| ... | ... | @@ -19463,15 +19616,18 @@ fn zirStructInit( |
| 19463 | 19616 | inst: Zir.Inst.Index, |
| 19464 | 19617 | is_ref: bool, |
| 19465 | 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 | 19626 | const zir_datas = sema.code.instructions.items(.data); |
| 19468 | 19627 | const inst_data = zir_datas[@intFromEnum(inst)].pl_node; |
| 19469 | 19628 | const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); |
| 19470 | 19629 | const src = block.nodeOffset(inst_data.src_node); |
| 19471 | 19630 | |
| 19472 | const pt = sema.pt; | |
| 19473 | const zcu = pt.zcu; | |
| 19474 | const ip = &zcu.intern_pool; | |
| 19475 | 19631 | const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data; |
| 19476 | 19632 | const first_field_type_data = zir_datas[@intFromEnum(first_item.field_type)].pl_node; |
| 19477 | 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 | 19669 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| 19514 | 19670 | const field_name = try ip.getOrPutString( |
| 19515 | 19671 | gpa, |
| 19672 | io, | |
| 19516 | 19673 | pt.tid, |
| 19517 | 19674 | sema.code.nullTerminatedString(field_type_extra.name_start), |
| 19518 | 19675 | .no_embedded_nulls, |
| ... | ... | @@ -19554,6 +19711,7 @@ fn zirStructInit( |
| 19554 | 19711 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| 19555 | 19712 | const field_name = try ip.getOrPutString( |
| 19556 | 19713 | gpa, |
| 19714 | io, | |
| 19557 | 19715 | pt.tid, |
| 19558 | 19716 | sema.code.nullTerminatedString(field_type_extra.name_start), |
| 19559 | 19717 | .no_embedded_nulls, |
| ... | ... | @@ -19797,8 +19955,11 @@ fn structInitAnon( |
| 19797 | 19955 | ) CompileError!Air.Inst.Ref { |
| 19798 | 19956 | const pt = sema.pt; |
| 19799 | 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 | 19961 | const ip = &zcu.intern_pool; |
| 19962 | ||
| 19802 | 19963 | const zir_datas = sema.code.instructions.items(.data); |
| 19803 | 19964 | |
| 19804 | 19965 | const types = try sema.arena.alloc(InternPool.Index, extra_data.fields_len); |
| ... | ... | @@ -19828,7 +19989,7 @@ fn structInitAnon( |
| 19828 | 19989 | }, |
| 19829 | 19990 | }; |
| 19830 | 19991 | |
| 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); | |
| 19832 | 19993 | |
| 19833 | 19994 | const init = try sema.resolveInst(item.data.init); |
| 19834 | 19995 | field_ty.* = sema.typeOf(init).toIntern(); |
| ... | ... | @@ -19871,7 +20032,7 @@ fn structInitAnon( |
| 19871 | 20032 | break :hash hasher.final(); |
| 19872 | 20033 | }; |
| 19873 | 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 | 20036 | .layout = .auto, |
| 19876 | 20037 | .fields_len = extra_data.fields_len, |
| 19877 | 20038 | .known_non_opv = false, |
| ... | ... | @@ -20131,7 +20292,9 @@ fn arrayInitAnon( |
| 20131 | 20292 | ) CompileError!Air.Inst.Ref { |
| 20132 | 20293 | const pt = sema.pt; |
| 20133 | 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 | 20298 | const ip = &zcu.intern_pool; |
| 20136 | 20299 | |
| 20137 | 20300 | const types = try sema.arena.alloc(InternPool.Index, operands.len); |
| ... | ... | @@ -20180,7 +20343,7 @@ fn arrayInitAnon( |
| 20180 | 20343 | break :blk new_values; |
| 20181 | 20344 | }; |
| 20182 | 20345 | |
| 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 | 20347 | .types = types, |
| 20185 | 20348 | .values = values_no_comptime, |
| 20186 | 20349 | })); |
| ... | ... | @@ -20247,7 +20410,11 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 20247 | 20410 | fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20248 | 20411 | const pt = sema.pt; |
| 20249 | 20412 | const zcu = pt.zcu; |
| 20413 | const comp = zcu.comp; | |
| 20414 | const gpa = comp.gpa; | |
| 20415 | const io = comp.io; | |
| 20250 | 20416 | const ip = &zcu.intern_pool; |
| 20417 | ||
| 20251 | 20418 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 20252 | 20419 | const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; |
| 20253 | 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 | 20422 | const wrapped_aggregate_ty = try sema.resolveTypeOrPoison(block, ty_src, extra.container_type) orelse return .generic_poison_type; |
| 20256 | 20423 | const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu); |
| 20257 | 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 | 20426 | return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src); |
| 20260 | 20427 | } |
| 20261 | 20428 | |
| ... | ... | @@ -20669,6 +20836,9 @@ fn zirReifyTuple( |
| 20669 | 20836 | ) CompileError!Air.Inst.Ref { |
| 20670 | 20837 | const pt = sema.pt; |
| 20671 | 20838 | const zcu = pt.zcu; |
| 20839 | const comp = zcu.comp; | |
| 20840 | const gpa = comp.gpa; | |
| 20841 | const io = comp.io; | |
| 20672 | 20842 | |
| 20673 | 20843 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 20674 | 20844 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| ... | ... | @@ -20691,7 +20861,7 @@ fn zirReifyTuple( |
| 20691 | 20861 | const field_values = try sema.arena.alloc(InternPool.Index, fields_len); |
| 20692 | 20862 | @memset(field_values, .none); |
| 20693 | 20863 | |
| 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 | 20865 | .types = field_types, |
| 20696 | 20866 | .values = field_values, |
| 20697 | 20867 | })); |
| ... | ... | @@ -20704,7 +20874,9 @@ fn zirReifyPointer( |
| 20704 | 20874 | ) CompileError!Air.Inst.Ref { |
| 20705 | 20875 | const pt = sema.pt; |
| 20706 | 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 | 20880 | const ip = &zcu.intern_pool; |
| 20709 | 20881 | |
| 20710 | 20882 | const extra = sema.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data; |
| ... | ... | @@ -20772,7 +20944,7 @@ fn zirReifyPointer( |
| 20772 | 20944 | } |
| 20773 | 20945 | try checkSentinelType(sema, block, sentinel_src, elem_ty); |
| 20774 | 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 | 20948 | return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel); |
| 20777 | 20949 | } |
| 20778 | 20950 | } |
| ... | ... | @@ -20801,7 +20973,9 @@ fn zirReifyFn( |
| 20801 | 20973 | ) CompileError!Air.Inst.Ref { |
| 20802 | 20974 | const pt = sema.pt; |
| 20803 | 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 | 20979 | const ip = &zcu.intern_pool; |
| 20806 | 20980 | |
| 20807 | 20981 | const extra = sema.code.extraData(Zir.Inst.ReifyFn, extended.operand).data; |
| ... | ... | @@ -20884,7 +21058,7 @@ fn zirReifyFn( |
| 20884 | 21058 | return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)}); |
| 20885 | 21059 | } |
| 20886 | 21060 | |
| 20887 | return .fromIntern(try ip.getFuncType(gpa, pt.tid, .{ | |
| 21061 | return .fromIntern(try ip.getFuncType(gpa, io, pt.tid, .{ | |
| 20888 | 21062 | .param_types = param_types_ip, |
| 20889 | 21063 | .noalias_bits = noalias_bits, |
| 20890 | 21064 | .comptime_bits = 0, |
| ... | ... | @@ -20904,7 +21078,9 @@ fn zirReifyStruct( |
| 20904 | 21078 | ) CompileError!Air.Inst.Ref { |
| 20905 | 21079 | const pt = sema.pt; |
| 20906 | 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 | 21084 | const ip = &zcu.intern_pool; |
| 20909 | 21085 | |
| 20910 | 21086 | const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); |
| ... | ... | @@ -21079,7 +21255,7 @@ fn zirReifyStruct( |
| 21079 | 21255 | return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout}); |
| 21080 | 21256 | } |
| 21081 | 21257 | |
| 21082 | const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{ | |
| 21258 | const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ | |
| 21083 | 21259 | .layout = layout, |
| 21084 | 21260 | .fields_len = @intCast(fields_len), |
| 21085 | 21261 | .known_non_opv = false, |
| ... | ... | @@ -21223,10 +21399,10 @@ fn zirReifyStruct( |
| 21223 | 21399 | } |
| 21224 | 21400 | if (backing_int_ty) |ty| { |
| 21225 | 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 | 21403 | } else { |
| 21228 | 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 | } |
| 21232 | 21408 | |
| ... | ... | @@ -21259,7 +21435,9 @@ fn zirReifyUnion( |
| 21259 | 21435 | ) CompileError!Air.Inst.Ref { |
| 21260 | 21436 | const pt = sema.pt; |
| 21261 | 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 | 21441 | const ip = &zcu.intern_pool; |
| 21264 | 21442 | |
| 21265 | 21443 | const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); |
| ... | ... | @@ -21400,7 +21578,7 @@ fn zirReifyUnion( |
| 21400 | 21578 | return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{}); |
| 21401 | 21579 | } |
| 21402 | 21580 | |
| 21403 | const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{ | |
| 21581 | const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ | |
| 21404 | 21582 | .flags = .{ |
| 21405 | 21583 | .layout = layout, |
| 21406 | 21584 | .status = .none, |
| ... | ... | @@ -21558,8 +21736,8 @@ fn zirReifyUnion( |
| 21558 | 21736 | } |
| 21559 | 21737 | } |
| 21560 | 21738 | |
| 21561 | loaded_union.setTagType(ip, enum_tag_ty); | |
| 21562 | loaded_union.setStatus(ip, .have_field_types); | |
| 21739 | loaded_union.setTagType(ip, io, enum_tag_ty); | |
| 21740 | loaded_union.setStatus(ip, io, .have_field_types); | |
| 21563 | 21741 | |
| 21564 | 21742 | const new_namespace_index = try pt.createNamespace(.{ |
| 21565 | 21743 | .parent = block.namespace.toOptional(), |
| ... | ... | @@ -21590,7 +21768,9 @@ fn zirReifyEnum( |
| 21590 | 21768 | ) CompileError!Air.Inst.Ref { |
| 21591 | 21769 | const pt = sema.pt; |
| 21592 | 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 | 21774 | const ip = &zcu.intern_pool; |
| 21595 | 21775 | |
| 21596 | 21776 | const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); |
| ... | ... | @@ -21688,7 +21868,7 @@ fn zirReifyEnum( |
| 21688 | 21868 | std.hash.autoHash(&hasher, field_name); |
| 21689 | 21869 | } |
| 21690 | 21870 | |
| 21691 | const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{ | |
| 21871 | const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ | |
| 21692 | 21872 | .has_values = true, |
| 21693 | 21873 | .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit, |
| 21694 | 21874 | .fields_len = @intCast(fields_len), |
| ... | ... | @@ -21844,13 +22024,16 @@ fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) |
| 21844 | 22024 | fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 21845 | 22025 | const pt = sema.pt; |
| 21846 | 22026 | const zcu = pt.zcu; |
| 22027 | const comp = zcu.comp; | |
| 22028 | const gpa = comp.gpa; | |
| 22029 | const io = comp.io; | |
| 21847 | 22030 | const ip = &zcu.intern_pool; |
| 21848 | 22031 | |
| 21849 | 22032 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 21850 | 22033 | const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 21851 | 22034 | const ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 21852 | 22035 | |
| 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 | 22037 | return sema.addNullTerminatedStrLit(type_name); |
| 21855 | 22038 | } |
| 21856 | 22039 | |
| ... | ... | @@ -22281,6 +22464,10 @@ fn ptrCastFull( |
| 22281 | 22464 | ) CompileError!Air.Inst.Ref { |
| 22282 | 22465 | const pt = sema.pt; |
| 22283 | 22466 | const zcu = pt.zcu; |
| 22467 | const comp = zcu.comp; | |
| 22468 | const gpa = comp.gpa; | |
| 22469 | const io = comp.io; | |
| 22470 | ||
| 22284 | 22471 | const operand_ty = sema.typeOf(operand); |
| 22285 | 22472 | |
| 22286 | 22473 | try sema.checkPtrType(block, src, dest_ty, true); |
| ... | ... | @@ -22452,14 +22639,14 @@ fn ptrCastFull( |
| 22452 | 22639 | if (dest_info.sentinel == .none) break :check_sent; |
| 22453 | 22640 | if (src_info.flags.size == .c) break :check_sent; |
| 22454 | 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 | 22643 | if (dest_info.sentinel == coerced_sent) break :check_sent; |
| 22457 | 22644 | } |
| 22458 | 22645 | if (is_array_ptr_to_slice) { |
| 22459 | 22646 | // [*]nT -> []T |
| 22460 | 22647 | const arr_ty: Type = .fromInterned(src_info.child); |
| 22461 | 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 | 22650 | if (dest_info.sentinel == coerced_sent) break :check_sent; |
| 22464 | 22651 | } |
| 22465 | 22652 | } |
| ... | ... | @@ -23577,8 +23764,11 @@ fn resolveExportOptions( |
| 23577 | 23764 | ) CompileError!Zcu.Export.Options { |
| 23578 | 23765 | const pt = sema.pt; |
| 23579 | 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 | 23770 | const ip = &zcu.intern_pool; |
| 23771 | ||
| 23582 | 23772 | const export_options_ty = try sema.getBuiltinType(src, .ExportOptions); |
| 23583 | 23773 | const air_ref = try sema.resolveInst(zir_ref); |
| 23584 | 23774 | const options = try sema.coerce(block, export_options_ty, air_ref, src); |
| ... | ... | @@ -23588,21 +23778,21 @@ fn resolveExportOptions( |
| 23588 | 23778 | const section_src = block.src(.{ .init_field_section = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 23589 | 23779 | const visibility_src = block.src(.{ .init_field_visibility = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 23590 | 23780 | |
| 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 | 23782 | const name = try sema.toConstString(block, name_src, name_operand, .{ .simple = .export_options }); |
| 23593 | 23783 | |
| 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 | 23785 | const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{ .simple = .export_options }); |
| 23596 | 23786 | const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage); |
| 23597 | 23787 | |
| 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 | 23789 | const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{ .simple = .export_options }); |
| 23600 | 23790 | const section = if (section_opt_val.optionalValue(zcu)) |section_val| |
| 23601 | 23791 | try sema.toConstString(block, section_src, Air.internedToRef(section_val.toIntern()), .{ .simple = .export_options }) |
| 23602 | 23792 | else |
| 23603 | 23793 | null; |
| 23604 | 23794 | |
| 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 | 23796 | const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_operand, .{ .simple = .export_options }); |
| 23607 | 23797 | const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility); |
| 23608 | 23798 | |
| ... | ... | @@ -23617,9 +23807,9 @@ fn resolveExportOptions( |
| 23617 | 23807 | } |
| 23618 | 23808 | |
| 23619 | 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 | 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 | 23813 | .visibility = visibility, |
| 23624 | 23814 | }; |
| 23625 | 23815 | } |
| ... | ... | @@ -25345,8 +25535,11 @@ fn zirMemcpy( |
| 25345 | 25535 | fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 25346 | 25536 | const pt = sema.pt; |
| 25347 | 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 | 25541 | const ip = &zcu.intern_pool; |
| 25542 | ||
| 25350 | 25543 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 25351 | 25544 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 25352 | 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 | 25578 | const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src); |
| 25386 | 25579 | |
| 25387 | 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 | 25582 | const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src; |
| 25390 | 25583 | const len_u64 = try len_val.toUnsignedIntSema(pt); |
| 25391 | 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 | 25631 | |
| 25439 | 25632 | const pt = sema.pt; |
| 25440 | 25633 | const zcu = pt.zcu; |
| 25634 | const comp = zcu.comp; | |
| 25635 | const gpa = comp.gpa; | |
| 25636 | const io = comp.io; | |
| 25441 | 25637 | const ip = &zcu.intern_pool; |
| 25638 | ||
| 25442 | 25639 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 25443 | 25640 | const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); |
| 25444 | 25641 | const target = zcu.getTarget(); |
| ... | ... | @@ -25482,7 +25679,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 25482 | 25679 | block, |
| 25483 | 25680 | LazySrcLoc.unneeded, |
| 25484 | 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 | 25684 | // The above should have errored. |
| 25488 | 25685 | @panic("std.builtin is corrupt"); |
| ... | ... | @@ -25648,8 +25845,11 @@ fn resolvePrefetchOptions( |
| 25648 | 25845 | ) CompileError!std.builtin.PrefetchOptions { |
| 25649 | 25846 | const pt = sema.pt; |
| 25650 | 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 | 25851 | const ip = &zcu.intern_pool; |
| 25852 | ||
| 25653 | 25853 | const options_ty = try sema.getBuiltinType(src, .PrefetchOptions); |
| 25654 | 25854 | const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src); |
| 25655 | 25855 | |
| ... | ... | @@ -25657,13 +25857,13 @@ fn resolvePrefetchOptions( |
| 25657 | 25857 | const locality_src = block.src(.{ .init_field_locality = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 25658 | 25858 | const cache_src = block.src(.{ .init_field_cache = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 25659 | 25859 | |
| 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 | 25861 | const rw_val = try sema.resolveConstDefinedValue(block, rw_src, rw, .{ .simple = .prefetch_options }); |
| 25662 | 25862 | |
| 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 | 25864 | const locality_val = try sema.resolveConstDefinedValue(block, locality_src, locality, .{ .simple = .prefetch_options }); |
| 25665 | 25865 | |
| 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 | 25867 | const cache_val = try sema.resolveConstDefinedValue(block, cache_src, cache, .{ .simple = .prefetch_options }); |
| 25668 | 25868 | |
| 25669 | 25869 | return std.builtin.PrefetchOptions{ |
| ... | ... | @@ -25717,8 +25917,11 @@ fn resolveExternOptions( |
| 25717 | 25917 | } { |
| 25718 | 25918 | const pt = sema.pt; |
| 25719 | 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 | 25923 | const ip = &zcu.intern_pool; |
| 25924 | ||
| 25722 | 25925 | const options_inst = try sema.resolveInst(zir_ref); |
| 25723 | 25926 | const extern_options_ty = try sema.getBuiltinType(src, .ExternOptions); |
| 25724 | 25927 | const options = try sema.coerce(block, extern_options_ty, options_inst, src); |
| ... | ... | @@ -25731,21 +25934,21 @@ fn resolveExternOptions( |
| 25731 | 25934 | const dll_import_src = block.src(.{ .init_field_dll_import = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 25732 | 25935 | const relocation_src = block.src(.{ .init_field_relocation = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 25733 | 25936 | |
| 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 | 25938 | const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options }); |
| 25736 | 25939 | |
| 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 | 25941 | const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{ .simple = .extern_options }); |
| 25739 | 25942 | |
| 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 | 25944 | const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{ .simple = .extern_options }); |
| 25742 | 25945 | const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage); |
| 25743 | 25946 | |
| 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 | 25948 | const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_ref, .{ .simple = .extern_options }); |
| 25746 | 25949 | const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility); |
| 25747 | 25950 | |
| 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 | 25952 | const is_thread_local_val = try sema.resolveConstDefinedValue(block, thread_local_src, is_thread_local, .{ .simple = .extern_options }); |
| 25750 | 25953 | |
| 25751 | 25954 | const library_name = if (library_name_val.optionalValue(zcu)) |library_name_payload| library_name: { |
| ... | ... | @@ -25757,10 +25960,10 @@ fn resolveExternOptions( |
| 25757 | 25960 | break :library_name library_name; |
| 25758 | 25961 | } else null; |
| 25759 | 25962 | |
| 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 | 25964 | const is_dll_import_val = try sema.resolveConstDefinedValue(block, dll_import_src, is_dll_import_ref, .{ .simple = .extern_options }); |
| 25762 | 25965 | |
| 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 | 25967 | const relocation_val = try sema.resolveConstDefinedValue(block, relocation_src, relocation_ref, .{ .simple = .extern_options }); |
| 25765 | 25968 | const relocation = try sema.interpretBuiltinType(block, relocation_src, relocation_val, std.builtin.ExternOptions.Relocation); |
| 25766 | 25969 | |
| ... | ... | @@ -25773,8 +25976,8 @@ fn resolveExternOptions( |
| 25773 | 25976 | } |
| 25774 | 25977 | |
| 25775 | 25978 | return .{ |
| 25776 | .name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls), | |
| 25777 | .library_name = try ip.getOrPutStringOpt(gpa, pt.tid, library_name, .no_embedded_nulls), | |
| 25979 | .name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls), | |
| 25980 | .library_name = try ip.getOrPutStringOpt(gpa, io, pt.tid, library_name, .no_embedded_nulls), | |
| 25778 | 25981 | .linkage = linkage, |
| 25779 | 25982 | .visibility = visibility, |
| 25780 | 25983 | .is_thread_local = is_thread_local_val.toBool(), |
| ... | ... | @@ -25919,7 +26122,9 @@ fn zirInComptime( |
| 25919 | 26122 | fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 25920 | 26123 | const pt = sema.pt; |
| 25921 | 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 | 26128 | const ip = &zcu.intern_pool; |
| 25924 | 26129 | |
| 25925 | 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 | 26160 | block, |
| 25956 | 26161 | src, |
| 25957 | 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 | 26164 | ) orelse @panic("std.builtin is corrupt"); |
| 25960 | 26165 | }, |
| 25961 | 26166 | .calling_convention_inline => { |
| ... | ... | @@ -26492,11 +26697,12 @@ fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !vo |
| 26492 | 26697 | |
| 26493 | 26698 | fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index { |
| 26494 | 26699 | const zcu = sema.pt.zcu; |
| 26700 | const io = zcu.comp.io; | |
| 26495 | 26701 | try sema.ensureMemoizedStateResolved(src, .panic); |
| 26496 | 26702 | const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin()); |
| 26497 | 26703 | switch (sema.owner.unwrap()) { |
| 26498 | 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 | 26707 | return panic_fn_index; |
| 26502 | 26708 | } |
| ... | ... | @@ -28539,10 +28745,15 @@ fn coerceExtra( |
| 28539 | 28745 | inst_src: LazySrcLoc, |
| 28540 | 28746 | opts: CoerceOpts, |
| 28541 | 28747 | ) CoersionError!Air.Inst.Ref { |
| 28542 | if (dest_ty.isGenericPoison()) return inst; | |
| 28543 | 28748 | const pt = sema.pt; |
| 28544 | 28749 | const zcu = pt.zcu; |
| 28750 | const comp = zcu.comp; | |
| 28751 | const gpa = comp.gpa; | |
| 28752 | const io = comp.io; | |
| 28545 | 28753 | const ip = &zcu.intern_pool; |
| 28754 | ||
| 28755 | if (dest_ty.isGenericPoison()) return inst; | |
| 28756 | ||
| 28546 | 28757 | const dest_ty_src = inst_src; // TODO better source location |
| 28547 | 28758 | try dest_ty.resolveFields(pt); |
| 28548 | 28759 | const inst_ty = sema.typeOf(inst); |
| ... | ... | @@ -28904,7 +29115,7 @@ fn coerceExtra( |
| 28904 | 29115 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 28905 | 29116 | .undef => try pt.undefRef(dest_ty), |
| 28906 | 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 | 29120 | else => unreachable, |
| 28910 | 29121 | }; |
| ... | ... | @@ -30070,6 +30281,10 @@ fn coerceInMemoryAllowedPtrs( |
| 30070 | 30281 | ) !InMemoryCoercionResult { |
| 30071 | 30282 | const pt = sema.pt; |
| 30072 | 30283 | const zcu = pt.zcu; |
| 30284 | const comp = zcu.comp; | |
| 30285 | const gpa = comp.gpa; | |
| 30286 | const io = comp.io; | |
| 30287 | ||
| 30073 | 30288 | const dest_info = dest_ptr_ty.ptrInfo(zcu); |
| 30074 | 30289 | const src_info = src_ptr_ty.ptrInfo(zcu); |
| 30075 | 30290 | |
| ... | ... | @@ -30175,7 +30390,7 @@ fn coerceInMemoryAllowedPtrs( |
| 30175 | 30390 | const ds = dest_info.sentinel; |
| 30176 | 30391 | if (ss == .none and ds == .none) break :ok true; |
| 30177 | 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 | 30395 | if (src_info.flags.size == .c) break :ok true; |
| 30181 | 30396 | if (!dest_is_mut and dest_info.sentinel == .none) break :ok true; |
| ... | ... | @@ -33086,6 +33301,9 @@ fn resolvePeerTypesInner( |
| 33086 | 33301 | ) !PeerResolveResult { |
| 33087 | 33302 | const pt = sema.pt; |
| 33088 | 33303 | const zcu = pt.zcu; |
| 33304 | const comp = zcu.comp; | |
| 33305 | const gpa = comp.gpa; | |
| 33306 | const io = comp.io; | |
| 33089 | 33307 | const ip = &zcu.intern_pool; |
| 33090 | 33308 | |
| 33091 | 33309 | var strat_reason: usize = 0; |
| ... | ... | @@ -33412,8 +33630,8 @@ fn resolvePeerTypesInner( |
| 33412 | 33630 | }).toIntern(); |
| 33413 | 33631 | |
| 33414 | 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); | |
| 33416 | const ptr_sent = try ip.getCoerced(sema.gpa, pt.tid, peer_info.sentinel, ptr_info.child); | |
| 33633 | const peer_sent = try ip.getCoerced(gpa, io, pt.tid, ptr_info.sentinel, ptr_info.child); | |
| 33634 | const ptr_sent = try ip.getCoerced(gpa, io, pt.tid, peer_info.sentinel, ptr_info.child); | |
| 33417 | 33635 | if (ptr_sent == peer_sent) { |
| 33418 | 33636 | ptr_info.sentinel = ptr_sent; |
| 33419 | 33637 | } else { |
| ... | ... | @@ -33715,8 +33933,8 @@ fn resolvePeerTypesInner( |
| 33715 | 33933 | no_sentinel: { |
| 33716 | 33934 | if (peer_sentinel == .none) break :no_sentinel; |
| 33717 | 33935 | if (cur_sentinel == .none) break :no_sentinel; |
| 33718 | const peer_sent_coerced = try ip.getCoerced(sema.gpa, pt.tid, peer_sentinel, sentinel_ty); | |
| 33719 | const cur_sent_coerced = try ip.getCoerced(sema.gpa, pt.tid, cur_sentinel, sentinel_ty); | |
| 33936 | const peer_sent_coerced = try ip.getCoerced(gpa, io, pt.tid, peer_sentinel, sentinel_ty); | |
| 33937 | const cur_sent_coerced = try ip.getCoerced(gpa, io, pt.tid, cur_sentinel, sentinel_ty); | |
| 33720 | 33938 | if (peer_sent_coerced != cur_sent_coerced) break :no_sentinel; |
| 33721 | 33939 | // Sentinels match |
| 33722 | 33940 | if (ptr_info.flags.size == .one) switch (ip.indexToKey(ptr_info.child)) { |
| ... | ... | @@ -34081,7 +34299,7 @@ fn resolvePeerTypesInner( |
| 34081 | 34299 | else => |result| { |
| 34082 | 34300 | const result_buf = try sema.arena.create(PeerResolveResult); |
| 34083 | 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); | |
| 34085 | 34303 | |
| 34086 | 34304 | // The error info needs the field types, but we can't reuse sub_peer_tys |
| 34087 | 34305 | // since the recursive call may have clobbered it. |
| ... | ... | @@ -34136,7 +34354,7 @@ fn resolvePeerTypesInner( |
| 34136 | 34354 | field_val.* = if (comptime_val) |v| v.toIntern() else .none; |
| 34137 | 34355 | } |
| 34138 | 34356 | |
| 34139 | const final_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{ | |
| 34357 | const final_ty = try ip.getTupleType(gpa, io, pt.tid, .{ | |
| 34140 | 34358 | .types = field_types, |
| 34141 | 34359 | .values = field_vals, |
| 34142 | 34360 | }); |
| ... | ... | @@ -34274,6 +34492,7 @@ pub fn resolveStructAlignment( |
| 34274 | 34492 | ) SemaError!void { |
| 34275 | 34493 | const pt = sema.pt; |
| 34276 | 34494 | const zcu = pt.zcu; |
| 34495 | const io = zcu.comp.io; | |
| 34277 | 34496 | const ip = &zcu.intern_pool; |
| 34278 | 34497 | const target = zcu.getTarget(); |
| 34279 | 34498 | |
| ... | ... | @@ -34287,15 +34506,15 @@ pub fn resolveStructAlignment( |
| 34287 | 34506 | // We'll guess "pointer-aligned", if the struct has an |
| 34288 | 34507 | // underaligned pointer field then some allocations |
| 34289 | 34508 | // might require explicit alignment. |
| 34290 | if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, ptr_align)) return; | |
| 34509 | if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return; | |
| 34291 | 34510 | |
| 34292 | 34511 | try sema.resolveStructFieldTypes(ty, struct_type); |
| 34293 | 34512 | |
| 34294 | 34513 | // We'll guess "pointer-aligned", if the struct has an |
| 34295 | 34514 | // underaligned pointer field then some allocations |
| 34296 | 34515 | // might require explicit alignment. |
| 34297 | if (struct_type.assumePointerAlignedIfWip(ip, ptr_align)) return; | |
| 34298 | defer struct_type.clearAlignmentWip(ip); | |
| 34516 | if (struct_type.assumePointerAlignedIfWip(ip, io, ptr_align)) return; | |
| 34517 | defer struct_type.clearAlignmentWip(ip, io); | |
| 34299 | 34518 | |
| 34300 | 34519 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. |
| 34301 | 34520 | // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. |
| ... | ... | @@ -34314,13 +34533,14 @@ pub fn resolveStructAlignment( |
| 34314 | 34533 | alignment = alignment.maxStrict(field_align); |
| 34315 | 34534 | } |
| 34316 | 34535 | |
| 34317 | struct_type.setAlignment(ip, alignment); | |
| 34536 | struct_type.setAlignment(ip, io, alignment); | |
| 34318 | 34537 | } |
| 34319 | 34538 | |
| 34320 | 34539 | pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { |
| 34321 | 34540 | const pt = sema.pt; |
| 34322 | 34541 | const zcu = pt.zcu; |
| 34323 | 34542 | const ip = &zcu.intern_pool; |
| 34543 | const io = zcu.comp.io; | |
| 34324 | 34544 | const struct_type = zcu.typeToStruct(ty) orelse return; |
| 34325 | 34545 | |
| 34326 | 34546 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| ... | ... | @@ -34341,7 +34561,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { |
| 34341 | 34561 | return; |
| 34342 | 34562 | } |
| 34343 | 34563 | |
| 34344 | if (struct_type.setLayoutWip(ip)) { | |
| 34564 | if (struct_type.setLayoutWip(ip, io)) { | |
| 34345 | 34565 | const msg = try sema.errMsg( |
| 34346 | 34566 | ty.srcLoc(zcu), |
| 34347 | 34567 | "struct '{f}' depends on itself", |
| ... | ... | @@ -34349,7 +34569,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { |
| 34349 | 34569 | ); |
| 34350 | 34570 | return sema.failWithOwnedErrorMsg(null, msg); |
| 34351 | 34571 | } |
| 34352 | defer struct_type.clearLayoutWip(ip); | |
| 34572 | defer struct_type.clearLayoutWip(ip, io); | |
| 34353 | 34573 | |
| 34354 | 34574 | const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len); |
| 34355 | 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 | 34688 | ); |
| 34469 | 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 | 34692 | _ = try ty.comptimeOnlySema(pt); |
| 34473 | 34693 | } |
| 34474 | 34694 | |
| ... | ... | @@ -34478,7 +34698,9 @@ fn backingIntType( |
| 34478 | 34698 | ) CompileError!void { |
| 34479 | 34699 | const pt = sema.pt; |
| 34480 | 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 | 34704 | const ip = &zcu.intern_pool; |
| 34483 | 34705 | |
| 34484 | 34706 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| ... | ... | @@ -34546,13 +34768,13 @@ fn backingIntType( |
| 34546 | 34768 | }; |
| 34547 | 34769 | |
| 34548 | 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 | 34772 | } else { |
| 34551 | 34773 | if (fields_bit_sum > std.math.maxInt(u16)) { |
| 34552 | 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 | 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 | } |
| 34557 | 34779 | |
| 34558 | 34780 | try sema.flushExports(); |
| ... | ... | @@ -34620,6 +34842,7 @@ pub fn resolveUnionAlignment( |
| 34620 | 34842 | ) SemaError!void { |
| 34621 | 34843 | const pt = sema.pt; |
| 34622 | 34844 | const zcu = pt.zcu; |
| 34845 | const io = zcu.comp.io; | |
| 34623 | 34846 | const ip = &zcu.intern_pool; |
| 34624 | 34847 | const target = zcu.getTarget(); |
| 34625 | 34848 | |
| ... | ... | @@ -34632,7 +34855,7 @@ pub fn resolveUnionAlignment( |
| 34632 | 34855 | // We'll guess "pointer-aligned", if the union has an |
| 34633 | 34856 | // underaligned pointer field then some allocations |
| 34634 | 34857 | // might require explicit alignment. |
| 34635 | if (union_type.assumePointerAlignedIfFieldTypesWip(ip, ptr_align)) return; | |
| 34858 | if (union_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return; | |
| 34636 | 34859 | |
| 34637 | 34860 | try sema.resolveUnionFieldTypes(ty, union_type); |
| 34638 | 34861 | |
| ... | ... | @@ -34653,12 +34876,13 @@ pub fn resolveUnionAlignment( |
| 34653 | 34876 | max_align = max_align.max(field_align); |
| 34654 | 34877 | } |
| 34655 | 34878 | |
| 34656 | union_type.setAlignment(ip, max_align); | |
| 34879 | union_type.setAlignment(ip, io, max_align); | |
| 34657 | 34880 | } |
| 34658 | 34881 | |
| 34659 | 34882 | /// This logic must be kept in sync with `Type.getUnionLayout`. |
| 34660 | 34883 | pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { |
| 34661 | 34884 | const pt = sema.pt; |
| 34885 | const io = pt.zcu.comp.io; | |
| 34662 | 34886 | const ip = &pt.zcu.intern_pool; |
| 34663 | 34887 | |
| 34664 | 34888 | try sema.resolveUnionFieldTypes(ty, ip.loadUnionType(ty.ip_index)); |
| ... | ... | @@ -34682,9 +34906,9 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { |
| 34682 | 34906 | .have_layout, .fully_resolved_wip, .fully_resolved => return, |
| 34683 | 34907 | } |
| 34684 | 34908 | |
| 34685 | errdefer union_type.setStatusIfLayoutWip(ip, old_flags.status); | |
| 34909 | errdefer union_type.setStatusIfLayoutWip(ip, io, old_flags.status); | |
| 34686 | 34910 | |
| 34687 | union_type.setStatus(ip, .layout_wip); | |
| 34911 | union_type.setStatus(ip, io, .layout_wip); | |
| 34688 | 34912 | |
| 34689 | 34913 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. |
| 34690 | 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 | 34989 | ); |
| 34766 | 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); | |
| 34769 | 34993 | |
| 34770 | 34994 | if (union_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) { |
| 34771 | 34995 | const msg = try sema.errMsg( |
| ... | ... | @@ -34797,13 +35021,14 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void { |
| 34797 | 35021 | |
| 34798 | 35022 | const pt = sema.pt; |
| 34799 | 35023 | const zcu = pt.zcu; |
| 35024 | const io = zcu.comp.io; | |
| 34800 | 35025 | const ip = &zcu.intern_pool; |
| 34801 | 35026 | const struct_type = zcu.typeToStruct(ty).?; |
| 34802 | 35027 | |
| 34803 | 35028 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| 34804 | 35029 | |
| 34805 | if (struct_type.setFullyResolved(ip)) return; | |
| 34806 | errdefer struct_type.clearFullyResolved(ip); | |
| 35030 | if (struct_type.setFullyResolved(ip, io)) return; | |
| 35031 | errdefer struct_type.clearFullyResolved(ip, io); | |
| 34807 | 35032 | |
| 34808 | 35033 | // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. |
| 34809 | 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 | 35048 | |
| 34824 | 35049 | const pt = sema.pt; |
| 34825 | 35050 | const zcu = pt.zcu; |
| 35051 | const io = zcu.comp.io; | |
| 34826 | 35052 | const ip = &zcu.intern_pool; |
| 34827 | 35053 | const union_obj = zcu.typeToUnion(ty).?; |
| 34828 | 35054 | |
| ... | ... | @@ -34841,14 +35067,14 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void { |
| 34841 | 35067 | // make sure pointer fields get their child types resolved as well. |
| 34842 | 35068 | // See also similar code for structs. |
| 34843 | 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); | |
| 34845 | 35071 | |
| 34846 | union_obj.setStatus(ip, .fully_resolved_wip); | |
| 35072 | union_obj.setStatus(ip, io, .fully_resolved_wip); | |
| 34847 | 35073 | for (0..union_obj.field_types.len) |field_index| { |
| 34848 | 35074 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); |
| 34849 | 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 | } |
| 34853 | 35079 | |
| 34854 | 35080 | // And let's not forget comptime-only status. |
| ... | ... | @@ -34862,13 +35088,14 @@ pub fn resolveStructFieldTypes( |
| 34862 | 35088 | ) SemaError!void { |
| 34863 | 35089 | const pt = sema.pt; |
| 34864 | 35090 | const zcu = pt.zcu; |
| 35091 | const io = zcu.comp.io; | |
| 34865 | 35092 | const ip = &zcu.intern_pool; |
| 34866 | 35093 | |
| 34867 | 35094 | assert(sema.owner.unwrap().type == ty); |
| 34868 | 35095 | |
| 34869 | 35096 | if (struct_type.haveFieldTypes(ip)) return; |
| 34870 | 35097 | |
| 34871 | if (struct_type.setFieldTypesWip(ip)) { | |
| 35098 | if (struct_type.setFieldTypesWip(ip, io)) { | |
| 34872 | 35099 | const msg = try sema.errMsg( |
| 34873 | 35100 | Type.fromInterned(ty).srcLoc(zcu), |
| 34874 | 35101 | "struct '{f}' depends on itself", |
| ... | ... | @@ -34876,7 +35103,7 @@ pub fn resolveStructFieldTypes( |
| 34876 | 35103 | ); |
| 34877 | 35104 | return sema.failWithOwnedErrorMsg(null, msg); |
| 34878 | 35105 | } |
| 34879 | defer struct_type.clearFieldTypesWip(ip); | |
| 35106 | defer struct_type.clearFieldTypesWip(ip, io); | |
| 34880 | 35107 | |
| 34881 | 35108 | // can't happen earlier than this because we only want the progress node if not already resolved |
| 34882 | 35109 | const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null); |
| ... | ... | @@ -34891,6 +35118,7 @@ pub fn resolveStructFieldTypes( |
| 34891 | 35118 | pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { |
| 34892 | 35119 | const pt = sema.pt; |
| 34893 | 35120 | const zcu = pt.zcu; |
| 35121 | const io = zcu.comp.io; | |
| 34894 | 35122 | const ip = &zcu.intern_pool; |
| 34895 | 35123 | const struct_type = zcu.typeToStruct(ty) orelse return; |
| 34896 | 35124 | |
| ... | ... | @@ -34901,7 +35129,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { |
| 34901 | 35129 | |
| 34902 | 35130 | try sema.resolveStructLayout(ty); |
| 34903 | 35131 | |
| 34904 | if (struct_type.setInitsWip(ip)) { | |
| 35132 | if (struct_type.setInitsWip(ip, io)) { | |
| 34905 | 35133 | const msg = try sema.errMsg( |
| 34906 | 35134 | ty.srcLoc(zcu), |
| 34907 | 35135 | "struct '{f}' depends on itself", |
| ... | ... | @@ -34909,7 +35137,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { |
| 34909 | 35137 | ); |
| 34910 | 35138 | return sema.failWithOwnedErrorMsg(null, msg); |
| 34911 | 35139 | } |
| 34912 | defer struct_type.clearInitsWip(ip); | |
| 35140 | defer struct_type.clearInitsWip(ip, io); | |
| 34913 | 35141 | |
| 34914 | 35142 | // can't happen earlier than this because we only want the progress node if not already resolved |
| 34915 | 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 | 35147 | error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, |
| 34920 | 35148 | error.ComptimeBreak, error.ComptimeReturn => unreachable, |
| 34921 | 35149 | }; |
| 34922 | struct_type.setHaveFieldInits(ip); | |
| 35150 | struct_type.setHaveFieldInits(ip, io); | |
| 34923 | 35151 | } |
| 34924 | 35152 | |
| 34925 | 35153 | pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) SemaError!void { |
| 34926 | 35154 | const pt = sema.pt; |
| 34927 | 35155 | const zcu = pt.zcu; |
| 35156 | const io = zcu.comp.io; | |
| 34928 | 35157 | const ip = &zcu.intern_pool; |
| 34929 | 35158 | |
| 34930 | 35159 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| ... | ... | @@ -34947,13 +35176,13 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load |
| 34947 | 35176 | const tracked_unit = zcu.trackUnitSema(union_type.name.toSlice(ip), null); |
| 34948 | 35177 | defer tracked_unit.end(zcu); |
| 34949 | 35178 | |
| 34950 | union_type.setStatus(ip, .field_types_wip); | |
| 34951 | errdefer union_type.setStatus(ip, .none); | |
| 35179 | union_type.setStatus(ip, io, .field_types_wip); | |
| 35180 | errdefer union_type.setStatus(ip, io, .none); | |
| 34952 | 35181 | sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) { |
| 34953 | 35182 | error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, |
| 34954 | 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 | } |
| 34958 | 35187 | |
| 34959 | 35188 | /// Returns a normal error set corresponding to the fully populated inferred |
| ... | ... | @@ -35055,11 +35284,14 @@ fn resolveAdHocInferredErrorSet( |
| 35055 | 35284 | ) CompileError!InternPool.Index { |
| 35056 | 35285 | const pt = sema.pt; |
| 35057 | 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 | 35290 | const ip = &zcu.intern_pool; |
| 35291 | ||
| 35060 | 35292 | const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value)); |
| 35061 | 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 | } |
| 35064 | 35296 | |
| 35065 | 35297 | fn resolveAdHocInferredErrorSetTy( |
| ... | ... | @@ -35159,8 +35391,11 @@ fn structFields( |
| 35159 | 35391 | ) CompileError!void { |
| 35160 | 35392 | const pt = sema.pt; |
| 35161 | 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 | 35397 | const ip = &zcu.intern_pool; |
| 35398 | ||
| 35164 | 35399 | const namespace_index = struct_type.namespace; |
| 35165 | 35400 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?; |
| 35166 | 35401 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| ... | ... | @@ -35173,7 +35408,7 @@ fn structFields( |
| 35173 | 35408 | return; |
| 35174 | 35409 | }, |
| 35175 | 35410 | .auto, .@"extern" => { |
| 35176 | struct_type.setLayoutResolved(ip, 0, .none); | |
| 35411 | struct_type.setLayoutResolved(ip, io, 0, .none); | |
| 35177 | 35412 | return; |
| 35178 | 35413 | }, |
| 35179 | 35414 | }; |
| ... | ... | @@ -35245,7 +35480,7 @@ fn structFields( |
| 35245 | 35480 | extra_index += 1; |
| 35246 | 35481 | |
| 35247 | 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 | 35484 | assert(struct_type.addFieldName(ip, field_name) == null); |
| 35250 | 35485 | |
| 35251 | 35486 | if (has_align) { |
| ... | ... | @@ -35345,8 +35580,8 @@ fn structFields( |
| 35345 | 35580 | extra_index += zir_field.init_body_len; |
| 35346 | 35581 | } |
| 35347 | 35582 | |
| 35348 | struct_type.clearFieldTypesWip(ip); | |
| 35349 | if (!any_inits) struct_type.setHaveFieldInits(ip); | |
| 35583 | struct_type.clearFieldTypesWip(ip, io); | |
| 35584 | if (!any_inits) struct_type.setHaveFieldInits(ip, io); | |
| 35350 | 35585 | |
| 35351 | 35586 | try sema.flushExports(); |
| 35352 | 35587 | } |
| ... | ... | @@ -35485,8 +35720,11 @@ fn unionFields( |
| 35485 | 35720 | |
| 35486 | 35721 | const pt = sema.pt; |
| 35487 | 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 | 35726 | const ip = &zcu.intern_pool; |
| 35727 | ||
| 35490 | 35728 | const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir.?; |
| 35491 | 35729 | const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 35492 | 35730 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| ... | ... | @@ -35595,7 +35833,7 @@ fn unionFields( |
| 35595 | 35833 | .enum_type => ip.loadEnumType(provided_ty.toIntern()), |
| 35596 | 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 | 35837 | // The fields of the union must match the enum exactly. |
| 35600 | 35838 | // A flag per field is used to check for missing and extraneous fields. |
| 35601 | 35839 | explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len); |
| ... | ... | @@ -35727,7 +35965,7 @@ fn unionFields( |
| 35727 | 35965 | } |
| 35728 | 35966 | |
| 35729 | 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 | 35969 | if (enum_field_names.len != 0) { |
| 35732 | 35970 | enum_field_names[field_i] = field_name; |
| 35733 | 35971 | } |
| ... | ... | @@ -35871,10 +36109,10 @@ fn unionFields( |
| 35871 | 36109 | } |
| 35872 | 36110 | } else if (enum_field_vals.count() > 0) { |
| 35873 | 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 | 36113 | } else { |
| 35876 | 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 | } |
| 35879 | 36117 | |
| 35880 | 36118 | try sema.flushExports(); |
| ... | ... | @@ -35890,18 +36128,21 @@ fn generateUnionTagTypeNumbered( |
| 35890 | 36128 | ) !InternPool.Index { |
| 35891 | 36129 | const pt = sema.pt; |
| 35892 | 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 | 36134 | const ip = &zcu.intern_pool; |
| 35895 | 36135 | |
| 35896 | 36136 | const name = try ip.getOrPutStringFmt( |
| 35897 | 36137 | gpa, |
| 36138 | io, | |
| 35898 | 36139 | pt.tid, |
| 35899 | 36140 | "@typeInfo({f}).@\"union\".tag_type.?", |
| 35900 | 36141 | .{union_name.fmt(ip)}, |
| 35901 | 36142 | .no_embedded_nulls, |
| 35902 | 36143 | ); |
| 35903 | 36144 | |
| 35904 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{ | |
| 36145 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{ | |
| 35905 | 36146 | .name = name, |
| 35906 | 36147 | .owner_union_ty = union_type, |
| 35907 | 36148 | .tag_ty = if (enum_field_vals.len == 0) |
| ... | ... | @@ -35926,18 +36167,21 @@ fn generateUnionTagTypeSimple( |
| 35926 | 36167 | ) !InternPool.Index { |
| 35927 | 36168 | const pt = sema.pt; |
| 35928 | 36169 | const zcu = pt.zcu; |
| 36170 | const comp = zcu.comp; | |
| 36171 | const gpa = comp.gpa; | |
| 36172 | const io = comp.io; | |
| 35929 | 36173 | const ip = &zcu.intern_pool; |
| 35930 | const gpa = sema.gpa; | |
| 35931 | 36174 | |
| 35932 | 36175 | const name = try ip.getOrPutStringFmt( |
| 35933 | 36176 | gpa, |
| 36177 | io, | |
| 35934 | 36178 | pt.tid, |
| 35935 | 36179 | "@typeInfo({f}).@\"union\".tag_type.?", |
| 35936 | 36180 | .{union_name.fmt(ip)}, |
| 35937 | 36181 | .no_embedded_nulls, |
| 35938 | 36182 | ); |
| 35939 | 36183 | |
| 35940 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{ | |
| 36184 | const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{ | |
| 35941 | 36185 | .name = name, |
| 35942 | 36186 | .owner_union_ty = union_type, |
| 35943 | 36187 | .tag_ty = (try pt.smallestUnsignedInt(enum_field_names.len -| 1)).toIntern(), |
| ... | ... | @@ -35958,7 +36202,11 @@ fn generateUnionTagTypeSimple( |
| 35958 | 36202 | pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 35959 | 36203 | const pt = sema.pt; |
| 35960 | 36204 | const zcu = pt.zcu; |
| 36205 | const comp = zcu.comp; | |
| 36206 | const gpa = comp.gpa; | |
| 36207 | const io = comp.io; | |
| 35961 | 36208 | const ip = &zcu.intern_pool; |
| 36209 | ||
| 35962 | 36210 | return switch (ty.toIntern()) { |
| 35963 | 36211 | .u0_type, |
| 35964 | 36212 | .i0_type, |
| ... | ... | @@ -36302,7 +36550,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36302 | 36550 | (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() |
| 36303 | 36551 | else |
| 36304 | 36552 | try ip.getCoercedInts( |
| 36305 | zcu.gpa, | |
| 36553 | gpa, | |
| 36554 | io, | |
| 36306 | 36555 | pt.tid, |
| 36307 | 36556 | ip.indexToKey(enum_type.values.get(ip)[0]).int, |
| 36308 | 36557 | enum_type.tag_ty, |
| ... | ... | @@ -36936,12 +37185,16 @@ fn checkRuntimeValue(sema: *Sema, ptr: Air.Inst.Ref) bool { |
| 36936 | 37185 | fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Air.Inst.Ref) CompileError!void { |
| 36937 | 37186 | if (sema.checkRuntimeValue(val)) return; |
| 36938 | 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 | 37188 | const pt = sema.pt; |
| 36943 | 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 | 37198 | try sema.explainWhyValueContainsReferenceToComptimeVar(msg, val_src, val_str, .fromInterned(val.toInterned().?)); |
| 36946 | 37199 | break :msg msg; |
| 36947 | 37200 | }); |
| ... | ... | @@ -37385,7 +37638,9 @@ fn resolveDeclaredEnumInner( |
| 37385 | 37638 | ) Zcu.CompileError!void { |
| 37386 | 37639 | const pt = sema.pt; |
| 37387 | 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 | 37644 | const ip = &zcu.intern_pool; |
| 37390 | 37645 | |
| 37391 | 37646 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; |
| ... | ... | @@ -37430,7 +37685,7 @@ fn resolveDeclaredEnumInner( |
| 37430 | 37685 | const field_name_zir = zir.nullTerminatedString(field_name_index); |
| 37431 | 37686 | extra_index += 1; // field name |
| 37432 | 37687 | |
| 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); | |
| 37434 | 37689 | |
| 37435 | 37690 | const value_src: LazySrcLoc = .{ |
| 37436 | 37691 | .base_node_inst = tracked_inst, |
| ... | ... | @@ -37541,7 +37796,9 @@ pub fn resolveNavPtrModifiers( |
| 37541 | 37796 | ) CompileError!NavPtrModifiers { |
| 37542 | 37797 | const pt = sema.pt; |
| 37543 | 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 | 37802 | const ip = &zcu.intern_pool; |
| 37546 | 37803 | |
| 37547 | 37804 | const align_src = block.src(.{ .node_offset_var_decl_align = .zero }); |
| ... | ... | @@ -37563,7 +37820,7 @@ pub fn resolveNavPtrModifiers( |
| 37563 | 37820 | } else if (bytes.len == 0) { |
| 37564 | 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 | }; |
| 37568 | 37825 | |
| 37569 | 37826 | const @"addrspace": std.builtin.AddressSpace = as: { |
| ... | ... | @@ -37595,8 +37852,10 @@ pub fn resolveNavPtrModifiers( |
| 37595 | 37852 | pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool { |
| 37596 | 37853 | const pt = sema.pt; |
| 37597 | 37854 | const zcu = pt.zcu; |
| 37855 | const comp = zcu.comp; | |
| 37856 | const gpa = comp.gpa; | |
| 37857 | const io = comp.io; | |
| 37598 | 37858 | const ip = &zcu.intern_pool; |
| 37599 | const gpa = zcu.gpa; | |
| 37600 | 37859 | |
| 37601 | 37860 | var any_changed = false; |
| 37602 | 37861 | |
| ... | ... | @@ -37613,7 +37872,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, |
| 37613 | 37872 | }, |
| 37614 | 37873 | }; |
| 37615 | 37874 | |
| 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 | 37876 | const nav = try sema.namespaceLookup(block, simple_src, parent_ns, name_nts) orelse |
| 37618 | 37877 | return sema.fail(block, simple_src, "{s} missing {s}", .{ parent_name, name }); |
| 37619 | 37878 |
src/Sema/LowerZon.zig+51-24| ... | ... | @@ -38,8 +38,11 @@ pub fn run( |
| 38 | 38 | block: *Sema.Block, |
| 39 | 39 | ) CompileError!InternPool.Index { |
| 40 | 40 | const pt = sema.pt; |
| 41 | const comp = pt.zcu.comp; | |
| 42 | const gpa = comp.gpa; | |
| 43 | const io = comp.io; | |
| 41 | 44 | |
| 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 | 46 | .file = file_index, |
| 44 | 47 | .inst = .main_struct_inst, // this is the only trackable instruction in a ZON file |
| 45 | 48 | }); |
| ... | ... | @@ -63,8 +66,10 @@ pub fn run( |
| 63 | 66 | } |
| 64 | 67 | |
| 65 | 68 | fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!InternPool.Index { |
| 66 | const gpa = self.sema.gpa; | |
| 67 | 69 | const pt = self.sema.pt; |
| 70 | const comp = pt.zcu.comp; | |
| 71 | const gpa = comp.gpa; | |
| 72 | const io = comp.io; | |
| 68 | 73 | const ip = &pt.zcu.intern_pool; |
| 69 | 74 | switch (node.get(self.file.zoir.?)) { |
| 70 | 75 | .true => return .bool_true, |
| ... | ... | @@ -94,13 +99,14 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter |
| 94 | 99 | .enum_literal => |val| return pt.intern(.{ |
| 95 | 100 | .enum_literal = try ip.getOrPutString( |
| 96 | 101 | gpa, |
| 102 | io, | |
| 97 | 103 | pt.tid, |
| 98 | 104 | val.get(self.file.zoir.?), |
| 99 | 105 | .no_embedded_nulls, |
| 100 | 106 | ), |
| 101 | 107 | }), |
| 102 | 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 | 110 | const result = try self.sema.addStrLit(ip_str, val.len); |
| 105 | 111 | return result.toInterned().?; |
| 106 | 112 | }, |
| ... | ... | @@ -112,14 +118,10 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter |
| 112 | 118 | values[i] = try self.lowerExprAnonResTy(nodes.at(@intCast(i))); |
| 113 | 119 | types[i] = Value.fromInterned(values[i]).typeOf(pt.zcu).toIntern(); |
| 114 | 120 | } |
| 115 | const ty = try ip.getTupleType( | |
| 116 | gpa, | |
| 117 | pt.tid, | |
| 118 | .{ | |
| 119 | .types = types, | |
| 120 | .values = values, | |
| 121 | }, | |
| 122 | ); | |
| 121 | const ty = try ip.getTupleType(gpa, io, pt.tid, .{ | |
| 122 | .types = types, | |
| 123 | .values = values, | |
| 124 | }); | |
| 123 | 125 | return (try pt.aggregateValue(.fromInterned(ty), values)).toIntern(); |
| 124 | 126 | }, |
| 125 | 127 | .struct_literal => |init| { |
| ... | ... | @@ -129,6 +131,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter |
| 129 | 131 | } |
| 130 | 132 | const struct_ty = switch (try ip.getStructType( |
| 131 | 133 | gpa, |
| 134 | io, | |
| 132 | 135 | pt.tid, |
| 133 | 136 | .{ |
| 134 | 137 | .layout = .auto, |
| ... | ... | @@ -168,6 +171,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter |
| 168 | 171 | for (init.names, 0..) |name, field_idx| { |
| 169 | 172 | const name_interned = try ip.getOrPutString( |
| 170 | 173 | gpa, |
| 174 | io, | |
| 171 | 175 | pt.tid, |
| 172 | 176 | name.get(self.file.zoir.?), |
| 173 | 177 | .no_embedded_nulls, |
| ... | ... | @@ -636,11 +640,16 @@ fn lowerArray(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 636 | 640 | } |
| 637 | 641 | |
| 638 | 642 | fn 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 | 648 | switch (node.get(self.file.zoir.?)) { |
| 641 | 649 | .enum_literal => |field_name| { |
| 642 | 650 | const field_name_interned = try ip.getOrPutString( |
| 643 | self.sema.gpa, | |
| 651 | gpa, | |
| 652 | io, | |
| 644 | 653 | self.sema.pt.tid, |
| 645 | 654 | field_name.get(self.file.zoir.?), |
| 646 | 655 | .no_embedded_nulls, |
| ... | ... | @@ -665,11 +674,16 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I |
| 665 | 674 | } |
| 666 | 675 | |
| 667 | 676 | fn 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 | 682 | switch (node.get(self.file.zoir.?)) { |
| 670 | 683 | .enum_literal => |field_name| { |
| 671 | 684 | const field_name_interned = try ip.getOrPutString( |
| 672 | self.sema.gpa, | |
| 685 | gpa, | |
| 686 | io, | |
| 673 | 687 | self.sema.pt.tid, |
| 674 | 688 | field_name.get(self.file.zoir.?), |
| 675 | 689 | .no_embedded_nulls, |
| ... | ... | @@ -747,8 +761,11 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 747 | 761 | } |
| 748 | 762 | |
| 749 | 763 | fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { |
| 750 | const ip = &self.sema.pt.zcu.intern_pool; | |
| 751 | const gpa = self.sema.gpa; | |
| 764 | const pt = self.sema.pt; | |
| 765 | const comp = pt.zcu.comp; | |
| 766 | const gpa = comp.gpa; | |
| 767 | const io = comp.io; | |
| 768 | const ip = &pt.zcu.intern_pool; | |
| 752 | 769 | |
| 753 | 770 | try res_ty.resolveFields(self.sema.pt); |
| 754 | 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 | 789 | for (0..fields.names.len) |i| { |
| 773 | 790 | const field_name = try ip.getOrPutString( |
| 774 | 791 | gpa, |
| 792 | io, | |
| 775 | 793 | self.sema.pt.tid, |
| 776 | 794 | fields.names[i].get(self.file.zoir.?), |
| 777 | 795 | .no_embedded_nulls, |
| ... | ... | @@ -807,8 +825,11 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool |
| 807 | 825 | } |
| 808 | 826 | |
| 809 | 827 | fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.Index { |
| 810 | const ip = &self.sema.pt.zcu.intern_pool; | |
| 811 | const gpa = self.sema.gpa; | |
| 828 | const pt = self.sema.pt; | |
| 829 | const comp = pt.zcu.comp; | |
| 830 | const gpa = comp.gpa; | |
| 831 | const io = comp.io; | |
| 832 | const ip = &pt.zcu.intern_pool; | |
| 812 | 833 | |
| 813 | 834 | const ptr_info = res_ty.ptrInfo(self.sema.pt.zcu); |
| 814 | 835 | |
| ... | ... | @@ -820,7 +841,7 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 820 | 841 | if (string_alignment and ptr_info.child == .u8_type and string_sentinel) { |
| 821 | 842 | switch (node.get(self.file.zoir.?)) { |
| 822 | 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 | 845 | const str_ref = try self.sema.addStrLit(ip_str, val.len); |
| 825 | 846 | return (try self.sema.coerce( |
| 826 | 847 | self.block, |
| ... | ... | @@ -892,7 +913,11 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 892 | 913 | } |
| 893 | 914 | |
| 894 | 915 | fn 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 | 921 | try res_ty.resolveFields(self.sema.pt); |
| 897 | 922 | const union_info = self.sema.pt.zcu.typeToUnion(res_ty).?; |
| 898 | 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 | 925 | const field_name, const maybe_field_node = switch (node.get(self.file.zoir.?)) { |
| 901 | 926 | .enum_literal => |name| b: { |
| 902 | 927 | const field_name = try ip.getOrPutString( |
| 903 | self.sema.gpa, | |
| 928 | gpa, | |
| 929 | io, | |
| 904 | 930 | self.sema.pt.tid, |
| 905 | 931 | name.get(self.file.zoir.?), |
| 906 | 932 | .no_embedded_nulls, |
| ... | ... | @@ -916,7 +942,8 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 916 | 942 | return error.WrongType; |
| 917 | 943 | } |
| 918 | 944 | const field_name = try ip.getOrPutString( |
| 919 | self.sema.gpa, | |
| 945 | gpa, | |
| 946 | io, | |
| 920 | 947 | self.sema.pt.tid, |
| 921 | 948 | fields.names[0].get(self.file.zoir.?), |
| 922 | 949 | .no_embedded_nulls, |
| ... | ... | @@ -942,7 +969,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 942 | 969 | } |
| 943 | 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 | 973 | .ty = res_ty.toIntern(), |
| 947 | 974 | .tag = tag.toIntern(), |
| 948 | 975 | .val = val, |
src/Type.zig+20-14| ... | ... | @@ -486,6 +486,7 @@ pub fn hasRuntimeBitsInner( |
| 486 | 486 | tid: strat.Tid(), |
| 487 | 487 | ) RuntimeBitsError!bool { |
| 488 | 488 | const ip = &zcu.intern_pool; |
| 489 | const io = zcu.comp.io; | |
| 489 | 490 | return switch (ty.toIntern()) { |
| 490 | 491 | .empty_tuple_type => false, |
| 491 | 492 | else => switch (ip.indexToKey(ty.toIntern())) { |
| ... | ... | @@ -571,7 +572,7 @@ pub fn hasRuntimeBitsInner( |
| 571 | 572 | }, |
| 572 | 573 | .struct_type => { |
| 573 | 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 | 576 | // In this case, we guess that hasRuntimeBits() for this type is true, |
| 576 | 577 | // and then later if our guess was incorrect, we emit a compile error. |
| 577 | 578 | return true; |
| ... | ... | @@ -610,7 +611,7 @@ pub fn hasRuntimeBitsInner( |
| 610 | 611 | .none => if (strat != .eager) { |
| 611 | 612 | // In this case, we guess that hasRuntimeBits() for this type is true, |
| 612 | 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 | 616 | .safety, .tagged => {}, |
| 616 | 617 | } |
| ... | ... | @@ -2491,8 +2492,11 @@ pub fn isNumeric(ty: Type, zcu: *const Zcu) bool { |
| 2491 | 2492 | /// resolves field types rather than asserting they are already resolved. |
| 2492 | 2493 | pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { |
| 2493 | 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 | 2498 | const ip = &zcu.intern_pool; |
| 2499 | var ty = starting_type; | |
| 2496 | 2500 | while (true) switch (ty.toIntern()) { |
| 2497 | 2501 | .empty_tuple_type => return Value.empty_tuple, |
| 2498 | 2502 | |
| ... | ... | @@ -2664,7 +2668,8 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { |
| 2664 | 2668 | (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() |
| 2665 | 2669 | else |
| 2666 | 2670 | try ip.getCoercedInts( |
| 2667 | zcu.gpa, | |
| 2671 | gpa, | |
| 2672 | io, | |
| 2668 | 2673 | pt.tid, |
| 2669 | 2674 | ip.indexToKey(enum_type.values.get(ip)[0]).int, |
| 2670 | 2675 | enum_type.tag_ty, |
| ... | ... | @@ -2720,6 +2725,7 @@ pub fn comptimeOnlyInner( |
| 2720 | 2725 | tid: strat.Tid(), |
| 2721 | 2726 | ) SemaError!bool { |
| 2722 | 2727 | const ip = &zcu.intern_pool; |
| 2728 | const io = zcu.comp.io; | |
| 2723 | 2729 | return switch (ty.toIntern()) { |
| 2724 | 2730 | .empty_tuple_type => false, |
| 2725 | 2731 | |
| ... | ... | @@ -2798,16 +2804,16 @@ pub fn comptimeOnlyInner( |
| 2798 | 2804 | .yes => true, |
| 2799 | 2805 | .unknown => unreachable, |
| 2800 | 2806 | }, |
| 2801 | .sema => switch (struct_type.setRequiresComptimeWip(ip)) { | |
| 2807 | .sema => switch (struct_type.setRequiresComptimeWip(ip, io)) { | |
| 2802 | 2808 | .no, .wip => false, |
| 2803 | 2809 | .yes => true, |
| 2804 | 2810 | .unknown => { |
| 2805 | 2811 | if (struct_type.flagsUnordered(ip).field_types_wip) { |
| 2806 | struct_type.setRequiresComptime(ip, .unknown); | |
| 2812 | struct_type.setRequiresComptime(ip, io, .unknown); | |
| 2807 | 2813 | return false; |
| 2808 | 2814 | } |
| 2809 | 2815 | |
| 2810 | errdefer struct_type.setRequiresComptime(ip, .unknown); | |
| 2816 | errdefer struct_type.setRequiresComptime(ip, io, .unknown); | |
| 2811 | 2817 | |
| 2812 | 2818 | const pt = strat.pt(zcu, tid); |
| 2813 | 2819 | try ty.resolveFields(pt); |
| ... | ... | @@ -2821,12 +2827,12 @@ pub fn comptimeOnlyInner( |
| 2821 | 2827 | // be considered resolved. Comptime-only types |
| 2822 | 2828 | // still maintain a layout of their |
| 2823 | 2829 | // runtime-known fields. |
| 2824 | struct_type.setRequiresComptime(ip, .yes); | |
| 2830 | struct_type.setRequiresComptime(ip, io, .yes); | |
| 2825 | 2831 | return true; |
| 2826 | 2832 | } |
| 2827 | 2833 | } |
| 2828 | 2834 | |
| 2829 | struct_type.setRequiresComptime(ip, .no); | |
| 2835 | struct_type.setRequiresComptime(ip, io, .no); | |
| 2830 | 2836 | return false; |
| 2831 | 2837 | }, |
| 2832 | 2838 | }, |
| ... | ... | @@ -2850,16 +2856,16 @@ pub fn comptimeOnlyInner( |
| 2850 | 2856 | .yes => true, |
| 2851 | 2857 | .unknown => unreachable, |
| 2852 | 2858 | }, |
| 2853 | .sema => switch (union_type.setRequiresComptimeWip(ip)) { | |
| 2859 | .sema => switch (union_type.setRequiresComptimeWip(ip, io)) { | |
| 2854 | 2860 | .no, .wip => return false, |
| 2855 | 2861 | .yes => return true, |
| 2856 | 2862 | .unknown => { |
| 2857 | 2863 | if (union_type.flagsUnordered(ip).status == .field_types_wip) { |
| 2858 | union_type.setRequiresComptime(ip, .unknown); | |
| 2864 | union_type.setRequiresComptime(ip, io, .unknown); | |
| 2859 | 2865 | return false; |
| 2860 | 2866 | } |
| 2861 | 2867 | |
| 2862 | errdefer union_type.setRequiresComptime(ip, .unknown); | |
| 2868 | errdefer union_type.setRequiresComptime(ip, io, .unknown); | |
| 2863 | 2869 | |
| 2864 | 2870 | const pt = strat.pt(zcu, tid); |
| 2865 | 2871 | try ty.resolveFields(pt); |
| ... | ... | @@ -2867,12 +2873,12 @@ pub fn comptimeOnlyInner( |
| 2867 | 2873 | for (0..union_type.field_types.len) |field_idx| { |
| 2868 | 2874 | const field_ty = union_type.field_types.get(ip)[field_idx]; |
| 2869 | 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 | 2877 | return true; |
| 2872 | 2878 | } |
| 2873 | 2879 | } |
| 2874 | 2880 | |
| 2875 | union_type.setRequiresComptime(ip, .no); | |
| 2881 | union_type.setRequiresComptime(ip, io, .no); | |
| 2876 | 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 | 60 | /// Asserts `val` is an array of `u8` |
| 61 | 61 | pub fn toIpString(val: Value, ty: Type, pt: Zcu.PerThread) !InternPool.NullTerminatedString { |
| 62 | 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 | 67 | assert(ty.zigTypeTag(zcu) == .array); |
| 64 | 68 | assert(ty.childType(zcu).toIntern() == .u8_type); |
| 65 | const ip = &zcu.intern_pool; | |
| 66 | 69 | switch (zcu.intern_pool.indexToKey(val.toIntern()).aggregate.storage) { |
| 67 | 70 | .bytes => |bytes| return bytes.toNullTerminatedString(ty.arrayLen(zcu), ip), |
| 68 | 71 | .elems => return arrayToIpString(val, ty.arrayLen(zcu), pt), |
| 69 | 72 | .repeated_elem => |elem| { |
| 70 | 73 | const byte: u8 = @intCast(Value.fromInterned(elem).toUnsignedInt(zcu)); |
| 71 | 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 | 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 | 112 | |
| 110 | 113 | fn arrayToIpString(val: Value, len_u64: u64, pt: Zcu.PerThread) !InternPool.NullTerminatedString { |
| 111 | 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 | 118 | const ip = &zcu.intern_pool; |
| 114 | 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 | 121 | try string_bytes.ensureUnusedCapacity(len); |
| 117 | 122 | for (0..len) |i| { |
| 118 | 123 | // 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 | 128 | const byte: u8 = @intCast(elem_val.toUnsignedInt(zcu)); |
| 124 | 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 | } |
| 128 | 133 | |
| 129 | 134 | pub fn fromInterned(i: InternPool.Index) Value { |
| ... | ... | @@ -1141,6 +1146,7 @@ pub fn sliceArray( |
| 1141 | 1146 | ) error{OutOfMemory}!Value { |
| 1142 | 1147 | const pt = sema.pt; |
| 1143 | 1148 | const ip = &pt.zcu.intern_pool; |
| 1149 | const io = pt.zcu.comp.io; | |
| 1144 | 1150 | return Value.fromInterned(try pt.intern(.{ |
| 1145 | 1151 | .aggregate = .{ |
| 1146 | 1152 | .ty = switch (pt.zcu.intern_pool.indexToKey(pt.zcu.intern_pool.typeOf(val.toIntern()))) { |
| ... | ... | @@ -1160,6 +1166,7 @@ pub fn sliceArray( |
| 1160 | 1166 | try ip.string_bytes.ensureUnusedCapacity(sema.gpa, end - start + 1); |
| 1161 | 1167 | break :storage .{ .bytes = try ip.getOrPutString( |
| 1162 | 1168 | sema.gpa, |
| 1169 | io, | |
| 1163 | 1170 | bytes.toSlice(end, ip)[start..], |
| 1164 | 1171 | .maybe_embedded_nulls, |
| 1165 | 1172 | ) }; |
| ... | ... | @@ -2874,6 +2881,7 @@ const interpret_mode: InterpretMode = @field(InterpretMode, @tagName(build_optio |
| 2874 | 2881 | /// `val` must be fully resolved. |
| 2875 | 2882 | pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T { |
| 2876 | 2883 | const zcu = pt.zcu; |
| 2884 | const io = zcu.comp.io; | |
| 2877 | 2885 | const ip = &zcu.intern_pool; |
| 2878 | 2886 | const ty = val.typeOf(zcu); |
| 2879 | 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 | 2968 | const struct_obj = zcu.typeToStruct(ty) orelse return error.TypeMismatch; |
| 2961 | 2969 | var result: T = undefined; |
| 2962 | 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 | 2972 | @field(result, field.name) = if (struct_obj.nameIndex(ip, field_name_ip)) |field_idx| f: { |
| 2965 | 2973 | const field_val = try val.fieldValue(pt, field_idx); |
| 2966 | 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 | 2987 | const T = @TypeOf(val); |
| 2980 | 2988 | |
| 2981 | 2989 | const zcu = pt.zcu; |
| 2990 | const io = zcu.comp.io; | |
| 2982 | 2991 | const ip = &zcu.intern_pool; |
| 2983 | 2992 | if (ty.zigTypeTag(zcu) != @typeInfo(T)) return error.TypeMismatch; |
| 2984 | 2993 | |
| ... | ... | @@ -3022,7 +3031,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory |
| 3022 | 3031 | .@"enum" => switch (interpret_mode) { |
| 3023 | 3032 | .direct => try pt.enumValue(ty, (try uninterpret(@intFromEnum(val), ty.intTagType(zcu), pt)).toIntern()), |
| 3024 | 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 | 3035 | const field_idx = ty.enumFieldIndex(field_name_ip, zcu) orelse return error.TypeMismatch; |
| 3027 | 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 | 3068 | defer zcu.gpa.free(field_vals); |
| 3060 | 3069 | @memset(field_vals, .none); |
| 3061 | 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 | 3072 | if (struct_obj.nameIndex(ip, field_name_ip)) |field_idx| { |
| 3064 | 3073 | const field_ty = ty.fieldType(field_idx, zcu); |
| 3065 | 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 | 37 | const Alignment = InternPool.Alignment; |
| 38 | 38 | const AnalUnit = InternPool.AnalUnit; |
| 39 | 39 | const BuiltinFn = std.zig.BuiltinFn; |
| 40 | const codegen = @import("codegen.zig"); | |
| 40 | 41 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 41 | 42 | const dev = @import("dev.zig"); |
| 42 | 43 | const Zoir = std.zig.Zoir; |
| ... | ... | @@ -317,6 +318,8 @@ incremental_debug_state: if (build_options.enable_debug_extensions) IncrementalD |
| 317 | 318 | /// this timer must be temporarily paused and resumed later. |
| 318 | 319 | cur_analysis_timer: ?Compilation.Timer = null, |
| 319 | 320 | |
| 321 | codegen_task_pool: CodegenTaskPool, | |
| 322 | ||
| 320 | 323 | generation: u32 = 0, |
| 321 | 324 | |
| 322 | 325 | pub const IncrementalDebugState = struct { |
| ... | ... | @@ -895,12 +898,13 @@ pub const Namespace = struct { |
| 895 | 898 | ns: Namespace, |
| 896 | 899 | ip: *InternPool, |
| 897 | 900 | gpa: Allocator, |
| 901 | io: Io, | |
| 898 | 902 | tid: Zcu.PerThread.Id, |
| 899 | 903 | name: InternPool.NullTerminatedString, |
| 900 | 904 | ) !InternPool.NullTerminatedString { |
| 901 | 905 | const ns_name = Type.fromInterned(ns.owner_type).containerTypeName(ip); |
| 902 | 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 | }; |
| 906 | 910 | |
| ... | ... | @@ -1139,13 +1143,15 @@ pub const File = struct { |
| 1139 | 1143 | } |
| 1140 | 1144 | |
| 1141 | 1145 | pub fn internFullyQualifiedName(file: File, pt: Zcu.PerThread) !InternPool.NullTerminatedString { |
| 1142 | const gpa = pt.zcu.gpa; | |
| 1143 | 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 | 1151 | var w: Writer = .fixed((try string_bytes.addManyAsSlice(file.fullyQualifiedNameLen()))[0]); |
| 1146 | 1152 | file.renderFullyQualifiedName(&w) catch unreachable; |
| 1147 | 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 | } |
| 1150 | 1156 | |
| 1151 | 1157 | pub const Index = InternPool.FileIndex; |
| ... | ... | @@ -2801,13 +2807,14 @@ pub const CompileError = error{ |
| 2801 | 2807 | ComptimeBreak, |
| 2802 | 2808 | }; |
| 2803 | 2809 | |
| 2804 | pub fn init(zcu: *Zcu, thread_count: usize) !void { | |
| 2805 | const gpa = zcu.gpa; | |
| 2806 | try zcu.intern_pool.init(gpa, thread_count); | |
| 2810 | pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void { | |
| 2811 | try zcu.intern_pool.init(gpa, io, thread_count); | |
| 2807 | 2812 | } |
| 2808 | 2813 | |
| 2809 | 2814 | pub 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 | 2819 | const pt: Zcu.PerThread = .activate(zcu, .main); |
| 2813 | 2820 | defer pt.deactivate(); |
| ... | ... | @@ -2897,7 +2904,7 @@ pub fn deinit(zcu: *Zcu) void { |
| 2897 | 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 | } |
| 2902 | 2909 | |
| 2903 | 2910 | pub fn namespacePtr(zcu: *Zcu, index: Namespace.Index) *Namespace { |
| ... | ... | @@ -4442,7 +4449,7 @@ pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void { |
| 4442 | 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 | } |
| 4448 | 4455 | |
| ... | ... | @@ -4620,10 +4627,12 @@ pub fn codegenFail( |
| 4620 | 4627 | |
| 4621 | 4628 | /// Takes ownership of `msg`, even on OOM. |
| 4622 | 4629 | pub 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(); | |
| 4626 | defer zcu.comp.mutex.unlock(); | |
| 4634 | comp.mutex.lockUncancelable(io); | |
| 4635 | defer comp.mutex.unlock(io); | |
| 4627 | 4636 | errdefer msg.deinit(gpa); |
| 4628 | 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 | 4641 | |
| 4633 | 4642 | /// Asserts that `zcu.failed_codegen` contains the key `nav`, with the necessary lock held. |
| 4634 | 4643 | pub fn assertCodegenFailed(zcu: *Zcu, nav: InternPool.Nav.Index) void { |
| 4635 | zcu.comp.mutex.lock(); | |
| 4636 | defer zcu.comp.mutex.unlock(); | |
| 4644 | const comp = zcu.comp; | |
| 4645 | const io = comp.io; | |
| 4646 | comp.mutex.lockUncancelable(io); | |
| 4647 | defer comp.mutex.unlock(io); | |
| 4637 | 4648 | assert(zcu.failed_codegen.contains(nav)); |
| 4638 | 4649 | } |
| 4639 | 4650 | |
| ... | ... | @@ -4794,8 +4805,9 @@ const TrackedUnitSema = struct { |
| 4794 | 4805 | report_time: { |
| 4795 | 4806 | const sema_ns = zcu.cur_analysis_timer.?.finish() orelse break :report_time; |
| 4796 | 4807 | const zir_decl = tus.analysis_timer_decl orelse break :report_time; |
| 4797 | comp.mutex.lock(); | |
| 4798 | defer comp.mutex.unlock(); | |
| 4808 | const io = comp.io; | |
| 4809 | comp.mutex.lockUncancelable(io); | |
| 4810 | defer comp.mutex.unlock(io); | |
| 4799 | 4811 | comp.time_report.?.stats.cpu_ns_sema += sema_ns; |
| 4800 | 4812 | const gop = comp.time_report.?.decl_sema_info.getOrPut(comp.gpa, zir_decl) catch |err| switch (err) { |
| 4801 | 4813 | error.OutOfMemory => { |
| ... | ... | @@ -4830,3 +4842,170 @@ pub fn trackUnitSema(zcu: *Zcu, name: []const u8, zir_inst: ?InternPool.TrackedI |
| 4830 | 4842 | .analysis_timer_decl = zir_inst, |
| 4831 | 4843 | }; |
| 4832 | 4844 | } |
| 4845 | ||
| 4846 | pub 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 | 269 | // Any potential AST errors are converted to ZIR errors when we run AstGen/ZonGen. |
| 270 | 270 | file.tree = try Ast.parse(gpa, source, file.getMode()); |
| 271 | 271 | if (timer.finish()) |ns_parse| { |
| 272 | comp.mutex.lock(); | |
| 273 | defer comp.mutex.unlock(); | |
| 272 | comp.mutex.lockUncancelable(io); | |
| 273 | defer comp.mutex.unlock(io); | |
| 274 | 274 | comp.time_report.?.stats.cpu_ns_parse += ns_parse; |
| 275 | 275 | } |
| 276 | 276 | |
| ... | ... | @@ -295,8 +295,8 @@ pub fn updateFile( |
| 295 | 295 | }, |
| 296 | 296 | } |
| 297 | 297 | if (timer.finish()) |ns_astgen| { |
| 298 | comp.mutex.lock(); | |
| 299 | defer comp.mutex.unlock(); | |
| 298 | comp.mutex.lockUncancelable(io); | |
| 299 | defer comp.mutex.unlock(io); | |
| 300 | 300 | comp.time_report.?.stats.cpu_ns_astgen += ns_astgen; |
| 301 | 301 | } |
| 302 | 302 | |
| ... | ... | @@ -315,8 +315,8 @@ pub fn updateFile( |
| 315 | 315 | switch (file.getMode()) { |
| 316 | 316 | .zig => { |
| 317 | 317 | if (file.zir.?.hasCompileErrors()) { |
| 318 | comp.mutex.lock(); | |
| 319 | defer comp.mutex.unlock(); | |
| 318 | comp.mutex.lockUncancelable(io); | |
| 319 | defer comp.mutex.unlock(io); | |
| 320 | 320 | try zcu.failed_files.putNoClobber(gpa, file_index, null); |
| 321 | 321 | } |
| 322 | 322 | if (file.zir.?.loweringFailed()) { |
| ... | ... | @@ -328,8 +328,8 @@ pub fn updateFile( |
| 328 | 328 | .zon => { |
| 329 | 329 | if (file.zoir.?.hasCompileErrors()) { |
| 330 | 330 | file.status = .astgen_failure; |
| 331 | comp.mutex.lock(); | |
| 332 | defer comp.mutex.unlock(); | |
| 331 | comp.mutex.lockUncancelable(io); | |
| 332 | defer comp.mutex.unlock(io); | |
| 333 | 333 | try zcu.failed_files.putNoClobber(gpa, file_index, null); |
| 334 | 334 | } else { |
| 335 | 335 | file.status = .success; |
| ... | ... | @@ -415,7 +415,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 415 | 415 | const zcu = pt.zcu; |
| 416 | 416 | const comp = zcu.comp; |
| 417 | 417 | const ip = &zcu.intern_pool; |
| 418 | const gpa = zcu.gpa; | |
| 418 | const gpa = comp.gpa; | |
| 419 | const io = comp.io; | |
| 419 | 420 | |
| 420 | 421 | // We need to visit every updated File for every TrackedInst in InternPool. |
| 421 | 422 | // This only includes Zig files; ZON files are omitted. |
| ... | ... | @@ -459,7 +460,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 459 | 460 | return; |
| 460 | 461 | |
| 461 | 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 | 464 | for (tracked_insts_list.viewAllowEmpty().items(.@"0"), 0..) |*tracked_inst, tracked_inst_unwrapped_index| { |
| 464 | 465 | const file_index = tracked_inst.file; |
| 465 | 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 | 531 | if (old_decl.name == .empty) continue; |
| 531 | 532 | const name_ip = try zcu.intern_pool.getOrPutString( |
| 532 | 533 | zcu.gpa, |
| 534 | io, | |
| 533 | 535 | pt.tid, |
| 534 | 536 | old_zir.nullTerminatedString(old_decl.name), |
| 535 | 537 | .no_embedded_nulls, |
| ... | ... | @@ -545,6 +547,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 545 | 547 | if (new_decl.name == .empty) continue; |
| 546 | 548 | const name_ip = try zcu.intern_pool.getOrPutString( |
| 547 | 549 | zcu.gpa, |
| 550 | io, | |
| 548 | 551 | pt.tid, |
| 549 | 552 | new_zir.nullTerminatedString(new_decl.name), |
| 550 | 553 | .no_embedded_nulls, |
| ... | ... | @@ -575,7 +578,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 575 | 578 | } |
| 576 | 579 | } |
| 577 | 580 | |
| 578 | try ip.rehashTrackedInsts(gpa, pt.tid); | |
| 581 | try ip.rehashTrackedInsts(gpa, io, pt.tid); | |
| 579 | 582 | |
| 580 | 583 | for (updated_files.keys(), updated_files.values()) |file_index, updated_file| { |
| 581 | 584 | const file = updated_file.file; |
| ... | ... | @@ -700,7 +703,9 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized |
| 700 | 703 | fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.CompileError!bool { |
| 701 | 704 | const zcu = pt.zcu; |
| 702 | 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; | |
| 704 | 709 | |
| 705 | 710 | const unit: AnalUnit = .wrap(.{ .memoized_state = stage }); |
| 706 | 711 | |
| ... | ... | @@ -716,7 +721,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) |
| 716 | 721 | const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index)); |
| 717 | 722 | const std_namespace = std_type.getNamespaceIndex(zcu); |
| 718 | 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 | 725 | const builtin_nav = zcu.namespacePtr(std_namespace).pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse |
| 721 | 726 | @panic("lib/std.zig is corrupt and missing 'builtin'"); |
| 722 | 727 | try pt.ensureNavValUpToDate(builtin_nav); |
| ... | ... | @@ -857,8 +862,10 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 857 | 862 | /// to `transitive_failed_analysis` if necessary. |
| 858 | 863 | fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void { |
| 859 | 864 | const zcu = pt.zcu; |
| 860 | const gpa = zcu.gpa; | |
| 861 | 865 | const ip = &zcu.intern_pool; |
| 866 | const comp = zcu.comp; | |
| 867 | const gpa = comp.gpa; | |
| 868 | const io = comp.io; | |
| 862 | 869 | |
| 863 | 870 | const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id }); |
| 864 | 871 | const comptime_unit = ip.getComptimeUnit(cu_id); |
| ... | ... | @@ -909,7 +916,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 909 | 916 | .r = .{ .simple = .comptime_keyword }, |
| 910 | 917 | } }, |
| 911 | 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 | 920 | Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip), |
| 914 | 921 | }, .no_embedded_nulls), |
| 915 | 922 | }; |
| ... | ... | @@ -1087,8 +1094,10 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 1087 | 1094 | |
| 1088 | 1095 | fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { val_changed: bool } { |
| 1089 | 1096 | const zcu = pt.zcu; |
| 1090 | const gpa = zcu.gpa; | |
| 1091 | 1097 | const ip = &zcu.intern_pool; |
| 1098 | const comp = zcu.comp; | |
| 1099 | const gpa = comp.gpa; | |
| 1100 | const io = comp.io; | |
| 1092 | 1101 | |
| 1093 | 1102 | const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id }); |
| 1094 | 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 | 1262 | break :val .fromInterned(try pt.getExtern(.{ |
| 1254 | 1263 | .name = old_nav.name, |
| 1255 | 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 | 1266 | .is_threadlocal = zir_decl.is_threadlocal, |
| 1258 | 1267 | .linkage = .strong, |
| 1259 | 1268 | .visibility = .default, |
| ... | ... | @@ -1310,7 +1319,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1310 | 1319 | } |
| 1311 | 1320 | } |
| 1312 | 1321 | |
| 1313 | ip.resolveNavValue(nav_id, .{ | |
| 1322 | ip.resolveNavValue(io, nav_id, .{ | |
| 1314 | 1323 | .val = nav_val.toIntern(), |
| 1315 | 1324 | .is_const = is_const, |
| 1316 | 1325 | .alignment = modifiers.alignment, |
| ... | ... | @@ -1327,7 +1336,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1327 | 1336 | if (zir_decl.linkage == .@"export") { |
| 1328 | 1337 | const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) }); |
| 1329 | 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 | 1340 | try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id); |
| 1332 | 1341 | } |
| 1333 | 1342 | |
| ... | ... | @@ -1472,7 +1481,9 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc |
| 1472 | 1481 | |
| 1473 | 1482 | fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { type_changed: bool } { |
| 1474 | 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 | 1487 | const ip = &zcu.intern_pool; |
| 1477 | 1488 | |
| 1478 | 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 | 1590 | |
| 1580 | 1591 | if (!changed) return .{ .type_changed = false }; |
| 1581 | 1592 | |
| 1582 | ip.resolveNavType(nav_id, .{ | |
| 1593 | ip.resolveNavType(io, nav_id, .{ | |
| 1583 | 1594 | .type = resolved_ty.toIntern(), |
| 1584 | 1595 | .is_const = is_const, |
| 1585 | 1596 | .alignment = modifiers.alignment, |
| ... | ... | @@ -1775,6 +1786,7 @@ fn createFileRootStruct( |
| 1775 | 1786 | ) Allocator.Error!InternPool.Index { |
| 1776 | 1787 | const zcu = pt.zcu; |
| 1777 | 1788 | const gpa = zcu.gpa; |
| 1789 | const io = zcu.comp.io; | |
| 1778 | 1790 | const ip = &zcu.intern_pool; |
| 1779 | 1791 | const file = zcu.fileByIndex(file_index); |
| 1780 | 1792 | const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; |
| ... | ... | @@ -1797,11 +1809,11 @@ fn createFileRootStruct( |
| 1797 | 1809 | const decls = file.zir.?.bodySlice(extra_index, decls_len); |
| 1798 | 1810 | extra_index += decls_len; |
| 1799 | 1811 | |
| 1800 | const tracked_inst = try ip.trackZir(gpa, pt.tid, .{ | |
| 1812 | const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{ | |
| 1801 | 1813 | .file = file_index, |
| 1802 | 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 | 1817 | .layout = .auto, |
| 1806 | 1818 | .fields_len = fields_len, |
| 1807 | 1819 | .known_non_opv = small.known_non_opv, |
| ... | ... | @@ -1916,7 +1928,9 @@ pub fn discoverImport( |
| 1916 | 1928 | }, |
| 1917 | 1929 | } { |
| 1918 | 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; | |
| 1920 | 1934 | |
| 1921 | 1935 | if (!mem.endsWith(u8, import_string, ".zig") and !mem.endsWith(u8, import_string, ".zon")) { |
| 1922 | 1936 | return .module; |
| ... | ... | @@ -1926,8 +1940,8 @@ pub fn discoverImport( |
| 1926 | 1940 | errdefer new_path.deinit(gpa); |
| 1927 | 1941 | |
| 1928 | 1942 | // We're about to do a GOP on `import_table`, so we need the mutex. |
| 1929 | zcu.comp.mutex.lock(); | |
| 1930 | defer zcu.comp.mutex.unlock(); | |
| 1943 | comp.mutex.lockUncancelable(io); | |
| 1944 | defer comp.mutex.unlock(io); | |
| 1931 | 1945 | |
| 1932 | 1946 | const gop = try zcu.import_table.getOrPutAdapted(gpa, new_path, Zcu.ImportTableAdapter{ .zcu = zcu }); |
| 1933 | 1947 | errdefer _ = zcu.import_table.pop(); |
| ... | ... | @@ -1942,7 +1956,7 @@ pub fn discoverImport( |
| 1942 | 1956 | const new_file = try gpa.create(Zcu.File); |
| 1943 | 1957 | errdefer gpa.destroy(new_file); |
| 1944 | 1958 | |
| 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 | 1960 | .bin_digest = new_path.digest(), |
| 1947 | 1961 | .file = new_file, |
| 1948 | 1962 | .root_type = .none, |
| ... | ... | @@ -2027,7 +2041,9 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{ |
| 2027 | 2041 | IllegalZigImport, |
| 2028 | 2042 | }!void { |
| 2029 | 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; | |
| 2031 | 2047 | |
| 2032 | 2048 | // We'll initially add [mod, undefined] pairs, and when we reach the pair while |
| 2033 | 2049 | // iterating, rewrite the undefined value. |
| ... | ... | @@ -2085,7 +2101,7 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{ |
| 2085 | 2101 | const new_file = try gpa.create(Zcu.File); |
| 2086 | 2102 | errdefer gpa.destroy(new_file); |
| 2087 | 2103 | |
| 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 | 2105 | .bin_digest = path.digest(), |
| 2090 | 2106 | .file = new_file, |
| 2091 | 2107 | .root_type = .none, |
| ... | ... | @@ -2291,7 +2307,8 @@ pub fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { |
| 2291 | 2307 | pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!void { |
| 2292 | 2308 | const zcu = pt.zcu; |
| 2293 | 2309 | const comp = zcu.comp; |
| 2294 | const gpa = zcu.gpa; | |
| 2310 | const gpa = comp.gpa; | |
| 2311 | const io = comp.io; | |
| 2295 | 2312 | |
| 2296 | 2313 | const gop = try zcu.builtin_modules.getOrPut(gpa, opts.hash()); |
| 2297 | 2314 | 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 | 2347 | .zoir_invalidated = false, |
| 2331 | 2348 | }; |
| 2332 | 2349 | |
| 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 | 2351 | .bin_digest = path.digest(), |
| 2335 | 2352 | .file = file, |
| 2336 | 2353 | .root_type = .none, |
| ... | ... | @@ -2469,7 +2486,7 @@ fn updateEmbedFileInner( |
| 2469 | 2486 | |
| 2470 | 2487 | // The loaded bytes of the file, including a sentinel 0 byte. |
| 2471 | 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 | 2490 | const old_len = string_bytes.mutate.len; |
| 2474 | 2491 | errdefer string_bytes.shrinkRetainingCapacity(old_len); |
| 2475 | 2492 | const bytes = (try string_bytes.addManyAsSlice(size_plus_one))[0]; |
| ... | ... | @@ -2480,7 +2497,7 @@ fn updateEmbedFileInner( |
| 2480 | 2497 | error.EndOfStream => return error.UnexpectedEof, |
| 2481 | 2498 | }; |
| 2482 | 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 | 2502 | if (ip_str_out) |p| p.* = ip_str; |
| 2486 | 2503 | |
| ... | ... | @@ -2516,7 +2533,8 @@ fn newEmbedFile( |
| 2516 | 2533 | ) !*Zcu.EmbedFile { |
| 2517 | 2534 | const zcu = pt.zcu; |
| 2518 | 2535 | const comp = zcu.comp; |
| 2519 | const gpa = zcu.gpa; | |
| 2536 | const io = comp.io; | |
| 2537 | const gpa = comp.gpa; | |
| 2520 | 2538 | const ip = &zcu.intern_pool; |
| 2521 | 2539 | |
| 2522 | 2540 | const new_file = try gpa.create(Zcu.EmbedFile); |
| ... | ... | @@ -2549,8 +2567,8 @@ fn newEmbedFile( |
| 2549 | 2567 | const path_str = try path.toAbsolute(comp.dirs, gpa); |
| 2550 | 2568 | defer gpa.free(path_str); |
| 2551 | 2569 | |
| 2552 | whole.cache_manifest_mutex.lock(); | |
| 2553 | defer whole.cache_manifest_mutex.unlock(); | |
| 2570 | try whole.cache_manifest_mutex.lock(io); | |
| 2571 | defer whole.cache_manifest_mutex.unlock(io); | |
| 2554 | 2572 | |
| 2555 | 2573 | man.addFilePostContents(path_str, contents, new_file.stat) catch |err| switch (err) { |
| 2556 | 2574 | error.Unexpected => unreachable, |
| ... | ... | @@ -2647,13 +2665,15 @@ const ScanDeclIter = struct { |
| 2647 | 2665 | |
| 2648 | 2666 | fn avoidNameConflict(iter: *ScanDeclIter, comptime fmt: []const u8, args: anytype) !InternPool.NullTerminatedString { |
| 2649 | 2667 | const pt = iter.pt; |
| 2650 | const gpa = pt.zcu.gpa; | |
| 2651 | 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 | 2673 | var gop = try iter.seen_decls.getOrPut(gpa, name); |
| 2654 | 2674 | var next_suffix: u32 = 0; |
| 2655 | 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 | 2677 | gop = try iter.seen_decls.getOrPut(gpa, name); |
| 2658 | 2678 | next_suffix += 1; |
| 2659 | 2679 | } |
| ... | ... | @@ -2669,7 +2689,8 @@ const ScanDeclIter = struct { |
| 2669 | 2689 | const comp = zcu.comp; |
| 2670 | 2690 | const namespace_index = iter.namespace_index; |
| 2671 | 2691 | const namespace = zcu.namespacePtr(namespace_index); |
| 2672 | const gpa = zcu.gpa; | |
| 2692 | const gpa = comp.gpa; | |
| 2693 | const io = comp.io; | |
| 2673 | 2694 | const file = namespace.fileScope(zcu); |
| 2674 | 2695 | const zir = file.zir.?; |
| 2675 | 2696 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -2697,6 +2718,7 @@ const ScanDeclIter = struct { |
| 2697 | 2718 | if (iter.pass != .named) return; |
| 2698 | 2719 | const name = try ip.getOrPutString( |
| 2699 | 2720 | gpa, |
| 2721 | io, | |
| 2700 | 2722 | pt.tid, |
| 2701 | 2723 | zir.nullTerminatedString(decl.name), |
| 2702 | 2724 | .no_embedded_nulls, |
| ... | ... | @@ -2706,7 +2728,7 @@ const ScanDeclIter = struct { |
| 2706 | 2728 | }, |
| 2707 | 2729 | }; |
| 2708 | 2730 | |
| 2709 | const tracked_inst = try ip.trackZir(gpa, pt.tid, .{ | |
| 2731 | const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{ | |
| 2710 | 2732 | .file = namespace.file_scope, |
| 2711 | 2733 | .inst = decl_inst, |
| 2712 | 2734 | }); |
| ... | ... | @@ -2718,7 +2740,7 @@ const ScanDeclIter = struct { |
| 2718 | 2740 | const cu = if (existing_unit) |eu| |
| 2719 | 2741 | eu.unwrap().@"comptime" |
| 2720 | 2742 | else |
| 2721 | try ip.createComptimeUnit(gpa, pt.tid, tracked_inst, namespace_index); | |
| 2743 | try ip.createComptimeUnit(gpa, io, pt.tid, tracked_inst, namespace_index); | |
| 2722 | 2744 | |
| 2723 | 2745 | const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); |
| 2724 | 2746 | |
| ... | ... | @@ -2737,9 +2759,9 @@ const ScanDeclIter = struct { |
| 2737 | 2759 | }, |
| 2738 | 2760 | else => unit: { |
| 2739 | 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 | 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 | 2765 | if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); |
| 2744 | 2766 | break :nav nav; |
| 2745 | 2767 | }; |
| ... | ... | @@ -2798,7 +2820,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2798 | 2820 | defer tracy.end(); |
| 2799 | 2821 | |
| 2800 | 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 | 2826 | const ip = &zcu.intern_pool; |
| 2803 | 2827 | |
| 2804 | 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 | 2834 | try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); |
| 2811 | 2835 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); |
| 2812 | 2836 | |
| 2813 | func.setAnalyzed(ip); | |
| 2837 | func.setAnalyzed(ip, io); | |
| 2814 | 2838 | if (func.analysisUnordered(ip).inferred_error_set) { |
| 2815 | func.setResolvedErrorSet(ip, .none); | |
| 2839 | func.setResolvedErrorSet(ip, io, .none); | |
| 2816 | 2840 | } |
| 2817 | 2841 | |
| 2818 | 2842 | if (zcu.comp.time_report) |*tr| { |
| ... | ... | @@ -2872,7 +2896,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2872 | 2896 | } |
| 2873 | 2897 | |
| 2874 | 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); | |
| 2876 | 2900 | |
| 2877 | 2901 | // First few indexes of extra are reserved and set at the end. |
| 2878 | 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 | 2995 | }); |
| 2972 | 2996 | } |
| 2973 | 2997 | |
| 2974 | func.setBranchHint(ip, sema.branch_hint orelse .none); | |
| 2998 | func.setBranchHint(ip, io, sema.branch_hint orelse .none); | |
| 2975 | 2999 | |
| 2976 | 3000 | if (zcu.comp.config.any_error_tracing and func.analysisUnordered(ip).has_error_trace and fn_ty_info.cc != .auto) { |
| 2977 | 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 | 3029 | else => |e| return e, |
| 3006 | 3030 | }; |
| 3007 | 3031 | assert(ies.resolved != .none); |
| 3008 | func.setResolvedErrorSet(ip, ies.resolved); | |
| 3032 | func.setResolvedErrorSet(ip, io, ies.resolved); | |
| 3009 | 3033 | } |
| 3010 | 3034 | |
| 3011 | 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 | 3060 | } |
| 3037 | 3061 | |
| 3038 | 3062 | pub 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 | } |
| 3041 | 3066 | |
| 3042 | 3067 | pub fn destroyNamespace(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) void { |
| ... | ... | @@ -3047,11 +3072,15 @@ pub fn getErrorValue( |
| 3047 | 3072 | pt: Zcu.PerThread, |
| 3048 | 3073 | name: InternPool.NullTerminatedString, |
| 3049 | 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 | } |
| 3052 | 3078 | |
| 3053 | 3079 | pub 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 | } |
| 3056 | 3085 | |
| 3057 | 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 | 3107 | return; |
| 3079 | 3108 | } |
| 3080 | 3109 | |
| 3081 | pt.zcu.comp.mutex.lock(); | |
| 3082 | defer pt.zcu.comp.mutex.unlock(); | |
| 3110 | const comp = pt.zcu.comp; | |
| 3111 | const io = comp.io; | |
| 3112 | comp.mutex.lockUncancelable(io); | |
| 3113 | defer comp.mutex.unlock(io); | |
| 3083 | 3114 | if (pt.zcu.failed_files.fetchSwapRemove(file_index)) |kv| { |
| 3084 | 3115 | assert(maybe_has_error); // the runtime safety case above |
| 3085 | 3116 | if (kv.value) |msg| pt.zcu.gpa.free(msg); // delete previous error message |
| ... | ... | @@ -3266,7 +3297,9 @@ fn processExportsInner( |
| 3266 | 3297 | |
| 3267 | 3298 | pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void { |
| 3268 | 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 | 3303 | const ip = &zcu.intern_pool; |
| 3271 | 3304 | |
| 3272 | 3305 | // 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 | 3317 | const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?; |
| 3285 | 3318 | // We know that the namespace has a `test_functions`... |
| 3286 | 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 | 3321 | Zcu.Namespace.NameAdapter{ .zcu = zcu }, |
| 3289 | 3322 | ).?; |
| 3290 | 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 | 3425 | } }), |
| 3393 | 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 | 3430 | // The linker thread is not running, so we actually need to dispatch this task directly. |
| 3398 | 3431 | @import("../link.zig").linkTestFunctionsNav(pt, nav_index); |
| ... | ... | @@ -3407,7 +3440,9 @@ pub fn reportRetryableFileError( |
| 3407 | 3440 | args: anytype, |
| 3408 | 3441 | ) error{OutOfMemory}!void { |
| 3409 | 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; | |
| 3411 | 3446 | |
| 3412 | 3447 | const file = zcu.fileByIndex(file_index); |
| 3413 | 3448 | |
| ... | ... | @@ -3417,8 +3452,8 @@ pub fn reportRetryableFileError( |
| 3417 | 3452 | errdefer gpa.free(msg); |
| 3418 | 3453 | |
| 3419 | 3454 | const old_msg: ?[]u8 = old_msg: { |
| 3420 | zcu.comp.mutex.lock(); | |
| 3421 | defer zcu.comp.mutex.unlock(); | |
| 3455 | comp.mutex.lockUncancelable(io); | |
| 3456 | defer comp.mutex.unlock(io); | |
| 3422 | 3457 | |
| 3423 | 3458 | const gop = try zcu.failed_files.getOrPut(gpa, file_index); |
| 3424 | 3459 | const old: ?[]u8 = if (gop.found_existing) old: { |
| ... | ... | @@ -3433,12 +3468,8 @@ pub fn reportRetryableFileError( |
| 3433 | 3468 | |
| 3434 | 3469 | /// Shortcut for calling `intern_pool.get`. |
| 3435 | 3470 | pub 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); | |
| 3437 | } | |
| 3438 | ||
| 3439 | /// Shortcut for calling `intern_pool.getUnion`. | |
| 3440 | pub 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); | |
| 3471 | const comp = pt.zcu.comp; | |
| 3472 | return pt.zcu.intern_pool.get(comp.gpa, comp.io, pt.tid, key); | |
| 3442 | 3473 | } |
| 3443 | 3474 | |
| 3444 | 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 | 3477 | /// this because it requires potentially pushing to the job queue. |
| 3447 | 3478 | pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!Value { |
| 3448 | 3479 | const ip = &pt.zcu.intern_pool; |
| 3480 | const comp = pt.zcu.comp; | |
| 3481 | const gpa = comp.gpa; | |
| 3482 | const io = comp.io; | |
| 3449 | 3483 | switch (ip.indexToKey(val.toIntern())) { |
| 3450 | 3484 | .@"extern" => |e| { |
| 3451 | 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 | 3502 | }, |
| 3469 | 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 | } |
| 3473 | 3507 | |
| 3474 | 3508 | pub 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 | 3600 | } |
| 3567 | 3601 | |
| 3568 | 3602 | pub 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 | } |
| 3571 | 3606 | |
| 3572 | 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 | 3619 | |
| 3585 | 3620 | pub fn singleErrorSetType(pt: Zcu.PerThread, name: InternPool.NullTerminatedString) Allocator.Error!Type { |
| 3586 | 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 | } |
| 3589 | 3625 | |
| 3590 | 3626 | /// Sorts `names` in place. |
| ... | ... | @@ -3598,7 +3634,8 @@ pub fn errorSetFromUnsortedNames( |
| 3598 | 3634 | {}, |
| 3599 | 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 | 3639 | return Type.fromInterned(new_ty); |
| 3603 | 3640 | } |
| 3604 | 3641 | |
| ... | ... | @@ -3709,9 +3746,17 @@ pub fn intValue_i64(pt: Zcu.PerThread, ty: Type, x: i64) Allocator.Error!Value { |
| 3709 | 3746 | } })); |
| 3710 | 3747 | } |
| 3711 | 3748 | |
| 3749 | /// Shortcut for calling `intern_pool.getUnion`. | |
| 3750 | /// TODO: remove either this or `unionValue`. | |
| 3751 | pub 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`. | |
| 3712 | 3757 | pub fn unionValue(pt: Zcu.PerThread, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value { |
| 3713 | const zcu = pt.zcu; | |
| 3714 | return Value.fromInterned(try zcu.intern_pool.getUnion(zcu.gpa, pt.tid, .{ | |
| 3758 | const comp = pt.zcu.comp; | |
| 3759 | return Value.fromInterned(try pt.zcu.intern_pool.getUnion(comp.gpa, comp.io, pt.tid, .{ | |
| 3715 | 3760 | .ty = union_ty.toIntern(), |
| 3716 | 3761 | .tag = tag.toIntern(), |
| 3717 | 3762 | .val = val.toIntern(), |
| ... | ... | @@ -3771,12 +3816,12 @@ pub fn nullValue(pt: Zcu.PerThread, opt_ty: Type) Allocator.Error!Value { |
| 3771 | 3816 | /// `ty` is an integer or a vector of integers. |
| 3772 | 3817 | pub fn overflowArithmeticTupleType(pt: Zcu.PerThread, ty: Type) !Type { |
| 3773 | 3818 | const zcu = pt.zcu; |
| 3774 | const ip = &zcu.intern_pool; | |
| 3819 | const comp = zcu.comp; | |
| 3775 | 3820 | const ov_ty: Type = if (ty.zigTypeTag(zcu) == .vector) try pt.vectorType(.{ |
| 3776 | 3821 | .len = ty.vectorLen(zcu), |
| 3777 | 3822 | .child = .u1_type, |
| 3778 | 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 | 3825 | .types = &.{ ty.toIntern(), ov_ty.toIntern() }, |
| 3781 | 3826 | .values = &.{ .none, .none }, |
| 3782 | 3827 | }); |
| ... | ... | @@ -3872,12 +3917,14 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err |
| 3872 | 3917 | /// If necessary, the new `Nav` is queued for codegen. |
| 3873 | 3918 | /// `key.owner_nav` is ignored and may be `undefined`. |
| 3874 | 3919 | pub 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 | 3923 | if (result.new_nav.unwrap()) |nav| { |
| 3877 | 3924 | // This job depends on any resolve_type_fully jobs queued up before it. |
| 3878 | pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 3879 | try pt.zcu.comp.queueJob(.{ .link_nav = nav }); | |
| 3880 | if (pt.zcu.comp.debugIncremental()) try pt.zcu.incremental_debug_state.newNav(pt.zcu, nav); | |
| 3925 | comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 3926 | try comp.queueJob(.{ .link_nav = nav }); | |
| 3927 | if (comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); | |
| 3881 | 3928 | } |
| 3882 | 3929 | return result.index; |
| 3883 | 3930 | } |
| ... | ... | @@ -3966,7 +4013,9 @@ fn recreateStructType( |
| 3966 | 4013 | key: InternPool.Key.NamespaceType.Declared, |
| 3967 | 4014 | ) Allocator.Error!InternPool.Index { |
| 3968 | 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 | 4019 | const ip = &zcu.intern_pool; |
| 3971 | 4020 | |
| 3972 | 4021 | const inst_info = key.zir_index.resolveFull(ip).?; |
| ... | ... | @@ -3995,7 +4044,7 @@ fn recreateStructType( |
| 3995 | 4044 | |
| 3996 | 4045 | const struct_obj = ip.loadStructType(old_ty); |
| 3997 | 4046 | |
| 3998 | const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{ | |
| 4047 | const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ | |
| 3999 | 4048 | .layout = small.layout, |
| 4000 | 4049 | .fields_len = fields_len, |
| 4001 | 4050 | .known_non_opv = small.known_non_opv, |
| ... | ... | @@ -4042,7 +4091,9 @@ fn recreateUnionType( |
| 4042 | 4091 | key: InternPool.Key.NamespaceType.Declared, |
| 4043 | 4092 | ) Allocator.Error!InternPool.Index { |
| 4044 | 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 | 4097 | const ip = &zcu.intern_pool; |
| 4047 | 4098 | |
| 4048 | 4099 | const inst_info = key.zir_index.resolveFull(ip).?; |
| ... | ... | @@ -4075,7 +4126,7 @@ fn recreateUnionType( |
| 4075 | 4126 | |
| 4076 | 4127 | const namespace_index = union_obj.namespace; |
| 4077 | 4128 | |
| 4078 | const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{ | |
| 4129 | const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ | |
| 4079 | 4130 | .flags = .{ |
| 4080 | 4131 | .layout = small.layout, |
| 4081 | 4132 | .status = .none, |
| ... | ... | @@ -4133,7 +4184,9 @@ fn recreateEnumType( |
| 4133 | 4184 | key: InternPool.Key.NamespaceType.Declared, |
| 4134 | 4185 | ) (Allocator.Error || Io.Cancelable)!InternPool.Index { |
| 4135 | 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 | 4190 | const ip = &zcu.intern_pool; |
| 4138 | 4191 | |
| 4139 | 4192 | const inst_info = key.zir_index.resolveFull(ip).?; |
| ... | ... | @@ -4197,7 +4250,7 @@ fn recreateEnumType( |
| 4197 | 4250 | |
| 4198 | 4251 | const namespace_index = enum_obj.namespace; |
| 4199 | 4252 | |
| 4200 | const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{ | |
| 4253 | const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ | |
| 4201 | 4254 | .has_values = any_values, |
| 4202 | 4255 | .tag_mode = if (small.nonexhaustive) |
| 4203 | 4256 | .nonexhaustive |
| ... | ... | @@ -4404,7 +4457,7 @@ pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPo |
| 4404 | 4457 | |
| 4405 | 4458 | pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dependee) Allocator.Error!void { |
| 4406 | 4459 | const zcu = pt.zcu; |
| 4407 | const gpa = zcu.gpa; | |
| 4460 | const gpa = zcu.comp.gpa; | |
| 4408 | 4461 | try zcu.intern_pool.addDependency(gpa, unit, dependee); |
| 4409 | 4462 | if (zcu.comp.debugIncremental()) { |
| 4410 | 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 | 4465 | } |
| 4413 | 4466 | } |
| 4414 | 4467 | |
| 4415 | /// Performs code generation, which comes after `Sema` but before `link` in the pipeline. | |
| 4416 | /// This part of the pipeline is self-contained/"pure", so can be run in parallel with most | |
| 4417 | /// other code. This function is currently run either on the main thread, or on a separate | |
| 4418 | /// codegen thread, depending on whether the backend supports `Zcu.Feature.separate_thread`. | |
| 4419 | pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air, out: *@import("../link.zig").ZcuTask.LinkFunc.SharedMir) void { | |
| 4468 | pub const RunCodegenError = Io.Cancelable || error{AlreadyReported}; | |
| 4469 | ||
| 4470 | /// Performs code generation, which comes after `Sema` but before `link` in the pipeline. This part | |
| 4471 | /// of the pipeline is self-contained and can usually be run concurrently with other components. | |
| 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. | |
| 4477 | pub fn runCodegen(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) RunCodegenError!codegen.AnyMir { | |
| 4420 | 4478 | const zcu = pt.zcu; |
| 4479 | const comp = zcu.comp; | |
| 4480 | const io = comp.io; | |
| 4421 | 4481 | |
| 4422 | 4482 | crash_report.CodegenFunc.start(zcu, func_index); |
| 4423 | 4483 | defer crash_report.CodegenFunc.stop(func_index); |
| 4424 | 4484 | |
| 4425 | var timer = zcu.comp.startTimer(); | |
| 4485 | var timer = comp.startTimer(); | |
| 4426 | 4486 | |
| 4427 | const success: bool = if (runCodegenInner(pt, func_index, air)) |mir| success: { | |
| 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 | }; | |
| 4487 | const codegen_result = runCodegenInner(pt, func_index, air); | |
| 4447 | 4488 | |
| 4448 | 4489 | if (timer.finish()) |ns_codegen| report_time: { |
| 4449 | 4490 | const ip = &zcu.intern_pool; |
| 4450 | 4491 | const nav = ip.indexToKey(func_index).func.owner_nav; |
| 4451 | 4492 | const zir_decl = ip.getNav(nav).srcInst(ip); |
| 4452 | zcu.comp.mutex.lock(); | |
| 4453 | defer zcu.comp.mutex.unlock(); | |
| 4493 | comp.mutex.lockUncancelable(io); | |
| 4494 | defer comp.mutex.unlock(io); | |
| 4454 | 4495 | const tr = &zcu.comp.time_report.?; |
| 4455 | 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 | 4498 | error.OutOfMemory => { |
| 4458 | zcu.comp.setAllocFailure(); | |
| 4499 | comp.setAllocFailure(); | |
| 4459 | 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 | 4504 | gop.value_ptr.* += ns_codegen; |
| 4464 | 4505 | } |
| 4465 | 4506 | |
| 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 | 4507 | if (zcu.pending_codegen_jobs.rmw(.Sub, 1, .monotonic) == 1) { |
| 4470 | 4508 | // Decremented to 0, so all done. |
| 4471 | 4509 | zcu.codegen_prog_node.end(); |
| 4472 | 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 | } |
| 4475 | 4531 | fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) error{ |
| 4476 | 4532 | OutOfMemory, |
| ... | ... | @@ -4527,7 +4583,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e |
| 4527 | 4583 | // "emit" step because LLVM does not support incremental linking. Our linker (LLD or self-hosted) |
| 4528 | 4584 | // will just see the ZCU object file which LLVM ultimately emits. |
| 4529 | 4585 | if (zcu.llvm_object) |llvm_object| { |
| 4530 | assert(pt.tid == .main); // LLVM has a lot of shared state | |
| 4586 | 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 | 4587 | try llvm_object.updateFunc(pt, func_index, air, &liveness); |
| 4532 | 4588 | return error.BackendDoesNotProduceMir; |
| 4533 | 4589 | } |
| ... | ... | @@ -4536,7 +4592,7 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e |
| 4536 | 4592 | |
| 4537 | 4593 | // Just like LLVM, the SPIR-V backend can't multi-threaded due to SPIR-V design limitations. |
| 4538 | 4594 | if (lf.cast(.spirv)) |spirv_file| { |
| 4539 | assert(pt.tid == .main); // SPIR-V has a lot of shared state | |
| 4595 | 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 | 4596 | spirv_file.updateFunc(pt, func_index, air, &liveness) catch |err| { |
| 4541 | 4597 | switch (err) { |
| 4542 | 4598 | error.OutOfMemory => comp.link_diags.setAllocFailure(), |
src/codegen/spirv/CodeGen.zig+9-6| ... | ... | @@ -2270,6 +2270,9 @@ fn buildWideMul( |
| 2270 | 2270 | ) !struct { Temporary, Temporary } { |
| 2271 | 2271 | const pt = cg.pt; |
| 2272 | 2272 | const zcu = cg.module.zcu; |
| 2273 | const comp = zcu.comp; | |
| 2274 | const gpa = comp.gpa; | |
| 2275 | const io = comp.io; | |
| 2273 | 2276 | const target = cg.module.zcu.getTarget(); |
| 2274 | 2277 | const ip = &zcu.intern_pool; |
| 2275 | 2278 | |
| ... | ... | @@ -2297,14 +2300,14 @@ fn buildWideMul( |
| 2297 | 2300 | }; |
| 2298 | 2301 | |
| 2299 | 2302 | for (0..ops) |i| { |
| 2300 | try cg.body.emit(cg.module.gpa, .OpIMul, .{ | |
| 2303 | try cg.body.emit(gpa, .OpIMul, .{ | |
| 2301 | 2304 | .id_result_type = arith_op_ty_id, |
| 2302 | 2305 | .id_result = value_results.at(i), |
| 2303 | 2306 | .operand_1 = lhs_op.at(i), |
| 2304 | 2307 | .operand_2 = rhs_op.at(i), |
| 2305 | 2308 | }); |
| 2306 | 2309 | |
| 2307 | try cg.body.emit(cg.module.gpa, .OpExtInst, .{ | |
| 2310 | try cg.body.emit(gpa, .OpExtInst, .{ | |
| 2308 | 2311 | .id_result_type = arith_op_ty_id, |
| 2309 | 2312 | .id_result = overflow_results.at(i), |
| 2310 | 2313 | .set = set, |
| ... | ... | @@ -2316,7 +2319,7 @@ fn buildWideMul( |
| 2316 | 2319 | .vulkan, .opengl => { |
| 2317 | 2320 | // Operations return a struct{T, T} |
| 2318 | 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 | 2323 | .types = &.{ arith_op_ty.toIntern(), arith_op_ty.toIntern() }, |
| 2321 | 2324 | .values = &.{ .none, .none }, |
| 2322 | 2325 | })); |
| ... | ... | @@ -2330,7 +2333,7 @@ fn buildWideMul( |
| 2330 | 2333 | for (0..ops) |i| { |
| 2331 | 2334 | const op_result = cg.module.allocId(); |
| 2332 | 2335 | |
| 2333 | try cg.body.emitRaw(cg.module.gpa, opcode, 4); | |
| 2336 | try cg.body.emitRaw(gpa, opcode, 4); | |
| 2334 | 2337 | cg.body.writeOperand(Id, op_result_ty_id); |
| 2335 | 2338 | cg.body.writeOperand(Id, op_result); |
| 2336 | 2339 | cg.body.writeOperand(Id, lhs_op.at(i)); |
| ... | ... | @@ -2340,14 +2343,14 @@ fn buildWideMul( |
| 2340 | 2343 | // Temporary to deal with the fact that these are structs eventually, |
| 2341 | 2344 | // but for now, take the struct apart and return two separate vectors. |
| 2342 | 2345 | |
| 2343 | try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{ | |
| 2346 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | |
| 2344 | 2347 | .id_result_type = arith_op_ty_id, |
| 2345 | 2348 | .id_result = value_results.at(i), |
| 2346 | 2349 | .composite = op_result, |
| 2347 | 2350 | .indexes = &.{0}, |
| 2348 | 2351 | }); |
| 2349 | 2352 | |
| 2350 | try cg.body.emit(cg.module.gpa, .OpCompositeExtract, .{ | |
| 2353 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | |
| 2351 | 2354 | .id_result_type = arith_op_ty_id, |
| 2352 | 2355 | .id_result = overflow_results.at(i), |
| 2353 | 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 | 180204 | fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180205 | 180205 | const pt = self.pt; |
| 180206 | 180206 | const zcu = pt.zcu; |
| 180207 | const io = zcu.comp.io; | |
| 180207 | 180208 | const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; |
| 180208 | 180209 | const extra = self.air.extraData(Air.Bin, pl_op.payload).data; |
| 180209 | 180210 | const ty = self.typeOfIndex(inst); |
| ... | ... | @@ -180477,7 +180478,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180477 | 180478 | for (mask_elems, 0..) |*elem, bit| elem.* = @intCast(bit / elem_bits); |
| 180478 | 180479 | const mask_mcv = try self.lowerValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 180479 | 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 | 180483 | const mask_mem: Memory = .{ |
| 180483 | 180484 | .base = .{ .reg = try self.copyToTmpRegister(.usize, mask_mcv.address()) }, |
| ... | ... | @@ -188476,6 +188477,7 @@ const Select = struct { |
| 188476 | 188477 | fn create(spec: TempSpec, s: *const Select) InnerError!struct { Temp, bool } { |
| 188477 | 188478 | const cg = s.cg; |
| 188478 | 188479 | const pt = cg.pt; |
| 188480 | const io = pt.zcu.comp.io; | |
| 188479 | 188481 | return switch (spec.kind) { |
| 188480 | 188482 | .unused => .{ undefined, false }, |
| 188481 | 188483 | .any => .{ try cg.tempAlloc(spec.type), true }, |
| ... | ... | @@ -188693,7 +188695,7 @@ const Select = struct { |
| 188693 | 188695 | }; |
| 188694 | 188696 | return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 188695 | 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 | 188699 | } }))), true }; |
| 188698 | 188700 | }, |
| 188699 | 188701 | .pshufb_trunc_mem => |trunc_spec| { |
| ... | ... | @@ -188720,7 +188722,7 @@ const Select = struct { |
| 188720 | 188722 | }; |
| 188721 | 188723 | return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 188722 | 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 | 188726 | } }))), true }; |
| 188725 | 188727 | }, |
| 188726 | 188728 | .pand_trunc_mem => |trunc_spec| { |
| ... | ... | @@ -188734,7 +188736,7 @@ const Select = struct { |
| 188734 | 188736 | while (index < elems.len) : (index += from_bytes) @memset(elems[index..][0..to_bytes], std.math.maxInt(u8)); |
| 188735 | 188737 | return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 188736 | 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 | 188740 | } }))), true }; |
| 188739 | 188741 | }, |
| 188740 | 188742 | .pand_mask_mem => |mask_spec| { |
| ... | ... | @@ -188753,7 +188755,7 @@ const Select = struct { |
| 188753 | 188755 | @memset(elems[mask_len..], invert_mask); |
| 188754 | 188756 | return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 188755 | 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 | 188759 | } }))), true }; |
| 188758 | 188760 | }, |
| 188759 | 188761 | .ptest_mask_mem => |mask_ref| { |
| ... | ... | @@ -188778,7 +188780,7 @@ const Select = struct { |
| 188778 | 188780 | } |
| 188779 | 188781 | return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 188780 | 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 | 188784 | } }))), true }; |
| 188783 | 188785 | }, |
| 188784 | 188786 | .pshufb_bswap_mem => |bswap_spec| { |
| ... | ... | @@ -188794,7 +188796,7 @@ const Select = struct { |
| 188794 | 188796 | }; |
| 188795 | 188797 | return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 188796 | 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 | 188800 | } }))), true }; |
| 188799 | 188801 | }, |
| 188800 | 188802 | .bits_mem => |direction| { |
| ... | ... | @@ -188808,7 +188810,7 @@ const Select = struct { |
| 188808 | 188810 | }; |
| 188809 | 188811 | return .{ try cg.tempMemFromValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 188810 | 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 | 188814 | } }))), true }; |
| 188813 | 188815 | }, |
| 188814 | 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 | 991 | }); |
| 992 | 992 | } |
| 993 | 993 | |
| 994 | fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { | |
| 994 | fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void { | |
| 995 | const io = comp.io; | |
| 995 | 996 | const target = comp.getTarget(); |
| 996 | 997 | const target_os_version = target.os.version_range.semver.min; |
| 997 | 998 | |
| ... | ... | @@ -1002,8 +1003,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { |
| 1002 | 1003 | var task_buffer_i: usize = 0; |
| 1003 | 1004 | |
| 1004 | 1005 | { |
| 1005 | comp.mutex.lock(); // protect comp.arena | |
| 1006 | defer comp.mutex.unlock(); | |
| 1006 | comp.mutex.lockUncancelable(io); // protect comp.arena | |
| 1007 | defer comp.mutex.unlock(io); | |
| 1007 | 1008 | |
| 1008 | 1009 | for (libs) |lib| { |
| 1009 | 1010 | if (lib.added_in) |add_in| { |
| ... | ... | @@ -1021,7 +1022,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { |
| 1021 | 1022 | } |
| 1022 | 1023 | } |
| 1023 | 1024 | |
| 1024 | comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); | |
| 1025 | try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); | |
| 1025 | 1026 | } |
| 1026 | 1027 | |
| 1027 | 1028 | fn buildSharedLib( |
| ... | ... | @@ -1094,8 +1095,8 @@ fn buildSharedLib( |
| 1094 | 1095 | |
| 1095 | 1096 | var sub_create_diag: Compilation.CreateDiagnostic = undefined; |
| 1096 | 1097 | const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ |
| 1098 | .thread_limit = comp.thread_limit, | |
| 1097 | 1099 | .dirs = comp.dirs.withoutLocalCache(), |
| 1098 | .thread_pool = comp.thread_pool, | |
| 1099 | 1100 | .self_exe_path = comp.self_exe_path, |
| 1100 | 1101 | // Because we manually cache the whole set of objects, we don't cache the individual objects |
| 1101 | 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 | 1135 | }); |
| 1136 | 1136 | } |
| 1137 | 1137 | |
| 1138 | fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { | |
| 1138 | fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void { | |
| 1139 | const io = comp.io; | |
| 1139 | 1140 | const target_version = comp.getTarget().os.versionRange().gnuLibCVersion().?; |
| 1140 | 1141 | |
| 1141 | 1142 | assert(comp.glibc_so_files == null); |
| ... | ... | @@ -1145,8 +1146,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { |
| 1145 | 1146 | var task_buffer_i: usize = 0; |
| 1146 | 1147 | |
| 1147 | 1148 | { |
| 1148 | comp.mutex.lock(); // protect comp.arena | |
| 1149 | defer comp.mutex.unlock(); | |
| 1149 | comp.mutex.lockUncancelable(io); // protect comp.arena | |
| 1150 | defer comp.mutex.unlock(io); | |
| 1150 | 1151 | |
| 1151 | 1152 | for (libs) |lib| { |
| 1152 | 1153 | if (lib.removed_in) |rem_in| { |
| ... | ... | @@ -1163,7 +1164,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { |
| 1163 | 1164 | } |
| 1164 | 1165 | } |
| 1165 | 1166 | |
| 1166 | comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); | |
| 1167 | try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); | |
| 1167 | 1168 | } |
| 1168 | 1169 | |
| 1169 | 1170 | fn buildSharedLib( |
| ... | ... | @@ -1233,8 +1234,8 @@ fn buildSharedLib( |
| 1233 | 1234 | |
| 1234 | 1235 | var sub_create_diag: Compilation.CreateDiagnostic = undefined; |
| 1235 | 1236 | const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ |
| 1237 | .thread_limit = comp.thread_limit, | |
| 1236 | 1238 | .dirs = comp.dirs.withoutLocalCache(), |
| 1237 | .thread_pool = comp.thread_pool, | |
| 1238 | 1239 | .self_exe_path = comp.self_exe_path, |
| 1239 | 1240 | // Because we manually cache the whole set of objects, we don't cache the individual objects |
| 1240 | 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 | 106 | OutOfMemory, |
| 107 | 107 | AlreadyReported, |
| 108 | 108 | ZigCompilerNotBuiltWithLLVMExtensions, |
| 109 | }; | |
| 109 | } || std.Io.Cancelable; | |
| 110 | 110 | |
| 111 | 111 | pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { |
| 112 | 112 | if (!build_options.have_llvm) { |
| ... | ... | @@ -256,13 +256,13 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! |
| 256 | 256 | |
| 257 | 257 | var sub_create_diag: Compilation.CreateDiagnostic = undefined; |
| 258 | 258 | const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ |
| 259 | .thread_limit = comp.thread_limit, | |
| 259 | 260 | .dirs = comp.dirs.withoutLocalCache(), |
| 260 | 261 | .self_exe_path = comp.self_exe_path, |
| 261 | 262 | .cache_mode = .whole, |
| 262 | 263 | .config = config, |
| 263 | 264 | .root_mod = root_mod, |
| 264 | 265 | .root_name = root_name, |
| 265 | .thread_pool = comp.thread_pool, | |
| 266 | 266 | .libc_installation = comp.libc_installation, |
| 267 | 267 | .emit_bin = .yes_cache, |
| 268 | 268 | .c_source_files = c_source_files.items, |
| ... | ... | @@ -295,7 +295,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError! |
| 295 | 295 | assert(comp.libcxx_static_lib == null); |
| 296 | 296 | const crt_file = try sub_compilation.toCrtFile(); |
| 297 | 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 | } |
| 300 | 300 | |
| 301 | 301 | pub 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 | 449 | |
| 450 | 450 | var sub_create_diag: Compilation.CreateDiagnostic = undefined; |
| 451 | 451 | const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ |
| 452 | .thread_limit = comp.thread_limit, | |
| 452 | 453 | .dirs = comp.dirs.withoutLocalCache(), |
| 453 | 454 | .self_exe_path = comp.self_exe_path, |
| 454 | 455 | .cache_mode = .whole, |
| 455 | 456 | .config = config, |
| 456 | 457 | .root_mod = root_mod, |
| 457 | 458 | .root_name = root_name, |
| 458 | .thread_pool = comp.thread_pool, | |
| 459 | 459 | .libc_installation = comp.libc_installation, |
| 460 | 460 | .emit_bin = .yes_cache, |
| 461 | 461 | .c_source_files = c_source_files.items, |
| ... | ... | @@ -492,7 +492,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 492 | 492 | assert(comp.libcxxabi_static_lib == null); |
| 493 | 493 | const crt_file = try sub_compilation.toCrtFile(); |
| 494 | 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 | } |
| 497 | 497 | |
| 498 | 498 | pub fn addCxxArgs( |
src/libs/libtsan.zig+3-3| ... | ... | @@ -11,7 +11,7 @@ pub const BuildError = error{ |
| 11 | 11 | AlreadyReported, |
| 12 | 12 | ZigCompilerNotBuiltWithLLVMExtensions, |
| 13 | 13 | TSANUnsupportedCPUArchitecture, |
| 14 | }; | |
| 14 | } || std.Io.Cancelable; | |
| 15 | 15 | |
| 16 | 16 | pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { |
| 17 | 17 | if (!build_options.have_llvm) { |
| ... | ... | @@ -279,8 +279,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo |
| 279 | 279 | |
| 280 | 280 | var sub_create_diag: Compilation.CreateDiagnostic = undefined; |
| 281 | 281 | const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ |
| 282 | .thread_limit = comp.thread_limit, | |
| 282 | 283 | .dirs = comp.dirs.withoutLocalCache(), |
| 283 | .thread_pool = comp.thread_pool, | |
| 284 | 284 | .self_exe_path = comp.self_exe_path, |
| 285 | 285 | .cache_mode = .whole, |
| 286 | 286 | .config = config, |
| ... | ... | @@ -319,7 +319,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo |
| 319 | 319 | }; |
| 320 | 320 | |
| 321 | 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 | 323 | assert(comp.tsan_lib == null); |
| 324 | 324 | comp.tsan_lib = crt_file; |
| 325 | 325 | } |
src/libs/libunwind.zig+3-3| ... | ... | @@ -12,7 +12,7 @@ pub const BuildError = error{ |
| 12 | 12 | OutOfMemory, |
| 13 | 13 | AlreadyReported, |
| 14 | 14 | ZigCompilerNotBuiltWithLLVMExtensions, |
| 15 | }; | |
| 15 | } || std.Io.Cancelable; | |
| 16 | 16 | |
| 17 | 17 | pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void { |
| 18 | 18 | if (!build_options.have_llvm) { |
| ... | ... | @@ -145,6 +145,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 145 | 145 | |
| 146 | 146 | var sub_create_diag: Compilation.CreateDiagnostic = undefined; |
| 147 | 147 | const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ |
| 148 | .thread_limit = comp.thread_limit, | |
| 148 | 149 | .dirs = comp.dirs.withoutLocalCache(), |
| 149 | 150 | .self_exe_path = comp.self_exe_path, |
| 150 | 151 | .config = config, |
| ... | ... | @@ -152,7 +153,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 152 | 153 | .cache_mode = .whole, |
| 153 | 154 | .root_name = root_name, |
| 154 | 155 | .main_mod = null, |
| 155 | .thread_pool = comp.thread_pool, | |
| 156 | 156 | .libc_installation = comp.libc_installation, |
| 157 | 157 | .emit_bin = .yes_cache, |
| 158 | 158 | .function_sections = comp.function_sections, |
| ... | ... | @@ -184,7 +184,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 184 | 184 | }; |
| 185 | 185 | |
| 186 | 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 | 188 | assert(comp.libunwind_static_lib == null); |
| 189 | 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 | 281 | const sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename }); |
| 282 | 282 | errdefer gpa.free(sub_path); |
| 283 | 283 | |
| 284 | comp.mutex.lock(); | |
| 285 | defer comp.mutex.unlock(); | |
| 284 | comp.mutex.lockUncancelable(io); | |
| 285 | defer comp.mutex.unlock(io); | |
| 286 | 286 | try comp.crt_files.ensureUnusedCapacity(gpa, 1); |
| 287 | 287 | comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{ |
| 288 | 288 | .full_object_path = .{ |
| ... | ... | @@ -388,8 +388,8 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 388 | 388 | log.warn("failed to write cache manifest for DLL import {s}.lib: {s}", .{ lib_name, @errorName(err) }); |
| 389 | 389 | }; |
| 390 | 390 | |
| 391 | comp.mutex.lock(); | |
| 392 | defer comp.mutex.unlock(); | |
| 391 | comp.mutex.lockUncancelable(io); | |
| 392 | defer comp.mutex.unlock(io); | |
| 393 | 393 | try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{ |
| 394 | 394 | .full_object_path = .{ |
| 395 | 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 | 248 | |
| 249 | 249 | var sub_create_diag: Compilation.CreateDiagnostic = undefined; |
| 250 | 250 | const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ |
| 251 | .thread_limit = comp.thread_limit, | |
| 251 | 252 | .dirs = comp.dirs.withoutLocalCache(), |
| 252 | 253 | .self_exe_path = comp.self_exe_path, |
| 253 | 254 | .cache_mode = .whole, |
| 254 | 255 | .config = config, |
| 255 | 256 | .root_mod = root_mod, |
| 256 | .thread_pool = comp.thread_pool, | |
| 257 | 257 | .root_name = "c", |
| 258 | 258 | .libc_installation = comp.libc_installation, |
| 259 | 259 | .emit_bin = .yes_cache, |
| ... | ... | @@ -287,10 +287,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro |
| 287 | 287 | errdefer comp.gpa.free(basename); |
| 288 | 288 | |
| 289 | 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(); | |
| 293 | defer comp.mutex.unlock(); | |
| 292 | comp.mutex.lockUncancelable(io); | |
| 293 | defer comp.mutex.unlock(io); | |
| 294 | 294 | try comp.crt_files.ensureUnusedCapacity(comp.gpa, 1); |
| 295 | 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 | 645 | }); |
| 646 | 646 | } |
| 647 | 647 | |
| 648 | fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { | |
| 648 | fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) std.Io.Cancelable!void { | |
| 649 | const io = comp.io; | |
| 649 | 650 | assert(comp.netbsd_so_files == null); |
| 650 | 651 | comp.netbsd_so_files = so_files; |
| 651 | 652 | |
| ... | ... | @@ -653,8 +654,8 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { |
| 653 | 654 | var task_buffer_i: usize = 0; |
| 654 | 655 | |
| 655 | 656 | { |
| 656 | comp.mutex.lock(); // protect comp.arena | |
| 657 | defer comp.mutex.unlock(); | |
| 657 | comp.mutex.lockUncancelable(io); // protect comp.arena | |
| 658 | defer comp.mutex.unlock(io); | |
| 658 | 659 | |
| 659 | 660 | for (libs) |lib| { |
| 660 | 661 | const so_path: Path = .{ |
| ... | ... | @@ -668,7 +669,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void { |
| 668 | 669 | } |
| 669 | 670 | } |
| 670 | 671 | |
| 671 | comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); | |
| 672 | try comp.queuePrelinkTasks(task_buffer[0..task_buffer_i]); | |
| 672 | 673 | } |
| 673 | 674 | |
| 674 | 675 | fn buildSharedLib( |
| ... | ... | @@ -737,8 +738,8 @@ fn buildSharedLib( |
| 737 | 738 | |
| 738 | 739 | var sub_create_diag: Compilation.CreateDiagnostic = undefined; |
| 739 | 740 | const sub_compilation = Compilation.create(comp.gpa, arena, io, &sub_create_diag, .{ |
| 741 | .thread_limit = comp.thread_limit, | |
| 740 | 742 | .dirs = comp.dirs.withoutLocalCache(), |
| 741 | .thread_pool = comp.thread_pool, | |
| 742 | 743 | .self_exe_path = comp.self_exe_path, |
| 743 | 744 | // Because we manually cache the whole set of objects, we don't cache the individual objects |
| 744 | 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 | 34 | /// Stored here so that function definitions can distinguish between |
| 35 | 35 | /// needing an allocator for things besides error reporting. |
| 36 | 36 | gpa: Allocator, |
| 37 | mutex: std.Thread.Mutex, | |
| 37 | io: Io, | |
| 38 | mutex: Io.Mutex, | |
| 38 | 39 | msgs: std.ArrayList(Msg), |
| 39 | 40 | flags: Flags, |
| 40 | 41 | lld: std.ArrayList(Lld), |
| ... | ... | @@ -126,10 +127,11 @@ pub const Diags = struct { |
| 126 | 127 | } |
| 127 | 128 | }; |
| 128 | 129 | |
| 129 | pub fn init(gpa: Allocator) Diags { | |
| 130 | pub fn init(gpa: Allocator, io: Io) Diags { | |
| 130 | 131 | return .{ |
| 131 | 132 | .gpa = gpa, |
| 132 | .mutex = .{}, | |
| 133 | .io = io, | |
| 134 | .mutex = .init, | |
| 133 | 135 | .msgs = .empty, |
| 134 | 136 | .flags = .{}, |
| 135 | 137 | .lld = .empty, |
| ... | ... | @@ -153,8 +155,10 @@ pub const Diags = struct { |
| 153 | 155 | } |
| 154 | 156 | |
| 155 | 157 | pub fn lockAndParseLldStderr(diags: *Diags, prefix: []const u8, stderr: []const u8) void { |
| 156 | diags.mutex.lock(); | |
| 157 | defer diags.mutex.unlock(); | |
| 158 | const io = diags.io; | |
| 159 | ||
| 160 | diags.mutex.lockUncancelable(io); | |
| 161 | defer diags.mutex.unlock(io); | |
| 158 | 162 | |
| 159 | 163 | diags.parseLldStderr(prefix, stderr) catch diags.setAllocFailure(); |
| 160 | 164 | } |
| ... | ... | @@ -226,9 +230,10 @@ pub const Diags = struct { |
| 226 | 230 | pub fn addErrorSourceLocation(diags: *Diags, sl: SourceLocation, comptime format: []const u8, args: anytype) void { |
| 227 | 231 | @branchHint(.cold); |
| 228 | 232 | const gpa = diags.gpa; |
| 233 | const io = diags.io; | |
| 229 | 234 | const eu_main_msg = std.fmt.allocPrint(gpa, format, args); |
| 230 | diags.mutex.lock(); | |
| 231 | defer diags.mutex.unlock(); | |
| 235 | diags.mutex.lockUncancelable(io); | |
| 236 | defer diags.mutex.unlock(io); | |
| 232 | 237 | addErrorLockedFallible(diags, sl, eu_main_msg) catch |err| switch (err) { |
| 233 | 238 | error.OutOfMemory => diags.setAllocFailureLocked(), |
| 234 | 239 | }; |
| ... | ... | @@ -247,8 +252,9 @@ pub const Diags = struct { |
| 247 | 252 | pub fn addErrorWithNotes(diags: *Diags, note_count: usize) error{OutOfMemory}!ErrorWithNotes { |
| 248 | 253 | @branchHint(.cold); |
| 249 | 254 | const gpa = diags.gpa; |
| 250 | diags.mutex.lock(); | |
| 251 | defer diags.mutex.unlock(); | |
| 255 | const io = diags.io; | |
| 256 | diags.mutex.lockUncancelable(io); | |
| 257 | defer diags.mutex.unlock(io); | |
| 252 | 258 | try diags.msgs.ensureUnusedCapacity(gpa, 1); |
| 253 | 259 | return addErrorWithNotesAssumeCapacity(diags, note_count); |
| 254 | 260 | } |
| ... | ... | @@ -276,9 +282,10 @@ pub const Diags = struct { |
| 276 | 282 | ) void { |
| 277 | 283 | @branchHint(.cold); |
| 278 | 284 | const gpa = diags.gpa; |
| 285 | const io = diags.io; | |
| 279 | 286 | const eu_main_msg = std.fmt.allocPrint(gpa, format, args); |
| 280 | diags.mutex.lock(); | |
| 281 | defer diags.mutex.unlock(); | |
| 287 | diags.mutex.lockUncancelable(io); | |
| 288 | defer diags.mutex.unlock(io); | |
| 282 | 289 | addMissingLibraryErrorLockedFallible(diags, checked_paths, eu_main_msg) catch |err| switch (err) { |
| 283 | 290 | error.OutOfMemory => diags.setAllocFailureLocked(), |
| 284 | 291 | }; |
| ... | ... | @@ -312,9 +319,10 @@ pub const Diags = struct { |
| 312 | 319 | ) void { |
| 313 | 320 | @branchHint(.cold); |
| 314 | 321 | const gpa = diags.gpa; |
| 322 | const io = diags.io; | |
| 315 | 323 | const eu_main_msg = std.fmt.allocPrint(gpa, format, args); |
| 316 | diags.mutex.lock(); | |
| 317 | defer diags.mutex.unlock(); | |
| 324 | diags.mutex.lockUncancelable(io); | |
| 325 | defer diags.mutex.unlock(io); | |
| 318 | 326 | addParseErrorLockedFallible(diags, path, eu_main_msg) catch |err| switch (err) { |
| 319 | 327 | error.OutOfMemory => diags.setAllocFailureLocked(), |
| 320 | 328 | }; |
| ... | ... | @@ -349,8 +357,9 @@ pub const Diags = struct { |
| 349 | 357 | |
| 350 | 358 | pub fn setAllocFailure(diags: *Diags) void { |
| 351 | 359 | @branchHint(.cold); |
| 352 | diags.mutex.lock(); | |
| 353 | defer diags.mutex.unlock(); | |
| 360 | const io = diags.io; | |
| 361 | diags.mutex.lockUncancelable(io); | |
| 362 | defer diags.mutex.unlock(io); | |
| 354 | 363 | setAllocFailureLocked(diags); |
| 355 | 364 | } |
| 356 | 365 | |
| ... | ... | @@ -1101,6 +1110,7 @@ pub const File = struct { |
| 1101 | 1110 | const comp = base.comp; |
| 1102 | 1111 | const diags = &comp.link_diags; |
| 1103 | 1112 | const gpa = comp.gpa; |
| 1113 | const io = comp.io; | |
| 1104 | 1114 | const stat = try file.stat(); |
| 1105 | 1115 | const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig; |
| 1106 | 1116 | const buf = try gpa.alloc(u8, size); |
| ... | ... | @@ -1123,8 +1133,8 @@ pub const File = struct { |
| 1123 | 1133 | } else { |
| 1124 | 1134 | if (fs.path.isAbsolute(arg.path)) { |
| 1125 | 1135 | const new_path = Path.initCwd(path: { |
| 1126 | comp.mutex.lock(); | |
| 1127 | defer comp.mutex.unlock(); | |
| 1136 | comp.mutex.lockUncancelable(io); | |
| 1137 | defer comp.mutex.unlock(io); | |
| 1128 | 1138 | break :path try comp.arena.dupe(u8, arg.path); |
| 1129 | 1139 | }); |
| 1130 | 1140 | switch (Compilation.classifyFileExt(arg.path)) { |
| ... | ... | @@ -1309,61 +1319,13 @@ pub const ZcuTask = union(enum) { |
| 1309 | 1319 | /// Write the constant value for a Decl to the output file. |
| 1310 | 1320 | link_nav: InternPool.Nav.Index, |
| 1311 | 1321 | /// Write the machine code for a function to the output file. |
| 1312 | link_func: LinkFunc, | |
| 1322 | link_func: Zcu.CodegenTaskPool.Index, | |
| 1313 | 1323 | link_type: InternPool.Index, |
| 1314 | 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 | }; |
| 1365 | 1326 | |
| 1366 | 1327 | pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1328 | const io = comp.io; | |
| 1367 | 1329 | const diags = &comp.link_diags; |
| 1368 | 1330 | const base = comp.bin_file orelse { |
| 1369 | 1331 | comp.link_prog_node.completeOne(); |
| ... | ... | @@ -1372,8 +1334,8 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1372 | 1334 | |
| 1373 | 1335 | var timer = comp.startTimer(); |
| 1374 | 1336 | defer if (timer.finish()) |ns| { |
| 1375 | comp.mutex.lock(); | |
| 1376 | defer comp.mutex.unlock(); | |
| 1337 | comp.mutex.lockUncancelable(io); | |
| 1338 | defer comp.mutex.unlock(io); | |
| 1377 | 1339 | comp.time_report.?.stats.cpu_ns_link += ns; |
| 1378 | 1340 | }; |
| 1379 | 1341 | |
| ... | ... | @@ -1484,6 +1446,7 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { |
| 1484 | 1446 | } |
| 1485 | 1447 | } |
| 1486 | 1448 | pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { |
| 1449 | const io = comp.io; | |
| 1487 | 1450 | const diags = &comp.link_diags; |
| 1488 | 1451 | const zcu = comp.zcu.?; |
| 1489 | 1452 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -1492,8 +1455,8 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { |
| 1492 | 1455 | |
| 1493 | 1456 | var timer = comp.startTimer(); |
| 1494 | 1457 | |
| 1495 | switch (task) { | |
| 1496 | .link_nav => |nav_index| { | |
| 1458 | const maybe_nav: ?InternPool.Nav.Index = switch (task) { | |
| 1459 | .link_nav => |nav_index| nav: { | |
| 1497 | 1460 | const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); |
| 1498 | 1461 | const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); |
| 1499 | 1462 | defer nav_prog_node.end(); |
| ... | ... | @@ -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| { | |
| 1519 | const nav = zcu.funcInfo(func.func).owner_nav; | |
| 1482 | .link_func => |codegen_task| 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 | 1491 | const fqn_slice = ip.getNav(nav).fqn.toSlice(ip); |
| 1492 | ||
| 1521 | 1493 | const nav_prog_node = comp.link_prog_node.start(fqn_slice, 0); |
| 1522 | 1494 | defer nav_prog_node.end(); |
| 1523 | switch (func.mir.status.load(.acquire)) { | |
| 1524 | .pending => unreachable, | |
| 1525 | .ready => {}, | |
| 1526 | .failed => return, | |
| 1527 | } | |
| 1495 | ||
| 1528 | 1496 | assert(zcu.llvm_object == null); // LLVM codegen doesn't produce MIR |
| 1529 | const mir = &func.mir.value; | |
| 1530 | 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 | 1499 | error.OutOfMemory => return diags.setAllocFailure(), |
| 1533 | 1500 | error.CodegenFail => return zcu.assertCodegenFailed(nav), |
| 1534 | 1501 | error.Overflow, error.RelocationNotByteAligned => { |
| ... | ... | @@ -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 | 1512 | const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip); |
| 1545 | 1513 | const nav_prog_node = comp.link_prog_node.start(name, 0); |
| 1546 | 1514 | defer nav_prog_node.end(); |
| ... | ... | @@ -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 | 1526 | const nav_prog_node = comp.link_prog_node.start("Update line number", 0); |
| 1558 | 1527 | defer nav_prog_node.end(); |
| 1559 | 1528 | if (pt.zcu.llvm_object == null) { |
| ... | ... | @@ -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 | }; | |
| 1569 | 1539 | |
| 1570 | 1540 | if (timer.finish()) |ns_link| report_time: { |
| 1571 | const zir_decl: ?InternPool.TrackedInst.Index = switch (task) { | |
| 1572 | .link_type, .update_line_number => null, | |
| 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(); | |
| 1541 | comp.mutex.lockUncancelable(io); | |
| 1542 | defer comp.mutex.unlock(io); | |
| 1578 | 1543 | const tr = &zcu.comp.time_report.?; |
| 1579 | 1544 | tr.stats.cpu_ns_link += ns_link; |
| 1580 | if (zir_decl) |inst| { | |
| 1581 | const gop = tr.decl_link_ns.getOrPut(zcu.gpa, inst) catch |err| switch (err) { | |
| 1545 | if (maybe_nav) |nav| { | |
| 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 | 1548 | error.OutOfMemory => { |
| 1583 | 1549 | zcu.comp.setAllocFailure(); |
| 1584 | 1550 | break :report_time; |
| ... | ... | @@ -2208,8 +2174,13 @@ fn resolvePathInputLib( |
| 2208 | 2174 | const n2 = file.preadAll(buf2, n) catch |err| |
| 2209 | 2175 | fatal("failed to read {f}: {s}", .{ test_path, @errorName(err) }); |
| 2210 | 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 | 2182 | defer diags.deinit(); |
| 2183 | ||
| 2213 | 2184 | const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items); |
| 2214 | 2185 | if (diags.hasErrors()) { |
| 2215 | 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 | 713 | pub fn loadInput(self: *Elf, input: link.Input) !void { |
| 714 | 714 | const comp = self.base.comp; |
| 715 | 715 | const gpa = comp.gpa; |
| 716 | const io = comp.io; | |
| 716 | 717 | const diags = &comp.link_diags; |
| 717 | 718 | const target = self.getTarget(); |
| 718 | 719 | const debug_fmt_strip = comp.config.debug_format == .strip; |
| ... | ... | @@ -720,8 +721,8 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { |
| 720 | 721 | const is_static_lib = self.base.isStaticLib(); |
| 721 | 722 | |
| 722 | 723 | if (comp.verbose_link) { |
| 723 | comp.mutex.lock(); // protect comp.arena | |
| 724 | defer comp.mutex.unlock(); | |
| 724 | comp.mutex.lockUncancelable(io); // protect comp.arena | |
| 725 | defer comp.mutex.unlock(io); | |
| 725 | 726 | |
| 726 | 727 | const argv = &self.dump_argv_list; |
| 727 | 728 | switch (input) { |
src/link/MachO.zig+2-2| ... | ... | @@ -29,9 +29,9 @@ resolver: SymbolResolver = .{}, |
| 29 | 29 | /// This table will be populated after `scanRelocs` has run. |
| 30 | 30 | /// Key is symbol index. |
| 31 | 31 | undefs: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, UndefRefs) = .empty, |
| 32 | undefs_mutex: std.Thread.Mutex = .{}, | |
| 32 | undefs_mutex: std.Io.Mutex = .init, | |
| 33 | 33 | dupes: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayList(File.Index)) = .empty, |
| 34 | dupes_mutex: std.Thread.Mutex = .{}, | |
| 34 | dupes_mutex: std.Io.Mutex = .init, | |
| 35 | 35 | |
| 36 | 36 | dyld_info_cmd: macho.dyld_info_command = .{}, |
| 37 | 37 | symtab_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 | 555 | const file = self.getFile(macho_file); |
| 556 | 556 | const ref = file.getSymbolRef(rel.target, macho_file); |
| 557 | 557 | if (ref.getFile(macho_file) == null) { |
| 558 | macho_file.undefs_mutex.lock(); | |
| 559 | defer macho_file.undefs_mutex.unlock(); | |
| 560 | 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 | 562 | const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]); |
| 562 | 563 | if (!gop.found_existing) { |
| 563 | 564 | gop.value_ptr.* = .{ .refs = .{} }; |
src/link/MachO/CodeSignature.zig+1-1| ... | ... | @@ -289,7 +289,7 @@ pub fn writeAdhocSignature( |
| 289 | 289 | self.code_directory.inner.nCodeSlots = total_pages; |
| 290 | 290 | |
| 291 | 291 | // 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 | 293 | try hasher.hash(opts.file, self.code_directory.code_slots.items, .{ |
| 294 | 294 | .chunk_size = self.page_size, |
| 295 | 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 | 512 | const addUndef = struct { |
| 513 | 513 | fn addUndef(mf: *MachO, index: MachO.SymbolResolver.Index, tag: anytype) !void { |
| 514 | 514 | const gpa = mf.base.comp.gpa; |
| 515 | mf.undefs_mutex.lock(); | |
| 516 | defer mf.undefs_mutex.unlock(); | |
| 515 | const io = mf.base.comp.io; | |
| 516 | mf.undefs_mutex.lockUncancelable(io); | |
| 517 | defer mf.undefs_mutex.unlock(io); | |
| 517 | 518 | const gop = try mf.undefs.getOrPut(gpa, index); |
| 518 | 519 | if (!gop.found_existing) { |
| 519 | 520 | gop.value_ptr.* = tag; |
src/link/MachO/file.zig+3-2| ... | ... | @@ -242,6 +242,7 @@ pub const File = union(enum) { |
| 242 | 242 | const tracy = trace(@src()); |
| 243 | 243 | defer tracy.end(); |
| 244 | 244 | |
| 245 | const io = macho_file.base.comp.io; | |
| 245 | 246 | const gpa = macho_file.base.comp.gpa; |
| 246 | 247 | |
| 247 | 248 | for (file.getSymbols(), file.getNlists(), 0..) |sym, nlist, i| { |
| ... | ... | @@ -252,8 +253,8 @@ pub const File = union(enum) { |
| 252 | 253 | const ref_file = ref.getFile(macho_file) orelse continue; |
| 253 | 254 | if (ref_file.getIndex() == file.getIndex()) continue; |
| 254 | 255 | |
| 255 | macho_file.dupes_mutex.lock(); | |
| 256 | defer macho_file.dupes_mutex.unlock(); | |
| 256 | macho_file.dupes_mutex.lockUncancelable(io); | |
| 257 | defer macho_file.dupes_mutex.unlock(io); | |
| 257 | 258 | |
| 258 | 259 | const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]); |
| 259 | 260 | if (!gop.found_existing) { |
src/link/MachO/hasher.zig+7-7| ... | ... | @@ -3,7 +3,7 @@ pub fn ParallelHasher(comptime Hasher: type) type { |
| 3 | 3 | |
| 4 | 4 | return struct { |
| 5 | 5 | allocator: Allocator, |
| 6 | thread_pool: *ThreadPool, | |
| 6 | io: std.Io, | |
| 7 | 7 | |
| 8 | 8 | pub fn hash(self: Self, file: fs.File, out: [][hash_size]u8, opts: struct { |
| 9 | 9 | chunk_size: u64 = 0x4000, |
| ... | ... | @@ -12,7 +12,7 @@ pub fn ParallelHasher(comptime Hasher: type) type { |
| 12 | 12 | const tracy = trace(@src()); |
| 13 | 13 | defer tracy.end(); |
| 14 | 14 | |
| 15 | var wg: WaitGroup = .{}; | |
| 15 | const io = self.io; | |
| 16 | 16 | |
| 17 | 17 | const file_size = blk: { |
| 18 | 18 | const file_size = opts.max_file_size orelse try file.getEndPos(); |
| ... | ... | @@ -27,8 +27,8 @@ pub fn ParallelHasher(comptime Hasher: type) type { |
| 27 | 27 | defer self.allocator.free(results); |
| 28 | 28 | |
| 29 | 29 | { |
| 30 | wg.reset(); | |
| 31 | defer wg.wait(); | |
| 30 | var group: std.Io.Group = .init; | |
| 31 | errdefer group.cancel(io); | |
| 32 | 32 | |
| 33 | 33 | for (out, results, 0..) |*out_buf, *result, i| { |
| 34 | 34 | const fstart = i * chunk_size; |
| ... | ... | @@ -36,7 +36,7 @@ pub fn ParallelHasher(comptime Hasher: type) type { |
| 36 | 36 | file_size - fstart |
| 37 | 37 | else |
| 38 | 38 | chunk_size; |
| 39 | self.thread_pool.spawnWg(&wg, worker, .{ | |
| 39 | group.async(io, worker, .{ | |
| 40 | 40 | file, |
| 41 | 41 | fstart, |
| 42 | 42 | buffer[fstart..][0..fsize], |
| ... | ... | @@ -44,6 +44,8 @@ pub fn ParallelHasher(comptime Hasher: type) type { |
| 44 | 44 | &(result.*), |
| 45 | 45 | }); |
| 46 | 46 | } |
| 47 | ||
| 48 | group.wait(io); | |
| 47 | 49 | } |
| 48 | 50 | for (results) |result| _ = try result; |
| 49 | 51 | } |
| ... | ... | @@ -72,5 +74,3 @@ const std = @import("std"); |
| 72 | 74 | const trace = @import("../../tracy.zig").trace; |
| 73 | 75 | |
| 74 | 76 | const Allocator = mem.Allocator; |
| 75 | const ThreadPool = std.Thread.Pool; | |
| 76 | const 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 | 773 | |
| 774 | 774 | const std = @import("std"); |
| 775 | 775 | const Path = std.Build.Cache.Path; |
| 776 | const WaitGroup = std.Thread.WaitGroup; | |
| 777 | 776 | const assert = std.debug.assert; |
| 778 | 777 | const log = std.log.scoped(.link); |
| 779 | 778 | const 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 | 15 | const hashes = try comp.gpa.alloc([Md5.digest_length]u8, actual_num_chunks); |
| 16 | 16 | defer comp.gpa.free(hashes); |
| 17 | 17 | |
| 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 | 19 | try hasher.hash(file, hashes, .{ |
| 20 | 20 | .chunk_size = chunk_size, |
| 21 | 21 | .max_file_size = file_size, |
| ... | ... | @@ -46,4 +46,3 @@ const trace = @import("../../tracy.zig").trace; |
| 46 | 46 | const Compilation = @import("../../Compilation.zig"); |
| 47 | 47 | const Md5 = std.crypto.hash.Md5; |
| 48 | 48 | const Hasher = @import("hasher.zig").ParallelHasher; |
| 49 | const ThreadPool = std.Thread.Pool; |
src/link/Queue.zig+154-279| ... | ... | @@ -1,254 +1,171 @@ |
| 1 | 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. If | |
| 4 | //! `!comp.separateCodegenThreadOk()`, then ZCU tasks will be run on the main thread, bypassing this | |
| 5 | //! queue entirely. | |
| 3 | //! There are two `std.Io.Queue`s, for prelink and ZCU tasks respectively. The compiler writes tasks | |
| 4 | //! to these queues, and a single concurrent linker task receives and processes them. `Compilation` | |
| 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 tasks | |
| 8 | //! are run, but before any ZCU tasks are run, `prelink` must be called on the `link.File`. | |
| 9 | //! If concurrency is unavailable, the `enqueuePrelink` and `enqueueZcu` functions will instead run | |
| 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 on | |
| 11 | //! MIR which has not yet been generated by any codegen thread. In this case, we must pause | |
| 12 | //! processing of linker tasks until the MIR is ready. It would be incorrect to run any other link | |
| 13 | //! tasks first, since this would make builds unreproducible. | |
| 12 | //! If the codegen backend does not permit concurrency, then `Compilation` will call `finishZcuQueue` | |
| 13 | //! early so that the concurrent linker task exists after prelink and ZCU tasks will run | |
| 14 | //! non-concurrently in `enqueueZcu`. | |
| 14 | 15 | |
| 15 | mutex: std.Thread.Mutex, | |
| 16 | /// Validates that only one `flushTaskQueue` thread is running at a time. | |
| 17 | flush_safety: std.debug.SafetyLock, | |
| 16 | /// This is the concurrent call to `runLinkTasks`. It may be set to non-`null` in `start`, and is | |
| 17 | /// set to `null` by the main thread after it is canceled. It is not otherwise modified; as such, it | |
| 18 | /// may be checked non-atomically. If a task is being queued and this is `null`, tasks must be run | |
| 19 | /// eagerly. | |
| 20 | future: ?std.Io.Future(void), | |
| 18 | 21 | |
| 19 | /// This value is positive while there are still prelink tasks yet to be queued. Once they are | |
| 20 | /// all queued, this value becomes 0, and ZCU tasks can be run. Guarded by `mutex`. | |
| 21 | prelink_wait_count: u32, | |
| 22 | /// This is only used if `future == null` during prelink. In that case, it is used to ensure that | |
| 23 | /// only one prelink task is run at a time. | |
| 24 | prelink_mutex: std.Io.Mutex, | |
| 22 | 25 | |
| 23 | /// Prelink tasks which have been enqueued and are not yet owned by the worker thread. | |
| 24 | /// Allocated into `gpa`, guarded by `mutex`. | |
| 25 | queued_prelink: std.ArrayList(PrelinkTask), | |
| 26 | /// The worker thread moves items from `queued_prelink` into this array in order to process them. | |
| 27 | /// Allocated into `gpa`, accessed only by the worker thread. | |
| 28 | wip_prelink: std.ArrayList(PrelinkTask), | |
| 26 | /// Only valid if `future != null`. | |
| 27 | prelink_queue: std.Io.Queue(PrelinkTask), | |
| 28 | /// Only valid if `future != null`. | |
| 29 | zcu_queue: std.Io.Queue(ZcuTask), | |
| 29 | 30 | |
| 30 | /// Like `queued_prelink`, but for ZCU tasks. | |
| 31 | /// Allocated into `gpa`, guarded by `mutex`. | |
| 32 | queued_zcu: std.ArrayList(ZcuTask), | |
| 33 | /// Like `wip_prelink`, but for ZCU tasks. | |
| 34 | /// Allocated into `gpa`, accessed only by the worker thread. | |
| 35 | wip_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. | |
| 40 | wip_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`. | |
| 48 | air_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`. | |
| 52 | air_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. | |
| 55 | air_bytes_cond: std.Thread.Condition, | |
| 56 | ||
| 57 | /// Guarded by `mutex`. | |
| 58 | state: 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. | |
| 73 | const max_air_bytes_in_flight = 10 * 1024 * 1024; | |
| 31 | /// The capacity of the task queue buffers. | |
| 32 | pub const buffer_size = 512; | |
| 74 | 33 | |
| 75 | 34 | /// The initial `Queue` state, containing no tasks, expecting no prelink tasks, and with no running worker thread. |
| 76 | 35 | /// The `queued_prelink` field may be appended to before calling `start`. |
| 77 | 36 | pub const empty: Queue = .{ |
| 78 | .mutex = .{}, | |
| 79 | .flush_safety = .{}, | |
| 80 | .prelink_wait_count = undefined, // set in `start` | |
| 81 | .queued_prelink = .empty, | |
| 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 = .{}, | |
| 37 | .future = null, | |
| 38 | .prelink_mutex = .init, | |
| 39 | .prelink_queue = undefined, // set in `start` if needed | |
| 40 | .zcu_queue = undefined, // set in `start` if needed | |
| 90 | 41 | }; |
| 91 | /// `lf` is needed to correctly deinit any pending `ZcuTask`s. | |
| 92 | pub fn deinit(q: *Queue, comp: *Compilation) void { | |
| 93 | const gpa = comp.gpa; | |
| 94 | for (q.queued_zcu.items) |t| t.deinit(comp.zcu.?); | |
| 95 | for (q.wip_zcu.items[q.wip_zcu_idx..]) |t| t.deinit(comp.zcu.?); | |
| 96 | q.queued_prelink.deinit(gpa); | |
| 97 | q.wip_prelink.deinit(gpa); | |
| 98 | q.queued_zcu.deinit(gpa); | |
| 99 | q.wip_zcu.deinit(gpa); | |
| 42 | ||
| 43 | pub fn cancel(q: *Queue, io: Io) void { | |
| 44 | if (q.future) |*f| { | |
| 45 | f.cancel(io); | |
| 46 | q.future = null; | |
| 47 | } | |
| 48 | } | |
| 49 | ||
| 50 | pub fn wait(q: *Queue, io: Io) void { | |
| 51 | if (q.future) |*f| { | |
| 52 | f.await(io); | |
| 53 | q.future = null; | |
| 54 | } | |
| 100 | 55 | } |
| 101 | 56 | |
| 102 | 57 | /// This is expected to be called exactly once, after which the caller must not directly access |
| 103 | 58 | /// `queued_prelink` any longer. This will spawn the link thread if necessary. |
| 104 | pub fn start(q: *Queue, comp: *Compilation) void { | |
| 105 | assert(q.state == .finished); | |
| 106 | assert(q.queued_zcu.items.len == 0); | |
| 107 | // Reset this to 1. We can't init it to 1 in `empty`, because it would fall to 0 on successive | |
| 108 | // incremental updates, but we still need the initial 1. | |
| 109 | q.prelink_wait_count = 1; | |
| 110 | if (q.queued_prelink.items.len != 0) { | |
| 111 | q.state = .running; | |
| 112 | comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); | |
| 59 | pub fn start( | |
| 60 | q: *Queue, | |
| 61 | comp: *Compilation, | |
| 62 | arena: Allocator, | |
| 63 | ) Allocator.Error!void { | |
| 64 | assert(q.future == null); | |
| 65 | q.prelink_queue = .init(try arena.alloc(PrelinkTask, buffer_size)); | |
| 66 | q.zcu_queue = .init(try arena.alloc(ZcuTask, buffer_size)); | |
| 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 | } |
| 115 | 78 | |
| 116 | /// Every call to this must be paired with a call to `finishPrelinkItem`. | |
| 117 | pub fn startPrelinkItem(q: *Queue) void { | |
| 118 | q.mutex.lock(); | |
| 119 | defer q.mutex.unlock(); | |
| 120 | assert(q.prelink_wait_count > 0); // must not have finished everything already | |
| 121 | q.prelink_wait_count += 1; | |
| 122 | } | |
| 123 | /// This function must be called exactly one more time than `startPrelinkItem` is. The final call | |
| 124 | /// indicates that we have finished calling `startPrelinkItem`, so once all pending items finish, | |
| 125 | /// we are ready to move on to ZCU tasks. | |
| 126 | pub fn finishPrelinkItem(q: *Queue, comp: *Compilation) void { | |
| 127 | { | |
| 128 | q.mutex.lock(); | |
| 129 | defer q.mutex.unlock(); | |
| 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; | |
| 79 | /// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that | |
| 80 | /// the queue is not yet closed. Also asserts that `tasks.len` is not 0. | |
| 81 | pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Io.Cancelable!void { | |
| 82 | const io = comp.io; | |
| 83 | ||
| 84 | if (q.future != null) { | |
| 85 | q.prelink_queue.putAll(io, tasks) catch |err| switch (err) { | |
| 86 | error.Canceled => |e| return e, | |
| 87 | error.Closed => unreachable, | |
| 88 | }; | |
| 89 | } else { | |
| 90 | try q.prelink_mutex.lock(io); | |
| 91 | defer q.prelink_mutex.unlock(io); | |
| 92 | for (tasks) |task| link.doPrelinkTask(comp, task); | |
| 142 | 93 | } |
| 143 | comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); | |
| 144 | 94 | } |
| 145 | 95 | |
| 146 | /// Called by codegen workers after they have populated a `ZcuTask.LinkFunc.SharedMir`. If the link | |
| 147 | /// thread was waiting for this MIR, it can resume. | |
| 148 | pub fn mirReady(q: *Queue, comp: *Compilation, func_index: InternPool.Index, mir: *ZcuTask.LinkFunc.SharedMir) void { | |
| 149 | // We would like to assert that `mir` is not pending, but that would race with a worker thread | |
| 150 | // potentially freeing it. | |
| 151 | { | |
| 152 | q.mutex.lock(); | |
| 153 | defer q.mutex.unlock(); | |
| 154 | switch (q.state) { | |
| 155 | .finished, .running => return, | |
| 156 | .wait_for_mir => |wait_for| if (wait_for != func_index) return, | |
| 96 | pub fn enqueueZcu( | |
| 97 | q: *Queue, | |
| 98 | comp: *Compilation, | |
| 99 | tid: usize, | |
| 100 | task: ZcuTask, | |
| 101 | ) Io.Cancelable!void { | |
| 102 | const io = comp.io; | |
| 103 | ||
| 104 | assert(tid == 0); | |
| 105 | ||
| 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); | |
| 162 | comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); | |
| 120 | ||
| 121 | link.doZcuTask(comp, tid, task); | |
| 163 | 122 | } |
| 164 | 123 | |
| 165 | /// Enqueues all prelink tasks in `tasks`. Asserts that they were expected, i.e. that | |
| 166 | /// `prelink_wait_count` is not yet 0. Also asserts that `tasks.len` is not 0. | |
| 167 | pub fn enqueuePrelink(q: *Queue, comp: *Compilation, tasks: []const PrelinkTask) Allocator.Error!void { | |
| 168 | { | |
| 169 | q.mutex.lock(); | |
| 170 | defer q.mutex.unlock(); | |
| 171 | assert(q.prelink_wait_count > 0); | |
| 172 | try q.queued_prelink.appendSlice(comp.gpa, tasks); | |
| 173 | switch (q.state) { | |
| 174 | .wait_for_mir => unreachable, // we've not started zcu tasks yet | |
| 175 | .running => return, | |
| 176 | .finished => {}, | |
| 124 | pub fn finishPrelinkQueue(q: *Queue, comp: *Compilation) void { | |
| 125 | if (q.future != null) { | |
| 126 | q.prelink_queue.close(comp.io); | |
| 127 | return; | |
| 128 | } | |
| 129 | // If linking non-concurrently, we must run prelink. | |
| 130 | prelink: { | |
| 131 | const lf = comp.bin_file orelse break :prelink; | |
| 132 | if (lf.post_prelink) break :prelink; | |
| 133 | ||
| 134 | if (lf.prelink()) |_| { | |
| 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 | } |
| 183 | 142 | |
| 184 | pub fn enqueueZcu(q: *Queue, comp: *Compilation, task: ZcuTask) Allocator.Error!void { | |
| 185 | assert(comp.separateCodegenThreadOk()); | |
| 186 | { | |
| 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; | |
| 143 | pub fn finishZcuQueue(q: *Queue, comp: *Compilation) void { | |
| 144 | if (q.future != null) { | |
| 145 | q.zcu_queue.close(comp.io); | |
| 210 | 146 | } |
| 211 | comp.thread_pool.spawnWgId(&comp.link_task_wait_group, flushTaskQueue, .{ q, comp }); | |
| 212 | 147 | } |
| 213 | 148 | |
| 214 | fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { | |
| 215 | q.flush_safety.lock(); // every `return` site should unlock this before unlocking `q.mutex` | |
| 216 | if (std.debug.runtime_safety) { | |
| 217 | q.mutex.lock(); | |
| 218 | defer q.mutex.unlock(); | |
| 219 | assert(q.state == .running); | |
| 220 | } | |
| 149 | fn runLinkTasks(q: *Queue, comp: *Compilation) void { | |
| 150 | const tid = Compilation.getTid(); | |
| 151 | const io = comp.io; | |
| 221 | 152 | |
| 222 | 153 | var have_idle_tasks = true; |
| 223 | prelink: while (true) { | |
| 224 | assert(q.wip_prelink.items.len == 0); | |
| 225 | swap_queues: while (true) { | |
| 226 | { | |
| 227 | q.mutex.lock(); | |
| 228 | defer q.mutex.unlock(); | |
| 229 | std.mem.swap(std.ArrayList(PrelinkTask), &q.queued_prelink, &q.wip_prelink); | |
| 230 | if (q.wip_prelink.items.len > 0) break :swap_queues; | |
| 231 | if (q.prelink_wait_count == 0) break :prelink; // prelink is done | |
| 232 | if (!have_idle_tasks) { | |
| 233 | // We're expecting more prelink tasks so can't move on to ZCU tasks. | |
| 234 | q.state = .finished; | |
| 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| { | |
| 154 | ||
| 155 | prelink_tasks: while (true) { | |
| 156 | var task_buf: [128]PrelinkTask = undefined; | |
| 157 | const limit: usize = if (have_idle_tasks) 0 else 1; | |
| 158 | const n = q.prelink_queue.get(io, &task_buf, limit) catch |err| switch (err) { | |
| 159 | error.Canceled => return, | |
| 160 | error.Closed => break :prelink_tasks, | |
| 161 | }; | |
| 162 | if (n == 0) { | |
| 163 | assert(have_idle_tasks); | |
| 164 | have_idle_tasks = runIdleTask(comp, tid); | |
| 165 | } else for (task_buf[0..n]) |task| { | |
| 248 | 166 | link.doPrelinkTask(comp, task); |
| 167 | have_idle_tasks = true; | |
| 249 | 168 | } |
| 250 | have_idle_tasks = true; | |
| 251 | q.wip_prelink.clearRetainingCapacity(); | |
| 252 | 169 | } |
| 253 | 170 | |
| 254 | 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 | 180 | } |
| 264 | 181 | } |
| 265 | 182 | |
| 266 | // Now we can run ZCU tasks. | |
| 267 | while (true) { | |
| 268 | if (q.wip_zcu.items.len == q.wip_zcu_idx) swap_queues: { | |
| 269 | q.wip_zcu.clearRetainingCapacity(); | |
| 270 | q.wip_zcu_idx = 0; | |
| 271 | while (true) { | |
| 272 | { | |
| 273 | q.mutex.lock(); | |
| 274 | defer q.mutex.unlock(); | |
| 275 | std.mem.swap(std.ArrayList(ZcuTask), &q.queued_zcu, &q.wip_zcu); | |
| 276 | if (q.wip_zcu.items.len > 0) break :swap_queues; | |
| 277 | if (!have_idle_tasks) { | |
| 278 | // We've exhausted all available tasks. | |
| 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; | |
| 183 | zcu_tasks: while (true) { | |
| 184 | var task_buf: [128]ZcuTask = undefined; | |
| 185 | const limit: usize = if (have_idle_tasks) 0 else 1; | |
| 186 | const n = q.zcu_queue.get(io, &task_buf, limit) catch |err| switch (err) { | |
| 187 | error.Canceled => return, | |
| 188 | error.Closed => break :zcu_tasks, | |
| 189 | }; | |
| 190 | if (n == 0) { | |
| 191 | assert(have_idle_tasks); | |
| 192 | have_idle_tasks = runIdleTask(comp, tid); | |
| 193 | } else for (task_buf[0..n]) |task| { | |
| 194 | link.doZcuTask(comp, tid, task); | |
| 195 | have_idle_tasks = true; | |
| 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 | } |
| 199 | fn 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 | } | |
| 335 | 208 | |
| 336 | 209 | const std = @import("std"); |
| 337 | 210 | const assert = std.debug.assert; |
| 338 | 211 | const Allocator = std.mem.Allocator; |
| 212 | const Io = std.Io; | |
| 213 | ||
| 339 | 214 | const Compilation = @import("../Compilation.zig"); |
| 340 | 215 | const InternPool = @import("../InternPool.zig"); |
| 341 | 216 | const link = @import("../link.zig"); |
src/link/Wasm.zig+3-2| ... | ... | @@ -3393,10 +3393,11 @@ pub fn updateExports( |
| 3393 | 3393 | pub fn loadInput(wasm: *Wasm, input: link.Input) !void { |
| 3394 | 3394 | const comp = wasm.base.comp; |
| 3395 | 3395 | const gpa = comp.gpa; |
| 3396 | const io = comp.io; | |
| 3396 | 3397 | |
| 3397 | 3398 | if (comp.verbose_link) { |
| 3398 | comp.mutex.lock(); // protect comp.arena | |
| 3399 | defer comp.mutex.unlock(); | |
| 3399 | comp.mutex.lockUncancelable(io); // protect comp.arena | |
| 3400 | defer comp.mutex.unlock(io); | |
| 3400 | 3401 | |
| 3401 | 3402 | const argv = &wasm.dump_argv_list; |
| 3402 | 3403 | switch (input) { |
src/main.zig+36-34| ... | ... | @@ -11,7 +11,6 @@ const Allocator = mem.Allocator; |
| 11 | 11 | const Ast = std.zig.Ast; |
| 12 | 12 | const Color = std.zig.Color; |
| 13 | 13 | const warn = std.log.warn; |
| 14 | const ThreadPool = std.Thread.Pool; | |
| 15 | 14 | const cleanExit = std.process.cleanExit; |
| 16 | 15 | const Cache = std.Build.Cache; |
| 17 | 16 | const Path = std.Build.Cache.Path; |
| ... | ... | @@ -200,6 +199,8 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 200 | 199 | const tr = tracy.trace(@src()); |
| 201 | 200 | defer tr.end(); |
| 202 | 201 | |
| 202 | Compilation.setMainThread(); | |
| 203 | ||
| 203 | 204 | if (args.len <= 1) { |
| 204 | 205 | std.log.info("{s}", .{usage}); |
| 205 | 206 | fatal("expected command argument", .{}); |
| ... | ... | @@ -239,6 +240,8 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 239 | 240 | |
| 240 | 241 | var threaded: Io.Threaded = .init(gpa); |
| 241 | 242 | defer threaded.deinit(); |
| 243 | threaded_impl_ptr = &threaded; | |
| 244 | threaded.stack_size = thread_stack_size; | |
| 242 | 245 | const io = threaded.io(); |
| 243 | 246 | |
| 244 | 247 | const cmd = args[1]; |
| ... | ... | @@ -3361,14 +3364,11 @@ fn buildOutputType( |
| 3361 | 3364 | }, |
| 3362 | 3365 | }; |
| 3363 | 3366 | |
| 3364 | var thread_pool: ThreadPool = undefined; | |
| 3365 | try thread_pool.init(.{ | |
| 3366 | .allocator = gpa, | |
| 3367 | .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)), | |
| 3368 | .track_ids = true, | |
| 3369 | .stack_size = thread_stack_size, | |
| 3370 | }); | |
| 3371 | defer thread_pool.deinit(); | |
| 3367 | const thread_limit = @min( | |
| 3368 | @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), | |
| 3369 | std.math.maxInt(Zcu.PerThread.IdBacking), | |
| 3370 | ); | |
| 3371 | setThreadLimit(thread_limit); | |
| 3372 | 3372 | |
| 3373 | 3373 | for (create_module.c_source_files.items) |*src| { |
| 3374 | 3374 | dev.check(.c_compiler); |
| ... | ... | @@ -3461,7 +3461,7 @@ fn buildOutputType( |
| 3461 | 3461 | var create_diag: Compilation.CreateDiagnostic = undefined; |
| 3462 | 3462 | const comp = Compilation.create(gpa, arena, io, &create_diag, .{ |
| 3463 | 3463 | .dirs = dirs, |
| 3464 | .thread_pool = &thread_pool, | |
| 3464 | .thread_limit = thread_limit, | |
| 3465 | 3465 | .self_exe_path = switch (native_os) { |
| 3466 | 3466 | .wasi => null, |
| 3467 | 3467 | else => self_exe_path, |
| ... | ... | @@ -4150,6 +4150,7 @@ fn serve( |
| 4150 | 4150 | runtime_args_start: ?usize, |
| 4151 | 4151 | ) !void { |
| 4152 | 4152 | const gpa = comp.gpa; |
| 4153 | const io = comp.io; | |
| 4153 | 4154 | |
| 4154 | 4155 | var server = try Server.init(.{ |
| 4155 | 4156 | .in = in, |
| ... | ... | @@ -4178,8 +4179,8 @@ fn serve( |
| 4178 | 4179 | const hdr = try server.receiveMessage(); |
| 4179 | 4180 | |
| 4180 | 4181 | // Lock the debug server while handling the message. |
| 4181 | if (comp.debugIncremental()) ids.mutex.lock(); | |
| 4182 | defer if (comp.debugIncremental()) ids.mutex.unlock(); | |
| 4182 | if (comp.debugIncremental()) try ids.mutex.lock(io); | |
| 4183 | defer if (comp.debugIncremental()) ids.mutex.unlock(io); | |
| 4183 | 4184 | |
| 4184 | 4185 | switch (hdr.tag) { |
| 4185 | 4186 | .exit => return cleanExit(), |
| ... | ... | @@ -5140,14 +5141,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) |
| 5140 | 5141 | child_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path; |
| 5141 | 5142 | child_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path; |
| 5142 | 5143 | |
| 5143 | var thread_pool: ThreadPool = undefined; | |
| 5144 | try thread_pool.init(.{ | |
| 5145 | .allocator = gpa, | |
| 5146 | .n_jobs = @min(@max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)), | |
| 5147 | .track_ids = true, | |
| 5148 | .stack_size = thread_stack_size, | |
| 5149 | }); | |
| 5150 | defer thread_pool.deinit(); | |
| 5144 | const thread_limit = @min( | |
| 5145 | @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), | |
| 5146 | std.math.maxInt(Zcu.PerThread.IdBacking), | |
| 5147 | ); | |
| 5148 | setThreadLimit(thread_limit); | |
| 5151 | 5149 | |
| 5152 | 5150 | // Dummy http client that is not actually used when fetch_command is unsupported. |
| 5153 | 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 | 5374 | .main_mod = build_mod, |
| 5377 | 5375 | .emit_bin = .yes_cache, |
| 5378 | 5376 | .self_exe_path = self_exe_path, |
| 5379 | .thread_pool = &thread_pool, | |
| 5377 | .thread_limit = thread_limit, | |
| 5380 | 5378 | .verbose_cc = verbose_cc, |
| 5381 | 5379 | .verbose_link = verbose_link, |
| 5382 | 5380 | .verbose_air = verbose_air, |
| ... | ... | @@ -5548,14 +5546,11 @@ fn jitCmd( |
| 5548 | 5546 | ); |
| 5549 | 5547 | defer dirs.deinit(); |
| 5550 | 5548 | |
| 5551 | var thread_pool: ThreadPool = undefined; | |
| 5552 | try thread_pool.init(.{ | |
| 5553 | .allocator = gpa, | |
| 5554 | .n_jobs = @min(@max(std.Thread.getCpuCount() catch 1, 1), std.math.maxInt(Zcu.PerThread.IdBacking)), | |
| 5555 | .track_ids = true, | |
| 5556 | .stack_size = thread_stack_size, | |
| 5557 | }); | |
| 5558 | defer thread_pool.deinit(); | |
| 5549 | const thread_limit = @min( | |
| 5550 | @max(std.Thread.getCpuCount() catch 1, 1), | |
| 5551 | std.math.maxInt(Zcu.PerThread.IdBacking), | |
| 5552 | ); | |
| 5553 | setThreadLimit(thread_limit); | |
| 5559 | 5554 | |
| 5560 | 5555 | var child_argv: std.ArrayList([]const u8) = .empty; |
| 5561 | 5556 | try child_argv.ensureUnusedCapacity(arena, args.len + 4); |
| ... | ... | @@ -5619,7 +5614,7 @@ fn jitCmd( |
| 5619 | 5614 | .main_mod = root_mod, |
| 5620 | 5615 | .emit_bin = .yes_cache, |
| 5621 | 5616 | .self_exe_path = self_exe_path, |
| 5622 | .thread_pool = &thread_pool, | |
| 5617 | .thread_limit = thread_limit, | |
| 5623 | 5618 | .cache_mode = .whole, |
| 5624 | 5619 | }) catch |err| switch (err) { |
| 5625 | 5620 | error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}), |
| ... | ... | @@ -6946,10 +6941,6 @@ fn cmdFetch( |
| 6946 | 6941 | |
| 6947 | 6942 | const path_or_url = opt_path_or_url orelse fatal("missing url or path parameter", .{}); |
| 6948 | 6943 | |
| 6949 | var thread_pool: ThreadPool = undefined; | |
| 6950 | try thread_pool.init(.{ .allocator = gpa }); | |
| 6951 | defer thread_pool.deinit(); | |
| 6952 | ||
| 6953 | 6944 | var http_client: std.http.Client = .{ .allocator = gpa, .io = io }; |
| 6954 | 6945 | defer http_client.deinit(); |
| 6955 | 6946 | |
| ... | ... | @@ -7601,3 +7592,14 @@ fn addLibDirectoryWarn2( |
| 7601 | 7592 | .path = path, |
| 7602 | 7593 | }); |
| 7603 | 7594 | } |
| 7595 | ||
| 7596 | var threaded_impl_ptr: *Io.Threaded = undefined; | |
| 7597 | fn 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 | 55 | }; |
| 56 | 56 | |
| 57 | 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 | 61 | return Value.fromInterned(switch (mv) { |
| 59 | 62 | .interned => |ip_index| ip_index, |
| 60 | 63 | .eu_payload => |sv| try pt.intern(.{ .error_union = .{ |
| ... | ... | @@ -68,7 +71,7 @@ pub const MutableValue = union(enum) { |
| 68 | 71 | .repeated => |sv| return pt.aggregateSplatValue(.fromInterned(sv.ty), try sv.child.intern(pt, arena)), |
| 69 | 72 | .bytes => |b| try pt.intern(.{ .aggregate = .{ |
| 70 | 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 | 76 | .aggregate => |a| { |
| 74 | 77 | const elems = try arena.alloc(InternPool.Index, a.elems.len); |
tools/update_cpu_features.zig+24-27| ... | ... | @@ -1882,10 +1882,18 @@ const targets = [_]ArchTarget{ |
| 1882 | 1882 | }; |
| 1883 | 1883 | |
| 1884 | 1884 | pub fn main() anyerror!void { |
| 1885 | var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); | |
| 1885 | var debug_allocator: std.heap.DebugAllocator(.{}) = .init; | |
| 1886 | defer _ = debug_allocator.deinit(); | |
| 1887 | const gpa = debug_allocator.allocator(); | |
| 1888 | ||
| 1889 | var arena_state: std.heap.ArenaAllocator = .init(gpa); | |
| 1886 | 1890 | defer arena_state.deinit(); |
| 1887 | 1891 | const arena = arena_state.allocator(); |
| 1888 | 1892 | |
| 1893 | var threaded: std.Io.Threaded = .init(gpa); | |
| 1894 | defer threaded.deinit(); | |
| 1895 | const io = threaded.io(); | |
| 1896 | ||
| 1889 | 1897 | var args = try std.process.argsWithAllocator(arena); |
| 1890 | 1898 | const args0 = args.next().?; |
| 1891 | 1899 | |
| ... | ... | @@ -1925,34 +1933,23 @@ pub fn main() anyerror!void { |
| 1925 | 1933 | const root_progress = std.Progress.start(.{ .estimated_total_items = targets.len }); |
| 1926 | 1934 | defer root_progress.end(); |
| 1927 | 1935 | |
| 1928 | if (builtin.single_threaded) { | |
| 1929 | for (targets) |target| { | |
| 1930 | if (filter) |zig_name| if (!std.mem.eql(u8, target.zig_name, zig_name)) continue; | |
| 1931 | try processOneTarget(.{ | |
| 1932 | .llvm_tblgen_exe = llvm_tblgen_exe, | |
| 1933 | .llvm_src_root = llvm_src_root, | |
| 1934 | .zig_src_dir = zig_src_dir, | |
| 1935 | .root_progress = root_progress, | |
| 1936 | .target = target, | |
| 1937 | }); | |
| 1938 | } | |
| 1939 | } else { | |
| 1940 | var pool: std.Thread.Pool = undefined; | |
| 1941 | try pool.init(.{ .allocator = arena, .n_jobs = targets.len }); | |
| 1942 | defer pool.deinit(); | |
| 1943 | ||
| 1944 | for (targets) |target| { | |
| 1945 | if (filter) |zig_name| if (!std.mem.eql(u8, target.zig_name, zig_name)) continue; | |
| 1946 | const job = Job{ | |
| 1947 | .llvm_tblgen_exe = llvm_tblgen_exe, | |
| 1948 | .llvm_src_root = llvm_src_root, | |
| 1949 | .zig_src_dir = zig_src_dir, | |
| 1950 | .root_progress = root_progress, | |
| 1951 | .target = target, | |
| 1952 | }; | |
| 1953 | try pool.spawn(processOneTarget, .{job}); | |
| 1936 | var group: std.Io.Group = .init; | |
| 1937 | defer group.cancel(io); | |
| 1938 | ||
| 1939 | for (targets) |target| { | |
| 1940 | if (filter) |zig_name| { | |
| 1941 | if (!std.mem.eql(u8, target.zig_name, zig_name)) continue; | |
| 1954 | 1942 | } |
| 1943 | group.async(io, processOneTarget, .{.{ | |
| 1944 | .llvm_tblgen_exe = llvm_tblgen_exe, | |
| 1945 | .llvm_src_root = llvm_src_root, | |
| 1946 | .zig_src_dir = zig_src_dir, | |
| 1947 | .root_progress = root_progress, | |
| 1948 | .target = target, | |
| 1949 | }}); | |
| 1955 | 1950 | } |
| 1951 | ||
| 1952 | group.wait(io); | |
| 1956 | 1953 | } |
| 1957 | 1954 | |
| 1958 | 1955 | const Job = struct { |