#include #include #include #include #include // 判断 AST 参数是否为 ... 生成的假 VA_LIST 参数 static cbool is_variadic_marker(const scc_ast_decl_t *decl_param) { return decl_param->name == nullptr && decl_param->param.type->base.type == SCC_AST_TYPE_BUILTIN && scc_ast_canon_type(decl_param->param.type)->builtin.type == SCC_AST_BUILTIN_TYPE_VA_LIST; } // 计算函数类型中的固定参数个数(去掉尾部的 ... 标记) static int fixed_param_count(const scc_ast_canon_type_t *canon) { int n = (int)scc_vec_size(canon->function.params); if (n > 0) { const scc_ast_decl_t *last = scc_vec_at(canon->function.params, (usize)(n - 1)); if (is_variadic_marker(last)) return n - 1; } return n; } static scc_hir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx, const scc_ast_qual_type_t *ast_type) { scc_abi_type_layout_t layout; // 映射内置类型 ctx->abi->compute_type_layout(ctx->abi, (void *)ast_type, &layout); switch (layout.size) { case 0: return scc_hir_builder_type_void(&ctx->builder); case 1: return scc_hir_builder_type_i8(&ctx->builder); case 2: return scc_hir_builder_type_i16(&ctx->builder); case 4: return scc_hir_builder_type_i32(&ctx->builder); case 8: return scc_hir_builder_type_i64(&ctx->builder); break; default: break; } return SCC_HIR_REF_nullptr; } static inline bool scc_hir_type_is_signed(scc_hir_type_tag_t tag) { switch (tag) { case SCC_HIR_TYPE_i8: case SCC_HIR_TYPE_i16: case SCC_HIR_TYPE_i32: case SCC_HIR_TYPE_i64: case SCC_HIR_TYPE_i128: return true; case SCC_HIR_TYPE_u8: case SCC_HIR_TYPE_u16: case SCC_HIR_TYPE_u32: case SCC_HIR_TYPE_u64: case SCC_HIR_TYPE_u128: return false; default: // 指针可以视作无符号整数 return false; } } // 判断是否为算术类型(整数或浮点) static cbool is_arithmetic_type(const scc_hir_type_t *type) { switch (type->tag) { case SCC_HIR_TYPE_i8: case SCC_HIR_TYPE_i16: case SCC_HIR_TYPE_i32: case SCC_HIR_TYPE_i64: case SCC_HIR_TYPE_i128: case SCC_HIR_TYPE_u8: case SCC_HIR_TYPE_u16: case SCC_HIR_TYPE_u32: case SCC_HIR_TYPE_u64: case SCC_HIR_TYPE_u128: case SCC_HIR_TYPE_f16: case SCC_HIR_TYPE_f32: case SCC_HIR_TYPE_f64: case SCC_HIR_TYPE_f128: return true; default: return false; } } // 辅助函数:生成数组初始化代码 static void emit_array_initialization(scc_ast2ir_ctx_t *ctx, scc_hir_value_ref_t array_ptr, const scc_hir_type_t *array_type, const scc_ast_expr_t *init_expr) { Assert(array_type->tag == SCC_HIR_TYPE_ARRAY); scc_hir_type_ref_t elem_type_ref = array_type->data.array.base; const scc_hir_type_t *elem_type = scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), elem_type_ref); usize array_len = array_type->data.array.len; // 字符串字面量初始化:直接 memcpy if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) { scc_hir_value_ref_t str_val = scc_ast2ir_expr(ctx, init_expr, false); scc_ap_t len_ap; scc_ap_set_int(&len_ap, array_len); scc_hir_value_ref_t len_ref = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &len_ap); scc_hir_builder_builtin_memcpy(&ctx->builder, array_ptr, str_val, len_ref); return; } // 复合初始化:逐个元素 store if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) { Panic("unsupported initializer for array"); } // 遍历初始化列表 usize idx = 0; scc_vec_foreach(init_expr->compound.rhs_exprs, i) { scc_ast_expr_t *elem_expr = scc_vec_at(init_expr->compound.rhs_exprs, i); Assert(elem_expr != nullptr); if (idx >= array_len) break; // 防止溢出 // 生成元素地址:array_ptr + idx * elem_size scc_ap_t offset_ap; scc_ap_set_int(&offset_ap, idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &offset_ap); scc_hir_value_ref_t elem_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, array_ptr, idx_val); // 递归处理:如果元素本身是数组且初始化表达式是复合初始化,需要嵌套处理 if (elem_type->tag == SCC_HIR_TYPE_ARRAY && elem_expr->base.type == SCC_AST_EXPR_COMPOUND) { // 递归调用自身,但注意 elem_ptr 已经是子数组的首地址 emit_array_initialization(ctx, elem_ptr, elem_type, elem_expr); } else { // 标量元素:计算右值并 store scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, elem_expr, false); scc_hir_builder_store(&ctx->builder, elem_ptr, val); } idx++; } // 如果初始化列表元素少于数组长度,剩余元素默认零初始化(C 标准要求) // 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理 } static void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx, scc_hir_value_ref_t base_ptr, const scc_hir_type_t *type, const scc_ast_expr_t *init_expr) { Assert(type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION); if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) { Panic("expected compound initializer"); } usize idx = 0; scc_vec_foreach(init_expr->compound.rhs_exprs, i) { if (idx >= type->data.aggregate.fields.size) break; scc_ast_expr_t *field_init = scc_vec_at(init_expr->compound.rhs_exprs, i); scc_hir_type_ref_t field_type_ref = scc_vec_at(type->data.aggregate.fields, idx); const scc_hir_type_t *field_type = scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), field_type_ref); scc_ap_t idx_ap; scc_ap_set_int(&idx_ap, idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); scc_hir_value_ref_t field_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, idx_val); if (field_type->tag == SCC_HIR_TYPE_ARRAY) { emit_array_initialization(ctx, field_ptr, field_type, field_init); } else if (field_type->tag == SCC_HIR_TYPE_STRUCT || field_type->tag == SCC_HIR_TYPE_UNION) { emit_aggregate_initialization(ctx, field_ptr, field_type, field_init); } else { scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, field_init, false); scc_hir_builder_store(&ctx->builder, field_ptr, val); } idx++; } } // static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {} // 辅助函数:计算数组实际长度(如果原长度为0) static void resolve_array_length(scc_ast2ir_ctx_t *ctx, const scc_hir_type_t *orig_array_type, scc_hir_type_t *resolved_array_type, const scc_ast_expr_t *init_expr) { *resolved_array_type = *orig_array_type; // 拷贝 Assert(orig_array_type->tag == SCC_HIR_TYPE_ARRAY); if (orig_array_type->data.array.len != 0) return; // 长度已知,无需推断 usize new_len = 0; switch (init_expr->base.type) { case SCC_AST_EXPR_STRING_LITERAL: // 字符串字面量:长度 = 字符串字符数 + 1('\0') // TODO: L"" \n \r 计算 暂不支持 new_len = scc_strlen(init_expr->literal.lexme) + 1; break; case SCC_AST_EXPR_COMPOUND: { // 复合初始化:元素个数 = 初始化列表长度 scc_vec_foreach(init_expr->compound.lhs_exprs, i) { scc_ast_expr_t *elem = scc_vec_at(init_expr->compound.lhs_exprs, i); // TODO: 支持嵌套的多维数组初始化(递归) // 这里简化:只统计顶层元素个数,假设是一维数组 new_len++; } break; } default: Panic("unsupported initializer for zero-length array"); } resolved_array_type->data.array.len = new_len; } scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, const scc_ast_qual_type_t *ast_type) { if (ctx == nullptr || ast_type == nullptr) { LOG_ERROR("args is nullptr"); return 0; } scc_hir_type_t ir_type; switch (ast_type->base.type) { case SCC_AST_TYPE_BUILTIN: { return parse_base_type(ctx, ast_type); } case SCC_AST_TYPE_POINTER: { scc_hir_type_init(&ir_type, SCC_HIR_TYPE_PTR); scc_hir_type_ref_t pointee_type = scc_ast2ir_type(ctx, scc_ast_canon_type(ast_type)->pointer.pointee); ir_type.data.pointer.base = pointee_type; break; } case SCC_AST_TYPE_ARRAY: { scc_hir_type_init(&ir_type, SCC_HIR_TYPE_ARRAY); scc_hir_type_ref_t element_type = scc_ast2ir_type(ctx, scc_ast_canon_type(ast_type)->array.element); ir_type.data.array.base = element_type; ir_type.data.array.len = 0; if (scc_ast_canon_type(ast_type)->array.size) { // TODO constant expression if (scc_ast_canon_type(ast_type)->array.size->base.type != SCC_AST_EXPR_INT_LITERAL) { Panic("TODO: array size expression"); } scc_ap_t value; scc_ap_from_cstr( &value, scc_ast_canon_type(ast_type)->array.size->literal.lexme, 10); // FIXME hack ir_type.data.array.len = value.data.digit; } } break; case SCC_AST_TYPE_FUNCTION: { scc_hir_type_init(&ir_type, SCC_HIR_TYPE_FUNC); // 处理返回类型 scc_hir_type_ref_t ret_type = scc_ast2ir_type( ctx, scc_ast_canon_type(ast_type)->function.return_type); // 将返回类型添加到程序的类型容器中 ir_type.data.function.ret_type = ret_type; // 转换参数类型(跳过尾部的 ... 假参数) scc_hir_type_ref_vec_t params; scc_vec_init(params); int n_fixed = fixed_param_count(scc_ast_canon_type(ast_type)); scc_ast_decl_vec_t *ast_params = &scc_ast_canon_type(ast_type)->function.params; for (int i = 0; i < n_fixed; i++) { scc_ast_decl_t *decl_param = scc_vec_at(*ast_params, i); Assert(decl_param->base.type == SCC_AST_DECL_PARAM); scc_hir_type_ref_t tmp_type = scc_ast2ir_type(ctx, decl_param->param.type); scc_vec_push(params, tmp_type); } ir_type.data.function.params = params; } break; case SCC_AST_TYPE_STRUCT: case SCC_AST_TYPE_UNION: { const scc_ast_canon_type_t *canon = scc_ast_canon_type(ast_type); // === 1. 查缓存,如果已存在则直接返回(递归时一定会命中) === scc_hir_type_ref_t cached = (scc_hir_type_ref_t)(usize)scc_hashtable_get(&ctx->type_cache, canon); if (cached != 0) { return cached; } // === 2. 创建占位类型(字段为空) === scc_hir_type_t placeholder; scc_hir_type_init(&placeholder, ast_type->base.type == SCC_AST_TYPE_STRUCT ? SCC_HIR_TYPE_STRUCT : SCC_HIR_TYPE_UNION); // 可以给占位符一个调试名 if (canon->record.name) { placeholder.name = canon->record.name; } // === 3. 直接添加到模块,不经过 builder 的 uniquing === // 因为此时我们不需要类型去重,只需要一个确定不移的引用 scc_hir_type_ref_t place_ref = scc_hir_module_add_type(scc_ast2ir_mir_module(ctx), &placeholder); // === 4. 将映射写入缓存(关键!必须在递归前) === scc_hashtable_set(&ctx->type_cache, canon, (void *)(usize)place_ref); // === 5. 递归解析所有字段 === // 此时若字段类型指回本结构体,将直接通过缓存返回 place_ref scc_hir_type_ref_vec_t fields; scc_vec_init(fields); scc_ast_decl_t *decl = canon->record.decl; if (decl == nullptr) { Panic("struct/union declaration is missing"); } scc_vec_foreach(decl->record.fields, i) { scc_ast_decl_t *field_decl = scc_vec_at(decl->record.fields, i); Assert(field_decl->base.type == SCC_AST_DECL_VAR); scc_hir_type_ref_t field_ir_type = scc_ast2ir_type(ctx, field_decl->var.type); scc_vec_push(fields, field_ir_type); } // === 6. 将字段填入占位类型 === scc_hir_type_t *place_type = scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), place_ref); // 注意:scc_hir_type_init 已经为 struct/union 初始化了 fields 空向量 // 这里直接 push 即可(也可以先 scc_vec_free 再 init,看需要) scc_vec_foreach(fields, i) { scc_vec_push(place_type->data.aggregate.fields, scc_vec_at(fields, i)); } scc_vec_free(fields); // 释放临时向量 // === 7. 返回占位符的引用(现在已经变成完整类型) === return place_ref; } break; case SCC_AST_TYPE_ENUM: scc_ast_canon_type_t *int_canon_type = scc_ast_ctx_get_builtin_type( ctx->ast_ctx, SCC_AST_BUILTIN_TYPE_INT); scc_ast_qual_type_t int_type = { .base.type = SCC_AST_TYPE_BUILTIN, .type = int_canon_type, }; return parse_base_type(ctx, &int_type); case SCC_AST_TYPE_TYPEDEF: // TODO maybe using cache return scc_ast2ir_type( ctx, scc_ast_canon_type(ast_type)->typedef_type.decl->typedef_decl.type); default: LOG_FATAL("Unsupported AST type: %d", ast_type->base.type); return 0; } return scc_hir_builder_type(&ctx->builder, &ir_type); } scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, const scc_ast_expr_t *expr) { // scc_hir_bblock_ref_t start_block = // scc_hir_builder_current_bblock(&ctx->builder); scc_hir_value_ref_t right_block = scc_hir_builder_create_bblock(&ctx->builder, "logic_right"); scc_hir_value_ref_t end_block = scc_hir_builder_create_bblock(&ctx->builder, "logic_end"); // 为结果创建临时存储空间 scc_hir_type_ref_t int32_type = scc_hir_builder_type_i32(&ctx->builder); scc_hir_value_ref_t result_var = scc_hir_builder_alloca(&ctx->builder, int32_type, "logic_result"); // 计算左操作数 scc_hir_value_ref_t left_val = scc_ast2ir_expr(ctx, expr->binary.lhs, false); scc_ap_t zero_ap; scc_ap_set_int(&zero_ap, 0); scc_ap_t one_ap; scc_ap_set_int(&one_ap, 1); scc_hir_value_ref_t zero_val = scc_hir_builder_integer(&ctx->builder, int32_type, &zero_ap); scc_hir_value_ref_t one_val = scc_hir_builder_integer(&ctx->builder, int32_type, &one_ap); if (expr->binary.op == SCC_AST_OP_LOGICAL_AND) { // a && b scc_hir_value_ref_t false_block = scc_hir_builder_create_bblock(&ctx->builder, "and_false"); // 如果左操作数为0,结果为0(短路) scc_hir_value_ref_t is_left_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, left_val, zero_val); scc_hir_builder_branch(&ctx->builder, is_left_zero, false_block, right_block); // false_block: 左边为0,结果为0 scc_hir_builder_append_bblock(&ctx->builder, false_block); scc_hir_builder_set_current_bblock(&ctx->builder, false_block); scc_hir_builder_store(&ctx->builder, result_var, zero_val); scc_hir_builder_jump(&ctx->builder, end_block); // right_block: 左边非0,计算右边 scc_hir_builder_append_bblock(&ctx->builder, right_block); scc_hir_builder_set_current_bblock(&ctx->builder, right_block); scc_hir_value_ref_t right_val = scc_ast2ir_expr(ctx, expr->binary.rhs, false); scc_hir_value_ref_t is_right_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, right_val, zero_val); scc_hir_value_ref_t result = scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_XOR, is_right_zero, one_val); // !right == 0 ? 1 : 0 scc_hir_builder_store(&ctx->builder, result_var, result); scc_hir_builder_jump(&ctx->builder, end_block); } else { // SCC_AST_OP_LOGICAL_OR // a || b scc_hir_value_ref_t true_block = scc_hir_builder_create_bblock(&ctx->builder, "or_true"); // 如果左操作数非0,结果为1(短路) scc_hir_value_ref_t is_left_nonzero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_NEQ, left_val, zero_val); scc_hir_builder_branch(&ctx->builder, is_left_nonzero, true_block, right_block); // true_block: 左边非0,结果为1 scc_hir_builder_append_bblock(&ctx->builder, true_block); scc_hir_builder_set_current_bblock(&ctx->builder, true_block); scc_hir_builder_store(&ctx->builder, result_var, one_val); scc_hir_builder_jump(&ctx->builder, end_block); // right_block: 左边为0,计算右边 scc_hir_builder_append_bblock(&ctx->builder, right_block); scc_hir_builder_set_current_bblock(&ctx->builder, right_block); scc_hir_value_ref_t right_val = scc_ast2ir_expr(ctx, expr->binary.rhs, false); scc_hir_value_ref_t is_right_zero = scc_hir_builder_binop( &ctx->builder, SCC_HIR_OP_EQ, right_val, zero_val); scc_hir_value_ref_t result = scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_XOR, is_right_zero, one_val); // !right == 0 ? 1 : 0 scc_hir_builder_store(&ctx->builder, result_var, result); scc_hir_builder_jump(&ctx->builder, end_block); } // 设置结束块为当前块,并返回结果 scc_hir_builder_append_bblock(&ctx->builder, end_block); scc_hir_builder_set_current_bblock(&ctx->builder, end_block); return scc_hir_builder_load(&ctx->builder, result_var); } /** * @brief * * @param ctx * @param expr * @return scc_hir_value_ref_t */ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, const scc_ast_expr_t *expr, cbool is_lvalue) { if (ctx == nullptr || expr == nullptr) { LOG_ERROR("args is nullptr"); return 0; } cbool is_assign = true; switch (expr->base.type) { case SCC_AST_EXPR_BINARY: { scc_ast_expr_t tmp_expr; scc_hir_value_ref_t lhs = SCC_HIR_REF_nullptr, rhs = SCC_HIR_REF_nullptr; switch (expr->binary.op) { case SCC_AST_OP_ASSIGN: // = rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); break; case SCC_AST_OP_ASSIGN_ADD: // += scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_ADD, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_SUB: // -= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_SUB, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_MUL: // *= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_MUL, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_DIV: // /= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_DIV, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_MOD: // %= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_MOD, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_AND: // &= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_AND, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_XOR: // ^= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_XOR, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_OR: // |= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_BITWISE_OR, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_LSHIFT: // <<= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_LEFT_SHIFT, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; case SCC_AST_OP_ASSIGN_RSHIFT: // >>= scc_ast_expr_binary_init(&tmp_expr, SCC_AST_OP_RIGHT_SHIFT, expr->binary.lhs, expr->binary.rhs, expr->base.loc); rhs = scc_ast2ir_expr(ctx, &tmp_expr, false); break; default: is_assign = false; break; } if (is_assign) { Assert(rhs != SCC_HIR_REF_nullptr); lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, true); // 将 RHS 转换为 LHS 指向的类型(C11 6.5.16.1 简单赋值) scc_hir_type_t *lhs_ptr_type = scc_hir_module_get_type_by_value( scc_ast2ir_mir_module(ctx), lhs); if (lhs_ptr_type->tag == SCC_HIR_TYPE_PTR && is_arithmetic_type( scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), lhs_ptr_type->data.pointer.base))) { rhs = scc_ast2ir_emit_conversion( ctx, rhs, lhs_ptr_type->data.pointer.base); } return scc_hir_builder_store(&ctx->builder, lhs, rhs); } if (expr->binary.op == SCC_AST_OP_LOGICAL_AND || expr->binary.op == SCC_AST_OP_LOGICAL_OR) { // TODO 类型提升 return scc_ast2ir_logical_expr(ctx, expr); } rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false); lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, false); // 类型提升:对算术类型二元操作应用寻常算术转换(C11 6.3.1.8) // 移位操作符不适用(仅对每个操作数单独整数提升) cbool is_shift = (expr->binary.op == SCC_AST_OP_LEFT_SHIFT || expr->binary.op == SCC_AST_OP_RIGHT_SHIFT); if (!is_shift && expr->binary.op != SCC_AST_OP_COMMA) { scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t lhs_type_ref = scc_hir_module_get_value(module, lhs)->type; scc_hir_type_ref_t rhs_type_ref = scc_hir_module_get_value(module, rhs)->type; scc_hir_type_t *lhs_type = scc_hir_module_get_type(module, lhs_type_ref); scc_hir_type_t *rhs_type = scc_hir_module_get_type(module, rhs_type_ref); if (is_arithmetic_type(lhs_type) && is_arithmetic_type(rhs_type)) { scc_hir_type_ref_t common = scc_ast2ir_usual_arithmetic_conversion(ctx, lhs_type_ref, rhs_type_ref); if (common != 0) { lhs = scc_ast2ir_emit_conversion(ctx, lhs, common); rhs = scc_ast2ir_emit_conversion(ctx, rhs, common); } } } else if (is_shift) { // 移位操作符:只进行整数提升(C11 6.5.7) scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t lhs_type_ref = scc_hir_module_get_value(module, lhs)->type; scc_hir_type_ref_t promoted = scc_ast2ir_integer_promotion(ctx, lhs_type_ref); if (promoted != 0) lhs = scc_ast2ir_emit_conversion(ctx, lhs, promoted); } // 映射操作符 scc_hir_op_type_t op; switch (expr->binary.op) { /* clang-format off */ case SCC_AST_OP_ADD: op = SCC_HIR_OP_ADD; break; case SCC_AST_OP_SUB: op = SCC_HIR_OP_SUB; break; case SCC_AST_OP_MUL: op = SCC_HIR_OP_MUL; break; case SCC_AST_OP_DIV: op = SCC_HIR_OP_DIV; break; case SCC_AST_OP_MOD: op = SCC_HIR_OP_MOD; break; case SCC_AST_OP_BITWISE_AND: op = SCC_HIR_OP_AND; break; case SCC_AST_OP_BITWISE_OR: op = SCC_HIR_OP_OR; break; case SCC_AST_OP_BITWISE_XOR: op = SCC_HIR_OP_XOR; break; case SCC_AST_OP_LEFT_SHIFT: op = SCC_HIR_OP_SHL; break; case SCC_AST_OP_RIGHT_SHIFT: { op = SCC_HIR_OP_SHR; // FIXME op = SCC_HIR_OP_SAR; break; } case SCC_AST_OP_EQUAL: op = SCC_HIR_OP_EQ; break; case SCC_AST_OP_NOT_EQUAL: op = SCC_HIR_OP_NEQ; break; case SCC_AST_OP_LESS: op = SCC_HIR_OP_LT; break; case SCC_AST_OP_LESS_EQUAL: op = SCC_HIR_OP_LE; break; case SCC_AST_OP_GREATER: op = SCC_HIR_OP_GT; break; case SCC_AST_OP_GREATER_EQUAL: op = SCC_HIR_OP_GE; break; case SCC_AST_OP_COMMA: { // 逗号运算符:计算左表达式,丢弃结果,返回右表达式 return rhs; } /* 逻辑操作符 */ case SCC_AST_OP_LOGICAL_OR: // || case SCC_AST_OP_LOGICAL_AND: // && UNREACHABLE(); return 0; /* clang-format on */ default: LOG_FATAL("Unsupported binary operator: %d", expr->binary.op); return 0; } // 创建操作节点 return scc_hir_builder_binop(&ctx->builder, op, lhs, rhs); } break; case SCC_AST_EXPR_UNARY: { if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) { return scc_ast2ir_expr(ctx, expr->unary.operand, true); } else if (expr->unary.op == SCC_AST_OP_INDIRECTION) { // 从地址取值 scc_hir_value_ref_t ptr = scc_ast2ir_expr(ctx, expr->unary.operand, false); if (is_lvalue) { // 作为左值使用(如 *ptr = ...),直接返回指针值(地址) return ptr; } else { // 作为右值使用(如 x = *ptr),加载指针指向的值 return scc_hir_builder_load(&ctx->builder, ptr); } } scc_hir_value_ref_t operand = scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue); switch (expr->unary.op) { case SCC_AST_OP_UNARY_PLUS: /* just pass */ return operand; case SCC_AST_OP_UNARY_MINUS: { // 负号 // 实现为0 - operand scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_set_int(&value, 0); scc_hir_value_ref_t zero_ref = scc_hir_builder_integer(&ctx->builder, type_ref, &value); return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_SUB, zero_ref, operand); } case SCC_AST_OP_ADDRESS_OF: case SCC_AST_OP_INDIRECTION: UNREACHABLE(); break; case SCC_AST_OP_BITWISE_NOT: // 按位取反 return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_NOT, operand, 0); case SCC_AST_OP_LOGICAL_NOT: { // 逻辑非 // 实现为与0比较 scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_set_int(&value, 0); scc_hir_value_ref_t zero_ref = scc_hir_builder_integer(&ctx->builder, type_ref, &value); return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_EQ, zero_ref, operand); } case SCC_AST_OP_PREFIX_INCREMENT: case SCC_AST_OP_PREFIX_DECREMENT: { // 获取左值地址 scc_hir_value_ref_t addr = scc_ast2ir_expr(ctx, expr->unary.operand, true); scc_hir_value_ref_t old_val = scc_hir_builder_load(&ctx->builder, addr); scc_hir_type_ref_t old_type = scc_hir_module_get_value( scc_hir_builder_get_module(&ctx->builder), old_val) ->type; // 整数提升:C11 6.3.1.1,对 short/char 等类型提升为 int scc_hir_type_ref_t promoted_type_ref = scc_ast2ir_integer_promotion(ctx, old_type); scc_hir_value_ref_t promoted = old_val; if (promoted_type_ref != 0) { promoted = scc_ast2ir_emit_conversion(ctx, old_val, promoted_type_ref); } else { promoted_type_ref = old_type; } scc_hir_value_ref_t one = scc_hir_builder_integer( &ctx->builder, promoted_type_ref, &(scc_ap_t){.data.digit = 1, .capacity = -1}); scc_hir_op_type_t op = (expr->unary.op == SCC_AST_OP_PREFIX_INCREMENT) ? SCC_HIR_OP_ADD : SCC_HIR_OP_SUB; scc_hir_value_ref_t new_val = scc_hir_builder_binop(&ctx->builder, op, promoted, one); // 如果原类型不是提升后的类型,需要截断回原类型再存储 scc_hir_value_ref_t stored_val = new_val; if (promoted_type_ref != old_type) { stored_val = scc_ast2ir_emit_conversion(ctx, new_val, old_type); } scc_hir_builder_store(&ctx->builder, addr, stored_val); Assert(new_val != SCC_HIR_REF_nullptr); return new_val; // 表达式的值是提升后的新值(符合 C 标准) } break; case SCC_AST_OP_POSTFIX_INCREMENT: case SCC_AST_OP_POSTFIX_DECREMENT: { // 获取左值地址 scc_hir_value_ref_t addr = scc_ast2ir_expr(ctx, expr->unary.operand, true); scc_hir_value_ref_t old_val = scc_hir_builder_load(&ctx->builder, addr); scc_hir_type_ref_t old_type = scc_hir_module_get_value( scc_hir_builder_get_module(&ctx->builder), old_val) ->type; // 整数提升(C11 6.3.1.1) scc_hir_type_ref_t promoted_type_ref = scc_ast2ir_integer_promotion(ctx, old_type); scc_hir_value_ref_t promoted = old_val; if (promoted_type_ref != 0) { promoted = scc_ast2ir_emit_conversion(ctx, old_val, promoted_type_ref); } else { promoted_type_ref = old_type; } scc_hir_value_ref_t one = scc_hir_builder_integer( &ctx->builder, promoted_type_ref, &(scc_ap_t){.data.digit = 1, .capacity = -1}); scc_hir_op_type_t op = (expr->unary.op == SCC_AST_OP_POSTFIX_INCREMENT) ? SCC_HIR_OP_ADD : SCC_HIR_OP_SUB; scc_hir_value_ref_t new_val = scc_hir_builder_binop(&ctx->builder, op, promoted, one); scc_hir_value_ref_t stored_val = new_val; if (promoted_type_ref != old_type) { stored_val = scc_ast2ir_emit_conversion(ctx, new_val, old_type); } scc_hir_builder_store(&ctx->builder, addr, stored_val); // 后缀返回旧值的提升后版本(C11 6.5.2.4) return promoted; } break; default: LOG_FATAL("Unsupported unary operator: %d", expr->unary.op); return 0; } UNREACHABLE(); } break; case SCC_AST_EXPR_COND: { scc_hir_type_ref_t true_type = SCC_HIR_REF_nullptr; scc_hir_type_ref_t false_type = SCC_HIR_REF_nullptr; scc_hir_value_ref_t true_block = scc_hir_builder_bblock(&ctx->builder, "cond_true"); scc_hir_value_ref_t false_block = scc_hir_builder_bblock(&ctx->builder, "cond_false"); scc_hir_value_ref_t merge_block = scc_hir_builder_bblock(&ctx->builder, "cond_merge"); scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, expr->cond.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, true_block, false_block); // 生成true分支 scc_hir_builder_set_current_bblock(&ctx->builder, true_block); scc_hir_value_ref_t true_val = scc_ast2ir_expr(ctx, expr->cond.then_expr, false); true_type = scc_hir_module_get_value( scc_hir_builder_get_module(&ctx->builder), true_val) ->type; Assert(true_type != SCC_HIR_REF_nullptr); scc_hir_value_ref_t result_slot = scc_hir_builder_alloca(&ctx->builder, true_type, "cond_result"); scc_hir_builder_store(&ctx->builder, result_slot, true_val); scc_hir_builder_jump(&ctx->builder, merge_block); // 生成false分支 scc_hir_builder_set_current_bblock(&ctx->builder, false_block); scc_hir_value_ref_t false_val = scc_ast2ir_expr(ctx, expr->cond.else_expr, false); false_type = scc_hir_module_get_value( scc_hir_builder_get_module(&ctx->builder), false_val) ->type; Assert(false_type != SCC_HIR_REF_nullptr); scc_hir_builder_store(&ctx->builder, result_slot, false_val); scc_hir_builder_jump(&ctx->builder, merge_block); // 合并并返回 scc_hir_builder_set_current_bblock(&ctx->builder, merge_block); if (true_type != false_type) { LOG_ERROR("Type mismatch in conditional expression"); // FIXME need panic } return scc_hir_builder_load(&ctx->builder, result_slot); } break; case SCC_AST_EXPR_CALL: { // 转换参数 scc_hir_value_ref_vec_t args; scc_vec_init(args); // 获取函数类型信息用于参数转换。注意:不能长期持有指向 types 向量 // 内部的指针(如 ft->data.function.params),因为递归的 // scc_ast2ir_expr 可能触发 scc_hir_module_add_type 导致 realloc。 // 改为通过 func_type_ref(稳定的索引)每次需要时重新获取指针。 scc_hir_func_ref_t callee_func = (scc_hir_func_ref_t)(usize)scc_hashtable_get( &ctx->symtab, expr->call.callee->identifier._target->name); scc_hir_type_ref_t func_type_ref = SCC_HIR_REF_nullptr; cbool is_variadic = false; int fixed_count = 0; if (callee_func != SCC_HIR_REF_nullptr) { scc_hir_func_t *hir_func = scc_hir_module_get_func( scc_ast2ir_mir_module(ctx), callee_func); scc_hir_func_meta_t *meta = SCC_HIR_FUNC_META(hir_func); is_variadic = meta->is_variadic; func_type_ref = meta->type; if (func_type_ref != SCC_HIR_REF_nullptr) { const scc_hir_type_t *ft = scc_hir_module_get_type( scc_ast2ir_mir_module(ctx), func_type_ref); if (ft != nullptr && ft->tag == SCC_HIR_TYPE_FUNC) fixed_count = (int)ft->data.function.params.size; } } scc_vec_foreach(expr->call.args, i) { scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i); scc_hir_value_ref_t arg_node; arg_node = scc_ast2ir_expr(ctx, arg_expr, false); if ((int)i < fixed_count) { // 固定参数:转换为形参类型 // 每次迭代重新获取指针(scc_ast2ir_expr 可能触发 types 向量 // realloc) scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); const scc_hir_type_t *ft = scc_hir_module_get_type(module, func_type_ref); scc_hir_type_ref_t param_type = scc_vec_at(ft->data.function.params, i); arg_node = scc_ast2ir_emit_conversion(ctx, arg_node, param_type); } else if (is_variadic) { // 可变参数:只应用默认参数提升(C11 6.5.2.2) // 整数提升:char/short → int scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); scc_hir_type_ref_t arg_type_ref = scc_hir_module_get_value(module, arg_node)->type; Assert(arg_type_ref != 0); scc_hir_type_tag_t arg_tag = scc_hir_module_get_type(module, arg_type_ref)->tag; scc_hir_type_ref_t promoted = scc_ast2ir_integer_promotion(ctx, arg_type_ref); if (promoted != 0) { arg_node = scc_ast2ir_emit_conversion(ctx, arg_node, promoted); } else if (arg_tag == SCC_HIR_TYPE_f32) { // float → double(默认参数提升) scc_hir_type_t f64_desc; scc_hir_type_init(&f64_desc, SCC_HIR_TYPE_f64); scc_hir_type_ref_t f64_ref = scc_hir_builder_type(&ctx->builder, &f64_desc); arg_node = scc_ast2ir_emit_conversion(ctx, arg_node, f64_ref); } // 指针、i32/i64 等保持不变 } scc_vec_push(args, arg_node); } // 创建调用节点(需要查找函数定义) if (!callee_func) { LOG_ERROR("Function %s not found", expr->call.callee->identifier._target->name); } scc_hir_value_ref_t node = scc_hir_builder_call( &ctx->builder, callee_func, args.data, args.size); scc_vec_free(args); return node; } case SCC_AST_EXPR_ARRAY_SUBSCRIPT: { // 1. 计算数组/指针基址(右值,得到地址) scc_hir_value_ref_t base_ptr = scc_ast2ir_expr(ctx, expr->subscript.array, true); // 2. 计算下标值 scc_hir_value_ref_t index = scc_ast2ir_expr(ctx, expr->subscript.index, false); // 保证 index 至少 64 位,防止后端寄存器分配时宽度错误 scc_hir_type_t *idx_type = scc_hir_module_get_type_by_value(scc_ast2ir_mir_module(ctx), index); if (idx_type != nullptr && scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), idx_type) < sizeof(void *)) { scc_hir_type_t ptrw_desc; scc_hir_type_init(&ptrw_desc, SCC_HIR_TYPE_u64); scc_hir_type_ref_t ptrw_ref = scc_hir_builder_type(&ctx->builder, &ptrw_desc); index = scc_ast2ir_emit_conversion(ctx, index, ptrw_ref); } // 3. 生成 getptr(GEP) scc_hir_value_ref_t elem_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, index); // 4. 根据左值/右值返回 if (is_lvalue) { return elem_ptr; // 作为左值:返回地址 } else { return scc_hir_builder_load(&ctx->builder, elem_ptr); // 作为右值:加载值 } } case SCC_AST_EXPR_MEMBER: { // 1. 获取基对象的左值(地址) scc_hir_value_ref_t base_ptr = scc_ast2ir_expr(ctx, expr->member.base, true); // 2. 通过偏移生成字段地址 // 需要基对象类型来计算索引:假设 sema 填好了 _target_idx usize field_idx = expr->member._target_idx; scc_ap_t idx_ap; scc_ap_set_int(&idx_ap, field_idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); scc_hir_value_ref_t field_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, idx_val); if (is_lvalue) return field_ptr; else return scc_hir_builder_load(&ctx->builder, field_ptr); } case SCC_AST_EXPR_PTR_MEMBER: { // 1. 计算指针值(obj->field 等价于 (*obj).field) scc_hir_value_ref_t obj_ptr = scc_ast2ir_expr(ctx, expr->member.base, false); // 2. 解引用得到对象地址,再访问成员 // 但更简单:先 load 出对象值?不对:obj // 是指向结构体的指针,我们需要指针的地址? 实际上,obj->field 相当于 // (*(obj)).field,所以可以直接用 obj 作为基地址进行 get_elem_ptr // 因为 get_elem_ptr 接收一个指针,obj 本身就是指向结构体的指针。 usize field_idx = expr->member._target_idx; scc_ap_t idx_ap; scc_ap_set_int(&idx_ap, field_idx); scc_hir_value_ref_t idx_val = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap); scc_hir_value_ref_t field_ptr = scc_hir_builder_get_elem_ptr(&ctx->builder, obj_ptr, idx_val); if (is_lvalue) return field_ptr; else return scc_hir_builder_load(&ctx->builder, field_ptr); } case SCC_AST_EXPR_CAST: { // 1. 转换操作数(右值) scc_hir_value_ref_t operand = scc_ast2ir_expr(ctx, expr->cast.expr, false); // 2. 转换目标类型为 IR 类型 scc_hir_type_ref_t target_type = scc_ast2ir_type(ctx, expr->cast.type); // 3. 确定转换模式(SEXT / ZEXT / TRUNC) // 这里用简单的启发式:根据大小变化决定 scc_hir_type_t *src_type = scc_hir_module_get_type_by_value( scc_ast2ir_mir_module(ctx), operand); scc_hir_type_t *dst_type = scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), target_type); usize src_size = scc_hir_module_type_size( scc_ast2ir_mir_module(ctx), src_type); // 你可能有这个函数,否则自行计算 usize dst_size = scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), dst_type); int conv_kind; if (dst_size > src_size) { // 目标更大,需要扩展。根据源类型有无符号决定符号扩展还是零扩展 conv_kind = scc_hir_type_is_signed(src_type->tag) ? SCC_HIR_CONV_SEXT : SCC_HIR_CONV_ZEXT; } else if (dst_size < src_size) { conv_kind = SCC_HIR_CONV_TRUNC; } else { // 同大小,可以视为 NOP 转换,或者直接返回操作数 return operand; // 或创建一个 CONV_SEXT 也没问题 } // 4. 构造转换节点 scc_hir_value_t conv_node = { .tag = SCC_HIR_VALUE_TAG_CONV, .type = target_type, .data.conv.operand = operand, .data.conv.target_type = target_type, .data.conv.conv_type = conv_kind, }; return scc_hir_module_add_value(scc_ast2ir_mir_module(ctx), &conv_node); } case SCC_AST_EXPR_SIZE_OF: { // 1. 将 sizeof 的操作数(类型或表达式)转换为 IR 类型 scc_hir_type_ref_t hir_type; if (expr->attr_of.type) { // sizeof(type) hir_type = scc_ast2ir_type(ctx, expr->attr_of.type); } else if (expr->attr_of.expr) { // sizeof expression:计算表达式类型 // 注意:sizeof // 不对表达式求值,只需类型,这里假设语义分析已经标注了类型 scc_hir_value_ref_t dummy = scc_ast2ir_expr(ctx, expr->attr_of.expr, false); hir_type = scc_hir_module_get_value(scc_ast2ir_mir_module(ctx), dummy) ->type; } else { scc_ap_t val; val.data.digit = 0; LOG_ERROR("[ast2ir] unsupported"); return scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &val); } // 2. 计算大小 const scc_hir_type_t *type = scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), hir_type); usize dst_size = scc_hir_module_type_size(scc_ast2ir_mir_module(ctx), type); scc_ap_t val; val.data.digit = dst_size; return scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &val); } case SCC_AST_EXPR_ALIGN_OF: { TODO(); // return scc_hir_builder_integer( // &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); } case SCC_AST_EXPR_COMPOUND: { // 1. 从 base 子节点取得类型(base 一定是 SCC_AST_EXPR_LVALUE) Assert(expr->compound.base != nullptr); Assert(expr->compound.base->base.type == SCC_AST_EXPR_LVALUE); scc_ast_qual_type_t *ast_type = expr->compound.base->lvalue.type; scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, ast_type); const scc_hir_type_t *type = scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), type_ref); // 2. 分配栈上临时存储 scc_hir_value_ref_t storage = scc_hir_builder_alloca(&ctx->builder, type_ref, "compound_literal"); // 3. 根据类型调用对应的初始化函数 if (type->tag == SCC_HIR_TYPE_ARRAY) { emit_array_initialization(ctx, storage, type, expr); } else if (type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION) { emit_aggregate_initialization(ctx, storage, type, expr); } else { // 标量:取初始化列表的第一个值 Assert(expr->compound.rhs_exprs.size > 0); scc_ast_expr_t *init_expr = scc_vec_at(expr->compound.rhs_exprs, 0); scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, init_expr, false); scc_hir_builder_store(&ctx->builder, storage, val); } // 4. 根据左值 / 右值返回 if (is_lvalue) { return storage; // 左值 } else { // 右值:数组退化为首元素指针,结构体暂时返回地址 if (type->tag == SCC_HIR_TYPE_ARRAY) { return scc_hir_builder_get_elem_ptr(&ctx->builder, storage, SCC_HIR_REF_nullptr); } else if (type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION) { return storage; // 调用者会 memcpy } else { return scc_hir_builder_load(&ctx->builder, storage); } } } break; case SCC_AST_EXPR_LVALUE: { UNREACHABLE(); // should only appear as compound.base } break; case SCC_AST_EXPR_BUILTIN: { TODO(); } break; case SCC_AST_EXPR_INT_LITERAL: { // FIXME maybe using some array to int; scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_t value; scc_ap_from_cstr(&value, expr->literal.lexme, 10); return scc_hir_builder_integer(&ctx->builder, type_ref, &value); } // SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量 case SCC_AST_EXPR_CHAR_LITERAL: { // FIXME just 'a' '\n' const char *lexme = expr->literal.lexme; Assert(lexme[0] == '\''); i8 int_lit = 0; if (lexme[1] == '\\') { switch (lexme[2]) { case 'a': int_lit = '\a'; break; case 'b': int_lit = '\b'; break; case 'f': int_lit = '\f'; break; case 'n': int_lit = '\n'; break; case 'r': int_lit = '\r'; } } else { int_lit = lexme[1]; } scc_ap_t value; // FIXME i32 maybe false, we need i8 or u8 scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); scc_ap_set_int(&value, int_lit); return scc_hir_builder_integer(&ctx->builder, type_ref, &value); } case SCC_AST_EXPR_STRING_LITERAL: { // FIXME scc_hir_value_ref_t value = scc_hir_builder_const_string(&ctx->builder, expr->literal.lexme, scc_strlen(expr->literal.lexme)); if (is_lvalue) TODO(); return value; } case SCC_AST_EXPR_IDENTIFIER: { if (expr->identifier._target == nullptr) { LOG_ERROR("unknown identifier %s", expr->identifier.name); } // FIXME hack hashtable scc_hir_value_ref_t in = (scc_hir_value_ref_t)(usize)scc_hashtable_get( &ctx->ast2ir_cache, expr->identifier._target); Assert(in != 0); if (is_lvalue) { return in; } else { // 右值:如果是数组类型,退化为指针(返回地址) scc_hir_type_t *ir_type = scc_hir_module_get_type_by_value( scc_ast2ir_mir_module(ctx), in); if (ir_type->tag == SCC_HIR_TYPE_PTR) { scc_hir_type_t *target_type = scc_hir_module_get_type( scc_ast2ir_mir_module(ctx), ir_type->data.pointer.base); if (target_type->tag == SCC_HIR_TYPE_ARRAY) { // 生成 getptr 获取数组首地址 return scc_hir_builder_get_elem_ptr(&ctx->builder, in, SCC_HIR_REF_nullptr); } else { // 标量类型:加载值 return scc_hir_builder_load(&ctx->builder, in); } } else { return in; } } } default: LOG_FATAL("Unsupported expression type: %d", expr->base.type); return 0; } UNREACHABLE(); } /** * @brief * * @param ctx * @param stmt */ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { if (stmt == nullptr) { return; } switch (stmt->base.type) { case SCC_AST_STMT_COMPOUND: { scc_vec_foreach(stmt->compound.block_items, i) { scc_ast_node_t *child_stmt = scc_vec_at(stmt->compound.block_items, i); if (SCC_AST_IS_A(scc_ast_stmt_t, child_stmt)) { scc_ast2ir_stmt(ctx, SCC_AST_CAST_TO(scc_ast_stmt_t, child_stmt)); } else if (SCC_AST_IS_A(scc_ast_decl_t, child_stmt)) { scc_ast2ir_decl( ctx, SCC_AST_CAST_TO(scc_ast_decl_t, child_stmt), false); } else { UNREACHABLE(); } } break; } case SCC_AST_STMT_EXPR: { scc_ast2ir_expr(ctx, stmt->expr.expr, false); break; } case SCC_AST_STMT_IF: { /* branch cond / \ true_block false_block \ / merge_block */ scc_hir_value_ref_t true_block = scc_hir_builder_create_bblock(&ctx->builder, "if_true"); scc_hir_value_ref_t false_block = scc_hir_builder_create_bblock(&ctx->builder, "if_false"); scc_hir_value_ref_t merge_block = scc_hir_builder_create_bblock(&ctx->builder, "if_merge"); scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->if_stmt.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, true_block, stmt->if_stmt.opt_else_stmt ? false_block : merge_block); // 生成true分支 scc_hir_builder_append_bblock(&ctx->builder, true_block); scc_hir_builder_set_current_bblock(&ctx->builder, true_block); scc_ast2ir_stmt(ctx, stmt->if_stmt.then_stmt); scc_hir_builder_jump(&ctx->builder, merge_block); // 生成false分支 if (stmt->if_stmt.opt_else_stmt) { scc_hir_builder_append_bblock(&ctx->builder, false_block); scc_hir_builder_set_current_bblock(&ctx->builder, false_block); scc_ast2ir_stmt(ctx, stmt->if_stmt.opt_else_stmt); scc_hir_builder_jump(&ctx->builder, merge_block); } scc_hir_builder_append_bblock(&ctx->builder, merge_block); scc_hir_builder_set_current_bblock(&ctx->builder, merge_block); break; } case SCC_AST_STMT_WHILE: { scc_hir_value_ref_t cond_block = scc_hir_builder_create_bblock(&ctx->builder, "while_cond"); scc_hir_value_ref_t body_block = scc_hir_builder_create_bblock(&ctx->builder, "while_body"); scc_hir_value_ref_t exit_block = scc_hir_builder_create_bblock(&ctx->builder, "while_exit"); scc_hashtable_set(&ctx->break_cache, stmt, (void *)exit_block); scc_hashtable_set(&ctx->continue_cache, stmt, (void *)cond_block); scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_append_bblock(&ctx->builder, cond_block); scc_hir_builder_set_current_bblock(&ctx->builder, cond_block); scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->while_stmt.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); scc_hir_builder_append_bblock(&ctx->builder, body_block); scc_hir_builder_set_current_bblock(&ctx->builder, body_block); scc_ast2ir_stmt(ctx, stmt->while_stmt.body); scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_append_bblock(&ctx->builder, exit_block); scc_hir_builder_set_current_bblock(&ctx->builder, exit_block); break; } case SCC_AST_STMT_DO_WHILE: { scc_hir_value_ref_t cond_block = scc_hir_builder_create_bblock(&ctx->builder, "do_while_cond"); scc_hir_value_ref_t body_block = scc_hir_builder_create_bblock(&ctx->builder, "do_while_body"); scc_hir_value_ref_t exit_block = scc_hir_builder_create_bblock(&ctx->builder, "do_while_exit"); scc_hashtable_set(&ctx->break_cache, stmt, (void *)exit_block); scc_hashtable_set(&ctx->continue_cache, stmt, (void *)cond_block); scc_hir_builder_jump(&ctx->builder, body_block); scc_hir_builder_append_bblock(&ctx->builder, body_block); scc_hir_builder_set_current_bblock(&ctx->builder, body_block); scc_ast2ir_stmt(ctx, stmt->while_stmt.body); scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_append_bblock(&ctx->builder, cond_block); scc_hir_builder_set_current_bblock(&ctx->builder, cond_block); scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->while_stmt.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); scc_hir_builder_append_bblock(&ctx->builder, exit_block); scc_hir_builder_set_current_bblock(&ctx->builder, exit_block); break; } case SCC_AST_STMT_FOR: { scc_hir_value_ref_t cond_block = scc_hir_builder_create_bblock(&ctx->builder, "for_cond"); scc_hir_value_ref_t body_block = scc_hir_builder_create_bblock(&ctx->builder, "for_body"); scc_hir_value_ref_t incr_block = scc_hir_builder_create_bblock(&ctx->builder, "for_incr"); scc_hir_value_ref_t exit_block = scc_hir_builder_create_bblock(&ctx->builder, "for_exit"); scc_hashtable_set(&ctx->break_cache, stmt, (void *)exit_block); scc_hashtable_set(&ctx->continue_cache, stmt, (void *)incr_block); if (stmt->for_stmt.init) { if (SCC_AST_IS_A(scc_ast_decl_t, stmt->for_stmt.init)) { scc_ast2ir_decl( ctx, SCC_AST_CAST_TO(scc_ast_decl_t, stmt->for_stmt.init), false); } else if (SCC_AST_IS_A(scc_ast_expr_t, stmt->for_stmt.init)) { scc_ast2ir_expr( ctx, SCC_AST_CAST_TO(scc_ast_expr_t, stmt->for_stmt.init), false); } else { LOG_FATAL("invalid for init statement"); } } scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_append_bblock(&ctx->builder, cond_block); scc_hir_builder_set_current_bblock(&ctx->builder, cond_block); if (stmt->for_stmt.cond) { scc_hir_value_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->for_stmt.cond, false); scc_hir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); } else { scc_hir_builder_jump(&ctx->builder, body_block); } scc_hir_builder_append_bblock(&ctx->builder, body_block); scc_hir_builder_set_current_bblock(&ctx->builder, body_block); scc_ast2ir_stmt(ctx, stmt->for_stmt.body); scc_hir_builder_jump(&ctx->builder, incr_block); scc_hir_builder_append_bblock(&ctx->builder, incr_block); scc_hir_builder_set_current_bblock(&ctx->builder, incr_block); if (stmt->for_stmt.incr) { scc_ast2ir_expr(ctx, stmt->for_stmt.incr, false); } scc_hir_builder_jump(&ctx->builder, cond_block); scc_hir_builder_append_bblock(&ctx->builder, exit_block); scc_hir_builder_set_current_bblock(&ctx->builder, exit_block); break; } case SCC_AST_STMT_SWITCH: { scc_hir_value_ref_t exit_block = scc_hir_builder_bblock(&ctx->builder, "switch_exit"); scc_hashtable_set(&ctx->break_cache, stmt, (void *)exit_block); // TODO: } break; case SCC_AST_STMT_CASE: case SCC_AST_STMT_DEFAULT: UNREACHABLE(); break; case SCC_AST_STMT_BREAK: { scc_hir_bblock_ref_t target = (usize)scc_hashtable_get(&ctx->break_cache, stmt->jump._target); Assert(target != SCC_HIR_REF_nullptr); scc_hir_builder_jump(&ctx->builder, target); } break; case SCC_AST_STMT_CONTINUE: { scc_hir_bblock_ref_t target = (usize)scc_hashtable_get(&ctx->continue_cache, stmt->jump._target); Assert(target != SCC_HIR_REF_nullptr); scc_hir_builder_jump(&ctx->builder, target); } break; case SCC_AST_STMT_RETURN: { if (stmt->return_stmt.expr) { scc_hir_value_ref_t ret_val_node = scc_ast2ir_expr(ctx, stmt->return_stmt.expr, false); // 将返回值转换为函数返回值类型 scc_hir_func_ref_t func = ctx->builder.current_func; if (func != SCC_HIR_REF_nullptr) { scc_hir_func_t *hir_func = scc_hir_module_get_func(scc_ast2ir_mir_module(ctx), func); scc_hir_func_meta_t *meta = SCC_HIR_FUNC_META(hir_func); if (meta->type != SCC_HIR_REF_nullptr) { const scc_hir_type_t *func_type = scc_hir_module_get_type( scc_ast2ir_mir_module(ctx), meta->type); if (func_type != nullptr && func_type->tag == SCC_HIR_TYPE_FUNC) { ret_val_node = scc_ast2ir_emit_conversion( ctx, ret_val_node, func_type->data.function.ret_type); } } } scc_hir_builder_ret(&ctx->builder, ret_val_node); } else { scc_hir_builder_ret_void(&ctx->builder); } break; } case SCC_AST_STMT_GOTO: { // scc_hir_bblock_ref_t target = (usize)scc_hashtable_get( // &ctx->ast2ir_cache, (void *)stmt->goto_stmt._target); // Assert(target != SCC_HIR_REF_nullptr); // scc_hir_builder_jump(&ctx->builder, target); } break; case SCC_AST_STMT_LABEL: { scc_hir_value_ref_t label_block = scc_hir_builder_bblock(&ctx->builder, stmt->label_stmt.label); scc_hir_builder_set_current_bblock(&ctx->builder, label_block); scc_hashtable_set(&ctx->ast2ir_cache, stmt, (void *)label_block); scc_ast2ir_stmt(ctx, stmt->label_stmt.stmt); } break; default: LOG_FATAL("Unsupported statement type: %d", stmt->base.type); break; } } /** * @brief * * @param ctx * @param decl */ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, cbool is_global) { if (ctx == nullptr || decl == nullptr) { LOG_ERROR("Invalid argument"); return; } switch (decl->base.type) { case SCC_AST_DECL_VAR: { // 1. 获取原始类型(可能数组长度为0) scc_hir_type_ref_t orig_type_ref = scc_ast2ir_type(ctx, decl->var.type); // 借用指针并拷贝类型(避免悬空) const scc_hir_type_t *orig_type; SCC_HIR_BUILDER_BEGIN_BORROW( &ctx->builder, orig_type, scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), orig_type_ref)); scc_hir_type_t final_type_desc = *orig_type; SCC_HIR_BUILDER_END_BORROW(&ctx->builder); // 2. 如果是未知长度数组且有初始化,解析实际长度 scc_hir_type_ref_t final_type_ref = orig_type_ref; if (decl->var.init && final_type_desc.tag == SCC_HIR_TYPE_ARRAY && final_type_desc.data.array.len == 0) { scc_hir_type_t tmp_type_desc; resolve_array_length(ctx, &final_type_desc, &tmp_type_desc, decl->var.init); final_type_desc = tmp_type_desc; final_type_ref = scc_hir_builder_type(&ctx->builder, &final_type_desc); // 此时 final_type_desc 中的长度已经确定 } // 3. 分配变量(栈或全局) scc_hir_value_ref_t alloc_val_node; if (is_global) { // 全局变量:需要生成全局分配,当前代码暂未实现,保留 TODO // alloc_val_node = scc_hir_builder_global_alloca(&ctx->builder, // final_type_ref, decl->name); // scc_vec_push(builder->cprog->global_vals, alloc_val_node); // 这里先返回,后续补充 return; } else { alloc_val_node = scc_hir_builder_alloca(&ctx->builder, final_type_ref, decl->name); } scc_hashtable_set(&ctx->ast2ir_cache, decl, (void *)(usize)alloc_val_node); // 4. 处理初始化 if (decl->var.init) { // 再次借用 final_type 以判断是否为数组 const scc_hir_type_t *final_type; SCC_HIR_BUILDER_BEGIN_BORROW( &ctx->builder, final_type, scc_hir_module_get_type(scc_ast2ir_mir_module(ctx), final_type_ref)); scc_hir_type_t type = *final_type; SCC_HIR_BUILDER_END_BORROW(&ctx->builder); if (type.tag == SCC_HIR_TYPE_ARRAY) { emit_array_initialization(ctx, alloc_val_node, &type, decl->var.init); } else if (type.tag == SCC_HIR_TYPE_STRUCT || type.tag == SCC_HIR_TYPE_UNION) { emit_aggregate_initialization(ctx, alloc_val_node, &type, decl->var.init); } else { // 标量类型 scc_hir_value_ref_t init_val = scc_ast2ir_expr(ctx, decl->var.init, false); scc_hir_builder_store(&ctx->builder, alloc_val_node, init_val); } } break; } case SCC_AST_DECL_FUNC: { scc_hir_type_ref_t func_type_ref = scc_ast2ir_type(ctx, decl->func.type); scc_hir_func_ref_t func_ref = (usize)scc_hashtable_get(&ctx->symtab, decl->name); if (func_ref == SCC_HIR_REF_nullptr) { func_ref = scc_hir_builder_func(&ctx->builder, func_type_ref, decl->name); // TODO: add func to cache because function pointer is needed scc_hashtable_set(&ctx->symtab, decl->name, (void *)(usize)func_ref); } // 检测是否是可变参数函数(无论是否有函数体) scc_hir_func_t *hir_func = scc_hir_module_get_func(&ctx->builder.cprog->module, func_ref); int n_fixed = fixed_param_count(scc_ast_canon_type(decl->func.type)); int n_total = (int)scc_vec_size( scc_ast_canon_type(decl->func.type)->function.params); if (n_total > n_fixed) { SCC_HIR_FUNC_META(hir_func)->is_variadic = true; } if (decl->func.body == nullptr) { // function decl break; } // TODO this is double check defined Assert(SCC_HIR_FUNC_META(hir_func)->defined == false); SCC_HIR_FUNC_META(hir_func)->defined = true; scc_hir_builder_begin_func(&ctx->builder, func_ref); scc_hir_builder_begin_bblock(&ctx->builder, "entry"); // 只处理固定参数,跳过尾部的 ... 假参数 scc_ast_decl_vec_t *ast_params = &scc_ast_canon_type(decl->func.type)->function.params; for (int i = 0; i < n_fixed; i++) { scc_ast_decl_t *param = scc_vec_at(*ast_params, i); scc_ast2ir_decl(ctx, param, false); } scc_ast2ir_stmt(ctx, decl->func.body); // FIXME need ret for none return or other default ret scc_hir_builder_ret_void(&ctx->builder); scc_hir_builder_end_bblock(&ctx->builder); scc_hir_builder_end_func(&ctx->builder); break; } case SCC_AST_DECL_LIST: { scc_vec_foreach(decl->list.vars, i) { scc_ast_decl_t *sub_decl = scc_vec_at(decl->list.vars, i); scc_ast2ir_decl(ctx, sub_decl, is_global); } break; } case SCC_AST_DECL_PARAM: { // 跳过 void 参数和 ... 假参数(无名 VA_LIST) if (decl->param.type->base.type == SCC_AST_TYPE_BUILTIN && scc_ast_canon_type(decl->param.type)->builtin.type == SCC_AST_BUILTIN_TYPE_VOID) { break; } if (is_variadic_marker(decl)) { break; } scc_hir_type_ref_t parma_type_ref = scc_ast2ir_type(ctx, decl->param.type); scc_hir_value_ref_t param_ref = scc_hir_builder_func_arg_ref( &ctx->builder, parma_type_ref, decl->name, decl->param.param_idx); if (!ctx->hint_using_value) { scc_hir_value_ref_t val_ref = scc_hir_builder_alloca( &ctx->builder, parma_type_ref, decl->name); scc_hir_builder_store(&ctx->builder, val_ref, param_ref); scc_hashtable_set(&ctx->ast2ir_cache, decl, (void *)(usize)val_ref); } else { Panic("using value is not supported"); } break; } case SCC_AST_DECL_STRUCT: case SCC_AST_DECL_UNION: { scc_ast_canon_type_t canon_type = { .record.decl = decl, .record.name = decl->name, }; scc_ast_qual_type_t type = { .base.type = SCC_AST_DECL_STRUCT ? SCC_AST_TYPE_STRUCT : SCC_AST_TYPE_UNION, .type = &canon_type, }; scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, &type); // scc_hir_builder_global_alloca(&ctx->builder, type_ref, // SCC_HIR_REF_nullptr); } break; case SCC_AST_DECL_ENUM: { scc_ap_t val; int idx = 0; scc_ap_set_int(&val, idx); scc_vec_foreach(decl->record.fields, i) { scc_ast_decl_t *item = scc_vec_at(decl->record.fields, i); Assert(item->base.type == SCC_AST_DECL_VAR); if (item->var.init) { Assert(item->var.init->base.type == SCC_AST_EXPR_INT_LITERAL); scc_ap_from_cstr(&val, item->var.init->literal.lexme, 10); } scc_hir_value_ref_t item_val_ref = scc_hir_builder_integer( &ctx->builder, scc_hir_builder_type_i32(&ctx->builder), &val); scc_hashtable_set(&ctx->ast2ir_cache, item, (void *)(usize)item_val_ref); // FIXME hack ap idx = val.data.digit; idx += 1; // scc_ap_add 1 (); scc_ap_set_int(&val, idx); } } break; case SCC_AST_DECL_TYPEDEF: break; default: LOG_FATAL("Unsupported declaration type: %d", decl->base.type); break; } } void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx, const scc_ast_translation_unit_t *tu) { Assert(ctx != nullptr && tu != nullptr); scc_vec_foreach(tu->declarations, i) { scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i); scc_ast2ir_decl(ctx, decl, true); } } void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, scc_ast_ctx_t *ast_ctx, scc_hir_cprog_t *cprog) { Assert(ctx != nullptr); Assert(abi != nullptr); Assert(ast_ctx != nullptr); Assert(cprog != nullptr); ctx->abi = abi; ctx->ast_ctx = ast_ctx; scc_hir_builder_init(&ctx->builder, cprog); scc_hashtable_usize_init(&ctx->ast2ir_cache); scc_hashtable_usize_init(&ctx->break_cache); scc_hashtable_usize_init(&ctx->continue_cache); scc_hashtable_cstr_init(&ctx->symtab); scc_hashtable_usize_init(&ctx->type_cache); ctx->hint_using_value = false; } void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) { scc_hir_builder_drop(&ctx->builder); scc_hashtable_drop(&ctx->ast2ir_cache); scc_hashtable_drop(&ctx->break_cache); scc_hashtable_drop(&ctx->continue_cache); scc_hashtable_drop(&ctx->type_cache); scc_hashtable_drop(&ctx->symtab); }