| ... | ... | @@ -132,10 +132,6 @@ failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{}, |
| 132 | 132 | /// are stored here. |
| 133 | 133 | cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, std.zig.ErrorBundle) = .{}, |
| 134 | 134 | |
| 135 | | /// Candidates for deletion. After a semantic analysis update completes, this list |
| 136 | | /// contains Decls that need to be deleted if they end up having no references to them. |
| 137 | | deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, |
| 138 | | |
| 139 | 135 | /// Key is the error name, index is the error tag value. Index 0 has a length-0 string. |
| 140 | 136 | global_error_set: GlobalErrorSet = .{}, |
| 141 | 137 | |
| ... | ... | @@ -165,7 +161,7 @@ emit_h: ?*GlobalEmitH, |
| 165 | 161 | |
| 166 | 162 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, |
| 167 | 163 | |
| 168 | | global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{}, |
| 164 | global_assembly: std.AutoArrayHashMapUnmanaged(Decl.Index, []u8) = .{}, |
| 169 | 165 | |
| 170 | 166 | reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { |
| 171 | 167 | referencer: Decl.Index, |
| ... | ... | @@ -438,9 +434,6 @@ pub const Decl = struct { |
| 438 | 434 | /// with it. That means when `Decl` is destroyed, the cleanup code should additionally |
| 439 | 435 | /// check if the value owns a `Namespace`, and destroy that too. |
| 440 | 436 | owns_tv: bool, |
| 441 | | /// This flag is set when this Decl is added to `Module.deletion_set`, and cleared |
| 442 | | /// when removed. |
| 443 | | deletion_flag: bool, |
| 444 | 437 | /// Whether the corresponding AST decl has a `pub` keyword. |
| 445 | 438 | is_pub: bool, |
| 446 | 439 | /// Whether the corresponding AST decl has a `export` keyword. |
| ... | ... | @@ -873,47 +866,6 @@ pub const Namespace = struct { |
| 873 | 866 | } |
| 874 | 867 | }; |
| 875 | 868 | |
| 876 | | pub fn deinit(ns: *Namespace, mod: *Module) void { |
| 877 | | ns.destroyDecls(mod); |
| 878 | | ns.* = undefined; |
| 879 | | } |
| 880 | | |
| 881 | | pub fn destroyDecls(ns: *Namespace, mod: *Module) void { |
| 882 | | const gpa = mod.gpa; |
| 883 | | |
| 884 | | var decls = ns.decls; |
| 885 | | ns.decls = .{}; |
| 886 | | |
| 887 | | for (decls.keys()) |decl_index| { |
| 888 | | mod.destroyDecl(decl_index); |
| 889 | | } |
| 890 | | decls.deinit(gpa); |
| 891 | | |
| 892 | | ns.usingnamespace_set.deinit(gpa); |
| 893 | | } |
| 894 | | |
| 895 | | pub fn deleteAllDecls( |
| 896 | | ns: *Namespace, |
| 897 | | mod: *Module, |
| 898 | | outdated_decls: ?*std.AutoArrayHashMap(Decl.Index, void), |
| 899 | | ) !void { |
| 900 | | const gpa = mod.gpa; |
| 901 | | |
| 902 | | var decls = ns.decls; |
| 903 | | ns.decls = .{}; |
| 904 | | |
| 905 | | // TODO rework this code to not panic on OOM. |
| 906 | | // (might want to coordinate with the clearDecl function) |
| 907 | | |
| 908 | | for (decls.keys()) |child_decl| { |
| 909 | | mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); |
| 910 | | mod.destroyDecl(child_decl); |
| 911 | | } |
| 912 | | decls.deinit(gpa); |
| 913 | | |
| 914 | | ns.usingnamespace_set.deinit(gpa); |
| 915 | | } |
| 916 | | |
| 917 | 869 | // This renders e.g. "std.fs.Dir.OpenOptions" |
| 918 | 870 | pub fn renderFullyQualifiedName( |
| 919 | 871 | ns: Namespace, |
| ... | ... | @@ -2527,7 +2479,6 @@ pub fn deinit(mod: *Module) void { |
| 2527 | 2479 | mod.embed_table.deinit(gpa); |
| 2528 | 2480 | } |
| 2529 | 2481 | |
| 2530 | | mod.deletion_set.deinit(gpa); |
| 2531 | 2482 | mod.compile_log_text.deinit(gpa); |
| 2532 | 2483 | |
| 2533 | 2484 | mod.zig_cache_artifact_directory.handle.close(); |
| ... | ... | @@ -2590,9 +2541,21 @@ pub fn deinit(mod: *Module) void { |
| 2590 | 2541 | |
| 2591 | 2542 | mod.test_functions.deinit(gpa); |
| 2592 | 2543 | |
| 2544 | for (mod.global_assembly.values()) |s| { |
| 2545 | gpa.free(s); |
| 2546 | } |
| 2593 | 2547 | mod.global_assembly.deinit(gpa); |
| 2548 | |
| 2594 | 2549 | mod.reference_table.deinit(gpa); |
| 2595 | 2550 | |
| 2551 | { |
| 2552 | var it = mod.intern_pool.allocated_namespaces.iterator(0); |
| 2553 | while (it.next()) |namespace| { |
| 2554 | namespace.decls.deinit(gpa); |
| 2555 | namespace.usingnamespace_set.deinit(gpa); |
| 2556 | } |
| 2557 | } |
| 2558 | |
| 2596 | 2559 | mod.intern_pool.deinit(gpa); |
| 2597 | 2560 | mod.tmp_hack_arena.deinit(); |
| 2598 | 2561 | |
| ... | ... | @@ -2606,20 +2569,10 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| 2606 | 2569 | const ip = &mod.intern_pool; |
| 2607 | 2570 | |
| 2608 | 2571 | { |
| 2609 | | const decl = mod.declPtr(decl_index); |
| 2610 | 2572 | _ = mod.test_functions.swapRemove(decl_index); |
| 2611 | | if (decl.deletion_flag) { |
| 2612 | | assert(mod.deletion_set.swapRemove(decl_index)); |
| 2613 | | } |
| 2614 | | if (mod.global_assembly.fetchRemove(decl_index)) |kv| { |
| 2573 | if (mod.global_assembly.fetchSwapRemove(decl_index)) |kv| { |
| 2615 | 2574 | gpa.free(kv.value); |
| 2616 | 2575 | } |
| 2617 | | if (decl.has_tv) { |
| 2618 | | if (decl.getOwnedInnerNamespaceIndex(mod).unwrap()) |i| { |
| 2619 | | mod.namespacePtr(i).destroyDecls(mod); |
| 2620 | | mod.destroyNamespace(i); |
| 2621 | | } |
| 2622 | | } |
| 2623 | 2576 | } |
| 2624 | 2577 | |
| 2625 | 2578 | ip.destroyDecl(gpa, decl_index); |
| ... | ... | @@ -4422,56 +4375,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 4422 | 4375 | } |
| 4423 | 4376 | } |
| 4424 | 4377 | |
| 4425 | | /// Make it as if the semantic analysis for this Decl never happened. |
| 4426 | | pub fn clearDecl( |
| 4427 | | mod: *Module, |
| 4428 | | decl_index: Decl.Index, |
| 4429 | | outdated_decls: ?*std.AutoArrayHashMap(Decl.Index, void), |
| 4430 | | ) Allocator.Error!void { |
| 4431 | | const tracy = trace(@src()); |
| 4432 | | defer tracy.end(); |
| 4433 | | |
| 4434 | | const decl = mod.declPtr(decl_index); |
| 4435 | | |
| 4436 | | const gpa = mod.gpa; |
| 4437 | | |
| 4438 | | if (outdated_decls) |map| { |
| 4439 | | _ = map.swapRemove(decl_index); |
| 4440 | | } |
| 4441 | | |
| 4442 | | if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| { |
| 4443 | | kv.value.destroy(gpa); |
| 4444 | | } |
| 4445 | | if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| { |
| 4446 | | var errors = kv.value; |
| 4447 | | errors.deinit(gpa); |
| 4448 | | } |
| 4449 | | if (mod.emit_h) |emit_h| { |
| 4450 | | if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| { |
| 4451 | | kv.value.destroy(gpa); |
| 4452 | | } |
| 4453 | | assert(emit_h.decl_table.swapRemove(decl_index)); |
| 4454 | | } |
| 4455 | | _ = mod.compile_log_decls.swapRemove(decl_index); |
| 4456 | | try mod.deleteDeclExports(decl_index); |
| 4457 | | |
| 4458 | | if (decl.has_tv) { |
| 4459 | | if (decl.ty.isFnOrHasRuntimeBits(mod)) { |
| 4460 | | mod.comp.bin_file.freeDecl(decl_index); |
| 4461 | | } |
| 4462 | | if (decl.getOwnedInnerNamespace(mod)) |namespace| { |
| 4463 | | try namespace.deleteAllDecls(mod, outdated_decls); |
| 4464 | | } |
| 4465 | | } |
| 4466 | | |
| 4467 | | if (decl.deletion_flag) { |
| 4468 | | decl.deletion_flag = false; |
| 4469 | | assert(mod.deletion_set.swapRemove(decl_index)); |
| 4470 | | } |
| 4471 | | |
| 4472 | | decl.analysis = .unreferenced; |
| 4473 | | } |
| 4474 | | |
| 4475 | 4378 | /// This function is exclusively called for anonymous decls. |
| 4476 | 4379 | /// All resources referenced by anonymous decls are owned by InternPool |
| 4477 | 4380 | /// so there is no cleanup to do here. |
| ... | ... | @@ -4488,14 +4391,6 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { |
| 4488 | 4391 | } |
| 4489 | 4392 | } |
| 4490 | 4393 | |
| 4491 | | /// We don't perform a deletion here, because this Decl or another one |
| 4492 | | /// may end up referencing it before the update is complete. |
| 4493 | | fn markDeclForDeletion(mod: *Module, decl_index: Decl.Index) !void { |
| 4494 | | const decl = mod.declPtr(decl_index); |
| 4495 | | decl.deletion_flag = true; |
| 4496 | | try mod.deletion_set.put(mod.gpa, decl_index, {}); |
| 4497 | | } |
| 4498 | | |
| 4499 | 4394 | /// Cancel the creation of an anon decl and delete any references to it. |
| 4500 | 4395 | /// If other decls depend on this decl, they must be aborted first. |
| 4501 | 4396 | pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { |
| ... | ... | @@ -4868,7 +4763,6 @@ pub fn allocateNewDecl( |
| 4868 | 4763 | .@"linksection" = .none, |
| 4869 | 4764 | .@"addrspace" = .generic, |
| 4870 | 4765 | .analysis = .unreferenced, |
| 4871 | | .deletion_flag = false, |
| 4872 | 4766 | .zir_decl_index = .none, |
| 4873 | 4767 | .src_scope = src_scope, |
| 4874 | 4768 | .generation = 0, |
| ... | ... | @@ -5366,52 +5260,6 @@ pub fn optionsSrc(mod: *Module, decl: *Decl, base_src: LazySrcLoc, wanted: []con |
| 5366 | 5260 | return base_src; |
| 5367 | 5261 | } |
| 5368 | 5262 | |
| 5369 | | /// Called from `performAllTheWork`, after all AstGen workers have finished, |
| 5370 | | /// and before the main semantic analysis loop begins. |
| 5371 | | pub fn processOutdatedAndDeletedDecls(mod: *Module) !void { |
| 5372 | | // Ultimately, the goal is to queue up `analyze_decl` tasks in the work queue |
| 5373 | | // for the outdated decls, but we cannot queue up the tasks until after |
| 5374 | | // we find out which ones have been deleted, otherwise there would be |
| 5375 | | // deleted Decl pointers in the work queue. |
| 5376 | | var outdated_decls = std.AutoArrayHashMap(Decl.Index, void).init(mod.gpa); |
| 5377 | | defer outdated_decls.deinit(); |
| 5378 | | for (mod.import_table.values()) |file| { |
| 5379 | | try outdated_decls.ensureUnusedCapacity(file.outdated_decls.items.len); |
| 5380 | | for (file.outdated_decls.items) |decl_index| { |
| 5381 | | outdated_decls.putAssumeCapacity(decl_index, {}); |
| 5382 | | } |
| 5383 | | file.outdated_decls.clearRetainingCapacity(); |
| 5384 | | |
| 5385 | | // Handle explicitly deleted decls from the source code. This is one of two |
| 5386 | | // places that Decl deletions happen. The other is in `Compilation`, after |
| 5387 | | // `performAllTheWork`, where we iterate over `Module.deletion_set` and |
| 5388 | | // delete Decls which are no longer referenced. |
| 5389 | | // If a Decl is explicitly deleted from source, and also no longer referenced, |
| 5390 | | // it may be both in this `deleted_decls` set, as well as in the |
| 5391 | | // `Module.deletion_set`. To avoid deleting it twice, we remove it from the |
| 5392 | | // deletion set at this time. |
| 5393 | | for (file.deleted_decls.items) |decl_index| { |
| 5394 | | const decl = mod.declPtr(decl_index); |
| 5395 | | |
| 5396 | | // Remove from the namespace it resides in, preserving declaration order. |
| 5397 | | assert(decl.zir_decl_index != .none); |
| 5398 | | _ = mod.namespacePtr(decl.src_namespace).decls.orderedRemoveAdapted( |
| 5399 | | decl.name, |
| 5400 | | DeclAdapter{ .mod = mod }, |
| 5401 | | ); |
| 5402 | | |
| 5403 | | try mod.clearDecl(decl_index, &outdated_decls); |
| 5404 | | mod.destroyDecl(decl_index); |
| 5405 | | } |
| 5406 | | file.deleted_decls.clearRetainingCapacity(); |
| 5407 | | } |
| 5408 | | // Finally we can queue up re-analysis tasks after we have processed |
| 5409 | | // the deleted decls. |
| 5410 | | for (outdated_decls.keys()) |key| { |
| 5411 | | try mod.markOutdatedDecl(key); |
| 5412 | | } |
| 5413 | | } |
| 5414 | | |
| 5415 | 5263 | /// Called from `Compilation.update`, after everything is done, just before |
| 5416 | 5264 | /// reporting compile errors. In this function we emit exported symbol collision |
| 5417 | 5265 | /// errors and communicate exported symbols to the linker backend. |