/* * Copyright (c) 2016 Andrew Kelley * * This file is part of zig, which is MIT licensed. * See http://opensource.org/licenses/MIT */ #include "analyze.hpp" #include "ir.hpp" #include "ir_print.hpp" #include "os.hpp" struct IrPrint { CodeGen *codegen; FILE *f; int indent; int indent_size; }; static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction); static void ir_print_indent(IrPrint *irp) { for (int i = 0; i < irp->indent; i += 1) { fprintf(irp->f, " "); } } static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) { ir_print_indent(irp); const char *type_name = instruction->value.type ? buf_ptr(&instruction->value.type->name) : "(unknown)"; const char *ref_count = ir_has_side_effects(instruction) ? "-" : buf_ptr(buf_sprintf("%" ZIG_PRI_usize "", instruction->ref_count)); fprintf(irp->f, "#%-3zu| %-12s| %-2s| ", instruction->debug_id, type_name, ref_count); } static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) { Buf buf = BUF_INIT; buf_resize(&buf, 0); render_const_value(irp->codegen, &buf, const_val); fprintf(irp->f, "%s", buf_ptr(&buf)); } static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) { fprintf(irp->f, "#%" ZIG_PRI_usize "", instruction->debug_id); } static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) { if (instruction == nullptr) { fprintf(irp->f, "(null)"); return; } if (instruction->value.special != ConstValSpecialRuntime) { ir_print_const_value(irp, &instruction->value); } else { ir_print_var_instruction(irp, instruction); } } static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) { fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id); } static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) { assert(return_instruction->value); fprintf(irp->f, "return "); ir_print_other_instruction(irp, return_instruction->value); } static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) { ir_print_const_value(irp, &const_instruction->base.value); } static const char *ir_bin_op_id_str(IrBinOp op_id) { switch (op_id) { case IrBinOpInvalid: zig_unreachable(); case IrBinOpBoolOr: return "BoolOr"; case IrBinOpBoolAnd: return "BoolAnd"; case IrBinOpCmpEq: return "=="; case IrBinOpCmpNotEq: return "!="; case IrBinOpCmpLessThan: return "<"; case IrBinOpCmpGreaterThan: return ">"; case IrBinOpCmpLessOrEq: return "<="; case IrBinOpCmpGreaterOrEq: return ">="; case IrBinOpBinOr: return "|"; case IrBinOpBinXor: return "^"; case IrBinOpBinAnd: return "&"; case IrBinOpBitShiftLeftLossy: return "<<"; case IrBinOpBitShiftLeftExact: return "@shlExact"; case IrBinOpBitShiftRightLossy: return ">>"; case IrBinOpBitShiftRightExact: return "@shrExact"; case IrBinOpAdd: return "+"; case IrBinOpAddWrap: return "+%"; case IrBinOpSub: return "-"; case IrBinOpSubWrap: return "-%"; case IrBinOpMult: return "*"; case IrBinOpMultWrap: return "*%"; case IrBinOpDivUnspecified: return "/"; case IrBinOpDivTrunc: return "@divTrunc"; case IrBinOpDivFloor: return "@divFloor"; case IrBinOpDivExact: return "@divExact"; case IrBinOpRemUnspecified: return "%"; case IrBinOpRemRem: return "@rem"; case IrBinOpRemMod: return "@mod"; case IrBinOpArrayCat: return "++"; case IrBinOpArrayMult: return "**"; case IrBinOpMergeErrorSets: return "||"; } zig_unreachable(); } static const char *ir_un_op_id_str(IrUnOp op_id) { switch (op_id) { case IrUnOpInvalid: zig_unreachable(); case IrUnOpBinNot: return "~"; case IrUnOpNegation: return "-"; case IrUnOpNegationWrap: return "-%"; case IrUnOpDereference: return "*"; case IrUnOpOptional: return "?"; } zig_unreachable(); } static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) { fprintf(irp->f, "%s ", ir_un_op_id_str(un_op_instruction->op_id)); ir_print_other_instruction(irp, un_op_instruction->value); } static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) { ir_print_other_instruction(irp, bin_op_instruction->op1); fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id)); ir_print_other_instruction(irp, bin_op_instruction->op2); if (!bin_op_instruction->safety_check_on) { fprintf(irp->f, " // no safety"); } } static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) { const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; const char *name = buf_ptr(&decl_var_instruction->var->name); if (decl_var_instruction->var_type) { fprintf(irp->f, "%s %s: ", var_or_const, name); ir_print_other_instruction(irp, decl_var_instruction->var_type); fprintf(irp->f, " "); } else { fprintf(irp->f, "%s %s ", var_or_const, name); } if (decl_var_instruction->align_value) { fprintf(irp->f, "align "); ir_print_other_instruction(irp, decl_var_instruction->align_value); fprintf(irp->f, " "); } fprintf(irp->f, "= "); ir_print_other_instruction(irp, decl_var_instruction->init_value); if (decl_var_instruction->var->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime); } } static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) { fprintf(irp->f, "cast "); ir_print_other_instruction(irp, cast_instruction->value); fprintf(irp->f, " to %s", buf_ptr(&cast_instruction->dest_type->name)); } static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) { if (call_instruction->is_async) { fprintf(irp->f, "async"); if (call_instruction->async_allocator != nullptr) { fprintf(irp->f, "<"); ir_print_other_instruction(irp, call_instruction->async_allocator); fprintf(irp->f, ">"); } fprintf(irp->f, " "); } if (call_instruction->fn_entry) { fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name)); } else { assert(call_instruction->fn_ref); ir_print_other_instruction(irp, call_instruction->fn_ref); } fprintf(irp->f, "("); for (size_t i = 0; i < call_instruction->arg_count; i += 1) { IrInstruction *arg = call_instruction->args[i]; if (i != 0) fprintf(irp->f, ", "); ir_print_other_instruction(irp, arg); } fprintf(irp->f, ")"); } static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) { fprintf(irp->f, "if ("); ir_print_other_instruction(irp, cond_br_instruction->condition); fprintf(irp->f, ") "); ir_print_other_block(irp, cond_br_instruction->then_block); fprintf(irp->f, " else "); ir_print_other_block(irp, cond_br_instruction->else_block); if (cond_br_instruction->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); ir_print_other_instruction(irp, cond_br_instruction->is_comptime); } } static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) { fprintf(irp->f, "goto "); ir_print_other_block(irp, br_instruction->dest_block); if (br_instruction->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); ir_print_other_instruction(irp, br_instruction->is_comptime); } } static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) { assert(phi_instruction->incoming_count != 0); assert(phi_instruction->incoming_count != SIZE_MAX); for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i]; IrInstruction *incoming_value = phi_instruction->incoming_values[i]; if (i != 0) fprintf(irp->f, " "); ir_print_other_block(irp, incoming_block); fprintf(irp->f, ":"); ir_print_other_instruction(irp, incoming_value); } } static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) { ir_print_other_instruction(irp, instruction->container_type); fprintf(irp->f, "{"); if (instruction->item_count > 50) { fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count); } else { for (size_t i = 0; i < instruction->item_count; i += 1) { IrInstruction *item = instruction->items[i]; if (i != 0) fprintf(irp->f, ", "); ir_print_other_instruction(irp, item); } } fprintf(irp->f, "}"); } static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) { ir_print_other_instruction(irp, instruction->container_type); fprintf(irp->f, "{"); for (size_t i = 0; i < instruction->field_count; i += 1) { IrInstructionContainerInitFieldsField *field = &instruction->fields[i]; const char *comma = (i == 0) ? "" : ", "; fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name)); ir_print_other_instruction(irp, field->value); } fprintf(irp->f, "} // container init"); } static void ir_print_struct_init(IrPrint *irp, IrInstructionStructInit *instruction) { fprintf(irp->f, "%s {", buf_ptr(&instruction->struct_type->name)); for (size_t i = 0; i < instruction->field_count; i += 1) { IrInstructionStructInitField *field = &instruction->fields[i]; Buf *field_name = field->type_struct_field->name; const char *comma = (i == 0) ? "" : ", "; fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field_name)); ir_print_other_instruction(irp, field->value); } fprintf(irp->f, "} // struct init"); } static void ir_print_union_init(IrPrint *irp, IrInstructionUnionInit *instruction) { Buf *field_name = instruction->field->enum_field->name; fprintf(irp->f, "%s {", buf_ptr(&instruction->union_type->name)); fprintf(irp->f, ".%s = ", buf_ptr(field_name)); ir_print_other_instruction(irp, instruction->init_value); fprintf(irp->f, "} // union init"); } static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) { fprintf(irp->f, "unreachable"); } static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) { fprintf(irp->f, "&"); ir_print_other_instruction(irp, instruction->array_ptr); fprintf(irp->f, "["); ir_print_other_instruction(irp, instruction->elem_index); fprintf(irp->f, "]"); if (!instruction->safety_check_on) { fprintf(irp->f, " // no safety"); } } static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) { fprintf(irp->f, "&%s", buf_ptr(&instruction->var->name)); } static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ".*"); } static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) { ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ".*"); } static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { fprintf(irp->f, "*"); ir_print_var_instruction(irp, instruction->ptr); fprintf(irp->f, " = "); ir_print_other_instruction(irp, instruction->value); } static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) { fprintf(irp->f, "@typeOf("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_to_ptr_type(IrPrint *irp, IrInstructionToPtrType *instruction) { fprintf(irp->f, "@toPtrType("); ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ")"); } static void ir_print_ptr_type_child(IrPrint *irp, IrInstructionPtrTypeChild *instruction) { fprintf(irp->f, "@ptrTypeChild("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) { if (instruction->field_name_buffer) { fprintf(irp->f, "fieldptr "); ir_print_other_instruction(irp, instruction->container_ptr); fprintf(irp->f, ".%s", buf_ptr(instruction->field_name_buffer)); } else { assert(instruction->field_name_expr); fprintf(irp->f, "@field("); ir_print_other_instruction(irp, instruction->container_ptr); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->field_name_expr); fprintf(irp->f, ")"); } } static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) { fprintf(irp->f, "@StructFieldPtr(&"); ir_print_other_instruction(irp, instruction->struct_ptr); fprintf(irp->f, ".%s", buf_ptr(instruction->field->name)); fprintf(irp->f, ")"); } static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) { fprintf(irp->f, "@UnionFieldPtr(&"); ir_print_other_instruction(irp, instruction->union_ptr); fprintf(irp->f, ".%s", buf_ptr(instruction->field->enum_field->name)); fprintf(irp->f, ")"); } static void ir_print_set_cold(IrPrint *irp, IrInstructionSetCold *instruction) { fprintf(irp->f, "@setCold("); ir_print_other_instruction(irp, instruction->is_cold); fprintf(irp->f, ")"); } static void ir_print_set_runtime_safety(IrPrint *irp, IrInstructionSetRuntimeSafety *instruction) { fprintf(irp->f, "@setRuntimeSafety("); ir_print_other_instruction(irp, instruction->safety_on); fprintf(irp->f, ")"); } static void ir_print_set_float_mode(IrPrint *irp, IrInstructionSetFloatMode *instruction) { fprintf(irp->f, "@setFloatMode("); ir_print_other_instruction(irp, instruction->scope_value); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->mode_value); fprintf(irp->f, ")"); } static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) { fprintf(irp->f, "["); ir_print_other_instruction(irp, instruction->size); fprintf(irp->f, "]"); ir_print_other_instruction(irp, instruction->child_type); } static void ir_print_promise_type(IrPrint *irp, IrInstructionPromiseType *instruction) { fprintf(irp->f, "promise"); if (instruction->payload_type != nullptr) { fprintf(irp->f, "->"); ir_print_other_instruction(irp, instruction->payload_type); } } static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) { const char *const_kw = instruction->is_const ? "const " : ""; fprintf(irp->f, "[]%s", const_kw); ir_print_other_instruction(irp, instruction->child_type); } static void ir_print_global_asm(IrPrint *irp, IrInstructionGlobalAsm *instruction) { fprintf(irp->f, "asm(\"%s\")", buf_ptr(instruction->asm_code)); } static void ir_print_asm(IrPrint *irp, IrInstructionAsm *instruction) { assert(instruction->base.source_node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr; const char *volatile_kw = instruction->has_side_effects ? " volatile" : ""; fprintf(irp->f, "asm%s (\"%s\") : ", volatile_kw, buf_ptr(instruction->asm_template)); for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { AsmOutput *asm_output = asm_expr->output_list.at(i); if (i != 0) fprintf(irp->f, ", "); fprintf(irp->f, "[%s] \"%s\" (", buf_ptr(asm_output->asm_symbolic_name), buf_ptr(asm_output->constraint)); if (asm_output->return_type) { fprintf(irp->f, "-> "); ir_print_other_instruction(irp, instruction->output_types[i]); } else { fprintf(irp->f, "%s", buf_ptr(asm_output->variable_name)); } fprintf(irp->f, ")"); } fprintf(irp->f, " : "); for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { AsmInput *asm_input = asm_expr->input_list.at(i); if (i != 0) fprintf(irp->f, ", "); fprintf(irp->f, "[%s] \"%s\" (", buf_ptr(asm_input->asm_symbolic_name), buf_ptr(asm_input->constraint)); ir_print_other_instruction(irp, instruction->input_list[i]); fprintf(irp->f, ")"); } fprintf(irp->f, " : "); for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) { Buf *reg_name = asm_expr->clobber_list.at(i); if (i != 0) fprintf(irp->f, ", "); fprintf(irp->f, "\"%s\"", buf_ptr(reg_name)); } fprintf(irp->f, ")"); } static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { fprintf(irp->f, "@sizeOf("); ir_print_other_instruction(irp, instruction->type_value); fprintf(irp->f, ")"); } static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) { ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, " != null"); } static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) { fprintf(irp->f, "&"); ir_print_other_instruction(irp, instruction->base_ptr); fprintf(irp->f, ".*.?"); if (!instruction->safety_check_on) { fprintf(irp->f, " // no safety"); } } static void ir_print_clz(IrPrint *irp, IrInstructionClz *instruction) { fprintf(irp->f, "@clz("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) { fprintf(irp->f, "@ctz("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_pop_count(IrPrint *irp, IrInstructionPopCount *instruction) { fprintf(irp->f, "@popCount("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction) { fprintf(irp->f, "switch ("); ir_print_other_instruction(irp, instruction->target_value); fprintf(irp->f, ") "); for (size_t i = 0; i < instruction->case_count; i += 1) { IrInstructionSwitchBrCase *this_case = &instruction->cases[i]; ir_print_other_instruction(irp, this_case->value); fprintf(irp->f, " => "); ir_print_other_block(irp, this_case->block); fprintf(irp->f, ", "); } fprintf(irp->f, "else => "); ir_print_other_block(irp, instruction->else_block); if (instruction->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); ir_print_other_instruction(irp, instruction->is_comptime); } } static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instruction) { fprintf(irp->f, "switchvar "); ir_print_other_instruction(irp, instruction->target_value_ptr); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->prong_value); } static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *instruction) { fprintf(irp->f, "switchtarget "); ir_print_other_instruction(irp, instruction->target_value_ptr); } static void ir_print_union_tag(IrPrint *irp, IrInstructionUnionTag *instruction) { fprintf(irp->f, "uniontag "); ir_print_other_instruction(irp, instruction->value); } static void ir_print_import(IrPrint *irp, IrInstructionImport *instruction) { fprintf(irp->f, "@import("); ir_print_other_instruction(irp, instruction->name); fprintf(irp->f, ")"); } static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) { const char *const_str = instruction->is_const ? "const " : ""; const char *volatile_str = instruction->is_volatile ? "volatile " : ""; fprintf(irp->f, "%s%sref ", const_str, volatile_str); ir_print_other_instruction(irp, instruction->value); } static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruction) { fprintf(irp->f, "@compileError("); ir_print_other_instruction(irp, instruction->msg); fprintf(irp->f, ")"); } static void ir_print_compile_log(IrPrint *irp, IrInstructionCompileLog *instruction) { fprintf(irp->f, "@compileLog("); for (size_t i = 0; i < instruction->msg_count; i += 1) { if (i != 0) fprintf(irp->f, ","); IrInstruction *msg = instruction->msg_list[i]; ir_print_other_instruction(irp, msg); } fprintf(irp->f, ")"); } static void ir_print_err_name(IrPrint *irp, IrInstructionErrName *instruction) { fprintf(irp->f, "@errorName("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_c_import(IrPrint *irp, IrInstructionCImport *instruction) { fprintf(irp->f, "@cImport(...)"); } static void ir_print_c_include(IrPrint *irp, IrInstructionCInclude *instruction) { fprintf(irp->f, "@cInclude("); ir_print_other_instruction(irp, instruction->name); fprintf(irp->f, ")"); } static void ir_print_c_define(IrPrint *irp, IrInstructionCDefine *instruction) { fprintf(irp->f, "@cDefine("); ir_print_other_instruction(irp, instruction->name); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_c_undef(IrPrint *irp, IrInstructionCUndef *instruction) { fprintf(irp->f, "@cUndef("); ir_print_other_instruction(irp, instruction->name); fprintf(irp->f, ")"); } static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instruction) { fprintf(irp->f, "@embedFile("); ir_print_other_instruction(irp, instruction->name); fprintf(irp->f, ")"); } static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) { fprintf(irp->f, "@cmpxchg("); ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->cmp_value); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->new_value); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->success_order_value); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->failure_order_value); fprintf(irp->f, ")"); } static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) { fprintf(irp->f, "@cmpxchg("); ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->cmp_value); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->new_value); fprintf(irp->f, ", TODO print atomic orders)"); } static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) { fprintf(irp->f, "@fence("); ir_print_other_instruction(irp, instruction->order_value); fprintf(irp->f, ")"); } static void ir_print_truncate(IrPrint *irp, IrInstructionTruncate *instruction) { fprintf(irp->f, "@truncate("); ir_print_other_instruction(irp, instruction->dest_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_int_cast(IrPrint *irp, IrInstructionIntCast *instruction) { fprintf(irp->f, "@intCast("); ir_print_other_instruction(irp, instruction->dest_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_float_cast(IrPrint *irp, IrInstructionFloatCast *instruction) { fprintf(irp->f, "@floatCast("); ir_print_other_instruction(irp, instruction->dest_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_err_set_cast(IrPrint *irp, IrInstructionErrSetCast *instruction) { fprintf(irp->f, "@errSetCast("); ir_print_other_instruction(irp, instruction->dest_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_from_bytes(IrPrint *irp, IrInstructionFromBytes *instruction) { fprintf(irp->f, "@bytesToSlice("); ir_print_other_instruction(irp, instruction->dest_child_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_to_bytes(IrPrint *irp, IrInstructionToBytes *instruction) { fprintf(irp->f, "@sliceToBytes("); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) { fprintf(irp->f, "@intToFloat("); ir_print_other_instruction(irp, instruction->dest_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_float_to_int(IrPrint *irp, IrInstructionFloatToInt *instruction) { fprintf(irp->f, "@floatToInt("); ir_print_other_instruction(irp, instruction->dest_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_bool_to_int(IrPrint *irp, IrInstructionBoolToInt *instruction) { fprintf(irp->f, "@boolToInt("); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) { fprintf(irp->f, "@IntType("); ir_print_other_instruction(irp, instruction->is_signed); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->bit_count); fprintf(irp->f, ")"); } static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruction) { fprintf(irp->f, "@Vector("); ir_print_other_instruction(irp, instruction->len); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->elem_type); fprintf(irp->f, ")"); } static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) { fprintf(irp->f, "! "); ir_print_other_instruction(irp, instruction->value); } static void ir_print_memset(IrPrint *irp, IrInstructionMemset *instruction) { fprintf(irp->f, "@memset("); ir_print_other_instruction(irp, instruction->dest_ptr); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->byte); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->count); fprintf(irp->f, ")"); } static void ir_print_memcpy(IrPrint *irp, IrInstructionMemcpy *instruction) { fprintf(irp->f, "@memcpy("); ir_print_other_instruction(irp, instruction->dest_ptr); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->src_ptr); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->count); fprintf(irp->f, ")"); } static void ir_print_slice(IrPrint *irp, IrInstructionSlice *instruction) { ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, "["); ir_print_other_instruction(irp, instruction->start); fprintf(irp->f, ".."); if (instruction->end) ir_print_other_instruction(irp, instruction->end); fprintf(irp->f, "]"); } static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) { fprintf(irp->f, "@memberCount("); ir_print_other_instruction(irp, instruction->container); fprintf(irp->f, ")"); } static void ir_print_member_type(IrPrint *irp, IrInstructionMemberType *instruction) { fprintf(irp->f, "@memberType("); ir_print_other_instruction(irp, instruction->container_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->member_index); fprintf(irp->f, ")"); } static void ir_print_member_name(IrPrint *irp, IrInstructionMemberName *instruction) { fprintf(irp->f, "@memberName("); ir_print_other_instruction(irp, instruction->container_type); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->member_index); fprintf(irp->f, ")"); } static void ir_print_breakpoint(IrPrint *irp, IrInstructionBreakpoint *instruction) { fprintf(irp->f, "@breakpoint()"); } static void ir_print_frame_address(IrPrint *irp, IrInstructionFrameAddress *instruction) { fprintf(irp->f, "@frameAddress()"); } static void ir_print_handle(IrPrint *irp, IrInstructionHandle *instruction) { fprintf(irp->f, "@handle()"); } static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) { fprintf(irp->f, "@returnAddress()"); } static void ir_print_align_of(IrPrint *irp, IrInstructionAlignOf *instruction) { fprintf(irp->f, "@alignOf("); ir_print_other_instruction(irp, instruction->type_value); fprintf(irp->f, ")"); } static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruction) { switch (instruction->op) { case IrOverflowOpAdd: fprintf(irp->f, "@addWithOverflow("); break; case IrOverflowOpSub: fprintf(irp->f, "@subWithOverflow("); break; case IrOverflowOpMul: fprintf(irp->f, "@mulWithOverflow("); break; case IrOverflowOpShl: fprintf(irp->f, "@shlWithOverflow("); break; } ir_print_other_instruction(irp, instruction->type_value); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->op1); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->op2); fprintf(irp->f, ", "); ir_print_other_instruction(irp, instruction->result_ptr); fprintf(irp->f, ")"); } static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) { fprintf(irp->f, "@testError("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) { fprintf(irp->f, "UnwrapErrorCode("); ir_print_other_instruction(irp, instruction->err_union); fprintf(irp->f, ")"); } static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) { fprintf(irp->f, "ErrorUnionFieldPayload("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); if (!instruction->safety_check_on) { fprintf(irp->f, " // no safety"); } } static void ir_print_maybe_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) { fprintf(irp->f, "@maybeWrap("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) { fprintf(irp->f, "@errWrapCode("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) { fprintf(irp->f, "@errWrapPayload("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) { fprintf(irp->f, "fn("); for (size_t i = 0; i < instruction->base.source_node->data.fn_proto.params.length; i += 1) { if (i != 0) fprintf(irp->f, ","); if (instruction->is_var_args && i == instruction->base.source_node->data.fn_proto.params.length - 1) { fprintf(irp->f, "..."); } else { ir_print_other_instruction(irp, instruction->param_types[i]); } } fprintf(irp->f, ")"); if (instruction->align_value != nullptr) { fprintf(irp->f, " align "); ir_print_other_instruction(irp, instruction->align_value); fprintf(irp->f, " "); } fprintf(irp->f, "->"); ir_print_other_instruction(irp, instruction->return_type); } static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *instruction) { fprintf(irp->f, "@testComptime("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) { fprintf(irp->f, "@ptrCast("); if (instruction->dest_type) { ir_print_other_instruction(irp, instruction->dest_type); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ")"); } static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) { fprintf(irp->f, "@ptrCast("); ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ")"); } static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { fprintf(irp->f, "@bitCast("); ir_print_other_instruction(irp, instruction->dest_type); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) { fprintf(irp->f, "@bitCast("); ir_print_other_instruction(irp, instruction->operand); fprintf(irp->f, ")"); } static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) { fprintf(irp->f, "WidenOrShorten("); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_ptr_to_int(IrPrint *irp, IrInstructionPtrToInt *instruction) { fprintf(irp->f, "@ptrToInt("); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction) { fprintf(irp->f, "@intToPtr("); if (instruction->dest_type == nullptr) { fprintf(irp->f, "(null)"); } else { ir_print_other_instruction(irp, instruction->dest_type); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) { fprintf(irp->f, "@intToEnum("); if (instruction->dest_type == nullptr) { fprintf(irp->f, "(null)"); } else { ir_print_other_instruction(irp, instruction->dest_type); } ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_enum_to_int(IrPrint *irp, IrInstructionEnumToInt *instruction) { fprintf(irp->f, "@enumToInt("); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntimeScope *instruction) { fprintf(irp->f, "@checkRuntimeScope("); ir_print_other_instruction(irp, instruction->scope_is_comptime); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->is_comptime); fprintf(irp->f, ")"); } static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) { fprintf(irp->f, "ArrayToVector("); ir_print_other_instruction(irp, instruction->array); fprintf(irp->f, ")"); } static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) { fprintf(irp->f, "VectorToArray("); ir_print_other_instruction(irp, instruction->vector); fprintf(irp->f, ")"); } static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) { fprintf(irp->f, "AssertZero("); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) { fprintf(irp->f, "@resizeSlice("); ir_print_other_instruction(irp, instruction->operand); fprintf(irp->f, ")"); } static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { fprintf(irp->f, "inttoerr "); ir_print_other_instruction(irp, instruction->target); } static void ir_print_err_to_int(IrPrint *irp, IrInstructionErrToInt *instruction) { fprintf(irp->f, "errtoint "); ir_print_other_instruction(irp, instruction->target); } static void ir_print_check_switch_prongs(IrPrint *irp, IrInstructionCheckSwitchProngs *instruction) { fprintf(irp->f, "@checkSwitchProngs("); ir_print_other_instruction(irp, instruction->target_value); fprintf(irp->f, ","); for (size_t i = 0; i < instruction->range_count; i += 1) { if (i != 0) fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->ranges[i].start); fprintf(irp->f, "..."); ir_print_other_instruction(irp, instruction->ranges[i].end); } const char *have_else_str = instruction->have_else_prong ? "yes" : "no"; fprintf(irp->f, ")else:%s", have_else_str); } static void ir_print_check_statement_is_void(IrPrint *irp, IrInstructionCheckStatementIsVoid *instruction) { fprintf(irp->f, "@checkStatementIsVoid("); ir_print_other_instruction(irp, instruction->statement_value); fprintf(irp->f, ")"); } static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction) { fprintf(irp->f, "typename "); ir_print_other_instruction(irp, instruction->type_value); } static void ir_print_tag_name(IrPrint *irp, IrInstructionTagName *instruction) { fprintf(irp->f, "tagname "); ir_print_other_instruction(irp, instruction->target); } static void ir_print_ptr_type(IrPrint *irp, IrInstructionPtrType *instruction) { fprintf(irp->f, "&"); if (instruction->align_value != nullptr) { fprintf(irp->f, "align("); ir_print_other_instruction(irp, instruction->align_value); fprintf(irp->f, ")"); } const char *const_str = instruction->is_const ? "const " : ""; const char *volatile_str = instruction->is_volatile ? "volatile " : ""; fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->host_int_bytes, const_str, volatile_str); ir_print_other_instruction(irp, instruction->child_type); } static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) { const char *ptr_str = (instruction->lval == LValPtr) ? "ptr " : ""; fprintf(irp->f, "declref %s%s", ptr_str, buf_ptr(instruction->tld->name)); } static void ir_print_panic(IrPrint *irp, IrInstructionPanic *instruction) { fprintf(irp->f, "@panic("); ir_print_other_instruction(irp, instruction->msg); fprintf(irp->f, ")"); } static void ir_print_field_parent_ptr(IrPrint *irp, IrInstructionFieldParentPtr *instruction) { fprintf(irp->f, "@fieldParentPtr("); ir_print_other_instruction(irp, instruction->type_value); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->field_name); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->field_ptr); fprintf(irp->f, ")"); } static void ir_print_byte_offset_of(IrPrint *irp, IrInstructionByteOffsetOf *instruction) { fprintf(irp->f, "@byte_offset_of("); ir_print_other_instruction(irp, instruction->type_value); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->field_name); fprintf(irp->f, ")"); } static void ir_print_bit_offset_of(IrPrint *irp, IrInstructionBitOffsetOf *instruction) { fprintf(irp->f, "@bit_offset_of("); ir_print_other_instruction(irp, instruction->type_value); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->field_name); fprintf(irp->f, ")"); } static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction) { fprintf(irp->f, "@typeInfo("); ir_print_other_instruction(irp, instruction->type_value); fprintf(irp->f, ")"); } static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) { fprintf(irp->f, "@typeId("); ir_print_other_instruction(irp, instruction->type_value); fprintf(irp->f, ")"); } static void ir_print_set_eval_branch_quota(IrPrint *irp, IrInstructionSetEvalBranchQuota *instruction) { fprintf(irp->f, "@setEvalBranchQuota("); ir_print_other_instruction(irp, instruction->new_quota); fprintf(irp->f, ")"); } static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instruction) { fprintf(irp->f, "@alignCast("); if (instruction->align_bytes == nullptr) { fprintf(irp->f, "null"); } else { ir_print_other_instruction(irp, instruction->align_bytes); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) { fprintf(irp->f, "@OpaqueType()"); } static void ir_print_set_align_stack(IrPrint *irp, IrInstructionSetAlignStack *instruction) { fprintf(irp->f, "@setAlignStack("); ir_print_other_instruction(irp, instruction->align_bytes); fprintf(irp->f, ")"); } static void ir_print_arg_type(IrPrint *irp, IrInstructionArgType *instruction) { fprintf(irp->f, "@ArgType("); ir_print_other_instruction(irp, instruction->fn_type); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->arg_index); fprintf(irp->f, ")"); } static void ir_print_enum_tag_type(IrPrint *irp, IrInstructionTagType *instruction) { fprintf(irp->f, "@TagType("); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } static void ir_print_export(IrPrint *irp, IrInstructionExport *instruction) { if (instruction->linkage == nullptr) { fprintf(irp->f, "@export("); ir_print_other_instruction(irp, instruction->name); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ")"); } else { fprintf(irp->f, "@exportWithLinkage("); ir_print_other_instruction(irp, instruction->name); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->target); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->linkage); fprintf(irp->f, ")"); } } static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTrace *instruction) { fprintf(irp->f, "@errorReturnTrace("); switch (instruction->optional) { case IrInstructionErrorReturnTrace::Null: fprintf(irp->f, "Null"); break; case IrInstructionErrorReturnTrace::NonNull: fprintf(irp->f, "NonNull"); break; } fprintf(irp->f, ")"); } static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruction) { ir_print_other_instruction(irp, instruction->err_set); fprintf(irp->f, "!"); ir_print_other_instruction(irp, instruction->payload); } static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) { fprintf(irp->f, "cancel "); ir_print_other_instruction(irp, instruction->target); } static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplicitAllocator *instruction) { fprintf(irp->f, "@getImplicitAllocator("); switch (instruction->id) { case ImplicitAllocatorIdArg: fprintf(irp->f, "Arg"); break; case ImplicitAllocatorIdLocalVar: fprintf(irp->f, "LocalVar"); break; } fprintf(irp->f, ")"); } static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) { fprintf(irp->f, "@coroId("); ir_print_other_instruction(irp, instruction->promise_ptr); fprintf(irp->f, ")"); } static void ir_print_coro_alloc(IrPrint *irp, IrInstructionCoroAlloc *instruction) { fprintf(irp->f, "@coroAlloc("); ir_print_other_instruction(irp, instruction->coro_id); fprintf(irp->f, ")"); } static void ir_print_coro_size(IrPrint *irp, IrInstructionCoroSize *instruction) { fprintf(irp->f, "@coroSize()"); } static void ir_print_coro_begin(IrPrint *irp, IrInstructionCoroBegin *instruction) { fprintf(irp->f, "@coroBegin("); ir_print_other_instruction(irp, instruction->coro_id); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->coro_mem_ptr); fprintf(irp->f, ")"); } static void ir_print_coro_alloc_fail(IrPrint *irp, IrInstructionCoroAllocFail *instruction) { fprintf(irp->f, "@coroAllocFail("); ir_print_other_instruction(irp, instruction->err_val); fprintf(irp->f, ")"); } static void ir_print_coro_suspend(IrPrint *irp, IrInstructionCoroSuspend *instruction) { fprintf(irp->f, "@coroSuspend("); if (instruction->save_point != nullptr) { ir_print_other_instruction(irp, instruction->save_point); } else { fprintf(irp->f, "null"); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->is_final); fprintf(irp->f, ")"); } static void ir_print_coro_end(IrPrint *irp, IrInstructionCoroEnd *instruction) { fprintf(irp->f, "@coroEnd()"); } static void ir_print_coro_free(IrPrint *irp, IrInstructionCoroFree *instruction) { fprintf(irp->f, "@coroFree("); ir_print_other_instruction(irp, instruction->coro_id); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->coro_handle); fprintf(irp->f, ")"); } static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruction) { fprintf(irp->f, "@coroResume("); ir_print_other_instruction(irp, instruction->awaiter_handle); fprintf(irp->f, ")"); } static void ir_print_coro_save(IrPrint *irp, IrInstructionCoroSave *instruction) { fprintf(irp->f, "@coroSave("); ir_print_other_instruction(irp, instruction->coro_handle); fprintf(irp->f, ")"); } static void ir_print_coro_promise(IrPrint *irp, IrInstructionCoroPromise *instruction) { fprintf(irp->f, "@coroPromise("); ir_print_other_instruction(irp, instruction->coro_handle); fprintf(irp->f, ")"); } static void ir_print_promise_result_type(IrPrint *irp, IrInstructionPromiseResultType *instruction) { fprintf(irp->f, "@PromiseResultType("); ir_print_other_instruction(irp, instruction->promise_type); fprintf(irp->f, ")"); } static void ir_print_coro_alloc_helper(IrPrint *irp, IrInstructionCoroAllocHelper *instruction) { fprintf(irp->f, "@coroAllocHelper("); ir_print_other_instruction(irp, instruction->realloc_fn); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->coro_size); fprintf(irp->f, ")"); } static void ir_print_atomic_rmw(IrPrint *irp, IrInstructionAtomicRmw *instruction) { fprintf(irp->f, "@atomicRmw("); if (instruction->operand_type != nullptr) { ir_print_other_instruction(irp, instruction->operand_type); } else { fprintf(irp->f, "[TODO print]"); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ","); if (instruction->op != nullptr) { ir_print_other_instruction(irp, instruction->op); } else { fprintf(irp->f, "[TODO print]"); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->operand); fprintf(irp->f, ","); if (instruction->ordering != nullptr) { ir_print_other_instruction(irp, instruction->ordering); } else { fprintf(irp->f, "[TODO print]"); } fprintf(irp->f, ")"); } static void ir_print_atomic_load(IrPrint *irp, IrInstructionAtomicLoad *instruction) { fprintf(irp->f, "@atomicLoad("); if (instruction->operand_type != nullptr) { ir_print_other_instruction(irp, instruction->operand_type); } else { fprintf(irp->f, "[TODO print]"); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->ptr); fprintf(irp->f, ","); if (instruction->ordering != nullptr) { ir_print_other_instruction(irp, instruction->ordering); } else { fprintf(irp->f, "[TODO print]"); } fprintf(irp->f, ")"); } static void ir_print_await_bookkeeping(IrPrint *irp, IrInstructionAwaitBookkeeping *instruction) { fprintf(irp->f, "@awaitBookkeeping("); ir_print_other_instruction(irp, instruction->promise_result_type); fprintf(irp->f, ")"); } static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr *instruction) { fprintf(irp->f, "@saveErrRetAddr()"); } static void ir_print_add_implicit_return_type(IrPrint *irp, IrInstructionAddImplicitReturnType *instruction) { fprintf(irp->f, "@addImplicitReturnType("); ir_print_other_instruction(irp, instruction->value); fprintf(irp->f, ")"); } static void ir_print_merge_err_ret_traces(IrPrint *irp, IrInstructionMergeErrRetTraces *instruction) { fprintf(irp->f, "@mergeErrRetTraces("); ir_print_other_instruction(irp, instruction->coro_promise_ptr); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->src_err_ret_trace_ptr); fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->dest_err_ret_trace_ptr); fprintf(irp->f, ")"); } static void ir_print_mark_err_ret_trace_ptr(IrPrint *irp, IrInstructionMarkErrRetTracePtr *instruction) { fprintf(irp->f, "@markErrRetTracePtr("); ir_print_other_instruction(irp, instruction->err_ret_trace_ptr); fprintf(irp->f, ")"); } static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { fprintf(irp->f, "@sqrt("); if (instruction->type != nullptr) { ir_print_other_instruction(irp, instruction->type); } else { fprintf(irp->f, "null"); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->op); fprintf(irp->f, ")"); } static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) { ZigVar *var = decl_var_instruction->var; const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; const char *name = buf_ptr(&decl_var_instruction->var->name); fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name), var->align_bytes); ir_print_other_instruction(irp, decl_var_instruction->init_value); if (decl_var_instruction->var->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime); } } static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) { fprintf(irp->f, "@bswap("); if (instruction->type != nullptr) { ir_print_other_instruction(irp, instruction->type); } else { fprintf(irp->f, "null"); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->op); fprintf(irp->f, ")"); } static void ir_print_bit_reverse(IrPrint *irp, IrInstructionBitReverse *instruction) { fprintf(irp->f, "@bitreverse("); if (instruction->type != nullptr) { ir_print_other_instruction(irp, instruction->type); } else { fprintf(irp->f, "null"); } fprintf(irp->f, ","); ir_print_other_instruction(irp, instruction->op); fprintf(irp->f, ")"); } static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { ir_print_prefix(irp, instruction); switch (instruction->id) { case IrInstructionIdInvalid: zig_unreachable(); case IrInstructionIdReturn: ir_print_return(irp, (IrInstructionReturn *)instruction); break; case IrInstructionIdConst: ir_print_const(irp, (IrInstructionConst *)instruction); break; case IrInstructionIdBinOp: ir_print_bin_op(irp, (IrInstructionBinOp *)instruction); break; case IrInstructionIdDeclVarSrc: ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction); break; case IrInstructionIdCast: ir_print_cast(irp, (IrInstructionCast *)instruction); break; case IrInstructionIdCall: ir_print_call(irp, (IrInstructionCall *)instruction); break; case IrInstructionIdUnOp: ir_print_un_op(irp, (IrInstructionUnOp *)instruction); break; case IrInstructionIdCondBr: ir_print_cond_br(irp, (IrInstructionCondBr *)instruction); break; case IrInstructionIdBr: ir_print_br(irp, (IrInstructionBr *)instruction); break; case IrInstructionIdPhi: ir_print_phi(irp, (IrInstructionPhi *)instruction); break; case IrInstructionIdContainerInitList: ir_print_container_init_list(irp, (IrInstructionContainerInitList *)instruction); break; case IrInstructionIdContainerInitFields: ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction); break; case IrInstructionIdStructInit: ir_print_struct_init(irp, (IrInstructionStructInit *)instruction); break; case IrInstructionIdUnionInit: ir_print_union_init(irp, (IrInstructionUnionInit *)instruction); break; case IrInstructionIdUnreachable: ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction); break; case IrInstructionIdElemPtr: ir_print_elem_ptr(irp, (IrInstructionElemPtr *)instruction); break; case IrInstructionIdVarPtr: ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction); break; case IrInstructionIdLoadPtr: ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction); break; case IrInstructionIdLoadPtrGen: ir_print_load_ptr_gen(irp, (IrInstructionLoadPtrGen *)instruction); break; case IrInstructionIdStorePtr: ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction); break; case IrInstructionIdTypeOf: ir_print_typeof(irp, (IrInstructionTypeOf *)instruction); break; case IrInstructionIdToPtrType: ir_print_to_ptr_type(irp, (IrInstructionToPtrType *)instruction); break; case IrInstructionIdPtrTypeChild: ir_print_ptr_type_child(irp, (IrInstructionPtrTypeChild *)instruction); break; case IrInstructionIdFieldPtr: ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction); break; case IrInstructionIdStructFieldPtr: ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction); break; case IrInstructionIdUnionFieldPtr: ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction); break; case IrInstructionIdSetCold: ir_print_set_cold(irp, (IrInstructionSetCold *)instruction); break; case IrInstructionIdSetRuntimeSafety: ir_print_set_runtime_safety(irp, (IrInstructionSetRuntimeSafety *)instruction); break; case IrInstructionIdSetFloatMode: ir_print_set_float_mode(irp, (IrInstructionSetFloatMode *)instruction); break; case IrInstructionIdArrayType: ir_print_array_type(irp, (IrInstructionArrayType *)instruction); break; case IrInstructionIdPromiseType: ir_print_promise_type(irp, (IrInstructionPromiseType *)instruction); break; case IrInstructionIdSliceType: ir_print_slice_type(irp, (IrInstructionSliceType *)instruction); break; case IrInstructionIdGlobalAsm: ir_print_global_asm(irp, (IrInstructionGlobalAsm *)instruction); break; case IrInstructionIdAsm: ir_print_asm(irp, (IrInstructionAsm *)instruction); break; case IrInstructionIdSizeOf: ir_print_size_of(irp, (IrInstructionSizeOf *)instruction); break; case IrInstructionIdTestNonNull: ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction); break; case IrInstructionIdOptionalUnwrapPtr: ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction); break; case IrInstructionIdCtz: ir_print_ctz(irp, (IrInstructionCtz *)instruction); break; case IrInstructionIdPopCount: ir_print_pop_count(irp, (IrInstructionPopCount *)instruction); break; case IrInstructionIdClz: ir_print_clz(irp, (IrInstructionClz *)instruction); break; case IrInstructionIdSwitchBr: ir_print_switch_br(irp, (IrInstructionSwitchBr *)instruction); break; case IrInstructionIdSwitchVar: ir_print_switch_var(irp, (IrInstructionSwitchVar *)instruction); break; case IrInstructionIdSwitchTarget: ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction); break; case IrInstructionIdUnionTag: ir_print_union_tag(irp, (IrInstructionUnionTag *)instruction); break; case IrInstructionIdImport: ir_print_import(irp, (IrInstructionImport *)instruction); break; case IrInstructionIdRef: ir_print_ref(irp, (IrInstructionRef *)instruction); break; case IrInstructionIdCompileErr: ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction); break; case IrInstructionIdCompileLog: ir_print_compile_log(irp, (IrInstructionCompileLog *)instruction); break; case IrInstructionIdErrName: ir_print_err_name(irp, (IrInstructionErrName *)instruction); break; case IrInstructionIdCImport: ir_print_c_import(irp, (IrInstructionCImport *)instruction); break; case IrInstructionIdCInclude: ir_print_c_include(irp, (IrInstructionCInclude *)instruction); break; case IrInstructionIdCDefine: ir_print_c_define(irp, (IrInstructionCDefine *)instruction); break; case IrInstructionIdCUndef: ir_print_c_undef(irp, (IrInstructionCUndef *)instruction); break; case IrInstructionIdEmbedFile: ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction); break; case IrInstructionIdCmpxchgSrc: ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction); break; case IrInstructionIdCmpxchgGen: ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction); break; case IrInstructionIdFence: ir_print_fence(irp, (IrInstructionFence *)instruction); break; case IrInstructionIdTruncate: ir_print_truncate(irp, (IrInstructionTruncate *)instruction); break; case IrInstructionIdIntCast: ir_print_int_cast(irp, (IrInstructionIntCast *)instruction); break; case IrInstructionIdFloatCast: ir_print_float_cast(irp, (IrInstructionFloatCast *)instruction); break; case IrInstructionIdErrSetCast: ir_print_err_set_cast(irp, (IrInstructionErrSetCast *)instruction); break; case IrInstructionIdFromBytes: ir_print_from_bytes(irp, (IrInstructionFromBytes *)instruction); break; case IrInstructionIdToBytes: ir_print_to_bytes(irp, (IrInstructionToBytes *)instruction); break; case IrInstructionIdIntToFloat: ir_print_int_to_float(irp, (IrInstructionIntToFloat *)instruction); break; case IrInstructionIdFloatToInt: ir_print_float_to_int(irp, (IrInstructionFloatToInt *)instruction); break; case IrInstructionIdBoolToInt: ir_print_bool_to_int(irp, (IrInstructionBoolToInt *)instruction); break; case IrInstructionIdIntType: ir_print_int_type(irp, (IrInstructionIntType *)instruction); break; case IrInstructionIdVectorType: ir_print_vector_type(irp, (IrInstructionVectorType *)instruction); break; case IrInstructionIdBoolNot: ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction); break; case IrInstructionIdMemset: ir_print_memset(irp, (IrInstructionMemset *)instruction); break; case IrInstructionIdMemcpy: ir_print_memcpy(irp, (IrInstructionMemcpy *)instruction); break; case IrInstructionIdSlice: ir_print_slice(irp, (IrInstructionSlice *)instruction); break; case IrInstructionIdMemberCount: ir_print_member_count(irp, (IrInstructionMemberCount *)instruction); break; case IrInstructionIdMemberType: ir_print_member_type(irp, (IrInstructionMemberType *)instruction); break; case IrInstructionIdMemberName: ir_print_member_name(irp, (IrInstructionMemberName *)instruction); break; case IrInstructionIdBreakpoint: ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction); break; case IrInstructionIdReturnAddress: ir_print_return_address(irp, (IrInstructionReturnAddress *)instruction); break; case IrInstructionIdFrameAddress: ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction); break; case IrInstructionIdHandle: ir_print_handle(irp, (IrInstructionHandle *)instruction); break; case IrInstructionIdAlignOf: ir_print_align_of(irp, (IrInstructionAlignOf *)instruction); break; case IrInstructionIdOverflowOp: ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction); break; case IrInstructionIdTestErr: ir_print_test_err(irp, (IrInstructionTestErr *)instruction); break; case IrInstructionIdUnwrapErrCode: ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction); break; case IrInstructionIdUnwrapErrPayload: ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction); break; case IrInstructionIdOptionalWrap: ir_print_maybe_wrap(irp, (IrInstructionOptionalWrap *)instruction); break; case IrInstructionIdErrWrapCode: ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction); break; case IrInstructionIdErrWrapPayload: ir_print_err_wrap_payload(irp, (IrInstructionErrWrapPayload *)instruction); break; case IrInstructionIdFnProto: ir_print_fn_proto(irp, (IrInstructionFnProto *)instruction); break; case IrInstructionIdTestComptime: ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); break; case IrInstructionIdPtrCastSrc: ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction); break; case IrInstructionIdPtrCastGen: ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction); break; case IrInstructionIdBitCast: ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction); break; case IrInstructionIdBitCastGen: ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction); break; case IrInstructionIdWidenOrShorten: ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction); break; case IrInstructionIdPtrToInt: ir_print_ptr_to_int(irp, (IrInstructionPtrToInt *)instruction); break; case IrInstructionIdIntToPtr: ir_print_int_to_ptr(irp, (IrInstructionIntToPtr *)instruction); break; case IrInstructionIdIntToEnum: ir_print_int_to_enum(irp, (IrInstructionIntToEnum *)instruction); break; case IrInstructionIdIntToErr: ir_print_int_to_err(irp, (IrInstructionIntToErr *)instruction); break; case IrInstructionIdErrToInt: ir_print_err_to_int(irp, (IrInstructionErrToInt *)instruction); break; case IrInstructionIdCheckSwitchProngs: ir_print_check_switch_prongs(irp, (IrInstructionCheckSwitchProngs *)instruction); break; case IrInstructionIdCheckStatementIsVoid: ir_print_check_statement_is_void(irp, (IrInstructionCheckStatementIsVoid *)instruction); break; case IrInstructionIdTypeName: ir_print_type_name(irp, (IrInstructionTypeName *)instruction); break; case IrInstructionIdTagName: ir_print_tag_name(irp, (IrInstructionTagName *)instruction); break; case IrInstructionIdPtrType: ir_print_ptr_type(irp, (IrInstructionPtrType *)instruction); break; case IrInstructionIdDeclRef: ir_print_decl_ref(irp, (IrInstructionDeclRef *)instruction); break; case IrInstructionIdPanic: ir_print_panic(irp, (IrInstructionPanic *)instruction); break; case IrInstructionIdFieldParentPtr: ir_print_field_parent_ptr(irp, (IrInstructionFieldParentPtr *)instruction); break; case IrInstructionIdByteOffsetOf: ir_print_byte_offset_of(irp, (IrInstructionByteOffsetOf *)instruction); break; case IrInstructionIdBitOffsetOf: ir_print_bit_offset_of(irp, (IrInstructionBitOffsetOf *)instruction); break; case IrInstructionIdTypeInfo: ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction); break; case IrInstructionIdTypeId: ir_print_type_id(irp, (IrInstructionTypeId *)instruction); break; case IrInstructionIdSetEvalBranchQuota: ir_print_set_eval_branch_quota(irp, (IrInstructionSetEvalBranchQuota *)instruction); break; case IrInstructionIdAlignCast: ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction); break; case IrInstructionIdOpaqueType: ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction); break; case IrInstructionIdSetAlignStack: ir_print_set_align_stack(irp, (IrInstructionSetAlignStack *)instruction); break; case IrInstructionIdArgType: ir_print_arg_type(irp, (IrInstructionArgType *)instruction); break; case IrInstructionIdTagType: ir_print_enum_tag_type(irp, (IrInstructionTagType *)instruction); break; case IrInstructionIdExport: ir_print_export(irp, (IrInstructionExport *)instruction); break; case IrInstructionIdErrorReturnTrace: ir_print_error_return_trace(irp, (IrInstructionErrorReturnTrace *)instruction); break; case IrInstructionIdErrorUnion: ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction); break; case IrInstructionIdCancel: ir_print_cancel(irp, (IrInstructionCancel *)instruction); break; case IrInstructionIdGetImplicitAllocator: ir_print_get_implicit_allocator(irp, (IrInstructionGetImplicitAllocator *)instruction); break; case IrInstructionIdCoroId: ir_print_coro_id(irp, (IrInstructionCoroId *)instruction); break; case IrInstructionIdCoroAlloc: ir_print_coro_alloc(irp, (IrInstructionCoroAlloc *)instruction); break; case IrInstructionIdCoroSize: ir_print_coro_size(irp, (IrInstructionCoroSize *)instruction); break; case IrInstructionIdCoroBegin: ir_print_coro_begin(irp, (IrInstructionCoroBegin *)instruction); break; case IrInstructionIdCoroAllocFail: ir_print_coro_alloc_fail(irp, (IrInstructionCoroAllocFail *)instruction); break; case IrInstructionIdCoroSuspend: ir_print_coro_suspend(irp, (IrInstructionCoroSuspend *)instruction); break; case IrInstructionIdCoroEnd: ir_print_coro_end(irp, (IrInstructionCoroEnd *)instruction); break; case IrInstructionIdCoroFree: ir_print_coro_free(irp, (IrInstructionCoroFree *)instruction); break; case IrInstructionIdCoroResume: ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction); break; case IrInstructionIdCoroSave: ir_print_coro_save(irp, (IrInstructionCoroSave *)instruction); break; case IrInstructionIdCoroAllocHelper: ir_print_coro_alloc_helper(irp, (IrInstructionCoroAllocHelper *)instruction); break; case IrInstructionIdAtomicRmw: ir_print_atomic_rmw(irp, (IrInstructionAtomicRmw *)instruction); break; case IrInstructionIdCoroPromise: ir_print_coro_promise(irp, (IrInstructionCoroPromise *)instruction); break; case IrInstructionIdPromiseResultType: ir_print_promise_result_type(irp, (IrInstructionPromiseResultType *)instruction); break; case IrInstructionIdAwaitBookkeeping: ir_print_await_bookkeeping(irp, (IrInstructionAwaitBookkeeping *)instruction); break; case IrInstructionIdSaveErrRetAddr: ir_print_save_err_ret_addr(irp, (IrInstructionSaveErrRetAddr *)instruction); break; case IrInstructionIdAddImplicitReturnType: ir_print_add_implicit_return_type(irp, (IrInstructionAddImplicitReturnType *)instruction); break; case IrInstructionIdMergeErrRetTraces: ir_print_merge_err_ret_traces(irp, (IrInstructionMergeErrRetTraces *)instruction); break; case IrInstructionIdMarkErrRetTracePtr: ir_print_mark_err_ret_trace_ptr(irp, (IrInstructionMarkErrRetTracePtr *)instruction); break; case IrInstructionIdSqrt: ir_print_sqrt(irp, (IrInstructionSqrt *)instruction); break; case IrInstructionIdBswap: ir_print_bswap(irp, (IrInstructionBswap *)instruction); break; case IrInstructionIdBitReverse: ir_print_bit_reverse(irp, (IrInstructionBitReverse *)instruction); break; case IrInstructionIdAtomicLoad: ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); break; case IrInstructionIdEnumToInt: ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction); break; case IrInstructionIdCheckRuntimeScope: ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction); break; case IrInstructionIdDeclVarGen: ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction); break; case IrInstructionIdArrayToVector: ir_print_array_to_vector(irp, (IrInstructionArrayToVector *)instruction); break; case IrInstructionIdVectorToArray: ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction); break; case IrInstructionIdAssertZero: ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction); break; case IrInstructionIdResizeSlice: ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction); break; } fprintf(irp->f, "\n"); } void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size) { IrPrint ir_print = {}; IrPrint *irp = &ir_print; irp->codegen = codegen; irp->f = f; irp->indent = indent_size; irp->indent_size = indent_size; for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) { IrBasicBlock *current_block = executable->basic_block_list.at(bb_i); fprintf(irp->f, "%s_%" ZIG_PRI_usize ":\n", current_block->name_hint, current_block->debug_id); for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { IrInstruction *instruction = current_block->instruction_list.at(instr_i); ir_print_instruction(irp, instruction); } } }