authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-01-07 00:42:30+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-01-23 21:19:53+00:00
log06d8bb32e3edfb4a26c6d3ecdf198574f4bd3f87
treec71cc2ab5af1f24f224031f947c9ac0396df2562
parentae845a33c04fb287ae5a7445743c2b570e40ca1f
signaturelock-open Commit is signed but in an unrecognized format.

InternPool: introduce TrackedInst

It is problematic for the cached `InternPool` state to directly reference ZIR instruction indices, as these are not stable across incremental updates. The existing ZIR mapping logic attempts to handle this by iterating the existing Decl graph for a file after `AstGen` and update ZIR indices on `Decl`s, struct types, etc. However, this is unreliable due to generic instantiations, and relies on specialized logic for everything which may refer to a ZIR instruction (e.g. a struct's owner decl). I therefore determined that a prerequisite change for incremental compilation would be to rework how we store these indices. This commit introduces a `TrackedInst` type which provides a stable index (`TrackedInst.Index`) for a single ZIR instruction in the compilation. The `InternPool` now stores these values in place of ZIR instruction indices. This makes the ZIR mapping logic relatively trivial: after `AstGen` completes, we simply iterate all `TrackedInst` values and update those indices which have changed. In future, if the corresponding ZIR instruction has been removed, we must also invalidate any dependencies on this instruction to trigger any required re-analysis, however the dependency system does not yet exist.

4 files changed, 110 insertions(+), 123 deletions(-)

src/Compilation.zig+4-1
......@@ -2795,6 +2795,7 @@ const Header = extern struct {
27952795 extra_len: u32,
27962796 limbs_len: u32,
27972797 string_bytes_len: u32,
2798 tracked_insts_len: u32,
27982799 },
27992800};
28002801
......@@ -2802,7 +2803,7 @@ const Header = extern struct {
28022803/// saved, such as the target and most CLI flags. A cache hit will only occur
28032804/// when subsequent compiler invocations use the same set of flags.
28042805pub fn saveState(comp: *Compilation) !void {
2805 var bufs_list: [6]std.os.iovec_const = undefined;
2806 var bufs_list: [7]std.os.iovec_const = undefined;
28062807 var bufs_len: usize = 0;
28072808
28082809 const lf = comp.bin_file orelse return;
......@@ -2815,6 +2816,7 @@ pub fn saveState(comp: *Compilation) !void {
28152816 .extra_len = @intCast(ip.extra.items.len),
28162817 .limbs_len = @intCast(ip.limbs.items.len),
28172818 .string_bytes_len = @intCast(ip.string_bytes.items.len),
2819 .tracked_insts_len = @intCast(ip.tracked_insts.count()),
28182820 },
28192821 };
28202822 addBuf(&bufs_list, &bufs_len, mem.asBytes(&header));
......@@ -2823,6 +2825,7 @@ pub fn saveState(comp: *Compilation) !void {
28232825 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data)));
28242826 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag)));
28252827 addBuf(&bufs_list, &bufs_len, ip.string_bytes.items);
2828 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys()));
28262829
28272830 // TODO: compilation errors
28282831 // TODO: files
src/InternPool.zig+51-19
......@@ -54,6 +54,34 @@ string_table: std.HashMapUnmanaged(
5454 std.hash_map.default_max_load_percentage,
5555) = .{},
5656
57/// An index into `tracked_insts` gives a reference to a single ZIR instruction which
58/// persists across incremental updates.
59tracked_insts: std.AutoArrayHashMapUnmanaged(TrackedInst, void) = .{},
60
61pub const TrackedInst = extern struct {
62 path_digest: Cache.BinDigest,
63 inst: Zir.Inst.Index,
64 comptime {
65 // The fields should be tightly packed. See also serialiation logic in `Compilation.saveState`.
66 assert(@sizeOf(@This()) == Cache.bin_digest_len + @sizeOf(Zir.Inst.Index));
67 }
68 pub const Index = enum(u32) {
69 _,
70 pub fn resolve(i: TrackedInst.Index, ip: *const InternPool) Zir.Inst.Index {
71 return ip.tracked_insts.keys()[@intFromEnum(i)].inst;
72 }
73 };
74};
75
76pub fn trackZir(ip: *InternPool, gpa: Allocator, file: *Module.File, inst: Zir.Inst.Index) Allocator.Error!TrackedInst.Index {
77 const key: TrackedInst = .{
78 .path_digest = file.path_digest,
79 .inst = inst,
80 };
81 const gop = try ip.tracked_insts.getOrPut(gpa, key);
82 return @enumFromInt(gop.index);
83}
84
5785const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false);
5886
5987const builtin = @import("builtin");
......@@ -62,11 +90,13 @@ const Allocator = std.mem.Allocator;
6290const assert = std.debug.assert;
6391const BigIntConst = std.math.big.int.Const;
6492const BigIntMutable = std.math.big.int.Mutable;
93const Cache = std.Build.Cache;
6594const Limb = std.math.big.Limb;
6695const Hash = std.hash.Wyhash;
6796
6897const InternPool = @This();
6998const Module = @import("Module.zig");
99const Zcu = Module;
70100const Zir = @import("Zir.zig");
71101
72102const KeyAdapter = struct {
......@@ -409,7 +439,7 @@ pub const Key = union(enum) {
409439 /// `none` when the struct has no declarations.
410440 namespace: OptionalNamespaceIndex,
411441 /// Index of the struct_decl ZIR instruction.
412 zir_index: Zir.Inst.Index,
442 zir_index: TrackedInst.Index,
413443 layout: std.builtin.Type.ContainerLayout,
414444 field_names: NullTerminatedString.Slice,
415445 field_types: Index.Slice,
......@@ -653,7 +683,7 @@ pub const Key = union(enum) {
653683 }
654684
655685 /// Asserts the struct is not packed.
656 pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: Zir.Inst.Index) void {
686 pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index) void {
657687 assert(s.layout != .Packed);
658688 const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?;
659689 ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index);
......@@ -769,7 +799,7 @@ pub const Key = union(enum) {
769799 flags: Tag.TypeUnion.Flags,
770800 /// The enum that provides the list of field names and values.
771801 enum_tag_ty: Index,
772 zir_index: Zir.Inst.Index,
802 zir_index: TrackedInst.Index,
773803
774804 /// The returned pointer expires with any addition to the `InternPool`.
775805 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags {
......@@ -1056,7 +1086,7 @@ pub const Key = union(enum) {
10561086 /// the body. We store this rather than the body directly so that when ZIR
10571087 /// is regenerated on update(), we can map this to the new corresponding
10581088 /// ZIR instruction.
1059 zir_body_inst: Zir.Inst.Index,
1089 zir_body_inst: TrackedInst.Index,
10601090 /// Relative to owner Decl.
10611091 lbrace_line: u32,
10621092 /// Relative to owner Decl.
......@@ -1082,7 +1112,7 @@ pub const Key = union(enum) {
10821112 }
10831113
10841114 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.
1085 pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *Zir.Inst.Index {
1115 pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *TrackedInst.Index {
10861116 return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]);
10871117 }
10881118
......@@ -1860,7 +1890,7 @@ pub const UnionType = struct {
18601890 /// If this slice has length 0 it means all elements are `none`.
18611891 field_aligns: Alignment.Slice,
18621892 /// Index of the union_decl ZIR instruction.
1863 zir_index: Zir.Inst.Index,
1893 zir_index: TrackedInst.Index,
18641894 /// Index into extra array of the `flags` field.
18651895 flags_index: u32,
18661896 /// Copied from `enum_tag_ty`.
......@@ -1954,10 +1984,10 @@ pub const UnionType = struct {
19541984 }
19551985
19561986 /// This does not mutate the field of UnionType.
1957 pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: Zir.Inst.Index) void {
1987 pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index) void {
19581988 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
19591989 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;
1960 const ptr: *Zir.Inst.Index =
1990 const ptr: *TrackedInst.Index =
19611991 @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]);
19621992 ptr.* = new_zir_index;
19631993 }
......@@ -2976,7 +3006,7 @@ pub const Tag = enum(u8) {
29763006 analysis: FuncAnalysis,
29773007 owner_decl: DeclIndex,
29783008 ty: Index,
2979 zir_body_inst: Zir.Inst.Index,
3009 zir_body_inst: TrackedInst.Index,
29803010 lbrace_line: u32,
29813011 rbrace_line: u32,
29823012 lbrace_column: u32,
......@@ -3050,7 +3080,7 @@ pub const Tag = enum(u8) {
30503080 namespace: NamespaceIndex,
30513081 /// The enum that provides the list of field names and values.
30523082 tag_ty: Index,
3053 zir_index: Zir.Inst.Index,
3083 zir_index: TrackedInst.Index,
30543084
30553085 pub const Flags = packed struct(u32) {
30563086 runtime_tag: UnionType.RuntimeTag,
......@@ -3072,7 +3102,7 @@ pub const Tag = enum(u8) {
30723102 /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits
30733103 pub const TypeStructPacked = struct {
30743104 decl: DeclIndex,
3075 zir_index: Zir.Inst.Index,
3105 zir_index: TrackedInst.Index,
30763106 fields_len: u32,
30773107 namespace: OptionalNamespaceIndex,
30783108 backing_int_ty: Index,
......@@ -3119,7 +3149,7 @@ pub const Tag = enum(u8) {
31193149 /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved
31203150 pub const TypeStruct = struct {
31213151 decl: DeclIndex,
3122 zir_index: Zir.Inst.Index,
3152 zir_index: TrackedInst.Index,
31233153 fields_len: u32,
31243154 flags: Flags,
31253155 size: u32,
......@@ -3708,6 +3738,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
37083738
37093739 ip.string_table.deinit(gpa);
37103740
3741 ip.tracked_insts.deinit(gpa);
3742
37113743 ip.* = undefined;
37123744}
37133745
......@@ -5358,7 +5390,7 @@ pub const UnionTypeInit = struct {
53585390 flags: Tag.TypeUnion.Flags,
53595391 decl: DeclIndex,
53605392 namespace: NamespaceIndex,
5361 zir_index: Zir.Inst.Index,
5393 zir_index: TrackedInst.Index,
53625394 fields_len: u32,
53635395 enum_tag_ty: Index,
53645396 /// May have length 0 which leaves the values unset until later.
......@@ -5430,7 +5462,7 @@ pub const StructTypeInit = struct {
54305462 decl: DeclIndex,
54315463 namespace: OptionalNamespaceIndex,
54325464 layout: std.builtin.Type.ContainerLayout,
5433 zir_index: Zir.Inst.Index,
5465 zir_index: TrackedInst.Index,
54345466 fields_len: u32,
54355467 known_non_opv: bool,
54365468 requires_comptime: RequiresComptime,
......@@ -5704,7 +5736,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Alloc
57045736pub const GetFuncDeclKey = struct {
57055737 owner_decl: DeclIndex,
57065738 ty: Index,
5707 zir_body_inst: Zir.Inst.Index,
5739 zir_body_inst: TrackedInst.Index,
57085740 lbrace_line: u32,
57095741 rbrace_line: u32,
57105742 lbrace_column: u32,
......@@ -5773,7 +5805,7 @@ pub const GetFuncDeclIesKey = struct {
57735805 is_var_args: bool,
57745806 is_generic: bool,
57755807 is_noinline: bool,
5776 zir_body_inst: Zir.Inst.Index,
5808 zir_body_inst: TrackedInst.Index,
57775809 lbrace_line: u32,
57785810 rbrace_line: u32,
57795811 lbrace_column: u32,
......@@ -6535,7 +6567,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
65356567 NullTerminatedString,
65366568 OptionalNullTerminatedString,
65376569 Tag.TypePointer.VectorIndex,
6538 Zir.Inst.Index,
6570 TrackedInst.Index,
65396571 => @intFromEnum(@field(extra, field.name)),
65406572
65416573 u32,
......@@ -6611,7 +6643,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
66116643 NullTerminatedString,
66126644 OptionalNullTerminatedString,
66136645 Tag.TypePointer.VectorIndex,
6614 Zir.Inst.Index,
6646 TrackedInst.Index,
66156647 => @enumFromInt(int32),
66166648
66176649 u32,
......@@ -8317,7 +8349,7 @@ pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool {
83178349 return funcAnalysis(ip, i).inferred_error_set;
83188350}
83198351
8320pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index {
8352pub fn funcZirBodyInst(ip: *const InternPool, i: Index) TrackedInst.Index {
83218353 assert(i != .none);
83228354 const item = ip.items.get(@intFromEnum(i));
83238355 const zir_body_inst_field_index = std.meta.fieldIndex(Tag.FuncDecl, "zir_body_inst").?;
src/Module.zig+34-86
......@@ -834,6 +834,9 @@ pub const File = struct {
834834 multi_pkg: bool = false,
835835 /// List of references to this file, used for multi-package errors.
836836 references: std.ArrayListUnmanaged(Reference) = .{},
837 /// The hash of the path to this file, used to store `InternPool.TrackedInst`.
838 /// undefined until `zir_loaded == true`.
839 path_digest: Cache.BinDigest = undefined,
837840
838841 /// Used by change detection algorithm, after astgen, contains the
839842 /// set of decls that existed in the previous ZIR but not in the new one.
......@@ -2594,7 +2597,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
25942597 const stat = try source_file.stat();
25952598
25962599 const want_local_cache = file.mod == mod.main_mod;
2597 const digest = hash: {
2600 const bin_digest = hash: {
25982601 var path_hash: Cache.HashHelper = .{};
25992602 path_hash.addBytes(build_options.version);
26002603 path_hash.add(builtin.zig_backend);
......@@ -2603,7 +2606,19 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
26032606 path_hash.addBytes(file.mod.root.sub_path);
26042607 }
26052608 path_hash.addBytes(file.sub_file_path);
2606 break :hash path_hash.final();
2609 var bin: Cache.BinDigest = undefined;
2610 path_hash.hasher.final(&bin);
2611 break :hash bin;
2612 };
2613 file.path_digest = bin_digest;
2614 const hex_digest = hex: {
2615 var hex: Cache.HexDigest = undefined;
2616 _ = std.fmt.bufPrint(
2617 &hex,
2618 "{s}",
2619 .{std.fmt.fmtSliceHexLower(&bin_digest)},
2620 ) catch unreachable;
2621 break :hex hex;
26072622 };
26082623 const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache;
26092624 const zir_dir = cache_directory.handle;
......@@ -2613,7 +2628,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
26132628 .never_loaded, .retryable_failure => lock: {
26142629 // First, load the cached ZIR code, if any.
26152630 log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{
2616 file.sub_file_path, want_local_cache, &digest,
2631 file.sub_file_path, want_local_cache, &hex_digest,
26172632 });
26182633
26192634 break :lock .shared;
......@@ -2640,7 +2655,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
26402655 // version. Likewise if we're working on AstGen and another process asks for
26412656 // the cached file, they'll get it.
26422657 const cache_file = while (true) {
2643 break zir_dir.createFile(&digest, .{
2658 break zir_dir.createFile(&hex_digest, .{
26442659 .read = true,
26452660 .truncate = false,
26462661 .lock = lock,
......@@ -2826,7 +2841,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
28262841 };
28272842 cache_file.writevAll(&iovecs) catch |err| {
28282843 log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{
2829 file.mod.root, file.sub_file_path, cache_directory, &digest, @errorName(err),
2844 file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err),
28302845 });
28312846 };
28322847
......@@ -2935,89 +2950,22 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File)
29352950 return zir;
29362951}
29372952
2938/// Patch ups:
2939/// * Struct.zir_index
2940/// * Decl.zir_index
2941/// * Fn.zir_body_inst
2942/// * Decl.zir_decl_index
2943fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
2944 const gpa = mod.gpa;
2945 const new_zir = file.zir;
2946
2947 // The root decl will be null if the previous ZIR had AST errors.
2948 const root_decl = file.root_decl.unwrap() orelse return;
2953fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void {
2954 const gpa = zcu.gpa;
29492955
2950 // Maps from old ZIR to new ZIR, declaration, struct_decl, enum_decl, etc. Any instruction which
2951 // creates a namespace, and any `declaration` instruction, gets mapped from old to new here.
29522956 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
29532957 defer inst_map.deinit(gpa);
29542958
2955 try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map);
2956
2957 // Walk the Decl graph, updating ZIR indexes, strings, and populating
2958 // the deleted and outdated lists.
2959
2960 var decl_stack: ArrayListUnmanaged(Decl.Index) = .{};
2961 defer decl_stack.deinit(gpa);
2962
2963 try decl_stack.append(gpa, root_decl);
2964
2965 file.deleted_decls.clearRetainingCapacity();
2966 file.outdated_decls.clearRetainingCapacity();
2967
2968 // The root decl is always outdated; otherwise we would not have had
2969 // to re-generate ZIR for the File.
2970 try file.outdated_decls.append(gpa, root_decl);
2971
2972 const ip = &mod.intern_pool;
2973
2974 while (decl_stack.popOrNull()) |decl_index| {
2975 const decl = mod.declPtr(decl_index);
2976 // Anonymous decls and the root decl have this set to 0. We still need
2977 // to walk them but we do not need to modify this value.
2978 // Anonymous decls should not be marked outdated. They will be re-generated
2979 // if their owner decl is marked outdated.
2980 if (decl.zir_decl_index.unwrap()) |old_zir_decl_index| {
2981 const new_zir_decl_index = inst_map.get(old_zir_decl_index) orelse {
2982 try file.deleted_decls.append(gpa, decl_index);
2983 continue;
2984 };
2985 const old_hash = decl.contentsHashZir(old_zir);
2986 decl.zir_decl_index = new_zir_decl_index.toOptional();
2987 const new_hash = decl.contentsHashZir(new_zir);
2988 if (!std.zig.srcHashEql(old_hash, new_hash)) {
2989 try file.outdated_decls.append(gpa, decl_index);
2990 }
2991 }
2959 try mapOldZirToNew(gpa, old_zir, file.zir, &inst_map);
29922960
2993 if (!decl.owns_tv) continue;
2994
2995 if (decl.getOwnedStruct(mod)) |struct_type| {
2996 struct_type.setZirIndex(ip, inst_map.get(struct_type.zir_index) orelse {
2997 try file.deleted_decls.append(gpa, decl_index);
2998 continue;
2999 });
3000 }
3001
3002 if (decl.getOwnedUnion(mod)) |union_type| {
3003 union_type.setZirIndex(ip, inst_map.get(union_type.zir_index) orelse {
3004 try file.deleted_decls.append(gpa, decl_index);
3005 continue;
3006 });
3007 }
3008
3009 if (decl.getOwnedFunction(mod)) |func| {
3010 func.zirBodyInst(ip).* = inst_map.get(func.zir_body_inst) orelse {
3011 try file.deleted_decls.append(gpa, decl_index);
3012 continue;
3013 };
3014 }
3015
3016 if (decl.getOwnedInnerNamespace(mod)) |namespace| {
3017 for (namespace.decls.keys()) |sub_decl| {
3018 try decl_stack.append(gpa, sub_decl);
3019 }
3020 }
2961 // TODO: this should be done after all AstGen workers complete, to avoid
2962 // iterating over this full set for every updated file.
2963 for (zcu.intern_pool.tracked_insts.keys()) |*ti| {
2964 if (!std.mem.eql(u8, &ti.path_digest, &file.path_digest)) continue;
2965 ti.inst = inst_map.get(ti.inst) orelse {
2966 // TODO: invalidate this `TrackedInst` via the dependency mechanism
2967 continue;
2968 };
30212969 }
30222970}
30232971
......@@ -3494,7 +3442,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
34943442 const struct_ty = sema.getStructType(
34953443 new_decl_index,
34963444 new_namespace_index,
3497 .main_struct_inst,
3445 try mod.intern_pool.trackZir(gpa, file, .main_struct_inst),
34983446 ) catch |err| switch (err) {
34993447 error.OutOfMemory => return error.OutOfMemory,
35003448 };
......@@ -4472,7 +4420,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
44724420 };
44734421 defer inner_block.instructions.deinit(gpa);
44744422
4475 const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*);
4423 const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).resolve(ip));
44764424
44774425 // Here we are performing "runtime semantic analysis" for a function body, which means
44784426 // we must map the parameter ZIR instructions to `arg` AIR instructions.
......@@ -6125,7 +6073,7 @@ pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]
61256073 const tags = file.zir.instructions.items(.tag);
61266074 const data = file.zir.instructions.items(.data);
61276075
6128 const param_body = file.zir.getParamBody(func.zir_body_inst);
6076 const param_body = file.zir.getParamBody(func.zir_body_inst.resolve(&mod.intern_pool));
61296077 const param = param_body[index];
61306078
61316079 return switch (tags[@intFromEnum(param)]) {
src/Sema.zig+21-17
......@@ -2708,11 +2708,12 @@ pub fn getStructType(
27082708 sema: *Sema,
27092709 decl: InternPool.DeclIndex,
27102710 namespace: InternPool.NamespaceIndex,
2711 zir_index: Zir.Inst.Index,
2711 tracked_inst: InternPool.TrackedInst.Index,
27122712) !InternPool.Index {
27132713 const mod = sema.mod;
27142714 const gpa = sema.gpa;
27152715 const ip = &mod.intern_pool;
2716 const zir_index = tracked_inst.resolve(ip);
27162717 const extended = sema.code.instructions.items(.data)[@intFromEnum(zir_index)].extended;
27172718 assert(extended.opcode == .struct_decl);
27182719 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
......@@ -2747,7 +2748,7 @@ pub fn getStructType(
27472748 const ty = try ip.getStructType(gpa, .{
27482749 .decl = decl,
27492750 .namespace = namespace.toOptional(),
2750 .zir_index = zir_index,
2751 .zir_index = tracked_inst,
27512752 .layout = small.layout,
27522753 .known_non_opv = small.known_non_opv,
27532754 .is_tuple = small.is_tuple,
......@@ -2797,7 +2798,8 @@ fn zirStructDecl(
27972798 errdefer mod.destroyNamespace(new_namespace_index);
27982799
27992800 const struct_ty = ty: {
2800 const ty = try sema.getStructType(new_decl_index, new_namespace_index, inst);
2801 const tracked_inst = try ip.trackZir(mod.gpa, block.getFileScope(mod), inst);
2802 const ty = try sema.getStructType(new_decl_index, new_namespace_index, tracked_inst);
28012803 if (sema.builtin_type_target_index != .none) {
28022804 ip.resolveBuiltinType(sema.builtin_type_target_index, ty);
28032805 break :ty sema.builtin_type_target_index;
......@@ -2856,7 +2858,7 @@ fn createAnonymousDeclTypeNamed(
28562858 return new_decl_index;
28572859 },
28582860 .func => {
2859 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index));
2861 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip));
28602862 const zir_tags = sema.code.instructions.items(.tag);
28612863
28622864 var buf = std.ArrayList(u8).init(gpa);
......@@ -3252,7 +3254,7 @@ fn zirUnionDecl(
32523254 },
32533255 .decl = new_decl_index,
32543256 .namespace = new_namespace_index,
3255 .zir_index = inst,
3257 .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst),
32563258 .fields_len = fields_len,
32573259 .enum_tag_ty = .none,
32583260 .field_types = &.{},
......@@ -7446,7 +7448,7 @@ fn analyzeCall(
74467448 // the AIR instructions of the callsite. The callee could be a generic function
74477449 // which means its parameter type expressions must be resolved in order and used
74487450 // to successively coerce the arguments.
7449 const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst);
7451 const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst.resolve(ip));
74507452 try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
74517453
74527454 var arg_i: u32 = 0;
......@@ -7494,7 +7496,7 @@ fn analyzeCall(
74947496 // each of the parameters, resolving the return type and providing it to the child
74957497 // `Sema` so that it can be used for the `ret_ptr` instruction.
74967498 const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)
7497 try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst)
7499 try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst.resolve(ip))
74987500 else
74997501 try sema.resolveInst(fn_info.ret_ty_ref);
75007502 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
......@@ -7885,7 +7887,7 @@ fn instantiateGenericCall(
78857887 const namespace_index = fn_owner_decl.src_namespace;
78867888 const namespace = mod.namespacePtr(namespace_index);
78877889 const fn_zir = namespace.file_scope.zir;
7888 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst);
7890 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip));
78897891
78907892 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());
78917893 @memset(comptime_args, .none);
......@@ -9467,7 +9469,7 @@ fn funcCommon(
94679469 .is_generic = final_is_generic,
94689470 .is_noinline = is_noinline,
94699471
9470 .zir_body_inst = func_inst,
9472 .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst),
94719473 .lbrace_line = src_locs.lbrace_line,
94729474 .rbrace_line = src_locs.rbrace_line,
94739475 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
......@@ -9545,7 +9547,7 @@ fn funcCommon(
95459547 .ty = func_ty,
95469548 .cc = cc,
95479549 .is_noinline = is_noinline,
9548 .zir_body_inst = func_inst,
9550 .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst),
95499551 .lbrace_line = src_locs.lbrace_line,
95509552 .rbrace_line = src_locs.rbrace_line,
95519553 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
......@@ -21553,7 +21555,7 @@ fn zirReify(
2155321555 .namespace = new_namespace_index,
2155421556 .enum_tag_ty = enum_tag_ty,
2155521557 .fields_len = fields_len,
21556 .zir_index = inst,
21558 .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently?
2155721559 .flags = .{
2155821560 .layout = layout,
2155921561 .status = .have_field_types,
......@@ -21721,7 +21723,7 @@ fn reifyStruct(
2172121723 const ty = try ip.getStructType(gpa, .{
2172221724 .decl = new_decl_index,
2172321725 .namespace = .none,
21724 .zir_index = inst,
21726 .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently?
2172521727 .layout = layout,
2172621728 .known_non_opv = false,
2172721729 .fields_len = fields_len,
......@@ -35593,7 +35595,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
3559335595 break :blk accumulator;
3559435596 };
3559535597
35596 const extended = zir.instructions.items(.data)[@intFromEnum(struct_type.zir_index)].extended;
35598 const zir_index = struct_type.zir_index.resolve(ip);
35599 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
3559735600 assert(extended.opcode == .struct_decl);
3559835601 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
3559935602
......@@ -35613,7 +35616,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
3561335616 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);
3561435617 } else {
3561535618 const body = zir.bodySlice(extra_index, backing_int_body_len);
35616 const ty_ref = try sema.resolveBody(&block, body, struct_type.zir_index);
35619 const ty_ref = try sema.resolveBody(&block, body, zir_index);
3561735620 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);
3561835621 }
3561935622 };
......@@ -36357,7 +36360,7 @@ fn semaStructFields(
3635736360 const decl = mod.declPtr(decl_index);
3635836361 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;
3635936362 const zir = mod.namespacePtr(namespace_index).file_scope.zir;
36360 const zir_index = struct_type.zir_index;
36363 const zir_index = struct_type.zir_index.resolve(ip);
3636136364
3636236365 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);
3636336366
......@@ -36628,7 +36631,7 @@ fn semaStructFieldInits(
3662836631 const decl = mod.declPtr(decl_index);
3662936632 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;
3663036633 const zir = mod.namespacePtr(namespace_index).file_scope.zir;
36631 const zir_index = struct_type.zir_index;
36634 const zir_index = struct_type.zir_index.resolve(ip);
3663236635 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);
3663336636
3663436637 var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa);
......@@ -36777,7 +36780,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
3677736780 const ip = &mod.intern_pool;
3677836781 const decl_index = union_type.decl;
3677936782 const zir = mod.namespacePtr(union_type.namespace).file_scope.zir;
36780 const extended = zir.instructions.items(.data)[@intFromEnum(union_type.zir_index)].extended;
36783 const zir_index = union_type.zir_index.resolve(ip);
36784 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
3678136785 assert(extended.opcode == .union_decl);
3678236786 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
3678336787 var extra_index: usize = extended.operand;