| author | |
| committer | |
| log | 55e89255e18163bcc153138a4883ec8d85e0d517 |
| tree | b396ca88ce1bac6d3ea7c73e5e081c6f1ed58360 |
| parent | db33ee45b7261c9ec62a1087cfc9377bc4e7aa8f |
The idea here is to move towards a future where anonymous decls are
represented entirely by an `InternPool.Index`. This was needed to start
implementing `InternPool.getFuncDecl` which requires moving creation and
deletion of Decl objects into InternPool.
* remove `Namespace.anon_decls`
* remove the concept of cleaning up resources from anonymous decls,
relying on InternPool instead.
* move namespace and decl object allocation into InternPool4 files changed, 170 insertions(+), 131 deletions(-)
src/Compilation.zig+1-7| ... | ... | @@ -2055,15 +2055,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void |
| 2055 | 2055 | const decl = module.declPtr(decl_index); |
| 2056 | 2056 | assert(decl.deletion_flag); |
| 2057 | 2057 | assert(decl.dependants.count() == 0); |
| 2058 | const is_anon = if (decl.zir_decl_index == 0) blk: { | |
| 2059 | break :blk module.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index); | |
| 2060 | } else false; | |
| 2058 | assert(decl.zir_decl_index != 0); | |
| 2061 | 2059 | |
| 2062 | 2060 | try module.clearDecl(decl_index, null); |
| 2063 | ||
| 2064 | if (is_anon) { | |
| 2065 | module.destroyDecl(decl_index); | |
| 2066 | } | |
| 2067 | 2061 | } |
| 2068 | 2062 | |
| 2069 | 2063 | try module.processExports(); |
src/InternPool.zig+108-3| ... | ... | @@ -20,6 +20,25 @@ limbs: std.ArrayListUnmanaged(u64) = .{}, |
| 20 | 20 | /// `string_bytes` array is agnostic to either usage. |
| 21 | 21 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| 22 | 22 | |
| 23 | /// Rather than allocating Decl objects with an Allocator, we instead allocate | |
| 24 | /// them with this SegmentedList. This provides four advantages: | |
| 25 | /// * Stable memory so that one thread can access a Decl object while another | |
| 26 | /// thread allocates additional Decl objects from this list. | |
| 27 | /// * It allows us to use u32 indexes to reference Decl objects rather than | |
| 28 | /// pointers, saving memory in Type, Value, and dependency sets. | |
| 29 | /// * Using integers to reference Decl objects rather than pointers makes | |
| 30 | /// serialization trivial. | |
| 31 | /// * It provides a unique integer to be used for anonymous symbol names, avoiding | |
| 32 | /// multi-threaded contention on an atomic counter. | |
| 33 | allocated_decls: std.SegmentedList(Module.Decl, 0) = .{}, | |
| 34 | /// When a Decl object is freed from `allocated_decls`, it is pushed into this stack. | |
| 35 | decls_free_list: std.ArrayListUnmanaged(Module.Decl.Index) = .{}, | |
| 36 | ||
| 37 | /// Same pattern as with `allocated_decls`. | |
| 38 | allocated_namespaces: std.SegmentedList(Module.Namespace, 0) = .{}, | |
| 39 | /// Same pattern as with `decls_free_list`. | |
| 40 | namespaces_free_list: std.ArrayListUnmanaged(Module.Namespace.Index) = .{}, | |
| 41 | ||
| 23 | 42 | /// Struct objects are stored in this data structure because: |
| 24 | 43 | /// * They contain pointers such as the field maps. |
| 25 | 44 | /// * They need to be mutated after creation. |
| ... | ... | @@ -2694,6 +2713,12 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 2694 | 2713 | ip.inferred_error_sets_free_list.deinit(gpa); |
| 2695 | 2714 | ip.allocated_inferred_error_sets.deinit(gpa); |
| 2696 | 2715 | |
| 2716 | ip.decls_free_list.deinit(gpa); | |
| 2717 | ip.allocated_decls.deinit(gpa); | |
| 2718 | ||
| 2719 | ip.namespaces_free_list.deinit(gpa); | |
| 2720 | ip.allocated_namespaces.deinit(gpa); | |
| 2721 | ||
| 2697 | 2722 | for (ip.maps.items) |*map| map.deinit(gpa); |
| 2698 | 2723 | ip.maps.deinit(gpa); |
| 2699 | 2724 | |
| ... | ... | @@ -4274,6 +4299,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: GetExternFuncKey) All |
| 4274 | 4299 | } |
| 4275 | 4300 | |
| 4276 | 4301 | pub const GetFuncDeclKey = struct { |
| 4302 | fn_owner_decl: Module.Decl.Index, | |
| 4277 | 4303 | param_types: []const Index, |
| 4278 | 4304 | noalias_bits: u32, |
| 4279 | 4305 | comptime_bits: u32, |
| ... | ... | @@ -4303,9 +4329,36 @@ pub const GetFuncDeclKey = struct { |
| 4303 | 4329 | }; |
| 4304 | 4330 | |
| 4305 | 4331 | pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index { |
| 4306 | _ = ip; | |
| 4307 | _ = gpa; | |
| 4308 | _ = key; | |
| 4332 | const fn_owner_decl = ip.declPtr(key.fn_owner_decl); | |
| 4333 | const decl_index = try ip.createDecl(gpa, .{ | |
| 4334 | .name = undefined, | |
| 4335 | .src_namespace = fn_owner_decl.src_namespace, | |
| 4336 | .src_node = fn_owner_decl.src_node, | |
| 4337 | .src_line = fn_owner_decl.src_line, | |
| 4338 | .has_tv = true, | |
| 4339 | .owns_tv = true, | |
| 4340 | .ty = @panic("TODO"), | |
| 4341 | .val = @panic("TODO"), | |
| 4342 | .alignment = .none, | |
| 4343 | .@"linksection" = fn_owner_decl.@"linksection", | |
| 4344 | .@"addrspace" = fn_owner_decl.@"addrspace", | |
| 4345 | .analysis = .complete, | |
| 4346 | .deletion_flag = false, | |
| 4347 | .zir_decl_index = fn_owner_decl.zir_decl_index, | |
| 4348 | .src_scope = fn_owner_decl.src_scope, | |
| 4349 | .generation = 0, | |
| 4350 | .is_pub = fn_owner_decl.is_pub, | |
| 4351 | .is_exported = fn_owner_decl.is_exported, | |
| 4352 | .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace, | |
| 4353 | .has_align = fn_owner_decl.has_align, | |
| 4354 | .alive = true, | |
| 4355 | .kind = .anon, | |
| 4356 | }); | |
| 4357 | // TODO better names for generic function instantiations | |
| 4358 | const decl_name = try ip.getOrPutStringFmt(gpa, "{}__anon_{d}", .{ | |
| 4359 | fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index), | |
| 4360 | }); | |
| 4361 | ip.declPtr(decl_index).name = decl_name; | |
| 4309 | 4362 | @panic("TODO"); |
| 4310 | 4363 | } |
| 4311 | 4364 | |
| ... | ... | @@ -5553,6 +5606,14 @@ pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.InferredErr |
| 5553 | 5606 | return ip.allocated_inferred_error_sets.at(@intFromEnum(index)); |
| 5554 | 5607 | } |
| 5555 | 5608 | |
| 5609 | pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl { | |
| 5610 | return ip.allocated_decls.at(@intFromEnum(index)); | |
| 5611 | } | |
| 5612 | ||
| 5613 | pub fn namespacePtr(ip: *InternPool, index: Module.Namespace.Index) *Module.Namespace { | |
| 5614 | return ip.allocated_namespaces.at(@intFromEnum(index)); | |
| 5615 | } | |
| 5616 | ||
| 5556 | 5617 | pub fn createStruct( |
| 5557 | 5618 | ip: *InternPool, |
| 5558 | 5619 | gpa: Allocator, |
| ... | ... | @@ -5619,6 +5680,50 @@ pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.In |
| 5619 | 5680 | }; |
| 5620 | 5681 | } |
| 5621 | 5682 | |
| 5683 | pub fn createDecl( | |
| 5684 | ip: *InternPool, | |
| 5685 | gpa: Allocator, | |
| 5686 | initialization: Module.Decl, | |
| 5687 | ) Allocator.Error!Module.Decl.Index { | |
| 5688 | if (ip.decls_free_list.popOrNull()) |index| { | |
| 5689 | ip.allocated_decls.at(@intFromEnum(index)).* = initialization; | |
| 5690 | return index; | |
| 5691 | } | |
| 5692 | const ptr = try ip.allocated_decls.addOne(gpa); | |
| 5693 | ptr.* = initialization; | |
| 5694 | return @as(Module.Decl.Index, @enumFromInt(ip.allocated_decls.len - 1)); | |
| 5695 | } | |
| 5696 | ||
| 5697 | pub fn destroyDecl(ip: *InternPool, gpa: Allocator, index: Module.Decl.Index) void { | |
| 5698 | ip.declPtr(index).* = undefined; | |
| 5699 | ip.decls_free_list.append(gpa, index) catch { | |
| 5700 | // In order to keep `destroyDecl` a non-fallible function, we ignore memory | |
| 5701 | // allocation failures here, instead leaking the Decl until garbage collection. | |
| 5702 | }; | |
| 5703 | } | |
| 5704 | ||
| 5705 | pub fn createNamespace( | |
| 5706 | ip: *InternPool, | |
| 5707 | gpa: Allocator, | |
| 5708 | initialization: Module.Namespace, | |
| 5709 | ) Allocator.Error!Module.Namespace.Index { | |
| 5710 | if (ip.namespaces_free_list.popOrNull()) |index| { | |
| 5711 | ip.allocated_namespaces.at(@intFromEnum(index)).* = initialization; | |
| 5712 | return index; | |
| 5713 | } | |
| 5714 | const ptr = try ip.allocated_namespaces.addOne(gpa); | |
| 5715 | ptr.* = initialization; | |
| 5716 | return @as(Module.Namespace.Index, @enumFromInt(ip.allocated_namespaces.len - 1)); | |
| 5717 | } | |
| 5718 | ||
| 5719 | pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: Module.Namespace.Index) void { | |
| 5720 | ip.namespacePtr(index).* = undefined; | |
| 5721 | ip.namespaces_free_list.append(gpa, index) catch { | |
| 5722 | // In order to keep `destroyNamespace` a non-fallible function, we ignore memory | |
| 5723 | // allocation failures here, instead leaking the Namespace until garbage collection. | |
| 5724 | }; | |
| 5725 | } | |
| 5726 | ||
| 5622 | 5727 | pub fn getOrPutString( |
| 5623 | 5728 | ip: *InternPool, |
| 5624 | 5729 | gpa: Allocator, |
src/Module.zig+41-108| ... | ... | @@ -87,7 +87,9 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{}, |
| 87 | 87 | /// Keys are fully resolved file paths. This table owns the keys and values. |
| 88 | 88 | embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{}, |
| 89 | 89 | |
| 90 | /// Stores all Type and Value objects; periodically garbage collected. | |
| 90 | /// Stores all Type and Value objects. | |
| 91 | /// The idea is that this will be periodically garbage-collected, but such logic | |
| 92 | /// is not yet implemented. | |
| 91 | 93 | intern_pool: InternPool = .{}, |
| 92 | 94 | |
| 93 | 95 | /// To be eliminated in a future commit by moving more data into InternPool. |
| ... | ... | @@ -152,25 +154,6 @@ emit_h: ?*GlobalEmitH, |
| 152 | 154 | |
| 153 | 155 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, |
| 154 | 156 | |
| 155 | /// Rather than allocating Decl objects with an Allocator, we instead allocate | |
| 156 | /// them with this SegmentedList. This provides four advantages: | |
| 157 | /// * Stable memory so that one thread can access a Decl object while another | |
| 158 | /// thread allocates additional Decl objects from this list. | |
| 159 | /// * It allows us to use u32 indexes to reference Decl objects rather than | |
| 160 | /// pointers, saving memory in Type, Value, and dependency sets. | |
| 161 | /// * Using integers to reference Decl objects rather than pointers makes | |
| 162 | /// serialization trivial. | |
| 163 | /// * It provides a unique integer to be used for anonymous symbol names, avoiding | |
| 164 | /// multi-threaded contention on an atomic counter. | |
| 165 | allocated_decls: std.SegmentedList(Decl, 0) = .{}, | |
| 166 | /// When a Decl object is freed from `allocated_decls`, it is pushed into this stack. | |
| 167 | decls_free_list: ArrayListUnmanaged(Decl.Index) = .{}, | |
| 168 | ||
| 169 | /// Same pattern as with `allocated_decls`. | |
| 170 | allocated_namespaces: std.SegmentedList(Namespace, 0) = .{}, | |
| 171 | /// Same pattern as with `decls_free_list`. | |
| 172 | namespaces_free_list: ArrayListUnmanaged(Namespace.Index) = .{}, | |
| 173 | ||
| 174 | 157 | global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{}, |
| 175 | 158 | |
| 176 | 159 | reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { |
| ... | ... | @@ -313,6 +296,9 @@ pub const CaptureScope = struct { |
| 313 | 296 | } |
| 314 | 297 | |
| 315 | 298 | pub fn incRef(self: *CaptureScope) void { |
| 299 | // TODO: wtf is reference counting doing in my beautiful codebase? 😠| |
| 300 | // seriously though, let's change this to rely on InternPool garbage | |
| 301 | // collection instead. | |
| 316 | 302 | self.refs += 1; |
| 317 | 303 | } |
| 318 | 304 | |
| ... | ... | @@ -1427,12 +1413,10 @@ pub const Namespace = struct { |
| 1427 | 1413 | /// Direct children of the namespace. Used during an update to detect |
| 1428 | 1414 | /// which decls have been added/removed from source. |
| 1429 | 1415 | /// Declaration order is preserved via entry order. |
| 1430 | /// Key memory is owned by `decl.name`. | |
| 1431 | /// Anonymous decls are not stored here; they are kept in `anon_decls` instead. | |
| 1416 | /// These are only declarations named directly by the AST; anonymous | |
| 1417 | /// declarations are not stored here. | |
| 1432 | 1418 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, |
| 1433 | 1419 | |
| 1434 | anon_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | |
| 1435 | ||
| 1436 | 1420 | /// Key is usingnamespace Decl itself. To find the namespace being included, |
| 1437 | 1421 | /// the Decl Value has to be resolved as a Type which has a Namespace. |
| 1438 | 1422 | /// Value is whether the usingnamespace decl is marked `pub`. |
| ... | ... | @@ -1487,18 +1471,11 @@ pub const Namespace = struct { |
| 1487 | 1471 | var decls = ns.decls; |
| 1488 | 1472 | ns.decls = .{}; |
| 1489 | 1473 | |
| 1490 | var anon_decls = ns.anon_decls; | |
| 1491 | ns.anon_decls = .{}; | |
| 1492 | ||
| 1493 | 1474 | for (decls.keys()) |decl_index| { |
| 1494 | 1475 | mod.destroyDecl(decl_index); |
| 1495 | 1476 | } |
| 1496 | 1477 | decls.deinit(gpa); |
| 1497 | 1478 | |
| 1498 | for (anon_decls.keys()) |key| { | |
| 1499 | mod.destroyDecl(key); | |
| 1500 | } | |
| 1501 | anon_decls.deinit(gpa); | |
| 1502 | 1479 | ns.usingnamespace_set.deinit(gpa); |
| 1503 | 1480 | } |
| 1504 | 1481 | |
| ... | ... | @@ -1512,9 +1489,6 @@ pub const Namespace = struct { |
| 1512 | 1489 | var decls = ns.decls; |
| 1513 | 1490 | ns.decls = .{}; |
| 1514 | 1491 | |
| 1515 | var anon_decls = ns.anon_decls; | |
| 1516 | ns.anon_decls = .{}; | |
| 1517 | ||
| 1518 | 1492 | // TODO rework this code to not panic on OOM. |
| 1519 | 1493 | // (might want to coordinate with the clearDecl function) |
| 1520 | 1494 | |
| ... | ... | @@ -1524,12 +1498,6 @@ pub const Namespace = struct { |
| 1524 | 1498 | } |
| 1525 | 1499 | decls.deinit(gpa); |
| 1526 | 1500 | |
| 1527 | for (anon_decls.keys()) |child_decl| { | |
| 1528 | mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); | |
| 1529 | mod.destroyDecl(child_decl); | |
| 1530 | } | |
| 1531 | anon_decls.deinit(gpa); | |
| 1532 | ||
| 1533 | 1501 | ns.usingnamespace_set.deinit(gpa); |
| 1534 | 1502 | } |
| 1535 | 1503 | |
| ... | ... | @@ -3195,14 +3163,9 @@ pub fn deinit(mod: *Module) void { |
| 3195 | 3163 | |
| 3196 | 3164 | mod.test_functions.deinit(gpa); |
| 3197 | 3165 | |
| 3198 | mod.decls_free_list.deinit(gpa); | |
| 3199 | mod.allocated_decls.deinit(gpa); | |
| 3200 | 3166 | mod.global_assembly.deinit(gpa); |
| 3201 | 3167 | mod.reference_table.deinit(gpa); |
| 3202 | 3168 | |
| 3203 | mod.namespaces_free_list.deinit(gpa); | |
| 3204 | mod.allocated_namespaces.deinit(gpa); | |
| 3205 | ||
| 3206 | 3169 | mod.memoized_decls.deinit(gpa); |
| 3207 | 3170 | mod.intern_pool.deinit(gpa); |
| 3208 | 3171 | mod.tmp_hack_arena.deinit(); |
| ... | ... | @@ -3210,6 +3173,8 @@ pub fn deinit(mod: *Module) void { |
| 3210 | 3173 | |
| 3211 | 3174 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| 3212 | 3175 | const gpa = mod.gpa; |
| 3176 | const ip = &mod.intern_pool; | |
| 3177 | ||
| 3213 | 3178 | { |
| 3214 | 3179 | const decl = mod.declPtr(decl_index); |
| 3215 | 3180 | _ = mod.test_functions.swapRemove(decl_index); |
| ... | ... | @@ -3228,12 +3193,10 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| 3228 | 3193 | if (decl.src_scope) |scope| scope.decRef(gpa); |
| 3229 | 3194 | decl.dependants.deinit(gpa); |
| 3230 | 3195 | decl.dependencies.deinit(gpa); |
| 3231 | decl.* = undefined; | |
| 3232 | 3196 | } |
| 3233 | mod.decls_free_list.append(gpa, decl_index) catch { | |
| 3234 | // In order to keep `destroyDecl` a non-fallible function, we ignore memory | |
| 3235 | // allocation failures here, instead leaking the Decl until garbage collection. | |
| 3236 | }; | |
| 3197 | ||
| 3198 | ip.destroyDecl(gpa, decl_index); | |
| 3199 | ||
| 3237 | 3200 | if (mod.emit_h) |mod_emit_h| { |
| 3238 | 3201 | const decl_emit_h = mod_emit_h.declPtr(decl_index); |
| 3239 | 3202 | decl_emit_h.fwd_decl.deinit(gpa); |
| ... | ... | @@ -3242,11 +3205,11 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| 3242 | 3205 | } |
| 3243 | 3206 | |
| 3244 | 3207 | pub fn declPtr(mod: *Module, index: Decl.Index) *Decl { |
| 3245 | return mod.allocated_decls.at(@intFromEnum(index)); | |
| 3208 | return mod.intern_pool.declPtr(index); | |
| 3246 | 3209 | } |
| 3247 | 3210 | |
| 3248 | 3211 | pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace { |
| 3249 | return mod.allocated_namespaces.at(@intFromEnum(index)); | |
| 3212 | return mod.intern_pool.namespacePtr(index); | |
| 3250 | 3213 | } |
| 3251 | 3214 | |
| 3252 | 3215 | pub fn unionPtr(mod: *Module, index: Union.Index) *Union { |
| ... | ... | @@ -3740,9 +3703,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 3740 | 3703 | for (namespace.decls.keys()) |sub_decl| { |
| 3741 | 3704 | try decl_stack.append(gpa, sub_decl); |
| 3742 | 3705 | } |
| 3743 | for (namespace.anon_decls.keys()) |sub_decl| { | |
| 3744 | try decl_stack.append(gpa, sub_decl); | |
| 3745 | } | |
| 3746 | 3706 | } |
| 3747 | 3707 | } |
| 3748 | 3708 | } |
| ... | ... | @@ -5202,21 +5162,19 @@ pub fn clearDecl( |
| 5202 | 5162 | } |
| 5203 | 5163 | |
| 5204 | 5164 | /// This function is exclusively called for anonymous decls. |
| 5165 | /// All resources referenced by anonymous decls are owned by InternPool | |
| 5166 | /// so there is no cleanup to do here. | |
| 5205 | 5167 | pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { |
| 5206 | const decl = mod.declPtr(decl_index); | |
| 5207 | ||
| 5208 | assert(!mod.declIsRoot(decl_index)); | |
| 5209 | assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index)); | |
| 5168 | const gpa = mod.gpa; | |
| 5169 | const ip = &mod.intern_pool; | |
| 5210 | 5170 | |
| 5211 | const dependants = decl.dependants.keys(); | |
| 5212 | for (dependants) |dep| { | |
| 5213 | mod.declPtr(dep).removeDependency(decl_index); | |
| 5214 | } | |
| 5171 | ip.destroyDecl(gpa, decl_index); | |
| 5215 | 5172 | |
| 5216 | for (decl.dependencies.keys()) |dep| { | |
| 5217 | mod.declPtr(dep).removeDependant(decl_index); | |
| 5173 | if (mod.emit_h) |mod_emit_h| { | |
| 5174 | const decl_emit_h = mod_emit_h.declPtr(decl_index); | |
| 5175 | decl_emit_h.fwd_decl.deinit(gpa); | |
| 5176 | decl_emit_h.* = undefined; | |
| 5218 | 5177 | } |
| 5219 | mod.destroyDecl(decl_index); | |
| 5220 | 5178 | } |
| 5221 | 5179 | |
| 5222 | 5180 | /// We don't perform a deletion here, because this Decl or another one |
| ... | ... | @@ -5233,7 +5191,6 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { |
| 5233 | 5191 | const decl = mod.declPtr(decl_index); |
| 5234 | 5192 | |
| 5235 | 5193 | assert(!mod.declIsRoot(decl_index)); |
| 5236 | assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index)); | |
| 5237 | 5194 | |
| 5238 | 5195 | // An aborted decl must not have dependants -- they must have |
| 5239 | 5196 | // been aborted first and removed from this list. |
| ... | ... | @@ -5545,21 +5502,11 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { |
| 5545 | 5502 | } |
| 5546 | 5503 | |
| 5547 | 5504 | pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index { |
| 5548 | if (mod.namespaces_free_list.popOrNull()) |index| { | |
| 5549 | mod.allocated_namespaces.at(@intFromEnum(index)).* = initialization; | |
| 5550 | return index; | |
| 5551 | } | |
| 5552 | const ptr = try mod.allocated_namespaces.addOne(mod.gpa); | |
| 5553 | ptr.* = initialization; | |
| 5554 | return @as(Namespace.Index, @enumFromInt(mod.allocated_namespaces.len - 1)); | |
| 5505 | return mod.intern_pool.createNamespace(mod.gpa, initialization); | |
| 5555 | 5506 | } |
| 5556 | 5507 | |
| 5557 | 5508 | pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void { |
| 5558 | mod.namespacePtr(index).* = undefined; | |
| 5559 | mod.namespaces_free_list.append(mod.gpa, index) catch { | |
| 5560 | // In order to keep `destroyNamespace` a non-fallible function, we ignore memory | |
| 5561 | // allocation failures here, instead leaking the Namespace until garbage collection. | |
| 5562 | }; | |
| 5509 | return mod.intern_pool.destroyNamespace(mod.gpa, index); | |
| 5563 | 5510 | } |
| 5564 | 5511 | |
| 5565 | 5512 | pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index { |
| ... | ... | @@ -5584,29 +5531,9 @@ pub fn allocateNewDecl( |
| 5584 | 5531 | src_node: Ast.Node.Index, |
| 5585 | 5532 | src_scope: ?*CaptureScope, |
| 5586 | 5533 | ) !Decl.Index { |
| 5587 | const decl_and_index: struct { | |
| 5588 | new_decl: *Decl, | |
| 5589 | decl_index: Decl.Index, | |
| 5590 | } = if (mod.decls_free_list.popOrNull()) |decl_index| d: { | |
| 5591 | break :d .{ | |
| 5592 | .new_decl = mod.declPtr(decl_index), | |
| 5593 | .decl_index = decl_index, | |
| 5594 | }; | |
| 5595 | } else d: { | |
| 5596 | const decl = try mod.allocated_decls.addOne(mod.gpa); | |
| 5597 | errdefer mod.allocated_decls.shrinkRetainingCapacity(mod.allocated_decls.len - 1); | |
| 5598 | if (mod.emit_h) |mod_emit_h| { | |
| 5599 | const decl_emit_h = try mod_emit_h.allocated_emit_h.addOne(mod.gpa); | |
| 5600 | decl_emit_h.* = .{}; | |
| 5601 | } | |
| 5602 | break :d .{ | |
| 5603 | .new_decl = decl, | |
| 5604 | .decl_index = @as(Decl.Index, @enumFromInt(mod.allocated_decls.len - 1)), | |
| 5605 | }; | |
| 5606 | }; | |
| 5607 | ||
| 5608 | if (src_scope) |scope| scope.incRef(); | |
| 5609 | decl_and_index.new_decl.* = .{ | |
| 5534 | const ip = &mod.intern_pool; | |
| 5535 | const gpa = mod.gpa; | |
| 5536 | const decl_index = try ip.createDecl(gpa, .{ | |
| 5610 | 5537 | .name = undefined, |
| 5611 | 5538 | .src_namespace = namespace, |
| 5612 | 5539 | .src_node = src_node, |
| ... | ... | @@ -5629,9 +5556,18 @@ pub fn allocateNewDecl( |
| 5629 | 5556 | .has_align = false, |
| 5630 | 5557 | .alive = false, |
| 5631 | 5558 | .kind = .anon, |
| 5632 | }; | |
| 5559 | }); | |
| 5560 | ||
| 5561 | if (mod.emit_h) |mod_emit_h| { | |
| 5562 | if (@intFromEnum(decl_index) >= mod_emit_h.allocated_emit_h.len) { | |
| 5563 | try mod_emit_h.allocated_emit_h.append(gpa, .{}); | |
| 5564 | assert(@intFromEnum(decl_index) == mod_emit_h.allocated_emit_h.len); | |
| 5565 | } | |
| 5566 | } | |
| 5567 | ||
| 5568 | if (src_scope) |scope| scope.incRef(); | |
| 5633 | 5569 | |
| 5634 | return decl_and_index.decl_index; | |
| 5570 | return decl_index; | |
| 5635 | 5571 | } |
| 5636 | 5572 | |
| 5637 | 5573 | pub fn getErrorValue( |
| ... | ... | @@ -5667,7 +5603,7 @@ pub fn createAnonymousDeclFromDecl( |
| 5667 | 5603 | const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{ |
| 5668 | 5604 | src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), |
| 5669 | 5605 | }); |
| 5670 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name); | |
| 5606 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, tv, name); | |
| 5671 | 5607 | return new_decl_index; |
| 5672 | 5608 | } |
| 5673 | 5609 | |
| ... | ... | @@ -5675,7 +5611,6 @@ pub fn initNewAnonDecl( |
| 5675 | 5611 | mod: *Module, |
| 5676 | 5612 | new_decl_index: Decl.Index, |
| 5677 | 5613 | src_line: u32, |
| 5678 | namespace: Namespace.Index, | |
| 5679 | 5614 | typed_value: TypedValue, |
| 5680 | 5615 | name: InternPool.NullTerminatedString, |
| 5681 | 5616 | ) Allocator.Error!void { |
| ... | ... | @@ -5692,8 +5627,6 @@ pub fn initNewAnonDecl( |
| 5692 | 5627 | new_decl.has_tv = true; |
| 5693 | 5628 | new_decl.analysis = .complete; |
| 5694 | 5629 | new_decl.generation = mod.generation; |
| 5695 | ||
| 5696 | try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {}); | |
| 5697 | 5630 | } |
| 5698 | 5631 | |
| 5699 | 5632 | pub fn errNoteNonLazy( |
src/Sema.zig+20-13| ... | ... | @@ -2891,12 +2891,12 @@ fn createAnonymousDeclTypeNamed( |
| 2891 | 2891 | const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ |
| 2892 | 2892 | src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index), |
| 2893 | 2893 | }) catch unreachable; |
| 2894 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | |
| 2894 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); | |
| 2895 | 2895 | return new_decl_index; |
| 2896 | 2896 | }, |
| 2897 | 2897 | .parent => { |
| 2898 | 2898 | const name = mod.declPtr(block.src_decl).name; |
| 2899 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | |
| 2899 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); | |
| 2900 | 2900 | return new_decl_index; |
| 2901 | 2901 | }, |
| 2902 | 2902 | .func => { |
| ... | ... | @@ -2932,7 +2932,7 @@ fn createAnonymousDeclTypeNamed( |
| 2932 | 2932 | |
| 2933 | 2933 | try writer.writeByte(')'); |
| 2934 | 2934 | const name = try mod.intern_pool.getOrPutString(gpa, buf.items); |
| 2935 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | |
| 2935 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); | |
| 2936 | 2936 | return new_decl_index; |
| 2937 | 2937 | }, |
| 2938 | 2938 | .dbg_var => { |
| ... | ... | @@ -2948,7 +2948,7 @@ fn createAnonymousDeclTypeNamed( |
| 2948 | 2948 | src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code), |
| 2949 | 2949 | }); |
| 2950 | 2950 | |
| 2951 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); | |
| 2951 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); | |
| 2952 | 2952 | return new_decl_index; |
| 2953 | 2953 | }, |
| 2954 | 2954 | else => {}, |
| ... | ... | @@ -7393,11 +7393,12 @@ fn instantiateGenericCall( |
| 7393 | 7393 | const ip = &mod.intern_pool; |
| 7394 | 7394 | |
| 7395 | 7395 | const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known"); |
| 7396 | const module_fn = switch (mod.intern_pool.indexToKey(func_val.toIntern())) { | |
| 7397 | .func => |x| x, | |
| 7398 | .ptr => |ptr| mod.intern_pool.indexToKey(mod.declPtr(ptr.addr.decl).val.toIntern()).func, | |
| 7396 | const generic_owner = switch (mod.intern_pool.indexToKey(func_val.toIntern())) { | |
| 7397 | .func => func_val.toIntern(), | |
| 7398 | .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.toIntern(), | |
| 7399 | 7399 | else => unreachable, |
| 7400 | 7400 | }; |
| 7401 | const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func; | |
| 7401 | 7402 | |
| 7402 | 7403 | // Even though there may already be a generic instantiation corresponding |
| 7403 | 7404 | // to this callsite, we must evaluate the expressions of the generic |
| ... | ... | @@ -7407,11 +7408,11 @@ fn instantiateGenericCall( |
| 7407 | 7408 | // The actual monomorphization happens via adding `func_instance` to |
| 7408 | 7409 | // `InternPool`. |
| 7409 | 7410 | |
| 7410 | const fn_owner_decl = mod.declPtr(module_fn.owner_decl); | |
| 7411 | const fn_owner_decl = mod.declPtr(generic_owner_func.owner_decl); | |
| 7411 | 7412 | const namespace_index = fn_owner_decl.src_namespace; |
| 7412 | 7413 | const namespace = mod.namespacePtr(namespace_index); |
| 7413 | 7414 | const fn_zir = namespace.file_scope.zir; |
| 7414 | const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); | |
| 7415 | const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst); | |
| 7415 | 7416 | |
| 7416 | 7417 | const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len); |
| 7417 | 7418 | @memset(comptime_args, .none); |
| ... | ... | @@ -7434,7 +7435,7 @@ fn instantiateGenericCall( |
| 7434 | 7435 | .fn_ret_ty = Type.void, |
| 7435 | 7436 | .owner_func_index = .none, |
| 7436 | 7437 | .comptime_args = comptime_args, |
| 7437 | .generic_owner = module_fn.generic_owner, | |
| 7438 | .generic_owner = generic_owner, | |
| 7438 | 7439 | .branch_quota = sema.branch_quota, |
| 7439 | 7440 | .branch_count = sema.branch_count, |
| 7440 | 7441 | .comptime_mutable_decls = sema.comptime_mutable_decls, |
| ... | ... | @@ -7444,7 +7445,7 @@ fn instantiateGenericCall( |
| 7444 | 7445 | var child_block: Block = .{ |
| 7445 | 7446 | .parent = null, |
| 7446 | 7447 | .sema = &child_sema, |
| 7447 | .src_decl = module_fn.owner_decl, | |
| 7448 | .src_decl = generic_owner_func.owner_decl, | |
| 7448 | 7449 | .namespace = namespace_index, |
| 7449 | 7450 | .wip_capture_scope = block.wip_capture_scope, |
| 7450 | 7451 | .instructions = .{}, |
| ... | ... | @@ -8737,7 +8738,13 @@ fn funcCommon( |
| 8737 | 8738 | if (inferred_error_set) |
| 8738 | 8739 | try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); |
| 8739 | 8740 | |
| 8741 | const fn_owner_decl = if (sema.generic_owner != .none) | |
| 8742 | mod.funcOwnerDeclIndex(sema.generic_owner) | |
| 8743 | else | |
| 8744 | sema.owner_decl_index; | |
| 8745 | ||
| 8740 | 8746 | break :i try ip.getFuncDecl(gpa, .{ |
| 8747 | .fn_owner_decl = fn_owner_decl, | |
| 8741 | 8748 | .param_types = param_types, |
| 8742 | 8749 | .noalias_bits = noalias_bits, |
| 8743 | 8750 | .comptime_bits = comptime_bits, |
| ... | ... | @@ -34628,7 +34635,7 @@ fn generateUnionTagTypeNumbered( |
| 34628 | 34635 | errdefer mod.destroyDecl(new_decl_index); |
| 34629 | 34636 | const fqn = try union_obj.getFullyQualifiedName(mod); |
| 34630 | 34637 | const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)}); |
| 34631 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{ | |
| 34638 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ | |
| 34632 | 34639 | .ty = Type.noreturn, |
| 34633 | 34640 | .val = Value.@"unreachable", |
| 34634 | 34641 | }, name); |
| ... | ... | @@ -34679,7 +34686,7 @@ fn generateUnionTagTypeSimple( |
| 34679 | 34686 | errdefer mod.destroyDecl(new_decl_index); |
| 34680 | 34687 | const fqn = try union_obj.getFullyQualifiedName(mod); |
| 34681 | 34688 | const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)}); |
| 34682 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{ | |
| 34689 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ | |
| 34683 | 34690 | .ty = Type.noreturn, |
| 34684 | 34691 | .val = Value.@"unreachable", |
| 34685 | 34692 | }, name); |