mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
2878 lines
114 KiB
Zig
2878 lines
114 KiB
Zig
const std = @import("std");
|
|
const mem = std.mem;
|
|
const Allocator = std.mem.Allocator;
|
|
const assert = std.debug.assert;
|
|
const Ast = std.zig.Ast;
|
|
const InternPool = @import("InternPool.zig");
|
|
|
|
const Zir = std.zig.Zir;
|
|
const Zcu = @import("Zcu.zig");
|
|
const LazySrcLoc = Zcu.LazySrcLoc;
|
|
|
|
/// Write human-readable, debug formatted ZIR code.
|
|
pub fn renderAsText(gpa: Allocator, tree: ?Ast, zir: Zir, bw: *std.io.Writer) !void {
|
|
var arena = std.heap.ArenaAllocator.init(gpa);
|
|
defer arena.deinit();
|
|
|
|
var writer: Writer = .{
|
|
.gpa = gpa,
|
|
.arena = arena.allocator(),
|
|
.tree = tree,
|
|
.code = zir,
|
|
.indent = 0,
|
|
.parent_decl_node = .root,
|
|
.recurse_decls = true,
|
|
.recurse_blocks = true,
|
|
};
|
|
|
|
const main_struct_inst: Zir.Inst.Index = .main_struct_inst;
|
|
try bw.print("%{d} ", .{@intFromEnum(main_struct_inst)});
|
|
try writer.writeInstToStream(bw, main_struct_inst);
|
|
try bw.writeAll("\n");
|
|
const imports_index = zir.extra[@intFromEnum(Zir.ExtraIndex.imports)];
|
|
if (imports_index != 0) {
|
|
try bw.writeAll("Imports:\n");
|
|
|
|
const extra = zir.extraData(Zir.Inst.Imports, imports_index);
|
|
var extra_index = extra.end;
|
|
|
|
for (0..extra.data.imports_len) |_| {
|
|
const item = zir.extraData(Zir.Inst.Imports.Item, extra_index);
|
|
extra_index = item.end;
|
|
|
|
const import_path = zir.nullTerminatedString(item.data.name);
|
|
try bw.print(" @import(\"{f}\") ", .{
|
|
std.zig.fmtString(import_path),
|
|
});
|
|
try writer.writeSrcTokAbs(bw, item.data.token);
|
|
try bw.writeAll("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn renderInstructionContext(
|
|
gpa: Allocator,
|
|
block: []const Zir.Inst.Index,
|
|
block_index: usize,
|
|
scope_file: *Zcu.File,
|
|
parent_decl_node: Ast.Node.Index,
|
|
indent: u32,
|
|
bw: *std.io.Writer,
|
|
) !void {
|
|
var arena = std.heap.ArenaAllocator.init(gpa);
|
|
defer arena.deinit();
|
|
|
|
var writer: Writer = .{
|
|
.gpa = gpa,
|
|
.arena = arena.allocator(),
|
|
.tree = scope_file.tree,
|
|
.code = scope_file.zir.?,
|
|
.indent = if (indent < 2) 2 else indent,
|
|
.parent_decl_node = parent_decl_node,
|
|
.recurse_decls = false,
|
|
.recurse_blocks = true,
|
|
};
|
|
|
|
try writer.writeBody(bw, block[0..block_index]);
|
|
try bw.splatByteAll(' ', writer.indent - 2);
|
|
try bw.print("> %{d} ", .{@intFromEnum(block[block_index])});
|
|
try writer.writeInstToStream(bw, block[block_index]);
|
|
try bw.writeByte('\n');
|
|
if (block_index + 1 < block.len) {
|
|
try writer.writeBody(bw, block[block_index + 1 ..]);
|
|
}
|
|
}
|
|
|
|
pub fn renderSingleInstruction(
|
|
gpa: Allocator,
|
|
inst: Zir.Inst.Index,
|
|
scope_file: *Zcu.File,
|
|
parent_decl_node: Ast.Node.Index,
|
|
indent: u32,
|
|
bw: *std.io.Writer,
|
|
) !void {
|
|
var arena = std.heap.ArenaAllocator.init(gpa);
|
|
defer arena.deinit();
|
|
|
|
var writer: Writer = .{
|
|
.gpa = gpa,
|
|
.arena = arena.allocator(),
|
|
.tree = scope_file.tree,
|
|
.code = scope_file.zir.?,
|
|
.indent = indent,
|
|
.parent_decl_node = parent_decl_node,
|
|
.recurse_decls = false,
|
|
.recurse_blocks = false,
|
|
};
|
|
|
|
try bw.print("%{d} ", .{@intFromEnum(inst)});
|
|
try writer.writeInstToStream(bw, inst);
|
|
}
|
|
|
|
const Writer = struct {
|
|
gpa: Allocator,
|
|
arena: Allocator,
|
|
tree: ?Ast,
|
|
code: Zir,
|
|
indent: u32,
|
|
parent_decl_node: Ast.Node.Index,
|
|
recurse_decls: bool,
|
|
recurse_blocks: bool,
|
|
|
|
/// Using `std.zig.findLineColumn` whenever we need to resolve a source location makes ZIR
|
|
/// printing O(N^2), which can have drastic effects - taking a ZIR dump from a few seconds to
|
|
/// many minutes. Since we're usually resolving source locations close to one another,
|
|
/// preserving state across source location resolutions speeds things up a lot.
|
|
line_col_cursor: struct {
|
|
line: usize = 0,
|
|
column: usize = 0,
|
|
line_start: usize = 0,
|
|
off: usize = 0,
|
|
|
|
fn find(cur: *@This(), source: []const u8, want_offset: usize) std.zig.Loc {
|
|
if (want_offset < cur.off) {
|
|
// Go back to the start of this line
|
|
cur.off = cur.line_start;
|
|
cur.column = 0;
|
|
|
|
while (want_offset < cur.off) {
|
|
// Go back to the newline
|
|
cur.off -= 1;
|
|
|
|
// Seek to the start of the previous line
|
|
while (cur.off > 0 and source[cur.off - 1] != '\n') {
|
|
cur.off -= 1;
|
|
}
|
|
cur.line_start = cur.off;
|
|
cur.line -= 1;
|
|
}
|
|
}
|
|
|
|
// The cursor is now positioned before `want_offset`.
|
|
// Seek forward as in `std.zig.findLineColumn`.
|
|
|
|
while (cur.off < want_offset) : (cur.off += 1) {
|
|
switch (source[cur.off]) {
|
|
'\n' => {
|
|
cur.line += 1;
|
|
cur.column = 0;
|
|
cur.line_start = cur.off + 1;
|
|
},
|
|
else => {
|
|
cur.column += 1;
|
|
},
|
|
}
|
|
}
|
|
|
|
while (cur.off < source.len and source[cur.off] != '\n') {
|
|
cur.off += 1;
|
|
}
|
|
|
|
return .{
|
|
.line = cur.line,
|
|
.column = cur.column,
|
|
.source_line = source[cur.line_start..cur.off],
|
|
};
|
|
}
|
|
} = .{},
|
|
|
|
const Error = std.io.Writer.Error || Allocator.Error;
|
|
|
|
fn writeInstToStream(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const tags = self.code.instructions.items(.tag);
|
|
const tag = tags[@intFromEnum(inst)];
|
|
try stream.print("= {s}(", .{@tagName(tags[@intFromEnum(inst)])});
|
|
switch (tag) {
|
|
.alloc,
|
|
.alloc_mut,
|
|
.alloc_comptime_mut,
|
|
.elem_type,
|
|
.indexable_ptr_elem_type,
|
|
.splat_op_result_ty,
|
|
.indexable_ptr_len,
|
|
.anyframe_type,
|
|
.bit_not,
|
|
.bool_not,
|
|
.slice_sentinel_ty,
|
|
.negate,
|
|
.negate_wrap,
|
|
.load,
|
|
.ensure_result_used,
|
|
.ensure_result_non_error,
|
|
.ensure_err_union_payload_void,
|
|
.ret_node,
|
|
.ret_load,
|
|
.resolve_inferred_alloc,
|
|
.optional_type,
|
|
.optional_payload_safe,
|
|
.optional_payload_unsafe,
|
|
.optional_payload_safe_ptr,
|
|
.optional_payload_unsafe_ptr,
|
|
.err_union_payload_unsafe,
|
|
.err_union_payload_unsafe_ptr,
|
|
.err_union_code,
|
|
.err_union_code_ptr,
|
|
.is_non_null,
|
|
.is_non_null_ptr,
|
|
.is_non_err,
|
|
.is_non_err_ptr,
|
|
.ret_is_non_err,
|
|
.typeof,
|
|
.type_info,
|
|
.size_of,
|
|
.bit_size_of,
|
|
.typeof_log2_int_type,
|
|
.int_from_ptr,
|
|
.compile_error,
|
|
.set_eval_branch_quota,
|
|
.int_from_enum,
|
|
.align_of,
|
|
.int_from_bool,
|
|
.embed_file,
|
|
.error_name,
|
|
.panic,
|
|
.set_runtime_safety,
|
|
.sqrt,
|
|
.sin,
|
|
.cos,
|
|
.tan,
|
|
.exp,
|
|
.exp2,
|
|
.log,
|
|
.log2,
|
|
.log10,
|
|
.abs,
|
|
.floor,
|
|
.ceil,
|
|
.trunc,
|
|
.round,
|
|
.tag_name,
|
|
.type_name,
|
|
.frame_type,
|
|
.clz,
|
|
.ctz,
|
|
.pop_count,
|
|
.byte_swap,
|
|
.bit_reverse,
|
|
.@"resume",
|
|
.make_ptr_const,
|
|
.validate_deref,
|
|
.validate_const,
|
|
.check_comptime_control_flow,
|
|
.opt_eu_base_ptr_init,
|
|
.restore_err_ret_index_unconditional,
|
|
.restore_err_ret_index_fn_entry,
|
|
=> try self.writeUnNode(stream, inst),
|
|
|
|
.ref,
|
|
.ret_implicit,
|
|
.validate_ref_ty,
|
|
=> try self.writeUnTok(stream, inst),
|
|
|
|
.bool_br_and,
|
|
.bool_br_or,
|
|
=> try self.writeBoolBr(stream, inst),
|
|
|
|
.validate_destructure => try self.writeValidateDestructure(stream, inst),
|
|
.array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
|
|
.ptr_type => try self.writePtrType(stream, inst),
|
|
.int => try self.writeInt(stream, inst),
|
|
.int_big => try self.writeIntBig(stream, inst),
|
|
.float => try self.writeFloat(stream, inst),
|
|
.float128 => try self.writeFloat128(stream, inst),
|
|
.str => try self.writeStr(stream, inst),
|
|
.int_type => try self.writeIntType(stream, inst),
|
|
|
|
.save_err_ret_index => try self.writeSaveErrRetIndex(stream, inst),
|
|
|
|
.@"break",
|
|
.break_inline,
|
|
.switch_continue,
|
|
=> try self.writeBreak(stream, inst),
|
|
|
|
.slice_start => try self.writeSliceStart(stream, inst),
|
|
.slice_end => try self.writeSliceEnd(stream, inst),
|
|
.slice_sentinel => try self.writeSliceSentinel(stream, inst),
|
|
.slice_length => try self.writeSliceLength(stream, inst),
|
|
|
|
.union_init => try self.writeUnionInit(stream, inst),
|
|
|
|
// Struct inits
|
|
|
|
.struct_init_empty,
|
|
.struct_init_empty_result,
|
|
.struct_init_empty_ref_result,
|
|
=> try self.writeUnNode(stream, inst),
|
|
|
|
.struct_init_anon => try self.writeStructInitAnon(stream, inst),
|
|
|
|
.struct_init,
|
|
.struct_init_ref,
|
|
=> try self.writeStructInit(stream, inst),
|
|
|
|
.validate_struct_init_ty,
|
|
.validate_struct_init_result_ty,
|
|
=> try self.writeUnNode(stream, inst),
|
|
|
|
.validate_ptr_struct_init => try self.writeBlock(stream, inst),
|
|
.struct_init_field_type => try self.writeStructInitFieldType(stream, inst),
|
|
.struct_init_field_ptr => try self.writePlNodeField(stream, inst),
|
|
|
|
// Array inits
|
|
|
|
.array_init_anon => try self.writeArrayInitAnon(stream, inst),
|
|
|
|
.array_init,
|
|
.array_init_ref,
|
|
=> try self.writeArrayInit(stream, inst),
|
|
|
|
.validate_array_init_ty,
|
|
.validate_array_init_result_ty,
|
|
=> try self.writeValidateArrayInitTy(stream, inst),
|
|
|
|
.validate_array_init_ref_ty => try self.writeValidateArrayInitRefTy(stream, inst),
|
|
.validate_ptr_array_init => try self.writeBlock(stream, inst),
|
|
.array_init_elem_type => try self.writeArrayInitElemType(stream, inst),
|
|
.array_init_elem_ptr => try self.writeArrayInitElemPtr(stream, inst),
|
|
|
|
.atomic_load => try self.writeAtomicLoad(stream, inst),
|
|
.atomic_store => try self.writeAtomicStore(stream, inst),
|
|
.atomic_rmw => try self.writeAtomicRmw(stream, inst),
|
|
.shuffle => try self.writeShuffle(stream, inst),
|
|
.mul_add => try self.writeMulAdd(stream, inst),
|
|
.builtin_call => try self.writeBuiltinCall(stream, inst),
|
|
|
|
.field_type_ref => try self.writeFieldTypeRef(stream, inst),
|
|
|
|
.add,
|
|
.addwrap,
|
|
.add_sat,
|
|
.add_unsafe,
|
|
.array_cat,
|
|
.mul,
|
|
.mulwrap,
|
|
.mul_sat,
|
|
.sub,
|
|
.subwrap,
|
|
.sub_sat,
|
|
.cmp_lt,
|
|
.cmp_lte,
|
|
.cmp_eq,
|
|
.cmp_gte,
|
|
.cmp_gt,
|
|
.cmp_neq,
|
|
.div,
|
|
.has_decl,
|
|
.has_field,
|
|
.mod_rem,
|
|
.shl,
|
|
.shl_exact,
|
|
.shl_sat,
|
|
.shr,
|
|
.shr_exact,
|
|
.xor,
|
|
.store_node,
|
|
.store_to_inferred_ptr,
|
|
.error_union_type,
|
|
.merge_error_sets,
|
|
.bit_and,
|
|
.bit_or,
|
|
.int_from_float,
|
|
.float_from_int,
|
|
.ptr_from_int,
|
|
.enum_from_int,
|
|
.float_cast,
|
|
.int_cast,
|
|
.ptr_cast,
|
|
.truncate,
|
|
.div_exact,
|
|
.div_floor,
|
|
.div_trunc,
|
|
.mod,
|
|
.rem,
|
|
.bit_offset_of,
|
|
.offset_of,
|
|
.splat,
|
|
.reduce,
|
|
.bitcast,
|
|
.vector_type,
|
|
.max,
|
|
.min,
|
|
.memcpy,
|
|
.memset,
|
|
.memmove,
|
|
.elem_ptr_node,
|
|
.elem_val_node,
|
|
.elem_ptr,
|
|
.elem_val,
|
|
.array_type,
|
|
.coerce_ptr_elem_ty,
|
|
=> try self.writePlNodeBin(stream, inst),
|
|
|
|
.for_len => try self.writePlNodeMultiOp(stream, inst),
|
|
|
|
.array_mul => try self.writeArrayMul(stream, inst),
|
|
|
|
.elem_val_imm => try self.writeElemValImm(stream, inst),
|
|
|
|
.@"export" => try self.writePlNodeExport(stream, inst),
|
|
|
|
.call => try self.writeCall(stream, inst, .direct),
|
|
.field_call => try self.writeCall(stream, inst, .field),
|
|
|
|
.block,
|
|
.block_inline,
|
|
.suspend_block,
|
|
.loop,
|
|
.c_import,
|
|
.typeof_builtin,
|
|
=> try self.writeBlock(stream, inst),
|
|
|
|
.block_comptime => try self.writeBlockComptime(stream, inst),
|
|
|
|
.condbr,
|
|
.condbr_inline,
|
|
=> try self.writeCondBr(stream, inst),
|
|
|
|
.@"try",
|
|
.try_ptr,
|
|
=> try self.writeTry(stream, inst),
|
|
|
|
.error_set_decl => try self.writeErrorSetDecl(stream, inst),
|
|
|
|
.switch_block,
|
|
.switch_block_ref,
|
|
=> try self.writeSwitchBlock(stream, inst),
|
|
|
|
.switch_block_err_union => try self.writeSwitchBlockErrUnion(stream, inst),
|
|
|
|
.field_val,
|
|
.field_ptr,
|
|
.decl_literal,
|
|
.decl_literal_no_coerce,
|
|
=> try self.writePlNodeField(stream, inst),
|
|
|
|
.field_ptr_named,
|
|
.field_val_named,
|
|
=> try self.writePlNodeFieldNamed(stream, inst),
|
|
|
|
.as_node, .as_shift_operand => try self.writeAs(stream, inst),
|
|
|
|
.repeat,
|
|
.repeat_inline,
|
|
.alloc_inferred,
|
|
.alloc_inferred_mut,
|
|
.alloc_inferred_comptime,
|
|
.alloc_inferred_comptime_mut,
|
|
.ret_ptr,
|
|
.ret_type,
|
|
.trap,
|
|
=> try self.writeNode(stream, inst),
|
|
|
|
.error_value,
|
|
.enum_literal,
|
|
.decl_ref,
|
|
.decl_val,
|
|
.ret_err_value,
|
|
.ret_err_value_code,
|
|
.param_anytype,
|
|
.param_anytype_comptime,
|
|
=> try self.writeStrTok(stream, inst),
|
|
|
|
.dbg_var_ptr,
|
|
.dbg_var_val,
|
|
=> try self.writeStrOp(stream, inst),
|
|
|
|
.param, .param_comptime => try self.writeParam(stream, inst),
|
|
|
|
.func => try self.writeFunc(stream, inst, false),
|
|
.func_inferred => try self.writeFunc(stream, inst, true),
|
|
.func_fancy => try self.writeFuncFancy(stream, inst),
|
|
|
|
.@"unreachable" => try self.writeUnreachable(stream, inst),
|
|
|
|
.dbg_stmt => try self.writeDbgStmt(stream, inst),
|
|
|
|
.@"defer" => try self.writeDefer(stream, inst),
|
|
.defer_err_code => try self.writeDeferErrCode(stream, inst),
|
|
|
|
.declaration => try self.writeDeclaration(stream, inst),
|
|
|
|
.extended => try self.writeExtended(stream, inst),
|
|
|
|
.import => try self.writeImport(stream, inst),
|
|
}
|
|
}
|
|
|
|
fn writeExtended(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const extended = self.code.instructions.items(.data)[@intFromEnum(inst)].extended;
|
|
try stream.print("{s}(", .{@tagName(extended.opcode)});
|
|
switch (extended.opcode) {
|
|
.this,
|
|
.ret_addr,
|
|
.error_return_trace,
|
|
.frame,
|
|
.frame_address,
|
|
.breakpoint,
|
|
.disable_instrumentation,
|
|
.disable_intrinsics,
|
|
.c_va_start,
|
|
.in_comptime,
|
|
.value_placeholder,
|
|
=> try self.writeExtNode(stream, extended),
|
|
|
|
.builtin_src => {
|
|
try stream.writeAll("))");
|
|
const inst_data = self.code.extraData(Zir.Inst.LineColumn, extended.operand).data;
|
|
try stream.print(":{d}:{d}", .{ inst_data.line + 1, inst_data.column + 1 });
|
|
},
|
|
|
|
.@"asm" => try self.writeAsm(stream, extended, false),
|
|
.asm_expr => try self.writeAsm(stream, extended, true),
|
|
.alloc => try self.writeAllocExtended(stream, extended),
|
|
|
|
.compile_log => try self.writeNodeMultiOp(stream, extended),
|
|
.typeof_peer => try self.writeTypeofPeer(stream, extended),
|
|
.min_multi => try self.writeNodeMultiOp(stream, extended),
|
|
.max_multi => try self.writeNodeMultiOp(stream, extended),
|
|
|
|
.select => try self.writeSelect(stream, extended),
|
|
|
|
.add_with_overflow,
|
|
.sub_with_overflow,
|
|
.mul_with_overflow,
|
|
.shl_with_overflow,
|
|
=> try self.writeOverflowArithmetic(stream, extended),
|
|
|
|
.struct_decl => try self.writeStructDecl(stream, extended),
|
|
.union_decl => try self.writeUnionDecl(stream, extended),
|
|
.enum_decl => try self.writeEnumDecl(stream, extended),
|
|
.opaque_decl => try self.writeOpaqueDecl(stream, extended),
|
|
|
|
.tuple_decl => try self.writeTupleDecl(stream, extended),
|
|
|
|
.c_undef,
|
|
.c_include,
|
|
.set_float_mode,
|
|
.wasm_memory_size,
|
|
.int_from_error,
|
|
.error_from_int,
|
|
.c_va_copy,
|
|
.c_va_end,
|
|
.work_item_id,
|
|
.work_group_size,
|
|
.work_group_id,
|
|
.branch_hint,
|
|
=> {
|
|
const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
|
try self.writeInstRef(stream, inst_data.operand);
|
|
try stream.writeAll(")) ");
|
|
try self.writeSrcNode(stream, inst_data.node);
|
|
},
|
|
|
|
.reify => {
|
|
const inst_data = self.code.extraData(Zir.Inst.Reify, extended.operand).data;
|
|
try stream.print("line({d}), ", .{inst_data.src_line});
|
|
try self.writeInstRef(stream, inst_data.operand);
|
|
try stream.writeAll(")) ");
|
|
const prev_parent_decl_node = self.parent_decl_node;
|
|
self.parent_decl_node = inst_data.node;
|
|
defer self.parent_decl_node = prev_parent_decl_node;
|
|
try self.writeSrcNode(stream, .zero);
|
|
},
|
|
|
|
.builtin_extern,
|
|
.c_define,
|
|
.error_cast,
|
|
.wasm_memory_grow,
|
|
.prefetch,
|
|
.c_va_arg,
|
|
=> {
|
|
const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
|
try self.writeInstRef(stream, inst_data.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, inst_data.rhs);
|
|
try stream.writeAll(")) ");
|
|
try self.writeSrcNode(stream, inst_data.node);
|
|
},
|
|
|
|
.cmpxchg => try self.writeCmpxchg(stream, extended),
|
|
.ptr_cast_full => try self.writePtrCastFull(stream, extended),
|
|
.ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),
|
|
|
|
.restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),
|
|
.closure_get => try self.writeClosureGet(stream, extended),
|
|
.field_parent_ptr => try self.writeFieldParentPtr(stream, extended),
|
|
.builtin_value => try self.writeBuiltinValue(stream, extended),
|
|
.inplace_arith_result_ty => try self.writeInplaceArithResultTy(stream, extended),
|
|
|
|
.dbg_empty_stmt => try stream.writeAll("))"),
|
|
.astgen_error => try stream.writeAll("))"),
|
|
}
|
|
}
|
|
|
|
fn writeExtNode(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
try stream.writeAll(")) ");
|
|
const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
|
|
try self.writeSrcNode(stream, src_node);
|
|
}
|
|
|
|
fn writeArrayInitElemType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].bin;
|
|
try self.writeInstRef(stream, inst_data.lhs);
|
|
try stream.print(", {d})", .{@intFromEnum(inst_data.rhs)});
|
|
}
|
|
|
|
fn writeUnNode(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
|
try self.writeInstRef(stream, inst_data.operand);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeUnTok(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].un_tok;
|
|
try self.writeInstRef(stream, inst_data.operand);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcTok(stream, inst_data.src_tok);
|
|
}
|
|
|
|
fn writeValidateDestructure(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.operand);
|
|
try stream.print(", {d}) (destructure=", .{extra.expect_len});
|
|
try self.writeSrcNode(stream, extra.destructure_node);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeValidateArrayInitTy(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.ty);
|
|
try stream.print(", {d}) ", .{extra.init_count});
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeArrayTypeSentinel(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.len);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.sentinel);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.elem_type);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writePtrType(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].ptr_type;
|
|
const str_allowzero = if (inst_data.flags.is_allowzero) "allowzero, " else "";
|
|
const str_const = if (!inst_data.flags.is_mutable) "const, " else "";
|
|
const str_volatile = if (inst_data.flags.is_volatile) "volatile, " else "";
|
|
const extra = self.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
|
|
try self.writeInstRef(stream, extra.data.elem_type);
|
|
try stream.print(", {s}{s}{s}{s}", .{
|
|
str_allowzero,
|
|
str_const,
|
|
str_volatile,
|
|
@tagName(inst_data.size),
|
|
});
|
|
var extra_index = extra.end;
|
|
if (inst_data.flags.has_sentinel) {
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])));
|
|
extra_index += 1;
|
|
}
|
|
if (inst_data.flags.has_align) {
|
|
try stream.writeAll(", align(");
|
|
try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])));
|
|
extra_index += 1;
|
|
if (inst_data.flags.has_bit_range) {
|
|
const bit_start = extra_index + @intFromBool(inst_data.flags.has_addrspace);
|
|
try stream.writeAll(":");
|
|
try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[bit_start])));
|
|
try stream.writeAll(":");
|
|
try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[bit_start + 1])));
|
|
}
|
|
try stream.writeAll(")");
|
|
}
|
|
if (inst_data.flags.has_addrspace) {
|
|
try stream.writeAll(", addrspace(");
|
|
try self.writeInstRef(stream, @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])));
|
|
try stream.writeAll(")");
|
|
}
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, extra.data.src_node);
|
|
}
|
|
|
|
fn writeInt(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].int;
|
|
try stream.print("{d})", .{inst_data});
|
|
}
|
|
|
|
fn writeIntBig(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
|
|
const byte_count = inst_data.len * @sizeOf(std.math.big.Limb);
|
|
const limb_bytes = self.code.string_bytes[@intFromEnum(inst_data.start)..][0..byte_count];
|
|
// limb_bytes is not aligned properly; we must allocate and copy the bytes
|
|
// in order to accomplish this.
|
|
const limbs = try self.gpa.alloc(std.math.big.Limb, inst_data.len);
|
|
defer self.gpa.free(limbs);
|
|
|
|
@memcpy(mem.sliceAsBytes(limbs), limb_bytes);
|
|
const big_int: std.math.big.int.Const = .{
|
|
.limbs = limbs,
|
|
.positive = true,
|
|
};
|
|
const as_string = try big_int.toStringAlloc(self.gpa, 10, .lower);
|
|
defer self.gpa.free(as_string);
|
|
try stream.print("{s})", .{as_string});
|
|
}
|
|
|
|
fn writeFloat(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const number = self.code.instructions.items(.data)[@intFromEnum(inst)].float;
|
|
try stream.print("{d})", .{number});
|
|
}
|
|
|
|
fn writeFloat128(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;
|
|
const number = extra.get();
|
|
// TODO improve std.format to be able to print f128 values
|
|
try stream.print("{d}) ", .{@as(f64, @floatCast(number))});
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeStr(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str;
|
|
const str = inst_data.get(self.code);
|
|
try stream.print("\"{f}\")", .{std.zig.fmtString(str)});
|
|
}
|
|
|
|
fn writeSliceStart(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.start);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeSliceEnd(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.start);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.end);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeSliceSentinel(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.start);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.end);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.sentinel);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeSliceLength(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.start);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.len);
|
|
if (extra.sentinel != .none) {
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.sentinel);
|
|
}
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeUnionInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.union_type);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.field_name);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.init);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeShuffle(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.elem_type);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.a);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.b);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.mask);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeSelect(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const extra = self.code.extraData(Zir.Inst.Select, extended.operand).data;
|
|
try self.writeInstRef(stream, extra.elem_type);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.pred);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.a);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.b);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, extra.node);
|
|
}
|
|
|
|
fn writeMulAdd(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.MulAdd, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.mulend1);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.mulend2);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.addend);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeBuiltinCall(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
|
|
|
|
try self.writeFlag(stream, "nodiscard ", extra.flags.ensure_result_used);
|
|
try self.writeFlag(stream, "nosuspend ", extra.flags.is_nosuspend);
|
|
|
|
try self.writeInstRef(stream, extra.modifier);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.callee);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.args);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeFieldParentPtr(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const extra = self.code.extraData(Zir.Inst.FieldParentPtr, extended.operand).data;
|
|
const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
|
|
const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
|
|
if (flags.align_cast) try stream.writeAll("align_cast, ");
|
|
if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, ");
|
|
if (flags.const_cast) try stream.writeAll("const_cast, ");
|
|
if (flags.volatile_cast) try stream.writeAll("volatile_cast, ");
|
|
try self.writeInstRef(stream, extra.parent_ptr_type);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.field_name);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.field_ptr);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, extra.src_node);
|
|
}
|
|
|
|
fn writeParam(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
|
|
const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
|
|
const body = self.code.bodySlice(extra.end, extra.data.type.body_len);
|
|
try stream.print("\"{f}\", ", .{
|
|
std.zig.fmtString(self.code.nullTerminatedString(extra.data.name)),
|
|
});
|
|
|
|
if (extra.data.type.is_generic) try stream.writeAll("[generic] ");
|
|
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcTok(stream, inst_data.src_tok);
|
|
}
|
|
|
|
fn writePlNodeBin(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.rhs);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writePlNodeMultiOp(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
|
|
const args = self.code.refSlice(extra.end, extra.data.operands_len);
|
|
try stream.writeAll("{");
|
|
for (args, 0..) |arg, i| {
|
|
if (i != 0) try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, arg);
|
|
}
|
|
try stream.writeAll("}) ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeArrayMul(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.res_ty);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.rhs);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeElemValImm(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm;
|
|
try self.writeInstRef(stream, inst_data.operand);
|
|
try stream.print(", {d})", .{inst_data.idx});
|
|
}
|
|
|
|
fn writeArrayInitElemPtr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
|
|
|
|
try self.writeInstRef(stream, extra.ptr);
|
|
try stream.print(", {d}) ", .{extra.index});
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writePlNodeExport(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;
|
|
|
|
try self.writeInstRef(stream, extra.exported);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.options);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeValidateArrayInitRefTy(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.ArrayInitRefTy, inst_data.payload_index).data;
|
|
|
|
try self.writeInstRef(stream, extra.ptr_ty);
|
|
try stream.writeAll(", ");
|
|
try stream.print(", {}) ", .{extra.elem_count});
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeStructInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
|
|
var field_i: u32 = 0;
|
|
var extra_index = extra.end;
|
|
|
|
while (field_i < extra.data.fields_len) : (field_i += 1) {
|
|
const item = self.code.extraData(Zir.Inst.StructInit.Item, extra_index);
|
|
extra_index = item.end;
|
|
|
|
if (field_i != 0) {
|
|
try stream.writeAll(", [");
|
|
} else {
|
|
try stream.writeAll("[");
|
|
}
|
|
try self.writeInstIndex(stream, item.data.field_type);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, item.data.init);
|
|
try stream.writeAll("]");
|
|
}
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeCmpxchg(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const extra = self.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;
|
|
|
|
try self.writeInstRef(stream, extra.ptr);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.expected_value);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.new_value);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.success_order);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.failure_order);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, extra.node);
|
|
}
|
|
|
|
fn writePtrCastFull(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
|
|
const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
|
|
const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
|
if (flags.ptr_cast) try stream.writeAll("ptr_cast, ");
|
|
if (flags.align_cast) try stream.writeAll("align_cast, ");
|
|
if (flags.addrspace_cast) try stream.writeAll("addrspace_cast, ");
|
|
if (flags.const_cast) try stream.writeAll("const_cast, ");
|
|
if (flags.volatile_cast) try stream.writeAll("volatile_cast, ");
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.rhs);
|
|
try stream.writeAll(")) ");
|
|
try self.writeSrcNode(stream, extra.node);
|
|
}
|
|
|
|
fn writePtrCastNoDest(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
|
|
const flags: Zir.Inst.FullPtrCastFlags = @bitCast(@as(FlagsInt, @truncate(extended.small)));
|
|
const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
|
if (flags.const_cast) try stream.writeAll("const_cast, ");
|
|
if (flags.volatile_cast) try stream.writeAll("volatile_cast, ");
|
|
try self.writeInstRef(stream, extra.operand);
|
|
try stream.writeAll(")) ");
|
|
try self.writeSrcNode(stream, extra.node);
|
|
}
|
|
|
|
fn writeAtomicLoad(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.AtomicLoad, inst_data.payload_index).data;
|
|
|
|
try self.writeInstRef(stream, extra.elem_type);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.ptr);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.ordering);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeAtomicStore(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data;
|
|
|
|
try self.writeInstRef(stream, extra.ptr);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.operand);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.ordering);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeAtomicRmw(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;
|
|
|
|
try self.writeInstRef(stream, extra.ptr);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.operation);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.operand);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.ordering);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeStructInitAnon(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
|
|
var field_i: u32 = 0;
|
|
var extra_index = extra.end;
|
|
|
|
while (field_i < extra.data.fields_len) : (field_i += 1) {
|
|
const item = self.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
|
|
extra_index = item.end;
|
|
|
|
const field_name = self.code.nullTerminatedString(item.data.field_name);
|
|
|
|
const prefix = if (field_i != 0) ", [" else "[";
|
|
try stream.print("{s}{s}=", .{ prefix, field_name });
|
|
try self.writeInstRef(stream, item.data.init);
|
|
try stream.writeAll("]");
|
|
}
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeStructInitFieldType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.container_type);
|
|
const field_name = self.code.nullTerminatedString(extra.name_start);
|
|
try stream.print(", {s}) ", .{field_name});
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeFieldTypeRef(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.container_type);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.field_name);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeNodeMultiOp(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const extra = self.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
|
|
const operands = self.code.refSlice(extra.end, extended.small);
|
|
|
|
for (operands, 0..) |operand, i| {
|
|
if (i != 0) try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, operand);
|
|
}
|
|
try stream.writeAll(")) ");
|
|
try self.writeSrcNode(stream, extra.data.src_node);
|
|
}
|
|
|
|
fn writeInstNode(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].inst_node;
|
|
try self.writeInstIndex(stream, inst_data.inst);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeAsm(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
extended: Zir.Inst.Extended.InstData,
|
|
tmpl_is_expr: bool,
|
|
) !void {
|
|
const extra = self.code.extraData(Zir.Inst.Asm, extended.operand);
|
|
const outputs_len = @as(u5, @truncate(extended.small));
|
|
const inputs_len = @as(u5, @truncate(extended.small >> 5));
|
|
const clobbers_len = @as(u5, @truncate(extended.small >> 10));
|
|
const is_volatile = @as(u1, @truncate(extended.small >> 15)) != 0;
|
|
|
|
try self.writeFlag(stream, "volatile, ", is_volatile);
|
|
if (tmpl_is_expr) {
|
|
try self.writeInstRef(stream, @enumFromInt(@intFromEnum(extra.data.asm_source)));
|
|
try stream.writeAll(", ");
|
|
} else {
|
|
const asm_source = self.code.nullTerminatedString(extra.data.asm_source);
|
|
try stream.print("\"{f}\", ", .{std.zig.fmtString(asm_source)});
|
|
}
|
|
try stream.writeAll(", ");
|
|
|
|
var extra_i: usize = extra.end;
|
|
var output_type_bits = extra.data.output_type_bits;
|
|
{
|
|
var i: usize = 0;
|
|
while (i < outputs_len) : (i += 1) {
|
|
const output = self.code.extraData(Zir.Inst.Asm.Output, extra_i);
|
|
extra_i = output.end;
|
|
|
|
const is_type = @as(u1, @truncate(output_type_bits)) != 0;
|
|
output_type_bits >>= 1;
|
|
|
|
const name = self.code.nullTerminatedString(output.data.name);
|
|
const constraint = self.code.nullTerminatedString(output.data.constraint);
|
|
try stream.print("output({f}, \"{f}\", ", .{
|
|
std.zig.fmtIdP(name), std.zig.fmtString(constraint),
|
|
});
|
|
try self.writeFlag(stream, "->", is_type);
|
|
try self.writeInstRef(stream, output.data.operand);
|
|
try stream.writeAll(")");
|
|
if (i + 1 < outputs_len) {
|
|
try stream.writeAll("), ");
|
|
}
|
|
}
|
|
}
|
|
{
|
|
var i: usize = 0;
|
|
while (i < inputs_len) : (i += 1) {
|
|
const input = self.code.extraData(Zir.Inst.Asm.Input, extra_i);
|
|
extra_i = input.end;
|
|
|
|
const name = self.code.nullTerminatedString(input.data.name);
|
|
const constraint = self.code.nullTerminatedString(input.data.constraint);
|
|
try stream.print("input({f}, \"{f}\", ", .{
|
|
std.zig.fmtIdP(name), std.zig.fmtString(constraint),
|
|
});
|
|
try self.writeInstRef(stream, input.data.operand);
|
|
try stream.writeAll(")");
|
|
if (i + 1 < inputs_len) {
|
|
try stream.writeAll(", ");
|
|
}
|
|
}
|
|
}
|
|
{
|
|
var i: usize = 0;
|
|
while (i < clobbers_len) : (i += 1) {
|
|
const str_index = self.code.extra[extra_i];
|
|
extra_i += 1;
|
|
const clobber = self.code.nullTerminatedString(@enumFromInt(str_index));
|
|
try stream.print("{f}", .{std.zig.fmtIdP(clobber)});
|
|
if (i + 1 < clobbers_len) {
|
|
try stream.writeAll(", ");
|
|
}
|
|
}
|
|
}
|
|
try stream.writeAll(")) ");
|
|
try self.writeSrcNode(stream, extra.data.src_node);
|
|
}
|
|
|
|
fn writeOverflowArithmetic(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
|
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.rhs);
|
|
try stream.writeAll(")) ");
|
|
try self.writeSrcNode(stream, extra.node);
|
|
}
|
|
|
|
fn writeCall(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
comptime kind: enum { direct, field },
|
|
) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const ExtraType = switch (kind) {
|
|
.direct => Zir.Inst.Call,
|
|
.field => Zir.Inst.FieldCall,
|
|
};
|
|
const extra = self.code.extraData(ExtraType, inst_data.payload_index);
|
|
const args_len = extra.data.flags.args_len;
|
|
const body = self.code.extra[extra.end..];
|
|
|
|
if (extra.data.flags.ensure_result_used) {
|
|
try stream.writeAll("nodiscard ");
|
|
}
|
|
try stream.print(".{s}, ", .{@tagName(@as(std.builtin.CallModifier, @enumFromInt(extra.data.flags.packed_modifier)))});
|
|
switch (kind) {
|
|
.direct => try self.writeInstRef(stream, extra.data.callee),
|
|
.field => {
|
|
const field_name = self.code.nullTerminatedString(extra.data.field_name_start);
|
|
try self.writeInstRef(stream, extra.data.obj_ptr);
|
|
try stream.print(", \"{f}\"", .{std.zig.fmtString(field_name)});
|
|
},
|
|
}
|
|
try stream.writeAll(", [");
|
|
|
|
self.indent += 2;
|
|
if (args_len != 0) {
|
|
try stream.writeAll("\n");
|
|
}
|
|
var i: usize = 0;
|
|
var arg_start: u32 = args_len;
|
|
while (i < args_len) : (i += 1) {
|
|
try stream.splatByteAll(' ', self.indent);
|
|
const arg_end = self.code.extra[extra.end + i];
|
|
defer arg_start = arg_end;
|
|
const arg_body = body[arg_start..arg_end];
|
|
try self.writeBracedBody(stream, @ptrCast(arg_body));
|
|
|
|
try stream.writeAll(",\n");
|
|
}
|
|
self.indent -= 2;
|
|
if (args_len != 0) {
|
|
try stream.splatByteAll(' ', self.indent);
|
|
}
|
|
|
|
try stream.writeAll("]) ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeBlock(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
|
|
const body = self.code.bodySlice(extra.end, extra.data.body_len);
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeBlockComptime(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index);
|
|
const body = self.code.bodySlice(extra.end, extra.data.body_len);
|
|
try stream.print("reason={s}, ", .{@tagName(extra.data.reason)});
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeCondBr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
|
|
const then_body = self.code.bodySlice(extra.end, extra.data.then_body_len);
|
|
const else_body = self.code.bodySlice(extra.end + then_body.len, extra.data.else_body_len);
|
|
try self.writeInstRef(stream, extra.data.condition);
|
|
try stream.writeAll(", ");
|
|
try self.writeBracedBody(stream, then_body);
|
|
try stream.writeAll(", ");
|
|
try self.writeBracedBody(stream, else_body);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeTry(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.Try, inst_data.payload_index);
|
|
const body = self.code.bodySlice(extra.end, extra.data.body_len);
|
|
try self.writeInstRef(stream, extra.data.operand);
|
|
try stream.writeAll(", ");
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeStructDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
|
|
|
|
const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand);
|
|
|
|
const prev_parent_decl_node = self.parent_decl_node;
|
|
self.parent_decl_node = extra.data.src_node;
|
|
defer self.parent_decl_node = prev_parent_decl_node;
|
|
|
|
const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
|
|
extra.data.fields_hash_0,
|
|
extra.data.fields_hash_1,
|
|
extra.data.fields_hash_2,
|
|
extra.data.fields_hash_3,
|
|
});
|
|
|
|
try stream.print("hash({x}) ", .{&fields_hash});
|
|
|
|
var extra_index: usize = extra.end;
|
|
|
|
const captures_len = if (small.has_captures_len) blk: {
|
|
const captures_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk captures_len;
|
|
} else 0;
|
|
|
|
const fields_len = if (small.has_fields_len) blk: {
|
|
const fields_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk fields_len;
|
|
} else 0;
|
|
|
|
const decls_len = if (small.has_decls_len) blk: {
|
|
const decls_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk decls_len;
|
|
} else 0;
|
|
|
|
try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
|
|
try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
|
|
|
|
try stream.print("{s}, ", .{@tagName(small.name_strategy)});
|
|
|
|
extra_index = try self.writeCaptures(stream, extra_index, captures_len);
|
|
try stream.writeAll(", ");
|
|
|
|
if (small.has_backing_int) {
|
|
const backing_int_body_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
try stream.writeAll("packed(");
|
|
if (backing_int_body_len == 0) {
|
|
const backing_int_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
try self.writeInstRef(stream, backing_int_ref);
|
|
} else {
|
|
const body = self.code.bodySlice(extra_index, backing_int_body_len);
|
|
extra_index += backing_int_body_len;
|
|
self.indent += 2;
|
|
try self.writeBracedDecl(stream, body);
|
|
self.indent -= 2;
|
|
}
|
|
try stream.writeAll("), ");
|
|
} else {
|
|
try stream.print("{s}, ", .{@tagName(small.layout)});
|
|
}
|
|
|
|
if (decls_len == 0) {
|
|
try stream.writeAll("{}, ");
|
|
} else {
|
|
try stream.writeAll("{\n");
|
|
self.indent += 2;
|
|
try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
|
|
self.indent -= 2;
|
|
extra_index += decls_len;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}, ");
|
|
}
|
|
|
|
if (fields_len == 0) {
|
|
try stream.writeAll("{}, {}) ");
|
|
} else {
|
|
const bits_per_field = 4;
|
|
const fields_per_u32 = 32 / bits_per_field;
|
|
const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
|
|
const Field = struct {
|
|
type_len: u32 = 0,
|
|
align_len: u32 = 0,
|
|
init_len: u32 = 0,
|
|
type: Zir.Inst.Ref = .none,
|
|
name: Zir.NullTerminatedString,
|
|
is_comptime: bool,
|
|
};
|
|
const fields = try self.arena.alloc(Field, fields_len);
|
|
{
|
|
var bit_bag_index: usize = extra_index;
|
|
extra_index += bit_bags_count;
|
|
var cur_bit_bag: u32 = undefined;
|
|
var field_i: u32 = 0;
|
|
while (field_i < fields_len) : (field_i += 1) {
|
|
if (field_i % fields_per_u32 == 0) {
|
|
cur_bit_bag = self.code.extra[bit_bag_index];
|
|
bit_bag_index += 1;
|
|
}
|
|
const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
const has_default = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
const is_comptime = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
|
|
const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
|
|
fields[field_i] = .{
|
|
.is_comptime = is_comptime,
|
|
.name = field_name_index,
|
|
};
|
|
|
|
if (has_type_body) {
|
|
fields[field_i].type_len = self.code.extra[extra_index];
|
|
} else {
|
|
fields[field_i].type = @enumFromInt(self.code.extra[extra_index]);
|
|
}
|
|
extra_index += 1;
|
|
|
|
if (has_align) {
|
|
fields[field_i].align_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
}
|
|
|
|
if (has_default) {
|
|
fields[field_i].init_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
try stream.writeAll("{\n");
|
|
self.indent += 2;
|
|
|
|
for (fields, 0..) |field, i| {
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try self.writeFlag(stream, "comptime ", field.is_comptime);
|
|
if (field.name != .empty) {
|
|
const field_name = self.code.nullTerminatedString(field.name);
|
|
try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)});
|
|
} else {
|
|
try stream.print("@\"{d}\": ", .{i});
|
|
}
|
|
if (field.type != .none) {
|
|
try self.writeInstRef(stream, field.type);
|
|
}
|
|
|
|
if (field.type_len > 0) {
|
|
const body = self.code.bodySlice(extra_index, field.type_len);
|
|
extra_index += body.len;
|
|
self.indent += 2;
|
|
try self.writeBracedDecl(stream, body);
|
|
self.indent -= 2;
|
|
}
|
|
|
|
if (field.align_len > 0) {
|
|
const body = self.code.bodySlice(extra_index, field.align_len);
|
|
extra_index += body.len;
|
|
self.indent += 2;
|
|
try stream.writeAll(" align(");
|
|
try self.writeBracedDecl(stream, body);
|
|
try stream.writeAll(")");
|
|
self.indent -= 2;
|
|
}
|
|
|
|
if (field.init_len > 0) {
|
|
const body = self.code.bodySlice(extra_index, field.init_len);
|
|
extra_index += body.len;
|
|
self.indent += 2;
|
|
try stream.writeAll(" = ");
|
|
try self.writeBracedDecl(stream, body);
|
|
self.indent -= 2;
|
|
}
|
|
|
|
try stream.writeAll(",\n");
|
|
}
|
|
|
|
self.indent -= 2;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}) ");
|
|
}
|
|
try self.writeSrcNode(stream, .zero);
|
|
}
|
|
|
|
fn writeUnionDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small));
|
|
|
|
const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand);
|
|
|
|
const prev_parent_decl_node = self.parent_decl_node;
|
|
self.parent_decl_node = extra.data.src_node;
|
|
defer self.parent_decl_node = prev_parent_decl_node;
|
|
|
|
const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
|
|
extra.data.fields_hash_0,
|
|
extra.data.fields_hash_1,
|
|
extra.data.fields_hash_2,
|
|
extra.data.fields_hash_3,
|
|
});
|
|
|
|
try stream.print("hash({x}) ", .{&fields_hash});
|
|
|
|
var extra_index: usize = extra.end;
|
|
|
|
const tag_type_ref = if (small.has_tag_type) blk: {
|
|
const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
break :blk tag_type_ref;
|
|
} else .none;
|
|
|
|
const captures_len = if (small.has_captures_len) blk: {
|
|
const captures_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk captures_len;
|
|
} else 0;
|
|
|
|
const body_len = if (small.has_body_len) blk: {
|
|
const body_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk body_len;
|
|
} else 0;
|
|
|
|
const fields_len = if (small.has_fields_len) blk: {
|
|
const fields_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk fields_len;
|
|
} else 0;
|
|
|
|
const decls_len = if (small.has_decls_len) blk: {
|
|
const decls_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk decls_len;
|
|
} else 0;
|
|
|
|
try stream.print("{s}, {s}, ", .{
|
|
@tagName(small.name_strategy), @tagName(small.layout),
|
|
});
|
|
try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag);
|
|
|
|
extra_index = try self.writeCaptures(stream, extra_index, captures_len);
|
|
try stream.writeAll(", ");
|
|
|
|
if (decls_len == 0) {
|
|
try stream.writeAll("{}");
|
|
} else {
|
|
try stream.writeAll("{\n");
|
|
self.indent += 2;
|
|
try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
|
|
self.indent -= 2;
|
|
extra_index += decls_len;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}");
|
|
}
|
|
|
|
if (tag_type_ref != .none) {
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, tag_type_ref);
|
|
}
|
|
|
|
if (fields_len == 0) {
|
|
try stream.writeAll("}) ");
|
|
try self.writeSrcNode(stream, .zero);
|
|
return;
|
|
}
|
|
try stream.writeAll(", ");
|
|
|
|
const body = self.code.bodySlice(extra_index, body_len);
|
|
extra_index += body.len;
|
|
|
|
try self.writeBracedDecl(stream, body);
|
|
try stream.writeAll(", {\n");
|
|
|
|
self.indent += 2;
|
|
const bits_per_field = 4;
|
|
const fields_per_u32 = 32 / bits_per_field;
|
|
const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
|
|
const body_end = extra_index;
|
|
extra_index += bit_bags_count;
|
|
var bit_bag_index: usize = body_end;
|
|
var cur_bit_bag: u32 = undefined;
|
|
var field_i: u32 = 0;
|
|
while (field_i < fields_len) : (field_i += 1) {
|
|
if (field_i % fields_per_u32 == 0) {
|
|
cur_bit_bag = self.code.extra[bit_bag_index];
|
|
bit_bag_index += 1;
|
|
}
|
|
const has_type = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
const has_value = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
const unused = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
|
|
_ = unused;
|
|
|
|
const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
|
|
const field_name = self.code.nullTerminatedString(field_name_index);
|
|
extra_index += 1;
|
|
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
|
|
|
|
if (has_type) {
|
|
const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
|
|
try stream.writeAll(": ");
|
|
try self.writeInstRef(stream, field_type);
|
|
}
|
|
if (has_align) {
|
|
const align_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
|
|
try stream.writeAll(" align(");
|
|
try self.writeInstRef(stream, align_ref);
|
|
try stream.writeAll(")");
|
|
}
|
|
if (has_value) {
|
|
const default_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
|
|
try stream.writeAll(" = ");
|
|
try self.writeInstRef(stream, default_ref);
|
|
}
|
|
try stream.writeAll(",\n");
|
|
}
|
|
|
|
self.indent -= 2;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}) ");
|
|
try self.writeSrcNode(stream, .zero);
|
|
}
|
|
|
|
fn writeEnumDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));
|
|
|
|
const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand);
|
|
|
|
const prev_parent_decl_node = self.parent_decl_node;
|
|
self.parent_decl_node = extra.data.src_node;
|
|
defer self.parent_decl_node = prev_parent_decl_node;
|
|
|
|
const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
|
|
extra.data.fields_hash_0,
|
|
extra.data.fields_hash_1,
|
|
extra.data.fields_hash_2,
|
|
extra.data.fields_hash_3,
|
|
});
|
|
|
|
try stream.print("hash({x}) ", .{&fields_hash});
|
|
|
|
var extra_index: usize = extra.end;
|
|
|
|
const tag_type_ref = if (small.has_tag_type) blk: {
|
|
const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
break :blk tag_type_ref;
|
|
} else .none;
|
|
|
|
const captures_len = if (small.has_captures_len) blk: {
|
|
const captures_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk captures_len;
|
|
} else 0;
|
|
|
|
const body_len = if (small.has_body_len) blk: {
|
|
const body_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk body_len;
|
|
} else 0;
|
|
|
|
const fields_len = if (small.has_fields_len) blk: {
|
|
const fields_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk fields_len;
|
|
} else 0;
|
|
|
|
const decls_len = if (small.has_decls_len) blk: {
|
|
const decls_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk decls_len;
|
|
} else 0;
|
|
|
|
try stream.print("{s}, ", .{@tagName(small.name_strategy)});
|
|
try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive);
|
|
|
|
extra_index = try self.writeCaptures(stream, extra_index, captures_len);
|
|
try stream.writeAll(", ");
|
|
|
|
if (decls_len == 0) {
|
|
try stream.writeAll("{}, ");
|
|
} else {
|
|
try stream.writeAll("{\n");
|
|
self.indent += 2;
|
|
try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
|
|
self.indent -= 2;
|
|
extra_index += decls_len;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}, ");
|
|
}
|
|
|
|
if (tag_type_ref != .none) {
|
|
try self.writeInstRef(stream, tag_type_ref);
|
|
try stream.writeAll(", ");
|
|
}
|
|
|
|
const body = self.code.bodySlice(extra_index, body_len);
|
|
extra_index += body.len;
|
|
|
|
try self.writeBracedDecl(stream, body);
|
|
if (fields_len == 0) {
|
|
try stream.writeAll(", {}) ");
|
|
} else {
|
|
try stream.writeAll(", {\n");
|
|
|
|
self.indent += 2;
|
|
const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
|
|
const body_end = extra_index;
|
|
extra_index += bit_bags_count;
|
|
var bit_bag_index: usize = body_end;
|
|
var cur_bit_bag: u32 = undefined;
|
|
var field_i: u32 = 0;
|
|
while (field_i < fields_len) : (field_i += 1) {
|
|
if (field_i % 32 == 0) {
|
|
cur_bit_bag = self.code.extra[bit_bag_index];
|
|
bit_bag_index += 1;
|
|
}
|
|
const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0;
|
|
cur_bit_bag >>= 1;
|
|
|
|
const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
|
|
|
|
if (has_tag_value) {
|
|
const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
|
|
try stream.writeAll(" = ");
|
|
try self.writeInstRef(stream, tag_value_ref);
|
|
}
|
|
try stream.writeAll(",\n");
|
|
}
|
|
self.indent -= 2;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}) ");
|
|
}
|
|
try self.writeSrcNode(stream, .zero);
|
|
}
|
|
|
|
fn writeOpaqueDecl(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
extended: Zir.Inst.Extended.InstData,
|
|
) !void {
|
|
const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small));
|
|
const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand);
|
|
|
|
const prev_parent_decl_node = self.parent_decl_node;
|
|
self.parent_decl_node = extra.data.src_node;
|
|
defer self.parent_decl_node = prev_parent_decl_node;
|
|
|
|
var extra_index: usize = extra.end;
|
|
|
|
const captures_len = if (small.has_captures_len) blk: {
|
|
const captures_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk captures_len;
|
|
} else 0;
|
|
|
|
const decls_len = if (small.has_decls_len) blk: {
|
|
const decls_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk decls_len;
|
|
} else 0;
|
|
|
|
try stream.print("{s}, ", .{@tagName(small.name_strategy)});
|
|
|
|
extra_index = try self.writeCaptures(stream, extra_index, captures_len);
|
|
try stream.writeAll(", ");
|
|
|
|
if (decls_len == 0) {
|
|
try stream.writeAll("{}) ");
|
|
} else {
|
|
try stream.writeAll("{\n");
|
|
self.indent += 2;
|
|
try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
|
|
self.indent -= 2;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}) ");
|
|
}
|
|
try self.writeSrcNode(stream, .zero);
|
|
}
|
|
|
|
fn writeTupleDecl(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const fields_len = extended.small;
|
|
assert(fields_len != 0);
|
|
const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand);
|
|
|
|
var extra_index = extra.end;
|
|
|
|
try stream.writeAll("{ ");
|
|
|
|
for (0..fields_len) |field_idx| {
|
|
if (field_idx != 0) try stream.writeAll(", ");
|
|
|
|
const field_ty, const field_init = self.code.extra[extra_index..][0..2].*;
|
|
extra_index += 2;
|
|
|
|
try stream.print("@\"{d}\": ", .{field_idx});
|
|
try self.writeInstRef(stream, @enumFromInt(field_ty));
|
|
try stream.writeAll(" = ");
|
|
try self.writeInstRef(stream, @enumFromInt(field_init));
|
|
}
|
|
|
|
try stream.writeAll(" }) ");
|
|
|
|
try self.writeSrcNode(stream, extra.data.src_node);
|
|
}
|
|
|
|
fn writeErrorSetDecl(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
|
|
|
|
try stream.writeAll("{\n");
|
|
self.indent += 2;
|
|
|
|
var extra_index = @as(u32, @intCast(extra.end));
|
|
const extra_index_end = extra_index + extra.data.fields_len;
|
|
while (extra_index < extra_index_end) : (extra_index += 1) {
|
|
const name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
|
|
const name = self.code.nullTerminatedString(name_index);
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.print("{f},\n", .{std.zig.fmtIdP(name)});
|
|
}
|
|
|
|
self.indent -= 2;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}) ");
|
|
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeSwitchBlockErrUnion(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.SwitchBlockErrUnion, inst_data.payload_index);
|
|
|
|
var extra_index: usize = extra.end;
|
|
|
|
const multi_cases_len = if (extra.data.bits.has_multi_cases) blk: {
|
|
const multi_cases_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk multi_cases_len;
|
|
} else 0;
|
|
|
|
const err_capture_inst: Zir.Inst.Index = if (extra.data.bits.any_uses_err_capture) blk: {
|
|
const tag_capture_inst = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk @enumFromInt(tag_capture_inst);
|
|
} else undefined;
|
|
|
|
try self.writeInstRef(stream, extra.data.operand);
|
|
|
|
if (extra.data.bits.any_uses_err_capture) {
|
|
try stream.writeAll(", err_capture=");
|
|
try self.writeInstIndex(stream, err_capture_inst);
|
|
}
|
|
|
|
self.indent += 2;
|
|
|
|
{
|
|
const info = @as(Zir.Inst.SwitchBlock.ProngInfo, @bitCast(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
|
|
assert(!info.is_inline);
|
|
const body = self.code.bodySlice(extra_index, info.body_len);
|
|
extra_index += body.len;
|
|
|
|
try stream.writeAll(",\n");
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("non_err => ");
|
|
try self.writeBracedBody(stream, body);
|
|
}
|
|
|
|
if (extra.data.bits.has_else) {
|
|
const info = @as(Zir.Inst.SwitchBlock.ProngInfo, @bitCast(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
const capture_text = switch (info.capture) {
|
|
.none => "",
|
|
.by_val => "by_val ",
|
|
.by_ref => "by_ref ",
|
|
};
|
|
const inline_text = if (info.is_inline) "inline " else "";
|
|
const body = self.code.bodySlice(extra_index, info.body_len);
|
|
extra_index += body.len;
|
|
|
|
try stream.writeAll(",\n");
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.print("{s}{s}else => ", .{ capture_text, inline_text });
|
|
try self.writeBracedBody(stream, body);
|
|
}
|
|
|
|
{
|
|
const scalar_cases_len = extra.data.bits.scalar_cases_len;
|
|
var scalar_i: usize = 0;
|
|
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
|
|
const item_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
const info = @as(Zir.Inst.SwitchBlock.ProngInfo, @bitCast(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
const body = self.code.bodySlice(extra_index, info.body_len);
|
|
extra_index += info.body_len;
|
|
|
|
try stream.writeAll(",\n");
|
|
try stream.splatByteAll(' ', self.indent);
|
|
switch (info.capture) {
|
|
.none => {},
|
|
.by_val => try stream.writeAll("by_val "),
|
|
.by_ref => try stream.writeAll("by_ref "),
|
|
}
|
|
if (info.is_inline) try stream.writeAll("inline ");
|
|
try self.writeInstRef(stream, item_ref);
|
|
try stream.writeAll(" => ");
|
|
try self.writeBracedBody(stream, body);
|
|
}
|
|
}
|
|
{
|
|
var multi_i: usize = 0;
|
|
while (multi_i < multi_cases_len) : (multi_i += 1) {
|
|
const items_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
const ranges_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
const info = @as(Zir.Inst.SwitchBlock.ProngInfo, @bitCast(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
const items = self.code.refSlice(extra_index, items_len);
|
|
extra_index += items_len;
|
|
|
|
try stream.writeAll(",\n");
|
|
try stream.splatByteAll(' ', self.indent);
|
|
switch (info.capture) {
|
|
.none => {},
|
|
.by_val => try stream.writeAll("by_val "),
|
|
.by_ref => try stream.writeAll("by_ref "),
|
|
}
|
|
if (info.is_inline) try stream.writeAll("inline ");
|
|
|
|
for (items, 0..) |item_ref, item_i| {
|
|
if (item_i != 0) try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, item_ref);
|
|
}
|
|
|
|
var range_i: usize = 0;
|
|
while (range_i < ranges_len) : (range_i += 1) {
|
|
const item_first = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
const item_last = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
|
|
if (range_i != 0 or items.len != 0) {
|
|
try stream.writeAll(", ");
|
|
}
|
|
try self.writeInstRef(stream, item_first);
|
|
try stream.writeAll("...");
|
|
try self.writeInstRef(stream, item_last);
|
|
}
|
|
|
|
const body = self.code.bodySlice(extra_index, info.body_len);
|
|
extra_index += info.body_len;
|
|
try stream.writeAll(" => ");
|
|
try self.writeBracedBody(stream, body);
|
|
}
|
|
}
|
|
|
|
self.indent -= 2;
|
|
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeSwitchBlock(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);
|
|
|
|
var extra_index: usize = extra.end;
|
|
|
|
const multi_cases_len = if (extra.data.bits.has_multi_cases) blk: {
|
|
const multi_cases_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk multi_cases_len;
|
|
} else 0;
|
|
|
|
const tag_capture_inst: Zir.Inst.Index = if (extra.data.bits.any_has_tag_capture) blk: {
|
|
const tag_capture_inst = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk @enumFromInt(tag_capture_inst);
|
|
} else undefined;
|
|
|
|
try self.writeInstRef(stream, extra.data.operand);
|
|
|
|
if (extra.data.bits.any_has_tag_capture) {
|
|
try stream.writeAll(", tag_capture=");
|
|
try self.writeInstIndex(stream, tag_capture_inst);
|
|
}
|
|
|
|
self.indent += 2;
|
|
|
|
const special_prongs = extra.data.bits.special_prongs;
|
|
|
|
if (special_prongs.hasElse()) {
|
|
const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(self.code.extra[extra_index]);
|
|
const capture_text = switch (info.capture) {
|
|
.none => "",
|
|
.by_val => "by_val ",
|
|
.by_ref => "by_ref ",
|
|
};
|
|
const inline_text = if (info.is_inline) "inline " else "";
|
|
extra_index += 1;
|
|
const body = self.code.bodySlice(extra_index, info.body_len);
|
|
extra_index += body.len;
|
|
|
|
try stream.writeAll(",\n");
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.print("{s}{s}else => ", .{ capture_text, inline_text });
|
|
try self.writeBracedBody(stream, body);
|
|
}
|
|
|
|
if (special_prongs.hasUnder()) {
|
|
var single_item_ref: Zir.Inst.Ref = .none;
|
|
var items_len: u32 = 0;
|
|
var ranges_len: u32 = 0;
|
|
if (special_prongs.hasOneAdditionalItem()) {
|
|
single_item_ref = @enumFromInt(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
} else if (special_prongs.hasManyAdditionalItems()) {
|
|
items_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
ranges_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
}
|
|
const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
const items = self.code.refSlice(extra_index, items_len);
|
|
extra_index += items_len;
|
|
|
|
try stream.writeAll(",\n");
|
|
try stream.splatByteAll(' ', self.indent);
|
|
switch (info.capture) {
|
|
.none => {},
|
|
.by_val => try stream.writeAll("by_val "),
|
|
.by_ref => try stream.writeAll("by_ref "),
|
|
}
|
|
if (info.is_inline) try stream.writeAll("inline ");
|
|
|
|
try stream.writeAll("_");
|
|
if (single_item_ref != .none) {
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, single_item_ref);
|
|
}
|
|
for (items) |item_ref| {
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, item_ref);
|
|
}
|
|
|
|
var range_i: usize = 0;
|
|
while (range_i < ranges_len) : (range_i += 1) {
|
|
const item_first: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
const item_last: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, item_first);
|
|
try stream.writeAll("...");
|
|
try self.writeInstRef(stream, item_last);
|
|
}
|
|
|
|
const body = self.code.bodySlice(extra_index, info.body_len);
|
|
extra_index += info.body_len;
|
|
try stream.writeAll(" => ");
|
|
try self.writeBracedBody(stream, body);
|
|
}
|
|
|
|
{
|
|
const scalar_cases_len = extra.data.bits.scalar_cases_len;
|
|
var scalar_i: usize = 0;
|
|
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
|
|
const item_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
const body = self.code.bodySlice(extra_index, info.body_len);
|
|
extra_index += info.body_len;
|
|
|
|
try stream.writeAll(",\n");
|
|
try stream.splatByteAll(' ', self.indent);
|
|
switch (info.capture) {
|
|
.none => {},
|
|
.by_val => try stream.writeAll("by_val "),
|
|
.by_ref => try stream.writeAll("by_ref "),
|
|
}
|
|
if (info.is_inline) try stream.writeAll("inline ");
|
|
try self.writeInstRef(stream, item_ref);
|
|
try stream.writeAll(" => ");
|
|
try self.writeBracedBody(stream, body);
|
|
}
|
|
}
|
|
{
|
|
var multi_i: usize = 0;
|
|
while (multi_i < multi_cases_len) : (multi_i += 1) {
|
|
const items_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
const ranges_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
const info: Zir.Inst.SwitchBlock.ProngInfo = @bitCast(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
const items = self.code.refSlice(extra_index, items_len);
|
|
extra_index += items_len;
|
|
|
|
try stream.writeAll(",\n");
|
|
try stream.splatByteAll(' ', self.indent);
|
|
switch (info.capture) {
|
|
.none => {},
|
|
.by_val => try stream.writeAll("by_val "),
|
|
.by_ref => try stream.writeAll("by_ref "),
|
|
}
|
|
if (info.is_inline) try stream.writeAll("inline ");
|
|
|
|
for (items, 0..) |item_ref, item_i| {
|
|
if (item_i != 0) try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, item_ref);
|
|
}
|
|
|
|
var range_i: usize = 0;
|
|
while (range_i < ranges_len) : (range_i += 1) {
|
|
const item_first: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
const item_last: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]);
|
|
extra_index += 1;
|
|
|
|
if (range_i != 0 or items.len != 0) {
|
|
try stream.writeAll(", ");
|
|
}
|
|
try self.writeInstRef(stream, item_first);
|
|
try stream.writeAll("...");
|
|
try self.writeInstRef(stream, item_last);
|
|
}
|
|
|
|
const body = self.code.bodySlice(extra_index, info.body_len);
|
|
extra_index += info.body_len;
|
|
try stream.writeAll(" => ");
|
|
try self.writeBracedBody(stream, body);
|
|
}
|
|
}
|
|
|
|
self.indent -= 2;
|
|
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writePlNodeField(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
|
|
const name = self.code.nullTerminatedString(extra.field_name_start);
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.print(", \"{f}\") ", .{std.zig.fmtString(name)});
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writePlNodeFieldNamed(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.field_name);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeAs(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.As, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.dest_type);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, extra.operand);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeNode(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const src_node = self.code.instructions.items(.data)[@intFromEnum(inst)].node;
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, src_node);
|
|
}
|
|
|
|
fn writeStrTok(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
) Error!void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
|
|
const str = inst_data.get(self.code);
|
|
try stream.print("\"{f}\") ", .{std.zig.fmtString(str)});
|
|
try self.writeSrcTok(stream, inst_data.src_tok);
|
|
}
|
|
|
|
fn writeStrOp(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].str_op;
|
|
const str = inst_data.getStr(self.code);
|
|
try self.writeInstRef(stream, inst_data.operand);
|
|
try stream.print(", \"{f}\")", .{std.zig.fmtString(str)});
|
|
}
|
|
|
|
fn writeFunc(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inst: Zir.Inst.Index,
|
|
inferred_error_set: bool,
|
|
) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.Func, inst_data.payload_index);
|
|
|
|
var extra_index = extra.end;
|
|
var ret_ty_ref: Zir.Inst.Ref = .none;
|
|
var ret_ty_body: []const Zir.Inst.Index = &.{};
|
|
|
|
switch (extra.data.ret_ty.body_len) {
|
|
0 => {
|
|
ret_ty_ref = .void_type;
|
|
},
|
|
1 => {
|
|
ret_ty_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
},
|
|
else => {
|
|
ret_ty_body = self.code.bodySlice(extra_index, extra.data.ret_ty.body_len);
|
|
extra_index += ret_ty_body.len;
|
|
},
|
|
}
|
|
|
|
const body = self.code.bodySlice(extra_index, extra.data.body_len);
|
|
extra_index += body.len;
|
|
|
|
var src_locs: Zir.Inst.Func.SrcLocs = undefined;
|
|
if (body.len != 0) {
|
|
src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
|
|
}
|
|
return self.writeFuncCommon(
|
|
stream,
|
|
inferred_error_set,
|
|
false,
|
|
false,
|
|
|
|
.none,
|
|
&.{},
|
|
ret_ty_ref,
|
|
ret_ty_body,
|
|
extra.data.ret_ty.is_generic,
|
|
|
|
body,
|
|
inst_data.src_node,
|
|
src_locs,
|
|
0,
|
|
);
|
|
}
|
|
|
|
fn writeFuncFancy(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
|
|
|
|
var extra_index: usize = extra.end;
|
|
var cc_ref: Zir.Inst.Ref = .none;
|
|
var cc_body: []const Zir.Inst.Index = &.{};
|
|
var ret_ty_ref: Zir.Inst.Ref = .none;
|
|
var ret_ty_body: []const Zir.Inst.Index = &.{};
|
|
|
|
if (extra.data.bits.has_cc_body) {
|
|
const body_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
cc_body = self.code.bodySlice(extra_index, body_len);
|
|
extra_index += cc_body.len;
|
|
} else if (extra.data.bits.has_cc_ref) {
|
|
cc_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
}
|
|
if (extra.data.bits.has_ret_ty_body) {
|
|
const body_len = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
ret_ty_body = self.code.bodySlice(extra_index, body_len);
|
|
extra_index += ret_ty_body.len;
|
|
} else if (extra.data.bits.has_ret_ty_ref) {
|
|
ret_ty_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
}
|
|
|
|
const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: {
|
|
const x = self.code.extra[extra_index];
|
|
extra_index += 1;
|
|
break :blk x;
|
|
} else 0;
|
|
|
|
const body = self.code.bodySlice(extra_index, extra.data.body_len);
|
|
extra_index += body.len;
|
|
|
|
var src_locs: Zir.Inst.Func.SrcLocs = undefined;
|
|
if (body.len != 0) {
|
|
src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
|
|
}
|
|
return self.writeFuncCommon(
|
|
stream,
|
|
extra.data.bits.is_inferred_error,
|
|
extra.data.bits.is_var_args,
|
|
extra.data.bits.is_noinline,
|
|
cc_ref,
|
|
cc_body,
|
|
ret_ty_ref,
|
|
ret_ty_body,
|
|
extra.data.bits.ret_ty_is_generic,
|
|
body,
|
|
inst_data.src_node,
|
|
src_locs,
|
|
noalias_bits,
|
|
);
|
|
}
|
|
|
|
fn writeAllocExtended(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const extra = self.code.extraData(Zir.Inst.AllocExtended, extended.operand);
|
|
const small = @as(Zir.Inst.AllocExtended.Small, @bitCast(extended.small));
|
|
|
|
var extra_index: usize = extra.end;
|
|
const type_inst: Zir.Inst.Ref = if (!small.has_type) .none else blk: {
|
|
const type_inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
break :blk type_inst;
|
|
};
|
|
const align_inst: Zir.Inst.Ref = if (!small.has_align) .none else blk: {
|
|
const align_inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
|
|
extra_index += 1;
|
|
break :blk align_inst;
|
|
};
|
|
try self.writeFlag(stream, ",is_const", small.is_const);
|
|
try self.writeFlag(stream, ",is_comptime", small.is_comptime);
|
|
try self.writeOptionalInstRef(stream, ",ty=", type_inst);
|
|
try self.writeOptionalInstRef(stream, ",align=", align_inst);
|
|
try stream.writeAll(")) ");
|
|
try self.writeSrcNode(stream, extra.data.src_node);
|
|
}
|
|
|
|
fn writeTypeofPeer(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const extra = self.code.extraData(Zir.Inst.TypeOfPeer, extended.operand);
|
|
const body = self.code.bodySlice(extra.data.body_index, extra.data.body_len);
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeAll(",[");
|
|
const args = self.code.refSlice(extra.end, extended.small);
|
|
for (args, 0..) |arg, i| {
|
|
if (i != 0) try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, arg);
|
|
}
|
|
try stream.writeAll("])");
|
|
}
|
|
|
|
fn writeBoolBr(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
const extra = self.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);
|
|
const body = self.code.bodySlice(extra.end, extra.data.body_len);
|
|
try self.writeInstRef(stream, extra.data.lhs);
|
|
try stream.writeAll(", ");
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeIntType(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const int_type = self.code.instructions.items(.data)[@intFromEnum(inst)].int_type;
|
|
const prefix: u8 = switch (int_type.signedness) {
|
|
.signed => 'i',
|
|
.unsigned => 'u',
|
|
};
|
|
try stream.print("{c}{d}) ", .{ prefix, int_type.bit_count });
|
|
try self.writeSrcNode(stream, int_type.src_node);
|
|
}
|
|
|
|
fn writeSaveErrRetIndex(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].save_err_ret_index;
|
|
|
|
try self.writeInstRef(stream, inst_data.operand);
|
|
|
|
try stream.writeAll(")");
|
|
}
|
|
|
|
fn writeRestoreErrRetIndex(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const extra = self.code.extraData(Zir.Inst.RestoreErrRetIndex, extended.operand).data;
|
|
|
|
try self.writeInstRef(stream, extra.block);
|
|
try self.writeInstRef(stream, extra.operand);
|
|
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, extra.src_node);
|
|
}
|
|
|
|
fn writeBreak(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"break";
|
|
const extra = self.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;
|
|
|
|
try self.writeInstIndex(stream, extra.block_inst);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, inst_data.operand);
|
|
try stream.writeAll(")");
|
|
}
|
|
|
|
fn writeArrayInit(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
|
|
const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
|
|
const args = self.code.refSlice(extra.end, extra.data.operands_len);
|
|
|
|
try self.writeInstRef(stream, args[0]);
|
|
try stream.writeAll("{");
|
|
for (args[1..], 0..) |arg, i| {
|
|
if (i != 0) try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, arg);
|
|
}
|
|
try stream.writeAll("}) ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeArrayInitAnon(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
|
|
const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
|
|
const args = self.code.refSlice(extra.end, extra.data.operands_len);
|
|
|
|
try stream.writeAll("{");
|
|
for (args, 0..) |arg, i| {
|
|
if (i != 0) try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, arg);
|
|
}
|
|
try stream.writeAll("}) ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeArrayInitSent(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
|
|
|
const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
|
|
const args = self.code.refSlice(extra.end, extra.data.operands_len);
|
|
const sent = args[args.len - 1];
|
|
const elems = args[0 .. args.len - 1];
|
|
|
|
try self.writeInstRef(stream, sent);
|
|
try stream.writeAll(", ");
|
|
|
|
try stream.writeAll(".{");
|
|
for (elems, 0..) |elem, i| {
|
|
if (i != 0) try stream.writeAll(", ");
|
|
try self.writeInstRef(stream, elem);
|
|
}
|
|
try stream.writeAll("}) ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeUnreachable(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"unreachable";
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, inst_data.src_node);
|
|
}
|
|
|
|
fn writeFuncCommon(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
inferred_error_set: bool,
|
|
var_args: bool,
|
|
is_noinline: bool,
|
|
cc_ref: Zir.Inst.Ref,
|
|
cc_body: []const Zir.Inst.Index,
|
|
ret_ty_ref: Zir.Inst.Ref,
|
|
ret_ty_body: []const Zir.Inst.Index,
|
|
ret_ty_is_generic: bool,
|
|
body: []const Zir.Inst.Index,
|
|
src_node: Ast.Node.Offset,
|
|
src_locs: Zir.Inst.Func.SrcLocs,
|
|
noalias_bits: u32,
|
|
) !void {
|
|
try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body);
|
|
if (ret_ty_is_generic) try stream.writeAll("[generic] ");
|
|
try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body);
|
|
try self.writeFlag(stream, "vargs, ", var_args);
|
|
try self.writeFlag(stream, "inferror, ", inferred_error_set);
|
|
try self.writeFlag(stream, "noinline, ", is_noinline);
|
|
|
|
if (noalias_bits != 0) {
|
|
try stream.print("noalias=0b{b}, ", .{noalias_bits});
|
|
}
|
|
|
|
try stream.writeAll("body=");
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeAll(") ");
|
|
if (body.len != 0) {
|
|
try stream.print("(lbrace={d}:{d},rbrace={d}:{d}) ", .{
|
|
src_locs.lbrace_line + 1, @as(u16, @truncate(src_locs.columns)) + 1,
|
|
src_locs.rbrace_line + 1, @as(u16, @truncate(src_locs.columns >> 16)) + 1,
|
|
});
|
|
}
|
|
try self.writeSrcNode(stream, src_node);
|
|
}
|
|
|
|
fn writeDbgStmt(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
|
|
try stream.print("{d}, {d})", .{ inst_data.line + 1, inst_data.column + 1 });
|
|
}
|
|
|
|
fn writeDefer(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].@"defer";
|
|
const body = self.code.bodySlice(inst_data.index, inst_data.len);
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeByte(')');
|
|
}
|
|
|
|
fn writeDeferErrCode(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code;
|
|
const extra = self.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
|
|
|
|
try self.writeInstRef(stream, extra.remapped_err_code.toRef());
|
|
try stream.writeAll(" = ");
|
|
try self.writeInstRef(stream, inst_data.err_code);
|
|
try stream.writeAll(", ");
|
|
const body = self.code.bodySlice(extra.index, extra.len);
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeByte(')');
|
|
}
|
|
|
|
fn writeDeclaration(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const decl = self.code.getDeclaration(inst);
|
|
|
|
const prev_parent_decl_node = self.parent_decl_node;
|
|
defer self.parent_decl_node = prev_parent_decl_node;
|
|
self.parent_decl_node = decl.src_node;
|
|
|
|
if (decl.is_pub) try stream.writeAll("pub ");
|
|
switch (decl.linkage) {
|
|
.normal => {},
|
|
.@"export" => try stream.writeAll("export "),
|
|
.@"extern" => try stream.writeAll("extern "),
|
|
}
|
|
switch (decl.kind) {
|
|
.@"comptime" => try stream.writeAll("comptime"),
|
|
.unnamed_test => try stream.writeAll("test"),
|
|
.@"test", .decltest, .@"const", .@"var" => {
|
|
try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) });
|
|
},
|
|
}
|
|
const src_hash = self.code.getAssociatedSrcHash(inst).?;
|
|
try stream.print(" line({d}) column({d}) hash({x})", .{
|
|
decl.src_line, decl.src_column, &src_hash,
|
|
});
|
|
|
|
{
|
|
if (decl.type_body) |b| {
|
|
try stream.writeAll(" type=");
|
|
try self.writeBracedDecl(stream, b);
|
|
}
|
|
|
|
if (decl.align_body) |b| {
|
|
try stream.writeAll(" align=");
|
|
try self.writeBracedDecl(stream, b);
|
|
}
|
|
|
|
if (decl.linksection_body) |b| {
|
|
try stream.writeAll(" linksection=");
|
|
try self.writeBracedDecl(stream, b);
|
|
}
|
|
|
|
if (decl.addrspace_body) |b| {
|
|
try stream.writeAll(" addrspace=");
|
|
try self.writeBracedDecl(stream, b);
|
|
}
|
|
|
|
if (decl.value_body) |b| {
|
|
try stream.writeAll(" value=");
|
|
try self.writeBracedDecl(stream, b);
|
|
}
|
|
}
|
|
|
|
try stream.writeAll(") ");
|
|
try self.writeSrcNode(stream, .zero);
|
|
}
|
|
|
|
fn writeClosureGet(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
try stream.print("{d})) ", .{extended.small});
|
|
const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
|
|
try self.writeSrcNode(stream, src_node);
|
|
}
|
|
|
|
fn writeBuiltinValue(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
|
|
try stream.print("{s})) ", .{@tagName(val)});
|
|
const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
|
|
try self.writeSrcNode(stream, src_node);
|
|
}
|
|
|
|
fn writeInplaceArithResultTy(self: *Writer, stream: *std.io.Writer, extended: Zir.Inst.Extended.InstData) !void {
|
|
const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small);
|
|
try self.writeInstRef(stream, @enumFromInt(extended.operand));
|
|
try stream.print(", {s}))", .{@tagName(op)});
|
|
}
|
|
|
|
fn writeInstRef(self: *Writer, stream: *std.io.Writer, ref: Zir.Inst.Ref) !void {
|
|
if (ref == .none) {
|
|
return stream.writeAll(".none");
|
|
} else if (ref.toIndex()) |i| {
|
|
return self.writeInstIndex(stream, i);
|
|
} else {
|
|
const val: InternPool.Index = @enumFromInt(@intFromEnum(ref));
|
|
return stream.print("@{s}", .{@tagName(val)});
|
|
}
|
|
}
|
|
|
|
fn writeInstIndex(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
_ = self;
|
|
return stream.print("%{d}", .{@intFromEnum(inst)});
|
|
}
|
|
|
|
fn writeCaptures(self: *Writer, stream: *std.io.Writer, extra_index: usize, captures_len: u32) !usize {
|
|
if (captures_len == 0) {
|
|
try stream.writeAll("{}");
|
|
return extra_index;
|
|
}
|
|
|
|
const captures: []const Zir.Inst.Capture = @ptrCast(self.code.extra[extra_index..][0..captures_len]);
|
|
const capture_names: []const Zir.NullTerminatedString = @ptrCast(self.code.extra[extra_index + captures_len ..][0..captures_len]);
|
|
for (captures, capture_names) |capture, name| {
|
|
try stream.writeAll("{ ");
|
|
if (name != .empty) {
|
|
const name_slice = self.code.nullTerminatedString(name);
|
|
try stream.print("{s} = ", .{name_slice});
|
|
}
|
|
try self.writeCapture(stream, capture);
|
|
}
|
|
|
|
return extra_index + 2 * captures_len;
|
|
}
|
|
|
|
fn writeCapture(self: *Writer, stream: *std.io.Writer, capture: Zir.Inst.Capture) !void {
|
|
switch (capture.unwrap()) {
|
|
.nested => |i| return stream.print("[{d}]", .{i}),
|
|
.instruction => |inst| return self.writeInstIndex(stream, inst),
|
|
.instruction_load => |ptr_inst| {
|
|
try stream.writeAll("load ");
|
|
try self.writeInstIndex(stream, ptr_inst);
|
|
},
|
|
.decl_val => |str| try stream.print("decl_val \"{f}\"", .{
|
|
std.zig.fmtString(self.code.nullTerminatedString(str)),
|
|
}),
|
|
.decl_ref => |str| try stream.print("decl_ref \"{f}\"", .{
|
|
std.zig.fmtString(self.code.nullTerminatedString(str)),
|
|
}),
|
|
}
|
|
}
|
|
|
|
fn writeOptionalInstRef(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
prefix: []const u8,
|
|
inst: Zir.Inst.Ref,
|
|
) !void {
|
|
if (inst == .none) return;
|
|
try stream.writeAll(prefix);
|
|
try self.writeInstRef(stream, inst);
|
|
}
|
|
|
|
fn writeOptionalInstRefOrBody(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
prefix: []const u8,
|
|
ref: Zir.Inst.Ref,
|
|
body: []const Zir.Inst.Index,
|
|
) !void {
|
|
if (body.len != 0) {
|
|
try stream.writeAll(prefix);
|
|
try self.writeBracedBody(stream, body);
|
|
try stream.writeAll(", ");
|
|
} else if (ref != .none) {
|
|
try stream.writeAll(prefix);
|
|
try self.writeInstRef(stream, ref);
|
|
try stream.writeAll(", ");
|
|
}
|
|
}
|
|
|
|
fn writeFlag(
|
|
self: *Writer,
|
|
stream: *std.io.Writer,
|
|
name: []const u8,
|
|
flag: bool,
|
|
) !void {
|
|
_ = self;
|
|
if (!flag) return;
|
|
try stream.writeAll(name);
|
|
}
|
|
|
|
fn writeSrcNode(self: *Writer, stream: *std.io.Writer, src_node: Ast.Node.Offset) !void {
|
|
const tree = self.tree orelse return;
|
|
const abs_node = src_node.toAbsolute(self.parent_decl_node);
|
|
const src_span = tree.nodeToSpan(abs_node);
|
|
const start = self.line_col_cursor.find(tree.source, src_span.start);
|
|
const end = self.line_col_cursor.find(tree.source, src_span.end);
|
|
try stream.print("node_offset:{d}:{d} to :{d}:{d}", .{
|
|
start.line + 1, start.column + 1,
|
|
end.line + 1, end.column + 1,
|
|
});
|
|
}
|
|
|
|
fn writeSrcTok(self: *Writer, stream: *std.io.Writer, src_tok: Ast.TokenOffset) !void {
|
|
const tree = self.tree orelse return;
|
|
const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));
|
|
const span_start = tree.tokenStart(abs_tok);
|
|
const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len));
|
|
const start = self.line_col_cursor.find(tree.source, span_start);
|
|
const end = self.line_col_cursor.find(tree.source, span_end);
|
|
try stream.print("token_offset:{d}:{d} to :{d}:{d}", .{
|
|
start.line + 1, start.column + 1,
|
|
end.line + 1, end.column + 1,
|
|
});
|
|
}
|
|
|
|
fn writeSrcTokAbs(self: *Writer, stream: *std.io.Writer, src_tok: Ast.TokenIndex) !void {
|
|
const tree = self.tree orelse return;
|
|
const span_start = tree.tokenStart(src_tok);
|
|
const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));
|
|
const start = self.line_col_cursor.find(tree.source, span_start);
|
|
const end = self.line_col_cursor.find(tree.source, span_end);
|
|
try stream.print("token_abs:{d}:{d} to :{d}:{d}", .{
|
|
start.line + 1, start.column + 1,
|
|
end.line + 1, end.column + 1,
|
|
});
|
|
}
|
|
|
|
fn writeBracedDecl(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
|
|
try self.writeBracedBodyConditional(stream, body, self.recurse_decls);
|
|
}
|
|
|
|
fn writeBracedBody(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
|
|
try self.writeBracedBodyConditional(stream, body, self.recurse_blocks);
|
|
}
|
|
|
|
fn writeBracedBodyConditional(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index, enabled: bool) !void {
|
|
if (body.len == 0) {
|
|
try stream.writeAll("{}");
|
|
} else if (enabled) {
|
|
try stream.writeAll("{\n");
|
|
self.indent += 2;
|
|
try self.writeBody(stream, body);
|
|
self.indent -= 2;
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.writeAll("}");
|
|
} else if (body.len == 1) {
|
|
try stream.writeByte('{');
|
|
try self.writeInstIndex(stream, body[0]);
|
|
try stream.writeByte('}');
|
|
} else if (body.len == 2) {
|
|
try stream.writeByte('{');
|
|
try self.writeInstIndex(stream, body[0]);
|
|
try stream.writeAll(", ");
|
|
try self.writeInstIndex(stream, body[1]);
|
|
try stream.writeByte('}');
|
|
} else {
|
|
try stream.writeByte('{');
|
|
try self.writeInstIndex(stream, body[0]);
|
|
try stream.writeAll("..");
|
|
try self.writeInstIndex(stream, body[body.len - 1]);
|
|
try stream.writeByte('}');
|
|
}
|
|
}
|
|
|
|
fn writeBody(self: *Writer, stream: *std.io.Writer, body: []const Zir.Inst.Index) !void {
|
|
for (body) |inst| {
|
|
try stream.splatByteAll(' ', self.indent);
|
|
try stream.print("%{d} ", .{@intFromEnum(inst)});
|
|
try self.writeInstToStream(stream, inst);
|
|
try stream.writeByte('\n');
|
|
}
|
|
}
|
|
|
|
fn writeImport(self: *Writer, stream: *std.io.Writer, inst: Zir.Inst.Index) !void {
|
|
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
|
|
const extra = self.code.extraData(Zir.Inst.Import, inst_data.payload_index).data;
|
|
try self.writeInstRef(stream, extra.res_ty);
|
|
const import_path = self.code.nullTerminatedString(extra.path);
|
|
try stream.print(", \"{f}\") ", .{std.zig.fmtString(import_path)});
|
|
try self.writeSrcTok(stream, inst_data.src_tok);
|
|
}
|
|
};
|