refactor(ast2ir): 移除废弃的ABI依赖并优化类型转换处理
移除了对scc_abi包的依赖,将相关头文件从libs/abi移动到libs/ast2ir目录下。 重构了基本类型解析功能,将parse_base_type函数提取为独立的 scc_ast2ir_parse_base_type实现,并支持有符号/无符号类型区分。 feat(ast2ir): 实现整数常量表达式求值器 新增了完整的整数常量表达式求值功能,支持C11标准中的常量表达式规则, 包括字面量、标识符、sizeof/_Alignof、一元/二元运算、条件表达式和 类型转换等操作。该功能用于数组大小和枚举值的编译期计算验证。 refactor(ast2ir): 完善类型提升和算术转换机制 改进了整数提升和寻常算术转换的实现,修复了移位操作的符号处理问题, 添加了无符号比较操作的支持,增强了类型安全检查,统一了错误处理流程。 fix(ast2ir): 修复赋值表达式返回值和数组大小计算问题 修正了赋值表达式的返回值处理,确保返回右侧值而不是存储指令引用。 使用新的常量表达式求值器替代原有的硬编码数组大小计算,提高了 数组声明的正确性。
This commit is contained in:
@@ -24,29 +24,6 @@ static int fixed_param_count(const scc_ast_canon_type_t *canon) {
|
||||
return n;
|
||||
}
|
||||
|
||||
static scc_hir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx,
|
||||
const scc_ast_qual_type_t *ast_type) {
|
||||
scc_abi_type_layout_t layout;
|
||||
// 映射内置类型
|
||||
ctx->abi->compute_type_layout(ctx->abi, (void *)ast_type, &layout);
|
||||
switch (layout.size) {
|
||||
case 0:
|
||||
return scc_hir_builder_type_void(&ctx->builder);
|
||||
case 1:
|
||||
return scc_hir_builder_type_i8(&ctx->builder);
|
||||
case 2:
|
||||
return scc_hir_builder_type_i16(&ctx->builder);
|
||||
case 4:
|
||||
return scc_hir_builder_type_i32(&ctx->builder);
|
||||
case 8:
|
||||
return scc_hir_builder_type_i64(&ctx->builder);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return SCC_HIR_REF_nullptr;
|
||||
}
|
||||
|
||||
static inline bool scc_hir_type_is_signed(scc_hir_type_tag_t tag) {
|
||||
switch (tag) {
|
||||
case SCC_HIR_TYPE_i8:
|
||||
@@ -69,6 +46,7 @@ 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) {
|
||||
Assert(type != nullptr);
|
||||
switch (type->tag) {
|
||||
case SCC_HIR_TYPE_i8:
|
||||
case SCC_HIR_TYPE_i16:
|
||||
@@ -235,7 +213,7 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
|
||||
switch (ast_type->base.type) {
|
||||
case SCC_AST_TYPE_BUILTIN: {
|
||||
return parse_base_type(ctx, ast_type);
|
||||
return scc_ast2ir_parse_base_type(ctx, ast_type);
|
||||
}
|
||||
case SCC_AST_TYPE_POINTER: {
|
||||
scc_hir_type_init(&ir_type, SCC_HIR_TYPE_PTR);
|
||||
@@ -253,16 +231,11 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
ir_type.data.array.base = element_type;
|
||||
ir_type.data.array.len = 0;
|
||||
if (scc_ast_canon_type(ast_type)->array.size) {
|
||||
// TODO constant expression
|
||||
if (scc_ast_canon_type(ast_type)->array.size->base.type !=
|
||||
SCC_AST_EXPR_INT_LITERAL) {
|
||||
Panic("TODO: array size expression");
|
||||
}
|
||||
scc_ap_t value;
|
||||
scc_ap_from_cstr(
|
||||
&value, scc_ast_canon_type(ast_type)->array.size->literal.lexme,
|
||||
10);
|
||||
// FIXME hack
|
||||
if (!scc_ast2ir_eval_constant_int(
|
||||
ctx, &value, scc_ast_canon_type(ast_type)->array.size)) {
|
||||
Panic("array size is not a constant expression");
|
||||
}
|
||||
ir_type.data.array.len = value.data.digit;
|
||||
}
|
||||
} break;
|
||||
@@ -359,7 +332,7 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
.base.type = SCC_AST_TYPE_BUILTIN,
|
||||
.type = int_canon_type,
|
||||
};
|
||||
return parse_base_type(ctx, &int_type);
|
||||
return scc_ast2ir_parse_base_type(ctx, &int_type);
|
||||
case SCC_AST_TYPE_TYPEDEF:
|
||||
// TODO maybe using cache
|
||||
return scc_ast2ir_type(
|
||||
@@ -569,7 +542,8 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
rhs = scc_ast2ir_emit_conversion(
|
||||
ctx, rhs, lhs_ptr_type->data.pointer.base);
|
||||
}
|
||||
return scc_hir_builder_store(&ctx->builder, lhs, rhs);
|
||||
scc_hir_builder_store(&ctx->builder, lhs, rhs);
|
||||
return rhs;
|
||||
}
|
||||
|
||||
if (expr->binary.op == SCC_AST_OP_LOGICAL_AND ||
|
||||
@@ -577,30 +551,36 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
// 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);
|
||||
if (expr->binary.op == SCC_AST_OP_COMMA) {
|
||||
lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, false);
|
||||
rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false);
|
||||
} else {
|
||||
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);
|
||||
scc_hir_type_ref_t common_type = 0;
|
||||
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;
|
||||
Assert(lhs_type_ref != 0 && rhs_type_ref != 0);
|
||||
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);
|
||||
common_type = scc_ast2ir_usual_arithmetic_conversion(
|
||||
ctx, lhs_type_ref, rhs_type_ref);
|
||||
if (common_type != 0) {
|
||||
lhs = scc_ast2ir_emit_conversion(ctx, lhs, common_type);
|
||||
rhs = scc_ast2ir_emit_conversion(ctx, rhs, common_type);
|
||||
}
|
||||
}
|
||||
} else if (is_shift) {
|
||||
@@ -628,16 +608,42 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
case SCC_AST_OP_BITWISE_XOR: op = SCC_HIR_OP_XOR; break;
|
||||
case SCC_AST_OP_LEFT_SHIFT: op = SCC_HIR_OP_SHL; break;
|
||||
case SCC_AST_OP_RIGHT_SHIFT: {
|
||||
op = SCC_HIR_OP_SHR;
|
||||
// FIXME op = SCC_HIR_OP_SAR;
|
||||
scc_hir_module_t *module = scc_ast2ir_mir_module(ctx);
|
||||
scc_hir_type_ref_t type_ref = scc_hir_module_get_value(module, lhs)->type;
|
||||
scc_hir_type_t *type = scc_hir_module_get_type(module, type_ref);
|
||||
op = scc_hir_type_is_signed(type->tag) ? SCC_HIR_OP_SAR : SCC_HIR_OP_SHR;
|
||||
break;
|
||||
}
|
||||
case SCC_AST_OP_EQUAL: op = SCC_HIR_OP_EQ; break;
|
||||
case SCC_AST_OP_NOT_EQUAL: op = SCC_HIR_OP_NEQ; break;
|
||||
case SCC_AST_OP_LESS: op = SCC_HIR_OP_LT; break;
|
||||
case SCC_AST_OP_LESS_EQUAL: op = SCC_HIR_OP_LE; break;
|
||||
case SCC_AST_OP_GREATER: op = SCC_HIR_OP_GT; break;
|
||||
case SCC_AST_OP_GREATER_EQUAL: op = SCC_HIR_OP_GE; break;
|
||||
case SCC_AST_OP_LESS: {
|
||||
scc_hir_module_t *module = scc_ast2ir_mir_module(ctx);
|
||||
scc_hir_type_ref_t tr = common_type ? common_type : scc_hir_module_get_value(module, lhs)->type;
|
||||
scc_hir_type_t *t = scc_hir_module_get_type(module, tr);
|
||||
op = scc_hir_type_is_signed(t->tag) ? SCC_HIR_OP_LT : SCC_HIR_OP_ULT;
|
||||
break;
|
||||
}
|
||||
case SCC_AST_OP_LESS_EQUAL: {
|
||||
scc_hir_module_t *module = scc_ast2ir_mir_module(ctx);
|
||||
scc_hir_type_ref_t tr = common_type ? common_type : scc_hir_module_get_value(module, lhs)->type;
|
||||
scc_hir_type_t *t = scc_hir_module_get_type(module, tr);
|
||||
op = scc_hir_type_is_signed(t->tag) ? SCC_HIR_OP_LE : SCC_HIR_OP_ULE;
|
||||
break;
|
||||
}
|
||||
case SCC_AST_OP_GREATER: {
|
||||
scc_hir_module_t *module = scc_ast2ir_mir_module(ctx);
|
||||
scc_hir_type_ref_t tr = common_type ? common_type : scc_hir_module_get_value(module, lhs)->type;
|
||||
scc_hir_type_t *t = scc_hir_module_get_type(module, tr);
|
||||
op = scc_hir_type_is_signed(t->tag) ? SCC_HIR_OP_GT : SCC_HIR_OP_UGT;
|
||||
break;
|
||||
}
|
||||
case SCC_AST_OP_GREATER_EQUAL: {
|
||||
scc_hir_module_t *module = scc_ast2ir_mir_module(ctx);
|
||||
scc_hir_type_ref_t tr = common_type ? common_type : scc_hir_module_get_value(module, lhs)->type;
|
||||
scc_hir_type_t *t = scc_hir_module_get_type(module, tr);
|
||||
op = scc_hir_type_is_signed(t->tag) ? SCC_HIR_OP_GE : SCC_HIR_OP_UGE;
|
||||
break;
|
||||
}
|
||||
case SCC_AST_OP_COMMA: {
|
||||
// 逗号运算符:计算左表达式,丢弃结果,返回右表达式
|
||||
return rhs;
|
||||
@@ -854,28 +860,24 @@ 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;
|
||||
}
|
||||
Assert(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) {
|
||||
@@ -897,8 +899,11 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
// 可变参数:只应用默认参数提升(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_value_t *arg_value =
|
||||
scc_hir_module_get_value(module, arg_node);
|
||||
Assert(arg_value != nullptr);
|
||||
scc_hir_type_ref_t arg_type_ref = arg_value->type;
|
||||
Assert(arg_type_ref != 0);
|
||||
scc_hir_type_tag_t arg_tag =
|
||||
scc_hir_module_get_type(module, arg_type_ref)->tag;
|
||||
@@ -1136,7 +1141,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
// FIXME maybe using some array to int;
|
||||
scc_hir_type_ref_t type_ref = scc_hir_builder_type_i32(&ctx->builder);
|
||||
scc_ap_t value;
|
||||
scc_ap_from_cstr(&value, expr->literal.lexme, 10);
|
||||
scc_ap_from_cstr(&value, expr->literal.lexme, 0);
|
||||
return scc_hir_builder_integer(&ctx->builder, type_ref, &value);
|
||||
}
|
||||
// SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量
|
||||
@@ -1655,24 +1660,23 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
||||
} break;
|
||||
case SCC_AST_DECL_ENUM: {
|
||||
scc_ap_t val;
|
||||
int idx = 0;
|
||||
scc_ap_set_int(&val, idx);
|
||||
scc_ap_set_int(&val, 0);
|
||||
scc_vec_foreach(decl->record.fields, i) {
|
||||
scc_ast_decl_t *item = scc_vec_at(decl->record.fields, i);
|
||||
Assert(item->base.type == SCC_AST_DECL_VAR);
|
||||
if (item->var.init) {
|
||||
Assert(item->var.init->base.type == SCC_AST_EXPR_INT_LITERAL);
|
||||
scc_ap_from_cstr(&val, item->var.init->literal.lexme, 10);
|
||||
if (!scc_ast2ir_eval_constant_int(ctx, &val, item->var.init)) {
|
||||
Panic("enum value is not a constant expression");
|
||||
}
|
||||
}
|
||||
scc_hir_value_ref_t item_val_ref = scc_hir_builder_integer(
|
||||
&ctx->builder, scc_hir_builder_type_i32(&ctx->builder), &val);
|
||||
scc_hashtable_set(&ctx->ast2ir_cache, item,
|
||||
(void *)(usize)item_val_ref);
|
||||
// FIXME hack ap
|
||||
idx = val.data.digit;
|
||||
idx += 1;
|
||||
// scc_ap_add 1 ();
|
||||
scc_ap_set_int(&val, idx);
|
||||
/* next = val + 1 */
|
||||
scc_ap_t one;
|
||||
scc_ap_set_int(&one, 1);
|
||||
scc_ap_add(&val, &val, &one);
|
||||
}
|
||||
} break;
|
||||
case SCC_AST_DECL_TYPEDEF:
|
||||
|
||||
Reference in New Issue
Block a user