| ... | @@ -154,9 +154,7 @@ pub const DeclPlusEmitH = struct { | ... | @@ -154,9 +154,7 @@ pub const DeclPlusEmitH = struct { |
| 154 | }; | 154 | }; |
| 155 | | 155 | |
| 156 | pub const Decl = struct { | 156 | pub const Decl = struct { |
| 157 | /// For declarations that have corresponding source code, this is identical to | 157 | /// Allocated with Module's allocator; outlives the ZIR code. |
| 158 | /// `getName().?`. For anonymous declarations this is allocated with Module's | | |
| 159 | /// allocator. | | |
| 160 | name: [*:0]const u8, | 158 | name: [*:0]const u8, |
| 161 | /// The most recent Type of the Decl after a successful semantic analysis. | 159 | /// The most recent Type of the Decl after a successful semantic analysis. |
| 162 | /// Populated when `has_tv`. | 160 | /// Populated when `has_tv`. |
| ... | @@ -270,13 +268,7 @@ pub const Decl = struct { | ... | @@ -270,13 +268,7 @@ pub const Decl = struct { |
| 270 | ); | 268 | ); |
| 271 | | 269 | |
| 272 | pub fn clearName(decl: *Decl, gpa: *Allocator) void { | 270 | pub fn clearName(decl: *Decl, gpa: *Allocator) void { |
| 273 | // name could be allocated in the ZIR or it could be owned by gpa. | 271 | gpa.free(mem.spanZ(decl.name)); |
| 274 | const file = decl.namespace.file_scope; | | |
| 275 | const string_table_start = @ptrToInt(file.zir.string_bytes.ptr); | | |
| 276 | const string_table_end = string_table_start + file.zir.string_bytes.len; | | |
| 277 | if (@ptrToInt(decl.name) < string_table_start or @ptrToInt(decl.name) >= string_table_end) { | | |
| 278 | gpa.free(mem.spanZ(decl.name)); | | |
| 279 | } | | |
| 280 | decl.name = undefined; | 272 | decl.name = undefined; |
| 281 | } | 273 | } |
| 282 | | 274 | |
| ... | @@ -285,7 +277,7 @@ pub const Decl = struct { | ... | @@ -285,7 +277,7 @@ pub const Decl = struct { |
| 285 | log.debug("destroy {*} ({s})", .{ decl, decl.name }); | 277 | log.debug("destroy {*} ({s})", .{ decl, decl.name }); |
| 286 | decl.clearName(gpa); | 278 | decl.clearName(gpa); |
| 287 | if (decl.has_tv) { | 279 | if (decl.has_tv) { |
| 288 | if (decl.val.getTypeNamespace()) |namespace| { | 280 | if (decl.getInnerNamespace()) |namespace| { |
| 289 | if (namespace.getDecl() == decl) { | 281 | if (namespace.getDecl() == decl) { |
| 290 | namespace.clearDecls(module); | 282 | namespace.clearDecls(module); |
| 291 | } | 283 | } |
| ... | @@ -308,6 +300,9 @@ pub const Decl = struct { | ... | @@ -308,6 +300,9 @@ pub const Decl = struct { |
| 308 | func.deinit(gpa); | 300 | func.deinit(gpa); |
| 309 | gpa.destroy(func); | 301 | gpa.destroy(func); |
| 310 | } | 302 | } |
| | 303 | if (decl.getVariable()) |variable| { |
| | 304 | gpa.destroy(variable); |
| | 305 | } |
| 311 | if (decl.value_arena) |arena_state| { | 306 | if (decl.value_arena) |arena_state| { |
| 312 | arena_state.promote(gpa).deinit(); | 307 | arena_state.promote(gpa).deinit(); |
| 313 | decl.value_arena = null; | 308 | decl.value_arena = null; |
| ... | @@ -472,6 +467,47 @@ pub const Decl = struct { | ... | @@ -472,6 +467,47 @@ pub const Decl = struct { |
| 472 | return func; | 467 | return func; |
| 473 | } | 468 | } |
| 474 | | 469 | |
| | 470 | pub fn getVariable(decl: *Decl) ?*Var { |
| | 471 | if (!decl.has_tv) return null; |
| | 472 | const variable = (decl.val.castTag(.variable) orelse return null).data; |
| | 473 | if (variable.owner_decl != decl) return null; |
| | 474 | return variable; |
| | 475 | } |
| | 476 | |
| | 477 | /// Gets the namespace that this Decl creates by being a struct, union, |
| | 478 | /// enum, or opaque. |
| | 479 | /// Only returns it if the Decl is the owner. |
| | 480 | pub fn getInnerNamespace(decl: *Decl) ?*Scope.Namespace { |
| | 481 | if (!decl.has_tv) return null; |
| | 482 | const ty = (decl.val.castTag(.ty) orelse return null).data; |
| | 483 | switch (ty.tag()) { |
| | 484 | .@"struct" => { |
| | 485 | const struct_obj = ty.castTag(.@"struct").?.data; |
| | 486 | if (struct_obj.owner_decl != decl) return null; |
| | 487 | return &struct_obj.namespace; |
| | 488 | }, |
| | 489 | .enum_full => { |
| | 490 | const enum_obj = ty.castTag(.enum_full).?.data; |
| | 491 | if (enum_obj.owner_decl != decl) return null; |
| | 492 | return &enum_obj.namespace; |
| | 493 | }, |
| | 494 | .empty_struct => { |
| | 495 | // design flaw, can't verify the owner is this decl |
| | 496 | @panic("TODO can't implement getInnerNamespace for this type"); |
| | 497 | }, |
| | 498 | .@"opaque" => { |
| | 499 | @panic("TODO opaque types"); |
| | 500 | }, |
| | 501 | .@"union", .union_tagged => { |
| | 502 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| | 503 | if (union_obj.owner_decl != decl) return null; |
| | 504 | return &union_obj.namespace; |
| | 505 | }, |
| | 506 | |
| | 507 | else => return null, |
| | 508 | } |
| | 509 | } |
| | 510 | |
| 475 | pub fn dump(decl: *Decl) void { | 511 | pub fn dump(decl: *Decl) void { |
| 476 | const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src); | 512 | const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src); |
| 477 | std.debug.print("{s}:{d}:{d} name={s} status={s}", .{ | 513 | std.debug.print("{s}:{d}:{d} name={s} status={s}", .{ |
| ... | @@ -504,6 +540,23 @@ pub const Decl = struct { | ... | @@ -504,6 +540,23 @@ pub const Decl = struct { |
| 504 | fn removeDependency(decl: *Decl, other: *Decl) void { | 540 | fn removeDependency(decl: *Decl, other: *Decl) void { |
| 505 | decl.dependencies.removeAssertDiscard(other); | 541 | decl.dependencies.removeAssertDiscard(other); |
| 506 | } | 542 | } |
| | 543 | |
| | 544 | fn hasLinkAllocation(decl: Decl) bool { |
| | 545 | return switch (decl.analysis) { |
| | 546 | .unreferenced, |
| | 547 | .in_progress, |
| | 548 | .dependency_failure, |
| | 549 | .sema_failure, |
| | 550 | .sema_failure_retryable, |
| | 551 | .codegen_failure, |
| | 552 | .codegen_failure_retryable, |
| | 553 | => false, |
| | 554 | |
| | 555 | .complete, |
| | 556 | .outdated, |
| | 557 | => true, |
| | 558 | }; |
| | 559 | } |
| 507 | }; | 560 | }; |
| 508 | | 561 | |
| 509 | /// This state is attached to every Decl when Module emit_h is non-null. | 562 | /// This state is attached to every Decl when Module emit_h is non-null. |
| ... | @@ -831,9 +884,8 @@ pub const Scope = struct { | ... | @@ -831,9 +884,8 @@ pub const Scope = struct { |
| 831 | /// Direct children of the namespace. Used during an update to detect | 884 | /// Direct children of the namespace. Used during an update to detect |
| 832 | /// which decls have been added/removed from source. | 885 | /// which decls have been added/removed from source. |
| 833 | /// Declaration order is preserved via entry order. | 886 | /// Declaration order is preserved via entry order. |
| 834 | /// Key memory references the string table of the containing `File` ZIR. | 887 | /// Key memory is owned by `decl.name`. |
| 835 | /// TODO save memory with https://github.com/ziglang/zig/issues/8619. | 888 | /// TODO save memory with https://github.com/ziglang/zig/issues/8619. |
| 836 | /// Does not contain anonymous decls. | | |
| 837 | decls: std.StringArrayHashMapUnmanaged(*Decl) = .{}, | 889 | decls: std.StringArrayHashMapUnmanaged(*Decl) = .{}, |
| 838 | | 890 | |
| 839 | pub fn deinit(ns: *Namespace, mod: *Module) void { | 891 | pub fn deinit(ns: *Namespace, mod: *Module) void { |
| ... | @@ -2468,8 +2520,6 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node | ... | @@ -2468,8 +2520,6 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node |
| 2468 | /// * Decl.zir_index | 2520 | /// * Decl.zir_index |
| 2469 | /// * Fn.zir_body_inst | 2521 | /// * Fn.zir_body_inst |
| 2470 | /// * Decl.zir_decl_index | 2522 | /// * Decl.zir_decl_index |
| 2471 | /// * Decl.name | | |
| 2472 | /// * Namespace.decl keys | | |
| 2473 | fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { | 2523 | fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { |
| 2474 | const new_zir = file.zir; | 2524 | const new_zir = file.zir; |
| 2475 | | 2525 | |
| ... | @@ -2484,18 +2534,6 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { | ... | @@ -2484,18 +2534,6 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { |
| 2484 | | 2534 | |
| 2485 | try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map, &extra_map); | 2535 | try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map, &extra_map); |
| 2486 | | 2536 | |
| 2487 | // Build string table for new ZIR. | | |
| 2488 | var string_table: std.StringHashMapUnmanaged(u32) = .{}; | | |
| 2489 | defer string_table.deinit(gpa); | | |
| 2490 | { | | |
| 2491 | var i: usize = 2; | | |
| 2492 | while (i < new_zir.string_bytes.len) { | | |
| 2493 | const string = new_zir.nullTerminatedString(i); | | |
| 2494 | try string_table.put(gpa, string, @intCast(u32, i)); | | |
| 2495 | i += string.len + 1; | | |
| 2496 | } | | |
| 2497 | } | | |
| 2498 | | | |
| 2499 | // Walk the Decl graph, updating ZIR indexes, strings, and populating | 2537 | // Walk the Decl graph, updating ZIR indexes, strings, and populating |
| 2500 | // the deleted and outdated lists. | 2538 | // the deleted and outdated lists. |
| 2501 | | 2539 | |
| ... | @@ -2523,12 +2561,6 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { | ... | @@ -2523,12 +2561,6 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { |
| 2523 | try file.deleted_decls.append(gpa, decl); | 2561 | try file.deleted_decls.append(gpa, decl); |
| 2524 | continue; | 2562 | continue; |
| 2525 | }; | 2563 | }; |
| 2526 | const new_name_index = string_table.get(mem.spanZ(decl.name)) orelse { | | |
| 2527 | try file.deleted_decls.append(gpa, decl); | | |
| 2528 | continue; | | |
| 2529 | }; | | |
| 2530 | decl.name = new_zir.nullTerminatedString(new_name_index).ptr; | | |
| 2531 | | | |
| 2532 | const new_hash = decl.contentsHashZir(new_zir); | 2564 | const new_hash = decl.contentsHashZir(new_zir); |
| 2533 | if (!std.zig.srcHashEql(old_hash, new_hash)) { | 2565 | if (!std.zig.srcHashEql(old_hash, new_hash)) { |
| 2534 | try file.outdated_decls.append(gpa, decl); | 2566 | try file.outdated_decls.append(gpa, decl); |
| ... | @@ -2558,16 +2590,9 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { | ... | @@ -2558,16 +2590,9 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { |
| 2558 | }; | 2590 | }; |
| 2559 | } | 2591 | } |
| 2560 | | 2592 | |
| 2561 | if (decl.val.getTypeNamespace()) |namespace| { | 2593 | if (decl.getInnerNamespace()) |namespace| { |
| 2562 | for (namespace.decls.items()) |*entry| { | 2594 | for (namespace.decls.items()) |*entry| { |
| 2563 | const sub_decl = entry.value; | 2595 | const sub_decl = entry.value; |
| 2564 | if (sub_decl.zir_decl_index != 0) { | | |
| 2565 | const new_key_index = string_table.get(entry.key) orelse { | | |
| 2566 | try file.deleted_decls.append(gpa, sub_decl); | | |
| 2567 | continue; | | |
| 2568 | }; | | |
| 2569 | entry.key = new_zir.nullTerminatedString(new_key_index); | | |
| 2570 | } | | |
| 2571 | try decl_stack.append(gpa, sub_decl); | 2596 | try decl_stack.append(gpa, sub_decl); |
| 2572 | } | 2597 | } |
| 2573 | } | 2598 | } |
| ... | @@ -2936,46 +2961,14 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -2936,46 +2961,14 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 2936 | } | 2961 | } |
| 2937 | return type_changed or is_inline != prev_is_inline; | 2962 | return type_changed or is_inline != prev_is_inline; |
| 2938 | } else { | 2963 | } else { |
| 2939 | const is_mutable = decl_tv.val.tag() == .variable; | | |
| 2940 | | | |
| 2941 | var is_threadlocal = false; // TODO implement threadlocal variables | | |
| 2942 | var is_extern = false; // TODO implement extern variables | | |
| 2943 | | | |
| 2944 | if (is_mutable and !decl_tv.ty.isValidVarType(is_extern)) { | | |
| 2945 | return mod.fail( | | |
| 2946 | &block_scope.base, | | |
| 2947 | src, // TODO point at the mut token | | |
| 2948 | "variable of type '{}' must be const", | | |
| 2949 | .{decl_tv.ty}, | | |
| 2950 | ); | | |
| 2951 | } | | |
| 2952 | | | |
| 2953 | var type_changed = true; | 2964 | var type_changed = true; |
| 2954 | if (decl.has_tv) { | 2965 | if (decl.has_tv) { |
| 2955 | type_changed = !decl.ty.eql(decl_tv.ty); | 2966 | type_changed = !decl.ty.eql(decl_tv.ty); |
| 2956 | decl.clearValues(gpa); | 2967 | decl.clearValues(gpa); |
| 2957 | } | 2968 | } |
| 2958 | | 2969 | |
| 2959 | const copied_val = try decl_tv.val.copy(&decl_arena.allocator); | | |
| 2960 | const is_extern_fn = copied_val.tag() == .extern_fn; | | |
| 2961 | | | |
| 2962 | // TODO: also avoid allocating this Var structure if `!is_mutable`. | | |
| 2963 | // I think this will require adjusting Sema to copy the value or something | | |
| 2964 | // like that; otherwise it causes use of undefined value when freeing resources. | | |
| 2965 | const decl_val: Value = if (is_extern_fn) copied_val else blk: { | | |
| 2966 | const new_variable = try decl_arena.allocator.create(Var); | | |
| 2967 | new_variable.* = .{ | | |
| 2968 | .owner_decl = decl, | | |
| 2969 | .init = copied_val, | | |
| 2970 | .is_extern = is_extern, | | |
| 2971 | .is_mutable = is_mutable, | | |
| 2972 | .is_threadlocal = is_threadlocal, | | |
| 2973 | }; | | |
| 2974 | break :blk try Value.Tag.variable.create(&decl_arena.allocator, new_variable); | | |
| 2975 | }; | | |
| 2976 | | | |
| 2977 | decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); | 2970 | decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); |
| 2978 | decl.val = decl_val; | 2971 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 2979 | decl.align_val = try align_val.copy(&decl_arena.allocator); | 2972 | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 2980 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); | 2973 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 2981 | decl.has_tv = true; | 2974 | decl.has_tv = true; |
| ... | @@ -3211,7 +3204,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo | ... | @@ -3211,7 +3204,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo |
| 3211 | const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node); | 3204 | const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node); |
| 3212 | | 3205 | |
| 3213 | // Every Decl needs a name. | 3206 | // Every Decl needs a name. |
| 3214 | const raw_decl_name: [:0]const u8 = switch (decl_name_index) { | 3207 | var is_named_test = false; |
| | 3208 | const decl_name: [:0]const u8 = switch (decl_name_index) { |
| 3215 | 0 => name: { | 3209 | 0 => name: { |
| 3216 | if (is_exported) { | 3210 | if (is_exported) { |
| 3217 | const i = iter.usingnamespace_index; | 3211 | const i = iter.usingnamespace_index; |
| ... | @@ -3228,24 +3222,28 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo | ... | @@ -3228,24 +3222,28 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo |
| 3228 | iter.unnamed_test_index += 1; | 3222 | iter.unnamed_test_index += 1; |
| 3229 | break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i}); | 3223 | break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i}); |
| 3230 | }, | 3224 | }, |
| 3231 | else => zir.nullTerminatedString(decl_name_index), | 3225 | else => name: { |
| 3232 | }; | 3226 | const raw_name = zir.nullTerminatedString(decl_name_index); |
| 3233 | const decl_name = if (raw_decl_name.len != 0) raw_decl_name else name: { | 3227 | if (raw_name.len == 0) { |
| 3234 | const test_name = zir.nullTerminatedString(decl_name_index + 1); | 3228 | is_named_test = true; |
| 3235 | break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name}); | 3229 | const test_name = zir.nullTerminatedString(decl_name_index + 1); |
| | 3230 | break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name}); |
| | 3231 | } else { |
| | 3232 | break :name try gpa.dupeZ(u8, raw_name); |
| | 3233 | } |
| | 3234 | }, |
| 3236 | }; | 3235 | }; |
| 3237 | | 3236 | |
| 3238 | // We create a Decl for it regardless of analysis status. | 3237 | // We create a Decl for it regardless of analysis status. |
| 3239 | const gop = try namespace.decls.getOrPut(gpa, decl_name); | 3238 | const gop = try namespace.decls.getOrPut(gpa, decl_name); |
| 3240 | if (!gop.found_existing) { | 3239 | if (!gop.found_existing) { |
| 3241 | const new_decl = try mod.allocateNewDecl(namespace, decl_node); | 3240 | const new_decl = try mod.allocateNewDecl(namespace, decl_node); |
| 3242 | log.debug("scan new decl {*} ({s}) into {*}", .{ new_decl, decl_name, namespace }); | 3241 | log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace }); |
| 3243 | new_decl.src_line = line; | 3242 | new_decl.src_line = line; |
| 3244 | new_decl.name = decl_name; | 3243 | new_decl.name = decl_name; |
| 3245 | gop.entry.value = new_decl; | 3244 | gop.entry.value = new_decl; |
| 3246 | // Exported decls, comptime decls, usingnamespace decls, and | 3245 | // Exported decls, comptime decls, usingnamespace decls, and |
| 3247 | // test decls if in test mode, get analyzed. | 3246 | // test decls if in test mode, get analyzed. |
| 3248 | const is_named_test = raw_decl_name.len == 0; | | |
| 3249 | const want_analysis = is_exported or switch (decl_name_index) { | 3247 | const want_analysis = is_exported or switch (decl_name_index) { |
| 3250 | 0 => true, // comptime decl | 3248 | 0 => true, // comptime decl |
| 3251 | 1 => mod.comp.bin_file.options.is_test, // test decl | 3249 | 1 => mod.comp.bin_file.options.is_test, // test decl |
| ... | @@ -3261,17 +3259,15 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo | ... | @@ -3261,17 +3259,15 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo |
| 3261 | new_decl.zir_decl_index = @intCast(u32, decl_sub_index); | 3259 | new_decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| 3262 | return; | 3260 | return; |
| 3263 | } | 3261 | } |
| | 3262 | gpa.free(decl_name); |
| 3264 | const decl = gop.entry.value; | 3263 | const decl = gop.entry.value; |
| 3265 | log.debug("scan existing decl {*} ({s}) of {*}", .{ decl, decl_name, namespace }); | 3264 | log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl_name, namespace }); |
| 3266 | // Update the AST node of the decl; even if its contents are unchanged, it may | 3265 | // Update the AST node of the decl; even if its contents are unchanged, it may |
| 3267 | // have been re-ordered. | 3266 | // have been re-ordered. |
| 3268 | const prev_src_node = decl.src_node; | 3267 | const prev_src_node = decl.src_node; |
| 3269 | decl.src_node = decl_node; | 3268 | decl.src_node = decl_node; |
| 3270 | decl.src_line = line; | 3269 | decl.src_line = line; |
| 3271 | | 3270 | |
| 3272 | decl.clearName(gpa); | | |
| 3273 | decl.name = decl_name; | | |
| 3274 | | | |
| 3275 | decl.is_pub = is_pub; | 3271 | decl.is_pub = is_pub; |
| 3276 | decl.is_exported = is_exported; | 3272 | decl.is_exported = is_exported; |
| 3277 | decl.has_align = has_align; | 3273 | decl.has_align = has_align; |
| ... | @@ -3305,14 +3301,13 @@ pub fn deleteDecl( | ... | @@ -3305,14 +3301,13 @@ pub fn deleteDecl( |
| 3305 | const tracy = trace(@src()); | 3301 | const tracy = trace(@src()); |
| 3306 | defer tracy.end(); | 3302 | defer tracy.end(); |
| 3307 | | 3303 | |
| 3308 | log.debug("deleting decl '{s}'", .{decl.name}); | 3304 | log.debug("deleting {*} ({s})", .{ decl, decl.name }); |
| 3309 | | 3305 | |
| 3310 | if (outdated_decls) |map| { | 3306 | if (outdated_decls) |map| { |
| 3311 | _ = map.swapRemove(decl); | 3307 | _ = map.swapRemove(decl); |
| 3312 | try map.ensureCapacity(map.count() + decl.dependants.count()); | 3308 | try map.ensureUnusedCapacity(decl.dependants.count()); |
| 3313 | } | 3309 | } |
| 3314 | try mod.deletion_set.ensureCapacity(mod.gpa, mod.deletion_set.count() + | 3310 | try mod.deletion_set.ensureUnusedCapacity(mod.gpa, decl.dependencies.count()); |
| 3315 | decl.dependencies.count()); | | |
| 3316 | | 3311 | |
| 3317 | // Remove from the namespace it resides in. | 3312 | // Remove from the namespace it resides in. |
| 3318 | decl.namespace.removeDecl(decl); | 3313 | decl.namespace.removeDecl(decl); |
| ... | @@ -3354,7 +3349,9 @@ pub fn deleteDecl( | ... | @@ -3354,7 +3349,9 @@ pub fn deleteDecl( |
| 3354 | } | 3349 | } |
| 3355 | _ = mod.compile_log_decls.swapRemove(decl); | 3350 | _ = mod.compile_log_decls.swapRemove(decl); |
| 3356 | mod.deleteDeclExports(decl); | 3351 | mod.deleteDeclExports(decl); |
| 3357 | mod.comp.bin_file.freeDecl(decl); | 3352 | if (decl.hasLinkAllocation()) { |
| | 3353 | mod.comp.bin_file.freeDecl(decl); |
| | 3354 | } |
| 3358 | | 3355 | |
| 3359 | decl.destroy(mod); | 3356 | decl.destroy(mod); |
| 3360 | } | 3357 | } |