commit b5ce51eee7efab8cfee67b3f57bf1631781cf53a (tree)
parent 0b041e0c70bc7ce4e1249018216f6d49b7909483
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Tue, 17 Feb 2026 19:56:05 +0000
stage0: implement InternPool core (Phase B)
Pre-populate 124 entries matching upstream InternPool.Index enum:
- Integer types (u0-u256, i0-i128), simple types, float types
- Pointer types (*usize, [*]u8, []const u8, etc.) with flag encoding
- All 47 vector types in exact upstream order
- Values: undef/zero/one variants, void/null/true/false/unreachable
Add hash table with open addressing + linear probing for dedup.
Implement ipIntern (lookup-or-insert), ipIndexToKey, ipTypeOf.
Add TypedInt struct and PTR_FLAGS_* defines to intern_pool.h.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 727 insertions(+), 8 deletions(-)
diff --git a/stage0/intern_pool.c b/stage0/intern_pool.c
@@ -7,6 +7,265 @@
#define IP_STRING_INITIAL_CAP 1024
#define IP_EXTRA_INITIAL_CAP 256
+// --- Hash helpers ---
+
+static uint32_t ipHashCombine(uint32_t h, uint32_t val) {
+ h ^= val + 0x9e3779b9 + (h << 6) + (h >> 2);
+ return h;
+}
+
+static uint32_t ipHashKey(const InternPoolKey* key) {
+ uint32_t h = (uint32_t)key->tag;
+ switch (key->tag) {
+ case IP_KEY_INT_TYPE:
+ h = ipHashCombine(h, key->data.int_type.bits);
+ h = ipHashCombine(h, key->data.int_type.signedness);
+ break;
+ case IP_KEY_PTR_TYPE:
+ h = ipHashCombine(h, key->data.ptr_type.child);
+ h = ipHashCombine(h, key->data.ptr_type.sentinel);
+ h = ipHashCombine(h, key->data.ptr_type.flags);
+ h = ipHashCombine(h, key->data.ptr_type.packed_offset);
+ break;
+ case IP_KEY_ARRAY_TYPE:
+ h = ipHashCombine(h, (uint32_t)key->data.array_type.len);
+ h = ipHashCombine(h, (uint32_t)(key->data.array_type.len >> 32));
+ h = ipHashCombine(h, key->data.array_type.child);
+ h = ipHashCombine(h, key->data.array_type.sentinel);
+ break;
+ case IP_KEY_VECTOR_TYPE:
+ h = ipHashCombine(h, key->data.vector_type.len);
+ h = ipHashCombine(h, key->data.vector_type.child);
+ break;
+ case IP_KEY_OPT_TYPE:
+ h = ipHashCombine(h, key->data.opt_type);
+ break;
+ case IP_KEY_ANYFRAME_TYPE:
+ h = ipHashCombine(h, key->data.anyframe_type);
+ break;
+ case IP_KEY_ERROR_UNION_TYPE:
+ h = ipHashCombine(h, key->data.error_union_type.error_set);
+ h = ipHashCombine(h, key->data.error_union_type.payload);
+ break;
+ case IP_KEY_SIMPLE_TYPE:
+ h = ipHashCombine(h, (uint32_t)key->data.simple_type);
+ break;
+ case IP_KEY_SIMPLE_VALUE:
+ h = ipHashCombine(h, (uint32_t)key->data.simple_value);
+ break;
+ case IP_KEY_UNDEF:
+ h = ipHashCombine(h, key->data.undef);
+ break;
+ case IP_KEY_INT:
+ h = ipHashCombine(h, key->data.int_val.ty);
+ h = ipHashCombine(h, (uint32_t)key->data.int_val.value);
+ h = ipHashCombine(h, (uint32_t)(key->data.int_val.value >> 32));
+ h = ipHashCombine(h, (uint32_t)key->data.int_val.is_negative);
+ break;
+ case IP_KEY_TUPLE_TYPE:
+ h = ipHashCombine(h, key->data.tuple_type);
+ break;
+ default:
+ /* For other tag types, just use the tag hash. */
+ break;
+ }
+ return h;
+}
+
+static bool ipKeysEqual(const InternPoolKey* a, const InternPoolKey* b) {
+ if (a->tag != b->tag) {
+ return false;
+ }
+ switch (a->tag) {
+ case IP_KEY_INT_TYPE:
+ return a->data.int_type.bits == b->data.int_type.bits
+ && a->data.int_type.signedness == b->data.int_type.signedness;
+ case IP_KEY_PTR_TYPE:
+ return a->data.ptr_type.child == b->data.ptr_type.child
+ && a->data.ptr_type.sentinel == b->data.ptr_type.sentinel
+ && a->data.ptr_type.flags == b->data.ptr_type.flags
+ && a->data.ptr_type.packed_offset
+ == b->data.ptr_type.packed_offset;
+ case IP_KEY_ARRAY_TYPE:
+ return a->data.array_type.len == b->data.array_type.len
+ && a->data.array_type.child == b->data.array_type.child
+ && a->data.array_type.sentinel == b->data.array_type.sentinel;
+ case IP_KEY_VECTOR_TYPE:
+ return a->data.vector_type.len == b->data.vector_type.len
+ && a->data.vector_type.child == b->data.vector_type.child;
+ case IP_KEY_OPT_TYPE:
+ return a->data.opt_type == b->data.opt_type;
+ case IP_KEY_ANYFRAME_TYPE:
+ return a->data.anyframe_type == b->data.anyframe_type;
+ case IP_KEY_ERROR_UNION_TYPE:
+ return a->data.error_union_type.error_set
+ == b->data.error_union_type.error_set
+ && a->data.error_union_type.payload
+ == b->data.error_union_type.payload;
+ case IP_KEY_SIMPLE_TYPE:
+ return a->data.simple_type == b->data.simple_type;
+ case IP_KEY_SIMPLE_VALUE:
+ return a->data.simple_value == b->data.simple_value;
+ case IP_KEY_UNDEF:
+ return a->data.undef == b->data.undef;
+ case IP_KEY_INT:
+ return a->data.int_val.ty == b->data.int_val.ty
+ && a->data.int_val.value == b->data.int_val.value
+ && a->data.int_val.is_negative == b->data.int_val.is_negative;
+ case IP_KEY_TUPLE_TYPE:
+ return a->data.tuple_type == b->data.tuple_type;
+ default:
+ /* Fallback: memcmp the entire data union. */
+ return memcmp(&a->data, &b->data, sizeof(a->data)) == 0;
+ }
+}
+
+// --- Helper to append an item directly (bypassing hash) ---
+
+static void ipAppendItem(InternPool* ip, InternPoolKey key) {
+ if (ip->items_len >= ip->items_cap) {
+ uint32_t new_cap = ip->items_cap * 2;
+ InternPoolKey* new_items
+ = realloc(ip->items, new_cap * sizeof(InternPoolKey));
+ if (!new_items) {
+ exit(1);
+ }
+ ip->items = new_items;
+ ip->items_cap = new_cap;
+ }
+ ip->items[ip->items_len] = key;
+ ip->items_len++;
+}
+
+// --- Hash table rebuild ---
+
+static void ipRebuildHash(InternPool* ip) {
+ memset(ip->hash_table, 0xFF, ip->hash_cap * sizeof(uint32_t));
+ for (uint32_t i = 0; i < ip->items_len; i++) {
+ uint32_t h = ipHashKey(&ip->items[i]) & (ip->hash_cap - 1);
+ while (ip->hash_table[h] != IP_INDEX_NONE) {
+ h = (h + 1) & (ip->hash_cap - 1);
+ }
+ ip->hash_table[h] = i;
+ }
+}
+
+// --- Hash table grow ---
+
+static void ipGrowHash(InternPool* ip) {
+ uint32_t new_cap = ip->hash_cap * 2;
+ uint32_t* new_table = realloc(ip->hash_table, new_cap * sizeof(uint32_t));
+ if (!new_table) {
+ exit(1);
+ }
+ ip->hash_table = new_table;
+ ip->hash_cap = new_cap;
+ ipRebuildHash(ip);
+}
+
+// --- Pre-interned key builders ---
+
+static InternPoolKey ipMakeIntType(uint16_t bits, uint8_t signedness) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_INT_TYPE;
+ key.data.int_type.bits = bits;
+ key.data.int_type.signedness = signedness;
+ return key;
+}
+
+static InternPoolKey ipMakeSimpleType(SimpleType st) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_SIMPLE_TYPE;
+ key.data.simple_type = st;
+ return key;
+}
+
+static InternPoolKey ipMakePtrType(
+ InternPoolIndex child, InternPoolIndex sentinel, uint32_t flags) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_PTR_TYPE;
+ key.data.ptr_type.child = child;
+ key.data.ptr_type.sentinel = sentinel;
+ key.data.ptr_type.flags = flags;
+ key.data.ptr_type.packed_offset = 0;
+ return key;
+}
+
+static InternPoolKey ipMakeVectorType(uint32_t len, InternPoolIndex child) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_VECTOR_TYPE;
+ key.data.vector_type.len = len;
+ key.data.vector_type.child = child;
+ return key;
+}
+
+static InternPoolKey ipMakeOptType(InternPoolIndex child) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_OPT_TYPE;
+ key.data.opt_type = child;
+ return key;
+}
+
+static InternPoolKey ipMakeErrorUnionType(
+ InternPoolIndex error_set, InternPoolIndex payload) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_ERROR_UNION_TYPE;
+ key.data.error_union_type.error_set = error_set;
+ key.data.error_union_type.payload = payload;
+ return key;
+}
+
+static InternPoolKey ipMakeTupleType(void) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_TUPLE_TYPE;
+ key.data.tuple_type = IP_INDEX_NONE;
+ return key;
+}
+
+static InternPoolKey ipMakeAnyframeType(InternPoolIndex return_type) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_ANYFRAME_TYPE;
+ key.data.anyframe_type = return_type;
+ return key;
+}
+
+static InternPoolKey ipMakeUndef(InternPoolIndex ty) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_UNDEF;
+ key.data.undef = ty;
+ return key;
+}
+
+static InternPoolKey ipMakeSimpleValue(SimpleValue sv) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_SIMPLE_VALUE;
+ key.data.simple_value = sv;
+ return key;
+}
+
+static InternPoolKey ipMakeTypedInt(
+ InternPoolIndex ty, uint64_t value, bool is_negative) {
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_INT;
+ key.data.int_val.ty = ty;
+ key.data.int_val.value = value;
+ key.data.int_val.is_negative = is_negative;
+ return key;
+}
+
+// --- ipInit: Pre-populate with all 124 pre-interned types/values ---
+
InternPool ipInit(void) {
InternPool ip;
memset(&ip, 0, sizeof(ip));
@@ -19,6 +278,232 @@ InternPool ipInit(void) {
ip.string_bytes_cap = IP_STRING_INITIAL_CAP;
ip.extra = ARR_INIT(uint32_t, IP_EXTRA_INITIAL_CAP);
ip.extra_cap = IP_EXTRA_INITIAL_CAP;
+
+ // Index 0: u0_type
+ ipAppendItem(&ip, ipMakeIntType(0, 0));
+ // Index 1: i0_type
+ ipAppendItem(&ip, ipMakeIntType(0, 1));
+ // Index 2: u1_type
+ ipAppendItem(&ip, ipMakeIntType(1, 0));
+ // Index 3: u8_type
+ ipAppendItem(&ip, ipMakeIntType(8, 0));
+ // Index 4: i8_type
+ ipAppendItem(&ip, ipMakeIntType(8, 1));
+ // Index 5: u16_type
+ ipAppendItem(&ip, ipMakeIntType(16, 0));
+ // Index 6: i16_type
+ ipAppendItem(&ip, ipMakeIntType(16, 1));
+ // Index 7: u29_type
+ ipAppendItem(&ip, ipMakeIntType(29, 0));
+ // Index 8: u32_type
+ ipAppendItem(&ip, ipMakeIntType(32, 0));
+ // Index 9: i32_type
+ ipAppendItem(&ip, ipMakeIntType(32, 1));
+ // Index 10: u64_type
+ ipAppendItem(&ip, ipMakeIntType(64, 0));
+ // Index 11: i64_type
+ ipAppendItem(&ip, ipMakeIntType(64, 1));
+ // Index 12: u80_type
+ ipAppendItem(&ip, ipMakeIntType(80, 0));
+ // Index 13: u128_type
+ ipAppendItem(&ip, ipMakeIntType(128, 0));
+ // Index 14: i128_type
+ ipAppendItem(&ip, ipMakeIntType(128, 1));
+ // Index 15: u256_type
+ ipAppendItem(&ip, ipMakeIntType(256, 0));
+
+ // Indices 16-27: simple types (usize..c_longdouble)
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_USIZE));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_ISIZE));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_CHAR));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_SHORT));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_USHORT));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_INT));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_UINT));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_LONG));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_ULONG));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_LONGLONG));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_ULONGLONG));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_C_LONGDOUBLE));
+
+ // Indices 28-32: float types
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_F16));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_F32));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_F64));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_F80));
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_F128));
+
+ // Index 33: anyopaque
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_ANYOPAQUE));
+ // Index 34: bool
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_BOOL));
+ // Index 35: void
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_VOID));
+ // Index 36: type
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_TYPE));
+ // Index 37: anyerror
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_ANYERROR));
+ // Index 38: comptime_int
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_COMPTIME_INT));
+ // Index 39: comptime_float
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_COMPTIME_FLOAT));
+ // Index 40: noreturn
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_NORETURN));
+ // Index 41: anyframe (with no return type = IP_INDEX_NONE)
+ ipAppendItem(&ip, ipMakeAnyframeType(IP_INDEX_NONE));
+ // Index 42: null type
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_NULL));
+ // Index 43: undefined type
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_UNDEFINED));
+ // Index 44: enum_literal type
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_ENUM_LITERAL));
+
+ // Index 45: *usize (single-item pointer to usize)
+ ipAppendItem(&ip,
+ ipMakePtrType(IP_INDEX_USIZE_TYPE, IP_INDEX_NONE, PTR_FLAGS_SIZE_ONE));
+
+ // Index 46: *const comptime_int
+ ipAppendItem(&ip,
+ ipMakePtrType(IP_INDEX_COMPTIME_INT_TYPE, IP_INDEX_NONE,
+ PTR_FLAGS_SIZE_ONE | PTR_FLAGS_IS_CONST));
+
+ // Index 47: [*]u8
+ ipAppendItem(&ip,
+ ipMakePtrType(IP_INDEX_U8_TYPE, IP_INDEX_NONE, PTR_FLAGS_SIZE_MANY));
+
+ // Index 48: [*]const u8
+ ipAppendItem(&ip,
+ ipMakePtrType(IP_INDEX_U8_TYPE, IP_INDEX_NONE,
+ PTR_FLAGS_SIZE_MANY | PTR_FLAGS_IS_CONST));
+
+ // Index 49: [*:0]const u8
+ ipAppendItem(&ip,
+ ipMakePtrType(IP_INDEX_U8_TYPE, IP_INDEX_ZERO_U8,
+ PTR_FLAGS_SIZE_MANY | PTR_FLAGS_IS_CONST));
+
+ // Index 50: []const u8
+ ipAppendItem(&ip,
+ ipMakePtrType(IP_INDEX_U8_TYPE, IP_INDEX_NONE,
+ PTR_FLAGS_SIZE_SLICE | PTR_FLAGS_IS_CONST));
+
+ // Index 51: [:0]const u8
+ ipAppendItem(&ip,
+ ipMakePtrType(IP_INDEX_U8_TYPE, IP_INDEX_ZERO_U8,
+ PTR_FLAGS_SIZE_SLICE | PTR_FLAGS_IS_CONST));
+
+ // Indices 52-98: vector types
+ // Matching InternPool.Index enum order exactly.
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_I8_TYPE)); // 52
+ ipAppendItem(&ip, ipMakeVectorType(16, IP_INDEX_I8_TYPE)); // 53
+ ipAppendItem(&ip, ipMakeVectorType(32, IP_INDEX_I8_TYPE)); // 54
+ ipAppendItem(&ip, ipMakeVectorType(64, IP_INDEX_I8_TYPE)); // 55
+ ipAppendItem(&ip, ipMakeVectorType(1, IP_INDEX_U8_TYPE)); // 56
+ ipAppendItem(&ip, ipMakeVectorType(2, IP_INDEX_U8_TYPE)); // 57
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_U8_TYPE)); // 58
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_U8_TYPE)); // 59
+ ipAppendItem(&ip, ipMakeVectorType(16, IP_INDEX_U8_TYPE)); // 60
+ ipAppendItem(&ip, ipMakeVectorType(32, IP_INDEX_U8_TYPE)); // 61
+ ipAppendItem(&ip, ipMakeVectorType(64, IP_INDEX_U8_TYPE)); // 62
+ ipAppendItem(&ip, ipMakeVectorType(2, IP_INDEX_I16_TYPE)); // 63
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_I16_TYPE)); // 64
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_I16_TYPE)); // 65
+ ipAppendItem(&ip, ipMakeVectorType(16, IP_INDEX_I16_TYPE)); // 66
+ ipAppendItem(&ip, ipMakeVectorType(32, IP_INDEX_I16_TYPE)); // 67
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_U16_TYPE)); // 68
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_U16_TYPE)); // 69
+ ipAppendItem(&ip, ipMakeVectorType(16, IP_INDEX_U16_TYPE)); // 70
+ ipAppendItem(&ip, ipMakeVectorType(32, IP_INDEX_U16_TYPE)); // 71
+ ipAppendItem(&ip, ipMakeVectorType(2, IP_INDEX_I32_TYPE)); // 72
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_I32_TYPE)); // 73
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_I32_TYPE)); // 74
+ ipAppendItem(&ip, ipMakeVectorType(16, IP_INDEX_I32_TYPE)); // 75
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_U32_TYPE)); // 76
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_U32_TYPE)); // 77
+ ipAppendItem(&ip, ipMakeVectorType(16, IP_INDEX_U32_TYPE)); // 78
+ ipAppendItem(&ip, ipMakeVectorType(2, IP_INDEX_I64_TYPE)); // 79
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_I64_TYPE)); // 80
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_I64_TYPE)); // 81
+ ipAppendItem(&ip, ipMakeVectorType(2, IP_INDEX_U64_TYPE)); // 82
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_U64_TYPE)); // 83
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_U64_TYPE)); // 84
+ ipAppendItem(&ip, ipMakeVectorType(1, IP_INDEX_U128_TYPE)); // 85
+ ipAppendItem(&ip, ipMakeVectorType(2, IP_INDEX_U128_TYPE)); // 86
+ ipAppendItem(&ip, ipMakeVectorType(1, IP_INDEX_U256_TYPE)); // 87
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_F16_TYPE)); // 88
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_F16_TYPE)); // 89
+ ipAppendItem(&ip, ipMakeVectorType(16, IP_INDEX_F16_TYPE)); // 90
+ ipAppendItem(&ip, ipMakeVectorType(32, IP_INDEX_F16_TYPE)); // 91
+ ipAppendItem(&ip, ipMakeVectorType(2, IP_INDEX_F32_TYPE)); // 92
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_F32_TYPE)); // 93
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_F32_TYPE)); // 94
+ ipAppendItem(&ip, ipMakeVectorType(16, IP_INDEX_F32_TYPE)); // 95
+ ipAppendItem(&ip, ipMakeVectorType(2, IP_INDEX_F64_TYPE)); // 96
+ ipAppendItem(&ip, ipMakeVectorType(4, IP_INDEX_F64_TYPE)); // 97
+ ipAppendItem(&ip, ipMakeVectorType(8, IP_INDEX_F64_TYPE)); // 98
+
+ // Index 99: ?noreturn
+ ipAppendItem(&ip, ipMakeOptType(IP_INDEX_NORETURN_TYPE));
+
+ // Index 100: anyerror!void
+ ipAppendItem(
+ &ip, ipMakeErrorUnionType(IP_INDEX_ANYERROR_TYPE, IP_INDEX_VOID_TYPE));
+
+ // Index 101: adhoc_inferred_error_set
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_ADHOC_INFERRED_ERROR_SET));
+
+ // Index 102: generic_poison
+ ipAppendItem(&ip, ipMakeSimpleType(SIMPLE_TYPE_GENERIC_POISON));
+
+ // Index 103: empty_tuple_type (tuple with zero elements)
+ ipAppendItem(&ip, ipMakeTupleType());
+
+ // Index 104: undef (untyped) -> simple_value undefined
+ ipAppendItem(&ip, ipMakeSimpleValue(SIMPLE_VALUE_UNDEFINED));
+ // Index 105: undef bool
+ ipAppendItem(&ip, ipMakeUndef(IP_INDEX_BOOL_TYPE));
+ // Index 106: undef usize
+ ipAppendItem(&ip, ipMakeUndef(IP_INDEX_USIZE_TYPE));
+ // Index 107: undef u1
+ ipAppendItem(&ip, ipMakeUndef(IP_INDEX_U1_TYPE));
+
+ // Index 108: zero (comptime_int)
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_COMPTIME_INT_TYPE, 0, false));
+ // Index 109: zero_usize
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_USIZE_TYPE, 0, false));
+ // Index 110: zero_u1
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_U1_TYPE, 0, false));
+ // Index 111: zero_u8
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_U8_TYPE, 0, false));
+
+ // Index 112: one (comptime_int)
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_COMPTIME_INT_TYPE, 1, false));
+ // Index 113: one_usize
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_USIZE_TYPE, 1, false));
+ // Index 114: one_u1
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_U1_TYPE, 1, false));
+ // Index 115: one_u8
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_U8_TYPE, 1, false));
+ // Index 116: four_u8
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_U8_TYPE, 4, false));
+ // Index 117: negative_one (comptime_int, -1)
+ ipAppendItem(&ip, ipMakeTypedInt(IP_INDEX_COMPTIME_INT_TYPE, 1, true));
+
+ // Index 118: void_value
+ ipAppendItem(&ip, ipMakeSimpleValue(SIMPLE_VALUE_VOID));
+ // Index 119: unreachable_value
+ ipAppendItem(&ip, ipMakeSimpleValue(SIMPLE_VALUE_UNREACHABLE));
+ // Index 120: null_value
+ ipAppendItem(&ip, ipMakeSimpleValue(SIMPLE_VALUE_NULL));
+ // Index 121: bool_true
+ ipAppendItem(&ip, ipMakeSimpleValue(SIMPLE_VALUE_TRUE));
+ // Index 122: bool_false
+ ipAppendItem(&ip, ipMakeSimpleValue(SIMPLE_VALUE_FALSE));
+ // Index 123: empty_tuple (value)
+ ipAppendItem(&ip, ipMakeSimpleValue(SIMPLE_VALUE_EMPTY_TUPLE));
+
+ // Build hash table from pre-interned entries.
+ ipRebuildHash(&ip);
+
return ip;
}
@@ -41,10 +526,25 @@ void ipDeinit(InternPool* ip) {
}
InternPoolIndex ipIntern(InternPool* ip, InternPoolKey key) {
- (void)ip;
- (void)key;
- // TODO: implement interning
- return IP_INDEX_NONE;
+ // Check load factor and grow if needed.
+ if (ip->items_len * 4 >= ip->hash_cap * 3) {
+ ipGrowHash(ip);
+ }
+
+ uint32_t h = ipHashKey(&key) & (ip->hash_cap - 1);
+ while (ip->hash_table[h] != IP_INDEX_NONE) {
+ uint32_t idx = ip->hash_table[h];
+ if (ipKeysEqual(&ip->items[idx], &key)) {
+ return idx;
+ }
+ h = (h + 1) & (ip->hash_cap - 1);
+ }
+
+ // Not found: append new item.
+ uint32_t new_index = ip->items_len;
+ ipAppendItem(ip, key);
+ ip->hash_table[h] = new_index;
+ return new_index;
}
InternPoolKey ipIndexToKey(const InternPool* ip, InternPoolIndex index) {
@@ -57,8 +557,209 @@ InternPoolKey ipIndexToKey(const InternPool* ip, InternPoolIndex index) {
}
InternPoolIndex ipTypeOf(const InternPool* ip, InternPoolIndex index) {
- (void)ip;
- (void)index;
- // TODO: implement type lookup
+ // Matching upstream InternPool.typeOf: hardcoded switch on pre-interned
+ // indices, then key-based lookup for dynamic entries.
+ switch (index) {
+ // All type indices (0-103) return type_type.
+ case IP_INDEX_U0_TYPE:
+ case IP_INDEX_I0_TYPE:
+ case IP_INDEX_U1_TYPE:
+ case IP_INDEX_U8_TYPE:
+ case IP_INDEX_I8_TYPE:
+ case IP_INDEX_U16_TYPE:
+ case IP_INDEX_I16_TYPE:
+ case IP_INDEX_U29_TYPE:
+ case IP_INDEX_U32_TYPE:
+ case IP_INDEX_I32_TYPE:
+ case IP_INDEX_U64_TYPE:
+ case IP_INDEX_I64_TYPE:
+ case IP_INDEX_U80_TYPE:
+ case IP_INDEX_U128_TYPE:
+ case IP_INDEX_I128_TYPE:
+ case IP_INDEX_U256_TYPE:
+ case IP_INDEX_USIZE_TYPE:
+ case IP_INDEX_ISIZE_TYPE:
+ case IP_INDEX_C_CHAR_TYPE:
+ case IP_INDEX_C_SHORT_TYPE:
+ case IP_INDEX_C_USHORT_TYPE:
+ case IP_INDEX_C_INT_TYPE:
+ case IP_INDEX_C_UINT_TYPE:
+ case IP_INDEX_C_LONG_TYPE:
+ case IP_INDEX_C_ULONG_TYPE:
+ case IP_INDEX_C_LONGLONG_TYPE:
+ case IP_INDEX_C_ULONGLONG_TYPE:
+ case IP_INDEX_C_LONGDOUBLE_TYPE:
+ case IP_INDEX_F16_TYPE:
+ case IP_INDEX_F32_TYPE:
+ case IP_INDEX_F64_TYPE:
+ case IP_INDEX_F80_TYPE:
+ case IP_INDEX_F128_TYPE:
+ case IP_INDEX_ANYOPAQUE_TYPE:
+ case IP_INDEX_BOOL_TYPE:
+ case IP_INDEX_VOID_TYPE:
+ case IP_INDEX_TYPE_TYPE:
+ case IP_INDEX_ANYERROR_TYPE:
+ case IP_INDEX_COMPTIME_INT_TYPE:
+ case IP_INDEX_COMPTIME_FLOAT_TYPE:
+ case IP_INDEX_NORETURN_TYPE:
+ case IP_INDEX_ANYFRAME_TYPE:
+ case IP_INDEX_NULL_TYPE:
+ case IP_INDEX_UNDEFINED_TYPE:
+ case IP_INDEX_ENUM_LITERAL_TYPE:
+ case IP_INDEX_PTR_USIZE_TYPE:
+ case IP_INDEX_PTR_CONST_COMPTIME_INT_TYPE:
+ case IP_INDEX_MANYPTR_U8_TYPE:
+ case IP_INDEX_MANYPTR_CONST_U8_TYPE:
+ case IP_INDEX_MANYPTR_CONST_U8_SENTINEL_0_TYPE:
+ case IP_INDEX_SLICE_CONST_U8_TYPE:
+ case IP_INDEX_SLICE_CONST_U8_SENTINEL_0_TYPE:
+ case IP_INDEX_VECTOR_8_I8_TYPE:
+ case IP_INDEX_VECTOR_16_I8_TYPE:
+ case IP_INDEX_VECTOR_32_I8_TYPE:
+ case IP_INDEX_VECTOR_64_I8_TYPE:
+ case IP_INDEX_VECTOR_1_U8_TYPE:
+ case IP_INDEX_VECTOR_2_U8_TYPE:
+ case IP_INDEX_VECTOR_4_U8_TYPE:
+ case IP_INDEX_VECTOR_8_U8_TYPE:
+ case IP_INDEX_VECTOR_16_U8_TYPE:
+ case IP_INDEX_VECTOR_32_U8_TYPE:
+ case IP_INDEX_VECTOR_64_U8_TYPE:
+ case IP_INDEX_VECTOR_2_I16_TYPE:
+ case IP_INDEX_VECTOR_4_I16_TYPE:
+ case IP_INDEX_VECTOR_8_I16_TYPE:
+ case IP_INDEX_VECTOR_16_I16_TYPE:
+ case IP_INDEX_VECTOR_32_I16_TYPE:
+ case IP_INDEX_VECTOR_4_U16_TYPE:
+ case IP_INDEX_VECTOR_8_U16_TYPE:
+ case IP_INDEX_VECTOR_16_U16_TYPE:
+ case IP_INDEX_VECTOR_32_U16_TYPE:
+ case IP_INDEX_VECTOR_2_I32_TYPE:
+ case IP_INDEX_VECTOR_4_I32_TYPE:
+ case IP_INDEX_VECTOR_8_I32_TYPE:
+ case IP_INDEX_VECTOR_16_I32_TYPE:
+ case IP_INDEX_VECTOR_4_U32_TYPE:
+ case IP_INDEX_VECTOR_8_U32_TYPE:
+ case IP_INDEX_VECTOR_16_U32_TYPE:
+ case IP_INDEX_VECTOR_2_I64_TYPE:
+ case IP_INDEX_VECTOR_4_I64_TYPE:
+ case IP_INDEX_VECTOR_8_I64_TYPE:
+ case IP_INDEX_VECTOR_2_U64_TYPE:
+ case IP_INDEX_VECTOR_4_U64_TYPE:
+ case IP_INDEX_VECTOR_8_U64_TYPE:
+ case IP_INDEX_VECTOR_1_U128_TYPE:
+ case IP_INDEX_VECTOR_2_U128_TYPE:
+ case IP_INDEX_VECTOR_1_U256_TYPE:
+ case IP_INDEX_VECTOR_4_F16_TYPE:
+ case IP_INDEX_VECTOR_8_F16_TYPE:
+ case IP_INDEX_VECTOR_16_F16_TYPE:
+ case IP_INDEX_VECTOR_32_F16_TYPE:
+ case IP_INDEX_VECTOR_2_F32_TYPE:
+ case IP_INDEX_VECTOR_4_F32_TYPE:
+ case IP_INDEX_VECTOR_8_F32_TYPE:
+ case IP_INDEX_VECTOR_16_F32_TYPE:
+ case IP_INDEX_VECTOR_2_F64_TYPE:
+ case IP_INDEX_VECTOR_4_F64_TYPE:
+ case IP_INDEX_VECTOR_8_F64_TYPE:
+ case IP_INDEX_OPTIONAL_NORETURN_TYPE:
+ case IP_INDEX_ANYERROR_VOID_ERROR_UNION_TYPE:
+ case IP_INDEX_ADHOC_INFERRED_ERROR_SET_TYPE:
+ case IP_INDEX_GENERIC_POISON_TYPE:
+ case IP_INDEX_EMPTY_TUPLE_TYPE:
+ return IP_INDEX_TYPE_TYPE;
+
+ // Pre-interned values with hardcoded types (matching upstream).
+ case IP_INDEX_UNDEF:
+ return IP_INDEX_UNDEFINED_TYPE;
+ case IP_INDEX_ZERO:
+ case IP_INDEX_ONE:
+ case IP_INDEX_NEGATIVE_ONE:
+ return IP_INDEX_COMPTIME_INT_TYPE;
+ case IP_INDEX_UNDEF_USIZE:
+ case IP_INDEX_ZERO_USIZE:
+ case IP_INDEX_ONE_USIZE:
+ return IP_INDEX_USIZE_TYPE;
+ case IP_INDEX_UNDEF_U1:
+ case IP_INDEX_ZERO_U1:
+ case IP_INDEX_ONE_U1:
+ return IP_INDEX_U1_TYPE;
+ case IP_INDEX_ZERO_U8:
+ case IP_INDEX_ONE_U8:
+ case IP_INDEX_FOUR_U8:
+ return IP_INDEX_U8_TYPE;
+ case IP_INDEX_VOID_VALUE:
+ return IP_INDEX_VOID_TYPE;
+ case IP_INDEX_UNREACHABLE_VALUE:
+ return IP_INDEX_NORETURN_TYPE;
+ case IP_INDEX_NULL_VALUE:
+ return IP_INDEX_NULL_TYPE;
+ case IP_INDEX_UNDEF_BOOL:
+ case IP_INDEX_BOOL_TRUE:
+ case IP_INDEX_BOOL_FALSE:
+ return IP_INDEX_BOOL_TYPE;
+ case IP_INDEX_EMPTY_TUPLE:
+ return IP_INDEX_EMPTY_TUPLE_TYPE;
+
+ default:
+ break;
+ }
+
+ // Dynamic entries: look up key and determine type from it.
+ if (index >= ip->items_len) {
+ return IP_INDEX_NONE;
+ }
+
+ InternPoolKey key = ip->items[index];
+ switch (key.tag) {
+ case IP_KEY_INT_TYPE:
+ case IP_KEY_PTR_TYPE:
+ case IP_KEY_ARRAY_TYPE:
+ case IP_KEY_VECTOR_TYPE:
+ case IP_KEY_OPT_TYPE:
+ case IP_KEY_ANYFRAME_TYPE:
+ case IP_KEY_ERROR_UNION_TYPE:
+ case IP_KEY_SIMPLE_TYPE:
+ case IP_KEY_STRUCT_TYPE:
+ case IP_KEY_TUPLE_TYPE:
+ case IP_KEY_UNION_TYPE:
+ case IP_KEY_OPAQUE_TYPE:
+ case IP_KEY_ENUM_TYPE:
+ case IP_KEY_FUNC_TYPE:
+ case IP_KEY_ERROR_SET_TYPE:
+ case IP_KEY_INFERRED_ERROR_SET_TYPE:
+ return IP_INDEX_TYPE_TYPE;
+
+ case IP_KEY_UNDEF:
+ return key.data.undef;
+ case IP_KEY_EMPTY_ENUM_VALUE:
+ return key.data.empty_enum_value;
+
+ case IP_KEY_SIMPLE_VALUE:
+ switch (key.data.simple_value) {
+ case SIMPLE_VALUE_UNDEFINED:
+ return IP_INDEX_UNDEFINED_TYPE;
+ case SIMPLE_VALUE_VOID:
+ return IP_INDEX_VOID_TYPE;
+ case SIMPLE_VALUE_NULL:
+ return IP_INDEX_NULL_TYPE;
+ case SIMPLE_VALUE_EMPTY_TUPLE:
+ return IP_INDEX_EMPTY_TUPLE_TYPE;
+ case SIMPLE_VALUE_TRUE:
+ case SIMPLE_VALUE_FALSE:
+ return IP_INDEX_BOOL_TYPE;
+ case SIMPLE_VALUE_UNREACHABLE:
+ return IP_INDEX_NORETURN_TYPE;
+ }
+ return IP_INDEX_NONE;
+
+ case IP_KEY_INT:
+ return key.data.int_val.ty;
+
+ case IP_KEY_ENUM_LITERAL:
+ return IP_INDEX_ENUM_LITERAL_TYPE;
+
+ default:
+ break;
+ }
+
return IP_INDEX_NONE;
}
diff --git a/stage0/intern_pool.h b/stage0/intern_pool.h
@@ -249,6 +249,24 @@ typedef struct {
uint32_t type_hash;
} NamespaceType;
+// --- Typed integer value (matching Key.Int) ---
+
+typedef struct {
+ InternPoolIndex ty;
+ uint64_t value;
+ bool is_negative;
+} TypedInt;
+
+// --- PtrType flags encoding ---
+// bits 0-1: size (0=one, 1=many, 2=slice, 3=c)
+// bit 8: is_const
+#define PTR_FLAGS_SIZE_ONE 0U
+#define PTR_FLAGS_SIZE_MANY 1U
+#define PTR_FLAGS_SIZE_SLICE 2U
+#define PTR_FLAGS_SIZE_C 3U
+#define PTR_FLAGS_SIZE_MASK 3U
+#define PTR_FLAGS_IS_CONST (1U << 8)
+
// --- InternPoolKeyTag enum (matching Key union variants) ---
typedef enum {
@@ -314,7 +332,7 @@ typedef struct {
InternPoolIndex variable;
InternPoolIndex extern_val;
InternPoolIndex func;
- uint64_t int_val;
+ TypedInt int_val;
InternPoolIndex err;
InternPoolIndex error_union;
uint32_t enum_literal; // string index