diff --git a/stage0/intern_pool.c b/stage0/intern_pool.c index 5ecfbad75a..ed1c137442 100644 --- 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 index 13cdb678f0..adcdc72149 100644 --- 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