feat(compiler): 实现HIR到LIR的函数定义标记和直接/间接调用区分

- 在HIR函数元数据中添加defined字段来标记函数是否已定义
- 在AST到IR转换过程中设置函数定义状态
- 修改LIR模块函数声明接口以支持定义状态参数
- 实现直接调用和间接调用的区别处理,通过符号查找确定调用类型
- 更新LIR调用指令结构以支持直接和间接调用的不同表示方式
- 调整x86后端指令选择以正确处理不同类型的调用

fix(x86-isel): 优化x86指令发射和操作数大小处理

- 移除move/load/store函数中的size参数,改由操作数本身携带大小信息
- 简化x86指令操作数结构,减少操作数数量限制
- 添加专门的mov系列表单选择函数,根据操作数类型和大小自动选择正确的指令形式
- 修正间接调用的指令形式为CALL_NEAR_MEMV而非GPRV
- 添加向量版本的load/store/move发射函数

refactor(reg-alloc): 更新寄存器分配迭代器接口

- 为分配迭代器的替换方法添加size参数,以便正确处理不同大小的寄存器
This commit is contained in:
zzy
2026-05-23 15:33:54 +08:00
parent d78b91894e
commit ea553718f0
21 changed files with 495 additions and 444 deletions

View File

@@ -185,21 +185,16 @@ typedef struct scc_lir_ins {
scc_lir_bblock_id_t jmp_target;
struct scc_lir_call {
const char *callee;
scc_lir_val_t *args;
int arg_count;
scc_lir_val_t ret_vreg;
u64 clobber_mask;
union {
const char *callee_name;
scc_lir_val_t callee_target;
};
} call;
struct scc_lir_call_indirect {
scc_lir_val_t target;
scc_lir_val_t *args;
int arg_count;
scc_lir_val_t ret_vreg;
u64 clobber_mask;
} call_indirect;
scc_lir_val_t ret_val;
struct scc_lir_parallel_copy {

View File

@@ -33,11 +33,11 @@ void scc_lir_module_drop(scc_lir_module_t *lir_module);
* @brief 添加一个函数声明(外部或未定义)
* @param mod 模块
* @param name 函数名
* @param attr 属性
* @param defined 是否定义
* @return 符号指针
*/
scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *lir_module,
const char *name);
const char *name, int defined);
/**
* @brief 添加一个全局数据符号(定义或外部)
@@ -56,4 +56,8 @@ scc_lir_symbol_id_t scc_lir_module_add_data(scc_lir_module_t *lir_module,
const u8 *init_data, usize size,
u32 align);
scc_lir_symbol_t *
scc_lir_module_unsafe_lookup_symbol(const scc_lir_module_t *lir_module,
const char *name);
#endif /* __SCC_LIR_MODULE_H__ */

View File

