src/print_zir.zig (120739B) - Raw
1 const std = @import("std"); 2 const mem = std.mem; 3 const Allocator = std.mem.Allocator; 4 const assert = std.debug.assert; 5 const Ast = std.zig.Ast; 6 const InternPool = @import("InternPool.zig"); 7 8 const Zir = std.zig.Zir; 9 const Zcu = @import("Zcu.zig"); 10 const LazySrcLoc = Zcu.LazySrcLoc; 11 12 /// Write human-readable, debug formatted ZIR code. 13 pub 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} ", .{@intFromEnum(main_struct_inst)}); 30 try writer.writeInstToStream(bw, main_struct_inst); 31 try bw.writeAll("\n"); 32 const imports_index = zir.extra[@intFromEnum(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 53 pub 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} ", .{@intFromEnum(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 86 pub 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} ", .{@intFromEnum(inst)}); 109 try writer.writeInstToStream(bw, inst); 110 } 111 112 const 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[@intFromEnum(inst)]; 188 try stream.print("= {s}(", .{@tagName(tags[@intFromEnum(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 .indexable_ptr_len, 197 .anyframe_type, 198 .bit_not, 199 .bool_not, 200 .slice_sentinel_ty, 201 .negate, 202 .negate_wrap, 203 .load, 204 .ensure_result_used, 205 .ensure_result_non_error, 206 .ensure_err_union_payload_void, 207 .ret_node, 208 .ret_load, 209 .resolve_inferred_alloc, 210 .optional_type, 211 .optional_payload_safe, 212 .optional_payload_unsafe, 213 .optional_payload_safe_ptr, 214 .optional_payload_unsafe_ptr, 215 .err_union_payload_unsafe, 216 .err_union_payload_unsafe_ptr, 217 .err_union_code, 218 .err_union_code_ptr, 219 .is_non_null, 220 .is_non_null_ptr, 221 .is_non_err, 222 .is_non_err_ptr, 223 .ret_is_non_err, 224 .typeof, 225 .type_info, 226 .size_of, 227 .bit_size_of, 228 .typeof_log2_int_type, 229 .int_from_ptr, 230 .compile_error, 231 .set_eval_branch_quota, 232 .int_from_enum, 233 .align_of, 234 .int_from_bool, 235 .embed_file, 236 .error_name, 237 .panic, 238 .set_runtime_safety, 239 .sqrt, 240 .sin, 241 .cos, 242 .tan, 243 .exp, 244 .exp2, 245 .log, 246 .log2, 247 .log10, 248 .abs, 249 .floor, 250 .ceil, 251 .trunc, 252 .round, 253 .tag_name, 254 .type_name, 255 .frame_type, 256 .clz, 257 .ctz, 258 .pop_count, 259 .byte_swap, 260 .bit_reverse, 261 .@"resume", 262 .make_ptr_const, 263 .validate_deref, 264 .validate_const, 265 .check_comptime_control_flow, 266 .opt_eu_base_ptr_init, 267 .restore_err_ret_index_unconditional, 268 .restore_err_ret_index_fn_entry, 269 => try self.writeUnNode(stream, inst), 270 271 .ref, 272 .ret_implicit, 273 .validate_ref_ty, 274 => try self.writeUnTok(stream, inst), 275 276 .bool_br_and, 277 .bool_br_or, 278 => try self.writeBoolBr(stream, inst), 279 280 .validate_destructure => try self.writeValidateDestructure(stream, inst), 281 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst), 282 .ptr_type => try self.writePtrType(stream, inst), 283 .int => try self.writeInt(stream, inst), 284 .int_big => try self.writeIntBig(stream, inst), 285 .float => try self.writeFloat(stream, inst), 286 .float128 => try self.writeFloat128(stream, inst), 287 .str => try self.writeStr(stream, inst), 288 .int_type => try self.writeIntType(stream, inst), 289 290 .save_err_ret_index => try self.writeSaveErrRetIndex(stream, inst), 291 292 .@"break", 293 .break_inline, 294 .switch_continue, 295 => try self.writeBreak(stream, inst), 296 297 .slice_start => try self.writeSliceStart(stream, inst), 298 .slice_end => try self.writeSliceEnd(stream, inst), 299 .slice_sentinel => try self.writeSliceSentinel(stream, inst), 300 .slice_length => try self.writeSliceLength(stream, inst), 301 302 .union_init => try self.writeUnionInit(stream, inst), 303 304 // Struct inits 305 306 .struct_init_empty, 307 .struct_init_empty_result, 308 .struct_init_empty_ref_result, 309 => try self.writeUnNode(stream, inst), 310 311 .struct_init_anon => try self.writeStructInitAnon(stream, inst), 312 313 .struct_init, 314 .struct_init_ref, 315 => try self.writeStructInit(stream, inst), 316 317 .validate_struct_init_ty, 318 .validate_struct_init_result_ty, 319 => try self.writeUnNode(stream, inst), 320 321 .validate_ptr_struct_init => try self.writeBlock(stream, inst), 322 .struct_init_field_type => try self.writeStructInitFieldType(stream, inst), 323 .struct_init_field_ptr => try self.writePlNodeField(stream, inst), 324 325 // Array inits 326 327 .array_init_anon => try self.writeArrayInitAnon(stream, inst), 328 329 .array_init, 330 .array_init_ref, 331 => try self.writeArrayInit(stream, inst), 332 333 .validate_array_init_ty, 334 .validate_array_init_result_ty, 335 => try self.writeValidateArrayInitTy(stream, inst), 336 337 .validate_array_init_ref_ty => try self.writeValidateArrayInitRefTy(stream, inst), 338 .validate_ptr_array_init => try self.writeBlock(stream, inst), 339 .array_init_elem_type => try self.writeArrayInitElemType(stream, inst), 340 .array_init_elem_ptr => try self.writeArrayInitElemPtr(stream, inst), 341 342 .atomic_load => try self.writeAtomicLoad(stream, inst), 343 .atomic_store => try self.writeAtomicStore(stream, inst), 344 .atomic_rmw => try self.writeAtomicRmw(stream, inst), 345 .shuffle => try self.writeShuffle(stream, inst), 346 .mul_add => try self.writeMulAdd(stream, inst), 347 .builtin_call => try self.writeBuiltinCall(stream, inst), 348 349 .field_type_ref => try self.writeFieldTypeRef(stream, inst), 350 351 .add, 352 .addwrap, 353 .add_sat, 354 .add_unsafe, 355 .array_cat, 356 .mul, 357 .mulwrap, 358 .mul_sat, 359 .sub, 360 .subwrap, 361 .sub_sat, 362 .cmp_lt, 363 .cmp_lte, 364 .cmp_eq, 365 .cmp_gte, 366 .cmp_gt, 367 .cmp_neq, 368 .div, 369 .has_decl, 370 .has_field, 371 .mod_rem, 372 .shl, 373 .shl_exact, 374 .shl_sat, 375 .shr, 376 .shr_exact, 377 .xor, 378 .store_node, 379 .store_to_inferred_ptr, 380 .error_union_type, 381 .merge_error_sets, 382 .bit_and, 383 .bit_or, 384 .int_from_float, 385 .float_from_int, 386 .ptr_from_int, 387 .enum_from_int, 388 .float_cast, 389 .int_cast, 390 .ptr_cast, 391 .truncate, 392 .div_exact, 393 .div_floor, 394 .div_trunc, 395 .mod, 396 .rem, 397 .bit_offset_of, 398 .offset_of, 399 .splat, 400 .reduce, 401 .bitcast, 402 .reify_int, 403 .vector_type, 404 .max, 405 .min, 406 .memcpy, 407 .memset, 408 .memmove, 409 .elem_ptr_node, 410 .elem_ptr_load, 411 .elem_ptr, 412 .elem_val, 413 .array_type, 414 .coerce_ptr_elem_ty, 415 => try self.writePlNodeBin(stream, inst), 416 417 .for_len => try self.writePlNodeMultiOp(stream, inst), 418 419 .array_mul => try self.writeArrayMul(stream, inst), 420 421 .elem_val_imm => try self.writeElemValImm(stream, inst), 422 423 .@"export" => try self.writePlNodeExport(stream, inst), 424 425 .call => try self.writeCall(stream, inst, .direct), 426 .field_call => try self.writeCall(stream, inst, .field), 427 428 .block, 429 .block_inline, 430 .suspend_block, 431 .loop, 432 .c_import, 433 .typeof_builtin, 434 => try self.writeBlock(stream, inst), 435 436 .block_comptime => try self.writeBlockComptime(stream, inst), 437 438 .condbr, 439 .condbr_inline, 440 => try self.writeCondBr(stream, inst), 441 442 .@"try", 443 .try_ptr, 444 => try self.writeTry(stream, inst), 445 446 .error_set_decl => try self.writeErrorSetDecl(stream, inst), 447 448 .switch_block, 449 .switch_block_ref, 450 => try self.writeSwitchBlock(stream, inst), 451 452 .switch_block_err_union => try self.writeSwitchBlockErrUnion(stream, inst), 453 454 .field_ptr_load, 455 .field_ptr, 456 .decl_literal, 457 .decl_literal_no_coerce, 458 => try self.writePlNodeField(stream, inst), 459 460 .field_ptr_named, 461 .field_ptr_named_load, 462 => try self.writePlNodeFieldNamed(stream, inst), 463 464 .as_node, .as_shift_operand => try self.writeAs(stream, inst), 465 466 .repeat, 467 .repeat_inline, 468 .alloc_inferred, 469 .alloc_inferred_mut, 470 .alloc_inferred_comptime, 471 .alloc_inferred_comptime_mut, 472 .ret_ptr, 473 .ret_type, 474 .trap, 475 => try self.writeNode(stream, inst), 476 477 .error_value, 478 .enum_literal, 479 .decl_ref, 480 .decl_val, 481 .ret_err_value, 482 .ret_err_value_code, 483 .param_anytype, 484 .param_anytype_comptime, 485 => try self.writeStrTok(stream, inst), 486 487 .dbg_var_ptr, 488 .dbg_var_val, 489 => try self.writeStrOp(stream, inst), 490 491 .param, .param_comptime => try self.writeParam(stream, inst), 492 493 .func => try self.writeFunc(stream, inst, false), 494 .func_inferred => try self.writeFunc(stream, inst, true), 495 .func_fancy => try self.writeFuncFancy(stream, inst), 496 497 .@"unreachable" => try self.writeUnreachable(stream, inst), 498 499 .dbg_stmt => try self.writeDbgStmt(stream, inst), 500 501 .@"defer" => try self.writeDefer(stream, inst), 502 .defer_err_code => try self.writeDeferErrCode(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)[@intFromEnum(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, extended), 553 .union_decl => try self.writeUnionDecl(stream, extended), 554 .enum_decl => try self.writeEnumDecl(stream, extended), 555 .opaque_decl => try self.writeOpaqueDecl(stream, extended), 556 557 .tuple_decl => try self.writeTupleDecl(stream, extended), 558 559 .c_undef, 560 .c_include, 561 .set_float_mode, 562 .wasm_memory_size, 563 .int_from_error, 564 .error_from_int, 565 .c_va_copy, 566 .c_va_end, 567 .work_item_id, 568 .work_group_size, 569 .work_group_id, 570 .branch_hint, 571 .float_op_result_ty, 572 .reify_tuple, 573 .reify_pointer_sentinel_ty, 574 => { 575 const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; 576 try self.writeInstRef(stream, inst_data.operand); 577 try stream.writeAll(")) "); 578 try self.writeSrcNode(stream, inst_data.node); 579 }, 580 581 .builtin_extern, 582 .c_define, 583 .error_cast, 584 .wasm_memory_grow, 585 .prefetch, 586 .c_va_arg, 587 .reify_enum_value_slice_ty, 588 => { 589 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; 590 try self.writeInstRef(stream, inst_data.lhs); 591 try stream.writeAll(", "); 592 try self.writeInstRef(stream, inst_data.rhs); 593 try stream.writeAll(")) "); 594 try self.writeSrcNode(stream, inst_data.node); 595 }, 596 597 .reify_slice_arg_ty => { 598 const reify_slice_arg_info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.operand); 599 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; 600 try stream.print("{t}, ", .{reify_slice_arg_info}); 601 try self.writeInstRef(stream, extra.operand); 602 try stream.writeAll(")) "); 603 try self.writeSrcNode(stream, extra.node); 604 }, 605 606 .reify_pointer => { 607 const extra = self.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data; 608 try self.writeInstRef(stream, extra.size); 609 try stream.writeAll(", "); 610 try self.writeInstRef(stream, extra.attrs); 611 try stream.writeAll(", "); 612 try self.writeInstRef(stream, extra.elem_ty); 613 try stream.writeAll(", "); 614 try self.writeInstRef(stream, extra.sentinel); 615 try stream.writeAll(")) "); 616 try self.writeSrcNode(stream, extra.node); 617 }, 618 .reify_fn => { 619 const extra = self.code.extraData(Zir.Inst.ReifyFn, extended.operand).data; 620 try self.writeInstRef(stream, extra.param_types); 621 try stream.writeAll(", "); 622 try self.writeInstRef(stream, extra.param_attrs); 623 try stream.writeAll(", "); 624 try self.writeInstRef(stream, extra.ret_ty); 625 try stream.writeAll(", "); 626 try self.writeInstRef(stream, extra.fn_attrs); 627 try stream.writeAll(")) "); 628 try self.writeSrcNode(stream, extra.node); 629 }, 630 .reify_struct => { 631 const extra = self.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data; 632 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small); 633 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat }); 634 try self.writeInstRef(stream, extra.layout); 635 try stream.writeAll(", "); 636 try self.writeInstRef(stream, extra.backing_ty); 637 try stream.writeAll(", "); 638 try self.writeInstRef(stream, extra.field_names); 639 try stream.writeAll(", "); 640 try self.writeInstRef(stream, extra.field_types); 641 try stream.writeAll(", "); 642 try self.writeInstRef(stream, extra.field_attrs); 643 try stream.writeAll(")) "); 644 const prev_parent_decl_node = self.parent_decl_node; 645 self.parent_decl_node = extra.node; 646 defer self.parent_decl_node = prev_parent_decl_node; 647 try self.writeSrcNode(stream, .zero); 648 }, 649 .reify_union => { 650 const extra = self.code.extraData(Zir.Inst.ReifyUnion, extended.operand).data; 651 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small); 652 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat }); 653 try self.writeInstRef(stream, extra.layout); 654 try stream.writeAll(", "); 655 try self.writeInstRef(stream, extra.arg_ty); 656 try stream.writeAll(", "); 657 try self.writeInstRef(stream, extra.field_names); 658 try stream.writeAll(", "); 659 try self.writeInstRef(stream, extra.field_types); 660 try stream.writeAll(", "); 661 try self.writeInstRef(stream, extra.field_attrs); 662 try stream.writeAll(")) "); 663 const prev_parent_decl_node = self.parent_decl_node; 664 self.parent_decl_node = extra.node; 665 defer self.parent_decl_node = prev_parent_decl_node; 666 try self.writeSrcNode(stream, .zero); 667 }, 668 .reify_enum => { 669 const extra = self.code.extraData(Zir.Inst.ReifyEnum, extended.operand).data; 670 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small); 671 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat }); 672 try self.writeInstRef(stream, extra.tag_ty); 673 try stream.writeAll(", "); 674 try self.writeInstRef(stream, extra.mode); 675 try stream.writeAll(", "); 676 try self.writeInstRef(stream, extra.field_names); 677 try stream.writeAll(", "); 678 try self.writeInstRef(stream, extra.field_values); 679 try stream.writeAll(")) "); 680 const prev_parent_decl_node = self.parent_decl_node; 681 self.parent_decl_node = extra.node; 682 defer self.parent_decl_node = prev_parent_decl_node; 683 try self.writeSrcNode(stream, .zero); 684 }, 685 686 .cmpxchg => try self.writeCmpxchg(stream, extended), 687 .ptr_cast_full => try self.writePtrCastFull(stream, extended), 688 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended), 689 690 .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended), 691 .closure_get => try self.writeClosureGet(stream, extended), 692 .field_parent_ptr => try self.writeFieldParentPtr(stream, extended), 693 .builtin_value => try self.writeBuiltinValue(stream, extended), 694 .inplace_arith_result_ty => try self.writeInplaceArithResultTy(stream, extended), 695 696 .dbg_empty_stmt => try stream.writeAll("))"), 697 .astgen_error => try stream.writeAll("))"), 698 } 699 } 700 701 fn writeExtNode(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 702 try stream.writeAll(")) "); 703 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); 704 try self.writeSrcNode(stream, src_node); 705 } 706 707 fn writeArrayInitElemType(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 708 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin; 709 try self.writeInstRef(stream, inst_data.lhs); 710 try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)}); 711 } 712 713 fn writeUnNode( 714 self: *Writer, 715 stream: *std.Io.Writer, 716 inst: Zir.Inst.Index, 717 ) Error!void { 718 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_node; 719 try self.writeInstRef(stream, inst_data.operand); 720 try stream.writeAll(") "); 721 try self.writeSrcNode(stream, inst_data.src_node); 722 } 723 724 fn writeUnTok( 725 self: *Writer, 726 stream: *std.Io.Writer, 727 inst: Zir.Inst.Index, 728 ) Error!void { 729 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; 730 try self.writeInstRef(stream, inst_data.operand); 731 try stream.writeAll(") "); 732 try self.writeSrcTok(stream, inst_data.src_tok); 733 } 734 735 fn writeValidateDestructure( 736 self: *Writer, 737 stream: *std.Io.Writer, 738 inst: Zir.Inst.Index, 739 ) Error!void { 740 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 741 const extra = self.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data; 742 try self.writeInstRef(stream, extra.operand); 743 try stream.print(", {d}) (destructure=", .{extra.expect_len}); 744 try self.writeSrcNode(stream, extra.destructure_node); 745 try stream.writeAll(") "); 746 try self.writeSrcNode(stream, inst_data.src_node); 747 } 748 749 fn writeValidateArrayInitTy( 750 self: *Writer, 751 stream: *std.Io.Writer, 752 inst: Zir.Inst.Index, 753 ) Error!void { 754 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 755 const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; 756 try self.writeInstRef(stream, extra.ty); 757 try stream.print(", {d}) ", .{extra.init_count}); 758 try self.writeSrcNode(stream, inst_data.src_node); 759 } 760 761 fn writeArrayTypeSentinel( 762 self: *Writer, 763 stream: *std.Io.Writer, 764 inst: Zir.Inst.Index, 765 ) Error!void { 766 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 767 const extra = self.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data; 768 try self.writeInstRef(stream, extra.len); 769 try stream.writeAll(", "); 770 try self.writeInstRef(stream, extra.sentinel); 771 try stream.writeAll(", "); 772 try self.writeInstRef(stream, extra.elem_type); 773 try stream.writeAll(") "); 774 try self.writeSrcNode(stream, inst_data.src_node); 775 } 776 777 fn writePtrType( 778 self: *Writer, 779 stream: *std.Io.Writer, 780 inst: Zir.Inst.Index, 781 ) Error!void { 782 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type; 783 const str_allowzero = if (inst_data.flags.is_allowzero) "allowzero, " else ""; 784 const str_const = if (!inst_data.flags.is_mutable) "const, " else ""; 785 const str_volatile = if (inst_data.flags.is_volatile) "volatile, " else ""; 786 const extra = self.code.extraData(Zir.Inst.PtrType, inst_data.payload_index); 787 try self.writeInstRef(stream, extra.data.elem_type); 788 try stream.print(", {s}{s}{s}{s}", .{ 789 str_allowzero, 790 str_const, 791 str_volatile, 792 @tagName(inst_data.size), 793 }); 794 var extra_index = extra.end; 795 if (inst_data.flags.has_sentinel) { 796 try stream.writeAll(", "); 797 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]))); 798 extra_index += 1; 799 } 800 if (inst_data.flags.has_align) { 801 try stream.writeAll(", align("); 802 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]))); 803 extra_index += 1; 804 if (inst_data.flags.has_bit_range) { 805 const bit_start = extra_index + @intFromBool(inst_data.flags.has_addrspace); 806 try stream.writeAll(":"); 807 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[bit_start]))); 808 try stream.writeAll(":"); 809 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[bit_start + 1]))); 810 } 811 try stream.writeAll(")"); 812 } 813 if (inst_data.flags.has_addrspace) { 814 try stream.writeAll(", addrspace("); 815 try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]))); 816 try stream.writeAll(")"); 817 } 818 try stream.writeAll(") "); 819 try self.writeSrcNode(stream, extra.data.src_node); 820 } 821 822 fn writeInt(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 823 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].int; 824 try stream.print("{d})", .{inst_data}); 825 } 826 827 fn writeIntBig(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 828 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str; 829 const byte_count = inst_data.len * @sizeOf(std.math.big.Limb); 830 const limb_bytes = self.code.string_bytes[@intFromEnum(inst_data.start)..][0..byte_count]; 831 // limb_bytes is not aligned properly; we must allocate and copy the bytes 832 // in order to accomplish this. 833 const limbs = try self.gpa.alloc(std.math.big.Limb, inst_data.len); 834 defer self.gpa.free(limbs); 835 836 @memcpy(mem.sliceAsBytes(limbs), limb_bytes); 837 const big_int: std.math.big.int.Const = .{ 838 .limbs = limbs, 839 .positive = true, 840 }; 841 const as_string = try big_int.toStringAlloc(self.gpa, 10, .lower); 842 defer self.gpa.free(as_string); 843 try stream.print("{s})", .{as_string}); 844 } 845 846 fn writeFloat(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 847 const number = self.code.instructions.items(.data)[@intFromEnum(inst)].float; 848 try stream.print("{d})", .{number}); 849 } 850 851 fn writeFloat128(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 852 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 853 const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data; 854 const number = extra.get(); 855 // TODO improve std.format to be able to print f128 values 856 try stream.print("{d}) ", .{@as(f64, @floatCast(number))}); 857 try self.writeSrcNode(stream, inst_data.src_node); 858 } 859 860 fn writeStr( 861 self: *Writer, 862 stream: *std.Io.Writer, 863 inst: Zir.Inst.Index, 864 ) Error!void { 865 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str; 866 const str = inst_data.get(self.code); 867 try stream.print("\"{f}\")", .{std.zig.fmtString(str)}); 868 } 869 870 fn writeSliceStart(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 871 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 872 const extra = self.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data; 873 try self.writeInstRef(stream, extra.lhs); 874 try stream.writeAll(", "); 875 try self.writeInstRef(stream, extra.start); 876 try stream.writeAll(") "); 877 try self.writeSrcNode(stream, inst_data.src_node); 878 } 879 880 fn writeSliceEnd(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 881 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 882 const extra = self.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data; 883 try self.writeInstRef(stream, extra.lhs); 884 try stream.writeAll(", "); 885 try self.writeInstRef(stream, extra.start); 886 try stream.writeAll(", "); 887 try self.writeInstRef(stream, extra.end); 888 try stream.writeAll(") "); 889 try self.writeSrcNode(stream, inst_data.src_node); 890 } 891 892 fn writeSliceSentinel(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 893 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 894 const extra = self.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data; 895 try self.writeInstRef(stream, extra.lhs); 896 try stream.writeAll(", "); 897 try self.writeInstRef(stream, extra.start); 898 try stream.writeAll(", "); 899 try self.writeInstRef(stream, extra.end); 900 try stream.writeAll(", "); 901 try self.writeInstRef(stream, extra.sentinel); 902 try stream.writeAll(") "); 903 try self.writeSrcNode(stream, inst_data.src_node); 904 } 905 906 fn writeSliceLength(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 907 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 908 const extra = self.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data; 909 try self.writeInstRef(stream, extra.lhs); 910 try stream.writeAll(", "); 911 try self.writeInstRef(stream, extra.start); 912 try stream.writeAll(", "); 913 try self.writeInstRef(stream, extra.len); 914 if (extra.sentinel != .none) { 915 try stream.writeAll(", "); 916 try self.writeInstRef(stream, extra.sentinel); 917 } 918 try stream.writeAll(") "); 919 try self.writeSrcNode(stream, inst_data.src_node); 920 } 921 922 fn writeUnionInit(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 923 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 924 const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; 925 try self.writeInstRef(stream, extra.union_type); 926 try stream.writeAll(", "); 927 try self.writeInstRef(stream, extra.field_name); 928 try stream.writeAll(", "); 929 try self.writeInstRef(stream, extra.init); 930 try stream.writeAll(") "); 931 try self.writeSrcNode(stream, inst_data.src_node); 932 } 933 934 fn writeShuffle(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 935 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 936 const extra = self.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data; 937 try self.writeInstRef(stream, extra.elem_type); 938 try stream.writeAll(", "); 939 try self.writeInstRef(stream, extra.a); 940 try stream.writeAll(", "); 941 try self.writeInstRef(stream, extra.b); 942 try stream.writeAll(", "); 943 try self.writeInstRef(stream, extra.mask); 944 try stream.writeAll(") "); 945 try self.writeSrcNode(stream, inst_data.src_node); 946 } 947 948 fn writeSelect(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 949 const extra = self.code.extraData(Zir.Inst.Select, extended.operand).data; 950 try self.writeInstRef(stream, extra.elem_type); 951 try stream.writeAll(", "); 952 try self.writeInstRef(stream, extra.pred); 953 try stream.writeAll(", "); 954 try self.writeInstRef(stream, extra.a); 955 try stream.writeAll(", "); 956 try self.writeInstRef(stream, extra.b); 957 try stream.writeAll(") "); 958 try self.writeSrcNode(stream, extra.node); 959 } 960 961 fn writeMulAdd(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 962 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 963 const extra = self.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data; 964 try self.writeInstRef(stream, extra.mulend1); 965 try stream.writeAll(", "); 966 try self.writeInstRef(stream, extra.mulend2); 967 try stream.writeAll(", "); 968 try self.writeInstRef(stream, extra.addend); 969 try stream.writeAll(") "); 970 try self.writeSrcNode(stream, inst_data.src_node); 971 } 972 973 fn writeBuiltinCall(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 974 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 975 const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data; 976 977 try self.writeFlag(stream, "nodiscard ", extra.flags.ensure_result_used); 978 try self.writeFlag(stream, "nosuspend ", extra.flags.is_nosuspend); 979 980 try self.writeInstRef(stream, extra.modifier); 981 try stream.writeAll(", "); 982 try self.writeInstRef(stream, extra.callee); 983 try stream.writeAll(", "); 984 try self.writeInstRef(stream, extra.args); 985 try stream.writeAll(") "); 986 try self.writeSrcNode(stream, inst_data.src_node); 987 } 988 989 fn writeFieldParentPtr(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 990 const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data; 991 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?; 992 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); 993 if (flags.align_cast) try stream.writeAll("align_cast, "); 994 if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, "); 995 if (flags.const_cast) try stream.writeAll("const_cast, "); 996 if (flags.volatile_cast) try stream.writeAll("volatile_cast, "); 997 try self.writeInstRef(stream, extra.parent_ptr_type); 998 try stream.writeAll(", "); 999 try self.writeInstRef(stream, extra.field_name); 1000 try stream.writeAll(", "); 1001 try self.writeInstRef(stream, extra.field_ptr); 1002 try stream.writeAll(") "); 1003 try self.writeSrcNode(stream, extra.src_node); 1004 } 1005 1006 fn writeParam(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1007 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok; 1008 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index); 1009 const body = self.code.bodySlice(extra.end, extra.data.type.body_len); 1010 try stream.print("\"{f}\", ", .{ 1011 std.zig.fmtString(self.code.nullTerminatedString(extra.data.name)), 1012 }); 1013 1014 if (extra.data.type.is_generic) try stream.writeAll("[generic] "); 1015 1016 try self.writeBracedBody(stream, body); 1017 try stream.writeAll(") "); 1018 try self.writeSrcTok(stream, inst_data.src_tok); 1019 } 1020 1021 fn writePlNodeBin(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1022 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1023 const extra = self.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 1024 try self.writeInstRef(stream, extra.lhs); 1025 try stream.writeAll(", "); 1026 try self.writeInstRef(stream, extra.rhs); 1027 try stream.writeAll(") "); 1028 try self.writeSrcNode(stream, inst_data.src_node); 1029 } 1030 1031 fn writePlNodeMultiOp(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1032 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1033 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); 1034 const args = self.code.refSlice(extra.end, extra.data.operands_len); 1035 try stream.writeAll("{"); 1036 for (args, 0..) |arg, i| { 1037 if (i != 0) try stream.writeAll(", "); 1038 try self.writeInstRef(stream, arg); 1039 } 1040 try stream.writeAll("}) "); 1041 try self.writeSrcNode(stream, inst_data.src_node); 1042 } 1043 1044 fn writeArrayMul(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1045 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1046 const extra = self.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data; 1047 try self.writeInstRef(stream, extra.res_ty); 1048 try stream.writeAll(", "); 1049 try self.writeInstRef(stream, extra.lhs); 1050 try stream.writeAll(", "); 1051 try self.writeInstRef(stream, extra.rhs); 1052 try stream.writeAll(") "); 1053 try self.writeSrcNode(stream, inst_data.src_node); 1054 } 1055 1056 fn writeElemValImm(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1057 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm; 1058 try self.writeInstRef(stream, inst_data.operand); 1059 try stream.print(", {d})", .{inst_data.idx}); 1060 } 1061 1062 fn writeArrayInitElemPtr(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1063 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1064 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data; 1065 1066 try self.writeInstRef(stream, extra.ptr); 1067 try stream.print(", {d}) ", .{extra.index}); 1068 try self.writeSrcNode(stream, inst_data.src_node); 1069 } 1070 1071 fn writePlNodeExport(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1072 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1073 const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data; 1074 1075 try self.writeInstRef(stream, extra.exported); 1076 try stream.writeAll(", "); 1077 try self.writeInstRef(stream, extra.options); 1078 try stream.writeAll(") "); 1079 try self.writeSrcNode(stream, inst_data.src_node); 1080 } 1081 1082 fn writeValidateArrayInitRefTy(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1083 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1084 const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data; 1085 1086 try self.writeInstRef(stream, extra.ptr_ty); 1087 try stream.writeAll(", "); 1088 try stream.print(", {}) ", .{extra.elem_count}); 1089 try self.writeSrcNode(stream, inst_data.src_node); 1090 } 1091 1092 fn writeStructInit(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1093 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1094 const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); 1095 var field_i: u32 = 0; 1096 var extra_index = extra.end; 1097 1098 while (field_i < extra.data.fields_len) : (field_i += 1) { 1099 const item = self.code.extraData(Zir.Inst.StructInit.Item, extra_index); 1100 extra_index = item.end; 1101 1102 if (field_i != 0) { 1103 try stream.writeAll(", ["); 1104 } else { 1105 try stream.writeAll("["); 1106 } 1107 try self.writeInstIndex(stream, item.data.field_type); 1108 try stream.writeAll(", "); 1109 try self.writeInstRef(stream, item.data.init); 1110 try stream.writeAll("]"); 1111 } 1112 try stream.writeAll(") "); 1113 try self.writeSrcNode(stream, inst_data.src_node); 1114 } 1115 1116 fn writeCmpxchg(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1117 const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data; 1118 1119 try self.writeInstRef(stream, extra.ptr); 1120 try stream.writeAll(", "); 1121 try self.writeInstRef(stream, extra.expected_value); 1122 try stream.writeAll(", "); 1123 try self.writeInstRef(stream, extra.new_value); 1124 try stream.writeAll(", "); 1125 try self.writeInstRef(stream, extra.success_order); 1126 try stream.writeAll(", "); 1127 try self.writeInstRef(stream, extra.failure_order); 1128 try stream.writeAll(") "); 1129 try self.writeSrcNode(stream, extra.node); 1130 } 1131 1132 fn writePtrCastFull(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1133 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?; 1134 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); 1135 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; 1136 if (flags.ptr_cast) try stream.writeAll("ptr_cast, "); 1137 if (flags.align_cast) try stream.writeAll("align_cast, "); 1138 if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, "); 1139 if (flags.const_cast) try stream.writeAll("const_cast, "); 1140 if (flags.volatile_cast) try stream.writeAll("volatile_cast, "); 1141 try self.writeInstRef(stream, extra.lhs); 1142 try stream.writeAll(", "); 1143 try self.writeInstRef(stream, extra.rhs); 1144 try stream.writeAll(")) "); 1145 try self.writeSrcNode(stream, extra.node); 1146 } 1147 1148 fn writePtrCastNoDest(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1149 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?; 1150 const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small))); 1151 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; 1152 if (flags.const_cast) try stream.writeAll("const_cast, "); 1153 if (flags.volatile_cast) try stream.writeAll("volatile_cast, "); 1154 try self.writeInstRef(stream, extra.operand); 1155 try stream.writeAll(")) "); 1156 try self.writeSrcNode(stream, extra.node); 1157 } 1158 1159 fn writeAtomicLoad(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1160 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1161 const extra = self.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data; 1162 1163 try self.writeInstRef(stream, extra.elem_type); 1164 try stream.writeAll(", "); 1165 try self.writeInstRef(stream, extra.ptr); 1166 try stream.writeAll(", "); 1167 try self.writeInstRef(stream, extra.ordering); 1168 try stream.writeAll(") "); 1169 try self.writeSrcNode(stream, inst_data.src_node); 1170 } 1171 1172 fn writeAtomicStore(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1173 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1174 const extra = self.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data; 1175 1176 try self.writeInstRef(stream, extra.ptr); 1177 try stream.writeAll(", "); 1178 try self.writeInstRef(stream, extra.operand); 1179 try stream.writeAll(", "); 1180 try self.writeInstRef(stream, extra.ordering); 1181 try stream.writeAll(") "); 1182 try self.writeSrcNode(stream, inst_data.src_node); 1183 } 1184 1185 fn writeAtomicRmw(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1186 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1187 const extra = self.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data; 1188 1189 try self.writeInstRef(stream, extra.ptr); 1190 try stream.writeAll(", "); 1191 try self.writeInstRef(stream, extra.operation); 1192 try stream.writeAll(", "); 1193 try self.writeInstRef(stream, extra.operand); 1194 try stream.writeAll(", "); 1195 try self.writeInstRef(stream, extra.ordering); 1196 try stream.writeAll(") "); 1197 try self.writeSrcNode(stream, inst_data.src_node); 1198 } 1199 1200 fn writeStructInitAnon(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1201 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1202 const extra = self.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index); 1203 var field_i: u32 = 0; 1204 var extra_index = extra.end; 1205 1206 while (field_i < extra.data.fields_len) : (field_i += 1) { 1207 const item = self.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index); 1208 extra_index = item.end; 1209 1210 const field_name = self.code.nullTerminatedString(item.data.field_name); 1211 1212 const prefix = if (field_i != 0) ", [" else "["; 1213 try stream.print("{s}{s}=", .{ prefix, field_name }); 1214 try self.writeInstRef(stream, item.data.init); 1215 try stream.writeAll("]"); 1216 } 1217 try stream.writeAll(") "); 1218 try self.writeSrcNode(stream, inst_data.src_node); 1219 } 1220 1221 fn writeStructInitFieldType(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1222 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1223 const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; 1224 try self.writeInstRef(stream, extra.container_type); 1225 const field_name = self.code.nullTerminatedString(extra.name_start); 1226 try stream.print(", {s}) ", .{field_name}); 1227 try self.writeSrcNode(stream, inst_data.src_node); 1228 } 1229 1230 fn writeFieldTypeRef(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1231 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1232 const extra = self.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data; 1233 try self.writeInstRef(stream, extra.container_type); 1234 try stream.writeAll(", "); 1235 try self.writeInstRef(stream, extra.field_name); 1236 try stream.writeAll(") "); 1237 try self.writeSrcNode(stream, inst_data.src_node); 1238 } 1239 1240 fn writeNodeMultiOp(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1241 const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); 1242 const operands = self.code.refSlice(extra.end, extended.small); 1243 1244 for (operands, 0..) |operand, i| { 1245 if (i != 0) try stream.writeAll(", "); 1246 try self.writeInstRef(stream, operand); 1247 } 1248 try stream.writeAll(")) "); 1249 try self.writeSrcNode(stream, extra.data.src_node); 1250 } 1251 1252 fn writeInstNode( 1253 self: *Writer, 1254 stream: *std.Io.Writer, 1255 inst: Zir.Inst.Index, 1256 ) Error!void { 1257 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].inst_node; 1258 try self.writeInstIndex(stream, inst_data.inst); 1259 try stream.writeAll(") "); 1260 try self.writeSrcNode(stream, inst_data.src_node); 1261 } 1262 1263 fn writeAsm( 1264 self: *Writer, 1265 stream: *std.Io.Writer, 1266 extended: Zir.Inst.Extended.InstData, 1267 tmpl_is_expr: bool, 1268 ) !void { 1269 const extra = self.code.extraData(Zir.Inst.Asm, extended.operand); 1270 const outputs_len = @as(u5, @truncate(extended.small)); 1271 const inputs_len = @as(u5, @truncate(extended.small >> 5)); 1272 const clobbers_len = @as(u5, @truncate(extended.small >> 10)); 1273 const is_volatile = @as(u1, @truncate(extended.small >> 15)) != 0; 1274 1275 try self.writeFlag(stream, "volatile, ", is_volatile); 1276 if (tmpl_is_expr) { 1277 try self.writeInstRef(stream, @enumFromInt(@intFromEnum(extra.data.asm_source))); 1278 try stream.writeAll(", "); 1279 } else { 1280 const asm_source = self.code.nullTerminatedString(extra.data.asm_source); 1281 try stream.print("\"{f}\", ", .{std.zig.fmtString(asm_source)}); 1282 } 1283 try stream.writeAll(", "); 1284 1285 var extra_i: usize = extra.end; 1286 var output_type_bits = extra.data.output_type_bits; 1287 { 1288 var i: usize = 0; 1289 while (i < outputs_len) : (i += 1) { 1290 const output = self.code.extraData(Zir.Inst.Asm.Output, extra_i); 1291 extra_i = output.end; 1292 1293 const is_type = @as(u1, @truncate(output_type_bits)) != 0; 1294 output_type_bits >>= 1; 1295 1296 const name = self.code.nullTerminatedString(output.data.name); 1297 const constraint = self.code.nullTerminatedString(output.data.constraint); 1298 try stream.print("output({f}, \"{f}\", ", .{ 1299 std.zig.fmtIdP(name), std.zig.fmtString(constraint), 1300 }); 1301 try self.writeFlag(stream, "->", is_type); 1302 try self.writeInstRef(stream, output.data.operand); 1303 try stream.writeAll(")"); 1304 if (i + 1 < outputs_len) { 1305 try stream.writeAll("), "); 1306 } 1307 } 1308 } 1309 { 1310 var i: usize = 0; 1311 while (i < inputs_len) : (i += 1) { 1312 const input = self.code.extraData(Zir.Inst.Asm.Input, extra_i); 1313 extra_i = input.end; 1314 1315 const name = self.code.nullTerminatedString(input.data.name); 1316 const constraint = self.code.nullTerminatedString(input.data.constraint); 1317 try stream.print("input({f}, \"{f}\", ", .{ 1318 std.zig.fmtIdP(name), std.zig.fmtString(constraint), 1319 }); 1320 try self.writeInstRef(stream, input.data.operand); 1321 try stream.writeAll(")"); 1322 if (i + 1 < inputs_len) { 1323 try stream.writeAll(", "); 1324 } 1325 } 1326 } 1327 { 1328 var i: usize = 0; 1329 while (i < clobbers_len) : (i += 1) { 1330 const str_index = self.code.extra[extra_i]; 1331 extra_i += 1; 1332 const clobber = self.code.nullTerminatedString(@enumFromInt(str_index)); 1333 try stream.print("{f}", .{std.zig.fmtIdP(clobber)}); 1334 if (i + 1 < clobbers_len) { 1335 try stream.writeAll(", "); 1336 } 1337 } 1338 } 1339 try stream.writeAll(")) "); 1340 try self.writeSrcNode(stream, extra.data.src_node); 1341 } 1342 1343 fn writeOverflowArithmetic(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1344 const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; 1345 1346 try self.writeInstRef(stream, extra.lhs); 1347 try stream.writeAll(", "); 1348 try self.writeInstRef(stream, extra.rhs); 1349 try stream.writeAll(")) "); 1350 try self.writeSrcNode(stream, extra.node); 1351 } 1352 1353 fn writeCall( 1354 self: *Writer, 1355 stream: *std.Io.Writer, 1356 inst: Zir.Inst.Index, 1357 comptime kind: enum { direct, field }, 1358 ) !void { 1359 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1360 const ExtraType = switch (kind) { 1361 .direct => Zir.Inst.Call, 1362 .field => Zir.Inst.FieldCall, 1363 }; 1364 const extra = self.code.extraData(ExtraType, inst_data.payload_index); 1365 const args_len = extra.data.flags.args_len; 1366 const body = self.code.extra[extra.end..]; 1367 1368 if (extra.data.flags.ensure_result_used) { 1369 try stream.writeAll("nodiscard "); 1370 } 1371 try stream.print(".{s}, ", .{@tagName(@as(std.builtin.CallModifier, @enumFromInt(extra.data.flags.packed_modifier)))}); 1372 switch (kind) { 1373 .direct => try self.writeInstRef(stream, extra.data.callee), 1374 .field => { 1375 const field_name = self.code.nullTerminatedString(extra.data.field_name_start); 1376 try self.writeInstRef(stream, extra.data.obj_ptr); 1377 try stream.print(", \"{f}\"", .{std.zig.fmtString(field_name)}); 1378 }, 1379 } 1380 try stream.writeAll(", ["); 1381 1382 self.indent += 2; 1383 if (args_len != 0) { 1384 try stream.writeAll("\n"); 1385 } 1386 var i: usize = 0; 1387 var arg_start: u32 = args_len; 1388 while (i < args_len) : (i += 1) { 1389 try stream.splatByteAll(' ', self.indent); 1390 const arg_end = self.code.extra[extra.end + i]; 1391 defer arg_start = arg_end; 1392 const arg_body = body[arg_start..arg_end]; 1393 try self.writeBracedBody(stream, @ptrCast(arg_body)); 1394 1395 try stream.writeAll(",\n"); 1396 } 1397 self.indent -= 2; 1398 if (args_len != 0) { 1399 try stream.splatByteAll(' ', self.indent); 1400 } 1401 1402 try stream.writeAll("]) "); 1403 try self.writeSrcNode(stream, inst_data.src_node); 1404 } 1405 1406 fn writeBlock(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1407 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1408 const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index); 1409 const body = self.code.bodySlice(extra.end, extra.data.body_len); 1410 try self.writeBracedBody(stream, body); 1411 try stream.writeAll(") "); 1412 try self.writeSrcNode(stream, inst_data.src_node); 1413 } 1414 1415 fn writeBlockComptime(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1416 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1417 const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index); 1418 const body = self.code.bodySlice(extra.end, extra.data.body_len); 1419 try stream.print("reason={s}, ", .{@tagName(extra.data.reason)}); 1420 try self.writeBracedBody(stream, body); 1421 try stream.writeAll(") "); 1422 try self.writeSrcNode(stream, inst_data.src_node); 1423 } 1424 1425 fn writeCondBr(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1426 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1427 const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); 1428 const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len); 1429 const else_body = self.code.bodySlice(extra.end + then_body.len, extra.data.else_body_len); 1430 try self.writeInstRef(stream, extra.data.condition); 1431 try stream.writeAll(", "); 1432 try self.writeBracedBody(stream, then_body); 1433 try stream.writeAll(", "); 1434 try self.writeBracedBody(stream, else_body); 1435 try stream.writeAll(") "); 1436 try self.writeSrcNode(stream, inst_data.src_node); 1437 } 1438 1439 fn writeTry(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 1440 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1441 const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index); 1442 const body = self.code.bodySlice(extra.end, extra.data.body_len); 1443 try self.writeInstRef(stream, extra.data.operand); 1444 try stream.writeAll(", "); 1445 try self.writeBracedBody(stream, body); 1446 try stream.writeAll(") "); 1447 try self.writeSrcNode(stream, inst_data.src_node); 1448 } 1449 1450 fn writeStructDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1451 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); 1452 1453 const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand); 1454 1455 const prev_parent_decl_node = self.parent_decl_node; 1456 self.parent_decl_node = extra.data.src_node; 1457 defer self.parent_decl_node = prev_parent_decl_node; 1458 1459 const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ 1460 extra.data.fields_hash_0, 1461 extra.data.fields_hash_1, 1462 extra.data.fields_hash_2, 1463 extra.data.fields_hash_3, 1464 }); 1465 1466 try stream.print("hash({x}) ", .{&fields_hash}); 1467 1468 var extra_index: usize = extra.end; 1469 1470 const captures_len = if (small.has_captures_len) blk: { 1471 const captures_len = self.code.extra[extra_index]; 1472 extra_index += 1; 1473 break :blk captures_len; 1474 } else 0; 1475 1476 const fields_len = if (small.has_fields_len) blk: { 1477 const fields_len = self.code.extra[extra_index]; 1478 extra_index += 1; 1479 break :blk fields_len; 1480 } else 0; 1481 1482 const decls_len = if (small.has_decls_len) blk: { 1483 const decls_len = self.code.extra[extra_index]; 1484 extra_index += 1; 1485 break :blk decls_len; 1486 } else 0; 1487 1488 try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv); 1489 try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only); 1490 1491 try stream.print("{s}, ", .{@tagName(small.name_strategy)}); 1492 1493 extra_index = try self.writeCaptures(stream, extra_index, captures_len); 1494 try stream.writeAll(", "); 1495 1496 if (small.has_backing_int) { 1497 const backing_int_body_len = self.code.extra[extra_index]; 1498 extra_index += 1; 1499 try stream.writeAll("packed("); 1500 if (backing_int_body_len == 0) { 1501 const backing_int_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); 1502 extra_index += 1; 1503 try self.writeInstRef(stream, backing_int_ref); 1504 } else { 1505 const body = self.code.bodySlice(extra_index, backing_int_body_len); 1506 extra_index += backing_int_body_len; 1507 self.indent += 2; 1508 try self.writeBracedDecl(stream, body); 1509 self.indent -= 2; 1510 } 1511 try stream.writeAll("), "); 1512 } else { 1513 try stream.print("{s}, ", .{@tagName(small.layout)}); 1514 } 1515 1516 if (decls_len == 0) { 1517 try stream.writeAll("{}, "); 1518 } else { 1519 try stream.writeAll("{\n"); 1520 self.indent += 2; 1521 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); 1522 self.indent -= 2; 1523 extra_index += decls_len; 1524 try stream.splatByteAll(' ', self.indent); 1525 try stream.writeAll("}, "); 1526 } 1527 1528 if (fields_len == 0) { 1529 try stream.writeAll("{}, {}) "); 1530 } else { 1531 const bits_per_field = 4; 1532 const fields_per_u32 = 32 / bits_per_field; 1533 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; 1534 const Field = struct { 1535 type_len: u32 = 0, 1536 align_len: u32 = 0, 1537 init_len: u32 = 0, 1538 type: Zir.Inst.Ref = .none, 1539 name: Zir.NullTerminatedString, 1540 is_comptime: bool, 1541 }; 1542 const fields = try self.arena.alloc(Field, fields_len); 1543 { 1544 var bit_bag_index: usize = extra_index; 1545 extra_index += bit_bags_count; 1546 var cur_bit_bag: u32 = undefined; 1547 var field_i: u32 = 0; 1548 while (field_i < fields_len) : (field_i += 1) { 1549 if (field_i % fields_per_u32 == 0) { 1550 cur_bit_bag = self.code.extra[bit_bag_index]; 1551 bit_bag_index += 1; 1552 } 1553 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; 1554 cur_bit_bag >>= 1; 1555 const has_default = @as(u1, @truncate(cur_bit_bag)) != 0; 1556 cur_bit_bag >>= 1; 1557 const is_comptime = @as(u1, @truncate(cur_bit_bag)) != 0; 1558 cur_bit_bag >>= 1; 1559 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; 1560 cur_bit_bag >>= 1; 1561 1562 const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]); 1563 extra_index += 1; 1564 1565 fields[field_i] = .{ 1566 .is_comptime = is_comptime, 1567 .name = field_name_index, 1568 }; 1569 1570 if (has_type_body) { 1571 fields[field_i].type_len = self.code.extra[extra_index]; 1572 } else { 1573 fields[field_i].type = @enumFromInt(self.code.extra[extra_index]); 1574 } 1575 extra_index += 1; 1576 1577 if (has_align) { 1578 fields[field_i].align_len = self.code.extra[extra_index]; 1579 extra_index += 1; 1580 } 1581 1582 if (has_default) { 1583 fields[field_i].init_len = self.code.extra[extra_index]; 1584 extra_index += 1; 1585 } 1586 } 1587 } 1588 1589 try stream.writeAll("{\n"); 1590 self.indent += 2; 1591 1592 for (fields, 0..) |field, i| { 1593 try stream.splatByteAll(' ', self.indent); 1594 try self.writeFlag(stream, "comptime ", field.is_comptime); 1595 if (field.name != .empty) { 1596 const field_name = self.code.nullTerminatedString(field.name); 1597 try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)}); 1598 } else { 1599 try stream.print("@\"{d}\": ", .{i}); 1600 } 1601 if (field.type != .none) { 1602 try self.writeInstRef(stream, field.type); 1603 } 1604 1605 if (field.type_len > 0) { 1606 const body = self.code.bodySlice(extra_index, field.type_len); 1607 extra_index += body.len; 1608 self.indent += 2; 1609 try self.writeBracedDecl(stream, body); 1610 self.indent -= 2; 1611 } 1612 1613 if (field.align_len > 0) { 1614 const body = self.code.bodySlice(extra_index, field.align_len); 1615 extra_index += body.len; 1616 self.indent += 2; 1617 try stream.writeAll(" align("); 1618 try self.writeBracedDecl(stream, body); 1619 try stream.writeAll(")"); 1620 self.indent -= 2; 1621 } 1622 1623 if (field.init_len > 0) { 1624 const body = self.code.bodySlice(extra_index, field.init_len); 1625 extra_index += body.len; 1626 self.indent += 2; 1627 try stream.writeAll(" = "); 1628 try self.writeBracedDecl(stream, body); 1629 self.indent -= 2; 1630 } 1631 1632 try stream.writeAll(",\n"); 1633 } 1634 1635 self.indent -= 2; 1636 try stream.splatByteAll(' ', self.indent); 1637 try stream.writeAll("}) "); 1638 } 1639 try self.writeSrcNode(stream, .zero); 1640 } 1641 1642 fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1643 const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); 1644 1645 const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand); 1646 1647 const prev_parent_decl_node = self.parent_decl_node; 1648 self.parent_decl_node = extra.data.src_node; 1649 defer self.parent_decl_node = prev_parent_decl_node; 1650 1651 const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ 1652 extra.data.fields_hash_0, 1653 extra.data.fields_hash_1, 1654 extra.data.fields_hash_2, 1655 extra.data.fields_hash_3, 1656 }); 1657 1658 try stream.print("hash({x}) ", .{&fields_hash}); 1659 1660 var extra_index: usize = extra.end; 1661 1662 const tag_type_ref = if (small.has_tag_type) blk: { 1663 const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 1664 extra_index += 1; 1665 break :blk tag_type_ref; 1666 } else .none; 1667 1668 const captures_len = if (small.has_captures_len) blk: { 1669 const captures_len = self.code.extra[extra_index]; 1670 extra_index += 1; 1671 break :blk captures_len; 1672 } else 0; 1673 1674 const body_len = if (small.has_body_len) blk: { 1675 const body_len = self.code.extra[extra_index]; 1676 extra_index += 1; 1677 break :blk body_len; 1678 } else 0; 1679 1680 const fields_len = if (small.has_fields_len) blk: { 1681 const fields_len = self.code.extra[extra_index]; 1682 extra_index += 1; 1683 break :blk fields_len; 1684 } else 0; 1685 1686 const decls_len = if (small.has_decls_len) blk: { 1687 const decls_len = self.code.extra[extra_index]; 1688 extra_index += 1; 1689 break :blk decls_len; 1690 } else 0; 1691 1692 try stream.print("{s}, {s}, ", .{ 1693 @tagName(small.name_strategy), @tagName(small.layout), 1694 }); 1695 try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag); 1696 1697 extra_index = try self.writeCaptures(stream, extra_index, captures_len); 1698 try stream.writeAll(", "); 1699 1700 if (decls_len == 0) { 1701 try stream.writeAll("{}"); 1702 } else { 1703 try stream.writeAll("{\n"); 1704 self.indent += 2; 1705 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); 1706 self.indent -= 2; 1707 extra_index += decls_len; 1708 try stream.splatByteAll(' ', self.indent); 1709 try stream.writeAll("}"); 1710 } 1711 1712 if (tag_type_ref != .none) { 1713 try stream.writeAll(", "); 1714 try self.writeInstRef(stream, tag_type_ref); 1715 } 1716 1717 if (fields_len == 0) { 1718 try stream.writeAll("}) "); 1719 try self.writeSrcNode(stream, .zero); 1720 return; 1721 } 1722 try stream.writeAll(", "); 1723 1724 const body = self.code.bodySlice(extra_index, body_len); 1725 extra_index += body.len; 1726 1727 try self.writeBracedDecl(stream, body); 1728 try stream.writeAll(", {\n"); 1729 1730 self.indent += 2; 1731 const bits_per_field = 4; 1732 const fields_per_u32 = 32 / bits_per_field; 1733 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; 1734 const body_end = extra_index; 1735 extra_index += bit_bags_count; 1736 var bit_bag_index: usize = body_end; 1737 var cur_bit_bag: u32 = undefined; 1738 var field_i: u32 = 0; 1739 while (field_i < fields_len) : (field_i += 1) { 1740 if (field_i % fields_per_u32 == 0) { 1741 cur_bit_bag = self.code.extra[bit_bag_index]; 1742 bit_bag_index += 1; 1743 } 1744 const has_type = @as(u1, @truncate(cur_bit_bag)) != 0; 1745 cur_bit_bag >>= 1; 1746 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; 1747 cur_bit_bag >>= 1; 1748 const has_value = @as(u1, @truncate(cur_bit_bag)) != 0; 1749 cur_bit_bag >>= 1; 1750 const unused = @as(u1, @truncate(cur_bit_bag)) != 0; 1751 cur_bit_bag >>= 1; 1752 1753 _ = unused; 1754 1755 const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]); 1756 const field_name = self.code.nullTerminatedString(field_name_index); 1757 extra_index += 1; 1758 1759 try stream.splatByteAll(' ', self.indent); 1760 try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); 1761 1762 if (has_type) { 1763 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 1764 extra_index += 1; 1765 1766 try stream.writeAll(": "); 1767 try self.writeInstRef(stream, field_type); 1768 } 1769 if (has_align) { 1770 const align_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 1771 extra_index += 1; 1772 1773 try stream.writeAll(" align("); 1774 try self.writeInstRef(stream, align_ref); 1775 try stream.writeAll(")"); 1776 } 1777 if (has_value) { 1778 const default_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 1779 extra_index += 1; 1780 1781 try stream.writeAll(" = "); 1782 try self.writeInstRef(stream, default_ref); 1783 } 1784 try stream.writeAll(",\n"); 1785 } 1786 1787 self.indent -= 2; 1788 try stream.splatByteAll(' ', self.indent); 1789 try stream.writeAll("}) "); 1790 try self.writeSrcNode(stream, .zero); 1791 } 1792 1793 fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1794 const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); 1795 1796 const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand); 1797 1798 const prev_parent_decl_node = self.parent_decl_node; 1799 self.parent_decl_node = extra.data.src_node; 1800 defer self.parent_decl_node = prev_parent_decl_node; 1801 1802 const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ 1803 extra.data.fields_hash_0, 1804 extra.data.fields_hash_1, 1805 extra.data.fields_hash_2, 1806 extra.data.fields_hash_3, 1807 }); 1808 1809 try stream.print("hash({x}) ", .{&fields_hash}); 1810 1811 var extra_index: usize = extra.end; 1812 1813 const tag_type_ref = if (small.has_tag_type) blk: { 1814 const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 1815 extra_index += 1; 1816 break :blk tag_type_ref; 1817 } else .none; 1818 1819 const captures_len = if (small.has_captures_len) blk: { 1820 const captures_len = self.code.extra[extra_index]; 1821 extra_index += 1; 1822 break :blk captures_len; 1823 } else 0; 1824 1825 const body_len = if (small.has_body_len) blk: { 1826 const body_len = self.code.extra[extra_index]; 1827 extra_index += 1; 1828 break :blk body_len; 1829 } else 0; 1830 1831 const fields_len = if (small.has_fields_len) blk: { 1832 const fields_len = self.code.extra[extra_index]; 1833 extra_index += 1; 1834 break :blk fields_len; 1835 } else 0; 1836 1837 const decls_len = if (small.has_decls_len) blk: { 1838 const decls_len = self.code.extra[extra_index]; 1839 extra_index += 1; 1840 break :blk decls_len; 1841 } else 0; 1842 1843 try stream.print("{s}, ", .{@tagName(small.name_strategy)}); 1844 try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive); 1845 1846 extra_index = try self.writeCaptures(stream, extra_index, captures_len); 1847 try stream.writeAll(", "); 1848 1849 if (decls_len == 0) { 1850 try stream.writeAll("{}, "); 1851 } else { 1852 try stream.writeAll("{\n"); 1853 self.indent += 2; 1854 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); 1855 self.indent -= 2; 1856 extra_index += decls_len; 1857 try stream.splatByteAll(' ', self.indent); 1858 try stream.writeAll("}, "); 1859 } 1860 1861 if (tag_type_ref != .none) { 1862 try self.writeInstRef(stream, tag_type_ref); 1863 try stream.writeAll(", "); 1864 } 1865 1866 const body = self.code.bodySlice(extra_index, body_len); 1867 extra_index += body.len; 1868 1869 try self.writeBracedDecl(stream, body); 1870 if (fields_len == 0) { 1871 try stream.writeAll(", {}) "); 1872 } else { 1873 try stream.writeAll(", {\n"); 1874 1875 self.indent += 2; 1876 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; 1877 const body_end = extra_index; 1878 extra_index += bit_bags_count; 1879 var bit_bag_index: usize = body_end; 1880 var cur_bit_bag: u32 = undefined; 1881 var field_i: u32 = 0; 1882 while (field_i < fields_len) : (field_i += 1) { 1883 if (field_i % 32 == 0) { 1884 cur_bit_bag = self.code.extra[bit_bag_index]; 1885 bit_bag_index += 1; 1886 } 1887 const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0; 1888 cur_bit_bag >>= 1; 1889 1890 const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index])); 1891 extra_index += 1; 1892 1893 try stream.splatByteAll(' ', self.indent); 1894 try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); 1895 1896 if (has_tag_value) { 1897 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 1898 extra_index += 1; 1899 1900 try stream.writeAll(" = "); 1901 try self.writeInstRef(stream, tag_value_ref); 1902 } 1903 try stream.writeAll(",\n"); 1904 } 1905 self.indent -= 2; 1906 try stream.splatByteAll(' ', self.indent); 1907 try stream.writeAll("}) "); 1908 } 1909 try self.writeSrcNode(stream, .zero); 1910 } 1911 1912 fn writeOpaqueDecl( 1913 self: *Writer, 1914 stream: *std.Io.Writer, 1915 extended: Zir.Inst.Extended.InstData, 1916 ) !void { 1917 const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small)); 1918 const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); 1919 1920 const prev_parent_decl_node = self.parent_decl_node; 1921 self.parent_decl_node = extra.data.src_node; 1922 defer self.parent_decl_node = prev_parent_decl_node; 1923 1924 var extra_index: usize = extra.end; 1925 1926 const captures_len = if (small.has_captures_len) blk: { 1927 const captures_len = self.code.extra[extra_index]; 1928 extra_index += 1; 1929 break :blk captures_len; 1930 } else 0; 1931 1932 const decls_len = if (small.has_decls_len) blk: { 1933 const decls_len = self.code.extra[extra_index]; 1934 extra_index += 1; 1935 break :blk decls_len; 1936 } else 0; 1937 1938 try stream.print("{s}, ", .{@tagName(small.name_strategy)}); 1939 1940 extra_index = try self.writeCaptures(stream, extra_index, captures_len); 1941 try stream.writeAll(", "); 1942 1943 if (decls_len == 0) { 1944 try stream.writeAll("{}) "); 1945 } else { 1946 try stream.writeAll("{\n"); 1947 self.indent += 2; 1948 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); 1949 self.indent -= 2; 1950 try stream.splatByteAll(' ', self.indent); 1951 try stream.writeAll("}) "); 1952 } 1953 try self.writeSrcNode(stream, .zero); 1954 } 1955 1956 fn writeTupleDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 1957 const fields_len = extended.small; 1958 assert(fields_len != 0); 1959 const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand); 1960 1961 var extra_index = extra.end; 1962 1963 try stream.writeAll("{ "); 1964 1965 for (0..fields_len) |field_idx| { 1966 if (field_idx != 0) try stream.writeAll(", "); 1967 1968 const field_ty, const field_init = self.code.extra[extra_index..][0..2].*; 1969 extra_index += 2; 1970 1971 try stream.print("@\"{d}\": ", .{field_idx}); 1972 try self.writeInstRef(stream, @enumFromInt(field_ty)); 1973 try stream.writeAll(" = "); 1974 try self.writeInstRef(stream, @enumFromInt(field_init)); 1975 } 1976 1977 try stream.writeAll(" }) "); 1978 1979 try self.writeSrcNode(stream, extra.data.src_node); 1980 } 1981 1982 fn writeErrorSetDecl( 1983 self: *Writer, 1984 stream: *std.Io.Writer, 1985 inst: Zir.Inst.Index, 1986 ) !void { 1987 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 1988 const extra = self.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); 1989 1990 try stream.writeAll("{\n"); 1991 self.indent += 2; 1992 1993 var extra_index = @as(u32, @intCast(extra.end)); 1994 const extra_index_end = extra_index + extra.data.fields_len; 1995 while (extra_index < extra_index_end) : (extra_index += 1) { 1996 const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]); 1997 const name = self.code.nullTerminatedString(name_index); 1998 try stream.splatByteAll(' ', self.indent); 1999 try stream.print("{f},\n", .{std.zig.fmtIdP(name)}); 2000 } 2001 2002 self.indent -= 2; 2003 try stream.splatByteAll(' ', self.indent); 2004 try stream.writeAll("}) "); 2005 2006 try self.writeSrcNode(stream, inst_data.src_node); 2007 } 2008 2009 fn writeSwitchBlockErrUnion(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2010 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2011 const extra = self.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index); 2012 2013 var extra_index: usize = extra.end; 2014 2015 const multi_cases_len = if (extra.data.bits.has_multi_cases) blk: { 2016 const multi_cases_len = self.code.extra[extra_index]; 2017 extra_index += 1; 2018 break :blk multi_cases_len; 2019 } else 0; 2020 2021 const err_capture_inst: Zir.Inst.Index = if (extra.data.bits.any_uses_err_capture) blk: { 2022 const tag_capture_inst = self.code.extra[extra_index]; 2023 extra_index += 1; 2024 break :blk @enumFromInt(tag_capture_inst); 2025 } else undefined; 2026 2027 try self.writeInstRef(stream, extra.data.operand); 2028 2029 if (extra.data.bits.any_uses_err_capture) { 2030 try stream.writeAll(", err_capture="); 2031 try self.writeInstIndex(stream, err_capture_inst); 2032 } 2033 2034 self.indent += 2; 2035 2036 { 2037 const info = @as(Zir.Inst.SwitchBlock.ProngInfo, @bitCast(self.code.extra[extra_index])); 2038 extra_index += 1; 2039 2040 assert(!info.is_inline); 2041 const body = self.code.bodySlice(extra_index, info.body_len); 2042 extra_index += body.len; 2043 2044 try stream.writeAll(",\n"); 2045 try stream.splatByteAll(' ', self.indent); 2046 try stream.writeAll("non_err => "); 2047 try self.writeBracedBody(stream, body); 2048 } 2049 2050 if (extra.data.bits.has_else) { 2051 const info = @as(Zir.Inst.SwitchBlock.ProngInfo, @bitCast(self.code.extra[extra_index])); 2052 extra_index += 1; 2053 const capture_text = switch (info.capture) { 2054 .none => "", 2055 .by_val => "by_val ", 2056 .by_ref => "by_ref ", 2057 }; 2058 const inline_text = if (info.is_inline) "inline " else ""; 2059 const body = self.code.bodySlice(extra_index, info.body_len); 2060 extra_index += body.len; 2061 2062 try stream.writeAll(",\n"); 2063 try stream.splatByteAll(' ', self.indent); 2064 try stream.print("{s}{s}else => ", .{ capture_text, inline_text }); 2065 try self.writeBracedBody(stream, body); 2066 } 2067 2068 { 2069 const scalar_cases_len = extra.data.bits.scalar_cases_len; 2070 var scalar_i: usize = 0; 2071 while (scalar_i < scalar_cases_len) : (scalar_i += 1) { 2072 const item_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 2073 extra_index += 1; 2074 const info = @as(Zir.Inst.SwitchBlock.ProngInfo, @bitCast(self.code.extra[extra_index])); 2075 extra_index += 1; 2076 const body = self.code.bodySlice(extra_index, info.body_len); 2077 extra_index += info.body_len; 2078 2079 try stream.writeAll(",\n"); 2080 try stream.splatByteAll(' ', self.indent); 2081 switch (info.capture) { 2082 .none => {}, 2083 .by_val => try stream.writeAll("by_val "), 2084 .by_ref => try stream.writeAll("by_ref "), 2085 } 2086 if (info.is_inline) try stream.writeAll("inline "); 2087 try self.writeInstRef(stream, item_ref); 2088 try stream.writeAll(" => "); 2089 try self.writeBracedBody(stream, body); 2090 } 2091 } 2092 { 2093 var multi_i: usize = 0; 2094 while (multi_i < multi_cases_len) : (multi_i += 1) { 2095 const items_len = self.code.extra[extra_index]; 2096 extra_index += 1; 2097 const ranges_len = self.code.extra[extra_index]; 2098 extra_index += 1; 2099 const info = @as(Zir.Inst.SwitchBlock.ProngInfo, @bitCast(self.code.extra[extra_index])); 2100 extra_index += 1; 2101 const items = self.code.refSlice(extra_index, items_len); 2102 extra_index += items_len; 2103 2104 try stream.writeAll(",\n"); 2105 try stream.splatByteAll(' ', self.indent); 2106 switch (info.capture) { 2107 .none => {}, 2108 .by_val => try stream.writeAll("by_val "), 2109 .by_ref => try stream.writeAll("by_ref "), 2110 } 2111 if (info.is_inline) try stream.writeAll("inline "); 2112 2113 for (items, 0..) |item_ref, item_i| { 2114 if (item_i != 0) try stream.writeAll(", "); 2115 try self.writeInstRef(stream, item_ref); 2116 } 2117 2118 var range_i: usize = 0; 2119 while (range_i < ranges_len) : (range_i += 1) { 2120 const item_first = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 2121 extra_index += 1; 2122 const item_last = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 2123 extra_index += 1; 2124 2125 if (range_i != 0 or items.len != 0) { 2126 try stream.writeAll(", "); 2127 } 2128 try self.writeInstRef(stream, item_first); 2129 try stream.writeAll("..."); 2130 try self.writeInstRef(stream, item_last); 2131 } 2132 2133 const body = self.code.bodySlice(extra_index, info.body_len); 2134 extra_index += info.body_len; 2135 try stream.writeAll(" => "); 2136 try self.writeBracedBody(stream, body); 2137 } 2138 } 2139 2140 self.indent -= 2; 2141 2142 try stream.writeAll(") "); 2143 try self.writeSrcNode(stream, inst_data.src_node); 2144 } 2145 2146 fn writeSwitchBlock(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2147 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2148 const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index); 2149 2150 var extra_index: usize = extra.end; 2151 2152 const multi_cases_len = if (extra.data.bits.has_multi_cases) blk: { 2153 const multi_cases_len = self.code.extra[extra_index]; 2154 extra_index += 1; 2155 break :blk multi_cases_len; 2156 } else 0; 2157 2158 const tag_capture_inst: Zir.Inst.Index = if (extra.data.bits.any_has_tag_capture) blk: { 2159 const tag_capture_inst = self.code.extra[extra_index]; 2160 extra_index += 1; 2161 break :blk @enumFromInt(tag_capture_inst); 2162 } else undefined; 2163 2164 try self.writeInstRef(stream, extra.data.operand); 2165 2166 if (extra.data.bits.any_has_tag_capture) { 2167 try stream.writeAll(", tag_capture="); 2168 try self.writeInstIndex(stream, tag_capture_inst); 2169 } 2170 2171 self.indent += 2; 2172 2173 const special_prongs = extra.data.bits.special_prongs; 2174 2175 if (special_prongs.hasElse()) { 2176 const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(self.code.extra[extra_index]); 2177 const capture_text = switch (info.capture) { 2178 .none => "", 2179 .by_val => "by_val ", 2180 .by_ref => "by_ref ", 2181 }; 2182 const inline_text = if (info.is_inline) "inline " else ""; 2183 extra_index += 1; 2184 const body = self.code.bodySlice(extra_index, info.body_len); 2185 extra_index += body.len; 2186 2187 try stream.writeAll(",\n"); 2188 try stream.splatByteAll(' ', self.indent); 2189 try stream.print("{s}{s}else => ", .{ capture_text, inline_text }); 2190 try self.writeBracedBody(stream, body); 2191 } 2192 2193 if (special_prongs.hasUnder()) { 2194 var single_item_ref: Zir.Inst.Ref = .none; 2195 var items_len: u32 = 0; 2196 var ranges_len: u32 = 0; 2197 if (special_prongs.hasOneAdditionalItem()) { 2198 single_item_ref = @enumFromInt(self.code.extra[extra_index]); 2199 extra_index += 1; 2200 } else if (special_prongs.hasManyAdditionalItems()) { 2201 items_len = self.code.extra[extra_index]; 2202 extra_index += 1; 2203 ranges_len = self.code.extra[extra_index]; 2204 extra_index += 1; 2205 } 2206 const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(self.code.extra[extra_index]); 2207 extra_index += 1; 2208 const items = self.code.refSlice(extra_index, items_len); 2209 extra_index += items_len; 2210 2211 try stream.writeAll(",\n"); 2212 try stream.splatByteAll(' ', self.indent); 2213 switch (info.capture) { 2214 .none => {}, 2215 .by_val => try stream.writeAll("by_val "), 2216 .by_ref => try stream.writeAll("by_ref "), 2217 } 2218 if (info.is_inline) try stream.writeAll("inline "); 2219 2220 try stream.writeAll("_"); 2221 if (single_item_ref != .none) { 2222 try stream.writeAll(", "); 2223 try self.writeInstRef(stream, single_item_ref); 2224 } 2225 for (items) |item_ref| { 2226 try stream.writeAll(", "); 2227 try self.writeInstRef(stream, item_ref); 2228 } 2229 2230 var range_i: usize = 0; 2231 while (range_i < ranges_len) : (range_i += 1) { 2232 const item_first: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); 2233 extra_index += 1; 2234 const item_last: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); 2235 extra_index += 1; 2236 2237 try stream.writeAll(", "); 2238 try self.writeInstRef(stream, item_first); 2239 try stream.writeAll("..."); 2240 try self.writeInstRef(stream, item_last); 2241 } 2242 2243 const body = self.code.bodySlice(extra_index, info.body_len); 2244 extra_index += info.body_len; 2245 try stream.writeAll(" => "); 2246 try self.writeBracedBody(stream, body); 2247 } 2248 2249 { 2250 const scalar_cases_len = extra.data.bits.scalar_cases_len; 2251 var scalar_i: usize = 0; 2252 while (scalar_i < scalar_cases_len) : (scalar_i += 1) { 2253 const item_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); 2254 extra_index += 1; 2255 const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(self.code.extra[extra_index]); 2256 extra_index += 1; 2257 const body = self.code.bodySlice(extra_index, info.body_len); 2258 extra_index += info.body_len; 2259 2260 try stream.writeAll(",\n"); 2261 try stream.splatByteAll(' ', self.indent); 2262 switch (info.capture) { 2263 .none => {}, 2264 .by_val => try stream.writeAll("by_val "), 2265 .by_ref => try stream.writeAll("by_ref "), 2266 } 2267 if (info.is_inline) try stream.writeAll("inline "); 2268 try self.writeInstRef(stream, item_ref); 2269 try stream.writeAll(" => "); 2270 try self.writeBracedBody(stream, body); 2271 } 2272 } 2273 { 2274 var multi_i: usize = 0; 2275 while (multi_i < multi_cases_len) : (multi_i += 1) { 2276 const items_len = self.code.extra[extra_index]; 2277 extra_index += 1; 2278 const ranges_len = self.code.extra[extra_index]; 2279 extra_index += 1; 2280 const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(self.code.extra[extra_index]); 2281 extra_index += 1; 2282 const items = self.code.refSlice(extra_index, items_len); 2283 extra_index += items_len; 2284 2285 try stream.writeAll(",\n"); 2286 try stream.splatByteAll(' ', self.indent); 2287 switch (info.capture) { 2288 .none => {}, 2289 .by_val => try stream.writeAll("by_val "), 2290 .by_ref => try stream.writeAll("by_ref "), 2291 } 2292 if (info.is_inline) try stream.writeAll("inline "); 2293 2294 for (items, 0..) |item_ref, item_i| { 2295 if (item_i != 0) try stream.writeAll(", "); 2296 try self.writeInstRef(stream, item_ref); 2297 } 2298 2299 var range_i: usize = 0; 2300 while (range_i < ranges_len) : (range_i += 1) { 2301 const item_first: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); 2302 extra_index += 1; 2303 const item_last: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); 2304 extra_index += 1; 2305 2306 if (range_i != 0 or items.len != 0) { 2307 try stream.writeAll(", "); 2308 } 2309 try self.writeInstRef(stream, item_first); 2310 try stream.writeAll("..."); 2311 try self.writeInstRef(stream, item_last); 2312 } 2313 2314 const body = self.code.bodySlice(extra_index, info.body_len); 2315 extra_index += info.body_len; 2316 try stream.writeAll(" => "); 2317 try self.writeBracedBody(stream, body); 2318 } 2319 } 2320 2321 self.indent -= 2; 2322 2323 try stream.writeAll(") "); 2324 try self.writeSrcNode(stream, inst_data.src_node); 2325 } 2326 2327 fn writePlNodeField(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2328 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2329 const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; 2330 const name = self.code.nullTerminatedString(extra.field_name_start); 2331 try self.writeInstRef(stream, extra.lhs); 2332 try stream.print(", \"{f}\") ", .{std.zig.fmtString(name)}); 2333 try self.writeSrcNode(stream, inst_data.src_node); 2334 } 2335 2336 fn writePlNodeFieldNamed(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2337 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2338 const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; 2339 try self.writeInstRef(stream, extra.lhs); 2340 try stream.writeAll(", "); 2341 try self.writeInstRef(stream, extra.field_name); 2342 try stream.writeAll(") "); 2343 try self.writeSrcNode(stream, inst_data.src_node); 2344 } 2345 2346 fn writeAs(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2347 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2348 const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data; 2349 try self.writeInstRef(stream, extra.dest_type); 2350 try stream.writeAll(", "); 2351 try self.writeInstRef(stream, extra.operand); 2352 try stream.writeAll(") "); 2353 try self.writeSrcNode(stream, inst_data.src_node); 2354 } 2355 2356 fn writeNode( 2357 self: *Writer, 2358 stream: *std.Io.Writer, 2359 inst: Zir.Inst.Index, 2360 ) Error!void { 2361 const src_node = self.code.instructions.items(.data)[@intFromEnum(inst)].node; 2362 try stream.writeAll(") "); 2363 try self.writeSrcNode(stream, src_node); 2364 } 2365 2366 fn writeStrTok( 2367 self: *Writer, 2368 stream: *std.Io.Writer, 2369 inst: Zir.Inst.Index, 2370 ) Error!void { 2371 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; 2372 const str = inst_data.get(self.code); 2373 try stream.print("\"{f}\") ", .{std.zig.fmtString(str)}); 2374 try self.writeSrcTok(stream, inst_data.src_tok); 2375 } 2376 2377 fn writeStrOp(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2378 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op; 2379 const str = inst_data.getStr(self.code); 2380 try self.writeInstRef(stream, inst_data.operand); 2381 try stream.print(", \"{f}\")", .{std.zig.fmtString(str)}); 2382 } 2383 2384 fn writeFunc( 2385 self: *Writer, 2386 stream: *std.Io.Writer, 2387 inst: Zir.Inst.Index, 2388 inferred_error_set: bool, 2389 ) !void { 2390 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2391 const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index); 2392 2393 var extra_index = extra.end; 2394 var ret_ty_ref: Zir.Inst.Ref = .none; 2395 var ret_ty_body: []const Zir.Inst.Index = &.{}; 2396 2397 switch (extra.data.ret_ty.body_len) { 2398 0 => { 2399 ret_ty_ref = .void_type; 2400 }, 2401 1 => { 2402 ret_ty_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 2403 extra_index += 1; 2404 }, 2405 else => { 2406 ret_ty_body = self.code.bodySlice(extra_index, extra.data.ret_ty.body_len); 2407 extra_index += ret_ty_body.len; 2408 }, 2409 } 2410 2411 const body = self.code.bodySlice(extra_index, extra.data.body_len); 2412 extra_index += body.len; 2413 2414 var src_locs: Zir.Inst.Func.SrcLocs = undefined; 2415 if (body.len != 0) { 2416 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data; 2417 } 2418 return self.writeFuncCommon( 2419 stream, 2420 inferred_error_set, 2421 false, 2422 false, 2423 2424 .none, 2425 &.{}, 2426 ret_ty_ref, 2427 ret_ty_body, 2428 extra.data.ret_ty.is_generic, 2429 2430 body, 2431 inst_data.src_node, 2432 src_locs, 2433 0, 2434 ); 2435 } 2436 2437 fn writeFuncFancy(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2438 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2439 const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); 2440 2441 var extra_index: usize = extra.end; 2442 var cc_ref: Zir.Inst.Ref = .none; 2443 var cc_body: []const Zir.Inst.Index = &.{}; 2444 var ret_ty_ref: Zir.Inst.Ref = .none; 2445 var ret_ty_body: []const Zir.Inst.Index = &.{}; 2446 2447 if (extra.data.bits.has_cc_body) { 2448 const body_len = self.code.extra[extra_index]; 2449 extra_index += 1; 2450 cc_body = self.code.bodySlice(extra_index, body_len); 2451 extra_index += cc_body.len; 2452 } else if (extra.data.bits.has_cc_ref) { 2453 cc_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 2454 extra_index += 1; 2455 } 2456 if (extra.data.bits.has_ret_ty_body) { 2457 const body_len = self.code.extra[extra_index]; 2458 extra_index += 1; 2459 ret_ty_body = self.code.bodySlice(extra_index, body_len); 2460 extra_index += ret_ty_body.len; 2461 } else if (extra.data.bits.has_ret_ty_ref) { 2462 ret_ty_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 2463 extra_index += 1; 2464 } 2465 2466 const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: { 2467 const x = self.code.extra[extra_index]; 2468 extra_index += 1; 2469 break :blk x; 2470 } else 0; 2471 2472 const body = self.code.bodySlice(extra_index, extra.data.body_len); 2473 extra_index += body.len; 2474 2475 var src_locs: Zir.Inst.Func.SrcLocs = undefined; 2476 if (body.len != 0) { 2477 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data; 2478 } 2479 return self.writeFuncCommon( 2480 stream, 2481 extra.data.bits.is_inferred_error, 2482 extra.data.bits.is_var_args, 2483 extra.data.bits.is_noinline, 2484 cc_ref, 2485 cc_body, 2486 ret_ty_ref, 2487 ret_ty_body, 2488 extra.data.bits.ret_ty_is_generic, 2489 body, 2490 inst_data.src_node, 2491 src_locs, 2492 noalias_bits, 2493 ); 2494 } 2495 2496 fn writeAllocExtended(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 2497 const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand); 2498 const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small)); 2499 2500 var extra_index: usize = extra.end; 2501 const type_inst: Zir.Inst.Ref = if (!small.has_type) .none else blk: { 2502 const type_inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 2503 extra_index += 1; 2504 break :blk type_inst; 2505 }; 2506 const align_inst: Zir.Inst.Ref = if (!small.has_align) .none else blk: { 2507 const align_inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); 2508 extra_index += 1; 2509 break :blk align_inst; 2510 }; 2511 try self.writeFlag(stream, ",is_const", small.is_const); 2512 try self.writeFlag(stream, ",is_comptime", small.is_comptime); 2513 try self.writeOptionalInstRef(stream, ",ty=", type_inst); 2514 try self.writeOptionalInstRef(stream, ",align=", align_inst); 2515 try stream.writeAll(")) "); 2516 try self.writeSrcNode(stream, extra.data.src_node); 2517 } 2518 2519 fn writeTypeofPeer(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 2520 const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand); 2521 const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len); 2522 try self.writeBracedBody(stream, body); 2523 try stream.writeAll(",["); 2524 const args = self.code.refSlice(extra.end, extended.small); 2525 for (args, 0..) |arg, i| { 2526 if (i != 0) try stream.writeAll(", "); 2527 try self.writeInstRef(stream, arg); 2528 } 2529 try stream.writeAll("])"); 2530 } 2531 2532 fn writeBoolBr(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2533 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2534 const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index); 2535 const body = self.code.bodySlice(extra.end, extra.data.body_len); 2536 try self.writeInstRef(stream, extra.data.lhs); 2537 try stream.writeAll(", "); 2538 try self.writeBracedBody(stream, body); 2539 try stream.writeAll(") "); 2540 try self.writeSrcNode(stream, inst_data.src_node); 2541 } 2542 2543 fn writeIntType(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2544 const int_type = self.code.instructions.items(.data)[@intFromEnum(inst)].int_type; 2545 const prefix: u8 = switch (int_type.signedness) { 2546 .signed => 'i', 2547 .unsigned => 'u', 2548 }; 2549 try stream.print("{c}{d}) ", .{ prefix, int_type.bit_count }); 2550 try self.writeSrcNode(stream, int_type.src_node); 2551 } 2552 2553 fn writeSaveErrRetIndex(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2554 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index; 2555 2556 try self.writeInstRef(stream, inst_data.operand); 2557 2558 try stream.writeAll(")"); 2559 } 2560 2561 fn writeRestoreErrRetIndex(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 2562 const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data; 2563 2564 try self.writeInstRef(stream, extra.block); 2565 try self.writeInstRef(stream, extra.operand); 2566 2567 try stream.writeAll(") "); 2568 try self.writeSrcNode(stream, extra.src_node); 2569 } 2570 2571 fn writeBreak(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2572 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; 2573 const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; 2574 2575 try self.writeInstIndex(stream, extra.block_inst); 2576 try stream.writeAll(", "); 2577 try self.writeInstRef(stream, inst_data.operand); 2578 try stream.writeAll(")"); 2579 } 2580 2581 fn writeArrayInit(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2582 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2583 2584 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); 2585 const args = self.code.refSlice(extra.end, extra.data.operands_len); 2586 2587 try self.writeInstRef(stream, args[0]); 2588 try stream.writeAll("{"); 2589 for (args[1..], 0..) |arg, i| { 2590 if (i != 0) try stream.writeAll(", "); 2591 try self.writeInstRef(stream, arg); 2592 } 2593 try stream.writeAll("}) "); 2594 try self.writeSrcNode(stream, inst_data.src_node); 2595 } 2596 2597 fn writeArrayInitAnon(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2598 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2599 2600 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); 2601 const args = self.code.refSlice(extra.end, extra.data.operands_len); 2602 2603 try stream.writeAll("{"); 2604 for (args, 0..) |arg, i| { 2605 if (i != 0) try stream.writeAll(", "); 2606 try self.writeInstRef(stream, arg); 2607 } 2608 try stream.writeAll("}) "); 2609 try self.writeSrcNode(stream, inst_data.src_node); 2610 } 2611 2612 fn writeArrayInitSent(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2613 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; 2614 2615 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); 2616 const args = self.code.refSlice(extra.end, extra.data.operands_len); 2617 const sent = args[args.len - 1]; 2618 const elems = args[0 .. args.len - 1]; 2619 2620 try self.writeInstRef(stream, sent); 2621 try stream.writeAll(", "); 2622 2623 try stream.writeAll(".{"); 2624 for (elems, 0..) |elem, i| { 2625 if (i != 0) try stream.writeAll(", "); 2626 try self.writeInstRef(stream, elem); 2627 } 2628 try stream.writeAll("}) "); 2629 try self.writeSrcNode(stream, inst_data.src_node); 2630 } 2631 2632 fn writeUnreachable(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2633 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable"; 2634 try stream.writeAll(") "); 2635 try self.writeSrcNode(stream, inst_data.src_node); 2636 } 2637 2638 fn writeFuncCommon( 2639 self: *Writer, 2640 stream: *std.Io.Writer, 2641 inferred_error_set: bool, 2642 var_args: bool, 2643 is_noinline: bool, 2644 cc_ref: Zir.Inst.Ref, 2645 cc_body: []const Zir.Inst.Index, 2646 ret_ty_ref: Zir.Inst.Ref, 2647 ret_ty_body: []const Zir.Inst.Index, 2648 ret_ty_is_generic: bool, 2649 body: []const Zir.Inst.Index, 2650 src_node: Ast.Node.Offset, 2651 src_locs: Zir.Inst.Func.SrcLocs, 2652 noalias_bits: u32, 2653 ) !void { 2654 try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body); 2655 if (ret_ty_is_generic) try stream.writeAll("[generic] "); 2656 try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body); 2657 try self.writeFlag(stream, "vargs, ", var_args); 2658 try self.writeFlag(stream, "inferror, ", inferred_error_set); 2659 try self.writeFlag(stream, "noinline, ", is_noinline); 2660 2661 if (noalias_bits != 0) { 2662 try stream.print("noalias=0b{b}, ", .{noalias_bits}); 2663 } 2664 2665 try stream.writeAll("body="); 2666 try self.writeBracedBody(stream, body); 2667 try stream.writeAll(") "); 2668 if (body.len != 0) { 2669 try stream.print("(lbrace={d}:{d},rbrace={d}:{d}) ", .{ 2670 src_locs.lbrace_line + 1, @as(u16, @truncate(src_locs.columns)) + 1, 2671 src_locs.rbrace_line + 1, @as(u16, @truncate(src_locs.columns >> 16)) + 1, 2672 }); 2673 } 2674 try self.writeSrcNode(stream, src_node); 2675 } 2676 2677 fn writeDbgStmt(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2678 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; 2679 try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 }); 2680 } 2681 2682 fn writeDefer(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2683 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"defer"; 2684 const body = self.code.bodySlice(inst_data.index, inst_data.len); 2685 try self.writeBracedBody(stream, body); 2686 try stream.writeByte(')'); 2687 } 2688 2689 fn writeDeferErrCode(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2690 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code; 2691 const extra = self.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data; 2692 2693 try self.writeInstRef(stream, extra.remapped_err_code.toRef()); 2694 try stream.writeAll(" = "); 2695 try self.writeInstRef(stream, inst_data.err_code); 2696 try stream.writeAll(", "); 2697 const body = self.code.bodySlice(extra.index, extra.len); 2698 try self.writeBracedBody(stream, body); 2699 try stream.writeByte(')'); 2700 } 2701 2702 fn writeDeclaration(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2703 const decl = self.code.getDeclaration(inst); 2704 2705 const prev_parent_decl_node = self.parent_decl_node; 2706 defer self.parent_decl_node = prev_parent_decl_node; 2707 self.parent_decl_node = decl.src_node; 2708 2709 if (decl.is_pub) try stream.writeAll("pub "); 2710 switch (decl.linkage) { 2711 .normal => {}, 2712 .@"export" => try stream.writeAll("export "), 2713 .@"extern" => try stream.writeAll("extern "), 2714 } 2715 switch (decl.kind) { 2716 .@"comptime" => try stream.writeAll("comptime"), 2717 .unnamed_test => try stream.writeAll("test"), 2718 .@"test", .decltest, .@"const", .@"var" => { 2719 try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) }); 2720 }, 2721 } 2722 const src_hash = self.code.getAssociatedSrcHash(inst).?; 2723 try stream.print(" line({d}) column({d}) hash({x})", .{ 2724 decl.src_line, decl.src_column, &src_hash, 2725 }); 2726 2727 { 2728 if (decl.type_body) |b| { 2729 try stream.writeAll(" type="); 2730 try self.writeBracedDecl(stream, b); 2731 } 2732 2733 if (decl.align_body) |b| { 2734 try stream.writeAll(" align="); 2735 try self.writeBracedDecl(stream, b); 2736 } 2737 2738 if (decl.linksection_body) |b| { 2739 try stream.writeAll(" linksection="); 2740 try self.writeBracedDecl(stream, b); 2741 } 2742 2743 if (decl.addrspace_body) |b| { 2744 try stream.writeAll(" addrspace="); 2745 try self.writeBracedDecl(stream, b); 2746 } 2747 2748 if (decl.value_body) |b| { 2749 try stream.writeAll(" value="); 2750 try self.writeBracedDecl(stream, b); 2751 } 2752 } 2753 2754 try stream.writeAll(") "); 2755 try self.writeSrcNode(stream, .zero); 2756 } 2757 2758 fn writeClosureGet(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 2759 try stream.print("{d})) ", .{extended.small}); 2760 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); 2761 try self.writeSrcNode(stream, src_node); 2762 } 2763 2764 fn writeBuiltinValue(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 2765 const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small); 2766 try stream.print("{s})) ", .{@tagName(val)}); 2767 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); 2768 try self.writeSrcNode(stream, src_node); 2769 } 2770 2771 fn writeInplaceArithResultTy(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { 2772 const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small); 2773 try self.writeInstRef(stream, @enumFromInt(extended.operand)); 2774 try stream.print(", {s}))", .{@tagName(op)}); 2775 } 2776 2777 fn writeInstRef(self: *Writer, stream: *std.Io.Writer, ref: Zir.Inst.Ref) !void { 2778 if (ref == .none) { 2779 return stream.writeAll(".none"); 2780 } else if (ref.toIndex()) |i| { 2781 return self.writeInstIndex(stream, i); 2782 } else { 2783 const val: InternPool.Index = @enumFromInt(@intFromEnum(ref)); 2784 return stream.print("@{s}", .{@tagName(val)}); 2785 } 2786 } 2787 2788 fn writeInstIndex(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2789 _ = self; 2790 return stream.print("%{d}", .{@intFromEnum(inst)}); 2791 } 2792 2793 fn writeCaptures(self: *Writer, stream: *std.Io.Writer, extra_index: usize, captures_len: u32) !usize { 2794 if (captures_len == 0) { 2795 try stream.writeAll("{}"); 2796 return extra_index; 2797 } 2798 2799 const captures: []const Zir.Inst.Capture = @ptrCast(self.code.extra[extra_index..][0..captures_len]); 2800 const capture_names: []const Zir.NullTerminatedString = @ptrCast(self.code.extra[extra_index + captures_len ..][0..captures_len]); 2801 for (captures, capture_names) |capture, name| { 2802 try stream.writeAll("{ "); 2803 if (name != .empty) { 2804 const name_slice = self.code.nullTerminatedString(name); 2805 try stream.print("{s} = ", .{name_slice}); 2806 } 2807 try self.writeCapture(stream, capture); 2808 } 2809 2810 return extra_index + 2 * captures_len; 2811 } 2812 2813 fn writeCapture(self: *Writer, stream: *std.Io.Writer, capture: Zir.Inst.Capture) !void { 2814 switch (capture.unwrap()) { 2815 .nested => |i| return stream.print("[{d}]", .{i}), 2816 .instruction => |inst| return self.writeInstIndex(stream, inst), 2817 .instruction_load => |ptr_inst| { 2818 try stream.writeAll("load "); 2819 try self.writeInstIndex(stream, ptr_inst); 2820 }, 2821 .decl_val => |str| try stream.print("decl_val \"{f}\"", .{ 2822 std.zig.fmtString(self.code.nullTerminatedString(str)), 2823 }), 2824 .decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{ 2825 std.zig.fmtString(self.code.nullTerminatedString(str)), 2826 }), 2827 } 2828 } 2829 2830 fn writeOptionalInstRef( 2831 self: *Writer, 2832 stream: *std.Io.Writer, 2833 prefix: []const u8, 2834 inst: Zir.Inst.Ref, 2835 ) !void { 2836 if (inst == .none) return; 2837 try stream.writeAll(prefix); 2838 try self.writeInstRef(stream, inst); 2839 } 2840 2841 fn writeOptionalInstRefOrBody( 2842 self: *Writer, 2843 stream: *std.Io.Writer, 2844 prefix: []const u8, 2845 ref: Zir.Inst.Ref, 2846 body: []const Zir.Inst.Index, 2847 ) !void { 2848 if (body.len != 0) { 2849 try stream.writeAll(prefix); 2850 try self.writeBracedBody(stream, body); 2851 try stream.writeAll(", "); 2852 } else if (ref != .none) { 2853 try stream.writeAll(prefix); 2854 try self.writeInstRef(stream, ref); 2855 try stream.writeAll(", "); 2856 } 2857 } 2858 2859 fn writeFlag( 2860 self: *Writer, 2861 stream: *std.Io.Writer, 2862 name: []const u8, 2863 flag: bool, 2864 ) !void { 2865 _ = self; 2866 if (!flag) return; 2867 try stream.writeAll(name); 2868 } 2869 2870 fn writeSrcNode(self: *Writer, stream: *std.Io.Writer, src_node: Ast.Node.Offset) !void { 2871 const tree = self.tree orelse return; 2872 const abs_node = src_node.toAbsolute(self.parent_decl_node); 2873 const src_span = tree.nodeToSpan(abs_node); 2874 const start = self.line_col_cursor.find(tree.source, src_span.start); 2875 const end = self.line_col_cursor.find(tree.source, src_span.end); 2876 try stream.print("node_offset:{d}:{d} to :{d}:{d}", .{ 2877 start.line + 1, start.column + 1, 2878 end.line + 1, end.column + 1, 2879 }); 2880 } 2881 2882 fn writeSrcTok(self: *Writer, stream: *std.Io.Writer, src_tok: Ast.TokenOffset) !void { 2883 const tree = self.tree orelse return; 2884 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node)); 2885 const span_start = tree.tokenStart(abs_tok); 2886 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len)); 2887 const start = self.line_col_cursor.find(tree.source, span_start); 2888 const end = self.line_col_cursor.find(tree.source, span_end); 2889 try stream.print("token_offset:{d}:{d} to :{d}:{d}", .{ 2890 start.line + 1, start.column + 1, 2891 end.line + 1, end.column + 1, 2892 }); 2893 } 2894 2895 fn writeSrcTokAbs(self: *Writer, stream: *std.Io.Writer, src_tok: Ast.TokenIndex) !void { 2896 const tree = self.tree orelse return; 2897 const span_start = tree.tokenStart(src_tok); 2898 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len)); 2899 const start = self.line_col_cursor.find(tree.source, span_start); 2900 const end = self.line_col_cursor.find(tree.source, span_end); 2901 try stream.print("token_abs:{d}:{d} to :{d}:{d}", .{ 2902 start.line + 1, start.column + 1, 2903 end.line + 1, end.column + 1, 2904 }); 2905 } 2906 2907 fn writeBracedDecl(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void { 2908 try self.writeBracedBodyConditional(stream, body, self.recurse_decls); 2909 } 2910 2911 fn writeBracedBody(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void { 2912 try self.writeBracedBodyConditional(stream, body, self.recurse_blocks); 2913 } 2914 2915 fn writeBracedBodyConditional(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index, enabled: bool) !void { 2916 if (body.len == 0) { 2917 try stream.writeAll("{}"); 2918 } else if (enabled) { 2919 try stream.writeAll("{\n"); 2920 self.indent += 2; 2921 try self.writeBody(stream, body); 2922 self.indent -= 2; 2923 try stream.splatByteAll(' ', self.indent); 2924 try stream.writeAll("}"); 2925 } else if (body.len == 1) { 2926 try stream.writeByte('{'); 2927 try self.writeInstIndex(stream, body[0]); 2928 try stream.writeByte('}'); 2929 } else if (body.len == 2) { 2930 try stream.writeByte('{'); 2931 try self.writeInstIndex(stream, body[0]); 2932 try stream.writeAll(", "); 2933 try self.writeInstIndex(stream, body[1]); 2934 try stream.writeByte('}'); 2935 } else { 2936 try stream.writeByte('{'); 2937 try self.writeInstIndex(stream, body[0]); 2938 try stream.writeAll(".."); 2939 try self.writeInstIndex(stream, body[body.len - 1]); 2940 try stream.writeByte('}'); 2941 } 2942 } 2943 2944 fn writeBody(self: *Writer, stream: *std.Io.Writer, body: []const Zir.Inst.Index) !void { 2945 for (body) |inst| { 2946 try stream.splatByteAll(' ', self.indent); 2947 try stream.print("%{d} ", .{@intFromEnum(inst)}); 2948 try self.writeInstToStream(stream, inst); 2949 try stream.writeByte('\n'); 2950 } 2951 } 2952 2953 fn writeImport(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { 2954 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok; 2955 const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data; 2956 try self.writeInstRef(stream, extra.res_ty); 2957 const import_path = self.code.nullTerminatedString(extra.path); 2958 try stream.print(", \"{f}\") ", .{std.zig.fmtString(import_path)}); 2959 try self.writeSrcTok(stream, inst_data.src_tok); 2960 } 2961 };