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