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:
@@ -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. 生成 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(
|
||||
|
||||
Reference in New Issue
Block a user