diff options
Diffstat (limited to 'src/ir_print.cpp')
| -rw-r--r-- | src/ir_print.cpp | 385 |
1 files changed, 377 insertions, 8 deletions
diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 7580f19059..6de585ec6f 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -10,27 +10,374 @@ #include "ir_print.hpp" #include "os.hpp" +static uint32_t hash_instruction_ptr(IrInstruction* instruction) { + return (uint32_t)(uintptr_t)instruction; +} + +static bool instruction_ptr_equal(IrInstruction* a, IrInstruction* b) { + return a == b; +} + +using InstructionSet = HashMap<IrInstruction*, uint8_t, hash_instruction_ptr, instruction_ptr_equal>; +using InstructionList = ZigList<IrInstruction*>; + struct IrPrint { + size_t pass_num; CodeGen *codegen; FILE *f; int indent; int indent_size; + + // When printing pass 2 instructions referenced var instructions are not + // present in the instruction list. Thus we track which instructions + // are printed (per executable) and after each pass 2 instruction those + // var instructions are rendered in a trailing fashion. + InstructionSet printed; + InstructionList pending; }; static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction); +static const char* ir_instruction_type_str(IrInstruction* instruction) { + switch (instruction->id) { + case IrInstructionIdInvalid: + return "Invalid"; + case IrInstructionIdDeclVarSrc: + return "DeclVarSrc"; + case IrInstructionIdDeclVarGen: + return "DeclVarGen"; + case IrInstructionIdBr: + return "Br"; + case IrInstructionIdCondBr: + return "CondBr"; + case IrInstructionIdSwitchBr: + return "SwitchBr"; + case IrInstructionIdSwitchVar: + return "SwitchVar"; + case IrInstructionIdSwitchElseVar: + return "SwitchElseVar"; + case IrInstructionIdSwitchTarget: + return "SwitchTarget"; + case IrInstructionIdPhi: + return "Phi"; + case IrInstructionIdUnOp: + return "UnOp"; + case IrInstructionIdBinOp: + return "BinOp"; + case IrInstructionIdLoadPtr: + return "LoadPtr"; + case IrInstructionIdLoadPtrGen: + return "LoadPtrGen"; + case IrInstructionIdStorePtr: + return "StorePtr"; + case IrInstructionIdFieldPtr: + return "FieldPtr"; + case IrInstructionIdStructFieldPtr: + return "StructFieldPtr"; + case IrInstructionIdUnionFieldPtr: + return "UnionFieldPtr"; + case IrInstructionIdElemPtr: + return "ElemPtr"; + case IrInstructionIdVarPtr: + return "VarPtr"; + case IrInstructionIdReturnPtr: + return "ReturnPtr"; + case IrInstructionIdCallSrc: + return "CallSrc"; + case IrInstructionIdCallGen: + return "CallGen"; + case IrInstructionIdConst: + return "Const"; + case IrInstructionIdReturn: + return "Return"; + case IrInstructionIdCast: + return "Cast"; + case IrInstructionIdResizeSlice: + return "ResizeSlice"; + case IrInstructionIdContainerInitList: + return "ContainerInitList"; + case IrInstructionIdContainerInitFields: + return "ContainerInitFields"; + case IrInstructionIdUnreachable: + return "Unreachable"; + case IrInstructionIdTypeOf: + return "TypeOf"; + case IrInstructionIdSetCold: + return "SetCold"; + case IrInstructionIdSetRuntimeSafety: + return "SetRuntimeSafety"; + case IrInstructionIdSetFloatMode: + return "SetFloatMode"; + case IrInstructionIdArrayType: + return "ArrayType"; + case IrInstructionIdAnyFrameType: + return "AnyFrameType"; + case IrInstructionIdSliceType: + return "SliceType"; + case IrInstructionIdGlobalAsm: + return "GlobalAsm"; + case IrInstructionIdAsm: + return "Asm"; + case IrInstructionIdSizeOf: + return "SizeOf"; + case IrInstructionIdTestNonNull: + return "TestNonNull"; + case IrInstructionIdOptionalUnwrapPtr: + return "OptionalUnwrapPtr"; + case IrInstructionIdOptionalWrap: + return "OptionalWrap"; + case IrInstructionIdUnionTag: + return "UnionTag"; + case IrInstructionIdClz: + return "Clz"; + case IrInstructionIdCtz: + return "Ctz"; + case IrInstructionIdPopCount: + return "PopCount"; + case IrInstructionIdBswap: + return "Bswap"; + case IrInstructionIdBitReverse: + return "BitReverse"; + case IrInstructionIdImport: + return "Import"; + case IrInstructionIdCImport: + return "CImport"; + case IrInstructionIdCInclude: + return "CInclude"; + case IrInstructionIdCDefine: + return "CDefine"; + case IrInstructionIdCUndef: + return "CUndef"; + case IrInstructionIdRef: + return "Ref"; + case IrInstructionIdRefGen: + return "RefGen"; + case IrInstructionIdCompileErr: + return "CompileErr"; + case IrInstructionIdCompileLog: + return "CompileLog"; + case IrInstructionIdErrName: + return "ErrName"; + case IrInstructionIdEmbedFile: + return "EmbedFile"; + case IrInstructionIdCmpxchgSrc: + return "CmpxchgSrc"; + case IrInstructionIdCmpxchgGen: + return "CmpxchgGen"; + case IrInstructionIdFence: + return "Fence"; + case IrInstructionIdTruncate: + return "Truncate"; + case IrInstructionIdIntCast: + return "IntCast"; + case IrInstructionIdFloatCast: + return "FloatCast"; + case IrInstructionIdIntToFloat: + return "IntToFloat"; + case IrInstructionIdFloatToInt: + return "FloatToInt"; + case IrInstructionIdBoolToInt: + return "BoolToInt"; + case IrInstructionIdIntType: + return "IntType"; + case IrInstructionIdVectorType: + return "VectorType"; + case IrInstructionIdBoolNot: + return "BoolNot"; + case IrInstructionIdMemset: + return "Memset"; + case IrInstructionIdMemcpy: + return "Memcpy"; + case IrInstructionIdSliceSrc: + return "SliceSrc"; + case IrInstructionIdSliceGen: + return "SliceGen"; + case IrInstructionIdMemberCount: + return "MemberCount"; + case IrInstructionIdMemberType: + return "MemberType"; + case IrInstructionIdMemberName: + return "MemberName"; + case IrInstructionIdBreakpoint: + return "Breakpoint"; + case IrInstructionIdReturnAddress: + return "ReturnAddress"; + case IrInstructionIdFrameAddress: + return "FrameAddress"; + case IrInstructionIdFrameHandle: + return "FrameHandle"; + case IrInstructionIdFrameType: + return "FrameType"; + case IrInstructionIdFrameSizeSrc: + return "FrameSizeSrc"; + case IrInstructionIdFrameSizeGen: + return "FrameSizeGen"; + case IrInstructionIdAlignOf: + return "AlignOf"; + case IrInstructionIdOverflowOp: + return "OverflowOp"; + case IrInstructionIdTestErrSrc: + return "TestErrSrc"; + case IrInstructionIdTestErrGen: + return "TestErrGen"; + case IrInstructionIdMulAdd: + return "MulAdd"; + case IrInstructionIdFloatOp: + return "FloatOp"; + case IrInstructionIdUnwrapErrCode: + return "UnwrapErrCode"; + case IrInstructionIdUnwrapErrPayload: + return "UnwrapErrPayload"; + case IrInstructionIdErrWrapCode: + return "ErrWrapCode"; + case IrInstructionIdErrWrapPayload: + return "ErrWrapPayload"; + case IrInstructionIdFnProto: + return "FnProto"; + case IrInstructionIdTestComptime: + return "TestComptime"; + case IrInstructionIdPtrCastSrc: + return "PtrCastSrc"; + case IrInstructionIdPtrCastGen: + return "PtrCastGen"; + case IrInstructionIdBitCastSrc: + return "BitCastSrc"; + case IrInstructionIdBitCastGen: + return "BitCastGen"; + case IrInstructionIdWidenOrShorten: + return "WidenOrShorten"; + case IrInstructionIdIntToPtr: + return "IntToPtr"; + case IrInstructionIdPtrToInt: + return "PtrToInt"; + case IrInstructionIdIntToEnum: + return "IntToEnum"; + case IrInstructionIdEnumToInt: + return "EnumToInt"; + case IrInstructionIdIntToErr: + return "IntToErr"; + case IrInstructionIdErrToInt: + return "ErrToInt"; + case IrInstructionIdCheckSwitchProngs: + return "CheckSwitchProngs"; + case IrInstructionIdCheckStatementIsVoid: + return "CheckStatementIsVoid"; + case IrInstructionIdTypeName: + return "TypeName"; + case IrInstructionIdDeclRef: + return "DeclRef"; + case IrInstructionIdPanic: + return "Panic"; + case IrInstructionIdTagName: + return "TagName"; + case IrInstructionIdTagType: + return "TagType"; + case IrInstructionIdFieldParentPtr: + return "FieldParentPtr"; + case IrInstructionIdByteOffsetOf: + return "ByteOffsetOf"; + case IrInstructionIdBitOffsetOf: + return "BitOffsetOf"; + case IrInstructionIdTypeInfo: + return "TypeInfo"; + case IrInstructionIdHasField: + return "HasField"; + case IrInstructionIdTypeId: + return "TypeId"; + case IrInstructionIdSetEvalBranchQuota: + return "SetEvalBranchQuota"; + case IrInstructionIdPtrType: + return "PtrType"; + case IrInstructionIdAlignCast: + return "AlignCast"; + case IrInstructionIdImplicitCast: + return "ImplicitCast"; + case IrInstructionIdResolveResult: + return "ResolveResult"; + case IrInstructionIdResetResult: + return "ResetResult"; + case IrInstructionIdOpaqueType: + return "OpaqueType"; + case IrInstructionIdSetAlignStack: + return "SetAlignStack"; + case IrInstructionIdArgType: + return "ArgType"; + case IrInstructionIdExport: + return "Export"; + case IrInstructionIdErrorReturnTrace: + return "ErrorReturnTrace"; + case IrInstructionIdErrorUnion: + return "ErrorUnion"; + case IrInstructionIdAtomicRmw: + return "AtomicRmw"; + case IrInstructionIdAtomicLoad: + return "AtomicLoad"; + case IrInstructionIdSaveErrRetAddr: + return "SaveErrRetAddr"; + case IrInstructionIdAddImplicitReturnType: + return "AddImplicitReturnType"; + case IrInstructionIdErrSetCast: + return "ErrSetCast"; + case IrInstructionIdToBytes: + return "ToBytes"; + case IrInstructionIdFromBytes: + return "FromBytes"; + case IrInstructionIdCheckRuntimeScope: + return "CheckRuntimeScope"; + case IrInstructionIdVectorToArray: + return "VectorToArray"; + case IrInstructionIdArrayToVector: + return "ArrayToVector"; + case IrInstructionIdAssertZero: + return "AssertZero"; + case IrInstructionIdAssertNonNull: + return "AssertNonNull"; + case IrInstructionIdHasDecl: + return "HasDecl"; + case IrInstructionIdUndeclaredIdent: + return "UndeclaredIdent"; + case IrInstructionIdAllocaSrc: + return "AllocaSrc"; + case IrInstructionIdAllocaGen: + return "AllocaGen"; + case IrInstructionIdEndExpr: + return "EndExpr"; + case IrInstructionIdPtrOfArrayToSlice: + return "PtrOfArrayToSlice"; + case IrInstructionIdUnionInitNamedField: + return "UnionInitNamedField"; + case IrInstructionIdSuspendBegin: + return "SuspendBegin"; + case IrInstructionIdSuspendFinish: + return "SuspendFinish"; + case IrInstructionIdAwaitSrc: + return "AwaitSrc"; + case IrInstructionIdAwaitGen: + return "AwaitGen"; + case IrInstructionIdResume: + return "Resume"; + case IrInstructionIdSpillBegin: + return "SpillBegin"; + case IrInstructionIdSpillEnd: + return "SpillEnd"; + } + zig_unreachable(); +} + 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) { +static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction, bool trailing) { ir_print_indent(irp); + const char mark = trailing ? ':' : '#'; 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); + fprintf(irp->f, "%c%-3zu| %-22s| %-12s| %-2s| ", mark, instruction->debug_id, + ir_instruction_type_str(instruction), type_name, ref_count); } static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) { @@ -42,6 +389,10 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) { static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) { fprintf(irp->f, "#%" ZIG_PRI_usize "", instruction->debug_id); + if (irp->pass_num == 2 && irp->printed.maybe_get(instruction) == nullptr) { + irp->printed.put(instruction, 0); + irp->pending.append(instruction); + } } static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) { @@ -49,6 +400,7 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) fprintf(irp->f, "(null)"); return; } + if (instruction->value.special != ConstValSpecialRuntime) { ir_print_const_value(irp, &instruction->value); } else { @@ -1550,8 +1902,8 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction) fprintf(irp->f, ")"); } -static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { - ir_print_prefix(irp, instruction); +static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) { + ir_print_prefix(irp, instruction, trailing); switch (instruction->id) { case IrInstructionIdInvalid: zig_unreachable(); @@ -2036,31 +2388,48 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { fprintf(irp->f, "\n"); } -void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size) { +void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, size_t pass_num) { IrPrint ir_print = {}; IrPrint *irp = &ir_print; + irp->pass_num = pass_num; irp->codegen = codegen; irp->f = f; irp->indent = indent_size; irp->indent_size = indent_size; + irp->printed = {}; + irp->printed.init(64); + irp->pending = {}; 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); + if (irp->pass_num == 2) { + irp->printed.put(instruction, 0); + irp->pending.clear(); + } + ir_print_instruction(irp, instruction, false); + for (size_t j = 0; j < irp->pending.length; ++j) + ir_print_instruction(irp, irp->pending.at(j), true); } } + + irp->pending.deinit(); + irp->printed.deinit(); } -void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size) { +void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, size_t pass_num) { IrPrint ir_print = {}; IrPrint *irp = &ir_print; + irp->pass_num = pass_num; irp->codegen = codegen; irp->f = f; irp->indent = indent_size; irp->indent_size = indent_size; + irp->printed = {}; + irp->printed.init(4); + irp->pending = {}; - ir_print_instruction(irp, instruction); + ir_print_instruction(irp, instruction, false); } |
