Files
zig/stage0/intern_pool.h
Motiejus a35da223fb sema: add func_instance support for generic function monomorphization
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>
2026-03-03 08:30:41 +00:00

509 lines
15 KiB
C

// intern_pool.h — Simplified single-threaded InternPool, ported from
// src/InternPool.zig.
#ifndef _ZIG0_INTERN_POOL_H__
#define _ZIG0_INTERN_POOL_H__
#include "common.h"
#include <stdbool.h>
#include <stdint.h>
// --- InternPool index type ---
typedef uint32_t InternPoolIndex;
// --- Pre-interned constants (matching InternPool.Index enum, values 0-123)
// ---
// Types (0-103)
#define IP_INDEX_U0_TYPE 0
#define IP_INDEX_I0_TYPE 1
#define IP_INDEX_U1_TYPE 2
#define IP_INDEX_U8_TYPE 3
#define IP_INDEX_I8_TYPE 4
#define IP_INDEX_U16_TYPE 5
#define IP_INDEX_I16_TYPE 6
#define IP_INDEX_U29_TYPE 7
#define IP_INDEX_U32_TYPE 8
#define IP_INDEX_I32_TYPE 9
#define IP_INDEX_U64_TYPE 10
#define IP_INDEX_I64_TYPE 11
#define IP_INDEX_U80_TYPE 12
#define IP_INDEX_U128_TYPE 13
#define IP_INDEX_I128_TYPE 14
#define IP_INDEX_U256_TYPE 15
#define IP_INDEX_USIZE_TYPE 16
#define IP_INDEX_ISIZE_TYPE 17
#define IP_INDEX_C_CHAR_TYPE 18
#define IP_INDEX_C_SHORT_TYPE 19
#define IP_INDEX_C_USHORT_TYPE 20
#define IP_INDEX_C_INT_TYPE 21
#define IP_INDEX_C_UINT_TYPE 22
#define IP_INDEX_C_LONG_TYPE 23
#define IP_INDEX_C_ULONG_TYPE 24
#define IP_INDEX_C_LONGLONG_TYPE 25
#define IP_INDEX_C_ULONGLONG_TYPE 26
#define IP_INDEX_C_LONGDOUBLE_TYPE 27
#define IP_INDEX_F16_TYPE 28
#define IP_INDEX_F32_TYPE 29
#define IP_INDEX_F64_TYPE 30
#define IP_INDEX_F80_TYPE 31
#define IP_INDEX_F128_TYPE 32
#define IP_INDEX_ANYOPAQUE_TYPE 33
#define IP_INDEX_BOOL_TYPE 34
#define IP_INDEX_VOID_TYPE 35
#define IP_INDEX_TYPE_TYPE 36
#define IP_INDEX_ANYERROR_TYPE 37
#define IP_INDEX_COMPTIME_INT_TYPE 38
#define IP_INDEX_COMPTIME_FLOAT_TYPE 39
#define IP_INDEX_NORETURN_TYPE 40
#define IP_INDEX_ANYFRAME_TYPE 41
#define IP_INDEX_NULL_TYPE 42
#define IP_INDEX_UNDEFINED_TYPE 43
#define IP_INDEX_ENUM_LITERAL_TYPE 44
#define IP_INDEX_PTR_USIZE_TYPE 45
#define IP_INDEX_PTR_CONST_COMPTIME_INT_TYPE 46
#define IP_INDEX_MANYPTR_U8_TYPE 47
#define IP_INDEX_MANYPTR_CONST_U8_TYPE 48
#define IP_INDEX_MANYPTR_CONST_U8_SENTINEL_0_TYPE 49
#define IP_INDEX_SLICE_CONST_U8_TYPE 50
#define IP_INDEX_SLICE_CONST_U8_SENTINEL_0_TYPE 51
// Vector types (52-98) — matching InternPool.Index enum order exactly.
#define IP_INDEX_VECTOR_8_I8_TYPE 52
#define IP_INDEX_VECTOR_16_I8_TYPE 53
#define IP_INDEX_VECTOR_32_I8_TYPE 54
#define IP_INDEX_VECTOR_64_I8_TYPE 55
#define IP_INDEX_VECTOR_1_U8_TYPE 56
#define IP_INDEX_VECTOR_2_U8_TYPE 57
#define IP_INDEX_VECTOR_4_U8_TYPE 58
#define IP_INDEX_VECTOR_8_U8_TYPE 59
#define IP_INDEX_VECTOR_16_U8_TYPE 60
#define IP_INDEX_VECTOR_32_U8_TYPE 61
#define IP_INDEX_VECTOR_64_U8_TYPE 62
#define IP_INDEX_VECTOR_2_I16_TYPE 63
#define IP_INDEX_VECTOR_4_I16_TYPE 64
#define IP_INDEX_VECTOR_8_I16_TYPE 65
#define IP_INDEX_VECTOR_16_I16_TYPE 66
#define IP_INDEX_VECTOR_32_I16_TYPE 67
#define IP_INDEX_VECTOR_4_U16_TYPE 68
#define IP_INDEX_VECTOR_8_U16_TYPE 69
#define IP_INDEX_VECTOR_16_U16_TYPE 70
#define IP_INDEX_VECTOR_32_U16_TYPE 71
#define IP_INDEX_VECTOR_2_I32_TYPE 72
#define IP_INDEX_VECTOR_4_I32_TYPE 73
#define IP_INDEX_VECTOR_8_I32_TYPE 74
#define IP_INDEX_VECTOR_16_I32_TYPE 75
#define IP_INDEX_VECTOR_4_U32_TYPE 76
#define IP_INDEX_VECTOR_8_U32_TYPE 77
#define IP_INDEX_VECTOR_16_U32_TYPE 78
#define IP_INDEX_VECTOR_2_I64_TYPE 79
#define IP_INDEX_VECTOR_4_I64_TYPE 80
#define IP_INDEX_VECTOR_8_I64_TYPE 81
#define IP_INDEX_VECTOR_2_U64_TYPE 82
#define IP_INDEX_VECTOR_4_U64_TYPE 83
#define IP_INDEX_VECTOR_8_U64_TYPE 84
#define IP_INDEX_VECTOR_1_U128_TYPE 85
#define IP_INDEX_VECTOR_2_U128_TYPE 86
#define IP_INDEX_VECTOR_1_U256_TYPE 87
#define IP_INDEX_VECTOR_4_F16_TYPE 88
#define IP_INDEX_VECTOR_8_F16_TYPE 89
#define IP_INDEX_VECTOR_16_F16_TYPE 90
#define IP_INDEX_VECTOR_32_F16_TYPE 91
#define IP_INDEX_VECTOR_2_F32_TYPE 92
#define IP_INDEX_VECTOR_4_F32_TYPE 93
#define IP_INDEX_VECTOR_8_F32_TYPE 94
#define IP_INDEX_VECTOR_16_F32_TYPE 95
#define IP_INDEX_VECTOR_2_F64_TYPE 96
#define IP_INDEX_VECTOR_4_F64_TYPE 97
#define IP_INDEX_VECTOR_8_F64_TYPE 98
// More types (99-103)
#define IP_INDEX_OPTIONAL_NORETURN_TYPE 99
#define IP_INDEX_ANYERROR_VOID_ERROR_UNION_TYPE 100
#define IP_INDEX_ADHOC_INFERRED_ERROR_SET_TYPE 101
#define IP_INDEX_GENERIC_POISON_TYPE 102
#define IP_INDEX_EMPTY_TUPLE_TYPE 103
// Values (104-123)
#define IP_INDEX_UNDEF 104
#define IP_INDEX_UNDEF_BOOL 105
#define IP_INDEX_UNDEF_USIZE 106
#define IP_INDEX_UNDEF_U1 107
#define IP_INDEX_ZERO 108
#define IP_INDEX_ZERO_USIZE 109
#define IP_INDEX_ZERO_U1 110
#define IP_INDEX_ZERO_U8 111
#define IP_INDEX_ONE 112
#define IP_INDEX_ONE_USIZE 113
#define IP_INDEX_ONE_U1 114
#define IP_INDEX_ONE_U8 115
#define IP_INDEX_FOUR_U8 116
#define IP_INDEX_NEGATIVE_ONE 117
#define IP_INDEX_VOID_VALUE 118
#define IP_INDEX_UNREACHABLE_VALUE 119
#define IP_INDEX_NULL_VALUE 120
#define IP_INDEX_BOOL_TRUE 121
#define IP_INDEX_BOOL_FALSE 122
#define IP_INDEX_EMPTY_TUPLE 123
#define IP_INDEX_NONE UINT32_MAX
#define IP_INDEX_PREINTERN_COUNT 124
// --- SimpleType enum (matching InternPool.SimpleType) ---
typedef enum {
SIMPLE_TYPE_F16 = 0,
SIMPLE_TYPE_F32,
SIMPLE_TYPE_F64,
SIMPLE_TYPE_F80,
SIMPLE_TYPE_F128,
SIMPLE_TYPE_USIZE,
SIMPLE_TYPE_ISIZE,
SIMPLE_TYPE_C_CHAR,
SIMPLE_TYPE_C_SHORT,
SIMPLE_TYPE_C_USHORT,
SIMPLE_TYPE_C_INT,
SIMPLE_TYPE_C_UINT,
SIMPLE_TYPE_C_LONG,
SIMPLE_TYPE_C_ULONG,
SIMPLE_TYPE_C_LONGLONG,
SIMPLE_TYPE_C_ULONGLONG,
SIMPLE_TYPE_C_LONGDOUBLE,
SIMPLE_TYPE_ANYOPAQUE,
SIMPLE_TYPE_BOOL,
SIMPLE_TYPE_VOID,
SIMPLE_TYPE_TYPE,
SIMPLE_TYPE_ANYERROR,
SIMPLE_TYPE_COMPTIME_INT,
SIMPLE_TYPE_COMPTIME_FLOAT,
SIMPLE_TYPE_NORETURN,
SIMPLE_TYPE_NULL,
SIMPLE_TYPE_UNDEFINED,
SIMPLE_TYPE_ENUM_LITERAL,
SIMPLE_TYPE_ADHOC_INFERRED_ERROR_SET,
SIMPLE_TYPE_GENERIC_POISON,
} SimpleType;
// --- SimpleValue enum (matching InternPool.SimpleValue) ---
typedef enum {
SIMPLE_VALUE_UNDEFINED = 0,
SIMPLE_VALUE_VOID,
SIMPLE_VALUE_NULL,
SIMPLE_VALUE_EMPTY_TUPLE,
SIMPLE_VALUE_TRUE,
SIMPLE_VALUE_FALSE,
SIMPLE_VALUE_UNREACHABLE,
} SimpleValue;
// --- Type descriptors ---
typedef struct {
uint16_t bits;
uint8_t signedness; // 0 = unsigned, 1 = signed
} IntType;
typedef struct {
InternPoolIndex child;
InternPoolIndex sentinel;
uint32_t flags;
uint32_t packed_offset;
} PtrType;
typedef struct {
uint64_t len;
InternPoolIndex child;
InternPoolIndex sentinel;
} ArrayType;
typedef struct {
uint32_t len;
InternPoolIndex child;
} VectorType;
typedef struct {
InternPoolIndex error_set;
InternPoolIndex payload;
} ErrorUnionType;
// Max inline param types for func_type dedup. Enough for bootstrap corpus.
#define FUNC_TYPE_MAX_PARAMS 8
typedef struct {
InternPoolIndex return_type;
uint32_t param_count;
uint32_t comptime_bits;
uint32_t noalias_bits;
InternPoolIndex param_types[FUNC_TYPE_MAX_PARAMS]; // inline for dedup
uint8_t cc;
bool is_var_args;
bool is_generic;
bool is_noinline;
} FuncType;
typedef struct {
uint32_t names_start;
uint32_t names_count;
// indices into extra
} ErrorSetType;
typedef struct {
uint32_t zir_index;
uint32_t type_hash;
} NamespaceType;
// --- Typed integer value (matching Key.Int) ---
typedef struct {
InternPoolIndex ty;
uint64_t value_lo; // low 64 bits
uint64_t value_hi; // high 64 bits (for types > 64 bits, e.g. u80, u128)
bool is_negative;
} TypedInt;
// --- PtrType flags encoding ---
// bits 0-1: size (0=one, 1=many, 2=slice, 3=c)
// bit 8: is_const
#define PTR_FLAGS_SIZE_ONE 0U
#define PTR_FLAGS_SIZE_MANY 1U
#define PTR_FLAGS_SIZE_SLICE 2U
#define PTR_FLAGS_SIZE_C 3U
#define PTR_FLAGS_SIZE_MASK 3U
#define PTR_FLAGS_IS_CONST (1U << 8)
// --- InternPoolKeyTag enum (matching Key union variants) ---
typedef enum {
IP_KEY_INT_TYPE,
IP_KEY_PTR_TYPE,
IP_KEY_ARRAY_TYPE,
IP_KEY_VECTOR_TYPE,
IP_KEY_OPT_TYPE,
IP_KEY_ANYFRAME_TYPE,
IP_KEY_ERROR_UNION_TYPE,
IP_KEY_SIMPLE_TYPE,
IP_KEY_STRUCT_TYPE,
IP_KEY_TUPLE_TYPE,
IP_KEY_UNION_TYPE,
IP_KEY_OPAQUE_TYPE,
IP_KEY_ENUM_TYPE,
IP_KEY_FUNC_TYPE,
IP_KEY_ERROR_SET_TYPE,
IP_KEY_INFERRED_ERROR_SET_TYPE,
IP_KEY_UNDEF,
IP_KEY_SIMPLE_VALUE,
IP_KEY_VARIABLE,
IP_KEY_EXTERN,
IP_KEY_FUNC,
IP_KEY_INT,
IP_KEY_ERR,
IP_KEY_ERROR_UNION,
IP_KEY_ENUM_LITERAL,
IP_KEY_ENUM_TAG,
IP_KEY_EMPTY_ENUM_VALUE,
IP_KEY_FLOAT,
IP_KEY_PTR,
IP_KEY_SLICE,
IP_KEY_OPT,
IP_KEY_AGGREGATE,
IP_KEY_UNION_VALUE,
IP_KEY_MEMOIZED_CALL,
IP_KEY_PTR_NAV,
IP_KEY_BYTES,
IP_KEY_PTR_UAV,
IP_KEY_PTR_UAV_ALIGNED,
IP_KEY_PTR_SLICE,
IP_KEY_PTR_COMPTIME_ALLOC,
IP_KEY_PTR_FIELD,
IP_KEY_PTR_OPT_PAYLOAD,
IP_KEY_OPT_PAYLOAD,
IP_KEY_OPT_NULL,
IP_KEY_REPEATED,
IP_KEY_INT_U16,
IP_KEY_FUNC_INSTANCE,
} InternPoolKeyTag;
// --- InternPoolKey (tagged union) ---
typedef struct {
InternPoolKeyTag tag;
union {
IntType int_type;
PtrType ptr_type;
ArrayType array_type;
VectorType vector_type;
InternPoolIndex opt_type; // child type
InternPoolIndex anyframe_type; // return type
ErrorUnionType error_union_type;
SimpleType simple_type;
InternPoolIndex struct_type;
InternPoolIndex tuple_type;
InternPoolIndex union_type;
InternPoolIndex opaque_type;
InternPoolIndex enum_type;
FuncType func_type;
ErrorSetType error_set_type;
InternPoolIndex inferred_error_set_type;
InternPoolIndex undef; // type index
SimpleValue simple_value;
InternPoolIndex variable;
InternPoolIndex extern_val;
struct {
uint32_t owner_nav; // Nav index
InternPoolIndex ty; // function type IP index
} func_decl;
struct {
InternPoolIndex generic_owner; // func_decl IP index
InternPoolIndex ty; // monomorphized function type IP index
uint32_t owner_nav; // Nav index
} func_instance;
TypedInt int_val;
InternPoolIndex err;
InternPoolIndex error_union;
uint32_t enum_literal; // string index
struct {
InternPoolIndex ty; // enum type IP index
InternPoolIndex int_val; // integer tag value IP index
} enum_tag;
InternPoolIndex empty_enum_value;
struct {
InternPoolIndex ty;
double val;
} float_val;
InternPoolIndex ptr;
InternPoolIndex slice;
InternPoolIndex opt;
InternPoolIndex aggregate;
struct {
InternPoolIndex ty; // union type
InternPoolIndex tag; // enum_tag for active field
InternPoolIndex val; // payload value
} union_val;
struct {
InternPoolIndex func; // func_decl IP index
InternPoolIndex result; // result value IP index
} memoized_call;
struct {
InternPoolIndex ty; // pointer type
uint32_t nav; // Nav index (NOT an IP index)
} ptr_nav;
struct {
InternPoolIndex ty; // aggregate type (array type)
uint32_t str_idx; // string_bytes offset
} bytes;
struct {
InternPoolIndex ty; // pointer type
InternPoolIndex val; // value being pointed to
} ptr_uav;
struct {
InternPoolIndex ty; // coerced pointer type
InternPoolIndex val; // value being pointed to
InternPoolIndex orig_ty; // original pointer type
} ptr_uav_aligned;
struct {
InternPoolIndex ty; // slice type
InternPoolIndex ptr; // many-pointer value
InternPoolIndex len; // usize value
} ptr_slice;
struct {
InternPoolIndex ty; // optional type
InternPoolIndex val; // payload value (or IP_INDEX_NONE for null)
} opt_payload;
struct {
InternPoolIndex ty; // pointer type
uint32_t alloc_index; // comptime allocation index
} ptr_comptime_alloc;
struct {
InternPoolIndex ty; // pointer type (result element pointer)
InternPoolIndex
base; // container value (ptr_nav or ptr_comptime_alloc)
uint32_t field_index; // field index within the container
} ptr_field;
struct {
InternPoolIndex ty; // pointer type
InternPoolIndex base; // base pointer
} ptr_opt_payload;
InternPoolIndex opt_null; // optional type (IP index)
struct {
InternPoolIndex ty; // aggregate type
InternPoolIndex elem_val; // value of every element
} repeated;
uint32_t int_u16; // u16 integer value
} data;
} InternPoolKey;
// --- Nav (declaration entry) ---
// Ported from InternPool.Nav. Navs are stored in a separate list from
// IP items — they do NOT consume IP indices. However, ptr_nav entries
// (pointers TO Navs) DO consume IP indices.
typedef struct {
uint32_t name; // NullTerminatedString index into IP string_bytes
uint32_t fqn; // fully qualified name string index
uint32_t zir_index; // ZIR instruction index of declaration
uint32_t namespace_idx; // owning namespace index
InternPoolIndex resolved_type; // IP_INDEX_NONE if unresolved
InternPoolIndex resolved_val; // IP_INDEX_NONE if unresolved
bool is_pub;
bool is_const;
} Nav;
#define IP_MAX_NAVS 16384
// --- InternPool struct ---
typedef struct {
InternPoolKey* items;
uint32_t items_len;
uint32_t items_cap;
uint32_t* hash_table;
uint32_t hash_cap;
uint8_t* string_bytes;
uint32_t string_bytes_len;
uint32_t string_bytes_cap;
uint32_t* extra;
uint32_t extra_len;
uint32_t extra_cap;
// Shard simulation: when skip_dedup_end > skip_dedup_start,
// ipIntern skips hash matches in [skip_dedup_start, skip_dedup_end),
// EXCEPT for indices in [cc_keep_start, cc_keep_end) which are in
// Zig's local shard and should participate in dedup.
// Ported from upstream: Zig's sharded IP separates preamble entries
// from main analysis entries across different shards, preventing
// cross-shard deduplication. This simulates that behavior in C's
// single-pool IP.
uint32_t skip_dedup_start;
uint32_t skip_dedup_end;
uint32_t cc_keep_start;
uint32_t cc_keep_end;
// Nav storage (ported from InternPool.zig Nav storage).
// Navs do NOT consume IP indices; ptr_nav entries (pointers to navs)
// do consume IP indices. Dynamically allocated (like items/extra).
Nav* navs;
uint32_t nav_count;
uint32_t nav_cap;
} InternPool;
// --- Function declarations ---
InternPool ipInit(void);
void ipDeinit(InternPool* ip);
InternPoolIndex ipIntern(InternPool* ip, InternPoolKey key);
InternPoolIndex ipForceIntern(InternPool* ip, InternPoolKey key);
InternPoolKey ipIndexToKey(const InternPool* ip, InternPoolIndex index);
InternPoolIndex ipTypeOf(const InternPool* ip, InternPoolIndex index);
// Nav management (ported from InternPool.createDeclNav)
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);
Nav* ipGetNav(InternPool* ip, uint32_t nav_index);
void ipResetNavs(InternPool* ip);
uint32_t ipNavCount(const InternPool* ip);
// String interning: add a null-terminated string to the IP string table.
// Returns the NullTerminatedString index (offset into string_bytes).
// If the string already exists, returns the existing index.
uint32_t ipGetOrPutString(InternPool* ip, const char* str);
#endif