authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-06 15:27:47-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-18 19:02:05-07:00
log55e89255e18163bcc153138a4883ec8d85e0d517
treeb396ca88ce1bac6d3ea7c73e5e081c6f1ed58360
parentdb33ee45b7261c9ec62a1087cfc9377bc4e7aa8f

compiler: begin untangling anonymous decls from source decls

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 InternPool

4 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,15 +2055,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2055 const decl = module.declPtr(decl_index);2055 const decl = module.declPtr(decl_index);
2056 assert(decl.deletion_flag);2056 assert(decl.deletion_flag);
2057 assert(decl.dependants.count() == 0);2057 assert(decl.dependants.count() == 0);
2058 const is_anon = if (decl.zir_decl_index == 0) blk: {2058 assert(decl.zir_decl_index != 0);
2059 break :blk module.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index);
2060 } else false;
20612059
2062 try module.clearDecl(decl_index, null);2060 try module.clearDecl(decl_index, null);
2063
2064 if (is_anon) {
2065 module.destroyDecl(decl_index);
2066 }
2067 }2061 }
20682062
2069 try module.processExports();2063 try module.processExports();
src/InternPool.zig+108-3
...@@ -20,6 +20,25 @@ limbs: std.ArrayListUnmanaged(u64) = .{},...@@ -20,6 +20,25 @@ limbs: std.ArrayListUnmanaged(u64) = .{},
20/// `string_bytes` array is agnostic to either usage.20/// `string_bytes` array is agnostic to either usage.
21string_bytes: std.ArrayListUnmanaged(u8) = .{},21string_bytes: std.ArrayListUnmanaged(u8) = .{},
2222
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.
33allocated_decls: std.SegmentedList(Module.Decl, 0) = .{},
34/// When a Decl object is freed from `allocated_decls`, it is pushed into this stack.
35decls_free_list: std.ArrayListUnmanaged(Module.Decl.Index) = .{},
36
37/// Same pattern as with `allocated_decls`.
38allocated_namespaces: std.SegmentedList(Module.Namespace, 0) = .{},
39/// Same pattern as with `decls_free_list`.
40namespaces_free_list: std.ArrayListUnmanaged(Module.Namespace.Index) = .{},
41
23/// Struct objects are stored in this data structure because:42/// Struct objects are stored in this data structure because:
24/// * They contain pointers such as the field maps.43/// * They contain pointers such as the field maps.
25/// * They need to be mutated after creation.44/// * They need to be mutated after creation.
...@@ -2694,6 +2713,12 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -2694,6 +2713,12 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
2694 ip.inferred_error_sets_free_list.deinit(gpa);2713 ip.inferred_error_sets_free_list.deinit(gpa);
2695 ip.allocated_inferred_error_sets.deinit(gpa);2714 ip.allocated_inferred_error_sets.deinit(gpa);
26962715
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 for (ip.maps.items) |*map| map.deinit(gpa);2722 for (ip.maps.items) |*map| map.deinit(gpa);
2698 ip.maps.deinit(gpa);2723 ip.maps.deinit(gpa);
26992724
...@@ -4274,6 +4299,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: GetExternFuncKey) All...@@ -4274,6 +4299,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: GetExternFuncKey) All
4274}4299}
42754300
4276pub const GetFuncDeclKey = struct {4301pub const GetFuncDeclKey = struct {
4302 fn_owner_decl: Module.Decl.Index,
4277 param_types: []const Index,4303 param_types: []const Index,
4278 noalias_bits: u32,4304 noalias_bits: u32,
4279 comptime_bits: u32,4305 comptime_bits: u32,
...@@ -4303,9 +4329,36 @@ pub const GetFuncDeclKey = struct {...@@ -4303,9 +4329,36 @@ pub const GetFuncDeclKey = struct {
4303};4329};
43044330
4305pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index {4331pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index {
4306 _ = ip;4332 const fn_owner_decl = ip.declPtr(key.fn_owner_decl);
4307 _ = gpa;4333 const decl_index = try ip.createDecl(gpa, .{
4308 _ = key;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 @panic("TODO");4362 @panic("TODO");
4310}4363}
43114364
...@@ -5553,6 +5606,14 @@ pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.InferredErr...@@ -5553,6 +5606,14 @@ pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.InferredErr
5553 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));5606 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
5554}5607}
55555608
5609pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl {
5610 return ip.allocated_decls.at(@intFromEnum(index));
5611}
5612
5613pub fn namespacePtr(ip: *InternPool, index: Module.Namespace.Index) *Module.Namespace {
5614 return ip.allocated_namespaces.at(@intFromEnum(index));
5615}
5616
5556pub fn createStruct(5617pub fn createStruct(
5557 ip: *InternPool,5618 ip: *InternPool,
5558 gpa: Allocator,5619 gpa: Allocator,
...@@ -5619,6 +5680,50 @@ pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.In...@@ -5619,6 +5680,50 @@ pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.In
5619 };5680 };
5620}5681}
56215682
5683pub 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
5697pub 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
5705pub 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
5719pub 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
5622pub fn getOrPutString(5727pub fn getOrPutString(
5623 ip: *InternPool,5728 ip: *InternPool,
5624 gpa: Allocator,5729 gpa: Allocator,
src/Module.zig+41-108
...@@ -87,7 +87,9 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{},...@@ -87,7 +87,9 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{},
87/// Keys are fully resolved file paths. This table owns the keys and values.87/// Keys are fully resolved file paths. This table owns the keys and values.
88embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},88embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},
8989
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.
91intern_pool: InternPool = .{},93intern_pool: InternPool = .{},
9294
93/// To be eliminated in a future commit by moving more data into InternPool.95/// To be eliminated in a future commit by moving more data into InternPool.
...@@ -152,25 +154,6 @@ emit_h: ?*GlobalEmitH,...@@ -152,25 +154,6 @@ emit_h: ?*GlobalEmitH,
152154
153test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},155test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
154156
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.
165allocated_decls: std.SegmentedList(Decl, 0) = .{},
166/// When a Decl object is freed from `allocated_decls`, it is pushed into this stack.
167decls_free_list: ArrayListUnmanaged(Decl.Index) = .{},
168
169/// Same pattern as with `allocated_decls`.
170allocated_namespaces: std.SegmentedList(Namespace, 0) = .{},
171/// Same pattern as with `decls_free_list`.
172namespaces_free_list: ArrayListUnmanaged(Namespace.Index) = .{},
173
174global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},157global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},
175158
176reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {159reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
...@@ -313,6 +296,9 @@ pub const CaptureScope = struct {...@@ -313,6 +296,9 @@ pub const CaptureScope = struct {
313 }296 }
314297
315 pub fn incRef(self: *CaptureScope) void {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 self.refs += 1;302 self.refs += 1;
317 }303 }
318304
...@@ -1427,12 +1413,10 @@ pub const Namespace = struct {...@@ -1427,12 +1413,10 @@ pub const Namespace = struct {
1427 /// Direct children of the namespace. Used during an update to detect1413 /// Direct children of the namespace. Used during an update to detect
1428 /// which decls have been added/removed from source.1414 /// which decls have been added/removed from source.
1429 /// Declaration order is preserved via entry order.1415 /// Declaration order is preserved via entry order.
1430 /// Key memory is owned by `decl.name`.1416 /// These are only declarations named directly by the AST; anonymous
1431 /// Anonymous decls are not stored here; they are kept in `anon_decls` instead.1417 /// declarations are not stored here.
1432 decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{},1418 decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{},
14331419
1434 anon_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
1435
1436 /// Key is usingnamespace Decl itself. To find the namespace being included,1420 /// Key is usingnamespace Decl itself. To find the namespace being included,
1437 /// the Decl Value has to be resolved as a Type which has a Namespace.1421 /// the Decl Value has to be resolved as a Type which has a Namespace.
1438 /// Value is whether the usingnamespace decl is marked `pub`.1422 /// Value is whether the usingnamespace decl is marked `pub`.
...@@ -1487,18 +1471,11 @@ pub const Namespace = struct {...@@ -1487,18 +1471,11 @@ pub const Namespace = struct {
1487 var decls = ns.decls;1471 var decls = ns.decls;
1488 ns.decls = .{};1472 ns.decls = .{};
14891473
1490 var anon_decls = ns.anon_decls;
1491 ns.anon_decls = .{};
1492
1493 for (decls.keys()) |decl_index| {1474 for (decls.keys()) |decl_index| {
1494 mod.destroyDecl(decl_index);1475 mod.destroyDecl(decl_index);
1495 }1476 }
1496 decls.deinit(gpa);1477 decls.deinit(gpa);
14971478
1498 for (anon_decls.keys()) |key| {
1499 mod.destroyDecl(key);
1500 }
1501 anon_decls.deinit(gpa);
1502 ns.usingnamespace_set.deinit(gpa);1479 ns.usingnamespace_set.deinit(gpa);
1503 }1480 }
15041481
...@@ -1512,9 +1489,6 @@ pub const Namespace = struct {...@@ -1512,9 +1489,6 @@ pub const Namespace = struct {
1512 var decls = ns.decls;1489 var decls = ns.decls;
1513 ns.decls = .{};1490 ns.decls = .{};
15141491
1515 var anon_decls = ns.anon_decls;
1516 ns.anon_decls = .{};
1517
1518 // TODO rework this code to not panic on OOM.1492 // TODO rework this code to not panic on OOM.
1519 // (might want to coordinate with the clearDecl function)1493 // (might want to coordinate with the clearDecl function)
15201494
...@@ -1524,12 +1498,6 @@ pub const Namespace = struct {...@@ -1524,12 +1498,6 @@ pub const Namespace = struct {
1524 }1498 }
1525 decls.deinit(gpa);1499 decls.deinit(gpa);
15261500
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 ns.usingnamespace_set.deinit(gpa);1501 ns.usingnamespace_set.deinit(gpa);
1534 }1502 }
15351503
...@@ -3195,14 +3163,9 @@ pub fn deinit(mod: *Module) void {...@@ -3195,14 +3163,9 @@ pub fn deinit(mod: *Module) void {
31953163
3196 mod.test_functions.deinit(gpa);3164 mod.test_functions.deinit(gpa);
31973165
3198 mod.decls_free_list.deinit(gpa);
3199 mod.allocated_decls.deinit(gpa);
3200 mod.global_assembly.deinit(gpa);3166 mod.global_assembly.deinit(gpa);
3201 mod.reference_table.deinit(gpa);3167 mod.reference_table.deinit(gpa);
32023168
3203 mod.namespaces_free_list.deinit(gpa);
3204 mod.allocated_namespaces.deinit(gpa);
3205
3206 mod.memoized_decls.deinit(gpa);3169 mod.memoized_decls.deinit(gpa);
3207 mod.intern_pool.deinit(gpa);3170 mod.intern_pool.deinit(gpa);
3208 mod.tmp_hack_arena.deinit();3171 mod.tmp_hack_arena.deinit();
...@@ -3210,6 +3173,8 @@ pub fn deinit(mod: *Module) void {...@@ -3210,6 +3173,8 @@ pub fn deinit(mod: *Module) void {
32103173
3211pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {3174pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3212 const gpa = mod.gpa;3175 const gpa = mod.gpa;
3176 const ip = &mod.intern_pool;
3177
3213 {3178 {
3214 const decl = mod.declPtr(decl_index);3179 const decl = mod.declPtr(decl_index);
3215 _ = mod.test_functions.swapRemove(decl_index);3180 _ = mod.test_functions.swapRemove(decl_index);
...@@ -3228,12 +3193,10 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -3228,12 +3193,10 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3228 if (decl.src_scope) |scope| scope.decRef(gpa);3193 if (decl.src_scope) |scope| scope.decRef(gpa);
3229 decl.dependants.deinit(gpa);3194 decl.dependants.deinit(gpa);
3230 decl.dependencies.deinit(gpa);3195 decl.dependencies.deinit(gpa);
3231 decl.* = undefined;
3232 }3196 }
3233 mod.decls_free_list.append(gpa, decl_index) catch {3197
3234 // In order to keep `destroyDecl` a non-fallible function, we ignore memory3198 ip.destroyDecl(gpa, decl_index);
3235 // allocation failures here, instead leaking the Decl until garbage collection.3199
3236 };
3237 if (mod.emit_h) |mod_emit_h| {3200 if (mod.emit_h) |mod_emit_h| {
3238 const decl_emit_h = mod_emit_h.declPtr(decl_index);3201 const decl_emit_h = mod_emit_h.declPtr(decl_index);
3239 decl_emit_h.fwd_decl.deinit(gpa);3202 decl_emit_h.fwd_decl.deinit(gpa);
...@@ -3242,11 +3205,11 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -3242,11 +3205,11 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3242}3205}
32433206
3244pub fn declPtr(mod: *Module, index: Decl.Index) *Decl {3207pub 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}
32473210
3248pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace {3211pub 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}
32513214
3252pub fn unionPtr(mod: *Module, index: Union.Index) *Union {3215pub fn unionPtr(mod: *Module, index: Union.Index) *Union {
...@@ -3740,9 +3703,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {...@@ -3740,9 +3703,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3740 for (namespace.decls.keys()) |sub_decl| {3703 for (namespace.decls.keys()) |sub_decl| {
3741 try decl_stack.append(gpa, sub_decl);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,21 +5162,19 @@ pub fn clearDecl(
5202}5162}
52035163
5204/// This function is exclusively called for anonymous decls.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.
5205pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {5167pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {
5206 const decl = mod.declPtr(decl_index);5168 const gpa = mod.gpa;
52075169 const ip = &mod.intern_pool;
5208 assert(!mod.declIsRoot(decl_index));
5209 assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index));
52105170
5211 const dependants = decl.dependants.keys();5171 ip.destroyDecl(gpa, decl_index);
5212 for (dependants) |dep| {
5213 mod.declPtr(dep).removeDependency(decl_index);
5214 }
52155172
5216 for (decl.dependencies.keys()) |dep| {5173 if (mod.emit_h) |mod_emit_h| {
5217 mod.declPtr(dep).removeDependant(decl_index);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}
52215179
5222/// We don't perform a deletion here, because this Decl or another one5180/// 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,7 +5191,6 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
5233 const decl = mod.declPtr(decl_index);5191 const decl = mod.declPtr(decl_index);
52345192
5235 assert(!mod.declIsRoot(decl_index));5193 assert(!mod.declIsRoot(decl_index));
5236 assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index));
52375194
5238 // An aborted decl must not have dependants -- they must have5195 // An aborted decl must not have dependants -- they must have
5239 // been aborted first and removed from this list.5196 // been aborted first and removed from this list.
...@@ -5545,21 +5502,11 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5545,21 +5502,11 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5545}5502}
55465503
5547pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {5504pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {
5548 if (mod.namespaces_free_list.popOrNull()) |index| {5505 return mod.intern_pool.createNamespace(mod.gpa, initialization);
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));
5555}5506}
55565507
5557pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {5508pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {
5558 mod.namespacePtr(index).* = undefined;5509 return mod.intern_pool.destroyNamespace(mod.gpa, index);
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 };
5563}5510}
55645511
5565pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index {5512pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index {
...@@ -5584,29 +5531,9 @@ pub fn allocateNewDecl(...@@ -5584,29 +5531,9 @@ pub fn allocateNewDecl(
5584 src_node: Ast.Node.Index,5531 src_node: Ast.Node.Index,
5585 src_scope: ?*CaptureScope,5532 src_scope: ?*CaptureScope,
5586) !Decl.Index {5533) !Decl.Index {
5587 const decl_and_index: struct {5534 const ip = &mod.intern_pool;
5588 new_decl: *Decl,5535 const gpa = mod.gpa;
5589 decl_index: Decl.Index,5536 const decl_index = try ip.createDecl(gpa, .{
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.* = .{
5610 .name = undefined,5537 .name = undefined,
5611 .src_namespace = namespace,5538 .src_namespace = namespace,
5612 .src_node = src_node,5539 .src_node = src_node,
...@@ -5629,9 +5556,18 @@ pub fn allocateNewDecl(...@@ -5629,9 +5556,18 @@ pub fn allocateNewDecl(
5629 .has_align = false,5556 .has_align = false,
5630 .alive = false,5557 .alive = false,
5631 .kind = .anon,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();
56335569
5634 return decl_and_index.decl_index;5570 return decl_index;
5635}5571}
56365572
5637pub fn getErrorValue(5573pub fn getErrorValue(
...@@ -5667,7 +5603,7 @@ pub fn createAnonymousDeclFromDecl(...@@ -5667,7 +5603,7 @@ pub fn createAnonymousDeclFromDecl(
5667 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{5603 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{
5668 src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),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 return new_decl_index;5607 return new_decl_index;
5672}5608}
56735609
...@@ -5675,7 +5611,6 @@ pub fn initNewAnonDecl(...@@ -5675,7 +5611,6 @@ pub fn initNewAnonDecl(
5675 mod: *Module,5611 mod: *Module,
5676 new_decl_index: Decl.Index,5612 new_decl_index: Decl.Index,
5677 src_line: u32,5613 src_line: u32,
5678 namespace: Namespace.Index,
5679 typed_value: TypedValue,5614 typed_value: TypedValue,
5680 name: InternPool.NullTerminatedString,5615 name: InternPool.NullTerminatedString,
5681) Allocator.Error!void {5616) Allocator.Error!void {
...@@ -5692,8 +5627,6 @@ pub fn initNewAnonDecl(...@@ -5692,8 +5627,6 @@ pub fn initNewAnonDecl(
5692 new_decl.has_tv = true;5627 new_decl.has_tv = true;
5693 new_decl.analysis = .complete;5628 new_decl.analysis = .complete;
5694 new_decl.generation = mod.generation;5629 new_decl.generation = mod.generation;
5695
5696 try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {});
5697}5630}
56985631
5699pub fn errNoteNonLazy(5632pub fn errNoteNonLazy(
src/Sema.zig+20-13
...@@ -2891,12 +2891,12 @@ fn createAnonymousDeclTypeNamed(...@@ -2891,12 +2891,12 @@ fn createAnonymousDeclTypeNamed(
2891 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{2891 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
2892 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index),2892 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index),
2893 }) catch unreachable;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 return new_decl_index;2895 return new_decl_index;
2896 },2896 },
2897 .parent => {2897 .parent => {
2898 const name = mod.declPtr(block.src_decl).name;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 return new_decl_index;2900 return new_decl_index;
2901 },2901 },
2902 .func => {2902 .func => {
...@@ -2932,7 +2932,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2932,7 +2932,7 @@ fn createAnonymousDeclTypeNamed(
29322932
2933 try writer.writeByte(')');2933 try writer.writeByte(')');
2934 const name = try mod.intern_pool.getOrPutString(gpa, buf.items);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 return new_decl_index;2936 return new_decl_index;
2937 },2937 },
2938 .dbg_var => {2938 .dbg_var => {
...@@ -2948,7 +2948,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2948,7 +2948,7 @@ fn createAnonymousDeclTypeNamed(
2948 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),2948 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),
2949 });2949 });
29502950
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 return new_decl_index;2952 return new_decl_index;
2953 },2953 },
2954 else => {},2954 else => {},
...@@ -7393,11 +7393,12 @@ fn instantiateGenericCall(...@@ -7393,11 +7393,12 @@ fn instantiateGenericCall(
7393 const ip = &mod.intern_pool;7393 const ip = &mod.intern_pool;
73947394
7395 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");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())) {7396 const generic_owner = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7397 .func => |x| x,7397 .func => func_val.toIntern(),
7398 .ptr => |ptr| mod.intern_pool.indexToKey(mod.declPtr(ptr.addr.decl).val.toIntern()).func,7398 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.toIntern(),
7399 else => unreachable,7399 else => unreachable,
7400 };7400 };
7401 const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func;
74017402
7402 // Even though there may already be a generic instantiation corresponding7403 // Even though there may already be a generic instantiation corresponding
7403 // to this callsite, we must evaluate the expressions of the generic7404 // to this callsite, we must evaluate the expressions of the generic
...@@ -7407,11 +7408,11 @@ fn instantiateGenericCall(...@@ -7407,11 +7408,11 @@ fn instantiateGenericCall(
7407 // The actual monomorphization happens via adding `func_instance` to7408 // The actual monomorphization happens via adding `func_instance` to
7408 // `InternPool`.7409 // `InternPool`.
74097410
7410 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);7411 const fn_owner_decl = mod.declPtr(generic_owner_func.owner_decl);
7411 const namespace_index = fn_owner_decl.src_namespace;7412 const namespace_index = fn_owner_decl.src_namespace;
7412 const namespace = mod.namespacePtr(namespace_index);7413 const namespace = mod.namespacePtr(namespace_index);
7413 const fn_zir = namespace.file_scope.zir;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);
74157416
7416 const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len);7417 const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len);
7417 @memset(comptime_args, .none);7418 @memset(comptime_args, .none);
...@@ -7434,7 +7435,7 @@ fn instantiateGenericCall(...@@ -7434,7 +7435,7 @@ fn instantiateGenericCall(
7434 .fn_ret_ty = Type.void,7435 .fn_ret_ty = Type.void,
7435 .owner_func_index = .none,7436 .owner_func_index = .none,
7436 .comptime_args = comptime_args,7437 .comptime_args = comptime_args,
7437 .generic_owner = module_fn.generic_owner,7438 .generic_owner = generic_owner,
7438 .branch_quota = sema.branch_quota,7439 .branch_quota = sema.branch_quota,
7439 .branch_count = sema.branch_count,7440 .branch_count = sema.branch_count,
7440 .comptime_mutable_decls = sema.comptime_mutable_decls,7441 .comptime_mutable_decls = sema.comptime_mutable_decls,
...@@ -7444,7 +7445,7 @@ fn instantiateGenericCall(...@@ -7444,7 +7445,7 @@ fn instantiateGenericCall(
7444 var child_block: Block = .{7445 var child_block: Block = .{
7445 .parent = null,7446 .parent = null,
7446 .sema = &child_sema,7447 .sema = &child_sema,
7447 .src_decl = module_fn.owner_decl,7448 .src_decl = generic_owner_func.owner_decl,
7448 .namespace = namespace_index,7449 .namespace = namespace_index,
7449 .wip_capture_scope = block.wip_capture_scope,7450 .wip_capture_scope = block.wip_capture_scope,
7450 .instructions = .{},7451 .instructions = .{},
...@@ -8737,7 +8738,13 @@ fn funcCommon(...@@ -8737,7 +8738,13 @@ fn funcCommon(
8737 if (inferred_error_set)8738 if (inferred_error_set)
8738 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);8739 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
87398740
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 break :i try ip.getFuncDecl(gpa, .{8746 break :i try ip.getFuncDecl(gpa, .{
8747 .fn_owner_decl = fn_owner_decl,
8741 .param_types = param_types,8748 .param_types = param_types,
8742 .noalias_bits = noalias_bits,8749 .noalias_bits = noalias_bits,
8743 .comptime_bits = comptime_bits,8750 .comptime_bits = comptime_bits,
...@@ -34628,7 +34635,7 @@ fn generateUnionTagTypeNumbered(...@@ -34628,7 +34635,7 @@ fn generateUnionTagTypeNumbered(
34628 errdefer mod.destroyDecl(new_decl_index);34635 errdefer mod.destroyDecl(new_decl_index);
34629 const fqn = try union_obj.getFullyQualifiedName(mod);34636 const fqn = try union_obj.getFullyQualifiedName(mod);
34630 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});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 .ty = Type.noreturn,34639 .ty = Type.noreturn,
34633 .val = Value.@"unreachable",34640 .val = Value.@"unreachable",
34634 }, name);34641 }, name);
...@@ -34679,7 +34686,7 @@ fn generateUnionTagTypeSimple(...@@ -34679,7 +34686,7 @@ fn generateUnionTagTypeSimple(
34679 errdefer mod.destroyDecl(new_decl_index);34686 errdefer mod.destroyDecl(new_decl_index);
34680 const fqn = try union_obj.getFullyQualifiedName(mod);34687 const fqn = try union_obj.getFullyQualifiedName(mod);
34681 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});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 .ty = Type.noreturn,34690 .ty = Type.noreturn,
34684 .val = Value.@"unreachable",34691 .val = Value.@"unreachable",
34685 }, name);34692 }, name);