feat(ir): 添加MIR中间表示层并重构LIR相关代码

- 新增mir库模块,包含scc_mir、scc_mir_module、scc_mir_dump等组件
- 添加LIR到MIR的转换接口scc_lir2mir
- 定义MIR操作数类型和指令结构,支持虚拟寄存器、物理寄存器、立即数等
- 实现x86_64指令选择器,将LIR指令转换为MIR指令
- 重构LIR模块中函数参数命名,统一使用lir_module参数名
- 移除LIR中物理寄存器相关的代码和注释
- 更新cbuild.toml依赖配置,添加mir模块依赖
This commit is contained in:
zzy
2026-04-26 17:38:30 +08:00
parent e850b5c981
commit f57ba9bd31
21 changed files with 830 additions and 54 deletions

View File

@@ -11,6 +11,7 @@ dependencies = [
{ name = "ast2ir", path = "./libs/ast2ir" }, { name = "ast2ir", path = "./libs/ast2ir" },
{ name = "hir", path = "./libs/ir/hir" }, { name = "hir", path = "./libs/ir/hir" },
{ name = "lir", path = "./libs/ir/lir" }, { name = "lir", path = "./libs/ir/lir" },
{ name = "mir", path = "./libs/ir/mir" },
# { name = "ir2mcode", path = "./libs/ir2mcode" }, # { name = "ir2mcode", path = "./libs/ir2mcode" },
# { name = "sccf2target", path = "./libs/target/sccf2target" }, # { name = "sccf2target", path = "./libs/target/sccf2target" },

View File

@@ -31,9 +31,9 @@ typedef enum scc_lir_attr {
} scc_lir_attr_t; } scc_lir_attr_t;
typedef enum { typedef enum {
SCC_LIR_INSTR_KIND_NONE, // 无操作数 SCC_LIR_INSTR_KIND_NONE, // 无操作数
SCC_LIR_INSTR_KIND_VREG, // 虚拟寄存器 SCC_LIR_INSTR_KIND_VREG, // 虚拟寄存器
SCC_LIR_INSTR_KIND_PREG, // 物理寄存器 (后端定义编号) // SCC_LIR_INSTR_KIND_PREG, // 物理寄存器 (后端定义编号)
SCC_LIR_INSTR_KIND_IMM, // 整数立即数 SCC_LIR_INSTR_KIND_IMM, // 整数立即数
SCC_LIR_INSTR_KIND_FIMM, // 浮点立即数 SCC_LIR_INSTR_KIND_FIMM, // 浮点立即数
SCC_LIR_INSTR_KIND_SYMBOL, // 全局符号 (函数名、全局变量、字符串常量) SCC_LIR_INSTR_KIND_SYMBOL, // 全局符号 (函数名、全局变量、字符串常量)

View File

@@ -7,7 +7,7 @@
typedef struct { typedef struct {
scc_tree_dump_t *dump_ctx; scc_tree_dump_t *dump_ctx;
scc_lir_module_t *module; scc_lir_module_t *lir_module;
} scc_lir_dump_ctx_t; } scc_lir_dump_ctx_t;
static inline void scc_lir_dump_init(scc_lir_dump_ctx_t *ctx, static inline void scc_lir_dump_init(scc_lir_dump_ctx_t *ctx,
@@ -15,7 +15,7 @@ static inline void scc_lir_dump_init(scc_lir_dump_ctx_t *ctx,
scc_lir_module_t *module) { scc_lir_module_t *module) {
Assert(ctx != nullptr && dump_ctx != nullptr && module != nullptr); Assert(ctx != nullptr && dump_ctx != nullptr && module != nullptr);
ctx->dump_ctx = dump_ctx; ctx->dump_ctx = dump_ctx;
ctx->module = module; ctx->lir_module = module;
} }
void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins); void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins);
void scc_lir_dump_bblock(scc_lir_dump_ctx_t *ctx, const scc_lir_bblock_t *bb); void scc_lir_dump_bblock(scc_lir_dump_ctx_t *ctx, const scc_lir_bblock_t *bb);

View File

@@ -22,12 +22,12 @@ typedef struct scc_lir_module {
/** /**
* @brief 初始化 LIR 模块 * @brief 初始化 LIR 模块
*/ */
void scc_lir_module_init(scc_lir_module_t *module); void scc_lir_module_init(scc_lir_module_t *lir_module);
/** /**
* @brief 销毁 LIR 模块,释放所有函数和符号资源 * @brief 销毁 LIR 模块,释放所有函数和符号资源
*/ */
void scc_lir_module_drop(scc_lir_module_t *module); void scc_lir_module_drop(scc_lir_module_t *lir_module);
/** /**
* @brief 添加一个函数声明(外部或未定义) * @brief 添加一个函数声明(外部或未定义)
@@ -36,7 +36,7 @@ void scc_lir_module_drop(scc_lir_module_t *module);
* @param attr 属性 * @param attr 属性
* @return 符号指针 * @return 符号指针
*/ */
scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *module, scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *lir_module,
const char *name); const char *name);
/** /**
@@ -50,7 +50,7 @@ scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *module,
* @param attr 属性 * @param attr 属性
* @return 符号指针 * @return 符号指针
*/ */
scc_lir_symbol_id_t scc_lir_module_add_data(scc_lir_module_t *module, scc_lir_symbol_id_t scc_lir_module_add_data(scc_lir_module_t *lir_module,
const char *name, const char *name,
scc_cfg_symbol_kind_t kind, scc_cfg_symbol_kind_t kind,
const u8 *init_data, usize size, const u8 *init_data, usize size,

View File

@@ -14,7 +14,6 @@ typedef struct {
scc_lir_func_t *current_func; scc_lir_func_t *current_func;
scc_lir_instr_vec_t instrs; scc_lir_instr_vec_t instrs;
scc_hashtable_t bb_map; // ir_bblock_ref_t -> scc_lir_bblock_id_t
scc_hashtable_t value_to_vreg; // ir_value_ref_t -> unsigned int vreg scc_hashtable_t value_to_vreg; // ir_value_ref_t -> unsigned int vreg
scc_hashtable_t func_decl_map; // ir_func_ref_t -> const char* (用于调用) scc_hashtable_t func_decl_map; // ir_func_ref_t -> const char* (用于调用)
} ir2lir_ctx_t; } ir2lir_ctx_t;
@@ -23,13 +22,11 @@ static void ir2lir_ctx_init(ir2lir_ctx_t *ctx, scc_lir_module_t *lir_module,
scc_hir_module_t *hir_module) { scc_hir_module_t *hir_module) {
ctx->hir_module = hir_module; ctx->hir_module = hir_module;
ctx->lir_module = lir_module; ctx->lir_module = lir_module;
scc_hashtable_usize_init(&ctx->bb_map);
scc_hashtable_usize_init(&ctx->value_to_vreg); scc_hashtable_usize_init(&ctx->value_to_vreg);
scc_hashtable_usize_init(&ctx->func_decl_map); scc_hashtable_usize_init(&ctx->func_decl_map);
} }
static void ir2lir_ctx_drop(ir2lir_ctx_t *ctx) { static void ir2lir_ctx_drop(ir2lir_ctx_t *ctx) {
scc_hashtable_drop(&ctx->bb_map);
scc_hashtable_drop(&ctx->value_to_vreg); scc_hashtable_drop(&ctx->value_to_vreg);
scc_hashtable_drop(&ctx->func_decl_map); scc_hashtable_drop(&ctx->func_decl_map);
} }
@@ -107,7 +104,8 @@ static int get_vreg_for_value(ir2lir_ctx_t *ctx, scc_hir_value_ref_t val_ref) {
if (found) if (found)
return (int)(usize)found; return (int)(usize)found;
int vreg = SCC_LIR_FUNC_META(ctx->current_func)->vregs_count++; int vreg = ++(SCC_LIR_FUNC_META(ctx->current_func)->vregs_count);
Assert(vreg != 0);
scc_hashtable_set(&ctx->value_to_vreg, (void *)(usize)val_ref, scc_hashtable_set(&ctx->value_to_vreg, (void *)(usize)val_ref,
(void *)(usize)vreg); (void *)(usize)vreg);
return vreg; return vreg;
@@ -386,25 +384,18 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
case SCC_HIR_VALUE_TAG_BRANCH: { case SCC_HIR_VALUE_TAG_BRANCH: {
scc_lir_val_t cond = scc_lir_val_t cond =
ir_value_to_lir_operand(ctx, value->data.branch.cond); ir_value_to_lir_operand(ctx, value->data.branch.cond);
scc_lir_bblock_id_t true_bb =
(scc_lir_bblock_id_t)(uintptr_t)scc_hashtable_get(
&ctx->bb_map,
(void *)(uintptr_t)value->data.branch.true_bblock);
scc_lir_bblock_id_t false_bb =
(scc_lir_bblock_id_t)(uintptr_t)scc_hashtable_get(
&ctx->bb_map,
(void *)(uintptr_t)value->data.branch.false_bblock);
scc_lir_instr_t instr = { scc_lir_instr_t instr = {
.op = SCC_LIR_BR, .arg0 = cond, .metadata.br = {true_bb, false_bb}}; .op = SCC_LIR_BR,
.arg0 = cond,
.metadata.br = {value->data.branch.true_bblock,
value->data.branch.false_bblock}};
scc_lir_builder_add_instr(ctx, &instr); scc_lir_builder_add_instr(ctx, &instr);
break; break;
} }
case SCC_HIR_VALUE_TAG_JUMP: { case SCC_HIR_VALUE_TAG_JUMP: {
scc_lir_bblock_id_t target =
(scc_lir_bblock_id_t)(usize)scc_hashtable_get(
&ctx->bb_map, (void *)(usize)value->data.jump.target_bblock);
scc_lir_instr_t instr = {.op = SCC_LIR_JMP, scc_lir_instr_t instr = {.op = SCC_LIR_JMP,
.metadata.jmp_target = target}; .metadata.jmp_target =
value->data.jump.target_bblock};
scc_lir_builder_add_instr(ctx, &instr); scc_lir_builder_add_instr(ctx, &instr);
break; break;
} }
@@ -487,7 +478,6 @@ static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
} }
// 清理本次函数翻译的临时映射 // 清理本次函数翻译的临时映射
scc_hashtable_drop(&ctx->bb_map);
scc_hashtable_drop(&ctx->value_to_vreg); scc_hashtable_drop(&ctx->value_to_vreg);
} }

