| author | |
| committer | |
| log | bd5831ce0e033662fed1adf98e81e7d058c6f883 |
| tree | 6d7f915268e23ae56e33a713b1be3ac7560a949e |
| parent | 1a1b5ee264d8b2219c34d53cc9602692e6d2ba24 |
| parent | 31758f79db2c9e1122fd40bdda2243311830a5d4 |
| signature |
stage2: use indexes for Decl objects34 files changed, 3048 insertions(+), 2185 deletions(-)
lib/std/array_hash_map.zig+1-1| ... | ... | @@ -798,7 +798,7 @@ pub fn ArrayHashMapUnmanaged( |
| 798 | 798 | allocator: Allocator, |
| 799 | 799 | additional_capacity: usize, |
| 800 | 800 | ) !void { |
| 801 | if (@sizeOf(ByIndexContext) != 0) | |
| 801 | if (@sizeOf(Context) != 0) | |
| 802 | 802 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureTotalCapacityContext instead."); |
| 803 | 803 | return self.ensureUnusedCapacityContext(allocator, additional_capacity, undefined); |
| 804 | 804 | } |
lib/std/hash_map.zig+2| ... | ... | @@ -913,6 +913,8 @@ pub fn HashMapUnmanaged( |
| 913 | 913 | } |
| 914 | 914 | |
| 915 | 915 | pub fn ensureUnusedCapacity(self: *Self, allocator: Allocator, additional_size: Size) Allocator.Error!void { |
| 916 | if (@sizeOf(Context) != 0) | |
| 917 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureUnusedCapacityContext instead."); | |
| 916 | 918 | return ensureUnusedCapacityContext(self, allocator, additional_size, undefined); |
| 917 | 919 | } |
| 918 | 920 | pub fn ensureUnusedCapacityContext(self: *Self, allocator: Allocator, additional_size: Size, ctx: Context) Allocator.Error!void { |
lib/std/segmented_list.zig created+472| ... | ... | @@ -0,0 +1,472 @@ |
| 1 | const std = @import("std.zig"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const testing = std.testing; | |
| 4 | const Allocator = std.mem.Allocator; | |
| 5 | ||
| 6 | // Imagine that `fn at(self: *Self, index: usize) &T` is a customer asking for a box | |
| 7 | // from a warehouse, based on a flat array, boxes ordered from 0 to N - 1. | |
| 8 | // But the warehouse actually stores boxes in shelves of increasing powers of 2 sizes. | |
| 9 | // So when the customer requests a box index, we have to translate it to shelf index | |
| 10 | // and box index within that shelf. Illustration: | |
| 11 | // | |
| 12 | // customer indexes: | |
| 13 | // shelf 0: 0 | |
| 14 | // shelf 1: 1 2 | |
| 15 | // shelf 2: 3 4 5 6 | |
| 16 | // shelf 3: 7 8 9 10 11 12 13 14 | |
| 17 | // shelf 4: 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
| 18 | // shelf 5: 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
| 19 | // ... | |
| 20 | // | |
| 21 | // warehouse indexes: | |
| 22 | // shelf 0: 0 | |
| 23 | // shelf 1: 0 1 | |
| 24 | // shelf 2: 0 1 2 3 | |
| 25 | // shelf 3: 0 1 2 3 4 5 6 7 | |
| 26 | // shelf 4: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
| 27 | // shelf 5: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
| 28 | // ... | |
| 29 | // | |
| 30 | // With this arrangement, here are the equations to get the shelf index and | |
| 31 | // box index based on customer box index: | |
| 32 | // | |
| 33 | // shelf_index = floor(log2(customer_index + 1)) | |
| 34 | // shelf_count = ceil(log2(box_count + 1)) | |
| 35 | // box_index = customer_index + 1 - 2 ** shelf | |
| 36 | // shelf_size = 2 ** shelf_index | |
| 37 | // | |
| 38 | // Now we complicate it a little bit further by adding a preallocated shelf, which must be | |
| 39 | // a power of 2: | |
| 40 | // prealloc=4 | |
| 41 | // | |
| 42 | // customer indexes: | |
| 43 | // prealloc: 0 1 2 3 | |
| 44 | // shelf 0: 4 5 6 7 8 9 10 11 | |
| 45 | // shelf 1: 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
| 46 | // shelf 2: 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
| 47 | // ... | |
| 48 | // | |
| 49 | // warehouse indexes: | |
| 50 | // prealloc: 0 1 2 3 | |
| 51 | // shelf 0: 0 1 2 3 4 5 6 7 | |
| 52 | // shelf 1: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
| 53 | // shelf 2: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
| 54 | // ... | |
| 55 | // | |
| 56 | // Now the equations are: | |
| 57 | // | |
| 58 | // shelf_index = floor(log2(customer_index + prealloc)) - log2(prealloc) - 1 | |
| 59 | // shelf_count = ceil(log2(box_count + prealloc)) - log2(prealloc) - 1 | |
| 60 | // box_index = customer_index + prealloc - 2 ** (log2(prealloc) + 1 + shelf) | |
| 61 | // shelf_size = prealloc * 2 ** (shelf_index + 1) | |
| 62 | ||
| 63 | /// This is a stack data structure where pointers to indexes have the same lifetime as the data structure | |
| 64 | /// itself, unlike ArrayList where append() invalidates all existing element pointers. | |
| 65 | /// The tradeoff is that elements are not guaranteed to be contiguous. For that, use ArrayList. | |
| 66 | /// Note however that most elements are contiguous, making this data structure cache-friendly. | |
| 67 | /// | |
| 68 | /// Because it never has to copy elements from an old location to a new location, it does not require | |
| 69 | /// its elements to be copyable, and it avoids wasting memory when backed by an ArenaAllocator. | |
| 70 | /// Note that the append() and pop() convenience methods perform a copy, but you can instead use | |
| 71 | /// addOne(), at(), setCapacity(), and shrinkCapacity() to avoid copying items. | |
| 72 | /// | |
| 73 | /// This data structure has O(1) append and O(1) pop. | |
| 74 | /// | |
| 75 | /// It supports preallocated elements, making it especially well suited when the expected maximum | |
| 76 | /// size is small. `prealloc_item_count` must be 0, or a power of 2. | |
| 77 | pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type { | |
| 78 | return struct { | |
| 79 | const Self = @This(); | |
| 80 | const ShelfIndex = std.math.Log2Int(usize); | |
| 81 | ||
| 82 | const prealloc_exp: ShelfIndex = blk: { | |
| 83 | // we don't use the prealloc_exp constant when prealloc_item_count is 0 | |
| 84 | // but lazy-init may still be triggered by other code so supply a value | |
| 85 | if (prealloc_item_count == 0) { | |
| 86 | break :blk 0; | |
| 87 | } else { | |
| 88 | assert(std.math.isPowerOfTwo(prealloc_item_count)); | |
| 89 | const value = std.math.log2_int(usize, prealloc_item_count); | |
| 90 | break :blk value; | |
| 91 | } | |
| 92 | }; | |
| 93 | ||
| 94 | prealloc_segment: [prealloc_item_count]T = undefined, | |
| 95 | dynamic_segments: [][*]T = &[_][*]T{}, | |
| 96 | len: usize = 0, | |
| 97 | ||
| 98 | pub const prealloc_count = prealloc_item_count; | |
| 99 | ||
| 100 | fn AtType(comptime SelfType: type) type { | |
| 101 | if (@typeInfo(SelfType).Pointer.is_const) { | |
| 102 | return *const T; | |
| 103 | } else { | |
| 104 | return *T; | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | pub fn deinit(self: *Self, allocator: Allocator) void { | |
| 109 | self.freeShelves(allocator, @intCast(ShelfIndex, self.dynamic_segments.len), 0); | |
| 110 | allocator.free(self.dynamic_segments); | |
| 111 | self.* = undefined; | |
| 112 | } | |
| 113 | ||
| 114 | pub fn at(self: anytype, i: usize) AtType(@TypeOf(self)) { | |
| 115 | assert(i < self.len); | |
| 116 | return self.uncheckedAt(i); | |
| 117 | } | |
| 118 | ||
| 119 | pub fn count(self: Self) usize { | |
| 120 | return self.len; | |
| 121 | } | |
| 122 | ||
| 123 | pub fn append(self: *Self, allocator: Allocator, item: T) Allocator.Error!void { | |
| 124 | const new_item_ptr = try self.addOne(allocator); | |
| 125 | new_item_ptr.* = item; | |
| 126 | } | |
| 127 | ||
| 128 | pub fn appendSlice(self: *Self, allocator: Allocator, items: []const T) Allocator.Error!void { | |
| 129 | for (items) |item| { | |
| 130 | try self.append(allocator, item); | |
| 131 | } | |
| 132 | } | |
| 133 | ||
| 134 | pub fn pop(self: *Self) ?T { | |
| 135 | if (self.len == 0) return null; | |
| 136 | ||
| 137 | const index = self.len - 1; | |
| 138 | const result = uncheckedAt(self, index).*; | |
| 139 | self.len = index; | |
| 140 | return result; | |
| 141 | } | |
| 142 | ||
| 143 | pub fn addOne(self: *Self, allocator: Allocator) Allocator.Error!*T { | |
| 144 | const new_length = self.len + 1; | |
| 145 | try self.growCapacity(allocator, new_length); | |
| 146 | const result = uncheckedAt(self, self.len); | |
| 147 | self.len = new_length; | |
| 148 | return result; | |
| 149 | } | |
| 150 | ||
| 151 | /// Reduce length to `new_len`. | |
| 152 | /// Invalidates pointers for the elements at index new_len and beyond. | |
| 153 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { | |
| 154 | assert(new_len <= self.len); | |
| 155 | self.len = new_len; | |
| 156 | } | |
| 157 | ||
| 158 | /// Invalidates all element pointers. | |
| 159 | pub fn clearRetainingCapacity(self: *Self) void { | |
| 160 | self.items.len = 0; | |
| 161 | } | |
| 162 | ||
| 163 | /// Invalidates all element pointers. | |
| 164 | pub fn clearAndFree(self: *Self, allocator: Allocator) void { | |
| 165 | self.setCapacity(allocator, 0) catch unreachable; | |
| 166 | self.items.len = 0; | |
| 167 | } | |
| 168 | ||
| 169 | /// Grows or shrinks capacity to match usage. | |
| 170 | /// TODO update this and related methods to match the conventions set by ArrayList | |
| 171 | pub fn setCapacity(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { | |
| 172 | if (prealloc_item_count != 0) { | |
| 173 | if (new_capacity <= @as(usize, 1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) { | |
| 174 | return self.shrinkCapacity(allocator, new_capacity); | |
| 175 | } | |
| 176 | } | |
| 177 | return self.growCapacity(allocator, new_capacity); | |
| 178 | } | |
| 179 | ||
| 180 | /// Only grows capacity, or retains current capacity | |
| 181 | pub fn growCapacity(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { | |
| 182 | const new_cap_shelf_count = shelfCount(new_capacity); | |
| 183 | const old_shelf_count = @intCast(ShelfIndex, self.dynamic_segments.len); | |
| 184 | if (new_cap_shelf_count > old_shelf_count) { | |
| 185 | self.dynamic_segments = try allocator.realloc(self.dynamic_segments, new_cap_shelf_count); | |
| 186 | var i = old_shelf_count; | |
| 187 | errdefer { | |
| 188 | self.freeShelves(allocator, i, old_shelf_count); | |
| 189 | self.dynamic_segments = allocator.shrink(self.dynamic_segments, old_shelf_count); | |
| 190 | } | |
| 191 | while (i < new_cap_shelf_count) : (i += 1) { | |
| 192 | self.dynamic_segments[i] = (try allocator.alloc(T, shelfSize(i))).ptr; | |
| 193 | } | |
| 194 | } | |
| 195 | } | |
| 196 | ||
| 197 | /// Only shrinks capacity or retains current capacity | |
| 198 | pub fn shrinkCapacity(self: *Self, allocator: Allocator, new_capacity: usize) void { | |
| 199 | if (new_capacity <= prealloc_item_count) { | |
| 200 | const len = @intCast(ShelfIndex, self.dynamic_segments.len); | |
| 201 | self.freeShelves(allocator, len, 0); | |
| 202 | allocator.free(self.dynamic_segments); | |
| 203 | self.dynamic_segments = &[_][*]T{}; | |
| 204 | return; | |
| 205 | } | |
| 206 | ||
| 207 | const new_cap_shelf_count = shelfCount(new_capacity); | |
| 208 | const old_shelf_count = @intCast(ShelfIndex, self.dynamic_segments.len); | |
| 209 | assert(new_cap_shelf_count <= old_shelf_count); | |
| 210 | if (new_cap_shelf_count == old_shelf_count) { | |
| 211 | return; | |
| 212 | } | |
| 213 | ||
| 214 | self.freeShelves(allocator, old_shelf_count, new_cap_shelf_count); | |
| 215 | self.dynamic_segments = allocator.shrink(self.dynamic_segments, new_cap_shelf_count); | |
| 216 | } | |
| 217 | ||
| 218 | pub fn shrink(self: *Self, new_len: usize) void { | |
| 219 | assert(new_len <= self.len); | |
| 220 | // TODO take advantage of the new realloc semantics | |
| 221 | self.len = new_len; | |
| 222 | } | |
| 223 | ||
| 224 | pub fn writeToSlice(self: *Self, dest: []T, start: usize) void { | |
| 225 | const end = start + dest.len; | |
| 226 | assert(end <= self.len); | |
| 227 | ||
| 228 | var i = start; | |
| 229 | if (end <= prealloc_item_count) { | |
| 230 | std.mem.copy(T, dest[i - start ..], self.prealloc_segment[i..end]); | |
| 231 | return; | |
| 232 | } else if (i < prealloc_item_count) { | |
| 233 | std.mem.copy(T, dest[i - start ..], self.prealloc_segment[i..]); | |
| 234 | i = prealloc_item_count; | |
| 235 | } | |
| 236 | ||
| 237 | while (i < end) { | |
| 238 | const shelf_index = shelfIndex(i); | |
| 239 | const copy_start = boxIndex(i, shelf_index); | |
| 240 | const copy_end = std.math.min(shelfSize(shelf_index), copy_start + end - i); | |
| 241 | ||
| 242 | std.mem.copy( | |
| 243 | T, | |
| 244 | dest[i - start ..], | |
| 245 | self.dynamic_segments[shelf_index][copy_start..copy_end], | |
| 246 | ); | |
| 247 | ||
| 248 | i += (copy_end - copy_start); | |
| 249 | } | |
| 250 | } | |
| 251 | ||
| 252 | pub fn uncheckedAt(self: anytype, index: usize) AtType(@TypeOf(self)) { | |
| 253 | if (index < prealloc_item_count) { | |
| 254 | return &self.prealloc_segment[index]; | |
| 255 | } | |
| 256 | const shelf_index = shelfIndex(index); | |
| 257 | const box_index = boxIndex(index, shelf_index); | |
| 258 | return &self.dynamic_segments[shelf_index][box_index]; | |
| 259 | } | |
| 260 | ||
| 261 | fn shelfCount(box_count: usize) ShelfIndex { | |
| 262 | if (prealloc_item_count == 0) { | |
| 263 | return log2_int_ceil(usize, box_count + 1); | |
| 264 | } | |
| 265 | return log2_int_ceil(usize, box_count + prealloc_item_count) - prealloc_exp - 1; | |
| 266 | } | |
| 267 | ||
| 268 | fn shelfSize(shelf_index: ShelfIndex) usize { | |
| 269 | if (prealloc_item_count == 0) { | |
| 270 | return @as(usize, 1) << shelf_index; | |
| 271 | } | |
| 272 | return @as(usize, 1) << (shelf_index + (prealloc_exp + 1)); | |
| 273 | } | |
| 274 | ||
| 275 | fn shelfIndex(list_index: usize) ShelfIndex { | |
| 276 | if (prealloc_item_count == 0) { | |
| 277 | return std.math.log2_int(usize, list_index + 1); | |
| 278 | } | |
| 279 | return std.math.log2_int(usize, list_index + prealloc_item_count) - prealloc_exp - 1; | |
| 280 | } | |
| 281 | ||
| 282 | fn boxIndex(list_index: usize, shelf_index: ShelfIndex) usize { | |
| 283 | if (prealloc_item_count == 0) { | |
| 284 | return (list_index + 1) - (@as(usize, 1) << shelf_index); | |
| 285 | } | |
| 286 | return list_index + prealloc_item_count - (@as(usize, 1) << ((prealloc_exp + 1) + shelf_index)); | |
| 287 | } | |
| 288 | ||
| 289 | fn freeShelves(self: *Self, allocator: Allocator, from_count: ShelfIndex, to_count: ShelfIndex) void { | |
| 290 | var i = from_count; | |
| 291 | while (i != to_count) { | |
| 292 | i -= 1; | |
| 293 | allocator.free(self.dynamic_segments[i][0..shelfSize(i)]); | |
| 294 | } | |
| 295 | } | |
| 296 | ||
| 297 | pub const Iterator = struct { | |
| 298 | list: *Self, | |
| 299 | index: usize, | |
| 300 | box_index: usize, | |
| 301 | shelf_index: ShelfIndex, | |
| 302 | shelf_size: usize, | |
| 303 | ||
| 304 | pub fn next(it: *Iterator) ?*T { | |
| 305 | if (it.index >= it.list.len) return null; | |
| 306 | if (it.index < prealloc_item_count) { | |
| 307 | const ptr = &it.list.prealloc_segment[it.index]; | |
| 308 | it.index += 1; | |
| 309 | if (it.index == prealloc_item_count) { | |
| 310 | it.box_index = 0; | |
| 311 | it.shelf_index = 0; | |
| 312 | it.shelf_size = prealloc_item_count * 2; | |
| 313 | } | |
| 314 | return ptr; | |
| 315 | } | |
| 316 | ||
| 317 | const ptr = &it.list.dynamic_segments[it.shelf_index][it.box_index]; | |
| 318 | it.index += 1; | |
| 319 | it.box_index += 1; | |
| 320 | if (it.box_index == it.shelf_size) { | |
| 321 | it.shelf_index += 1; | |
| 322 | it.box_index = 0; | |
| 323 | it.shelf_size *= 2; | |
| 324 | } | |
| 325 | return ptr; | |
| 326 | } | |
| 327 | ||
| 328 | pub fn prev(it: *Iterator) ?*T { | |
| 329 | if (it.index == 0) return null; | |
| 330 | ||
| 331 | it.index -= 1; | |
| 332 | if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index]; | |
| 333 | ||
| 334 | if (it.box_index == 0) { | |
| 335 | it.shelf_index -= 1; | |
| 336 | it.shelf_size /= 2; | |
| 337 | it.box_index = it.shelf_size - 1; | |
| 338 | } else { | |
| 339 | it.box_index -= 1; | |
| 340 | } | |
| 341 | ||
| 342 | return &it.list.dynamic_segments[it.shelf_index][it.box_index]; | |
| 343 | } | |
| 344 | ||
| 345 | pub fn peek(it: *Iterator) ?*T { | |
| 346 | if (it.index >= it.list.len) | |
| 347 | return null; | |
| 348 | if (it.index < prealloc_item_count) | |
| 349 | return &it.list.prealloc_segment[it.index]; | |
| 350 | ||
| 351 | return &it.list.dynamic_segments[it.shelf_index][it.box_index]; | |
| 352 | } | |
| 353 | ||
| 354 | pub fn set(it: *Iterator, index: usize) void { | |
| 355 | it.index = index; | |
| 356 | if (index < prealloc_item_count) return; | |
| 357 | it.shelf_index = shelfIndex(index); | |
| 358 | it.box_index = boxIndex(index, it.shelf_index); | |
| 359 | it.shelf_size = shelfSize(it.shelf_index); | |
| 360 | } | |
| 361 | }; | |
| 362 | ||
| 363 | pub fn iterator(self: *Self, start_index: usize) Iterator { | |
| 364 | var it = Iterator{ | |
| 365 | .list = self, | |
| 366 | .index = undefined, | |
| 367 | .shelf_index = undefined, | |
| 368 | .box_index = undefined, | |
| 369 | .shelf_size = undefined, | |
| 370 | }; | |
| 371 | it.set(start_index); | |
| 372 | return it; | |
| 373 | } | |
| 374 | }; | |
| 375 | } | |
| 376 | ||
| 377 | test "basic usage" { | |
| 378 | try testSegmentedList(0); | |
| 379 | try testSegmentedList(1); | |
| 380 | try testSegmentedList(2); | |
| 381 | try testSegmentedList(4); | |
| 382 | try testSegmentedList(8); | |
| 383 | try testSegmentedList(16); | |
| 384 | } | |
| 385 | ||
| 386 | fn testSegmentedList(comptime prealloc: usize) !void { | |
| 387 | const gpa = std.testing.allocator; | |
| 388 | ||
| 389 | var list: SegmentedList(i32, prealloc) = .{}; | |
| 390 | defer list.deinit(gpa); | |
| 391 | ||
| 392 | { | |
| 393 | var i: usize = 0; | |
| 394 | while (i < 100) : (i += 1) { | |
| 395 | try list.append(gpa, @intCast(i32, i + 1)); | |
| 396 | try testing.expect(list.len == i + 1); | |
| 397 | } | |
| 398 | } | |
| 399 | ||
| 400 | { | |
| 401 | var i: usize = 0; | |
| 402 | while (i < 100) : (i += 1) { | |
| 403 | try testing.expect(list.at(i).* == @intCast(i32, i + 1)); | |
| 404 | } | |
| 405 | } | |
| 406 | ||
| 407 | { | |
| 408 | var it = list.iterator(0); | |
| 409 | var x: i32 = 0; | |
| 410 | while (it.next()) |item| { | |
| 411 | x += 1; | |
| 412 | try testing.expect(item.* == x); | |
| 413 | } | |
| 414 | try testing.expect(x == 100); | |
| 415 | while (it.prev()) |item| : (x -= 1) { | |
| 416 | try testing.expect(item.* == x); | |
| 417 | } | |
| 418 | try testing.expect(x == 0); | |
| 419 | } | |
| 420 | ||
| 421 | try testing.expect(list.pop().? == 100); | |
| 422 | try testing.expect(list.len == 99); | |
| 423 | ||
| 424 | try list.appendSlice(gpa, &[_]i32{ 1, 2, 3 }); | |
| 425 | try testing.expect(list.len == 102); | |
| 426 | try testing.expect(list.pop().? == 3); | |
| 427 | try testing.expect(list.pop().? == 2); | |
| 428 | try testing.expect(list.pop().? == 1); | |
| 429 | try testing.expect(list.len == 99); | |
| 430 | ||
| 431 | try list.appendSlice(gpa, &[_]i32{}); | |
| 432 | try testing.expect(list.len == 99); | |
| 433 | ||
| 434 | { | |
| 435 | var i: i32 = 99; | |
| 436 | while (list.pop()) |item| : (i -= 1) { | |
| 437 | try testing.expect(item == i); | |
| 438 | list.shrinkCapacity(gpa, list.len); | |
| 439 | } | |
| 440 | } | |
| 441 | ||
| 442 | { | |
| 443 | var control: [100]i32 = undefined; | |
| 444 | var dest: [100]i32 = undefined; | |
| 445 | ||
| 446 | var i: i32 = 0; | |
| 447 | while (i < 100) : (i += 1) { | |
| 448 | try list.append(gpa, i + 1); | |
| 449 | control[@intCast(usize, i)] = i + 1; | |
| 450 | } | |
| 451 | ||
| 452 | std.mem.set(i32, dest[0..], 0); | |
| 453 | list.writeToSlice(dest[0..], 0); | |
| 454 | try testing.expect(std.mem.eql(i32, control[0..], dest[0..])); | |
| 455 | ||
| 456 | std.mem.set(i32, dest[0..], 0); | |
| 457 | list.writeToSlice(dest[50..], 50); | |
| 458 | try testing.expect(std.mem.eql(i32, control[50..], dest[50..])); | |
| 459 | } | |
| 460 | ||
| 461 | try list.setCapacity(gpa, 0); | |
| 462 | } | |
| 463 | ||
| 464 | /// TODO look into why this std.math function was changed in | |
| 465 | /// fc9430f56798a53f9393a697f4ccd6bf9981b970. | |
| 466 | fn log2_int_ceil(comptime T: type, x: T) std.math.Log2Int(T) { | |
| 467 | assert(x != 0); | |
| 468 | const log2_val = std.math.log2_int(T, x); | |
| 469 | if (@as(T, 1) << log2_val == x) | |
| 470 | return log2_val; | |
| 471 | return log2_val + 1; | |
| 472 | } |
lib/std/std.zig+1| ... | ... | @@ -29,6 +29,7 @@ pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceE |
| 29 | 29 | pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue; |
| 30 | 30 | pub const PriorityDequeue = @import("priority_dequeue.zig").PriorityDequeue; |
| 31 | 31 | pub const Progress = @import("Progress.zig"); |
| 32 | pub const SegmentedList = @import("segmented_list.zig").SegmentedList; | |
| 32 | 33 | pub const SemanticVersion = @import("SemanticVersion.zig"); |
| 33 | 34 | pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList; |
| 34 | 35 | pub const StaticBitSet = bit_set.StaticBitSet; |
src/Compilation.zig+120-103| ... | ... | @@ -191,22 +191,22 @@ pub const CSourceFile = struct { |
| 191 | 191 | |
| 192 | 192 | const Job = union(enum) { |
| 193 | 193 | /// Write the constant value for a Decl to the output file. |
| 194 | codegen_decl: *Module.Decl, | |
| 194 | codegen_decl: Module.Decl.Index, | |
| 195 | 195 | /// Write the machine code for a function to the output file. |
| 196 | 196 | codegen_func: *Module.Fn, |
| 197 | 197 | /// Render the .h file snippet for the Decl. |
| 198 | emit_h_decl: *Module.Decl, | |
| 198 | emit_h_decl: Module.Decl.Index, | |
| 199 | 199 | /// The Decl needs to be analyzed and possibly export itself. |
| 200 | 200 | /// It may have already be analyzed, or it may have been determined |
| 201 | 201 | /// to be outdated; in this case perform semantic analysis again. |
| 202 | analyze_decl: *Module.Decl, | |
| 202 | analyze_decl: Module.Decl.Index, | |
| 203 | 203 | /// The file that was loaded with `@embedFile` has changed on disk |
| 204 | 204 | /// and has been re-loaded into memory. All Decls that depend on it |
| 205 | 205 | /// need to be re-analyzed. |
| 206 | 206 | update_embed_file: *Module.EmbedFile, |
| 207 | 207 | /// The source file containing the Decl has been updated, and so the |
| 208 | 208 | /// Decl may need its line number information updated in the debug info. |
| 209 | update_line_number: *Module.Decl, | |
| 209 | update_line_number: Module.Decl.Index, | |
| 210 | 210 | /// The main source file for the package needs to be analyzed. |
| 211 | 211 | analyze_pkg: *Package, |
| 212 | 212 | |
| ... | ... | @@ -2105,17 +2105,18 @@ pub fn update(comp: *Compilation) !void { |
| 2105 | 2105 | // deletion set may grow as we call `clearDecl` within this loop, |
| 2106 | 2106 | // and more unreferenced Decls are revealed. |
| 2107 | 2107 | while (module.deletion_set.count() != 0) { |
| 2108 | const decl = module.deletion_set.keys()[0]; | |
| 2108 | const decl_index = module.deletion_set.keys()[0]; | |
| 2109 | const decl = module.declPtr(decl_index); | |
| 2109 | 2110 | assert(decl.deletion_flag); |
| 2110 | 2111 | assert(decl.dependants.count() == 0); |
| 2111 | 2112 | const is_anon = if (decl.zir_decl_index == 0) blk: { |
| 2112 | break :blk decl.src_namespace.anon_decls.swapRemove(decl); | |
| 2113 | break :blk decl.src_namespace.anon_decls.swapRemove(decl_index); | |
| 2113 | 2114 | } else false; |
| 2114 | 2115 | |
| 2115 | try module.clearDecl(decl, null); | |
| 2116 | try module.clearDecl(decl_index, null); | |
| 2116 | 2117 | |
| 2117 | 2118 | if (is_anon) { |
| 2118 | decl.destroy(module); | |
| 2119 | module.destroyDecl(decl_index); | |
| 2119 | 2120 | } |
| 2120 | 2121 | } |
| 2121 | 2122 | |
| ... | ... | @@ -2444,13 +2445,15 @@ pub fn totalErrorCount(self: *Compilation) usize { |
| 2444 | 2445 | // the previous parse success, including compile errors, but we cannot |
| 2445 | 2446 | // emit them until the file succeeds parsing. |
| 2446 | 2447 | for (module.failed_decls.keys()) |key| { |
| 2447 | if (key.getFileScope().okToReportErrors()) { | |
| 2448 | const decl = module.declPtr(key); | |
| 2449 | if (decl.getFileScope().okToReportErrors()) { | |
| 2448 | 2450 | total += 1; |
| 2449 | 2451 | } |
| 2450 | 2452 | } |
| 2451 | 2453 | if (module.emit_h) |emit_h| { |
| 2452 | 2454 | for (emit_h.failed_decls.keys()) |key| { |
| 2453 | if (key.getFileScope().okToReportErrors()) { | |
| 2455 | const decl = module.declPtr(key); | |
| 2456 | if (decl.getFileScope().okToReportErrors()) { | |
| 2454 | 2457 | total += 1; |
| 2455 | 2458 | } |
| 2456 | 2459 | } |
| ... | ... | @@ -2529,9 +2532,10 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2529 | 2532 | { |
| 2530 | 2533 | var it = module.failed_decls.iterator(); |
| 2531 | 2534 | while (it.next()) |entry| { |
| 2535 | const decl = module.declPtr(entry.key_ptr.*); | |
| 2532 | 2536 | // Skip errors for Decls within files that had a parse failure. |
| 2533 | 2537 | // We'll try again once parsing succeeds. |
| 2534 | if (entry.key_ptr.*.getFileScope().okToReportErrors()) { | |
| 2538 | if (decl.getFileScope().okToReportErrors()) { | |
| 2535 | 2539 | try AllErrors.add(module, &arena, &errors, entry.value_ptr.*.*); |
| 2536 | 2540 | } |
| 2537 | 2541 | } |
| ... | ... | @@ -2539,9 +2543,10 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2539 | 2543 | if (module.emit_h) |emit_h| { |
| 2540 | 2544 | var it = emit_h.failed_decls.iterator(); |
| 2541 | 2545 | while (it.next()) |entry| { |
| 2546 | const decl = module.declPtr(entry.key_ptr.*); | |
| 2542 | 2547 | // Skip errors for Decls within files that had a parse failure. |
| 2543 | 2548 | // We'll try again once parsing succeeds. |
| 2544 | if (entry.key_ptr.*.getFileScope().okToReportErrors()) { | |
| 2549 | if (decl.getFileScope().okToReportErrors()) { | |
| 2545 | 2550 | try AllErrors.add(module, &arena, &errors, entry.value_ptr.*.*); |
| 2546 | 2551 | } |
| 2547 | 2552 | } |
| ... | ... | @@ -2564,7 +2569,8 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2564 | 2569 | const keys = module.compile_log_decls.keys(); |
| 2565 | 2570 | const values = module.compile_log_decls.values(); |
| 2566 | 2571 | // First one will be the error; subsequent ones will be notes. |
| 2567 | const src_loc = keys[0].nodeOffsetSrcLoc(values[0]); | |
| 2572 | const err_decl = module.declPtr(keys[0]); | |
| 2573 | const src_loc = err_decl.nodeOffsetSrcLoc(values[0]); | |
| 2568 | 2574 | const err_msg = Module.ErrorMsg{ |
| 2569 | 2575 | .src_loc = src_loc, |
| 2570 | 2576 | .msg = "found compile log statement", |
| ... | ... | @@ -2573,8 +2579,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2573 | 2579 | defer self.gpa.free(err_msg.notes); |
| 2574 | 2580 | |
| 2575 | 2581 | for (keys[1..]) |key, i| { |
| 2582 | const note_decl = module.declPtr(key); | |
| 2576 | 2583 | err_msg.notes[i] = .{ |
| 2577 | .src_loc = key.nodeOffsetSrcLoc(values[i + 1]), | |
| 2584 | .src_loc = note_decl.nodeOffsetSrcLoc(values[i + 1]), | |
| 2578 | 2585 | .msg = "also here", |
| 2579 | 2586 | }; |
| 2580 | 2587 | } |
| ... | ... | @@ -2708,38 +2715,42 @@ pub fn performAllTheWork( |
| 2708 | 2715 | |
| 2709 | 2716 | fn processOneJob(comp: *Compilation, job: Job) !void { |
| 2710 | 2717 | switch (job) { |
| 2711 | .codegen_decl => |decl| switch (decl.analysis) { | |
| 2712 | .unreferenced => unreachable, | |
| 2713 | .in_progress => unreachable, | |
| 2714 | .outdated => unreachable, | |
| 2715 | ||
| 2716 | .file_failure, | |
| 2717 | .sema_failure, | |
| 2718 | .codegen_failure, | |
| 2719 | .dependency_failure, | |
| 2720 | .sema_failure_retryable, | |
| 2721 | => return, | |
| 2722 | ||
| 2723 | .complete, .codegen_failure_retryable => { | |
| 2724 | if (build_options.omit_stage2) | |
| 2725 | @panic("sadly stage2 is omitted from this build to save memory on the CI server"); | |
| 2726 | ||
| 2727 | const named_frame = tracy.namedFrame("codegen_decl"); | |
| 2728 | defer named_frame.end(); | |
| 2729 | ||
| 2730 | const module = comp.bin_file.options.module.?; | |
| 2731 | assert(decl.has_tv); | |
| 2732 | ||
| 2733 | if (decl.alive) { | |
| 2734 | try module.linkerUpdateDecl(decl); | |
| 2735 | return; | |
| 2736 | } | |
| 2718 | .codegen_decl => |decl_index| { | |
| 2719 | if (build_options.omit_stage2) | |
| 2720 | @panic("sadly stage2 is omitted from this build to save memory on the CI server"); | |
| 2737 | 2721 | |
| 2738 | // Instead of sending this decl to the linker, we actually will delete it | |
| 2739 | // because we found out that it in fact was never referenced. | |
| 2740 | module.deleteUnusedDecl(decl); | |
| 2741 | return; | |
| 2742 | }, | |
| 2722 | const module = comp.bin_file.options.module.?; | |
| 2723 | const decl = module.declPtr(decl_index); | |
| 2724 | ||
| 2725 | switch (decl.analysis) { | |
| 2726 | .unreferenced => unreachable, | |
| 2727 | .in_progress => unreachable, | |
| 2728 | .outdated => unreachable, | |
| 2729 | ||
| 2730 | .file_failure, | |
| 2731 | .sema_failure, | |
| 2732 | .codegen_failure, | |
| 2733 | .dependency_failure, | |
| 2734 | .sema_failure_retryable, | |
| 2735 | => return, | |
| 2736 | ||
| 2737 | .complete, .codegen_failure_retryable => { | |
| 2738 | const named_frame = tracy.namedFrame("codegen_decl"); | |
| 2739 | defer named_frame.end(); | |
| 2740 | ||
| 2741 | assert(decl.has_tv); | |
| 2742 | ||
| 2743 | if (decl.alive) { | |
| 2744 | try module.linkerUpdateDecl(decl_index); | |
| 2745 | return; | |
| 2746 | } | |
| 2747 | ||
| 2748 | // Instead of sending this decl to the linker, we actually will delete it | |
| 2749 | // because we found out that it in fact was never referenced. | |
| 2750 | module.deleteUnusedDecl(decl_index); | |
| 2751 | return; | |
| 2752 | }, | |
| 2753 | } | |
| 2743 | 2754 | }, |
| 2744 | 2755 | .codegen_func => |func| { |
| 2745 | 2756 | if (build_options.omit_stage2) |
| ... | ... | @@ -2754,68 +2765,73 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 2754 | 2765 | error.AnalysisFail => return, |
| 2755 | 2766 | }; |
| 2756 | 2767 | }, |
| 2757 | .emit_h_decl => |decl| switch (decl.analysis) { | |
| 2758 | .unreferenced => unreachable, | |
| 2759 | .in_progress => unreachable, | |
| 2760 | .outdated => unreachable, | |
| 2761 | ||
| 2762 | .file_failure, | |
| 2763 | .sema_failure, | |
| 2764 | .dependency_failure, | |
| 2765 | .sema_failure_retryable, | |
| 2766 | => return, | |
| 2767 | ||
| 2768 | // emit-h only requires semantic analysis of the Decl to be complete, | |
| 2769 | // it does not depend on machine code generation to succeed. | |
| 2770 | .codegen_failure, .codegen_failure_retryable, .complete => { | |
| 2771 | if (build_options.omit_stage2) | |
| 2772 | @panic("sadly stage2 is omitted from this build to save memory on the CI server"); | |
| 2773 | ||
| 2774 | const named_frame = tracy.namedFrame("emit_h_decl"); | |
| 2775 | defer named_frame.end(); | |
| 2776 | ||
| 2777 | const gpa = comp.gpa; | |
| 2778 | const module = comp.bin_file.options.module.?; | |
| 2779 | const emit_h = module.emit_h.?; | |
| 2780 | _ = try emit_h.decl_table.getOrPut(gpa, decl); | |
| 2781 | const decl_emit_h = decl.getEmitH(module); | |
| 2782 | const fwd_decl = &decl_emit_h.fwd_decl; | |
| 2783 | fwd_decl.shrinkRetainingCapacity(0); | |
| 2784 | var typedefs_arena = std.heap.ArenaAllocator.init(gpa); | |
| 2785 | defer typedefs_arena.deinit(); | |
| 2786 | ||
| 2787 | var dg: c_codegen.DeclGen = .{ | |
| 2788 | .gpa = gpa, | |
| 2789 | .module = module, | |
| 2790 | .error_msg = null, | |
| 2791 | .decl = decl, | |
| 2792 | .fwd_decl = fwd_decl.toManaged(gpa), | |
| 2793 | .typedefs = c_codegen.TypedefMap.initContext(gpa, .{ | |
| 2794 | .target = comp.getTarget(), | |
| 2795 | }), | |
| 2796 | .typedefs_arena = typedefs_arena.allocator(), | |
| 2797 | }; | |
| 2798 | defer dg.fwd_decl.deinit(); | |
| 2799 | defer dg.typedefs.deinit(); | |
| 2768 | .emit_h_decl => |decl_index| { | |
| 2769 | if (build_options.omit_stage2) | |
| 2770 | @panic("sadly stage2 is omitted from this build to save memory on the CI server"); | |
| 2800 | 2771 | |
| 2801 | c_codegen.genHeader(&dg) catch |err| switch (err) { | |
| 2802 | error.AnalysisFail => { | |
| 2803 | try emit_h.failed_decls.put(gpa, decl, dg.error_msg.?); | |
| 2804 | return; | |
| 2805 | }, | |
| 2806 | else => |e| return e, | |
| 2807 | }; | |
| 2772 | const module = comp.bin_file.options.module.?; | |
| 2773 | const decl = module.declPtr(decl_index); | |
| 2774 | ||
| 2775 | switch (decl.analysis) { | |
| 2776 | .unreferenced => unreachable, | |
| 2777 | .in_progress => unreachable, | |
| 2778 | .outdated => unreachable, | |
| 2779 | ||
| 2780 | .file_failure, | |
| 2781 | .sema_failure, | |
| 2782 | .dependency_failure, | |
| 2783 | .sema_failure_retryable, | |
| 2784 | => return, | |
| 2785 | ||
| 2786 | // emit-h only requires semantic analysis of the Decl to be complete, | |
| 2787 | // it does not depend on machine code generation to succeed. | |
| 2788 | .codegen_failure, .codegen_failure_retryable, .complete => { | |
| 2789 | const named_frame = tracy.namedFrame("emit_h_decl"); | |
| 2790 | defer named_frame.end(); | |
| 2791 | ||
| 2792 | const gpa = comp.gpa; | |
| 2793 | const emit_h = module.emit_h.?; | |
| 2794 | _ = try emit_h.decl_table.getOrPut(gpa, decl_index); | |
| 2795 | const decl_emit_h = emit_h.declPtr(decl_index); | |
| 2796 | const fwd_decl = &decl_emit_h.fwd_decl; | |
| 2797 | fwd_decl.shrinkRetainingCapacity(0); | |
| 2798 | var typedefs_arena = std.heap.ArenaAllocator.init(gpa); | |
| 2799 | defer typedefs_arena.deinit(); | |
| 2800 | ||
| 2801 | var dg: c_codegen.DeclGen = .{ | |
| 2802 | .gpa = gpa, | |
| 2803 | .module = module, | |
| 2804 | .error_msg = null, | |
| 2805 | .decl_index = decl_index, | |
| 2806 | .decl = decl, | |
| 2807 | .fwd_decl = fwd_decl.toManaged(gpa), | |
| 2808 | .typedefs = c_codegen.TypedefMap.initContext(gpa, .{ | |
| 2809 | .mod = module, | |
| 2810 | }), | |
| 2811 | .typedefs_arena = typedefs_arena.allocator(), | |
| 2812 | }; | |
| 2813 | defer dg.fwd_decl.deinit(); | |
| 2814 | defer dg.typedefs.deinit(); | |
| 2808 | 2815 | |
| 2809 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); | |
| 2810 | fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len); | |
| 2811 | }, | |
| 2816 | c_codegen.genHeader(&dg) catch |err| switch (err) { | |
| 2817 | error.AnalysisFail => { | |
| 2818 | try emit_h.failed_decls.put(gpa, decl_index, dg.error_msg.?); | |
| 2819 | return; | |
| 2820 | }, | |
| 2821 | else => |e| return e, | |
| 2822 | }; | |
| 2823 | ||
| 2824 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); | |
| 2825 | fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len); | |
| 2826 | }, | |
| 2827 | } | |
| 2812 | 2828 | }, |
| 2813 | .analyze_decl => |decl| { | |
| 2829 | .analyze_decl => |decl_index| { | |
| 2814 | 2830 | if (build_options.omit_stage2) |
| 2815 | 2831 | @panic("sadly stage2 is omitted from this build to save memory on the CI server"); |
| 2816 | 2832 | |
| 2817 | 2833 | const module = comp.bin_file.options.module.?; |
| 2818 | module.ensureDeclAnalyzed(decl) catch |err| switch (err) { | |
| 2834 | module.ensureDeclAnalyzed(decl_index) catch |err| switch (err) { | |
| 2819 | 2835 | error.OutOfMemory => return error.OutOfMemory, |
| 2820 | 2836 | error.AnalysisFail => return, |
| 2821 | 2837 | }; |
| ... | ... | @@ -2833,7 +2849,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 2833 | 2849 | error.AnalysisFail => return, |
| 2834 | 2850 | }; |
| 2835 | 2851 | }, |
| 2836 | .update_line_number => |decl| { | |
| 2852 | .update_line_number => |decl_index| { | |
| 2837 | 2853 | if (build_options.omit_stage2) |
| 2838 | 2854 | @panic("sadly stage2 is omitted from this build to save memory on the CI server"); |
| 2839 | 2855 | |
| ... | ... | @@ -2842,9 +2858,10 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 2842 | 2858 | |
| 2843 | 2859 | const gpa = comp.gpa; |
| 2844 | 2860 | const module = comp.bin_file.options.module.?; |
| 2861 | const decl = module.declPtr(decl_index); | |
| 2845 | 2862 | comp.bin_file.updateDeclLineNumber(module, decl) catch |err| { |
| 2846 | 2863 | try module.failed_decls.ensureUnusedCapacity(gpa, 1); |
| 2847 | module.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create( | |
| 2864 | module.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( | |
| 2848 | 2865 | gpa, |
| 2849 | 2866 | decl.srcLoc(), |
| 2850 | 2867 | "unable to update line number: {s}", |
| ... | ... | @@ -3472,7 +3489,7 @@ fn reportRetryableEmbedFileError( |
| 3472 | 3489 | const mod = comp.bin_file.options.module.?; |
| 3473 | 3490 | const gpa = mod.gpa; |
| 3474 | 3491 | |
| 3475 | const src_loc: Module.SrcLoc = embed_file.owner_decl.srcLoc(); | |
| 3492 | const src_loc: Module.SrcLoc = mod.declPtr(embed_file.owner_decl).srcLoc(); | |
| 3476 | 3493 | |
| 3477 | 3494 | const err_msg = if (embed_file.pkg.root_src_directory.path) |dir_path| |
| 3478 | 3495 | try Module.ErrorMsg.create( |
src/Module.zig+529-381| ... | ... | @@ -49,15 +49,15 @@ global_zir_cache: Compilation.Directory, |
| 49 | 49 | /// Used by AstGen worker to load and store ZIR cache. |
| 50 | 50 | local_zir_cache: Compilation.Directory, |
| 51 | 51 | /// It's rare for a decl to be exported, so we save memory by having a sparse |
| 52 | /// map of Decl pointers to details about them being exported. | |
| 52 | /// map of Decl indexes to details about them being exported. | |
| 53 | 53 | /// The Export memory is owned by the `export_owners` table; the slice itself |
| 54 | 54 | /// is owned by this table. The slice is guaranteed to not be empty. |
| 55 | decl_exports: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{}, | |
| 55 | decl_exports: std.AutoArrayHashMapUnmanaged(Decl.Index, []*Export) = .{}, | |
| 56 | 56 | /// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl |
| 57 | 57 | /// is modified. Note that the key of this table is not the Decl being exported, but the Decl that |
| 58 | 58 | /// is performing the export of another Decl. |
| 59 | 59 | /// This table owns the Export memory. |
| 60 | export_owners: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{}, | |
| 60 | export_owners: std.AutoArrayHashMapUnmanaged(Decl.Index, []*Export) = .{}, | |
| 61 | 61 | /// The set of all the Zig source files in the Module. We keep track of this in order |
| 62 | 62 | /// to iterate over it and check which source files have been modified on the file system when |
| 63 | 63 | /// an update is requested, as well as to cache `@import` results. |
| ... | ... | @@ -89,10 +89,10 @@ align_stack_fns: std.AutoHashMapUnmanaged(*const Fn, SetAlignStack) = .{}, |
| 89 | 89 | /// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator. |
| 90 | 90 | /// Note that a Decl can succeed but the Fn it represents can fail. In this case, |
| 91 | 91 | /// a Decl can have a failed_decls entry but have analysis status of success. |
| 92 | failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{}, | |
| 92 | failed_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, *ErrorMsg) = .{}, | |
| 93 | 93 | /// Keep track of one `@compileLog` callsite per owner Decl. |
| 94 | 94 | /// The value is the AST node index offset from the Decl. |
| 95 | compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, i32) = .{}, | |
| 95 | compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, i32) = .{}, | |
| 96 | 96 | /// Using a map here for consistency with the other fields here. |
| 97 | 97 | /// The ErrorMsg memory is owned by the `File`, using Module's general purpose allocator. |
| 98 | 98 | failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{}, |
| ... | ... | @@ -102,11 +102,9 @@ failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{}, |
| 102 | 102 | /// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator. |
| 103 | 103 | failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{}, |
| 104 | 104 | |
| 105 | next_anon_name_index: usize = 0, | |
| 106 | ||
| 107 | 105 | /// Candidates for deletion. After a semantic analysis update completes, this list |
| 108 | 106 | /// contains Decls that need to be deleted if they end up having no references to them. |
| 109 | deletion_set: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, | |
| 107 | deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | |
| 110 | 108 | |
| 111 | 109 | /// Error tags and their values, tag names are duped with mod.gpa. |
| 112 | 110 | /// Corresponds with `error_name_list`. |
| ... | ... | @@ -137,7 +135,21 @@ compile_log_text: ArrayListUnmanaged(u8) = .{}, |
| 137 | 135 | |
| 138 | 136 | emit_h: ?*GlobalEmitH, |
| 139 | 137 | |
| 140 | test_functions: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, | |
| 138 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | |
| 139 | ||
| 140 | /// Rather than allocating Decl objects with an Allocator, we instead allocate | |
| 141 | /// them with this SegmentedList. This provides four advantages: | |
| 142 | /// * Stable memory so that one thread can access a Decl object while another | |
| 143 | /// thread allocates additional Decl objects from this list. | |
| 144 | /// * It allows us to use u32 indexes to reference Decl objects rather than | |
| 145 | /// pointers, saving memory in Type, Value, and dependency sets. | |
| 146 | /// * Using integers to reference Decl objects rather than pointers makes | |
| 147 | /// serialization trivial. | |
| 148 | /// * It provides a unique integer to be used for anonymous symbol names, avoiding | |
| 149 | /// multi-threaded contention on an atomic counter. | |
| 150 | allocated_decls: std.SegmentedList(Decl, 0) = .{}, | |
| 151 | /// When a Decl object is freed from `allocated_decls`, it is pushed into this stack. | |
| 152 | decls_free_list: std.ArrayListUnmanaged(Decl.Index) = .{}, | |
| 141 | 153 | |
| 142 | 154 | const MonomorphedFuncsSet = std.HashMapUnmanaged( |
| 143 | 155 | *Fn, |
| ... | ... | @@ -173,7 +185,7 @@ pub const MemoizedCallSet = std.HashMapUnmanaged( |
| 173 | 185 | ); |
| 174 | 186 | |
| 175 | 187 | pub const MemoizedCall = struct { |
| 176 | target: std.Target, | |
| 188 | module: *Module, | |
| 177 | 189 | |
| 178 | 190 | pub const Key = struct { |
| 179 | 191 | func: *Fn, |
| ... | ... | @@ -191,7 +203,7 @@ pub const MemoizedCall = struct { |
| 191 | 203 | assert(a.args.len == b.args.len); |
| 192 | 204 | for (a.args) |a_arg, arg_i| { |
| 193 | 205 | const b_arg = b.args[arg_i]; |
| 194 | if (!a_arg.eql(b_arg, ctx.target)) { | |
| 206 | if (!a_arg.eql(b_arg, ctx.module)) { | |
| 195 | 207 | return false; |
| 196 | 208 | } |
| 197 | 209 | } |
| ... | ... | @@ -210,7 +222,7 @@ pub const MemoizedCall = struct { |
| 210 | 222 | // This logic must be kept in sync with the logic in `analyzeCall` that |
| 211 | 223 | // computes the hash. |
| 212 | 224 | for (key.args) |arg| { |
| 213 | arg.hash(&hasher, ctx.target); | |
| 225 | arg.hash(&hasher, ctx.module); | |
| 214 | 226 | } |
| 215 | 227 | |
| 216 | 228 | return hasher.final(); |
| ... | ... | @@ -231,9 +243,17 @@ pub const GlobalEmitH = struct { |
| 231 | 243 | /// When emit_h is non-null, each Decl gets one more compile error slot for |
| 232 | 244 | /// emit-h failing for that Decl. This table is also how we tell if a Decl has |
| 233 | 245 | /// failed emit-h or succeeded. |
| 234 | failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{}, | |
| 246 | failed_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, *ErrorMsg) = .{}, | |
| 235 | 247 | /// Tracks all decls in order to iterate over them and emit .h code for them. |
| 236 | decl_table: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, | |
| 248 | decl_table: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | |
| 249 | /// Similar to the allocated_decls field of Module, this is where `EmitH` objects | |
| 250 | /// are allocated. There will be exactly one EmitH object per Decl object, with | |
| 251 | /// identical indexes. | |
| 252 | allocated_emit_h: std.SegmentedList(EmitH, 0) = .{}, | |
| 253 | ||
| 254 | pub fn declPtr(global_emit_h: *GlobalEmitH, decl_index: Decl.Index) *EmitH { | |
| 255 | return global_emit_h.allocated_emit_h.at(@enumToInt(decl_index)); | |
| 256 | } | |
| 237 | 257 | }; |
| 238 | 258 | |
| 239 | 259 | pub const ErrorInt = u32; |
| ... | ... | @@ -244,12 +264,12 @@ pub const Export = struct { |
| 244 | 264 | /// Represents the position of the export, if any, in the output file. |
| 245 | 265 | link: link.File.Export, |
| 246 | 266 | /// The Decl that performs the export. Note that this is *not* the Decl being exported. |
| 247 | owner_decl: *Decl, | |
| 267 | owner_decl: Decl.Index, | |
| 248 | 268 | /// The Decl containing the export statement. Inline function calls |
| 249 | 269 | /// may cause this to be different from the owner_decl. |
| 250 | src_decl: *Decl, | |
| 270 | src_decl: Decl.Index, | |
| 251 | 271 | /// The Decl being exported. Note this is *not* the Decl performing the export. |
| 252 | exported_decl: *Decl, | |
| 272 | exported_decl: Decl.Index, | |
| 253 | 273 | status: enum { |
| 254 | 274 | in_progress, |
| 255 | 275 | failed, |
| ... | ... | @@ -259,22 +279,16 @@ pub const Export = struct { |
| 259 | 279 | complete, |
| 260 | 280 | }, |
| 261 | 281 | |
| 262 | pub fn getSrcLoc(exp: Export) SrcLoc { | |
| 282 | pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc { | |
| 283 | const src_decl = mod.declPtr(exp.src_decl); | |
| 263 | 284 | return .{ |
| 264 | .file_scope = exp.src_decl.getFileScope(), | |
| 265 | .parent_decl_node = exp.src_decl.src_node, | |
| 285 | .file_scope = src_decl.getFileScope(), | |
| 286 | .parent_decl_node = src_decl.src_node, | |
| 266 | 287 | .lazy = exp.src, |
| 267 | 288 | }; |
| 268 | 289 | } |
| 269 | 290 | }; |
| 270 | 291 | |
| 271 | /// When Module emit_h field is non-null, each Decl is allocated via this struct, so that | |
| 272 | /// there can be EmitH state attached to each Decl. | |
| 273 | pub const DeclPlusEmitH = struct { | |
| 274 | decl: Decl, | |
| 275 | emit_h: EmitH, | |
| 276 | }; | |
| 277 | ||
| 278 | 292 | pub const CaptureScope = struct { |
| 279 | 293 | parent: ?*CaptureScope, |
| 280 | 294 | |
| ... | ... | @@ -458,36 +472,33 @@ pub const Decl = struct { |
| 458 | 472 | /// typed_value may need to be regenerated. |
| 459 | 473 | dependencies: DepsTable = .{}, |
| 460 | 474 | |
| 461 | pub const DepsTable = std.AutoArrayHashMapUnmanaged(*Decl, void); | |
| 462 | ||
| 463 | pub fn clearName(decl: *Decl, gpa: Allocator) void { | |
| 464 | gpa.free(mem.sliceTo(decl.name, 0)); | |
| 465 | decl.name = undefined; | |
| 466 | } | |
| 475 | pub const Index = enum(u32) { | |
| 476 | _, | |
| 467 | 477 | |
| 468 | pub fn destroy(decl: *Decl, module: *Module) void { | |
| 469 | const gpa = module.gpa; | |
| 470 | log.debug("destroy {*} ({s})", .{ decl, decl.name }); | |
| 471 | _ = module.test_functions.swapRemove(decl); | |
| 472 | if (decl.deletion_flag) { | |
| 473 | assert(module.deletion_set.swapRemove(decl)); | |
| 478 | pub fn toOptional(i: Index) OptionalIndex { | |
| 479 | return @intToEnum(OptionalIndex, @enumToInt(i)); | |
| 474 | 480 | } |
| 475 | if (decl.has_tv) { | |
| 476 | if (decl.getInnerNamespace()) |namespace| { | |
| 477 | namespace.destroyDecls(module); | |
| 478 | } | |
| 479 | decl.clearValues(gpa); | |
| 481 | }; | |
| 482 | ||
| 483 | pub const OptionalIndex = enum(u32) { | |
| 484 | none = std.math.maxInt(u32), | |
| 485 | _, | |
| 486 | ||
| 487 | pub fn init(oi: ?Index) OptionalIndex { | |
| 488 | return oi orelse .none; | |
| 480 | 489 | } |
| 481 | decl.dependants.deinit(gpa); | |
| 482 | decl.dependencies.deinit(gpa); | |
| 483 | decl.clearName(gpa); | |
| 484 | if (module.emit_h != null) { | |
| 485 | const decl_plus_emit_h = @fieldParentPtr(DeclPlusEmitH, "decl", decl); | |
| 486 | decl_plus_emit_h.emit_h.fwd_decl.deinit(gpa); | |
| 487 | gpa.destroy(decl_plus_emit_h); | |
| 488 | } else { | |
| 489 | gpa.destroy(decl); | |
| 490 | ||
| 491 | pub fn unwrap(oi: OptionalIndex) ?Index { | |
| 492 | if (oi == .none) return null; | |
| 493 | return @intToEnum(Index, @enumToInt(oi)); | |
| 490 | 494 | } |
| 495 | }; | |
| 496 | ||
| 497 | pub const DepsTable = std.AutoArrayHashMapUnmanaged(Decl.Index, void); | |
| 498 | ||
| 499 | pub fn clearName(decl: *Decl, gpa: Allocator) void { | |
| 500 | gpa.free(mem.sliceTo(decl.name, 0)); | |
| 501 | decl.name = undefined; | |
| 491 | 502 | } |
| 492 | 503 | |
| 493 | 504 | pub fn clearValues(decl: *Decl, gpa: Allocator) void { |
| ... | ... | @@ -573,13 +584,6 @@ pub const Decl = struct { |
| 573 | 584 | return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); |
| 574 | 585 | } |
| 575 | 586 | |
| 576 | /// Returns true if and only if the Decl is the top level struct associated with a File. | |
| 577 | pub fn isRoot(decl: *const Decl) bool { | |
| 578 | if (decl.src_namespace.parent != null) | |
| 579 | return false; | |
| 580 | return decl == decl.src_namespace.getDecl(); | |
| 581 | } | |
| 582 | ||
| 583 | 587 | pub fn relativeToLine(decl: Decl, offset: u32) u32 { |
| 584 | 588 | return decl.src_line + offset; |
| 585 | 589 | } |
| ... | ... | @@ -622,20 +626,20 @@ pub const Decl = struct { |
| 622 | 626 | return tree.tokens.items(.start)[decl.srcToken()]; |
| 623 | 627 | } |
| 624 | 628 | |
| 625 | pub fn renderFullyQualifiedName(decl: Decl, writer: anytype) !void { | |
| 629 | pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void { | |
| 626 | 630 | const unqualified_name = mem.sliceTo(decl.name, 0); |
| 627 | return decl.src_namespace.renderFullyQualifiedName(unqualified_name, writer); | |
| 631 | return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer); | |
| 628 | 632 | } |
| 629 | 633 | |
| 630 | pub fn renderFullyQualifiedDebugName(decl: Decl, writer: anytype) !void { | |
| 634 | pub fn renderFullyQualifiedDebugName(decl: Decl, mod: *Module, writer: anytype) !void { | |
| 631 | 635 | const unqualified_name = mem.sliceTo(decl.name, 0); |
| 632 | return decl.src_namespace.renderFullyQualifiedDebugName(unqualified_name, writer); | |
| 636 | return decl.src_namespace.renderFullyQualifiedDebugName(mod, unqualified_name, writer); | |
| 633 | 637 | } |
| 634 | 638 | |
| 635 | pub fn getFullyQualifiedName(decl: Decl, gpa: Allocator) ![:0]u8 { | |
| 636 | var buffer = std.ArrayList(u8).init(gpa); | |
| 639 | pub fn getFullyQualifiedName(decl: Decl, mod: *Module) ![:0]u8 { | |
| 640 | var buffer = std.ArrayList(u8).init(mod.gpa); | |
| 637 | 641 | defer buffer.deinit(); |
| 638 | try decl.renderFullyQualifiedName(buffer.writer()); | |
| 642 | try decl.renderFullyQualifiedName(mod, buffer.writer()); | |
| 639 | 643 | return buffer.toOwnedSliceSentinel(0); |
| 640 | 644 | } |
| 641 | 645 | |
| ... | ... | @@ -662,7 +666,6 @@ pub const Decl = struct { |
| 662 | 666 | if (!decl.owns_tv) return null; |
| 663 | 667 | const ty = (decl.val.castTag(.ty) orelse return null).data; |
| 664 | 668 | const struct_obj = (ty.castTag(.@"struct") orelse return null).data; |
| 665 | assert(struct_obj.owner_decl == decl); | |
| 666 | 669 | return struct_obj; |
| 667 | 670 | } |
| 668 | 671 | |
| ... | ... | @@ -672,7 +675,6 @@ pub const Decl = struct { |
| 672 | 675 | if (!decl.owns_tv) return null; |
| 673 | 676 | const ty = (decl.val.castTag(.ty) orelse return null).data; |
| 674 | 677 | const union_obj = (ty.cast(Type.Payload.Union) orelse return null).data; |
| 675 | assert(union_obj.owner_decl == decl); | |
| 676 | 678 | return union_obj; |
| 677 | 679 | } |
| 678 | 680 | |
| ... | ... | @@ -681,7 +683,6 @@ pub const Decl = struct { |
| 681 | 683 | pub fn getFunction(decl: *const Decl) ?*Fn { |
| 682 | 684 | if (!decl.owns_tv) return null; |
| 683 | 685 | const func = (decl.val.castTag(.function) orelse return null).data; |
| 684 | assert(func.owner_decl == decl); | |
| 685 | 686 | return func; |
| 686 | 687 | } |
| 687 | 688 | |
| ... | ... | @@ -690,16 +691,14 @@ pub const Decl = struct { |
| 690 | 691 | pub fn getExternFn(decl: *const Decl) ?*ExternFn { |
| 691 | 692 | if (!decl.owns_tv) return null; |
| 692 | 693 | const extern_fn = (decl.val.castTag(.extern_fn) orelse return null).data; |
| 693 | assert(extern_fn.owner_decl == decl); | |
| 694 | 694 | return extern_fn; |
| 695 | 695 | } |
| 696 | 696 | |
| 697 | 697 | /// If the Decl has a value and it is a variable, returns it, |
| 698 | 698 | /// otherwise null. |
| 699 | pub fn getVariable(decl: *Decl) ?*Var { | |
| 699 | pub fn getVariable(decl: *const Decl) ?*Var { | |
| 700 | 700 | if (!decl.owns_tv) return null; |
| 701 | 701 | const variable = (decl.val.castTag(.variable) orelse return null).data; |
| 702 | assert(variable.owner_decl == decl); | |
| 703 | 702 | return variable; |
| 704 | 703 | } |
| 705 | 704 | |
| ... | ... | @@ -712,12 +711,10 @@ pub const Decl = struct { |
| 712 | 711 | switch (ty.tag()) { |
| 713 | 712 | .@"struct" => { |
| 714 | 713 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 715 | assert(struct_obj.owner_decl == decl); | |
| 716 | 714 | return &struct_obj.namespace; |
| 717 | 715 | }, |
| 718 | 716 | .enum_full, .enum_nonexhaustive => { |
| 719 | 717 | const enum_obj = ty.cast(Type.Payload.EnumFull).?.data; |
| 720 | assert(enum_obj.owner_decl == decl); | |
| 721 | 718 | return &enum_obj.namespace; |
| 722 | 719 | }, |
| 723 | 720 | .empty_struct => { |
| ... | ... | @@ -725,12 +722,10 @@ pub const Decl = struct { |
| 725 | 722 | }, |
| 726 | 723 | .@"opaque" => { |
| 727 | 724 | const opaque_obj = ty.cast(Type.Payload.Opaque).?.data; |
| 728 | assert(opaque_obj.owner_decl == decl); | |
| 729 | 725 | return &opaque_obj.namespace; |
| 730 | 726 | }, |
| 731 | 727 | .@"union", .union_tagged => { |
| 732 | 728 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 733 | assert(union_obj.owner_decl == decl); | |
| 734 | 729 | return &union_obj.namespace; |
| 735 | 730 | }, |
| 736 | 731 | |
| ... | ... | @@ -757,17 +752,11 @@ pub const Decl = struct { |
| 757 | 752 | return decl.src_namespace.file_scope; |
| 758 | 753 | } |
| 759 | 754 | |
| 760 | pub fn getEmitH(decl: *Decl, module: *Module) *EmitH { | |
| 761 | assert(module.emit_h != null); | |
| 762 | const decl_plus_emit_h = @fieldParentPtr(DeclPlusEmitH, "decl", decl); | |
| 763 | return &decl_plus_emit_h.emit_h; | |
| 764 | } | |
| 765 | ||
| 766 | pub fn removeDependant(decl: *Decl, other: *Decl) void { | |
| 755 | pub fn removeDependant(decl: *Decl, other: Decl.Index) void { | |
| 767 | 756 | assert(decl.dependants.swapRemove(other)); |
| 768 | 757 | } |
| 769 | 758 | |
| 770 | pub fn removeDependency(decl: *Decl, other: *Decl) void { | |
| 759 | pub fn removeDependency(decl: *Decl, other: Decl.Index) void { | |
| 771 | 760 | assert(decl.dependencies.swapRemove(other)); |
| 772 | 761 | } |
| 773 | 762 | |
| ... | ... | @@ -790,16 +779,6 @@ pub const Decl = struct { |
| 790 | 779 | return decl.ty.abiAlignment(target); |
| 791 | 780 | } |
| 792 | 781 | } |
| 793 | ||
| 794 | pub fn markAlive(decl: *Decl) void { | |
| 795 | if (decl.alive) return; | |
| 796 | decl.alive = true; | |
| 797 | ||
| 798 | // This is the first time we are marking this Decl alive. We must | |
| 799 | // therefore recurse into its value and mark any Decl it references | |
| 800 | // as also alive, so that any Decl referenced does not get garbage collected. | |
| 801 | decl.val.markReferencedDeclsAlive(); | |
| 802 | } | |
| 803 | 782 | }; |
| 804 | 783 | |
| 805 | 784 | /// This state is attached to every Decl when Module emit_h is non-null. |
| ... | ... | @@ -810,7 +789,7 @@ pub const EmitH = struct { |
| 810 | 789 | /// Represents the data that an explicit error set syntax provides. |
| 811 | 790 | pub const ErrorSet = struct { |
| 812 | 791 | /// The Decl that corresponds to the error set itself. |
| 813 | owner_decl: *Decl, | |
| 792 | owner_decl: Decl.Index, | |
| 814 | 793 | /// Offset from Decl node index, points to the error set AST node. |
| 815 | 794 | node_offset: i32, |
| 816 | 795 | /// The string bytes are stored in the owner Decl arena. |
| ... | ... | @@ -819,10 +798,11 @@ pub const ErrorSet = struct { |
| 819 | 798 | |
| 820 | 799 | pub const NameMap = std.StringArrayHashMapUnmanaged(void); |
| 821 | 800 | |
| 822 | pub fn srcLoc(self: ErrorSet) SrcLoc { | |
| 801 | pub fn srcLoc(self: ErrorSet, mod: *Module) SrcLoc { | |
| 802 | const owner_decl = mod.declPtr(self.owner_decl); | |
| 823 | 803 | return .{ |
| 824 | .file_scope = self.owner_decl.getFileScope(), | |
| 825 | .parent_decl_node = self.owner_decl.src_node, | |
| 804 | .file_scope = owner_decl.getFileScope(), | |
| 805 | .parent_decl_node = owner_decl.src_node, | |
| 826 | 806 | .lazy = .{ .node_offset = self.node_offset }, |
| 827 | 807 | }; |
| 828 | 808 | } |
| ... | ... | @@ -844,12 +824,12 @@ pub const PropertyBoolean = enum { no, yes, unknown, wip }; |
| 844 | 824 | |
| 845 | 825 | /// Represents the data that a struct declaration provides. |
| 846 | 826 | pub const Struct = struct { |
| 847 | /// The Decl that corresponds to the struct itself. | |
| 848 | owner_decl: *Decl, | |
| 849 | 827 | /// Set of field names in declaration order. |
| 850 | 828 | fields: Fields, |
| 851 | 829 | /// Represents the declarations inside this struct. |
| 852 | 830 | namespace: Namespace, |
| 831 | /// The Decl that corresponds to the struct itself. | |
| 832 | owner_decl: Decl.Index, | |
| 853 | 833 | /// Offset from `owner_decl`, points to the struct AST node. |
| 854 | 834 | node_offset: i32, |
| 855 | 835 | /// Index of the struct_decl ZIR instruction. |
| ... | ... | @@ -900,30 +880,32 @@ pub const Struct = struct { |
| 900 | 880 | } |
| 901 | 881 | }; |
| 902 | 882 | |
| 903 | pub fn getFullyQualifiedName(s: *Struct, gpa: Allocator) ![:0]u8 { | |
| 904 | return s.owner_decl.getFullyQualifiedName(gpa); | |
| 883 | pub fn getFullyQualifiedName(s: *Struct, mod: *Module) ![:0]u8 { | |
| 884 | return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod); | |
| 905 | 885 | } |
| 906 | 886 | |
| 907 | pub fn srcLoc(s: Struct) SrcLoc { | |
| 887 | pub fn srcLoc(s: Struct, mod: *Module) SrcLoc { | |
| 888 | const owner_decl = mod.declPtr(s.owner_decl); | |
| 908 | 889 | return .{ |
| 909 | .file_scope = s.owner_decl.getFileScope(), | |
| 910 | .parent_decl_node = s.owner_decl.src_node, | |
| 890 | .file_scope = owner_decl.getFileScope(), | |
| 891 | .parent_decl_node = owner_decl.src_node, | |
| 911 | 892 | .lazy = .{ .node_offset = s.node_offset }, |
| 912 | 893 | }; |
| 913 | 894 | } |
| 914 | 895 | |
| 915 | pub fn fieldSrcLoc(s: Struct, gpa: Allocator, query: FieldSrcQuery) SrcLoc { | |
| 896 | pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc { | |
| 916 | 897 | @setCold(true); |
| 917 | const tree = s.owner_decl.getFileScope().getTree(gpa) catch |err| { | |
| 898 | const owner_decl = mod.declPtr(s.owner_decl); | |
| 899 | const file = owner_decl.getFileScope(); | |
| 900 | const tree = file.getTree(mod.gpa) catch |err| { | |
| 918 | 901 | // In this case we emit a warning + a less precise source location. |
| 919 | 902 | log.warn("unable to load {s}: {s}", .{ |
| 920 | s.owner_decl.getFileScope().sub_file_path, @errorName(err), | |
| 903 | file.sub_file_path, @errorName(err), | |
| 921 | 904 | }); |
| 922 | return s.srcLoc(); | |
| 905 | return s.srcLoc(mod); | |
| 923 | 906 | }; |
| 924 | const node = s.owner_decl.relativeToNodeIndex(s.node_offset); | |
| 907 | const node = owner_decl.relativeToNodeIndex(s.node_offset); | |
| 925 | 908 | const node_tags = tree.nodes.items(.tag); |
| 926 | const file = s.owner_decl.getFileScope(); | |
| 927 | 909 | switch (node_tags[node]) { |
| 928 | 910 | .container_decl, |
| 929 | 911 | .container_decl_trailing, |
| ... | ... | @@ -1013,18 +995,19 @@ pub const Struct = struct { |
| 1013 | 995 | /// the number of fields. |
| 1014 | 996 | pub const EnumSimple = struct { |
| 1015 | 997 | /// The Decl that corresponds to the enum itself. |
| 1016 | owner_decl: *Decl, | |
| 1017 | /// Set of field names in declaration order. | |
| 1018 | fields: NameMap, | |
| 998 | owner_decl: Decl.Index, | |
| 1019 | 999 | /// Offset from `owner_decl`, points to the enum decl AST node. |
| 1020 | 1000 | node_offset: i32, |
| 1001 | /// Set of field names in declaration order. | |
| 1002 | fields: NameMap, | |
| 1021 | 1003 | |
| 1022 | 1004 | pub const NameMap = EnumFull.NameMap; |
| 1023 | 1005 | |
| 1024 | pub fn srcLoc(self: EnumSimple) SrcLoc { | |
| 1006 | pub fn srcLoc(self: EnumSimple, mod: *Module) SrcLoc { | |
| 1007 | const owner_decl = mod.declPtr(self.owner_decl); | |
| 1025 | 1008 | return .{ |
| 1026 | .file_scope = self.owner_decl.getFileScope(), | |
| 1027 | .parent_decl_node = self.owner_decl.src_node, | |
| 1009 | .file_scope = owner_decl.getFileScope(), | |
| 1010 | .parent_decl_node = owner_decl.src_node, | |
| 1028 | 1011 | .lazy = .{ .node_offset = self.node_offset }, |
| 1029 | 1012 | }; |
| 1030 | 1013 | } |
| ... | ... | @@ -1035,7 +1018,9 @@ pub const EnumSimple = struct { |
| 1035 | 1018 | /// are explicitly provided. |
| 1036 | 1019 | pub const EnumNumbered = struct { |
| 1037 | 1020 | /// The Decl that corresponds to the enum itself. |
| 1038 | owner_decl: *Decl, | |
| 1021 | owner_decl: Decl.Index, | |
| 1022 | /// Offset from `owner_decl`, points to the enum decl AST node. | |
| 1023 | node_offset: i32, | |
| 1039 | 1024 | /// An integer type which is used for the numerical value of the enum. |
| 1040 | 1025 | /// Whether zig chooses this type or the user specifies it, it is stored here. |
| 1041 | 1026 | tag_ty: Type, |
| ... | ... | @@ -1045,16 +1030,15 @@ pub const EnumNumbered = struct { |
| 1045 | 1030 | /// Entries are in declaration order, same as `fields`. |
| 1046 | 1031 | /// If this hash map is empty, it means the enum tags are auto-numbered. |
| 1047 | 1032 | values: ValueMap, |
| 1048 | /// Offset from `owner_decl`, points to the enum decl AST node. | |
| 1049 | node_offset: i32, | |
| 1050 | 1033 | |
| 1051 | 1034 | pub const NameMap = EnumFull.NameMap; |
| 1052 | 1035 | pub const ValueMap = EnumFull.ValueMap; |
| 1053 | 1036 | |
| 1054 | pub fn srcLoc(self: EnumNumbered) SrcLoc { | |
| 1037 | pub fn srcLoc(self: EnumNumbered, mod: *Module) SrcLoc { | |
| 1038 | const owner_decl = mod.declPtr(self.owner_decl); | |
| 1055 | 1039 | return .{ |
| 1056 | .file_scope = self.owner_decl.getFileScope(), | |
| 1057 | .parent_decl_node = self.owner_decl.src_node, | |
| 1040 | .file_scope = owner_decl.getFileScope(), | |
| 1041 | .parent_decl_node = owner_decl.src_node, | |
| 1058 | 1042 | .lazy = .{ .node_offset = self.node_offset }, |
| 1059 | 1043 | }; |
| 1060 | 1044 | } |
| ... | ... | @@ -1064,7 +1048,9 @@ pub const EnumNumbered = struct { |
| 1064 | 1048 | /// at least one tag value explicitly specified, or at least one declaration. |
| 1065 | 1049 | pub const EnumFull = struct { |
| 1066 | 1050 | /// The Decl that corresponds to the enum itself. |
| 1067 | owner_decl: *Decl, | |
| 1051 | owner_decl: Decl.Index, | |
| 1052 | /// Offset from `owner_decl`, points to the enum decl AST node. | |
| 1053 | node_offset: i32, | |
| 1068 | 1054 | /// An integer type which is used for the numerical value of the enum. |
| 1069 | 1055 | /// Whether zig chooses this type or the user specifies it, it is stored here. |
| 1070 | 1056 | tag_ty: Type, |
| ... | ... | @@ -1076,26 +1062,23 @@ pub const EnumFull = struct { |
| 1076 | 1062 | values: ValueMap, |
| 1077 | 1063 | /// Represents the declarations inside this enum. |
| 1078 | 1064 | namespace: Namespace, |
| 1079 | /// Offset from `owner_decl`, points to the enum decl AST node. | |
| 1080 | node_offset: i32, | |
| 1081 | 1065 | /// true if zig inferred this tag type, false if user specified it |
| 1082 | 1066 | tag_ty_inferred: bool, |
| 1083 | 1067 | |
| 1084 | 1068 | pub const NameMap = std.StringArrayHashMapUnmanaged(void); |
| 1085 | 1069 | pub const ValueMap = std.ArrayHashMapUnmanaged(Value, void, Value.ArrayHashContext, false); |
| 1086 | 1070 | |
| 1087 | pub fn srcLoc(self: EnumFull) SrcLoc { | |
| 1071 | pub fn srcLoc(self: EnumFull, mod: *Module) SrcLoc { | |
| 1072 | const owner_decl = mod.declPtr(self.owner_decl); | |
| 1088 | 1073 | return .{ |
| 1089 | .file_scope = self.owner_decl.getFileScope(), | |
| 1090 | .parent_decl_node = self.owner_decl.src_node, | |
| 1074 | .file_scope = owner_decl.getFileScope(), | |
| 1075 | .parent_decl_node = owner_decl.src_node, | |
| 1091 | 1076 | .lazy = .{ .node_offset = self.node_offset }, |
| 1092 | 1077 | }; |
| 1093 | 1078 | } |
| 1094 | 1079 | }; |
| 1095 | 1080 | |
| 1096 | 1081 | pub const Union = struct { |
| 1097 | /// The Decl that corresponds to the union itself. | |
| 1098 | owner_decl: *Decl, | |
| 1099 | 1082 | /// An enum type which is used for the tag of the union. |
| 1100 | 1083 | /// This type is created even for untagged unions, even when the memory |
| 1101 | 1084 | /// layout does not store the tag. |
| ... | ... | @@ -1106,6 +1089,8 @@ pub const Union = struct { |
| 1106 | 1089 | fields: Fields, |
| 1107 | 1090 | /// Represents the declarations inside this union. |
| 1108 | 1091 | namespace: Namespace, |
| 1092 | /// The Decl that corresponds to the union itself. | |
| 1093 | owner_decl: Decl.Index, | |
| 1109 | 1094 | /// Offset from `owner_decl`, points to the union decl AST node. |
| 1110 | 1095 | node_offset: i32, |
| 1111 | 1096 | /// Index of the union_decl ZIR instruction. |
| ... | ... | @@ -1145,30 +1130,32 @@ pub const Union = struct { |
| 1145 | 1130 | |
| 1146 | 1131 | pub const Fields = std.StringArrayHashMapUnmanaged(Field); |
| 1147 | 1132 | |
| 1148 | pub fn getFullyQualifiedName(s: *Union, gpa: Allocator) ![:0]u8 { | |
| 1149 | return s.owner_decl.getFullyQualifiedName(gpa); | |
| 1133 | pub fn getFullyQualifiedName(s: *Union, mod: *Module) ![:0]u8 { | |
| 1134 | return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod); | |
| 1150 | 1135 | } |
| 1151 | 1136 | |
| 1152 | pub fn srcLoc(self: Union) SrcLoc { | |
| 1137 | pub fn srcLoc(self: Union, mod: *Module) SrcLoc { | |
| 1138 | const owner_decl = mod.declPtr(self.owner_decl); | |
| 1153 | 1139 | return .{ |
| 1154 | .file_scope = self.owner_decl.getFileScope(), | |
| 1155 | .parent_decl_node = self.owner_decl.src_node, | |
| 1140 | .file_scope = owner_decl.getFileScope(), | |
| 1141 | .parent_decl_node = owner_decl.src_node, | |
| 1156 | 1142 | .lazy = .{ .node_offset = self.node_offset }, |
| 1157 | 1143 | }; |
| 1158 | 1144 | } |
| 1159 | 1145 | |
| 1160 | pub fn fieldSrcLoc(u: Union, gpa: Allocator, query: FieldSrcQuery) SrcLoc { | |
| 1146 | pub fn fieldSrcLoc(u: Union, mod: *Module, query: FieldSrcQuery) SrcLoc { | |
| 1161 | 1147 | @setCold(true); |
| 1162 | const tree = u.owner_decl.getFileScope().getTree(gpa) catch |err| { | |
| 1148 | const owner_decl = mod.declPtr(u.owner_decl); | |
| 1149 | const file = owner_decl.getFileScope(); | |
| 1150 | const tree = file.getTree(mod.gpa) catch |err| { | |
| 1163 | 1151 | // In this case we emit a warning + a less precise source location. |
| 1164 | 1152 | log.warn("unable to load {s}: {s}", .{ |
| 1165 | u.owner_decl.getFileScope().sub_file_path, @errorName(err), | |
| 1153 | file.sub_file_path, @errorName(err), | |
| 1166 | 1154 | }); |
| 1167 | return u.srcLoc(); | |
| 1155 | return u.srcLoc(mod); | |
| 1168 | 1156 | }; |
| 1169 | const node = u.owner_decl.relativeToNodeIndex(u.node_offset); | |
| 1157 | const node = owner_decl.relativeToNodeIndex(u.node_offset); | |
| 1170 | 1158 | const node_tags = tree.nodes.items(.tag); |
| 1171 | const file = u.owner_decl.getFileScope(); | |
| 1172 | 1159 | switch (node_tags[node]) { |
| 1173 | 1160 | .container_decl, |
| 1174 | 1161 | .container_decl_trailing, |
| ... | ... | @@ -1348,22 +1335,23 @@ pub const Union = struct { |
| 1348 | 1335 | |
| 1349 | 1336 | pub const Opaque = struct { |
| 1350 | 1337 | /// The Decl that corresponds to the opaque itself. |
| 1351 | owner_decl: *Decl, | |
| 1352 | /// Represents the declarations inside this opaque. | |
| 1353 | namespace: Namespace, | |
| 1338 | owner_decl: Decl.Index, | |
| 1354 | 1339 | /// Offset from `owner_decl`, points to the opaque decl AST node. |
| 1355 | 1340 | node_offset: i32, |
| 1341 | /// Represents the declarations inside this opaque. | |
| 1342 | namespace: Namespace, | |
| 1356 | 1343 | |
| 1357 | pub fn srcLoc(self: Opaque) SrcLoc { | |
| 1344 | pub fn srcLoc(self: Opaque, mod: *Module) SrcLoc { | |
| 1345 | const owner_decl = mod.declPtr(self.owner_decl); | |
| 1358 | 1346 | return .{ |
| 1359 | .file_scope = self.owner_decl.getFileScope(), | |
| 1360 | .parent_decl_node = self.owner_decl.src_node, | |
| 1347 | .file_scope = owner_decl.getFileScope(), | |
| 1348 | .parent_decl_node = owner_decl.src_node, | |
| 1361 | 1349 | .lazy = .{ .node_offset = self.node_offset }, |
| 1362 | 1350 | }; |
| 1363 | 1351 | } |
| 1364 | 1352 | |
| 1365 | pub fn getFullyQualifiedName(s: *Opaque, gpa: Allocator) ![:0]u8 { | |
| 1366 | return s.owner_decl.getFullyQualifiedName(gpa); | |
| 1353 | pub fn getFullyQualifiedName(s: *Opaque, mod: *Module) ![:0]u8 { | |
| 1354 | return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod); | |
| 1367 | 1355 | } |
| 1368 | 1356 | }; |
| 1369 | 1357 | |
| ... | ... | @@ -1371,7 +1359,7 @@ pub const Opaque = struct { |
| 1371 | 1359 | /// arena allocator. |
| 1372 | 1360 | pub const ExternFn = struct { |
| 1373 | 1361 | /// The Decl that corresponds to the function itself. |
| 1374 | owner_decl: *Decl, | |
| 1362 | owner_decl: Decl.Index, | |
| 1375 | 1363 | /// Library name if specified. |
| 1376 | 1364 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. |
| 1377 | 1365 | /// Allocated with Module's allocator; outlives the ZIR code. |
| ... | ... | @@ -1389,7 +1377,12 @@ pub const ExternFn = struct { |
| 1389 | 1377 | /// instead. |
| 1390 | 1378 | pub const Fn = struct { |
| 1391 | 1379 | /// The Decl that corresponds to the function itself. |
| 1392 | owner_decl: *Decl, | |
| 1380 | owner_decl: Decl.Index, | |
| 1381 | /// The ZIR instruction that is a function instruction. Use this to find | |
| 1382 | /// the body. We store this rather than the body directly so that when ZIR | |
| 1383 | /// is regenerated on update(), we can map this to the new corresponding | |
| 1384 | /// ZIR instruction. | |
| 1385 | zir_body_inst: Zir.Inst.Index, | |
| 1393 | 1386 | /// If this is not null, this function is a generic function instantiation, and |
| 1394 | 1387 | /// there is a `TypedValue` here for each parameter of the function. |
| 1395 | 1388 | /// Non-comptime parameters are marked with a `generic_poison` for the value. |
| ... | ... | @@ -1403,11 +1396,6 @@ pub const Fn = struct { |
| 1403 | 1396 | /// parameter and tells whether it is anytype. |
| 1404 | 1397 | /// TODO apply the same enhancement for param_names below to this field. |
| 1405 | 1398 | anytype_args: [*]bool, |
| 1406 | /// The ZIR instruction that is a function instruction. Use this to find | |
| 1407 | /// the body. We store this rather than the body directly so that when ZIR | |
| 1408 | /// is regenerated on update(), we can map this to the new corresponding | |
| 1409 | /// ZIR instruction. | |
| 1410 | zir_body_inst: Zir.Inst.Index, | |
| 1411 | 1399 | |
| 1412 | 1400 | /// Prefer to use `getParamName` to access this because of the future improvement |
| 1413 | 1401 | /// we want to do mentioned in the TODO below. |
| ... | ... | @@ -1537,8 +1525,9 @@ pub const Fn = struct { |
| 1537 | 1525 | return func.param_names[index]; |
| 1538 | 1526 | } |
| 1539 | 1527 | |
| 1540 | pub fn hasInferredErrorSet(func: Fn) bool { | |
| 1541 | const zir = func.owner_decl.getFileScope().zir; | |
| 1528 | pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool { | |
| 1529 | const owner_decl = mod.declPtr(func.owner_decl); | |
| 1530 | const zir = owner_decl.getFileScope().zir; | |
| 1542 | 1531 | const zir_tags = zir.instructions.items(.tag); |
| 1543 | 1532 | switch (zir_tags[func.zir_body_inst]) { |
| 1544 | 1533 | .func => return false, |
| ... | ... | @@ -1556,7 +1545,7 @@ pub const Fn = struct { |
| 1556 | 1545 | pub const Var = struct { |
| 1557 | 1546 | /// if is_extern == true this is undefined |
| 1558 | 1547 | init: Value, |
| 1559 | owner_decl: *Decl, | |
| 1548 | owner_decl: Decl.Index, | |
| 1560 | 1549 | |
| 1561 | 1550 | /// Library name if specified. |
| 1562 | 1551 | /// For example `extern "c" var stderrp = ...` would have 'c' as library name. |
| ... | ... | @@ -1576,14 +1565,16 @@ pub const Var = struct { |
| 1576 | 1565 | }; |
| 1577 | 1566 | |
| 1578 | 1567 | pub const DeclAdapter = struct { |
| 1568 | mod: *Module, | |
| 1569 | ||
| 1579 | 1570 | pub fn hash(self: @This(), s: []const u8) u32 { |
| 1580 | 1571 | _ = self; |
| 1581 | 1572 | return @truncate(u32, std.hash.Wyhash.hash(0, s)); |
| 1582 | 1573 | } |
| 1583 | 1574 | |
| 1584 | pub fn eql(self: @This(), a: []const u8, b_decl: *Decl, b_index: usize) bool { | |
| 1585 | _ = self; | |
| 1575 | pub fn eql(self: @This(), a: []const u8, b_decl_index: Decl.Index, b_index: usize) bool { | |
| 1586 | 1576 | _ = b_index; |
| 1577 | const b_decl = self.mod.declPtr(b_decl_index); | |
| 1587 | 1578 | return mem.eql(u8, a, mem.sliceTo(b_decl.name, 0)); |
| 1588 | 1579 | } |
| 1589 | 1580 | }; |
| ... | ... | @@ -1599,25 +1590,30 @@ pub const Namespace = struct { |
| 1599 | 1590 | /// Declaration order is preserved via entry order. |
| 1600 | 1591 | /// Key memory is owned by `decl.name`. |
| 1601 | 1592 | /// Anonymous decls are not stored here; they are kept in `anon_decls` instead. |
| 1602 | decls: std.ArrayHashMapUnmanaged(*Decl, void, DeclContext, true) = .{}, | |
| 1593 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, | |
| 1603 | 1594 | |
| 1604 | anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, | |
| 1595 | anon_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | |
| 1605 | 1596 | |
| 1606 | 1597 | /// Key is usingnamespace Decl itself. To find the namespace being included, |
| 1607 | 1598 | /// the Decl Value has to be resolved as a Type which has a Namespace. |
| 1608 | 1599 | /// Value is whether the usingnamespace decl is marked `pub`. |
| 1609 | usingnamespace_set: std.AutoHashMapUnmanaged(*Decl, bool) = .{}, | |
| 1600 | usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{}, | |
| 1610 | 1601 | |
| 1611 | 1602 | const DeclContext = struct { |
| 1612 | pub fn hash(self: @This(), decl: *Decl) u32 { | |
| 1613 | _ = self; | |
| 1603 | module: *Module, | |
| 1604 | ||
| 1605 | pub fn hash(ctx: @This(), decl_index: Decl.Index) u32 { | |
| 1606 | const decl = ctx.module.declPtr(decl_index); | |
| 1614 | 1607 | return @truncate(u32, std.hash.Wyhash.hash(0, mem.sliceTo(decl.name, 0))); |
| 1615 | 1608 | } |
| 1616 | 1609 | |
| 1617 | pub fn eql(self: @This(), a: *Decl, b: *Decl, b_index: usize) bool { | |
| 1618 | _ = self; | |
| 1610 | pub fn eql(ctx: @This(), a_decl_index: Decl.Index, b_decl_index: Decl.Index, b_index: usize) bool { | |
| 1619 | 1611 | _ = b_index; |
| 1620 | return mem.eql(u8, mem.sliceTo(a.name, 0), mem.sliceTo(b.name, 0)); | |
| 1612 | const a_decl = ctx.module.declPtr(a_decl_index); | |
| 1613 | const b_decl = ctx.module.declPtr(b_decl_index); | |
| 1614 | const a_name = mem.sliceTo(a_decl.name, 0); | |
| 1615 | const b_name = mem.sliceTo(b_decl.name, 0); | |
| 1616 | return mem.eql(u8, a_name, b_name); | |
| 1621 | 1617 | } |
| 1622 | 1618 | }; |
| 1623 | 1619 | |
| ... | ... | @@ -1637,13 +1633,13 @@ pub const Namespace = struct { |
| 1637 | 1633 | var anon_decls = ns.anon_decls; |
| 1638 | 1634 | ns.anon_decls = .{}; |
| 1639 | 1635 | |
| 1640 | for (decls.keys()) |decl| { | |
| 1641 | decl.destroy(mod); | |
| 1636 | for (decls.keys()) |decl_index| { | |
| 1637 | mod.destroyDecl(decl_index); | |
| 1642 | 1638 | } |
| 1643 | 1639 | decls.deinit(gpa); |
| 1644 | 1640 | |
| 1645 | 1641 | for (anon_decls.keys()) |key| { |
| 1646 | key.destroy(mod); | |
| 1642 | mod.destroyDecl(key); | |
| 1647 | 1643 | } |
| 1648 | 1644 | anon_decls.deinit(gpa); |
| 1649 | 1645 | ns.usingnamespace_set.deinit(gpa); |
| ... | ... | @@ -1652,7 +1648,7 @@ pub const Namespace = struct { |
| 1652 | 1648 | pub fn deleteAllDecls( |
| 1653 | 1649 | ns: *Namespace, |
| 1654 | 1650 | mod: *Module, |
| 1655 | outdated_decls: ?*std.AutoArrayHashMap(*Decl, void), | |
| 1651 | outdated_decls: ?*std.AutoArrayHashMap(Decl.Index, void), | |
| 1656 | 1652 | ) !void { |
| 1657 | 1653 | const gpa = mod.gpa; |
| 1658 | 1654 | |
| ... | ... | @@ -1669,13 +1665,13 @@ pub const Namespace = struct { |
| 1669 | 1665 | |
| 1670 | 1666 | for (decls.keys()) |child_decl| { |
| 1671 | 1667 | mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); |
| 1672 | child_decl.destroy(mod); | |
| 1668 | mod.destroyDecl(child_decl); | |
| 1673 | 1669 | } |
| 1674 | 1670 | decls.deinit(gpa); |
| 1675 | 1671 | |
| 1676 | 1672 | for (anon_decls.keys()) |child_decl| { |
| 1677 | 1673 | mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); |
| 1678 | child_decl.destroy(mod); | |
| 1674 | mod.destroyDecl(child_decl); | |
| 1679 | 1675 | } |
| 1680 | 1676 | anon_decls.deinit(gpa); |
| 1681 | 1677 | |
| ... | ... | @@ -1685,12 +1681,14 @@ pub const Namespace = struct { |
| 1685 | 1681 | // This renders e.g. "std.fs.Dir.OpenOptions" |
| 1686 | 1682 | pub fn renderFullyQualifiedName( |
| 1687 | 1683 | ns: Namespace, |
| 1684 | mod: *Module, | |
| 1688 | 1685 | name: []const u8, |
| 1689 | 1686 | writer: anytype, |
| 1690 | 1687 | ) @TypeOf(writer).Error!void { |
| 1691 | 1688 | if (ns.parent) |parent| { |
| 1692 | const decl = ns.getDecl(); | |
| 1693 | try parent.renderFullyQualifiedName(mem.sliceTo(decl.name, 0), writer); | |
| 1689 | const decl_index = ns.getDeclIndex(); | |
| 1690 | const decl = mod.declPtr(decl_index); | |
| 1691 | try parent.renderFullyQualifiedName(mod, mem.sliceTo(decl.name, 0), writer); | |
| 1694 | 1692 | } else { |
| 1695 | 1693 | try ns.file_scope.renderFullyQualifiedName(writer); |
| 1696 | 1694 | } |
| ... | ... | @@ -1703,13 +1701,15 @@ pub const Namespace = struct { |
| 1703 | 1701 | /// This renders e.g. "std/fs.zig:Dir.OpenOptions" |
| 1704 | 1702 | pub fn renderFullyQualifiedDebugName( |
| 1705 | 1703 | ns: Namespace, |
| 1704 | mod: *Module, | |
| 1706 | 1705 | name: []const u8, |
| 1707 | 1706 | writer: anytype, |
| 1708 | 1707 | ) @TypeOf(writer).Error!void { |
| 1709 | 1708 | var separator_char: u8 = '.'; |
| 1710 | 1709 | if (ns.parent) |parent| { |
| 1711 | const decl = ns.getDecl(); | |
| 1712 | try parent.renderFullyQualifiedDebugName(mem.sliceTo(decl.name, 0), writer); | |
| 1710 | const decl_index = ns.getDeclIndex(); | |
| 1711 | const decl = mod.declPtr(decl_index); | |
| 1712 | try parent.renderFullyQualifiedDebugName(mod, mem.sliceTo(decl.name, 0), writer); | |
| 1713 | 1713 | } else { |
| 1714 | 1714 | try ns.file_scope.renderFullyQualifiedDebugName(writer); |
| 1715 | 1715 | separator_char = ':'; |
| ... | ... | @@ -1720,12 +1720,14 @@ pub const Namespace = struct { |
| 1720 | 1720 | } |
| 1721 | 1721 | } |
| 1722 | 1722 | |
| 1723 | pub fn getDecl(ns: Namespace) *Decl { | |
| 1723 | pub fn getDeclIndex(ns: Namespace) Decl.Index { | |
| 1724 | 1724 | return ns.ty.getOwnerDecl(); |
| 1725 | 1725 | } |
| 1726 | 1726 | }; |
| 1727 | 1727 | |
| 1728 | 1728 | pub const File = struct { |
| 1729 | /// The Decl of the struct that represents this File. | |
| 1730 | root_decl: Decl.OptionalIndex, | |
| 1729 | 1731 | status: enum { |
| 1730 | 1732 | never_loaded, |
| 1731 | 1733 | retryable_failure, |
| ... | ... | @@ -1749,16 +1751,14 @@ pub const File = struct { |
| 1749 | 1751 | zir: Zir, |
| 1750 | 1752 | /// Package that this file is a part of, managed externally. |
| 1751 | 1753 | pkg: *Package, |
| 1752 | /// The Decl of the struct that represents this File. | |
| 1753 | root_decl: ?*Decl, | |
| 1754 | 1754 | |
| 1755 | 1755 | /// Used by change detection algorithm, after astgen, contains the |
| 1756 | 1756 | /// set of decls that existed in the previous ZIR but not in the new one. |
| 1757 | deleted_decls: std.ArrayListUnmanaged(*Decl) = .{}, | |
| 1757 | deleted_decls: std.ArrayListUnmanaged(Decl.Index) = .{}, | |
| 1758 | 1758 | /// Used by change detection algorithm, after astgen, contains the |
| 1759 | 1759 | /// set of decls that existed both in the previous ZIR and in the new one, |
| 1760 | 1760 | /// but their source code has been modified. |
| 1761 | outdated_decls: std.ArrayListUnmanaged(*Decl) = .{}, | |
| 1761 | outdated_decls: std.ArrayListUnmanaged(Decl.Index) = .{}, | |
| 1762 | 1762 | |
| 1763 | 1763 | /// The most recent successful ZIR for this file, with no errors. |
| 1764 | 1764 | /// This is only populated when a previously successful ZIR |
| ... | ... | @@ -1798,8 +1798,8 @@ pub const File = struct { |
| 1798 | 1798 | log.debug("deinit File {s}", .{file.sub_file_path}); |
| 1799 | 1799 | file.deleted_decls.deinit(gpa); |
| 1800 | 1800 | file.outdated_decls.deinit(gpa); |
| 1801 | if (file.root_decl) |root_decl| { | |
| 1802 | root_decl.destroy(mod); | |
| 1801 | if (file.root_decl.unwrap()) |root_decl| { | |
| 1802 | mod.destroyDecl(root_decl); | |
| 1803 | 1803 | } |
| 1804 | 1804 | gpa.free(file.sub_file_path); |
| 1805 | 1805 | file.unload(gpa); |
| ... | ... | @@ -1932,7 +1932,7 @@ pub const EmbedFile = struct { |
| 1932 | 1932 | /// The Decl that was created from the `@embedFile` to own this resource. |
| 1933 | 1933 | /// This is how zig knows what other Decl objects to invalidate if the file |
| 1934 | 1934 | /// changes on disk. |
| 1935 | owner_decl: *Decl, | |
| 1935 | owner_decl: Decl.Index, | |
| 1936 | 1936 | |
| 1937 | 1937 | fn destroy(embed_file: *EmbedFile, mod: *Module) void { |
| 1938 | 1938 | const gpa = mod.gpa; |
| ... | ... | @@ -2776,6 +2776,7 @@ pub fn deinit(mod: *Module) void { |
| 2776 | 2776 | } |
| 2777 | 2777 | emit_h.failed_decls.deinit(gpa); |
| 2778 | 2778 | emit_h.decl_table.deinit(gpa); |
| 2779 | emit_h.allocated_emit_h.deinit(gpa); | |
| 2779 | 2780 | gpa.destroy(emit_h); |
| 2780 | 2781 | } |
| 2781 | 2782 | |
| ... | ... | @@ -2827,6 +2828,52 @@ pub fn deinit(mod: *Module) void { |
| 2827 | 2828 | } |
| 2828 | 2829 | mod.memoized_calls.deinit(gpa); |
| 2829 | 2830 | } |
| 2831 | ||
| 2832 | mod.decls_free_list.deinit(gpa); | |
| 2833 | mod.allocated_decls.deinit(gpa); | |
| 2834 | } | |
| 2835 | ||
| 2836 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { | |
| 2837 | const gpa = mod.gpa; | |
| 2838 | { | |
| 2839 | const decl = mod.declPtr(decl_index); | |
| 2840 | log.debug("destroy {*} ({s})", .{ decl, decl.name }); | |
| 2841 | _ = mod.test_functions.swapRemove(decl_index); | |
| 2842 | if (decl.deletion_flag) { | |
| 2843 | assert(mod.deletion_set.swapRemove(decl_index)); | |
| 2844 | } | |
| 2845 | if (decl.has_tv) { | |
| 2846 | if (decl.getInnerNamespace()) |namespace| { | |
| 2847 | namespace.destroyDecls(mod); | |
| 2848 | } | |
| 2849 | decl.clearValues(gpa); | |
| 2850 | } | |
| 2851 | decl.dependants.deinit(gpa); | |
| 2852 | decl.dependencies.deinit(gpa); | |
| 2853 | decl.clearName(gpa); | |
| 2854 | decl.* = undefined; | |
| 2855 | } | |
| 2856 | mod.decls_free_list.append(gpa, decl_index) catch { | |
| 2857 | // In order to keep `destroyDecl` a non-fallible function, we ignore memory | |
| 2858 | // allocation failures here, instead leaking the Decl until garbage collection. | |
| 2859 | }; | |
| 2860 | if (mod.emit_h) |mod_emit_h| { | |
| 2861 | const decl_emit_h = mod_emit_h.declPtr(decl_index); | |
| 2862 | decl_emit_h.fwd_decl.deinit(gpa); | |
| 2863 | decl_emit_h.* = undefined; | |
| 2864 | } | |
| 2865 | } | |
| 2866 | ||
| 2867 | pub fn declPtr(mod: *Module, decl_index: Decl.Index) *Decl { | |
| 2868 | return mod.allocated_decls.at(@enumToInt(decl_index)); | |
| 2869 | } | |
| 2870 | ||
| 2871 | /// Returns true if and only if the Decl is the top level struct associated with a File. | |
| 2872 | pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { | |
| 2873 | const decl = mod.declPtr(decl_index); | |
| 2874 | if (decl.src_namespace.parent != null) | |
| 2875 | return false; | |
| 2876 | return decl_index == decl.src_namespace.getDeclIndex(); | |
| 2830 | 2877 | } |
| 2831 | 2878 | |
| 2832 | 2879 | fn freeExportList(gpa: Allocator, export_list: []*Export) void { |
| ... | ... | @@ -3230,14 +3277,14 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 3230 | 3277 | // We do not need to hold any locks at this time because all the Decl and Namespace |
| 3231 | 3278 | // objects being touched are specific to this File, and the only other concurrent |
| 3232 | 3279 | // tasks are touching other File objects. |
| 3233 | try updateZirRefs(gpa, file, prev_zir.*); | |
| 3280 | try updateZirRefs(mod, file, prev_zir.*); | |
| 3234 | 3281 | // At this point, `file.outdated_decls` and `file.deleted_decls` are populated, |
| 3235 | 3282 | // and semantic analysis will deal with them properly. |
| 3236 | 3283 | // No need to keep previous ZIR. |
| 3237 | 3284 | prev_zir.deinit(gpa); |
| 3238 | 3285 | gpa.destroy(prev_zir); |
| 3239 | 3286 | file.prev_zir = null; |
| 3240 | } else if (file.root_decl) |root_decl| { | |
| 3287 | } else if (file.root_decl.unwrap()) |root_decl| { | |
| 3241 | 3288 | // This is an update, but it is the first time the File has succeeded |
| 3242 | 3289 | // ZIR. We must mark it outdated since we have already tried to |
| 3243 | 3290 | // semantically analyze it. |
| ... | ... | @@ -3251,7 +3298,8 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 3251 | 3298 | /// * Decl.zir_index |
| 3252 | 3299 | /// * Fn.zir_body_inst |
| 3253 | 3300 | /// * Decl.zir_decl_index |
| 3254 | fn updateZirRefs(gpa: Allocator, file: *File, old_zir: Zir) !void { | |
| 3301 | fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { | |
| 3302 | const gpa = mod.gpa; | |
| 3255 | 3303 | const new_zir = file.zir; |
| 3256 | 3304 | |
| 3257 | 3305 | // Maps from old ZIR to new ZIR, struct_decl, enum_decl, etc. Any instruction which |
| ... | ... | @@ -3268,10 +3316,10 @@ fn updateZirRefs(gpa: Allocator, file: *File, old_zir: Zir) !void { |
| 3268 | 3316 | // Walk the Decl graph, updating ZIR indexes, strings, and populating |
| 3269 | 3317 | // the deleted and outdated lists. |
| 3270 | 3318 | |
| 3271 | var decl_stack: std.ArrayListUnmanaged(*Decl) = .{}; | |
| 3319 | var decl_stack: std.ArrayListUnmanaged(Decl.Index) = .{}; | |
| 3272 | 3320 | defer decl_stack.deinit(gpa); |
| 3273 | 3321 | |
| 3274 | const root_decl = file.root_decl.?; | |
| 3322 | const root_decl = file.root_decl.unwrap().?; | |
| 3275 | 3323 | try decl_stack.append(gpa, root_decl); |
| 3276 | 3324 | |
| 3277 | 3325 | file.deleted_decls.clearRetainingCapacity(); |
| ... | ... | @@ -3281,7 +3329,8 @@ fn updateZirRefs(gpa: Allocator, file: *File, old_zir: Zir) !void { |
| 3281 | 3329 | // to re-generate ZIR for the File. |
| 3282 | 3330 | try file.outdated_decls.append(gpa, root_decl); |
| 3283 | 3331 | |
| 3284 | while (decl_stack.popOrNull()) |decl| { | |
| 3332 | while (decl_stack.popOrNull()) |decl_index| { | |
| 3333 | const decl = mod.declPtr(decl_index); | |
| 3285 | 3334 | // Anonymous decls and the root decl have this set to 0. We still need |
| 3286 | 3335 | // to walk them but we do not need to modify this value. |
| 3287 | 3336 | // Anonymous decls should not be marked outdated. They will be re-generated |
| ... | ... | @@ -3292,7 +3341,7 @@ fn updateZirRefs(gpa: Allocator, file: *File, old_zir: Zir) !void { |
| 3292 | 3341 | log.debug("updateZirRefs {s}: delete {*} ({s})", .{ |
| 3293 | 3342 | file.sub_file_path, decl, decl.name, |
| 3294 | 3343 | }); |
| 3295 | try file.deleted_decls.append(gpa, decl); | |
| 3344 | try file.deleted_decls.append(gpa, decl_index); | |
| 3296 | 3345 | continue; |
| 3297 | 3346 | }; |
| 3298 | 3347 | const old_hash = decl.contentsHashZir(old_zir); |
| ... | ... | @@ -3302,7 +3351,7 @@ fn updateZirRefs(gpa: Allocator, file: *File, old_zir: Zir) !void { |
| 3302 | 3351 | log.debug("updateZirRefs {s}: outdated {*} ({s}) {d} => {d}", .{ |
| 3303 | 3352 | file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index, |
| 3304 | 3353 | }); |
| 3305 | try file.outdated_decls.append(gpa, decl); | |
| 3354 | try file.outdated_decls.append(gpa, decl_index); | |
| 3306 | 3355 | } else { |
| 3307 | 3356 | log.debug("updateZirRefs {s}: unchanged {*} ({s}) {d} => {d}", .{ |
| 3308 | 3357 | file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index, |
| ... | ... | @@ -3314,21 +3363,21 @@ fn updateZirRefs(gpa: Allocator, file: *File, old_zir: Zir) !void { |
| 3314 | 3363 | |
| 3315 | 3364 | if (decl.getStruct()) |struct_obj| { |
| 3316 | 3365 | struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse { |
| 3317 | try file.deleted_decls.append(gpa, decl); | |
| 3366 | try file.deleted_decls.append(gpa, decl_index); | |
| 3318 | 3367 | continue; |
| 3319 | 3368 | }; |
| 3320 | 3369 | } |
| 3321 | 3370 | |
| 3322 | 3371 | if (decl.getUnion()) |union_obj| { |
| 3323 | 3372 | union_obj.zir_index = inst_map.get(union_obj.zir_index) orelse { |
| 3324 | try file.deleted_decls.append(gpa, decl); | |
| 3373 | try file.deleted_decls.append(gpa, decl_index); | |
| 3325 | 3374 | continue; |
| 3326 | 3375 | }; |
| 3327 | 3376 | } |
| 3328 | 3377 | |
| 3329 | 3378 | if (decl.getFunction()) |func| { |
| 3330 | 3379 | func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse { |
| 3331 | try file.deleted_decls.append(gpa, decl); | |
| 3380 | try file.deleted_decls.append(gpa, decl_index); | |
| 3332 | 3381 | continue; |
| 3333 | 3382 | }; |
| 3334 | 3383 | } |
| ... | ... | @@ -3485,10 +3534,12 @@ pub fn mapOldZirToNew( |
| 3485 | 3534 | /// However the resolution status of the Type may not be fully resolved. |
| 3486 | 3535 | /// For example an inferred error set is not resolved until after `analyzeFnBody`. |
| 3487 | 3536 | /// is called. |
| 3488 | pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) SemaError!void { | |
| 3537 | pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | |
| 3489 | 3538 | const tracy = trace(@src()); |
| 3490 | 3539 | defer tracy.end(); |
| 3491 | 3540 | |
| 3541 | const decl = mod.declPtr(decl_index); | |
| 3542 | ||
| 3492 | 3543 | const subsequent_analysis = switch (decl.analysis) { |
| 3493 | 3544 | .in_progress => unreachable, |
| 3494 | 3545 | |
| ... | ... | @@ -3507,15 +3558,16 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) SemaError!void { |
| 3507 | 3558 | |
| 3508 | 3559 | // The exports this Decl performs will be re-discovered, so we remove them here |
| 3509 | 3560 | // prior to re-analysis. |
| 3510 | mod.deleteDeclExports(decl); | |
| 3561 | mod.deleteDeclExports(decl_index); | |
| 3511 | 3562 | // Dependencies will be re-discovered, so we remove them here prior to re-analysis. |
| 3512 | for (decl.dependencies.keys()) |dep| { | |
| 3513 | dep.removeDependant(decl); | |
| 3563 | for (decl.dependencies.keys()) |dep_index| { | |
| 3564 | const dep = mod.declPtr(dep_index); | |
| 3565 | dep.removeDependant(decl_index); | |
| 3514 | 3566 | if (dep.dependants.count() == 0 and !dep.deletion_flag) { |
| 3515 | 3567 | log.debug("insert {*} ({s}) dependant {*} ({s}) into deletion set", .{ |
| 3516 | 3568 | decl, decl.name, dep, dep.name, |
| 3517 | 3569 | }); |
| 3518 | try mod.markDeclForDeletion(dep); | |
| 3570 | try mod.markDeclForDeletion(dep_index); | |
| 3519 | 3571 | } |
| 3520 | 3572 | } |
| 3521 | 3573 | decl.dependencies.clearRetainingCapacity(); |
| ... | ... | @@ -3530,7 +3582,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) SemaError!void { |
| 3530 | 3582 | decl_prog_node.activate(); |
| 3531 | 3583 | defer decl_prog_node.end(); |
| 3532 | 3584 | |
| 3533 | const type_changed = mod.semaDecl(decl) catch |err| switch (err) { | |
| 3585 | const type_changed = mod.semaDecl(decl_index) catch |err| switch (err) { | |
| 3534 | 3586 | error.AnalysisFail => { |
| 3535 | 3587 | if (decl.analysis == .in_progress) { |
| 3536 | 3588 | // If this decl caused the compile error, the analysis field would |
| ... | ... | @@ -3545,7 +3597,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) SemaError!void { |
| 3545 | 3597 | else => |e| { |
| 3546 | 3598 | decl.analysis = .sema_failure_retryable; |
| 3547 | 3599 | try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); |
| 3548 | mod.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create( | |
| 3600 | mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( | |
| 3549 | 3601 | mod.gpa, |
| 3550 | 3602 | decl.srcLoc(), |
| 3551 | 3603 | "unable to analyze: {s}", |
| ... | ... | @@ -3559,7 +3611,8 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) SemaError!void { |
| 3559 | 3611 | // We may need to chase the dependants and re-analyze them. |
| 3560 | 3612 | // However, if the decl is a function, and the type is the same, we do not need to. |
| 3561 | 3613 | if (type_changed or decl.ty.zigTypeTag() != .Fn) { |
| 3562 | for (decl.dependants.keys()) |dep| { | |
| 3614 | for (decl.dependants.keys()) |dep_index| { | |
| 3615 | const dep = mod.declPtr(dep_index); | |
| 3563 | 3616 | switch (dep.analysis) { |
| 3564 | 3617 | .unreferenced => unreachable, |
| 3565 | 3618 | .in_progress => continue, // already doing analysis, ok |
| ... | ... | @@ -3573,7 +3626,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) SemaError!void { |
| 3573 | 3626 | .codegen_failure_retryable, |
| 3574 | 3627 | .complete, |
| 3575 | 3628 | => if (dep.generation != mod.generation) { |
| 3576 | try mod.markOutdatedDecl(dep); | |
| 3629 | try mod.markOutdatedDecl(dep_index); | |
| 3577 | 3630 | }, |
| 3578 | 3631 | } |
| 3579 | 3632 | } |
| ... | ... | @@ -3585,7 +3638,10 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { |
| 3585 | 3638 | const tracy = trace(@src()); |
| 3586 | 3639 | defer tracy.end(); |
| 3587 | 3640 | |
| 3588 | switch (func.owner_decl.analysis) { | |
| 3641 | const decl_index = func.owner_decl; | |
| 3642 | const decl = mod.declPtr(decl_index); | |
| 3643 | ||
| 3644 | switch (decl.analysis) { | |
| 3589 | 3645 | .unreferenced => unreachable, |
| 3590 | 3646 | .in_progress => unreachable, |
| 3591 | 3647 | .outdated => unreachable, |
| ... | ... | @@ -3607,13 +3663,12 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { |
| 3607 | 3663 | } |
| 3608 | 3664 | |
| 3609 | 3665 | const gpa = mod.gpa; |
| 3610 | const decl = func.owner_decl; | |
| 3611 | 3666 | |
| 3612 | 3667 | var tmp_arena = std.heap.ArenaAllocator.init(gpa); |
| 3613 | 3668 | defer tmp_arena.deinit(); |
| 3614 | 3669 | const sema_arena = tmp_arena.allocator(); |
| 3615 | 3670 | |
| 3616 | var air = mod.analyzeFnBody(decl, func, sema_arena) catch |err| switch (err) { | |
| 3671 | var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) { | |
| 3617 | 3672 | error.AnalysisFail => { |
| 3618 | 3673 | if (func.state == .in_progress) { |
| 3619 | 3674 | // If this decl caused the compile error, the analysis field would |
| ... | ... | @@ -3635,7 +3690,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { |
| 3635 | 3690 | |
| 3636 | 3691 | if (builtin.mode == .Debug and mod.comp.verbose_air) { |
| 3637 | 3692 | std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name}); |
| 3638 | @import("print_air.zig").dump(gpa, air, liveness); | |
| 3693 | @import("print_air.zig").dump(mod, air, liveness); | |
| 3639 | 3694 | std.debug.print("# End Function AIR: {s}\n\n", .{decl.name}); |
| 3640 | 3695 | } |
| 3641 | 3696 | |
| ... | ... | @@ -3647,7 +3702,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { |
| 3647 | 3702 | }, |
| 3648 | 3703 | else => { |
| 3649 | 3704 | try mod.failed_decls.ensureUnusedCapacity(gpa, 1); |
| 3650 | mod.failed_decls.putAssumeCapacityNoClobber(decl, try Module.ErrorMsg.create( | |
| 3705 | mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( | |
| 3651 | 3706 | gpa, |
| 3652 | 3707 | decl.srcLoc(), |
| 3653 | 3708 | "unable to codegen: {s}", |
| ... | ... | @@ -3668,7 +3723,9 @@ pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void { |
| 3668 | 3723 | |
| 3669 | 3724 | // TODO we can potentially relax this if we store some more information along |
| 3670 | 3725 | // with decl dependency edges |
| 3671 | for (embed_file.owner_decl.dependants.keys()) |dep| { | |
| 3726 | const owner_decl = mod.declPtr(embed_file.owner_decl); | |
| 3727 | for (owner_decl.dependants.keys()) |dep_index| { | |
| 3728 | const dep = mod.declPtr(dep_index); | |
| 3672 | 3729 | switch (dep.analysis) { |
| 3673 | 3730 | .unreferenced => unreachable, |
| 3674 | 3731 | .in_progress => continue, // already doing analysis, ok |
| ... | ... | @@ -3682,7 +3739,7 @@ pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void { |
| 3682 | 3739 | .codegen_failure_retryable, |
| 3683 | 3740 | .complete, |
| 3684 | 3741 | => if (dep.generation != mod.generation) { |
| 3685 | try mod.markOutdatedDecl(dep); | |
| 3742 | try mod.markOutdatedDecl(dep_index); | |
| 3686 | 3743 | }, |
| 3687 | 3744 | } |
| 3688 | 3745 | } |
| ... | ... | @@ -3699,7 +3756,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3699 | 3756 | const tracy = trace(@src()); |
| 3700 | 3757 | defer tracy.end(); |
| 3701 | 3758 | |
| 3702 | if (file.root_decl != null) return; | |
| 3759 | if (file.root_decl != .none) return; | |
| 3703 | 3760 | |
| 3704 | 3761 | const gpa = mod.gpa; |
| 3705 | 3762 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| ... | ... | @@ -3724,10 +3781,11 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3724 | 3781 | .file_scope = file, |
| 3725 | 3782 | }, |
| 3726 | 3783 | }; |
| 3727 | const decl_name = try file.fullyQualifiedNameZ(gpa); | |
| 3728 | const new_decl = try mod.allocateNewDecl(decl_name, &struct_obj.namespace, 0, null); | |
| 3729 | file.root_decl = new_decl; | |
| 3730 | struct_obj.owner_decl = new_decl; | |
| 3784 | const new_decl_index = try mod.allocateNewDecl(&struct_obj.namespace, 0, null); | |
| 3785 | const new_decl = mod.declPtr(new_decl_index); | |
| 3786 | file.root_decl = new_decl_index.toOptional(); | |
| 3787 | struct_obj.owner_decl = new_decl_index; | |
| 3788 | new_decl.name = try file.fullyQualifiedNameZ(gpa); | |
| 3731 | 3789 | new_decl.src_line = 0; |
| 3732 | 3790 | new_decl.is_pub = true; |
| 3733 | 3791 | new_decl.is_exported = false; |
| ... | ... | @@ -3757,6 +3815,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3757 | 3815 | .perm_arena = new_decl_arena_allocator, |
| 3758 | 3816 | .code = file.zir, |
| 3759 | 3817 | .owner_decl = new_decl, |
| 3818 | .owner_decl_index = new_decl_index, | |
| 3760 | 3819 | .func = null, |
| 3761 | 3820 | .fn_ret_ty = Type.void, |
| 3762 | 3821 | .owner_func = null, |
| ... | ... | @@ -3769,7 +3828,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3769 | 3828 | var block_scope: Sema.Block = .{ |
| 3770 | 3829 | .parent = null, |
| 3771 | 3830 | .sema = &sema, |
| 3772 | .src_decl = new_decl, | |
| 3831 | .src_decl = new_decl_index, | |
| 3773 | 3832 | .namespace = &struct_obj.namespace, |
| 3774 | 3833 | .wip_capture_scope = wip_captures.scope, |
| 3775 | 3834 | .instructions = .{}, |
| ... | ... | @@ -3808,10 +3867,12 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3808 | 3867 | /// Returns `true` if the Decl type changed. |
| 3809 | 3868 | /// Returns `true` if this is the first time analyzing the Decl. |
| 3810 | 3869 | /// Returns `false` otherwise. |
| 3811 | fn semaDecl(mod: *Module, decl: *Decl) !bool { | |
| 3870 | fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | |
| 3812 | 3871 | const tracy = trace(@src()); |
| 3813 | 3872 | defer tracy.end(); |
| 3814 | 3873 | |
| 3874 | const decl = mod.declPtr(decl_index); | |
| 3875 | ||
| 3815 | 3876 | if (decl.getFileScope().status != .success_zir) { |
| 3816 | 3877 | return error.AnalysisFail; |
| 3817 | 3878 | } |
| ... | ... | @@ -3838,13 +3899,14 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3838 | 3899 | .perm_arena = decl_arena_allocator, |
| 3839 | 3900 | .code = zir, |
| 3840 | 3901 | .owner_decl = decl, |
| 3902 | .owner_decl_index = decl_index, | |
| 3841 | 3903 | .func = null, |
| 3842 | 3904 | .fn_ret_ty = Type.void, |
| 3843 | 3905 | .owner_func = null, |
| 3844 | 3906 | }; |
| 3845 | 3907 | defer sema.deinit(); |
| 3846 | 3908 | |
| 3847 | if (decl.isRoot()) { | |
| 3909 | if (mod.declIsRoot(decl_index)) { | |
| 3848 | 3910 | log.debug("semaDecl root {*} ({s})", .{ decl, decl.name }); |
| 3849 | 3911 | const main_struct_inst = Zir.main_struct_inst; |
| 3850 | 3912 | const struct_obj = decl.getStruct().?; |
| ... | ... | @@ -3864,7 +3926,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3864 | 3926 | var block_scope: Sema.Block = .{ |
| 3865 | 3927 | .parent = null, |
| 3866 | 3928 | .sema = &sema, |
| 3867 | .src_decl = decl, | |
| 3929 | .src_decl = decl_index, | |
| 3868 | 3930 | .namespace = decl.src_namespace, |
| 3869 | 3931 | .wip_capture_scope = wip_captures.scope, |
| 3870 | 3932 | .instructions = .{}, |
| ... | ... | @@ -3922,15 +3984,15 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3922 | 3984 | const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State); |
| 3923 | 3985 | |
| 3924 | 3986 | if (decl.is_usingnamespace) { |
| 3925 | if (!decl_tv.ty.eql(Type.type, target)) { | |
| 3987 | if (!decl_tv.ty.eql(Type.type, mod)) { | |
| 3926 | 3988 | return sema.fail(&block_scope, src, "expected type, found {}", .{ |
| 3927 | decl_tv.ty.fmt(target), | |
| 3989 | decl_tv.ty.fmt(mod), | |
| 3928 | 3990 | }); |
| 3929 | 3991 | } |
| 3930 | 3992 | var buffer: Value.ToTypeBuffer = undefined; |
| 3931 | 3993 | const ty = try decl_tv.val.toType(&buffer).copy(decl_arena_allocator); |
| 3932 | 3994 | if (ty.getNamespace() == null) { |
| 3933 | return sema.fail(&block_scope, src, "type {} has no namespace", .{ty.fmt(target)}); | |
| 3995 | return sema.fail(&block_scope, src, "type {} has no namespace", .{ty.fmt(mod)}); | |
| 3934 | 3996 | } |
| 3935 | 3997 | |
| 3936 | 3998 | decl.ty = Type.type; |
| ... | ... | @@ -3949,7 +4011,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3949 | 4011 | |
| 3950 | 4012 | if (decl_tv.val.castTag(.function)) |fn_payload| { |
| 3951 | 4013 | const func = fn_payload.data; |
| 3952 | const owns_tv = func.owner_decl == decl; | |
| 4014 | const owns_tv = func.owner_decl == decl_index; | |
| 3953 | 4015 | if (owns_tv) { |
| 3954 | 4016 | var prev_type_has_bits = false; |
| 3955 | 4017 | var prev_is_inline = false; |
| ... | ... | @@ -3957,7 +4019,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3957 | 4019 | |
| 3958 | 4020 | if (decl.has_tv) { |
| 3959 | 4021 | prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(); |
| 3960 | type_changed = !decl.ty.eql(decl_tv.ty, target); | |
| 4022 | type_changed = !decl.ty.eql(decl_tv.ty, mod); | |
| 3961 | 4023 | if (decl.getFunction()) |prev_func| { |
| 3962 | 4024 | prev_is_inline = prev_func.state == .inline_only; |
| 3963 | 4025 | } |
| ... | ... | @@ -3982,13 +4044,13 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3982 | 4044 | // We don't fully codegen the decl until later, but we do need to reserve a global |
| 3983 | 4045 | // offset table index for it. This allows us to codegen decls out of dependency |
| 3984 | 4046 | // order, increasing how many computations can be done in parallel. |
| 3985 | try mod.comp.bin_file.allocateDeclIndexes(decl); | |
| 4047 | try mod.comp.bin_file.allocateDeclIndexes(decl_index); | |
| 3986 | 4048 | try mod.comp.work_queue.writeItem(.{ .codegen_func = func }); |
| 3987 | 4049 | if (type_changed and mod.emit_h != null) { |
| 3988 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); | |
| 4050 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); | |
| 3989 | 4051 | } |
| 3990 | 4052 | } else if (!prev_is_inline and prev_type_has_bits) { |
| 3991 | mod.comp.bin_file.freeDecl(decl); | |
| 4053 | mod.comp.bin_file.freeDecl(decl_index); | |
| 3992 | 4054 | } |
| 3993 | 4055 | |
| 3994 | 4056 | const is_inline = decl.ty.fnCallingConvention() == .Inline; |
| ... | ... | @@ -3999,14 +4061,14 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3999 | 4061 | } |
| 4000 | 4062 | // The scope needs to have the decl in it. |
| 4001 | 4063 | const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) }; |
| 4002 | try sema.analyzeExport(&block_scope, export_src, options, decl); | |
| 4064 | try sema.analyzeExport(&block_scope, export_src, options, decl_index); | |
| 4003 | 4065 | } |
| 4004 | 4066 | return type_changed or is_inline != prev_is_inline; |
| 4005 | 4067 | } |
| 4006 | 4068 | } |
| 4007 | 4069 | var type_changed = true; |
| 4008 | 4070 | if (decl.has_tv) { |
| 4009 | type_changed = !decl.ty.eql(decl_tv.ty, target); | |
| 4071 | type_changed = !decl.ty.eql(decl_tv.ty, mod); | |
| 4010 | 4072 | decl.clearValues(gpa); |
| 4011 | 4073 | } |
| 4012 | 4074 | |
| ... | ... | @@ -4016,7 +4078,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 4016 | 4078 | switch (decl_tv.val.tag()) { |
| 4017 | 4079 | .variable => { |
| 4018 | 4080 | const variable = decl_tv.val.castTag(.variable).?.data; |
| 4019 | if (variable.owner_decl == decl) { | |
| 4081 | if (variable.owner_decl == decl_index) { | |
| 4020 | 4082 | decl.owns_tv = true; |
| 4021 | 4083 | queue_linker_work = true; |
| 4022 | 4084 | |
| ... | ... | @@ -4026,7 +4088,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 4026 | 4088 | }, |
| 4027 | 4089 | .extern_fn => { |
| 4028 | 4090 | const extern_fn = decl_tv.val.castTag(.extern_fn).?.data; |
| 4029 | if (extern_fn.owner_decl == decl) { | |
| 4091 | if (extern_fn.owner_decl == decl_index) { | |
| 4030 | 4092 | decl.owns_tv = true; |
| 4031 | 4093 | queue_linker_work = true; |
| 4032 | 4094 | is_extern = true; |
| ... | ... | @@ -4065,11 +4127,11 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 4065 | 4127 | // codegen backend wants full access to the Decl Type. |
| 4066 | 4128 | try sema.resolveTypeFully(&block_scope, src, decl.ty); |
| 4067 | 4129 | |
| 4068 | try mod.comp.bin_file.allocateDeclIndexes(decl); | |
| 4069 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl }); | |
| 4130 | try mod.comp.bin_file.allocateDeclIndexes(decl_index); | |
| 4131 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); | |
| 4070 | 4132 | |
| 4071 | 4133 | if (type_changed and mod.emit_h != null) { |
| 4072 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); | |
| 4134 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); | |
| 4073 | 4135 | } |
| 4074 | 4136 | } |
| 4075 | 4137 | |
| ... | ... | @@ -4077,15 +4139,18 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 4077 | 4139 | const export_src = src; // TODO point to the export token |
| 4078 | 4140 | // The scope needs to have the decl in it. |
| 4079 | 4141 | const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) }; |
| 4080 | try sema.analyzeExport(&block_scope, export_src, options, decl); | |
| 4142 | try sema.analyzeExport(&block_scope, export_src, options, decl_index); | |
| 4081 | 4143 | } |
| 4082 | 4144 | |
| 4083 | 4145 | return type_changed; |
| 4084 | 4146 | } |
| 4085 | 4147 | |
| 4086 | 4148 | /// Returns the depender's index of the dependee. |
| 4087 | pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !void { | |
| 4088 | if (depender == dependee) return; | |
| 4149 | pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_index: Decl.Index) !void { | |
| 4150 | if (depender_index == dependee_index) return; | |
| 4151 | ||
| 4152 | const depender = mod.declPtr(depender_index); | |
| 4153 | const dependee = mod.declPtr(dependee_index); | |
| 4089 | 4154 | |
| 4090 | 4155 | log.debug("{*} ({s}) depends on {*} ({s})", .{ |
| 4091 | 4156 | depender, depender.name, dependee, dependee.name, |
| ... | ... | @@ -4096,11 +4161,11 @@ pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !vo |
| 4096 | 4161 | |
| 4097 | 4162 | if (dependee.deletion_flag) { |
| 4098 | 4163 | dependee.deletion_flag = false; |
| 4099 | assert(mod.deletion_set.swapRemove(dependee)); | |
| 4164 | assert(mod.deletion_set.swapRemove(dependee_index)); | |
| 4100 | 4165 | } |
| 4101 | 4166 | |
| 4102 | dependee.dependants.putAssumeCapacity(depender, {}); | |
| 4103 | depender.dependencies.putAssumeCapacity(dependee, {}); | |
| 4167 | dependee.dependants.putAssumeCapacity(depender_index, {}); | |
| 4168 | depender.dependencies.putAssumeCapacity(dependee_index, {}); | |
| 4104 | 4169 | } |
| 4105 | 4170 | |
| 4106 | 4171 | pub const ImportFileResult = struct { |
| ... | ... | @@ -4146,7 +4211,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { |
| 4146 | 4211 | .zir = undefined, |
| 4147 | 4212 | .status = .never_loaded, |
| 4148 | 4213 | .pkg = pkg, |
| 4149 | .root_decl = null, | |
| 4214 | .root_decl = .none, | |
| 4150 | 4215 | }; |
| 4151 | 4216 | return ImportFileResult{ |
| 4152 | 4217 | .file = new_file, |
| ... | ... | @@ -4214,7 +4279,7 @@ pub fn importFile( |
| 4214 | 4279 | .zir = undefined, |
| 4215 | 4280 | .status = .never_loaded, |
| 4216 | 4281 | .pkg = cur_file.pkg, |
| 4217 | .root_decl = null, | |
| 4282 | .root_decl = .none, | |
| 4218 | 4283 | }; |
| 4219 | 4284 | return ImportFileResult{ |
| 4220 | 4285 | .file = new_file, |
| ... | ... | @@ -4388,8 +4453,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 4388 | 4453 | const line = iter.parent_decl.relativeToLine(line_off); |
| 4389 | 4454 | const decl_name_index = zir.extra[decl_sub_index + 5]; |
| 4390 | 4455 | const decl_doccomment_index = zir.extra[decl_sub_index + 7]; |
| 4391 | const decl_index = zir.extra[decl_sub_index + 6]; | |
| 4392 | const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node; | |
| 4456 | const decl_zir_index = zir.extra[decl_sub_index + 6]; | |
| 4457 | const decl_block_inst_data = zir.instructions.items(.data)[decl_zir_index].pl_node; | |
| 4393 | 4458 | const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node); |
| 4394 | 4459 | |
| 4395 | 4460 | // Every Decl needs a name. |
| ... | ... | @@ -4432,15 +4497,22 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 4432 | 4497 | if (is_usingnamespace) try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1); |
| 4433 | 4498 | |
| 4434 | 4499 | // We create a Decl for it regardless of analysis status. |
| 4435 | const gop = try namespace.decls.getOrPutAdapted(gpa, @as([]const u8, mem.sliceTo(decl_name, 0)), DeclAdapter{}); | |
| 4500 | const gop = try namespace.decls.getOrPutContextAdapted( | |
| 4501 | gpa, | |
| 4502 | @as([]const u8, mem.sliceTo(decl_name, 0)), | |
| 4503 | DeclAdapter{ .mod = mod }, | |
| 4504 | Namespace.DeclContext{ .module = mod }, | |
| 4505 | ); | |
| 4436 | 4506 | if (!gop.found_existing) { |
| 4437 | const new_decl = try mod.allocateNewDecl(decl_name, namespace, decl_node, iter.parent_decl.src_scope); | |
| 4507 | const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope); | |
| 4508 | const new_decl = mod.declPtr(new_decl_index); | |
| 4509 | new_decl.name = decl_name; | |
| 4438 | 4510 | if (is_usingnamespace) { |
| 4439 | namespace.usingnamespace_set.putAssumeCapacity(new_decl, is_pub); | |
| 4511 | namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub); | |
| 4440 | 4512 | } |
| 4441 | 4513 | log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace }); |
| 4442 | 4514 | new_decl.src_line = line; |
| 4443 | gop.key_ptr.* = new_decl; | |
| 4515 | gop.key_ptr.* = new_decl_index; | |
| 4444 | 4516 | // Exported decls, comptime decls, usingnamespace decls, and |
| 4445 | 4517 | // test decls if in test mode, get analyzed. |
| 4446 | 4518 | const decl_pkg = namespace.file_scope.pkg; |
| ... | ... | @@ -4451,7 +4523,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 4451 | 4523 | // the test name filter. |
| 4452 | 4524 | if (!mod.comp.bin_file.options.is_test) break :blk false; |
| 4453 | 4525 | if (decl_pkg != mod.main_pkg) break :blk false; |
| 4454 | try mod.test_functions.put(gpa, new_decl, {}); | |
| 4526 | try mod.test_functions.put(gpa, new_decl_index, {}); | |
| 4455 | 4527 | break :blk true; |
| 4456 | 4528 | }, |
| 4457 | 4529 | else => blk: { |
| ... | ... | @@ -4459,12 +4531,12 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 4459 | 4531 | if (!mod.comp.bin_file.options.is_test) break :blk false; |
| 4460 | 4532 | if (decl_pkg != mod.main_pkg) break :blk false; |
| 4461 | 4533 | // TODO check the name against --test-filter |
| 4462 | try mod.test_functions.put(gpa, new_decl, {}); | |
| 4534 | try mod.test_functions.put(gpa, new_decl_index, {}); | |
| 4463 | 4535 | break :blk true; |
| 4464 | 4536 | }, |
| 4465 | 4537 | }; |
| 4466 | 4538 | if (want_analysis) { |
| 4467 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | |
| 4539 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl_index }); | |
| 4468 | 4540 | } |
| 4469 | 4541 | new_decl.is_pub = is_pub; |
| 4470 | 4542 | new_decl.is_exported = is_exported; |
| ... | ... | @@ -4476,7 +4548,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 4476 | 4548 | return; |
| 4477 | 4549 | } |
| 4478 | 4550 | gpa.free(decl_name); |
| 4479 | const decl = gop.key_ptr.*; | |
| 4551 | const decl_index = gop.key_ptr.*; | |
| 4552 | const decl = mod.declPtr(decl_index); | |
| 4480 | 4553 | log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl.name, namespace }); |
| 4481 | 4554 | // Update the AST node of the decl; even if its contents are unchanged, it may |
| 4482 | 4555 | // have been re-ordered. |
| ... | ... | @@ -4497,17 +4570,17 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 4497 | 4570 | .elf => if (decl.fn_link.elf.len != 0) { |
| 4498 | 4571 | // TODO Look into detecting when this would be unnecessary by storing enough state |
| 4499 | 4572 | // in `Decl` to notice that the line number did not change. |
| 4500 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl }); | |
| 4573 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); | |
| 4501 | 4574 | }, |
| 4502 | 4575 | .macho => if (decl.fn_link.macho.len != 0) { |
| 4503 | 4576 | // TODO Look into detecting when this would be unnecessary by storing enough state |
| 4504 | 4577 | // in `Decl` to notice that the line number did not change. |
| 4505 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl }); | |
| 4578 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); | |
| 4506 | 4579 | }, |
| 4507 | 4580 | .plan9 => { |
| 4508 | 4581 | // TODO Look into detecting when this would be unnecessary by storing enough state |
| 4509 | 4582 | // in `Decl` to notice that the line number did not change. |
| 4510 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl }); | |
| 4583 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); | |
| 4511 | 4584 | }, |
| 4512 | 4585 | .c, .wasm, .spirv, .nvptx => {}, |
| 4513 | 4586 | } |
| ... | ... | @@ -4517,25 +4590,27 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 4517 | 4590 | /// Make it as if the semantic analysis for this Decl never happened. |
| 4518 | 4591 | pub fn clearDecl( |
| 4519 | 4592 | mod: *Module, |
| 4520 | decl: *Decl, | |
| 4521 | outdated_decls: ?*std.AutoArrayHashMap(*Decl, void), | |
| 4593 | decl_index: Decl.Index, | |
| 4594 | outdated_decls: ?*std.AutoArrayHashMap(Decl.Index, void), | |
| 4522 | 4595 | ) Allocator.Error!void { |
| 4523 | 4596 | const tracy = trace(@src()); |
| 4524 | 4597 | defer tracy.end(); |
| 4525 | 4598 | |
| 4599 | const decl = mod.declPtr(decl_index); | |
| 4526 | 4600 | log.debug("clearing {*} ({s})", .{ decl, decl.name }); |
| 4527 | 4601 | |
| 4528 | 4602 | const gpa = mod.gpa; |
| 4529 | 4603 | try mod.deletion_set.ensureUnusedCapacity(gpa, decl.dependencies.count()); |
| 4530 | 4604 | |
| 4531 | 4605 | if (outdated_decls) |map| { |
| 4532 | _ = map.swapRemove(decl); | |
| 4606 | _ = map.swapRemove(decl_index); | |
| 4533 | 4607 | try map.ensureUnusedCapacity(decl.dependants.count()); |
| 4534 | 4608 | } |
| 4535 | 4609 | |
| 4536 | 4610 | // Remove itself from its dependencies. |
| 4537 | for (decl.dependencies.keys()) |dep| { | |
| 4538 | dep.removeDependant(decl); | |
| 4611 | for (decl.dependencies.keys()) |dep_index| { | |
| 4612 | const dep = mod.declPtr(dep_index); | |
| 4613 | dep.removeDependant(decl_index); | |
| 4539 | 4614 | if (dep.dependants.count() == 0 and !dep.deletion_flag) { |
| 4540 | 4615 | log.debug("insert {*} ({s}) dependant {*} ({s}) into deletion set", .{ |
| 4541 | 4616 | decl, decl.name, dep, dep.name, |
| ... | ... | @@ -4543,35 +4618,36 @@ pub fn clearDecl( |
| 4543 | 4618 | // We don't recursively perform a deletion here, because during the update, |
| 4544 | 4619 | // another reference to it may turn up. |
| 4545 | 4620 | dep.deletion_flag = true; |
| 4546 | mod.deletion_set.putAssumeCapacity(dep, {}); | |
| 4621 | mod.deletion_set.putAssumeCapacity(dep_index, {}); | |
| 4547 | 4622 | } |
| 4548 | 4623 | } |
| 4549 | 4624 | decl.dependencies.clearRetainingCapacity(); |
| 4550 | 4625 | |
| 4551 | 4626 | // Anything that depends on this deleted decl needs to be re-analyzed. |
| 4552 | for (decl.dependants.keys()) |dep| { | |
| 4553 | dep.removeDependency(decl); | |
| 4627 | for (decl.dependants.keys()) |dep_index| { | |
| 4628 | const dep = mod.declPtr(dep_index); | |
| 4629 | dep.removeDependency(decl_index); | |
| 4554 | 4630 | if (outdated_decls) |map| { |
| 4555 | map.putAssumeCapacity(dep, {}); | |
| 4631 | map.putAssumeCapacity(dep_index, {}); | |
| 4556 | 4632 | } |
| 4557 | 4633 | } |
| 4558 | 4634 | decl.dependants.clearRetainingCapacity(); |
| 4559 | 4635 | |
| 4560 | if (mod.failed_decls.fetchSwapRemove(decl)) |kv| { | |
| 4636 | if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| { | |
| 4561 | 4637 | kv.value.destroy(gpa); |
| 4562 | 4638 | } |
| 4563 | 4639 | if (mod.emit_h) |emit_h| { |
| 4564 | if (emit_h.failed_decls.fetchSwapRemove(decl)) |kv| { | |
| 4640 | if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| { | |
| 4565 | 4641 | kv.value.destroy(gpa); |
| 4566 | 4642 | } |
| 4567 | assert(emit_h.decl_table.swapRemove(decl)); | |
| 4643 | assert(emit_h.decl_table.swapRemove(decl_index)); | |
| 4568 | 4644 | } |
| 4569 | _ = mod.compile_log_decls.swapRemove(decl); | |
| 4570 | mod.deleteDeclExports(decl); | |
| 4645 | _ = mod.compile_log_decls.swapRemove(decl_index); | |
| 4646 | mod.deleteDeclExports(decl_index); | |
| 4571 | 4647 | |
| 4572 | 4648 | if (decl.has_tv) { |
| 4573 | 4649 | if (decl.ty.isFnOrHasRuntimeBits()) { |
| 4574 | mod.comp.bin_file.freeDecl(decl); | |
| 4650 | mod.comp.bin_file.freeDecl(decl_index); | |
| 4575 | 4651 | |
| 4576 | 4652 | // TODO instead of a union, put this memory trailing Decl objects, |
| 4577 | 4653 | // and allow it to be variably sized. |
| ... | ... | @@ -4604,15 +4680,16 @@ pub fn clearDecl( |
| 4604 | 4680 | |
| 4605 | 4681 | if (decl.deletion_flag) { |
| 4606 | 4682 | decl.deletion_flag = false; |
| 4607 | assert(mod.deletion_set.swapRemove(decl)); | |
| 4683 | assert(mod.deletion_set.swapRemove(decl_index)); | |
| 4608 | 4684 | } |
| 4609 | 4685 | |
| 4610 | 4686 | decl.analysis = .unreferenced; |
| 4611 | 4687 | } |
| 4612 | 4688 | |
| 4613 | 4689 | /// This function is exclusively called for anonymous decls. |
| 4614 | pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void { | |
| 4615 | log.debug("deleteUnusedDecl {*} ({s})", .{ decl, decl.name }); | |
| 4690 | pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { | |
| 4691 | const decl = mod.declPtr(decl_index); | |
| 4692 | log.debug("deleteUnusedDecl {d} ({s})", .{ decl_index, decl.name }); | |
| 4616 | 4693 | |
| 4617 | 4694 | // TODO: remove `allocateDeclIndexes` and make the API that the linker backends |
| 4618 | 4695 | // are required to notice the first time `updateDecl` happens and keep track |
| ... | ... | @@ -4626,55 +4703,58 @@ pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void { |
| 4626 | 4703 | .c => {}, // this linker backend has already migrated to the new API |
| 4627 | 4704 | else => if (decl.has_tv) { |
| 4628 | 4705 | if (decl.ty.isFnOrHasRuntimeBits()) { |
| 4629 | mod.comp.bin_file.freeDecl(decl); | |
| 4706 | mod.comp.bin_file.freeDecl(decl_index); | |
| 4630 | 4707 | } |
| 4631 | 4708 | }, |
| 4632 | 4709 | } |
| 4633 | 4710 | |
| 4634 | assert(!decl.isRoot()); | |
| 4635 | assert(decl.src_namespace.anon_decls.swapRemove(decl)); | |
| 4711 | assert(!mod.declIsRoot(decl_index)); | |
| 4712 | assert(decl.src_namespace.anon_decls.swapRemove(decl_index)); | |
| 4636 | 4713 | |
| 4637 | 4714 | const dependants = decl.dependants.keys(); |
| 4638 | 4715 | for (dependants) |dep| { |
| 4639 | dep.removeDependency(decl); | |
| 4716 | mod.declPtr(dep).removeDependency(decl_index); | |
| 4640 | 4717 | } |
| 4641 | 4718 | |
| 4642 | 4719 | for (decl.dependencies.keys()) |dep| { |
| 4643 | dep.removeDependant(decl); | |
| 4720 | mod.declPtr(dep).removeDependant(decl_index); | |
| 4644 | 4721 | } |
| 4645 | decl.destroy(mod); | |
| 4722 | mod.destroyDecl(decl_index); | |
| 4646 | 4723 | } |
| 4647 | 4724 | |
| 4648 | 4725 | /// We don't perform a deletion here, because this Decl or another one |
| 4649 | 4726 | /// may end up referencing it before the update is complete. |
| 4650 | fn markDeclForDeletion(mod: *Module, decl: *Decl) !void { | |
| 4727 | fn markDeclForDeletion(mod: *Module, decl_index: Decl.Index) !void { | |
| 4728 | const decl = mod.declPtr(decl_index); | |
| 4651 | 4729 | decl.deletion_flag = true; |
| 4652 | try mod.deletion_set.put(mod.gpa, decl, {}); | |
| 4730 | try mod.deletion_set.put(mod.gpa, decl_index, {}); | |
| 4653 | 4731 | } |
| 4654 | 4732 | |
| 4655 | 4733 | /// Cancel the creation of an anon decl and delete any references to it. |
| 4656 | 4734 | /// If other decls depend on this decl, they must be aborted first. |
| 4657 | pub fn abortAnonDecl(mod: *Module, decl: *Decl) void { | |
| 4735 | pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { | |
| 4736 | const decl = mod.declPtr(decl_index); | |
| 4658 | 4737 | log.debug("abortAnonDecl {*} ({s})", .{ decl, decl.name }); |
| 4659 | 4738 | |
| 4660 | assert(!decl.isRoot()); | |
| 4661 | assert(decl.src_namespace.anon_decls.swapRemove(decl)); | |
| 4739 | assert(!mod.declIsRoot(decl_index)); | |
| 4740 | assert(decl.src_namespace.anon_decls.swapRemove(decl_index)); | |
| 4662 | 4741 | |
| 4663 | 4742 | // An aborted decl must not have dependants -- they must have |
| 4664 | 4743 | // been aborted first and removed from this list. |
| 4665 | 4744 | assert(decl.dependants.count() == 0); |
| 4666 | 4745 | |
| 4667 | for (decl.dependencies.keys()) |dep| { | |
| 4668 | dep.removeDependant(decl); | |
| 4746 | for (decl.dependencies.keys()) |dep_index| { | |
| 4747 | const dep = mod.declPtr(dep_index); | |
| 4748 | dep.removeDependant(decl_index); | |
| 4669 | 4749 | } |
| 4670 | 4750 | |
| 4671 | decl.destroy(mod); | |
| 4751 | mod.destroyDecl(decl_index); | |
| 4672 | 4752 | } |
| 4673 | 4753 | |
| 4674 | 4754 | /// Delete all the Export objects that are caused by this Decl. Re-analysis of |
| 4675 | 4755 | /// this Decl will cause them to be re-created (or not). |
| 4676 | fn deleteDeclExports(mod: *Module, decl: *Decl) void { | |
| 4677 | const kv = mod.export_owners.fetchSwapRemove(decl) orelse return; | |
| 4756 | fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) void { | |
| 4757 | const kv = mod.export_owners.fetchSwapRemove(decl_index) orelse return; | |
| 4678 | 4758 | |
| 4679 | 4759 | for (kv.value) |exp| { |
| 4680 | 4760 | if (mod.decl_exports.getPtr(exp.exported_decl)) |value_ptr| { |
| ... | ... | @@ -4683,7 +4763,7 @@ fn deleteDeclExports(mod: *Module, decl: *Decl) void { |
| 4683 | 4763 | var i: usize = 0; |
| 4684 | 4764 | var new_len = list.len; |
| 4685 | 4765 | while (i < new_len) { |
| 4686 | if (list[i].owner_decl == decl) { | |
| 4766 | if (list[i].owner_decl == decl_index) { | |
| 4687 | 4767 | mem.copyBackwards(*Export, list[i..], list[i + 1 .. new_len]); |
| 4688 | 4768 | new_len -= 1; |
| 4689 | 4769 | } else { |
| ... | ... | @@ -4713,11 +4793,13 @@ fn deleteDeclExports(mod: *Module, decl: *Decl) void { |
| 4713 | 4793 | mod.gpa.free(kv.value); |
| 4714 | 4794 | } |
| 4715 | 4795 | |
| 4716 | pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) SemaError!Air { | |
| 4796 | pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { | |
| 4717 | 4797 | const tracy = trace(@src()); |
| 4718 | 4798 | defer tracy.end(); |
| 4719 | 4799 | |
| 4720 | 4800 | const gpa = mod.gpa; |
| 4801 | const decl_index = func.owner_decl; | |
| 4802 | const decl = mod.declPtr(decl_index); | |
| 4721 | 4803 | |
| 4722 | 4804 | // Use the Decl's arena for captured values. |
| 4723 | 4805 | var decl_arena = decl.value_arena.?.promote(gpa); |
| ... | ... | @@ -4731,8 +4813,9 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem |
| 4731 | 4813 | .perm_arena = decl_arena_allocator, |
| 4732 | 4814 | .code = decl.getFileScope().zir, |
| 4733 | 4815 | .owner_decl = decl, |
| 4816 | .owner_decl_index = decl_index, | |
| 4734 | 4817 | .func = func, |
| 4735 | .fn_ret_ty = func.owner_decl.ty.fnReturnType(), | |
| 4818 | .fn_ret_ty = decl.ty.fnReturnType(), | |
| 4736 | 4819 | .owner_func = func, |
| 4737 | 4820 | }; |
| 4738 | 4821 | defer sema.deinit(); |
| ... | ... | @@ -4748,7 +4831,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem |
| 4748 | 4831 | var inner_block: Sema.Block = .{ |
| 4749 | 4832 | .parent = null, |
| 4750 | 4833 | .sema = &sema, |
| 4751 | .src_decl = decl, | |
| 4834 | .src_decl = decl_index, | |
| 4752 | 4835 | .namespace = decl.src_namespace, |
| 4753 | 4836 | .wip_capture_scope = wip_captures.scope, |
| 4754 | 4837 | .instructions = .{}, |
| ... | ... | @@ -4903,10 +4986,11 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem |
| 4903 | 4986 | }; |
| 4904 | 4987 | } |
| 4905 | 4988 | |
| 4906 | fn markOutdatedDecl(mod: *Module, decl: *Decl) !void { | |
| 4989 | fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { | |
| 4990 | const decl = mod.declPtr(decl_index); | |
| 4907 | 4991 | log.debug("mark outdated {*} ({s})", .{ decl, decl.name }); |
| 4908 | try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl }); | |
| 4909 | if (mod.failed_decls.fetchSwapRemove(decl)) |kv| { | |
| 4992 | try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl_index }); | |
| 4993 | if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| { | |
| 4910 | 4994 | kv.value.destroy(mod.gpa); |
| 4911 | 4995 | } |
| 4912 | 4996 | if (decl.has_tv and decl.owns_tv) { |
| ... | ... | @@ -4916,33 +5000,43 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void { |
| 4916 | 5000 | } |
| 4917 | 5001 | } |
| 4918 | 5002 | if (mod.emit_h) |emit_h| { |
| 4919 | if (emit_h.failed_decls.fetchSwapRemove(decl)) |kv| { | |
| 5003 | if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| { | |
| 4920 | 5004 | kv.value.destroy(mod.gpa); |
| 4921 | 5005 | } |
| 4922 | 5006 | } |
| 4923 | _ = mod.compile_log_decls.swapRemove(decl); | |
| 5007 | _ = mod.compile_log_decls.swapRemove(decl_index); | |
| 4924 | 5008 | decl.analysis = .outdated; |
| 4925 | 5009 | } |
| 4926 | 5010 | |
| 4927 | 5011 | pub fn allocateNewDecl( |
| 4928 | 5012 | mod: *Module, |
| 4929 | name: [:0]const u8, | |
| 4930 | 5013 | namespace: *Namespace, |
| 4931 | 5014 | src_node: Ast.Node.Index, |
| 4932 | 5015 | src_scope: ?*CaptureScope, |
| 4933 | ) !*Decl { | |
| 4934 | // If we have emit-h then we must allocate a bigger structure to store the emit-h state. | |
| 4935 | const new_decl: *Decl = if (mod.emit_h != null) blk: { | |
| 4936 | const parent_struct = try mod.gpa.create(DeclPlusEmitH); | |
| 4937 | parent_struct.* = .{ | |
| 4938 | .emit_h = .{}, | |
| 4939 | .decl = undefined, | |
| 5016 | ) !Decl.Index { | |
| 5017 | const decl_and_index: struct { | |
| 5018 | new_decl: *Decl, | |
| 5019 | decl_index: Decl.Index, | |
| 5020 | } = if (mod.decls_free_list.popOrNull()) |decl_index| d: { | |
| 5021 | break :d .{ | |
| 5022 | .new_decl = mod.declPtr(decl_index), | |
| 5023 | .decl_index = decl_index, | |
| 5024 | }; | |
| 5025 | } else d: { | |
| 5026 | const decl = try mod.allocated_decls.addOne(mod.gpa); | |
| 5027 | errdefer mod.allocated_decls.shrinkRetainingCapacity(mod.allocated_decls.len - 1); | |
| 5028 | if (mod.emit_h) |mod_emit_h| { | |
| 5029 | const decl_emit_h = try mod_emit_h.allocated_emit_h.addOne(mod.gpa); | |
| 5030 | decl_emit_h.* = .{}; | |
| 5031 | } | |
| 5032 | break :d .{ | |
| 5033 | .new_decl = decl, | |
| 5034 | .decl_index = @intToEnum(Decl.Index, mod.allocated_decls.len - 1), | |
| 4940 | 5035 | }; |
| 4941 | break :blk &parent_struct.decl; | |
| 4942 | } else try mod.gpa.create(Decl); | |
| 5036 | }; | |
| 4943 | 5037 | |
| 4944 | new_decl.* = .{ | |
| 4945 | .name = name, | |
| 5038 | decl_and_index.new_decl.* = .{ | |
| 5039 | .name = undefined, | |
| 4946 | 5040 | .src_namespace = namespace, |
| 4947 | 5041 | .src_node = src_node, |
| 4948 | 5042 | .src_line = undefined, |
| ... | ... | @@ -4986,7 +5080,7 @@ pub fn allocateNewDecl( |
| 4986 | 5080 | .is_usingnamespace = false, |
| 4987 | 5081 | }; |
| 4988 | 5082 | |
| 4989 | return new_decl; | |
| 5083 | return decl_and_index.decl_index; | |
| 4990 | 5084 | } |
| 4991 | 5085 | |
| 4992 | 5086 | /// Get error value for error tag `name`. |
| ... | ... | @@ -5010,18 +5104,9 @@ pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged |
| 5010 | 5104 | }; |
| 5011 | 5105 | } |
| 5012 | 5106 | |
| 5013 | /// Takes ownership of `name` even if it returns an error. | |
| 5014 | pub fn createAnonymousDeclNamed( | |
| 5015 | mod: *Module, | |
| 5016 | block: *Sema.Block, | |
| 5017 | typed_value: TypedValue, | |
| 5018 | name: [:0]u8, | |
| 5019 | ) !*Decl { | |
| 5020 | return mod.createAnonymousDeclFromDeclNamed(block.src_decl, block.namespace, block.wip_capture_scope, typed_value, name); | |
| 5021 | } | |
| 5022 | ||
| 5023 | pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !*Decl { | |
| 5024 | return mod.createAnonymousDeclFromDecl(block.src_decl, block.namespace, block.wip_capture_scope, typed_value); | |
| 5107 | pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index { | |
| 5108 | const src_decl = mod.declPtr(block.src_decl); | |
| 5109 | return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value); | |
| 5025 | 5110 | } |
| 5026 | 5111 | |
| 5027 | 5112 | pub fn createAnonymousDeclFromDecl( |
| ... | ... | @@ -5030,30 +5115,31 @@ pub fn createAnonymousDeclFromDecl( |
| 5030 | 5115 | namespace: *Namespace, |
| 5031 | 5116 | src_scope: ?*CaptureScope, |
| 5032 | 5117 | tv: TypedValue, |
| 5033 | ) !*Decl { | |
| 5034 | const name_index = mod.getNextAnonNameIndex(); | |
| 5118 | ) !Decl.Index { | |
| 5119 | const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope); | |
| 5120 | errdefer mod.destroyDecl(new_decl_index); | |
| 5035 | 5121 | const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ |
| 5036 | src_decl.name, name_index, | |
| 5122 | src_decl.name, @enumToInt(new_decl_index), | |
| 5037 | 5123 | }); |
| 5038 | return mod.createAnonymousDeclFromDeclNamed(src_decl, namespace, src_scope, tv, name); | |
| 5124 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name); | |
| 5125 | return new_decl_index; | |
| 5039 | 5126 | } |
| 5040 | 5127 | |
| 5041 | 5128 | /// Takes ownership of `name` even if it returns an error. |
| 5042 | pub fn createAnonymousDeclFromDeclNamed( | |
| 5129 | pub fn initNewAnonDecl( | |
| 5043 | 5130 | mod: *Module, |
| 5044 | src_decl: *Decl, | |
| 5131 | new_decl_index: Decl.Index, | |
| 5132 | src_line: u32, | |
| 5045 | 5133 | namespace: *Namespace, |
| 5046 | src_scope: ?*CaptureScope, | |
| 5047 | 5134 | typed_value: TypedValue, |
| 5048 | 5135 | name: [:0]u8, |
| 5049 | ) !*Decl { | |
| 5136 | ) !void { | |
| 5050 | 5137 | errdefer mod.gpa.free(name); |
| 5051 | 5138 | |
| 5052 | try namespace.anon_decls.ensureUnusedCapacity(mod.gpa, 1); | |
| 5139 | const new_decl = mod.declPtr(new_decl_index); | |
| 5053 | 5140 | |
| 5054 | const new_decl = try mod.allocateNewDecl(name, namespace, src_decl.src_node, src_scope); | |
| 5055 | ||
| 5056 | new_decl.src_line = src_decl.src_line; | |
| 5141 | new_decl.name = name; | |
| 5142 | new_decl.src_line = src_line; | |
| 5057 | 5143 | new_decl.ty = typed_value.ty; |
| 5058 | 5144 | new_decl.val = typed_value.val; |
| 5059 | 5145 | new_decl.@"align" = 0; |
| ... | ... | @@ -5062,22 +5148,16 @@ pub fn createAnonymousDeclFromDeclNamed( |
| 5062 | 5148 | new_decl.analysis = .complete; |
| 5063 | 5149 | new_decl.generation = mod.generation; |
| 5064 | 5150 | |
| 5065 | namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {}); | |
| 5151 | try namespace.anon_decls.putNoClobber(mod.gpa, new_decl_index, {}); | |
| 5066 | 5152 | |
| 5067 | 5153 | // The Decl starts off with alive=false and the codegen backend will set alive=true |
| 5068 | 5154 | // if the Decl is referenced by an instruction or another constant. Otherwise, |
| 5069 | 5155 | // the Decl will be garbage collected by the `codegen_decl` task instead of sent |
| 5070 | 5156 | // to the linker. |
| 5071 | 5157 | if (typed_value.ty.isFnOrHasRuntimeBits()) { |
| 5072 | try mod.comp.bin_file.allocateDeclIndexes(new_decl); | |
| 5073 | try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl }); | |
| 5158 | try mod.comp.bin_file.allocateDeclIndexes(new_decl_index); | |
| 5159 | try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index }); | |
| 5074 | 5160 | } |
| 5075 | ||
| 5076 | return new_decl; | |
| 5077 | } | |
| 5078 | ||
| 5079 | pub fn getNextAnonNameIndex(mod: *Module) usize { | |
| 5080 | return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic); | |
| 5081 | 5161 | } |
| 5082 | 5162 | |
| 5083 | 5163 | pub fn makeIntType(arena: Allocator, signedness: std.builtin.Signedness, bits: u16) !Type { |
| ... | ... | @@ -5339,12 +5419,12 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void { |
| 5339 | 5419 | // for the outdated decls, but we cannot queue up the tasks until after |
| 5340 | 5420 | // we find out which ones have been deleted, otherwise there would be |
| 5341 | 5421 | // deleted Decl pointers in the work queue. |
| 5342 | var outdated_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa); | |
| 5422 | var outdated_decls = std.AutoArrayHashMap(Decl.Index, void).init(mod.gpa); | |
| 5343 | 5423 | defer outdated_decls.deinit(); |
| 5344 | 5424 | for (mod.import_table.values()) |file| { |
| 5345 | 5425 | try outdated_decls.ensureUnusedCapacity(file.outdated_decls.items.len); |
| 5346 | for (file.outdated_decls.items) |decl| { | |
| 5347 | outdated_decls.putAssumeCapacity(decl, {}); | |
| 5426 | for (file.outdated_decls.items) |decl_index| { | |
| 5427 | outdated_decls.putAssumeCapacity(decl_index, {}); | |
| 5348 | 5428 | } |
| 5349 | 5429 | file.outdated_decls.clearRetainingCapacity(); |
| 5350 | 5430 | |
| ... | ... | @@ -5356,15 +5436,16 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void { |
| 5356 | 5436 | // it may be both in this `deleted_decls` set, as well as in the |
| 5357 | 5437 | // `Module.deletion_set`. To avoid deleting it twice, we remove it from the |
| 5358 | 5438 | // deletion set at this time. |
| 5359 | for (file.deleted_decls.items) |decl| { | |
| 5439 | for (file.deleted_decls.items) |decl_index| { | |
| 5440 | const decl = mod.declPtr(decl_index); | |
| 5360 | 5441 | log.debug("deleted from source: {*} ({s})", .{ decl, decl.name }); |
| 5361 | 5442 | |
| 5362 | 5443 | // Remove from the namespace it resides in, preserving declaration order. |
| 5363 | 5444 | assert(decl.zir_decl_index != 0); |
| 5364 | _ = decl.src_namespace.decls.orderedRemoveAdapted(@as([]const u8, mem.sliceTo(decl.name, 0)), DeclAdapter{}); | |
| 5445 | _ = decl.src_namespace.decls.orderedRemoveAdapted(@as([]const u8, mem.sliceTo(decl.name, 0)), DeclAdapter{ .mod = mod }); | |
| 5365 | 5446 | |
| 5366 | try mod.clearDecl(decl, &outdated_decls); | |
| 5367 | decl.destroy(mod); | |
| 5447 | try mod.clearDecl(decl_index, &outdated_decls); | |
| 5448 | mod.destroyDecl(decl_index); | |
| 5368 | 5449 | } |
| 5369 | 5450 | file.deleted_decls.clearRetainingCapacity(); |
| 5370 | 5451 | } |
| ... | ... | @@ -5393,13 +5474,13 @@ pub fn processExports(mod: *Module) !void { |
| 5393 | 5474 | if (gop.found_existing) { |
| 5394 | 5475 | new_export.status = .failed_retryable; |
| 5395 | 5476 | try mod.failed_exports.ensureUnusedCapacity(gpa, 1); |
| 5396 | const src_loc = new_export.getSrcLoc(); | |
| 5477 | const src_loc = new_export.getSrcLoc(mod); | |
| 5397 | 5478 | const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {s}", .{ |
| 5398 | 5479 | new_export.options.name, |
| 5399 | 5480 | }); |
| 5400 | 5481 | errdefer msg.destroy(gpa); |
| 5401 | 5482 | const other_export = gop.value_ptr.*; |
| 5402 | const other_src_loc = other_export.getSrcLoc(); | |
| 5483 | const other_src_loc = other_export.getSrcLoc(mod); | |
| 5403 | 5484 | try mod.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{}); |
| 5404 | 5485 | mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg); |
| 5405 | 5486 | new_export.status = .failed; |
| ... | ... | @@ -5413,7 +5494,7 @@ pub fn processExports(mod: *Module) !void { |
| 5413 | 5494 | const new_export = exports[0]; |
| 5414 | 5495 | new_export.status = .failed_retryable; |
| 5415 | 5496 | try mod.failed_exports.ensureUnusedCapacity(gpa, 1); |
| 5416 | const src_loc = new_export.getSrcLoc(); | |
| 5497 | const src_loc = new_export.getSrcLoc(mod); | |
| 5417 | 5498 | const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{ |
| 5418 | 5499 | @errorName(err), |
| 5419 | 5500 | }); |
| ... | ... | @@ -5427,12 +5508,14 @@ pub fn populateTestFunctions(mod: *Module) !void { |
| 5427 | 5508 | const gpa = mod.gpa; |
| 5428 | 5509 | const builtin_pkg = mod.main_pkg.table.get("builtin").?; |
| 5429 | 5510 | const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; |
| 5430 | const builtin_namespace = builtin_file.root_decl.?.src_namespace; | |
| 5431 | const decl = builtin_namespace.decls.getKeyAdapted(@as([]const u8, "test_functions"), DeclAdapter{}).?; | |
| 5511 | const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?); | |
| 5512 | const builtin_namespace = root_decl.src_namespace; | |
| 5513 | const decl_index = builtin_namespace.decls.getKeyAdapted(@as([]const u8, "test_functions"), DeclAdapter{ .mod = mod }).?; | |
| 5514 | const decl = mod.declPtr(decl_index); | |
| 5432 | 5515 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 5433 | 5516 | const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); |
| 5434 | 5517 | |
| 5435 | const array_decl = d: { | |
| 5518 | const array_decl_index = d: { | |
| 5436 | 5519 | // Add mod.test_functions to an array decl then make the test_functions |
| 5437 | 5520 | // decl reference it as a slice. |
| 5438 | 5521 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| ... | ... | @@ -5440,50 +5523,52 @@ pub fn populateTestFunctions(mod: *Module) !void { |
| 5440 | 5523 | const arena = new_decl_arena.allocator(); |
| 5441 | 5524 | |
| 5442 | 5525 | const test_fn_vals = try arena.alloc(Value, mod.test_functions.count()); |
| 5443 | const array_decl = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{ | |
| 5526 | const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{ | |
| 5444 | 5527 | .ty = try Type.Tag.array.create(arena, .{ |
| 5445 | 5528 | .len = test_fn_vals.len, |
| 5446 | 5529 | .elem_type = try tmp_test_fn_ty.copy(arena), |
| 5447 | 5530 | }), |
| 5448 | 5531 | .val = try Value.Tag.aggregate.create(arena, test_fn_vals), |
| 5449 | 5532 | }); |
| 5533 | const array_decl = mod.declPtr(array_decl_index); | |
| 5450 | 5534 | |
| 5451 | 5535 | // Add a dependency on each test name and function pointer. |
| 5452 | 5536 | try array_decl.dependencies.ensureUnusedCapacity(gpa, test_fn_vals.len * 2); |
| 5453 | 5537 | |
| 5454 | for (mod.test_functions.keys()) |test_decl, i| { | |
| 5538 | for (mod.test_functions.keys()) |test_decl_index, i| { | |
| 5539 | const test_decl = mod.declPtr(test_decl_index); | |
| 5455 | 5540 | const test_name_slice = mem.sliceTo(test_decl.name, 0); |
| 5456 | const test_name_decl = n: { | |
| 5541 | const test_name_decl_index = n: { | |
| 5457 | 5542 | var name_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| 5458 | 5543 | errdefer name_decl_arena.deinit(); |
| 5459 | 5544 | const bytes = try name_decl_arena.allocator().dupe(u8, test_name_slice); |
| 5460 | const test_name_decl = try mod.createAnonymousDeclFromDecl(array_decl, array_decl.src_namespace, null, .{ | |
| 5545 | const test_name_decl_index = try mod.createAnonymousDeclFromDecl(array_decl, array_decl.src_namespace, null, .{ | |
| 5461 | 5546 | .ty = try Type.Tag.array_u8.create(name_decl_arena.allocator(), bytes.len), |
| 5462 | 5547 | .val = try Value.Tag.bytes.create(name_decl_arena.allocator(), bytes), |
| 5463 | 5548 | }); |
| 5464 | try test_name_decl.finalizeNewArena(&name_decl_arena); | |
| 5465 | break :n test_name_decl; | |
| 5549 | try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena); | |
| 5550 | break :n test_name_decl_index; | |
| 5466 | 5551 | }; |
| 5467 | array_decl.dependencies.putAssumeCapacityNoClobber(test_decl, {}); | |
| 5468 | array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl, {}); | |
| 5469 | try mod.linkerUpdateDecl(test_name_decl); | |
| 5552 | array_decl.dependencies.putAssumeCapacityNoClobber(test_decl_index, {}); | |
| 5553 | array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, {}); | |
| 5554 | try mod.linkerUpdateDecl(test_name_decl_index); | |
| 5470 | 5555 | |
| 5471 | 5556 | const field_vals = try arena.create([3]Value); |
| 5472 | 5557 | field_vals.* = .{ |
| 5473 | 5558 | try Value.Tag.slice.create(arena, .{ |
| 5474 | .ptr = try Value.Tag.decl_ref.create(arena, test_name_decl), | |
| 5559 | .ptr = try Value.Tag.decl_ref.create(arena, test_name_decl_index), | |
| 5475 | 5560 | .len = try Value.Tag.int_u64.create(arena, test_name_slice.len), |
| 5476 | 5561 | }), // name |
| 5477 | try Value.Tag.decl_ref.create(arena, test_decl), // func | |
| 5562 | try Value.Tag.decl_ref.create(arena, test_decl_index), // func | |
| 5478 | 5563 | Value.initTag(.null_value), // async_frame_size |
| 5479 | 5564 | }; |
| 5480 | 5565 | test_fn_vals[i] = try Value.Tag.aggregate.create(arena, field_vals); |
| 5481 | 5566 | } |
| 5482 | 5567 | |
| 5483 | 5568 | try array_decl.finalizeNewArena(&new_decl_arena); |
| 5484 | break :d array_decl; | |
| 5569 | break :d array_decl_index; | |
| 5485 | 5570 | }; |
| 5486 | try mod.linkerUpdateDecl(array_decl); | |
| 5571 | try mod.linkerUpdateDecl(array_decl_index); | |
| 5487 | 5572 | |
| 5488 | 5573 | { |
| 5489 | 5574 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| ... | ... | @@ -5493,7 +5578,7 @@ pub fn populateTestFunctions(mod: *Module) !void { |
| 5493 | 5578 | // This copy accesses the old Decl Type/Value so it must be done before `clearValues`. |
| 5494 | 5579 | const new_ty = try Type.Tag.const_slice.create(arena, try tmp_test_fn_ty.copy(arena)); |
| 5495 | 5580 | const new_val = try Value.Tag.slice.create(arena, .{ |
| 5496 | .ptr = try Value.Tag.decl_ref.create(arena, array_decl), | |
| 5581 | .ptr = try Value.Tag.decl_ref.create(arena, array_decl_index), | |
| 5497 | 5582 | .len = try Value.Tag.int_u64.create(arena, mod.test_functions.count()), |
| 5498 | 5583 | }); |
| 5499 | 5584 | |
| ... | ... | @@ -5506,15 +5591,17 @@ pub fn populateTestFunctions(mod: *Module) !void { |
| 5506 | 5591 | |
| 5507 | 5592 | try decl.finalizeNewArena(&new_decl_arena); |
| 5508 | 5593 | } |
| 5509 | try mod.linkerUpdateDecl(decl); | |
| 5594 | try mod.linkerUpdateDecl(decl_index); | |
| 5510 | 5595 | } |
| 5511 | 5596 | |
| 5512 | pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void { | |
| 5597 | pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void { | |
| 5513 | 5598 | const comp = mod.comp; |
| 5514 | 5599 | |
| 5515 | 5600 | if (comp.bin_file.options.emit == null) return; |
| 5516 | 5601 | |
| 5517 | comp.bin_file.updateDecl(mod, decl) catch |err| switch (err) { | |
| 5602 | const decl = mod.declPtr(decl_index); | |
| 5603 | ||
| 5604 | comp.bin_file.updateDecl(mod, decl_index) catch |err| switch (err) { | |
| 5518 | 5605 | error.OutOfMemory => return error.OutOfMemory, |
| 5519 | 5606 | error.AnalysisFail => { |
| 5520 | 5607 | decl.analysis = .codegen_failure; |
| ... | ... | @@ -5523,7 +5610,7 @@ pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void { |
| 5523 | 5610 | else => { |
| 5524 | 5611 | const gpa = mod.gpa; |
| 5525 | 5612 | try mod.failed_decls.ensureUnusedCapacity(gpa, 1); |
| 5526 | mod.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create( | |
| 5613 | mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( | |
| 5527 | 5614 | gpa, |
| 5528 | 5615 | decl.srcLoc(), |
| 5529 | 5616 | "unable to codegen: {s}", |
| ... | ... | @@ -5566,3 +5653,64 @@ fn reportRetryableFileError( |
| 5566 | 5653 | } |
| 5567 | 5654 | gop.value_ptr.* = err_msg; |
| 5568 | 5655 | } |
| 5656 | ||
| 5657 | pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void { | |
| 5658 | switch (val.tag()) { | |
| 5659 | .decl_ref_mut => return mod.markDeclIndexAlive(val.castTag(.decl_ref_mut).?.data.decl_index), | |
| 5660 | .extern_fn => return mod.markDeclIndexAlive(val.castTag(.extern_fn).?.data.owner_decl), | |
| 5661 | .function => return mod.markDeclIndexAlive(val.castTag(.function).?.data.owner_decl), | |
| 5662 | .variable => return mod.markDeclIndexAlive(val.castTag(.variable).?.data.owner_decl), | |
| 5663 | .decl_ref => return mod.markDeclIndexAlive(val.cast(Value.Payload.Decl).?.data), | |
| 5664 | ||
| 5665 | .repeated, | |
| 5666 | .eu_payload, | |
| 5667 | .opt_payload, | |
| 5668 | .empty_array_sentinel, | |
| 5669 | => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.SubValue).?.data), | |
| 5670 | ||
| 5671 | .eu_payload_ptr, | |
| 5672 | .opt_payload_ptr, | |
| 5673 | => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.PayloadPtr).?.data.container_ptr), | |
| 5674 | ||
| 5675 | .slice => { | |
| 5676 | const slice = val.cast(Value.Payload.Slice).?.data; | |
| 5677 | mod.markReferencedDeclsAlive(slice.ptr); | |
| 5678 | mod.markReferencedDeclsAlive(slice.len); | |
| 5679 | }, | |
| 5680 | ||
| 5681 | .elem_ptr => { | |
| 5682 | const elem_ptr = val.cast(Value.Payload.ElemPtr).?.data; | |
| 5683 | return mod.markReferencedDeclsAlive(elem_ptr.array_ptr); | |
| 5684 | }, | |
| 5685 | .field_ptr => { | |
| 5686 | const field_ptr = val.cast(Value.Payload.FieldPtr).?.data; | |
| 5687 | return mod.markReferencedDeclsAlive(field_ptr.container_ptr); | |
| 5688 | }, | |
| 5689 | .aggregate => { | |
| 5690 | for (val.castTag(.aggregate).?.data) |field_val| { | |
| 5691 | mod.markReferencedDeclsAlive(field_val); | |
| 5692 | } | |
| 5693 | }, | |
| 5694 | .@"union" => { | |
| 5695 | const data = val.cast(Value.Payload.Union).?.data; | |
| 5696 | mod.markReferencedDeclsAlive(data.tag); | |
| 5697 | mod.markReferencedDeclsAlive(data.val); | |
| 5698 | }, | |
| 5699 | ||
| 5700 | else => {}, | |
| 5701 | } | |
| 5702 | } | |
| 5703 | ||
| 5704 | pub fn markDeclAlive(mod: *Module, decl: *Decl) void { | |
| 5705 | if (decl.alive) return; | |
| 5706 | decl.alive = true; | |
| 5707 | ||
| 5708 | // This is the first time we are marking this Decl alive. We must | |
| 5709 | // therefore recurse into its value and mark any Decl it references | |
| 5710 | // as also alive, so that any Decl referenced does not get garbage collected. | |
| 5711 | mod.markReferencedDeclsAlive(decl.val); | |
| 5712 | } | |
| 5713 | ||
| 5714 | fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) void { | |
| 5715 | return mod.markDeclAlive(mod.declPtr(decl_index)); | |
| 5716 | } |
src/RangeSet.zig+16-16| ... | ... | @@ -1,12 +1,14 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const Order = std.math.Order; |
| 3 | const Type = @import("type.zig").Type; | |
| 4 | const Value = @import("value.zig").Value; | |
| 3 | ||
| 5 | 4 | const RangeSet = @This(); |
| 5 | const Module = @import("Module.zig"); | |
| 6 | 6 | const SwitchProngSrc = @import("Module.zig").SwitchProngSrc; |
| 7 | const Type = @import("type.zig").Type; | |
| 8 | const Value = @import("value.zig").Value; | |
| 7 | 9 | |
| 8 | 10 | ranges: std.ArrayList(Range), |
| 9 | target: std.Target, | |
| 11 | module: *Module, | |
| 10 | 12 | |
| 11 | 13 | pub const Range = struct { |
| 12 | 14 | first: Value, |
| ... | ... | @@ -14,10 +16,10 @@ pub const Range = struct { |
| 14 | 16 | src: SwitchProngSrc, |
| 15 | 17 | }; |
| 16 | 18 | |
| 17 | pub fn init(allocator: std.mem.Allocator, target: std.Target) RangeSet { | |
| 19 | pub fn init(allocator: std.mem.Allocator, module: *Module) RangeSet { | |
| 18 | 20 | return .{ |
| 19 | 21 | .ranges = std.ArrayList(Range).init(allocator), |
| 20 | .target = target, | |
| 22 | .module = module, | |
| 21 | 23 | }; |
| 22 | 24 | } |
| 23 | 25 | |
| ... | ... | @@ -32,11 +34,9 @@ pub fn add( |
| 32 | 34 | ty: Type, |
| 33 | 35 | src: SwitchProngSrc, |
| 34 | 36 | ) !?SwitchProngSrc { |
| 35 | const target = self.target; | |
| 36 | ||
| 37 | 37 | for (self.ranges.items) |range| { |
| 38 | if (last.compare(.gte, range.first, ty, target) and | |
| 39 | first.compare(.lte, range.last, ty, target)) | |
| 38 | if (last.compare(.gte, range.first, ty, self.module) and | |
| 39 | first.compare(.lte, range.last, ty, self.module)) | |
| 40 | 40 | { |
| 41 | 41 | return range.src; // They overlap. |
| 42 | 42 | } |
| ... | ... | @@ -49,26 +49,24 @@ pub fn add( |
| 49 | 49 | return null; |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | const LessThanContext = struct { ty: Type, target: std.Target }; | |
| 52 | const LessThanContext = struct { ty: Type, module: *Module }; | |
| 53 | 53 | |
| 54 | 54 | /// Assumes a and b do not overlap |
| 55 | 55 | fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool { |
| 56 | return a.first.compare(.lt, b.first, ctx.ty, ctx.target); | |
| 56 | return a.first.compare(.lt, b.first, ctx.ty, ctx.module); | |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool { |
| 60 | 60 | if (self.ranges.items.len == 0) |
| 61 | 61 | return false; |
| 62 | 62 | |
| 63 | const target = self.target; | |
| 64 | ||
| 65 | 63 | std.sort.sort(Range, self.ranges.items, LessThanContext{ |
| 66 | 64 | .ty = ty, |
| 67 | .target = target, | |
| 65 | .module = self.module, | |
| 68 | 66 | }, lessThan); |
| 69 | 67 | |
| 70 | if (!self.ranges.items[0].first.eql(first, ty, target) or | |
| 71 | !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, target)) | |
| 68 | if (!self.ranges.items[0].first.eql(first, ty, self.module) or | |
| 69 | !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, self.module)) | |
| 72 | 70 | { |
| 73 | 71 | return false; |
| 74 | 72 | } |
| ... | ... | @@ -78,6 +76,8 @@ pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool { |
| 78 | 76 | var counter = try std.math.big.int.Managed.init(self.ranges.allocator); |
| 79 | 77 | defer counter.deinit(); |
| 80 | 78 | |
| 79 | const target = self.module.getTarget(); | |
| 80 | ||
| 81 | 81 | // look for gaps |
| 82 | 82 | for (self.ranges.items[1..]) |cur, i| { |
| 83 | 83 | // i starts counting from the second item. |
src/Sema.zig+780-784| ... | ... | @@ -24,6 +24,7 @@ inst_map: InstMap = .{}, |
| 24 | 24 | /// and `src_decl` of `Block` is the `Decl` of the callee. |
| 25 | 25 | /// This `Decl` owns the arena memory of this `Sema`. |
| 26 | 26 | owner_decl: *Decl, |
| 27 | owner_decl_index: Decl.Index, | |
| 27 | 28 | /// For an inline or comptime function call, this will be the root parent function |
| 28 | 29 | /// which contains the callsite. Corresponds to `owner_decl`. |
| 29 | 30 | owner_func: ?*Module.Fn, |
| ... | ... | @@ -47,7 +48,7 @@ comptime_break_inst: Zir.Inst.Index = undefined, |
| 47 | 48 | /// access to the source location set by the previous instruction which did |
| 48 | 49 | /// contain a mapped source location. |
| 49 | 50 | src: LazySrcLoc = .{ .token_offset = 0 }, |
| 50 | decl_val_table: std.AutoHashMapUnmanaged(*Decl, Air.Inst.Ref) = .{}, | |
| 51 | decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{}, | |
| 51 | 52 | /// When doing a generic function instantiation, this array collects a |
| 52 | 53 | /// `Value` object for each parameter that is comptime known and thus elided |
| 53 | 54 | /// from the generated function. This memory is allocated by a parent `Sema` and |
| ... | ... | @@ -111,10 +112,6 @@ pub const Block = struct { |
| 111 | 112 | parent: ?*Block, |
| 112 | 113 | /// Shared among all child blocks. |
| 113 | 114 | sema: *Sema, |
| 114 | /// This Decl is the Decl according to the Zig source code corresponding to this Block. | |
| 115 | /// This can vary during inline or comptime function calls. See `Sema.owner_decl` | |
| 116 | /// for the one that will be the same for all Block instances. | |
| 117 | src_decl: *Decl, | |
| 118 | 115 | /// The namespace to use for lookups from this source block |
| 119 | 116 | /// When analyzing fields, this is different from src_decl.src_namepsace. |
| 120 | 117 | namespace: *Namespace, |
| ... | ... | @@ -130,6 +127,10 @@ pub const Block = struct { |
| 130 | 127 | /// If runtime_index is not 0 then one of these is guaranteed to be non null. |
| 131 | 128 | runtime_cond: ?LazySrcLoc = null, |
| 132 | 129 | runtime_loop: ?LazySrcLoc = null, |
| 130 | /// This Decl is the Decl according to the Zig source code corresponding to this Block. | |
| 131 | /// This can vary during inline or comptime function calls. See `Sema.owner_decl` | |
| 132 | /// for the one that will be the same for all Block instances. | |
| 133 | src_decl: Decl.Index, | |
| 133 | 134 | /// Non zero if a non-inline loop or a runtime conditional have been encountered. |
| 134 | 135 | /// Stores to to comptime variables are only allowed when var.runtime_index <= runtime_index. |
| 135 | 136 | runtime_index: u32 = 0, |
| ... | ... | @@ -512,20 +513,21 @@ pub const Block = struct { |
| 512 | 513 | } |
| 513 | 514 | |
| 514 | 515 | /// `alignment` value of 0 means to use ABI alignment. |
| 515 | pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u32) !*Decl { | |
| 516 | pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u32) !Decl.Index { | |
| 516 | 517 | const sema = wad.block.sema; |
| 517 | 518 | // Do this ahead of time because `createAnonymousDecl` depends on calling |
| 518 | 519 | // `type.hasRuntimeBits()`. |
| 519 | 520 | _ = try sema.typeHasRuntimeBits(wad.block, wad.src, ty); |
| 520 | const new_decl = try sema.mod.createAnonymousDecl(wad.block, .{ | |
| 521 | const new_decl_index = try sema.mod.createAnonymousDecl(wad.block, .{ | |
| 521 | 522 | .ty = ty, |
| 522 | 523 | .val = val, |
| 523 | 524 | }); |
| 525 | const new_decl = sema.mod.declPtr(new_decl_index); | |
| 524 | 526 | new_decl.@"align" = alignment; |
| 525 | errdefer sema.mod.abortAnonDecl(new_decl); | |
| 527 | errdefer sema.mod.abortAnonDecl(new_decl_index); | |
| 526 | 528 | try new_decl.finalizeNewArena(&wad.new_decl_arena); |
| 527 | 529 | wad.finished = true; |
| 528 | return new_decl; | |
| 530 | return new_decl_index; | |
| 529 | 531 | } |
| 530 | 532 | }; |
| 531 | 533 | }; |
| ... | ... | @@ -676,7 +678,7 @@ fn analyzeBodyInner( |
| 676 | 678 | crash_info.setBodyIndex(i); |
| 677 | 679 | const inst = body[i]; |
| 678 | 680 | std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{ |
| 679 | block.src_decl.src_namespace.file_scope.sub_file_path, inst, | |
| 681 | sema.mod.declPtr(block.src_decl).src_namespace.file_scope.sub_file_path, inst, | |
| 680 | 682 | }); |
| 681 | 683 | const air_inst: Air.Inst.Ref = switch (tags[inst]) { |
| 682 | 684 | // zig fmt: off |
| ... | ... | @@ -1383,8 +1385,7 @@ pub fn resolveConstString( |
| 1383 | 1385 | const wanted_type = Type.initTag(.const_slice_u8); |
| 1384 | 1386 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 1385 | 1387 | const val = try sema.resolveConstValue(block, src, coerced_inst); |
| 1386 | const target = sema.mod.getTarget(); | |
| 1387 | return val.toAllocatedBytes(wanted_type, sema.arena, target); | |
| 1388 | return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod); | |
| 1388 | 1389 | } |
| 1389 | 1390 | |
| 1390 | 1391 | pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { |
| ... | ... | @@ -1538,28 +1539,24 @@ fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileErro |
| 1538 | 1539 | } |
| 1539 | 1540 | |
| 1540 | 1541 | fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError { |
| 1541 | const target = sema.mod.getTarget(); | |
| 1542 | 1542 | return sema.fail(block, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{ |
| 1543 | lhs_ty.fmt(target), rhs_ty.fmt(target), | |
| 1543 | lhs_ty.fmt(sema.mod), rhs_ty.fmt(sema.mod), | |
| 1544 | 1544 | }); |
| 1545 | 1545 | } |
| 1546 | 1546 | |
| 1547 | 1547 | fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, optional_ty: Type) CompileError { |
| 1548 | const target = sema.mod.getTarget(); | |
| 1549 | return sema.fail(block, src, "expected optional type, found {}", .{optional_ty.fmt(target)}); | |
| 1548 | return sema.fail(block, src, "expected optional type, found {}", .{optional_ty.fmt(sema.mod)}); | |
| 1550 | 1549 | } |
| 1551 | 1550 | |
| 1552 | 1551 | fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { |
| 1553 | const target = sema.mod.getTarget(); | |
| 1554 | 1552 | return sema.fail(block, src, "type '{}' does not support array initialization syntax", .{ |
| 1555 | ty.fmt(target), | |
| 1553 | ty.fmt(sema.mod), | |
| 1556 | 1554 | }); |
| 1557 | 1555 | } |
| 1558 | 1556 | |
| 1559 | 1557 | fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { |
| 1560 | const target = sema.mod.getTarget(); | |
| 1561 | 1558 | return sema.fail(block, src, "type '{}' does not support struct initialization syntax", .{ |
| 1562 | ty.fmt(target), | |
| 1559 | ty.fmt(sema.mod), | |
| 1563 | 1560 | }); |
| 1564 | 1561 | } |
| 1565 | 1562 | |
| ... | ... | @@ -1570,9 +1567,8 @@ fn failWithErrorSetCodeMissing( |
| 1570 | 1567 | dest_err_set_ty: Type, |
| 1571 | 1568 | src_err_set_ty: Type, |
| 1572 | 1569 | ) CompileError { |
| 1573 | const target = sema.mod.getTarget(); | |
| 1574 | 1570 | return sema.fail(block, src, "expected type '{}', found type '{}'", .{ |
| 1575 | dest_err_set_ty.fmt(target), src_err_set_ty.fmt(target), | |
| 1571 | dest_err_set_ty.fmt(sema.mod), src_err_set_ty.fmt(sema.mod), | |
| 1576 | 1572 | }); |
| 1577 | 1573 | } |
| 1578 | 1574 | |
| ... | ... | @@ -1586,7 +1582,9 @@ fn errNote( |
| 1586 | 1582 | comptime format: []const u8, |
| 1587 | 1583 | args: anytype, |
| 1588 | 1584 | ) error{OutOfMemory}!void { |
| 1589 | return sema.mod.errNoteNonLazy(src.toSrcLoc(block.src_decl), parent, format, args); | |
| 1585 | const mod = sema.mod; | |
| 1586 | const src_decl = mod.declPtr(block.src_decl); | |
| 1587 | return mod.errNoteNonLazy(src.toSrcLoc(src_decl), parent, format, args); | |
| 1590 | 1588 | } |
| 1591 | 1589 | |
| 1592 | 1590 | fn addFieldErrNote( |
| ... | ... | @@ -1598,10 +1596,12 @@ fn addFieldErrNote( |
| 1598 | 1596 | comptime format: []const u8, |
| 1599 | 1597 | args: anytype, |
| 1600 | 1598 | ) !void { |
| 1601 | const decl = container_ty.getOwnerDecl(); | |
| 1599 | const mod = sema.mod; | |
| 1600 | const decl_index = container_ty.getOwnerDecl(); | |
| 1601 | const decl = mod.declPtr(decl_index); | |
| 1602 | 1602 | const tree = try sema.getAstTree(block); |
| 1603 | 1603 | const field_src = enumFieldSrcLoc(decl, tree.*, container_ty.getNodeOffset(), field_index); |
| 1604 | try sema.mod.errNoteNonLazy(field_src.toSrcLoc(decl), parent, format, args); | |
| 1604 | try mod.errNoteNonLazy(field_src.toSrcLoc(decl), parent, format, args); | |
| 1605 | 1605 | } |
| 1606 | 1606 | |
| 1607 | 1607 | fn errMsg( |
| ... | ... | @@ -1611,7 +1611,9 @@ fn errMsg( |
| 1611 | 1611 | comptime format: []const u8, |
| 1612 | 1612 | args: anytype, |
| 1613 | 1613 | ) error{OutOfMemory}!*Module.ErrorMsg { |
| 1614 | return Module.ErrorMsg.create(sema.gpa, src.toSrcLoc(block.src_decl), format, args); | |
| 1614 | const mod = sema.mod; | |
| 1615 | const src_decl = mod.declPtr(block.src_decl); | |
| 1616 | return Module.ErrorMsg.create(sema.gpa, src.toSrcLoc(src_decl), format, args); | |
| 1615 | 1617 | } |
| 1616 | 1618 | |
| 1617 | 1619 | pub fn fail( |
| ... | ... | @@ -1654,7 +1656,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: *Block, err_msg: *Module.ErrorMsg) |
| 1654 | 1656 | sema.owner_decl.analysis = .sema_failure; |
| 1655 | 1657 | sema.owner_decl.generation = mod.generation; |
| 1656 | 1658 | } |
| 1657 | const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl); | |
| 1659 | const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index); | |
| 1658 | 1660 | if (gop.found_existing) { |
| 1659 | 1661 | // If there are multiple errors for the same Decl, prefer the first one added. |
| 1660 | 1662 | err_msg.destroy(mod.gpa); |
| ... | ... | @@ -1756,7 +1758,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1756 | 1758 | try inferred_alloc.stored_inst_list.append(sema.arena, operand); |
| 1757 | 1759 | |
| 1758 | 1760 | try sema.requireRuntimeBlock(block, src); |
| 1759 | const ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 1761 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 1760 | 1762 | .pointee_type = pointee_ty, |
| 1761 | 1763 | .@"align" = inferred_alloc.alignment, |
| 1762 | 1764 | .@"addrspace" = addr_space, |
| ... | ... | @@ -1770,7 +1772,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1770 | 1772 | // The alloc will turn into a Decl. |
| 1771 | 1773 | var anon_decl = try block.startAnonDecl(src); |
| 1772 | 1774 | defer anon_decl.deinit(); |
| 1773 | iac.data.decl = try anon_decl.finish( | |
| 1775 | iac.data.decl_index = try anon_decl.finish( | |
| 1774 | 1776 | try pointee_ty.copy(anon_decl.arena()), |
| 1775 | 1777 | Value.undef, |
| 1776 | 1778 | iac.data.alignment, |
| ... | ... | @@ -1778,7 +1780,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1778 | 1780 | if (iac.data.alignment != 0) { |
| 1779 | 1781 | try sema.resolveTypeLayout(block, src, pointee_ty); |
| 1780 | 1782 | } |
| 1781 | const ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 1783 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 1782 | 1784 | .pointee_type = pointee_ty, |
| 1783 | 1785 | .@"align" = iac.data.alignment, |
| 1784 | 1786 | .@"addrspace" = addr_space, |
| ... | ... | @@ -1786,7 +1788,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1786 | 1788 | return sema.addConstant( |
| 1787 | 1789 | ptr_ty, |
| 1788 | 1790 | try Value.Tag.decl_ref_mut.create(sema.arena, .{ |
| 1789 | .decl = iac.data.decl, | |
| 1791 | .decl_index = iac.data.decl_index, | |
| 1790 | 1792 | .runtime_index = block.runtime_index, |
| 1791 | 1793 | }), |
| 1792 | 1794 | ); |
| ... | ... | @@ -1827,7 +1829,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1827 | 1829 | } |
| 1828 | 1830 | } |
| 1829 | 1831 | |
| 1830 | const ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 1832 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 1831 | 1833 | .pointee_type = pointee_ty, |
| 1832 | 1834 | .@"addrspace" = addr_space, |
| 1833 | 1835 | }); |
| ... | ... | @@ -1848,7 +1850,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1848 | 1850 | } |
| 1849 | 1851 | const ty_op = air_datas[trash_inst].ty_op; |
| 1850 | 1852 | const operand_ty = sema.typeOf(ty_op.operand); |
| 1851 | const ptr_operand_ty = try Type.ptr(sema.arena, target, .{ | |
| 1853 | const ptr_operand_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 1852 | 1854 | .pointee_type = operand_ty, |
| 1853 | 1855 | .@"addrspace" = addr_space, |
| 1854 | 1856 | }); |
| ... | ... | @@ -1924,18 +1926,19 @@ fn zirStructDecl( |
| 1924 | 1926 | errdefer new_decl_arena.deinit(); |
| 1925 | 1927 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 1926 | 1928 | |
| 1929 | const mod = sema.mod; | |
| 1927 | 1930 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); |
| 1928 | 1931 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); |
| 1929 | 1932 | const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); |
| 1930 | const type_name = try sema.createTypeName(block, small.name_strategy, "struct"); | |
| 1931 | const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ | |
| 1933 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 1932 | 1934 | .ty = Type.type, |
| 1933 | 1935 | .val = struct_val, |
| 1934 | }, type_name); | |
| 1936 | }, small.name_strategy, "struct"); | |
| 1937 | const new_decl = mod.declPtr(new_decl_index); | |
| 1935 | 1938 | new_decl.owns_tv = true; |
| 1936 | errdefer sema.mod.abortAnonDecl(new_decl); | |
| 1939 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 1937 | 1940 | struct_obj.* = .{ |
| 1938 | .owner_decl = new_decl, | |
| 1941 | .owner_decl = new_decl_index, | |
| 1939 | 1942 | .fields = .{}, |
| 1940 | 1943 | .node_offset = src.node_offset, |
| 1941 | 1944 | .zir_index = inst, |
| ... | ... | @@ -1953,15 +1956,23 @@ fn zirStructDecl( |
| 1953 | 1956 | }); |
| 1954 | 1957 | try sema.analyzeStructDecl(new_decl, inst, struct_obj); |
| 1955 | 1958 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 1956 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 1959 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 1957 | 1960 | } |
| 1958 | 1961 | |
| 1959 | fn createTypeName( | |
| 1962 | fn createAnonymousDeclTypeNamed( | |
| 1960 | 1963 | sema: *Sema, |
| 1961 | 1964 | block: *Block, |
| 1965 | typed_value: TypedValue, | |
| 1962 | 1966 | name_strategy: Zir.Inst.NameStrategy, |
| 1963 | 1967 | anon_prefix: []const u8, |
| 1964 | ) ![:0]u8 { | |
| 1968 | ) !Decl.Index { | |
| 1969 | const mod = sema.mod; | |
| 1970 | const namespace = block.namespace; | |
| 1971 | const src_scope = block.wip_capture_scope; | |
| 1972 | const src_decl = mod.declPtr(block.src_decl); | |
| 1973 | const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope); | |
| 1974 | errdefer mod.destroyDecl(new_decl_index); | |
| 1975 | ||
| 1965 | 1976 | switch (name_strategy) { |
| 1966 | 1977 | .anon => { |
| 1967 | 1978 | // It would be neat to have "struct:line:column" but this name has |
| ... | ... | @@ -1970,20 +1981,24 @@ fn createTypeName( |
| 1970 | 1981 | // semantically analyzed. |
| 1971 | 1982 | // This name is also used as the key in the parent namespace so it cannot be |
| 1972 | 1983 | // renamed. |
| 1973 | const name_index = sema.mod.getNextAnonNameIndex(); | |
| 1974 | return std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{ | |
| 1975 | block.src_decl.name, anon_prefix, name_index, | |
| 1984 | const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{ | |
| 1985 | src_decl.name, anon_prefix, @enumToInt(new_decl_index), | |
| 1976 | 1986 | }); |
| 1987 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | |
| 1988 | return new_decl_index; | |
| 1989 | }, | |
| 1990 | .parent => { | |
| 1991 | const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); | |
| 1992 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | |
| 1993 | return new_decl_index; | |
| 1977 | 1994 | }, |
| 1978 | .parent => return sema.gpa.dupeZ(u8, mem.sliceTo(block.src_decl.name, 0)), | |
| 1979 | 1995 | .func => { |
| 1980 | const target = sema.mod.getTarget(); | |
| 1981 | 1996 | const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst); |
| 1982 | 1997 | const zir_tags = sema.code.instructions.items(.tag); |
| 1983 | 1998 | |
| 1984 | 1999 | var buf = std.ArrayList(u8).init(sema.gpa); |
| 1985 | 2000 | defer buf.deinit(); |
| 1986 | try buf.appendSlice(mem.sliceTo(block.src_decl.name, 0)); | |
| 2001 | try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); | |
| 1987 | 2002 | try buf.appendSlice("("); |
| 1988 | 2003 | |
| 1989 | 2004 | var arg_i: usize = 0; |
| ... | ... | @@ -1995,7 +2010,7 @@ fn createTypeName( |
| 1995 | 2010 | const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg) catch unreachable; |
| 1996 | 2011 | |
| 1997 | 2012 | if (arg_i != 0) try buf.appendSlice(","); |
| 1998 | try buf.writer().print("{}", .{arg_val.fmtValue(sema.typeOf(arg), target)}); | |
| 2013 | try buf.writer().print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)}); | |
| 1999 | 2014 | |
| 2000 | 2015 | arg_i += 1; |
| 2001 | 2016 | continue; |
| ... | ... | @@ -2004,7 +2019,9 @@ fn createTypeName( |
| 2004 | 2019 | }; |
| 2005 | 2020 | |
| 2006 | 2021 | try buf.appendSlice(")"); |
| 2007 | return buf.toOwnedSliceSentinel(0); | |
| 2022 | const name = try buf.toOwnedSliceSentinel(0); | |
| 2023 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | |
| 2024 | return new_decl_index; | |
| 2008 | 2025 | }, |
| 2009 | 2026 | } |
| 2010 | 2027 | } |
| ... | ... | @@ -2064,16 +2081,16 @@ fn zirEnumDecl( |
| 2064 | 2081 | }; |
| 2065 | 2082 | const enum_ty = Type.initPayload(&enum_ty_payload.base); |
| 2066 | 2083 | const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty); |
| 2067 | const type_name = try sema.createTypeName(block, small.name_strategy, "enum"); | |
| 2068 | const new_decl = try mod.createAnonymousDeclNamed(block, .{ | |
| 2084 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 2069 | 2085 | .ty = Type.type, |
| 2070 | 2086 | .val = enum_val, |
| 2071 | }, type_name); | |
| 2087 | }, small.name_strategy, "enum"); | |
| 2088 | const new_decl = mod.declPtr(new_decl_index); | |
| 2072 | 2089 | new_decl.owns_tv = true; |
| 2073 | errdefer mod.abortAnonDecl(new_decl); | |
| 2090 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 2074 | 2091 | |
| 2075 | 2092 | enum_obj.* = .{ |
| 2076 | .owner_decl = new_decl, | |
| 2093 | .owner_decl = new_decl_index, | |
| 2077 | 2094 | .tag_ty = Type.@"null", |
| 2078 | 2095 | .tag_ty_inferred = true, |
| 2079 | 2096 | .fields = .{}, |
| ... | ... | @@ -2101,7 +2118,7 @@ fn zirEnumDecl( |
| 2101 | 2118 | enum_obj.tag_ty_inferred = false; |
| 2102 | 2119 | } |
| 2103 | 2120 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2104 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 2121 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 2105 | 2122 | } |
| 2106 | 2123 | extra_index += body.len; |
| 2107 | 2124 | |
| ... | ... | @@ -2116,8 +2133,13 @@ fn zirEnumDecl( |
| 2116 | 2133 | // should be the enum itself. |
| 2117 | 2134 | |
| 2118 | 2135 | const prev_owner_decl = sema.owner_decl; |
| 2136 | const prev_owner_decl_index = sema.owner_decl_index; | |
| 2119 | 2137 | sema.owner_decl = new_decl; |
| 2120 | defer sema.owner_decl = prev_owner_decl; | |
| 2138 | sema.owner_decl_index = new_decl_index; | |
| 2139 | defer { | |
| 2140 | sema.owner_decl = prev_owner_decl; | |
| 2141 | sema.owner_decl_index = prev_owner_decl_index; | |
| 2142 | } | |
| 2121 | 2143 | |
| 2122 | 2144 | const prev_owner_func = sema.owner_func; |
| 2123 | 2145 | sema.owner_func = null; |
| ... | ... | @@ -2133,7 +2155,7 @@ fn zirEnumDecl( |
| 2133 | 2155 | var enum_block: Block = .{ |
| 2134 | 2156 | .parent = null, |
| 2135 | 2157 | .sema = sema, |
| 2136 | .src_decl = new_decl, | |
| 2158 | .src_decl = new_decl_index, | |
| 2137 | 2159 | .namespace = &enum_obj.namespace, |
| 2138 | 2160 | .wip_capture_scope = wip_captures.scope, |
| 2139 | 2161 | .instructions = .{}, |
| ... | ... | @@ -2168,7 +2190,7 @@ fn zirEnumDecl( |
| 2168 | 2190 | if (any_values) { |
| 2169 | 2191 | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ |
| 2170 | 2192 | .ty = enum_obj.tag_ty, |
| 2171 | .target = target, | |
| 2193 | .mod = mod, | |
| 2172 | 2194 | }); |
| 2173 | 2195 | } |
| 2174 | 2196 | |
| ... | ... | @@ -2196,8 +2218,8 @@ fn zirEnumDecl( |
| 2196 | 2218 | const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name); |
| 2197 | 2219 | if (gop.found_existing) { |
| 2198 | 2220 | const tree = try sema.getAstTree(block); |
| 2199 | const field_src = enumFieldSrcLoc(block.src_decl, tree.*, src.node_offset, field_i); | |
| 2200 | const other_tag_src = enumFieldSrcLoc(block.src_decl, tree.*, src.node_offset, gop.index); | |
| 2221 | const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset, field_i); | |
| 2222 | const other_tag_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset, gop.index); | |
| 2201 | 2223 | const msg = msg: { |
| 2202 | 2224 | const msg = try sema.errMsg(block, field_src, "duplicate enum tag", .{}); |
| 2203 | 2225 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -2218,7 +2240,7 @@ fn zirEnumDecl( |
| 2218 | 2240 | const copied_tag_val = try tag_val.copy(new_decl_arena_allocator); |
| 2219 | 2241 | enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{ |
| 2220 | 2242 | .ty = enum_obj.tag_ty, |
| 2221 | .target = target, | |
| 2243 | .mod = mod, | |
| 2222 | 2244 | }); |
| 2223 | 2245 | } else if (any_values) { |
| 2224 | 2246 | const tag_val = if (last_tag_val) |val| |
| ... | ... | @@ -2229,13 +2251,13 @@ fn zirEnumDecl( |
| 2229 | 2251 | const copied_tag_val = try tag_val.copy(new_decl_arena_allocator); |
| 2230 | 2252 | enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{ |
| 2231 | 2253 | .ty = enum_obj.tag_ty, |
| 2232 | .target = target, | |
| 2254 | .mod = mod, | |
| 2233 | 2255 | }); |
| 2234 | 2256 | } |
| 2235 | 2257 | } |
| 2236 | 2258 | |
| 2237 | 2259 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2238 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 2260 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 2239 | 2261 | } |
| 2240 | 2262 | |
| 2241 | 2263 | fn zirUnionDecl( |
| ... | ... | @@ -2279,15 +2301,16 @@ fn zirUnionDecl( |
| 2279 | 2301 | }; |
| 2280 | 2302 | const union_ty = Type.initPayload(&union_payload.base); |
| 2281 | 2303 | const union_val = try Value.Tag.ty.create(new_decl_arena_allocator, union_ty); |
| 2282 | const type_name = try sema.createTypeName(block, small.name_strategy, "union"); | |
| 2283 | const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ | |
| 2304 | const mod = sema.mod; | |
| 2305 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 2284 | 2306 | .ty = Type.type, |
| 2285 | 2307 | .val = union_val, |
| 2286 | }, type_name); | |
| 2308 | }, small.name_strategy, "union"); | |
| 2309 | const new_decl = mod.declPtr(new_decl_index); | |
| 2287 | 2310 | new_decl.owns_tv = true; |
| 2288 | errdefer sema.mod.abortAnonDecl(new_decl); | |
| 2311 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 2289 | 2312 | union_obj.* = .{ |
| 2290 | .owner_decl = new_decl, | |
| 2313 | .owner_decl = new_decl_index, | |
| 2291 | 2314 | .tag_ty = Type.initTag(.@"null"), |
| 2292 | 2315 | .fields = .{}, |
| 2293 | 2316 | .node_offset = src.node_offset, |
| ... | ... | @@ -2304,10 +2327,10 @@ fn zirUnionDecl( |
| 2304 | 2327 | &union_obj.namespace, new_decl, new_decl.name, |
| 2305 | 2328 | }); |
| 2306 | 2329 | |
| 2307 | _ = try sema.mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl); | |
| 2330 | _ = try mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl); | |
| 2308 | 2331 | |
| 2309 | 2332 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2310 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 2333 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 2311 | 2334 | } |
| 2312 | 2335 | |
| 2313 | 2336 | fn zirOpaqueDecl( |
| ... | ... | @@ -2347,16 +2370,16 @@ fn zirOpaqueDecl( |
| 2347 | 2370 | }; |
| 2348 | 2371 | const opaque_ty = Type.initPayload(&opaque_ty_payload.base); |
| 2349 | 2372 | const opaque_val = try Value.Tag.ty.create(new_decl_arena_allocator, opaque_ty); |
| 2350 | const type_name = try sema.createTypeName(block, small.name_strategy, "opaque"); | |
| 2351 | const new_decl = try mod.createAnonymousDeclNamed(block, .{ | |
| 2373 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 2352 | 2374 | .ty = Type.type, |
| 2353 | 2375 | .val = opaque_val, |
| 2354 | }, type_name); | |
| 2376 | }, small.name_strategy, "opaque"); | |
| 2377 | const new_decl = mod.declPtr(new_decl_index); | |
| 2355 | 2378 | new_decl.owns_tv = true; |
| 2356 | errdefer mod.abortAnonDecl(new_decl); | |
| 2379 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 2357 | 2380 | |
| 2358 | 2381 | opaque_obj.* = .{ |
| 2359 | .owner_decl = new_decl, | |
| 2382 | .owner_decl = new_decl_index, | |
| 2360 | 2383 | .node_offset = src.node_offset, |
| 2361 | 2384 | .namespace = .{ |
| 2362 | 2385 | .parent = block.namespace, |
| ... | ... | @@ -2371,7 +2394,7 @@ fn zirOpaqueDecl( |
| 2371 | 2394 | extra_index = try mod.scanNamespace(&opaque_obj.namespace, extra_index, decls_len, new_decl); |
| 2372 | 2395 | |
| 2373 | 2396 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2374 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 2397 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 2375 | 2398 | } |
| 2376 | 2399 | |
| 2377 | 2400 | fn zirErrorSetDecl( |
| ... | ... | @@ -2395,13 +2418,14 @@ fn zirErrorSetDecl( |
| 2395 | 2418 | const error_set = try new_decl_arena_allocator.create(Module.ErrorSet); |
| 2396 | 2419 | const error_set_ty = try Type.Tag.error_set.create(new_decl_arena_allocator, error_set); |
| 2397 | 2420 | const error_set_val = try Value.Tag.ty.create(new_decl_arena_allocator, error_set_ty); |
| 2398 | const type_name = try sema.createTypeName(block, name_strategy, "error"); | |
| 2399 | const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ | |
| 2421 | const mod = sema.mod; | |
| 2422 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 2400 | 2423 | .ty = Type.type, |
| 2401 | 2424 | .val = error_set_val, |
| 2402 | }, type_name); | |
| 2425 | }, name_strategy, "error"); | |
| 2426 | const new_decl = mod.declPtr(new_decl_index); | |
| 2403 | 2427 | new_decl.owns_tv = true; |
| 2404 | errdefer sema.mod.abortAnonDecl(new_decl); | |
| 2428 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 2405 | 2429 | |
| 2406 | 2430 | var names = Module.ErrorSet.NameMap{}; |
| 2407 | 2431 | try names.ensureUnusedCapacity(new_decl_arena_allocator, extra.data.fields_len); |
| ... | ... | @@ -2410,7 +2434,7 @@ fn zirErrorSetDecl( |
| 2410 | 2434 | const extra_index_end = extra_index + (extra.data.fields_len * 2); |
| 2411 | 2435 | while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string |
| 2412 | 2436 | const str_index = sema.code.extra[extra_index]; |
| 2413 | const kv = try sema.mod.getErrorValue(sema.code.nullTerminatedString(str_index)); | |
| 2437 | const kv = try mod.getErrorValue(sema.code.nullTerminatedString(str_index)); | |
| 2414 | 2438 | const result = names.getOrPutAssumeCapacity(kv.key); |
| 2415 | 2439 | assert(!result.found_existing); // verified in AstGen |
| 2416 | 2440 | } |
| ... | ... | @@ -2419,12 +2443,12 @@ fn zirErrorSetDecl( |
| 2419 | 2443 | Module.ErrorSet.sortNames(&names); |
| 2420 | 2444 | |
| 2421 | 2445 | error_set.* = .{ |
| 2422 | .owner_decl = new_decl, | |
| 2446 | .owner_decl = new_decl_index, | |
| 2423 | 2447 | .node_offset = inst_data.src_node, |
| 2424 | 2448 | .names = names, |
| 2425 | 2449 | }; |
| 2426 | 2450 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 2427 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 2451 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 2428 | 2452 | } |
| 2429 | 2453 | |
| 2430 | 2454 | fn zirRetPtr( |
| ... | ... | @@ -2444,7 +2468,7 @@ fn zirRetPtr( |
| 2444 | 2468 | } |
| 2445 | 2469 | |
| 2446 | 2470 | const target = sema.mod.getTarget(); |
| 2447 | const ptr_type = try Type.ptr(sema.arena, target, .{ | |
| 2471 | const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ | |
| 2448 | 2472 | .pointee_type = sema.fn_ret_ty, |
| 2449 | 2473 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 2450 | 2474 | }); |
| ... | ... | @@ -2535,14 +2559,13 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 2535 | 2559 | else |
| 2536 | 2560 | object_ty; |
| 2537 | 2561 | |
| 2538 | const target = sema.mod.getTarget(); | |
| 2539 | 2562 | if (!array_ty.isIndexable()) { |
| 2540 | 2563 | const msg = msg: { |
| 2541 | 2564 | const msg = try sema.errMsg( |
| 2542 | 2565 | block, |
| 2543 | 2566 | src, |
| 2544 | 2567 | "type '{}' does not support indexing", |
| 2545 | .{array_ty.fmt(target)}, | |
| 2568 | .{array_ty.fmt(sema.mod)}, | |
| 2546 | 2569 | ); |
| 2547 | 2570 | errdefer msg.destroy(sema.gpa); |
| 2548 | 2571 | try sema.errNote( |
| ... | ... | @@ -2598,7 +2621,7 @@ fn zirAllocExtended( |
| 2598 | 2621 | return sema.addConstant( |
| 2599 | 2622 | inferred_alloc_ty, |
| 2600 | 2623 | try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ |
| 2601 | .decl = undefined, | |
| 2624 | .decl_index = undefined, | |
| 2602 | 2625 | .alignment = alignment, |
| 2603 | 2626 | }), |
| 2604 | 2627 | ); |
| ... | ... | @@ -2612,7 +2635,7 @@ fn zirAllocExtended( |
| 2612 | 2635 | const target = sema.mod.getTarget(); |
| 2613 | 2636 | try sema.requireRuntimeBlock(block, src); |
| 2614 | 2637 | try sema.resolveTypeLayout(block, src, var_ty); |
| 2615 | const ptr_type = try Type.ptr(sema.arena, target, .{ | |
| 2638 | const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ | |
| 2616 | 2639 | .pointee_type = var_ty, |
| 2617 | 2640 | .@"align" = alignment, |
| 2618 | 2641 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| ... | ... | @@ -2649,7 +2672,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 2649 | 2672 | const ptr_ty = sema.typeOf(ptr); |
| 2650 | 2673 | var ptr_info = ptr_ty.ptrInfo().data; |
| 2651 | 2674 | ptr_info.mutable = false; |
| 2652 | const const_ptr_ty = try Type.ptr(sema.arena, sema.mod.getTarget(), ptr_info); | |
| 2675 | const const_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); | |
| 2653 | 2676 | |
| 2654 | 2677 | if (try sema.resolveMaybeUndefVal(block, inst_data.src(), ptr)) |val| { |
| 2655 | 2678 | return sema.addConstant(const_ptr_ty, val); |
| ... | ... | @@ -2669,7 +2692,7 @@ fn zirAllocInferredComptime( |
| 2669 | 2692 | return sema.addConstant( |
| 2670 | 2693 | inferred_alloc_ty, |
| 2671 | 2694 | try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ |
| 2672 | .decl = undefined, | |
| 2695 | .decl_index = undefined, | |
| 2673 | 2696 | .alignment = 0, |
| 2674 | 2697 | }), |
| 2675 | 2698 | ); |
| ... | ... | @@ -2687,7 +2710,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 2687 | 2710 | return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src); |
| 2688 | 2711 | } |
| 2689 | 2712 | const target = sema.mod.getTarget(); |
| 2690 | const ptr_type = try Type.ptr(sema.arena, target, .{ | |
| 2713 | const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ | |
| 2691 | 2714 | .pointee_type = var_ty, |
| 2692 | 2715 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 2693 | 2716 | }); |
| ... | ... | @@ -2709,7 +2732,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 2709 | 2732 | } |
| 2710 | 2733 | try sema.validateVarType(block, ty_src, var_ty, false); |
| 2711 | 2734 | const target = sema.mod.getTarget(); |
| 2712 | const ptr_type = try Type.ptr(sema.arena, target, .{ | |
| 2735 | const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ | |
| 2713 | 2736 | .pointee_type = var_ty, |
| 2714 | 2737 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 2715 | 2738 | }); |
| ... | ... | @@ -2735,7 +2758,7 @@ fn zirAllocInferred( |
| 2735 | 2758 | return sema.addConstant( |
| 2736 | 2759 | inferred_alloc_ty, |
| 2737 | 2760 | try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ |
| 2738 | .decl = undefined, | |
| 2761 | .decl_index = undefined, | |
| 2739 | 2762 | .alignment = 0, |
| 2740 | 2763 | }), |
| 2741 | 2764 | ); |
| ... | ... | @@ -2776,11 +2799,12 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 2776 | 2799 | switch (ptr_val.tag()) { |
| 2777 | 2800 | .inferred_alloc_comptime => { |
| 2778 | 2801 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 2779 | const decl = iac.data.decl; | |
| 2780 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | |
| 2802 | const decl_index = iac.data.decl_index; | |
| 2803 | try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index); | |
| 2781 | 2804 | |
| 2805 | const decl = sema.mod.declPtr(decl_index); | |
| 2782 | 2806 | const final_elem_ty = try decl.ty.copy(sema.arena); |
| 2783 | const final_ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 2807 | const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 2784 | 2808 | .pointee_type = final_elem_ty, |
| 2785 | 2809 | .mutable = var_is_mut, |
| 2786 | 2810 | .@"align" = iac.data.alignment, |
| ... | ... | @@ -2791,11 +2815,11 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 2791 | 2815 | |
| 2792 | 2816 | if (var_is_mut) { |
| 2793 | 2817 | sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{ |
| 2794 | .decl = decl, | |
| 2818 | .decl_index = decl_index, | |
| 2795 | 2819 | .runtime_index = block.runtime_index, |
| 2796 | 2820 | }); |
| 2797 | 2821 | } else { |
| 2798 | sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, decl); | |
| 2822 | sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, decl_index); | |
| 2799 | 2823 | } |
| 2800 | 2824 | }, |
| 2801 | 2825 | .inferred_alloc => { |
| ... | ... | @@ -2803,7 +2827,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 2803 | 2827 | const peer_inst_list = inferred_alloc.data.stored_inst_list.items; |
| 2804 | 2828 | const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none); |
| 2805 | 2829 | |
| 2806 | const final_ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 2830 | const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 2807 | 2831 | .pointee_type = final_elem_ty, |
| 2808 | 2832 | .mutable = var_is_mut, |
| 2809 | 2833 | .@"align" = inferred_alloc.data.alignment, |
| ... | ... | @@ -2873,22 +2897,22 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 2873 | 2897 | if (store_op.lhs != Air.indexToRef(bitcast_inst)) break :ct; |
| 2874 | 2898 | if (air_datas[bitcast_inst].ty_op.operand != Air.indexToRef(const_inst)) break :ct; |
| 2875 | 2899 | |
| 2876 | const new_decl = d: { | |
| 2900 | const new_decl_index = d: { | |
| 2877 | 2901 | var anon_decl = try block.startAnonDecl(src); |
| 2878 | 2902 | defer anon_decl.deinit(); |
| 2879 | const new_decl = try anon_decl.finish( | |
| 2903 | const new_decl_index = try anon_decl.finish( | |
| 2880 | 2904 | try final_elem_ty.copy(anon_decl.arena()), |
| 2881 | 2905 | try store_val.copy(anon_decl.arena()), |
| 2882 | 2906 | inferred_alloc.data.alignment, |
| 2883 | 2907 | ); |
| 2884 | break :d new_decl; | |
| 2908 | break :d new_decl_index; | |
| 2885 | 2909 | }; |
| 2886 | try sema.mod.declareDeclDependency(sema.owner_decl, new_decl); | |
| 2910 | try sema.mod.declareDeclDependency(sema.owner_decl_index, new_decl_index); | |
| 2887 | 2911 | |
| 2888 | 2912 | // Even though we reuse the constant instruction, we still remove it from the |
| 2889 | 2913 | // block so that codegen does not see it. |
| 2890 | 2914 | block.instructions.shrinkRetainingCapacity(block.instructions.items.len - 3); |
| 2891 | sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl); | |
| 2915 | sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl_index); | |
| 2892 | 2916 | // if bitcast ty ref needs to be made const, make_ptr_const |
| 2893 | 2917 | // ZIR handles it later, so we can just use the ty ref here. |
| 2894 | 2918 | air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty; |
| ... | ... | @@ -3218,10 +3242,11 @@ fn validateStructInit( |
| 3218 | 3242 | } |
| 3219 | 3243 | |
| 3220 | 3244 | if (root_msg) |msg| { |
| 3221 | const fqn = try struct_obj.getFullyQualifiedName(gpa); | |
| 3245 | const mod = sema.mod; | |
| 3246 | const fqn = try struct_obj.getFullyQualifiedName(mod); | |
| 3222 | 3247 | defer gpa.free(fqn); |
| 3223 | try sema.mod.errNoteNonLazy( | |
| 3224 | struct_obj.srcLoc(), | |
| 3248 | try mod.errNoteNonLazy( | |
| 3249 | struct_obj.srcLoc(mod), | |
| 3225 | 3250 | msg, |
| 3226 | 3251 | "struct '{s}' declared here", |
| 3227 | 3252 | .{fqn}, |
| ... | ... | @@ -3325,10 +3350,10 @@ fn validateStructInit( |
| 3325 | 3350 | } |
| 3326 | 3351 | |
| 3327 | 3352 | if (root_msg) |msg| { |
| 3328 | const fqn = try struct_obj.getFullyQualifiedName(gpa); | |
| 3353 | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); | |
| 3329 | 3354 | defer gpa.free(fqn); |
| 3330 | 3355 | try sema.mod.errNoteNonLazy( |
| 3331 | struct_obj.srcLoc(), | |
| 3356 | struct_obj.srcLoc(sema.mod), | |
| 3332 | 3357 | msg, |
| 3333 | 3358 | "struct '{s}' declared here", |
| 3334 | 3359 | .{fqn}, |
| ... | ... | @@ -3497,9 +3522,8 @@ fn failWithBadMemberAccess( |
| 3497 | 3522 | else => unreachable, |
| 3498 | 3523 | }; |
| 3499 | 3524 | const msg = msg: { |
| 3500 | const target = sema.mod.getTarget(); | |
| 3501 | 3525 | const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{s}'", .{ |
| 3502 | kw_name, agg_ty.fmt(target), field_name, | |
| 3526 | kw_name, agg_ty.fmt(sema.mod), field_name, | |
| 3503 | 3527 | }); |
| 3504 | 3528 | errdefer msg.destroy(sema.gpa); |
| 3505 | 3529 | try sema.addDeclaredHereNote(msg, agg_ty); |
| ... | ... | @@ -3517,7 +3541,7 @@ fn failWithBadStructFieldAccess( |
| 3517 | 3541 | ) CompileError { |
| 3518 | 3542 | const gpa = sema.gpa; |
| 3519 | 3543 | |
| 3520 | const fqn = try struct_obj.getFullyQualifiedName(gpa); | |
| 3544 | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); | |
| 3521 | 3545 | defer gpa.free(fqn); |
| 3522 | 3546 | |
| 3523 | 3547 | const msg = msg: { |
| ... | ... | @@ -3528,7 +3552,7 @@ fn failWithBadStructFieldAccess( |
| 3528 | 3552 | .{ field_name, fqn }, |
| 3529 | 3553 | ); |
| 3530 | 3554 | errdefer msg.destroy(gpa); |
| 3531 | try sema.mod.errNoteNonLazy(struct_obj.srcLoc(), msg, "struct declared here", .{}); | |
| 3555 | try sema.mod.errNoteNonLazy(struct_obj.srcLoc(sema.mod), msg, "struct declared here", .{}); | |
| 3532 | 3556 | break :msg msg; |
| 3533 | 3557 | }; |
| 3534 | 3558 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | ... | @@ -3543,7 +3567,7 @@ fn failWithBadUnionFieldAccess( |
| 3543 | 3567 | ) CompileError { |
| 3544 | 3568 | const gpa = sema.gpa; |
| 3545 | 3569 | |
| 3546 | const fqn = try union_obj.getFullyQualifiedName(gpa); | |
| 3570 | const fqn = try union_obj.getFullyQualifiedName(sema.mod); | |
| 3547 | 3571 | defer gpa.free(fqn); |
| 3548 | 3572 | |
| 3549 | 3573 | const msg = msg: { |
| ... | ... | @@ -3554,14 +3578,14 @@ fn failWithBadUnionFieldAccess( |
| 3554 | 3578 | .{ field_name, fqn }, |
| 3555 | 3579 | ); |
| 3556 | 3580 | errdefer msg.destroy(gpa); |
| 3557 | try sema.mod.errNoteNonLazy(union_obj.srcLoc(), msg, "union declared here", .{}); | |
| 3581 | try sema.mod.errNoteNonLazy(union_obj.srcLoc(sema.mod), msg, "union declared here", .{}); | |
| 3558 | 3582 | break :msg msg; |
| 3559 | 3583 | }; |
| 3560 | 3584 | return sema.failWithOwnedErrorMsg(block, msg); |
| 3561 | 3585 | } |
| 3562 | 3586 | |
| 3563 | 3587 | fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void { |
| 3564 | const src_loc = decl_ty.declSrcLocOrNull() orelse return; | |
| 3588 | const src_loc = decl_ty.declSrcLocOrNull(sema.mod) orelse return; | |
| 3565 | 3589 | const category = switch (decl_ty.zigTypeTag()) { |
| 3566 | 3590 | .Union => "union", |
| 3567 | 3591 | .Struct => "struct", |
| ... | ... | @@ -3645,7 +3669,7 @@ fn storeToInferredAlloc( |
| 3645 | 3669 | try inferred_alloc.data.stored_inst_list.append(sema.arena, operand); |
| 3646 | 3670 | // Create a runtime bitcast instruction with exactly the type the pointer wants. |
| 3647 | 3671 | const target = sema.mod.getTarget(); |
| 3648 | const ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 3672 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 3649 | 3673 | .pointee_type = operand_ty, |
| 3650 | 3674 | .@"align" = inferred_alloc.data.alignment, |
| 3651 | 3675 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| ... | ... | @@ -3670,7 +3694,7 @@ fn storeToInferredAllocComptime( |
| 3670 | 3694 | } |
| 3671 | 3695 | var anon_decl = try block.startAnonDecl(src); |
| 3672 | 3696 | defer anon_decl.deinit(); |
| 3673 | iac.data.decl = try anon_decl.finish( | |
| 3697 | iac.data.decl_index = try anon_decl.finish( | |
| 3674 | 3698 | try operand_ty.copy(anon_decl.arena()), |
| 3675 | 3699 | try operand_val.copy(anon_decl.arena()), |
| 3676 | 3700 | iac.data.alignment, |
| ... | ... | @@ -3869,7 +3893,6 @@ fn zirCompileLog( |
| 3869 | 3893 | const src_node = extra.data.src_node; |
| 3870 | 3894 | const src: LazySrcLoc = .{ .node_offset = src_node }; |
| 3871 | 3895 | const args = sema.code.refSlice(extra.end, extended.small); |
| 3872 | const target = sema.mod.getTarget(); | |
| 3873 | 3896 | |
| 3874 | 3897 | for (args) |arg_ref, i| { |
| 3875 | 3898 | if (i != 0) try writer.print(", ", .{}); |
| ... | ... | @@ -3878,15 +3901,15 @@ fn zirCompileLog( |
| 3878 | 3901 | const arg_ty = sema.typeOf(arg); |
| 3879 | 3902 | if (try sema.resolveMaybeUndefVal(block, src, arg)) |val| { |
| 3880 | 3903 | try writer.print("@as({}, {})", .{ |
| 3881 | arg_ty.fmt(target), val.fmtValue(arg_ty, target), | |
| 3904 | arg_ty.fmt(sema.mod), val.fmtValue(arg_ty, sema.mod), | |
| 3882 | 3905 | }); |
| 3883 | 3906 | } else { |
| 3884 | try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(target)}); | |
| 3907 | try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(sema.mod)}); | |
| 3885 | 3908 | } |
| 3886 | 3909 | } |
| 3887 | 3910 | try writer.print("\n", .{}); |
| 3888 | 3911 | |
| 3889 | const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, sema.owner_decl); | |
| 3912 | const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, sema.owner_decl_index); | |
| 3890 | 3913 | if (!gop.found_existing) { |
| 3891 | 3914 | gop.value_ptr.* = src_node; |
| 3892 | 3915 | } |
| ... | ... | @@ -3996,7 +4019,8 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 3996 | 4019 | // Ignore the result, all the relevant operations have written to c_import_buf already. |
| 3997 | 4020 | _ = try sema.analyzeBodyBreak(&child_block, body); |
| 3998 | 4021 | |
| 3999 | const c_import_res = sema.mod.comp.cImport(c_import_buf.items) catch |err| | |
| 4022 | const mod = sema.mod; | |
| 4023 | const c_import_res = mod.comp.cImport(c_import_buf.items) catch |err| | |
| 4000 | 4024 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 4001 | 4025 | |
| 4002 | 4026 | if (c_import_res.errors.len != 0) { |
| ... | ... | @@ -4004,12 +4028,12 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 4004 | 4028 | const msg = try sema.errMsg(&child_block, src, "C import failed", .{}); |
| 4005 | 4029 | errdefer msg.destroy(sema.gpa); |
| 4006 | 4030 | |
| 4007 | if (!sema.mod.comp.bin_file.options.link_libc) | |
| 4031 | if (!mod.comp.bin_file.options.link_libc) | |
| 4008 | 4032 | try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{}); |
| 4009 | 4033 | |
| 4010 | 4034 | for (c_import_res.errors) |_| { |
| 4011 | 4035 | // TODO integrate with LazySrcLoc |
| 4012 | // try sema.mod.errNoteNonLazy(.{}, msg, "{s}", .{clang_err.msg_ptr[0..clang_err.msg_len]}); | |
| 4036 | // try mod.errNoteNonLazy(.{}, msg, "{s}", .{clang_err.msg_ptr[0..clang_err.msg_len]}); | |
| 4013 | 4037 | // if (clang_err.filename_ptr) |p| p[0..clang_err.filename_len] else "(no file)", |
| 4014 | 4038 | // clang_err.line + 1, |
| 4015 | 4039 | // clang_err.column + 1, |
| ... | ... | @@ -4027,20 +4051,21 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 4027 | 4051 | error.OutOfMemory => return error.OutOfMemory, |
| 4028 | 4052 | else => unreachable, // we pass null for root_src_dir_path |
| 4029 | 4053 | }; |
| 4030 | const std_pkg = sema.mod.main_pkg.table.get("std").?; | |
| 4031 | const builtin_pkg = sema.mod.main_pkg.table.get("builtin").?; | |
| 4054 | const std_pkg = mod.main_pkg.table.get("std").?; | |
| 4055 | const builtin_pkg = mod.main_pkg.table.get("builtin").?; | |
| 4032 | 4056 | try c_import_pkg.add(sema.gpa, "builtin", builtin_pkg); |
| 4033 | 4057 | try c_import_pkg.add(sema.gpa, "std", std_pkg); |
| 4034 | 4058 | |
| 4035 | const result = sema.mod.importPkg(c_import_pkg) catch |err| | |
| 4059 | const result = mod.importPkg(c_import_pkg) catch |err| | |
| 4036 | 4060 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 4037 | 4061 | |
| 4038 | sema.mod.astGenFile(result.file) catch |err| | |
| 4062 | mod.astGenFile(result.file) catch |err| | |
| 4039 | 4063 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 4040 | 4064 | |
| 4041 | try sema.mod.semaFile(result.file); | |
| 4042 | const file_root_decl = result.file.root_decl.?; | |
| 4043 | try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl); | |
| 4065 | try mod.semaFile(result.file); | |
| 4066 | const file_root_decl_index = result.file.root_decl.unwrap().?; | |
| 4067 | const file_root_decl = mod.declPtr(file_root_decl_index); | |
| 4068 | try mod.declareDeclDependency(sema.owner_decl_index, file_root_decl_index); | |
| 4044 | 4069 | return sema.addConstant(file_root_decl.ty, file_root_decl.val); |
| 4045 | 4070 | } |
| 4046 | 4071 | |
| ... | ... | @@ -4139,6 +4164,7 @@ fn analyzeBlockBody( |
| 4139 | 4164 | defer tracy.end(); |
| 4140 | 4165 | |
| 4141 | 4166 | const gpa = sema.gpa; |
| 4167 | const mod = sema.mod; | |
| 4142 | 4168 | |
| 4143 | 4169 | // Blocks must terminate with noreturn instruction. |
| 4144 | 4170 | assert(child_block.instructions.items.len != 0); |
| ... | ... | @@ -4173,16 +4199,16 @@ fn analyzeBlockBody( |
| 4173 | 4199 | |
| 4174 | 4200 | const type_src = src; // TODO: better source location |
| 4175 | 4201 | const valid_rt = try sema.validateRunTimeType(child_block, type_src, resolved_ty, false); |
| 4176 | const target = sema.mod.getTarget(); | |
| 4177 | 4202 | if (!valid_rt) { |
| 4178 | 4203 | const msg = msg: { |
| 4179 | const msg = try sema.errMsg(child_block, type_src, "value with comptime only type '{}' depends on runtime control flow", .{resolved_ty.fmt(target)}); | |
| 4204 | const msg = try sema.errMsg(child_block, type_src, "value with comptime only type '{}' depends on runtime control flow", .{resolved_ty.fmt(mod)}); | |
| 4180 | 4205 | errdefer msg.destroy(sema.gpa); |
| 4181 | 4206 | |
| 4182 | 4207 | const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?; |
| 4183 | 4208 | try sema.errNote(child_block, runtime_src, msg, "runtime control flow here", .{}); |
| 4184 | 4209 | |
| 4185 | try sema.explainWhyTypeIsComptime(child_block, type_src, msg, type_src.toSrcLoc(child_block.src_decl), resolved_ty); | |
| 4210 | const child_src_decl = mod.declPtr(child_block.src_decl); | |
| 4211 | try sema.explainWhyTypeIsComptime(child_block, type_src, msg, type_src.toSrcLoc(child_src_decl), resolved_ty); | |
| 4186 | 4212 | |
| 4187 | 4213 | break :msg msg; |
| 4188 | 4214 | }; |
| ... | ... | @@ -4204,7 +4230,7 @@ fn analyzeBlockBody( |
| 4204 | 4230 | const br_operand = sema.air_instructions.items(.data)[br].br.operand; |
| 4205 | 4231 | const br_operand_src = src; |
| 4206 | 4232 | const br_operand_ty = sema.typeOf(br_operand); |
| 4207 | if (br_operand_ty.eql(resolved_ty, target)) { | |
| 4233 | if (br_operand_ty.eql(resolved_ty, mod)) { | |
| 4208 | 4234 | // No type coercion needed. |
| 4209 | 4235 | continue; |
| 4210 | 4236 | } |
| ... | ... | @@ -4262,9 +4288,9 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 4262 | 4288 | if (extra.namespace != .none) { |
| 4263 | 4289 | return sema.fail(block, src, "TODO: implement exporting with field access", .{}); |
| 4264 | 4290 | } |
| 4265 | const decl = try sema.lookupIdentifier(block, operand_src, decl_name); | |
| 4291 | const decl_index = try sema.lookupIdentifier(block, operand_src, decl_name); | |
| 4266 | 4292 | const options = try sema.resolveExportOptions(block, options_src, extra.options); |
| 4267 | try sema.analyzeExport(block, src, options, decl); | |
| 4293 | try sema.analyzeExport(block, src, options, decl_index); | |
| 4268 | 4294 | } |
| 4269 | 4295 | |
| 4270 | 4296 | fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | ... | @@ -4278,11 +4304,11 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 4278 | 4304 | const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 4279 | 4305 | const operand = try sema.resolveInstConst(block, operand_src, extra.operand); |
| 4280 | 4306 | const options = try sema.resolveExportOptions(block, options_src, extra.options); |
| 4281 | const decl = switch (operand.val.tag()) { | |
| 4307 | const decl_index = switch (operand.val.tag()) { | |
| 4282 | 4308 | .function => operand.val.castTag(.function).?.data.owner_decl, |
| 4283 | 4309 | else => return sema.fail(block, operand_src, "TODO implement exporting arbitrary Value objects", .{}), // TODO put this Value into an anonymous Decl and then export it. |
| 4284 | 4310 | }; |
| 4285 | try sema.analyzeExport(block, src, options, decl); | |
| 4311 | try sema.analyzeExport(block, src, options, decl_index); | |
| 4286 | 4312 | } |
| 4287 | 4313 | |
| 4288 | 4314 | pub fn analyzeExport( |
| ... | ... | @@ -4290,18 +4316,18 @@ pub fn analyzeExport( |
| 4290 | 4316 | block: *Block, |
| 4291 | 4317 | src: LazySrcLoc, |
| 4292 | 4318 | borrowed_options: std.builtin.ExportOptions, |
| 4293 | exported_decl: *Decl, | |
| 4319 | exported_decl_index: Decl.Index, | |
| 4294 | 4320 | ) !void { |
| 4295 | 4321 | const Export = Module.Export; |
| 4296 | 4322 | const mod = sema.mod; |
| 4297 | const target = mod.getTarget(); | |
| 4298 | 4323 | |
| 4299 | try mod.ensureDeclAnalyzed(exported_decl); | |
| 4324 | try mod.ensureDeclAnalyzed(exported_decl_index); | |
| 4325 | const exported_decl = mod.declPtr(exported_decl_index); | |
| 4300 | 4326 | // TODO run the same checks as we do for C ABI struct fields |
| 4301 | 4327 | switch (exported_decl.ty.zigTypeTag()) { |
| 4302 | 4328 | .Fn, .Int, .Enum, .Struct, .Union, .Array, .Float => {}, |
| 4303 | 4329 | else => return sema.fail(block, src, "unable to export type '{}'", .{ |
| 4304 | exported_decl.ty.fmt(target), | |
| 4330 | exported_decl.ty.fmt(sema.mod), | |
| 4305 | 4331 | }), |
| 4306 | 4332 | } |
| 4307 | 4333 | |
| ... | ... | @@ -4319,13 +4345,6 @@ pub fn analyzeExport( |
| 4319 | 4345 | const section: ?[]const u8 = if (borrowed_options.section) |s| try gpa.dupe(u8, s) else null; |
| 4320 | 4346 | errdefer if (section) |s| gpa.free(s); |
| 4321 | 4347 | |
| 4322 | const src_decl = block.src_decl; | |
| 4323 | const owner_decl = sema.owner_decl; | |
| 4324 | ||
| 4325 | log.debug("exporting Decl '{s}' as symbol '{s}' from Decl '{s}'", .{ | |
| 4326 | exported_decl.name, symbol_name, owner_decl.name, | |
| 4327 | }); | |
| 4328 | ||
| 4329 | 4348 | new_export.* = .{ |
| 4330 | 4349 | .options = .{ |
| 4331 | 4350 | .name = symbol_name, |
| ... | ... | @@ -4343,14 +4362,14 @@ pub fn analyzeExport( |
| 4343 | 4362 | .spirv => .{ .spirv = {} }, |
| 4344 | 4363 | .nvptx => .{ .nvptx = {} }, |
| 4345 | 4364 | }, |
| 4346 | .owner_decl = owner_decl, | |
| 4347 | .src_decl = src_decl, | |
| 4348 | .exported_decl = exported_decl, | |
| 4365 | .owner_decl = sema.owner_decl_index, | |
| 4366 | .src_decl = block.src_decl, | |
| 4367 | .exported_decl = exported_decl_index, | |
| 4349 | 4368 | .status = .in_progress, |
| 4350 | 4369 | }; |
| 4351 | 4370 | |
| 4352 | 4371 | // Add to export_owners table. |
| 4353 | const eo_gop = mod.export_owners.getOrPutAssumeCapacity(owner_decl); | |
| 4372 | const eo_gop = mod.export_owners.getOrPutAssumeCapacity(sema.owner_decl_index); | |
| 4354 | 4373 | if (!eo_gop.found_existing) { |
| 4355 | 4374 | eo_gop.value_ptr.* = &[0]*Export{}; |
| 4356 | 4375 | } |
| ... | ... | @@ -4359,7 +4378,7 @@ pub fn analyzeExport( |
| 4359 | 4378 | errdefer eo_gop.value_ptr.* = gpa.shrink(eo_gop.value_ptr.*, eo_gop.value_ptr.len - 1); |
| 4360 | 4379 | |
| 4361 | 4380 | // Add to exported_decl table. |
| 4362 | const de_gop = mod.decl_exports.getOrPutAssumeCapacity(exported_decl); | |
| 4381 | const de_gop = mod.decl_exports.getOrPutAssumeCapacity(exported_decl_index); | |
| 4363 | 4382 | if (!de_gop.found_existing) { |
| 4364 | 4383 | de_gop.value_ptr.* = &[0]*Export{}; |
| 4365 | 4384 | } |
| ... | ... | @@ -4381,7 +4400,8 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 4381 | 4400 | const func = sema.owner_func orelse |
| 4382 | 4401 | return sema.fail(block, src, "@setAlignStack outside function body", .{}); |
| 4383 | 4402 | |
| 4384 | switch (func.owner_decl.ty.fnCallingConvention()) { | |
| 4403 | const fn_owner_decl = sema.mod.declPtr(func.owner_decl); | |
| 4404 | switch (fn_owner_decl.ty.fnCallingConvention()) { | |
| 4385 | 4405 | .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), |
| 4386 | 4406 | .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}), |
| 4387 | 4407 | else => {}, |
| ... | ... | @@ -4561,8 +4581,8 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 4561 | 4581 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; |
| 4562 | 4582 | const src = inst_data.src(); |
| 4563 | 4583 | const decl_name = inst_data.get(sema.code); |
| 4564 | const decl = try sema.lookupIdentifier(block, src, decl_name); | |
| 4565 | return sema.analyzeDeclRef(decl); | |
| 4584 | const decl_index = try sema.lookupIdentifier(block, src, decl_name); | |
| 4585 | return sema.analyzeDeclRef(decl_index); | |
| 4566 | 4586 | } |
| 4567 | 4587 | |
| 4568 | 4588 | fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -4573,11 +4593,11 @@ fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 4573 | 4593 | return sema.analyzeDeclVal(block, src, decl); |
| 4574 | 4594 | } |
| 4575 | 4595 | |
| 4576 | fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: []const u8) !*Decl { | |
| 4596 | fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: []const u8) !Decl.Index { | |
| 4577 | 4597 | var namespace = block.namespace; |
| 4578 | 4598 | while (true) { |
| 4579 | if (try sema.lookupInNamespace(block, src, namespace, name, false)) |decl| { | |
| 4580 | return decl; | |
| 4599 | if (try sema.lookupInNamespace(block, src, namespace, name, false)) |decl_index| { | |
| 4600 | return decl_index; | |
| 4581 | 4601 | } |
| 4582 | 4602 | namespace = namespace.parent orelse break; |
| 4583 | 4603 | } |
| ... | ... | @@ -4593,12 +4613,13 @@ fn lookupInNamespace( |
| 4593 | 4613 | namespace: *Namespace, |
| 4594 | 4614 | ident_name: []const u8, |
| 4595 | 4615 | observe_usingnamespace: bool, |
| 4596 | ) CompileError!?*Decl { | |
| 4616 | ) CompileError!?Decl.Index { | |
| 4597 | 4617 | const mod = sema.mod; |
| 4598 | 4618 | |
| 4599 | const namespace_decl = namespace.getDecl(); | |
| 4619 | const namespace_decl_index = namespace.getDeclIndex(); | |
| 4620 | const namespace_decl = sema.mod.declPtr(namespace_decl_index); | |
| 4600 | 4621 | if (namespace_decl.analysis == .file_failure) { |
| 4601 | try mod.declareDeclDependency(sema.owner_decl, namespace_decl); | |
| 4622 | try mod.declareDeclDependency(sema.owner_decl_index, namespace_decl_index); | |
| 4602 | 4623 | return error.AnalysisFail; |
| 4603 | 4624 | } |
| 4604 | 4625 | |
| ... | ... | @@ -4610,7 +4631,7 @@ fn lookupInNamespace( |
| 4610 | 4631 | defer checked_namespaces.deinit(gpa); |
| 4611 | 4632 | |
| 4612 | 4633 | // Keep track of name conflicts for error notes. |
| 4613 | var candidates: std.ArrayListUnmanaged(*Decl) = .{}; | |
| 4634 | var candidates: std.ArrayListUnmanaged(Decl.Index) = .{}; | |
| 4614 | 4635 | defer candidates.deinit(gpa); |
| 4615 | 4636 | |
| 4616 | 4637 | try checked_namespaces.put(gpa, namespace, {}); |
| ... | ... | @@ -4618,23 +4639,25 @@ fn lookupInNamespace( |
| 4618 | 4639 | |
| 4619 | 4640 | while (check_i < checked_namespaces.count()) : (check_i += 1) { |
| 4620 | 4641 | const check_ns = checked_namespaces.keys()[check_i]; |
| 4621 | if (check_ns.decls.getKeyAdapted(ident_name, Module.DeclAdapter{})) |decl| { | |
| 4642 | if (check_ns.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .mod = mod })) |decl_index| { | |
| 4622 | 4643 | // Skip decls which are not marked pub, which are in a different |
| 4623 | 4644 | // file than the `a.b`/`@hasDecl` syntax. |
| 4645 | const decl = mod.declPtr(decl_index); | |
| 4624 | 4646 | if (decl.is_pub or src_file == decl.getFileScope()) { |
| 4625 | try candidates.append(gpa, decl); | |
| 4647 | try candidates.append(gpa, decl_index); | |
| 4626 | 4648 | } |
| 4627 | 4649 | } |
| 4628 | 4650 | var it = check_ns.usingnamespace_set.iterator(); |
| 4629 | 4651 | while (it.next()) |entry| { |
| 4630 | const sub_usingnamespace_decl = entry.key_ptr.*; | |
| 4652 | const sub_usingnamespace_decl_index = entry.key_ptr.*; | |
| 4653 | const sub_usingnamespace_decl = mod.declPtr(sub_usingnamespace_decl_index); | |
| 4631 | 4654 | const sub_is_pub = entry.value_ptr.*; |
| 4632 | 4655 | if (!sub_is_pub and src_file != sub_usingnamespace_decl.getFileScope()) { |
| 4633 | 4656 | // Skip usingnamespace decls which are not marked pub, which are in |
| 4634 | 4657 | // a different file than the `a.b`/`@hasDecl` syntax. |
| 4635 | 4658 | continue; |
| 4636 | 4659 | } |
| 4637 | try sema.ensureDeclAnalyzed(sub_usingnamespace_decl); | |
| 4660 | try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index); | |
| 4638 | 4661 | const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data; |
| 4639 | 4662 | const sub_ns = ns_ty.getNamespace().?; |
| 4640 | 4663 | try checked_namespaces.put(gpa, sub_ns, {}); |
| ... | ... | @@ -4644,15 +4667,16 @@ fn lookupInNamespace( |
| 4644 | 4667 | switch (candidates.items.len) { |
| 4645 | 4668 | 0 => {}, |
| 4646 | 4669 | 1 => { |
| 4647 | const decl = candidates.items[0]; | |
| 4648 | try mod.declareDeclDependency(sema.owner_decl, decl); | |
| 4649 | return decl; | |
| 4670 | const decl_index = candidates.items[0]; | |
| 4671 | try mod.declareDeclDependency(sema.owner_decl_index, decl_index); | |
| 4672 | return decl_index; | |
| 4650 | 4673 | }, |
| 4651 | 4674 | else => { |
| 4652 | 4675 | const msg = msg: { |
| 4653 | 4676 | const msg = try sema.errMsg(block, src, "ambiguous reference", .{}); |
| 4654 | 4677 | errdefer msg.destroy(gpa); |
| 4655 | for (candidates.items) |candidate| { | |
| 4678 | for (candidates.items) |candidate_index| { | |
| 4679 | const candidate = mod.declPtr(candidate_index); | |
| 4656 | 4680 | const src_loc = candidate.srcLoc(); |
| 4657 | 4681 | try mod.errNoteNonLazy(src_loc, msg, "declared here", .{}); |
| 4658 | 4682 | } |
| ... | ... | @@ -4661,9 +4685,9 @@ fn lookupInNamespace( |
| 4661 | 4685 | return sema.failWithOwnedErrorMsg(block, msg); |
| 4662 | 4686 | }, |
| 4663 | 4687 | } |
| 4664 | } else if (namespace.decls.getKeyAdapted(ident_name, Module.DeclAdapter{})) |decl| { | |
| 4665 | try mod.declareDeclDependency(sema.owner_decl, decl); | |
| 4666 | return decl; | |
| 4688 | } else if (namespace.decls.getKeyAdapted(ident_name, Module.DeclAdapter{ .mod = mod })) |decl_index| { | |
| 4689 | try mod.declareDeclDependency(sema.owner_decl_index, decl_index); | |
| 4690 | return decl_index; | |
| 4667 | 4691 | } |
| 4668 | 4692 | |
| 4669 | 4693 | log.debug("{*} ({s}) depends on non-existence of '{s}' in {*} ({s})", .{ |
| ... | ... | @@ -4672,7 +4696,7 @@ fn lookupInNamespace( |
| 4672 | 4696 | // TODO This dependency is too strong. Really, it should only be a dependency |
| 4673 | 4697 | // on the non-existence of `ident_name` in the namespace. We can lessen the number of |
| 4674 | 4698 | // outdated declarations by making this dependency more sophisticated. |
| 4675 | try mod.declareDeclDependency(sema.owner_decl, namespace_decl); | |
| 4699 | try mod.declareDeclDependency(sema.owner_decl_index, namespace_decl_index); | |
| 4676 | 4700 | return null; |
| 4677 | 4701 | } |
| 4678 | 4702 | |
| ... | ... | @@ -4725,13 +4749,14 @@ const GenericCallAdapter = struct { |
| 4725 | 4749 | /// Unlike comptime_args, the Type here is not always present. |
| 4726 | 4750 | /// .generic_poison is used to communicate non-anytype parameters. |
| 4727 | 4751 | comptime_tvs: []const TypedValue, |
| 4728 | target: std.Target, | |
| 4752 | module: *Module, | |
| 4729 | 4753 | |
| 4730 | 4754 | pub fn eql(ctx: @This(), adapted_key: void, other_key: *Module.Fn) bool { |
| 4731 | 4755 | _ = adapted_key; |
| 4732 | 4756 | // The generic function Decl is guaranteed to be the first dependency |
| 4733 | 4757 | // of each of its instantiations. |
| 4734 | const generic_owner_decl = other_key.owner_decl.dependencies.keys()[0]; | |
| 4758 | const other_owner_decl = ctx.module.declPtr(other_key.owner_decl); | |
| 4759 | const generic_owner_decl = other_owner_decl.dependencies.keys()[0]; | |
| 4735 | 4760 | if (ctx.generic_fn.owner_decl != generic_owner_decl) return false; |
| 4736 | 4761 | |
| 4737 | 4762 | const other_comptime_args = other_key.comptime_args.?; |
| ... | ... | @@ -4747,18 +4772,18 @@ const GenericCallAdapter = struct { |
| 4747 | 4772 | |
| 4748 | 4773 | if (this_is_anytype) { |
| 4749 | 4774 | // Both are anytype parameters. |
| 4750 | if (!this_arg.ty.eql(other_arg.ty, ctx.target)) { | |
| 4775 | if (!this_arg.ty.eql(other_arg.ty, ctx.module)) { | |
| 4751 | 4776 | return false; |
| 4752 | 4777 | } |
| 4753 | 4778 | if (this_is_comptime) { |
| 4754 | 4779 | // Both are comptime and anytype parameters with matching types. |
| 4755 | if (!this_arg.val.eql(other_arg.val, other_arg.ty, ctx.target)) { | |
| 4780 | if (!this_arg.val.eql(other_arg.val, other_arg.ty, ctx.module)) { | |
| 4756 | 4781 | return false; |
| 4757 | 4782 | } |
| 4758 | 4783 | } |
| 4759 | 4784 | } else if (this_is_comptime) { |
| 4760 | 4785 | // Both are comptime parameters but not anytype parameters. |
| 4761 | if (!this_arg.val.eql(other_arg.val, other_arg.ty, ctx.target)) { | |
| 4786 | if (!this_arg.val.eql(other_arg.val, other_arg.ty, ctx.module)) { | |
| 4762 | 4787 | return false; |
| 4763 | 4788 | } |
| 4764 | 4789 | } |
| ... | ... | @@ -4787,7 +4812,6 @@ fn analyzeCall( |
| 4787 | 4812 | const mod = sema.mod; |
| 4788 | 4813 | |
| 4789 | 4814 | const callee_ty = sema.typeOf(func); |
| 4790 | const target = sema.mod.getTarget(); | |
| 4791 | 4815 | const func_ty = func_ty: { |
| 4792 | 4816 | switch (callee_ty.zigTypeTag()) { |
| 4793 | 4817 | .Fn => break :func_ty callee_ty, |
| ... | ... | @@ -4799,7 +4823,7 @@ fn analyzeCall( |
| 4799 | 4823 | }, |
| 4800 | 4824 | else => {}, |
| 4801 | 4825 | } |
| 4802 | return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(target)}); | |
| 4826 | return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)}); | |
| 4803 | 4827 | }; |
| 4804 | 4828 | |
| 4805 | 4829 | const func_ty_info = func_ty.fnInfo(); |
| ... | ... | @@ -4891,7 +4915,7 @@ fn analyzeCall( |
| 4891 | 4915 | const result: Air.Inst.Ref = if (is_inline_call) res: { |
| 4892 | 4916 | const func_val = try sema.resolveConstValue(block, func_src, func); |
| 4893 | 4917 | const module_fn = switch (func_val.tag()) { |
| 4894 | .decl_ref => func_val.castTag(.decl_ref).?.data.val.castTag(.function).?.data, | |
| 4918 | .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data, | |
| 4895 | 4919 | .function => func_val.castTag(.function).?.data, |
| 4896 | 4920 | .extern_fn => return sema.fail(block, call_src, "{s} call of extern function", .{ |
| 4897 | 4921 | @as([]const u8, if (is_comptime_call) "comptime" else "inline"), |
| ... | ... | @@ -4922,7 +4946,8 @@ fn analyzeCall( |
| 4922 | 4946 | // In order to save a bit of stack space, directly modify Sema rather |
| 4923 | 4947 | // than create a child one. |
| 4924 | 4948 | const parent_zir = sema.code; |
| 4925 | sema.code = module_fn.owner_decl.getFileScope().zir; | |
| 4949 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 4950 | sema.code = fn_owner_decl.getFileScope().zir; | |
| 4926 | 4951 | defer sema.code = parent_zir; |
| 4927 | 4952 | |
| 4928 | 4953 | const parent_inst_map = sema.inst_map; |
| ... | ... | @@ -4936,14 +4961,14 @@ fn analyzeCall( |
| 4936 | 4961 | sema.func = module_fn; |
| 4937 | 4962 | defer sema.func = parent_func; |
| 4938 | 4963 | |
| 4939 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, module_fn.owner_decl.src_scope); | |
| 4964 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, fn_owner_decl.src_scope); | |
| 4940 | 4965 | defer wip_captures.deinit(); |
| 4941 | 4966 | |
| 4942 | 4967 | var child_block: Block = .{ |
| 4943 | 4968 | .parent = null, |
| 4944 | 4969 | .sema = sema, |
| 4945 | 4970 | .src_decl = module_fn.owner_decl, |
| 4946 | .namespace = module_fn.owner_decl.src_namespace, | |
| 4971 | .namespace = fn_owner_decl.src_namespace, | |
| 4947 | 4972 | .wip_capture_scope = wip_captures.scope, |
| 4948 | 4973 | .instructions = .{}, |
| 4949 | 4974 | .label = null, |
| ... | ... | @@ -4976,7 +5001,7 @@ fn analyzeCall( |
| 4976 | 5001 | // comptime state. |
| 4977 | 5002 | var should_memoize = true; |
| 4978 | 5003 | |
| 4979 | var new_fn_info = module_fn.owner_decl.ty.fnInfo(); | |
| 5004 | var new_fn_info = fn_owner_decl.ty.fnInfo(); | |
| 4980 | 5005 | new_fn_info.param_types = try sema.arena.alloc(Type, new_fn_info.param_types.len); |
| 4981 | 5006 | new_fn_info.comptime_params = (try sema.arena.alloc(bool, new_fn_info.param_types.len)).ptr; |
| 4982 | 5007 | |
| ... | ... | @@ -5073,7 +5098,7 @@ fn analyzeCall( |
| 5073 | 5098 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); |
| 5074 | 5099 | // Create a fresh inferred error set type for inline/comptime calls. |
| 5075 | 5100 | const fn_ret_ty = blk: { |
| 5076 | if (module_fn.hasInferredErrorSet()) { | |
| 5101 | if (module_fn.hasInferredErrorSet(mod)) { | |
| 5077 | 5102 | const node = try sema.gpa.create(Module.Fn.InferredErrorSetListNode); |
| 5078 | 5103 | node.data = .{ .func = module_fn }; |
| 5079 | 5104 | if (parent_func) |some| { |
| ... | ... | @@ -5097,7 +5122,7 @@ fn analyzeCall( |
| 5097 | 5122 | // bug generating invalid LLVM IR. |
| 5098 | 5123 | const res2: Air.Inst.Ref = res2: { |
| 5099 | 5124 | if (should_memoize and is_comptime_call) { |
| 5100 | if (mod.memoized_calls.getContext(memoized_call_key, .{ .target = target })) |result| { | |
| 5125 | if (mod.memoized_calls.getContext(memoized_call_key, .{ .module = mod })) |result| { | |
| 5101 | 5126 | const ty_inst = try sema.addType(fn_ret_ty); |
| 5102 | 5127 | try sema.air_values.append(gpa, result.val); |
| 5103 | 5128 | sema.air_instructions.set(block_inst, .{ |
| ... | ... | @@ -5150,7 +5175,13 @@ fn analyzeCall( |
| 5150 | 5175 | }; |
| 5151 | 5176 | |
| 5152 | 5177 | if (!is_comptime_call) { |
| 5153 | try sema.emitDbgInline(block, module_fn, parent_func.?, parent_func.?.owner_decl.ty, .dbg_inline_end); | |
| 5178 | try sema.emitDbgInline( | |
| 5179 | block, | |
| 5180 | module_fn, | |
| 5181 | parent_func.?, | |
| 5182 | mod.declPtr(parent_func.?.owner_decl).ty, | |
| 5183 | .dbg_inline_end, | |
| 5184 | ); | |
| 5154 | 5185 | } |
| 5155 | 5186 | |
| 5156 | 5187 | if (should_memoize and is_comptime_call) { |
| ... | ... | @@ -5172,7 +5203,7 @@ fn analyzeCall( |
| 5172 | 5203 | try mod.memoized_calls.putContext(gpa, memoized_call_key, .{ |
| 5173 | 5204 | .val = try result_val.copy(arena), |
| 5174 | 5205 | .arena = arena_allocator.state, |
| 5175 | }, .{ .target = sema.mod.getTarget() }); | |
| 5206 | }, .{ .module = mod }); | |
| 5176 | 5207 | delete_memoized_call_key = false; |
| 5177 | 5208 | } |
| 5178 | 5209 | } |
| ... | ... | @@ -5239,13 +5270,14 @@ fn instantiateGenericCall( |
| 5239 | 5270 | const func_val = try sema.resolveConstValue(block, func_src, func); |
| 5240 | 5271 | const module_fn = switch (func_val.tag()) { |
| 5241 | 5272 | .function => func_val.castTag(.function).?.data, |
| 5242 | .decl_ref => func_val.castTag(.decl_ref).?.data.val.castTag(.function).?.data, | |
| 5273 | .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data, | |
| 5243 | 5274 | else => unreachable, |
| 5244 | 5275 | }; |
| 5245 | 5276 | // Check the Module's generic function map with an adapted context, so that we |
| 5246 | 5277 | // can match against `uncasted_args` rather than doing the work below to create a |
| 5247 | 5278 | // generic Scope only to junk it if it matches an existing instantiation. |
| 5248 | const namespace = module_fn.owner_decl.src_namespace; | |
| 5279 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 5280 | const namespace = fn_owner_decl.src_namespace; | |
| 5249 | 5281 | const fn_zir = namespace.file_scope.zir; |
| 5250 | 5282 | const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); |
| 5251 | 5283 | const zir_tags = fn_zir.instructions.items(.tag); |
| ... | ... | @@ -5261,7 +5293,6 @@ fn instantiateGenericCall( |
| 5261 | 5293 | std.hash.autoHash(&hasher, @ptrToInt(module_fn)); |
| 5262 | 5294 | |
| 5263 | 5295 | const comptime_tvs = try sema.arena.alloc(TypedValue, func_ty_info.param_types.len); |
| 5264 | const target = sema.mod.getTarget(); | |
| 5265 | 5296 | |
| 5266 | 5297 | { |
| 5267 | 5298 | var i: usize = 0; |
| ... | ... | @@ -5290,9 +5321,9 @@ fn instantiateGenericCall( |
| 5290 | 5321 | const arg_src = call_src; // TODO better source location |
| 5291 | 5322 | const arg_ty = sema.typeOf(uncasted_args[i]); |
| 5292 | 5323 | const arg_val = try sema.resolveValue(block, arg_src, uncasted_args[i]); |
| 5293 | arg_val.hash(arg_ty, &hasher, target); | |
| 5324 | arg_val.hash(arg_ty, &hasher, mod); | |
| 5294 | 5325 | if (is_anytype) { |
| 5295 | arg_ty.hashWithHasher(&hasher, target); | |
| 5326 | arg_ty.hashWithHasher(&hasher, mod); | |
| 5296 | 5327 | comptime_tvs[i] = .{ |
| 5297 | 5328 | .ty = arg_ty, |
| 5298 | 5329 | .val = arg_val, |
| ... | ... | @@ -5305,7 +5336,7 @@ fn instantiateGenericCall( |
| 5305 | 5336 | } |
| 5306 | 5337 | } else if (is_anytype) { |
| 5307 | 5338 | const arg_ty = sema.typeOf(uncasted_args[i]); |
| 5308 | arg_ty.hashWithHasher(&hasher, target); | |
| 5339 | arg_ty.hashWithHasher(&hasher, mod); | |
| 5309 | 5340 | comptime_tvs[i] = .{ |
| 5310 | 5341 | .ty = arg_ty, |
| 5311 | 5342 | .val = Value.initTag(.generic_poison), |
| ... | ... | @@ -5328,7 +5359,7 @@ fn instantiateGenericCall( |
| 5328 | 5359 | .precomputed_hash = precomputed_hash, |
| 5329 | 5360 | .func_ty_info = func_ty_info, |
| 5330 | 5361 | .comptime_tvs = comptime_tvs, |
| 5331 | .target = target, | |
| 5362 | .module = mod, | |
| 5332 | 5363 | }; |
| 5333 | 5364 | const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter); |
| 5334 | 5365 | const callee = if (!gop.found_existing) callee: { |
| ... | ... | @@ -5343,37 +5374,40 @@ fn instantiateGenericCall( |
| 5343 | 5374 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); |
| 5344 | 5375 | |
| 5345 | 5376 | // Create a Decl for the new function. |
| 5346 | const src_decl = namespace.getDecl(); | |
| 5377 | const src_decl_index = namespace.getDeclIndex(); | |
| 5378 | const src_decl = mod.declPtr(src_decl_index); | |
| 5379 | const new_decl_index = try mod.allocateNewDecl(namespace, fn_owner_decl.src_node, src_decl.src_scope); | |
| 5380 | errdefer mod.destroyDecl(new_decl_index); | |
| 5381 | const new_decl = mod.declPtr(new_decl_index); | |
| 5347 | 5382 | // TODO better names for generic function instantiations |
| 5348 | const name_index = mod.getNextAnonNameIndex(); | |
| 5349 | 5383 | const decl_name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{ |
| 5350 | module_fn.owner_decl.name, name_index, | |
| 5384 | fn_owner_decl.name, @enumToInt(new_decl_index), | |
| 5351 | 5385 | }); |
| 5352 | const new_decl = try mod.allocateNewDecl(decl_name, namespace, module_fn.owner_decl.src_node, src_decl.src_scope); | |
| 5353 | errdefer new_decl.destroy(mod); | |
| 5354 | new_decl.src_line = module_fn.owner_decl.src_line; | |
| 5355 | new_decl.is_pub = module_fn.owner_decl.is_pub; | |
| 5356 | new_decl.is_exported = module_fn.owner_decl.is_exported; | |
| 5357 | new_decl.has_align = module_fn.owner_decl.has_align; | |
| 5358 | new_decl.has_linksection_or_addrspace = module_fn.owner_decl.has_linksection_or_addrspace; | |
| 5359 | new_decl.@"addrspace" = module_fn.owner_decl.@"addrspace"; | |
| 5360 | new_decl.zir_decl_index = module_fn.owner_decl.zir_decl_index; | |
| 5386 | new_decl.name = decl_name; | |
| 5387 | new_decl.src_line = fn_owner_decl.src_line; | |
| 5388 | new_decl.is_pub = fn_owner_decl.is_pub; | |
| 5389 | new_decl.is_exported = fn_owner_decl.is_exported; | |
| 5390 | new_decl.has_align = fn_owner_decl.has_align; | |
| 5391 | new_decl.has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace; | |
| 5392 | new_decl.@"addrspace" = fn_owner_decl.@"addrspace"; | |
| 5393 | new_decl.zir_decl_index = fn_owner_decl.zir_decl_index; | |
| 5361 | 5394 | new_decl.alive = true; // This Decl is called at runtime. |
| 5362 | 5395 | new_decl.analysis = .in_progress; |
| 5363 | 5396 | new_decl.generation = mod.generation; |
| 5364 | 5397 | |
| 5365 | namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {}); | |
| 5366 | errdefer assert(namespace.anon_decls.orderedRemove(new_decl)); | |
| 5398 | namespace.anon_decls.putAssumeCapacityNoClobber(new_decl_index, {}); | |
| 5399 | errdefer assert(namespace.anon_decls.orderedRemove(new_decl_index)); | |
| 5367 | 5400 | |
| 5368 | 5401 | // The generic function Decl is guaranteed to be the first dependency |
| 5369 | 5402 | // of each of its instantiations. |
| 5370 | 5403 | assert(new_decl.dependencies.keys().len == 0); |
| 5371 | try mod.declareDeclDependency(new_decl, module_fn.owner_decl); | |
| 5404 | try mod.declareDeclDependency(new_decl_index, module_fn.owner_decl); | |
| 5372 | 5405 | // Resolving the new function type below will possibly declare more decl dependencies |
| 5373 | 5406 | // and so we remove them all here in case of error. |
| 5374 | 5407 | errdefer { |
| 5375 | for (new_decl.dependencies.keys()) |dep| { | |
| 5376 | dep.removeDependant(new_decl); | |
| 5408 | for (new_decl.dependencies.keys()) |dep_index| { | |
| 5409 | const dep = mod.declPtr(dep_index); | |
| 5410 | dep.removeDependant(new_decl_index); | |
| 5377 | 5411 | } |
| 5378 | 5412 | } |
| 5379 | 5413 | |
| ... | ... | @@ -5392,6 +5426,7 @@ fn instantiateGenericCall( |
| 5392 | 5426 | .perm_arena = new_decl_arena_allocator, |
| 5393 | 5427 | .code = fn_zir, |
| 5394 | 5428 | .owner_decl = new_decl, |
| 5429 | .owner_decl_index = new_decl_index, | |
| 5395 | 5430 | .func = null, |
| 5396 | 5431 | .fn_ret_ty = Type.void, |
| 5397 | 5432 | .owner_func = null, |
| ... | ... | @@ -5407,7 +5442,7 @@ fn instantiateGenericCall( |
| 5407 | 5442 | var child_block: Block = .{ |
| 5408 | 5443 | .parent = null, |
| 5409 | 5444 | .sema = &child_sema, |
| 5410 | .src_decl = new_decl, | |
| 5445 | .src_decl = new_decl_index, | |
| 5411 | 5446 | .namespace = namespace, |
| 5412 | 5447 | .wip_capture_scope = wip_captures.scope, |
| 5413 | 5448 | .instructions = .{}, |
| ... | ... | @@ -5564,7 +5599,7 @@ fn instantiateGenericCall( |
| 5564 | 5599 | // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field |
| 5565 | 5600 | // will be populated, ensuring it will have `analyzeBody` called with the ZIR |
| 5566 | 5601 | // parameters mapped appropriately. |
| 5567 | try mod.comp.bin_file.allocateDeclIndexes(new_decl); | |
| 5602 | try mod.comp.bin_file.allocateDeclIndexes(new_decl_index); | |
| 5568 | 5603 | try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func }); |
| 5569 | 5604 | |
| 5570 | 5605 | try new_decl.finalizeNewArena(&new_decl_arena); |
| ... | ... | @@ -5577,7 +5612,7 @@ fn instantiateGenericCall( |
| 5577 | 5612 | try sema.requireRuntimeBlock(block, call_src); |
| 5578 | 5613 | |
| 5579 | 5614 | const comptime_args = callee.comptime_args.?; |
| 5580 | const new_fn_info = callee.owner_decl.ty.fnInfo(); | |
| 5615 | const new_fn_info = mod.declPtr(callee.owner_decl).ty.fnInfo(); | |
| 5581 | 5616 | const runtime_args_len = @intCast(u32, new_fn_info.param_types.len); |
| 5582 | 5617 | const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len); |
| 5583 | 5618 | { |
| ... | ... | @@ -5700,8 +5735,7 @@ fn zirArrayType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5700 | 5735 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 5701 | 5736 | const len = try sema.resolveInt(block, .unneeded, bin_inst.lhs, Type.usize); |
| 5702 | 5737 | const elem_type = try sema.resolveType(block, .unneeded, bin_inst.rhs); |
| 5703 | const target = sema.mod.getTarget(); | |
| 5704 | const array_ty = try Type.array(sema.arena, len, null, elem_type, target); | |
| 5738 | const array_ty = try Type.array(sema.arena, len, null, elem_type, sema.mod); | |
| 5705 | 5739 | |
| 5706 | 5740 | return sema.addType(array_ty); |
| 5707 | 5741 | } |
| ... | ... | @@ -5720,8 +5754,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil |
| 5720 | 5754 | const uncasted_sentinel = sema.resolveInst(extra.sentinel); |
| 5721 | 5755 | const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src); |
| 5722 | 5756 | const sentinel_val = try sema.resolveConstValue(block, sentinel_src, sentinel); |
| 5723 | const target = sema.mod.getTarget(); | |
| 5724 | const array_ty = try Type.array(sema.arena, len, sentinel_val, elem_type, target); | |
| 5757 | const array_ty = try Type.array(sema.arena, len, sentinel_val, elem_type, sema.mod); | |
| 5725 | 5758 | |
| 5726 | 5759 | return sema.addType(array_ty); |
| 5727 | 5760 | } |
| ... | ... | @@ -5748,14 +5781,13 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 5748 | 5781 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 5749 | 5782 | const error_set = try sema.resolveType(block, lhs_src, extra.lhs); |
| 5750 | 5783 | const payload = try sema.resolveType(block, rhs_src, extra.rhs); |
| 5751 | const target = sema.mod.getTarget(); | |
| 5752 | 5784 | |
| 5753 | 5785 | if (error_set.zigTypeTag() != .ErrorSet) { |
| 5754 | 5786 | return sema.fail(block, lhs_src, "expected error set type, found {}", .{ |
| 5755 | error_set.fmt(target), | |
| 5787 | error_set.fmt(sema.mod), | |
| 5756 | 5788 | }); |
| 5757 | 5789 | } |
| 5758 | const err_union_ty = try Type.errorUnion(sema.arena, error_set, payload, target); | |
| 5790 | const err_union_ty = try Type.errorUnion(sema.arena, error_set, payload, sema.mod); | |
| 5759 | 5791 | return sema.addType(err_union_ty); |
| 5760 | 5792 | } |
| 5761 | 5793 | |
| ... | ... | @@ -5862,11 +5894,10 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 5862 | 5894 | } |
| 5863 | 5895 | const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs); |
| 5864 | 5896 | const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs); |
| 5865 | const target = sema.mod.getTarget(); | |
| 5866 | 5897 | if (lhs_ty.zigTypeTag() != .ErrorSet) |
| 5867 | return sema.fail(block, lhs_src, "expected error set type, found {}", .{lhs_ty.fmt(target)}); | |
| 5898 | return sema.fail(block, lhs_src, "expected error set type, found {}", .{lhs_ty.fmt(sema.mod)}); | |
| 5868 | 5899 | if (rhs_ty.zigTypeTag() != .ErrorSet) |
| 5869 | return sema.fail(block, rhs_src, "expected error set type, found {}", .{rhs_ty.fmt(target)}); | |
| 5900 | return sema.fail(block, rhs_src, "expected error set type, found {}", .{rhs_ty.fmt(sema.mod)}); | |
| 5870 | 5901 | |
| 5871 | 5902 | // Anything merged with anyerror is anyerror. |
| 5872 | 5903 | if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror) { |
| ... | ... | @@ -5912,7 +5943,6 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5912 | 5943 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 5913 | 5944 | const operand = sema.resolveInst(inst_data.operand); |
| 5914 | 5945 | const operand_ty = sema.typeOf(operand); |
| 5915 | const target = sema.mod.getTarget(); | |
| 5916 | 5946 | |
| 5917 | 5947 | const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag()) { |
| 5918 | 5948 | .Enum => operand, |
| ... | ... | @@ -5929,7 +5959,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5929 | 5959 | }, |
| 5930 | 5960 | else => { |
| 5931 | 5961 | return sema.fail(block, operand_src, "expected enum or tagged union, found {}", .{ |
| 5932 | operand_ty.fmt(target), | |
| 5962 | operand_ty.fmt(sema.mod), | |
| 5933 | 5963 | }); |
| 5934 | 5964 | }, |
| 5935 | 5965 | }; |
| ... | ... | @@ -5953,7 +5983,6 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5953 | 5983 | } |
| 5954 | 5984 | |
| 5955 | 5985 | fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 5956 | const target = sema.mod.getTarget(); | |
| 5957 | 5986 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 5958 | 5987 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 5959 | 5988 | const src = inst_data.src(); |
| ... | ... | @@ -5963,7 +5992,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5963 | 5992 | const operand = sema.resolveInst(extra.rhs); |
| 5964 | 5993 | |
| 5965 | 5994 | if (dest_ty.zigTypeTag() != .Enum) { |
| 5966 | return sema.fail(block, dest_ty_src, "expected enum, found {}", .{dest_ty.fmt(target)}); | |
| 5995 | return sema.fail(block, dest_ty_src, "expected enum, found {}", .{dest_ty.fmt(sema.mod)}); | |
| 5967 | 5996 | } |
| 5968 | 5997 | |
| 5969 | 5998 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |int_val| { |
| ... | ... | @@ -5973,17 +6002,17 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 5973 | 6002 | if (int_val.isUndef()) { |
| 5974 | 6003 | return sema.failWithUseOfUndef(block, operand_src); |
| 5975 | 6004 | } |
| 5976 | if (!dest_ty.enumHasInt(int_val, target)) { | |
| 6005 | if (!dest_ty.enumHasInt(int_val, sema.mod)) { | |
| 5977 | 6006 | const msg = msg: { |
| 5978 | 6007 | const msg = try sema.errMsg( |
| 5979 | 6008 | block, |
| 5980 | 6009 | src, |
| 5981 | 6010 | "enum '{}' has no tag with value {}", |
| 5982 | .{ dest_ty.fmt(target), int_val.fmtValue(sema.typeOf(operand), target) }, | |
| 6011 | .{ dest_ty.fmt(sema.mod), int_val.fmtValue(sema.typeOf(operand), sema.mod) }, | |
| 5983 | 6012 | ); |
| 5984 | 6013 | errdefer msg.destroy(sema.gpa); |
| 5985 | 6014 | try sema.mod.errNoteNonLazy( |
| 5986 | dest_ty.declSrcLoc(), | |
| 6015 | dest_ty.declSrcLoc(sema.mod), | |
| 5987 | 6016 | msg, |
| 5988 | 6017 | "enum declared here", |
| 5989 | 6018 | .{}, |
| ... | ... | @@ -6028,14 +6057,13 @@ fn analyzeOptionalPayloadPtr( |
| 6028 | 6057 | const optional_ptr_ty = sema.typeOf(optional_ptr); |
| 6029 | 6058 | assert(optional_ptr_ty.zigTypeTag() == .Pointer); |
| 6030 | 6059 | |
| 6031 | const target = sema.mod.getTarget(); | |
| 6032 | 6060 | const opt_type = optional_ptr_ty.elemType(); |
| 6033 | 6061 | if (opt_type.zigTypeTag() != .Optional) { |
| 6034 | return sema.fail(block, src, "expected optional type, found {}", .{opt_type.fmt(target)}); | |
| 6062 | return sema.fail(block, src, "expected optional type, found {}", .{opt_type.fmt(sema.mod)}); | |
| 6035 | 6063 | } |
| 6036 | 6064 | |
| 6037 | 6065 | const child_type = try opt_type.optionalChildAlloc(sema.arena); |
| 6038 | const child_pointer = try Type.ptr(sema.arena, target, .{ | |
| 6066 | const child_pointer = try Type.ptr(sema.arena, sema.mod, .{ | |
| 6039 | 6067 | .pointee_type = child_type, |
| 6040 | 6068 | .mutable = !optional_ptr_ty.isConstPtr(), |
| 6041 | 6069 | .@"addrspace" = optional_ptr_ty.ptrAddressSpace(), |
| ... | ... | @@ -6106,8 +6134,7 @@ fn zirOptionalPayload( |
| 6106 | 6134 | return sema.failWithExpectedOptionalType(block, src, operand_ty); |
| 6107 | 6135 | } |
| 6108 | 6136 | const ptr_info = operand_ty.ptrInfo().data; |
| 6109 | const target = sema.mod.getTarget(); | |
| 6110 | break :t try Type.ptr(sema.arena, target, .{ | |
| 6137 | break :t try Type.ptr(sema.arena, sema.mod, .{ | |
| 6111 | 6138 | .pointee_type = try ptr_info.pointee_type.copy(sema.arena), |
| 6112 | 6139 | .@"align" = ptr_info.@"align", |
| 6113 | 6140 | .@"addrspace" = ptr_info.@"addrspace", |
| ... | ... | @@ -6154,9 +6181,8 @@ fn zirErrUnionPayload( |
| 6154 | 6181 | const operand_src = src; |
| 6155 | 6182 | const operand_ty = sema.typeOf(operand); |
| 6156 | 6183 | if (operand_ty.zigTypeTag() != .ErrorUnion) { |
| 6157 | const target = sema.mod.getTarget(); | |
| 6158 | 6184 | return sema.fail(block, operand_src, "expected error union type, found '{}'", .{ |
| 6159 | operand_ty.fmt(target), | |
| 6185 | operand_ty.fmt(sema.mod), | |
| 6160 | 6186 | }); |
| 6161 | 6187 | } |
| 6162 | 6188 | |
| ... | ... | @@ -6205,15 +6231,14 @@ fn analyzeErrUnionPayloadPtr( |
| 6205 | 6231 | const operand_ty = sema.typeOf(operand); |
| 6206 | 6232 | assert(operand_ty.zigTypeTag() == .Pointer); |
| 6207 | 6233 | |
| 6208 | const target = sema.mod.getTarget(); | |
| 6209 | 6234 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) { |
| 6210 | 6235 | return sema.fail(block, src, "expected error union type, found {}", .{ |
| 6211 | operand_ty.elemType().fmt(target), | |
| 6236 | operand_ty.elemType().fmt(sema.mod), | |
| 6212 | 6237 | }); |
| 6213 | 6238 | } |
| 6214 | 6239 | |
| 6215 | 6240 | const payload_ty = operand_ty.elemType().errorUnionPayload(); |
| 6216 | const operand_pointer_ty = try Type.ptr(sema.arena, target, .{ | |
| 6241 | const operand_pointer_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 6217 | 6242 | .pointee_type = payload_ty, |
| 6218 | 6243 | .mutable = !operand_ty.isConstPtr(), |
| 6219 | 6244 | .@"addrspace" = operand_ty.ptrAddressSpace(), |
| ... | ... | @@ -6272,10 +6297,9 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 6272 | 6297 | const src = inst_data.src(); |
| 6273 | 6298 | const operand = sema.resolveInst(inst_data.operand); |
| 6274 | 6299 | const operand_ty = sema.typeOf(operand); |
| 6275 | const target = sema.mod.getTarget(); | |
| 6276 | 6300 | if (operand_ty.zigTypeTag() != .ErrorUnion) { |
| 6277 | 6301 | return sema.fail(block, src, "expected error union type, found '{}'", .{ |
| 6278 | operand_ty.fmt(target), | |
| 6302 | operand_ty.fmt(sema.mod), | |
| 6279 | 6303 | }); |
| 6280 | 6304 | } |
| 6281 | 6305 | |
| ... | ... | @@ -6302,9 +6326,8 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 6302 | 6326 | assert(operand_ty.zigTypeTag() == .Pointer); |
| 6303 | 6327 | |
| 6304 | 6328 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) { |
| 6305 | const target = sema.mod.getTarget(); | |
| 6306 | 6329 | return sema.fail(block, src, "expected error union type, found {}", .{ |
| 6307 | operand_ty.elemType().fmt(target), | |
| 6330 | operand_ty.elemType().fmt(sema.mod), | |
| 6308 | 6331 | }); |
| 6309 | 6332 | } |
| 6310 | 6333 | |
| ... | ... | @@ -6329,10 +6352,9 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 6329 | 6352 | const src = inst_data.src(); |
| 6330 | 6353 | const operand = sema.resolveInst(inst_data.operand); |
| 6331 | 6354 | const operand_ty = sema.typeOf(operand); |
| 6332 | const target = sema.mod.getTarget(); | |
| 6333 | 6355 | if (operand_ty.zigTypeTag() != .ErrorUnion) { |
| 6334 | 6356 | return sema.fail(block, src, "expected error union type, found '{}'", .{ |
| 6335 | operand_ty.fmt(target), | |
| 6357 | operand_ty.fmt(sema.mod), | |
| 6336 | 6358 | }); |
| 6337 | 6359 | } |
| 6338 | 6360 | if (operand_ty.errorUnionPayload().zigTypeTag() != .Void) { |
| ... | ... | @@ -6606,7 +6628,7 @@ fn funcCommon( |
| 6606 | 6628 | errdefer sema.gpa.destroy(new_extern_fn); |
| 6607 | 6629 | |
| 6608 | 6630 | new_extern_fn.* = Module.ExternFn{ |
| 6609 | .owner_decl = sema.owner_decl, | |
| 6631 | .owner_decl = sema.owner_decl_index, | |
| 6610 | 6632 | .lib_name = null, |
| 6611 | 6633 | }; |
| 6612 | 6634 | |
| ... | ... | @@ -6645,7 +6667,7 @@ fn funcCommon( |
| 6645 | 6667 | new_func.* = .{ |
| 6646 | 6668 | .state = anal_state, |
| 6647 | 6669 | .zir_body_inst = func_inst, |
| 6648 | .owner_decl = sema.owner_decl, | |
| 6670 | .owner_decl = sema.owner_decl_index, | |
| 6649 | 6671 | .comptime_args = comptime_args, |
| 6650 | 6672 | .anytype_args = undefined, |
| 6651 | 6673 | .hash = hash, |
| ... | ... | @@ -6838,8 +6860,7 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 6838 | 6860 | const ptr = sema.resolveInst(inst_data.operand); |
| 6839 | 6861 | const ptr_ty = sema.typeOf(ptr); |
| 6840 | 6862 | if (!ptr_ty.isPtrAtRuntime()) { |
| 6841 | const target = sema.mod.getTarget(); | |
| 6842 | return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(target)}); | |
| 6863 | return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}); | |
| 6843 | 6864 | } |
| 6844 | 6865 | if (try sema.resolveMaybeUndefVal(block, ptr_src, ptr)) |ptr_val| { |
| 6845 | 6866 | return sema.addConstant(Type.usize, ptr_val); |
| ... | ... | @@ -7018,7 +7039,6 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 7018 | 7039 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 7019 | 7040 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 7020 | 7041 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 7021 | const target = sema.mod.getTarget(); | |
| 7022 | 7042 | |
| 7023 | 7043 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 7024 | 7044 | switch (dest_ty.zigTypeTag()) { |
| ... | ... | @@ -7038,10 +7058,10 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 7038 | 7058 | .Type, |
| 7039 | 7059 | .Undefined, |
| 7040 | 7060 | .Void, |
| 7041 | => return sema.fail(block, dest_ty_src, "invalid type '{}' for @bitCast", .{dest_ty.fmt(target)}), | |
| 7061 | => return sema.fail(block, dest_ty_src, "invalid type '{}' for @bitCast", .{dest_ty.fmt(sema.mod)}), | |
| 7042 | 7062 | |
| 7043 | 7063 | .Pointer => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}', use @ptrCast to cast to a pointer", .{ |
| 7044 | dest_ty.fmt(target), | |
| 7064 | dest_ty.fmt(sema.mod), | |
| 7045 | 7065 | }), |
| 7046 | 7066 | .Struct, .Union => if (dest_ty.containerLayout() == .Auto) { |
| 7047 | 7067 | const container = switch (dest_ty.zigTypeTag()) { |
| ... | ... | @@ -7050,7 +7070,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 7050 | 7070 | else => unreachable, |
| 7051 | 7071 | }; |
| 7052 | 7072 | return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}', {s} does not have a guaranteed in-memory layout", .{ |
| 7053 | dest_ty.fmt(target), container, | |
| 7073 | dest_ty.fmt(sema.mod), container, | |
| 7054 | 7074 | }); |
| 7055 | 7075 | }, |
| 7056 | 7076 | .BoundFn => @panic("TODO remove this type from the language and compiler"), |
| ... | ... | @@ -7088,7 +7108,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 7088 | 7108 | block, |
| 7089 | 7109 | dest_ty_src, |
| 7090 | 7110 | "expected float type, found '{}'", |
| 7091 | .{dest_ty.fmt(target)}, | |
| 7111 | .{dest_ty.fmt(sema.mod)}, | |
| 7092 | 7112 | ), |
| 7093 | 7113 | }; |
| 7094 | 7114 | |
| ... | ... | @@ -7099,7 +7119,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 7099 | 7119 | block, |
| 7100 | 7120 | operand_src, |
| 7101 | 7121 | "expected float type, found '{}'", |
| 7102 | .{operand_ty.fmt(target)}, | |
| 7122 | .{operand_ty.fmt(sema.mod)}, | |
| 7103 | 7123 | ), |
| 7104 | 7124 | } |
| 7105 | 7125 | |
| ... | ... | @@ -7241,7 +7261,6 @@ fn zirSwitchCapture( |
| 7241 | 7261 | const operand_ptr = sema.resolveInst(cond_info.operand); |
| 7242 | 7262 | const operand_ptr_ty = sema.typeOf(operand_ptr); |
| 7243 | 7263 | const operand_ty = if (operand_is_ref) operand_ptr_ty.childType() else operand_ptr_ty; |
| 7244 | const target = sema.mod.getTarget(); | |
| 7245 | 7264 | |
| 7246 | 7265 | const operand = if (operand_is_ref) |
| 7247 | 7266 | try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src) |
| ... | ... | @@ -7277,7 +7296,7 @@ fn zirSwitchCapture( |
| 7277 | 7296 | // Previous switch validation ensured this will succeed |
| 7278 | 7297 | const first_item_val = sema.resolveConstValue(block, .unneeded, first_item) catch unreachable; |
| 7279 | 7298 | |
| 7280 | const first_field_index = @intCast(u32, enum_ty.enumTagFieldIndex(first_item_val, target).?); | |
| 7299 | const first_field_index = @intCast(u32, enum_ty.enumTagFieldIndex(first_item_val, sema.mod).?); | |
| 7281 | 7300 | const first_field = union_obj.fields.values()[first_field_index]; |
| 7282 | 7301 | |
| 7283 | 7302 | for (items[1..]) |item| { |
| ... | ... | @@ -7285,16 +7304,16 @@ fn zirSwitchCapture( |
| 7285 | 7304 | // Previous switch validation ensured this will succeed |
| 7286 | 7305 | const item_val = sema.resolveConstValue(block, .unneeded, item_ref) catch unreachable; |
| 7287 | 7306 | |
| 7288 | const field_index = enum_ty.enumTagFieldIndex(item_val, target).?; | |
| 7307 | const field_index = enum_ty.enumTagFieldIndex(item_val, sema.mod).?; | |
| 7289 | 7308 | const field = union_obj.fields.values()[field_index]; |
| 7290 | if (!field.ty.eql(first_field.ty, target)) { | |
| 7309 | if (!field.ty.eql(first_field.ty, sema.mod)) { | |
| 7291 | 7310 | const first_item_src = switch_src; // TODO better source location |
| 7292 | 7311 | const item_src = switch_src; |
| 7293 | 7312 | const msg = msg: { |
| 7294 | 7313 | const msg = try sema.errMsg(block, switch_src, "capture group with incompatible types", .{}); |
| 7295 | 7314 | errdefer msg.destroy(sema.gpa); |
| 7296 | try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(target)}); | |
| 7297 | try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(target)}); | |
| 7315 | try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(sema.mod)}); | |
| 7316 | try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(sema.mod)}); | |
| 7298 | 7317 | break :msg msg; |
| 7299 | 7318 | }; |
| 7300 | 7319 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | ... | @@ -7304,7 +7323,7 @@ fn zirSwitchCapture( |
| 7304 | 7323 | if (is_ref) { |
| 7305 | 7324 | assert(operand_is_ref); |
| 7306 | 7325 | |
| 7307 | const field_ty_ptr = try Type.ptr(sema.arena, target, .{ | |
| 7326 | const field_ty_ptr = try Type.ptr(sema.arena, sema.mod, .{ | |
| 7308 | 7327 | .pointee_type = first_field.ty, |
| 7309 | 7328 | .@"addrspace" = .generic, |
| 7310 | 7329 | .mutable = operand_ptr_ty.ptrIsMutable(), |
| ... | ... | @@ -7388,7 +7407,6 @@ fn zirSwitchCond( |
| 7388 | 7407 | else |
| 7389 | 7408 | operand_ptr; |
| 7390 | 7409 | const operand_ty = sema.typeOf(operand); |
| 7391 | const target = sema.mod.getTarget(); | |
| 7392 | 7410 | |
| 7393 | 7411 | switch (operand_ty.zigTypeTag()) { |
| 7394 | 7412 | .Type, |
| ... | ... | @@ -7436,7 +7454,7 @@ fn zirSwitchCond( |
| 7436 | 7454 | .Vector, |
| 7437 | 7455 | .Frame, |
| 7438 | 7456 | .AnyFrame, |
| 7439 | => return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(target)}), | |
| 7457 | => return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 7440 | 7458 | } |
| 7441 | 7459 | } |
| 7442 | 7460 | |
| ... | ... | @@ -7588,10 +7606,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7588 | 7606 | ); |
| 7589 | 7607 | } |
| 7590 | 7608 | try sema.mod.errNoteNonLazy( |
| 7591 | operand_ty.declSrcLoc(), | |
| 7609 | operand_ty.declSrcLoc(sema.mod), | |
| 7592 | 7610 | msg, |
| 7593 | 7611 | "enum '{}' declared here", |
| 7594 | .{operand_ty.fmt(target)}, | |
| 7612 | .{operand_ty.fmt(sema.mod)}, | |
| 7595 | 7613 | ); |
| 7596 | 7614 | break :msg msg; |
| 7597 | 7615 | }; |
| ... | ... | @@ -7705,10 +7723,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7705 | 7723 | |
| 7706 | 7724 | if (maybe_msg) |msg| { |
| 7707 | 7725 | try sema.mod.errNoteNonLazy( |
| 7708 | operand_ty.declSrcLoc(), | |
| 7726 | operand_ty.declSrcLoc(sema.mod), | |
| 7709 | 7727 | msg, |
| 7710 | 7728 | "error set '{}' declared here", |
| 7711 | .{operand_ty.fmt(target)}, | |
| 7729 | .{operand_ty.fmt(sema.mod)}, | |
| 7712 | 7730 | ); |
| 7713 | 7731 | return sema.failWithOwnedErrorMsg(block, msg); |
| 7714 | 7732 | } |
| ... | ... | @@ -7738,7 +7756,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7738 | 7756 | }, |
| 7739 | 7757 | .Union => return sema.fail(block, src, "TODO validate switch .Union", .{}), |
| 7740 | 7758 | .Int, .ComptimeInt => { |
| 7741 | var range_set = RangeSet.init(gpa, target); | |
| 7759 | var range_set = RangeSet.init(gpa, sema.mod); | |
| 7742 | 7760 | defer range_set.deinit(); |
| 7743 | 7761 | |
| 7744 | 7762 | var extra_index: usize = special.end; |
| ... | ... | @@ -7914,13 +7932,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7914 | 7932 | block, |
| 7915 | 7933 | src, |
| 7916 | 7934 | "else prong required when switching on type '{}'", |
| 7917 | .{operand_ty.fmt(target)}, | |
| 7935 | .{operand_ty.fmt(sema.mod)}, | |
| 7918 | 7936 | ); |
| 7919 | 7937 | } |
| 7920 | 7938 | |
| 7921 | 7939 | var seen_values = ValueSrcMap.initContext(gpa, .{ |
| 7922 | 7940 | .ty = operand_ty, |
| 7923 | .target = target, | |
| 7941 | .mod = sema.mod, | |
| 7924 | 7942 | }); |
| 7925 | 7943 | defer seen_values.deinit(); |
| 7926 | 7944 | |
| ... | ... | @@ -7985,7 +8003,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 7985 | 8003 | .ComptimeFloat, |
| 7986 | 8004 | .Float, |
| 7987 | 8005 | => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{ |
| 7988 | operand_ty.fmt(target), | |
| 8006 | operand_ty.fmt(sema.mod), | |
| 7989 | 8007 | }), |
| 7990 | 8008 | } |
| 7991 | 8009 | |
| ... | ... | @@ -8035,7 +8053,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8035 | 8053 | const item = sema.resolveInst(item_ref); |
| 8036 | 8054 | // Validation above ensured these will succeed. |
| 8037 | 8055 | const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable; |
| 8038 | if (operand_val.eql(item_val, operand_ty, target)) { | |
| 8056 | if (operand_val.eql(item_val, operand_ty, sema.mod)) { | |
| 8039 | 8057 | return sema.resolveBlockBody(block, src, &child_block, body, inst, merges); |
| 8040 | 8058 | } |
| 8041 | 8059 | } |
| ... | ... | @@ -8057,7 +8075,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8057 | 8075 | const item = sema.resolveInst(item_ref); |
| 8058 | 8076 | // Validation above ensured these will succeed. |
| 8059 | 8077 | const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable; |
| 8060 | if (operand_val.eql(item_val, operand_ty, target)) { | |
| 8078 | if (operand_val.eql(item_val, operand_ty, sema.mod)) { | |
| 8061 | 8079 | return sema.resolveBlockBody(block, src, &child_block, body, inst, merges); |
| 8062 | 8080 | } |
| 8063 | 8081 | } |
| ... | ... | @@ -8072,8 +8090,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8072 | 8090 | // Validation above ensured these will succeed. |
| 8073 | 8091 | const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first) catch unreachable; |
| 8074 | 8092 | const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last) catch unreachable; |
| 8075 | if (Value.compare(operand_val, .gte, first_tv.val, operand_ty, target) and | |
| 8076 | Value.compare(operand_val, .lte, last_tv.val, operand_ty, target)) | |
| 8093 | if (Value.compare(operand_val, .gte, first_tv.val, operand_ty, sema.mod) and | |
| 8094 | Value.compare(operand_val, .lte, last_tv.val, operand_ty, sema.mod)) | |
| 8077 | 8095 | { |
| 8078 | 8096 | return sema.resolveBlockBody(block, src, &child_block, body, inst, merges); |
| 8079 | 8097 | } |
| ... | ... | @@ -8385,7 +8403,7 @@ fn resolveSwitchItemVal( |
| 8385 | 8403 | return TypedValue{ .ty = item_ty, .val = val }; |
| 8386 | 8404 | } else |err| switch (err) { |
| 8387 | 8405 | error.NeededSourceLocation => { |
| 8388 | const src = switch_prong_src.resolve(sema.gpa, block.src_decl, switch_node_offset, range_expand); | |
| 8406 | const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_node_offset, range_expand); | |
| 8389 | 8407 | return TypedValue{ |
| 8390 | 8408 | .ty = item_ty, |
| 8391 | 8409 | .val = try sema.resolveConstValue(block, src, item), |
| ... | ... | @@ -8434,19 +8452,18 @@ fn validateSwitchItemEnum( |
| 8434 | 8452 | switch_prong_src: Module.SwitchProngSrc, |
| 8435 | 8453 | ) CompileError!void { |
| 8436 | 8454 | const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); |
| 8437 | const target = sema.mod.getTarget(); | |
| 8438 | const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, target) orelse { | |
| 8455 | const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse { | |
| 8439 | 8456 | const msg = msg: { |
| 8440 | const src = switch_prong_src.resolve(sema.gpa, block.src_decl, src_node_offset, .none); | |
| 8457 | const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .none); | |
| 8441 | 8458 | const msg = try sema.errMsg( |
| 8442 | 8459 | block, |
| 8443 | 8460 | src, |
| 8444 | 8461 | "enum '{}' has no tag with value '{}'", |
| 8445 | .{ item_tv.ty.fmt(target), item_tv.val.fmtValue(item_tv.ty, target) }, | |
| 8462 | .{ item_tv.ty.fmt(sema.mod), item_tv.val.fmtValue(item_tv.ty, sema.mod) }, | |
| 8446 | 8463 | ); |
| 8447 | 8464 | errdefer msg.destroy(sema.gpa); |
| 8448 | 8465 | try sema.mod.errNoteNonLazy( |
| 8449 | item_tv.ty.declSrcLoc(), | |
| 8466 | item_tv.ty.declSrcLoc(sema.mod), | |
| 8450 | 8467 | msg, |
| 8451 | 8468 | "enum declared here", |
| 8452 | 8469 | .{}, |
| ... | ... | @@ -8487,8 +8504,9 @@ fn validateSwitchDupe( |
| 8487 | 8504 | ) CompileError!void { |
| 8488 | 8505 | const prev_prong_src = maybe_prev_src orelse return; |
| 8489 | 8506 | const gpa = sema.gpa; |
| 8490 | const src = switch_prong_src.resolve(gpa, block.src_decl, src_node_offset, .none); | |
| 8491 | const prev_src = prev_prong_src.resolve(gpa, block.src_decl, src_node_offset, .none); | |
| 8507 | const block_src_decl = sema.mod.declPtr(block.src_decl); | |
| 8508 | const src = switch_prong_src.resolve(gpa, block_src_decl, src_node_offset, .none); | |
| 8509 | const prev_src = prev_prong_src.resolve(gpa, block_src_decl, src_node_offset, .none); | |
| 8492 | 8510 | const msg = msg: { |
| 8493 | 8511 | const msg = try sema.errMsg( |
| 8494 | 8512 | block, |
| ... | ... | @@ -8525,7 +8543,8 @@ fn validateSwitchItemBool( |
| 8525 | 8543 | false_count.* += 1; |
| 8526 | 8544 | } |
| 8527 | 8545 | if (true_count.* + false_count.* > 2) { |
| 8528 | const src = switch_prong_src.resolve(sema.gpa, block.src_decl, src_node_offset, .none); | |
| 8546 | const block_src_decl = sema.mod.declPtr(block.src_decl); | |
| 8547 | const src = switch_prong_src.resolve(sema.gpa, block_src_decl, src_node_offset, .none); | |
| 8529 | 8548 | return sema.fail(block, src, "duplicate switch value", .{}); |
| 8530 | 8549 | } |
| 8531 | 8550 | } |
| ... | ... | @@ -8558,13 +8577,12 @@ fn validateSwitchNoRange( |
| 8558 | 8577 | const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = src_node_offset }; |
| 8559 | 8578 | const range_src: LazySrcLoc = .{ .node_offset_switch_range = src_node_offset }; |
| 8560 | 8579 | |
| 8561 | const target = sema.mod.getTarget(); | |
| 8562 | 8580 | const msg = msg: { |
| 8563 | 8581 | const msg = try sema.errMsg( |
| 8564 | 8582 | block, |
| 8565 | 8583 | operand_src, |
| 8566 | 8584 | "ranges not allowed when switching on type '{}'", |
| 8567 | .{operand_ty.fmt(target)}, | |
| 8585 | .{operand_ty.fmt(sema.mod)}, | |
| 8568 | 8586 | ); |
| 8569 | 8587 | errdefer msg.destroy(sema.gpa); |
| 8570 | 8588 | try sema.errNote( |
| ... | ... | @@ -8587,7 +8605,6 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 8587 | 8605 | const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs); |
| 8588 | 8606 | const field_name = try sema.resolveConstString(block, name_src, extra.rhs); |
| 8589 | 8607 | const ty = try sema.resolveTypeFields(block, ty_src, unresolved_ty); |
| 8590 | const target = sema.mod.getTarget(); | |
| 8591 | 8608 | |
| 8592 | 8609 | const has_field = hf: { |
| 8593 | 8610 | if (ty.isSlice()) { |
| ... | ... | @@ -8610,7 +8627,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 8610 | 8627 | .Enum => ty.enumFields().contains(field_name), |
| 8611 | 8628 | .Array => mem.eql(u8, field_name, "len"), |
| 8612 | 8629 | else => return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{ |
| 8613 | ty.fmt(target), | |
| 8630 | ty.fmt(sema.mod), | |
| 8614 | 8631 | }), |
| 8615 | 8632 | }; |
| 8616 | 8633 | }; |
| ... | ... | @@ -8633,7 +8650,8 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 8633 | 8650 | try checkNamespaceType(sema, block, lhs_src, container_type); |
| 8634 | 8651 | |
| 8635 | 8652 | const namespace = container_type.getNamespace() orelse return Air.Inst.Ref.bool_false; |
| 8636 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl| { | |
| 8653 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| { | |
| 8654 | const decl = sema.mod.declPtr(decl_index); | |
| 8637 | 8655 | if (decl.is_pub or decl.getFileScope() == block.getFileScope()) { |
| 8638 | 8656 | return Air.Inst.Ref.bool_true; |
| 8639 | 8657 | } |
| ... | ... | @@ -8661,8 +8679,9 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 8661 | 8679 | }, |
| 8662 | 8680 | }; |
| 8663 | 8681 | try mod.semaFile(result.file); |
| 8664 | const file_root_decl = result.file.root_decl.?; | |
| 8665 | try mod.declareDeclDependency(sema.owner_decl, file_root_decl); | |
| 8682 | const file_root_decl_index = result.file.root_decl.unwrap().?; | |
| 8683 | const file_root_decl = mod.declPtr(file_root_decl_index); | |
| 8684 | try mod.declareDeclDependency(sema.owner_decl_index, file_root_decl_index); | |
| 8666 | 8685 | return sema.addConstant(file_root_decl.ty, file_root_decl.val); |
| 8667 | 8686 | } |
| 8668 | 8687 | |
| ... | ... | @@ -8763,7 +8782,7 @@ fn zirShl( |
| 8763 | 8782 | } |
| 8764 | 8783 | const int_info = scalar_ty.intInfo(target); |
| 8765 | 8784 | const truncated = try shifted.intTrunc(lhs_ty, sema.arena, int_info.signedness, int_info.bits, target); |
| 8766 | if (truncated.compare(.eq, shifted, lhs_ty, target)) { | |
| 8785 | if (truncated.compare(.eq, shifted, lhs_ty, sema.mod)) { | |
| 8767 | 8786 | break :val shifted; |
| 8768 | 8787 | } |
| 8769 | 8788 | return sema.addConstUndef(lhs_ty); |
| ... | ... | @@ -8927,7 +8946,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 8927 | 8946 | |
| 8928 | 8947 | if (scalar_type.zigTypeTag() != .Int) { |
| 8929 | 8948 | return sema.fail(block, src, "unable to perform binary not operation on type '{}'", .{ |
| 8930 | operand_type.fmt(target), | |
| 8949 | operand_type.fmt(sema.mod), | |
| 8931 | 8950 | }); |
| 8932 | 8951 | } |
| 8933 | 8952 | |
| ... | ... | @@ -8939,7 +8958,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 8939 | 8958 | var elem_val_buf: Value.ElemValueBuffer = undefined; |
| 8940 | 8959 | const elems = try sema.arena.alloc(Value, vec_len); |
| 8941 | 8960 | for (elems) |*elem, i| { |
| 8942 | const elem_val = val.elemValueBuffer(i, &elem_val_buf); | |
| 8961 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_val_buf); | |
| 8943 | 8962 | elem.* = try elem_val.bitwiseNot(scalar_type, sema.arena, target); |
| 8944 | 8963 | } |
| 8945 | 8964 | return sema.addConstant( |
| ... | ... | @@ -9047,14 +9066,13 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9047 | 9066 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 9048 | 9067 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 9049 | 9068 | |
| 9050 | const target = sema.mod.getTarget(); | |
| 9051 | 9069 | const lhs_info = (try sema.getArrayCatInfo(block, lhs_src, lhs)) orelse |
| 9052 | return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty.fmt(target)}); | |
| 9070 | return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty.fmt(sema.mod)}); | |
| 9053 | 9071 | const rhs_info = (try sema.getArrayCatInfo(block, rhs_src, rhs)) orelse |
| 9054 | return sema.fail(block, rhs_src, "expected array, found '{}'", .{rhs_ty.fmt(target)}); | |
| 9055 | if (!lhs_info.elem_type.eql(rhs_info.elem_type, target)) { | |
| 9072 | return sema.fail(block, rhs_src, "expected array, found '{}'", .{rhs_ty.fmt(sema.mod)}); | |
| 9073 | if (!lhs_info.elem_type.eql(rhs_info.elem_type, sema.mod)) { | |
| 9056 | 9074 | return sema.fail(block, rhs_src, "expected array of type '{}', found '{}'", .{ |
| 9057 | lhs_info.elem_type.fmt(target), rhs_ty.fmt(target), | |
| 9075 | lhs_info.elem_type.fmt(sema.mod), rhs_ty.fmt(sema.mod), | |
| 9058 | 9076 | }); |
| 9059 | 9077 | } |
| 9060 | 9078 | |
| ... | ... | @@ -9062,7 +9080,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9062 | 9080 | // will catch this if it is a problem. |
| 9063 | 9081 | var res_sent: ?Value = null; |
| 9064 | 9082 | if (rhs_info.sentinel != null and lhs_info.sentinel != null) { |
| 9065 | if (rhs_info.sentinel.?.eql(lhs_info.sentinel.?, lhs_info.elem_type, target)) { | |
| 9083 | if (rhs_info.sentinel.?.eql(lhs_info.sentinel.?, lhs_info.elem_type, sema.mod)) { | |
| 9066 | 9084 | res_sent = lhs_info.sentinel.?; |
| 9067 | 9085 | } |
| 9068 | 9086 | } |
| ... | ... | @@ -9084,14 +9102,14 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9084 | 9102 | { |
| 9085 | 9103 | var i: usize = 0; |
| 9086 | 9104 | while (i < lhs_len) : (i += 1) { |
| 9087 | const val = try lhs_sub_val.elemValue(sema.arena, i); | |
| 9105 | const val = try lhs_sub_val.elemValue(sema.mod, sema.arena, i); | |
| 9088 | 9106 | buf[i] = try val.copy(anon_decl.arena()); |
| 9089 | 9107 | } |
| 9090 | 9108 | } |
| 9091 | 9109 | { |
| 9092 | 9110 | var i: usize = 0; |
| 9093 | 9111 | while (i < rhs_len) : (i += 1) { |
| 9094 | const val = try rhs_sub_val.elemValue(sema.arena, i); | |
| 9112 | const val = try rhs_sub_val.elemValue(sema.mod, sema.arena, i); | |
| 9095 | 9113 | buf[lhs_len + i] = try val.copy(anon_decl.arena()); |
| 9096 | 9114 | } |
| 9097 | 9115 | } |
| ... | ... | @@ -9123,7 +9141,6 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9123 | 9141 | |
| 9124 | 9142 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, inst: Air.Inst.Ref) !?Type.ArrayInfo { |
| 9125 | 9143 | const t = sema.typeOf(inst); |
| 9126 | const target = sema.mod.getTarget(); | |
| 9127 | 9144 | return switch (t.zigTypeTag()) { |
| 9128 | 9145 | .Array => t.arrayInfo(), |
| 9129 | 9146 | .Pointer => blk: { |
| ... | ... | @@ -9133,7 +9150,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, inst: Air.Inst.R |
| 9133 | 9150 | return Type.ArrayInfo{ |
| 9134 | 9151 | .elem_type = t.childType(), |
| 9135 | 9152 | .sentinel = t.sentinel(), |
| 9136 | .len = val.sliceLen(target), | |
| 9153 | .len = val.sliceLen(sema.mod), | |
| 9137 | 9154 | }; |
| 9138 | 9155 | } |
| 9139 | 9156 | if (ptrinfo.pointee_type.zigTypeTag() != .Array) return null; |
| ... | ... | @@ -9229,10 +9246,9 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9229 | 9246 | if (lhs_ty.isTuple()) { |
| 9230 | 9247 | return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor); |
| 9231 | 9248 | } |
| 9232 | const target = sema.mod.getTarget(); | |
| 9233 | 9249 | |
| 9234 | 9250 | const mulinfo = (try sema.getArrayCatInfo(block, lhs_src, lhs)) orelse |
| 9235 | return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty.fmt(target)}); | |
| 9251 | return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty.fmt(sema.mod)}); | |
| 9236 | 9252 | |
| 9237 | 9253 | const final_len_u64 = std.math.mul(u64, mulinfo.len, factor) catch |
| 9238 | 9254 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); |
| ... | ... | @@ -9264,7 +9280,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9264 | 9280 | // Optimization for the common pattern of a single element repeated N times, such |
| 9265 | 9281 | // as zero-filling a byte array. |
| 9266 | 9282 | const val = if (lhs_len == 1) blk: { |
| 9267 | const elem_val = try lhs_sub_val.elemValue(sema.arena, 0); | |
| 9283 | const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, 0); | |
| 9268 | 9284 | const copied_val = try elem_val.copy(anon_decl.arena()); |
| 9269 | 9285 | break :blk try Value.Tag.repeated.create(anon_decl.arena(), copied_val); |
| 9270 | 9286 | } else blk: { |
| ... | ... | @@ -9273,7 +9289,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9273 | 9289 | while (i < factor) : (i += 1) { |
| 9274 | 9290 | var j: usize = 0; |
| 9275 | 9291 | while (j < lhs_len) : (j += 1) { |
| 9276 | const val = try lhs_sub_val.elemValue(sema.arena, j); | |
| 9292 | const val = try lhs_sub_val.elemValue(sema.mod, sema.arena, j); | |
| 9277 | 9293 | buf[lhs_len * i + j] = try val.copy(anon_decl.arena()); |
| 9278 | 9294 | } |
| 9279 | 9295 | } |
| ... | ... | @@ -9310,9 +9326,8 @@ fn zirNegate( |
| 9310 | 9326 | const rhs_ty = sema.typeOf(rhs); |
| 9311 | 9327 | const rhs_scalar_ty = rhs_ty.scalarType(); |
| 9312 | 9328 | |
| 9313 | const target = sema.mod.getTarget(); | |
| 9314 | 9329 | if (tag_override == .sub and rhs_scalar_ty.isUnsignedInt()) { |
| 9315 | return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(target)}); | |
| 9330 | return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}); | |
| 9316 | 9331 | } |
| 9317 | 9332 | |
| 9318 | 9333 | const lhs = if (rhs_ty.zigTypeTag() == .Vector) |
| ... | ... | @@ -9364,12 +9379,13 @@ fn zirOverflowArithmetic( |
| 9364 | 9379 | const ptr = sema.resolveInst(extra.ptr); |
| 9365 | 9380 | |
| 9366 | 9381 | const lhs_ty = sema.typeOf(lhs); |
| 9367 | const target = sema.mod.getTarget(); | |
| 9382 | const mod = sema.mod; | |
| 9383 | const target = mod.getTarget(); | |
| 9368 | 9384 | |
| 9369 | 9385 | // Note, the types of lhs/rhs (also for shifting)/ptr are already correct as ensured by astgen. |
| 9370 | 9386 | const dest_ty = lhs_ty; |
| 9371 | 9387 | if (dest_ty.zigTypeTag() != .Int) { |
| 9372 | return sema.fail(block, src, "expected integer type, found '{}'", .{dest_ty.fmt(target)}); | |
| 9388 | return sema.fail(block, src, "expected integer type, found '{}'", .{dest_ty.fmt(mod)}); | |
| 9373 | 9389 | } |
| 9374 | 9390 | |
| 9375 | 9391 | const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, lhs); |
| ... | ... | @@ -9445,7 +9461,7 @@ fn zirOverflowArithmetic( |
| 9445 | 9461 | if (!lhs_val.isUndef()) { |
| 9446 | 9462 | if (lhs_val.compareWithZero(.eq)) { |
| 9447 | 9463 | break :result .{ .overflowed = .no, .wrapped = lhs }; |
| 9448 | } else if (lhs_val.compare(.eq, Value.one, dest_ty, target)) { | |
| 9464 | } else if (lhs_val.compare(.eq, Value.one, dest_ty, mod)) { | |
| 9449 | 9465 | break :result .{ .overflowed = .no, .wrapped = rhs }; |
| 9450 | 9466 | } |
| 9451 | 9467 | } |
| ... | ... | @@ -9455,7 +9471,7 @@ fn zirOverflowArithmetic( |
| 9455 | 9471 | if (!rhs_val.isUndef()) { |
| 9456 | 9472 | if (rhs_val.compareWithZero(.eq)) { |
| 9457 | 9473 | break :result .{ .overflowed = .no, .wrapped = rhs }; |
| 9458 | } else if (rhs_val.compare(.eq, Value.one, dest_ty, target)) { | |
| 9474 | } else if (rhs_val.compare(.eq, Value.one, dest_ty, mod)) { | |
| 9459 | 9475 | break :result .{ .overflowed = .no, .wrapped = lhs }; |
| 9460 | 9476 | } |
| 9461 | 9477 | } |
| ... | ... | @@ -9596,7 +9612,8 @@ fn analyzeArithmetic( |
| 9596 | 9612 | }); |
| 9597 | 9613 | } |
| 9598 | 9614 | |
| 9599 | const target = sema.mod.getTarget(); | |
| 9615 | const mod = sema.mod; | |
| 9616 | const target = mod.getTarget(); | |
| 9600 | 9617 | const maybe_lhs_val = try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs); |
| 9601 | 9618 | const maybe_rhs_val = try sema.resolveMaybeUndefVal(block, rhs_src, casted_rhs); |
| 9602 | 9619 | const rs: struct { src: LazySrcLoc, air_tag: Air.Inst.Tag } = rs: { |
| ... | ... | @@ -9834,7 +9851,7 @@ fn analyzeArithmetic( |
| 9834 | 9851 | if (lhs_val.isUndef()) { |
| 9835 | 9852 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 9836 | 9853 | if (maybe_rhs_val) |rhs_val| { |
| 9837 | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, target)) { | |
| 9854 | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, mod)) { | |
| 9838 | 9855 | return sema.addConstUndef(resolved_type); |
| 9839 | 9856 | } |
| 9840 | 9857 | } |
| ... | ... | @@ -9909,7 +9926,7 @@ fn analyzeArithmetic( |
| 9909 | 9926 | if (lhs_val.isUndef()) { |
| 9910 | 9927 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 9911 | 9928 | if (maybe_rhs_val) |rhs_val| { |
| 9912 | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, target)) { | |
| 9929 | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, mod)) { | |
| 9913 | 9930 | return sema.addConstUndef(resolved_type); |
| 9914 | 9931 | } |
| 9915 | 9932 | } |
| ... | ... | @@ -9972,7 +9989,7 @@ fn analyzeArithmetic( |
| 9972 | 9989 | if (lhs_val.isUndef()) { |
| 9973 | 9990 | if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) { |
| 9974 | 9991 | if (maybe_rhs_val) |rhs_val| { |
| 9975 | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, target)) { | |
| 9992 | if (rhs_val.compare(.neq, Value.negative_one, resolved_type, mod)) { | |
| 9976 | 9993 | return sema.addConstUndef(resolved_type); |
| 9977 | 9994 | } |
| 9978 | 9995 | } |
| ... | ... | @@ -10062,7 +10079,7 @@ fn analyzeArithmetic( |
| 10062 | 10079 | if (lhs_val.compareWithZero(.eq)) { |
| 10063 | 10080 | return sema.addConstant(resolved_type, Value.zero); |
| 10064 | 10081 | } |
| 10065 | if (lhs_val.compare(.eq, Value.one, resolved_type, target)) { | |
| 10082 | if (lhs_val.compare(.eq, Value.one, resolved_type, mod)) { | |
| 10066 | 10083 | return casted_rhs; |
| 10067 | 10084 | } |
| 10068 | 10085 | } |
| ... | ... | @@ -10078,7 +10095,7 @@ fn analyzeArithmetic( |
| 10078 | 10095 | if (rhs_val.compareWithZero(.eq)) { |
| 10079 | 10096 | return sema.addConstant(resolved_type, Value.zero); |
| 10080 | 10097 | } |
| 10081 | if (rhs_val.compare(.eq, Value.one, resolved_type, target)) { | |
| 10098 | if (rhs_val.compare(.eq, Value.one, resolved_type, mod)) { | |
| 10082 | 10099 | return casted_lhs; |
| 10083 | 10100 | } |
| 10084 | 10101 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -10113,7 +10130,7 @@ fn analyzeArithmetic( |
| 10113 | 10130 | if (lhs_val.compareWithZero(.eq)) { |
| 10114 | 10131 | return sema.addConstant(resolved_type, Value.zero); |
| 10115 | 10132 | } |
| 10116 | if (lhs_val.compare(.eq, Value.one, resolved_type, target)) { | |
| 10133 | if (lhs_val.compare(.eq, Value.one, resolved_type, mod)) { | |
| 10117 | 10134 | return casted_rhs; |
| 10118 | 10135 | } |
| 10119 | 10136 | } |
| ... | ... | @@ -10125,7 +10142,7 @@ fn analyzeArithmetic( |
| 10125 | 10142 | if (rhs_val.compareWithZero(.eq)) { |
| 10126 | 10143 | return sema.addConstant(resolved_type, Value.zero); |
| 10127 | 10144 | } |
| 10128 | if (rhs_val.compare(.eq, Value.one, resolved_type, target)) { | |
| 10145 | if (rhs_val.compare(.eq, Value.one, resolved_type, mod)) { | |
| 10129 | 10146 | return casted_lhs; |
| 10130 | 10147 | } |
| 10131 | 10148 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -10149,7 +10166,7 @@ fn analyzeArithmetic( |
| 10149 | 10166 | if (lhs_val.compareWithZero(.eq)) { |
| 10150 | 10167 | return sema.addConstant(resolved_type, Value.zero); |
| 10151 | 10168 | } |
| 10152 | if (lhs_val.compare(.eq, Value.one, resolved_type, target)) { | |
| 10169 | if (lhs_val.compare(.eq, Value.one, resolved_type, mod)) { | |
| 10153 | 10170 | return casted_rhs; |
| 10154 | 10171 | } |
| 10155 | 10172 | } |
| ... | ... | @@ -10161,7 +10178,7 @@ fn analyzeArithmetic( |
| 10161 | 10178 | if (rhs_val.compareWithZero(.eq)) { |
| 10162 | 10179 | return sema.addConstant(resolved_type, Value.zero); |
| 10163 | 10180 | } |
| 10164 | if (rhs_val.compare(.eq, Value.one, resolved_type, target)) { | |
| 10181 | if (rhs_val.compare(.eq, Value.one, resolved_type, mod)) { | |
| 10165 | 10182 | return casted_lhs; |
| 10166 | 10183 | } |
| 10167 | 10184 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -10431,7 +10448,7 @@ fn analyzePtrArithmetic( |
| 10431 | 10448 | if (air_tag == .ptr_sub) { |
| 10432 | 10449 | return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{}); |
| 10433 | 10450 | } |
| 10434 | const new_ptr_val = try ptr_val.elemPtr(ptr_ty, sema.arena, offset_int, target); | |
| 10451 | const new_ptr_val = try ptr_val.elemPtr(ptr_ty, sema.arena, offset_int, sema.mod); | |
| 10435 | 10452 | return sema.addConstant(new_ptr_ty, new_ptr_val); |
| 10436 | 10453 | } else break :rs offset_src; |
| 10437 | 10454 | } else break :rs ptr_src; |
| ... | ... | @@ -10605,7 +10622,6 @@ fn zirCmpEq( |
| 10605 | 10622 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 10606 | 10623 | const lhs = sema.resolveInst(extra.lhs); |
| 10607 | 10624 | const rhs = sema.resolveInst(extra.rhs); |
| 10608 | const target = sema.mod.getTarget(); | |
| 10609 | 10625 | |
| 10610 | 10626 | const lhs_ty = sema.typeOf(lhs); |
| 10611 | 10627 | const rhs_ty = sema.typeOf(rhs); |
| ... | ... | @@ -10630,7 +10646,7 @@ fn zirCmpEq( |
| 10630 | 10646 | |
| 10631 | 10647 | if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) { |
| 10632 | 10648 | const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty; |
| 10633 | return sema.fail(block, src, "comparison of '{}' with null", .{non_null_type.fmt(target)}); | |
| 10649 | return sema.fail(block, src, "comparison of '{}' with null", .{non_null_type.fmt(sema.mod)}); | |
| 10634 | 10650 | } |
| 10635 | 10651 | |
| 10636 | 10652 | if (lhs_ty_tag == .Union and (rhs_ty_tag == .EnumLiteral or rhs_ty_tag == .Enum)) { |
| ... | ... | @@ -10670,7 +10686,7 @@ fn zirCmpEq( |
| 10670 | 10686 | if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) { |
| 10671 | 10687 | const lhs_as_type = try sema.analyzeAsType(block, lhs_src, lhs); |
| 10672 | 10688 | const rhs_as_type = try sema.analyzeAsType(block, rhs_src, rhs); |
| 10673 | if (lhs_as_type.eql(rhs_as_type, target) == (op == .eq)) { | |
| 10689 | if (lhs_as_type.eql(rhs_as_type, sema.mod) == (op == .eq)) { | |
| 10674 | 10690 | return Air.Inst.Ref.bool_true; |
| 10675 | 10691 | } else { |
| 10676 | 10692 | return Air.Inst.Ref.bool_false; |
| ... | ... | @@ -10747,10 +10763,9 @@ fn analyzeCmp( |
| 10747 | 10763 | } |
| 10748 | 10764 | const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; |
| 10749 | 10765 | const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } }); |
| 10750 | const target = sema.mod.getTarget(); | |
| 10751 | 10766 | if (!resolved_type.isSelfComparable(is_equality_cmp)) { |
| 10752 | 10767 | return sema.fail(block, src, "{s} operator not allowed for type '{}'", .{ |
| 10753 | @tagName(op), resolved_type.fmt(target), | |
| 10768 | @tagName(op), resolved_type.fmt(sema.mod), | |
| 10754 | 10769 | }); |
| 10755 | 10770 | } |
| 10756 | 10771 | const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src); |
| ... | ... | @@ -10768,7 +10783,6 @@ fn cmpSelf( |
| 10768 | 10783 | rhs_src: LazySrcLoc, |
| 10769 | 10784 | ) CompileError!Air.Inst.Ref { |
| 10770 | 10785 | const resolved_type = sema.typeOf(casted_lhs); |
| 10771 | const target = sema.mod.getTarget(); | |
| 10772 | 10786 | const runtime_src: LazySrcLoc = src: { |
| 10773 | 10787 | if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| { |
| 10774 | 10788 | if (lhs_val.isUndef()) return sema.addConstUndef(Type.bool); |
| ... | ... | @@ -10777,11 +10791,11 @@ fn cmpSelf( |
| 10777 | 10791 | |
| 10778 | 10792 | if (resolved_type.zigTypeTag() == .Vector) { |
| 10779 | 10793 | const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.@"bool"); |
| 10780 | const cmp_val = try lhs_val.compareVector(op, rhs_val, resolved_type, sema.arena, target); | |
| 10794 | const cmp_val = try lhs_val.compareVector(op, rhs_val, resolved_type, sema.arena, sema.mod); | |
| 10781 | 10795 | return sema.addConstant(result_ty, cmp_val); |
| 10782 | 10796 | } |
| 10783 | 10797 | |
| 10784 | if (lhs_val.compare(op, rhs_val, resolved_type, target)) { | |
| 10798 | if (lhs_val.compare(op, rhs_val, resolved_type, sema.mod)) { | |
| 10785 | 10799 | return Air.Inst.Ref.bool_true; |
| 10786 | 10800 | } else { |
| 10787 | 10801 | return Air.Inst.Ref.bool_false; |
| ... | ... | @@ -10849,7 +10863,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 10849 | 10863 | .Null, |
| 10850 | 10864 | .BoundFn, |
| 10851 | 10865 | .Opaque, |
| 10852 | => return sema.fail(block, src, "no size available for type '{}'", .{operand_ty.fmt(target)}), | |
| 10866 | => return sema.fail(block, src, "no size available for type '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 10853 | 10867 | |
| 10854 | 10868 | .Type, |
| 10855 | 10869 | .EnumLiteral, |
| ... | ... | @@ -10892,9 +10906,9 @@ fn zirThis( |
| 10892 | 10906 | block: *Block, |
| 10893 | 10907 | extended: Zir.Inst.Extended.InstData, |
| 10894 | 10908 | ) CompileError!Air.Inst.Ref { |
| 10895 | const this_decl = block.namespace.getDecl(); | |
| 10909 | const this_decl_index = block.namespace.getDeclIndex(); | |
| 10896 | 10910 | const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; |
| 10897 | return sema.analyzeDeclVal(block, src, this_decl); | |
| 10911 | return sema.analyzeDeclVal(block, src, this_decl_index); | |
| 10898 | 10912 | } |
| 10899 | 10913 | |
| 10900 | 10914 | fn zirClosureCapture( |
| ... | ... | @@ -10927,7 +10941,7 @@ fn zirClosureGet( |
| 10927 | 10941 | ) CompileError!Air.Inst.Ref { |
| 10928 | 10942 | // TODO CLOSURE: Test this with inline functions |
| 10929 | 10943 | const inst_data = sema.code.instructions.items(.data)[inst].inst_node; |
| 10930 | var scope: *CaptureScope = block.src_decl.src_scope.?; | |
| 10944 | var scope: *CaptureScope = sema.mod.declPtr(block.src_decl).src_scope.?; | |
| 10931 | 10945 | // Note: The target closure must be in this scope list. |
| 10932 | 10946 | // If it's not here, the zir is invalid, or the list is broken. |
| 10933 | 10947 | const tv = while (true) { |
| ... | ... | @@ -10973,11 +10987,12 @@ fn zirBuiltinSrc( |
| 10973 | 10987 | const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; |
| 10974 | 10988 | const extra = sema.code.extraData(Zir.Inst.LineColumn, extended.operand).data; |
| 10975 | 10989 | const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{}); |
| 10990 | const fn_owner_decl = sema.mod.declPtr(func.owner_decl); | |
| 10976 | 10991 | |
| 10977 | 10992 | const func_name_val = blk: { |
| 10978 | 10993 | var anon_decl = try block.startAnonDecl(src); |
| 10979 | 10994 | defer anon_decl.deinit(); |
| 10980 | const name = std.mem.span(func.owner_decl.name); | |
| 10995 | const name = std.mem.span(fn_owner_decl.name); | |
| 10981 | 10996 | const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]); |
| 10982 | 10997 | const new_decl = try anon_decl.finish( |
| 10983 | 10998 | try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len - 1), |
| ... | ... | @@ -10990,7 +11005,7 @@ fn zirBuiltinSrc( |
| 10990 | 11005 | const file_name_val = blk: { |
| 10991 | 11006 | var anon_decl = try block.startAnonDecl(src); |
| 10992 | 11007 | defer anon_decl.deinit(); |
| 10993 | const name = try func.owner_decl.getFileScope().fullPathZ(anon_decl.arena()); | |
| 11008 | const name = try fn_owner_decl.getFileScope().fullPathZ(anon_decl.arena()); | |
| 10994 | 11009 | const new_decl = try anon_decl.finish( |
| 10995 | 11010 | try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), name.len), |
| 10996 | 11011 | try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]), |
| ... | ... | @@ -11118,24 +11133,26 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 11118 | 11133 | } |
| 11119 | 11134 | |
| 11120 | 11135 | const args_val = v: { |
| 11121 | const fn_info_decl = (try sema.namespaceLookup( | |
| 11136 | const fn_info_decl_index = (try sema.namespaceLookup( | |
| 11122 | 11137 | block, |
| 11123 | 11138 | src, |
| 11124 | 11139 | type_info_ty.getNamespace().?, |
| 11125 | 11140 | "Fn", |
| 11126 | 11141 | )).?; |
| 11127 | try sema.mod.declareDeclDependency(sema.owner_decl, fn_info_decl); | |
| 11128 | try sema.ensureDeclAnalyzed(fn_info_decl); | |
| 11142 | try sema.mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index); | |
| 11143 | try sema.ensureDeclAnalyzed(fn_info_decl_index); | |
| 11144 | const fn_info_decl = sema.mod.declPtr(fn_info_decl_index); | |
| 11129 | 11145 | var fn_ty_buffer: Value.ToTypeBuffer = undefined; |
| 11130 | 11146 | const fn_ty = fn_info_decl.val.toType(&fn_ty_buffer); |
| 11131 | const param_info_decl = (try sema.namespaceLookup( | |
| 11147 | const param_info_decl_index = (try sema.namespaceLookup( | |
| 11132 | 11148 | block, |
| 11133 | 11149 | src, |
| 11134 | 11150 | fn_ty.getNamespace().?, |
| 11135 | 11151 | "Param", |
| 11136 | 11152 | )).?; |
| 11137 | try sema.mod.declareDeclDependency(sema.owner_decl, param_info_decl); | |
| 11138 | try sema.ensureDeclAnalyzed(param_info_decl); | |
| 11153 | try sema.mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index); | |
| 11154 | try sema.ensureDeclAnalyzed(param_info_decl_index); | |
| 11155 | const param_info_decl = sema.mod.declPtr(param_info_decl_index); | |
| 11139 | 11156 | var param_buffer: Value.ToTypeBuffer = undefined; |
| 11140 | 11157 | const param_ty = param_info_decl.val.toType(&param_buffer); |
| 11141 | 11158 | const new_decl = try params_anon_decl.finish( |
| ... | ... | @@ -11307,14 +11324,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 11307 | 11324 | |
| 11308 | 11325 | // Get the Error type |
| 11309 | 11326 | const error_field_ty = t: { |
| 11310 | const set_field_ty_decl = (try sema.namespaceLookup( | |
| 11327 | const set_field_ty_decl_index = (try sema.namespaceLookup( | |
| 11311 | 11328 | block, |
| 11312 | 11329 | src, |
| 11313 | 11330 | type_info_ty.getNamespace().?, |
| 11314 | 11331 | "Error", |
| 11315 | 11332 | )).?; |
| 11316 | try sema.mod.declareDeclDependency(sema.owner_decl, set_field_ty_decl); | |
| 11317 | try sema.ensureDeclAnalyzed(set_field_ty_decl); | |
| 11333 | try sema.mod.declareDeclDependency(sema.owner_decl_index, set_field_ty_decl_index); | |
| 11334 | try sema.ensureDeclAnalyzed(set_field_ty_decl_index); | |
| 11335 | const set_field_ty_decl = sema.mod.declPtr(set_field_ty_decl_index); | |
| 11318 | 11336 | var buffer: Value.ToTypeBuffer = undefined; |
| 11319 | 11337 | break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); |
| 11320 | 11338 | }; |
| ... | ... | @@ -11416,14 +11434,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 11416 | 11434 | defer fields_anon_decl.deinit(); |
| 11417 | 11435 | |
| 11418 | 11436 | const enum_field_ty = t: { |
| 11419 | const enum_field_ty_decl = (try sema.namespaceLookup( | |
| 11437 | const enum_field_ty_decl_index = (try sema.namespaceLookup( | |
| 11420 | 11438 | block, |
| 11421 | 11439 | src, |
| 11422 | 11440 | type_info_ty.getNamespace().?, |
| 11423 | 11441 | "EnumField", |
| 11424 | 11442 | )).?; |
| 11425 | try sema.mod.declareDeclDependency(sema.owner_decl, enum_field_ty_decl); | |
| 11426 | try sema.ensureDeclAnalyzed(enum_field_ty_decl); | |
| 11443 | try sema.mod.declareDeclDependency(sema.owner_decl_index, enum_field_ty_decl_index); | |
| 11444 | try sema.ensureDeclAnalyzed(enum_field_ty_decl_index); | |
| 11445 | const enum_field_ty_decl = sema.mod.declPtr(enum_field_ty_decl_index); | |
| 11427 | 11446 | var buffer: Value.ToTypeBuffer = undefined; |
| 11428 | 11447 | break :t try enum_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); |
| 11429 | 11448 | }; |
| ... | ... | @@ -11514,14 +11533,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 11514 | 11533 | defer fields_anon_decl.deinit(); |
| 11515 | 11534 | |
| 11516 | 11535 | const union_field_ty = t: { |
| 11517 | const union_field_ty_decl = (try sema.namespaceLookup( | |
| 11536 | const union_field_ty_decl_index = (try sema.namespaceLookup( | |
| 11518 | 11537 | block, |
| 11519 | 11538 | src, |
| 11520 | 11539 | type_info_ty.getNamespace().?, |
| 11521 | 11540 | "UnionField", |
| 11522 | 11541 | )).?; |
| 11523 | try sema.mod.declareDeclDependency(sema.owner_decl, union_field_ty_decl); | |
| 11524 | try sema.ensureDeclAnalyzed(union_field_ty_decl); | |
| 11542 | try sema.mod.declareDeclDependency(sema.owner_decl_index, union_field_ty_decl_index); | |
| 11543 | try sema.ensureDeclAnalyzed(union_field_ty_decl_index); | |
| 11544 | const union_field_ty_decl = sema.mod.declPtr(union_field_ty_decl_index); | |
| 11525 | 11545 | var buffer: Value.ToTypeBuffer = undefined; |
| 11526 | 11546 | break :t try union_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); |
| 11527 | 11547 | }; |
| ... | ... | @@ -11621,14 +11641,15 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 11621 | 11641 | defer fields_anon_decl.deinit(); |
| 11622 | 11642 | |
| 11623 | 11643 | const struct_field_ty = t: { |
| 11624 | const struct_field_ty_decl = (try sema.namespaceLookup( | |
| 11644 | const struct_field_ty_decl_index = (try sema.namespaceLookup( | |
| 11625 | 11645 | block, |
| 11626 | 11646 | src, |
| 11627 | 11647 | type_info_ty.getNamespace().?, |
| 11628 | 11648 | "StructField", |
| 11629 | 11649 | )).?; |
| 11630 | try sema.mod.declareDeclDependency(sema.owner_decl, struct_field_ty_decl); | |
| 11631 | try sema.ensureDeclAnalyzed(struct_field_ty_decl); | |
| 11650 | try sema.mod.declareDeclDependency(sema.owner_decl_index, struct_field_ty_decl_index); | |
| 11651 | try sema.ensureDeclAnalyzed(struct_field_ty_decl_index); | |
| 11652 | const struct_field_ty_decl = sema.mod.declPtr(struct_field_ty_decl_index); | |
| 11632 | 11653 | var buffer: Value.ToTypeBuffer = undefined; |
| 11633 | 11654 | break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); |
| 11634 | 11655 | }; |
| ... | ... | @@ -11811,14 +11832,15 @@ fn typeInfoDecls( |
| 11811 | 11832 | defer decls_anon_decl.deinit(); |
| 11812 | 11833 | |
| 11813 | 11834 | const declaration_ty = t: { |
| 11814 | const declaration_ty_decl = (try sema.namespaceLookup( | |
| 11835 | const declaration_ty_decl_index = (try sema.namespaceLookup( | |
| 11815 | 11836 | block, |
| 11816 | 11837 | src, |
| 11817 | 11838 | type_info_ty.getNamespace().?, |
| 11818 | 11839 | "Declaration", |
| 11819 | 11840 | )).?; |
| 11820 | try sema.mod.declareDeclDependency(sema.owner_decl, declaration_ty_decl); | |
| 11821 | try sema.ensureDeclAnalyzed(declaration_ty_decl); | |
| 11841 | try sema.mod.declareDeclDependency(sema.owner_decl_index, declaration_ty_decl_index); | |
| 11842 | try sema.ensureDeclAnalyzed(declaration_ty_decl_index); | |
| 11843 | const declaration_ty_decl = sema.mod.declPtr(declaration_ty_decl_index); | |
| 11822 | 11844 | var buffer: Value.ToTypeBuffer = undefined; |
| 11823 | 11845 | break :t try declaration_ty_decl.val.toType(&buffer).copy(decls_anon_decl.arena()); |
| 11824 | 11846 | }; |
| ... | ... | @@ -11827,7 +11849,8 @@ fn typeInfoDecls( |
| 11827 | 11849 | const decls_len = if (opt_namespace) |ns| ns.decls.count() else 0; |
| 11828 | 11850 | const decls_vals = try decls_anon_decl.arena().alloc(Value, decls_len); |
| 11829 | 11851 | for (decls_vals) |*decls_val, i| { |
| 11830 | const decl = opt_namespace.?.decls.keys()[i]; | |
| 11852 | const decl_index = opt_namespace.?.decls.keys()[i]; | |
| 11853 | const decl = sema.mod.declPtr(decl_index); | |
| 11831 | 11854 | const name_val = v: { |
| 11832 | 11855 | var anon_decl = try block.startAnonDecl(src); |
| 11833 | 11856 | defer anon_decl.deinit(); |
| ... | ... | @@ -11947,12 +11970,11 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi |
| 11947 | 11970 | }, |
| 11948 | 11971 | else => {}, |
| 11949 | 11972 | } |
| 11950 | const target = sema.mod.getTarget(); | |
| 11951 | 11973 | return sema.fail( |
| 11952 | 11974 | block, |
| 11953 | 11975 | src, |
| 11954 | 11976 | "bit shifting operation expected integer type, found '{}'", |
| 11955 | .{operand.fmt(target)}, | |
| 11977 | .{operand.fmt(sema.mod)}, | |
| 11956 | 11978 | ); |
| 11957 | 11979 | } |
| 11958 | 11980 | |
| ... | ... | @@ -12426,8 +12448,7 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 12426 | 12448 | |
| 12427 | 12449 | const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple; |
| 12428 | 12450 | const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type); |
| 12429 | const target = sema.mod.getTarget(); | |
| 12430 | const ty = try Type.ptr(sema.arena, target, .{ | |
| 12451 | const ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 12431 | 12452 | .pointee_type = elem_type, |
| 12432 | 12453 | .@"addrspace" = .generic, |
| 12433 | 12454 | .mutable = inst_data.is_mutable, |
| ... | ... | @@ -12466,7 +12487,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 12466 | 12487 | // Check if this happens to be the lazy alignment of our element type, in |
| 12467 | 12488 | // which case we can make this 0 without resolving it. |
| 12468 | 12489 | if (val.castTag(.lazy_align)) |payload| { |
| 12469 | if (payload.data.eql(unresolved_elem_ty, target)) { | |
| 12490 | if (payload.data.eql(unresolved_elem_ty, sema.mod)) { | |
| 12470 | 12491 | break :blk 0; |
| 12471 | 12492 | } |
| 12472 | 12493 | } |
| ... | ... | @@ -12505,7 +12526,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 12505 | 12526 | try sema.resolveTypeLayout(block, elem_ty_src, elem_ty); |
| 12506 | 12527 | break :t elem_ty; |
| 12507 | 12528 | }; |
| 12508 | const ty = try Type.ptr(sema.arena, target, .{ | |
| 12529 | const ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 12509 | 12530 | .pointee_type = elem_ty, |
| 12510 | 12531 | .sentinel = sentinel, |
| 12511 | 12532 | .@"align" = abi_align, |
| ... | ... | @@ -12754,10 +12775,10 @@ fn finishStructInit( |
| 12754 | 12775 | const gpa = sema.gpa; |
| 12755 | 12776 | |
| 12756 | 12777 | if (root_msg) |msg| { |
| 12757 | const fqn = try struct_obj.getFullyQualifiedName(gpa); | |
| 12778 | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); | |
| 12758 | 12779 | defer gpa.free(fqn); |
| 12759 | 12780 | try sema.mod.errNoteNonLazy( |
| 12760 | struct_obj.srcLoc(), | |
| 12781 | struct_obj.srcLoc(sema.mod), | |
| 12761 | 12782 | msg, |
| 12762 | 12783 | "struct '{s}' declared here", |
| 12763 | 12784 | .{fqn}, |
| ... | ... | @@ -12782,7 +12803,7 @@ fn finishStructInit( |
| 12782 | 12803 | |
| 12783 | 12804 | if (is_ref) { |
| 12784 | 12805 | const target = sema.mod.getTarget(); |
| 12785 | const alloc_ty = try Type.ptr(sema.arena, target, .{ | |
| 12806 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 12786 | 12807 | .pointee_type = struct_ty, |
| 12787 | 12808 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 12788 | 12809 | }); |
| ... | ... | @@ -12851,7 +12872,7 @@ fn zirStructInitAnon( |
| 12851 | 12872 | |
| 12852 | 12873 | if (is_ref) { |
| 12853 | 12874 | const target = sema.mod.getTarget(); |
| 12854 | const alloc_ty = try Type.ptr(sema.arena, target, .{ | |
| 12875 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 12855 | 12876 | .pointee_type = tuple_ty, |
| 12856 | 12877 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 12857 | 12878 | }); |
| ... | ... | @@ -12862,7 +12883,7 @@ fn zirStructInitAnon( |
| 12862 | 12883 | const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index); |
| 12863 | 12884 | extra_index = item.end; |
| 12864 | 12885 | |
| 12865 | const field_ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 12886 | const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 12866 | 12887 | .mutable = true, |
| 12867 | 12888 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 12868 | 12889 | .pointee_type = field_ty, |
| ... | ... | @@ -12949,13 +12970,13 @@ fn zirArrayInit( |
| 12949 | 12970 | |
| 12950 | 12971 | if (is_ref) { |
| 12951 | 12972 | const target = sema.mod.getTarget(); |
| 12952 | const alloc_ty = try Type.ptr(sema.arena, target, .{ | |
| 12973 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 12953 | 12974 | .pointee_type = array_ty, |
| 12954 | 12975 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 12955 | 12976 | }); |
| 12956 | 12977 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 12957 | 12978 | |
| 12958 | const elem_ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 12979 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 12959 | 12980 | .mutable = true, |
| 12960 | 12981 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 12961 | 12982 | .pointee_type = elem_ty, |
| ... | ... | @@ -13017,14 +13038,14 @@ fn zirArrayInitAnon( |
| 13017 | 13038 | |
| 13018 | 13039 | if (is_ref) { |
| 13019 | 13040 | const target = sema.mod.getTarget(); |
| 13020 | const alloc_ty = try Type.ptr(sema.arena, target, .{ | |
| 13041 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 13021 | 13042 | .pointee_type = tuple_ty, |
| 13022 | 13043 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 13023 | 13044 | }); |
| 13024 | 13045 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 13025 | 13046 | for (operands) |operand, i_usize| { |
| 13026 | 13047 | const i = @intCast(u32, i_usize); |
| 13027 | const field_ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 13048 | const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 13028 | 13049 | .mutable = true, |
| 13029 | 13050 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 13030 | 13051 | .pointee_type = types[i], |
| ... | ... | @@ -13096,7 +13117,6 @@ fn fieldType( |
| 13096 | 13117 | ty_src: LazySrcLoc, |
| 13097 | 13118 | ) CompileError!Air.Inst.Ref { |
| 13098 | 13119 | const resolved_ty = try sema.resolveTypeFields(block, ty_src, aggregate_ty); |
| 13099 | const target = sema.mod.getTarget(); | |
| 13100 | 13120 | var cur_ty = resolved_ty; |
| 13101 | 13121 | while (true) { |
| 13102 | 13122 | switch (cur_ty.zigTypeTag()) { |
| ... | ... | @@ -13127,7 +13147,7 @@ fn fieldType( |
| 13127 | 13147 | else => {}, |
| 13128 | 13148 | } |
| 13129 | 13149 | return sema.fail(block, ty_src, "expected struct or union; found '{}'", .{ |
| 13130 | resolved_ty.fmt(target), | |
| 13150 | resolved_ty.fmt(sema.mod), | |
| 13131 | 13151 | }); |
| 13132 | 13152 | } |
| 13133 | 13153 | } |
| ... | ... | @@ -13216,10 +13236,10 @@ fn zirUnaryMath( |
| 13216 | 13236 | const scalar_ty = operand_ty.scalarType(); |
| 13217 | 13237 | switch (scalar_ty.zigTypeTag()) { |
| 13218 | 13238 | .ComptimeFloat, .Float => {}, |
| 13219 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(target)}), | |
| 13239 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}), | |
| 13220 | 13240 | } |
| 13221 | 13241 | }, |
| 13222 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(target)}), | |
| 13242 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}), | |
| 13223 | 13243 | } |
| 13224 | 13244 | |
| 13225 | 13245 | switch (operand_ty.zigTypeTag()) { |
| ... | ... | @@ -13234,7 +13254,7 @@ fn zirUnaryMath( |
| 13234 | 13254 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 13235 | 13255 | const elems = try sema.arena.alloc(Value, vec_len); |
| 13236 | 13256 | for (elems) |*elem, i| { |
| 13237 | const elem_val = val.elemValueBuffer(i, &elem_buf); | |
| 13257 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); | |
| 13238 | 13258 | elem.* = try eval(elem_val, scalar_ty, sema.arena, target); |
| 13239 | 13259 | } |
| 13240 | 13260 | return sema.addConstant( |
| ... | ... | @@ -13267,7 +13287,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 13267 | 13287 | const src = inst_data.src(); |
| 13268 | 13288 | const operand = sema.resolveInst(inst_data.operand); |
| 13269 | 13289 | const operand_ty = sema.typeOf(operand); |
| 13270 | const target = sema.mod.getTarget(); | |
| 13290 | const mod = sema.mod; | |
| 13271 | 13291 | |
| 13272 | 13292 | try sema.resolveTypeLayout(block, operand_src, operand_ty); |
| 13273 | 13293 | const enum_ty = switch (operand_ty.zigTypeTag()) { |
| ... | ... | @@ -13278,31 +13298,33 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 13278 | 13298 | }, |
| 13279 | 13299 | .Enum => operand_ty, |
| 13280 | 13300 | .Union => operand_ty.unionTagType() orelse { |
| 13281 | const decl = operand_ty.getOwnerDecl(); | |
| 13301 | const decl_index = operand_ty.getOwnerDecl(); | |
| 13302 | const decl = mod.declPtr(decl_index); | |
| 13282 | 13303 | const msg = msg: { |
| 13283 | 13304 | const msg = try sema.errMsg(block, src, "union '{s}' is untagged", .{ |
| 13284 | 13305 | decl.name, |
| 13285 | 13306 | }); |
| 13286 | 13307 | errdefer msg.destroy(sema.gpa); |
| 13287 | try sema.mod.errNoteNonLazy(decl.srcLoc(), msg, "declared here", .{}); | |
| 13308 | try mod.errNoteNonLazy(decl.srcLoc(), msg, "declared here", .{}); | |
| 13288 | 13309 | break :msg msg; |
| 13289 | 13310 | }; |
| 13290 | 13311 | return sema.failWithOwnedErrorMsg(block, msg); |
| 13291 | 13312 | }, |
| 13292 | 13313 | else => return sema.fail(block, operand_src, "expected enum or union; found {}", .{ |
| 13293 | operand_ty.fmt(target), | |
| 13314 | operand_ty.fmt(mod), | |
| 13294 | 13315 | }), |
| 13295 | 13316 | }; |
| 13296 | const enum_decl = enum_ty.getOwnerDecl(); | |
| 13317 | const enum_decl_index = enum_ty.getOwnerDecl(); | |
| 13297 | 13318 | const casted_operand = try sema.coerce(block, enum_ty, operand, operand_src); |
| 13298 | 13319 | if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| { |
| 13299 | const field_index = enum_ty.enumTagFieldIndex(val, target) orelse { | |
| 13320 | const field_index = enum_ty.enumTagFieldIndex(val, mod) orelse { | |
| 13321 | const enum_decl = mod.declPtr(enum_decl_index); | |
| 13300 | 13322 | const msg = msg: { |
| 13301 | 13323 | const msg = try sema.errMsg(block, src, "no field with value {} in enum '{s}'", .{ |
| 13302 | 13324 | casted_operand, enum_decl.name, |
| 13303 | 13325 | }); |
| 13304 | 13326 | errdefer msg.destroy(sema.gpa); |
| 13305 | try sema.mod.errNoteNonLazy(enum_decl.srcLoc(), msg, "declared here", .{}); | |
| 13327 | try mod.errNoteNonLazy(enum_decl.srcLoc(), msg, "declared here", .{}); | |
| 13306 | 13328 | break :msg msg; |
| 13307 | 13329 | }; |
| 13308 | 13330 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | ... | @@ -13317,6 +13339,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 13317 | 13339 | } |
| 13318 | 13340 | |
| 13319 | 13341 | fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13342 | const mod = sema.mod; | |
| 13320 | 13343 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 13321 | 13344 | const src = inst_data.src(); |
| 13322 | 13345 | const type_info_ty = try sema.resolveBuiltinTypeFields(block, src, "Type"); |
| ... | ... | @@ -13326,8 +13349,8 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13326 | 13349 | const val = try sema.resolveConstValue(block, operand_src, type_info); |
| 13327 | 13350 | const union_val = val.cast(Value.Payload.Union).?.data; |
| 13328 | 13351 | const tag_ty = type_info_ty.unionTagType().?; |
| 13329 | const target = sema.mod.getTarget(); | |
| 13330 | const tag_index = tag_ty.enumTagFieldIndex(union_val.tag, target).?; | |
| 13352 | const target = mod.getTarget(); | |
| 13353 | const tag_index = tag_ty.enumTagFieldIndex(union_val.tag, mod).?; | |
| 13331 | 13354 | switch (@intToEnum(std.builtin.TypeId, tag_index)) { |
| 13332 | 13355 | .Type => return Air.Inst.Ref.type_type, |
| 13333 | 13356 | .Void => return Air.Inst.Ref.void_type, |
| ... | ... | @@ -13406,14 +13429,14 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13406 | 13429 | return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{}); |
| 13407 | 13430 | } |
| 13408 | 13431 | const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data; |
| 13409 | const ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 13432 | const ptr_ty = try Type.ptr(sema.arena, mod, .{ | |
| 13410 | 13433 | .@"addrspace" = .generic, |
| 13411 | 13434 | .pointee_type = child_ty, |
| 13412 | 13435 | }); |
| 13413 | 13436 | actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?; |
| 13414 | 13437 | } |
| 13415 | 13438 | |
| 13416 | const ty = try Type.ptr(sema.arena, target, .{ | |
| 13439 | const ty = try Type.ptr(sema.arena, mod, .{ | |
| 13417 | 13440 | .size = ptr_size, |
| 13418 | 13441 | .mutable = !is_const_val.toBool(), |
| 13419 | 13442 | .@"volatile" = is_volatile_val.toBool(), |
| ... | ... | @@ -13439,14 +13462,14 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13439 | 13462 | var buffer: Value.ToTypeBuffer = undefined; |
| 13440 | 13463 | const child_ty = try child_val.toType(&buffer).copy(sema.arena); |
| 13441 | 13464 | const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: { |
| 13442 | const ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 13465 | const ptr_ty = try Type.ptr(sema.arena, mod, .{ | |
| 13443 | 13466 | .@"addrspace" = .generic, |
| 13444 | 13467 | .pointee_type = child_ty, |
| 13445 | 13468 | }); |
| 13446 | 13469 | break :blk (try sema.pointerDeref(block, src, p.data, ptr_ty)).?; |
| 13447 | 13470 | } else null; |
| 13448 | 13471 | |
| 13449 | const ty = try Type.array(sema.arena, len, sentinel, child_ty, target); | |
| 13472 | const ty = try Type.array(sema.arena, len, sentinel, child_ty, sema.mod); | |
| 13450 | 13473 | return sema.addType(ty); |
| 13451 | 13474 | }, |
| 13452 | 13475 | .Optional => { |
| ... | ... | @@ -13483,8 +13506,9 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13483 | 13506 | const payload_val = union_val.val.optionalValue() orelse |
| 13484 | 13507 | return sema.addType(Type.initTag(.anyerror)); |
| 13485 | 13508 | const slice_val = payload_val.castTag(.slice).?.data; |
| 13486 | const decl = slice_val.ptr.pointerDecl().?; | |
| 13487 | try sema.ensureDeclAnalyzed(decl); | |
| 13509 | const decl_index = slice_val.ptr.pointerDecl().?; | |
| 13510 | try sema.ensureDeclAnalyzed(decl_index); | |
| 13511 | const decl = mod.declPtr(decl_index); | |
| 13488 | 13512 | const array_val = decl.val.castTag(.aggregate).?.data; |
| 13489 | 13513 | |
| 13490 | 13514 | var names: Module.ErrorSet.NameMap = .{}; |
| ... | ... | @@ -13494,9 +13518,9 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13494 | 13518 | // TODO use reflection instead of magic numbers here |
| 13495 | 13519 | // error_set: type, |
| 13496 | 13520 | const name_val = struct_val[0]; |
| 13497 | const name_str = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, target); | |
| 13521 | const name_str = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, sema.mod); | |
| 13498 | 13522 | |
| 13499 | const kv = try sema.mod.getErrorValue(name_str); | |
| 13523 | const kv = try mod.getErrorValue(name_str); | |
| 13500 | 13524 | names.putAssumeCapacityNoClobber(kv.key, {}); |
| 13501 | 13525 | } |
| 13502 | 13526 | |
| ... | ... | @@ -13518,7 +13542,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13518 | 13542 | const is_tuple_val = struct_val[3]; |
| 13519 | 13543 | |
| 13520 | 13544 | // Decls |
| 13521 | if (decls_val.sliceLen(target) > 0) { | |
| 13545 | if (decls_val.sliceLen(mod) > 0) { | |
| 13522 | 13546 | return sema.fail(block, src, "reified structs must have no decls", .{}); |
| 13523 | 13547 | } |
| 13524 | 13548 | |
| ... | ... | @@ -13548,11 +13572,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13548 | 13572 | } |
| 13549 | 13573 | |
| 13550 | 13574 | // Decls |
| 13551 | if (decls_val.sliceLen(target) > 0) { | |
| 13575 | if (decls_val.sliceLen(mod) > 0) { | |
| 13552 | 13576 | return sema.fail(block, src, "reified enums must have no decls", .{}); |
| 13553 | 13577 | } |
| 13554 | 13578 | |
| 13555 | const mod = sema.mod; | |
| 13556 | 13579 | const gpa = sema.gpa; |
| 13557 | 13580 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| 13558 | 13581 | errdefer new_decl_arena.deinit(); |
| ... | ... | @@ -13572,20 +13595,20 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13572 | 13595 | }; |
| 13573 | 13596 | const enum_ty = Type.initPayload(&enum_ty_payload.base); |
| 13574 | 13597 | const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty); |
| 13575 | const type_name = try sema.createTypeName(block, .anon, "enum"); | |
| 13576 | const new_decl = try mod.createAnonymousDeclNamed(block, .{ | |
| 13598 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 13577 | 13599 | .ty = Type.type, |
| 13578 | 13600 | .val = enum_val, |
| 13579 | }, type_name); | |
| 13601 | }, .anon, "enum"); | |
| 13602 | const new_decl = mod.declPtr(new_decl_index); | |
| 13580 | 13603 | new_decl.owns_tv = true; |
| 13581 | errdefer mod.abortAnonDecl(new_decl); | |
| 13604 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 13582 | 13605 | |
| 13583 | 13606 | // Enum tag type |
| 13584 | 13607 | var buffer: Value.ToTypeBuffer = undefined; |
| 13585 | 13608 | const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator); |
| 13586 | 13609 | |
| 13587 | 13610 | enum_obj.* = .{ |
| 13588 | .owner_decl = new_decl, | |
| 13611 | .owner_decl = new_decl_index, | |
| 13589 | 13612 | .tag_ty = int_tag_ty, |
| 13590 | 13613 | .tag_ty_inferred = false, |
| 13591 | 13614 | .fields = .{}, |
| ... | ... | @@ -13599,17 +13622,17 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13599 | 13622 | }; |
| 13600 | 13623 | |
| 13601 | 13624 | // Fields |
| 13602 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(target)); | |
| 13625 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); | |
| 13603 | 13626 | if (fields_len > 0) { |
| 13604 | 13627 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 13605 | 13628 | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ |
| 13606 | 13629 | .ty = enum_obj.tag_ty, |
| 13607 | .target = target, | |
| 13630 | .mod = mod, | |
| 13608 | 13631 | }); |
| 13609 | 13632 | |
| 13610 | 13633 | var i: usize = 0; |
| 13611 | 13634 | while (i < fields_len) : (i += 1) { |
| 13612 | const elem_val = try fields_val.elemValue(sema.arena, i); | |
| 13635 | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); | |
| 13613 | 13636 | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 13614 | 13637 | // TODO use reflection instead of magic numbers here |
| 13615 | 13638 | // name: []const u8 |
| ... | ... | @@ -13620,7 +13643,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13620 | 13643 | const field_name = try name_val.toAllocatedBytes( |
| 13621 | 13644 | Type.initTag(.const_slice_u8), |
| 13622 | 13645 | new_decl_arena_allocator, |
| 13623 | target, | |
| 13646 | sema.mod, | |
| 13624 | 13647 | ); |
| 13625 | 13648 | |
| 13626 | 13649 | const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name); |
| ... | ... | @@ -13632,13 +13655,13 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13632 | 13655 | const copied_tag_val = try value_val.copy(new_decl_arena_allocator); |
| 13633 | 13656 | enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{ |
| 13634 | 13657 | .ty = enum_obj.tag_ty, |
| 13635 | .target = target, | |
| 13658 | .mod = mod, | |
| 13636 | 13659 | }); |
| 13637 | 13660 | } |
| 13638 | 13661 | } |
| 13639 | 13662 | |
| 13640 | 13663 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 13641 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 13664 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 13642 | 13665 | }, |
| 13643 | 13666 | .Opaque => { |
| 13644 | 13667 | const struct_val = union_val.val.castTag(.aggregate).?.data; |
| ... | ... | @@ -13646,11 +13669,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13646 | 13669 | const decls_val = struct_val[0]; |
| 13647 | 13670 | |
| 13648 | 13671 | // Decls |
| 13649 | if (decls_val.sliceLen(target) > 0) { | |
| 13672 | if (decls_val.sliceLen(mod) > 0) { | |
| 13650 | 13673 | return sema.fail(block, src, "reified opaque must have no decls", .{}); |
| 13651 | 13674 | } |
| 13652 | 13675 | |
| 13653 | const mod = sema.mod; | |
| 13654 | 13676 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| 13655 | 13677 | errdefer new_decl_arena.deinit(); |
| 13656 | 13678 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| ... | ... | @@ -13663,16 +13685,16 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13663 | 13685 | }; |
| 13664 | 13686 | const opaque_ty = Type.initPayload(&opaque_ty_payload.base); |
| 13665 | 13687 | const opaque_val = try Value.Tag.ty.create(new_decl_arena_allocator, opaque_ty); |
| 13666 | const type_name = try sema.createTypeName(block, .anon, "opaque"); | |
| 13667 | const new_decl = try mod.createAnonymousDeclNamed(block, .{ | |
| 13688 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 13668 | 13689 | .ty = Type.type, |
| 13669 | 13690 | .val = opaque_val, |
| 13670 | }, type_name); | |
| 13691 | }, .anon, "opaque"); | |
| 13692 | const new_decl = mod.declPtr(new_decl_index); | |
| 13671 | 13693 | new_decl.owns_tv = true; |
| 13672 | errdefer mod.abortAnonDecl(new_decl); | |
| 13694 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 13673 | 13695 | |
| 13674 | 13696 | opaque_obj.* = .{ |
| 13675 | .owner_decl = new_decl, | |
| 13697 | .owner_decl = new_decl_index, | |
| 13676 | 13698 | .node_offset = src.node_offset, |
| 13677 | 13699 | .namespace = .{ |
| 13678 | 13700 | .parent = block.namespace, |
| ... | ... | @@ -13682,7 +13704,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13682 | 13704 | }; |
| 13683 | 13705 | |
| 13684 | 13706 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 13685 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 13707 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 13686 | 13708 | }, |
| 13687 | 13709 | .Union => { |
| 13688 | 13710 | // TODO use reflection instead of magic numbers here |
| ... | ... | @@ -13697,7 +13719,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13697 | 13719 | const decls_val = struct_val[3]; |
| 13698 | 13720 | |
| 13699 | 13721 | // Decls |
| 13700 | if (decls_val.sliceLen(target) > 0) { | |
| 13722 | if (decls_val.sliceLen(mod) > 0) { | |
| 13701 | 13723 | return sema.fail(block, src, "reified unions must have no decls", .{}); |
| 13702 | 13724 | } |
| 13703 | 13725 | |
| ... | ... | @@ -13714,15 +13736,15 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13714 | 13736 | }; |
| 13715 | 13737 | const union_ty = Type.initPayload(&union_payload.base); |
| 13716 | 13738 | const new_union_val = try Value.Tag.ty.create(new_decl_arena_allocator, union_ty); |
| 13717 | const type_name = try sema.createTypeName(block, .anon, "union"); | |
| 13718 | const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ | |
| 13739 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 13719 | 13740 | .ty = Type.type, |
| 13720 | 13741 | .val = new_union_val, |
| 13721 | }, type_name); | |
| 13742 | }, .anon, "union"); | |
| 13743 | const new_decl = mod.declPtr(new_decl_index); | |
| 13722 | 13744 | new_decl.owns_tv = true; |
| 13723 | errdefer sema.mod.abortAnonDecl(new_decl); | |
| 13745 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 13724 | 13746 | union_obj.* = .{ |
| 13725 | .owner_decl = new_decl, | |
| 13747 | .owner_decl = new_decl_index, | |
| 13726 | 13748 | .tag_ty = Type.initTag(.@"null"), |
| 13727 | 13749 | .fields = .{}, |
| 13728 | 13750 | .node_offset = src.node_offset, |
| ... | ... | @@ -13737,7 +13759,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13737 | 13759 | }; |
| 13738 | 13760 | |
| 13739 | 13761 | // Tag type |
| 13740 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(target)); | |
| 13762 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); | |
| 13741 | 13763 | union_obj.tag_ty = if (tag_type_val.optionalValue()) |payload_val| blk: { |
| 13742 | 13764 | var buffer: Value.ToTypeBuffer = undefined; |
| 13743 | 13765 | break :blk try payload_val.toType(&buffer).copy(new_decl_arena_allocator); |
| ... | ... | @@ -13749,7 +13771,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13749 | 13771 | |
| 13750 | 13772 | var i: usize = 0; |
| 13751 | 13773 | while (i < fields_len) : (i += 1) { |
| 13752 | const elem_val = try fields_val.elemValue(sema.arena, i); | |
| 13774 | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); | |
| 13753 | 13775 | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 13754 | 13776 | // TODO use reflection instead of magic numbers here |
| 13755 | 13777 | // name: []const u8 |
| ... | ... | @@ -13762,7 +13784,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13762 | 13784 | const field_name = try name_val.toAllocatedBytes( |
| 13763 | 13785 | Type.initTag(.const_slice_u8), |
| 13764 | 13786 | new_decl_arena_allocator, |
| 13765 | target, | |
| 13787 | sema.mod, | |
| 13766 | 13788 | ); |
| 13767 | 13789 | |
| 13768 | 13790 | const gop = union_obj.fields.getOrPutAssumeCapacity(field_name); |
| ... | ... | @@ -13780,7 +13802,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 13780 | 13802 | } |
| 13781 | 13803 | |
| 13782 | 13804 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 13783 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 13805 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 13784 | 13806 | }, |
| 13785 | 13807 | .Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}), |
| 13786 | 13808 | .BoundFn => @panic("TODO delete BoundFn from the language"), |
| ... | ... | @@ -13794,9 +13816,7 @@ fn reifyTuple( |
| 13794 | 13816 | src: LazySrcLoc, |
| 13795 | 13817 | fields_val: Value, |
| 13796 | 13818 | ) CompileError!Air.Inst.Ref { |
| 13797 | const target = sema.mod.getTarget(); | |
| 13798 | ||
| 13799 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(target)); | |
| 13819 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(sema.mod)); | |
| 13800 | 13820 | if (fields_len == 0) return sema.addType(Type.initTag(.empty_struct_literal)); |
| 13801 | 13821 | |
| 13802 | 13822 | const types = try sema.arena.alloc(Type, fields_len); |
| ... | ... | @@ -13808,7 +13828,7 @@ fn reifyTuple( |
| 13808 | 13828 | |
| 13809 | 13829 | var i: usize = 0; |
| 13810 | 13830 | while (i < fields_len) : (i += 1) { |
| 13811 | const elem_val = try fields_val.elemValue(sema.arena, i); | |
| 13831 | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); | |
| 13812 | 13832 | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 13813 | 13833 | // TODO use reflection instead of magic numbers here |
| 13814 | 13834 | // name: []const u8 |
| ... | ... | @@ -13821,7 +13841,7 @@ fn reifyTuple( |
| 13821 | 13841 | const field_name = try name_val.toAllocatedBytes( |
| 13822 | 13842 | Type.initTag(.const_slice_u8), |
| 13823 | 13843 | sema.arena, |
| 13824 | target, | |
| 13844 | sema.mod, | |
| 13825 | 13845 | ); |
| 13826 | 13846 | |
| 13827 | 13847 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { |
| ... | ... | @@ -13850,7 +13870,7 @@ fn reifyTuple( |
| 13850 | 13870 | |
| 13851 | 13871 | const default_val = if (default_value_val.optionalValue()) |opt_val| blk: { |
| 13852 | 13872 | const payload_val = if (opt_val.pointerDecl()) |opt_decl| |
| 13853 | opt_decl.val | |
| 13873 | sema.mod.declPtr(opt_decl).val | |
| 13854 | 13874 | else |
| 13855 | 13875 | opt_val; |
| 13856 | 13876 | break :blk try payload_val.copy(sema.arena); |
| ... | ... | @@ -13883,15 +13903,16 @@ fn reifyStruct( |
| 13883 | 13903 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); |
| 13884 | 13904 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); |
| 13885 | 13905 | const new_struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); |
| 13886 | const type_name = try sema.createTypeName(block, .anon, "struct"); | |
| 13887 | const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ | |
| 13906 | const mod = sema.mod; | |
| 13907 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ | |
| 13888 | 13908 | .ty = Type.type, |
| 13889 | 13909 | .val = new_struct_val, |
| 13890 | }, type_name); | |
| 13910 | }, .anon, "struct"); | |
| 13911 | const new_decl = mod.declPtr(new_decl_index); | |
| 13891 | 13912 | new_decl.owns_tv = true; |
| 13892 | errdefer sema.mod.abortAnonDecl(new_decl); | |
| 13913 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 13893 | 13914 | struct_obj.* = .{ |
| 13894 | .owner_decl = new_decl, | |
| 13915 | .owner_decl = new_decl_index, | |
| 13895 | 13916 | .fields = .{}, |
| 13896 | 13917 | .node_offset = src.node_offset, |
| 13897 | 13918 | .zir_index = inst, |
| ... | ... | @@ -13905,14 +13926,14 @@ fn reifyStruct( |
| 13905 | 13926 | }, |
| 13906 | 13927 | }; |
| 13907 | 13928 | |
| 13908 | const target = sema.mod.getTarget(); | |
| 13929 | const target = mod.getTarget(); | |
| 13909 | 13930 | |
| 13910 | 13931 | // Fields |
| 13911 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(target)); | |
| 13932 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); | |
| 13912 | 13933 | try struct_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 13913 | 13934 | var i: usize = 0; |
| 13914 | 13935 | while (i < fields_len) : (i += 1) { |
| 13915 | const elem_val = try fields_val.elemValue(sema.arena, i); | |
| 13936 | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); | |
| 13916 | 13937 | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 13917 | 13938 | // TODO use reflection instead of magic numbers here |
| 13918 | 13939 | // name: []const u8 |
| ... | ... | @@ -13929,7 +13950,7 @@ fn reifyStruct( |
| 13929 | 13950 | const field_name = try name_val.toAllocatedBytes( |
| 13930 | 13951 | Type.initTag(.const_slice_u8), |
| 13931 | 13952 | new_decl_arena_allocator, |
| 13932 | target, | |
| 13953 | mod, | |
| 13933 | 13954 | ); |
| 13934 | 13955 | |
| 13935 | 13956 | const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name); |
| ... | ... | @@ -13940,7 +13961,7 @@ fn reifyStruct( |
| 13940 | 13961 | |
| 13941 | 13962 | const default_val = if (default_value_val.optionalValue()) |opt_val| blk: { |
| 13942 | 13963 | const payload_val = if (opt_val.pointerDecl()) |opt_decl| |
| 13943 | opt_decl.val | |
| 13964 | mod.declPtr(opt_decl).val | |
| 13944 | 13965 | else |
| 13945 | 13966 | opt_val; |
| 13946 | 13967 | break :blk try payload_val.copy(new_decl_arena_allocator); |
| ... | ... | @@ -13957,7 +13978,7 @@ fn reifyStruct( |
| 13957 | 13978 | } |
| 13958 | 13979 | |
| 13959 | 13980 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 13960 | return sema.analyzeDeclVal(block, src, new_decl); | |
| 13981 | return sema.analyzeDeclVal(block, src, new_decl_index); | |
| 13961 | 13982 | } |
| 13962 | 13983 | |
| 13963 | 13984 | fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -13968,8 +13989,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13968 | 13989 | var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded); |
| 13969 | 13990 | defer anon_decl.deinit(); |
| 13970 | 13991 | |
| 13971 | const target = sema.mod.getTarget(); | |
| 13972 | const bytes = try ty.nameAllocArena(anon_decl.arena(), target); | |
| 13992 | const bytes = try ty.nameAllocArena(anon_decl.arena(), sema.mod); | |
| 13973 | 13993 | |
| 13974 | 13994 | const new_decl = try anon_decl.finish( |
| 13975 | 13995 | try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len), |
| ... | ... | @@ -14010,7 +14030,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 14010 | 14030 | error.FloatCannotFit => { |
| 14011 | 14031 | return sema.fail(block, operand_src, "integer value {d} cannot be stored in type '{}'", .{ |
| 14012 | 14032 | std.math.floor(val.toFloat(f64)), |
| 14013 | dest_ty.fmt(target), | |
| 14033 | dest_ty.fmt(sema.mod), | |
| 14014 | 14034 | }); |
| 14015 | 14035 | }, |
| 14016 | 14036 | else => |e| return e, |
| ... | ... | @@ -14064,9 +14084,9 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14064 | 14084 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { |
| 14065 | 14085 | const addr = val.toUnsignedInt(target); |
| 14066 | 14086 | if (!type_res.isAllowzeroPtr() and addr == 0) |
| 14067 | return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{type_res.fmt(target)}); | |
| 14087 | return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{type_res.fmt(sema.mod)}); | |
| 14068 | 14088 | if (addr != 0 and addr % ptr_align != 0) |
| 14069 | return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{type_res.fmt(target)}); | |
| 14089 | return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{type_res.fmt(sema.mod)}); | |
| 14070 | 14090 | |
| 14071 | 14091 | const val_payload = try sema.arena.create(Value.Payload.U64); |
| 14072 | 14092 | val_payload.* = .{ |
| ... | ... | @@ -14110,7 +14130,6 @@ fn zirErrSetCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 14110 | 14130 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 14111 | 14131 | const operand = sema.resolveInst(extra.rhs); |
| 14112 | 14132 | const operand_ty = sema.typeOf(operand); |
| 14113 | const target = sema.mod.getTarget(); | |
| 14114 | 14133 | try sema.checkErrorSetType(block, dest_ty_src, dest_ty); |
| 14115 | 14134 | try sema.checkErrorSetType(block, operand_src, operand_ty); |
| 14116 | 14135 | |
| ... | ... | @@ -14124,7 +14143,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 14124 | 14143 | block, |
| 14125 | 14144 | src, |
| 14126 | 14145 | "error.{s} not a member of error set '{}'", |
| 14127 | .{ error_name, dest_ty.fmt(target) }, | |
| 14146 | .{ error_name, dest_ty.fmt(sema.mod) }, | |
| 14128 | 14147 | ); |
| 14129 | 14148 | } |
| 14130 | 14149 | } |
| ... | ... | @@ -14178,11 +14197,11 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 14178 | 14197 | var buf: Type.Payload.ElemType = undefined; |
| 14179 | 14198 | var dest_ptr_info = dest_ty.optionalChild(&buf).ptrInfo().data; |
| 14180 | 14199 | dest_ptr_info.@"align" = operand_align; |
| 14181 | break :blk try Type.optional(sema.arena, try Type.ptr(sema.arena, target, dest_ptr_info)); | |
| 14200 | break :blk try Type.optional(sema.arena, try Type.ptr(sema.arena, sema.mod, dest_ptr_info)); | |
| 14182 | 14201 | } else { |
| 14183 | 14202 | var dest_ptr_info = dest_ty.ptrInfo().data; |
| 14184 | 14203 | dest_ptr_info.@"align" = operand_align; |
| 14185 | break :blk try Type.ptr(sema.arena, target, dest_ptr_info); | |
| 14204 | break :blk try Type.ptr(sema.arena, sema.mod, dest_ptr_info); | |
| 14186 | 14205 | } |
| 14187 | 14206 | }; |
| 14188 | 14207 | |
| ... | ... | @@ -14235,7 +14254,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14235 | 14254 | |
| 14236 | 14255 | if (operand_info.signedness != dest_info.signedness) { |
| 14237 | 14256 | return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{ |
| 14238 | @tagName(dest_info.signedness), operand_ty.fmt(target), | |
| 14257 | @tagName(dest_info.signedness), operand_ty.fmt(sema.mod), | |
| 14239 | 14258 | }); |
| 14240 | 14259 | } |
| 14241 | 14260 | if (operand_info.bits < dest_info.bits) { |
| ... | ... | @@ -14244,7 +14263,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14244 | 14263 | block, |
| 14245 | 14264 | src, |
| 14246 | 14265 | "destination type '{}' has more bits than source type '{}'", |
| 14247 | .{ dest_ty.fmt(target), operand_ty.fmt(target) }, | |
| 14266 | .{ dest_ty.fmt(sema.mod), operand_ty.fmt(sema.mod) }, | |
| 14248 | 14267 | ); |
| 14249 | 14268 | errdefer msg.destroy(sema.gpa); |
| 14250 | 14269 | try sema.errNote(block, dest_ty_src, msg, "destination type has {d} bits", .{ |
| ... | ... | @@ -14270,7 +14289,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14270 | 14289 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 14271 | 14290 | const elems = try sema.arena.alloc(Value, operand_ty.vectorLen()); |
| 14272 | 14291 | for (elems) |*elem, i| { |
| 14273 | const elem_val = val.elemValueBuffer(i, &elem_buf); | |
| 14292 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); | |
| 14274 | 14293 | elem.* = try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, target); |
| 14275 | 14294 | } |
| 14276 | 14295 | return sema.addConstant( |
| ... | ... | @@ -14302,8 +14321,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 14302 | 14321 | // TODO insert safety check that the alignment is correct |
| 14303 | 14322 | |
| 14304 | 14323 | const ptr_info = ptr_ty.ptrInfo().data; |
| 14305 | const target = sema.mod.getTarget(); | |
| 14306 | const dest_ty = try Type.ptr(sema.arena, target, .{ | |
| 14324 | const dest_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 14307 | 14325 | .pointee_type = ptr_info.pointee_type, |
| 14308 | 14326 | .@"align" = dest_align, |
| 14309 | 14327 | .@"addrspace" = ptr_info.@"addrspace", |
| ... | ... | @@ -14346,7 +14364,7 @@ fn zirBitCount( |
| 14346 | 14364 | const elems = try sema.arena.alloc(Value, vec_len); |
| 14347 | 14365 | const scalar_ty = operand_ty.scalarType(); |
| 14348 | 14366 | for (elems) |*elem, i| { |
| 14349 | const elem_val = val.elemValueBuffer(i, &elem_buf); | |
| 14367 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); | |
| 14350 | 14368 | const count = comptimeOp(elem_val, scalar_ty, target); |
| 14351 | 14369 | elem.* = try Value.Tag.int_u64.create(sema.arena, count); |
| 14352 | 14370 | } |
| ... | ... | @@ -14386,7 +14404,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14386 | 14404 | block, |
| 14387 | 14405 | ty_src, |
| 14388 | 14406 | "@byteSwap requires the number of bits to be evenly divisible by 8, but {} has {} bits", |
| 14389 | .{ scalar_ty.fmt(target), bits }, | |
| 14407 | .{ scalar_ty.fmt(sema.mod), bits }, | |
| 14390 | 14408 | ); |
| 14391 | 14409 | } |
| 14392 | 14410 | |
| ... | ... | @@ -14414,7 +14432,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14414 | 14432 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 14415 | 14433 | const elems = try sema.arena.alloc(Value, vec_len); |
| 14416 | 14434 | for (elems) |*elem, i| { |
| 14417 | const elem_val = val.elemValueBuffer(i, &elem_buf); | |
| 14435 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); | |
| 14418 | 14436 | elem.* = try elem_val.byteSwap(operand_ty, target, sema.arena); |
| 14419 | 14437 | } |
| 14420 | 14438 | return sema.addConstant( |
| ... | ... | @@ -14462,7 +14480,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 14462 | 14480 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 14463 | 14481 | const elems = try sema.arena.alloc(Value, vec_len); |
| 14464 | 14482 | for (elems) |*elem, i| { |
| 14465 | const elem_val = val.elemValueBuffer(i, &elem_buf); | |
| 14483 | const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf); | |
| 14466 | 14484 | elem.* = try elem_val.bitReverse(operand_ty, target, sema.arena); |
| 14467 | 14485 | } |
| 14468 | 14486 | return sema.addConstant( |
| ... | ... | @@ -14506,7 +14524,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 14506 | 14524 | block, |
| 14507 | 14525 | lhs_src, |
| 14508 | 14526 | "expected struct type, found '{}'", |
| 14509 | .{ty.fmt(target)}, | |
| 14527 | .{ty.fmt(sema.mod)}, | |
| 14510 | 14528 | ); |
| 14511 | 14529 | } |
| 14512 | 14530 | |
| ... | ... | @@ -14516,7 +14534,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 14516 | 14534 | block, |
| 14517 | 14535 | rhs_src, |
| 14518 | 14536 | "struct '{}' has no field '{s}'", |
| 14519 | .{ ty.fmt(target), field_name }, | |
| 14537 | .{ ty.fmt(sema.mod), field_name }, | |
| 14520 | 14538 | ); |
| 14521 | 14539 | }; |
| 14522 | 14540 | |
| ... | ... | @@ -14542,20 +14560,18 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 14542 | 14560 | } |
| 14543 | 14561 | |
| 14544 | 14562 | fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { |
| 14545 | const target = sema.mod.getTarget(); | |
| 14546 | 14563 | switch (ty.zigTypeTag()) { |
| 14547 | 14564 | .Struct, .Enum, .Union, .Opaque => return, |
| 14548 | else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(target)}), | |
| 14565 | else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(sema.mod)}), | |
| 14549 | 14566 | } |
| 14550 | 14567 | } |
| 14551 | 14568 | |
| 14552 | 14569 | /// Returns `true` if the type was a comptime_int. |
| 14553 | 14570 | fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { |
| 14554 | const target = sema.mod.getTarget(); | |
| 14555 | 14571 | switch (try ty.zigTypeTagOrPoison()) { |
| 14556 | 14572 | .ComptimeInt => return true, |
| 14557 | 14573 | .Int => return false, |
| 14558 | else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(target)}), | |
| 14574 | else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(sema.mod)}), | |
| 14559 | 14575 | } |
| 14560 | 14576 | } |
| 14561 | 14577 | |
| ... | ... | @@ -14565,7 +14581,6 @@ fn checkPtrOperand( |
| 14565 | 14581 | ty_src: LazySrcLoc, |
| 14566 | 14582 | ty: Type, |
| 14567 | 14583 | ) CompileError!void { |
| 14568 | const target = sema.mod.getTarget(); | |
| 14569 | 14584 | switch (ty.zigTypeTag()) { |
| 14570 | 14585 | .Pointer => return, |
| 14571 | 14586 | .Fn => { |
| ... | ... | @@ -14574,7 +14589,7 @@ fn checkPtrOperand( |
| 14574 | 14589 | block, |
| 14575 | 14590 | ty_src, |
| 14576 | 14591 | "expected pointer, found {}", |
| 14577 | .{ty.fmt(target)}, | |
| 14592 | .{ty.fmt(sema.mod)}, | |
| 14578 | 14593 | ); |
| 14579 | 14594 | errdefer msg.destroy(sema.gpa); |
| 14580 | 14595 | |
| ... | ... | @@ -14587,7 +14602,7 @@ fn checkPtrOperand( |
| 14587 | 14602 | .Optional => if (ty.isPtrLikeOptional()) return, |
| 14588 | 14603 | else => {}, |
| 14589 | 14604 | } |
| 14590 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(target)}); | |
| 14605 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)}); | |
| 14591 | 14606 | } |
| 14592 | 14607 | |
| 14593 | 14608 | fn checkPtrType( |
| ... | ... | @@ -14596,7 +14611,6 @@ fn checkPtrType( |
| 14596 | 14611 | ty_src: LazySrcLoc, |
| 14597 | 14612 | ty: Type, |
| 14598 | 14613 | ) CompileError!void { |
| 14599 | const target = sema.mod.getTarget(); | |
| 14600 | 14614 | switch (ty.zigTypeTag()) { |
| 14601 | 14615 | .Pointer => return, |
| 14602 | 14616 | .Fn => { |
| ... | ... | @@ -14605,7 +14619,7 @@ fn checkPtrType( |
| 14605 | 14619 | block, |
| 14606 | 14620 | ty_src, |
| 14607 | 14621 | "expected pointer type, found '{}'", |
| 14608 | .{ty.fmt(target)}, | |
| 14622 | .{ty.fmt(sema.mod)}, | |
| 14609 | 14623 | ); |
| 14610 | 14624 | errdefer msg.destroy(sema.gpa); |
| 14611 | 14625 | |
| ... | ... | @@ -14618,7 +14632,7 @@ fn checkPtrType( |
| 14618 | 14632 | .Optional => if (ty.isPtrLikeOptional()) return, |
| 14619 | 14633 | else => {}, |
| 14620 | 14634 | } |
| 14621 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(target)}); | |
| 14635 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)}); | |
| 14622 | 14636 | } |
| 14623 | 14637 | |
| 14624 | 14638 | fn checkVectorElemType( |
| ... | ... | @@ -14631,8 +14645,7 @@ fn checkVectorElemType( |
| 14631 | 14645 | .Int, .Float, .Bool => return, |
| 14632 | 14646 | else => if (ty.isPtrAtRuntime()) return, |
| 14633 | 14647 | } |
| 14634 | const target = sema.mod.getTarget(); | |
| 14635 | return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(target)}); | |
| 14648 | return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(sema.mod)}); | |
| 14636 | 14649 | } |
| 14637 | 14650 | |
| 14638 | 14651 | fn checkFloatType( |
| ... | ... | @@ -14641,10 +14654,9 @@ fn checkFloatType( |
| 14641 | 14654 | ty_src: LazySrcLoc, |
| 14642 | 14655 | ty: Type, |
| 14643 | 14656 | ) CompileError!void { |
| 14644 | const target = sema.mod.getTarget(); | |
| 14645 | 14657 | switch (ty.zigTypeTag()) { |
| 14646 | 14658 | .ComptimeInt, .ComptimeFloat, .Float => {}, |
| 14647 | else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(target)}), | |
| 14659 | else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(sema.mod)}), | |
| 14648 | 14660 | } |
| 14649 | 14661 | } |
| 14650 | 14662 | |
| ... | ... | @@ -14654,14 +14666,13 @@ fn checkNumericType( |
| 14654 | 14666 | ty_src: LazySrcLoc, |
| 14655 | 14667 | ty: Type, |
| 14656 | 14668 | ) CompileError!void { |
| 14657 | const target = sema.mod.getTarget(); | |
| 14658 | 14669 | switch (ty.zigTypeTag()) { |
| 14659 | 14670 | .ComptimeFloat, .Float, .ComptimeInt, .Int => {}, |
| 14660 | 14671 | .Vector => switch (ty.childType().zigTypeTag()) { |
| 14661 | 14672 | .ComptimeFloat, .Float, .ComptimeInt, .Int => {}, |
| 14662 | 14673 | else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}), |
| 14663 | 14674 | }, |
| 14664 | else => return sema.fail(block, ty_src, "expected number, found '{}'", .{ty.fmt(target)}), | |
| 14675 | else => return sema.fail(block, ty_src, "expected number, found '{}'", .{ty.fmt(sema.mod)}), | |
| 14665 | 14676 | } |
| 14666 | 14677 | } |
| 14667 | 14678 | |
| ... | ... | @@ -14697,7 +14708,7 @@ fn checkAtomicOperandType( |
| 14697 | 14708 | block, |
| 14698 | 14709 | ty_src, |
| 14699 | 14710 | "expected bool, integer, float, enum, or pointer type; found {}", |
| 14700 | .{ty.fmt(target)}, | |
| 14711 | .{ty.fmt(sema.mod)}, | |
| 14701 | 14712 | ); |
| 14702 | 14713 | }, |
| 14703 | 14714 | }; |
| ... | ... | @@ -14761,7 +14772,6 @@ fn checkIntOrVector( |
| 14761 | 14772 | operand_src: LazySrcLoc, |
| 14762 | 14773 | ) CompileError!Type { |
| 14763 | 14774 | const operand_ty = sema.typeOf(operand); |
| 14764 | const target = sema.mod.getTarget(); | |
| 14765 | 14775 | switch (try operand_ty.zigTypeTagOrPoison()) { |
| 14766 | 14776 | .Int => return operand_ty, |
| 14767 | 14777 | .Vector => { |
| ... | ... | @@ -14769,12 +14779,12 @@ fn checkIntOrVector( |
| 14769 | 14779 | switch (try elem_ty.zigTypeTagOrPoison()) { |
| 14770 | 14780 | .Int => return elem_ty, |
| 14771 | 14781 | else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{ |
| 14772 | elem_ty.fmt(target), | |
| 14782 | elem_ty.fmt(sema.mod), | |
| 14773 | 14783 | }), |
| 14774 | 14784 | } |
| 14775 | 14785 | }, |
| 14776 | 14786 | else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{ |
| 14777 | operand_ty.fmt(target), | |
| 14787 | operand_ty.fmt(sema.mod), | |
| 14778 | 14788 | }), |
| 14779 | 14789 | } |
| 14780 | 14790 | } |
| ... | ... | @@ -14786,7 +14796,6 @@ fn checkIntOrVectorAllowComptime( |
| 14786 | 14796 | operand_src: LazySrcLoc, |
| 14787 | 14797 | ) CompileError!Type { |
| 14788 | 14798 | const operand_ty = sema.typeOf(operand); |
| 14789 | const target = sema.mod.getTarget(); | |
| 14790 | 14799 | switch (try operand_ty.zigTypeTagOrPoison()) { |
| 14791 | 14800 | .Int, .ComptimeInt => return operand_ty, |
| 14792 | 14801 | .Vector => { |
| ... | ... | @@ -14794,21 +14803,20 @@ fn checkIntOrVectorAllowComptime( |
| 14794 | 14803 | switch (try elem_ty.zigTypeTagOrPoison()) { |
| 14795 | 14804 | .Int, .ComptimeInt => return elem_ty, |
| 14796 | 14805 | else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{ |
| 14797 | elem_ty.fmt(target), | |
| 14806 | elem_ty.fmt(sema.mod), | |
| 14798 | 14807 | }), |
| 14799 | 14808 | } |
| 14800 | 14809 | }, |
| 14801 | 14810 | else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{ |
| 14802 | operand_ty.fmt(target), | |
| 14811 | operand_ty.fmt(sema.mod), | |
| 14803 | 14812 | }), |
| 14804 | 14813 | } |
| 14805 | 14814 | } |
| 14806 | 14815 | |
| 14807 | 14816 | fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { |
| 14808 | const target = sema.mod.getTarget(); | |
| 14809 | 14817 | switch (ty.zigTypeTag()) { |
| 14810 | 14818 | .ErrorSet => return, |
| 14811 | else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty.fmt(target)}), | |
| 14819 | else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty.fmt(sema.mod)}), | |
| 14812 | 14820 | } |
| 14813 | 14821 | } |
| 14814 | 14822 | |
| ... | ... | @@ -14892,10 +14900,9 @@ fn checkVectorizableBinaryOperands( |
| 14892 | 14900 | return sema.failWithOwnedErrorMsg(block, msg); |
| 14893 | 14901 | } |
| 14894 | 14902 | } else { |
| 14895 | const target = sema.mod.getTarget(); | |
| 14896 | 14903 | const msg = msg: { |
| 14897 | 14904 | const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: {} and {}", .{ |
| 14898 | lhs_ty.fmt(target), rhs_ty.fmt(target), | |
| 14905 | lhs_ty.fmt(sema.mod), rhs_ty.fmt(sema.mod), | |
| 14899 | 14906 | }); |
| 14900 | 14907 | errdefer msg.destroy(sema.gpa); |
| 14901 | 14908 | if (lhs_is_vector) { |
| ... | ... | @@ -14934,9 +14941,8 @@ fn resolveExportOptions( |
| 14934 | 14941 | return sema.fail(block, src, "TODO: implement exporting with linksection", .{}); |
| 14935 | 14942 | } |
| 14936 | 14943 | const name_ty = Type.initTag(.const_slice_u8); |
| 14937 | const target = sema.mod.getTarget(); | |
| 14938 | 14944 | return std.builtin.ExportOptions{ |
| 14939 | .name = try name_val.toAllocatedBytes(name_ty, sema.arena, target), | |
| 14945 | .name = try name_val.toAllocatedBytes(name_ty, sema.arena, sema.mod), | |
| 14940 | 14946 | .linkage = linkage_val.toEnum(std.builtin.GlobalLinkage), |
| 14941 | 14947 | .section = null, // TODO |
| 14942 | 14948 | }; |
| ... | ... | @@ -14995,13 +15001,12 @@ fn zirCmpxchg( |
| 14995 | 15001 | const ptr_ty = sema.typeOf(ptr); |
| 14996 | 15002 | const elem_ty = ptr_ty.elemType(); |
| 14997 | 15003 | try sema.checkAtomicOperandType(block, elem_ty_src, elem_ty); |
| 14998 | const target = sema.mod.getTarget(); | |
| 14999 | 15004 | if (elem_ty.zigTypeTag() == .Float) { |
| 15000 | 15005 | return sema.fail( |
| 15001 | 15006 | block, |
| 15002 | 15007 | elem_ty_src, |
| 15003 | 15008 | "expected bool, integer, enum, or pointer type; found '{}'", |
| 15004 | .{elem_ty.fmt(target)}, | |
| 15009 | .{elem_ty.fmt(sema.mod)}, | |
| 15005 | 15010 | ); |
| 15006 | 15011 | } |
| 15007 | 15012 | const expected_value = try sema.coerce(block, elem_ty, sema.resolveInst(extra.expected_value), expected_src); |
| ... | ... | @@ -15038,7 +15043,7 @@ fn zirCmpxchg( |
| 15038 | 15043 | return sema.addConstUndef(result_ty); |
| 15039 | 15044 | } |
| 15040 | 15045 | const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src; |
| 15041 | const result_val = if (stored_val.eql(expected_val, elem_ty, target)) blk: { | |
| 15046 | const result_val = if (stored_val.eql(expected_val, elem_ty, sema.mod)) blk: { | |
| 15042 | 15047 | try sema.storePtr(block, src, ptr, new_value); |
| 15043 | 15048 | break :blk Value.@"null"; |
| 15044 | 15049 | } else try Value.Tag.opt_payload.create(sema.arena, stored_val); |
| ... | ... | @@ -15103,7 +15108,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15103 | 15108 | const target = sema.mod.getTarget(); |
| 15104 | 15109 | |
| 15105 | 15110 | if (operand_ty.zigTypeTag() != .Vector) { |
| 15106 | return sema.fail(block, operand_src, "expected vector, found {}", .{operand_ty.fmt(target)}); | |
| 15111 | return sema.fail(block, operand_src, "expected vector, found {}", .{operand_ty.fmt(sema.mod)}); | |
| 15107 | 15112 | } |
| 15108 | 15113 | |
| 15109 | 15114 | const scalar_ty = operand_ty.childType(); |
| ... | ... | @@ -15113,13 +15118,13 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15113 | 15118 | .And, .Or, .Xor => switch (scalar_ty.zigTypeTag()) { |
| 15114 | 15119 | .Int, .Bool => {}, |
| 15115 | 15120 | else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found {}", .{ |
| 15116 | @tagName(operation), operand_ty.fmt(target), | |
| 15121 | @tagName(operation), operand_ty.fmt(sema.mod), | |
| 15117 | 15122 | }), |
| 15118 | 15123 | }, |
| 15119 | 15124 | .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag()) { |
| 15120 | 15125 | .Int, .Float => {}, |
| 15121 | 15126 | else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found {}", .{ |
| 15122 | @tagName(operation), operand_ty.fmt(target), | |
| 15127 | @tagName(operation), operand_ty.fmt(sema.mod), | |
| 15123 | 15128 | }), |
| 15124 | 15129 | }, |
| 15125 | 15130 | } |
| ... | ... | @@ -15134,11 +15139,11 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15134 | 15139 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { |
| 15135 | 15140 | if (operand_val.isUndef()) return sema.addConstUndef(scalar_ty); |
| 15136 | 15141 | |
| 15137 | var accum: Value = try operand_val.elemValue(sema.arena, 0); | |
| 15142 | var accum: Value = try operand_val.elemValue(sema.mod, sema.arena, 0); | |
| 15138 | 15143 | var elem_buf: Value.ElemValueBuffer = undefined; |
| 15139 | 15144 | var i: u32 = 1; |
| 15140 | 15145 | while (i < vec_len) : (i += 1) { |
| 15141 | const elem_val = operand_val.elemValueBuffer(i, &elem_buf); | |
| 15146 | const elem_val = operand_val.elemValueBuffer(sema.mod, i, &elem_buf); | |
| 15142 | 15147 | switch (operation) { |
| 15143 | 15148 | .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena, target), |
| 15144 | 15149 | .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena, target), |
| ... | ... | @@ -15174,11 +15179,10 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 15174 | 15179 | var b = sema.resolveInst(extra.b); |
| 15175 | 15180 | var mask = sema.resolveInst(extra.mask); |
| 15176 | 15181 | var mask_ty = sema.typeOf(mask); |
| 15177 | const target = sema.mod.getTarget(); | |
| 15178 | 15182 | |
| 15179 | 15183 | const mask_len = switch (sema.typeOf(mask).zigTypeTag()) { |
| 15180 | 15184 | .Array, .Vector => sema.typeOf(mask).arrayLen(), |
| 15181 | else => return sema.fail(block, mask_src, "expected vector or array, found {}", .{sema.typeOf(mask).fmt(target)}), | |
| 15185 | else => return sema.fail(block, mask_src, "expected vector or array, found {}", .{sema.typeOf(mask).fmt(sema.mod)}), | |
| 15182 | 15186 | }; |
| 15183 | 15187 | mask_ty = try Type.Tag.vector.create(sema.arena, .{ |
| 15184 | 15188 | .len = mask_len, |
| ... | ... | @@ -15210,21 +15214,20 @@ fn analyzeShuffle( |
| 15210 | 15214 | .elem_type = elem_ty, |
| 15211 | 15215 | }); |
| 15212 | 15216 | |
| 15213 | const target = sema.mod.getTarget(); | |
| 15214 | 15217 | var maybe_a_len = switch (sema.typeOf(a).zigTypeTag()) { |
| 15215 | 15218 | .Array, .Vector => sema.typeOf(a).arrayLen(), |
| 15216 | 15219 | .Undefined => null, |
| 15217 | 15220 | else => return sema.fail(block, a_src, "expected vector or array with element type {}, found {}", .{ |
| 15218 | elem_ty.fmt(target), | |
| 15219 | sema.typeOf(a).fmt(target), | |
| 15221 | elem_ty.fmt(sema.mod), | |
| 15222 | sema.typeOf(a).fmt(sema.mod), | |
| 15220 | 15223 | }), |
| 15221 | 15224 | }; |
| 15222 | 15225 | var maybe_b_len = switch (sema.typeOf(b).zigTypeTag()) { |
| 15223 | 15226 | .Array, .Vector => sema.typeOf(b).arrayLen(), |
| 15224 | 15227 | .Undefined => null, |
| 15225 | 15228 | else => return sema.fail(block, b_src, "expected vector or array with element type {}, found {}", .{ |
| 15226 | elem_ty.fmt(target), | |
| 15227 | sema.typeOf(b).fmt(target), | |
| 15229 | elem_ty.fmt(sema.mod), | |
| 15230 | sema.typeOf(b).fmt(sema.mod), | |
| 15228 | 15231 | }), |
| 15229 | 15232 | }; |
| 15230 | 15233 | if (maybe_a_len == null and maybe_b_len == null) { |
| ... | ... | @@ -15253,7 +15256,7 @@ fn analyzeShuffle( |
| 15253 | 15256 | var i: usize = 0; |
| 15254 | 15257 | while (i < mask_len) : (i += 1) { |
| 15255 | 15258 | var buf: Value.ElemValueBuffer = undefined; |
| 15256 | const elem = mask.elemValueBuffer(i, &buf); | |
| 15259 | const elem = mask.elemValueBuffer(sema.mod, i, &buf); | |
| 15257 | 15260 | if (elem.isUndef()) continue; |
| 15258 | 15261 | const int = elem.toSignedInt(); |
| 15259 | 15262 | var unsigned: u32 = undefined; |
| ... | ... | @@ -15272,7 +15275,7 @@ fn analyzeShuffle( |
| 15272 | 15275 | |
| 15273 | 15276 | try sema.errNote(block, operand_info[chosen][1], msg, "selected index {d} out of bounds of {}", .{ |
| 15274 | 15277 | unsigned, |
| 15275 | operand_info[chosen][2].fmt(target), | |
| 15278 | operand_info[chosen][2].fmt(sema.mod), | |
| 15276 | 15279 | }); |
| 15277 | 15280 | |
| 15278 | 15281 | if (chosen == 1) { |
| ... | ... | @@ -15292,7 +15295,7 @@ fn analyzeShuffle( |
| 15292 | 15295 | i = 0; |
| 15293 | 15296 | while (i < mask_len) : (i += 1) { |
| 15294 | 15297 | var buf: Value.ElemValueBuffer = undefined; |
| 15295 | const mask_elem_val = mask.elemValueBuffer(i, &buf); | |
| 15298 | const mask_elem_val = mask.elemValueBuffer(sema.mod, i, &buf); | |
| 15296 | 15299 | if (mask_elem_val.isUndef()) { |
| 15297 | 15300 | values[i] = Value.undef; |
| 15298 | 15301 | continue; |
| ... | ... | @@ -15300,9 +15303,9 @@ fn analyzeShuffle( |
| 15300 | 15303 | const int = mask_elem_val.toSignedInt(); |
| 15301 | 15304 | const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int); |
| 15302 | 15305 | if (int >= 0) { |
| 15303 | values[i] = try a_val.elemValue(sema.arena, unsigned); | |
| 15306 | values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned); | |
| 15304 | 15307 | } else { |
| 15305 | values[i] = try b_val.elemValue(sema.arena, unsigned); | |
| 15308 | values[i] = try b_val.elemValue(sema.mod, sema.arena, unsigned); | |
| 15306 | 15309 | } |
| 15307 | 15310 | } |
| 15308 | 15311 | const res_val = try Value.Tag.aggregate.create(sema.arena, values); |
| ... | ... | @@ -15358,7 +15361,6 @@ fn analyzeShuffle( |
| 15358 | 15361 | fn zirSelect(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 15359 | 15362 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 15360 | 15363 | const extra = sema.code.extraData(Zir.Inst.Select, inst_data.payload_index).data; |
| 15361 | const target = sema.mod.getTarget(); | |
| 15362 | 15364 | |
| 15363 | 15365 | const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 15364 | 15366 | const pred_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| ... | ... | @@ -15372,7 +15374,7 @@ fn zirSelect(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15372 | 15374 | |
| 15373 | 15375 | const vec_len_u64 = switch (try pred_ty.zigTypeTagOrPoison()) { |
| 15374 | 15376 | .Vector, .Array => pred_ty.arrayLen(), |
| 15375 | else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(target)}), | |
| 15377 | else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(sema.mod)}), | |
| 15376 | 15378 | }; |
| 15377 | 15379 | const vec_len = try sema.usizeCast(block, pred_src, vec_len_u64); |
| 15378 | 15380 | |
| ... | ... | @@ -15399,12 +15401,12 @@ fn zirSelect(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15399 | 15401 | var buf: Value.ElemValueBuffer = undefined; |
| 15400 | 15402 | const elems = try sema.gpa.alloc(Value, vec_len); |
| 15401 | 15403 | for (elems) |*elem, i| { |
| 15402 | const pred_elem_val = pred_val.elemValueBuffer(i, &buf); | |
| 15404 | const pred_elem_val = pred_val.elemValueBuffer(sema.mod, i, &buf); | |
| 15403 | 15405 | const should_choose_a = pred_elem_val.toBool(); |
| 15404 | 15406 | if (should_choose_a) { |
| 15405 | elem.* = a_val.elemValueBuffer(i, &buf); | |
| 15407 | elem.* = a_val.elemValueBuffer(sema.mod, i, &buf); | |
| 15406 | 15408 | } else { |
| 15407 | elem.* = b_val.elemValueBuffer(i, &buf); | |
| 15409 | elem.* = b_val.elemValueBuffer(sema.mod, i, &buf); | |
| 15408 | 15410 | } |
| 15409 | 15411 | } |
| 15410 | 15412 | |
| ... | ... | @@ -15630,7 +15632,7 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15630 | 15632 | |
| 15631 | 15633 | switch (ty.zigTypeTag()) { |
| 15632 | 15634 | .ComptimeFloat, .Float, .Vector => {}, |
| 15633 | else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(target)}), | |
| 15635 | else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(sema.mod)}), | |
| 15634 | 15636 | } |
| 15635 | 15637 | |
| 15636 | 15638 | const runtime_src = if (maybe_mulend1) |mulend1_val| rs: { |
| ... | ... | @@ -15704,10 +15706,9 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 15704 | 15706 | break :modifier modifier_val.toEnum(std.builtin.CallOptions.Modifier); |
| 15705 | 15707 | }; |
| 15706 | 15708 | |
| 15707 | const target = sema.mod.getTarget(); | |
| 15708 | 15709 | const args_ty = sema.typeOf(args); |
| 15709 | 15710 | if (!args_ty.isTuple() and args_ty.tag() != .empty_struct_literal) { |
| 15710 | return sema.fail(block, args_src, "expected a tuple, found {}", .{args_ty.fmt(target)}); | |
| 15711 | return sema.fail(block, args_src, "expected a tuple, found {}", .{args_ty.fmt(sema.mod)}); | |
| 15711 | 15712 | } |
| 15712 | 15713 | |
| 15713 | 15714 | var resolved_args: []Air.Inst.Ref = undefined; |
| ... | ... | @@ -15744,10 +15745,9 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 15744 | 15745 | const field_name = try sema.resolveConstString(block, name_src, extra.field_name); |
| 15745 | 15746 | const field_ptr = sema.resolveInst(extra.field_ptr); |
| 15746 | 15747 | const field_ptr_ty = sema.typeOf(field_ptr); |
| 15747 | const target = sema.mod.getTarget(); | |
| 15748 | 15748 | |
| 15749 | 15749 | if (struct_ty.zigTypeTag() != .Struct) { |
| 15750 | return sema.fail(block, ty_src, "expected struct type, found '{}'", .{struct_ty.fmt(target)}); | |
| 15750 | return sema.fail(block, ty_src, "expected struct type, found '{}'", .{struct_ty.fmt(sema.mod)}); | |
| 15751 | 15751 | } |
| 15752 | 15752 | try sema.resolveTypeLayout(block, ty_src, struct_ty); |
| 15753 | 15753 | |
| ... | ... | @@ -15756,7 +15756,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 15756 | 15756 | return sema.failWithBadStructFieldAccess(block, struct_obj, name_src, field_name); |
| 15757 | 15757 | |
| 15758 | 15758 | if (field_ptr_ty.zigTypeTag() != .Pointer) { |
| 15759 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{field_ptr_ty.fmt(target)}); | |
| 15759 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{field_ptr_ty.fmt(sema.mod)}); | |
| 15760 | 15760 | } |
| 15761 | 15761 | const field = struct_obj.fields.values()[field_index]; |
| 15762 | 15762 | const field_ptr_ty_info = field_ptr_ty.ptrInfo().data; |
| ... | ... | @@ -15773,11 +15773,11 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 15773 | 15773 | ptr_ty_data.@"align" = field.abi_align; |
| 15774 | 15774 | } |
| 15775 | 15775 | |
| 15776 | const actual_field_ptr_ty = try Type.ptr(sema.arena, target, ptr_ty_data); | |
| 15776 | const actual_field_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_ty_data); | |
| 15777 | 15777 | const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, ptr_src); |
| 15778 | 15778 | |
| 15779 | 15779 | ptr_ty_data.pointee_type = struct_ty; |
| 15780 | const result_ptr = try Type.ptr(sema.arena, target, ptr_ty_data); | |
| 15780 | const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data); | |
| 15781 | 15781 | |
| 15782 | 15782 | if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| { |
| 15783 | 15783 | const payload = field_ptr_val.castTag(.field_ptr).?.data; |
| ... | ... | @@ -15850,8 +15850,8 @@ fn analyzeMinMax( |
| 15850 | 15850 | var rhs_buf: Value.ElemValueBuffer = undefined; |
| 15851 | 15851 | const elems = try sema.arena.alloc(Value, vec_len); |
| 15852 | 15852 | for (elems) |*elem, i| { |
| 15853 | const lhs_elem_val = lhs_val.elemValueBuffer(i, &lhs_buf); | |
| 15854 | const rhs_elem_val = rhs_val.elemValueBuffer(i, &rhs_buf); | |
| 15853 | const lhs_elem_val = lhs_val.elemValueBuffer(sema.mod, i, &lhs_buf); | |
| 15854 | const rhs_elem_val = rhs_val.elemValueBuffer(sema.mod, i, &rhs_buf); | |
| 15855 | 15855 | elem.* = opFunc(lhs_elem_val, rhs_elem_val, target); |
| 15856 | 15856 | } |
| 15857 | 15857 | return sema.addConstant( |
| ... | ... | @@ -15878,18 +15878,17 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 15878 | 15878 | const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; |
| 15879 | 15879 | const dest_ptr = sema.resolveInst(extra.dest); |
| 15880 | 15880 | const dest_ptr_ty = sema.typeOf(dest_ptr); |
| 15881 | const target = sema.mod.getTarget(); | |
| 15882 | 15881 | |
| 15883 | 15882 | try sema.checkPtrOperand(block, dest_src, dest_ptr_ty); |
| 15884 | 15883 | if (dest_ptr_ty.isConstPtr()) { |
| 15885 | return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(target)}); | |
| 15884 | return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)}); | |
| 15886 | 15885 | } |
| 15887 | 15886 | |
| 15888 | 15887 | const uncasted_src_ptr = sema.resolveInst(extra.source); |
| 15889 | 15888 | const uncasted_src_ptr_ty = sema.typeOf(uncasted_src_ptr); |
| 15890 | 15889 | try sema.checkPtrOperand(block, src_src, uncasted_src_ptr_ty); |
| 15891 | 15890 | const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data; |
| 15892 | const wanted_src_ptr_ty = try Type.ptr(sema.arena, target, .{ | |
| 15891 | const wanted_src_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 15893 | 15892 | .pointee_type = dest_ptr_ty.elemType2(), |
| 15894 | 15893 | .@"align" = src_ptr_info.@"align", |
| 15895 | 15894 | .@"addrspace" = src_ptr_info.@"addrspace", |
| ... | ... | @@ -15936,10 +15935,9 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 15936 | 15935 | const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; |
| 15937 | 15936 | const dest_ptr = sema.resolveInst(extra.dest); |
| 15938 | 15937 | const dest_ptr_ty = sema.typeOf(dest_ptr); |
| 15939 | const target = sema.mod.getTarget(); | |
| 15940 | 15938 | try sema.checkPtrOperand(block, dest_src, dest_ptr_ty); |
| 15941 | 15939 | if (dest_ptr_ty.isConstPtr()) { |
| 15942 | return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(target)}); | |
| 15940 | return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)}); | |
| 15943 | 15941 | } |
| 15944 | 15942 | const elem_ty = dest_ptr_ty.elemType2(); |
| 15945 | 15943 | const value = try sema.coerce(block, elem_ty, sema.resolveInst(extra.byte), value_src); |
| ... | ... | @@ -16057,7 +16055,7 @@ fn zirVarExtended( |
| 16057 | 16055 | }); |
| 16058 | 16056 | |
| 16059 | 16057 | new_var.* = .{ |
| 16060 | .owner_decl = sema.owner_decl, | |
| 16058 | .owner_decl = sema.owner_decl_index, | |
| 16061 | 16059 | .init = init_val, |
| 16062 | 16060 | .is_extern = small.is_extern, |
| 16063 | 16061 | .is_mutable = true, // TODO get rid of this unused field |
| ... | ... | @@ -16294,7 +16292,7 @@ fn zirBuiltinExtern( |
| 16294 | 16292 | |
| 16295 | 16293 | var ty = try sema.resolveType(block, ty_src, extra.lhs); |
| 16296 | 16294 | const options_inst = sema.resolveInst(extra.rhs); |
| 16297 | const target = sema.mod.getTarget(); | |
| 16295 | const mod = sema.mod; | |
| 16298 | 16296 | |
| 16299 | 16297 | const options = options: { |
| 16300 | 16298 | const extern_options_ty = try sema.getBuiltinType(block, options_src, "ExternOptions"); |
| ... | ... | @@ -16315,11 +16313,11 @@ fn zirBuiltinExtern( |
| 16315 | 16313 | var library_name: ?[]const u8 = null; |
| 16316 | 16314 | if (!library_name_val.isNull()) { |
| 16317 | 16315 | const payload = library_name_val.castTag(.opt_payload).?.data; |
| 16318 | library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, target); | |
| 16316 | library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod); | |
| 16319 | 16317 | } |
| 16320 | 16318 | |
| 16321 | 16319 | break :options std.builtin.ExternOptions{ |
| 16322 | .name = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, target), | |
| 16320 | .name = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod), | |
| 16323 | 16321 | .library_name = library_name, |
| 16324 | 16322 | .linkage = linkage_val.toEnum(std.builtin.GlobalLinkage), |
| 16325 | 16323 | .is_thread_local = is_thread_local_val.toBool(), |
| ... | ... | @@ -16344,8 +16342,10 @@ fn zirBuiltinExtern( |
| 16344 | 16342 | |
| 16345 | 16343 | // TODO check duplicate extern |
| 16346 | 16344 | |
| 16347 | const new_decl = try sema.mod.allocateNewDecl(try sema.gpa.dupeZ(u8, options.name), sema.owner_decl.src_namespace, sema.owner_decl.src_node, null); | |
| 16348 | errdefer new_decl.destroy(sema.mod); | |
| 16345 | const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, null); | |
| 16346 | errdefer mod.destroyDecl(new_decl_index); | |
| 16347 | const new_decl = mod.declPtr(new_decl_index); | |
| 16348 | new_decl.name = try sema.gpa.dupeZ(u8, options.name); | |
| 16349 | 16349 | |
| 16350 | 16350 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| 16351 | 16351 | errdefer new_decl_arena.deinit(); |
| ... | ... | @@ -16355,7 +16355,7 @@ fn zirBuiltinExtern( |
| 16355 | 16355 | errdefer new_decl_arena_allocator.destroy(new_var); |
| 16356 | 16356 | |
| 16357 | 16357 | new_var.* = .{ |
| 16358 | .owner_decl = sema.owner_decl, | |
| 16358 | .owner_decl = sema.owner_decl_index, | |
| 16359 | 16359 | .init = Value.initTag(.unreachable_value), |
| 16360 | 16360 | .is_extern = true, |
| 16361 | 16361 | .is_mutable = false, // TODO get rid of this unused field |
| ... | ... | @@ -16378,13 +16378,13 @@ fn zirBuiltinExtern( |
| 16378 | 16378 | new_decl.@"linksection" = null; |
| 16379 | 16379 | new_decl.has_tv = true; |
| 16380 | 16380 | new_decl.analysis = .complete; |
| 16381 | new_decl.generation = sema.mod.generation; | |
| 16381 | new_decl.generation = mod.generation; | |
| 16382 | 16382 | |
| 16383 | 16383 | const arena_state = try new_decl_arena_allocator.create(std.heap.ArenaAllocator.State); |
| 16384 | 16384 | arena_state.* = new_decl_arena.state; |
| 16385 | 16385 | new_decl.value_arena = arena_state; |
| 16386 | 16386 | |
| 16387 | const ref = try sema.analyzeDeclRef(new_decl); | |
| 16387 | const ref = try sema.analyzeDeclRef(new_decl_index); | |
| 16388 | 16388 | try sema.requireRuntimeBlock(block, src); |
| 16389 | 16389 | return block.addBitCast(ty, ref); |
| 16390 | 16390 | } |
| ... | ... | @@ -16412,12 +16412,14 @@ fn validateVarType( |
| 16412 | 16412 | ) CompileError!void { |
| 16413 | 16413 | if (try sema.validateRunTimeType(block, src, var_ty, is_extern)) return; |
| 16414 | 16414 | |
| 16415 | const target = sema.mod.getTarget(); | |
| 16415 | const mod = sema.mod; | |
| 16416 | ||
| 16416 | 16417 | const msg = msg: { |
| 16417 | const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty.fmt(target)}); | |
| 16418 | const msg = try sema.errMsg(block, src, "variable of type '{}' must be const or comptime", .{var_ty.fmt(mod)}); | |
| 16418 | 16419 | errdefer msg.destroy(sema.gpa); |
| 16419 | 16420 | |
| 16420 | try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(block.src_decl), var_ty); | |
| 16421 | const src_decl = mod.declPtr(block.src_decl); | |
| 16422 | try sema.explainWhyTypeIsComptime(block, src, msg, src.toSrcLoc(src_decl), var_ty); | |
| 16421 | 16423 | |
| 16422 | 16424 | break :msg msg; |
| 16423 | 16425 | }; |
| ... | ... | @@ -16489,7 +16491,6 @@ fn explainWhyTypeIsComptime( |
| 16489 | 16491 | ty: Type, |
| 16490 | 16492 | ) CompileError!void { |
| 16491 | 16493 | const mod = sema.mod; |
| 16492 | const target = mod.getTarget(); | |
| 16493 | 16494 | switch (ty.zigTypeTag()) { |
| 16494 | 16495 | .Bool, |
| 16495 | 16496 | .Int, |
| ... | ... | @@ -16503,7 +16504,7 @@ fn explainWhyTypeIsComptime( |
| 16503 | 16504 | |
| 16504 | 16505 | .Fn => { |
| 16505 | 16506 | try mod.errNoteNonLazy(src_loc, msg, "use '*const {}' for a function pointer type", .{ |
| 16506 | ty.fmt(target), | |
| 16507 | ty.fmt(sema.mod), | |
| 16507 | 16508 | }); |
| 16508 | 16509 | }, |
| 16509 | 16510 | |
| ... | ... | @@ -16534,7 +16535,7 @@ fn explainWhyTypeIsComptime( |
| 16534 | 16535 | if (ty.castTag(.@"struct")) |payload| { |
| 16535 | 16536 | const struct_obj = payload.data; |
| 16536 | 16537 | for (struct_obj.fields.values()) |field, i| { |
| 16537 | const field_src_loc = struct_obj.fieldSrcLoc(sema.gpa, .{ | |
| 16538 | const field_src_loc = struct_obj.fieldSrcLoc(sema.mod, .{ | |
| 16538 | 16539 | .index = i, |
| 16539 | 16540 | .range = .type, |
| 16540 | 16541 | }); |
| ... | ... | @@ -16551,7 +16552,7 @@ fn explainWhyTypeIsComptime( |
| 16551 | 16552 | if (ty.cast(Type.Payload.Union)) |payload| { |
| 16552 | 16553 | const union_obj = payload.data; |
| 16553 | 16554 | for (union_obj.fields.values()) |field, i| { |
| 16554 | const field_src_loc = union_obj.fieldSrcLoc(sema.gpa, .{ | |
| 16555 | const field_src_loc = union_obj.fieldSrcLoc(sema.mod, .{ | |
| 16555 | 16556 | .index = i, |
| 16556 | 16557 | .range = .type, |
| 16557 | 16558 | }); |
| ... | ... | @@ -16668,7 +16669,7 @@ fn panicWithMsg( |
| 16668 | 16669 | const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); |
| 16669 | 16670 | const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); |
| 16670 | 16671 | const target = mod.getTarget(); |
| 16671 | const ptr_stack_trace_ty = try Type.ptr(arena, target, .{ | |
| 16672 | const ptr_stack_trace_ty = try Type.ptr(arena, mod, .{ | |
| 16672 | 16673 | .pointee_type = stack_trace_ty, |
| 16673 | 16674 | .@"addrspace" = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic |
| 16674 | 16675 | }); |
| ... | ... | @@ -16748,8 +16749,6 @@ fn fieldVal( |
| 16748 | 16749 | else |
| 16749 | 16750 | object_ty; |
| 16750 | 16751 | |
| 16751 | const target = sema.mod.getTarget(); | |
| 16752 | ||
| 16753 | 16752 | switch (inner_ty.zigTypeTag()) { |
| 16754 | 16753 | .Array => { |
| 16755 | 16754 | if (mem.eql(u8, field_name, "len")) { |
| ... | ... | @@ -16762,7 +16761,7 @@ fn fieldVal( |
| 16762 | 16761 | block, |
| 16763 | 16762 | field_name_src, |
| 16764 | 16763 | "no member named '{s}' in '{}'", |
| 16765 | .{ field_name, object_ty.fmt(target) }, | |
| 16764 | .{ field_name, object_ty.fmt(sema.mod) }, | |
| 16766 | 16765 | ); |
| 16767 | 16766 | } |
| 16768 | 16767 | }, |
| ... | ... | @@ -16786,7 +16785,7 @@ fn fieldVal( |
| 16786 | 16785 | block, |
| 16787 | 16786 | field_name_src, |
| 16788 | 16787 | "no member named '{s}' in '{}'", |
| 16789 | .{ field_name, object_ty.fmt(target) }, | |
| 16788 | .{ field_name, object_ty.fmt(sema.mod) }, | |
| 16790 | 16789 | ); |
| 16791 | 16790 | } |
| 16792 | 16791 | } else if (ptr_info.pointee_type.zigTypeTag() == .Array) { |
| ... | ... | @@ -16800,7 +16799,7 @@ fn fieldVal( |
| 16800 | 16799 | block, |
| 16801 | 16800 | field_name_src, |
| 16802 | 16801 | "no member named '{s}' in '{}'", |
| 16803 | .{ field_name, ptr_info.pointee_type.fmt(target) }, | |
| 16802 | .{ field_name, ptr_info.pointee_type.fmt(sema.mod) }, | |
| 16804 | 16803 | ); |
| 16805 | 16804 | } |
| 16806 | 16805 | } |
| ... | ... | @@ -16822,7 +16821,7 @@ fn fieldVal( |
| 16822 | 16821 | break :blk entry.key_ptr.*; |
| 16823 | 16822 | } |
| 16824 | 16823 | return sema.fail(block, src, "no error named '{s}' in '{}'", .{ |
| 16825 | field_name, child_type.fmt(target), | |
| 16824 | field_name, child_type.fmt(sema.mod), | |
| 16826 | 16825 | }); |
| 16827 | 16826 | } else (try sema.mod.getErrorValue(field_name)).key; |
| 16828 | 16827 | |
| ... | ... | @@ -16876,10 +16875,10 @@ fn fieldVal( |
| 16876 | 16875 | else => unreachable, |
| 16877 | 16876 | }; |
| 16878 | 16877 | return sema.fail(block, src, "{s} '{}' has no member named '{s}'", .{ |
| 16879 | kw_name, child_type.fmt(target), field_name, | |
| 16878 | kw_name, child_type.fmt(sema.mod), field_name, | |
| 16880 | 16879 | }); |
| 16881 | 16880 | }, |
| 16882 | else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(target)}), | |
| 16881 | else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}), | |
| 16883 | 16882 | } |
| 16884 | 16883 | }, |
| 16885 | 16884 | .Struct => if (is_pointer_to) { |
| ... | ... | @@ -16898,7 +16897,7 @@ fn fieldVal( |
| 16898 | 16897 | }, |
| 16899 | 16898 | else => {}, |
| 16900 | 16899 | } |
| 16901 | return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(target)}); | |
| 16900 | return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); | |
| 16902 | 16901 | } |
| 16903 | 16902 | |
| 16904 | 16903 | fn fieldPtr( |
| ... | ... | @@ -16912,12 +16911,11 @@ fn fieldPtr( |
| 16912 | 16911 | // When editing this function, note that there is corresponding logic to be edited |
| 16913 | 16912 | // in `fieldVal`. This function takes a pointer and returns a pointer. |
| 16914 | 16913 | |
| 16915 | const target = sema.mod.getTarget(); | |
| 16916 | 16914 | const object_ptr_src = src; // TODO better source location |
| 16917 | 16915 | const object_ptr_ty = sema.typeOf(object_ptr); |
| 16918 | 16916 | const object_ty = switch (object_ptr_ty.zigTypeTag()) { |
| 16919 | 16917 | .Pointer => object_ptr_ty.elemType(), |
| 16920 | else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(target)}), | |
| 16918 | else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(sema.mod)}), | |
| 16921 | 16919 | }; |
| 16922 | 16920 | |
| 16923 | 16921 | // Zig allows dereferencing a single pointer during field lookup. Note that |
| ... | ... | @@ -16945,7 +16943,7 @@ fn fieldPtr( |
| 16945 | 16943 | block, |
| 16946 | 16944 | field_name_src, |
| 16947 | 16945 | "no member named '{s}' in '{}'", |
| 16948 | .{ field_name, object_ty.fmt(target) }, | |
| 16946 | .{ field_name, object_ty.fmt(sema.mod) }, | |
| 16949 | 16947 | ); |
| 16950 | 16948 | } |
| 16951 | 16949 | }, |
| ... | ... | @@ -16971,7 +16969,7 @@ fn fieldPtr( |
| 16971 | 16969 | } |
| 16972 | 16970 | try sema.requireRuntimeBlock(block, src); |
| 16973 | 16971 | |
| 16974 | const result_ty = try Type.ptr(sema.arena, target, .{ | |
| 16972 | const result_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 16975 | 16973 | .pointee_type = slice_ptr_ty, |
| 16976 | 16974 | .mutable = object_ptr_ty.ptrIsMutable(), |
| 16977 | 16975 | .@"addrspace" = object_ptr_ty.ptrAddressSpace(), |
| ... | ... | @@ -16985,13 +16983,13 @@ fn fieldPtr( |
| 16985 | 16983 | |
| 16986 | 16984 | return sema.analyzeDeclRef(try anon_decl.finish( |
| 16987 | 16985 | Type.usize, |
| 16988 | try Value.Tag.int_u64.create(anon_decl.arena(), val.sliceLen(target)), | |
| 16986 | try Value.Tag.int_u64.create(anon_decl.arena(), val.sliceLen(sema.mod)), | |
| 16989 | 16987 | 0, // default alignment |
| 16990 | 16988 | )); |
| 16991 | 16989 | } |
| 16992 | 16990 | try sema.requireRuntimeBlock(block, src); |
| 16993 | 16991 | |
| 16994 | const result_ty = try Type.ptr(sema.arena, target, .{ | |
| 16992 | const result_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 16995 | 16993 | .pointee_type = Type.usize, |
| 16996 | 16994 | .mutable = object_ptr_ty.ptrIsMutable(), |
| 16997 | 16995 | .@"addrspace" = object_ptr_ty.ptrAddressSpace(), |
| ... | ... | @@ -17003,7 +17001,7 @@ fn fieldPtr( |
| 17003 | 17001 | block, |
| 17004 | 17002 | field_name_src, |
| 17005 | 17003 | "no member named '{s}' in '{}'", |
| 17006 | .{ field_name, object_ty.fmt(target) }, | |
| 17004 | .{ field_name, object_ty.fmt(sema.mod) }, | |
| 17007 | 17005 | ); |
| 17008 | 17006 | } |
| 17009 | 17007 | }, |
| ... | ... | @@ -17027,7 +17025,7 @@ fn fieldPtr( |
| 17027 | 17025 | break :blk entry.key_ptr.*; |
| 17028 | 17026 | } |
| 17029 | 17027 | return sema.fail(block, src, "no error named '{s}' in '{}'", .{ |
| 17030 | field_name, child_type.fmt(target), | |
| 17028 | field_name, child_type.fmt(sema.mod), | |
| 17031 | 17029 | }); |
| 17032 | 17030 | } else (try sema.mod.getErrorValue(field_name)).key; |
| 17033 | 17031 | |
| ... | ... | @@ -17085,7 +17083,7 @@ fn fieldPtr( |
| 17085 | 17083 | } |
| 17086 | 17084 | return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); |
| 17087 | 17085 | }, |
| 17088 | else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(target)}), | |
| 17086 | else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}), | |
| 17089 | 17087 | } |
| 17090 | 17088 | }, |
| 17091 | 17089 | .Struct => { |
| ... | ... | @@ -17104,7 +17102,7 @@ fn fieldPtr( |
| 17104 | 17102 | }, |
| 17105 | 17103 | else => {}, |
| 17106 | 17104 | } |
| 17107 | return sema.fail(block, src, "type '{}' does not support field access (fieldPtr, {}.{s})", .{ object_ty.fmt(target), object_ptr_ty.fmt(target), field_name }); | |
| 17105 | return sema.fail(block, src, "type '{}' does not support field access (fieldPtr, {}.{s})", .{ object_ty.fmt(sema.mod), object_ptr_ty.fmt(sema.mod), field_name }); | |
| 17108 | 17106 | } |
| 17109 | 17107 | |
| 17110 | 17108 | fn fieldCallBind( |
| ... | ... | @@ -17118,13 +17116,12 @@ fn fieldCallBind( |
| 17118 | 17116 | // When editing this function, note that there is corresponding logic to be edited |
| 17119 | 17117 | // in `fieldVal`. This function takes a pointer and returns a pointer. |
| 17120 | 17118 | |
| 17121 | const target = sema.mod.getTarget(); | |
| 17122 | 17119 | const raw_ptr_src = src; // TODO better source location |
| 17123 | 17120 | const raw_ptr_ty = sema.typeOf(raw_ptr); |
| 17124 | 17121 | const inner_ty = if (raw_ptr_ty.zigTypeTag() == .Pointer and raw_ptr_ty.ptrSize() == .One) |
| 17125 | 17122 | raw_ptr_ty.childType() |
| 17126 | 17123 | else |
| 17127 | return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(target)}); | |
| 17124 | return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(sema.mod)}); | |
| 17128 | 17125 | |
| 17129 | 17126 | // Optionally dereference a second pointer to get the concrete type. |
| 17130 | 17127 | const is_double_ptr = inner_ty.zigTypeTag() == .Pointer and inner_ty.ptrSize() == .One; |
| ... | ... | @@ -17184,7 +17181,7 @@ fn fieldCallBind( |
| 17184 | 17181 | first_param_type.zigTypeTag() == .Pointer and |
| 17185 | 17182 | (first_param_type.ptrSize() == .One or |
| 17186 | 17183 | first_param_type.ptrSize() == .C) and |
| 17187 | first_param_type.childType().eql(concrete_ty, target))) | |
| 17184 | first_param_type.childType().eql(concrete_ty, sema.mod))) | |
| 17188 | 17185 | { |
| 17189 | 17186 | // zig fmt: on |
| 17190 | 17187 | // TODO: bound fn calls on rvalues should probably |
| ... | ... | @@ -17195,7 +17192,7 @@ fn fieldCallBind( |
| 17195 | 17192 | .arg0_inst = object_ptr, |
| 17196 | 17193 | }); |
| 17197 | 17194 | return sema.addConstant(ty, value); |
| 17198 | } else if (first_param_type.eql(concrete_ty, target)) { | |
| 17195 | } else if (first_param_type.eql(concrete_ty, sema.mod)) { | |
| 17199 | 17196 | var deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| 17200 | 17197 | const ty = Type.Tag.bound_fn.init(); |
| 17201 | 17198 | const value = try Value.Tag.bound_fn.create(arena, .{ |
| ... | ... | @@ -17211,7 +17208,7 @@ fn fieldCallBind( |
| 17211 | 17208 | else => {}, |
| 17212 | 17209 | } |
| 17213 | 17210 | |
| 17214 | return sema.fail(block, src, "type '{}' has no field or member function named '{s}'", .{ concrete_ty.fmt(target), field_name }); | |
| 17211 | return sema.fail(block, src, "type '{}' has no field or member function named '{s}'", .{ concrete_ty.fmt(sema.mod), field_name }); | |
| 17215 | 17212 | } |
| 17216 | 17213 | |
| 17217 | 17214 | fn finishFieldCallBind( |
| ... | ... | @@ -17224,8 +17221,7 @@ fn finishFieldCallBind( |
| 17224 | 17221 | object_ptr: Air.Inst.Ref, |
| 17225 | 17222 | ) CompileError!Air.Inst.Ref { |
| 17226 | 17223 | const arena = sema.arena; |
| 17227 | const target = sema.mod.getTarget(); | |
| 17228 | const ptr_field_ty = try Type.ptr(arena, target, .{ | |
| 17224 | const ptr_field_ty = try Type.ptr(arena, sema.mod, .{ | |
| 17229 | 17225 | .pointee_type = field_ty, |
| 17230 | 17226 | .mutable = ptr_ty.ptrIsMutable(), |
| 17231 | 17227 | .@"addrspace" = ptr_ty.ptrAddressSpace(), |
| ... | ... | @@ -17254,9 +17250,10 @@ fn namespaceLookup( |
| 17254 | 17250 | src: LazySrcLoc, |
| 17255 | 17251 | namespace: *Namespace, |
| 17256 | 17252 | decl_name: []const u8, |
| 17257 | ) CompileError!?*Decl { | |
| 17253 | ) CompileError!?Decl.Index { | |
| 17258 | 17254 | const gpa = sema.gpa; |
| 17259 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl| { | |
| 17255 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| { | |
| 17256 | const decl = sema.mod.declPtr(decl_index); | |
| 17260 | 17257 | if (!decl.is_pub and decl.getFileScope() != block.getFileScope()) { |
| 17261 | 17258 | const msg = msg: { |
| 17262 | 17259 | const msg = try sema.errMsg(block, src, "'{s}' is not marked 'pub'", .{ |
| ... | ... | @@ -17268,7 +17265,7 @@ fn namespaceLookup( |
| 17268 | 17265 | }; |
| 17269 | 17266 | return sema.failWithOwnedErrorMsg(block, msg); |
| 17270 | 17267 | } |
| 17271 | return decl; | |
| 17268 | return decl_index; | |
| 17272 | 17269 | } |
| 17273 | 17270 | return null; |
| 17274 | 17271 | } |
| ... | ... | @@ -17377,7 +17374,7 @@ fn structFieldPtrByIndex( |
| 17377 | 17374 | ptr_ty_data.@"align" = field.abi_align; |
| 17378 | 17375 | } |
| 17379 | 17376 | |
| 17380 | const ptr_field_ty = try Type.ptr(sema.arena, target, ptr_ty_data); | |
| 17377 | const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, ptr_ty_data); | |
| 17381 | 17378 | |
| 17382 | 17379 | if (field.is_comptime) { |
| 17383 | 17380 | var anon_decl = try block.startAnonDecl(field_src); |
| ... | ... | @@ -17476,15 +17473,14 @@ fn tupleFieldIndex( |
| 17476 | 17473 | field_name: []const u8, |
| 17477 | 17474 | field_name_src: LazySrcLoc, |
| 17478 | 17475 | ) CompileError!u32 { |
| 17479 | const target = sema.mod.getTarget(); | |
| 17480 | 17476 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { |
| 17481 | 17477 | return sema.fail(block, field_name_src, "tuple {} has no such field '{s}': {s}", .{ |
| 17482 | tuple_ty.fmt(target), field_name, @errorName(err), | |
| 17478 | tuple_ty.fmt(sema.mod), field_name, @errorName(err), | |
| 17483 | 17479 | }); |
| 17484 | 17480 | }; |
| 17485 | 17481 | if (field_index >= tuple_ty.structFieldCount()) { |
| 17486 | 17482 | return sema.fail(block, field_name_src, "tuple {} has no such field '{s}'", .{ |
| 17487 | tuple_ty.fmt(target), field_name, | |
| 17483 | tuple_ty.fmt(sema.mod), field_name, | |
| 17488 | 17484 | }); |
| 17489 | 17485 | } |
| 17490 | 17486 | return field_index; |
| ... | ... | @@ -17535,8 +17531,7 @@ fn unionFieldPtr( |
| 17535 | 17531 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 17536 | 17532 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 17537 | 17533 | const field = union_obj.fields.values()[field_index]; |
| 17538 | const target = sema.mod.getTarget(); | |
| 17539 | const ptr_field_ty = try Type.ptr(arena, target, .{ | |
| 17534 | const ptr_field_ty = try Type.ptr(arena, sema.mod, .{ | |
| 17540 | 17535 | .pointee_type = field.ty, |
| 17541 | 17536 | .mutable = union_ptr_ty.ptrIsMutable(), |
| 17542 | 17537 | .@"addrspace" = union_ptr_ty.ptrAddressSpace(), |
| ... | ... | @@ -17559,7 +17554,7 @@ fn unionFieldPtr( |
| 17559 | 17554 | // .data = field_index, |
| 17560 | 17555 | //}; |
| 17561 | 17556 | //const field_tag = Value.initPayload(&field_tag_buf.base); |
| 17562 | //const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, target); | |
| 17557 | //const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, mod); | |
| 17563 | 17558 | //if (!tag_matches) { |
| 17564 | 17559 | // // TODO enhance this saying which one was active |
| 17565 | 17560 | // // and which one was accessed, and showing where the union was declared. |
| ... | ... | @@ -17608,8 +17603,7 @@ fn unionFieldVal( |
| 17608 | 17603 | .data = field_index, |
| 17609 | 17604 | }; |
| 17610 | 17605 | const field_tag = Value.initPayload(&field_tag_buf.base); |
| 17611 | const target = sema.mod.getTarget(); | |
| 17612 | const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, target); | |
| 17606 | const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); | |
| 17613 | 17607 | switch (union_obj.layout) { |
| 17614 | 17608 | .Auto => { |
| 17615 | 17609 | if (tag_matches) { |
| ... | ... | @@ -17630,7 +17624,7 @@ fn unionFieldVal( |
| 17630 | 17624 | if (tag_matches) { |
| 17631 | 17625 | return sema.addConstant(field.ty, tag_and_val.val); |
| 17632 | 17626 | } else { |
| 17633 | const old_ty = union_ty.unionFieldType(tag_and_val.tag, target); | |
| 17627 | const old_ty = union_ty.unionFieldType(tag_and_val.tag, sema.mod); | |
| 17634 | 17628 | const new_val = try sema.bitCastVal(block, src, tag_and_val.val, old_ty, field.ty, 0); |
| 17635 | 17629 | return sema.addConstant(field.ty, new_val); |
| 17636 | 17630 | } |
| ... | ... | @@ -17655,17 +17649,17 @@ fn elemPtr( |
| 17655 | 17649 | const target = sema.mod.getTarget(); |
| 17656 | 17650 | const indexable_ty = switch (indexable_ptr_ty.zigTypeTag()) { |
| 17657 | 17651 | .Pointer => indexable_ptr_ty.elemType(), |
| 17658 | else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(target)}), | |
| 17652 | else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(sema.mod)}), | |
| 17659 | 17653 | }; |
| 17660 | 17654 | if (!indexable_ty.isIndexable()) { |
| 17661 | return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(target)}); | |
| 17655 | return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(sema.mod)}); | |
| 17662 | 17656 | } |
| 17663 | 17657 | |
| 17664 | 17658 | switch (indexable_ty.zigTypeTag()) { |
| 17665 | 17659 | .Pointer => { |
| 17666 | 17660 | // In all below cases, we have to deref the ptr operand to get the actual indexable pointer. |
| 17667 | 17661 | const indexable = try sema.analyzeLoad(block, indexable_ptr_src, indexable_ptr, indexable_ptr_src); |
| 17668 | const result_ty = try indexable_ty.elemPtrType(sema.arena, target); | |
| 17662 | const result_ty = try indexable_ty.elemPtrType(sema.arena, sema.mod); | |
| 17669 | 17663 | switch (indexable_ty.ptrSize()) { |
| 17670 | 17664 | .Slice => return sema.elemPtrSlice(block, indexable_ptr_src, indexable, elem_index_src, elem_index), |
| 17671 | 17665 | .Many, .C => { |
| ... | ... | @@ -17676,7 +17670,7 @@ fn elemPtr( |
| 17676 | 17670 | const ptr_val = maybe_ptr_val orelse break :rs indexable_ptr_src; |
| 17677 | 17671 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 17678 | 17672 | const index = @intCast(usize, index_val.toUnsignedInt(target)); |
| 17679 | const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, target); | |
| 17673 | const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod); | |
| 17680 | 17674 | return sema.addConstant(result_ty, elem_ptr); |
| 17681 | 17675 | }; |
| 17682 | 17676 | |
| ... | ... | @@ -17713,7 +17707,7 @@ fn elemVal( |
| 17713 | 17707 | const target = sema.mod.getTarget(); |
| 17714 | 17708 | |
| 17715 | 17709 | if (!indexable_ty.isIndexable()) { |
| 17716 | return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(target)}); | |
| 17710 | return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(sema.mod)}); | |
| 17717 | 17711 | } |
| 17718 | 17712 | |
| 17719 | 17713 | // TODO in case of a vector of pointers, we need to detect whether the element |
| ... | ... | @@ -17731,7 +17725,7 @@ fn elemVal( |
| 17731 | 17725 | const indexable_val = maybe_indexable_val orelse break :rs indexable_src; |
| 17732 | 17726 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 17733 | 17727 | const index = @intCast(usize, index_val.toUnsignedInt(target)); |
| 17734 | const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, target); | |
| 17728 | const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, sema.mod); | |
| 17735 | 17729 | if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| { |
| 17736 | 17730 | return sema.addConstant(indexable_ty.elemType2(), elem_val); |
| 17737 | 17731 | } |
| ... | ... | @@ -17785,8 +17779,7 @@ fn tupleFieldPtr( |
| 17785 | 17779 | } |
| 17786 | 17780 | |
| 17787 | 17781 | const field_ty = tuple_fields.types[field_index]; |
| 17788 | const target = sema.mod.getTarget(); | |
| 17789 | const ptr_field_ty = try Type.ptr(sema.arena, target, .{ | |
| 17782 | const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 17790 | 17783 | .pointee_type = field_ty, |
| 17791 | 17784 | .mutable = tuple_ptr_ty.ptrIsMutable(), |
| 17792 | 17785 | .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(), |
| ... | ... | @@ -17881,7 +17874,7 @@ fn elemValArray( |
| 17881 | 17874 | } |
| 17882 | 17875 | if (maybe_index_val) |index_val| { |
| 17883 | 17876 | const index = @intCast(usize, index_val.toUnsignedInt(target)); |
| 17884 | const elem_val = try array_val.elemValue(sema.arena, index); | |
| 17877 | const elem_val = try array_val.elemValue(sema.mod, sema.arena, index); | |
| 17885 | 17878 | return sema.addConstant(elem_ty, elem_val); |
| 17886 | 17879 | } |
| 17887 | 17880 | } |
| ... | ... | @@ -17914,7 +17907,7 @@ fn elemPtrArray( |
| 17914 | 17907 | const array_sent = array_ty.sentinel() != null; |
| 17915 | 17908 | const array_len = array_ty.arrayLen(); |
| 17916 | 17909 | const array_len_s = array_len + @boolToInt(array_sent); |
| 17917 | const elem_ptr_ty = try array_ptr_ty.elemPtrType(sema.arena, target); | |
| 17910 | const elem_ptr_ty = try array_ptr_ty.elemPtrType(sema.arena, sema.mod); | |
| 17918 | 17911 | |
| 17919 | 17912 | if (array_len_s == 0) { |
| 17920 | 17913 | return sema.fail(block, elem_index_src, "indexing into empty array", .{}); |
| ... | ... | @@ -17937,7 +17930,7 @@ fn elemPtrArray( |
| 17937 | 17930 | } |
| 17938 | 17931 | if (maybe_index_val) |index_val| { |
| 17939 | 17932 | const index = @intCast(usize, index_val.toUnsignedInt(target)); |
| 17940 | const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, sema.arena, index, target); | |
| 17933 | const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, sema.arena, index, sema.mod); | |
| 17941 | 17934 | return sema.addConstant(elem_ptr_ty, elem_ptr); |
| 17942 | 17935 | } |
| 17943 | 17936 | } |
| ... | ... | @@ -17977,7 +17970,7 @@ fn elemValSlice( |
| 17977 | 17970 | |
| 17978 | 17971 | if (maybe_slice_val) |slice_val| { |
| 17979 | 17972 | runtime_src = elem_index_src; |
| 17980 | const slice_len = slice_val.sliceLen(target); | |
| 17973 | const slice_len = slice_val.sliceLen(sema.mod); | |
| 17981 | 17974 | const slice_len_s = slice_len + @boolToInt(slice_sent); |
| 17982 | 17975 | if (slice_len_s == 0) { |
| 17983 | 17976 | return sema.fail(block, elem_index_src, "indexing into empty slice", .{}); |
| ... | ... | @@ -17988,7 +17981,7 @@ fn elemValSlice( |
| 17988 | 17981 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; |
| 17989 | 17982 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); |
| 17990 | 17983 | } |
| 17991 | const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, target); | |
| 17984 | const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, sema.mod); | |
| 17992 | 17985 | if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| { |
| 17993 | 17986 | return sema.addConstant(elem_ty, elem_val); |
| 17994 | 17987 | } |
| ... | ... | @@ -17999,7 +17992,7 @@ fn elemValSlice( |
| 17999 | 17992 | try sema.requireRuntimeBlock(block, runtime_src); |
| 18000 | 17993 | if (block.wantSafety()) { |
| 18001 | 17994 | const len_inst = if (maybe_slice_val) |slice_val| |
| 18002 | try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(target)) | |
| 17995 | try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod)) | |
| 18003 | 17996 | else |
| 18004 | 17997 | try block.addTyOp(.slice_len, Type.usize, slice); |
| 18005 | 17998 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| ... | ... | @@ -18020,7 +18013,7 @@ fn elemPtrSlice( |
| 18020 | 18013 | const target = sema.mod.getTarget(); |
| 18021 | 18014 | const slice_ty = sema.typeOf(slice); |
| 18022 | 18015 | const slice_sent = slice_ty.sentinel() != null; |
| 18023 | const elem_ptr_ty = try slice_ty.elemPtrType(sema.arena, target); | |
| 18016 | const elem_ptr_ty = try slice_ty.elemPtrType(sema.arena, sema.mod); | |
| 18024 | 18017 | |
| 18025 | 18018 | const maybe_undef_slice_val = try sema.resolveMaybeUndefVal(block, slice_src, slice); |
| 18026 | 18019 | // index must be defined since it can index out of bounds |
| ... | ... | @@ -18030,7 +18023,7 @@ fn elemPtrSlice( |
| 18030 | 18023 | if (slice_val.isUndef()) { |
| 18031 | 18024 | return sema.addConstUndef(elem_ptr_ty); |
| 18032 | 18025 | } |
| 18033 | const slice_len = slice_val.sliceLen(target); | |
| 18026 | const slice_len = slice_val.sliceLen(sema.mod); | |
| 18034 | 18027 | const slice_len_s = slice_len + @boolToInt(slice_sent); |
| 18035 | 18028 | if (slice_len_s == 0) { |
| 18036 | 18029 | return sema.fail(block, elem_index_src, "indexing into empty slice", .{}); |
| ... | ... | @@ -18041,7 +18034,7 @@ fn elemPtrSlice( |
| 18041 | 18034 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; |
| 18042 | 18035 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); |
| 18043 | 18036 | } |
| 18044 | const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, target); | |
| 18037 | const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, sema.mod); | |
| 18045 | 18038 | return sema.addConstant(elem_ptr_ty, elem_ptr_val); |
| 18046 | 18039 | } |
| 18047 | 18040 | } |
| ... | ... | @@ -18052,7 +18045,7 @@ fn elemPtrSlice( |
| 18052 | 18045 | const len_inst = len: { |
| 18053 | 18046 | if (maybe_undef_slice_val) |slice_val| |
| 18054 | 18047 | if (!slice_val.isUndef()) |
| 18055 | break :len try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(target)); | |
| 18048 | break :len try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod)); | |
| 18056 | 18049 | break :len try block.addTyOp(.slice_len, Type.usize, slice); |
| 18057 | 18050 | }; |
| 18058 | 18051 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| ... | ... | @@ -18079,7 +18072,7 @@ fn coerce( |
| 18079 | 18072 | const inst_ty = try sema.resolveTypeFields(block, inst_src, sema.typeOf(inst)); |
| 18080 | 18073 | const target = sema.mod.getTarget(); |
| 18081 | 18074 | // If the types are the same, we can return the operand. |
| 18082 | if (dest_ty.eql(inst_ty, target)) | |
| 18075 | if (dest_ty.eql(inst_ty, sema.mod)) | |
| 18083 | 18076 | return inst; |
| 18084 | 18077 | |
| 18085 | 18078 | const arena = sema.arena; |
| ... | ... | @@ -18185,7 +18178,7 @@ fn coerce( |
| 18185 | 18178 | // *[N:s]T to [*]T |
| 18186 | 18179 | if (dest_info.sentinel) |dst_sentinel| { |
| 18187 | 18180 | if (array_ty.sentinel()) |src_sentinel| { |
| 18188 | if (src_sentinel.eql(dst_sentinel, dst_elem_type, target)) { | |
| 18181 | if (src_sentinel.eql(dst_sentinel, dst_elem_type, sema.mod)) { | |
| 18189 | 18182 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 18190 | 18183 | } |
| 18191 | 18184 | } |
| ... | ... | @@ -18254,7 +18247,7 @@ fn coerce( |
| 18254 | 18247 | } |
| 18255 | 18248 | if (inst_info.size == .Slice) { |
| 18256 | 18249 | if (dest_info.sentinel == null or inst_info.sentinel == null or |
| 18257 | !dest_info.sentinel.?.eql(inst_info.sentinel.?, dest_info.pointee_type, target)) | |
| 18250 | !dest_info.sentinel.?.eql(inst_info.sentinel.?, dest_info.pointee_type, sema.mod)) | |
| 18258 | 18251 | break :p; |
| 18259 | 18252 | |
| 18260 | 18253 | const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty); |
| ... | ... | @@ -18334,7 +18327,7 @@ fn coerce( |
| 18334 | 18327 | } |
| 18335 | 18328 | |
| 18336 | 18329 | if (dest_info.sentinel == null or inst_info.sentinel == null or |
| 18337 | !dest_info.sentinel.?.eql(inst_info.sentinel.?, dest_info.pointee_type, target)) | |
| 18330 | !dest_info.sentinel.?.eql(inst_info.sentinel.?, dest_info.pointee_type, sema.mod)) | |
| 18338 | 18331 | break :p; |
| 18339 | 18332 | |
| 18340 | 18333 | const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty); |
| ... | ... | @@ -18347,11 +18340,16 @@ fn coerce( |
| 18347 | 18340 | const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse break :float; |
| 18348 | 18341 | |
| 18349 | 18342 | if (val.floatHasFraction()) { |
| 18350 | return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val.fmtValue(inst_ty, target), dest_ty.fmt(target) }); | |
| 18343 | return sema.fail( | |
| 18344 | block, | |
| 18345 | inst_src, | |
| 18346 | "fractional component prevents float value {} from coercion to type '{}'", | |
| 18347 | .{ val.fmtValue(inst_ty, sema.mod), dest_ty.fmt(sema.mod) }, | |
| 18348 | ); | |
| 18351 | 18349 | } |
| 18352 | 18350 | const result_val = val.floatToInt(sema.arena, inst_ty, dest_ty, target) catch |err| switch (err) { |
| 18353 | 18351 | error.FloatCannotFit => { |
| 18354 | return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty.fmt(target) }); | |
| 18352 | return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty.fmt(sema.mod) }); | |
| 18355 | 18353 | }, |
| 18356 | 18354 | else => |e| return e, |
| 18357 | 18355 | }; |
| ... | ... | @@ -18361,7 +18359,7 @@ fn coerce( |
| 18361 | 18359 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 18362 | 18360 | // comptime known integer to other number |
| 18363 | 18361 | if (!val.intFitsInType(dest_ty, target)) { |
| 18364 | return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty.fmt(target), val.fmtValue(inst_ty, target) }); | |
| 18362 | return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) }); | |
| 18365 | 18363 | } |
| 18366 | 18364 | return try sema.addConstant(dest_ty, val); |
| 18367 | 18365 | } |
| ... | ... | @@ -18391,12 +18389,12 @@ fn coerce( |
| 18391 | 18389 | .Float => { |
| 18392 | 18390 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 18393 | 18391 | const result_val = try val.floatCast(sema.arena, dest_ty, target); |
| 18394 | if (!val.eql(result_val, dest_ty, target)) { | |
| 18392 | if (!val.eql(result_val, dest_ty, sema.mod)) { | |
| 18395 | 18393 | return sema.fail( |
| 18396 | 18394 | block, |
| 18397 | 18395 | inst_src, |
| 18398 | 18396 | "type {} cannot represent float value {}", |
| 18399 | .{ dest_ty.fmt(target), val.fmtValue(inst_ty, target) }, | |
| 18397 | .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) }, | |
| 18400 | 18398 | ); |
| 18401 | 18399 | } |
| 18402 | 18400 | return try sema.addConstant(dest_ty, result_val); |
| ... | ... | @@ -18415,12 +18413,12 @@ fn coerce( |
| 18415 | 18413 | const result_val = try val.intToFloat(sema.arena, inst_ty, dest_ty, target); |
| 18416 | 18414 | // TODO implement this compile error |
| 18417 | 18415 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); |
| 18418 | //if (!int_again_val.eql(val, inst_ty, target)) { | |
| 18416 | //if (!int_again_val.eql(val, inst_ty, mod)) { | |
| 18419 | 18417 | // return sema.fail( |
| 18420 | 18418 | // block, |
| 18421 | 18419 | // inst_src, |
| 18422 | 18420 | // "type {} cannot represent integer value {}", |
| 18423 | // .{ dest_ty.fmt(target), val }, | |
| 18421 | // .{ dest_ty.fmt(sema.mod), val }, | |
| 18424 | 18422 | // ); |
| 18425 | 18423 | //} |
| 18426 | 18424 | return try sema.addConstant(dest_ty, result_val); |
| ... | ... | @@ -18441,11 +18439,11 @@ fn coerce( |
| 18441 | 18439 | block, |
| 18442 | 18440 | inst_src, |
| 18443 | 18441 | "enum '{}' has no field named '{s}'", |
| 18444 | .{ dest_ty.fmt(target), bytes }, | |
| 18442 | .{ dest_ty.fmt(sema.mod), bytes }, | |
| 18445 | 18443 | ); |
| 18446 | 18444 | errdefer msg.destroy(sema.gpa); |
| 18447 | 18445 | try sema.mod.errNoteNonLazy( |
| 18448 | dest_ty.declSrcLoc(), | |
| 18446 | dest_ty.declSrcLoc(sema.mod), | |
| 18449 | 18447 | msg, |
| 18450 | 18448 | "enum declared here", |
| 18451 | 18449 | .{}, |
| ... | ... | @@ -18462,7 +18460,7 @@ fn coerce( |
| 18462 | 18460 | .Union => blk: { |
| 18463 | 18461 | // union to its own tag type |
| 18464 | 18462 | const union_tag_ty = inst_ty.unionTagType() orelse break :blk; |
| 18465 | if (union_tag_ty.eql(dest_ty, target)) { | |
| 18463 | if (union_tag_ty.eql(dest_ty, sema.mod)) { | |
| 18466 | 18464 | return sema.unionToTag(block, dest_ty, inst, inst_src); |
| 18467 | 18465 | } |
| 18468 | 18466 | }, |
| ... | ... | @@ -18557,7 +18555,7 @@ fn coerce( |
| 18557 | 18555 | return sema.addConstUndef(dest_ty); |
| 18558 | 18556 | } |
| 18559 | 18557 | |
| 18560 | return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_ty.fmt(target), inst_ty.fmt(target) }); | |
| 18558 | return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) }); | |
| 18561 | 18559 | } |
| 18562 | 18560 | |
| 18563 | 18561 | const InMemoryCoercionResult = enum { |
| ... | ... | @@ -18586,7 +18584,7 @@ fn coerceInMemoryAllowed( |
| 18586 | 18584 | dest_src: LazySrcLoc, |
| 18587 | 18585 | src_src: LazySrcLoc, |
| 18588 | 18586 | ) CompileError!InMemoryCoercionResult { |
| 18589 | if (dest_ty.eql(src_ty, target)) | |
| 18587 | if (dest_ty.eql(src_ty, sema.mod)) | |
| 18590 | 18588 | return .ok; |
| 18591 | 18589 | |
| 18592 | 18590 | // Differently-named integers with the same number of bits. |
| ... | ... | @@ -18650,7 +18648,7 @@ fn coerceInMemoryAllowed( |
| 18650 | 18648 | } |
| 18651 | 18649 | const ok_sent = dest_info.sentinel == null or |
| 18652 | 18650 | (src_info.sentinel != null and |
| 18653 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, target)); | |
| 18651 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, sema.mod)); | |
| 18654 | 18652 | if (!ok_sent) { |
| 18655 | 18653 | return .no_match; |
| 18656 | 18654 | } |
| ... | ... | @@ -18893,7 +18891,7 @@ fn coerceInMemoryAllowedPtrs( |
| 18893 | 18891 | |
| 18894 | 18892 | const ok_sent = dest_info.sentinel == null or src_info.size == .C or |
| 18895 | 18893 | (src_info.sentinel != null and |
| 18896 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, target)); | |
| 18894 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, sema.mod)); | |
| 18897 | 18895 | if (!ok_sent) { |
| 18898 | 18896 | return .no_match; |
| 18899 | 18897 | } |
| ... | ... | @@ -18934,7 +18932,7 @@ fn coerceInMemoryAllowedPtrs( |
| 18934 | 18932 | // resolved and we compare the alignment numerically. |
| 18935 | 18933 | alignment: { |
| 18936 | 18934 | if (src_info.@"align" == 0 and dest_info.@"align" == 0 and |
| 18937 | dest_info.pointee_type.eql(src_info.pointee_type, target)) | |
| 18935 | dest_info.pointee_type.eql(src_info.pointee_type, sema.mod)) | |
| 18938 | 18936 | { |
| 18939 | 18937 | break :alignment; |
| 18940 | 18938 | } |
| ... | ... | @@ -19089,8 +19087,7 @@ fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref { |
| 19089 | 19087 | // We have a pointer-to-array and a pointer-to-vector. If the elements and |
| 19090 | 19088 | // lengths match, return the result. |
| 19091 | 19089 | const vector_ty = sema.typeOf(prev_ptr).childType(); |
| 19092 | const target = sema.mod.getTarget(); | |
| 19093 | if (array_ty.childType().eql(vector_ty.childType(), target) and | |
| 19090 | if (array_ty.childType().eql(vector_ty.childType(), sema.mod) and | |
| 19094 | 19091 | array_ty.arrayLen() == vector_ty.vectorLen()) |
| 19095 | 19092 | { |
| 19096 | 19093 | return prev_ptr; |
| ... | ... | @@ -19114,8 +19111,8 @@ fn storePtrVal( |
| 19114 | 19111 | |
| 19115 | 19112 | const bitcasted_val = try sema.bitCastVal(block, src, operand_val, operand_ty, mut_kit.ty, 0); |
| 19116 | 19113 | |
| 19117 | const arena = mut_kit.beginArena(sema.gpa); | |
| 19118 | defer mut_kit.finishArena(); | |
| 19114 | const arena = mut_kit.beginArena(sema.mod); | |
| 19115 | defer mut_kit.finishArena(sema.mod); | |
| 19119 | 19116 | |
| 19120 | 19117 | mut_kit.val.* = try bitcasted_val.copy(arena); |
| 19121 | 19118 | } |
| ... | ... | @@ -19126,13 +19123,15 @@ const ComptimePtrMutationKit = struct { |
| 19126 | 19123 | ty: Type, |
| 19127 | 19124 | decl_arena: std.heap.ArenaAllocator = undefined, |
| 19128 | 19125 | |
| 19129 | fn beginArena(self: *ComptimePtrMutationKit, gpa: Allocator) Allocator { | |
| 19130 | self.decl_arena = self.decl_ref_mut.decl.value_arena.?.promote(gpa); | |
| 19126 | fn beginArena(self: *ComptimePtrMutationKit, mod: *Module) Allocator { | |
| 19127 | const decl = mod.declPtr(self.decl_ref_mut.decl_index); | |
| 19128 | self.decl_arena = decl.value_arena.?.promote(mod.gpa); | |
| 19131 | 19129 | return self.decl_arena.allocator(); |
| 19132 | 19130 | } |
| 19133 | 19131 | |
| 19134 | fn finishArena(self: *ComptimePtrMutationKit) void { | |
| 19135 | self.decl_ref_mut.decl.value_arena.?.* = self.decl_arena.state; | |
| 19132 | fn finishArena(self: *ComptimePtrMutationKit, mod: *Module) void { | |
| 19133 | const decl = mod.declPtr(self.decl_ref_mut.decl_index); | |
| 19134 | decl.value_arena.?.* = self.decl_arena.state; | |
| 19136 | 19135 | self.decl_arena = undefined; |
| 19137 | 19136 | } |
| 19138 | 19137 | }; |
| ... | ... | @@ -19154,10 +19153,11 @@ fn beginComptimePtrMutation( |
| 19154 | 19153 | switch (ptr_val.tag()) { |
| 19155 | 19154 | .decl_ref_mut => { |
| 19156 | 19155 | const decl_ref_mut = ptr_val.castTag(.decl_ref_mut).?.data; |
| 19156 | const decl = sema.mod.declPtr(decl_ref_mut.decl_index); | |
| 19157 | 19157 | return ComptimePtrMutationKit{ |
| 19158 | 19158 | .decl_ref_mut = decl_ref_mut, |
| 19159 | .val = &decl_ref_mut.decl.val, | |
| 19160 | .ty = decl_ref_mut.decl.ty, | |
| 19159 | .val = &decl.val, | |
| 19160 | .ty = decl.ty, | |
| 19161 | 19161 | }; |
| 19162 | 19162 | }, |
| 19163 | 19163 | .elem_ptr => { |
| ... | ... | @@ -19178,8 +19178,8 @@ fn beginComptimePtrMutation( |
| 19178 | 19178 | // An array has been initialized to undefined at comptime and now we |
| 19179 | 19179 | // are for the first time setting an element. We must change the representation |
| 19180 | 19180 | // of the array from `undef` to `array`. |
| 19181 | const arena = parent.beginArena(sema.gpa); | |
| 19182 | defer parent.finishArena(); | |
| 19181 | const arena = parent.beginArena(sema.mod); | |
| 19182 | defer parent.finishArena(sema.mod); | |
| 19183 | 19183 | |
| 19184 | 19184 | const array_len_including_sentinel = |
| 19185 | 19185 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel()); |
| ... | ... | @@ -19200,8 +19200,8 @@ fn beginComptimePtrMutation( |
| 19200 | 19200 | // If we wanted to avoid this, there would need to be special detection |
| 19201 | 19201 | // elsewhere to identify when writing a value to an array element that is stored |
| 19202 | 19202 | // using the `bytes` tag, and handle it without making a call to this function. |
| 19203 | const arena = parent.beginArena(sema.gpa); | |
| 19204 | defer parent.finishArena(); | |
| 19203 | const arena = parent.beginArena(sema.mod); | |
| 19204 | defer parent.finishArena(sema.mod); | |
| 19205 | 19205 | |
| 19206 | 19206 | const bytes = parent.val.castTag(.bytes).?.data; |
| 19207 | 19207 | const dest_len = parent.ty.arrayLenIncludingSentinel(); |
| ... | ... | @@ -19229,8 +19229,8 @@ fn beginComptimePtrMutation( |
| 19229 | 19229 | // need to be special detection elsewhere to identify when writing a value to an |
| 19230 | 19230 | // array element that is stored using the `repeated` tag, and handle it |
| 19231 | 19231 | // without making a call to this function. |
| 19232 | const arena = parent.beginArena(sema.gpa); | |
| 19233 | defer parent.finishArena(); | |
| 19232 | const arena = parent.beginArena(sema.mod); | |
| 19233 | defer parent.finishArena(sema.mod); | |
| 19234 | 19234 | |
| 19235 | 19235 | const repeated_val = try parent.val.castTag(.repeated).?.data.copy(arena); |
| 19236 | 19236 | const array_len_including_sentinel = |
| ... | ... | @@ -19281,8 +19281,8 @@ fn beginComptimePtrMutation( |
| 19281 | 19281 | // A struct or union has been initialized to undefined at comptime and now we |
| 19282 | 19282 | // are for the first time setting a field. We must change the representation |
| 19283 | 19283 | // of the struct/union from `undef` to `struct`/`union`. |
| 19284 | const arena = parent.beginArena(sema.gpa); | |
| 19285 | defer parent.finishArena(); | |
| 19284 | const arena = parent.beginArena(sema.mod); | |
| 19285 | defer parent.finishArena(sema.mod); | |
| 19286 | 19286 | |
| 19287 | 19287 | switch (parent.ty.zigTypeTag()) { |
| 19288 | 19288 | .Struct => { |
| ... | ... | @@ -19322,8 +19322,8 @@ fn beginComptimePtrMutation( |
| 19322 | 19322 | }, |
| 19323 | 19323 | .@"union" => { |
| 19324 | 19324 | // We need to set the active field of the union. |
| 19325 | const arena = parent.beginArena(sema.gpa); | |
| 19326 | defer parent.finishArena(); | |
| 19325 | const arena = parent.beginArena(sema.mod); | |
| 19326 | defer parent.finishArena(sema.mod); | |
| 19327 | 19327 | |
| 19328 | 19328 | const payload = &parent.val.castTag(.@"union").?.data; |
| 19329 | 19329 | payload.tag = try Value.Tag.enum_field_index.create(arena, field_index); |
| ... | ... | @@ -19347,8 +19347,8 @@ fn beginComptimePtrMutation( |
| 19347 | 19347 | // An error union has been initialized to undefined at comptime and now we |
| 19348 | 19348 | // are for the first time setting the payload. We must change the |
| 19349 | 19349 | // representation of the error union from `undef` to `opt_payload`. |
| 19350 | const arena = parent.beginArena(sema.gpa); | |
| 19351 | defer parent.finishArena(); | |
| 19350 | const arena = parent.beginArena(sema.mod); | |
| 19351 | defer parent.finishArena(sema.mod); | |
| 19352 | 19352 | |
| 19353 | 19353 | const payload = try arena.create(Value.Payload.SubValue); |
| 19354 | 19354 | payload.* = .{ |
| ... | ... | @@ -19380,8 +19380,8 @@ fn beginComptimePtrMutation( |
| 19380 | 19380 | // An optional has been initialized to undefined at comptime and now we |
| 19381 | 19381 | // are for the first time setting the payload. We must change the |
| 19382 | 19382 | // representation of the optional from `undef` to `opt_payload`. |
| 19383 | const arena = parent.beginArena(sema.gpa); | |
| 19384 | defer parent.finishArena(); | |
| 19383 | const arena = parent.beginArena(sema.mod); | |
| 19384 | defer parent.finishArena(sema.mod); | |
| 19385 | 19385 | |
| 19386 | 19386 | const payload = try arena.create(Value.Payload.SubValue); |
| 19387 | 19387 | payload.* = .{ |
| ... | ... | @@ -19451,12 +19451,13 @@ fn beginComptimePtrLoad( |
| 19451 | 19451 | .decl_ref, |
| 19452 | 19452 | .decl_ref_mut, |
| 19453 | 19453 | => blk: { |
| 19454 | const decl = switch (ptr_val.tag()) { | |
| 19454 | const decl_index = switch (ptr_val.tag()) { | |
| 19455 | 19455 | .decl_ref => ptr_val.castTag(.decl_ref).?.data, |
| 19456 | .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl, | |
| 19456 | .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index, | |
| 19457 | 19457 | else => unreachable, |
| 19458 | 19458 | }; |
| 19459 | 19459 | const is_mutable = ptr_val.tag() == .decl_ref_mut; |
| 19460 | const decl = sema.mod.declPtr(decl_index); | |
| 19460 | 19461 | const decl_tv = try decl.typedValue(); |
| 19461 | 19462 | if (decl_tv.val.tag() == .variable) return error.RuntimeLoad; |
| 19462 | 19463 | |
| ... | ... | @@ -19477,7 +19478,9 @@ fn beginComptimePtrLoad( |
| 19477 | 19478 | // This code assumes that elem_ptrs have been "flattened" in order for direct dereference |
| 19478 | 19479 | // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that |
| 19479 | 19480 | // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened" |
| 19480 | if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, target))); | |
| 19481 | if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| { | |
| 19482 | assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, sema.mod))); | |
| 19483 | } | |
| 19481 | 19484 | |
| 19482 | 19485 | if (elem_ptr.index != 0) { |
| 19483 | 19486 | if (elem_ty.hasWellDefinedLayout()) { |
| ... | ... | @@ -19510,11 +19513,11 @@ fn beginComptimePtrLoad( |
| 19510 | 19513 | if (maybe_array_ty) |load_ty| { |
| 19511 | 19514 | // It's possible that we're loading a [N]T, in which case we'd like to slice |
| 19512 | 19515 | // the pointee array directly from our parent array. |
| 19513 | if (load_ty.isArrayOrVector() and load_ty.childType().eql(elem_ty, target)) { | |
| 19516 | if (load_ty.isArrayOrVector() and load_ty.childType().eql(elem_ty, sema.mod)) { | |
| 19514 | 19517 | const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel()); |
| 19515 | 19518 | deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{ |
| 19516 | .ty = try Type.array(sema.arena, N, null, elem_ty, target), | |
| 19517 | .val = try array_tv.val.sliceArray(sema.arena, elem_ptr.index, elem_ptr.index + N), | |
| 19519 | .ty = try Type.array(sema.arena, N, null, elem_ty, sema.mod), | |
| 19520 | .val = try array_tv.val.sliceArray(sema.mod, sema.arena, elem_ptr.index, elem_ptr.index + N), | |
| 19518 | 19521 | } else null; |
| 19519 | 19522 | break :blk deref; |
| 19520 | 19523 | } |
| ... | ... | @@ -19522,7 +19525,7 @@ fn beginComptimePtrLoad( |
| 19522 | 19525 | |
| 19523 | 19526 | deref.pointee = if (elem_ptr.index < check_len) TypedValue{ |
| 19524 | 19527 | .ty = elem_ty, |
| 19525 | .val = try array_tv.val.elemValue(sema.arena, elem_ptr.index), | |
| 19528 | .val = try array_tv.val.elemValue(sema.mod, sema.arena, elem_ptr.index), | |
| 19526 | 19529 | } else null; |
| 19527 | 19530 | break :blk deref; |
| 19528 | 19531 | }, |
| ... | ... | @@ -19637,9 +19640,9 @@ fn bitCast( |
| 19637 | 19640 | |
| 19638 | 19641 | if (old_bits != dest_bits) { |
| 19639 | 19642 | return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{ |
| 19640 | dest_ty.fmt(target), | |
| 19643 | dest_ty.fmt(sema.mod), | |
| 19641 | 19644 | dest_bits, |
| 19642 | old_ty.fmt(target), | |
| 19645 | old_ty.fmt(sema.mod), | |
| 19643 | 19646 | old_bits, |
| 19644 | 19647 | }); |
| 19645 | 19648 | } |
| ... | ... | @@ -19662,7 +19665,7 @@ pub fn bitCastVal( |
| 19662 | 19665 | buffer_offset: usize, |
| 19663 | 19666 | ) !Value { |
| 19664 | 19667 | const target = sema.mod.getTarget(); |
| 19665 | if (old_ty.eql(new_ty, target)) return val; | |
| 19668 | if (old_ty.eql(new_ty, sema.mod)) return val; | |
| 19666 | 19669 | |
| 19667 | 19670 | // For types with well-defined memory layouts, we serialize them a byte buffer, |
| 19668 | 19671 | // then deserialize to the new type. |
| ... | ... | @@ -19718,12 +19721,11 @@ fn coerceEnumToUnion( |
| 19718 | 19721 | inst_src: LazySrcLoc, |
| 19719 | 19722 | ) !Air.Inst.Ref { |
| 19720 | 19723 | const inst_ty = sema.typeOf(inst); |
| 19721 | const target = sema.mod.getTarget(); | |
| 19722 | 19724 | |
| 19723 | 19725 | const tag_ty = union_ty.unionTagType() orelse { |
| 19724 | 19726 | const msg = msg: { |
| 19725 | 19727 | const msg = try sema.errMsg(block, inst_src, "expected {}, found {}", .{ |
| 19726 | union_ty.fmt(target), inst_ty.fmt(target), | |
| 19728 | union_ty.fmt(sema.mod), inst_ty.fmt(sema.mod), | |
| 19727 | 19729 | }); |
| 19728 | 19730 | errdefer msg.destroy(sema.gpa); |
| 19729 | 19731 | try sema.errNote(block, union_ty_src, msg, "cannot coerce enum to untagged union", .{}); |
| ... | ... | @@ -19736,10 +19738,10 @@ fn coerceEnumToUnion( |
| 19736 | 19738 | const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src); |
| 19737 | 19739 | if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| { |
| 19738 | 19740 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 19739 | const field_index = union_obj.tag_ty.enumTagFieldIndex(val, target) orelse { | |
| 19741 | const field_index = union_obj.tag_ty.enumTagFieldIndex(val, sema.mod) orelse { | |
| 19740 | 19742 | const msg = msg: { |
| 19741 | 19743 | const msg = try sema.errMsg(block, inst_src, "union {} has no tag with value {}", .{ |
| 19742 | union_ty.fmt(target), val.fmtValue(tag_ty, target), | |
| 19744 | union_ty.fmt(sema.mod), val.fmtValue(tag_ty, sema.mod), | |
| 19743 | 19745 | }); |
| 19744 | 19746 | errdefer msg.destroy(sema.gpa); |
| 19745 | 19747 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | ... | @@ -19753,7 +19755,7 @@ fn coerceEnumToUnion( |
| 19753 | 19755 | const msg = msg: { |
| 19754 | 19756 | const field_name = union_obj.fields.keys()[field_index]; |
| 19755 | 19757 | const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{s}'", .{ |
| 19756 | inst_ty.fmt(target), union_ty.fmt(target), field_ty.fmt(target), field_name, | |
| 19758 | inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod), field_ty.fmt(sema.mod), field_name, | |
| 19757 | 19759 | }); |
| 19758 | 19760 | errdefer msg.destroy(sema.gpa); |
| 19759 | 19761 | |
| ... | ... | @@ -19775,7 +19777,7 @@ fn coerceEnumToUnion( |
| 19775 | 19777 | if (tag_ty.isNonexhaustiveEnum()) { |
| 19776 | 19778 | const msg = msg: { |
| 19777 | 19779 | const msg = try sema.errMsg(block, inst_src, "runtime coercion to union {} from non-exhaustive enum", .{ |
| 19778 | union_ty.fmt(target), | |
| 19780 | union_ty.fmt(sema.mod), | |
| 19779 | 19781 | }); |
| 19780 | 19782 | errdefer msg.destroy(sema.gpa); |
| 19781 | 19783 | try sema.addDeclaredHereNote(msg, tag_ty); |
| ... | ... | @@ -19795,7 +19797,7 @@ fn coerceEnumToUnion( |
| 19795 | 19797 | block, |
| 19796 | 19798 | inst_src, |
| 19797 | 19799 | "runtime coercion from enum '{}' to union '{}' which has non-void fields", |
| 19798 | .{ tag_ty.fmt(target), union_ty.fmt(target) }, | |
| 19800 | .{ tag_ty.fmt(sema.mod), union_ty.fmt(sema.mod) }, | |
| 19799 | 19801 | ); |
| 19800 | 19802 | errdefer msg.destroy(sema.gpa); |
| 19801 | 19803 | |
| ... | ... | @@ -19804,7 +19806,7 @@ fn coerceEnumToUnion( |
| 19804 | 19806 | while (it.next()) |field| { |
| 19805 | 19807 | const field_name = field.key_ptr.*; |
| 19806 | 19808 | const field_ty = field.value_ptr.ty; |
| 19807 | try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(target) }); | |
| 19809 | try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) }); | |
| 19808 | 19810 | field_index += 1; |
| 19809 | 19811 | } |
| 19810 | 19812 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | ... | @@ -19892,7 +19894,7 @@ fn coerceArrayLike( |
| 19892 | 19894 | if (dest_len != inst_len) { |
| 19893 | 19895 | const msg = msg: { |
| 19894 | 19896 | const msg = try sema.errMsg(block, inst_src, "expected {}, found {}", .{ |
| 19895 | dest_ty.fmt(target), inst_ty.fmt(target), | |
| 19897 | dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod), | |
| 19896 | 19898 | }); |
| 19897 | 19899 | errdefer msg.destroy(sema.gpa); |
| 19898 | 19900 | try sema.errNote(block, dest_ty_src, msg, "destination has length {d}", .{dest_len}); |
| ... | ... | @@ -19959,12 +19961,11 @@ fn coerceTupleToArray( |
| 19959 | 19961 | const inst_ty = sema.typeOf(inst); |
| 19960 | 19962 | const inst_len = inst_ty.arrayLen(); |
| 19961 | 19963 | const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen()); |
| 19962 | const target = sema.mod.getTarget(); | |
| 19963 | 19964 | |
| 19964 | 19965 | if (dest_len != inst_len) { |
| 19965 | 19966 | const msg = msg: { |
| 19966 | 19967 | const msg = try sema.errMsg(block, inst_src, "expected {}, found {}", .{ |
| 19967 | dest_ty.fmt(target), inst_ty.fmt(target), | |
| 19968 | dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod), | |
| 19968 | 19969 | }); |
| 19969 | 19970 | errdefer msg.destroy(sema.gpa); |
| 19970 | 19971 | try sema.errNote(block, dest_ty_src, msg, "destination has length {d}", .{dest_len}); |
| ... | ... | @@ -20017,8 +20018,7 @@ fn coerceTupleToSlicePtrs( |
| 20017 | 20018 | const tuple_ty = sema.typeOf(ptr_tuple).childType(); |
| 20018 | 20019 | const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src); |
| 20019 | 20020 | const slice_info = slice_ty.ptrInfo().data; |
| 20020 | const target = sema.mod.getTarget(); | |
| 20021 | const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(), slice_info.sentinel, slice_info.pointee_type, target); | |
| 20021 | const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(), slice_info.sentinel, slice_info.pointee_type, sema.mod); | |
| 20022 | 20022 | const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src); |
| 20023 | 20023 | if (slice_info.@"align" != 0) { |
| 20024 | 20024 | return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{}); |
| ... | ... | @@ -20141,23 +20141,23 @@ fn analyzeDeclVal( |
| 20141 | 20141 | sema: *Sema, |
| 20142 | 20142 | block: *Block, |
| 20143 | 20143 | src: LazySrcLoc, |
| 20144 | decl: *Decl, | |
| 20144 | decl_index: Decl.Index, | |
| 20145 | 20145 | ) CompileError!Air.Inst.Ref { |
| 20146 | if (sema.decl_val_table.get(decl)) |result| { | |
| 20146 | if (sema.decl_val_table.get(decl_index)) |result| { | |
| 20147 | 20147 | return result; |
| 20148 | 20148 | } |
| 20149 | const decl_ref = try sema.analyzeDeclRef(decl); | |
| 20149 | const decl_ref = try sema.analyzeDeclRef(decl_index); | |
| 20150 | 20150 | const result = try sema.analyzeLoad(block, src, decl_ref, src); |
| 20151 | 20151 | if (Air.refToIndex(result)) |index| { |
| 20152 | 20152 | if (sema.air_instructions.items(.tag)[index] == .constant) { |
| 20153 | try sema.decl_val_table.put(sema.gpa, decl, result); | |
| 20153 | try sema.decl_val_table.put(sema.gpa, decl_index, result); | |
| 20154 | 20154 | } |
| 20155 | 20155 | } |
| 20156 | 20156 | return result; |
| 20157 | 20157 | } |
| 20158 | 20158 | |
| 20159 | fn ensureDeclAnalyzed(sema: *Sema, decl: *Decl) CompileError!void { | |
| 20160 | sema.mod.ensureDeclAnalyzed(decl) catch |err| { | |
| 20159 | fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void { | |
| 20160 | sema.mod.ensureDeclAnalyzed(decl_index) catch |err| { | |
| 20161 | 20161 | if (sema.owner_func) |owner_func| { |
| 20162 | 20162 | owner_func.state = .dependency_failure; |
| 20163 | 20163 | } else { |
| ... | ... | @@ -20186,7 +20186,7 @@ fn refValue(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type, val: Value) ! |
| 20186 | 20186 | try val.copy(anon_decl.arena()), |
| 20187 | 20187 | 0, // default alignment |
| 20188 | 20188 | ); |
| 20189 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | |
| 20189 | try sema.mod.declareDeclDependency(sema.owner_decl_index, decl); | |
| 20190 | 20190 | return try Value.Tag.decl_ref.create(sema.arena, decl); |
| 20191 | 20191 | } |
| 20192 | 20192 | |
| ... | ... | @@ -20197,29 +20197,29 @@ fn optRefValue(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type, opt_val: ? |
| 20197 | 20197 | return result; |
| 20198 | 20198 | } |
| 20199 | 20199 | |
| 20200 | fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { | |
| 20201 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | |
| 20202 | try sema.ensureDeclAnalyzed(decl); | |
| 20200 | fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref { | |
| 20201 | try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index); | |
| 20202 | try sema.ensureDeclAnalyzed(decl_index); | |
| 20203 | 20203 | |
| 20204 | const target = sema.mod.getTarget(); | |
| 20204 | const decl = sema.mod.declPtr(decl_index); | |
| 20205 | 20205 | const decl_tv = try decl.typedValue(); |
| 20206 | 20206 | if (decl_tv.val.castTag(.variable)) |payload| { |
| 20207 | 20207 | const variable = payload.data; |
| 20208 | const ty = try Type.ptr(sema.arena, target, .{ | |
| 20208 | const ty = try Type.ptr(sema.arena, sema.mod, .{ | |
| 20209 | 20209 | .pointee_type = decl_tv.ty, |
| 20210 | 20210 | .mutable = variable.is_mutable, |
| 20211 | 20211 | .@"addrspace" = decl.@"addrspace", |
| 20212 | 20212 | .@"align" = decl.@"align", |
| 20213 | 20213 | }); |
| 20214 | return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl)); | |
| 20214 | return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl_index)); | |
| 20215 | 20215 | } |
| 20216 | 20216 | return sema.addConstant( |
| 20217 | try Type.ptr(sema.arena, target, .{ | |
| 20217 | try Type.ptr(sema.arena, sema.mod, .{ | |
| 20218 | 20218 | .pointee_type = decl_tv.ty, |
| 20219 | 20219 | .mutable = false, |
| 20220 | 20220 | .@"addrspace" = decl.@"addrspace", |
| 20221 | 20221 | }), |
| 20222 | try Value.Tag.decl_ref.create(sema.arena, decl), | |
| 20222 | try Value.Tag.decl_ref.create(sema.arena, decl_index), | |
| 20223 | 20223 | ); |
| 20224 | 20224 | } |
| 20225 | 20225 | |
| ... | ... | @@ -20243,13 +20243,12 @@ fn analyzeRef( |
| 20243 | 20243 | |
| 20244 | 20244 | try sema.requireRuntimeBlock(block, src); |
| 20245 | 20245 | const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local); |
| 20246 | const target = sema.mod.getTarget(); | |
| 20247 | const ptr_type = try Type.ptr(sema.arena, target, .{ | |
| 20246 | const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ | |
| 20248 | 20247 | .pointee_type = operand_ty, |
| 20249 | 20248 | .mutable = false, |
| 20250 | 20249 | .@"addrspace" = address_space, |
| 20251 | 20250 | }); |
| 20252 | const mut_ptr_type = try Type.ptr(sema.arena, target, .{ | |
| 20251 | const mut_ptr_type = try Type.ptr(sema.arena, sema.mod, .{ | |
| 20253 | 20252 | .pointee_type = operand_ty, |
| 20254 | 20253 | .@"addrspace" = address_space, |
| 20255 | 20254 | }); |
| ... | ... | @@ -20267,11 +20266,10 @@ fn analyzeLoad( |
| 20267 | 20266 | ptr: Air.Inst.Ref, |
| 20268 | 20267 | ptr_src: LazySrcLoc, |
| 20269 | 20268 | ) CompileError!Air.Inst.Ref { |
| 20270 | const target = sema.mod.getTarget(); | |
| 20271 | 20269 | const ptr_ty = sema.typeOf(ptr); |
| 20272 | 20270 | const elem_ty = switch (ptr_ty.zigTypeTag()) { |
| 20273 | 20271 | .Pointer => ptr_ty.childType(), |
| 20274 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(target)}), | |
| 20272 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}), | |
| 20275 | 20273 | }; |
| 20276 | 20274 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 20277 | 20275 | if (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) |elem_val| { |
| ... | ... | @@ -20310,8 +20308,7 @@ fn analyzeSliceLen( |
| 20310 | 20308 | if (slice_val.isUndef()) { |
| 20311 | 20309 | return sema.addConstUndef(Type.usize); |
| 20312 | 20310 | } |
| 20313 | const target = sema.mod.getTarget(); | |
| 20314 | return sema.addIntUnsigned(Type.usize, slice_val.sliceLen(target)); | |
| 20311 | return sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod)); | |
| 20315 | 20312 | } |
| 20316 | 20313 | try sema.requireRuntimeBlock(block, src); |
| 20317 | 20314 | return block.addTyOp(.slice_len, Type.usize, slice_inst); |
| ... | ... | @@ -20417,8 +20414,9 @@ fn analyzeSlice( |
| 20417 | 20414 | const target = sema.mod.getTarget(); |
| 20418 | 20415 | const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag()) { |
| 20419 | 20416 | .Pointer => ptr_ptr_ty.elemType(), |
| 20420 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(target)}), | |
| 20417 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(sema.mod)}), | |
| 20421 | 20418 | }; |
| 20419 | const mod = sema.mod; | |
| 20422 | 20420 | |
| 20423 | 20421 | var array_ty = ptr_ptr_child_ty; |
| 20424 | 20422 | var slice_ty = ptr_ptr_ty; |
| ... | ... | @@ -20465,7 +20463,7 @@ fn analyzeSlice( |
| 20465 | 20463 | elem_ty = ptr_ptr_child_ty.childType(); |
| 20466 | 20464 | }, |
| 20467 | 20465 | }, |
| 20468 | else => return sema.fail(block, ptr_src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(target)}), | |
| 20466 | else => return sema.fail(block, ptr_src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(mod)}), | |
| 20469 | 20467 | } |
| 20470 | 20468 | |
| 20471 | 20469 | const ptr = if (slice_ty.isSlice()) |
| ... | ... | @@ -20492,7 +20490,7 @@ fn analyzeSlice( |
| 20492 | 20490 | sema.arena, |
| 20493 | 20491 | array_ty.arrayLenIncludingSentinel(), |
| 20494 | 20492 | ); |
| 20495 | if (end_val.compare(.gt, len_s_val, Type.usize, target)) { | |
| 20493 | if (end_val.compare(.gt, len_s_val, Type.usize, mod)) { | |
| 20496 | 20494 | const sentinel_label: []const u8 = if (array_ty.sentinel() != null) |
| 20497 | 20495 | " +1 (sentinel)" |
| 20498 | 20496 | else |
| ... | ... | @@ -20503,8 +20501,8 @@ fn analyzeSlice( |
| 20503 | 20501 | end_src, |
| 20504 | 20502 | "end index {} out of bounds for array of length {}{s}", |
| 20505 | 20503 | .{ |
| 20506 | end_val.fmtValue(Type.usize, target), | |
| 20507 | len_val.fmtValue(Type.usize, target), | |
| 20504 | end_val.fmtValue(Type.usize, mod), | |
| 20505 | len_val.fmtValue(Type.usize, mod), | |
| 20508 | 20506 | sentinel_label, |
| 20509 | 20507 | }, |
| 20510 | 20508 | ); |
| ... | ... | @@ -20513,7 +20511,7 @@ fn analyzeSlice( |
| 20513 | 20511 | // end_is_len is only true if we are NOT using the sentinel |
| 20514 | 20512 | // length. For sentinel-length, we don't want the type to |
| 20515 | 20513 | // contain the sentinel. |
| 20516 | if (end_val.eql(len_val, Type.usize, target)) { | |
| 20514 | if (end_val.eql(len_val, Type.usize, mod)) { | |
| 20517 | 20515 | end_is_len = true; |
| 20518 | 20516 | } |
| 20519 | 20517 | } |
| ... | ... | @@ -20529,10 +20527,10 @@ fn analyzeSlice( |
| 20529 | 20527 | const has_sentinel = slice_ty.sentinel() != null; |
| 20530 | 20528 | var int_payload: Value.Payload.U64 = .{ |
| 20531 | 20529 | .base = .{ .tag = .int_u64 }, |
| 20532 | .data = slice_val.sliceLen(target) + @boolToInt(has_sentinel), | |
| 20530 | .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel), | |
| 20533 | 20531 | }; |
| 20534 | 20532 | const slice_len_val = Value.initPayload(&int_payload.base); |
| 20535 | if (end_val.compare(.gt, slice_len_val, Type.usize, target)) { | |
| 20533 | if (end_val.compare(.gt, slice_len_val, Type.usize, mod)) { | |
| 20536 | 20534 | const sentinel_label: []const u8 = if (has_sentinel) |
| 20537 | 20535 | " +1 (sentinel)" |
| 20538 | 20536 | else |
| ... | ... | @@ -20543,8 +20541,8 @@ fn analyzeSlice( |
| 20543 | 20541 | end_src, |
| 20544 | 20542 | "end index {} out of bounds for slice of length {d}{s}", |
| 20545 | 20543 | .{ |
| 20546 | end_val.fmtValue(Type.usize, target), | |
| 20547 | slice_val.sliceLen(target), | |
| 20544 | end_val.fmtValue(Type.usize, mod), | |
| 20545 | slice_val.sliceLen(mod), | |
| 20548 | 20546 | sentinel_label, |
| 20549 | 20547 | }, |
| 20550 | 20548 | ); |
| ... | ... | @@ -20557,7 +20555,7 @@ fn analyzeSlice( |
| 20557 | 20555 | int_payload.data -= 1; |
| 20558 | 20556 | } |
| 20559 | 20557 | |
| 20560 | if (end_val.eql(slice_len_val, Type.usize, target)) { | |
| 20558 | if (end_val.eql(slice_len_val, Type.usize, mod)) { | |
| 20561 | 20559 | end_is_len = true; |
| 20562 | 20560 | } |
| 20563 | 20561 | } |
| ... | ... | @@ -20590,14 +20588,14 @@ fn analyzeSlice( |
| 20590 | 20588 | // requirement: start <= end |
| 20591 | 20589 | if (try sema.resolveDefinedValue(block, src, end)) |end_val| { |
| 20592 | 20590 | if (try sema.resolveDefinedValue(block, src, start)) |start_val| { |
| 20593 | if (start_val.compare(.gt, end_val, Type.usize, target)) { | |
| 20591 | if (start_val.compare(.gt, end_val, Type.usize, mod)) { | |
| 20594 | 20592 | return sema.fail( |
| 20595 | 20593 | block, |
| 20596 | 20594 | start_src, |
| 20597 | 20595 | "start index {} is larger than end index {}", |
| 20598 | 20596 | .{ |
| 20599 | start_val.fmtValue(Type.usize, target), | |
| 20600 | end_val.fmtValue(Type.usize, target), | |
| 20597 | start_val.fmtValue(Type.usize, mod), | |
| 20598 | end_val.fmtValue(Type.usize, mod), | |
| 20601 | 20599 | }, |
| 20602 | 20600 | ); |
| 20603 | 20601 | } |
| ... | ... | @@ -20613,8 +20611,8 @@ fn analyzeSlice( |
| 20613 | 20611 | if (opt_new_len_val) |new_len_val| { |
| 20614 | 20612 | const new_len_int = new_len_val.toUnsignedInt(target); |
| 20615 | 20613 | |
| 20616 | const return_ty = try Type.ptr(sema.arena, target, .{ | |
| 20617 | .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty, target), | |
| 20614 | const return_ty = try Type.ptr(sema.arena, mod, .{ | |
| 20615 | .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty, mod), | |
| 20618 | 20616 | .sentinel = null, |
| 20619 | 20617 | .@"align" = new_ptr_ty_info.@"align", |
| 20620 | 20618 | .@"addrspace" = new_ptr_ty_info.@"addrspace", |
| ... | ... | @@ -20641,7 +20639,7 @@ fn analyzeSlice( |
| 20641 | 20639 | return sema.fail(block, ptr_src, "non-zero length slice of undefined pointer", .{}); |
| 20642 | 20640 | } |
| 20643 | 20641 | |
| 20644 | const return_ty = try Type.ptr(sema.arena, target, .{ | |
| 20642 | const return_ty = try Type.ptr(sema.arena, mod, .{ | |
| 20645 | 20643 | .pointee_type = elem_ty, |
| 20646 | 20644 | .sentinel = sentinel, |
| 20647 | 20645 | .@"align" = new_ptr_ty_info.@"align", |
| ... | ... | @@ -20667,7 +20665,7 @@ fn analyzeSlice( |
| 20667 | 20665 | if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { |
| 20668 | 20666 | // we don't need to add one for sentinels because the |
| 20669 | 20667 | // underlying value data includes the sentinel |
| 20670 | break :blk try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(target)); | |
| 20668 | break :blk try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(mod)); | |
| 20671 | 20669 | } |
| 20672 | 20670 | |
| 20673 | 20671 | const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); |
| ... | ... | @@ -20920,7 +20918,6 @@ fn cmpVector( |
| 20920 | 20918 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 20921 | 20919 | |
| 20922 | 20920 | const result_ty = try Type.vector(sema.arena, lhs_ty.vectorLen(), Type.@"bool"); |
| 20923 | const target = sema.mod.getTarget(); | |
| 20924 | 20921 | |
| 20925 | 20922 | const runtime_src: LazySrcLoc = src: { |
| 20926 | 20923 | if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| { |
| ... | ... | @@ -20928,7 +20925,7 @@ fn cmpVector( |
| 20928 | 20925 | if (lhs_val.isUndef() or rhs_val.isUndef()) { |
| 20929 | 20926 | return sema.addConstUndef(result_ty); |
| 20930 | 20927 | } |
| 20931 | const cmp_val = try lhs_val.compareVector(op, rhs_val, lhs_ty, sema.arena, target); | |
| 20928 | const cmp_val = try lhs_val.compareVector(op, rhs_val, lhs_ty, sema.arena, sema.mod); | |
| 20932 | 20929 | return sema.addConstant(result_ty, cmp_val); |
| 20933 | 20930 | } else { |
| 20934 | 20931 | break :src rhs_src; |
| ... | ... | @@ -21080,7 +21077,7 @@ fn resolvePeerTypes( |
| 21080 | 21077 | const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison(); |
| 21081 | 21078 | const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison(); |
| 21082 | 21079 | |
| 21083 | if (candidate_ty.eql(chosen_ty, target)) | |
| 21080 | if (candidate_ty.eql(chosen_ty, sema.mod)) | |
| 21084 | 21081 | continue; |
| 21085 | 21082 | |
| 21086 | 21083 | switch (candidate_ty_tag) { |
| ... | ... | @@ -21496,27 +21493,27 @@ fn resolvePeerTypes( |
| 21496 | 21493 | // the source locations. |
| 21497 | 21494 | const chosen_src = candidate_srcs.resolve( |
| 21498 | 21495 | sema.gpa, |
| 21499 | block.src_decl, | |
| 21496 | sema.mod.declPtr(block.src_decl), | |
| 21500 | 21497 | chosen_i, |
| 21501 | 21498 | ); |
| 21502 | 21499 | const candidate_src = candidate_srcs.resolve( |
| 21503 | 21500 | sema.gpa, |
| 21504 | block.src_decl, | |
| 21501 | sema.mod.declPtr(block.src_decl), | |
| 21505 | 21502 | candidate_i + 1, |
| 21506 | 21503 | ); |
| 21507 | 21504 | |
| 21508 | 21505 | const msg = msg: { |
| 21509 | 21506 | const msg = try sema.errMsg(block, src, "incompatible types: '{}' and '{}'", .{ |
| 21510 | chosen_ty.fmt(target), | |
| 21511 | candidate_ty.fmt(target), | |
| 21507 | chosen_ty.fmt(sema.mod), | |
| 21508 | candidate_ty.fmt(sema.mod), | |
| 21512 | 21509 | }); |
| 21513 | 21510 | errdefer msg.destroy(sema.gpa); |
| 21514 | 21511 | |
| 21515 | 21512 | if (chosen_src) |src_loc| |
| 21516 | try sema.errNote(block, src_loc, msg, "type '{}' here", .{chosen_ty.fmt(target)}); | |
| 21513 | try sema.errNote(block, src_loc, msg, "type '{}' here", .{chosen_ty.fmt(sema.mod)}); | |
| 21517 | 21514 | |
| 21518 | 21515 | if (candidate_src) |src_loc| |
| 21519 | try sema.errNote(block, src_loc, msg, "type '{}' here", .{candidate_ty.fmt(target)}); | |
| 21516 | try sema.errNote(block, src_loc, msg, "type '{}' here", .{candidate_ty.fmt(sema.mod)}); | |
| 21520 | 21517 | |
| 21521 | 21518 | break :msg msg; |
| 21522 | 21519 | }; |
| ... | ... | @@ -21538,13 +21535,13 @@ fn resolvePeerTypes( |
| 21538 | 21535 | else => unreachable, |
| 21539 | 21536 | }; |
| 21540 | 21537 | |
| 21541 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); | |
| 21538 | const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data); | |
| 21542 | 21539 | const opt_ptr_ty = if (any_are_null) |
| 21543 | 21540 | try Type.optional(sema.arena, new_ptr_ty) |
| 21544 | 21541 | else |
| 21545 | 21542 | new_ptr_ty; |
| 21546 | 21543 | const set_ty = err_set_ty orelse return opt_ptr_ty; |
| 21547 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, target); | |
| 21544 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod); | |
| 21548 | 21545 | } |
| 21549 | 21546 | |
| 21550 | 21547 | if (seen_const) { |
| ... | ... | @@ -21554,24 +21551,24 @@ fn resolvePeerTypes( |
| 21554 | 21551 | const ptr_ty = chosen_ty.errorUnionPayload(); |
| 21555 | 21552 | var info = ptr_ty.ptrInfo(); |
| 21556 | 21553 | info.data.mutable = false; |
| 21557 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); | |
| 21554 | const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data); | |
| 21558 | 21555 | const opt_ptr_ty = if (any_are_null) |
| 21559 | 21556 | try Type.optional(sema.arena, new_ptr_ty) |
| 21560 | 21557 | else |
| 21561 | 21558 | new_ptr_ty; |
| 21562 | 21559 | const set_ty = err_set_ty orelse chosen_ty.errorUnionSet(); |
| 21563 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, target); | |
| 21560 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod); | |
| 21564 | 21561 | }, |
| 21565 | 21562 | .Pointer => { |
| 21566 | 21563 | var info = chosen_ty.ptrInfo(); |
| 21567 | 21564 | info.data.mutable = false; |
| 21568 | const new_ptr_ty = try Type.ptr(sema.arena, target, info.data); | |
| 21565 | const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data); | |
| 21569 | 21566 | const opt_ptr_ty = if (any_are_null) |
| 21570 | 21567 | try Type.optional(sema.arena, new_ptr_ty) |
| 21571 | 21568 | else |
| 21572 | 21569 | new_ptr_ty; |
| 21573 | 21570 | const set_ty = err_set_ty orelse return opt_ptr_ty; |
| 21574 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, target); | |
| 21571 | return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod); | |
| 21575 | 21572 | }, |
| 21576 | 21573 | else => return chosen_ty, |
| 21577 | 21574 | } |
| ... | ... | @@ -21583,16 +21580,16 @@ fn resolvePeerTypes( |
| 21583 | 21580 | else => try Type.optional(sema.arena, chosen_ty), |
| 21584 | 21581 | }; |
| 21585 | 21582 | const set_ty = err_set_ty orelse return opt_ty; |
| 21586 | return try Type.errorUnion(sema.arena, set_ty, opt_ty, target); | |
| 21583 | return try Type.errorUnion(sema.arena, set_ty, opt_ty, sema.mod); | |
| 21587 | 21584 | } |
| 21588 | 21585 | |
| 21589 | 21586 | if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag()) { |
| 21590 | 21587 | .ErrorSet => return ty, |
| 21591 | 21588 | .ErrorUnion => { |
| 21592 | 21589 | const payload_ty = chosen_ty.errorUnionPayload(); |
| 21593 | return try Type.errorUnion(sema.arena, ty, payload_ty, target); | |
| 21590 | return try Type.errorUnion(sema.arena, ty, payload_ty, sema.mod); | |
| 21594 | 21591 | }, |
| 21595 | else => return try Type.errorUnion(sema.arena, ty, chosen_ty, target), | |
| 21592 | else => return try Type.errorUnion(sema.arena, ty, chosen_ty, sema.mod), | |
| 21596 | 21593 | }; |
| 21597 | 21594 | |
| 21598 | 21595 | return chosen_ty; |
| ... | ... | @@ -21670,12 +21667,11 @@ fn resolveStructLayout( |
| 21670 | 21667 | ) CompileError!void { |
| 21671 | 21668 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 21672 | 21669 | if (resolved_ty.castTag(.@"struct")) |payload| { |
| 21673 | const target = sema.mod.getTarget(); | |
| 21674 | 21670 | const struct_obj = payload.data; |
| 21675 | 21671 | switch (struct_obj.status) { |
| 21676 | 21672 | .none, .have_field_types => {}, |
| 21677 | 21673 | .field_types_wip, .layout_wip => { |
| 21678 | return sema.fail(block, src, "struct {} depends on itself", .{ty.fmt(target)}); | |
| 21674 | return sema.fail(block, src, "struct {} depends on itself", .{ty.fmt(sema.mod)}); | |
| 21679 | 21675 | }, |
| 21680 | 21676 | .have_layout, .fully_resolved_wip, .fully_resolved => return, |
| 21681 | 21677 | } |
| ... | ... | @@ -21703,11 +21699,10 @@ fn resolveUnionLayout( |
| 21703 | 21699 | ) CompileError!void { |
| 21704 | 21700 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 21705 | 21701 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |
| 21706 | const target = sema.mod.getTarget(); | |
| 21707 | 21702 | switch (union_obj.status) { |
| 21708 | 21703 | .none, .have_field_types => {}, |
| 21709 | 21704 | .field_types_wip, .layout_wip => { |
| 21710 | return sema.fail(block, src, "union {} depends on itself", .{ty.fmt(target)}); | |
| 21705 | return sema.fail(block, src, "union {} depends on itself", .{ty.fmt(sema.mod)}); | |
| 21711 | 21706 | }, |
| 21712 | 21707 | .have_layout, .fully_resolved_wip, .fully_resolved => return, |
| 21713 | 21708 | } |
| ... | ... | @@ -21774,10 +21769,6 @@ fn resolveStructFully( |
| 21774 | 21769 | .fully_resolved_wip, .fully_resolved => return, |
| 21775 | 21770 | } |
| 21776 | 21771 | |
| 21777 | log.debug("resolveStructFully {*} ('{s}')", .{ | |
| 21778 | struct_obj.owner_decl, struct_obj.owner_decl.name, | |
| 21779 | }); | |
| 21780 | ||
| 21781 | 21772 | { |
| 21782 | 21773 | // After we have resolve struct layout we have to go over the fields again to |
| 21783 | 21774 | // make sure pointer fields get their child types resolved as well. |
| ... | ... | @@ -21866,11 +21857,10 @@ fn resolveTypeFieldsStruct( |
| 21866 | 21857 | ty: Type, |
| 21867 | 21858 | struct_obj: *Module.Struct, |
| 21868 | 21859 | ) CompileError!void { |
| 21869 | const target = sema.mod.getTarget(); | |
| 21870 | 21860 | switch (struct_obj.status) { |
| 21871 | 21861 | .none => {}, |
| 21872 | 21862 | .field_types_wip => { |
| 21873 | return sema.fail(block, src, "struct {} depends on itself", .{ty.fmt(target)}); | |
| 21863 | return sema.fail(block, src, "struct {} depends on itself", .{ty.fmt(sema.mod)}); | |
| 21874 | 21864 | }, |
| 21875 | 21865 | .have_field_types, |
| 21876 | 21866 | .have_layout, |
| ... | ... | @@ -21897,11 +21887,10 @@ fn resolveTypeFieldsUnion( |
| 21897 | 21887 | ty: Type, |
| 21898 | 21888 | union_obj: *Module.Union, |
| 21899 | 21889 | ) CompileError!void { |
| 21900 | const target = sema.mod.getTarget(); | |
| 21901 | 21890 | switch (union_obj.status) { |
| 21902 | 21891 | .none => {}, |
| 21903 | 21892 | .field_types_wip => { |
| 21904 | return sema.fail(block, src, "union {} depends on itself", .{ty.fmt(target)}); | |
| 21893 | return sema.fail(block, src, "union {} depends on itself", .{ty.fmt(sema.mod)}); | |
| 21905 | 21894 | }, |
| 21906 | 21895 | .have_field_types, |
| 21907 | 21896 | .have_layout, |
| ... | ... | @@ -21945,7 +21934,8 @@ fn resolveInferredErrorSet( |
| 21945 | 21934 | // `*Module.Fn`. Not only is the function not relevant to the inferred error set |
| 21946 | 21935 | // in this case, it may be a generic function which would cause an assertion failure |
| 21947 | 21936 | // if we called `ensureFuncBodyAnalyzed` on it here. |
| 21948 | if (ies.func.owner_decl.ty.fnInfo().return_type.errorUnionSet().castTag(.error_set_inferred).?.data == ies) { | |
| 21937 | const ies_func_owner_decl = sema.mod.declPtr(ies.func.owner_decl); | |
| 21938 | if (ies_func_owner_decl.ty.fnInfo().return_type.errorUnionSet().castTag(.error_set_inferred).?.data == ies) { | |
| 21949 | 21939 | // In this case we are dealing with the actual InferredErrorSet object that |
| 21950 | 21940 | // corresponds to the function, not one created to track an inline/comptime call. |
| 21951 | 21941 | try sema.ensureFuncBodyAnalyzed(ies.func); |
| ... | ... | @@ -21986,7 +21976,7 @@ fn semaStructFields( |
| 21986 | 21976 | defer tracy.end(); |
| 21987 | 21977 | |
| 21988 | 21978 | const gpa = mod.gpa; |
| 21989 | const decl = struct_obj.owner_decl; | |
| 21979 | const decl_index = struct_obj.owner_decl; | |
| 21990 | 21980 | const zir = struct_obj.namespace.file_scope.zir; |
| 21991 | 21981 | const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended; |
| 21992 | 21982 | assert(extended.opcode == .struct_decl); |
| ... | ... | @@ -22026,6 +22016,7 @@ fn semaStructFields( |
| 22026 | 22016 | } |
| 22027 | 22017 | extra_index += body.len; |
| 22028 | 22018 | |
| 22019 | const decl = mod.declPtr(decl_index); | |
| 22029 | 22020 | var decl_arena = decl.value_arena.?.promote(gpa); |
| 22030 | 22021 | defer decl.value_arena.?.* = decl_arena.state; |
| 22031 | 22022 | const decl_arena_allocator = decl_arena.allocator(); |
| ... | ... | @@ -22040,6 +22031,7 @@ fn semaStructFields( |
| 22040 | 22031 | .perm_arena = decl_arena_allocator, |
| 22041 | 22032 | .code = zir, |
| 22042 | 22033 | .owner_decl = decl, |
| 22034 | .owner_decl_index = decl_index, | |
| 22043 | 22035 | .func = null, |
| 22044 | 22036 | .fn_ret_ty = Type.void, |
| 22045 | 22037 | .owner_func = null, |
| ... | ... | @@ -22052,7 +22044,7 @@ fn semaStructFields( |
| 22052 | 22044 | var block_scope: Block = .{ |
| 22053 | 22045 | .parent = null, |
| 22054 | 22046 | .sema = &sema, |
| 22055 | .src_decl = decl, | |
| 22047 | .src_decl = decl_index, | |
| 22056 | 22048 | .namespace = &struct_obj.namespace, |
| 22057 | 22049 | .wip_capture_scope = wip_captures.scope, |
| 22058 | 22050 | .instructions = .{}, |
| ... | ... | @@ -22171,7 +22163,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22171 | 22163 | defer tracy.end(); |
| 22172 | 22164 | |
| 22173 | 22165 | const gpa = mod.gpa; |
| 22174 | const decl = union_obj.owner_decl; | |
| 22166 | const decl_index = union_obj.owner_decl; | |
| 22175 | 22167 | const zir = union_obj.namespace.file_scope.zir; |
| 22176 | 22168 | const extended = zir.instructions.items(.data)[union_obj.zir_index].extended; |
| 22177 | 22169 | assert(extended.opcode == .union_decl); |
| ... | ... | @@ -22217,8 +22209,10 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22217 | 22209 | } |
| 22218 | 22210 | extra_index += body.len; |
| 22219 | 22211 | |
| 22220 | var decl_arena = union_obj.owner_decl.value_arena.?.promote(gpa); | |
| 22221 | defer union_obj.owner_decl.value_arena.?.* = decl_arena.state; | |
| 22212 | const decl = mod.declPtr(decl_index); | |
| 22213 | ||
| 22214 | var decl_arena = decl.value_arena.?.promote(gpa); | |
| 22215 | defer decl.value_arena.?.* = decl_arena.state; | |
| 22222 | 22216 | const decl_arena_allocator = decl_arena.allocator(); |
| 22223 | 22217 | |
| 22224 | 22218 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| ... | ... | @@ -22231,6 +22225,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22231 | 22225 | .perm_arena = decl_arena_allocator, |
| 22232 | 22226 | .code = zir, |
| 22233 | 22227 | .owner_decl = decl, |
| 22228 | .owner_decl_index = decl_index, | |
| 22234 | 22229 | .func = null, |
| 22235 | 22230 | .fn_ret_ty = Type.void, |
| 22236 | 22231 | .owner_func = null, |
| ... | ... | @@ -22243,7 +22238,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22243 | 22238 | var block_scope: Block = .{ |
| 22244 | 22239 | .parent = null, |
| 22245 | 22240 | .sema = &sema, |
| 22246 | .src_decl = decl, | |
| 22241 | .src_decl = decl_index, | |
| 22247 | 22242 | .namespace = &union_obj.namespace, |
| 22248 | 22243 | .wip_capture_scope = wip_captures.scope, |
| 22249 | 22244 | .instructions = .{}, |
| ... | ... | @@ -22353,7 +22348,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22353 | 22348 | const copied_val = try val.copy(decl_arena_allocator); |
| 22354 | 22349 | map.putAssumeCapacityContext(copied_val, {}, .{ |
| 22355 | 22350 | .ty = int_tag_ty, |
| 22356 | .target = target, | |
| 22351 | .mod = mod, | |
| 22357 | 22352 | }); |
| 22358 | 22353 | } else { |
| 22359 | 22354 | const val = if (last_tag_val) |val| |
| ... | ... | @@ -22365,7 +22360,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22365 | 22360 | const copied_val = try val.copy(decl_arena_allocator); |
| 22366 | 22361 | map.putAssumeCapacityContext(copied_val, {}, .{ |
| 22367 | 22362 | .ty = int_tag_ty, |
| 22368 | .target = target, | |
| 22363 | .mod = mod, | |
| 22369 | 22364 | }); |
| 22370 | 22365 | } |
| 22371 | 22366 | } |
| ... | ... | @@ -22411,7 +22406,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil |
| 22411 | 22406 | const enum_has_field = names.orderedRemove(field_name); |
| 22412 | 22407 | if (!enum_has_field) { |
| 22413 | 22408 | const msg = msg: { |
| 22414 | const msg = try sema.errMsg(block, src, "enum '{}' has no field named '{s}'", .{ union_obj.tag_ty.fmt(target), field_name }); | |
| 22409 | const msg = try sema.errMsg(block, src, "enum '{}' has no field named '{s}'", .{ union_obj.tag_ty.fmt(sema.mod), field_name }); | |
| 22415 | 22410 | errdefer msg.destroy(sema.gpa); |
| 22416 | 22411 | try sema.addDeclaredHereNote(msg, union_obj.tag_ty); |
| 22417 | 22412 | break :msg msg; |
| ... | ... | @@ -22475,15 +22470,16 @@ fn generateUnionTagTypeNumbered( |
| 22475 | 22470 | const enum_ty = Type.initPayload(&enum_ty_payload.base); |
| 22476 | 22471 | const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty); |
| 22477 | 22472 | // TODO better type name |
| 22478 | const new_decl = try mod.createAnonymousDecl(block, .{ | |
| 22473 | const new_decl_index = try mod.createAnonymousDecl(block, .{ | |
| 22479 | 22474 | .ty = Type.type, |
| 22480 | 22475 | .val = enum_val, |
| 22481 | 22476 | }); |
| 22477 | const new_decl = mod.declPtr(new_decl_index); | |
| 22482 | 22478 | new_decl.owns_tv = true; |
| 22483 | errdefer mod.abortAnonDecl(new_decl); | |
| 22479 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 22484 | 22480 | |
| 22485 | 22481 | enum_obj.* = .{ |
| 22486 | .owner_decl = new_decl, | |
| 22482 | .owner_decl = new_decl_index, | |
| 22487 | 22483 | .tag_ty = int_ty, |
| 22488 | 22484 | .fields = .{}, |
| 22489 | 22485 | .values = .{}, |
| ... | ... | @@ -22493,7 +22489,7 @@ fn generateUnionTagTypeNumbered( |
| 22493 | 22489 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 22494 | 22490 | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ |
| 22495 | 22491 | .ty = int_ty, |
| 22496 | .target = sema.mod.getTarget(), | |
| 22492 | .mod = mod, | |
| 22497 | 22493 | }); |
| 22498 | 22494 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 22499 | 22495 | return enum_ty; |
| ... | ... | @@ -22515,15 +22511,16 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Ty |
| 22515 | 22511 | const enum_ty = Type.initPayload(&enum_ty_payload.base); |
| 22516 | 22512 | const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty); |
| 22517 | 22513 | // TODO better type name |
| 22518 | const new_decl = try mod.createAnonymousDecl(block, .{ | |
| 22514 | const new_decl_index = try mod.createAnonymousDecl(block, .{ | |
| 22519 | 22515 | .ty = Type.type, |
| 22520 | 22516 | .val = enum_val, |
| 22521 | 22517 | }); |
| 22518 | const new_decl = mod.declPtr(new_decl_index); | |
| 22522 | 22519 | new_decl.owns_tv = true; |
| 22523 | errdefer mod.abortAnonDecl(new_decl); | |
| 22520 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 22524 | 22521 | |
| 22525 | 22522 | enum_obj.* = .{ |
| 22526 | .owner_decl = new_decl, | |
| 22523 | .owner_decl = new_decl_index, | |
| 22527 | 22524 | .fields = .{}, |
| 22528 | 22525 | .node_offset = 0, |
| 22529 | 22526 | }; |
| ... | ... | @@ -22545,7 +22542,7 @@ fn getBuiltin( |
| 22545 | 22542 | const opt_builtin_inst = try sema.namespaceLookupRef( |
| 22546 | 22543 | block, |
| 22547 | 22544 | src, |
| 22548 | std_file.root_decl.?.src_namespace, | |
| 22545 | mod.declPtr(std_file.root_decl.unwrap().?).src_namespace, | |
| 22549 | 22546 | "builtin", |
| 22550 | 22547 | ); |
| 22551 | 22548 | const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst.?, src); |
| ... | ... | @@ -22984,8 +22981,7 @@ fn analyzeComptimeAlloc( |
| 22984 | 22981 | // Needed to make an anon decl with type `var_type` (the `finish()` call below). |
| 22985 | 22982 | _ = try sema.typeHasOnePossibleValue(block, src, var_type); |
| 22986 | 22983 | |
| 22987 | const target = sema.mod.getTarget(); | |
| 22988 | const ptr_type = try Type.ptr(sema.arena, target, .{ | |
| 22984 | const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ | |
| 22989 | 22985 | .pointee_type = var_type, |
| 22990 | 22986 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), |
| 22991 | 22987 | .@"align" = alignment, |
| ... | ... | @@ -22994,7 +22990,7 @@ fn analyzeComptimeAlloc( |
| 22994 | 22990 | var anon_decl = try block.startAnonDecl(src); |
| 22995 | 22991 | defer anon_decl.deinit(); |
| 22996 | 22992 | |
| 22997 | const decl = try anon_decl.finish( | |
| 22993 | const decl_index = try anon_decl.finish( | |
| 22998 | 22994 | try var_type.copy(anon_decl.arena()), |
| 22999 | 22995 | // There will be stores before the first load, but they may be to sub-elements or |
| 23000 | 22996 | // sub-fields. So we need to initialize with undef to allow the mechanism to expand |
| ... | ... | @@ -23002,12 +22998,13 @@ fn analyzeComptimeAlloc( |
| 23002 | 22998 | Value.undef, |
| 23003 | 22999 | alignment, |
| 23004 | 23000 | ); |
| 23001 | const decl = sema.mod.declPtr(decl_index); | |
| 23005 | 23002 | decl.@"align" = alignment; |
| 23006 | 23003 | |
| 23007 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | |
| 23004 | try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index); | |
| 23008 | 23005 | return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{ |
| 23009 | 23006 | .runtime_index = block.runtime_index, |
| 23010 | .decl = decl, | |
| 23007 | .decl_index = decl_index, | |
| 23011 | 23008 | })); |
| 23012 | 23009 | } |
| 23013 | 23010 | |
| ... | ... | @@ -23099,7 +23096,7 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 23099 | 23096 | // The type is not in-memory coercible or the direct dereference failed, so it must |
| 23100 | 23097 | // be bitcast according to the pointer type we are performing the load through. |
| 23101 | 23098 | if (!load_ty.hasWellDefinedLayout()) |
| 23102 | return sema.fail(block, src, "comptime dereference requires {} to have a well-defined layout, but it does not.", .{load_ty.fmt(target)}); | |
| 23099 | return sema.fail(block, src, "comptime dereference requires {} to have a well-defined layout, but it does not.", .{load_ty.fmt(sema.mod)}); | |
| 23103 | 23100 | |
| 23104 | 23101 | const load_sz = try sema.typeAbiSize(block, src, load_ty); |
| 23105 | 23102 | |
| ... | ... | @@ -23114,11 +23111,11 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr |
| 23114 | 23111 | if (deref.ty_without_well_defined_layout) |bad_ty| { |
| 23115 | 23112 | // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem |
| 23116 | 23113 | // is that some type we encountered when de-referencing does not have a well-defined layout. |
| 23117 | return sema.fail(block, src, "comptime dereference requires {} to have a well-defined layout, but it does not.", .{bad_ty.fmt(target)}); | |
| 23114 | return sema.fail(block, src, "comptime dereference requires {} to have a well-defined layout, but it does not.", .{bad_ty.fmt(sema.mod)}); | |
| 23118 | 23115 | } else { |
| 23119 | 23116 | // If all encountered types had well-defined layouts, the parent is the root decl and it just |
| 23120 | 23117 | // wasn't big enough for the load. |
| 23121 | return sema.fail(block, src, "dereference of {} exceeds bounds of containing decl of type {}", .{ ptr_ty.fmt(target), deref.parent.?.tv.ty.fmt(target) }); | |
| 23118 | return sema.fail(block, src, "dereference of {} exceeds bounds of containing decl of type {}", .{ ptr_ty.fmt(sema.mod), deref.parent.?.tv.ty.fmt(sema.mod) }); | |
| 23122 | 23119 | } |
| 23123 | 23120 | } |
| 23124 | 23121 | |
| ... | ... | @@ -23484,9 +23481,8 @@ fn anonStructFieldIndex( |
| 23484 | 23481 | return @intCast(u32, i); |
| 23485 | 23482 | } |
| 23486 | 23483 | } |
| 23487 | const target = sema.mod.getTarget(); | |
| 23488 | 23484 | return sema.fail(block, field_src, "anonymous struct {} has no such field '{s}'", .{ |
| 23489 | struct_ty.fmt(target), field_name, | |
| 23485 | struct_ty.fmt(sema.mod), field_name, | |
| 23490 | 23486 | }); |
| 23491 | 23487 | } |
| 23492 | 23488 |
src/TypedValue.zig+29-23| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const Type = @import("type.zig").Type; |
| 3 | 3 | const Value = @import("value.zig").Value; |
| 4 | const Module = @import("Module.zig"); | |
| 4 | 5 | const Allocator = std.mem.Allocator; |
| 5 | 6 | const TypedValue = @This(); |
| 6 | 7 | const Target = std.Target; |
| ... | ... | @@ -31,13 +32,13 @@ pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue { |
| 31 | 32 | }; |
| 32 | 33 | } |
| 33 | 34 | |
| 34 | pub fn eql(a: TypedValue, b: TypedValue, target: std.Target) bool { | |
| 35 | if (!a.ty.eql(b.ty, target)) return false; | |
| 36 | return a.val.eql(b.val, a.ty, target); | |
| 35 | pub fn eql(a: TypedValue, b: TypedValue, mod: *Module) bool { | |
| 36 | if (!a.ty.eql(b.ty, mod)) return false; | |
| 37 | return a.val.eql(b.val, a.ty, mod); | |
| 37 | 38 | } |
| 38 | 39 | |
| 39 | pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, target: std.Target) void { | |
| 40 | return tv.val.hash(tv.ty, hasher, target); | |
| 40 | pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, mod: *Module) void { | |
| 41 | return tv.val.hash(tv.ty, hasher, mod); | |
| 41 | 42 | } |
| 42 | 43 | |
| 43 | 44 | pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value { |
| ... | ... | @@ -48,7 +49,7 @@ const max_aggregate_items = 100; |
| 48 | 49 | |
| 49 | 50 | const FormatContext = struct { |
| 50 | 51 | tv: TypedValue, |
| 51 | target: Target, | |
| 52 | mod: *Module, | |
| 52 | 53 | }; |
| 53 | 54 | |
| 54 | 55 | pub fn format( |
| ... | ... | @@ -59,7 +60,7 @@ pub fn format( |
| 59 | 60 | ) !void { |
| 60 | 61 | _ = options; |
| 61 | 62 | comptime std.debug.assert(fmt.len == 0); |
| 62 | return ctx.tv.print(writer, 3, ctx.target); | |
| 63 | return ctx.tv.print(writer, 3, ctx.mod); | |
| 63 | 64 | } |
| 64 | 65 | |
| 65 | 66 | /// Prints the Value according to the Type, not according to the Value Tag. |
| ... | ... | @@ -67,8 +68,9 @@ pub fn print( |
| 67 | 68 | tv: TypedValue, |
| 68 | 69 | writer: anytype, |
| 69 | 70 | level: u8, |
| 70 | target: std.Target, | |
| 71 | mod: *Module, | |
| 71 | 72 | ) @TypeOf(writer).Error!void { |
| 73 | const target = mod.getTarget(); | |
| 72 | 74 | var val = tv.val; |
| 73 | 75 | var ty = tv.ty; |
| 74 | 76 | while (true) switch (val.tag()) { |
| ... | ... | @@ -156,7 +158,7 @@ pub fn print( |
| 156 | 158 | try print(.{ |
| 157 | 159 | .ty = fields[i].ty, |
| 158 | 160 | .val = vals[i], |
| 159 | }, writer, level - 1, target); | |
| 161 | }, writer, level - 1, mod); | |
| 160 | 162 | } |
| 161 | 163 | return writer.writeAll(" }"); |
| 162 | 164 | } else { |
| ... | ... | @@ -170,7 +172,7 @@ pub fn print( |
| 170 | 172 | try print(.{ |
| 171 | 173 | .ty = elem_ty, |
| 172 | 174 | .val = vals[i], |
| 173 | }, writer, level - 1, target); | |
| 175 | }, writer, level - 1, mod); | |
| 174 | 176 | } |
| 175 | 177 | return writer.writeAll(" }"); |
| 176 | 178 | } |
| ... | ... | @@ -185,12 +187,12 @@ pub fn print( |
| 185 | 187 | try print(.{ |
| 186 | 188 | .ty = ty.unionTagType().?, |
| 187 | 189 | .val = union_val.tag, |
| 188 | }, writer, level - 1, target); | |
| 190 | }, writer, level - 1, mod); | |
| 189 | 191 | try writer.writeAll(" = "); |
| 190 | 192 | try print(.{ |
| 191 | .ty = ty.unionFieldType(union_val.tag, target), | |
| 193 | .ty = ty.unionFieldType(union_val.tag, mod), | |
| 192 | 194 | .val = union_val.val, |
| 193 | }, writer, level - 1, target); | |
| 195 | }, writer, level - 1, mod); | |
| 194 | 196 | |
| 195 | 197 | return writer.writeAll(" }"); |
| 196 | 198 | }, |
| ... | ... | @@ -205,7 +207,7 @@ pub fn print( |
| 205 | 207 | }, |
| 206 | 208 | .bool_true => return writer.writeAll("true"), |
| 207 | 209 | .bool_false => return writer.writeAll("false"), |
| 208 | .ty => return val.castTag(.ty).?.data.print(writer, target), | |
| 210 | .ty => return val.castTag(.ty).?.data.print(writer, mod), | |
| 209 | 211 | .int_type => { |
| 210 | 212 | const int_type = val.castTag(.int_type).?.data; |
| 211 | 213 | return writer.print("{s}{d}", .{ |
| ... | ... | @@ -222,28 +224,32 @@ pub fn print( |
| 222 | 224 | const x = sub_ty.abiAlignment(target); |
| 223 | 225 | return writer.print("{d}", .{x}); |
| 224 | 226 | }, |
| 225 | .function => return writer.print("(function '{s}')", .{val.castTag(.function).?.data.owner_decl.name}), | |
| 227 | .function => return writer.print("(function '{s}')", .{ | |
| 228 | mod.declPtr(val.castTag(.function).?.data.owner_decl).name, | |
| 229 | }), | |
| 226 | 230 | .extern_fn => return writer.writeAll("(extern function)"), |
| 227 | 231 | .variable => return writer.writeAll("(variable)"), |
| 228 | 232 | .decl_ref_mut => { |
| 229 | const decl = val.castTag(.decl_ref_mut).?.data.decl; | |
| 233 | const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index; | |
| 234 | const decl = mod.declPtr(decl_index); | |
| 230 | 235 | if (level == 0) { |
| 231 | 236 | return writer.print("(decl ref mut '{s}')", .{decl.name}); |
| 232 | 237 | } |
| 233 | 238 | return print(.{ |
| 234 | 239 | .ty = decl.ty, |
| 235 | 240 | .val = decl.val, |
| 236 | }, writer, level - 1, target); | |
| 241 | }, writer, level - 1, mod); | |
| 237 | 242 | }, |
| 238 | 243 | .decl_ref => { |
| 239 | const decl = val.castTag(.decl_ref).?.data; | |
| 244 | const decl_index = val.castTag(.decl_ref).?.data; | |
| 245 | const decl = mod.declPtr(decl_index); | |
| 240 | 246 | if (level == 0) { |
| 241 | 247 | return writer.print("(decl ref '{s}')", .{decl.name}); |
| 242 | 248 | } |
| 243 | 249 | return print(.{ |
| 244 | 250 | .ty = decl.ty, |
| 245 | 251 | .val = decl.val, |
| 246 | }, writer, level - 1, target); | |
| 252 | }, writer, level - 1, mod); | |
| 247 | 253 | }, |
| 248 | 254 | .elem_ptr => { |
| 249 | 255 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| ... | ... | @@ -251,7 +257,7 @@ pub fn print( |
| 251 | 257 | try print(.{ |
| 252 | 258 | .ty = elem_ptr.elem_ty, |
| 253 | 259 | .val = elem_ptr.array_ptr, |
| 254 | }, writer, level - 1, target); | |
| 260 | }, writer, level - 1, mod); | |
| 255 | 261 | return writer.print("[{}]", .{elem_ptr.index}); |
| 256 | 262 | }, |
| 257 | 263 | .field_ptr => { |
| ... | ... | @@ -260,7 +266,7 @@ pub fn print( |
| 260 | 266 | try print(.{ |
| 261 | 267 | .ty = field_ptr.container_ty, |
| 262 | 268 | .val = field_ptr.container_ptr, |
| 263 | }, writer, level - 1, target); | |
| 269 | }, writer, level - 1, mod); | |
| 264 | 270 | |
| 265 | 271 | if (field_ptr.container_ty.zigTypeTag() == .Struct) { |
| 266 | 272 | const field_name = field_ptr.container_ty.structFields().keys()[field_ptr.field_index]; |
| ... | ... | @@ -288,7 +294,7 @@ pub fn print( |
| 288 | 294 | }; |
| 289 | 295 | while (i < max_aggregate_items) : (i += 1) { |
| 290 | 296 | if (i != 0) try writer.writeAll(", "); |
| 291 | try print(elem_tv, writer, level - 1, target); | |
| 297 | try print(elem_tv, writer, level - 1, mod); | |
| 292 | 298 | } |
| 293 | 299 | return writer.writeAll(" }"); |
| 294 | 300 | }, |
| ... | ... | @@ -300,7 +306,7 @@ pub fn print( |
| 300 | 306 | try print(.{ |
| 301 | 307 | .ty = ty.elemType2(), |
| 302 | 308 | .val = ty.sentinel().?, |
| 303 | }, writer, level - 1, target); | |
| 309 | }, writer, level - 1, mod); | |
| 304 | 310 | return writer.writeAll(" }"); |
| 305 | 311 | }, |
| 306 | 312 | .slice => return writer.writeAll("(slice)"), |
src/arch/aarch64/CodeGen.zig+34-24| ... | ... | @@ -237,8 +237,10 @@ pub fn generate( |
| 237 | 237 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 238 | 238 | } |
| 239 | 239 | |
| 240 | assert(module_fn.owner_decl.has_tv); | |
| 241 | const fn_type = module_fn.owner_decl.ty; | |
| 240 | const mod = bin_file.options.module.?; | |
| 241 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 242 | assert(fn_owner_decl.has_tv); | |
| 243 | const fn_type = fn_owner_decl.ty; | |
| 242 | 244 | |
| 243 | 245 | var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); |
| 244 | 246 | defer { |
| ... | ... | @@ -819,9 +821,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 819 | 821 | return @as(u32, 0); |
| 820 | 822 | } |
| 821 | 823 | |
| 822 | const target = self.target.*; | |
| 823 | 824 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 824 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 825 | const mod = self.bin_file.options.module.?; | |
| 826 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 825 | 827 | }; |
| 826 | 828 | // TODO swap this for inst.ty.ptrAlign |
| 827 | 829 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| ... | ... | @@ -830,9 +832,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 830 | 832 | |
| 831 | 833 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 832 | 834 | const elem_ty = self.air.typeOfIndex(inst); |
| 833 | const target = self.target.*; | |
| 834 | 835 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 835 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 836 | const mod = self.bin_file.options.module.?; | |
| 837 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 836 | 838 | }; |
| 837 | 839 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 838 | 840 | if (abi_align > self.stack_align) |
| ... | ... | @@ -1422,7 +1424,7 @@ fn binOp( |
| 1422 | 1424 | lhs_ty: Type, |
| 1423 | 1425 | rhs_ty: Type, |
| 1424 | 1426 | ) InnerError!MCValue { |
| 1425 | const target = self.target.*; | |
| 1427 | const mod = self.bin_file.options.module.?; | |
| 1426 | 1428 | switch (tag) { |
| 1427 | 1429 | .add, |
| 1428 | 1430 | .sub, |
| ... | ... | @@ -1432,7 +1434,7 @@ fn binOp( |
| 1432 | 1434 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 1433 | 1435 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1434 | 1436 | .Int => { |
| 1435 | assert(lhs_ty.eql(rhs_ty, target)); | |
| 1437 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 1436 | 1438 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1437 | 1439 | if (int_info.bits <= 64) { |
| 1438 | 1440 | // Only say yes if the operation is |
| ... | ... | @@ -1483,7 +1485,7 @@ fn binOp( |
| 1483 | 1485 | switch (lhs_ty.zigTypeTag()) { |
| 1484 | 1486 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1485 | 1487 | .Int => { |
| 1486 | assert(lhs_ty.eql(rhs_ty, target)); | |
| 1488 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 1487 | 1489 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1488 | 1490 | if (int_info.bits <= 64) { |
| 1489 | 1491 | // TODO add optimisations for multiplication |
| ... | ... | @@ -1534,7 +1536,7 @@ fn binOp( |
| 1534 | 1536 | switch (lhs_ty.zigTypeTag()) { |
| 1535 | 1537 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1536 | 1538 | .Int => { |
| 1537 | assert(lhs_ty.eql(rhs_ty, target)); | |
| 1539 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 1538 | 1540 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1539 | 1541 | if (int_info.bits <= 64) { |
| 1540 | 1542 | // TODO implement bitwise operations with immediates |
| ... | ... | @@ -2425,12 +2427,12 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 2425 | 2427 | const ty = self.air.typeOfIndex(inst); |
| 2426 | 2428 | |
| 2427 | 2429 | const result = self.args[arg_index]; |
| 2428 | const target = self.target.*; | |
| 2429 | 2430 | const mcv = switch (result) { |
| 2430 | 2431 | // Copy registers to the stack |
| 2431 | 2432 | .register => |reg| blk: { |
| 2433 | const mod = self.bin_file.options.module.?; | |
| 2432 | 2434 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { |
| 2433 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(target)}); | |
| 2435 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); | |
| 2434 | 2436 | }; |
| 2435 | 2437 | const abi_align = ty.abiAlignment(self.target.*); |
| 2436 | 2438 | const stack_offset = try self.allocMem(inst, abi_size, abi_align); |
| ... | ... | @@ -2537,17 +2539,19 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 2537 | 2539 | |
| 2538 | 2540 | // Due to incremental compilation, how function calls are generated depends |
| 2539 | 2541 | // on linking. |
| 2542 | const mod = self.bin_file.options.module.?; | |
| 2540 | 2543 | if (self.air.value(callee)) |func_value| { |
| 2541 | 2544 | if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) { |
| 2542 | 2545 | if (func_value.castTag(.function)) |func_payload| { |
| 2543 | 2546 | const func = func_payload.data; |
| 2544 | 2547 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 2545 | 2548 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 2549 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 2546 | 2550 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { |
| 2547 | 2551 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 2548 | break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 2552 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 2549 | 2553 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| |
| 2550 | coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * ptr_bytes | |
| 2554 | coff_file.offset_table_virtual_address + fn_owner_decl.link.coff.offset_table_index * ptr_bytes | |
| 2551 | 2555 | else |
| 2552 | 2556 | unreachable; |
| 2553 | 2557 | |
| ... | ... | @@ -2565,8 +2569,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 2565 | 2569 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 2566 | 2570 | if (func_value.castTag(.function)) |func_payload| { |
| 2567 | 2571 | const func = func_payload.data; |
| 2572 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 2568 | 2573 | try self.genSetReg(Type.initTag(.u64), .x30, .{ |
| 2569 | .got_load = func.owner_decl.link.macho.local_sym_index, | |
| 2574 | .got_load = fn_owner_decl.link.macho.local_sym_index, | |
| 2570 | 2575 | }); |
| 2571 | 2576 | // blr x30 |
| 2572 | 2577 | _ = try self.addInst(.{ |
| ... | ... | @@ -2575,7 +2580,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 2575 | 2580 | }); |
| 2576 | 2581 | } else if (func_value.castTag(.extern_fn)) |func_payload| { |
| 2577 | 2582 | const extern_fn = func_payload.data; |
| 2578 | const decl_name = extern_fn.owner_decl.name; | |
| 2583 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | |
| 2579 | 2584 | if (extern_fn.lib_name) |lib_name| { |
| 2580 | 2585 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ |
| 2581 | 2586 | decl_name, |
| ... | ... | @@ -2588,7 +2593,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 2588 | 2593 | .tag = .call_extern, |
| 2589 | 2594 | .data = .{ |
| 2590 | 2595 | .extern_fn = .{ |
| 2591 | .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index, | |
| 2596 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.local_sym_index, | |
| 2592 | 2597 | .sym_name = n_strx, |
| 2593 | 2598 | }, |
| 2594 | 2599 | }, |
| ... | ... | @@ -2602,7 +2607,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 2602 | 2607 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 2603 | 2608 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 2604 | 2609 | const got_addr = p9.bases.data; |
| 2605 | const got_index = func_payload.data.owner_decl.link.plan9.got_index.?; | |
| 2610 | const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?; | |
| 2606 | 2611 | const fn_got_addr = got_addr + got_index * ptr_bytes; |
| 2607 | 2612 | |
| 2608 | 2613 | try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr }); |
| ... | ... | @@ -3478,12 +3483,13 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3478 | 3483 | .direct_load => .load_memory_ptr_direct, |
| 3479 | 3484 | else => unreachable, |
| 3480 | 3485 | }; |
| 3486 | const mod = self.bin_file.options.module.?; | |
| 3481 | 3487 | _ = try self.addInst(.{ |
| 3482 | 3488 | .tag = tag, |
| 3483 | 3489 | .data = .{ |
| 3484 | 3490 | .payload = try self.addExtra(Mir.LoadMemoryPie{ |
| 3485 | 3491 | .register = @enumToInt(src_reg), |
| 3486 | .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index, | |
| 3492 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.local_sym_index, | |
| 3487 | 3493 | .sym_index = sym_index, |
| 3488 | 3494 | }), |
| 3489 | 3495 | }, |
| ... | ... | @@ -3597,12 +3603,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3597 | 3603 | .direct_load => .load_memory_direct, |
| 3598 | 3604 | else => unreachable, |
| 3599 | 3605 | }; |
| 3606 | const mod = self.bin_file.options.module.?; | |
| 3600 | 3607 | _ = try self.addInst(.{ |
| 3601 | 3608 | .tag = tag, |
| 3602 | 3609 | .data = .{ |
| 3603 | 3610 | .payload = try self.addExtra(Mir.LoadMemoryPie{ |
| 3604 | 3611 | .register = @enumToInt(reg), |
| 3605 | .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index, | |
| 3612 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.local_sym_index, | |
| 3606 | 3613 | .sym_index = sym_index, |
| 3607 | 3614 | }), |
| 3608 | 3615 | }, |
| ... | ... | @@ -3860,7 +3867,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 3860 | 3867 | } |
| 3861 | 3868 | } |
| 3862 | 3869 | |
| 3863 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { | |
| 3870 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { | |
| 3864 | 3871 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 3865 | 3872 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 3866 | 3873 | |
| ... | ... | @@ -3872,7 +3879,10 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 3872 | 3879 | } |
| 3873 | 3880 | } |
| 3874 | 3881 | |
| 3875 | decl.alive = true; | |
| 3882 | const mod = self.bin_file.options.module.?; | |
| 3883 | const decl = mod.declPtr(decl_index); | |
| 3884 | mod.markDeclAlive(decl); | |
| 3885 | ||
| 3876 | 3886 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 3877 | 3887 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 3878 | 3888 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; |
| ... | ... | @@ -3886,7 +3896,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 3886 | 3896 | const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes; |
| 3887 | 3897 | return MCValue{ .memory = got_addr }; |
| 3888 | 3898 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 3889 | try p9.seeDecl(decl); | |
| 3899 | try p9.seeDecl(decl_index); | |
| 3890 | 3900 | const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes; |
| 3891 | 3901 | return MCValue{ .memory = got_addr }; |
| 3892 | 3902 | } else { |
| ... | ... | @@ -3922,7 +3932,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3922 | 3932 | return self.lowerDeclRef(typed_value, payload.data); |
| 3923 | 3933 | } |
| 3924 | 3934 | if (typed_value.val.castTag(.decl_ref_mut)) |payload| { |
| 3925 | return self.lowerDeclRef(typed_value, payload.data.decl); | |
| 3935 | return self.lowerDeclRef(typed_value, payload.data.decl_index); | |
| 3926 | 3936 | } |
| 3927 | 3937 | const target = self.target.*; |
| 3928 | 3938 |
src/arch/arm/CodeGen.zig+33-20| ... | ... | @@ -271,8 +271,10 @@ pub fn generate( |
| 271 | 271 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | assert(module_fn.owner_decl.has_tv); | |
| 275 | const fn_type = module_fn.owner_decl.ty; | |
| 274 | const mod = bin_file.options.module.?; | |
| 275 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 276 | assert(fn_owner_decl.has_tv); | |
| 277 | const fn_type = fn_owner_decl.ty; | |
| 276 | 278 | |
| 277 | 279 | var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); |
| 278 | 280 | defer { |
| ... | ... | @@ -838,9 +840,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 838 | 840 | return @as(u32, 0); |
| 839 | 841 | } |
| 840 | 842 | |
| 841 | const target = self.target.*; | |
| 842 | 843 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 843 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 844 | const mod = self.bin_file.options.module.?; | |
| 845 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 844 | 846 | }; |
| 845 | 847 | // TODO swap this for inst.ty.ptrAlign |
| 846 | 848 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| ... | ... | @@ -849,9 +851,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 849 | 851 | |
| 850 | 852 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 851 | 853 | const elem_ty = self.air.typeOfIndex(inst); |
| 852 | const target = self.target.*; | |
| 853 | 854 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 854 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 855 | const mod = self.bin_file.options.module.?; | |
| 856 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 855 | 857 | }; |
| 856 | 858 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 857 | 859 | if (abi_align > self.stack_align) |
| ... | ... | @@ -1204,7 +1206,8 @@ fn minMax( |
| 1204 | 1206 | .Float => return self.fail("TODO ARM min/max on floats", .{}), |
| 1205 | 1207 | .Vector => return self.fail("TODO ARM min/max on vectors", .{}), |
| 1206 | 1208 | .Int => { |
| 1207 | assert(lhs_ty.eql(rhs_ty, self.target.*)); | |
| 1209 | const mod = self.bin_file.options.module.?; | |
| 1210 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 1208 | 1211 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1209 | 1212 | if (int_info.bits <= 32) { |
| 1210 | 1213 | const lhs_is_register = lhs == .register; |
| ... | ... | @@ -1372,7 +1375,8 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1372 | 1375 | switch (lhs_ty.zigTypeTag()) { |
| 1373 | 1376 | .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}), |
| 1374 | 1377 | .Int => { |
| 1375 | assert(lhs_ty.eql(rhs_ty, self.target.*)); | |
| 1378 | const mod = self.bin_file.options.module.?; | |
| 1379 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 1376 | 1380 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1377 | 1381 | if (int_info.bits < 32) { |
| 1378 | 1382 | const stack_offset = try self.allocMem(inst, tuple_size, tuple_align); |
| ... | ... | @@ -1472,7 +1476,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1472 | 1476 | switch (lhs_ty.zigTypeTag()) { |
| 1473 | 1477 | .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), |
| 1474 | 1478 | .Int => { |
| 1475 | assert(lhs_ty.eql(rhs_ty, self.target.*)); | |
| 1479 | const mod = self.bin_file.options.module.?; | |
| 1480 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 1476 | 1481 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1477 | 1482 | if (int_info.bits <= 16) { |
| 1478 | 1483 | const stack_offset = try self.allocMem(inst, tuple_size, tuple_align); |
| ... | ... | @@ -2682,7 +2687,6 @@ fn binOp( |
| 2682 | 2687 | lhs_ty: Type, |
| 2683 | 2688 | rhs_ty: Type, |
| 2684 | 2689 | ) InnerError!MCValue { |
| 2685 | const target = self.target.*; | |
| 2686 | 2690 | switch (tag) { |
| 2687 | 2691 | .add, |
| 2688 | 2692 | .sub, |
| ... | ... | @@ -2692,7 +2696,8 @@ fn binOp( |
| 2692 | 2696 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 2693 | 2697 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 2694 | 2698 | .Int => { |
| 2695 | assert(lhs_ty.eql(rhs_ty, target)); | |
| 2699 | const mod = self.bin_file.options.module.?; | |
| 2700 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 2696 | 2701 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2697 | 2702 | if (int_info.bits <= 32) { |
| 2698 | 2703 | // Only say yes if the operation is |
| ... | ... | @@ -2740,7 +2745,8 @@ fn binOp( |
| 2740 | 2745 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 2741 | 2746 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 2742 | 2747 | .Int => { |
| 2743 | assert(lhs_ty.eql(rhs_ty, target)); | |
| 2748 | const mod = self.bin_file.options.module.?; | |
| 2749 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 2744 | 2750 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2745 | 2751 | if (int_info.bits <= 32) { |
| 2746 | 2752 | // TODO add optimisations for multiplication |
| ... | ... | @@ -2794,7 +2800,8 @@ fn binOp( |
| 2794 | 2800 | switch (lhs_ty.zigTypeTag()) { |
| 2795 | 2801 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 2796 | 2802 | .Int => { |
| 2797 | assert(lhs_ty.eql(rhs_ty, target)); | |
| 2803 | const mod = self.bin_file.options.module.?; | |
| 2804 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 2798 | 2805 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2799 | 2806 | if (int_info.bits <= 32) { |
| 2800 | 2807 | const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null; |
| ... | ... | @@ -3100,8 +3107,9 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void { |
| 3100 | 3107 | const dbg_info = &dw.dbg_info; |
| 3101 | 3108 | const index = dbg_info.items.len; |
| 3102 | 3109 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 |
| 3110 | const mod = self.bin_file.options.module.?; | |
| 3103 | 3111 | const atom = switch (self.bin_file.tag) { |
| 3104 | .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom, | |
| 3112 | .elf => &mod.declPtr(self.mod_fn.owner_decl).link.elf.dbg_info_atom, | |
| 3105 | 3113 | .macho => unreachable, |
| 3106 | 3114 | else => unreachable, |
| 3107 | 3115 | }; |
| ... | ... | @@ -3318,11 +3326,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3318 | 3326 | const func = func_payload.data; |
| 3319 | 3327 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 3320 | 3328 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 3329 | const mod = self.bin_file.options.module.?; | |
| 3330 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 3321 | 3331 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { |
| 3322 | 3332 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 3323 | break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 3333 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 3324 | 3334 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| |
| 3325 | coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * ptr_bytes | |
| 3335 | coff_file.offset_table_virtual_address + fn_owner_decl.link.coff.offset_table_index * ptr_bytes | |
| 3326 | 3336 | else |
| 3327 | 3337 | unreachable; |
| 3328 | 3338 | |
| ... | ... | @@ -4924,11 +4934,14 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 4924 | 4934 | } |
| 4925 | 4935 | } |
| 4926 | 4936 | |
| 4927 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { | |
| 4937 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { | |
| 4928 | 4938 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 4929 | 4939 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 4930 | 4940 | |
| 4931 | decl.alive = true; | |
| 4941 | const mod = self.bin_file.options.module.?; | |
| 4942 | const decl = mod.declPtr(decl_index); | |
| 4943 | mod.markDeclAlive(decl); | |
| 4944 | ||
| 4932 | 4945 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 4933 | 4946 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 4934 | 4947 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; |
| ... | ... | @@ -4939,7 +4952,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 4939 | 4952 | const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes; |
| 4940 | 4953 | return MCValue{ .memory = got_addr }; |
| 4941 | 4954 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 4942 | try p9.seeDecl(decl); | |
| 4955 | try p9.seeDecl(decl_index); | |
| 4943 | 4956 | const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes; |
| 4944 | 4957 | return MCValue{ .memory = got_addr }; |
| 4945 | 4958 | } else { |
| ... | ... | @@ -4976,7 +4989,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 4976 | 4989 | return self.lowerDeclRef(typed_value, payload.data); |
| 4977 | 4990 | } |
| 4978 | 4991 | if (typed_value.val.castTag(.decl_ref_mut)) |payload| { |
| 4979 | return self.lowerDeclRef(typed_value, payload.data.decl); | |
| 4992 | return self.lowerDeclRef(typed_value, payload.data.decl_index); | |
| 4980 | 4993 | } |
| 4981 | 4994 | const target = self.target.*; |
| 4982 | 4995 |
src/arch/riscv64/CodeGen.zig+26-16| ... | ... | @@ -229,8 +229,10 @@ pub fn generate( |
| 229 | 229 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | assert(module_fn.owner_decl.has_tv); | |
| 233 | const fn_type = module_fn.owner_decl.ty; | |
| 232 | const mod = bin_file.options.module.?; | |
| 233 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 234 | assert(fn_owner_decl.has_tv); | |
| 235 | const fn_type = fn_owner_decl.ty; | |
| 234 | 236 | |
| 235 | 237 | var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); |
| 236 | 238 | defer { |
| ... | ... | @@ -738,8 +740,9 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { |
| 738 | 740 | const dbg_info = &dw.dbg_info; |
| 739 | 741 | const index = dbg_info.items.len; |
| 740 | 742 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 |
| 743 | const mod = self.bin_file.options.module.?; | |
| 741 | 744 | const atom = switch (self.bin_file.tag) { |
| 742 | .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom, | |
| 745 | .elf => &mod.declPtr(self.mod_fn.owner_decl).link.elf.dbg_info_atom, | |
| 743 | 746 | .macho => unreachable, |
| 744 | 747 | else => unreachable, |
| 745 | 748 | }; |
| ... | ... | @@ -768,9 +771,9 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u |
| 768 | 771 | /// Use a pointer instruction as the basis for allocating stack memory. |
| 769 | 772 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 770 | 773 | const elem_ty = self.air.typeOfIndex(inst).elemType(); |
| 771 | const target = self.target.*; | |
| 772 | 774 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 773 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 775 | const mod = self.bin_file.options.module.?; | |
| 776 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 774 | 777 | }; |
| 775 | 778 | // TODO swap this for inst.ty.ptrAlign |
| 776 | 779 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| ... | ... | @@ -779,9 +782,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 779 | 782 | |
| 780 | 783 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 781 | 784 | const elem_ty = self.air.typeOfIndex(inst); |
| 782 | const target = self.target.*; | |
| 783 | 785 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 784 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 786 | const mod = self.bin_file.options.module.?; | |
| 787 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 785 | 788 | }; |
| 786 | 789 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 787 | 790 | if (abi_align > self.stack_align) |
| ... | ... | @@ -1037,7 +1040,8 @@ fn binOp( |
| 1037 | 1040 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 1038 | 1041 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1039 | 1042 | .Int => { |
| 1040 | assert(lhs_ty.eql(rhs_ty, self.target.*)); | |
| 1043 | const mod = self.bin_file.options.module.?; | |
| 1044 | assert(lhs_ty.eql(rhs_ty, mod)); | |
| 1041 | 1045 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1042 | 1046 | if (int_info.bits <= 64) { |
| 1043 | 1047 | // TODO immediate operands |
| ... | ... | @@ -1679,11 +1683,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 1679 | 1683 | |
| 1680 | 1684 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1681 | 1685 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 1686 | const mod = self.bin_file.options.module.?; | |
| 1687 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 1682 | 1688 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { |
| 1683 | 1689 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 1684 | break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 1690 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 1685 | 1691 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| |
| 1686 | coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * ptr_bytes | |
| 1692 | coff_file.offset_table_virtual_address + fn_owner_decl.link.coff.offset_table_index * ptr_bytes | |
| 1687 | 1693 | else |
| 1688 | 1694 | unreachable; |
| 1689 | 1695 | |
| ... | ... | @@ -1768,7 +1774,8 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1768 | 1774 | if (self.liveness.isUnused(inst)) |
| 1769 | 1775 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1770 | 1776 | const ty = self.air.typeOf(bin_op.lhs); |
| 1771 | assert(ty.eql(self.air.typeOf(bin_op.rhs), self.target.*)); | |
| 1777 | const mod = self.bin_file.options.module.?; | |
| 1778 | assert(ty.eql(self.air.typeOf(bin_op.rhs), mod)); | |
| 1772 | 1779 | if (ty.zigTypeTag() == .ErrorSet) |
| 1773 | 1780 | return self.fail("TODO implement cmp for errors", .{}); |
| 1774 | 1781 | |
| ... | ... | @@ -2501,10 +2508,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 2501 | 2508 | } |
| 2502 | 2509 | } |
| 2503 | 2510 | |
| 2504 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { | |
| 2511 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { | |
| 2505 | 2512 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 2506 | 2513 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 2507 | decl.alive = true; | |
| 2514 | const mod = self.bin_file.options.module.?; | |
| 2515 | const decl = mod.declPtr(decl_index); | |
| 2516 | mod.markDeclAlive(decl); | |
| 2508 | 2517 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 2509 | 2518 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 2510 | 2519 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; |
| ... | ... | @@ -2517,7 +2526,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 2517 | 2526 | const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes; |
| 2518 | 2527 | return MCValue{ .memory = got_addr }; |
| 2519 | 2528 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 2520 | try p9.seeDecl(decl); | |
| 2529 | try p9.seeDecl(decl_index); | |
| 2521 | 2530 | const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes; |
| 2522 | 2531 | return MCValue{ .memory = got_addr }; |
| 2523 | 2532 | } else { |
| ... | ... | @@ -2534,7 +2543,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 2534 | 2543 | return self.lowerDeclRef(typed_value, payload.data); |
| 2535 | 2544 | } |
| 2536 | 2545 | if (typed_value.val.castTag(.decl_ref_mut)) |payload| { |
| 2537 | return self.lowerDeclRef(typed_value, payload.data.decl); | |
| 2546 | return self.lowerDeclRef(typed_value, payload.data.decl_index); | |
| 2538 | 2547 | } |
| 2539 | 2548 | const target = self.target.*; |
| 2540 | 2549 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| ... | ... | @@ -2544,7 +2553,8 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 2544 | 2553 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 2545 | 2554 | const ptr_type = typed_value.ty.slicePtrFieldType(&buf); |
| 2546 | 2555 | const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); |
| 2547 | const slice_len = typed_value.val.sliceLen(target); | |
| 2556 | const mod = self.bin_file.options.module.?; | |
| 2557 | const slice_len = typed_value.val.sliceLen(mod); | |
| 2548 | 2558 | // Codegen can't handle some kinds of indirection. If the wrong union field is accessed here it may mean |
| 2549 | 2559 | // the Sema code needs to use anonymous Decls or alloca instructions to store data. |
| 2550 | 2560 | const ptr_imm = ptr_mcv.memory; |
src/arch/sparcv9/CodeGen.zig+16-10| ... | ... | @@ -243,8 +243,10 @@ pub fn generate( |
| 243 | 243 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | assert(module_fn.owner_decl.has_tv); | |
| 247 | const fn_type = module_fn.owner_decl.ty; | |
| 246 | const mod = bin_file.options.module.?; | |
| 247 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 248 | assert(fn_owner_decl.has_tv); | |
| 249 | const fn_type = fn_owner_decl.ty; | |
| 248 | 250 | |
| 249 | 251 | var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); |
| 250 | 252 | defer { |
| ... | ... | @@ -871,7 +873,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 871 | 873 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 872 | 874 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { |
| 873 | 875 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 874 | break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 876 | const mod = self.bin_file.options.module.?; | |
| 877 | break :blk @intCast(u32, got.p_vaddr + mod.declPtr(func.owner_decl).link.elf.offset_table_index * ptr_bytes); | |
| 875 | 878 | } else unreachable; |
| 876 | 879 | |
| 877 | 880 | try self.genSetReg(Type.initTag(.usize), .o7, .{ .memory = got_addr }); |
| ... | ... | @@ -1026,9 +1029,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 1026 | 1029 | return @as(u32, 0); |
| 1027 | 1030 | } |
| 1028 | 1031 | |
| 1029 | const target = self.target.*; | |
| 1030 | 1032 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 1031 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 1033 | const mod = self.bin_file.options.module.?; | |
| 1034 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 1032 | 1035 | }; |
| 1033 | 1036 | // TODO swap this for inst.ty.ptrAlign |
| 1034 | 1037 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| ... | ... | @@ -1037,9 +1040,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 1037 | 1040 | |
| 1038 | 1041 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 1039 | 1042 | const elem_ty = self.air.typeOfIndex(inst); |
| 1040 | const target = self.target.*; | |
| 1041 | 1043 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 1042 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 1044 | const mod = self.bin_file.options.module.?; | |
| 1045 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 1043 | 1046 | }; |
| 1044 | 1047 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 1045 | 1048 | if (abi_align > self.stack_align) |
| ... | ... | @@ -1372,7 +1375,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 1372 | 1375 | return self.lowerDeclRef(typed_value, payload.data); |
| 1373 | 1376 | } |
| 1374 | 1377 | if (typed_value.val.castTag(.decl_ref_mut)) |payload| { |
| 1375 | return self.lowerDeclRef(typed_value, payload.data.decl); | |
| 1378 | return self.lowerDeclRef(typed_value, payload.data.decl_index); | |
| 1376 | 1379 | } |
| 1377 | 1380 | const target = self.target.*; |
| 1378 | 1381 | |
| ... | ... | @@ -1422,7 +1425,7 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT |
| 1422 | 1425 | }; |
| 1423 | 1426 | } |
| 1424 | 1427 | |
| 1425 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { | |
| 1428 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { | |
| 1426 | 1429 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1427 | 1430 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 1428 | 1431 | |
| ... | ... | @@ -1434,7 +1437,10 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 1434 | 1437 | } |
| 1435 | 1438 | } |
| 1436 | 1439 | |
| 1437 | decl.alive = true; | |
| 1440 | const mod = self.bin_file.options.module.?; | |
| 1441 | const decl = mod.declPtr(decl_index); | |
| 1442 | ||
| 1443 | mod.markDeclAlive(decl); | |
| 1438 | 1444 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 1439 | 1445 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 1440 | 1446 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; |
src/arch/wasm/CodeGen.zig+52-35| ... | ... | @@ -538,6 +538,10 @@ const Self = @This(); |
| 538 | 538 | /// Reference to the function declaration the code |
| 539 | 539 | /// section belongs to |
| 540 | 540 | decl: *Decl, |
| 541 | decl_index: Decl.Index, | |
| 542 | /// Current block depth. Used to calculate the relative difference between a break | |
| 543 | /// and block | |
| 544 | block_depth: u32 = 0, | |
| 541 | 545 | air: Air, |
| 542 | 546 | liveness: Liveness, |
| 543 | 547 | gpa: mem.Allocator, |
| ... | ... | @@ -559,9 +563,6 @@ local_index: u32 = 0, |
| 559 | 563 | arg_index: u32 = 0, |
| 560 | 564 | /// If codegen fails, an error messages will be allocated and saved in `err_msg` |
| 561 | 565 | err_msg: *Module.ErrorMsg, |
| 562 | /// Current block depth. Used to calculate the relative difference between a break | |
| 563 | /// and block | |
| 564 | block_depth: u32 = 0, | |
| 565 | 566 | /// List of all locals' types generated throughout this declaration |
| 566 | 567 | /// used to emit locals count at start of 'code' section. |
| 567 | 568 | locals: std.ArrayListUnmanaged(u8), |
| ... | ... | @@ -644,7 +645,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue { |
| 644 | 645 | // In the other cases, we will simply lower the constant to a value that fits |
| 645 | 646 | // into a single local (such as a pointer, integer, bool, etc). |
| 646 | 647 | const result = if (isByRef(ty, self.target)) blk: { |
| 647 | const sym_index = try self.bin_file.lowerUnnamedConst(self.decl, .{ .ty = ty, .val = val }); | |
| 648 | const sym_index = try self.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, self.decl_index); | |
| 648 | 649 | break :blk WValue{ .memory = sym_index }; |
| 649 | 650 | } else try self.lowerConstant(val, ty); |
| 650 | 651 | |
| ... | ... | @@ -838,7 +839,8 @@ pub fn generate( |
| 838 | 839 | .liveness = liveness, |
| 839 | 840 | .values = .{}, |
| 840 | 841 | .code = code, |
| 841 | .decl = func.owner_decl, | |
| 842 | .decl_index = func.owner_decl, | |
| 843 | .decl = bin_file.options.module.?.declPtr(func.owner_decl), | |
| 842 | 844 | .err_msg = undefined, |
| 843 | 845 | .locals = .{}, |
| 844 | 846 | .target = bin_file.options.target, |
| ... | ... | @@ -1022,8 +1024,9 @@ fn allocStack(self: *Self, ty: Type) !WValue { |
| 1022 | 1024 | } |
| 1023 | 1025 | |
| 1024 | 1026 | const abi_size = std.math.cast(u32, ty.abiSize(self.target)) catch { |
| 1027 | const module = self.bin_file.base.options.module.?; | |
| 1025 | 1028 | return self.fail("Type {} with ABI size of {d} exceeds stack frame size", .{ |
| 1026 | ty.fmt(self.target), ty.abiSize(self.target), | |
| 1029 | ty.fmt(module), ty.abiSize(self.target), | |
| 1027 | 1030 | }); |
| 1028 | 1031 | }; |
| 1029 | 1032 | const abi_align = ty.abiAlignment(self.target); |
| ... | ... | @@ -1056,8 +1059,9 @@ fn allocStackPtr(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1056 | 1059 | |
| 1057 | 1060 | const abi_alignment = ptr_ty.ptrAlignment(self.target); |
| 1058 | 1061 | const abi_size = std.math.cast(u32, pointee_ty.abiSize(self.target)) catch { |
| 1062 | const module = self.bin_file.base.options.module.?; | |
| 1059 | 1063 | return self.fail("Type {} with ABI size of {d} exceeds stack frame size", .{ |
| 1060 | pointee_ty.fmt(self.target), pointee_ty.abiSize(self.target), | |
| 1064 | pointee_ty.fmt(module), pointee_ty.abiSize(self.target), | |
| 1061 | 1065 | }); |
| 1062 | 1066 | }; |
| 1063 | 1067 | if (abi_alignment > self.stack_alignment) { |
| ... | ... | @@ -1542,20 +1546,21 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 1542 | 1546 | const ret_ty = fn_ty.fnReturnType(); |
| 1543 | 1547 | const first_param_sret = isByRef(ret_ty, self.target); |
| 1544 | 1548 | |
| 1545 | const target: ?*Decl = blk: { | |
| 1549 | const callee: ?*Decl = blk: { | |
| 1546 | 1550 | const func_val = self.air.value(pl_op.operand) orelse break :blk null; |
| 1551 | const module = self.bin_file.base.options.module.?; | |
| 1547 | 1552 | |
| 1548 | 1553 | if (func_val.castTag(.function)) |func| { |
| 1549 | break :blk func.data.owner_decl; | |
| 1554 | break :blk module.declPtr(func.data.owner_decl); | |
| 1550 | 1555 | } else if (func_val.castTag(.extern_fn)) |extern_fn| { |
| 1551 | const ext_decl = extern_fn.data.owner_decl; | |
| 1556 | const ext_decl = module.declPtr(extern_fn.data.owner_decl); | |
| 1552 | 1557 | var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target); |
| 1553 | 1558 | defer func_type.deinit(self.gpa); |
| 1554 | 1559 | ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type); |
| 1555 | 1560 | try self.bin_file.addOrUpdateImport(ext_decl); |
| 1556 | 1561 | break :blk ext_decl; |
| 1557 | 1562 | } else if (func_val.castTag(.decl_ref)) |decl_ref| { |
| 1558 | break :blk decl_ref.data; | |
| 1563 | break :blk module.declPtr(decl_ref.data); | |
| 1559 | 1564 | } |
| 1560 | 1565 | return self.fail("Expected a function, but instead found type '{s}'", .{func_val.tag()}); |
| 1561 | 1566 | }; |
| ... | ... | @@ -1580,7 +1585,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 1580 | 1585 | } |
| 1581 | 1586 | } |
| 1582 | 1587 | |
| 1583 | if (target) |direct| { | |
| 1588 | if (callee) |direct| { | |
| 1584 | 1589 | try self.addLabel(.call, direct.link.wasm.sym_index); |
| 1585 | 1590 | } else { |
| 1586 | 1591 | // in this case we call a function pointer |
| ... | ... | @@ -1837,16 +1842,16 @@ fn wrapBinOp(self: *Self, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError |
| 1837 | 1842 | fn lowerParentPtr(self: *Self, ptr_val: Value, ptr_child_ty: Type) InnerError!WValue { |
| 1838 | 1843 | switch (ptr_val.tag()) { |
| 1839 | 1844 | .decl_ref_mut => { |
| 1840 | const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl; | |
| 1841 | return self.lowerParentPtrDecl(ptr_val, decl); | |
| 1845 | const decl_index = ptr_val.castTag(.decl_ref_mut).?.data.decl_index; | |
| 1846 | return self.lowerParentPtrDecl(ptr_val, decl_index); | |
| 1842 | 1847 | }, |
| 1843 | 1848 | .decl_ref => { |
| 1844 | const decl = ptr_val.castTag(.decl_ref).?.data; | |
| 1845 | return self.lowerParentPtrDecl(ptr_val, decl); | |
| 1849 | const decl_index = ptr_val.castTag(.decl_ref).?.data; | |
| 1850 | return self.lowerParentPtrDecl(ptr_val, decl_index); | |
| 1846 | 1851 | }, |
| 1847 | 1852 | .variable => { |
| 1848 | const decl = ptr_val.castTag(.variable).?.data.owner_decl; | |
| 1849 | return self.lowerParentPtrDecl(ptr_val, decl); | |
| 1853 | const decl_index = ptr_val.castTag(.variable).?.data.owner_decl; | |
| 1854 | return self.lowerParentPtrDecl(ptr_val, decl_index); | |
| 1850 | 1855 | }, |
| 1851 | 1856 | .field_ptr => { |
| 1852 | 1857 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| ... | ... | @@ -1918,24 +1923,31 @@ fn lowerParentPtr(self: *Self, ptr_val: Value, ptr_child_ty: Type) InnerError!WV |
| 1918 | 1923 | } |
| 1919 | 1924 | } |
| 1920 | 1925 | |
| 1921 | fn lowerParentPtrDecl(self: *Self, ptr_val: Value, decl: *Module.Decl) InnerError!WValue { | |
| 1922 | decl.markAlive(); | |
| 1926 | fn lowerParentPtrDecl(self: *Self, ptr_val: Value, decl_index: Module.Decl.Index) InnerError!WValue { | |
| 1927 | const module = self.bin_file.base.options.module.?; | |
| 1928 | const decl = module.declPtr(decl_index); | |
| 1929 | module.markDeclAlive(decl); | |
| 1923 | 1930 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 1924 | 1931 | .base = .{ .tag = .single_mut_pointer }, |
| 1925 | 1932 | .data = decl.ty, |
| 1926 | 1933 | }; |
| 1927 | 1934 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 1928 | return self.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl); | |
| 1935 | return self.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index); | |
| 1929 | 1936 | } |
| 1930 | 1937 | |
| 1931 | fn lowerDeclRefValue(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!WValue { | |
| 1938 | fn lowerDeclRefValue(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!WValue { | |
| 1932 | 1939 | if (tv.ty.isSlice()) { |
| 1933 | return WValue{ .memory = try self.bin_file.lowerUnnamedConst(decl, tv) }; | |
| 1934 | } else if (decl.ty.zigTypeTag() != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime()) { | |
| 1940 | return WValue{ .memory = try self.bin_file.lowerUnnamedConst(tv, decl_index) }; | |
| 1941 | } | |
| 1942 | ||
| 1943 | const module = self.bin_file.base.options.module.?; | |
| 1944 | const decl = module.declPtr(decl_index); | |
| 1945 | if (decl.ty.zigTypeTag() != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime()) { | |
| 1935 | 1946 | return WValue{ .imm32 = 0xaaaaaaaa }; |
| 1936 | 1947 | } |
| 1937 | 1948 | |
| 1938 | decl.markAlive(); | |
| 1949 | module.markDeclAlive(decl); | |
| 1950 | ||
| 1939 | 1951 | const target_sym_index = decl.link.wasm.sym_index; |
| 1940 | 1952 | if (decl.ty.zigTypeTag() == .Fn) { |
| 1941 | 1953 | try self.bin_file.addTableFunction(target_sym_index); |
| ... | ... | @@ -1946,12 +1958,12 @@ fn lowerDeclRefValue(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError |
| 1946 | 1958 | fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { |
| 1947 | 1959 | if (val.isUndefDeep()) return self.emitUndefined(ty); |
| 1948 | 1960 | if (val.castTag(.decl_ref)) |decl_ref| { |
| 1949 | const decl = decl_ref.data; | |
| 1950 | return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl); | |
| 1961 | const decl_index = decl_ref.data; | |
| 1962 | return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index); | |
| 1951 | 1963 | } |
| 1952 | if (val.castTag(.decl_ref_mut)) |decl_ref| { | |
| 1953 | const decl = decl_ref.data.decl; | |
| 1954 | return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl); | |
| 1964 | if (val.castTag(.decl_ref_mut)) |decl_ref_mut| { | |
| 1965 | const decl_index = decl_ref_mut.data.decl_index; | |
| 1966 | return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index); | |
| 1955 | 1967 | } |
| 1956 | 1968 | |
| 1957 | 1969 | const target = self.target; |
| ... | ... | @@ -2347,8 +2359,9 @@ fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2347 | 2359 | const struct_ptr = try self.resolveInst(extra.data.struct_operand); |
| 2348 | 2360 | const struct_ty = self.air.typeOf(extra.data.struct_operand).childType(); |
| 2349 | 2361 | const offset = std.math.cast(u32, struct_ty.structFieldOffset(extra.data.field_index, self.target)) catch { |
| 2362 | const module = self.bin_file.base.options.module.?; | |
| 2350 | 2363 | return self.fail("Field type '{}' too big to fit into stack frame", .{ |
| 2351 | struct_ty.structFieldType(extra.data.field_index).fmt(self.target), | |
| 2364 | struct_ty.structFieldType(extra.data.field_index).fmt(module), | |
| 2352 | 2365 | }); |
| 2353 | 2366 | }; |
| 2354 | 2367 | return self.structFieldPtr(struct_ptr, offset); |
| ... | ... | @@ -2360,8 +2373,9 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u32) InnerEr |
| 2360 | 2373 | const struct_ty = self.air.typeOf(ty_op.operand).childType(); |
| 2361 | 2374 | const field_ty = struct_ty.structFieldType(index); |
| 2362 | 2375 | const offset = std.math.cast(u32, struct_ty.structFieldOffset(index, self.target)) catch { |
| 2376 | const module = self.bin_file.base.options.module.?; | |
| 2363 | 2377 | return self.fail("Field type '{}' too big to fit into stack frame", .{ |
| 2364 | field_ty.fmt(self.target), | |
| 2378 | field_ty.fmt(module), | |
| 2365 | 2379 | }); |
| 2366 | 2380 | }; |
| 2367 | 2381 | return self.structFieldPtr(struct_ptr, offset); |
| ... | ... | @@ -2387,7 +2401,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2387 | 2401 | const field_ty = struct_ty.structFieldType(field_index); |
| 2388 | 2402 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} }; |
| 2389 | 2403 | const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, self.target)) catch { |
| 2390 | return self.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(self.target)}); | |
| 2404 | const module = self.bin_file.base.options.module.?; | |
| 2405 | return self.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(module)}); | |
| 2391 | 2406 | }; |
| 2392 | 2407 | |
| 2393 | 2408 | if (isByRef(field_ty, self.target)) { |
| ... | ... | @@ -2782,7 +2797,8 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue |
| 2782 | 2797 | } |
| 2783 | 2798 | |
| 2784 | 2799 | const offset = std.math.cast(u32, opt_ty.abiSize(self.target) - payload_ty.abiSize(self.target)) catch { |
| 2785 | return self.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(self.target)}); | |
| 2800 | const module = self.bin_file.base.options.module.?; | |
| 2801 | return self.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(module)}); | |
| 2786 | 2802 | }; |
| 2787 | 2803 | |
| 2788 | 2804 | try self.emitWValue(operand); |
| ... | ... | @@ -2811,7 +2827,8 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2811 | 2827 | return operand; |
| 2812 | 2828 | } |
| 2813 | 2829 | const offset = std.math.cast(u32, op_ty.abiSize(self.target) - payload_ty.abiSize(self.target)) catch { |
| 2814 | return self.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(self.target)}); | |
| 2830 | const module = self.bin_file.base.options.module.?; | |
| 2831 | return self.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(module)}); | |
| 2815 | 2832 | }; |
| 2816 | 2833 | |
| 2817 | 2834 | // Create optional type, set the non-null bit, and store the operand inside the optional type |
src/arch/x86_64/CodeGen.zig+32-21| ... | ... | @@ -309,8 +309,10 @@ pub fn generate( |
| 309 | 309 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 310 | 310 | } |
| 311 | 311 | |
| 312 | assert(module_fn.owner_decl.has_tv); | |
| 313 | const fn_type = module_fn.owner_decl.ty; | |
| 312 | const mod = bin_file.options.module.?; | |
| 313 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 314 | assert(fn_owner_decl.has_tv); | |
| 315 | const fn_type = fn_owner_decl.ty; | |
| 314 | 316 | |
| 315 | 317 | var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); |
| 316 | 318 | defer { |
| ... | ... | @@ -396,14 +398,14 @@ pub fn generate( |
| 396 | 398 | |
| 397 | 399 | if (builtin.mode == .Debug and bin_file.options.module.?.comp.verbose_mir) { |
| 398 | 400 | const w = std.io.getStdErr().writer(); |
| 399 | w.print("# Begin Function MIR: {s}:\n", .{module_fn.owner_decl.name}) catch {}; | |
| 401 | w.print("# Begin Function MIR: {s}:\n", .{fn_owner_decl.name}) catch {}; | |
| 400 | 402 | const PrintMir = @import("PrintMir.zig"); |
| 401 | 403 | const print = PrintMir{ |
| 402 | 404 | .mir = mir, |
| 403 | 405 | .bin_file = bin_file, |
| 404 | 406 | }; |
| 405 | 407 | print.printMir(w, function.mir_to_air_map, air) catch {}; // we don't care if the debug printing fails |
| 406 | w.print("# End Function MIR: {s}\n\n", .{module_fn.owner_decl.name}) catch {}; | |
| 408 | w.print("# End Function MIR: {s}\n\n", .{fn_owner_decl.name}) catch {}; | |
| 407 | 409 | } |
| 408 | 410 | |
| 409 | 411 | if (function.err_msg) |em| { |
| ... | ... | @@ -915,9 +917,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 915 | 917 | return self.allocMem(inst, @sizeOf(usize), @alignOf(usize)); |
| 916 | 918 | } |
| 917 | 919 | |
| 918 | const target = self.target.*; | |
| 919 | 920 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 920 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 921 | const mod = self.bin_file.options.module.?; | |
| 922 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 921 | 923 | }; |
| 922 | 924 | // TODO swap this for inst.ty.ptrAlign |
| 923 | 925 | const abi_align = ptr_ty.ptrAlignment(self.target.*); |
| ... | ... | @@ -926,9 +928,9 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 926 | 928 | |
| 927 | 929 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 928 | 930 | const elem_ty = self.air.typeOfIndex(inst); |
| 929 | const target = self.target.*; | |
| 930 | 931 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) catch { |
| 931 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(target)}); | |
| 932 | const mod = self.bin_file.options.module.?; | |
| 933 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | |
| 932 | 934 | }; |
| 933 | 935 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 934 | 936 | if (abi_align > self.stack_align) |
| ... | ... | @@ -2650,6 +2652,8 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2650 | 2652 | .direct_load => 0b01, |
| 2651 | 2653 | else => unreachable, |
| 2652 | 2654 | }; |
| 2655 | const mod = self.bin_file.options.module.?; | |
| 2656 | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); | |
| 2653 | 2657 | _ = try self.addInst(.{ |
| 2654 | 2658 | .tag = .lea_pie, |
| 2655 | 2659 | .ops = (Mir.Ops{ |
| ... | ... | @@ -2658,7 +2662,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2658 | 2662 | }).encode(), |
| 2659 | 2663 | .data = .{ |
| 2660 | 2664 | .load_reloc = .{ |
| 2661 | .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index, | |
| 2665 | .atom_index = fn_owner_decl.link.macho.local_sym_index, | |
| 2662 | 2666 | .sym_index = sym_index, |
| 2663 | 2667 | }, |
| 2664 | 2668 | }, |
| ... | ... | @@ -3583,17 +3587,19 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3583 | 3587 | |
| 3584 | 3588 | // Due to incremental compilation, how function calls are generated depends |
| 3585 | 3589 | // on linking. |
| 3590 | const mod = self.bin_file.options.module.?; | |
| 3586 | 3591 | if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) { |
| 3587 | 3592 | if (self.air.value(callee)) |func_value| { |
| 3588 | 3593 | if (func_value.castTag(.function)) |func_payload| { |
| 3589 | 3594 | const func = func_payload.data; |
| 3590 | 3595 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 3591 | 3596 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 3597 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 3592 | 3598 | const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: { |
| 3593 | 3599 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 3594 | break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 3600 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | |
| 3595 | 3601 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| |
| 3596 | @intCast(u32, coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * ptr_bytes) | |
| 3602 | @intCast(u32, coff_file.offset_table_virtual_address + fn_owner_decl.link.coff.offset_table_index * ptr_bytes) | |
| 3597 | 3603 | else |
| 3598 | 3604 | unreachable; |
| 3599 | 3605 | _ = try self.addInst(.{ |
| ... | ... | @@ -3625,8 +3631,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3625 | 3631 | if (self.air.value(callee)) |func_value| { |
| 3626 | 3632 | if (func_value.castTag(.function)) |func_payload| { |
| 3627 | 3633 | const func = func_payload.data; |
| 3634 | const fn_owner_decl = mod.declPtr(func.owner_decl); | |
| 3628 | 3635 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 3629 | .got_load = func.owner_decl.link.macho.local_sym_index, | |
| 3636 | .got_load = fn_owner_decl.link.macho.local_sym_index, | |
| 3630 | 3637 | }); |
| 3631 | 3638 | // callq *%rax |
| 3632 | 3639 | _ = try self.addInst(.{ |
| ... | ... | @@ -3639,7 +3646,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3639 | 3646 | }); |
| 3640 | 3647 | } else if (func_value.castTag(.extern_fn)) |func_payload| { |
| 3641 | 3648 | const extern_fn = func_payload.data; |
| 3642 | const decl_name = extern_fn.owner_decl.name; | |
| 3649 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | |
| 3643 | 3650 | if (extern_fn.lib_name) |lib_name| { |
| 3644 | 3651 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ |
| 3645 | 3652 | decl_name, |
| ... | ... | @@ -3652,7 +3659,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3652 | 3659 | .ops = undefined, |
| 3653 | 3660 | .data = .{ |
| 3654 | 3661 | .extern_fn = .{ |
| 3655 | .atom_index = self.mod_fn.owner_decl.link.macho.local_sym_index, | |
| 3662 | .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.local_sym_index, | |
| 3656 | 3663 | .sym_name = n_strx, |
| 3657 | 3664 | }, |
| 3658 | 3665 | }, |
| ... | ... | @@ -3680,7 +3687,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3680 | 3687 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 3681 | 3688 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 3682 | 3689 | const got_addr = p9.bases.data; |
| 3683 | const got_index = func_payload.data.owner_decl.link.plan9.got_index.?; | |
| 3690 | const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?; | |
| 3684 | 3691 | const fn_got_addr = got_addr + got_index * ptr_bytes; |
| 3685 | 3692 | _ = try self.addInst(.{ |
| 3686 | 3693 | .tag = .call, |
| ... | ... | @@ -4012,9 +4019,11 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { |
| 4012 | 4019 | const dbg_info = &dw.dbg_info; |
| 4013 | 4020 | const index = dbg_info.items.len; |
| 4014 | 4021 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 |
| 4022 | const mod = self.bin_file.options.module.?; | |
| 4023 | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); | |
| 4015 | 4024 | const atom = switch (self.bin_file.tag) { |
| 4016 | .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom, | |
| 4017 | .macho => &self.mod_fn.owner_decl.link.macho.dbg_info_atom, | |
| 4025 | .elf => &fn_owner_decl.link.elf.dbg_info_atom, | |
| 4026 | .macho => &fn_owner_decl.link.macho.dbg_info_atom, | |
| 4018 | 4027 | else => unreachable, |
| 4019 | 4028 | }; |
| 4020 | 4029 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); |
| ... | ... | @@ -6124,7 +6133,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV |
| 6124 | 6133 | return mcv; |
| 6125 | 6134 | } |
| 6126 | 6135 | |
| 6127 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { | |
| 6136 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { | |
| 6128 | 6137 | log.debug("lowerDeclRef: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() }); |
| 6129 | 6138 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 6130 | 6139 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| ... | ... | @@ -6137,7 +6146,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 6137 | 6146 | } |
| 6138 | 6147 | } |
| 6139 | 6148 | |
| 6140 | decl.markAlive(); | |
| 6149 | const module = self.bin_file.options.module.?; | |
| 6150 | const decl = module.declPtr(decl_index); | |
| 6151 | module.markDeclAlive(decl); | |
| 6141 | 6152 | |
| 6142 | 6153 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 6143 | 6154 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| ... | ... | @@ -6152,7 +6163,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 6152 | 6163 | const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes; |
| 6153 | 6164 | return MCValue{ .memory = got_addr }; |
| 6154 | 6165 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 6155 | try p9.seeDecl(decl); | |
| 6166 | try p9.seeDecl(decl_index); | |
| 6156 | 6167 | const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes; |
| 6157 | 6168 | return MCValue{ .memory = got_addr }; |
| 6158 | 6169 | } else { |
| ... | ... | @@ -6189,7 +6200,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 6189 | 6200 | return self.lowerDeclRef(typed_value, payload.data); |
| 6190 | 6201 | } |
| 6191 | 6202 | if (typed_value.val.castTag(.decl_ref_mut)) |payload| { |
| 6192 | return self.lowerDeclRef(typed_value, payload.data.decl); | |
| 6203 | return self.lowerDeclRef(typed_value, payload.data.decl_index); | |
| 6193 | 6204 | } |
| 6194 | 6205 | |
| 6195 | 6206 | const target = self.target.*; |
src/codegen.zig+15-9| ... | ... | @@ -347,7 +347,9 @@ pub fn generateSymbol( |
| 347 | 347 | |
| 348 | 348 | switch (container_ptr.tag()) { |
| 349 | 349 | .decl_ref => { |
| 350 | const decl = container_ptr.castTag(.decl_ref).?.data; | |
| 350 | const decl_index = container_ptr.castTag(.decl_ref).?.data; | |
| 351 | const mod = bin_file.options.module.?; | |
| 352 | const decl = mod.declPtr(decl_index); | |
| 351 | 353 | const addend = blk: { |
| 352 | 354 | switch (decl.ty.tag()) { |
| 353 | 355 | .@"struct" => { |
| ... | ... | @@ -364,7 +366,7 @@ pub fn generateSymbol( |
| 364 | 366 | }, |
| 365 | 367 | } |
| 366 | 368 | }; |
| 367 | return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output, .{ | |
| 369 | return lowerDeclRef(bin_file, src_loc, typed_value, decl_index, code, debug_output, .{ | |
| 368 | 370 | .parent_atom_index = reloc_info.parent_atom_index, |
| 369 | 371 | .addend = (reloc_info.addend orelse 0) + addend, |
| 370 | 372 | }); |
| ... | ... | @@ -400,8 +402,8 @@ pub fn generateSymbol( |
| 400 | 402 | |
| 401 | 403 | switch (array_ptr.tag()) { |
| 402 | 404 | .decl_ref => { |
| 403 | const decl = array_ptr.castTag(.decl_ref).?.data; | |
| 404 | return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output, .{ | |
| 405 | const decl_index = array_ptr.castTag(.decl_ref).?.data; | |
| 406 | return lowerDeclRef(bin_file, src_loc, typed_value, decl_index, code, debug_output, .{ | |
| 405 | 407 | .parent_atom_index = reloc_info.parent_atom_index, |
| 406 | 408 | .addend = (reloc_info.addend orelse 0) + addend, |
| 407 | 409 | }); |
| ... | ... | @@ -589,7 +591,8 @@ pub fn generateSymbol( |
| 589 | 591 | } |
| 590 | 592 | |
| 591 | 593 | const union_ty = typed_value.ty.cast(Type.Payload.Union).?.data; |
| 592 | const field_index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag, target).?; | |
| 594 | const mod = bin_file.options.module.?; | |
| 595 | const field_index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag, mod).?; | |
| 593 | 596 | assert(union_ty.haveFieldTypes()); |
| 594 | 597 | const field_ty = union_ty.fields.values()[field_index].ty; |
| 595 | 598 | if (!field_ty.hasRuntimeBits()) { |
| ... | ... | @@ -772,12 +775,13 @@ fn lowerDeclRef( |
| 772 | 775 | bin_file: *link.File, |
| 773 | 776 | src_loc: Module.SrcLoc, |
| 774 | 777 | typed_value: TypedValue, |
| 775 | decl: *Module.Decl, | |
| 778 | decl_index: Module.Decl.Index, | |
| 776 | 779 | code: *std.ArrayList(u8), |
| 777 | 780 | debug_output: DebugInfoOutput, |
| 778 | 781 | reloc_info: RelocInfo, |
| 779 | 782 | ) GenerateSymbolError!Result { |
| 780 | 783 | const target = bin_file.options.target; |
| 784 | const module = bin_file.options.module.?; | |
| 781 | 785 | if (typed_value.ty.isSlice()) { |
| 782 | 786 | // generate ptr |
| 783 | 787 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| ... | ... | @@ -796,7 +800,7 @@ fn lowerDeclRef( |
| 796 | 800 | // generate length |
| 797 | 801 | var slice_len: Value.Payload.U64 = .{ |
| 798 | 802 | .base = .{ .tag = .int_u64 }, |
| 799 | .data = typed_value.val.sliceLen(target), | |
| 803 | .data = typed_value.val.sliceLen(module), | |
| 800 | 804 | }; |
| 801 | 805 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 802 | 806 | .ty = Type.usize, |
| ... | ... | @@ -813,14 +817,16 @@ fn lowerDeclRef( |
| 813 | 817 | } |
| 814 | 818 | |
| 815 | 819 | const ptr_width = target.cpu.arch.ptrBitWidth(); |
| 820 | const decl = module.declPtr(decl_index); | |
| 816 | 821 | const is_fn_body = decl.ty.zigTypeTag() == .Fn; |
| 817 | 822 | if (!is_fn_body and !decl.ty.hasRuntimeBits()) { |
| 818 | 823 | try code.writer().writeByteNTimes(0xaa, @divExact(ptr_width, 8)); |
| 819 | 824 | return Result{ .appended = {} }; |
| 820 | 825 | } |
| 821 | 826 | |
| 822 | decl.markAlive(); | |
| 823 | const vaddr = try bin_file.getDeclVAddr(decl, .{ | |
| 827 | module.markDeclAlive(decl); | |
| 828 | ||
| 829 | const vaddr = try bin_file.getDeclVAddr(decl_index, .{ | |
| 824 | 830 | .parent_atom_index = reloc_info.parent_atom_index, |
| 825 | 831 | .offset = code.items.len, |
| 826 | 832 | .addend = reloc_info.addend orelse 0, |
src/codegen/c.zig+43-44| ... | ... | @@ -32,8 +32,8 @@ pub const CValue = union(enum) { |
| 32 | 32 | /// Index into the parameters |
| 33 | 33 | arg: usize, |
| 34 | 34 | /// By-value |
| 35 | decl: *Decl, | |
| 36 | decl_ref: *Decl, | |
| 35 | decl: Decl.Index, | |
| 36 | decl_ref: Decl.Index, | |
| 37 | 37 | /// An undefined (void *) pointer (cannot be dereferenced) |
| 38 | 38 | undefined_ptr: void, |
| 39 | 39 | /// Render the slice as an identifier (using fmtIdent) |
| ... | ... | @@ -58,7 +58,7 @@ pub const TypedefMap = std.ArrayHashMap( |
| 58 | 58 | |
| 59 | 59 | const FormatTypeAsCIdentContext = struct { |
| 60 | 60 | ty: Type, |
| 61 | target: std.Target, | |
| 61 | mod: *Module, | |
| 62 | 62 | }; |
| 63 | 63 | |
| 64 | 64 | /// TODO make this not cut off at 128 bytes |
| ... | ... | @@ -71,14 +71,14 @@ fn formatTypeAsCIdentifier( |
| 71 | 71 | _ = fmt; |
| 72 | 72 | _ = options; |
| 73 | 73 | var buffer = [1]u8{0} ** 128; |
| 74 | var buf = std.fmt.bufPrint(&buffer, "{}", .{data.ty.fmt(data.target)}) catch &buffer; | |
| 74 | var buf = std.fmt.bufPrint(&buffer, "{}", .{data.ty.fmt(data.mod)}) catch &buffer; | |
| 75 | 75 | return formatIdent(buf, "", .{}, writer); |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | pub fn typeToCIdentifier(ty: Type, target: std.Target) std.fmt.Formatter(formatTypeAsCIdentifier) { | |
| 78 | pub fn typeToCIdentifier(ty: Type, mod: *Module) std.fmt.Formatter(formatTypeAsCIdentifier) { | |
| 79 | 79 | return .{ .data = .{ |
| 80 | 80 | .ty = ty, |
| 81 | .target = target, | |
| 81 | .mod = mod, | |
| 82 | 82 | } }; |
| 83 | 83 | } |
| 84 | 84 | |
| ... | ... | @@ -349,6 +349,7 @@ pub const DeclGen = struct { |
| 349 | 349 | gpa: std.mem.Allocator, |
| 350 | 350 | module: *Module, |
| 351 | 351 | decl: *Decl, |
| 352 | decl_index: Decl.Index, | |
| 352 | 353 | fwd_decl: std.ArrayList(u8), |
| 353 | 354 | error_msg: ?*Module.ErrorMsg, |
| 354 | 355 | /// The key of this map is Type which has references to typedefs_arena. |
| ... | ... | @@ -376,10 +377,8 @@ pub const DeclGen = struct { |
| 376 | 377 | writer: anytype, |
| 377 | 378 | ty: Type, |
| 378 | 379 | val: Value, |
| 379 | decl: *Decl, | |
| 380 | decl_index: Decl.Index, | |
| 380 | 381 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 381 | const target = dg.module.getTarget(); | |
| 382 | ||
| 383 | 382 | if (ty.isSlice()) { |
| 384 | 383 | try writer.writeByte('('); |
| 385 | 384 | try dg.renderTypecast(writer, ty); |
| ... | ... | @@ -387,11 +386,12 @@ pub const DeclGen = struct { |
| 387 | 386 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 388 | 387 | try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr()); |
| 389 | 388 | try writer.writeAll(", "); |
| 390 | try writer.print("{d}", .{val.sliceLen(target)}); | |
| 389 | try writer.print("{d}", .{val.sliceLen(dg.module)}); | |
| 391 | 390 | try writer.writeAll("}"); |
| 392 | 391 | return; |
| 393 | 392 | } |
| 394 | 393 | |
| 394 | const decl = dg.module.declPtr(decl_index); | |
| 395 | 395 | assert(decl.has_tv); |
| 396 | 396 | // We shouldn't cast C function pointers as this is UB (when you call |
| 397 | 397 | // them). The analysis until now should ensure that the C function |
| ... | ... | @@ -399,21 +399,21 @@ pub const DeclGen = struct { |
| 399 | 399 | // somewhere and we should let the C compiler tell us about it. |
| 400 | 400 | if (ty.castPtrToFn() == null) { |
| 401 | 401 | // Determine if we must pointer cast. |
| 402 | if (ty.eql(decl.ty, target)) { | |
| 402 | if (ty.eql(decl.ty, dg.module)) { | |
| 403 | 403 | try writer.writeByte('&'); |
| 404 | try dg.renderDeclName(writer, decl); | |
| 404 | try dg.renderDeclName(writer, decl_index); | |
| 405 | 405 | return; |
| 406 | 406 | } |
| 407 | 407 | |
| 408 | 408 | try writer.writeAll("(("); |
| 409 | 409 | try dg.renderTypecast(writer, ty); |
| 410 | 410 | try writer.writeAll(")&"); |
| 411 | try dg.renderDeclName(writer, decl); | |
| 411 | try dg.renderDeclName(writer, decl_index); | |
| 412 | 412 | try writer.writeByte(')'); |
| 413 | 413 | return; |
| 414 | 414 | } |
| 415 | 415 | |
| 416 | try dg.renderDeclName(writer, decl); | |
| 416 | try dg.renderDeclName(writer, decl_index); | |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | 419 | fn renderInt128( |
| ... | ... | @@ -471,13 +471,13 @@ pub const DeclGen = struct { |
| 471 | 471 | try writer.writeByte(')'); |
| 472 | 472 | switch (ptr_val.tag()) { |
| 473 | 473 | .decl_ref_mut, .decl_ref, .variable => { |
| 474 | const decl = switch (ptr_val.tag()) { | |
| 474 | const decl_index = switch (ptr_val.tag()) { | |
| 475 | 475 | .decl_ref => ptr_val.castTag(.decl_ref).?.data, |
| 476 | .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl, | |
| 476 | .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index, | |
| 477 | 477 | .variable => ptr_val.castTag(.variable).?.data.owner_decl, |
| 478 | 478 | else => unreachable, |
| 479 | 479 | }; |
| 480 | try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl); | |
| 480 | try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index); | |
| 481 | 481 | }, |
| 482 | 482 | .field_ptr => { |
| 483 | 483 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| ... | ... | @@ -685,7 +685,7 @@ pub const DeclGen = struct { |
| 685 | 685 | var index: usize = 0; |
| 686 | 686 | while (index < ai.len) : (index += 1) { |
| 687 | 687 | if (index != 0) try writer.writeAll(","); |
| 688 | const elem_val = try val.elemValue(arena_allocator, index); | |
| 688 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | |
| 689 | 689 | try dg.renderValue(writer, ai.elem_type, elem_val); |
| 690 | 690 | } |
| 691 | 691 | if (ai.sentinel) |s| { |
| ... | ... | @@ -837,7 +837,7 @@ pub const DeclGen = struct { |
| 837 | 837 | try writer.writeAll(".payload = {"); |
| 838 | 838 | } |
| 839 | 839 | |
| 840 | const index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag, target).?; | |
| 840 | const index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag, dg.module).?; | |
| 841 | 841 | const field_ty = ty.unionFields().values()[index].ty; |
| 842 | 842 | const field_name = ty.unionFields().keys()[index]; |
| 843 | 843 | if (field_ty.hasRuntimeBits()) { |
| ... | ... | @@ -889,7 +889,7 @@ pub const DeclGen = struct { |
| 889 | 889 | try w.writeAll("void"); |
| 890 | 890 | } |
| 891 | 891 | try w.writeAll(" "); |
| 892 | try dg.renderDeclName(w, dg.decl); | |
| 892 | try dg.renderDeclName(w, dg.decl_index); | |
| 893 | 893 | try w.writeAll("("); |
| 894 | 894 | const param_len = dg.decl.ty.fnParamLen(); |
| 895 | 895 | |
| ... | ... | @@ -927,8 +927,7 @@ pub const DeclGen = struct { |
| 927 | 927 | try bw.writeAll(" (*"); |
| 928 | 928 | |
| 929 | 929 | const name_start = buffer.items.len; |
| 930 | const target = dg.module.getTarget(); | |
| 931 | try bw.print("zig_F_{s})(", .{typeToCIdentifier(t, target)}); | |
| 930 | try bw.print("zig_F_{s})(", .{typeToCIdentifier(t, dg.module)}); | |
| 932 | 931 | const name_end = buffer.items.len - 2; |
| 933 | 932 | |
| 934 | 933 | const param_len = fn_info.param_types.len; |
| ... | ... | @@ -982,11 +981,10 @@ pub const DeclGen = struct { |
| 982 | 981 | |
| 983 | 982 | try bw.writeAll("; size_t len; } "); |
| 984 | 983 | const name_index = buffer.items.len; |
| 985 | const target = dg.module.getTarget(); | |
| 986 | 984 | if (t.isConstPtr()) { |
| 987 | try bw.print("zig_L_{s}", .{typeToCIdentifier(child_type, target)}); | |
| 985 | try bw.print("zig_L_{s}", .{typeToCIdentifier(child_type, dg.module)}); | |
| 988 | 986 | } else { |
| 989 | try bw.print("zig_M_{s}", .{typeToCIdentifier(child_type, target)}); | |
| 987 | try bw.print("zig_M_{s}", .{typeToCIdentifier(child_type, dg.module)}); | |
| 990 | 988 | } |
| 991 | 989 | if (ptr_sentinel) |s| { |
| 992 | 990 | try bw.writeAll("_s_"); |
| ... | ... | @@ -1009,7 +1007,7 @@ pub const DeclGen = struct { |
| 1009 | 1007 | |
| 1010 | 1008 | fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1011 | 1009 | const struct_obj = t.castTag(.@"struct").?.data; // Handle 0 bit types elsewhere. |
| 1012 | const fqn = try struct_obj.getFullyQualifiedName(dg.typedefs.allocator); | |
| 1010 | const fqn = try struct_obj.getFullyQualifiedName(dg.module); | |
| 1013 | 1011 | defer dg.typedefs.allocator.free(fqn); |
| 1014 | 1012 | |
| 1015 | 1013 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| ... | ... | @@ -1072,8 +1070,7 @@ pub const DeclGen = struct { |
| 1072 | 1070 | try buffer.appendSlice("} "); |
| 1073 | 1071 | |
| 1074 | 1072 | const name_start = buffer.items.len; |
| 1075 | const target = dg.module.getTarget(); | |
| 1076 | try writer.print("zig_T_{};\n", .{typeToCIdentifier(t, target)}); | |
| 1073 | try writer.print("zig_T_{};\n", .{typeToCIdentifier(t, dg.module)}); | |
| 1077 | 1074 | |
| 1078 | 1075 | const rendered = buffer.toOwnedSlice(); |
| 1079 | 1076 | errdefer dg.typedefs.allocator.free(rendered); |
| ... | ... | @@ -1090,7 +1087,7 @@ pub const DeclGen = struct { |
| 1090 | 1087 | |
| 1091 | 1088 | fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 1092 | 1089 | const union_ty = t.cast(Type.Payload.Union).?.data; |
| 1093 | const fqn = try union_ty.getFullyQualifiedName(dg.typedefs.allocator); | |
| 1090 | const fqn = try union_ty.getFullyQualifiedName(dg.module); | |
| 1094 | 1091 | defer dg.typedefs.allocator.free(fqn); |
| 1095 | 1092 | |
| 1096 | 1093 | const target = dg.module.getTarget(); |
| ... | ... | @@ -1157,7 +1154,6 @@ pub const DeclGen = struct { |
| 1157 | 1154 | try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0); |
| 1158 | 1155 | try bw.writeAll("; uint16_t error; } "); |
| 1159 | 1156 | const name_index = buffer.items.len; |
| 1160 | const target = dg.module.getTarget(); | |
| 1161 | 1157 | if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| { |
| 1162 | 1158 | const func = inf_err_set_payload.data.func; |
| 1163 | 1159 | try bw.writeAll("zig_E_"); |
| ... | ... | @@ -1165,7 +1161,7 @@ pub const DeclGen = struct { |
| 1165 | 1161 | try bw.writeAll(";\n"); |
| 1166 | 1162 | } else { |
| 1167 | 1163 | try bw.print("zig_E_{s}_{s};\n", .{ |
| 1168 | typeToCIdentifier(err_set_type, target), typeToCIdentifier(child_type, target), | |
| 1164 | typeToCIdentifier(err_set_type, dg.module), typeToCIdentifier(child_type, dg.module), | |
| 1169 | 1165 | }); |
| 1170 | 1166 | } |
| 1171 | 1167 | |
| ... | ... | @@ -1195,8 +1191,7 @@ pub const DeclGen = struct { |
| 1195 | 1191 | try dg.renderType(bw, elem_type); |
| 1196 | 1192 | |
| 1197 | 1193 | const name_start = buffer.items.len + 1; |
| 1198 | const target = dg.module.getTarget(); | |
| 1199 | try bw.print(" zig_A_{s}_{d}", .{ typeToCIdentifier(elem_type, target), c_len }); | |
| 1194 | try bw.print(" zig_A_{s}_{d}", .{ typeToCIdentifier(elem_type, dg.module), c_len }); | |
| 1200 | 1195 | const name_end = buffer.items.len; |
| 1201 | 1196 | |
| 1202 | 1197 | try bw.print("[{d}];\n", .{c_len}); |
| ... | ... | @@ -1224,8 +1219,7 @@ pub const DeclGen = struct { |
| 1224 | 1219 | try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0); |
| 1225 | 1220 | try bw.writeAll("; bool is_null; } "); |
| 1226 | 1221 | const name_index = buffer.items.len; |
| 1227 | const target = dg.module.getTarget(); | |
| 1228 | try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type, target)}); | |
| 1222 | try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type, dg.module)}); | |
| 1229 | 1223 | |
| 1230 | 1224 | const rendered = buffer.toOwnedSlice(); |
| 1231 | 1225 | errdefer dg.typedefs.allocator.free(rendered); |
| ... | ... | @@ -1535,16 +1529,17 @@ pub const DeclGen = struct { |
| 1535 | 1529 | } |
| 1536 | 1530 | } |
| 1537 | 1531 | |
| 1538 | fn renderDeclName(dg: DeclGen, writer: anytype, decl: *Decl) !void { | |
| 1539 | decl.markAlive(); | |
| 1532 | fn renderDeclName(dg: DeclGen, writer: anytype, decl_index: Decl.Index) !void { | |
| 1533 | const decl = dg.module.declPtr(decl_index); | |
| 1534 | dg.module.markDeclAlive(decl); | |
| 1540 | 1535 | |
| 1541 | if (dg.module.decl_exports.get(decl)) |exports| { | |
| 1536 | if (dg.module.decl_exports.get(decl_index)) |exports| { | |
| 1542 | 1537 | return writer.writeAll(exports[0].options.name); |
| 1543 | 1538 | } else if (decl.val.tag() == .extern_fn) { |
| 1544 | 1539 | return writer.writeAll(mem.sliceTo(decl.name, 0)); |
| 1545 | 1540 | } else { |
| 1546 | 1541 | const gpa = dg.module.gpa; |
| 1547 | const name = try decl.getFullyQualifiedName(gpa); | |
| 1542 | const name = try decl.getFullyQualifiedName(dg.module); | |
| 1548 | 1543 | defer gpa.free(name); |
| 1549 | 1544 | return writer.print("{ }", .{fmtIdent(name)}); |
| 1550 | 1545 | } |
| ... | ... | @@ -1616,7 +1611,11 @@ pub fn genDecl(o: *Object) !void { |
| 1616 | 1611 | try fwd_decl_writer.writeAll("zig_threadlocal "); |
| 1617 | 1612 | } |
| 1618 | 1613 | |
| 1619 | const decl_c_value: CValue = if (is_global) .{ .bytes = mem.span(o.dg.decl.name) } else .{ .decl = o.dg.decl }; | |
| 1614 | const decl_c_value: CValue = if (is_global) .{ | |
| 1615 | .bytes = mem.span(o.dg.decl.name), | |
| 1616 | } else .{ | |
| 1617 | .decl = o.dg.decl_index, | |
| 1618 | }; | |
| 1620 | 1619 | |
| 1621 | 1620 | try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align"); |
| 1622 | 1621 | try fwd_decl_writer.writeAll(";\n"); |
| ... | ... | @@ -1641,7 +1640,7 @@ pub fn genDecl(o: *Object) !void { |
| 1641 | 1640 | // TODO ask the Decl if it is const |
| 1642 | 1641 | // https://github.com/ziglang/zig/issues/7582 |
| 1643 | 1642 | |
| 1644 | const decl_c_value: CValue = .{ .decl = o.dg.decl }; | |
| 1643 | const decl_c_value: CValue = .{ .decl = o.dg.decl_index }; | |
| 1645 | 1644 | try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align"); |
| 1646 | 1645 | |
| 1647 | 1646 | try writer.writeAll(" = "); |
| ... | ... | @@ -2234,13 +2233,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2234 | 2233 | if (src_val_is_undefined) |
| 2235 | 2234 | return try airStoreUndefined(f, dest_ptr); |
| 2236 | 2235 | |
| 2237 | const target = f.object.dg.module.getTarget(); | |
| 2238 | 2236 | const writer = f.object.writer(); |
| 2239 | 2237 | if (lhs_child_type.zigTypeTag() == .Array) { |
| 2240 | 2238 | // For this memcpy to safely work we need the rhs to have the same |
| 2241 | 2239 | // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). |
| 2242 | 2240 | const rhs_type = f.air.typeOf(bin_op.rhs); |
| 2243 | assert(rhs_type.eql(lhs_child_type, target)); | |
| 2241 | assert(rhs_type.eql(lhs_child_type, f.object.dg.module)); | |
| 2244 | 2242 | |
| 2245 | 2243 | // If the source is a constant, writeCValue will emit a brace initialization |
| 2246 | 2244 | // so work around this by initializing into new local. |
| ... | ... | @@ -2780,7 +2778,8 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue { |
| 2780 | 2778 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 2781 | 2779 | const writer = f.object.writer(); |
| 2782 | 2780 | const function = f.air.values[ty_pl.payload].castTag(.function).?.data; |
| 2783 | try writer.print("/* dbg func:{s} */\n", .{function.owner_decl.name}); | |
| 2781 | const mod = f.object.dg.module; | |
| 2782 | try writer.print("/* dbg func:{s} */\n", .{mod.declPtr(function.owner_decl).name}); | |
| 2784 | 2783 | return CValue.none; |
| 2785 | 2784 | } |
| 2786 | 2785 |
src/codegen/llvm.zig+134-113| ... | ... | @@ -161,6 +161,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { |
| 161 | 161 | |
| 162 | 162 | pub const Object = struct { |
| 163 | 163 | gpa: Allocator, |
| 164 | module: *Module, | |
| 164 | 165 | llvm_module: *const llvm.Module, |
| 165 | 166 | di_builder: ?*llvm.DIBuilder, |
| 166 | 167 | /// One of these mappings: |
| ... | ... | @@ -181,7 +182,7 @@ pub const Object = struct { |
| 181 | 182 | /// version of the name and incorrectly get function not found in the llvm module. |
| 182 | 183 | /// * it works for functions not all globals. |
| 183 | 184 | /// Therefore, this table keeps track of the mapping. |
| 184 | decl_map: std.AutoHashMapUnmanaged(*const Module.Decl, *const llvm.Value), | |
| 185 | decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *const llvm.Value), | |
| 185 | 186 | /// Maps Zig types to LLVM types. The table memory itself is backed by the GPA of |
| 186 | 187 | /// the compiler, but the Type/Value memory here is backed by `type_map_arena`. |
| 187 | 188 | /// TODO we need to remove entries from this map in response to incremental compilation |
| ... | ... | @@ -340,6 +341,7 @@ pub const Object = struct { |
| 340 | 341 | |
| 341 | 342 | return Object{ |
| 342 | 343 | .gpa = gpa, |
| 344 | .module = options.module.?, | |
| 343 | 345 | .llvm_module = llvm_module, |
| 344 | 346 | .di_map = .{}, |
| 345 | 347 | .di_builder = opt_di_builder, |
| ... | ... | @@ -568,18 +570,20 @@ pub const Object = struct { |
| 568 | 570 | air: Air, |
| 569 | 571 | liveness: Liveness, |
| 570 | 572 | ) !void { |
| 571 | const decl = func.owner_decl; | |
| 573 | const decl_index = func.owner_decl; | |
| 574 | const decl = module.declPtr(decl_index); | |
| 572 | 575 | |
| 573 | 576 | var dg: DeclGen = .{ |
| 574 | 577 | .context = o.context, |
| 575 | 578 | .object = o, |
| 576 | 579 | .module = module, |
| 580 | .decl_index = decl_index, | |
| 577 | 581 | .decl = decl, |
| 578 | 582 | .err_msg = null, |
| 579 | 583 | .gpa = module.gpa, |
| 580 | 584 | }; |
| 581 | 585 | |
| 582 | const llvm_func = try dg.resolveLlvmFunction(decl); | |
| 586 | const llvm_func = try dg.resolveLlvmFunction(decl_index); | |
| 583 | 587 | |
| 584 | 588 | if (module.align_stack_fns.get(func)) |align_info| { |
| 585 | 589 | dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment); |
| ... | ... | @@ -632,7 +636,7 @@ pub const Object = struct { |
| 632 | 636 | |
| 633 | 637 | const line_number = decl.src_line + 1; |
| 634 | 638 | const is_internal_linkage = decl.val.tag() != .extern_fn and |
| 635 | !dg.module.decl_exports.contains(decl); | |
| 639 | !dg.module.decl_exports.contains(decl_index); | |
| 636 | 640 | const noret_bit: c_uint = if (fn_info.return_type.isNoReturn()) |
| 637 | 641 | llvm.DIFlags.NoReturn |
| 638 | 642 | else |
| ... | ... | @@ -684,48 +688,51 @@ pub const Object = struct { |
| 684 | 688 | fg.genBody(air.getMainBody()) catch |err| switch (err) { |
| 685 | 689 | error.CodegenFail => { |
| 686 | 690 | decl.analysis = .codegen_failure; |
| 687 | try module.failed_decls.put(module.gpa, decl, dg.err_msg.?); | |
| 691 | try module.failed_decls.put(module.gpa, decl_index, dg.err_msg.?); | |
| 688 | 692 | dg.err_msg = null; |
| 689 | 693 | return; |
| 690 | 694 | }, |
| 691 | 695 | else => |e| return e, |
| 692 | 696 | }; |
| 693 | 697 | |
| 694 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | |
| 695 | try o.updateDeclExports(module, decl, decl_exports); | |
| 698 | const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{}; | |
| 699 | try o.updateDeclExports(module, decl_index, decl_exports); | |
| 696 | 700 | } |
| 697 | 701 | |
| 698 | pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void { | |
| 702 | pub fn updateDecl(self: *Object, module: *Module, decl_index: Module.Decl.Index) !void { | |
| 703 | const decl = module.declPtr(decl_index); | |
| 699 | 704 | var dg: DeclGen = .{ |
| 700 | 705 | .context = self.context, |
| 701 | 706 | .object = self, |
| 702 | 707 | .module = module, |
| 703 | 708 | .decl = decl, |
| 709 | .decl_index = decl_index, | |
| 704 | 710 | .err_msg = null, |
| 705 | 711 | .gpa = module.gpa, |
| 706 | 712 | }; |
| 707 | 713 | dg.genDecl() catch |err| switch (err) { |
| 708 | 714 | error.CodegenFail => { |
| 709 | 715 | decl.analysis = .codegen_failure; |
| 710 | try module.failed_decls.put(module.gpa, decl, dg.err_msg.?); | |
| 716 | try module.failed_decls.put(module.gpa, decl_index, dg.err_msg.?); | |
| 711 | 717 | dg.err_msg = null; |
| 712 | 718 | return; |
| 713 | 719 | }, |
| 714 | 720 | else => |e| return e, |
| 715 | 721 | }; |
| 716 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | |
| 717 | try self.updateDeclExports(module, decl, decl_exports); | |
| 722 | const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{}; | |
| 723 | try self.updateDeclExports(module, decl_index, decl_exports); | |
| 718 | 724 | } |
| 719 | 725 | |
| 720 | 726 | pub fn updateDeclExports( |
| 721 | 727 | self: *Object, |
| 722 | module: *const Module, | |
| 723 | decl: *const Module.Decl, | |
| 728 | module: *Module, | |
| 729 | decl_index: Module.Decl.Index, | |
| 724 | 730 | exports: []const *Module.Export, |
| 725 | 731 | ) !void { |
| 726 | 732 | // If the module does not already have the function, we ignore this function call |
| 727 | 733 | // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`. |
| 728 | const llvm_global = self.decl_map.get(decl) orelse return; | |
| 734 | const llvm_global = self.decl_map.get(decl_index) orelse return; | |
| 735 | const decl = module.declPtr(decl_index); | |
| 729 | 736 | if (decl.isExtern()) { |
| 730 | 737 | llvm_global.setValueName(decl.name); |
| 731 | 738 | llvm_global.setUnnamedAddr(.False); |
| ... | ... | @@ -798,7 +805,7 @@ pub const Object = struct { |
| 798 | 805 | } |
| 799 | 806 | } |
| 800 | 807 | } else { |
| 801 | const fqn = try decl.getFullyQualifiedName(module.gpa); | |
| 808 | const fqn = try decl.getFullyQualifiedName(module); | |
| 802 | 809 | defer module.gpa.free(fqn); |
| 803 | 810 | llvm_global.setValueName2(fqn.ptr, fqn.len); |
| 804 | 811 | llvm_global.setLinkage(.Internal); |
| ... | ... | @@ -814,8 +821,8 @@ pub const Object = struct { |
| 814 | 821 | } |
| 815 | 822 | } |
| 816 | 823 | |
| 817 | pub fn freeDecl(self: *Object, decl: *Module.Decl) void { | |
| 818 | const llvm_value = self.decl_map.get(decl) orelse return; | |
| 824 | pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void { | |
| 825 | const llvm_value = self.decl_map.get(decl_index) orelse return; | |
| 819 | 826 | llvm_value.deleteGlobal(); |
| 820 | 827 | } |
| 821 | 828 | |
| ... | ... | @@ -847,7 +854,7 @@ pub const Object = struct { |
| 847 | 854 | const gpa = o.gpa; |
| 848 | 855 | // Be careful not to reference this `gop` variable after any recursive calls |
| 849 | 856 | // to `lowerDebugType`. |
| 850 | const gop = try o.di_type_map.getOrPutContext(gpa, ty, .{ .target = o.target }); | |
| 857 | const gop = try o.di_type_map.getOrPutContext(gpa, ty, .{ .mod = o.module }); | |
| 851 | 858 | if (gop.found_existing) { |
| 852 | 859 | const annotated = gop.value_ptr.*; |
| 853 | 860 | const di_type = annotated.toDIType(); |
| ... | ... | @@ -860,7 +867,7 @@ pub const Object = struct { |
| 860 | 867 | }; |
| 861 | 868 | return o.lowerDebugTypeImpl(entry, resolve, di_type); |
| 862 | 869 | } |
| 863 | errdefer assert(o.di_type_map.orderedRemoveContext(ty, .{ .target = o.target })); | |
| 870 | errdefer assert(o.di_type_map.orderedRemoveContext(ty, .{ .mod = o.module })); | |
| 864 | 871 | // The Type memory is ephemeral; since we want to store a longer-lived |
| 865 | 872 | // reference, we need to copy it here. |
| 866 | 873 | gop.key_ptr.* = try ty.copy(o.type_map_arena.allocator()); |
| ... | ... | @@ -891,7 +898,7 @@ pub const Object = struct { |
| 891 | 898 | .Int => { |
| 892 | 899 | const info = ty.intInfo(target); |
| 893 | 900 | assert(info.bits != 0); |
| 894 | const name = try ty.nameAlloc(gpa, target); | |
| 901 | const name = try ty.nameAlloc(gpa, o.module); | |
| 895 | 902 | defer gpa.free(name); |
| 896 | 903 | const dwarf_encoding: c_uint = switch (info.signedness) { |
| 897 | 904 | .signed => DW.ATE.signed, |
| ... | ... | @@ -902,13 +909,14 @@ pub const Object = struct { |
| 902 | 909 | return di_type; |
| 903 | 910 | }, |
| 904 | 911 | .Enum => { |
| 905 | const owner_decl = ty.getOwnerDecl(); | |
| 912 | const owner_decl_index = ty.getOwnerDecl(); | |
| 913 | const owner_decl = o.module.declPtr(owner_decl_index); | |
| 906 | 914 | |
| 907 | 915 | if (!ty.hasRuntimeBitsIgnoreComptime()) { |
| 908 | const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl); | |
| 916 | const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); | |
| 909 | 917 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 910 | 918 | // means we can't use `gop` anymore. |
| 911 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .target = o.target }); | |
| 919 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .mod = o.module }); | |
| 912 | 920 | return enum_di_ty; |
| 913 | 921 | } |
| 914 | 922 | |
| ... | ... | @@ -938,7 +946,7 @@ pub const Object = struct { |
| 938 | 946 | const di_file = try o.getDIFile(gpa, owner_decl.src_namespace.file_scope); |
| 939 | 947 | const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace); |
| 940 | 948 | |
| 941 | const name = try ty.nameAlloc(gpa, target); | |
| 949 | const name = try ty.nameAlloc(gpa, o.module); | |
| 942 | 950 | defer gpa.free(name); |
| 943 | 951 | var buffer: Type.Payload.Bits = undefined; |
| 944 | 952 | const int_ty = ty.intTagType(&buffer); |
| ... | ... | @@ -956,12 +964,12 @@ pub const Object = struct { |
| 956 | 964 | "", |
| 957 | 965 | ); |
| 958 | 966 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 959 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .target = o.target }); | |
| 967 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .mod = o.module }); | |
| 960 | 968 | return enum_di_ty; |
| 961 | 969 | }, |
| 962 | 970 | .Float => { |
| 963 | 971 | const bits = ty.floatBits(target); |
| 964 | const name = try ty.nameAlloc(gpa, target); | |
| 972 | const name = try ty.nameAlloc(gpa, o.module); | |
| 965 | 973 | defer gpa.free(name); |
| 966 | 974 | const di_type = dib.createBasicType(name, bits, DW.ATE.float); |
| 967 | 975 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); |
| ... | ... | @@ -1009,7 +1017,7 @@ pub const Object = struct { |
| 1009 | 1017 | const bland_ptr_ty = Type.initPayload(&payload.base); |
| 1010 | 1018 | const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve); |
| 1011 | 1019 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1012 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .target = o.target }); | |
| 1020 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .mod = o.module }); | |
| 1013 | 1021 | return ptr_di_ty; |
| 1014 | 1022 | } |
| 1015 | 1023 | |
| ... | ... | @@ -1018,7 +1026,7 @@ pub const Object = struct { |
| 1018 | 1026 | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 1019 | 1027 | const len_ty = Type.usize; |
| 1020 | 1028 | |
| 1021 | const name = try ty.nameAlloc(gpa, target); | |
| 1029 | const name = try ty.nameAlloc(gpa, o.module); | |
| 1022 | 1030 | defer gpa.free(name); |
| 1023 | 1031 | const di_file: ?*llvm.DIFile = null; |
| 1024 | 1032 | const line = 0; |
| ... | ... | @@ -1089,12 +1097,12 @@ pub const Object = struct { |
| 1089 | 1097 | ); |
| 1090 | 1098 | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 1091 | 1099 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1092 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); | |
| 1100 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module }); | |
| 1093 | 1101 | return full_di_ty; |
| 1094 | 1102 | } |
| 1095 | 1103 | |
| 1096 | 1104 | const elem_di_ty = try o.lowerDebugType(ptr_info.pointee_type, .fwd); |
| 1097 | const name = try ty.nameAlloc(gpa, target); | |
| 1105 | const name = try ty.nameAlloc(gpa, o.module); | |
| 1098 | 1106 | defer gpa.free(name); |
| 1099 | 1107 | const ptr_di_ty = dib.createPointerType( |
| 1100 | 1108 | elem_di_ty, |
| ... | ... | @@ -1103,7 +1111,7 @@ pub const Object = struct { |
| 1103 | 1111 | name, |
| 1104 | 1112 | ); |
| 1105 | 1113 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1106 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .target = o.target }); | |
| 1114 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .mod = o.module }); | |
| 1107 | 1115 | return ptr_di_ty; |
| 1108 | 1116 | }, |
| 1109 | 1117 | .Opaque => { |
| ... | ... | @@ -1112,9 +1120,10 @@ pub const Object = struct { |
| 1112 | 1120 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); |
| 1113 | 1121 | return di_ty; |
| 1114 | 1122 | } |
| 1115 | const name = try ty.nameAlloc(gpa, target); | |
| 1123 | const name = try ty.nameAlloc(gpa, o.module); | |
| 1116 | 1124 | defer gpa.free(name); |
| 1117 | const owner_decl = ty.getOwnerDecl(); | |
| 1125 | const owner_decl_index = ty.getOwnerDecl(); | |
| 1126 | const owner_decl = o.module.declPtr(owner_decl_index); | |
| 1118 | 1127 | const opaque_di_ty = dib.createForwardDeclType( |
| 1119 | 1128 | DW.TAG.structure_type, |
| 1120 | 1129 | name, |
| ... | ... | @@ -1124,7 +1133,7 @@ pub const Object = struct { |
| 1124 | 1133 | ); |
| 1125 | 1134 | // The recursive call to `lowerDebugType` va `namespaceToDebugScope` |
| 1126 | 1135 | // means we can't use `gop` anymore. |
| 1127 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(opaque_di_ty), .{ .target = o.target }); | |
| 1136 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(opaque_di_ty), .{ .mod = o.module }); | |
| 1128 | 1137 | return opaque_di_ty; |
| 1129 | 1138 | }, |
| 1130 | 1139 | .Array => { |
| ... | ... | @@ -1135,7 +1144,7 @@ pub const Object = struct { |
| 1135 | 1144 | @intCast(c_int, ty.arrayLen()), |
| 1136 | 1145 | ); |
| 1137 | 1146 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1138 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(array_di_ty), .{ .target = o.target }); | |
| 1147 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(array_di_ty), .{ .mod = o.module }); | |
| 1139 | 1148 | return array_di_ty; |
| 1140 | 1149 | }, |
| 1141 | 1150 | .Vector => { |
| ... | ... | @@ -1146,11 +1155,11 @@ pub const Object = struct { |
| 1146 | 1155 | ty.vectorLen(), |
| 1147 | 1156 | ); |
| 1148 | 1157 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1149 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(vector_di_ty), .{ .target = o.target }); | |
| 1158 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(vector_di_ty), .{ .mod = o.module }); | |
| 1150 | 1159 | return vector_di_ty; |
| 1151 | 1160 | }, |
| 1152 | 1161 | .Optional => { |
| 1153 | const name = try ty.nameAlloc(gpa, target); | |
| 1162 | const name = try ty.nameAlloc(gpa, o.module); | |
| 1154 | 1163 | defer gpa.free(name); |
| 1155 | 1164 | var buf: Type.Payload.ElemType = undefined; |
| 1156 | 1165 | const child_ty = ty.optionalChild(&buf); |
| ... | ... | @@ -1162,7 +1171,7 @@ pub const Object = struct { |
| 1162 | 1171 | if (ty.isPtrLikeOptional()) { |
| 1163 | 1172 | const ptr_di_ty = try o.lowerDebugType(child_ty, resolve); |
| 1164 | 1173 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1165 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .target = o.target }); | |
| 1174 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .mod = o.module }); | |
| 1166 | 1175 | return ptr_di_ty; |
| 1167 | 1176 | } |
| 1168 | 1177 | |
| ... | ... | @@ -1235,7 +1244,7 @@ pub const Object = struct { |
| 1235 | 1244 | ); |
| 1236 | 1245 | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 1237 | 1246 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1238 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); | |
| 1247 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module }); | |
| 1239 | 1248 | return full_di_ty; |
| 1240 | 1249 | }, |
| 1241 | 1250 | .ErrorUnion => { |
| ... | ... | @@ -1244,10 +1253,10 @@ pub const Object = struct { |
| 1244 | 1253 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 1245 | 1254 | const err_set_di_ty = try o.lowerDebugType(err_set_ty, .full); |
| 1246 | 1255 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1247 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty), .{ .target = o.target }); | |
| 1256 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty), .{ .mod = o.module }); | |
| 1248 | 1257 | return err_set_di_ty; |
| 1249 | 1258 | } |
| 1250 | const name = try ty.nameAlloc(gpa, target); | |
| 1259 | const name = try ty.nameAlloc(gpa, o.module); | |
| 1251 | 1260 | defer gpa.free(name); |
| 1252 | 1261 | const di_file: ?*llvm.DIFile = null; |
| 1253 | 1262 | const line = 0; |
| ... | ... | @@ -1332,7 +1341,7 @@ pub const Object = struct { |
| 1332 | 1341 | ); |
| 1333 | 1342 | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 1334 | 1343 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1335 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); | |
| 1344 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module }); | |
| 1336 | 1345 | return full_di_ty; |
| 1337 | 1346 | }, |
| 1338 | 1347 | .ErrorSet => { |
| ... | ... | @@ -1344,7 +1353,7 @@ pub const Object = struct { |
| 1344 | 1353 | }, |
| 1345 | 1354 | .Struct => { |
| 1346 | 1355 | const compile_unit_scope = o.di_compile_unit.?.toScope(); |
| 1347 | const name = try ty.nameAlloc(gpa, target); | |
| 1356 | const name = try ty.nameAlloc(gpa, o.module); | |
| 1348 | 1357 | defer gpa.free(name); |
| 1349 | 1358 | |
| 1350 | 1359 | if (ty.castTag(.@"struct")) |payload| { |
| ... | ... | @@ -1431,7 +1440,7 @@ pub const Object = struct { |
| 1431 | 1440 | ); |
| 1432 | 1441 | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 1433 | 1442 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1434 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); | |
| 1443 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module }); | |
| 1435 | 1444 | return full_di_ty; |
| 1436 | 1445 | } |
| 1437 | 1446 | |
| ... | ... | @@ -1445,23 +1454,23 @@ pub const Object = struct { |
| 1445 | 1454 | // into. Therefore we can satisfy this by making an empty namespace, |
| 1446 | 1455 | // rather than changing the frontend to unnecessarily resolve the |
| 1447 | 1456 | // struct field types. |
| 1448 | const owner_decl = ty.getOwnerDecl(); | |
| 1449 | const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl); | |
| 1457 | const owner_decl_index = ty.getOwnerDecl(); | |
| 1458 | const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); | |
| 1450 | 1459 | dib.replaceTemporary(fwd_decl, struct_di_ty); |
| 1451 | 1460 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 1452 | 1461 | // means we can't use `gop` anymore. |
| 1453 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .target = o.target }); | |
| 1462 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module }); | |
| 1454 | 1463 | return struct_di_ty; |
| 1455 | 1464 | } |
| 1456 | 1465 | } |
| 1457 | 1466 | |
| 1458 | 1467 | if (!ty.hasRuntimeBitsIgnoreComptime()) { |
| 1459 | const owner_decl = ty.getOwnerDecl(); | |
| 1460 | const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl); | |
| 1468 | const owner_decl_index = ty.getOwnerDecl(); | |
| 1469 | const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); | |
| 1461 | 1470 | dib.replaceTemporary(fwd_decl, struct_di_ty); |
| 1462 | 1471 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 1463 | 1472 | // means we can't use `gop` anymore. |
| 1464 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .target = o.target }); | |
| 1473 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module }); | |
| 1465 | 1474 | return struct_di_ty; |
| 1466 | 1475 | } |
| 1467 | 1476 | |
| ... | ... | @@ -1516,14 +1525,14 @@ pub const Object = struct { |
| 1516 | 1525 | ); |
| 1517 | 1526 | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 1518 | 1527 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1519 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); | |
| 1528 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module }); | |
| 1520 | 1529 | return full_di_ty; |
| 1521 | 1530 | }, |
| 1522 | 1531 | .Union => { |
| 1523 | 1532 | const compile_unit_scope = o.di_compile_unit.?.toScope(); |
| 1524 | const owner_decl = ty.getOwnerDecl(); | |
| 1533 | const owner_decl_index = ty.getOwnerDecl(); | |
| 1525 | 1534 | |
| 1526 | const name = try ty.nameAlloc(gpa, target); | |
| 1535 | const name = try ty.nameAlloc(gpa, o.module); | |
| 1527 | 1536 | defer gpa.free(name); |
| 1528 | 1537 | |
| 1529 | 1538 | const fwd_decl = opt_fwd_decl orelse blk: { |
| ... | ... | @@ -1540,11 +1549,11 @@ pub const Object = struct { |
| 1540 | 1549 | }; |
| 1541 | 1550 | |
| 1542 | 1551 | if (!ty.hasRuntimeBitsIgnoreComptime()) { |
| 1543 | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl); | |
| 1552 | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); | |
| 1544 | 1553 | dib.replaceTemporary(fwd_decl, union_di_ty); |
| 1545 | 1554 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 1546 | 1555 | // means we can't use `gop` anymore. |
| 1547 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target }); | |
| 1556 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .mod = o.module }); | |
| 1548 | 1557 | return union_di_ty; |
| 1549 | 1558 | } |
| 1550 | 1559 | |
| ... | ... | @@ -1572,7 +1581,7 @@ pub const Object = struct { |
| 1572 | 1581 | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 1573 | 1582 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 1574 | 1583 | // means we can't use `gop` anymore. |
| 1575 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); | |
| 1584 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module }); | |
| 1576 | 1585 | return full_di_ty; |
| 1577 | 1586 | } |
| 1578 | 1587 | |
| ... | ... | @@ -1626,7 +1635,7 @@ pub const Object = struct { |
| 1626 | 1635 | if (layout.tag_size == 0) { |
| 1627 | 1636 | dib.replaceTemporary(fwd_decl, union_di_ty); |
| 1628 | 1637 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1629 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target }); | |
| 1638 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .mod = o.module }); | |
| 1630 | 1639 | return union_di_ty; |
| 1631 | 1640 | } |
| 1632 | 1641 | |
| ... | ... | @@ -1685,7 +1694,7 @@ pub const Object = struct { |
| 1685 | 1694 | ); |
| 1686 | 1695 | dib.replaceTemporary(fwd_decl, full_di_ty); |
| 1687 | 1696 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1688 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); | |
| 1697 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module }); | |
| 1689 | 1698 | return full_di_ty; |
| 1690 | 1699 | }, |
| 1691 | 1700 | .Fn => { |
| ... | ... | @@ -1733,7 +1742,7 @@ pub const Object = struct { |
| 1733 | 1742 | 0, |
| 1734 | 1743 | ); |
| 1735 | 1744 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1736 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(fn_di_ty), .{ .target = o.target }); | |
| 1745 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(fn_di_ty), .{ .mod = o.module }); | |
| 1737 | 1746 | return fn_di_ty; |
| 1738 | 1747 | }, |
| 1739 | 1748 | .ComptimeInt => unreachable, |
| ... | ... | @@ -1762,7 +1771,8 @@ pub const Object = struct { |
| 1762 | 1771 | /// This is to be used instead of void for debug info types, to avoid tripping |
| 1763 | 1772 | /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"' |
| 1764 | 1773 | /// when targeting CodeView (Windows). |
| 1765 | fn makeEmptyNamespaceDIType(o: *Object, decl: *const Module.Decl) !*llvm.DIType { | |
| 1774 | fn makeEmptyNamespaceDIType(o: *Object, decl_index: Module.Decl.Index) !*llvm.DIType { | |
| 1775 | const decl = o.module.declPtr(decl_index); | |
| 1766 | 1776 | const fields: [0]*llvm.DIType = .{}; |
| 1767 | 1777 | return o.di_builder.?.createStructType( |
| 1768 | 1778 | try o.namespaceToDebugScope(decl.src_namespace), |
| ... | ... | @@ -1787,6 +1797,7 @@ pub const DeclGen = struct { |
| 1787 | 1797 | object: *Object, |
| 1788 | 1798 | module: *Module, |
| 1789 | 1799 | decl: *Module.Decl, |
| 1800 | decl_index: Module.Decl.Index, | |
| 1790 | 1801 | gpa: Allocator, |
| 1791 | 1802 | err_msg: ?*Module.ErrorMsg, |
| 1792 | 1803 | |
| ... | ... | @@ -1804,6 +1815,7 @@ pub const DeclGen = struct { |
| 1804 | 1815 | |
| 1805 | 1816 | fn genDecl(dg: *DeclGen) !void { |
| 1806 | 1817 | const decl = dg.decl; |
| 1818 | const decl_index = dg.decl_index; | |
| 1807 | 1819 | assert(decl.has_tv); |
| 1808 | 1820 | |
| 1809 | 1821 | log.debug("gen: {s} type: {}, value: {}", .{ |
| ... | ... | @@ -1817,7 +1829,7 @@ pub const DeclGen = struct { |
| 1817 | 1829 | _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl); |
| 1818 | 1830 | } else { |
| 1819 | 1831 | const target = dg.module.getTarget(); |
| 1820 | var global = try dg.resolveGlobalDecl(decl); | |
| 1832 | var global = try dg.resolveGlobalDecl(decl_index); | |
| 1821 | 1833 | global.setAlignment(decl.getAlignment(target)); |
| 1822 | 1834 | assert(decl.has_tv); |
| 1823 | 1835 | const init_val = if (decl.val.castTag(.variable)) |payload| init_val: { |
| ... | ... | @@ -1858,7 +1870,7 @@ pub const DeclGen = struct { |
| 1858 | 1870 | // old uses. |
| 1859 | 1871 | const new_global_ptr = new_global.constBitCast(global.typeOf()); |
| 1860 | 1872 | global.replaceAllUsesWith(new_global_ptr); |
| 1861 | dg.object.decl_map.putAssumeCapacity(decl, new_global); | |
| 1873 | dg.object.decl_map.putAssumeCapacity(decl_index, new_global); | |
| 1862 | 1874 | new_global.takeName(global); |
| 1863 | 1875 | global.deleteGlobal(); |
| 1864 | 1876 | global = new_global; |
| ... | ... | @@ -1869,7 +1881,7 @@ pub const DeclGen = struct { |
| 1869 | 1881 | const di_file = try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope); |
| 1870 | 1882 | |
| 1871 | 1883 | const line_number = decl.src_line + 1; |
| 1872 | const is_internal_linkage = !dg.module.decl_exports.contains(decl); | |
| 1884 | const is_internal_linkage = !dg.module.decl_exports.contains(decl_index); | |
| 1873 | 1885 | const di_global = dib.createGlobalVariable( |
| 1874 | 1886 | di_file.toScope(), |
| 1875 | 1887 | decl.name, |
| ... | ... | @@ -1888,12 +1900,10 @@ pub const DeclGen = struct { |
| 1888 | 1900 | /// If the llvm function does not exist, create it. |
| 1889 | 1901 | /// Note that this can be called before the function's semantic analysis has |
| 1890 | 1902 | /// completed, so if any attributes rely on that, they must be done in updateFunc, not here. |
| 1891 | fn resolveLlvmFunction(dg: *DeclGen, decl: *Module.Decl) !*const llvm.Value { | |
| 1892 | return dg.resolveLlvmFunctionExtra(decl, decl.ty); | |
| 1893 | } | |
| 1894 | ||
| 1895 | fn resolveLlvmFunctionExtra(dg: *DeclGen, decl: *Module.Decl, zig_fn_type: Type) !*const llvm.Value { | |
| 1896 | const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl); | |
| 1903 | fn resolveLlvmFunction(dg: *DeclGen, decl_index: Module.Decl.Index) !*const llvm.Value { | |
| 1904 | const decl = dg.module.declPtr(decl_index); | |
| 1905 | const zig_fn_type = decl.ty; | |
| 1906 | const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index); | |
| 1897 | 1907 | if (gop.found_existing) return gop.value_ptr.*; |
| 1898 | 1908 | |
| 1899 | 1909 | assert(decl.has_tv); |
| ... | ... | @@ -1903,7 +1913,7 @@ pub const DeclGen = struct { |
| 1903 | 1913 | |
| 1904 | 1914 | const fn_type = try dg.llvmType(zig_fn_type); |
| 1905 | 1915 | |
| 1906 | const fqn = try decl.getFullyQualifiedName(dg.gpa); | |
| 1916 | const fqn = try decl.getFullyQualifiedName(dg.module); | |
| 1907 | 1917 | defer dg.gpa.free(fqn); |
| 1908 | 1918 | |
| 1909 | 1919 | const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace"); |
| ... | ... | @@ -1996,12 +2006,13 @@ pub const DeclGen = struct { |
| 1996 | 2006 | // TODO add target-cpu and target-features fn attributes |
| 1997 | 2007 | } |
| 1998 | 2008 | |
| 1999 | fn resolveGlobalDecl(dg: *DeclGen, decl: *Module.Decl) Error!*const llvm.Value { | |
| 2000 | const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl); | |
| 2009 | fn resolveGlobalDecl(dg: *DeclGen, decl_index: Module.Decl.Index) Error!*const llvm.Value { | |
| 2010 | const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index); | |
| 2001 | 2011 | if (gop.found_existing) return gop.value_ptr.*; |
| 2002 | errdefer assert(dg.object.decl_map.remove(decl)); | |
| 2012 | errdefer assert(dg.object.decl_map.remove(decl_index)); | |
| 2003 | 2013 | |
| 2004 | const fqn = try decl.getFullyQualifiedName(dg.gpa); | |
| 2014 | const decl = dg.module.declPtr(decl_index); | |
| 2015 | const fqn = try decl.getFullyQualifiedName(dg.module); | |
| 2005 | 2016 | defer dg.gpa.free(fqn); |
| 2006 | 2017 | |
| 2007 | 2018 | const llvm_type = try dg.llvmType(decl.ty); |
| ... | ... | @@ -2122,7 +2133,7 @@ pub const DeclGen = struct { |
| 2122 | 2133 | }, |
| 2123 | 2134 | .Opaque => switch (t.tag()) { |
| 2124 | 2135 | .@"opaque" => { |
| 2125 | const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .target = target }); | |
| 2136 | const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module }); | |
| 2126 | 2137 | if (gop.found_existing) return gop.value_ptr.*; |
| 2127 | 2138 | |
| 2128 | 2139 | // The Type memory is ephemeral; since we want to store a longer-lived |
| ... | ... | @@ -2130,7 +2141,7 @@ pub const DeclGen = struct { |
| 2130 | 2141 | gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator()); |
| 2131 | 2142 | |
| 2132 | 2143 | const opaque_obj = t.castTag(.@"opaque").?.data; |
| 2133 | const name = try opaque_obj.getFullyQualifiedName(gpa); | |
| 2144 | const name = try opaque_obj.getFullyQualifiedName(dg.module); | |
| 2134 | 2145 | defer gpa.free(name); |
| 2135 | 2146 | |
| 2136 | 2147 | const llvm_struct_ty = dg.context.structCreateNamed(name); |
| ... | ... | @@ -2191,7 +2202,7 @@ pub const DeclGen = struct { |
| 2191 | 2202 | return dg.context.intType(16); |
| 2192 | 2203 | }, |
| 2193 | 2204 | .Struct => { |
| 2194 | const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .target = target }); | |
| 2205 | const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module }); | |
| 2195 | 2206 | if (gop.found_existing) return gop.value_ptr.*; |
| 2196 | 2207 | |
| 2197 | 2208 | // The Type memory is ephemeral; since we want to store a longer-lived |
| ... | ... | @@ -2260,7 +2271,7 @@ pub const DeclGen = struct { |
| 2260 | 2271 | return int_llvm_ty; |
| 2261 | 2272 | } |
| 2262 | 2273 | |
| 2263 | const name = try struct_obj.getFullyQualifiedName(gpa); | |
| 2274 | const name = try struct_obj.getFullyQualifiedName(dg.module); | |
| 2264 | 2275 | defer gpa.free(name); |
| 2265 | 2276 | |
| 2266 | 2277 | const llvm_struct_ty = dg.context.structCreateNamed(name); |
| ... | ... | @@ -2314,7 +2325,7 @@ pub const DeclGen = struct { |
| 2314 | 2325 | return llvm_struct_ty; |
| 2315 | 2326 | }, |
| 2316 | 2327 | .Union => { |
| 2317 | const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .target = target }); | |
| 2328 | const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module }); | |
| 2318 | 2329 | if (gop.found_existing) return gop.value_ptr.*; |
| 2319 | 2330 | |
| 2320 | 2331 | // The Type memory is ephemeral; since we want to store a longer-lived |
| ... | ... | @@ -2330,7 +2341,7 @@ pub const DeclGen = struct { |
| 2330 | 2341 | return enum_tag_llvm_ty; |
| 2331 | 2342 | } |
| 2332 | 2343 | |
| 2333 | const name = try union_obj.getFullyQualifiedName(gpa); | |
| 2344 | const name = try union_obj.getFullyQualifiedName(dg.module); | |
| 2334 | 2345 | defer gpa.free(name); |
| 2335 | 2346 | |
| 2336 | 2347 | const llvm_union_ty = dg.context.structCreateNamed(name); |
| ... | ... | @@ -2439,7 +2450,7 @@ pub const DeclGen = struct { |
| 2439 | 2450 | // TODO this duplicates code with Pointer but they should share the handling |
| 2440 | 2451 | // of the tv.val.tag() and then Int should do extra constPtrToInt on top |
| 2441 | 2452 | .Int => switch (tv.val.tag()) { |
| 2442 | .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl), | |
| 2453 | .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index), | |
| 2443 | 2454 | .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), |
| 2444 | 2455 | else => { |
| 2445 | 2456 | var bigint_space: Value.BigIntSpace = undefined; |
| ... | ... | @@ -2524,12 +2535,13 @@ pub const DeclGen = struct { |
| 2524 | 2535 | } |
| 2525 | 2536 | }, |
| 2526 | 2537 | .Pointer => switch (tv.val.tag()) { |
| 2527 | .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl), | |
| 2538 | .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index), | |
| 2528 | 2539 | .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), |
| 2529 | 2540 | .variable => { |
| 2530 | const decl = tv.val.castTag(.variable).?.data.owner_decl; | |
| 2531 | decl.markAlive(); | |
| 2532 | const val = try dg.resolveGlobalDecl(decl); | |
| 2541 | const decl_index = tv.val.castTag(.variable).?.data.owner_decl; | |
| 2542 | const decl = dg.module.declPtr(decl_index); | |
| 2543 | dg.module.markDeclAlive(decl); | |
| 2544 | const val = try dg.resolveGlobalDecl(decl_index); | |
| 2533 | 2545 | const llvm_var_type = try dg.llvmType(tv.ty); |
| 2534 | 2546 | const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace"); |
| 2535 | 2547 | const llvm_type = llvm_var_type.pointerType(llvm_addrspace); |
| ... | ... | @@ -2683,13 +2695,14 @@ pub const DeclGen = struct { |
| 2683 | 2695 | return dg.context.constStruct(&fields, fields.len, .False); |
| 2684 | 2696 | }, |
| 2685 | 2697 | .Fn => { |
| 2686 | const fn_decl = switch (tv.val.tag()) { | |
| 2698 | const fn_decl_index = switch (tv.val.tag()) { | |
| 2687 | 2699 | .extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl, |
| 2688 | 2700 | .function => tv.val.castTag(.function).?.data.owner_decl, |
| 2689 | 2701 | else => unreachable, |
| 2690 | 2702 | }; |
| 2691 | fn_decl.markAlive(); | |
| 2692 | return dg.resolveLlvmFunction(fn_decl); | |
| 2703 | const fn_decl = dg.module.declPtr(fn_decl_index); | |
| 2704 | dg.module.markDeclAlive(fn_decl); | |
| 2705 | return dg.resolveLlvmFunction(fn_decl_index); | |
| 2693 | 2706 | }, |
| 2694 | 2707 | .ErrorSet => { |
| 2695 | 2708 | const llvm_ty = try dg.llvmType(tv.ty); |
| ... | ... | @@ -2911,7 +2924,7 @@ pub const DeclGen = struct { |
| 2911 | 2924 | }); |
| 2912 | 2925 | } |
| 2913 | 2926 | const union_obj = tv.ty.cast(Type.Payload.Union).?.data; |
| 2914 | const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag, target).?; | |
| 2927 | const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag, dg.module).?; | |
| 2915 | 2928 | assert(union_obj.haveFieldTypes()); |
| 2916 | 2929 | const field_ty = union_obj.fields.values()[field_index].ty; |
| 2917 | 2930 | const payload = p: { |
| ... | ... | @@ -3049,17 +3062,22 @@ pub const DeclGen = struct { |
| 3049 | 3062 | llvm_ptr: *const llvm.Value, |
| 3050 | 3063 | }; |
| 3051 | 3064 | |
| 3052 | fn lowerParentPtrDecl(dg: *DeclGen, ptr_val: Value, decl: *Module.Decl, ptr_child_ty: Type) Error!*const llvm.Value { | |
| 3053 | decl.markAlive(); | |
| 3065 | fn lowerParentPtrDecl( | |
| 3066 | dg: *DeclGen, | |
| 3067 | ptr_val: Value, | |
| 3068 | decl_index: Module.Decl.Index, | |
| 3069 | ptr_child_ty: Type, | |
| 3070 | ) Error!*const llvm.Value { | |
| 3071 | const decl = dg.module.declPtr(decl_index); | |
| 3072 | dg.module.markDeclAlive(decl); | |
| 3054 | 3073 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 3055 | 3074 | .base = .{ .tag = .single_mut_pointer }, |
| 3056 | 3075 | .data = decl.ty, |
| 3057 | 3076 | }; |
| 3058 | 3077 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 3059 | const llvm_ptr = try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl); | |
| 3078 | const llvm_ptr = try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index); | |
| 3060 | 3079 | |
| 3061 | const target = dg.module.getTarget(); | |
| 3062 | if (ptr_child_ty.eql(decl.ty, target)) { | |
| 3080 | if (ptr_child_ty.eql(decl.ty, dg.module)) { | |
| 3063 | 3081 | return llvm_ptr; |
| 3064 | 3082 | } else { |
| 3065 | 3083 | return llvm_ptr.constBitCast((try dg.llvmType(ptr_child_ty)).pointerType(0)); |
| ... | ... | @@ -3071,7 +3089,7 @@ pub const DeclGen = struct { |
| 3071 | 3089 | var bitcast_needed: bool = undefined; |
| 3072 | 3090 | const llvm_ptr = switch (ptr_val.tag()) { |
| 3073 | 3091 | .decl_ref_mut => { |
| 3074 | const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl; | |
| 3092 | const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl_index; | |
| 3075 | 3093 | return dg.lowerParentPtrDecl(ptr_val, decl, ptr_child_ty); |
| 3076 | 3094 | }, |
| 3077 | 3095 | .decl_ref => { |
| ... | ... | @@ -3123,7 +3141,7 @@ pub const DeclGen = struct { |
| 3123 | 3141 | }, |
| 3124 | 3142 | .Struct => { |
| 3125 | 3143 | const field_ty = parent_ty.structFieldType(field_index); |
| 3126 | bitcast_needed = !field_ty.eql(ptr_child_ty, target); | |
| 3144 | bitcast_needed = !field_ty.eql(ptr_child_ty, dg.module); | |
| 3127 | 3145 | |
| 3128 | 3146 | var ty_buf: Type.Payload.Pointer = undefined; |
| 3129 | 3147 | const llvm_field_index = llvmFieldIndex(parent_ty, field_index, target, &ty_buf).?; |
| ... | ... | @@ -3139,7 +3157,7 @@ pub const DeclGen = struct { |
| 3139 | 3157 | .elem_ptr => blk: { |
| 3140 | 3158 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 3141 | 3159 | const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr, elem_ptr.elem_ty); |
| 3142 | bitcast_needed = !elem_ptr.elem_ty.eql(ptr_child_ty, target); | |
| 3160 | bitcast_needed = !elem_ptr.elem_ty.eql(ptr_child_ty, dg.module); | |
| 3143 | 3161 | |
| 3144 | 3162 | const llvm_usize = try dg.llvmType(Type.usize); |
| 3145 | 3163 | const indices: [1]*const llvm.Value = .{ |
| ... | ... | @@ -3153,7 +3171,7 @@ pub const DeclGen = struct { |
| 3153 | 3171 | var buf: Type.Payload.ElemType = undefined; |
| 3154 | 3172 | |
| 3155 | 3173 | const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf); |
| 3156 | bitcast_needed = !payload_ty.eql(ptr_child_ty, target); | |
| 3174 | bitcast_needed = !payload_ty.eql(ptr_child_ty, dg.module); | |
| 3157 | 3175 | |
| 3158 | 3176 | if (!payload_ty.hasRuntimeBitsIgnoreComptime() or payload_ty.isPtrLikeOptional()) { |
| 3159 | 3177 | // In this case, we represent pointer to optional the same as pointer |
| ... | ... | @@ -3173,7 +3191,7 @@ pub const DeclGen = struct { |
| 3173 | 3191 | const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, eu_payload_ptr.container_ty); |
| 3174 | 3192 | |
| 3175 | 3193 | const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload(); |
| 3176 | bitcast_needed = !payload_ty.eql(ptr_child_ty, target); | |
| 3194 | bitcast_needed = !payload_ty.eql(ptr_child_ty, dg.module); | |
| 3177 | 3195 | |
| 3178 | 3196 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3179 | 3197 | // In this case, we represent pointer to error union the same as pointer |
| ... | ... | @@ -3201,15 +3219,14 @@ pub const DeclGen = struct { |
| 3201 | 3219 | fn lowerDeclRefValue( |
| 3202 | 3220 | self: *DeclGen, |
| 3203 | 3221 | tv: TypedValue, |
| 3204 | decl: *Module.Decl, | |
| 3222 | decl_index: Module.Decl.Index, | |
| 3205 | 3223 | ) Error!*const llvm.Value { |
| 3206 | const target = self.module.getTarget(); | |
| 3207 | 3224 | if (tv.ty.isSlice()) { |
| 3208 | 3225 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 3209 | 3226 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); |
| 3210 | 3227 | var slice_len: Value.Payload.U64 = .{ |
| 3211 | 3228 | .base = .{ .tag = .int_u64 }, |
| 3212 | .data = tv.val.sliceLen(target), | |
| 3229 | .data = tv.val.sliceLen(self.module), | |
| 3213 | 3230 | }; |
| 3214 | 3231 | const fields: [2]*const llvm.Value = .{ |
| 3215 | 3232 | try self.genTypedValue(.{ |
| ... | ... | @@ -3229,8 +3246,9 @@ pub const DeclGen = struct { |
| 3229 | 3246 | // const bar = foo; |
| 3230 | 3247 | // ... &bar; |
| 3231 | 3248 | // `bar` is just an alias and we actually want to lower a reference to `foo`. |
| 3249 | const decl = self.module.declPtr(decl_index); | |
| 3232 | 3250 | if (decl.val.castTag(.function)) |func| { |
| 3233 | if (func.data.owner_decl != decl) { | |
| 3251 | if (func.data.owner_decl != decl_index) { | |
| 3234 | 3252 | return self.lowerDeclRefValue(tv, func.data.owner_decl); |
| 3235 | 3253 | } |
| 3236 | 3254 | } |
| ... | ... | @@ -3240,12 +3258,12 @@ pub const DeclGen = struct { |
| 3240 | 3258 | return self.lowerPtrToVoid(tv.ty); |
| 3241 | 3259 | } |
| 3242 | 3260 | |
| 3243 | decl.markAlive(); | |
| 3261 | self.module.markDeclAlive(decl); | |
| 3244 | 3262 | |
| 3245 | 3263 | const llvm_val = if (is_fn_body) |
| 3246 | try self.resolveLlvmFunction(decl) | |
| 3264 | try self.resolveLlvmFunction(decl_index) | |
| 3247 | 3265 | else |
| 3248 | try self.resolveGlobalDecl(decl); | |
| 3266 | try self.resolveGlobalDecl(decl_index); | |
| 3249 | 3267 | |
| 3250 | 3268 | const llvm_type = try self.llvmType(tv.ty); |
| 3251 | 3269 | if (tv.ty.zigTypeTag() == .Int) { |
| ... | ... | @@ -4405,7 +4423,8 @@ pub const FuncGen = struct { |
| 4405 | 4423 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 4406 | 4424 | |
| 4407 | 4425 | const func = self.air.values[ty_pl.payload].castTag(.function).?.data; |
| 4408 | const decl = func.owner_decl; | |
| 4426 | const decl_index = func.owner_decl; | |
| 4427 | const decl = self.dg.module.declPtr(decl_index); | |
| 4409 | 4428 | const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope); |
| 4410 | 4429 | self.di_file = di_file; |
| 4411 | 4430 | const line_number = decl.src_line + 1; |
| ... | ... | @@ -4417,10 +4436,10 @@ pub const FuncGen = struct { |
| 4417 | 4436 | .base_line = self.base_line, |
| 4418 | 4437 | }); |
| 4419 | 4438 | |
| 4420 | const fqn = try decl.getFullyQualifiedName(self.gpa); | |
| 4439 | const fqn = try decl.getFullyQualifiedName(self.dg.module); | |
| 4421 | 4440 | defer self.gpa.free(fqn); |
| 4422 | 4441 | |
| 4423 | const is_internal_linkage = !self.dg.module.decl_exports.contains(decl); | |
| 4442 | const is_internal_linkage = !self.dg.module.decl_exports.contains(decl_index); | |
| 4424 | 4443 | const subprogram = dib.createFunction( |
| 4425 | 4444 | di_file.toScope(), |
| 4426 | 4445 | decl.name, |
| ... | ... | @@ -4447,7 +4466,8 @@ pub const FuncGen = struct { |
| 4447 | 4466 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 4448 | 4467 | |
| 4449 | 4468 | const func = self.air.values[ty_pl.payload].castTag(.function).?.data; |
| 4450 | const decl = func.owner_decl; | |
| 4469 | const mod = self.dg.module; | |
| 4470 | const decl = mod.declPtr(func.owner_decl); | |
| 4451 | 4471 | const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope); |
| 4452 | 4472 | self.di_file = di_file; |
| 4453 | 4473 | const old = self.dbg_inlined.pop(); |
| ... | ... | @@ -5887,7 +5907,7 @@ pub const FuncGen = struct { |
| 5887 | 5907 | if (self.dg.object.di_builder) |dib| { |
| 5888 | 5908 | const src_index = self.getSrcArgIndex(self.arg_index - 1); |
| 5889 | 5909 | const func = self.dg.decl.getFunction().?; |
| 5890 | const lbrace_line = func.owner_decl.src_line + func.lbrace_line + 1; | |
| 5910 | const lbrace_line = self.dg.module.declPtr(func.owner_decl).src_line + func.lbrace_line + 1; | |
| 5891 | 5911 | const lbrace_col = func.lbrace_column + 1; |
| 5892 | 5912 | const di_local_var = dib.createParameterVariable( |
| 5893 | 5913 | self.di_scope.?, |
| ... | ... | @@ -6430,8 +6450,9 @@ pub const FuncGen = struct { |
| 6430 | 6450 | const operand = try self.resolveInst(un_op); |
| 6431 | 6451 | const enum_ty = self.air.typeOf(un_op); |
| 6432 | 6452 | |
| 6453 | const mod = self.dg.module; | |
| 6433 | 6454 | const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{ |
| 6434 | try enum_ty.getOwnerDecl().getFullyQualifiedName(arena), | |
| 6455 | try mod.declPtr(enum_ty.getOwnerDecl()).getFullyQualifiedName(mod), | |
| 6435 | 6456 | }); |
| 6436 | 6457 | |
| 6437 | 6458 | const llvm_fn = try self.getEnumTagNameFunction(enum_ty, llvm_fn_name); |
| ... | ... | @@ -6617,7 +6638,7 @@ pub const FuncGen = struct { |
| 6617 | 6638 | |
| 6618 | 6639 | for (values) |*val, i| { |
| 6619 | 6640 | var buf: Value.ElemValueBuffer = undefined; |
| 6620 | const elem = mask.elemValueBuffer(i, &buf); | |
| 6641 | const elem = mask.elemValueBuffer(self.dg.module, i, &buf); | |
| 6621 | 6642 | if (elem.isUndef()) { |
| 6622 | 6643 | val.* = llvm_i32.getUndef(); |
| 6623 | 6644 | } else { |
src/codegen/spirv.zig+10-6| ... | ... | @@ -633,7 +633,13 @@ pub const DeclGen = struct { |
| 633 | 633 | return result_id.toRef(); |
| 634 | 634 | } |
| 635 | 635 | |
| 636 | fn airArithOp(self: *DeclGen, inst: Air.Inst.Index, comptime fop: Opcode, comptime sop: Opcode, comptime uop: Opcode) !IdRef { | |
| 636 | fn airArithOp( | |
| 637 | self: *DeclGen, | |
| 638 | inst: Air.Inst.Index, | |
| 639 | comptime fop: Opcode, | |
| 640 | comptime sop: Opcode, | |
| 641 | comptime uop: Opcode, | |
| 642 | ) !IdRef { | |
| 637 | 643 | // LHS and RHS are guaranteed to have the same type, and AIR guarantees |
| 638 | 644 | // the result to be the same as the LHS and RHS, which matches SPIR-V. |
| 639 | 645 | const ty = self.air.typeOfIndex(inst); |
| ... | ... | @@ -644,10 +650,8 @@ pub const DeclGen = struct { |
| 644 | 650 | const result_id = self.spv.allocId(); |
| 645 | 651 | const result_type_id = try self.resolveTypeId(ty); |
| 646 | 652 | |
| 647 | const target = self.getTarget(); | |
| 648 | ||
| 649 | assert(self.air.typeOf(bin_op.lhs).eql(ty, target)); | |
| 650 | assert(self.air.typeOf(bin_op.rhs).eql(ty, target)); | |
| 653 | assert(self.air.typeOf(bin_op.lhs).eql(ty, self.module)); | |
| 654 | assert(self.air.typeOf(bin_op.rhs).eql(ty, self.module)); | |
| 651 | 655 | |
| 652 | 656 | // Binary operations are generally applicable to both scalar and vector operations |
| 653 | 657 | // in SPIR-V, but int and float versions of operations require different opcodes. |
| ... | ... | @@ -694,7 +698,7 @@ pub const DeclGen = struct { |
| 694 | 698 | const result_id = self.spv.allocId(); |
| 695 | 699 | const result_type_id = try self.resolveTypeId(Type.initTag(.bool)); |
| 696 | 700 | const op_ty = self.air.typeOf(bin_op.lhs); |
| 697 | assert(op_ty.eql(self.air.typeOf(bin_op.rhs), self.getTarget())); | |
| 701 | assert(op_ty.eql(self.air.typeOf(bin_op.rhs), self.module)); | |
| 698 | 702 | |
| 699 | 703 | // Comparisons are generally applicable to both scalar and vector operations in SPIR-V, |
| 700 | 704 | // but int and float versions of operations require different opcodes. |
src/crash_report.zig+9-6| ... | ... | @@ -90,9 +90,11 @@ fn dumpStatusReport() !void { |
| 90 | 90 | |
| 91 | 91 | const stderr = io.getStdErr().writer(); |
| 92 | 92 | const block: *Sema.Block = anal.block; |
| 93 | const mod = anal.sema.mod; | |
| 94 | const block_src_decl = mod.declPtr(block.src_decl); | |
| 93 | 95 | |
| 94 | 96 | try stderr.writeAll("Analyzing "); |
| 95 | try writeFullyQualifiedDeclWithFile(block.src_decl, stderr); | |
| 97 | try writeFullyQualifiedDeclWithFile(mod, block_src_decl, stderr); | |
| 96 | 98 | try stderr.writeAll("\n"); |
| 97 | 99 | |
| 98 | 100 | print_zir.renderInstructionContext( |
| ... | ... | @@ -100,7 +102,7 @@ fn dumpStatusReport() !void { |
| 100 | 102 | anal.body, |
| 101 | 103 | anal.body_index, |
| 102 | 104 | block.namespace.file_scope, |
| 103 | block.src_decl.src_node, | |
| 105 | block_src_decl.src_node, | |
| 104 | 106 | 6, // indent |
| 105 | 107 | stderr, |
| 106 | 108 | ) catch |err| switch (err) { |
| ... | ... | @@ -115,13 +117,14 @@ fn dumpStatusReport() !void { |
| 115 | 117 | while (parent) |curr| { |
| 116 | 118 | fba.reset(); |
| 117 | 119 | try stderr.writeAll(" in "); |
| 118 | try writeFullyQualifiedDeclWithFile(curr.block.src_decl, stderr); | |
| 120 | const curr_block_src_decl = mod.declPtr(curr.block.src_decl); | |
| 121 | try writeFullyQualifiedDeclWithFile(mod, curr_block_src_decl, stderr); | |
| 119 | 122 | try stderr.writeAll("\n > "); |
| 120 | 123 | print_zir.renderSingleInstruction( |
| 121 | 124 | allocator, |
| 122 | 125 | curr.body[curr.body_index], |
| 123 | 126 | curr.block.namespace.file_scope, |
| 124 | curr.block.src_decl.src_node, | |
| 127 | curr_block_src_decl.src_node, | |
| 125 | 128 | 6, // indent |
| 126 | 129 | stderr, |
| 127 | 130 | ) catch |err| switch (err) { |
| ... | ... | @@ -146,10 +149,10 @@ fn writeFilePath(file: *Module.File, stream: anytype) !void { |
| 146 | 149 | try stream.writeAll(file.sub_file_path); |
| 147 | 150 | } |
| 148 | 151 | |
| 149 | fn writeFullyQualifiedDeclWithFile(decl: *Decl, stream: anytype) !void { | |
| 152 | fn writeFullyQualifiedDeclWithFile(mod: *Module, decl: *Decl, stream: anytype) !void { | |
| 150 | 153 | try writeFilePath(decl.getFileScope(), stream); |
| 151 | 154 | try stream.writeAll(": "); |
| 152 | try decl.renderFullyQualifiedDebugName(stream); | |
| 155 | try decl.renderFullyQualifiedDebugName(mod, stream); | |
| 153 | 156 | } |
| 154 | 157 | |
| 155 | 158 | pub fn compilerPanic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { |
src/link.zig+51-47| ... | ... | @@ -417,17 +417,18 @@ pub const File = struct { |
| 417 | 417 | /// Called from within the CodeGen to lower a local variable instantion as an unnamed |
| 418 | 418 | /// constant. Returns the symbol index of the lowered constant in the read-only section |
| 419 | 419 | /// of the final binary. |
| 420 | pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl: *Module.Decl) UpdateDeclError!u32 { | |
| 420 | pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: Module.Decl.Index) UpdateDeclError!u32 { | |
| 421 | const decl = base.options.module.?.declPtr(decl_index); | |
| 421 | 422 | log.debug("lowerUnnamedConst {*} ({s})", .{ decl, decl.name }); |
| 422 | 423 | switch (base.tag) { |
| 423 | 424 | // zig fmt: off |
| 424 | .coff => return @fieldParentPtr(Coff, "base", base).lowerUnnamedConst(tv, decl), | |
| 425 | .elf => return @fieldParentPtr(Elf, "base", base).lowerUnnamedConst(tv, decl), | |
| 426 | .macho => return @fieldParentPtr(MachO, "base", base).lowerUnnamedConst(tv, decl), | |
| 427 | .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerUnnamedConst(tv, decl), | |
| 425 | .coff => return @fieldParentPtr(Coff, "base", base).lowerUnnamedConst(tv, decl_index), | |
| 426 | .elf => return @fieldParentPtr(Elf, "base", base).lowerUnnamedConst(tv, decl_index), | |
| 427 | .macho => return @fieldParentPtr(MachO, "base", base).lowerUnnamedConst(tv, decl_index), | |
| 428 | .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerUnnamedConst(tv, decl_index), | |
| 428 | 429 | .spirv => unreachable, |
| 429 | 430 | .c => unreachable, |
| 430 | .wasm => unreachable, | |
| 431 | .wasm => return @fieldParentPtr(Wasm, "base", base).lowerUnnamedConst(tv, decl_index), | |
| 431 | 432 | .nvptx => unreachable, |
| 432 | 433 | // zig fmt: on |
| 433 | 434 | } |
| ... | ... | @@ -435,19 +436,20 @@ pub const File = struct { |
| 435 | 436 | |
| 436 | 437 | /// May be called before or after updateDeclExports but must be called |
| 437 | 438 | /// after allocateDeclIndexes for any given Decl. |
| 438 | pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) UpdateDeclError!void { | |
| 439 | pub fn updateDecl(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void { | |
| 440 | const decl = module.declPtr(decl_index); | |
| 439 | 441 | log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty.fmtDebug() }); |
| 440 | 442 | assert(decl.has_tv); |
| 441 | 443 | switch (base.tag) { |
| 442 | 444 | // zig fmt: off |
| 443 | .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl), | |
| 444 | .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), | |
| 445 | .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl), | |
| 446 | .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl), | |
| 447 | .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl), | |
| 448 | .spirv => return @fieldParentPtr(SpirV, "base", base).updateDecl(module, decl), | |
| 449 | .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDecl(module, decl), | |
| 450 | .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateDecl(module, decl), | |
| 445 | .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl_index), | |
| 446 | .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl_index), | |
| 447 | .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl_index), | |
| 448 | .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index), | |
| 449 | .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl_index), | |
| 450 | .spirv => return @fieldParentPtr(SpirV, "base", base).updateDecl(module, decl_index), | |
| 451 | .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDecl(module, decl_index), | |
| 452 | .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateDecl(module, decl_index), | |
| 451 | 453 | // zig fmt: on |
| 452 | 454 | } |
| 453 | 455 | } |
| ... | ... | @@ -455,8 +457,9 @@ pub const File = struct { |
| 455 | 457 | /// May be called before or after updateDeclExports but must be called |
| 456 | 458 | /// after allocateDeclIndexes for any given Decl. |
| 457 | 459 | pub fn updateFunc(base: *File, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) UpdateDeclError!void { |
| 460 | const owner_decl = module.declPtr(func.owner_decl); | |
| 458 | 461 | log.debug("updateFunc {*} ({s}), type={}", .{ |
| 459 | func.owner_decl, func.owner_decl.name, func.owner_decl.ty.fmtDebug(), | |
| 462 | owner_decl, owner_decl.name, owner_decl.ty.fmtDebug(), | |
| 460 | 463 | }); |
| 461 | 464 | switch (base.tag) { |
| 462 | 465 | // zig fmt: off |
| ... | ... | @@ -492,19 +495,20 @@ pub const File = struct { |
| 492 | 495 | /// TODO we're transitioning to deleting this function and instead having |
| 493 | 496 | /// each linker backend notice the first time updateDecl or updateFunc is called, or |
| 494 | 497 | /// a callee referenced from AIR. |
| 495 | pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) error{OutOfMemory}!void { | |
| 498 | pub fn allocateDeclIndexes(base: *File, decl_index: Module.Decl.Index) error{OutOfMemory}!void { | |
| 499 | const decl = base.options.module.?.declPtr(decl_index); | |
| 496 | 500 | log.debug("allocateDeclIndexes {*} ({s})", .{ decl, decl.name }); |
| 497 | 501 | switch (base.tag) { |
| 498 | .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl), | |
| 499 | .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl), | |
| 500 | .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl) catch |err| switch (err) { | |
| 502 | .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index), | |
| 503 | .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl_index), | |
| 504 | .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl_index) catch |err| switch (err) { | |
| 501 | 505 | // remap this error code because we are transitioning away from |
| 502 | 506 | // `allocateDeclIndexes`. |
| 503 | 507 | error.Overflow => return error.OutOfMemory, |
| 504 | 508 | error.OutOfMemory => return error.OutOfMemory, |
| 505 | 509 | }, |
| 506 | .wasm => return @fieldParentPtr(Wasm, "base", base).allocateDeclIndexes(decl), | |
| 507 | .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl), | |
| 510 | .wasm => return @fieldParentPtr(Wasm, "base", base).allocateDeclIndexes(decl_index), | |
| 511 | .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl_index), | |
| 508 | 512 | .c, .spirv, .nvptx => {}, |
| 509 | 513 | } |
| 510 | 514 | } |
| ... | ... | @@ -621,17 +625,16 @@ pub const File = struct { |
| 621 | 625 | } |
| 622 | 626 | |
| 623 | 627 | /// Called when a Decl is deleted from the Module. |
| 624 | pub fn freeDecl(base: *File, decl: *Module.Decl) void { | |
| 625 | log.debug("freeDecl {*} ({s})", .{ decl, decl.name }); | |
| 628 | pub fn freeDecl(base: *File, decl_index: Module.Decl.Index) void { | |
| 626 | 629 | switch (base.tag) { |
| 627 | .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl), | |
| 628 | .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl), | |
| 629 | .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl), | |
| 630 | .c => @fieldParentPtr(C, "base", base).freeDecl(decl), | |
| 631 | .wasm => @fieldParentPtr(Wasm, "base", base).freeDecl(decl), | |
| 632 | .spirv => @fieldParentPtr(SpirV, "base", base).freeDecl(decl), | |
| 633 | .plan9 => @fieldParentPtr(Plan9, "base", base).freeDecl(decl), | |
| 634 | .nvptx => @fieldParentPtr(NvPtx, "base", base).freeDecl(decl), | |
| 630 | .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl_index), | |
| 631 | .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl_index), | |
| 632 | .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl_index), | |
| 633 | .c => @fieldParentPtr(C, "base", base).freeDecl(decl_index), | |
| 634 | .wasm => @fieldParentPtr(Wasm, "base", base).freeDecl(decl_index), | |
| 635 | .spirv => @fieldParentPtr(SpirV, "base", base).freeDecl(decl_index), | |
| 636 | .plan9 => @fieldParentPtr(Plan9, "base", base).freeDecl(decl_index), | |
| 637 | .nvptx => @fieldParentPtr(NvPtx, "base", base).freeDecl(decl_index), | |
| 635 | 638 | } |
| 636 | 639 | } |
| 637 | 640 | |
| ... | ... | @@ -656,20 +659,21 @@ pub const File = struct { |
| 656 | 659 | pub fn updateDeclExports( |
| 657 | 660 | base: *File, |
| 658 | 661 | module: *Module, |
| 659 | decl: *Module.Decl, | |
| 662 | decl_index: Module.Decl.Index, | |
| 660 | 663 | exports: []const *Module.Export, |
| 661 | 664 | ) UpdateDeclExportsError!void { |
| 665 | const decl = module.declPtr(decl_index); | |
| 662 | 666 | log.debug("updateDeclExports {*} ({s})", .{ decl, decl.name }); |
| 663 | 667 | assert(decl.has_tv); |
| 664 | 668 | switch (base.tag) { |
| 665 | .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl, exports), | |
| 666 | .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports), | |
| 667 | .macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl, exports), | |
| 668 | .c => return @fieldParentPtr(C, "base", base).updateDeclExports(module, decl, exports), | |
| 669 | .wasm => return @fieldParentPtr(Wasm, "base", base).updateDeclExports(module, decl, exports), | |
| 670 | .spirv => return @fieldParentPtr(SpirV, "base", base).updateDeclExports(module, decl, exports), | |
| 671 | .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDeclExports(module, decl, exports), | |
| 672 | .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateDeclExports(module, decl, exports), | |
| 669 | .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl_index, exports), | |
| 670 | .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl_index, exports), | |
| 671 | .macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl_index, exports), | |
| 672 | .c => return @fieldParentPtr(C, "base", base).updateDeclExports(module, decl_index, exports), | |
| 673 | .wasm => return @fieldParentPtr(Wasm, "base", base).updateDeclExports(module, decl_index, exports), | |
| 674 | .spirv => return @fieldParentPtr(SpirV, "base", base).updateDeclExports(module, decl_index, exports), | |
| 675 | .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDeclExports(module, decl_index, exports), | |
| 676 | .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateDeclExports(module, decl_index, exports), | |
| 673 | 677 | } |
| 674 | 678 | } |
| 675 | 679 | |
| ... | ... | @@ -683,14 +687,14 @@ pub const File = struct { |
| 683 | 687 | /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's |
| 684 | 688 | /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the |
| 685 | 689 | /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory. |
| 686 | pub fn getDeclVAddr(base: *File, decl: *const Module.Decl, reloc_info: RelocInfo) !u64 { | |
| 690 | pub fn getDeclVAddr(base: *File, decl_index: Module.Decl.Index, reloc_info: RelocInfo) !u64 { | |
| 687 | 691 | switch (base.tag) { |
| 688 | .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl, reloc_info), | |
| 689 | .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl, reloc_info), | |
| 690 | .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, reloc_info), | |
| 691 | .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, reloc_info), | |
| 692 | .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl_index, reloc_info), | |
| 693 | .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl_index, reloc_info), | |
| 694 | .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl_index, reloc_info), | |
| 695 | .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl_index, reloc_info), | |
| 692 | 696 | .c => unreachable, |
| 693 | .wasm => return @fieldParentPtr(Wasm, "base", base).getDeclVAddr(decl, reloc_info), | |
| 697 | .wasm => return @fieldParentPtr(Wasm, "base", base).getDeclVAddr(decl_index, reloc_info), | |
| 694 | 698 | .spirv => unreachable, |
| 695 | 699 | .nvptx => unreachable, |
| 696 | 700 | } |
src/link/C.zig+36-27| ... | ... | @@ -21,7 +21,7 @@ base: link.File, |
| 21 | 21 | /// This linker backend does not try to incrementally link output C source code. |
| 22 | 22 | /// Instead, it tracks all declarations in this table, and iterates over it |
| 23 | 23 | /// in the flush function, stitching pre-rendered pieces of C code together. |
| 24 | decl_table: std.AutoArrayHashMapUnmanaged(*const Module.Decl, DeclBlock) = .{}, | |
| 24 | decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclBlock) = .{}, | |
| 25 | 25 | /// Stores Type/Value data for `typedefs` to reference. |
| 26 | 26 | /// Accumulates allocations and then there is a periodic garbage collection after flush(). |
| 27 | 27 | arena: std.heap.ArenaAllocator, |
| ... | ... | @@ -87,9 +87,9 @@ pub fn deinit(self: *C) void { |
| 87 | 87 | self.arena.deinit(); |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | pub fn freeDecl(self: *C, decl: *Module.Decl) void { | |
| 90 | pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void { | |
| 91 | 91 | const gpa = self.base.allocator; |
| 92 | if (self.decl_table.fetchSwapRemove(decl)) |kv| { | |
| 92 | if (self.decl_table.fetchSwapRemove(decl_index)) |kv| { | |
| 93 | 93 | var decl_block = kv.value; |
| 94 | 94 | decl_block.deinit(gpa); |
| 95 | 95 | } |
| ... | ... | @@ -99,8 +99,8 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes |
| 99 | 99 | const tracy = trace(@src()); |
| 100 | 100 | defer tracy.end(); |
| 101 | 101 | |
| 102 | const decl = func.owner_decl; | |
| 103 | const gop = try self.decl_table.getOrPut(self.base.allocator, decl); | |
| 102 | const decl_index = func.owner_decl; | |
| 103 | const gop = try self.decl_table.getOrPut(self.base.allocator, decl_index); | |
| 104 | 104 | if (!gop.found_existing) { |
| 105 | 105 | gop.value_ptr.* = .{}; |
| 106 | 106 | } |
| ... | ... | @@ -126,9 +126,10 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes |
| 126 | 126 | .gpa = module.gpa, |
| 127 | 127 | .module = module, |
| 128 | 128 | .error_msg = null, |
| 129 | .decl = decl, | |
| 129 | .decl_index = decl_index, | |
| 130 | .decl = module.declPtr(decl_index), | |
| 130 | 131 | .fwd_decl = fwd_decl.toManaged(module.gpa), |
| 131 | .typedefs = typedefs.promoteContext(module.gpa, .{ .target = module.getTarget() }), | |
| 132 | .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }), | |
| 132 | 133 | .typedefs_arena = self.arena.allocator(), |
| 133 | 134 | }, |
| 134 | 135 | .code = code.toManaged(module.gpa), |
| ... | ... | @@ -150,7 +151,7 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes |
| 150 | 151 | |
| 151 | 152 | codegen.genFunc(&function) catch |err| switch (err) { |
| 152 | 153 | error.AnalysisFail => { |
| 153 | try module.failed_decls.put(module.gpa, decl, function.object.dg.error_msg.?); | |
| 154 | try module.failed_decls.put(module.gpa, decl_index, function.object.dg.error_msg.?); | |
| 154 | 155 | return; |
| 155 | 156 | }, |
| 156 | 157 | else => |e| return e, |
| ... | ... | @@ -166,11 +167,11 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes |
| 166 | 167 | code.shrinkAndFree(module.gpa, code.items.len); |
| 167 | 168 | } |
| 168 | 169 | |
| 169 | pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { | |
| 170 | pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void { | |
| 170 | 171 | const tracy = trace(@src()); |
| 171 | 172 | defer tracy.end(); |
| 172 | 173 | |
| 173 | const gop = try self.decl_table.getOrPut(self.base.allocator, decl); | |
| 174 | const gop = try self.decl_table.getOrPut(self.base.allocator, decl_index); | |
| 174 | 175 | if (!gop.found_existing) { |
| 175 | 176 | gop.value_ptr.* = .{}; |
| 176 | 177 | } |
| ... | ... | @@ -186,14 +187,17 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { |
| 186 | 187 | typedefs.clearRetainingCapacity(); |
| 187 | 188 | code.shrinkRetainingCapacity(0); |
| 188 | 189 | |
| 190 | const decl = module.declPtr(decl_index); | |
| 191 | ||
| 189 | 192 | var object: codegen.Object = .{ |
| 190 | 193 | .dg = .{ |
| 191 | 194 | .gpa = module.gpa, |
| 192 | 195 | .module = module, |
| 193 | 196 | .error_msg = null, |
| 197 | .decl_index = decl_index, | |
| 194 | 198 | .decl = decl, |
| 195 | 199 | .fwd_decl = fwd_decl.toManaged(module.gpa), |
| 196 | .typedefs = typedefs.promoteContext(module.gpa, .{ .target = module.getTarget() }), | |
| 200 | .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }), | |
| 197 | 201 | .typedefs_arena = self.arena.allocator(), |
| 198 | 202 | }, |
| 199 | 203 | .code = code.toManaged(module.gpa), |
| ... | ... | @@ -211,7 +215,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { |
| 211 | 215 | |
| 212 | 216 | codegen.genDecl(&object) catch |err| switch (err) { |
| 213 | 217 | error.AnalysisFail => { |
| 214 | try module.failed_decls.put(module.gpa, decl, object.dg.error_msg.?); | |
| 218 | try module.failed_decls.put(module.gpa, decl_index, object.dg.error_msg.?); | |
| 215 | 219 | return; |
| 216 | 220 | }, |
| 217 | 221 | else => |e| return e, |
| ... | ... | @@ -287,14 +291,14 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) |
| 287 | 291 | |
| 288 | 292 | const decl_keys = self.decl_table.keys(); |
| 289 | 293 | const decl_values = self.decl_table.values(); |
| 290 | for (decl_keys) |decl| { | |
| 291 | assert(decl.has_tv); | |
| 292 | f.remaining_decls.putAssumeCapacityNoClobber(decl, {}); | |
| 294 | for (decl_keys) |decl_index| { | |
| 295 | assert(module.declPtr(decl_index).has_tv); | |
| 296 | f.remaining_decls.putAssumeCapacityNoClobber(decl_index, {}); | |
| 293 | 297 | } |
| 294 | 298 | |
| 295 | 299 | while (f.remaining_decls.popOrNull()) |kv| { |
| 296 | const decl = kv.key; | |
| 297 | try flushDecl(self, &f, decl); | |
| 300 | const decl_index = kv.key; | |
| 301 | try flushDecl(self, &f, decl_index); | |
| 298 | 302 | } |
| 299 | 303 | |
| 300 | 304 | f.all_buffers.items[err_typedef_index] = .{ |
| ... | ... | @@ -305,7 +309,8 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) |
| 305 | 309 | |
| 306 | 310 | // Now the function bodies. |
| 307 | 311 | try f.all_buffers.ensureUnusedCapacity(gpa, f.fn_count); |
| 308 | for (decl_keys) |decl, i| { | |
| 312 | for (decl_keys) |decl_index, i| { | |
| 313 | const decl = module.declPtr(decl_index); | |
| 309 | 314 | if (decl.getFunction() != null) { |
| 310 | 315 | const decl_block = &decl_values[i]; |
| 311 | 316 | const buf = decl_block.code.items; |
| ... | ... | @@ -325,7 +330,7 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) |
| 325 | 330 | } |
| 326 | 331 | |
| 327 | 332 | const Flush = struct { |
| 328 | remaining_decls: std.AutoArrayHashMapUnmanaged(*const Module.Decl, void) = .{}, | |
| 333 | remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{}, | |
| 329 | 334 | typedefs: Typedefs = .{}, |
| 330 | 335 | err_typedef_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 331 | 336 | /// We collect a list of buffers to write, and write them all at once with pwritev 😎 |
| ... | ... | @@ -354,7 +359,9 @@ const FlushDeclError = error{ |
| 354 | 359 | }; |
| 355 | 360 | |
| 356 | 361 | /// Assumes `decl` was in the `remaining_decls` set, and has already been removed. |
| 357 | fn flushDecl(self: *C, f: *Flush, decl: *const Module.Decl) FlushDeclError!void { | |
| 362 | fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!void { | |
| 363 | const module = self.base.options.module.?; | |
| 364 | const decl = module.declPtr(decl_index); | |
| 358 | 365 | // Before flushing any particular Decl we must ensure its |
| 359 | 366 | // dependencies are already flushed, so that the order in the .c |
| 360 | 367 | // file comes out correctly. |
| ... | ... | @@ -364,15 +371,17 @@ fn flushDecl(self: *C, f: *Flush, decl: *const Module.Decl) FlushDeclError!void |
| 364 | 371 | } |
| 365 | 372 | } |
| 366 | 373 | |
| 367 | const decl_block = self.decl_table.getPtr(decl).?; | |
| 374 | const decl_block = self.decl_table.getPtr(decl_index).?; | |
| 368 | 375 | const gpa = self.base.allocator; |
| 369 | 376 | |
| 370 | 377 | if (decl_block.typedefs.count() != 0) { |
| 371 | try f.typedefs.ensureUnusedCapacity(gpa, @intCast(u32, decl_block.typedefs.count())); | |
| 378 | try f.typedefs.ensureUnusedCapacityContext(gpa, @intCast(u32, decl_block.typedefs.count()), .{ | |
| 379 | .mod = module, | |
| 380 | }); | |
| 372 | 381 | var it = decl_block.typedefs.iterator(); |
| 373 | 382 | while (it.next()) |new| { |
| 374 | 383 | const gop = f.typedefs.getOrPutAssumeCapacityContext(new.key_ptr.*, .{ |
| 375 | .target = self.base.options.target, | |
| 384 | .mod = module, | |
| 376 | 385 | }); |
| 377 | 386 | if (!gop.found_existing) { |
| 378 | 387 | try f.err_typedef_buf.appendSlice(gpa, new.value_ptr.rendered); |
| ... | ... | @@ -417,8 +426,8 @@ pub fn flushEmitH(module: *Module) !void { |
| 417 | 426 | .iov_len = zig_h.len, |
| 418 | 427 | }); |
| 419 | 428 | |
| 420 | for (emit_h.decl_table.keys()) |decl| { | |
| 421 | const decl_emit_h = decl.getEmitH(module); | |
| 429 | for (emit_h.decl_table.keys()) |decl_index| { | |
| 430 | const decl_emit_h = emit_h.declPtr(decl_index); | |
| 422 | 431 | const buf = decl_emit_h.fwd_decl.items; |
| 423 | 432 | all_buffers.appendAssumeCapacity(.{ |
| 424 | 433 | .iov_base = buf.ptr, |
| ... | ... | @@ -442,11 +451,11 @@ pub fn flushEmitH(module: *Module) !void { |
| 442 | 451 | pub fn updateDeclExports( |
| 443 | 452 | self: *C, |
| 444 | 453 | module: *Module, |
| 445 | decl: *Module.Decl, | |
| 454 | decl_index: Module.Decl.Index, | |
| 446 | 455 | exports: []const *Module.Export, |
| 447 | 456 | ) !void { |
| 448 | 457 | _ = exports; |
| 449 | _ = decl; | |
| 458 | _ = decl_index; | |
| 450 | 459 | _ = module; |
| 451 | 460 | _ = self; |
| 452 | 461 | } |
src/link/Coff.zig+32-17| ... | ... | @@ -418,11 +418,12 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { |
| 418 | 418 | return self; |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void { | |
| 421 | pub fn allocateDeclIndexes(self: *Coff, decl_index: Module.Decl.Index) !void { | |
| 422 | 422 | if (self.llvm_object) |_| return; |
| 423 | 423 | |
| 424 | 424 | try self.offset_table.ensureUnusedCapacity(self.base.allocator, 1); |
| 425 | 425 | |
| 426 | const decl = self.base.options.module.?.declPtr(decl_index); | |
| 426 | 427 | if (self.offset_table_free_list.popOrNull()) |i| { |
| 427 | 428 | decl.link.coff.offset_table_index = i; |
| 428 | 429 | } else { |
| ... | ... | @@ -674,7 +675,8 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live |
| 674 | 675 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 675 | 676 | defer code_buffer.deinit(); |
| 676 | 677 | |
| 677 | const decl = func.owner_decl; | |
| 678 | const decl_index = func.owner_decl; | |
| 679 | const decl = module.declPtr(decl_index); | |
| 678 | 680 | const res = try codegen.generateFunction( |
| 679 | 681 | &self.base, |
| 680 | 682 | decl.srcLoc(), |
| ... | ... | @@ -688,7 +690,7 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live |
| 688 | 690 | .appended => code_buffer.items, |
| 689 | 691 | .fail => |em| { |
| 690 | 692 | decl.analysis = .codegen_failure; |
| 691 | try module.failed_decls.put(module.gpa, decl, em); | |
| 693 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 692 | 694 | return; |
| 693 | 695 | }, |
| 694 | 696 | }; |
| ... | ... | @@ -696,24 +698,26 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live |
| 696 | 698 | return self.finishUpdateDecl(module, func.owner_decl, code); |
| 697 | 699 | } |
| 698 | 700 | |
| 699 | pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl: *Module.Decl) !u32 { | |
| 701 | pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { | |
| 700 | 702 | _ = self; |
| 701 | 703 | _ = tv; |
| 702 | _ = decl; | |
| 704 | _ = decl_index; | |
| 703 | 705 | log.debug("TODO lowerUnnamedConst for Coff", .{}); |
| 704 | 706 | return error.AnalysisFail; |
| 705 | 707 | } |
| 706 | 708 | |
| 707 | pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { | |
| 709 | pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !void { | |
| 708 | 710 | if (build_options.skip_non_native and builtin.object_format != .coff) { |
| 709 | 711 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 710 | 712 | } |
| 711 | 713 | if (build_options.have_llvm) { |
| 712 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl); | |
| 714 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl_index); | |
| 713 | 715 | } |
| 714 | 716 | const tracy = trace(@src()); |
| 715 | 717 | defer tracy.end(); |
| 716 | 718 | |
| 719 | const decl = module.declPtr(decl_index); | |
| 720 | ||
| 717 | 721 | if (decl.val.tag() == .extern_fn) { |
| 718 | 722 | return; // TODO Should we do more when front-end analyzed extern decl? |
| 719 | 723 | } |
| ... | ... | @@ -735,15 +739,16 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { |
| 735 | 739 | .appended => code_buffer.items, |
| 736 | 740 | .fail => |em| { |
| 737 | 741 | decl.analysis = .codegen_failure; |
| 738 | try module.failed_decls.put(module.gpa, decl, em); | |
| 742 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 739 | 743 | return; |
| 740 | 744 | }, |
| 741 | 745 | }; |
| 742 | 746 | |
| 743 | return self.finishUpdateDecl(module, decl, code); | |
| 747 | return self.finishUpdateDecl(module, decl_index, code); | |
| 744 | 748 | } |
| 745 | 749 | |
| 746 | fn finishUpdateDecl(self: *Coff, module: *Module, decl: *Module.Decl, code: []const u8) !void { | |
| 750 | fn finishUpdateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index, code: []const u8) !void { | |
| 751 | const decl = module.declPtr(decl_index); | |
| 747 | 752 | const required_alignment = decl.ty.abiAlignment(self.base.options.target); |
| 748 | 753 | const curr_size = decl.link.coff.size; |
| 749 | 754 | if (curr_size != 0) { |
| ... | ... | @@ -778,15 +783,18 @@ fn finishUpdateDecl(self: *Coff, module: *Module, decl: *Module.Decl, code: []co |
| 778 | 783 | try self.base.file.?.pwriteAll(code, self.section_data_offset + self.offset_table_size + decl.link.coff.text_offset); |
| 779 | 784 | |
| 780 | 785 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. |
| 781 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | |
| 782 | return self.updateDeclExports(module, decl, decl_exports); | |
| 786 | const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{}; | |
| 787 | return self.updateDeclExports(module, decl_index, decl_exports); | |
| 783 | 788 | } |
| 784 | 789 | |
| 785 | pub fn freeDecl(self: *Coff, decl: *Module.Decl) void { | |
| 790 | pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { | |
| 786 | 791 | if (build_options.have_llvm) { |
| 787 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl); | |
| 792 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | |
| 788 | 793 | } |
| 789 | 794 | |
| 795 | const mod = self.base.options.module.?; | |
| 796 | const decl = mod.declPtr(decl_index); | |
| 797 | ||
| 790 | 798 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 791 | 799 | self.freeTextBlock(&decl.link.coff); |
| 792 | 800 | self.offset_table_free_list.append(self.base.allocator, decl.link.coff.offset_table_index) catch {}; |
| ... | ... | @@ -795,16 +803,17 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void { |
| 795 | 803 | pub fn updateDeclExports( |
| 796 | 804 | self: *Coff, |
| 797 | 805 | module: *Module, |
| 798 | decl: *Module.Decl, | |
| 806 | decl_index: Module.Decl.Index, | |
| 799 | 807 | exports: []const *Module.Export, |
| 800 | 808 | ) !void { |
| 801 | 809 | if (build_options.skip_non_native and builtin.object_format != .coff) { |
| 802 | 810 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 803 | 811 | } |
| 804 | 812 | if (build_options.have_llvm) { |
| 805 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports); | |
| 813 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports); | |
| 806 | 814 | } |
| 807 | 815 | |
| 816 | const decl = module.declPtr(decl_index); | |
| 808 | 817 | for (exports) |exp| { |
| 809 | 818 | if (exp.options.section) |section_name| { |
| 810 | 819 | if (!mem.eql(u8, section_name, ".text")) { |
| ... | ... | @@ -1474,8 +1483,14 @@ fn findLib(self: *Coff, arena: Allocator, name: []const u8) !?[]const u8 { |
| 1474 | 1483 | return null; |
| 1475 | 1484 | } |
| 1476 | 1485 | |
| 1477 | pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl, reloc_info: link.File.RelocInfo) !u64 { | |
| 1486 | pub fn getDeclVAddr( | |
| 1487 | self: *Coff, | |
| 1488 | decl_index: Module.Decl.Index, | |
| 1489 | reloc_info: link.File.RelocInfo, | |
| 1490 | ) !u64 { | |
| 1478 | 1491 | _ = reloc_info; |
| 1492 | const mod = self.base.options.module.?; | |
| 1493 | const decl = mod.declPtr(decl_index); | |
| 1479 | 1494 | assert(self.llvm_object == null); |
| 1480 | 1495 | return self.text_section_virtual_address + decl.link.coff.text_offset; |
| 1481 | 1496 | } |
src/link/Dwarf.zig+23-23| ... | ... | @@ -67,7 +67,7 @@ pub const Atom = struct { |
| 67 | 67 | /// Decl's inner Atom is assigned an offset within the DWARF section. |
| 68 | 68 | pub const DeclState = struct { |
| 69 | 69 | gpa: Allocator, |
| 70 | target: std.Target, | |
| 70 | mod: *Module, | |
| 71 | 71 | dbg_line: std.ArrayList(u8), |
| 72 | 72 | dbg_info: std.ArrayList(u8), |
| 73 | 73 | abbrev_type_arena: std.heap.ArenaAllocator, |
| ... | ... | @@ -81,10 +81,10 @@ pub const DeclState = struct { |
| 81 | 81 | abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{}, |
| 82 | 82 | exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation) = .{}, |
| 83 | 83 | |
| 84 | fn init(gpa: Allocator, target: std.Target) DeclState { | |
| 84 | fn init(gpa: Allocator, mod: *Module) DeclState { | |
| 85 | 85 | return .{ |
| 86 | 86 | .gpa = gpa, |
| 87 | .target = target, | |
| 87 | .mod = mod, | |
| 88 | 88 | .dbg_line = std.ArrayList(u8).init(gpa), |
| 89 | 89 | .dbg_info = std.ArrayList(u8).init(gpa), |
| 90 | 90 | .abbrev_type_arena = std.heap.ArenaAllocator.init(gpa), |
| ... | ... | @@ -118,7 +118,7 @@ pub const DeclState = struct { |
| 118 | 118 | addend: ?u32, |
| 119 | 119 | ) !void { |
| 120 | 120 | const resolv = self.abbrev_resolver.getContext(ty, .{ |
| 121 | .target = self.target, | |
| 121 | .mod = self.mod, | |
| 122 | 122 | }) orelse blk: { |
| 123 | 123 | const sym_index = @intCast(u32, self.abbrev_table.items.len); |
| 124 | 124 | try self.abbrev_table.append(self.gpa, .{ |
| ... | ... | @@ -128,10 +128,10 @@ pub const DeclState = struct { |
| 128 | 128 | }); |
| 129 | 129 | log.debug("@{d}: {}", .{ sym_index, ty.fmtDebug() }); |
| 130 | 130 | try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{ |
| 131 | .target = self.target, | |
| 131 | .mod = self.mod, | |
| 132 | 132 | }); |
| 133 | 133 | break :blk self.abbrev_resolver.getContext(ty, .{ |
| 134 | .target = self.target, | |
| 134 | .mod = self.mod, | |
| 135 | 135 | }).?; |
| 136 | 136 | }; |
| 137 | 137 | const add: u32 = addend orelse 0; |
| ... | ... | @@ -153,8 +153,8 @@ pub const DeclState = struct { |
| 153 | 153 | ) error{OutOfMemory}!void { |
| 154 | 154 | const arena = self.abbrev_type_arena.allocator(); |
| 155 | 155 | const dbg_info_buffer = &self.dbg_info; |
| 156 | const target = self.target; | |
| 157 | const target_endian = self.target.cpu.arch.endian(); | |
| 156 | const target = module.getTarget(); | |
| 157 | const target_endian = target.cpu.arch.endian(); | |
| 158 | 158 | |
| 159 | 159 | switch (ty.zigTypeTag()) { |
| 160 | 160 | .NoReturn => unreachable, |
| ... | ... | @@ -181,7 +181,7 @@ pub const DeclState = struct { |
| 181 | 181 | // DW.AT.byte_size, DW.FORM.data1 |
| 182 | 182 | dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target))); |
| 183 | 183 | // DW.AT.name, DW.FORM.string |
| 184 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); | |
| 184 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | |
| 185 | 185 | }, |
| 186 | 186 | .Optional => { |
| 187 | 187 | if (ty.isPtrLikeOptional()) { |
| ... | ... | @@ -192,7 +192,7 @@ pub const DeclState = struct { |
| 192 | 192 | // DW.AT.byte_size, DW.FORM.data1 |
| 193 | 193 | dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target))); |
| 194 | 194 | // DW.AT.name, DW.FORM.string |
| 195 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); | |
| 195 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | |
| 196 | 196 | } else { |
| 197 | 197 | // Non-pointer optionals are structs: struct { .maybe = *, .val = * } |
| 198 | 198 | var buf = try arena.create(Type.Payload.ElemType); |
| ... | ... | @@ -203,7 +203,7 @@ pub const DeclState = struct { |
| 203 | 203 | const abi_size = ty.abiSize(target); |
| 204 | 204 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 205 | 205 | // DW.AT.name, DW.FORM.string |
| 206 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); | |
| 206 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | |
| 207 | 207 | // DW.AT.member |
| 208 | 208 | try dbg_info_buffer.ensureUnusedCapacity(7); |
| 209 | 209 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member)); |
| ... | ... | @@ -242,7 +242,7 @@ pub const DeclState = struct { |
| 242 | 242 | // DW.AT.byte_size, DW.FORM.sdata |
| 243 | 243 | dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize) * 2); |
| 244 | 244 | // DW.AT.name, DW.FORM.string |
| 245 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); | |
| 245 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | |
| 246 | 246 | // DW.AT.member |
| 247 | 247 | try dbg_info_buffer.ensureUnusedCapacity(5); |
| 248 | 248 | dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member)); |
| ... | ... | @@ -285,7 +285,7 @@ pub const DeclState = struct { |
| 285 | 285 | // DW.AT.array_type |
| 286 | 286 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_type)); |
| 287 | 287 | // DW.AT.name, DW.FORM.string |
| 288 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); | |
| 288 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | |
| 289 | 289 | // DW.AT.type, DW.FORM.ref4 |
| 290 | 290 | var index = dbg_info_buffer.items.len; |
| 291 | 291 | try dbg_info_buffer.resize(index + 4); |
| ... | ... | @@ -312,7 +312,7 @@ pub const DeclState = struct { |
| 312 | 312 | switch (ty.tag()) { |
| 313 | 313 | .tuple, .anon_struct => { |
| 314 | 314 | // DW.AT.name, DW.FORM.string |
| 315 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); | |
| 315 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)}); | |
| 316 | 316 | |
| 317 | 317 | const fields = ty.tupleFields(); |
| 318 | 318 | for (fields.types) |field, field_index| { |
| ... | ... | @@ -331,7 +331,7 @@ pub const DeclState = struct { |
| 331 | 331 | }, |
| 332 | 332 | else => { |
| 333 | 333 | // DW.AT.name, DW.FORM.string |
| 334 | const struct_name = try ty.nameAllocArena(arena, target); | |
| 334 | const struct_name = try ty.nameAllocArena(arena, module); | |
| 335 | 335 | try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); |
| 336 | 336 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); |
| 337 | 337 | dbg_info_buffer.appendAssumeCapacity(0); |
| ... | ... | @@ -372,7 +372,7 @@ pub const DeclState = struct { |
| 372 | 372 | const abi_size = ty.abiSize(target); |
| 373 | 373 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 374 | 374 | // DW.AT.name, DW.FORM.string |
| 375 | const enum_name = try ty.nameAllocArena(arena, target); | |
| 375 | const enum_name = try ty.nameAllocArena(arena, module); | |
| 376 | 376 | try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1); |
| 377 | 377 | dbg_info_buffer.appendSliceAssumeCapacity(enum_name); |
| 378 | 378 | dbg_info_buffer.appendAssumeCapacity(0); |
| ... | ... | @@ -410,7 +410,7 @@ pub const DeclState = struct { |
| 410 | 410 | const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0; |
| 411 | 411 | const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size; |
| 412 | 412 | const is_tagged = layout.tag_size > 0; |
| 413 | const union_name = try ty.nameAllocArena(arena, target); | |
| 413 | const union_name = try ty.nameAllocArena(arena, module); | |
| 414 | 414 | |
| 415 | 415 | // TODO this is temporary to match current state of unions in Zig - we don't yet have |
| 416 | 416 | // safety checks implemented meaning the implicit tag is not yet stored and generated |
| ... | ... | @@ -491,7 +491,7 @@ pub const DeclState = struct { |
| 491 | 491 | self.abbrev_type_arena.allocator(), |
| 492 | 492 | module, |
| 493 | 493 | ty, |
| 494 | self.target, | |
| 494 | target, | |
| 495 | 495 | &self.dbg_info, |
| 496 | 496 | ); |
| 497 | 497 | }, |
| ... | ... | @@ -507,7 +507,7 @@ pub const DeclState = struct { |
| 507 | 507 | // DW.AT.byte_size, DW.FORM.sdata |
| 508 | 508 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 509 | 509 | // DW.AT.name, DW.FORM.string |
| 510 | const name = try ty.nameAllocArena(arena, target); | |
| 510 | const name = try ty.nameAllocArena(arena, module); | |
| 511 | 511 | try dbg_info_buffer.writer().print("{s}\x00", .{name}); |
| 512 | 512 | |
| 513 | 513 | // DW.AT.member |
| ... | ... | @@ -654,17 +654,17 @@ pub fn deinit(self: *Dwarf) void { |
| 654 | 654 | |
| 655 | 655 | /// Initializes Decl's state and its matching output buffers. |
| 656 | 656 | /// Call this before `commitDeclState`. |
| 657 | pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !DeclState { | |
| 657 | pub fn initDeclState(self: *Dwarf, mod: *Module, decl: *Module.Decl) !DeclState { | |
| 658 | 658 | const tracy = trace(@src()); |
| 659 | 659 | defer tracy.end(); |
| 660 | 660 | |
| 661 | const decl_name = try decl.getFullyQualifiedName(self.allocator); | |
| 661 | const decl_name = try decl.getFullyQualifiedName(mod); | |
| 662 | 662 | defer self.allocator.free(decl_name); |
| 663 | 663 | |
| 664 | 664 | log.debug("initDeclState {s}{*}", .{ decl_name, decl }); |
| 665 | 665 | |
| 666 | 666 | const gpa = self.allocator; |
| 667 | var decl_state = DeclState.init(gpa, self.target); | |
| 667 | var decl_state = DeclState.init(gpa, mod); | |
| 668 | 668 | errdefer decl_state.deinit(); |
| 669 | 669 | const dbg_line_buffer = &decl_state.dbg_line; |
| 670 | 670 | const dbg_info_buffer = &decl_state.dbg_info; |
| ... | ... | @@ -2133,7 +2133,7 @@ fn addDbgInfoErrorSet( |
| 2133 | 2133 | const abi_size = ty.abiSize(target); |
| 2134 | 2134 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 2135 | 2135 | // DW.AT.name, DW.FORM.string |
| 2136 | const name = try ty.nameAllocArena(arena, target); | |
| 2136 | const name = try ty.nameAllocArena(arena, module); | |
| 2137 | 2137 | try dbg_info_buffer.writer().print("{s}\x00", .{name}); |
| 2138 | 2138 | |
| 2139 | 2139 | // DW.AT.enumerator |
src/link/Elf.zig+57-41| ... | ... | @@ -134,7 +134,7 @@ atom_free_lists: std.AutoHashMapUnmanaged(u16, std.ArrayListUnmanaged(*TextBlock |
| 134 | 134 | /// We store them here so that we can properly dispose of any allocated |
| 135 | 135 | /// memory within the atom in the incremental linker. |
| 136 | 136 | /// TODO consolidate this. |
| 137 | decls: std.AutoHashMapUnmanaged(*Module.Decl, ?u16) = .{}, | |
| 137 | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, ?u16) = .{}, | |
| 138 | 138 | |
| 139 | 139 | /// List of atoms that are owned directly by the linker. |
| 140 | 140 | /// Currently these are only atoms that are the result of linking |
| ... | ... | @@ -178,7 +178,7 @@ const Reloc = struct { |
| 178 | 178 | }; |
| 179 | 179 | |
| 180 | 180 | const RelocTable = std.AutoHashMapUnmanaged(*TextBlock, std.ArrayListUnmanaged(Reloc)); |
| 181 | const UnnamedConstTable = std.AutoHashMapUnmanaged(*Module.Decl, std.ArrayListUnmanaged(*TextBlock)); | |
| 181 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*TextBlock)); | |
| 182 | 182 | |
| 183 | 183 | /// When allocating, the ideal_capacity is calculated by |
| 184 | 184 | /// actual_capacity + (actual_capacity / ideal_factor) |
| ... | ... | @@ -389,7 +389,10 @@ pub fn deinit(self: *Elf) void { |
| 389 | 389 | } |
| 390 | 390 | } |
| 391 | 391 | |
| 392 | pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl, reloc_info: File.RelocInfo) !u64 { | |
| 392 | pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: File.RelocInfo) !u64 { | |
| 393 | const mod = self.base.options.module.?; | |
| 394 | const decl = mod.declPtr(decl_index); | |
| 395 | ||
| 393 | 396 | assert(self.llvm_object == null); |
| 394 | 397 | assert(decl.link.elf.local_sym_index != 0); |
| 395 | 398 | |
| ... | ... | @@ -2189,15 +2192,17 @@ fn allocateLocalSymbol(self: *Elf) !u32 { |
| 2189 | 2192 | return index; |
| 2190 | 2193 | } |
| 2191 | 2194 | |
| 2192 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | |
| 2195 | pub fn allocateDeclIndexes(self: *Elf, decl_index: Module.Decl.Index) !void { | |
| 2193 | 2196 | if (self.llvm_object) |_| return; |
| 2194 | 2197 | |
| 2198 | const mod = self.base.options.module.?; | |
| 2199 | const decl = mod.declPtr(decl_index); | |
| 2195 | 2200 | if (decl.link.elf.local_sym_index != 0) return; |
| 2196 | 2201 | |
| 2197 | 2202 | try self.offset_table.ensureUnusedCapacity(self.base.allocator, 1); |
| 2198 | try self.decls.putNoClobber(self.base.allocator, decl, null); | |
| 2203 | try self.decls.putNoClobber(self.base.allocator, decl_index, null); | |
| 2199 | 2204 | |
| 2200 | const decl_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 2205 | const decl_name = try decl.getFullyQualifiedName(mod); | |
| 2201 | 2206 | defer self.base.allocator.free(decl_name); |
| 2202 | 2207 | |
| 2203 | 2208 | log.debug("allocating symbol indexes for {s}", .{decl_name}); |
| ... | ... | @@ -2214,8 +2219,8 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2214 | 2219 | self.offset_table.items[decl.link.elf.offset_table_index] = 0; |
| 2215 | 2220 | } |
| 2216 | 2221 | |
| 2217 | fn freeUnnamedConsts(self: *Elf, decl: *Module.Decl) void { | |
| 2218 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl) orelse return; | |
| 2222 | fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void { | |
| 2223 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; | |
| 2219 | 2224 | for (unnamed_consts.items) |atom| { |
| 2220 | 2225 | self.freeTextBlock(atom, self.phdr_load_ro_index.?); |
| 2221 | 2226 | self.local_symbol_free_list.append(self.base.allocator, atom.local_sym_index) catch {}; |
| ... | ... | @@ -2225,15 +2230,18 @@ fn freeUnnamedConsts(self: *Elf, decl: *Module.Decl) void { |
| 2225 | 2230 | unnamed_consts.clearAndFree(self.base.allocator); |
| 2226 | 2231 | } |
| 2227 | 2232 | |
| 2228 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { | |
| 2233 | pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { | |
| 2229 | 2234 | if (build_options.have_llvm) { |
| 2230 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl); | |
| 2235 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | |
| 2231 | 2236 | } |
| 2232 | 2237 | |
| 2233 | const kv = self.decls.fetchRemove(decl); | |
| 2238 | const mod = self.base.options.module.?; | |
| 2239 | const decl = mod.declPtr(decl_index); | |
| 2240 | ||
| 2241 | const kv = self.decls.fetchRemove(decl_index); | |
| 2234 | 2242 | if (kv.?.value) |index| { |
| 2235 | 2243 | self.freeTextBlock(&decl.link.elf, index); |
| 2236 | self.freeUnnamedConsts(decl); | |
| 2244 | self.freeUnnamedConsts(decl_index); | |
| 2237 | 2245 | } |
| 2238 | 2246 | |
| 2239 | 2247 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| ... | ... | @@ -2274,14 +2282,17 @@ fn getDeclPhdrIndex(self: *Elf, decl: *Module.Decl) !u16 { |
| 2274 | 2282 | return phdr_index; |
| 2275 | 2283 | } |
| 2276 | 2284 | |
| 2277 | fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8) !*elf.Elf64_Sym { | |
| 2278 | const decl_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 2285 | fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, stt_bits: u8) !*elf.Elf64_Sym { | |
| 2286 | const mod = self.base.options.module.?; | |
| 2287 | const decl = mod.declPtr(decl_index); | |
| 2288 | ||
| 2289 | const decl_name = try decl.getFullyQualifiedName(mod); | |
| 2279 | 2290 | defer self.base.allocator.free(decl_name); |
| 2280 | 2291 | |
| 2281 | 2292 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); |
| 2282 | 2293 | const required_alignment = decl.ty.abiAlignment(self.base.options.target); |
| 2283 | 2294 | |
| 2284 | const decl_ptr = self.decls.getPtr(decl).?; | |
| 2295 | const decl_ptr = self.decls.getPtr(decl_index).?; | |
| 2285 | 2296 | if (decl_ptr.* == null) { |
| 2286 | 2297 | decl_ptr.* = try self.getDeclPhdrIndex(decl); |
| 2287 | 2298 | } |
| ... | ... | @@ -2355,10 +2366,11 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2355 | 2366 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2356 | 2367 | defer code_buffer.deinit(); |
| 2357 | 2368 | |
| 2358 | const decl = func.owner_decl; | |
| 2359 | self.freeUnnamedConsts(decl); | |
| 2369 | const decl_index = func.owner_decl; | |
| 2370 | const decl = module.declPtr(decl_index); | |
| 2371 | self.freeUnnamedConsts(decl_index); | |
| 2360 | 2372 | |
| 2361 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(decl) else null; | |
| 2373 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(module, decl) else null; | |
| 2362 | 2374 | defer if (decl_state) |*ds| ds.deinit(); |
| 2363 | 2375 | |
| 2364 | 2376 | const res = if (decl_state) |*ds| |
| ... | ... | @@ -2372,11 +2384,11 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2372 | 2384 | .appended => code_buffer.items, |
| 2373 | 2385 | .fail => |em| { |
| 2374 | 2386 | decl.analysis = .codegen_failure; |
| 2375 | try module.failed_decls.put(module.gpa, decl, em); | |
| 2387 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 2376 | 2388 | return; |
| 2377 | 2389 | }, |
| 2378 | 2390 | }; |
| 2379 | const local_sym = try self.updateDeclCode(decl, code, elf.STT_FUNC); | |
| 2391 | const local_sym = try self.updateDeclCode(decl_index, code, elf.STT_FUNC); | |
| 2380 | 2392 | if (decl_state) |*ds| { |
| 2381 | 2393 | try self.dwarf.?.commitDeclState( |
| 2382 | 2394 | &self.base, |
| ... | ... | @@ -2389,21 +2401,23 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2389 | 2401 | } |
| 2390 | 2402 | |
| 2391 | 2403 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. |
| 2392 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | |
| 2393 | return self.updateDeclExports(module, decl, decl_exports); | |
| 2404 | const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{}; | |
| 2405 | return self.updateDeclExports(module, decl_index, decl_exports); | |
| 2394 | 2406 | } |
| 2395 | 2407 | |
| 2396 | pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { | |
| 2408 | pub fn updateDecl(self: *Elf, module: *Module, decl_index: Module.Decl.Index) !void { | |
| 2397 | 2409 | if (build_options.skip_non_native and builtin.object_format != .elf) { |
| 2398 | 2410 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 2399 | 2411 | } |
| 2400 | 2412 | if (build_options.have_llvm) { |
| 2401 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl); | |
| 2413 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl_index); | |
| 2402 | 2414 | } |
| 2403 | 2415 | |
| 2404 | 2416 | const tracy = trace(@src()); |
| 2405 | 2417 | defer tracy.end(); |
| 2406 | 2418 | |
| 2419 | const decl = module.declPtr(decl_index); | |
| 2420 | ||
| 2407 | 2421 | if (decl.val.tag() == .extern_fn) { |
| 2408 | 2422 | return; // TODO Should we do more when front-end analyzed extern decl? |
| 2409 | 2423 | } |
| ... | ... | @@ -2414,12 +2428,12 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2414 | 2428 | } |
| 2415 | 2429 | } |
| 2416 | 2430 | |
| 2417 | assert(!self.unnamed_const_atoms.contains(decl)); | |
| 2431 | assert(!self.unnamed_const_atoms.contains(decl_index)); | |
| 2418 | 2432 | |
| 2419 | 2433 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2420 | 2434 | defer code_buffer.deinit(); |
| 2421 | 2435 | |
| 2422 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(decl) else null; | |
| 2436 | var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(module, decl) else null; | |
| 2423 | 2437 | defer if (decl_state) |*ds| ds.deinit(); |
| 2424 | 2438 | |
| 2425 | 2439 | // TODO implement .debug_info for global variables |
| ... | ... | @@ -2446,12 +2460,12 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2446 | 2460 | .appended => code_buffer.items, |
| 2447 | 2461 | .fail => |em| { |
| 2448 | 2462 | decl.analysis = .codegen_failure; |
| 2449 | try module.failed_decls.put(module.gpa, decl, em); | |
| 2463 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 2450 | 2464 | return; |
| 2451 | 2465 | }, |
| 2452 | 2466 | }; |
| 2453 | 2467 | |
| 2454 | const local_sym = try self.updateDeclCode(decl, code, elf.STT_OBJECT); | |
| 2468 | const local_sym = try self.updateDeclCode(decl_index, code, elf.STT_OBJECT); | |
| 2455 | 2469 | if (decl_state) |*ds| { |
| 2456 | 2470 | try self.dwarf.?.commitDeclState( |
| 2457 | 2471 | &self.base, |
| ... | ... | @@ -2464,16 +2478,18 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2464 | 2478 | } |
| 2465 | 2479 | |
| 2466 | 2480 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. |
| 2467 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | |
| 2468 | return self.updateDeclExports(module, decl, decl_exports); | |
| 2481 | const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{}; | |
| 2482 | return self.updateDeclExports(module, decl_index, decl_exports); | |
| 2469 | 2483 | } |
| 2470 | 2484 | |
| 2471 | pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl) !u32 { | |
| 2485 | pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 { | |
| 2472 | 2486 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2473 | 2487 | defer code_buffer.deinit(); |
| 2474 | 2488 | |
| 2475 | const module = self.base.options.module.?; | |
| 2476 | const gop = try self.unnamed_const_atoms.getOrPut(self.base.allocator, decl); | |
| 2489 | const mod = self.base.options.module.?; | |
| 2490 | const decl = mod.declPtr(decl_index); | |
| 2491 | ||
| 2492 | const gop = try self.unnamed_const_atoms.getOrPut(self.base.allocator, decl_index); | |
| 2477 | 2493 | if (!gop.found_existing) { |
| 2478 | 2494 | gop.value_ptr.* = .{}; |
| 2479 | 2495 | } |
| ... | ... | @@ -2485,7 +2501,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl |
| 2485 | 2501 | try self.managed_atoms.append(self.base.allocator, atom); |
| 2486 | 2502 | |
| 2487 | 2503 | const name_str_index = blk: { |
| 2488 | const decl_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 2504 | const decl_name = try decl.getFullyQualifiedName(mod); | |
| 2489 | 2505 | defer self.base.allocator.free(decl_name); |
| 2490 | 2506 | |
| 2491 | 2507 | const index = unnamed_consts.items.len; |
| ... | ... | @@ -2510,7 +2526,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl |
| 2510 | 2526 | .appended => code_buffer.items, |
| 2511 | 2527 | .fail => |em| { |
| 2512 | 2528 | decl.analysis = .codegen_failure; |
| 2513 | try module.failed_decls.put(module.gpa, decl, em); | |
| 2529 | try mod.failed_decls.put(mod.gpa, decl_index, em); | |
| 2514 | 2530 | log.err("{s}", .{em.msg}); |
| 2515 | 2531 | return error.AnalysisFail; |
| 2516 | 2532 | }, |
| ... | ... | @@ -2547,24 +2563,25 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl |
| 2547 | 2563 | pub fn updateDeclExports( |
| 2548 | 2564 | self: *Elf, |
| 2549 | 2565 | module: *Module, |
| 2550 | decl: *Module.Decl, | |
| 2566 | decl_index: Module.Decl.Index, | |
| 2551 | 2567 | exports: []const *Module.Export, |
| 2552 | 2568 | ) !void { |
| 2553 | 2569 | if (build_options.skip_non_native and builtin.object_format != .elf) { |
| 2554 | 2570 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 2555 | 2571 | } |
| 2556 | 2572 | if (build_options.have_llvm) { |
| 2557 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports); | |
| 2573 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports); | |
| 2558 | 2574 | } |
| 2559 | 2575 | |
| 2560 | 2576 | const tracy = trace(@src()); |
| 2561 | 2577 | defer tracy.end(); |
| 2562 | 2578 | |
| 2563 | 2579 | try self.global_symbols.ensureUnusedCapacity(self.base.allocator, exports.len); |
| 2580 | const decl = module.declPtr(decl_index); | |
| 2564 | 2581 | if (decl.link.elf.local_sym_index == 0) return; |
| 2565 | 2582 | const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index]; |
| 2566 | 2583 | |
| 2567 | const decl_ptr = self.decls.getPtr(decl).?; | |
| 2584 | const decl_ptr = self.decls.getPtr(decl_index).?; | |
| 2568 | 2585 | if (decl_ptr.* == null) { |
| 2569 | 2586 | decl_ptr.* = try self.getDeclPhdrIndex(decl); |
| 2570 | 2587 | } |
| ... | ... | @@ -2633,12 +2650,11 @@ pub fn updateDeclExports( |
| 2633 | 2650 | } |
| 2634 | 2651 | |
| 2635 | 2652 | /// Must be called only after a successful call to `updateDecl`. |
| 2636 | pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Decl) !void { | |
| 2637 | _ = module; | |
| 2653 | pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl: *const Module.Decl) !void { | |
| 2638 | 2654 | const tracy = trace(@src()); |
| 2639 | 2655 | defer tracy.end(); |
| 2640 | 2656 | |
| 2641 | const decl_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 2657 | const decl_name = try decl.getFullyQualifiedName(mod); | |
| 2642 | 2658 | defer self.base.allocator.free(decl_name); |
| 2643 | 2659 | |
| 2644 | 2660 | log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl }); |
src/link/MachO.zig+65-47| ... | ... | @@ -247,14 +247,14 @@ unnamed_const_atoms: UnnamedConstTable = .{}, |
| 247 | 247 | /// We store them here so that we can properly dispose of any allocated |
| 248 | 248 | /// memory within the atom in the incremental linker. |
| 249 | 249 | /// TODO consolidate this. |
| 250 | decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, ?MatchingSection) = .{}, | |
| 250 | decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, ?MatchingSection) = .{}, | |
| 251 | 251 | |
| 252 | 252 | const Entry = struct { |
| 253 | 253 | target: Atom.Relocation.Target, |
| 254 | 254 | atom: *Atom, |
| 255 | 255 | }; |
| 256 | 256 | |
| 257 | const UnnamedConstTable = std.AutoHashMapUnmanaged(*Module.Decl, std.ArrayListUnmanaged(*Atom)); | |
| 257 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); | |
| 258 | 258 | |
| 259 | 259 | const PendingUpdate = union(enum) { |
| 260 | 260 | resolve_undef: u32, |
| ... | ... | @@ -3451,10 +3451,15 @@ pub fn deinit(self: *MachO) void { |
| 3451 | 3451 | } |
| 3452 | 3452 | self.atom_free_lists.deinit(self.base.allocator); |
| 3453 | 3453 | } |
| 3454 | for (self.decls.keys()) |decl| { | |
| 3455 | decl.link.macho.deinit(self.base.allocator); | |
| 3454 | if (self.base.options.module) |mod| { | |
| 3455 | for (self.decls.keys()) |decl_index| { | |
| 3456 | const decl = mod.declPtr(decl_index); | |
| 3457 | decl.link.macho.deinit(self.base.allocator); | |
| 3458 | } | |
| 3459 | self.decls.deinit(self.base.allocator); | |
| 3460 | } else { | |
| 3461 | assert(self.decls.count() == 0); | |
| 3456 | 3462 | } |
| 3457 | self.decls.deinit(self.base.allocator); | |
| 3458 | 3463 | |
| 3459 | 3464 | { |
| 3460 | 3465 | var it = self.unnamed_const_atoms.valueIterator(); |
| ... | ... | @@ -3652,13 +3657,14 @@ pub fn allocateTlvPtrEntry(self: *MachO, target: Atom.Relocation.Target) !u32 { |
| 3652 | 3657 | return index; |
| 3653 | 3658 | } |
| 3654 | 3659 | |
| 3655 | pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { | |
| 3660 | pub fn allocateDeclIndexes(self: *MachO, decl_index: Module.Decl.Index) !void { | |
| 3656 | 3661 | if (self.llvm_object) |_| return; |
| 3662 | const decl = self.base.options.module.?.declPtr(decl_index); | |
| 3657 | 3663 | if (decl.link.macho.local_sym_index != 0) return; |
| 3658 | 3664 | |
| 3659 | 3665 | decl.link.macho.local_sym_index = try self.allocateLocalSymbol(); |
| 3660 | 3666 | try self.atom_by_index_table.putNoClobber(self.base.allocator, decl.link.macho.local_sym_index, &decl.link.macho); |
| 3661 | try self.decls.putNoClobber(self.base.allocator, decl, null); | |
| 3667 | try self.decls.putNoClobber(self.base.allocator, decl_index, null); | |
| 3662 | 3668 | |
| 3663 | 3669 | const got_target = .{ .local = decl.link.macho.local_sym_index }; |
| 3664 | 3670 | const got_index = try self.allocateGotEntry(got_target); |
| ... | ... | @@ -3676,8 +3682,9 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3676 | 3682 | const tracy = trace(@src()); |
| 3677 | 3683 | defer tracy.end(); |
| 3678 | 3684 | |
| 3679 | const decl = func.owner_decl; | |
| 3680 | self.freeUnnamedConsts(decl); | |
| 3685 | const decl_index = func.owner_decl; | |
| 3686 | const decl = module.declPtr(decl_index); | |
| 3687 | self.freeUnnamedConsts(decl_index); | |
| 3681 | 3688 | |
| 3682 | 3689 | // TODO clearing the code and relocs buffer should probably be orchestrated |
| 3683 | 3690 | // in a different, smarter, more automatic way somewhere else, in a more centralised |
| ... | ... | @@ -3690,7 +3697,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3690 | 3697 | defer code_buffer.deinit(); |
| 3691 | 3698 | |
| 3692 | 3699 | var decl_state = if (self.d_sym) |*d_sym| |
| 3693 | try d_sym.dwarf.initDeclState(decl) | |
| 3700 | try d_sym.dwarf.initDeclState(module, decl) | |
| 3694 | 3701 | else |
| 3695 | 3702 | null; |
| 3696 | 3703 | defer if (decl_state) |*ds| ds.deinit(); |
| ... | ... | @@ -3708,12 +3715,12 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3708 | 3715 | }, |
| 3709 | 3716 | .fail => |em| { |
| 3710 | 3717 | decl.analysis = .codegen_failure; |
| 3711 | try module.failed_decls.put(module.gpa, decl, em); | |
| 3718 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 3712 | 3719 | return; |
| 3713 | 3720 | }, |
| 3714 | 3721 | } |
| 3715 | 3722 | |
| 3716 | const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len); | |
| 3723 | const symbol = try self.placeDecl(decl_index, decl.link.macho.code.items.len); | |
| 3717 | 3724 | |
| 3718 | 3725 | if (decl_state) |*ds| { |
| 3719 | 3726 | try self.d_sym.?.dwarf.commitDeclState( |
| ... | ... | @@ -3728,22 +3735,23 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3728 | 3735 | |
| 3729 | 3736 | // Since we updated the vaddr and the size, each corresponding export symbol also |
| 3730 | 3737 | // needs to be updated. |
| 3731 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | |
| 3732 | try self.updateDeclExports(module, decl, decl_exports); | |
| 3738 | const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{}; | |
| 3739 | try self.updateDeclExports(module, decl_index, decl_exports); | |
| 3733 | 3740 | } |
| 3734 | 3741 | |
| 3735 | pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.Decl) !u32 { | |
| 3742 | pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 { | |
| 3736 | 3743 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 3737 | 3744 | defer code_buffer.deinit(); |
| 3738 | 3745 | |
| 3739 | 3746 | const module = self.base.options.module.?; |
| 3740 | const gop = try self.unnamed_const_atoms.getOrPut(self.base.allocator, decl); | |
| 3747 | const gop = try self.unnamed_const_atoms.getOrPut(self.base.allocator, decl_index); | |
| 3741 | 3748 | if (!gop.found_existing) { |
| 3742 | 3749 | gop.value_ptr.* = .{}; |
| 3743 | 3750 | } |
| 3744 | 3751 | const unnamed_consts = gop.value_ptr; |
| 3745 | 3752 | |
| 3746 | const decl_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 3753 | const decl = module.declPtr(decl_index); | |
| 3754 | const decl_name = try decl.getFullyQualifiedName(module); | |
| 3747 | 3755 | defer self.base.allocator.free(decl_name); |
| 3748 | 3756 | |
| 3749 | 3757 | const name_str_index = blk: { |
| ... | ... | @@ -3769,7 +3777,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De |
| 3769 | 3777 | .appended => code_buffer.items, |
| 3770 | 3778 | .fail => |em| { |
| 3771 | 3779 | decl.analysis = .codegen_failure; |
| 3772 | try module.failed_decls.put(module.gpa, decl, em); | |
| 3780 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 3773 | 3781 | log.err("{s}", .{em.msg}); |
| 3774 | 3782 | return error.AnalysisFail; |
| 3775 | 3783 | }, |
| ... | ... | @@ -3800,16 +3808,18 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De |
| 3800 | 3808 | return atom.local_sym_index; |
| 3801 | 3809 | } |
| 3802 | 3810 | |
| 3803 | pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | |
| 3811 | pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void { | |
| 3804 | 3812 | if (build_options.skip_non_native and builtin.object_format != .macho) { |
| 3805 | 3813 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 3806 | 3814 | } |
| 3807 | 3815 | if (build_options.have_llvm) { |
| 3808 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl); | |
| 3816 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl_index); | |
| 3809 | 3817 | } |
| 3810 | 3818 | const tracy = trace(@src()); |
| 3811 | 3819 | defer tracy.end(); |
| 3812 | 3820 | |
| 3821 | const decl = module.declPtr(decl_index); | |
| 3822 | ||
| 3813 | 3823 | if (decl.val.tag() == .extern_fn) { |
| 3814 | 3824 | return; // TODO Should we do more when front-end analyzed extern decl? |
| 3815 | 3825 | } |
| ... | ... | @@ -3824,7 +3834,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3824 | 3834 | defer code_buffer.deinit(); |
| 3825 | 3835 | |
| 3826 | 3836 | var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym| |
| 3827 | try d_sym.dwarf.initDeclState(decl) | |
| 3837 | try d_sym.dwarf.initDeclState(module, decl) | |
| 3828 | 3838 | else |
| 3829 | 3839 | null; |
| 3830 | 3840 | defer if (decl_state) |*ds| ds.deinit(); |
| ... | ... | @@ -3862,12 +3872,12 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3862 | 3872 | }, |
| 3863 | 3873 | .fail => |em| { |
| 3864 | 3874 | decl.analysis = .codegen_failure; |
| 3865 | try module.failed_decls.put(module.gpa, decl, em); | |
| 3875 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 3866 | 3876 | return; |
| 3867 | 3877 | }, |
| 3868 | 3878 | } |
| 3869 | 3879 | }; |
| 3870 | const symbol = try self.placeDecl(decl, code.len); | |
| 3880 | const symbol = try self.placeDecl(decl_index, code.len); | |
| 3871 | 3881 | |
| 3872 | 3882 | if (decl_state) |*ds| { |
| 3873 | 3883 | try self.d_sym.?.dwarf.commitDeclState( |
| ... | ... | @@ -3882,13 +3892,13 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3882 | 3892 | |
| 3883 | 3893 | // Since we updated the vaddr and the size, each corresponding export symbol also |
| 3884 | 3894 | // needs to be updated. |
| 3885 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | |
| 3886 | try self.updateDeclExports(module, decl, decl_exports); | |
| 3895 | const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{}; | |
| 3896 | try self.updateDeclExports(module, decl_index, decl_exports); | |
| 3887 | 3897 | } |
| 3888 | 3898 | |
| 3889 | 3899 | /// Checks if the value, or any of its embedded values stores a pointer, and thus requires |
| 3890 | 3900 | /// a rebase opcode for the dynamic linker. |
| 3891 | fn needsPointerRebase(ty: Type, val: Value, target: std.Target) bool { | |
| 3901 | fn needsPointerRebase(ty: Type, val: Value, mod: *Module) bool { | |
| 3892 | 3902 | if (ty.zigTypeTag() == .Fn) { |
| 3893 | 3903 | return false; |
| 3894 | 3904 | } |
| ... | ... | @@ -3903,8 +3913,8 @@ fn needsPointerRebase(ty: Type, val: Value, target: std.Target) bool { |
| 3903 | 3913 | if (ty.arrayLen() == 0) return false; |
| 3904 | 3914 | const elem_ty = ty.childType(); |
| 3905 | 3915 | var elem_value_buf: Value.ElemValueBuffer = undefined; |
| 3906 | const elem_val = val.elemValueBuffer(0, &elem_value_buf); | |
| 3907 | return needsPointerRebase(elem_ty, elem_val, target); | |
| 3916 | const elem_val = val.elemValueBuffer(mod, 0, &elem_value_buf); | |
| 3917 | return needsPointerRebase(elem_ty, elem_val, mod); | |
| 3908 | 3918 | }, |
| 3909 | 3919 | .Struct => { |
| 3910 | 3920 | const fields = ty.structFields().values(); |
| ... | ... | @@ -3912,7 +3922,7 @@ fn needsPointerRebase(ty: Type, val: Value, target: std.Target) bool { |
| 3912 | 3922 | if (val.castTag(.aggregate)) |payload| { |
| 3913 | 3923 | const field_values = payload.data; |
| 3914 | 3924 | for (field_values) |field_val, i| { |
| 3915 | if (needsPointerRebase(fields[i].ty, field_val, target)) return true; | |
| 3925 | if (needsPointerRebase(fields[i].ty, field_val, mod)) return true; | |
| 3916 | 3926 | } else return false; |
| 3917 | 3927 | } else return false; |
| 3918 | 3928 | }, |
| ... | ... | @@ -3921,18 +3931,18 @@ fn needsPointerRebase(ty: Type, val: Value, target: std.Target) bool { |
| 3921 | 3931 | const sub_val = payload.data; |
| 3922 | 3932 | var buffer: Type.Payload.ElemType = undefined; |
| 3923 | 3933 | const sub_ty = ty.optionalChild(&buffer); |
| 3924 | return needsPointerRebase(sub_ty, sub_val, target); | |
| 3934 | return needsPointerRebase(sub_ty, sub_val, mod); | |
| 3925 | 3935 | } else return false; |
| 3926 | 3936 | }, |
| 3927 | 3937 | .Union => { |
| 3928 | 3938 | const union_obj = val.cast(Value.Payload.Union).?.data; |
| 3929 | const active_field_ty = ty.unionFieldType(union_obj.tag, target); | |
| 3930 | return needsPointerRebase(active_field_ty, union_obj.val, target); | |
| 3939 | const active_field_ty = ty.unionFieldType(union_obj.tag, mod); | |
| 3940 | return needsPointerRebase(active_field_ty, union_obj.val, mod); | |
| 3931 | 3941 | }, |
| 3932 | 3942 | .ErrorUnion => { |
| 3933 | 3943 | if (val.castTag(.eu_payload)) |payload| { |
| 3934 | 3944 | const payload_ty = ty.errorUnionPayload(); |
| 3935 | return needsPointerRebase(payload_ty, payload.data, target); | |
| 3945 | return needsPointerRebase(payload_ty, payload.data, mod); | |
| 3936 | 3946 | } else return false; |
| 3937 | 3947 | }, |
| 3938 | 3948 | else => return false, |
| ... | ... | @@ -3942,6 +3952,7 @@ fn needsPointerRebase(ty: Type, val: Value, target: std.Target) bool { |
| 3942 | 3952 | fn getMatchingSectionAtom(self: *MachO, atom: *Atom, name: []const u8, ty: Type, val: Value) !MatchingSection { |
| 3943 | 3953 | const code = atom.code.items; |
| 3944 | 3954 | const target = self.base.options.target; |
| 3955 | const mod = self.base.options.module.?; | |
| 3945 | 3956 | const alignment = ty.abiAlignment(target); |
| 3946 | 3957 | const align_log_2 = math.log2(alignment); |
| 3947 | 3958 | const zig_ty = ty.zigTypeTag(); |
| ... | ... | @@ -3969,7 +3980,7 @@ fn getMatchingSectionAtom(self: *MachO, atom: *Atom, name: []const u8, ty: Type, |
| 3969 | 3980 | }; |
| 3970 | 3981 | } |
| 3971 | 3982 | |
| 3972 | if (needsPointerRebase(ty, val, target)) { | |
| 3983 | if (needsPointerRebase(ty, val, mod)) { | |
| 3973 | 3984 | break :blk (try self.getMatchingSection(.{ |
| 3974 | 3985 | .segname = makeStaticString("__DATA_CONST"), |
| 3975 | 3986 | .sectname = makeStaticString("__const"), |
| ... | ... | @@ -4025,15 +4036,17 @@ fn getMatchingSectionAtom(self: *MachO, atom: *Atom, name: []const u8, ty: Type, |
| 4025 | 4036 | return match; |
| 4026 | 4037 | } |
| 4027 | 4038 | |
| 4028 | fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 { | |
| 4039 | fn placeDecl(self: *MachO, decl_index: Module.Decl.Index, code_len: usize) !*macho.nlist_64 { | |
| 4040 | const module = self.base.options.module.?; | |
| 4041 | const decl = module.declPtr(decl_index); | |
| 4029 | 4042 | const required_alignment = decl.ty.abiAlignment(self.base.options.target); |
| 4030 | 4043 | assert(decl.link.macho.local_sym_index != 0); // Caller forgot to call allocateDeclIndexes() |
| 4031 | 4044 | const symbol = &self.locals.items[decl.link.macho.local_sym_index]; |
| 4032 | 4045 | |
| 4033 | const sym_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 4046 | const sym_name = try decl.getFullyQualifiedName(module); | |
| 4034 | 4047 | defer self.base.allocator.free(sym_name); |
| 4035 | 4048 | |
| 4036 | const decl_ptr = self.decls.getPtr(decl).?; | |
| 4049 | const decl_ptr = self.decls.getPtr(decl_index).?; | |
| 4037 | 4050 | if (decl_ptr.* == null) { |
| 4038 | 4051 | decl_ptr.* = try self.getMatchingSectionAtom(&decl.link.macho, sym_name, decl.ty, decl.val); |
| 4039 | 4052 | } |
| ... | ... | @@ -4101,19 +4114,20 @@ pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.D |
| 4101 | 4114 | pub fn updateDeclExports( |
| 4102 | 4115 | self: *MachO, |
| 4103 | 4116 | module: *Module, |
| 4104 | decl: *Module.Decl, | |
| 4117 | decl_index: Module.Decl.Index, | |
| 4105 | 4118 | exports: []const *Module.Export, |
| 4106 | 4119 | ) !void { |
| 4107 | 4120 | if (build_options.skip_non_native and builtin.object_format != .macho) { |
| 4108 | 4121 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 4109 | 4122 | } |
| 4110 | 4123 | if (build_options.have_llvm) { |
| 4111 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports); | |
| 4124 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports); | |
| 4112 | 4125 | } |
| 4113 | 4126 | const tracy = trace(@src()); |
| 4114 | 4127 | defer tracy.end(); |
| 4115 | 4128 | |
| 4116 | 4129 | try self.globals.ensureUnusedCapacity(self.base.allocator, exports.len); |
| 4130 | const decl = module.declPtr(decl_index); | |
| 4117 | 4131 | if (decl.link.macho.local_sym_index == 0) return; |
| 4118 | 4132 | const decl_sym = &self.locals.items[decl.link.macho.local_sym_index]; |
| 4119 | 4133 | |
| ... | ... | @@ -4250,9 +4264,8 @@ pub fn deleteExport(self: *MachO, exp: Export) void { |
| 4250 | 4264 | global.n_value = 0; |
| 4251 | 4265 | } |
| 4252 | 4266 | |
| 4253 | fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void { | |
| 4254 | log.debug("freeUnnamedConsts for decl {*}", .{decl}); | |
| 4255 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl) orelse return; | |
| 4267 | fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void { | |
| 4268 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; | |
| 4256 | 4269 | for (unnamed_consts.items) |atom| { |
| 4257 | 4270 | self.freeAtom(atom, .{ |
| 4258 | 4271 | .seg = self.text_segment_cmd_index.?, |
| ... | ... | @@ -4267,15 +4280,17 @@ fn freeUnnamedConsts(self: *MachO, decl: *Module.Decl) void { |
| 4267 | 4280 | unnamed_consts.clearAndFree(self.base.allocator); |
| 4268 | 4281 | } |
| 4269 | 4282 | |
| 4270 | pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { | |
| 4283 | pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void { | |
| 4271 | 4284 | if (build_options.have_llvm) { |
| 4272 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl); | |
| 4285 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | |
| 4273 | 4286 | } |
| 4287 | const mod = self.base.options.module.?; | |
| 4288 | const decl = mod.declPtr(decl_index); | |
| 4274 | 4289 | log.debug("freeDecl {*}", .{decl}); |
| 4275 | const kv = self.decls.fetchSwapRemove(decl); | |
| 4290 | const kv = self.decls.fetchSwapRemove(decl_index); | |
| 4276 | 4291 | if (kv.?.value) |match| { |
| 4277 | 4292 | self.freeAtom(&decl.link.macho, match, false); |
| 4278 | self.freeUnnamedConsts(decl); | |
| 4293 | self.freeUnnamedConsts(decl_index); | |
| 4279 | 4294 | } |
| 4280 | 4295 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 4281 | 4296 | if (decl.link.macho.local_sym_index != 0) { |
| ... | ... | @@ -4307,7 +4322,10 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { |
| 4307 | 4322 | } |
| 4308 | 4323 | } |
| 4309 | 4324 | |
| 4310 | pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, reloc_info: File.RelocInfo) !u64 { | |
| 4325 | pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: File.RelocInfo) !u64 { | |
| 4326 | const mod = self.base.options.module.?; | |
| 4327 | const decl = mod.declPtr(decl_index); | |
| 4328 | ||
| 4311 | 4329 | assert(self.llvm_object == null); |
| 4312 | 4330 | assert(decl.link.macho.local_sym_index != 0); |
| 4313 | 4331 |
src/link/NvPtx.zig+6-6| ... | ... | @@ -74,27 +74,27 @@ pub fn updateFunc(self: *NvPtx, module: *Module, func: *Module.Fn, air: Air, liv |
| 74 | 74 | try self.llvm_object.updateFunc(module, func, air, liveness); |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | pub fn updateDecl(self: *NvPtx, module: *Module, decl: *Module.Decl) !void { | |
| 77 | pub fn updateDecl(self: *NvPtx, module: *Module, decl_index: Module.Decl.Index) !void { | |
| 78 | 78 | if (!build_options.have_llvm) return; |
| 79 | return self.llvm_object.updateDecl(module, decl); | |
| 79 | return self.llvm_object.updateDecl(module, decl_index); | |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | pub fn updateDeclExports( |
| 83 | 83 | self: *NvPtx, |
| 84 | 84 | module: *Module, |
| 85 | decl: *const Module.Decl, | |
| 85 | decl_index: Module.Decl.Index, | |
| 86 | 86 | exports: []const *Module.Export, |
| 87 | 87 | ) !void { |
| 88 | 88 | if (!build_options.have_llvm) return; |
| 89 | 89 | if (build_options.skip_non_native and builtin.object_format != .nvptx) { |
| 90 | 90 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 91 | 91 | } |
| 92 | return self.llvm_object.updateDeclExports(module, decl, exports); | |
| 92 | return self.llvm_object.updateDeclExports(module, decl_index, exports); | |
| 93 | 93 | } |
| 94 | 94 | |
| 95 | pub fn freeDecl(self: *NvPtx, decl: *Module.Decl) void { | |
| 95 | pub fn freeDecl(self: *NvPtx, decl_index: Module.Decl.Index) void { | |
| 96 | 96 | if (!build_options.have_llvm) return; |
| 97 | return self.llvm_object.freeDecl(decl); | |
| 97 | return self.llvm_object.freeDecl(decl_index); | |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | 100 | pub fn flush(self: *NvPtx, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
src/link/Plan9.zig+57-37| ... | ... | @@ -59,9 +59,9 @@ path_arena: std.heap.ArenaAllocator, |
| 59 | 59 | /// If we group the decls by file, it makes it really easy to do this (put the symbol in the correct place) |
| 60 | 60 | fn_decl_table: std.AutoArrayHashMapUnmanaged( |
| 61 | 61 | *Module.File, |
| 62 | struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(*Module.Decl, FnDeclOutput) = .{} }, | |
| 62 | struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, FnDeclOutput) = .{} }, | |
| 63 | 63 | ) = .{}, |
| 64 | data_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{}, | |
| 64 | data_decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, []const u8) = .{}, | |
| 65 | 65 | |
| 66 | 66 | hdr: aout.ExecHdr = undefined, |
| 67 | 67 | |
| ... | ... | @@ -162,11 +162,13 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 { |
| 162 | 162 | return self; |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | fn putFn(self: *Plan9, decl: *Module.Decl, out: FnDeclOutput) !void { | |
| 165 | fn putFn(self: *Plan9, decl_index: Module.Decl.Index, out: FnDeclOutput) !void { | |
| 166 | 166 | const gpa = self.base.allocator; |
| 167 | const mod = self.base.options.module.?; | |
| 168 | const decl = mod.declPtr(decl_index); | |
| 167 | 169 | const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope()); |
| 168 | 170 | if (fn_map_res.found_existing) { |
| 169 | try fn_map_res.value_ptr.functions.put(gpa, decl, out); | |
| 171 | try fn_map_res.value_ptr.functions.put(gpa, decl_index, out); | |
| 170 | 172 | } else { |
| 171 | 173 | const file = decl.getFileScope(); |
| 172 | 174 | const arena = self.path_arena.allocator(); |
| ... | ... | @@ -178,7 +180,7 @@ fn putFn(self: *Plan9, decl: *Module.Decl, out: FnDeclOutput) !void { |
| 178 | 180 | break :blk @intCast(u32, self.syms.items.len - 1); |
| 179 | 181 | }, |
| 180 | 182 | }; |
| 181 | try fn_map_res.value_ptr.functions.put(gpa, decl, out); | |
| 183 | try fn_map_res.value_ptr.functions.put(gpa, decl_index, out); | |
| 182 | 184 | |
| 183 | 185 | var a = std.ArrayList(u8).init(arena); |
| 184 | 186 | errdefer a.deinit(); |
| ... | ... | @@ -229,9 +231,10 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv |
| 229 | 231 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 230 | 232 | } |
| 231 | 233 | |
| 232 | const decl = func.owner_decl; | |
| 234 | const decl_index = func.owner_decl; | |
| 235 | const decl = module.declPtr(decl_index); | |
| 233 | 236 | |
| 234 | try self.seeDecl(decl); | |
| 237 | try self.seeDecl(decl_index); | |
| 235 | 238 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); |
| 236 | 239 | |
| 237 | 240 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| ... | ... | @@ -262,7 +265,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv |
| 262 | 265 | .appended => code_buffer.toOwnedSlice(), |
| 263 | 266 | .fail => |em| { |
| 264 | 267 | decl.analysis = .codegen_failure; |
| 265 | try module.failed_decls.put(module.gpa, decl, em); | |
| 268 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 266 | 269 | return; |
| 267 | 270 | }, |
| 268 | 271 | }; |
| ... | ... | @@ -272,19 +275,21 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv |
| 272 | 275 | .start_line = start_line.?, |
| 273 | 276 | .end_line = end_line, |
| 274 | 277 | }; |
| 275 | try self.putFn(decl, out); | |
| 278 | try self.putFn(decl_index, out); | |
| 276 | 279 | return self.updateFinish(decl); |
| 277 | 280 | } |
| 278 | 281 | |
| 279 | pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl: *Module.Decl) !u32 { | |
| 282 | pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { | |
| 280 | 283 | _ = self; |
| 281 | 284 | _ = tv; |
| 282 | _ = decl; | |
| 285 | _ = decl_index; | |
| 283 | 286 | log.debug("TODO lowerUnnamedConst for Plan9", .{}); |
| 284 | 287 | return error.AnalysisFail; |
| 285 | 288 | } |
| 286 | 289 | |
| 287 | pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void { | |
| 290 | pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) !void { | |
| 291 | const decl = module.declPtr(decl_index); | |
| 292 | ||
| 288 | 293 | if (decl.val.tag() == .extern_fn) { |
| 289 | 294 | return; // TODO Should we do more when front-end analyzed extern decl? |
| 290 | 295 | } |
| ... | ... | @@ -295,7 +300,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void { |
| 295 | 300 | } |
| 296 | 301 | } |
| 297 | 302 | |
| 298 | try self.seeDecl(decl); | |
| 303 | try self.seeDecl(decl_index); | |
| 299 | 304 | |
| 300 | 305 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); |
| 301 | 306 | |
| ... | ... | @@ -315,13 +320,13 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void { |
| 315 | 320 | .appended => code_buffer.items, |
| 316 | 321 | .fail => |em| { |
| 317 | 322 | decl.analysis = .codegen_failure; |
| 318 | try module.failed_decls.put(module.gpa, decl, em); | |
| 323 | try module.failed_decls.put(module.gpa, decl_index, em); | |
| 319 | 324 | return; |
| 320 | 325 | }, |
| 321 | 326 | }; |
| 322 | 327 | var duped_code = try self.base.allocator.dupe(u8, code); |
| 323 | 328 | errdefer self.base.allocator.free(duped_code); |
| 324 | try self.data_decl_table.put(self.base.allocator, decl, duped_code); | |
| 329 | try self.data_decl_table.put(self.base.allocator, decl_index, duped_code); | |
| 325 | 330 | return self.updateFinish(decl); |
| 326 | 331 | } |
| 327 | 332 | /// called at the end of update{Decl,Func} |
| ... | ... | @@ -435,7 +440,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 435 | 440 | while (it_file.next()) |fentry| { |
| 436 | 441 | var it = fentry.value_ptr.functions.iterator(); |
| 437 | 442 | while (it.next()) |entry| { |
| 438 | const decl = entry.key_ptr.*; | |
| 443 | const decl_index = entry.key_ptr.*; | |
| 444 | const decl = mod.declPtr(decl_index); | |
| 439 | 445 | const out = entry.value_ptr.*; |
| 440 | 446 | log.debug("write text decl {*} ({s}), lines {d} to {d}", .{ decl, decl.name, out.start_line + 1, out.end_line }); |
| 441 | 447 | { |
| ... | ... | @@ -462,7 +468,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 462 | 468 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| 463 | 469 | } |
| 464 | 470 | self.syms.items[decl.link.plan9.sym_index.?].value = off; |
| 465 | if (mod.decl_exports.get(decl)) |exports| { | |
| 471 | if (mod.decl_exports.get(decl_index)) |exports| { | |
| 466 | 472 | try self.addDeclExports(mod, decl, exports); |
| 467 | 473 | } |
| 468 | 474 | } |
| ... | ... | @@ -482,7 +488,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 482 | 488 | { |
| 483 | 489 | var it = self.data_decl_table.iterator(); |
| 484 | 490 | while (it.next()) |entry| { |
| 485 | const decl = entry.key_ptr.*; | |
| 491 | const decl_index = entry.key_ptr.*; | |
| 492 | const decl = mod.declPtr(decl_index); | |
| 486 | 493 | const code = entry.value_ptr.*; |
| 487 | 494 | log.debug("write data decl {*} ({s})", .{ decl, decl.name }); |
| 488 | 495 | |
| ... | ... | @@ -498,7 +505,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 498 | 505 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| 499 | 506 | } |
| 500 | 507 | self.syms.items[decl.link.plan9.sym_index.?].value = off; |
| 501 | if (mod.decl_exports.get(decl)) |exports| { | |
| 508 | if (mod.decl_exports.get(decl_index)) |exports| { | |
| 502 | 509 | try self.addDeclExports(mod, decl, exports); |
| 503 | 510 | } |
| 504 | 511 | } |
| ... | ... | @@ -564,24 +571,25 @@ fn addDeclExports( |
| 564 | 571 | } |
| 565 | 572 | } |
| 566 | 573 | |
| 567 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { | |
| 574 | pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { | |
| 568 | 575 | // TODO audit the lifetimes of decls table entries. It's possible to get |
| 569 | 576 | // allocateDeclIndexes and then freeDecl without any updateDecl in between. |
| 570 | 577 | // However that is planned to change, see the TODO comment in Module.zig |
| 571 | 578 | // in the deleteUnusedDecl function. |
| 579 | const mod = self.base.options.module.?; | |
| 580 | const decl = mod.declPtr(decl_index); | |
| 572 | 581 | const is_fn = (decl.val.tag() == .function); |
| 573 | 582 | if (is_fn) { |
| 574 | var symidx_and_submap = | |
| 575 | self.fn_decl_table.get(decl.getFileScope()).?; | |
| 583 | var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope()).?; | |
| 576 | 584 | var submap = symidx_and_submap.functions; |
| 577 | _ = submap.swapRemove(decl); | |
| 585 | _ = submap.swapRemove(decl_index); | |
| 578 | 586 | if (submap.count() == 0) { |
| 579 | 587 | self.syms.items[symidx_and_submap.sym_index] = aout.Sym.undefined_symbol; |
| 580 | 588 | self.syms_index_free_list.append(self.base.allocator, symidx_and_submap.sym_index) catch {}; |
| 581 | 589 | submap.deinit(self.base.allocator); |
| 582 | 590 | } |
| 583 | 591 | } else { |
| 584 | _ = self.data_decl_table.swapRemove(decl); | |
| 592 | _ = self.data_decl_table.swapRemove(decl_index); | |
| 585 | 593 | } |
| 586 | 594 | if (decl.link.plan9.got_index) |i| { |
| 587 | 595 | // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length |
| ... | ... | @@ -593,7 +601,9 @@ pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { |
| 593 | 601 | } |
| 594 | 602 | } |
| 595 | 603 | |
| 596 | pub fn seeDecl(self: *Plan9, decl: *Module.Decl) !void { | |
| 604 | pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !void { | |
| 605 | const mod = self.base.options.module.?; | |
| 606 | const decl = mod.declPtr(decl_index); | |
| 597 | 607 | if (decl.link.plan9.got_index == null) { |
| 598 | 608 | if (self.got_index_free_list.popOrNull()) |i| { |
| 599 | 609 | decl.link.plan9.got_index = i; |
| ... | ... | @@ -607,14 +617,13 @@ pub fn seeDecl(self: *Plan9, decl: *Module.Decl) !void { |
| 607 | 617 | pub fn updateDeclExports( |
| 608 | 618 | self: *Plan9, |
| 609 | 619 | module: *Module, |
| 610 | decl: *Module.Decl, | |
| 620 | decl_index: Module.Decl.Index, | |
| 611 | 621 | exports: []const *Module.Export, |
| 612 | 622 | ) !void { |
| 613 | try self.seeDecl(decl); | |
| 623 | try self.seeDecl(decl_index); | |
| 614 | 624 | // we do all the things in flush |
| 615 | 625 | _ = self; |
| 616 | 626 | _ = module; |
| 617 | _ = decl; | |
| 618 | 627 | _ = exports; |
| 619 | 628 | } |
| 620 | 629 | pub fn deinit(self: *Plan9) void { |
| ... | ... | @@ -709,14 +718,18 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 709 | 718 | }); |
| 710 | 719 | } |
| 711 | 720 | } |
| 721 | ||
| 722 | const mod = self.base.options.module.?; | |
| 723 | ||
| 712 | 724 | // write the data symbols |
| 713 | 725 | { |
| 714 | 726 | var it = self.data_decl_table.iterator(); |
| 715 | 727 | while (it.next()) |entry| { |
| 716 | const decl = entry.key_ptr.*; | |
| 728 | const decl_index = entry.key_ptr.*; | |
| 729 | const decl = mod.declPtr(decl_index); | |
| 717 | 730 | const sym = self.syms.items[decl.link.plan9.sym_index.?]; |
| 718 | 731 | try self.writeSym(writer, sym); |
| 719 | if (self.base.options.module.?.decl_exports.get(decl)) |exports| { | |
| 732 | if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| { | |
| 720 | 733 | for (exports) |e| { |
| 721 | 734 | try self.writeSym(writer, self.syms.items[e.link.plan9.?]); |
| 722 | 735 | } |
| ... | ... | @@ -737,10 +750,11 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 737 | 750 | // write all the decls come from the file of the z symbol |
| 738 | 751 | var submap_it = symidx_and_submap.functions.iterator(); |
| 739 | 752 | while (submap_it.next()) |entry| { |
| 740 | const decl = entry.key_ptr.*; | |
| 753 | const decl_index = entry.key_ptr.*; | |
| 754 | const decl = mod.declPtr(decl_index); | |
| 741 | 755 | const sym = self.syms.items[decl.link.plan9.sym_index.?]; |
| 742 | 756 | try self.writeSym(writer, sym); |
| 743 | if (self.base.options.module.?.decl_exports.get(decl)) |exports| { | |
| 757 | if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| { | |
| 744 | 758 | for (exports) |e| { |
| 745 | 759 | const s = self.syms.items[e.link.plan9.?]; |
| 746 | 760 | if (mem.eql(u8, s.name, "_start")) |
| ... | ... | @@ -754,12 +768,18 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 754 | 768 | } |
| 755 | 769 | |
| 756 | 770 | /// this will be removed, moved to updateFinish |
| 757 | pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { | |
| 771 | pub fn allocateDeclIndexes(self: *Plan9, decl_index: Module.Decl.Index) !void { | |
| 758 | 772 | _ = self; |
| 759 | _ = decl; | |
| 773 | _ = decl_index; | |
| 760 | 774 | } |
| 761 | pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, reloc_info: link.File.RelocInfo) !u64 { | |
| 775 | pub fn getDeclVAddr( | |
| 776 | self: *Plan9, | |
| 777 | decl_index: Module.Decl.Index, | |
| 778 | reloc_info: link.File.RelocInfo, | |
| 779 | ) !u64 { | |
| 762 | 780 | _ = reloc_info; |
| 781 | const mod = self.base.options.module.?; | |
| 782 | const decl = mod.declPtr(decl_index); | |
| 763 | 783 | if (decl.ty.zigTypeTag() == .Fn) { |
| 764 | 784 | var start = self.bases.text; |
| 765 | 785 | var it_file = self.fn_decl_table.iterator(); |
| ... | ... | @@ -767,7 +787,7 @@ pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, reloc_info: link.Fil |
| 767 | 787 | var symidx_and_submap = fentry.value_ptr; |
| 768 | 788 | var submap_it = symidx_and_submap.functions.iterator(); |
| 769 | 789 | while (submap_it.next()) |entry| { |
| 770 | if (entry.key_ptr.* == decl) return start; | |
| 790 | if (entry.key_ptr.* == decl_index) return start; | |
| 771 | 791 | start += entry.value_ptr.code.len; |
| 772 | 792 | } |
| 773 | 793 | } |
| ... | ... | @@ -776,7 +796,7 @@ pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, reloc_info: link.Fil |
| 776 | 796 | var start = self.bases.data + self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; |
| 777 | 797 | var it = self.data_decl_table.iterator(); |
| 778 | 798 | while (it.next()) |kv| { |
| 779 | if (decl == kv.key_ptr.*) return start; | |
| 799 | if (decl_index == kv.key_ptr.*) return start; | |
| 780 | 800 | start += kv.value_ptr.len; |
| 781 | 801 | } |
| 782 | 802 | unreachable; |
src/link/SpirV.zig+14-10| ... | ... | @@ -54,7 +54,7 @@ base: link.File, |
| 54 | 54 | /// This linker backend does not try to incrementally link output SPIR-V code. |
| 55 | 55 | /// Instead, it tracks all declarations in this table, and iterates over it |
| 56 | 56 | /// in the flush function. |
| 57 | decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, DeclGenContext) = .{}, | |
| 57 | decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclGenContext) = .{}, | |
| 58 | 58 | |
| 59 | 59 | const DeclGenContext = struct { |
| 60 | 60 | air: Air, |
| ... | ... | @@ -145,29 +145,31 @@ pub fn updateFunc(self: *SpirV, module: *Module, func: *Module.Fn, air: Air, liv |
| 145 | 145 | }; |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void { | |
| 148 | pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index) !void { | |
| 149 | 149 | if (build_options.skip_non_native) { |
| 150 | 150 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 151 | 151 | } |
| 152 | 152 | _ = module; |
| 153 | 153 | // Keep track of all decls so we can iterate over them on flush(). |
| 154 | _ = try self.decl_table.getOrPut(self.base.allocator, decl); | |
| 154 | _ = try self.decl_table.getOrPut(self.base.allocator, decl_index); | |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | pub fn updateDeclExports( |
| 158 | 158 | self: *SpirV, |
| 159 | 159 | module: *Module, |
| 160 | decl: *const Module.Decl, | |
| 160 | decl_index: Module.Decl.Index, | |
| 161 | 161 | exports: []const *Module.Export, |
| 162 | 162 | ) !void { |
| 163 | 163 | _ = self; |
| 164 | 164 | _ = module; |
| 165 | _ = decl; | |
| 165 | _ = decl_index; | |
| 166 | 166 | _ = exports; |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void { | |
| 170 | const index = self.decl_table.getIndex(decl).?; | |
| 169 | pub fn freeDecl(self: *SpirV, decl_index: Module.Decl.Index) void { | |
| 170 | const index = self.decl_table.getIndex(decl_index).?; | |
| 171 | const module = self.base.options.module.?; | |
| 172 | const decl = module.declPtr(decl_index); | |
| 171 | 173 | if (decl.val.tag() == .function) { |
| 172 | 174 | self.decl_table.values()[index].deinit(self.base.allocator); |
| 173 | 175 | } |
| ... | ... | @@ -208,7 +210,8 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No |
| 208 | 210 | // TODO: We're allocating an ID unconditionally now, are there |
| 209 | 211 | // declarations which don't generate a result? |
| 210 | 212 | // TODO: fn_link is used here, but thats probably not the right field. It will work anyway though. |
| 211 | for (self.decl_table.keys()) |decl| { | |
| 213 | for (self.decl_table.keys()) |decl_index| { | |
| 214 | const decl = module.declPtr(decl_index); | |
| 212 | 215 | if (decl.has_tv) { |
| 213 | 216 | decl.fn_link.spirv.id = spv.allocId(); |
| 214 | 217 | } |
| ... | ... | @@ -220,7 +223,8 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No |
| 220 | 223 | |
| 221 | 224 | var it = self.decl_table.iterator(); |
| 222 | 225 | while (it.next()) |entry| { |
| 223 | const decl = entry.key_ptr.*; | |
| 226 | const decl_index = entry.key_ptr.*; | |
| 227 | const decl = module.declPtr(decl_index); | |
| 224 | 228 | if (!decl.has_tv) continue; |
| 225 | 229 | |
| 226 | 230 | const air = entry.value_ptr.air; |
| ... | ... | @@ -228,7 +232,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No |
| 228 | 232 | |
| 229 | 233 | // Note, if `decl` is not a function, air/liveness may be undefined. |
| 230 | 234 | if (try decl_gen.gen(decl, air, liveness)) |msg| { |
| 231 | try module.failed_decls.put(module.gpa, decl, msg); | |
| 235 | try module.failed_decls.put(module.gpa, decl_index, msg); | |
| 232 | 236 | return; // TODO: Attempt to generate more decls? |
| 233 | 237 | } |
| 234 | 238 | } |
src/link/Wasm.zig+70-47| ... | ... | @@ -48,7 +48,7 @@ host_name: []const u8 = "env", |
| 48 | 48 | /// List of all `Decl` that are currently alive. |
| 49 | 49 | /// This is ment for bookkeeping so we can safely cleanup all codegen memory |
| 50 | 50 | /// when calling `deinit` |
| 51 | decls: std.AutoHashMapUnmanaged(*Module.Decl, void) = .{}, | |
| 51 | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, void) = .{}, | |
| 52 | 52 | /// List of all symbols generated by Zig code. |
| 53 | 53 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, |
| 54 | 54 | /// List of symbol indexes which are free to be used. |
| ... | ... | @@ -429,9 +429,14 @@ pub fn deinit(self: *Wasm) void { |
| 429 | 429 | if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa); |
| 430 | 430 | } |
| 431 | 431 | |
| 432 | var decl_it = self.decls.keyIterator(); | |
| 433 | while (decl_it.next()) |decl_ptr| { | |
| 434 | decl_ptr.*.link.wasm.deinit(gpa); | |
| 432 | if (self.base.options.module) |mod| { | |
| 433 | var decl_it = self.decls.keyIterator(); | |
| 434 | while (decl_it.next()) |decl_index_ptr| { | |
| 435 | const decl = mod.declPtr(decl_index_ptr.*); | |
| 436 | decl.link.wasm.deinit(gpa); | |
| 437 | } | |
| 438 | } else { | |
| 439 | assert(self.decls.count() == 0); | |
| 435 | 440 | } |
| 436 | 441 | |
| 437 | 442 | for (self.func_types.items) |*func_type| { |
| ... | ... | @@ -476,12 +481,13 @@ pub fn deinit(self: *Wasm) void { |
| 476 | 481 | self.string_table.deinit(gpa); |
| 477 | 482 | } |
| 478 | 483 | |
| 479 | pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void { | |
| 484 | pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void { | |
| 480 | 485 | if (self.llvm_object) |_| return; |
| 486 | const decl = self.base.options.module.?.declPtr(decl_index); | |
| 481 | 487 | if (decl.link.wasm.sym_index != 0) return; |
| 482 | 488 | |
| 483 | 489 | try self.symbols.ensureUnusedCapacity(self.base.allocator, 1); |
| 484 | try self.decls.putNoClobber(self.base.allocator, decl, {}); | |
| 490 | try self.decls.putNoClobber(self.base.allocator, decl_index, {}); | |
| 485 | 491 | |
| 486 | 492 | const atom = &decl.link.wasm; |
| 487 | 493 | |
| ... | ... | @@ -502,14 +508,15 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void { |
| 502 | 508 | try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom); |
| 503 | 509 | } |
| 504 | 510 | |
| 505 | pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | |
| 511 | pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { | |
| 506 | 512 | if (build_options.skip_non_native and builtin.object_format != .wasm) { |
| 507 | 513 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 508 | 514 | } |
| 509 | 515 | if (build_options.have_llvm) { |
| 510 | if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(module, func, air, liveness); | |
| 516 | if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness); | |
| 511 | 517 | } |
| 512 | const decl = func.owner_decl; | |
| 518 | const decl_index = func.owner_decl; | |
| 519 | const decl = mod.declPtr(decl_index); | |
| 513 | 520 | assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes() |
| 514 | 521 | |
| 515 | 522 | decl.link.wasm.clear(); |
| ... | ... | @@ -530,7 +537,7 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live |
| 530 | 537 | .appended => code_writer.items, |
| 531 | 538 | .fail => |em| { |
| 532 | 539 | decl.analysis = .codegen_failure; |
| 533 | try module.failed_decls.put(module.gpa, decl, em); | |
| 540 | try mod.failed_decls.put(mod.gpa, decl_index, em); | |
| 534 | 541 | return; |
| 535 | 542 | }, |
| 536 | 543 | }; |
| ... | ... | @@ -540,14 +547,15 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live |
| 540 | 547 | |
| 541 | 548 | // Generate code for the Decl, storing it in memory to be later written to |
| 542 | 549 | // the file on flush(). |
| 543 | pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { | |
| 550 | pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void { | |
| 544 | 551 | if (build_options.skip_non_native and builtin.object_format != .wasm) { |
| 545 | 552 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 546 | 553 | } |
| 547 | 554 | if (build_options.have_llvm) { |
| 548 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl); | |
| 555 | if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index); | |
| 549 | 556 | } |
| 550 | 557 | |
| 558 | const decl = mod.declPtr(decl_index); | |
| 551 | 559 | assert(decl.link.wasm.sym_index != 0); // Must call allocateDeclIndexes() |
| 552 | 560 | |
| 553 | 561 | decl.link.wasm.clear(); |
| ... | ... | @@ -580,7 +588,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { |
| 580 | 588 | .appended => code_writer.items, |
| 581 | 589 | .fail => |em| { |
| 582 | 590 | decl.analysis = .codegen_failure; |
| 583 | try module.failed_decls.put(module.gpa, decl, em); | |
| 591 | try mod.failed_decls.put(mod.gpa, decl_index, em); | |
| 584 | 592 | return; |
| 585 | 593 | }, |
| 586 | 594 | }; |
| ... | ... | @@ -590,12 +598,13 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { |
| 590 | 598 | |
| 591 | 599 | fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void { |
| 592 | 600 | if (code.len == 0) return; |
| 601 | const mod = self.base.options.module.?; | |
| 593 | 602 | const atom: *Atom = &decl.link.wasm; |
| 594 | 603 | atom.size = @intCast(u32, code.len); |
| 595 | 604 | atom.alignment = decl.ty.abiAlignment(self.base.options.target); |
| 596 | 605 | const symbol = &self.symbols.items[atom.sym_index]; |
| 597 | 606 | |
| 598 | const full_name = try decl.getFullyQualifiedName(self.base.allocator); | |
| 607 | const full_name = try decl.getFullyQualifiedName(mod); | |
| 599 | 608 | defer self.base.allocator.free(full_name); |
| 600 | 609 | symbol.name = try self.string_table.put(self.base.allocator, full_name); |
| 601 | 610 | try atom.code.appendSlice(self.base.allocator, code); |
| ... | ... | @@ -606,12 +615,15 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void { |
| 606 | 615 | /// Lowers a constant typed value to a local symbol and atom. |
| 607 | 616 | /// Returns the symbol index of the local |
| 608 | 617 | /// The given `decl` is the parent decl whom owns the constant. |
| 609 | pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { | |
| 618 | pub fn lowerUnnamedConst(self: *Wasm, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { | |
| 610 | 619 | assert(tv.ty.zigTypeTag() != .Fn); // cannot create local symbols for functions |
| 611 | 620 | |
| 621 | const mod = self.base.options.module.?; | |
| 622 | const decl = mod.declPtr(decl_index); | |
| 623 | ||
| 612 | 624 | // Create and initialize a new local symbol and atom |
| 613 | 625 | const local_index = decl.link.wasm.locals.items.len; |
| 614 | const fqdn = try decl.getFullyQualifiedName(self.base.allocator); | |
| 626 | const fqdn = try decl.getFullyQualifiedName(mod); | |
| 615 | 627 | defer self.base.allocator.free(fqdn); |
| 616 | 628 | const name = try std.fmt.allocPrintZ(self.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index }); |
| 617 | 629 | defer self.base.allocator.free(name); |
| ... | ... | @@ -641,7 +653,6 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { |
| 641 | 653 | var value_bytes = std.ArrayList(u8).init(self.base.allocator); |
| 642 | 654 | defer value_bytes.deinit(); |
| 643 | 655 | |
| 644 | const module = self.base.options.module.?; | |
| 645 | 656 | const result = try codegen.generateSymbol( |
| 646 | 657 | &self.base, |
| 647 | 658 | decl.srcLoc(), |
| ... | ... | @@ -658,7 +669,7 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { |
| 658 | 669 | .appended => value_bytes.items, |
| 659 | 670 | .fail => |em| { |
| 660 | 671 | decl.analysis = .codegen_failure; |
| 661 | try module.failed_decls.put(module.gpa, decl, em); | |
| 672 | try mod.failed_decls.put(mod.gpa, decl_index, em); | |
| 662 | 673 | return error.AnalysisFail; |
| 663 | 674 | }, |
| 664 | 675 | }; |
| ... | ... | @@ -672,9 +683,11 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { |
| 672 | 683 | /// Returns the given pointer address |
| 673 | 684 | pub fn getDeclVAddr( |
| 674 | 685 | self: *Wasm, |
| 675 | decl: *const Module.Decl, | |
| 686 | decl_index: Module.Decl.Index, | |
| 676 | 687 | reloc_info: link.File.RelocInfo, |
| 677 | 688 | ) !u64 { |
| 689 | const mod = self.base.options.module.?; | |
| 690 | const decl = mod.declPtr(decl_index); | |
| 678 | 691 | const target_symbol_index = decl.link.wasm.sym_index; |
| 679 | 692 | assert(target_symbol_index != 0); |
| 680 | 693 | assert(reloc_info.parent_atom_index != 0); |
| ... | ... | @@ -722,21 +735,23 @@ pub fn deleteExport(self: *Wasm, exp: Export) void { |
| 722 | 735 | |
| 723 | 736 | pub fn updateDeclExports( |
| 724 | 737 | self: *Wasm, |
| 725 | module: *Module, | |
| 726 | decl: *const Module.Decl, | |
| 738 | mod: *Module, | |
| 739 | decl_index: Module.Decl.Index, | |
| 727 | 740 | exports: []const *Module.Export, |
| 728 | 741 | ) !void { |
| 729 | 742 | if (build_options.skip_non_native and builtin.object_format != .wasm) { |
| 730 | 743 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 731 | 744 | } |
| 732 | 745 | if (build_options.have_llvm) { |
| 733 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl, exports); | |
| 746 | if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(mod, decl_index, exports); | |
| 734 | 747 | } |
| 735 | 748 | |
| 749 | const decl = mod.declPtr(decl_index); | |
| 750 | ||
| 736 | 751 | for (exports) |exp| { |
| 737 | 752 | if (exp.options.section) |section| { |
| 738 | try module.failed_exports.putNoClobber(module.gpa, exp, try Module.ErrorMsg.create( | |
| 739 | module.gpa, | |
| 753 | try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create( | |
| 754 | mod.gpa, | |
| 740 | 755 | decl.srcLoc(), |
| 741 | 756 | "Unimplemented: ExportOptions.section '{s}'", |
| 742 | 757 | .{section}, |
| ... | ... | @@ -754,8 +769,8 @@ pub fn updateDeclExports( |
| 754 | 769 | // are strong symbols, we have a linker error. |
| 755 | 770 | // In the other case we replace one with the other. |
| 756 | 771 | if (!exp_is_weak and !existing_sym.isWeak()) { |
| 757 | try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create( | |
| 758 | module.gpa, | |
| 772 | try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create( | |
| 773 | mod.gpa, | |
| 759 | 774 | decl.srcLoc(), |
| 760 | 775 | \\LinkError: symbol '{s}' defined multiple times |
| 761 | 776 | \\ first definition in '{s}' |
| ... | ... | @@ -773,8 +788,9 @@ pub fn updateDeclExports( |
| 773 | 788 | } |
| 774 | 789 | } |
| 775 | 790 | |
| 776 | const sym_index = exp.exported_decl.link.wasm.sym_index; | |
| 777 | const sym_loc = exp.exported_decl.link.wasm.symbolLoc(); | |
| 791 | const exported_decl = mod.declPtr(exp.exported_decl); | |
| 792 | const sym_index = exported_decl.link.wasm.sym_index; | |
| 793 | const sym_loc = exported_decl.link.wasm.symbolLoc(); | |
| 778 | 794 | const symbol = sym_loc.getSymbol(self); |
| 779 | 795 | switch (exp.options.linkage) { |
| 780 | 796 | .Internal => { |
| ... | ... | @@ -786,8 +802,8 @@ pub fn updateDeclExports( |
| 786 | 802 | }, |
| 787 | 803 | .Strong => {}, // symbols are strong by default |
| 788 | 804 | .LinkOnce => { |
| 789 | try module.failed_exports.putNoClobber(module.gpa, exp, try Module.ErrorMsg.create( | |
| 790 | module.gpa, | |
| 805 | try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create( | |
| 806 | mod.gpa, | |
| 791 | 807 | decl.srcLoc(), |
| 792 | 808 | "Unimplemented: LinkOnce", |
| 793 | 809 | .{}, |
| ... | ... | @@ -813,13 +829,15 @@ pub fn updateDeclExports( |
| 813 | 829 | } |
| 814 | 830 | } |
| 815 | 831 | |
| 816 | pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { | |
| 832 | pub fn freeDecl(self: *Wasm, decl_index: Module.Decl.Index) void { | |
| 817 | 833 | if (build_options.have_llvm) { |
| 818 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl); | |
| 834 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | |
| 819 | 835 | } |
| 836 | const mod = self.base.options.module.?; | |
| 837 | const decl = mod.declPtr(decl_index); | |
| 820 | 838 | const atom = &decl.link.wasm; |
| 821 | 839 | self.symbols_free_list.append(self.base.allocator, atom.sym_index) catch {}; |
| 822 | _ = self.decls.remove(decl); | |
| 840 | _ = self.decls.remove(decl_index); | |
| 823 | 841 | self.symbols.items[atom.sym_index].tag = .dead; |
| 824 | 842 | for (atom.locals.items) |local_atom| { |
| 825 | 843 | const local_symbol = &self.symbols.items[local_atom.sym_index]; |
| ... | ... | @@ -1414,8 +1432,8 @@ fn populateErrorNameTable(self: *Wasm) !void { |
| 1414 | 1432 | |
| 1415 | 1433 | // Addend for each relocation to the table |
| 1416 | 1434 | var addend: u32 = 0; |
| 1417 | const module = self.base.options.module.?; | |
| 1418 | for (module.error_name_list.items) |error_name| { | |
| 1435 | const mod = self.base.options.module.?; | |
| 1436 | for (mod.error_name_list.items) |error_name| { | |
| 1419 | 1437 | const len = @intCast(u32, error_name.len + 1); // names are 0-termianted |
| 1420 | 1438 | |
| 1421 | 1439 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| ... | ... | @@ -1456,9 +1474,11 @@ fn resetState(self: *Wasm) void { |
| 1456 | 1474 | for (self.segment_info.items) |*segment_info| { |
| 1457 | 1475 | self.base.allocator.free(segment_info.name); |
| 1458 | 1476 | } |
| 1477 | const mod = self.base.options.module.?; | |
| 1459 | 1478 | var decl_it = self.decls.keyIterator(); |
| 1460 | while (decl_it.next()) |decl| { | |
| 1461 | const atom = &decl.*.link.wasm; | |
| 1479 | while (decl_it.next()) |decl_index_ptr| { | |
| 1480 | const decl = mod.declPtr(decl_index_ptr.*); | |
| 1481 | const atom = &decl.link.wasm; | |
| 1462 | 1482 | atom.next = null; |
| 1463 | 1483 | atom.prev = null; |
| 1464 | 1484 | |
| ... | ... | @@ -1546,12 +1566,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1546 | 1566 | defer self.resetState(); |
| 1547 | 1567 | try self.setupStart(); |
| 1548 | 1568 | try self.setupImports(); |
| 1569 | const mod = self.base.options.module.?; | |
| 1549 | 1570 | var decl_it = self.decls.keyIterator(); |
| 1550 | while (decl_it.next()) |decl| { | |
| 1551 | if (decl.*.isExtern()) continue; | |
| 1571 | while (decl_it.next()) |decl_index_ptr| { | |
| 1572 | const decl = mod.declPtr(decl_index_ptr.*); | |
| 1573 | if (decl.isExtern()) continue; | |
| 1552 | 1574 | const atom = &decl.*.link.wasm; |
| 1553 | if (decl.*.ty.zigTypeTag() == .Fn) { | |
| 1554 | try self.parseAtom(atom, .{ .function = decl.*.fn_link.wasm }); | |
| 1575 | if (decl.ty.zigTypeTag() == .Fn) { | |
| 1576 | try self.parseAtom(atom, .{ .function = decl.fn_link.wasm }); | |
| 1555 | 1577 | } else { |
| 1556 | 1578 | try self.parseAtom(atom, .data); |
| 1557 | 1579 | } |
| ... | ... | @@ -2045,7 +2067,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 2045 | 2067 | |
| 2046 | 2068 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 2047 | 2069 | // will not be part of the linker line anyway. |
| 2048 | const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: { | |
| 2070 | const module_obj_path: ?[]const u8 = if (self.base.options.module) |mod| blk: { | |
| 2049 | 2071 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| 2050 | 2072 | if (use_stage1) { |
| 2051 | 2073 | const obj_basename = try std.zig.binNameAlloc(arena, .{ |
| ... | ... | @@ -2054,7 +2076,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 2054 | 2076 | .output_mode = .Obj, |
| 2055 | 2077 | }); |
| 2056 | 2078 | switch (self.base.options.cache_mode) { |
| 2057 | .incremental => break :blk try module.zig_cache_artifact_directory.join( | |
| 2079 | .incremental => break :blk try mod.zig_cache_artifact_directory.join( | |
| 2058 | 2080 | arena, |
| 2059 | 2081 | &[_][]const u8{obj_basename}, |
| 2060 | 2082 | ), |
| ... | ... | @@ -2253,7 +2275,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 2253 | 2275 | } |
| 2254 | 2276 | |
| 2255 | 2277 | if (auto_export_symbols) { |
| 2256 | if (self.base.options.module) |module| { | |
| 2278 | if (self.base.options.module) |mod| { | |
| 2257 | 2279 | // when we use stage1, we use the exports that stage1 provided us. |
| 2258 | 2280 | // For stage2, we can directly retrieve them from the module. |
| 2259 | 2281 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| ... | ... | @@ -2264,14 +2286,15 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 2264 | 2286 | } else { |
| 2265 | 2287 | const skip_export_non_fn = target.os.tag == .wasi and |
| 2266 | 2288 | self.base.options.wasi_exec_model == .command; |
| 2267 | for (module.decl_exports.values()) |exports| { | |
| 2289 | for (mod.decl_exports.values()) |exports| { | |
| 2268 | 2290 | for (exports) |exprt| { |
| 2269 | if (skip_export_non_fn and exprt.exported_decl.ty.zigTypeTag() != .Fn) { | |
| 2291 | const exported_decl = mod.declPtr(exprt.exported_decl); | |
| 2292 | if (skip_export_non_fn and exported_decl.ty.zigTypeTag() != .Fn) { | |
| 2270 | 2293 | // skip exporting symbols when we're building a WASI command |
| 2271 | 2294 | // and the symbol is not a function |
| 2272 | 2295 | continue; |
| 2273 | 2296 | } |
| 2274 | const symbol_name = exprt.exported_decl.name; | |
| 2297 | const symbol_name = exported_decl.name; | |
| 2275 | 2298 | const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}); |
| 2276 | 2299 | try argv.append(arg); |
| 2277 | 2300 | } |
src/main.zig+4-4| ... | ... | @@ -3892,7 +3892,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void |
| 3892 | 3892 | .tree_loaded = true, |
| 3893 | 3893 | .zir = undefined, |
| 3894 | 3894 | .pkg = undefined, |
| 3895 | .root_decl = null, | |
| 3895 | .root_decl = .none, | |
| 3896 | 3896 | }; |
| 3897 | 3897 | |
| 3898 | 3898 | file.pkg = try Package.create(gpa, null, file.sub_file_path); |
| ... | ... | @@ -4098,7 +4098,7 @@ fn fmtPathFile( |
| 4098 | 4098 | .tree_loaded = true, |
| 4099 | 4099 | .zir = undefined, |
| 4100 | 4100 | .pkg = undefined, |
| 4101 | .root_decl = null, | |
| 4101 | .root_decl = .none, | |
| 4102 | 4102 | }; |
| 4103 | 4103 | |
| 4104 | 4104 | file.pkg = try Package.create(fmt.gpa, null, file.sub_file_path); |
| ... | ... | @@ -4757,7 +4757,7 @@ pub fn cmdAstCheck( |
| 4757 | 4757 | .tree = undefined, |
| 4758 | 4758 | .zir = undefined, |
| 4759 | 4759 | .pkg = undefined, |
| 4760 | .root_decl = null, | |
| 4760 | .root_decl = .none, | |
| 4761 | 4761 | }; |
| 4762 | 4762 | if (zig_source_file) |file_name| { |
| 4763 | 4763 | var f = fs.cwd().openFile(file_name, .{}) catch |err| { |
| ... | ... | @@ -4910,7 +4910,7 @@ pub fn cmdChangelist( |
| 4910 | 4910 | .tree = undefined, |
| 4911 | 4911 | .zir = undefined, |
| 4912 | 4912 | .pkg = undefined, |
| 4913 | .root_decl = null, | |
| 4913 | .root_decl = .none, | |
| 4914 | 4914 | }; |
| 4915 | 4915 | |
| 4916 | 4916 | file.pkg = try Package.create(gpa, null, file.sub_file_path); |
src/print_air.zig+7-4| ... | ... | @@ -7,7 +7,7 @@ const Value = @import("value.zig").Value; |
| 7 | 7 | const Air = @import("Air.zig"); |
| 8 | 8 | const Liveness = @import("Liveness.zig"); |
| 9 | 9 | |
| 10 | pub fn dump(gpa: Allocator, air: Air, liveness: Liveness) void { | |
| 10 | pub fn dump(module: *Module, air: Air, liveness: Liveness) void { | |
| 11 | 11 | const instruction_bytes = air.instructions.len * |
| 12 | 12 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include |
| 13 | 13 | // the debug safety tag but we want to measure release size. |
| ... | ... | @@ -41,11 +41,12 @@ pub fn dump(gpa: Allocator, air: Air, liveness: Liveness) void { |
| 41 | 41 | liveness.special.count(), fmtIntSizeBin(liveness_special_bytes), |
| 42 | 42 | }); |
| 43 | 43 | // zig fmt: on |
| 44 | var arena = std.heap.ArenaAllocator.init(gpa); | |
| 44 | var arena = std.heap.ArenaAllocator.init(module.gpa); | |
| 45 | 45 | defer arena.deinit(); |
| 46 | 46 | |
| 47 | 47 | var writer: Writer = .{ |
| 48 | .gpa = gpa, | |
| 48 | .module = module, | |
| 49 | .gpa = module.gpa, | |
| 49 | 50 | .arena = arena.allocator(), |
| 50 | 51 | .air = air, |
| 51 | 52 | .liveness = liveness, |
| ... | ... | @@ -58,6 +59,7 @@ pub fn dump(gpa: Allocator, air: Air, liveness: Liveness) void { |
| 58 | 59 | } |
| 59 | 60 | |
| 60 | 61 | const Writer = struct { |
| 62 | module: *Module, | |
| 61 | 63 | gpa: Allocator, |
| 62 | 64 | arena: Allocator, |
| 63 | 65 | air: Air, |
| ... | ... | @@ -591,7 +593,8 @@ const Writer = struct { |
| 591 | 593 | fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 592 | 594 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; |
| 593 | 595 | const function = w.air.values[ty_pl.payload].castTag(.function).?.data; |
| 594 | try s.print("{s}", .{function.owner_decl.name}); | |
| 596 | const owner_decl = w.module.declPtr(function.owner_decl); | |
| 597 | try s.print("{s}", .{owner_decl.name}); | |
| 595 | 598 | } |
| 596 | 599 | |
| 597 | 600 | fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
src/type.zig+150-124| ... | ... | @@ -521,7 +521,7 @@ pub const Type = extern union { |
| 521 | 521 | } |
| 522 | 522 | } |
| 523 | 523 | |
| 524 | pub fn eql(a: Type, b: Type, target: Target) bool { | |
| 524 | pub fn eql(a: Type, b: Type, mod: *Module) bool { | |
| 525 | 525 | // As a shortcut, if the small tags / addresses match, we're done. |
| 526 | 526 | if (a.tag_if_small_enough == b.tag_if_small_enough) return true; |
| 527 | 527 | |
| ... | ... | @@ -637,7 +637,7 @@ pub const Type = extern union { |
| 637 | 637 | const a_info = a.fnInfo(); |
| 638 | 638 | const b_info = b.fnInfo(); |
| 639 | 639 | |
| 640 | if (!eql(a_info.return_type, b_info.return_type, target)) | |
| 640 | if (!eql(a_info.return_type, b_info.return_type, mod)) | |
| 641 | 641 | return false; |
| 642 | 642 | |
| 643 | 643 | if (a_info.cc != b_info.cc) |
| ... | ... | @@ -663,7 +663,7 @@ pub const Type = extern union { |
| 663 | 663 | if (a_param_ty.tag() == .generic_poison) continue; |
| 664 | 664 | if (b_param_ty.tag() == .generic_poison) continue; |
| 665 | 665 | |
| 666 | if (!eql(a_param_ty, b_param_ty, target)) | |
| 666 | if (!eql(a_param_ty, b_param_ty, mod)) | |
| 667 | 667 | return false; |
| 668 | 668 | } |
| 669 | 669 | |
| ... | ... | @@ -681,13 +681,13 @@ pub const Type = extern union { |
| 681 | 681 | if (a.arrayLen() != b.arrayLen()) |
| 682 | 682 | return false; |
| 683 | 683 | const elem_ty = a.elemType(); |
| 684 | if (!elem_ty.eql(b.elemType(), target)) | |
| 684 | if (!elem_ty.eql(b.elemType(), mod)) | |
| 685 | 685 | return false; |
| 686 | 686 | const sentinel_a = a.sentinel(); |
| 687 | 687 | const sentinel_b = b.sentinel(); |
| 688 | 688 | if (sentinel_a) |sa| { |
| 689 | 689 | if (sentinel_b) |sb| { |
| 690 | return sa.eql(sb, elem_ty, target); | |
| 690 | return sa.eql(sb, elem_ty, mod); | |
| 691 | 691 | } else { |
| 692 | 692 | return false; |
| 693 | 693 | } |
| ... | ... | @@ -718,7 +718,7 @@ pub const Type = extern union { |
| 718 | 718 | |
| 719 | 719 | const info_a = a.ptrInfo().data; |
| 720 | 720 | const info_b = b.ptrInfo().data; |
| 721 | if (!info_a.pointee_type.eql(info_b.pointee_type, target)) | |
| 721 | if (!info_a.pointee_type.eql(info_b.pointee_type, mod)) | |
| 722 | 722 | return false; |
| 723 | 723 | if (info_a.@"align" != info_b.@"align") |
| 724 | 724 | return false; |
| ... | ... | @@ -741,7 +741,7 @@ pub const Type = extern union { |
| 741 | 741 | const sentinel_b = info_b.sentinel; |
| 742 | 742 | if (sentinel_a) |sa| { |
| 743 | 743 | if (sentinel_b) |sb| { |
| 744 | if (!sa.eql(sb, info_a.pointee_type, target)) | |
| 744 | if (!sa.eql(sb, info_a.pointee_type, mod)) | |
| 745 | 745 | return false; |
| 746 | 746 | } else { |
| 747 | 747 | return false; |
| ... | ... | @@ -762,7 +762,7 @@ pub const Type = extern union { |
| 762 | 762 | |
| 763 | 763 | var buf_a: Payload.ElemType = undefined; |
| 764 | 764 | var buf_b: Payload.ElemType = undefined; |
| 765 | return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b), target); | |
| 765 | return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b), mod); | |
| 766 | 766 | }, |
| 767 | 767 | |
| 768 | 768 | .anyerror_void_error_union, .error_union => { |
| ... | ... | @@ -770,18 +770,18 @@ pub const Type = extern union { |
| 770 | 770 | |
| 771 | 771 | const a_set = a.errorUnionSet(); |
| 772 | 772 | const b_set = b.errorUnionSet(); |
| 773 | if (!a_set.eql(b_set, target)) return false; | |
| 773 | if (!a_set.eql(b_set, mod)) return false; | |
| 774 | 774 | |
| 775 | 775 | const a_payload = a.errorUnionPayload(); |
| 776 | 776 | const b_payload = b.errorUnionPayload(); |
| 777 | if (!a_payload.eql(b_payload, target)) return false; | |
| 777 | if (!a_payload.eql(b_payload, mod)) return false; | |
| 778 | 778 | |
| 779 | 779 | return true; |
| 780 | 780 | }, |
| 781 | 781 | |
| 782 | 782 | .anyframe_T => { |
| 783 | 783 | if (b.zigTypeTag() != .AnyFrame) return false; |
| 784 | return a.childType().eql(b.childType(), target); | |
| 784 | return a.childType().eql(b.childType(), mod); | |
| 785 | 785 | }, |
| 786 | 786 | |
| 787 | 787 | .empty_struct => { |
| ... | ... | @@ -804,7 +804,7 @@ pub const Type = extern union { |
| 804 | 804 | |
| 805 | 805 | for (a_tuple.types) |a_ty, i| { |
| 806 | 806 | const b_ty = b_tuple.types[i]; |
| 807 | if (!eql(a_ty, b_ty, target)) return false; | |
| 807 | if (!eql(a_ty, b_ty, mod)) return false; | |
| 808 | 808 | } |
| 809 | 809 | |
| 810 | 810 | for (a_tuple.values) |a_val, i| { |
| ... | ... | @@ -820,7 +820,7 @@ pub const Type = extern union { |
| 820 | 820 | if (b_val.tag() == .unreachable_value) { |
| 821 | 821 | return false; |
| 822 | 822 | } else { |
| 823 | if (!Value.eql(a_val, b_val, ty, target)) return false; | |
| 823 | if (!Value.eql(a_val, b_val, ty, mod)) return false; | |
| 824 | 824 | } |
| 825 | 825 | } |
| 826 | 826 | } |
| ... | ... | @@ -840,7 +840,7 @@ pub const Type = extern union { |
| 840 | 840 | |
| 841 | 841 | for (a_struct_obj.types) |a_ty, i| { |
| 842 | 842 | const b_ty = b_struct_obj.types[i]; |
| 843 | if (!eql(a_ty, b_ty, target)) return false; | |
| 843 | if (!eql(a_ty, b_ty, mod)) return false; | |
| 844 | 844 | } |
| 845 | 845 | |
| 846 | 846 | for (a_struct_obj.values) |a_val, i| { |
| ... | ... | @@ -856,7 +856,7 @@ pub const Type = extern union { |
| 856 | 856 | if (b_val.tag() == .unreachable_value) { |
| 857 | 857 | return false; |
| 858 | 858 | } else { |
| 859 | if (!Value.eql(a_val, b_val, ty, target)) return false; | |
| 859 | if (!Value.eql(a_val, b_val, ty, mod)) return false; | |
| 860 | 860 | } |
| 861 | 861 | } |
| 862 | 862 | } |
| ... | ... | @@ -911,13 +911,13 @@ pub const Type = extern union { |
| 911 | 911 | } |
| 912 | 912 | } |
| 913 | 913 | |
| 914 | pub fn hash(self: Type, target: Target) u64 { | |
| 914 | pub fn hash(self: Type, mod: *Module) u64 { | |
| 915 | 915 | var hasher = std.hash.Wyhash.init(0); |
| 916 | self.hashWithHasher(&hasher, target); | |
| 916 | self.hashWithHasher(&hasher, mod); | |
| 917 | 917 | return hasher.final(); |
| 918 | 918 | } |
| 919 | 919 | |
| 920 | pub fn hashWithHasher(ty: Type, hasher: *std.hash.Wyhash, target: Target) void { | |
| 920 | pub fn hashWithHasher(ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void { | |
| 921 | 921 | switch (ty.tag()) { |
| 922 | 922 | .generic_poison => unreachable, |
| 923 | 923 | |
| ... | ... | @@ -1036,7 +1036,7 @@ pub const Type = extern union { |
| 1036 | 1036 | std.hash.autoHash(hasher, std.builtin.TypeId.Fn); |
| 1037 | 1037 | |
| 1038 | 1038 | const fn_info = ty.fnInfo(); |
| 1039 | hashWithHasher(fn_info.return_type, hasher, target); | |
| 1039 | hashWithHasher(fn_info.return_type, hasher, mod); | |
| 1040 | 1040 | std.hash.autoHash(hasher, fn_info.alignment); |
| 1041 | 1041 | std.hash.autoHash(hasher, fn_info.cc); |
| 1042 | 1042 | std.hash.autoHash(hasher, fn_info.is_var_args); |
| ... | ... | @@ -1046,7 +1046,7 @@ pub const Type = extern union { |
| 1046 | 1046 | for (fn_info.param_types) |param_ty, i| { |
| 1047 | 1047 | std.hash.autoHash(hasher, fn_info.paramIsComptime(i)); |
| 1048 | 1048 | if (param_ty.tag() == .generic_poison) continue; |
| 1049 | hashWithHasher(param_ty, hasher, target); | |
| 1049 | hashWithHasher(param_ty, hasher, mod); | |
| 1050 | 1050 | } |
| 1051 | 1051 | }, |
| 1052 | 1052 | |
| ... | ... | @@ -1059,8 +1059,8 @@ pub const Type = extern union { |
| 1059 | 1059 | |
| 1060 | 1060 | const elem_ty = ty.elemType(); |
| 1061 | 1061 | std.hash.autoHash(hasher, ty.arrayLen()); |
| 1062 | hashWithHasher(elem_ty, hasher, target); | |
| 1063 | hashSentinel(ty.sentinel(), elem_ty, hasher, target); | |
| 1062 | hashWithHasher(elem_ty, hasher, mod); | |
| 1063 | hashSentinel(ty.sentinel(), elem_ty, hasher, mod); | |
| 1064 | 1064 | }, |
| 1065 | 1065 | |
| 1066 | 1066 | .vector => { |
| ... | ... | @@ -1068,7 +1068,7 @@ pub const Type = extern union { |
| 1068 | 1068 | |
| 1069 | 1069 | const elem_ty = ty.elemType(); |
| 1070 | 1070 | std.hash.autoHash(hasher, ty.vectorLen()); |
| 1071 | hashWithHasher(elem_ty, hasher, target); | |
| 1071 | hashWithHasher(elem_ty, hasher, mod); | |
| 1072 | 1072 | }, |
| 1073 | 1073 | |
| 1074 | 1074 | .single_const_pointer_to_comptime_int, |
| ... | ... | @@ -1092,8 +1092,8 @@ pub const Type = extern union { |
| 1092 | 1092 | std.hash.autoHash(hasher, std.builtin.TypeId.Pointer); |
| 1093 | 1093 | |
| 1094 | 1094 | const info = ty.ptrInfo().data; |
| 1095 | hashWithHasher(info.pointee_type, hasher, target); | |
| 1096 | hashSentinel(info.sentinel, info.pointee_type, hasher, target); | |
| 1095 | hashWithHasher(info.pointee_type, hasher, mod); | |
| 1096 | hashSentinel(info.sentinel, info.pointee_type, hasher, mod); | |
| 1097 | 1097 | std.hash.autoHash(hasher, info.@"align"); |
| 1098 | 1098 | std.hash.autoHash(hasher, info.@"addrspace"); |
| 1099 | 1099 | std.hash.autoHash(hasher, info.bit_offset); |
| ... | ... | @@ -1111,22 +1111,22 @@ pub const Type = extern union { |
| 1111 | 1111 | std.hash.autoHash(hasher, std.builtin.TypeId.Optional); |
| 1112 | 1112 | |
| 1113 | 1113 | var buf: Payload.ElemType = undefined; |
| 1114 | hashWithHasher(ty.optionalChild(&buf), hasher, target); | |
| 1114 | hashWithHasher(ty.optionalChild(&buf), hasher, mod); | |
| 1115 | 1115 | }, |
| 1116 | 1116 | |
| 1117 | 1117 | .anyerror_void_error_union, .error_union => { |
| 1118 | 1118 | std.hash.autoHash(hasher, std.builtin.TypeId.ErrorUnion); |
| 1119 | 1119 | |
| 1120 | 1120 | const set_ty = ty.errorUnionSet(); |
| 1121 | hashWithHasher(set_ty, hasher, target); | |
| 1121 | hashWithHasher(set_ty, hasher, mod); | |
| 1122 | 1122 | |
| 1123 | 1123 | const payload_ty = ty.errorUnionPayload(); |
| 1124 | hashWithHasher(payload_ty, hasher, target); | |
| 1124 | hashWithHasher(payload_ty, hasher, mod); | |
| 1125 | 1125 | }, |
| 1126 | 1126 | |
| 1127 | 1127 | .anyframe_T => { |
| 1128 | 1128 | std.hash.autoHash(hasher, std.builtin.TypeId.AnyFrame); |
| 1129 | hashWithHasher(ty.childType(), hasher, target); | |
| 1129 | hashWithHasher(ty.childType(), hasher, mod); | |
| 1130 | 1130 | }, |
| 1131 | 1131 | |
| 1132 | 1132 | .empty_struct => { |
| ... | ... | @@ -1145,10 +1145,10 @@ pub const Type = extern union { |
| 1145 | 1145 | std.hash.autoHash(hasher, tuple.types.len); |
| 1146 | 1146 | |
| 1147 | 1147 | for (tuple.types) |field_ty, i| { |
| 1148 | hashWithHasher(field_ty, hasher, target); | |
| 1148 | hashWithHasher(field_ty, hasher, mod); | |
| 1149 | 1149 | const field_val = tuple.values[i]; |
| 1150 | 1150 | if (field_val.tag() == .unreachable_value) continue; |
| 1151 | field_val.hash(field_ty, hasher, target); | |
| 1151 | field_val.hash(field_ty, hasher, mod); | |
| 1152 | 1152 | } |
| 1153 | 1153 | }, |
| 1154 | 1154 | .anon_struct => { |
| ... | ... | @@ -1160,9 +1160,9 @@ pub const Type = extern union { |
| 1160 | 1160 | const field_name = struct_obj.names[i]; |
| 1161 | 1161 | const field_val = struct_obj.values[i]; |
| 1162 | 1162 | hasher.update(field_name); |
| 1163 | hashWithHasher(field_ty, hasher, target); | |
| 1163 | hashWithHasher(field_ty, hasher, mod); | |
| 1164 | 1164 | if (field_val.tag() == .unreachable_value) continue; |
| 1165 | field_val.hash(field_ty, hasher, target); | |
| 1165 | field_val.hash(field_ty, hasher, mod); | |
| 1166 | 1166 | } |
| 1167 | 1167 | }, |
| 1168 | 1168 | |
| ... | ... | @@ -1210,35 +1210,35 @@ pub const Type = extern union { |
| 1210 | 1210 | } |
| 1211 | 1211 | } |
| 1212 | 1212 | |
| 1213 | fn hashSentinel(opt_val: ?Value, ty: Type, hasher: *std.hash.Wyhash, target: Target) void { | |
| 1213 | fn hashSentinel(opt_val: ?Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void { | |
| 1214 | 1214 | if (opt_val) |s| { |
| 1215 | 1215 | std.hash.autoHash(hasher, true); |
| 1216 | s.hash(ty, hasher, target); | |
| 1216 | s.hash(ty, hasher, mod); | |
| 1217 | 1217 | } else { |
| 1218 | 1218 | std.hash.autoHash(hasher, false); |
| 1219 | 1219 | } |
| 1220 | 1220 | } |
| 1221 | 1221 | |
| 1222 | 1222 | pub const HashContext64 = struct { |
| 1223 | target: Target, | |
| 1223 | mod: *Module, | |
| 1224 | 1224 | |
| 1225 | 1225 | pub fn hash(self: @This(), t: Type) u64 { |
| 1226 | return t.hash(self.target); | |
| 1226 | return t.hash(self.mod); | |
| 1227 | 1227 | } |
| 1228 | 1228 | pub fn eql(self: @This(), a: Type, b: Type) bool { |
| 1229 | return a.eql(b, self.target); | |
| 1229 | return a.eql(b, self.mod); | |
| 1230 | 1230 | } |
| 1231 | 1231 | }; |
| 1232 | 1232 | |
| 1233 | 1233 | pub const HashContext32 = struct { |
| 1234 | target: Target, | |
| 1234 | mod: *Module, | |
| 1235 | 1235 | |
| 1236 | 1236 | pub fn hash(self: @This(), t: Type) u32 { |
| 1237 | return @truncate(u32, t.hash(self.target)); | |
| 1237 | return @truncate(u32, t.hash(self.mod)); | |
| 1238 | 1238 | } |
| 1239 | 1239 | pub fn eql(self: @This(), a: Type, b: Type, b_index: usize) bool { |
| 1240 | 1240 | _ = b_index; |
| 1241 | return a.eql(b, self.target); | |
| 1241 | return a.eql(b, self.mod); | |
| 1242 | 1242 | } |
| 1243 | 1243 | }; |
| 1244 | 1244 | |
| ... | ... | @@ -1483,16 +1483,16 @@ pub const Type = extern union { |
| 1483 | 1483 | @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()"); |
| 1484 | 1484 | } |
| 1485 | 1485 | |
| 1486 | pub fn fmt(ty: Type, target: Target) std.fmt.Formatter(format2) { | |
| 1486 | pub fn fmt(ty: Type, module: *Module) std.fmt.Formatter(format2) { | |
| 1487 | 1487 | return .{ .data = .{ |
| 1488 | 1488 | .ty = ty, |
| 1489 | .target = target, | |
| 1489 | .module = module, | |
| 1490 | 1490 | } }; |
| 1491 | 1491 | } |
| 1492 | 1492 | |
| 1493 | 1493 | const FormatContext = struct { |
| 1494 | 1494 | ty: Type, |
| 1495 | target: Target, | |
| 1495 | module: *Module, | |
| 1496 | 1496 | }; |
| 1497 | 1497 | |
| 1498 | 1498 | fn format2( |
| ... | ... | @@ -1503,7 +1503,7 @@ pub const Type = extern union { |
| 1503 | 1503 | ) !void { |
| 1504 | 1504 | comptime assert(unused_format_string.len == 0); |
| 1505 | 1505 | _ = options; |
| 1506 | return print(ctx.ty, writer, ctx.target); | |
| 1506 | return print(ctx.ty, writer, ctx.module); | |
| 1507 | 1507 | } |
| 1508 | 1508 | |
| 1509 | 1509 | pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) { |
| ... | ... | @@ -1579,27 +1579,39 @@ pub const Type = extern union { |
| 1579 | 1579 | |
| 1580 | 1580 | .@"struct" => { |
| 1581 | 1581 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 1582 | return struct_obj.owner_decl.renderFullyQualifiedName(writer); | |
| 1582 | return writer.print("({s} decl={d})", .{ | |
| 1583 | @tagName(t), struct_obj.owner_decl, | |
| 1584 | }); | |
| 1583 | 1585 | }, |
| 1584 | 1586 | .@"union", .union_tagged => { |
| 1585 | 1587 | const union_obj = ty.cast(Payload.Union).?.data; |
| 1586 | return union_obj.owner_decl.renderFullyQualifiedName(writer); | |
| 1588 | return writer.print("({s} decl={d})", .{ | |
| 1589 | @tagName(t), union_obj.owner_decl, | |
| 1590 | }); | |
| 1587 | 1591 | }, |
| 1588 | 1592 | .enum_full, .enum_nonexhaustive => { |
| 1589 | 1593 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| 1590 | return enum_full.owner_decl.renderFullyQualifiedName(writer); | |
| 1594 | return writer.print("({s} decl={d})", .{ | |
| 1595 | @tagName(t), enum_full.owner_decl, | |
| 1596 | }); | |
| 1591 | 1597 | }, |
| 1592 | 1598 | .enum_simple => { |
| 1593 | 1599 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 1594 | return enum_simple.owner_decl.renderFullyQualifiedName(writer); | |
| 1600 | return writer.print("({s} decl={d})", .{ | |
| 1601 | @tagName(t), enum_simple.owner_decl, | |
| 1602 | }); | |
| 1595 | 1603 | }, |
| 1596 | 1604 | .enum_numbered => { |
| 1597 | 1605 | const enum_numbered = ty.castTag(.enum_numbered).?.data; |
| 1598 | return enum_numbered.owner_decl.renderFullyQualifiedName(writer); | |
| 1606 | return writer.print("({s} decl={d})", .{ | |
| 1607 | @tagName(t), enum_numbered.owner_decl, | |
| 1608 | }); | |
| 1599 | 1609 | }, |
| 1600 | 1610 | .@"opaque" => { |
| 1601 | // TODO use declaration name | |
| 1602 | return writer.writeAll("opaque {}"); | |
| 1611 | const opaque_obj = ty.castTag(.@"opaque").?.data; | |
| 1612 | return writer.print("({s} decl={d})", .{ | |
| 1613 | @tagName(t), opaque_obj.owner_decl, | |
| 1614 | }); | |
| 1603 | 1615 | }, |
| 1604 | 1616 | |
| 1605 | 1617 | .anyerror_void_error_union => return writer.writeAll("anyerror!void"), |
| ... | ... | @@ -1845,7 +1857,9 @@ pub const Type = extern union { |
| 1845 | 1857 | }, |
| 1846 | 1858 | .error_set_inferred => { |
| 1847 | 1859 | const func = ty.castTag(.error_set_inferred).?.data.func; |
| 1848 | return writer.print("@typeInfo(@typeInfo(@TypeOf({s})).Fn.return_type.?).ErrorUnion.error_set", .{func.owner_decl.name}); | |
| 1860 | return writer.print("({s} func={d})", .{ | |
| 1861 | @tagName(t), func.owner_decl, | |
| 1862 | }); | |
| 1849 | 1863 | }, |
| 1850 | 1864 | .error_set_merged => { |
| 1851 | 1865 | const names = ty.castTag(.error_set_merged).?.data.keys(); |
| ... | ... | @@ -1871,15 +1885,15 @@ pub const Type = extern union { |
| 1871 | 1885 | |
| 1872 | 1886 | pub const nameAllocArena = nameAlloc; |
| 1873 | 1887 | |
| 1874 | pub fn nameAlloc(ty: Type, ally: Allocator, target: Target) Allocator.Error![:0]const u8 { | |
| 1888 | pub fn nameAlloc(ty: Type, ally: Allocator, module: *Module) Allocator.Error![:0]const u8 { | |
| 1875 | 1889 | var buffer = std.ArrayList(u8).init(ally); |
| 1876 | 1890 | defer buffer.deinit(); |
| 1877 | try ty.print(buffer.writer(), target); | |
| 1891 | try ty.print(buffer.writer(), module); | |
| 1878 | 1892 | return buffer.toOwnedSliceSentinel(0); |
| 1879 | 1893 | } |
| 1880 | 1894 | |
| 1881 | 1895 | /// Prints a name suitable for `@typeName`. |
| 1882 | pub fn print(ty: Type, writer: anytype, target: Target) @TypeOf(writer).Error!void { | |
| 1896 | pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { | |
| 1883 | 1897 | const t = ty.tag(); |
| 1884 | 1898 | switch (t) { |
| 1885 | 1899 | .inferred_alloc_const => unreachable, |
| ... | ... | @@ -1946,32 +1960,38 @@ pub const Type = extern union { |
| 1946 | 1960 | |
| 1947 | 1961 | .empty_struct => { |
| 1948 | 1962 | const namespace = ty.castTag(.empty_struct).?.data; |
| 1949 | try namespace.renderFullyQualifiedName("", writer); | |
| 1963 | try namespace.renderFullyQualifiedName(mod, "", writer); | |
| 1950 | 1964 | }, |
| 1951 | 1965 | |
| 1952 | 1966 | .@"struct" => { |
| 1953 | 1967 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 1954 | try struct_obj.owner_decl.renderFullyQualifiedName(writer); | |
| 1968 | const decl = mod.declPtr(struct_obj.owner_decl); | |
| 1969 | try decl.renderFullyQualifiedName(mod, writer); | |
| 1955 | 1970 | }, |
| 1956 | 1971 | .@"union", .union_tagged => { |
| 1957 | 1972 | const union_obj = ty.cast(Payload.Union).?.data; |
| 1958 | try union_obj.owner_decl.renderFullyQualifiedName(writer); | |
| 1973 | const decl = mod.declPtr(union_obj.owner_decl); | |
| 1974 | try decl.renderFullyQualifiedName(mod, writer); | |
| 1959 | 1975 | }, |
| 1960 | 1976 | .enum_full, .enum_nonexhaustive => { |
| 1961 | 1977 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| 1962 | try enum_full.owner_decl.renderFullyQualifiedName(writer); | |
| 1978 | const decl = mod.declPtr(enum_full.owner_decl); | |
| 1979 | try decl.renderFullyQualifiedName(mod, writer); | |
| 1963 | 1980 | }, |
| 1964 | 1981 | .enum_simple => { |
| 1965 | 1982 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 1966 | try enum_simple.owner_decl.renderFullyQualifiedName(writer); | |
| 1983 | const decl = mod.declPtr(enum_simple.owner_decl); | |
| 1984 | try decl.renderFullyQualifiedName(mod, writer); | |
| 1967 | 1985 | }, |
| 1968 | 1986 | .enum_numbered => { |
| 1969 | 1987 | const enum_numbered = ty.castTag(.enum_numbered).?.data; |
| 1970 | try enum_numbered.owner_decl.renderFullyQualifiedName(writer); | |
| 1988 | const decl = mod.declPtr(enum_numbered.owner_decl); | |
| 1989 | try decl.renderFullyQualifiedName(mod, writer); | |
| 1971 | 1990 | }, |
| 1972 | 1991 | .@"opaque" => { |
| 1973 | 1992 | const opaque_obj = ty.cast(Payload.Opaque).?.data; |
| 1974 | try opaque_obj.owner_decl.renderFullyQualifiedName(writer); | |
| 1993 | const decl = mod.declPtr(opaque_obj.owner_decl); | |
| 1994 | try decl.renderFullyQualifiedName(mod, writer); | |
| 1975 | 1995 | }, |
| 1976 | 1996 | |
| 1977 | 1997 | .anyerror_void_error_union => try writer.writeAll("anyerror!void"), |
| ... | ... | @@ -1990,7 +2010,8 @@ pub const Type = extern union { |
| 1990 | 2010 | const func = ty.castTag(.error_set_inferred).?.data.func; |
| 1991 | 2011 | |
| 1992 | 2012 | try writer.writeAll("@typeInfo(@typeInfo(@TypeOf("); |
| 1993 | try func.owner_decl.renderFullyQualifiedName(writer); | |
| 2013 | const owner_decl = mod.declPtr(func.owner_decl); | |
| 2014 | try owner_decl.renderFullyQualifiedName(mod, writer); | |
| 1994 | 2015 | try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set"); |
| 1995 | 2016 | }, |
| 1996 | 2017 | |
| ... | ... | @@ -1999,7 +2020,7 @@ pub const Type = extern union { |
| 1999 | 2020 | try writer.writeAll("fn("); |
| 2000 | 2021 | for (fn_info.param_types) |param_ty, i| { |
| 2001 | 2022 | if (i != 0) try writer.writeAll(", "); |
| 2002 | try print(param_ty, writer, target); | |
| 2023 | try print(param_ty, writer, mod); | |
| 2003 | 2024 | } |
| 2004 | 2025 | if (fn_info.is_var_args) { |
| 2005 | 2026 | if (fn_info.param_types.len != 0) { |
| ... | ... | @@ -2016,14 +2037,14 @@ pub const Type = extern union { |
| 2016 | 2037 | if (fn_info.alignment != 0) { |
| 2017 | 2038 | try writer.print("align({d}) ", .{fn_info.alignment}); |
| 2018 | 2039 | } |
| 2019 | try print(fn_info.return_type, writer, target); | |
| 2040 | try print(fn_info.return_type, writer, mod); | |
| 2020 | 2041 | }, |
| 2021 | 2042 | |
| 2022 | 2043 | .error_union => { |
| 2023 | 2044 | const error_union = ty.castTag(.error_union).?.data; |
| 2024 | try print(error_union.error_set, writer, target); | |
| 2045 | try print(error_union.error_set, writer, mod); | |
| 2025 | 2046 | try writer.writeAll("!"); |
| 2026 | try print(error_union.payload, writer, target); | |
| 2047 | try print(error_union.payload, writer, mod); | |
| 2027 | 2048 | }, |
| 2028 | 2049 | |
| 2029 | 2050 | .array_u8 => { |
| ... | ... | @@ -2037,21 +2058,21 @@ pub const Type = extern union { |
| 2037 | 2058 | .vector => { |
| 2038 | 2059 | const payload = ty.castTag(.vector).?.data; |
| 2039 | 2060 | try writer.print("@Vector({d}, ", .{payload.len}); |
| 2040 | try print(payload.elem_type, writer, target); | |
| 2061 | try print(payload.elem_type, writer, mod); | |
| 2041 | 2062 | try writer.writeAll(")"); |
| 2042 | 2063 | }, |
| 2043 | 2064 | .array => { |
| 2044 | 2065 | const payload = ty.castTag(.array).?.data; |
| 2045 | 2066 | try writer.print("[{d}]", .{payload.len}); |
| 2046 | try print(payload.elem_type, writer, target); | |
| 2067 | try print(payload.elem_type, writer, mod); | |
| 2047 | 2068 | }, |
| 2048 | 2069 | .array_sentinel => { |
| 2049 | 2070 | const payload = ty.castTag(.array_sentinel).?.data; |
| 2050 | 2071 | try writer.print("[{d}:{}]", .{ |
| 2051 | 2072 | payload.len, |
| 2052 | payload.sentinel.fmtValue(payload.elem_type, target), | |
| 2073 | payload.sentinel.fmtValue(payload.elem_type, mod), | |
| 2053 | 2074 | }); |
| 2054 | try print(payload.elem_type, writer, target); | |
| 2075 | try print(payload.elem_type, writer, mod); | |
| 2055 | 2076 | }, |
| 2056 | 2077 | .tuple => { |
| 2057 | 2078 | const tuple = ty.castTag(.tuple).?.data; |
| ... | ... | @@ -2063,9 +2084,9 @@ pub const Type = extern union { |
| 2063 | 2084 | if (val.tag() != .unreachable_value) { |
| 2064 | 2085 | try writer.writeAll("comptime "); |
| 2065 | 2086 | } |
| 2066 | try print(field_ty, writer, target); | |
| 2087 | try print(field_ty, writer, mod); | |
| 2067 | 2088 | if (val.tag() != .unreachable_value) { |
| 2068 | try writer.print(" = {}", .{val.fmtValue(field_ty, target)}); | |
| 2089 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); | |
| 2069 | 2090 | } |
| 2070 | 2091 | } |
| 2071 | 2092 | try writer.writeAll("}"); |
| ... | ... | @@ -2083,10 +2104,10 @@ pub const Type = extern union { |
| 2083 | 2104 | try writer.writeAll(anon_struct.names[i]); |
| 2084 | 2105 | try writer.writeAll(": "); |
| 2085 | 2106 | |
| 2086 | try print(field_ty, writer, target); | |
| 2107 | try print(field_ty, writer, mod); | |
| 2087 | 2108 | |
| 2088 | 2109 | if (val.tag() != .unreachable_value) { |
| 2089 | try writer.print(" = {}", .{val.fmtValue(field_ty, target)}); | |
| 2110 | try writer.print(" = {}", .{val.fmtValue(field_ty, mod)}); | |
| 2090 | 2111 | } |
| 2091 | 2112 | } |
| 2092 | 2113 | try writer.writeAll("}"); |
| ... | ... | @@ -2106,8 +2127,8 @@ pub const Type = extern union { |
| 2106 | 2127 | |
| 2107 | 2128 | if (info.sentinel) |s| switch (info.size) { |
| 2108 | 2129 | .One, .C => unreachable, |
| 2109 | .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, target)}), | |
| 2110 | .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, target)}), | |
| 2130 | .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}), | |
| 2131 | .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}), | |
| 2111 | 2132 | } else switch (info.size) { |
| 2112 | 2133 | .One => try writer.writeAll("*"), |
| 2113 | 2134 | .Many => try writer.writeAll("[*]"), |
| ... | ... | @@ -2129,7 +2150,7 @@ pub const Type = extern union { |
| 2129 | 2150 | if (info.@"volatile") try writer.writeAll("volatile "); |
| 2130 | 2151 | if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero "); |
| 2131 | 2152 | |
| 2132 | try print(info.pointee_type, writer, target); | |
| 2153 | try print(info.pointee_type, writer, mod); | |
| 2133 | 2154 | }, |
| 2134 | 2155 | |
| 2135 | 2156 | .int_signed => { |
| ... | ... | @@ -2143,22 +2164,22 @@ pub const Type = extern union { |
| 2143 | 2164 | .optional => { |
| 2144 | 2165 | const child_type = ty.castTag(.optional).?.data; |
| 2145 | 2166 | try writer.writeByte('?'); |
| 2146 | try print(child_type, writer, target); | |
| 2167 | try print(child_type, writer, mod); | |
| 2147 | 2168 | }, |
| 2148 | 2169 | .optional_single_mut_pointer => { |
| 2149 | 2170 | const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data; |
| 2150 | 2171 | try writer.writeAll("?*"); |
| 2151 | try print(pointee_type, writer, target); | |
| 2172 | try print(pointee_type, writer, mod); | |
| 2152 | 2173 | }, |
| 2153 | 2174 | .optional_single_const_pointer => { |
| 2154 | 2175 | const pointee_type = ty.castTag(.optional_single_const_pointer).?.data; |
| 2155 | 2176 | try writer.writeAll("?*const "); |
| 2156 | try print(pointee_type, writer, target); | |
| 2177 | try print(pointee_type, writer, mod); | |
| 2157 | 2178 | }, |
| 2158 | 2179 | .anyframe_T => { |
| 2159 | 2180 | const return_type = ty.castTag(.anyframe_T).?.data; |
| 2160 | 2181 | try writer.print("anyframe->", .{}); |
| 2161 | try print(return_type, writer, target); | |
| 2182 | try print(return_type, writer, mod); | |
| 2162 | 2183 | }, |
| 2163 | 2184 | .error_set => { |
| 2164 | 2185 | const names = ty.castTag(.error_set).?.data.names.keys(); |
| ... | ... | @@ -3834,8 +3855,8 @@ pub const Type = extern union { |
| 3834 | 3855 | /// For [*]T, returns *T |
| 3835 | 3856 | /// For []T, returns *T |
| 3836 | 3857 | /// Handles const-ness and address spaces in particular. |
| 3837 | pub fn elemPtrType(ptr_ty: Type, arena: Allocator, target: Target) !Type { | |
| 3838 | return try Type.ptr(arena, target, .{ | |
| 3858 | pub fn elemPtrType(ptr_ty: Type, arena: Allocator, mod: *Module) !Type { | |
| 3859 | return try Type.ptr(arena, mod, .{ | |
| 3839 | 3860 | .pointee_type = ptr_ty.elemType2(), |
| 3840 | 3861 | .mutable = ptr_ty.ptrIsMutable(), |
| 3841 | 3862 | .@"addrspace" = ptr_ty.ptrAddressSpace(), |
| ... | ... | @@ -3948,9 +3969,9 @@ pub const Type = extern union { |
| 3948 | 3969 | return union_obj.fields; |
| 3949 | 3970 | } |
| 3950 | 3971 | |
| 3951 | pub fn unionFieldType(ty: Type, enum_tag: Value, target: Target) Type { | |
| 3972 | pub fn unionFieldType(ty: Type, enum_tag: Value, mod: *Module) Type { | |
| 3952 | 3973 | const union_obj = ty.cast(Payload.Union).?.data; |
| 3953 | const index = union_obj.tag_ty.enumTagFieldIndex(enum_tag, target).?; | |
| 3974 | const index = union_obj.tag_ty.enumTagFieldIndex(enum_tag, mod).?; | |
| 3954 | 3975 | assert(union_obj.haveFieldTypes()); |
| 3955 | 3976 | return union_obj.fields.values()[index].ty; |
| 3956 | 3977 | } |
| ... | ... | @@ -4970,20 +4991,20 @@ pub const Type = extern union { |
| 4970 | 4991 | /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or |
| 4971 | 4992 | /// an integer which represents the enum value. Returns the field index in |
| 4972 | 4993 | /// declaration order, or `null` if `enum_tag` does not match any field. |
| 4973 | pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, target: Target) ?usize { | |
| 4994 | pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?usize { | |
| 4974 | 4995 | if (enum_tag.castTag(.enum_field_index)) |payload| { |
| 4975 | 4996 | return @as(usize, payload.data); |
| 4976 | 4997 | } |
| 4977 | 4998 | const S = struct { |
| 4978 | fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, tg: Target) ?usize { | |
| 4999 | fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize { | |
| 4979 | 5000 | if (int_val.compareWithZero(.lt)) return null; |
| 4980 | 5001 | var end_payload: Value.Payload.U64 = .{ |
| 4981 | 5002 | .base = .{ .tag = .int_u64 }, |
| 4982 | 5003 | .data = end, |
| 4983 | 5004 | }; |
| 4984 | 5005 | const end_val = Value.initPayload(&end_payload.base); |
| 4985 | if (int_val.compare(.gte, end_val, int_ty, tg)) return null; | |
| 4986 | return @intCast(usize, int_val.toUnsignedInt(tg)); | |
| 5006 | if (int_val.compare(.gte, end_val, int_ty, m)) return null; | |
| 5007 | return @intCast(usize, int_val.toUnsignedInt(m.getTarget())); | |
| 4987 | 5008 | } |
| 4988 | 5009 | }; |
| 4989 | 5010 | switch (ty.tag()) { |
| ... | ... | @@ -4991,11 +5012,11 @@ pub const Type = extern union { |
| 4991 | 5012 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| 4992 | 5013 | const tag_ty = enum_full.tag_ty; |
| 4993 | 5014 | if (enum_full.values.count() == 0) { |
| 4994 | return S.fieldWithRange(tag_ty, enum_tag, enum_full.fields.count(), target); | |
| 5015 | return S.fieldWithRange(tag_ty, enum_tag, enum_full.fields.count(), mod); | |
| 4995 | 5016 | } else { |
| 4996 | 5017 | return enum_full.values.getIndexContext(enum_tag, .{ |
| 4997 | 5018 | .ty = tag_ty, |
| 4998 | .target = target, | |
| 5019 | .mod = mod, | |
| 4999 | 5020 | }); |
| 5000 | 5021 | } |
| 5001 | 5022 | }, |
| ... | ... | @@ -5003,11 +5024,11 @@ pub const Type = extern union { |
| 5003 | 5024 | const enum_obj = ty.castTag(.enum_numbered).?.data; |
| 5004 | 5025 | const tag_ty = enum_obj.tag_ty; |
| 5005 | 5026 | if (enum_obj.values.count() == 0) { |
| 5006 | return S.fieldWithRange(tag_ty, enum_tag, enum_obj.fields.count(), target); | |
| 5027 | return S.fieldWithRange(tag_ty, enum_tag, enum_obj.fields.count(), mod); | |
| 5007 | 5028 | } else { |
| 5008 | 5029 | return enum_obj.values.getIndexContext(enum_tag, .{ |
| 5009 | 5030 | .ty = tag_ty, |
| 5010 | .target = target, | |
| 5031 | .mod = mod, | |
| 5011 | 5032 | }); |
| 5012 | 5033 | } |
| 5013 | 5034 | }, |
| ... | ... | @@ -5020,7 +5041,7 @@ pub const Type = extern union { |
| 5020 | 5041 | .data = bits, |
| 5021 | 5042 | }; |
| 5022 | 5043 | const tag_ty = Type.initPayload(&buffer.base); |
| 5023 | return S.fieldWithRange(tag_ty, enum_tag, fields_len, target); | |
| 5044 | return S.fieldWithRange(tag_ty, enum_tag, fields_len, mod); | |
| 5024 | 5045 | }, |
| 5025 | 5046 | .atomic_order, |
| 5026 | 5047 | .atomic_rmw_op, |
| ... | ... | @@ -5224,32 +5245,35 @@ pub const Type = extern union { |
| 5224 | 5245 | } |
| 5225 | 5246 | } |
| 5226 | 5247 | |
| 5227 | pub fn declSrcLoc(ty: Type) Module.SrcLoc { | |
| 5228 | return declSrcLocOrNull(ty).?; | |
| 5248 | pub fn declSrcLoc(ty: Type, mod: *Module) Module.SrcLoc { | |
| 5249 | return declSrcLocOrNull(ty, mod).?; | |
| 5229 | 5250 | } |
| 5230 | 5251 | |
| 5231 | pub fn declSrcLocOrNull(ty: Type) ?Module.SrcLoc { | |
| 5252 | pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc { | |
| 5232 | 5253 | switch (ty.tag()) { |
| 5233 | 5254 | .enum_full, .enum_nonexhaustive => { |
| 5234 | 5255 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| 5235 | return enum_full.srcLoc(); | |
| 5256 | return enum_full.srcLoc(mod); | |
| 5257 | }, | |
| 5258 | .enum_numbered => { | |
| 5259 | const enum_numbered = ty.castTag(.enum_numbered).?.data; | |
| 5260 | return enum_numbered.srcLoc(mod); | |
| 5236 | 5261 | }, |
| 5237 | .enum_numbered => return ty.castTag(.enum_numbered).?.data.srcLoc(), | |
| 5238 | 5262 | .enum_simple => { |
| 5239 | 5263 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 5240 | return enum_simple.srcLoc(); | |
| 5264 | return enum_simple.srcLoc(mod); | |
| 5241 | 5265 | }, |
| 5242 | 5266 | .@"struct" => { |
| 5243 | 5267 | const struct_obj = ty.castTag(.@"struct").?.data; |
| 5244 | return struct_obj.srcLoc(); | |
| 5268 | return struct_obj.srcLoc(mod); | |
| 5245 | 5269 | }, |
| 5246 | 5270 | .error_set => { |
| 5247 | 5271 | const error_set = ty.castTag(.error_set).?.data; |
| 5248 | return error_set.srcLoc(); | |
| 5272 | return error_set.srcLoc(mod); | |
| 5249 | 5273 | }, |
| 5250 | 5274 | .@"union", .union_tagged => { |
| 5251 | 5275 | const union_obj = ty.cast(Payload.Union).?.data; |
| 5252 | return union_obj.srcLoc(); | |
| 5276 | return union_obj.srcLoc(mod); | |
| 5253 | 5277 | }, |
| 5254 | 5278 | .atomic_order, |
| 5255 | 5279 | .atomic_rmw_op, |
| ... | ... | @@ -5268,7 +5292,7 @@ pub const Type = extern union { |
| 5268 | 5292 | } |
| 5269 | 5293 | } |
| 5270 | 5294 | |
| 5271 | pub fn getOwnerDecl(ty: Type) *Module.Decl { | |
| 5295 | pub fn getOwnerDecl(ty: Type) Module.Decl.Index { | |
| 5272 | 5296 | switch (ty.tag()) { |
| 5273 | 5297 | .enum_full, .enum_nonexhaustive => { |
| 5274 | 5298 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| ... | ... | @@ -5357,30 +5381,30 @@ pub const Type = extern union { |
| 5357 | 5381 | } |
| 5358 | 5382 | |
| 5359 | 5383 | /// Asserts the type is an enum. |
| 5360 | pub fn enumHasInt(ty: Type, int: Value, target: Target) bool { | |
| 5384 | pub fn enumHasInt(ty: Type, int: Value, mod: *Module) bool { | |
| 5361 | 5385 | const S = struct { |
| 5362 | fn intInRange(tag_ty: Type, int_val: Value, end: usize, tg: Target) bool { | |
| 5386 | fn intInRange(tag_ty: Type, int_val: Value, end: usize, m: *Module) bool { | |
| 5363 | 5387 | if (int_val.compareWithZero(.lt)) return false; |
| 5364 | 5388 | var end_payload: Value.Payload.U64 = .{ |
| 5365 | 5389 | .base = .{ .tag = .int_u64 }, |
| 5366 | 5390 | .data = end, |
| 5367 | 5391 | }; |
| 5368 | 5392 | const end_val = Value.initPayload(&end_payload.base); |
| 5369 | if (int_val.compare(.gte, end_val, tag_ty, tg)) return false; | |
| 5393 | if (int_val.compare(.gte, end_val, tag_ty, m)) return false; | |
| 5370 | 5394 | return true; |
| 5371 | 5395 | } |
| 5372 | 5396 | }; |
| 5373 | 5397 | switch (ty.tag()) { |
| 5374 | .enum_nonexhaustive => return int.intFitsInType(ty, target), | |
| 5398 | .enum_nonexhaustive => return int.intFitsInType(ty, mod.getTarget()), | |
| 5375 | 5399 | .enum_full => { |
| 5376 | 5400 | const enum_full = ty.castTag(.enum_full).?.data; |
| 5377 | 5401 | const tag_ty = enum_full.tag_ty; |
| 5378 | 5402 | if (enum_full.values.count() == 0) { |
| 5379 | return S.intInRange(tag_ty, int, enum_full.fields.count(), target); | |
| 5403 | return S.intInRange(tag_ty, int, enum_full.fields.count(), mod); | |
| 5380 | 5404 | } else { |
| 5381 | 5405 | return enum_full.values.containsContext(int, .{ |
| 5382 | 5406 | .ty = tag_ty, |
| 5383 | .target = target, | |
| 5407 | .mod = mod, | |
| 5384 | 5408 | }); |
| 5385 | 5409 | } |
| 5386 | 5410 | }, |
| ... | ... | @@ -5388,11 +5412,11 @@ pub const Type = extern union { |
| 5388 | 5412 | const enum_obj = ty.castTag(.enum_numbered).?.data; |
| 5389 | 5413 | const tag_ty = enum_obj.tag_ty; |
| 5390 | 5414 | if (enum_obj.values.count() == 0) { |
| 5391 | return S.intInRange(tag_ty, int, enum_obj.fields.count(), target); | |
| 5415 | return S.intInRange(tag_ty, int, enum_obj.fields.count(), mod); | |
| 5392 | 5416 | } else { |
| 5393 | 5417 | return enum_obj.values.containsContext(int, .{ |
| 5394 | 5418 | .ty = tag_ty, |
| 5395 | .target = target, | |
| 5419 | .mod = mod, | |
| 5396 | 5420 | }); |
| 5397 | 5421 | } |
| 5398 | 5422 | }, |
| ... | ... | @@ -5405,7 +5429,7 @@ pub const Type = extern union { |
| 5405 | 5429 | .data = bits, |
| 5406 | 5430 | }; |
| 5407 | 5431 | const tag_ty = Type.initPayload(&buffer.base); |
| 5408 | return S.intInRange(tag_ty, int, fields_len, target); | |
| 5432 | return S.intInRange(tag_ty, int, fields_len, mod); | |
| 5409 | 5433 | }, |
| 5410 | 5434 | .atomic_order, |
| 5411 | 5435 | .atomic_rmw_op, |
| ... | ... | @@ -5937,7 +5961,9 @@ pub const Type = extern union { |
| 5937 | 5961 | pub const @"anyopaque" = initTag(.anyopaque); |
| 5938 | 5962 | pub const @"null" = initTag(.@"null"); |
| 5939 | 5963 | |
| 5940 | pub fn ptr(arena: Allocator, target: Target, data: Payload.Pointer.Data) !Type { | |
| 5964 | pub fn ptr(arena: Allocator, mod: *Module, data: Payload.Pointer.Data) !Type { | |
| 5965 | const target = mod.getTarget(); | |
| 5966 | ||
| 5941 | 5967 | var d = data; |
| 5942 | 5968 | |
| 5943 | 5969 | if (d.size == .C) { |
| ... | ... | @@ -5967,7 +5993,7 @@ pub const Type = extern union { |
| 5967 | 5993 | d.bit_offset == 0 and d.host_size == 0 and !d.@"allowzero" and !d.@"volatile") |
| 5968 | 5994 | { |
| 5969 | 5995 | if (d.sentinel) |sent| { |
| 5970 | if (!d.mutable and d.pointee_type.eql(Type.u8, target)) { | |
| 5996 | if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) { | |
| 5971 | 5997 | switch (d.size) { |
| 5972 | 5998 | .Slice => { |
| 5973 | 5999 | if (sent.compareWithZero(.eq)) { |
| ... | ... | @@ -5982,7 +6008,7 @@ pub const Type = extern union { |
| 5982 | 6008 | else => {}, |
| 5983 | 6009 | } |
| 5984 | 6010 | } |
| 5985 | } else if (!d.mutable and d.pointee_type.eql(Type.u8, target)) { | |
| 6011 | } else if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) { | |
| 5986 | 6012 | switch (d.size) { |
| 5987 | 6013 | .Slice => return Type.initTag(.const_slice_u8), |
| 5988 | 6014 | .Many => return Type.initTag(.manyptr_const_u8), |
| ... | ... | @@ -6016,11 +6042,11 @@ pub const Type = extern union { |
| 6016 | 6042 | len: u64, |
| 6017 | 6043 | sent: ?Value, |
| 6018 | 6044 | elem_type: Type, |
| 6019 | target: Target, | |
| 6045 | mod: *Module, | |
| 6020 | 6046 | ) Allocator.Error!Type { |
| 6021 | if (elem_type.eql(Type.u8, target)) { | |
| 6047 | if (elem_type.eql(Type.u8, mod)) { | |
| 6022 | 6048 | if (sent) |some| { |
| 6023 | if (some.eql(Value.zero, elem_type, target)) { | |
| 6049 | if (some.eql(Value.zero, elem_type, mod)) { | |
| 6024 | 6050 | return Tag.array_u8_sentinel_0.create(arena, len); |
| 6025 | 6051 | } |
| 6026 | 6052 | } else { |
| ... | ... | @@ -6067,11 +6093,11 @@ pub const Type = extern union { |
| 6067 | 6093 | arena: Allocator, |
| 6068 | 6094 | error_set: Type, |
| 6069 | 6095 | payload: Type, |
| 6070 | target: Target, | |
| 6096 | mod: *Module, | |
| 6071 | 6097 | ) Allocator.Error!Type { |
| 6072 | 6098 | assert(error_set.zigTypeTag() == .ErrorSet); |
| 6073 | if (error_set.eql(Type.@"anyerror", target) and | |
| 6074 | payload.eql(Type.void, target)) | |
| 6099 | if (error_set.eql(Type.@"anyerror", mod) and | |
| 6100 | payload.eql(Type.void, mod)) | |
| 6075 | 6101 | { |
| 6076 | 6102 | return Type.initTag(.anyerror_void_error_union); |
| 6077 | 6103 | } |
src/value.zig+122-139| ... | ... | @@ -731,16 +731,16 @@ pub const Value = extern union { |
| 731 | 731 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream), |
| 732 | 732 | .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), |
| 733 | 733 | .int_big_negative => return out_stream.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), |
| 734 | .function => return out_stream.print("(function '{s}')", .{val.castTag(.function).?.data.owner_decl.name}), | |
| 734 | .function => return out_stream.print("(function decl={d})", .{val.castTag(.function).?.data.owner_decl}), | |
| 735 | 735 | .extern_fn => return out_stream.writeAll("(extern function)"), |
| 736 | 736 | .variable => return out_stream.writeAll("(variable)"), |
| 737 | 737 | .decl_ref_mut => { |
| 738 | const decl = val.castTag(.decl_ref_mut).?.data.decl; | |
| 739 | return out_stream.print("(decl_ref_mut '{s}')", .{decl.name}); | |
| 738 | const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index; | |
| 739 | return out_stream.print("(decl_ref_mut {d})", .{decl_index}); | |
| 740 | 740 | }, |
| 741 | 741 | .decl_ref => { |
| 742 | const decl = val.castTag(.decl_ref).?.data; | |
| 743 | return out_stream.print("(decl ref '{s}')", .{decl.name}); | |
| 742 | const decl_index = val.castTag(.decl_ref).?.data; | |
| 743 | return out_stream.print("(decl_ref {d})", .{decl_index}); | |
| 744 | 744 | }, |
| 745 | 745 | .elem_ptr => { |
| 746 | 746 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| ... | ... | @@ -798,16 +798,17 @@ pub const Value = extern union { |
| 798 | 798 | return .{ .data = val }; |
| 799 | 799 | } |
| 800 | 800 | |
| 801 | pub fn fmtValue(val: Value, ty: Type, target: Target) std.fmt.Formatter(TypedValue.format) { | |
| 801 | pub fn fmtValue(val: Value, ty: Type, mod: *Module) std.fmt.Formatter(TypedValue.format) { | |
| 802 | 802 | return .{ .data = .{ |
| 803 | 803 | .tv = .{ .ty = ty, .val = val }, |
| 804 | .target = target, | |
| 804 | .mod = mod, | |
| 805 | 805 | } }; |
| 806 | 806 | } |
| 807 | 807 | |
| 808 | 808 | /// Asserts that the value is representable as an array of bytes. |
| 809 | 809 | /// Copies the value into a freshly allocated slice of memory, which is owned by the caller. |
| 810 | pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, target: Target) ![]u8 { | |
| 810 | pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module) ![]u8 { | |
| 811 | const target = mod.getTarget(); | |
| 811 | 812 | switch (val.tag()) { |
| 812 | 813 | .bytes => { |
| 813 | 814 | const bytes = val.castTag(.bytes).?.data; |
| ... | ... | @@ -823,25 +824,26 @@ pub const Value = extern union { |
| 823 | 824 | return result; |
| 824 | 825 | }, |
| 825 | 826 | .decl_ref => { |
| 826 | const decl = val.castTag(.decl_ref).?.data; | |
| 827 | const decl_index = val.castTag(.decl_ref).?.data; | |
| 828 | const decl = mod.declPtr(decl_index); | |
| 827 | 829 | const decl_val = try decl.value(); |
| 828 | return decl_val.toAllocatedBytes(decl.ty, allocator, target); | |
| 830 | return decl_val.toAllocatedBytes(decl.ty, allocator, mod); | |
| 829 | 831 | }, |
| 830 | 832 | .the_only_possible_value => return &[_]u8{}, |
| 831 | 833 | .slice => { |
| 832 | 834 | const slice = val.castTag(.slice).?.data; |
| 833 | return arrayToAllocatedBytes(slice.ptr, slice.len.toUnsignedInt(target), allocator, target); | |
| 835 | return arrayToAllocatedBytes(slice.ptr, slice.len.toUnsignedInt(target), allocator, mod); | |
| 834 | 836 | }, |
| 835 | else => return arrayToAllocatedBytes(val, ty.arrayLen(), allocator, target), | |
| 837 | else => return arrayToAllocatedBytes(val, ty.arrayLen(), allocator, mod), | |
| 836 | 838 | } |
| 837 | 839 | } |
| 838 | 840 | |
| 839 | fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, target: Target) ![]u8 { | |
| 841 | fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, mod: *Module) ![]u8 { | |
| 840 | 842 | const result = try allocator.alloc(u8, @intCast(usize, len)); |
| 841 | 843 | var elem_value_buf: ElemValueBuffer = undefined; |
| 842 | 844 | for (result) |*elem, i| { |
| 843 | const elem_val = val.elemValueBuffer(i, &elem_value_buf); | |
| 844 | elem.* = @intCast(u8, elem_val.toUnsignedInt(target)); | |
| 845 | const elem_val = val.elemValueBuffer(mod, i, &elem_value_buf); | |
| 846 | elem.* = @intCast(u8, elem_val.toUnsignedInt(mod.getTarget())); | |
| 845 | 847 | } |
| 846 | 848 | return result; |
| 847 | 849 | } |
| ... | ... | @@ -1164,7 +1166,7 @@ pub const Value = extern union { |
| 1164 | 1166 | var elem_value_buf: ElemValueBuffer = undefined; |
| 1165 | 1167 | var buf_off: usize = 0; |
| 1166 | 1168 | while (elem_i < len) : (elem_i += 1) { |
| 1167 | const elem_val = val.elemValueBuffer(elem_i, &elem_value_buf); | |
| 1169 | const elem_val = val.elemValueBuffer(mod, elem_i, &elem_value_buf); | |
| 1168 | 1170 | writeToMemory(elem_val, elem_ty, mod, buffer[buf_off..]); |
| 1169 | 1171 | buf_off += elem_size; |
| 1170 | 1172 | } |
| ... | ... | @@ -1975,34 +1977,47 @@ pub const Value = extern union { |
| 1975 | 1977 | |
| 1976 | 1978 | /// Asserts the values are comparable. Both operands have type `ty`. |
| 1977 | 1979 | /// Vector results will be reduced with AND. |
| 1978 | pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, target: Target) bool { | |
| 1980 | pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool { | |
| 1979 | 1981 | if (ty.zigTypeTag() == .Vector) { |
| 1980 | 1982 | var i: usize = 0; |
| 1981 | 1983 | while (i < ty.vectorLen()) : (i += 1) { |
| 1982 | if (!compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType(), target)) { | |
| 1984 | if (!compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType(), mod)) { | |
| 1983 | 1985 | return false; |
| 1984 | 1986 | } |
| 1985 | 1987 | } |
| 1986 | 1988 | return true; |
| 1987 | 1989 | } |
| 1988 | return compareScalar(lhs, op, rhs, ty, target); | |
| 1990 | return compareScalar(lhs, op, rhs, ty, mod); | |
| 1989 | 1991 | } |
| 1990 | 1992 | |
| 1991 | 1993 | /// Asserts the values are comparable. Both operands have type `ty`. |
| 1992 | pub fn compareScalar(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, target: Target) bool { | |
| 1994 | pub fn compareScalar( | |
| 1995 | lhs: Value, | |
| 1996 | op: std.math.CompareOperator, | |
| 1997 | rhs: Value, | |
| 1998 | ty: Type, | |
| 1999 | mod: *Module, | |
| 2000 | ) bool { | |
| 1993 | 2001 | return switch (op) { |
| 1994 | .eq => lhs.eql(rhs, ty, target), | |
| 1995 | .neq => !lhs.eql(rhs, ty, target), | |
| 1996 | else => compareHetero(lhs, op, rhs, target), | |
| 2002 | .eq => lhs.eql(rhs, ty, mod), | |
| 2003 | .neq => !lhs.eql(rhs, ty, mod), | |
| 2004 | else => compareHetero(lhs, op, rhs, mod.getTarget()), | |
| 1997 | 2005 | }; |
| 1998 | 2006 | } |
| 1999 | 2007 | |
| 2000 | 2008 | /// Asserts the values are comparable vectors of type `ty`. |
| 2001 | pub fn compareVector(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, allocator: Allocator, target: Target) !Value { | |
| 2009 | pub fn compareVector( | |
| 2010 | lhs: Value, | |
| 2011 | op: std.math.CompareOperator, | |
| 2012 | rhs: Value, | |
| 2013 | ty: Type, | |
| 2014 | allocator: Allocator, | |
| 2015 | mod: *Module, | |
| 2016 | ) !Value { | |
| 2002 | 2017 | assert(ty.zigTypeTag() == .Vector); |
| 2003 | 2018 | const result_data = try allocator.alloc(Value, ty.vectorLen()); |
| 2004 | 2019 | for (result_data) |*scalar, i| { |
| 2005 | const res_bool = compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType(), target); | |
| 2020 | const res_bool = compareScalar(lhs.indexVectorlike(i), op, rhs.indexVectorlike(i), ty.scalarType(), mod); | |
| 2006 | 2021 | scalar.* = if (res_bool) Value.@"true" else Value.@"false"; |
| 2007 | 2022 | } |
| 2008 | 2023 | return Value.Tag.aggregate.create(allocator, result_data); |
| ... | ... | @@ -2032,7 +2047,8 @@ pub const Value = extern union { |
| 2032 | 2047 | /// for `a`. This function must act *as if* `a` has been coerced to `ty`. This complication |
| 2033 | 2048 | /// is required in order to make generic function instantiation effecient - specifically |
| 2034 | 2049 | /// the insertion into the monomorphized function table. |
| 2035 | pub fn eql(a: Value, b: Value, ty: Type, target: Target) bool { | |
| 2050 | pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool { | |
| 2051 | const target = mod.getTarget(); | |
| 2036 | 2052 | const a_tag = a.tag(); |
| 2037 | 2053 | const b_tag = b.tag(); |
| 2038 | 2054 | if (a_tag == b_tag) switch (a_tag) { |
| ... | ... | @@ -2052,31 +2068,31 @@ pub const Value = extern union { |
| 2052 | 2068 | const a_payload = a.castTag(.opt_payload).?.data; |
| 2053 | 2069 | const b_payload = b.castTag(.opt_payload).?.data; |
| 2054 | 2070 | var buffer: Type.Payload.ElemType = undefined; |
| 2055 | return eql(a_payload, b_payload, ty.optionalChild(&buffer), target); | |
| 2071 | return eql(a_payload, b_payload, ty.optionalChild(&buffer), mod); | |
| 2056 | 2072 | }, |
| 2057 | 2073 | .slice => { |
| 2058 | 2074 | const a_payload = a.castTag(.slice).?.data; |
| 2059 | 2075 | const b_payload = b.castTag(.slice).?.data; |
| 2060 | if (!eql(a_payload.len, b_payload.len, Type.usize, target)) return false; | |
| 2076 | if (!eql(a_payload.len, b_payload.len, Type.usize, mod)) return false; | |
| 2061 | 2077 | |
| 2062 | 2078 | var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 2063 | 2079 | const ptr_ty = ty.slicePtrFieldType(&ptr_buf); |
| 2064 | 2080 | |
| 2065 | return eql(a_payload.ptr, b_payload.ptr, ptr_ty, target); | |
| 2081 | return eql(a_payload.ptr, b_payload.ptr, ptr_ty, mod); | |
| 2066 | 2082 | }, |
| 2067 | 2083 | .elem_ptr => { |
| 2068 | 2084 | const a_payload = a.castTag(.elem_ptr).?.data; |
| 2069 | 2085 | const b_payload = b.castTag(.elem_ptr).?.data; |
| 2070 | 2086 | if (a_payload.index != b_payload.index) return false; |
| 2071 | 2087 | |
| 2072 | return eql(a_payload.array_ptr, b_payload.array_ptr, ty, target); | |
| 2088 | return eql(a_payload.array_ptr, b_payload.array_ptr, ty, mod); | |
| 2073 | 2089 | }, |
| 2074 | 2090 | .field_ptr => { |
| 2075 | 2091 | const a_payload = a.castTag(.field_ptr).?.data; |
| 2076 | 2092 | const b_payload = b.castTag(.field_ptr).?.data; |
| 2077 | 2093 | if (a_payload.field_index != b_payload.field_index) return false; |
| 2078 | 2094 | |
| 2079 | return eql(a_payload.container_ptr, b_payload.container_ptr, ty, target); | |
| 2095 | return eql(a_payload.container_ptr, b_payload.container_ptr, ty, mod); | |
| 2080 | 2096 | }, |
| 2081 | 2097 | .@"error" => { |
| 2082 | 2098 | const a_name = a.castTag(.@"error").?.data.name; |
| ... | ... | @@ -2086,7 +2102,7 @@ pub const Value = extern union { |
| 2086 | 2102 | .eu_payload => { |
| 2087 | 2103 | const a_payload = a.castTag(.eu_payload).?.data; |
| 2088 | 2104 | const b_payload = b.castTag(.eu_payload).?.data; |
| 2089 | return eql(a_payload, b_payload, ty.errorUnionPayload(), target); | |
| 2105 | return eql(a_payload, b_payload, ty.errorUnionPayload(), mod); | |
| 2090 | 2106 | }, |
| 2091 | 2107 | .eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"), |
| 2092 | 2108 | .opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"), |
| ... | ... | @@ -2104,7 +2120,7 @@ pub const Value = extern union { |
| 2104 | 2120 | const types = ty.tupleFields().types; |
| 2105 | 2121 | assert(types.len == a_field_vals.len); |
| 2106 | 2122 | for (types) |field_ty, i| { |
| 2107 | if (!eql(a_field_vals[i], b_field_vals[i], field_ty, target)) return false; | |
| 2123 | if (!eql(a_field_vals[i], b_field_vals[i], field_ty, mod)) return false; | |
| 2108 | 2124 | } |
| 2109 | 2125 | return true; |
| 2110 | 2126 | } |
| ... | ... | @@ -2113,7 +2129,7 @@ pub const Value = extern union { |
| 2113 | 2129 | const fields = ty.structFields().values(); |
| 2114 | 2130 | assert(fields.len == a_field_vals.len); |
| 2115 | 2131 | for (fields) |field, i| { |
| 2116 | if (!eql(a_field_vals[i], b_field_vals[i], field.ty, target)) return false; | |
| 2132 | if (!eql(a_field_vals[i], b_field_vals[i], field.ty, mod)) return false; | |
| 2117 | 2133 | } |
| 2118 | 2134 | return true; |
| 2119 | 2135 | } |
| ... | ... | @@ -2122,7 +2138,7 @@ pub const Value = extern union { |
| 2122 | 2138 | for (a_field_vals) |a_elem, i| { |
| 2123 | 2139 | const b_elem = b_field_vals[i]; |
| 2124 | 2140 | |
| 2125 | if (!eql(a_elem, b_elem, elem_ty, target)) return false; | |
| 2141 | if (!eql(a_elem, b_elem, elem_ty, mod)) return false; | |
| 2126 | 2142 | } |
| 2127 | 2143 | return true; |
| 2128 | 2144 | }, |
| ... | ... | @@ -2132,7 +2148,7 @@ pub const Value = extern union { |
| 2132 | 2148 | switch (ty.containerLayout()) { |
| 2133 | 2149 | .Packed, .Extern => { |
| 2134 | 2150 | const tag_ty = ty.unionTagTypeHypothetical(); |
| 2135 | if (!a_union.tag.eql(b_union.tag, tag_ty, target)) { | |
| 2151 | if (!a_union.tag.eql(b_union.tag, tag_ty, mod)) { | |
| 2136 | 2152 | // In this case, we must disregard mismatching tags and compare |
| 2137 | 2153 | // based on the in-memory bytes of the payloads. |
| 2138 | 2154 | @panic("TODO comptime comparison of extern union values with mismatching tags"); |
| ... | ... | @@ -2140,13 +2156,13 @@ pub const Value = extern union { |
| 2140 | 2156 | }, |
| 2141 | 2157 | .Auto => { |
| 2142 | 2158 | const tag_ty = ty.unionTagTypeHypothetical(); |
| 2143 | if (!a_union.tag.eql(b_union.tag, tag_ty, target)) { | |
| 2159 | if (!a_union.tag.eql(b_union.tag, tag_ty, mod)) { | |
| 2144 | 2160 | return false; |
| 2145 | 2161 | } |
| 2146 | 2162 | }, |
| 2147 | 2163 | } |
| 2148 | const active_field_ty = ty.unionFieldType(a_union.tag, target); | |
| 2149 | return a_union.val.eql(b_union.val, active_field_ty, target); | |
| 2164 | const active_field_ty = ty.unionFieldType(a_union.tag, mod); | |
| 2165 | return a_union.val.eql(b_union.val, active_field_ty, mod); | |
| 2150 | 2166 | }, |
| 2151 | 2167 | else => {}, |
| 2152 | 2168 | } else if (a_tag == .null_value or b_tag == .null_value) { |
| ... | ... | @@ -2171,7 +2187,7 @@ pub const Value = extern union { |
| 2171 | 2187 | var buf_b: ToTypeBuffer = undefined; |
| 2172 | 2188 | const a_type = a.toType(&buf_a); |
| 2173 | 2189 | const b_type = b.toType(&buf_b); |
| 2174 | return a_type.eql(b_type, target); | |
| 2190 | return a_type.eql(b_type, mod); | |
| 2175 | 2191 | }, |
| 2176 | 2192 | .Enum => { |
| 2177 | 2193 | var buf_a: Payload.U64 = undefined; |
| ... | ... | @@ -2180,7 +2196,7 @@ pub const Value = extern union { |
| 2180 | 2196 | const b_val = b.enumToInt(ty, &buf_b); |
| 2181 | 2197 | var buf_ty: Type.Payload.Bits = undefined; |
| 2182 | 2198 | const int_ty = ty.intTagType(&buf_ty); |
| 2183 | return eql(a_val, b_val, int_ty, target); | |
| 2199 | return eql(a_val, b_val, int_ty, mod); | |
| 2184 | 2200 | }, |
| 2185 | 2201 | .Array, .Vector => { |
| 2186 | 2202 | const len = ty.arrayLen(); |
| ... | ... | @@ -2189,9 +2205,9 @@ pub const Value = extern union { |
| 2189 | 2205 | var a_buf: ElemValueBuffer = undefined; |
| 2190 | 2206 | var b_buf: ElemValueBuffer = undefined; |
| 2191 | 2207 | while (i < len) : (i += 1) { |
| 2192 | const a_elem = elemValueBuffer(a, i, &a_buf); | |
| 2193 | const b_elem = elemValueBuffer(b, i, &b_buf); | |
| 2194 | if (!eql(a_elem, b_elem, elem_ty, target)) return false; | |
| 2208 | const a_elem = elemValueBuffer(a, mod, i, &a_buf); | |
| 2209 | const b_elem = elemValueBuffer(b, mod, i, &b_buf); | |
| 2210 | if (!eql(a_elem, b_elem, elem_ty, mod)) return false; | |
| 2195 | 2211 | } |
| 2196 | 2212 | return true; |
| 2197 | 2213 | }, |
| ... | ... | @@ -2215,7 +2231,7 @@ pub const Value = extern union { |
| 2215 | 2231 | .base = .{ .tag = .opt_payload }, |
| 2216 | 2232 | .data = a, |
| 2217 | 2233 | }; |
| 2218 | return eql(Value.initPayload(&buffer.base), b, ty, target); | |
| 2234 | return eql(Value.initPayload(&buffer.base), b, ty, mod); | |
| 2219 | 2235 | } |
| 2220 | 2236 | }, |
| 2221 | 2237 | else => {}, |
| ... | ... | @@ -2225,7 +2241,7 @@ pub const Value = extern union { |
| 2225 | 2241 | |
| 2226 | 2242 | /// This function is used by hash maps and so treats floating-point NaNs as equal |
| 2227 | 2243 | /// to each other, and not equal to other floating-point values. |
| 2228 | pub fn hash(val: Value, ty: Type, hasher: *std.hash.Wyhash, target: Target) void { | |
| 2244 | pub fn hash(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void { | |
| 2229 | 2245 | const zig_ty_tag = ty.zigTypeTag(); |
| 2230 | 2246 | std.hash.autoHash(hasher, zig_ty_tag); |
| 2231 | 2247 | if (val.isUndef()) return; |
| ... | ... | @@ -2242,7 +2258,7 @@ pub const Value = extern union { |
| 2242 | 2258 | |
| 2243 | 2259 | .Type => { |
| 2244 | 2260 | var buf: ToTypeBuffer = undefined; |
| 2245 | return val.toType(&buf).hashWithHasher(hasher, target); | |
| 2261 | return val.toType(&buf).hashWithHasher(hasher, mod); | |
| 2246 | 2262 | }, |
| 2247 | 2263 | .Float, .ComptimeFloat => { |
| 2248 | 2264 | // Normalize the float here because this hash must match eql semantics. |
| ... | ... | @@ -2263,11 +2279,11 @@ pub const Value = extern union { |
| 2263 | 2279 | const slice = val.castTag(.slice).?.data; |
| 2264 | 2280 | var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 2265 | 2281 | const ptr_ty = ty.slicePtrFieldType(&ptr_buf); |
| 2266 | hash(slice.ptr, ptr_ty, hasher, target); | |
| 2267 | hash(slice.len, Type.usize, hasher, target); | |
| 2282 | hash(slice.ptr, ptr_ty, hasher, mod); | |
| 2283 | hash(slice.len, Type.usize, hasher, mod); | |
| 2268 | 2284 | }, |
| 2269 | 2285 | |
| 2270 | else => return hashPtr(val, hasher, target), | |
| 2286 | else => return hashPtr(val, hasher, mod.getTarget()), | |
| 2271 | 2287 | }, |
| 2272 | 2288 | .Array, .Vector => { |
| 2273 | 2289 | const len = ty.arrayLen(); |
| ... | ... | @@ -2275,15 +2291,15 @@ pub const Value = extern union { |
| 2275 | 2291 | var index: usize = 0; |
| 2276 | 2292 | var elem_value_buf: ElemValueBuffer = undefined; |
| 2277 | 2293 | while (index < len) : (index += 1) { |
| 2278 | const elem_val = val.elemValueBuffer(index, &elem_value_buf); | |
| 2279 | elem_val.hash(elem_ty, hasher, target); | |
| 2294 | const elem_val = val.elemValueBuffer(mod, index, &elem_value_buf); | |
| 2295 | elem_val.hash(elem_ty, hasher, mod); | |
| 2280 | 2296 | } |
| 2281 | 2297 | }, |
| 2282 | 2298 | .Struct => { |
| 2283 | 2299 | if (ty.isTupleOrAnonStruct()) { |
| 2284 | 2300 | const fields = ty.tupleFields(); |
| 2285 | 2301 | for (fields.values) |field_val, i| { |
| 2286 | field_val.hash(fields.types[i], hasher, target); | |
| 2302 | field_val.hash(fields.types[i], hasher, mod); | |
| 2287 | 2303 | } |
| 2288 | 2304 | return; |
| 2289 | 2305 | } |
| ... | ... | @@ -2292,13 +2308,13 @@ pub const Value = extern union { |
| 2292 | 2308 | switch (val.tag()) { |
| 2293 | 2309 | .empty_struct_value => { |
| 2294 | 2310 | for (fields) |field| { |
| 2295 | field.default_val.hash(field.ty, hasher, target); | |
| 2311 | field.default_val.hash(field.ty, hasher, mod); | |
| 2296 | 2312 | } |
| 2297 | 2313 | }, |
| 2298 | 2314 | .aggregate => { |
| 2299 | 2315 | const field_values = val.castTag(.aggregate).?.data; |
| 2300 | 2316 | for (field_values) |field_val, i| { |
| 2301 | field_val.hash(fields[i].ty, hasher, target); | |
| 2317 | field_val.hash(fields[i].ty, hasher, mod); | |
| 2302 | 2318 | } |
| 2303 | 2319 | }, |
| 2304 | 2320 | else => unreachable, |
| ... | ... | @@ -2310,7 +2326,7 @@ pub const Value = extern union { |
| 2310 | 2326 | const sub_val = payload.data; |
| 2311 | 2327 | var buffer: Type.Payload.ElemType = undefined; |
| 2312 | 2328 | const sub_ty = ty.optionalChild(&buffer); |
| 2313 | sub_val.hash(sub_ty, hasher, target); | |
| 2329 | sub_val.hash(sub_ty, hasher, mod); | |
| 2314 | 2330 | } else { |
| 2315 | 2331 | std.hash.autoHash(hasher, false); // non-null |
| 2316 | 2332 | } |
| ... | ... | @@ -2319,14 +2335,14 @@ pub const Value = extern union { |
| 2319 | 2335 | if (val.tag() == .@"error") { |
| 2320 | 2336 | std.hash.autoHash(hasher, false); // error |
| 2321 | 2337 | const sub_ty = ty.errorUnionSet(); |
| 2322 | val.hash(sub_ty, hasher, target); | |
| 2338 | val.hash(sub_ty, hasher, mod); | |
| 2323 | 2339 | return; |
| 2324 | 2340 | } |
| 2325 | 2341 | |
| 2326 | 2342 | if (val.castTag(.eu_payload)) |payload| { |
| 2327 | 2343 | std.hash.autoHash(hasher, true); // payload |
| 2328 | 2344 | const sub_ty = ty.errorUnionPayload(); |
| 2329 | payload.data.hash(sub_ty, hasher, target); | |
| 2345 | payload.data.hash(sub_ty, hasher, mod); | |
| 2330 | 2346 | return; |
| 2331 | 2347 | } else unreachable; |
| 2332 | 2348 | }, |
| ... | ... | @@ -2339,15 +2355,15 @@ pub const Value = extern union { |
| 2339 | 2355 | .Enum => { |
| 2340 | 2356 | var enum_space: Payload.U64 = undefined; |
| 2341 | 2357 | const int_val = val.enumToInt(ty, &enum_space); |
| 2342 | hashInt(int_val, hasher, target); | |
| 2358 | hashInt(int_val, hasher, mod.getTarget()); | |
| 2343 | 2359 | }, |
| 2344 | 2360 | .Union => { |
| 2345 | 2361 | const union_obj = val.cast(Payload.Union).?.data; |
| 2346 | 2362 | if (ty.unionTagType()) |tag_ty| { |
| 2347 | union_obj.tag.hash(tag_ty, hasher, target); | |
| 2363 | union_obj.tag.hash(tag_ty, hasher, mod); | |
| 2348 | 2364 | } |
| 2349 | const active_field_ty = ty.unionFieldType(union_obj.tag, target); | |
| 2350 | union_obj.val.hash(active_field_ty, hasher, target); | |
| 2365 | const active_field_ty = ty.unionFieldType(union_obj.tag, mod); | |
| 2366 | union_obj.val.hash(active_field_ty, hasher, mod); | |
| 2351 | 2367 | }, |
| 2352 | 2368 | .Fn => { |
| 2353 | 2369 | const func: *Module.Fn = val.castTag(.function).?.data; |
| ... | ... | @@ -2372,30 +2388,30 @@ pub const Value = extern union { |
| 2372 | 2388 | |
| 2373 | 2389 | pub const ArrayHashContext = struct { |
| 2374 | 2390 | ty: Type, |
| 2375 | target: Target, | |
| 2391 | mod: *Module, | |
| 2376 | 2392 | |
| 2377 | 2393 | pub fn hash(self: @This(), val: Value) u32 { |
| 2378 | const other_context: HashContext = .{ .ty = self.ty, .target = self.target }; | |
| 2394 | const other_context: HashContext = .{ .ty = self.ty, .mod = self.mod }; | |
| 2379 | 2395 | return @truncate(u32, other_context.hash(val)); |
| 2380 | 2396 | } |
| 2381 | 2397 | pub fn eql(self: @This(), a: Value, b: Value, b_index: usize) bool { |
| 2382 | 2398 | _ = b_index; |
| 2383 | return a.eql(b, self.ty, self.target); | |
| 2399 | return a.eql(b, self.ty, self.mod); | |
| 2384 | 2400 | } |
| 2385 | 2401 | }; |
| 2386 | 2402 | |
| 2387 | 2403 | pub const HashContext = struct { |
| 2388 | 2404 | ty: Type, |
| 2389 | target: Target, | |
| 2405 | mod: *Module, | |
| 2390 | 2406 | |
| 2391 | 2407 | pub fn hash(self: @This(), val: Value) u64 { |
| 2392 | 2408 | var hasher = std.hash.Wyhash.init(0); |
| 2393 | val.hash(self.ty, &hasher, self.target); | |
| 2409 | val.hash(self.ty, &hasher, self.mod); | |
| 2394 | 2410 | return hasher.final(); |
| 2395 | 2411 | } |
| 2396 | 2412 | |
| 2397 | 2413 | pub fn eql(self: @This(), a: Value, b: Value) bool { |
| 2398 | return a.eql(b, self.ty, self.target); | |
| 2414 | return a.eql(b, self.ty, self.mod); | |
| 2399 | 2415 | } |
| 2400 | 2416 | }; |
| 2401 | 2417 | |
| ... | ... | @@ -2434,9 +2450,9 @@ pub const Value = extern union { |
| 2434 | 2450 | /// Gets the decl referenced by this pointer. If the pointer does not point |
| 2435 | 2451 | /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr), |
| 2436 | 2452 | /// this function returns null. |
| 2437 | pub fn pointerDecl(val: Value) ?*Module.Decl { | |
| 2453 | pub fn pointerDecl(val: Value) ?Module.Decl.Index { | |
| 2438 | 2454 | return switch (val.tag()) { |
| 2439 | .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl, | |
| 2455 | .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl_index, | |
| 2440 | 2456 | .extern_fn => val.castTag(.extern_fn).?.data.owner_decl, |
| 2441 | 2457 | .function => val.castTag(.function).?.data.owner_decl, |
| 2442 | 2458 | .variable => val.castTag(.variable).?.data.owner_decl, |
| ... | ... | @@ -2462,7 +2478,7 @@ pub const Value = extern union { |
| 2462 | 2478 | .function, |
| 2463 | 2479 | .variable, |
| 2464 | 2480 | => { |
| 2465 | const decl: *Module.Decl = ptr_val.pointerDecl().?; | |
| 2481 | const decl: Module.Decl.Index = ptr_val.pointerDecl().?; | |
| 2466 | 2482 | std.hash.autoHash(hasher, decl); |
| 2467 | 2483 | }, |
| 2468 | 2484 | |
| ... | ... | @@ -2505,53 +2521,6 @@ pub const Value = extern union { |
| 2505 | 2521 | } |
| 2506 | 2522 | } |
| 2507 | 2523 | |
| 2508 | pub fn markReferencedDeclsAlive(val: Value) void { | |
| 2509 | switch (val.tag()) { | |
| 2510 | .decl_ref_mut => return val.castTag(.decl_ref_mut).?.data.decl.markAlive(), | |
| 2511 | .extern_fn => return val.castTag(.extern_fn).?.data.owner_decl.markAlive(), | |
| 2512 | .function => return val.castTag(.function).?.data.owner_decl.markAlive(), | |
| 2513 | .variable => return val.castTag(.variable).?.data.owner_decl.markAlive(), | |
| 2514 | .decl_ref => return val.cast(Payload.Decl).?.data.markAlive(), | |
| 2515 | ||
| 2516 | .repeated, | |
| 2517 | .eu_payload, | |
| 2518 | .opt_payload, | |
| 2519 | .empty_array_sentinel, | |
| 2520 | => return markReferencedDeclsAlive(val.cast(Payload.SubValue).?.data), | |
| 2521 | ||
| 2522 | .eu_payload_ptr, | |
| 2523 | .opt_payload_ptr, | |
| 2524 | => return markReferencedDeclsAlive(val.cast(Payload.PayloadPtr).?.data.container_ptr), | |
| 2525 | ||
| 2526 | .slice => { | |
| 2527 | const slice = val.cast(Payload.Slice).?.data; | |
| 2528 | markReferencedDeclsAlive(slice.ptr); | |
| 2529 | markReferencedDeclsAlive(slice.len); | |
| 2530 | }, | |
| 2531 | ||
| 2532 | .elem_ptr => { | |
| 2533 | const elem_ptr = val.cast(Payload.ElemPtr).?.data; | |
| 2534 | return markReferencedDeclsAlive(elem_ptr.array_ptr); | |
| 2535 | }, | |
| 2536 | .field_ptr => { | |
| 2537 | const field_ptr = val.cast(Payload.FieldPtr).?.data; | |
| 2538 | return markReferencedDeclsAlive(field_ptr.container_ptr); | |
| 2539 | }, | |
| 2540 | .aggregate => { | |
| 2541 | for (val.castTag(.aggregate).?.data) |field_val| { | |
| 2542 | markReferencedDeclsAlive(field_val); | |
| 2543 | } | |
| 2544 | }, | |
| 2545 | .@"union" => { | |
| 2546 | const data = val.cast(Payload.Union).?.data; | |
| 2547 | markReferencedDeclsAlive(data.tag); | |
| 2548 | markReferencedDeclsAlive(data.val); | |
| 2549 | }, | |
| 2550 | ||
| 2551 | else => {}, | |
| 2552 | } | |
| 2553 | } | |
| 2554 | ||
| 2555 | 2524 | pub fn slicePtr(val: Value) Value { |
| 2556 | 2525 | return switch (val.tag()) { |
| 2557 | 2526 | .slice => val.castTag(.slice).?.data.ptr, |
| ... | ... | @@ -2561,11 +2530,12 @@ pub const Value = extern union { |
| 2561 | 2530 | }; |
| 2562 | 2531 | } |
| 2563 | 2532 | |
| 2564 | pub fn sliceLen(val: Value, target: Target) u64 { | |
| 2533 | pub fn sliceLen(val: Value, mod: *Module) u64 { | |
| 2565 | 2534 | return switch (val.tag()) { |
| 2566 | .slice => val.castTag(.slice).?.data.len.toUnsignedInt(target), | |
| 2535 | .slice => val.castTag(.slice).?.data.len.toUnsignedInt(mod.getTarget()), | |
| 2567 | 2536 | .decl_ref => { |
| 2568 | const decl = val.castTag(.decl_ref).?.data; | |
| 2537 | const decl_index = val.castTag(.decl_ref).?.data; | |
| 2538 | const decl = mod.declPtr(decl_index); | |
| 2569 | 2539 | if (decl.ty.zigTypeTag() == .Array) { |
| 2570 | 2540 | return decl.ty.arrayLen(); |
| 2571 | 2541 | } else { |
| ... | ... | @@ -2599,18 +2569,19 @@ pub const Value = extern union { |
| 2599 | 2569 | |
| 2600 | 2570 | /// Asserts the value is a single-item pointer to an array, or an array, |
| 2601 | 2571 | /// or an unknown-length pointer, and returns the element value at the index. |
| 2602 | pub fn elemValue(val: Value, arena: Allocator, index: usize) !Value { | |
| 2603 | return elemValueAdvanced(val, index, arena, undefined); | |
| 2572 | pub fn elemValue(val: Value, mod: *Module, arena: Allocator, index: usize) !Value { | |
| 2573 | return elemValueAdvanced(val, mod, index, arena, undefined); | |
| 2604 | 2574 | } |
| 2605 | 2575 | |
| 2606 | 2576 | pub const ElemValueBuffer = Payload.U64; |
| 2607 | 2577 | |
| 2608 | pub fn elemValueBuffer(val: Value, index: usize, buffer: *ElemValueBuffer) Value { | |
| 2609 | return elemValueAdvanced(val, index, null, buffer) catch unreachable; | |
| 2578 | pub fn elemValueBuffer(val: Value, mod: *Module, index: usize, buffer: *ElemValueBuffer) Value { | |
| 2579 | return elemValueAdvanced(val, mod, index, null, buffer) catch unreachable; | |
| 2610 | 2580 | } |
| 2611 | 2581 | |
| 2612 | 2582 | pub fn elemValueAdvanced( |
| 2613 | 2583 | val: Value, |
| 2584 | mod: *Module, | |
| 2614 | 2585 | index: usize, |
| 2615 | 2586 | arena: ?Allocator, |
| 2616 | 2587 | buffer: *ElemValueBuffer, |
| ... | ... | @@ -2643,13 +2614,13 @@ pub const Value = extern union { |
| 2643 | 2614 | .repeated => return val.castTag(.repeated).?.data, |
| 2644 | 2615 | |
| 2645 | 2616 | .aggregate => return val.castTag(.aggregate).?.data[index], |
| 2646 | .slice => return val.castTag(.slice).?.data.ptr.elemValueAdvanced(index, arena, buffer), | |
| 2617 | .slice => return val.castTag(.slice).?.data.ptr.elemValueAdvanced(mod, index, arena, buffer), | |
| 2647 | 2618 | |
| 2648 | .decl_ref => return val.castTag(.decl_ref).?.data.val.elemValueAdvanced(index, arena, buffer), | |
| 2649 | .decl_ref_mut => return val.castTag(.decl_ref_mut).?.data.decl.val.elemValueAdvanced(index, arena, buffer), | |
| 2619 | .decl_ref => return mod.declPtr(val.castTag(.decl_ref).?.data).val.elemValueAdvanced(mod, index, arena, buffer), | |
| 2620 | .decl_ref_mut => return mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.elemValueAdvanced(mod, index, arena, buffer), | |
| 2650 | 2621 | .elem_ptr => { |
| 2651 | 2622 | const data = val.castTag(.elem_ptr).?.data; |
| 2652 | return data.array_ptr.elemValueAdvanced(index + data.index, arena, buffer); | |
| 2623 | return data.array_ptr.elemValueAdvanced(mod, index + data.index, arena, buffer); | |
| 2653 | 2624 | }, |
| 2654 | 2625 | |
| 2655 | 2626 | // The child type of arrays which have only one possible value need |
| ... | ... | @@ -2661,18 +2632,24 @@ pub const Value = extern union { |
| 2661 | 2632 | } |
| 2662 | 2633 | |
| 2663 | 2634 | // Asserts that the provided start/end are in-bounds. |
| 2664 | pub fn sliceArray(val: Value, arena: Allocator, start: usize, end: usize) error{OutOfMemory}!Value { | |
| 2635 | pub fn sliceArray( | |
| 2636 | val: Value, | |
| 2637 | mod: *Module, | |
| 2638 | arena: Allocator, | |
| 2639 | start: usize, | |
| 2640 | end: usize, | |
| 2641 | ) error{OutOfMemory}!Value { | |
| 2665 | 2642 | return switch (val.tag()) { |
| 2666 | 2643 | .empty_array_sentinel => if (start == 0 and end == 1) val else Value.initTag(.empty_array), |
| 2667 | 2644 | .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]), |
| 2668 | 2645 | .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]), |
| 2669 | .slice => sliceArray(val.castTag(.slice).?.data.ptr, arena, start, end), | |
| 2646 | .slice => sliceArray(val.castTag(.slice).?.data.ptr, mod, arena, start, end), | |
| 2670 | 2647 | |
| 2671 | .decl_ref => sliceArray(val.castTag(.decl_ref).?.data.val, arena, start, end), | |
| 2672 | .decl_ref_mut => sliceArray(val.castTag(.decl_ref_mut).?.data.decl.val, arena, start, end), | |
| 2648 | .decl_ref => sliceArray(mod.declPtr(val.castTag(.decl_ref).?.data).val, mod, arena, start, end), | |
| 2649 | .decl_ref_mut => sliceArray(mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val, mod, arena, start, end), | |
| 2673 | 2650 | .elem_ptr => blk: { |
| 2674 | 2651 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| 2675 | break :blk sliceArray(elem_ptr.array_ptr, arena, start + elem_ptr.index, end + elem_ptr.index); | |
| 2652 | break :blk sliceArray(elem_ptr.array_ptr, mod, arena, start + elem_ptr.index, end + elem_ptr.index); | |
| 2676 | 2653 | }, |
| 2677 | 2654 | |
| 2678 | 2655 | .repeated, |
| ... | ... | @@ -2718,7 +2695,13 @@ pub const Value = extern union { |
| 2718 | 2695 | } |
| 2719 | 2696 | |
| 2720 | 2697 | /// Returns a pointer to the element value at the index. |
| 2721 | pub fn elemPtr(val: Value, ty: Type, arena: Allocator, index: usize, target: Target) Allocator.Error!Value { | |
| 2698 | pub fn elemPtr( | |
| 2699 | val: Value, | |
| 2700 | ty: Type, | |
| 2701 | arena: Allocator, | |
| 2702 | index: usize, | |
| 2703 | mod: *Module, | |
| 2704 | ) Allocator.Error!Value { | |
| 2722 | 2705 | const elem_ty = ty.elemType2(); |
| 2723 | 2706 | const ptr_val = switch (val.tag()) { |
| 2724 | 2707 | .slice => val.castTag(.slice).?.data.ptr, |
| ... | ... | @@ -2727,7 +2710,7 @@ pub const Value = extern union { |
| 2727 | 2710 | |
| 2728 | 2711 | if (ptr_val.tag() == .elem_ptr) { |
| 2729 | 2712 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| 2730 | if (elem_ptr.elem_ty.eql(elem_ty, target)) { | |
| 2713 | if (elem_ptr.elem_ty.eql(elem_ty, mod)) { | |
| 2731 | 2714 | return Tag.elem_ptr.create(arena, .{ |
| 2732 | 2715 | .array_ptr = elem_ptr.array_ptr, |
| 2733 | 2716 | .elem_ty = elem_ptr.elem_ty, |
| ... | ... | @@ -5059,7 +5042,7 @@ pub const Value = extern union { |
| 5059 | 5042 | |
| 5060 | 5043 | pub const Decl = struct { |
| 5061 | 5044 | base: Payload, |
| 5062 | data: *Module.Decl, | |
| 5045 | data: Module.Decl.Index, | |
| 5063 | 5046 | }; |
| 5064 | 5047 | |
| 5065 | 5048 | pub const Variable = struct { |
| ... | ... | @@ -5079,7 +5062,7 @@ pub const Value = extern union { |
| 5079 | 5062 | data: Data, |
| 5080 | 5063 | |
| 5081 | 5064 | pub const Data = struct { |
| 5082 | decl: *Module.Decl, | |
| 5065 | decl_index: Module.Decl.Index, | |
| 5083 | 5066 | runtime_index: u32, |
| 5084 | 5067 | }; |
| 5085 | 5068 | }; |
| ... | ... | @@ -5215,7 +5198,7 @@ pub const Value = extern union { |
| 5215 | 5198 | |
| 5216 | 5199 | base: Payload = .{ .tag = base_tag }, |
| 5217 | 5200 | data: struct { |
| 5218 | decl: *Module.Decl, | |
| 5201 | decl_index: Module.Decl.Index, | |
| 5219 | 5202 | /// 0 means ABI-aligned. |
| 5220 | 5203 | alignment: u16, |
| 5221 | 5204 | }, |