Files
scc/libs/ir/lir/src/scc_hir2lir.c
zzy 2c13ac54df feat(ast2ir): 添加浮点类型支持和复合初始化功能
- 在ABI类型计算中添加FLOAT和DOUBLE类型的映射
- 修复AST操作符注释中的歧义描述
- 为ast2ir上下文添加类型缓存以解决递归结构体定义问题
- 实现复合初始化表达式的支持,包括数组和结构体初始化
- 添加前置和后置自增/自减操作符的IR转换
- 实现三元条件表达式的IR生成
- 添加类型转换(cast)和sizeof操作符的支持
- 重构数组长度推断逻辑并添加类型大小计算函数
- 实现结构体和联合体的递归类型解析
- 添加函数指针调用相关的IR节点类型定义

fix(ast): 修正间接操作符的注释说明

refactor(ast2ir): 优化代码结构并添加必要的断言验证
2026-05-19 17:35:24 +08:00

537 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 map_cmp_cond(op, is_float);
}
}
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};
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_LEA,
.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,
};
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, const 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);
}