View File

@@ -144,9 +144,9 @@ static void dump_operand(scc_lir_dump_ctx_t *ctx, const scc_lir_val_t *op) {
case SCC_LIR_INSTR_KIND_VREG: case SCC_LIR_INSTR_KIND_VREG:
scc_tree_dump_append_fmt(td, "%%%u", op->data.reg); scc_tree_dump_append_fmt(td, "%%%u", op->data.reg);
break; break;
case SCC_LIR_INSTR_KIND_PREG: // case SCC_LIR_INSTR_KIND_PREG:
scc_tree_dump_append_fmt(td, "Phy%u", op->data.reg); // scc_tree_dump_append_fmt(td, "Phy%u", op->data.reg);
break; // break;
case SCC_LIR_INSTR_KIND_IMM: case SCC_LIR_INSTR_KIND_IMM:
// TODO hack ap // TODO hack ap
scc_tree_dump_append_fmt(td, "%lld", op->data.imm.data.digit); scc_tree_dump_append_fmt(td, "%lld", op->data.imm.data.digit);
@@ -295,7 +295,7 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
break; break;
case SCC_LIR_JMP: case SCC_LIR_JMP:
scc_tree_dump_append_fmt(td, "BB#%zu", ins->metadata.jmp_target); scc_tree_dump_append_fmt(td, "#BB%d", ins->metadata.jmp_target);
break; break;
case SCC_LIR_JMP_INDIRECT: case SCC_LIR_JMP_INDIRECT:
@@ -395,7 +395,7 @@ void scc_lir_dump_bblock(scc_lir_dump_ctx_t *ctx, const scc_lir_bblock_t *bb) {
// 基本块头部 // 基本块头部
scc_tree_dump_begin_line(td); scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "BB%zu", bb->id); scc_tree_dump_node(td, "#BB%zu", bb->id);
if (bb->name) { if (bb->name) {
scc_tree_dump_append_fmt(td, " (%s)", bb->name); scc_tree_dump_append_fmt(td, " (%s)", bb->name);
} }
@@ -430,10 +430,10 @@ void scc_lir_dump_func(scc_lir_dump_ctx_t *ctx, const scc_lir_func_t *func) {
scc_tree_dump_append(td, " {"); scc_tree_dump_append(td, " {");
// 输出所有基本块 // 输出所有基本块
for (usize i = 0; i < scc_vec_size(func->bblocks); ++i) { scc_vec_foreach(func->bblocks, i) {
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i); scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
const scc_cfg_bblock_t *bb = const scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&ctx->module->cfg_module, id); scc_cfg_module_unsafe_get_bblock(&ctx->lir_module->cfg_module, id);
scc_lir_dump_bblock(ctx, bb); scc_lir_dump_bblock(ctx, bb);
} }
@@ -442,18 +442,20 @@ void scc_lir_dump_func(scc_lir_dump_ctx_t *ctx, const scc_lir_func_t *func) {
} }
void scc_lir_dump_module(scc_lir_dump_ctx_t *ctx) { void scc_lir_dump_module(scc_lir_dump_ctx_t *ctx) {
scc_vec_foreach(ctx->module->cfg_module.symbols, i) { scc_vec_foreach(ctx->lir_module->cfg_module.symbols, i) {
// FIXME 0 is null // FIXME 0 is null
if (i == 0) if (i == 0)
continue; continue;
scc_lir_symbol_t *sym = &scc_vec_at(ctx->module->cfg_module.symbols, i); scc_lir_symbol_t *sym =
&scc_vec_at(ctx->lir_module->cfg_module.symbols, i);
scc_tree_dump_begin_line(ctx->dump_ctx); scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "symbol"); scc_tree_dump_node(ctx->dump_ctx, "symbol");
scc_tree_dump_append_fmt(ctx->dump_ctx, " %s", sym->name); scc_tree_dump_append_fmt(ctx->dump_ctx, " %s", sym->name);
} }
scc_vec_foreach(ctx->module->cfg_module.funcs, i) { scc_vec_foreach(ctx->lir_module->cfg_module.funcs, i) {
if (i == 0) if (i == 0)
continue; continue;
scc_lir_dump_func(ctx, &scc_vec_at(ctx->module->cfg_module.funcs, i)); scc_lir_dump_func(ctx,
&scc_vec_at(ctx->lir_module->cfg_module.funcs, i));
} }
} }

