feat(ast2ir): 实现C11类型提升系统并重构HIR基本块管理

- 新增 scc_ast2ir_promote.c 实现整数提升(6.3.1.1)和寻常算术转换(6.3.1.8)
- 重构 HIR Builder: bblock → create_bblock + append_bblock,引入BBList链表管理
- AST2IR 全面集成类型提升:二元运算、赋值、函数调用参数、自增/自减操作符
- 变参函数支持:跳过 ... 假参数,实现默认参数提升(float→double等)
- 简化 HIR Dump 实现
- MIR: Win64 ABI改进、x86指令选择优化
- 新增 printf 测试用例
This commit is contained in:
zzy
2026-05-24 15:46:22 +08:00
parent ea553718f0
commit cec96333e7
27 changed files with 1223 additions and 740 deletions

View File

@@ -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__ */

View File

@@ -4,6 +4,26 @@
#include <scc_hir_builder.h>
#include <scc_hir_def.h>
// 判断 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. 生成 getptrGEP
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(

View File

@@ -0,0 +1,321 @@
#include <scc_ast2ir.h>
// 判断是否为整数类型(不包括指针、浮点)
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);
// 秩 >= intrank >= 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);
}