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 {...@@ -2795,6 +2795,7 @@ const Header = extern struct {
2795 extra_len: u32,2795 extra_len: u32,
2796 limbs_len: u32,2796 limbs_len: u32,
2797 string_bytes_len: u32,2797 string_bytes_len: u32,
2798 tracked_insts_len: u32,
2798 },2799 },
2799};2800};
28002801
...@@ -2802,7 +2803,7 @@ const Header = extern struct {...@@ -2802,7 +2803,7 @@ const Header = extern struct {
2802/// saved, such as the target and most CLI flags. A cache hit will only occur2803/// saved, such as the target and most CLI flags. A cache hit will only occur
2803/// when subsequent compiler invocations use the same set of flags.2804/// when subsequent compiler invocations use the same set of flags.
2804pub fn saveState(comp: *Compilation) !void {2805pub 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;
2806 var bufs_len: usize = 0;2807 var bufs_len: usize = 0;
28072808
2808 const lf = comp.bin_file orelse return;2809 const lf = comp.bin_file orelse return;
...@@ -2815,6 +2816,7 @@ pub fn saveState(comp: *Compilation) !void {...@@ -2815,6 +2816,7 @@ pub fn saveState(comp: *Compilation) !void {
2815 .extra_len = @intCast(ip.extra.items.len),2816 .extra_len = @intCast(ip.extra.items.len),
2816 .limbs_len = @intCast(ip.limbs.items.len),2817 .limbs_len = @intCast(ip.limbs.items.len),
2817 .string_bytes_len = @intCast(ip.string_bytes.items.len),2818 .string_bytes_len = @intCast(ip.string_bytes.items.len),
2819 .tracked_insts_len = @intCast(ip.tracked_insts.count()),
2818 },2820 },
2819 };2821 };
2820 addBuf(&bufs_list, &bufs_len, mem.asBytes(&header));2822 addBuf(&bufs_list, &bufs_len, mem.asBytes(&header));
...@@ -2823,6 +2825,7 @@ pub fn saveState(comp: *Compilation) !void {...@@ -2823,6 +2825,7 @@ pub fn saveState(comp: *Compilation) !void {
2823 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data)));2825 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data)));
2824 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag)));2826 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag)));
2825 addBuf(&bufs_list, &bufs_len, ip.string_bytes.items);2827 addBuf(&bufs_list, &bufs_len, ip.string_bytes.items);
2828 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys()));
28262829
2827 // TODO: compilation errors2830 // TODO: compilation errors
2828 // TODO: files2831 // TODO: files
src/InternPool.zig+51-19
...@@ -54,6 +54,34 @@ string_table: std.HashMapUnmanaged(...@@ -54,6 +54,34 @@ string_table: std.HashMapUnmanaged(
54 std.hash_map.default_max_load_percentage,54 std.hash_map.default_max_load_percentage,
55) = .{},55) = .{},
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
57const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false);85const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false);
5886
59const builtin = @import("builtin");87const builtin = @import("builtin");
...@@ -62,11 +90,13 @@ const Allocator = std.mem.Allocator;...@@ -62,11 +90,13 @@ const Allocator = std.mem.Allocator;
62const assert = std.debug.assert;90const assert = std.debug.assert;
63const BigIntConst = std.math.big.int.Const;91const BigIntConst = std.math.big.int.Const;
64const BigIntMutable = std.math.big.int.Mutable;92const BigIntMutable = std.math.big.int.Mutable;
93const Cache = std.Build.Cache;
65const Limb = std.math.big.Limb;94const Limb = std.math.big.Limb;
66const Hash = std.hash.Wyhash;95const Hash = std.hash.Wyhash;
6796
68const InternPool = @This();97const InternPool = @This();
69const Module = @import("Module.zig");98const Module = @import("Module.zig");
99const Zcu = Module;
70const Zir = @import("Zir.zig");100const Zir = @import("Zir.zig");
71101
72const KeyAdapter = struct {102const KeyAdapter = struct {
...@@ -409,7 +439,7 @@ pub const Key = union(enum) {...@@ -409,7 +439,7 @@ pub const Key = union(enum) {
409 /// `none` when the struct has no declarations.439 /// `none` when the struct has no declarations.
410 namespace: OptionalNamespaceIndex,440 namespace: OptionalNamespaceIndex,
411 /// Index of the struct_decl ZIR instruction.441 /// Index of the struct_decl ZIR instruction.
412 zir_index: Zir.Inst.Index,442 zir_index: TrackedInst.Index,
413 layout: std.builtin.Type.ContainerLayout,443 layout: std.builtin.Type.ContainerLayout,
414 field_names: NullTerminatedString.Slice,444 field_names: NullTerminatedString.Slice,
415 field_types: Index.Slice,445 field_types: Index.Slice,
...@@ -653,7 +683,7 @@ pub const Key = union(enum) {...@@ -653,7 +683,7 @@ pub const Key = union(enum) {
653 }683 }
654684
655 /// Asserts the struct is not packed.685 /// 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 {
657 assert(s.layout != .Packed);687 assert(s.layout != .Packed);
658 const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?;688 const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?;
659 ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index);689 ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index);
...@@ -769,7 +799,7 @@ pub const Key = union(enum) {...@@ -769,7 +799,7 @@ pub const Key = union(enum) {
769 flags: Tag.TypeUnion.Flags,799 flags: Tag.TypeUnion.Flags,
770 /// The enum that provides the list of field names and values.800 /// The enum that provides the list of field names and values.
771 enum_tag_ty: Index,801 enum_tag_ty: Index,
772 zir_index: Zir.Inst.Index,802 zir_index: TrackedInst.Index,
773803
774 /// The returned pointer expires with any addition to the `InternPool`.804 /// The returned pointer expires with any addition to the `InternPool`.
775 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags {805 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags {
...@@ -1056,7 +1086,7 @@ pub const Key = union(enum) {...@@ -1056,7 +1086,7 @@ pub const Key = union(enum) {
1056 /// the body. We store this rather than the body directly so that when ZIR1086 /// the body. We store this rather than the body directly so that when ZIR
1057 /// is regenerated on update(), we can map this to the new corresponding1087 /// is regenerated on update(), we can map this to the new corresponding
1058 /// ZIR instruction.1088 /// ZIR instruction.
1059 zir_body_inst: Zir.Inst.Index,1089 zir_body_inst: TrackedInst.Index,
1060 /// Relative to owner Decl.1090 /// Relative to owner Decl.
1061 lbrace_line: u32,1091 lbrace_line: u32,
1062 /// Relative to owner Decl.1092 /// Relative to owner Decl.
...@@ -1082,7 +1112,7 @@ pub const Key = union(enum) {...@@ -1082,7 +1112,7 @@ pub const Key = union(enum) {
1082 }1112 }
10831113
1084 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.1114 /// 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 {
1086 return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]);1116 return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]);
1087 }1117 }
10881118
...@@ -1860,7 +1890,7 @@ pub const UnionType = struct {...@@ -1860,7 +1890,7 @@ pub const UnionType = struct {
1860 /// If this slice has length 0 it means all elements are `none`.1890 /// If this slice has length 0 it means all elements are `none`.
1861 field_aligns: Alignment.Slice,1891 field_aligns: Alignment.Slice,
1862 /// Index of the union_decl ZIR instruction.1892 /// Index of the union_decl ZIR instruction.
1863 zir_index: Zir.Inst.Index,1893 zir_index: TrackedInst.Index,
1864 /// Index into extra array of the `flags` field.1894 /// Index into extra array of the `flags` field.
1865 flags_index: u32,1895 flags_index: u32,
1866 /// Copied from `enum_tag_ty`.1896 /// Copied from `enum_tag_ty`.
...@@ -1954,10 +1984,10 @@ pub const UnionType = struct {...@@ -1954,10 +1984,10 @@ pub const UnionType = struct {
1954 }1984 }
19551985
1956 /// This does not mutate the field of UnionType.1986 /// 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 {
1958 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;1988 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
1959 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;1989 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;
1960 const ptr: *Zir.Inst.Index =1990 const ptr: *TrackedInst.Index =
1961 @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]);1991 @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]);
1962 ptr.* = new_zir_index;1992 ptr.* = new_zir_index;
1963 }1993 }
...@@ -2976,7 +3006,7 @@ pub const Tag = enum(u8) {...@@ -2976,7 +3006,7 @@ pub const Tag = enum(u8) {
2976 analysis: FuncAnalysis,3006 analysis: FuncAnalysis,
2977 owner_decl: DeclIndex,3007 owner_decl: DeclIndex,
2978 ty: Index,3008 ty: Index,
2979 zir_body_inst: Zir.Inst.Index,3009 zir_body_inst: TrackedInst.Index,
2980 lbrace_line: u32,3010 lbrace_line: u32,
2981 rbrace_line: u32,3011 rbrace_line: u32,
2982 lbrace_column: u32,3012 lbrace_column: u32,
...@@ -3050,7 +3080,7 @@ pub const Tag = enum(u8) {...@@ -3050,7 +3080,7 @@ pub const Tag = enum(u8) {
3050 namespace: NamespaceIndex,3080 namespace: NamespaceIndex,
3051 /// The enum that provides the list of field names and values.3081 /// The enum that provides the list of field names and values.
3052 tag_ty: Index,3082 tag_ty: Index,
3053 zir_index: Zir.Inst.Index,3083 zir_index: TrackedInst.Index,
30543084
3055 pub const Flags = packed struct(u32) {3085 pub const Flags = packed struct(u32) {
3056 runtime_tag: UnionType.RuntimeTag,3086 runtime_tag: UnionType.RuntimeTag,
...@@ -3072,7 +3102,7 @@ pub const Tag = enum(u8) {...@@ -3072,7 +3102,7 @@ pub const Tag = enum(u8) {
3072 /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits3102 /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits
3073 pub const TypeStructPacked = struct {3103 pub const TypeStructPacked = struct {
3074 decl: DeclIndex,3104 decl: DeclIndex,
3075 zir_index: Zir.Inst.Index,3105 zir_index: TrackedInst.Index,
3076 fields_len: u32,3106 fields_len: u32,
3077 namespace: OptionalNamespaceIndex,3107 namespace: OptionalNamespaceIndex,
3078 backing_int_ty: Index,3108 backing_int_ty: Index,
...@@ -3119,7 +3149,7 @@ pub const Tag = enum(u8) {...@@ -3119,7 +3149,7 @@ pub const Tag = enum(u8) {
3119 /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved3149 /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved
3120 pub const TypeStruct = struct {3150 pub const TypeStruct = struct {
3121 decl: DeclIndex,3151 decl: DeclIndex,
3122 zir_index: Zir.Inst.Index,3152 zir_index: TrackedInst.Index,
3123 fields_len: u32,3153 fields_len: u32,
3124 flags: Flags,3154 flags: Flags,
3125 size: u32,3155 size: u32,
...@@ -3708,6 +3738,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -3708,6 +3738,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
37083738
3709 ip.string_table.deinit(gpa);3739 ip.string_table.deinit(gpa);
37103740
3741 ip.tracked_insts.deinit(gpa);
3742
3711 ip.* = undefined;3743 ip.* = undefined;
3712}3744}
37133745
...@@ -5358,7 +5390,7 @@ pub const UnionTypeInit = struct {...@@ -5358,7 +5390,7 @@ pub const UnionTypeInit = struct {
5358 flags: Tag.TypeUnion.Flags,5390 flags: Tag.TypeUnion.Flags,
5359 decl: DeclIndex,5391 decl: DeclIndex,
5360 namespace: NamespaceIndex,5392 namespace: NamespaceIndex,
5361 zir_index: Zir.Inst.Index,5393 zir_index: TrackedInst.Index,
5362 fields_len: u32,5394 fields_len: u32,
5363 enum_tag_ty: Index,5395 enum_tag_ty: Index,
5364 /// May have length 0 which leaves the values unset until later.5396 /// May have length 0 which leaves the values unset until later.
...@@ -5430,7 +5462,7 @@ pub const StructTypeInit = struct {...@@ -5430,7 +5462,7 @@ pub const StructTypeInit = struct {
5430 decl: DeclIndex,5462 decl: DeclIndex,
5431 namespace: OptionalNamespaceIndex,5463 namespace: OptionalNamespaceIndex,
5432 layout: std.builtin.Type.ContainerLayout,5464 layout: std.builtin.Type.ContainerLayout,
5433 zir_index: Zir.Inst.Index,5465 zir_index: TrackedInst.Index,
5434 fields_len: u32,5466 fields_len: u32,
5435 known_non_opv: bool,5467 known_non_opv: bool,
5436 requires_comptime: RequiresComptime,5468 requires_comptime: RequiresComptime,
...@@ -5704,7 +5736,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Alloc...@@ -5704,7 +5736,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Alloc
5704pub const GetFuncDeclKey = struct {5736pub const GetFuncDeclKey = struct {
5705 owner_decl: DeclIndex,5737 owner_decl: DeclIndex,
5706 ty: Index,5738 ty: Index,
5707 zir_body_inst: Zir.Inst.Index,5739 zir_body_inst: TrackedInst.Index,
5708 lbrace_line: u32,5740 lbrace_line: u32,
5709 rbrace_line: u32,5741 rbrace_line: u32,
5710 lbrace_column: u32,5742 lbrace_column: u32,
...@@ -5773,7 +5805,7 @@ pub const GetFuncDeclIesKey = struct {...@@ -5773,7 +5805,7 @@ pub const GetFuncDeclIesKey = struct {
5773 is_var_args: bool,5805 is_var_args: bool,
5774 is_generic: bool,5806 is_generic: bool,
5775 is_noinline: bool,5807 is_noinline: bool,
5776 zir_body_inst: Zir.Inst.Index,5808 zir_body_inst: TrackedInst.Index,
5777 lbrace_line: u32,5809 lbrace_line: u32,
5778 rbrace_line: u32,5810 rbrace_line: u32,
5779 lbrace_column: u32,5811 lbrace_column: u32,
...@@ -6535,7 +6567,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -6535,7 +6567,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
6535 NullTerminatedString,6567 NullTerminatedString,
6536 OptionalNullTerminatedString,6568 OptionalNullTerminatedString,
6537 Tag.TypePointer.VectorIndex,6569 Tag.TypePointer.VectorIndex,
6538 Zir.Inst.Index,6570 TrackedInst.Index,
6539 => @intFromEnum(@field(extra, field.name)),6571 => @intFromEnum(@field(extra, field.name)),
65406572
6541 u32,6573 u32,
...@@ -6611,7 +6643,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct...@@ -6611,7 +6643,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
6611 NullTerminatedString,6643 NullTerminatedString,
6612 OptionalNullTerminatedString,6644 OptionalNullTerminatedString,
6613 Tag.TypePointer.VectorIndex,6645 Tag.TypePointer.VectorIndex,
6614 Zir.Inst.Index,6646 TrackedInst.Index,
6615 => @enumFromInt(int32),6647 => @enumFromInt(int32),
66166648
6617 u32,6649 u32,
...@@ -8317,7 +8349,7 @@ pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool {...@@ -8317,7 +8349,7 @@ pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool {
8317 return funcAnalysis(ip, i).inferred_error_set;8349 return funcAnalysis(ip, i).inferred_error_set;
8318}8350}
83198351
8320pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index {8352pub fn funcZirBodyInst(ip: *const InternPool, i: Index) TrackedInst.Index {
8321 assert(i != .none);8353 assert(i != .none);
8322 const item = ip.items.get(@intFromEnum(i));8354 const item = ip.items.get(@intFromEnum(i));
8323 const zir_body_inst_field_index = std.meta.fieldIndex(Tag.FuncDecl, "zir_body_inst").?;8355 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 {...@@ -834,6 +834,9 @@ pub const File = struct {
834 multi_pkg: bool = false,834 multi_pkg: bool = false,
835 /// List of references to this file, used for multi-package errors.835 /// List of references to this file, used for multi-package errors.
836 references: std.ArrayListUnmanaged(Reference) = .{},836 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
838 /// Used by change detection algorithm, after astgen, contains the841 /// Used by change detection algorithm, after astgen, contains the
839 /// set of decls that existed in the previous ZIR but not in the new one.842 /// 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 {...@@ -2594,7 +2597,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2594 const stat = try source_file.stat();2597 const stat = try source_file.stat();
25952598
2596 const want_local_cache = file.mod == mod.main_mod;2599 const want_local_cache = file.mod == mod.main_mod;
2597 const digest = hash: {2600 const bin_digest = hash: {
2598 var path_hash: Cache.HashHelper = .{};2601 var path_hash: Cache.HashHelper = .{};
2599 path_hash.addBytes(build_options.version);2602 path_hash.addBytes(build_options.version);
2600 path_hash.add(builtin.zig_backend);2603 path_hash.add(builtin.zig_backend);
...@@ -2603,7 +2606,19 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2603,7 +2606,19 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2603 path_hash.addBytes(file.mod.root.sub_path);2606 path_hash.addBytes(file.mod.root.sub_path);
2604 }2607 }
2605 path_hash.addBytes(file.sub_file_path);2608 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;
2607 };2622 };
2608 const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache;2623 const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache;
2609 const zir_dir = cache_directory.handle;2624 const zir_dir = cache_directory.handle;
...@@ -2613,7 +2628,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2613,7 +2628,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2613 .never_loaded, .retryable_failure => lock: {2628 .never_loaded, .retryable_failure => lock: {
2614 // First, load the cached ZIR code, if any.2629 // First, load the cached ZIR code, if any.
2615 log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{2630 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,
2617 });2632 });
26182633
2619 break :lock .shared;2634 break :lock .shared;
...@@ -2640,7 +2655,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2640,7 +2655,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2640 // version. Likewise if we're working on AstGen and another process asks for2655 // version. Likewise if we're working on AstGen and another process asks for
2641 // the cached file, they'll get it.2656 // the cached file, they'll get it.
2642 const cache_file = while (true) {2657 const cache_file = while (true) {
2643 break zir_dir.createFile(&digest, .{2658 break zir_dir.createFile(&hex_digest, .{
2644 .read = true,2659 .read = true,
2645 .truncate = false,2660 .truncate = false,
2646 .lock = lock,2661 .lock = lock,
...@@ -2826,7 +2841,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2826,7 +2841,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2826 };2841 };
2827 cache_file.writevAll(&iovecs) catch |err| {2842 cache_file.writevAll(&iovecs) catch |err| {
2828 log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{2843 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),
2830 });2845 });
2831 };2846 };
28322847
...@@ -2935,89 +2950,22 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File)...@@ -2935,89 +2950,22 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File)
2935 return zir;2950 return zir;
2936}2951}
29372952
2938/// Patch ups:2953fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void {
2939/// * Struct.zir_index2954 const gpa = zcu.gpa;
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;
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.
2952 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};2956 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
2953 defer inst_map.deinit(gpa);2957 defer inst_map.deinit(gpa);
29542958
2955 try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map);2959 try mapOldZirToNew(gpa, old_zir, file.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 }
29922960
2993 if (!decl.owns_tv) continue;2961 // TODO: this should be done after all AstGen workers complete, to avoid
29942962 // iterating over this full set for every updated file.
2995 if (decl.getOwnedStruct(mod)) |struct_type| {2963 for (zcu.intern_pool.tracked_insts.keys()) |*ti| {
2996 struct_type.setZirIndex(ip, inst_map.get(struct_type.zir_index) orelse {2964 if (!std.mem.eql(u8, &ti.path_digest, &file.path_digest)) continue;
2997 try file.deleted_decls.append(gpa, decl_index);2965 ti.inst = inst_map.get(ti.inst) orelse {
2998 continue;2966 // TODO: invalidate this `TrackedInst` via the dependency mechanism
2999 });2967 continue;
3000 }2968 };
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 }
3021 }2969 }
3022}2970}
30232971
...@@ -3494,7 +3442,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -3494,7 +3442,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
3494 const struct_ty = sema.getStructType(3442 const struct_ty = sema.getStructType(
3495 new_decl_index,3443 new_decl_index,
3496 new_namespace_index,3444 new_namespace_index,
3497 .main_struct_inst,3445 try mod.intern_pool.trackZir(gpa, file, .main_struct_inst),
3498 ) catch |err| switch (err) {3446 ) catch |err| switch (err) {
3499 error.OutOfMemory => return error.OutOfMemory,3447 error.OutOfMemory => return error.OutOfMemory,
3500 };3448 };
...@@ -4472,7 +4420,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato...@@ -4472,7 +4420,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
4472 };4420 };
4473 defer inner_block.instructions.deinit(gpa);4421 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
4477 // Here we are performing "runtime semantic analysis" for a function body, which means4425 // Here we are performing "runtime semantic analysis" for a function body, which means
4478 // we must map the parameter ZIR instructions to `arg` AIR instructions.4426 // 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]...@@ -6125,7 +6073,7 @@ pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]
6125 const tags = file.zir.instructions.items(.tag);6073 const tags = file.zir.instructions.items(.tag);
6126 const data = file.zir.instructions.items(.data);6074 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));
6129 const param = param_body[index];6077 const param = param_body[index];
61306078
6131 return switch (tags[@intFromEnum(param)]) {6079 return switch (tags[@intFromEnum(param)]) {
src/Sema.zig+21-17
...@@ -2708,11 +2708,12 @@ pub fn getStructType(...@@ -2708,11 +2708,12 @@ pub fn getStructType(
2708 sema: *Sema,2708 sema: *Sema,
2709 decl: InternPool.DeclIndex,2709 decl: InternPool.DeclIndex,
2710 namespace: InternPool.NamespaceIndex,2710 namespace: InternPool.NamespaceIndex,
2711 zir_index: Zir.Inst.Index,2711 tracked_inst: InternPool.TrackedInst.Index,
2712) !InternPool.Index {2712) !InternPool.Index {
2713 const mod = sema.mod;2713 const mod = sema.mod;
2714 const gpa = sema.gpa;2714 const gpa = sema.gpa;
2715 const ip = &mod.intern_pool;2715 const ip = &mod.intern_pool;
2716 const zir_index = tracked_inst.resolve(ip);
2716 const extended = sema.code.instructions.items(.data)[@intFromEnum(zir_index)].extended;2717 const extended = sema.code.instructions.items(.data)[@intFromEnum(zir_index)].extended;
2717 assert(extended.opcode == .struct_decl);2718 assert(extended.opcode == .struct_decl);
2718 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);2719 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
...@@ -2747,7 +2748,7 @@ pub fn getStructType(...@@ -2747,7 +2748,7 @@ pub fn getStructType(
2747 const ty = try ip.getStructType(gpa, .{2748 const ty = try ip.getStructType(gpa, .{
2748 .decl = decl,2749 .decl = decl,
2749 .namespace = namespace.toOptional(),2750 .namespace = namespace.toOptional(),
2750 .zir_index = zir_index,2751 .zir_index = tracked_inst,
2751 .layout = small.layout,2752 .layout = small.layout,
2752 .known_non_opv = small.known_non_opv,2753 .known_non_opv = small.known_non_opv,
2753 .is_tuple = small.is_tuple,2754 .is_tuple = small.is_tuple,
...@@ -2797,7 +2798,8 @@ fn zirStructDecl(...@@ -2797,7 +2798,8 @@ fn zirStructDecl(
2797 errdefer mod.destroyNamespace(new_namespace_index);2798 errdefer mod.destroyNamespace(new_namespace_index);
27982799
2799 const struct_ty = ty: {2800 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);
2801 if (sema.builtin_type_target_index != .none) {2803 if (sema.builtin_type_target_index != .none) {
2802 ip.resolveBuiltinType(sema.builtin_type_target_index, ty);2804 ip.resolveBuiltinType(sema.builtin_type_target_index, ty);
2803 break :ty sema.builtin_type_target_index;2805 break :ty sema.builtin_type_target_index;
...@@ -2856,7 +2858,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2856,7 +2858,7 @@ fn createAnonymousDeclTypeNamed(
2856 return new_decl_index;2858 return new_decl_index;
2857 },2859 },
2858 .func => {2860 .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));
2860 const zir_tags = sema.code.instructions.items(.tag);2862 const zir_tags = sema.code.instructions.items(.tag);
28612863
2862 var buf = std.ArrayList(u8).init(gpa);2864 var buf = std.ArrayList(u8).init(gpa);
...@@ -3252,7 +3254,7 @@ fn zirUnionDecl(...@@ -3252,7 +3254,7 @@ fn zirUnionDecl(
3252 },3254 },
3253 .decl = new_decl_index,3255 .decl = new_decl_index,
3254 .namespace = new_namespace_index,3256 .namespace = new_namespace_index,
3255 .zir_index = inst,3257 .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst),
3256 .fields_len = fields_len,3258 .fields_len = fields_len,
3257 .enum_tag_ty = .none,3259 .enum_tag_ty = .none,
3258 .field_types = &.{},3260 .field_types = &.{},
...@@ -7446,7 +7448,7 @@ fn analyzeCall(...@@ -7446,7 +7448,7 @@ fn analyzeCall(
7446 // the AIR instructions of the callsite. The callee could be a generic function7448 // the AIR instructions of the callsite. The callee could be a generic function
7447 // which means its parameter type expressions must be resolved in order and used7449 // which means its parameter type expressions must be resolved in order and used
7448 // to successively coerce the arguments.7450 // 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));
7450 try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);7452 try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
74517453
7452 var arg_i: u32 = 0;7454 var arg_i: u32 = 0;
...@@ -7494,7 +7496,7 @@ fn analyzeCall(...@@ -7494,7 +7496,7 @@ fn analyzeCall(
7494 // each of the parameters, resolving the return type and providing it to the child7496 // each of the parameters, resolving the return type and providing it to the child
7495 // `Sema` so that it can be used for the `ret_ptr` instruction.7497 // `Sema` so that it can be used for the `ret_ptr` instruction.
7496 const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)7498 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))
7498 else7500 else
7499 try sema.resolveInst(fn_info.ret_ty_ref);7501 try sema.resolveInst(fn_info.ret_ty_ref);
7500 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };7502 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
...@@ -7885,7 +7887,7 @@ fn instantiateGenericCall(...@@ -7885,7 +7887,7 @@ fn instantiateGenericCall(
7885 const namespace_index = fn_owner_decl.src_namespace;7887 const namespace_index = fn_owner_decl.src_namespace;
7886 const namespace = mod.namespacePtr(namespace_index);7888 const namespace = mod.namespacePtr(namespace_index);
7887 const fn_zir = namespace.file_scope.zir;7889 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
7890 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());7892 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());
7891 @memset(comptime_args, .none);7893 @memset(comptime_args, .none);
...@@ -9467,7 +9469,7 @@ fn funcCommon(...@@ -9467,7 +9469,7 @@ fn funcCommon(
9467 .is_generic = final_is_generic,9469 .is_generic = final_is_generic,
9468 .is_noinline = is_noinline,9470 .is_noinline = is_noinline,
94699471
9470 .zir_body_inst = func_inst,9472 .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst),
9471 .lbrace_line = src_locs.lbrace_line,9473 .lbrace_line = src_locs.lbrace_line,
9472 .rbrace_line = src_locs.rbrace_line,9474 .rbrace_line = src_locs.rbrace_line,
9473 .lbrace_column = @as(u16, @truncate(src_locs.columns)),9475 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
...@@ -9545,7 +9547,7 @@ fn funcCommon(...@@ -9545,7 +9547,7 @@ fn funcCommon(
9545 .ty = func_ty,9547 .ty = func_ty,
9546 .cc = cc,9548 .cc = cc,
9547 .is_noinline = is_noinline,9549 .is_noinline = is_noinline,
9548 .zir_body_inst = func_inst,9550 .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst),
9549 .lbrace_line = src_locs.lbrace_line,9551 .lbrace_line = src_locs.lbrace_line,
9550 .rbrace_line = src_locs.rbrace_line,9552 .rbrace_line = src_locs.rbrace_line,
9551 .lbrace_column = @as(u16, @truncate(src_locs.columns)),9553 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
...@@ -21553,7 +21555,7 @@ fn zirReify(...@@ -21553,7 +21555,7 @@ fn zirReify(
21553 .namespace = new_namespace_index,21555 .namespace = new_namespace_index,
21554 .enum_tag_ty = enum_tag_ty,21556 .enum_tag_ty = enum_tag_ty,
21555 .fields_len = fields_len,21557 .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?
21557 .flags = .{21559 .flags = .{
21558 .layout = layout,21560 .layout = layout,
21559 .status = .have_field_types,21561 .status = .have_field_types,
...@@ -21721,7 +21723,7 @@ fn reifyStruct(...@@ -21721,7 +21723,7 @@ fn reifyStruct(
21721 const ty = try ip.getStructType(gpa, .{21723 const ty = try ip.getStructType(gpa, .{
21722 .decl = new_decl_index,21724 .decl = new_decl_index,
21723 .namespace = .none,21725 .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?
21725 .layout = layout,21727 .layout = layout,
21726 .known_non_opv = false,21728 .known_non_opv = false,
21727 .fields_len = fields_len,21729 .fields_len = fields_len,
...@@ -35593,7 +35595,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp...@@ -35593,7 +35595,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
35593 break :blk accumulator;35595 break :blk accumulator;
35594 };35596 };
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;
35597 assert(extended.opcode == .struct_decl);35600 assert(extended.opcode == .struct_decl);
35598 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);35601 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
3559935602
...@@ -35613,7 +35616,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp...@@ -35613,7 +35616,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
35613 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);35616 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);
35614 } else {35617 } else {
35615 const body = zir.bodySlice(extra_index, backing_int_body_len);35618 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);
35617 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);35620 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);
35618 }35621 }
35619 };35622 };
...@@ -36357,7 +36360,7 @@ fn semaStructFields(...@@ -36357,7 +36360,7 @@ fn semaStructFields(
36357 const decl = mod.declPtr(decl_index);36360 const decl = mod.declPtr(decl_index);
36358 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;36361 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;
36359 const zir = mod.namespacePtr(namespace_index).file_scope.zir;36362 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
36362 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);36365 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);
3636336366
...@@ -36628,7 +36631,7 @@ fn semaStructFieldInits(...@@ -36628,7 +36631,7 @@ fn semaStructFieldInits(
36628 const decl = mod.declPtr(decl_index);36631 const decl = mod.declPtr(decl_index);
36629 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;36632 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;
36630 const zir = mod.namespacePtr(namespace_index).file_scope.zir;36633 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);
36632 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);36635 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);
3663336636
36634 var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa);36637 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...@@ -36777,7 +36780,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
36777 const ip = &mod.intern_pool;36780 const ip = &mod.intern_pool;
36778 const decl_index = union_type.decl;36781 const decl_index = union_type.decl;
36779 const zir = mod.namespacePtr(union_type.namespace).file_scope.zir;36782 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;
36781 assert(extended.opcode == .union_decl);36785 assert(extended.opcode == .union_decl);
36782 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);36786 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
36783 var extra_index: usize = extended.operand;36787 var extra_index: usize = extended.operand;