View File

@@ -1,21 +1,22 @@
#include <scc_lir_module.h> #include <scc_lir_module.h>
void scc_lir_module_init(scc_lir_module_t *module) { void scc_lir_module_init(scc_lir_module_t *lir_module) {
// FIXME // FIXME
// module->module // lir_module->lir_module
scc_vec_init(module->func_metas); scc_vec_init(lir_module->func_metas);
scc_vec_init(module->symbol_metas); scc_vec_init(lir_module->symbol_metas);
} }
void scc_lir_module_drop(scc_lir_module_t *module) { void scc_lir_module_drop(scc_lir_module_t *lir_module) {
scc_vec_free(module->func_metas); // FIXME memory leak
scc_vec_free(module->symbol_metas); scc_vec_free(lir_module->func_metas);
scc_vec_free(lir_module->symbol_metas);
} }
scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *module, scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *lir_module,
const char *name) { const char *name) {
if (!module || !name) if (!lir_module || !name)
return SCC_CFG_ID_nullptr; return SCC_CFG_ID_nullptr;
scc_lir_symbol_meta_t *meta = scc_malloc(sizeof(scc_lir_symbol_meta_t)); scc_lir_symbol_meta_t *meta = scc_malloc(sizeof(scc_lir_symbol_meta_t));
@@ -26,21 +27,21 @@ scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *module,
.meta = meta}; .meta = meta};
meta->func.func = nullptr; meta->func.func = nullptr;
scc_vec_push(module->symbol_metas, meta); scc_vec_push(lir_module->symbol_metas, meta);
scc_cfg_symbol_id_t id = scc_cfg_symbol_id_t id =
scc_cfg_module_add_symbol(&module->cfg_module, &sym); scc_cfg_module_add_symbol(&lir_module->cfg_module, &sym);
if (id == SCC_CFG_ID_nullptr) { if (id == SCC_CFG_ID_nullptr) {
Panic("scc_lir: add func decl '%s' failed", name); Panic("scc_lir: add func decl '%s' failed", name);
} }
return id; return id;
} }
scc_lir_symbol_id_t scc_lir_module_add_data(scc_lir_module_t *module, scc_lir_symbol_id_t scc_lir_module_add_data(scc_lir_module_t *lir_module,
const char *name, const char *name,
scc_cfg_symbol_kind_t kind, scc_cfg_symbol_kind_t kind,
const u8 *init_data, usize size, const u8 *init_data, usize size,
u32 align) { u32 align) {
if (!module || !name) if (!lir_module || !name)
return SCC_CFG_ID_nullptr; return SCC_CFG_ID_nullptr;
if (kind != SCC_CFG_SYMBOL_KIND_DATA && kind != SCC_CFG_SYMBOL_KIND_EXTERN) if (kind != SCC_CFG_SYMBOL_KIND_DATA && kind != SCC_CFG_SYMBOL_KIND_EXTERN)
return SCC_CFG_ID_nullptr; return SCC_CFG_ID_nullptr;
@@ -67,9 +68,9 @@ scc_lir_symbol_id_t scc_lir_module_add_data(scc_lir_module_t *module,
} }
} }
scc_vec_push(module->symbol_metas, meta); scc_vec_push(lir_module->symbol_metas, meta);
scc_cfg_symbol_id_t id = scc_cfg_symbol_id_t id =
scc_cfg_module_add_symbol(&module->cfg_module, &sym); scc_cfg_module_add_symbol(&lir_module->cfg_module, &sym);
if (id = SCC_CFG_ID_nullptr) { if (id = SCC_CFG_ID_nullptr) {
/* 冲突时释放已分配的数据 */ /* 冲突时释放已分配的数据 */
scc_free(meta->data.init_data); scc_free(meta->data.init_data);

15
libs/ir/mir/cbuild.toml Normal file
View File

@@ -0,0 +1,15 @@
[package]
name = "scc_mir"
version = "0.1.0"
authors = []
description = ""
dependencies = [
{ name = "scc_cfg", path = "../cfg" },
{ name = "scc_lir", path = "../lir" },
{ name = "scc_utils", path = "../../../runtime/scc_utils" },
{ name = "tree_dump", path = "../../tree_dump" },
{ name = "scc_mcode", path = "../../mcode" },
]
# features = {}
# default_features = []

View File

@@ -0,0 +1,10 @@
#ifndef __SCC_LIR2MIR_H__
#define __SCC_LIR2MIR_H__
#include "scc_mir_module.h"
#include <scc_lir_module.h>
void scc_lir2mir(scc_mir_module_t *mir_module,
const scc_lir_module_t *lir_module);
#endif /* __SCC_LIR2MIR_H__ */

View File

@@ -0,0 +1,60 @@
// scc_mir.h (示意)
#ifndef __SCC_MIR_H__
#define __SCC_MIR_H__
#include <scc_lir.h> // 复用 VREG 概念和一些基础类型
// #include "scc_target_desc.h" // 目标架构描述(寄存器文件、指令编码)
typedef enum {
SCC_MIR_OP_NONE,
SCC_MIR_OP_MEM, // 内存访问
SCC_MIR_OP_VREG, // 虚拟寄存器
SCC_MIR_OP_PREG, // 物理寄存器
SCC_MIR_OP_IMM, // 立即数
SCC_MIR_OP_SYMBOL, // 符号地址(用于重定位)
SCC_MIR_OP_BLOCK // 基本块引用(label)
} scc_mir_op_kind_t;
typedef struct scc_mir_operand {
scc_mir_op_kind_t kind;
union {
int vreg; // 虚拟寄存器索引
int preg; // 物理寄存器
i64 imm; // 立即数
const char *symbol; // 符号名
int stack_slot; // 栈槽 ID (由 FrameLayout 分配)
scc_lir_bblock_id_t block_id; // 目标基本块
};
} scc_mir_operand_t;
typedef enum {
SCC_MIR_PSUEDO_ALLOCA = -1,
} scc_mir_psuedo_op_t;
typedef struct scc_mir_instr {
int opcode; // 目标特定的指令编码 (如 X86::ADD32rr)
int num_operands; // 实际使用的操作数个数
scc_mir_operand_t
operands[8]; // 固定小数组RISC 风格指令通常不超过 4 操作数
scc_pos_t src_loc; // 调试信息 (继承自 LIR)
} scc_mir_instr_t;
typedef SCC_VEC(scc_mir_instr_t) scc_mir_instr_vec_t;
typedef scc_cfg_bblock_t scc_mir_bblock_t;
typedef struct scc_mir_bblock_meta {
} scc_mir_bblock_meta_t;
#define SCC_MIR_BBLOCK_VALUES(bblock) \
((scc_mir_instr_vec_t *)&((bblock)->values))
typedef scc_cfg_func_t scc_mir_func_t;
typedef struct scc_mir_func_meta {
// 栈帧信息 (由 FrameLayout Pass 填充)
int frame_size;
int stack_alignment;
// 寄存器分配信息
SCC_VEC(int) vreg_alloc; // vreg -> phys reg 映射
} scc_mir_func_meta_t;
#define SCC_MIR_FUNC_META(func) ((scc_mir_func_meta_t *)(func)->meta)
#endif /* __SCC_MIR_H__ */

View File

@@ -0,0 +1,22 @@
#ifndef __SCC_MIR_DUMP_H__
#define __SCC_MIR_DUMP_H__
#include "scc_mir.h"
#include "scc_mir_module.h"
#include <scc_tree_dump.h>
typedef struct {
scc_tree_dump_t *dump_ctx;
scc_mir_module_t *mir_module;
} scc_mir_dump_ctx_t;
static inline void scc_mir_dump_init(scc_mir_dump_ctx_t *ctx,
scc_tree_dump_t *dump_ctx,
scc_mir_module_t *module) {
Assert(ctx != nullptr && dump_ctx != nullptr && module != nullptr);
ctx->dump_ctx = dump_ctx;
ctx->mir_module = module;
}
void scc_mir_dump_module(scc_mir_dump_ctx_t *ctx);
#endif /* __SCC_MIR_DUMP_H__*/

View File

@@ -0,0 +1,18 @@
#ifndef __SCC_MIR_MODULE_H__
#define __SCC_MIR_MODULE_H__
#include "scc_mir.h"
#include <scc_lir_module.h>
typedef scc_lir_symbol_meta_vec_t scc_mir_symbol_meta_vec_t;
typedef SCC_VEC(scc_mir_func_meta_t *) scc_mir_func_meta_vec_t;
typedef struct scc_mir_module {
scc_cfg_module_t cfg_module;
scc_mir_func_meta_vec_t func_metas;
scc_mir_symbol_meta_vec_t symbol_metas;
} scc_mir_module_t;
void scc_mir_module_init(scc_mir_module_t *mir_module);
void scc_mir_module_drop(scc_mir_module_t *mir_module);
#endif /* __SCC_MIR_MODULE_H__ */

View File

@@ -0,0 +1,131 @@
#ifndef __SCC_MIR_PASS_H__
#define __SCC_MIR_PASS_H__
#include "scc_mir.h"
/** Pass 的唯一标识符 (枚举) */
typedef enum {
SCC_MIR_PASS_ABI_LOWERING, // ABI 物理化 (核心)
SCC_MIR_PASS_REG_ALLOC, // 寄存器分配 (核心)
SCC_MIR_PASS_FRAME_LAYOUT, // 栈帧布局 (核心)
SCC_MIR_PASS_PROLOGUE_EPILOGUE, // 序言/尾声插入 (核心)
SCC_MIR_PASS_DEAD_CODE_ELIM, // 死代码消除 (优化)
SCC_MIR_PASS_CONST_PROP, // 常量传播 (优化)
SCC_MIR_PASS_PEEPHOLE, // 窥孔优化 (优化)
SCC_MIR_PASS_CFG_SIMPLIFY, // CFG 简化 (优化)
SCC_MIR_PASS_COPY_PROP, // 复制传播 (优化)
SCC_MIR_PASS_COUNT
} scc_mir_pass_id_t;
/** Pass 运行阶段 (用于自动排序) */
typedef enum {
SCC_MIR_STAGE_ANY, // 无特殊阶段要求
SCC_MIR_STAGE_PRE_REGALLOC, // 寄存器分配前
SCC_MIR_STAGE_REGALLOC, // 寄存器分配本身
SCC_MIR_STAGE_POST_REGALLOC // 寄存器分配后
} scc_mir_pass_stage_t;
/**
* @brief Pass 执行函数原型
* @param func 输入的 MIR 函数 (Pass 可修改或替换)
* @param ctx 可选的上下文指针 (如目标机器信息、调试标志)
* @return 执行后的 MIR 函数指针 (若未修改可返回原指针,若需替换可返回新指针)
* @warning Pass 应负责释放不再使用的旧函数资源
*/
typedef scc_mir_func_t *(*scc_mir_pass_fn_t)(scc_mir_func_t *func, void *ctx);
typedef struct scc_lir_pass_desc {
scc_mir_pass_id_t id; // 唯一标识
const char *name; // 可读名称
scc_mir_pass_stage_t stage; // 所属阶段
scc_mir_pass_id_t *deps; // 依赖的 Pass ID 数组 (可为 NULL)
usize num_deps; // 依赖数量
scc_mir_pass_fn_t run; // 执行函数
cbool required; // 是否为核心必需 Pass
} scc_mir_pass_desc_t;
/* --------------------------------------------------------------------------
* Pass 管理器
* -------------------------------------------------------------------------- */
typedef struct scc_lir_pass_manager {
SCC_VEC(scc_mir_pass_desc_t) passes; // 所有已注册 Pass
SCC_VEC(scc_mir_pass_id_t) pipeline; // 当前流水线顺序
void *ctx; // 传递给每个 Pass 的上下文
} scc_mir_pass_manager_t;
/**
* @brief 初始化 Pass 管理器
* @param pm 管理器指针
* @param ctx 全局上下文 (如 scc_target_t*)
*/
void scc_mir_pass_manager_init(scc_mir_pass_manager_t *pm, void *ctx);
/**
* @brief 销毁 Pass 管理器,释放资源
*/
void scc_mir_pass_manager_drop(scc_mir_pass_manager_t *pm);
/**
* @brief 注册一个 Pass (通常在编译器初始化时调用)
* @param pm 管理器
* @param desc Pass 描述符
*/
void scc_mir_pass_register(scc_mir_pass_manager_t *pm,
const scc_mir_pass_desc_t *desc);
/**
* @brief 构建默认的核心流水线 (仅包含 required=true 的 Pass)
* @param pm 管理器
*
* 自动按阶段排序并解析依赖。
*/
void scc_mir_pass_build_core_pipeline(scc_mir_pass_manager_t *pm);
/**
* @brief 向流水线追加一个可选 Pass
* @param pm 管理器
* @param id 要添加的 Pass ID
* @return 成功返回 true若依赖不满足或 ID 无效返回 false
*/
cbool scc_mir_pass_add_to_pipeline(scc_mir_pass_manager_t *pm,
scc_mir_pass_id_t id);
/**
* @brief 对指定函数运行当前流水线中的所有 Pass
* @param pm 管理器
* @param func 要处理的 LIR 函数
* @return 最终处理后的函数指针
*/
scc_lir_func_t *scc_mir_pass_run_pipeline(scc_mir_pass_manager_t *pm,
scc_lir_func_t *func);
/* --------------------------------------------------------------------------
* 便捷宏:声明并注册一个 Pass
* -------------------------------------------------------------------------- */
/**
* @brief 在模块内部声明并注册一个 Pass
* @param pm 管理器指针
* @param id Pass ID 枚举值
* @param name_str Pass 名称字符串
* @param stage 运行阶段
* @param deps_arr 依赖数组 (可为 NULL)
* @param num_deps 依赖数量
* @param fn 执行函数
* @param req 是否必需
*/
#define SCC_MIR_REGISTER_PASS(pm, id, name_str, stage, deps_arr, num_deps, fn, \
req) \
do { \
scc_mir_pass_desc_t desc = {.id = (id), \
.name = (name_str), \
.stage = (stage), \
.deps = (deps_arr), \
.num_deps = (num_deps), \
.run = (fn), \
.required = (req)}; \
scc_mir_pass_register((pm), &desc); \
} while (0)
#endif /* __SCC_LIR_PASS_H__ */

393
libs/ir/mir/src/mir_x86.c Normal file
View File

@@ -0,0 +1,393 @@
#include <scc_lir_module.h>
#include <scc_mir_module.h>
#include <scc_tree_dump.h>
#include <x86/scc_x86_iform.c>
#include <x86/scc_x86_reg.c>
static const char *preg_name(int preg_id) {
if (preg_id < 1 || preg_id >= SCC_X86_REG_COUNT)
return "???";
return scc_x86_reg_table[preg_id].name;
}
void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_instr_t *instr) {
scc_x86_iform_t iform = instr->opcode;
const scc_x86_iform_info_t *info = &scc_x86_iform_table[iform];
scc_tree_dump_append_fmt(td, " %s", info->iform_name);
// Assert(instr->num_operands == info->num_ops);
for (int i = 0; i < instr->num_operands; i += 1) {
if (i == 0)
scc_tree_dump_append(td, " ");
else
scc_tree_dump_append_fmt(td, ", ");
scc_mir_operand_t *op = &instr->operands[i];
switch (op->kind) {
case SCC_MIR_OP_VREG:
scc_tree_dump_append_fmt(td, "$%d", op->vreg);
break;
case SCC_MIR_OP_PREG:
scc_tree_dump_append_fmt(td, "$%s", preg_name(op->preg));
break;
case SCC_MIR_OP_IMM:
scc_tree_dump_append_fmt(td, "%ld", op->imm);
break;
case SCC_MIR_OP_BLOCK:
scc_tree_dump_append_fmt(td, "#BB%d", op->block_id);
break;
case SCC_MIR_OP_SYMBOL:
scc_tree_dump_append_fmt(td, "@%s", op->symbol);
break;
default:
break;
}
}
}
typedef struct x86_isel {
scc_mir_instr_vec_t instrs;
} x86_isel_t;
static void add_instr(x86_isel_t *isel, const scc_mir_instr_t *instr) {
scc_vec_push(isel->instrs, *instr);
}
static inline void add_instr_0(x86_isel_t *isel, scc_x86_iform_t opcode) {
scc_mir_instr_t out = {.opcode = opcode, .num_operands = 0};
add_instr(isel, &out);
}
static inline void add_instr_1(x86_isel_t *isel, scc_x86_iform_t opcode,
scc_mir_operand_t op1) {
scc_mir_instr_t out = {.opcode = opcode, .num_operands = 1};
out.operands[0] = op1;
add_instr(isel, &out);
}
static inline void add_instr_2(x86_isel_t *isel, scc_x86_iform_t opcode,
scc_mir_operand_t op1, scc_mir_operand_t op2) {
scc_mir_instr_t out = {.opcode = opcode, .num_operands = 2};
out.operands[0] = op1;
out.operands[1] = op2;
add_instr(isel, &out);
}
// 将 LIR 值转换为 MIR 操作数
static scc_mir_operand_t lir_val_to_mir_op(const scc_lir_val_t *val) {
scc_mir_operand_t op = {0};
switch (val->kind) {
case SCC_LIR_INSTR_KIND_NONE:
op.kind = SCC_MIR_OP_NONE;
break;
case SCC_LIR_INSTR_KIND_VREG:
op.kind = SCC_MIR_OP_VREG;
op.vreg = val->data.reg;
break;
case SCC_LIR_INSTR_KIND_IMM:
op.kind = SCC_MIR_OP_IMM;
// FIXME hack ap
op.imm = val->data.imm.data.digit;
break;
case SCC_LIR_INSTR_KIND_FIMM:
// 浮点立即数暂时作为普通立即数处理(后端需特殊处理)
op.kind = SCC_MIR_OP_IMM;
op.imm = *(i64 *)&val->data.fimm;
break;
case SCC_LIR_INSTR_KIND_SYMBOL:
op.kind = SCC_MIR_OP_SYMBOL;
op.symbol = val->data.symbol;
break;
default:
UNREACHABLE();
}
return op;
}
static void sel_mir(x86_isel_t *isel, const scc_lir_instr_t *instr) {
switch (instr->op) {
case SCC_LIR_MOV: {
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89,
lir_val_to_mir_op(&instr->to),
lir_val_to_mir_op(&instr->arg0));
} break;
case SCC_LIR_LOAD: {
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_MEMV,
lir_val_to_mir_op(&instr->to),
lir_val_to_mir_op(&instr->arg0));
} break;
case SCC_LIR_LOAD_ADDR: {
add_instr_2(isel, SCC_X86_IFORM_LEA_GPRV_AGEN,
lir_val_to_mir_op(&instr->to),
lir_val_to_mir_op(&instr->arg0));
} break;
case SCC_LIR_STORE:
case SCC_LIR_STORE_ADDR: {
add_instr_2(isel, SCC_X86_IFORM_MOV_MEMV_GPRV,
lir_val_to_mir_op(&instr->arg1),
lir_val_to_mir_op(&instr->arg0));
} break;
// case SCC_LIR_LEA:
// case SCC_LIR_NEG:
// case SCC_LIR_NOT:
// case SCC_LIR_FNEG:
// case SCC_LIR_FCVT:
case SCC_LIR_ALLOCA: {
add_instr_2(isel, SCC_MIR_PSUEDO_ALLOCA, lir_val_to_mir_op(&instr->to),
(scc_mir_operand_t){
.kind = SCC_MIR_OP_IMM,
.imm = instr->size,
});
} break;
case SCC_LIR_ADD:
case SCC_LIR_SUB:
case SCC_LIR_MUL:
case SCC_LIR_AND:
case SCC_LIR_OR:
case SCC_LIR_XOR:
case SCC_LIR_SHL:
case SCC_LIR_SHR:
case SCC_LIR_SAR: {
int base;
bool is_commutative =
(instr->op != SCC_LIR_SUB && instr->op != SCC_LIR_SHL &&
instr->op != SCC_LIR_SHR && instr->op != SCC_LIR_SAR);
switch (instr->op) {
case SCC_LIR_ADD:
base = SCC_X86_IFORM_ADD_GPRV_GPRV_01;
break;
case SCC_LIR_SUB:
base = SCC_X86_IFORM_SUB_GPRV_GPRV_29;
break;
case SCC_LIR_AND:
base = SCC_X86_IFORM_AND_GPRV_GPRV_21;
break;
case SCC_LIR_OR:
base = SCC_X86_IFORM_OR_GPRV_GPRV_09;
break;
case SCC_LIR_XOR:
base = SCC_X86_IFORM_XOR_GPRV_GPRV_31;
break;
case SCC_LIR_MUL:
base = SCC_X86_IFORM_IMUL_GPRV_GPRV;
break;
case SCC_LIR_SHL:
base = SCC_X86_IFORM_SHR_GPRV_IMMB;
break; // 简化,实际应处理 CL 移位
case SCC_LIR_SHR:
base = SCC_X86_IFORM_SHR_GPRV_IMMB;
break;
case SCC_LIR_SAR:
base = SCC_X86_IFORM_SAR_GPRV_IMMB;
break;
default:
return;
}
if (instr->arg0.kind == SCC_LIR_INSTR_KIND_IMM) {
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_IMMV,
lir_val_to_mir_op(&instr->to),
lir_val_to_mir_op(&instr->arg0));
}
// 三地址转两地址:若 to != arg0需先 mov to, arg0
if (instr->to.kind == SCC_LIR_INSTR_KIND_VREG &&
instr->arg0.kind == SCC_LIR_INSTR_KIND_VREG &&
instr->to.data.reg != instr->arg0.data.reg) {
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89,
lir_val_to_mir_op(&instr->to),
lir_val_to_mir_op(&instr->arg0));
}
// 如果是立即数,使用 RI 变体
if (instr->arg1.kind == SCC_LIR_INSTR_KIND_IMM) {
// 需要根据立即数大小选择 RI8/RI32
add_instr_2(isel, base, lir_val_to_mir_op(&instr->to),
lir_val_to_mir_op(&instr->arg1));
break;
}
// 生成两地址运算指令
add_instr_2(isel, base, lir_val_to_mir_op(&instr->to),
lir_val_to_mir_op(&instr->arg1));
} break;
// case SCC_LIR_DIV_S:
// case SCC_LIR_DIV_U:
// case SCC_LIR_REM_S:
// case SCC_LIR_REM_U:
// case SCC_LIR_FADD:
// case SCC_LIR_FSUB:
// case SCC_LIR_FMUL:
// case SCC_LIR_FDIV:
// dump_operand(ctx, &instr->to);
// scc_tree_dump_append(td, ", ");
// dump_operand(ctx, &instr->arg0);
// scc_tree_dump_append(td, ", ");
// dump_operand(ctx, &instr->arg1);
// break;
// case SCC_LIR_CMP:
// dump_operand(ctx, &instr->to);
// scc_tree_dump_append_fmt(td, ", %s, ",
// cond_to_string(instr->metadata.cond));
// dump_operand(ctx, &instr->arg0);
// scc_tree_dump_append(td, ", ");
// dump_operand(ctx, &instr->arg1);
// break;
// case SCC_LIR_BR:
// dump_operand(ctx, &instr->arg0);
// scc_tree_dump_append_fmt(td, ", BB#%zu, BB#%zu",
// instr->metadata.br.true_target,
// instr->metadata.br.false_target);
// break;
case SCC_LIR_JMP: {
add_instr_1(isel, SCC_X86_IFORM_JMP_GPRV,
(scc_mir_operand_t){
.kind = SCC_MIR_OP_BLOCK,
.block_id = instr->metadata.jmp_target,
});
} break;
// case SCC_LIR_JMP_INDIRECT:
// dump_operand(ctx, &instr->arg0);
// break;
case SCC_LIR_CALL: {
const struct scc_lir_call *c = &instr->metadata.call;
Assert(c->callee != nullptr);
add_instr_1(isel, SCC_X86_IFORM_CALL_NEAR_GPRV,
(scc_mir_operand_t){
.kind = SCC_MIR_OP_SYMBOL,
.symbol = c->callee,
});
} break;
// case SCC_LIR_CALL: {
// const struct scc_lir_call *c = &instr->metadata.call;
// if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) {
// dump_operand(ctx, &c->ret_vreg);
// scc_tree_dump_append(td, " = ");
// }
// scc_tree_dump_append_fmt(td, "call @%s(",
// c->callee ? c->callee : "<null>");
// for (u8 i = 0; i < c->arg_count; i++) {
// if (i > 0)
// scc_tree_dump_append(td, ", ");
// dump_operand(ctx, &c->args[i]);
// }
// scc_tree_dump_append_fmt(td, ") clobber=0x%llx",
// (unsigned long long)c->clobber_mask);
// break;
// }
// case SCC_LIR_CALL_INDIRECT: {
// const struct scc_lir_call_indirect *c =
// &instr->metadata.call_indirect; if (c->ret_vreg.kind !=
// SCC_LIR_INSTR_KIND_NONE) {
// dump_operand(ctx, &c->ret_vreg);
// scc_tree_dump_append(td, " = ");
// }
// scc_tree_dump_append(td, "call ");
// dump_operand(ctx, &c->target);
// scc_tree_dump_append(td, "(");
// for (u8 i = 0; i < c->arg_count; i++) {
// if (i > 0)
// scc_tree_dump_append(td, ", ");
// dump_operand(ctx, &c->args[i]);
// }
// scc_tree_dump_append_fmt(td, ") clobber=0x%llx",
// (unsigned long long)c->clobber_mask);
// break;
// }
case SCC_LIR_RET: {
if (instr->metadata.ret_val.kind != SCC_LIR_INSTR_KIND_NONE) {
// FIXME target ABI
add_instr_2(isel, SCC_X86_IFORM_MOV_GPRV_GPRV_89,
(scc_mir_operand_t){
.kind = SCC_MIR_OP_PREG,
.preg = SCC_X86_REG_RAX,
},
lir_val_to_mir_op(&instr->metadata.ret_val));
}
add_instr_0(isel, SCC_X86_IFORM_RET_FAR);
} break;
// case SCC_LIR_PARALLEL_COPY: {
// const struct scc_lir_parallel_copy *pc =
// &instr->metadata.parallel_copy; scc_tree_dump_append(td, "[");
// for (u8 i = 0; i < pc->num_copies; i++) {
// if (i > 0)
// scc_tree_dump_append(td, ", ");
// dump_operand(ctx, &pc->dests[i]);
// scc_tree_dump_append(td, " <- ");
// dump_operand(ctx, &pc->srcs[i]);
// }
// scc_tree_dump_append(td, "]");
// break;
// }
// case SCC_LIR_VA_START:
// dump_operand(ctx, &instr->metadata.va_start.ap);
// scc_tree_dump_append(td, ", ");
// dump_operand(ctx, &instr->metadata.va_start.last);
// break;
// case SCC_LIR_VA_ARG:
// dump_operand(ctx, &instr->metadata.va_arg.to);
// scc_tree_dump_append(td, " = va_arg ");
// dump_operand(ctx, &instr->metadata.va_arg.ap);
// scc_tree_dump_append_fmt(td, ", size=%u, align=%u, float=%d",
// instr->metadata.va_arg.type_size,
// instr->metadata.va_arg.type_align,
// instr->metadata.va_arg.is_float);
// break;
// case SCC_LIR_VA_END:
// dump_operand(ctx, &instr->metadata.va_end.ap);
// break;
// case SCC_LIR_VA_COPY:
// dump_operand(ctx, &instr->metadata.va_copy.dest);
// scc_tree_dump_append(td, ", ");
// dump_operand(ctx, &instr->metadata.va_copy.src);
// break;
// case SCC_LIR_NOP:
// break;
//
default:
break;
UNREACHABLE();
break;
}
}
static void sel_func(scc_lir_module_t *lir_module, const scc_lir_func_t *func) {
x86_isel_t isel;
scc_vec_foreach(func->bblocks, i) {
scc_vec_init(isel.instrs);
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&lir_module->cfg_module, id);
scc_lir_instr_vec_t *instrs = SCC_LIR_BBLOCK_VALUES(bb);
scc_vec_foreach(*instrs, i) {
const scc_lir_instr_t *ins = &scc_vec_at(*instrs, i);
sel_mir(&isel, ins);
}
bb->values = *(scc_cfg_value_vec_t *)&isel.instrs;
scc_vec_init(isel.instrs);
}
}
void scc_isel_x86_64(scc_mir_module_t *mir_module,
scc_lir_module_t *lir_module) {
scc_vec_foreach(lir_module->cfg_module.funcs, i) {
if (i == 0)
continue;
scc_lir_func_t *func = &scc_vec_at(lir_module->cfg_module.funcs, i);
sel_func(lir_module, func);
}
}

