diff --git a/ir.h b/ir.h index da8a498..3099dcd 100644 --- a/ir.h +++ b/ir.h @@ -505,7 +505,6 @@ void ir_strtab_free(ir_strtab *strtab); # define IR_DEBUG_GCM (1<<28) # define IR_DEBUG_SCHEDULE (1<<29) # define IR_DEBUG_RA (1<<30) -# define IR_DEBUG_CODEGEN (1<<31) #endif typedef struct _ir_ctx ir_ctx; @@ -757,6 +756,7 @@ void ir_dump_use_lists(const ir_ctx *ctx, FILE *f); void ir_dump_cfg(ir_ctx *ctx, FILE *f); void ir_dump_cfg_map(const ir_ctx *ctx, FILE *f); void ir_dump_live_ranges(const ir_ctx *ctx, FILE *f); +void ir_dump_codegen(const ir_ctx *ctx, FILE *f); /* IR to C conversion (implementation in ir_emit_c.c) */ int ir_emit_c(ir_ctx *ctx, FILE *f); diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index 8b5f911..1c5dbb2 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -255,14 +255,12 @@ enum _ir_rule { IR_LAST_RULE }; -#ifdef IR_DEBUG #define IR_RULE_NAME(name) #name, const char *ir_rule_name[IR_LAST_OP] = { NULL, IR_RULES(IR_RULE_NAME) NULL }; -#endif /* register allocation */ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constraints *constraints) diff --git a/ir_dump.c b/ir_dump.c index c21a299..bafac5f 100644 --- a/ir_dump.c +++ b/ir_dump.c @@ -445,3 +445,254 @@ void ir_dump_live_ranges(const ir_ctx *ctx, FILE *f) #endif fprintf(f, "}\n"); } + +void ir_dump_codegen(const ir_ctx *ctx, FILE *f) +{ + ir_ref i, j, n, ref, *p; + ir_insn *insn; + uint32_t flags, b; + ir_block *bb; + bool first; + + fprintf(f, "{\n"); + for (i = IR_UNUSED + 1, insn = ctx->ir_base - i; i < ctx->consts_count; i++, insn--) { + fprintf(f, "\t%s c_%d = ", ir_type_cname[insn->type], i); + if (insn->op == IR_FUNC) { + if (!insn->const_flags) { + fprintf(f, "func(%s)", ir_get_str(ctx, insn->val.i32)); + } else { + fprintf(f, "func(%s, %d)", ir_get_str(ctx, insn->val.i32), insn->const_flags); + } + } else if (insn->op == IR_FUNC_ADDR) { + fprintf(f, "func_addr("); + ir_print_const(ctx, insn, f, true); + if (insn->const_flags) { + fprintf(f, ", %d", insn->const_flags); + } + fprintf(f, ")"); + } else { + ir_print_const(ctx, insn, f, true); + } + fprintf(f, ";\n"); + } + + for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) { + fprintf(f, "#BB%d:\n", b); + + for (i = bb->start, insn = ctx->ir_base + i; i <= bb->end;) { + flags = ir_op_flags[insn->op]; + if (flags & IR_OP_FLAG_CONTROL) { + if (!(flags & IR_OP_FLAG_MEM) || insn->type == IR_VOID) { + fprintf(f, "\tl_%d = ", i); + } else { + fprintf(f, "\t%s d_%d", ir_type_cname[insn->type], i); + if (ctx->vregs && ctx->vregs[i]) { + fprintf(f, " {R%d}", ctx->vregs[i]); + } + if (ctx->regs) { + int8_t reg = ctx->regs[i][0]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), insn->type), + (reg & (IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL)) ? ":store" : ""); + } + } + fprintf(f, ", l_%d = ", i); + } + } else { + fprintf(f, "\t"); + if (flags & IR_OP_FLAG_DATA) { + fprintf(f, "%s d_%d", ir_type_cname[insn->type], i); + if (ctx->vregs && ctx->vregs[i]) { + fprintf(f, " {R%d}", ctx->vregs[i]); + } + if (ctx->regs) { + int8_t reg = ctx->regs[i][0]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), insn->type), + (reg & (IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL)) ? ":store" : ""); + } + } + fprintf(f, " = "); + } + } + fprintf(f, "%s", ir_op_name[insn->op]); + n = ir_operands_count(ctx, insn); + if ((insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) && n != 2) { + fprintf(f, "/%d", n); + } else if ((insn->op == IR_CALL || insn->op == IR_TAILCALL) && n != 2) { + fprintf(f, "/%d", n - 2); + } else if (insn->op == IR_PHI && n != 3) { + fprintf(f, "/%d", n - 1); + } else if (insn->op == IR_SNAPSHOT) { + fprintf(f, "/%d", n - 1); + } + first = 1; + for (j = 1, p = insn->ops + 1; j <= n; j++, p++) { + uint32_t opnd_kind = IR_OPND_KIND(flags, j); + + ref = *p; + if (ref) { + switch (opnd_kind) { + case IR_OPND_DATA: + if (IR_IS_CONST_REF(ref)) { + fprintf(f, "%sc_%d", first ? "(" : ", ", -ref); + } else { + fprintf(f, "%sd_%d", first ? "(" : ", ", ref); + } + if (ctx->vregs && ref > 0 && ctx->vregs[ref]) { + fprintf(f, " {R%d}", ctx->vregs[ref]); + } + if (ctx->regs) { + int8_t *regs = ctx->regs[i]; + int8_t reg = regs[j]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), + (reg & (IR_REG_SPILL_LOAD|IR_REG_SPILL_SPECIAL)) ? ":load" : ""); + } + } + first = 0; + break; + case IR_OPND_CONTROL: + case IR_OPND_CONTROL_DEP: + case IR_OPND_CONTROL_REF: + fprintf(f, "%sl_%d", first ? "(" : ", ", ref); + first = 0; + break; + case IR_OPND_STR: + fprintf(f, "%s\"%s\"", first ? "(" : ", ", ir_get_str(ctx, ref)); + first = 0; + break; + case IR_OPND_PROB: + if (ref == 0) { + break; + } + IR_FALLTHROUGH; + case IR_OPND_NUM: + fprintf(f, "%s%d", first ? "(" : ", ", ref); + first = 0; + break; + } + } else if (opnd_kind == IR_OPND_NUM) { + fprintf(f, "%s%d", first ? "(" : ", ", ref); + first = 0; + } else if (IR_IS_REF_OPND_KIND(opnd_kind) && j != n) { + fprintf(f, "%snull", first ? "(" : ", "); + first = 0; + } + } + if (first) { + fprintf(f, ";"); + } else { + fprintf(f, ");"); + } + if (((flags & IR_OP_FLAG_DATA) || ((flags & IR_OP_FLAG_MEM) && insn->type != IR_VOID)) && ctx->binding) { + ir_ref var = ir_binding_find(ctx, i); + if (var) { + IR_ASSERT(var < 0); + fprintf(f, " # BIND(0x%x);", -var); + } + } + if (ctx->rules) { + uint32_t rule = ctx->rules[i]; + uint32_t id = rule & ~(IR_FUSED|IR_SKIPPED|IR_SIMPLE); + + if (id < IR_LAST_OP) { + fprintf(f, " # RULE(%s", ir_op_name[id]); + } else { + IR_ASSERT(id > IR_LAST_OP /*&& id < IR_LAST_RULE*/); + fprintf(f, " # RULE(%s", ir_rule_name[id - IR_LAST_OP]); + } + if (rule & IR_FUSED) { + fprintf(f, ":FUSED"); + } + if (rule & IR_SKIPPED) { + fprintf(f, ":SKIPPED"); + } + if (rule & IR_SIMPLE) { + fprintf(f, ":SIMPLE"); + } + fprintf(f, ")"); + } + fprintf(f, "\n"); + n = ir_insn_inputs_to_len(n); + i += n; + insn += n; + } + + if (bb->flags & IR_BB_DESSA_MOVES) { + uint32_t succ; + ir_block *succ_bb; + ir_use_list *use_list; + ir_ref k, i, *p, use_ref, input; + ir_insn *use_insn; + + IR_ASSERT(bb->successors_count == 1); + succ = ctx->cfg_edges[bb->successors]; + succ_bb = &ctx->cfg_blocks[succ]; + IR_ASSERT(succ_bb->predecessors_count > 1); + use_list = &ctx->use_lists[succ_bb->start]; + k = ir_phi_input_number(ctx, succ_bb, b); + + for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { + use_ref = *p; + use_insn = &ctx->ir_base[use_ref]; + if (use_insn->op == IR_PHI) { + input = ir_insn_op(use_insn, k); + if (IR_IS_CONST_REF(input)) { + fprintf(f, "\t# DESSA MOV c_%d", -input); + } else if (ctx->vregs[input] != ctx->vregs[use_ref]) { + fprintf(f, "\t# DESSA MOV d_%d {R%d}", input, ctx->vregs[input]); + } else { + continue; + } + if (ctx->regs) { + int8_t *regs = ctx->regs[use_ref]; + int8_t reg = regs[k]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[input].type), + (reg & (IR_REG_SPILL_LOAD|IR_REG_SPILL_SPECIAL)) ? ":load" : ""); + } + } + fprintf(f, " -> d_%d {R%d}", use_ref, ctx->vregs[use_ref]); + if (ctx->regs) { + int8_t reg = ctx->regs[use_ref][0]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[use_ref].type), + (reg & (IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL)) ? ":store" : ""); + } + } + fprintf(f, "\n"); + } + } + } + + insn = &ctx->ir_base[bb->end]; + if (insn->op == IR_END || insn->op == IR_LOOP_END) { + uint32_t succ; + + IR_ASSERT(bb->successors_count == 1); + succ = ctx->cfg_edges[bb->successors]; + if (succ != b + 1) { + fprintf(f, "\t# GOTO BB%d\n", succ); + } + } else if (insn->op == IR_IF) { + uint32_t true_block, false_block, *p; + + p = &ctx->cfg_edges[bb->successors]; + true_block = *p; + if (ctx->ir_base[ctx->cfg_blocks[true_block].start].op == IR_IF_TRUE) { + false_block = *(p+1); + IR_ASSERT(ctx->ir_base[ctx->cfg_blocks[false_block].start].op == IR_IF_FALSE); + } else { + false_block = true_block; + IR_ASSERT(ctx->ir_base[ctx->cfg_blocks[false_block].start].op == IR_IF_FALSE); + true_block = *(p+1); + IR_ASSERT(ctx->ir_base[ctx->cfg_blocks[true_block].start].op == IR_IF_TRUE); + } + fprintf(f, "\t# IF_TRUE BB%d, IF_FALSE BB%d\n", true_block, false_block); + } else if (insn->op == IR_SWITCH) { + fprintf(f, "\t# SWITCH ...\n"); + } + } + fprintf(f, "}\n"); +} diff --git a/ir_main.c b/ir_main.c index 49e8b02..93ef968 100644 --- a/ir_main.c +++ b/ir_main.c @@ -61,6 +61,7 @@ static void help(const char *cmd) #define IR_DUMP_CFG (1<<4) #define IR_DUMP_CFG_MAP (1<<5) #define IR_DUMP_LIVE_RANGES (1<<6) +#define IR_DUMP_CODEGEN (1<<7) #define IR_DUMP_AFTER_LOAD (1<<16) #define IR_DUMP_AFTER_SCCP (1<<17) @@ -98,7 +99,12 @@ static int _save(ir_ctx *ctx, uint32_t dump, uint32_t pass, const char *dump_fil snprintf(fn, sizeof(fn)-1, "06-coalescing-%s", dump_file); dump_file = fn; } else if (pass == IR_DUMP_FINAL) { - snprintf(fn, sizeof(fn)-1, "07-final-%s", dump_file); + if (dump & IR_DUMP_CODEGEN) { + snprintf(fn, sizeof(fn)-1, "07-codegen-%s", dump_file); + } else { + snprintf(fn, sizeof(fn)-1, "07-final-%s", dump_file); + } + dump_file = fn; dump_file = fn; } } @@ -110,7 +116,9 @@ static int _save(ir_ctx *ctx, uint32_t dump, uint32_t pass, const char *dump_fil } else { f = stderr; } - if (dump & IR_DUMP_SAVE) { + if (pass == IR_DUMP_FINAL && (dump & IR_DUMP_CODEGEN)) { + ir_dump_codegen(ctx, f); + } else if (dump & IR_DUMP_SAVE) { ir_save(ctx, f); } if (dump & IR_DUMP_DUMP) { @@ -209,7 +217,7 @@ int ir_compile_func(ir_ctx *ctx, int opt_level, uint32_t dump, const char *dump_ ir_compute_dessa_moves(ctx); } - if ((dump & (IR_DUMP_FINAL|IR_DUMP_AFTER_ALL)) + if ((dump & (IR_DUMP_FINAL|IR_DUMP_AFTER_ALL|IR_DUMP_CODEGEN)) && !_save(ctx, dump, IR_DUMP_FINAL, dump_file)) { return 0; } @@ -293,6 +301,8 @@ int main(int argc, char **argv) dump |= IR_DUMP_CFG_MAP; } else if (strcmp(argv[i], "--dump-live-ranges") == 0) { dump |= IR_DUMP_LIVE_RANGES; + } else if (strcmp(argv[i], "--dump-codegen") == 0) { + dump |= IR_DUMP_CODEGEN; } else if (strcmp(argv[i], "--dump-after-load") == 0) { dump |= IR_DUMP_AFTER_LOAD; } else if (strcmp(argv[i], "--dump-after-sccp") == 0) { @@ -332,8 +342,6 @@ int main(int argc, char **argv) flags |= IR_DEBUG_SCHEDULE; } else if (strcmp(argv[i], "--debug-ra") == 0) { flags |= IR_DEBUG_RA; - } else if (strcmp(argv[i], "--debug-codegen") == 0) { - flags |= IR_DEBUG_CODEGEN; #endif } else if (strcmp(argv[i], "--debug-regset") == 0) { if (i + 1 == argc || argv[i + 1][0] == '-') { diff --git a/ir_private.h b/ir_private.h index a8bb69f..093d4f6 100644 --- a/ir_private.h +++ b/ir_private.h @@ -1164,9 +1164,7 @@ IR_ALWAYS_INLINE int8_t ir_get_alocated_reg(const ir_ctx *ctx, ir_ref ref, int o #define IR_RULE_MASK 0xff -#ifdef IR_DEBUG extern const char *ir_rule_name[]; -#endif typedef struct _ir_target_constraints ir_target_constraints; diff --git a/ir_save.c b/ir_save.c index a65d6a8..64e0019 100644 --- a/ir_save.c +++ b/ir_save.c @@ -14,9 +14,6 @@ void ir_save(const ir_ctx *ctx, FILE *f) ir_insn *insn; uint32_t flags; bool first; -#ifdef IR_DEBUG - bool verbose = (ctx->flags & IR_DEBUG_CODEGEN); -#endif fprintf(f, "{\n"); for (i = IR_UNUSED + 1, insn = ctx->ir_base - i; i < ctx->consts_count; i++, insn--) { @@ -43,11 +40,6 @@ void ir_save(const ir_ctx *ctx, FILE *f) for (i = IR_UNUSED + 1, insn = ctx->ir_base + i; i < ctx->insns_count;) { flags = ir_op_flags[insn->op]; if (flags & IR_OP_FLAG_CONTROL) { -#ifdef IR_DEBUG - if (verbose && ctx->cfg_map && (flags & IR_OP_FLAG_BB_START)) { - fprintf(f, "#BB%d:\n", ctx->cfg_map[i]); - } -#endif if (!(flags & IR_OP_FLAG_MEM) || insn->type == IR_VOID) { fprintf(f, "\tl_%d = ", i); } else { @@ -56,20 +48,7 @@ void ir_save(const ir_ctx *ctx, FILE *f) } else { fprintf(f, "\t"); if (flags & IR_OP_FLAG_DATA) { - fprintf(f, "%s d_%d", ir_type_cname[insn->type], i); -#ifdef IR_DEBUG - if (verbose && ctx->vregs && ctx->vregs[i]) { - fprintf(f, " {R%d}", ctx->vregs[i]); - } - if (verbose && ctx->regs) { - int8_t reg = ctx->regs[i][0]; - if (reg != IR_REG_NONE) { - fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), - (reg & (IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL)) ? ":store" : ""); - } - } -#endif - fprintf(f, " = "); + fprintf(f, "%s d_%d = ", ir_type_cname[insn->type], i); } } fprintf(f, "%s", ir_op_name[insn->op]); @@ -96,18 +75,6 @@ void ir_save(const ir_ctx *ctx, FILE *f) } else { fprintf(f, "%sd_%d", first ? "(" : ", ", ref); } -#ifdef IR_DEBUG - if (verbose && ctx->vregs && ref > 0 && ctx->vregs[ref]) { - fprintf(f, " {R%d}", ctx->vregs[ref]); - } - if (verbose && ctx->regs) { - int8_t reg = ctx->regs[i][j]; - if (reg != IR_REG_NONE) { - fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), - (reg & (IR_REG_SPILL_LOAD|IR_REG_SPILL_SPECIAL)) ? ":load" : ""); - } - } -#endif first = 0; break; case IR_OPND_CONTROL: @@ -150,82 +117,7 @@ void ir_save(const ir_ctx *ctx, FILE *f) fprintf(f, " # BIND(0x%x);", -var); } } -#ifdef IR_DEBUG - if (verbose && ctx->rules) { - uint32_t rule = ctx->rules[i]; - uint32_t id = rule & ~(IR_FUSED|IR_SKIPPED|IR_SIMPLE); - - if (id < IR_LAST_OP) { - fprintf(f, " # RULE(%s", ir_op_name[id]); - } else { - IR_ASSERT(id > IR_LAST_OP /*&& id < IR_LAST_RULE*/); - fprintf(f, " # RULE(%s", ir_rule_name[id - IR_LAST_OP]); - } - if (rule & IR_FUSED) { - fprintf(f, ":FUSED"); - } - if (rule & IR_SKIPPED) { - fprintf(f, ":SKIPPED"); - } - if (rule & IR_SIMPLE) { - fprintf(f, ":SIMPLE"); - } - fprintf(f, ")"); - } -#endif fprintf(f, "\n"); -#ifdef IR_DEBUG - if (verbose && ctx->cfg_map && (flags & IR_OP_FLAG_BB_END)) { - uint32_t b = ctx->cfg_map[i]; - ir_block *bb = &ctx->cfg_blocks[b]; - - if (bb->flags & IR_BB_DESSA_MOVES) { - uint32_t succ; - ir_block *succ_bb; - ir_use_list *use_list; - ir_ref k, i, *p, use_ref, input; - ir_insn *use_insn; - - IR_ASSERT(bb->successors_count == 1); - succ = ctx->cfg_edges[bb->successors]; - succ_bb = &ctx->cfg_blocks[succ]; - IR_ASSERT(succ_bb->predecessors_count > 1); - use_list = &ctx->use_lists[succ_bb->start]; - k = ir_phi_input_number(ctx, succ_bb, b); - - for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { - use_ref = *p; - use_insn = &ctx->ir_base[use_ref]; - if (use_insn->op == IR_PHI) { - input = ir_insn_op(use_insn, k); - if (IR_IS_CONST_REF(input)) { - fprintf(f, "\t# DESSA MOV c_%d", -input); - } else if (ctx->vregs[input] != ctx->vregs[use_ref]) { - fprintf(f, "\t# DESSA MOV d_%d {R%d}", input, ctx->vregs[input]); - } else { - continue; - } - if (ctx->regs) { - int8_t reg = ctx->regs[use_ref][k]; - if (reg != IR_REG_NONE) { - fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), - (reg & (IR_REG_SPILL_LOAD|IR_REG_SPILL_SPECIAL)) ? ":load" : ""); - } - } - fprintf(f, " -> d_%d {R%d}", use_ref, ctx->vregs[use_ref]); - if (ctx->regs) { - int8_t reg = ctx->regs[use_ref][0]; - if (reg != IR_REG_NONE) { - fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), - (reg & (IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL)) ? ":store" : ""); - } - } - fprintf(f, "\n"); - } - } - } - } -#endif n = ir_insn_inputs_to_len(n); i += n; insn += n; diff --git a/ir_test.c b/ir_test.c index f1f3ee5..0b3cdea 100644 --- a/ir_test.c +++ b/ir_test.c @@ -127,8 +127,6 @@ int main(int argc, char **argv) flags |= IR_DEBUG_SCHEDULE; } else if (strcmp(argv[i], "--debug-ra") == 0) { flags |= IR_DEBUG_RA; - } else if (strcmp(argv[i], "--debug-codegen") == 0) { - flags |= IR_DEBUG_CODEGEN; #endif } else if (strcmp(argv[i], "--debug-regset") == 0) { if (i + 1 == argc || argv[i + 1][0] == '-') { diff --git a/ir_x86.dasc b/ir_x86.dasc index 01e3cbd..7de1634 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -514,14 +514,12 @@ enum _ir_rule { IR_LAST_RULE }; -#ifdef IR_DEBUG #define IR_RULE_NAME(name) #name, const char *ir_rule_name[IR_LAST_OP] = { NULL, IR_RULES(IR_RULE_NAME) NULL }; -#endif /* register allocation */ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constraints *constraints)