Port IP_KEY_FUNC_INSTANCE from upstream InternPool.getFuncInstance. When a generic non-inline function is called, create a monomorphized func_type (runtime params only) and a func_instance entry referencing the generic owner's func_decl. This matches the Zig compiler's IP entry sequence for generic instantiations. Bumps num_passing from 84 to 85. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1107 lines
40 KiB
C
1107 lines
40 KiB
C
#include "intern_pool.h"
|
|
#include "wyhash.h"
|
|
#include <assert.h>
|
|
#include <stdio.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 ipHashKey(const InternPoolKey* key) {
|
|
Wyhash h;
|
|
wyhash_init(&h, (uint64_t)key->tag);
|
|
switch (key->tag) {
|
|
case IP_KEY_INT_TYPE:
|
|
wyhash_update_u32(&h, (uint32_t)key->data.int_type.bits);
|
|
wyhash_update_u32(&h, (uint32_t)key->data.int_type.signedness);
|
|
break;
|
|
case IP_KEY_PTR_TYPE:
|
|
return (uint32_t)wyhash_hash((uint64_t)key->tag, &key->data.ptr_type,
|
|
sizeof(key->data.ptr_type));
|
|
case IP_KEY_ARRAY_TYPE:
|
|
wyhash_update_u64(&h, key->data.array_type.len);
|
|
wyhash_update_u32(&h, key->data.array_type.child);
|
|
wyhash_update_u32(&h, key->data.array_type.sentinel);
|
|
break;
|
|
case IP_KEY_VECTOR_TYPE:
|
|
wyhash_update_u32(&h, key->data.vector_type.len);
|
|
wyhash_update_u32(&h, key->data.vector_type.child);
|
|
break;
|
|
case IP_KEY_OPT_TYPE:
|
|
wyhash_update_u32(&h, key->data.opt_type);
|
|
break;
|
|
case IP_KEY_ANYFRAME_TYPE:
|
|
wyhash_update_u32(&h, key->data.anyframe_type);
|
|
break;
|
|
case IP_KEY_ERROR_UNION_TYPE:
|
|
wyhash_update_u32(&h, key->data.error_union_type.error_set);
|
|
wyhash_update_u32(&h, key->data.error_union_type.payload);
|
|
break;
|
|
case IP_KEY_SIMPLE_TYPE:
|
|
wyhash_update_u32(&h, (uint32_t)key->data.simple_type);
|
|
break;
|
|
case IP_KEY_SIMPLE_VALUE:
|
|
wyhash_update_u32(&h, (uint32_t)key->data.simple_value);
|
|
break;
|
|
case IP_KEY_UNDEF:
|
|
wyhash_update_u32(&h, key->data.undef);
|
|
break;
|
|
case IP_KEY_INT:
|
|
wyhash_update_u32(&h, key->data.int_val.ty);
|
|
wyhash_update_u64(&h, key->data.int_val.value_lo);
|
|
wyhash_update_u64(&h, key->data.int_val.value_hi);
|
|
wyhash_update_u32(&h, (uint32_t)key->data.int_val.is_negative);
|
|
break;
|
|
case IP_KEY_TUPLE_TYPE:
|
|
wyhash_update_u32(&h, key->data.tuple_type);
|
|
break;
|
|
case IP_KEY_ENUM_LITERAL:
|
|
wyhash_update_u32(&h, key->data.enum_literal);
|
|
break;
|
|
case IP_KEY_ENUM_TAG:
|
|
wyhash_update_u32(&h, key->data.enum_tag.ty);
|
|
wyhash_update_u32(&h, key->data.enum_tag.int_val);
|
|
break;
|
|
case IP_KEY_FLOAT:
|
|
wyhash_update_u32(&h, key->data.float_val.ty);
|
|
wyhash_update(
|
|
&h, &key->data.float_val.val, sizeof(key->data.float_val.val));
|
|
break;
|
|
case IP_KEY_PTR_NAV:
|
|
wyhash_update_u32(&h, key->data.ptr_nav.ty);
|
|
wyhash_update_u32(&h, key->data.ptr_nav.nav);
|
|
break;
|
|
case IP_KEY_FUNC:
|
|
wyhash_update_u32(&h, key->data.func_decl.owner_nav);
|
|
wyhash_update_u32(&h, key->data.func_decl.ty);
|
|
break;
|
|
case IP_KEY_FUNC_INSTANCE:
|
|
wyhash_update_u32(&h, key->data.func_instance.generic_owner);
|
|
wyhash_update_u32(&h, key->data.func_instance.ty);
|
|
break;
|
|
case IP_KEY_MEMOIZED_CALL:
|
|
wyhash_update_u32(&h, key->data.memoized_call.func);
|
|
wyhash_update_u32(&h, key->data.memoized_call.result);
|
|
break;
|
|
case IP_KEY_BYTES:
|
|
wyhash_update_u32(&h, key->data.bytes.ty);
|
|
wyhash_update_u32(&h, key->data.bytes.str_idx);
|
|
break;
|
|
case IP_KEY_PTR_UAV:
|
|
wyhash_update_u32(&h, key->data.ptr_uav.ty);
|
|
wyhash_update_u32(&h, key->data.ptr_uav.val);
|
|
break;
|
|
case IP_KEY_PTR_UAV_ALIGNED:
|
|
wyhash_update_u32(&h, key->data.ptr_uav_aligned.ty);
|
|
wyhash_update_u32(&h, key->data.ptr_uav_aligned.val);
|
|
wyhash_update_u32(&h, key->data.ptr_uav_aligned.orig_ty);
|
|
break;
|
|
case IP_KEY_PTR_SLICE:
|
|
wyhash_update_u32(&h, key->data.ptr_slice.ty);
|
|
wyhash_update_u32(&h, key->data.ptr_slice.ptr);
|
|
wyhash_update_u32(&h, key->data.ptr_slice.len);
|
|
break;
|
|
case IP_KEY_OPT:
|
|
wyhash_update_u32(&h, key->data.opt);
|
|
break;
|
|
case IP_KEY_OPT_PAYLOAD:
|
|
wyhash_update_u32(&h, key->data.opt_payload.ty);
|
|
wyhash_update_u32(&h, key->data.opt_payload.val);
|
|
break;
|
|
case IP_KEY_PTR_COMPTIME_ALLOC:
|
|
wyhash_update_u32(&h, key->data.ptr_comptime_alloc.ty);
|
|
wyhash_update_u32(&h, key->data.ptr_comptime_alloc.alloc_index);
|
|
break;
|
|
case IP_KEY_PTR_FIELD:
|
|
wyhash_update_u32(&h, key->data.ptr_field.ty);
|
|
wyhash_update_u32(&h, key->data.ptr_field.base);
|
|
wyhash_update_u32(&h, key->data.ptr_field.field_index);
|
|
break;
|
|
case IP_KEY_PTR_OPT_PAYLOAD:
|
|
wyhash_update_u32(&h, key->data.ptr_opt_payload.ty);
|
|
wyhash_update_u32(&h, key->data.ptr_opt_payload.base);
|
|
break;
|
|
case IP_KEY_OPT_NULL:
|
|
wyhash_update_u32(&h, key->data.opt_null);
|
|
break;
|
|
case IP_KEY_REPEATED:
|
|
wyhash_update_u32(&h, key->data.repeated.ty);
|
|
wyhash_update_u32(&h, key->data.repeated.elem_val);
|
|
break;
|
|
case IP_KEY_INT_U16:
|
|
wyhash_update_u32(&h, key->data.int_u16);
|
|
break;
|
|
case IP_KEY_FUNC_TYPE:
|
|
wyhash_update_u32(&h, key->data.func_type.return_type);
|
|
wyhash_update_u32(&h, key->data.func_type.param_count);
|
|
wyhash_update_u32(&h, (uint32_t)key->data.func_type.cc);
|
|
wyhash_update_u32(&h, (uint32_t)key->data.func_type.is_var_args);
|
|
wyhash_update_u32(&h, (uint32_t)key->data.func_type.is_generic);
|
|
wyhash_update_u32(&h, (uint32_t)key->data.func_type.is_noinline);
|
|
wyhash_update_u32(&h, key->data.func_type.comptime_bits);
|
|
wyhash_update_u32(&h, key->data.func_type.noalias_bits);
|
|
for (uint32_t pi = 0;
|
|
pi < key->data.func_type.param_count && pi < FUNC_TYPE_MAX_PARAMS;
|
|
pi++)
|
|
wyhash_update_u32(&h, key->data.func_type.param_types[pi]);
|
|
break;
|
|
case IP_KEY_SLICE:
|
|
wyhash_update_u32(&h, key->data.slice);
|
|
break;
|
|
case IP_KEY_AGGREGATE:
|
|
wyhash_update_u32(&h, key->data.aggregate);
|
|
break;
|
|
case IP_KEY_UNION_VALUE:
|
|
wyhash_update_u32(&h, key->data.union_val.ty);
|
|
wyhash_update_u32(&h, key->data.union_val.tag);
|
|
wyhash_update_u32(&h, key->data.union_val.val);
|
|
break;
|
|
default:
|
|
/* For other tag types, just use the tag hash (seed only). */
|
|
break;
|
|
}
|
|
return (uint32_t)wyhash_final(&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_ENUM_TAG:
|
|
return a->data.enum_tag.ty == b->data.enum_tag.ty
|
|
&& a->data.enum_tag.int_val == b->data.enum_tag.int_val;
|
|
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;
|
|
case IP_KEY_FUNC:
|
|
return a->data.func_decl.owner_nav == b->data.func_decl.owner_nav
|
|
&& a->data.func_decl.ty == b->data.func_decl.ty;
|
|
case IP_KEY_FUNC_INSTANCE:
|
|
return a->data.func_instance.generic_owner
|
|
== b->data.func_instance.generic_owner
|
|
&& a->data.func_instance.ty == b->data.func_instance.ty;
|
|
case IP_KEY_MEMOIZED_CALL:
|
|
return a->data.memoized_call.func == b->data.memoized_call.func
|
|
&& a->data.memoized_call.result == b->data.memoized_call.result;
|
|
case IP_KEY_BYTES:
|
|
return a->data.bytes.ty == b->data.bytes.ty
|
|
&& a->data.bytes.str_idx == b->data.bytes.str_idx;
|
|
case IP_KEY_PTR_UAV:
|
|
return a->data.ptr_uav.ty == b->data.ptr_uav.ty
|
|
&& a->data.ptr_uav.val == b->data.ptr_uav.val;
|
|
case IP_KEY_PTR_UAV_ALIGNED:
|
|
return a->data.ptr_uav_aligned.ty == b->data.ptr_uav_aligned.ty
|
|
&& a->data.ptr_uav_aligned.val == b->data.ptr_uav_aligned.val
|
|
&& a->data.ptr_uav_aligned.orig_ty
|
|
== b->data.ptr_uav_aligned.orig_ty;
|
|
case IP_KEY_PTR_SLICE:
|
|
return a->data.ptr_slice.ty == b->data.ptr_slice.ty
|
|
&& a->data.ptr_slice.ptr == b->data.ptr_slice.ptr
|
|
&& a->data.ptr_slice.len == b->data.ptr_slice.len;
|
|
case IP_KEY_OPT:
|
|
return a->data.opt == b->data.opt;
|
|
case IP_KEY_OPT_PAYLOAD:
|
|
return a->data.opt_payload.ty == b->data.opt_payload.ty
|
|
&& a->data.opt_payload.val == b->data.opt_payload.val;
|
|
case IP_KEY_PTR_COMPTIME_ALLOC:
|
|
return a->data.ptr_comptime_alloc.ty == b->data.ptr_comptime_alloc.ty
|
|
&& a->data.ptr_comptime_alloc.alloc_index
|
|
== b->data.ptr_comptime_alloc.alloc_index;
|
|
case IP_KEY_PTR_FIELD:
|
|
return a->data.ptr_field.ty == b->data.ptr_field.ty
|
|
&& a->data.ptr_field.base == b->data.ptr_field.base
|
|
&& a->data.ptr_field.field_index == b->data.ptr_field.field_index;
|
|
case IP_KEY_PTR_OPT_PAYLOAD:
|
|
return a->data.ptr_opt_payload.ty == b->data.ptr_opt_payload.ty
|
|
&& a->data.ptr_opt_payload.base == b->data.ptr_opt_payload.base;
|
|
case IP_KEY_OPT_NULL:
|
|
return a->data.opt_null == b->data.opt_null;
|
|
case IP_KEY_REPEATED:
|
|
return a->data.repeated.ty == b->data.repeated.ty
|
|
&& a->data.repeated.elem_val == b->data.repeated.elem_val;
|
|
case IP_KEY_INT_U16:
|
|
return a->data.int_u16 == b->data.int_u16;
|
|
case IP_KEY_FUNC_TYPE:
|
|
if (a->data.func_type.return_type != b->data.func_type.return_type
|
|
|| a->data.func_type.param_count != b->data.func_type.param_count
|
|
|| a->data.func_type.cc != b->data.func_type.cc
|
|
|| a->data.func_type.is_var_args != b->data.func_type.is_var_args
|
|
|| a->data.func_type.is_generic != b->data.func_type.is_generic
|
|
|| a->data.func_type.is_noinline != b->data.func_type.is_noinline
|
|
|| a->data.func_type.comptime_bits
|
|
!= b->data.func_type.comptime_bits
|
|
|| a->data.func_type.noalias_bits
|
|
!= b->data.func_type.noalias_bits)
|
|
return false;
|
|
for (uint32_t pi = 0;
|
|
pi < a->data.func_type.param_count && pi < FUNC_TYPE_MAX_PARAMS;
|
|
pi++) {
|
|
if (a->data.func_type.param_types[pi]
|
|
!= b->data.func_type.param_types[pi])
|
|
return false;
|
|
}
|
|
return true;
|
|
case IP_KEY_SLICE:
|
|
return a->data.slice == b->data.slice;
|
|
case IP_KEY_AGGREGATE:
|
|
return a->data.aggregate == b->data.aggregate;
|
|
case IP_KEY_UNION_VALUE:
|
|
return a->data.union_val.ty == b->data.union_val.ty
|
|
&& a->data.union_val.tag == b->data.union_val.tag
|
|
&& a->data.union_val.val == b->data.union_val.val;
|
|
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;
|
|
ip.navs = ARR_INIT(Nav, 64);
|
|
ip.nav_cap = 64;
|
|
|
|
// 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 — stored as type_slice wrapping [*]const u8
|
|
{
|
|
InternPoolKey sk;
|
|
memset(&sk, 0, sizeof(sk));
|
|
sk.tag = IP_KEY_SLICE;
|
|
sk.data.slice = IP_INDEX_MANYPTR_CONST_U8_TYPE; // index 48
|
|
ipAppendItem(&ip, sk);
|
|
}
|
|
|
|
// Index 51: [:0]const u8 — stored as type_slice wrapping [*:0]const u8
|
|
{
|
|
InternPoolKey sk;
|
|
memset(&sk, 0, sizeof(sk));
|
|
sk.tag = IP_KEY_SLICE;
|
|
sk.data.slice = IP_INDEX_MANYPTR_CONST_U8_SENTINEL_0_TYPE; // 49
|
|
ipAppendItem(&ip, sk);
|
|
}
|
|
|
|
// 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);
|
|
free(ip->navs);
|
|
ip->items = NULL;
|
|
ip->hash_table = NULL;
|
|
ip->string_bytes = NULL;
|
|
ip->extra = NULL;
|
|
ip->navs = 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;
|
|
ip->nav_count = 0;
|
|
ip->nav_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)) {
|
|
// Shard simulation: skip matches in the preamble memoized
|
|
// range, EXCEPT for:
|
|
// 1. Entries in the CC sub-range (in Zig's local shard)
|
|
// 2. comptime_int entries (shared across all shards)
|
|
// Ported from upstream Zig's sharded IP behavior.
|
|
if (idx >= ip->skip_dedup_start && idx < ip->skip_dedup_end
|
|
&& !(idx >= ip->cc_keep_start && idx < ip->cc_keep_end)
|
|
&& !(ip->items[idx].tag == IP_KEY_INT
|
|
&& ip->items[idx].data.int_val.ty
|
|
== IP_INDEX_COMPTIME_INT_TYPE)) {
|
|
h = (h + 1) & (ip->hash_cap - 1);
|
|
continue;
|
|
}
|
|
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;
|
|
}
|
|
|
|
InternPoolIndex ipForceIntern(InternPool* ip, InternPoolKey key) {
|
|
uint32_t new_index = ip->items_len;
|
|
ipAppendItem(ip, key);
|
|
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:
|
|
case IP_KEY_SLICE:
|
|
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_ENUM_TAG:
|
|
return key.data.enum_tag.ty;
|
|
|
|
case IP_KEY_PTR_NAV:
|
|
return key.data.ptr_nav.ty;
|
|
|
|
case IP_KEY_FUNC:
|
|
return key.data.func_decl.ty;
|
|
|
|
case IP_KEY_FUNC_INSTANCE:
|
|
return key.data.func_instance.ty;
|
|
|
|
case IP_KEY_MEMOIZED_CALL:
|
|
return IP_INDEX_VOID_TYPE;
|
|
|
|
case IP_KEY_BYTES:
|
|
return key.data.bytes.ty;
|
|
|
|
case IP_KEY_PTR_UAV:
|
|
return key.data.ptr_uav.ty;
|
|
|
|
case IP_KEY_PTR_UAV_ALIGNED:
|
|
return key.data.ptr_uav_aligned.ty;
|
|
|
|
case IP_KEY_PTR_SLICE:
|
|
return key.data.ptr_slice.ty;
|
|
|
|
case IP_KEY_OPT:
|
|
return key.data.opt;
|
|
|
|
case IP_KEY_OPT_PAYLOAD:
|
|
return key.data.opt_payload.ty;
|
|
|
|
case IP_KEY_PTR_COMPTIME_ALLOC:
|
|
return key.data.ptr_comptime_alloc.ty;
|
|
|
|
case IP_KEY_PTR_FIELD:
|
|
return key.data.ptr_field.ty;
|
|
|
|
case IP_KEY_PTR_OPT_PAYLOAD:
|
|
return key.data.ptr_opt_payload.ty;
|
|
|
|
case IP_KEY_OPT_NULL:
|
|
return key.data.opt_null;
|
|
|
|
case IP_KEY_REPEATED:
|
|
return IP_INDEX_NONE; // type depends on context
|
|
|
|
case IP_KEY_INT_U16:
|
|
return IP_INDEX_U16_TYPE;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return IP_INDEX_NONE;
|
|
}
|
|
|
|
// --- Nav management ---
|
|
// Ported from InternPool.createDeclNav / InternPool.getNav.
|
|
|
|
uint32_t ipCreateDeclNav(InternPool* ip, uint32_t name, uint32_t fqn,
|
|
uint32_t zir_index, uint32_t namespace_idx, bool is_pub, bool is_const) {
|
|
assert(ip->nav_count < IP_MAX_NAVS);
|
|
if (ip->nav_count >= ip->nav_cap) {
|
|
uint32_t new_cap = ip->nav_cap * 2;
|
|
Nav* new_navs = realloc(ip->navs, new_cap * sizeof(Nav));
|
|
if (!new_navs)
|
|
exit(1);
|
|
ip->navs = new_navs;
|
|
ip->nav_cap = new_cap;
|
|
}
|
|
uint32_t idx = ip->nav_count++;
|
|
Nav* nav = &ip->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(InternPool* ip, uint32_t nav_index) {
|
|
assert(nav_index < ip->nav_count);
|
|
return &ip->navs[nav_index];
|
|
}
|
|
|
|
void ipResetNavs(InternPool* ip) { ip->nav_count = 0; }
|
|
|
|
uint32_t ipNavCount(const InternPool* ip) { return ip->nav_count; }
|
|
|
|
// --- String interning ---
|
|
// Add a null-terminated string to the IP string table. Returns the
|
|
// NullTerminatedString index. Searches for an existing copy first.
|
|
// Ported from InternPool.getOrPutString.
|
|
uint32_t ipGetOrPutString(InternPool* ip, const char* str) {
|
|
uint32_t slen = (uint32_t)strlen(str);
|
|
// Search for existing string.
|
|
for (uint32_t i = 0; i + slen < ip->string_bytes_len; i++) {
|
|
if (memcmp(&ip->string_bytes[i], str, slen) == 0
|
|
&& ip->string_bytes[i + slen] == 0) {
|
|
return i;
|
|
}
|
|
}
|
|
// Not found: append.
|
|
uint32_t needed = slen + 1; // include null terminator
|
|
while (ip->string_bytes_len + needed > ip->string_bytes_cap) {
|
|
uint32_t new_cap = ip->string_bytes_cap * 2;
|
|
if (new_cap == 0)
|
|
new_cap = 256;
|
|
ip->string_bytes = realloc(ip->string_bytes, new_cap);
|
|
ip->string_bytes_cap = new_cap;
|
|
}
|
|
uint32_t idx = ip->string_bytes_len;
|
|
memcpy(&ip->string_bytes[idx], str, slen);
|
|
ip->string_bytes[idx + slen] = 0;
|
|
ip->string_bytes_len += needed;
|
|
return idx;
|
|
}
|