| ... | @@ -291,7 +291,7 @@ pub const Decl = struct { | ... | @@ -291,7 +291,7 @@ pub const Decl = struct { |
| 291 | } | 291 | } |
| 292 | if (decl.has_tv) { | 292 | if (decl.has_tv) { |
| 293 | if (decl.getInnerNamespace()) |namespace| { | 293 | if (decl.getInnerNamespace()) |namespace| { |
| 294 | namespace.clearDecls(module); | 294 | namespace.destroyDecls(module); |
| 295 | } | 295 | } |
| 296 | decl.clearValues(gpa); | 296 | decl.clearValues(gpa); |
| 297 | } | 297 | } |
| ... | @@ -880,14 +880,14 @@ pub const Scope = struct { | ... | @@ -880,14 +880,14 @@ pub const Scope = struct { |
| 880 | anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, | 880 | anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, |
| 881 | | 881 | |
| 882 | pub fn deinit(ns: *Namespace, mod: *Module) void { | 882 | pub fn deinit(ns: *Namespace, mod: *Module) void { |
| 883 | ns.clearDecls(mod); | 883 | ns.destroyDecls(mod); |
| 884 | ns.* = undefined; | 884 | ns.* = undefined; |
| 885 | } | 885 | } |
| 886 | | 886 | |
| 887 | pub fn clearDecls(ns: *Namespace, mod: *Module) void { | 887 | pub fn destroyDecls(ns: *Namespace, mod: *Module) void { |
| 888 | const gpa = mod.gpa; | 888 | const gpa = mod.gpa; |
| 889 | | 889 | |
| 890 | log.debug("clearDecls {*}", .{ns}); | 890 | log.debug("destroyDecls {*}", .{ns}); |
| 891 | | 891 | |
| 892 | var decls = ns.decls; | 892 | var decls = ns.decls; |
| 893 | ns.decls = .{}; | 893 | ns.decls = .{}; |
| ... | @@ -915,30 +915,28 @@ pub const Scope = struct { | ... | @@ -915,30 +915,28 @@ pub const Scope = struct { |
| 915 | | 915 | |
| 916 | log.debug("deleteAllDecls {*}", .{ns}); | 916 | log.debug("deleteAllDecls {*}", .{ns}); |
| 917 | | 917 | |
| 918 | while (ns.decls.count() != 0) { | 918 | var decls = ns.decls; |
| 919 | const last_entry = ns.decls.entries.items[ns.decls.entries.items.len - 1]; | | |
| 920 | const child_decl = last_entry.value; | | |
| 921 | try mod.deleteDecl(child_decl, outdated_decls); | | |
| 922 | } | | |
| 923 | ns.decls.deinit(gpa); | | |
| 924 | ns.decls = .{}; | 919 | ns.decls = .{}; |
| 925 | | 920 | |
| 926 | while (ns.anon_decls.count() != 0) { | 921 | var anon_decls = ns.anon_decls; |
| 927 | const last_entry = ns.anon_decls.entries.items[ns.anon_decls.entries.items.len - 1]; | | |
| 928 | const child_decl = last_entry.key; | | |
| 929 | try mod.deleteDecl(child_decl, outdated_decls); | | |
| 930 | } | | |
| 931 | ns.anon_decls.deinit(gpa); | | |
| 932 | ns.anon_decls = .{}; | 922 | ns.anon_decls = .{}; |
| 933 | } | | |
| 934 | | 923 | |
| 935 | pub fn removeDecl(ns: *Namespace, child: *Decl) void { | 924 | // TODO rework this code to not panic on OOM. |
| 936 | if (child.zir_decl_index == 0) { | 925 | // (might want to coordinate with the clearDecl function) |
| 937 | _ = ns.anon_decls.swapRemove(child); | 926 | |
| 938 | } else { | 927 | for (decls.items()) |entry| { |
| 939 | // Preserve declaration order. | 928 | const child_decl = entry.value; |
| 940 | _ = ns.decls.orderedRemove(mem.spanZ(child.name)); | 929 | mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); |
| | 930 | child_decl.destroy(mod); |
| | 931 | } |
| | 932 | decls.deinit(gpa); |
| | 933 | |
| | 934 | for (anon_decls.items()) |entry| { |
| | 935 | const child_decl = entry.key; |
| | 936 | mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); |
| | 937 | child_decl.destroy(mod); |
| 941 | } | 938 | } |
| | 939 | anon_decls.deinit(gpa); |
| 942 | } | 940 | } |
| 943 | | 941 | |
| 944 | // This renders e.g. "std.fs.Dir.OpenOptions" | 942 | // This renders e.g. "std.fs.Dir.OpenOptions" |
| ... | @@ -2122,6 +2120,14 @@ pub const InnerError = error{ OutOfMemory, AnalysisFail }; | ... | @@ -2122,6 +2120,14 @@ pub const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 2122 | pub fn deinit(mod: *Module) void { | 2120 | pub fn deinit(mod: *Module) void { |
| 2123 | const gpa = mod.gpa; | 2121 | const gpa = mod.gpa; |
| 2124 | | 2122 | |
| | 2123 | for (mod.import_table.items()) |entry| { |
| | 2124 | gpa.free(entry.key); |
| | 2125 | entry.value.destroy(mod); |
| | 2126 | } |
| | 2127 | mod.import_table.deinit(gpa); |
| | 2128 | |
| | 2129 | mod.deletion_set.deinit(gpa); |
| | 2130 | |
| 2125 | // The callsite of `Compilation.create` owns the `root_pkg`, however | 2131 | // The callsite of `Compilation.create` owns the `root_pkg`, however |
| 2126 | // Module owns the builtin and std packages that it adds. | 2132 | // Module owns the builtin and std packages that it adds. |
| 2127 | if (mod.root_pkg.table.remove("builtin")) |entry| { | 2133 | if (mod.root_pkg.table.remove("builtin")) |entry| { |
| ... | @@ -2142,8 +2148,6 @@ pub fn deinit(mod: *Module) void { | ... | @@ -2142,8 +2148,6 @@ pub fn deinit(mod: *Module) void { |
| 2142 | mod.local_zir_cache.handle.close(); | 2148 | mod.local_zir_cache.handle.close(); |
| 2143 | mod.global_zir_cache.handle.close(); | 2149 | mod.global_zir_cache.handle.close(); |
| 2144 | | 2150 | |
| 2145 | mod.deletion_set.deinit(gpa); | | |
| 2146 | | | |
| 2147 | for (mod.failed_decls.items()) |entry| { | 2151 | for (mod.failed_decls.items()) |entry| { |
| 2148 | entry.value.destroy(gpa); | 2152 | entry.value.destroy(gpa); |
| 2149 | } | 2153 | } |
| ... | @@ -2188,12 +2192,6 @@ pub fn deinit(mod: *Module) void { | ... | @@ -2188,12 +2192,6 @@ pub fn deinit(mod: *Module) void { |
| 2188 | mod.global_error_set.deinit(gpa); | 2192 | mod.global_error_set.deinit(gpa); |
| 2189 | | 2193 | |
| 2190 | mod.error_name_list.deinit(gpa); | 2194 | mod.error_name_list.deinit(gpa); |
| 2191 | | | |
| 2192 | for (mod.import_table.items()) |entry| { | | |
| 2193 | gpa.free(entry.key); | | |
| 2194 | entry.value.destroy(mod); | | |
| 2195 | } | | |
| 2196 | mod.import_table.deinit(gpa); | | |
| 2197 | } | 2195 | } |
| 2198 | | 2196 | |
| 2199 | fn freeExportList(gpa: *Allocator, export_list: []*Export) void { | 2197 | fn freeExportList(gpa: *Allocator, export_list: []*Export) void { |
| ... | @@ -3420,7 +3418,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo | ... | @@ -3420,7 +3418,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo |
| 3420 | } | 3418 | } |
| 3421 | } | 3419 | } |
| 3422 | | 3420 | |
| 3423 | pub fn deleteDecl( | 3421 | /// Make it as if the semantic analysis for this Decl never happened. |
| | 3422 | pub fn clearDecl( |
| 3424 | mod: *Module, | 3423 | mod: *Module, |
| 3425 | decl: *Decl, | 3424 | decl: *Decl, |
| 3426 | outdated_decls: ?*std.AutoArrayHashMap(*Decl, void), | 3425 | outdated_decls: ?*std.AutoArrayHashMap(*Decl, void), |
| ... | @@ -3428,7 +3427,7 @@ pub fn deleteDecl( | ... | @@ -3428,7 +3427,7 @@ pub fn deleteDecl( |
| 3428 | const tracy = trace(@src()); | 3427 | const tracy = trace(@src()); |
| 3429 | defer tracy.end(); | 3428 | defer tracy.end(); |
| 3430 | | 3429 | |
| 3431 | log.debug("deleting {*} ({s})", .{ decl, decl.name }); | 3430 | log.debug("clearing {*} ({s})", .{ decl, decl.name }); |
| 3432 | | 3431 | |
| 3433 | const gpa = mod.gpa; | 3432 | const gpa = mod.gpa; |
| 3434 | try mod.deletion_set.ensureUnusedCapacity(gpa, decl.dependencies.count()); | 3433 | try mod.deletion_set.ensureUnusedCapacity(gpa, decl.dependencies.count()); |
| ... | @@ -3438,10 +3437,7 @@ pub fn deleteDecl( | ... | @@ -3438,10 +3437,7 @@ pub fn deleteDecl( |
| 3438 | try map.ensureUnusedCapacity(decl.dependants.count()); | 3437 | try map.ensureUnusedCapacity(decl.dependants.count()); |
| 3439 | } | 3438 | } |
| 3440 | | 3439 | |
| 3441 | // Remove from the namespace it resides in. | 3440 | // Remove itself from its dependencies. |
| 3442 | decl.namespace.removeDecl(decl); | | |
| 3443 | | | |
| 3444 | // Remove itself from its dependencies, because we are about to destroy the decl pointer. | | |
| 3445 | for (decl.dependencies.items()) |entry| { | 3441 | for (decl.dependencies.items()) |entry| { |
| 3446 | const dep = entry.key; | 3442 | const dep = entry.key; |
| 3447 | dep.removeDependant(decl); | 3443 | dep.removeDependant(decl); |
| ... | @@ -3452,6 +3448,8 @@ pub fn deleteDecl( | ... | @@ -3452,6 +3448,8 @@ pub fn deleteDecl( |
| 3452 | mod.deletion_set.putAssumeCapacity(dep, {}); | 3448 | mod.deletion_set.putAssumeCapacity(dep, {}); |
| 3453 | } | 3449 | } |
| 3454 | } | 3450 | } |
| | 3451 | decl.dependencies.clearRetainingCapacity(); |
| | 3452 | |
| 3455 | // Anything that depends on this deleted decl needs to be re-analyzed. | 3453 | // Anything that depends on this deleted decl needs to be re-analyzed. |
| 3456 | for (decl.dependants.items()) |entry| { | 3454 | for (decl.dependants.items()) |entry| { |
| 3457 | const dep = entry.key; | 3455 | const dep = entry.key; |
| ... | @@ -3467,6 +3465,8 @@ pub fn deleteDecl( | ... | @@ -3467,6 +3465,8 @@ pub fn deleteDecl( |
| 3467 | assert(mod.deletion_set.contains(dep)); | 3465 | assert(mod.deletion_set.contains(dep)); |
| 3468 | } | 3466 | } |
| 3469 | } | 3467 | } |
| | 3468 | decl.dependants.clearRetainingCapacity(); |
| | 3469 | |
| 3470 | if (mod.failed_decls.swapRemove(decl)) |entry| { | 3470 | if (mod.failed_decls.swapRemove(decl)) |entry| { |
| 3471 | entry.value.destroy(gpa); | 3471 | entry.value.destroy(gpa); |
| 3472 | } | 3472 | } |
| ... | @@ -3482,6 +3482,25 @@ pub fn deleteDecl( | ... | @@ -3482,6 +3482,25 @@ pub fn deleteDecl( |
| 3482 | if (decl.has_tv) { | 3482 | if (decl.has_tv) { |
| 3483 | if (decl.ty.hasCodeGenBits()) { | 3483 | if (decl.ty.hasCodeGenBits()) { |
| 3484 | mod.comp.bin_file.freeDecl(decl); | 3484 | mod.comp.bin_file.freeDecl(decl); |
| | 3485 | |
| | 3486 | // TODO instead of a union, put this memory trailing Decl objects, |
| | 3487 | // and allow it to be variably sized. |
| | 3488 | decl.link = switch (mod.comp.bin_file.tag) { |
| | 3489 | .coff => .{ .coff = link.File.Coff.TextBlock.empty }, |
| | 3490 | .elf => .{ .elf = link.File.Elf.TextBlock.empty }, |
| | 3491 | .macho => .{ .macho = link.File.MachO.TextBlock.empty }, |
| | 3492 | .c => .{ .c = link.File.C.DeclBlock.empty }, |
| | 3493 | .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty }, |
| | 3494 | .spirv => .{ .spirv = {} }, |
| | 3495 | }; |
| | 3496 | decl.fn_link = switch (mod.comp.bin_file.tag) { |
| | 3497 | .coff => .{ .coff = {} }, |
| | 3498 | .elf => .{ .elf = link.File.Elf.SrcFn.empty }, |
| | 3499 | .macho => .{ .macho = link.File.MachO.SrcFn.empty }, |
| | 3500 | .c => .{ .c = link.File.C.FnBlock.empty }, |
| | 3501 | .wasm => .{ .wasm = link.File.Wasm.FnData.empty }, |
| | 3502 | .spirv => .{ .spirv = .{} }, |
| | 3503 | }; |
| 3485 | } | 3504 | } |
| 3486 | if (decl.getInnerNamespace()) |namespace| { | 3505 | if (decl.getInnerNamespace()) |namespace| { |
| 3487 | try namespace.deleteAllDecls(mod, outdated_decls); | 3506 | try namespace.deleteAllDecls(mod, outdated_decls); |
| ... | @@ -3489,7 +3508,12 @@ pub fn deleteDecl( | ... | @@ -3489,7 +3508,12 @@ pub fn deleteDecl( |
| 3489 | decl.clearValues(gpa); | 3508 | decl.clearValues(gpa); |
| 3490 | } | 3509 | } |
| 3491 | | 3510 | |
| 3492 | decl.destroy(mod); | 3511 | if (decl.deletion_flag) { |
| | 3512 | decl.deletion_flag = false; |
| | 3513 | mod.deletion_set.swapRemoveAssertDiscard(decl); |
| | 3514 | } |
| | 3515 | |
| | 3516 | decl.analysis = .unreferenced; |
| 3493 | } | 3517 | } |
| 3494 | | 3518 | |
| 3495 | /// Delete all the Export objects that are caused by this Decl. Re-analysis of | 3519 | /// Delete all the Export objects that are caused by this Decl. Re-analysis of |
| ... | @@ -4836,7 +4860,13 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void { | ... | @@ -4836,7 +4860,13 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void { |
| 4836 | // deletion set at this time. | 4860 | // deletion set at this time. |
| 4837 | for (file.deleted_decls.items) |decl| { | 4861 | for (file.deleted_decls.items) |decl| { |
| 4838 | log.debug("deleted from source: {*} ({s})", .{ decl, decl.name }); | 4862 | log.debug("deleted from source: {*} ({s})", .{ decl, decl.name }); |
| 4839 | try mod.deleteDecl(decl, &outdated_decls); | 4863 | |
| | 4864 | // Remove from the namespace it resides in, preserving declaration order. |
| | 4865 | assert(decl.zir_decl_index != 0); |
| | 4866 | _ = decl.namespace.decls.orderedRemove(mem.spanZ(decl.name)); |
| | 4867 | |
| | 4868 | try mod.clearDecl(decl, &outdated_decls); |
| | 4869 | decl.destroy(mod); |
| 4840 | } | 4870 | } |
| 4841 | file.deleted_decls.clearRetainingCapacity(); | 4871 | file.deleted_decls.clearRetainingCapacity(); |
| 4842 | } | 4872 | } |