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:
zzy
2026-05-05 15:59:31 +08:00
parent 676f3ec82c
commit aa8a1ff8ce
14 changed files with 842 additions and 399 deletions

View File

@@ -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___ */

View File

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