frontend: compile: create and (optionally) show isel graph for each block

This commit is contained in:
2025-08-29 15:47:42 +01:00
parent 9c1e0958b0
commit ebfbbd0a1a

View File

@@ -1,5 +1,6 @@
#include "../debug.h" #include "../debug.h"
#include "cmd.h" #include "cmd.h"
#include "mie/select/builder.h"
#include <blue/cmd.h> #include <blue/cmd.h>
#include <blue/term.h> #include <blue/term.h>
@@ -11,8 +12,12 @@
#include <ivy/lang/diag.h> #include <ivy/lang/diag.h>
#include <ivy/lang/lex.h> #include <ivy/lang/lex.h>
#include <mie/ctx.h> #include <mie/ctx.h>
#include <mie/ir/block.h>
#include <mie/ir/convert.h> #include <mie/ir/convert.h>
#include <mie/ir/func.h>
#include <mie/ir/module.h> #include <mie/ir/module.h>
#include <mie/select/builder.h>
#include <mie/select/graph.h>
#include <stdio.h> #include <stdio.h>
enum { enum {
@@ -20,6 +25,8 @@ enum {
OPT_SHOW_LEX_TOKENS, OPT_SHOW_LEX_TOKENS,
OPT_SHOW_AST_NODES, OPT_SHOW_AST_NODES,
OPT_SHOW_IR, OPT_SHOW_IR,
OPT_SHOW_ISEL_PRE,
OPT_SHOW_ISEL_POST,
}; };
struct codegen_args { struct codegen_args {
@@ -54,6 +61,9 @@ static int compile_file(const char *path, const b_arglist *args)
> 0; > 0;
bool show_ir bool show_ir
= b_arglist_get_count(args, OPT_SHOW_IR, B_COMMAND_INVALID_ID) > 0; = b_arglist_get_count(args, OPT_SHOW_IR, B_COMMAND_INVALID_ID) > 0;
bool show_isel_pre
= b_arglist_get_count(args, OPT_SHOW_ISEL_PRE, B_COMMAND_INVALID_ID)
> 0;
enum ivy_status status = IVY_OK; enum ivy_status status = IVY_OK;
struct ivy_file *src = NULL; struct ivy_file *src = NULL;
@@ -123,11 +133,6 @@ static int compile_file(const char *path, const b_arglist *args)
if (status != IVY_OK) { if (status != IVY_OK) {
ivy_diag_ctx_write( ivy_diag_ctx_write(
diag, IVY_DIAG_FORMAT_PRETTY, &diag_stream); diag, IVY_DIAG_FORMAT_PRETTY, &diag_stream);
#if 0
b_err("failed to parse '%s'", path);
b_i("reason: lex error (%s)",
ivy_status_to_string(ivy_lexer_get_status(lex)));
#endif
break; break;
} }
@@ -172,11 +177,6 @@ static int compile_file(const char *path, const b_arglist *args)
ivy_ast_node_iterate(root, &it, print_ast_node, NULL); ivy_ast_node_iterate(root, &it, print_ast_node, NULL);
} }
if (!show_ir) {
ivy_parser_destroy(parser, NULL);
return 0;
}
ivy_codegen_start_module(codegen); ivy_codegen_start_module(codegen);
struct ivy_ast_node *node = ivy_parser_root_node(parser); struct ivy_ast_node *node = ivy_parser_root_node(parser);
@@ -197,14 +197,64 @@ static int compile_file(const char *path, const b_arglist *args)
struct mie_module *mod = NULL; struct mie_module *mod = NULL;
ivy_codegen_end_module(codegen, &mod); ivy_codegen_end_module(codegen, &mod);
struct mie_ir_converter *convert if (show_ir) {
= mie_ir_converter_create(ctx, MIE_IR_MEM, MIE_IR_TEXT); struct mie_ir_converter *convert
mie_ir_converter_set_src_value(convert, MIE_VALUE(mod)); = mie_ir_converter_create(ctx, MIE_IR_MEM, MIE_IR_TEXT);
mie_ir_converter_set_dest_file(convert, stdout); mie_ir_converter_set_src_value(convert, MIE_VALUE(mod));
mie_ir_converter_process(convert); mie_ir_converter_set_dest_file(convert, stdout);
mie_ir_converter_process(convert);
mie_ir_converter_destroy(convert);
}
struct mie_select_builder *builder = mie_select_builder_create(ctx);
b_queue_iterator func_it;
b_queue_foreach (&func_it, &mod->m_func) {
struct mie_value *func_v
= b_unbox(struct mie_value, func_it.entry, v_entry);
struct mie_func *func = (struct mie_func *)func_v;
b_queue_iterator block_it;
b_queue_foreach (&block_it, &func->f_blocks) {
struct mie_value *block_v = b_unbox(
struct mie_value, block_it.entry, v_entry);
struct mie_block *block = (struct mie_block *)block_v;
b_queue_iterator instr_it;
b_queue_foreach (&instr_it, &block->b_phi) {
struct mie_value *instr_v = b_unbox(
struct mie_value, instr_it.entry, v_entry);
mie_select_builder_push_instr(
builder, (struct mie_instr *)instr_v);
}
b_queue_foreach (&instr_it, &block->b_instr) {
struct mie_value *instr_v = b_unbox(
struct mie_value, instr_it.entry, v_entry);
mie_select_builder_push_instr(
builder, (struct mie_instr *)instr_v);
}
if (block->b_terminator) {
mie_select_builder_push_instr(
builder, block->b_terminator);
}
struct mie_select_graph *graph
= mie_select_builder_finish(builder);
if (show_isel_pre) {
printf("%s.%s instruction graph:\n",
func->f_base.v_name.n_str,
block->b_base.v_name.n_str);
mie_select_graph_dump_dot(graph);
mie_select_graph_destroy(graph);
}
}
}
mie_value_destroy(MIE_VALUE(mod)); mie_value_destroy(MIE_VALUE(mod));
mie_ir_converter_destroy(convert);
ivy_codegen_destroy(codegen); ivy_codegen_destroy(codegen);
ivy_parser_destroy(parser, NULL); ivy_parser_destroy(parser, NULL);
@@ -267,6 +317,24 @@ B_COMMAND(CMD_COMPILE, CMD_ROOT)
"input files."); "input files.");
} }
B_COMMAND_OPTION(OPT_SHOW_ISEL_PRE)
{
B_OPTION_LONG_NAME("show-isel-pre");
B_OPTION_SHORT_NAME('s');
B_OPTION_DESC(
"print the instruction selection graph before "
"selection has taken place.");
}
B_COMMAND_OPTION(OPT_SHOW_ISEL_POST)
{
B_OPTION_LONG_NAME("show-isel-post");
B_OPTION_SHORT_NAME('m');
B_OPTION_DESC(
"print the instruction selection graph after "
"selection has taken place.");
}
B_COMMAND_ARG(ARG_SOURCE_FILE) B_COMMAND_ARG(ARG_SOURCE_FILE)
{ {
B_ARG_NAME("source file"); B_ARG_NAME("source file");