#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; }