stage1 enhance IR print

- pass2 now prints missing instructions in a trailing fashion
- instruction struct name added to print as column 2
This commit is contained in:
Michael Dusan 2019-08-31 12:30:26 -04:00 committed by Andrew Kelley
parent 5c3a9a1a3e
commit 1f99899408
4 changed files with 383 additions and 14 deletions

View File

@ -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");
}

View File

@ -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");
}

View File

@ -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);
}

View File

@ -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