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>
766 lines
27 KiB
C
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;
|
|
}
|