1const std = @import("std");
2const mem = std.mem;
3const Allocator = std.mem.Allocator;
4const assert = std.debug.assert;
5const Ast = std.zig.Ast;
6const InternPool = @import("InternPool.zig");
7
8const Zir = std.zig.Zir;
9const Zcu = @import("Zcu.zig");
10const LazySrcLoc = Zcu.LazySrcLoc;
11
12/// Write human-readable, debug formatted ZIR code.
13pub fn renderAsText(gpa: Allocator, tree: ?Ast, zir: Zir, bw: *std.Io.Writer) !void {
14 var arena = std.heap.ArenaAllocator.init(gpa);
15 defer arena.deinit();
16
17 var writer: Writer = .{
18 .gpa = gpa,
19 .arena = arena.allocator(),
20 .tree = tree,
21 .code = zir,
22 .indent = 0,
23 .parent_decl_node = .root,
24 .recurse_decls = true,
25 .recurse_blocks = true,
26 };
27
28 const main_struct_inst: Zir.Inst.Index = .main_struct_inst;
29 try bw.print("%{d} ", .{@backingInt(main_struct_inst)});
30 try writer.writeInstToStream(bw, main_struct_inst);
31 try bw.writeAll("\n");
32 const imports_index = zir.extra[@backingInt(Zir.ExtraIndex.imports)];
33 if (imports_index != 0) {
34 try bw.writeAll("Imports:\n");
35
36 const extra = zir.extraData(Zir.Inst.Imports, imports_index);
37 var extra_index = extra.end;
38
39 for (0..extra.data.imports_len) |_| {
40 const item = zir.extraData(Zir.Inst.Imports.Item, extra_index);
41 extra_index = item.end;
42
43 const import_path = zir.nullTerminatedString(item.data.name);
44 try bw.print(" @import(\"{f}\") ", .{
45 std.zig.fmtString(import_path),
46 });
47 try writer.writeSrcTokAbs(bw, item.data.token);
48 try bw.writeAll("\n");
49 }
50 }
51}
52
53pub fn renderInstructionContext(
54 gpa: Allocator,
55 block: []const Zir.Inst.Index,
56 block_index: usize,
57 scope_file: *Zcu.File,
58 parent_decl_node: Ast.Node.Index,
59 indent: u32,
60 bw: *std.Io.Writer,
61) !void {
62 var arena = std.heap.ArenaAllocator.init(gpa);
63 defer arena.deinit();
64
65 var writer: Writer = .{
66 .gpa = gpa,
67 .arena = arena.allocator(),
68 .tree = scope_file.tree,
69 .code = scope_file.zir.?,
70 .indent = if (indent < 2) 2 else indent,
71 .parent_decl_node = parent_decl_node,
72 .recurse_decls = false,
73 .recurse_blocks = true,
74 };
75
76 try writer.writeBody(bw, block[0..block_index]);
77 try bw.splatByteAll(' ', writer.indent - 2);
78 try bw.print("> %{d} ", .{@backingInt(block[block_index])});
79 try writer.writeInstToStream(bw, block[block_index]);
80 try bw.writeByte('\n');
81 if (block_index + 1 < block.len) {
82 try writer.writeBody(bw, block[block_index + 1 ..]);
83 }
84}
85
86pub fn renderSingleInstruction(
87 gpa: Allocator,
88 inst: Zir.Inst.Index,
89 scope_file: *Zcu.File,
90 parent_decl_node: Ast.Node.Index,
91 indent: u32,
92 bw: *std.Io.Writer,
93) !void {
94 var arena = std.heap.ArenaAllocator.init(gpa);
95 defer arena.deinit();
96
97 var writer: Writer = .{
98 .gpa = gpa,
99 .arena = arena.allocator(),
100 .tree = scope_file.tree,
101 .code = scope_file.zir.?,
102 .indent = indent,
103 .parent_decl_node = parent_decl_node,
104 .recurse_decls = false,
105 .recurse_blocks = false,
106 };
107
108 try bw.print("%{d} ", .{@backingInt(inst)});
109 try writer.writeInstToStream(bw, inst);
110}
111
112const Writer = struct {
113 gpa: Allocator,
114 arena: Allocator,
115 tree: ?Ast,
116 code: Zir,
117 indent: u32,
118 parent_decl_node: Ast.Node.Index,
119 recurse_decls: bool,
120 recurse_blocks: bool,
121
122 /// Using `std.zig.findLineColumn` whenever we need to resolve a source location makes ZIR
123 /// printing O(N^2), which can have drastic effects - taking a ZIR dump from a few seconds to
124 /// many minutes. Since we're usually resolving source locations close to one another,
125 /// preserving state across source location resolutions speeds things up a lot.
126 line_col_cursor: struct {
127 line: usize = 0,
128 column: usize = 0,
129 line_start: usize = 0,
130 off: usize = 0,
131
132 fn find(cur: *@This(), source: []const u8, want_offset: usize) std.zig.Loc {
133 if (want_offset < cur.off) {
134 // Go back to the start of this line
135 cur.off = cur.line_start;
136 cur.column = 0;
137
138 while (want_offset < cur.off) {
139 // Go back to the newline
140 cur.off -= 1;
141
142 // Seek to the start of the previous line
143 while (cur.off > 0 and source[cur.off - 1] != '\n') {
144 cur.off -= 1;
145 }
146 cur.line_start = cur.off;
147 cur.line -= 1;
148 }
149 }
150
151 // The cursor is now positioned before `want_offset`.
152 // Seek forward as in `std.zig.findLineColumn`.
153
154 while (cur.off < want_offset) : (cur.off += 1) {
155 switch (source[cur.off]) {
156 '\n' => {
157 cur.line += 1;
158 cur.column = 0;
159 cur.line_start = cur.off + 1;
160 },
161 else => {
162 cur.column += 1;
163 },
164 }
165 }
166
167 while (cur.off < source.len and source[cur.off] != '\n') {
168 cur.off += 1;
169 }
170
171 return .{
172 .line = cur.line,
173 .column = cur.column,
174 .source_line = source[cur.line_start..cur.off],
175 };
176 }
177 } = .{},
178
179 const Error = std.Io.Writer.Error || Allocator.Error;
180
181 fn writeInstToStream(
182 self: *Writer,
183 stream: *std.Io.Writer,
184 inst: Zir.Inst.Index,
185 ) Error!void {
186 const tags = self.code.instructions.items(.tag);
187 const tag = tags[@backingInt(inst)];
188 try stream.print("= {s}(", .{@tagName(tags[@backingInt(inst)])});
189 switch (tag) {
190 .alloc,
191 .alloc_mut,
192 .alloc_comptime_mut,
193 .elem_type,
194 .indexable_ptr_elem_type,
195 .splat_op_result_ty,
196 .from_backing_int_arg_ty,
197 .indexable_ptr_len,
198 .anyframe_type,
199 .bit_not,
200 .bool_not,
201 .slice_sentinel_ty,
202 .negate,
203 .negate_wrap,
204 .load,
205 .ensure_result_used,
206 .ensure_result_non_error,
207 .ensure_err_union_payload_void,
208 .deref,
209 .ref_deref,
210 .ret_node,
211 .ret_load,
212 .resolve_inferred_alloc,
213 .optional_type,
214 .optional_payload_safe,
215 .optional_payload_unsafe,
216 .optional_payload_safe_ptr,
217 .optional_payload_unsafe_ptr,
218 .err_union_payload_unsafe,
219 .err_union_payload_unsafe_ptr,
220 .err_union_code,
221 .err_union_code_ptr,
222 .is_non_null,
223 .is_non_null_ptr,
224 .is_non_err,
225 .is_non_err_ptr,
226 .ret_is_non_err,
227 .typeof,
228 .type_info,
229 .size_of,
230 .bit_size_of,
231 .typeof_log2_int_type,
232 .int_from_ptr,
233 .compile_error,
234 .set_eval_branch_quota,
235 .int_from_enum,
236 .backing_int,
237 .align_of,
238 .int_from_bool,
239 .embed_file,
240 .error_name,
241 .panic,
242 .set_runtime_safety,
243 .sqrt,
244 .sin,
245 .cos,
246 .tan,
247 .exp,
248 .exp2,
249 .log,
250 .log2,
251 .log10,
252 .abs,
253 .floor,
254 .ceil,
255 .trunc,
256 .round,
257 .tag_name,
258 .type_name,
259 .frame_type,
260 .clz,
261 .ctz,
262 .pop_count,
263 .byte_swap,
264 .bit_reverse,
265 .@"resume",
266 .make_ptr_const,
267 .validate_const,
268 .check_comptime_control_flow,
269 .opt_eu_base_ptr_init,
270 .restore_err_ret_index_unconditional,
271 .restore_err_ret_index_fn_entry,
272 => try self.writeUnNode(stream, inst),
273
274 .ref,
275 .ret_implicit,
276 .validate_ref_ty,
277 => try self.writeUnTok(stream, inst),
278
279 .bool_br_and,
280 .bool_br_or,
281 => try self.writeBoolBr(stream, inst),
282
283 .validate_destructure => try self.writeValidateDestructure(stream, inst),
284 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
285 .ptr_type => try self.writePtrType(stream, inst),
286 .int => try self.writeInt(stream, inst),
287 .int_big => try self.writeIntBig(stream, inst),
288 .float => try self.writeFloat(stream, inst),
289 .float128 => try self.writeFloat128(stream, inst),
290 .str => try self.writeStr(stream, inst),
291 .int_type => try self.writeIntType(stream, inst),
292
293 .save_err_ret_index => try self.writeSaveErrRetIndex(stream, inst),
294
295 .@"break",
296 .break_inline,
297 .switch_continue,
298 => try self.writeBreak(stream, inst),
299
300 .slice_start => try self.writeSliceStart(stream, inst),
301 .slice_end => try self.writeSliceEnd(stream, inst),
302 .slice_sentinel => try self.writeSliceSentinel(stream, inst),
303 .slice_length => try self.writeSliceLength(stream, inst),
304
305 .union_init => try self.writeUnionInit(stream, inst),
306
307 // Struct inits
308
309 .struct_init_empty,
310 .struct_init_empty_result,
311 .struct_init_empty_ref_result,
312 => try self.writeUnNode(stream, inst),
313
314 .struct_init_anon => try self.writeStructInitAnon(stream, inst),
315
316 .struct_init,
317 .struct_init_ref,
318 => try self.writeStructInit(stream, inst),
319
320 .validate_struct_init_ty,
321 .validate_struct_init_result_ty,
322 => try self.writeUnNode(stream, inst),
323
324 .validate_ptr_struct_init => try self.writeBlock(stream, inst),
325 .struct_init_field_type => try self.writeStructInitFieldType(stream, inst),
326 .struct_init_field_ptr => try self.writePlNodeField(stream, inst),
327
328 // Array inits
329
330 .array_init_anon => try self.writeArrayInitAnon(stream, inst),
331
332 .array_init,
333 .array_init_ref,
334 => try self.writeArrayInit(stream, inst),
335
336 .validate_array_init_ty,
337 .validate_array_init_result_ty,
338 => try self.writeValidateArrayInitTy(stream, inst),
339
340 .validate_array_init_ref_ty => try self.writeValidateArrayInitRefTy(stream, inst),
341 .validate_ptr_array_init => try self.writeBlock(stream, inst),
342 .array_init_elem_type => try self.writeArrayInitElemType(stream, inst),
343 .array_init_elem_ptr => try self.writeArrayInitElemPtr(stream, inst),
344
345 .atomic_load => try self.writeAtomicLoad(stream, inst),
346 .atomic_store => try self.writeAtomicStore(stream, inst),
347 .atomic_rmw => try self.writeAtomicRmw(stream, inst),
348 .shuffle => try self.writeShuffle(stream, inst),
349 .mul_add => try self.writeMulAdd(stream, inst),
350 .builtin_call => try self.writeBuiltinCall(stream, inst),
351
352 .field_type_ref => try self.writeFieldTypeRef(stream, inst),
353
354 .add,
355 .addwrap,
356 .add_sat,
357 .add_unsafe,
358 .array_cat,
359 .mul,
360 .mulwrap,
361 .mul_sat,
362 .sub,
363 .subwrap,
364 .sub_sat,
365 .cmp_lt,
366 .cmp_lte,
367 .cmp_eq,
368 .cmp_gte,
369 .cmp_gt,
370 .cmp_neq,
371 .div,
372 .has_decl,
373 .has_field,
374 .mod_rem,
375 .shl,
376 .shl_exact,
377 .shl_sat,
378 .shr,
379 .shr_exact,
380 .xor,
381 .store_node,
382 .store_to_inferred_ptr,
383 .error_union_type,
384 .merge_error_sets,
385 .bit_and,
386 .bit_or,
387 .int_from_float,
388 .float_from_int,
389 .ptr_from_int,
390 .enum_from_int,
391 .float_cast,
392 .int_cast,
393 .ptr_cast,
394 .truncate,
395 .div_exact,
396 .div_floor,
397 .div_ceil,
398 .div_trunc,
399 .mod,
400 .rem,
401 .bit_offset_of,
402 .offset_of,
403 .splat,
404 .reduce,
405 .bitcast,
406 .reify_int,
407 .vector_type,
408 .max,
409 .min,
410 .memcpy,
411 .memset,
412 .memmove,
413 .elem_ptr_node,
414 .elem_ptr_load,
415 .elem_ptr,
416 .elem_val,
417 .array_type,
418 .coerce_ptr_elem_ty,
419 => try self.writePlNodeBin(stream, inst),
420
421 .for_len => try self.writePlNodeMultiOp(stream, inst),
422
423 .from_backing_int => try self.writePlNodeBin(stream, inst),
424
425 .elem_val_imm => try self.writeElemValImm(stream, inst),
426
427 .@"export" => try self.writePlNodeExport(stream, inst),
428
429 .call => try self.writeCall(stream, inst, .direct),
430 .field_call => try self.writeCall(stream, inst, .field),
431
432 .block,
433 .block_inline,
434 .suspend_block,
435 .loop,
436 .typeof_builtin,
437 => try self.writeBlock(stream, inst),
438
439 .block_comptime => try self.writeBlockComptime(stream, inst),
440
441 .condbr,
442 .condbr_inline,
443 => try self.writeCondBr(stream, inst),
444
445 .@"try",
446 .try_ptr,
447 => try self.writeTry(stream, inst),
448
449 .error_set_decl => try self.writeErrorSetDecl(stream, inst),
450
451 .switch_block,
452 .switch_block_ref,
453 .switch_block_err_union,
454 => try self.writeSwitchBlock(stream, inst),
455
456 .field_ptr_load,
457 .field_ptr,
458 .decl_literal,
459 .decl_literal_no_coerce,
460 => try self.writePlNodeField(stream, inst),
461
462 .field_ptr_named,
463 .field_ptr_named_load,
464 => try self.writePlNodeFieldNamed(stream, inst),
465
466 .as_node, .as_shift_operand => try self.writeAs(stream, inst),
467
468 .repeat,
469 .repeat_inline,
470 .alloc_inferred,
471 .alloc_inferred_mut,
472 .alloc_inferred_comptime,
473 .alloc_inferred_comptime_mut,
474 .ret_ptr,
475 .ret_type,
476 .trap,
477 => try self.writeNode(stream, inst),
478
479 .error_value,
480 .enum_literal,
481 .decl_ref,
482 .decl_val,
483 .ret_err_value,
484 .param_anytype,
485 .param_anytype_comptime,
486 => try self.writeStrTok(stream, inst),
487
488 .dbg_var_ptr,
489 .dbg_var_val,
490 => try self.writeStrOp(stream, inst),
491
492 .param, .param_comptime => try self.writeParam(stream, inst),
493
494 .func => try self.writeFunc(stream, inst, false),
495 .func_inferred => try self.writeFunc(stream, inst, true),
496 .func_fancy => try self.writeFuncFancy(stream, inst),
497
498 .@"unreachable" => try self.writeUnreachable(stream, inst),
499
500 .dbg_stmt => try self.writeDbgStmt(stream, inst),
501
502 .@"defer" => try self.writeDefer(stream, inst),
503
504 .declaration => try self.writeDeclaration(stream, inst),
505
506 .extended => try self.writeExtended(stream, inst),
507
508 .import => try self.writeImport(stream, inst),
509 }
510 }
511
512 fn writeExtended(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
513 const extended = self.code.instructions.items(.data)[@backingInt(inst)].extended;
514 try stream.print("{s}(", .{@tagName(extended.opcode)});
515 switch (extended.opcode) {
516 .this,
517 .ret_addr,
518 .error_return_trace,
519 .frame,
520 .frame_address,
521 .breakpoint,
522 .disable_instrumentation,
523 .disable_intrinsics,
524 .c_va_start,
525 .in_comptime,
526 .value_placeholder,
527 => try self.writeExtNode(stream, extended),
528
529 .builtin_src => {
530 try stream.writeAll("))");
531 const inst_data = self.code.extraData(Zir.Inst.LineColumn, extended.operand).data;
532 try stream.print(":{d}:{d}", .{ inst_data.line + 1, inst_data.column + 1 });
533 },
534
535 .@"asm" => try self.writeAsm(stream, extended, false),
536 .asm_expr => try self.writeAsm(stream, extended, true),
537 .alloc => try self.writeAllocExtended(stream, extended),
538
539 .compile_log => try self.writeNodeMultiOp(stream, extended),
540 .typeof_peer => try self.writeTypeofPeer(stream, extended),
541 .min_multi => try self.writeNodeMultiOp(stream, extended),
542 .max_multi => try self.writeNodeMultiOp(stream, extended),
543
544 .select => try self.writeSelect(stream, extended),
545
546 .add_with_overflow,
547 .sub_with_overflow,
548 .mul_with_overflow,
549 .shl_with_overflow,
550 => try self.writeOverflowArithmetic(stream, extended),
551
552 .struct_decl => try self.writeStructDecl(stream, inst),
553 .union_decl => try self.writeUnionDecl(stream, inst),
554 .enum_decl => try self.writeEnumDecl(stream, inst),
555 .opaque_decl => try self.writeOpaqueDecl(stream, inst),
556
557 .tuple_decl => try self.writeTupleDecl(stream, extended),
558
559 .set_float_mode,
560 .wasm_memory_size,
561 .int_from_error,
562 .error_from_int,
563 .c_va_copy,
564 .c_va_end,
565 .work_item_id,
566 .work_group_size,
567 .work_group_id,
568 .branch_hint,
569 .float_op_result_ty,
570 .reify_tuple,
571 .reify_pointer_sentinel_ty,
572 .round_op_ty,
573 => {
574 const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
575 try self.writeInstRef(stream, inst_data.operand);
576 try stream.writeAll(")) ");
577 try self.writeSrcNode(stream, inst_data.node);
578 },
579
580 .builtin_extern,
581 .error_cast,
582 .wasm_memory_grow,
583 .prefetch,
584 .c_va_arg,
585 .reify_enum_value_slice_ty,
586 => {
587 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
588 try self.writeInstRef(stream, inst_data.lhs);
589 try stream.writeAll(", ");
590 try self.writeInstRef(stream, inst_data.rhs);
591 try stream.writeAll(")) ");
592 try self.writeSrcNode(stream, inst_data.node);
593 },
594
595 .round_op => {
596 const round_op: Zir.Inst.RoundOp = @fromBackingInt(@intCast(extended.small));
597 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
598 try stream.print("{s}, ", .{@tagName(round_op)});
599 try self.writeInstRef(stream, inst_data.lhs);
600 try stream.writeAll(", ");
601 try self.writeInstRef(stream, inst_data.rhs);
602 try stream.writeAll(")) ");
603 try self.writeSrcNode(stream, inst_data.node);
604 },
605
606 .reify_slice_arg_ty => {
607 const reify_slice_arg_info: Zir.Inst.ReifySliceArgInfo = @fromBackingInt(@intCast(extended.small));
608 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
609 try stream.print("{t}, ", .{reify_slice_arg_info});
610 try self.writeInstRef(stream, extra.operand);
611 try stream.writeAll(")) ");
612 try self.writeSrcNode(stream, extra.node);
613 },
614
615 .reify_pointer => {
616 const extra = self.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;
617 try self.writeInstRef(stream, extra.size);
618 try stream.writeAll(", ");
619 try self.writeInstRef(stream, extra.attrs);
620 try stream.writeAll(", ");
621 try self.writeInstRef(stream, extra.elem_ty);
622 try stream.writeAll(", ");
623 try self.writeInstRef(stream, extra.sentinel);
624 try stream.writeAll(")) ");
625 try self.writeSrcNode(stream, extra.node);
626 },
627 .reify_fn => {
628 const extra = self.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;
629 try self.writeInstRef(stream, extra.param_types);
630 try stream.writeAll(", ");
631 try self.writeInstRef(stream, extra.param_attrs);
632 try stream.writeAll(", ");
633 try self.writeInstRef(stream, extra.ret_ty);
634 try stream.writeAll(", ");
635 try self.writeInstRef(stream, extra.fn_attrs);
636 try stream.writeAll(")) ");
637 try self.writeSrcNode(stream, extra.node);
638 },
639 .reify_struct => {
640 const extra = self.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data;
641 const name_strat: Zir.Inst.NameStrategy = @fromBackingInt(@intCast(extended.small));
642 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
643 try self.writeInstRef(stream, extra.layout);
644 try stream.writeAll(", ");
645 try self.writeInstRef(stream, extra.backing_ty);
646 try stream.writeAll(", ");
647 try self.writeInstRef(stream, extra.field_names);
648 try stream.writeAll(", ");
649 try self.writeInstRef(stream, extra.field_types);
650 try stream.writeAll(", ");
651 try self.writeInstRef(stream, extra.field_attrs);
652 try stream.writeAll(")) ");
653 const prev_parent_decl_node = self.parent_decl_node;
654 self.parent_decl_node = extra.node;
655 defer self.parent_decl_node = prev_parent_decl_node;
656 try self.writeSrcNode(stream, .zero);
657 },
658 .reify_union => {
659 const extra = self.code.extraData(Zir.Inst.ReifyUnion, extended.operand).data;
660 const name_strat: Zir.Inst.NameStrategy = @fromBackingInt(@intCast(extended.small));
661 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
662 try self.writeInstRef(stream, extra.layout);
663 try stream.writeAll(", ");
664 try self.writeInstRef(stream, extra.arg_ty);
665 try stream.writeAll(", ");
666 try self.writeInstRef(stream, extra.field_names);
667 try stream.writeAll(", ");
668 try self.writeInstRef(stream, extra.field_types);
669 try stream.writeAll(", ");
670 try self.writeInstRef(stream, extra.field_attrs);
671 try stream.writeAll(")) ");
672 const prev_parent_decl_node = self.parent_decl_node;
673 self.parent_decl_node = extra.node;
674 defer self.parent_decl_node = prev_parent_decl_node;
675 try self.writeSrcNode(stream, .zero);
676 },
677 .reify_enum => {
678 const extra = self.code.extraData(Zir.Inst.ReifyEnum, extended.operand).data;
679 const name_strat: Zir.Inst.NameStrategy = @fromBackingInt(@intCast(extended.small));
680 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
681 try self.writeInstRef(stream, extra.tag_ty);
682 try stream.writeAll(", ");
683 try self.writeInstRef(stream, extra.mode);
684 try stream.writeAll(", ");
685 try self.writeInstRef(stream, extra.field_names);
686 try stream.writeAll(", ");
687 try self.writeInstRef(stream, extra.field_values);
688 try stream.writeAll(")) ");
689 const prev_parent_decl_node = self.parent_decl_node;
690 self.parent_decl_node = extra.node;
691 defer self.parent_decl_node = prev_parent_decl_node;
692 try self.writeSrcNode(stream, .zero);
693 },
694 .reify_spirv_type => {
695 const extra = self.code.extraData(Zir.Inst.ReifySpirvType, extended.operand).data;
696 try stream.print("line({d}), ", .{extra.src_line});
697 try self.writeInstRef(stream, extra.operand);
698 try stream.writeAll(")) ");
699 const prev_parent_decl_node = self.parent_decl_node;
700 self.parent_decl_node = extra.node;
701 defer self.parent_decl_node = prev_parent_decl_node;
702 try self.writeSrcNode(stream, .zero);
703 },
704
705 .cmpxchg => try self.writeCmpxchg(stream, extended),
706 .ptr_cast_full => try self.writePtrCastFull(stream, extended),
707 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),
708
709 .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),
710 .closure_get => try self.writeClosureGet(stream, extended),
711 .field_parent_ptr => try self.writeFieldParentPtr(stream, extended),
712 .std_lang_value => try self.writeStdLangValue(stream, extended),
713 .inplace_arith_result_ty => try self.writeInplaceArithResultTy(stream, extended),
714
715 .dbg_empty_stmt => try stream.writeAll("))"),
716 .astgen_error => try stream.writeAll("))"),
717 }
718 }
719
720 fn writeExtNode(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
721 try stream.writeAll(")) ");
722 const src_node: Ast.Node.Offset = @fromBackingInt(@intCast(@as(i32, @bitCast(extended.operand))));
723 try self.writeSrcNode(stream, src_node);
724 }
725
726 fn writeArrayInitElemType(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
727 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].bin;
728 try self.writeInstRef(stream, inst_data.lhs);
729 try stream.print(", {d})", .{@backingInt(inst_data.rhs)});
730 }
731
732 fn writeUnNode(
733 self: *Writer,
734 stream: *std.Io.Writer,
735 inst: Zir.Inst.Index,
736 ) Error!void {
737 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].un_node;
738 try self.writeInstRef(stream, inst_data.operand);
739 try stream.writeAll(") ");
740 try self.writeSrcNode(stream, inst_data.src_node);
741 }
742
743 fn writeUnTok(
744 self: *Writer,
745 stream: *std.Io.Writer,
746 inst: Zir.Inst.Index,
747 ) Error!void {
748 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].un_tok;
749 try self.writeInstRef(stream, inst_data.operand);
750 try stream.writeAll(") ");
751 try self.writeSrcTok(stream, inst_data.src_tok);
752 }
753
754 fn writeValidateDestructure(
755 self: *Writer,
756 stream: *std.Io.Writer,
757 inst: Zir.Inst.Index,
758 ) Error!void {
759 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
760 const extra = self.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data;
761 try self.writeInstRef(stream, extra.operand);
762 try stream.print(", {d}) (destructure=", .{extra.expect_len});
763 try self.writeSrcNode(stream, extra.destructure_node);
764 try stream.writeAll(") ");
765 try self.writeSrcNode(stream, inst_data.src_node);
766 }
767
768 fn writeValidateArrayInitTy(
769 self: *Writer,
770 stream: *std.Io.Writer,
771 inst: Zir.Inst.Index,
772 ) Error!void {
773 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
774 const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
775 try self.writeInstRef(stream, extra.ty);
776 try stream.print(", {d}) ", .{extra.init_count});
777 try self.writeSrcNode(stream, inst_data.src_node);
778 }
779
780 fn writeArrayTypeSentinel(
781 self: *Writer,
782 stream: *std.Io.Writer,
783 inst: Zir.Inst.Index,
784 ) Error!void {
785 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
786 const extra = self.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
787 try self.writeInstRef(stream, extra.len);
788 try stream.writeAll(", ");
789 try self.writeInstRef(stream, extra.sentinel);
790 try stream.writeAll(", ");
791 try self.writeInstRef(stream, extra.elem_type);
792 try stream.writeAll(") ");
793 try self.writeSrcNode(stream, inst_data.src_node);
794 }
795
796 fn writePtrType(
797 self: *Writer,
798 stream: *std.Io.Writer,
799 inst: Zir.Inst.Index,
800 ) Error!void {
801 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].ptr_type;
802 const str_allowzero = if (inst_data.flags.is_allowzero) "allowzero, " else "";
803 const str_const = if (!inst_data.flags.is_mutable) "const, " else "";
804 const str_volatile = if (inst_data.flags.is_volatile) "volatile, " else "";
805 const extra = self.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
806 try self.writeInstRef(stream, extra.data.elem_type);
807 try stream.print(", {s}{s}{s}{s}", .{
808 str_allowzero,
809 str_const,
810 str_volatile,
811 @tagName(inst_data.size),
812 });
813 var extra_index = extra.end;
814 if (inst_data.flags.has_sentinel) {
815 try stream.writeAll(", ");
816 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index]))));
817 extra_index += 1;
818 }
819 if (inst_data.flags.has_align) {
820 try stream.writeAll(", align(");
821 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index]))));
822 extra_index += 1;
823 if (inst_data.flags.has_bit_range) {
824 const bit_start = extra_index + @intFromBool(inst_data.flags.has_addrspace);
825 try stream.writeAll(":");
826 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[bit_start]))));
827 try stream.writeAll(":");
828 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[bit_start + 1]))));
829 }
830 try stream.writeAll(")");
831 }
832 if (inst_data.flags.has_addrspace) {
833 try stream.writeAll(", addrspace(");
834 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index]))));
835 try stream.writeAll(")");
836 }
837 try stream.writeAll(") ");
838 try self.writeSrcNode(stream, extra.data.src_node);
839 }
840
841 fn writeInt(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
842 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].int;
843 try stream.print("{d})", .{inst_data});
844 }
845
846 fn writeIntBig(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
847 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].str;
848 const byte_count = inst_data.len * @sizeOf(std.math.big.Limb);
849 const limb_bytes = self.code.string_bytes[@backingInt(inst_data.start)..][0..byte_count];
850 // limb_bytes is not aligned properly; we must allocate and copy the bytes
851 // in order to accomplish this.
852 const limbs = try self.gpa.alloc(std.math.big.Limb, inst_data.len);
853 defer self.gpa.free(limbs);
854
855 @memcpy(mem.sliceAsBytes(limbs), limb_bytes);
856 const big_int: std.math.big.int.Const = .{
857 .limbs = limbs,
858 .positive = true,
859 };
860 const as_string = try big_int.toStringAlloc(self.gpa, 10, .lower);
861 defer self.gpa.free(as_string);
862 try stream.print("{s})", .{as_string});
863 }
864
865 fn writeFloat(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
866 const number = self.code.instructions.items(.data)[@backingInt(inst)].float;
867 try stream.print("{d})", .{number});
868 }
869
870 fn writeFloat128(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
871 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
872 const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;
873 const number = extra.get();
874 // TODO improve std.format to be able to print f128 values
875 try stream.print("{d}) ", .{@as(f64, @floatCast(number))});
876 try self.writeSrcNode(stream, inst_data.src_node);
877 }
878
879 fn writeStr(
880 self: *Writer,
881 stream: *std.Io.Writer,
882 inst: Zir.Inst.Index,
883 ) Error!void {
884 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].str;
885 const str = inst_data.get(self.code);
886 try stream.print("\"{f}\")", .{std.zig.fmtString(str)});
887 }
888
889 fn writeSliceStart(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
890 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
891 const extra = self.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data;
892 try self.writeInstRef(stream, extra.lhs);
893 try stream.writeAll(", ");
894 try self.writeInstRef(stream, extra.start);
895 try stream.writeAll(") ");
896 try self.writeSrcNode(stream, inst_data.src_node);
897 }
898
899 fn writeSliceEnd(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
900 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
901 const extra = self.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data;
902 try self.writeInstRef(stream, extra.lhs);
903 try stream.writeAll(", ");
904 try self.writeInstRef(stream, extra.start);
905 try stream.writeAll(", ");
906 try self.writeInstRef(stream, extra.end);
907 try stream.writeAll(") ");
908 try self.writeSrcNode(stream, inst_data.src_node);
909 }
910
911 fn writeSliceSentinel(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
912 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
913 const extra = self.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data;
914 try self.writeInstRef(stream, extra.lhs);
915 try stream.writeAll(", ");
916 try self.writeInstRef(stream, extra.start);
917 try stream.writeAll(", ");
918 try self.writeInstRef(stream, extra.end);
919 try stream.writeAll(", ");
920 try self.writeInstRef(stream, extra.sentinel);
921 try stream.writeAll(") ");
922 try self.writeSrcNode(stream, inst_data.src_node);
923 }
924
925 fn writeSliceLength(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
926 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
927 const extra = self.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data;
928 try self.writeInstRef(stream, extra.lhs);
929 try stream.writeAll(", ");
930 try self.writeInstRef(stream, extra.start);
931 try stream.writeAll(", ");
932 try self.writeInstRef(stream, extra.len);
933 if (extra.sentinel != .none) {
934 try stream.writeAll(", ");
935 try self.writeInstRef(stream, extra.sentinel);
936 }
937 try stream.writeAll(") ");
938 try self.writeSrcNode(stream, inst_data.src_node);
939 }
940
941 fn writeUnionInit(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
942 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
943 const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
944 try self.writeInstRef(stream, extra.union_type);
945 try stream.writeAll(", ");
946 try self.writeInstRef(stream, extra.field_name);
947 try stream.writeAll(", ");
948 try self.writeInstRef(stream, extra.init);
949 try stream.writeAll(") ");
950 try self.writeSrcNode(stream, inst_data.src_node);
951 }
952
953 fn writeShuffle(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
954 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
955 const extra = self.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;
956 try self.writeInstRef(stream, extra.elem_type);
957 try stream.writeAll(", ");
958 try self.writeInstRef(stream, extra.a);
959 try stream.writeAll(", ");
960 try self.writeInstRef(stream, extra.b);
961 try stream.writeAll(", ");
962 try self.writeInstRef(stream, extra.mask);
963 try stream.writeAll(") ");
964 try self.writeSrcNode(stream, inst_data.src_node);
965 }
966
967 fn writeSelect(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
968 const extra = self.code.extraData(Zir.Inst.Select, extended.operand).data;
969 try self.writeInstRef(stream, extra.elem_type);
970 try stream.writeAll(", ");
971 try self.writeInstRef(stream, extra.pred);
972 try stream.writeAll(", ");
973 try self.writeInstRef(stream, extra.a);
974 try stream.writeAll(", ");
975 try self.writeInstRef(stream, extra.b);
976 try stream.writeAll(") ");
977 try self.writeSrcNode(stream, extra.node);
978 }
979
980 fn writeMulAdd(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
981 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
982 const extra = self.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data;
983 try self.writeInstRef(stream, extra.mulend1);
984 try stream.writeAll(", ");
985 try self.writeInstRef(stream, extra.mulend2);
986 try stream.writeAll(", ");
987 try self.writeInstRef(stream, extra.addend);
988 try stream.writeAll(") ");
989 try self.writeSrcNode(stream, inst_data.src_node);
990 }
991
992 fn writeFromBackingInt(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
993 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
994 const extra = self.code.extraData(Zir.Inst.FromBackingInt, inst_data.payload_index);
995 try self.writeInstRef(stream, extra.data.result_type);
996 try stream.writeAll(", ");
997 try self.writeBracedBody(stream, self.code.bodySlice(extra.end, extra.data.body_len));
998 try stream.writeAll(") ");
999 try self.writeSrcNode(stream, inst_data.src_node);
1000 }
1001
1002 fn writeBuiltinCall(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1003 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1004 const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
1005
1006 try self.writeFlag(stream, "nodiscard ", extra.flags.ensure_result_used);
1007 try self.writeFlag(stream, "nosuspend ", extra.flags.is_nosuspend);
1008
1009 try self.writeInstRef(stream, extra.modifier);
1010 try stream.writeAll(", ");
1011 try self.writeInstRef(stream, extra.callee);
1012 try stream.writeAll(", ");
1013 try self.writeInstRef(stream, extra.args);
1014 try stream.writeAll(") ");
1015 try self.writeSrcNode(stream, inst_data.src_node);
1016 }
1017
1018 fn writeFieldParentPtr(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1019 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;
1020 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
1021 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1022 if (flags.align_cast) try stream.writeAll("align_cast, ");
1023 if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, ");
1024 if (flags.const_cast) try stream.writeAll("const_cast, ");
1025 if (flags.volatile_cast) try stream.writeAll("volatile_cast, ");
1026 try self.writeInstRef(stream, extra.parent_ptr_type);
1027 try stream.writeAll(", ");
1028 try self.writeInstRef(stream, extra.field_name);
1029 try stream.writeAll(", ");
1030 try self.writeInstRef(stream, extra.field_ptr);
1031 try stream.writeAll(") ");
1032 try self.writeSrcNode(stream, extra.src_node);
1033 }
1034
1035 fn writeParam(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1036 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_tok;
1037 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
1038 const body = self.code.bodySlice(extra.end, extra.data.type.body_len);
1039 try stream.print("\"{f}\", ", .{
1040 std.zig.fmtString(self.code.nullTerminatedString(extra.data.name)),
1041 });
1042
1043 if (extra.data.type.is_generic) try stream.writeAll("[generic] ");
1044
1045 try self.writeBracedBody(stream, body);
1046 try stream.writeAll(") ");
1047 try self.writeSrcTok(stream, inst_data.src_tok);
1048 }
1049
1050 fn writePlNodeBin(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1051 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1052 const extra = self.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1053 try self.writeInstRef(stream, extra.lhs);
1054 try stream.writeAll(", ");
1055 try self.writeInstRef(stream, extra.rhs);
1056 try stream.writeAll(") ");
1057 try self.writeSrcNode(stream, inst_data.src_node);
1058 }
1059
1060 fn writePlNodeMultiOp(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1061 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1062 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
1063 const args = self.code.refSlice(extra.end, extra.data.operands_len);
1064 try stream.writeAll("{");
1065 for (args, 0..) |arg, i| {
1066 if (i != 0) try stream.writeAll(", ");
1067 try self.writeInstRef(stream, arg);
1068 }
1069 try stream.writeAll("}) ");
1070 try self.writeSrcNode(stream, inst_data.src_node);
1071 }
1072
1073 fn writeElemValImm(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1074 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].elem_val_imm;
1075 try self.writeInstRef(stream, inst_data.operand);
1076 try stream.print(", {d})", .{inst_data.idx});
1077 }
1078
1079 fn writeArrayInitElemPtr(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1080 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1081 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
1082
1083 try self.writeInstRef(stream, extra.ptr);
1084 try stream.print(", {d}) ", .{extra.index});
1085 try self.writeSrcNode(stream, inst_data.src_node);
1086 }
1087
1088 fn writePlNodeExport(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1089 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1090 const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;
1091
1092 try self.writeInstRef(stream, extra.exported);
1093 try stream.writeAll(", ");
1094 try self.writeInstRef(stream, extra.options);
1095 try stream.writeAll(") ");
1096 try self.writeSrcNode(stream, inst_data.src_node);
1097 }
1098
1099 fn writeValidateArrayInitRefTy(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1100 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1101 const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data;
1102
1103 try self.writeInstRef(stream, extra.ptr_ty);
1104 try stream.writeAll(", ");
1105 try stream.print(", {}) ", .{extra.elem_count});
1106 try self.writeSrcNode(stream, inst_data.src_node);
1107 }
1108
1109 fn writeStructInit(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1110 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1111 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
1112 var field_i: u32 = 0;
1113 var extra_index = extra.end;
1114
1115 while (field_i < extra.data.fields_len) : (field_i += 1) {
1116 const item = self.code.extraData(Zir.Inst.StructInit.Item, extra_index);
1117 extra_index = item.end;
1118
1119 if (field_i != 0) {
1120 try stream.writeAll(", [");
1121 } else {
1122 try stream.writeAll("[");
1123 }
1124 try self.writeInstIndex(stream, item.data.field_type);
1125 try stream.writeAll(", ");
1126 try self.writeInstRef(stream, item.data.init);
1127 try stream.writeAll("]");
1128 }
1129 try stream.writeAll(") ");
1130 try self.writeSrcNode(stream, inst_data.src_node);
1131 }
1132
1133 fn writeCmpxchg(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1134 const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;
1135
1136 try self.writeInstRef(stream, extra.ptr);
1137 try stream.writeAll(", ");
1138 try self.writeInstRef(stream, extra.expected_value);
1139 try stream.writeAll(", ");
1140 try self.writeInstRef(stream, extra.new_value);
1141 try stream.writeAll(", ");
1142 try self.writeInstRef(stream, extra.success_order);
1143 try stream.writeAll(", ");
1144 try self.writeInstRef(stream, extra.failure_order);
1145 try stream.writeAll(") ");
1146 try self.writeSrcNode(stream, extra.node);
1147 }
1148
1149 fn writePtrCastFull(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1150 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
1151 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1152 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
1153 if (flags.ptr_cast) try stream.writeAll("ptr_cast, ");
1154 if (flags.align_cast) try stream.writeAll("align_cast, ");
1155 if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, ");
1156 if (flags.const_cast) try stream.writeAll("const_cast, ");
1157 if (flags.volatile_cast) try stream.writeAll("volatile_cast, ");
1158 try self.writeInstRef(stream, extra.lhs);
1159 try stream.writeAll(", ");
1160 try self.writeInstRef(stream, extra.rhs);
1161 try stream.writeAll(")) ");
1162 try self.writeSrcNode(stream, extra.node);
1163 }
1164
1165 fn writePtrCastNoDest(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1166 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
1167 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
1168 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
1169 if (flags.const_cast) try stream.writeAll("const_cast, ");
1170 if (flags.volatile_cast) try stream.writeAll("volatile_cast, ");
1171 try self.writeInstRef(stream, extra.operand);
1172 try stream.writeAll(")) ");
1173 try self.writeSrcNode(stream, extra.node);
1174 }
1175
1176 fn writeAtomicLoad(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1177 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1178 const extra = self.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data;
1179
1180 try self.writeInstRef(stream, extra.elem_type);
1181 try stream.writeAll(", ");
1182 try self.writeInstRef(stream, extra.ptr);
1183 try stream.writeAll(", ");
1184 try self.writeInstRef(stream, extra.ordering);
1185 try stream.writeAll(") ");
1186 try self.writeSrcNode(stream, inst_data.src_node);
1187 }
1188
1189 fn writeAtomicStore(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1190 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1191 const extra = self.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data;
1192
1193 try self.writeInstRef(stream, extra.ptr);
1194 try stream.writeAll(", ");
1195 try self.writeInstRef(stream, extra.operand);
1196 try stream.writeAll(", ");
1197 try self.writeInstRef(stream, extra.ordering);
1198 try stream.writeAll(") ");
1199 try self.writeSrcNode(stream, inst_data.src_node);
1200 }
1201
1202 fn writeAtomicRmw(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1203 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1204 const extra = self.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;
1205
1206 try self.writeInstRef(stream, extra.ptr);
1207 try stream.writeAll(", ");
1208 try self.writeInstRef(stream, extra.operation);
1209 try stream.writeAll(", ");
1210 try self.writeInstRef(stream, extra.operand);
1211 try stream.writeAll(", ");
1212 try self.writeInstRef(stream, extra.ordering);
1213 try stream.writeAll(") ");
1214 try self.writeSrcNode(stream, inst_data.src_node);
1215 }
1216
1217 fn writeStructInitAnon(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1218 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1219 const extra = self.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
1220 var field_i: u32 = 0;
1221 var extra_index = extra.end;
1222
1223 while (field_i < extra.data.fields_len) : (field_i += 1) {
1224 const item = self.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
1225 extra_index = item.end;
1226
1227 const field_name = self.code.nullTerminatedString(item.data.field_name);
1228
1229 const prefix = if (field_i != 0) ", [" else "[";
1230 try stream.print("{s}{s}=", .{ prefix, field_name });
1231 try self.writeInstRef(stream, item.data.init);
1232 try stream.writeAll("]");
1233 }
1234 try stream.writeAll(") ");
1235 try self.writeSrcNode(stream, inst_data.src_node);
1236 }
1237
1238 fn writeStructInitFieldType(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1239 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1240 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
1241 try self.writeInstRef(stream, extra.container_type);
1242 const field_name = self.code.nullTerminatedString(extra.name_start);
1243 try stream.print(", {s}) ", .{field_name});
1244 try self.writeSrcNode(stream, inst_data.src_node);
1245 }
1246
1247 fn writeFieldTypeRef(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1248 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1249 const extra = self.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data;
1250 try self.writeInstRef(stream, extra.container_type);
1251 try stream.writeAll(", ");
1252 try self.writeInstRef(stream, extra.field_name);
1253 try stream.writeAll(") ");
1254 try self.writeSrcNode(stream, inst_data.src_node);
1255 }
1256
1257 fn writeNodeMultiOp(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1258 const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
1259 const operands = self.code.refSlice(extra.end, extended.small);
1260
1261 for (operands, 0..) |operand, i| {
1262 if (i != 0) try stream.writeAll(", ");
1263 try self.writeInstRef(stream, operand);
1264 }
1265 try stream.writeAll(")) ");
1266 try self.writeSrcNode(stream, extra.data.src_node);
1267 }
1268
1269 fn writeInstNode(
1270 self: *Writer,
1271 stream: *std.Io.Writer,
1272 inst: Zir.Inst.Index,
1273 ) Error!void {
1274 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].inst_node;
1275 try self.writeInstIndex(stream, inst_data.inst);
1276 try stream.writeAll(") ");
1277 try self.writeSrcNode(stream, inst_data.src_node);
1278 }
1279
1280 fn writeAsm(
1281 self: *Writer,
1282 stream: *std.Io.Writer,
1283 extended: Zir.Inst.Extended.InstData,
1284 tmpl_is_expr: bool,
1285 ) !void {
1286 const extra = self.code.extraData(Zir.Inst.Asm, extended.operand);
1287 const small: Zir.Inst.Asm.Small = @bitCast(extended.small);
1288
1289 try self.writeFlag(stream, "volatile, ", small.is_volatile);
1290 if (tmpl_is_expr) {
1291 try self.writeInstRef(stream, @fromBackingInt(@intCast(@backingInt(extra.data.asm_source))));
1292 } else {
1293 const asm_source = self.code.nullTerminatedString(extra.data.asm_source);
1294 try stream.print("\"{f}\"", .{std.zig.fmtString(asm_source)});
1295 }
1296 try stream.writeAll(", ");
1297
1298 var extra_i: usize = extra.end;
1299 var output_type_bits = extra.data.output_type_bits;
1300 {
1301 var i: usize = 0;
1302 while (i < small.outputs_len) : (i += 1) {
1303 const output = self.code.extraData(Zir.Inst.Asm.Output, extra_i);
1304 extra_i = output.end;
1305
1306 const is_type = @as(u1, @truncate(output_type_bits)) != 0;
1307 output_type_bits >>= 1;
1308
1309 const name = self.code.nullTerminatedString(output.data.name);
1310 const constraint = self.code.nullTerminatedString(output.data.constraint);
1311 try stream.print("output({f}, \"{f}\", ", .{
1312 std.zig.fmtIdP(name), std.zig.fmtString(constraint),
1313 });
1314 try self.writeFlag(stream, "-> ", is_type);
1315 try self.writeInstRef(stream, output.data.operand);
1316 try stream.writeAll("), ");
1317 }
1318 }
1319 {
1320 var i: usize = 0;
1321 while (i < small.inputs_len) : (i += 1) {
1322 const input = self.code.extraData(Zir.Inst.Asm.Input, extra_i);
1323 extra_i = input.end;
1324
1325 const name = self.code.nullTerminatedString(input.data.name);
1326 const constraint = self.code.nullTerminatedString(input.data.constraint);
1327 try stream.print("input({f}, \"{f}\", ", .{
1328 std.zig.fmtIdP(name), std.zig.fmtString(constraint),
1329 });
1330 try self.writeInstRef(stream, input.data.operand);
1331 try stream.writeAll("), ");
1332 }
1333 }
1334
1335 try self.writeInstRef(stream, extra.data.clobbers);
1336
1337 try stream.writeAll(")) ");
1338 try self.writeSrcNode(stream, extra.data.src_node);
1339 }
1340
1341 fn writeOverflowArithmetic(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1342 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
1343
1344 try self.writeInstRef(stream, extra.lhs);
1345 try stream.writeAll(", ");
1346 try self.writeInstRef(stream, extra.rhs);
1347 try stream.writeAll(")) ");
1348 try self.writeSrcNode(stream, extra.node);
1349 }
1350
1351 fn writeCall(
1352 self: *Writer,
1353 stream: *std.Io.Writer,
1354 inst: Zir.Inst.Index,
1355 comptime kind: enum { direct, field },
1356 ) !void {
1357 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1358 const ExtraType = switch (kind) {
1359 .direct => Zir.Inst.Call,
1360 .field => Zir.Inst.FieldCall,
1361 };
1362 const extra = self.code.extraData(ExtraType, inst_data.payload_index);
1363 const args_len = extra.data.flags.args_len;
1364 const body = self.code.extra[extra.end..];
1365
1366 if (extra.data.flags.ensure_result_used) {
1367 try stream.writeAll("nodiscard ");
1368 }
1369 try stream.print(".{s}, ", .{@tagName(@as(std.lang.CallModifier, @fromBackingInt(@intCast(extra.data.flags.packed_modifier))))});
1370 switch (kind) {
1371 .direct => try self.writeInstRef(stream, extra.data.callee),
1372 .field => {
1373 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);
1374 try self.writeInstRef(stream, extra.data.obj_ptr);
1375 try stream.print(", \"{f}\"", .{std.zig.fmtString(field_name)});
1376 },
1377 }
1378 try stream.writeAll(", [");
1379
1380 self.indent += 2;
1381 if (args_len != 0) {
1382 try stream.writeAll("\n");
1383 }
1384 var i: usize = 0;
1385 var arg_start: u32 = args_len;
1386 while (i < args_len) : (i += 1) {
1387 try stream.splatByteAll(' ', self.indent);
1388 const arg_end = self.code.extra[extra.end + i];
1389 defer arg_start = arg_end;
1390 const arg_body = body[arg_start..arg_end];
1391 try self.writeBracedBody(stream, @ptrCast(arg_body));
1392
1393 try stream.writeAll(",\n");
1394 }
1395 self.indent -= 2;
1396 if (args_len != 0) {
1397 try stream.splatByteAll(' ', self.indent);
1398 }
1399
1400 try stream.writeAll("]) ");
1401 try self.writeSrcNode(stream, inst_data.src_node);
1402 }
1403
1404 fn writeBlock(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1405 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1406 const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
1407 const body = self.code.bodySlice(extra.end, extra.data.body_len);
1408 try self.writeBracedBody(stream, body);
1409 try stream.writeAll(") ");
1410 try self.writeSrcNode(stream, inst_data.src_node);
1411 }
1412
1413 fn writeBlockComptime(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1414 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1415 const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index);
1416 const body = self.code.bodySlice(extra.end, extra.data.body_len);
1417 try stream.print("reason={s}, ", .{@tagName(extra.data.reason)});
1418 try self.writeBracedBody(stream, body);
1419 try stream.writeAll(") ");
1420 try self.writeSrcNode(stream, inst_data.src_node);
1421 }
1422
1423 fn writeCondBr(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1424 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1425 const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
1426 const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len);
1427 const else_body = self.code.bodySlice(extra.end + then_body.len, extra.data.else_body_len);
1428 try self.writeInstRef(stream, extra.data.condition);
1429 try stream.writeAll(", ");
1430 try self.writeBracedBody(stream, then_body);
1431 try stream.writeAll(", ");
1432 try self.writeBracedBody(stream, else_body);
1433 try stream.writeAll(") ");
1434 try self.writeSrcNode(stream, inst_data.src_node);
1435 }
1436
1437 fn writeTry(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1438 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1439 const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1440 const body = self.code.bodySlice(extra.end, extra.data.body_len);
1441 try self.writeInstRef(stream, extra.data.operand);
1442 try stream.writeAll(", ");
1443 try self.writeBracedBody(stream, body);
1444 try stream.writeAll(") ");
1445 try self.writeSrcNode(stream, inst_data.src_node);
1446 }
1447
1448 fn writeStructDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1449 const struct_decl = self.code.getStructDecl(inst);
1450
1451 const prev_parent_decl_node = self.parent_decl_node;
1452 self.parent_decl_node = struct_decl.src_node;
1453 defer self.parent_decl_node = prev_parent_decl_node;
1454
1455 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
1456 try stream.print("hash({x}) ", .{&fields_hash});
1457
1458 try stream.print("{s}, ", .{@tagName(struct_decl.name_strategy)});
1459
1460 if (struct_decl.backing_int_type_body) |backing_int_type_body| {
1461 assert(struct_decl.layout == .@"packed");
1462 try stream.writeAll("packed(");
1463 try self.writeBracedDecl(stream, backing_int_type_body);
1464 try stream.writeAll("), ");
1465 } else {
1466 try stream.print("{s}, ", .{@tagName(struct_decl.layout)});
1467 }
1468
1469 try self.writeCaptures(stream, struct_decl.captures, struct_decl.capture_names);
1470 try stream.writeAll(", ");
1471 try self.writeBracedDecl(stream, struct_decl.decls);
1472 try stream.writeAll(", ");
1473
1474 if (struct_decl.field_names.len == 0) {
1475 try stream.writeAll("{}) ");
1476 } else {
1477 try stream.writeAll("{\n");
1478 self.indent += 2;
1479
1480 var it = struct_decl.iterateFields();
1481 while (it.next()) |field| {
1482 try stream.splatByteAll(' ', self.indent);
1483 try self.writeFlag(stream, "comptime ", field.is_comptime);
1484 const field_name = self.code.nullTerminatedString(field.name);
1485 try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)});
1486
1487 self.indent += 2;
1488 try self.writeBracedDecl(stream, field.type_body);
1489 if (field.align_body) |body| {
1490 try stream.writeAll(" align(");
1491 try self.writeBracedDecl(stream, body);
1492 try stream.writeByte(')');
1493 }
1494 if (field.default_body) |body| {
1495 try stream.writeAll(" = ");
1496 try self.writeBracedDecl(stream, body);
1497 }
1498 self.indent -= 2;
1499
1500 try stream.writeAll(",\n");
1501 }
1502
1503 self.indent -= 2;
1504 try stream.splatByteAll(' ', self.indent);
1505 try stream.writeAll("}) ");
1506 }
1507 try self.writeSrcNode(stream, .zero);
1508 }
1509
1510 fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1511 const union_decl = self.code.getUnionDecl(inst);
1512
1513 const prev_parent_decl_node = self.parent_decl_node;
1514 self.parent_decl_node = union_decl.src_node;
1515 defer self.parent_decl_node = prev_parent_decl_node;
1516
1517 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
1518 try stream.print("hash({x}) ", .{&fields_hash});
1519
1520 try stream.print("{s}, ", .{@tagName(union_decl.name_strategy)});
1521
1522 switch (union_decl.kind) {
1523 .auto => try stream.writeAll("auto, "),
1524 .@"extern" => try stream.writeAll("extern, "),
1525 .@"packed" => try stream.writeAll("packed, "),
1526 .packed_explicit => {
1527 try stream.writeAll("packed(");
1528 try self.writeBracedDecl(stream, union_decl.arg_type_body.?);
1529 try stream.writeAll("), ");
1530 },
1531 .tagged_explicit => {
1532 try stream.writeAll("tagged(");
1533 try self.writeBracedDecl(stream, union_decl.arg_type_body.?);
1534 try stream.writeAll("), ");
1535 },
1536 .tagged_enum => try stream.writeAll("tagged(enum), "),
1537 .tagged_enum_explicit => {
1538 try stream.writeAll("tagged(enum(");
1539 try self.writeBracedDecl(stream, union_decl.arg_type_body.?);
1540 try stream.writeAll(")), ");
1541 },
1542 }
1543
1544 try self.writeCaptures(stream, union_decl.captures, union_decl.capture_names);
1545 try stream.writeAll(", ");
1546 try self.writeBracedDecl(stream, union_decl.decls);
1547 try stream.writeAll(", ");
1548
1549 if (union_decl.field_names.len == 0) {
1550 try stream.writeAll("}) ");
1551 } else {
1552 try stream.writeAll("{\n");
1553 self.indent += 2;
1554
1555 var it = union_decl.iterateFields();
1556 while (it.next()) |field| {
1557 try stream.splatByteAll(' ', self.indent);
1558 const field_name = self.code.nullTerminatedString(field.name);
1559 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
1560
1561 self.indent += 2;
1562 if (field.type_body) |body| {
1563 try stream.writeAll(": ");
1564 try self.writeBracedDecl(stream, body);
1565 }
1566 if (field.align_body) |body| {
1567 try stream.writeAll(" align(");
1568 try self.writeBracedDecl(stream, body);
1569 try stream.writeByte(')');
1570 }
1571 if (field.value_body) |body| {
1572 try stream.writeAll(" = ");
1573 try self.writeBracedDecl(stream, body);
1574 }
1575 self.indent -= 2;
1576
1577 try stream.writeAll(",\n");
1578 }
1579 self.indent -= 2;
1580 try stream.splatByteAll(' ', self.indent);
1581 try stream.writeAll("}) ");
1582 }
1583 try self.writeSrcNode(stream, .zero);
1584 }
1585
1586 fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1587 const enum_decl = self.code.getEnumDecl(inst);
1588
1589 const prev_parent_decl_node = self.parent_decl_node;
1590 self.parent_decl_node = enum_decl.src_node;
1591 defer self.parent_decl_node = prev_parent_decl_node;
1592
1593 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
1594 try stream.print("hash({x}) ", .{&fields_hash});
1595
1596 try stream.print("{s}, ", .{@tagName(enum_decl.name_strategy)});
1597 try self.writeFlag(stream, "nonexhaustive, ", enum_decl.nonexhaustive);
1598 if (enum_decl.tag_type_body) |tag_type_body| {
1599 try stream.writeAll("tag(");
1600 try self.writeBracedDecl(stream, tag_type_body);
1601 try stream.writeAll("), ");
1602 }
1603
1604 try self.writeCaptures(stream, enum_decl.captures, enum_decl.capture_names);
1605 try stream.writeAll(", ");
1606 try self.writeBracedDecl(stream, enum_decl.decls);
1607 try stream.writeAll(", ");
1608
1609 if (enum_decl.field_names.len == 0) {
1610 try stream.writeAll("{}) ");
1611 } else {
1612 try stream.writeAll("{\n");
1613 self.indent += 2;
1614
1615 var it = enum_decl.iterateFields();
1616 while (it.next()) |field| {
1617 try stream.splatByteAll(' ', self.indent);
1618 const field_name = self.code.nullTerminatedString(field.name);
1619 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
1620 if (field.value_body) |body| {
1621 try stream.writeAll(" = ");
1622 try self.writeBracedDecl(stream, body);
1623 }
1624 try stream.writeAll(",\n");
1625 }
1626 self.indent -= 2;
1627 try stream.splatByteAll(' ', self.indent);
1628 try stream.writeAll("}) ");
1629 }
1630 try self.writeSrcNode(stream, .zero);
1631 }
1632
1633 fn writeOpaqueDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1634 const opaque_decl = self.code.getOpaqueDecl(inst);
1635
1636 const prev_parent_decl_node = self.parent_decl_node;
1637 self.parent_decl_node = opaque_decl.src_node;
1638 defer self.parent_decl_node = prev_parent_decl_node;
1639
1640 try stream.print("{s}, ", .{@tagName(opaque_decl.name_strategy)});
1641 try self.writeCaptures(stream, opaque_decl.captures, opaque_decl.capture_names);
1642 try stream.writeAll(", ");
1643 try self.writeBracedDecl(stream, opaque_decl.decls);
1644 try stream.writeAll(") ");
1645 try self.writeSrcNode(stream, .zero);
1646 }
1647
1648 fn writeTupleDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1649 const fields_len = extended.small;
1650 assert(fields_len != 0);
1651 const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand);
1652
1653 var extra_index = extra.end;
1654
1655 try stream.writeAll("{ ");
1656
1657 for (0..fields_len) |field_idx| {
1658 if (field_idx != 0) try stream.writeAll(", ");
1659
1660 const field_ty, const field_init = self.code.extra[extra_index..][0..2].*;
1661 extra_index += 2;
1662
1663 try stream.print("@\"{d}\": ", .{field_idx});
1664 try self.writeInstRef(stream, @fromBackingInt(@intCast(field_ty)));
1665 try stream.writeAll(" = ");
1666 try self.writeInstRef(stream, @fromBackingInt(@intCast(field_init)));
1667 }
1668
1669 try stream.writeAll(" }) ");
1670
1671 try self.writeSrcNode(stream, extra.data.src_node);
1672 }
1673
1674 fn writeErrorSetDecl(
1675 self: *Writer,
1676 stream: *std.Io.Writer,
1677 inst: Zir.Inst.Index,
1678 ) !void {
1679 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1680 const extra = self.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
1681
1682 try stream.writeAll("{\n");
1683 self.indent += 2;
1684
1685 var extra_index = @as(u32, @intCast(extra.end));
1686 const extra_index_end = extra_index + extra.data.fields_len;
1687 while (extra_index < extra_index_end) : (extra_index += 1) {
1688 const name_index: Zir.NullTerminatedString = @fromBackingInt(@intCast(self.code.extra[extra_index]));
1689 const name = self.code.nullTerminatedString(name_index);
1690 try stream.splatByteAll(' ', self.indent);
1691 try stream.print("{f},\n", .{std.zig.fmtIdP(name)});
1692 }
1693
1694 self.indent -= 2;
1695 try stream.splatByteAll(' ', self.indent);
1696 try stream.writeAll("}) ");
1697
1698 try self.writeSrcNode(stream, inst_data.src_node);
1699 }
1700
1701 fn writeSwitchBlock(
1702 self: *Writer,
1703 stream: *std.Io.Writer,
1704 inst: Zir.Inst.Index,
1705 ) !void {
1706 const zir_switch = self.code.getSwitchBlock(inst);
1707 var extra_index = zir_switch.end;
1708
1709 try self.writeInstRef(stream, zir_switch.main_operand);
1710
1711 self.indent += 2;
1712
1713 if (zir_switch.non_err_case) |non_err_case| {
1714 if (non_err_case.operand_is_ref) try stream.writeAll(" ref");
1715
1716 try stream.writeAll(",\n");
1717 try stream.splatByteAll(' ', self.indent);
1718
1719 try self.writeSwitchCaptures(stream, non_err_case.capture, false, inst, &zir_switch);
1720
1721 try stream.writeAll("non_err => ");
1722 try self.writeBracedBody(stream, non_err_case.body);
1723 try stream.writeAll(" ");
1724 try self.writeSrcNode(stream, zir_switch.catch_or_if_src_node_offset.unwrap().?);
1725 }
1726 if (zir_switch.else_case) |else_case| {
1727 try stream.writeAll(",\n");
1728 try stream.splatByteAll(' ', self.indent);
1729
1730 try self.writeSwitchCaptures(stream, else_case.capture, else_case.has_tag_capture, inst, &zir_switch);
1731 if (else_case.is_inline) try stream.writeAll("inline ");
1732
1733 try stream.writeAll("else => ");
1734 try self.writeBracedBody(stream, else_case.body);
1735 }
1736
1737 var case_it = zir_switch.iterateCases();
1738 while (case_it.next()) |case| {
1739 try stream.writeAll(",\n");
1740 try stream.splatByteAll(' ', self.indent);
1741
1742 const prong_info = case.prong_info;
1743 try self.writeSwitchCaptures(stream, prong_info.capture, prong_info.has_tag_capture, inst, &zir_switch);
1744 if (prong_info.is_inline) try stream.writeAll("inline ");
1745
1746 const prong_body = self.code.bodySlice(extra_index, prong_info.body_len);
1747 extra_index += prong_body.len;
1748
1749 for (case.item_infos, 0..) |item_info, i| {
1750 if (i > 0) try stream.writeAll(", ");
1751
1752 switch (item_info.unwrap()) {
1753 .enum_literal => |str_index| {
1754 const str = self.code.nullTerminatedString(str_index);
1755 try stream.print("\".{f}\"", .{std.zig.fmtString(str)});
1756 },
1757 .error_value => |str_index| {
1758 const str = self.code.nullTerminatedString(str_index);
1759 try stream.print("\"error.{f}\"", .{std.zig.fmtString(str)});
1760 },
1761 .under => try stream.writeByte('_'),
1762 .body_len => |body_len| {
1763 const item_body = self.code.bodySlice(extra_index, body_len);
1764 extra_index += item_body.len;
1765 try self.writeBracedDecl(stream, item_body);
1766 },
1767 }
1768 }
1769 for (case.range_infos, 0..) |range_info, i| {
1770 if (i > 0 and case.item_infos.len == 0) try stream.writeAll(", ");
1771 switch (range_info[0].unwrap()) {
1772 .enum_literal => |str_index| {
1773 const str = self.code.nullTerminatedString(str_index);
1774 try stream.print("\".{f}\"", .{std.zig.fmtString(str)});
1775 },
1776 .error_value => |str_index| {
1777 const str = self.code.nullTerminatedString(str_index);
1778 try stream.print("\"error.{f}\"", .{std.zig.fmtString(str)});
1779 },
1780 .under => unreachable, // '_..._' is not allowed
1781 .body_len => |body_len| {
1782 const item_body = self.code.bodySlice(extra_index, body_len);
1783 extra_index += item_body.len;
1784 try self.writeBracedDecl(stream, item_body);
1785 },
1786 }
1787 try stream.writeAll("...");
1788 switch (range_info[1].unwrap()) {
1789 .enum_literal => |str_index| {
1790 const str = self.code.nullTerminatedString(str_index);
1791 try stream.print("\".{f}\"", .{std.zig.fmtString(str)});
1792 },
1793 .error_value => |str_index| {
1794 const str = self.code.nullTerminatedString(str_index);
1795 try stream.print("\"error.{f}\"", .{std.zig.fmtString(str)});
1796 },
1797 .under => unreachable, // '_..._' is not allowed
1798 .body_len => |body_len| {
1799 const item_body = self.code.bodySlice(extra_index, body_len);
1800 extra_index += item_body.len;
1801 try self.writeBracedDecl(stream, item_body);
1802 },
1803 }
1804 }
1805 try stream.writeAll(" => ");
1806 try self.writeBracedBody(stream, prong_body);
1807 }
1808
1809 self.indent -= 2;
1810
1811 try stream.writeAll(") ");
1812 try self.writeSrcNode(stream, zir_switch.switch_src_node_offset);
1813 }
1814
1815 fn writeSwitchCaptures(
1816 self: *Writer,
1817 stream: *std.Io.Writer,
1818 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
1819 has_tag_capture: bool,
1820 switch_inst: Zir.Inst.Index,
1821 zir_switch: *const Zir.UnwrappedSwitchBlock,
1822 ) !void {
1823 if (capture != .none) {
1824 try stream.print("{t}=", .{capture});
1825 const capture_inst = zir_switch.payload_capture_placeholder.unwrap() orelse switch_inst;
1826 try self.writeInstIndex(stream, capture_inst);
1827 try stream.writeAll(" ");
1828 }
1829 if (has_tag_capture) {
1830 try stream.writeAll("tag=");
1831 const capture_inst = zir_switch.tag_capture_placeholder.unwrap() orelse switch_inst;
1832 try self.writeInstIndex(stream, capture_inst);
1833 try stream.writeAll(" ");
1834 }
1835 }
1836
1837 fn writePlNodeField(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1838 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1839 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
1840 const name = self.code.nullTerminatedString(extra.field_name_start);
1841 try self.writeInstRef(stream, extra.lhs);
1842 try stream.print(", \"{f}\") ", .{std.zig.fmtString(name)});
1843 try self.writeSrcNode(stream, inst_data.src_node);
1844 }
1845
1846 fn writePlNodeFieldNamed(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1847 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1848 const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
1849 try self.writeInstRef(stream, extra.lhs);
1850 try stream.writeAll(", ");
1851 try self.writeInstRef(stream, extra.field_name);
1852 try stream.writeAll(") ");
1853 try self.writeSrcNode(stream, inst_data.src_node);
1854 }
1855
1856 fn writeAs(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1857 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1858 const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data;
1859 try self.writeInstRef(stream, extra.dest_type);
1860 try stream.writeAll(", ");
1861 try self.writeInstRef(stream, extra.operand);
1862 try stream.writeAll(") ");
1863 try self.writeSrcNode(stream, inst_data.src_node);
1864 }
1865
1866 fn writeNode(
1867 self: *Writer,
1868 stream: *std.Io.Writer,
1869 inst: Zir.Inst.Index,
1870 ) Error!void {
1871 const src_node = self.code.instructions.items(.data)[@backingInt(inst)].node;
1872 try stream.writeAll(") ");
1873 try self.writeSrcNode(stream, src_node);
1874 }
1875
1876 fn writeStrTok(
1877 self: *Writer,
1878 stream: *std.Io.Writer,
1879 inst: Zir.Inst.Index,
1880 ) Error!void {
1881 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].str_tok;
1882 const str = inst_data.get(self.code);
1883 try stream.print("\"{f}\") ", .{std.zig.fmtString(str)});
1884 try self.writeSrcTok(stream, inst_data.src_tok);
1885 }
1886
1887 fn writeStrOp(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1888 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].str_op;
1889 const str = inst_data.getStr(self.code);
1890 try self.writeInstRef(stream, inst_data.operand);
1891 try stream.print(", \"{f}\")", .{std.zig.fmtString(str)});
1892 }
1893
1894 fn writeFunc(
1895 self: *Writer,
1896 stream: *std.Io.Writer,
1897 inst: Zir.Inst.Index,
1898 inferred_error_set: bool,
1899 ) !void {
1900 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1901 const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index);
1902
1903 var extra_index = extra.end;
1904 var ret_ty_ref: Zir.Inst.Ref = .none;
1905 var ret_ty_body: []const Zir.Inst.Index = &.{};
1906
1907 switch (extra.data.ret_ty.body_len) {
1908 0 => {
1909 ret_ty_ref = .void_type;
1910 },
1911 1 => {
1912 ret_ty_ref = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
1913 extra_index += 1;
1914 },
1915 else => {
1916 ret_ty_body = self.code.bodySlice(extra_index, extra.data.ret_ty.body_len);
1917 extra_index += ret_ty_body.len;
1918 },
1919 }
1920
1921 const body = self.code.bodySlice(extra_index, extra.data.body_len);
1922 extra_index += body.len;
1923
1924 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
1925 if (body.len != 0) {
1926 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
1927 }
1928 return self.writeFuncCommon(
1929 stream,
1930 inferred_error_set,
1931 false,
1932 false,
1933
1934 .none,
1935 &.{},
1936 ret_ty_ref,
1937 ret_ty_body,
1938 extra.data.ret_ty.is_generic,
1939
1940 body,
1941 inst_data.src_node,
1942 src_locs,
1943 0,
1944 );
1945 }
1946
1947 fn writeFuncFancy(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1948 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1949 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
1950
1951 var extra_index: usize = extra.end;
1952 var cc_ref: Zir.Inst.Ref = .none;
1953 var cc_body: []const Zir.Inst.Index = &.{};
1954 var ret_ty_ref: Zir.Inst.Ref = .none;
1955 var ret_ty_body: []const Zir.Inst.Index = &.{};
1956
1957 if (extra.data.bits.has_cc_body) {
1958 const body_len = self.code.extra[extra_index];
1959 extra_index += 1;
1960 cc_body = self.code.bodySlice(extra_index, body_len);
1961 extra_index += cc_body.len;
1962 } else if (extra.data.bits.has_cc_ref) {
1963 cc_ref = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
1964 extra_index += 1;
1965 }
1966 if (extra.data.bits.has_ret_ty_body) {
1967 const body_len = self.code.extra[extra_index];
1968 extra_index += 1;
1969 ret_ty_body = self.code.bodySlice(extra_index, body_len);
1970 extra_index += ret_ty_body.len;
1971 } else if (extra.data.bits.has_ret_ty_ref) {
1972 ret_ty_ref = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
1973 extra_index += 1;
1974 }
1975
1976 const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {
1977 const x = self.code.extra[extra_index];
1978 extra_index += 1;
1979 break :blk x;
1980 } else 0;
1981
1982 const body = self.code.bodySlice(extra_index, extra.data.body_len);
1983 extra_index += body.len;
1984
1985 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
1986 if (body.len != 0) {
1987 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
1988 }
1989 return self.writeFuncCommon(
1990 stream,
1991 extra.data.bits.is_inferred_error,
1992 extra.data.bits.is_var_args,
1993 extra.data.bits.is_noinline,
1994 cc_ref,
1995 cc_body,
1996 ret_ty_ref,
1997 ret_ty_body,
1998 extra.data.bits.ret_ty_is_generic,
1999 body,
2000 inst_data.src_node,
2001 src_locs,
2002 noalias_bits,
2003 );
2004 }
2005
2006 fn writeAllocExtended(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2007 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
2008 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));
2009
2010 var extra_index: usize = extra.end;
2011 const type_inst: Zir.Inst.Ref = if (!small.has_type) .none else blk: {
2012 const type_inst = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
2013 extra_index += 1;
2014 break :blk type_inst;
2015 };
2016 const align_inst: Zir.Inst.Ref = if (!small.has_align) .none else blk: {
2017 const align_inst = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
2018 extra_index += 1;
2019 break :blk align_inst;
2020 };
2021 try self.writeFlag(stream, ",is_const", small.is_const);
2022 try self.writeFlag(stream, ",is_comptime", small.is_comptime);
2023 try self.writeOptionalInstRef(stream, ",ty=", type_inst);
2024 try self.writeOptionalInstRef(stream, ",align=", align_inst);
2025 try stream.writeAll(")) ");
2026 try self.writeSrcNode(stream, extra.data.src_node);
2027 }
2028
2029 fn writeTypeofPeer(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2030 const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);
2031 const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len);
2032 try self.writeBracedBody(stream, body);
2033 try stream.writeAll(",[");
2034 const args = self.code.refSlice(extra.end, extended.small);
2035 for (args, 0..) |arg, i| {
2036 if (i != 0) try stream.writeAll(", ");
2037 try self.writeInstRef(stream, arg);
2038 }
2039 try stream.writeAll("])");
2040 }
2041
2042 fn writeBoolBr(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2043 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
2044 const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);
2045 const body = self.code.bodySlice(extra.end, extra.data.body_len);
2046 try self.writeInstRef(stream, extra.data.lhs);
2047 try stream.writeAll(", ");
2048 try self.writeBracedBody(stream, body);
2049 try stream.writeAll(") ");
2050 try self.writeSrcNode(stream, inst_data.src_node);
2051 }
2052
2053 fn writeIntType(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2054 const int_type = self.code.instructions.items(.data)[@backingInt(inst)].int_type;
2055 const prefix: u8 = switch (int_type.signedness) {
2056 .signed => 'i',
2057 .unsigned => 'u',
2058 };
2059 try stream.print("{c}{d}) ", .{ prefix, int_type.bit_count });
2060 try self.writeSrcNode(stream, int_type.src_node);
2061 }
2062
2063 fn writeSaveErrRetIndex(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2064 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].save_err_ret_index;
2065
2066 try self.writeInstRef(stream, inst_data.operand);
2067
2068 try stream.writeAll(")");
2069 }
2070
2071 fn writeRestoreErrRetIndex(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2072 const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;
2073
2074 try self.writeInstRef(stream, extra.block);
2075 try self.writeInstRef(stream, extra.operand);
2076
2077 try stream.writeAll(") ");
2078 try self.writeSrcNode(stream, extra.src_node);
2079 }
2080
2081 fn writeBreak(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2082 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].@"break";
2083 const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;
2084
2085 try self.writeInstIndex(stream, extra.block_inst);
2086 try stream.writeAll(", ");
2087 try self.writeInstRef(stream, inst_data.operand);
2088 try stream.writeAll(")");
2089 }
2090
2091 fn writeArrayInit(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2092 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
2093
2094 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
2095 const args = self.code.refSlice(extra.end, extra.data.operands_len);
2096
2097 try self.writeInstRef(stream, args[0]);
2098 try stream.writeAll("{");
2099 for (args[1..], 0..) |arg, i| {
2100 if (i != 0) try stream.writeAll(", ");
2101 try self.writeInstRef(stream, arg);
2102 }
2103 try stream.writeAll("}) ");
2104 try self.writeSrcNode(stream, inst_data.src_node);
2105 }
2106
2107 fn writeArrayInitAnon(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2108 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
2109
2110 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
2111 const args = self.code.refSlice(extra.end, extra.data.operands_len);
2112
2113 try stream.writeAll("{");
2114 for (args, 0..) |arg, i| {
2115 if (i != 0) try stream.writeAll(", ");
2116 try self.writeInstRef(stream, arg);
2117 }
2118 try stream.writeAll("}) ");
2119 try self.writeSrcNode(stream, inst_data.src_node);
2120 }
2121
2122 fn writeArrayInitSent(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2123 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
2124
2125 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
2126 const args = self.code.refSlice(extra.end, extra.data.operands_len);
2127 const sent = args[args.len - 1];
2128 const elems = args[0 .. args.len - 1];
2129
2130 try self.writeInstRef(stream, sent);
2131 try stream.writeAll(", ");
2132
2133 try stream.writeAll(".{");
2134 for (elems, 0..) |elem, i| {
2135 if (i != 0) try stream.writeAll(", ");
2136 try self.writeInstRef(stream, elem);
2137 }
2138 try stream.writeAll("}) ");
2139 try self.writeSrcNode(stream, inst_data.src_node);
2140 }
2141
2142 fn writeUnreachable(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2143 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].@"unreachable";
2144 try stream.writeAll(") ");
2145 try self.writeSrcNode(stream, inst_data.src_node);
2146 }
2147
2148 fn writeFuncCommon(
2149 self: *Writer,
2150 stream: *std.Io.Writer,
2151 inferred_error_set: bool,
2152 var_args: bool,
2153 is_noinline: bool,
2154 cc_ref: Zir.Inst.Ref,
2155 cc_body: []const Zir.Inst.Index,
2156 ret_ty_ref: Zir.Inst.Ref,
2157 ret_ty_body: []const Zir.Inst.Index,
2158 ret_ty_is_generic: bool,
2159 body: []const Zir.Inst.Index,
2160 src_node: Ast.Node.Offset,
2161 src_locs: Zir.Inst.Func.SrcLocs,
2162 noalias_bits: u32,
2163 ) !void {
2164 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
2165 if (ret_ty_is_generic) try stream.writeAll("[generic] ");
2166 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
2167 try self.writeFlag(stream, "vargs, ", var_args);
2168 try self.writeFlag(stream, "inferror, ", inferred_error_set);
2169 try self.writeFlag(stream, "noinline, ", is_noinline);
2170
2171 if (noalias_bits != 0) {
2172 try stream.print("noalias=0b{b}, ", .{noalias_bits});
2173 }
2174
2175 try stream.writeAll("body=");
2176 try self.writeBracedBody(stream, body);
2177 try stream.writeAll(") ");
2178 if (body.len != 0) {
2179 try stream.print("(lbrace={d}:{d},rbrace={d}:{d}) ", .{
2180 src_locs.lbrace_line + 1, @as(u16, @truncate(src_locs.columns)) + 1,
2181 src_locs.rbrace_line + 1, @as(u16, @truncate(src_locs.columns >> 16)) + 1,
2182 });
2183 }
2184 try self.writeSrcNode(stream, src_node);
2185 }
2186
2187 fn writeDbgStmt(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2188 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].dbg_stmt;
2189 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });
2190 }
2191
2192 fn writeDefer(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2193 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].@"defer";
2194 const body = self.code.bodySlice(inst_data.index, inst_data.len);
2195 try self.writeBracedBody(stream, body);
2196 try stream.writeByte(')');
2197 }
2198
2199 fn writeDeclaration(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2200 const decl = self.code.getDeclaration(inst);
2201
2202 const prev_parent_decl_node = self.parent_decl_node;
2203 defer self.parent_decl_node = prev_parent_decl_node;
2204 self.parent_decl_node = decl.src_node;
2205
2206 if (decl.is_pub) try stream.writeAll("pub ");
2207 switch (decl.linkage) {
2208 .normal => {},
2209 .@"export" => try stream.writeAll("export "),
2210 .@"extern" => try stream.writeAll("extern "),
2211 }
2212 switch (decl.kind) {
2213 .@"comptime" => try stream.writeAll("comptime"),
2214 .unnamed_test => try stream.writeAll("test"),
2215 .@"test", .decltest, .@"const", .@"var" => {
2216 try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) });
2217 },
2218 }
2219 const src_hash = self.code.getAssociatedSrcHash(inst).?;
2220 try stream.print(" line({d}) column({d}) hash({x})", .{
2221 decl.src_line, decl.src_column, &src_hash,
2222 });
2223
2224 {
2225 if (decl.type_body) |b| {
2226 try stream.writeAll(" type=");
2227 try self.writeBracedDecl(stream, b);
2228 }
2229
2230 if (decl.align_body) |b| {
2231 try stream.writeAll(" align=");
2232 try self.writeBracedDecl(stream, b);
2233 }
2234
2235 if (decl.linksection_body) |b| {
2236 try stream.writeAll(" linksection=");
2237 try self.writeBracedDecl(stream, b);
2238 }
2239
2240 if (decl.addrspace_body) |b| {
2241 try stream.writeAll(" addrspace=");
2242 try self.writeBracedDecl(stream, b);
2243 }
2244
2245 if (decl.value_body) |b| {
2246 try stream.writeAll(" value=");
2247 try self.writeBracedDecl(stream, b);
2248 }
2249 }
2250
2251 try stream.writeAll(") ");
2252 try self.writeSrcNode(stream, .zero);
2253 }
2254
2255 fn writeClosureGet(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2256 try stream.print("{d})) ", .{extended.small});
2257 const src_node: Ast.Node.Offset = @fromBackingInt(@intCast(@as(i32, @bitCast(extended.operand))));
2258 try self.writeSrcNode(stream, src_node);
2259 }
2260
2261 fn writeStdLangValue(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2262 const val: Zir.Inst.StdLangValue = @fromBackingInt(@intCast(extended.small));
2263 try stream.print("{s})) ", .{@tagName(val)});
2264 const src_node: Ast.Node.Offset = @fromBackingInt(@intCast(@as(i32, @bitCast(extended.operand))));
2265 try self.writeSrcNode(stream, src_node);
2266 }
2267
2268 fn writeInplaceArithResultTy(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2269 const op: Zir.Inst.InplaceOp = @fromBackingInt(@intCast(extended.small));
2270 try self.writeInstRef(stream, @fromBackingInt(@intCast(extended.operand)));
2271 try stream.print(", {s}))", .{@tagName(op)});
2272 }
2273
2274 fn writeInstRef(self: *Writer, stream: *std.Io.Writer, ref: Zir.Inst.Ref) !void {
2275 if (ref == .none) {
2276 return stream.writeAll(".none");
2277 } else if (ref.toIndex()) |i| {
2278 return self.writeInstIndex(stream, i);
2279 } else {
2280 const val: InternPool.Index = @fromBackingInt(@intCast(@backingInt(ref)));
2281 return stream.print("@{s}", .{@tagName(val)});
2282 }
2283 }
2284
2285 fn writeInstIndex(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2286 _ = self;
2287 return stream.print("%{d}", .{@backingInt(inst)});
2288 }
2289
2290 fn writeCaptures(self: *Writer, stream: *std.Io.Writer, captures: []const Zir.Inst.Capture, capture_names: []const Zir.NullTerminatedString) !void {
2291 if (captures.len == 0) {
2292 assert(capture_names.len == 0);
2293 return stream.writeAll("{}");
2294 }
2295 for (captures, capture_names) |capture, name| {
2296 try stream.writeAll("{ ");
2297 if (name != .empty) {
2298 const name_slice = self.code.nullTerminatedString(name);
2299 try stream.print("{s} = ", .{name_slice});
2300 }
2301 try self.writeCapture(stream, capture);
2302 }
2303 }
2304
2305 fn writeCapture(self: *Writer, stream: *std.Io.Writer, capture: Zir.Inst.Capture) !void {
2306 switch (capture.unwrap()) {
2307 .nested => |i| return stream.print("[{d}]", .{i}),
2308 .instruction => |inst| return self.writeInstIndex(stream, inst),
2309 .instruction_load => |ptr_inst| {
2310 try stream.writeAll("load ");
2311 try self.writeInstIndex(stream, ptr_inst);
2312 },
2313 .decl_val => |str| try stream.print("decl_val \"{f}\"", .{
2314 std.zig.fmtString(self.code.nullTerminatedString(str)),
2315 }),
2316 .decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{
2317 std.zig.fmtString(self.code.nullTerminatedString(str)),
2318 }),
2319 }
2320 }
2321
2322 fn writeOptionalInstRef(
2323 self: *Writer,
2324 stream: *std.Io.Writer,
2325 prefix: []const u8,
2326 inst: Zir.Inst.Ref,
2327 ) !void {
2328 if (inst == .none) return;
2329 try stream.writeAll(prefix);
2330 try self.writeInstRef(stream, inst);
2331 }
2332
2333 fn writeOptionalInstRefOrBody(
2334 self: *Writer,
2335 stream: *std.Io.Writer,
2336 prefix: []const u8,
2337 ref: Zir.Inst.Ref,
2338 body: []const Zir.Inst.Index,
2339 ) !void {
2340 if (body.len != 0) {
2341 try stream.writeAll(prefix);
2342 try self.writeBracedBody(stream, body);
2343 try stream.writeAll(", ");
2344 } else if (ref != .none) {
2345 try stream.writeAll(prefix);
2346 try self.writeInstRef(stream, ref);
2347 try stream.writeAll(", ");
2348 }
2349 }
2350
2351 fn writeFlag(
2352 self: *Writer,
2353 stream: *std.Io.Writer,
2354 name: []const u8,
2355 flag: bool,
2356 ) !void {
2357 _ = self;
2358 if (!flag) return;
2359 try stream.writeAll(name);
2360 }
2361
2362 fn writeSrcNode(self: *Writer, stream: *std.Io.Writer, src_node: Ast.Node.Offset) !void {
2363 const tree = self.tree orelse return;
2364 const abs_node = src_node.toAbsolute(self.parent_decl_node);
2365 const src_span = tree.nodeToSpan(abs_node);
2366 const start = self.line_col_cursor.find(tree.source, src_span.start);
2367 const end = self.line_col_cursor.find(tree.source, src_span.end);
2368 try stream.print("node_offset:{d}:{d} to :{d}:{d}", .{
2369 start.line + 1, start.column + 1,
2370 end.line + 1, end.column + 1,
2371 });
2372 }
2373
2374 fn writeSrcTok(self: *Writer, stream: *std.Io.Writer, src_tok: Ast.TokenOffset) !void {
2375 const tree = self.tree orelse return;
2376 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));
2377 const span_start = tree.tokenStart(abs_tok);
2378 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len));
2379 const start = self.line_col_cursor.find(tree.source, span_start);
2380 const end = self.line_col_cursor.find(tree.source, span_end);
2381 try stream.print("token_offset:{d}:{d} to :{d}:{d}", .{
2382 start.line + 1, start.column + 1,
2383 end.line + 1, end.column + 1,
2384 });
2385 }
2386
2387 fn writeSrcTokAbs(self: *Writer, stream: *std.Io.Writer, src_tok: Ast.TokenIndex) !void {
2388 const tree = self.tree orelse return;
2389 const span_start = tree.tokenStart(src_tok);
2390 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));
2391 const start = self.line_col_cursor.find(tree.source, span_start);
2392 const end = self.line_col_cursor.find(tree.source, span_end);
2393 try stream.print("token_abs:{d}:{d} to :{d}:{d}", .{
2394 start.line + 1, start.column + 1,
2395 end.line + 1, end.column + 1,
2396 });
2397 }
2398
2399 fn writeBracedDecl(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void {
2400 try self.writeBracedBodyConditional(stream, body, self.recurse_decls);
2401 }
2402
2403 fn writeBracedBody(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void {
2404 try self.writeBracedBodyConditional(stream, body, self.recurse_blocks);
2405 }
2406
2407 fn writeBracedBodyConditional(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index, enabled: bool) !void {
2408 if (body.len == 0) {
2409 try stream.writeAll("{}");
2410 } else if (enabled) {
2411 try stream.writeAll("{\n");
2412 self.indent += 2;
2413 try self.writeBody(stream, body);
2414 self.indent -= 2;
2415 try stream.splatByteAll(' ', self.indent);
2416 try stream.writeAll("}");
2417 } else if (body.len == 1) {
2418 try stream.writeByte('{');
2419 try self.writeInstIndex(stream, body[0]);
2420 try stream.writeByte('}');
2421 } else if (body.len == 2) {
2422 try stream.writeByte('{');
2423 try self.writeInstIndex(stream, body[0]);
2424 try stream.writeAll(", ");
2425 try self.writeInstIndex(stream, body[1]);
2426 try stream.writeByte('}');
2427 } else {
2428 try stream.writeByte('{');
2429 try self.writeInstIndex(stream, body[0]);
2430 try stream.writeAll("..");
2431 try self.writeInstIndex(stream, body[body.len - 1]);
2432 try stream.writeByte('}');
2433 }
2434 }
2435
2436 fn writeBody(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void {
2437 for (body) |inst| {
2438 try stream.splatByteAll(' ', self.indent);
2439 try stream.print("%{d} ", .{@backingInt(inst)});
2440 try self.writeInstToStream(stream, inst);
2441 try stream.writeByte('\n');
2442 }
2443 }
2444
2445 fn writeImport(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2446 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_tok;
2447 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;
2448 try self.writeInstRef(stream, extra.res_ty);
2449 const import_path = self.code.nullTerminatedString(extra.path);
2450 try stream.print(", \"{f}\") ", .{std.zig.fmtString(import_path)});
2451 try self.writeSrcTok(stream, inst_data.src_tok);
2452 }
2453};