zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

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:
Mstage0/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) {