- 重构ast_dump.c中的宏定义,简化PRINT_VALUE、PRINT_NODE、 PRINT_QUOTED_VALUE等宏的实现 - 移除冗余的PRINT_COLORED宏定义 - 统一使用SCC_TREE_DUMP_PRINT_PURE和SCC_TREE_DUMP_PRINT_AROUND 宏进行转储输出 - 在dump_stmt_impl函数中优化节点转储逻辑,统一使用end_node_dump 替代手动换行 - 添加对未知节点类型的警告日志输出 - 创建新的ast2ir模块,包含AST到IR的基本转换功能 - 实现ast_type_to_ir_type、ast_expr_to_ir、ast_stmt_to_ir、 ast_decl_to_ir等核心转换函数 - 更新IR库依赖配置,添加scc_utils和tree_dump依赖 - 新增IR基础接口定义文件ir_base.h和IR构建器接口ir_builder.h
346 lines
11 KiB
C
346 lines
11 KiB
C
#include "ir_ctx.h"
|
||
#include "ir_builtin.h"
|
||
|
||
/**
|
||
* @brief 哈希混合函数(类似Rust的hash combine)
|
||
*
|
||
* Rust的默认哈希实现(SipHash 1-3)使用旋转和异或,
|
||
* 这里使用简单的FNV-1a变体,类似于Rust的`#[derive(Hash)]`
|
||
*/
|
||
static inline u32 scc_hash_mix(u32 seed, u32 value) {
|
||
// FNV-1a风格混合
|
||
return (seed ^ value) * 16777619u;
|
||
}
|
||
|
||
static u32 hash_key(const void *key) { return (u32)(usize)key; }
|
||
static int cmp_key(const void *key1, const void *key2) {
|
||
return (u32)(usize)key1 != (u32)(usize)key2;
|
||
}
|
||
static u32 hash_type(const scc_ir_type_t *key) {
|
||
// 初始哈希:tag
|
||
u32 hash = (u32)key->tag;
|
||
|
||
switch (key->tag) {
|
||
case SCC_IR_TYPE_VOID:
|
||
case SCC_IR_TYPE_I1:
|
||
case SCC_IR_TYPE_I8:
|
||
case SCC_IR_TYPE_I16:
|
||
case SCC_IR_TYPE_I32:
|
||
case SCC_IR_TYPE_I64:
|
||
case SCC_IR_TYPE_I128:
|
||
case SCC_IR_TYPE_F16:
|
||
case SCC_IR_TYPE_F32:
|
||
case SCC_IR_TYPE_F64:
|
||
case SCC_IR_TYPE_F128:
|
||
// 基本类型,只有tag
|
||
break;
|
||
|
||
case SCC_IR_TYPE_PTR:
|
||
hash = scc_hash_mix(hash, (u32)key->data.array.base);
|
||
break;
|
||
|
||
case SCC_IR_TYPE_ARRAY:
|
||
hash = scc_hash_mix(hash, (u32)key->data.array.base);
|
||
hash = scc_hash_mix(hash, (u32)key->data.array.len);
|
||
break;
|
||
|
||
case SCC_IR_TYPE_FUNC:
|
||
// 注意:这里需要递归哈希参数类型
|
||
hash = scc_hash_mix(hash, (u32)key->data.function.ret_type);
|
||
for (usize i = 0; i < key->data.function.params.size; i++) {
|
||
hash = scc_hash_mix(hash, (u32)key->data.function.params.data[i]);
|
||
}
|
||
hash = scc_hash_mix(hash, (u32)key->data.function.params.size);
|
||
break;
|
||
|
||
case SCC_IR_TYPE_STRUCT:
|
||
case SCC_IR_TYPE_VECTOR:
|
||
default:
|
||
UNREACHABLE();
|
||
return 0;
|
||
}
|
||
|
||
return hash;
|
||
}
|
||
static int cmp_type(const scc_ir_type_t *key1, const scc_ir_type_t *key2) {
|
||
// tag不同
|
||
if (key1->tag != key2->tag) {
|
||
return 1;
|
||
}
|
||
|
||
switch (key1->tag) {
|
||
case SCC_IR_TYPE_VOID:
|
||
case SCC_IR_TYPE_I1:
|
||
case SCC_IR_TYPE_I8:
|
||
case SCC_IR_TYPE_I16:
|
||
case SCC_IR_TYPE_I32:
|
||
case SCC_IR_TYPE_I64:
|
||
case SCC_IR_TYPE_I128:
|
||
case SCC_IR_TYPE_F16:
|
||
case SCC_IR_TYPE_F32:
|
||
case SCC_IR_TYPE_F64:
|
||
case SCC_IR_TYPE_F128:
|
||
return 0; // 基本类型,tag相同即可
|
||
case SCC_IR_TYPE_PTR:
|
||
return key1->data.pointer.base != key2->data.pointer.base;
|
||
|
||
case SCC_IR_TYPE_ARRAY:
|
||
return (key1->data.array.base != key2->data.array.base) ||
|
||
(key1->data.array.len != key2->data.array.len);
|
||
|
||
case SCC_IR_TYPE_FUNC: {
|
||
if (key1->data.function.ret_type != key2->data.function.ret_type) {
|
||
return 1;
|
||
}
|
||
|
||
if (key1->data.function.params.size !=
|
||
key2->data.function.params.size) {
|
||
return 1;
|
||
}
|
||
|
||
for (usize i = 0; i < key1->data.function.params.size; i++) {
|
||
if (key1->data.function.params.data[i] !=
|
||
key2->data.function.params.data[i]) {
|
||
return 1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
default:
|
||
UNREACHABLE();
|
||
return 1;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
void scc_ir_ctx_init(scc_ir_cprog_ctx_t *ctx) {
|
||
// 初始化向量
|
||
scc_vec_init(ctx->nodes);
|
||
scc_vec_init(ctx->types);
|
||
scc_vec_init(ctx->bblocks);
|
||
scc_vec_init(ctx->funcs);
|
||
|
||
// 设置哈希函数
|
||
ctx->uid2nodes.hash_func = hash_key;
|
||
ctx->uid2nodes.key_cmp = cmp_key;
|
||
ctx->uid2types.hash_func = hash_key;
|
||
ctx->uid2types.key_cmp = cmp_key;
|
||
ctx->uid2bblocks.hash_func = hash_key;
|
||
ctx->uid2bblocks.key_cmp = cmp_key;
|
||
ctx->uid2funcs.hash_func = hash_key;
|
||
ctx->uid2funcs.key_cmp = cmp_key;
|
||
// 初始化哈希表
|
||
scc_hashtable_init(&ctx->uid2nodes);
|
||
scc_hashtable_init(&ctx->uid2types);
|
||
scc_hashtable_init(&ctx->uid2bblocks);
|
||
scc_hashtable_init(&ctx->uid2funcs);
|
||
|
||
ctx->type_uniquing.hash_func = (void *)hash_type;
|
||
ctx->type_uniquing.key_cmp = (void *)cmp_type;
|
||
scc_hashtable_init(&ctx->type_uniquing);
|
||
|
||
// 预留UID 0 作为无效引用
|
||
ctx->node_uid = 1;
|
||
ctx->type_uid = 1;
|
||
ctx->bblock_uid = 1;
|
||
ctx->func_uid = 1;
|
||
}
|
||
|
||
void scc_ir_ctx_drop(scc_ir_cprog_ctx_t *ctx) {
|
||
// 释放所有实体的内部内存
|
||
for (usize i = 0; i < ctx->nodes.size; i++) {
|
||
scc_ir_node_t *node = &ctx->nodes.data[i];
|
||
scc_vec_free(node->used_by);
|
||
if (node->tag == SCC_IR_NODE_CALL) {
|
||
scc_vec_free(node->data.call.args);
|
||
}
|
||
}
|
||
|
||
for (usize i = 0; i < ctx->types.size; i++) {
|
||
scc_ir_type_t *type = &ctx->types.data[i];
|
||
if (type->tag == SCC_IR_TYPE_FUNC) {
|
||
scc_vec_free(type->data.function.params);
|
||
}
|
||
}
|
||
|
||
for (usize i = 0; i < ctx->bblocks.size; i++) {
|
||
scc_ir_bblock_t *bblock = &ctx->bblocks.data[i];
|
||
scc_vec_free(bblock->instrs);
|
||
}
|
||
|
||
for (usize i = 0; i < ctx->funcs.size; i++) {
|
||
scc_ir_func_t *func = &ctx->funcs.data[i];
|
||
scc_vec_free(func->params);
|
||
scc_vec_free(func->bblocks);
|
||
}
|
||
|
||
// 释放向量
|
||
scc_vec_free(ctx->nodes);
|
||
scc_vec_free(ctx->types);
|
||
scc_vec_free(ctx->bblocks);
|
||
scc_vec_free(ctx->funcs);
|
||
|
||
// 释放哈希表
|
||
scc_hashtable_drop(&ctx->uid2nodes);
|
||
scc_hashtable_drop(&ctx->uid2types);
|
||
scc_hashtable_drop(&ctx->uid2bblocks);
|
||
scc_hashtable_drop(&ctx->uid2funcs);
|
||
}
|
||
|
||
void scc_ir_ctx_reset(scc_ir_cprog_ctx_t *ctx) {
|
||
// 先销毁再重新初始化
|
||
scc_ir_ctx_drop(ctx);
|
||
scc_ir_ctx_init(ctx);
|
||
}
|
||
|
||
// 辅助宏:创建实体并添加到哈希表
|
||
#define CREATE_ENTITY(ctx, vec, uid, data, hashtable) \
|
||
do { \
|
||
/* 分配新UID */ \
|
||
unsigned new_uid = (ctx)->uid++; \
|
||
/* 添加到向量 */ \
|
||
scc_vec_push((vec), *(data)); \
|
||
/* 添加到哈希表 */ \
|
||
scc_hashtable_set(&(ctx)->hashtable, (const void *)(usize)new_uid, \
|
||
(void *)(usize)(scc_vec_size(vec) - 1)); \
|
||
return new_uid; \
|
||
} while (0)
|
||
|
||
scc_ir_type_ref_t scc_ir_ctx_new_type(scc_ir_cprog_ctx_t *ctx,
|
||
const scc_ir_type_t *type) {
|
||
// 首先检查去重表
|
||
void *existing = scc_hashtable_get(&ctx->type_uniquing, type);
|
||
if (existing) {
|
||
return (scc_ir_type_ref_t)(uintptr_t)existing;
|
||
}
|
||
|
||
// 创建新类型
|
||
unsigned new_uid = ctx->type_uid++;
|
||
scc_vec_push(ctx->types, *type);
|
||
|
||
// 添加到UID映射
|
||
usize idx = ctx->types.size - 1;
|
||
scc_hashtable_set(&ctx->uid2types, &new_uid, (void *)idx);
|
||
|
||
// 添加到去重表
|
||
scc_hashtable_set(&ctx->type_uniquing,
|
||
&ctx->types.data[idx], // 使用向量中的地址作为键
|
||
(void *)(uintptr_t)new_uid);
|
||
|
||
return new_uid;
|
||
}
|
||
|
||
scc_ir_node_ref_t scc_ir_ctx_new_node(scc_ir_cprog_ctx_t *ctx,
|
||
const scc_ir_node_t *node) {
|
||
CREATE_ENTITY(ctx, ctx->nodes, node_uid, node, uid2nodes);
|
||
}
|
||
|
||
scc_ir_bblock_ref_t scc_ir_ctx_new_bblock(scc_ir_cprog_ctx_t *ctx,
|
||
const scc_ir_bblock_t *bblock) {
|
||
CREATE_ENTITY(ctx, ctx->bblocks, bblock_uid, bblock, uid2bblocks);
|
||
}
|
||
|
||
scc_ir_func_ref_t scc_ir_ctx_new_func(scc_ir_cprog_ctx_t *ctx,
|
||
const scc_ir_func_t *func) {
|
||
CREATE_ENTITY(ctx, ctx->funcs, func_uid, func, uid2funcs);
|
||
}
|
||
|
||
#undef CREATE_ENTITY
|
||
|
||
// 辅助宏:从哈希表获取索引
|
||
#define GET_ENTITY_INDEX(ctx, ref, hashtable) \
|
||
((usize)scc_hashtable_get(&(ctx)->hashtable, (void *)(usize)ref))
|
||
|
||
scc_ir_type_t *scc_ir_ctx_get_type(scc_ir_cprog_ctx_t *ctx,
|
||
scc_ir_type_ref_t ref) {
|
||
if (ref == 0)
|
||
return null;
|
||
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2types);
|
||
if (idx >= ctx->types.size)
|
||
return null;
|
||
return &ctx->types.data[idx];
|
||
}
|
||
|
||
scc_ir_node_t *scc_ir_ctx_get_node(scc_ir_cprog_ctx_t *ctx,
|
||
scc_ir_node_ref_t ref) {
|
||
if (ref == 0)
|
||
return null;
|
||
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2nodes);
|
||
if (idx >= ctx->nodes.size)
|
||
return null;
|
||
return &ctx->nodes.data[idx];
|
||
}
|
||
|
||
scc_ir_bblock_t *scc_ir_ctx_get_bblock(scc_ir_cprog_ctx_t *ctx,
|
||
scc_ir_bblock_ref_t ref) {
|
||
if (ref == 0)
|
||
return null;
|
||
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2bblocks);
|
||
if (idx >= ctx->bblocks.size)
|
||
return null;
|
||
return &ctx->bblocks.data[idx];
|
||
}
|
||
|
||
scc_ir_func_t *scc_ir_ctx_get_func(scc_ir_cprog_ctx_t *ctx,
|
||
scc_ir_func_ref_t ref) {
|
||
if (ref == 0)
|
||
return null;
|
||
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2funcs);
|
||
if (idx >= ctx->funcs.size)
|
||
return null;
|
||
return &ctx->funcs.data[idx];
|
||
}
|
||
|
||
#undef GET_ENTITY_INDEX
|
||
|
||
// 内置类型和常量缓存
|
||
static scc_ir_type_ref_t cached_i32_type = 0;
|
||
static scc_ir_node_ref_t cached_zero_const = 0;
|
||
|
||
scc_ir_type_ref_t scc_ir_ctx_get_builtin_i32(scc_ir_cprog_ctx_t *ctx) {
|
||
if (cached_i32_type == 0) {
|
||
scc_ir_type_t i32_type = {.tag = SCC_IR_TYPE_I32};
|
||
cached_i32_type = scc_ir_ctx_new_type(ctx, &i32_type);
|
||
}
|
||
return cached_i32_type;
|
||
}
|
||
|
||
scc_ir_node_ref_t scc_ir_ctx_get_builtin_zero(scc_ir_cprog_ctx_t *ctx) {
|
||
if (cached_zero_const == 0) {
|
||
scc_ir_node_t zero_node = {.tag = SCC_IR_NODE_CONST_INT,
|
||
.type = scc_ir_ctx_get_builtin_i32(ctx),
|
||
.name = "zero",
|
||
.data.const_int.int32 = 0};
|
||
cached_zero_const = scc_ir_ctx_new_node(ctx, &zero_node);
|
||
}
|
||
return cached_zero_const;
|
||
}
|
||
|
||
// 常量池(简化版)
|
||
typedef struct {
|
||
i32 value;
|
||
scc_ir_node_ref_t ref;
|
||
} i32_const_entry_t;
|
||
|
||
scc_ir_node_ref_t scc_ir_ctx_get_i32_const(scc_ir_cprog_ctx_t *ctx, i32 value) {
|
||
// 如果是0,使用内置zero
|
||
if (value == 0) {
|
||
return scc_ir_ctx_get_builtin_zero(ctx);
|
||
}
|
||
|
||
// TODO: 实现常量池哈希表
|
||
// 这里简化实现,每次都创建新常量
|
||
scc_ir_node_t const_node = {.tag = SCC_IR_NODE_CONST_INT,
|
||
.type = scc_ir_ctx_get_builtin_i32(ctx),
|
||
.data.const_int.int32 = value};
|
||
|
||
const_node.name = "";
|
||
|
||
return scc_ir_ctx_new_node(ctx, &const_node);
|
||
}
|
||
|
||
scc_ir_node_ref_t scc_ir_ctx_get_null_const(scc_ir_cprog_ctx_t *ctx,
|
||
scc_ir_type_ref_t ptr_type) {
|
||
return 1;
|
||
}
|