View File

@@ -0,0 +1,12 @@
#include <scc_lir2mir.h>
extern void scc_isel_x86_64(scc_mir_module_t *mir_module,
scc_lir_module_t *lir_module);
void scc_lir2mir(scc_mir_module_t *mir_module,
const scc_lir_module_t *lir_module) {
// FIXME hack cfg module
mir_module->cfg_module = lir_module->cfg_module;
// TODO using target ABI choice it
scc_isel_x86_64(mir_module, lir_module);
}

View File

View File

@@ -0,0 +1,80 @@
#include <scc_mir_dump.h>
void scc_x86_instr_dump(scc_tree_dump_t *dump, const scc_mir_instr_t *instr);
void scc_mir_dump_instr(scc_mir_dump_ctx_t *ctx, const scc_mir_instr_t *ins) {
scc_tree_dump_t *td = ctx->dump_ctx;
scc_tree_dump_begin_line(td);
if (ins->opcode >= 0) {
scc_x86_instr_dump(td, ins);
return;
}
switch (ins->opcode) {
case SCC_MIR_PSUEDO_ALLOCA:
scc_tree_dump_node(td, " @alloca");
scc_tree_dump_append_fmt(td, "(%d)", ins->operands[1].imm);
Assert(ins->operands[0].kind == SCC_MIR_OP_VREG);
scc_tree_dump_append_fmt(td, " %%%d", ins->operands[0].vreg);
break;
default:
break;
}
}
void scc_mir_dump_bblock(scc_mir_dump_ctx_t *ctx, const scc_mir_bblock_t *bb) {
Assert(ctx != nullptr && bb != nullptr);
scc_tree_dump_t *td = ctx->dump_ctx;
// 基本块头部
scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "#BB%zu", bb->id);
if (bb->name) {
scc_tree_dump_append_fmt(td, " (%s)", bb->name);
}
scc_tree_dump_append(td, ":");
// 输出每条指令
scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES(bb);
scc_vec_foreach(*instrs, i) {
const scc_mir_instr_t *ins = &scc_vec_at(*instrs, i);
scc_mir_dump_instr(ctx, ins);
}
}
void scc_mir_dump_func(scc_mir_dump_ctx_t *ctx, const scc_mir_func_t *func) {
Assert(ctx != nullptr && func != nullptr);
scc_tree_dump_t *td = ctx->dump_ctx;
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
// 函数头部
scc_tree_dump_begin_line(td);
scc_tree_dump_node(td, "func @%s", func->name ? func->name : "<anon>");
// 输出所有基本块
scc_vec_foreach(func->bblocks, i) {
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
const scc_cfg_bblock_t *bb =
scc_cfg_module_unsafe_get_bblock(&ctx->mir_module->cfg_module, id);
scc_mir_dump_bblock(ctx, bb);
}
}
void scc_mir_dump_module(scc_mir_dump_ctx_t *ctx) {
scc_vec_foreach(ctx->mir_module->cfg_module.symbols, i) {
// FIXME 0 is null
if (i == 0)
continue;
scc_cfg_symbol_t *sym =
&scc_vec_at(ctx->mir_module->cfg_module.symbols, i);
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "symbol");
scc_tree_dump_append_fmt(ctx->dump_ctx, " %s", sym->name);
}
scc_vec_foreach(ctx->mir_module->cfg_module.funcs, i) {
if (i == 0)
continue;
scc_mir_dump_func(ctx,
&scc_vec_at(ctx->mir_module->cfg_module.funcs, i));
}
}

