stage1 解决重构哈希 nob优化支持头文件缓存以及win下exe缓存

This commit is contained in:
zzy committed 2026-09-17 20:55:21 +08:00
1 parent 70ac7380e9
commit fb0ff9b663
8 files changed
+236 -98

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
#include "spl_fold.h"
static usize spl_fold_bucket_hash(usize k) { return MAP_HASH_INT(k); }
static int spl_fold_bucket_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
void spl_fold_init(spl_fold_t *fold, void *ctx, spl_fold_eq_fn eq, spl_fold_next_fn next,
spl_fold_set_next_fn set_next) {
map_init(fold->buckets, spl_fold_bucket_hash, spl_fold_bucket_cmp);
fold->ctx = ctx;
fold->eq = eq;
fold->next = next;
fold->set_next = set_next;
}
void spl_fold_drop(spl_fold_t *fold) { map_free(fold->buckets); }
spl_fold_id_t spl_fold_find(const spl_fold_t *fold, usize hash, const void *probe) {
spl_fold_id_t cur = 0;
if (!map_get(fold->buckets, hash, &cur))
return 0;
while (cur) {
if (fold->eq(fold->ctx, cur, probe))
return cur;
cur = fold->next(fold->ctx, cur);
}
return 0;
}
void spl_fold_insert(spl_fold_t *fold, usize hash, spl_fold_id_t id) {
spl_fold_id_t head = 0;
map_get(fold->buckets, hash, &head);
fold->set_next(fold->ctx, id, head);
map_put(fold->buckets, hash, id);
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef __SPL_FOLD_H__
#define __SPL_FOLD_H__
#include "../stage0/include/utils.h"
/* 通用 intrusive 哈希集合,对应 LLVM FoldingSet 的桶链部分。
- 节点表由调用方持有,节点自带 next 字段;
- hash 只用于选择桶(本实现以完整 hash 值作桶 map 的 key),
相等始终由 eq 回调做结构比较;
- 只增不删,适合类型 intern。 */
typedef usize spl_fold_id_t;
/* 相等返回非零;probe 指向调用方的临时(尚未入表)节点。 */
typedef int (*spl_fold_eq_fn)(void *ctx, spl_fold_id_t node, const void *probe);
typedef spl_fold_id_t (*spl_fold_next_fn)(void *ctx, spl_fold_id_t node);
typedef void (*spl_fold_set_next_fn)(void *ctx, spl_fold_id_t node, spl_fold_id_t next);
typedef struct {
MAP(usize, spl_fold_id_t) buckets;
void *ctx;
spl_fold_eq_fn eq;
spl_fold_next_fn next;
spl_fold_set_next_fn set_next;
} spl_fold_t;
void spl_fold_init(spl_fold_t *fold, void *ctx, spl_fold_eq_fn eq, spl_fold_next_fn next,
spl_fold_set_next_fn set_next);
void spl_fold_drop(spl_fold_t *fold);
/* 命中返回已存在的 id,否则返回 0。 */
spl_fold_id_t spl_fold_find(const spl_fold_t *fold, usize hash, const void *probe);
/* 把已分配 id 的节点挂到对应桶头。 */
void spl_fold_insert(spl_fold_t *fold, usize hash, spl_fold_id_t id);
#endif /* __SPL_FOLD_H__ */
+40 -26
View File
@@ -1,36 +1,37 @@
#include "spl_lang_type.h"
static usize spl_lang_type_hash(spl_lang_type_node_t n) {
usize hash = (usize)n.kind * 131 + n.ir_type_id;
usize hash = spl_hash_seed();
hash = spl_hash_mix(hash, (usize)n.kind);
hash = spl_hash_mix(hash, n.ir_type_id);
switch (n.kind) {
case SPL_LANG_TYPE_PTR:
case SPL_LANG_TYPE_SLICE:
case SPL_LANG_TYPE_RANGE:
hash += n.extra.elem;
hash = spl_hash_mix(hash, n.extra.elem);
break;
case SPL_LANG_TYPE_TUPLE:
hash = spl_hash_mix(hash, vec_size(n.extra.elems));
for (usize i = 0; i < vec_size(n.extra.elems); i++) {
hash += vec_at(n.extra.elems, i);
hash = spl_hash_mix(hash, vec_at(n.extra.elems, i));
}
break;
case SPL_LANG_TYPE_FN:
hash += n.extra.fn.ret;
hash = spl_hash_mix(hash, n.extra.fn.ret);
hash = spl_hash_mix(hash, vec_size(n.extra.fn.params));
for (usize i = 0; i < vec_size(n.extra.fn.params); i++) {
hash += vec_at(n.extra.fn.params, i);
hash = spl_hash_mix(hash, vec_at(n.extra.fn.params, i));
}
break;
case SPL_LANG_TYPE_STRUCT:
case SPL_LANG_TYPE_UNION:
case SPL_LANG_TYPE_ENUM:
case SPL_LANG_TYPE_SHAPE:
hash = spl_hash_mix(hash, vec_size(n.methods));
for (usize i = 0; i < vec_size(n.methods); i++) {
spl_lang_method_t *m = &vec_at(n.methods, i);
hash += m->def_id * 31;
if (m->name) {
const char *s = m->name;
while (*s)
hash = hash * 31 + (usize)(*s++);
}
hash = spl_hash_mix(hash, m->def_id);
hash = spl_hash_mix_str(hash, m->name);
}
break;
default:
@@ -87,9 +88,6 @@ static int spl_lang_type_eq(spl_lang_type_node_t n1, spl_lang_type_node_t n2) {
}
}
static usize spl_lang_map_hash(usize k) { return MAP_HASH_INT(k); }
static int spl_lang_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
static void spl_lang_node_free_extra(spl_lang_type_node_t *n) {
switch (n->kind) {
case SPL_LANG_TYPE_TUPLE:
@@ -109,20 +107,35 @@ static void spl_lang_node_free_extra(spl_lang_type_node_t *n) {
}
}
/* spl_fold 回调:只在链内做结构比较(同桶已保证 hash 相同)。 */
static int spl_lang_fold_eq(void *ctx, spl_fold_id_t node, const void *probe) {
spl_lang_type_t *type = (spl_lang_type_t *)ctx;
return spl_lang_type_eq(vec_at(type->lang_table, node),
*(const spl_lang_type_node_t *)probe) == 0;
}
static spl_fold_id_t spl_lang_fold_next(void *ctx, spl_fold_id_t node) {
spl_lang_type_t *type = (spl_lang_type_t *)ctx;
return vec_at(type->lang_table, node).hash_next;
}
static void spl_lang_fold_set_next(void *ctx, spl_fold_id_t node, spl_fold_id_t next) {
spl_lang_type_t *type = (spl_lang_type_t *)ctx;
vec_at(type->lang_table, node).hash_next = next;
}
spl_lang_type_id_t spl_lang_node_push(spl_lang_type_t *type, spl_lang_type_node_t *node) {
usize hash = spl_lang_type_hash(*node);
usize idx = (usize)-1;
spl_lang_type_id_t cand = 0;
while (map_get_continue(type->lang_map, hash, &cand, &idx)) {
spl_lang_type_node_t *existing = &vec_at(type->lang_table, cand);
if (spl_lang_type_eq(*existing, *node) == 0) {
spl_lang_node_free_extra(node);
return cand;
}
spl_lang_type_id_t existing = spl_fold_find(&type->lang_fold, hash, node);
if (existing) {
spl_lang_node_free_extra(node);
return existing;
}
spl_lang_type_id_t id = vec_size(type->lang_table);
vec_push(type->lang_table, *node);
map_put_new(type->lang_map, hash, id);
spl_fold_insert(&type->lang_fold, hash, id);
node->kind = SPL_LANG_TYPE_ERROR;
return id;
}
@@ -133,7 +146,8 @@ void spl_lang_type_init(spl_lang_type_t *type) {
vec_init(type->lang_table);
spl_lang_type_node_t lang_node = {0};
vec_push(type->lang_table, lang_node);
map_init(type->lang_map, spl_lang_map_hash, spl_lang_map_cmp);
spl_fold_init(&type->lang_fold, type, spl_lang_fold_eq, spl_lang_fold_next,
spl_lang_fold_set_next);
vec_init(type->def_table);
vec_push(type->def_table, (spl_def_node_t){0});
@@ -144,7 +158,7 @@ void spl_lang_type_drop(spl_lang_type_t *type) {
spl_lang_type_node_t *n = &vec_at(type->lang_table, i);
spl_lang_node_free_extra(n);
}
map_free(type->lang_map);
spl_fold_drop(&type->lang_fold);
vec_free(type->lang_table);
vec_free(type->def_table);
@@ -182,7 +196,7 @@ void spl_lang_define_ir(spl_lang_type_t *type, spl_type_id_t id, spl_type_node_t
return;
spl_type_node_t *slot = &vec_at(type->ir.type_table, id);
/* slot 原是空 ERROR 节点,无 vec 字段可释放。node 的 vec 字段 move 进 slot。
占位 id 不写 type_map,不参与 hash-consing。 */
占位 id 不写 type_fold,不参与 hash-consing。 */
*slot = *node;
node->kind = SPL_TYPE_ERROR;
}
+3 -3
View File
@@ -51,9 +51,9 @@ typedef struct {
spl_lang_type_id_t ret;
} fn;
} extra;
usize hash_next; /* 同 hash 桶内下一个类型 id;0 表示链尾。不参与相等比较。 */
} spl_lang_type_node_t;
typedef VEC(spl_lang_type_node_t) spl_lang_type_vec_t;
typedef MAP(usize, spl_lang_type_id_t) spl_lang_type_map_t;
typedef enum {
SPL_DEF_ERROR,
@@ -91,7 +91,7 @@ typedef VEC(spl_def_node_t) spl_def_node_vec_t;
typedef struct {
spl_type_t ir;
spl_lang_type_vec_t lang_table;
spl_lang_type_map_t lang_map;
spl_fold_t lang_fold;
spl_def_node_vec_t def_table;
} spl_lang_type_t;
@@ -105,7 +105,7 @@ spl_type_id_t spl_lang_type_get_ir_type(spl_lang_type_t *type, spl_lang_type_id_
/* 前向引用支持:reserve 一个 type_table 空槽位(kind=ERROR)作为身份锚点,
让 *Node / []Node 这类成员能拿到稳定 pointee;成员解析完后再调 define
把真实内容填进去。占位槽位**不写 type_map**,不参与 hash-consing——
把真实内容填进去。占位槽位**不写 type_fold**,不参与 hash-consing——
后续相同形状的类型走 spl_type_node_push 会生成独立 id,语义等价。 */
spl_type_id_t spl_lang_reserve_ir(spl_lang_type_t *type);
void spl_lang_define_ir(spl_lang_type_t *type, spl_type_id_t id, spl_type_node_t *node);
+44 -31
View File
@@ -1,7 +1,8 @@
#include "spl_type.h"
static usize spl_type_hash(spl_type_node_t n) {
usize hash = (usize)n.kind * 131;
usize hash = spl_hash_seed();
hash = spl_hash_mix(hash, (usize)n.kind);
switch (n.kind) {
case SPL_TYPE_ERROR:
case SPL_TYPE_UNIT:
@@ -13,38 +14,38 @@ static usize spl_type_hash(spl_type_node_t n) {
case SPL_TYPE_BOOL:
break;
case SPL_TYPE_INT:
hash += n.int_type.bits + (usize)n.int_type.is_signed;
hash = spl_hash_mix(hash, n.int_type.bits);
hash = spl_hash_mix(hash, (usize)n.int_type.is_signed);
break;
case SPL_TYPE_FLOAT:
hash += n.float_type.bits;
hash = spl_hash_mix(hash, n.float_type.bits);
break;
case SPL_TYPE_PTR:
hash += n.ptr_type.pointee;
hash = spl_hash_mix(hash, n.ptr_type.pointee);
break;
case SPL_TYPE_ARRAY:
hash += n.array_type.element + n.array_type.len;
hash = spl_hash_mix(hash, n.array_type.element);
hash = spl_hash_mix(hash, n.array_type.len);
break;
case SPL_TYPE_STRUCT:
case SPL_TYPE_UNION:
case SPL_TYPE_ENUM:
case SPL_TYPE_SHAPE:
hash += (usize)n.layout.mode * 31 + n.layout.fixed_align_bits;
hash += n.agg_type.tag_type;
hash = spl_hash_mix(hash, (usize)n.layout.mode);
hash = spl_hash_mix(hash, n.layout.fixed_align_bits);
hash = spl_hash_mix(hash, n.agg_type.tag_type);
hash = spl_hash_mix(hash, vec_size(n.agg_type.variants));
for (usize i = 0; i < vec_size(n.agg_type.variants); i++) {
spl_type_member_t *m = &n.agg_type.variants.data[i];
hash += m->type_id;
if (m->name) {
const char *s = m->name;
while (*s) {
hash = hash * 31 + (usize)(*s++);
}
}
spl_type_member_t *m = &vec_at(n.agg_type.variants, i);
hash = spl_hash_mix(hash, m->type_id);
hash = spl_hash_mix_str(hash, m->name);
}
break;
case SPL_TYPE_FN:
hash += n.fn_type.ret;
hash = spl_hash_mix(hash, n.fn_type.ret);
hash = spl_hash_mix(hash, vec_size(n.fn_type.params));
for (usize i = 0; i < vec_size(n.fn_type.params); i++) {
hash += vec_at(n.fn_type.params, i);
hash = spl_hash_mix(hash, vec_at(n.fn_type.params, i));
}
break;
}
@@ -110,9 +111,6 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) {
return 1;
}
static usize spl_type_map_hash(usize k) { return MAP_HASH_INT(k); }
static int spl_type_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
static void spl_type_node_free_vecs(spl_type_node_t *tn) {
switch (tn->kind) {
case SPL_TYPE_STRUCT:
@@ -129,20 +127,34 @@ static void spl_type_node_free_vecs(spl_type_node_t *tn) {
}
}
/* spl_fold 回调:只在链内做结构比较(同桶已保证 hash 相同)。 */
static int spl_type_fold_eq(void *ctx, spl_fold_id_t node, const void *probe) {
spl_type_t *type = (spl_type_t *)ctx;
return spl_type_eq(vec_at(type->type_table, node), *(const spl_type_node_t *)probe) == 0;
}
static spl_fold_id_t spl_type_fold_next(void *ctx, spl_fold_id_t node) {
spl_type_t *type = (spl_type_t *)ctx;
return vec_at(type->type_table, node).hash_next;
}
static void spl_type_fold_set_next(void *ctx, spl_fold_id_t node, spl_fold_id_t next) {
spl_type_t *type = (spl_type_t *)ctx;
vec_at(type->type_table, node).hash_next = next;
}
spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t *tn) {
usize hash = spl_type_hash(*tn);
usize idx = (usize)-1;
spl_type_id_t cand = 0;
while (map_get_continue(type->type_map, hash, &cand, &idx)) {
spl_type_node_t *existing = &vec_at(type->type_table, cand);
if (spl_type_eq(*existing, *tn) == 0) {
spl_type_node_free_vecs(tn);
return cand;
}
spl_type_id_t existing = spl_fold_find(&type->type_fold, hash, tn);
if (existing) {
spl_type_node_free_vecs(tn);
return existing;
}
spl_type_id_t id = vec_size(type->type_table);
vec_push(type->type_table, *tn);
map_put_new(type->type_map, hash, id);
spl_fold_insert(&type->type_fold, hash, id);
tn->kind = SPL_TYPE_ERROR;
return id;
}
@@ -151,7 +163,8 @@ void spl_type_init(spl_type_t *type) {
vec_init(type->type_table);
spl_type_node_t type_node = {0};
vec_push(type->type_table, type_node);
map_init(type->type_map, spl_type_map_hash, spl_type_map_cmp);
spl_fold_init(&type->type_fold, type, spl_type_fold_eq, spl_type_fold_next,
spl_type_fold_set_next);
}
void spl_type_drop(spl_type_t *type) {
@@ -159,7 +172,7 @@ void spl_type_drop(spl_type_t *type) {
spl_type_node_t *n = &vec_at(type->type_table, i);
spl_type_node_free_vecs(n);
}
map_free(type->type_map);
spl_fold_drop(&type->type_fold);
vec_free(type->type_table);
}
+23 -3
View File
@@ -2,6 +2,27 @@
#define __SPL_TYPE_H__
#include "../stage0/include/utils.h"
#include "spl_fold.h"
/* 类型 intern 用的哈希混合(FNV-1a 风格,顺序敏感)。
hash 只用于选择桶;相等判定始终由结构比较完成。 */
static inline usize spl_hash_mix(usize h, usize x) {
h ^= x;
h *= (usize)1099511628211ULL;
return h;
}
static inline usize spl_hash_mix_str(usize h, const char *s) {
if (!s)
return spl_hash_mix(h, 0);
while (*s) {
h = spl_hash_mix(h, (usize)(unsigned char)*s);
s++;
}
return spl_hash_mix(h, 0); /* 终止符参与混合,避免名称拼接歧义 */
}
static inline usize spl_hash_seed(void) { return (usize)14695981039346656037ULL; }
typedef usize spl_type_id_t;
typedef VEC(spl_type_id_t) spl_type_id_vec_t;
@@ -73,14 +94,13 @@ typedef struct {
struct {
} shape_type;
};
usize hash_next; /* 同 hash 桶内下一个类型 id;0 表示链尾。不参与相等比较。 */
} spl_type_node_t;
typedef VEC(spl_type_node_t) spl_type_node_vec_t;
typedef MAP(usize, spl_type_id_t) spl_type_node_map_t;
typedef struct {
spl_type_node_vec_t type_table;
spl_type_node_map_t type_map;
spl_fold_t type_fold;
} spl_type_t;
void spl_type_init(spl_type_t *type);