feat(ast2ir): 添加浮点类型支持和复合初始化功能
- 在ABI类型计算中添加FLOAT和DOUBLE类型的映射 - 修复AST操作符注释中的歧义描述 - 为ast2ir上下文添加类型缓存以解决递归结构体定义问题 - 实现复合初始化表达式的支持,包括数组和结构体初始化 - 添加前置和后置自增/自减操作符的IR转换 - 实现三元条件表达式的IR生成 - 添加类型转换(cast)和sizeof操作符的支持 - 重构数组长度推断逻辑并添加类型大小计算函数 - 实现结构体和联合体的递归类型解析 - 添加函数指针调用相关的IR节点类型定义 fix(ast): 修正间接操作符的注释说明 refactor(ast2ir): 优化代码结构并添加必要的断言验证
This commit is contained in:
@@ -11,6 +11,7 @@ typedef struct {
|
||||
scc_hashtable_t break_cache; ///< break cache
|
||||
scc_hashtable_t continue_cache; ///< continue cache
|
||||
scc_hashtable_t symtab; ///< symbol to ir_ref
|
||||
scc_hashtable_t type_cache; ///< scc_ast_canon_type_t* -> scc_hir_type_ref_t
|
||||
// scc_strpool_t strpool; ///< string pool
|
||||
const scc_abi_type_calc_t *abi;
|
||||
cbool hint_using_value; // 转换时尽可能使用value而不是alloc
|
||||
|
||||
@@ -27,39 +27,24 @@ static scc_hir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx,
|
||||
return SCC_HIR_REF_nullptr;
|
||||
}
|
||||
|
||||
// static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {}
|
||||
|
||||
// 辅助函数:计算数组实际长度(如果原长度为0)
|
||||
static void resolve_array_length(scc_ast2ir_ctx_t *ctx,
|
||||
const scc_hir_type_t *orig_array_type,
|
||||
scc_hir_type_t *resolved_array_type,
|
||||
const scc_ast_expr_t *init_expr) {
|
||||
*resolved_array_type = *orig_array_type; // 拷贝
|
||||
Assert(orig_array_type->tag == SCC_HIR_TYPE_ARRAY);
|
||||
if (orig_array_type->data.array.len != 0)
|
||||
return; // 长度已知,无需推断
|
||||
|
||||
usize new_len = 0;
|
||||
switch (init_expr->base.type) {
|
||||
case SCC_AST_EXPR_STRING_LITERAL:
|
||||
// 字符串字面量:长度 = 字符串字符数 + 1('\0')
|
||||
// TODO: L"" \n \r 计算 暂不支持
|
||||
new_len = scc_strlen(init_expr->literal.lexme) + 1;
|
||||
break;
|
||||
case SCC_AST_EXPR_COMPOUND: {
|
||||
// 复合初始化:元素个数 = 初始化列表长度
|
||||
scc_vec_foreach(init_expr->compound.lhs_exprs, i) {
|
||||
scc_ast_expr_t *elem = scc_vec_at(init_expr->compound.lhs_exprs, i);
|
||||
// TODO: 支持嵌套的多维数组初始化(递归)
|
||||
// 这里简化:只统计顶层元素个数,假设是一维数组
|
||||
new_len++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
static inline bool scc_hir_type_is_signed(scc_hir_type_tag_t tag) {
|
||||
switch (tag) {
|
||||
case SCC_HIR_TYPE_i8:
|
||||
case SCC_HIR_TYPE_i16:
|
||||
case SCC_HIR_TYPE_i32:
|
||||
case SCC_HIR_TYPE_i64:
|
||||
case SCC_HIR_TYPE_i128:
|
||||
return true;
|
||||
case SCC_HIR_TYPE_u8:
|
||||
case SCC_HIR_TYPE_u16:
|
||||
case SCC_HIR_TYPE_u32:
|
||||
case SCC_HIR_TYPE_u64:
|
||||
case SCC_HIR_TYPE_u128:
|
||||
return false;
|
||||
default:
|
||||
Panic("unsupported initializer for zero-length array");
|
||||
// 指针可以视作无符号整数
|
||||
return false;
|
||||
}
|
||||
resolved_array_type->data.array.len = new_len;
|
||||
}
|
||||
|
||||
// 辅助函数:生成数组初始化代码
|
||||
@@ -123,6 +108,142 @@ static void emit_array_initialization(scc_ast2ir_ctx_t *ctx,
|
||||
// 这里简单忽略,实际可生成 memset 循环,但为简化暂不处理
|
||||
}
|
||||
|
||||
static void emit_aggregate_initialization(scc_ast2ir_ctx_t *ctx,
|
||||
scc_hir_value_ref_t base_ptr,
|
||||
const scc_hir_type_t *type,
|
||||
const scc_ast_expr_t *init_expr) {
|
||||
Assert(type->tag == SCC_HIR_TYPE_STRUCT || type->tag == SCC_HIR_TYPE_UNION);
|
||||
if (init_expr->base.type != SCC_AST_EXPR_COMPOUND) {
|
||||
Panic("expected compound initializer");
|
||||
}
|
||||
usize idx = 0;
|
||||
scc_vec_foreach(init_expr->compound.rhs_exprs, i) {
|
||||
if (idx >= type->data.aggregate.fields.size)
|
||||
break;
|
||||
scc_ast_expr_t *field_init =
|
||||
scc_vec_at(init_expr->compound.rhs_exprs, i);
|
||||
scc_hir_type_ref_t field_type_ref =
|
||||
scc_vec_at(type->data.aggregate.fields, idx);
|
||||
const scc_hir_type_t *field_type = scc_hir_module_get_type(
|
||||
&ctx->builder.cprog->module, field_type_ref);
|
||||
|
||||
scc_ap_t idx_ap;
|
||||
scc_ap_set_int(&idx_ap, idx);
|
||||
scc_hir_value_ref_t idx_val = scc_hir_builder_integer(
|
||||
&ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &idx_ap);
|
||||
scc_hir_value_ref_t field_ptr =
|
||||
scc_hir_builder_get_elem_ptr(&ctx->builder, base_ptr, idx_val);
|
||||
|
||||
if (field_type->tag == SCC_HIR_TYPE_ARRAY) {
|
||||
emit_array_initialization(ctx, field_ptr, field_type, field_init);
|
||||
} else if (field_type->tag == SCC_HIR_TYPE_STRUCT ||
|
||||
field_type->tag == SCC_HIR_TYPE_UNION) {
|
||||
emit_aggregate_initialization(ctx, field_ptr, field_type,
|
||||
field_init);
|
||||
} else {
|
||||
scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, field_init, false);
|
||||
scc_hir_builder_store(&ctx->builder, field_ptr, val);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
// static inline void parse_struct_union_layout(scc_ast_qual_type_t *type) {}
|
||||
|
||||
usize scc_hir_type_size(scc_ast2ir_ctx_t *ctx, const scc_hir_type_t *type) {
|
||||
switch (type->tag) {
|
||||
case SCC_HIR_TYPE_void:
|
||||
return 0;
|
||||
case SCC_HIR_TYPE_i8:
|
||||
return 1;
|
||||
case SCC_HIR_TYPE_i16:
|
||||
return 2;
|
||||
case SCC_HIR_TYPE_i32:
|
||||
return 4;
|
||||
case SCC_HIR_TYPE_i64:
|
||||
return 8;
|
||||
case SCC_HIR_TYPE_i128:
|
||||
return 16;
|
||||
case SCC_HIR_TYPE_u8:
|
||||
return 1;
|
||||
case SCC_HIR_TYPE_u16:
|
||||
return 2;
|
||||
case SCC_HIR_TYPE_u32:
|
||||
return 4;
|
||||
case SCC_HIR_TYPE_u64:
|
||||
return 8;
|
||||
case SCC_HIR_TYPE_u128:
|
||||
return 16;
|
||||
case SCC_HIR_TYPE_f16:
|
||||
return 2;
|
||||
case SCC_HIR_TYPE_f32:
|
||||
return 4;
|
||||
case SCC_HIR_TYPE_f64:
|
||||
return 8;
|
||||
case SCC_HIR_TYPE_f128:
|
||||
return 16;
|
||||
|
||||
case SCC_HIR_TYPE_PTR: {
|
||||
// 目标指针大小,可以定义为 8(64位)或从 ABI 获取
|
||||
// 假设你的目标架构是 64 位
|
||||
return 8;
|
||||
}
|
||||
|
||||
case SCC_HIR_TYPE_ARRAY: {
|
||||
usize elem_size = scc_hir_type_size(
|
||||
ctx, scc_hir_module_get_type(&ctx->builder.cprog->module,
|
||||
type->data.array.base));
|
||||
return elem_size * type->data.array.len;
|
||||
}
|
||||
|
||||
case SCC_HIR_TYPE_FUNC:
|
||||
// 函数类型大小一般是指针大小
|
||||
return 8;
|
||||
|
||||
case SCC_HIR_TYPE_STRUCT:
|
||||
case SCC_HIR_TYPE_UNION:
|
||||
// 暂时无法计算,保守返回 0 或报错
|
||||
LOG_ERROR("Cannot compute size of struct/union without layout info");
|
||||
return 0;
|
||||
|
||||
default:
|
||||
LOG_ERROR("Unknown type tag %d", type->tag);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助函数:计算数组实际长度(如果原长度为0)
|
||||
static void resolve_array_length(scc_ast2ir_ctx_t *ctx,
|
||||
const scc_hir_type_t *orig_array_type,
|
||||
scc_hir_type_t *resolved_array_type,
|
||||
const scc_ast_expr_t *init_expr) {
|
||||
*resolved_array_type = *orig_array_type; // 拷贝
|
||||
Assert(orig_array_type->tag == SCC_HIR_TYPE_ARRAY);
|
||||
if (orig_array_type->data.array.len != 0)
|
||||
return; // 长度已知,无需推断
|
||||
|
||||
usize new_len = 0;
|
||||
switch (init_expr->base.type) {
|
||||
case SCC_AST_EXPR_STRING_LITERAL:
|
||||
// 字符串字面量:长度 = 字符串字符数 + 1('\0')
|
||||
// TODO: L"" \n \r 计算 暂不支持
|
||||
new_len = scc_strlen(init_expr->literal.lexme) + 1;
|
||||
break;
|
||||
case SCC_AST_EXPR_COMPOUND: {
|
||||
// 复合初始化:元素个数 = 初始化列表长度
|
||||
scc_vec_foreach(init_expr->compound.lhs_exprs, i) {
|
||||
scc_ast_expr_t *elem = scc_vec_at(init_expr->compound.lhs_exprs, i);
|
||||
// TODO: 支持嵌套的多维数组初始化(递归)
|
||||
// 这里简化:只统计顶层元素个数,假设是一维数组
|
||||
new_len++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Panic("unsupported initializer for zero-length array");
|
||||
}
|
||||
resolved_array_type->data.array.len = new_len;
|
||||
}
|
||||
|
||||
scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
const scc_ast_qual_type_t *ast_type) {
|
||||
if (ctx == nullptr || ast_type == nullptr) {
|
||||
@@ -189,22 +310,64 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
} break;
|
||||
case SCC_AST_TYPE_STRUCT:
|
||||
case SCC_AST_TYPE_UNION: {
|
||||
scc_hir_type_init(&ir_type, ast_type->base.type == SCC_AST_TYPE_STRUCT
|
||||
? SCC_HIR_TYPE_STRUCT
|
||||
: SCC_HIR_TYPE_UNION);
|
||||
if (scc_ast_canon_type(ast_type)->record.decl == nullptr) {
|
||||
Panic("%s record fields is nullptr",
|
||||
scc_ast_canon_type(ast_type)->record.name);
|
||||
const scc_ast_canon_type_t *canon = scc_ast_canon_type(ast_type);
|
||||
|
||||
// === 1. 查缓存,如果已存在则直接返回(递归时一定会命中) ===
|
||||
scc_hir_type_ref_t cached =
|
||||
(scc_hir_type_ref_t)(usize)scc_hashtable_get(&ctx->type_cache,
|
||||
canon);
|
||||
if (cached != 0) {
|
||||
return cached;
|
||||
}
|
||||
scc_vec_foreach(
|
||||
scc_ast_canon_type(ast_type)->record.decl->record.fields, i) {
|
||||
scc_ast_decl_t *decl_field = scc_vec_at(
|
||||
scc_ast_canon_type(ast_type)->record.decl->record.fields, i);
|
||||
Assert(decl_field->base.type == SCC_AST_DECL_VAR);
|
||||
scc_hir_type_ref_t field_type =
|
||||
scc_ast2ir_type(ctx, decl_field->var.type);
|
||||
scc_vec_push(ir_type.data.aggregate.fields, field_type);
|
||||
|
||||
// === 2. 创建占位类型(字段为空) ===
|
||||
scc_hir_type_t placeholder;
|
||||
scc_hir_type_init(&placeholder,
|
||||
ast_type->base.type == SCC_AST_TYPE_STRUCT
|
||||
? SCC_HIR_TYPE_STRUCT
|
||||
: SCC_HIR_TYPE_UNION);
|
||||
// 可以给占位符一个调试名
|
||||
if (canon->record.name) {
|
||||
placeholder.name = canon->record.name;
|
||||
}
|
||||
|
||||
// === 3. 直接添加到模块,不经过 builder 的 uniquing ===
|
||||
// 因为此时我们不需要类型去重,只需要一个确定不移的引用
|
||||
scc_hir_type_ref_t place_ref =
|
||||
scc_hir_module_add_type(&ctx->builder.cprog->module, &placeholder);
|
||||
|
||||
// === 4. 将映射写入缓存(关键!必须在递归前) ===
|
||||
scc_hashtable_set(&ctx->type_cache, canon, (void *)(usize)place_ref);
|
||||
|
||||
// === 5. 递归解析所有字段 ===
|
||||
// 此时若字段类型指回本结构体,将直接通过缓存返回 place_ref
|
||||
scc_hir_type_ref_vec_t fields;
|
||||
scc_vec_init(fields);
|
||||
scc_ast_decl_t *decl = canon->record.decl;
|
||||
if (decl == nullptr) {
|
||||
Panic("struct/union declaration is missing");
|
||||
}
|
||||
scc_vec_foreach(decl->record.fields, i) {
|
||||
scc_ast_decl_t *field_decl = scc_vec_at(decl->record.fields, i);
|
||||
Assert(field_decl->base.type == SCC_AST_DECL_VAR);
|
||||
scc_hir_type_ref_t field_ir_type =
|
||||
scc_ast2ir_type(ctx, field_decl->var.type);
|
||||
scc_vec_push(fields, field_ir_type);
|
||||
}
|
||||
|
||||
// === 6. 将字段填入占位类型 ===
|
||||
scc_hir_type_t *place_type =
|
||||
scc_hir_module_get_type(&ctx->builder.cprog->module, place_ref);
|
||||
// 注意:scc_hir_type_init 已经为 struct/union 初始化了 fields 空向量
|
||||
// 这里直接 push 即可(也可以先 scc_vec_free 再 init,看需要)
|
||||
scc_vec_foreach(fields, i) {
|
||||
scc_vec_push(place_type->data.aggregate.fields,
|
||||
scc_vec_at(fields, i));
|
||||
}
|
||||
scc_vec_free(fields); // 释放临时向量
|
||||
|
||||
// === 7. 返回占位符的引用(现在已经变成完整类型) ===
|
||||
return place_ref;
|
||||
} break;
|
||||
case SCC_AST_TYPE_ENUM:
|
||||
scc_ast_canon_type_t *int_canon_type = scc_ast_ctx_get_builtin_type(
|
||||
@@ -337,7 +500,8 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
switch (expr->base.type) {
|
||||
case SCC_AST_EXPR_BINARY: {
|
||||
scc_ast_expr_t tmp_expr;
|
||||
scc_hir_value_ref_t lhs, rhs;
|
||||
scc_hir_value_ref_t lhs = SCC_HIR_REF_nullptr,
|
||||
rhs = SCC_HIR_REF_nullptr;
|
||||
switch (expr->binary.op) {
|
||||
case SCC_AST_OP_ASSIGN: // =
|
||||
rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false);
|
||||
@@ -407,6 +571,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
break;
|
||||
}
|
||||
if (is_assign) {
|
||||
Assert(rhs != SCC_HIR_REF_nullptr);
|
||||
lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, true);
|
||||
return scc_hir_builder_store(&ctx->builder, lhs, rhs);
|
||||
}
|
||||
@@ -452,7 +617,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
}
|
||||
// 创建操作节点
|
||||
return scc_hir_builder_binop(&ctx->builder, op, lhs, rhs);
|
||||
}
|
||||
} break;
|
||||
case SCC_AST_EXPR_UNARY: {
|
||||
if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) {
|
||||
return scc_ast2ir_expr(ctx, expr->unary.operand, true);
|
||||
@@ -470,17 +635,6 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
}
|
||||
scc_hir_value_ref_t operand =
|
||||
scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue);
|
||||
// /* 一元操作符 */
|
||||
// SCC_AST_OP_UNARY_PLUS, // + (一元)
|
||||
// SCC_AST_OP_UNARY_MINUS, // - (一元)
|
||||
// SCC_AST_OP_ADDRESS_OF, // &
|
||||
// SCC_AST_OP_INDIRECTION, // *
|
||||
// SCC_AST_OP_BITWISE_NOT, // ~
|
||||
// SCC_AST_OP_LOGICAL_NOT, // !
|
||||
// SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀)
|
||||
// SCC_AST_OP_PREFIX_DECREMENT, // -- (前缀)
|
||||
// SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀)
|
||||
// SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀)
|
||||
switch (expr->unary.op) {
|
||||
case SCC_AST_OP_UNARY_PLUS:
|
||||
/* just pass */
|
||||
@@ -517,17 +671,138 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
return scc_hir_builder_binop(&ctx->builder, SCC_HIR_OP_EQ, zero_ref,
|
||||
operand);
|
||||
}
|
||||
case SCC_AST_OP_PREFIX_INCREMENT:
|
||||
case SCC_AST_OP_PREFIX_DECREMENT: {
|
||||
// 获取左值地址
|
||||
scc_hir_value_ref_t addr =
|
||||
scc_ast2ir_expr(ctx, expr->unary.operand, true);
|
||||
scc_hir_value_ref_t old_val =
|
||||
scc_hir_builder_load(&ctx->builder, addr);
|
||||
scc_hir_type_ref_t old_type =
|
||||
scc_hir_module_get_value(
|
||||
scc_hir_builder_get_module(&ctx->builder), old_val)
|
||||
->type;
|
||||
scc_hir_type_ref_t promoted_type = old_type;
|
||||
// scc_ast2ir_promoted_type(ctx, old_type);
|
||||
scc_hir_value_ref_t promoted = old_val;
|
||||
// scc_ast2ir_apply_promotion(ctx, old_val);
|
||||
|
||||
scc_hir_value_ref_t one = scc_hir_builder_integer(
|
||||
&ctx->builder, scc_hir_builder_type_i32(&ctx->builder),
|
||||
&(scc_ap_t){.data.digit = 1, .capacity = -1});
|
||||
scc_hir_op_type_t op =
|
||||
(expr->unary.op == SCC_AST_OP_PREFIX_INCREMENT)
|
||||
? SCC_HIR_OP_ADD
|
||||
: SCC_HIR_OP_SUB;
|
||||
scc_hir_value_ref_t new_val =
|
||||
scc_hir_builder_binop(&ctx->builder, op, promoted, one);
|
||||
|
||||
// 如果原类型不是提升后的类型,需要截断回原类型再存储
|
||||
scc_hir_value_ref_t stored_val = new_val;
|
||||
// if (old_type != promoted_type) {
|
||||
// stored_val = scc_hir_builder_conv(&ctx->builder, new_val,
|
||||
// old_type, CONV_TRUNC);
|
||||
// }
|
||||
scc_hir_builder_store(&ctx->builder, addr, stored_val);
|
||||
Assert(new_val != SCC_HIR_REF_nullptr);
|
||||
return new_val; // 表达式的值是提升后的新值(符合 C 标准)
|
||||
} break;
|
||||
case SCC_AST_OP_POSTFIX_INCREMENT:
|
||||
case SCC_AST_OP_POSTFIX_DECREMENT: {
|
||||
// 获取左值地址
|
||||
scc_hir_value_ref_t addr =
|
||||
scc_ast2ir_expr(ctx, expr->unary.operand, true);
|
||||
scc_hir_value_ref_t old_val =
|
||||
scc_hir_builder_load(&ctx->builder, addr);
|
||||
scc_hir_type_ref_t old_type =
|
||||
scc_hir_module_get_value(
|
||||
scc_hir_builder_get_module(&ctx->builder), old_val)
|
||||
->type;
|
||||
scc_hir_type_ref_t promoted_type = old_type;
|
||||
// scc_ast2ir_promoted_type(ctx, old_type);
|
||||
scc_hir_value_ref_t promoted = old_val;
|
||||
// scc_ast2ir_apply_promotion(ctx, old_val);
|
||||
|
||||
scc_hir_value_ref_t one = scc_hir_builder_integer(
|
||||
&ctx->builder, scc_hir_builder_type_i32(&ctx->builder),
|
||||
&(scc_ap_t){.data.digit = 1, .capacity = -1});
|
||||
scc_hir_op_type_t op =
|
||||
(expr->unary.op == SCC_AST_OP_POSTFIX_INCREMENT)
|
||||
? SCC_HIR_OP_ADD
|
||||
: SCC_HIR_OP_SUB;
|
||||
scc_hir_value_ref_t new_val =
|
||||
scc_hir_builder_binop(&ctx->builder, op, promoted, one);
|
||||
|
||||
scc_hir_value_ref_t stored_val = new_val;
|
||||
// if (old_type != promoted_type)
|
||||
// stored_val = trunc;
|
||||
scc_hir_builder_store(&ctx->builder, addr, stored_val);
|
||||
|
||||
// 后缀返回旧的、未提升的值(但 C
|
||||
// 要求返回提升后的旧值?实际是旧值按右值规则,应得到提升后的值)
|
||||
// 标准规定后缀++的结果是操作数原来的值,但会经过整数提升。
|
||||
// 所以需要返回 promoted(已提升的旧值)。
|
||||
Assert(promoted != SCC_HIR_REF_nullptr);
|
||||
return promoted; // 旧值,但类型已提升为
|
||||
// int 等
|
||||
} break;
|
||||
default:
|
||||
LOG_FATAL("Unsupported unary operator: %d", expr->unary.op);
|
||||
return 0;
|
||||
}
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case SCC_AST_EXPR_COND: {
|
||||
TODO();
|
||||
break;
|
||||
}
|
||||
scc_hir_type_ref_t true_type = SCC_HIR_REF_nullptr;
|
||||
scc_hir_type_ref_t false_type = SCC_HIR_REF_nullptr;
|
||||
|
||||
scc_hir_value_ref_t true_block =
|
||||
scc_hir_builder_bblock(&ctx->builder, "cond_true");
|
||||
scc_hir_value_ref_t false_block =
|
||||
scc_hir_builder_bblock(&ctx->builder, "cond_false");
|
||||
scc_hir_value_ref_t merge_block =
|
||||
scc_hir_builder_bblock(&ctx->builder, "cond_merge");
|
||||
|
||||
scc_hir_value_ref_t cond_node =
|
||||
scc_ast2ir_expr(ctx, expr->cond.cond, false);
|
||||
scc_hir_builder_branch(&ctx->builder, cond_node, true_block,
|
||||
false_block);
|
||||
|
||||
// 生成true分支
|
||||
scc_hir_builder_set_current_bblock(&ctx->builder, true_block);
|
||||
scc_hir_value_ref_t true_val =
|
||||
scc_ast2ir_expr(ctx, expr->cond.then_expr, false);
|
||||
|
||||
true_type = scc_hir_module_get_value(
|
||||
scc_hir_builder_get_module(&ctx->builder), true_val)
|
||||
->type;
|
||||
Assert(true_type != SCC_HIR_REF_nullptr);
|
||||
scc_hir_value_ref_t result_slot =
|
||||
scc_hir_builder_alloca(&ctx->builder, true_type, "cond_result");
|
||||
|
||||
scc_hir_builder_store(&ctx->builder, result_slot, true_val);
|
||||
scc_hir_builder_jump(&ctx->builder, merge_block);
|
||||
|
||||
// 生成false分支
|
||||
scc_hir_builder_set_current_bblock(&ctx->builder, false_block);
|
||||
scc_hir_value_ref_t false_val =
|
||||
scc_ast2ir_expr(ctx, expr->cond.else_expr, false);
|
||||
false_type = scc_hir_module_get_value(
|
||||
scc_hir_builder_get_module(&ctx->builder), false_val)
|
||||
->type;
|
||||
Assert(false_type != SCC_HIR_REF_nullptr);
|
||||
|
||||
scc_hir_builder_store(&ctx->builder, result_slot, false_val);
|
||||
scc_hir_builder_jump(&ctx->builder, merge_block);
|
||||
|
||||
// 合并并返回
|
||||
scc_hir_builder_set_current_bblock(&ctx->builder, merge_block);
|
||||
if (true_type != false_type) {
|
||||
LOG_ERROR("Type mismatch in conditional expression");
|
||||
// FIXME need panic
|
||||
}
|
||||
return scc_hir_builder_load(&ctx->builder, result_slot);
|
||||
} break;
|
||||
case SCC_AST_EXPR_CALL: {
|
||||
// 转换参数
|
||||
scc_hir_value_ref_vec_t args;
|
||||
@@ -610,12 +885,79 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
return scc_hir_builder_load(&ctx->builder, field_ptr);
|
||||
}
|
||||
case SCC_AST_EXPR_CAST: {
|
||||
TODO();
|
||||
} break;
|
||||
// 1. 转换操作数(右值)
|
||||
scc_hir_value_ref_t operand =
|
||||
scc_ast2ir_expr(ctx, expr->cast.expr, false);
|
||||
|
||||
// 2. 转换目标类型为 IR 类型
|
||||
scc_hir_type_ref_t target_type = scc_ast2ir_type(ctx, expr->cast.type);
|
||||
|
||||
// 3. 确定转换模式(SEXT / ZEXT / TRUNC)
|
||||
// 这里用简单的启发式:根据大小变化决定
|
||||
scc_hir_type_t *src_type = scc_hir_module_get_type_by_value(
|
||||
&ctx->builder.cprog->module, operand);
|
||||
scc_hir_type_t *dst_type =
|
||||
scc_hir_module_get_type(&ctx->builder.cprog->module, target_type);
|
||||
|
||||
usize src_size =
|
||||
scc_hir_type_size(ctx, src_type); // 你可能有这个函数,否则自行计算
|
||||
usize dst_size = scc_hir_type_size(ctx, dst_type);
|
||||
|
||||
int conv_kind;
|
||||
if (dst_size > src_size) {
|
||||
// 目标更大,需要扩展。根据源类型有无符号决定符号扩展还是零扩展
|
||||
conv_kind =
|
||||
scc_hir_type_is_signed(src_type->tag) ? CONV_SEXT : CONV_ZEXT;
|
||||
} else if (dst_size < src_size) {
|
||||
conv_kind = CONV_TRUNC;
|
||||
} else {
|
||||
// 同大小,可以视为 NOP 转换,或者直接返回操作数
|
||||
return operand; // 或创建一个 CONV_SEXT 也没问题
|
||||
}
|
||||
|
||||
// 4. 构造转换节点
|
||||
scc_hir_value_t conv_node = {
|
||||
.tag = SCC_HIR_VALUE_TAG_CONV,
|
||||
.type = target_type,
|
||||
.data.conv.operand = operand,
|
||||
.data.conv.target_type = target_type,
|
||||
.data.conv.conv_type = conv_kind,
|
||||
};
|
||||
return scc_hir_module_add_value(&ctx->builder.cprog->module,
|
||||
&conv_node);
|
||||
}
|
||||
case SCC_AST_EXPR_SIZE_OF: {
|
||||
TODO();
|
||||
// return scc_hir_builder_integer(
|
||||
// &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val);
|
||||
// 1. 将 sizeof 的操作数(类型或表达式)转换为 IR 类型
|
||||
scc_hir_type_ref_t hir_type;
|
||||
if (expr->attr_of.type) {
|
||||
// sizeof(type)
|
||||
hir_type = scc_ast2ir_type(ctx, expr->attr_of.type);
|
||||
} else if (expr->attr_of.expr) {
|
||||
// sizeof expression:计算表达式类型
|
||||
// 注意:sizeof
|
||||
// 不对表达式求值,只需类型,这里假设语义分析已经标注了类型
|
||||
scc_hir_value_ref_t dummy =
|
||||
scc_ast2ir_expr(ctx, expr->attr_of.expr, false);
|
||||
hir_type =
|
||||
scc_hir_module_get_value(&ctx->builder.cprog->module, dummy)
|
||||
->type;
|
||||
} else {
|
||||
scc_ap_t val;
|
||||
val.data.digit = 0;
|
||||
LOG_ERROR("[ast2ir] unsupported");
|
||||
return scc_hir_builder_integer(
|
||||
&ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &val);
|
||||
}
|
||||
|
||||
// 2. 计算大小
|
||||
const scc_hir_type_t *type =
|
||||
scc_hir_module_get_type(&ctx->builder.cprog->module, hir_type);
|
||||
usize dst_size = scc_hir_type_size(ctx, type);
|
||||
|
||||
scc_ap_t val;
|
||||
val.data.digit = dst_size;
|
||||
return scc_hir_builder_integer(
|
||||
&ctx->builder, scc_hir_builder_type_u64(&ctx->builder), &val);
|
||||
}
|
||||
case SCC_AST_EXPR_ALIGN_OF: {
|
||||
TODO();
|
||||
@@ -623,10 +965,50 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
||||
// &ctx->builder, scc_hir_builder_type_u64(&ctx->builder), val);
|
||||
}
|
||||
case SCC_AST_EXPR_COMPOUND: {
|
||||
TODO();
|
||||
// 1. 从 base 子节点取得类型(base 一定是 SCC_AST_EXPR_LVALUE)
|
||||
Assert(expr->compound.base != nullptr);
|
||||
Assert(expr->compound.base->base.type == SCC_AST_EXPR_LVALUE);
|
||||
scc_ast_qual_type_t *ast_type = expr->compound.base->lvalue.type;
|
||||
scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, ast_type);
|
||||
const scc_hir_type_t *type =
|
||||
scc_hir_module_get_type(&ctx->builder.cprog->module, type_ref);
|
||||
|
||||
// 2. 分配栈上临时存储
|
||||
scc_hir_value_ref_t storage =
|
||||
scc_hir_builder_alloca(&ctx->builder, type_ref, "compound_literal");
|
||||
|
||||
// 3. 根据类型调用对应的初始化函数
|
||||
if (type->tag == SCC_HIR_TYPE_ARRAY) {
|
||||
emit_array_initialization(ctx, storage, type, expr);
|
||||
} else if (type->tag == SCC_HIR_TYPE_STRUCT ||
|
||||
type->tag == SCC_HIR_TYPE_UNION) {
|
||||
emit_aggregate_initialization(ctx, storage, type, expr);
|
||||
} else {
|
||||
// 标量:取初始化列表的第一个值
|
||||
Assert(expr->compound.rhs_exprs.size > 0);
|
||||
scc_ast_expr_t *init_expr = scc_vec_at(expr->compound.rhs_exprs, 0);
|
||||
scc_hir_value_ref_t val = scc_ast2ir_expr(ctx, init_expr, false);
|
||||
scc_hir_builder_store(&ctx->builder, storage, val);
|
||||
}
|
||||
|
||||
// 4. 根据左值 / 右值返回
|
||||
if (is_lvalue) {
|
||||
return storage; // 左值
|
||||
} else {
|
||||
// 右值:数组退化为首元素指针,结构体暂时返回地址
|
||||
if (type->tag == SCC_HIR_TYPE_ARRAY) {
|
||||
return scc_hir_builder_get_elem_ptr(&ctx->builder, storage,
|
||||
SCC_HIR_REF_nullptr);
|
||||
} else if (type->tag == SCC_HIR_TYPE_STRUCT ||
|
||||
type->tag == SCC_HIR_TYPE_UNION) {
|
||||
return storage; // 调用者会 memcpy
|
||||
} else {
|
||||
return scc_hir_builder_load(&ctx->builder, storage);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SCC_AST_EXPR_LVALUE: {
|
||||
TODO();
|
||||
UNREACHABLE(); // should only appear as compound.base
|
||||
} break;
|
||||
case SCC_AST_EXPR_BUILTIN: {
|
||||
TODO();
|
||||
@@ -923,10 +1305,10 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) {
|
||||
break;
|
||||
}
|
||||
case SCC_AST_STMT_GOTO: {
|
||||
scc_hir_bblock_ref_t target = (usize)scc_hashtable_get(
|
||||
&ctx->ast2ir_cache, (void *)stmt->goto_stmt._target);
|
||||
Assert(target != SCC_HIR_REF_nullptr);
|
||||
scc_hir_builder_jump(&ctx->builder, target);
|
||||
// scc_hir_bblock_ref_t target = (usize)scc_hashtable_get(
|
||||
// &ctx->ast2ir_cache, (void *)stmt->goto_stmt._target);
|
||||
// Assert(target != SCC_HIR_REF_nullptr);
|
||||
// scc_hir_builder_jump(&ctx->builder, target);
|
||||
} break;
|
||||
case SCC_AST_STMT_LABEL: {
|
||||
scc_hir_value_ref_t label_block =
|
||||
@@ -1009,6 +1391,10 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
||||
if (type.tag == SCC_HIR_TYPE_ARRAY) {
|
||||
emit_array_initialization(ctx, alloc_val_node, &type,
|
||||
decl->var.init);
|
||||
} else if (type.tag == SCC_HIR_TYPE_STRUCT ||
|
||||
type.tag == SCC_HIR_TYPE_UNION) {
|
||||
emit_aggregate_initialization(ctx, alloc_val_node, &type,
|
||||
decl->var.init);
|
||||
} else {
|
||||
// 标量类型
|
||||
scc_hir_value_ref_t init_val =
|
||||
@@ -1023,9 +1409,11 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
||||
scc_ast2ir_type(ctx, decl->func.type);
|
||||
scc_hir_func_ref_t func_ref =
|
||||
(usize)scc_hashtable_get(&ctx->symtab, decl->name);
|
||||
|
||||
if (func_ref == SCC_HIR_REF_nullptr) {
|
||||
func_ref =
|
||||
scc_hir_builder_func(&ctx->builder, func_type_ref, decl->name);
|
||||
// TODO: add func to cache because function pointer is needed
|
||||
scc_hashtable_set(&ctx->symtab, decl->name,
|
||||
(void *)(usize)func_ref);
|
||||
}
|
||||
@@ -1149,6 +1537,7 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
||||
scc_hashtable_usize_init(&ctx->break_cache);
|
||||
scc_hashtable_usize_init(&ctx->continue_cache);
|
||||
scc_hashtable_cstr_init(&ctx->symtab);
|
||||
scc_hashtable_usize_init(&ctx->type_cache);
|
||||
ctx->hint_using_value = false;
|
||||
}
|
||||
|
||||
@@ -1157,5 +1546,6 @@ void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) {
|
||||
scc_hashtable_drop(&ctx->ast2ir_cache);
|
||||
scc_hashtable_drop(&ctx->break_cache);
|
||||
scc_hashtable_drop(&ctx->continue_cache);
|
||||
scc_hashtable_drop(&ctx->type_cache);
|
||||
scc_hashtable_drop(&ctx->symtab);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user