View File

@@ -0,0 +1,12 @@
#include "scc_mir_module.h"
void scc_mir_module_init(scc_mir_module_t *mir_module) {
scc_vec_init(mir_module->func_metas);
scc_vec_init(mir_module->symbol_metas);
}
void scc_mir_module_drop(scc_mir_module_t *mir_module) {
// FIXME memory leak
scc_vec_free(mir_module->func_metas);
scc_vec_free(mir_module->symbol_metas);
}

View File

View File

@@ -16,6 +16,7 @@ typedef struct {
cbool emit_ast; cbool emit_ast;
cbool emit_hir; cbool emit_hir;
cbool emit_lir; cbool emit_lir;
cbool emit_mir;
} scc_config_t; } scc_config_t;
static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
@@ -183,6 +184,13 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
scc_hints[SCC_HINT_EMIT_LIR]); scc_hints[SCC_HINT_EMIT_LIR]);
scc_argparse_spec_setup_bool(&opt_lir.spec, &(config->emit_lir)); scc_argparse_spec_setup_bool(&opt_lir.spec, &(config->emit_lir));
scc_argparse_cmd_add_opt(root, &opt_lir); scc_argparse_cmd_add_opt(root, &opt_lir);
// -M, --emit-mir
scc_argparse_opt_t opt_mir;
scc_argparse_opt_init(&opt_mir, 'M', "emit-mir",
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);
} }
#endif /* __SCC_CONFIG_H___ */ #endif /* __SCC_CONFIG_H___ */

