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:
393
libs/ir/mir/src/mir_x86.c
Normal file
393
libs/ir/mir/src/mir_x86.c
Normal 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);
|
||||
}
|
||||
}
|
||||
12
libs/ir/mir/src/scc_lir2mir.c
Normal file
12
libs/ir/mir/src/scc_lir2mir.c
Normal 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);
|
||||
}
|
||||
0
libs/ir/mir/src/scc_mir.c
Normal file
0
libs/ir/mir/src/scc_mir.c
Normal file
80
libs/ir/mir/src/scc_mir_dump.c
Normal file
80
libs/ir/mir/src/scc_mir_dump.c
Normal 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));
|
||||
}
|
||||
}
|
||||
12
libs/ir/mir/src/scc_mir_module.c
Normal file
12
libs/ir/mir/src/scc_mir_module.c
Normal 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);
|
||||
}
|
||||
0
libs/ir/mir/src/scc_mir_pass.c
Normal file
0
libs/ir/mir/src/scc_mir_pass.c
Normal file
Reference in New Issue
Block a user