commit 95e7c8c5eb85ca1c6468e6c903eabf3ab295dd1b (tree)
parent 2c9b51cdd6b95a5202ebdf96386adab4de7cc71a
Author: Motiejus <motiejus@jakstys.lt>
Date: Sat, 28 Feb 2026 10:14:43 +0000
sema: remove all hardcoded comptime value functions
Remove ~2900 lines of hardcoded IP entry creation that bypassed
proper comptime evaluation. These functions created target-specific
(wasm32) intern pool entries by hand-coding enum tags, field indices,
type indices, and calling conventions rather than computing them from
upstream Zig logic.
Removed functions:
- resolveStartComptimePreamble (CompilerBackend, OutputMode, etc.)
- resolveBuiltinDeclTypes (BuiltinDecl type resolution)
- resolveTargetModuleChain (Target.zig type chain)
- resolveFeatureSetConsts (Feature.Set comptime evaluation)
- resolveExportPreamble (@export function type)
- resolveExportComptimeBlock (@export comptime block)
- resolveExportContinuation (@export continuation)
- triggerArchModuleCascade (arch-specific module imports)
- Plus helper functions only used by the above
All 193 corpus tests still pass — the hardcoded entries were not
needed for the current test suite's AIR comparison.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | stage0/sema.c | | | 2921 | +------------------------------------------------------------------------------ |
1 file changed, 3 insertions(+), 2918 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -3238,159 +3238,6 @@ static InternPoolIndex getEnumFieldIntVal(
return internTypedInt(int_tag_type, target_field_idx);
}
-// --- getEnumInstFromNav ---
-// Given a nav index that owns an enum type declaration, find the
-// ZIR enum_decl instruction. Returns the ZIR instruction index,
-// or UINT32_MAX if not found.
-static uint32_t getEnumInstFromNav(uint32_t nav_idx) {
- const Nav* nav = ipGetNav(nav_idx);
- uint32_t file_idx = s_namespaces[nav->namespace_idx].file_idx;
- if (!s_loaded_modules[file_idx].has_zir)
- return UINT32_MAX;
- const Zir* zir = &s_loaded_modules[file_idx].zir;
- const uint32_t* body = NULL;
- uint32_t body_len = 0;
- getValueBodyFromZir(zir, nav->zir_index, &body, &body_len);
- if (!body || body_len == 0)
- return UINT32_MAX;
- for (uint32_t i = 0; i < body_len; i++) {
- uint32_t inst = body[i];
- if (inst < zir->inst_len && zir->inst_tags[inst] == ZIR_INST_EXTENDED
- && zir->inst_datas[inst].extended.opcode == ZIR_EXT_ENUM_DECL)
- return inst;
- }
- return UINT32_MAX;
-}
-
-// --- internEnumTagByFieldName ---
-// Create an enum_tag IP entry for the given enum type and field name.
-// Looks up the field by name in the enum's ZIR declaration, gets the
-// field's integer value, and interns the enum_tag.
-// If force is true, always creates a new entry (no dedup) — use this
-// when matching the Zig compiler's expression evaluation which creates
-// fresh intermediate values.
-// Returns IP_INDEX_NONE on failure.
-static InternPoolIndex internEnumTagByFieldName(InternPoolIndex enum_type_ip,
- uint32_t enum_nav_idx, const char* field_name, bool force) {
- uint32_t file_idx
- = s_namespaces[ipGetNav(enum_nav_idx)->namespace_idx].file_idx;
- if (!s_loaded_modules[file_idx].has_zir)
- return IP_INDEX_NONE;
- const Zir* zir = &s_loaded_modules[file_idx].zir;
- uint32_t enum_inst = getEnumInstFromNav(enum_nav_idx);
- if (enum_inst == UINT32_MAX)
- return IP_INDEX_NONE;
- uint32_t field_idx = findEnumFieldByName(zir, enum_inst, field_name);
- if (field_idx == UINT32_MAX)
- return IP_INDEX_NONE;
- InternPoolIndex int_val = getEnumFieldIntVal(zir, enum_inst, field_idx);
- if (int_val == IP_INDEX_NONE)
- return IP_INDEX_NONE;
- InternPoolKey k;
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_ENUM_TAG;
- k.data.enum_tag.ty = enum_type_ip;
- k.data.enum_tag.int_val = int_val;
- if (force)
- return ipForceIntern(s_module_ip, k);
- return ipIntern(s_module_ip, k);
-}
-
-// Forward declaration.
-static InternPoolIndex findUnionTagEnum(InternPoolIndex union_type);
-
-// --- internUnionTagByFieldName ---
-// Create an enum_tag IP entry for a tagged union's field.
-// Looks up the field by name in the union's ZIR declaration, gets the
-// auto-enum tag value, and creates an enum_tag for the tag enum.
-// union_type_ip: the union type's IP index (used to find tag enum).
-// union_nav_idx: the nav owning the union declaration.
-// field_name: name of the union field.
-// force: if true, always creates a new entry.
-// Returns IP_INDEX_NONE on failure.
-static InternPoolIndex internUnionTagByFieldName(InternPoolIndex union_type_ip,
- uint32_t union_nav_idx, const char* field_name, bool force) {
- InternPoolIndex tag_enum = findUnionTagEnum(union_type_ip);
- if (tag_enum == IP_INDEX_NONE)
- return IP_INDEX_NONE;
- uint32_t file_idx
- = s_namespaces[ipGetNav(union_nav_idx)->namespace_idx].file_idx;
- if (!s_loaded_modules[file_idx].has_zir)
- return IP_INDEX_NONE;
- const Zir* zir = &s_loaded_modules[file_idx].zir;
- // Find the union_decl ZIR instruction.
- const uint32_t* vbody = NULL;
- uint32_t vbody_len = 0;
- getValueBodyFromZir(
- zir, ipGetNav(union_nav_idx)->zir_index, &vbody, &vbody_len);
- if (!vbody)
- return IP_INDEX_NONE;
- uint32_t union_inst = UINT32_MAX;
- for (uint32_t i = 0; i < vbody_len; i++) {
- uint32_t inst = vbody[i];
- if (inst < zir->inst_len && zir->inst_tags[inst] == ZIR_INST_EXTENDED
- && zir->inst_datas[inst].extended.opcode == ZIR_EXT_UNION_DECL) {
- union_inst = inst;
- break;
- }
- }
- if (union_inst == UINT32_MAX)
- return IP_INDEX_NONE;
- // Parse union_decl to find field names.
- uint16_t small = zir->inst_datas[union_inst].extended.small;
- uint32_t operand = zir->inst_datas[union_inst].extended.operand;
- uint32_t extra_index = operand + 6;
- if (small & (1 << 0))
- extra_index++; // tag_type
- uint32_t captures_len = 0;
- if (small & (1 << 1))
- captures_len = zir->extra[extra_index++];
- uint32_t body_len_val = 0;
- if (small & (1 << 2))
- body_len_val = zir->extra[extra_index++];
- uint32_t fields_len = 0;
- if (small & (1 << 3))
- fields_len = zir->extra[extra_index++];
- uint32_t decls_len = 0;
- if (small & (1 << 4))
- decls_len = zir->extra[extra_index++];
- extra_index += captures_len * 2;
- // Skip to field entries.
- uint32_t field_extra = extra_index + decls_len + body_len_val;
- uint32_t num_bit_bags = (fields_len + 7) / 8;
- uint32_t cursor = field_extra + num_bit_bags;
- for (uint32_t fi = 0; fi < fields_len; fi++) {
- uint32_t bag_idx = fi / 8;
- uint32_t bit_offset = (fi % 8) * 4;
- uint32_t bits
- = (zir->extra[field_extra + bag_idx] >> bit_offset) & 0xF;
- bool ft_has_type = (bits & 1) != 0;
- bool ft_has_align = (bits & 2) != 0;
- bool ft_has_value = (bits & 4) != 0;
- uint32_t fname_idx = zir->extra[cursor++];
- const char* fname = (const char*)&zir->string_bytes[fname_idx];
- if (strcmp(fname, field_name) == 0) {
- // Auto-enum tag: field index is the tag value.
- InternPoolIndex int_val = internTypedInt(IP_INDEX_U8_TYPE, fi);
- InternPoolKey k;
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_ENUM_TAG;
- k.data.enum_tag.ty = tag_enum;
- k.data.enum_tag.int_val = int_val;
- if (force)
- return ipForceIntern(s_module_ip, k);
- return ipIntern(s_module_ip, k);
- }
- if (ft_has_type)
- cursor++;
- if (ft_has_align)
- cursor++;
- if (ft_has_value)
- cursor++;
- }
- return IP_INDEX_NONE;
-}
-
// Forward declaration: resolves a ZIR instruction to an IP type index.
static InternPoolIndex resolveZirTypeInst(
const Zir* zir, uint32_t inst, uint32_t struct_ns, uint32_t file_idx);
@@ -4510,72 +4357,6 @@ static InternPoolIndex resolveStructDeclFromZir(
return struct_ip;
}
-// --- resolveAnonStructDeclFromZir ---
-// Like resolveStructDeclFromZir but for anonymous struct types returned from
-// comptime generic function calls (e.g. FeatureSetFns(Feature)).
-// Does NOT create ptr_nav for the struct (anonymous — no owning nav).
-// Takes file_idx directly instead of deriving it from a nav.
-// Returns the IP index of the struct type, or IP_INDEX_NONE on failure.
-static InternPoolIndex resolveAnonStructDeclFromZir(
- const Zir* zir, uint32_t struct_inst, uint32_t file_idx) {
- if (zir->inst_tags[struct_inst] != ZIR_INST_EXTENDED)
- return IP_INDEX_NONE;
- if (zir->inst_datas[struct_inst].extended.opcode != ZIR_EXT_STRUCT_DECL)
- return IP_INDEX_NONE;
-
- uint16_t small = zir->inst_datas[struct_inst].extended.small;
- uint32_t operand = zir->inst_datas[struct_inst].extended.operand;
-
- // Skip 6 u32 header (fields_hash×4, src_line, src_node).
- uint32_t extra_index = operand + 6;
-
- // Parse StructDecl.Small flags.
- bool has_captures_len = (small & (1 << 0)) != 0;
- bool has_fields_len = (small & (1 << 1)) != 0;
- bool has_decls_len = (small & (1 << 2)) != 0;
-
- uint32_t captures_len = 0;
- if (has_captures_len) {
- captures_len = zir->extra[extra_index++];
- }
- if (has_fields_len) {
- extra_index++; // skip fields_len
- }
- uint32_t decls_len = 0;
- if (has_decls_len) {
- decls_len = zir->extra[extra_index++];
- }
-
- extra_index += captures_len * 2; // skip captures
-
- // Skip backing_int if present (bit 3 of small).
- bool has_backing_int = (small & (1 << 3)) != 0;
- if (has_backing_int) {
- uint32_t backing_int_body_len = zir->extra[extra_index++];
- if (backing_int_body_len == 0) {
- extra_index++; // skip backing_int_ref
- } else {
- extra_index += backing_int_body_len; // skip body instructions
- }
- }
-
- // Create type_struct IP entry.
- InternPoolKey key;
- memset(&key, 0, sizeof(key));
- key.tag = IP_KEY_STRUCT_TYPE;
- key.data.struct_type = s_next_struct_hash++;
- InternPoolIndex struct_ip = ipIntern(s_module_ip, key);
-
- // Create namespace for the struct.
- uint32_t ns_idx = createNamespace(struct_ip, file_idx);
-
- // Scan namespace declarations.
- const uint32_t* decl_insts = &zir->extra[extra_index];
- scanNamespaceC(ns_idx, decl_insts, decls_len, zir);
-
- return struct_ip;
-}
-
// --- findNamespaceForType ---
// Find the namespace owned by a given type IP index.
static uint32_t findNamespaceForType(InternPoolIndex type_ip) {
@@ -5295,7 +5076,7 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) {
if (!AIR_REF_IS_IP(result) || AIR_REF_TO_IP(result) == IP_INDEX_NONE) {
// Value body evaluation failed. Try to resolve the TYPE annotation
- // so that resolveNavRef can create a ptr_nav with the correct type.
+ // so that callers can create a ptr_nav with the correct type.
// For `const lime1: CpuModel = .{...}`, the type body resolves to
// CpuModel even though the struct literal can't be evaluated.
const uint32_t* type_body = NULL;
@@ -5324,7 +5105,7 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) {
// Note: we do NOT create ptr_nav here. In the Zig compiler,
// ensureNavResolved only resolves the value; ptr_nav creation is
// handled separately by analyzeNavRefInner (called from analyzeNavVal).
- // Callers that need ptr_nav (resolveNestedTypeDecl, etc.) create it
+ // Callers that need ptr_nav create it
// explicitly.
nav = ipGetNav(nav_idx);
nav->resolved_type = result_ip;
@@ -5503,22 +5284,6 @@ static uint32_t findFileByPathSuffix(const char* suffix) {
return UINT32_MAX;
}
-// --- createCgBuiltinNav ---
-// Create a Nav in the compiler-generated builtin namespace.
-// Uses IP string_bytes for the name since this namespace has no ZIR.
-static uint32_t createCgBuiltinNav(const char* name) {
- if (s_cg_builtin_ns_idx == UINT32_MAX)
- return UINT32_MAX;
- uint32_t str_idx = ipGetOrPutString(s_module_ip, name);
- uint32_t nav_idx = ipCreateDeclNav(
- str_idx, str_idx, 0, s_cg_builtin_ns_idx, true, true);
- // Add to the namespace's pub_navs list.
- SemaNamespace* ns = &s_namespaces[s_cg_builtin_ns_idx];
- if (ns->pub_nav_count < SEMA_NS_MAX_NAVS)
- ns->pub_navs[ns->pub_nav_count++] = nav_idx;
- return nav_idx;
-}
-
// Forward declarations for functions used by resolveCgBuiltinField.
static InternPoolIndex internEnumTag(
InternPoolIndex enum_ty, InternPoolIndex int_val);
@@ -5615,17 +5380,6 @@ static InternPoolIndex internEnumTag(
return ipIntern(s_module_ip, key);
}
-// --- internEnumLiteral ---
-// Create an enum_literal IP entry for a named field.
-static InternPoolIndex internEnumLiteral(const char* name) {
- uint32_t str_idx = ipGetOrPutString(s_module_ip, name);
- InternPoolKey key;
- memset(&key, 0, sizeof(key));
- key.tag = IP_KEY_ENUM_LITERAL;
- key.data.enum_literal = str_idx;
- return ipIntern(s_module_ip, key);
-}
-
// --- internTypedInt ---
// Intern a typed integer value. Creates int_small if small enough.
static InternPoolIndex internTypedInt(InternPoolIndex ty, uint64_t val) {
@@ -5638,102 +5392,6 @@ static InternPoolIndex internTypedInt(InternPoolIndex ty, uint64_t val) {
return ipIntern(s_module_ip, key);
}
-// --- internStringLiteral ---
-// Intern a string literal, creating the sequence of IP entries that
-// the Zig compiler creates for a comptime string like "main".
-// Creates: [len:0]u8 type, bytes value, *const [len:0]u8 ptr_type,
-// ptr_uav, ptr_uav_aligned, int_usize(len), ptr_slice,
-// [len]u8 type, *const [len]u8 ptr_type, ptr_uav_aligned,
-// individual int_u8 values, bytes value.
-static void internStringLiteral(const char* str) {
- uint32_t slen = (uint32_t)strlen(str);
-
- // $198: [len:0]u8 (sentinel-terminated array type).
- InternPoolKey arr_key;
- memset(&arr_key, 0, sizeof(arr_key));
- arr_key.tag = IP_KEY_ARRAY_TYPE;
- arr_key.data.array_type.len = slen;
- arr_key.data.array_type.child = IP_INDEX_U8_TYPE;
- arr_key.data.array_type.sentinel = IP_INDEX_ZERO_U8;
- InternPoolIndex arr_type = ipIntern(s_module_ip, arr_key);
-
- // $199: bytes value (the string data stored in string_bytes).
- uint32_t str_idx = ipGetOrPutString(s_module_ip, str);
- InternPoolKey bytes_key;
- memset(&bytes_key, 0, sizeof(bytes_key));
- bytes_key.tag = IP_KEY_BYTES;
- bytes_key.data.bytes.ty = arr_type;
- bytes_key.data.bytes.str_idx = str_idx;
- InternPoolIndex bytes_val = ipIntern(s_module_ip, bytes_key);
-
- // $200: *const [len:0]u8 pointer type.
- InternPoolIndex arr_ptr_type = internPtrConst(arr_type);
-
- // $201: ptr_uav — pointer to the bytes value.
- InternPoolKey uav_key;
- memset(&uav_key, 0, sizeof(uav_key));
- uav_key.tag = IP_KEY_PTR_UAV;
- uav_key.data.ptr_uav.ty = arr_ptr_type;
- uav_key.data.ptr_uav.val = bytes_val;
- InternPoolIndex uav_ptr = ipIntern(s_module_ip, uav_key);
-
- // $202: ptr_uav_aligned — coerced to [*:0]const u8.
- InternPoolKey uav_aligned_key;
- memset(&uav_aligned_key, 0, sizeof(uav_aligned_key));
- uav_aligned_key.tag = IP_KEY_PTR_UAV_ALIGNED;
- uav_aligned_key.data.ptr_uav_aligned.ty
- = IP_INDEX_MANYPTR_CONST_U8_SENTINEL_0_TYPE;
- uav_aligned_key.data.ptr_uav_aligned.val = bytes_val;
- uav_aligned_key.data.ptr_uav_aligned.orig_ty = uav_ptr;
- InternPoolIndex uav_aligned = ipIntern(s_module_ip, uav_aligned_key);
-
- // $203: int_usize(len).
- InternPoolIndex len_val = internTypedInt(IP_INDEX_USIZE_TYPE, slen);
-
- // $204: ptr_slice — [:0]const u8 slice value.
- InternPoolKey slice_key;
- memset(&slice_key, 0, sizeof(slice_key));
- slice_key.tag = IP_KEY_PTR_SLICE;
- slice_key.data.ptr_slice.ty = IP_INDEX_SLICE_CONST_U8_SENTINEL_0_TYPE;
- slice_key.data.ptr_slice.ptr = uav_aligned;
- slice_key.data.ptr_slice.len = len_val;
- (void)ipIntern(s_module_ip, slice_key);
-
- // $205: [len]u8 (non-sentinel array type).
- InternPoolKey arr2_key;
- memset(&arr2_key, 0, sizeof(arr2_key));
- arr2_key.tag = IP_KEY_ARRAY_TYPE;
- arr2_key.data.array_type.len = slen;
- arr2_key.data.array_type.child = IP_INDEX_U8_TYPE;
- arr2_key.data.array_type.sentinel = IP_INDEX_NONE;
- InternPoolIndex arr2_type = ipIntern(s_module_ip, arr2_key);
-
- // $206: *const [len]u8 pointer type.
- InternPoolIndex arr2_ptr_type = internPtrConst(arr2_type);
-
- // $207: ptr_uav_aligned — pointer to string as [len]u8.
- InternPoolKey uav2_key;
- memset(&uav2_key, 0, sizeof(uav2_key));
- uav2_key.tag = IP_KEY_PTR_UAV_ALIGNED;
- uav2_key.data.ptr_uav_aligned.ty = arr2_ptr_type;
- uav2_key.data.ptr_uav_aligned.val = bytes_val;
- uav2_key.data.ptr_uav_aligned.orig_ty = uav_ptr;
- (void)ipIntern(s_module_ip, uav2_key);
-
- // $208-$211: individual int_u8 values for each byte.
- for (uint32_t i = 0; i < slen; i++) {
- (void)internTypedInt(IP_INDEX_U8_TYPE, (uint8_t)str[i]);
- }
-
- // $212: bytes value for the non-sentinel array.
- InternPoolKey bytes2_key;
- memset(&bytes2_key, 0, sizeof(bytes2_key));
- bytes2_key.tag = IP_KEY_BYTES;
- bytes2_key.data.bytes.ty = arr2_type;
- bytes2_key.data.bytes.str_idx = str_idx;
- (void)ipIntern(s_module_ip, bytes2_key);
-}
-
// --- internFuncType ---
// Create a function type IP entry.
// Ported from InternPool.zig getFuncType.
@@ -5762,2545 +5420,6 @@ static InternPoolIndex internFuncDecl(
return ipIntern(s_module_ip, key);
}
-// --- resolveNavType ---
-// Resolve a nav's type (ensureNavValUpToDate) without full resolution.
-// Returns the nav index (or UINT32_MAX if not found).
-static uint32_t resolveNavType(uint32_t parent_ns, const char* name) {
- uint32_t nav = findNavInNamespace(parent_ns, name);
- if (nav != UINT32_MAX) {
- (void)ensureNavValUpToDate(nav);
- }
- return nav;
-}
-
-// --- resolveFeatureSetConsts ---
-// Evaluate comptime declarations in Feature.Set's namespace that are
-// needed for its field types. The Zig compiler creates these entries
-// during resolveStructLayout(Set) when resolving [usize_count]usize.
-// We extract needed_bit_count from ZIR (literal), then compute
-// byte_count and usize_count, matching the Zig compiler's evaluation
-// chain in resolveDeclaredEnumInner / evalComptimeDecl.
-static void resolveFeatureSetConsts(uint32_t set_ns) {
- uint32_t nbc_nav = findNavInNamespace(set_ns, "needed_bit_count");
- uint32_t bc_nav = findNavInNamespace(set_ns, "byte_count");
- uint32_t uc_nav = findNavInNamespace(set_ns, "usize_count");
- if (nbc_nav == UINT32_MAX || bc_nav == UINT32_MAX || uc_nav == UINT32_MAX)
- return;
-
- // Evaluate needed_bit_count via analyzeNavValC (simple integer literal).
- InternPoolIndex nbc_ip = analyzeNavValC(nbc_nav);
- if (nbc_ip == IP_INDEX_NONE)
- return;
-
- InternPoolKey nbc_key = ipIndexToKey(s_module_ip, nbc_ip);
- uint64_t needed_bit_count = nbc_key.data.int_val.value_lo;
-
- // Create ptr_nav for needed_bit_count, matching Zig's
- // analyzeNavRefInner which creates a ptr_nav when byte_count's
- // comptime body references the needed_bit_count declaration.
- (void)internNavPtr(IP_INDEX_PTR_CONST_COMPTIME_INT_TYPE, nbc_nav);
-
- // Compute byte_count = (needed_bit_count + 7) / 8.
- // The Zig compiler interns the intermediate (needed_bit_count + 7)
- // during comptime evaluation of the add operation.
- uint64_t nbc_plus_7 = needed_bit_count + 7;
- InternPoolKey ct;
- memset(&ct, 0, sizeof(ct));
- ct.tag = IP_KEY_INT;
- ct.data.int_val.ty = IP_INDEX_COMPTIME_INT_TYPE;
- ct.data.int_val.value_lo = nbc_plus_7;
- (void)ipIntern(s_module_ip, ct);
-
- uint64_t byte_count = nbc_plus_7 / 8;
- InternPoolKey bk;
- memset(&bk, 0, sizeof(bk));
- bk.tag = IP_KEY_INT;
- bk.data.int_val.ty = IP_INDEX_COMPTIME_INT_TYPE;
- bk.data.int_val.value_lo = byte_count;
- InternPoolIndex bc_ip = ipIntern(s_module_ip, bk);
-
- {
- Nav* n = ipGetNav(bc_nav);
- n->resolved_type = bc_ip;
- (void)internNavPtr(IP_INDEX_PTR_CONST_COMPTIME_INT_TYPE, bc_nav);
- }
-
- // Compute usize_count = (byte_count + @sizeOf(usize) - 1) /
- // @sizeOf(usize).
- // Target is wasm32 → @sizeOf(usize) = 4.
- uint64_t ptr_size = 4;
- uint64_t usize_count = (byte_count + ptr_size - 1) / ptr_size;
- InternPoolKey uk;
- memset(&uk, 0, sizeof(uk));
- uk.tag = IP_KEY_INT;
- uk.data.int_val.ty = IP_INDEX_COMPTIME_INT_TYPE;
- uk.data.int_val.value_lo = usize_count;
- InternPoolIndex uc_ip = ipIntern(s_module_ip, uk);
-
- {
- Nav* n = ipGetNav(uc_nav);
- n->resolved_type = uc_ip;
- (void)internNavPtr(IP_INDEX_PTR_CONST_COMPTIME_INT_TYPE, uc_nav);
- }
-
- // Coerce usize_count to usize (needed for the array length).
- InternPoolKey ui;
- memset(&ui, 0, sizeof(ui));
- ui.tag = IP_KEY_INT;
- ui.data.int_val.ty = IP_INDEX_USIZE_TYPE;
- ui.data.int_val.value_lo = usize_count;
- (void)ipIntern(s_module_ip, ui);
-
- // Create array type [usize_count]usize.
- InternPoolKey ak;
- memset(&ak, 0, sizeof(ak));
- ak.tag = IP_KEY_ARRAY_TYPE;
- ak.data.array_type.child = IP_INDEX_USIZE_TYPE;
- ak.data.array_type.sentinel = IP_INDEX_NONE;
- ak.data.array_type.len = usize_count;
- (void)ipIntern(s_module_ip, ak);
-}
-
-// --- resolveNestedTypeDecl ---
-// Resolve a nested type declaration: ensureNavValUpToDate +
-// resolveStructFullyC. Returns the nav index (or UINT32_MAX if not found).
-static uint32_t resolveNestedTypeDecl(uint32_t parent_ns, const char* name) {
- uint32_t nav = findNavInNamespace(parent_ns, name);
- if (nav != UINT32_MAX) {
- (void)ensureNavValUpToDate(nav);
- // Mimic analyzeNavRefInner: create ptr_type + ptr_nav for the
- // declaration, matching what analyzeMemoizedState does via
- // sema.analyzeNavVal. For type declarations, the nav's "type"
- // is the metatype `type` (IP_INDEX_TYPE_TYPE), not the actual
- // resolved struct/enum type.
- const Nav* n = ipGetNav(nav);
- if (n->resolved_type != IP_INDEX_NONE) {
- InternPoolIndex ptr_ty = internPtrConst(IP_INDEX_TYPE_TYPE);
- (void)internNavPtr(ptr_ty, nav);
- }
- resolveStructFullyC(nav);
- resolveUnionFullyC(nav);
- }
- return nav;
-}
-
-// --- resolveAllTypesFullyC ---
-// Fixed-point iteration: resolve field types of all created struct types
-// until no new entries are created. Matches the recursive resolveFully
-// chain in the Zig compiler (Sema.zig resolveStructFully iterates each
-// field type and calls field_ty.resolveFully).
-static void resolveAllTypesFullyC(void) {
- for (uint32_t round = 0; round < 32; round++) {
- uint32_t ip_before = s_module_ip->items_len;
- for (uint32_t nsi = 0; nsi < s_num_namespaces; nsi++) {
- const SemaNamespace* ns = &s_namespaces[nsi];
- uint32_t file_idx = ns->file_idx;
- if (!s_loaded_modules[file_idx].has_zir)
- continue;
- const Zir* zir = &s_loaded_modules[file_idx].zir;
- for (uint32_t k = 0; k < ns->pub_nav_count; k++) {
- const Nav* nav = ipGetNav(ns->pub_navs[k]);
- if (nav->resolved_type == IP_INDEX_NONE)
- continue;
- if (nav->resolved_type >= s_module_ip->items_len)
- continue;
- if (s_module_ip->items[nav->resolved_type].tag
- != IP_KEY_STRUCT_TYPE)
- continue;
- // Ensure field types are resolved.
- const uint32_t* vbody = NULL;
- uint32_t vbody_len = 0;
- getValueBodyFromZir(zir, nav->zir_index, &vbody, &vbody_len);
- for (uint32_t vi = 0; vi < vbody_len; vi++) {
- uint32_t vinst = vbody[vi];
- if (vinst < zir->inst_len
- && zir->inst_tags[vinst] == ZIR_INST_EXTENDED
- && zir->inst_datas[vinst].extended.opcode
- == ZIR_EXT_STRUCT_DECL) {
- uint32_t sns
- = findNamespaceForType(nav->resolved_type);
- if (sns != UINT32_MAX)
- resolveStructFieldTypesC(
- zir, vinst, sns, file_idx);
- break;
- }
- }
- }
- }
- if (s_module_ip->items_len == ip_before)
- break; // no new entries, stable
- }
-}
-
-// --- resolveTargetModuleChain ---
-// After main-stage BuiltinDecl types are resolved, the Zig compiler
-// continues with demand-driven processing that loads Target.zig and
-// its nested types. This happens when builtin.target is accessed
-// (triggered by the panic stage or @export processing).
-// Creates entries $488+ matching the Zig compiler's processing order.
-//
-// Ported from the demand-driven module loading in PerThread.zig
-// ensureFileAnalyzed / scanNamespace / resolveStructFully chain.
-
-static void resolveTargetModuleChain(void) {
- if (!s_module_ip || !s_global_module_root)
- return;
- if (s_std_file_idx == UINT32_MAX || s_builtin_file_idx == UINT32_MAX)
- return;
-
- InternPoolIndex ptr_type = internPtrConst(IP_INDEX_TYPE_TYPE);
-
- // $488: Create deferred ptr_nav for `const builtin = @import("builtin")`
- // in std/builtin.zig. This is first accessed when the panic stage
- // evaluates builtin.zig_backend or when builtin.target is accessed.
- if (s_cg_builtin_nav != UINT32_MAX)
- (void)internNavPtr(ptr_type, s_cg_builtin_nav);
-
- // $489: Load Target.zig → creates root struct.
- // std.Target = @import("Target.zig")
- uint32_t std_ns_idx = s_file_namespace[s_std_file_idx];
- uint32_t target_nav = findNavInNamespace(std_ns_idx, "Target");
- if (target_nav == UINT32_MAX)
- return;
-
- // Resolve the Target import: load Target.zig
- const Zir* std_zir = &s_loaded_modules[s_std_file_idx].zir;
- const Nav* t_nav = ipGetNav(target_nav);
- const char* target_import
- = findDeclImportPathFromZir(std_zir, t_nav->zir_index);
- if (!target_import)
- return;
-
- char target_full[1024];
- if (!resolveImportPath(s_loaded_modules[s_std_file_idx].source_dir,
- target_import, target_full, sizeof(target_full)))
- return;
-
- uint32_t target_file_idx = ensureFileAnalyzedC(target_full);
- if (target_file_idx == UINT32_MAX)
- return;
-
- Nav* tn = ipGetNav(target_nav);
- tn->resolved_type = s_file_root_type[target_file_idx];
- (void)internNavPtr(ptr_type, target_nav);
-
- // Resolve Target's nested types in the order the Zig compiler
- // processes them (matching the demand-driven resolution chain
- // through builtin.target).
- uint32_t target_ns = s_file_namespace[target_file_idx];
- const Zir* target_zir = &s_loaded_modules[target_file_idx].zir;
-
- // Phase 1: Create type entries for Target's 5 field types in field order.
- // Matches Zig's resolveStructLayout which resolves each field type
- // sequentially, creating type + ptr_nav WITHOUT deep resolution.
- uint32_t cpu_nav = resolveNavType(target_ns, "Cpu");
- uint32_t os_nav = resolveNavType(target_ns, "Os");
- (void)resolveNavType(target_ns, "Abi");
- (void)resolveNavType(target_ns, "ObjectFormat");
- uint32_t dl_nav = resolveNavType(target_ns, "DynamicLinker");
-
- // Phase 2: Fully resolve each struct in field order, interleaved with
- // inner type resolution. Matches Zig's resolveFully loop which
- // recursively resolves each field type before moving to the next.
-
- // 2a. Target.Cpu — resolve field types, then inner types.
- if (cpu_nav != UINT32_MAX) {
- resolveStructFullyC(cpu_nav);
- const Nav* cn = ipGetNav(cpu_nav);
- uint32_t cpu_ns = findNamespaceForType(cn->resolved_type);
- if (cpu_ns != UINT32_MAX) {
- // Create remaining field type entries that
- // resolveStructFieldTypesC couldn't resolve (Feature.Set is
- // a compound type ref in ZIR). Must come before deep
- // resolution so Feature/Set entries precede opt_type from
- // Model's field types.
- (void)resolveNavType(cpu_ns, "Feature");
- uint32_t feat_nav = findNavInNamespace(cpu_ns, "Feature");
- if (feat_nav != UINT32_MAX) {
- const Nav* fn_nav = ipGetNav(feat_nav);
- uint32_t feat_ns = findNamespaceForType(fn_nav->resolved_type);
- if (feat_ns != UINT32_MAX)
- (void)resolveNavType(feat_ns, "Set");
- }
-
- // Deep resolution (matches resolveFully loop).
- // Model must be resolved first — its field types
- // (including ?[:0]const u8) precede Feature.Set's
- // comptime consts in the Zig IP.
- (void)resolveNestedTypeDecl(cpu_ns, "Arch");
- (void)resolveNestedTypeDecl(cpu_ns, "Model");
-
- // Feature.Set's comptime declarations follow Model's
- // field types in the Zig compiler's evaluation chain.
- if (feat_nav != UINT32_MAX) {
- const Nav* fn_nav3 = ipGetNav(feat_nav);
- uint32_t feat_ns3
- = findNamespaceForType(fn_nav3->resolved_type);
- if (feat_ns3 != UINT32_MAX) {
- uint32_t set_nav2 = findNavInNamespace(feat_ns3, "Set");
- if (set_nav2 != UINT32_MAX) {
- const Nav* sn = ipGetNav(set_nav2);
- uint32_t set_ns2
- = findNamespaceForType(sn->resolved_type);
- if (set_ns2 != UINT32_MAX)
- resolveFeatureSetConsts(set_ns2);
- }
- }
- }
-
- (void)resolveNestedTypeDecl(cpu_ns, "Feature");
- if (feat_nav != UINT32_MAX) {
- const Nav* fn2 = ipGetNav(feat_nav);
- uint32_t fns2 = findNamespaceForType(fn2->resolved_type);
- if (fns2 != UINT32_MAX)
- (void)resolveNestedTypeDecl(fns2, "Set");
- }
- }
- }
-
- // 2b. Target.Os — resolve field types, then inner types.
- //
- // resolveStructFullyC(os_nav) cascades into resolving VersionRange
- // field types, which reference std.SemanticVersion.Range. Pre-set
- // Target.zig's `std` import so the decl_val resolver can find it.
- // The DECL_VAL and field_val handlers in resolveZirTypeInst create
- // ptr_nav entries as side effects, matching Zig's analyzeNavRef.
- if (os_nav != UINT32_MAX) {
- // Target.zig has `const std = @import("std")`.
- // Pre-set resolved_type so field type resolution inside
- // Target.zig can resolve std.* references without re-loading
- // the already-loaded std.zig.
- {
- uint32_t std_import_nav = findNavInNamespace(target_ns, "std");
- if (std_import_nav != UINT32_MAX) {
- Nav* si = ipGetNav(std_import_nav);
- if (si->resolved_type == IP_INDEX_NONE)
- si->resolved_type = s_file_root_type[s_std_file_idx];
- }
- }
-
- resolveStructFullyC(os_nav);
- const Nav* on = ipGetNav(os_nav);
- uint32_t os_ns = findNamespaceForType(on->resolved_type);
- if (os_ns != UINT32_MAX) {
- (void)resolveNestedTypeDecl(os_ns, "Tag");
- uint32_t vr_nav = resolveNavType(os_ns, "VersionRange");
-
- if (vr_nav != UINT32_MAX)
- resolveUnionFullyC(vr_nav);
-
- (void)resolveNestedTypeDecl(os_ns, "HurdVersionRange");
- (void)resolveNestedTypeDecl(os_ns, "LinuxVersionRange");
- (void)resolveNestedTypeDecl(os_ns, "WindowsVersion");
- }
- }
-
- // 2c. Target.DynamicLinker — resolve field types.
- if (dl_nav != UINT32_MAX)
- resolveStructFullyC(dl_nav);
- (void)target_zir;
-}
-
-// --- resolveNavRef ---
-// Resolve a nav's value and create ptr_type + ptr_nav for it.
-// This matches the Zig compiler's analyzeNavRefInner: first resolve
-// the nav value via ensureNavResolved, then create ptr_nav.
-// Returns the ptr_nav IP index, or IP_INDEX_NONE.
-static InternPoolIndex resolveNavRef(uint32_t nav_idx) {
- (void)ensureNavValUpToDate(nav_idx);
- const Nav* n = ipGetNav(nav_idx);
- if (n->resolved_type == IP_INDEX_NONE)
- return IP_INDEX_NONE;
- InternPoolIndex val_ty = ipTypeOf(s_module_ip, n->resolved_type);
- if (val_ty == IP_INDEX_NONE)
- val_ty = IP_INDEX_TYPE_TYPE;
- InternPoolIndex ptr_ty = internPtrConst(val_ty);
- return internNavPtr(ptr_ty, nav_idx);
-}
-
-// --- triggerArchModuleCascade ---
-// Trigger the arch-specific module import cascade that the Zig compiler
-// performs during cCallingConvention() evaluation. When the Zig compiler
-// dereferences *const Target in loadComptimePtrInner, it cascades through
-// nav resolution into importing the arch-specific module (e.g.
-// Target/wasm.zig for wasm32). This creates type_struct, ptr_nav,
-// type_enum_auto, func_decl, memoized_call entries etc.
-//
-// The arch module name is derived from the arch family: wasm32/wasm64 →
-// "wasm", x86/x86_64 → "x86", etc. We find the matching nav in
-// Target.zig's namespace by trying progressively shorter prefixes.
-//
-// The nav resolution order was determined by tracing the Zig compiler's
-// demand-driven evaluation in loadComptimePtrInner. We replicate the
-// exact same order to produce matching IP indices.
-//
-// Ported from the side effects of Sema/comptime_ptr_access.zig
-// loadComptimePtrInner → ensureNavResolved → analyzeNavVal chain.
-static void resolveExportComptimeBlock(uint32_t builtin_ns_idx);
-static void resolveExportContinuation(Sema* sema);
-static void zirExport(Sema* sema, uint32_t inst);
-static void triggerArchModuleCascade(
- uint32_t target_ns, uint32_t target_file_idx) {
- if (!s_target_cpu_arch_name || !s_module_ip)
- return;
-
- // Find the arch module nav by trying progressively shorter prefixes
- // of the arch name. E.g. "wasm32" → "wasm32" (no) → ... → "wasm" (yes).
- char name[64];
- snprintf(name, sizeof(name), "%s", s_target_cpu_arch_name);
-
- uint32_t arch_module_nav = UINT32_MAX;
- for (size_t len = strlen(name); len > 0; len--) {
- name[len] = '\0';
- arch_module_nav = findNavInNamespace(target_ns, name);
- if (arch_module_nav != UINT32_MAX)
- break;
- }
- if (arch_module_nav == UINT32_MAX)
- return;
-
- // $685: Resolve the arch module nav → @import("Target/<arch>.zig").
- // Creates type_struct for the arch module root.
- (void)ensureNavValUpToDate(arch_module_nav);
- const Nav* arch_n = ipGetNav(arch_module_nav);
- if (arch_n->resolved_type == IP_INDEX_NONE)
- return;
- InternPoolIndex arch_struct = arch_n->resolved_type;
- uint32_t arch_ns = findNamespaceForType(arch_struct);
- if (arch_ns == UINT32_MAX)
- return;
-
- // $686: ptr_nav for the arch module nav (e.g. "wasm" in Target.zig).
- InternPoolIndex arch_ptr_ty = internPtrConst(IP_INDEX_TYPE_TYPE);
- (void)internNavPtr(arch_ptr_ty, arch_module_nav);
-
- // Resolve navs in the arch module in the order the Zig compiler's
- // demand-driven evaluation resolves them during loadComptimePtrInner.
- // Order determined by tracing the Zig compiler (see cascade trace).
-
- // $687-$688: "cpu" struct in arch module.
- uint32_t cpu_nav = findNavInNamespace(arch_ns, "cpu");
- if (cpu_nav != UINT32_MAX)
- (void)resolveNavRef(cpu_nav);
-
- // $689: "std" (private import in arch module).
- uint32_t std_priv = findNavInNamespace(arch_ns, "std");
- if (std_priv != UINT32_MAX)
- (void)resolveNavRef(std_priv);
-
- // $690: "CpuModel" (private const = std.Target.Cpu.Model).
- uint32_t cpumodel = findNavInNamespace(arch_ns, "CpuModel");
- if (cpumodel != UINT32_MAX)
- (void)resolveNavRef(cpumodel);
-
- // $691: ptr_nav for the target's default CPU model constant.
- // The Zig compiler resolves exactly one CPU model during the
- // cCallingConvention cascade (demand-driven from loadComptimePtrInner
- // dereferencing cpu.model which is *const CpuModel).
- // Find it in the cpu struct's namespace using s_target_cpu_model_name.
- uint32_t model_nav = UINT32_MAX;
- if (cpu_nav != UINT32_MAX && s_target_cpu_model_name) {
- const Nav* cpu_n = ipGetNav(cpu_nav);
- if (cpu_n->resolved_type != IP_INDEX_NONE) {
- uint32_t cpu_ns = findNamespaceForType(cpu_n->resolved_type);
- if (cpu_ns != UINT32_MAX) {
- model_nav
- = findNavInNamespace(cpu_ns, s_target_cpu_model_name);
- if (model_nav != UINT32_MAX)
- (void)resolveNavRef(model_nav);
- }
- }
- }
-
- // $692: "CpuFeature" (private const = std.Target.Cpu.Feature).
- uint32_t cpufeat = findNavInNamespace(arch_ns, "CpuFeature");
- uint32_t fsf_nav = UINT32_MAX;
- uint32_t cpufeat_ns = UINT32_MAX;
- if (cpufeat != UINT32_MAX) {
- (void)resolveNavRef(cpufeat);
-
- // $693-$696: FeatureSetFns — a function in std.Target.Cpu.Feature.
- // (Not in Feature.Set — FeatureSetFns is at Feature's level.)
- const Nav* cf = ipGetNav(cpufeat);
- if (cf->resolved_type != IP_INDEX_NONE) {
- cpufeat_ns = findNamespaceForType(cf->resolved_type);
- if (cpufeat_ns != UINT32_MAX) {
- fsf_nav = findNavInNamespace(cpufeat_ns, "FeatureSetFns");
- if (fsf_nav != UINT32_MAX)
- (void)resolveNavRef(fsf_nav);
- }
- }
- }
-
- // $697-$698: "Feature" enum in arch module.
- uint32_t feature = findNavInNamespace(arch_ns, "Feature");
- if (feature != UINT32_MAX)
- (void)resolveNavRef(feature);
-
- // $699-$706: Evaluate FeatureSetFns(Feature) generic call.
- // Creates type_struct (the anonymous return struct), memoized_call,
- // then resolves featureSet from the struct's namespace creating
- // type_pointer, type_slice, type_function, func_decl, ptr entries.
- // Ported from Sema.zig analyzeCall for comptime generic functions
- // that return struct types.
- if (fsf_nav != UINT32_MAX && feature != UINT32_MAX) {
- const Nav* fsf = ipGetNav(fsf_nav);
- InternPoolIndex fsf_func_decl = fsf->resolved_type;
- InternPoolIndex feature_type = ipGetNav(feature)->resolved_type;
-
- if (fsf_func_decl != IP_INDEX_NONE && feature_type != IP_INDEX_NONE) {
- // Get FeatureSetFns's ZIR to find the inner struct_decl.
- uint32_t fsf_file = s_namespaces[fsf->namespace_idx].file_idx;
- const Zir* fsf_zir = &s_loaded_modules[fsf_file].zir;
-
- // Find the func instruction in FeatureSetFns's value body.
- const uint32_t* vb = NULL;
- uint32_t vb_len = 0;
- getValueBodyFromZir(fsf_zir, fsf->zir_index, &vb, &vb_len);
-
- uint32_t func_inst = UINT32_MAX;
- for (uint32_t i = 0; i < vb_len; i++) {
- if (vb[i] < fsf_zir->inst_len) {
- ZirInstTag t = fsf_zir->inst_tags[vb[i]];
- if (t == ZIR_INST_FUNC || t == ZIR_INST_FUNC_FANCY) {
- func_inst = vb[i];
- break;
- }
- }
- }
-
- if (func_inst != UINT32_MAX) {
- // Parse func to get function body.
- Sema tmp;
- semaInit(&tmp, s_module_ip, *fsf_zir);
- FuncZirInfo fi = parseFuncZir(&tmp, func_inst);
- semaDeinit(&tmp);
-
- // Search function body for struct_decl.
- const uint32_t* fb = &fsf_zir->extra[fi.extra_index];
- uint32_t struct_inst = UINT32_MAX;
- for (uint32_t i = 0; i < fi.body_len; i++) {
- uint32_t bi = fb[i];
- if (bi < fsf_zir->inst_len
- && fsf_zir->inst_tags[bi] == ZIR_INST_EXTENDED
- && fsf_zir->inst_datas[bi].extended.opcode
- == ZIR_EXT_STRUCT_DECL) {
- struct_inst = bi;
- break;
- }
- }
-
- if (struct_inst != UINT32_MAX) {
- // $699: type_struct — the anonymous struct returned
- // by FeatureSetFns(Feature).
- InternPoolIndex anon_struct = resolveAnonStructDeclFromZir(
- fsf_zir, struct_inst, fsf_file);
-
- if (anon_struct != IP_INDEX_NONE) {
- // $700: memoized_call — cache the generic call
- // result.
- InternPoolKey mck;
- memset(&mck, 0, sizeof(mck));
- mck.tag = IP_KEY_MEMOIZED_CALL;
- mck.data.memoized_call.func = fsf_func_decl;
- mck.data.memoized_call.result = anon_struct;
- (void)ipIntern(s_module_ip, mck);
-
- // $701-$706: Resolve featureSet from the
- // struct namespace. The param type []const F
- // resolves to []const Feature via capture.
- uint32_t anon_ns = findNamespaceForType(anon_struct);
- if (anon_ns != UINT32_MAX) {
- uint32_t fs_nav
- = findNavInNamespace(anon_ns, "featureSet");
- if (fs_nav != UINT32_MAX) {
- // $701: [*]const Feature
- // (many-pointer, const — the
- // element ptr for the slice).
- InternPoolKey mpk;
- memset(&mpk, 0, sizeof(mpk));
- mpk.tag = IP_KEY_PTR_TYPE;
- mpk.data.ptr_type.child = feature_type;
- mpk.data.ptr_type.sentinel = IP_INDEX_NONE;
- mpk.data.ptr_type.flags
- = PTR_FLAGS_SIZE_MANY | PTR_FLAGS_IS_CONST;
- mpk.data.ptr_type.packed_offset = 0;
- InternPoolIndex mp_feat
- = ipIntern(s_module_ip, mpk);
- // $702: []const Feature (slice type
- // wrapping the many-pointer).
- InternPoolKey sk;
- memset(&sk, 0, sizeof(sk));
- sk.tag = IP_KEY_SLICE;
- sk.data.slice = mp_feat;
- (void)ipIntern(s_module_ip, sk);
-
- // Get Set type for return type.
- InternPoolIndex set_type = IP_INDEX_VOID_TYPE;
- if (cpufeat_ns != UINT32_MAX) {
- uint32_t set_nav = findNavInNamespace(
- cpufeat_ns, "Set");
- if (set_nav != UINT32_MAX) {
- InternPoolIndex st
- = ipGetNav(set_nav)->resolved_type;
- if (st != IP_INDEX_NONE)
- set_type = st;
- }
- }
- // $703: func_type for featureSet.
- InternPoolIndex ft
- = internFuncType(set_type, 1, 0, false);
- // $704: func_decl for featureSet.
- InternPoolIndex fd
- = internFuncDecl(fs_nav, ft);
- Nav* fsn = ipGetNav(fs_nav);
- fsn->resolved_type = fd;
- // $705: ptr_type(*const fn_type).
- InternPoolIndex pt = internPtrConst(ft);
- // $706: ptr_nav for featureSet.
- (void)internNavPtr(pt, fs_nav);
- }
- }
- }
- }
- }
- }
- }
-
- // Variables carried forward from features block to featureSet block.
- InternPoolIndex feat_agg_ip = IP_INDEX_NONE;
- InternPoolIndex feat_uav_ip = IP_INDEX_NONE;
- uint32_t stored_feat_count = 0;
- uint32_t stored_feat_values[64];
- memset(stored_feat_values, 0, sizeof(stored_feat_values));
-
- // $707-$720: Evaluate the CPU model's feature set.
- // The Zig compiler evaluates featureSet(&[_]Feature{...}) from the
- // CPU model's struct literal. This creates the feature array type,
- // enum_tag entries for each feature, an aggregate for the array value,
- // and a pointer/slice chain.
- // Ported from the comptime evaluation of CpuModel.features init.
- if (model_nav != UINT32_MAX && feature != UINT32_MAX) {
- InternPoolIndex feature_type = ipGetNav(feature)->resolved_type;
- if (feature_type != IP_INDEX_NONE) {
- // Get the Feature enum's ZIR instruction (for field lookup).
- const Nav* feat_n = ipGetNav(feature);
- uint32_t feat_file = s_namespaces[feat_n->namespace_idx].file_idx;
- const Zir* feat_zir = &s_loaded_modules[feat_file].zir;
- const uint32_t* feat_vb = NULL;
- uint32_t feat_vb_len = 0;
- getValueBodyFromZir(
- feat_zir, feat_n->zir_index, &feat_vb, &feat_vb_len);
- uint32_t enum_inst = UINT32_MAX;
- for (uint32_t i = 0; i < feat_vb_len; i++) {
- if (feat_vb[i] < feat_zir->inst_len
- && feat_zir->inst_tags[feat_vb[i]] == ZIR_INST_EXTENDED
- && feat_zir->inst_datas[feat_vb[i]].extended.opcode
- == ZIR_EXT_ENUM_DECL) {
- enum_inst = feat_vb[i];
- break;
- }
- }
-
- if (enum_inst != UINT32_MAX) {
- // Get the model nav's ZIR value body.
- const Nav* model_n = ipGetNav(model_nav);
- uint32_t model_file
- = s_namespaces[model_n->namespace_idx].file_idx;
- const Zir* model_zir = &s_loaded_modules[model_file].zir;
- const uint32_t* mvb = NULL;
- uint32_t mvb_len = 0;
- getValueBodyFromZir(
- model_zir, model_n->zir_index, &mvb, &mvb_len);
-
- if (mvb && mvb_len > 0) {
- // Find the call instruction and the next
- // top-level instruction in the value body.
- // The enum_literal instructions for the feature
- // array are between these two (as sub-insts
- // not in the value body's top-level list).
- uint32_t call_inst = UINT32_MAX;
- uint32_t after_call = UINT32_MAX;
- for (uint32_t i = 0; i < mvb_len; i++) {
- uint32_t mi = mvb[i];
- if (mi < model_zir->inst_len
- && model_zir->inst_tags[mi] == ZIR_INST_CALL) {
- call_inst = mi;
- if (i + 1 < mvb_len)
- after_call = mvb[i + 1];
- break;
- }
- }
-
- // Phase 1: Scan ZIR instructions between the
- // call and the next top-level inst for
- // decl_literal instructions matching Feature
- // enum fields.
- uint32_t feat_indices[64];
- uint32_t feat_count = 0;
- if (call_inst != UINT32_MAX && after_call != UINT32_MAX) {
- for (uint32_t zi = call_inst + 1; zi < after_call;
- zi++) {
- if (zi >= model_zir->inst_len)
- continue;
- if (model_zir->inst_tags[zi]
- != ZIR_INST_DECL_LITERAL)
- continue;
- // decl_literal uses pl_node; payload is
- // Field {lhs: Ref, field_name_start: u32}.
- uint32_t pi = model_zir->inst_datas[zi]
- .pl_node.payload_index;
- uint32_t nsi = model_zir->extra[pi + 1];
- const char* fn
- = (const char*)&model_zir->string_bytes[nsi];
- uint32_t fidx
- = findEnumFieldByName(feat_zir, enum_inst, fn);
- if (fidx != UINT32_MAX && feat_count < 64)
- feat_indices[feat_count++] = fidx;
- }
- }
- if (feat_count > 0) {
- // $707: type_array_small [N]Feature.
- InternPoolKey ak;
- memset(&ak, 0, sizeof(ak));
- ak.tag = IP_KEY_ARRAY_TYPE;
- ak.data.array_type.len = feat_count;
- ak.data.array_type.child = feature_type;
- ak.data.array_type.sentinel = IP_INDEX_NONE;
- InternPoolIndex arr_type = ipIntern(s_module_ip, ak);
-
- // $708-$714: enum_tag for each feature.
- for (uint32_t i = 0; i < feat_count; i++) {
- InternPoolIndex iv = getEnumFieldIntVal(
- feat_zir, enum_inst, feat_indices[i]);
- if (iv != IP_INDEX_NONE)
- (void)internEnumTag(feature_type, iv);
- }
-
- // Save feature values for featureSet eval.
- stored_feat_count = feat_count;
- for (uint32_t si = 0; si < feat_count && si < 64;
- si++) {
- InternPoolIndex siv = getEnumFieldIntVal(
- feat_zir, enum_inst, feat_indices[si]);
- if (siv != IP_INDEX_NONE) {
- InternPoolKey sk
- = ipIndexToKey(s_module_ip, siv);
- stored_feat_values[si]
- = (uint32_t)sk.data.int_val.value_lo;
- }
- }
-
- // $715: aggregate (array value).
- InternPoolKey agk;
- memset(&agk, 0, sizeof(agk));
- agk.tag = IP_KEY_AGGREGATE;
- agk.data.aggregate = arr_type;
- InternPoolIndex agg = ipIntern(s_module_ip, agk);
-
- // $716: *const [N]Feature.
- InternPoolIndex arr_ptr = internPtrConst(arr_type);
-
- feat_agg_ip = agg;
-
- // $717: ptr_uav.
- InternPoolKey uav;
- memset(&uav, 0, sizeof(uav));
- uav.tag = IP_KEY_PTR_UAV;
- uav.data.ptr_uav.ty = arr_ptr;
- uav.data.ptr_uav.val = agg;
- InternPoolIndex uav_ptr = ipIntern(s_module_ip, uav);
- feat_uav_ip = uav_ptr;
-
- // $718: ptr_uav_aligned.
- InternPoolKey uaa;
- memset(&uaa, 0, sizeof(uaa));
- uaa.tag = IP_KEY_PTR_UAV_ALIGNED;
- uaa.data.ptr_uav_aligned.ty = arr_ptr;
- uaa.data.ptr_uav_aligned.val = agg;
- uaa.data.ptr_uav_aligned.orig_ty = uav_ptr;
- InternPoolIndex aligned = ipIntern(s_module_ip, uaa);
-
- // $719: int_usize(N).
- InternPoolIndex len_val
- = internTypedInt(IP_INDEX_USIZE_TYPE, feat_count);
-
- // $720: ptr_slice.
- // Slice type []const Feature was already
- // created as IP_KEY_SLICE wrapping [*]const
- // Feature (from $702). Look it up.
- InternPoolKey mpk2;
- memset(&mpk2, 0, sizeof(mpk2));
- mpk2.tag = IP_KEY_PTR_TYPE;
- mpk2.data.ptr_type.child = feature_type;
- mpk2.data.ptr_type.sentinel = IP_INDEX_NONE;
- mpk2.data.ptr_type.flags
- = PTR_FLAGS_SIZE_MANY | PTR_FLAGS_IS_CONST;
- mpk2.data.ptr_type.packed_offset = 0;
- InternPoolIndex mp2 = ipIntern(s_module_ip, mpk2);
- InternPoolKey slk;
- memset(&slk, 0, sizeof(slk));
- slk.tag = IP_KEY_SLICE;
- slk.data.slice = mp2;
- InternPoolIndex slice_ty = ipIntern(s_module_ip, slk);
-
- InternPoolKey psk;
- memset(&psk, 0, sizeof(psk));
- psk.tag = IP_KEY_PTR_SLICE;
- psk.data.ptr_slice.ty = slice_ty;
- psk.data.ptr_slice.ptr = aligned;
- psk.data.ptr_slice.len = len_val;
- (void)ipIntern(s_module_ip, psk);
- }
- }
- }
- }
- }
-
- // $721+: Comptime evaluation of featureSet().
- // The Zig compiler evaluates featureSet(&[_]Feature{...}) which
- // creates: [1]usize type, repeated zero values, comptime allocations,
- // Log2Int type resolutions (Index=u9, ShiftInt=u5), function decls
- // for addFeature, and per-feature bit manipulation values.
- // Ported from the side effects of Sema comptime evaluation.
- if (model_nav != UINT32_MAX && feature != UINT32_MAX
- && cpufeat_ns != UINT32_MAX) {
- // Look up Set inside std.Target.Cpu.Feature (cpufeat_ns), not inside
- // the arch module's Feature enum (which has no declarations).
- uint32_t set_nav = findNavInNamespace(cpufeat_ns, "Set");
- uint32_t set_ns = UINT32_MAX;
- if (set_nav != UINT32_MAX) {
- const Nav* sn2 = ipGetNav(set_nav);
- set_ns = findNamespaceForType(sn2->resolved_type);
- }
- if (set_ns != UINT32_MAX) {
- // Look up needed_bit_count and usize_count from Set navs.
- uint32_t nbc_nav = findNavInNamespace(set_ns, "needed_bit_count");
- uint32_t uc_nav = findNavInNamespace(set_ns, "usize_count");
- uint32_t needed_bit_count = 0;
- uint32_t usize_count_val = 0;
- if (nbc_nav != UINT32_MAX) {
- InternPoolIndex nbc = ipGetNav(nbc_nav)->resolved_type;
- if (nbc != IP_INDEX_NONE) {
- InternPoolKey k = ipIndexToKey(s_module_ip, nbc);
- needed_bit_count = (uint32_t)k.data.int_val.value_lo;
- }
- }
- if (uc_nav != UINT32_MAX) {
- InternPoolIndex uc = ipGetNav(uc_nav)->resolved_type;
- if (uc != IP_INDEX_NONE) {
- InternPoolKey k = ipIndexToKey(s_module_ip, uc);
- usize_count_val = (uint32_t)k.data.int_val.value_lo;
- }
- }
- if (needed_bit_count > 0 && usize_count_val > 0) {
- uint32_t usize_bits = 32; // wasm32: @bitSizeOf(usize)
-
- // Find the [usize_count]usize array type (already created
- // by resolveFeatureSetConsts).
- InternPoolKey arr9k;
- memset(&arr9k, 0, sizeof(arr9k));
- arr9k.tag = IP_KEY_ARRAY_TYPE;
- arr9k.data.array_type.len = usize_count_val;
- arr9k.data.array_type.child = IP_INDEX_USIZE_TYPE;
- arr9k.data.array_type.sentinel = IP_INDEX_NONE;
- InternPoolIndex arr9_ty = ipIntern(s_module_ip, arr9k);
-
- // $721: type_array_small [1]usize.
- InternPoolKey a1k;
- memset(&a1k, 0, sizeof(a1k));
- a1k.tag = IP_KEY_ARRAY_TYPE;
- a1k.data.array_type.len = 1;
- a1k.data.array_type.child = IP_INDEX_USIZE_TYPE;
- a1k.data.array_type.sentinel = IP_INDEX_NONE;
- InternPoolIndex arr1_ty = ipIntern(s_module_ip, a1k);
-
- // $722: repeated([1]u32, 0) — [1]usize{0}.
- InternPoolIndex usize_zero
- = internTypedInt(IP_INDEX_USIZE_TYPE, 0);
- InternPoolKey rk;
- memset(&rk, 0, sizeof(rk));
- rk.tag = IP_KEY_REPEATED;
- rk.data.repeated.ty = arr1_ty;
- rk.data.repeated.elem_val = usize_zero;
- (void)ipIntern(s_module_ip, rk);
-
- // $723: repeated([9]u32, 0) — [9]usize{0,...,0}.
- rk.data.repeated.ty = arr9_ty;
- rk.data.repeated.elem_val = usize_zero;
- InternPoolIndex arr9_zero = ipIntern(s_module_ip, rk);
-
- // --- Set.empty evaluation ---
- // The Zig compiler evaluates Set.empty = Set{.ints =
- // [9]usize{0,...,0}}. Since Set has one field and its value is
- // the repeated zero array, the aggregate is stored as
- // repeated(Set_type, arr9_zero).
- InternPoolIndex set_struct = ipGetNav(set_nav)->resolved_type;
-
- // $724: repeated(Set, arr9_zero) — Set.empty value.
- rk.data.repeated.ty = set_struct;
- rk.data.repeated.elem_val = arr9_zero;
- (void)ipIntern(s_module_ip, rk);
-
- // $725-$726: Resolve Set.empty nav → creates *const Set
- // pointer type and ptr_nav for the empty declaration.
- uint32_t empty_nav = findNavInNamespace(set_ns, "empty");
- if (empty_nav != UINT32_MAX) {
- Nav* en = ipGetNav(empty_nav);
- if (en->resolved_type == IP_INDEX_NONE) {
- // Set empty's resolved value to the Set.empty
- // repeated value we just created.
- en->resolved_type = set_struct;
- }
- InternPoolIndex ptr_const_set = internPtrConst(set_struct);
- (void)internNavPtr(ptr_const_set, empty_nav);
- }
-
- // $727: type_pointer — *Set (mutable pointer for
- // addFeature's self parameter).
- InternPoolIndex ptr_mut_set = internPtrMutable(set_struct);
-
- // $728: undef(Set) — initial undefined value for
- // the comptime alloc before Set.empty is copied in.
- InternPoolIndex undef_set = internUndef(set_struct);
-
- // $729: ptr_comptime_alloc — comptime alloc for the
- // return value of featureSet().
- InternPoolIndex pca0 = internPtrComptimeAlloc(ptr_mut_set, 0);
-
- // $730: ptr_comptime_alloc — comptime alloc for the
- // local variable `var x` in featureSet().
- InternPoolIndex pca1 = internPtrComptimeAlloc(ptr_mut_set, 1);
-
- // $731: int_usize(0xFFFFFFFF) — max usize value.
- // Created during the for loop range computation.
- (void)internTypedInt(IP_INDEX_USIZE_TYPE, 0xFFFFFFFF);
-
- (void)undef_set;
- (void)pca0;
- (void)pca1;
-
- // $732: *const Feature — pointer for for-loop
- // element access during featureSet iteration.
- InternPoolIndex feature_type2
- = ipGetNav(feature)->resolved_type;
- InternPoolIndex ptr_const_feat = internPtrConst(feature_type2);
-
- // $733: ptr_uav_aligned — element pointer into the
- // features array, used by for-loop iteration.
- if (feat_agg_ip != IP_INDEX_NONE
- && feat_uav_ip != IP_INDEX_NONE) {
- InternPoolKey uaa;
- memset(&uaa, 0, sizeof(uaa));
- uaa.tag = IP_KEY_PTR_UAV_ALIGNED;
- uaa.data.ptr_uav_aligned.ty = ptr_const_feat;
- uaa.data.ptr_uav_aligned.val = feat_agg_ip;
- uaa.data.ptr_uav_aligned.orig_ty = feat_uav_ip;
- (void)ipIntern(s_module_ip, uaa);
- }
-
- // $734-$737: Load std.math module and resolve Log2Int.
- uint32_t std_ns_idx2 = s_file_namespace[s_std_file_idx];
- uint32_t math_nav = findNavInNamespace(std_ns_idx2, "math");
- if (math_nav != UINT32_MAX) {
- char math_path[1024];
- snprintf(math_path, sizeof(math_path), "%s/math.zig",
- s_loaded_modules[s_std_file_idx].source_dir);
- uint32_t math_file = ensureFileAnalyzedC(math_path);
- if (math_file != UINT32_MAX) {
- // $734: type_struct for std.math root.
- // (created by ensureFileAnalyzedC)
- // $735: ptr_nav for 'std.math'.
- Nav* mn = ipGetNav(math_nav);
- mn->resolved_type = s_file_root_type[math_file];
- InternPoolIndex ptr_type
- = internPtrConst(IP_INDEX_TYPE_TYPE);
- (void)internNavPtr(ptr_type, math_nav);
-
- // $736-$737: Log2Int func_decl + ptr_nav.
- uint32_t math_ns = s_file_namespace[math_file];
- uint32_t log2int_nav
- = findNavInNamespace(math_ns, "Log2Int");
- if (log2int_nav != UINT32_MAX) {
- // Log2Int is fn(comptime type) type.
- // The func_type must match what analyzeNavValC
- // creates (ret=type, params=1) so it deduplicates
- // with the existing entry. This avoids creating
- // an extra func_type + ptr_type pair.
- InternPoolIndex log2int_ft = internFuncType(
- IP_INDEX_TYPE_TYPE, 1, 0, false);
-
- InternPoolIndex log2int_fd
- = internFuncDecl(log2int_nav, log2int_ft);
- Nav* l2n = ipGetNav(log2int_nav);
- l2n->resolved_type = log2int_fd;
- InternPoolIndex l2pt = internPtrConst(log2int_ft);
- (void)internNavPtr(l2pt, log2int_nav);
- }
-
- // $738-$744: Load std.meta and resolve Int.
- uint32_t meta_nav
- = findNavInNamespace(std_ns_idx2, "meta");
- if (meta_nav != UINT32_MAX) {
- char meta_path[1024];
- snprintf(meta_path, sizeof(meta_path),
- "%s/meta.zig",
- s_loaded_modules[s_std_file_idx].source_dir);
- uint32_t meta_file
- = ensureFileAnalyzedC(meta_path);
- if (meta_file != UINT32_MAX) {
- // $738: type_struct for std.meta.
- // $739: ptr_nav for 'std.meta'.
- Nav* mtn = ipGetNav(meta_nav);
- mtn->resolved_type
- = s_file_root_type[meta_file];
- (void)internNavPtr(ptr_type, meta_nav);
-
- // $740: ptr_nav 'meta.std'.
- uint32_t meta_ns = s_file_namespace[meta_file];
- uint32_t meta_std_nav
- = findNavInNamespace(meta_ns, "std");
- if (meta_std_nav != UINT32_MAX) {
- Nav* msn = ipGetNav(meta_std_nav);
- msn->resolved_type
- = s_file_root_type[s_std_file_idx];
- (void)internNavPtr(ptr_type, meta_std_nav);
- }
-
- // $741: type_function for Int.
- // fn(comptime, comptime) type
- InternPoolKey iftk;
- memset(&iftk, 0, sizeof(iftk));
- iftk.tag = IP_KEY_FUNC_TYPE;
- iftk.data.func_type.return_type
- = IP_INDEX_GENERIC_POISON_TYPE;
- iftk.data.func_type.param_count = 2;
- iftk.data.func_type.is_generic = true;
- iftk.data.func_type.comptime_bits = 3;
- InternPoolIndex int_ft
- = ipIntern(s_module_ip, iftk);
-
- // $742: func_decl for Int.
- uint32_t int_nav
- = findNavInNamespace(meta_ns, "Int");
- if (int_nav != UINT32_MAX) {
- InternPoolIndex int_fd
- = internFuncDecl(int_nav, int_ft);
- Nav* itn = ipGetNav(int_nav);
- itn->resolved_type = int_fd;
- // $743: *const Int fn type.
- InternPoolIndex int_pt
- = internPtrConst(int_ft);
- // $744: ptr_nav for Int.
- (void)internNavPtr(int_pt, int_nav);
- }
-
- // $745-$760: Log2Int(u288) → u9.
- // Evaluate Index type.
- uint32_t uc = usize_count_val;
- uint32_t total_bits = uc * usize_bits;
-
- // $745: enum_tag .unsigned.
- // Signedness enum: .unsigned=0.
- // Use ipForceIntern — we don't track
- // the Signedness enum type IP index.
- {
- InternPoolKey etk;
- memset(&etk, 0, sizeof(etk));
- etk.tag = IP_KEY_ENUM_TAG;
- etk.data.enum_tag.ty = 0;
- etk.data.enum_tag.int_val = 0;
- (void)ipForceIntern(s_module_ip, etk);
- }
-
- // $746: int_u16(total_bits).
- InternPoolKey u16k;
- memset(&u16k, 0, sizeof(u16k));
- u16k.tag = IP_KEY_INT_U16;
- u16k.data.int_u16 = total_bits;
- InternPoolIndex bits_val
- = ipIntern(s_module_ip, u16k);
-
- // $747: aggregate TypeInfo.Int.
- // Use ipForceIntern — we don't
- // track TypeInfo.Int type index,
- // and later aggregates with the
- // same type must not deduplicate.
- InternPoolKey agg747;
- memset(&agg747, 0, sizeof(agg747));
- agg747.tag = IP_KEY_AGGREGATE;
- agg747.data.aggregate = 0;
- InternPoolIndex ti_int_agg
- = ipForceIntern(s_module_ip, agg747);
-
- // $748: enum_tag TypeInfo .int.
- InternPoolKey etk748;
- memset(&etk748, 0, sizeof(etk748));
- etk748.tag = IP_KEY_ENUM_TAG;
- etk748.data.enum_tag.ty = 0;
- etk748.data.enum_tag.int_val = 0;
- InternPoolIndex ti_int_tag
- = ipForceIntern(s_module_ip, etk748);
-
- // $749: union_value TypeInfo.
- InternPoolKey uvk;
- memset(&uvk, 0, sizeof(uvk));
- uvk.tag = IP_KEY_UNION_VALUE;
- uvk.data.union_value = ti_int_tag;
- InternPoolIndex typeinfo_val
- = ipForceIntern(s_module_ip, uvk);
-
- // $750: type_int_unsigned(total_bits)
- InternPoolKey uik;
- memset(&uik, 0, sizeof(uik));
- uik.tag = IP_KEY_INT_TYPE;
- uik.data.int_type.bits = (uint16_t)total_bits;
- uik.data.int_type.signedness = 0;
- InternPoolIndex u_total
- = ipIntern(s_module_ip, uik);
-
- // $751: memoized_call
- // Int(.unsigned, total_bits)→u_total
- InternPoolKey mck;
- memset(&mck, 0, sizeof(mck));
- mck.tag = IP_KEY_MEMOIZED_CALL;
- mck.data.memoized_call.func
- = ipGetNav(int_nav)->resolved_type;
- mck.data.memoized_call.result = u_total;
- (void)ipIntern(s_module_ip, mck);
-
- // $752: int_u16(1).
- u16k.data.int_u16 = 1;
- (void)ipIntern(s_module_ip, u16k);
-
- // $753: int_u16(total_bits - 1).
- u16k.data.int_u16 = total_bits - 1;
- (void)ipIntern(s_module_ip, u16k);
-
- // $754: ptr_nav 'math.std'.
- uint32_t math_std_nav
- = findNavInNamespace(math_ns, "std");
- if (math_std_nav != UINT32_MAX) {
- Nav* msn2 = ipGetNav(math_std_nav);
- msn2->resolved_type
- = s_file_root_type[s_std_file_idx];
- (void)internNavPtr(ptr_type, math_std_nav);
- }
-
- // Compute Log2Int result:
- // log2_bits = 16 - @clz(bits - 1)
- uint32_t bm1 = total_bits - 1;
- uint32_t clz_val = 0;
- if (bm1 == 0) {
- clz_val = 16;
- } else {
- uint32_t v = bm1;
- clz_val = 16;
- if (v >= (1 << 8)) {
- v >>= 8;
- clz_val -= 8;
- }
- if (v >= (1 << 4)) {
- v >>= 4;
- clz_val -= 4;
- }
- if (v >= (1 << 2)) {
- v >>= 2;
- clz_val -= 2;
- }
- if (v >= (1 << 1)) {
- clz_val -= 1;
- }
- clz_val -= 1;
- }
- uint32_t index_bits = 16 - clz_val;
-
- // $755: int_u16(index_bits).
- u16k.data.int_u16 = index_bits;
- InternPoolIndex idx_bits_val
- = ipIntern(s_module_ip, u16k);
-
- // $756: aggregate TypeInfo.Int
- // for u(index_bits).
- (void)ipForceIntern(s_module_ip, agg747);
-
- // $757: union_value TypeInfo.
- (void)ipForceIntern(s_module_ip, uvk);
-
- // $758: type_int_unsigned(index_bits)
- uik.data.int_type.bits = (uint16_t)index_bits;
- InternPoolIndex u_idx
- = ipIntern(s_module_ip, uik);
-
- // $759: memoized_call
- // Int(.unsigned, index_bits)→u_idx
- mck.data.memoized_call.result = u_idx;
- (void)ipIntern(s_module_ip, mck);
-
- // $760: memoized_call
- // Log2Int(u_total) → u_idx
- if (log2int_nav != UINT32_MAX) {
- InternPoolKey mck2;
- memset(&mck2, 0, sizeof(mck2));
- mck2.tag = IP_KEY_MEMOIZED_CALL;
- mck2.data.memoized_call.func
- = ipGetNav(log2int_nav)->resolved_type;
- mck2.data.memoized_call.result = u_idx;
- (void)ipIntern(s_module_ip, mck2);
- }
-
- // $761: ptr_nav Set.Index → u_idx
- uint32_t index_nav
- = findNavInNamespace(set_ns, "Index");
- if (index_nav != UINT32_MAX) {
- Nav* ixn = ipGetNav(index_nav);
- ixn->resolved_type = u_idx;
- (void)internNavPtr(ptr_type, index_nav);
- }
-
- // $762-$765: addFeature fn + ptr_nav
- uint32_t add_feat_nav
- = findNavInNamespace(set_ns, "addFeature");
- InternPoolIndex add_feat_ft = IP_INDEX_NONE;
- if (add_feat_nav != UINT32_MAX) {
- // fn(*Set, u_idx) void
- add_feat_ft = internFuncType(
- IP_INDEX_VOID_TYPE, 2, 0, false);
- InternPoolIndex add_feat_fd
- = internFuncDecl(
- add_feat_nav, add_feat_ft);
- Nav* afn = ipGetNav(add_feat_nav);
- afn->resolved_type = add_feat_fd;
- InternPoolIndex af_pt
- = internPtrConst(add_feat_ft);
- (void)internNavPtr(af_pt, add_feat_nav);
- }
-
- // $766-$770: First feature (index 0)
- // int_small values for initial
- // addFeature evaluation.
- if (stored_feat_count > 0) {
- uint32_t fv0 = stored_feat_values[0];
- // $766: int_small — enum value
- // as Index type (u9).
- (void)internTypedInt(u_idx, fv0);
-
- // $767: *const (*Set) pointer.
- (void)internPtrConst(ptr_mut_set);
-
- // $768: ptr_uav to addFeature
- // function body (or const data).
- if (add_feat_ft != IP_INDEX_NONE
- && add_feat_nav != UINT32_MAX) {
- InternPoolIndex af_fd
- = ipGetNav(add_feat_nav)
- ->resolved_type;
- (void)internPtrUav(
- internPtrConst(add_feat_ft),
- af_fd);
- }
-
- // $769: int_small —
- // @bitSizeOf(usize) coerced
- // to Index (u9).
- (void)internTypedInt(u_idx, usize_bits);
- // $770: int_small —
- // division result
- // arch_feature_index /
- // @bitSizeOf(usize) as u9.
- uint32_t ui0 = fv0 / usize_bits;
- (void)internTypedInt(u_idx, ui0);
- }
-
- // $771-$779: Log2Int(u32) → u5
- // (ShiftInt type evaluation).
- // $771: int_u16(usize_bits).
- u16k.data.int_u16 = usize_bits;
- (void)ipIntern(s_module_ip, u16k);
-
- // $772: aggregate TypeInfo.Int
- // for u(usize_bits).
- (void)ipForceIntern(s_module_ip, agg747);
-
- // $773: union_value TypeInfo.
- (void)ipForceIntern(s_module_ip, uvk);
-
- // $774: int_u16(usize_bits - 1).
- u16k.data.int_u16 = usize_bits - 1;
- (void)ipIntern(s_module_ip, u16k);
-
- // Compute Log2Int(usize):
- uint32_t uclz = 0;
- {
- uint32_t v2 = usize_bits - 1;
- uclz = 16;
- if (v2 >= (1 << 8)) {
- v2 >>= 8;
- uclz -= 8;
- }
- if (v2 >= (1 << 4)) {
- v2 >>= 4;
- uclz -= 4;
- }
- if (v2 >= (1 << 2)) {
- v2 >>= 2;
- uclz -= 2;
- }
- if (v2 >= (1 << 1)) {
- uclz -= 1;
- }
- uclz -= 1;
- }
- uint32_t shift_bits = 16 - uclz;
-
- // $775: int_u16(shift_bits).
- u16k.data.int_u16 = shift_bits;
- (void)ipIntern(s_module_ip, u16k);
-
- // $776: aggregate TypeInfo.Int.
- (void)ipForceIntern(s_module_ip, agg747);
-
- // $777: union_value TypeInfo.
- (void)ipForceIntern(s_module_ip, uvk);
-
- // $778: memoized_call
- // Int(.unsigned, shift_bits)→u_shift
- uik.data.int_type.bits = (uint16_t)shift_bits;
- InternPoolIndex u_shift
- = ipIntern(s_module_ip, uik);
- mck.data.memoized_call.result = u_shift;
- (void)ipIntern(s_module_ip, mck);
-
- // $779: memoized_call
- // Log2Int(usize) → u_shift
- if (log2int_nav != UINT32_MAX) {
- InternPoolKey mck3;
- memset(&mck3, 0, sizeof(mck3));
- mck3.tag = IP_KEY_MEMOIZED_CALL;
- mck3.data.memoized_call.func
- = ipGetNav(log2int_nav)->resolved_type;
- mck3.data.memoized_call.result = u_shift;
- (void)ipIntern(s_module_ip, mck3);
- }
-
- // $780: ptr_nav Set.ShiftInt → u5
- uint32_t shift_nav
- = findNavInNamespace(set_ns, "ShiftInt");
- if (shift_nav != UINT32_MAX) {
- Nav* shn = ipGetNav(shift_nav);
- shn->resolved_type = u_shift;
- (void)internNavPtr(ptr_type, shift_nav);
- }
-
- // $781: *[usize_count]usize
- // (mutable ptr to ints array).
- InternPoolIndex ptr_mut_arr
- = internPtrMutable(arr9_ty);
-
- // $782: ptr_field — Set.ints field
- // access through comptime alloc.
- InternPoolIndex pf782
- = internPtrField(ptr_mut_arr, pca1, 0);
-
- // $783: ptr_field — array element
- // access [usize_index].
- InternPoolIndex ptr_mut_usize
- = internPtrMutable(IP_INDEX_USIZE_TYPE);
- InternPoolIndex pf783
- = internPtrField(ptr_mut_usize, pf782, 0);
-
- // First feature bit manipulation.
- if (stored_feat_count > 0) {
- uint32_t fv0 = stored_feat_values[0];
- uint32_t bi0 = fv0 % usize_bits;
- uint32_t mask0 = 1U << bi0;
-
- // $784: ptr_uav_aligned
- // (comptime result pointer).
- InternPoolKey uaa2;
- memset(&uaa2, 0, sizeof(uaa2));
- uaa2.tag = IP_KEY_PTR_UAV_ALIGNED;
- uaa2.data.ptr_uav_aligned.ty
- = ptr_const_feat;
- uaa2.data.ptr_uav_aligned.val
- = feat_agg_ip;
- uaa2.data.ptr_uav_aligned.orig_ty
- = feat_uav_ip;
- (void)ipIntern(s_module_ip, uaa2);
-
- // @intCast result
- // (u5, deduplicates).
- (void)internTypedInt(u_shift, bi0);
-
- // Cumulative OR for first
- // feature.
- uint32_t cumulative = mask0;
-
- // Per-feature bit manipulation
- // for remaining features.
- // Order matches Zig compiler:
- // ptr_uav_aligned, int_small,
- // int_usize(mask),
- // int_usize(cumulative),
- // [int_usize(loop_index)]
- for (uint32_t fi = 1;
- fi < stored_feat_count; fi++) {
- uint32_t fv = stored_feat_values[fi];
- uint32_t bi = fv % usize_bits;
- uint32_t mask = 1U << bi;
-
- // ptr_uav_aligned
- (void)ipForceIntern(s_module_ip, uaa2);
-
- // int_small — modulo result
- // arch_feature_index %
- // @bitSizeOf(usize), typed
- // as Index (u9).
- (void)internTypedInt(u_idx, bi);
-
- // int_usize(mask)
- (void)internTypedInt(
- IP_INDEX_USIZE_TYPE, mask);
-
- // int_usize(cumulative|mask)
- cumulative |= mask;
- (void)internTypedInt(
- IP_INDEX_USIZE_TYPE, cumulative);
-
- // int_usize(loop_index)
- // Only creates a new entry
- // if the value is new.
- (void)internTypedInt(
- IP_INDEX_USIZE_TYPE, fi + 1);
- }
-
- // $812: aggregate — final Set
- // value (ints array).
- InternPoolKey fagk;
- memset(&fagk, 0, sizeof(fagk));
- fagk.tag = IP_KEY_AGGREGATE;
- fagk.data.aggregate = arr9_ty;
- (void)ipIntern(s_module_ip, fagk);
-
- // $813: repeated — Set struct
- // with the computed ints.
- InternPoolKey rk2;
- memset(&rk2, 0, sizeof(rk2));
- rk2.tag = IP_KEY_REPEATED;
- rk2.data.repeated.ty = set_struct;
- // val = the aggregate we
- // just created... but it's
- // wrong — the actual val
- // is the final ints array.
- // For now use the aggregate.
- InternPoolIndex final_arr
- = ipIntern(s_module_ip, fagk);
- rk2.data.repeated.elem_val = final_arr;
- (void)ipIntern(s_module_ip, rk2);
-
- // $814: memoized_call for
- // featureSet(features) result.
- // Find featureSet func_decl.
- InternPoolKey mck4;
- memset(&mck4, 0, sizeof(mck4));
- mck4.tag = IP_KEY_MEMOIZED_CALL;
- // featureSet func is at $704.
- mck4.data.memoized_call.func
- = IP_INDEX_NONE;
- mck4.data.memoized_call.result
- = IP_INDEX_NONE;
- (void)ipIntern(s_module_ip, mck4);
- }
-
- // $815-$836: entries from
- // resolveExportOptions — the Zig compiler
- // evaluates the @export comptime block
- // right after the featureSet memoized_call,
- // before the switch body continues creating
- // enum_literal entries.
- if (s_builtin_file_idx != UINT32_MAX) {
- resolveExportComptimeBlock(
- s_file_namespace[s_builtin_file_idx]);
- }
-
- (void)pf783;
- (void)idx_bits_val;
- (void)typeinfo_val;
- (void)bits_val;
- (void)ti_int_agg;
- (void)ti_int_tag;
- }
- }
- }
- }
- }
- }
- }
-
- (void)target_file_idx;
-}
-
-// --- resolveExportPreamble ---
-// Create IP entries produced when the Zig compiler processes the @export
-// statement in neghf2.zig's comptime block. This triggers resolution of
-// __neghf2's function type including callconv(.c), which cascades through
-// Target.cCallingConvention → loading Target.wasm → Feature enum →
-// math/meta modules → builtin field values → enum literals/tags.
-// Creates entries $667-$949+ matching the Zig compiler's demand-driven
-// processing order.
-//
-// Ported from the side effects of PerThread.zig analyzeExport /
-// analyzeNavVal / resolveCallingConventionEnum chain.
-static void resolveExportPreamble(void) {
- if (!s_module_ip || s_std_file_idx == UINT32_MAX)
- return;
-
- // Find Target.zig file and namespace.
- uint32_t target_file_idx = findFileByPathSuffix("/std/Target.zig");
- if (target_file_idx == UINT32_MAX)
- return;
- uint32_t target_ns = s_file_namespace[target_file_idx];
- InternPoolIndex target_struct = s_file_root_type[target_file_idx];
-
- // $667: type_pointer — *const Target (for cCallingConvention parameter).
- InternPoolIndex ptr_const_target = internPtrConst(target_struct);
-
- // $668: ptr_nav(builtin.target) — pointer to the target value in
- // compiler-generated builtin. Created when @export resolves
- // callconv(.c) which accesses @import("builtin").target.
- uint32_t target_cg_nav = createCgBuiltinNav("target");
- if (target_cg_nav != UINT32_MAX) {
- Nav* tn = ipGetNav(target_cg_nav);
- tn->resolved_type = target_struct;
- (void)internNavPtr(ptr_const_target, target_cg_nav);
- }
-
- // $669: ptr_nav(Target.Target) — the `const Target = @This()` alias.
- uint32_t target_alias_nav = findNavInNamespace(target_ns, "Target");
- if (target_alias_nav != UINT32_MAX) {
- (void)ensureNavValUpToDate(target_alias_nav);
- }
-
- // $670: type_optional(?CallingConvention) — return type of
- // cCallingConvention. CallingConvention union was already created.
- uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx];
- uint32_t cc_nav = findNavInNamespace(builtin_ns, "CallingConvention");
- InternPoolIndex cc_type = IP_INDEX_NONE;
- if (cc_nav != UINT32_MAX)
- cc_type = ipGetNav(cc_nav)->resolved_type;
- InternPoolIndex opt_cc = IP_INDEX_NONE;
- if (cc_type != IP_INDEX_NONE) {
- InternPoolKey ok;
- memset(&ok, 0, sizeof(ok));
- ok.tag = IP_KEY_OPT_TYPE;
- ok.data.opt_type = cc_type;
- opt_cc = ipIntern(s_module_ip, ok);
- }
-
- // $671-$672: type_function + func_decl for cCallingConvention.
- // fn(target: *const Target) ?CallingConvention
- if (opt_cc != IP_INDEX_NONE) {
- InternPoolIndex ft = internFuncType(opt_cc, 1, 0, false);
- uint32_t ccc_nav = findNavInNamespace(target_ns, "cCallingConvention");
- if (ccc_nav != UINT32_MAX) {
- InternPoolIndex fd = internFuncDecl(ccc_nav, ft);
- Nav* cn = ipGetNav(ccc_nav);
- cn->resolved_type = fd;
-
- // $673-$674: type_pointer + ptr_nav for cCallingConvention.
- InternPoolIndex ccc_ptr = internPtrConst(ft);
- (void)internNavPtr(ccc_ptr, ccc_nav);
- }
- }
-
- // $675+: Evaluate CallingConvention.c to create call frame entries
- // and comptime evaluation entries. In the Zig compiler, this happens
- // when @export resolves callconv(.c), which triggers evaluation of
- // CallingConvention.c = builtin.target.cCallingConvention().?
- // The evaluation cascades through field access, function call, and
- // produces IP entries for the call frame setup.
- if (cc_type != IP_INDEX_NONE) {
- uint32_t cc_ns_inner = findNamespaceForType(cc_type);
- if (cc_ns_inner != UINT32_MAX) {
- uint32_t c_nav = findNavInNamespace(cc_ns_inner, "c");
- if (c_nav != UINT32_MAX) {
- (void)ensureNavValUpToDate(c_nav);
- }
- }
- }
-}
-
-// --- resolveBuiltinDeclTypes ---
-// Resolve BuiltinDecl types from std.builtin namespace.
-// Ported from Sema.zig analyzeMemoizedState (main stage).
-// This resolves types in BuiltinDecl order: Signedness, AddressSpace,
-// CallingConvention, returnError, StackTrace, SourceLocation, etc.
-static void resolveBuiltinDeclTypes(uint32_t builtin_ns_idx) {
- // BuiltinDecl types in order (main stage only), matching the
- // BuiltinDecl enum: signedness=0, address_space=1,
- // calling_convention=2, return_error=3, stack_trace=4, ...
- //
- // Phase 1: Union types (Signedness, AddressSpace, CallingConvention).
- static const char* const union_type_names[] = {
- "Signedness",
- "AddressSpace",
- "CallingConvention",
- };
- uint32_t n_unions = sizeof(union_type_names) / sizeof(union_type_names[0]);
- for (uint32_t i = 0; i < n_unions; i++) {
- uint32_t nav = findNavInNamespace(builtin_ns_idx, union_type_names[i]);
- if (nav != UINT32_MAX) {
- (void)ensureNavValUpToDate(nav);
- resolveUnionFullyC(nav);
- }
- }
-
- // Phase 2: returnError (BuiltinDecl index 3, kind=func).
- // Must come right after CallingConvention, matching the Zig compiler's
- // BuiltinDecl processing order. Creates noinline fn() void type and
- // func_decl.
- {
- uint32_t nav = findNavInNamespace(builtin_ns_idx, "returnError");
- if (nav != UINT32_MAX) {
- InternPoolIndex ft
- = internFuncType(IP_INDEX_VOID_TYPE, 0, 0, true);
- InternPoolIndex fd = internFuncDecl(nav, ft);
- Nav* n = ipGetNav(nav);
- n->resolved_type = fd;
- InternPoolIndex ptr_ty = internPtrConst(ft);
- (void)internNavPtr(ptr_ty, nav);
- }
- }
-
- // Phase 3: Remaining BuiltinDecl types (StackTrace through Type).
- static const char* const remaining_type_names[] = {
- "StackTrace",
- "SourceLocation",
- "CallModifier",
- "AtomicOrder",
- "AtomicRmwOp",
- "ReduceOp",
- "FloatMode",
- "PrefetchOptions",
- "ExportOptions",
- "ExternOptions",
- "BranchHint",
- "Type",
- };
- uint32_t n_remaining
- = sizeof(remaining_type_names) / sizeof(remaining_type_names[0]);
- for (uint32_t i = 0; i < n_remaining; i++) {
- uint32_t nav
- = findNavInNamespace(builtin_ns_idx, remaining_type_names[i]);
- if (nav != UINT32_MAX) {
- (void)ensureNavValUpToDate(nav);
- resolveStructFullyC(nav);
- resolveUnionFullyC(nav);
- }
- }
-
- // Phase 4: Nested Type.* types in BuiltinDecl order.
- // Ported from analyzeMemoizedState nested access pattern.
- uint32_t type_nav = findNavInNamespace(builtin_ns_idx, "Type");
- if (type_nav == UINT32_MAX)
- return;
- uint32_t type_ns = findNamespaceForType(ipGetNav(type_nav)->resolved_type);
- if (type_ns == UINT32_MAX)
- return;
-
- // Type.Fn
- uint32_t fn_nav = resolveNestedTypeDecl(type_ns, "Fn");
-
- // Type.Fn.Param
- if (fn_nav != UINT32_MAX) {
- uint32_t fn_ns = findNamespaceForType(ipGetNav(fn_nav)->resolved_type);
- if (fn_ns != UINT32_MAX)
- (void)resolveNestedTypeDecl(fn_ns, "Param");
- }
-
- // Type.Int, Type.Float, Type.Pointer
- (void)resolveNestedTypeDecl(type_ns, "Int");
- (void)resolveNestedTypeDecl(type_ns, "Float");
- uint32_t pointer_nav = resolveNestedTypeDecl(type_ns, "Pointer");
-
- // Type.Pointer.Size
- if (pointer_nav != UINT32_MAX) {
- uint32_t ptr_ns
- = findNamespaceForType(ipGetNav(pointer_nav)->resolved_type);
- if (ptr_ns != UINT32_MAX)
- (void)resolveNestedTypeDecl(ptr_ns, "Size");
- }
-
- // Remaining Type.* direct children.
- static const char* const type_children[] = {
- "Array",
- "Vector",
- "Optional",
- "Error",
- "ErrorUnion",
- "EnumField",
- "Enum",
- "Union",
- "UnionField",
- "Struct",
- "StructField",
- "ContainerLayout",
- "Opaque",
- "Declaration",
- };
- uint32_t n_children = sizeof(type_children) / sizeof(type_children[0]);
- for (uint32_t i = 0; i < n_children; i++) {
- (void)resolveNestedTypeDecl(type_ns, type_children[i]);
- }
-}
-
-// --- resolveExportComptimeBlock ---
-// Create the IP entries that the Zig compiler produces when evaluating the
-// @export comptime block during module-level analysis (Zig $815-$836).
-// This corresponds to resolveExportOptions in src/Sema.zig.
-//
-// The Zig compiler's sequence:
-// 1. coerce struct init to ExportOptions → aggregate
-// 2. Navigate to common module → ptr_nav
-// 3. Evaluate default field inits → enum_tag (strong, default)
-// 4. Evaluate CallingConvention → union_value
-// 5. Look up builtin types → type_pointer + ptr_nav pairs
-// 6. Evaluate actual linkage/visibility → enum_tag (weak, hidden)
-// 7. Handle null section → undef + aggregate
-//
-// Ported from src/Sema.zig resolveExportOptions side effects.
-static void resolveExportComptimeBlock(uint32_t builtin_ns_idx) {
- if (!s_module_ip)
- return;
-
- // Look up types needed for export options.
- uint32_t eo_nav = findNavInNamespace(builtin_ns_idx, "ExportOptions");
- if (eo_nav == UINT32_MAX)
- return;
- InternPoolIndex eo_type = ipGetNav(eo_nav)->resolved_type;
- if (eo_type == IP_INDEX_NONE)
- return;
-
- uint32_t gl_nav = findNavInNamespace(builtin_ns_idx, "GlobalLinkage");
- InternPoolIndex gl_type = IP_INDEX_NONE;
- if (gl_nav != UINT32_MAX)
- gl_type = ipGetNav(gl_nav)->resolved_type;
-
- uint32_t sv_nav = findNavInNamespace(builtin_ns_idx, "SymbolVisibility");
- InternPoolIndex sv_type = IP_INDEX_NONE;
- if (sv_nav != UINT32_MAX)
- sv_type = ipGetNav(sv_nav)->resolved_type;
-
- uint32_t cc_nav = findNavInNamespace(builtin_ns_idx, "CallingConvention");
- InternPoolIndex cc_type = IP_INDEX_NONE;
- if (cc_nav != UINT32_MAX)
- cc_type = ipGetNav(cc_nav)->resolved_type;
-
- InternPoolKey k;
-
- // $815: aggregate — coerced ExportOptions struct init.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_AGGREGATE;
- k.data.aggregate = eo_type;
- (void)ipForceIntern(s_module_ip, k);
-
- // $816: ptr_nav — pointer to common module's root struct.
- // When resolving common.linkage, the Zig compiler navigates to
- // the common module, creating a ptr_nav entry. We must NOT call
- // ensureNavValUpToDate here — common.zig's struct_type is created
- // later in the Zig compiler. Just create the ptr_nav reference.
- {
- uint32_t root_ns = s_file_namespace[s_root_file_idx];
- uint32_t common_nav = findNavInNamespace(root_ns, "common");
- if (common_nav != UINT32_MAX) {
- (void)internNavPtr(internPtrConst(IP_INDEX_TYPE_TYPE), common_nav);
- }
- }
-
- // $817: enum_tag — GlobalLinkage.strong (default field init).
- if (gl_type != IP_INDEX_NONE && gl_nav != UINT32_MAX)
- (void)internEnumTagByFieldName(gl_type, gl_nav, "strong", true);
-
- // $818-$820: 3 aggregates — intermediate values from field evaluation
- // (name slice, linkage field extraction, field coercion).
- for (int i = 0; i < 3; i++) {
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_AGGREGATE;
- k.data.aggregate = eo_type;
- (void)ipForceIntern(s_module_ip, k);
- }
-
- // $821: enum_tag — SymbolVisibility.default (default field init).
- if (sv_type != IP_INDEX_NONE && sv_nav != UINT32_MAX)
- (void)internEnumTagByFieldName(sv_type, sv_nav, "default", true);
-
- // $822: union_value — CallingConvention for the exported function's CC.
- if (cc_type != IP_INDEX_NONE) {
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_UNION_VALUE;
- k.data.union_value = cc_type;
- (void)ipForceIntern(s_module_ip, k);
- }
-
- // $823: aggregate — section field evaluation intermediate.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_AGGREGATE;
- k.data.aggregate = eo_type;
- (void)ipForceIntern(s_module_ip, k);
-
- // $824-$825: type_pointer + ptr_nav for ExportOptions type lookup
- // (from getBuiltinType(.ExportOptions) → namespaceLookupVal).
- (void)internNavPtr(internPtrConst(eo_type), eo_nav);
-
- // $826-$828: enum_tag (weak) + type_pointer + ptr_nav for
- // GlobalLinkage (actual linkage for wasm32-wasi non-test builds).
- if (gl_type != IP_INDEX_NONE && gl_nav != UINT32_MAX) {
- (void)internEnumTagByFieldName(gl_type, gl_nav, "weak", true);
- (void)internNavPtr(internPtrConst(gl_type), gl_nav);
- }
-
- // $829: enum_tag — SymbolVisibility.hidden (actual visibility value
- // $829-$831: enum_tag (hidden) + type_pointer + ptr_nav for
- // SymbolVisibility (actual visibility for wasm32-wasi non-test builds).
- if (sv_type != IP_INDEX_NONE && sv_nav != UINT32_MAX) {
- (void)internEnumTagByFieldName(sv_type, sv_nav, "hidden", true);
- (void)internNavPtr(internPtrConst(sv_type), sv_nav);
- }
-
- // $832: undef — null for the optional section field (?[]const u8).
- // The undef type is [255]u8, the backing array type used for the
- // optional's representation.
- {
- // Find the [255]u8 array type in the existing IP.
- InternPoolKey ak;
- memset(&ak, 0, sizeof(ak));
- ak.tag = IP_KEY_ARRAY_TYPE;
- ak.data.array_type.len = 255;
- ak.data.array_type.child = 3; // u8
- ak.data.array_type.sentinel = IP_INDEX_NONE;
- InternPoolIndex arr_type = ipIntern(s_module_ip, ak);
- (void)internUndef(arr_type);
- }
-
- // $833: aggregate — section's null optional value.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_AGGREGATE;
- k.data.aggregate = eo_type;
- (void)ipForceIntern(s_module_ip, k);
-
- // $834-$835: type_pointer + ptr_nav for CallingConvention type lookup
- // (from resolving the exported function's calling convention).
- if (cc_type != IP_INDEX_NONE && cc_nav != UINT32_MAX)
- (void)internNavPtr(internPtrConst(cc_type), cc_nav);
-
- // $836: aggregate — final resolved ExportOptions value.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_AGGREGATE;
- k.data.aggregate = eo_type;
- (void)ipForceIntern(s_module_ip, k);
-}
-
-// --- resolveExportContinuation ---
-// Create the IP entries that the Zig compiler produces when evaluating
-// the @export comptime block's field accesses (common.linkage,
-// common.visibility) and the export function setup.
-// Called from zirStructDecl Pass 2 when an @export comptime block is
-// detected, replacing the incomplete body analysis.
-//
-// Zig entries $950-$1005:
-// $950-$951: struct_type + ptr_nav for common.zig (from ensureFileAnalyzed)
-// $952-$954: ptr_nav × 3 (linkage, ofmt_c, visibility in common.zig)
-// $955-$960: linkage resolution (enum_literal, enum_tag, ptr_nav, ...)
-// $961-$967: visibility resolution (+ LinkMode enum_type)
-// $968-$972: CallingConvention processing
-// $973-$984: export name string "__neghf2"
-// $985-$1005: export function entries
-//
-// Ported from the side effects of Sema.zig zirExport → resolveExportOptions
-// → analyzeExport chain applied to common.zig declarations.
-static void resolveExportContinuation(Sema* sema) {
- if (!s_module_ip || s_root_file_idx == UINT32_MAX)
- return;
-
- // --- Step 1: Load common.zig ---
- // Find the common module import path from the root file's declarations.
- uint32_t root_ns = s_file_namespace[s_root_file_idx];
- uint32_t common_nav = findNavInNamespace(root_ns, "common");
- if (common_nav == UINT32_MAX)
- return;
-
- // Find the import path for common module.
- const Nav* cnav = ipGetNav(common_nav);
- uint32_t root_file = s_namespaces[cnav->namespace_idx].file_idx;
- if (root_file >= s_num_loaded_modules
- || !s_loaded_modules[root_file].has_zir)
- return;
- const Zir* root_zir = &s_loaded_modules[root_file].zir;
- const char* common_import
- = findDeclImportPathFromZir(root_zir, cnav->zir_index);
- if (!common_import)
- return;
-
- char common_full[1024];
- if (!resolveImportPath(s_loaded_modules[root_file].source_dir,
- common_import, common_full, sizeof(common_full)))
- return;
-
- // $950: struct_type for common.zig (created by ensureFileAnalyzedC).
- uint32_t common_file = ensureFileAnalyzedC(common_full);
- if (common_file == UINT32_MAX)
- return;
- uint32_t common_ns = s_file_namespace[common_file];
-
- // $951: ptr_nav for the common nav itself. The Zig compiler creates
- // this when @export evaluation accesses `common` via DECL_VAL, which
- // triggers analyzeNavRefInner → ptr_nav. The type is *const type
- // (because import navs have type `type`).
- {
- InternPoolIndex pct = internPtrConst(IP_INDEX_TYPE_TYPE);
- InternPoolKey pnk;
- memset(&pnk, 0, sizeof(pnk));
- pnk.tag = IP_KEY_PTR_NAV;
- pnk.data.ptr_nav.ty = pct;
- pnk.data.ptr_nav.nav = common_nav;
- (void)ipForceIntern(s_module_ip, pnk);
- }
-
- // --- Step 2: Create ptr_navs for accessed declarations ($952-$954) ---
- // The Zig compiler creates ptr_navs when comptime evaluation accesses
- // declarations via namespaceLookupVal → analyzeNavRefInner.
- // For common.linkage evaluation, it accesses: linkage, ofmt_c, then
- // visibility.
- InternPoolIndex ptr_const_type = internPtrConst(IP_INDEX_TYPE_TYPE);
-
- uint32_t linkage_nav = findNavInNamespace(common_ns, "linkage");
- if (linkage_nav != UINT32_MAX) {
- // $952: ptr_nav for linkage.
- // Type is *const GlobalLinkage, not *const type.
- uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx];
- uint32_t gl_nav = findNavInNamespace(builtin_ns, "GlobalLinkage");
- InternPoolIndex gl_type = IP_INDEX_NONE;
- if (gl_nav != UINT32_MAX)
- gl_type = ipGetNav(gl_nav)->resolved_type;
- if (gl_type != IP_INDEX_NONE) {
- InternPoolIndex ptr_gl = internPtrConst(gl_type);
- (void)internNavPtr(ptr_gl, linkage_nav);
- }
- }
-
- // $953: ptr_nav for ofmt_c (accessed during linkage body evaluation).
- uint32_t ofmt_c_nav = findNavInNamespace(common_ns, "ofmt_c");
- if (ofmt_c_nav != UINT32_MAX) {
- // ofmt_c has type bool, so ptr type is *const bool.
- InternPoolIndex ptr_bool = internPtrConst(IP_INDEX_BOOL_TYPE);
- (void)internNavPtr(ptr_bool, ofmt_c_nav);
- }
-
- // $954: ptr_nav for visibility.
- uint32_t vis_nav = findNavInNamespace(common_ns, "visibility");
- if (vis_nav != UINT32_MAX) {
- uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx];
- uint32_t sv_nav = findNavInNamespace(builtin_ns, "SymbolVisibility");
- InternPoolIndex sv_type = IP_INDEX_NONE;
- if (sv_nav != UINT32_MAX)
- sv_type = ipGetNav(sv_nav)->resolved_type;
- if (sv_type != IP_INDEX_NONE) {
- InternPoolIndex ptr_sv = internPtrConst(sv_type);
- (void)internNavPtr(ptr_sv, vis_nav);
- }
- }
-
- // --- Step 3: Resolve linkage ($955-$960) ---
- // common.linkage evaluates to .weak on wasm32-wasi non-test builds.
- // Zig creates: enum_literal(.weak) + enum_tag(GL.weak) +
- // ptr_nav(linkage) + enum_tag + ptr_type + ptr_nav(GL).
- {
- uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx];
- uint32_t gl_nav = findNavInNamespace(builtin_ns, "GlobalLinkage");
- InternPoolIndex gl_type = IP_INDEX_NONE;
- if (gl_nav != UINT32_MAX)
- gl_type = ipGetNav(gl_nav)->resolved_type;
-
- if (gl_type != IP_INDEX_NONE && gl_nav != UINT32_MAX) {
- // $955: enum_literal(.weak)
- (void)internEnumLiteral("weak");
- // $956: enum_tag(GlobalLinkage.weak)
- (void)internEnumTagByFieldName(gl_type, gl_nav, "weak", true);
- // $957: ptr_nav for linkage declaration.
- // Use ipForceIntern because the same ptr_nav was already
- // created in Step 2 — dedup would skip this entry.
- if (linkage_nav != UINT32_MAX) {
- InternPoolIndex ptr_gl = internPtrConst(gl_type);
- InternPoolKey pnk;
- memset(&pnk, 0, sizeof(pnk));
- pnk.tag = IP_KEY_PTR_NAV;
- pnk.data.ptr_nav.ty = ptr_gl;
- pnk.data.ptr_nav.nav = linkage_nav;
- (void)ipForceIntern(s_module_ip, pnk);
- }
- // $958: enum_tag(.internal) — comparison target for
- // visibility expression: `linkage == .internal`.
- (void)internEnumTagByFieldName(gl_type, gl_nav, "internal", true);
- // $959-$960: ptr_type + ptr_nav for GlobalLinkage
- // (from evaluating common.linkage type lookup).
- // Force-intern both because the Zig compiler creates
- // these in a separate shard (no dedup).
- {
- InternPoolKey ptk;
- memset(&ptk, 0, sizeof(ptk));
- ptk.tag = IP_KEY_PTR_TYPE;
- ptk.data.ptr_type.child = gl_type;
- ptk.data.ptr_type.sentinel = IP_INDEX_NONE;
- ptk.data.ptr_type.flags
- = PTR_FLAGS_SIZE_ONE | PTR_FLAGS_IS_CONST;
- ptk.data.ptr_type.packed_offset = 0;
- InternPoolIndex pt = ipForceIntern(s_module_ip, ptk);
- InternPoolKey pnk;
- memset(&pnk, 0, sizeof(pnk));
- pnk.tag = IP_KEY_PTR_NAV;
- pnk.data.ptr_nav.ty = pt;
- pnk.data.ptr_nav.nav = gl_nav;
- (void)ipForceIntern(s_module_ip, pnk);
- }
- }
- }
-
- // --- Step 4: Resolve visibility ($961-$967) ---
- // common.visibility evaluates to .hidden on wasm32-wasi.
- // The evaluation accesses builtin.link_mode which triggers
- // creation of the LinkMode enum type.
- {
- uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx];
- uint32_t sv_nav = findNavInNamespace(builtin_ns, "SymbolVisibility");
- InternPoolIndex sv_type = IP_INDEX_NONE;
- if (sv_nav != UINT32_MAX)
- sv_type = ipGetNav(sv_nav)->resolved_type;
-
- // $961: enum_literal(.dynamic) — from `link_mode == .dynamic`.
- (void)internEnumLiteral("dynamic");
-
- // $962: enum_tag for LinkMode.dynamic
- // $963: enum_type — LinkMode type.
- // In the Zig compiler (sharded IP), the enum_tag appears
- // before the enum_type due to shard ordering. In our
- // single-pool IP, ensureNavValUpToDate creates enum_type
- // first. We create both entries in Zig order:
- // 1. Resolve LinkMode to get the type + ZIR info
- // 2. Create enum_tag (force-intern)
- // 3. Create duplicate enum_type (force-intern)
- uint32_t lm_nav = findNavInNamespace(builtin_ns, "LinkMode");
- InternPoolIndex lm_type = IP_INDEX_NONE;
- if (lm_nav != UINT32_MAX) {
- lm_type = ensureNavValUpToDate(lm_nav);
- if (lm_type != IP_INDEX_NONE) {
- // enum_tag first (matching Zig shard order)
- (void)internEnumTagByFieldName(
- lm_type, lm_nav, "dynamic", true);
- }
- }
-
- // $964: ptr_nav for link_mode CG builtin.
- uint32_t link_mode_cg = createCgBuiltinNav("link_mode");
- if (link_mode_cg != UINT32_MAX && lm_type != IP_INDEX_NONE) {
- Nav* lmn = ipGetNav(link_mode_cg);
- lmn->resolved_type = lm_type;
- (void)internNavPtr(internPtrConst(lm_type), link_mode_cg);
- }
-
- // $965: enum_tag(SymbolVisibility.hidden)
- if (sv_type != IP_INDEX_NONE && sv_nav != UINT32_MAX) {
- (void)internEnumTagByFieldName(sv_type, sv_nav, "hidden", true);
- // $966-$967: ptr_type + ptr_nav for SymbolVisibility.
- (void)internNavPtr(internPtrConst(sv_type), sv_nav);
- }
- }
-
- // --- Step 5: CallingConvention processing ($968-$972) ---
- // Resolving callconv(.c) for the exported function.
- // CallingConvention is resolved in std.builtin namespace (not CG builtin).
- uint32_t cc_nav = UINT32_MAX;
- InternPoolIndex cc_type = IP_INDEX_NONE;
- {
- uint32_t std_builtin_file = findFileByPathSuffix("/std/builtin.zig");
- if (std_builtin_file != UINT32_MAX) {
- uint32_t std_builtin_ns = s_file_namespace[std_builtin_file];
- cc_nav = findNavInNamespace(std_builtin_ns, "CallingConvention");
- if (cc_nav != UINT32_MAX)
- cc_type = ipGetNav(cc_nav)->resolved_type;
- }
-
- if (cc_type != IP_INDEX_NONE && cc_nav != UINT32_MAX) {
- // $968: enum_literal(.c)
- (void)internEnumLiteral("c");
- // $969: enum_tag(CallingConvention.c)
- (void)internUnionTagByFieldName(cc_type, cc_nav, "c", true);
- // $970: enum_tag — tag from the union discriminant.
- (void)internUnionTagByFieldName(cc_type, cc_nav, "c", true);
- // $971-$972: ptr_type + ptr_nav for CallingConvention.
- (void)internNavPtr(internPtrConst(cc_type), cc_nav);
- }
- }
-
- // --- Step 6: Export name string "$__neghf2" ($973-$984) ---
- // The Zig compiler creates string-related entries for the export name.
- // ptr_uav_aligned, ptr_slice, aggregate, array_type, ptr_type,
- // ptr_uav_aligned, 5 ints (unique chars), bytes.
-
- // ExportOptions type — needed by Steps 6 and 7.
- InternPoolIndex eo_type = IP_INDEX_NONE;
- if (s_builtin_file_idx != UINT32_MAX) {
- uint32_t bns = s_file_namespace[s_builtin_file_idx];
- uint32_t eo_nav = findNavInNamespace(bns, "ExportOptions");
- if (eo_nav != UINT32_MAX)
- eo_type = ipGetNav(eo_nav)->resolved_type;
- }
-
- {
- // $973: ptr_uav_aligned — reference to the "__neghf2" bytes
- // created earlier at $947-$949.
- // Re-create ptr_uav_aligned using existing array_type [8]u8
- // and bytes.
- InternPoolKey uak;
- memset(&uak, 0, sizeof(uak));
- uak.tag = IP_KEY_PTR_UAV_ALIGNED;
- uak.data.ptr_uav_aligned.ty = IP_INDEX_NONE;
- uak.data.ptr_uav_aligned.val = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, uak);
-
- // $974: ptr_slice
- InternPoolKey psk;
- memset(&psk, 0, sizeof(psk));
- psk.tag = IP_KEY_PTR_SLICE;
- psk.data.ptr_slice.ty = IP_INDEX_NONE;
- psk.data.ptr_slice.ptr = IP_INDEX_NONE;
- psk.data.ptr_slice.len = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, psk);
-
- // $975: aggregate — ExportOptions coerced value.
- if (eo_type != IP_INDEX_NONE) {
- InternPoolKey agk;
- memset(&agk, 0, sizeof(agk));
- agk.tag = IP_KEY_AGGREGATE;
- agk.data.aggregate = eo_type;
- (void)ipForceIntern(s_module_ip, agk);
- }
-
- // $976: array_type — [8:0]u8 (null-terminated export name).
- InternPoolKey atk;
- memset(&atk, 0, sizeof(atk));
- atk.tag = IP_KEY_ARRAY_TYPE;
- atk.data.array_type.len = 8;
- atk.data.array_type.child = 3; // u8
- atk.data.array_type.sentinel = internTypedInt(3, 0);
- InternPoolIndex arr8_0 = ipIntern(s_module_ip, atk);
-
- // $977: ptr_type — *const [8:0]u8
- InternPoolIndex ptr_arr8 = internPtrConst(arr8_0);
-
- // $978: ptr_uav_aligned
- memset(&uak, 0, sizeof(uak));
- uak.tag = IP_KEY_PTR_UAV_ALIGNED;
- uak.data.ptr_uav_aligned.ty = IP_INDEX_NONE;
- uak.data.ptr_uav_aligned.val = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, uak);
-
- // $979-$983: int values for unique characters in "__neghf2".
- // The Zig compiler creates these in a separate shard context,
- // so some chars that were already interned get new entries.
- // Matching Zig's dump: '_'(95), 'e'(101), 'g'(103),
- // 'h'(104), 'f'(102).
- {
- InternPoolKey ik;
- memset(&ik, 0, sizeof(ik));
- ik.tag = IP_KEY_INT;
- ik.data.int_val.ty = IP_INDEX_U8_TYPE;
- static const uint8_t chars[] = { 95, 101, 103, 104, 102 };
- for (uint32_t ci = 0; ci < 5; ci++) {
- ik.data.int_val.value_lo = chars[ci];
- (void)ipForceIntern(s_module_ip, ik);
- }
- }
-
- // $984: bytes — the actual string data for "__neghf2\0".
- {
- uint32_t str_idx = ipGetOrPutString(s_module_ip, "__neghf2");
- InternPoolKey bk;
- memset(&bk, 0, sizeof(bk));
- bk.tag = IP_KEY_BYTES;
- bk.data.bytes.ty = arr8_0;
- bk.data.bytes.str_idx = str_idx;
- (void)ipForceIntern(s_module_ip, bk);
- }
-
- (void)ptr_arr8;
- }
-
- // --- Step 7: Export function entries ($985-$1016) ---
- {
- InternPoolKey k;
-
- // $985: undef — for section field (null optional).
- // Force-intern because the same undef was created earlier
- // in a different shard context.
- InternPoolKey ak;
- memset(&ak, 0, sizeof(ak));
- ak.tag = IP_KEY_ARRAY_TYPE;
- ak.data.array_type.len = 255;
- ak.data.array_type.child = 3;
- ak.data.array_type.sentinel = IP_INDEX_NONE;
- InternPoolIndex arr255 = ipIntern(s_module_ip, ak);
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_UNDEF;
- k.data.undef = arr255;
- (void)ipForceIntern(s_module_ip, k);
-
- // $986: undef — for the optional name length.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_UNDEF;
- k.data.undef = IP_INDEX_USIZE_TYPE;
- (void)ipForceIntern(s_module_ip, k);
-
- // $987: enum_tag — CallingConvention.c tag for the func.
- // cc_nav and cc_type are from Step 5 (std.builtin namespace).
- if (cc_type != IP_INDEX_NONE && cc_nav != UINT32_MAX)
- (void)internUnionTagByFieldName(cc_type, cc_nav, "c", true);
-
- // $988: union_value — CallingConvention.c value.
- if (cc_type != IP_INDEX_NONE) {
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_UNION_VALUE;
- k.data.union_value = cc_type;
- (void)ipForceIntern(s_module_ip, k);
- }
-
- // $989: func_type — fn(f16) callconv(.c) f16.
- InternPoolIndex ft_c = internFuncType(28, 1, 1, false);
-
- // $990: func — __neghf2 func_decl with correct CC.
- uint32_t neghf2_nav = findNavInNamespace(root_ns, "__neghf2");
- InternPoolIndex fd = IP_INDEX_NONE;
- if (neghf2_nav != UINT32_MAX) {
- fd = internFuncDecl(neghf2_nav, ft_c);
- Nav* fn_nav = ipGetNav(neghf2_nav);
- fn_nav->resolved_type = ft_c;
-
- // $991-$992: ptr_type + ptr_nav for the exported function.
- InternPoolIndex ptr_ft = internPtrConst(ft_c);
- (void)internNavPtr(ptr_ft, neghf2_nav);
- }
-
- // $993: int_u16(16) — f16 bit width for CC param passing.
- (void)internTypedInt(IP_INDEX_U16_TYPE, 16);
-
- // $994: enum_tag — CC.c for export metadata.
- if (cc_type != IP_INDEX_NONE && cc_nav != UINT32_MAX)
- (void)internUnionTagByFieldName(cc_type, cc_nav, "c", true);
-
- // $995: repeated — section default value.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_REPEATED;
- k.data.repeated.ty = IP_INDEX_NONE;
- k.data.repeated.elem_val = IP_INDEX_NULL_VALUE;
- (void)ipForceIntern(s_module_ip, k);
-
- // $996: union_value — CC union value.
- if (cc_type != IP_INDEX_NONE) {
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_UNION_VALUE;
- k.data.union_value = cc_type;
- (void)ipForceIntern(s_module_ip, k);
- }
-
- // $997: aggregate — ExportOptions value.
- if (eo_type != IP_INDEX_NONE) {
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_AGGREGATE;
- k.data.aggregate = eo_type;
- (void)ipForceIntern(s_module_ip, k);
- }
-
- // $998: union_value — CC union value.
- if (cc_type != IP_INDEX_NONE) {
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_UNION_VALUE;
- k.data.union_value = cc_type;
- (void)ipForceIntern(s_module_ip, k);
- }
-
- // $999: int_u16(15) — f16 significand bits.
- (void)internTypedInt(IP_INDEX_U16_TYPE, 15);
-
- // $1000: int_small — computed value from CC resolution.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_INT;
- k.data.int_val.ty = IP_INDEX_U16_TYPE;
- k.data.int_val.value_lo = 0;
- (void)ipForceIntern(s_module_ip, k);
-
- // $1001: int_u16(32768) — f16 sign bit mask (0x8000).
- (void)internTypedInt(IP_INDEX_U16_TYPE, 32768);
-
- // $1002: func_type — fn(f16) f16 (no CC, inner function).
- (void)internFuncType(28, 1, 0, false);
-
- // $1003: array_type — [8]u8 for function name.
- memset(&ak, 0, sizeof(ak));
- ak.tag = IP_KEY_ARRAY_TYPE;
- ak.data.array_type.len = 8;
- ak.data.array_type.child = 3;
- ak.data.array_type.sentinel = IP_INDEX_NONE;
- InternPoolIndex arr8 = ipIntern(s_module_ip, ak);
-
- // $1004: bytes — "__neghf2" (non-sentinel).
- {
- uint32_t str_idx = ipGetOrPutString(s_module_ip, "__neghf2");
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_BYTES;
- k.data.bytes.ty = arr8;
- k.data.bytes.str_idx = str_idx;
- (void)ipForceIntern(s_module_ip, k);
- }
-
- // $1005: ptr_type — *const [8]u8.
- InternPoolIndex ptr_arr8ns = internPtrConst(arr8);
-
- // $1006: ptr_uav — pointer to the bytes.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_PTR_UAV;
- k.data.ptr_uav.ty = IP_INDEX_NONE;
- k.data.ptr_uav.val = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, k);
-
- // $1007: ptr_uav_aligned
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_PTR_UAV_ALIGNED;
- k.data.ptr_uav_aligned.ty = IP_INDEX_NONE;
- k.data.ptr_uav_aligned.val = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, k);
-
- // $1008: ptr_slice
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_PTR_SLICE;
- k.data.ptr_slice.ty = IP_INDEX_NONE;
- k.data.ptr_slice.ptr = IP_INDEX_NONE;
- k.data.ptr_slice.len = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, k);
-
- // $1009: ptr_uav_aligned
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_PTR_UAV_ALIGNED;
- k.data.ptr_uav_aligned.ty = IP_INDEX_NONE;
- k.data.ptr_uav_aligned.val = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, k);
-
- // $1010: ptr_slice
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_PTR_SLICE;
- k.data.ptr_slice.ty = IP_INDEX_NONE;
- k.data.ptr_slice.ptr = IP_INDEX_NONE;
- k.data.ptr_slice.len = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, k);
-
- // $1011: opt_payload
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_OPT_PAYLOAD;
- k.data.opt_payload.ty = IP_INDEX_NONE;
- k.data.opt_payload.val = IP_INDEX_NONE;
- (void)ipForceIntern(s_module_ip, k);
-
- // $1012: aggregate
- if (eo_type != IP_INDEX_NONE) {
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_AGGREGATE;
- k.data.aggregate = eo_type;
- (void)ipForceIntern(s_module_ip, k);
- }
-
- // $1013: ptr_type — *const error info.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_PTR_TYPE;
- k.data.ptr_type.child = IP_INDEX_NONE;
- k.data.ptr_type.flags = 0x100;
- (void)ipForceIntern(s_module_ip, k);
-
- // $1014: type_slice — []u8 (slice of u8).
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_PTR_TYPE;
- k.data.ptr_type.child = IP_INDEX_U8_TYPE;
- k.data.ptr_type.flags = PTR_FLAGS_SIZE_SLICE;
- InternPoolIndex slice_u8 = ipIntern(s_module_ip, k);
-
- // $1015: ptr_type — *const []u8.
- (void)internPtrConst(slice_u8);
-
- // $1016: undef — undef(usize) for function end.
- memset(&k, 0, sizeof(k));
- k.tag = IP_KEY_UNDEF;
- k.data.undef = IP_INDEX_USIZE_TYPE;
- (void)ipForceIntern(s_module_ip, k);
-
- (void)fd;
- (void)ptr_arr8ns;
- }
-
- (void)sema;
- (void)ptr_const_type;
-}
-
-// --- resolveStartComptimePreamble ---
-// Create the IP entries that the Zig compiler generates when processing
-// start.zig's comptime block. This block evaluates builtin.zig_backend
-// (CompilerBackend enum) and builtin.output_mode (OutputMode enum),
-// triggering resolution of those types and their field values.
-// Ported from the side effects of PerThread.zig analyze_comptime_unit
-// processing start.zig's comptime declarations.
-static void resolveStartComptimePreamble(void) {
- uint32_t builtin_file_idx = findFileByPathSuffix("/std/builtin.zig");
- if (builtin_file_idx == UINT32_MAX)
- return;
- uint32_t builtin_ns_idx = s_file_namespace[builtin_file_idx];
-
- // --- CompilerBackend enum type ($142-$167) ---
- // Resolve CompilerBackend (enum(u64), nonexhaustive).
- // In the Zig compiler, this is triggered by start.zig accessing
- // builtin.zig_backend which has type CompilerBackend.
- uint32_t cb_nav = findNavInNamespace(builtin_ns_idx, "CompilerBackend");
- InternPoolIndex cb_enum_ip = IP_INDEX_NONE;
- if (cb_nav != UINT32_MAX)
- cb_enum_ip = ensureNavValUpToDate(cb_nav);
- if (cb_enum_ip == IP_INDEX_NONE)
- return;
-
- // --- $168: enum_tag for zig_backend value ---
- // For wasm32-wasi with use_llvm=false: stage2_wasm = 4.
- // The int_small(u64, 4) was already created during CompilerBackend
- // field value processing.
- InternPoolIndex zig_backend_int = internTypedInt(IP_INDEX_U64_TYPE, 4);
- (void)internEnumTag(cb_enum_ip, zig_backend_int);
-
- // Store target CPU arch name for comptime evaluator (e.g.
- // builtin.target.cpu.arch resolution in cCallingConvention).
- // Determined from the same target info that sets zig_backend.
- s_target_cpu_arch_name = "wasm32";
- s_target_cpu_model_name = "lime1";
-
- // --- $169-$170: type_pointer + ptr_nav for zig_backend access ---
- // When start.zig accesses builtin.zig_backend, the Zig compiler
- // creates a ptr_nav for the zig_backend Nav in the compiler-generated
- // builtin namespace. ptr_type = *const CompilerBackend.
- InternPoolIndex cb_ptr_type = internPtrConst(cb_enum_ip);
- uint32_t zb_nav = createCgBuiltinNav("zig_backend");
- if (zb_nav != UINT32_MAX) {
- Nav* zb = ipGetNav(zb_nav);
- zb->resolved_type = cb_enum_ip;
- (void)internNavPtr(cb_ptr_type, zb_nav);
- }
-
- // --- $171-$176: enum_literal entries for switch cases ---
- // start.zig simplified_logic switch cases (in ZIR order):
- // .stage2_aarch64, .stage2_arm, .stage2_powerpc,
- // .stage2_sparc64, .stage2_spirv, .stage2_x86.
- (void)internEnumLiteral("stage2_aarch64");
- (void)internEnumLiteral("stage2_arm");
- (void)internEnumLiteral("stage2_powerpc");
- (void)internEnumLiteral("stage2_sparc64");
- (void)internEnumLiteral("stage2_spirv");
- (void)internEnumLiteral("stage2_x86");
-
- // --- $177-$182: enum_tag entries for coerced switch values ---
- // Each switch case enum_literal is coerced to CompilerBackend type,
- // creating enum_tag entries. Values: 7, 5, 12, 10, 11, 8.
- (void)internEnumTag(cb_enum_ip, internTypedInt(IP_INDEX_U64_TYPE, 7));
- (void)internEnumTag(cb_enum_ip, internTypedInt(IP_INDEX_U64_TYPE, 5));
- (void)internEnumTag(cb_enum_ip, internTypedInt(IP_INDEX_U64_TYPE, 12));
- (void)internEnumTag(cb_enum_ip, internTypedInt(IP_INDEX_U64_TYPE, 10));
- (void)internEnumTag(cb_enum_ip, internTypedInt(IP_INDEX_U64_TYPE, 11));
- (void)internEnumTag(cb_enum_ip, internTypedInt(IP_INDEX_U64_TYPE, 8));
-
- // --- $183-$184: type_pointer + ptr_nav for simplified_logic access ---
- // The comptime block accesses start.simplified_logic (type bool).
- // This creates *const bool pointer and ptr_nav for the Nav.
- uint32_t start_file_idx = findFileByPathSuffix("/std/start.zig");
- if (start_file_idx != UINT32_MAX) {
- uint32_t start_ns_idx = s_file_namespace[start_file_idx];
- uint32_t sl_nav = findNavInNamespace(start_ns_idx, "simplified_logic");
- if (sl_nav != UINT32_MAX) {
- InternPoolIndex bool_ptr = internPtrConst(IP_INDEX_BOOL_TYPE);
- (void)internNavPtr(bool_ptr, sl_nav);
- }
- }
-
- // --- $185-$190: Resolve OutputMode enum type and values ---
- uint32_t om_nav = findNavInNamespace(builtin_ns_idx, "OutputMode");
- InternPoolIndex om_enum_ip = IP_INDEX_NONE;
- if (om_nav != UINT32_MAX)
- om_enum_ip = ensureNavValUpToDate(om_nav);
-
- // --- $191: ptr_nav for OutputMode ---
- // Already created by ensureNavValUpToDate.
-
- // --- $191-$197: output_mode value, access ptr, and comparisons ---
- if (om_enum_ip != IP_INDEX_NONE) {
- // $191: enum_tag for output_mode = .Obj = 2.
- InternPoolKey u2_key;
- memset(&u2_key, 0, sizeof(u2_key));
- u2_key.tag = IP_KEY_INT_TYPE;
- u2_key.data.int_type.bits = 2;
- u2_key.data.int_type.signedness = 0;
- InternPoolIndex u2_type = ipIntern(s_module_ip, u2_key);
- InternPoolIndex obj_int = internTypedInt(u2_type, 2);
- (void)internEnumTag(om_enum_ip, obj_int);
-
- // $192-$193: *const OutputMode + ptr_nav for output_mode access.
- InternPoolIndex om_ptr_type = internPtrConst(om_enum_ip);
- uint32_t om_cg_nav = createCgBuiltinNav("output_mode");
- if (om_cg_nav != UINT32_MAX) {
- Nav* om_cg = ipGetNav(om_cg_nav);
- om_cg->resolved_type = om_enum_ip;
- (void)internNavPtr(om_ptr_type, om_cg_nav);
- }
-
- // $194-$197: enum_literal + enum_tag for comparisons.
- // start.zig else branch evaluates:
- // output_mode == .Lib (line 53)
- // output_mode == .Exe (line 57)
- (void)internEnumLiteral("Lib");
- (void)internEnumTag(om_enum_ip, internTypedInt(u2_type, 1));
- (void)internEnumLiteral("Exe");
- (void)internEnumTag(om_enum_ip, internTypedInt(u2_type, 0));
- }
-
- // --- $198-$212: string literal "main" from @hasDecl(root, "main") ---
- // start.zig's else branch evaluates @hasDecl(root, "main") which
- // triggers interning of the string literal "main".
- internStringLiteral("main");
-
- // --- $213+: BuiltinDecl type resolution ---
- // The Zig compiler calls analyzeMemoizedState which resolves types
- // from std.builtin in BuiltinDecl order. Port this by resolving each
- // declaration via ensureNavValUpToDate.
- resolveBuiltinDeclTypes(builtin_ns_idx);
- resolveAllTypesFullyC();
-
- // $488+: Load Target.zig and resolve nested types needed by
- // builtin.target, CallingConvention.c, and @export processing.
- resolveTargetModuleChain();
-
- // $667+: Entries from @export processing of __neghf2's function type.
- // The Zig compiler resolves callconv(.c) which triggers
- // cCallingConvention resolution, wasm module loading, etc.
- resolveExportPreamble();
-
- // CG builtin navs for is_test, object_format, link_mode.
- // These are accessed by comptime evaluation of common.zig declarations
- // (e.g. common.linkage depends on builtin.is_test and
- // builtin.object_format). Create the navs here; their values are
- // resolved lazily by resolveCgBuiltinField when first accessed.
- (void)createCgBuiltinNav("is_test");
- (void)createCgBuiltinNav("object_format");
- (void)createCgBuiltinNav("link_mode");
-}
-
// --- findDeclImportPathFromZir ---
// Given a declaration ZIR instruction, check if its value body contains
// a ZIR_INST_IMPORT. Returns the import path string, or NULL.
@@ -12672,28 +9791,7 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) {
sema->has_compile_errors = false;
- if (s_in_main_analysis) {
- // Check if this comptime block contains @export.
- bool has_export = false;
- for (uint32_t vi = 0; vi < vb_len; vi++) {
- if (sema->code.inst_tags[vb[vi]] == ZIR_INST_EXPORT) {
- has_export = true;
- break;
- }
- }
- if (has_export) {
- // Exported names already recorded in pre-scan.
- // Create all IP entries matching the Zig compiler's
- // @export evaluation.
- resolveExportContinuation(sema);
- } else {
- SemaBlock decl_block;
- semaBlockInit(&decl_block, sema, block);
- decl_block.is_comptime = true;
- (void)analyzeBodyInner(sema, &decl_block, vb, vb_len);
- semaBlockDeinit(&decl_block);
- }
- } else {
+ {
SemaBlock decl_block;
semaBlockInit(&decl_block, sema, block);
decl_block.is_comptime = true;
@@ -13459,15 +10557,6 @@ static AirInstRef zirFieldValComptime(
if (int_val != IP_INDEX_NONE) {
InternPoolIndex tag
= internEnumTag(arch_ty, int_val);
- // Trigger arch module cascade ($685+).
- // Must happen here (after enum_tag, before
- // switch body creates enum_literals).
- uint32_t tfi
- = findFileByPathSuffix("/std/Target.zig");
- if (tfi != UINT32_MAX) {
- triggerArchModuleCascade(
- s_file_namespace[tfi], tfi);
- }
return AIR_REF_FROM_IP(tag);
}
}
@@ -16437,10 +13526,6 @@ SemaFuncAirList semaAnalyze(Sema* sema) {
// Load std/builtin.zig chain ($137+).
resolveBuiltinModuleChain(start_file_idx);
-
- // Process start.zig's comptime preamble ($142+).
- // Creates CompilerBackend, OutputMode, etc.
- resolveStartComptimePreamble();
} else {
// No module root — root module is file_idx=0.
if (s_num_loaded_modules == 0) {