Files
scc/libs/ir/lir/src/scc_hir2lir.c
zzy 41d060d7e7 feat(lir): 修改HIR到LIR转换以支持可变参数函数
- 移除SCC_LIR_LEA指令类型,改用SCC_LIR_LOAD_ADDR
- 在scc_lir_func_meta_t中添加is_va_arg字段用于标识可变参数函数
- 修改scc_hir2lir函数参数类型,移除const限定符
- 更新比较操作的指令映射逻辑,将条件信息存储在metadata中
- 调整代码结构,在各个switch case分支中统一使用"} break"格式

fix(x86-isel): 修复x86指令选择中的立即数和重定位处理

- 修改emit_direct_call函数以正确处理全局符号重定位
- 更新立即数字段访问从imm到imm0
- 添加新的重定位操作数类型SCC_X86_OPR_RELOC
- 实现重定位目标类型的完整处理逻辑,包括基本块和符号

refactor(x86-mir): 重构x86操作数结构以支持重定位机制

- 将内存操作数的disp字段改为结构体形式包含displacement信息
- 移除不再使用的常用操作数构造器函数
- 保留并完善slot操作数构造器
- 更新内存操作数的调试输出格式

feat(ir2mcode): 添加重定位表支持以处理符号引用

- 定义新的重定位结构体scc_reloc_t用于记录重定位信息
- 修改scc_ir2mcode_emit_instr函数签名以传递重定位表
- 实现重定位补丁应用功能scc_ir2mcode_patch
- 更新机器码生成流程以收集和处理重定位信息

refactor(ir2sccf): 重构SCEF文件生成以支持重定位处理

- 提取独立的emit_mir_module函数处理MIR模块的机器码生成
- 实现基本块间重定位的地址解析和补丁应用
- 改进符号重定位的处理机制
- 简化机器码段数据的最终处理流程
2026-05-21 16:19:49 +08:00

