zig

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

blob 4462083b (157343B) - Raw


      1 //! Zig Intermediate Representation. Astgen.zig converts AST nodes to these
      2 //! untyped IR instructions. Next, Sema.zig processes these into AIR.
      3 //! The minimum amount of information needed to represent a list of ZIR instructions.
      4 //! Once this structure is completed, it can be used to generate AIR, followed by
      5 //! machine code, without any memory access into the AST tree token list, node list,
      6 //! or source bytes. Exceptions include:
      7 //!  * Compile errors, which may need to reach into these data structures to
      8 //!    create a useful report.
      9 //!  * In the future, possibly inline assembly, which needs to get parsed and
     10 //!    handled by the codegen backend, and errors reported there. However for now,
     11 //!    inline assembly is not an exception.
     12 
     13 const std = @import("std");
     14 const builtin = @import("builtin");
     15 const mem = std.mem;
     16 const Allocator = std.mem.Allocator;
     17 const assert = std.debug.assert;
     18 const BigIntConst = std.math.big.int.Const;
     19 const BigIntMutable = std.math.big.int.Mutable;
     20 const Ast = std.zig.Ast;
     21 
     22 const InternPool = @import("InternPool.zig");
     23 const Zir = @This();
     24 const Module = @import("Module.zig");
     25 const LazySrcLoc = Module.LazySrcLoc;
     26 
     27 instructions: std.MultiArrayList(Inst).Slice,
     28 /// In order to store references to strings in fewer bytes, we copy all
     29 /// string bytes into here. String bytes can be null. It is up to whomever
     30 /// is referencing the data here whether they want to store both index and length,
     31 /// thus allowing null bytes, or store only index, and use null-termination. The
     32 /// `string_bytes` array is agnostic to either usage.
     33 /// Index 0 is reserved for special cases.
     34 string_bytes: []u8,
     35 /// The meaning of this data is determined by `Inst.Tag` value.
     36 /// The first few indexes are reserved. See `ExtraIndex` for the values.
     37 extra: []u32,
     38 
     39 /// The data stored at byte offset 0 when ZIR is stored in a file.
     40 pub const Header = extern struct {
     41     instructions_len: u32,
     42     string_bytes_len: u32,
     43     extra_len: u32,
     44     /// We could leave this as padding, however it triggers a Valgrind warning because
     45     /// we read and write undefined bytes to the file system. This is harmless, but
     46     /// it's essentially free to have a zero field here and makes the warning go away,
     47     /// making it more likely that following Valgrind warnings will be taken seriously.
     48     unused: u32 = 0,
     49     stat_inode: std.fs.File.INode,
     50     stat_size: u64,
     51     stat_mtime: i128,
     52 };
     53 
     54 pub const ExtraIndex = enum(u32) {
     55     /// If this is 0, no compile errors. Otherwise there is a `CompileErrors`
     56     /// payload at this index.
     57     compile_errors,
     58     /// If this is 0, this file contains no imports. Otherwise there is a `Imports`
     59     /// payload at this index.
     60     imports,
     61 
     62     _,
     63 };
     64 
     65 fn ExtraData(comptime T: type) type {
     66     return struct { data: T, end: usize };
     67 }
     68 
     69 /// Returns the requested data, as well as the new index which is at the start of the
     70 /// trailers for the object.
     71 pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
     72     const fields = @typeInfo(T).Struct.fields;
     73     var i: usize = index;
     74     var result: T = undefined;
     75     inline for (fields) |field| {
     76         @field(result, field.name) = switch (field.type) {
     77             u32 => code.extra[i],
     78 
     79             Inst.Ref,
     80             Inst.Index,
     81             Inst.Declaration.Name,
     82             NullTerminatedString,
     83             => @enumFromInt(code.extra[i]),
     84 
     85             i32,
     86             Inst.Call.Flags,
     87             Inst.BuiltinCall.Flags,
     88             Inst.SwitchBlock.Bits,
     89             Inst.SwitchBlockErrUnion.Bits,
     90             Inst.FuncFancy.Bits,
     91             Inst.Declaration.Flags,
     92             => @bitCast(code.extra[i]),
     93 
     94             else => @compileError("bad field type"),
     95         };
     96         i += 1;
     97     }
     98     return .{
     99         .data = result,
    100         .end = i,
    101     };
    102 }
    103 
    104 pub const NullTerminatedString = enum(u32) {
    105     empty = 0,
    106     _,
    107 };
    108 
    109 /// Given an index into `string_bytes` returns the null-terminated string found there.
    110 pub fn nullTerminatedString(code: Zir, index: NullTerminatedString) [:0]const u8 {
    111     const start = @intFromEnum(index);
    112     var end: u32 = start;
    113     while (code.string_bytes[end] != 0) {
    114         end += 1;
    115     }
    116     return code.string_bytes[start..end :0];
    117 }
    118 
    119 pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
    120     return @ptrCast(code.extra[start..][0..len]);
    121 }
    122 
    123 pub fn bodySlice(zir: Zir, start: usize, len: usize) []Inst.Index {
    124     return @ptrCast(zir.extra[start..][0..len]);
    125 }
    126 
    127 pub fn hasCompileErrors(code: Zir) bool {
    128     return code.extra[@intFromEnum(ExtraIndex.compile_errors)] != 0;
    129 }
    130 
    131 pub fn deinit(code: *Zir, gpa: Allocator) void {
    132     code.instructions.deinit(gpa);
    133     gpa.free(code.string_bytes);
    134     gpa.free(code.extra);
    135     code.* = undefined;
    136 }
    137 
    138 /// These are untyped instructions generated from an Abstract Syntax Tree.
    139 /// The data here is immutable because it is possible to have multiple
    140 /// analyses on the same ZIR happening at the same time.
    141 pub const Inst = struct {
    142     tag: Tag,
    143     data: Data,
    144 
    145     /// These names are used directly as the instruction names in the text format.
    146     /// See `data_field_map` for a list of which `Data` fields are used by each `Tag`.
    147     pub const Tag = enum(u8) {
    148         /// Arithmetic addition, asserts no integer overflow.
    149         /// Uses the `pl_node` union field. Payload is `Bin`.
    150         add,
    151         /// Twos complement wrapping integer addition.
    152         /// Uses the `pl_node` union field. Payload is `Bin`.
    153         addwrap,
    154         /// Saturating addition.
    155         /// Uses the `pl_node` union field. Payload is `Bin`.
    156         add_sat,
    157         /// The same as `add` except no safety check.
    158         add_unsafe,
    159         /// Arithmetic subtraction. Asserts no integer overflow.
    160         /// Uses the `pl_node` union field. Payload is `Bin`.
    161         sub,
    162         /// Twos complement wrapping integer subtraction.
    163         /// Uses the `pl_node` union field. Payload is `Bin`.
    164         subwrap,
    165         /// Saturating subtraction.
    166         /// Uses the `pl_node` union field. Payload is `Bin`.
    167         sub_sat,
    168         /// Arithmetic multiplication. Asserts no integer overflow.
    169         /// Uses the `pl_node` union field. Payload is `Bin`.
    170         mul,
    171         /// Twos complement wrapping integer multiplication.
    172         /// Uses the `pl_node` union field. Payload is `Bin`.
    173         mulwrap,
    174         /// Saturating multiplication.
    175         /// Uses the `pl_node` union field. Payload is `Bin`.
    176         mul_sat,
    177         /// Implements the `@divExact` builtin.
    178         /// Uses the `pl_node` union field with payload `Bin`.
    179         div_exact,
    180         /// Implements the `@divFloor` builtin.
    181         /// Uses the `pl_node` union field with payload `Bin`.
    182         div_floor,
    183         /// Implements the `@divTrunc` builtin.
    184         /// Uses the `pl_node` union field with payload `Bin`.
    185         div_trunc,
    186         /// Implements the `@mod` builtin.
    187         /// Uses the `pl_node` union field with payload `Bin`.
    188         mod,
    189         /// Implements the `@rem` builtin.
    190         /// Uses the `pl_node` union field with payload `Bin`.
    191         rem,
    192         /// Ambiguously remainder division or modulus. If the computation would possibly have
    193         /// a different value depending on whether the operation is remainder division or modulus,
    194         /// a compile error is emitted. Otherwise the computation is performed.
    195         /// Uses the `pl_node` union field. Payload is `Bin`.
    196         mod_rem,
    197         /// Integer shift-left. Zeroes are shifted in from the right hand side.
    198         /// Uses the `pl_node` union field. Payload is `Bin`.
    199         shl,
    200         /// Implements the `@shlExact` builtin.
    201         /// Uses the `pl_node` union field with payload `Bin`.
    202         shl_exact,
    203         /// Saturating shift-left.
    204         /// Uses the `pl_node` union field. Payload is `Bin`.
    205         shl_sat,
    206         /// Integer shift-right. Arithmetic or logical depending on the signedness of
    207         /// the integer type.
    208         /// Uses the `pl_node` union field. Payload is `Bin`.
    209         shr,
    210         /// Implements the `@shrExact` builtin.
    211         /// Uses the `pl_node` union field with payload `Bin`.
    212         shr_exact,
    213 
    214         /// Declares a parameter of the current function. Used for:
    215         /// * debug info
    216         /// * checking shadowing against declarations in the current namespace
    217         /// * parameter type expressions referencing other parameters
    218         /// These occur in the block outside a function body (the same block as
    219         /// contains the func instruction).
    220         /// Uses the `pl_tok` field. Token is the parameter name, payload is a `Param`.
    221         param,
    222         /// Same as `param` except the parameter is marked comptime.
    223         param_comptime,
    224         /// Same as `param` except the parameter is marked anytype.
    225         /// Uses the `str_tok` field. Token is the parameter name. String is the parameter name.
    226         param_anytype,
    227         /// Same as `param` except the parameter is marked both comptime and anytype.
    228         /// Uses the `str_tok` field. Token is the parameter name. String is the parameter name.
    229         param_anytype_comptime,
    230         /// Array concatenation. `a ++ b`
    231         /// Uses the `pl_node` union field. Payload is `Bin`.
    232         array_cat,
    233         /// Array multiplication `a ** b`
    234         /// Uses the `pl_node` union field. Payload is `ArrayMul`.
    235         array_mul,
    236         /// `[N]T` syntax. No source location provided.
    237         /// Uses the `pl_node` union field. Payload is `Bin`. lhs is length, rhs is element type.
    238         array_type,
    239         /// `[N:S]T` syntax. Source location is the array type expression node.
    240         /// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`.
    241         array_type_sentinel,
    242         /// `@Vector` builtin.
    243         /// Uses the `pl_node` union field with `Bin` payload.
    244         /// lhs is length, rhs is element type.
    245         vector_type,
    246         /// Given a pointer type, returns its element type. Reaches through any optional or error
    247         /// union types wrapping the pointer. Asserts that the underlying type is a pointer type.
    248         /// Returns generic poison if the element type is `anyopaque`.
    249         /// Uses the `un_node` field.
    250         elem_type,
    251         /// Given an indexable pointer (slice, many-ptr, single-ptr-to-array), returns its
    252         /// element type. Emits a compile error if the type is not an indexable pointer.
    253         /// Uses the `un_node` field.
    254         indexable_ptr_elem_type,
    255         /// Given a vector type, returns its element type.
    256         /// Uses the `un_node` field.
    257         vector_elem_type,
    258         /// Given a pointer to an indexable object, returns the len property. This is
    259         /// used by for loops. This instruction also emits a for-loop specific compile
    260         /// error if the indexable object is not indexable.
    261         /// Uses the `un_node` field. The AST node is the for loop node.
    262         indexable_ptr_len,
    263         /// Create a `anyframe->T` type.
    264         /// Uses the `un_node` field.
    265         anyframe_type,
    266         /// Type coercion to the function's return type.
    267         /// Uses the `pl_node` field. Payload is `As`. AST node could be many things.
    268         as_node,
    269         /// Same as `as_node` but ignores runtime to comptime int error.
    270         as_shift_operand,
    271         /// Bitwise AND. `&`
    272         bit_and,
    273         /// Reinterpret the memory representation of a value as a different type.
    274         /// Uses the pl_node field with payload `Bin`.
    275         bitcast,
    276         /// Bitwise NOT. `~`
    277         /// Uses `un_node`.
    278         bit_not,
    279         /// Bitwise OR. `|`
    280         bit_or,
    281         /// A labeled block of code, which can return a value.
    282         /// Uses the `pl_node` union field. Payload is `Block`.
    283         block,
    284         /// Like `block`, but forces full evaluation of its contents at compile-time.
    285         /// Uses the `pl_node` union field. Payload is `Block`.
    286         block_comptime,
    287         /// A list of instructions which are analyzed in the parent context, without
    288         /// generating a runtime block. Must terminate with an "inline" variant of
    289         /// a noreturn instruction.
    290         /// Uses the `pl_node` union field. Payload is `Block`.
    291         block_inline,
    292         /// This instruction may only ever appear in the list of declarations for a
    293         /// namespace type, e.g. within a `struct_decl` instruction. It represents a
    294         /// single source declaration (`const`/`var`/`fn`), containing the name,
    295         /// attributes, type, and value of the declaration.
    296         /// Uses the `pl_node` union field. Payload is `Declaration`.
    297         declaration,
    298         /// Implements `suspend {...}`.
    299         /// Uses the `pl_node` union field. Payload is `Block`.
    300         suspend_block,
    301         /// Boolean NOT. See also `bit_not`.
    302         /// Uses the `un_node` field.
    303         bool_not,
    304         /// Short-circuiting boolean `and`. `lhs` is a boolean `Ref` and the other operand
    305         /// is a block, which is evaluated if `lhs` is `true`.
    306         /// Uses the `bool_br` union field.
    307         bool_br_and,
    308         /// Short-circuiting boolean `or`. `lhs` is a boolean `Ref` and the other operand
    309         /// is a block, which is evaluated if `lhs` is `false`.
    310         /// Uses the `bool_br` union field.
    311         bool_br_or,
    312         /// Return a value from a block.
    313         /// Uses the `break` union field.
    314         /// Uses the source information from previous instruction.
    315         @"break",
    316         /// Return a value from a block. This instruction is used as the terminator
    317         /// of a `block_inline`. It allows using the return value from `Sema.analyzeBody`.
    318         /// This instruction may also be used when it is known that there is only one
    319         /// break instruction in a block, and the target block is the parent.
    320         /// Uses the `break` union field.
    321         break_inline,
    322         /// Checks that comptime control flow does not happen inside a runtime block.
    323         /// Uses the `un_node` union field.
    324         check_comptime_control_flow,
    325         /// Function call.
    326         /// Uses the `pl_node` union field with payload `Call`.
    327         /// AST node is the function call.
    328         call,
    329         /// Function call using `a.b()` syntax.
    330         /// Uses the named field as the callee. If there is no such field, searches in the type for
    331         /// a decl matching the field name. The decl is resolved and we ensure that it's a function
    332         /// which can accept the object as the first parameter, with one pointer fixup. This
    333         /// function is then used as the callee, with the object as an implicit first parameter.
    334         /// Uses the `pl_node` union field with payload `FieldCall`.
    335         /// AST node is the function call.
    336         field_call,
    337         /// Implements the `@call` builtin.
    338         /// Uses the `pl_node` union field with payload `BuiltinCall`.
    339         /// AST node is the builtin call.
    340         builtin_call,
    341         /// `<`
    342         /// Uses the `pl_node` union field. Payload is `Bin`.
    343         cmp_lt,
    344         /// `<=`
    345         /// Uses the `pl_node` union field. Payload is `Bin`.
    346         cmp_lte,
    347         /// `==`
    348         /// Uses the `pl_node` union field. Payload is `Bin`.
    349         cmp_eq,
    350         /// `>=`
    351         /// Uses the `pl_node` union field. Payload is `Bin`.
    352         cmp_gte,
    353         /// `>`
    354         /// Uses the `pl_node` union field. Payload is `Bin`.
    355         cmp_gt,
    356         /// `!=`
    357         /// Uses the `pl_node` union field. Payload is `Bin`.
    358         cmp_neq,
    359         /// Conditional branch. Splits control flow based on a boolean condition value.
    360         /// Uses the `pl_node` union field. AST node is an if, while, for, etc.
    361         /// Payload is `CondBr`.
    362         condbr,
    363         /// Same as `condbr`, except the condition is coerced to a comptime value, and
    364         /// only the taken branch is analyzed. The then block and else block must
    365         /// terminate with an "inline" variant of a noreturn instruction.
    366         condbr_inline,
    367         /// Given an operand which is an error union, splits control flow. In
    368         /// case of error, control flow goes into the block that is part of this
    369         /// instruction, which is guaranteed to end with a return instruction
    370         /// and never breaks out of the block.
    371         /// In the case of non-error, control flow proceeds to the next instruction
    372         /// after the `try`, with the result of this instruction being the unwrapped
    373         /// payload value, as if `err_union_payload_unsafe` was executed on the operand.
    374         /// Uses the `pl_node` union field. Payload is `Try`.
    375         @"try",
    376         /// Same as `try` except the operand is a pointer and the result is a pointer.
    377         try_ptr,
    378         /// An error set type definition. Contains a list of field names.
    379         /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
    380         error_set_decl,
    381         error_set_decl_anon,
    382         error_set_decl_func,
    383         /// Declares the beginning of a statement. Used for debug info.
    384         /// Uses the `dbg_stmt` union field. The line and column are offset
    385         /// from the parent declaration.
    386         dbg_stmt,
    387         /// Marks a variable declaration. Used for debug info.
    388         /// Uses the `str_op` union field. The string is the local variable name,
    389         /// and the operand is the pointer to the variable's location. The local
    390         /// may be a const or a var.
    391         dbg_var_ptr,
    392         /// Same as `dbg_var_ptr` but the local is always a const and the operand
    393         /// is the local's value.
    394         dbg_var_val,
    395         /// Marks the beginning of a semantic scope for debug info variables.
    396         dbg_block_begin,
    397         /// Marks the end of a semantic scope for debug info variables.
    398         dbg_block_end,
    399         /// Uses a name to identify a Decl and takes a pointer to it.
    400         /// Uses the `str_tok` union field.
    401         decl_ref,
    402         /// Uses a name to identify a Decl and uses it as a value.
    403         /// Uses the `str_tok` union field.
    404         decl_val,
    405         /// Load the value from a pointer. Assumes `x.*` syntax.
    406         /// Uses `un_node` field. AST node is the `x.*` syntax.
    407         load,
    408         /// Arithmetic division. Asserts no integer overflow.
    409         /// Uses the `pl_node` union field. Payload is `Bin`.
    410         div,
    411         /// Given a pointer to an array, slice, or pointer, returns a pointer to the element at
    412         /// the provided index.
    413         /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
    414         elem_ptr_node,
    415         /// Same as `elem_ptr_node` but used only for for loop.
    416         /// Uses the `pl_node` union field. AST node is the condition of a for loop.
    417         /// Payload is `Bin`.
    418         /// No OOB safety check is emitted.
    419         elem_ptr,
    420         /// Given an array, slice, or pointer, returns the element at the provided index.
    421         /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
    422         elem_val_node,
    423         /// Same as `elem_val_node` but used only for for loop.
    424         /// Uses the `pl_node` union field. AST node is the condition of a for loop.
    425         /// Payload is `Bin`.
    426         /// No OOB safety check is emitted.
    427         elem_val,
    428         /// Same as `elem_val` but takes the index as an immediate value.
    429         /// No OOB safety check is emitted. A prior instruction must validate this operation.
    430         /// Uses the `elem_val_imm` union field.
    431         elem_val_imm,
    432         /// Emits a compile error if the operand is not `void`.
    433         /// Uses the `un_node` field.
    434         ensure_result_used,
    435         /// Emits a compile error if an error is ignored.
    436         /// Uses the `un_node` field.
    437         ensure_result_non_error,
    438         /// Emits a compile error error union payload is not void.
    439         ensure_err_union_payload_void,
    440         /// Create a `E!T` type.
    441         /// Uses the `pl_node` field with `Bin` payload.
    442         error_union_type,
    443         /// `error.Foo` syntax. Uses the `str_tok` field of the Data union.
    444         error_value,
    445         /// Implements the `@export` builtin function, based on either an identifier to a Decl,
    446         /// or field access of a Decl. The thing being exported is the Decl.
    447         /// Uses the `pl_node` union field. Payload is `Export`.
    448         @"export",
    449         /// Implements the `@export` builtin function, based on a comptime-known value.
    450         /// The thing being exported is the comptime-known value which is the operand.
    451         /// Uses the `pl_node` union field. Payload is `ExportValue`.
    452         export_value,
    453         /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
    454         /// to the named field. The field name is stored in string_bytes. Used by a.b syntax.
    455         /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.
    456         field_ptr,
    457         /// Given a struct or object that contains virtual fields, returns the named field.
    458         /// The field name is stored in string_bytes. Used by a.b syntax.
    459         /// This instruction also accepts a pointer.
    460         /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field.
    461         field_val,
    462         /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
    463         /// to the named field. The field name is a comptime instruction. Used by @field.
    464         /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed.
    465         field_ptr_named,
    466         /// Given a struct or object that contains virtual fields, returns the named field.
    467         /// The field name is a comptime instruction. Used by @field.
    468         /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed.
    469         field_val_named,
    470         /// Returns a function type, or a function instance, depending on whether
    471         /// the body_len is 0. Calling convention is auto.
    472         /// Uses the `pl_node` union field. `payload_index` points to a `Func`.
    473         func,
    474         /// Same as `func` but has an inferred error set.
    475         func_inferred,
    476         /// Represents a function declaration or function prototype, depending on
    477         /// whether body_len is 0.
    478         /// Uses the `pl_node` union field. `payload_index` points to a `FuncFancy`.
    479         func_fancy,
    480         /// Implements the `@import` builtin.
    481         /// Uses the `str_tok` field.
    482         import,
    483         /// Integer literal that fits in a u64. Uses the `int` union field.
    484         int,
    485         /// Arbitrary sized integer literal. Uses the `str` union field.
    486         int_big,
    487         /// A float literal that fits in a f64. Uses the float union value.
    488         float,
    489         /// A float literal that fits in a f128. Uses the `pl_node` union value.
    490         /// Payload is `Float128`.
    491         float128,
    492         /// Make an integer type out of signedness and bit count.
    493         /// Payload is `int_type`
    494         int_type,
    495         /// Return a boolean false if an optional is null. `x != null`
    496         /// Uses the `un_node` field.
    497         is_non_null,
    498         /// Return a boolean false if an optional is null. `x.* != null`
    499         /// Uses the `un_node` field.
    500         is_non_null_ptr,
    501         /// Return a boolean false if value is an error
    502         /// Uses the `un_node` field.
    503         is_non_err,
    504         /// Return a boolean false if dereferenced pointer is an error
    505         /// Uses the `un_node` field.
    506         is_non_err_ptr,
    507         /// Same as `is_non_er` but doesn't validate that the type can be an error.
    508         /// Uses the `un_node` field.
    509         ret_is_non_err,
    510         /// A labeled block of code that loops forever. At the end of the body will have either
    511         /// a `repeat` instruction or a `repeat_inline` instruction.
    512         /// Uses the `pl_node` field. The AST node is either a for loop or while loop.
    513         /// This ZIR instruction is needed because AIR does not (yet?) match ZIR, and Sema
    514         /// needs to emit more than 1 AIR block for this instruction.
    515         /// The payload is `Block`.
    516         loop,
    517         /// Sends runtime control flow back to the beginning of the current block.
    518         /// Uses the `node` field.
    519         repeat,
    520         /// Sends comptime control flow back to the beginning of the current block.
    521         /// Uses the `node` field.
    522         repeat_inline,
    523         /// Asserts that all the lengths provided match. Used to build a for loop.
    524         /// Return value is the length as a usize.
    525         /// Uses the `pl_node` field with payload `MultiOp`.
    526         /// There is exactly one item corresponding to each AST node inside the for
    527         /// loop condition. Any item may be `none`, indicating an unbounded range.
    528         /// Illegal behaviors:
    529         ///  * If all lengths are unbounded ranges (always a compile error).
    530         ///  * If any two lengths do not match each other.
    531         for_len,
    532         /// Merge two error sets into one, `E1 || E2`.
    533         /// Uses the `pl_node` field with payload `Bin`.
    534         merge_error_sets,
    535         /// Turns an R-Value into a const L-Value. In other words, it takes a value,
    536         /// stores it in a memory location, and returns a const pointer to it. If the value
    537         /// is `comptime`, the memory location is global static constant data. Otherwise,
    538         /// the memory location is in the stack frame, local to the scope containing the
    539         /// instruction.
    540         /// Uses the `un_tok` union field.
    541         ref,
    542         /// Sends control flow back to the function's callee.
    543         /// Includes an operand as the return value.
    544         /// Includes an AST node source location.
    545         /// Uses the `un_node` union field.
    546         ret_node,
    547         /// Sends control flow back to the function's callee.
    548         /// The operand is a `ret_ptr` instruction, where the return value can be found.
    549         /// Includes an AST node source location.
    550         /// Uses the `un_node` union field.
    551         ret_load,
    552         /// Sends control flow back to the function's callee.
    553         /// Includes an operand as the return value.
    554         /// Includes a token source location.
    555         /// Uses the `un_tok` union field.
    556         ret_implicit,
    557         /// Sends control flow back to the function's callee.
    558         /// The return operand is `error.foo` where `foo` is given by the string.
    559         /// If the current function has an inferred error set, the error given by the
    560         /// name is added to it.
    561         /// Uses the `str_tok` union field.
    562         ret_err_value,
    563         /// A string name is provided which is an anonymous error set value.
    564         /// If the current function has an inferred error set, the error given by the
    565         /// name is added to it.
    566         /// Results in the error code. Note that control flow is not diverted with
    567         /// this instruction; a following 'ret' instruction will do the diversion.
    568         /// Uses the `str_tok` union field.
    569         ret_err_value_code,
    570         /// Obtains a pointer to the return value.
    571         /// Uses the `node` union field.
    572         ret_ptr,
    573         /// Obtains the return type of the in-scope function.
    574         /// Uses the `node` union field.
    575         ret_type,
    576         /// Create a pointer type which can have a sentinel, alignment, address space, and/or bit range.
    577         /// Uses the `ptr_type` union field.
    578         ptr_type,
    579         /// Slice operation `lhs[rhs..]`. No sentinel and no end offset.
    580         /// Returns a pointer to the subslice.
    581         /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceStart`.
    582         slice_start,
    583         /// Slice operation `array_ptr[start..end]`. No sentinel.
    584         /// Returns a pointer to the subslice.
    585         /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceEnd`.
    586         slice_end,
    587         /// Slice operation `array_ptr[start..end:sentinel]`.
    588         /// Returns a pointer to the subslice.
    589         /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceSentinel`.
    590         slice_sentinel,
    591         /// Slice operation `array_ptr[start..][0..len]`. Optional sentinel.
    592         /// Returns a pointer to the subslice.
    593         /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceLength`.
    594         slice_length,
    595         /// Write a value to a pointer. For loading, see `load`.
    596         /// Source location is assumed to be same as previous instruction.
    597         /// Uses the `bin` union field.
    598         store,
    599         /// Same as `store` except provides a source location.
    600         /// Uses the `pl_node` union field. Payload is `Bin`.
    601         store_node,
    602         /// Same as `store` but the type of the value being stored will be used to infer
    603         /// the pointer type.
    604         /// Uses the `bin` union field.
    605         store_to_inferred_ptr,
    606         /// String Literal. Makes an anonymous Decl and then takes a pointer to it.
    607         /// Uses the `str` union field.
    608         str,
    609         /// Arithmetic negation. Asserts no integer overflow.
    610         /// Same as sub with a lhs of 0, split into a separate instruction to save memory.
    611         /// Uses `un_node`.
    612         negate,
    613         /// Twos complement wrapping integer negation.
    614         /// Same as subwrap with a lhs of 0, split into a separate instruction to save memory.
    615         /// Uses `un_node`.
    616         negate_wrap,
    617         /// Returns the type of a value.
    618         /// Uses the `un_node` field.
    619         typeof,
    620         /// Implements `@TypeOf` for one operand.
    621         /// Uses the `pl_node` field.
    622         typeof_builtin,
    623         /// Given a value, look at the type of it, which must be an integer type.
    624         /// Returns the integer type for the RHS of a shift operation.
    625         /// Uses the `un_node` field.
    626         typeof_log2_int_type,
    627         /// Asserts control-flow will not reach this instruction (`unreachable`).
    628         /// Uses the `@"unreachable"` union field.
    629         @"unreachable",
    630         /// Bitwise XOR. `^`
    631         /// Uses the `pl_node` union field. Payload is `Bin`.
    632         xor,
    633         /// Create an optional type '?T'
    634         /// Uses the `un_node` field.
    635         optional_type,
    636         /// ?T => T with safety.
    637         /// Given an optional value, returns the payload value, with a safety check that
    638         /// the value is non-null. Used for `orelse`, `if` and `while`.
    639         /// Uses the `un_node` field.
    640         optional_payload_safe,
    641         /// ?T => T without safety.
    642         /// Given an optional value, returns the payload value. No safety checks.
    643         /// Uses the `un_node` field.
    644         optional_payload_unsafe,
    645         /// *?T => *T with safety.
    646         /// Given a pointer to an optional value, returns a pointer to the payload value,
    647         /// with a safety check that the value is non-null. Used for `orelse`, `if` and `while`.
    648         /// Uses the `un_node` field.
    649         optional_payload_safe_ptr,
    650         /// *?T => *T without safety.
    651         /// Given a pointer to an optional value, returns a pointer to the payload value.
    652         /// No safety checks.
    653         /// Uses the `un_node` field.
    654         optional_payload_unsafe_ptr,
    655         /// E!T => T without safety.
    656         /// Given an error union value, returns the payload value. No safety checks.
    657         /// Uses the `un_node` field.
    658         err_union_payload_unsafe,
    659         /// *E!T => *T without safety.
    660         /// Given a pointer to a error union value, returns a pointer to the payload value.
    661         /// No safety checks.
    662         /// Uses the `un_node` field.
    663         err_union_payload_unsafe_ptr,
    664         /// E!T => E without safety.
    665         /// Given an error union value, returns the error code. No safety checks.
    666         /// Uses the `un_node` field.
    667         err_union_code,
    668         /// *E!T => E without safety.
    669         /// Given a pointer to an error union value, returns the error code. No safety checks.
    670         /// Uses the `un_node` field.
    671         err_union_code_ptr,
    672         /// An enum literal. Uses the `str_tok` union field.
    673         enum_literal,
    674         /// A switch expression. Uses the `pl_node` union field.
    675         /// AST node is the switch, payload is `SwitchBlock`.
    676         switch_block,
    677         /// A switch expression. Uses the `pl_node` union field.
    678         /// AST node is the switch, payload is `SwitchBlock`. Operand is a pointer.
    679         switch_block_ref,
    680         /// A switch on an error union `a catch |err| switch (err) {...}`.
    681         /// Uses the `pl_node` union field. AST node is the `catch`, payload is `SwitchBlockErrUnion`.
    682         switch_block_err_union,
    683         /// Check that operand type supports the dereference operand (.*).
    684         /// Uses the `un_node` field.
    685         validate_deref,
    686         /// Check that the operand's type is an array or tuple with the given number of elements.
    687         /// Uses the `pl_node` field. Payload is `ValidateDestructure`.
    688         validate_destructure,
    689         /// Given a struct or union, and a field name as a Ref,
    690         /// returns the field type. Uses the `pl_node` field. Payload is `FieldTypeRef`.
    691         field_type_ref,
    692         /// Given a pointer, initializes all error unions and optionals in the pointee to payloads,
    693         /// returning the base payload pointer. For instance, converts *E!?T into a valid *T
    694         /// (clobbering any existing error or null value).
    695         /// Uses the `un_node` field.
    696         opt_eu_base_ptr_init,
    697         /// Coerce a given value such that when a reference is taken, the resulting pointer will be
    698         /// coercible to the given type. For instance, given a value of type 'u32' and the pointer
    699         /// type '*u64', coerces the value to a 'u64'. Asserts that the type is a pointer type.
    700         /// Uses the `pl_node` field. Payload is `Bin`.
    701         /// LHS is the pointer type, RHS is the value.
    702         coerce_ptr_elem_ty,
    703         /// Given a type, validate that it is a pointer type suitable for return from the address-of
    704         /// operator. Emit a compile error if not.
    705         /// Uses the `un_tok` union field. Token is the `&` operator. Operand is the type.
    706         validate_ref_ty,
    707 
    708         // The following tags all relate to struct initialization expressions.
    709 
    710         /// A struct literal with a specified explicit type, with no fields.
    711         /// Uses the `un_node` field.
    712         struct_init_empty,
    713         /// An anonymous struct literal with a known result type, with no fields.
    714         /// Uses the `un_node` field.
    715         struct_init_empty_result,
    716         /// An anonymous struct literal with no fields, returned by reference, with a known result
    717         /// type for the pointer. Asserts that the type is a pointer.
    718         /// Uses the `un_node` field.
    719         struct_init_empty_ref_result,
    720         /// Struct initialization without a type. Creates a value of an anonymous struct type.
    721         /// Uses the `pl_node` field. Payload is `StructInitAnon`.
    722         struct_init_anon,
    723         /// Finalizes a typed struct or union initialization, performs validation, and returns the
    724         /// struct or union value. The given type must be validated prior to this instruction, using
    725         /// `validate_struct_init_ty` or `validate_struct_init_result_ty`. If the given type is
    726         /// generic poison, this is downgraded to an anonymous initialization.
    727         /// Uses the `pl_node` field. Payload is `StructInit`.
    728         struct_init,
    729         /// Struct initialization syntax, make the result a pointer. Equivalent to `struct_init`
    730         /// followed by `ref` - this ZIR tag exists as an optimization for a common pattern.
    731         /// Uses the `pl_node` field. Payload is `StructInit`.
    732         struct_init_ref,
    733         /// Checks that the type supports struct init syntax. Always returns void.
    734         /// Uses the `un_node` field.
    735         validate_struct_init_ty,
    736         /// Like `validate_struct_init_ty`, but additionally accepts types which structs coerce to.
    737         /// Used on the known result type of a struct init expression. Always returns void.
    738         /// Uses the `un_node` field.
    739         validate_struct_init_result_ty,
    740         /// Given a set of `struct_init_field_ptr` instructions, assumes they are all part of a
    741         /// struct initialization expression, and emits compile errors for duplicate fields as well
    742         /// as missing fields, if applicable.
    743         /// This instruction asserts that there is at least one struct_init_field_ptr instruction,
    744         /// because it must use one of them to find out the struct type.
    745         /// Uses the `pl_node` field. Payload is `Block`.
    746         validate_ptr_struct_init,
    747         /// Given a type being used for a struct initialization expression, returns the type of the
    748         /// field with the given name.
    749         /// Uses the `pl_node` field. Payload is `FieldType`.
    750         struct_init_field_type,
    751         /// Given a pointer being used as the result pointer of a struct initialization expression,
    752         /// return a pointer to the field of the given name.
    753         /// Uses the `pl_node` field. The AST node is the field initializer. Payload is Field.
    754         struct_init_field_ptr,
    755 
    756         // The following tags all relate to array initialization expressions.
    757 
    758         /// Array initialization without a type. Creates a value of a tuple type.
    759         /// Uses the `pl_node` field. Payload is `MultiOp`.
    760         array_init_anon,
    761         /// Array initialization syntax with a known type. The given type must be validated prior to
    762         /// this instruction, using some `validate_array_init_*_ty` instruction.
    763         /// Uses the `pl_node` field. Payload is `MultiOp`, where the first operand is the type.
    764         array_init,
    765         /// Array initialization syntax, make the result a pointer. Equivalent to `array_init`
    766         /// followed by `ref`- this ZIR tag exists as an optimization for a common pattern.
    767         /// Uses the `pl_node` field. Payload is `MultiOp`, where the first operand is the type.
    768         array_init_ref,
    769         /// Checks that the type supports array init syntax. Always returns void.
    770         /// Uses the `pl_node` field. Payload is `ArrayInit`.
    771         validate_array_init_ty,
    772         /// Like `validate_array_init_ty`, but additionally accepts types which arrays coerce to.
    773         /// Used on the known result type of an array init expression. Always returns void.
    774         /// Uses the `pl_node` field. Payload is `ArrayInit`.
    775         validate_array_init_result_ty,
    776         /// Given a pointer or slice type and an element count, return the expected type of an array
    777         /// initializer such that a pointer to the initializer has the given pointer type, checking
    778         /// that this type supports array init syntax and emitting a compile error if not. Preserves
    779         /// error union and optional wrappers on the array type, if any.
    780         /// Asserts that the given type is a pointer or slice type.
    781         /// Uses the `pl_node` field. Payload is `ArrayInitRefTy`.
    782         validate_array_init_ref_ty,
    783         /// Given a set of `array_init_elem_ptr` instructions, assumes they are all part of an array
    784         /// initialization expression, and emits a compile error if the number of elements does not
    785         /// match the array type.
    786         /// This instruction asserts that there is at least one `array_init_elem_ptr` instruction,
    787         /// because it must use one of them to find out the array type.
    788         /// Uses the `pl_node` field. Payload is `Block`.
    789         validate_ptr_array_init,
    790         /// Given a type being used for an array initialization expression, returns the type of the
    791         /// element at the given index.
    792         /// Uses the `bin` union field. lhs is the indexable type, rhs is the index.
    793         array_init_elem_type,
    794         /// Given a pointer being used as the result pointer of an array initialization expression,
    795         /// return a pointer to the element at the given index.
    796         /// Uses the `pl_node` union field. AST node is an element inside array initialization
    797         /// syntax. Payload is `ElemPtrImm`.
    798         array_init_elem_ptr,
    799 
    800         /// Implements the `@unionInit` builtin.
    801         /// Uses the `pl_node` field. Payload is `UnionInit`.
    802         union_init,
    803         /// Implements the `@typeInfo` builtin. Uses `un_node`.
    804         type_info,
    805         /// Implements the `@sizeOf` builtin. Uses `un_node`.
    806         size_of,
    807         /// Implements the `@bitSizeOf` builtin. Uses `un_node`.
    808         bit_size_of,
    809 
    810         /// Implement builtin `@intFromPtr`. Uses `un_node`.
    811         /// Convert a pointer to a `usize` integer.
    812         int_from_ptr,
    813         /// Emit an error message and fail compilation.
    814         /// Uses the `un_node` field.
    815         compile_error,
    816         /// Changes the maximum number of backwards branches that compile-time
    817         /// code execution can use before giving up and making a compile error.
    818         /// Uses the `un_node` union field.
    819         set_eval_branch_quota,
    820         /// Converts an enum value into an integer. Resulting type will be the tag type
    821         /// of the enum. Uses `un_node`.
    822         int_from_enum,
    823         /// Implement builtin `@alignOf`. Uses `un_node`.
    824         align_of,
    825         /// Implement builtin `@intFromBool`. Uses `un_node`.
    826         int_from_bool,
    827         /// Implement builtin `@embedFile`. Uses `un_node`.
    828         embed_file,
    829         /// Implement builtin `@errorName`. Uses `un_node`.
    830         error_name,
    831         /// Implement builtin `@panic`. Uses `un_node`.
    832         panic,
    833         /// Implements `@trap`.
    834         /// Uses the `node` field.
    835         trap,
    836         /// Implement builtin `@setRuntimeSafety`. Uses `un_node`.
    837         set_runtime_safety,
    838         /// Implement builtin `@sqrt`. Uses `un_node`.
    839         sqrt,
    840         /// Implement builtin `@sin`. Uses `un_node`.
    841         sin,
    842         /// Implement builtin `@cos`. Uses `un_node`.
    843         cos,
    844         /// Implement builtin `@tan`. Uses `un_node`.
    845         tan,
    846         /// Implement builtin `@exp`. Uses `un_node`.
    847         exp,
    848         /// Implement builtin `@exp2`. Uses `un_node`.
    849         exp2,
    850         /// Implement builtin `@log`. Uses `un_node`.
    851         log,
    852         /// Implement builtin `@log2`. Uses `un_node`.
    853         log2,
    854         /// Implement builtin `@log10`. Uses `un_node`.
    855         log10,
    856         /// Implement builtin `@abs`. Uses `un_node`.
    857         abs,
    858         /// Implement builtin `@floor`. Uses `un_node`.
    859         floor,
    860         /// Implement builtin `@ceil`. Uses `un_node`.
    861         ceil,
    862         /// Implement builtin `@trunc`. Uses `un_node`.
    863         trunc,
    864         /// Implement builtin `@round`. Uses `un_node`.
    865         round,
    866         /// Implement builtin `@tagName`. Uses `un_node`.
    867         tag_name,
    868         /// Implement builtin `@typeName`. Uses `un_node`.
    869         type_name,
    870         /// Implement builtin `@Frame`. Uses `un_node`.
    871         frame_type,
    872         /// Implement builtin `@frameSize`. Uses `un_node`.
    873         frame_size,
    874 
    875         /// Implements the `@intFromFloat` builtin.
    876         /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
    877         int_from_float,
    878         /// Implements the `@floatFromInt` builtin.
    879         /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
    880         float_from_int,
    881         /// Implements the `@ptrFromInt` builtin.
    882         /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
    883         ptr_from_int,
    884         /// Converts an integer into an enum value.
    885         /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
    886         enum_from_int,
    887         /// Convert a larger float type to any other float type, possibly causing
    888         /// a loss of precision.
    889         /// Uses the `pl_node` field. AST is the `@floatCast` syntax.
    890         /// Payload is `Bin` with lhs as the dest type, rhs the operand.
    891         float_cast,
    892         /// Implements the `@intCast` builtin.
    893         /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
    894         /// Convert an integer value to another integer type, asserting that the destination type
    895         /// can hold the same mathematical value.
    896         int_cast,
    897         /// Implements the `@ptrCast` builtin.
    898         /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
    899         /// Not every `@ptrCast` will correspond to this instruction - see also
    900         /// `ptr_cast_full` in `Extended`.
    901         ptr_cast,
    902         /// Implements the `@truncate` builtin.
    903         /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
    904         truncate,
    905 
    906         /// Implements the `@hasDecl` builtin.
    907         /// Uses the `pl_node` union field. Payload is `Bin`.
    908         has_decl,
    909         /// Implements the `@hasField` builtin.
    910         /// Uses the `pl_node` union field. Payload is `Bin`.
    911         has_field,
    912 
    913         /// Implements the `@clz` builtin. Uses the `un_node` union field.
    914         clz,
    915         /// Implements the `@ctz` builtin. Uses the `un_node` union field.
    916         ctz,
    917         /// Implements the `@popCount` builtin. Uses the `un_node` union field.
    918         pop_count,
    919         /// Implements the `@byteSwap` builtin. Uses the `un_node` union field.
    920         byte_swap,
    921         /// Implements the `@bitReverse` builtin. Uses the `un_node` union field.
    922         bit_reverse,
    923 
    924         /// Implements the `@bitOffsetOf` builtin.
    925         /// Uses the `pl_node` union field with payload `Bin`.
    926         bit_offset_of,
    927         /// Implements the `@offsetOf` builtin.
    928         /// Uses the `pl_node` union field with payload `Bin`.
    929         offset_of,
    930         /// Implements the `@splat` builtin.
    931         /// Uses the `pl_node` union field with payload `Bin`.
    932         splat,
    933         /// Implements the `@reduce` builtin.
    934         /// Uses the `pl_node` union field with payload `Bin`.
    935         reduce,
    936         /// Implements the `@shuffle` builtin.
    937         /// Uses the `pl_node` union field with payload `Shuffle`.
    938         shuffle,
    939         /// Implements the `@atomicLoad` builtin.
    940         /// Uses the `pl_node` union field with payload `AtomicLoad`.
    941         atomic_load,
    942         /// Implements the `@atomicRmw` builtin.
    943         /// Uses the `pl_node` union field with payload `AtomicRmw`.
    944         atomic_rmw,
    945         /// Implements the `@atomicStore` builtin.
    946         /// Uses the `pl_node` union field with payload `AtomicStore`.
    947         atomic_store,
    948         /// Implements the `@mulAdd` builtin.
    949         /// Uses the `pl_node` union field with payload `MulAdd`.
    950         /// The addend communicates the type of the builtin.
    951         /// The mulends need to be coerced to the same type.
    952         mul_add,
    953         /// Implements the `@fieldParentPtr` builtin.
    954         /// Uses the `pl_node` union field with payload `FieldParentPtr`.
    955         field_parent_ptr,
    956         /// Implements the `@memcpy` builtin.
    957         /// Uses the `pl_node` union field with payload `Bin`.
    958         memcpy,
    959         /// Implements the `@memset` builtin.
    960         /// Uses the `pl_node` union field with payload `Bin`.
    961         memset,
    962         /// Implements the `@min` builtin for 2 args.
    963         /// Uses the `pl_node` union field with payload `Bin`
    964         min,
    965         /// Implements the `@max` builtin for 2 args.
    966         /// Uses the `pl_node` union field with payload `Bin`
    967         max,
    968         /// Implements the `@cImport` builtin.
    969         /// Uses the `pl_node` union field with payload `Block`.
    970         c_import,
    971 
    972         /// Allocates stack local memory.
    973         /// Uses the `un_node` union field. The operand is the type of the allocated object.
    974         /// The node source location points to a var decl node.
    975         /// A `make_ptr_const` instruction should be used once the value has
    976         /// been stored to the allocation. To ensure comptime value detection
    977         /// functions, there are some restrictions on how this pointer should be
    978         /// used prior to the `make_ptr_const` instruction: no pointer derived
    979         /// from this `alloc` may be returned from a block or stored to another
    980         /// address. In other words, it must be trivial to determine whether any
    981         /// given pointer derives from this one.
    982         alloc,
    983         /// Same as `alloc` except mutable. As such, `make_ptr_const` need not be used,
    984         /// and there are no restrictions on the usage of the pointer.
    985         alloc_mut,
    986         /// Allocates comptime-mutable memory.
    987         /// Uses the `un_node` union field. The operand is the type of the allocated object.
    988         /// The node source location points to a var decl node.
    989         alloc_comptime_mut,
    990         /// Same as `alloc` except the type is inferred.
    991         /// Uses the `node` union field.
    992         alloc_inferred,
    993         /// Same as `alloc_inferred` except mutable.
    994         alloc_inferred_mut,
    995         /// Allocates comptime const memory.
    996         /// Uses the `node` union field. The type of the allocated object is inferred.
    997         /// The node source location points to a var decl node.
    998         alloc_inferred_comptime,
    999         /// Same as `alloc_comptime_mut` except the type is inferred.
   1000         alloc_inferred_comptime_mut,
   1001         /// Each `store_to_inferred_ptr` puts the type of the stored value into a set,
   1002         /// and then `resolve_inferred_alloc` triggers peer type resolution on the set.
   1003         /// The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which
   1004         /// is the allocation that needs to have its type inferred.
   1005         /// Uses the `un_node` field. The AST node is the var decl.
   1006         resolve_inferred_alloc,
   1007         /// Turns a pointer coming from an `alloc` or `Extended.alloc` into a constant
   1008         /// version of the same pointer. For inferred allocations this is instead implicitly
   1009         /// handled by the `resolve_inferred_alloc` instruction.
   1010         /// Uses the `un_node` union field.
   1011         make_ptr_const,
   1012 
   1013         /// Implements `resume` syntax. Uses `un_node` field.
   1014         @"resume",
   1015         @"await",
   1016 
   1017         /// When a type or function refers to a comptime value from an outer
   1018         /// scope, that forms a closure over comptime value.  The outer scope
   1019         /// will record a capture of that value, which encodes its current state
   1020         /// and marks it to persist.  Uses `un_tok` field.  Operand is the
   1021         /// instruction value to capture.
   1022         closure_capture,
   1023         /// The inner scope of a closure uses closure_get to retrieve the value
   1024         /// stored by the outer scope.  Uses `inst_node` field.  Operand is the
   1025         /// closure_capture instruction ref.
   1026         closure_get,
   1027 
   1028         /// A defer statement.
   1029         /// Uses the `defer` union field.
   1030         @"defer",
   1031         /// An errdefer statement with a code.
   1032         /// Uses the `err_defer_code` union field.
   1033         defer_err_code,
   1034 
   1035         /// Requests that Sema update the saved error return trace index for the enclosing
   1036         /// block, if the operand is .none or of an error/error-union type.
   1037         /// Uses the `save_err_ret_index` field.
   1038         save_err_ret_index,
   1039         /// Sets error return trace to zero if no operand is given,
   1040         /// otherwise sets the value to the given amount.
   1041         /// Uses the `restore_err_ret_index` union field.
   1042         restore_err_ret_index,
   1043 
   1044         /// The ZIR instruction tag is one of the `Extended` ones.
   1045         /// Uses the `extended` union field.
   1046         extended,
   1047 
   1048         /// Returns whether the instruction is one of the control flow "noreturn" types.
   1049         /// Function calls do not count.
   1050         pub fn isNoReturn(tag: Tag) bool {
   1051             return switch (tag) {
   1052                 .param,
   1053                 .param_comptime,
   1054                 .param_anytype,
   1055                 .param_anytype_comptime,
   1056                 .add,
   1057                 .addwrap,
   1058                 .add_sat,
   1059                 .add_unsafe,
   1060                 .alloc,
   1061                 .alloc_mut,
   1062                 .alloc_comptime_mut,
   1063                 .alloc_inferred,
   1064                 .alloc_inferred_mut,
   1065                 .alloc_inferred_comptime,
   1066                 .alloc_inferred_comptime_mut,
   1067                 .make_ptr_const,
   1068                 .array_cat,
   1069                 .array_mul,
   1070                 .array_type,
   1071                 .array_type_sentinel,
   1072                 .vector_type,
   1073                 .elem_type,
   1074                 .indexable_ptr_elem_type,
   1075                 .vector_elem_type,
   1076                 .indexable_ptr_len,
   1077                 .anyframe_type,
   1078                 .as_node,
   1079                 .as_shift_operand,
   1080                 .bit_and,
   1081                 .bitcast,
   1082                 .bit_or,
   1083                 .block,
   1084                 .block_comptime,
   1085                 .block_inline,
   1086                 .declaration,
   1087                 .suspend_block,
   1088                 .loop,
   1089                 .bool_br_and,
   1090                 .bool_br_or,
   1091                 .bool_not,
   1092                 .call,
   1093                 .field_call,
   1094                 .cmp_lt,
   1095                 .cmp_lte,
   1096                 .cmp_eq,
   1097                 .cmp_gte,
   1098                 .cmp_gt,
   1099                 .cmp_neq,
   1100                 .error_set_decl,
   1101                 .error_set_decl_anon,
   1102                 .error_set_decl_func,
   1103                 .dbg_stmt,
   1104                 .dbg_var_ptr,
   1105                 .dbg_var_val,
   1106                 .dbg_block_begin,
   1107                 .dbg_block_end,
   1108                 .decl_ref,
   1109                 .decl_val,
   1110                 .load,
   1111                 .div,
   1112                 .elem_ptr,
   1113                 .elem_val,
   1114                 .elem_ptr_node,
   1115                 .elem_val_node,
   1116                 .elem_val_imm,
   1117                 .ensure_result_used,
   1118                 .ensure_result_non_error,
   1119                 .ensure_err_union_payload_void,
   1120                 .@"export",
   1121                 .export_value,
   1122                 .field_ptr,
   1123                 .field_val,
   1124                 .field_ptr_named,
   1125                 .field_val_named,
   1126                 .func,
   1127                 .func_inferred,
   1128                 .func_fancy,
   1129                 .has_decl,
   1130                 .int,
   1131                 .int_big,
   1132                 .float,
   1133                 .float128,
   1134                 .int_type,
   1135                 .is_non_null,
   1136                 .is_non_null_ptr,
   1137                 .is_non_err,
   1138                 .is_non_err_ptr,
   1139                 .ret_is_non_err,
   1140                 .mod_rem,
   1141                 .mul,
   1142                 .mulwrap,
   1143                 .mul_sat,
   1144                 .ref,
   1145                 .shl,
   1146                 .shl_sat,
   1147                 .shr,
   1148                 .store,
   1149                 .store_node,
   1150                 .store_to_inferred_ptr,
   1151                 .str,
   1152                 .sub,
   1153                 .subwrap,
   1154                 .sub_sat,
   1155                 .negate,
   1156                 .negate_wrap,
   1157                 .typeof,
   1158                 .typeof_builtin,
   1159                 .xor,
   1160                 .optional_type,
   1161                 .optional_payload_safe,
   1162                 .optional_payload_unsafe,
   1163                 .optional_payload_safe_ptr,
   1164                 .optional_payload_unsafe_ptr,
   1165                 .err_union_payload_unsafe,
   1166                 .err_union_payload_unsafe_ptr,
   1167                 .err_union_code,
   1168                 .err_union_code_ptr,
   1169                 .ptr_type,
   1170                 .enum_literal,
   1171                 .merge_error_sets,
   1172                 .error_union_type,
   1173                 .bit_not,
   1174                 .error_value,
   1175                 .slice_start,
   1176                 .slice_end,
   1177                 .slice_sentinel,
   1178                 .slice_length,
   1179                 .import,
   1180                 .typeof_log2_int_type,
   1181                 .resolve_inferred_alloc,
   1182                 .set_eval_branch_quota,
   1183                 .switch_block,
   1184                 .switch_block_ref,
   1185                 .switch_block_err_union,
   1186                 .validate_deref,
   1187                 .validate_destructure,
   1188                 .union_init,
   1189                 .field_type_ref,
   1190                 .enum_from_int,
   1191                 .int_from_enum,
   1192                 .type_info,
   1193                 .size_of,
   1194                 .bit_size_of,
   1195                 .int_from_ptr,
   1196                 .align_of,
   1197                 .int_from_bool,
   1198                 .embed_file,
   1199                 .error_name,
   1200                 .set_runtime_safety,
   1201                 .sqrt,
   1202                 .sin,
   1203                 .cos,
   1204                 .tan,
   1205                 .exp,
   1206                 .exp2,
   1207                 .log,
   1208                 .log2,
   1209                 .log10,
   1210                 .abs,
   1211                 .floor,
   1212                 .ceil,
   1213                 .trunc,
   1214                 .round,
   1215                 .tag_name,
   1216                 .type_name,
   1217                 .frame_type,
   1218                 .frame_size,
   1219                 .int_from_float,
   1220                 .float_from_int,
   1221                 .ptr_from_int,
   1222                 .float_cast,
   1223                 .int_cast,
   1224                 .ptr_cast,
   1225                 .truncate,
   1226                 .has_field,
   1227                 .clz,
   1228                 .ctz,
   1229                 .pop_count,
   1230                 .byte_swap,
   1231                 .bit_reverse,
   1232                 .div_exact,
   1233                 .div_floor,
   1234                 .div_trunc,
   1235                 .mod,
   1236                 .rem,
   1237                 .shl_exact,
   1238                 .shr_exact,
   1239                 .bit_offset_of,
   1240                 .offset_of,
   1241                 .splat,
   1242                 .reduce,
   1243                 .shuffle,
   1244                 .atomic_load,
   1245                 .atomic_rmw,
   1246                 .atomic_store,
   1247                 .mul_add,
   1248                 .builtin_call,
   1249                 .field_parent_ptr,
   1250                 .max,
   1251                 .memcpy,
   1252                 .memset,
   1253                 .min,
   1254                 .c_import,
   1255                 .@"resume",
   1256                 .@"await",
   1257                 .ret_err_value_code,
   1258                 .extended,
   1259                 .closure_get,
   1260                 .closure_capture,
   1261                 .ret_ptr,
   1262                 .ret_type,
   1263                 .@"try",
   1264                 .try_ptr,
   1265                 .@"defer",
   1266                 .defer_err_code,
   1267                 .save_err_ret_index,
   1268                 .restore_err_ret_index,
   1269                 .for_len,
   1270                 .opt_eu_base_ptr_init,
   1271                 .coerce_ptr_elem_ty,
   1272                 .struct_init_empty,
   1273                 .struct_init_empty_result,
   1274                 .struct_init_empty_ref_result,
   1275                 .struct_init_anon,
   1276                 .struct_init,
   1277                 .struct_init_ref,
   1278                 .validate_struct_init_ty,
   1279                 .validate_struct_init_result_ty,
   1280                 .validate_ptr_struct_init,
   1281                 .struct_init_field_type,
   1282                 .struct_init_field_ptr,
   1283                 .array_init_anon,
   1284                 .array_init,
   1285                 .array_init_ref,
   1286                 .validate_array_init_ty,
   1287                 .validate_array_init_result_ty,
   1288                 .validate_array_init_ref_ty,
   1289                 .validate_ptr_array_init,
   1290                 .array_init_elem_type,
   1291                 .array_init_elem_ptr,
   1292                 .validate_ref_ty,
   1293                 => false,
   1294 
   1295                 .@"break",
   1296                 .break_inline,
   1297                 .condbr,
   1298                 .condbr_inline,
   1299                 .compile_error,
   1300                 .ret_node,
   1301                 .ret_load,
   1302                 .ret_implicit,
   1303                 .ret_err_value,
   1304                 .@"unreachable",
   1305                 .repeat,
   1306                 .repeat_inline,
   1307                 .panic,
   1308                 .trap,
   1309                 .check_comptime_control_flow,
   1310                 => true,
   1311             };
   1312         }
   1313 
   1314         pub fn isParam(tag: Tag) bool {
   1315             return switch (tag) {
   1316                 .param,
   1317                 .param_comptime,
   1318                 .param_anytype,
   1319                 .param_anytype_comptime,
   1320                 => true,
   1321 
   1322                 else => false,
   1323             };
   1324         }
   1325 
   1326         /// AstGen uses this to find out if `Ref.void_value` should be used in place
   1327         /// of the result of a given instruction. This allows Sema to forego adding
   1328         /// the instruction to the map after analysis.
   1329         pub fn isAlwaysVoid(tag: Tag, data: Data) bool {
   1330             return switch (tag) {
   1331                 .dbg_stmt,
   1332                 .dbg_var_ptr,
   1333                 .dbg_var_val,
   1334                 .dbg_block_begin,
   1335                 .dbg_block_end,
   1336                 .ensure_result_used,
   1337                 .ensure_result_non_error,
   1338                 .ensure_err_union_payload_void,
   1339                 .set_eval_branch_quota,
   1340                 .atomic_store,
   1341                 .store,
   1342                 .store_node,
   1343                 .store_to_inferred_ptr,
   1344                 .resolve_inferred_alloc,
   1345                 .validate_deref,
   1346                 .validate_destructure,
   1347                 .@"export",
   1348                 .export_value,
   1349                 .set_runtime_safety,
   1350                 .memcpy,
   1351                 .memset,
   1352                 .check_comptime_control_flow,
   1353                 .@"defer",
   1354                 .defer_err_code,
   1355                 .restore_err_ret_index,
   1356                 .save_err_ret_index,
   1357                 .validate_struct_init_ty,
   1358                 .validate_struct_init_result_ty,
   1359                 .validate_ptr_struct_init,
   1360                 .validate_array_init_ty,
   1361                 .validate_array_init_result_ty,
   1362                 .validate_ptr_array_init,
   1363                 .validate_ref_ty,
   1364                 => true,
   1365 
   1366                 .param,
   1367                 .param_comptime,
   1368                 .param_anytype,
   1369                 .param_anytype_comptime,
   1370                 .add,
   1371                 .addwrap,
   1372                 .add_sat,
   1373                 .add_unsafe,
   1374                 .alloc,
   1375                 .alloc_mut,
   1376                 .alloc_comptime_mut,
   1377                 .alloc_inferred,
   1378                 .alloc_inferred_mut,
   1379                 .alloc_inferred_comptime,
   1380                 .alloc_inferred_comptime_mut,
   1381                 .make_ptr_const,
   1382                 .array_cat,
   1383                 .array_mul,
   1384                 .array_type,
   1385                 .array_type_sentinel,
   1386                 .vector_type,
   1387                 .elem_type,
   1388                 .indexable_ptr_elem_type,
   1389                 .vector_elem_type,
   1390                 .indexable_ptr_len,
   1391                 .anyframe_type,
   1392                 .as_node,
   1393                 .as_shift_operand,
   1394                 .bit_and,
   1395                 .bitcast,
   1396                 .bit_or,
   1397                 .block,
   1398                 .block_comptime,
   1399                 .block_inline,
   1400                 .declaration,
   1401                 .suspend_block,
   1402                 .loop,
   1403                 .bool_br_and,
   1404                 .bool_br_or,
   1405                 .bool_not,
   1406                 .call,
   1407                 .field_call,
   1408                 .cmp_lt,
   1409                 .cmp_lte,
   1410                 .cmp_eq,
   1411                 .cmp_gte,
   1412                 .cmp_gt,
   1413                 .cmp_neq,
   1414                 .error_set_decl,
   1415                 .error_set_decl_anon,
   1416                 .error_set_decl_func,
   1417                 .decl_ref,
   1418                 .decl_val,
   1419                 .load,
   1420                 .div,
   1421                 .elem_ptr,
   1422                 .elem_val,
   1423                 .elem_ptr_node,
   1424                 .elem_val_node,
   1425                 .elem_val_imm,
   1426                 .field_ptr,
   1427                 .field_val,
   1428                 .field_ptr_named,
   1429                 .field_val_named,
   1430                 .func,
   1431                 .func_inferred,
   1432                 .func_fancy,
   1433                 .has_decl,
   1434                 .int,
   1435                 .int_big,
   1436                 .float,
   1437                 .float128,
   1438                 .int_type,
   1439                 .is_non_null,
   1440                 .is_non_null_ptr,
   1441                 .is_non_err,
   1442                 .is_non_err_ptr,
   1443                 .ret_is_non_err,
   1444                 .mod_rem,
   1445                 .mul,
   1446                 .mulwrap,
   1447                 .mul_sat,
   1448                 .ref,
   1449                 .shl,
   1450                 .shl_sat,
   1451                 .shr,
   1452                 .str,
   1453                 .sub,
   1454                 .subwrap,
   1455                 .sub_sat,
   1456                 .negate,
   1457                 .negate_wrap,
   1458                 .typeof,
   1459                 .typeof_builtin,
   1460                 .xor,
   1461                 .optional_type,
   1462                 .optional_payload_safe,
   1463                 .optional_payload_unsafe,
   1464                 .optional_payload_safe_ptr,
   1465                 .optional_payload_unsafe_ptr,
   1466                 .err_union_payload_unsafe,
   1467                 .err_union_payload_unsafe_ptr,
   1468                 .err_union_code,
   1469                 .err_union_code_ptr,
   1470                 .ptr_type,
   1471                 .enum_literal,
   1472                 .merge_error_sets,
   1473                 .error_union_type,
   1474                 .bit_not,
   1475                 .error_value,
   1476                 .slice_start,
   1477                 .slice_end,
   1478                 .slice_sentinel,
   1479                 .slice_length,
   1480                 .import,
   1481                 .typeof_log2_int_type,
   1482                 .switch_block,
   1483                 .switch_block_ref,
   1484                 .switch_block_err_union,
   1485                 .union_init,
   1486                 .field_type_ref,
   1487                 .enum_from_int,
   1488                 .int_from_enum,
   1489                 .type_info,
   1490                 .size_of,
   1491                 .bit_size_of,
   1492                 .int_from_ptr,
   1493                 .align_of,
   1494                 .int_from_bool,
   1495                 .embed_file,
   1496                 .error_name,
   1497                 .sqrt,
   1498                 .sin,
   1499                 .cos,
   1500                 .tan,
   1501                 .exp,
   1502                 .exp2,
   1503                 .log,
   1504                 .log2,
   1505                 .log10,
   1506                 .abs,
   1507                 .floor,
   1508                 .ceil,
   1509                 .trunc,
   1510                 .round,
   1511                 .tag_name,
   1512                 .type_name,
   1513                 .frame_type,
   1514                 .frame_size,
   1515                 .int_from_float,
   1516                 .float_from_int,
   1517                 .ptr_from_int,
   1518                 .float_cast,
   1519                 .int_cast,
   1520                 .ptr_cast,
   1521                 .truncate,
   1522                 .has_field,
   1523                 .clz,
   1524                 .ctz,
   1525                 .pop_count,
   1526                 .byte_swap,
   1527                 .bit_reverse,
   1528                 .div_exact,
   1529                 .div_floor,
   1530                 .div_trunc,
   1531                 .mod,
   1532                 .rem,
   1533                 .shl_exact,
   1534                 .shr_exact,
   1535                 .bit_offset_of,
   1536                 .offset_of,
   1537                 .splat,
   1538                 .reduce,
   1539                 .shuffle,
   1540                 .atomic_load,
   1541                 .atomic_rmw,
   1542                 .mul_add,
   1543                 .builtin_call,
   1544                 .field_parent_ptr,
   1545                 .max,
   1546                 .min,
   1547                 .c_import,
   1548                 .@"resume",
   1549                 .@"await",
   1550                 .ret_err_value_code,
   1551                 .closure_get,
   1552                 .closure_capture,
   1553                 .@"break",
   1554                 .break_inline,
   1555                 .condbr,
   1556                 .condbr_inline,
   1557                 .compile_error,
   1558                 .ret_node,
   1559                 .ret_load,
   1560                 .ret_implicit,
   1561                 .ret_err_value,
   1562                 .ret_ptr,
   1563                 .ret_type,
   1564                 .@"unreachable",
   1565                 .repeat,
   1566                 .repeat_inline,
   1567                 .panic,
   1568                 .trap,
   1569                 .for_len,
   1570                 .@"try",
   1571                 .try_ptr,
   1572                 .opt_eu_base_ptr_init,
   1573                 .coerce_ptr_elem_ty,
   1574                 .struct_init_empty,
   1575                 .struct_init_empty_result,
   1576                 .struct_init_empty_ref_result,
   1577                 .struct_init_anon,
   1578                 .struct_init,
   1579                 .struct_init_ref,
   1580                 .struct_init_field_type,
   1581                 .struct_init_field_ptr,
   1582                 .array_init_anon,
   1583                 .array_init,
   1584                 .array_init_ref,
   1585                 .validate_array_init_ref_ty,
   1586                 .array_init_elem_type,
   1587                 .array_init_elem_ptr,
   1588                 => false,
   1589 
   1590                 .extended => switch (data.extended.opcode) {
   1591                     .fence, .set_cold, .breakpoint => true,
   1592                     else => false,
   1593                 },
   1594             };
   1595         }
   1596 
   1597         /// Used by debug safety-checking code.
   1598         pub const data_tags = list: {
   1599             @setEvalBranchQuota(2000);
   1600             break :list std.enums.directEnumArray(Tag, Data.FieldEnum, 0, .{
   1601                 .add = .pl_node,
   1602                 .addwrap = .pl_node,
   1603                 .add_sat = .pl_node,
   1604                 .add_unsafe = .pl_node,
   1605                 .sub = .pl_node,
   1606                 .subwrap = .pl_node,
   1607                 .sub_sat = .pl_node,
   1608                 .mul = .pl_node,
   1609                 .mulwrap = .pl_node,
   1610                 .mul_sat = .pl_node,
   1611 
   1612                 .param = .pl_tok,
   1613                 .param_comptime = .pl_tok,
   1614                 .param_anytype = .str_tok,
   1615                 .param_anytype_comptime = .str_tok,
   1616                 .array_cat = .pl_node,
   1617                 .array_mul = .pl_node,
   1618                 .array_type = .pl_node,
   1619                 .array_type_sentinel = .pl_node,
   1620                 .vector_type = .pl_node,
   1621                 .elem_type = .un_node,
   1622                 .indexable_ptr_elem_type = .un_node,
   1623                 .vector_elem_type = .un_node,
   1624                 .indexable_ptr_len = .un_node,
   1625                 .anyframe_type = .un_node,
   1626                 .as_node = .pl_node,
   1627                 .as_shift_operand = .pl_node,
   1628                 .bit_and = .pl_node,
   1629                 .bitcast = .pl_node,
   1630                 .bit_not = .un_node,
   1631                 .bit_or = .pl_node,
   1632                 .block = .pl_node,
   1633                 .block_comptime = .pl_node,
   1634                 .block_inline = .pl_node,
   1635                 .declaration = .pl_node,
   1636                 .suspend_block = .pl_node,
   1637                 .bool_not = .un_node,
   1638                 .bool_br_and = .bool_br,
   1639                 .bool_br_or = .bool_br,
   1640                 .@"break" = .@"break",
   1641                 .break_inline = .@"break",
   1642                 .check_comptime_control_flow = .un_node,
   1643                 .for_len = .pl_node,
   1644                 .call = .pl_node,
   1645                 .field_call = .pl_node,
   1646                 .cmp_lt = .pl_node,
   1647                 .cmp_lte = .pl_node,
   1648                 .cmp_eq = .pl_node,
   1649                 .cmp_gte = .pl_node,
   1650                 .cmp_gt = .pl_node,
   1651                 .cmp_neq = .pl_node,
   1652                 .condbr = .pl_node,
   1653                 .condbr_inline = .pl_node,
   1654                 .@"try" = .pl_node,
   1655                 .try_ptr = .pl_node,
   1656                 .error_set_decl = .pl_node,
   1657                 .error_set_decl_anon = .pl_node,
   1658                 .error_set_decl_func = .pl_node,
   1659                 .dbg_stmt = .dbg_stmt,
   1660                 .dbg_var_ptr = .str_op,
   1661                 .dbg_var_val = .str_op,
   1662                 .dbg_block_begin = .tok,
   1663                 .dbg_block_end = .tok,
   1664                 .decl_ref = .str_tok,
   1665                 .decl_val = .str_tok,
   1666                 .load = .un_node,
   1667                 .div = .pl_node,
   1668                 .elem_ptr = .pl_node,
   1669                 .elem_ptr_node = .pl_node,
   1670                 .elem_val = .pl_node,
   1671                 .elem_val_node = .pl_node,
   1672                 .elem_val_imm = .elem_val_imm,
   1673                 .ensure_result_used = .un_node,
   1674                 .ensure_result_non_error = .un_node,
   1675                 .ensure_err_union_payload_void = .un_node,
   1676                 .error_union_type = .pl_node,
   1677                 .error_value = .str_tok,
   1678                 .@"export" = .pl_node,
   1679                 .export_value = .pl_node,
   1680                 .field_ptr = .pl_node,
   1681                 .field_val = .pl_node,
   1682                 .field_ptr_named = .pl_node,
   1683                 .field_val_named = .pl_node,
   1684                 .func = .pl_node,
   1685                 .func_inferred = .pl_node,
   1686                 .func_fancy = .pl_node,
   1687                 .import = .str_tok,
   1688                 .int = .int,
   1689                 .int_big = .str,
   1690                 .float = .float,
   1691                 .float128 = .pl_node,
   1692                 .int_type = .int_type,
   1693                 .is_non_null = .un_node,
   1694                 .is_non_null_ptr = .un_node,
   1695                 .is_non_err = .un_node,
   1696                 .is_non_err_ptr = .un_node,
   1697                 .ret_is_non_err = .un_node,
   1698                 .loop = .pl_node,
   1699                 .repeat = .node,
   1700                 .repeat_inline = .node,
   1701                 .merge_error_sets = .pl_node,
   1702                 .mod_rem = .pl_node,
   1703                 .ref = .un_tok,
   1704                 .ret_node = .un_node,
   1705                 .ret_load = .un_node,
   1706                 .ret_implicit = .un_tok,
   1707                 .ret_err_value = .str_tok,
   1708                 .ret_err_value_code = .str_tok,
   1709                 .ret_ptr = .node,
   1710                 .ret_type = .node,
   1711                 .ptr_type = .ptr_type,
   1712                 .slice_start = .pl_node,
   1713                 .slice_end = .pl_node,
   1714                 .slice_sentinel = .pl_node,
   1715                 .slice_length = .pl_node,
   1716                 .store = .bin,
   1717                 .store_node = .pl_node,
   1718                 .store_to_inferred_ptr = .bin,
   1719                 .str = .str,
   1720                 .negate = .un_node,
   1721                 .negate_wrap = .un_node,
   1722                 .typeof = .un_node,
   1723                 .typeof_log2_int_type = .un_node,
   1724                 .@"unreachable" = .@"unreachable",
   1725                 .xor = .pl_node,
   1726                 .optional_type = .un_node,
   1727                 .optional_payload_safe = .un_node,
   1728                 .optional_payload_unsafe = .un_node,
   1729                 .optional_payload_safe_ptr = .un_node,
   1730                 .optional_payload_unsafe_ptr = .un_node,
   1731                 .err_union_payload_unsafe = .un_node,
   1732                 .err_union_payload_unsafe_ptr = .un_node,
   1733                 .err_union_code = .un_node,
   1734                 .err_union_code_ptr = .un_node,
   1735                 .enum_literal = .str_tok,
   1736                 .switch_block = .pl_node,
   1737                 .switch_block_ref = .pl_node,
   1738                 .switch_block_err_union = .pl_node,
   1739                 .validate_deref = .un_node,
   1740                 .validate_destructure = .pl_node,
   1741                 .field_type_ref = .pl_node,
   1742                 .union_init = .pl_node,
   1743                 .type_info = .un_node,
   1744                 .size_of = .un_node,
   1745                 .bit_size_of = .un_node,
   1746                 .opt_eu_base_ptr_init = .un_node,
   1747                 .coerce_ptr_elem_ty = .pl_node,
   1748                 .validate_ref_ty = .un_tok,
   1749 
   1750                 .int_from_ptr = .un_node,
   1751                 .compile_error = .un_node,
   1752                 .set_eval_branch_quota = .un_node,
   1753                 .int_from_enum = .un_node,
   1754                 .align_of = .un_node,
   1755                 .int_from_bool = .un_node,
   1756                 .embed_file = .un_node,
   1757                 .error_name = .un_node,
   1758                 .panic = .un_node,
   1759                 .trap = .node,
   1760                 .set_runtime_safety = .un_node,
   1761                 .sqrt = .un_node,
   1762                 .sin = .un_node,
   1763                 .cos = .un_node,
   1764                 .tan = .un_node,
   1765                 .exp = .un_node,
   1766                 .exp2 = .un_node,
   1767                 .log = .un_node,
   1768                 .log2 = .un_node,
   1769                 .log10 = .un_node,
   1770                 .abs = .un_node,
   1771                 .floor = .un_node,
   1772                 .ceil = .un_node,
   1773                 .trunc = .un_node,
   1774                 .round = .un_node,
   1775                 .tag_name = .un_node,
   1776                 .type_name = .un_node,
   1777                 .frame_type = .un_node,
   1778                 .frame_size = .un_node,
   1779 
   1780                 .int_from_float = .pl_node,
   1781                 .float_from_int = .pl_node,
   1782                 .ptr_from_int = .pl_node,
   1783                 .enum_from_int = .pl_node,
   1784                 .float_cast = .pl_node,
   1785                 .int_cast = .pl_node,
   1786                 .ptr_cast = .pl_node,
   1787                 .truncate = .pl_node,
   1788                 .typeof_builtin = .pl_node,
   1789 
   1790                 .has_decl = .pl_node,
   1791                 .has_field = .pl_node,
   1792 
   1793                 .clz = .un_node,
   1794                 .ctz = .un_node,
   1795                 .pop_count = .un_node,
   1796                 .byte_swap = .un_node,
   1797                 .bit_reverse = .un_node,
   1798 
   1799                 .div_exact = .pl_node,
   1800                 .div_floor = .pl_node,
   1801                 .div_trunc = .pl_node,
   1802                 .mod = .pl_node,
   1803                 .rem = .pl_node,
   1804 
   1805                 .shl = .pl_node,
   1806                 .shl_exact = .pl_node,
   1807                 .shl_sat = .pl_node,
   1808                 .shr = .pl_node,
   1809                 .shr_exact = .pl_node,
   1810 
   1811                 .bit_offset_of = .pl_node,
   1812                 .offset_of = .pl_node,
   1813                 .splat = .pl_node,
   1814                 .reduce = .pl_node,
   1815                 .shuffle = .pl_node,
   1816                 .atomic_load = .pl_node,
   1817                 .atomic_rmw = .pl_node,
   1818                 .atomic_store = .pl_node,
   1819                 .mul_add = .pl_node,
   1820                 .builtin_call = .pl_node,
   1821                 .field_parent_ptr = .pl_node,
   1822                 .max = .pl_node,
   1823                 .memcpy = .pl_node,
   1824                 .memset = .pl_node,
   1825                 .min = .pl_node,
   1826                 .c_import = .pl_node,
   1827 
   1828                 .alloc = .un_node,
   1829                 .alloc_mut = .un_node,
   1830                 .alloc_comptime_mut = .un_node,
   1831                 .alloc_inferred = .node,
   1832                 .alloc_inferred_mut = .node,
   1833                 .alloc_inferred_comptime = .node,
   1834                 .alloc_inferred_comptime_mut = .node,
   1835                 .resolve_inferred_alloc = .un_node,
   1836                 .make_ptr_const = .un_node,
   1837 
   1838                 .@"resume" = .un_node,
   1839                 .@"await" = .un_node,
   1840 
   1841                 .closure_capture = .un_tok,
   1842                 .closure_get = .inst_node,
   1843 
   1844                 .@"defer" = .@"defer",
   1845                 .defer_err_code = .defer_err_code,
   1846 
   1847                 .save_err_ret_index = .save_err_ret_index,
   1848                 .restore_err_ret_index = .restore_err_ret_index,
   1849 
   1850                 .struct_init_empty = .un_node,
   1851                 .struct_init_empty_result = .un_node,
   1852                 .struct_init_empty_ref_result = .un_node,
   1853                 .struct_init_anon = .pl_node,
   1854                 .struct_init = .pl_node,
   1855                 .struct_init_ref = .pl_node,
   1856                 .validate_struct_init_ty = .un_node,
   1857                 .validate_struct_init_result_ty = .un_node,
   1858                 .validate_ptr_struct_init = .pl_node,
   1859                 .struct_init_field_type = .pl_node,
   1860                 .struct_init_field_ptr = .pl_node,
   1861                 .array_init_anon = .pl_node,
   1862                 .array_init = .pl_node,
   1863                 .array_init_ref = .pl_node,
   1864                 .validate_array_init_ty = .pl_node,
   1865                 .validate_array_init_result_ty = .pl_node,
   1866                 .validate_array_init_ref_ty = .pl_node,
   1867                 .validate_ptr_array_init = .pl_node,
   1868                 .array_init_elem_type = .bin,
   1869                 .array_init_elem_ptr = .pl_node,
   1870 
   1871                 .extended = .extended,
   1872             });
   1873         };
   1874 
   1875         // Uncomment to view how many tag slots are available.
   1876         //comptime {
   1877         //    @compileLog("ZIR tags left: ", 256 - @typeInfo(Tag).Enum.fields.len);
   1878         //}
   1879     };
   1880 
   1881     /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum.
   1882     /// `noreturn` instructions may not go here; they must be part of the main `Tag` enum.
   1883     pub const Extended = enum(u16) {
   1884         /// Declares a global variable.
   1885         /// `operand` is payload index to `ExtendedVar`.
   1886         /// `small` is `ExtendedVar.Small`.
   1887         variable,
   1888         /// A struct type definition. Contains references to ZIR instructions for
   1889         /// the field types, defaults, and alignments.
   1890         /// `operand` is payload index to `StructDecl`.
   1891         /// `small` is `StructDecl.Small`.
   1892         struct_decl,
   1893         /// An enum type definition. Contains references to ZIR instructions for
   1894         /// the field value expressions and optional type tag expression.
   1895         /// `operand` is payload index to `EnumDecl`.
   1896         /// `small` is `EnumDecl.Small`.
   1897         enum_decl,
   1898         /// A union type definition. Contains references to ZIR instructions for
   1899         /// the field types and optional type tag expression.
   1900         /// `operand` is payload index to `UnionDecl`.
   1901         /// `small` is `UnionDecl.Small`.
   1902         union_decl,
   1903         /// An opaque type definition. Contains references to decls and captures.
   1904         /// `operand` is payload index to `OpaqueDecl`.
   1905         /// `small` is `OpaqueDecl.Small`.
   1906         opaque_decl,
   1907         /// Implements the `@This` builtin.
   1908         /// `operand` is `src_node: i32`.
   1909         this,
   1910         /// Implements the `@returnAddress` builtin.
   1911         /// `operand` is `src_node: i32`.
   1912         ret_addr,
   1913         /// Implements the `@src` builtin.
   1914         /// `operand` is payload index to `LineColumn`.
   1915         builtin_src,
   1916         /// Implements the `@errorReturnTrace` builtin.
   1917         /// `operand` is `src_node: i32`.
   1918         error_return_trace,
   1919         /// Implements the `@frame` builtin.
   1920         /// `operand` is `src_node: i32`.
   1921         frame,
   1922         /// Implements the `@frameAddress` builtin.
   1923         /// `operand` is `src_node: i32`.
   1924         frame_address,
   1925         /// Same as `alloc` from `Tag` but may contain an alignment instruction.
   1926         /// `operand` is payload index to `AllocExtended`.
   1927         /// `small`:
   1928         ///  * 0b000X - has type
   1929         ///  * 0b00X0 - has alignment
   1930         ///  * 0b0X00 - 1=const, 0=var
   1931         ///  * 0bX000 - is comptime
   1932         alloc,
   1933         /// The `@extern` builtin.
   1934         /// `operand` is payload index to `BinNode`.
   1935         builtin_extern,
   1936         /// Inline assembly.
   1937         /// `small`:
   1938         ///  * 0b00000000_000XXXXX - `outputs_len`.
   1939         ///  * 0b000000XX_XXX00000 - `inputs_len`.
   1940         ///  * 0b0XXXXX00_00000000 - `clobbers_len`.
   1941         ///  * 0bX0000000_00000000 - is volatile
   1942         /// `operand` is payload index to `Asm`.
   1943         @"asm",
   1944         /// Same as `asm` except the assembly template is not a string literal but a comptime
   1945         /// expression.
   1946         /// The `asm_source` field of the Asm is not a null-terminated string
   1947         /// but instead a Ref.
   1948         asm_expr,
   1949         /// Log compile time variables and emit an error message.
   1950         /// `operand` is payload index to `NodeMultiOp`.
   1951         /// `small` is `operands_len`.
   1952         /// The AST node is the compile log builtin call.
   1953         compile_log,
   1954         /// The builtin `@TypeOf` which returns the type after Peer Type Resolution
   1955         /// of one or more params.
   1956         /// `operand` is payload index to `TypeOfPeer`.
   1957         /// `small` is `operands_len`.
   1958         /// The AST node is the builtin call.
   1959         typeof_peer,
   1960         /// Implements the `@min` builtin for more than 2 args.
   1961         /// `operand` is payload index to `NodeMultiOp`.
   1962         /// `small` is `operands_len`.
   1963         /// The AST node is the builtin call.
   1964         min_multi,
   1965         /// Implements the `@max` builtin for more than 2 args.
   1966         /// `operand` is payload index to `NodeMultiOp`.
   1967         /// `small` is `operands_len`.
   1968         /// The AST node is the builtin call.
   1969         max_multi,
   1970         /// Implements the `@addWithOverflow` builtin.
   1971         /// `operand` is payload index to `BinNode`.
   1972         /// `small` is unused.
   1973         add_with_overflow,
   1974         /// Implements the `@subWithOverflow` builtin.
   1975         /// `operand` is payload index to `BinNode`.
   1976         /// `small` is unused.
   1977         sub_with_overflow,
   1978         /// Implements the `@mulWithOverflow` builtin.
   1979         /// `operand` is payload index to `BinNode`.
   1980         /// `small` is unused.
   1981         mul_with_overflow,
   1982         /// Implements the `@shlWithOverflow` builtin.
   1983         /// `operand` is payload index to `BinNode`.
   1984         /// `small` is unused.
   1985         shl_with_overflow,
   1986         /// `operand` is payload index to `UnNode`.
   1987         c_undef,
   1988         /// `operand` is payload index to `UnNode`.
   1989         c_include,
   1990         /// `operand` is payload index to `BinNode`.
   1991         c_define,
   1992         /// `operand` is payload index to `UnNode`.
   1993         wasm_memory_size,
   1994         /// `operand` is payload index to `BinNode`.
   1995         wasm_memory_grow,
   1996         /// The `@prefetch` builtin.
   1997         /// `operand` is payload index to `BinNode`.
   1998         prefetch,
   1999         /// Implements the `@fence` builtin.
   2000         /// `operand` is payload index to `UnNode`.
   2001         fence,
   2002         /// Implement builtin `@setFloatMode`.
   2003         /// `operand` is payload index to `UnNode`.
   2004         set_float_mode,
   2005         /// Implement builtin `@setAlignStack`.
   2006         /// `operand` is payload index to `UnNode`.
   2007         set_align_stack,
   2008         /// Implements `@setCold`.
   2009         /// `operand` is payload index to `UnNode`.
   2010         set_cold,
   2011         /// Implements the `@errorCast` builtin.
   2012         /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.
   2013         error_cast,
   2014         /// `operand` is payload index to `UnNode`.
   2015         await_nosuspend,
   2016         /// Implements `@breakpoint`.
   2017         /// `operand` is `src_node: i32`.
   2018         breakpoint,
   2019         /// Implements the `@select` builtin.
   2020         /// `operand` is payload index to `Select`.
   2021         select,
   2022         /// Implement builtin `@errToInt`.
   2023         /// `operand` is payload index to `UnNode`.
   2024         int_from_error,
   2025         /// Implement builtin `@errorFromInt`.
   2026         /// `operand` is payload index to `UnNode`.
   2027         error_from_int,
   2028         /// Implement builtin `@Type`.
   2029         /// `operand` is payload index to `UnNode`.
   2030         /// `small` contains `NameStrategy`.
   2031         reify,
   2032         /// Implements the `@asyncCall` builtin.
   2033         /// `operand` is payload index to `AsyncCall`.
   2034         builtin_async_call,
   2035         /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
   2036         /// `small` 0=>weak 1=>strong
   2037         /// `operand` is payload index to `Cmpxchg`.
   2038         cmpxchg,
   2039         /// Implement builtin `@cVaArg`.
   2040         /// `operand` is payload index to `BinNode`.
   2041         c_va_arg,
   2042         /// Implement builtin `@cVaCopy`.
   2043         /// `operand` is payload index to `UnNode`.
   2044         c_va_copy,
   2045         /// Implement builtin `@cVaEnd`.
   2046         /// `operand` is payload index to `UnNode`.
   2047         c_va_end,
   2048         /// Implement builtin `@cVaStart`.
   2049         /// `operand` is `src_node: i32`.
   2050         c_va_start,
   2051         /// Implements the following builtins:
   2052         /// `@ptrCast`, `@alignCast`, `@addrSpaceCast`, `@constCast`, `@volatileCast`.
   2053         /// Represents an arbitrary nesting of the above builtins. Such a nesting is treated as a
   2054         /// single operation which can modify multiple components of a pointer type.
   2055         /// `operand` is payload index to `BinNode`.
   2056         /// `small` contains `FullPtrCastFlags`.
   2057         /// AST node is the root of the nested casts.
   2058         /// `lhs` is dest type, `rhs` is operand.
   2059         ptr_cast_full,
   2060         /// `operand` is payload index to `UnNode`.
   2061         /// `small` contains `FullPtrCastFlags`.
   2062         /// Guaranteed to only have flags where no explicit destination type is
   2063         /// required (const_cast and volatile_cast).
   2064         /// AST node is the root of the nested casts.
   2065         ptr_cast_no_dest,
   2066         /// Implements the `@workItemId` builtin.
   2067         /// `operand` is payload index to `UnNode`.
   2068         work_item_id,
   2069         /// Implements the `@workGroupSize` builtin.
   2070         /// `operand` is payload index to `UnNode`.
   2071         work_group_size,
   2072         /// Implements the `@workGroupId` builtin.
   2073         /// `operand` is payload index to `UnNode`.
   2074         work_group_id,
   2075         /// Implements the `@inComptime` builtin.
   2076         /// `operand` is `src_node: i32`.
   2077         in_comptime,
   2078         /// Used as a placeholder instruction which is just a dummy index for Sema to replace
   2079         /// with a specific value. For instance, this is used for the capture of an `errdefer`.
   2080         /// This should never appear in a body.
   2081         value_placeholder,
   2082 
   2083         pub const InstData = struct {
   2084             opcode: Extended,
   2085             small: u16,
   2086             operand: u32,
   2087         };
   2088     };
   2089 
   2090     /// The position of a ZIR instruction within the `Zir` instructions array.
   2091     pub const Index = enum(u32) {
   2092         /// ZIR is structured so that the outermost "main" struct of any file
   2093         /// is always at index 0.
   2094         main_struct_inst = 0,
   2095         ref_start_index = InternPool.static_len,
   2096         _,
   2097 
   2098         pub fn toRef(i: Index) Inst.Ref {
   2099             return @enumFromInt(@intFromEnum(Index.ref_start_index) + @intFromEnum(i));
   2100         }
   2101 
   2102         pub fn toOptional(i: Index) OptionalIndex {
   2103             return @enumFromInt(@intFromEnum(i));
   2104         }
   2105     };
   2106 
   2107     pub const OptionalIndex = enum(u32) {
   2108         /// ZIR is structured so that the outermost "main" struct of any file
   2109         /// is always at index 0.
   2110         main_struct_inst = 0,
   2111         ref_start_index = InternPool.static_len,
   2112         none = std.math.maxInt(u32),
   2113         _,
   2114 
   2115         pub fn unwrap(oi: OptionalIndex) ?Index {
   2116             return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
   2117         }
   2118     };
   2119 
   2120     /// A reference to ZIR instruction, or to an InternPool index, or neither.
   2121     ///
   2122     /// If the integer tag value is < InternPool.static_len, then it
   2123     /// corresponds to an InternPool index. Otherwise, this refers to a ZIR
   2124     /// instruction.
   2125     ///
   2126     /// The tag type is specified so that it is safe to bitcast between `[]u32`
   2127     /// and `[]Ref`.
   2128     pub const Ref = enum(u32) {
   2129         u0_type = @intFromEnum(InternPool.Index.u0_type),
   2130         i0_type = @intFromEnum(InternPool.Index.i0_type),
   2131         u1_type = @intFromEnum(InternPool.Index.u1_type),
   2132         u8_type = @intFromEnum(InternPool.Index.u8_type),
   2133         i8_type = @intFromEnum(InternPool.Index.i8_type),
   2134         u16_type = @intFromEnum(InternPool.Index.u16_type),
   2135         i16_type = @intFromEnum(InternPool.Index.i16_type),
   2136         u29_type = @intFromEnum(InternPool.Index.u29_type),
   2137         u32_type = @intFromEnum(InternPool.Index.u32_type),
   2138         i32_type = @intFromEnum(InternPool.Index.i32_type),
   2139         u64_type = @intFromEnum(InternPool.Index.u64_type),
   2140         i64_type = @intFromEnum(InternPool.Index.i64_type),
   2141         u80_type = @intFromEnum(InternPool.Index.u80_type),
   2142         u128_type = @intFromEnum(InternPool.Index.u128_type),
   2143         i128_type = @intFromEnum(InternPool.Index.i128_type),
   2144         usize_type = @intFromEnum(InternPool.Index.usize_type),
   2145         isize_type = @intFromEnum(InternPool.Index.isize_type),
   2146         c_char_type = @intFromEnum(InternPool.Index.c_char_type),
   2147         c_short_type = @intFromEnum(InternPool.Index.c_short_type),
   2148         c_ushort_type = @intFromEnum(InternPool.Index.c_ushort_type),
   2149         c_int_type = @intFromEnum(InternPool.Index.c_int_type),
   2150         c_uint_type = @intFromEnum(InternPool.Index.c_uint_type),
   2151         c_long_type = @intFromEnum(InternPool.Index.c_long_type),
   2152         c_ulong_type = @intFromEnum(InternPool.Index.c_ulong_type),
   2153         c_longlong_type = @intFromEnum(InternPool.Index.c_longlong_type),
   2154         c_ulonglong_type = @intFromEnum(InternPool.Index.c_ulonglong_type),
   2155         c_longdouble_type = @intFromEnum(InternPool.Index.c_longdouble_type),
   2156         f16_type = @intFromEnum(InternPool.Index.f16_type),
   2157         f32_type = @intFromEnum(InternPool.Index.f32_type),
   2158         f64_type = @intFromEnum(InternPool.Index.f64_type),
   2159         f80_type = @intFromEnum(InternPool.Index.f80_type),
   2160         f128_type = @intFromEnum(InternPool.Index.f128_type),
   2161         anyopaque_type = @intFromEnum(InternPool.Index.anyopaque_type),
   2162         bool_type = @intFromEnum(InternPool.Index.bool_type),
   2163         void_type = @intFromEnum(InternPool.Index.void_type),
   2164         type_type = @intFromEnum(InternPool.Index.type_type),
   2165         anyerror_type = @intFromEnum(InternPool.Index.anyerror_type),
   2166         comptime_int_type = @intFromEnum(InternPool.Index.comptime_int_type),
   2167         comptime_float_type = @intFromEnum(InternPool.Index.comptime_float_type),
   2168         noreturn_type = @intFromEnum(InternPool.Index.noreturn_type),
   2169         anyframe_type = @intFromEnum(InternPool.Index.anyframe_type),
   2170         null_type = @intFromEnum(InternPool.Index.null_type),
   2171         undefined_type = @intFromEnum(InternPool.Index.undefined_type),
   2172         enum_literal_type = @intFromEnum(InternPool.Index.enum_literal_type),
   2173         atomic_order_type = @intFromEnum(InternPool.Index.atomic_order_type),
   2174         atomic_rmw_op_type = @intFromEnum(InternPool.Index.atomic_rmw_op_type),
   2175         calling_convention_type = @intFromEnum(InternPool.Index.calling_convention_type),
   2176         address_space_type = @intFromEnum(InternPool.Index.address_space_type),
   2177         float_mode_type = @intFromEnum(InternPool.Index.float_mode_type),
   2178         reduce_op_type = @intFromEnum(InternPool.Index.reduce_op_type),
   2179         call_modifier_type = @intFromEnum(InternPool.Index.call_modifier_type),
   2180         prefetch_options_type = @intFromEnum(InternPool.Index.prefetch_options_type),
   2181         export_options_type = @intFromEnum(InternPool.Index.export_options_type),
   2182         extern_options_type = @intFromEnum(InternPool.Index.extern_options_type),
   2183         type_info_type = @intFromEnum(InternPool.Index.type_info_type),
   2184         manyptr_u8_type = @intFromEnum(InternPool.Index.manyptr_u8_type),
   2185         manyptr_const_u8_type = @intFromEnum(InternPool.Index.manyptr_const_u8_type),
   2186         manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type),
   2187         single_const_pointer_to_comptime_int_type = @intFromEnum(InternPool.Index.single_const_pointer_to_comptime_int_type),
   2188         slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),
   2189         slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
   2190         optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
   2191         anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),
   2192         adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type),
   2193         generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
   2194         empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),
   2195         undef = @intFromEnum(InternPool.Index.undef),
   2196         zero = @intFromEnum(InternPool.Index.zero),
   2197         zero_usize = @intFromEnum(InternPool.Index.zero_usize),
   2198         zero_u8 = @intFromEnum(InternPool.Index.zero_u8),
   2199         one = @intFromEnum(InternPool.Index.one),
   2200         one_usize = @intFromEnum(InternPool.Index.one_usize),
   2201         one_u8 = @intFromEnum(InternPool.Index.one_u8),
   2202         four_u8 = @intFromEnum(InternPool.Index.four_u8),
   2203         negative_one = @intFromEnum(InternPool.Index.negative_one),
   2204         calling_convention_c = @intFromEnum(InternPool.Index.calling_convention_c),
   2205         calling_convention_inline = @intFromEnum(InternPool.Index.calling_convention_inline),
   2206         void_value = @intFromEnum(InternPool.Index.void_value),
   2207         unreachable_value = @intFromEnum(InternPool.Index.unreachable_value),
   2208         null_value = @intFromEnum(InternPool.Index.null_value),
   2209         bool_true = @intFromEnum(InternPool.Index.bool_true),
   2210         bool_false = @intFromEnum(InternPool.Index.bool_false),
   2211         empty_struct = @intFromEnum(InternPool.Index.empty_struct),
   2212         generic_poison = @intFromEnum(InternPool.Index.generic_poison),
   2213 
   2214         /// This tag is here to match Air and InternPool, however it is unused
   2215         /// for ZIR purposes.
   2216         var_args_param_type = @intFromEnum(InternPool.Index.var_args_param_type),
   2217         /// This Ref does not correspond to any ZIR instruction or constant
   2218         /// value and may instead be used as a sentinel to indicate null.
   2219         none = @intFromEnum(InternPool.Index.none),
   2220         _,
   2221 
   2222         pub fn toIndex(inst: Ref) ?Index {
   2223             assert(inst != .none);
   2224             const ref_int = @intFromEnum(inst);
   2225             if (ref_int >= @intFromEnum(Index.ref_start_index)) {
   2226                 return @enumFromInt(ref_int - @intFromEnum(Index.ref_start_index));
   2227             } else {
   2228                 return null;
   2229             }
   2230         }
   2231 
   2232         pub fn toIndexAllowNone(inst: Ref) ?Index {
   2233             if (inst == .none) return null;
   2234             return toIndex(inst);
   2235         }
   2236     };
   2237 
   2238     /// All instructions have an 8-byte payload, which is contained within
   2239     /// this union. `Tag` determines which union field is active, as well as
   2240     /// how to interpret the data within.
   2241     pub const Data = union {
   2242         /// Used for `Tag.extended`. The extended opcode determines the meaning
   2243         /// of the `small` and `operand` fields.
   2244         extended: Extended.InstData,
   2245         /// Used for unary operators, with an AST node source location.
   2246         un_node: struct {
   2247             /// Offset from Decl AST node index.
   2248             src_node: i32,
   2249             /// The meaning of this operand depends on the corresponding `Tag`.
   2250             operand: Ref,
   2251 
   2252             pub fn src(self: @This()) LazySrcLoc {
   2253                 return LazySrcLoc.nodeOffset(self.src_node);
   2254             }
   2255         },
   2256         /// Used for unary operators, with a token source location.
   2257         un_tok: struct {
   2258             /// Offset from Decl AST token index.
   2259             src_tok: Ast.TokenIndex,
   2260             /// The meaning of this operand depends on the corresponding `Tag`.
   2261             operand: Ref,
   2262 
   2263             pub fn src(self: @This()) LazySrcLoc {
   2264                 return .{ .token_offset = self.src_tok };
   2265             }
   2266         },
   2267         pl_node: struct {
   2268             /// Offset from Decl AST node index.
   2269             /// `Tag` determines which kind of AST node this points to.
   2270             src_node: i32,
   2271             /// index into extra.
   2272             /// `Tag` determines what lives there.
   2273             payload_index: u32,
   2274 
   2275             pub fn src(self: @This()) LazySrcLoc {
   2276                 return LazySrcLoc.nodeOffset(self.src_node);
   2277             }
   2278         },
   2279         pl_tok: struct {
   2280             /// Offset from Decl AST token index.
   2281             src_tok: Ast.TokenIndex,
   2282             /// index into extra.
   2283             /// `Tag` determines what lives there.
   2284             payload_index: u32,
   2285 
   2286             pub fn src(self: @This()) LazySrcLoc {
   2287                 return .{ .token_offset = self.src_tok };
   2288             }
   2289         },
   2290         bin: Bin,
   2291         /// For strings which may contain null bytes.
   2292         str: struct {
   2293             /// Offset into `string_bytes`.
   2294             start: NullTerminatedString,
   2295             /// Number of bytes in the string.
   2296             len: u32,
   2297 
   2298             pub fn get(self: @This(), code: Zir) []const u8 {
   2299                 return code.string_bytes[@intFromEnum(self.start)..][0..self.len];
   2300             }
   2301         },
   2302         str_tok: struct {
   2303             /// Offset into `string_bytes`. Null-terminated.
   2304             start: NullTerminatedString,
   2305             /// Offset from Decl AST token index.
   2306             src_tok: u32,
   2307 
   2308             pub fn get(self: @This(), code: Zir) [:0]const u8 {
   2309                 return code.nullTerminatedString(self.start);
   2310             }
   2311 
   2312             pub fn src(self: @This()) LazySrcLoc {
   2313                 return .{ .token_offset = self.src_tok };
   2314             }
   2315         },
   2316         /// Offset from Decl AST token index.
   2317         tok: Ast.TokenIndex,
   2318         /// Offset from Decl AST node index.
   2319         node: i32,
   2320         int: u64,
   2321         float: f64,
   2322         ptr_type: struct {
   2323             flags: packed struct {
   2324                 is_allowzero: bool,
   2325                 is_mutable: bool,
   2326                 is_volatile: bool,
   2327                 has_sentinel: bool,
   2328                 has_align: bool,
   2329                 has_addrspace: bool,
   2330                 has_bit_range: bool,
   2331                 _: u1 = undefined,
   2332             },
   2333             size: std.builtin.Type.Pointer.Size,
   2334             /// Index into extra. See `PtrType`.
   2335             payload_index: u32,
   2336         },
   2337         int_type: struct {
   2338             /// Offset from Decl AST node index.
   2339             /// `Tag` determines which kind of AST node this points to.
   2340             src_node: i32,
   2341             signedness: std.builtin.Signedness,
   2342             bit_count: u16,
   2343 
   2344             pub fn src(self: @This()) LazySrcLoc {
   2345                 return LazySrcLoc.nodeOffset(self.src_node);
   2346             }
   2347         },
   2348         bool_br: struct {
   2349             lhs: Ref,
   2350             /// Points to a `Block`.
   2351             payload_index: u32,
   2352         },
   2353         @"unreachable": struct {
   2354             /// Offset from Decl AST node index.
   2355             /// `Tag` determines which kind of AST node this points to.
   2356             src_node: i32,
   2357 
   2358             pub fn src(self: @This()) LazySrcLoc {
   2359                 return LazySrcLoc.nodeOffset(self.src_node);
   2360             }
   2361         },
   2362         @"break": struct {
   2363             operand: Ref,
   2364             payload_index: u32,
   2365         },
   2366         dbg_stmt: LineColumn,
   2367         /// Used for unary operators which reference an inst,
   2368         /// with an AST node source location.
   2369         inst_node: struct {
   2370             /// Offset from Decl AST node index.
   2371             src_node: i32,
   2372             /// The meaning of this operand depends on the corresponding `Tag`.
   2373             inst: Index,
   2374 
   2375             pub fn src(self: @This()) LazySrcLoc {
   2376                 return LazySrcLoc.nodeOffset(self.src_node);
   2377             }
   2378         },
   2379         str_op: struct {
   2380             /// Offset into `string_bytes`. Null-terminated.
   2381             str: NullTerminatedString,
   2382             operand: Ref,
   2383 
   2384             pub fn getStr(self: @This(), zir: Zir) [:0]const u8 {
   2385                 return zir.nullTerminatedString(self.str);
   2386             }
   2387         },
   2388         @"defer": struct {
   2389             index: u32,
   2390             len: u32,
   2391         },
   2392         defer_err_code: struct {
   2393             err_code: Ref,
   2394             payload_index: u32,
   2395         },
   2396         save_err_ret_index: struct {
   2397             operand: Ref, // If error type (or .none), save new trace index
   2398         },
   2399         restore_err_ret_index: struct {
   2400             block: Ref, // If restored, the index is from this block's entrypoint
   2401             operand: Ref, // If non-error (or .none), then restore the index
   2402         },
   2403         elem_val_imm: struct {
   2404             /// The indexable value being accessed.
   2405             operand: Ref,
   2406             /// The index being accessed.
   2407             idx: u32,
   2408         },
   2409 
   2410         // Make sure we don't accidentally add a field to make this union
   2411         // bigger than expected. Note that in Debug builds, Zig is allowed
   2412         // to insert a secret field for safety checks.
   2413         comptime {
   2414             if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) {
   2415                 assert(@sizeOf(Data) == 8);
   2416             }
   2417         }
   2418 
   2419         /// TODO this has to be kept in sync with `Data` which we want to be an untagged
   2420         /// union. There is some kind of language awkwardness here and it has to do with
   2421         /// deserializing an untagged union (in this case `Data`) from a file, and trying
   2422         /// to preserve the hidden safety field.
   2423         pub const FieldEnum = enum {
   2424             extended,
   2425             un_node,
   2426             un_tok,
   2427             pl_node,
   2428             pl_tok,
   2429             bin,
   2430             str,
   2431             str_tok,
   2432             tok,
   2433             node,
   2434             int,
   2435             float,
   2436             ptr_type,
   2437             int_type,
   2438             bool_br,
   2439             @"unreachable",
   2440             @"break",
   2441             dbg_stmt,
   2442             inst_node,
   2443             str_op,
   2444             @"defer",
   2445             defer_err_code,
   2446             save_err_ret_index,
   2447             restore_err_ret_index,
   2448             elem_val_imm,
   2449         };
   2450     };
   2451 
   2452     pub const Break = struct {
   2453         pub const no_src_node = std.math.maxInt(i32);
   2454 
   2455         operand_src_node: i32,
   2456         block_inst: Index,
   2457     };
   2458 
   2459     /// Trailing:
   2460     /// 0. Output for every outputs_len
   2461     /// 1. Input for every inputs_len
   2462     /// 2. clobber: NullTerminatedString // index into string_bytes (null terminated) for every clobbers_len.
   2463     pub const Asm = struct {
   2464         src_node: i32,
   2465         // null-terminated string index
   2466         asm_source: NullTerminatedString,
   2467         /// 1 bit for each outputs_len: whether it uses `-> T` or not.
   2468         ///   0b0 - operand is a pointer to where to store the output.
   2469         ///   0b1 - operand is a type; asm expression has the output as the result.
   2470         /// 0b0X is the first output, 0bX0 is the second, etc.
   2471         output_type_bits: u32,
   2472 
   2473         pub const Output = struct {
   2474             /// index into string_bytes (null terminated)
   2475             name: NullTerminatedString,
   2476             /// index into string_bytes (null terminated)
   2477             constraint: NullTerminatedString,
   2478             /// How to interpret this is determined by `output_type_bits`.
   2479             operand: Ref,
   2480         };
   2481 
   2482         pub const Input = struct {
   2483             /// index into string_bytes (null terminated)
   2484             name: NullTerminatedString,
   2485             /// index into string_bytes (null terminated)
   2486             constraint: NullTerminatedString,
   2487             operand: Ref,
   2488         };
   2489     };
   2490 
   2491     /// Trailing:
   2492     /// if (ret_body_len == 1) {
   2493     ///   0. return_type: Ref
   2494     /// }
   2495     /// if (ret_body_len > 1) {
   2496     ///   1. return_type: Index // for each ret_body_len
   2497     /// }
   2498     /// 2. body: Index // for each body_len
   2499     /// 3. src_locs: SrcLocs // if body_len != 0
   2500     pub const Func = struct {
   2501         /// If this is 0 it means a void return type.
   2502         /// If this is 1 it means return_type is a simple Ref
   2503         ret_body_len: u32,
   2504         /// Points to the block that contains the param instructions for this function.
   2505         /// If this is a `declaration`, it refers to the declaration's value body.
   2506         param_block: Index,
   2507         body_len: u32,
   2508 
   2509         pub const SrcLocs = struct {
   2510             /// Line index in the source file relative to the parent decl.
   2511             lbrace_line: u32,
   2512             /// Line index in the source file relative to the parent decl.
   2513             rbrace_line: u32,
   2514             /// lbrace_column is least significant bits u16
   2515             /// rbrace_column is most significant bits u16
   2516             columns: u32,
   2517         };
   2518     };
   2519 
   2520     /// Trailing:
   2521     /// 0. lib_name: NullTerminatedString, // null terminated string index, if has_lib_name is set
   2522     /// if (has_align_ref and !has_align_body) {
   2523     ///   1. align: Ref,
   2524     /// }
   2525     /// if (has_align_body) {
   2526     ///   2. align_body_len: u32
   2527     ///   3. align_body: u32 // for each align_body_len
   2528     /// }
   2529     /// if (has_addrspace_ref and !has_addrspace_body) {
   2530     ///   4. addrspace: Ref,
   2531     /// }
   2532     /// if (has_addrspace_body) {
   2533     ///   5. addrspace_body_len: u32
   2534     ///   6. addrspace_body: u32 // for each addrspace_body_len
   2535     /// }
   2536     /// if (has_section_ref and !has_section_body) {
   2537     ///   7. section: Ref,
   2538     /// }
   2539     /// if (has_section_body) {
   2540     ///   8. section_body_len: u32
   2541     ///   9. section_body: u32 // for each section_body_len
   2542     /// }
   2543     /// if (has_cc_ref and !has_cc_body) {
   2544     ///   10. cc: Ref,
   2545     /// }
   2546     /// if (has_cc_body) {
   2547     ///   11. cc_body_len: u32
   2548     ///   12. cc_body: u32 // for each cc_body_len
   2549     /// }
   2550     /// if (has_ret_ty_ref and !has_ret_ty_body) {
   2551     ///   13. ret_ty: Ref,
   2552     /// }
   2553     /// if (has_ret_ty_body) {
   2554     ///   14. ret_ty_body_len: u32
   2555     ///   15. ret_ty_body: u32 // for each ret_ty_body_len
   2556     /// }
   2557     /// 16. noalias_bits: u32 // if has_any_noalias
   2558     ///     - each bit starting with LSB corresponds to parameter indexes
   2559     /// 17. body: Index // for each body_len
   2560     /// 18. src_locs: Func.SrcLocs // if body_len != 0
   2561     pub const FuncFancy = struct {
   2562         /// Points to the block that contains the param instructions for this function.
   2563         /// If this is a `declaration`, it refers to the declaration's value body.
   2564         param_block: Index,
   2565         body_len: u32,
   2566         bits: Bits,
   2567 
   2568         /// If both has_cc_ref and has_cc_body are false, it means auto calling convention.
   2569         /// If both has_align_ref and has_align_body are false, it means default alignment.
   2570         /// If both has_ret_ty_ref and has_ret_ty_body are false, it means void return type.
   2571         /// If both has_section_ref and has_section_body are false, it means default section.
   2572         /// If both has_addrspace_ref and has_addrspace_body are false, it means default addrspace.
   2573         pub const Bits = packed struct {
   2574             is_var_args: bool,
   2575             is_inferred_error: bool,
   2576             is_test: bool,
   2577             is_extern: bool,
   2578             is_noinline: bool,
   2579             has_align_ref: bool,
   2580             has_align_body: bool,
   2581             has_addrspace_ref: bool,
   2582             has_addrspace_body: bool,
   2583             has_section_ref: bool,
   2584             has_section_body: bool,
   2585             has_cc_ref: bool,
   2586             has_cc_body: bool,
   2587             has_ret_ty_ref: bool,
   2588             has_ret_ty_body: bool,
   2589             has_lib_name: bool,
   2590             has_any_noalias: bool,
   2591             _: u15 = undefined,
   2592         };
   2593     };
   2594 
   2595     /// Trailing:
   2596     /// 0. lib_name: NullTerminatedString, // null terminated string index, if has_lib_name is set
   2597     /// 1. align: Ref, // if has_align is set
   2598     /// 2. init: Ref // if has_init is set
   2599     /// The source node is obtained from the containing `block_inline`.
   2600     pub const ExtendedVar = struct {
   2601         var_type: Ref,
   2602 
   2603         pub const Small = packed struct {
   2604             has_lib_name: bool,
   2605             has_align: bool,
   2606             has_init: bool,
   2607             is_extern: bool,
   2608             is_const: bool,
   2609             is_threadlocal: bool,
   2610             _: u10 = undefined,
   2611         };
   2612     };
   2613 
   2614     /// This data is stored inside extra, with trailing operands according to `operands_len`.
   2615     /// Each operand is a `Ref`.
   2616     pub const MultiOp = struct {
   2617         operands_len: u32,
   2618     };
   2619 
   2620     /// Trailing: operand: Ref, // for each `operands_len` (stored in `small`).
   2621     pub const NodeMultiOp = struct {
   2622         src_node: i32,
   2623     };
   2624 
   2625     /// This data is stored inside extra, with trailing operands according to `body_len`.
   2626     /// Each operand is an `Index`.
   2627     pub const Block = struct {
   2628         body_len: u32,
   2629     };
   2630 
   2631     /// Trailing:
   2632     /// 0. doc_comment: u32          // if `has_doc_comment`; null-terminated string index
   2633     /// 1. align_body_len: u32       // if `has_align_linksection_addrspace`; 0 means no `align`
   2634     /// 2. linksection_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `linksection`
   2635     /// 3. addrspace_body_len: u32   // if `has_align_linksection_addrspace`; 0 means no `addrspace`
   2636     /// 4. value_body_inst: Zir.Inst.Index
   2637     ///    - for each `value_body_len`
   2638     ///    - body to be exited via `break_inline` to this `declaration` instruction
   2639     /// 5. align_body_inst: Zir.Inst.Index
   2640     ///    - for each `align_body_len`
   2641     ///    - body to be exited via `break_inline` to this `declaration` instruction
   2642     /// 6. linksection_body_inst: Zir.Inst.Index
   2643     ///    - for each `linksection_body_len`
   2644     ///    - body to be exited via `break_inline` to this `declaration` instruction
   2645     /// 7. addrspace_body_inst: Zir.Inst.Index
   2646     ///    - for each `addrspace_body_len`
   2647     ///    - body to be exited via `break_inline` to this `declaration` instruction
   2648     pub const Declaration = struct {
   2649         // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`.
   2650         src_hash_0: u32,
   2651         src_hash_1: u32,
   2652         src_hash_2: u32,
   2653         src_hash_3: u32,
   2654         /// The name of this `Decl`. Also indicates whether it is a test, comptime block, etc.
   2655         name: Name,
   2656         /// This Decl's line number relative to that of its parent.
   2657         /// TODO: column must be encoded similarly to respect non-formatted code!
   2658         line_offset: u32,
   2659         flags: Flags,
   2660 
   2661         pub const Flags = packed struct(u32) {
   2662             value_body_len: u28,
   2663             is_pub: bool,
   2664             is_export: bool,
   2665             has_doc_comment: bool,
   2666             has_align_linksection_addrspace: bool,
   2667         };
   2668 
   2669         pub const Name = enum(u32) {
   2670             @"comptime" = std.math.maxInt(u32),
   2671             @"usingnamespace" = std.math.maxInt(u32) - 1,
   2672             unnamed_test = std.math.maxInt(u32) - 2,
   2673             /// In this case, `has_doc_comment` will be true, and the doc
   2674             /// comment body is the identifier name.
   2675             decltest = std.math.maxInt(u32) - 3,
   2676             /// Other values are `NullTerminatedString` values, i.e. index into
   2677             /// `string_bytes`. If the byte referenced is 0, the decl is a named
   2678             /// test, and the actual name begins at the following byte.
   2679             _,
   2680 
   2681             pub fn isNamedTest(name: Name, zir: Zir) bool {
   2682                 return switch (name) {
   2683                     .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => false,
   2684                     _ => zir.string_bytes[@intFromEnum(name)] == 0,
   2685                 };
   2686             }
   2687             pub fn toString(name: Name, zir: Zir) ?NullTerminatedString {
   2688                 switch (name) {
   2689                     .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => return null,
   2690                     _ => {},
   2691                 }
   2692                 const idx: u32 = @intFromEnum(name);
   2693                 if (zir.string_bytes[idx] == 0) {
   2694                     // Named test
   2695                     return @enumFromInt(idx + 1);
   2696                 }
   2697                 return @enumFromInt(idx);
   2698             }
   2699         };
   2700 
   2701         pub const Bodies = struct {
   2702             value_body: []const Index,
   2703             align_body: ?[]const Index,
   2704             linksection_body: ?[]const Index,
   2705             addrspace_body: ?[]const Index,
   2706         };
   2707 
   2708         pub fn getBodies(declaration: Declaration, extra_end: u32, zir: Zir) Bodies {
   2709             var extra_index: u32 = extra_end;
   2710             extra_index += @intFromBool(declaration.flags.has_doc_comment);
   2711             const value_body_len = declaration.flags.value_body_len;
   2712             const align_body_len, const linksection_body_len, const addrspace_body_len = lens: {
   2713                 if (!declaration.flags.has_align_linksection_addrspace) {
   2714                     break :lens .{ 0, 0, 0 };
   2715                 }
   2716                 const lens = zir.extra[extra_index..][0..3].*;
   2717                 extra_index += 3;
   2718                 break :lens lens;
   2719             };
   2720             return .{
   2721                 .value_body = b: {
   2722                     defer extra_index += value_body_len;
   2723                     break :b zir.bodySlice(extra_index, value_body_len);
   2724                 },
   2725                 .align_body = if (align_body_len == 0) null else b: {
   2726                     defer extra_index += align_body_len;
   2727                     break :b zir.bodySlice(extra_index, align_body_len);
   2728                 },
   2729                 .linksection_body = if (linksection_body_len == 0) null else b: {
   2730                     defer extra_index += linksection_body_len;
   2731                     break :b zir.bodySlice(extra_index, linksection_body_len);
   2732                 },
   2733                 .addrspace_body = if (addrspace_body_len == 0) null else b: {
   2734                     defer extra_index += addrspace_body_len;
   2735                     break :b zir.bodySlice(extra_index, addrspace_body_len);
   2736                 },
   2737             };
   2738         }
   2739     };
   2740 
   2741     /// Stored inside extra, with trailing arguments according to `args_len`.
   2742     /// Implicit 0. arg_0_start: u32, // always same as `args_len`
   2743     /// 1. arg_end: u32, // for each `args_len`
   2744     /// arg_N_start is the same as arg_N-1_end
   2745     pub const Call = struct {
   2746         // Note: Flags *must* come first so that unusedResultExpr
   2747         // can find it when it goes to modify them.
   2748         flags: Flags,
   2749         callee: Ref,
   2750 
   2751         pub const Flags = packed struct {
   2752             /// std.builtin.CallModifier in packed form
   2753             pub const PackedModifier = u3;
   2754             pub const PackedArgsLen = u27;
   2755 
   2756             packed_modifier: PackedModifier,
   2757             ensure_result_used: bool = false,
   2758             pop_error_return_trace: bool,
   2759             args_len: PackedArgsLen,
   2760 
   2761             comptime {
   2762                 if (@sizeOf(Flags) != 4 or @bitSizeOf(Flags) != 32)
   2763                     @compileError("Layout of Call.Flags needs to be updated!");
   2764                 if (@bitSizeOf(std.builtin.CallModifier) != @bitSizeOf(PackedModifier))
   2765                     @compileError("Call.Flags.PackedModifier needs to be updated!");
   2766             }
   2767         };
   2768     };
   2769 
   2770     /// Stored inside extra, with trailing arguments according to `args_len`.
   2771     /// Implicit 0. arg_0_start: u32, // always same as `args_len`
   2772     /// 1. arg_end: u32, // for each `args_len`
   2773     /// arg_N_start is the same as arg_N-1_end
   2774     pub const FieldCall = struct {
   2775         // Note: Flags *must* come first so that unusedResultExpr
   2776         // can find it when it goes to modify them.
   2777         flags: Call.Flags,
   2778         obj_ptr: Ref,
   2779         /// Offset into `string_bytes`.
   2780         field_name_start: NullTerminatedString,
   2781     };
   2782 
   2783     pub const TypeOfPeer = struct {
   2784         src_node: i32,
   2785         body_len: u32,
   2786         body_index: u32,
   2787     };
   2788 
   2789     pub const BuiltinCall = struct {
   2790         // Note: Flags *must* come first so that unusedResultExpr
   2791         // can find it when it goes to modify them.
   2792         flags: Flags,
   2793         modifier: Ref,
   2794         callee: Ref,
   2795         args: Ref,
   2796 
   2797         pub const Flags = packed struct {
   2798             is_nosuspend: bool,
   2799             ensure_result_used: bool,
   2800             _: u30 = undefined,
   2801 
   2802             comptime {
   2803                 if (@sizeOf(Flags) != 4 or @bitSizeOf(Flags) != 32)
   2804                     @compileError("Layout of BuiltinCall.Flags needs to be updated!");
   2805             }
   2806         };
   2807     };
   2808 
   2809     /// This data is stored inside extra, with two sets of trailing `Ref`:
   2810     /// * 0. the then body, according to `then_body_len`.
   2811     /// * 1. the else body, according to `else_body_len`.
   2812     pub const CondBr = struct {
   2813         condition: Ref,
   2814         then_body_len: u32,
   2815         else_body_len: u32,
   2816     };
   2817 
   2818     /// This data is stored inside extra, trailed by:
   2819     /// * 0. body: Index //  for each `body_len`.
   2820     pub const Try = struct {
   2821         /// The error union to unwrap.
   2822         operand: Ref,
   2823         body_len: u32,
   2824     };
   2825 
   2826     /// Stored in extra. Depending on the flags in Data, there will be up to 5
   2827     /// trailing Ref fields:
   2828     /// 0. sentinel: Ref // if `has_sentinel` flag is set
   2829     /// 1. align: Ref // if `has_align` flag is set
   2830     /// 2. address_space: Ref // if `has_addrspace` flag is set
   2831     /// 3. bit_start: Ref // if `has_bit_range` flag is set
   2832     /// 4. host_size: Ref // if `has_bit_range` flag is set
   2833     pub const PtrType = struct {
   2834         elem_type: Ref,
   2835         src_node: i32,
   2836     };
   2837 
   2838     pub const ArrayTypeSentinel = struct {
   2839         len: Ref,
   2840         sentinel: Ref,
   2841         elem_type: Ref,
   2842     };
   2843 
   2844     pub const SliceStart = struct {
   2845         lhs: Ref,
   2846         start: Ref,
   2847     };
   2848 
   2849     pub const SliceEnd = struct {
   2850         lhs: Ref,
   2851         start: Ref,
   2852         end: Ref,
   2853     };
   2854 
   2855     pub const SliceSentinel = struct {
   2856         lhs: Ref,
   2857         start: Ref,
   2858         end: Ref,
   2859         sentinel: Ref,
   2860     };
   2861 
   2862     pub const SliceLength = struct {
   2863         lhs: Ref,
   2864         start: Ref,
   2865         len: Ref,
   2866         sentinel: Ref,
   2867         start_src_node_offset: i32,
   2868     };
   2869 
   2870     /// The meaning of these operands depends on the corresponding `Tag`.
   2871     pub const Bin = struct {
   2872         lhs: Ref,
   2873         rhs: Ref,
   2874     };
   2875 
   2876     pub const BinNode = struct {
   2877         node: i32,
   2878         lhs: Ref,
   2879         rhs: Ref,
   2880     };
   2881 
   2882     pub const UnNode = struct {
   2883         node: i32,
   2884         operand: Ref,
   2885     };
   2886 
   2887     pub const ElemPtrImm = struct {
   2888         ptr: Ref,
   2889         index: u32,
   2890     };
   2891 
   2892     pub const SwitchBlockErrUnion = struct {
   2893         operand: Ref,
   2894         bits: Bits,
   2895         main_src_node_offset: i32,
   2896 
   2897         pub const Bits = packed struct(u32) {
   2898             /// If true, one or more prongs have multiple items.
   2899             has_multi_cases: bool,
   2900             /// If true, there is an else prong. This is mutually exclusive with `has_under`.
   2901             has_else: bool,
   2902             any_uses_err_capture: bool,
   2903             payload_is_ref: bool,
   2904             scalar_cases_len: ScalarCasesLen,
   2905 
   2906             pub const ScalarCasesLen = u28;
   2907         };
   2908 
   2909         pub const MultiProng = struct {
   2910             items: []const Ref,
   2911             body: []const Index,
   2912         };
   2913     };
   2914 
   2915     /// 0. multi_cases_len: u32 // If has_multi_cases is set.
   2916     /// 1. tag_capture_inst: u32 // If any_has_tag_capture is set. Index of instruction prongs use to refer to the inline tag capture.
   2917     /// 2. else_body { // If has_else or has_under is set.
   2918     ///        info: ProngInfo,
   2919     ///        body member Index for every info.body_len
   2920     ///     }
   2921     /// 3. scalar_cases: { // for every scalar_cases_len
   2922     ///        item: Ref,
   2923     ///        info: ProngInfo,
   2924     ///        body member Index for every info.body_len
   2925     ///     }
   2926     /// 4. multi_cases: { // for every multi_cases_len
   2927     ///        items_len: u32,
   2928     ///        ranges_len: u32,
   2929     ///        info: ProngInfo,
   2930     ///        item: Ref // for every items_len
   2931     ///        ranges: { // for every ranges_len
   2932     ///            item_first: Ref,
   2933     ///            item_last: Ref,
   2934     ///        }
   2935     ///        body member Index for every info.body_len
   2936     ///    }
   2937     ///
   2938     /// When analyzing a case body, the switch instruction itself refers to the
   2939     /// captured payload. Whether this is captured by reference or by value
   2940     /// depends on whether the `byref` bit is set for the corresponding body.
   2941     pub const SwitchBlock = struct {
   2942         /// The operand passed to the `switch` expression. If this is a
   2943         /// `switch_block`, this is the operand value; if `switch_block_ref` it
   2944         /// is a pointer to the operand. `switch_block_ref` is always used if
   2945         /// any prong has a byref capture.
   2946         operand: Ref,
   2947         bits: Bits,
   2948 
   2949         /// These are stored in trailing data in `extra` for each prong.
   2950         pub const ProngInfo = packed struct(u32) {
   2951             body_len: u28,
   2952             capture: Capture,
   2953             is_inline: bool,
   2954             has_tag_capture: bool,
   2955 
   2956             pub const Capture = enum(u2) {
   2957                 none,
   2958                 by_val,
   2959                 by_ref,
   2960             };
   2961         };
   2962 
   2963         pub const Bits = packed struct(u32) {
   2964             /// If true, one or more prongs have multiple items.
   2965             has_multi_cases: bool,
   2966             /// If true, there is an else prong. This is mutually exclusive with `has_under`.
   2967             has_else: bool,
   2968             /// If true, there is an underscore prong. This is mutually exclusive with `has_else`.
   2969             has_under: bool,
   2970             /// If true, at least one prong has an inline tag capture.
   2971             any_has_tag_capture: bool,
   2972             scalar_cases_len: ScalarCasesLen,
   2973 
   2974             pub const ScalarCasesLen = u28;
   2975 
   2976             pub fn specialProng(bits: Bits) SpecialProng {
   2977                 const has_else: u2 = @intFromBool(bits.has_else);
   2978                 const has_under: u2 = @intFromBool(bits.has_under);
   2979                 return switch ((has_else << 1) | has_under) {
   2980                     0b00 => .none,
   2981                     0b01 => .under,
   2982                     0b10 => .@"else",
   2983                     0b11 => unreachable,
   2984                 };
   2985             }
   2986         };
   2987 
   2988         pub const MultiProng = struct {
   2989             items: []const Ref,
   2990             body: []const Index,
   2991         };
   2992     };
   2993 
   2994     pub const ArrayInitRefTy = struct {
   2995         ptr_ty: Ref,
   2996         elem_count: u32,
   2997     };
   2998 
   2999     pub const Field = struct {
   3000         lhs: Ref,
   3001         /// Offset into `string_bytes`.
   3002         field_name_start: NullTerminatedString,
   3003     };
   3004 
   3005     pub const FieldNamed = struct {
   3006         lhs: Ref,
   3007         field_name: Ref,
   3008     };
   3009 
   3010     pub const As = struct {
   3011         dest_type: Ref,
   3012         operand: Ref,
   3013     };
   3014 
   3015     /// Trailing:
   3016     /// 0. src_node: i32, // if has_src_node
   3017     /// 1. fields_len: u32, // if has_fields_len
   3018     /// 2. decls_len: u32, // if has_decls_len
   3019     /// 3. backing_int_body_len: u32, // if has_backing_int
   3020     /// 4. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0
   3021     /// 5. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0
   3022     /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction
   3023     /// 7. flags: u32 // for every 8 fields
   3024     ///    - sets of 4 bits:
   3025     ///      0b000X: whether corresponding field has an align expression
   3026     ///      0b00X0: whether corresponding field has a default expression
   3027     ///      0b0X00: whether corresponding field is comptime
   3028     ///      0bX000: whether corresponding field has a type expression
   3029     /// 8. fields: { // for every fields_len
   3030     ///        field_name: u32, // if !is_tuple
   3031     ///        doc_comment: NullTerminatedString, // .empty if no doc comment
   3032     ///        field_type: Ref, // if corresponding bit is not set. none means anytype.
   3033     ///        field_type_body_len: u32, // if corresponding bit is set
   3034     ///        align_body_len: u32, // if corresponding bit is set
   3035     ///        init_body_len: u32, // if corresponding bit is set
   3036     ///    }
   3037     /// 10. bodies: { // for every fields_len
   3038     ///        field_type_body_inst: Inst, // for each field_type_body_len
   3039     ///        align_body_inst: Inst, // for each align_body_len
   3040     ///        init_body_inst: Inst, // for each init_body_len
   3041     ///    }
   3042     pub const StructDecl = struct {
   3043         pub const Small = packed struct {
   3044             has_src_node: bool,
   3045             has_fields_len: bool,
   3046             has_decls_len: bool,
   3047             has_backing_int: bool,
   3048             known_non_opv: bool,
   3049             known_comptime_only: bool,
   3050             is_tuple: bool,
   3051             name_strategy: NameStrategy,
   3052             layout: std.builtin.Type.ContainerLayout,
   3053             any_default_inits: bool,
   3054             any_comptime_fields: bool,
   3055             any_aligned_fields: bool,
   3056             _: u2 = undefined,
   3057         };
   3058     };
   3059 
   3060     pub const NameStrategy = enum(u2) {
   3061         /// Use the same name as the parent declaration name.
   3062         /// e.g. `const Foo = struct {...};`.
   3063         parent,
   3064         /// Use the name of the currently executing comptime function call,
   3065         /// with the current parameters. e.g. `ArrayList(i32)`.
   3066         func,
   3067         /// Create an anonymous name for this declaration.
   3068         /// Like this: "ParentDeclName_struct_69"
   3069         anon,
   3070         /// Use the name specified in the next `dbg_var_{val,ptr}` instruction.
   3071         dbg_var,
   3072     };
   3073 
   3074     pub const FullPtrCastFlags = packed struct(u5) {
   3075         ptr_cast: bool = false,
   3076         align_cast: bool = false,
   3077         addrspace_cast: bool = false,
   3078         const_cast: bool = false,
   3079         volatile_cast: bool = false,
   3080 
   3081         pub inline fn needResultTypeBuiltinName(flags: FullPtrCastFlags) []const u8 {
   3082             if (flags.ptr_cast) return "@ptrCast";
   3083             if (flags.align_cast) return "@alignCast";
   3084             if (flags.addrspace_cast) return "@addrSpaceCast";
   3085             unreachable;
   3086         }
   3087     };
   3088 
   3089     /// Trailing:
   3090     /// 0. src_node: i32, // if has_src_node
   3091     /// 1. tag_type: Ref, // if has_tag_type
   3092     /// 2. body_len: u32, // if has_body_len
   3093     /// 3. fields_len: u32, // if has_fields_len
   3094     /// 4. decls_len: u32, // if has_decls_len
   3095     /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction
   3096     /// 6. inst: Index // for every body_len
   3097     /// 7. has_bits: u32 // for every 32 fields
   3098     ///    - the bit is whether corresponding field has an value expression
   3099     /// 8. fields: { // for every fields_len
   3100     ///        field_name: u32,
   3101     ///        doc_comment: u32, // .empty if no doc_comment
   3102     ///        value: Ref, // if corresponding bit is set
   3103     ///    }
   3104     pub const EnumDecl = struct {
   3105         pub const Small = packed struct {
   3106             has_src_node: bool,
   3107             has_tag_type: bool,
   3108             has_body_len: bool,
   3109             has_fields_len: bool,
   3110             has_decls_len: bool,
   3111             name_strategy: NameStrategy,
   3112             nonexhaustive: bool,
   3113             _: u8 = undefined,
   3114         };
   3115     };
   3116 
   3117     /// Trailing:
   3118     /// 0. src_node: i32, // if has_src_node
   3119     /// 1. tag_type: Ref, // if has_tag_type
   3120     /// 2. body_len: u32, // if has_body_len
   3121     /// 3. fields_len: u32, // if has_fields_len
   3122     /// 4. decls_len: u32, // if has_decls_len
   3123     /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction
   3124     /// 6. inst: Index // for every body_len
   3125     /// 7. has_bits: u32 // for every 8 fields
   3126     ///    - sets of 4 bits:
   3127     ///      0b000X: whether corresponding field has a type expression
   3128     ///      0b00X0: whether corresponding field has a align expression
   3129     ///      0b0X00: whether corresponding field has a tag value expression
   3130     ///      0bX000: unused
   3131     /// 8. fields: { // for every fields_len
   3132     ///        field_name: NullTerminatedString, // null terminated string index
   3133     ///        doc_comment: NullTerminatedString, // .empty if no doc comment
   3134     ///        field_type: Ref, // if corresponding bit is set
   3135     ///        - if none, means `anytype`.
   3136     ///        align: Ref, // if corresponding bit is set
   3137     ///        tag_value: Ref, // if corresponding bit is set
   3138     ///    }
   3139     pub const UnionDecl = struct {
   3140         pub const Small = packed struct {
   3141             has_src_node: bool,
   3142             has_tag_type: bool,
   3143             has_body_len: bool,
   3144             has_fields_len: bool,
   3145             has_decls_len: bool,
   3146             name_strategy: NameStrategy,
   3147             layout: std.builtin.Type.ContainerLayout,
   3148             /// has_tag_type | auto_enum_tag | result
   3149             /// -------------------------------------
   3150             ///    false     | false         |  union { }
   3151             ///    false     | true          |  union(enum) { }
   3152             ///    true      | true          |  union(enum(T)) { }
   3153             ///    true      | false         |  union(T) { }
   3154             auto_enum_tag: bool,
   3155             any_aligned_fields: bool,
   3156             _: u5 = undefined,
   3157         };
   3158     };
   3159 
   3160     /// Trailing:
   3161     /// 0. src_node: i32, // if has_src_node
   3162     /// 1. decls_len: u32, // if has_decls_len
   3163     /// 2. decl: Index, // for every decls_len; points to a `declaration` instruction
   3164     pub const OpaqueDecl = struct {
   3165         pub const Small = packed struct {
   3166             has_src_node: bool,
   3167             has_decls_len: bool,
   3168             name_strategy: NameStrategy,
   3169             _: u12 = undefined,
   3170         };
   3171     };
   3172 
   3173     /// Trailing:
   3174     /// { // for every fields_len
   3175     ///      field_name: NullTerminatedString // null terminated string index
   3176     ///     doc_comment: NullTerminatedString // null terminated string index
   3177     /// }
   3178     pub const ErrorSetDecl = struct {
   3179         fields_len: u32,
   3180     };
   3181 
   3182     /// A f128 value, broken up into 4 u32 parts.
   3183     pub const Float128 = struct {
   3184         piece0: u32,
   3185         piece1: u32,
   3186         piece2: u32,
   3187         piece3: u32,
   3188 
   3189         pub fn get(self: Float128) f128 {
   3190             const int_bits = @as(u128, self.piece0) |
   3191                 (@as(u128, self.piece1) << 32) |
   3192                 (@as(u128, self.piece2) << 64) |
   3193                 (@as(u128, self.piece3) << 96);
   3194             return @as(f128, @bitCast(int_bits));
   3195         }
   3196     };
   3197 
   3198     /// Trailing is an item per field.
   3199     pub const StructInit = struct {
   3200         fields_len: u32,
   3201 
   3202         pub const Item = struct {
   3203             /// The `struct_init_field_type` ZIR instruction for this field init.
   3204             field_type: Index,
   3205             /// The field init expression to be used as the field value. This value will be coerced
   3206             /// to the field type if not already.
   3207             init: Ref,
   3208         };
   3209     };
   3210 
   3211     /// Trailing is an Item per field.
   3212     /// TODO make this instead array of inits followed by array of names because
   3213     /// it will be simpler Sema code and better for CPU cache.
   3214     pub const StructInitAnon = struct {
   3215         fields_len: u32,
   3216 
   3217         pub const Item = struct {
   3218             /// Null-terminated string table index.
   3219             field_name: NullTerminatedString,
   3220             /// The field init expression to be used as the field value.
   3221             init: Ref,
   3222         };
   3223     };
   3224 
   3225     pub const FieldType = struct {
   3226         container_type: Ref,
   3227         /// Offset into `string_bytes`, null terminated.
   3228         name_start: NullTerminatedString,
   3229     };
   3230 
   3231     pub const FieldTypeRef = struct {
   3232         container_type: Ref,
   3233         field_name: Ref,
   3234     };
   3235 
   3236     pub const Cmpxchg = struct {
   3237         node: i32,
   3238         ptr: Ref,
   3239         expected_value: Ref,
   3240         new_value: Ref,
   3241         success_order: Ref,
   3242         failure_order: Ref,
   3243     };
   3244 
   3245     pub const AtomicRmw = struct {
   3246         ptr: Ref,
   3247         operation: Ref,
   3248         operand: Ref,
   3249         ordering: Ref,
   3250     };
   3251 
   3252     pub const UnionInit = struct {
   3253         union_type: Ref,
   3254         field_name: Ref,
   3255         init: Ref,
   3256     };
   3257 
   3258     pub const AtomicStore = struct {
   3259         ptr: Ref,
   3260         operand: Ref,
   3261         ordering: Ref,
   3262     };
   3263 
   3264     pub const AtomicLoad = struct {
   3265         elem_type: Ref,
   3266         ptr: Ref,
   3267         ordering: Ref,
   3268     };
   3269 
   3270     pub const MulAdd = struct {
   3271         mulend1: Ref,
   3272         mulend2: Ref,
   3273         addend: Ref,
   3274     };
   3275 
   3276     pub const FieldParentPtr = struct {
   3277         parent_type: Ref,
   3278         field_name: Ref,
   3279         field_ptr: Ref,
   3280     };
   3281 
   3282     pub const Shuffle = struct {
   3283         elem_type: Ref,
   3284         a: Ref,
   3285         b: Ref,
   3286         mask: Ref,
   3287     };
   3288 
   3289     pub const Select = struct {
   3290         node: i32,
   3291         elem_type: Ref,
   3292         pred: Ref,
   3293         a: Ref,
   3294         b: Ref,
   3295     };
   3296 
   3297     pub const AsyncCall = struct {
   3298         node: i32,
   3299         frame_buffer: Ref,
   3300         result_ptr: Ref,
   3301         fn_ptr: Ref,
   3302         args: Ref,
   3303     };
   3304 
   3305     /// Trailing: inst: Index // for every body_len
   3306     pub const Param = struct {
   3307         /// Null-terminated string index.
   3308         name: NullTerminatedString,
   3309         /// Null-terminated string index.
   3310         doc_comment: NullTerminatedString,
   3311         /// The body contains the type of the parameter.
   3312         body_len: u32,
   3313     };
   3314 
   3315     /// Trailing:
   3316     /// 0. type_inst: Ref,  // if small 0b000X is set
   3317     /// 1. align_inst: Ref, // if small 0b00X0 is set
   3318     pub const AllocExtended = struct {
   3319         src_node: i32,
   3320 
   3321         pub const Small = packed struct {
   3322             has_type: bool,
   3323             has_align: bool,
   3324             is_const: bool,
   3325             is_comptime: bool,
   3326             _: u12 = undefined,
   3327         };
   3328     };
   3329 
   3330     pub const Export = struct {
   3331         /// If present, this is referring to a Decl via field access, e.g. `a.b`.
   3332         /// If omitted, this is referring to a Decl via identifier, e.g. `a`.
   3333         namespace: Ref,
   3334         /// Null-terminated string index.
   3335         decl_name: NullTerminatedString,
   3336         options: Ref,
   3337     };
   3338 
   3339     pub const ExportValue = struct {
   3340         /// The comptime value to export.
   3341         operand: Ref,
   3342         options: Ref,
   3343     };
   3344 
   3345     /// Trailing: `CompileErrors.Item` for each `items_len`.
   3346     pub const CompileErrors = struct {
   3347         items_len: u32,
   3348 
   3349         /// Trailing: `note_payload_index: u32` for each `notes_len`.
   3350         /// It's a payload index of another `Item`.
   3351         pub const Item = struct {
   3352             /// null terminated string index
   3353             msg: NullTerminatedString,
   3354             node: Ast.Node.Index,
   3355             /// If node is 0 then this will be populated.
   3356             token: Ast.TokenIndex,
   3357             /// Can be used in combination with `token`.
   3358             byte_offset: u32,
   3359             /// 0 or a payload index of a `Block`, each is a payload
   3360             /// index of another `Item`.
   3361             notes: u32,
   3362 
   3363             pub fn notesLen(item: Item, zir: Zir) u32 {
   3364                 if (item.notes == 0) return 0;
   3365                 const block = zir.extraData(Block, item.notes);
   3366                 return block.data.body_len;
   3367             }
   3368         };
   3369     };
   3370 
   3371     /// Trailing: for each `imports_len` there is an Item
   3372     pub const Imports = struct {
   3373         imports_len: u32,
   3374 
   3375         pub const Item = struct {
   3376             /// null terminated string index
   3377             name: NullTerminatedString,
   3378             /// points to the import name
   3379             token: Ast.TokenIndex,
   3380         };
   3381     };
   3382 
   3383     pub const LineColumn = struct {
   3384         line: u32,
   3385         column: u32,
   3386     };
   3387 
   3388     pub const ArrayInit = struct {
   3389         ty: Ref,
   3390         init_count: u32,
   3391     };
   3392 
   3393     pub const Src = struct {
   3394         node: i32,
   3395         line: u32,
   3396         column: u32,
   3397     };
   3398 
   3399     pub const DeferErrCode = struct {
   3400         remapped_err_code: Index,
   3401         index: u32,
   3402         len: u32,
   3403     };
   3404 
   3405     pub const ValidateDestructure = struct {
   3406         /// The value being destructured.
   3407         operand: Ref,
   3408         /// The `destructure_assign` node.
   3409         destructure_node: i32,
   3410         /// The expected field count.
   3411         expect_len: u32,
   3412     };
   3413 
   3414     pub const ArrayMul = struct {
   3415         /// The result type of the array multiplication operation, or `.none` if none was available.
   3416         res_ty: Ref,
   3417         /// The LHS of the array multiplication.
   3418         lhs: Ref,
   3419         /// The RHS of the array multiplication.
   3420         rhs: Ref,
   3421     };
   3422 };
   3423 
   3424 pub const SpecialProng = enum { none, @"else", under };
   3425 
   3426 pub const DeclIterator = struct {
   3427     extra_index: u32,
   3428     decls_remaining: u32,
   3429     zir: Zir,
   3430 
   3431     pub fn next(it: *DeclIterator) ?Inst.Index {
   3432         if (it.decls_remaining == 0) return null;
   3433         const decl_inst: Zir.Inst.Index = @enumFromInt(it.zir.extra[it.extra_index]);
   3434         it.extra_index += 1;
   3435         it.decls_remaining -= 1;
   3436         assert(it.zir.instructions.items(.tag)[@intFromEnum(decl_inst)] == .declaration);
   3437         return decl_inst;
   3438     }
   3439 };
   3440 
   3441 pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
   3442     const tags = zir.instructions.items(.tag);
   3443     const datas = zir.instructions.items(.data);
   3444     switch (tags[@intFromEnum(decl_inst)]) {
   3445         // Functions are allowed and yield no iterations.
   3446         // There is one case matching this in the extended instruction set below.
   3447         .func, .func_inferred, .func_fancy => return .{
   3448             .extra_index = undefined,
   3449             .decls_remaining = 0,
   3450             .zir = zir,
   3451         },
   3452 
   3453         .extended => {
   3454             const extended = datas[@intFromEnum(decl_inst)].extended;
   3455             switch (extended.opcode) {
   3456                 .struct_decl => {
   3457                     const small: Inst.StructDecl.Small = @bitCast(extended.small);
   3458                     var extra_index: u32 = extended.operand;
   3459                     extra_index += @intFromBool(small.has_src_node);
   3460                     extra_index += @intFromBool(small.has_fields_len);
   3461                     const decls_len = if (small.has_decls_len) decls_len: {
   3462                         const decls_len = zir.extra[extra_index];
   3463                         extra_index += 1;
   3464                         break :decls_len decls_len;
   3465                     } else 0;
   3466 
   3467                     if (small.has_backing_int) {
   3468                         const backing_int_body_len = zir.extra[extra_index];
   3469                         extra_index += 1; // backing_int_body_len
   3470                         if (backing_int_body_len == 0) {
   3471                             extra_index += 1; // backing_int_ref
   3472                         } else {
   3473                             extra_index += backing_int_body_len; // backing_int_body_inst
   3474                         }
   3475                     }
   3476 
   3477                     return .{
   3478                         .extra_index = extra_index,
   3479                         .decls_remaining = decls_len,
   3480                         .zir = zir,
   3481                     };
   3482                 },
   3483                 .enum_decl => {
   3484                     const small: Inst.EnumDecl.Small = @bitCast(extended.small);
   3485                     var extra_index: u32 = extended.operand;
   3486                     extra_index += @intFromBool(small.has_src_node);
   3487                     extra_index += @intFromBool(small.has_tag_type);
   3488                     extra_index += @intFromBool(small.has_body_len);
   3489                     extra_index += @intFromBool(small.has_fields_len);
   3490                     const decls_len = if (small.has_decls_len) decls_len: {
   3491                         const decls_len = zir.extra[extra_index];
   3492                         extra_index += 1;
   3493                         break :decls_len decls_len;
   3494                     } else 0;
   3495 
   3496                     return .{
   3497                         .extra_index = extra_index,
   3498                         .decls_remaining = decls_len,
   3499                         .zir = zir,
   3500                     };
   3501                 },
   3502                 .union_decl => {
   3503                     const small: Inst.UnionDecl.Small = @bitCast(extended.small);
   3504                     var extra_index: u32 = extended.operand;
   3505                     extra_index += @intFromBool(small.has_src_node);
   3506                     extra_index += @intFromBool(small.has_tag_type);
   3507                     extra_index += @intFromBool(small.has_body_len);
   3508                     extra_index += @intFromBool(small.has_fields_len);
   3509                     const decls_len = if (small.has_decls_len) decls_len: {
   3510                         const decls_len = zir.extra[extra_index];
   3511                         extra_index += 1;
   3512                         break :decls_len decls_len;
   3513                     } else 0;
   3514 
   3515                     return .{
   3516                         .extra_index = extra_index,
   3517                         .decls_remaining = decls_len,
   3518                         .zir = zir,
   3519                     };
   3520                 },
   3521                 .opaque_decl => {
   3522                     const small: Inst.OpaqueDecl.Small = @bitCast(extended.small);
   3523                     var extra_index: u32 = extended.operand;
   3524                     extra_index += @intFromBool(small.has_src_node);
   3525                     const decls_len = if (small.has_decls_len) decls_len: {
   3526                         const decls_len = zir.extra[extra_index];
   3527                         extra_index += 1;
   3528                         break :decls_len decls_len;
   3529                     } else 0;
   3530 
   3531                     return .{
   3532                         .extra_index = extra_index,
   3533                         .decls_remaining = decls_len,
   3534                         .zir = zir,
   3535                     };
   3536                 },
   3537                 else => unreachable,
   3538             }
   3539         },
   3540         else => unreachable,
   3541     }
   3542 }
   3543 
   3544 /// The iterator would have to allocate memory anyway to iterate. So here we populate
   3545 /// an ArrayList as the result.
   3546 pub fn findDecls(zir: Zir, list: *std.ArrayList(Inst.Index), decl_inst: Zir.Inst.Index) !void {
   3547     list.clearRetainingCapacity();
   3548     const declaration, const extra_end = zir.getDeclaration(decl_inst);
   3549     const bodies = declaration.getBodies(extra_end, zir);
   3550 
   3551     try zir.findDeclsBody(list, bodies.value_body);
   3552     if (bodies.align_body) |b| try zir.findDeclsBody(list, b);
   3553     if (bodies.linksection_body) |b| try zir.findDeclsBody(list, b);
   3554     if (bodies.addrspace_body) |b| try zir.findDeclsBody(list, b);
   3555 }
   3556 
   3557 fn findDeclsInner(
   3558     zir: Zir,
   3559     list: *std.ArrayList(Inst.Index),
   3560     inst: Inst.Index,
   3561 ) Allocator.Error!void {
   3562     const tags = zir.instructions.items(.tag);
   3563     const datas = zir.instructions.items(.data);
   3564 
   3565     switch (tags[@intFromEnum(inst)]) {
   3566         // Functions instructions are interesting and have a body.
   3567         .func,
   3568         .func_inferred,
   3569         => {
   3570             try list.append(inst);
   3571 
   3572             const inst_data = datas[@intFromEnum(inst)].pl_node;
   3573             const extra = zir.extraData(Inst.Func, inst_data.payload_index);
   3574             var extra_index: usize = extra.end;
   3575             switch (extra.data.ret_body_len) {
   3576                 0 => {},
   3577                 1 => extra_index += 1,
   3578                 else => {
   3579                     const body = zir.bodySlice(extra_index, extra.data.ret_body_len);
   3580                     extra_index += body.len;
   3581                     try zir.findDeclsBody(list, body);
   3582                 },
   3583             }
   3584             const body = zir.bodySlice(extra_index, extra.data.body_len);
   3585             return zir.findDeclsBody(list, body);
   3586         },
   3587         .func_fancy => {
   3588             try list.append(inst);
   3589 
   3590             const inst_data = datas[@intFromEnum(inst)].pl_node;
   3591             const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
   3592             var extra_index: usize = extra.end;
   3593             extra_index += @intFromBool(extra.data.bits.has_lib_name);
   3594 
   3595             if (extra.data.bits.has_align_body) {
   3596                 const body_len = zir.extra[extra_index];
   3597                 extra_index += 1;
   3598                 const body = zir.bodySlice(extra_index, body_len);
   3599                 try zir.findDeclsBody(list, body);
   3600                 extra_index += body.len;
   3601             } else if (extra.data.bits.has_align_ref) {
   3602                 extra_index += 1;
   3603             }
   3604 
   3605             if (extra.data.bits.has_addrspace_body) {
   3606                 const body_len = zir.extra[extra_index];
   3607                 extra_index += 1;
   3608                 const body = zir.bodySlice(extra_index, body_len);
   3609                 try zir.findDeclsBody(list, body);
   3610                 extra_index += body.len;
   3611             } else if (extra.data.bits.has_addrspace_ref) {
   3612                 extra_index += 1;
   3613             }
   3614 
   3615             if (extra.data.bits.has_section_body) {
   3616                 const body_len = zir.extra[extra_index];
   3617                 extra_index += 1;
   3618                 const body = zir.bodySlice(extra_index, body_len);
   3619                 try zir.findDeclsBody(list, body);
   3620                 extra_index += body.len;
   3621             } else if (extra.data.bits.has_section_ref) {
   3622                 extra_index += 1;
   3623             }
   3624 
   3625             if (extra.data.bits.has_cc_body) {
   3626                 const body_len = zir.extra[extra_index];
   3627                 extra_index += 1;
   3628                 const body = zir.bodySlice(extra_index, body_len);
   3629                 try zir.findDeclsBody(list, body);
   3630                 extra_index += body.len;
   3631             } else if (extra.data.bits.has_cc_ref) {
   3632                 extra_index += 1;
   3633             }
   3634 
   3635             if (extra.data.bits.has_ret_ty_body) {
   3636                 const body_len = zir.extra[extra_index];
   3637                 extra_index += 1;
   3638                 const body = zir.bodySlice(extra_index, body_len);
   3639                 try zir.findDeclsBody(list, body);
   3640                 extra_index += body.len;
   3641             } else if (extra.data.bits.has_ret_ty_ref) {
   3642                 extra_index += 1;
   3643             }
   3644 
   3645             extra_index += @intFromBool(extra.data.bits.has_any_noalias);
   3646 
   3647             const body = zir.bodySlice(extra_index, extra.data.body_len);
   3648             return zir.findDeclsBody(list, body);
   3649         },
   3650         .extended => {
   3651             const extended = datas[@intFromEnum(inst)].extended;
   3652             switch (extended.opcode) {
   3653 
   3654                 // Decl instructions are interesting but have no body.
   3655                 // TODO yes they do have a body actually. recurse over them just like block instructions.
   3656                 .struct_decl,
   3657                 .union_decl,
   3658                 .enum_decl,
   3659                 .opaque_decl,
   3660                 => return list.append(inst),
   3661 
   3662                 else => return,
   3663             }
   3664         },
   3665 
   3666         // Block instructions, recurse over the bodies.
   3667 
   3668         .block, .block_comptime, .block_inline => {
   3669             const inst_data = datas[@intFromEnum(inst)].pl_node;
   3670             const extra = zir.extraData(Inst.Block, inst_data.payload_index);
   3671             const body = zir.bodySlice(extra.end, extra.data.body_len);
   3672             return zir.findDeclsBody(list, body);
   3673         },
   3674         .condbr, .condbr_inline => {
   3675             const inst_data = datas[@intFromEnum(inst)].pl_node;
   3676             const extra = zir.extraData(Inst.CondBr, inst_data.payload_index);
   3677             const then_body = zir.bodySlice(extra.end, extra.data.then_body_len);
   3678             const else_body = zir.bodySlice(extra.end + then_body.len, extra.data.else_body_len);
   3679             try zir.findDeclsBody(list, then_body);
   3680             try zir.findDeclsBody(list, else_body);
   3681         },
   3682         .@"try", .try_ptr => {
   3683             const inst_data = datas[@intFromEnum(inst)].pl_node;
   3684             const extra = zir.extraData(Inst.Try, inst_data.payload_index);
   3685             const body = zir.bodySlice(extra.end, extra.data.body_len);
   3686             try zir.findDeclsBody(list, body);
   3687         },
   3688         .switch_block => return findDeclsSwitch(zir, list, inst),
   3689 
   3690         .suspend_block => @panic("TODO iterate suspend block"),
   3691 
   3692         else => return, // Regular instruction, not interesting.
   3693     }
   3694 }
   3695 
   3696 fn findDeclsSwitch(
   3697     zir: Zir,
   3698     list: *std.ArrayList(Inst.Index),
   3699     inst: Inst.Index,
   3700 ) Allocator.Error!void {
   3701     const inst_data = zir.instructions.items(.data)[@intFromEnum(inst)].pl_node;
   3702     const extra = zir.extraData(Inst.SwitchBlock, inst_data.payload_index);
   3703 
   3704     var extra_index: usize = extra.end;
   3705 
   3706     const multi_cases_len = if (extra.data.bits.has_multi_cases) blk: {
   3707         const multi_cases_len = zir.extra[extra_index];
   3708         extra_index += 1;
   3709         break :blk multi_cases_len;
   3710     } else 0;
   3711 
   3712     const special_prong = extra.data.bits.specialProng();
   3713     if (special_prong != .none) {
   3714         const body_len: u31 = @truncate(zir.extra[extra_index]);
   3715         extra_index += 1;
   3716         const body = zir.bodySlice(extra_index, body_len);
   3717         extra_index += body.len;
   3718 
   3719         try zir.findDeclsBody(list, body);
   3720     }
   3721 
   3722     {
   3723         const scalar_cases_len = extra.data.bits.scalar_cases_len;
   3724         for (0..scalar_cases_len) |_| {
   3725             extra_index += 1;
   3726             const body_len: u31 = @truncate(zir.extra[extra_index]);
   3727             extra_index += 1;
   3728             const body = zir.bodySlice(extra_index, body_len);
   3729             extra_index += body_len;
   3730 
   3731             try zir.findDeclsBody(list, body);
   3732         }
   3733     }
   3734     {
   3735         for (0..multi_cases_len) |_| {
   3736             const items_len = zir.extra[extra_index];
   3737             extra_index += 1;
   3738             const ranges_len = zir.extra[extra_index];
   3739             extra_index += 1;
   3740             const body_len: u31 = @truncate(zir.extra[extra_index]);
   3741             extra_index += 1;
   3742             const items = zir.refSlice(extra_index, items_len);
   3743             extra_index += items_len;
   3744             _ = items;
   3745 
   3746             var range_i: usize = 0;
   3747             while (range_i < ranges_len) : (range_i += 1) {
   3748                 extra_index += 1;
   3749                 extra_index += 1;
   3750             }
   3751 
   3752             const body = zir.bodySlice(extra_index, body_len);
   3753             extra_index += body_len;
   3754 
   3755             try zir.findDeclsBody(list, body);
   3756         }
   3757     }
   3758 }
   3759 
   3760 fn findDeclsBody(
   3761     zir: Zir,
   3762     list: *std.ArrayList(Inst.Index),
   3763     body: []const Inst.Index,
   3764 ) Allocator.Error!void {
   3765     for (body) |member| {
   3766         try zir.findDeclsInner(list, member);
   3767     }
   3768 }
   3769 
   3770 pub const FnInfo = struct {
   3771     param_body: []const Inst.Index,
   3772     param_body_inst: Inst.Index,
   3773     ret_ty_body: []const Inst.Index,
   3774     body: []const Inst.Index,
   3775     ret_ty_ref: Zir.Inst.Ref,
   3776     total_params_len: u32,
   3777 };
   3778 
   3779 pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index {
   3780     const tags = zir.instructions.items(.tag);
   3781     const datas = zir.instructions.items(.data);
   3782     const inst_data = datas[@intFromEnum(fn_inst)].pl_node;
   3783 
   3784     const param_block_index = switch (tags[@intFromEnum(fn_inst)]) {
   3785         .func, .func_inferred => blk: {
   3786             const extra = zir.extraData(Inst.Func, inst_data.payload_index);
   3787             break :blk extra.data.param_block;
   3788         },
   3789         .func_fancy => blk: {
   3790             const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
   3791             break :blk extra.data.param_block;
   3792         },
   3793         else => unreachable,
   3794     };
   3795 
   3796     switch (tags[@intFromEnum(param_block_index)]) {
   3797         .block, .block_comptime, .block_inline => {
   3798             const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(param_block_index)].pl_node.payload_index);
   3799             return zir.bodySlice(param_block.end, param_block.data.body_len);
   3800         },
   3801         .declaration => {
   3802             const decl, const extra_end = zir.getDeclaration(param_block_index);
   3803             return decl.getBodies(extra_end, zir).value_body;
   3804         },
   3805         else => unreachable,
   3806     }
   3807 }
   3808 
   3809 pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
   3810     const tags = zir.instructions.items(.tag);
   3811     const datas = zir.instructions.items(.data);
   3812     const info: struct {
   3813         param_block: Inst.Index,
   3814         body: []const Inst.Index,
   3815         ret_ty_ref: Inst.Ref,
   3816         ret_ty_body: []const Inst.Index,
   3817     } = switch (tags[@intFromEnum(fn_inst)]) {
   3818         .func, .func_inferred => blk: {
   3819             const inst_data = datas[@intFromEnum(fn_inst)].pl_node;
   3820             const extra = zir.extraData(Inst.Func, inst_data.payload_index);
   3821 
   3822             var extra_index: usize = extra.end;
   3823             var ret_ty_ref: Inst.Ref = .none;
   3824             var ret_ty_body: []const Inst.Index = &.{};
   3825 
   3826             switch (extra.data.ret_body_len) {
   3827                 0 => {
   3828                     ret_ty_ref = .void_type;
   3829                 },
   3830                 1 => {
   3831                     ret_ty_ref = @enumFromInt(zir.extra[extra_index]);
   3832                     extra_index += 1;
   3833                 },
   3834                 else => {
   3835                     ret_ty_body = zir.bodySlice(extra_index, extra.data.ret_body_len);
   3836                     extra_index += ret_ty_body.len;
   3837                 },
   3838             }
   3839 
   3840             const body = zir.bodySlice(extra_index, extra.data.body_len);
   3841             extra_index += body.len;
   3842 
   3843             break :blk .{
   3844                 .param_block = extra.data.param_block,
   3845                 .ret_ty_ref = ret_ty_ref,
   3846                 .ret_ty_body = ret_ty_body,
   3847                 .body = body,
   3848             };
   3849         },
   3850         .func_fancy => blk: {
   3851             const inst_data = datas[@intFromEnum(fn_inst)].pl_node;
   3852             const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
   3853 
   3854             var extra_index: usize = extra.end;
   3855             var ret_ty_ref: Inst.Ref = .void_type;
   3856             var ret_ty_body: []const Inst.Index = &.{};
   3857 
   3858             extra_index += @intFromBool(extra.data.bits.has_lib_name);
   3859             if (extra.data.bits.has_align_body) {
   3860                 extra_index += zir.extra[extra_index] + 1;
   3861             } else if (extra.data.bits.has_align_ref) {
   3862                 extra_index += 1;
   3863             }
   3864             if (extra.data.bits.has_addrspace_body) {
   3865                 extra_index += zir.extra[extra_index] + 1;
   3866             } else if (extra.data.bits.has_addrspace_ref) {
   3867                 extra_index += 1;
   3868             }
   3869             if (extra.data.bits.has_section_body) {
   3870                 extra_index += zir.extra[extra_index] + 1;
   3871             } else if (extra.data.bits.has_section_ref) {
   3872                 extra_index += 1;
   3873             }
   3874             if (extra.data.bits.has_cc_body) {
   3875                 extra_index += zir.extra[extra_index] + 1;
   3876             } else if (extra.data.bits.has_cc_ref) {
   3877                 extra_index += 1;
   3878             }
   3879             if (extra.data.bits.has_ret_ty_body) {
   3880                 const body_len = zir.extra[extra_index];
   3881                 extra_index += 1;
   3882                 ret_ty_body = zir.bodySlice(extra_index, body_len);
   3883                 extra_index += ret_ty_body.len;
   3884             } else if (extra.data.bits.has_ret_ty_ref) {
   3885                 ret_ty_ref = @enumFromInt(zir.extra[extra_index]);
   3886                 extra_index += 1;
   3887             }
   3888 
   3889             extra_index += @intFromBool(extra.data.bits.has_any_noalias);
   3890 
   3891             const body = zir.bodySlice(extra_index, extra.data.body_len);
   3892             extra_index += body.len;
   3893             break :blk .{
   3894                 .param_block = extra.data.param_block,
   3895                 .ret_ty_ref = ret_ty_ref,
   3896                 .ret_ty_body = ret_ty_body,
   3897                 .body = body,
   3898             };
   3899         },
   3900         else => unreachable,
   3901     };
   3902     const param_body = switch (tags[@intFromEnum(info.param_block)]) {
   3903         .block, .block_comptime, .block_inline => param_body: {
   3904             const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(info.param_block)].pl_node.payload_index);
   3905             break :param_body zir.bodySlice(param_block.end, param_block.data.body_len);
   3906         },
   3907         .declaration => param_body: {
   3908             const decl, const extra_end = zir.getDeclaration(info.param_block);
   3909             break :param_body decl.getBodies(extra_end, zir).value_body;
   3910         },
   3911         else => unreachable,
   3912     };
   3913     var total_params_len: u32 = 0;
   3914     for (param_body) |inst| {
   3915         switch (tags[@intFromEnum(inst)]) {
   3916             .param, .param_comptime, .param_anytype, .param_anytype_comptime => {
   3917                 total_params_len += 1;
   3918             },
   3919             else => continue,
   3920         }
   3921     }
   3922     return .{
   3923         .param_body = param_body,
   3924         .param_body_inst = info.param_block,
   3925         .ret_ty_body = info.ret_ty_body,
   3926         .ret_ty_ref = info.ret_ty_ref,
   3927         .body = info.body,
   3928         .total_params_len = total_params_len,
   3929     };
   3930 }
   3931 
   3932 pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) struct { Inst.Declaration, u32 } {
   3933     assert(zir.instructions.items(.tag)[@intFromEnum(inst)] == .declaration);
   3934     const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].pl_node;
   3935     const extra = zir.extraData(Inst.Declaration, pl_node.payload_index);
   3936     return .{
   3937         extra.data,
   3938         @intCast(extra.end),
   3939     };
   3940 }