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

@@ -68,6 +68,11 @@ void scc_hir_builder_init(scc_hir_builder_t *builder, scc_hir_cprog_t *cprog);
*/
void scc_hir_builder_drop(scc_hir_builder_t *builder);
static inline scc_hir_module_t *
scc_hir_builder_get_module(scc_hir_builder_t *builder) {
return &builder->cprog->module;
}
scc_hir_func_ref_t scc_hir_builder_func(scc_hir_builder_t *builder,
scc_hir_type_ref_t type_ref,
const char *name);
@@ -92,7 +97,7 @@ scc_hir_value_ref_t scc_hir_builder_alloca(scc_hir_builder_t *builder,
const char *name);
#define SCC_HIR_BUILDER_TYPE_FUNC(scc_type) \
[[maybe_unused]] static inline scc_hir_type_ref_t \
SCC_MAYBE_UNUSED static inline scc_hir_type_ref_t \
scc_hir_builder_type_##scc_type(scc_hir_builder_t *builder) { \
scc_hir_type_t type_desc; \
scc_hir_type_init(&type_desc, SCC_HIR_TYPE_##scc_type); \

View File

@@ -89,7 +89,9 @@ typedef enum scc_hir_value_tag {
SCC_HIR_VALUE_TAG_OP, ///< 二元运算
SCC_HIR_VALUE_TAG_BRANCH, ///< 有条件分支
SCC_HIR_VALUE_TAG_JUMP, ///< 无条件跳转
SCC_HIR_VALUE_TAG_JUMP_INDIRECT, ///< 无条件跳转(地址)
SCC_HIR_VALUE_TAG_CALL, ///< 调用函数
SCC_HIR_VALUE_TAG_CALL_INDIRECT, ///< 调用函数(地址)
SCC_HIR_VALUE_TAG_RET, ///< 函数返回
} scc_hir_value_tag_t;
@@ -222,11 +224,15 @@ struct scc_hir_value {
scc_hir_bblock_ref_t true_bblock;
scc_hir_bblock_ref_t false_bblock;
} branch;
struct {
union {
scc_hir_value_ref_t target_ptr;
scc_hir_bblock_ref_t target_bblock;
} jump;
struct {
scc_hir_func_ref_t callee; // TODO function pointer call
union {
scc_hir_func_ref_t func_ref;
scc_hir_value_ref_t ptr_ref;
} callee;
scc_hir_value_ref_vec_t args;
} call;
struct {

View File

@@ -105,7 +105,7 @@ void scc_hir_value_init(scc_hir_value_t *in, const char *name,
break;
case SCC_HIR_VALUE_TAG_CALL:
scc_vec_init(in->data.call.args);
in->data.call.callee = 0;
in->data.call.callee.func_ref = 0;
break;
case SCC_HIR_VALUE_TAG_RET:
in->data.ret.ret_val = 0;

View File

@@ -625,7 +625,7 @@ scc_hir_value_ref_t scc_hir_builder_call(scc_hir_builder_t *builder,
SCC_HIR_BUILDER_CHECK_NO_BORROW(builder);
scc_hir_value_t call_node = {0};
call_node.tag = SCC_HIR_VALUE_TAG_CALL;
call_node.data.call.callee = callee;
call_node.data.call.callee.func_ref = callee;
scc_vec_init(call_node.data.call.args);
for (usize i = 0; i < arg_count; i++) {

View File

@@ -3,7 +3,9 @@
#include <scc_tree_dump.h>
#define GET_MODULE(ctx) (&(ctx->cprog->module))
static void dump_type_with_visited(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref,
scc_hashtable_t *visited);
static const char *get_node_type_str(scc_hir_value_tag_t tag) {
static const char *node_types[] = {
[SCC_HIR_VALUE_TAG_NULLPTR] = "NullPtr",
@@ -168,9 +170,9 @@ static void dump_jump_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
static void dump_call_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
scc_tree_dump_begin_line(ctx->dump_ctx);
if (value->data.call.callee) {
scc_hir_func_t *callee =
scc_hir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
if (value->data.call.callee.func_ref) {
scc_hir_func_t *callee = scc_hir_module_get_func(
GET_MODULE(ctx), value->data.call.callee.func_ref);
scc_tree_dump_value(ctx->dump_ctx, "func='%s'",
callee ? (callee->name ? callee->name : "<unnamed>")
: "<invalid>");
@@ -256,60 +258,12 @@ void scc_hir_dump_value(scc_hir_dump_t *ctx, scc_hir_value_ref_t value_ref) {
break;
}
}
void scc_hir_dump_type(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref) {
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter");
return;
}
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Type: ");
scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag));
switch (type->tag) {
case SCC_HIR_TYPE_PTR:
if (type->data.pointer.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.pointer.base);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_ARRAY:
if (type->data.array.len > 0) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Array Length: ");
scc_tree_dump_value(ctx->dump_ctx, "%zu", type->data.array.len);
scc_tree_dump_append(ctx->dump_ctx, "\n");
}
if (type->data.array.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.array.base);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_FUNC:
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
cbool is_last = (i + 1 == scc_vec_size(type->data.function.params));
scc_tree_dump_push(ctx->dump_ctx, is_last);
scc_hir_dump_type(ctx, scc_vec_at(type->data.function.params, i));
scc_tree_dump_pop(ctx->dump_ctx);
}
if (type->data.function.ret_type) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.function.ret_type);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
default:
break;
}
scc_hashtable_t visited;
scc_hashtable_usize_init(&visited);
dump_type_with_visited(ctx, type_ref, &visited);
scc_hashtable_drop(&visited);
}
void scc_hir_dump_bblock(scc_hir_dump_t *ctx, scc_hir_bblock_ref_t bblock_ref) {
if (!ctx || !bblock_ref) {
LOG_ERROR("invalid parameter");
@@ -379,13 +333,94 @@ void scc_hir_dump_cprog(scc_hir_dump_t *ctx) {
}
// ----- 线性输出(保留原逻辑,改用新 API-----
void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref) {
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!ctx || !type) {
// 在 scc_hir_dump.c 中添加以下静态辅助函数(放在文件前部,现有函数之前)
static void dump_type_linear_with_visited(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref,
scc_hashtable_t *visited);
static void dump_type_with_visited(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref,
scc_hashtable_t *visited) {
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter");
return;
}
// 检查循环
if (scc_hashtable_get(visited, (void *)(usize)type_ref)) {
scc_tree_dump_append(ctx->dump_ctx, " <recursive>");
return;
}
scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1);
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Type: ");
scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag));
switch (type->tag) {
case SCC_HIR_TYPE_PTR:
if (type->data.pointer.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
dump_type_with_visited(ctx, type->data.pointer.base, visited);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_ARRAY:
if (type->data.array.len > 0) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Array Length: ");
scc_tree_dump_value(ctx->dump_ctx, "%zu", type->data.array.len);
scc_tree_dump_append(ctx->dump_ctx, "\n");
}
if (type->data.array.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
dump_type_with_visited(ctx, type->data.array.base, visited);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_FUNC:
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
cbool is_last = (i + 1 == scc_vec_size(type->data.function.params));
scc_tree_dump_push(ctx->dump_ctx, is_last);
dump_type_with_visited(
ctx, scc_vec_at(type->data.function.params, i), visited);
scc_tree_dump_pop(ctx->dump_ctx);
}
if (type->data.function.ret_type) {
scc_tree_dump_push(ctx->dump_ctx, true);
dump_type_with_visited(ctx, type->data.function.ret_type, visited);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
default:
break;
}
}
static void dump_type_linear_with_visited(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref,
scc_hashtable_t *visited) {
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter");
return;
}
// 检查循环
if (scc_hashtable_get(visited, (void *)(usize)type_ref)) {
scc_tree_dump_append(ctx->dump_ctx, " <recursive>");
return;
}
scc_hashtable_set(visited, (void *)(usize)type_ref, (void *)1);
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
switch (type->tag) {
case SCC_HIR_TYPE_unknown:
case SCC_HIR_TYPE_void:
@@ -407,24 +442,25 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
break;
case SCC_HIR_TYPE_ARRAY:
scc_tree_dump_append(ctx->dump_ctx, "[");
scc_hir_dump_type_linear(ctx, type->data.array.base);
dump_type_linear_with_visited(ctx, type->data.array.base, visited);
scc_tree_dump_append_fmt(ctx->dump_ctx, ", %zu]", type->data.array.len);
break;
case SCC_HIR_TYPE_PTR:
scc_tree_dump_append(ctx->dump_ctx, "*");
scc_hir_dump_type_linear(ctx, type->data.pointer.base);
dump_type_linear_with_visited(ctx, type->data.pointer.base, visited);
break;
case SCC_HIR_TYPE_FUNC:
scc_tree_dump_append(ctx->dump_ctx, "(");
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
if (i > 0)
scc_tree_dump_append(ctx->dump_ctx, ", ");
scc_hir_dump_type_linear(ctx,
scc_vec_at(type->data.function.params, i));
dump_type_linear_with_visited(
ctx, scc_vec_at(type->data.function.params, i), visited);
}
if (type->data.function.ret_type) {
scc_tree_dump_append(ctx->dump_ctx, ") -> ");
scc_hir_dump_type_linear(ctx, type->data.function.ret_type);
dump_type_linear_with_visited(ctx, type->data.function.ret_type,
visited);
} else {
scc_tree_dump_append(ctx->dump_ctx, ")");
}
@@ -434,9 +470,9 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
scc_tree_dump_append_fmt(ctx->dump_ctx, "%s {",
type->tag == SCC_HIR_TYPE_STRUCT ? "struct"
: "union");
scc_vec_foreach(type->data.aggregate.fields, i) {
scc_hir_dump_type_linear(
ctx, scc_vec_at(type->data.aggregate.fields, i));
for (usize i = 0; i < scc_vec_size(type->data.aggregate.fields); i++) {
dump_type_linear_with_visited(
ctx, scc_vec_at(type->data.aggregate.fields, i), visited);
scc_tree_dump_append(ctx->dump_ctx, ";");
}
scc_tree_dump_append(ctx->dump_ctx, "}");
@@ -447,6 +483,14 @@ void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
}
}
void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref) {
scc_hashtable_t visited;
scc_hashtable_usize_init(&visited);
dump_type_linear_with_visited(ctx, type_ref, &visited);
scc_hashtable_drop(&visited);
}
static void format_ref_or_value(scc_hir_dump_t *ctx,
scc_hir_value_ref_t value_ref) {
scc_hir_value_t *value =
@@ -580,8 +624,8 @@ void scc_hir_dump_value_linear(scc_hir_dump_t *ctx,
value->data.jump.target_bblock);
break;
case SCC_HIR_VALUE_TAG_CALL: {
scc_hir_func_t *func =
scc_hir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
scc_hir_func_t *func = scc_hir_module_get_func(
GET_MODULE(ctx), value->data.call.callee.func_ref);
scc_tree_dump_append_fmt(ctx->dump_ctx, "call @%s(",
func ? (func->name ? func->name : "<unnamed>")
: "<invalid>");