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