authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-26 20:58:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-26 21:35:30-07:00
log7b37bc771b9a1ed38b06358269bf6a716a38de60
treeadbec372f70eac7fe1b4fa19f1be8a0d6224a29c
parent5f3b21a5b6895bd2bfc7144a038a4b7b60313736

move Zir to std.zig.Zir

Part of an effort to ship more of the compiler in source form.

16 files changed, 4105 insertions(+), 4105 deletions(-)

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