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 try stream.print(":{d}:{d} ", .{ struct_decl.src_line + 1, struct_decl.src_column + 1 });
1456
1457 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
1458 try stream.print("hash({x}) ", .{&fields_hash});
1459
1460 try stream.print("{s}, ", .{@tagName(struct_decl.name_strategy)});
1461
1462 if (struct_decl.backing_int_type_body) |backing_int_type_body| {
1463 assert(struct_decl.layout == .@"packed");
1464 try stream.writeAll("packed(");
1465 try self.writeBracedDecl(stream, backing_int_type_body);
1466 try stream.writeAll("), ");
1467 } else {
1468 try stream.print("{s}, ", .{@tagName(struct_decl.layout)});
1469 }
1470
1471 try self.writeCaptures(stream, struct_decl.captures, struct_decl.capture_names);
1472 try stream.writeAll(", ");
1473 try self.writeBracedDecl(stream, struct_decl.decls);
1474 try stream.writeAll(", ");
1475
1476 if (struct_decl.field_names.len == 0) {
1477 try stream.writeAll("{}) ");
1478 } else {
1479 try stream.writeAll("{\n");
1480 self.indent += 2;
1481
1482 var it = struct_decl.iterateFields();
1483 while (it.next()) |field| {
1484 try stream.splatByteAll(' ', self.indent);
1485 try self.writeFlag(stream, "comptime ", field.is_comptime);
1486 const field_name = self.code.nullTerminatedString(field.name);
1487 try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)});
1488
1489 self.indent += 2;
1490 try self.writeBracedDecl(stream, field.type_body);
1491 if (field.align_body) |body| {
1492 try stream.writeAll(" align(");
1493 try self.writeBracedDecl(stream, body);
1494 try stream.writeByte(')');
1495 }
1496 if (field.default_body) |body| {
1497 try stream.writeAll(" = ");
1498 try self.writeBracedDecl(stream, body);
1499 }
1500 self.indent -= 2;
1501
1502 try stream.writeAll(",\n");
1503 }
1504
1505 self.indent -= 2;
1506 try stream.splatByteAll(' ', self.indent);
1507 try stream.writeAll("}) ");
1508 }
1509 try self.writeSrcNode(stream, .zero);
1510 }
1511
1512 fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1513 const union_decl = self.code.getUnionDecl(inst);
1514
1515 const prev_parent_decl_node = self.parent_decl_node;
1516 self.parent_decl_node = union_decl.src_node;
1517 defer self.parent_decl_node = prev_parent_decl_node;
1518
1519 try stream.print(":{d}:{d} ", .{ union_decl.src_line + 1, union_decl.src_column + 1 });
1520
1521 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
1522 try stream.print("hash({x}) ", .{&fields_hash});
1523
1524 try stream.print("{s}, ", .{@tagName(union_decl.name_strategy)});
1525
1526 switch (union_decl.kind) {
1527 .auto => try stream.writeAll("auto, "),
1528 .@"extern" => try stream.writeAll("extern, "),
1529 .@"packed" => try stream.writeAll("packed, "),
1530 .packed_explicit => {
1531 try stream.writeAll("packed(");
1532 try self.writeBracedDecl(stream, union_decl.arg_type_body.?);
1533 try stream.writeAll("), ");
1534 },
1535 .tagged_explicit => {
1536 try stream.writeAll("tagged(");
1537 try self.writeBracedDecl(stream, union_decl.arg_type_body.?);
1538 try stream.writeAll("), ");
1539 },
1540 .tagged_enum => try stream.writeAll("tagged(enum), "),
1541 .tagged_enum_explicit => {
1542 try stream.writeAll("tagged(enum(");
1543 try self.writeBracedDecl(stream, union_decl.arg_type_body.?);
1544 try stream.writeAll(")), ");
1545 },
1546 }
1547
1548 try self.writeCaptures(stream, union_decl.captures, union_decl.capture_names);
1549 try stream.writeAll(", ");
1550 try self.writeBracedDecl(stream, union_decl.decls);
1551 try stream.writeAll(", ");
1552
1553 if (union_decl.field_names.len == 0) {
1554 try stream.writeAll("}) ");
1555 } else {
1556 try stream.writeAll("{\n");
1557 self.indent += 2;
1558
1559 var it = union_decl.iterateFields();
1560 while (it.next()) |field| {
1561 try stream.splatByteAll(' ', self.indent);
1562 const field_name = self.code.nullTerminatedString(field.name);
1563 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
1564
1565 self.indent += 2;
1566 if (field.type_body) |body| {
1567 try stream.writeAll(": ");
1568 try self.writeBracedDecl(stream, body);
1569 }
1570 if (field.align_body) |body| {
1571 try stream.writeAll(" align(");
1572 try self.writeBracedDecl(stream, body);
1573 try stream.writeByte(')');
1574 }
1575 if (field.value_body) |body| {
1576 try stream.writeAll(" = ");
1577 try self.writeBracedDecl(stream, body);
1578 }
1579 self.indent -= 2;
1580
1581 try stream.writeAll(",\n");
1582 }
1583 self.indent -= 2;
1584 try stream.splatByteAll(' ', self.indent);
1585 try stream.writeAll("}) ");
1586 }
1587 try self.writeSrcNode(stream, .zero);
1588 }
1589
1590 fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1591 const enum_decl = self.code.getEnumDecl(inst);
1592
1593 const prev_parent_decl_node = self.parent_decl_node;
1594 self.parent_decl_node = enum_decl.src_node;
1595 defer self.parent_decl_node = prev_parent_decl_node;
1596
1597 try stream.print(":{d}:{d} ", .{ enum_decl.src_line + 1, enum_decl.src_column + 1 });
1598
1599 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
1600 try stream.print("hash({x}) ", .{&fields_hash});
1601
1602 try stream.print("{s}, ", .{@tagName(enum_decl.name_strategy)});
1603 try self.writeFlag(stream, "nonexhaustive, ", enum_decl.nonexhaustive);
1604 if (enum_decl.tag_type_body) |tag_type_body| {
1605 try stream.writeAll("tag(");
1606 try self.writeBracedDecl(stream, tag_type_body);
1607 try stream.writeAll("), ");
1608 }
1609
1610 try self.writeCaptures(stream, enum_decl.captures, enum_decl.capture_names);
1611 try stream.writeAll(", ");
1612 try self.writeBracedDecl(stream, enum_decl.decls);
1613 try stream.writeAll(", ");
1614
1615 if (enum_decl.field_names.len == 0) {
1616 try stream.writeAll("{}) ");
1617 } else {
1618 try stream.writeAll("{\n");
1619 self.indent += 2;
1620
1621 var it = enum_decl.iterateFields();
1622 while (it.next()) |field| {
1623 try stream.splatByteAll(' ', self.indent);
1624 const field_name = self.code.nullTerminatedString(field.name);
1625 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
1626 if (field.value_body) |body| {
1627 try stream.writeAll(" = ");
1628 try self.writeBracedDecl(stream, body);
1629 }
1630 try stream.writeAll(",\n");
1631 }
1632 self.indent -= 2;
1633 try stream.splatByteAll(' ', self.indent);
1634 try stream.writeAll("}) ");
1635 }
1636 try self.writeSrcNode(stream, .zero);
1637 }
1638
1639 fn writeOpaqueDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1640 const opaque_decl = self.code.getOpaqueDecl(inst);
1641
1642 const prev_parent_decl_node = self.parent_decl_node;
1643 self.parent_decl_node = opaque_decl.src_node;
1644 defer self.parent_decl_node = prev_parent_decl_node;
1645
1646 try stream.print(":{d}:{d} ", .{ opaque_decl.src_line + 1, opaque_decl.src_column + 1 });
1647
1648 try stream.print("{s}, ", .{@tagName(opaque_decl.name_strategy)});
1649 try self.writeCaptures(stream, opaque_decl.captures, opaque_decl.capture_names);
1650 try stream.writeAll(", ");
1651 try self.writeBracedDecl(stream, opaque_decl.decls);
1652 try stream.writeAll(") ");
1653 try self.writeSrcNode(stream, .zero);
1654 }
1655
1656 fn writeTupleDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1657 const fields_len = extended.small;
1658 assert(fields_len != 0);
1659 const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand);
1660
1661 var extra_index = extra.end;
1662
1663 try stream.writeAll("{ ");
1664
1665 for (0..fields_len) |field_idx| {
1666 if (field_idx != 0) try stream.writeAll(", ");
1667
1668 const field_ty, const field_init = self.code.extra[extra_index..][0..2].*;
1669 extra_index += 2;
1670
1671 try stream.print("@\"{d}\": ", .{field_idx});
1672 try self.writeInstRef(stream, @fromBackingInt(@intCast(field_ty)));
1673 try stream.writeAll(" = ");
1674 try self.writeInstRef(stream, @fromBackingInt(@intCast(field_init)));
1675 }
1676
1677 try stream.writeAll(" }) ");
1678
1679 try self.writeSrcNode(stream, extra.data.src_node);
1680 }
1681
1682 fn writeErrorSetDecl(
1683 self: *Writer,
1684 stream: *std.Io.Writer,
1685 inst: Zir.Inst.Index,
1686 ) !void {
1687 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1688 const extra = self.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
1689
1690 try stream.writeAll("{\n");
1691 self.indent += 2;
1692
1693 var extra_index = @as(u32, @intCast(extra.end));
1694 const extra_index_end = extra_index + extra.data.fields_len;
1695 while (extra_index < extra_index_end) : (extra_index += 1) {
1696 const name_index: Zir.NullTerminatedString = @fromBackingInt(@intCast(self.code.extra[extra_index]));
1697 const name = self.code.nullTerminatedString(name_index);
1698 try stream.splatByteAll(' ', self.indent);
1699 try stream.print("{f},\n", .{std.zig.fmtIdP(name)});
1700 }
1701
1702 self.indent -= 2;
1703 try stream.splatByteAll(' ', self.indent);
1704 try stream.writeAll("}) ");
1705
1706 try self.writeSrcNode(stream, inst_data.src_node);
1707 }
1708
1709 fn writeSwitchBlock(
1710 self: *Writer,
1711 stream: *std.Io.Writer,
1712 inst: Zir.Inst.Index,
1713 ) !void {
1714 const zir_switch = self.code.getSwitchBlock(inst);
1715 var extra_index = zir_switch.end;
1716
1717 try self.writeInstRef(stream, zir_switch.main_operand);
1718
1719 self.indent += 2;
1720
1721 if (zir_switch.non_err_case) |non_err_case| {
1722 if (non_err_case.operand_is_ref) try stream.writeAll(" ref");
1723
1724 try stream.writeAll(",\n");
1725 try stream.splatByteAll(' ', self.indent);
1726
1727 try self.writeSwitchCaptures(stream, non_err_case.capture, false, inst, &zir_switch);
1728
1729 try stream.writeAll("non_err => ");
1730 try self.writeBracedBody(stream, non_err_case.body);
1731 try stream.writeAll(" ");
1732 try self.writeSrcNode(stream, zir_switch.catch_or_if_src_node_offset.unwrap().?);
1733 }
1734 if (zir_switch.else_case) |else_case| {
1735 try stream.writeAll(",\n");
1736 try stream.splatByteAll(' ', self.indent);
1737
1738 try self.writeSwitchCaptures(stream, else_case.capture, else_case.has_tag_capture, inst, &zir_switch);
1739 if (else_case.is_inline) try stream.writeAll("inline ");
1740
1741 try stream.writeAll("else => ");
1742 try self.writeBracedBody(stream, else_case.body);
1743 }
1744
1745 var case_it = zir_switch.iterateCases();
1746 while (case_it.next()) |case| {
1747 try stream.writeAll(",\n");
1748 try stream.splatByteAll(' ', self.indent);
1749
1750 const prong_info = case.prong_info;
1751 try self.writeSwitchCaptures(stream, prong_info.capture, prong_info.has_tag_capture, inst, &zir_switch);
1752 if (prong_info.is_inline) try stream.writeAll("inline ");
1753
1754 const prong_body = self.code.bodySlice(extra_index, prong_info.body_len);
1755 extra_index += prong_body.len;
1756
1757 for (case.item_infos, 0..) |item_info, i| {
1758 if (i > 0) try stream.writeAll(", ");
1759
1760 switch (item_info.unwrap()) {
1761 .enum_literal => |str_index| {
1762 const str = self.code.nullTerminatedString(str_index);
1763 try stream.print("\".{f}\"", .{std.zig.fmtString(str)});
1764 },
1765 .error_value => |str_index| {
1766 const str = self.code.nullTerminatedString(str_index);
1767 try stream.print("\"error.{f}\"", .{std.zig.fmtString(str)});
1768 },
1769 .under => try stream.writeByte('_'),
1770 .body_len => |body_len| {
1771 const item_body = self.code.bodySlice(extra_index, body_len);
1772 extra_index += item_body.len;
1773 try self.writeBracedDecl(stream, item_body);
1774 },
1775 }
1776 }
1777 for (case.range_infos, 0..) |range_info, i| {
1778 if (i > 0 and case.item_infos.len == 0) try stream.writeAll(", ");
1779 switch (range_info[0].unwrap()) {
1780 .enum_literal => |str_index| {
1781 const str = self.code.nullTerminatedString(str_index);
1782 try stream.print("\".{f}\"", .{std.zig.fmtString(str)});
1783 },
1784 .error_value => |str_index| {
1785 const str = self.code.nullTerminatedString(str_index);
1786 try stream.print("\"error.{f}\"", .{std.zig.fmtString(str)});
1787 },
1788 .under => unreachable, // '_..._' is not allowed
1789 .body_len => |body_len| {
1790 const item_body = self.code.bodySlice(extra_index, body_len);
1791 extra_index += item_body.len;
1792 try self.writeBracedDecl(stream, item_body);
1793 },
1794 }
1795 try stream.writeAll("...");
1796 switch (range_info[1].unwrap()) {
1797 .enum_literal => |str_index| {
1798 const str = self.code.nullTerminatedString(str_index);
1799 try stream.print("\".{f}\"", .{std.zig.fmtString(str)});
1800 },
1801 .error_value => |str_index| {
1802 const str = self.code.nullTerminatedString(str_index);
1803 try stream.print("\"error.{f}\"", .{std.zig.fmtString(str)});
1804 },
1805 .under => unreachable, // '_..._' is not allowed
1806 .body_len => |body_len| {
1807 const item_body = self.code.bodySlice(extra_index, body_len);
1808 extra_index += item_body.len;
1809 try self.writeBracedDecl(stream, item_body);
1810 },
1811 }
1812 }
1813 try stream.writeAll(" => ");
1814 try self.writeBracedBody(stream, prong_body);
1815 }
1816
1817 self.indent -= 2;
1818
1819 try stream.writeAll(") ");
1820 try self.writeSrcNode(stream, zir_switch.switch_src_node_offset);
1821 }
1822
1823 fn writeSwitchCaptures(
1824 self: *Writer,
1825 stream: *std.Io.Writer,
1826 capture: Zir.Inst.SwitchBlock.ProngInfo.Capture,
1827 has_tag_capture: bool,
1828 switch_inst: Zir.Inst.Index,
1829 zir_switch: *const Zir.UnwrappedSwitchBlock,
1830 ) !void {
1831 if (capture != .none) {
1832 try stream.print("{t}=", .{capture});
1833 const capture_inst = zir_switch.payload_capture_placeholder.unwrap() orelse switch_inst;
1834 try self.writeInstIndex(stream, capture_inst);
1835 try stream.writeAll(" ");
1836 }
1837 if (has_tag_capture) {
1838 try stream.writeAll("tag=");
1839 const capture_inst = zir_switch.tag_capture_placeholder.unwrap() orelse switch_inst;
1840 try self.writeInstIndex(stream, capture_inst);
1841 try stream.writeAll(" ");
1842 }
1843 }
1844
1845 fn writePlNodeField(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1846 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1847 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
1848 const name = self.code.nullTerminatedString(extra.field_name_start);
1849 try self.writeInstRef(stream, extra.lhs);
1850 try stream.print(", \"{f}\") ", .{std.zig.fmtString(name)});
1851 try self.writeSrcNode(stream, inst_data.src_node);
1852 }
1853
1854 fn writePlNodeFieldNamed(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1855 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1856 const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
1857 try self.writeInstRef(stream, extra.lhs);
1858 try stream.writeAll(", ");
1859 try self.writeInstRef(stream, extra.field_name);
1860 try stream.writeAll(") ");
1861 try self.writeSrcNode(stream, inst_data.src_node);
1862 }
1863
1864 fn writeAs(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1865 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1866 const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data;
1867 try self.writeInstRef(stream, extra.dest_type);
1868 try stream.writeAll(", ");
1869 try self.writeInstRef(stream, extra.operand);
1870 try stream.writeAll(") ");
1871 try self.writeSrcNode(stream, inst_data.src_node);
1872 }
1873
1874 fn writeNode(
1875 self: *Writer,
1876 stream: *std.Io.Writer,
1877 inst: Zir.Inst.Index,
1878 ) Error!void {
1879 const src_node = self.code.instructions.items(.data)[@backingInt(inst)].node;
1880 try stream.writeAll(") ");
1881 try self.writeSrcNode(stream, src_node);
1882 }
1883
1884 fn writeStrTok(
1885 self: *Writer,
1886 stream: *std.Io.Writer,
1887 inst: Zir.Inst.Index,
1888 ) Error!void {
1889 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].str_tok;
1890 const str = inst_data.get(self.code);
1891 try stream.print("\"{f}\") ", .{std.zig.fmtString(str)});
1892 try self.writeSrcTok(stream, inst_data.src_tok);
1893 }
1894
1895 fn writeStrOp(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1896 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].str_op;
1897 const str = inst_data.getStr(self.code);
1898 try self.writeInstRef(stream, inst_data.operand);
1899 try stream.print(", \"{f}\")", .{std.zig.fmtString(str)});
1900 }
1901
1902 fn writeFunc(
1903 self: *Writer,
1904 stream: *std.Io.Writer,
1905 inst: Zir.Inst.Index,
1906 inferred_error_set: bool,
1907 ) !void {
1908 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1909 const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index);
1910
1911 var extra_index = extra.end;
1912 var ret_ty_ref: Zir.Inst.Ref = .none;
1913 var ret_ty_body: []const Zir.Inst.Index = &.{};
1914
1915 switch (extra.data.ret_ty.body_len) {
1916 0 => {
1917 ret_ty_ref = .void_type;
1918 },
1919 1 => {
1920 ret_ty_ref = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
1921 extra_index += 1;
1922 },
1923 else => {
1924 ret_ty_body = self.code.bodySlice(extra_index, extra.data.ret_ty.body_len);
1925 extra_index += ret_ty_body.len;
1926 },
1927 }
1928
1929 const body = self.code.bodySlice(extra_index, extra.data.body_len);
1930 extra_index += body.len;
1931
1932 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
1933 if (body.len != 0) {
1934 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
1935 }
1936 return self.writeFuncCommon(
1937 stream,
1938 inferred_error_set,
1939 false,
1940 false,
1941
1942 .none,
1943 &.{},
1944 ret_ty_ref,
1945 ret_ty_body,
1946 extra.data.ret_ty.is_generic,
1947
1948 body,
1949 inst_data.src_node,
1950 src_locs,
1951 0,
1952 );
1953 }
1954
1955 fn writeFuncFancy(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1956 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
1957 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
1958
1959 var extra_index: usize = extra.end;
1960 var cc_ref: Zir.Inst.Ref = .none;
1961 var cc_body: []const Zir.Inst.Index = &.{};
1962 var ret_ty_ref: Zir.Inst.Ref = .none;
1963 var ret_ty_body: []const Zir.Inst.Index = &.{};
1964
1965 if (extra.data.bits.has_cc_body) {
1966 const body_len = self.code.extra[extra_index];
1967 extra_index += 1;
1968 cc_body = self.code.bodySlice(extra_index, body_len);
1969 extra_index += cc_body.len;
1970 } else if (extra.data.bits.has_cc_ref) {
1971 cc_ref = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
1972 extra_index += 1;
1973 }
1974 if (extra.data.bits.has_ret_ty_body) {
1975 const body_len = self.code.extra[extra_index];
1976 extra_index += 1;
1977 ret_ty_body = self.code.bodySlice(extra_index, body_len);
1978 extra_index += ret_ty_body.len;
1979 } else if (extra.data.bits.has_ret_ty_ref) {
1980 ret_ty_ref = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
1981 extra_index += 1;
1982 }
1983
1984 const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {
1985 const x = self.code.extra[extra_index];
1986 extra_index += 1;
1987 break :blk x;
1988 } else 0;
1989
1990 const body = self.code.bodySlice(extra_index, extra.data.body_len);
1991 extra_index += body.len;
1992
1993 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
1994 if (body.len != 0) {
1995 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
1996 }
1997 return self.writeFuncCommon(
1998 stream,
1999 extra.data.bits.is_inferred_error,
2000 extra.data.bits.is_var_args,
2001 extra.data.bits.is_noinline,
2002 cc_ref,
2003 cc_body,
2004 ret_ty_ref,
2005 ret_ty_body,
2006 extra.data.bits.ret_ty_is_generic,
2007 body,
2008 inst_data.src_node,
2009 src_locs,
2010 noalias_bits,
2011 );
2012 }
2013
2014 fn writeAllocExtended(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2015 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
2016 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));
2017
2018 var extra_index: usize = extra.end;
2019 const type_inst: Zir.Inst.Ref = if (!small.has_type) .none else blk: {
2020 const type_inst = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
2021 extra_index += 1;
2022 break :blk type_inst;
2023 };
2024 const align_inst: Zir.Inst.Ref = if (!small.has_align) .none else blk: {
2025 const align_inst = @as(Zir.Inst.Ref, @fromBackingInt(@intCast(self.code.extra[extra_index])));
2026 extra_index += 1;
2027 break :blk align_inst;
2028 };
2029 try self.writeFlag(stream, ",is_const", small.is_const);
2030 try self.writeFlag(stream, ",is_comptime", small.is_comptime);
2031 try self.writeOptionalInstRef(stream, ",ty=", type_inst);
2032 try self.writeOptionalInstRef(stream, ",align=", align_inst);
2033 try stream.writeAll(")) ");
2034 try self.writeSrcNode(stream, extra.data.src_node);
2035 }
2036
2037 fn writeTypeofPeer(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2038 const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);
2039 const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len);
2040 try self.writeBracedBody(stream, body);
2041 try stream.writeAll(",[");
2042 const args = self.code.refSlice(extra.end, extended.small);
2043 for (args, 0..) |arg, i| {
2044 if (i != 0) try stream.writeAll(", ");
2045 try self.writeInstRef(stream, arg);
2046 }
2047 try stream.writeAll("])");
2048 }
2049
2050 fn writeBoolBr(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2051 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
2052 const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);
2053 const body = self.code.bodySlice(extra.end, extra.data.body_len);
2054 try self.writeInstRef(stream, extra.data.lhs);
2055 try stream.writeAll(", ");
2056 try self.writeBracedBody(stream, body);
2057 try stream.writeAll(") ");
2058 try self.writeSrcNode(stream, inst_data.src_node);
2059 }
2060
2061 fn writeIntType(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2062 const int_type = self.code.instructions.items(.data)[@backingInt(inst)].int_type;
2063 const prefix: u8 = switch (int_type.signedness) {
2064 .signed => 'i',
2065 .unsigned => 'u',
2066 };
2067 try stream.print("{c}{d}) ", .{ prefix, int_type.bit_count });
2068 try self.writeSrcNode(stream, int_type.src_node);
2069 }
2070
2071 fn writeSaveErrRetIndex(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2072 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].save_err_ret_index;
2073
2074 try self.writeInstRef(stream, inst_data.operand);
2075
2076 try stream.writeAll(")");
2077 }
2078
2079 fn writeRestoreErrRetIndex(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2080 const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;
2081
2082 try self.writeInstRef(stream, extra.block);
2083 try self.writeInstRef(stream, extra.operand);
2084
2085 try stream.writeAll(") ");
2086 try self.writeSrcNode(stream, extra.src_node);
2087 }
2088
2089 fn writeBreak(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2090 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].@"break";
2091 const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;
2092
2093 try self.writeInstIndex(stream, extra.block_inst);
2094 try stream.writeAll(", ");
2095 try self.writeInstRef(stream, inst_data.operand);
2096 try stream.writeAll(")");
2097 }
2098
2099 fn writeArrayInit(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2100 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
2101
2102 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
2103 const args = self.code.refSlice(extra.end, extra.data.operands_len);
2104
2105 try self.writeInstRef(stream, args[0]);
2106 try stream.writeAll("{");
2107 for (args[1..], 0..) |arg, i| {
2108 if (i != 0) try stream.writeAll(", ");
2109 try self.writeInstRef(stream, arg);
2110 }
2111 try stream.writeAll("}) ");
2112 try self.writeSrcNode(stream, inst_data.src_node);
2113 }
2114
2115 fn writeArrayInitAnon(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2116 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
2117
2118 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
2119 const args = self.code.refSlice(extra.end, extra.data.operands_len);
2120
2121 try stream.writeAll("{");
2122 for (args, 0..) |arg, i| {
2123 if (i != 0) try stream.writeAll(", ");
2124 try self.writeInstRef(stream, arg);
2125 }
2126 try stream.writeAll("}) ");
2127 try self.writeSrcNode(stream, inst_data.src_node);
2128 }
2129
2130 fn writeArrayInitSent(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2131 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_node;
2132
2133 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
2134 const args = self.code.refSlice(extra.end, extra.data.operands_len);
2135 const sent = args[args.len - 1];
2136 const elems = args[0 .. args.len - 1];
2137
2138 try self.writeInstRef(stream, sent);
2139 try stream.writeAll(", ");
2140
2141 try stream.writeAll(".{");
2142 for (elems, 0..) |elem, i| {
2143 if (i != 0) try stream.writeAll(", ");
2144 try self.writeInstRef(stream, elem);
2145 }
2146 try stream.writeAll("}) ");
2147 try self.writeSrcNode(stream, inst_data.src_node);
2148 }
2149
2150 fn writeUnreachable(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2151 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].@"unreachable";
2152 try stream.writeAll(") ");
2153 try self.writeSrcNode(stream, inst_data.src_node);
2154 }
2155
2156 fn writeFuncCommon(
2157 self: *Writer,
2158 stream: *std.Io.Writer,
2159 inferred_error_set: bool,
2160 var_args: bool,
2161 is_noinline: bool,
2162 cc_ref: Zir.Inst.Ref,
2163 cc_body: []const Zir.Inst.Index,
2164 ret_ty_ref: Zir.Inst.Ref,
2165 ret_ty_body: []const Zir.Inst.Index,
2166 ret_ty_is_generic: bool,
2167 body: []const Zir.Inst.Index,
2168 src_node: Ast.Node.Offset,
2169 src_locs: Zir.Inst.Func.SrcLocs,
2170 noalias_bits: u32,
2171 ) !void {
2172 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
2173 if (ret_ty_is_generic) try stream.writeAll("[generic] ");
2174 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
2175 try self.writeFlag(stream, "vargs, ", var_args);
2176 try self.writeFlag(stream, "inferror, ", inferred_error_set);
2177 try self.writeFlag(stream, "noinline, ", is_noinline);
2178
2179 if (noalias_bits != 0) {
2180 try stream.print("noalias=0b{b}, ", .{noalias_bits});
2181 }
2182
2183 try stream.writeAll("body=");
2184 try self.writeBracedBody(stream, body);
2185 try stream.writeAll(") ");
2186 if (body.len != 0) {
2187 try stream.print("(lbrace={d}:{d},rbrace={d}:{d}) ", .{
2188 src_locs.lbrace_line + 1, @as(u16, @truncate(src_locs.columns)) + 1,
2189 src_locs.rbrace_line + 1, @as(u16, @truncate(src_locs.columns >> 16)) + 1,
2190 });
2191 }
2192 try self.writeSrcNode(stream, src_node);
2193 }
2194
2195 fn writeDbgStmt(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2196 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].dbg_stmt;
2197 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });
2198 }
2199
2200 fn writeDefer(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2201 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].@"defer";
2202 const body = self.code.bodySlice(inst_data.index, inst_data.len);
2203 try self.writeBracedBody(stream, body);
2204 try stream.writeByte(')');
2205 }
2206
2207 fn writeDeclaration(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2208 const decl = self.code.getDeclaration(inst);
2209
2210 const prev_parent_decl_node = self.parent_decl_node;
2211 defer self.parent_decl_node = prev_parent_decl_node;
2212 self.parent_decl_node = decl.src_node;
2213
2214 if (decl.is_pub) try stream.writeAll("pub ");
2215 switch (decl.linkage) {
2216 .normal => {},
2217 .@"export" => try stream.writeAll("export "),
2218 .@"extern" => try stream.writeAll("extern "),
2219 }
2220 switch (decl.kind) {
2221 .@"comptime" => try stream.writeAll("comptime"),
2222 .unnamed_test => try stream.writeAll("test"),
2223 .@"test", .decltest, .@"const", .@"var" => {
2224 try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) });
2225 },
2226 }
2227 try stream.print(":{d}:{d}", .{ decl.src_line + 1, decl.src_column + 1 });
2228
2229 const src_hash = self.code.getAssociatedSrcHash(inst).?;
2230 try stream.print(" hash({x})", .{&src_hash});
2231
2232 {
2233 if (decl.type_body) |b| {
2234 try stream.writeAll(" type=");
2235 try self.writeBracedDecl(stream, b);
2236 }
2237
2238 if (decl.align_body) |b| {
2239 try stream.writeAll(" align=");
2240 try self.writeBracedDecl(stream, b);
2241 }
2242
2243 if (decl.linksection_body) |b| {
2244 try stream.writeAll(" linksection=");
2245 try self.writeBracedDecl(stream, b);
2246 }
2247
2248 if (decl.addrspace_body) |b| {
2249 try stream.writeAll(" addrspace=");
2250 try self.writeBracedDecl(stream, b);
2251 }
2252
2253 if (decl.value_body) |b| {
2254 try stream.writeAll(" value=");
2255 try self.writeBracedDecl(stream, b);
2256 }
2257 }
2258
2259 try stream.writeAll(") ");
2260 try self.writeSrcNode(stream, .zero);
2261 }
2262
2263 fn writeClosureGet(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2264 try stream.print("{d})) ", .{extended.small});
2265 const src_node: Ast.Node.Offset = @fromBackingInt(@intCast(@as(i32, @bitCast(extended.operand))));
2266 try self.writeSrcNode(stream, src_node);
2267 }
2268
2269 fn writeStdLangValue(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2270 const val: Zir.Inst.StdLangValue = @fromBackingInt(@intCast(extended.small));
2271 try stream.print("{s})) ", .{@tagName(val)});
2272 const src_node: Ast.Node.Offset = @fromBackingInt(@intCast(@as(i32, @bitCast(extended.operand))));
2273 try self.writeSrcNode(stream, src_node);
2274 }
2275
2276 fn writeInplaceArithResultTy(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
2277 const op: Zir.Inst.InplaceOp = @fromBackingInt(@intCast(extended.small));
2278 try self.writeInstRef(stream, @fromBackingInt(@intCast(extended.operand)));
2279 try stream.print(", {s}))", .{@tagName(op)});
2280 }
2281
2282 fn writeInstRef(self: *Writer, stream: *std.Io.Writer, ref: Zir.Inst.Ref) !void {
2283 if (ref == .none) {
2284 return stream.writeAll(".none");
2285 } else if (ref.toIndex()) |i| {
2286 return self.writeInstIndex(stream, i);
2287 } else {
2288 const val: InternPool.Index = @fromBackingInt(@intCast(@backingInt(ref)));
2289 return stream.print("@{s}", .{@tagName(val)});
2290 }
2291 }
2292
2293 fn writeInstIndex(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2294 _ = self;
2295 return stream.print("%{d}", .{@backingInt(inst)});
2296 }
2297
2298 fn writeCaptures(self: *Writer, stream: *std.Io.Writer, captures: []const Zir.Inst.Capture, capture_names: []const Zir.NullTerminatedString) !void {
2299 if (captures.len == 0) {
2300 assert(capture_names.len == 0);
2301 return stream.writeAll("{}");
2302 }
2303 for (captures, capture_names) |capture, name| {
2304 try stream.writeAll("{ ");
2305 if (name != .empty) {
2306 const name_slice = self.code.nullTerminatedString(name);
2307 try stream.print("{s} = ", .{name_slice});
2308 }
2309 try self.writeCapture(stream, capture);
2310 }
2311 }
2312
2313 fn writeCapture(self: *Writer, stream: *std.Io.Writer, capture: Zir.Inst.Capture) !void {
2314 switch (capture.unwrap()) {
2315 .nested => |i| return stream.print("[{d}]", .{i}),
2316 .instruction => |inst| return self.writeInstIndex(stream, inst),
2317 .instruction_load => |ptr_inst| {
2318 try stream.writeAll("load ");
2319 try self.writeInstIndex(stream, ptr_inst);
2320 },
2321 .decl_val => |str| try stream.print("decl_val \"{f}\"", .{
2322 std.zig.fmtString(self.code.nullTerminatedString(str)),
2323 }),
2324 .decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{
2325 std.zig.fmtString(self.code.nullTerminatedString(str)),
2326 }),
2327 }
2328 }
2329
2330 fn writeOptionalInstRef(
2331 self: *Writer,
2332 stream: *std.Io.Writer,
2333 prefix: []const u8,
2334 inst: Zir.Inst.Ref,
2335 ) !void {
2336 if (inst == .none) return;
2337 try stream.writeAll(prefix);
2338 try self.writeInstRef(stream, inst);
2339 }
2340
2341 fn writeOptionalInstRefOrBody(
2342 self: *Writer,
2343 stream: *std.Io.Writer,
2344 prefix: []const u8,
2345 ref: Zir.Inst.Ref,
2346 body: []const Zir.Inst.Index,
2347 ) !void {
2348 if (body.len != 0) {
2349 try stream.writeAll(prefix);
2350 try self.writeBracedBody(stream, body);
2351 try stream.writeAll(", ");
2352 } else if (ref != .none) {
2353 try stream.writeAll(prefix);
2354 try self.writeInstRef(stream, ref);
2355 try stream.writeAll(", ");
2356 }
2357 }
2358
2359 fn writeFlag(
2360 self: *Writer,
2361 stream: *std.Io.Writer,
2362 name: []const u8,
2363 flag: bool,
2364 ) !void {
2365 _ = self;
2366 if (!flag) return;
2367 try stream.writeAll(name);
2368 }
2369
2370 fn writeSrcNode(self: *Writer, stream: *std.Io.Writer, src_node: Ast.Node.Offset) !void {
2371 const tree = self.tree orelse return;
2372 const abs_node = src_node.toAbsolute(self.parent_decl_node);
2373 const src_span = tree.nodeToSpan(abs_node);
2374 const start = self.line_col_cursor.find(tree.source, src_span.start);
2375 const end = self.line_col_cursor.find(tree.source, src_span.end);
2376 try stream.print("node_offset:{d}:{d} to :{d}:{d}", .{
2377 start.line + 1, start.column + 1,
2378 end.line + 1, end.column + 1,
2379 });
2380 }
2381
2382 fn writeSrcTok(self: *Writer, stream: *std.Io.Writer, src_tok: Ast.TokenOffset) !void {
2383 const tree = self.tree orelse return;
2384 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));
2385 const span_start = tree.tokenStart(abs_tok);
2386 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len));
2387 const start = self.line_col_cursor.find(tree.source, span_start);
2388 const end = self.line_col_cursor.find(tree.source, span_end);
2389 try stream.print("token_offset:{d}:{d} to :{d}:{d}", .{
2390 start.line + 1, start.column + 1,
2391 end.line + 1, end.column + 1,
2392 });
2393 }
2394
2395 fn writeSrcTokAbs(self: *Writer, stream: *std.Io.Writer, src_tok: Ast.TokenIndex) !void {
2396 const tree = self.tree orelse return;
2397 const span_start = tree.tokenStart(src_tok);
2398 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));
2399 const start = self.line_col_cursor.find(tree.source, span_start);
2400 const end = self.line_col_cursor.find(tree.source, span_end);
2401 try stream.print("token_abs:{d}:{d} to :{d}:{d}", .{
2402 start.line + 1, start.column + 1,
2403 end.line + 1, end.column + 1,
2404 });
2405 }
2406
2407 fn writeBracedDecl(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void {
2408 try self.writeBracedBodyConditional(stream, body, self.recurse_decls);
2409 }
2410
2411 fn writeBracedBody(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void {
2412 try self.writeBracedBodyConditional(stream, body, self.recurse_blocks);
2413 }
2414
2415 fn writeBracedBodyConditional(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index, enabled: bool) !void {
2416 if (body.len == 0) {
2417 try stream.writeAll("{}");
2418 } else if (enabled) {
2419 try stream.writeAll("{\n");
2420 self.indent += 2;
2421 try self.writeBody(stream, body);
2422 self.indent -= 2;
2423 try stream.splatByteAll(' ', self.indent);
2424 try stream.writeAll("}");
2425 } else if (body.len == 1) {
2426 try stream.writeByte('{');
2427 try self.writeInstIndex(stream, body[0]);
2428 try stream.writeByte('}');
2429 } else if (body.len == 2) {
2430 try stream.writeByte('{');
2431 try self.writeInstIndex(stream, body[0]);
2432 try stream.writeAll(", ");
2433 try self.writeInstIndex(stream, body[1]);
2434 try stream.writeByte('}');
2435 } else {
2436 try stream.writeByte('{');
2437 try self.writeInstIndex(stream, body[0]);
2438 try stream.writeAll("..");
2439 try self.writeInstIndex(stream, body[body.len - 1]);
2440 try stream.writeByte('}');
2441 }
2442 }
2443
2444 fn writeBody(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void {
2445 for (body) |inst| {
2446 try stream.splatByteAll(' ', self.indent);
2447 try stream.print("%{d} ", .{@backingInt(inst)});
2448 try self.writeInstToStream(stream, inst);
2449 try stream.writeByte('\n');
2450 }
2451 }
2452
2453 fn writeImport(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2454 const inst_data = self.code.instructions.items(.data)[@backingInt(inst)].pl_tok;
2455 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;
2456 try self.writeInstRef(stream, extra.res_ty);
2457 const import_path = self.code.nullTerminatedString(extra.path);
2458 try stream.print(", \"{f}\") ", .{std.zig.fmtString(import_path)});
2459 try self.writeSrcTok(stream, inst_data.src_tok);
2460 }
2461};