533 lines
19 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file scc_hir2lir.c
* @brief 将高级 IR (scc_ir) 降级为低层 LIR (scc_lir)
*/
#include <scc_hashtable.h>
#include <scc_hir2lir.h>
/* ---------- 转换上下文 ---------- */
typedef struct {
scc_hir_module_t *hir_module;
scc_lir_module_t *lir_module;
scc_lir_func_t *current_func;
scc_lir_instr_vec_t instrs;
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* (用于调用)
} ir2lir_ctx_t;
static void ir2lir_ctx_init(ir2lir_ctx_t *ctx, scc_lir_module_t *lir_module,
scc_hir_module_t *hir_module) {
ctx->hir_module = hir_module;
ctx->lir_module = lir_module;
scc_hashtable_usize_init(&ctx->value_to_vreg);
scc_hashtable_usize_init(&ctx->func_decl_map);
}
static void ir2lir_ctx_drop(ir2lir_ctx_t *ctx) {
scc_hashtable_drop(&ctx->value_to_vreg);
scc_hashtable_drop(&ctx->func_decl_map);
}
static scc_lir_val_t ir_value_to_lir_operand(ir2lir_ctx_t *ctx,
scc_hir_value_ref_t val_ref);
static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
scc_hir_value_ref_t value_ref);
static void ir_type_to_lir_size_ext(scc_hir_type_t *type, u8 *out_size,
scc_lir_ext_t *out_ext) {
switch (type->tag) {
case SCC_HIR_TYPE_i8:
*out_size = SCC_LIR_SIZE_8;
*out_ext = SCC_LIR_EXT_SEXT;
break;
case SCC_HIR_TYPE_u8:
*out_size = SCC_LIR_SIZE_8;
*out_ext = SCC_LIR_EXT_ZEXT;
break;
case SCC_HIR_TYPE_i16:
*out_size = SCC_LIR_SIZE_16;
*out_ext = SCC_LIR_EXT_SEXT;
break;
case SCC_HIR_TYPE_u16:
*out_size = SCC_LIR_SIZE_16;
*out_ext = SCC_LIR_EXT_ZEXT;
break;
case SCC_HIR_TYPE_i32:
*out_size = SCC_LIR_SIZE_32;
*out_ext = SCC_LIR_EXT_SEXT;
break;
case SCC_HIR_TYPE_u32:
*out_size = SCC_LIR_SIZE_32;
*out_ext = SCC_LIR_EXT_ZEXT;
break;
case SCC_HIR_TYPE_i64:
*out_size = SCC_LIR_SIZE_64;
*out_ext = SCC_LIR_EXT_SEXT;
break;
case SCC_HIR_TYPE_u64:
*out_size = SCC_LIR_SIZE_64;
*out_ext = SCC_LIR_EXT_ZEXT;
break;
case SCC_HIR_TYPE_f32:
*out_size = SCC_LIR_SIZE_32;
*out_ext = SCC_LIR_EXT_FLOAT;
break;
case SCC_HIR_TYPE_f64:
*out_size = SCC_LIR_SIZE_64;
*out_ext = SCC_LIR_EXT_FLOAT;
break;
case SCC_HIR_TYPE_PTR:
*out_size = SCC_LIR_SIZE_64;
*out_ext = SCC_LIR_EXT_NONE;
break;
case SCC_HIR_TYPE_void:
*out_size = 0;
*out_ext = SCC_LIR_EXT_NONE;
break;
default:
Panic("unsupported IR type in lowering");
}
}
static inline void scc_lir_builder_add_instr(ir2lir_ctx_t *ctx,
scc_lir_instr_t *instr) {
scc_vec_push(ctx->instrs, *instr);
}
// 获取或创建 IR 值对应的虚拟寄存器
static int get_vreg_for_value(ir2lir_ctx_t *ctx, scc_hir_value_ref_t val_ref) {
void *found =
scc_hashtable_get(&ctx->value_to_vreg, (void *)(usize)val_ref);
if (found)
return (int)(usize)found;
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,
(void *)(usize)vreg);
return vreg;
}
// 获取 LIR 操作数:若为常量/全局符号则直接构造,否则返回对应 vreg
static scc_lir_val_t ir_value_to_lir_operand(ir2lir_ctx_t *ctx,
scc_hir_value_ref_t val_ref) {
scc_hir_value_t *val = scc_hir_module_get_value(ctx->hir_module, val_ref);
Assert(val != nullptr);
switch (val->tag) {
case SCC_HIR_VALUE_TAG_INTEGER: {
return SCC_LIR_IMM(val->data.integer);
}
case SCC_HIR_VALUE_TAG_DECIMAL: {
TODO();
}
case SCC_HIR_VALUE_TAG_GLOBAL_ALLOC: {
// 全局变量地址作为符号
scc_hir_value_t *global_val = scc_hir_module_get_value(
ctx->hir_module, val->data.global_alloc.value);
return SCC_LIR_SYMBOL(global_val->name);
}
case SCC_HIR_VALUE_TAG_FUNC_ARG_REF: {
// 函数参数:预先已分配 vreg
return SCC_LIR_ARG(val->data.arg_ref.idx);
}
case SCC_HIR_VALUE_TAG_NULLPTR: {
scc_ap_t ap;
ap.data.digit = 0;
ap.capacity = -1;
return SCC_LIR_IMM(ap);
}
default: {
// 其他所有产生值的指令:确保其指令已生成,然后返回 vreg
// 注意:这里可能会递归调用 translate_ir_value因此需要先检查是否已翻译
void *found =
scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)val_ref);
if (!found) {
translate_hir_value(ctx, val, val_ref);
}
unsigned int vreg = (unsigned int)(uintptr_t)scc_hashtable_get(
&ctx->value_to_vreg, (void *)(uintptr_t)val_ref);
return SCC_LIR_VREG(vreg);
}
}
}
static scc_lir_cond_t map_cmp_cond(scc_hir_op_type_t op, cbool is_float) {
if (is_float) {
switch (op) {
case SCC_HIR_OP_EQ:
return SCC_LIR_COND_FEQ;
case SCC_HIR_OP_NEQ:
return SCC_LIR_COND_FNE;
case SCC_HIR_OP_LT:
return SCC_LIR_COND_FLT;
case SCC_HIR_OP_LE:
return SCC_LIR_COND_FLE;
case SCC_HIR_OP_GT:
return SCC_LIR_COND_FGT;
case SCC_HIR_OP_GE:
return SCC_LIR_COND_FGE;
default:
Panic("invalid float cmp");
}
} else {
// 默认为有符号比较 (无符号需额外处理类型)
switch (op) {
case SCC_HIR_OP_EQ:
return SCC_LIR_COND_EQ;
case SCC_HIR_OP_NEQ:
return SCC_LIR_COND_NE;
case SCC_HIR_OP_LT:
return SCC_LIR_COND_SLT;
case SCC_HIR_OP_LE:
return SCC_LIR_COND_SLE;
case SCC_HIR_OP_GT:
return SCC_LIR_COND_SGT;
case SCC_HIR_OP_GE:
return SCC_LIR_COND_SGE;
default:
Panic("invalid int cmp");
}
}
return SCC_LIR_COND_EQ;
}
static scc_lir_op_t map_binop(scc_hir_op_type_t op, cbool is_float) {
if (is_float) {
switch (op) {
case SCC_HIR_OP_ADD:
return SCC_LIR_FADD;
case SCC_HIR_OP_SUB:
return SCC_LIR_FSUB;
case SCC_HIR_OP_MUL:
return SCC_LIR_FMUL;
case SCC_HIR_OP_DIV:
return SCC_LIR_FDIV;
default:
Panic("unsupported float binop");
}
} else {
switch (op) {
case SCC_HIR_OP_ADD:
return SCC_LIR_ADD;
case SCC_HIR_OP_SUB:
return SCC_LIR_SUB;
case SCC_HIR_OP_MUL:
return SCC_LIR_MUL;
case SCC_HIR_OP_DIV:
return SCC_LIR_DIV_S;
case SCC_HIR_OP_MOD:
return SCC_LIR_REM_S;
case SCC_HIR_OP_AND:
return SCC_LIR_AND;
case SCC_HIR_OP_OR:
return SCC_LIR_OR;
case SCC_HIR_OP_XOR:
return SCC_LIR_XOR;
case SCC_HIR_OP_SHL:
return SCC_LIR_SHL;
case SCC_HIR_OP_SHR:
return SCC_LIR_SHR;
case SCC_HIR_OP_SAR:
return SCC_LIR_SAR;
default:
return SCC_LIR_CMP;
}
}
return SCC_LIR_NOP;
}
static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
scc_hir_value_ref_t value_ref) {
// 防止重复翻译
if (scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)value_ref))
return;
scc_hir_type_t *ty = scc_hir_module_get_type(ctx->hir_module, value->type);
u8 size = 0;
scc_lir_ext_t ext = SCC_LIR_EXT_NONE;
if (ty != nullptr) {
ir_type_to_lir_size_ext(ty, &size, &ext);
}
bool is_float = (ext == SCC_LIR_EXT_FLOAT);
// 为当前指令分配目标虚拟寄存器
unsigned int dst_vreg = get_vreg_for_value(ctx, value_ref);
switch (value->tag) {
case SCC_HIR_VALUE_TAG_OP: {
scc_lir_val_t lhs = ir_value_to_lir_operand(ctx, value->data.op.lhs);
scc_lir_val_t rhs = ir_value_to_lir_operand(ctx, value->data.op.rhs);
scc_lir_op_t op = map_binop(value->data.op.op, is_float);
scc_lir_instr_t instr = {
.op = op,
.size = size,
.ext = ext,
.to = SCC_LIR_VREG(dst_vreg),
.arg0 = lhs,
.arg1 = rhs,
};
if (op == SCC_LIR_CMP) {
instr.metadata.cond = map_cmp_cond(value->data.op.op, is_float);
}
scc_lir_builder_add_instr(ctx, &instr);
} break;
case SCC_HIR_VALUE_TAG_LOAD: {
scc_lir_val_t addr =
ir_value_to_lir_operand(ctx, value->data.load.target);
scc_lir_instr_t instr = {.op = SCC_LIR_LOAD,
.size = size,
.ext = ext,
.to = SCC_LIR_VREG(dst_vreg),
.arg0 = addr};
scc_lir_builder_add_instr(ctx, &instr);
} break;
case SCC_HIR_VALUE_TAG_STORE: {
scc_lir_val_t data =
ir_value_to_lir_operand(ctx, value->data.store.value);
scc_lir_val_t addr =
ir_value_to_lir_operand(ctx, value->data.store.target);
scc_lir_instr_t instr = {
.op = SCC_LIR_STORE, .size = size, .arg0 = data, .arg1 = addr};
scc_lir_builder_add_instr(ctx, &instr);
} break;
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: {
// 将指针运算转换为 LEA
scc_lir_val_t base =
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.src_addr);
scc_lir_val_t index = SCC_LIR_IMM(0);
if (value->data.get_elem_ptr.index)
ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.index);
// 计算元素大小
scc_hir_type_t *ptr_ty = scc_hir_module_get_type_by_value(
ctx->hir_module, value->data.get_elem_ptr.src_addr);
scc_hir_type_t *elem_ty = nullptr;
if (ptr_ty->tag == SCC_HIR_TYPE_PTR) {
elem_ty = scc_hir_module_get_type(ctx->hir_module,
ptr_ty->data.pointer.base);
} else if (ptr_ty->tag == SCC_HIR_TYPE_ARRAY) {
elem_ty = scc_hir_module_get_type(ctx->hir_module,
ptr_ty->data.array.base);
}
Assert(elem_ty != nullptr);
int elem_size = 0;
// 简化:仅处理基本类型
if (elem_ty->tag == SCC_HIR_TYPE_i32 ||
elem_ty->tag == SCC_HIR_TYPE_u32)
elem_size = 4;
else if (elem_ty->tag == SCC_HIR_TYPE_i64 ||
elem_ty->tag == SCC_HIR_TYPE_u64)
elem_size = 8;
else if (elem_ty->tag == SCC_HIR_TYPE_i8 ||
elem_ty->tag == SCC_HIR_TYPE_u8)
elem_size = 1;
else if (elem_ty->tag == SCC_HIR_TYPE_ARRAY)
elem_size = 8; // FIXME ptr size
else
Panic("unsupported element type for getelemptr");
// 构造地址表达式base + index * elem_size
scc_lir_val_t addr =
SCC_LIR_ADDR(dst_vreg, -1, index.data.reg, elem_size);
// 更简单的做法:使用 LEA 指令,参数为 base 和 index由后端展开
scc_lir_instr_t instr = {.op = SCC_LIR_LOAD_ADDR,
.size = SCC_LIR_SIZE_64,
.to = SCC_LIR_VREG(dst_vreg),
.arg0 = base,
.arg1 = index};
// 实际需要将 index * elem_size 的信息编码,这里简化,假设后端处理
scc_lir_builder_add_instr(ctx, &instr);
} break;
case SCC_HIR_VALUE_TAG_ALLOC: {
// alloca 指令:分配栈空间
scc_hir_type_t *alloc_ty =
scc_hir_module_get_type(ctx->hir_module, ty->data.pointer.base);
// 计算大小和对齐(简化)
int alloc_size = 8; // 默认
if (alloc_ty->tag == SCC_HIR_TYPE_i32)
alloc_size = 4;
scc_lir_instr_t instr = {.op = SCC_LIR_ALLOCA,
.size = SCC_LIR_SIZE_64,
.to = SCC_LIR_VREG(dst_vreg),
.metadata.alloca = {alloc_size, alloc_size}};
scc_lir_builder_add_instr(ctx, &instr);
} break;
case SCC_HIR_VALUE_TAG_CALL: {
scc_hir_func_t *callee = scc_hir_module_get_func(
ctx->hir_module, value->data.call.callee.func_ref);
int arg_count = scc_vec_size(value->data.call.args);
scc_lir_val_t *lir_args = scc_malloc(sizeof(scc_lir_val_t) * arg_count);
for (int i = 0; i < arg_count; i++) {
scc_hir_value_ref_t arg_ref = scc_vec_at(value->data.call.args, i);
lir_args[i] = ir_value_to_lir_operand(ctx, arg_ref);
}
scc_lir_instr_t instr = {
.op = SCC_LIR_CALL,
.size = size,
.to = SCC_LIR_VREG(dst_vreg),
.metadata.call = {.callee = callee->name,
.args = lir_args,
.arg_count = arg_count,
.ret_vreg = SCC_LIR_VREG(dst_vreg),
.clobber_mask = 0}};
scc_lir_builder_add_instr(ctx, &instr);
// 注意lir_args 内存将随指令结构体复制到基本块向量中,但
// metadata.call.args 指针仍指向 malloc 内存,
// 这会导致内存泄漏。实际实现中应使用 arena
// 分配或随函数释放。此处为示例简化。
} break;
case SCC_HIR_VALUE_TAG_BRANCH: {
scc_lir_val_t cond =
ir_value_to_lir_operand(ctx, value->data.branch.cond);
scc_lir_instr_t instr = {
.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);
} break;
case SCC_HIR_VALUE_TAG_JUMP: {
scc_lir_instr_t instr = {.op = SCC_LIR_JMP,
.metadata.jmp_target =
value->data.jump.target_bblock};
scc_lir_builder_add_instr(ctx, &instr);
} break;
case SCC_HIR_VALUE_TAG_RET: {
scc_lir_val_t ret_val;
if (value->data.ret.ret_val != SCC_HIR_REF_nullptr) {
ret_val = ir_value_to_lir_operand(ctx, value->data.ret.ret_val);
} else {
ret_val = SCC_LIR_NONE();
}
scc_lir_instr_t instr = {.op = SCC_LIR_RET,
.metadata.ret_val = ret_val};
scc_lir_builder_add_instr(ctx, &instr);
} break;
case SCC_HIR_VALUE_TAG_CONV: {
// 类型转换:使用 MOV 指令配合扩展/截断
scc_lir_val_t src =
ir_value_to_lir_operand(ctx, value->data.conv.operand);
scc_lir_ext_t conv_ext = SCC_LIR_EXT_NONE;
if (value->data.conv.conv_type == CONV_SEXT)
conv_ext = SCC_LIR_EXT_SEXT;
else if (value->data.conv.conv_type == CONV_ZEXT)
conv_ext = SCC_LIR_EXT_ZEXT;
// TRUNC 用 NONE 即可MOV 截断)
scc_lir_instr_t instr = {.op = SCC_LIR_MOV,
.size = size,
.ext = conv_ext,
.to = SCC_LIR_VREG(dst_vreg),
.arg0 = src};
scc_lir_builder_add_instr(ctx, &instr);
} break;
default:
// 不生成指令的节点(如 CONST_INT, FUNC_ARG_REF不会调用本函数
break;
}
}
static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
scc_hir_func_meta_t *func_meta = SCC_HIR_FUNC_META(ir_func);
scc_lir_func_meta_t *lir_func_meta =
scc_malloc(sizeof(scc_lir_func_meta_t));
Assert(lir_func_meta != nullptr);
*lir_func_meta = (scc_lir_func_meta_t){
.attr = SCC_LIR_ATTR_NONE,
.frame_size = 0,
.vregs_count = 0,
.is_va_arg = false,
};
scc_vec_push(ctx->lir_module->func_metas, lir_func_meta);
ctx->current_func = ir_func;
ir_func->meta = lir_func_meta;
// 预先为所有参数分配虚拟寄存器
scc_vec_foreach(func_meta->params, i) {
scc_hir_value_ref_t param_ref = scc_vec_at(func_meta->params, i);
get_vreg_for_value(ctx, param_ref);
}
scc_vec_foreach(ir_func->bblocks, i) {
scc_hir_bblock_ref_t bb_ref = scc_vec_at(ir_func->bblocks, i);
scc_hir_bblock_t *bb =
scc_hir_module_get_bblock(ctx->hir_module, bb_ref);
scc_vec_init(ctx->instrs);
// 翻译指令
scc_vec_foreach(bb->values, j) {
scc_hir_value_ref_t val_ref =
scc_vec_at(*SCC_HIR_BBLOCK_VALUES(bb), j);
scc_hir_value_t *val =
scc_hir_module_get_value(ctx->hir_module, val_ref);
translate_hir_value(ctx, val, val_ref);
}
bb->values = *(scc_cfg_value_vec_t *)&ctx->instrs;
// MOVE
scc_vec_init(ctx->instrs);
}
// 清理本次函数翻译的临时映射
scc_hashtable_drop(&ctx->value_to_vreg);
}
void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) {
Assert(module != nullptr && cprog != nullptr);
// FIXME
module->cfg_module = cprog->module.cfg_module;
ir2lir_ctx_t ctx;
ir2lir_ctx_init(&ctx, module, &cprog->module);
// 1. 处理全局变量
for (usize i = 0; i < scc_vec_size(cprog->global_vals); i++) {
scc_hir_value_ref_t gv_ref = scc_vec_at(cprog->global_vals, i);
scc_hir_value_t *galloc =
scc_hir_module_get_value(&cprog->module, gv_ref);
Assert(galloc->tag == SCC_HIR_VALUE_TAG_GLOBAL_ALLOC);
scc_hir_value_t *val = scc_hir_module_get_value(
&cprog->module, galloc->data.global_alloc.value);
scc_hir_buffer_t *data = &val->data.const_array.fields;
scc_lir_symbol_id_t id = scc_lir_module_add_data(
module, galloc->name, SCC_CFG_SYMBOL_KIND_DATA,
scc_vec_unsafe_get_data(*data), scc_vec_size(*data), 0);
Assert(id != SCC_CFG_ID_nullptr);
}
// 2. 处理函数声明 (外部函数)
for (usize i = 0; i < scc_vec_size(cprog->func_decls); i++) {
scc_hir_func_ref_t func_ref = scc_vec_at(cprog->func_decls, i);
scc_hir_func_t *func =
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);
Assert(id != SCC_CFG_ID_nullptr);
// 记录映射,供调用时使用
scc_hashtable_set(&ctx.func_decl_map, (void *)(uintptr_t)func_ref,
(void *)func->name);
}
// 3. 处理函数定义
for (usize i = 0; i < scc_vec_size(cprog->func_defs); i++) {
scc_hir_func_ref_t func_ref = scc_vec_at(cprog->func_defs, i);
scc_hir_func_t *func =
scc_hir_module_get_func(&cprog->module, func_ref);
if (!func)
continue;
translate_func(&ctx, func);
}
ir2lir_ctx_drop(&ctx);
}