View File

@@ -7,8 +7,9 @@
#include <scc_ast_dump.h> #include <scc_ast_dump.h>
#include <scc_hir2lir.h> #include <scc_hir2lir.h>
#include <scc_hir_dump.h> #include <scc_hir_dump.h>
#include <scc_lir2mir.h>
#include <scc_lir_dump.h> #include <scc_lir_dump.h>
#include <scc_mir_dump.h>
// #include <scc_ir2mcode.h> // #include <scc_ir2mcode.h>
// #include <sccf2pe.h> // #include <sccf2pe.h>
@@ -262,6 +263,26 @@ sstream_drop:
return 0; return 0;
} }
scc_mir_module_t mir_module;
scc_mir_module_init(&mir_module);
scc_lir2mir(&mir_module, &lir_module);
if (config.emit_mir) {
scc_mir_dump_ctx_t mir_dump_ctx;
scc_tree_dump_t tree_dump;
if (fp == nullptr) {
scc_tree_dump_init(&tree_dump, true);
} else {
scc_tree_dump_init(&tree_dump, false);
}
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_drop(&tree_dump);
return 0;
}
// scc_ir2mcode_ctx_t ir2mcode_ctx; // scc_ir2mcode_ctx_t ir2mcode_ctx;
// sccf_builder_t sccf_builder; // sccf_builder_t sccf_builder;
// scc_ir2mcode_init(&ir2mcode_ctx, &cprog, &sccf_builder, // scc_ir2mcode_init(&ir2mcode_ctx, &cprog, &sccf_builder,