Files
zig/stage0/intern_pool.c
Motiejus Jakštys 25db8d160e 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>
2026-02-17 19:56:05 +00:00

766 lines
27 KiB
C

#include "intern_pool.h"
#include <stdlib.h>
#include <string.h>
#define IP_INITIAL_CAP 256
#define IP_HASH_INITIAL_CAP 512
#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));
ip.items = ARR_INIT(InternPoolKey, IP_INITIAL_CAP);
ip.items_cap = IP_INITIAL_CAP;
ip.hash_table = ARR_INIT(uint32_t, IP_HASH_INITIAL_CAP);
ip.hash_cap = IP_HASH_INITIAL_CAP;
memset(ip.hash_table, 0xFF, IP_HASH_INITIAL_CAP * sizeof(uint32_t));
ip.string_bytes = ARR_INIT(uint8_t, IP_STRING_INITIAL_CAP);
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;
}
void ipDeinit(InternPool* ip) {
free(ip->items);
free(ip->hash_table);
free(ip->string_bytes);
free(ip->extra);
ip->items = NULL;
ip->hash_table = NULL;
ip->string_bytes = NULL;
ip->extra = NULL;
ip->items_len = 0;
ip->items_cap = 0;
ip->hash_cap = 0;
ip->string_bytes_len = 0;
ip->string_bytes_cap = 0;
ip->extra_len = 0;
ip->extra_cap = 0;
}
InternPoolIndex ipIntern(InternPool* ip, InternPoolKey key) {
// 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) {
InternPoolKey key;
memset(&key, 0, sizeof(key));
if (index < ip->items_len) {
key = ip->items[index];
}
return key;
}
InternPoolIndex ipTypeOf(const InternPool* ip, InternPoolIndex index) {
// 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;
}