From 2c13ac54df78de2b9727dbd4206e5a613529f027 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Tue, 19 May 2026 17:35:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(ast2ir):=20=E6=B7=BB=E5=8A=A0=E6=B5=AE?= =?UTF-8?q?=E7=82=B9=E7=B1=BB=E5=9E=8B=E6=94=AF=E6=8C=81=E5=92=8C=E5=A4=8D?= =?UTF-8?q?=E5=90=88=E5=88=9D=E5=A7=8B=E5=8C=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在ABI类型计算中添加FLOAT和DOUBLE类型的映射 - 修复AST操作符注释中的歧义描述 - 为ast2ir上下文添加类型缓存以解决递归结构体定义问题 - 实现复合初始化表达式的支持,包括数组和结构体初始化 - 添加前置和后置自增/自减操作符的IR转换 - 实现三元条件表达式的IR生成 - 添加类型转换(cast)和sizeof操作符的支持 - 重构数组长度推断逻辑并添加类型大小计算函数 - 实现结构体和联合体的递归类型解析 - 添加函数指针调用相关的IR节点类型定义 fix(ast): 修正间接操作符的注释说明 refactor(ast2ir): 优化代码结构并添加必要的断言验证 --- libs/abi/src/scc_type_abi.c | 6 + libs/ast/include/scc_ast_def.h | 2 +- libs/ast2ir/include/scc_ast2ir.h | 1 + libs/ast2ir/src/scc_ast2ir.c | 538 +++++++++++++++++++--- libs/ir/hir/include/scc_hir_builder.h | 7 +- libs/ir/hir/include/scc_hir_def.h | 10 +- libs/ir/hir/src/scc_hir.c | 2 +- libs/ir/hir/src/scc_hir_builder.c | 2 +- libs/ir/hir/src/scc_hir_dump.c | 184 +++++--- libs/ir/lir/src/scc_hir2lir.c | 4 +- libs/parser/include/scc_sema.h | 8 + libs/parser/src/parse_decl.c | 10 +- libs/parser/src/scc_parser.c | 1 + libs/parser/src/scc_sema.c | 95 +++- libs/pproc/src/pproc_include.c | 2 +- runtime/ap/include/ap.h | 2 +- runtime/log/include/log.h | 4 +- runtime/scc_core/include/scc_core_macro.h | 10 + runtime/scc_core/include/scc_core_vec.h | 85 ++++ runtime/scc_core/src/core_impl.c | 11 +- src/config.c | 1 - 21 files changed, 808 insertions(+), 177 deletions(-) diff --git a/libs/abi/src/scc_type_abi.c b/libs/abi/src/scc_type_abi.c index 949e1af..a46efea 100644 --- a/libs/abi/src/scc_type_abi.c +++ b/libs/abi/src/scc_type_abi.c @@ -61,6 +61,12 @@ void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type, case SCC_AST_BUILTIN_TYPE_UNSIGNED_LONG_LONG: kind = SCC_ABI_TYPE_U_LONG_LONG; break; + case SCC_AST_BUILTIN_TYPE_FLOAT: + kind = SCC_ABI_TYPE_FLOAT; + break; + case SCC_AST_BUILTIN_TYPE_DOUBLE: + kind = SCC_ABI_TYPE_DOUBLE; + break; default: Panic("Unsupported AST type: %d", scc_ast_canon_type(ast_type)->builtin.type); diff --git a/libs/ast/include/scc_ast_def.h b/libs/ast/include/scc_ast_def.h index c2a73f8..ebf0272 100644 --- a/libs/ast/include/scc_ast_def.h +++ b/libs/ast/include/scc_ast_def.h @@ -262,7 +262,7 @@ typedef enum scc_ast_expr_op { SCC_AST_OP_UNARY_PLUS, // + (一元) SCC_AST_OP_UNARY_MINUS, // - (一元) SCC_AST_OP_ADDRESS_OF, // & - SCC_AST_OP_INDIRECTION, // * + SCC_AST_OP_INDIRECTION, // * (取地址) SCC_AST_OP_BITWISE_NOT, // ~ SCC_AST_OP_LOGICAL_NOT, // ! SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀) diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index ec6ac75..bb2c9f5 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -11,6 +11,7 @@ typedef struct { scc_hashtable_t break_cache; ///< break cache scc_hashtable_t continue_cache; ///< continue cache scc_hashtable_t symtab; ///< symbol to ir_ref + scc_hashtable_t type_cache; ///< scc_ast_canon_type_t* -> scc_hir_type_ref_t // scc_strpool_t strpool; ///< string pool const scc_abi_type_calc_t *abi; cbool hint_using_value; // 转换时尽可能使用value而不是alloc diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index 5ebd108..01b31ef 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -27,39 +27,24 @@ static scc_hir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx, return SCC_HIR_REF_nullptr; } -// 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; - } +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: - Panic("unsupported initializer for zero-length array"); + // 指针可以视作无符号整数 + return false; } - resolved_array_type->data.array.len = new_len; } // 辅助函数:生成数组初始化代码 @@ -123,6 +108,142 @@ static void emit_array_initialization(scc_ast2ir_ctx_t *ctx, // 这里简单忽略,实际可生成 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( + &ctx->builder.cprog->module, 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) {} + +usize scc_hir_type_size(scc_ast2ir_ctx_t *ctx, const scc_hir_type_t *type) { + switch (type->tag) { + case SCC_HIR_TYPE_void: + return 0; + case SCC_HIR_TYPE_i8: + return 1; + case SCC_HIR_TYPE_i16: + return 2; + case SCC_HIR_TYPE_i32: + return 4; + case SCC_HIR_TYPE_i64: + return 8; + case SCC_HIR_TYPE_i128: + return 16; + case SCC_HIR_TYPE_u8: + return 1; + case SCC_HIR_TYPE_u16: + return 2; + case SCC_HIR_TYPE_u32: + return 4; + case SCC_HIR_TYPE_u64: + return 8; + case SCC_HIR_TYPE_u128: + return 16; + case SCC_HIR_TYPE_f16: + return 2; + case SCC_HIR_TYPE_f32: + return 4; + case SCC_HIR_TYPE_f64: + return 8; + case SCC_HIR_TYPE_f128: + return 16; + + case SCC_HIR_TYPE_PTR: { + // 目标指针大小,可以定义为 8(64位)或从 ABI 获取 + // 假设你的目标架构是 64 位 + return 8; + } + + case SCC_HIR_TYPE_ARRAY: { + usize elem_size = scc_hir_type_size( + ctx, scc_hir_module_get_type(&ctx->builder.cprog->module, + type->data.array.base)); + return elem_size * type->data.array.len; + } + + case SCC_HIR_TYPE_FUNC: + // 函数类型大小一般是指针大小 + return 8; + + case SCC_HIR_TYPE_STRUCT: + case SCC_HIR_TYPE_UNION: + // 暂时无法计算,保守返回 0 或报错 + LOG_ERROR("Cannot compute size of struct/union without layout info"); + return 0; + + default: + LOG_ERROR("Unknown type tag %d", type->tag); + return 0; + } +} + +// 辅助函数:计算数组实际长度(如果原长度为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) { @@ -189,22 +310,64 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, } break; case SCC_AST_TYPE_STRUCT: case SCC_AST_TYPE_UNION: { - scc_hir_type_init(&ir_type, ast_type->base.type == SCC_AST_TYPE_STRUCT - ? SCC_HIR_TYPE_STRUCT - : SCC_HIR_TYPE_UNION); - if (scc_ast_canon_type(ast_type)->record.decl == nullptr) { - Panic("%s record fields is nullptr", - scc_ast_canon_type(ast_type)->record.name); + 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; } - scc_vec_foreach( - scc_ast_canon_type(ast_type)->record.decl->record.fields, i) { - scc_ast_decl_t *decl_field = scc_vec_at( - scc_ast_canon_type(ast_type)->record.decl->record.fields, i); - Assert(decl_field->base.type == SCC_AST_DECL_VAR); - scc_hir_type_ref_t field_type = - scc_ast2ir_type(ctx, decl_field->var.type); - scc_vec_push(ir_type.data.aggregate.fields, field_type); + + // === 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(&ctx->builder.cprog->module, &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(&ctx->builder.cprog->module, 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( @@ -337,7 +500,8 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, switch (expr->base.type) { case SCC_AST_EXPR_BINARY: { scc_ast_expr_t tmp_expr; - scc_hir_value_ref_t lhs, rhs; + 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); @@ -407,6 +571,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, break; } if (is_assign) { + Assert(rhs != SCC_HIR_REF_nullptr); lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, true); return scc_hir_builder_store(&ctx->builder, lhs, rhs); } @@ -452,7 +617,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, } // 创建操作节点 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); @@ -470,17 +635,6 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, } scc_hir_value_ref_t operand = scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue); - // /* 一元操作符 */ - // SCC_AST_OP_UNARY_PLUS, // + (一元) - // SCC_AST_OP_UNARY_MINUS, // - (一元) - // SCC_AST_OP_ADDRESS_OF, // & - // SCC_AST_OP_INDIRECTION, // * - // SCC_AST_OP_BITWISE_NOT, // ~ - // SCC_AST_OP_LOGICAL_NOT, // ! - // SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀) - // SCC_AST_OP_PREFIX_DECREMENT, // -- (前缀) - // SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀) - // SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀) switch (expr->unary.op) { case SCC_AST_OP_UNARY_PLUS: /* just pass */ @@ -517,17 +671,138 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, 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; + scc_hir_type_ref_t promoted_type = old_type; + // scc_ast2ir_promoted_type(ctx, old_type); + scc_hir_value_ref_t promoted = old_val; + // scc_ast2ir_apply_promotion(ctx, old_val); + + scc_hir_value_ref_t one = scc_hir_builder_integer( + &ctx->builder, scc_hir_builder_type_i32(&ctx->builder), + &(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 (old_type != promoted_type) { + // stored_val = scc_hir_builder_conv(&ctx->builder, new_val, + // old_type, CONV_TRUNC); + // } + 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; + scc_hir_type_ref_t promoted_type = old_type; + // scc_ast2ir_promoted_type(ctx, old_type); + scc_hir_value_ref_t promoted = old_val; + // scc_ast2ir_apply_promotion(ctx, old_val); + + scc_hir_value_ref_t one = scc_hir_builder_integer( + &ctx->builder, scc_hir_builder_type_i32(&ctx->builder), + &(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 (old_type != promoted_type) + // stored_val = trunc; + scc_hir_builder_store(&ctx->builder, addr, stored_val); + + // 后缀返回旧的、未提升的值(但 C + // 要求返回提升后的旧值?实际是旧值按右值规则,应得到提升后的值) + // 标准规定后缀++的结果是操作数原来的值,但会经过整数提升。 + // 所以需要返回 promoted(已提升的旧值)。 + Assert(promoted != SCC_HIR_REF_nullptr); + return promoted; // 旧值,但类型已提升为 + // int 等 + } break; default: LOG_FATAL("Unsupported unary operator: %d", expr->unary.op); return 0; } UNREACHABLE(); - break; - } + } break; case SCC_AST_EXPR_COND: { - TODO(); - break; - } + 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; @@ -610,12 +885,79 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, return scc_hir_builder_load(&ctx->builder, field_ptr); } case SCC_AST_EXPR_CAST: { - TODO(); - } break; + // 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( + &ctx->builder.cprog->module, operand); + scc_hir_type_t *dst_type = + scc_hir_module_get_type(&ctx->builder.cprog->module, target_type); + + usize src_size = + scc_hir_type_size(ctx, src_type); // 你可能有这个函数,否则自行计算 + usize dst_size = scc_hir_type_size(ctx, dst_type); + + int conv_kind; + if (dst_size > src_size) { + // 目标更大,需要扩展。根据源类型有无符号决定符号扩展还是零扩展 + conv_kind = + scc_hir_type_is_signed(src_type->tag) ? CONV_SEXT : CONV_ZEXT; + } else if (dst_size < src_size) { + conv_kind = 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(&ctx->builder.cprog->module, + &conv_node); + } case SCC_AST_EXPR_SIZE_OF: { - TODO(); - // return scc_hir_builder_integer( - // &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); + // 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(&ctx->builder.cprog->module, 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(&ctx->builder.cprog->module, hir_type); + usize dst_size = scc_hir_type_size(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(); @@ -623,10 +965,50 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, // &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val); } case SCC_AST_EXPR_COMPOUND: { - TODO(); + // 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(&ctx->builder.cprog->module, 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: { - TODO(); + UNREACHABLE(); // should only appear as compound.base } break; case SCC_AST_EXPR_BUILTIN: { TODO(); @@ -923,10 +1305,10 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { 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); + // 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 = @@ -1009,6 +1391,10 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, 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 = @@ -1023,9 +1409,11 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, 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); } @@ -1149,6 +1537,7 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, 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; } @@ -1157,5 +1546,6 @@ void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) { 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); } diff --git a/libs/ir/hir/include/scc_hir_builder.h b/libs/ir/hir/include/scc_hir_builder.h index 076f14c..b7cbb0c 100644 --- a/libs/ir/hir/include/scc_hir_builder.h +++ b/libs/ir/hir/include/scc_hir_builder.h @@ -68,6 +68,11 @@ void scc_hir_builder_init(scc_hir_builder_t *builder, scc_hir_cprog_t *cprog); */ void scc_hir_builder_drop(scc_hir_builder_t *builder); +static inline scc_hir_module_t * +scc_hir_builder_get_module(scc_hir_builder_t *builder) { + return &builder->cprog->module; +} + scc_hir_func_ref_t scc_hir_builder_func(scc_hir_builder_t *builder, scc_hir_type_ref_t type_ref, const char *name); @@ -92,7 +97,7 @@ scc_hir_value_ref_t scc_hir_builder_alloca(scc_hir_builder_t *builder, const char *name); #define SCC_HIR_BUILDER_TYPE_FUNC(scc_type) \ - [[maybe_unused]] static inline scc_hir_type_ref_t \ + SCC_MAYBE_UNUSED static inline scc_hir_type_ref_t \ scc_hir_builder_type_##scc_type(scc_hir_builder_t *builder) { \ scc_hir_type_t type_desc; \ scc_hir_type_init(&type_desc, SCC_HIR_TYPE_##scc_type); \ diff --git a/libs/ir/hir/include/scc_hir_def.h b/libs/ir/hir/include/scc_hir_def.h index 4613a4e..c49284b 100644 --- a/libs/ir/hir/include/scc_hir_def.h +++ b/libs/ir/hir/include/scc_hir_def.h @@ -89,7 +89,9 @@ typedef enum scc_hir_value_tag { SCC_HIR_VALUE_TAG_OP, ///< 二元运算 SCC_HIR_VALUE_TAG_BRANCH, ///< 有条件分支 SCC_HIR_VALUE_TAG_JUMP, ///< 无条件跳转 + SCC_HIR_VALUE_TAG_JUMP_INDIRECT, ///< 无条件跳转(地址) SCC_HIR_VALUE_TAG_CALL, ///< 调用函数 + SCC_HIR_VALUE_TAG_CALL_INDIRECT, ///< 调用函数(地址) SCC_HIR_VALUE_TAG_RET, ///< 函数返回 } scc_hir_value_tag_t; @@ -222,11 +224,15 @@ struct scc_hir_value { scc_hir_bblock_ref_t true_bblock; scc_hir_bblock_ref_t false_bblock; } branch; - struct { + union { + scc_hir_value_ref_t target_ptr; scc_hir_bblock_ref_t target_bblock; } jump; struct { - scc_hir_func_ref_t callee; // TODO function pointer call + union { + scc_hir_func_ref_t func_ref; + scc_hir_value_ref_t ptr_ref; + } callee; scc_hir_value_ref_vec_t args; } call; struct { diff --git a/libs/ir/hir/src/scc_hir.c b/libs/ir/hir/src/scc_hir.c index dae53e5..88a2cba 100644 --- a/libs/ir/hir/src/scc_hir.c +++ b/libs/ir/hir/src/scc_hir.c @@ -105,7 +105,7 @@ void scc_hir_value_init(scc_hir_value_t *in, const char *name, break; case SCC_HIR_VALUE_TAG_CALL: scc_vec_init(in->data.call.args); - in->data.call.callee = 0; + in->data.call.callee.func_ref = 0; break; case SCC_HIR_VALUE_TAG_RET: in->data.ret.ret_val = 0; diff --git a/libs/ir/hir/src/scc_hir_builder.c b/libs/ir/hir/src/scc_hir_builder.c index 21bbad2..303bc34 100644 --- a/libs/ir/hir/src/scc_hir_builder.c +++ b/libs/ir/hir/src/scc_hir_builder.c @@ -625,7 +625,7 @@ scc_hir_value_ref_t scc_hir_builder_call(scc_hir_builder_t *builder, SCC_HIR_BUILDER_CHECK_NO_BORROW(builder); scc_hir_value_t call_node = {0}; call_node.tag = SCC_HIR_VALUE_TAG_CALL; - call_node.data.call.callee = callee; + call_node.data.call.callee.func_ref = callee; scc_vec_init(call_node.data.call.args); for (usize i = 0; i < arg_count; i++) { diff --git a/libs/ir/hir/src/scc_hir_dump.c b/libs/ir/hir/src/scc_hir_dump.c index a8d04b0..645173c 100644 --- a/libs/ir/hir/src/scc_hir_dump.c +++ b/libs/ir/hir/src/scc_hir_dump.c @@ -3,7 +3,9 @@ #include #define GET_MODULE(ctx) (&(ctx->cprog->module)) - +static void dump_type_with_visited(scc_hir_dump_t *ctx, + scc_hir_type_ref_t type_ref, + scc_hashtable_t *visited); static const char *get_node_type_str(scc_hir_value_tag_t tag) { static const char *node_types[] = { [SCC_HIR_VALUE_TAG_NULLPTR] = "NullPtr", @@ -168,9 +170,9 @@ static void dump_jump_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) { static void dump_call_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) { scc_tree_dump_begin_line(ctx->dump_ctx); - if (value->data.call.callee) { - scc_hir_func_t *callee = - scc_hir_module_get_func(GET_MODULE(ctx), value->data.call.callee); + if (value->data.call.callee.func_ref) { + scc_hir_func_t *callee = scc_hir_module_get_func( + GET_MODULE(ctx), value->data.call.callee.func_ref); scc_tree_dump_value(ctx->dump_ctx, "func='%s'", callee ? (callee->name ? callee->name : "") : ""); @@ -256,60 +258,12 @@ void scc_hir_dump_value(scc_hir_dump_t *ctx, scc_hir_value_ref_t value_ref) { break; } } - void scc_hir_dump_type(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref) { - if (!ctx || !type_ref) { - LOG_ERROR("invalid parameter"); - return; - } - scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref); - if (!type) { - LOG_ERROR("invalid type ref"); - return; - } - scc_tree_dump_begin_line(ctx->dump_ctx); - scc_tree_dump_node(ctx->dump_ctx, "Type: "); - scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag)); - - switch (type->tag) { - case SCC_HIR_TYPE_PTR: - if (type->data.pointer.base) { - scc_tree_dump_push(ctx->dump_ctx, true); - scc_hir_dump_type(ctx, type->data.pointer.base); - scc_tree_dump_pop(ctx->dump_ctx); - } - break; - case SCC_HIR_TYPE_ARRAY: - if (type->data.array.len > 0) { - scc_tree_dump_begin_line(ctx->dump_ctx); - scc_tree_dump_node(ctx->dump_ctx, "Array Length: "); - scc_tree_dump_value(ctx->dump_ctx, "%zu", type->data.array.len); - scc_tree_dump_append(ctx->dump_ctx, "\n"); - } - if (type->data.array.base) { - scc_tree_dump_push(ctx->dump_ctx, true); - scc_hir_dump_type(ctx, type->data.array.base); - scc_tree_dump_pop(ctx->dump_ctx); - } - break; - case SCC_HIR_TYPE_FUNC: - for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) { - cbool is_last = (i + 1 == scc_vec_size(type->data.function.params)); - scc_tree_dump_push(ctx->dump_ctx, is_last); - scc_hir_dump_type(ctx, scc_vec_at(type->data.function.params, i)); - scc_tree_dump_pop(ctx->dump_ctx); - } - if (type->data.function.ret_type) { - scc_tree_dump_push(ctx->dump_ctx, true); - scc_hir_dump_type(ctx, type->data.function.ret_type); - scc_tree_dump_pop(ctx->dump_ctx); - } - break; - default: - break; - } + scc_hashtable_t visited; + scc_hashtable_usize_init(&visited); + dump_type_with_visited(ctx, type_ref, &visited); + scc_hashtable_drop(&visited); } - void scc_hir_dump_bblock(scc_hir_dump_t *ctx, scc_hir_bblock_ref_t bblock_ref) { if (!ctx || !bblock_ref) { LOG_ERROR("invalid parameter"); @@ -379,13 +333,94 @@ void scc_hir_dump_cprog(scc_hir_dump_t *ctx) { } // ----- 线性输出(保留原逻辑,改用新 API)----- -void scc_hir_dump_type_linear(scc_hir_dump_t *ctx, - scc_hir_type_ref_t type_ref) { - scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref); - if (!ctx || !type) { + +// 在 scc_hir_dump.c 中添加以下静态辅助函数(放在文件前部,现有函数之前) + +static void dump_type_linear_with_visited(scc_hir_dump_t *ctx, + scc_hir_type_ref_t type_ref, + scc_hashtable_t *visited); +static void dump_type_with_visited(scc_hir_dump_t *ctx, + scc_hir_type_ref_t type_ref, + scc_hashtable_t *visited) { + if (!ctx || !type_ref) { LOG_ERROR("invalid parameter"); return; } + // 检查循环 + if (scc_hashtable_get(visited, (void *)(usize)type_ref)) { + scc_tree_dump_append(ctx->dump_ctx, " "); + return; + } + scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1); + + scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref); + if (!type) { + LOG_ERROR("invalid type ref"); + return; + } + scc_tree_dump_begin_line(ctx->dump_ctx); + scc_tree_dump_node(ctx->dump_ctx, "Type: "); + scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag)); + + switch (type->tag) { + case SCC_HIR_TYPE_PTR: + if (type->data.pointer.base) { + scc_tree_dump_push(ctx->dump_ctx, true); + dump_type_with_visited(ctx, type->data.pointer.base, visited); + scc_tree_dump_pop(ctx->dump_ctx); + } + break; + case SCC_HIR_TYPE_ARRAY: + if (type->data.array.len > 0) { + scc_tree_dump_begin_line(ctx->dump_ctx); + scc_tree_dump_node(ctx->dump_ctx, "Array Length: "); + scc_tree_dump_value(ctx->dump_ctx, "%zu", type->data.array.len); + scc_tree_dump_append(ctx->dump_ctx, "\n"); + } + if (type->data.array.base) { + scc_tree_dump_push(ctx->dump_ctx, true); + dump_type_with_visited(ctx, type->data.array.base, visited); + scc_tree_dump_pop(ctx->dump_ctx); + } + break; + case SCC_HIR_TYPE_FUNC: + for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) { + cbool is_last = (i + 1 == scc_vec_size(type->data.function.params)); + scc_tree_dump_push(ctx->dump_ctx, is_last); + dump_type_with_visited( + ctx, scc_vec_at(type->data.function.params, i), visited); + scc_tree_dump_pop(ctx->dump_ctx); + } + if (type->data.function.ret_type) { + scc_tree_dump_push(ctx->dump_ctx, true); + dump_type_with_visited(ctx, type->data.function.ret_type, visited); + scc_tree_dump_pop(ctx->dump_ctx); + } + break; + default: + break; + } +} + +static void dump_type_linear_with_visited(scc_hir_dump_t *ctx, + scc_hir_type_ref_t type_ref, + scc_hashtable_t *visited) { + if (!ctx || !type_ref) { + LOG_ERROR("invalid parameter"); + return; + } + // 检查循环 + if (scc_hashtable_get(visited, (void *)(usize)type_ref)) { + scc_tree_dump_append(ctx->dump_ctx, " "); + return; + } + scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1); + + scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref); + if (!type) { + LOG_ERROR("invalid type ref"); + return; + } switch (type->tag) { case SCC_HIR_TYPE_unknown: case SCC_HIR_TYPE_void: @@ -407,24 +442,25 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx, break; case SCC_HIR_TYPE_ARRAY: scc_tree_dump_append(ctx->dump_ctx, "["); - scc_hir_dump_type_linear(ctx, type->data.array.base); + dump_type_linear_with_visited(ctx, type->data.array.base, visited); scc_tree_dump_append_fmt(ctx->dump_ctx, ", %zu]", type->data.array.len); break; case SCC_HIR_TYPE_PTR: scc_tree_dump_append(ctx->dump_ctx, "*"); - scc_hir_dump_type_linear(ctx, type->data.pointer.base); + dump_type_linear_with_visited(ctx, type->data.pointer.base, visited); break; case SCC_HIR_TYPE_FUNC: scc_tree_dump_append(ctx->dump_ctx, "("); for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) { if (i > 0) scc_tree_dump_append(ctx->dump_ctx, ", "); - scc_hir_dump_type_linear(ctx, - scc_vec_at(type->data.function.params, i)); + dump_type_linear_with_visited( + ctx, scc_vec_at(type->data.function.params, i), visited); } if (type->data.function.ret_type) { scc_tree_dump_append(ctx->dump_ctx, ") -> "); - scc_hir_dump_type_linear(ctx, type->data.function.ret_type); + dump_type_linear_with_visited(ctx, type->data.function.ret_type, + visited); } else { scc_tree_dump_append(ctx->dump_ctx, ")"); } @@ -434,9 +470,9 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx, scc_tree_dump_append_fmt(ctx->dump_ctx, "%s {", type->tag == SCC_HIR_TYPE_STRUCT ? "struct" : "union"); - scc_vec_foreach(type->data.aggregate.fields, i) { - scc_hir_dump_type_linear( - ctx, scc_vec_at(type->data.aggregate.fields, i)); + for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) { + dump_type_linear_with_visited( + ctx, scc_vec_at(type->data.aggregate.fields, i), visited); scc_tree_dump_append(ctx->dump_ctx, ";"); } scc_tree_dump_append(ctx->dump_ctx, "}"); @@ -447,6 +483,14 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx, } } +void scc_hir_dump_type_linear(scc_hir_dump_t *ctx, + scc_hir_type_ref_t type_ref) { + scc_hashtable_t visited; + scc_hashtable_usize_init(&visited); + dump_type_linear_with_visited(ctx, type_ref, &visited); + scc_hashtable_drop(&visited); +} + static void format_ref_or_value(scc_hir_dump_t *ctx, scc_hir_value_ref_t value_ref) { scc_hir_value_t *value = @@ -580,8 +624,8 @@ void scc_hir_dump_value_linear(scc_hir_dump_t *ctx, value->data.jump.target_bblock); break; case SCC_HIR_VALUE_TAG_CALL: { - scc_hir_func_t *func = - scc_hir_module_get_func(GET_MODULE(ctx), value->data.call.callee); + scc_hir_func_t *func = scc_hir_module_get_func( + GET_MODULE(ctx), value->data.call.callee.func_ref); scc_tree_dump_append_fmt(ctx->dump_ctx, "call @%s(", func ? (func->name ? func->name : "") : ""); diff --git a/libs/ir/lir/src/scc_hir2lir.c b/libs/ir/lir/src/scc_hir2lir.c index 04d35b2..817216c 100644 --- a/libs/ir/lir/src/scc_hir2lir.c +++ b/libs/ir/lir/src/scc_hir2lir.c @@ -358,8 +358,8 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, break; } case SCC_HIR_VALUE_TAG_CALL: { - scc_hir_func_t *callee = - scc_hir_module_get_func(ctx->hir_module, value->data.call.callee); + 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++) { diff --git a/libs/parser/include/scc_sema.h b/libs/parser/include/scc_sema.h index d0991dd..fc43460 100644 --- a/libs/parser/include/scc_sema.h +++ b/libs/parser/include/scc_sema.h @@ -2,6 +2,7 @@ #define __SCC_SEMA_H__ #include +#include typedef struct scc_sema_ctx scc_sema_ctx_t; /** @@ -13,6 +14,12 @@ typedef void (*scc_sema_callback_t)(scc_sema_ctx_t *context, typedef scc_ast_qual_type_t *(*scc_sema_got_type_t)(scc_sema_ctx_t *context, const char *name); +typedef struct scc_label_scope { + int function_scope_depth; + scc_hashtable_t labels; // 标签名 -> scc_ast_stmt_t* (LABEL节点) + scc_ast_stmt_vec_t pending_gotos; // 尚未找到目标的goto语句 +} scc_sema_label_scope_t; + /** * @brief 语义分析回调集合 */ @@ -26,6 +33,7 @@ struct scc_sema_ctx { scc_ast_stmt_vec_t break_stack; scc_ast_stmt_vec_t continue_stack; + scc_sema_label_scope_t label_scope; void *context; }; diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index d0b85f2..5b13d0b 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -290,7 +290,10 @@ CONTINUE: decl->var.init = scc_parse_initializer(parser, lvalue); } else if (tok_ptr->type == SCC_TOK_L_BRACE) { scc_parse_decl_sema(parser, decl); - scc_sema_decl(parser, scc_ast_decl_t_BEGIN, nullptr); + + // 进入函数作用域(用于参数和标签) + scc_sema_decl(parser, scc_ast_decl_t_BEGIN, decl); + // FIXME hack struct scc_vec_foreach(decl->func.type->type->function.params, i) { scc_ast_decl_t *param = @@ -299,7 +302,10 @@ CONTINUE: scc_parse_decl_sema(parser, param); } scc_ast_stmt_t *body = scc_parse_statement(parser); - scc_sema_decl(parser, scc_ast_decl_t_END, nullptr); + + // 退出函数作用域 + scc_sema_decl(parser, scc_ast_decl_t_END, decl); + Assert(decl->base.type == SCC_AST_DECL_FUNC); decl->func.body = body; Assert(decl->func.type != nullptr); diff --git a/libs/parser/src/scc_parser.c b/libs/parser/src/scc_parser.c index c19fa88..89e57f5 100644 --- a/libs/parser/src/scc_parser.c +++ b/libs/parser/src/scc_parser.c @@ -73,6 +73,7 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) { if (decl != nullptr) { scc_vec_push(unit->declarations, decl); } else { + parser->errcode = 1; break; } if (parser->errcode != 0) { // FIXME errcode diff --git a/libs/parser/src/scc_sema.c b/libs/parser/src/scc_sema.c index 260ff1e..8c6aa56 100644 --- a/libs/parser/src/scc_sema.c +++ b/libs/parser/src/scc_sema.c @@ -133,37 +133,72 @@ static void stmt_callback(scc_sema_ctx_t *sema_ctx, } scc_ast_stmt_t *stmt = SCC_AST_CAST_TO(scc_ast_stmt_t, node); switch (stmt->base.type) { - case SCC_AST_STMT_BREAK: + case SCC_AST_STMT_BREAK: { if (scc_vec_size(sema_ctx->break_stack) == 0) SCC_ERROR(stmt->base.loc, "break not in loop/switch"); else stmt->jump._target = scc_vec_at( sema_ctx->break_stack, scc_vec_size(sema_ctx->break_stack) - 1); - break; - case SCC_AST_STMT_CONTINUE: + } break; + case SCC_AST_STMT_CONTINUE: { if (scc_vec_size(sema_ctx->continue_stack) == 0) SCC_ERROR(stmt->base.loc, "continue not in loop"); else stmt->jump._target = scc_vec_at(sema_ctx->continue_stack, scc_vec_size(sema_ctx->continue_stack) - 1); - case SCC_AST_STMT_GOTO: - scc_ast_node_t *target_node = - scc_sema_symtab_lookup_symbol(sema_symtab, stmt->goto_stmt.label); - if (target_node == nullptr) { - SCC_ERROR(stmt->base.loc, ""); + } break; + case SCC_AST_STMT_GOTO: { + scc_ast_stmt_t *goto_stmt = SCC_AST_CAST_TO(scc_ast_stmt_t, node); + scc_sema_label_scope_t *scope = &sema_ctx->label_scope; + if (scope->function_scope_depth != 1) { + SCC_ERROR(goto_stmt->base.loc, "goto not inside any function"); break; } - if (!SCC_AST_IS_A(scc_ast_stmt_t, target_node)) { - SCC_ERROR(stmt->base.loc, ""); + + // 尝试直接查找标签 + scc_ast_node_t *target = + scc_hashtable_get(&scope->labels, goto_stmt->goto_stmt.label); + if (target) { + goto_stmt->goto_stmt._target = + SCC_AST_CAST_TO(scc_ast_stmt_t, target); + } else { + // 未找到则加入待处理列表 + scc_vec_push(scope->pending_gotos, goto_stmt); + } + } break; + case SCC_AST_STMT_LABEL: { + scc_ast_stmt_t *label_stmt = SCC_AST_CAST_TO(scc_ast_stmt_t, node); + scc_sema_label_scope_t *scope = &sema_ctx->label_scope; + // 获取当前函数标签作用域 + if (scope->function_scope_depth != 1) { + SCC_ERROR(label_stmt->base.loc, "label not inside any function"); break; } - stmt->goto_stmt._target = SCC_AST_CAST_TO(scc_ast_stmt_t, target_node); - break; - case SCC_AST_STMT_LABEL: - scc_sema_symtab_add_symbol(sema_symtab, stmt->label_stmt.label, - &stmt->base); - break; + + // 检查重复定义 + if (scc_hashtable_get(&scope->labels, label_stmt->label_stmt.label)) { + SCC_ERROR(label_stmt->base.loc, "duplicate label '%s'", + label_stmt->label_stmt.label); + break; + } + + // 添加标签 + scc_hashtable_set(&scope->labels, label_stmt->label_stmt.label, + &label_stmt->base); + + // 检查是否有等待该标签的 goto + scc_vec_foreach(scope->pending_gotos, i) { + scc_ast_stmt_t *goto_stmt = scc_vec_at(scope->pending_gotos, i); + if (goto_stmt == nullptr) + continue; + if (scc_strcmp(goto_stmt->goto_stmt.label, + label_stmt->label_stmt.label) == 0) { + goto_stmt->goto_stmt._target = label_stmt; + scc_vec_at(scope->pending_gotos, i) = nullptr; + } + } + } break; default: break; } @@ -175,10 +210,37 @@ static void decl_callback(scc_sema_ctx_t *sema_ctx, scc_sema_symtab_t *sema_symtab = sema_ctx->context; // Function declaration scope + // FIXME 使用 node_type 区分其他未来的scope if (node_type == scc_ast_decl_t_BEGIN) { + // 创建标签作用域 + scc_sema_label_scope_t *scope = &sema_ctx->label_scope; + scope->function_scope_depth += 1; + scc_hashtable_cstr_init(&scope->labels); + scc_vec_init(scope->pending_gotos); + + // 进入普通符号表作用域(用于参数和局部变量) scc_sema_symtab_enter_scope(sema_symtab); return; } else if (node_type == scc_ast_decl_t_END) { + scc_sema_label_scope_t *scope = &sema_ctx->label_scope; + scope->function_scope_depth -= 1; + + // 处理尚未绑定的 goto + scc_vec_foreach(scope->pending_gotos, i) { + scc_ast_stmt_t *goto_stmt = scc_vec_at(scope->pending_gotos, i); + if (goto_stmt == nullptr) { + continue; + } + // 标签未定义 -> 报错 + SCC_ERROR(goto_stmt->base.loc, "label '%s' used but not defined", + goto_stmt->goto_stmt.label); + } + + // 清理 + scc_hashtable_drop(&scope->labels); + scc_vec_free(scope->pending_gotos); + + // 退出普通符号表作用域 scc_sema_symtab_leave_scope(sema_symtab); return; } @@ -242,6 +304,7 @@ void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_ctx_t *ast_ctx) { sema_ctx->on_stmt = stmt_callback; sema_ctx->on_type = type_callback; sema_ctx->got_type = got_type_callback; + sema_ctx->label_scope = (scc_sema_label_scope_t){0}; scc_sema_symtab_init(sema_symtab); diff --git a/libs/pproc/src/pproc_include.c b/libs/pproc/src/pproc_include.c index 6f06b62..088c358 100644 --- a/libs/pproc/src/pproc_include.c +++ b/libs/pproc/src/pproc_include.c @@ -99,11 +99,11 @@ void scc_pproc_parse_include(scc_pproc_t *pp, scc_lexer_tok_t *include_tok, for (int i = 1; i < len - 1; i++) { scc_str_append_ch(&fname, includename[i]); } - scc_str_drop(&line); int is_system = includename[0] == '<'; if (switch_file_stack(pp, &fname, &pos, is_system)) { // LOG_ERROR() } + scc_str_drop(&line); scc_str_drop(&fname); return; ERROR: diff --git a/runtime/ap/include/ap.h b/runtime/ap/include/ap.h index b0d7681..9b9e3e3 100644 --- a/runtime/ap/include/ap.h +++ b/runtime/ap/include/ap.h @@ -4,7 +4,7 @@ * @brief Arbitrary Precision Library * */ -#ifdef __AP_SCC__ +#ifdef __SCC__ #include #define SCC_AP_DIGIT u64 #define SCC_AP_PANIC Panic diff --git a/runtime/log/include/log.h b/runtime/log/include/log.h index da37f7c..ce0a1a3 100644 --- a/runtime/log/include/log.h +++ b/runtime/log/include/log.h @@ -21,7 +21,7 @@ #define __scc_log_unreachable() (__builtin_unreachable()) #elif defined _MSC_VER // MSVC #define __scc_log_unreachable() (__assume(false)) -#elif defined __SCC_BUILTIN__ // The SCC Compiler (my compiler) +#elif defined __SCC_BUILTIN_UNREACHEABLE__ // The SCC Compiler (my compiler) #define __scc_log_unreachable() (__scc_builtin_unreachable()) #else #define __scc_log_unreachable() ((void)0) @@ -184,7 +184,7 @@ void log_set_handler(logger_t *logger, log_handler handler); * 或使用 _Static_assert (C11) */ #if __STDC_VERSION__ >= 201112L -#define StaticAssert static_assert +#define StaticAssert _Static_assert #else #define StaticAssert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1] #endif diff --git a/runtime/scc_core/include/scc_core_macro.h b/runtime/scc_core/include/scc_core_macro.h index f313ed1..672e84a 100644 --- a/runtime/scc_core/include/scc_core_macro.h +++ b/runtime/scc_core/include/scc_core_macro.h @@ -13,4 +13,14 @@ #define scc_min(a, b) ((a) < (b) ? (a) : (b)) #define scc_max(a, b) ((a) > (b) ? (a) : (b)) +#ifdef __GNUC__ +#define SCC_MAYBE_UNUSED __attribute__((unused)) +#elif defined(_MSC_VER) +#define SCC_MAYBE_UNUSED __pragma(warning(suppress : 4100)) +#elif defined(__clang__) +#define SCC_MAYBE_UNUSED __attribute__((unused)) +#else +#define SCC_MAYBE_UNUSED +#endif + #endif // __SCC_CORE_MACRO_H__ diff --git a/runtime/scc_core/include/scc_core_vec.h b/runtime/scc_core/include/scc_core_vec.h index 43bf838..66cba5f 100644 --- a/runtime/scc_core/include/scc_core_vec.h +++ b/runtime/scc_core/include/scc_core_vec.h @@ -15,13 +15,16 @@ #include "scc_core_type.h" #define __scc_vec_realloc scc_realloc #define __scc_vec_free scc_free +#define __scc_vec_memcpy scc_memcpy #else #include #include +#include typedef size_t usize; #define __scc_vec_realloc realloc #define __scc_vec_free free +#define __scc_vec_memcpy memcpy #ifndef LOG_FATAL #include @@ -169,4 +172,86 @@ typedef size_t usize; (vec).data = array; \ } while (0) +/** + * @def scc_vec_sized_realloc(vec, elem_size, new_cap) + * @brief 内部宏:按 elem_size 重新分配内存 + */ +#define scc_vec_sized_realloc(vec, elem_size, new_cap) \ + do { \ + void *new_data = \ + __scc_vec_realloc((vec).data, (new_cap) * (elem_size)); \ + if (!new_data) \ + LOG_FATAL("scc_vec_sized_realloc: failed\n"); \ + (vec).data = new_data; \ + (vec).cap = new_cap; \ + } while (0) + +/** + * @def scc_vec_sized_push(vec, elem_size, src_ptr) + * @brief 添加一个元素(从 src_ptr 拷贝 elem_size 字节) + * @param vec SCC_VEC(type) 定义的向量变量(type 可为 char 或 void) + * @param elem_size 每个元素占用的字节数 + * @param src_ptr 源数据的指针 + * @param copy_size 要拷贝的字节数 + * + * @note 使用前需确保 vec.data 类型与 src_ptr 无关,内部会按字节拷贝。 + * 推荐声明时为 `SCC_VEC(char)` 或 `SCC_VEC(unsigned char)`。 + */ +#define scc_vec_sized_push(vec, elem_size, src_ptr, copy_size) \ + do { \ + if ((vec).size >= (vec).cap) { \ + usize new_cap = (vec).cap ? (vec).cap * 2 : 4; \ + scc_vec_sized_realloc(vec, elem_size, new_cap); \ + } \ + char *slot = (char *)(vec).data + (vec).size * (elem_size); \ + __scc_vec_memcpy(slot, (src_ptr), (copy_size)); \ + (vec).size++; \ + } while (0) + +/** + * @def scc_vec_sized_at_ptr(vec, elem_size, idx) + * @brief 获取第 idx 个元素的指针(void*) + * @return 指向元素的指针,需转换为具体类型使用 + */ +#define scc_vec_sized_at_ptr(vec, elem_size, idx) \ + ((void *)((char *)(vec).data + (idx) * (elem_size))) + +/** + * @def scc_vec_sized_foreach(vec, elem_size, elem_ptr_var, block) + * @brief 遍历所有元素 + * @param elem_ptr_var 循环内的变量名(void* 类型) + * @param block 循环体语句块 + */ +#define scc_vec_sized_foreach(vec, elem_size, elem_ptr_var, block) \ + do { \ + for (usize __i = 0; __i < (vec).size; ++__i) { \ + void *elem_ptr_var = scc_vec_sized_at_ptr(vec, elem_size, __i); \ + block; \ + } \ + } while (0) + +/** + * @def scc_vec_sized_pop(vec, elem_size) + * @brief 弹出最后一个元素(仅减小 size,不返回数据) + */ +#define scc_vec_sized_pop(vec, elem_size) \ + do { \ + if ((vec).size == 0) \ + LOG_FATAL("scc_vec_sized_pop: empty\n"); \ + (vec).size--; \ + } while (0) + +/** + * @def scc_vec_sized_clear(vec) + * @brief 清空向量(重置 size = 0,不释放内存) + */ +#define scc_vec_sized_clear(vec) ((vec).size = 0) + +/** + * @def scc_vec_sized_free(vec) + * @brief 释放向量内存(与原始 scc_vec_free 相同,可复用) + * @note 注意:如果元素内部有堆资源,需在释放前自行遍历调用析构函数。 + */ +#define scc_vec_sized_free(vec) scc_vec_free(vec) + #endif /* __SCC_CORE_VEC_H__ */ diff --git a/runtime/scc_core/src/core_impl.c b/runtime/scc_core/src/core_impl.c index 36982dd..118dcdf 100644 --- a/runtime/scc_core/src/core_impl.c +++ b/runtime/scc_core/src/core_impl.c @@ -39,8 +39,15 @@ usize scc_fread(scc_file_t file, void *buffer, usize size) { return scc_pal_fread(file, buffer, size); } -usize scc_fwrite(scc_file_t file, const void *buffer, usize size) { - return scc_pal_fwrite(file, buffer, size); +usize scc_fwrite(scc_file_t file, const void *buf, usize size) { + if (file == scc_stdout) { + scc_pal_write(buf, size); + } else if (file == scc_stderr) { + scc_pal_ewrite(buf, size); + } else { + return scc_pal_fwrite(file, buf, size); + } + return 0; } cbool scc_fexists(const char *path) { diff --git a/src/config.c b/src/config.c index fd63ac1..4484ad4 100644 --- a/src/config.c +++ b/src/config.c @@ -155,7 +155,6 @@ void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, static const char *emit_stages[] = { [SCC_EMIT_STAGE_LEX] = "lex", [SCC_EMIT_STAGE_PP] = "pp", - [SCC_EMIT_STAGE_AST] = "ast", // -T [SCC_EMIT_STAGE_HIR] = "hir", // -H [SCC_EMIT_STAGE_LIR] = "lir", // -L