feat(ast2ir): 添加浮点类型支持和复合初始化功能

- 在ABI类型计算中添加FLOAT和DOUBLE类型的映射
- 修复AST操作符注释中的歧义描述
- 为ast2ir上下文添加类型缓存以解决递归结构体定义问题
- 实现复合初始化表达式的支持,包括数组和结构体初始化
- 添加前置和后置自增/自减操作符的IR转换
- 实现三元条件表达式的IR生成
- 添加类型转换(cast)和sizeof操作符的支持
- 重构数组长度推断逻辑并添加类型大小计算函数
- 实现结构体和联合体的递归类型解析
- 添加函数指针调用相关的IR节点类型定义

fix(ast): 修正间接操作符的注释说明

refactor(ast2ir): 优化代码结构并添加必要的断言验证
This commit is contained in:
zzy
2026-05-19 17:35:24 +08:00
parent 3df858fb85
commit 2c13ac54df
21 changed files with 808 additions and 177 deletions

View File

@@ -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

View File

@@ -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: {
// 目标指针大小,可以定义为 864位或从 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);
}