#include "moar.h" #include "jit/internal.h" #include "platform/io.h" void MVM_jit_dump_bytecode(MVMThreadContext *tc, MVMJitCode *code) { char filename[1024]; FILE * dump; snprintf(filename, sizeof(filename), "%s/moar-jit-%04d.bin", tc->instance->jit_bytecode_dir, code->seq_nr); dump = MVM_platform_fopen(filename, "w"); if (dump) { fwrite(code->func_ptr, sizeof(char), code->size, dump); fclose(dump); if (MVM_spesh_debug_enabled(tc)) MVM_spesh_debug_printf(tc, "JIT: Dumped bytecode to %s\n\n", filename); } else if (tc->instance->jit_debug_enabled) { FILE *file = tc->instance->spesh_log_fh ? tc->instance->spesh_log_fh : stderr; fprintf(file, "JIT ERROR: could not dump bytecode: %s", strerror(errno)); } } static void dump_tree(MVMThreadContext *tc, MVMJitTreeTraverser *traverser, MVMJitExprTree *tree, MVMint32 node) { MVMJitExprInfo *info = MVM_JIT_EXPR_INFO(tree, node); const char *op_name = MVM_jit_expr_operator_name(tc, tree->nodes[node]); MVMint32 *links = MVM_JIT_EXPR_LINKS(tree, node); MVMuint32 *depth = traverser->data; MVMuint32 i, j; char indent[64]; char nargs[80]; (*depth)++; #define MVM_MIN(a,b) ((a) < (b) ? (a) : (b)) i = MVM_MIN(*depth*2, sizeof(indent)-1); memset(indent, ' ', i); indent[i] = 0; j = 0; for (i = 0; i < info->num_args; i++) { MVMint32 arg = links[i]; j += snprintf(nargs + j, sizeof(nargs)-j-3, "%"PRId32, arg); if (i+1 < info->num_args && j < sizeof(nargs)-3) { j += sprintf(nargs + j, ", "); } } nargs[j] = 0; fprintf(traverser->data, "%04d%s%s (%s; sz=%d)\n", node, indent, op_name, nargs, info->size); } static void ascend_tree(MVMThreadContext *tc, MVMJitTreeTraverser *traverser, MVMJitExprTree *tree, MVMint32 node) { MVMuint32 *depth = traverser->data; (*depth)--; } static void write_graphviz_node(MVMThreadContext *tc, MVMJitTreeTraverser *traverser, MVMJitExprTree *tree, MVMint32 node) { FILE *graph_file = traverser->data; const char *op_name = MVM_jit_expr_operator_name(tc, tree->nodes[node]); MVMint32 *links = MVM_JIT_EXPR_LINKS(tree, node); MVMint32 *args = MVM_JIT_EXPR_ARGS(tree, node); MVMJitExprInfo *info = MVM_JIT_EXPR_INFO(tree, node); MVMint32 i; /* maximum length of op name is 'invokish' at 8 characters, let's allocate * 16; maximum number of parameters is 4, and 64 bits; printing them in * hexadecimal would require at most 8 characters, plus 4 for the '0x' and * the ', '; minus 2 for the last one, plus 2 for the ampersands, plus 0 for * the terminus, gives us 16 + 4*12 + 3 = 67; 80 should be plenty */ char node_label[80]; char *ptr = node_label + sprintf(node_label, "%s%s", op_name, info->num_args ? "(" : ""); for (i = 0; i < info->num_args; i++) { ptr += sprintf(ptr, "%" PRId32 "%s", args[i], (i + 1 < info->num_args) ? ", " : ")"); } if (info->type != 0) { ptr += sprintf(ptr, ":%s", MVM_register_type(info->type)); } fprintf(graph_file, " n_%04d [label=\"%s\"];\n", node, node_label); for (i = 0; i < info->num_links; i++) { fprintf(graph_file, " n_%04d -> n_%04d;\n", node, links[i]); } } void MVM_jit_dump_expr_tree(MVMThreadContext *tc, MVMJitExprTree *tree) { MVMJitTreeTraverser traverser; FILE *log = tc->instance->spesh_log_fh; if (!log) return; traverser.policy = MVM_JIT_TRAVERSER_ONCE; traverser.preorder = NULL; traverser.inorder = NULL; traverser.postorder = &write_graphviz_node; traverser.data = log; fprintf(log, "JIT: Starting dump of JIT expression tree\n" "=========================================\n\n"); fprintf(log, "digraph {\n"); MVM_jit_expr_tree_traverse(tc, tree, &traverser); fprintf(log, "}\n\n"); fprintf(log, "End dump of JIT expression tree\n" "===============================\n\n"); } void MVM_jit_dump_tile_list(MVMThreadContext *tc, MVMJitTileList *list) { MVMuint32 i, j; FILE *f = tc->instance->spesh_log_fh; if (!f) return; fprintf(f, "JIT: Starting tile list log\n" "===========================\n\n"); for (i = 0; i < list->blocks_num; i++) { MVMuint32 start = list->blocks[i].start, end = list->blocks[i].end; fprintf(f, "Block{%d} [%d-%d)\n", i, start, end); for (j = start; j < end; j++) { MVMJitTile *tile = list->items[j]; fprintf(f, " %d: %s\n", j, tile->debug_name ? tile->debug_name : ""); } if (list->blocks[i].num_succ == 2) { fprintf(f, "-> { %d, %d }\n", list->blocks[i].succ[0], list->blocks[i].succ[1]); } else if (list->blocks[i].num_succ == 1) { fprintf(f, "-> { %d }\n", list->blocks[i].succ[0]); } else { fprintf(f, "-> {}\n"); } } fprintf(f, "\nEnd of tile list log\n" "====================\n\n"); }