feat(compiler): 启用 ir2mcode 和 sccf2target 库并实现 x86_64 代码生成
- 在 cbuild.toml 中启用 ir2mcode 和 sccf2target 依赖库 - 修改 justfile 中的构建命令,使用 release 模式并更新 tokei 统计排除 mcode 目录 - 重构 LIR 中的地址操作数类型,将 SCC_LIR_INSTR_KIND_ADDR 重命名为 SCC_LIR_INSTR_KIND_MEM - 实现完整的 MIR 到 x86_64 机器码转换,包括: - 添加 move、compare、binary operation 等指令发射函数 - 实现条件分支和跳转指令生成 - 支持算术、逻辑、移位等基本操作 - 添加调用和返回指令处理 - 实现栈分配和寄存器分配功能 - 完善 ir2mcode 模块,将 MIR 指令转换为机器码 - 更新 ir2sccf 模块,集成机器码生成功能 - 添加 mcode 库的架构支持和内存管理功能 - 修复 PE 文件生成中的空指针检查问题
This commit is contained in:
35
src/config.h
35
src/config.h
@@ -18,6 +18,9 @@ typedef struct {
|
||||
cbool emit_lir;
|
||||
cbool emit_mir;
|
||||
|
||||
cbool emit_flatbin;
|
||||
cbool emit_sccf;
|
||||
cbool emit_target;
|
||||
cbool emit_mir_pass_reg_alloc;
|
||||
cbool emit_mir_pass_stack_layout;
|
||||
cbool emit_mir_pass_prolog_epilog;
|
||||
@@ -43,6 +46,10 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
||||
SCC_HINT_EMIT_HIR,
|
||||
SCC_HINT_EMIT_LIR,
|
||||
SCC_HINT_EMIT_MIR,
|
||||
|
||||
SCC_HINT_EMIT_FLATBIN,
|
||||
SCC_HINT_EMIT_SCCF,
|
||||
SCC_HINT_EMIT_TARGET,
|
||||
};
|
||||
static const char *scc_hints_en[] = {
|
||||
[SCC_HINT_PROG_NAME] = "scc",
|
||||
@@ -65,6 +72,10 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
||||
[SCC_HINT_EMIT_LIR] = "Generate Low-level IR and exit",
|
||||
[SCC_HINT_EMIT_MIR] = "Generate Machine IR and exit",
|
||||
|
||||
[SCC_HINT_EMIT_FLATBIN] = "Generate flat binary and exit",
|
||||
[SCC_HINT_EMIT_SCCF] = "Generate SCCF and exit",
|
||||
[SCC_HINT_EMIT_TARGET] = "Generate target description and exit",
|
||||
|
||||
};
|
||||
static const char *scc_hints_zh[] = {
|
||||
[SCC_HINT_PROG_NAME] = "scc",
|
||||
@@ -84,6 +95,10 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
||||
[SCC_HINT_EMIT_HIR] = "生成`高级中间代码`并退出",
|
||||
[SCC_HINT_EMIT_LIR] = "生成`低级中间代码`并退出",
|
||||
[SCC_HINT_EMIT_MIR] = "生成`机器中间代码`并退出",
|
||||
|
||||
[SCC_HINT_EMIT_FLATBIN] = "生成`flat binary`并退出",
|
||||
[SCC_HINT_EMIT_SCCF] = "生成`SCCF`并退出",
|
||||
[SCC_HINT_EMIT_TARGET] = "生成`目标代码`并退出",
|
||||
};
|
||||
|
||||
const char **scc_hints;
|
||||
@@ -195,6 +210,26 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
||||
scc_hints[SCC_HINT_EMIT_MIR]);
|
||||
scc_argparse_spec_setup_bool(&opt_mir.spec, &(config->emit_mir));
|
||||
scc_argparse_cmd_add_opt(root, &opt_mir);
|
||||
|
||||
// --emit-flatbin
|
||||
scc_argparse_opt_t opt_flatbin;
|
||||
scc_argparse_opt_init(&opt_flatbin, 0, "emit-flatbin",
|
||||
scc_hints[SCC_HINT_EMIT_FLATBIN]);
|
||||
scc_argparse_spec_setup_bool(&opt_flatbin.spec, &(config->emit_flatbin));
|
||||
scc_argparse_cmd_add_opt(root, &opt_flatbin);
|
||||
// --emit-sccf
|
||||
scc_argparse_opt_t opt_sccf;
|
||||
scc_argparse_opt_init(&opt_sccf, 0, "emit-sccf",
|
||||
scc_hints[SCC_HINT_EMIT_SCCF]);
|
||||
scc_argparse_spec_setup_bool(&opt_sccf.spec, &(config->emit_sccf));
|
||||
scc_argparse_cmd_add_opt(root, &opt_sccf);
|
||||
// --emit-target
|
||||
scc_argparse_opt_t opt_emit_target;
|
||||
scc_argparse_opt_init(&opt_emit_target, 0, "emit-target",
|
||||
scc_hints[SCC_HINT_EMIT_TARGET]);
|
||||
scc_argparse_spec_setup_string(&opt_emit_target.spec,
|
||||
&(config->emit_target));
|
||||
scc_argparse_cmd_add_opt(root, &opt_emit_target);
|
||||
}
|
||||
|
||||
#endif /* __SCC_CONFIG_H___ */
|
||||
|
||||
69
src/main.c
69
src/main.c
@@ -10,8 +10,10 @@
|
||||
#include <scc_lir2mir.h>
|
||||
#include <scc_lir_dump.h>
|
||||
#include <scc_mir_dump.h>
|
||||
// #include <scc_ir2mcode.h>
|
||||
// #include <sccf2pe.h>
|
||||
|
||||
#include <scc_ir2mcode.h>
|
||||
#include <scc_ir2sccf.h>
|
||||
#include <sccf2pe.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -65,6 +67,8 @@ static void tree_dump_output(const char *str, usize len, void *user) {
|
||||
|
||||
void init_platform(void);
|
||||
|
||||
#define GET_VALID_FP(fp) (fp == nullptr ? scc_stdout : fp)
|
||||
|
||||
int main(int argc, const char **argv, const char **envp) {
|
||||
init_platform();
|
||||
|
||||
@@ -215,8 +219,7 @@ sstream_drop:
|
||||
scc_tree_dump_init(&tree_dump, false);
|
||||
}
|
||||
scc_ast_dump_node(&tree_dump, (scc_ast_node_t *)translation_unit);
|
||||
scc_tree_dump_flush(&tree_dump, tree_dump_output,
|
||||
fp == nullptr ? scc_stdout : fp);
|
||||
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
|
||||
scc_tree_dump_drop(&tree_dump);
|
||||
return 0;
|
||||
}
|
||||
@@ -241,8 +244,7 @@ sstream_drop:
|
||||
// scc_ir_dump_cprog(&ir_dump_ctx);
|
||||
scc_hir_dump_cprog_linear(&ir_dump_ctx);
|
||||
|
||||
scc_tree_dump_flush(&tree_dump, tree_dump_output,
|
||||
fp == nullptr ? scc_stdout : fp);
|
||||
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
|
||||
scc_tree_dump_drop(&tree_dump);
|
||||
return 0;
|
||||
}
|
||||
@@ -262,8 +264,7 @@ sstream_drop:
|
||||
// scc_ir_dump_cprog(&ir_dump_ctx);
|
||||
scc_lir_dump_module(&lir_dump_ctx);
|
||||
|
||||
scc_tree_dump_flush(&tree_dump, tree_dump_output,
|
||||
fp == nullptr ? scc_stdout : fp);
|
||||
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
|
||||
scc_tree_dump_drop(&tree_dump);
|
||||
return 0;
|
||||
}
|
||||
@@ -282,30 +283,46 @@ sstream_drop:
|
||||
scc_mir_dump_init(&mir_dump_ctx, &tree_dump, &mir_module);
|
||||
scc_mir_dump_module(&mir_dump_ctx);
|
||||
|
||||
scc_tree_dump_flush(&tree_dump, tree_dump_output,
|
||||
fp == nullptr ? scc_stdout : fp);
|
||||
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
|
||||
scc_tree_dump_drop(&tree_dump);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// scc_ir2mcode_ctx_t ir2mcode_ctx;
|
||||
// sccf_builder_t sccf_builder;
|
||||
// scc_ir2mcode_init(&ir2mcode_ctx, &cprog, &sccf_builder,
|
||||
// SCC_MCODE_ARCH_AMD64);
|
||||
// scc_ir2mcode(&ir2mcode_ctx);
|
||||
// scc_ir2mcode_drop(&ir2mcode_ctx);
|
||||
if (config.emit_flatbin) {
|
||||
scc_mcode_t mcode = {0};
|
||||
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||
scc_ir2mcode(&mcode, &mir_module);
|
||||
if (fp == nullptr) {
|
||||
LOG_WARN("emit flatbin can't write to stdout");
|
||||
return 0;
|
||||
}
|
||||
usize ret = scc_fwrite(fp, scc_vec_unsafe_get_data(mcode.mcode),
|
||||
scc_vec_size(mcode.mcode));
|
||||
if (ret != scc_vec_size(mcode.mcode)) {
|
||||
LOG_ERROR("write flatbin failed, write %zu but need write %zu\n",
|
||||
ret, scc_vec_size(mcode.mcode));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sccf_builder_set_entry_symbol_name(&sccf_builder,
|
||||
// config.entry_point_symbol);
|
||||
// const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder);
|
||||
// scc_pe_builder_t pe_builder;
|
||||
// sccf2pe(&pe_builder, sccf);
|
||||
sccf_builder_t sccf_builder = {0};
|
||||
sccf_builder_init(&sccf_builder);
|
||||
scc_ir2sccf(&sccf_builder, &mir_module);
|
||||
sccf_builder_set_entry_symbol_name(&sccf_builder,
|
||||
config.entry_point_symbol);
|
||||
if (config.emit_sccf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if (fp == nullptr) {
|
||||
// scc_printf("output exe at %s\n", config.output_file);
|
||||
// } else {
|
||||
// scc_pe_dump_to_file(&pe_builder, config.output_file);
|
||||
// }
|
||||
const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder);
|
||||
scc_pe_builder_t pe_builder;
|
||||
sccf2pe(&pe_builder, sccf);
|
||||
if (fp == nullptr) {
|
||||
scc_printf("output exe at %s\n", config.output_file);
|
||||
} else {
|
||||
scc_pe_dump_to_file(&pe_builder, config.output_file);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user