#include /** * @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_type(const void *_key) { const scc_ir_type_t *key = _key; // 初始哈希:tag u32 hash = (u32)key->tag; switch (key->tag) { case SCC_IR_TYPE_void: case SCC_IR_TYPE_u8: case SCC_IR_TYPE_u16: case SCC_IR_TYPE_u32: case SCC_IR_TYPE_u64: case SCC_IR_TYPE_u128: 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 void *_key1, const void *_key2) { const scc_ir_type_t *key1 = _key1, *key2 = _key2; // tag不同 if (key1->tag != key2->tag) { return 1; } switch (key1->tag) { case SCC_IR_TYPE_void: case SCC_IR_TYPE_u8: case SCC_IR_TYPE_u16: case SCC_IR_TYPE_u32: case SCC_IR_TYPE_u64: case SCC_IR_TYPE_u128: 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_ctx_t *ctx, scc_ir_module_t *module) { ctx->module = module; scc_hashtable_init(&ctx->type_uniquing, hash_type, cmp_type); // scc_hashtable_init(&ctx->const_pool, /* 常量哈希函数 */, // /* 常量比较函数 */); scc_hashtable_init(&ctx->func_decl_set, (scc_hashtable_hash_func_t)scc_strhash32, (scc_hashtable_equal_func_t)scc_strcmp); } void scc_ir_ctx_drop(scc_ir_ctx_t *ctx) { scc_hashtable_drop(&ctx->type_uniquing); // scc_hashtable_drop(&ctx->const_pool); scc_hashtable_drop(&ctx->func_decl_set); } scc_ir_type_ref_t scc_ir_ctx_get_type(scc_ir_ctx_t *ctx, const scc_ir_type_t *type_desc) { // 先查哈希表 void *found = scc_hashtable_get(&ctx->type_uniquing, (void *)type_desc); if (found) { return (scc_ir_type_ref_t)(usize)found; } // 不存在,添加新类型 scc_ir_type_ref_t new_ref = scc_ir_module_add_type(ctx->module, type_desc); scc_hashtable_set(&ctx->type_uniquing, (void *)type_desc, (void *)(usize)new_ref); return new_ref; } // scc_ir_node_ref_t scc_ir_ctx_get_const_int(scc_ir_ctx_t *ctx, // scc_ir_type_ref_t type, i64 value) // { // return scc_ir_node_ref_t(); // } scc_ir_func_ref_t scc_ir_ctx_declare_func(scc_ir_ctx_t *ctx, scc_ir_type_ref_t type, const char *name) { // 检查是否已声明 void *found = scc_hashtable_get(&ctx->func_decl_set, (void *)name); if (found) { return (scc_ir_func_ref_t)(usize)found; } // 创建新函数 scc_ir_func_t func = { .name = name, .type = type, }; scc_vec_init(func.params); scc_vec_init(func.bblocks); scc_ir_func_ref_t new_ref = scc_ir_module_add_func(ctx->module, &func); scc_hashtable_set(&ctx->func_decl_set, (void *)name, (void *)(usize)new_ref); return new_ref; }