/** * @file scc_hir2lir.c * @brief 将高级 IR (scc_ir) 降级为低层 LIR (scc_lir) */ #include #include /* ---------- 转换上下文 ---------- */ 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); }