zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob a5e61fa4 (279887B) - Raw


      1 //! Compilation of all Zig source code is represented by one `Module`.
      2 //! Each `Compilation` has exactly one or zero `Module`, depending on whether
      3 //! there is or is not any zig source code, respectively.
      4 
      5 const std = @import("std");
      6 const builtin = @import("builtin");
      7 const mem = std.mem;
      8 const Allocator = std.mem.Allocator;
      9 const ArrayListUnmanaged = std.ArrayListUnmanaged;
     10 const assert = std.debug.assert;
     11 const log = std.log.scoped(.module);
     12 const BigIntConst = std.math.big.int.Const;
     13 const BigIntMutable = std.math.big.int.Mutable;
     14 const Target = std.Target;
     15 const Ast = std.zig.Ast;
     16 
     17 const Module = @This();
     18 const Compilation = @import("Compilation.zig");
     19 const Cache = std.Build.Cache;
     20 const Value = @import("value.zig").Value;
     21 const Type = @import("type.zig").Type;
     22 const TypedValue = @import("TypedValue.zig");
     23 const Package = @import("Package.zig");
     24 const link = @import("link.zig");
     25 const Air = @import("Air.zig");
     26 const Zir = @import("Zir.zig");
     27 const trace = @import("tracy.zig").trace;
     28 const AstGen = @import("AstGen.zig");
     29 const Sema = @import("Sema.zig");
     30 const target_util = @import("target.zig");
     31 const build_options = @import("build_options");
     32 const Liveness = @import("Liveness.zig");
     33 const isUpDir = @import("introspect.zig").isUpDir;
     34 const clang = @import("clang.zig");
     35 const InternPool = @import("InternPool.zig");
     36 
     37 comptime {
     38     @setEvalBranchQuota(4000);
     39     for (
     40         @typeInfo(Zir.Inst.Ref).Enum.fields,
     41         @typeInfo(Air.Inst.Ref).Enum.fields,
     42         @typeInfo(InternPool.Index).Enum.fields,
     43     ) |zir_field, air_field, ip_field| {
     44         assert(mem.eql(u8, zir_field.name, ip_field.name));
     45         assert(mem.eql(u8, air_field.name, ip_field.name));
     46     }
     47 }
     48 
     49 /// General-purpose allocator. Used for both temporary and long-term storage.
     50 gpa: Allocator,
     51 comp: *Compilation,
     52 
     53 /// Where build artifacts and incremental compilation metadata serialization go.
     54 zig_cache_artifact_directory: Compilation.Directory,
     55 /// Pointer to externally managed resource.
     56 root_pkg: *Package,
     57 /// Normally, `main_pkg` and `root_pkg` are the same. The exception is `zig test`, in which
     58 /// `root_pkg` is the test runner, and `main_pkg` is the user's source file which has the tests.
     59 main_pkg: *Package,
     60 sema_prog_node: std.Progress.Node = undefined,
     61 
     62 /// Used by AstGen worker to load and store ZIR cache.
     63 global_zir_cache: Compilation.Directory,
     64 /// Used by AstGen worker to load and store ZIR cache.
     65 local_zir_cache: Compilation.Directory,
     66 /// It's rare for a decl to be exported, so we save memory by having a sparse
     67 /// map of Decl indexes to details about them being exported.
     68 /// The Export memory is owned by the `export_owners` table; the slice itself
     69 /// is owned by this table. The slice is guaranteed to not be empty.
     70 decl_exports: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Export)) = .{},
     71 /// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl
     72 /// is modified. Note that the key of this table is not the Decl being exported, but the Decl that
     73 /// is performing the export of another Decl.
     74 /// This table owns the Export memory.
     75 export_owners: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Export)) = .{},
     76 /// The set of all the Zig source files in the Module. We keep track of this in order
     77 /// to iterate over it and check which source files have been modified on the file system when
     78 /// an update is requested, as well as to cache `@import` results.
     79 /// Keys are fully resolved file paths. This table owns the keys and values.
     80 import_table: std.StringArrayHashMapUnmanaged(*File) = .{},
     81 /// The set of all the files which have been loaded with `@embedFile` in the Module.
     82 /// We keep track of this in order to iterate over it and check which files have been
     83 /// modified on the file system when an update is requested, as well as to cache
     84 /// `@embedFile` results.
     85 /// Keys are fully resolved file paths. This table owns the keys and values.
     86 embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},
     87 
     88 /// This is a temporary addition to stage2 in order to match legacy behavior,
     89 /// however the end-game once the lang spec is settled will be to use a global
     90 /// InternPool for comptime memoized objects, making this behavior consistent across all types,
     91 /// not only string literals. Or, we might decide to not guarantee string literals
     92 /// to have equal comptime pointers, in which case this field can be deleted (perhaps
     93 /// the commit that introduced it can simply be reverted).
     94 /// This table uses an optional index so that when a Decl is destroyed, the string literal
     95 /// is still reclaimable by a future Decl.
     96 string_literal_table: std.HashMapUnmanaged(StringLiteralContext.Key, Decl.OptionalIndex, StringLiteralContext, std.hash_map.default_max_load_percentage) = .{},
     97 string_literal_bytes: ArrayListUnmanaged(u8) = .{},
     98 
     99 /// Stores all Type and Value objects; periodically garbage collected.
    100 intern_pool: InternPool = .{},
    101 /// Temporarily used for some unfortunate allocations made by backends that need to construct
    102 /// pointer types that can't be represented by the InternPool. Once all types are migrated
    103 /// to be stored in the InternPool, this can be removed.
    104 tmp_hack_arena: std.heap.ArenaAllocator,
    105 
    106 /// The set of all the generic function instantiations. This is used so that when a generic
    107 /// function is called twice with the same comptime parameter arguments, both calls dispatch
    108 /// to the same function.
    109 monomorphed_funcs: MonomorphedFuncsSet = .{},
    110 /// The set of all comptime function calls that have been cached so that future calls
    111 /// with the same parameters will get the same return value.
    112 memoized_calls: MemoizedCallSet = .{},
    113 /// Contains the values from `@setAlignStack`. A sparse table is used here
    114 /// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
    115 /// functions are many.
    116 align_stack_fns: std.AutoHashMapUnmanaged(*const Fn, SetAlignStack) = .{},
    117 
    118 /// We optimize memory usage for a compilation with no compile errors by storing the
    119 /// error messages and mapping outside of `Decl`.
    120 /// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
    121 /// Note that a Decl can succeed but the Fn it represents can fail. In this case,
    122 /// a Decl can have a failed_decls entry but have analysis status of success.
    123 failed_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, *ErrorMsg) = .{},
    124 /// Keep track of one `@compileLog` callsite per owner Decl.
    125 /// The value is the AST node index offset from the Decl.
    126 compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, i32) = .{},
    127 /// Using a map here for consistency with the other fields here.
    128 /// The ErrorMsg memory is owned by the `File`, using Module's general purpose allocator.
    129 failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{},
    130 /// The ErrorMsg memory is owned by the `EmbedFile`, using Module's general purpose allocator.
    131 failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{},
    132 /// Using a map here for consistency with the other fields here.
    133 /// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.
    134 failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},
    135 /// If a decl failed due to a cimport error, the corresponding Clang errors
    136 /// are stored here.
    137 cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, []CImportError) = .{},
    138 
    139 /// Candidates for deletion. After a semantic analysis update completes, this list
    140 /// contains Decls that need to be deleted if they end up having no references to them.
    141 deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
    142 
    143 /// Error tags and their values, tag names are duped with mod.gpa.
    144 /// Corresponds with `error_name_list`.
    145 global_error_set: std.StringHashMapUnmanaged(ErrorInt) = .{},
    146 
    147 /// ErrorInt -> []const u8 for fast lookups for @intToError at comptime
    148 /// Corresponds with `global_error_set`.
    149 error_name_list: ArrayListUnmanaged([]const u8),
    150 
    151 /// Incrementing integer used to compare against the corresponding Decl
    152 /// field to determine whether a Decl's status applies to an ongoing update, or a
    153 /// previous analysis.
    154 generation: u32 = 0,
    155 
    156 stage1_flags: packed struct {
    157     have_winmain: bool = false,
    158     have_wwinmain: bool = false,
    159     have_winmain_crt_startup: bool = false,
    160     have_wwinmain_crt_startup: bool = false,
    161     have_dllmain_crt_startup: bool = false,
    162     have_c_main: bool = false,
    163     reserved: u2 = 0,
    164 } = .{},
    165 
    166 job_queued_update_builtin_zig: bool = true,
    167 
    168 compile_log_text: ArrayListUnmanaged(u8) = .{},
    169 
    170 emit_h: ?*GlobalEmitH,
    171 
    172 test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
    173 
    174 /// Rather than allocating Decl objects with an Allocator, we instead allocate
    175 /// them with this SegmentedList. This provides four advantages:
    176 ///  * Stable memory so that one thread can access a Decl object while another
    177 ///    thread allocates additional Decl objects from this list.
    178 ///  * It allows us to use u32 indexes to reference Decl objects rather than
    179 ///    pointers, saving memory in Type, Value, and dependency sets.
    180 ///  * Using integers to reference Decl objects rather than pointers makes
    181 ///    serialization trivial.
    182 ///  * It provides a unique integer to be used for anonymous symbol names, avoiding
    183 ///    multi-threaded contention on an atomic counter.
    184 allocated_decls: std.SegmentedList(Decl, 0) = .{},
    185 /// When a Decl object is freed from `allocated_decls`, it is pushed into this stack.
    186 decls_free_list: ArrayListUnmanaged(Decl.Index) = .{},
    187 
    188 global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},
    189 
    190 reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
    191     referencer: Decl.Index,
    192     src: LazySrcLoc,
    193 }) = .{},
    194 
    195 pub const CImportError = struct {
    196     offset: u32,
    197     line: u32,
    198     column: u32,
    199     path: ?[*:0]u8,
    200     source_line: ?[*:0]u8,
    201     msg: [*:0]u8,
    202 
    203     pub fn deinit(err: CImportError, gpa: Allocator) void {
    204         if (err.path) |some| gpa.free(std.mem.span(some));
    205         if (err.source_line) |some| gpa.free(std.mem.span(some));
    206         gpa.free(std.mem.span(err.msg));
    207     }
    208 };
    209 
    210 pub const StringLiteralContext = struct {
    211     bytes: *ArrayListUnmanaged(u8),
    212 
    213     pub const Key = struct {
    214         index: u32,
    215         len: u32,
    216     };
    217 
    218     pub fn eql(self: @This(), a: Key, b: Key) bool {
    219         _ = self;
    220         return a.index == b.index and a.len == b.len;
    221     }
    222 
    223     pub fn hash(self: @This(), x: Key) u64 {
    224         const x_slice = self.bytes.items[x.index..][0..x.len];
    225         return std.hash_map.hashString(x_slice);
    226     }
    227 };
    228 
    229 pub const StringLiteralAdapter = struct {
    230     bytes: *ArrayListUnmanaged(u8),
    231 
    232     pub fn eql(self: @This(), a_slice: []const u8, b: StringLiteralContext.Key) bool {
    233         const b_slice = self.bytes.items[b.index..][0..b.len];
    234         return mem.eql(u8, a_slice, b_slice);
    235     }
    236 
    237     pub fn hash(self: @This(), adapted_key: []const u8) u64 {
    238         _ = self;
    239         return std.hash_map.hashString(adapted_key);
    240     }
    241 };
    242 
    243 const MonomorphedFuncsSet = std.HashMapUnmanaged(
    244     *Fn,
    245     void,
    246     MonomorphedFuncsContext,
    247     std.hash_map.default_max_load_percentage,
    248 );
    249 
    250 const MonomorphedFuncsContext = struct {
    251     pub fn eql(ctx: @This(), a: *Fn, b: *Fn) bool {
    252         _ = ctx;
    253         return a == b;
    254     }
    255 
    256     /// Must match `Sema.GenericCallAdapter.hash`.
    257     pub fn hash(ctx: @This(), key: *Fn) u64 {
    258         _ = ctx;
    259         return key.hash;
    260     }
    261 };
    262 
    263 pub const MemoizedCallSet = std.HashMapUnmanaged(
    264     MemoizedCall.Key,
    265     MemoizedCall.Result,
    266     MemoizedCall,
    267     std.hash_map.default_max_load_percentage,
    268 );
    269 
    270 pub const MemoizedCall = struct {
    271     module: *Module,
    272 
    273     pub const Key = struct {
    274         func: *Fn,
    275         args: []TypedValue,
    276     };
    277 
    278     pub const Result = struct {
    279         val: Value,
    280         arena: std.heap.ArenaAllocator.State,
    281     };
    282 
    283     pub fn eql(ctx: @This(), a: Key, b: Key) bool {
    284         if (a.func != b.func) return false;
    285 
    286         assert(a.args.len == b.args.len);
    287         for (a.args, 0..) |a_arg, arg_i| {
    288             const b_arg = b.args[arg_i];
    289             if (!a_arg.eql(b_arg, ctx.module)) {
    290                 return false;
    291             }
    292         }
    293 
    294         return true;
    295     }
    296 
    297     /// Must match `Sema.GenericCallAdapter.hash`.
    298     pub fn hash(ctx: @This(), key: Key) u64 {
    299         var hasher = std.hash.Wyhash.init(0);
    300 
    301         // The generic function Decl is guaranteed to be the first dependency
    302         // of each of its instantiations.
    303         std.hash.autoHash(&hasher, key.func);
    304 
    305         // This logic must be kept in sync with the logic in `analyzeCall` that
    306         // computes the hash.
    307         for (key.args) |arg| {
    308             arg.hash(&hasher, ctx.module);
    309         }
    310 
    311         return hasher.final();
    312     }
    313 };
    314 
    315 pub const SetAlignStack = struct {
    316     alignment: u32,
    317     /// TODO: This needs to store a non-lazy source location for the case of an inline function
    318     /// which does `@setAlignStack` (applying it to the caller).
    319     src: LazySrcLoc,
    320 };
    321 
    322 /// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
    323 pub const GlobalEmitH = struct {
    324     /// Where to put the output.
    325     loc: Compilation.EmitLoc,
    326     /// When emit_h is non-null, each Decl gets one more compile error slot for
    327     /// emit-h failing for that Decl. This table is also how we tell if a Decl has
    328     /// failed emit-h or succeeded.
    329     failed_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, *ErrorMsg) = .{},
    330     /// Tracks all decls in order to iterate over them and emit .h code for them.
    331     decl_table: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
    332     /// Similar to the allocated_decls field of Module, this is where `EmitH` objects
    333     /// are allocated. There will be exactly one EmitH object per Decl object, with
    334     /// identical indexes.
    335     allocated_emit_h: std.SegmentedList(EmitH, 0) = .{},
    336 
    337     pub fn declPtr(global_emit_h: *GlobalEmitH, decl_index: Decl.Index) *EmitH {
    338         return global_emit_h.allocated_emit_h.at(@enumToInt(decl_index));
    339     }
    340 };
    341 
    342 pub const ErrorInt = u32;
    343 
    344 pub const Export = struct {
    345     options: std.builtin.ExportOptions,
    346     src: LazySrcLoc,
    347     /// The Decl that performs the export. Note that this is *not* the Decl being exported.
    348     owner_decl: Decl.Index,
    349     /// The Decl containing the export statement.  Inline function calls
    350     /// may cause this to be different from the owner_decl.
    351     src_decl: Decl.Index,
    352     /// The Decl being exported. Note this is *not* the Decl performing the export.
    353     exported_decl: Decl.Index,
    354     status: enum {
    355         in_progress,
    356         failed,
    357         /// Indicates that the failure was due to a temporary issue, such as an I/O error
    358         /// when writing to the output file. Retrying the export may succeed.
    359         failed_retryable,
    360         complete,
    361     },
    362 
    363     pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc {
    364         const src_decl = mod.declPtr(exp.src_decl);
    365         return .{
    366             .file_scope = src_decl.getFileScope(),
    367             .parent_decl_node = src_decl.src_node,
    368             .lazy = exp.src,
    369         };
    370     }
    371 };
    372 
    373 pub const CaptureScope = struct {
    374     parent: ?*CaptureScope,
    375 
    376     /// Values from this decl's evaluation that will be closed over in
    377     /// child decls. Values stored in the value_arena of the linked decl.
    378     /// During sema, this map is backed by the gpa.  Once sema completes,
    379     /// it is reallocated using the value_arena.
    380     captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, TypedValue) = .{},
    381 
    382     pub fn failed(noalias self: *const @This()) bool {
    383         return self.captures.available == 0 and self.captures.size == std.math.maxInt(u32);
    384     }
    385 
    386     pub fn fail(noalias self: *@This()) void {
    387         self.captures.available = 0;
    388         self.captures.size = std.math.maxInt(u32);
    389     }
    390 };
    391 
    392 pub const WipCaptureScope = struct {
    393     scope: *CaptureScope,
    394     finalized: bool,
    395     gpa: Allocator,
    396     perm_arena: Allocator,
    397 
    398     pub fn init(gpa: Allocator, perm_arena: Allocator, parent: ?*CaptureScope) !@This() {
    399         const scope = try perm_arena.create(CaptureScope);
    400         scope.* = .{ .parent = parent };
    401         return @This(){
    402             .scope = scope,
    403             .finalized = false,
    404             .gpa = gpa,
    405             .perm_arena = perm_arena,
    406         };
    407     }
    408 
    409     pub fn finalize(noalias self: *@This()) !void {
    410         assert(!self.finalized);
    411         // use a temp to avoid unintentional aliasing due to RLS
    412         const tmp = try self.scope.captures.clone(self.perm_arena);
    413         self.scope.captures.deinit(self.gpa);
    414         self.scope.captures = tmp;
    415         self.finalized = true;
    416     }
    417 
    418     pub fn reset(noalias self: *@This(), parent: ?*CaptureScope) !void {
    419         if (!self.finalized) try self.finalize();
    420         self.scope = try self.perm_arena.create(CaptureScope);
    421         self.scope.* = .{ .parent = parent };
    422         self.finalized = false;
    423     }
    424 
    425     pub fn deinit(noalias self: *@This()) void {
    426         if (!self.finalized) {
    427             self.scope.captures.deinit(self.gpa);
    428             self.scope.fail();
    429         }
    430         self.* = undefined;
    431     }
    432 };
    433 
    434 const ValueArena = struct {
    435     state: std.heap.ArenaAllocator.State,
    436     state_acquired: ?*std.heap.ArenaAllocator.State = null,
    437 
    438     /// If this ValueArena replaced an existing one during re-analysis, this is the previous instance
    439     prev: ?*ValueArena = null,
    440 
    441     /// Returns an allocator backed by either promoting `state`, or by the existing ArenaAllocator
    442     /// that has already promoted `state`. `out_arena_allocator` provides storage for the initial promotion,
    443     /// and must live until the matching call to release().
    444     pub fn acquire(self: *ValueArena, child_allocator: Allocator, out_arena_allocator: *std.heap.ArenaAllocator) Allocator {
    445         if (self.state_acquired) |state_acquired| {
    446             return @fieldParentPtr(std.heap.ArenaAllocator, "state", state_acquired).allocator();
    447         }
    448 
    449         out_arena_allocator.* = self.state.promote(child_allocator);
    450         self.state_acquired = &out_arena_allocator.state;
    451         return out_arena_allocator.allocator();
    452     }
    453 
    454     /// Releases the allocator acquired by `acquire. `arena_allocator` must match the one passed to `acquire`.
    455     pub fn release(self: *ValueArena, arena_allocator: *std.heap.ArenaAllocator) void {
    456         if (@fieldParentPtr(std.heap.ArenaAllocator, "state", self.state_acquired.?) == arena_allocator) {
    457             self.state = self.state_acquired.?.*;
    458             self.state_acquired = null;
    459         }
    460     }
    461 
    462     pub fn deinit(self: ValueArena, child_allocator: Allocator) void {
    463         assert(self.state_acquired == null);
    464 
    465         const prev = self.prev;
    466         self.state.promote(child_allocator).deinit();
    467 
    468         if (prev) |p| {
    469             p.deinit(child_allocator);
    470         }
    471     }
    472 };
    473 
    474 pub const Decl = struct {
    475     /// Allocated with Module's allocator; outlives the ZIR code.
    476     name: [*:0]const u8,
    477     /// The most recent Type of the Decl after a successful semantic analysis.
    478     /// Populated when `has_tv`.
    479     ty: Type,
    480     /// The most recent Value of the Decl after a successful semantic analysis.
    481     /// Populated when `has_tv`.
    482     val: Value,
    483     /// Populated when `has_tv`.
    484     /// Points to memory inside value_arena.
    485     @"linksection": ?[*:0]const u8,
    486     /// Populated when `has_tv`.
    487     @"align": u32,
    488     /// Populated when `has_tv`.
    489     @"addrspace": std.builtin.AddressSpace,
    490     /// The memory for ty, val, align, linksection, and captures.
    491     /// If this is `null` then there is no memory management needed.
    492     value_arena: ?*ValueArena = null,
    493     /// The direct parent namespace of the Decl.
    494     /// Reference to externally owned memory.
    495     /// In the case of the Decl corresponding to a file, this is
    496     /// the namespace of the struct, since there is no parent.
    497     src_namespace: *Namespace,
    498 
    499     /// The scope which lexically contains this decl.  A decl must depend
    500     /// on its lexical parent, in order to ensure that this pointer is valid.
    501     /// This scope is allocated out of the arena of the parent decl.
    502     src_scope: ?*CaptureScope,
    503 
    504     /// An integer that can be checked against the corresponding incrementing
    505     /// generation field of Module. This is used to determine whether `complete` status
    506     /// represents pre- or post- re-analysis.
    507     generation: u32,
    508     /// The AST node index of this declaration.
    509     /// Must be recomputed when the corresponding source file is modified.
    510     src_node: Ast.Node.Index,
    511     /// Line number corresponding to `src_node`. Stored separately so that source files
    512     /// do not need to be loaded into memory in order to compute debug line numbers.
    513     /// This value is absolute.
    514     src_line: u32,
    515     /// Index to ZIR `extra` array to the entry in the parent's decl structure
    516     /// (the part that says "for every decls_len"). The first item at this index is
    517     /// the contents hash, followed by line, name, etc.
    518     /// For anonymous decls and also the root Decl for a File, this is 0.
    519     zir_decl_index: Zir.Inst.Index,
    520 
    521     /// Represents the "shallow" analysis status. For example, for decls that are functions,
    522     /// the function type is analyzed with this set to `in_progress`, however, the semantic
    523     /// analysis of the function body is performed with this value set to `success`. Functions
    524     /// have their own analysis status field.
    525     analysis: enum {
    526         /// This Decl corresponds to an AST Node that has not been referenced yet, and therefore
    527         /// because of Zig's lazy declaration analysis, it will remain unanalyzed until referenced.
    528         unreferenced,
    529         /// Semantic analysis for this Decl is running right now.
    530         /// This state detects dependency loops.
    531         in_progress,
    532         /// The file corresponding to this Decl had a parse error or ZIR error.
    533         /// There will be a corresponding ErrorMsg in Module.failed_files.
    534         file_failure,
    535         /// This Decl might be OK but it depends on another one which did not successfully complete
    536         /// semantic analysis.
    537         dependency_failure,
    538         /// Semantic analysis failure.
    539         /// There will be a corresponding ErrorMsg in Module.failed_decls.
    540         sema_failure,
    541         /// There will be a corresponding ErrorMsg in Module.failed_decls.
    542         /// This indicates the failure was something like running out of disk space,
    543         /// and attempting semantic analysis again may succeed.
    544         sema_failure_retryable,
    545         /// There will be a corresponding ErrorMsg in Module.failed_decls.
    546         liveness_failure,
    547         /// There will be a corresponding ErrorMsg in Module.failed_decls.
    548         codegen_failure,
    549         /// There will be a corresponding ErrorMsg in Module.failed_decls.
    550         /// This indicates the failure was something like running out of disk space,
    551         /// and attempting codegen again may succeed.
    552         codegen_failure_retryable,
    553         /// Everything is done. During an update, this Decl may be out of date, depending
    554         /// on its dependencies. The `generation` field can be used to determine if this
    555         /// completion status occurred before or after a given update.
    556         complete,
    557         /// A Module update is in progress, and this Decl has been flagged as being known
    558         /// to require re-analysis.
    559         outdated,
    560     },
    561     /// Whether `typed_value`, `align`, `linksection` and `addrspace` are populated.
    562     has_tv: bool,
    563     /// If `true` it means the `Decl` is the resource owner of the type/value associated
    564     /// with it. That means when `Decl` is destroyed, the cleanup code should additionally
    565     /// check if the value owns a `Namespace`, and destroy that too.
    566     owns_tv: bool,
    567     /// This flag is set when this Decl is added to `Module.deletion_set`, and cleared
    568     /// when removed.
    569     deletion_flag: bool,
    570     /// Whether the corresponding AST decl has a `pub` keyword.
    571     is_pub: bool,
    572     /// Whether the corresponding AST decl has a `export` keyword.
    573     is_exported: bool,
    574     /// Whether the ZIR code provides an align instruction.
    575     has_align: bool,
    576     /// Whether the ZIR code provides a linksection and address space instruction.
    577     has_linksection_or_addrspace: bool,
    578     /// Flag used by garbage collection to mark and sweep.
    579     /// Decls which correspond to an AST node always have this field set to `true`.
    580     /// Anonymous Decls are initialized with this field set to `false` and then it
    581     /// is the responsibility of machine code backends to mark it `true` whenever
    582     /// a `decl_ref` Value is encountered that points to this Decl.
    583     /// When the `codegen_decl` job is encountered in the main work queue, if the
    584     /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it
    585     /// deletes the Decl on the spot.
    586     alive: bool,
    587     /// If true `name` is already fully qualified.
    588     name_fully_qualified: bool = false,
    589     /// What kind of a declaration is this.
    590     kind: Kind,
    591 
    592     /// The shallow set of other decls whose typed_value could possibly change if this Decl's
    593     /// typed_value is modified.
    594     dependants: DepsTable = .{},
    595     /// The shallow set of other decls whose typed_value changing indicates that this Decl's
    596     /// typed_value may need to be regenerated.
    597     dependencies: DepsTable = .{},
    598 
    599     pub const Kind = enum {
    600         @"usingnamespace",
    601         @"test",
    602         @"comptime",
    603         named,
    604         anon,
    605     };
    606 
    607     pub const Index = enum(u32) {
    608         _,
    609 
    610         pub fn toOptional(i: Index) OptionalIndex {
    611             return @intToEnum(OptionalIndex, @enumToInt(i));
    612         }
    613     };
    614 
    615     pub const OptionalIndex = enum(u32) {
    616         none = std.math.maxInt(u32),
    617         _,
    618 
    619         pub fn init(oi: ?Index) OptionalIndex {
    620             return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
    621         }
    622 
    623         pub fn unwrap(oi: OptionalIndex) ?Index {
    624             if (oi == .none) return null;
    625             return @intToEnum(Index, @enumToInt(oi));
    626         }
    627     };
    628 
    629     pub const DepsTable = std.AutoArrayHashMapUnmanaged(Decl.Index, DepType);
    630 
    631     /// Later types take priority; e.g. if a dependent decl has both `normal`
    632     /// and `function_body` dependencies on another decl, it will be marked as
    633     /// having a `function_body` dependency.
    634     pub const DepType = enum {
    635         /// The dependent references or uses the dependency's value, so must be
    636         /// updated whenever it is changed. However, if the dependency is a
    637         /// function and its type is unchanged, the dependent does not need to
    638         /// be updated.
    639         normal,
    640         /// The dependent performs an inline or comptime call to the dependency,
    641         /// or is a generic instantiation of it. It must therefore be updated
    642         /// whenever the dependency is updated, even if the function type
    643         /// remained the same.
    644         function_body,
    645     };
    646 
    647     pub fn clearName(decl: *Decl, gpa: Allocator) void {
    648         gpa.free(mem.sliceTo(decl.name, 0));
    649         decl.name = undefined;
    650     }
    651 
    652     pub fn clearValues(decl: *Decl, mod: *Module) void {
    653         const gpa = mod.gpa;
    654         if (decl.getExternFn()) |extern_fn| {
    655             extern_fn.deinit(gpa);
    656             gpa.destroy(extern_fn);
    657         }
    658         if (decl.getFunction()) |func| {
    659             _ = mod.align_stack_fns.remove(func);
    660             if (func.comptime_args != null) {
    661                 _ = mod.monomorphed_funcs.remove(func);
    662             }
    663             func.deinit(gpa);
    664             gpa.destroy(func);
    665         }
    666         if (decl.getVariable()) |variable| {
    667             variable.deinit(gpa);
    668             gpa.destroy(variable);
    669         }
    670         if (decl.value_arena) |value_arena| {
    671             if (decl.owns_tv) {
    672                 if (decl.val.castTag(.str_lit)) |str_lit| {
    673                     mod.string_literal_table.getPtrContext(str_lit.data, .{
    674                         .bytes = &mod.string_literal_bytes,
    675                     }).?.* = .none;
    676                 }
    677             }
    678             value_arena.deinit(gpa);
    679             decl.value_arena = null;
    680             decl.has_tv = false;
    681             decl.owns_tv = false;
    682         }
    683     }
    684 
    685     pub fn finalizeNewArena(decl: *Decl, arena: *std.heap.ArenaAllocator) !void {
    686         assert(decl.value_arena == null);
    687         const value_arena = try arena.allocator().create(ValueArena);
    688         value_arena.* = .{ .state = arena.state };
    689         decl.value_arena = value_arena;
    690     }
    691 
    692     /// This name is relative to the containing namespace of the decl.
    693     /// The memory is owned by the containing File ZIR.
    694     pub fn getName(decl: Decl) ?[:0]const u8 {
    695         const zir = decl.getFileScope().zir;
    696         return decl.getNameZir(zir);
    697     }
    698 
    699     pub fn getNameZir(decl: Decl, zir: Zir) ?[:0]const u8 {
    700         assert(decl.zir_decl_index != 0);
    701         const name_index = zir.extra[decl.zir_decl_index + 5];
    702         if (name_index <= 1) return null;
    703         return zir.nullTerminatedString(name_index);
    704     }
    705 
    706     pub fn contentsHash(decl: Decl) std.zig.SrcHash {
    707         const zir = decl.getFileScope().zir;
    708         return decl.contentsHashZir(zir);
    709     }
    710 
    711     pub fn contentsHashZir(decl: Decl, zir: Zir) std.zig.SrcHash {
    712         assert(decl.zir_decl_index != 0);
    713         const hash_u32s = zir.extra[decl.zir_decl_index..][0..4];
    714         const contents_hash = @bitCast(std.zig.SrcHash, hash_u32s.*);
    715         return contents_hash;
    716     }
    717 
    718     pub fn zirBlockIndex(decl: *const Decl) Zir.Inst.Index {
    719         assert(decl.zir_decl_index != 0);
    720         const zir = decl.getFileScope().zir;
    721         return zir.extra[decl.zir_decl_index + 6];
    722     }
    723 
    724     pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref {
    725         if (!decl.has_align) return .none;
    726         assert(decl.zir_decl_index != 0);
    727         const zir = decl.getFileScope().zir;
    728         return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 8]);
    729     }
    730 
    731     pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref {
    732         if (!decl.has_linksection_or_addrspace) return .none;
    733         assert(decl.zir_decl_index != 0);
    734         const zir = decl.getFileScope().zir;
    735         const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align);
    736         return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
    737     }
    738 
    739     pub fn zirAddrspaceRef(decl: Decl) Zir.Inst.Ref {
    740         if (!decl.has_linksection_or_addrspace) return .none;
    741         assert(decl.zir_decl_index != 0);
    742         const zir = decl.getFileScope().zir;
    743         const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align) + 1;
    744         return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
    745     }
    746 
    747     pub fn relativeToLine(decl: Decl, offset: u32) u32 {
    748         return decl.src_line + offset;
    749     }
    750 
    751     pub fn relativeToNodeIndex(decl: Decl, offset: i32) Ast.Node.Index {
    752         return @bitCast(Ast.Node.Index, offset + @bitCast(i32, decl.src_node));
    753     }
    754 
    755     pub fn nodeIndexToRelative(decl: Decl, node_index: Ast.Node.Index) i32 {
    756         return @bitCast(i32, node_index) - @bitCast(i32, decl.src_node);
    757     }
    758 
    759     pub fn tokSrcLoc(decl: Decl, token_index: Ast.TokenIndex) LazySrcLoc {
    760         return .{ .token_offset = token_index - decl.srcToken() };
    761     }
    762 
    763     pub fn nodeSrcLoc(decl: Decl, node_index: Ast.Node.Index) LazySrcLoc {
    764         return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index));
    765     }
    766 
    767     pub fn srcLoc(decl: Decl) SrcLoc {
    768         return decl.nodeOffsetSrcLoc(0);
    769     }
    770 
    771     pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32) SrcLoc {
    772         return .{
    773             .file_scope = decl.getFileScope(),
    774             .parent_decl_node = decl.src_node,
    775             .lazy = LazySrcLoc.nodeOffset(node_offset),
    776         };
    777     }
    778 
    779     pub fn srcToken(decl: Decl) Ast.TokenIndex {
    780         const tree = &decl.getFileScope().tree;
    781         return tree.firstToken(decl.src_node);
    782     }
    783 
    784     pub fn srcByteOffset(decl: Decl) u32 {
    785         const tree = &decl.getFileScope().tree;
    786         return tree.tokens.items(.start)[decl.srcToken()];
    787     }
    788 
    789     pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {
    790         const unqualified_name = mem.sliceTo(decl.name, 0);
    791         if (decl.name_fully_qualified) {
    792             return writer.writeAll(unqualified_name);
    793         }
    794         return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer);
    795     }
    796 
    797     pub fn renderFullyQualifiedDebugName(decl: Decl, mod: *Module, writer: anytype) !void {
    798         const unqualified_name = mem.sliceTo(decl.name, 0);
    799         return decl.src_namespace.renderFullyQualifiedDebugName(mod, unqualified_name, writer);
    800     }
    801 
    802     pub fn getFullyQualifiedName(decl: Decl, mod: *Module) ![:0]u8 {
    803         var buffer = std.ArrayList(u8).init(mod.gpa);
    804         defer buffer.deinit();
    805         try decl.renderFullyQualifiedName(mod, buffer.writer());
    806 
    807         // Sanitize the name for nvptx which is more restrictive.
    808         if (mod.comp.bin_file.options.target.cpu.arch.isNvptx()) {
    809             for (buffer.items) |*byte| switch (byte.*) {
    810                 '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',
    811                 else => {},
    812             };
    813         }
    814 
    815         return buffer.toOwnedSliceSentinel(0);
    816     }
    817 
    818     pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {
    819         if (!decl.has_tv) return error.AnalysisFail;
    820         return TypedValue{
    821             .ty = decl.ty,
    822             .val = decl.val,
    823         };
    824     }
    825 
    826     pub fn value(decl: *Decl) error{AnalysisFail}!Value {
    827         return (try decl.typedValue()).val;
    828     }
    829 
    830     pub fn isFunction(decl: Decl, mod: *const Module) !bool {
    831         const tv = try decl.typedValue();
    832         return tv.ty.zigTypeTag(mod) == .Fn;
    833     }
    834 
    835     /// If the Decl has a value and it is a struct, return it,
    836     /// otherwise null.
    837     pub fn getStruct(decl: *Decl) ?*Struct {
    838         if (!decl.owns_tv) return null;
    839         const ty = (decl.val.castTag(.ty) orelse return null).data;
    840         const struct_obj = (ty.castTag(.@"struct") orelse return null).data;
    841         return struct_obj;
    842     }
    843 
    844     /// If the Decl has a value and it is a union, return it,
    845     /// otherwise null.
    846     pub fn getUnion(decl: *Decl) ?*Union {
    847         if (!decl.owns_tv) return null;
    848         const ty = (decl.val.castTag(.ty) orelse return null).data;
    849         const union_obj = (ty.cast(Type.Payload.Union) orelse return null).data;
    850         return union_obj;
    851     }
    852 
    853     /// If the Decl has a value and it is a function, return it,
    854     /// otherwise null.
    855     pub fn getFunction(decl: *const Decl) ?*Fn {
    856         if (!decl.owns_tv) return null;
    857         const func = (decl.val.castTag(.function) orelse return null).data;
    858         return func;
    859     }
    860 
    861     /// If the Decl has a value and it is an extern function, returns it,
    862     /// otherwise null.
    863     pub fn getExternFn(decl: *const Decl) ?*ExternFn {
    864         if (!decl.owns_tv) return null;
    865         const extern_fn = (decl.val.castTag(.extern_fn) orelse return null).data;
    866         return extern_fn;
    867     }
    868 
    869     /// If the Decl has a value and it is a variable, returns it,
    870     /// otherwise null.
    871     pub fn getVariable(decl: *const Decl) ?*Var {
    872         if (!decl.owns_tv) return null;
    873         const variable = (decl.val.castTag(.variable) orelse return null).data;
    874         return variable;
    875     }
    876 
    877     /// Gets the namespace that this Decl creates by being a struct, union,
    878     /// enum, or opaque.
    879     /// Only returns it if the Decl is the owner.
    880     pub fn getInnerNamespace(decl: *Decl) ?*Namespace {
    881         if (!decl.owns_tv) return null;
    882         const ty = (decl.val.castTag(.ty) orelse return null).data;
    883         switch (ty.tag()) {
    884             .@"struct" => {
    885                 const struct_obj = ty.castTag(.@"struct").?.data;
    886                 return &struct_obj.namespace;
    887             },
    888             .enum_full, .enum_nonexhaustive => {
    889                 const enum_obj = ty.cast(Type.Payload.EnumFull).?.data;
    890                 return &enum_obj.namespace;
    891             },
    892             .empty_struct => {
    893                 return ty.castTag(.empty_struct).?.data;
    894             },
    895             .@"opaque" => {
    896                 const opaque_obj = ty.cast(Type.Payload.Opaque).?.data;
    897                 return &opaque_obj.namespace;
    898             },
    899             .@"union", .union_safety_tagged, .union_tagged => {
    900                 const union_obj = ty.cast(Type.Payload.Union).?.data;
    901                 return &union_obj.namespace;
    902             },
    903 
    904             else => return null,
    905         }
    906     }
    907 
    908     pub fn dump(decl: *Decl) void {
    909         const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src);
    910         std.debug.print("{s}:{d}:{d} name={s} status={s}", .{
    911             decl.scope.sub_file_path,
    912             loc.line + 1,
    913             loc.column + 1,
    914             mem.sliceTo(decl.name, 0),
    915             @tagName(decl.analysis),
    916         });
    917         if (decl.has_tv) {
    918             std.debug.print(" ty={} val={}", .{ decl.ty, decl.val });
    919         }
    920         std.debug.print("\n", .{});
    921     }
    922 
    923     pub fn getFileScope(decl: Decl) *File {
    924         return decl.src_namespace.file_scope;
    925     }
    926 
    927     pub fn removeDependant(decl: *Decl, other: Decl.Index) void {
    928         assert(decl.dependants.swapRemove(other));
    929     }
    930 
    931     pub fn removeDependency(decl: *Decl, other: Decl.Index) void {
    932         assert(decl.dependencies.swapRemove(other));
    933     }
    934 
    935     pub fn isExtern(decl: Decl) bool {
    936         assert(decl.has_tv);
    937         return switch (decl.val.ip_index) {
    938             .none => switch (decl.val.tag()) {
    939                 .extern_fn => true,
    940                 .variable => decl.val.castTag(.variable).?.data.init.ip_index == .unreachable_value,
    941                 else => false,
    942             },
    943             else => false,
    944         };
    945     }
    946 
    947     pub fn getAlignment(decl: Decl, mod: *Module) u32 {
    948         assert(decl.has_tv);
    949         if (decl.@"align" != 0) {
    950             // Explicit alignment.
    951             return decl.@"align";
    952         } else {
    953             // Natural alignment.
    954             return decl.ty.abiAlignment(mod);
    955         }
    956     }
    957 };
    958 
    959 /// This state is attached to every Decl when Module emit_h is non-null.
    960 pub const EmitH = struct {
    961     fwd_decl: ArrayListUnmanaged(u8) = .{},
    962 };
    963 
    964 /// Represents the data that an explicit error set syntax provides.
    965 pub const ErrorSet = struct {
    966     /// The Decl that corresponds to the error set itself.
    967     owner_decl: Decl.Index,
    968     /// The string bytes are stored in the owner Decl arena.
    969     /// These must be in sorted order. See sortNames.
    970     names: NameMap,
    971 
    972     pub const NameMap = std.StringArrayHashMapUnmanaged(void);
    973 
    974     pub fn srcLoc(self: ErrorSet, mod: *Module) SrcLoc {
    975         const owner_decl = mod.declPtr(self.owner_decl);
    976         return .{
    977             .file_scope = owner_decl.getFileScope(),
    978             .parent_decl_node = owner_decl.src_node,
    979             .lazy = LazySrcLoc.nodeOffset(0),
    980         };
    981     }
    982 
    983     /// sort the NameMap. This should be called whenever the map is modified.
    984     /// alloc should be the allocator used for the NameMap data.
    985     pub fn sortNames(names: *NameMap) void {
    986         const Context = struct {
    987             keys: [][]const u8,
    988             pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
    989                 return std.mem.lessThan(u8, ctx.keys[a_index], ctx.keys[b_index]);
    990             }
    991         };
    992         names.sort(Context{ .keys = names.keys() });
    993     }
    994 };
    995 
    996 pub const PropertyBoolean = enum { no, yes, unknown, wip };
    997 
    998 /// Represents the data that a struct declaration provides.
    999 pub const Struct = struct {
   1000     /// Set of field names in declaration order.
   1001     fields: Fields,
   1002     /// Represents the declarations inside this struct.
   1003     namespace: Namespace,
   1004     /// The Decl that corresponds to the struct itself.
   1005     owner_decl: Decl.Index,
   1006     /// Index of the struct_decl ZIR instruction.
   1007     zir_index: Zir.Inst.Index,
   1008     /// Indexes into `fields` sorted to be most memory efficient.
   1009     optimized_order: ?[*]u32 = null,
   1010     layout: std.builtin.Type.ContainerLayout,
   1011     /// If the layout is not packed, this is the noreturn type.
   1012     /// If the layout is packed, this is the backing integer type of the packed struct.
   1013     /// Whether zig chooses this type or the user specifies it, it is stored here.
   1014     /// This will be set to the noreturn type until status is `have_layout`.
   1015     backing_int_ty: Type = Type.noreturn,
   1016     status: enum {
   1017         none,
   1018         field_types_wip,
   1019         have_field_types,
   1020         layout_wip,
   1021         have_layout,
   1022         fully_resolved_wip,
   1023         // The types and all its fields have had their layout resolved. Even through pointer,
   1024         // which `have_layout` does not ensure.
   1025         fully_resolved,
   1026     },
   1027     /// If true, has more than one possible value. However it may still be non-runtime type
   1028     /// if it is a comptime-only type.
   1029     /// If false, resolving the fields is necessary to determine whether the type has only
   1030     /// one possible value.
   1031     known_non_opv: bool,
   1032     requires_comptime: PropertyBoolean = .unknown,
   1033     have_field_inits: bool = false,
   1034     is_tuple: bool,
   1035     assumed_runtime_bits: bool = false,
   1036 
   1037     pub const Fields = std.StringArrayHashMapUnmanaged(Field);
   1038 
   1039     /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl.
   1040     pub const Field = struct {
   1041         /// Uses `noreturn` to indicate `anytype`.
   1042         /// undefined until `status` is >= `have_field_types`.
   1043         ty: Type,
   1044         /// Uses `unreachable_value` to indicate no default.
   1045         default_val: Value,
   1046         /// Zero means to use the ABI alignment of the type.
   1047         abi_align: u32,
   1048         /// undefined until `status` is `have_layout`.
   1049         offset: u32,
   1050         /// If true then `default_val` is the comptime field value.
   1051         is_comptime: bool,
   1052 
   1053         /// Returns the field alignment. If the struct is packed, returns 0.
   1054         pub fn alignment(
   1055             field: Field,
   1056             mod: *Module,
   1057             layout: std.builtin.Type.ContainerLayout,
   1058         ) u32 {
   1059             if (field.abi_align != 0) {
   1060                 assert(layout != .Packed);
   1061                 return field.abi_align;
   1062             }
   1063 
   1064             const target = mod.getTarget();
   1065 
   1066             switch (layout) {
   1067                 .Packed => return 0,
   1068                 .Auto => {
   1069                     if (target.ofmt == .c) {
   1070                         return alignmentExtern(field, mod);
   1071                     } else {
   1072                         return field.ty.abiAlignment(mod);
   1073                     }
   1074                 },
   1075                 .Extern => return alignmentExtern(field, mod),
   1076             }
   1077         }
   1078 
   1079         pub fn alignmentExtern(field: Field, mod: *Module) u32 {
   1080             // This logic is duplicated in Type.abiAlignmentAdvanced.
   1081             const ty_abi_align = field.ty.abiAlignment(mod);
   1082 
   1083             if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {
   1084                 // The C ABI requires 128 bit integer fields of structs
   1085                 // to be 16-bytes aligned.
   1086                 return @max(ty_abi_align, 16);
   1087             }
   1088 
   1089             return ty_abi_align;
   1090         }
   1091     };
   1092 
   1093     /// Used in `optimized_order` to indicate field that is not present in the
   1094     /// runtime version of the struct.
   1095     pub const omitted_field = std.math.maxInt(u32);
   1096 
   1097     pub fn getFullyQualifiedName(s: *Struct, mod: *Module) ![:0]u8 {
   1098         return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
   1099     }
   1100 
   1101     pub fn srcLoc(s: Struct, mod: *Module) SrcLoc {
   1102         const owner_decl = mod.declPtr(s.owner_decl);
   1103         return .{
   1104             .file_scope = owner_decl.getFileScope(),
   1105             .parent_decl_node = owner_decl.src_node,
   1106             .lazy = LazySrcLoc.nodeOffset(0),
   1107         };
   1108     }
   1109 
   1110     pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc {
   1111         @setCold(true);
   1112         const owner_decl = mod.declPtr(s.owner_decl);
   1113         const file = owner_decl.getFileScope();
   1114         const tree = file.getTree(mod.gpa) catch |err| {
   1115             // In this case we emit a warning + a less precise source location.
   1116             log.warn("unable to load {s}: {s}", .{
   1117                 file.sub_file_path, @errorName(err),
   1118             });
   1119             return s.srcLoc(mod);
   1120         };
   1121         const node = owner_decl.relativeToNodeIndex(0);
   1122 
   1123         var buf: [2]Ast.Node.Index = undefined;
   1124         if (tree.fullContainerDecl(&buf, node)) |container_decl| {
   1125             return queryFieldSrc(tree.*, query, file, container_decl);
   1126         } else {
   1127             // This struct was generated using @Type
   1128             return s.srcLoc(mod);
   1129         }
   1130     }
   1131 
   1132     pub fn haveFieldTypes(s: Struct) bool {
   1133         return switch (s.status) {
   1134             .none,
   1135             .field_types_wip,
   1136             => false,
   1137             .have_field_types,
   1138             .layout_wip,
   1139             .have_layout,
   1140             .fully_resolved_wip,
   1141             .fully_resolved,
   1142             => true,
   1143         };
   1144     }
   1145 
   1146     pub fn haveLayout(s: Struct) bool {
   1147         return switch (s.status) {
   1148             .none,
   1149             .field_types_wip,
   1150             .have_field_types,
   1151             .layout_wip,
   1152             => false,
   1153             .have_layout,
   1154             .fully_resolved_wip,
   1155             .fully_resolved,
   1156             => true,
   1157         };
   1158     }
   1159 
   1160     pub fn packedFieldBitOffset(s: Struct, mod: *Module, index: usize) u16 {
   1161         assert(s.layout == .Packed);
   1162         assert(s.haveLayout());
   1163         var bit_sum: u64 = 0;
   1164         for (s.fields.values(), 0..) |field, i| {
   1165             if (i == index) {
   1166                 return @intCast(u16, bit_sum);
   1167             }
   1168             bit_sum += field.ty.bitSize(mod);
   1169         }
   1170         unreachable; // index out of bounds
   1171     }
   1172 
   1173     pub const RuntimeFieldIterator = struct {
   1174         module: *Module,
   1175         struct_obj: *const Struct,
   1176         index: u32 = 0,
   1177 
   1178         pub const FieldAndIndex = struct {
   1179             field: Field,
   1180             index: u32,
   1181         };
   1182 
   1183         pub fn next(it: *RuntimeFieldIterator) ?FieldAndIndex {
   1184             const mod = it.module;
   1185             while (true) {
   1186                 var i = it.index;
   1187                 it.index += 1;
   1188                 if (it.struct_obj.fields.count() <= i)
   1189                     return null;
   1190 
   1191                 if (it.struct_obj.optimized_order) |some| {
   1192                     i = some[i];
   1193                     if (i == Module.Struct.omitted_field) return null;
   1194                 }
   1195                 const field = it.struct_obj.fields.values()[i];
   1196 
   1197                 if (!field.is_comptime and field.ty.hasRuntimeBits(mod)) {
   1198                     return FieldAndIndex{ .index = i, .field = field };
   1199                 }
   1200             }
   1201         }
   1202     };
   1203 
   1204     pub fn runtimeFieldIterator(s: *const Struct, module: *Module) RuntimeFieldIterator {
   1205         return .{
   1206             .struct_obj = s,
   1207             .module = module,
   1208         };
   1209     }
   1210 };
   1211 
   1212 /// Represents the data that an enum declaration provides, when the fields
   1213 /// are auto-numbered, and there are no declarations. The integer tag type
   1214 /// is inferred to be the smallest power of two unsigned int that fits
   1215 /// the number of fields.
   1216 pub const EnumSimple = struct {
   1217     /// The Decl that corresponds to the enum itself.
   1218     owner_decl: Decl.Index,
   1219     /// Set of field names in declaration order.
   1220     fields: NameMap,
   1221 
   1222     pub const NameMap = EnumFull.NameMap;
   1223 
   1224     pub fn srcLoc(self: EnumSimple, mod: *Module) SrcLoc {
   1225         const owner_decl = mod.declPtr(self.owner_decl);
   1226         return .{
   1227             .file_scope = owner_decl.getFileScope(),
   1228             .parent_decl_node = owner_decl.src_node,
   1229             .lazy = LazySrcLoc.nodeOffset(0),
   1230         };
   1231     }
   1232 };
   1233 
   1234 /// Represents the data that an enum declaration provides, when there are no
   1235 /// declarations. However an integer tag type is provided, and the enum tag values
   1236 /// are explicitly provided.
   1237 pub const EnumNumbered = struct {
   1238     /// The Decl that corresponds to the enum itself.
   1239     owner_decl: Decl.Index,
   1240     /// An integer type which is used for the numerical value of the enum.
   1241     /// Whether zig chooses this type or the user specifies it, it is stored here.
   1242     tag_ty: Type,
   1243     /// Set of field names in declaration order.
   1244     fields: NameMap,
   1245     /// Maps integer tag value to field index.
   1246     /// Entries are in declaration order, same as `fields`.
   1247     /// If this hash map is empty, it means the enum tags are auto-numbered.
   1248     values: ValueMap,
   1249 
   1250     pub const NameMap = EnumFull.NameMap;
   1251     pub const ValueMap = EnumFull.ValueMap;
   1252 
   1253     pub fn srcLoc(self: EnumNumbered, mod: *Module) SrcLoc {
   1254         const owner_decl = mod.declPtr(self.owner_decl);
   1255         return .{
   1256             .file_scope = owner_decl.getFileScope(),
   1257             .parent_decl_node = owner_decl.src_node,
   1258             .lazy = LazySrcLoc.nodeOffset(0),
   1259         };
   1260     }
   1261 };
   1262 
   1263 /// Represents the data that an enum declaration provides, when there is
   1264 /// at least one tag value explicitly specified, or at least one declaration.
   1265 pub const EnumFull = struct {
   1266     /// The Decl that corresponds to the enum itself.
   1267     owner_decl: Decl.Index,
   1268     /// An integer type which is used for the numerical value of the enum.
   1269     /// Whether zig chooses this type or the user specifies it, it is stored here.
   1270     tag_ty: Type,
   1271     /// Set of field names in declaration order.
   1272     fields: NameMap,
   1273     /// Maps integer tag value to field index.
   1274     /// Entries are in declaration order, same as `fields`.
   1275     /// If this hash map is empty, it means the enum tags are auto-numbered.
   1276     values: ValueMap,
   1277     /// Represents the declarations inside this enum.
   1278     namespace: Namespace,
   1279     /// true if zig inferred this tag type, false if user specified it
   1280     tag_ty_inferred: bool,
   1281 
   1282     pub const NameMap = std.StringArrayHashMapUnmanaged(void);
   1283     pub const ValueMap = std.ArrayHashMapUnmanaged(Value, void, Value.ArrayHashContext, false);
   1284 
   1285     pub fn srcLoc(self: EnumFull, mod: *Module) SrcLoc {
   1286         const owner_decl = mod.declPtr(self.owner_decl);
   1287         return .{
   1288             .file_scope = owner_decl.getFileScope(),
   1289             .parent_decl_node = owner_decl.src_node,
   1290             .lazy = LazySrcLoc.nodeOffset(0),
   1291         };
   1292     }
   1293 
   1294     pub fn fieldSrcLoc(e: EnumFull, mod: *Module, query: FieldSrcQuery) SrcLoc {
   1295         @setCold(true);
   1296         const owner_decl = mod.declPtr(e.owner_decl);
   1297         const file = owner_decl.getFileScope();
   1298         const tree = file.getTree(mod.gpa) catch |err| {
   1299             // In this case we emit a warning + a less precise source location.
   1300             log.warn("unable to load {s}: {s}", .{
   1301                 file.sub_file_path, @errorName(err),
   1302             });
   1303             return e.srcLoc(mod);
   1304         };
   1305         const node = owner_decl.relativeToNodeIndex(0);
   1306         var buf: [2]Ast.Node.Index = undefined;
   1307         if (tree.fullContainerDecl(&buf, node)) |container_decl| {
   1308             return queryFieldSrc(tree.*, query, file, container_decl);
   1309         } else {
   1310             // This enum was generated using @Type
   1311             return e.srcLoc(mod);
   1312         }
   1313     }
   1314 };
   1315 
   1316 pub const Union = struct {
   1317     /// An enum type which is used for the tag of the union.
   1318     /// This type is created even for untagged unions, even when the memory
   1319     /// layout does not store the tag.
   1320     /// Whether zig chooses this type or the user specifies it, it is stored here.
   1321     /// This will be set to the null type until status is `have_field_types`.
   1322     tag_ty: Type,
   1323     /// Set of field names in declaration order.
   1324     fields: Fields,
   1325     /// Represents the declarations inside this union.
   1326     namespace: Namespace,
   1327     /// The Decl that corresponds to the union itself.
   1328     owner_decl: Decl.Index,
   1329     /// Index of the union_decl ZIR instruction.
   1330     zir_index: Zir.Inst.Index,
   1331 
   1332     layout: std.builtin.Type.ContainerLayout,
   1333     status: enum {
   1334         none,
   1335         field_types_wip,
   1336         have_field_types,
   1337         layout_wip,
   1338         have_layout,
   1339         fully_resolved_wip,
   1340         // The types and all its fields have had their layout resolved. Even through pointer,
   1341         // which `have_layout` does not ensure.
   1342         fully_resolved,
   1343     },
   1344     requires_comptime: PropertyBoolean = .unknown,
   1345     assumed_runtime_bits: bool = false,
   1346 
   1347     pub const Field = struct {
   1348         /// undefined until `status` is `have_field_types` or `have_layout`.
   1349         ty: Type,
   1350         /// 0 means the ABI alignment of the type.
   1351         abi_align: u32,
   1352 
   1353         /// Returns the field alignment, assuming the union is not packed.
   1354         /// Keep implementation in sync with `Sema.unionFieldAlignment`.
   1355         /// Prefer to call that function instead of this one during Sema.
   1356         pub fn normalAlignment(field: Field, mod: *Module) u32 {
   1357             if (field.abi_align == 0) {
   1358                 return field.ty.abiAlignment(mod);
   1359             } else {
   1360                 return field.abi_align;
   1361             }
   1362         }
   1363     };
   1364 
   1365     pub const Fields = std.StringArrayHashMapUnmanaged(Field);
   1366 
   1367     pub fn getFullyQualifiedName(s: *Union, mod: *Module) ![:0]u8 {
   1368         return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
   1369     }
   1370 
   1371     pub fn srcLoc(self: Union, mod: *Module) SrcLoc {
   1372         const owner_decl = mod.declPtr(self.owner_decl);
   1373         return .{
   1374             .file_scope = owner_decl.getFileScope(),
   1375             .parent_decl_node = owner_decl.src_node,
   1376             .lazy = LazySrcLoc.nodeOffset(0),
   1377         };
   1378     }
   1379 
   1380     pub fn fieldSrcLoc(u: Union, mod: *Module, query: FieldSrcQuery) SrcLoc {
   1381         @setCold(true);
   1382         const owner_decl = mod.declPtr(u.owner_decl);
   1383         const file = owner_decl.getFileScope();
   1384         const tree = file.getTree(mod.gpa) catch |err| {
   1385             // In this case we emit a warning + a less precise source location.
   1386             log.warn("unable to load {s}: {s}", .{
   1387                 file.sub_file_path, @errorName(err),
   1388             });
   1389             return u.srcLoc(mod);
   1390         };
   1391         const node = owner_decl.relativeToNodeIndex(0);
   1392 
   1393         var buf: [2]Ast.Node.Index = undefined;
   1394         if (tree.fullContainerDecl(&buf, node)) |container_decl| {
   1395             return queryFieldSrc(tree.*, query, file, container_decl);
   1396         } else {
   1397             // This union was generated using @Type
   1398             return u.srcLoc(mod);
   1399         }
   1400     }
   1401 
   1402     pub fn haveFieldTypes(u: Union) bool {
   1403         return switch (u.status) {
   1404             .none,
   1405             .field_types_wip,
   1406             => false,
   1407             .have_field_types,
   1408             .layout_wip,
   1409             .have_layout,
   1410             .fully_resolved_wip,
   1411             .fully_resolved,
   1412             => true,
   1413         };
   1414     }
   1415 
   1416     pub fn hasAllZeroBitFieldTypes(u: Union, mod: *Module) bool {
   1417         assert(u.haveFieldTypes());
   1418         for (u.fields.values()) |field| {
   1419             if (field.ty.hasRuntimeBits(mod)) return false;
   1420         }
   1421         return true;
   1422     }
   1423 
   1424     pub fn mostAlignedField(u: Union, mod: *Module) u32 {
   1425         assert(u.haveFieldTypes());
   1426         var most_alignment: u32 = 0;
   1427         var most_index: usize = undefined;
   1428         for (u.fields.values(), 0..) |field, i| {
   1429             if (!field.ty.hasRuntimeBits(mod)) continue;
   1430 
   1431             const field_align = field.normalAlignment(mod);
   1432             if (field_align > most_alignment) {
   1433                 most_alignment = field_align;
   1434                 most_index = i;
   1435             }
   1436         }
   1437         return @intCast(u32, most_index);
   1438     }
   1439 
   1440     /// Returns 0 if the union is represented with 0 bits at runtime.
   1441     pub fn abiAlignment(u: Union, mod: *Module, have_tag: bool) u32 {
   1442         var max_align: u32 = 0;
   1443         if (have_tag) max_align = u.tag_ty.abiAlignment(mod);
   1444         for (u.fields.values()) |field| {
   1445             if (!field.ty.hasRuntimeBits(mod)) continue;
   1446 
   1447             const field_align = field.normalAlignment(mod);
   1448             max_align = @max(max_align, field_align);
   1449         }
   1450         return max_align;
   1451     }
   1452 
   1453     pub fn abiSize(u: Union, mod: *Module, have_tag: bool) u64 {
   1454         return u.getLayout(mod, have_tag).abi_size;
   1455     }
   1456 
   1457     pub const Layout = struct {
   1458         abi_size: u64,
   1459         abi_align: u32,
   1460         most_aligned_field: u32,
   1461         most_aligned_field_size: u64,
   1462         biggest_field: u32,
   1463         payload_size: u64,
   1464         payload_align: u32,
   1465         tag_align: u32,
   1466         tag_size: u64,
   1467         padding: u32,
   1468     };
   1469 
   1470     pub fn haveLayout(u: Union) bool {
   1471         return switch (u.status) {
   1472             .none,
   1473             .field_types_wip,
   1474             .have_field_types,
   1475             .layout_wip,
   1476             => false,
   1477             .have_layout,
   1478             .fully_resolved_wip,
   1479             .fully_resolved,
   1480             => true,
   1481         };
   1482     }
   1483 
   1484     pub fn getLayout(u: Union, mod: *Module, have_tag: bool) Layout {
   1485         assert(u.haveLayout());
   1486         var most_aligned_field: u32 = undefined;
   1487         var most_aligned_field_size: u64 = undefined;
   1488         var biggest_field: u32 = undefined;
   1489         var payload_size: u64 = 0;
   1490         var payload_align: u32 = 0;
   1491         const fields = u.fields.values();
   1492         for (fields, 0..) |field, i| {
   1493             if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
   1494 
   1495             const field_align = a: {
   1496                 if (field.abi_align == 0) {
   1497                     break :a field.ty.abiAlignment(mod);
   1498                 } else {
   1499                     break :a field.abi_align;
   1500                 }
   1501             };
   1502             const field_size = field.ty.abiSize(mod);
   1503             if (field_size > payload_size) {
   1504                 payload_size = field_size;
   1505                 biggest_field = @intCast(u32, i);
   1506             }
   1507             if (field_align > payload_align) {
   1508                 payload_align = field_align;
   1509                 most_aligned_field = @intCast(u32, i);
   1510                 most_aligned_field_size = field_size;
   1511             }
   1512         }
   1513         payload_align = @max(payload_align, 1);
   1514         if (!have_tag or !u.tag_ty.hasRuntimeBits(mod)) {
   1515             return .{
   1516                 .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align),
   1517                 .abi_align = payload_align,
   1518                 .most_aligned_field = most_aligned_field,
   1519                 .most_aligned_field_size = most_aligned_field_size,
   1520                 .biggest_field = biggest_field,
   1521                 .payload_size = payload_size,
   1522                 .payload_align = payload_align,
   1523                 .tag_align = 0,
   1524                 .tag_size = 0,
   1525                 .padding = 0,
   1526             };
   1527         }
   1528         // Put the tag before or after the payload depending on which one's
   1529         // alignment is greater.
   1530         const tag_size = u.tag_ty.abiSize(mod);
   1531         const tag_align = @max(1, u.tag_ty.abiAlignment(mod));
   1532         var size: u64 = 0;
   1533         var padding: u32 = undefined;
   1534         if (tag_align >= payload_align) {
   1535             // {Tag, Payload}
   1536             size += tag_size;
   1537             size = std.mem.alignForwardGeneric(u64, size, payload_align);
   1538             size += payload_size;
   1539             const prev_size = size;
   1540             size = std.mem.alignForwardGeneric(u64, size, tag_align);
   1541             padding = @intCast(u32, size - prev_size);
   1542         } else {
   1543             // {Payload, Tag}
   1544             size += payload_size;
   1545             size = std.mem.alignForwardGeneric(u64, size, tag_align);
   1546             size += tag_size;
   1547             const prev_size = size;
   1548             size = std.mem.alignForwardGeneric(u64, size, payload_align);
   1549             padding = @intCast(u32, size - prev_size);
   1550         }
   1551         return .{
   1552             .abi_size = size,
   1553             .abi_align = @max(tag_align, payload_align),
   1554             .most_aligned_field = most_aligned_field,
   1555             .most_aligned_field_size = most_aligned_field_size,
   1556             .biggest_field = biggest_field,
   1557             .payload_size = payload_size,
   1558             .payload_align = payload_align,
   1559             .tag_align = tag_align,
   1560             .tag_size = tag_size,
   1561             .padding = padding,
   1562         };
   1563     }
   1564 };
   1565 
   1566 pub const Opaque = struct {
   1567     /// The Decl that corresponds to the opaque itself.
   1568     owner_decl: Decl.Index,
   1569     /// Represents the declarations inside this opaque.
   1570     namespace: Namespace,
   1571 
   1572     pub fn srcLoc(self: Opaque, mod: *Module) SrcLoc {
   1573         const owner_decl = mod.declPtr(self.owner_decl);
   1574         return .{
   1575             .file_scope = owner_decl.getFileScope(),
   1576             .parent_decl_node = owner_decl.src_node,
   1577             .lazy = LazySrcLoc.nodeOffset(0),
   1578         };
   1579     }
   1580 
   1581     pub fn getFullyQualifiedName(s: *Opaque, mod: *Module) ![:0]u8 {
   1582         return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
   1583     }
   1584 };
   1585 
   1586 /// Some extern function struct memory is owned by the Decl's TypedValue.Managed
   1587 /// arena allocator.
   1588 pub const ExternFn = struct {
   1589     /// The Decl that corresponds to the function itself.
   1590     owner_decl: Decl.Index,
   1591     /// Library name if specified.
   1592     /// For example `extern "c" fn write(...) usize` would have 'c' as library name.
   1593     /// Allocated with Module's allocator; outlives the ZIR code.
   1594     lib_name: ?[*:0]const u8,
   1595 
   1596     pub fn deinit(extern_fn: *ExternFn, gpa: Allocator) void {
   1597         if (extern_fn.lib_name) |lib_name| {
   1598             gpa.free(mem.sliceTo(lib_name, 0));
   1599         }
   1600     }
   1601 };
   1602 
   1603 /// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
   1604 /// Extern functions do not have this data structure; they are represented by `ExternFn`
   1605 /// instead.
   1606 pub const Fn = struct {
   1607     /// The Decl that corresponds to the function itself.
   1608     owner_decl: Decl.Index,
   1609     /// The ZIR instruction that is a function instruction. Use this to find
   1610     /// the body. We store this rather than the body directly so that when ZIR
   1611     /// is regenerated on update(), we can map this to the new corresponding
   1612     /// ZIR instruction.
   1613     zir_body_inst: Zir.Inst.Index,
   1614     /// If this is not null, this function is a generic function instantiation, and
   1615     /// there is a `TypedValue` here for each parameter of the function.
   1616     /// Non-comptime parameters are marked with a `generic_poison` for the value.
   1617     /// Non-anytype parameters are marked with a `generic_poison` for the type.
   1618     /// These never have .generic_poison for the Type
   1619     /// because the Type is needed to pass to `Type.eql` and for inserting comptime arguments
   1620     /// into the inst_map when analyzing the body of a generic function instantiation.
   1621     /// Instead, the is_anytype knowledge is communicated via `isAnytypeParam`.
   1622     comptime_args: ?[*]TypedValue,
   1623 
   1624     /// Precomputed hash for monomorphed_funcs.
   1625     /// This is important because it may be accessed when resizing monomorphed_funcs
   1626     /// while this Fn has already been added to the set, but does not have the
   1627     /// owner_decl, comptime_args, or other fields populated yet.
   1628     /// This field is undefined if comptime_args == null.
   1629     hash: u64,
   1630 
   1631     /// Relative to owner Decl.
   1632     lbrace_line: u32,
   1633     /// Relative to owner Decl.
   1634     rbrace_line: u32,
   1635     lbrace_column: u16,
   1636     rbrace_column: u16,
   1637 
   1638     /// When a generic function is instantiated, this value is inherited from the
   1639     /// active Sema context. Importantly, this value is also updated when an existing
   1640     /// generic function instantiation is found and called.
   1641     branch_quota: u32,
   1642 
   1643     /// If this is not none, this function is a generic function instantiation, and
   1644     /// this is the generic function decl from which the instance was derived.
   1645     /// This information is redundant with a combination of checking if comptime_args is
   1646     /// not null and looking at the first decl dependency of owner_decl. This redundant
   1647     /// information is useful for three reasons:
   1648     /// 1. Improved perf of monomorphed_funcs when checking the eql() function because it
   1649     ///    can do two fewer pointer chases by grabbing the info from this field directly
   1650     ///    instead of accessing the decl and then the dependencies set.
   1651     /// 2. While a generic function instantiation is being initialized, we need hash()
   1652     ///    and eql() to work before the initialization is complete. Completing the
   1653     ///    insertion into the decl dependency set has more fallible operations than simply
   1654     ///    setting this field.
   1655     /// 3. I forgot what the third thing was while typing up the other two.
   1656     generic_owner_decl: Decl.OptionalIndex,
   1657 
   1658     state: Analysis,
   1659     is_cold: bool = false,
   1660     is_noinline: bool,
   1661     calls_or_awaits_errorable_fn: bool = false,
   1662 
   1663     /// Any inferred error sets that this function owns, both its own inferred error set and
   1664     /// inferred error sets of any inline/comptime functions called. Not to be confused
   1665     /// with inferred error sets of generic instantiations of this function, which are
   1666     /// *not* tracked here - they are tracked in the new `Fn` object created for the
   1667     /// instantiations.
   1668     inferred_error_sets: InferredErrorSetList = .{},
   1669 
   1670     pub const Analysis = enum {
   1671         /// This function has not yet undergone analysis, because we have not
   1672         /// seen a potential runtime call. It may be analyzed in future.
   1673         none,
   1674         /// Analysis for this function has been queued, but not yet completed.
   1675         queued,
   1676         /// This function intentionally only has ZIR generated because it is marked
   1677         /// inline, which means no runtime version of the function will be generated.
   1678         inline_only,
   1679         in_progress,
   1680         /// There will be a corresponding ErrorMsg in Module.failed_decls
   1681         sema_failure,
   1682         /// This Fn might be OK but it depends on another Decl which did not
   1683         /// successfully complete semantic analysis.
   1684         dependency_failure,
   1685         success,
   1686     };
   1687 
   1688     /// This struct is used to keep track of any dependencies related to functions instances
   1689     /// that return inferred error sets. Note that a function may be associated to
   1690     /// multiple different error sets, for example an inferred error set which
   1691     /// this function returns, but also any inferred error sets of called inline
   1692     /// or comptime functions.
   1693     pub const InferredErrorSet = struct {
   1694         /// The function from which this error set originates.
   1695         func: *Fn,
   1696 
   1697         /// All currently known errors that this error set contains. This includes
   1698         /// direct additions via `return error.Foo;`, and possibly also errors that
   1699         /// are returned from any dependent functions. When the inferred error set is
   1700         /// fully resolved, this map contains all the errors that the function might return.
   1701         errors: ErrorSet.NameMap = .{},
   1702 
   1703         /// Other inferred error sets which this inferred error set should include.
   1704         inferred_error_sets: std.AutoArrayHashMapUnmanaged(*InferredErrorSet, void) = .{},
   1705 
   1706         /// Whether the function returned anyerror. This is true if either of
   1707         /// the dependent functions returns anyerror.
   1708         is_anyerror: bool = false,
   1709 
   1710         /// Whether this error set is already fully resolved. If true, resolving
   1711         /// can skip resolving any dependents of this inferred error set.
   1712         is_resolved: bool = false,
   1713 
   1714         pub fn addErrorSet(self: *InferredErrorSet, gpa: Allocator, err_set_ty: Type) !void {
   1715             switch (err_set_ty.ip_index) {
   1716                 .anyerror_type => {
   1717                     self.is_anyerror = true;
   1718                 },
   1719                 .none => switch (err_set_ty.tag()) {
   1720                     .error_set => {
   1721                         const names = err_set_ty.castTag(.error_set).?.data.names.keys();
   1722                         for (names) |name| {
   1723                             try self.errors.put(gpa, name, {});
   1724                         }
   1725                     },
   1726                     .error_set_single => {
   1727                         const name = err_set_ty.castTag(.error_set_single).?.data;
   1728                         try self.errors.put(gpa, name, {});
   1729                     },
   1730                     .error_set_inferred => {
   1731                         const ies = err_set_ty.castTag(.error_set_inferred).?.data;
   1732                         try self.inferred_error_sets.put(gpa, ies, {});
   1733                     },
   1734                     .error_set_merged => {
   1735                         const names = err_set_ty.castTag(.error_set_merged).?.data.keys();
   1736                         for (names) |name| {
   1737                             try self.errors.put(gpa, name, {});
   1738                         }
   1739                     },
   1740                     else => unreachable,
   1741                 },
   1742                 else => @panic("TODO"),
   1743             }
   1744         }
   1745     };
   1746 
   1747     pub const InferredErrorSetList = std.SinglyLinkedList(InferredErrorSet);
   1748     pub const InferredErrorSetListNode = InferredErrorSetList.Node;
   1749 
   1750     pub fn deinit(func: *Fn, gpa: Allocator) void {
   1751         var it = func.inferred_error_sets.first;
   1752         while (it) |node| {
   1753             const next = node.next;
   1754             node.data.errors.deinit(gpa);
   1755             node.data.inferred_error_sets.deinit(gpa);
   1756             gpa.destroy(node);
   1757             it = next;
   1758         }
   1759     }
   1760 
   1761     pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {
   1762         const file = mod.declPtr(func.owner_decl).getFileScope();
   1763 
   1764         const tags = file.zir.instructions.items(.tag);
   1765 
   1766         const param_body = file.zir.getParamBody(func.zir_body_inst);
   1767         const param = param_body[index];
   1768 
   1769         return switch (tags[param]) {
   1770             .param, .param_comptime => false,
   1771             .param_anytype, .param_anytype_comptime => true,
   1772             else => unreachable,
   1773         };
   1774     }
   1775 
   1776     pub fn getParamName(func: Fn, mod: *Module, index: u32) [:0]const u8 {
   1777         const file = mod.declPtr(func.owner_decl).getFileScope();
   1778 
   1779         const tags = file.zir.instructions.items(.tag);
   1780         const data = file.zir.instructions.items(.data);
   1781 
   1782         const param_body = file.zir.getParamBody(func.zir_body_inst);
   1783         const param = param_body[index];
   1784 
   1785         return switch (tags[param]) {
   1786             .param, .param_comptime => blk: {
   1787                 const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index);
   1788                 break :blk file.zir.nullTerminatedString(extra.data.name);
   1789             },
   1790             .param_anytype, .param_anytype_comptime => blk: {
   1791                 const param_data = data[param].str_tok;
   1792                 break :blk param_data.get(file.zir);
   1793             },
   1794             else => unreachable,
   1795         };
   1796     }
   1797 
   1798     pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool {
   1799         const owner_decl = mod.declPtr(func.owner_decl);
   1800         const zir = owner_decl.getFileScope().zir;
   1801         const zir_tags = zir.instructions.items(.tag);
   1802         switch (zir_tags[func.zir_body_inst]) {
   1803             .func => return false,
   1804             .func_inferred => return true,
   1805             .func_fancy => {
   1806                 const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;
   1807                 const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
   1808                 return extra.data.bits.is_inferred_error;
   1809             },
   1810             else => unreachable,
   1811         }
   1812     }
   1813 };
   1814 
   1815 pub const Var = struct {
   1816     /// if is_extern == true this is undefined
   1817     init: Value,
   1818     owner_decl: Decl.Index,
   1819 
   1820     /// Library name if specified.
   1821     /// For example `extern "c" var stderrp = ...` would have 'c' as library name.
   1822     /// Allocated with Module's allocator; outlives the ZIR code.
   1823     lib_name: ?[*:0]const u8,
   1824 
   1825     is_extern: bool,
   1826     is_mutable: bool,
   1827     is_threadlocal: bool,
   1828     is_weak_linkage: bool,
   1829 
   1830     pub fn deinit(variable: *Var, gpa: Allocator) void {
   1831         if (variable.lib_name) |lib_name| {
   1832             gpa.free(mem.sliceTo(lib_name, 0));
   1833         }
   1834     }
   1835 };
   1836 
   1837 pub const DeclAdapter = struct {
   1838     mod: *Module,
   1839 
   1840     pub fn hash(self: @This(), s: []const u8) u32 {
   1841         _ = self;
   1842         return @truncate(u32, std.hash.Wyhash.hash(0, s));
   1843     }
   1844 
   1845     pub fn eql(self: @This(), a: []const u8, b_decl_index: Decl.Index, b_index: usize) bool {
   1846         _ = b_index;
   1847         const b_decl = self.mod.declPtr(b_decl_index);
   1848         return mem.eql(u8, a, mem.sliceTo(b_decl.name, 0));
   1849     }
   1850 };
   1851 
   1852 /// The container that structs, enums, unions, and opaques have.
   1853 pub const Namespace = struct {
   1854     parent: ?*Namespace,
   1855     file_scope: *File,
   1856     /// Will be a struct, enum, union, or opaque.
   1857     ty: Type,
   1858     /// Direct children of the namespace. Used during an update to detect
   1859     /// which decls have been added/removed from source.
   1860     /// Declaration order is preserved via entry order.
   1861     /// Key memory is owned by `decl.name`.
   1862     /// Anonymous decls are not stored here; they are kept in `anon_decls` instead.
   1863     decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{},
   1864 
   1865     anon_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
   1866 
   1867     /// Key is usingnamespace Decl itself. To find the namespace being included,
   1868     /// the Decl Value has to be resolved as a Type which has a Namespace.
   1869     /// Value is whether the usingnamespace decl is marked `pub`.
   1870     usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{},
   1871 
   1872     const DeclContext = struct {
   1873         module: *Module,
   1874 
   1875         pub fn hash(ctx: @This(), decl_index: Decl.Index) u32 {
   1876             const decl = ctx.module.declPtr(decl_index);
   1877             return @truncate(u32, std.hash.Wyhash.hash(0, mem.sliceTo(decl.name, 0)));
   1878         }
   1879 
   1880         pub fn eql(ctx: @This(), a_decl_index: Decl.Index, b_decl_index: Decl.Index, b_index: usize) bool {
   1881             _ = b_index;
   1882             const a_decl = ctx.module.declPtr(a_decl_index);
   1883             const b_decl = ctx.module.declPtr(b_decl_index);
   1884             const a_name = mem.sliceTo(a_decl.name, 0);
   1885             const b_name = mem.sliceTo(b_decl.name, 0);
   1886             return mem.eql(u8, a_name, b_name);
   1887         }
   1888     };
   1889 
   1890     pub fn deinit(ns: *Namespace, mod: *Module) void {
   1891         ns.destroyDecls(mod);
   1892         ns.* = undefined;
   1893     }
   1894 
   1895     pub fn destroyDecls(ns: *Namespace, mod: *Module) void {
   1896         const gpa = mod.gpa;
   1897 
   1898         log.debug("destroyDecls {*}", .{ns});
   1899 
   1900         var decls = ns.decls;
   1901         ns.decls = .{};
   1902 
   1903         var anon_decls = ns.anon_decls;
   1904         ns.anon_decls = .{};
   1905 
   1906         for (decls.keys()) |decl_index| {
   1907             mod.destroyDecl(decl_index);
   1908         }
   1909         decls.deinit(gpa);
   1910 
   1911         for (anon_decls.keys()) |key| {
   1912             mod.destroyDecl(key);
   1913         }
   1914         anon_decls.deinit(gpa);
   1915         ns.usingnamespace_set.deinit(gpa);
   1916     }
   1917 
   1918     pub fn deleteAllDecls(
   1919         ns: *Namespace,
   1920         mod: *Module,
   1921         outdated_decls: ?*std.AutoArrayHashMap(Decl.Index, void),
   1922     ) !void {
   1923         const gpa = mod.gpa;
   1924 
   1925         log.debug("deleteAllDecls {*}", .{ns});
   1926 
   1927         var decls = ns.decls;
   1928         ns.decls = .{};
   1929 
   1930         var anon_decls = ns.anon_decls;
   1931         ns.anon_decls = .{};
   1932 
   1933         // TODO rework this code to not panic on OOM.
   1934         // (might want to coordinate with the clearDecl function)
   1935 
   1936         for (decls.keys()) |child_decl| {
   1937             mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory");
   1938             mod.destroyDecl(child_decl);
   1939         }
   1940         decls.deinit(gpa);
   1941 
   1942         for (anon_decls.keys()) |child_decl| {
   1943             mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory");
   1944             mod.destroyDecl(child_decl);
   1945         }
   1946         anon_decls.deinit(gpa);
   1947 
   1948         ns.usingnamespace_set.deinit(gpa);
   1949     }
   1950 
   1951     // This renders e.g. "std.fs.Dir.OpenOptions"
   1952     pub fn renderFullyQualifiedName(
   1953         ns: Namespace,
   1954         mod: *Module,
   1955         name: []const u8,
   1956         writer: anytype,
   1957     ) @TypeOf(writer).Error!void {
   1958         if (ns.parent) |parent| {
   1959             const decl_index = ns.getDeclIndex();
   1960             const decl = mod.declPtr(decl_index);
   1961             try parent.renderFullyQualifiedName(mod, mem.sliceTo(decl.name, 0), writer);
   1962         } else {
   1963             try ns.file_scope.renderFullyQualifiedName(writer);
   1964         }
   1965         if (name.len != 0) {
   1966             try writer.writeAll(".");
   1967             try writer.writeAll(name);
   1968         }
   1969     }
   1970 
   1971     /// This renders e.g. "std/fs.zig:Dir.OpenOptions"
   1972     pub fn renderFullyQualifiedDebugName(
   1973         ns: Namespace,
   1974         mod: *Module,
   1975         name: []const u8,
   1976         writer: anytype,
   1977     ) @TypeOf(writer).Error!void {
   1978         var separator_char: u8 = '.';
   1979         if (ns.parent) |parent| {
   1980             const decl_index = ns.getDeclIndex();
   1981             const decl = mod.declPtr(decl_index);
   1982             try parent.renderFullyQualifiedDebugName(mod, mem.sliceTo(decl.name, 0), writer);
   1983         } else {
   1984             try ns.file_scope.renderFullyQualifiedDebugName(writer);
   1985             separator_char = ':';
   1986         }
   1987         if (name.len != 0) {
   1988             try writer.writeByte(separator_char);
   1989             try writer.writeAll(name);
   1990         }
   1991     }
   1992 
   1993     pub fn getDeclIndex(ns: Namespace) Decl.Index {
   1994         return ns.ty.getOwnerDecl();
   1995     }
   1996 };
   1997 
   1998 pub const File = struct {
   1999     /// The Decl of the struct that represents this File.
   2000     root_decl: Decl.OptionalIndex,
   2001     status: enum {
   2002         never_loaded,
   2003         retryable_failure,
   2004         parse_failure,
   2005         astgen_failure,
   2006         success_zir,
   2007     },
   2008     source_loaded: bool,
   2009     tree_loaded: bool,
   2010     zir_loaded: bool,
   2011     /// Relative to the owning package's root_src_dir.
   2012     /// Memory is stored in gpa, owned by File.
   2013     sub_file_path: []const u8,
   2014     /// Whether this is populated depends on `source_loaded`.
   2015     source: [:0]const u8,
   2016     /// Whether this is populated depends on `status`.
   2017     stat: Cache.File.Stat,
   2018     /// Whether this is populated or not depends on `tree_loaded`.
   2019     tree: Ast,
   2020     /// Whether this is populated or not depends on `zir_loaded`.
   2021     zir: Zir,
   2022     /// Package that this file is a part of, managed externally.
   2023     pkg: *Package,
   2024     /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen.
   2025     multi_pkg: bool = false,
   2026     /// List of references to this file, used for multi-package errors.
   2027     references: std.ArrayListUnmanaged(Reference) = .{},
   2028 
   2029     /// Used by change detection algorithm, after astgen, contains the
   2030     /// set of decls that existed in the previous ZIR but not in the new one.
   2031     deleted_decls: ArrayListUnmanaged(Decl.Index) = .{},
   2032     /// Used by change detection algorithm, after astgen, contains the
   2033     /// set of decls that existed both in the previous ZIR and in the new one,
   2034     /// but their source code has been modified.
   2035     outdated_decls: ArrayListUnmanaged(Decl.Index) = .{},
   2036 
   2037     /// The most recent successful ZIR for this file, with no errors.
   2038     /// This is only populated when a previously successful ZIR
   2039     /// newly introduces compile errors during an update. When ZIR is
   2040     /// successful, this field is unloaded.
   2041     prev_zir: ?*Zir = null,
   2042 
   2043     /// A single reference to a file.
   2044     pub const Reference = union(enum) {
   2045         /// The file is imported directly (i.e. not as a package) with @import.
   2046         import: SrcLoc,
   2047         /// The file is the root of a package.
   2048         root: *Package,
   2049     };
   2050 
   2051     pub fn unload(file: *File, gpa: Allocator) void {
   2052         file.unloadTree(gpa);
   2053         file.unloadSource(gpa);
   2054         file.unloadZir(gpa);
   2055     }
   2056 
   2057     pub fn unloadTree(file: *File, gpa: Allocator) void {
   2058         if (file.tree_loaded) {
   2059             file.tree_loaded = false;
   2060             file.tree.deinit(gpa);
   2061         }
   2062     }
   2063 
   2064     pub fn unloadSource(file: *File, gpa: Allocator) void {
   2065         if (file.source_loaded) {
   2066             file.source_loaded = false;
   2067             gpa.free(file.source);
   2068         }
   2069     }
   2070 
   2071     pub fn unloadZir(file: *File, gpa: Allocator) void {
   2072         if (file.zir_loaded) {
   2073             file.zir_loaded = false;
   2074             file.zir.deinit(gpa);
   2075         }
   2076     }
   2077 
   2078     pub fn deinit(file: *File, mod: *Module) void {
   2079         const gpa = mod.gpa;
   2080         log.debug("deinit File {s}", .{file.sub_file_path});
   2081         file.deleted_decls.deinit(gpa);
   2082         file.outdated_decls.deinit(gpa);
   2083         file.references.deinit(gpa);
   2084         if (file.root_decl.unwrap()) |root_decl| {
   2085             mod.destroyDecl(root_decl);
   2086         }
   2087         gpa.free(file.sub_file_path);
   2088         file.unload(gpa);
   2089         if (file.prev_zir) |prev_zir| {
   2090             prev_zir.deinit(gpa);
   2091             gpa.destroy(prev_zir);
   2092         }
   2093         file.* = undefined;
   2094     }
   2095 
   2096     pub const Source = struct {
   2097         bytes: [:0]const u8,
   2098         stat: Cache.File.Stat,
   2099     };
   2100 
   2101     pub fn getSource(file: *File, gpa: Allocator) !Source {
   2102         if (file.source_loaded) return Source{
   2103             .bytes = file.source,
   2104             .stat = file.stat,
   2105         };
   2106 
   2107         const root_dir_path = file.pkg.root_src_directory.path orelse ".";
   2108         log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{
   2109             root_dir_path, file.sub_file_path,
   2110         });
   2111 
   2112         // Keep track of inode, file size, mtime, hash so we can detect which files
   2113         // have been modified when an incremental update is requested.
   2114         var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{});
   2115         defer f.close();
   2116 
   2117         const stat = try f.stat();
   2118 
   2119         if (stat.size > std.math.maxInt(u32))
   2120             return error.FileTooBig;
   2121 
   2122         const source = try gpa.allocSentinel(u8, @intCast(usize, stat.size), 0);
   2123         defer if (!file.source_loaded) gpa.free(source);
   2124         const amt = try f.readAll(source);
   2125         if (amt != stat.size)
   2126             return error.UnexpectedEndOfFile;
   2127 
   2128         // Here we do not modify stat fields because this function is the one
   2129         // used for error reporting. We need to keep the stat fields stale so that
   2130         // astGenFile can know to regenerate ZIR.
   2131 
   2132         file.source = source;
   2133         file.source_loaded = true;
   2134         return Source{
   2135             .bytes = source,
   2136             .stat = .{
   2137                 .size = stat.size,
   2138                 .inode = stat.inode,
   2139                 .mtime = stat.mtime,
   2140             },
   2141         };
   2142     }
   2143 
   2144     pub fn getTree(file: *File, gpa: Allocator) !*const Ast {
   2145         if (file.tree_loaded) return &file.tree;
   2146 
   2147         const source = try file.getSource(gpa);
   2148         file.tree = try Ast.parse(gpa, source.bytes, .zig);
   2149         file.tree_loaded = true;
   2150         return &file.tree;
   2151     }
   2152 
   2153     pub fn destroy(file: *File, mod: *Module) void {
   2154         const gpa = mod.gpa;
   2155         file.deinit(mod);
   2156         gpa.destroy(file);
   2157     }
   2158 
   2159     pub fn renderFullyQualifiedName(file: File, writer: anytype) !void {
   2160         // Convert all the slashes into dots and truncate the extension.
   2161         const ext = std.fs.path.extension(file.sub_file_path);
   2162         const noext = file.sub_file_path[0 .. file.sub_file_path.len - ext.len];
   2163         for (noext) |byte| switch (byte) {
   2164             '/', '\\' => try writer.writeByte('.'),
   2165             else => try writer.writeByte(byte),
   2166         };
   2167     }
   2168 
   2169     pub fn renderFullyQualifiedDebugName(file: File, writer: anytype) !void {
   2170         for (file.sub_file_path) |byte| switch (byte) {
   2171             '/', '\\' => try writer.writeByte('/'),
   2172             else => try writer.writeByte(byte),
   2173         };
   2174     }
   2175 
   2176     pub fn fullyQualifiedNameZ(file: File, gpa: Allocator) ![:0]u8 {
   2177         var buf = std.ArrayList(u8).init(gpa);
   2178         defer buf.deinit();
   2179         try file.renderFullyQualifiedName(buf.writer());
   2180         return buf.toOwnedSliceSentinel(0);
   2181     }
   2182 
   2183     /// Returns the full path to this file relative to its package.
   2184     pub fn fullPath(file: File, ally: Allocator) ![]u8 {
   2185         return file.pkg.root_src_directory.join(ally, &[_][]const u8{file.sub_file_path});
   2186     }
   2187 
   2188     /// Returns the full path to this file relative to its package.
   2189     pub fn fullPathZ(file: File, ally: Allocator) ![:0]u8 {
   2190         return file.pkg.root_src_directory.joinZ(ally, &[_][]const u8{file.sub_file_path});
   2191     }
   2192 
   2193     pub fn dumpSrc(file: *File, src: LazySrcLoc) void {
   2194         const loc = std.zig.findLineColumn(file.source.bytes, src);
   2195         std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 });
   2196     }
   2197 
   2198     pub fn okToReportErrors(file: File) bool {
   2199         return switch (file.status) {
   2200             .parse_failure, .astgen_failure => false,
   2201             else => true,
   2202         };
   2203     }
   2204 
   2205     /// Add a reference to this file during AstGen.
   2206     pub fn addReference(file: *File, mod: Module, ref: Reference) !void {
   2207         // Don't add the same module root twice. Note that since we always add module roots at the
   2208         // front of the references array (see below), this loop is actually O(1) on valid code.
   2209         if (ref == .root) {
   2210             for (file.references.items) |other| {
   2211                 switch (other) {
   2212                     .root => |r| if (ref.root == r) return,
   2213                     else => break, // reached the end of the "is-root" references
   2214                 }
   2215             }
   2216         }
   2217 
   2218         switch (ref) {
   2219             // We put root references at the front of the list both to make the above loop fast and
   2220             // to make multi-module errors more helpful (since "root-of" notes are generally more
   2221             // informative than "imported-from" notes). This path is hit very rarely, so the speed
   2222             // of the insert operation doesn't matter too much.
   2223             .root => try file.references.insert(mod.gpa, 0, ref),
   2224 
   2225             // Other references we'll just put at the end.
   2226             else => try file.references.append(mod.gpa, ref),
   2227         }
   2228 
   2229         const pkg = switch (ref) {
   2230             .import => |loc| loc.file_scope.pkg,
   2231             .root => |pkg| pkg,
   2232         };
   2233         if (pkg != file.pkg) file.multi_pkg = true;
   2234     }
   2235 
   2236     /// Mark this file and every file referenced by it as multi_pkg and report an
   2237     /// astgen_failure error for them. AstGen must have completed in its entirety.
   2238     pub fn recursiveMarkMultiPkg(file: *File, mod: *Module) void {
   2239         file.multi_pkg = true;
   2240         file.status = .astgen_failure;
   2241 
   2242         // We can only mark children as failed if the ZIR is loaded, which may not
   2243         // be the case if there were other astgen failures in this file
   2244         if (!file.zir_loaded) return;
   2245 
   2246         const imports_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.imports)];
   2247         if (imports_index == 0) return;
   2248         const extra = file.zir.extraData(Zir.Inst.Imports, imports_index);
   2249 
   2250         var import_i: u32 = 0;
   2251         var extra_index = extra.end;
   2252         while (import_i < extra.data.imports_len) : (import_i += 1) {
   2253             const item = file.zir.extraData(Zir.Inst.Imports.Item, extra_index);
   2254             extra_index = item.end;
   2255 
   2256             const import_path = file.zir.nullTerminatedString(item.data.name);
   2257             if (mem.eql(u8, import_path, "builtin")) continue;
   2258 
   2259             const res = mod.importFile(file, import_path) catch continue;
   2260             if (!res.is_pkg and !res.file.multi_pkg) {
   2261                 res.file.recursiveMarkMultiPkg(mod);
   2262             }
   2263         }
   2264     }
   2265 };
   2266 
   2267 /// Represents the contents of a file loaded with `@embedFile`.
   2268 pub const EmbedFile = struct {
   2269     /// Relative to the owning package's root_src_dir.
   2270     /// Memory is stored in gpa, owned by EmbedFile.
   2271     sub_file_path: []const u8,
   2272     bytes: [:0]const u8,
   2273     stat: Cache.File.Stat,
   2274     /// Package that this file is a part of, managed externally.
   2275     pkg: *Package,
   2276     /// The Decl that was created from the `@embedFile` to own this resource.
   2277     /// This is how zig knows what other Decl objects to invalidate if the file
   2278     /// changes on disk.
   2279     owner_decl: Decl.Index,
   2280 
   2281     fn destroy(embed_file: *EmbedFile, mod: *Module) void {
   2282         const gpa = mod.gpa;
   2283         gpa.free(embed_file.sub_file_path);
   2284         gpa.free(embed_file.bytes);
   2285         gpa.destroy(embed_file);
   2286     }
   2287 };
   2288 
   2289 /// This struct holds data necessary to construct API-facing `AllErrors.Message`.
   2290 /// Its memory is managed with the general purpose allocator so that they
   2291 /// can be created and destroyed in response to incremental updates.
   2292 /// In some cases, the File could have been inferred from where the ErrorMsg
   2293 /// is stored. For example, if it is stored in Module.failed_decls, then the File
   2294 /// would be determined by the Decl Scope. However, the data structure contains the field
   2295 /// anyway so that `ErrorMsg` can be reused for error notes, which may be in a different
   2296 /// file than the parent error message. It also simplifies processing of error messages.
   2297 pub const ErrorMsg = struct {
   2298     src_loc: SrcLoc,
   2299     msg: []const u8,
   2300     notes: []ErrorMsg = &.{},
   2301     reference_trace: []Trace = &.{},
   2302 
   2303     pub const Trace = struct {
   2304         decl: ?[*:0]const u8,
   2305         src_loc: SrcLoc,
   2306         hidden: u32 = 0,
   2307     };
   2308 
   2309     pub fn create(
   2310         gpa: Allocator,
   2311         src_loc: SrcLoc,
   2312         comptime format: []const u8,
   2313         args: anytype,
   2314     ) !*ErrorMsg {
   2315         const err_msg = try gpa.create(ErrorMsg);
   2316         errdefer gpa.destroy(err_msg);
   2317         err_msg.* = try ErrorMsg.init(gpa, src_loc, format, args);
   2318         return err_msg;
   2319     }
   2320 
   2321     /// Assumes the ErrorMsg struct and msg were both allocated with `gpa`,
   2322     /// as well as all notes.
   2323     pub fn destroy(err_msg: *ErrorMsg, gpa: Allocator) void {
   2324         err_msg.deinit(gpa);
   2325         gpa.destroy(err_msg);
   2326     }
   2327 
   2328     pub fn init(
   2329         gpa: Allocator,
   2330         src_loc: SrcLoc,
   2331         comptime format: []const u8,
   2332         args: anytype,
   2333     ) !ErrorMsg {
   2334         return ErrorMsg{
   2335             .src_loc = src_loc,
   2336             .msg = try std.fmt.allocPrint(gpa, format, args),
   2337         };
   2338     }
   2339 
   2340     pub fn deinit(err_msg: *ErrorMsg, gpa: Allocator) void {
   2341         for (err_msg.notes) |*note| {
   2342             note.deinit(gpa);
   2343         }
   2344         gpa.free(err_msg.notes);
   2345         gpa.free(err_msg.msg);
   2346         gpa.free(err_msg.reference_trace);
   2347         err_msg.* = undefined;
   2348     }
   2349 
   2350     pub fn clearTrace(err_msg: *ErrorMsg, gpa: Allocator) void {
   2351         if (err_msg.reference_trace.len == 0) return;
   2352         gpa.free(err_msg.reference_trace);
   2353         err_msg.reference_trace = &.{};
   2354     }
   2355 };
   2356 
   2357 /// Canonical reference to a position within a source file.
   2358 pub const SrcLoc = struct {
   2359     file_scope: *File,
   2360     /// Might be 0 depending on tag of `lazy`.
   2361     parent_decl_node: Ast.Node.Index,
   2362     /// Relative to `parent_decl_node`.
   2363     lazy: LazySrcLoc,
   2364 
   2365     pub fn declSrcToken(src_loc: SrcLoc) Ast.TokenIndex {
   2366         const tree = src_loc.file_scope.tree;
   2367         return tree.firstToken(src_loc.parent_decl_node);
   2368     }
   2369 
   2370     pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.TokenIndex {
   2371         return @bitCast(Ast.Node.Index, offset + @bitCast(i32, src_loc.parent_decl_node));
   2372     }
   2373 
   2374     pub const Span = struct {
   2375         start: u32,
   2376         end: u32,
   2377         main: u32,
   2378     };
   2379 
   2380     pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {
   2381         switch (src_loc.lazy) {
   2382             .unneeded => unreachable,
   2383             .entire_file => return Span{ .start = 0, .end = 1, .main = 0 },
   2384 
   2385             .byte_abs => |byte_index| return Span{ .start = byte_index, .end = byte_index + 1, .main = byte_index },
   2386 
   2387             .token_abs => |tok_index| {
   2388                 const tree = try src_loc.file_scope.getTree(gpa);
   2389                 const start = tree.tokens.items(.start)[tok_index];
   2390                 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
   2391                 return Span{ .start = start, .end = end, .main = start };
   2392             },
   2393             .node_abs => |node| {
   2394                 const tree = try src_loc.file_scope.getTree(gpa);
   2395                 return nodeToSpan(tree, node);
   2396             },
   2397             .byte_offset => |byte_off| {
   2398                 const tree = try src_loc.file_scope.getTree(gpa);
   2399                 const tok_index = src_loc.declSrcToken();
   2400                 const start = tree.tokens.items(.start)[tok_index] + byte_off;
   2401                 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
   2402                 return Span{ .start = start, .end = end, .main = start };
   2403             },
   2404             .token_offset => |tok_off| {
   2405                 const tree = try src_loc.file_scope.getTree(gpa);
   2406                 const tok_index = src_loc.declSrcToken() + tok_off;
   2407                 const start = tree.tokens.items(.start)[tok_index];
   2408                 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
   2409                 return Span{ .start = start, .end = end, .main = start };
   2410             },
   2411             .node_offset => |traced_off| {
   2412                 const node_off = traced_off.x;
   2413                 const tree = try src_loc.file_scope.getTree(gpa);
   2414                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2415                 assert(src_loc.file_scope.tree_loaded);
   2416                 return nodeToSpan(tree, node);
   2417             },
   2418             .node_offset_main_token => |node_off| {
   2419                 const tree = try src_loc.file_scope.getTree(gpa);
   2420                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2421                 const main_token = tree.nodes.items(.main_token)[node];
   2422                 return tokensToSpan(tree, main_token, main_token, main_token);
   2423             },
   2424             .node_offset_bin_op => |node_off| {
   2425                 const tree = try src_loc.file_scope.getTree(gpa);
   2426                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2427                 assert(src_loc.file_scope.tree_loaded);
   2428                 return nodeToSpan(tree, node);
   2429             },
   2430             .node_offset_initializer => |node_off| {
   2431                 const tree = try src_loc.file_scope.getTree(gpa);
   2432                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2433                 return tokensToSpan(
   2434                     tree,
   2435                     tree.firstToken(node) - 3,
   2436                     tree.lastToken(node),
   2437                     tree.nodes.items(.main_token)[node] - 2,
   2438                 );
   2439             },
   2440             .node_offset_var_decl_ty => |node_off| {
   2441                 const tree = try src_loc.file_scope.getTree(gpa);
   2442                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2443                 const node_tags = tree.nodes.items(.tag);
   2444                 const full = switch (node_tags[node]) {
   2445                     .global_var_decl,
   2446                     .local_var_decl,
   2447                     .simple_var_decl,
   2448                     .aligned_var_decl,
   2449                     => tree.fullVarDecl(node).?,
   2450                     .@"usingnamespace" => {
   2451                         const node_data = tree.nodes.items(.data);
   2452                         return nodeToSpan(tree, node_data[node].lhs);
   2453                     },
   2454                     else => unreachable,
   2455                 };
   2456                 if (full.ast.type_node != 0) {
   2457                     return nodeToSpan(tree, full.ast.type_node);
   2458                 }
   2459                 const tok_index = full.ast.mut_token + 1; // the name token
   2460                 const start = tree.tokens.items(.start)[tok_index];
   2461                 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
   2462                 return Span{ .start = start, .end = end, .main = start };
   2463             },
   2464             .node_offset_var_decl_align => |node_off| {
   2465                 const tree = try src_loc.file_scope.getTree(gpa);
   2466                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2467                 const full = tree.fullVarDecl(node).?;
   2468                 return nodeToSpan(tree, full.ast.align_node);
   2469             },
   2470             .node_offset_var_decl_section => |node_off| {
   2471                 const tree = try src_loc.file_scope.getTree(gpa);
   2472                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2473                 const full = tree.fullVarDecl(node).?;
   2474                 return nodeToSpan(tree, full.ast.section_node);
   2475             },
   2476             .node_offset_var_decl_addrspace => |node_off| {
   2477                 const tree = try src_loc.file_scope.getTree(gpa);
   2478                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2479                 const full = tree.fullVarDecl(node).?;
   2480                 return nodeToSpan(tree, full.ast.addrspace_node);
   2481             },
   2482             .node_offset_var_decl_init => |node_off| {
   2483                 const tree = try src_loc.file_scope.getTree(gpa);
   2484                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2485                 const full = tree.fullVarDecl(node).?;
   2486                 return nodeToSpan(tree, full.ast.init_node);
   2487             },
   2488             .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0),
   2489             .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1),
   2490             .node_offset_builtin_call_arg2 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 2),
   2491             .node_offset_builtin_call_arg3 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 3),
   2492             .node_offset_builtin_call_arg4 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 4),
   2493             .node_offset_builtin_call_arg5 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 5),
   2494             .node_offset_array_access_index => |node_off| {
   2495                 const tree = try src_loc.file_scope.getTree(gpa);
   2496                 const node_datas = tree.nodes.items(.data);
   2497                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2498                 return nodeToSpan(tree, node_datas[node].rhs);
   2499             },
   2500             .node_offset_slice_ptr,
   2501             .node_offset_slice_start,
   2502             .node_offset_slice_end,
   2503             .node_offset_slice_sentinel,
   2504             => |node_off| {
   2505                 const tree = try src_loc.file_scope.getTree(gpa);
   2506                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2507                 const full = tree.fullSlice(node).?;
   2508                 const part_node = switch (src_loc.lazy) {
   2509                     .node_offset_slice_ptr => full.ast.sliced,
   2510                     .node_offset_slice_start => full.ast.start,
   2511                     .node_offset_slice_end => full.ast.end,
   2512                     .node_offset_slice_sentinel => full.ast.sentinel,
   2513                     else => unreachable,
   2514                 };
   2515                 return nodeToSpan(tree, part_node);
   2516             },
   2517             .node_offset_call_func => |node_off| {
   2518                 const tree = try src_loc.file_scope.getTree(gpa);
   2519                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2520                 var buf: [1]Ast.Node.Index = undefined;
   2521                 const full = tree.fullCall(&buf, node).?;
   2522                 return nodeToSpan(tree, full.ast.fn_expr);
   2523             },
   2524             .node_offset_field_name => |node_off| {
   2525                 const tree = try src_loc.file_scope.getTree(gpa);
   2526                 const node_datas = tree.nodes.items(.data);
   2527                 const node_tags = tree.nodes.items(.tag);
   2528                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2529                 var buf: [1]Ast.Node.Index = undefined;
   2530                 const tok_index = switch (node_tags[node]) {
   2531                     .field_access => node_datas[node].rhs,
   2532                     .call_one,
   2533                     .call_one_comma,
   2534                     .async_call_one,
   2535                     .async_call_one_comma,
   2536                     .call,
   2537                     .call_comma,
   2538                     .async_call,
   2539                     .async_call_comma,
   2540                     => blk: {
   2541                         const full = tree.fullCall(&buf, node).?;
   2542                         break :blk tree.lastToken(full.ast.fn_expr);
   2543                     },
   2544                     else => tree.firstToken(node) - 2,
   2545                 };
   2546                 const start = tree.tokens.items(.start)[tok_index];
   2547                 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
   2548                 return Span{ .start = start, .end = end, .main = start };
   2549             },
   2550             .node_offset_deref_ptr => |node_off| {
   2551                 const tree = try src_loc.file_scope.getTree(gpa);
   2552                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2553                 return nodeToSpan(tree, node);
   2554             },
   2555             .node_offset_asm_source => |node_off| {
   2556                 const tree = try src_loc.file_scope.getTree(gpa);
   2557                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2558                 const full = tree.fullAsm(node).?;
   2559                 return nodeToSpan(tree, full.ast.template);
   2560             },
   2561             .node_offset_asm_ret_ty => |node_off| {
   2562                 const tree = try src_loc.file_scope.getTree(gpa);
   2563                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2564                 const full = tree.fullAsm(node).?;
   2565                 const asm_output = full.outputs[0];
   2566                 const node_datas = tree.nodes.items(.data);
   2567                 return nodeToSpan(tree, node_datas[asm_output].lhs);
   2568             },
   2569 
   2570             .node_offset_if_cond => |node_off| {
   2571                 const tree = try src_loc.file_scope.getTree(gpa);
   2572                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2573                 const node_tags = tree.nodes.items(.tag);
   2574                 const src_node = switch (node_tags[node]) {
   2575                     .if_simple,
   2576                     .@"if",
   2577                     => tree.fullIf(node).?.ast.cond_expr,
   2578 
   2579                     .while_simple,
   2580                     .while_cont,
   2581                     .@"while",
   2582                     => tree.fullWhile(node).?.ast.cond_expr,
   2583 
   2584                     .for_simple,
   2585                     .@"for",
   2586                     => {
   2587                         const inputs = tree.fullFor(node).?.ast.inputs;
   2588                         const start = tree.firstToken(inputs[0]);
   2589                         const end = tree.lastToken(inputs[inputs.len - 1]);
   2590                         return tokensToSpan(tree, start, end, start);
   2591                     },
   2592 
   2593                     .@"orelse" => node,
   2594                     .@"catch" => node,
   2595                     else => unreachable,
   2596                 };
   2597                 return nodeToSpan(tree, src_node);
   2598             },
   2599             .for_input => |for_input| {
   2600                 const tree = try src_loc.file_scope.getTree(gpa);
   2601                 const node = src_loc.declRelativeToNodeIndex(for_input.for_node_offset);
   2602                 const for_full = tree.fullFor(node).?;
   2603                 const src_node = for_full.ast.inputs[for_input.input_index];
   2604                 return nodeToSpan(tree, src_node);
   2605             },
   2606             .for_capture_from_input => |node_off| {
   2607                 const tree = try src_loc.file_scope.getTree(gpa);
   2608                 const token_tags = tree.tokens.items(.tag);
   2609                 const input_node = src_loc.declRelativeToNodeIndex(node_off);
   2610                 // We have to actually linear scan the whole AST to find the for loop
   2611                 // that contains this input.
   2612                 const node_tags = tree.nodes.items(.tag);
   2613                 for (node_tags, 0..) |node_tag, node_usize| {
   2614                     const node = @intCast(Ast.Node.Index, node_usize);
   2615                     switch (node_tag) {
   2616                         .for_simple, .@"for" => {
   2617                             const for_full = tree.fullFor(node).?;
   2618                             for (for_full.ast.inputs, 0..) |input, input_index| {
   2619                                 if (input_node == input) {
   2620                                     var count = input_index;
   2621                                     var tok = for_full.payload_token;
   2622                                     while (true) {
   2623                                         switch (token_tags[tok]) {
   2624                                             .comma => {
   2625                                                 count -= 1;
   2626                                                 tok += 1;
   2627                                             },
   2628                                             .identifier => {
   2629                                                 if (count == 0)
   2630                                                     return tokensToSpan(tree, tok, tok + 1, tok);
   2631                                                 tok += 1;
   2632                                             },
   2633                                             .asterisk => {
   2634                                                 if (count == 0)
   2635                                                     return tokensToSpan(tree, tok, tok + 2, tok);
   2636                                                 tok += 1;
   2637                                             },
   2638                                             else => unreachable,
   2639                                         }
   2640                                     }
   2641                                 }
   2642                             }
   2643                         },
   2644                         else => continue,
   2645                     }
   2646                 } else unreachable;
   2647             },
   2648             .node_offset_bin_lhs => |node_off| {
   2649                 const tree = try src_loc.file_scope.getTree(gpa);
   2650                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2651                 const node_datas = tree.nodes.items(.data);
   2652                 return nodeToSpan(tree, node_datas[node].lhs);
   2653             },
   2654             .node_offset_bin_rhs => |node_off| {
   2655                 const tree = try src_loc.file_scope.getTree(gpa);
   2656                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2657                 const node_datas = tree.nodes.items(.data);
   2658                 return nodeToSpan(tree, node_datas[node].rhs);
   2659             },
   2660 
   2661             .node_offset_switch_operand => |node_off| {
   2662                 const tree = try src_loc.file_scope.getTree(gpa);
   2663                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2664                 const node_datas = tree.nodes.items(.data);
   2665                 return nodeToSpan(tree, node_datas[node].lhs);
   2666             },
   2667 
   2668             .node_offset_switch_special_prong => |node_off| {
   2669                 const tree = try src_loc.file_scope.getTree(gpa);
   2670                 const switch_node = src_loc.declRelativeToNodeIndex(node_off);
   2671                 const node_datas = tree.nodes.items(.data);
   2672                 const node_tags = tree.nodes.items(.tag);
   2673                 const main_tokens = tree.nodes.items(.main_token);
   2674                 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
   2675                 const case_nodes = tree.extra_data[extra.start..extra.end];
   2676                 for (case_nodes) |case_node| {
   2677                     const case = tree.fullSwitchCase(case_node).?;
   2678                     const is_special = (case.ast.values.len == 0) or
   2679                         (case.ast.values.len == 1 and
   2680                         node_tags[case.ast.values[0]] == .identifier and
   2681                         mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));
   2682                     if (!is_special) continue;
   2683 
   2684                     return nodeToSpan(tree, case_node);
   2685                 } else unreachable;
   2686             },
   2687 
   2688             .node_offset_switch_range => |node_off| {
   2689                 const tree = try src_loc.file_scope.getTree(gpa);
   2690                 const switch_node = src_loc.declRelativeToNodeIndex(node_off);
   2691                 const node_datas = tree.nodes.items(.data);
   2692                 const node_tags = tree.nodes.items(.tag);
   2693                 const main_tokens = tree.nodes.items(.main_token);
   2694                 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
   2695                 const case_nodes = tree.extra_data[extra.start..extra.end];
   2696                 for (case_nodes) |case_node| {
   2697                     const case = tree.fullSwitchCase(case_node).?;
   2698                     const is_special = (case.ast.values.len == 0) or
   2699                         (case.ast.values.len == 1 and
   2700                         node_tags[case.ast.values[0]] == .identifier and
   2701                         mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));
   2702                     if (is_special) continue;
   2703 
   2704                     for (case.ast.values) |item_node| {
   2705                         if (node_tags[item_node] == .switch_range) {
   2706                             return nodeToSpan(tree, item_node);
   2707                         }
   2708                     }
   2709                 } else unreachable;
   2710             },
   2711             .node_offset_switch_prong_capture => |node_off| {
   2712                 const tree = try src_loc.file_scope.getTree(gpa);
   2713                 const case_node = src_loc.declRelativeToNodeIndex(node_off);
   2714                 const case = tree.fullSwitchCase(case_node).?;
   2715                 const start_tok = case.payload_token.?;
   2716                 const token_tags = tree.tokens.items(.tag);
   2717                 const end_tok = switch (token_tags[start_tok]) {
   2718                     .asterisk => start_tok + 1,
   2719                     else => start_tok,
   2720                 };
   2721                 const start = tree.tokens.items(.start)[start_tok];
   2722                 const end_start = tree.tokens.items(.start)[end_tok];
   2723                 const end = end_start + @intCast(u32, tree.tokenSlice(end_tok).len);
   2724                 return Span{ .start = start, .end = end, .main = start };
   2725             },
   2726             .node_offset_fn_type_align => |node_off| {
   2727                 const tree = try src_loc.file_scope.getTree(gpa);
   2728                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2729                 var buf: [1]Ast.Node.Index = undefined;
   2730                 const full = tree.fullFnProto(&buf, node).?;
   2731                 return nodeToSpan(tree, full.ast.align_expr);
   2732             },
   2733             .node_offset_fn_type_addrspace => |node_off| {
   2734                 const tree = try src_loc.file_scope.getTree(gpa);
   2735                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2736                 var buf: [1]Ast.Node.Index = undefined;
   2737                 const full = tree.fullFnProto(&buf, node).?;
   2738                 return nodeToSpan(tree, full.ast.addrspace_expr);
   2739             },
   2740             .node_offset_fn_type_section => |node_off| {
   2741                 const tree = try src_loc.file_scope.getTree(gpa);
   2742                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2743                 var buf: [1]Ast.Node.Index = undefined;
   2744                 const full = tree.fullFnProto(&buf, node).?;
   2745                 return nodeToSpan(tree, full.ast.section_expr);
   2746             },
   2747             .node_offset_fn_type_cc => |node_off| {
   2748                 const tree = try src_loc.file_scope.getTree(gpa);
   2749                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2750                 var buf: [1]Ast.Node.Index = undefined;
   2751                 const full = tree.fullFnProto(&buf, node).?;
   2752                 return nodeToSpan(tree, full.ast.callconv_expr);
   2753             },
   2754 
   2755             .node_offset_fn_type_ret_ty => |node_off| {
   2756                 const tree = try src_loc.file_scope.getTree(gpa);
   2757                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2758                 var buf: [1]Ast.Node.Index = undefined;
   2759                 const full = tree.fullFnProto(&buf, node).?;
   2760                 return nodeToSpan(tree, full.ast.return_type);
   2761             },
   2762             .node_offset_param => |node_off| {
   2763                 const tree = try src_loc.file_scope.getTree(gpa);
   2764                 const token_tags = tree.tokens.items(.tag);
   2765                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2766 
   2767                 var first_tok = tree.firstToken(node);
   2768                 while (true) switch (token_tags[first_tok - 1]) {
   2769                     .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
   2770                     else => break,
   2771                 };
   2772                 return tokensToSpan(
   2773                     tree,
   2774                     first_tok,
   2775                     tree.lastToken(node),
   2776                     first_tok,
   2777                 );
   2778             },
   2779             .token_offset_param => |token_off| {
   2780                 const tree = try src_loc.file_scope.getTree(gpa);
   2781                 const token_tags = tree.tokens.items(.tag);
   2782                 const main_token = tree.nodes.items(.main_token)[src_loc.parent_decl_node];
   2783                 const tok_index = @bitCast(Ast.TokenIndex, token_off + @bitCast(i32, main_token));
   2784 
   2785                 var first_tok = tok_index;
   2786                 while (true) switch (token_tags[first_tok - 1]) {
   2787                     .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
   2788                     else => break,
   2789                 };
   2790                 return tokensToSpan(
   2791                     tree,
   2792                     first_tok,
   2793                     tok_index,
   2794                     first_tok,
   2795                 );
   2796             },
   2797 
   2798             .node_offset_anyframe_type => |node_off| {
   2799                 const tree = try src_loc.file_scope.getTree(gpa);
   2800                 const node_datas = tree.nodes.items(.data);
   2801                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2802                 return nodeToSpan(tree, node_datas[parent_node].rhs);
   2803             },
   2804 
   2805             .node_offset_lib_name => |node_off| {
   2806                 const tree = try src_loc.file_scope.getTree(gpa);
   2807                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2808                 var buf: [1]Ast.Node.Index = undefined;
   2809                 const full = tree.fullFnProto(&buf, parent_node).?;
   2810                 const tok_index = full.lib_name.?;
   2811                 const start = tree.tokens.items(.start)[tok_index];
   2812                 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
   2813                 return Span{ .start = start, .end = end, .main = start };
   2814             },
   2815 
   2816             .node_offset_array_type_len => |node_off| {
   2817                 const tree = try src_loc.file_scope.getTree(gpa);
   2818                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2819 
   2820                 const full = tree.fullArrayType(parent_node).?;
   2821                 return nodeToSpan(tree, full.ast.elem_count);
   2822             },
   2823             .node_offset_array_type_sentinel => |node_off| {
   2824                 const tree = try src_loc.file_scope.getTree(gpa);
   2825                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2826 
   2827                 const full = tree.fullArrayType(parent_node).?;
   2828                 return nodeToSpan(tree, full.ast.sentinel);
   2829             },
   2830             .node_offset_array_type_elem => |node_off| {
   2831                 const tree = try src_loc.file_scope.getTree(gpa);
   2832                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2833 
   2834                 const full = tree.fullArrayType(parent_node).?;
   2835                 return nodeToSpan(tree, full.ast.elem_type);
   2836             },
   2837             .node_offset_un_op => |node_off| {
   2838                 const tree = try src_loc.file_scope.getTree(gpa);
   2839                 const node_datas = tree.nodes.items(.data);
   2840                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2841 
   2842                 return nodeToSpan(tree, node_datas[node].lhs);
   2843             },
   2844             .node_offset_ptr_elem => |node_off| {
   2845                 const tree = try src_loc.file_scope.getTree(gpa);
   2846                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2847 
   2848                 const full = tree.fullPtrType(parent_node).?;
   2849                 return nodeToSpan(tree, full.ast.child_type);
   2850             },
   2851             .node_offset_ptr_sentinel => |node_off| {
   2852                 const tree = try src_loc.file_scope.getTree(gpa);
   2853                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2854 
   2855                 const full = tree.fullPtrType(parent_node).?;
   2856                 return nodeToSpan(tree, full.ast.sentinel);
   2857             },
   2858             .node_offset_ptr_align => |node_off| {
   2859                 const tree = try src_loc.file_scope.getTree(gpa);
   2860                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2861 
   2862                 const full = tree.fullPtrType(parent_node).?;
   2863                 return nodeToSpan(tree, full.ast.align_node);
   2864             },
   2865             .node_offset_ptr_addrspace => |node_off| {
   2866                 const tree = try src_loc.file_scope.getTree(gpa);
   2867                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2868 
   2869                 const full = tree.fullPtrType(parent_node).?;
   2870                 return nodeToSpan(tree, full.ast.addrspace_node);
   2871             },
   2872             .node_offset_ptr_bitoffset => |node_off| {
   2873                 const tree = try src_loc.file_scope.getTree(gpa);
   2874                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2875 
   2876                 const full = tree.fullPtrType(parent_node).?;
   2877                 return nodeToSpan(tree, full.ast.bit_range_start);
   2878             },
   2879             .node_offset_ptr_hostsize => |node_off| {
   2880                 const tree = try src_loc.file_scope.getTree(gpa);
   2881                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2882 
   2883                 const full = tree.fullPtrType(parent_node).?;
   2884                 return nodeToSpan(tree, full.ast.bit_range_end);
   2885             },
   2886             .node_offset_container_tag => |node_off| {
   2887                 const tree = try src_loc.file_scope.getTree(gpa);
   2888                 const node_tags = tree.nodes.items(.tag);
   2889                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2890 
   2891                 switch (node_tags[parent_node]) {
   2892                     .container_decl_arg, .container_decl_arg_trailing => {
   2893                         const full = tree.containerDeclArg(parent_node);
   2894                         return nodeToSpan(tree, full.ast.arg);
   2895                     },
   2896                     .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {
   2897                         const full = tree.taggedUnionEnumTag(parent_node);
   2898 
   2899                         return tokensToSpan(
   2900                             tree,
   2901                             tree.firstToken(full.ast.arg) - 2,
   2902                             tree.lastToken(full.ast.arg) + 1,
   2903                             tree.nodes.items(.main_token)[full.ast.arg],
   2904                         );
   2905                     },
   2906                     else => unreachable,
   2907                 }
   2908             },
   2909             .node_offset_field_default => |node_off| {
   2910                 const tree = try src_loc.file_scope.getTree(gpa);
   2911                 const node_tags = tree.nodes.items(.tag);
   2912                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2913 
   2914                 const full: Ast.full.ContainerField = switch (node_tags[parent_node]) {
   2915                     .container_field => tree.containerField(parent_node),
   2916                     .container_field_init => tree.containerFieldInit(parent_node),
   2917                     else => unreachable,
   2918                 };
   2919                 return nodeToSpan(tree, full.ast.value_expr);
   2920             },
   2921             .node_offset_init_ty => |node_off| {
   2922                 const tree = try src_loc.file_scope.getTree(gpa);
   2923                 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
   2924 
   2925                 var buf: [2]Ast.Node.Index = undefined;
   2926                 const full = tree.fullArrayInit(&buf, parent_node).?;
   2927                 return nodeToSpan(tree, full.ast.type_expr);
   2928             },
   2929             .node_offset_store_ptr => |node_off| {
   2930                 const tree = try src_loc.file_scope.getTree(gpa);
   2931                 const node_tags = tree.nodes.items(.tag);
   2932                 const node_datas = tree.nodes.items(.data);
   2933                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2934 
   2935                 switch (node_tags[node]) {
   2936                     .assign => {
   2937                         return nodeToSpan(tree, node_datas[node].lhs);
   2938                     },
   2939                     else => return nodeToSpan(tree, node),
   2940                 }
   2941             },
   2942             .node_offset_store_operand => |node_off| {
   2943                 const tree = try src_loc.file_scope.getTree(gpa);
   2944                 const node_tags = tree.nodes.items(.tag);
   2945                 const node_datas = tree.nodes.items(.data);
   2946                 const node = src_loc.declRelativeToNodeIndex(node_off);
   2947 
   2948                 switch (node_tags[node]) {
   2949                     .assign => {
   2950                         return nodeToSpan(tree, node_datas[node].rhs);
   2951                     },
   2952                     else => return nodeToSpan(tree, node),
   2953                 }
   2954             },
   2955         }
   2956     }
   2957 
   2958     pub fn byteOffsetBuiltinCallArg(
   2959         src_loc: SrcLoc,
   2960         gpa: Allocator,
   2961         node_off: i32,
   2962         arg_index: u32,
   2963     ) !Span {
   2964         const tree = try src_loc.file_scope.getTree(gpa);
   2965         const node_datas = tree.nodes.items(.data);
   2966         const node_tags = tree.nodes.items(.tag);
   2967         const node = src_loc.declRelativeToNodeIndex(node_off);
   2968         const param = switch (node_tags[node]) {
   2969             .builtin_call_two, .builtin_call_two_comma => switch (arg_index) {
   2970                 0 => node_datas[node].lhs,
   2971                 1 => node_datas[node].rhs,
   2972                 else => unreachable,
   2973             },
   2974             .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + arg_index],
   2975             else => unreachable,
   2976         };
   2977         return nodeToSpan(tree, param);
   2978     }
   2979 
   2980     pub fn nodeToSpan(tree: *const Ast, node: u32) Span {
   2981         return tokensToSpan(
   2982             tree,
   2983             tree.firstToken(node),
   2984             tree.lastToken(node),
   2985             tree.nodes.items(.main_token)[node],
   2986         );
   2987     }
   2988 
   2989     fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {
   2990         const token_starts = tree.tokens.items(.start);
   2991         var start_tok = start;
   2992         var end_tok = end;
   2993 
   2994         if (tree.tokensOnSameLine(start, end)) {
   2995             // do nothing
   2996         } else if (tree.tokensOnSameLine(start, main)) {
   2997             end_tok = main;
   2998         } else if (tree.tokensOnSameLine(main, end)) {
   2999             start_tok = main;
   3000         } else {
   3001             start_tok = main;
   3002             end_tok = main;
   3003         }
   3004         const start_off = token_starts[start_tok];
   3005         const end_off = token_starts[end_tok] + @intCast(u32, tree.tokenSlice(end_tok).len);
   3006         return Span{ .start = start_off, .end = end_off, .main = token_starts[main] };
   3007     }
   3008 };
   3009 
   3010 /// This wraps a simple integer in debug builds so that later on we can find out
   3011 /// where in semantic analysis the value got set.
   3012 const TracedOffset = struct {
   3013     x: i32,
   3014     trace: std.debug.Trace = .{},
   3015 
   3016     const want_tracing = build_options.value_tracing;
   3017 };
   3018 
   3019 /// Resolving a source location into a byte offset may require doing work
   3020 /// that we would rather not do unless the error actually occurs.
   3021 /// Therefore we need a data structure that contains the information necessary
   3022 /// to lazily produce a `SrcLoc` as required.
   3023 /// Most of the offsets in this data structure are relative to the containing Decl.
   3024 /// This makes the source location resolve properly even when a Decl gets
   3025 /// shifted up or down in the file, as long as the Decl's contents itself
   3026 /// do not change.
   3027 pub const LazySrcLoc = union(enum) {
   3028     /// When this tag is set, the code that constructed this `LazySrcLoc` is asserting
   3029     /// that all code paths which would need to resolve the source location are
   3030     /// unreachable. If you are debugging this tag incorrectly being this value,
   3031     /// look into using reverse-continue with a memory watchpoint to see where the
   3032     /// value is being set to this tag.
   3033     unneeded,
   3034     /// Means the source location points to an entire file; not any particular
   3035     /// location within the file. `file_scope` union field will be active.
   3036     entire_file,
   3037     /// The source location points to a byte offset within a source file,
   3038     /// offset from 0. The source file is determined contextually.
   3039     /// Inside a `SrcLoc`, the `file_scope` union field will be active.
   3040     byte_abs: u32,
   3041     /// The source location points to a token within a source file,
   3042     /// offset from 0. The source file is determined contextually.
   3043     /// Inside a `SrcLoc`, the `file_scope` union field will be active.
   3044     token_abs: u32,
   3045     /// The source location points to an AST node within a source file,
   3046     /// offset from 0. The source file is determined contextually.
   3047     /// Inside a `SrcLoc`, the `file_scope` union field will be active.
   3048     node_abs: u32,
   3049     /// The source location points to a byte offset within a source file,
   3050     /// offset from the byte offset of the Decl within the file.
   3051     /// The Decl is determined contextually.
   3052     byte_offset: u32,
   3053     /// This data is the offset into the token list from the Decl token.
   3054     /// The Decl is determined contextually.
   3055     token_offset: u32,
   3056     /// The source location points to an AST node, which is this value offset
   3057     /// from its containing Decl node AST index.
   3058     /// The Decl is determined contextually.
   3059     node_offset: TracedOffset,
   3060     /// The source location points to the main token of an AST node, found
   3061     /// by taking this AST node index offset from the containing Decl AST node.
   3062     /// The Decl is determined contextually.
   3063     node_offset_main_token: i32,
   3064     /// The source location points to the beginning of a struct initializer.
   3065     /// The Decl is determined contextually.
   3066     node_offset_initializer: i32,
   3067     /// The source location points to a variable declaration type expression,
   3068     /// found by taking this AST node index offset from the containing
   3069     /// Decl AST node, which points to a variable declaration AST node. Next, navigate
   3070     /// to the type expression.
   3071     /// The Decl is determined contextually.
   3072     node_offset_var_decl_ty: i32,
   3073     /// The source location points to the alignment expression of a var decl.
   3074     /// The Decl is determined contextually.
   3075     node_offset_var_decl_align: i32,
   3076     /// The source location points to the linksection expression of a var decl.
   3077     /// The Decl is determined contextually.
   3078     node_offset_var_decl_section: i32,
   3079     /// The source location points to the addrspace expression of a var decl.
   3080     /// The Decl is determined contextually.
   3081     node_offset_var_decl_addrspace: i32,
   3082     /// The source location points to the initializer of a var decl.
   3083     /// The Decl is determined contextually.
   3084     node_offset_var_decl_init: i32,
   3085     /// The source location points to the first parameter of a builtin
   3086     /// function call, found by taking this AST node index offset from the containing
   3087     /// Decl AST node, which points to a builtin call AST node. Next, navigate
   3088     /// to the first parameter.
   3089     /// The Decl is determined contextually.
   3090     node_offset_builtin_call_arg0: i32,
   3091     /// Same as `node_offset_builtin_call_arg0` except arg index 1.
   3092     node_offset_builtin_call_arg1: i32,
   3093     node_offset_builtin_call_arg2: i32,
   3094     node_offset_builtin_call_arg3: i32,
   3095     node_offset_builtin_call_arg4: i32,
   3096     node_offset_builtin_call_arg5: i32,
   3097     /// The source location points to the index expression of an array access
   3098     /// expression, found by taking this AST node index offset from the containing
   3099     /// Decl AST node, which points to an array access AST node. Next, navigate
   3100     /// to the index expression.
   3101     /// The Decl is determined contextually.
   3102     node_offset_array_access_index: i32,
   3103     /// The source location points to the LHS of a slice expression
   3104     /// expression, found by taking this AST node index offset from the containing
   3105     /// Decl AST node, which points to a slice AST node. Next, navigate
   3106     /// to the sentinel expression.
   3107     /// The Decl is determined contextually.
   3108     node_offset_slice_ptr: i32,
   3109     /// The source location points to start expression of a slice expression
   3110     /// expression, found by taking this AST node index offset from the containing
   3111     /// Decl AST node, which points to a slice AST node. Next, navigate
   3112     /// to the sentinel expression.
   3113     /// The Decl is determined contextually.
   3114     node_offset_slice_start: i32,
   3115     /// The source location points to the end expression of a slice
   3116     /// expression, found by taking this AST node index offset from the containing
   3117     /// Decl AST node, which points to a slice AST node. Next, navigate
   3118     /// to the sentinel expression.
   3119     /// The Decl is determined contextually.
   3120     node_offset_slice_end: i32,
   3121     /// The source location points to the sentinel expression of a slice
   3122     /// expression, found by taking this AST node index offset from the containing
   3123     /// Decl AST node, which points to a slice AST node. Next, navigate
   3124     /// to the sentinel expression.
   3125     /// The Decl is determined contextually.
   3126     node_offset_slice_sentinel: i32,
   3127     /// The source location points to the callee expression of a function
   3128     /// call expression, found by taking this AST node index offset from the containing
   3129     /// Decl AST node, which points to a function call AST node. Next, navigate
   3130     /// to the callee expression.
   3131     /// The Decl is determined contextually.
   3132     node_offset_call_func: i32,
   3133     /// The payload is offset from the containing Decl AST node.
   3134     /// The source location points to the field name of:
   3135     ///  * a field access expression (`a.b`), or
   3136     ///  * the callee of a method call (`a.b()`), or
   3137     ///  * the operand ("b" node) of a field initialization expression (`.a = b`), or
   3138     /// The Decl is determined contextually.
   3139     node_offset_field_name: i32,
   3140     /// The source location points to the pointer of a pointer deref expression,
   3141     /// found by taking this AST node index offset from the containing
   3142     /// Decl AST node, which points to a pointer deref AST node. Next, navigate
   3143     /// to the pointer expression.
   3144     /// The Decl is determined contextually.
   3145     node_offset_deref_ptr: i32,
   3146     /// The source location points to the assembly source code of an inline assembly
   3147     /// expression, found by taking this AST node index offset from the containing
   3148     /// Decl AST node, which points to inline assembly AST node. Next, navigate
   3149     /// to the asm template source code.
   3150     /// The Decl is determined contextually.
   3151     node_offset_asm_source: i32,
   3152     /// The source location points to the return type of an inline assembly
   3153     /// expression, found by taking this AST node index offset from the containing
   3154     /// Decl AST node, which points to inline assembly AST node. Next, navigate
   3155     /// to the return type expression.
   3156     /// The Decl is determined contextually.
   3157     node_offset_asm_ret_ty: i32,
   3158     /// The source location points to the condition expression of an if
   3159     /// expression, found by taking this AST node index offset from the containing
   3160     /// Decl AST node, which points to an if expression AST node. Next, navigate
   3161     /// to the condition expression.
   3162     /// The Decl is determined contextually.
   3163     node_offset_if_cond: i32,
   3164     /// The source location points to a binary expression, such as `a + b`, found
   3165     /// by taking this AST node index offset from the containing Decl AST node.
   3166     /// The Decl is determined contextually.
   3167     node_offset_bin_op: i32,
   3168     /// The source location points to the LHS of a binary expression, found
   3169     /// by taking this AST node index offset from the containing Decl AST node,
   3170     /// which points to a binary expression AST node. Next, navigate to the LHS.
   3171     /// The Decl is determined contextually.
   3172     node_offset_bin_lhs: i32,
   3173     /// The source location points to the RHS of a binary expression, found
   3174     /// by taking this AST node index offset from the containing Decl AST node,
   3175     /// which points to a binary expression AST node. Next, navigate to the RHS.
   3176     /// The Decl is determined contextually.
   3177     node_offset_bin_rhs: i32,
   3178     /// The source location points to the operand of a switch expression, found
   3179     /// by taking this AST node index offset from the containing Decl AST node,
   3180     /// which points to a switch expression AST node. Next, navigate to the operand.
   3181     /// The Decl is determined contextually.
   3182     node_offset_switch_operand: i32,
   3183     /// The source location points to the else/`_` prong of a switch expression, found
   3184     /// by taking this AST node index offset from the containing Decl AST node,
   3185     /// which points to a switch expression AST node. Next, navigate to the else/`_` prong.
   3186     /// The Decl is determined contextually.
   3187     node_offset_switch_special_prong: i32,
   3188     /// The source location points to all the ranges of a switch expression, found
   3189     /// by taking this AST node index offset from the containing Decl AST node,
   3190     /// which points to a switch expression AST node. Next, navigate to any of the
   3191     /// range nodes. The error applies to all of them.
   3192     /// The Decl is determined contextually.
   3193     node_offset_switch_range: i32,
   3194     /// The source location points to the capture of a switch_prong.
   3195     /// The Decl is determined contextually.
   3196     node_offset_switch_prong_capture: i32,
   3197     /// The source location points to the align expr of a function type
   3198     /// expression, found by taking this AST node index offset from the containing
   3199     /// Decl AST node, which points to a function type AST node. Next, navigate to
   3200     /// the calling convention node.
   3201     /// The Decl is determined contextually.
   3202     node_offset_fn_type_align: i32,
   3203     /// The source location points to the addrspace expr of a function type
   3204     /// expression, found by taking this AST node index offset from the containing
   3205     /// Decl AST node, which points to a function type AST node. Next, navigate to
   3206     /// the calling convention node.
   3207     /// The Decl is determined contextually.
   3208     node_offset_fn_type_addrspace: i32,
   3209     /// The source location points to the linksection expr of a function type
   3210     /// expression, found by taking this AST node index offset from the containing
   3211     /// Decl AST node, which points to a function type AST node. Next, navigate to
   3212     /// the calling convention node.
   3213     /// The Decl is determined contextually.
   3214     node_offset_fn_type_section: i32,
   3215     /// The source location points to the calling convention of a function type
   3216     /// expression, found by taking this AST node index offset from the containing
   3217     /// Decl AST node, which points to a function type AST node. Next, navigate to
   3218     /// the calling convention node.
   3219     /// The Decl is determined contextually.
   3220     node_offset_fn_type_cc: i32,
   3221     /// The source location points to the return type of a function type
   3222     /// expression, found by taking this AST node index offset from the containing
   3223     /// Decl AST node, which points to a function type AST node. Next, navigate to
   3224     /// the return type node.
   3225     /// The Decl is determined contextually.
   3226     node_offset_fn_type_ret_ty: i32,
   3227     node_offset_param: i32,
   3228     token_offset_param: i32,
   3229     /// The source location points to the type expression of an `anyframe->T`
   3230     /// expression, found by taking this AST node index offset from the containing
   3231     /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate
   3232     /// to the type expression.
   3233     /// The Decl is determined contextually.
   3234     node_offset_anyframe_type: i32,
   3235     /// The source location points to the string literal of `extern "foo"`, found
   3236     /// by taking this AST node index offset from the containing
   3237     /// Decl AST node, which points to a function prototype or variable declaration
   3238     /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.
   3239     /// The Decl is determined contextually.
   3240     node_offset_lib_name: i32,
   3241     /// The source location points to the len expression of an `[N:S]T`
   3242     /// expression, found by taking this AST node index offset from the containing
   3243     /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate
   3244     /// to the len expression.
   3245     /// The Decl is determined contextually.
   3246     node_offset_array_type_len: i32,
   3247     /// The source location points to the sentinel expression of an `[N:S]T`
   3248     /// expression, found by taking this AST node index offset from the containing
   3249     /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate
   3250     /// to the sentinel expression.
   3251     /// The Decl is determined contextually.
   3252     node_offset_array_type_sentinel: i32,
   3253     /// The source location points to the elem expression of an `[N:S]T`
   3254     /// expression, found by taking this AST node index offset from the containing
   3255     /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate
   3256     /// to the elem expression.
   3257     /// The Decl is determined contextually.
   3258     node_offset_array_type_elem: i32,
   3259     /// The source location points to the operand of an unary expression.
   3260     /// The Decl is determined contextually.
   3261     node_offset_un_op: i32,
   3262     /// The source location points to the elem type of a pointer.
   3263     /// The Decl is determined contextually.
   3264     node_offset_ptr_elem: i32,
   3265     /// The source location points to the sentinel of a pointer.
   3266     /// The Decl is determined contextually.
   3267     node_offset_ptr_sentinel: i32,
   3268     /// The source location points to the align expr of a pointer.
   3269     /// The Decl is determined contextually.
   3270     node_offset_ptr_align: i32,
   3271     /// The source location points to the addrspace expr of a pointer.
   3272     /// The Decl is determined contextually.
   3273     node_offset_ptr_addrspace: i32,
   3274     /// The source location points to the bit-offset of a pointer.
   3275     /// The Decl is determined contextually.
   3276     node_offset_ptr_bitoffset: i32,
   3277     /// The source location points to the host size of a pointer.
   3278     /// The Decl is determined contextually.
   3279     node_offset_ptr_hostsize: i32,
   3280     /// The source location points to the tag type of an union or an enum.
   3281     /// The Decl is determined contextually.
   3282     node_offset_container_tag: i32,
   3283     /// The source location points to the default value of a field.
   3284     /// The Decl is determined contextually.
   3285     node_offset_field_default: i32,
   3286     /// The source location points to the type of an array or struct initializer.
   3287     /// The Decl is determined contextually.
   3288     node_offset_init_ty: i32,
   3289     /// The source location points to the LHS of an assignment.
   3290     /// The Decl is determined contextually.
   3291     node_offset_store_ptr: i32,
   3292     /// The source location points to the RHS of an assignment.
   3293     /// The Decl is determined contextually.
   3294     node_offset_store_operand: i32,
   3295     /// The source location points to a for loop input.
   3296     /// The Decl is determined contextually.
   3297     for_input: struct {
   3298         /// Points to the for loop AST node.
   3299         for_node_offset: i32,
   3300         /// Picks one of the inputs from the condition.
   3301         input_index: u32,
   3302     },
   3303     /// The source location points to one of the captures of a for loop, found
   3304     /// by taking this AST node index offset from the containing
   3305     /// Decl AST node, which points to one of the input nodes of a for loop.
   3306     /// Next, navigate to the corresponding capture.
   3307     /// The Decl is determined contextually.
   3308     for_capture_from_input: i32,
   3309 
   3310     pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
   3311 
   3312     noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc {
   3313         var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };
   3314         result.node_offset.trace.addAddr(@returnAddress(), "init");
   3315         return result;
   3316     }
   3317 
   3318     fn nodeOffsetRelease(node_offset: i32) LazySrcLoc {
   3319         return .{ .node_offset = .{ .x = node_offset } };
   3320     }
   3321 
   3322     /// Upgrade to a `SrcLoc` based on the `Decl` provided.
   3323     pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl) SrcLoc {
   3324         return switch (lazy) {
   3325             .unneeded,
   3326             .entire_file,
   3327             .byte_abs,
   3328             .token_abs,
   3329             .node_abs,
   3330             => .{
   3331                 .file_scope = decl.getFileScope(),
   3332                 .parent_decl_node = 0,
   3333                 .lazy = lazy,
   3334             },
   3335 
   3336             .byte_offset,
   3337             .token_offset,
   3338             .node_offset,
   3339             .node_offset_main_token,
   3340             .node_offset_initializer,
   3341             .node_offset_var_decl_ty,
   3342             .node_offset_var_decl_align,
   3343             .node_offset_var_decl_section,
   3344             .node_offset_var_decl_addrspace,
   3345             .node_offset_var_decl_init,
   3346             .node_offset_builtin_call_arg0,
   3347             .node_offset_builtin_call_arg1,
   3348             .node_offset_builtin_call_arg2,
   3349             .node_offset_builtin_call_arg3,
   3350             .node_offset_builtin_call_arg4,
   3351             .node_offset_builtin_call_arg5,
   3352             .node_offset_array_access_index,
   3353             .node_offset_slice_ptr,
   3354             .node_offset_slice_start,
   3355             .node_offset_slice_end,
   3356             .node_offset_slice_sentinel,
   3357             .node_offset_call_func,
   3358             .node_offset_field_name,
   3359             .node_offset_deref_ptr,
   3360             .node_offset_asm_source,
   3361             .node_offset_asm_ret_ty,
   3362             .node_offset_if_cond,
   3363             .node_offset_bin_op,
   3364             .node_offset_bin_lhs,
   3365             .node_offset_bin_rhs,
   3366             .node_offset_switch_operand,
   3367             .node_offset_switch_special_prong,
   3368             .node_offset_switch_range,
   3369             .node_offset_switch_prong_capture,
   3370             .node_offset_fn_type_align,
   3371             .node_offset_fn_type_addrspace,
   3372             .node_offset_fn_type_section,
   3373             .node_offset_fn_type_cc,
   3374             .node_offset_fn_type_ret_ty,
   3375             .node_offset_param,
   3376             .token_offset_param,
   3377             .node_offset_anyframe_type,
   3378             .node_offset_lib_name,
   3379             .node_offset_array_type_len,
   3380             .node_offset_array_type_sentinel,
   3381             .node_offset_array_type_elem,
   3382             .node_offset_un_op,
   3383             .node_offset_ptr_elem,
   3384             .node_offset_ptr_sentinel,
   3385             .node_offset_ptr_align,
   3386             .node_offset_ptr_addrspace,
   3387             .node_offset_ptr_bitoffset,
   3388             .node_offset_ptr_hostsize,
   3389             .node_offset_container_tag,
   3390             .node_offset_field_default,
   3391             .node_offset_init_ty,
   3392             .node_offset_store_ptr,
   3393             .node_offset_store_operand,
   3394             .for_input,
   3395             .for_capture_from_input,
   3396             => .{
   3397                 .file_scope = decl.getFileScope(),
   3398                 .parent_decl_node = decl.src_node,
   3399                 .lazy = lazy,
   3400             },
   3401         };
   3402     }
   3403 };
   3404 
   3405 pub const SemaError = error{ OutOfMemory, AnalysisFail };
   3406 pub const CompileError = error{
   3407     OutOfMemory,
   3408     /// When this is returned, the compile error for the failure has already been recorded.
   3409     AnalysisFail,
   3410     /// Returned when a compile error needed to be reported but a provided LazySrcLoc was set
   3411     /// to the `unneeded` tag. The source location was, in fact, needed. It is expected that
   3412     /// somewhere up the call stack, the operation will be retried after doing expensive work
   3413     /// to compute a source location.
   3414     NeededSourceLocation,
   3415     /// A Type or Value was needed to be used during semantic analysis, but it was not available
   3416     /// because the function is generic. This is only seen when analyzing the body of a param
   3417     /// instruction.
   3418     GenericPoison,
   3419     /// In a comptime scope, a return instruction was encountered. This error is only seen when
   3420     /// doing a comptime function call.
   3421     ComptimeReturn,
   3422     /// In a comptime scope, a break instruction was encountered. This error is only seen when
   3423     /// evaluating a comptime block.
   3424     ComptimeBreak,
   3425 };
   3426 
   3427 pub fn init(mod: *Module) !void {
   3428     const gpa = mod.gpa;
   3429     try mod.error_name_list.append(gpa, "(no error)");
   3430     try mod.intern_pool.init(gpa);
   3431 }
   3432 
   3433 pub fn deinit(mod: *Module) void {
   3434     const gpa = mod.gpa;
   3435 
   3436     for (mod.import_table.keys()) |key| {
   3437         gpa.free(key);
   3438     }
   3439     var failed_decls = mod.failed_decls;
   3440     mod.failed_decls = .{};
   3441     for (mod.import_table.values()) |value| {
   3442         value.destroy(mod);
   3443     }
   3444     mod.import_table.deinit(gpa);
   3445 
   3446     {
   3447         var it = mod.embed_table.iterator();
   3448         while (it.next()) |entry| {
   3449             gpa.free(entry.key_ptr.*);
   3450             entry.value_ptr.*.destroy(mod);
   3451         }
   3452         mod.embed_table.deinit(gpa);
   3453     }
   3454 
   3455     mod.deletion_set.deinit(gpa);
   3456 
   3457     // The callsite of `Compilation.create` owns the `main_pkg`, however
   3458     // Module owns the builtin and std packages that it adds.
   3459     if (mod.main_pkg.table.fetchRemove("builtin")) |kv| {
   3460         gpa.free(kv.key);
   3461         kv.value.destroy(gpa);
   3462     }
   3463     if (mod.main_pkg.table.fetchRemove("std")) |kv| {
   3464         gpa.free(kv.key);
   3465         // It's possible for main_pkg to be std when running 'zig test'! In this case, we must not
   3466         // destroy it, since it would lead to a double-free.
   3467         if (kv.value != mod.main_pkg) {
   3468             kv.value.destroy(gpa);
   3469         }
   3470     }
   3471     if (mod.main_pkg.table.fetchRemove("root")) |kv| {
   3472         gpa.free(kv.key);
   3473     }
   3474     if (mod.root_pkg != mod.main_pkg) {
   3475         mod.root_pkg.destroy(gpa);
   3476     }
   3477 
   3478     mod.compile_log_text.deinit(gpa);
   3479 
   3480     mod.zig_cache_artifact_directory.handle.close();
   3481     mod.local_zir_cache.handle.close();
   3482     mod.global_zir_cache.handle.close();
   3483 
   3484     for (failed_decls.values()) |value| {
   3485         value.destroy(gpa);
   3486     }
   3487     failed_decls.deinit(gpa);
   3488 
   3489     if (mod.emit_h) |emit_h| {
   3490         for (emit_h.failed_decls.values()) |value| {
   3491             value.destroy(gpa);
   3492         }
   3493         emit_h.failed_decls.deinit(gpa);
   3494         emit_h.decl_table.deinit(gpa);
   3495         emit_h.allocated_emit_h.deinit(gpa);
   3496         gpa.destroy(emit_h);
   3497     }
   3498 
   3499     for (mod.failed_files.values()) |value| {
   3500         if (value) |msg| msg.destroy(gpa);
   3501     }
   3502     mod.failed_files.deinit(gpa);
   3503 
   3504     for (mod.failed_embed_files.values()) |msg| {
   3505         msg.destroy(gpa);
   3506     }
   3507     mod.failed_embed_files.deinit(gpa);
   3508 
   3509     for (mod.failed_exports.values()) |value| {
   3510         value.destroy(gpa);
   3511     }
   3512     mod.failed_exports.deinit(gpa);
   3513 
   3514     for (mod.cimport_errors.values()) |errs| {
   3515         for (errs) |err| err.deinit(gpa);
   3516     }
   3517     mod.cimport_errors.deinit(gpa);
   3518 
   3519     mod.compile_log_decls.deinit(gpa);
   3520 
   3521     for (mod.decl_exports.values()) |*export_list| {
   3522         export_list.deinit(gpa);
   3523     }
   3524     mod.decl_exports.deinit(gpa);
   3525 
   3526     for (mod.export_owners.values()) |*value| {
   3527         freeExportList(gpa, value);
   3528     }
   3529     mod.export_owners.deinit(gpa);
   3530 
   3531     {
   3532         var it = mod.global_error_set.keyIterator();
   3533         while (it.next()) |key| {
   3534             gpa.free(key.*);
   3535         }
   3536         mod.global_error_set.deinit(gpa);
   3537     }
   3538 
   3539     mod.error_name_list.deinit(gpa);
   3540     mod.test_functions.deinit(gpa);
   3541     mod.align_stack_fns.deinit(gpa);
   3542     mod.monomorphed_funcs.deinit(gpa);
   3543 
   3544     {
   3545         var it = mod.memoized_calls.iterator();
   3546         while (it.next()) |entry| {
   3547             gpa.free(entry.key_ptr.args);
   3548             entry.value_ptr.arena.promote(gpa).deinit();
   3549         }
   3550         mod.memoized_calls.deinit(gpa);
   3551     }
   3552 
   3553     mod.decls_free_list.deinit(gpa);
   3554     mod.allocated_decls.deinit(gpa);
   3555     mod.global_assembly.deinit(gpa);
   3556     mod.reference_table.deinit(gpa);
   3557 
   3558     mod.string_literal_table.deinit(gpa);
   3559     mod.string_literal_bytes.deinit(gpa);
   3560 
   3561     mod.intern_pool.deinit(gpa);
   3562     mod.tmp_hack_arena.deinit();
   3563 }
   3564 
   3565 pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
   3566     const gpa = mod.gpa;
   3567     {
   3568         const decl = mod.declPtr(decl_index);
   3569         log.debug("destroy {*} ({s})", .{ decl, decl.name });
   3570         _ = mod.test_functions.swapRemove(decl_index);
   3571         if (decl.deletion_flag) {
   3572             assert(mod.deletion_set.swapRemove(decl_index));
   3573         }
   3574         if (mod.global_assembly.fetchRemove(decl_index)) |kv| {
   3575             gpa.free(kv.value);
   3576         }
   3577         if (decl.has_tv) {
   3578             if (decl.getInnerNamespace()) |namespace| {
   3579                 namespace.destroyDecls(mod);
   3580             }
   3581         }
   3582         decl.clearValues(mod);
   3583         decl.dependants.deinit(gpa);
   3584         decl.dependencies.deinit(gpa);
   3585         decl.clearName(gpa);
   3586         decl.* = undefined;
   3587     }
   3588     mod.decls_free_list.append(gpa, decl_index) catch {
   3589         // In order to keep `destroyDecl` a non-fallible function, we ignore memory
   3590         // allocation failures here, instead leaking the Decl until garbage collection.
   3591     };
   3592     if (mod.emit_h) |mod_emit_h| {
   3593         const decl_emit_h = mod_emit_h.declPtr(decl_index);
   3594         decl_emit_h.fwd_decl.deinit(gpa);
   3595         decl_emit_h.* = undefined;
   3596     }
   3597 }
   3598 
   3599 pub fn declPtr(mod: *Module, decl_index: Decl.Index) *Decl {
   3600     return mod.allocated_decls.at(@enumToInt(decl_index));
   3601 }
   3602 
   3603 /// Returns true if and only if the Decl is the top level struct associated with a File.
   3604 pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
   3605     const decl = mod.declPtr(decl_index);
   3606     if (decl.src_namespace.parent != null)
   3607         return false;
   3608     return decl_index == decl.src_namespace.getDeclIndex();
   3609 }
   3610 
   3611 fn freeExportList(gpa: Allocator, export_list: *ArrayListUnmanaged(*Export)) void {
   3612     for (export_list.items) |exp| {
   3613         gpa.free(exp.options.name);
   3614         if (exp.options.section) |s| gpa.free(s);
   3615         gpa.destroy(exp);
   3616     }
   3617     export_list.deinit(gpa);
   3618 }
   3619 
   3620 // TODO https://github.com/ziglang/zig/issues/8643
   3621 const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8;
   3622 const HackDataLayout = extern struct {
   3623     data: [8]u8 align(@alignOf(Zir.Inst.Data)),
   3624     safety_tag: u8,
   3625 };
   3626 comptime {
   3627     if (data_has_safety_tag) {
   3628         assert(@sizeOf(HackDataLayout) == @sizeOf(Zir.Inst.Data));
   3629     }
   3630 }
   3631 
   3632 pub fn astGenFile(mod: *Module, file: *File) !void {
   3633     const tracy = trace(@src());
   3634     defer tracy.end();
   3635 
   3636     const comp = mod.comp;
   3637     const gpa = mod.gpa;
   3638 
   3639     // In any case we need to examine the stat of the file to determine the course of action.
   3640     var source_file = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{});
   3641     defer source_file.close();
   3642 
   3643     const stat = try source_file.stat();
   3644 
   3645     const want_local_cache = file.pkg == mod.main_pkg;
   3646     const digest = hash: {
   3647         var path_hash: Cache.HashHelper = .{};
   3648         path_hash.addBytes(build_options.version);
   3649         path_hash.add(builtin.zig_backend);
   3650         if (!want_local_cache) {
   3651             path_hash.addOptionalBytes(file.pkg.root_src_directory.path);
   3652         }
   3653         path_hash.addBytes(file.sub_file_path);
   3654         break :hash path_hash.final();
   3655     };
   3656     const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache;
   3657     const zir_dir = cache_directory.handle;
   3658 
   3659     // Determine whether we need to reload the file from disk and redo parsing and AstGen.
   3660     var lock: std.fs.File.Lock = switch (file.status) {
   3661         .never_loaded, .retryable_failure => lock: {
   3662             // First, load the cached ZIR code, if any.
   3663             log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{
   3664                 file.sub_file_path, want_local_cache, &digest,
   3665             });
   3666 
   3667             break :lock .shared;
   3668         },
   3669         .parse_failure, .astgen_failure, .success_zir => lock: {
   3670             const unchanged_metadata =
   3671                 stat.size == file.stat.size and
   3672                 stat.mtime == file.stat.mtime and
   3673                 stat.inode == file.stat.inode;
   3674 
   3675             if (unchanged_metadata) {
   3676                 log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});
   3677                 return;
   3678             }
   3679 
   3680             log.debug("metadata changed: {s}", .{file.sub_file_path});
   3681 
   3682             break :lock .exclusive;
   3683         },
   3684     };
   3685 
   3686     // We ask for a lock in order to coordinate with other zig processes.
   3687     // If another process is already working on this file, we will get the cached
   3688     // version. Likewise if we're working on AstGen and another process asks for
   3689     // the cached file, they'll get it.
   3690     const cache_file = while (true) {
   3691         break zir_dir.createFile(&digest, .{
   3692             .read = true,
   3693             .truncate = false,
   3694             .lock = lock,
   3695         }) catch |err| switch (err) {
   3696             error.NotDir => unreachable, // no dir components
   3697             error.InvalidUtf8 => unreachable, // it's a hex encoded name
   3698             error.BadPathName => unreachable, // it's a hex encoded name
   3699             error.NameTooLong => unreachable, // it's a fixed size name
   3700             error.PipeBusy => unreachable, // it's not a pipe
   3701             error.WouldBlock => unreachable, // not asking for non-blocking I/O
   3702             // There are no dir components, so you would think that this was
   3703             // unreachable, however we have observed on macOS two processes racing
   3704             // to do openat() with O_CREAT manifest in ENOENT.
   3705             error.FileNotFound => continue,
   3706 
   3707             else => |e| return e, // Retryable errors are handled at callsite.
   3708         };
   3709     };
   3710     defer cache_file.close();
   3711 
   3712     while (true) {
   3713         update: {
   3714             // First we read the header to determine the lengths of arrays.
   3715             const header = cache_file.reader().readStruct(Zir.Header) catch |err| switch (err) {
   3716                 // This can happen if Zig bails out of this function between creating
   3717                 // the cached file and writing it.
   3718                 error.EndOfStream => break :update,
   3719                 else => |e| return e,
   3720             };
   3721             const unchanged_metadata =
   3722                 stat.size == header.stat_size and
   3723                 stat.mtime == header.stat_mtime and
   3724                 stat.inode == header.stat_inode;
   3725 
   3726             if (!unchanged_metadata) {
   3727                 log.debug("AstGen cache stale: {s}", .{file.sub_file_path});
   3728                 break :update;
   3729             }
   3730             log.debug("AstGen cache hit: {s} instructions_len={d}", .{
   3731                 file.sub_file_path, header.instructions_len,
   3732             });
   3733 
   3734             file.zir = loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) {
   3735                 error.UnexpectedFileSize => {
   3736                     log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path});
   3737                     break :update;
   3738                 },
   3739                 else => |e| return e,
   3740             };
   3741             file.zir_loaded = true;
   3742             file.stat = .{
   3743                 .size = header.stat_size,
   3744                 .inode = header.stat_inode,
   3745                 .mtime = header.stat_mtime,
   3746             };
   3747             file.status = .success_zir;
   3748             log.debug("AstGen cached success: {s}", .{file.sub_file_path});
   3749 
   3750             // TODO don't report compile errors until Sema @importFile
   3751             if (file.zir.hasCompileErrors()) {
   3752                 {
   3753                     comp.mutex.lock();
   3754                     defer comp.mutex.unlock();
   3755                     try mod.failed_files.putNoClobber(gpa, file, null);
   3756                 }
   3757                 file.status = .astgen_failure;
   3758                 return error.AnalysisFail;
   3759             }
   3760             return;
   3761         }
   3762 
   3763         // If we already have the exclusive lock then it is our job to update.
   3764         if (builtin.os.tag == .wasi or lock == .exclusive) break;
   3765         // Otherwise, unlock to give someone a chance to get the exclusive lock
   3766         // and then upgrade to an exclusive lock.
   3767         cache_file.unlock();
   3768         lock = .exclusive;
   3769         try cache_file.lock(lock);
   3770     }
   3771 
   3772     // The cache is definitely stale so delete the contents to avoid an underwrite later.
   3773     cache_file.setEndPos(0) catch |err| switch (err) {
   3774         error.FileTooBig => unreachable, // 0 is not too big
   3775 
   3776         else => |e| return e,
   3777     };
   3778 
   3779     mod.lockAndClearFileCompileError(file);
   3780 
   3781     // If the previous ZIR does not have compile errors, keep it around
   3782     // in case parsing or new ZIR fails. In case of successful ZIR update
   3783     // at the end of this function we will free it.
   3784     // We keep the previous ZIR loaded so that we can use it
   3785     // for the update next time it does not have any compile errors. This avoids
   3786     // needlessly tossing out semantic analysis work when an error is
   3787     // temporarily introduced.
   3788     if (file.zir_loaded and !file.zir.hasCompileErrors()) {
   3789         assert(file.prev_zir == null);
   3790         const prev_zir_ptr = try gpa.create(Zir);
   3791         file.prev_zir = prev_zir_ptr;
   3792         prev_zir_ptr.* = file.zir;
   3793         file.zir = undefined;
   3794         file.zir_loaded = false;
   3795     }
   3796     file.unload(gpa);
   3797 
   3798     if (stat.size > std.math.maxInt(u32))
   3799         return error.FileTooBig;
   3800 
   3801     const source = try gpa.allocSentinel(u8, @intCast(usize, stat.size), 0);
   3802     defer if (!file.source_loaded) gpa.free(source);
   3803     const amt = try source_file.readAll(source);
   3804     if (amt != stat.size)
   3805         return error.UnexpectedEndOfFile;
   3806 
   3807     file.stat = .{
   3808         .size = stat.size,
   3809         .inode = stat.inode,
   3810         .mtime = stat.mtime,
   3811     };
   3812     file.source = source;
   3813     file.source_loaded = true;
   3814 
   3815     file.tree = try Ast.parse(gpa, source, .zig);
   3816     file.tree_loaded = true;
   3817 
   3818     // Any potential AST errors are converted to ZIR errors here.
   3819     file.zir = try AstGen.generate(gpa, file.tree);
   3820     file.zir_loaded = true;
   3821     file.status = .success_zir;
   3822     log.debug("AstGen fresh success: {s}", .{file.sub_file_path});
   3823 
   3824     const safety_buffer = if (data_has_safety_tag)
   3825         try gpa.alloc([8]u8, file.zir.instructions.len)
   3826     else
   3827         undefined;
   3828     defer if (data_has_safety_tag) gpa.free(safety_buffer);
   3829     const data_ptr = if (data_has_safety_tag)
   3830         if (file.zir.instructions.len == 0)
   3831             @as([*]const u8, undefined)
   3832         else
   3833             @ptrCast([*]const u8, safety_buffer.ptr)
   3834     else
   3835         @ptrCast([*]const u8, file.zir.instructions.items(.data).ptr);
   3836     if (data_has_safety_tag) {
   3837         // The `Data` union has a safety tag but in the file format we store it without.
   3838         for (file.zir.instructions.items(.data), 0..) |*data, i| {
   3839             const as_struct = @ptrCast(*const HackDataLayout, data);
   3840             safety_buffer[i] = as_struct.data;
   3841         }
   3842     }
   3843 
   3844     const header: Zir.Header = .{
   3845         .instructions_len = @intCast(u32, file.zir.instructions.len),
   3846         .string_bytes_len = @intCast(u32, file.zir.string_bytes.len),
   3847         .extra_len = @intCast(u32, file.zir.extra.len),
   3848 
   3849         .stat_size = stat.size,
   3850         .stat_inode = stat.inode,
   3851         .stat_mtime = stat.mtime,
   3852     };
   3853     var iovecs = [_]std.os.iovec_const{
   3854         .{
   3855             .iov_base = @ptrCast([*]const u8, &header),
   3856             .iov_len = @sizeOf(Zir.Header),
   3857         },
   3858         .{
   3859             .iov_base = @ptrCast([*]const u8, file.zir.instructions.items(.tag).ptr),
   3860             .iov_len = file.zir.instructions.len,
   3861         },
   3862         .{
   3863             .iov_base = data_ptr,
   3864             .iov_len = file.zir.instructions.len * 8,
   3865         },
   3866         .{
   3867             .iov_base = file.zir.string_bytes.ptr,
   3868             .iov_len = file.zir.string_bytes.len,
   3869         },
   3870         .{
   3871             .iov_base = @ptrCast([*]const u8, file.zir.extra.ptr),
   3872             .iov_len = file.zir.extra.len * 4,
   3873         },
   3874     };
   3875     cache_file.writevAll(&iovecs) catch |err| {
   3876         const pkg_path = file.pkg.root_src_directory.path orelse ".";
   3877         const cache_path = cache_directory.path orelse ".";
   3878         log.warn("unable to write cached ZIR code for {s}/{s} to {s}/{s}: {s}", .{
   3879             pkg_path, file.sub_file_path, cache_path, &digest, @errorName(err),
   3880         });
   3881     };
   3882 
   3883     if (file.zir.hasCompileErrors()) {
   3884         {
   3885             comp.mutex.lock();
   3886             defer comp.mutex.unlock();
   3887             try mod.failed_files.putNoClobber(gpa, file, null);
   3888         }
   3889         file.status = .astgen_failure;
   3890         return error.AnalysisFail;
   3891     }
   3892 
   3893     if (file.prev_zir) |prev_zir| {
   3894         // Iterate over all Namespace objects contained within this File, looking at the
   3895         // previous and new ZIR together and update the references to point
   3896         // to the new one. For example, Decl name, Decl zir_decl_index, and Namespace
   3897         // decl_table keys need to get updated to point to the new memory, even if the
   3898         // underlying source code is unchanged.
   3899         // We do not need to hold any locks at this time because all the Decl and Namespace
   3900         // objects being touched are specific to this File, and the only other concurrent
   3901         // tasks are touching other File objects.
   3902         try updateZirRefs(mod, file, prev_zir.*);
   3903         // At this point, `file.outdated_decls` and `file.deleted_decls` are populated,
   3904         // and semantic analysis will deal with them properly.
   3905         // No need to keep previous ZIR.
   3906         prev_zir.deinit(gpa);
   3907         gpa.destroy(prev_zir);
   3908         file.prev_zir = null;
   3909     } else if (file.root_decl.unwrap()) |root_decl| {
   3910         // This is an update, but it is the first time the File has succeeded
   3911         // ZIR. We must mark it outdated since we have already tried to
   3912         // semantically analyze it.
   3913         try file.outdated_decls.resize(gpa, 1);
   3914         file.outdated_decls.items[0] = root_decl;
   3915     }
   3916 }
   3917 
   3918 pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
   3919     return loadZirCacheBody(gpa, try cache_file.reader().readStruct(Zir.Header), cache_file);
   3920 }
   3921 
   3922 fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {
   3923     var instructions: std.MultiArrayList(Zir.Inst) = .{};
   3924     errdefer instructions.deinit(gpa);
   3925 
   3926     try instructions.setCapacity(gpa, header.instructions_len);
   3927     instructions.len = header.instructions_len;
   3928 
   3929     var zir: Zir = .{
   3930         .instructions = instructions.toOwnedSlice(),
   3931         .string_bytes = &.{},
   3932         .extra = &.{},
   3933     };
   3934     errdefer zir.deinit(gpa);
   3935 
   3936     zir.string_bytes = try gpa.alloc(u8, header.string_bytes_len);
   3937     zir.extra = try gpa.alloc(u32, header.extra_len);
   3938 
   3939     const safety_buffer = if (data_has_safety_tag)
   3940         try gpa.alloc([8]u8, header.instructions_len)
   3941     else
   3942         undefined;
   3943     defer if (data_has_safety_tag) gpa.free(safety_buffer);
   3944 
   3945     const data_ptr = if (data_has_safety_tag)
   3946         @ptrCast([*]u8, safety_buffer.ptr)
   3947     else
   3948         @ptrCast([*]u8, zir.instructions.items(.data).ptr);
   3949 
   3950     var iovecs = [_]std.os.iovec{
   3951         .{
   3952             .iov_base = @ptrCast([*]u8, zir.instructions.items(.tag).ptr),
   3953             .iov_len = header.instructions_len,
   3954         },
   3955         .{
   3956             .iov_base = data_ptr,
   3957             .iov_len = header.instructions_len * 8,
   3958         },
   3959         .{
   3960             .iov_base = zir.string_bytes.ptr,
   3961             .iov_len = header.string_bytes_len,
   3962         },
   3963         .{
   3964             .iov_base = @ptrCast([*]u8, zir.extra.ptr),
   3965             .iov_len = header.extra_len * 4,
   3966         },
   3967     };
   3968     const amt_read = try cache_file.readvAll(&iovecs);
   3969     const amt_expected = zir.instructions.len * 9 +
   3970         zir.string_bytes.len +
   3971         zir.extra.len * 4;
   3972     if (amt_read != amt_expected) return error.UnexpectedFileSize;
   3973     if (data_has_safety_tag) {
   3974         const tags = zir.instructions.items(.tag);
   3975         for (zir.instructions.items(.data), 0..) |*data, i| {
   3976             const union_tag = Zir.Inst.Tag.data_tags[@enumToInt(tags[i])];
   3977             const as_struct = @ptrCast(*HackDataLayout, data);
   3978             as_struct.* = .{
   3979                 .safety_tag = @enumToInt(union_tag),
   3980                 .data = safety_buffer[i],
   3981             };
   3982         }
   3983     }
   3984 
   3985     return zir;
   3986 }
   3987 
   3988 /// Patch ups:
   3989 /// * Struct.zir_index
   3990 /// * Decl.zir_index
   3991 /// * Fn.zir_body_inst
   3992 /// * Decl.zir_decl_index
   3993 fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
   3994     const gpa = mod.gpa;
   3995     const new_zir = file.zir;
   3996 
   3997     // The root decl will be null if the previous ZIR had AST errors.
   3998     const root_decl = file.root_decl.unwrap() orelse return;
   3999 
   4000     // Maps from old ZIR to new ZIR, struct_decl, enum_decl, etc. Any instruction which
   4001     // creates a namespace, gets mapped from old to new here.
   4002     var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
   4003     defer inst_map.deinit(gpa);
   4004     // Maps from old ZIR to new ZIR, the extra data index for the sub-decl item.
   4005     // e.g. the thing that Decl.zir_decl_index points to.
   4006     var extra_map: std.AutoHashMapUnmanaged(u32, u32) = .{};
   4007     defer extra_map.deinit(gpa);
   4008 
   4009     try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map, &extra_map);
   4010 
   4011     // Walk the Decl graph, updating ZIR indexes, strings, and populating
   4012     // the deleted and outdated lists.
   4013 
   4014     var decl_stack: ArrayListUnmanaged(Decl.Index) = .{};
   4015     defer decl_stack.deinit(gpa);
   4016 
   4017     try decl_stack.append(gpa, root_decl);
   4018 
   4019     file.deleted_decls.clearRetainingCapacity();
   4020     file.outdated_decls.clearRetainingCapacity();
   4021 
   4022     // The root decl is always outdated; otherwise we would not have had
   4023     // to re-generate ZIR for the File.
   4024     try file.outdated_decls.append(gpa, root_decl);
   4025 
   4026     while (decl_stack.popOrNull()) |decl_index| {
   4027         const decl = mod.declPtr(decl_index);
   4028         // Anonymous decls and the root decl have this set to 0. We still need
   4029         // to walk them but we do not need to modify this value.
   4030         // Anonymous decls should not be marked outdated. They will be re-generated
   4031         // if their owner decl is marked outdated.
   4032         if (decl.zir_decl_index != 0) {
   4033             const old_zir_decl_index = decl.zir_decl_index;
   4034             const new_zir_decl_index = extra_map.get(old_zir_decl_index) orelse {
   4035                 log.debug("updateZirRefs {s}: delete {*} ({s})", .{
   4036                     file.sub_file_path, decl, decl.name,
   4037                 });
   4038                 try file.deleted_decls.append(gpa, decl_index);
   4039                 continue;
   4040             };
   4041             const old_hash = decl.contentsHashZir(old_zir);
   4042             decl.zir_decl_index = new_zir_decl_index;
   4043             const new_hash = decl.contentsHashZir(new_zir);
   4044             if (!std.zig.srcHashEql(old_hash, new_hash)) {
   4045                 log.debug("updateZirRefs {s}: outdated {*} ({s}) {d} => {d}", .{
   4046                     file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index,
   4047                 });
   4048                 try file.outdated_decls.append(gpa, decl_index);
   4049             } else {
   4050                 log.debug("updateZirRefs {s}: unchanged {*} ({s}) {d} => {d}", .{
   4051                     file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index,
   4052                 });
   4053             }
   4054         }
   4055 
   4056         if (!decl.owns_tv) continue;
   4057 
   4058         if (decl.getStruct()) |struct_obj| {
   4059             struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse {
   4060                 try file.deleted_decls.append(gpa, decl_index);
   4061                 continue;
   4062             };
   4063         }
   4064 
   4065         if (decl.getUnion()) |union_obj| {
   4066             union_obj.zir_index = inst_map.get(union_obj.zir_index) orelse {
   4067                 try file.deleted_decls.append(gpa, decl_index);
   4068                 continue;
   4069             };
   4070         }
   4071 
   4072         if (decl.getFunction()) |func| {
   4073             func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
   4074                 try file.deleted_decls.append(gpa, decl_index);
   4075                 continue;
   4076             };
   4077         }
   4078 
   4079         if (decl.getInnerNamespace()) |namespace| {
   4080             for (namespace.decls.keys()) |sub_decl| {
   4081                 try decl_stack.append(gpa, sub_decl);
   4082             }
   4083             for (namespace.anon_decls.keys()) |sub_decl| {
   4084                 try decl_stack.append(gpa, sub_decl);
   4085             }
   4086         }
   4087     }
   4088 }
   4089 
   4090 pub fn populateBuiltinFile(mod: *Module) !void {
   4091     const tracy = trace(@src());
   4092     defer tracy.end();
   4093 
   4094     const comp = mod.comp;
   4095     const pkg_and_file = blk: {
   4096         comp.mutex.lock();
   4097         defer comp.mutex.unlock();
   4098 
   4099         const builtin_pkg = mod.main_pkg.table.get("builtin").?;
   4100         const result = try mod.importPkg(builtin_pkg);
   4101         break :blk .{
   4102             .file = result.file,
   4103             .pkg = builtin_pkg,
   4104         };
   4105     };
   4106     const file = pkg_and_file.file;
   4107     const builtin_pkg = pkg_and_file.pkg;
   4108     const gpa = mod.gpa;
   4109     file.source = try comp.generateBuiltinZigSource(gpa);
   4110     file.source_loaded = true;
   4111 
   4112     if (builtin_pkg.root_src_directory.handle.statFile(builtin_pkg.root_src_path)) |stat| {
   4113         if (stat.size != file.source.len) {
   4114             const full_path = try builtin_pkg.root_src_directory.join(gpa, &.{
   4115                 builtin_pkg.root_src_path,
   4116             });
   4117             defer gpa.free(full_path);
   4118 
   4119             log.warn(
   4120                 "the cached file '{s}' had the wrong size. Expected {d}, found {d}. " ++
   4121                     "Overwriting with correct file contents now",
   4122                 .{ full_path, file.source.len, stat.size },
   4123             );
   4124 
   4125             try writeBuiltinFile(file, builtin_pkg);
   4126         } else {
   4127             file.stat = .{
   4128                 .size = stat.size,
   4129                 .inode = stat.inode,
   4130                 .mtime = stat.mtime,
   4131             };
   4132         }
   4133     } else |err| switch (err) {
   4134         error.BadPathName => unreachable, // it's always "builtin.zig"
   4135         error.NameTooLong => unreachable, // it's always "builtin.zig"
   4136         error.PipeBusy => unreachable, // it's not a pipe
   4137         error.WouldBlock => unreachable, // not asking for non-blocking I/O
   4138 
   4139         error.FileNotFound => try writeBuiltinFile(file, builtin_pkg),
   4140 
   4141         else => |e| return e,
   4142     }
   4143 
   4144     file.tree = try Ast.parse(gpa, file.source, .zig);
   4145     file.tree_loaded = true;
   4146     assert(file.tree.errors.len == 0); // builtin.zig must parse
   4147 
   4148     file.zir = try AstGen.generate(gpa, file.tree);
   4149     file.zir_loaded = true;
   4150     file.status = .success_zir;
   4151 }
   4152 
   4153 fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
   4154     var af = try builtin_pkg.root_src_directory.handle.atomicFile(builtin_pkg.root_src_path, .{});
   4155     defer af.deinit();
   4156     try af.file.writeAll(file.source);
   4157     try af.finish();
   4158 
   4159     file.stat = .{
   4160         .size = file.source.len,
   4161         .inode = 0, // dummy value
   4162         .mtime = 0, // dummy value
   4163     };
   4164 }
   4165 
   4166 pub fn mapOldZirToNew(
   4167     gpa: Allocator,
   4168     old_zir: Zir,
   4169     new_zir: Zir,
   4170     inst_map: *std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index),
   4171     extra_map: *std.AutoHashMapUnmanaged(u32, u32),
   4172 ) Allocator.Error!void {
   4173     // Contain ZIR indexes of declaration instructions.
   4174     const MatchedZirDecl = struct {
   4175         old_inst: Zir.Inst.Index,
   4176         new_inst: Zir.Inst.Index,
   4177     };
   4178     var match_stack: ArrayListUnmanaged(MatchedZirDecl) = .{};
   4179     defer match_stack.deinit(gpa);
   4180 
   4181     // Main struct inst is always the same
   4182     try match_stack.append(gpa, .{
   4183         .old_inst = Zir.main_struct_inst,
   4184         .new_inst = Zir.main_struct_inst,
   4185     });
   4186 
   4187     var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
   4188     defer old_decls.deinit();
   4189     var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
   4190     defer new_decls.deinit();
   4191 
   4192     while (match_stack.popOrNull()) |match_item| {
   4193         try inst_map.put(gpa, match_item.old_inst, match_item.new_inst);
   4194 
   4195         // Maps name to extra index of decl sub item.
   4196         var decl_map: std.StringHashMapUnmanaged(u32) = .{};
   4197         defer decl_map.deinit(gpa);
   4198 
   4199         {
   4200             var old_decl_it = old_zir.declIterator(match_item.old_inst);
   4201             while (old_decl_it.next()) |old_decl| {
   4202                 try decl_map.put(gpa, old_decl.name, old_decl.sub_index);
   4203             }
   4204         }
   4205 
   4206         var new_decl_it = new_zir.declIterator(match_item.new_inst);
   4207         while (new_decl_it.next()) |new_decl| {
   4208             const old_extra_index = decl_map.get(new_decl.name) orelse continue;
   4209             const new_extra_index = new_decl.sub_index;
   4210             try extra_map.put(gpa, old_extra_index, new_extra_index);
   4211 
   4212             try old_zir.findDecls(&old_decls, old_extra_index);
   4213             try new_zir.findDecls(&new_decls, new_extra_index);
   4214             var i: usize = 0;
   4215             while (true) : (i += 1) {
   4216                 if (i >= old_decls.items.len) break;
   4217                 if (i >= new_decls.items.len) break;
   4218                 try match_stack.append(gpa, .{
   4219                     .old_inst = old_decls.items[i],
   4220                     .new_inst = new_decls.items[i],
   4221                 });
   4222             }
   4223         }
   4224     }
   4225 }
   4226 
   4227 /// This ensures that the Decl will have a Type and Value populated.
   4228 /// However the resolution status of the Type may not be fully resolved.
   4229 /// For example an inferred error set is not resolved until after `analyzeFnBody`.
   4230 /// is called.
   4231 pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
   4232     const tracy = trace(@src());
   4233     defer tracy.end();
   4234 
   4235     const decl = mod.declPtr(decl_index);
   4236 
   4237     const subsequent_analysis = switch (decl.analysis) {
   4238         .in_progress => unreachable,
   4239 
   4240         .file_failure,
   4241         .sema_failure,
   4242         .sema_failure_retryable,
   4243         .liveness_failure,
   4244         .codegen_failure,
   4245         .dependency_failure,
   4246         .codegen_failure_retryable,
   4247         => return error.AnalysisFail,
   4248 
   4249         .complete => return,
   4250 
   4251         .outdated => blk: {
   4252             log.debug("re-analyzing {*} ({s})", .{ decl, decl.name });
   4253 
   4254             // The exports this Decl performs will be re-discovered, so we remove them here
   4255             // prior to re-analysis.
   4256             try mod.deleteDeclExports(decl_index);
   4257 
   4258             // Similarly, `@setAlignStack` invocations will be re-discovered.
   4259             if (decl.getFunction()) |func| {
   4260                 _ = mod.align_stack_fns.remove(func);
   4261             }
   4262 
   4263             // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
   4264             for (decl.dependencies.keys()) |dep_index| {
   4265                 const dep = mod.declPtr(dep_index);
   4266                 dep.removeDependant(decl_index);
   4267                 if (dep.dependants.count() == 0 and !dep.deletion_flag) {
   4268                     log.debug("insert {*} ({s}) dependant {*} ({s}) into deletion set", .{
   4269                         decl, decl.name, dep, dep.name,
   4270                     });
   4271                     try mod.markDeclForDeletion(dep_index);
   4272                 }
   4273             }
   4274             decl.dependencies.clearRetainingCapacity();
   4275 
   4276             break :blk true;
   4277         },
   4278 
   4279         .unreferenced => false,
   4280     };
   4281 
   4282     var decl_prog_node = mod.sema_prog_node.start(mem.sliceTo(decl.name, 0), 0);
   4283     decl_prog_node.activate();
   4284     defer decl_prog_node.end();
   4285 
   4286     const type_changed = blk: {
   4287         if (decl.zir_decl_index == 0 and !mod.declIsRoot(decl_index)) {
   4288             // Anonymous decl. We don't semantically analyze these.
   4289             break :blk false; // tv unchanged
   4290         }
   4291 
   4292         break :blk mod.semaDecl(decl_index) catch |err| switch (err) {
   4293             error.AnalysisFail => {
   4294                 if (decl.analysis == .in_progress) {
   4295                     // If this decl caused the compile error, the analysis field would
   4296                     // be changed to indicate it was this Decl's fault. Because this
   4297                     // did not happen, we infer here that it was a dependency failure.
   4298                     decl.analysis = .dependency_failure;
   4299                 }
   4300                 return error.AnalysisFail;
   4301             },
   4302             error.NeededSourceLocation => unreachable,
   4303             error.GenericPoison => unreachable,
   4304             else => |e| {
   4305                 decl.analysis = .sema_failure_retryable;
   4306                 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);
   4307                 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
   4308                     mod.gpa,
   4309                     decl.srcLoc(),
   4310                     "unable to analyze: {s}",
   4311                     .{@errorName(e)},
   4312                 ));
   4313                 return error.AnalysisFail;
   4314             },
   4315         };
   4316     };
   4317 
   4318     if (subsequent_analysis) {
   4319         // Update all dependents which have at least this level of dependency.
   4320         // If our type remained the same and we're a function, only update
   4321         // decls which depend on our body; otherwise, update all dependents.
   4322         const update_level: Decl.DepType = if (!type_changed and decl.ty.zigTypeTag(mod) == .Fn) .function_body else .normal;
   4323 
   4324         for (decl.dependants.keys(), decl.dependants.values()) |dep_index, dep_type| {
   4325             if (@enumToInt(dep_type) < @enumToInt(update_level)) continue;
   4326 
   4327             const dep = mod.declPtr(dep_index);
   4328             switch (dep.analysis) {
   4329                 .unreferenced => unreachable,
   4330                 .in_progress => continue, // already doing analysis, ok
   4331                 .outdated => continue, // already queued for update
   4332 
   4333                 .file_failure,
   4334                 .dependency_failure,
   4335                 .sema_failure,
   4336                 .sema_failure_retryable,
   4337                 .liveness_failure,
   4338                 .codegen_failure,
   4339                 .codegen_failure_retryable,
   4340                 .complete,
   4341                 => if (dep.generation != mod.generation) {
   4342                     try mod.markOutdatedDecl(dep_index);
   4343                 },
   4344             }
   4345         }
   4346     }
   4347 }
   4348 
   4349 pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
   4350     const tracy = trace(@src());
   4351     defer tracy.end();
   4352 
   4353     const decl_index = func.owner_decl;
   4354     const decl = mod.declPtr(decl_index);
   4355 
   4356     switch (decl.analysis) {
   4357         .unreferenced => unreachable,
   4358         .in_progress => unreachable,
   4359         .outdated => unreachable,
   4360 
   4361         .file_failure,
   4362         .sema_failure,
   4363         .liveness_failure,
   4364         .codegen_failure,
   4365         .dependency_failure,
   4366         .sema_failure_retryable,
   4367         => return error.AnalysisFail,
   4368 
   4369         .complete, .codegen_failure_retryable => {
   4370             switch (func.state) {
   4371                 .sema_failure, .dependency_failure => return error.AnalysisFail,
   4372                 .none, .queued => {},
   4373                 .in_progress => unreachable,
   4374                 .inline_only => unreachable, // don't queue work for this
   4375                 .success => return,
   4376             }
   4377 
   4378             const gpa = mod.gpa;
   4379 
   4380             var tmp_arena = std.heap.ArenaAllocator.init(gpa);
   4381             defer tmp_arena.deinit();
   4382             const sema_arena = tmp_arena.allocator();
   4383 
   4384             var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
   4385                 error.AnalysisFail => {
   4386                     if (func.state == .in_progress) {
   4387                         // If this decl caused the compile error, the analysis field would
   4388                         // be changed to indicate it was this Decl's fault. Because this
   4389                         // did not happen, we infer here that it was a dependency failure.
   4390                         func.state = .dependency_failure;
   4391                     }
   4392                     return error.AnalysisFail;
   4393                 },
   4394                 error.OutOfMemory => return error.OutOfMemory,
   4395             };
   4396             defer air.deinit(gpa);
   4397 
   4398             const comp = mod.comp;
   4399 
   4400             const no_bin_file = (comp.bin_file.options.emit == null and
   4401                 comp.emit_asm == null and
   4402                 comp.emit_llvm_ir == null and
   4403                 comp.emit_llvm_bc == null);
   4404 
   4405             const dump_air = builtin.mode == .Debug and comp.verbose_air;
   4406             const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
   4407 
   4408             if (no_bin_file and !dump_air and !dump_llvm_ir) return;
   4409 
   4410             log.debug("analyze liveness of {s}", .{decl.name});
   4411             var liveness = try Liveness.analyze(gpa, air, &mod.intern_pool);
   4412             defer liveness.deinit(gpa);
   4413 
   4414             if (dump_air) {
   4415                 const fqn = try decl.getFullyQualifiedName(mod);
   4416                 defer mod.gpa.free(fqn);
   4417 
   4418                 std.debug.print("# Begin Function AIR: {s}:\n", .{fqn});
   4419                 @import("print_air.zig").dump(mod, air, liveness);
   4420                 std.debug.print("# End Function AIR: {s}\n\n", .{fqn});
   4421             }
   4422 
   4423             if (std.debug.runtime_safety) {
   4424                 var verify = Liveness.Verify{
   4425                     .gpa = gpa,
   4426                     .air = air,
   4427                     .liveness = liveness,
   4428                     .intern_pool = &mod.intern_pool,
   4429                 };
   4430                 defer verify.deinit();
   4431 
   4432                 verify.verify() catch |err| switch (err) {
   4433                     error.OutOfMemory => return error.OutOfMemory,
   4434                     else => {
   4435                         try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
   4436                         mod.failed_decls.putAssumeCapacityNoClobber(
   4437                             decl_index,
   4438                             try Module.ErrorMsg.create(
   4439                                 gpa,
   4440                                 decl.srcLoc(),
   4441                                 "invalid liveness: {s}",
   4442                                 .{@errorName(err)},
   4443                             ),
   4444                         );
   4445                         decl.analysis = .liveness_failure;
   4446                         return error.AnalysisFail;
   4447                     },
   4448                 };
   4449             }
   4450 
   4451             if (no_bin_file and !dump_llvm_ir) return;
   4452 
   4453             comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) {
   4454                 error.OutOfMemory => return error.OutOfMemory,
   4455                 error.AnalysisFail => {
   4456                     decl.analysis = .codegen_failure;
   4457                     return;
   4458                 },
   4459                 else => {
   4460                     try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
   4461                     mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
   4462                         gpa,
   4463                         decl.srcLoc(),
   4464                         "unable to codegen: {s}",
   4465                         .{@errorName(err)},
   4466                     ));
   4467                     decl.analysis = .codegen_failure_retryable;
   4468                     return;
   4469                 },
   4470             };
   4471             return;
   4472         },
   4473     }
   4474 }
   4475 
   4476 /// Ensure this function's body is or will be analyzed and emitted. This should
   4477 /// be called whenever a potential runtime call of a function is seen.
   4478 ///
   4479 /// The caller is responsible for ensuring the function decl itself is already
   4480 /// analyzed, and for ensuring it can exist at runtime (see
   4481 /// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
   4482 /// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
   4483 pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {
   4484     const decl_index = func.owner_decl;
   4485     const decl = mod.declPtr(decl_index);
   4486 
   4487     switch (decl.analysis) {
   4488         .unreferenced => unreachable,
   4489         .in_progress => unreachable,
   4490         .outdated => unreachable,
   4491 
   4492         .file_failure,
   4493         .sema_failure,
   4494         .liveness_failure,
   4495         .codegen_failure,
   4496         .dependency_failure,
   4497         .sema_failure_retryable,
   4498         .codegen_failure_retryable,
   4499         // The function analysis failed, but we've already emitted an error for
   4500         // that. The callee doesn't need the function to be analyzed right now,
   4501         // so its analysis can safely continue.
   4502         => return,
   4503 
   4504         .complete => {},
   4505     }
   4506 
   4507     assert(decl.has_tv);
   4508 
   4509     switch (func.state) {
   4510         .none => {},
   4511         .queued => return,
   4512         // As above, we don't need to forward errors here.
   4513         .sema_failure, .dependency_failure => return,
   4514         .in_progress => return,
   4515         .inline_only => unreachable, // don't queue work for this
   4516         .success => return,
   4517     }
   4518 
   4519     // Decl itself is safely analyzed, and body analysis is not yet queued
   4520 
   4521     try mod.comp.work_queue.writeItem(.{ .codegen_func = func });
   4522     if (mod.emit_h != null) {
   4523         // TODO: we ideally only want to do this if the function's type changed
   4524         // since the last update
   4525         try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
   4526     }
   4527     func.state = .queued;
   4528 }
   4529 
   4530 pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {
   4531     const tracy = trace(@src());
   4532     defer tracy.end();
   4533 
   4534     // TODO we can potentially relax this if we store some more information along
   4535     // with decl dependency edges
   4536     const owner_decl = mod.declPtr(embed_file.owner_decl);
   4537     for (owner_decl.dependants.keys()) |dep_index| {
   4538         const dep = mod.declPtr(dep_index);
   4539         switch (dep.analysis) {
   4540             .unreferenced => unreachable,
   4541             .in_progress => continue, // already doing analysis, ok
   4542             .outdated => continue, // already queued for update
   4543 
   4544             .file_failure,
   4545             .dependency_failure,
   4546             .sema_failure,
   4547             .sema_failure_retryable,
   4548             .liveness_failure,
   4549             .codegen_failure,
   4550             .codegen_failure_retryable,
   4551             .complete,
   4552             => if (dep.generation != mod.generation) {
   4553                 try mod.markOutdatedDecl(dep_index);
   4554             },
   4555         }
   4556     }
   4557 }
   4558 
   4559 pub fn semaPkg(mod: *Module, pkg: *Package) !void {
   4560     const file = (try mod.importPkg(pkg)).file;
   4561     return mod.semaFile(file);
   4562 }
   4563 
   4564 /// Regardless of the file status, will create a `Decl` so that we
   4565 /// can track dependencies and re-analyze when the file becomes outdated.
   4566 pub fn semaFile(mod: *Module, file: *File) SemaError!void {
   4567     const tracy = trace(@src());
   4568     defer tracy.end();
   4569 
   4570     if (file.root_decl != .none) return;
   4571 
   4572     const gpa = mod.gpa;
   4573     var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
   4574     errdefer new_decl_arena.deinit();
   4575     const new_decl_arena_allocator = new_decl_arena.allocator();
   4576 
   4577     const struct_obj = try new_decl_arena_allocator.create(Module.Struct);
   4578     const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);
   4579     const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);
   4580     const ty_ty = comptime Type.type;
   4581     struct_obj.* = .{
   4582         .owner_decl = undefined, // set below
   4583         .fields = .{},
   4584         .zir_index = undefined, // set below
   4585         .layout = .Auto,
   4586         .status = .none,
   4587         .known_non_opv = undefined,
   4588         .is_tuple = undefined, // set below
   4589         .namespace = .{
   4590             .parent = null,
   4591             .ty = struct_ty,
   4592             .file_scope = file,
   4593         },
   4594     };
   4595     const new_decl_index = try mod.allocateNewDecl(&struct_obj.namespace, 0, null);
   4596     const new_decl = mod.declPtr(new_decl_index);
   4597     file.root_decl = new_decl_index.toOptional();
   4598     struct_obj.owner_decl = new_decl_index;
   4599     new_decl.name = try file.fullyQualifiedNameZ(gpa);
   4600     new_decl.src_line = 0;
   4601     new_decl.is_pub = true;
   4602     new_decl.is_exported = false;
   4603     new_decl.has_align = false;
   4604     new_decl.has_linksection_or_addrspace = false;
   4605     new_decl.ty = ty_ty;
   4606     new_decl.val = struct_val;
   4607     new_decl.@"align" = 0;
   4608     new_decl.@"linksection" = null;
   4609     new_decl.has_tv = true;
   4610     new_decl.owns_tv = true;
   4611     new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive.
   4612     new_decl.analysis = .in_progress;
   4613     new_decl.generation = mod.generation;
   4614     new_decl.name_fully_qualified = true;
   4615 
   4616     if (file.status == .success_zir) {
   4617         assert(file.zir_loaded);
   4618         const main_struct_inst = Zir.main_struct_inst;
   4619         struct_obj.zir_index = main_struct_inst;
   4620         const extended = file.zir.instructions.items(.data)[main_struct_inst].extended;
   4621         const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
   4622         struct_obj.is_tuple = small.is_tuple;
   4623 
   4624         var sema_arena = std.heap.ArenaAllocator.init(gpa);
   4625         defer sema_arena.deinit();
   4626         const sema_arena_allocator = sema_arena.allocator();
   4627 
   4628         var sema: Sema = .{
   4629             .mod = mod,
   4630             .gpa = gpa,
   4631             .arena = sema_arena_allocator,
   4632             .perm_arena = new_decl_arena_allocator,
   4633             .code = file.zir,
   4634             .owner_decl = new_decl,
   4635             .owner_decl_index = new_decl_index,
   4636             .func = null,
   4637             .fn_ret_ty = Type.void,
   4638             .owner_func = null,
   4639         };
   4640         defer sema.deinit();
   4641 
   4642         var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null);
   4643         defer wip_captures.deinit();
   4644 
   4645         if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| {
   4646             try wip_captures.finalize();
   4647             new_decl.analysis = .complete;
   4648         } else |err| switch (err) {
   4649             error.OutOfMemory => return error.OutOfMemory,
   4650             error.AnalysisFail => {},
   4651         }
   4652 
   4653         if (mod.comp.whole_cache_manifest) |whole_cache_manifest| {
   4654             const source = file.getSource(gpa) catch |err| {
   4655                 try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)});
   4656                 return error.AnalysisFail;
   4657             };
   4658 
   4659             const resolved_path = std.fs.path.resolve(
   4660                 gpa,
   4661                 if (file.pkg.root_src_directory.path) |pkg_path|
   4662                     &[_][]const u8{ pkg_path, file.sub_file_path }
   4663                 else
   4664                     &[_][]const u8{file.sub_file_path},
   4665             ) catch |err| {
   4666                 try reportRetryableFileError(mod, file, "unable to resolve path: {s}", .{@errorName(err)});
   4667                 return error.AnalysisFail;
   4668             };
   4669             errdefer gpa.free(resolved_path);
   4670 
   4671             mod.comp.whole_cache_manifest_mutex.lock();
   4672             defer mod.comp.whole_cache_manifest_mutex.unlock();
   4673             try whole_cache_manifest.addFilePostContents(resolved_path, source.bytes, source.stat);
   4674         }
   4675     } else {
   4676         new_decl.analysis = .file_failure;
   4677     }
   4678 
   4679     try new_decl.finalizeNewArena(&new_decl_arena);
   4680 }
   4681 
   4682 /// Returns `true` if the Decl type changed.
   4683 /// Returns `true` if this is the first time analyzing the Decl.
   4684 /// Returns `false` otherwise.
   4685 fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
   4686     const tracy = trace(@src());
   4687     defer tracy.end();
   4688 
   4689     const decl = mod.declPtr(decl_index);
   4690 
   4691     if (decl.getFileScope().status != .success_zir) {
   4692         return error.AnalysisFail;
   4693     }
   4694 
   4695     const gpa = mod.gpa;
   4696     const zir = decl.getFileScope().zir;
   4697     const zir_datas = zir.instructions.items(.data);
   4698 
   4699     decl.analysis = .in_progress;
   4700 
   4701     // We need the memory for the Type to go into the arena for the Decl
   4702     var decl_arena = std.heap.ArenaAllocator.init(gpa);
   4703     const decl_arena_allocator = decl_arena.allocator();
   4704     const decl_value_arena = blk: {
   4705         errdefer decl_arena.deinit();
   4706         const s = try decl_arena_allocator.create(ValueArena);
   4707         s.* = .{ .state = undefined };
   4708         break :blk s;
   4709     };
   4710     defer {
   4711         if (decl.value_arena) |value_arena| {
   4712             assert(value_arena.state_acquired == null);
   4713             decl_value_arena.prev = value_arena;
   4714         }
   4715 
   4716         decl_value_arena.state = decl_arena.state;
   4717         decl.value_arena = decl_value_arena;
   4718     }
   4719 
   4720     var analysis_arena = std.heap.ArenaAllocator.init(gpa);
   4721     defer analysis_arena.deinit();
   4722     const analysis_arena_allocator = analysis_arena.allocator();
   4723 
   4724     var sema: Sema = .{
   4725         .mod = mod,
   4726         .gpa = gpa,
   4727         .arena = analysis_arena_allocator,
   4728         .perm_arena = decl_arena_allocator,
   4729         .code = zir,
   4730         .owner_decl = decl,
   4731         .owner_decl_index = decl_index,
   4732         .func = null,
   4733         .fn_ret_ty = Type.void,
   4734         .owner_func = null,
   4735     };
   4736     defer sema.deinit();
   4737 
   4738     if (mod.declIsRoot(decl_index)) {
   4739         log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
   4740         const main_struct_inst = Zir.main_struct_inst;
   4741         const struct_obj = decl.getStruct().?;
   4742         // This might not have gotten set in `semaFile` if the first time had
   4743         // a ZIR failure, so we set it here in case.
   4744         struct_obj.zir_index = main_struct_inst;
   4745         try sema.analyzeStructDecl(decl, main_struct_inst, struct_obj);
   4746         decl.analysis = .complete;
   4747         decl.generation = mod.generation;
   4748         return false;
   4749     }
   4750     log.debug("semaDecl {*} ({s})", .{ decl, decl.name });
   4751 
   4752     var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);
   4753     defer wip_captures.deinit();
   4754 
   4755     var block_scope: Sema.Block = .{
   4756         .parent = null,
   4757         .sema = &sema,
   4758         .src_decl = decl_index,
   4759         .namespace = decl.src_namespace,
   4760         .wip_capture_scope = wip_captures.scope,
   4761         .instructions = .{},
   4762         .inlining = null,
   4763         .is_comptime = true,
   4764     };
   4765     defer {
   4766         block_scope.instructions.deinit(gpa);
   4767         block_scope.params.deinit(gpa);
   4768     }
   4769 
   4770     const zir_block_index = decl.zirBlockIndex();
   4771     const inst_data = zir_datas[zir_block_index].pl_node;
   4772     const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);
   4773     const body = zir.extra[extra.end..][0..extra.data.body_len];
   4774     const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
   4775     try wip_captures.finalize();
   4776     const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 };
   4777     const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 };
   4778     const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
   4779     const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
   4780     const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
   4781     const decl_tv = try sema.resolveInstValue(&block_scope, init_src, result_ref, "global variable initializer must be comptime-known");
   4782 
   4783     // Note this resolves the type of the Decl, not the value; if this Decl
   4784     // is a struct, for example, this resolves `type` (which needs no resolution),
   4785     // not the struct itself.
   4786     try sema.resolveTypeLayout(decl_tv.ty);
   4787 
   4788     if (decl.kind == .@"usingnamespace") {
   4789         if (!decl_tv.ty.eql(Type.type, mod)) {
   4790             return sema.fail(&block_scope, ty_src, "expected type, found {}", .{
   4791                 decl_tv.ty.fmt(mod),
   4792             });
   4793         }
   4794         const ty = try decl_tv.val.toType().copy(decl_arena_allocator);
   4795         if (ty.getNamespace() == null) {
   4796             return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)});
   4797         }
   4798 
   4799         decl.ty = Type.type;
   4800         decl.val = try Value.Tag.ty.create(decl_arena_allocator, ty);
   4801         decl.@"align" = 0;
   4802         decl.@"linksection" = null;
   4803         decl.has_tv = true;
   4804         decl.owns_tv = false;
   4805         decl.analysis = .complete;
   4806         decl.generation = mod.generation;
   4807 
   4808         return true;
   4809     }
   4810 
   4811     if (decl_tv.val.castTag(.function)) |fn_payload| {
   4812         const func = fn_payload.data;
   4813         const owns_tv = func.owner_decl == decl_index;
   4814         if (owns_tv) {
   4815             var prev_type_has_bits = false;
   4816             var prev_is_inline = false;
   4817             var type_changed = true;
   4818 
   4819             if (decl.has_tv) {
   4820                 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
   4821                 type_changed = !decl.ty.eql(decl_tv.ty, mod);
   4822                 if (decl.getFunction()) |prev_func| {
   4823                     prev_is_inline = prev_func.state == .inline_only;
   4824                 }
   4825             }
   4826             decl.clearValues(mod);
   4827 
   4828             decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
   4829             decl.val = try decl_tv.val.copy(decl_arena_allocator);
   4830             // linksection, align, and addrspace were already set by Sema
   4831             decl.has_tv = true;
   4832             decl.owns_tv = owns_tv;
   4833             decl.analysis = .complete;
   4834             decl.generation = mod.generation;
   4835 
   4836             const is_inline = decl.ty.fnCallingConvention() == .Inline;
   4837             if (decl.is_exported) {
   4838                 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
   4839                 if (is_inline) {
   4840                     return sema.fail(&block_scope, export_src, "export of inline function", .{});
   4841                 }
   4842                 // The scope needs to have the decl in it.
   4843                 const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) };
   4844                 try sema.analyzeExport(&block_scope, export_src, options, decl_index);
   4845             }
   4846             return type_changed or is_inline != prev_is_inline;
   4847         }
   4848     }
   4849     var type_changed = true;
   4850     if (decl.has_tv) {
   4851         type_changed = !decl.ty.eql(decl_tv.ty, mod);
   4852     }
   4853     decl.clearValues(mod);
   4854 
   4855     decl.owns_tv = false;
   4856     var queue_linker_work = false;
   4857     var is_extern = false;
   4858     switch (decl_tv.val.ip_index) {
   4859         .generic_poison => unreachable,
   4860         .unreachable_value => unreachable,
   4861 
   4862         .none => switch (decl_tv.val.tag()) {
   4863             .variable => {
   4864                 const variable = decl_tv.val.castTag(.variable).?.data;
   4865                 if (variable.owner_decl == decl_index) {
   4866                     decl.owns_tv = true;
   4867                     queue_linker_work = true;
   4868 
   4869                     const copied_init = try variable.init.copy(decl_arena_allocator);
   4870                     variable.init = copied_init;
   4871                 }
   4872             },
   4873             .extern_fn => {
   4874                 const extern_fn = decl_tv.val.castTag(.extern_fn).?.data;
   4875                 if (extern_fn.owner_decl == decl_index) {
   4876                     decl.owns_tv = true;
   4877                     queue_linker_work = true;
   4878                     is_extern = true;
   4879                 }
   4880             },
   4881 
   4882             .function => {},
   4883 
   4884             else => {
   4885                 log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });
   4886                 queue_linker_work = true;
   4887             },
   4888         },
   4889         else => {
   4890             log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });
   4891             queue_linker_work = true;
   4892         },
   4893     }
   4894 
   4895     decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
   4896     decl.val = try decl_tv.val.copy(decl_arena_allocator);
   4897     decl.@"align" = blk: {
   4898         const align_ref = decl.zirAlignRef();
   4899         if (align_ref == .none) break :blk 0;
   4900         break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);
   4901     };
   4902     decl.@"linksection" = blk: {
   4903         const linksection_ref = decl.zirLinksectionRef();
   4904         if (linksection_ref == .none) break :blk null;
   4905         const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime-known");
   4906         if (mem.indexOfScalar(u8, bytes, 0) != null) {
   4907             return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});
   4908         } else if (bytes.len == 0) {
   4909             return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
   4910         }
   4911         break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;
   4912     };
   4913     decl.@"addrspace" = blk: {
   4914         const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.ip_index) {
   4915             .none => switch (decl_tv.val.tag()) {
   4916                 .function, .extern_fn => .function,
   4917                 .variable => .variable,
   4918                 else => .constant,
   4919             },
   4920             else => .constant,
   4921         };
   4922 
   4923         const target = sema.mod.getTarget();
   4924         break :blk switch (decl.zirAddrspaceRef()) {
   4925             .none => switch (addrspace_ctx) {
   4926                 .function => target_util.defaultAddressSpace(target, .function),
   4927                 .variable => target_util.defaultAddressSpace(target, .global_mutable),
   4928                 .constant => target_util.defaultAddressSpace(target, .global_constant),
   4929                 else => unreachable,
   4930             },
   4931             else => |addrspace_ref| try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx),
   4932         };
   4933     };
   4934     decl.has_tv = true;
   4935     decl.analysis = .complete;
   4936     decl.generation = mod.generation;
   4937 
   4938     const has_runtime_bits = is_extern or
   4939         (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty));
   4940 
   4941     if (has_runtime_bits) {
   4942         log.debug("queue linker work for {*} ({s})", .{ decl, decl.name });
   4943 
   4944         // Needed for codegen_decl which will call updateDecl and then the
   4945         // codegen backend wants full access to the Decl Type.
   4946         try sema.resolveTypeFully(decl.ty);
   4947 
   4948         try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });
   4949 
   4950         if (type_changed and mod.emit_h != null) {
   4951             try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
   4952         }
   4953     }
   4954 
   4955     if (decl.is_exported) {
   4956         const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
   4957         // The scope needs to have the decl in it.
   4958         const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) };
   4959         try sema.analyzeExport(&block_scope, export_src, options, decl_index);
   4960     }
   4961 
   4962     return type_changed;
   4963 }
   4964 
   4965 /// Returns the depender's index of the dependee.
   4966 pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_index: Decl.Index) !void {
   4967     return mod.declareDeclDependencyType(depender_index, dependee_index, .normal);
   4968 }
   4969 
   4970 /// Returns the depender's index of the dependee.
   4971 pub fn declareDeclDependencyType(mod: *Module, depender_index: Decl.Index, dependee_index: Decl.Index, dep_type: Decl.DepType) !void {
   4972     if (depender_index == dependee_index) return;
   4973 
   4974     const depender = mod.declPtr(depender_index);
   4975     const dependee = mod.declPtr(dependee_index);
   4976 
   4977     if (depender.dependencies.get(dependee_index)) |cur_type| {
   4978         if (@enumToInt(cur_type) >= @enumToInt(dep_type)) {
   4979             // We already have this dependency (or stricter) marked
   4980             return;
   4981         }
   4982     }
   4983 
   4984     log.debug("{*} ({s}) depends on {*} ({s})", .{
   4985         depender, depender.name, dependee, dependee.name,
   4986     });
   4987 
   4988     if (dependee.deletion_flag) {
   4989         dependee.deletion_flag = false;
   4990         assert(mod.deletion_set.swapRemove(dependee_index));
   4991     }
   4992 
   4993     try depender.dependencies.ensureUnusedCapacity(mod.gpa, 1);
   4994     try dependee.dependants.ensureUnusedCapacity(mod.gpa, 1);
   4995 
   4996     dependee.dependants.putAssumeCapacity(depender_index, dep_type);
   4997     depender.dependencies.putAssumeCapacity(dependee_index, dep_type);
   4998 }
   4999 
   5000 pub const ImportFileResult = struct {
   5001     file: *File,
   5002     is_new: bool,
   5003     is_pkg: bool,
   5004 };
   5005 
   5006 pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
   5007     const gpa = mod.gpa;
   5008 
   5009     // The resolved path is used as the key in the import table, to detect if
   5010     // an import refers to the same as another, despite different relative paths
   5011     // or differently mapped package names.
   5012     const resolved_path = try std.fs.path.resolve(gpa, &[_][]const u8{
   5013         pkg.root_src_directory.path orelse ".", pkg.root_src_path,
   5014     });
   5015     var keep_resolved_path = false;
   5016     defer if (!keep_resolved_path) gpa.free(resolved_path);
   5017 
   5018     const gop = try mod.import_table.getOrPut(gpa, resolved_path);
   5019     errdefer _ = mod.import_table.pop();
   5020     if (gop.found_existing) {
   5021         try gop.value_ptr.*.addReference(mod.*, .{ .root = pkg });
   5022         return ImportFileResult{
   5023             .file = gop.value_ptr.*,
   5024             .is_new = false,
   5025             .is_pkg = true,
   5026         };
   5027     }
   5028 
   5029     const sub_file_path = try gpa.dupe(u8, pkg.root_src_path);
   5030     errdefer gpa.free(sub_file_path);
   5031 
   5032     const new_file = try gpa.create(File);
   5033     errdefer gpa.destroy(new_file);
   5034 
   5035     keep_resolved_path = true; // It's now owned by import_table.
   5036     gop.value_ptr.* = new_file;
   5037     new_file.* = .{
   5038         .sub_file_path = sub_file_path,
   5039         .source = undefined,
   5040         .source_loaded = false,
   5041         .tree_loaded = false,
   5042         .zir_loaded = false,
   5043         .stat = undefined,
   5044         .tree = undefined,
   5045         .zir = undefined,
   5046         .status = .never_loaded,
   5047         .pkg = pkg,
   5048         .root_decl = .none,
   5049     };
   5050     try new_file.addReference(mod.*, .{ .root = pkg });
   5051     return ImportFileResult{
   5052         .file = new_file,
   5053         .is_new = true,
   5054         .is_pkg = true,
   5055     };
   5056 }
   5057 
   5058 pub fn importFile(
   5059     mod: *Module,
   5060     cur_file: *File,
   5061     import_string: []const u8,
   5062 ) !ImportFileResult {
   5063     if (std.mem.eql(u8, import_string, "std")) {
   5064         return mod.importPkg(mod.main_pkg.table.get("std").?);
   5065     }
   5066     if (std.mem.eql(u8, import_string, "builtin")) {
   5067         return mod.importPkg(mod.main_pkg.table.get("builtin").?);
   5068     }
   5069     if (std.mem.eql(u8, import_string, "root")) {
   5070         return mod.importPkg(mod.root_pkg);
   5071     }
   5072     if (cur_file.pkg.table.get(import_string)) |pkg| {
   5073         return mod.importPkg(pkg);
   5074     }
   5075     if (!mem.endsWith(u8, import_string, ".zig")) {
   5076         return error.PackageNotFound;
   5077     }
   5078     const gpa = mod.gpa;
   5079 
   5080     // The resolved path is used as the key in the import table, to detect if
   5081     // an import refers to the same as another, despite different relative paths
   5082     // or differently mapped package names.
   5083     const cur_pkg_dir_path = cur_file.pkg.root_src_directory.path orelse ".";
   5084     const resolved_path = try std.fs.path.resolve(gpa, &[_][]const u8{
   5085         cur_pkg_dir_path, cur_file.sub_file_path, "..", import_string,
   5086     });
   5087     var keep_resolved_path = false;
   5088     defer if (!keep_resolved_path) gpa.free(resolved_path);
   5089 
   5090     const gop = try mod.import_table.getOrPut(gpa, resolved_path);
   5091     errdefer _ = mod.import_table.pop();
   5092     if (gop.found_existing) return ImportFileResult{
   5093         .file = gop.value_ptr.*,
   5094         .is_new = false,
   5095         .is_pkg = false,
   5096     };
   5097 
   5098     const new_file = try gpa.create(File);
   5099     errdefer gpa.destroy(new_file);
   5100 
   5101     const resolved_root_path = try std.fs.path.resolve(gpa, &[_][]const u8{cur_pkg_dir_path});
   5102     defer gpa.free(resolved_root_path);
   5103 
   5104     const sub_file_path = p: {
   5105         if (mem.startsWith(u8, resolved_path, resolved_root_path)) {
   5106             // +1 for the directory separator here.
   5107             break :p try gpa.dupe(u8, resolved_path[resolved_root_path.len + 1 ..]);
   5108         }
   5109         if (mem.eql(u8, resolved_root_path, ".") and
   5110             !isUpDir(resolved_path) and
   5111             !std.fs.path.isAbsolute(resolved_path))
   5112         {
   5113             break :p try gpa.dupe(u8, resolved_path);
   5114         }
   5115         return error.ImportOutsidePkgPath;
   5116     };
   5117     errdefer gpa.free(sub_file_path);
   5118 
   5119     log.debug("new importFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, import_string={s}", .{
   5120         resolved_root_path, resolved_path, sub_file_path, import_string,
   5121     });
   5122 
   5123     keep_resolved_path = true; // It's now owned by import_table.
   5124     gop.value_ptr.* = new_file;
   5125     new_file.* = .{
   5126         .sub_file_path = sub_file_path,
   5127         .source = undefined,
   5128         .source_loaded = false,
   5129         .tree_loaded = false,
   5130         .zir_loaded = false,
   5131         .stat = undefined,
   5132         .tree = undefined,
   5133         .zir = undefined,
   5134         .status = .never_loaded,
   5135         .pkg = cur_file.pkg,
   5136         .root_decl = .none,
   5137     };
   5138     return ImportFileResult{
   5139         .file = new_file,
   5140         .is_new = true,
   5141         .is_pkg = false,
   5142     };
   5143 }
   5144 
   5145 pub fn embedFile(mod: *Module, cur_file: *File, import_string: []const u8) !*EmbedFile {
   5146     const gpa = mod.gpa;
   5147 
   5148     if (cur_file.pkg.table.get(import_string)) |pkg| {
   5149         const resolved_path = try std.fs.path.resolve(gpa, &[_][]const u8{
   5150             pkg.root_src_directory.path orelse ".", pkg.root_src_path,
   5151         });
   5152         var keep_resolved_path = false;
   5153         defer if (!keep_resolved_path) gpa.free(resolved_path);
   5154 
   5155         const gop = try mod.embed_table.getOrPut(gpa, resolved_path);
   5156         errdefer assert(mod.embed_table.remove(resolved_path));
   5157         if (gop.found_existing) return gop.value_ptr.*;
   5158 
   5159         const sub_file_path = try gpa.dupe(u8, pkg.root_src_path);
   5160         errdefer gpa.free(sub_file_path);
   5161 
   5162         return newEmbedFile(mod, pkg, sub_file_path, resolved_path, &keep_resolved_path, gop);
   5163     }
   5164 
   5165     // The resolved path is used as the key in the table, to detect if a file
   5166     // refers to the same as another, despite different relative paths.
   5167     const cur_pkg_dir_path = cur_file.pkg.root_src_directory.path orelse ".";
   5168     const resolved_path = try std.fs.path.resolve(gpa, &[_][]const u8{
   5169         cur_pkg_dir_path, cur_file.sub_file_path, "..", import_string,
   5170     });
   5171     var keep_resolved_path = false;
   5172     defer if (!keep_resolved_path) gpa.free(resolved_path);
   5173 
   5174     const gop = try mod.embed_table.getOrPut(gpa, resolved_path);
   5175     errdefer assert(mod.embed_table.remove(resolved_path));
   5176     if (gop.found_existing) return gop.value_ptr.*;
   5177 
   5178     const resolved_root_path = try std.fs.path.resolve(gpa, &[_][]const u8{cur_pkg_dir_path});
   5179     defer gpa.free(resolved_root_path);
   5180 
   5181     const sub_file_path = p: {
   5182         if (mem.startsWith(u8, resolved_path, resolved_root_path)) {
   5183             // +1 for the directory separator here.
   5184             break :p try gpa.dupe(u8, resolved_path[resolved_root_path.len + 1 ..]);
   5185         }
   5186         if (mem.eql(u8, resolved_root_path, ".") and
   5187             !isUpDir(resolved_path) and
   5188             !std.fs.path.isAbsolute(resolved_path))
   5189         {
   5190             break :p try gpa.dupe(u8, resolved_path);
   5191         }
   5192         return error.ImportOutsidePkgPath;
   5193     };
   5194     errdefer gpa.free(sub_file_path);
   5195 
   5196     return newEmbedFile(mod, cur_file.pkg, sub_file_path, resolved_path, &keep_resolved_path, gop);
   5197 }
   5198 
   5199 fn newEmbedFile(
   5200     mod: *Module,
   5201     pkg: *Package,
   5202     sub_file_path: []const u8,
   5203     resolved_path: []const u8,
   5204     keep_resolved_path: *bool,
   5205     gop: std.StringHashMapUnmanaged(*EmbedFile).GetOrPutResult,
   5206 ) !*EmbedFile {
   5207     const gpa = mod.gpa;
   5208 
   5209     const new_file = try gpa.create(EmbedFile);
   5210     errdefer gpa.destroy(new_file);
   5211 
   5212     var file = try pkg.root_src_directory.handle.openFile(sub_file_path, .{});
   5213     defer file.close();
   5214 
   5215     const actual_stat = try file.stat();
   5216     const stat: Cache.File.Stat = .{
   5217         .size = actual_stat.size,
   5218         .inode = actual_stat.inode,
   5219         .mtime = actual_stat.mtime,
   5220     };
   5221     const size_usize = std.math.cast(usize, actual_stat.size) orelse return error.Overflow;
   5222     const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
   5223     errdefer gpa.free(bytes);
   5224 
   5225     if (mod.comp.whole_cache_manifest) |whole_cache_manifest| {
   5226         const copied_resolved_path = try gpa.dupe(u8, resolved_path);
   5227         errdefer gpa.free(copied_resolved_path);
   5228         mod.comp.whole_cache_manifest_mutex.lock();
   5229         defer mod.comp.whole_cache_manifest_mutex.unlock();
   5230         try whole_cache_manifest.addFilePostContents(copied_resolved_path, bytes, stat);
   5231     }
   5232 
   5233     keep_resolved_path.* = true; // It's now owned by embed_table.
   5234     gop.value_ptr.* = new_file;
   5235     new_file.* = .{
   5236         .sub_file_path = sub_file_path,
   5237         .bytes = bytes,
   5238         .stat = stat,
   5239         .pkg = pkg,
   5240         .owner_decl = undefined, // Set by Sema immediately after this function returns.
   5241     };
   5242     return new_file;
   5243 }
   5244 
   5245 pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
   5246     var file = try embed_file.pkg.root_src_directory.handle.openFile(embed_file.sub_file_path, .{});
   5247     defer file.close();
   5248 
   5249     const stat = try file.stat();
   5250 
   5251     const unchanged_metadata =
   5252         stat.size == embed_file.stat.size and
   5253         stat.mtime == embed_file.stat.mtime and
   5254         stat.inode == embed_file.stat.inode;
   5255 
   5256     if (unchanged_metadata) return;
   5257 
   5258     const gpa = mod.gpa;
   5259     const size_usize = std.math.cast(usize, stat.size) orelse return error.Overflow;
   5260     const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
   5261     gpa.free(embed_file.bytes);
   5262     embed_file.bytes = bytes;
   5263     embed_file.stat = .{
   5264         .size = stat.size,
   5265         .mtime = stat.mtime,
   5266         .inode = stat.inode,
   5267     };
   5268 
   5269     mod.comp.mutex.lock();
   5270     defer mod.comp.mutex.unlock();
   5271     try mod.comp.work_queue.writeItem(.{ .update_embed_file = embed_file });
   5272 }
   5273 
   5274 pub fn scanNamespace(
   5275     mod: *Module,
   5276     namespace: *Namespace,
   5277     extra_start: usize,
   5278     decls_len: u32,
   5279     parent_decl: *Decl,
   5280 ) Allocator.Error!usize {
   5281     const tracy = trace(@src());
   5282     defer tracy.end();
   5283 
   5284     const gpa = mod.gpa;
   5285     const zir = namespace.file_scope.zir;
   5286 
   5287     try mod.comp.work_queue.ensureUnusedCapacity(decls_len);
   5288     try namespace.decls.ensureTotalCapacity(gpa, decls_len);
   5289 
   5290     const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
   5291     var extra_index = extra_start + bit_bags_count;
   5292     var bit_bag_index: usize = extra_start;
   5293     var cur_bit_bag: u32 = undefined;
   5294     var decl_i: u32 = 0;
   5295     var scan_decl_iter: ScanDeclIter = .{
   5296         .module = mod,
   5297         .namespace = namespace,
   5298         .parent_decl = parent_decl,
   5299     };
   5300     while (decl_i < decls_len) : (decl_i += 1) {
   5301         if (decl_i % 8 == 0) {
   5302             cur_bit_bag = zir.extra[bit_bag_index];
   5303             bit_bag_index += 1;
   5304         }
   5305         const flags = @truncate(u4, cur_bit_bag);
   5306         cur_bit_bag >>= 4;
   5307 
   5308         const decl_sub_index = extra_index;
   5309         extra_index += 8; // src_hash(4) + line(1) + name(1) + value(1) + doc_comment(1)
   5310         extra_index += @truncate(u1, flags >> 2); // Align
   5311         extra_index += @as(u2, @truncate(u1, flags >> 3)) * 2; // Link section or address space, consists of 2 Refs
   5312 
   5313         try scanDecl(&scan_decl_iter, decl_sub_index, flags);
   5314     }
   5315     return extra_index;
   5316 }
   5317 
   5318 const ScanDeclIter = struct {
   5319     module: *Module,
   5320     namespace: *Namespace,
   5321     parent_decl: *Decl,
   5322     usingnamespace_index: usize = 0,
   5323     comptime_index: usize = 0,
   5324     unnamed_test_index: usize = 0,
   5325 };
   5326 
   5327 fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Error!void {
   5328     const tracy = trace(@src());
   5329     defer tracy.end();
   5330 
   5331     const mod = iter.module;
   5332     const namespace = iter.namespace;
   5333     const gpa = mod.gpa;
   5334     const zir = namespace.file_scope.zir;
   5335 
   5336     // zig fmt: off
   5337     const is_pub                       = (flags & 0b0001) != 0;
   5338     const export_bit                   = (flags & 0b0010) != 0;
   5339     const has_align                    = (flags & 0b0100) != 0;
   5340     const has_linksection_or_addrspace = (flags & 0b1000) != 0;
   5341     // zig fmt: on
   5342 
   5343     const line_off = zir.extra[decl_sub_index + 4];
   5344     const line = iter.parent_decl.relativeToLine(line_off);
   5345     const decl_name_index = zir.extra[decl_sub_index + 5];
   5346     const decl_doccomment_index = zir.extra[decl_sub_index + 7];
   5347     const decl_zir_index = zir.extra[decl_sub_index + 6];
   5348     const decl_block_inst_data = zir.instructions.items(.data)[decl_zir_index].pl_node;
   5349     const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
   5350 
   5351     // Every Decl needs a name.
   5352     var is_named_test = false;
   5353     var kind: Decl.Kind = .named;
   5354     const decl_name: [:0]const u8 = switch (decl_name_index) {
   5355         0 => name: {
   5356             if (export_bit) {
   5357                 const i = iter.usingnamespace_index;
   5358                 iter.usingnamespace_index += 1;
   5359                 kind = .@"usingnamespace";
   5360                 break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i});
   5361             } else {
   5362                 const i = iter.comptime_index;
   5363                 iter.comptime_index += 1;
   5364                 kind = .@"comptime";
   5365                 break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i});
   5366             }
   5367         },
   5368         1 => name: {
   5369             const i = iter.unnamed_test_index;
   5370             iter.unnamed_test_index += 1;
   5371             kind = .@"test";
   5372             break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i});
   5373         },
   5374         2 => name: {
   5375             is_named_test = true;
   5376             const test_name = zir.nullTerminatedString(decl_doccomment_index);
   5377             kind = .@"test";
   5378             break :name try std.fmt.allocPrintZ(gpa, "decltest.{s}", .{test_name});
   5379         },
   5380         else => name: {
   5381             const raw_name = zir.nullTerminatedString(decl_name_index);
   5382             if (raw_name.len == 0) {
   5383                 is_named_test = true;
   5384                 const test_name = zir.nullTerminatedString(decl_name_index + 1);
   5385                 kind = .@"test";
   5386                 break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});
   5387             } else {
   5388                 break :name try gpa.dupeZ(u8, raw_name);
   5389             }
   5390         },
   5391     };
   5392     var must_free_decl_name = true;
   5393     defer if (must_free_decl_name) gpa.free(decl_name);
   5394 
   5395     const is_exported = export_bit and decl_name_index != 0;
   5396     if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
   5397 
   5398     // We create a Decl for it regardless of analysis status.
   5399     const gop = try namespace.decls.getOrPutContextAdapted(
   5400         gpa,
   5401         @as([]const u8, mem.sliceTo(decl_name, 0)),
   5402         DeclAdapter{ .mod = mod },
   5403         Namespace.DeclContext{ .module = mod },
   5404     );
   5405     const comp = mod.comp;
   5406     if (!gop.found_existing) {
   5407         const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope);
   5408         const new_decl = mod.declPtr(new_decl_index);
   5409         new_decl.kind = kind;
   5410         new_decl.name = decl_name;
   5411         must_free_decl_name = false;
   5412         if (kind == .@"usingnamespace") {
   5413             namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);
   5414         }
   5415         log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace });
   5416         new_decl.src_line = line;
   5417         gop.key_ptr.* = new_decl_index;
   5418         // Exported decls, comptime decls, usingnamespace decls, and
   5419         // test decls if in test mode, get analyzed.
   5420         const decl_pkg = namespace.file_scope.pkg;
   5421         const want_analysis = is_exported or switch (decl_name_index) {
   5422             0 => true, // comptime or usingnamespace decl
   5423             1 => blk: {
   5424                 // test decl with no name. Skip the part where we check against
   5425                 // the test name filter.
   5426                 if (!comp.bin_file.options.is_test) break :blk false;
   5427                 if (decl_pkg != mod.main_pkg) break :blk false;
   5428                 try mod.test_functions.put(gpa, new_decl_index, {});
   5429                 break :blk true;
   5430             },
   5431             else => blk: {
   5432                 if (!is_named_test) break :blk false;
   5433                 if (!comp.bin_file.options.is_test) break :blk false;
   5434                 if (decl_pkg != mod.main_pkg) break :blk false;
   5435                 if (comp.test_filter) |test_filter| {
   5436                     if (mem.indexOf(u8, decl_name, test_filter) == null) {
   5437                         break :blk false;
   5438                     }
   5439                 }
   5440                 try mod.test_functions.put(gpa, new_decl_index, {});
   5441                 break :blk true;
   5442             },
   5443         };
   5444         if (want_analysis) {
   5445             comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl_index });
   5446         }
   5447         new_decl.is_pub = is_pub;
   5448         new_decl.is_exported = is_exported;
   5449         new_decl.has_align = has_align;
   5450         new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
   5451         new_decl.zir_decl_index = @intCast(u32, decl_sub_index);
   5452         new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive.
   5453         return;
   5454     }
   5455     const decl_index = gop.key_ptr.*;
   5456     const decl = mod.declPtr(decl_index);
   5457     if (kind == .@"test") {
   5458         const src_loc = SrcLoc{
   5459             .file_scope = decl.getFileScope(),
   5460             .parent_decl_node = decl.src_node,
   5461             .lazy = .{ .token_offset = 1 },
   5462         };
   5463         const msg = try ErrorMsg.create(
   5464             gpa,
   5465             src_loc,
   5466             "duplicate test name: {s}",
   5467             .{decl_name},
   5468         );
   5469         errdefer msg.destroy(gpa);
   5470         try mod.failed_decls.putNoClobber(gpa, decl_index, msg);
   5471         const other_src_loc = SrcLoc{
   5472             .file_scope = namespace.file_scope,
   5473             .parent_decl_node = decl_node,
   5474             .lazy = .{ .token_offset = 1 },
   5475         };
   5476         try mod.errNoteNonLazy(other_src_loc, msg, "other test here", .{});
   5477     }
   5478     log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl.name, namespace });
   5479     // Update the AST node of the decl; even if its contents are unchanged, it may
   5480     // have been re-ordered.
   5481     decl.src_node = decl_node;
   5482     decl.src_line = line;
   5483 
   5484     decl.is_pub = is_pub;
   5485     decl.is_exported = is_exported;
   5486     decl.kind = kind;
   5487     decl.has_align = has_align;
   5488     decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
   5489     decl.zir_decl_index = @intCast(u32, decl_sub_index);
   5490     if (decl.getFunction()) |_| {
   5491         switch (comp.bin_file.tag) {
   5492             .coff, .elf, .macho, .plan9 => {
   5493                 // TODO Look into detecting when this would be unnecessary by storing enough state
   5494                 // in `Decl` to notice that the line number did not change.
   5495                 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
   5496             },
   5497             .c, .wasm, .spirv, .nvptx => {},
   5498         }
   5499     }
   5500 }
   5501 
   5502 /// Make it as if the semantic analysis for this Decl never happened.
   5503 pub fn clearDecl(
   5504     mod: *Module,
   5505     decl_index: Decl.Index,
   5506     outdated_decls: ?*std.AutoArrayHashMap(Decl.Index, void),
   5507 ) Allocator.Error!void {
   5508     const tracy = trace(@src());
   5509     defer tracy.end();
   5510 
   5511     const decl = mod.declPtr(decl_index);
   5512     log.debug("clearing {*} ({s})", .{ decl, decl.name });
   5513 
   5514     const gpa = mod.gpa;
   5515     try mod.deletion_set.ensureUnusedCapacity(gpa, decl.dependencies.count());
   5516 
   5517     if (outdated_decls) |map| {
   5518         _ = map.swapRemove(decl_index);
   5519         try map.ensureUnusedCapacity(decl.dependants.count());
   5520     }
   5521 
   5522     // Remove itself from its dependencies.
   5523     for (decl.dependencies.keys()) |dep_index| {
   5524         const dep = mod.declPtr(dep_index);
   5525         dep.removeDependant(decl_index);
   5526         if (dep.dependants.count() == 0 and !dep.deletion_flag) {
   5527             log.debug("insert {*} ({s}) dependant {*} ({s}) into deletion set", .{
   5528                 decl, decl.name, dep, dep.name,
   5529             });
   5530             // We don't recursively perform a deletion here, because during the update,
   5531             // another reference to it may turn up.
   5532             dep.deletion_flag = true;
   5533             mod.deletion_set.putAssumeCapacity(dep_index, {});
   5534         }
   5535     }
   5536     decl.dependencies.clearRetainingCapacity();
   5537 
   5538     // Anything that depends on this deleted decl needs to be re-analyzed.
   5539     for (decl.dependants.keys()) |dep_index| {
   5540         const dep = mod.declPtr(dep_index);
   5541         dep.removeDependency(decl_index);
   5542         if (outdated_decls) |map| {
   5543             map.putAssumeCapacity(dep_index, {});
   5544         }
   5545     }
   5546     decl.dependants.clearRetainingCapacity();
   5547 
   5548     if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {
   5549         kv.value.destroy(gpa);
   5550     }
   5551     if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
   5552         for (kv.value) |err| err.deinit(gpa);
   5553     }
   5554     if (mod.emit_h) |emit_h| {
   5555         if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
   5556             kv.value.destroy(gpa);
   5557         }
   5558         assert(emit_h.decl_table.swapRemove(decl_index));
   5559     }
   5560     _ = mod.compile_log_decls.swapRemove(decl_index);
   5561     try mod.deleteDeclExports(decl_index);
   5562 
   5563     if (decl.has_tv) {
   5564         if (decl.ty.isFnOrHasRuntimeBits(mod)) {
   5565             mod.comp.bin_file.freeDecl(decl_index);
   5566         }
   5567         if (decl.getInnerNamespace()) |namespace| {
   5568             try namespace.deleteAllDecls(mod, outdated_decls);
   5569         }
   5570     }
   5571     decl.clearValues(mod);
   5572 
   5573     if (decl.deletion_flag) {
   5574         decl.deletion_flag = false;
   5575         assert(mod.deletion_set.swapRemove(decl_index));
   5576     }
   5577 
   5578     decl.analysis = .unreferenced;
   5579 }
   5580 
   5581 /// This function is exclusively called for anonymous decls.
   5582 pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {
   5583     const decl = mod.declPtr(decl_index);
   5584     log.debug("deleteUnusedDecl {d} ({s})", .{ decl_index, decl.name });
   5585 
   5586     assert(!mod.declIsRoot(decl_index));
   5587     assert(decl.src_namespace.anon_decls.swapRemove(decl_index));
   5588 
   5589     const dependants = decl.dependants.keys();
   5590     for (dependants) |dep| {
   5591         mod.declPtr(dep).removeDependency(decl_index);
   5592     }
   5593 
   5594     for (decl.dependencies.keys()) |dep| {
   5595         mod.declPtr(dep).removeDependant(decl_index);
   5596     }
   5597     mod.destroyDecl(decl_index);
   5598 }
   5599 
   5600 /// We don't perform a deletion here, because this Decl or another one
   5601 /// may end up referencing it before the update is complete.
   5602 fn markDeclForDeletion(mod: *Module, decl_index: Decl.Index) !void {
   5603     const decl = mod.declPtr(decl_index);
   5604     decl.deletion_flag = true;
   5605     try mod.deletion_set.put(mod.gpa, decl_index, {});
   5606 }
   5607 
   5608 /// Cancel the creation of an anon decl and delete any references to it.
   5609 /// If other decls depend on this decl, they must be aborted first.
   5610 pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
   5611     const decl = mod.declPtr(decl_index);
   5612     log.debug("abortAnonDecl {*} ({s})", .{ decl, decl.name });
   5613 
   5614     assert(!mod.declIsRoot(decl_index));
   5615     assert(decl.src_namespace.anon_decls.swapRemove(decl_index));
   5616 
   5617     // An aborted decl must not have dependants -- they must have
   5618     // been aborted first and removed from this list.
   5619     assert(decl.dependants.count() == 0);
   5620 
   5621     for (decl.dependencies.keys()) |dep_index| {
   5622         const dep = mod.declPtr(dep_index);
   5623         dep.removeDependant(decl_index);
   5624     }
   5625 
   5626     mod.destroyDecl(decl_index);
   5627 }
   5628 
   5629 /// Delete all the Export objects that are caused by this Decl. Re-analysis of
   5630 /// this Decl will cause them to be re-created (or not).
   5631 fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
   5632     var export_owners = (mod.export_owners.fetchSwapRemove(decl_index) orelse return).value;
   5633 
   5634     for (export_owners.items) |exp| {
   5635         if (mod.decl_exports.getPtr(exp.exported_decl)) |value_ptr| {
   5636             // Remove exports with owner_decl matching the regenerating decl.
   5637             const list = value_ptr.items;
   5638             var i: usize = 0;
   5639             var new_len = list.len;
   5640             while (i < new_len) {
   5641                 if (list[i].owner_decl == decl_index) {
   5642                     mem.copyBackwards(*Export, list[i..], list[i + 1 .. new_len]);
   5643                     new_len -= 1;
   5644                 } else {
   5645                     i += 1;
   5646                 }
   5647             }
   5648             value_ptr.shrinkAndFree(mod.gpa, new_len);
   5649             if (new_len == 0) {
   5650                 assert(mod.decl_exports.swapRemove(exp.exported_decl));
   5651             }
   5652         }
   5653         if (mod.comp.bin_file.cast(link.File.Elf)) |elf| {
   5654             elf.deleteDeclExport(decl_index, exp.options.name);
   5655         }
   5656         if (mod.comp.bin_file.cast(link.File.MachO)) |macho| {
   5657             try macho.deleteDeclExport(decl_index, exp.options.name);
   5658         }
   5659         if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {
   5660             wasm.deleteDeclExport(decl_index);
   5661         }
   5662         if (mod.comp.bin_file.cast(link.File.Coff)) |coff| {
   5663             coff.deleteDeclExport(decl_index, exp.options.name);
   5664         }
   5665         if (mod.failed_exports.fetchSwapRemove(exp)) |failed_kv| {
   5666             failed_kv.value.destroy(mod.gpa);
   5667         }
   5668         mod.gpa.free(exp.options.name);
   5669         mod.gpa.destroy(exp);
   5670     }
   5671     export_owners.deinit(mod.gpa);
   5672 }
   5673 
   5674 pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
   5675     const tracy = trace(@src());
   5676     defer tracy.end();
   5677 
   5678     const gpa = mod.gpa;
   5679     const decl_index = func.owner_decl;
   5680     const decl = mod.declPtr(decl_index);
   5681 
   5682     // Use the Decl's arena for captured values.
   5683     var decl_arena: std.heap.ArenaAllocator = undefined;
   5684     const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);
   5685     defer decl.value_arena.?.release(&decl_arena);
   5686 
   5687     var sema: Sema = .{
   5688         .mod = mod,
   5689         .gpa = gpa,
   5690         .arena = arena,
   5691         .perm_arena = decl_arena_allocator,
   5692         .code = decl.getFileScope().zir,
   5693         .owner_decl = decl,
   5694         .owner_decl_index = decl_index,
   5695         .func = func,
   5696         .fn_ret_ty = decl.ty.fnReturnType(),
   5697         .owner_func = func,
   5698         .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
   5699     };
   5700     defer sema.deinit();
   5701 
   5702     // reset in case calls to errorable functions are removed.
   5703     func.calls_or_awaits_errorable_fn = false;
   5704 
   5705     // First few indexes of extra are reserved and set at the end.
   5706     const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;
   5707     try sema.air_extra.ensureTotalCapacity(gpa, reserved_count);
   5708     sema.air_extra.items.len += reserved_count;
   5709 
   5710     var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);
   5711     defer wip_captures.deinit();
   5712 
   5713     var inner_block: Sema.Block = .{
   5714         .parent = null,
   5715         .sema = &sema,
   5716         .src_decl = decl_index,
   5717         .namespace = decl.src_namespace,
   5718         .wip_capture_scope = wip_captures.scope,
   5719         .instructions = .{},
   5720         .inlining = null,
   5721         .is_comptime = false,
   5722     };
   5723     defer inner_block.instructions.deinit(gpa);
   5724 
   5725     const fn_info = sema.code.getFnInfo(func.zir_body_inst);
   5726     const zir_tags = sema.code.instructions.items(.tag);
   5727 
   5728     // Here we are performing "runtime semantic analysis" for a function body, which means
   5729     // we must map the parameter ZIR instructions to `arg` AIR instructions.
   5730     // AIR requires the `arg` parameters to be the first N instructions.
   5731     // This could be a generic function instantiation, however, in which case we need to
   5732     // map the comptime parameters to constant values and only emit arg AIR instructions
   5733     // for the runtime ones.
   5734     const fn_ty = decl.ty;
   5735     const fn_ty_info = fn_ty.fnInfo();
   5736     const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);
   5737     try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
   5738     try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
   5739     try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
   5740 
   5741     var runtime_param_index: usize = 0;
   5742     var total_param_index: usize = 0;
   5743     for (fn_info.param_body) |inst| {
   5744         switch (zir_tags[inst]) {
   5745             .param, .param_comptime, .param_anytype, .param_anytype_comptime => {},
   5746             else => continue,
   5747         }
   5748         const param_ty = if (func.comptime_args) |comptime_args| t: {
   5749             const arg_tv = comptime_args[total_param_index];
   5750 
   5751             const arg_val = if (!arg_tv.val.isGenericPoison())
   5752                 arg_tv.val
   5753             else if (try arg_tv.ty.onePossibleValue(mod)) |opv|
   5754                 opv
   5755             else
   5756                 break :t arg_tv.ty;
   5757 
   5758             const arg = try sema.addConstant(arg_tv.ty, arg_val);
   5759             sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
   5760             total_param_index += 1;
   5761             continue;
   5762         } else fn_ty_info.param_types[runtime_param_index];
   5763 
   5764         const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
   5765             error.NeededSourceLocation => unreachable,
   5766             error.GenericPoison => unreachable,
   5767             error.ComptimeReturn => unreachable,
   5768             error.ComptimeBreak => unreachable,
   5769             else => |e| return e,
   5770         };
   5771         if (opt_opv) |opv| {
   5772             const arg = try sema.addConstant(param_ty, opv);
   5773             sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
   5774             total_param_index += 1;
   5775             runtime_param_index += 1;
   5776             continue;
   5777         }
   5778         const air_ty = try sema.addType(param_ty);
   5779         const arg_index = @intCast(u32, sema.air_instructions.len);
   5780         inner_block.instructions.appendAssumeCapacity(arg_index);
   5781         sema.air_instructions.appendAssumeCapacity(.{
   5782             .tag = .arg,
   5783             .data = .{ .arg = .{
   5784                 .ty = air_ty,
   5785                 .src_index = @intCast(u32, total_param_index),
   5786             } },
   5787         });
   5788         sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
   5789         total_param_index += 1;
   5790         runtime_param_index += 1;
   5791     }
   5792 
   5793     func.state = .in_progress;
   5794     log.debug("set {s} to in_progress", .{decl.name});
   5795 
   5796     const last_arg_index = inner_block.instructions.items.len;
   5797 
   5798     // Save the error trace as our first action in the function.
   5799     // If this is unnecessary after all, Liveness will clean it up for us.
   5800     const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&inner_block);
   5801     sema.error_return_trace_index_on_fn_entry = error_return_trace_index;
   5802     inner_block.error_return_trace_index = error_return_trace_index;
   5803 
   5804     sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
   5805         // TODO make these unreachable instead of @panic
   5806         error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
   5807         error.GenericPoison => @panic("zig compiler bug: GenericPoison"),
   5808         error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"),
   5809         else => |e| return e,
   5810     };
   5811 
   5812     {
   5813         var it = sema.unresolved_inferred_allocs.keyIterator();
   5814         while (it.next()) |ptr_inst| {
   5815             // The lack of a resolve_inferred_alloc means that this instruction
   5816             // is unused so it just has to be a no-op.
   5817             sema.air_instructions.set(ptr_inst.*, .{
   5818                 .tag = .alloc,
   5819                 .data = .{ .ty = Type.single_const_pointer_to_comptime_int },
   5820             });
   5821         }
   5822     }
   5823 
   5824     // If we don't get an error return trace from a caller, create our own.
   5825     if (func.calls_or_awaits_errorable_fn and
   5826         mod.comp.bin_file.options.error_return_tracing and
   5827         !sema.fn_ret_ty.isError(mod))
   5828     {
   5829         sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
   5830             // TODO make these unreachable instead of @panic
   5831             error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
   5832             error.GenericPoison => @panic("zig compiler bug: GenericPoison"),
   5833             error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"),
   5834             error.ComptimeBreak => @panic("zig compiler bug: ComptimeBreak"),
   5835             else => |e| return e,
   5836         };
   5837     }
   5838 
   5839     try wip_captures.finalize();
   5840 
   5841     // Copy the block into place and mark that as the main block.
   5842     try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
   5843         inner_block.instructions.items.len);
   5844     const main_block_index = sema.addExtraAssumeCapacity(Air.Block{
   5845         .body_len = @intCast(u32, inner_block.instructions.items.len),
   5846     });
   5847     sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
   5848     sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = main_block_index;
   5849 
   5850     func.state = .success;
   5851     log.debug("set {s} to success", .{decl.name});
   5852 
   5853     // Finally we must resolve the return type and parameter types so that backends
   5854     // have full access to type information.
   5855     // Crucially, this happens *after* we set the function state to success above,
   5856     // so that dependencies on the function body will now be satisfied rather than
   5857     // result in circular dependency errors.
   5858     sema.resolveFnTypes(fn_ty_info) catch |err| switch (err) {
   5859         error.NeededSourceLocation => unreachable,
   5860         error.GenericPoison => unreachable,
   5861         error.ComptimeReturn => unreachable,
   5862         error.ComptimeBreak => unreachable,
   5863         error.AnalysisFail => {
   5864             // In this case our function depends on a type that had a compile error.
   5865             // We should not try to lower this function.
   5866             decl.analysis = .dependency_failure;
   5867             return error.AnalysisFail;
   5868         },
   5869         else => |e| return e,
   5870     };
   5871 
   5872     // Similarly, resolve any queued up types that were requested to be resolved for
   5873     // the backends.
   5874     for (sema.types_to_resolve.items) |inst_ref| {
   5875         const ty = sema.getTmpAir().getRefType(inst_ref);
   5876         sema.resolveTypeFully(ty) catch |err| switch (err) {
   5877             error.NeededSourceLocation => unreachable,
   5878             error.GenericPoison => unreachable,
   5879             error.ComptimeReturn => unreachable,
   5880             error.ComptimeBreak => unreachable,
   5881             error.AnalysisFail => {
   5882                 // In this case our function depends on a type that had a compile error.
   5883                 // We should not try to lower this function.
   5884                 decl.analysis = .dependency_failure;
   5885                 return error.AnalysisFail;
   5886             },
   5887             else => |e| return e,
   5888         };
   5889     }
   5890 
   5891     return Air{
   5892         .instructions = sema.air_instructions.toOwnedSlice(),
   5893         .extra = try sema.air_extra.toOwnedSlice(gpa),
   5894         .values = try sema.air_values.toOwnedSlice(gpa),
   5895     };
   5896 }
   5897 
   5898 fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
   5899     const decl = mod.declPtr(decl_index);
   5900     log.debug("mark outdated {*} ({s})", .{ decl, decl.name });
   5901     try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl_index });
   5902     if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {
   5903         kv.value.destroy(mod.gpa);
   5904     }
   5905     if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
   5906         for (kv.value) |err| err.deinit(mod.gpa);
   5907     }
   5908     if (decl.has_tv and decl.owns_tv) {
   5909         if (decl.val.castTag(.function)) |payload| {
   5910             const func = payload.data;
   5911             _ = mod.align_stack_fns.remove(func);
   5912         }
   5913     }
   5914     if (mod.emit_h) |emit_h| {
   5915         if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
   5916             kv.value.destroy(mod.gpa);
   5917         }
   5918     }
   5919     _ = mod.compile_log_decls.swapRemove(decl_index);
   5920     decl.analysis = .outdated;
   5921 }
   5922 
   5923 pub fn allocateNewDecl(
   5924     mod: *Module,
   5925     namespace: *Namespace,
   5926     src_node: Ast.Node.Index,
   5927     src_scope: ?*CaptureScope,
   5928 ) !Decl.Index {
   5929     const decl_and_index: struct {
   5930         new_decl: *Decl,
   5931         decl_index: Decl.Index,
   5932     } = if (mod.decls_free_list.popOrNull()) |decl_index| d: {
   5933         break :d .{
   5934             .new_decl = mod.declPtr(decl_index),
   5935             .decl_index = decl_index,
   5936         };
   5937     } else d: {
   5938         const decl = try mod.allocated_decls.addOne(mod.gpa);
   5939         errdefer mod.allocated_decls.shrinkRetainingCapacity(mod.allocated_decls.len - 1);
   5940         if (mod.emit_h) |mod_emit_h| {
   5941             const decl_emit_h = try mod_emit_h.allocated_emit_h.addOne(mod.gpa);
   5942             decl_emit_h.* = .{};
   5943         }
   5944         break :d .{
   5945             .new_decl = decl,
   5946             .decl_index = @intToEnum(Decl.Index, mod.allocated_decls.len - 1),
   5947         };
   5948     };
   5949 
   5950     decl_and_index.new_decl.* = .{
   5951         .name = undefined,
   5952         .src_namespace = namespace,
   5953         .src_node = src_node,
   5954         .src_line = undefined,
   5955         .has_tv = false,
   5956         .owns_tv = false,
   5957         .ty = undefined,
   5958         .val = undefined,
   5959         .@"align" = undefined,
   5960         .@"linksection" = undefined,
   5961         .@"addrspace" = .generic,
   5962         .analysis = .unreferenced,
   5963         .deletion_flag = false,
   5964         .zir_decl_index = 0,
   5965         .src_scope = src_scope,
   5966         .generation = 0,
   5967         .is_pub = false,
   5968         .is_exported = false,
   5969         .has_linksection_or_addrspace = false,
   5970         .has_align = false,
   5971         .alive = false,
   5972         .kind = .anon,
   5973     };
   5974 
   5975     return decl_and_index.decl_index;
   5976 }
   5977 
   5978 /// Get error value for error tag `name`.
   5979 pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).KV {
   5980     const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
   5981     if (gop.found_existing) {
   5982         return std.StringHashMapUnmanaged(ErrorInt).KV{
   5983             .key = gop.key_ptr.*,
   5984             .value = gop.value_ptr.*,
   5985         };
   5986     }
   5987 
   5988     errdefer assert(mod.global_error_set.remove(name));
   5989     try mod.error_name_list.ensureUnusedCapacity(mod.gpa, 1);
   5990     gop.key_ptr.* = try mod.gpa.dupe(u8, name);
   5991     gop.value_ptr.* = @intCast(ErrorInt, mod.error_name_list.items.len);
   5992     mod.error_name_list.appendAssumeCapacity(gop.key_ptr.*);
   5993     return std.StringHashMapUnmanaged(ErrorInt).KV{
   5994         .key = gop.key_ptr.*,
   5995         .value = gop.value_ptr.*,
   5996     };
   5997 }
   5998 
   5999 pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {
   6000     const src_decl = mod.declPtr(block.src_decl);
   6001     return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value);
   6002 }
   6003 
   6004 pub fn createAnonymousDeclFromDecl(
   6005     mod: *Module,
   6006     src_decl: *Decl,
   6007     namespace: *Namespace,
   6008     src_scope: ?*CaptureScope,
   6009     tv: TypedValue,
   6010 ) !Decl.Index {
   6011     const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope);
   6012     errdefer mod.destroyDecl(new_decl_index);
   6013     const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
   6014         src_decl.name, @enumToInt(new_decl_index),
   6015     });
   6016     try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name);
   6017     return new_decl_index;
   6018 }
   6019 
   6020 /// Takes ownership of `name` even if it returns an error.
   6021 pub fn initNewAnonDecl(
   6022     mod: *Module,
   6023     new_decl_index: Decl.Index,
   6024     src_line: u32,
   6025     namespace: *Namespace,
   6026     typed_value: TypedValue,
   6027     name: [:0]u8,
   6028 ) !void {
   6029     errdefer mod.gpa.free(name);
   6030 
   6031     const new_decl = mod.declPtr(new_decl_index);
   6032 
   6033     new_decl.name = name;
   6034     new_decl.src_line = src_line;
   6035     new_decl.ty = typed_value.ty;
   6036     new_decl.val = typed_value.val;
   6037     new_decl.@"align" = 0;
   6038     new_decl.@"linksection" = null;
   6039     new_decl.has_tv = true;
   6040     new_decl.analysis = .complete;
   6041     new_decl.generation = mod.generation;
   6042 
   6043     try namespace.anon_decls.putNoClobber(mod.gpa, new_decl_index, {});
   6044 
   6045     // The Decl starts off with alive=false and the codegen backend will set alive=true
   6046     // if the Decl is referenced by an instruction or another constant. Otherwise,
   6047     // the Decl will be garbage collected by the `codegen_decl` task instead of sent
   6048     // to the linker.
   6049     if (typed_value.ty.isFnOrHasRuntimeBits(mod)) {
   6050         try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index });
   6051     }
   6052 }
   6053 
   6054 pub fn errNoteNonLazy(
   6055     mod: *Module,
   6056     src_loc: SrcLoc,
   6057     parent: *ErrorMsg,
   6058     comptime format: []const u8,
   6059     args: anytype,
   6060 ) error{OutOfMemory}!void {
   6061     if (src_loc.lazy == .unneeded) {
   6062         assert(parent.src_loc.lazy == .unneeded);
   6063         return;
   6064     }
   6065     const msg = try std.fmt.allocPrint(mod.gpa, format, args);
   6066     errdefer mod.gpa.free(msg);
   6067 
   6068     parent.notes = try mod.gpa.realloc(parent.notes, parent.notes.len + 1);
   6069     parent.notes[parent.notes.len - 1] = .{
   6070         .src_loc = src_loc,
   6071         .msg = msg,
   6072     };
   6073 }
   6074 
   6075 pub fn getTarget(mod: Module) Target {
   6076     return mod.comp.bin_file.options.target;
   6077 }
   6078 
   6079 pub fn optimizeMode(mod: Module) std.builtin.Mode {
   6080     return mod.comp.bin_file.options.optimize_mode;
   6081 }
   6082 
   6083 fn lockAndClearFileCompileError(mod: *Module, file: *File) void {
   6084     switch (file.status) {
   6085         .success_zir, .retryable_failure => {},
   6086         .never_loaded, .parse_failure, .astgen_failure => {
   6087             mod.comp.mutex.lock();
   6088             defer mod.comp.mutex.unlock();
   6089             if (mod.failed_files.fetchSwapRemove(file)) |kv| {
   6090                 if (kv.value) |msg| msg.destroy(mod.gpa); // Delete previous error message.
   6091             }
   6092         },
   6093     }
   6094 }
   6095 
   6096 pub const SwitchProngSrc = union(enum) {
   6097     scalar: u32,
   6098     multi: Multi,
   6099     range: Multi,
   6100     multi_capture: u32,
   6101 
   6102     pub const Multi = struct {
   6103         prong: u32,
   6104         item: u32,
   6105     };
   6106 
   6107     pub const RangeExpand = enum { none, first, last };
   6108 
   6109     /// This function is intended to be called only when it is certain that we need
   6110     /// the LazySrcLoc in order to emit a compile error.
   6111     pub fn resolve(
   6112         prong_src: SwitchProngSrc,
   6113         gpa: Allocator,
   6114         decl: *Decl,
   6115         switch_node_offset: i32,
   6116         range_expand: RangeExpand,
   6117     ) LazySrcLoc {
   6118         @setCold(true);
   6119         const tree = decl.getFileScope().getTree(gpa) catch |err| {
   6120             // In this case we emit a warning + a less precise source location.
   6121             log.warn("unable to load {s}: {s}", .{
   6122                 decl.getFileScope().sub_file_path, @errorName(err),
   6123             });
   6124             return LazySrcLoc.nodeOffset(0);
   6125         };
   6126         const switch_node = decl.relativeToNodeIndex(switch_node_offset);
   6127         const main_tokens = tree.nodes.items(.main_token);
   6128         const node_datas = tree.nodes.items(.data);
   6129         const node_tags = tree.nodes.items(.tag);
   6130         const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
   6131         const case_nodes = tree.extra_data[extra.start..extra.end];
   6132 
   6133         var multi_i: u32 = 0;
   6134         var scalar_i: u32 = 0;
   6135         for (case_nodes) |case_node| {
   6136             const case = tree.fullSwitchCase(case_node).?;
   6137             if (case.ast.values.len == 0)
   6138                 continue;
   6139             if (case.ast.values.len == 1 and
   6140                 node_tags[case.ast.values[0]] == .identifier and
   6141                 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
   6142             {
   6143                 continue;
   6144             }
   6145             const is_multi = case.ast.values.len != 1 or
   6146                 node_tags[case.ast.values[0]] == .switch_range;
   6147 
   6148             switch (prong_src) {
   6149                 .scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc.nodeOffset(
   6150                     decl.nodeIndexToRelative(case.ast.values[0]),
   6151                 ),
   6152                 .multi_capture => |i| if (is_multi and i == multi_i) {
   6153                     return LazySrcLoc{ .node_offset_switch_prong_capture = decl.nodeIndexToRelative(case_node) };
   6154                 },
   6155                 .multi => |s| if (is_multi and s.prong == multi_i) {
   6156                     var item_i: u32 = 0;
   6157                     for (case.ast.values) |item_node| {
   6158                         if (node_tags[item_node] == .switch_range) continue;
   6159 
   6160                         if (item_i == s.item) return LazySrcLoc.nodeOffset(
   6161                             decl.nodeIndexToRelative(item_node),
   6162                         );
   6163                         item_i += 1;
   6164                     } else unreachable;
   6165                 },
   6166                 .range => |s| if (is_multi and s.prong == multi_i) {
   6167                     var range_i: u32 = 0;
   6168                     for (case.ast.values) |range| {
   6169                         if (node_tags[range] != .switch_range) continue;
   6170 
   6171                         if (range_i == s.item) switch (range_expand) {
   6172                             .none => return LazySrcLoc.nodeOffset(
   6173                                 decl.nodeIndexToRelative(range),
   6174                             ),
   6175                             .first => return LazySrcLoc.nodeOffset(
   6176                                 decl.nodeIndexToRelative(node_datas[range].lhs),
   6177                             ),
   6178                             .last => return LazySrcLoc.nodeOffset(
   6179                                 decl.nodeIndexToRelative(node_datas[range].rhs),
   6180                             ),
   6181                         };
   6182                         range_i += 1;
   6183                     } else unreachable;
   6184                 },
   6185             }
   6186             if (is_multi) {
   6187                 multi_i += 1;
   6188             } else {
   6189                 scalar_i += 1;
   6190             }
   6191         } else unreachable;
   6192     }
   6193 };
   6194 
   6195 pub const PeerTypeCandidateSrc = union(enum) {
   6196     /// Do not print out error notes for candidate sources
   6197     none: void,
   6198     /// When we want to know the the src of candidate i, look up at
   6199     /// index i in this slice
   6200     override: []const ?LazySrcLoc,
   6201     /// resolvePeerTypes originates from a @TypeOf(...) call
   6202     typeof_builtin_call_node_offset: i32,
   6203 
   6204     pub fn resolve(
   6205         self: PeerTypeCandidateSrc,
   6206         gpa: Allocator,
   6207         decl: *Decl,
   6208         candidate_i: usize,
   6209     ) ?LazySrcLoc {
   6210         @setCold(true);
   6211 
   6212         switch (self) {
   6213             .none => {
   6214                 return null;
   6215             },
   6216             .override => |candidate_srcs| {
   6217                 if (candidate_i >= candidate_srcs.len)
   6218                     return null;
   6219                 return candidate_srcs[candidate_i];
   6220             },
   6221             .typeof_builtin_call_node_offset => |node_offset| {
   6222                 switch (candidate_i) {
   6223                     0 => return LazySrcLoc{ .node_offset_builtin_call_arg0 = node_offset },
   6224                     1 => return LazySrcLoc{ .node_offset_builtin_call_arg1 = node_offset },
   6225                     2 => return LazySrcLoc{ .node_offset_builtin_call_arg2 = node_offset },
   6226                     3 => return LazySrcLoc{ .node_offset_builtin_call_arg3 = node_offset },
   6227                     4 => return LazySrcLoc{ .node_offset_builtin_call_arg4 = node_offset },
   6228                     5 => return LazySrcLoc{ .node_offset_builtin_call_arg5 = node_offset },
   6229                     else => {},
   6230                 }
   6231 
   6232                 const tree = decl.getFileScope().getTree(gpa) catch |err| {
   6233                     // In this case we emit a warning + a less precise source location.
   6234                     log.warn("unable to load {s}: {s}", .{
   6235                         decl.getFileScope().sub_file_path, @errorName(err),
   6236                     });
   6237                     return LazySrcLoc.nodeOffset(0);
   6238                 };
   6239                 const node = decl.relativeToNodeIndex(node_offset);
   6240                 const node_datas = tree.nodes.items(.data);
   6241                 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
   6242 
   6243                 return LazySrcLoc{ .node_abs = params[candidate_i] };
   6244             },
   6245         }
   6246     }
   6247 };
   6248 
   6249 const FieldSrcQuery = struct {
   6250     index: usize,
   6251     range: enum { name, type, value, alignment } = .name,
   6252 };
   6253 
   6254 fn queryFieldSrc(
   6255     tree: Ast,
   6256     query: FieldSrcQuery,
   6257     file_scope: *File,
   6258     container_decl: Ast.full.ContainerDecl,
   6259 ) SrcLoc {
   6260     var field_index: usize = 0;
   6261     for (container_decl.ast.members) |member_node| {
   6262         const field = tree.fullContainerField(member_node) orelse continue;
   6263         if (field_index == query.index) {
   6264             return switch (query.range) {
   6265                 .name => .{
   6266                     .file_scope = file_scope,
   6267                     .parent_decl_node = 0,
   6268                     .lazy = .{ .token_abs = field.ast.main_token },
   6269                 },
   6270                 .type => .{
   6271                     .file_scope = file_scope,
   6272                     .parent_decl_node = 0,
   6273                     .lazy = .{ .node_abs = field.ast.type_expr },
   6274                 },
   6275                 .value => .{
   6276                     .file_scope = file_scope,
   6277                     .parent_decl_node = 0,
   6278                     .lazy = .{ .node_abs = field.ast.value_expr },
   6279                 },
   6280                 .alignment => .{
   6281                     .file_scope = file_scope,
   6282                     .parent_decl_node = 0,
   6283                     .lazy = .{ .node_abs = field.ast.align_expr },
   6284                 },
   6285             };
   6286         }
   6287         field_index += 1;
   6288     }
   6289     unreachable;
   6290 }
   6291 
   6292 pub fn paramSrc(
   6293     func_node_offset: i32,
   6294     gpa: Allocator,
   6295     decl: *Decl,
   6296     param_i: usize,
   6297 ) LazySrcLoc {
   6298     @setCold(true);
   6299     const tree = decl.getFileScope().getTree(gpa) catch |err| {
   6300         // In this case we emit a warning + a less precise source location.
   6301         log.warn("unable to load {s}: {s}", .{
   6302             decl.getFileScope().sub_file_path, @errorName(err),
   6303         });
   6304         return LazySrcLoc.nodeOffset(0);
   6305     };
   6306     const node = decl.relativeToNodeIndex(func_node_offset);
   6307     var buf: [1]Ast.Node.Index = undefined;
   6308     const full = tree.fullFnProto(&buf, node).?;
   6309     var it = full.iterate(tree);
   6310     var i: usize = 0;
   6311     while (it.next()) |param| : (i += 1) {
   6312         if (i == param_i) {
   6313             if (param.anytype_ellipsis3) |some| {
   6314                 const main_token = tree.nodes.items(.main_token)[decl.src_node];
   6315                 return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) };
   6316             }
   6317             return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) };
   6318         }
   6319     }
   6320     unreachable;
   6321 }
   6322 
   6323 pub fn argSrc(
   6324     call_node_offset: i32,
   6325     gpa: Allocator,
   6326     decl: *Decl,
   6327     start_arg_i: usize,
   6328     bound_arg_src: ?LazySrcLoc,
   6329 ) LazySrcLoc {
   6330     if (start_arg_i == 0 and bound_arg_src != null) return bound_arg_src.?;
   6331     const arg_i = start_arg_i - @boolToInt(bound_arg_src != null);
   6332     @setCold(true);
   6333     const tree = decl.getFileScope().getTree(gpa) catch |err| {
   6334         // In this case we emit a warning + a less precise source location.
   6335         log.warn("unable to load {s}: {s}", .{
   6336             decl.getFileScope().sub_file_path, @errorName(err),
   6337         });
   6338         return LazySrcLoc.nodeOffset(0);
   6339     };
   6340     const node_tags = tree.nodes.items(.tag);
   6341     const node = decl.relativeToNodeIndex(call_node_offset);
   6342     var args: [1]Ast.Node.Index = undefined;
   6343     const full = switch (node_tags[node]) {
   6344         .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&args, node),
   6345         .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
   6346         .builtin_call => {
   6347             const node_datas = tree.nodes.items(.data);
   6348             const call_args_node = tree.extra_data[node_datas[node].rhs - 1];
   6349             const call_args_offset = decl.nodeIndexToRelative(call_args_node);
   6350             return initSrc(call_args_offset, gpa, decl, arg_i);
   6351         },
   6352         else => unreachable,
   6353     };
   6354     return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full.ast.params[arg_i]));
   6355 }
   6356 
   6357 pub fn initSrc(
   6358     init_node_offset: i32,
   6359     gpa: Allocator,
   6360     decl: *Decl,
   6361     init_index: usize,
   6362 ) LazySrcLoc {
   6363     @setCold(true);
   6364     const tree = decl.getFileScope().getTree(gpa) catch |err| {
   6365         // In this case we emit a warning + a less precise source location.
   6366         log.warn("unable to load {s}: {s}", .{
   6367             decl.getFileScope().sub_file_path, @errorName(err),
   6368         });
   6369         return LazySrcLoc.nodeOffset(0);
   6370     };
   6371     const node_tags = tree.nodes.items(.tag);
   6372     const node = decl.relativeToNodeIndex(init_node_offset);
   6373     var buf: [2]Ast.Node.Index = undefined;
   6374     switch (node_tags[node]) {
   6375         .array_init_one,
   6376         .array_init_one_comma,
   6377         .array_init_dot_two,
   6378         .array_init_dot_two_comma,
   6379         .array_init_dot,
   6380         .array_init_dot_comma,
   6381         .array_init,
   6382         .array_init_comma,
   6383         => {
   6384             const full = tree.fullArrayInit(&buf, node).?.ast.elements;
   6385             return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full[init_index]));
   6386         },
   6387         .struct_init_one,
   6388         .struct_init_one_comma,
   6389         .struct_init_dot_two,
   6390         .struct_init_dot_two_comma,
   6391         .struct_init_dot,
   6392         .struct_init_dot_comma,
   6393         .struct_init,
   6394         .struct_init_comma,
   6395         => {
   6396             const full = tree.fullStructInit(&buf, node).?.ast.fields;
   6397             return LazySrcLoc{ .node_offset_initializer = decl.nodeIndexToRelative(full[init_index]) };
   6398         },
   6399         else => return LazySrcLoc.nodeOffset(init_node_offset),
   6400     }
   6401 }
   6402 
   6403 pub fn optionsSrc(gpa: Allocator, decl: *Decl, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {
   6404     @setCold(true);
   6405     const tree = decl.getFileScope().getTree(gpa) catch |err| {
   6406         // In this case we emit a warning + a less precise source location.
   6407         log.warn("unable to load {s}: {s}", .{
   6408             decl.getFileScope().sub_file_path, @errorName(err),
   6409         });
   6410         return LazySrcLoc.nodeOffset(0);
   6411     };
   6412 
   6413     const o_i: struct { off: i32, i: u8 } = switch (base_src) {
   6414         .node_offset_builtin_call_arg0 => |n| .{ .off = n, .i = 0 },
   6415         .node_offset_builtin_call_arg1 => |n| .{ .off = n, .i = 1 },
   6416         else => unreachable,
   6417     };
   6418 
   6419     const node = decl.relativeToNodeIndex(o_i.off);
   6420     const node_datas = tree.nodes.items(.data);
   6421     const node_tags = tree.nodes.items(.tag);
   6422     const arg_node = switch (node_tags[node]) {
   6423         .builtin_call_two, .builtin_call_two_comma => switch (o_i.i) {
   6424             0 => node_datas[node].lhs,
   6425             1 => node_datas[node].rhs,
   6426             else => unreachable,
   6427         },
   6428         .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + o_i.i],
   6429         else => unreachable,
   6430     };
   6431     var buf: [2]std.zig.Ast.Node.Index = undefined;
   6432     const init_nodes = if (tree.fullStructInit(&buf, arg_node)) |struct_init| struct_init.ast.fields else return base_src;
   6433     for (init_nodes) |init_node| {
   6434         // . IDENTIFIER = init_node
   6435         const name_token = tree.firstToken(init_node) - 2;
   6436         const name = tree.tokenSlice(name_token);
   6437         if (std.mem.eql(u8, name, wanted)) {
   6438             return LazySrcLoc{ .node_offset_initializer = decl.nodeIndexToRelative(init_node) };
   6439         }
   6440     }
   6441     return base_src;
   6442 }
   6443 
   6444 /// Called from `performAllTheWork`, after all AstGen workers have finished,
   6445 /// and before the main semantic analysis loop begins.
   6446 pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
   6447     // Ultimately, the goal is to queue up `analyze_decl` tasks in the work queue
   6448     // for the outdated decls, but we cannot queue up the tasks until after
   6449     // we find out which ones have been deleted, otherwise there would be
   6450     // deleted Decl pointers in the work queue.
   6451     var outdated_decls = std.AutoArrayHashMap(Decl.Index, void).init(mod.gpa);
   6452     defer outdated_decls.deinit();
   6453     for (mod.import_table.values()) |file| {
   6454         try outdated_decls.ensureUnusedCapacity(file.outdated_decls.items.len);
   6455         for (file.outdated_decls.items) |decl_index| {
   6456             outdated_decls.putAssumeCapacity(decl_index, {});
   6457         }
   6458         file.outdated_decls.clearRetainingCapacity();
   6459 
   6460         // Handle explicitly deleted decls from the source code. This is one of two
   6461         // places that Decl deletions happen. The other is in `Compilation`, after
   6462         // `performAllTheWork`, where we iterate over `Module.deletion_set` and
   6463         // delete Decls which are no longer referenced.
   6464         // If a Decl is explicitly deleted from source, and also no longer referenced,
   6465         // it may be both in this `deleted_decls` set, as well as in the
   6466         // `Module.deletion_set`. To avoid deleting it twice, we remove it from the
   6467         // deletion set at this time.
   6468         for (file.deleted_decls.items) |decl_index| {
   6469             const decl = mod.declPtr(decl_index);
   6470             log.debug("deleted from source: {*} ({s})", .{ decl, decl.name });
   6471 
   6472             // Remove from the namespace it resides in, preserving declaration order.
   6473             assert(decl.zir_decl_index != 0);
   6474             _ = decl.src_namespace.decls.orderedRemoveAdapted(@as([]const u8, mem.sliceTo(decl.name, 0)), DeclAdapter{ .mod = mod });
   6475 
   6476             try mod.clearDecl(decl_index, &outdated_decls);
   6477             mod.destroyDecl(decl_index);
   6478         }
   6479         file.deleted_decls.clearRetainingCapacity();
   6480     }
   6481     // Finally we can queue up re-analysis tasks after we have processed
   6482     // the deleted decls.
   6483     for (outdated_decls.keys()) |key| {
   6484         try mod.markOutdatedDecl(key);
   6485     }
   6486 }
   6487 
   6488 /// Called from `Compilation.update`, after everything is done, just before
   6489 /// reporting compile errors. In this function we emit exported symbol collision
   6490 /// errors and communicate exported symbols to the linker backend.
   6491 pub fn processExports(mod: *Module) !void {
   6492     const gpa = mod.gpa;
   6493     // Map symbol names to `Export` for name collision detection.
   6494     var symbol_exports: std.StringArrayHashMapUnmanaged(*Export) = .{};
   6495     defer symbol_exports.deinit(gpa);
   6496 
   6497     var it = mod.decl_exports.iterator();
   6498     while (it.next()) |entry| {
   6499         const exported_decl = entry.key_ptr.*;
   6500         const exports = entry.value_ptr.items;
   6501         for (exports) |new_export| {
   6502             const gop = try symbol_exports.getOrPut(gpa, new_export.options.name);
   6503             if (gop.found_existing) {
   6504                 new_export.status = .failed_retryable;
   6505                 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
   6506                 const src_loc = new_export.getSrcLoc(mod);
   6507                 const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {s}", .{
   6508                     new_export.options.name,
   6509                 });
   6510                 errdefer msg.destroy(gpa);
   6511                 const other_export = gop.value_ptr.*;
   6512                 const other_src_loc = other_export.getSrcLoc(mod);
   6513                 try mod.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{});
   6514                 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
   6515                 new_export.status = .failed;
   6516             } else {
   6517                 gop.value_ptr.* = new_export;
   6518             }
   6519         }
   6520         mod.comp.bin_file.updateDeclExports(mod, exported_decl, exports) catch |err| switch (err) {
   6521             error.OutOfMemory => return error.OutOfMemory,
   6522             else => {
   6523                 const new_export = exports[0];
   6524                 new_export.status = .failed_retryable;
   6525                 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
   6526                 const src_loc = new_export.getSrcLoc(mod);
   6527                 const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{
   6528                     @errorName(err),
   6529                 });
   6530                 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
   6531             },
   6532         };
   6533     }
   6534 }
   6535 
   6536 pub fn populateTestFunctions(
   6537     mod: *Module,
   6538     main_progress_node: *std.Progress.Node,
   6539 ) !void {
   6540     const gpa = mod.gpa;
   6541     const builtin_pkg = mod.main_pkg.table.get("builtin").?;
   6542     const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;
   6543     const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?);
   6544     const builtin_namespace = root_decl.src_namespace;
   6545     const decl_index = builtin_namespace.decls.getKeyAdapted(@as([]const u8, "test_functions"), DeclAdapter{ .mod = mod }).?;
   6546     {
   6547         // We have to call `ensureDeclAnalyzed` here in case `builtin.test_functions`
   6548         // was not referenced by start code.
   6549         mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
   6550         mod.sema_prog_node.activate();
   6551         defer {
   6552             mod.sema_prog_node.end();
   6553             mod.sema_prog_node = undefined;
   6554         }
   6555         try mod.ensureDeclAnalyzed(decl_index);
   6556     }
   6557     const decl = mod.declPtr(decl_index);
   6558     var buf: Type.SlicePtrFieldTypeBuffer = undefined;
   6559     const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf, mod).childType(mod);
   6560 
   6561     const array_decl_index = d: {
   6562         // Add mod.test_functions to an array decl then make the test_functions
   6563         // decl reference it as a slice.
   6564         var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
   6565         errdefer new_decl_arena.deinit();
   6566         const arena = new_decl_arena.allocator();
   6567 
   6568         const test_fn_vals = try arena.alloc(Value, mod.test_functions.count());
   6569         const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{
   6570             .ty = try Type.Tag.array.create(arena, .{
   6571                 .len = test_fn_vals.len,
   6572                 .elem_type = try tmp_test_fn_ty.copy(arena),
   6573             }),
   6574             .val = try Value.Tag.aggregate.create(arena, test_fn_vals),
   6575         });
   6576         const array_decl = mod.declPtr(array_decl_index);
   6577 
   6578         // Add a dependency on each test name and function pointer.
   6579         try array_decl.dependencies.ensureUnusedCapacity(gpa, test_fn_vals.len * 2);
   6580 
   6581         for (mod.test_functions.keys(), 0..) |test_decl_index, i| {
   6582             const test_decl = mod.declPtr(test_decl_index);
   6583             const test_name_slice = mem.sliceTo(test_decl.name, 0);
   6584             const test_name_decl_index = n: {
   6585                 var name_decl_arena = std.heap.ArenaAllocator.init(gpa);
   6586                 errdefer name_decl_arena.deinit();
   6587                 const bytes = try name_decl_arena.allocator().dupe(u8, test_name_slice);
   6588                 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(array_decl, array_decl.src_namespace, null, .{
   6589                     .ty = try Type.array(name_decl_arena.allocator(), bytes.len, null, Type.u8, mod),
   6590                     .val = try Value.Tag.bytes.create(name_decl_arena.allocator(), bytes),
   6591                 });
   6592                 try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena);
   6593                 break :n test_name_decl_index;
   6594             };
   6595             array_decl.dependencies.putAssumeCapacityNoClobber(test_decl_index, .normal);
   6596             array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, .normal);
   6597             try mod.linkerUpdateDecl(test_name_decl_index);
   6598 
   6599             const field_vals = try arena.create([3]Value);
   6600             field_vals.* = .{
   6601                 try Value.Tag.slice.create(arena, .{
   6602                     .ptr = try Value.Tag.decl_ref.create(arena, test_name_decl_index),
   6603                     .len = try mod.intValue(Type.usize, test_name_slice.len),
   6604                 }), // name
   6605                 try Value.Tag.decl_ref.create(arena, test_decl_index), // func
   6606                 Value.null, // async_frame_size
   6607             };
   6608             test_fn_vals[i] = try Value.Tag.aggregate.create(arena, field_vals);
   6609         }
   6610 
   6611         try array_decl.finalizeNewArena(&new_decl_arena);
   6612         break :d array_decl_index;
   6613     };
   6614     try mod.linkerUpdateDecl(array_decl_index);
   6615 
   6616     {
   6617         var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
   6618         errdefer new_decl_arena.deinit();
   6619         const arena = new_decl_arena.allocator();
   6620 
   6621         {
   6622             // This copy accesses the old Decl Type/Value so it must be done before `clearValues`.
   6623             const new_ty = try Type.ptr(arena, mod, .{
   6624                 .size = .Slice,
   6625                 .pointee_type = try tmp_test_fn_ty.copy(arena),
   6626                 .mutable = false,
   6627                 .@"addrspace" = .generic,
   6628             });
   6629             const new_var = try gpa.create(Var);
   6630             errdefer gpa.destroy(new_var);
   6631             new_var.* = decl.val.castTag(.variable).?.data.*;
   6632             new_var.init = try Value.Tag.slice.create(arena, .{
   6633                 .ptr = try Value.Tag.decl_ref.create(arena, array_decl_index),
   6634                 .len = try mod.intValue(Type.usize, mod.test_functions.count()),
   6635             });
   6636             const new_val = try Value.Tag.variable.create(arena, new_var);
   6637 
   6638             // Since we are replacing the Decl's value we must perform cleanup on the
   6639             // previous value.
   6640             decl.clearValues(mod);
   6641             decl.ty = new_ty;
   6642             decl.val = new_val;
   6643             decl.has_tv = true;
   6644         }
   6645 
   6646         try decl.finalizeNewArena(&new_decl_arena);
   6647     }
   6648     try mod.linkerUpdateDecl(decl_index);
   6649 }
   6650 
   6651 pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void {
   6652     const comp = mod.comp;
   6653 
   6654     const no_bin_file = (comp.bin_file.options.emit == null and
   6655         comp.emit_asm == null and
   6656         comp.emit_llvm_ir == null and
   6657         comp.emit_llvm_bc == null);
   6658 
   6659     const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
   6660 
   6661     if (no_bin_file and !dump_llvm_ir) return;
   6662 
   6663     const decl = mod.declPtr(decl_index);
   6664 
   6665     comp.bin_file.updateDecl(mod, decl_index) catch |err| switch (err) {
   6666         error.OutOfMemory => return error.OutOfMemory,
   6667         error.AnalysisFail => {
   6668             decl.analysis = .codegen_failure;
   6669             return;
   6670         },
   6671         else => {
   6672             const gpa = mod.gpa;
   6673             try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
   6674             mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
   6675                 gpa,
   6676                 decl.srcLoc(),
   6677                 "unable to codegen: {s}",
   6678                 .{@errorName(err)},
   6679             ));
   6680             decl.analysis = .codegen_failure_retryable;
   6681             return;
   6682         },
   6683     };
   6684 }
   6685 
   6686 fn reportRetryableFileError(
   6687     mod: *Module,
   6688     file: *File,
   6689     comptime format: []const u8,
   6690     args: anytype,
   6691 ) error{OutOfMemory}!void {
   6692     file.status = .retryable_failure;
   6693 
   6694     const err_msg = try ErrorMsg.create(
   6695         mod.gpa,
   6696         .{
   6697             .file_scope = file,
   6698             .parent_decl_node = 0,
   6699             .lazy = .entire_file,
   6700         },
   6701         format,
   6702         args,
   6703     );
   6704     errdefer err_msg.destroy(mod.gpa);
   6705 
   6706     mod.comp.mutex.lock();
   6707     defer mod.comp.mutex.unlock();
   6708 
   6709     const gop = try mod.failed_files.getOrPut(mod.gpa, file);
   6710     if (gop.found_existing) {
   6711         if (gop.value_ptr.*) |old_err_msg| {
   6712             old_err_msg.destroy(mod.gpa);
   6713         }
   6714     }
   6715     gop.value_ptr.* = err_msg;
   6716 }
   6717 
   6718 pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void {
   6719     if (val.ip_index != .none) return;
   6720     switch (val.tag()) {
   6721         .decl_ref_mut => return mod.markDeclIndexAlive(val.castTag(.decl_ref_mut).?.data.decl_index),
   6722         .extern_fn => return mod.markDeclIndexAlive(val.castTag(.extern_fn).?.data.owner_decl),
   6723         .function => return mod.markDeclIndexAlive(val.castTag(.function).?.data.owner_decl),
   6724         .variable => return mod.markDeclIndexAlive(val.castTag(.variable).?.data.owner_decl),
   6725         .decl_ref => return mod.markDeclIndexAlive(val.cast(Value.Payload.Decl).?.data),
   6726 
   6727         .repeated,
   6728         .eu_payload,
   6729         .opt_payload,
   6730         .empty_array_sentinel,
   6731         => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.SubValue).?.data),
   6732 
   6733         .eu_payload_ptr,
   6734         .opt_payload_ptr,
   6735         => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.PayloadPtr).?.data.container_ptr),
   6736 
   6737         .slice => {
   6738             const slice = val.cast(Value.Payload.Slice).?.data;
   6739             mod.markReferencedDeclsAlive(slice.ptr);
   6740             mod.markReferencedDeclsAlive(slice.len);
   6741         },
   6742 
   6743         .elem_ptr => {
   6744             const elem_ptr = val.cast(Value.Payload.ElemPtr).?.data;
   6745             return mod.markReferencedDeclsAlive(elem_ptr.array_ptr);
   6746         },
   6747         .field_ptr => {
   6748             const field_ptr = val.cast(Value.Payload.FieldPtr).?.data;
   6749             return mod.markReferencedDeclsAlive(field_ptr.container_ptr);
   6750         },
   6751         .aggregate => {
   6752             for (val.castTag(.aggregate).?.data) |field_val| {
   6753                 mod.markReferencedDeclsAlive(field_val);
   6754             }
   6755         },
   6756         .@"union" => {
   6757             const data = val.cast(Value.Payload.Union).?.data;
   6758             mod.markReferencedDeclsAlive(data.tag);
   6759             mod.markReferencedDeclsAlive(data.val);
   6760         },
   6761 
   6762         else => {},
   6763     }
   6764 }
   6765 
   6766 pub fn markDeclAlive(mod: *Module, decl: *Decl) void {
   6767     if (decl.alive) return;
   6768     decl.alive = true;
   6769 
   6770     // This is the first time we are marking this Decl alive. We must
   6771     // therefore recurse into its value and mark any Decl it references
   6772     // as also alive, so that any Decl referenced does not get garbage collected.
   6773     mod.markReferencedDeclsAlive(decl.val);
   6774 }
   6775 
   6776 fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) void {
   6777     return mod.markDeclAlive(mod.declPtr(decl_index));
   6778 }
   6779 
   6780 pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u8) !void {
   6781     try mod.global_assembly.ensureUnusedCapacity(mod.gpa, 1);
   6782 
   6783     const duped_source = try mod.gpa.dupe(u8, source);
   6784     errdefer mod.gpa.free(duped_source);
   6785 
   6786     mod.global_assembly.putAssumeCapacityNoClobber(decl_index, duped_source);
   6787 }
   6788 
   6789 pub fn wantDllExports(mod: Module) bool {
   6790     return mod.comp.bin_file.options.dll_export_fns and mod.getTarget().os.tag == .windows;
   6791 }
   6792 
   6793 pub fn getDeclExports(mod: Module, decl_index: Decl.Index) []const *Export {
   6794     if (mod.decl_exports.get(decl_index)) |l| {
   6795         return l.items;
   6796     } else {
   6797         return &[0]*Export{};
   6798     }
   6799 }
   6800 
   6801 pub const Feature = enum {
   6802     panic_fn,
   6803     panic_unwrap_error,
   6804     safety_check_formatted,
   6805     error_return_trace,
   6806     is_named_enum_value,
   6807     error_set_has_value,
   6808     field_reordering,
   6809 };
   6810 
   6811 pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {
   6812     return switch (feature) {
   6813         .panic_fn => mod.comp.bin_file.options.target.ofmt == .c or
   6814             mod.comp.bin_file.options.use_llvm,
   6815         .panic_unwrap_error => mod.comp.bin_file.options.target.ofmt == .c or
   6816             mod.comp.bin_file.options.use_llvm,
   6817         .safety_check_formatted => mod.comp.bin_file.options.target.ofmt == .c or
   6818             mod.comp.bin_file.options.use_llvm,
   6819         .error_return_trace => mod.comp.bin_file.options.use_llvm,
   6820         .is_named_enum_value => mod.comp.bin_file.options.use_llvm,
   6821         .error_set_has_value => mod.comp.bin_file.options.use_llvm or mod.comp.bin_file.options.target.isWasm(),
   6822         .field_reordering => mod.comp.bin_file.options.use_llvm,
   6823     };
   6824 }
   6825 
   6826 /// Shortcut for calling `intern_pool.get`.
   6827 pub fn intern(mod: *Module, key: InternPool.Key) Allocator.Error!InternPool.Index {
   6828     return mod.intern_pool.get(mod.gpa, key);
   6829 }
   6830 
   6831 pub fn intType(mod: *Module, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type {
   6832     const i = try intern(mod, .{ .int_type = .{
   6833         .signedness = signedness,
   6834         .bits = bits,
   6835     } });
   6836     return i.toType();
   6837 }
   6838 
   6839 pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type {
   6840     if (std.debug.runtime_safety and info.sentinel != .none) {
   6841         const sent_ty = mod.intern_pool.indexToKey(info.sentinel).typeOf();
   6842         assert(sent_ty == info.child);
   6843     }
   6844     const i = try intern(mod, .{ .array_type = info });
   6845     return i.toType();
   6846 }
   6847 
   6848 pub fn vectorType(mod: *Module, info: InternPool.Key.VectorType) Allocator.Error!Type {
   6849     const i = try intern(mod, .{ .vector_type = info });
   6850     return i.toType();
   6851 }
   6852 
   6853 pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!Type {
   6854     const i = try intern(mod, .{ .opt_type = child_type });
   6855     return i.toType();
   6856 }
   6857 
   6858 pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
   6859     if (std.debug.runtime_safety and info.sentinel != .none) {
   6860         const sent_ty = mod.intern_pool.indexToKey(info.sentinel).typeOf();
   6861         assert(sent_ty == info.elem_type);
   6862     }
   6863     const i = try intern(mod, .{ .ptr_type = info });
   6864     return i.toType();
   6865 }
   6866 
   6867 pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
   6868     if (child_type.ip_index == .none) {
   6869         // TODO remove this after all types can be represented via the InternPool
   6870         return Type.Tag.pointer.create(mod.tmp_hack_arena.allocator(), .{
   6871             .pointee_type = child_type,
   6872             .@"addrspace" = .generic,
   6873         });
   6874     }
   6875     return ptrType(mod, .{ .elem_type = child_type.ip_index });
   6876 }
   6877 
   6878 pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
   6879     if (child_type.ip_index == .none) {
   6880         // TODO remove this after all types can be represented via the InternPool
   6881         return Type.Tag.pointer.create(mod.tmp_hack_arena.allocator(), .{
   6882             .pointee_type = child_type,
   6883             .mutable = false,
   6884             .@"addrspace" = .generic,
   6885         });
   6886     }
   6887     return ptrType(mod, .{ .elem_type = child_type.ip_index, .is_const = true });
   6888 }
   6889 
   6890 pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
   6891     assert(ty.zigTypeTag(mod) == .Pointer);
   6892     const i = try intern(mod, .{ .ptr = .{
   6893         .ty = ty.ip_index,
   6894         .addr = .{ .int = try intern(mod, .{ .int = .{
   6895             .ty = ty.ip_index,
   6896             .storage = .{ .u64 = x },
   6897         } }) },
   6898     } });
   6899     return i.toValue();
   6900 }
   6901 
   6902 pub fn intValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {
   6903     if (std.debug.runtime_safety) {
   6904         const tag = ty.zigTypeTag(mod);
   6905         assert(tag == .Int or tag == .ComptimeInt);
   6906     }
   6907     if (std.math.cast(u64, x)) |casted| return intValue_u64(mod, ty, casted);
   6908     if (std.math.cast(i64, x)) |casted| return intValue_i64(mod, ty, casted);
   6909     var limbs_buffer: [4]usize = undefined;
   6910     var big_int = BigIntMutable.init(&limbs_buffer, x);
   6911     return intValue_big(mod, ty, big_int.toConst());
   6912 }
   6913 
   6914 pub fn intValue_big(mod: *Module, ty: Type, x: BigIntConst) Allocator.Error!Value {
   6915     const i = try intern(mod, .{ .int = .{
   6916         .ty = ty.ip_index,
   6917         .storage = .{ .big_int = x },
   6918     } });
   6919     return i.toValue();
   6920 }
   6921 
   6922 pub fn intValue_u64(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
   6923     const i = try intern(mod, .{ .int = .{
   6924         .ty = ty.ip_index,
   6925         .storage = .{ .u64 = x },
   6926     } });
   6927     return i.toValue();
   6928 }
   6929 
   6930 pub fn intValue_i64(mod: *Module, ty: Type, x: i64) Allocator.Error!Value {
   6931     const i = try intern(mod, .{ .int = .{
   6932         .ty = ty.ip_index,
   6933         .storage = .{ .i64 = x },
   6934     } });
   6935     return i.toValue();
   6936 }
   6937 
   6938 pub fn smallestUnsignedInt(mod: *Module, max: u64) Allocator.Error!Type {
   6939     return intType(mod, .unsigned, Type.smallestUnsignedBits(max));
   6940 }
   6941 
   6942 /// Returns the smallest possible integer type containing both `min` and
   6943 /// `max`. Asserts that neither value is undef.
   6944 /// TODO: if #3806 is implemented, this becomes trivial
   6945 pub fn intFittingRange(mod: *Module, min: Value, max: Value) !Type {
   6946     assert(!min.isUndef());
   6947     assert(!max.isUndef());
   6948 
   6949     if (std.debug.runtime_safety) {
   6950         assert(Value.order(min, max, mod).compare(.lte));
   6951     }
   6952 
   6953     const sign = min.orderAgainstZero(mod) == .lt;
   6954 
   6955     const min_val_bits = intBitsForValue(mod, min, sign);
   6956     const max_val_bits = intBitsForValue(mod, max, sign);
   6957 
   6958     return mod.intType(
   6959         if (sign) .signed else .unsigned,
   6960         @max(min_val_bits, max_val_bits),
   6961     );
   6962 }
   6963 
   6964 /// Given a value representing an integer, returns the number of bits necessary to represent
   6965 /// this value in an integer. If `sign` is true, returns the number of bits necessary in a
   6966 /// twos-complement integer; otherwise in an unsigned integer.
   6967 /// Asserts that `val` is not undef. If `val` is negative, asserts that `sign` is true.
   6968 pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {
   6969     assert(!val.isUndef());
   6970 
   6971     const key = mod.intern_pool.indexToKey(val.ip_index);
   6972     switch (key.int.storage) {
   6973         .i64 => |x| {
   6974             if (std.math.cast(u64, x)) |casted| return Type.smallestUnsignedBits(casted);
   6975             assert(sign);
   6976             // Protect against overflow in the following negation.
   6977             if (x == std.math.minInt(i64)) return 64;
   6978             return Type.smallestUnsignedBits(@intCast(u64, -x - 1)) + 1;
   6979         },
   6980         .u64 => |x| {
   6981             return Type.smallestUnsignedBits(x) + @boolToInt(sign);
   6982         },
   6983         .big_int => |big| {
   6984             if (big.positive) return @intCast(u16, big.bitCountAbs() + @boolToInt(sign));
   6985 
   6986             // Zero is still a possibility, in which case unsigned is fine
   6987             if (big.eqZero()) return 0;
   6988 
   6989             return @intCast(u16, big.bitCountTwosComp());
   6990         },
   6991     }
   6992 }
   6993 
   6994 pub const AtomicPtrAlignmentError = error{
   6995     FloatTooBig,
   6996     IntTooBig,
   6997     BadType,
   6998     OutOfMemory,
   6999 };
   7000 
   7001 pub const AtomicPtrAlignmentDiagnostics = struct {
   7002     bits: u16 = undefined,
   7003     max_bits: u16 = undefined,
   7004 };
   7005 
   7006 /// If ABI alignment of `ty` is OK for atomic operations, returns 0.
   7007 /// Otherwise returns the alignment required on a pointer for the target
   7008 /// to perform atomic operations.
   7009 // TODO this function does not take into account CPU features, which can affect
   7010 // this value. Audit this!
   7011 pub fn atomicPtrAlignment(
   7012     mod: *Module,
   7013     ty: Type,
   7014     diags: *AtomicPtrAlignmentDiagnostics,
   7015 ) AtomicPtrAlignmentError!u32 {
   7016     const target = mod.getTarget();
   7017     const max_atomic_bits: u16 = switch (target.cpu.arch) {
   7018         .avr,
   7019         .msp430,
   7020         .spu_2,
   7021         => 16,
   7022 
   7023         .arc,
   7024         .arm,
   7025         .armeb,
   7026         .hexagon,
   7027         .m68k,
   7028         .le32,
   7029         .mips,
   7030         .mipsel,
   7031         .nvptx,
   7032         .powerpc,
   7033         .powerpcle,
   7034         .r600,
   7035         .riscv32,
   7036         .sparc,
   7037         .sparcel,
   7038         .tce,
   7039         .tcele,
   7040         .thumb,
   7041         .thumbeb,
   7042         .x86,
   7043         .xcore,
   7044         .amdil,
   7045         .hsail,
   7046         .spir,
   7047         .kalimba,
   7048         .lanai,
   7049         .shave,
   7050         .wasm32,
   7051         .renderscript32,
   7052         .csky,
   7053         .spirv32,
   7054         .dxil,
   7055         .loongarch32,
   7056         .xtensa,
   7057         => 32,
   7058 
   7059         .amdgcn,
   7060         .bpfel,
   7061         .bpfeb,
   7062         .le64,
   7063         .mips64,
   7064         .mips64el,
   7065         .nvptx64,
   7066         .powerpc64,
   7067         .powerpc64le,
   7068         .riscv64,
   7069         .sparc64,
   7070         .s390x,
   7071         .amdil64,
   7072         .hsail64,
   7073         .spir64,
   7074         .wasm64,
   7075         .renderscript64,
   7076         .ve,
   7077         .spirv64,
   7078         .loongarch64,
   7079         => 64,
   7080 
   7081         .aarch64,
   7082         .aarch64_be,
   7083         .aarch64_32,
   7084         => 128,
   7085 
   7086         .x86_64 => if (std.Target.x86.featureSetHas(target.cpu.features, .cx16)) 128 else 64,
   7087     };
   7088 
   7089     const int_ty = switch (ty.zigTypeTag(mod)) {
   7090         .Int => ty,
   7091         .Enum => try ty.intTagType(mod),
   7092         .Float => {
   7093             const bit_count = ty.floatBits(target);
   7094             if (bit_count > max_atomic_bits) {
   7095                 diags.* = .{
   7096                     .bits = bit_count,
   7097                     .max_bits = max_atomic_bits,
   7098                 };
   7099                 return error.FloatTooBig;
   7100             }
   7101             return 0;
   7102         },
   7103         .Bool => return 0,
   7104         else => {
   7105             if (ty.isPtrAtRuntime(mod)) return 0;
   7106             return error.BadType;
   7107         },
   7108     };
   7109 
   7110     const bit_count = int_ty.intInfo(mod).bits;
   7111     if (bit_count > max_atomic_bits) {
   7112         diags.* = .{
   7113             .bits = bit_count,
   7114             .max_bits = max_atomic_bits,
   7115         };
   7116         return error.IntTooBig;
   7117     }
   7118 
   7119     return 0;
   7120 }