Files
zig/stage0/intern_pool.c
Motiejus Jakštys 7006c814b9 stage0: add Nav, namespace, and module-level IP entry infrastructure
Port module-level analysis infrastructure from upstream Zig to create
InternPool entries that match the Zig compiler's output. This is the
first step toward closing the IP gap for neghf2.zig (corpus test 4).

- Add Nav struct to intern_pool.h with ipCreateDeclNav/ipGetNav/
  ipResetNavs/ipNavCount management functions
- Add IP_KEY_PTR_NAV to InternPool (hash, equality, typeOf)
- Add SemaNamespace struct to sema.h for declaration grouping
- Port createFileRootStruct, scanNamespace from PerThread.zig
- Port ensureFileAnalyzed for recursive import resolution
- Add resolveModuleDeclImports: creates type_struct + type_pointer +
  ptr_nav entries for import declarations, matching upstream order
- Add internPtrConst and internNavPtr helpers (from analyzeNavRefInner)

The C sema now creates entries [124-129] matching the Zig compiler:
type_struct(neghf2), type_struct(common), type_pointer(*const type),
ptr_nav(common), type_struct(std), ptr_nav(std). The remaining ~870
entries will be added in subsequent commits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:42:40 +00:00

833 lines
29 KiB
C

#include "intern_pool.h"
#include <assert.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_lo);
h = ipHashCombine(h, (uint32_t)(key->data.int_val.value_lo >> 32));
h = ipHashCombine(h, (uint32_t)key->data.int_val.value_hi);
h = ipHashCombine(h, (uint32_t)(key->data.int_val.value_hi >> 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;
case IP_KEY_ENUM_LITERAL:
h = ipHashCombine(h, key->data.enum_literal);
break;
case IP_KEY_FLOAT: {
uint64_t fbits;
memcpy(&fbits, &key->data.float_val.val, sizeof(fbits));
h = ipHashCombine(h, key->data.float_val.ty);
h = ipHashCombine(h, (uint32_t)fbits);
h = ipHashCombine(h, (uint32_t)(fbits >> 32));
break;
}
case IP_KEY_PTR_NAV:
h = ipHashCombine(h, key->data.ptr_nav.ty);
h = ipHashCombine(h, key->data.ptr_nav.nav);
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_lo == b->data.int_val.value_lo
&& a->data.int_val.value_hi == b->data.int_val.value_hi
&& 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;
case IP_KEY_ENUM_LITERAL:
return a->data.enum_literal == b->data.enum_literal;
case IP_KEY_FLOAT:
return a->data.float_val.ty == b->data.float_val.ty
&& memcmp(&a->data.float_val.val, &b->data.float_val.val,
sizeof(double))
== 0;
case IP_KEY_PTR_NAV:
return a->data.ptr_nav.ty == b->data.ptr_nav.ty
&& a->data.ptr_nav.nav == b->data.ptr_nav.nav;
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_lo = 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_FLOAT:
return key.data.float_val.ty;
case IP_KEY_ENUM_LITERAL:
return IP_INDEX_ENUM_LITERAL_TYPE;
case IP_KEY_PTR_NAV:
return key.data.ptr_nav.ty;
default:
break;
}
return IP_INDEX_NONE;
}
// --- Nav management ---
// Ported from InternPool.createDeclNav / InternPool.getNav.
static Nav s_navs[IP_MAX_NAVS];
static uint32_t s_num_navs;
uint32_t ipCreateDeclNav(uint32_t name, uint32_t fqn, uint32_t zir_index,
uint32_t namespace_idx, bool is_pub, bool is_const) {
assert(s_num_navs < IP_MAX_NAVS);
uint32_t idx = s_num_navs++;
Nav* nav = &s_navs[idx];
memset(nav, 0, sizeof(*nav));
nav->name = name;
nav->fqn = fqn;
nav->zir_index = zir_index;
nav->namespace_idx = namespace_idx;
nav->resolved_type = IP_INDEX_NONE;
nav->resolved_val = IP_INDEX_NONE;
nav->is_pub = is_pub;
nav->is_const = is_const;
return idx;
}
Nav* ipGetNav(uint32_t nav_index) {
assert(nav_index < s_num_navs);
return &s_navs[nav_index];
}
void ipResetNavs(void) { s_num_navs = 0; }
uint32_t ipNavCount(void) { return s_num_navs; }