diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index dded231..f2e7559 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -38,4 +38,33 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt); scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, const scc_ast_qual_type_t *ast_type); +// ====== 类型提升(Type Promotion)接口 ====== + +/** + * @brief 整数提升(C11 6.3.1.1) + * 对 _Bool、char、short 等秩低于 int 的类型提升为 int/unsigned int + * @param type_ref 原始类型引用 + * @return 提升后的类型的引用,若无需提升则返回原始类型 + */ +scc_hir_type_ref_t scc_ast2ir_integer_promotion(scc_ast2ir_ctx_t *ctx, + scc_hir_type_ref_t type_ref); + +/** + * @brief 寻常算术转换(C11 6.3.1.8) + * 对二元算术操作的两个操作数类型找到公共类型 + * @return 公共类型的引用 + */ +scc_hir_type_ref_t scc_ast2ir_usual_arithmetic_conversion( + scc_ast2ir_ctx_t *ctx, scc_hir_type_ref_t t1_ref, + scc_hir_type_ref_t t2_ref); + +/** + * @brief 插入类型转换指令 + * 根据源类型和目标类型自动选择 SEXT/ZEXT/TRUNC/F2I/I2F/F2F + * @return 转换后的值引用 + */ +scc_hir_value_ref_t scc_ast2ir_emit_conversion(scc_ast2ir_ctx_t *ctx, + scc_hir_value_ref_t value, + scc_hir_type_ref_t target_type); + #endif /* __SCC_AST2IR_H__ */ diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index 0ea3cc9..b4678d9 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -4,6 +4,26 @@ #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; @@ -47,6 +67,29 @@ static inline bool scc_hir_type_is_signed(scc_hir_type_tag_t tag) { } } +// 判断是否为算术类型(整数或浮点) +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, @@ -233,12 +276,14 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, // 将返回类型添加到程序的类型容器中 ir_type.data.function.ret_type = ret_type; - // 转换参数类型 + // 转换参数类型(跳过尾部的 ... 假参数) scc_hir_type_ref_vec_t params; scc_vec_init(params); - scc_vec_foreach(scc_ast_canon_type(ast_type)->function.params, i) { - scc_ast_decl_t *decl_param = - scc_vec_at(scc_ast_canon_type(ast_type)->function.params, i); + 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); @@ -328,16 +373,14 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, } scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, - const scc_ast_expr_t *expr, - scc_hir_value_ref_t lhs, - scc_hir_value_ref_t rhs) { + 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_bblock(&ctx->builder, "logic_right"); + scc_hir_builder_create_bblock(&ctx->builder, "logic_right"); scc_hir_value_ref_t end_block = - scc_hir_builder_bblock(&ctx->builder, "logic_end"); + scc_hir_builder_create_bblock(&ctx->builder, "logic_end"); // 为结果创建临时存储空间 scc_hir_type_ref_t int32_type = scc_hir_builder_type_i32(&ctx->builder); @@ -360,7 +403,7 @@ scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, if (expr->binary.op == SCC_AST_OP_LOGICAL_AND) { // a && b scc_hir_value_ref_t false_block = - scc_hir_builder_bblock(&ctx->builder, "and_false"); + scc_hir_builder_create_bblock(&ctx->builder, "and_false"); // 如果左操作数为0,结果为0(短路) scc_hir_value_ref_t is_left_zero = scc_hir_builder_binop( @@ -369,11 +412,13 @@ scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, 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); @@ -388,7 +433,7 @@ scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, } else { // SCC_AST_OP_LOGICAL_OR // a || b scc_hir_value_ref_t true_block = - scc_hir_builder_bblock(&ctx->builder, "or_true"); + scc_hir_builder_create_bblock(&ctx->builder, "or_true"); // 如果左操作数非0,结果为1(短路) scc_hir_value_ref_t is_left_nonzero = scc_hir_builder_binop( @@ -397,11 +442,13 @@ scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, 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); @@ -415,6 +462,7 @@ scc_hir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, } // 设置结束块为当前块,并返回结果 + 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); } @@ -511,11 +559,61 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, 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) { @@ -547,7 +645,8 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, /* 逻辑操作符 */ case SCC_AST_OP_LOGICAL_OR: // || case SCC_AST_OP_LOGICAL_AND: // && - return scc_ast2ir_logical_expr(ctx, expr, lhs, rhs); + UNREACHABLE(); + return 0; /* clang-format on */ default: LOG_FATAL("Unsupported binary operator: %d", expr->binary.op); @@ -620,13 +719,20 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, 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); + + // 整数提升: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; - // scc_ast2ir_apply_promotion(ctx, 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, scc_hir_builder_type_i32(&ctx->builder), + &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) @@ -637,10 +743,9 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, // 如果原类型不是提升后的类型,需要截断回原类型再存储 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); - // } + 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 标准) @@ -656,13 +761,20 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, 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); + + // 整数提升(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; - // scc_ast2ir_apply_promotion(ctx, 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, scc_hir_builder_type_i32(&ctx->builder), + &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) @@ -672,17 +784,13 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, 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; + 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); - // 后缀返回旧的、未提升的值(但 C - // 要求返回提升后的旧值?实际是旧值按右值规则,应得到提升后的值) - // 标准规定后缀++的结果是操作数原来的值,但会经过整数提升。 - // 所以需要返回 promoted(已提升的旧值)。 - Assert(promoted != SCC_HIR_REF_nullptr); - return promoted; // 旧值,但类型已提升为 - // int 等 + // 后缀返回旧值的提升后版本(C11 6.5.2.4) + return promoted; } break; default: LOG_FATAL("Unsupported unary operator: %d", expr->unary.op); @@ -746,22 +854,78 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, 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; + 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); } // 创建调用节点(需要查找函数定义) - scc_hir_func_ref_t func = (scc_hir_value_ref_t)(usize)scc_hashtable_get( - &ctx->symtab, expr->call.callee->identifier._target->name); - if (!func) { + 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, func, args.data, args.size); + scc_hir_value_ref_t node = scc_hir_builder_call( + &ctx->builder, callee_func, args.data, args.size); scc_vec_free(args); return node; } @@ -772,6 +936,18 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, // 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); @@ -846,10 +1022,11 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, int conv_kind; if (dst_size > src_size) { // 目标更大,需要扩展。根据源类型有无符号决定符号扩展还是零扩展 - conv_kind = - scc_hir_type_is_signed(src_type->tag) ? CONV_SEXT : CONV_ZEXT; + 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 = CONV_TRUNC; + conv_kind = SCC_HIR_CONV_TRUNC; } else { // 同大小,可以视为 NOP 转换,或者直接返回操作数 return operand; // 或创建一个 CONV_SEXT 也没问题 @@ -963,10 +1140,9 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, // SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量 case SCC_AST_EXPR_CHAR_LITERAL: { // FIXME just 'a' '\n' - scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder); const char *lexme = expr->literal.lexme; Assert(lexme[0] == '\''); - u8 int_lit = 0; + i8 int_lit = 0; if (lexme[1] == '\\') { switch (lexme[2]) { case 'a': @@ -988,6 +1164,8 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, 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); } @@ -1079,95 +1257,105 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { merge_block */ scc_hir_value_ref_t true_block = - scc_hir_builder_bblock(&ctx->builder, "if_true"); + scc_hir_builder_create_bblock(&ctx->builder, "if_true"); scc_hir_value_ref_t false_block = - scc_hir_builder_bblock(&ctx->builder, "if_false"); + scc_hir_builder_create_bblock(&ctx->builder, "if_false"); scc_hir_value_ref_t merge_block = - scc_hir_builder_bblock(&ctx->builder, "if_merge"); + 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, - false_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_bblock(&ctx->builder, "while_cond"); + scc_hir_builder_create_bblock(&ctx->builder, "while_cond"); scc_hir_value_ref_t body_block = - scc_hir_builder_bblock(&ctx->builder, "while_body"); + scc_hir_builder_create_bblock(&ctx->builder, "while_body"); scc_hir_value_ref_t exit_block = - scc_hir_builder_bblock(&ctx->builder, "while_exit"); + 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_bblock(&ctx->builder, "do_while_cond"); + scc_hir_builder_create_bblock(&ctx->builder, "do_while_cond"); scc_hir_value_ref_t body_block = - scc_hir_builder_bblock(&ctx->builder, "do_while_body"); + scc_hir_builder_create_bblock(&ctx->builder, "do_while_body"); scc_hir_value_ref_t exit_block = - scc_hir_builder_bblock(&ctx->builder, "do_while_exit"); + 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_bblock(&ctx->builder, "for_cond"); + scc_hir_builder_create_bblock(&ctx->builder, "for_cond"); scc_hir_value_ref_t body_block = - scc_hir_builder_bblock(&ctx->builder, "for_body"); + scc_hir_builder_create_bblock(&ctx->builder, "for_body"); scc_hir_value_ref_t incr_block = - scc_hir_builder_bblock(&ctx->builder, "for_incr"); + scc_hir_builder_create_bblock(&ctx->builder, "for_incr"); scc_hir_value_ref_t exit_block = - scc_hir_builder_bblock(&ctx->builder, "for_exit"); + 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); @@ -1188,6 +1376,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { 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 = @@ -1198,16 +1387,19 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { 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; } @@ -1238,6 +1430,23 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { 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); @@ -1357,14 +1566,21 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, (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; } - scc_hir_func_t *hir_func = - scc_hir_module_get_func(&ctx->builder.cprog->module, func_ref); - Assert(hir_func != nullptr); // TODO this is double check defined Assert(SCC_HIR_FUNC_META(hir_func)->defined == false); SCC_HIR_FUNC_META(hir_func)->defined = true; @@ -1372,10 +1588,11 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, scc_hir_builder_begin_func(&ctx->builder, func_ref); scc_hir_builder_begin_bblock(&ctx->builder, "entry"); - scc_vec_foreach(scc_ast_canon_type(decl->func.type)->function.params, - i) { - scc_ast_decl_t *param = scc_vec_at( - scc_ast_canon_type(decl->func.type)->function.params, i); + // 只处理固定参数,跳过尾部的 ... 假参数 + 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); } @@ -1395,11 +1612,15 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, 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( diff --git a/libs/ast2ir/src/scc_ast2ir_promote.c b/libs/ast2ir/src/scc_ast2ir_promote.c new file mode 100644 index 0000000..4f24179 --- /dev/null +++ b/libs/ast2ir/src/scc_ast2ir_promote.c @@ -0,0 +1,321 @@ +#include + +// 判断是否为整数类型(不包括指针、浮点) +static cbool is_integer_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: + return true; + default: + return false; + } +} + +// 判断是否为浮点类型 +static cbool is_floating_type(const scc_hir_type_t *type) { + switch (type->tag) { + 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; + } +} + +// 获取整数等级(rank),参考 C11 6.3.1.1 +static int integer_tag_rank(scc_hir_type_tag_t tag) { + switch (tag) { + case SCC_HIR_TYPE_i8: + case SCC_HIR_TYPE_u8: + return 1; + case SCC_HIR_TYPE_i16: + case SCC_HIR_TYPE_u16: + return 2; + case SCC_HIR_TYPE_i32: + case SCC_HIR_TYPE_u32: + return 3; + case SCC_HIR_TYPE_i64: + case SCC_HIR_TYPE_u64: + return 4; + case SCC_HIR_TYPE_i128: + case SCC_HIR_TYPE_u128: + return 5; + default: + return 0; + } +} + +// 获取浮点等级(等级越高精度越高) +static int floating_rank(const scc_hir_type_t *type) { + switch (type->tag) { + case SCC_HIR_TYPE_f16: + return 1; + case SCC_HIR_TYPE_f32: + return 2; + case SCC_HIR_TYPE_f64: + return 3; + case SCC_HIR_TYPE_f128: + return 4; + default: + return 0; + } +} + +// 获取类型是否为有符号 +static cbool is_signed_tag(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; + default: + return false; + } +} + +// 获取无符号版本的 tag +static scc_hir_type_tag_t unsigned_tag(scc_hir_type_tag_t tag) { + switch (tag) { + case SCC_HIR_TYPE_i8: + case SCC_HIR_TYPE_u8: + return SCC_HIR_TYPE_u8; + case SCC_HIR_TYPE_i16: + case SCC_HIR_TYPE_u16: + return SCC_HIR_TYPE_u16; + case SCC_HIR_TYPE_i32: + case SCC_HIR_TYPE_u32: + return SCC_HIR_TYPE_u32; + case SCC_HIR_TYPE_i64: + case SCC_HIR_TYPE_u64: + return SCC_HIR_TYPE_u64; + case SCC_HIR_TYPE_i128: + case SCC_HIR_TYPE_u128: + return SCC_HIR_TYPE_u128; + default: + return tag; + } +} + +// 获取有符号版本的 tag +static scc_hir_type_tag_t signed_tag(scc_hir_type_tag_t tag) { + switch (tag) { + case SCC_HIR_TYPE_i8: + case SCC_HIR_TYPE_u8: + return SCC_HIR_TYPE_i8; + case SCC_HIR_TYPE_i16: + case SCC_HIR_TYPE_u16: + return SCC_HIR_TYPE_i16; + case SCC_HIR_TYPE_i32: + case SCC_HIR_TYPE_u32: + return SCC_HIR_TYPE_i32; + case SCC_HIR_TYPE_i64: + case SCC_HIR_TYPE_u64: + return SCC_HIR_TYPE_i64; + case SCC_HIR_TYPE_i128: + case SCC_HIR_TYPE_u128: + return SCC_HIR_TYPE_i128; + default: + return tag; + } +} + +// 通过 tag 快速创建类型引用 +static scc_hir_type_ref_t make_type(scc_ast2ir_ctx_t *ctx, + scc_hir_type_tag_t tag) { + scc_hir_type_t desc; + scc_hir_type_init(&desc, tag); + return scc_hir_builder_type(&ctx->builder, &desc); +} + +/** + * @brief 整数提升(C11 6.3.1.1) + * + * 如果 int 可以表示原始类型的所有值,则提升为 int; + * 否则提升为 unsigned int。 + * + * 对于秩 >= int 的类型,不做提升。 + */ +scc_hir_type_ref_t scc_ast2ir_integer_promotion(scc_ast2ir_ctx_t *ctx, + scc_hir_type_ref_t type_ref) { + scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); + scc_hir_type_t *type = scc_hir_module_get_type(module, type_ref); + if (type == nullptr || !is_integer_type(type)) + return 0; + + int rank = integer_tag_rank(type->tag); + + // 秩 >= int(rank >= 3),无需提升 + if (rank >= 3) + return 0; + + return make_type(ctx, SCC_HIR_TYPE_i32); +} + +/** + * @brief 寻常算术转换(C11 6.3.1.8) + * + * 确定二元算术操作中两个操作数的公共类型。 + * + * 规则: + * 1. 如果任一操作数是 long double,另一操作数转换为 long double + * 2. 如果任一操作数是 double,另一操作数转换为 double + * 3. 如果任一操作数是 float,另一操作数转换为 float + * 4. 否则,对两个操作数应用整数提升,然后: + * a. 如果两个类型相同,无需转换 + * b. 如果两个都是有符号或无符号,较小秩的转换为较大秩的 + * c. 如果无符号类型的秩 >= 有符号类型的秩,有符号转换为无符号 + * d. 如果有符号类型可以表示无符号类型的所有值,无符号转换为有符号 + * e. 否则,两个都转换为有符号类型的无符号版本 + */ +scc_hir_type_ref_t scc_ast2ir_usual_arithmetic_conversion( + scc_ast2ir_ctx_t *ctx, scc_hir_type_ref_t t1_ref, + scc_hir_type_ref_t t2_ref) { + scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); + scc_hir_type_t *t1 = scc_hir_module_get_type(module, t1_ref); + scc_hir_type_t *t2 = scc_hir_module_get_type(module, t2_ref); + + // --- 浮点类型处理 --- + if (is_floating_type(t1) || is_floating_type(t2)) { + int r1 = is_floating_type(t1) ? floating_rank(t1) : 0; + int r2 = is_floating_type(t2) ? floating_rank(t2) : 0; + scc_hir_type_tag_t wider = (r1 >= r2) ? t1->tag : t2->tag; + return make_type(ctx, wider); + } + + // --- 整数类型处理 --- + // 应用整数提升:得到提升后的 tag + scc_hir_type_ref_t p1_ref = scc_ast2ir_integer_promotion(ctx, t1_ref); + scc_hir_type_ref_t p2_ref = scc_ast2ir_integer_promotion(ctx, t2_ref); + + scc_hir_type_tag_t tag1 = + (p1_ref != 0) + ? scc_hir_module_get_type(module, p1_ref)->tag + : t1->tag; + scc_hir_type_tag_t tag2 = + (p2_ref != 0) + ? scc_hir_module_get_type(module, p2_ref)->tag + : t2->tag; + + // 如果提升后相同,直接返回 + if (tag1 == tag2) + return make_type(ctx, tag1); + + cbool s1 = is_signed_tag(tag1); + cbool s2 = is_signed_tag(tag2); + int r1 = integer_tag_rank(tag1); + int r2 = integer_tag_rank(tag2); + + // 两个都是有符号,或两个都是无符号:较小秩转换为较大秩 + if (s1 == s2) { + return make_type(ctx, (r1 >= r2) ? tag1 : tag2); + } + + // 一个有符号一个无符号 + scc_hir_type_tag_t unsigned_t = + s1 ? unsigned_tag(tag1) : unsigned_tag(tag2); + scc_hir_type_tag_t signed_t = s1 ? tag1 : tag2; + scc_hir_type_tag_t unsigned_other = s1 ? tag2 : tag1; // 无符号的那个 + int unsigned_rank = integer_tag_rank(unsigned_other); + + // 如果无符号类型的秩 >= 有符号类型的秩:有符号转换为无符号 + if (unsigned_rank >= integer_tag_rank(signed_t)) { + return make_type(ctx, unsigned_t); + } + + // 如果有符号类型可以表示无符号类型的所有值:无符号转换为有符号 + if (integer_tag_rank(signed_t) > integer_tag_rank(unsigned_other)) { + return make_type(ctx, signed_t); + } + + return make_type(ctx, unsigned_tag(signed_t)); +} + +/** + * @brief 确定类型转换的种类 + * + * 根据源类型和目标类型选择合适的转换方式: + * - SEXT: 源有符号且目标更大 + * - ZEXT: 源无符号且目标更大 + * - TRUNC: 目标更小 + * - 返回 -1 表示无需转换(同类型同大小) + */ +static int determine_conv_kind(scc_hir_type_tag_t src, scc_hir_type_tag_t dst) { + if (src == dst) + return -1; + + static const int size_map[] = { + [SCC_HIR_TYPE_i8] = 1, [SCC_HIR_TYPE_u8] = 1, + [SCC_HIR_TYPE_i16] = 2, [SCC_HIR_TYPE_u16] = 2, + [SCC_HIR_TYPE_i32] = 4, [SCC_HIR_TYPE_u32] = 4, + [SCC_HIR_TYPE_i64] = 8, [SCC_HIR_TYPE_u64] = 8, + [SCC_HIR_TYPE_i128] = 16, [SCC_HIR_TYPE_u128] = 16, + [SCC_HIR_TYPE_f32] = 4, [SCC_HIR_TYPE_f64] = 8, + }; + + cbool src_float = (src == SCC_HIR_TYPE_f32 || src == SCC_HIR_TYPE_f64); + cbool dst_float = (dst == SCC_HIR_TYPE_f32 || dst == SCC_HIR_TYPE_f64); + + if (src_float && dst_float) { + if (size_map[src] < size_map[dst]) + return SCC_HIR_CONV_SEXT; + else + return SCC_HIR_CONV_TRUNC; + } + + if (src_float && !dst_float) + return SCC_HIR_CONV_SEXT; + + if (!src_float && dst_float) + return SCC_HIR_CONV_SEXT; + + int src_size = size_map[src]; + int dst_size = size_map[dst]; + + if (dst_size > src_size) { + return is_signed_tag(src) ? SCC_HIR_CONV_SEXT : SCC_HIR_CONV_ZEXT; + } else if (dst_size < src_size) { + return SCC_HIR_CONV_TRUNC; + } else { + return -1; + } +} + +/** + * @brief 插入类型转换指令 + * + * 在 IR 中插入一个 conv 节点将 value 转换为 target_type。 + * 自动选择 SEXT/ZEXT/TRUNC 或直接返回(无需转换时)。 + */ +scc_hir_value_ref_t scc_ast2ir_emit_conversion(scc_ast2ir_ctx_t *ctx, + scc_hir_value_ref_t value, + scc_hir_type_ref_t target_type) { + scc_hir_module_t *module = scc_ast2ir_mir_module(ctx); + scc_hir_type_t *src_type = + scc_hir_module_get_type_by_value(module, value); + scc_hir_type_t *dst_type = + scc_hir_module_get_type(module, target_type); + + if (src_type == nullptr || dst_type == nullptr) + return value; + + if (src_type->tag == dst_type->tag) + return value; + + int kind = determine_conv_kind(src_type->tag, dst_type->tag); + if (kind < 0) + return value; + + return scc_hir_builder_conv(&ctx->builder, value, target_type, kind); +} diff --git a/libs/ir/hir/include/scc_hir_builder.h b/libs/ir/hir/include/scc_hir_builder.h index a9c8fe1..df63d58 100644 --- a/libs/ir/hir/include/scc_hir_builder.h +++ b/libs/ir/hir/include/scc_hir_builder.h @@ -143,6 +143,17 @@ scc_hir_builder_integer(scc_hir_builder_t *builder, scc_hir_type_ref_t type, scc_hir_value_ref_t scc_hir_builder_const_string(scc_hir_builder_t *builder, const char *str, usize len); +/** + * @brief 创建类型转换指令(SEXT/ZEXT/TRUNC) + * @param operand 被转换的值 + * @param target_type 目标类型 + * @param conv_kind 转换种类(SCC_HIR_CONV_SEXT/ZEXT/TRUNC) + */ +scc_hir_value_ref_t scc_hir_builder_conv(scc_hir_builder_t *builder, + scc_hir_value_ref_t operand, + scc_hir_type_ref_t target_type, + int conv_kind); + /** * @brief 开始构建函数 * @param func_ref 函数引用 @@ -171,6 +182,21 @@ scc_hir_func_ref_t scc_hir_builder_current_func(scc_hir_builder_t *builder); scc_hir_bblock_ref_t scc_hir_builder_bblock(scc_hir_builder_t *builder, const char *label); +/** + * @brief 创建一个新的基本块(仅分配对象,不添加到当前函数的基本块列表) + * @param label 基本块标签(可为 nullptr) + * @return 基本块引用(真实 ID) + */ +scc_hir_bblock_ref_t scc_hir_builder_create_bblock(scc_hir_builder_t *builder, + const char *label); + +/** + * @brief 将指定基本块追加到当前函数的基本块列表末尾 + * @param bblock 基本块引用 + */ +void scc_hir_builder_append_bblock(scc_hir_builder_t *builder, + scc_hir_bblock_ref_t bblock); + /** * @brief 开始构建新的基本块 * @param label 基本块标签(可为nullptr,自动生成) diff --git a/libs/ir/hir/include/scc_hir_def.h b/libs/ir/hir/include/scc_hir_def.h index ac3bedf..4b2d81f 100644 --- a/libs/ir/hir/include/scc_hir_def.h +++ b/libs/ir/hir/include/scc_hir_def.h @@ -176,6 +176,13 @@ typedef struct { } func; } scc_hir_builtin_t; +typedef enum { + SCC_HIR_CONV_NONE, + SCC_HIR_CONV_SEXT, + SCC_HIR_CONV_ZEXT, + SCC_HIR_CONV_TRUNC, +} scc_hir_conv_type_t; + struct scc_hir_value { scc_hir_type_ref_t type; const char *name; @@ -199,9 +206,9 @@ struct scc_hir_value { scc_hir_value_ref_t value; } global_alloc; struct { - scc_hir_value_ref_t operand; + scc_hir_value_ref_t operand; // 原始类型 scc_hir_type_ref_t target_type; // 目标类型 - enum { CONV_SEXT, CONV_ZEXT, CONV_TRUNC } conv_type; + scc_hir_conv_type_t conv_type; } conv; struct { scc_hir_value_ref_t target; @@ -250,6 +257,7 @@ typedef struct scc_hir_func_meta { scc_hir_type_ref_t type; scc_hir_value_ref_vec_t params; int defined; + cbool is_variadic; } scc_hir_func_meta_t; #define SCC_HIR_BBLOCK_VALUES(bblock) \ diff --git a/libs/ir/hir/include/scc_hir_dump.h b/libs/ir/hir/include/scc_hir_dump.h index eb142a8..cf1229b 100644 --- a/libs/ir/hir/include/scc_hir_dump.h +++ b/libs/ir/hir/include/scc_hir_dump.h @@ -11,11 +11,6 @@ typedef struct { void scc_hir_dump_init(scc_hir_dump_t *ctx, scc_tree_dump_t *tree_dump, scc_hir_cprog_t *cprog); -void scc_hir_dump_value(scc_hir_dump_t *ctx, scc_hir_value_ref_t node_ref); -void scc_hir_dump_type(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref); -void scc_hir_dump_bblock(scc_hir_dump_t *ctx, scc_hir_bblock_ref_t bblock_ref); -void scc_hir_dump_func(scc_hir_dump_t *ctx, scc_hir_func_ref_t func_ref); -void scc_hir_dump_cprog(scc_hir_dump_t *ctx); void scc_hir_dump_cprog_linear(scc_hir_dump_t *ctx); #endif /* __SCC_HIR_DUMP_H__ */ diff --git a/libs/ir/hir/src/scc_hir.c b/libs/ir/hir/src/scc_hir.c index 88a2cba..f509725 100644 --- a/libs/ir/hir/src/scc_hir.c +++ b/libs/ir/hir/src/scc_hir.c @@ -56,6 +56,8 @@ void scc_hir_func_init(scc_hir_func_t *in, const char *name) { in->name = name; scc_hir_func_meta_t *meta = SCC_HIR_FUNC_META(in); meta->type = SCC_HIR_REF_nullptr; + meta->is_variadic = false; + meta->defined = false; scc_vec_init(in->bblocks); scc_vec_init(meta->params); } @@ -110,6 +112,11 @@ void scc_hir_value_init(scc_hir_value_t *in, const char *name, case SCC_HIR_VALUE_TAG_RET: in->data.ret.ret_val = 0; break; + case SCC_HIR_VALUE_TAG_CONV: + in->data.conv.conv_type = SCC_HIR_CONV_NONE; + in->data.conv.operand = 0; + in->data.conv.target_type = 0; + break; default: UNREACHABLE(); break; diff --git a/libs/ir/hir/src/scc_hir_builder.c b/libs/ir/hir/src/scc_hir_builder.c index 74fb7c6..11c3abc 100644 --- a/libs/ir/hir/src/scc_hir_builder.c +++ b/libs/ir/hir/src/scc_hir_builder.c @@ -188,7 +188,6 @@ scc_hir_func_ref_t scc_hir_builder_func(scc_hir_builder_t *builder, // 创建新函数 scc_hir_func_t func; scc_hir_func_meta_t *meta = scc_malloc(sizeof(scc_hir_func_meta_t)); - meta->defined = 0; Assert(meta != nullptr); func.meta = meta; scc_hir_func_init(&func, name); @@ -231,6 +230,37 @@ scc_hir_bblock_ref_t scc_hir_builder_bblock(scc_hir_builder_t *builder, return bblock_ref; } +scc_hir_bblock_ref_t scc_hir_builder_create_bblock(scc_hir_builder_t *builder, + const char *label) { + SCC_HIR_BUILDER_CHECK_NO_BORROW(builder); + scc_hir_bblock_t bblock = {0}; + if (label) { + bblock.name = label; + } + bblock.meta = nullptr; + scc_vec_init(*SCC_HIR_BBLOCK_VALUES(&bblock)); + // 直接添加到模块,获得真实 ID,但不挂载到当前函数 + return scc_hir_module_add_bblock(scc_hir_builder_get_module(builder), + &bblock); +} + +void scc_hir_builder_append_bblock(scc_hir_builder_t *builder, + scc_hir_bblock_ref_t bblock) { + SCC_HIR_BUILDER_CHECK_NO_BORROW(builder); + scc_hir_func_t *func = scc_hir_module_get_func( + scc_hir_builder_get_module(builder), builder->current_func); + if (!func) { + LOG_ERROR("No current function"); + return; + } + // FIXME 检查是否已经挂载过(可选,防止重复挂载) + for (usize i = 0; i < func->bblocks.size; i++) { + if (func->bblocks.data[i] == bblock) + return; + } + scc_vec_push(func->bblocks, bblock); +} + scc_hir_type_ref_t scc_hir_builder_type(scc_hir_builder_t *builder, const scc_hir_type_t *type_desc) { SCC_HIR_BUILDER_CHECK_NO_BORROW(builder); @@ -270,15 +300,55 @@ scc_hir_value_ref_t scc_hir_builder_const_string(scc_hir_builder_t *builder, .type = array_type_ref, .data.const_array.base_type = u8_type, }; - char *buff = scc_malloc(len - 1); - Assert(buff); + scc_str_t buf; + scc_str_init(&buf); // FIXME content to real string for (usize i = 1; i < len - 1; i++) { - buff[i - 1] = str[i]; + if (str[i] != '\\') { + scc_str_append_ch(&buf, str[i]); + } else { + if (i + 1 < len) { + i += 1; + switch (str[i]) { + case 'a': + scc_str_append_ch(&buf, '\a'); + break; + case 'b': + scc_str_append_ch(&buf, '\b'); + break; + case 'f': + scc_str_append_ch(&buf, '\f'); + break; + case 'n': + scc_str_append_ch(&buf, '\n'); + break; + case 't': + scc_str_append_ch(&buf, '\t'); + break; + case 'r': + scc_str_append_ch(&buf, '\r'); + break; + case '\\': + scc_str_append_ch(&buf, '\\'); + break; + case '"': + scc_str_append_ch(&buf, '"'); + break; + default: + LOG_WARN("Unknown escape sequence: \\%c", str[i]); + scc_str_append_ch(&buf, str[i]); + break; + } + } else { + scc_str_append_ch(&buf, '\\'); + LOG_ERROR("invalid escape character"); + } + } } - buff[len - 2] = '\0'; + scc_str_append_ch(&buf, '\0'); + usize buf_len = scc_str_len(&buf); scc_vec_unsafe_from_buffer(const_array_value.data.const_array.fields, - (u8 *)buff, len - 1); + (u8 *)scc_str_move_cstr(&buf), buf_len); scc_hir_value_ref_t const_array_ref = scc_hir_module_add_value(GET_MODULE(builder), &const_array_value); Assert(const_array_ref != SCC_HIR_REF_nullptr); @@ -293,6 +363,23 @@ scc_hir_value_ref_t scc_hir_builder_const_string(scc_hir_builder_t *builder, return pointer_to_global_value; } +scc_hir_value_ref_t scc_hir_builder_conv(scc_hir_builder_t *builder, + scc_hir_value_ref_t operand, + scc_hir_type_ref_t target_type, + int conv_kind) { + Assert(builder != nullptr); + scc_hir_value_t value; + scc_hir_value_init(&value, nullptr, SCC_HIR_VALUE_TAG_CONV); + value.type = target_type; + value.data.conv.operand = operand; + value.data.conv.target_type = target_type; + value.data.conv.conv_type = conv_kind; + scc_hir_value_ref_t ref = + scc_hir_module_add_value(&builder->cprog->module, &value); + scc_hir_builder_add_instr(builder, ref); + return ref; +} + void scc_hir_builder_begin_func(scc_hir_builder_t *builder, scc_hir_func_ref_t func_ref) { SCC_HIR_BUILDER_CHECK_NO_BORROW(builder); diff --git a/libs/ir/hir/src/scc_hir_dump.c b/libs/ir/hir/src/scc_hir_dump.c index 645173c..f9a5dc3 100644 --- a/libs/ir/hir/src/scc_hir_dump.c +++ b/libs/ir/hir/src/scc_hir_dump.c @@ -3,9 +3,13 @@ #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); + +void scc_hir_dump_init(scc_hir_dump_t *ctx, scc_tree_dump_t *td, + scc_hir_cprog_t *cprog) { + ctx->dump_ctx = td; + ctx->cprog = cprog; +} + static const char *get_node_type_str(scc_hir_value_tag_t tag) { static const char *node_types[] = { [SCC_HIR_VALUE_TAG_NULLPTR] = "NullPtr", @@ -71,337 +75,6 @@ static const char *get_type_tag_str(scc_hir_type_tag_t tag) { return ""; } -static inline void dump_child_node_ref(scc_hir_dump_t *ctx, - scc_hir_value_ref_t child, - cbool is_last) { - if (!child) - return; - scc_tree_dump_push(ctx->dump_ctx, is_last); - scc_hir_dump_value(ctx, child); - scc_tree_dump_pop(ctx->dump_ctx); -} - -static void dump_integer_node(scc_hir_dump_t *ctx, - const scc_hir_value_t *value) { - scc_tree_dump_push(ctx->dump_ctx, true); - scc_tree_dump_begin_line(ctx->dump_ctx); - // FIXME hack it - scc_tree_dump_value(ctx->dump_ctx, "%d", value->data.integer.data.digit); - scc_tree_dump_pop(ctx->dump_ctx); -} - -static void dump_op_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) { - scc_tree_dump_push(ctx->dump_ctx, false); - scc_tree_dump_begin_line(ctx->dump_ctx); - scc_tree_dump_node(ctx->dump_ctx, "op: "); - scc_tree_dump_value(ctx->dump_ctx, "%s", get_op_str(value->data.op.op)); - scc_tree_dump_pop(ctx->dump_ctx); - - if (value->data.op.lhs) - dump_child_node_ref(ctx, value->data.op.lhs, - value->data.op.rhs ? false : true); - if (value->data.op.rhs) - dump_child_node_ref(ctx, value->data.op.rhs, true); -} - -static void dump_load_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) { - if (value->data.load.target) - dump_child_node_ref(ctx, value->data.load.target, true); -} - -static void dump_store_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) { - if (value->data.store.target) - dump_child_node_ref(ctx, value->data.store.target, false); - if (value->data.store.value) - dump_child_node_ref(ctx, value->data.store.value, true); -} - -static void dump_get_elem_ptr_node(scc_hir_dump_t *ctx, - const scc_hir_value_t *value) { - if (value->data.get_elem_ptr.src_addr) - dump_child_node_ref(ctx, value->data.get_elem_ptr.src_addr, false); - if (value->data.get_elem_ptr.index) - dump_child_node_ref(ctx, value->data.get_elem_ptr.index, true); -} - -static void dump_branch_node(scc_hir_dump_t *ctx, - const scc_hir_value_t *value) { - if (value->data.branch.cond) - dump_child_node_ref(ctx, value->data.branch.cond, false); - - if (value->data.branch.true_bblock) { - scc_hir_bblock_t *true_bblock = scc_hir_module_get_bblock( - GET_MODULE(ctx), value->data.branch.true_bblock); - if (true_bblock) { - scc_tree_dump_begin_line(ctx->dump_ctx); - scc_tree_dump_node(ctx->dump_ctx, "TrueBlock: "); - scc_tree_dump_value(ctx->dump_ctx, "'%s'", - true_bblock->name ? true_bblock->name - : ""); - } - } - if (value->data.branch.false_bblock) { - scc_hir_bblock_t *false_bblock = scc_hir_module_get_bblock( - GET_MODULE(ctx), value->data.branch.false_bblock); - if (false_bblock) { - scc_tree_dump_begin_line(ctx->dump_ctx); - scc_tree_dump_node(ctx->dump_ctx, "FalseBlock: "); - scc_tree_dump_value(ctx->dump_ctx, "'%s'", - false_bblock->name ? false_bblock->name - : ""); - } - } -} - -static void dump_jump_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) { - scc_tree_dump_begin_line(ctx->dump_ctx); - if (value->data.jump.target_bblock) { - scc_hir_bblock_t *target = scc_hir_module_get_bblock( - GET_MODULE(ctx), value->data.jump.target_bblock); - if (target) - scc_tree_dump_value(ctx->dump_ctx, "to '%s'", - target->name ? target->name : ""); - else - scc_tree_dump_value(ctx->dump_ctx, "to invalid block"); - } else { - scc_tree_dump_value(ctx->dump_ctx, "to nullptr"); - } -} - -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.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 : "") - : ""); - } else { - scc_tree_dump_value(ctx->dump_ctx, "func=nullptr"); - } - - for (usize i = 0; i < scc_vec_size(value->data.call.args); i++) { - cbool is_last = (i + 1 == scc_vec_size(value->data.call.args)); - scc_tree_dump_push(ctx->dump_ctx, is_last); - scc_hir_value_ref_t arg = scc_vec_at(value->data.call.args, i); - dump_child_node_ref(ctx, arg, is_last); - scc_tree_dump_pop(ctx->dump_ctx); - } -} - -static void dump_ret_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) { - if (value->data.ret.ret_val) - dump_child_node_ref(ctx, value->data.ret.ret_val, true); -} - -void scc_hir_dump_init(scc_hir_dump_t *ctx, scc_tree_dump_t *td, - scc_hir_cprog_t *cprog) { - ctx->dump_ctx = td; - ctx->cprog = cprog; -} - -void scc_hir_dump_value(scc_hir_dump_t *ctx, scc_hir_value_ref_t value_ref) { - scc_hir_value_t *value = - scc_hir_module_get_value(GET_MODULE(ctx), value_ref); - if (!value) { - LOG_ERROR("Invalid value ref"); - return; - } - - scc_tree_dump_begin_line(ctx->dump_ctx); - scc_tree_dump_node(ctx->dump_ctx, "%s", get_node_type_str(value->tag)); - if (value->name && value->name[0]) - scc_tree_dump_value(ctx->dump_ctx, " [%s]", value->name); - if (value->type) { - scc_hir_type_t *type = - scc_hir_module_get_type(GET_MODULE(ctx), value->type); - if (type) { - scc_tree_dump_append(ctx->dump_ctx, " : "); - scc_tree_dump_value(ctx->dump_ctx, "%s", - get_type_tag_str(type->tag)); - } - } - - switch (value->tag) { - case SCC_HIR_VALUE_TAG_INTEGER: - dump_integer_node(ctx, value); - break; - case SCC_HIR_VALUE_TAG_ALLOC: - break; - case SCC_HIR_VALUE_TAG_LOAD: - dump_load_node(ctx, value); - break; - case SCC_HIR_VALUE_TAG_STORE: - dump_store_node(ctx, value); - break; - case SCC_HIR_VALUE_TAG_GET_ELEM_PTR: - dump_get_elem_ptr_node(ctx, value); - break; - case SCC_HIR_VALUE_TAG_OP: - dump_op_node(ctx, value); - break; - case SCC_HIR_VALUE_TAG_BRANCH: - dump_branch_node(ctx, value); - break; - case SCC_HIR_VALUE_TAG_JUMP: - dump_jump_node(ctx, value); - break; - case SCC_HIR_VALUE_TAG_CALL: - dump_call_node(ctx, value); - break; - case SCC_HIR_VALUE_TAG_RET: - dump_ret_node(ctx, value); - break; - default: - scc_tree_dump_value(ctx->dump_ctx, "unknown"); - scc_tree_dump_append_fmt(ctx->dump_ctx, " tag(%d)", value->tag); - break; - } -} -void scc_hir_dump_type(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref) { - 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"); - return; - } - scc_hir_bblock_t *bblock = - scc_hir_module_get_bblock(GET_MODULE(ctx), bblock_ref); - if (!bblock) { - LOG_ERROR("invalid bblock ref"); - return; - } - scc_tree_dump_begin_line(ctx->dump_ctx); - scc_tree_dump_node(ctx->dump_ctx, "BasicBlock: "); - scc_tree_dump_value(ctx->dump_ctx, "'%s'", - bblock->name ? bblock->name : ""); - scc_tree_dump_append(ctx->dump_ctx, "\n"); - - scc_hir_value_ref_vec_t *values = SCC_HIR_BBLOCK_VALUES(bblock); - scc_vec_foreach(*values, i) { - cbool is_last = (i + 1 == scc_vec_size(*values)); - scc_tree_dump_push(ctx->dump_ctx, is_last); - scc_hir_dump_value(ctx, scc_vec_at(*values, i)); - scc_tree_dump_pop(ctx->dump_ctx); - } -} - -void scc_hir_dump_func(scc_hir_dump_t *ctx, scc_hir_func_ref_t func_ref) { - scc_hir_func_t *func = scc_hir_module_get_func(GET_MODULE(ctx), func_ref); - if (!ctx || !func) { - LOG_ERROR("invalid parameter"); - return; - } - scc_tree_dump_begin_line(ctx->dump_ctx); - scc_tree_dump_node(ctx->dump_ctx, "Function: "); - scc_tree_dump_value(ctx->dump_ctx, "'%s'", - func->name ? func->name : ""); - scc_tree_dump_append(ctx->dump_ctx, "\n"); - - if (SCC_HIR_FUNC_META(func)->type) { - scc_tree_dump_push(ctx->dump_ctx, false); - scc_hir_dump_type(ctx, SCC_HIR_FUNC_META(func)->type); - scc_tree_dump_pop(ctx->dump_ctx); - } - for (usize i = 0; i < scc_vec_size(SCC_HIR_FUNC_META(func)->params); i++) { - cbool is_last = - (i + 1 == scc_vec_size(SCC_HIR_FUNC_META(func)->params)); - scc_tree_dump_push(ctx->dump_ctx, is_last); - scc_hir_dump_value(ctx, scc_vec_at(SCC_HIR_FUNC_META(func)->params, i)); - scc_tree_dump_pop(ctx->dump_ctx); - } - for (usize i = 0; i < scc_vec_size(func->bblocks); i++) { - cbool is_last = (i + 1 == scc_vec_size(func->bblocks)); - scc_tree_dump_push(ctx->dump_ctx, is_last); - scc_hir_dump_bblock(ctx, scc_vec_at(func->bblocks, i)); - scc_tree_dump_pop(ctx->dump_ctx); - } -} - -void scc_hir_dump_cprog(scc_hir_dump_t *ctx) { - scc_tree_dump_node(ctx->dump_ctx, "Func defs:\n"); - scc_vec_foreach(ctx->cprog->func_defs, i) { - cbool is_last = (i + 1 == scc_vec_size(ctx->cprog->func_defs)); - scc_tree_dump_push(ctx->dump_ctx, is_last); - scc_hir_dump_func(ctx, scc_vec_at(ctx->cprog->func_defs, i)); - scc_tree_dump_pop(ctx->dump_ctx); - } -} - -// ----- 线性输出(保留原逻辑,改用新 API)----- - -// 在 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) { @@ -653,7 +326,7 @@ void scc_hir_dump_value_linear(scc_hir_dump_t *ctx, scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s", value->name); scc_tree_dump_begin_line(ctx->dump_ctx); scc_hir_dump_value_linear(ctx, value->data.global_alloc.value); - return; + break; case SCC_HIR_VALUE_TAG_ARRAY: scc_tree_dump_append(ctx->dump_ctx, "const_array "); scc_hir_dump_type_linear(ctx, value->data.const_array.base_type); @@ -664,6 +337,19 @@ void scc_hir_dump_value_linear(scc_hir_dump_t *ctx, } scc_tree_dump_append(ctx->dump_ctx, " ]"); break; + case SCC_HIR_VALUE_TAG_CONV: + static const char *conv_name[] = { + [SCC_HIR_CONV_NONE] = "null", + [SCC_HIR_CONV_SEXT] = "sext", + [SCC_HIR_CONV_ZEXT] = "zext", + [SCC_HIR_CONV_TRUNC] = "trunc", + }; + scc_tree_dump_append_fmt(ctx->dump_ctx, "conv.%s(", + conv_name[value->data.conv.conv_type]); + scc_hir_dump_type_linear(ctx, value->data.conv.target_type); + scc_tree_dump_append(ctx->dump_ctx, ") "); + format_ref_or_value(ctx, value->data.conv.operand); + break; default: scc_tree_dump_append_fmt(ctx->dump_ctx, "<%s value %u>", get_node_type_str(value->tag), value_ref); @@ -706,24 +392,8 @@ void scc_hir_dump_func_linear(scc_hir_dump_t *ctx, scc_hir_func_ref_t func_ref, (func->name && func->name[0]) ? func->name : ""); - if (scc_vec_size(SCC_HIR_FUNC_META(func)->params) > 0) { - scc_tree_dump_append(ctx->dump_ctx, "("); - for (usize i = 0; i < scc_vec_size(SCC_HIR_FUNC_META(func)->params); - i++) { - if (i > 0) - scc_tree_dump_append(ctx->dump_ctx, ", "); - scc_hir_value_ref_t param_ref = - scc_vec_at(SCC_HIR_FUNC_META(func)->params, i); - scc_hir_value_t *param_node = - scc_hir_module_get_value(GET_MODULE(ctx), param_ref); - scc_tree_dump_append(ctx->dump_ctx, "%"); - if (param_node && param_node->name && param_node->name[0] != '\0') - scc_tree_dump_append_fmt(ctx->dump_ctx, "%u[%s]", param_ref, - param_node->name); - else - scc_tree_dump_append_fmt(ctx->dump_ctx, "%u", param_ref); - } - scc_tree_dump_append(ctx->dump_ctx, ")"); + if (SCC_HIR_FUNC_META(func)->is_variadic) { + scc_tree_dump_append(ctx->dump_ctx, "(...)"); } else { scc_tree_dump_append(ctx->dump_ctx, "()"); } diff --git a/libs/ir/lir/include/scc_lir.h b/libs/ir/lir/include/scc_lir.h index 6bd4c5d..ae02b63 100644 --- a/libs/ir/lir/include/scc_lir.h +++ b/libs/ir/lir/include/scc_lir.h @@ -135,6 +135,9 @@ typedef enum { /* 栈管理 */ SCC_LIR_ALLOCA, + /* 类型扩展 */ + SCC_LIR_EXTEND, + SCC_LIR_NOP } scc_lir_op_t; @@ -208,6 +211,10 @@ typedef struct scc_lir_ins { int align_bytes; } alloca; + struct scc_lir_extend { + int from_size; // 源类型宽度(字节) + } extend; + struct { scc_lir_val_t ap; scc_lir_val_t last; diff --git a/libs/ir/lir/src/scc_hir2lir.c b/libs/ir/lir/src/scc_hir2lir.c index 8b8b857..3fdefdc 100644 --- a/libs/ir/lir/src/scc_hir2lir.c +++ b/libs/ir/lir/src/scc_hir2lir.c @@ -428,21 +428,37 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value, scc_lir_builder_add_instr(ctx, &instr); } break; case SCC_HIR_VALUE_TAG_CONV: { - // 类型转换:使用 MOV 指令配合扩展/截断 + // 类型转换:使用 LIR_EXTEND 指令实现符号/零扩展 scc_lir_val_t src = ir_value_to_lir_operand(ctx, value->data.conv.operand); scc_lir_ext_t conv_ext = SCC_LIR_EXT_NONE; - if (value->data.conv.conv_type == CONV_SEXT) + if (value->data.conv.conv_type == SCC_HIR_CONV_SEXT) conv_ext = SCC_LIR_EXT_SEXT; - else if (value->data.conv.conv_type == CONV_ZEXT) + else if (value->data.conv.conv_type == SCC_HIR_CONV_ZEXT) conv_ext = SCC_LIR_EXT_ZEXT; - // TRUNC 用 NONE 即可(MOV 截断) - scc_lir_instr_t instr = {.op = SCC_LIR_MOV, - .size = size, - .ext = conv_ext, - .to = SCC_LIR_VREG(dst_vreg), - .arg0 = src}; - scc_lir_builder_add_instr(ctx, &instr); + // TRUNC 用 SCC_LIR_MOV 截断 + if (value->data.conv.conv_type == SCC_HIR_CONV_TRUNC) { + scc_lir_instr_t instr = {.op = SCC_LIR_MOV, + .size = size, + .to = SCC_LIR_VREG(dst_vreg), + .arg0 = src}; + scc_lir_builder_add_instr(ctx, &instr); + } else { + // 计算源类型宽度 + scc_hir_type_t *src_type = scc_hir_module_get_type( + ctx->hir_module, + scc_hir_module_get_value(ctx->hir_module, + value->data.conv.operand) + ->type); + int from_size = scc_hir_module_type_size(ctx->hir_module, src_type); + scc_lir_instr_t instr = {.op = SCC_LIR_EXTEND, + .size = size, + .ext = conv_ext, + .to = SCC_LIR_VREG(dst_vreg), + .arg0 = src, + .metadata.extend.from_size = from_size}; + scc_lir_builder_add_instr(ctx, &instr); + } } break; case SCC_HIR_VALUE_TAG_BUILTIN: { scc_hir_builtin_t *b = &value->data.builtin; @@ -542,7 +558,7 @@ static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) { .attr = SCC_LIR_ATTR_NONE, .frame_size = 0, .vregs_count = 0, - .is_va_arg = false, + .is_va_arg = func_meta->is_variadic, }; scc_vec_push(ctx->lir_module->func_metas, lir_func_meta); ctx->current_func = ir_func; diff --git a/libs/ir/lir/src/scc_lir_dump.c b/libs/ir/lir/src/scc_lir_dump.c index 0c8dc78..3643fba 100644 --- a/libs/ir/lir/src/scc_lir_dump.c +++ b/libs/ir/lir/src/scc_lir_dump.c @@ -7,134 +7,65 @@ #include static const char *op_to_string(scc_lir_op_t op) { - switch (op) { - case SCC_LIR_MOV: - return "mov"; - case SCC_LIR_LOAD: - return "load"; - case SCC_LIR_LOAD_ADDR: - return "load.addr"; - case SCC_LIR_STORE: - return "store"; - // case SCC_LIR_STORE_ADDR: - // return "store.addr"; - case SCC_LIR_ADD: - return "add"; - case SCC_LIR_SUB: - return "sub"; - case SCC_LIR_MUL: - return "mul"; - case SCC_LIR_DIV_S: - return "div.s"; - case SCC_LIR_DIV_U: - return "div.u"; - case SCC_LIR_REM_S: - return "rem.s"; - case SCC_LIR_REM_U: - return "rem.u"; - case SCC_LIR_AND: - return "and"; - case SCC_LIR_OR: - return "or"; - case SCC_LIR_XOR: - return "xor"; - case SCC_LIR_SHL: - return "shl"; - case SCC_LIR_SHR: - return "shr"; - case SCC_LIR_SAR: - return "sar"; - case SCC_LIR_NEG: - return "neg"; - case SCC_LIR_NOT: - return "not"; - case SCC_LIR_FADD: - return "fadd"; - case SCC_LIR_FSUB: - return "fsub"; - case SCC_LIR_FMUL: - return "fmul"; - case SCC_LIR_FDIV: - return "fdiv"; - case SCC_LIR_FNEG: - return "fneg"; - case SCC_LIR_FCVT: - return "fcvt"; - case SCC_LIR_CMP: - return "cmp"; - case SCC_LIR_BR: - return "br"; - case SCC_LIR_JMP: - return "jmp"; - case SCC_LIR_JMP_INDIRECT: - return "jmp.indirect"; - case SCC_LIR_CALL: - return "call"; - case SCC_LIR_CALL_INDIRECT: - return "call.indirect"; - case SCC_LIR_RET: - return "ret"; - case SCC_LIR_PARALLEL_COPY: - return "parallel_copy"; - case SCC_LIR_VA_START: - return "va_start"; - case SCC_LIR_VA_ARG: - return "va_arg"; - case SCC_LIR_VA_END: - return "va_end"; - case SCC_LIR_VA_COPY: - return "va_copy"; - case SCC_LIR_ALLOCA: - return "alloca"; - - case SCC_LIR_MEMCPY: - return "memcpy"; - case SCC_LIR_MEMSET: - return "memset"; - case SCC_LIR_NOP: - return "nop"; - default: - return "???"; - } + static const char *op_names[] = { + [SCC_LIR_MOV] = "mov", + [SCC_LIR_LOAD] = "load", + [SCC_LIR_LOAD_ADDR] = "load.addr", + [SCC_LIR_STORE] = "store", + [SCC_LIR_ADD] = "add", + [SCC_LIR_SUB] = "sub", + [SCC_LIR_MUL] = "mul", + [SCC_LIR_DIV_S] = "div.s", + [SCC_LIR_DIV_U] = "div.u", + [SCC_LIR_REM_S] = "rem.s", + [SCC_LIR_REM_U] = "rem.u", + [SCC_LIR_AND] = "and", + [SCC_LIR_OR] = "or", + [SCC_LIR_XOR] = "xor", + [SCC_LIR_SHL] = "shl", + [SCC_LIR_SHR] = "shr", + [SCC_LIR_SAR] = "sar", + [SCC_LIR_NEG] = "neg", + [SCC_LIR_NOT] = "not", + [SCC_LIR_FADD] = "fadd", + [SCC_LIR_FSUB] = "fsub", + [SCC_LIR_FMUL] = "fmul", + [SCC_LIR_FDIV] = "fdiv", + [SCC_LIR_FNEG] = "fneg", + [SCC_LIR_FCVT] = "fcvt", + [SCC_LIR_CMP] = "cmp", + [SCC_LIR_BR] = "br", + [SCC_LIR_JMP] = "jmp", + [SCC_LIR_JMP_INDIRECT] = "jmp.indirect", + [SCC_LIR_CALL] = "call", + [SCC_LIR_CALL_INDIRECT] = "call.indirect", + [SCC_LIR_RET] = "ret", + [SCC_LIR_PARALLEL_COPY] = "parallel_copy", + [SCC_LIR_VA_START] = "va_start", + [SCC_LIR_VA_ARG] = "va_arg", + [SCC_LIR_VA_END] = "va_end", + [SCC_LIR_VA_COPY] = "va_copy", + [SCC_LIR_ALLOCA] = "alloca", + [SCC_LIR_EXTEND] = "extend", + [SCC_LIR_MEMCPY] = "memcpy", + [SCC_LIR_MEMSET] = "memset", + [SCC_LIR_NOP] = "nop", + }; + return op_names[op]; } static const char *cond_to_string(scc_lir_cond_t cond) { - switch (cond) { - case SCC_LIR_COND_EQ: - return "eq"; - case SCC_LIR_COND_NE: - return "ne"; - case SCC_LIR_COND_SLT: - return "slt"; - case SCC_LIR_COND_SLE: - return "sle"; - case SCC_LIR_COND_SGT: - return "sgt"; - case SCC_LIR_COND_SGE: - return "sge"; - case SCC_LIR_COND_ULT: - return "ult"; - case SCC_LIR_COND_ULE: - return "ule"; - case SCC_LIR_COND_UGT: - return "ugt"; - case SCC_LIR_COND_UGE: - return "uge"; - case SCC_LIR_COND_FEQ: - return "feq"; - case SCC_LIR_COND_FNE: - return "fne"; - case SCC_LIR_COND_FLT: - return "flt"; - case SCC_LIR_COND_FLE: - return "fle"; - case SCC_LIR_COND_FGT: - return "fgt"; - case SCC_LIR_COND_FGE: - return "fge"; - default: - return "???"; - } + static const char *names[] = { + [SCC_LIR_COND_EQ] = "eq", [SCC_LIR_COND_NE] = "ne", + [SCC_LIR_COND_SLT] = "slt", [SCC_LIR_COND_SLE] = "sle", + [SCC_LIR_COND_SGT] = "sgt", [SCC_LIR_COND_SGE] = "sge", + [SCC_LIR_COND_ULT] = "ult", [SCC_LIR_COND_ULE] = "ule", + [SCC_LIR_COND_UGT] = "ugt", [SCC_LIR_COND_UGE] = "uge", + [SCC_LIR_COND_FEQ] = "feq", [SCC_LIR_COND_FNE] = "fne", + [SCC_LIR_COND_FLT] = "flt", [SCC_LIR_COND_FLE] = "fle", + [SCC_LIR_COND_FGT] = "fgt", [SCC_LIR_COND_FGE] = "fge", + }; + return names[cond]; } static void dump_operand(scc_lir_dump_ctx_t *ctx, const scc_lir_val_t *op) { @@ -150,9 +81,6 @@ static void dump_operand(scc_lir_dump_ctx_t *ctx, const scc_lir_val_t *op) { case SCC_LIR_INSTR_KIND_VREG: scc_tree_dump_append_fmt(td, "%%%u", op->data.reg); break; - // case SCC_LIR_INSTR_KIND_PREG: - // scc_tree_dump_append_fmt(td, "Phy%u", op->data.reg); - // break; case SCC_LIR_INSTR_KIND_IMM: // TODO hack ap scc_tree_dump_append_fmt(td, "%lld", op->data.imm.data.digit); @@ -241,6 +169,26 @@ void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { ins->metadata.alloca.align_bytes); dump_operand(ctx, &ins->to); break; + case SCC_LIR_EXTEND: { + const char *ext_name = ""; + switch (ins->ext) { + case SCC_LIR_EXT_ZEXT: + ext_name = "zext"; + break; + case SCC_LIR_EXT_SEXT: + ext_name = "sext"; + break; + default: + ext_name = "ext"; + break; + } + scc_tree_dump_append_fmt(td, "%s(%d<-%d) ", ext_name, ins->size * 8, + ins->metadata.extend.from_size * 8); + dump_operand(ctx, &ins->to); + scc_tree_dump_append(td, " <- "); + dump_operand(ctx, &ins->arg0); + break; + } // case SCC_LIR_STORE_ADDR: case SCC_LIR_STORE: dump_operand(ctx, &ins->arg0); diff --git a/libs/ir/mir/include/arch/scc_x86_mir.h b/libs/ir/mir/include/arch/scc_x86_mir.h index 66675f6..e8f6f7c 100644 --- a/libs/ir/mir/include/arch/scc_x86_mir.h +++ b/libs/ir/mir/include/arch/scc_x86_mir.h @@ -101,40 +101,6 @@ scc_mir_x86_instr_3(scc_mir_x86_instr_t *out, scc_x86_iform_t opcode, out->x86_instr.src_loc = pos; } -static inline scc_x86_iform_t -scc_mir_x86_mov_reg_mem(scc_x86_operand_value_t op0, - scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); - Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_MEM); - return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_MEMB - : SCC_X86_IFORM_MOV_GPRV_MEMV; -} -static inline scc_x86_iform_t -scc_mir_x86_mov_mem_reg(scc_x86_operand_value_t op0, - scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); - Assert(op0.kind == SCC_X86_OPR_MEM && op1.kind == SCC_X86_OPR_REG); - return op0.size == 1 ? SCC_X86_IFORM_MOV_MEMB_GPR8 - : SCC_X86_IFORM_MOV_MEMV_GPRV; -} -static inline scc_x86_iform_t -scc_mir_x86_mov_reg_reg(scc_x86_operand_value_t op0, - scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); - Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_REG); - return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_GPR8_8A - : SCC_X86_IFORM_MOV_GPRV_GPRV_8B; -} - -static inline scc_x86_iform_t -scc_mir_x86_mov_reg_imm(scc_x86_operand_value_t op0, - scc_x86_operand_value_t op1) { - Assert(op0.size == op1.size); - Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_IMM); - return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_IMMB_B0 - : SCC_X86_IFORM_MOV_GPRV_IMMV; -} - void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, scc_x86_operand_value_t dst, scc_x86_operand_value_t src); diff --git a/libs/ir/mir/include/scc_mir.h b/libs/ir/mir/include/scc_mir.h index ebeda16..533fb66 100644 --- a/libs/ir/mir/include/scc_mir.h +++ b/libs/ir/mir/include/scc_mir.h @@ -29,6 +29,7 @@ typedef struct scc_mir_stack_slot { int size; // 通常是 8 字节 (指针大小) int alignment; // 对齐要求 int offset; // 相对于 RSP 的偏移 (最终确定) + int arg_idx; // == 0 means local slot, > 0 means argument slot } scc_mir_stack_slot_t; typedef SCC_VEC(scc_mir_stack_slot_t) scc_mir_stack_slot_vec_t; diff --git a/libs/ir/mir/include/target/scc_win64.h b/libs/ir/mir/include/target/scc_win64.h index 03541c0..53088e3 100644 --- a/libs/ir/mir/include/target/scc_win64.h +++ b/libs/ir/mir/include/target/scc_win64.h @@ -8,7 +8,7 @@ void scc_win_pc_x64_abi_lowering(scc_abi_lowering_t *abi_lowering); void scc_win_pc_x64_reg_alloc_fill(scc_reg_alloc_op_t *ops); -void scc_win_pc_x64_frame_alloc_init(scc_frame_layout_t *ctx); +void scc_win_pc_x64_frame_layout_init(scc_frame_layout_t *ctx); void scc_win_pc_x64_prolog_epilog_init(scc_prolog_epilog_t *ctx); #endif diff --git a/libs/ir/mir/src/arch/scc_x86_isel.c b/libs/ir/mir/src/arch/scc_x86_isel.c index 8f1b4f5..da141bc 100644 --- a/libs/ir/mir/src/arch/scc_x86_isel.c +++ b/libs/ir/mir/src/arch/scc_x86_isel.c @@ -47,9 +47,14 @@ void scc_x86_instr_dump(scc_tree_dump_t *td, const scc_mir_func_t *func, if (slot == nullptr) { scc_tree_dump_append_fmt(td, "[slot:%d]", slot_id); } else { - scc_tree_dump_append_fmt(td, "[slot:%d(of=%d,sz=%d,al=%d)]", - slot_id, slot->offset, slot->size, - slot->alignment); + if (slot->arg_idx > 0) { + scc_tree_dump_append_fmt(td, "[slot:arg%d]", + slot->arg_idx); + } else { + scc_tree_dump_append_fmt( + td, "[slot:%d(of=%d,sz=%d,al=%d)]", slot_id, + slot->offset, slot->size, slot->alignment); + } } } else { scc_tree_dump_append(td, "("); @@ -137,29 +142,6 @@ scc_x86_operand_value_t scc_x86_lir_val_to_mir_op(scc_x86_64_isel_t *isel, return op; } -static scc_x86_operand_value_t build_mem_op(scc_x86_64_isel_t *isel, - scc_x86_operand_value_t base, - scc_x86_operand_value_t index, - int scale, i64 offset) { - (void)isel; - scc_x86_operand_value_t mem_op; - mem_op.kind = SCC_X86_OPR_MEM; - // base 必须为寄存器 - Assert(base.kind == SCC_X86_OPR_REG); - mem_op.mem.base = base.reg; - // index 可选 - if (index.kind == SCC_X86_OPR_REG) { - mem_op.mem.index = index.reg; - mem_op.mem.scale = scale; - } else { - mem_op.mem.index = SCC_X86_REG_INVALID; - mem_op.mem.scale = 1; - } - mem_op.mem.disp.displacement = offset; - mem_op.mem.disp.displacement_bits = 0; - return mem_op; -} - // 虚拟临时寄存器分配(简单递增) static scc_x86_operand_value_t new_vreg_temp(scc_x86_64_isel_t *isel, int size) { @@ -247,20 +229,21 @@ void scc_x86_emit_move(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst_reg, void scc_x86_emit_load(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, scc_x86_operand_value_t src) { + scc_x86_operand_value_t tmp_reg = dst; if (dst.kind != SCC_X86_OPR_REG) { - scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, dst.size); - scc_x86_emit_move(isel, tmp_reg, dst); - dst = tmp_reg; + tmp_reg = new_vreg_temp(isel, src.size); + } + scc_x86_emit_load_to_vec(&isel->instrs, tmp_reg, src); + if (dst.kind != SCC_X86_OPR_REG) { + scc_x86_emit_move(isel, dst, tmp_reg); } - - scc_x86_emit_load_to_vec(&isel->instrs, dst, src); } void scc_x86_emit_store(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, scc_x86_operand_value_t src) { - if (src.kind != SCC_X86_OPR_REG) { + if (src.kind == SCC_X86_OPR_MEM) { scc_x86_operand_value_t tmp_reg = new_vreg_temp(isel, src.size); - scc_x86_emit_move(isel, tmp_reg, src); + scc_x86_emit_load(isel, tmp_reg, src); src = tmp_reg; } scc_x86_emit_store_to_vec(&isel->instrs, dst, src); @@ -279,52 +262,55 @@ static void emit_load_addr(scc_x86_64_isel_t *isel, scc_x86_operand_value_t dst, // ---- 处理 base ---- scc_x86_operand_value_t base_reg = base; - if (base.kind != SCC_X86_OPR_REG) { - base_reg = new_vreg_temp(isel, size); + switch (base.kind) { + case SCC_X86_OPR_REG: { + base_reg = base; + } break; + case SCC_X86_OPR_RELOC: { + Assert(base.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL); + base_reg = new_vreg_temp(isel, 8); scc_x86_emit_move(isel, base_reg, base); + } break; + case SCC_X86_OPR_MEM: { + base_reg = new_vreg_temp(isel, 8); + scc_x86_emit_move(isel, base_reg, base); + } break; + default: { + Panic("Unsupported base kind %d in load_addr", base.kind); + } } - // ---- 处理 index * scale ---- - scc_x86_operand_value_t scaled_index = index; - Assert(index.kind != SCC_X86_OPR_NONE); - // 确保 index 在寄存器中 - if (index.kind != SCC_X86_OPR_REG) { - scc_x86_operand_value_t index_tmp = new_vreg_temp(isel, index.size); - scc_x86_emit_move(isel, index_tmp, index); - index = index_tmp; + scc_x86_operand_value_t index_reg = index; + switch (index.kind) { + case SCC_X86_OPR_REG: { + index_reg = index; + } break; + case SCC_X86_OPR_RELOC: { + Assert(index.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL); + index_reg = new_vreg_temp(isel, 8); + scc_x86_emit_move(isel, index_reg, index); + } break; + case SCC_X86_OPR_MEM: { + index_reg = new_vreg_temp(isel, 8); + scc_x86_emit_move(isel, index_reg, index); + } break; + case SCC_X86_OPR_IMM: { + index_reg = new_vreg_temp(isel, index.size); + scc_x86_emit_move(isel, index_reg, index); + } break; + default: { + Panic("Unsupported index kind %d in load_addr", base.kind); + } } - // ---- 计算 base + scaled_index ---- - scc_x86_operand_value_t sum = base_reg; - if (base_reg.kind == SCC_X86_OPR_REG && - scaled_index.kind == SCC_X86_OPR_REG) { - if (dst.reg != base_reg.reg) { - scc_x86_emit_move(isel, dst, base_reg); - sum = dst; - } - add_instr_2(isel, SCC_X86_IFORM_ADD_GPRV_GPRV_03, sum, scaled_index); - } else if (base_reg.kind == SCC_X86_OPR_REG) { - if (dst.reg != base_reg.reg) - scc_x86_emit_move(isel, dst, base_reg); - sum = dst; - } else if (scaled_index.kind == SCC_X86_OPR_REG) { - scc_x86_emit_move(isel, dst, scaled_index); - sum = dst; - } else { - // base 和 index 都无效 => 结果为 0 - scc_x86_emit_move(isel, dst, scc_x86_op_imm(0, size)); - return; - } - - // ---- 加上 offset ---- - if (offset != 0) { - scc_x86_operand_value_t mem_op = build_mem_op( - isel, sum, (scc_x86_operand_value_t){.kind = SCC_X86_OPR_NONE}, 1, - offset); - scc_x86_emit_move(isel, dst, mem_op); - } else if (sum.reg != dst.reg) { - scc_x86_emit_move(isel, dst, sum); - } + scc_x86_operand_value_t mem_op = + scc_x86_op_mem((scc_x86_mem_t){.base = base_reg.reg, + .index = index_reg.reg, + .scale = scale, + .disp.displacement = offset, + .disp.displacement_bits = 8}, + size); + scc_x86_emit_move(isel, dst, mem_op); } static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { @@ -455,8 +441,9 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { case SCC_LIR_CMP: { Assert(src0.size == src1.size); if (scc_x86_op_is_vreg(&src0) && src1.kind == SCC_X86_OPR_IMM) + // SCC_X86_IFORM_CMP_GPR8_IMMB_82R7 历史遗留指令在amd64中已不再使用 add_instr_2(isel, - src0.size == 1 ? SCC_X86_IFORM_CMP_GPR8_IMMB_82R7 + src0.size == 1 ? SCC_X86_IFORM_CMP_GPR8_IMMB_80R7 : SCC_X86_IFORM_CMP_GPRV_IMMZ, src0, src1); else if (scc_x86_op_is_vreg(&src0) && scc_x86_op_is_vreg(&src1)) @@ -519,6 +506,44 @@ static void sel_mir(scc_x86_64_isel_t *isel, const scc_lir_instr_t *instr) { break; } + /* ---- 类型扩展 ---- */ + case SCC_LIR_EXTEND: { + int from_size = instr->metadata.extend.from_size; + scc_x86_operand_value_t ext_src = + scc_x86_lir_val_to_mir_op(isel, &instr->arg0, from_size); + + if (instr->ext == SCC_LIR_EXT_ZEXT) { + if (from_size == 4) { + // 32→64: x86-64 写32位寄存器自动零扩展到64位 + scc_x86_emit_move(isel, dst, ext_src); + } else { + scc_x86_iform_t iform = (from_size == 1) + ? SCC_X86_IFORM_MOVZX_GPRV_GPR8 + : SCC_X86_IFORM_MOVZX_GPRV_GPR16; + add_instr_2(isel, iform, dst, ext_src); + } + } else if (instr->ext == SCC_LIR_EXT_SEXT) { + scc_x86_iform_t iform; + switch (from_size) { + case 1: + iform = SCC_X86_IFORM_MOVSX_GPRV_GPR8; + break; + case 2: + iform = SCC_X86_IFORM_MOVSX_GPRV_GPR16; + break; + case 4: + iform = SCC_X86_IFORM_MOVSXD_GPRV_GPRZ; + break; + default: + UNREACHABLE(); + } + add_instr_2(isel, iform, dst, ext_src); + } else { + UNREACHABLE(); + } + break; + } + /* ---- 其他(占位) ---- */ case SCC_LIR_NOP: add_instr_0(isel, SCC_X86_IFORM_NOP_90); @@ -575,11 +600,10 @@ static void sel_func(const scc_lir_module_t *lir_module, scc_cfg_module_unsafe_get_bblock(&lir_module->cfg_module, id); scc_lir_instr_vec_t *instrs = SCC_LIR_BBLOCK_VALUES(bb); scc_vec_foreach(*instrs, i) { - const scc_lir_instr_t *ins = &scc_vec_at(*instrs, i); + scc_lir_instr_t *ins = &scc_vec_at(*instrs, i); // HACK BR size - if (ins->op == SCC_LIR_CMP && i + 1 < scc_vec_size(*instrs) && - scc_vec_at(*instrs, i + 1).op == SCC_LIR_BR) { - scc_vec_at(*instrs, i + 1).size = ins->size; + if (ins->op == SCC_LIR_BR) { + ins->size = scc_vec_at(*instrs, i - 1).size; } sel_mir(isel, ins); } diff --git a/libs/ir/mir/src/arch/scc_x86_mir.c b/libs/ir/mir/src/arch/scc_x86_mir.c index 62385f4..42b43ac 100644 --- a/libs/ir/mir/src/arch/scc_x86_mir.c +++ b/libs/ir/mir/src/arch/scc_x86_mir.c @@ -1,5 +1,47 @@ #include +static inline scc_x86_iform_t +scc_mir_x86_mov_reg_mem(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_MEM); + return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_MEMB + : SCC_X86_IFORM_MOV_GPRV_MEMV; +} +static inline scc_x86_iform_t +scc_mir_x86_mov_reg_reg(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_REG); + return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_GPR8_8A + : SCC_X86_IFORM_MOV_GPRV_GPRV_8B; +} + +static inline scc_x86_iform_t +scc_mir_x86_mov_reg_imm(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_REG && op1.kind == SCC_X86_OPR_IMM); + return op0.size == 1 ? SCC_X86_IFORM_MOV_GPR8_IMMB_B0 + : SCC_X86_IFORM_MOV_GPRV_IMMV; +} +static inline scc_x86_iform_t +scc_mir_x86_mov_mem_reg(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_MEM && op1.kind == SCC_X86_OPR_REG); + return op0.size == 1 ? SCC_X86_IFORM_MOV_MEMB_GPR8 + : SCC_X86_IFORM_MOV_MEMV_GPRV; +} +static inline scc_x86_iform_t +scc_mir_x86_mov_mem_imm(scc_x86_operand_value_t op0, + scc_x86_operand_value_t op1) { + Assert(op0.size == op1.size); + Assert(op0.kind == SCC_X86_OPR_MEM && op1.kind == SCC_X86_OPR_IMM); + return op0.size == 1 ? SCC_X86_IFORM_MOV_MEMB_IMMB + : SCC_X86_IFORM_MOV_MEMV_IMMZ; +} + void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, scc_x86_operand_value_t dst, scc_x86_operand_value_t src) { @@ -7,21 +49,35 @@ void scc_x86_emit_move_to_vec(scc_mir_x86_instr_vec_t *vec, LOG_WARN("Mismatched register sizes for move %d != %d", dst.size, src.size); } - Assert(dst.kind == SCC_X86_OPR_REG); scc_mir_x86_instr_t ins; - if (src.kind == SCC_X86_OPR_REG) { - scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_reg_reg(dst, src), dst, src, - scc_pos_create()); - } else if (src.kind == SCC_X86_OPR_IMM) { - scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_reg_imm(dst, src), dst, src, - scc_pos_create()); - } else if (src.kind == SCC_X86_OPR_MEM || - (src.kind == SCC_X86_OPR_RELOC && - src.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL)) { - scc_mir_x86_instr_2(&ins, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src, - scc_pos_create()); + if (dst.kind == SCC_X86_OPR_REG) { + if (src.kind == SCC_X86_OPR_REG) { + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_reg_reg(dst, src), dst, + src, scc_pos_create()); + } else if (src.kind == SCC_X86_OPR_IMM) { + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_reg_imm(dst, src), dst, + src, scc_pos_create()); + } else if (src.kind == SCC_X86_OPR_MEM || + (src.kind == SCC_X86_OPR_RELOC && + src.reloc.target == SCC_X86_RELOC_TARGET_SYMBOL)) { + Assert(dst.size == 8); + scc_mir_x86_instr_2(&ins, SCC_X86_IFORM_LEA_GPRV_AGEN, dst, src, + scc_pos_create()); + } else { + Panic("emit_move: unsupported src kind %d", src.kind); + } + } else if (dst.kind == SCC_X86_OPR_MEM) { + if (src.kind == SCC_X86_OPR_IMM) { + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_mem_imm(dst, src), dst, + src, scc_pos_create()); + } else if (src.kind == SCC_X86_OPR_REG) { + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_mem_reg(dst, src), dst, + src, scc_pos_create()); + } else { + Panic("emit_move: unsupported src kind %d", src.kind); + } } else { - Panic("emit_move: unsupported src kind %d", src.kind); + Panic("emit_move: unsupported dst kind %d", dst.kind); } scc_vec_push(*vec, ins); } @@ -65,7 +121,6 @@ void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec, LOG_WARN("Mismatched sizes for store %d != %d", dst_addr.size, src.size); } - Assert(src.kind == SCC_X86_OPR_REG); scc_x86_operand_value_t mem_op; if (dst_addr.kind == SCC_X86_OPR_REG) { mem_op = (scc_x86_operand_value_t){ @@ -83,10 +138,17 @@ void scc_x86_emit_store_to_vec(scc_mir_x86_instr_vec_t *vec, } else if (dst_addr.kind == SCC_X86_OPR_MEM) { mem_op = dst_addr; } else { - Panic("emit_store: dst_addr must be REG or MEM"); + Panic("emit_store: dst_addr kind not supported %d", dst_addr.kind); } scc_mir_x86_instr_t ins; - scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_mem_reg(mem_op, src), mem_op, src, - scc_pos_create()); + if (src.kind == SCC_X86_OPR_REG) { + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_mem_reg(mem_op, src), mem_op, + src, scc_pos_create()); + } else if (src.kind == SCC_X86_OPR_IMM) { + scc_mir_x86_instr_2(&ins, scc_mir_x86_mov_mem_imm(mem_op, src), mem_op, + src, scc_pos_create()); + } else { + Panic("unsupported src kind not supported %d", src.kind); + } scc_vec_push(*vec, ins); -} \ No newline at end of file +} diff --git a/libs/ir/mir/src/scc_mir.c b/libs/ir/mir/src/scc_mir.c index b44ff2e..eeee1d7 100644 --- a/libs/ir/mir/src/scc_mir.c +++ b/libs/ir/mir/src/scc_mir.c @@ -39,8 +39,11 @@ int scc_mir_vreg_map2slot(scc_mir_func_t *func, int vreg, int size, int align) { return 0; } int new_slot = scc_vec_size(meta->stack_slots); - scc_mir_stack_slot_t s = { - .slot_id = new_slot, .size = size, .alignment = align, .offset = 0}; + scc_mir_stack_slot_t s = {.slot_id = new_slot, + .size = size, + .alignment = align, + .offset = 0, + .arg_idx = 0}; scc_vec_push(meta->stack_slots, s); scc_hashtable_set(&meta->vreg2physic, (void *)(usize)vreg, (void *)(usize)new_slot); diff --git a/libs/ir/mir/src/scc_mir_pass.c b/libs/ir/mir/src/scc_mir_pass.c index a9efc08..b62897b 100644 --- a/libs/ir/mir/src/scc_mir_pass.c +++ b/libs/ir/mir/src/scc_mir_pass.c @@ -14,7 +14,9 @@ void scc_frame_layout(scc_frame_layout_t *ctx, scc_mir_module_t *module) { scc_vec_foreach(module->cfg_module.funcs, i) { if (i == 0) continue; - ctx->impl_fn(ctx, module, &scc_vec_at(module->cfg_module.funcs, i)); + scc_mir_func_t *func = &scc_vec_at(module->cfg_module.funcs, i); + ctx->offset = SCC_MIR_FUNC_META(func)->frame_size; + ctx->impl_fn(ctx, module, func); } } @@ -69,7 +71,7 @@ void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) { // scc_x86_peephole_optimize(mir_module); scc_frame_layout_t frame_layout_ctx = {0}; - scc_win_pc_x64_frame_alloc_init(&frame_layout_ctx); + scc_win_pc_x64_frame_layout_init(&frame_layout_ctx); scc_frame_layout(&frame_layout_ctx, mir_module); if (stage == SCC_MIR_STAGE_FRAME_LAYOUT) { return; diff --git a/libs/ir/mir/src/target/win64_abi.c b/libs/ir/mir/src/target/win64_abi.c index ff28e37..a13da5b 100644 --- a/libs/ir/mir/src/target/win64_abi.c +++ b/libs/ir/mir/src/target/win64_abi.c @@ -7,11 +7,13 @@ static const int WIN64_STACK_ALIGN = 16; -static void frame_alloc_impl(scc_frame_layout_t *ctx, - scc_mir_module_t *mir_module, - scc_mir_func_t *mir_func) { - ctx->offset = 8; +static void frame_layout_impl(scc_frame_layout_t *ctx, + scc_mir_module_t *mir_module, + scc_mir_func_t *mir_func) { + ctx->offset += 8; // call return address frame scc_mir_func_meta_t *func_meta = SCC_MIR_FUNC_META(mir_func); + + // Pass 1: 处理局部变量槽 (arg_idx == 0),从 RSP 向上分配偏移 scc_vec_foreach(mir_func->bblocks, i) { scc_cfg_bblock_id_t id = scc_vec_at(mir_func->bblocks, i); scc_cfg_bblock_t *bb = @@ -25,16 +27,17 @@ static void frame_alloc_impl(scc_frame_layout_t *ctx, int slot_id = scc_x86_op_slot_id(op); scc_mir_stack_slot_t *slot = scc_mir_unsafe_slot(mir_func, slot_id); + if (slot->arg_idx > 0) + continue; // 传入参数槽,Pass 2 处理 if (slot->offset == 0) { - ctx->offset += slot->size; slot->offset = ctx->offset; + ctx->offset += slot->size; } - *op = scc_x86_op_mem( (scc_x86_mem_t){ .seg = SCC_X86_REG_INVALID, .base = SCC_X86_REG_RSP, - .disp = {.displacement = -slot->offset}, + .disp = {.displacement = slot->offset}, .index = SCC_X86_REG_INVALID, .scale = 1, }, @@ -44,14 +47,50 @@ static void frame_alloc_impl(scc_frame_layout_t *ctx, } } - int total_size = ctx->offset + 32; // shadow space + int total_size = ctx->offset; ctx->offset = (total_size + WIN64_STACK_ALIGN - 1) & ~(WIN64_STACK_ALIGN - 1); func_meta->frame_size = ctx->offset; + + // Pass 2: 处理传入参数槽 (arg_idx > 0) + // 在 Win64 布局中,栈上参数位于 return address + 8 + arg_idx * 8 + // 即 RSP + frame_size + 8 + arg_idx * 8 + scc_vec_foreach(mir_func->bblocks, i) { + scc_cfg_bblock_id_t id = scc_vec_at(mir_func->bblocks, i); + scc_cfg_bblock_t *bb = + scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id); + scc_mir_x86_instr_vec_t *instrs = SCC_MIR_X86_BBLOCK_INSTRS(bb); + scc_vec_foreach(*instrs, j) { + scc_mir_x86_instr_t *ins = &scc_vec_at(*instrs, j); + for (int k = 0; k < ins->x86_instr.num_operands; k++) { + scc_x86_operand_value_t *op = &ins->x86_instr.operands[k]; + if (scc_x86_op_is_slot(op)) { + int slot_id = scc_x86_op_slot_id(op); + scc_mir_stack_slot_t *slot = + scc_mir_unsafe_slot(mir_func, slot_id); + if (slot->arg_idx == 0) + continue; // 局部变量槽,Pass 1 已处理 + if (slot->offset == 0) { + slot->offset = + func_meta->frame_size + 8 + slot->arg_idx * 8; + } + *op = scc_x86_op_mem( + (scc_x86_mem_t){ + .seg = SCC_X86_REG_INVALID, + .base = SCC_X86_REG_RSP, + .disp = {.displacement = slot->offset}, + .index = SCC_X86_REG_INVALID, + .scale = 1, + }, + op->size); + } + } + } + } } -void scc_win_pc_x64_frame_alloc_init(scc_frame_layout_t *ctx) { - ctx->impl_fn = frame_alloc_impl; +void scc_win_pc_x64_frame_layout_init(scc_frame_layout_t *ctx) { + ctx->impl_fn = frame_layout_impl; } /* @@ -136,6 +175,15 @@ static void lower_call(void *userdata, const scc_lir_instr_t *instr) { scc_x86_64_isel_t *isel = userdata; u8 size = 8; + scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(isel->func); + int call_stack_size = instr->metadata.call.arg_count * 8; + if (meta->frame_size < call_stack_size) { + meta->frame_size = call_stack_size; + } + if (meta->frame_size < 32) { + meta->frame_size = 32; // Windows X64 shadow space + } + for (int i = instr->metadata.call.arg_count - 1; i >= 0; i -= 1) { scc_lir_val_t *args = &instr->metadata.call.args[i]; switch (i) { @@ -156,10 +204,15 @@ static void lower_call(void *userdata, const scc_lir_instr_t *instr) { scc_x86_lir_val_to_mir_op(isel, args, size)); break; default: - scc_x86_operand_value_t op = - scc_x86_lir_val_to_mir_op(isel, args, size); - TODO(); - add_instr_1(isel, SCC_X86_ICLASS_PUSH, op); + scc_x86_emit_move( + isel, + scc_x86_op_mem((scc_x86_mem_t){.base = SCC_X86_REG_RSP, + .index = SCC_X86_REG_INVALID, + .scale = 1, + .disp.displacement = i * 8, + .disp.displacement_bits = 8}, + size), + scc_x86_lir_val_to_mir_op(isel, args, size)); break; } } @@ -176,14 +229,34 @@ static void lower_call(void *userdata, const scc_lir_instr_t *instr) { Panic("unhandled opcode"); } + int ret_size = instr->size; scc_x86_operand_value_t ret_reg = - scc_x86_lir_val_to_mir_op(isel, &instr->to, size); - if (ret_reg.kind != SCC_X86_OPR_NONE) { + scc_x86_lir_val_to_mir_op(isel, &instr->to, ret_size); + if (ret_reg.kind != SCC_X86_OPR_NONE && ret_size != 0) { scc_x86_emit_move(isel, ret_reg, - scc_x86_op_preg(SCC_X86_REG_RAX, size)); + scc_x86_op_preg(SCC_X86_REG_RAX, ret_size)); } } +// 查找或创建传入参数的栈槽 (arg_idx > 0 表示栈上传入参数) +static int get_or_create_arg_slot(scc_mir_func_t *func, int arg_idx, int size) { + scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func); + scc_vec_foreach(meta->stack_slots, i) { + scc_mir_stack_slot_t *s = &scc_vec_at(meta->stack_slots, i); + if (s->arg_idx == arg_idx) + return s->slot_id; + } + int slot_id = (int)scc_vec_size(meta->stack_slots); + scc_vec_push(meta->stack_slots, ((scc_mir_stack_slot_t){ + .slot_id = slot_id, + .size = size, + .alignment = 8, + .offset = 0, + .arg_idx = arg_idx, + })); + return slot_id; +} + static void lower_param(void *userdata, const scc_lir_val_t *val, void *out_op) { scc_x86_operand_value_t *out = out_op; @@ -202,10 +275,13 @@ static void lower_param(void *userdata, const scc_lir_val_t *val, case 3: *out = scc_x86_op_preg(SCC_X86_REG_R9, size); break; - default: - *out = scc_x86_op_slot(-val->data.arg, size); + default: { + scc_x86_64_isel_t *isel = userdata; + int slot_id = get_or_create_arg_slot(isel->func, val->data.arg, size); + *out = scc_x86_op_slot(slot_id, size); break; } + } } static void lower_ret(void *userdata, const scc_lir_instr_t *instr) { diff --git a/libs/ir2mcode/src/scc_ir2sccf.c b/libs/ir2mcode/src/scc_ir2sccf.c index 5c50671..f44ca4c 100644 --- a/libs/ir2mcode/src/scc_ir2sccf.c +++ b/libs/ir2mcode/src/scc_ir2sccf.c @@ -62,8 +62,8 @@ static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode, scc_hashtable_usize_init(&bblock_offset); scc_reloc_vec_t relocs; scc_vec_init(relocs); - scc_vec_foreach(func->bblocks, i) { - scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i); + scc_vec_foreach(func->bblocks, j) { + scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, j); const scc_cfg_bblock_t *bb = scc_cfg_module_unsafe_get_bblock(&mir_module->cfg_module, id); @@ -72,20 +72,21 @@ static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode, (void *)scc_mcode_size(mcode)); scc_mir_instr_vec_t *instrs = SCC_MIR_BBLOCK_VALUES_PTR(bb); - scc_vec_foreach(*instrs, i) { + scc_vec_foreach(*instrs, k) { const scc_mir_instr_t *ins = - scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, i); + scc_vec_sized_at_ptr(*instrs, mir_module->instr_size, k); // FIXME reloc symbol needed scc_ir2mcode_emit_instr(mcode, &relocs, ins); } } - scc_vec_foreach(relocs, i) { - scc_reloc_t *reloc = &scc_vec_at(relocs, i); + scc_vec_foreach(relocs, j) { + scc_reloc_t *reloc = &scc_vec_at(relocs, j); if (reloc->target_kind == SCC_RELOC_TARGET_BBLOCK) { reloc->target_kind = SCC_RELOC_TARGET_NONE; usize addr = (usize)scc_hashtable_get( &bblock_offset, (void *)(usize)reloc->bblock_id); + Assert(addr != 0); scc_ir2mcode_patch(mcode, reloc, addr); } else if (reloc->target_kind == SCC_RELOC_TARGET_SYMBOL) { usize sym_idx = diff --git a/libs/mcode/include/x86/scc_x86_patch.h b/libs/mcode/include/x86/scc_x86_patch.h index c632aa9..f1df626 100644 --- a/libs/mcode/include/x86/scc_x86_patch.h +++ b/libs/mcode/include/x86/scc_x86_patch.h @@ -120,11 +120,11 @@ static inline int scc_x86_patch_imm0_ex(scc_mcode_t *mcode, usize offset, static inline void scc_x86_patch(scc_mcode_t *mcode, scc_x86_patch_type_t patch_type, u64 offset, - i64 value) { + u64 value) { switch (patch_type) { case SCC_X86_PATCH_PC32: - scc_x86_patch_brdisp(mcode, offset - 4, - scc_x86_op_relbr(value - offset)); + i32 rel = value - offset; + scc_x86_patch_brdisp(mcode, offset - 4, scc_x86_op_relbr(rel)); break; default: TODO(); diff --git a/libs/mcode/src/scc_x86_encode.c b/libs/mcode/src/scc_x86_encode.c index 385d24b..d212032 100644 --- a/libs/mcode/src/scc_x86_encode.c +++ b/libs/mcode/src/scc_x86_encode.c @@ -218,9 +218,13 @@ static int scale_to_enc(uint8_t scale) { /* 修正:位移大小只由数值范围决定,与基址寄存器无关 */ static int disp_size(int32_t disp, scc_x86_reg_t base) { - (void)base; - if (disp == 0) + if (disp == 0) { + /* RBP/R13 with disp=0: must use mod=01 + disp8=0, + because mod=00 + r/m=101 means RIP-relative */ + if (base == SCC_X86_REG_RBP || base == SCC_X86_REG_R13) + return 8; return 0; + } if (disp >= -128 && disp <= 127) return 8; return 32; @@ -496,10 +500,12 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform, } else if (ops[i].kind == SCC_X86_OPR_MEM) { base_reg = ops[i].mem.base; idx_reg = ops[i].mem.index; - } else if (ops[i].kind == SCC_X86_OPR_IMM || - ops[i].kind == SCC_X86_OPR_RELBR) { + } else if (ops[i].kind == SCC_X86_OPR_IMM) { imm_val = ops[i].imm0; imm_idx = i; + } else if (ops[i].kind == SCC_X86_OPR_RELBR) { + imm_val = ops[i].brdisp; // i32 → i64 自动符号扩展 + imm_idx = i; } } diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index d38d650..8522877 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -24,9 +24,9 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path, const char *fname = scc_str_as_cstr(&fpath); scc_file_t fp = scc_fopen(fname, SCC_FILE_READ); if (fp == nullptr) { - LOG_ERROR("load_from_def file read error: %s", fname); return; } + LOG_TRACE("load_from_def file read sucessful: %s", fname); usize fsize = scc_fsize(fp); char *buffer = scc_malloc(fsize); @@ -152,7 +152,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { } pe_idata_lib_ctx_t idata_lib_ctx; - pe_idata_lib_init(&idata_lib_ctx, __FILE__ "/../../.dll_def"); + pe_idata_lib_init(&idata_lib_ctx, "./.scc_dll"); scc_vec_foreach(symtab, i) { sccf_sym_t *sym = &scc_vec_at(symtab, i); if (sym->sccf_sym_type == SCCF_SYM_TYPE_EXTERN) { diff --git a/tests/simple/expect.toml b/tests/simple/expect.toml index bdca9dd..b3d52ce 100644 --- a/tests/simple/expect.toml +++ b/tests/simple/expect.toml @@ -23,3 +23,4 @@ "./return_val_cases/19_goto.c" = 219 [stdout_val_cases] "./stdout_val_cases/01_include.c" = "Hello World!\n" +"./stdout_val_cases/02_printf.c" = "Hello printf: 123\n" diff --git a/tests/simple/stdout_val_cases/01_include.c b/tests/simple/stdout_val_cases/01_include.c index ab544ea..157db0b 100644 --- a/tests/simple/stdout_val_cases/01_include.c +++ b/tests/simple/stdout_val_cases/01_include.c @@ -1,6 +1,6 @@ #include "stdio.h" int main(void) { - puts("hello world"); + puts("hello world!"); return 0; } diff --git a/tests/simple/stdout_val_cases/02_printf.c b/tests/simple/stdout_val_cases/02_printf.c new file mode 100644 index 0000000..2935106 --- /dev/null +++ b/tests/simple/stdout_val_cases/02_printf.c @@ -0,0 +1,6 @@ +#include "stdio.h" + +int main(void) { + printf("hello printf: %d\n", 123); + return 0; +}