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:
@@ -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 {
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user