Commit 1f99899408

Michael Dusan <michael.dusan@gmail.com>
2019-08-31 18:30:26
stage1 enhance IR print
- pass2 now prints missing instructions in a trailing fashion - instruction struct name added to print as column 2
1 parent 5c3a9a1
src/analyze.cpp
@@ -4415,7 +4415,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
 
     if (g->verbose_ir) {
         fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name));
-        ir_print(g, stderr, &fn->analyzed_executable, 4);
+        ir_print(g, stderr, &fn->analyzed_executable, 4, 2);
         fprintf(stderr, "}\n");
     }
     fn->anal_state = FnAnalStateComplete;
@@ -4449,7 +4449,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
         fprintf(stderr, "\n");
         ast_render(stderr, fn_table_entry->body_node, 4);
         fprintf(stderr, "\n{ // (IR)\n");
-        ir_print(g, stderr, &fn_table_entry->ir_executable, 4);
+        ir_print(g, stderr, &fn_table_entry->ir_executable, 4, 1);
         fprintf(stderr, "}\n");
     }
 
src/ir.cpp
@@ -10867,7 +10867,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
         fprintf(stderr, "\nSource: ");
         ast_render(stderr, node, 4);
         fprintf(stderr, "\n{ // (IR)\n");
-        ir_print(codegen, stderr, ir_executable, 2);
+        ir_print(codegen, stderr, ir_executable, 2, 1);
         fprintf(stderr, "}\n");
     }
     IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
@@ -10888,7 +10888,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
 
     if (codegen->verbose_ir) {
         fprintf(stderr, "{ // (analyzed)\n");
-        ir_print(codegen, stderr, analyzed_executable, 2);
+        ir_print(codegen, stderr, analyzed_executable, 2, 2);
         fprintf(stderr, "}\n");
     }
 
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);
 }
src/ir_print.hpp
@@ -12,7 +12,7 @@
 
 #include <stdio.h>
 
-void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size);
-void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size);
+void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, size_t pass_num);
+void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, size_t pass_num);
 
 #endif