@@ -27,6 +27,7 @@ static void ir2lir_ctx_init(ir2lir_ctx_t *ctx, scc_lir_module_t *lir_module,
}
static void ir2lir_ctx_drop(ir2lir_ctx_t *ctx) {
// FIXME memory leak
scc_hashtable_drop(&ctx->value_to_vreg);
scc_hashtable_drop(&ctx->func_decl_map);
}
@@ -373,15 +374,26 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
lir_args[i] = ir_value_to_lir_operand(ctx, arg_ref);
}
scc_lir_instr_t instr = {
.op = SCC_LIR_CALL,
// TODO this is on windows all extern is indirect call
// On Linux ELF all call is direct call expect using `-no-plt`
scc_lir_symbol_t *sym =
scc_lir_module_unsafe_lookup_symbol(ctx->lir_module, callee->name);
Assert(sym != nullptr);
int is_direct_call = sym->kind == SCC_CFG_SYMBOL_KIND_FUNC;
scc_lir_instr_t instr = (scc_lir_instr_t){
.op = is_direct_call ? SCC_LIR_CALL : SCC_LIR_CALL_INDIRECT,
.size = size,
.to = SCC_LIR_VREG(dst_vreg),
.metadata.call = {.callee = callee->name,
.args = lir_args,
.metadata.call = {.args = lir_args,
.arg_count = arg_count,
.ret_vreg = SCC_LIR_VREG(dst_vreg),
.clobber_mask = 0}};
.clobber_mask = 0},
};
if (is_direct_call) {
instr.metadata.call.callee_name = callee->name;
} else {
instr.metadata.call.callee_target = SCC_LIR_SYMBOL(callee->name);
}
scc_lir_builder_add_instr(ctx, &instr);
// 注意lir_args 内存将随指令结构体复制到基本块向量中,但
// metadata.call.args 指针仍指向 malloc 内存,
@@ -598,11 +610,11 @@ void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) {
scc_hir_module_get_func(&cprog->module, func_ref);
if (!func)
continue;
scc_lir_symbol_id_t id =
scc_lir_module_add_func_decl(module, func->name);
scc_lir_symbol_id_t id = scc_lir_module_add_func_decl(
module, func->name, SCC_HIR_FUNC_META(func)->defined);
Assert(id != SCC_CFG_ID_nullptr);
// 记录映射,供调用时使用
scc_hashtable_set(&ctx.func_decl_map, (void *)(uintptr_t)func_ref,
scc_hashtable_set(&ctx.func_decl_map, (void *)(usize)func_ref,
(void *)func->name);
}
@@ -613,8 +625,8 @@ void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) {
scc_hir_module_get_func(&cprog->module, func_ref);
if (!func)
continue;
translate_func(&ctx, func);
}
ir2lir_ctx_drop(&ctx);
}

View File

@@ -290,30 +290,21 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) {
case SCC_LIR_JMP_INDIRECT:
dump_operand(ctx, &ins->arg0);
break;
case SCC_LIR_CALL: {
case SCC_LIR_CALL:
case SCC_LIR_CALL_INDIRECT: {
const struct scc_lir_call *c = &ins->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 = &ins->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);
if (ins->op == SCC_LIR_CALL) {
scc_tree_dump_append_fmt(
td, "@%s", c->callee_name ? c->callee_name : "<null>");
} else {
dump_operand(ctx, &c->callee_target);
}
scc_tree_dump_append(td, "(");
for (u8 i = 0; i < c->arg_count; i++) {
if (i > 0)

View File

@@ -3,7 +3,6 @@
void scc_lir_module_init(scc_lir_module_t *lir_module) {
// FIXME
// lir_module->lir_module
scc_vec_init(lir_module->func_metas);
scc_vec_init(lir_module->symbol_metas);
}
@@ -14,15 +13,25 @@ void scc_lir_module_drop(scc_lir_module_t *lir_module) {
scc_vec_free(lir_module->symbol_metas);
}
scc_lir_symbol_t *
scc_lir_module_unsafe_lookup_symbol(const scc_lir_module_t *lir_module,
const char *name) {
// FIXME const ?
return (void *)scc_cfg_module_unsafe_lookup_symbol(&lir_module->cfg_module,
name);
}
scc_lir_symbol_id_t scc_lir_module_add_func_decl(scc_lir_module_t *lir_module,
const char *name) {
const char *name,
int defined) {
if (!lir_module || !name)
return SCC_CFG_ID_nullptr;
scc_lir_symbol_meta_t *meta = scc_malloc(sizeof(scc_lir_symbol_meta_t));
Assert(meta != nullptr);
scc_lir_symbol_t sym = {.name = name,
.kind = SCC_CFG_SYMBOL_KIND_FUNC,
.kind = defined ? SCC_CFG_SYMBOL_KIND_FUNC
: SCC_CFG_SYMBOL_KIND_EXTERN,
.linkage = SCC_CFG_SYMBOL_LINK_GLOABL,
.meta = meta};
meta->func.func = nullptr;