| ... | @@ -132,10 +132,6 @@ failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{}, | ... | @@ -132,10 +132,6 @@ failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{}, |
| 132 | /// are stored here. | 132 | /// are stored here. |
| 133 | cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, std.zig.ErrorBundle) = .{}, | 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 | /// Key is the error name, index is the error tag value. Index 0 has a length-0 string. | 135 | /// Key is the error name, index is the error tag value. Index 0 has a length-0 string. |
| 140 | global_error_set: GlobalErrorSet = .{}, | 136 | global_error_set: GlobalErrorSet = .{}, |
| 141 | | 137 | |
| ... | @@ -165,7 +161,7 @@ emit_h: ?*GlobalEmitH, | ... | @@ -165,7 +161,7 @@ emit_h: ?*GlobalEmitH, |
| 165 | | 161 | |
| 166 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | 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 | reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { | 166 | reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { |
| 171 | referencer: Decl.Index, | 167 | referencer: Decl.Index, |
| ... | @@ -438,9 +434,6 @@ pub const Decl = struct { | ... | @@ -438,9 +434,6 @@ pub const Decl = struct { |
| 438 | /// with it. That means when `Decl` is destroyed, the cleanup code should additionally | 434 | /// with it. That means when `Decl` is destroyed, the cleanup code should additionally |
| 439 | /// check if the value owns a `Namespace`, and destroy that too. | 435 | /// check if the value owns a `Namespace`, and destroy that too. |
| 440 | owns_tv: bool, | 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 | /// Whether the corresponding AST decl has a `pub` keyword. | 437 | /// Whether the corresponding AST decl has a `pub` keyword. |
| 445 | is_pub: bool, | 438 | is_pub: bool, |
| 446 | /// Whether the corresponding AST decl has a `export` keyword. | 439 | /// Whether the corresponding AST decl has a `export` keyword. |
| ... | @@ -873,47 +866,6 @@ pub const Namespace = struct { | ... | @@ -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 | // This renders e.g. "std.fs.Dir.OpenOptions" | 869 | // This renders e.g. "std.fs.Dir.OpenOptions" |
| 918 | pub fn renderFullyQualifiedName( | 870 | pub fn renderFullyQualifiedName( |
| 919 | ns: Namespace, | 871 | ns: Namespace, |
| ... | @@ -2527,7 +2479,6 @@ pub fn deinit(mod: *Module) void { | ... | @@ -2527,7 +2479,6 @@ pub fn deinit(mod: *Module) void { |
| 2527 | mod.embed_table.deinit(gpa); | 2479 | mod.embed_table.deinit(gpa); |
| 2528 | } | 2480 | } |
| 2529 | | 2481 | |
| 2530 | mod.deletion_set.deinit(gpa); | | |
| 2531 | mod.compile_log_text.deinit(gpa); | 2482 | mod.compile_log_text.deinit(gpa); |
| 2532 | | 2483 | |
| 2533 | mod.zig_cache_artifact_directory.handle.close(); | 2484 | mod.zig_cache_artifact_directory.handle.close(); |
| ... | @@ -2590,9 +2541,21 @@ pub fn deinit(mod: *Module) void { | ... | @@ -2590,9 +2541,21 @@ pub fn deinit(mod: *Module) void { |
| 2590 | | 2541 | |
| 2591 | mod.test_functions.deinit(gpa); | 2542 | mod.test_functions.deinit(gpa); |
| 2592 | | 2543 | |
| | 2544 | for (mod.global_assembly.values()) |s| { |
| | 2545 | gpa.free(s); |
| | 2546 | } |
| 2593 | mod.global_assembly.deinit(gpa); | 2547 | mod.global_assembly.deinit(gpa); |
| | 2548 | |
| 2594 | mod.reference_table.deinit(gpa); | 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 | mod.intern_pool.deinit(gpa); | 2559 | mod.intern_pool.deinit(gpa); |
| 2597 | mod.tmp_hack_arena.deinit(); | 2560 | mod.tmp_hack_arena.deinit(); |
| 2598 | | 2561 | |
| ... | @@ -2606,20 +2569,10 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { | ... | @@ -2606,20 +2569,10 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| 2606 | const ip = &mod.intern_pool; | 2569 | const ip = &mod.intern_pool; |
| 2607 | | 2570 | |
| 2608 | { | 2571 | { |
| 2609 | const decl = mod.declPtr(decl_index); | | |
| 2610 | _ = mod.test_functions.swapRemove(decl_index); | 2572 | _ = mod.test_functions.swapRemove(decl_index); |
| 2611 | if (decl.deletion_flag) { | 2573 | if (mod.global_assembly.fetchSwapRemove(decl_index)) |kv| { |
| 2612 | assert(mod.deletion_set.swapRemove(decl_index)); | | |
| 2613 | } | | |
| 2614 | if (mod.global_assembly.fetchRemove(decl_index)) |kv| { | | |
| 2615 | gpa.free(kv.value); | 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 | ip.destroyDecl(gpa, decl_index); | 2578 | ip.destroyDecl(gpa, decl_index); |
| ... | @@ -4422,56 +4375,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -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 | /// This function is exclusively called for anonymous decls. | 4378 | /// This function is exclusively called for anonymous decls. |
| 4476 | /// All resources referenced by anonymous decls are owned by InternPool | 4379 | /// All resources referenced by anonymous decls are owned by InternPool |
| 4477 | /// so there is no cleanup to do here. | 4380 | /// so there is no cleanup to do here. |
| ... | @@ -4488,14 +4391,6 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { | ... | @@ -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 | /// Cancel the creation of an anon decl and delete any references to it. | 4394 | /// Cancel the creation of an anon decl and delete any references to it. |
| 4500 | /// If other decls depend on this decl, they must be aborted first. | 4395 | /// If other decls depend on this decl, they must be aborted first. |
| 4501 | pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { | 4396 | pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { |
| ... | @@ -4868,7 +4763,6 @@ pub fn allocateNewDecl( | ... | @@ -4868,7 +4763,6 @@ pub fn allocateNewDecl( |
| 4868 | .@"linksection" = .none, | 4763 | .@"linksection" = .none, |
| 4869 | .@"addrspace" = .generic, | 4764 | .@"addrspace" = .generic, |
| 4870 | .analysis = .unreferenced, | 4765 | .analysis = .unreferenced, |
| 4871 | .deletion_flag = false, | | |
| 4872 | .zir_decl_index = .none, | 4766 | .zir_decl_index = .none, |
| 4873 | .src_scope = src_scope, | 4767 | .src_scope = src_scope, |
| 4874 | .generation = 0, | 4768 | .generation = 0, |
| ... | @@ -5366,52 +5260,6 @@ pub fn optionsSrc(mod: *Module, decl: *Decl, base_src: LazySrcLoc, wanted: []con | ... | @@ -5366,52 +5260,6 @@ pub fn optionsSrc(mod: *Module, decl: *Decl, base_src: LazySrcLoc, wanted: []con |
| 5366 | return base_src; | 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 | /// Called from `Compilation.update`, after everything is done, just before | 5263 | /// Called from `Compilation.update`, after everything is done, just before |
| 5416 | /// reporting compile errors. In this function we emit exported symbol collision | 5264 | /// reporting compile errors. In this function we emit exported symbol collision |
| 5417 | /// errors and communicate exported symbols to the linker backend. | 5265 | /// errors and communicate exported symbols to the linker backend. |