diff --git a/build.zig b/build.zig index 4d8fd054e9..950f8cd529 100644 --- a/build.zig +++ b/build.zig @@ -16,6 +16,7 @@ const zig0_headers = &[_][]const u8{ "ast.h", "astgen.h", "common.h", + "compilation.h", "intern_pool.h", "parser.h", "sema.h", @@ -24,6 +25,8 @@ const zig0_headers = &[_][]const u8{ "verbose_air.h", "verbose_intern_pool.h", "wyhash.h", + "zcu.h", + "zcu_per_thread.h", "zir.h", }; const zig0_c_lib_files = &[_][]const u8{ @@ -40,6 +43,7 @@ const zig0_c_lib_files = &[_][]const u8{ "verbose_intern_pool.c", "wyhash.c", "zig0.c", + "zcu.c", "zir.c", }; const zig0_all_c_files = zig0_c_lib_files ++ &[_][]const u8{"main.c"}; diff --git a/stage0/compilation.h b/stage0/compilation.h new file mode 100644 index 0000000000..765293831a --- /dev/null +++ b/stage0/compilation.h @@ -0,0 +1,20 @@ +// compilation.h — ported from src/Compilation.zig (Config subset we use) +#ifndef _ZIG0_COMPILATION_H__ +#define _ZIG0_COMPILATION_H__ +#include + +// Matches Compilation.Config (the fields relevant to stage0). +typedef struct { + const char* module_root; // was: s_global_module_root + const char* target_cpu_arch; // was: s_target_cpu_arch_name ("wasm32") + const char* target_cpu_model; // was: s_target_cpu_model_name ("lime1") + const char* object_format; // was: s_config_object_format ("wasm") + const char* link_mode; // was: s_config_link_mode ("static") + bool is_test; // was: s_config_is_test +} CompilationConfig; + +// Matches Compilation struct (minimal subset). +typedef struct Compilation { + CompilationConfig config; +} Compilation; +#endif diff --git a/stage0/intern_pool.c b/stage0/intern_pool.c index ff6b650bd9..5ecc64a264 100644 --- a/stage0/intern_pool.c +++ b/stage0/intern_pool.c @@ -443,6 +443,8 @@ InternPool ipInit(void) { ip.string_bytes_cap = IP_STRING_INITIAL_CAP; ip.extra = ARR_INIT(uint32_t, IP_EXTRA_INITIAL_CAP); ip.extra_cap = IP_EXTRA_INITIAL_CAP; + ip.navs = ARR_INIT(Nav, 64); + ip.nav_cap = 64; // Index 0: u0_type ipAppendItem(&ip, ipMakeIntType(0, 0)); @@ -685,10 +687,12 @@ void ipDeinit(InternPool* ip) { free(ip->hash_table); free(ip->string_bytes); free(ip->extra); + free(ip->navs); ip->items = NULL; ip->hash_table = NULL; ip->string_bytes = NULL; ip->extra = NULL; + ip->navs = NULL; ip->items_len = 0; ip->items_cap = 0; ip->hash_cap = 0; @@ -696,6 +700,8 @@ void ipDeinit(InternPool* ip) { ip->string_bytes_cap = 0; ip->extra_len = 0; ip->extra_cap = 0; + ip->nav_count = 0; + ip->nav_cap = 0; } InternPoolIndex ipIntern(InternPool* ip, InternPoolKey key) { @@ -1008,14 +1014,19 @@ InternPoolIndex ipTypeOf(const InternPool* ip, InternPoolIndex index) { // --- Nav management --- // Ported from InternPool.createDeclNav / InternPool.getNav. -static Nav s_navs[IP_MAX_NAVS]; -static uint32_t s_num_navs; - -uint32_t ipCreateDeclNav(uint32_t name, uint32_t fqn, uint32_t zir_index, - uint32_t namespace_idx, bool is_pub, bool is_const) { - assert(s_num_navs < IP_MAX_NAVS); - uint32_t idx = s_num_navs++; - Nav* nav = &s_navs[idx]; +uint32_t ipCreateDeclNav(InternPool* ip, uint32_t name, uint32_t fqn, + uint32_t zir_index, uint32_t namespace_idx, bool is_pub, bool is_const) { + assert(ip->nav_count < IP_MAX_NAVS); + if (ip->nav_count >= ip->nav_cap) { + uint32_t new_cap = ip->nav_cap * 2; + Nav* new_navs = realloc(ip->navs, new_cap * sizeof(Nav)); + if (!new_navs) + exit(1); + ip->navs = new_navs; + ip->nav_cap = new_cap; + } + uint32_t idx = ip->nav_count++; + Nav* nav = &ip->navs[idx]; memset(nav, 0, sizeof(*nav)); nav->name = name; nav->fqn = fqn; @@ -1028,14 +1039,14 @@ uint32_t ipCreateDeclNav(uint32_t name, uint32_t fqn, uint32_t zir_index, return idx; } -Nav* ipGetNav(uint32_t nav_index) { - assert(nav_index < s_num_navs); - return &s_navs[nav_index]; +Nav* ipGetNav(InternPool* ip, uint32_t nav_index) { + assert(nav_index < ip->nav_count); + return &ip->navs[nav_index]; } -void ipResetNavs(void) { s_num_navs = 0; } +void ipResetNavs(InternPool* ip) { ip->nav_count = 0; } -uint32_t ipNavCount(void) { return s_num_navs; } +uint32_t ipNavCount(const InternPool* ip) { return ip->nav_count; } // --- String interning --- // Add a null-terminated string to the IP string table. Returns the diff --git a/stage0/intern_pool.h b/stage0/intern_pool.h index e976eb4960..8e586faef9 100644 --- a/stage0/intern_pool.h +++ b/stage0/intern_pool.h @@ -423,6 +423,24 @@ typedef struct { } data; } InternPoolKey; +// --- Nav (declaration entry) --- +// Ported from InternPool.Nav. Navs are stored in a separate list from +// IP items — they do NOT consume IP indices. However, ptr_nav entries +// (pointers TO Navs) DO consume IP indices. + +typedef struct { + uint32_t name; // NullTerminatedString index into IP string_bytes + uint32_t fqn; // fully qualified name string index + uint32_t zir_index; // ZIR instruction index of declaration + uint32_t namespace_idx; // owning namespace index + InternPoolIndex resolved_type; // IP_INDEX_NONE if unresolved + InternPoolIndex resolved_val; // IP_INDEX_NONE if unresolved + bool is_pub; + bool is_const; +} Nav; + +#define IP_MAX_NAVS 16384 + // --- InternPool struct --- typedef struct { @@ -449,26 +467,14 @@ typedef struct { uint32_t skip_dedup_end; uint32_t cc_keep_start; uint32_t cc_keep_end; + // Nav storage (ported from InternPool.zig Nav storage). + // Navs do NOT consume IP indices; ptr_nav entries (pointers to navs) + // do consume IP indices. Dynamically allocated (like items/extra). + Nav* navs; + uint32_t nav_count; + uint32_t nav_cap; } InternPool; -// --- Nav (declaration entry) --- -// Ported from InternPool.Nav. Navs are stored in a separate list from -// IP items — they do NOT consume IP indices. However, ptr_nav entries -// (pointers TO Navs) DO consume IP indices. - -typedef struct { - uint32_t name; // NullTerminatedString index into IP string_bytes - uint32_t fqn; // fully qualified name string index - uint32_t zir_index; // ZIR instruction index of declaration - uint32_t namespace_idx; // owning namespace index - InternPoolIndex resolved_type; // IP_INDEX_NONE if unresolved - InternPoolIndex resolved_val; // IP_INDEX_NONE if unresolved - bool is_pub; - bool is_const; -} Nav; - -#define IP_MAX_NAVS 16384 - // --- Function declarations --- InternPool ipInit(void); @@ -479,11 +485,11 @@ InternPoolKey ipIndexToKey(const InternPool* ip, InternPoolIndex index); InternPoolIndex ipTypeOf(const InternPool* ip, InternPoolIndex index); // Nav management (ported from InternPool.createDeclNav) -uint32_t ipCreateDeclNav(uint32_t name, uint32_t fqn, uint32_t zir_index, - uint32_t namespace_idx, bool is_pub, bool is_const); -Nav* ipGetNav(uint32_t nav_index); -void ipResetNavs(void); -uint32_t ipNavCount(void); +uint32_t ipCreateDeclNav(InternPool* ip, uint32_t name, uint32_t fqn, + uint32_t zir_index, uint32_t namespace_idx, bool is_pub, bool is_const); +Nav* ipGetNav(InternPool* ip, uint32_t nav_index); +void ipResetNavs(InternPool* ip); +uint32_t ipNavCount(const InternPool* ip); // String interning: add a null-terminated string to the IP string table. // Returns the NullTerminatedString index (offset into string_bytes). diff --git a/stage0/sema.c b/stage0/sema.c index acfbfe0c97..27281e9755 100644 --- a/stage0/sema.c +++ b/stage0/sema.c @@ -1,5 +1,6 @@ #include "sema.h" #include "astgen.h" +#include "zcu.h" #include #include #include @@ -34,16 +35,10 @@ static uint32_t simpleStringHash(const char* s) { #define CC_TAG_AUTO 0 #define CC_TAG_INLINE 3 -// Exported declaration names collected by ZIR_INST_EXPORT handler. -// Module-level state shared between analyzeBodyInner and zirFunc. -#define MAX_EXPORTED_DECL_NAMES 16 -static uint32_t s_exported_decl_names[MAX_EXPORTED_DECL_NAMES]; - // --- Memoized state (BuiltinDecl resolution) --- // Ported from Zcu.BuiltinDecl + PerThread.analyzeMemoizedState. // Resolves std.builtin type declarations (ExportOptions, Type, etc.) // on first @export, creating IP entries as side effects. -#define NUM_BUILTIN_DECL_MAIN 36 typedef struct { const char* lookup_name; // name to find in namespace int parent_idx; // -1=direct (std.builtin ns), >=0=index into table @@ -87,95 +82,11 @@ static const BuiltinDeclEntry s_builtin_decl_entries[NUM_BUILTIN_DECL_MAIN] = { { "Opaque", 15, true }, /* 34 Type.Opaque */ { "Declaration", 15, true }, /* 35 Type.Declaration */ }; -static bool s_memoized_main_resolved; -static bool s_full_memoized_resolved; -static InternPoolIndex s_builtin_decl_values[NUM_BUILTIN_DECL_MAIN]; -// IP range created by analyzeMemoizedStateC during preamble. -// Used by ensureFullMemoizedStateC to skip dedup with preamble entries, -// matching upstream Zig's sharded IP behavior. -static uint32_t s_preamble_memoized_start; -static uint32_t s_preamble_memoized_end; -// Sub-range within preamble memoized range for CC tag entries. -// These entries are in Zig's local shard and SHOULD dedup during main -// analysis, so they're excluded from skip_dedup. -static uint32_t s_preamble_cc_start; -static uint32_t s_preamble_cc_end; -// Nav IDs for builtins 0-4, stored during preamble for later clearing. -static uint32_t s_preamble_builtin_navs[5]; -static uint32_t s_preamble_builtin_nav_count; -// --- Module-level IP entry tracking --- -// Tracks loaded modules to create struct type IP entries matching the -// Zig compiler's module-level analysis. Each imported file module gets -// a type_struct IP entry, created lazily when the module is first -// accessed during semantic analysis. -#define MAX_LOADED_MODULES 512 -typedef struct { - char path[1024]; // canonical file path - char source_dir[1024]; // directory containing this file - Zir zir; // parsed ZIR (inst_len>0 if loaded) - Ast ast; // AST (kept alive to own source memory) - bool has_zir; // true if zir/ast are populated - bool analyzed; // true if createFileRootStructC has been called -} LoadedModule; - -// Global module_root for import resolution (set by semaAnalyze). -static const char* s_global_module_root; - -static LoadedModule s_loaded_modules[MAX_LOADED_MODULES]; -static uint32_t s_num_loaded_modules; -static uint32_t s_next_struct_hash; // unique hash counter for struct types -static InternPool* s_module_ip; // IP for struct type creation -static uint32_t - s_root_file_idx; // file_idx of root module (ZIR owned by caller) -static uint32_t s_cg_builtin_ns_idx - = UINT32_MAX; // compiler-generated builtin namespace -static uint32_t s_cg_builtin_nav - = UINT32_MAX; // nav for `const builtin = @import("builtin")` in - // std/builtin.zig — ptr_nav deferred to $488 -static uint32_t s_builtin_file_idx - = UINT32_MAX; // file index of std/builtin.zig -static uint32_t s_std_file_idx = UINT32_MAX; // file index of std.zig -static const char* s_target_cpu_arch_name = NULL; // e.g. "wasm32" -static const char* s_target_cpu_model_name = NULL; // e.g. "lime1" -// Compilation config — ported from Compilation.Config. -// These are derived from the target and set during semaAnalyze init. -static const char* s_config_object_format = "wasm"; // ObjectFormat name -static const char* s_config_link_mode = "static"; // LinkMode name -static bool s_config_is_test = false; -// Flag: true during main sema analysis (semaAnalyze), false during -// preamble. When true, DECL_VAL for local navs in comptime context -// calls ensureNavValUpToDate for lazy evaluation. -static bool s_in_main_analysis; - -// Enum field value force-intern threshold. -// During memoized resolution, AddressSpace enum field values (comptime_int) -// go into the same single IP as main analysis. In Zig's sharded IP, -// AddressSpace is in a different shard, so its values don't participate -// in dedup during main analysis. CC tag enum values (0..N-1) ARE in -// Zig's local shard and DO dedup. AddressSpace comptime_int values -// below N (the CC field count) correctly substitute for CC entries when -// dedup happens. Values >= N must NOT be findable via dedup, so they -// use ipForceIntern. Set to 0 to disable (all values use ipIntern). -static uint32_t s_enum_force_intern_threshold; - -// --- Namespace storage --- -// Ported from Zcu.Namespace. -#define MAX_NAMESPACES 512 - -static SemaNamespace s_namespaces[MAX_NAMESPACES]; -static uint32_t s_num_namespaces; - -// File→root_type mapping: tracks which IP index is the root struct -// type for each loaded module. -static InternPoolIndex s_file_root_type[MAX_LOADED_MODULES]; -// File→namespace mapping: tracks which namespace index corresponds -// to each loaded module's root struct. -static uint32_t s_file_namespace[MAX_LOADED_MODULES]; - -void semaInit(Sema* sema, InternPool* ip, Zir code) { +void semaInit(Sema* sema, Zcu* zcu, Zir code) { memset(sema, 0, sizeof(*sema)); - sema->ip = ip; + sema->zcu = zcu; + sema->ip = &zcu->ip; sema->code = code; sema->air_inst_tags = ARR_INIT(uint8_t, SEMA_AIR_INITIAL_CAP); sema->air_inst_cap = SEMA_AIR_INITIAL_CAP; @@ -425,10 +336,11 @@ static TypeIndex semaTypeOf(Sema* sema, AirInstRef ref); static uint32_t findEnumFieldByName( const Zir* zir, uint32_t enum_inst, const char* name); static InternPoolIndex getEnumFieldIntVal( - const Zir* zir, uint32_t enum_inst, uint32_t field_idx); -static uint32_t findEnumDeclForNav(uint32_t nav_idx, const Zir** out_zir); + Sema* sema, const Zir* zir, uint32_t enum_inst, uint32_t field_idx); +static uint32_t findEnumDeclForNav( + Sema* sema, uint32_t nav_idx, const Zir** out_zir); static InternPoolIndex internEnumTag( - InternPoolIndex enum_ty, InternPoolIndex int_val); + Sema* sema, InternPoolIndex enum_ty, InternPoolIndex int_val); // --- ZIR instruction handlers --- // Ported from src/Sema.zig instruction handlers. @@ -932,24 +844,24 @@ static AirInstRef semaCoerce( const char* lit_name = (const char*)&sema->ip->string_bytes[lit_str]; // Find the nav whose resolved_type matches the enum type. uint32_t enum_nav = UINT32_MAX; - for (uint32_t ni = 0; ni < ipNavCount(); ni++) { - if (ipGetNav(ni)->resolved_type == target_ty) { + for (uint32_t ni = 0; ni < ipNavCount(sema->ip); ni++) { + if (ipGetNav(sema->ip, ni)->resolved_type == target_ty) { enum_nav = ni; break; } } if (enum_nav != UINT32_MAX) { const Zir* enum_zir = NULL; - uint32_t enum_inst = findEnumDeclForNav(enum_nav, &enum_zir); + uint32_t enum_inst = findEnumDeclForNav(sema, enum_nav, &enum_zir); if (enum_inst != UINT32_MAX && enum_zir != NULL) { uint32_t fidx = findEnumFieldByName(enum_zir, enum_inst, lit_name); if (fidx != UINT32_MAX) { InternPoolIndex int_val - = getEnumFieldIntVal(enum_zir, enum_inst, fidx); + = getEnumFieldIntVal(sema, enum_zir, enum_inst, fidx); if (int_val != IP_INDEX_NONE) { return AIR_REF_FROM_IP( - internEnumTag(target_ty, int_val)); + internEnumTag(sema, target_ty, int_val)); } } } @@ -1950,7 +1862,7 @@ static FuncZirInfo parseFuncZir(Sema* sema, uint32_t inst) { // Forward declaration (defined later, used by findDeclImportPath et al). static uint32_t findDeclInstByNameInZir(const Zir* zir, const char* decl_name); // Forward declaration (defined after createFileRootStructC). -static uint32_t ensureFileAnalyzedC(const char* full_path); +static uint32_t ensureFileAnalyzedC(Sema* sema, const char* full_path); // findDeclImportPath: given a declaration name index, check if the // declaration's value body contains a ZIR_INST_IMPORT. If so, return @@ -2051,7 +1963,8 @@ static bool findDeclImportFieldVal(Sema* sema, uint32_t name_idx, // loadImportZirFromPath: load, parse, and AstGen a file at the given path. // Returns a Zir with inst_len > 0 on success; inst_len == 0 on failure. -static Zir loadImportZirFromPath(const char* full_path, Ast* out_ast) { +static Zir loadImportZirFromPath( + Sema* sema, const char* full_path, Ast* out_ast) { Zir empty_zir; memset(&empty_zir, 0, sizeof(empty_zir)); FILE* f = fopen(full_path, "rb"); @@ -2074,7 +1987,7 @@ static Zir loadImportZirFromPath(const char* full_path, Ast* out_ast) { src[read_len] = '\0'; // Ensure the module is analyzed (creates type_struct + namespace). - (void)ensureFileAnalyzedC(full_path); + (void)ensureFileAnalyzedC(sema, full_path); // Parse. *out_ast = astParse(src, (uint32_t)read_len); @@ -2090,8 +2003,8 @@ static Zir loadImportZirFromPath(const char* full_path, Ast* out_ast) { // (like "std") via module_root. // Returns a Zir with inst_len > 0 on success; inst_len == 0 on failure. // The caller must call zirDeinit and astDeinit on the returned structures. -static Zir loadImportZir( - const char* source_dir, const char* import_path, Ast* out_ast) { +static Zir loadImportZir(Sema* sema, const char* source_dir, + const char* import_path, Ast* out_ast) { Zir empty_zir; memset(&empty_zir, 0, sizeof(empty_zir)); @@ -2112,7 +2025,7 @@ static Zir loadImportZir( if (n < 0 || (size_t)n >= sizeof(full_path)) return empty_zir; - return loadImportZirFromPath(full_path, out_ast); + return loadImportZirFromPath(sema, full_path, out_ast); } // findDeclImportPathInZir: find a declaration by name in a ZIR module and @@ -2361,10 +2274,10 @@ static void computeSourceDir(const char* module_root, const char* source_dir, // loadStdImportZir: load a non-relative import via the module root. // For @import("std"), resolves to /lib/std/std.zig. // For @import("math.zig") from std dir, uses source_dir as usual. -static Zir loadStdImportZir(const char* module_root, const char* source_dir, - const char* import_path, Ast* out_ast) { +static Zir loadStdImportZir(Sema* sema, const char* module_root, + const char* source_dir, const char* import_path, Ast* out_ast) { // First try relative to source_dir (normal case). - Zir zir = loadImportZir(source_dir, import_path, out_ast); + Zir zir = loadImportZir(sema, source_dir, import_path, out_ast); if (zir.inst_len > 0) return zir; @@ -2378,7 +2291,7 @@ static Zir loadStdImportZir(const char* module_root, const char* source_dir, int n = snprintf(full_path, sizeof(full_path), "%s/lib/%s/%s.zig", module_root, import_path, import_path); if (n >= 0 && (size_t)n < sizeof(full_path)) { - zir = loadImportZirFromPath(full_path, out_ast); + zir = loadImportZirFromPath(sema, full_path, out_ast); if (zir.inst_len > 0) return zir; } @@ -2393,40 +2306,41 @@ static Zir loadStdImportZir(const char* module_root, const char* source_dir, // Create a struct type IP entry for a new module. // Each module gets a unique struct type in the InternPool. -static InternPoolIndex createModuleStructType(void) { +static InternPoolIndex createModuleStructType(Sema* sema) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_STRUCT_TYPE; - key.data.struct_type = s_next_struct_hash++; - return ipIntern(s_module_ip, key); + key.data.struct_type = sema->zcu->next_struct_hash++; + return ipIntern(sema->ip, key); } // Forward declaration for createNamespace (defined below). -static uint32_t createNamespace(InternPoolIndex owner_type, uint32_t file_idx); +static uint32_t createNamespace( + Sema* sema, InternPoolIndex owner_type, uint32_t file_idx); // ensureCgBuiltinModule: create the compiler-generated builtin module // on demand, the first time @import("builtin") is encountered. // Ported from Compilation.zig updateBuiltinModule: creates a virtual // module with no ZIR, storing navs for is_test, object_format, etc. // Returns the CG builtin struct type, or IP_INDEX_NONE on failure. -static InternPoolIndex ensureCgBuiltinModule(void) { +static InternPoolIndex ensureCgBuiltinModule(Sema* sema) { // Already created — return cached type. - if (s_cg_builtin_ns_idx != UINT32_MAX) - return s_namespaces[s_cg_builtin_ns_idx].owner_type; + if (sema->zcu->cg_builtin_ns_idx != UINT32_MAX) + return sema->zcu->namespaces[sema->zcu->cg_builtin_ns_idx].owner_type; - if (!s_module_ip || s_num_loaded_modules >= MAX_LOADED_MODULES) + if (!sema->ip || sema->zcu->num_files >= ZCU_MAX_FILES) return IP_INDEX_NONE; - InternPoolIndex cg_struct = createModuleStructType(); - uint32_t cg_file_idx = s_num_loaded_modules++; - LoadedModule* cg_mod = &s_loaded_modules[cg_file_idx]; + InternPoolIndex cg_struct = createModuleStructType(sema); + uint32_t cg_file_idx = sema->zcu->num_files++; + ZcuFile* cg_mod = &sema->zcu->files[cg_file_idx]; memset(cg_mod, 0, sizeof(*cg_mod)); snprintf(cg_mod->path, sizeof(cg_mod->path), ""); cg_mod->analyzed = true; - s_file_root_type[cg_file_idx] = cg_struct; - uint32_t cg_ns_idx = createNamespace(cg_struct, cg_file_idx); - s_file_namespace[cg_file_idx] = cg_ns_idx; - s_cg_builtin_ns_idx = cg_ns_idx; + sema->zcu->file_root_types[cg_file_idx] = cg_struct; + uint32_t cg_ns_idx = createNamespace(sema, cg_struct, cg_file_idx); + sema->zcu->file_namespaces[cg_file_idx] = cg_ns_idx; + sema->zcu->cg_builtin_ns_idx = cg_ns_idx; return cg_struct; } @@ -2436,10 +2350,10 @@ static InternPoolIndex ensureCgBuiltinModule(void) { // Create a new Namespace. Returns the namespace index. static uint32_t createNamespace( - InternPoolIndex owner_type, uint32_t file_idx) { - assert(s_num_namespaces < MAX_NAMESPACES); - uint32_t idx = s_num_namespaces++; - SemaNamespace* ns = &s_namespaces[idx]; + Sema* sema, InternPoolIndex owner_type, uint32_t file_idx) { + assert(sema->zcu->num_namespaces < ZCU_MAX_NAMESPACES); + uint32_t idx = sema->zcu->num_namespaces++; + ZcuNamespace* ns = &sema->zcu->namespaces[idx]; memset(ns, 0, sizeof(*ns)); ns->owner_type = owner_type; ns->file_idx = file_idx; @@ -2453,9 +2367,9 @@ static uint32_t createNamespace( // it in the namespace's pub/priv lists. Comptime declarations are // recorded in the namespace's comptime list. -static void scanNamespaceC(uint32_t ns_idx, const uint32_t* decl_insts, - uint32_t decls_len, const Zir* zir) { - SemaNamespace* ns = &s_namespaces[ns_idx]; +static void scanNamespaceC(Sema* sema, uint32_t ns_idx, + const uint32_t* decl_insts, uint32_t decls_len, const Zir* zir) { + ZcuNamespace* ns = &sema->zcu->namespaces[ns_idx]; // Pass 1: named declarations (const/var) for (uint32_t d = 0; d < decls_len; d++) { @@ -2479,14 +2393,14 @@ static void scanNamespaceC(uint32_t ns_idx, const uint32_t* decl_insts, // Create Nav (does NOT consume IP index) uint32_t nav_idx = ipCreateDeclNav( - name_idx, name_idx, decl_inst, ns_idx, is_pub, is_const); + sema->ip, name_idx, name_idx, decl_inst, ns_idx, is_pub, is_const); // Add to pub or priv list if (is_pub) { - assert(ns->pub_nav_count < SEMA_NS_MAX_NAVS); + assert(ns->pub_nav_count < ZCU_NS_MAX_NAVS); ns->pub_navs[ns->pub_nav_count++] = nav_idx; } else { - assert(ns->priv_nav_count < SEMA_NS_MAX_NAVS); + assert(ns->priv_nav_count < ZCU_NS_MAX_NAVS); ns->priv_navs[ns->priv_nav_count++] = nav_idx; } } @@ -2506,7 +2420,7 @@ static void scanNamespaceC(uint32_t ns_idx, const uint32_t* decl_insts, // Record comptime declarations if (id == 3) { // comptime - assert(ns->comptime_decl_count < SEMA_NS_MAX_COMPTIME); + assert(ns->comptime_decl_count < ZCU_NS_MAX_COMPTIME); ns->comptime_decls[ns->comptime_decl_count++] = decl_inst; } } @@ -2519,7 +2433,7 @@ static void scanNamespaceC(uint32_t ns_idx, const uint32_t* decl_insts, // Returns the IP index of the struct type. static InternPoolIndex createFileRootStructC( - uint32_t file_idx, const Zir* zir) { + Sema* sema, uint32_t file_idx, const Zir* zir) { // Parse struct_decl at instruction 0 assert(zir->inst_tags[0] == ZIR_INST_EXTENDED); assert(zir->inst_datas[0].extended.opcode == ZIR_EXT_STRUCT_DECL); @@ -2555,17 +2469,17 @@ static InternPoolIndex createFileRootStructC( const uint32_t* decl_insts = &zir->extra[extra_index]; // Create type_struct IP entry - InternPoolIndex struct_type = createModuleStructType(); + InternPoolIndex struct_type = createModuleStructType(sema); // Create namespace for this file - uint32_t ns_idx = createNamespace(struct_type, file_idx); + uint32_t ns_idx = createNamespace(sema, struct_type, file_idx); // Scan namespace declarations - scanNamespaceC(ns_idx, decl_insts, decls_len, zir); + scanNamespaceC(sema, ns_idx, decl_insts, decls_len, zir); // Record file→type and file→namespace mappings - s_file_root_type[file_idx] = struct_type; - s_file_namespace[file_idx] = ns_idx; + sema->zcu->file_root_types[file_idx] = struct_type; + sema->zcu->file_namespaces[file_idx] = ns_idx; return struct_type; } @@ -2575,7 +2489,7 @@ static InternPoolIndex createFileRootStructC( // Returns the IP index of the pointer type. // Ported from Sema.zig analyzeNavRefInner → pt.ptrType call. -static InternPoolIndex internPtrConst(InternPoolIndex child_type) { +static InternPoolIndex internPtrConst(Sema* sema, InternPoolIndex child_type) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_PTR_TYPE; @@ -2583,7 +2497,7 @@ static InternPoolIndex internPtrConst(InternPoolIndex child_type) { key.data.ptr_type.sentinel = IP_INDEX_NONE; key.data.ptr_type.flags = PTR_FLAGS_SIZE_ONE | PTR_FLAGS_IS_CONST; key.data.ptr_type.packed_offset = 0; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internNavPtr --- @@ -2592,19 +2506,20 @@ static InternPoolIndex internPtrConst(InternPoolIndex child_type) { // Each ptr_nav is unique per (ty, nav) pair. static InternPoolIndex internNavPtr( - InternPoolIndex ptr_type, uint32_t nav_idx) { + Sema* sema, InternPoolIndex ptr_type, uint32_t nav_idx) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_PTR_NAV; key.data.ptr_nav.ty = ptr_type; key.data.ptr_nav.nav = nav_idx; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internPtrMutable --- // Create a single-item mutable pointer type: *child_type. // Like internPtrConst but without the IS_CONST flag. -static InternPoolIndex internPtrMutable(InternPoolIndex child_type) { +static InternPoolIndex internPtrMutable( + Sema* sema, InternPoolIndex child_type) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_PTR_TYPE; @@ -2612,54 +2527,54 @@ static InternPoolIndex internPtrMutable(InternPoolIndex child_type) { key.data.ptr_type.sentinel = IP_INDEX_NONE; key.data.ptr_type.flags = PTR_FLAGS_SIZE_ONE; key.data.ptr_type.packed_offset = 0; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internUndef --- // Create an undef value for the given type. -static InternPoolIndex internUndef(InternPoolIndex type_idx) { +static InternPoolIndex internUndef(Sema* sema, InternPoolIndex type_idx) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_UNDEF; key.data.undef = type_idx; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internPtrComptimeAlloc --- // Create a ptr_comptime_alloc entry (comptime return value slot). static InternPoolIndex internPtrComptimeAlloc( - InternPoolIndex ptr_type, uint32_t alloc_index) { + Sema* sema, InternPoolIndex ptr_type, uint32_t alloc_index) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_PTR_COMPTIME_ALLOC; key.data.ptr_comptime_alloc.ty = ptr_type; key.data.ptr_comptime_alloc.alloc_index = alloc_index; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internPtrUav --- // Create a ptr_uav entry (unique addressable value). static InternPoolIndex internPtrUav( - InternPoolIndex ptr_type, InternPoolIndex val) { + Sema* sema, InternPoolIndex ptr_type, InternPoolIndex val) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_PTR_UAV; key.data.ptr_uav.ty = ptr_type; key.data.ptr_uav.val = val; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internPtrField --- // Create a ptr_field entry (field access on a pointer). -static InternPoolIndex internPtrField( - InternPoolIndex ptr_type, InternPoolIndex base, uint32_t field_index) { +static InternPoolIndex internPtrField(Sema* sema, InternPoolIndex ptr_type, + InternPoolIndex base, uint32_t field_index) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_PTR_FIELD; key.data.ptr_field.ty = ptr_type; key.data.ptr_field.base = base; key.data.ptr_field.field_index = field_index; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- findNavInNamespace --- @@ -2667,27 +2582,28 @@ static InternPoolIndex internPtrField( // the Nav's name string from the owning ZIR's string_bytes. // Returns the Nav index, or UINT32_MAX if not found. -static uint32_t findNavInNamespace(uint32_t ns_idx, const char* name) { - const SemaNamespace* ns = &s_namespaces[ns_idx]; +static uint32_t findNavInNamespace( + Sema* sema, uint32_t ns_idx, const char* name) { + const ZcuNamespace* ns = &sema->zcu->namespaces[ns_idx]; // Nav names come from ZIR string_bytes (normal modules) or IP // string_bytes (compiler-generated builtin module without ZIR). const uint8_t* string_bytes; - if (s_loaded_modules[ns->file_idx].has_zir) { - string_bytes = s_loaded_modules[ns->file_idx].zir.string_bytes; - } else if (s_module_ip) { - string_bytes = s_module_ip->string_bytes; + if (sema->zcu->files[ns->file_idx].has_zir) { + string_bytes = sema->zcu->files[ns->file_idx].zir.string_bytes; + } else if (sema->ip) { + string_bytes = sema->ip->string_bytes; } else { return UINT32_MAX; } for (uint32_t i = 0; i < ns->pub_nav_count; i++) { - const Nav* nav = ipGetNav(ns->pub_navs[i]); + const Nav* nav = ipGetNav(sema->ip, ns->pub_navs[i]); const char* nav_name = (const char*)&string_bytes[nav->name]; if (strcmp(nav_name, name) == 0) return ns->pub_navs[i]; } for (uint32_t i = 0; i < ns->priv_nav_count; i++) { - const Nav* nav = ipGetNav(ns->priv_navs[i]); + const Nav* nav = ipGetNav(sema->ip, ns->priv_navs[i]); const char* nav_name = (const char*)&string_bytes[nav->name]; if (strcmp(nav_name, name) == 0) return ns->priv_navs[i]; @@ -2696,19 +2612,21 @@ static uint32_t findNavInNamespace(uint32_t ns_idx, const char* name) { } // Forward declarations. -static void resolveModuleDeclImports(uint32_t file_idx, uint32_t depth); -static uint32_t doImport(const char* source_dir, const char* import_string); +static void resolveModuleDeclImports( + Sema* sema, uint32_t file_idx, uint32_t depth); +static uint32_t doImport( + Sema* sema, const char* source_dir, const char* import_string); // Forward declarations for import resolution functions. static const char* findDeclImportPathFromZir( const Zir* zir, uint32_t decl_inst); -static bool resolveImportPath(const char* source_dir, const char* import_path, - char* out_full, size_t out_size); +static bool resolveImportPath(const Sema* sema, const char* source_dir, + const char* import_path, char* out_full, size_t out_size); // Forward declaration (defined later). -static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx); -static void analyzeMemoizedStateC(void); -static InternPoolIndex getBuiltinTypeC(int builtin_idx); +static InternPoolIndex ensureNavValUpToDate(Sema* sema, uint32_t nav_idx); +static void analyzeMemoizedStateC(Sema* sema); +static InternPoolIndex getBuiltinTypeC(Sema* sema, int builtin_idx); // Forward declaration for getValueBodyFromZir (defined later at ~line 7032). static void getValueBodyFromZir(const Zir* zir, uint32_t decl_inst, @@ -2722,7 +2640,8 @@ static void getTypeBodyFromZir(const Zir* zir, uint32_t decl_inst, // For instruction refs, resolves ZIR_INST_INT and ZIR_INST_AS_NODE to // comptime_int. Returns IP_INDEX_NONE on failure. // Ported from Sema.zig resolveInst for the limited case of comptime ints. -static InternPoolIndex resolveZirRefValue(const Zir* zir, uint32_t ref) { +static InternPoolIndex resolveZirRefValue( + Sema* sema, const Zir* zir, uint32_t ref) { if (ref < ZIR_REF_START_INDEX) return ref; // pre-interned: maps directly to IP index @@ -2739,7 +2658,7 @@ static InternPoolIndex resolveZirRefValue(const Zir* zir, uint32_t ref) { key.data.int_val.ty = IP_INDEX_COMPTIME_INT_TYPE; key.data.int_val.value_lo = val; key.data.int_val.is_negative = false; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } if (tag == ZIR_INST_AS_NODE) { // as_node uses pl_node data: { src_node, payload_index }. @@ -2747,7 +2666,7 @@ static InternPoolIndex resolveZirRefValue(const Zir* zir, uint32_t ref) { // We ignore dest_type and recursively resolve the operand. uint32_t payload_index = zir->inst_datas[inst].pl_node.payload_index; uint32_t operand_ref = zir->extra[payload_index + 1]; - return resolveZirRefValue(zir, operand_ref); + return resolveZirRefValue(sema, zir, operand_ref); } return IP_INDEX_NONE; } @@ -2757,9 +2676,9 @@ static InternPoolIndex resolveZirRefValue(const Zir* zir, uint32_t ref) { // Returns the interned int_small IP index. // Ported from PerThread.zig getCoerced for integer coercion. static InternPoolIndex coerceIntToTagType( - InternPoolIndex comptime_int_ip, InternPoolIndex tag_type) { + Sema* sema, InternPoolIndex comptime_int_ip, InternPoolIndex tag_type) { // Get the value from the comptime_int entry. - InternPoolKey src = ipIndexToKey(s_module_ip, comptime_int_ip); + InternPoolKey src = ipIndexToKey(sema->ip, comptime_int_ip); uint64_t val = src.data.int_val.value_lo; bool neg = src.data.int_val.is_negative; @@ -2770,18 +2689,19 @@ static InternPoolIndex coerceIntToTagType( key.data.int_val.ty = tag_type; key.data.int_val.value_lo = val; key.data.int_val.is_negative = neg; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // Forward declarations for mutually recursive type resolvers. -static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx); +static InternPoolIndex ensureNavValUpToDate(Sema* sema, uint32_t nav_idx); static InternPoolIndex resolveCgBuiltinField( - uint32_t field_nav, const char* field_name); -static InternPoolIndex internTypedInt(InternPoolIndex tag_type, uint64_t val); -static InternPoolIndex internFuncType(InternPoolIndex return_type, + Sema* sema, uint32_t field_nav, const char* field_name); +static InternPoolIndex internTypedInt( + Sema* sema, InternPoolIndex tag_type, uint64_t val); +static InternPoolIndex internFuncType(Sema* sema, InternPoolIndex return_type, uint32_t param_count, uint8_t cc, bool is_noinline); static InternPoolIndex internFuncDecl( - uint32_t owner_nav, InternPoolIndex func_type); + Sema* sema, uint32_t owner_nav, InternPoolIndex func_type); // --- resolveEnumDeclFromZir --- // Parse an enum_decl extended ZIR instruction and create IP entries. @@ -2789,7 +2709,7 @@ static InternPoolIndex internFuncDecl( // Returns the IP index of the enum type, or IP_INDEX_NONE on failure. // Ported from Sema.zig zirEnumDecl + resolveDeclaredEnumInner. static InternPoolIndex resolveEnumDeclFromZir( - const Zir* zir, uint32_t enum_inst, uint32_t nav_idx) { + Sema* sema, const Zir* zir, uint32_t enum_inst, uint32_t nav_idx) { if (zir->inst_tags[enum_inst] != ZIR_INST_EXTENDED) return IP_INDEX_NONE; if (zir->inst_datas[enum_inst].extended.opcode != ZIR_EXT_ENUM_DECL) @@ -2838,17 +2758,18 @@ static InternPoolIndex resolveEnumDeclFromZir( InternPoolKey ek; memset(&ek, 0, sizeof(ek)); ek.tag = IP_KEY_ENUM_TYPE; - ek.data.enum_type = s_next_struct_hash++; - InternPoolIndex enum_ip = ipIntern(s_module_ip, ek); + ek.data.enum_type = sema->zcu->next_struct_hash++; + InternPoolIndex enum_ip = ipIntern(sema->ip, ek); // Create namespace and scan declarations (e.g. WindowsVersion.Range). // Matches Zig compiler's getEnumType which creates namespace before // resolveDeclaredEnumInner processes field values. if (decls_len > 0 && nav_idx != UINT32_MAX) { uint32_t enum_file_idx - = s_namespaces[ipGetNav(nav_idx)->namespace_idx].file_idx; - uint32_t ens = createNamespace(enum_ip, enum_file_idx); - scanNamespaceC(ens, decl_insts, decls_len, zir); + = sema->zcu->namespaces[ipGetNav(sema->ip, nav_idx)->namespace_idx] + .file_idx; + uint32_t ens = createNamespace(sema, enum_ip, enum_file_idx); + scanNamespaceC(sema, ens, decl_insts, decls_len, zir); } // Resolve the integer tag type (runs AFTER enum_type creation, @@ -2875,7 +2796,7 @@ static InternPoolIndex resolveEnumDeclFromZir( itk.tag = IP_KEY_INT_TYPE; itk.data.int_type.bits = bits; itk.data.int_type.signedness = ip_sign; - int_tag_type = ipIntern(s_module_ip, itk); + int_tag_type = ipIntern(sema->ip, itk); } } } @@ -2898,7 +2819,7 @@ static InternPoolIndex resolveEnumDeclFromZir( itk.tag = IP_KEY_INT_TYPE; itk.data.int_type.bits = (uint16_t)bits; itk.data.int_type.signedness = 0; - int_tag_type = ipIntern(s_module_ip, itk); + int_tag_type = ipIntern(sema->ip, itk); } // Read bit bags to determine which fields have explicit values. @@ -2924,43 +2845,44 @@ static InternPoolIndex resolveEnumDeclFromZir( uint32_t val_ref = zir->extra[extra_index++]; // Step 1: resolve to comptime_int. - InternPoolIndex comptime_ip = resolveZirRefValue(zir, val_ref); + InternPoolIndex comptime_ip + = resolveZirRefValue(sema, zir, val_ref); if (comptime_ip == IP_INDEX_NONE) { auto_val++; continue; } // Get the actual integer value for auto_val tracking. - InternPoolKey ct_key = ipIndexToKey(s_module_ip, comptime_ip); + InternPoolKey ct_key = ipIndexToKey(sema->ip, comptime_ip); auto_val = ct_key.data.int_val.value_lo + 1; // Step 2: coerce to tag type. if (int_tag_type != IP_INDEX_NONE) - (void)coerceIntToTagType(comptime_ip, int_tag_type); + (void)coerceIntToTagType(sema, comptime_ip, int_tag_type); } else { // Auto-increment: intern as typed int directly. if (int_tag_type != IP_INDEX_NONE && auto_val > 0) { // First intern comptime_int (if not pre-interned). // Use ipForceIntern for values >= threshold to keep // them out of the hash table (see - // s_enum_force_intern_threshold). + // sema->zcu->enum_force_intern_threshold). 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 = auto_val; InternPoolIndex ct_ip; - if (s_enum_force_intern_threshold > 0 - && auto_val >= s_enum_force_intern_threshold) { - ct_ip = ipForceIntern(s_module_ip, ct); + if (sema->zcu->enum_force_intern_threshold > 0 + && auto_val >= sema->zcu->enum_force_intern_threshold) { + ct_ip = ipForceIntern(sema->ip, ct); } else { - ct_ip = ipIntern(s_module_ip, ct); + ct_ip = ipIntern(sema->ip, ct); } // Then coerce to tag type. - (void)coerceIntToTagType(ct_ip, int_tag_type); + (void)coerceIntToTagType(sema, ct_ip, int_tag_type); } else if (int_tag_type != IP_INDEX_NONE) { // Value 0: comptime_int(0) is pre-interned. - (void)coerceIntToTagType(IP_INDEX_ZERO, int_tag_type); + (void)coerceIntToTagType(sema, IP_INDEX_ZERO, int_tag_type); } auto_val++; } @@ -2968,10 +2890,10 @@ static InternPoolIndex resolveEnumDeclFromZir( // Set the Nav's resolved type and create ptr_nav. if (nav_idx != UINT32_MAX) { - Nav* nav = ipGetNav(nav_idx); + Nav* nav = ipGetNav(sema->ip, nav_idx); nav->resolved_type = enum_ip; - InternPoolIndex ptr_type = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(ptr_type, nav_idx); + InternPoolIndex ptr_type = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, ptr_type, nav_idx); } return enum_ip; @@ -3045,8 +2967,8 @@ static uint32_t findEnumFieldByName( // Parses the enum_decl ZIR to find the tag type and computes the value. // For auto-enums, values are 0, 1, 2, ... For explicit enums, reads the // explicit values from ZIR. Returns IP_INDEX_NONE on failure. -static InternPoolIndex getEnumFieldIntVal( - const Zir* zir, uint32_t enum_inst, uint32_t target_field_idx) { +static InternPoolIndex getEnumFieldIntVal(Sema* sema, const Zir* zir, + uint32_t enum_inst, uint32_t target_field_idx) { uint16_t small = zir->inst_datas[enum_inst].extended.small; uint32_t operand = zir->inst_datas[enum_inst].extended.operand; @@ -3094,7 +3016,7 @@ static InternPoolIndex getEnumFieldIntVal( itk.tag = IP_KEY_INT_TYPE; itk.data.int_type.bits = bits; itk.data.int_type.signedness = ip_sign; - int_tag_type = ipIntern(s_module_ip, itk); + int_tag_type = ipIntern(sema->ip, itk); } } } @@ -3116,7 +3038,7 @@ static InternPoolIndex getEnumFieldIntVal( itk.tag = IP_KEY_INT_TYPE; itk.data.int_type.bits = (uint16_t)bits; itk.data.int_type.signedness = 0; - int_tag_type = ipIntern(s_module_ip, itk); + int_tag_type = ipIntern(sema->ip, itk); } if (int_tag_type == IP_INDEX_NONE) @@ -3124,18 +3046,18 @@ static InternPoolIndex getEnumFieldIntVal( // Compute the field's integer value (auto-increment, skipping // explicit values). Simple case: auto-enum field_idx maps to value. - return internTypedInt(int_tag_type, target_field_idx); + return internTypedInt(sema, int_tag_type, target_field_idx); } // 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); +static InternPoolIndex resolveZirTypeInst(Sema* sema, const Zir* zir, + uint32_t inst, uint32_t struct_ns, uint32_t file_idx); // Forward declarations for mutual recursion. -static InternPoolIndex resolveZirTypeInst( - const Zir* zir, uint32_t inst, uint32_t struct_ns, uint32_t file_idx); -static InternPoolIndex resolveZirTypeRef( - const Zir* zir, ZirInstRef ref, uint32_t struct_ns, uint32_t file_idx); +static InternPoolIndex resolveZirTypeInst(Sema* sema, const Zir* zir, + uint32_t inst, uint32_t struct_ns, uint32_t file_idx); +static InternPoolIndex resolveZirTypeRef(Sema* sema, const Zir* zir, + ZirInstRef ref, uint32_t struct_ns, uint32_t file_idx); // --- resolveZirPtrTypeInst --- // Resolve a ZIR ptr_type instruction to create IP pointer/slice type entries. @@ -3143,8 +3065,8 @@ static InternPoolIndex resolveZirTypeRef( // For single/many/c pointers: creates a pointer type. // Returns the final IP index for the type. // Ported from Sema.zig zirPtrType. -static InternPoolIndex resolveZirPtrTypeInst( - const Zir* zir, uint32_t inst, uint32_t struct_ns, uint32_t file_idx) { +static InternPoolIndex resolveZirPtrTypeInst(Sema* sema, const Zir* zir, + uint32_t inst, uint32_t struct_ns, uint32_t file_idx) { uint8_t flags = zir->inst_datas[inst].ptr_type.flags; uint8_t size = zir->inst_datas[inst].ptr_type.size; uint32_t pi = zir->inst_datas[inst].ptr_type.payload_index; @@ -3177,7 +3099,8 @@ static InternPoolIndex resolveZirPtrTypeInst( } else { // Instruction ref — use resolveZirTypeInst for full resolution. uint32_t child_inst = elem_ref - ZIR_REF_START_INDEX; - child_ip = resolveZirTypeInst(zir, child_inst, struct_ns, file_idx); + child_ip + = resolveZirTypeInst(sema, zir, child_inst, struct_ns, file_idx); } if (child_ip == IP_INDEX_NONE) return IP_INDEX_NONE; @@ -3201,7 +3124,7 @@ static InternPoolIndex resolveZirPtrTypeInst( ptr_key.data.ptr_type.sentinel = sentinel_ip; ptr_key.data.ptr_type.flags = ptr_flags; ptr_key.data.ptr_type.packed_offset = 0; - InternPoolIndex ptr_ip = ipIntern(s_module_ip, ptr_key); + InternPoolIndex ptr_ip = ipIntern(sema->ip, ptr_key); if (size == 2) { // Slice type wrapping the many-pointer. @@ -3209,13 +3132,14 @@ static InternPoolIndex resolveZirPtrTypeInst( memset(&slice_key, 0, sizeof(slice_key)); slice_key.tag = IP_KEY_SLICE; slice_key.data.slice = ptr_ip; - return ipIntern(s_module_ip, slice_key); + return ipIntern(sema->ip, slice_key); } return ptr_ip; } // Forward declaration for findNamespaceForType (used by field_val handler). -static uint32_t findNamespaceForType(InternPoolIndex type_ip); +static uint32_t findNamespaceForType( + const Sema* sema, InternPoolIndex type_ip); // --- resolveZirTypeInst --- // Resolve a ZIR instruction to an IP type index. @@ -3223,26 +3147,26 @@ static uint32_t findNamespaceForType(InternPoolIndex type_ip); // For decl_val, searches struct_ns then file root namespace. // For field_val, resolves base type then looks up member in its namespace. // Ported from Sema.zig resolveInst dispatch for type instructions. -static InternPoolIndex resolveZirTypeInst( - const Zir* zir, uint32_t inst, uint32_t struct_ns, uint32_t file_idx) { +static InternPoolIndex resolveZirTypeInst(Sema* sema, const Zir* zir, + uint32_t inst, uint32_t struct_ns, uint32_t file_idx) { if (inst >= zir->inst_len) return IP_INDEX_NONE; ZirInstTag tag = zir->inst_tags[inst]; if (tag == ZIR_INST_PTR_TYPE) - return resolveZirPtrTypeInst(zir, inst, struct_ns, file_idx); + return resolveZirPtrTypeInst(sema, zir, inst, struct_ns, file_idx); if (tag == ZIR_INST_OPTIONAL_TYPE) { ZirInstRef child_ref = zir->inst_datas[inst].un_node.operand; InternPoolIndex child_ip - = resolveZirTypeRef(zir, child_ref, struct_ns, file_idx); + = resolveZirTypeRef(sema, zir, child_ref, struct_ns, file_idx); if (child_ip == IP_INDEX_NONE) return IP_INDEX_NONE; InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_OPT_TYPE; key.data.opt_type = child_ip; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } if (tag == ZIR_INST_DECL_VAL) { @@ -3253,28 +3177,34 @@ static InternPoolIndex resolveZirTypeInst( uint32_t nav = UINT32_MAX; uint32_t search_ns = struct_ns; for (uint32_t depth = 0; depth < 8 && nav == UINT32_MAX; depth++) { - nav = findNavInNamespace(search_ns, name); + nav = findNavInNamespace(sema, search_ns, name); if (nav != UINT32_MAX) break; // Find parent: the nav that resolves to this namespace's owner. - InternPoolIndex owner = s_namespaces[search_ns].owner_type; + InternPoolIndex owner + = sema->zcu->namespaces[search_ns].owner_type; if (owner == IP_INDEX_NONE) break; uint32_t parent_ns = UINT32_MAX; for (uint32_t nsi = 0; - nsi < s_num_namespaces && parent_ns == UINT32_MAX; nsi++) { - const SemaNamespace* pns = &s_namespaces[nsi]; + nsi < sema->zcu->num_namespaces && parent_ns == UINT32_MAX; + nsi++) { + const ZcuNamespace* pns = &sema->zcu->namespaces[nsi]; for (uint32_t k = 0; k < pns->pub_nav_count; k++) { - if (ipGetNav(pns->pub_navs[k])->resolved_type == owner) { - parent_ns = ipGetNav(pns->pub_navs[k])->namespace_idx; + if (ipGetNav(sema->ip, pns->pub_navs[k])->resolved_type + == owner) { + parent_ns = ipGetNav(sema->ip, pns->pub_navs[k]) + ->namespace_idx; break; } } if (parent_ns != UINT32_MAX) break; for (uint32_t k = 0; k < pns->priv_nav_count; k++) { - if (ipGetNav(pns->priv_navs[k])->resolved_type == owner) { - parent_ns = ipGetNav(pns->priv_navs[k])->namespace_idx; + if (ipGetNav(sema->ip, pns->priv_navs[k])->resolved_type + == owner) { + parent_ns = ipGetNav(sema->ip, pns->priv_navs[k]) + ->namespace_idx; break; } } @@ -3284,27 +3214,28 @@ static InternPoolIndex resolveZirTypeInst( search_ns = parent_ns; } if (nav == UINT32_MAX) { - uint32_t root_ns = s_file_namespace[file_idx]; - nav = findNavInNamespace(root_ns, name); + uint32_t root_ns = sema->zcu->file_namespaces[file_idx]; + nav = findNavInNamespace(sema, root_ns, name); } if (nav != UINT32_MAX) { - InternPoolIndex result = ensureNavValUpToDate(nav); + InternPoolIndex result = ensureNavValUpToDate(sema, nav); if (result != IP_INDEX_NONE && result != IP_INDEX_VOID_TYPE) { // Create ptr_type + ptr_nav matching analyzeNavRefInner. // During main analysis: all navs, typeOf(val) child. // During preamble: type decls only, type_type child. - if (result < s_module_ip->items_len) { - if (s_in_main_analysis) { - InternPoolIndex val_ty = ipTypeOf(s_module_ip, result); - InternPoolIndex dv_ptr_ty = internPtrConst(val_ty); - (void)internNavPtr(dv_ptr_ty, nav); + if (result < sema->ip->items_len) { + if (sema->zcu->in_main_analysis) { + InternPoolIndex val_ty = ipTypeOf(sema->ip, result); + InternPoolIndex dv_ptr_ty + = internPtrConst(sema, val_ty); + (void)internNavPtr(sema, dv_ptr_ty, nav); } else { - InternPoolKeyTag kt = s_module_ip->items[result].tag; + InternPoolKeyTag kt = sema->ip->items[result].tag; if (kt == IP_KEY_STRUCT_TYPE || kt == IP_KEY_ENUM_TYPE || kt == IP_KEY_UNION_TYPE) { InternPoolIndex dv_ptr_ty - = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(dv_ptr_ty, nav); + = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, dv_ptr_ty, nav); } } } @@ -3315,11 +3246,11 @@ static InternPoolIndex resolveZirTypeInst( // Also reached when ensureNavValUpToDate returns VOID_TYPE, // which happens when the body contains type instructions // (optional_type, ptr_type) that analyzeNavValC can't handle. - const Nav* tnav = ipGetNav(nav); + const Nav* tnav = ipGetNav(sema->ip, nav); uint32_t tnns = tnav->namespace_idx; - uint32_t tnfi = s_namespaces[tnns].file_idx; - if (s_loaded_modules[tnfi].has_zir) { - const Zir* tzir = &s_loaded_modules[tnfi].zir; + uint32_t tnfi = sema->zcu->namespaces[tnns].file_idx; + if (sema->zcu->files[tnfi].has_zir) { + const Zir* tzir = &sema->zcu->files[tnfi].zir; const uint32_t* tbody = NULL; uint32_t tbody_len = 0; getValueBodyFromZir(tzir, tnav->zir_index, &tbody, &tbody_len); @@ -3331,16 +3262,16 @@ static InternPoolIndex resolveZirTypeInst( ZirInstRef op = tzir->inst_datas[last_inst].break_data.operand; InternPoolIndex alias_result - = resolveZirTypeRef(tzir, op, tnns, tnfi); + = resolveZirTypeRef(sema, tzir, op, tnns, tnfi); if (alias_result != IP_INDEX_NONE) { - Nav* wnav = ipGetNav(nav); + Nav* wnav = ipGetNav(sema->ip, nav); wnav->resolved_type = alias_result; // Create ptr_nav for the alias declaration, // matching analyzeNavRefInner which creates // a ptr_nav for every resolved nav reference. InternPoolIndex ptr_ty - = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(ptr_ty, nav); + = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, ptr_ty, nav); return alias_result; } } @@ -3364,35 +3295,36 @@ static InternPoolIndex resolveZirTypeInst( // Resolve the base type. InternPoolIndex base - = resolveZirTypeRef(zir, lhs_ref, struct_ns, file_idx); + = resolveZirTypeRef(sema, zir, lhs_ref, struct_ns, file_idx); if (base == IP_INDEX_NONE) return IP_INDEX_NONE; // Find the namespace for the base type. - uint32_t base_ns = findNamespaceForType(base); + uint32_t base_ns = findNamespaceForType(sema, base); if (base_ns == UINT32_MAX) return IP_INDEX_NONE; // Look up the field name in the base type's namespace. - uint32_t member_nav = findNavInNamespace(base_ns, fname); + uint32_t member_nav = findNavInNamespace(sema, base_ns, fname); if (member_nav != UINT32_MAX) { - InternPoolIndex result = ensureNavValUpToDate(member_nav); + InternPoolIndex result = ensureNavValUpToDate(sema, member_nav); if (result != IP_INDEX_NONE) { // Create ptr_type + ptr_nav matching analyzeNavRefInner. // During main analysis, create for ALL navs using // typeOf(val). During preamble, only for type decls. - if (result < s_module_ip->items_len) { - if (s_in_main_analysis) { - InternPoolIndex val_ty = ipTypeOf(s_module_ip, result); - InternPoolIndex nav_ptr_ty = internPtrConst(val_ty); - (void)internNavPtr(nav_ptr_ty, member_nav); + if (result < sema->ip->items_len) { + if (sema->zcu->in_main_analysis) { + InternPoolIndex val_ty = ipTypeOf(sema->ip, result); + InternPoolIndex nav_ptr_ty + = internPtrConst(sema, val_ty); + (void)internNavPtr(sema, nav_ptr_ty, member_nav); } else { - InternPoolKeyTag kt = s_module_ip->items[result].tag; + InternPoolKeyTag kt = sema->ip->items[result].tag; if (kt == IP_KEY_STRUCT_TYPE || kt == IP_KEY_ENUM_TYPE || kt == IP_KEY_UNION_TYPE) { InternPoolIndex nav_ptr_ty - = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(nav_ptr_ty, member_nav); + = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, nav_ptr_ty, member_nav); } } } @@ -3412,7 +3344,7 @@ static InternPoolIndex resolveZirTypeInst( key.tag = IP_KEY_INT_TYPE; key.data.int_type.bits = bits; key.data.int_type.signedness = signedness; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // array_type: [N]T syntax. Payload is Bin (lhs=length, rhs=elem type). @@ -3445,8 +3377,9 @@ static InternPoolIndex resolveZirTypeInst( len_resolved = true; // Intern int_comptime_int_u32(value) then int_usize(value), // matching Sema.zig resolveInt coercion sequence. - (void)internTypedInt(IP_INDEX_COMPTIME_INT_TYPE, arr_len); - (void)internTypedInt(IP_INDEX_USIZE_TYPE, arr_len); + (void)internTypedInt( + sema, IP_INDEX_COMPTIME_INT_TYPE, arr_len); + (void)internTypedInt(sema, IP_INDEX_USIZE_TYPE, arr_len); } } if (!len_resolved) @@ -3454,7 +3387,7 @@ static InternPoolIndex resolveZirTypeInst( // Resolve element type. InternPoolIndex child_ip - = resolveZirTypeRef(zir, elem_ref, struct_ns, file_idx); + = resolveZirTypeRef(sema, zir, elem_ref, struct_ns, file_idx); if (child_ip == IP_INDEX_NONE) return IP_INDEX_NONE; @@ -3464,7 +3397,7 @@ static InternPoolIndex resolveZirTypeInst( key.data.array_type.len = arr_len; key.data.array_type.child = child_ip; key.data.array_type.sentinel = sentinel_ip; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } return IP_INDEX_NONE; @@ -3474,20 +3407,20 @@ static InternPoolIndex resolveZirTypeInst( // Resolve a ZIR Ref to an IP type index. // For pre-interned refs, returns the ref directly. // For instruction refs, dispatches to resolveZirTypeInst. -static InternPoolIndex resolveZirTypeRef( - const Zir* zir, ZirInstRef ref, uint32_t struct_ns, uint32_t file_idx) { +static InternPoolIndex resolveZirTypeRef(Sema* sema, const Zir* zir, + ZirInstRef ref, uint32_t struct_ns, uint32_t file_idx) { if (ref < ZIR_REF_START_INDEX) return ref; return resolveZirTypeInst( - zir, ref - ZIR_REF_START_INDEX, struct_ns, file_idx); + sema, zir, ref - ZIR_REF_START_INDEX, struct_ns, file_idx); } // --- resolveStructFieldTypesC --- // Resolve struct field types from ZIR, creating any needed IP entries // for compound types (pointers, slices, optionals, etc.). // Ported from Sema.zig structFields + resolveStructFully. -static void resolveStructFieldTypesC(const Zir* zir, uint32_t struct_inst, - uint32_t struct_ns, uint32_t file_idx) { +static void resolveStructFieldTypesC(Sema* sema, const Zir* zir, + uint32_t struct_inst, uint32_t struct_ns, uint32_t file_idx) { if (zir->inst_tags[struct_inst] != ZIR_INST_EXTENDED) return; if (zir->inst_datas[struct_inst].extended.opcode != ZIR_EXT_STRUCT_DECL) @@ -3583,13 +3516,13 @@ static void resolveStructFieldTypesC(const Zir* zir, uint32_t struct_inst, if (last_zi < zir->inst_len && zir->inst_tags[last_zi] == ZIR_INST_BREAK_INLINE) { ZirInstRef op = zir->inst_datas[last_zi].break_data.operand; - (void)resolveZirTypeRef(zir, op, struct_ns, file_idx); + (void)resolveZirTypeRef(sema, zir, op, struct_ns, file_idx); } } else if (!field_info[fi].has_type_body && field_info[fi].type_ref >= ZIR_REF_START_INDEX) { // Non-body field type that's an instruction ref. (void)resolveZirTypeRef( - zir, field_info[fi].type_ref, struct_ns, file_idx); + sema, zir, field_info[fi].type_ref, struct_ns, file_idx); } sei += field_info[fi].type_body_len; sei += field_info[fi].align_body_len; @@ -3602,16 +3535,17 @@ static void resolveStructFieldTypesC(const Zir* zir, uint32_t struct_inst, // Find the ZIR enum_decl instruction for an enum type nav. // Parses the nav's declaration value body to find the EXTENDED/ENUM_DECL. // Sets *out_zir to the ZIR. Returns UINT32_MAX on failure. -static uint32_t findEnumDeclForNav(uint32_t nav_idx, const Zir** out_zir) { - const Nav* n = ipGetNav(nav_idx); +static uint32_t findEnumDeclForNav( + Sema* sema, uint32_t nav_idx, const Zir** out_zir) { + const Nav* n = ipGetNav(sema->ip, nav_idx); uint32_t ns_idx = n->namespace_idx; - if (ns_idx == UINT32_MAX || ns_idx >= s_num_namespaces) + if (ns_idx == UINT32_MAX || ns_idx >= sema->zcu->num_namespaces) return UINT32_MAX; - uint32_t file_idx = s_namespaces[ns_idx].file_idx; - if (file_idx >= s_num_loaded_modules - || !s_loaded_modules[file_idx].has_zir) + uint32_t file_idx = sema->zcu->namespaces[ns_idx].file_idx; + if (file_idx >= sema->zcu->num_files + || !sema->zcu->files[file_idx].has_zir) return UINT32_MAX; - const Zir* zir = &s_loaded_modules[file_idx].zir; + const Zir* zir = &sema->zcu->files[file_idx].zir; *out_zir = zir; const uint32_t* vb = NULL; @@ -3636,8 +3570,8 @@ static uint32_t findEnumDeclForNav(uint32_t nav_idx, const Zir** out_zir) { // zir - the ZIR containing the struct_decl // struct_inst - ZIR instruction index of the struct_decl // struct_ns - the struct's namespace index in s_namespaces -static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, - uint32_t struct_ns, uint32_t file_idx) { +static void resolveStructFieldInitsC(Sema* sema, const Zir* zir, + uint32_t struct_inst, uint32_t struct_ns, uint32_t file_idx) { if (zir->inst_tags[struct_inst] != ZIR_INST_EXTENDED) return; if (zir->inst_datas[struct_inst].extended.opcode != ZIR_EXT_STRUCT_DECL) @@ -3766,8 +3700,8 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, && zir->inst_tags[tb_last] == ZIR_INST_BREAK_INLINE) { ZirInstRef type_op = zir->inst_datas[tb_last].break_data.operand; - opt_ty - = resolveZirTypeRef(zir, type_op, struct_ns, file_idx); + opt_ty = resolveZirTypeRef( + sema, zir, type_op, struct_ns, file_idx); } } if (opt_ty != IP_INDEX_NONE) { @@ -3775,7 +3709,7 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, memset(&ok, 0, sizeof(ok)); ok.tag = IP_KEY_OPT; ok.data.opt = opt_ty; - (void)ipIntern(s_module_ip, ok); + (void)ipIntern(sema->ip, ok); } continue; } @@ -3804,15 +3738,16 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, // then fall back to the file root namespace. uint32_t ns_search[2]; ns_search[0] = struct_ns; - ns_search[1] = s_file_namespace[file_idx]; + ns_search[1] = sema->zcu->file_namespaces[file_idx]; bool found = false; for (uint32_t nk = 0; nk < 2 && !found; nk++) { - const SemaNamespace* sns = &s_namespaces[ns_search[nk]]; + const ZcuNamespace* sns + = &sema->zcu->namespaces[ns_search[nk]]; for (uint32_t j = 0; j < sns->pub_nav_count; j++) { - const Nav* enav = ipGetNav(sns->pub_navs[j]); + const Nav* enav = ipGetNav(sema->ip, sns->pub_navs[j]); if (enav->resolved_type == IP_INDEX_NONE) continue; - if (s_module_ip->items[enav->resolved_type].tag + if (sema->ip->items[enav->resolved_type].tag != IP_KEY_ENUM_TYPE) continue; @@ -3842,7 +3777,7 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, // Find the enum's tag type from ZIR and compute // the int value for this field. InternPoolIndex int_val - = getEnumFieldIntVal(zir, ed_inst, field_idx); + = getEnumFieldIntVal(sema, zir, ed_inst, field_idx); if (int_val == IP_INDEX_NONE) break; @@ -3851,7 +3786,7 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, etk.tag = IP_KEY_ENUM_TAG; etk.data.enum_tag.ty = enum_ip; etk.data.enum_tag.int_val = int_val; - (void)ipIntern(s_module_ip, etk); + (void)ipIntern(sema->ip, etk); found = true; break; } @@ -3894,14 +3829,14 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, itk.tag = IP_KEY_INT_TYPE; itk.data.int_type.bits = bits; itk.data.int_type.signedness = ip_sign; - field_ty = ipIntern(s_module_ip, itk); + field_ty = ipIntern(sema->ip, itk); } } } } if (field_ty != IP_INDEX_NONE) - (void)internTypedInt(field_ty, val); + (void)internTypedInt(sema, field_ty, val); } } } @@ -3912,7 +3847,7 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, // Returns the IP index of the struct type, or IP_INDEX_NONE on failure. // Ported from Sema.zig zirStructDecl (minimal: type + namespace only). static InternPoolIndex resolveStructDeclFromZir( - const Zir* zir, uint32_t struct_inst, uint32_t nav_idx) { + Sema* sema, const Zir* zir, uint32_t struct_inst, uint32_t nav_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) @@ -3958,24 +3893,24 @@ static InternPoolIndex resolveStructDeclFromZir( 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); + key.data.struct_type = sema->zcu->next_struct_hash++; + InternPoolIndex struct_ip = ipIntern(sema->ip, key); // Create namespace for the struct. - const Nav* nav = ipGetNav(nav_idx); + const Nav* nav = ipGetNav(sema->ip, nav_idx); uint32_t ns_idx = createNamespace( - struct_ip, s_namespaces[nav->namespace_idx].file_idx); + sema, struct_ip, sema->zcu->namespaces[nav->namespace_idx].file_idx); // Scan namespace declarations. const uint32_t* decl_insts = &zir->extra[extra_index]; - scanNamespaceC(ns_idx, decl_insts, decls_len, zir); + scanNamespaceC(sema, ns_idx, decl_insts, decls_len, zir); // Set the Nav's resolved type and create ptr_nav. { - Nav* wnav = ipGetNav(nav_idx); + Nav* wnav = ipGetNav(sema->ip, nav_idx); wnav->resolved_type = struct_ip; - InternPoolIndex ptr_type = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(ptr_type, nav_idx); + InternPoolIndex ptr_type = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, ptr_type, nav_idx); } return struct_ip; @@ -3983,32 +3918,33 @@ static InternPoolIndex resolveStructDeclFromZir( // --- findNamespaceForType --- // Find the namespace owned by a given type IP index. -static uint32_t findNamespaceForType(InternPoolIndex type_ip) { - for (uint32_t i = 0; i < s_num_namespaces; i++) { - if (s_namespaces[i].owner_type == type_ip) +static uint32_t findNamespaceForType( + const Sema* sema, InternPoolIndex type_ip) { + for (uint32_t i = 0; i < sema->zcu->num_namespaces; i++) { + if (sema->zcu->namespaces[i].owner_type == type_ip) return i; } return UINT32_MAX; } // Forward declarations for mutually recursive resolution. -static bool resolveStructLayoutC(uint32_t nav_idx); -static void resolveTypeFullyC(InternPoolIndex ip_idx); -static void resolveStructFullyC(uint32_t nav_idx); -static void resolveUnionFullyC(uint32_t nav_idx); +static bool resolveStructLayoutC(Sema* sema, uint32_t nav_idx); +static void resolveTypeFullyC(Sema* sema, InternPoolIndex ip_idx); +static void resolveStructFullyC(Sema* sema, uint32_t nav_idx); +static void resolveUnionFullyC(Sema* sema, uint32_t nav_idx); // --- findNavForIPIndex --- // Search all namespaces for a nav whose resolved_type matches ip_idx. // Returns the nav index, or UINT32_MAX if not found. -static uint32_t findNavForIPIndex(InternPoolIndex ip_idx) { - for (uint32_t nsi = 0; nsi < s_num_namespaces; nsi++) { - const SemaNamespace* ns = &s_namespaces[nsi]; +static uint32_t findNavForIPIndex(Sema* sema, InternPoolIndex ip_idx) { + for (uint32_t nsi = 0; nsi < sema->zcu->num_namespaces; nsi++) { + const ZcuNamespace* ns = &sema->zcu->namespaces[nsi]; for (uint32_t k = 0; k < ns->pub_nav_count; k++) { - if (ipGetNav(ns->pub_navs[k])->resolved_type == ip_idx) + if (ipGetNav(sema->ip, ns->pub_navs[k])->resolved_type == ip_idx) return ns->pub_navs[k]; } for (uint32_t k = 0; k < ns->priv_nav_count; k++) { - if (ipGetNav(ns->priv_navs[k])->resolved_type == ip_idx) + if (ipGetNav(sema->ip, ns->priv_navs[k])->resolved_type == ip_idx) return ns->priv_navs[k]; } } @@ -4020,35 +3956,35 @@ static uint32_t findNavForIPIndex(InternPoolIndex ip_idx) { // For struct/union types: calls resolveStructFullyC/resolveUnionFullyC. // For compound types (pointer, optional, array, slice): recurses on child. // For simple types (int, float, bool, void, etc.): no-op. -static void resolveTypeFullyC(InternPoolIndex ip_idx) { - if (ip_idx == IP_INDEX_NONE || ip_idx >= s_module_ip->items_len) +static void resolveTypeFullyC(Sema* sema, InternPoolIndex ip_idx) { + if (ip_idx == IP_INDEX_NONE || ip_idx >= sema->ip->items_len) return; - InternPoolKeyTag tag = s_module_ip->items[ip_idx].tag; + InternPoolKeyTag tag = sema->ip->items[ip_idx].tag; switch (tag) { case IP_KEY_STRUCT_TYPE: { - uint32_t nav = findNavForIPIndex(ip_idx); + uint32_t nav = findNavForIPIndex(sema, ip_idx); if (nav != UINT32_MAX) - resolveStructFullyC(nav); + resolveStructFullyC(sema, nav); break; } case IP_KEY_UNION_TYPE: { - uint32_t nav = findNavForIPIndex(ip_idx); + uint32_t nav = findNavForIPIndex(sema, ip_idx); if (nav != UINT32_MAX) - resolveUnionFullyC(nav); + resolveUnionFullyC(sema, nav); break; } case IP_KEY_PTR_TYPE: - resolveTypeFullyC(s_module_ip->items[ip_idx].data.ptr_type.child); + resolveTypeFullyC(sema, sema->ip->items[ip_idx].data.ptr_type.child); break; case IP_KEY_OPT_TYPE: - resolveTypeFullyC(s_module_ip->items[ip_idx].data.opt_type); + resolveTypeFullyC(sema, sema->ip->items[ip_idx].data.opt_type); break; case IP_KEY_ARRAY_TYPE: - resolveTypeFullyC(s_module_ip->items[ip_idx].data.array_type.child); + resolveTypeFullyC(sema, sema->ip->items[ip_idx].data.array_type.child); break; case IP_KEY_SLICE: // Slice wraps a pointer type; resolve the pointer's child. - resolveTypeFullyC(s_module_ip->items[ip_idx].data.slice); + resolveTypeFullyC(sema, sema->ip->items[ip_idx].data.slice); break; default: break; @@ -4062,8 +3998,8 @@ static void resolveTypeFullyC(InternPoolIndex ip_idx) { // field_ty.resolveFully(pt); // Re-parses the struct's ZIR fields to get the resolved type refs, then // calls resolveTypeFullyC on each. -static void resolveStructFieldTypesFully(const Zir* zir, uint32_t struct_inst, - uint32_t struct_ns, uint32_t file_idx) { +static void resolveStructFieldTypesFully(Sema* sema, const Zir* zir, + uint32_t struct_inst, uint32_t struct_ns, uint32_t file_idx) { if (zir->inst_tags[struct_inst] != ZIR_INST_EXTENDED) return; if (zir->inst_datas[struct_inst].extended.opcode != ZIR_EXT_STRUCT_DECL) @@ -4158,19 +4094,20 @@ static void resolveStructFieldTypesFully(const Zir* zir, uint32_t struct_inst, if (last_zi < zir->inst_len && zir->inst_tags[last_zi] == ZIR_INST_BREAK_INLINE) { ZirInstRef op = zir->inst_datas[last_zi].break_data.operand; - resolved = resolveZirTypeRef(zir, op, struct_ns, file_idx); + resolved + = resolveZirTypeRef(sema, zir, op, struct_ns, file_idx); } } else if (!finfo[fi].has_type_body && finfo[fi].type_ref >= ZIR_REF_START_INDEX) { resolved = resolveZirTypeRef( - zir, finfo[fi].type_ref, struct_ns, file_idx); + sema, zir, finfo[fi].type_ref, struct_ns, file_idx); } sei += finfo[fi].type_body_len; sei += finfo[fi].align_body_len; sei += finfo[fi].init_body_len; if (resolved != IP_INDEX_NONE) - resolveTypeFullyC(resolved); + resolveTypeFullyC(sema, resolved); } } @@ -4180,28 +4117,27 @@ static void resolveStructFieldTypesFully(const Zir* zir, uint32_t struct_inst, // This creates type entries (like ?u64) during union layout resolution, // before field init values (like opt_null) are created later in // resolveStructFullyC. -static bool s_struct_layout_resolved[4096]; -static bool resolveStructLayoutC(uint32_t nav_idx) { - const Nav* nav = ipGetNav(nav_idx); +static bool resolveStructLayoutC(Sema* sema, uint32_t nav_idx) { + const Nav* nav = ipGetNav(sema->ip, nav_idx); if (nav->resolved_type == IP_INDEX_NONE) return false; - if (s_module_ip->items[nav->resolved_type].tag != IP_KEY_STRUCT_TYPE) + if (sema->ip->items[nav->resolved_type].tag != IP_KEY_STRUCT_TYPE) return false; - if (nav_idx < 4096 && s_struct_layout_resolved[nav_idx]) + if (nav_idx < 4096 && sema->zcu->struct_layout_resolved[nav_idx]) return true; if (nav_idx < 4096) - s_struct_layout_resolved[nav_idx] = true; + sema->zcu->struct_layout_resolved[nav_idx] = true; // Find the struct's namespace. - uint32_t ns_idx = findNamespaceForType(nav->resolved_type); + uint32_t ns_idx = findNamespaceForType(sema, nav->resolved_type); if (ns_idx == UINT32_MAX) return false; // Find the struct_decl ZIR instruction. - uint32_t file_idx = s_namespaces[ns_idx].file_idx; - if (!s_loaded_modules[file_idx].has_zir) + uint32_t file_idx = sema->zcu->namespaces[ns_idx].file_idx; + if (!sema->zcu->files[file_idx].has_zir) return false; - const Zir* zir = &s_loaded_modules[file_idx].zir; + const Zir* zir = &sema->zcu->files[file_idx].zir; const uint32_t* vbody = NULL; uint32_t vbody_len = 0; @@ -4222,7 +4158,7 @@ static bool resolveStructLayoutC(uint32_t nav_idx) { return false; // Resolve field types (creates pointer/slice/optional IP entries). - resolveStructFieldTypesC(zir, struct_inst, ns_idx, file_idx); + resolveStructFieldTypesC(sema, zir, struct_inst, ns_idx, file_idx); return true; } @@ -4231,31 +4167,30 @@ static bool resolveStructLayoutC(uint32_t nav_idx) { // and recursively resolve field types fully. Ported from Sema.zig // resolveStructFully (called after all BuiltinDecl types are created). // Assumes resolveStructLayoutC has already been called (field types resolved). -static bool s_struct_fully_resolved[4096]; -static void resolveStructFullyC(uint32_t nav_idx) { - const Nav* nav = ipGetNav(nav_idx); +static void resolveStructFullyC(Sema* sema, uint32_t nav_idx) { + const Nav* nav = ipGetNav(sema->ip, nav_idx); if (nav->resolved_type == IP_INDEX_NONE) return; - if (s_module_ip->items[nav->resolved_type].tag != IP_KEY_STRUCT_TYPE) + if (sema->ip->items[nav->resolved_type].tag != IP_KEY_STRUCT_TYPE) return; - if (nav_idx < 4096 && s_struct_fully_resolved[nav_idx]) + if (nav_idx < 4096 && sema->zcu->struct_fully_resolved[nav_idx]) return; if (nav_idx < 4096) - s_struct_fully_resolved[nav_idx] = true; + sema->zcu->struct_fully_resolved[nav_idx] = true; // Ensure layout is resolved first (idempotent). - resolveStructLayoutC(nav_idx); + resolveStructLayoutC(sema, nav_idx); // Find the struct's namespace. - uint32_t ns_idx = findNamespaceForType(nav->resolved_type); + uint32_t ns_idx = findNamespaceForType(sema, nav->resolved_type); if (ns_idx == UINT32_MAX) return; // Find the struct_decl ZIR instruction. - uint32_t file_idx = s_namespaces[ns_idx].file_idx; - if (!s_loaded_modules[file_idx].has_zir) + uint32_t file_idx = sema->zcu->namespaces[ns_idx].file_idx; + if (!sema->zcu->files[file_idx].has_zir) return; - const Zir* zir = &s_loaded_modules[file_idx].zir; + const Zir* zir = &sema->zcu->files[file_idx].zir; const uint32_t* vbody = NULL; uint32_t vbody_len = 0; @@ -4276,11 +4211,11 @@ static void resolveStructFullyC(uint32_t nav_idx) { return; // Resolve field default values (creates enum_tag, opt_null, etc.). - resolveStructFieldInitsC(zir, struct_inst, ns_idx, file_idx); + resolveStructFieldInitsC(sema, zir, struct_inst, ns_idx, file_idx); // Recursively resolve field types (matching Zig's resolveStructFully // field loop that calls field_ty.resolveFully on each field). - resolveStructFieldTypesFully(zir, struct_inst, ns_idx, file_idx); + resolveStructFieldTypesFully(sema, zir, struct_inst, ns_idx, file_idx); } // --- resolveUnionFullyC --- @@ -4289,43 +4224,40 @@ static void resolveStructFullyC(uint32_t nav_idx) { // separation of getUnionType (creation) and resolveUnionFully (resolution). // This allows controlling when field type resolution happens relative to // other type creation, important for ordering IP entries correctly. -static bool s_union_fully_resolved[4096]; // Mapping from union type IP index → tag enum IP index. // Set by resolveUnionFullyC when creating the tag enum. -static InternPoolIndex s_union_tag_enums[256]; -static InternPoolIndex s_union_tag_types[256]; // corresponding union type IPs -static uint32_t s_num_union_tag_enums; // Look up the tag enum IP index for a union type. -static InternPoolIndex findUnionTagEnum(InternPoolIndex union_type) { - for (uint32_t i = 0; i < s_num_union_tag_enums; i++) { - if (s_union_tag_types[i] == union_type) - return s_union_tag_enums[i]; +static InternPoolIndex findUnionTagEnum( + Sema* sema, InternPoolIndex union_type) { + for (uint32_t i = 0; i < sema->zcu->num_union_tag_enums; i++) { + if (sema->zcu->union_tag_types[i] == union_type) + return sema->zcu->union_tag_enums[i]; } return IP_INDEX_NONE; } -static void resolveUnionFullyC(uint32_t nav_idx) { - const Nav* nav = ipGetNav(nav_idx); +static void resolveUnionFullyC(Sema* sema, uint32_t nav_idx) { + const Nav* nav = ipGetNav(sema->ip, nav_idx); if (nav->resolved_type == IP_INDEX_NONE) return; - if (s_module_ip->items[nav->resolved_type].tag != IP_KEY_UNION_TYPE) + if (sema->ip->items[nav->resolved_type].tag != IP_KEY_UNION_TYPE) return; - if (nav_idx < 4096 && s_union_fully_resolved[nav_idx]) + if (nav_idx < 4096 && sema->zcu->union_fully_resolved[nav_idx]) return; if (nav_idx < 4096) - s_union_fully_resolved[nav_idx] = true; + sema->zcu->union_fully_resolved[nav_idx] = true; // Find the union's namespace. - uint32_t ns_idx = findNamespaceForType(nav->resolved_type); + uint32_t ns_idx = findNamespaceForType(sema, nav->resolved_type); if (ns_idx == UINT32_MAX) return; // Find the union_decl ZIR instruction from the nav's declaration body. - uint32_t file_idx = s_namespaces[ns_idx].file_idx; - if (!s_loaded_modules[file_idx].has_zir) + uint32_t file_idx = sema->zcu->namespaces[ns_idx].file_idx; + if (!sema->zcu->files[file_idx].has_zir) return; - const Zir* zir = &s_loaded_modules[file_idx].zir; + const Zir* zir = &sema->zcu->files[file_idx].zir; const uint32_t* vbody = NULL; uint32_t vbody_len = 0; @@ -4393,7 +4325,7 @@ static void resolveUnionFullyC(uint32_t nav_idx) { if (ft_has_type) { ZirInstRef type_ref = zir->extra[cursor++]; InternPoolIndex resolved - = resolveZirTypeRef(zir, type_ref, ns_idx, file_idx); + = resolveZirTypeRef(sema, zir, type_ref, ns_idx, file_idx); if (resolved != IP_INDEX_NONE && num_resolved_fields < 128) resolved_field_types[num_resolved_fields++] = resolved; } @@ -4407,19 +4339,22 @@ static void resolveUnionFullyC(uint32_t nav_idx) { // Phase 2: Tag values and tag enum for tagged unions. if (auto_enum_tag || has_tag_type) { if (fields_len > 0) - (void)internTypedInt(IP_INDEX_COMPTIME_INT_TYPE, fields_len - 1); + (void)internTypedInt( + sema, IP_INDEX_COMPTIME_INT_TYPE, fields_len - 1); for (uint32_t i = 2; i < fields_len; i++) - (void)internTypedInt(IP_INDEX_U8_TYPE, i); + (void)internTypedInt(sema, IP_INDEX_U8_TYPE, i); InternPoolKey ek; memset(&ek, 0, sizeof(ek)); ek.tag = IP_KEY_ENUM_TYPE; - ek.data.enum_type = s_next_struct_hash++; - InternPoolIndex tag_enum = ipIntern(s_module_ip, ek); + ek.data.enum_type = sema->zcu->next_struct_hash++; + InternPoolIndex tag_enum = ipIntern(sema->ip, ek); // Save union → tag enum mapping for comptime union init. - if (s_num_union_tag_enums < 256) { - s_union_tag_types[s_num_union_tag_enums] = nav->resolved_type; - s_union_tag_enums[s_num_union_tag_enums] = tag_enum; - s_num_union_tag_enums++; + if (sema->zcu->num_union_tag_enums < 256) { + sema->zcu->union_tag_types[sema->zcu->num_union_tag_enums] + = nav->resolved_type; + sema->zcu->union_tag_enums[sema->zcu->num_union_tag_enums] + = tag_enum; + sema->zcu->num_union_tag_enums++; } } @@ -4430,8 +4365,8 @@ static void resolveUnionFullyC(uint32_t nav_idx) { InternPoolKey ek; memset(&ek, 0, sizeof(ek)); ek.tag = IP_KEY_ENUM_TYPE; - ek.data.enum_type = s_next_struct_hash++; - (void)ipIntern(s_module_ip, ek); + ek.data.enum_type = sema->zcu->next_struct_hash++; + (void)ipIntern(sema->ip, ek); } // Phase 2b: Resolve struct field types for each struct-typed field. @@ -4440,12 +4375,13 @@ static void resolveUnionFullyC(uint32_t nav_idx) { // the tag enum. This creates type entries (like ?u64) during layout // resolution, before field init values are created in Phase 3. for (uint32_t i = 0; i < num_resolved_fields; i++) { - if (resolved_field_types[i] < s_module_ip->items_len - && s_module_ip->items[resolved_field_types[i]].tag + if (resolved_field_types[i] < sema->ip->items_len + && sema->ip->items[resolved_field_types[i]].tag == IP_KEY_STRUCT_TYPE) { - uint32_t field_nav = findNavForIPIndex(resolved_field_types[i]); + uint32_t field_nav + = findNavForIPIndex(sema, resolved_field_types[i]); if (field_nav != UINT32_MAX) - resolveStructLayoutC(field_nav); + resolveStructLayoutC(sema, field_nav); } } @@ -4454,7 +4390,7 @@ static void resolveUnionFullyC(uint32_t nav_idx) { // for (0..union_obj.field_types.len) |field_index| // field_ty.resolveFully(pt); for (uint32_t i = 0; i < num_resolved_fields; i++) { - resolveTypeFullyC(resolved_field_types[i]); + resolveTypeFullyC(sema, resolved_field_types[i]); } } @@ -4462,26 +4398,27 @@ static void resolveUnionFullyC(uint32_t nav_idx) { // Find a union field by name and return its type IP index and field index. // Parses the union_decl ZIR to iterate fields. Returns IP_INDEX_NONE if // not found. Sets *out_field_idx to the field's position in the union. -static InternPoolIndex resolveUnionFieldByName(InternPoolIndex union_type, - const char* field_name, uint32_t* out_field_idx) { +static InternPoolIndex resolveUnionFieldByName(Sema* sema, + InternPoolIndex union_type, const char* field_name, + uint32_t* out_field_idx) { if (out_field_idx) *out_field_idx = UINT32_MAX; // Find the nav for the union type. - uint32_t nav_idx = findNavForIPIndex(union_type); + uint32_t nav_idx = findNavForIPIndex(sema, union_type); if (nav_idx == UINT32_MAX) return IP_INDEX_NONE; - const Nav* nav = ipGetNav(nav_idx); + const Nav* nav = ipGetNav(sema->ip, nav_idx); // Find the namespace and ZIR. - uint32_t ns_idx = findNamespaceForType(union_type); + uint32_t ns_idx = findNamespaceForType(sema, union_type); if (ns_idx == UINT32_MAX) return IP_INDEX_NONE; - uint32_t file_idx = s_namespaces[ns_idx].file_idx; - if (file_idx >= s_num_loaded_modules - || !s_loaded_modules[file_idx].has_zir) + uint32_t file_idx = sema->zcu->namespaces[ns_idx].file_idx; + if (file_idx >= sema->zcu->num_files + || !sema->zcu->files[file_idx].has_zir) return IP_INDEX_NONE; - const Zir* zir = &s_loaded_modules[file_idx].zir; + const Zir* zir = &sema->zcu->files[file_idx].zir; // Find the union_decl instruction from the nav's value body. const uint32_t* vbody = NULL; @@ -4545,7 +4482,8 @@ static InternPoolIndex resolveUnionFieldByName(InternPoolIndex union_type, InternPoolIndex field_type = IP_INDEX_NONE; if (ft_has_type) { ZirInstRef type_ref = zir->extra[cursor++]; - field_type = resolveZirTypeRef(zir, type_ref, ns_idx, file_idx); + field_type + = resolveZirTypeRef(sema, zir, type_ref, ns_idx, file_idx); } if (ft_has_align) cursor++; @@ -4567,7 +4505,7 @@ static InternPoolIndex resolveUnionFieldByName(InternPoolIndex union_type, // Returns the IP index of the union type, or IP_INDEX_NONE on failure. // Ported from Sema.zig zirUnionDecl (getUnionType part only). static InternPoolIndex resolveUnionDeclFromZir( - const Zir* zir, uint32_t union_inst, uint32_t nav_idx) { + Sema* sema, const Zir* zir, uint32_t union_inst, uint32_t nav_idx) { if (zir->inst_tags[union_inst] != ZIR_INST_EXTENDED) return IP_INDEX_NONE; if (zir->inst_datas[union_inst].extended.opcode != ZIR_EXT_UNION_DECL) @@ -4596,26 +4534,27 @@ static InternPoolIndex resolveUnionDeclFromZir( InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_UNION_TYPE; - key.data.union_type = s_next_struct_hash++; - InternPoolIndex union_ip = ipIntern(s_module_ip, key); + key.data.union_type = sema->zcu->next_struct_hash++; + InternPoolIndex union_ip = ipIntern(sema->ip, key); // Set resolved_type and create ptr_nav for the union nav. { - Nav* wnav = ipGetNav(nav_idx); + Nav* wnav = ipGetNav(sema->ip, nav_idx); wnav->resolved_type = union_ip; - InternPoolIndex ptr_type = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(ptr_type, nav_idx); + InternPoolIndex ptr_type = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, ptr_type, nav_idx); } // Create namespace for the union. uint32_t file_idx - = s_namespaces[ipGetNav(nav_idx)->namespace_idx].file_idx; - uint32_t ns_idx = createNamespace(union_ip, file_idx); + = sema->zcu->namespaces[ipGetNav(sema->ip, nav_idx)->namespace_idx] + .file_idx; + uint32_t ns_idx = createNamespace(sema, union_ip, file_idx); // Scan namespace declarations (creates Navs for sub-types like // CommonOptions, X86RegparmOptions, etc.). const uint32_t* decl_insts = &zir->extra[extra_index]; - scanNamespaceC(ns_idx, decl_insts, decls_len, zir); + scanNamespaceC(sema, ns_idx, decl_insts, decls_len, zir); return union_ip; } @@ -4624,14 +4563,14 @@ static InternPoolIndex resolveUnionDeclFromZir( // Evaluate a Nav's const declaration value body using a mini-sema. // Creates IP entries for the resolved type and ptr_nav. // Ported from PerThread.zig analyzeNavVal. -static InternPoolIndex analyzeNavValC(uint32_t nav_idx) { - Nav* nav = ipGetNav(nav_idx); +static InternPoolIndex analyzeNavValC(Sema* sema, uint32_t nav_idx) { + Nav* nav = ipGetNav(sema->ip, nav_idx); uint32_t ns_idx = nav->namespace_idx; - const SemaNamespace* ns = &s_namespaces[ns_idx]; + const ZcuNamespace* ns = &sema->zcu->namespaces[ns_idx]; uint32_t file_idx = ns->file_idx; - if (!s_loaded_modules[file_idx].has_zir) + if (!sema->zcu->files[file_idx].has_zir) return IP_INDEX_NONE; - const Zir* zir = &s_loaded_modules[file_idx].zir; + const Zir* zir = &sema->zcu->files[file_idx].zir; const uint32_t* value_body = NULL; uint32_t value_body_len = 0; @@ -4644,10 +4583,9 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) { // Enable import resolution so comptime expressions can access // cross-module declarations (e.g. @import("builtin").target). Sema mini_sema; - semaInit(&mini_sema, s_module_ip, *zir); + semaInit(&mini_sema, sema->zcu, *zir); mini_sema.file_idx = file_idx; - mini_sema.source_dir = s_loaded_modules[file_idx].source_dir; - mini_sema.module_root = s_global_module_root; + mini_sema.source_dir = sema->zcu->files[file_idx].source_dir; // Pre-expand inst_map to cover the full ZIR range. // Value body instructions may reference ZIR instructions outside @@ -4712,9 +4650,9 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) { && zir->inst_tags[last_inst] == ZIR_INST_BREAK_INLINE) { ZirInstRef op = zir->inst_datas[last_inst].break_data.operand; InternPoolIndex type_result - = resolveZirTypeRef(zir, op, ns_idx, file_idx); + = resolveZirTypeRef(sema, zir, op, ns_idx, file_idx); if (type_result != IP_INDEX_NONE) { - nav = ipGetNav(nav_idx); + nav = ipGetNav(sema->ip, nav_idx); nav->resolved_type = type_result; return type_result; } @@ -4731,7 +4669,7 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) { // handled separately by analyzeNavRefInner (called from analyzeNavVal). // Callers that need ptr_nav create it // explicitly. - nav = ipGetNav(nav_idx); + nav = ipGetNav(sema->ip, nav_idx); nav->resolved_type = result_ip; return result_ip; @@ -4744,15 +4682,15 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) { // For const declarations that are not type declarations, falls through // to analyzeNavValC for general comptime evaluation. // Ported from PerThread.zig ensureNavValUpToDate. -static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) { - const Nav* nav = ipGetNav(nav_idx); +static InternPoolIndex ensureNavValUpToDate(Sema* sema, uint32_t nav_idx) { + const Nav* nav = ipGetNav(sema->ip, nav_idx); // If already resolved, return the cached value. if (nav->resolved_type != IP_INDEX_NONE) return nav->resolved_type; uint32_t ns_idx = nav->namespace_idx; - const SemaNamespace* ns = &s_namespaces[ns_idx]; + const ZcuNamespace* ns = &sema->zcu->namespaces[ns_idx]; uint32_t file_idx = ns->file_idx; // CG builtin module navs have no ZIR — resolve via @@ -4763,19 +4701,19 @@ static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) { // are synthetic modules with no ZIR). std/builtin.zig shares the // same namespace index when the CG builtin is a sub-namespace, // but its navs have valid ZIR and should be resolved normally. - if (s_cg_builtin_ns_idx != UINT32_MAX && ns_idx == s_cg_builtin_ns_idx - && !s_loaded_modules[file_idx].has_zir) { - const char* nav_name - = (const char*)&s_module_ip->string_bytes[nav->name]; - InternPoolIndex val = resolveCgBuiltinField(nav_idx, nav_name); + if (sema->zcu->cg_builtin_ns_idx != UINT32_MAX + && ns_idx == sema->zcu->cg_builtin_ns_idx + && !sema->zcu->files[file_idx].has_zir) { + const char* nav_name = (const char*)&sema->ip->string_bytes[nav->name]; + InternPoolIndex val = resolveCgBuiltinField(sema, nav_idx, nav_name); if (val != IP_INDEX_NONE) return val; return IP_INDEX_NONE; } - if (!s_loaded_modules[file_idx].has_zir) + if (!sema->zcu->files[file_idx].has_zir) return IP_INDEX_NONE; - const Zir* zir = &s_loaded_modules[file_idx].zir; + const Zir* zir = &sema->zcu->files[file_idx].zir; // Get the value body from the declaration. const uint32_t* body = NULL; @@ -4792,19 +4730,20 @@ static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) { if (zir->inst_tags[inst] == ZIR_INST_EXTENDED) { uint16_t opcode = zir->inst_datas[inst].extended.opcode; if (opcode == ZIR_EXT_ENUM_DECL) - return resolveEnumDeclFromZir(zir, inst, nav_idx); + return resolveEnumDeclFromZir(sema, zir, inst, nav_idx); if (opcode == ZIR_EXT_STRUCT_DECL) - return resolveStructDeclFromZir(zir, inst, nav_idx); + return resolveStructDeclFromZir(sema, zir, inst, nav_idx); if (opcode == ZIR_EXT_UNION_DECL) - return resolveUnionDeclFromZir(zir, inst, nav_idx); + return resolveUnionDeclFromZir(sema, zir, inst, nav_idx); if (opcode == ZIR_EXT_THIS) { // @This() resolves to the type that owns the namespace // this declaration is declared in. E.g. `const V = @This();` // inside a struct resolves V to that struct type. - Nav* wnav = ipGetNav(nav_idx); + Nav* wnav = ipGetNav(sema->ip, nav_idx); wnav->resolved_type = ns->owner_type; - InternPoolIndex ptr_type = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(ptr_type, nav_idx); + InternPoolIndex ptr_type + = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, ptr_type, nav_idx); return ns->owner_type; } } @@ -4821,7 +4760,7 @@ static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) { if (tag == ZIR_INST_FUNC || tag == ZIR_INST_FUNC_FANCY) { // Create a temp sema to parse func info from the ZIR. Sema tmp_sema; - semaInit(&tmp_sema, s_module_ip, *zir); + semaInit(&tmp_sema, sema->zcu, *zir); FuncZirInfo fi = parseFuncZir(&tmp_sema, inst); semaDeinit(&tmp_sema); @@ -4833,15 +4772,15 @@ static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) { if (fi.ret_ty_body_len == 1) { uint32_t ret_ref = zir->extra[fi.ret_ty_ref_pos]; InternPoolIndex resolved - = resolveZirTypeRef(zir, ret_ref, ns_idx, file_idx); + = resolveZirTypeRef(sema, zir, ret_ref, ns_idx, file_idx); if (resolved != IP_INDEX_NONE) ret_ty = resolved; } else if (fi.ret_ty_body_len == 2) { // 2-instruction body: type instruction + break_inline. // Resolve the first instruction as a type. uint32_t type_inst = zir->extra[fi.ret_ty_ref_pos]; - InternPoolIndex resolved - = resolveZirTypeInst(zir, type_inst, ns_idx, file_idx); + InternPoolIndex resolved = resolveZirTypeInst( + sema, zir, type_inst, ns_idx, file_idx); if (resolved != IP_INDEX_NONE) ret_ty = resolved; } @@ -4876,15 +4815,15 @@ static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) { uint8_t cc = 0; if (fi.is_inline) { cc = CC_TAG_INLINE; - (void)getBuiltinTypeC(2); // CallingConvention + (void)getBuiltinTypeC(sema, 2); // CallingConvention } InternPoolIndex ft - = internFuncType(ret_ty, param_count, cc, false); - InternPoolIndex fd = internFuncDecl(nav_idx, ft); - Nav* wnav = ipGetNav(nav_idx); + = internFuncType(sema, ret_ty, param_count, cc, false); + InternPoolIndex fd = internFuncDecl(sema, nav_idx, ft); + Nav* wnav = ipGetNav(sema->ip, nav_idx); wnav->resolved_type = fd; - InternPoolIndex ptr_ty = internPtrConst(ft); - (void)internNavPtr(ptr_ty, nav_idx); + InternPoolIndex ptr_ty = internPtrConst(sema, ft); + (void)internNavPtr(sema, ptr_ty, nav_idx); return fd; } } @@ -4904,16 +4843,17 @@ static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) { // Resolve via doImport (handles "builtin", "root", // "std", and file paths). - uint32_t import_file_idx - = doImport(s_loaded_modules[file_idx].source_dir, import_path); + uint32_t import_file_idx = doImport( + sema, sema->zcu->files[file_idx].source_dir, import_path); if (import_file_idx == UINT32_MAX) break; - InternPoolIndex struct_type = s_file_root_type[import_file_idx]; + InternPoolIndex struct_type + = sema->zcu->file_root_types[import_file_idx]; if (struct_type == 0 && import_file_idx > 0) break; - Nav* wnav = ipGetNav(nav_idx); + Nav* wnav = ipGetNav(sema->ip, nav_idx); wnav->resolved_type = struct_type; return struct_type; } @@ -4922,15 +4862,15 @@ static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) { // Fallback: for non-type declarations (const values), use // analyzeNavValC to evaluate the body at comptime. // Ported from PerThread.zig analyzeNavVal fallthrough. - return analyzeNavValC(nav_idx); + return analyzeNavValC(sema, nav_idx); } // --- findFileByPathSuffix --- // Find a loaded module by path suffix. Returns file index or UINT32_MAX. -static uint32_t findFileByPathSuffix(const char* suffix) { +static uint32_t findFileByPathSuffix(Sema* sema, const char* suffix) { size_t slen = strlen(suffix); - for (uint32_t i = 0; i < s_num_loaded_modules; i++) { - const char* p = s_loaded_modules[i].path; + for (uint32_t i = 0; i < sema->zcu->num_files; i++) { + const char* p = sema->zcu->files[i].path; size_t plen = strlen(p); if (plen >= slen && strcmp(p + plen - slen, suffix) == 0) return i; @@ -4940,35 +4880,35 @@ static uint32_t findFileByPathSuffix(const char* suffix) { // Forward declarations for functions used by resolveCgBuiltinField. static InternPoolIndex internEnumTag( - InternPoolIndex enum_ty, InternPoolIndex int_val); + Sema* sema, InternPoolIndex enum_ty, InternPoolIndex int_val); // resolveEnumFieldInTarget: look up an enum field by name in a type // declared in std.Target. Returns the interned enum_tag, or IP_INDEX_NONE. // Ported from the pattern in Compilation.Config where target-derived // enum values are resolved through the standard library's type system. static InternPoolIndex resolveEnumFieldInTarget( - const char* type_name, const char* field_name) { - uint32_t tfi = findFileByPathSuffix("/std/Target.zig"); + Sema* sema, const char* type_name, const char* field_name) { + uint32_t tfi = findFileByPathSuffix(sema, "/std/Target.zig"); if (tfi == UINT32_MAX) return IP_INDEX_NONE; - uint32_t tns = s_file_namespace[tfi]; - uint32_t nav = findNavInNamespace(tns, type_name); + uint32_t tns = sema->zcu->file_namespaces[tfi]; + uint32_t nav = findNavInNamespace(sema, tns, type_name); if (nav == UINT32_MAX) return IP_INDEX_NONE; - InternPoolIndex ty = ensureNavValUpToDate(nav); + InternPoolIndex ty = ensureNavValUpToDate(sema, nav); if (ty == IP_INDEX_NONE) return IP_INDEX_NONE; const Zir* tzir = NULL; - uint32_t enum_inst = findEnumDeclForNav(nav, &tzir); + uint32_t enum_inst = findEnumDeclForNav(sema, nav, &tzir); if (enum_inst == UINT32_MAX) return IP_INDEX_NONE; uint32_t fidx = findEnumFieldByName(tzir, enum_inst, field_name); if (fidx == UINT32_MAX) return IP_INDEX_NONE; - InternPoolIndex iv = getEnumFieldIntVal(tzir, enum_inst, fidx); + InternPoolIndex iv = getEnumFieldIntVal(sema, tzir, enum_inst, fidx); if (iv == IP_INDEX_NONE) return IP_INDEX_NONE; - return internEnumTag(ty, iv); + return internEnumTag(sema, ty, iv); } // --- resolveCgBuiltinField --- @@ -4981,9 +4921,9 @@ static InternPoolIndex resolveEnumFieldInTarget( // Ported from PerThread.zig analyzeNavVal for compiler-generated // builtin module fields. static InternPoolIndex resolveCgBuiltinField( - uint32_t field_nav, const char* field_name) { + Sema* sema, uint32_t field_nav, const char* field_name) { // Already resolved — return cached value. - const Nav* nav = ipGetNav(field_nav); + const Nav* nav = ipGetNav(sema->ip, field_nav); if (nav->resolved_type != IP_INDEX_NONE) return nav->resolved_type; @@ -4991,21 +4931,23 @@ static InternPoolIndex resolveCgBuiltinField( if (strcmp(field_name, "is_test") == 0) { // Ported from Compilation.Config.is_test. - result = readBool(&s_config_is_test) ? IP_INDEX_BOOL_TRUE - : IP_INDEX_BOOL_FALSE; + result = readBool(&sema->zcu->comp->config.is_test) + ? IP_INDEX_BOOL_TRUE + : IP_INDEX_BOOL_FALSE; } else if (strcmp(field_name, "object_format") == 0) { - // Look up s_config_object_format in Target.ObjectFormat enum. - // Ported from Compilation.Config.object_format. - result - = resolveEnumFieldInTarget("ObjectFormat", s_config_object_format); + // Look up sema->zcu->comp->config.object_format in Target.ObjectFormat + // enum. Ported from Compilation.Config.object_format. + result = resolveEnumFieldInTarget( + sema, "ObjectFormat", sema->zcu->comp->config.object_format); } else if (strcmp(field_name, "link_mode") == 0) { - // Look up s_config_link_mode in Target.LinkMode enum. + // Look up sema->zcu->comp->config.link_mode in Target.LinkMode enum. // Ported from Compilation.Config.link_mode. - result = resolveEnumFieldInTarget("LinkMode", s_config_link_mode); + result = resolveEnumFieldInTarget( + sema, "LinkMode", sema->zcu->comp->config.link_mode); } if (result != IP_INDEX_NONE) { - Nav* wnav = ipGetNav(field_nav); + Nav* wnav = ipGetNav(sema->ip, field_nav); wnav->resolved_type = result; } return result; @@ -5015,31 +4957,32 @@ static InternPoolIndex resolveCgBuiltinField( // Create an enum_tag IP entry for a specific value of an enum type. // The int value must already be interned (e.g. int_small(u64, val)). static InternPoolIndex internEnumTag( - InternPoolIndex enum_ty, InternPoolIndex int_val) { + Sema* sema, InternPoolIndex enum_ty, InternPoolIndex int_val) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_ENUM_TAG; key.data.enum_tag.ty = enum_ty; key.data.enum_tag.int_val = int_val; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internTypedInt --- // Intern a typed integer value. Creates int_small if small enough. -static InternPoolIndex internTypedInt(InternPoolIndex ty, uint64_t val) { +static InternPoolIndex internTypedInt( + Sema* sema, InternPoolIndex ty, uint64_t val) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_INT; key.data.int_val.ty = ty; key.data.int_val.value_lo = val; key.data.int_val.is_negative = false; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internFuncType --- // Create a function type IP entry. // Ported from InternPool.zig getFuncType. -static InternPoolIndex internFuncType(InternPoolIndex return_type, +static InternPoolIndex internFuncType(Sema* sema, InternPoolIndex return_type, uint32_t param_count, uint8_t cc, bool is_noinline) { InternPoolKey key; memset(&key, 0, sizeof(key)); @@ -5048,20 +4991,20 @@ static InternPoolIndex internFuncType(InternPoolIndex return_type, key.data.func_type.param_count = param_count; key.data.func_type.cc = cc; key.data.func_type.is_noinline = is_noinline; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- internFuncDecl --- // Create a func_decl IP entry for a function declaration. // Ported from InternPool.zig getFuncDecl. static InternPoolIndex internFuncDecl( - uint32_t owner_nav, InternPoolIndex func_type) { + Sema* sema, uint32_t owner_nav, InternPoolIndex func_type) { InternPoolKey key; memset(&key, 0, sizeof(key)); key.tag = IP_KEY_FUNC; key.data.func_decl.owner_nav = owner_nav; key.data.func_decl.ty = func_type; - return ipIntern(s_module_ip, key); + return ipIntern(sema->ip, key); } // --- findDeclImportPathFromZir --- @@ -5166,8 +5109,8 @@ static void normalizePath(char* path) { *out = '\0'; } -static bool resolveImportPath(const char* source_dir, const char* import_path, - char* out_full, size_t out_size) { +static bool resolveImportPath(const Sema* sema, const char* source_dir, + const char* import_path, char* out_full, size_t out_size) { const char* rel = import_path; if (rel[0] == '.' && rel[1] == '/') rel += 2; @@ -5189,9 +5132,9 @@ static bool resolveImportPath(const char* source_dir, const char* import_path, } // Bare module names (e.g. "std") resolve via module_root. - if (s_global_module_root) { - snprintf(out_full, out_size, "%s/lib/%s/%s.zig", s_global_module_root, - import_path, import_path); + if (sema->zcu->comp->config.module_root) { + snprintf(out_full, out_size, "%s/lib/%s/%s.zig", + sema->zcu->comp->config.module_root, import_path, import_path); return true; } return false; @@ -5205,14 +5148,15 @@ static bool resolveImportPath(const char* source_dir, const char* import_path, // This matches the Zig compiler's demand-driven resolution order: // type_struct → type_pointer → ptr_nav, then recurse. -static void resolveModuleDeclImports(uint32_t file_idx, uint32_t depth) { - if (depth == 0 || file_idx >= s_num_loaded_modules) +static void resolveModuleDeclImports( + Sema* sema, uint32_t file_idx, uint32_t depth) { + if (depth == 0 || file_idx >= sema->zcu->num_files) return; - LoadedModule* mod = &s_loaded_modules[file_idx]; + ZcuFile* mod = &sema->zcu->files[file_idx]; if (!mod->has_zir) return; - uint32_t ns_idx = s_file_namespace[file_idx]; - SemaNamespace* ns = &s_namespaces[ns_idx]; + uint32_t ns_idx = sema->zcu->file_namespaces[file_idx]; + ZcuNamespace* ns = &sema->zcu->namespaces[ns_idx]; const Zir* zir = &mod->zir; // Process all named declarations (pub first, then priv — matching @@ -5223,7 +5167,7 @@ static void resolveModuleDeclImports(uint32_t file_idx, uint32_t depth) { for (uint32_t i = 0; i < count; i++) { uint32_t nav_idx = navs[i]; - Nav* nav = ipGetNav(nav_idx); + Nav* nav = ipGetNav(sema->ip, nav_idx); // Check if this declaration is an import. const char* import_path @@ -5232,10 +5176,12 @@ static void resolveModuleDeclImports(uint32_t file_idx, uint32_t depth) { continue; // Resolve via doImport (handles all special names). - uint32_t import_file_idx = doImport(mod->source_dir, import_path); + uint32_t import_file_idx + = doImport(sema, mod->source_dir, import_path); if (import_file_idx == UINT32_MAX) continue; - InternPoolIndex struct_type = s_file_root_type[import_file_idx]; + InternPoolIndex struct_type + = sema->zcu->file_root_types[import_file_idx]; if (struct_type == 0 && import_file_idx > 0) continue; // failed to create struct @@ -5243,12 +5189,13 @@ static void resolveModuleDeclImports(uint32_t file_idx, uint32_t depth) { // Import declarations have value-type `type`, so the pointer // is `*const type` (not *const struct). This matches upstream // analyzeNavRefInner which gets the declared type. - InternPoolIndex ptr_type = internPtrConst(IP_INDEX_TYPE_TYPE); + InternPoolIndex ptr_type + = internPtrConst(sema, IP_INDEX_TYPE_TYPE); nav->resolved_type = struct_type; - (void)internNavPtr(ptr_type, nav_idx); + (void)internNavPtr(sema, ptr_type, nav_idx); // Recurse depth-first into imported file's declarations. - resolveModuleDeclImports(import_file_idx, depth - 1); + resolveModuleDeclImports(sema, import_file_idx, depth - 1); } } } @@ -5261,10 +5208,11 @@ static void populateDeclTableFromZir(Sema* sema, const Zir* zir); // Ported from src/Zcu/PerThread.zig analyzeComptimeUnit (lines 853-926). // Side effects (IP entries from @import, field access, etc.) are the // primary purpose — the comptime block itself produces void. -static void analyzeComptimeUnit(uint32_t file_idx, uint32_t comptime_decl) { - if (!s_loaded_modules[file_idx].has_zir) +static void analyzeComptimeUnit( + Sema* sema, uint32_t file_idx, uint32_t comptime_decl) { + if (!sema->zcu->files[file_idx].has_zir) return; - const Zir* zir = &s_loaded_modules[file_idx].zir; + const Zir* zir = &sema->zcu->files[file_idx].zir; // Get the value body from the comptime declaration. const uint32_t* body = NULL; @@ -5277,10 +5225,9 @@ static void analyzeComptimeUnit(uint32_t file_idx, uint32_t comptime_decl) { // Ported from analyzeComptimeUnit: sema is created with the // module's ZIR, fn_ret_ty = void (comptime blocks are always void). Sema ct_sema; - semaInit(&ct_sema, s_module_ip, *zir); + semaInit(&ct_sema, sema->zcu, *zir); ct_sema.file_idx = file_idx; - ct_sema.source_dir = s_loaded_modules[file_idx].source_dir; - ct_sema.module_root = s_global_module_root; + ct_sema.source_dir = sema->zcu->files[file_idx].source_dir; // Populate the decl table so nested imports resolve correctly. populateDeclTableFromZir(&ct_sema, zir); @@ -5303,28 +5250,29 @@ static void analyzeComptimeUnit(uint32_t file_idx, uint32_t comptime_decl) { // Resolves an import string to a file index. Handles special module // names ("builtin", "root", "std") and regular file paths. // Returns file_idx, or UINT32_MAX if the import cannot be resolved. -static uint32_t doImport(const char* source_dir, const char* import_string) { +static uint32_t doImport( + Sema* sema, const char* source_dir, const char* import_string) { // Special module names — ported from PerThread.zig doImport // lines 1982-1990. if (strcmp(import_string, "builtin") == 0) { // @import("builtin") → compiler-generated builtin module. - InternPoolIndex cg = ensureCgBuiltinModule(); + InternPoolIndex cg = ensureCgBuiltinModule(sema); if (cg == IP_INDEX_NONE) return UINT32_MAX; // Find the CG builtin's file_idx. - for (uint32_t fi = 0; fi < s_num_loaded_modules; fi++) { - if (s_file_root_type[fi] == cg) + for (uint32_t fi = 0; fi < sema->zcu->num_files; fi++) { + if (sema->zcu->file_root_types[fi] == cg) return fi; } return UINT32_MAX; } if (strcmp(import_string, "root") == 0) { // @import("root") → user's root module. - return s_root_file_idx; + return sema->zcu->root_file_idx; } if (strcmp(import_string, "std") == 0) { // @import("std") → standard library. - return s_std_file_idx; + return sema->zcu->std_file_idx; } // Regular file import — resolve path and load. @@ -5332,9 +5280,9 @@ static uint32_t doImport(const char* source_dir, const char* import_string) { return UINT32_MAX; char import_full[1024]; if (!resolveImportPath( - source_dir, import_string, import_full, sizeof(import_full))) + sema, source_dir, import_string, import_full, sizeof(import_full))) return UINT32_MAX; - return ensureFileAnalyzedC(import_full); + return ensureFileAnalyzedC(sema, import_full); } // --- ensureFileAnalyzedC --- @@ -5343,8 +5291,8 @@ static uint32_t doImport(const char* source_dir, const char* import_string) { // namespace, and Nav entries matching the Zig compiler's sequence. // Returns the file index, or UINT32_MAX on failure. -static uint32_t ensureFileAnalyzedC(const char* full_path) { - if (!s_module_ip) +static uint32_t ensureFileAnalyzedC(Sema* sema, const char* full_path) { + if (!sema->ip) return UINT32_MAX; // Normalize: strip leading "./" to avoid duplicate entries for the @@ -5353,23 +5301,23 @@ static uint32_t ensureFileAnalyzedC(const char* full_path) { full_path += 2; // Check if already tracked. - for (uint32_t i = 0; i < s_num_loaded_modules; i++) { - if (strcmp(s_loaded_modules[i].path, full_path) == 0) { + for (uint32_t i = 0; i < sema->zcu->num_files; i++) { + if (strcmp(sema->zcu->files[i].path, full_path) == 0) { // Already loaded. Ensure it's been analyzed. - if (!s_loaded_modules[i].analyzed && s_loaded_modules[i].has_zir) { - s_loaded_modules[i].analyzed = true; - (void)createFileRootStructC(i, &s_loaded_modules[i].zir); + if (!sema->zcu->files[i].analyzed && sema->zcu->files[i].has_zir) { + sema->zcu->files[i].analyzed = true; + (void)createFileRootStructC(sema, i, &sema->zcu->files[i].zir); } return i; } } - if (s_num_loaded_modules >= MAX_LOADED_MODULES) + if (sema->zcu->num_files >= ZCU_MAX_FILES) return UINT32_MAX; // Register new module. - uint32_t file_idx = s_num_loaded_modules++; - LoadedModule* mod = &s_loaded_modules[file_idx]; + uint32_t file_idx = sema->zcu->num_files++; + ZcuFile* mod = &sema->zcu->files[file_idx]; memset(mod, 0, sizeof(*mod)); snprintf(mod->path, sizeof(mod->path), "%s", full_path); @@ -5412,48 +5360,48 @@ static uint32_t ensureFileAnalyzedC(const char* full_path) { if (mod->has_zir) { mod->analyzed = true; - (void)createFileRootStructC(file_idx, &mod->zir); + (void)createFileRootStructC(sema, file_idx, &mod->zir); } return file_idx; } // Reset module tracking state. -static void resetModuleTracking(void) { +static void resetModuleTracking(Sema* sema) { // Free ZIR/AST data from loaded modules. - for (uint32_t i = 0; i < s_num_loaded_modules; i++) { - if (s_loaded_modules[i].has_zir) { - zirDeinit(&s_loaded_modules[i].zir); - astDeinit(&s_loaded_modules[i].ast); + for (uint32_t i = 0; i < sema->zcu->num_files; i++) { + if (sema->zcu->files[i].has_zir) { + zirDeinit(&sema->zcu->files[i].zir); + astDeinit(&sema->zcu->files[i].ast); } } - s_num_loaded_modules = 0; - s_next_struct_hash = 0; - s_module_ip = NULL; - s_root_file_idx = 0; - s_num_namespaces = 0; - s_std_file_idx = UINT32_MAX; - s_builtin_file_idx = UINT32_MAX; - s_cg_builtin_nav = UINT32_MAX; - s_cg_builtin_ns_idx = UINT32_MAX; - s_global_module_root = NULL; - s_target_cpu_arch_name = NULL; - s_target_cpu_model_name = NULL; - ipResetNavs(); - memset(s_file_root_type, 0, sizeof(s_file_root_type)); - memset(s_file_namespace, 0, sizeof(s_file_namespace)); - memset(s_struct_layout_resolved, 0, sizeof(s_struct_layout_resolved)); - memset(s_struct_fully_resolved, 0, sizeof(s_struct_fully_resolved)); - memset(s_union_fully_resolved, 0, sizeof(s_union_fully_resolved)); - s_num_union_tag_enums = 0; - s_memoized_main_resolved = false; - s_full_memoized_resolved = false; - memset(s_builtin_decl_values, 0, sizeof(s_builtin_decl_values)); - s_preamble_memoized_start = 0; - s_preamble_memoized_end = 0; - s_preamble_cc_start = 0; - s_preamble_cc_end = 0; - s_preamble_builtin_nav_count = 0; + sema->zcu->num_files = 0; + sema->zcu->next_struct_hash = 0; + sema->zcu->root_file_idx = 0; + sema->zcu->num_namespaces = 0; + sema->zcu->std_file_idx = UINT32_MAX; + sema->zcu->builtin_file_idx = UINT32_MAX; + sema->zcu->cg_builtin_nav = UINT32_MAX; + sema->zcu->cg_builtin_ns_idx = UINT32_MAX; + ipResetNavs(sema->ip); + memset(sema->zcu->file_root_types, 0, sizeof(sema->zcu->file_root_types)); + memset(sema->zcu->file_namespaces, 0, sizeof(sema->zcu->file_namespaces)); + memset(sema->zcu->struct_layout_resolved, 0, + sizeof(sema->zcu->struct_layout_resolved)); + memset(sema->zcu->struct_fully_resolved, 0, + sizeof(sema->zcu->struct_fully_resolved)); + memset(sema->zcu->union_fully_resolved, 0, + sizeof(sema->zcu->union_fully_resolved)); + sema->zcu->num_union_tag_enums = 0; + sema->zcu->memoized_main_resolved = false; + sema->zcu->full_memoized_resolved = false; + memset(sema->zcu->builtin_decl_values, 0, + sizeof(sema->zcu->builtin_decl_values)); + sema->zcu->preamble_memoized_start = 0; + sema->zcu->preamble_memoized_end = 0; + sema->zcu->preamble_cc_start = 0; + sema->zcu->preamble_cc_end = 0; + sema->zcu->preamble_builtin_nav_count = 0; } // populateDeclTableFromZir: populate sema's decl table from a ZIR module. @@ -6117,8 +6065,9 @@ static InternPoolIndex registerStructTypeFromZir( // module (freeing the old ones). On failure, returns UINT32_MAX. // If out_resolved_dir is non-NULL and a re-export was followed, writes // the resolved target module's source directory there. -static uint32_t findFuncInModuleZir(const char* source_dir, Zir* zir, Ast* ast, - const char* func_name, char* out_resolved_dir, size_t resolved_dir_size) { +static uint32_t findFuncInModuleZir(Sema* sema, const char* source_dir, + Zir* zir, Ast* ast, const char* func_name, char* out_resolved_dir, + size_t resolved_dir_size) { uint32_t func_inst = findFuncInstInZir(zir, func_name); if (func_inst != UINT32_MAX) return func_inst; @@ -6134,7 +6083,8 @@ static uint32_t findFuncInModuleZir(const char* source_dir, Zir* zir, Ast* ast, snprintf( reexport_import, sizeof(reexport_import), "%s", reexport_import_ptr); Ast target_ast; - Zir target_zir = loadImportZir(source_dir, reexport_import, &target_ast); + Zir target_zir + = loadImportZir(sema, source_dir, reexport_import, &target_ast); if (target_zir.inst_len == 0) return UINT32_MAX; func_inst = findFuncInstInZir(&target_zir, reexport_field); @@ -6237,29 +6187,29 @@ static AirInstRef comptimeFieldCall(Sema* sema, SemaBlock* block, && sema->ip->items[ns_type].tag == IP_KEY_PTR_TYPE) { ns_type = sema->ip->items[ns_type].data.ptr_type.child; } - uint32_t ns_idx = findNamespaceForType(ns_type); + uint32_t ns_idx = findNamespaceForType(sema, ns_type); if (ns_idx == UINT32_MAX) return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE); // Look up the function by field name. const char* fn_name = (const char*)&sema->code.string_bytes[field_name_start]; - uint32_t fn_nav_idx = findNavInNamespace(ns_idx, fn_name); + uint32_t fn_nav_idx = findNavInNamespace(sema, ns_idx, fn_name); if (fn_nav_idx == UINT32_MAX) return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE); // Ensure the function nav is resolved (creates func_type + // func_decl + ptr_type + ptr_nav entries). - (void)ensureNavValUpToDate(fn_nav_idx); + (void)ensureNavValUpToDate(sema, fn_nav_idx); // Get the function nav's ZIR. - const Nav* fn_nav = ipGetNav(fn_nav_idx); + const Nav* fn_nav = ipGetNav(sema->ip, fn_nav_idx); uint32_t fn_ns_idx = fn_nav->namespace_idx; - const SemaNamespace* fn_ns = &s_namespaces[fn_ns_idx]; + const ZcuNamespace* fn_ns = &sema->zcu->namespaces[fn_ns_idx]; uint32_t fn_file_idx = fn_ns->file_idx; - if (!s_loaded_modules[fn_file_idx].has_zir) + if (!sema->zcu->files[fn_file_idx].has_zir) return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE); - const Zir* fn_zir = &s_loaded_modules[fn_file_idx].zir; + const Zir* fn_zir = &sema->zcu->files[fn_file_idx].zir; // Get function info from the ZIR declaration. // Parse the declaration to find the function value body. @@ -6284,10 +6234,9 @@ static AirInstRef comptimeFieldCall(Sema* sema, SemaBlock* block, // Create a mini-sema with the function's ZIR to parse func info. Sema fn_sema; - semaInit(&fn_sema, s_module_ip, *fn_zir); + semaInit(&fn_sema, sema->zcu, *fn_zir); fn_sema.file_idx = fn_file_idx; - fn_sema.source_dir = s_loaded_modules[fn_file_idx].source_dir; - fn_sema.module_root = s_global_module_root; + fn_sema.source_dir = sema->zcu->files[fn_file_idx].source_dir; // Parse function info (parameters, body). FuncZirInfo fi = parseFuncZir(&fn_sema, func_zir_inst); @@ -6353,7 +6302,7 @@ static AirInstRef comptimeFieldCall(Sema* sema, SemaBlock* block, // types because they get deduped to existing entries). { // Get function type to extract return type. - const Nav* fn_nav_resolved = ipGetNav(fn_nav_idx); + const Nav* fn_nav_resolved = ipGetNav(sema->ip, fn_nav_idx); InternPoolIndex fn_decl_ip = fn_nav_resolved->resolved_type; if (fn_decl_ip != IP_INDEX_NONE && sema->ip->items[fn_decl_ip].tag == IP_KEY_FUNC) { @@ -6371,12 +6320,14 @@ static AirInstRef comptimeFieldCall(Sema* sema, SemaBlock* block, // the Zig compiler creates no new IP entries for the frame. if (obj_type >= ZIR_REF_START_INDEX || ret_ty >= ZIR_REF_START_INDEX) { - InternPoolIndex param_ptr_ty = internPtrConst(obj_type); - (void)internPtrUav(param_ptr_ty, obj_ip); - InternPoolIndex ret_mut_ptr = internPtrMutable(ret_ty); - (void)internUndef(ret_ty); + InternPoolIndex param_ptr_ty + = internPtrConst(sema, obj_type); + (void)internPtrUav(sema, param_ptr_ty, obj_ip); + InternPoolIndex ret_mut_ptr + = internPtrMutable(sema, ret_ty); + (void)internUndef(sema, ret_ty); InternPoolIndex ret_alloc - = internPtrComptimeAlloc(ret_mut_ptr, 0); + = internPtrComptimeAlloc(sema, ret_mut_ptr, 0); fn_sema.comptime_ret_ptr = ret_alloc; } } @@ -6422,16 +6373,16 @@ static AirInstRef comptimeFieldCall(Sema* sema, SemaBlock* block, InternPoolIndex result_ip = AIR_REF_IS_IP(result) ? AIR_REF_TO_IP(result) : IP_INDEX_VOID_VALUE; - const Nav* fn_nav2 = ipGetNav(fn_nav_idx); + const Nav* fn_nav2 = ipGetNav(sema->ip, fn_nav_idx); InternPoolIndex func_ip = fn_nav2->resolved_type; if (func_ip != IP_INDEX_NONE - && s_module_ip->items[func_ip].tag == IP_KEY_FUNC) { + && sema->ip->items[func_ip].tag == IP_KEY_FUNC) { InternPoolKey mc_key; memset(&mc_key, 0, sizeof(mc_key)); mc_key.tag = IP_KEY_MEMOIZED_CALL; mc_key.data.memoized_call.func = func_ip; mc_key.data.memoized_call.result = result_ip; - (void)ipIntern(s_module_ip, mc_key); + (void)ipIntern(sema->ip, mc_key); } } @@ -6674,13 +6625,15 @@ static AirInstRef zirCall( // Load base import (e.g. std.zig). Ast base_ast; memset(&base_ast, 0, sizeof(base_ast)); - Zir base_zir = loadStdImportZir(sema->module_root, - sema->source_dir, base_import, &base_ast); + Zir base_zir = loadStdImportZir(sema, + sema->zcu->comp->config.module_root, sema->source_dir, + base_import, &base_ast); if (base_zir.inst_len > 0) { // Follow intermediate fields (all but last). char cur_dir[1024]; - computeSourceDir(sema->module_root, sema->source_dir, - base_import, cur_dir, sizeof(cur_dir)); + computeSourceDir(sema->zcu->comp->config.module_root, + sema->source_dir, base_import, cur_dir, + sizeof(cur_dir)); Zir cur_zir = base_zir; Ast cur_ast = base_ast; for (uint32_t fi = 0; fi + 1 < nfields; fi++) { @@ -6707,8 +6660,8 @@ static AirInstRef zirCall( // Load the sub-module. Ast next_ast; memset(&next_ast, 0, sizeof(next_ast)); - Zir next_zir - = loadImportZir(cur_dir, sub_import, &next_ast); + Zir next_zir = loadImportZir( + sema, cur_dir, sub_import, &next_ast); // Compute new source dir BEFORE freeing cur_zir, // since sub_import points into cur_zir string bytes. char new_dir[1024]; @@ -6732,8 +6685,8 @@ static AirInstRef zirCall( if (fn_import) { Ast fn_ast; memset(&fn_ast, 0, sizeof(fn_ast)); - Zir fn_zir - = loadImportZir(cur_dir, fn_import, &fn_ast); + Zir fn_zir = loadImportZir( + sema, cur_dir, fn_import, &fn_ast); // Compute source dir BEFORE freeing cur_zir, // since fn_import points into cur_zir string // bytes. @@ -6745,10 +6698,10 @@ static AirInstRef zirCall( if (fn_zir.inst_len > 0) { // Try direct lookup first, then follow // re-exports (e.g. scalbn -> ldexp). - func_inst - = findFuncInModuleZir(fn_src_dir, &fn_zir, - &fn_ast, fn_name, import_source_dir, - sizeof(import_source_dir)); + func_inst = findFuncInModuleZir(sema, + fn_src_dir, &fn_zir, &fn_ast, fn_name, + import_source_dir, + sizeof(import_source_dir)); if (func_inst != UINT32_MAX) { // If findFuncInModuleZir found it // directly (no re-export), it did @@ -6790,8 +6743,9 @@ static AirInstRef zirCall( // fields[0] = "panic" Ast base_ast; memset(&base_ast, 0, sizeof(base_ast)); - Zir base_zir = loadStdImportZir(sema->module_root, - sema->source_dir, base_import, &base_ast); + Zir base_zir = loadStdImportZir(sema, + sema->zcu->comp->config.module_root, sema->source_dir, + base_import, &base_ast); if (base_zir.inst_len > 0) { const char* field_name = fields[0]; func_inst = findFuncInstInZir(&base_zir, field_name); @@ -6801,8 +6755,8 @@ static AirInstRef zirCall( import_zir = base_zir; import_ast = base_ast; is_cross_module = true; - computeSourceDir(sema->module_root, sema->source_dir, - base_import, import_source_dir, + computeSourceDir(sema->zcu->comp->config.module_root, + sema->source_dir, base_import, import_source_dir, sizeof(import_source_dir)); } else { zirDeinit(&base_zir); @@ -6829,12 +6783,12 @@ static AirInstRef zirCall( const char* field_name = (const char*)&sema->code.string_bytes[callee_name_idx]; import_zir = loadImportZir( - sema->source_dir, import_path, &import_ast); + sema, sema->source_dir, import_path, &import_ast); if (import_zir.inst_len > 0) { - computeSourceDir(sema->module_root, sema->source_dir, - import_path, import_source_dir, + computeSourceDir(sema->zcu->comp->config.module_root, + sema->source_dir, import_path, import_source_dir, sizeof(import_source_dir)); - func_inst = findFuncInModuleZir(import_source_dir, + func_inst = findFuncInModuleZir(sema, import_source_dir, &import_zir, &import_ast, field_name, import_source_dir, sizeof(import_source_dir)); if (func_inst != UINT32_MAX) { @@ -6865,8 +6819,9 @@ static AirInstRef zirCall( // it (which may itself be an @import). Ast base_ast; memset(&base_ast, 0, sizeof(base_ast)); - Zir base_zir = loadStdImportZir(sema->module_root, - sema->source_dir, chain_import, &base_ast); + Zir base_zir = loadStdImportZir(sema, + sema->zcu->comp->config.module_root, sema->source_dir, + chain_import, &base_ast); if (base_zir.inst_len > 0) { // Find chain_field in base module; if it's // also an @import, follow it. @@ -6880,11 +6835,12 @@ static AirInstRef zirCall( sub_import_ptr); // Compute source_dir for the base import. char base_dir[1024]; - computeSourceDir(sema->module_root, + computeSourceDir( + sema->zcu->comp->config.module_root, sema->source_dir, chain_import, base_dir, sizeof(base_dir)); import_zir = loadImportZir( - base_dir, sub_import, &import_ast); + sema, base_dir, sub_import, &import_ast); zirDeinit(&base_zir); astDeinit(&base_ast); if (import_zir.inst_len > 0) { @@ -6894,7 +6850,7 @@ static AirInstRef zirCall( computeSourceDir(NULL, base_dir, sub_import, import_source_dir, sizeof(import_source_dir)); - func_inst = findFuncInModuleZir( + func_inst = findFuncInModuleZir(sema, import_source_dir, &import_zir, &import_ast, field_name, import_source_dir, sizeof(import_source_dir)); @@ -6917,7 +6873,8 @@ static AirInstRef zirCall( import_zir = base_zir; import_ast = base_ast; is_cross_module = true; - computeSourceDir(sema->module_root, + computeSourceDir( + sema->zcu->comp->config.module_root, sema->source_dir, chain_import, import_source_dir, sizeof(import_source_dir)); @@ -6969,25 +6926,27 @@ static AirInstRef zirCall( // Load std module, find sub-module Ast alias_ast; memset(&alias_ast, 0, sizeof(alias_ast)); - Zir alias_zir = loadStdImportZir(sema->module_root, + Zir alias_zir = loadStdImportZir(sema, + sema->zcu->comp->config.module_root, sema->source_dir, alias_import, &alias_ast); if (alias_zir.inst_len > 0) { const char* sub_path = findDeclImportPathInZir( &alias_zir, alias_field); if (sub_path) { char alias_dir[1024]; - computeSourceDir(sema->module_root, + computeSourceDir( + sema->zcu->comp->config.module_root, sema->source_dir, alias_import, alias_dir, sizeof(alias_dir)); - import_zir = loadImportZir( - alias_dir, sub_path, &import_ast); + import_zir = loadImportZir(sema, alias_dir, + sub_path, &import_ast); zirDeinit(&alias_zir); astDeinit(&alias_ast); if (import_zir.inst_len > 0) { computeSourceDir(NULL, alias_dir, sub_path, import_source_dir, sizeof(import_source_dir)); - func_inst = findFuncInModuleZir( + func_inst = findFuncInModuleZir(sema, import_source_dir, &import_zir, &import_ast, fn_field, import_source_dir, @@ -7009,7 +6968,8 @@ static AirInstRef zirCall( const char* mid_field = fn_field; Ast base_ast; memset(&base_ast, 0, sizeof(base_ast)); - Zir base_zir = loadStdImportZir(sema->module_root, + Zir base_zir = loadStdImportZir(sema, + sema->zcu->comp->config.module_root, sema->source_dir, base_import, &base_ast); if (base_zir.inst_len > 0) { const char* sub_import_ptr @@ -7021,11 +6981,12 @@ static AirInstRef zirCall( snprintf(sub_import, sizeof(sub_import), "%s", sub_import_ptr); char base_dir[1024]; - computeSourceDir(sema->module_root, + computeSourceDir( + sema->zcu->comp->config.module_root, sema->source_dir, base_import, base_dir, sizeof(base_dir)); - import_zir = loadImportZir( - base_dir, sub_import, &import_ast); + import_zir = loadImportZir(sema, base_dir, + sub_import, &import_ast); zirDeinit(&base_zir); astDeinit(&base_ast); if (import_zir.inst_len > 0) { @@ -7037,7 +6998,7 @@ static AirInstRef zirCall( computeSourceDir(NULL, base_dir, sub_import, import_source_dir, sizeof(import_source_dir)); - func_inst = findFuncInModuleZir( + func_inst = findFuncInModuleZir(sema, import_source_dir, &import_zir, &import_ast, fn_name, import_source_dir, @@ -7085,9 +7046,9 @@ static AirInstRef zirCall( if (base_imp) { Ast b_ast; memset(&b_ast, 0, sizeof(b_ast)); - Zir b_zir = loadStdImportZir( - sema->module_root, sema->source_dir, - base_imp, &b_ast); + Zir b_zir = loadStdImportZir(sema, + sema->zcu->comp->config.module_root, + sema->source_dir, base_imp, &b_ast); if (b_zir.inst_len > 0) { const char* sp_ptr = findDeclImportPathInZir( @@ -7098,11 +7059,13 @@ static AirInstRef zirCall( snprintf( sp, sizeof(sp), "%s", sp_ptr); char bd[1024]; - computeSourceDir(sema->module_root, + computeSourceDir( + sema->zcu->comp->config + .module_root, sema->source_dir, base_imp, bd, sizeof(bd)); import_zir = loadImportZir( - bd, sp, &import_ast); + sema, bd, sp, &import_ast); zirDeinit(&b_zir); astDeinit(&b_ast); if (import_zir.inst_len > 0) { @@ -7149,13 +7112,14 @@ static AirInstRef zirCall( const char* field_name = NULL; if (findDeclImportFieldVal( sema, callee_name_idx, &import_path, &field_name)) { - import_zir - = loadImportZir(sema->source_dir, import_path, &import_ast); + import_zir = loadImportZir( + sema, sema->source_dir, import_path, &import_ast); if (import_zir.inst_len > 0) { - computeSourceDir(sema->module_root, sema->source_dir, - import_path, import_source_dir, sizeof(import_source_dir)); - func_inst = findFuncInModuleZir(import_source_dir, &import_zir, - &import_ast, field_name, import_source_dir, + computeSourceDir(sema->zcu->comp->config.module_root, + sema->source_dir, import_path, import_source_dir, + sizeof(import_source_dir)); + func_inst = findFuncInModuleZir(sema, import_source_dir, + &import_zir, &import_ast, field_name, import_source_dir, sizeof(import_source_dir)); if (func_inst != UINT32_MAX) { saved_code = sema->code; @@ -8482,7 +8446,7 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { // The body is NOT analyzed (inline functions get inlined at // the call site, not compiled as standalone function bodies). uint32_t ns_idx = (sema->file_idx != UINT32_MAX) - ? s_file_namespace[sema->file_idx] + ? sema->zcu->file_namespaces[sema->file_idx] : UINT32_MAX; // Resolve return type. @@ -8490,13 +8454,13 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { if (fi.ret_ty_body_len == 1) { uint32_t ret_ref = sema->code.extra[fi.ret_ty_ref_pos]; InternPoolIndex resolved = resolveZirTypeRef( - &sema->code, ret_ref, ns_idx, sema->file_idx); + sema, &sema->code, ret_ref, ns_idx, sema->file_idx); if (resolved != IP_INDEX_NONE) ret_ty = resolved; } else if (fi.ret_ty_body_len == 2) { uint32_t type_inst = sema->code.extra[fi.ret_ty_ref_pos]; InternPoolIndex resolved = resolveZirTypeInst( - &sema->code, type_inst, ns_idx, sema->file_idx); + sema, &sema->code, type_inst, ns_idx, sema->file_idx); if (resolved != IP_INDEX_NONE) ret_ty = resolved; } @@ -8533,20 +8497,21 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { func_name = (const char*)&sema->code.string_bytes[sema->cur_decl_name]; uint32_t func_nav = UINT32_MAX; - if (func_name && s_root_file_idx != UINT32_MAX) { - uint32_t rns = s_file_namespace[s_root_file_idx]; - func_nav = findNavInNamespace(rns, func_name); + if (func_name && sema->zcu->root_file_idx != UINT32_MAX) { + uint32_t rns + = sema->zcu->file_namespaces[sema->zcu->root_file_idx]; + func_nav = findNavInNamespace(sema, rns, func_name); } if (func_nav != UINT32_MAX) { - (void)internFuncDecl(func_nav, func_type_ip); - Nav* fn = ipGetNav(func_nav); + (void)internFuncDecl(sema, func_nav, func_type_ip); + Nav* fn = ipGetNav(sema->ip, func_nav); fn->resolved_type = func_type_ip; } // Ported from Sema.zig zirFuncFancy: the CC body evaluation // calls getBuiltinType(.CallingConvention) which triggers // ensureMemoizedStateResolved(.main), resolving all builtins. - (void)getBuiltinTypeC(2); // 2 = CallingConvention + (void)getBuiltinTypeC(sema, 2); // 2 = CallingConvention return; } @@ -8560,19 +8525,19 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { // types (pointers, optionals, etc.) that create IP entries. InternPoolIndex ret_ty = IP_INDEX_VOID_TYPE; uint32_t ns_idx = (sema->file_idx != UINT32_MAX) - ? s_file_namespace[sema->file_idx] + ? sema->zcu->file_namespaces[sema->file_idx] : UINT32_MAX; if (fi.ret_ty_body_len == 1) { uint32_t ret_ref = sema->code.extra[fi.ret_ty_ref_pos]; InternPoolIndex resolved = resolveZirTypeRef( - &sema->code, ret_ref, ns_idx, sema->file_idx); + sema, &sema->code, ret_ref, ns_idx, sema->file_idx); if (resolved != IP_INDEX_NONE) ret_ty = resolved; } else if (fi.ret_ty_body_len == 2) { // 2-instruction body: type instruction + break_inline. uint32_t type_inst = sema->code.extra[fi.ret_ty_ref_pos]; InternPoolIndex resolved = resolveZirTypeInst( - &sema->code, type_inst, ns_idx, sema->file_idx); + sema, &sema->code, type_inst, ns_idx, sema->file_idx); if (resolved != IP_INDEX_NONE) ret_ty = resolved; } @@ -8610,12 +8575,12 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { ZirInstRef tref = sema->code.inst_datas[bi2].break_data.operand; (void)resolveZirTypeRef( - &sema->code, tref, ns_idx, sema->file_idx); + sema, &sema->code, tref, ns_idx, sema->file_idx); } } else if (type_body_len == 2) { uint32_t ti = sema->code.extra[pp + 2]; (void)resolveZirTypeInst( - &sema->code, ti, ns_idx, sema->file_idx); + sema, &sema->code, ti, ns_idx, sema->file_idx); } } } @@ -8646,11 +8611,11 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { AirInstRef res = resolveInst(sema, operand); if (AIR_REF_IS_IP(res)) { InternPoolIndex ip_idx = AIR_REF_TO_IP(res); - if (s_module_ip->items[ip_idx].tag + if (sema->ip->items[ip_idx].tag == IP_KEY_ENUM_LITERAL) { uint32_t str_idx - = s_module_ip->items[ip_idx].data.enum_literal; - cc_name = (const char*)&s_module_ip + = sema->ip->items[ip_idx].data.enum_literal; + cc_name = (const char*)&sema->ip ->string_bytes[str_idx]; } } @@ -8669,13 +8634,14 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { // ensureMemoizedStateResolved(.main), then coerces the // enum literal to the CallingConvention union type. InternPoolIndex cc_type_ip - = getBuiltinTypeC(2); // 2 = CallingConvention + = getBuiltinTypeC(sema, 2); // 2 = CallingConvention if (cc_type_ip != IP_INDEX_NONE) { - uint32_t cc_ns = findNamespaceForType(cc_type_ip); + uint32_t cc_ns = findNamespaceForType(sema, cc_type_ip); if (cc_ns != UINT32_MAX) { - uint32_t c_nav = findNavInNamespace(cc_ns, cc_name); + uint32_t c_nav + = findNavInNamespace(sema, cc_ns, cc_name); if (c_nav != UINT32_MAX) { - (void)ensureNavValUpToDate(c_nav); + (void)ensureNavValUpToDate(sema, c_nav); } } } @@ -8705,13 +8671,14 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { = (const char*)&sema->code.string_bytes[sema->cur_decl_name]; } uint32_t func_nav = UINT32_MAX; - if (func_name && s_root_file_idx != UINT32_MAX) { - uint32_t rns = s_file_namespace[s_root_file_idx]; - func_nav = findNavInNamespace(rns, func_name); + if (func_name && sema->zcu->root_file_idx != UINT32_MAX) { + uint32_t rns + = sema->zcu->file_namespaces[sema->zcu->root_file_idx]; + func_nav = findNavInNamespace(sema, rns, func_name); } if (func_nav != UINT32_MAX) { - (void)internFuncDecl(func_nav, func_type_ip); - Nav* fn = ipGetNav(func_nav); + (void)internFuncDecl(sema, func_nav, func_type_ip); + Nav* fn = ipGetNav(sema->ip, func_nav); fn->resolved_type = func_type_ip; } @@ -8854,7 +8821,7 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) { // Note: we do NOT call ensureFileAnalyzedC here — the imported // module's struct_type is created later when the import is // actually accessed (during DECL_VAL in the comptime block body). - if (s_in_main_analysis && sema->source_dir) { + if (sema->zcu->in_main_analysis && sema->source_dir) { for (uint32_t d = 0; d < decls_len; d++) { uint32_t decl_inst = decl_list[d]; uint32_t payload @@ -8869,8 +8836,8 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) { continue; // Verify the import path is resolvable (without loading). char import_full[1024]; - if (!resolveImportPath(sema->source_dir, import_path, import_full, - sizeof(import_full))) + if (!resolveImportPath(sema, sema->source_dir, import_path, + import_full, sizeof(import_full))) continue; // Create ptr_type(*const type) + ptr_nav for the import nav. // The child type is TYPE_TYPE because import declarations @@ -8879,8 +8846,8 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) { uint32_t decl_name_idx = sema->code.extra[payload + 6]; const char* decl_name = (const char*)&sema->code.string_bytes[decl_name_idx]; - uint32_t ns_idx = s_file_namespace[sema->file_idx]; - uint32_t nav = findNavInNamespace(ns_idx, decl_name); + uint32_t ns_idx = sema->zcu->file_namespaces[sema->file_idx]; + uint32_t nav = findNavInNamespace(sema, ns_idx, decl_name); if (nav != UINT32_MAX) { // Force-create a new ptr_type instead of deduplicating. // In the Zig compiler, the IP is sharded and this ptr_type @@ -8894,8 +8861,8 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) { pt_key.data.ptr_type.flags = PTR_FLAGS_SIZE_ONE | PTR_FLAGS_IS_CONST; pt_key.data.ptr_type.packed_offset = 0; - InternPoolIndex pt = ipForceIntern(s_module_ip, pt_key); - (void)internNavPtr(pt, nav); + InternPoolIndex pt = ipForceIntern(sema->ip, pt_key); + (void)internNavPtr(sema, pt, nav); } } } @@ -8905,7 +8872,7 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) { // process function declarations in Pass 2a, zirFunc knows which // functions are exported (even though the comptime block hasn't // been fully evaluated yet). - if (s_in_main_analysis) { + if (sema->zcu->in_main_analysis) { for (uint32_t d = 0; d < decls_len; d++) { uint32_t di2 = decl_list[d]; uint32_t pl2 @@ -8932,7 +8899,7 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) { continue; uint32_t ni = sema->code.inst_datas[ei].str_tok.start; if (sema->num_exported_decl_names < MAX_EXPORTED_DECL_NAMES) { - s_exported_decl_names[sema->num_exported_decl_names++] + sema->exported_decl_names[sema->num_exported_decl_names++] = ni; } } @@ -9238,15 +9205,15 @@ static AirInstRef semaResolveSwitchComptime( if (is_enum_operand && operand_enum_type != IP_INDEX_NONE) { // Find the enum declaration ZIR to look up field names/values. uint32_t enum_nav = UINT32_MAX; - for (uint32_t ni = 0; ni < ipNavCount(); ni++) { - if (ipGetNav(ni)->resolved_type == operand_enum_type) { + for (uint32_t ni = 0; ni < ipNavCount(sema->ip); ni++) { + if (ipGetNav(sema->ip, ni)->resolved_type == operand_enum_type) { enum_nav = ni; break; } } if (enum_nav != UINT32_MAX) { const Zir* enum_zir = NULL; - uint32_t enum_inst = findEnumDeclForNav(enum_nav, &enum_zir); + uint32_t enum_inst = findEnumDeclForNav(sema, enum_nav, &enum_zir); if (enum_inst != UINT32_MAX && enum_zir != NULL) { for (uint32_t i = 0; i < total_items; i++) { // Get the item's name from the ZIR enum_literal inst. @@ -9270,11 +9237,11 @@ static AirInstRef semaResolveSwitchComptime( if (fidx == UINT32_MAX) continue; InternPoolIndex int_val - = getEnumFieldIntVal(enum_zir, enum_inst, fidx); + = getEnumFieldIntVal(sema, enum_zir, enum_inst, fidx); if (int_val == IP_INDEX_NONE) continue; coerced_items[i] - = internEnumTag(operand_enum_type, int_val); + = internEnumTag(sema, operand_enum_type, int_val); } } } @@ -9617,9 +9584,8 @@ static AirInstRef evalCrossModuleDeclValue( // resolution (e.g. common.zig -> builtin.abi) from causing // infinite recursion or expensive file I/O. Sema mini_sema; - semaInit(&mini_sema, parent_sema->ip, *import_zir); + semaInit(&mini_sema, parent_sema->zcu, *import_zir); mini_sema.source_dir = NULL; - mini_sema.module_root = NULL; SemaBlock ct_block; semaBlockInit(&ct_block, &mini_sema, NULL); @@ -9688,20 +9654,22 @@ static AirInstRef zirFieldValComptime( InternPoolKeyTag kt = sema->ip->items[obj_ip].tag; if (kt == IP_KEY_STRUCT_TYPE || kt == IP_KEY_UNION_TYPE || kt == IP_KEY_ENUM_TYPE) { - uint32_t base_ns = findNamespaceForType(obj_ip); + uint32_t base_ns = findNamespaceForType(sema, obj_ip); if (base_ns != UINT32_MAX) { - uint32_t member_nav = findNavInNamespace(base_ns, field_name); + uint32_t member_nav + = findNavInNamespace(sema, base_ns, field_name); if (member_nav != UINT32_MAX) { - InternPoolIndex val = ensureNavValUpToDate(member_nav); + InternPoolIndex val + = ensureNavValUpToDate(sema, member_nav); if (val != IP_INDEX_NONE) { // Create ptr_type + ptr_nav matching Zig's // analyzeNavRefInner. In Zig, fieldVal for // namespace lookups goes through analyzeNavRef // which creates these entries. - if (s_in_main_analysis) { + if (sema->zcu->in_main_analysis) { InternPoolIndex ptr_ty - = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(ptr_ty, member_nav); + = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, ptr_ty, member_nav); } return AIR_REF_FROM_IP(val); } @@ -9733,7 +9701,7 @@ static AirInstRef zirFieldValComptime( if (import_path) { Ast import_ast; Zir import_zir = loadImportZir( - sema->source_dir, import_path, &import_ast); + sema, sema->source_dir, import_path, &import_ast); if (import_zir.inst_len > 0) { uint32_t field_decl = findDeclInstByNameInZir(&import_zir, field_name); @@ -9782,17 +9750,17 @@ static AirInstRef zirFieldPtr(Sema* sema, SemaBlock* block, uint32_t inst) { InternPoolIndex obj_ip = AIR_REF_TO_IP(obj); InternPoolIndex obj_type = ipTypeOf(sema->ip, obj_ip); if (obj_type == IP_INDEX_TYPE_TYPE) { - uint32_t ns = findNamespaceForType(obj_ip); + uint32_t ns = findNamespaceForType(sema, obj_ip); if (ns != UINT32_MAX) { - uint32_t nav_idx = findNavInNamespace(ns, field_name); + uint32_t nav_idx = findNavInNamespace(sema, ns, field_name); if (nav_idx != UINT32_MAX) { - const Nav* n = ipGetNav(nav_idx); + const Nav* n = ipGetNav(sema->ip, nav_idx); if (n->resolved_type != IP_INDEX_NONE) { // Check if a ptr_nav already exists for this // nav (created during init). If so, return it // to match Zig's analyzeNavRef pattern. InternPoolIndex val_ty = n->resolved_type; - InternPoolIndex ptr_ty = internPtrConst(val_ty); + InternPoolIndex ptr_ty = internPtrConst(sema, val_ty); InternPoolKey pk; memset(&pk, 0, sizeof(pk)); pk.tag = IP_KEY_PTR_NAV; @@ -9824,15 +9792,15 @@ static AirInstRef zirFieldPtr(Sema* sema, SemaBlock* block, uint32_t inst) { InternPoolIndex union_ty = sema->comptime_inner_type; uint32_t field_idx = UINT32_MAX; InternPoolIndex field_type - = resolveUnionFieldByName(union_ty, field_name, &field_idx); - InternPoolIndex tag_enum = findUnionTagEnum(union_ty); + = resolveUnionFieldByName(sema, union_ty, field_name, &field_idx); + InternPoolIndex tag_enum = findUnionTagEnum(sema, union_ty); if (field_type != IP_INDEX_NONE && tag_enum != IP_INDEX_NONE && field_idx != UINT32_MAX) { // 1. Create *mut FieldType (matches upstream ptrTypeSema). - InternPoolIndex field_ptr_ty = internPtrMutable(field_type); + InternPoolIndex field_ptr_ty = internPtrMutable(sema, field_type); // 2. Create enum_tag (matches upstream enumValueFieldIndex). InternPoolIndex int_val - = internTypedInt(IP_INDEX_U8_TYPE, field_idx); + = internTypedInt(sema, IP_INDEX_U8_TYPE, field_idx); InternPoolKey etk; memset(&etk, 0, sizeof(etk)); etk.tag = IP_KEY_ENUM_TAG; @@ -9840,7 +9808,7 @@ static AirInstRef zirFieldPtr(Sema* sema, SemaBlock* block, uint32_t inst) { etk.data.enum_tag.int_val = int_val; InternPoolIndex field_tag = ipForceIntern(sema->ip, etk); // 3. Create undef(FieldType) (matches upstream undefValue). - InternPoolIndex undef_val = internUndef(field_type); + InternPoolIndex undef_val = internUndef(sema, field_type); // 4. Create union_value (matches upstream unionValue). InternPoolKey uvk; memset(&uvk, 0, sizeof(uvk)); @@ -10091,11 +10059,11 @@ static AirInstRef zirDeclLiteralComptime(Sema* sema, uint32_t inst) { if (AIR_REF_IS_IP(lhs_result)) { InternPoolIndex lhs_ip = AIR_REF_TO_IP(lhs_result); // The LHS should be a type. Find its namespace. - uint32_t ns = findNamespaceForType(lhs_ip); + uint32_t ns = findNamespaceForType(sema, lhs_ip); if (ns != UINT32_MAX) { - uint32_t nav = findNavInNamespace(ns, field_name); + uint32_t nav = findNavInNamespace(sema, ns, field_name); if (nav != UINT32_MAX) { - InternPoolIndex val = ensureNavValUpToDate(nav); + InternPoolIndex val = ensureNavValUpToDate(sema, nav); if (val != IP_INDEX_NONE) return AIR_REF_FROM_IP(val); } @@ -10283,8 +10251,8 @@ static AirInstRef zirExtended(Sema* sema, SemaBlock* block, uint32_t inst) { // namespace this code is declared in). // Ported from src/Sema.zig:16800 zirThis. if (sema->file_idx != UINT32_MAX) { - uint32_t ns_idx = s_file_namespace[sema->file_idx]; - return AIR_REF_FROM_IP(s_namespaces[ns_idx].owner_type); + uint32_t ns_idx = sema->zcu->file_namespaces[sema->file_idx]; + return AIR_REF_FROM_IP(sema->zcu->namespaces[ns_idx].owner_type); } return AIR_REF_FROM_IP(IP_INDEX_VOID_TYPE); } @@ -10344,22 +10312,27 @@ static AirInstRef zirExtended(Sema* sema, SemaBlock* block, uint32_t inst) { if (opcode == ZIR_EXT_BUILTIN_VALUE) { uint16_t bv_kind = sema->code.inst_datas[inst].extended.small; if (bv_kind == ZIR_BUILTIN_VALUE_CALLING_CONVENTION - && s_builtin_file_idx != UINT32_MAX) { - uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx]; + && sema->zcu->builtin_file_idx != UINT32_MAX) { + uint32_t builtin_ns + = sema->zcu->file_namespaces[sema->zcu->builtin_file_idx]; uint32_t cc_nav - = findNavInNamespace(builtin_ns, "CallingConvention"); + = findNavInNamespace(sema, builtin_ns, "CallingConvention"); if (cc_nav != UINT32_MAX) { - InternPoolIndex cc_type = ipGetNav(cc_nav)->resolved_type; + InternPoolIndex cc_type + = ipGetNav(sema->ip, cc_nav)->resolved_type; if (cc_type != IP_INDEX_NONE) return AIR_REF_FROM_IP(cc_type); } } if (bv_kind == ZIR_BUILTIN_VALUE_EXPORT_OPTIONS - && s_builtin_file_idx != UINT32_MAX) { - uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx]; - uint32_t eo_nav = findNavInNamespace(builtin_ns, "ExportOptions"); + && sema->zcu->builtin_file_idx != UINT32_MAX) { + uint32_t builtin_ns + = sema->zcu->file_namespaces[sema->zcu->builtin_file_idx]; + uint32_t eo_nav + = findNavInNamespace(sema, builtin_ns, "ExportOptions"); if (eo_nav != UINT32_MAX) { - InternPoolIndex eo_type = ipGetNav(eo_nav)->resolved_type; + InternPoolIndex eo_type + = ipGetNav(sema->ip, eo_nav)->resolved_type; if (eo_type != IP_INDEX_NONE) return AIR_REF_FROM_IP(eo_type); } @@ -10453,7 +10426,7 @@ static bool zirBlockInline(Sema* sema, SemaBlock* block, uint32_t inst) { // (*const [len:0]u8), ptr_uav. Returns the ptr_uav IP index. // Ported from src/Sema.zig addStrLit + uavRef. static InternPoolIndex internStrLit( - InternPool* ip, const char* str, uint32_t len) { + Sema* sema, InternPool* ip, const char* str, uint32_t len) { // type_array_big: [len:0]u8. InternPoolKey arr_key; memset(&arr_key, 0, sizeof(arr_key)); @@ -10473,7 +10446,7 @@ static InternPoolIndex internStrLit( InternPoolIndex bytes_val = ipIntern(ip, bytes_key); // type_pointer: *const [len:0]u8. - InternPoolIndex arr_ptr_type = internPtrConst(arr_type); + InternPoolIndex arr_ptr_type = internPtrConst(sema, arr_type); // ptr_uav: pointer to the bytes value. InternPoolKey uav_key; @@ -10490,21 +10463,22 @@ static InternPoolIndex internStrLit( // ensureMemoizedStateUpToDate. Called on first getBuiltinType or // @export to create IP entries matching the Zig compiler's // ensureMemoizedStateResolved(.main) chain. -static void analyzeMemoizedStateC(void) { - if (s_memoized_main_resolved) +static void analyzeMemoizedStateC(Sema* sema) { + if (sema->zcu->memoized_main_resolved) return; - s_memoized_main_resolved = true; + sema->zcu->memoized_main_resolved = true; - if (s_builtin_file_idx == UINT32_MAX) + if (sema->zcu->builtin_file_idx == UINT32_MAX) return; - uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx]; + uint32_t builtin_ns + = sema->zcu->file_namespaces[sema->zcu->builtin_file_idx]; for (int i = 0; i < NUM_BUILTIN_DECL_MAIN; i++) - s_builtin_decl_values[i] = IP_INDEX_NONE; + sema->zcu->builtin_decl_values[i] = IP_INDEX_NONE; // Record IP position before memoized resolution for shard simulation. - s_preamble_memoized_start = s_module_ip->items_len; - s_preamble_builtin_nav_count = 0; + sema->zcu->preamble_memoized_start = sema->ip->items_len; + sema->zcu->preamble_builtin_nav_count = 0; // AddressSpace (builtin index 1) is enum(u5) with 24 fields (values // 0..23). Its comptime_int entries go into C's single IP hash table. @@ -10520,7 +10494,7 @@ static void analyzeMemoizedStateC(void) { // The value 13 is target-specific (wasm32-wasi bootstrap constant): // it equals the number of CC tag values the Zig compiler materializes // during memoized state resolution for this target. - s_enum_force_intern_threshold = 13; + sema->zcu->enum_force_intern_threshold = 13; // Resolve .main-stage builtins. Ported from Sema.zig // analyzeMemoizedState which iterates all BuiltinDecl values @@ -10543,43 +10517,45 @@ static void analyzeMemoizedStateC(void) { lookup_ns = builtin_ns; } else { InternPoolIndex parent_type - = s_builtin_decl_values[entry->parent_idx]; + = sema->zcu->builtin_decl_values[entry->parent_idx]; if (parent_type == IP_INDEX_NONE) continue; - lookup_ns = findNamespaceForType(parent_type); + lookup_ns = findNamespaceForType(sema, parent_type); if (lookup_ns == UINT32_MAX) continue; } - uint32_t nav = findNavInNamespace(lookup_ns, entry->lookup_name); + uint32_t nav = findNavInNamespace(sema, lookup_ns, entry->lookup_name); if (nav == UINT32_MAX) continue; // Record nav ID for later clearing in shard simulation. - if (s_preamble_builtin_nav_count < 5) - s_preamble_builtin_navs[s_preamble_builtin_nav_count++] = nav; + if (sema->zcu->preamble_builtin_nav_count < 5) + sema->zcu->preamble_builtin_navs[sema->zcu + ->preamble_builtin_nav_count++] + = nav; // Track CC (builtin 2) range: these entries are in Zig's local // shard and should NOT be skipped during main analysis dedup. if (i == 2) - s_preamble_cc_start = s_module_ip->items_len; + sema->zcu->preamble_cc_start = sema->ip->items_len; - InternPoolIndex val = ensureNavValUpToDate(nav); + InternPoolIndex val = ensureNavValUpToDate(sema, nav); if (val == IP_INDEX_NONE) continue; if (i == 2) - s_preamble_cc_end = s_module_ip->items_len; + sema->zcu->preamble_cc_end = sema->ip->items_len; - s_builtin_decl_values[i] = val; + sema->zcu->builtin_decl_values[i] = val; } // Disable the threshold after memoized resolution so future // enum resolutions during main analysis use normal ipIntern. - s_enum_force_intern_threshold = 0; + sema->zcu->enum_force_intern_threshold = 0; // Record IP position after memoized resolution. - s_preamble_memoized_end = s_module_ip->items_len; + sema->zcu->preamble_memoized_end = sema->ip->items_len; } // --- ensureFullMemoizedStateC --- @@ -10593,17 +10569,18 @@ static void analyzeMemoizedStateC(void) { // evaluation or export resolution). // Ported from upstream analyzeMemoizedState(.main): resolves ALL // builtins 0-35 via ensureNavValUpToDate + resolveTypeFullyC. -static void ensureFullMemoizedStateC(void) { - if (s_full_memoized_resolved) +static void ensureFullMemoizedStateC(Sema* sema) { + if (sema->zcu->full_memoized_resolved) return; - s_full_memoized_resolved = true; + sema->zcu->full_memoized_resolved = true; // First ensure builtins 0-4 are resolved (preamble state). - analyzeMemoizedStateC(); + analyzeMemoizedStateC(sema); - if (s_builtin_file_idx == UINT32_MAX) + if (sema->zcu->builtin_file_idx == UINT32_MAX) return; - uint32_t builtin_ns = s_file_namespace[s_builtin_file_idx]; + uint32_t builtin_ns + = sema->zcu->file_namespaces[sema->zcu->builtin_file_idx]; // Shard simulation: clear builtins 0-4 state so they get re-resolved // as fresh entries during main analysis. Ported from upstream: Zig's @@ -10611,20 +10588,21 @@ static void ensureFullMemoizedStateC(void) { // analysis creates fresh entries for builtins 0-4 types. We simulate // this by enabling skip_dedup on the preamble memoized range and // clearing the cached nav resolutions. - if (s_preamble_memoized_end > s_preamble_memoized_start) { - s_module_ip->skip_dedup_start = s_preamble_memoized_start; - s_module_ip->skip_dedup_end = s_preamble_memoized_end; - s_module_ip->cc_keep_start = s_preamble_cc_start; - s_module_ip->cc_keep_end = s_preamble_cc_end; + if (sema->zcu->preamble_memoized_end + > sema->zcu->preamble_memoized_start) { + sema->ip->skip_dedup_start = sema->zcu->preamble_memoized_start; + sema->ip->skip_dedup_end = sema->zcu->preamble_memoized_end; + sema->ip->cc_keep_start = sema->zcu->preamble_cc_start; + sema->ip->cc_keep_end = sema->zcu->preamble_cc_end; // Clear builtins 0-4 values so they're re-resolved. for (int i = 0; i < 5 && i < NUM_BUILTIN_DECL_MAIN; i++) - s_builtin_decl_values[i] = IP_INDEX_NONE; + sema->zcu->builtin_decl_values[i] = IP_INDEX_NONE; // Clear nav resolved_type for builtins 0-4 so // ensureNavValUpToDate re-resolves them. - for (uint32_t n = 0; n < s_preamble_builtin_nav_count; n++) { - Nav* nav = ipGetNav(s_preamble_builtin_navs[n]); + for (uint32_t n = 0; n < sema->zcu->preamble_builtin_nav_count; n++) { + Nav* nav = ipGetNav(sema->ip, sema->zcu->preamble_builtin_navs[n]); nav->resolved_type = IP_INDEX_NONE; } } @@ -10633,7 +10611,7 @@ static void ensureFullMemoizedStateC(void) { // With shard simulation active, builtins 0-4 are re-resolved // as fresh entries, matching upstream's sharded IP behavior. for (int i = 0; i < NUM_BUILTIN_DECL_MAIN; i++) { - if (s_builtin_decl_values[i] != IP_INDEX_NONE) + if (sema->zcu->builtin_decl_values[i] != IP_INDEX_NONE) continue; const BuiltinDeclEntry* entry = &s_builtin_decl_entries[i]; @@ -10642,30 +10620,30 @@ static void ensureFullMemoizedStateC(void) { lookup_ns = builtin_ns; } else { InternPoolIndex parent_type - = s_builtin_decl_values[entry->parent_idx]; + = sema->zcu->builtin_decl_values[entry->parent_idx]; if (parent_type == IP_INDEX_NONE) continue; - lookup_ns = findNamespaceForType(parent_type); + lookup_ns = findNamespaceForType(sema, parent_type); if (lookup_ns == UINT32_MAX) continue; } - uint32_t nav = findNavInNamespace(lookup_ns, entry->lookup_name); + uint32_t nav = findNavInNamespace(sema, lookup_ns, entry->lookup_name); if (nav == UINT32_MAX) continue; - InternPoolIndex val = ensureNavValUpToDate(nav); + InternPoolIndex val = ensureNavValUpToDate(sema, nav); if (val == IP_INDEX_NONE) continue; - s_builtin_decl_values[i] = val; + sema->zcu->builtin_decl_values[i] = val; } // Disable shard simulation after Phase 1. - s_module_ip->skip_dedup_start = 0; - s_module_ip->skip_dedup_end = 0; - s_module_ip->cc_keep_start = 0; - s_module_ip->cc_keep_end = 0; + sema->ip->skip_dedup_start = 0; + sema->ip->skip_dedup_end = 0; + sema->ip->cc_keep_start = 0; + sema->ip->cc_keep_end = 0; // Phase 2: Call resolveTypeFullyC on ALL type builtins. // Ported from analyzeMemoizedState line 37560: @@ -10673,9 +10651,9 @@ static void ensureFullMemoizedStateC(void) { for (int i = 0; i < NUM_BUILTIN_DECL_MAIN; i++) { if (!s_builtin_decl_entries[i].is_type) continue; - InternPoolIndex val = s_builtin_decl_values[i]; + InternPoolIndex val = sema->zcu->builtin_decl_values[i]; if (val != IP_INDEX_NONE) - resolveTypeFullyC(val); + resolveTypeFullyC(sema, val); } } @@ -10683,9 +10661,9 @@ static void ensureFullMemoizedStateC(void) { // Ported from Sema.zig getBuiltinType (line 37446). // Calls ensureMemoizedStateResolved(.main) which resolves ALL builtins, // then returns the requested builtin's type value. -static InternPoolIndex getBuiltinTypeC(int builtin_idx) { - ensureFullMemoizedStateC(); - return s_builtin_decl_values[builtin_idx]; +static InternPoolIndex getBuiltinTypeC(Sema* sema, int builtin_idx) { + ensureFullMemoizedStateC(sema); + return sema->zcu->builtin_decl_values[builtin_idx]; } // --- zirExport --- @@ -10694,7 +10672,7 @@ static void zirExport(Sema* sema, uint32_t inst) { // Trigger memoized state resolution on first export. // Ported from Sema.zig: zirExport → resolveExportOptions → // getBuiltinType(.ExportOptions) → ensureMemoizedStateResolved(.main). - ensureFullMemoizedStateC(); + ensureFullMemoizedStateC(sema); uint32_t payload_index = sema->code.inst_datas[inst].pl_node.payload_index; uint32_t exported_ref = sema->code.extra[payload_index]; @@ -10705,7 +10683,7 @@ static void zirExport(Sema* sema, uint32_t inst) { uint32_t name_idx = sema->code.inst_datas[exported_inst].str_tok.start; if (sema->num_exported_decl_names < MAX_EXPORTED_DECL_NAMES) { - s_exported_decl_names[sema->num_exported_decl_names++] + sema->exported_decl_names[sema->num_exported_decl_names++] = name_idx; } } @@ -10761,13 +10739,14 @@ static void zirValidatePtrStructInit(Sema* sema, uint32_t inst) { // Create int_usize(field_idx) — the field index as an interned value. // Ported from Zig's ptr.ptrField which stores field index as byte_offset. - (void)internTypedInt(IP_INDEX_USIZE_TYPE, sema->comptime_field_idx); + (void)internTypedInt(sema, IP_INDEX_USIZE_TYPE, sema->comptime_field_idx); // Create ptr_field pointing to the struct field within the union. // Ported from Sema.zig validateUnionInit reading back the field. - InternPoolIndex field_ptr_ty = internPtrMutable(sema->comptime_field_type); + InternPoolIndex field_ptr_ty + = internPtrMutable(sema, sema->comptime_field_type); InternPoolIndex pf = internPtrField( - field_ptr_ty, sema->comptime_ret_ptr, sema->comptime_field_idx); + sema, field_ptr_ty, sema->comptime_ret_ptr, sema->comptime_field_idx); (void)pf; // Create repeated(field_type, opt_null) — the default value for @@ -10811,7 +10790,7 @@ static AirInstRef zirStructInitEmptyResult( // --- zirRetPtr --- // Ported from src/Sema.zig zirRetPtr / retPtrComptime. -static AirInstRef zirRetPtr(const Sema* sema, SemaBlock* block) { +static AirInstRef zirRetPtr(Sema* sema, SemaBlock* block) { // In comptime context with a tracked comptime alloc, return the // comptime alloc pointer directly (no AIR ALLOC instruction). // Ported from Sema.zig retPtrComptime. @@ -10821,7 +10800,7 @@ static AirInstRef zirRetPtr(const Sema* sema, SemaBlock* block) { TypeIndex ret_ty = sema->fn_ret_ty; if (ret_ty == TYPE_NONE) ret_ty = IP_INDEX_VOID_TYPE; - TypeIndex ptr_ty = internPtrMutable(ret_ty); + TypeIndex ptr_ty = internPtrMutable(sema, ret_ty); AirInstData d; memset(&d, 0, sizeof(d)); d.ty.ty_ref = AIR_REF_FROM_IP(ptr_ty); @@ -10926,7 +10905,7 @@ static AirInstRef zirRef(Sema* sema, uint32_t inst) { return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE); // Create *const T pointer type. - InternPoolIndex ptr_ty = internPtrConst(val_ty); + InternPoolIndex ptr_ty = internPtrConst(sema, val_ty); // Create ptr_uav entry (pointer to the comptime value). InternPoolKey key; @@ -10976,9 +10955,9 @@ static AirInstRef zirOptEuBasePtrInit(Sema* sema, uint32_t inst) { // Save inner type for comptime union init detection. sema->comptime_inner_type = inner_ty; // Create *mut T pointer type → matches Zig $926. - InternPoolIndex inner_ptr_ty = internPtrMutable(inner_ty); + InternPoolIndex inner_ptr_ty = internPtrMutable(sema, inner_ty); // Create undef(T) → matches Zig $927. - InternPoolIndex undef_inner = internUndef(inner_ty); + InternPoolIndex undef_inner = internUndef(sema, inner_ty); // Create opt_payload(opt_ty, undef_inner) → matches Zig $928. InternPoolKey opk; memset(&opk, 0, sizeof(opk)); @@ -11917,21 +11896,23 @@ static bool analyzeBodyInner( if (import_path) { // Resolve via doImport (handles "builtin", // "root", "std", and file paths). - uint32_t fid = doImport(sema->source_dir, import_path); + uint32_t fid + = doImport(sema, sema->source_dir, import_path); if (fid != UINT32_MAX) { - resolved = s_file_root_type[fid]; + resolved = sema->zcu->file_root_types[fid]; // Create ptr_nav for the import nav, // matching Zig's analyzeNavRefInner. // Created during both preamble and main analysis // (the Zig compiler creates these whenever imports // are accessed in comptime context). if (sema->file_idx != UINT32_MAX) { - uint32_t nav_idx2 = findNavInNamespace( - s_file_namespace[sema->file_idx], decl_name); + uint32_t nav_idx2 = findNavInNamespace(sema, + sema->zcu->file_namespaces[sema->file_idx], + decl_name); if (nav_idx2 != UINT32_MAX) { InternPoolIndex pt - = internPtrConst(IP_INDEX_TYPE_TYPE); - (void)internNavPtr(pt, nav_idx2); + = internPtrConst(sema, IP_INDEX_TYPE_TYPE); + (void)internNavPtr(sema, pt, nav_idx2); } } } @@ -11942,23 +11923,24 @@ static bool analyzeBodyInner( // ensureNavValUpToDate; during preamble, only // return already-resolved values to avoid // creating IP entries out of order. - uint32_t ns_idx = s_file_namespace[sema->file_idx]; - uint32_t nav = findNavInNamespace(ns_idx, decl_name); + uint32_t ns_idx + = sema->zcu->file_namespaces[sema->file_idx]; + uint32_t nav = findNavInNamespace(sema, ns_idx, decl_name); if (nav != UINT32_MAX) { - if (s_in_main_analysis) { - InternPoolIndex val = ensureNavValUpToDate(nav); + if (sema->zcu->in_main_analysis) { + InternPoolIndex val + = ensureNavValUpToDate(sema, nav); if (val != IP_INDEX_NONE) { resolved = val; // Create ptr_type + ptr_nav matching // analyzeNavRefInner. Uses typeOf(val) as // the child type (not always type_type). - InternPoolIndex vt - = ipTypeOf(s_module_ip, val); - InternPoolIndex pt = internPtrConst(vt); - (void)internNavPtr(pt, nav); + InternPoolIndex vt = ipTypeOf(sema->ip, val); + InternPoolIndex pt = internPtrConst(sema, vt); + (void)internNavPtr(sema, pt, nav); } } else { - const Nav* n = ipGetNav(nav); + const Nav* n = ipGetNav(sema->ip, nav); if (n->resolved_type != IP_INDEX_NONE) resolved = n->resolved_type; } @@ -11973,20 +11955,23 @@ static bool analyzeBodyInner( const char* import_path = findDeclImportPath(sema, decl_name_idx); if (import_path && sema->source_dir) { - uint32_t fid = doImport(sema->source_dir, import_path); + uint32_t fid + = doImport(sema, sema->source_dir, import_path); if (fid != UINT32_MAX) - resolved = s_file_root_type[fid]; + resolved = sema->zcu->file_root_types[fid]; } else if (!import_path) { // Local declaration: look up in file namespace. - uint32_t ns_idx = s_file_namespace[sema->file_idx]; - uint32_t nav = findNavInNamespace(ns_idx, decl_name); + uint32_t ns_idx + = sema->zcu->file_namespaces[sema->file_idx]; + uint32_t nav = findNavInNamespace(sema, ns_idx, decl_name); if (nav != UINT32_MAX) { - if (s_in_main_analysis) { - InternPoolIndex val = ensureNavValUpToDate(nav); + if (sema->zcu->in_main_analysis) { + InternPoolIndex val + = ensureNavValUpToDate(sema, nav); if (val != IP_INDEX_NONE) resolved = val; } else { - const Nav* n = ipGetNav(nav); + const Nav* n = ipGetNav(sema->ip, nav); if (n->resolved_type != IP_INDEX_NONE) resolved = n->resolved_type; } @@ -12008,9 +11993,9 @@ static bool analyzeBodyInner( const char* import_path = (const char*)&sema->code.string_bytes[path_idx]; InternPoolIndex result = IP_INDEX_VOID_VALUE; - uint32_t fid = doImport(sema->source_dir, import_path); + uint32_t fid = doImport(sema, sema->source_dir, import_path); if (fid != UINT32_MAX) - result = s_file_root_type[fid]; + result = sema->zcu->file_root_types[fid]; instMapPut(&sema->inst_map, inst, AIR_REF_FROM_IP(result)); i++; continue; @@ -12453,7 +12438,7 @@ static bool analyzeBodyInner( // type_pointer + ptr_uav entries matching Zig's zirStr/addStrLit. case ZIR_INST_STR: { AirInstRef str_result = AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE); - if (block->is_comptime && s_in_main_analysis) { + if (block->is_comptime && sema->zcu->in_main_analysis) { uint32_t str_len = sema->code.inst_datas[inst].str.len; // Extract the string from ZIR string_bytes. char str_buf[256]; @@ -12463,7 +12448,7 @@ static bool analyzeBodyInner( str_buf, &sema->code.string_bytes[str_start], str_len); str_buf[str_len] = '\0'; InternPoolIndex uav - = internStrLit(sema->ip, str_buf, str_len); + = internStrLit(sema, sema->ip, str_buf, str_len); str_result = AIR_REF_FROM_IP(uav); } } @@ -12609,7 +12594,7 @@ SemaFuncAirList semaAnalyze(Sema* sema) { (void)typeChildType(ip, IP_INDEX_VOID_TYPE); (void)typeIsSlice(ip, IP_INDEX_VOID_TYPE); (void)valueToType(valueFromInterned(IP_INDEX_VOID_VALUE)); - (void)ipNavCount(); + (void)ipNavCount(sema->ip); // Set up the func_air_list for collecting per-function AIR. // Use static storage to satisfy cppcheck autoVariables @@ -12626,11 +12611,7 @@ SemaFuncAirList semaAnalyze(Sema* sema) { // Initialize module tracking. Struct type IP entries are created // lazily as imports are resolved during semantic analysis, matching // the Zig compiler's demand-driven processing order. - resetModuleTracking(); - s_module_ip = ip; - - // Set global module root for import resolution. - s_global_module_root = sema->module_root; + resetModuleTracking(sema); // Create root struct type + scan namespace for the root module // (matches Zig's createFileRootStruct called from semaFile). @@ -12639,7 +12620,7 @@ SemaFuncAirList semaAnalyze(Sema* sema) { // its imports, and only later loads the root module. We must match // this order so that InternPool indices agree. if (sema->code.inst_len > 0 && sema->source_dir) { - if (sema->module_root) { + if (sema->zcu->comp->config.module_root) { // Match the Zig compiler's module loading order. // std.zig's comptime blocks force loading start.zig and // debug.zig, then debug.assert entries are created, then @@ -12662,8 +12643,8 @@ SemaFuncAirList semaAnalyze(Sema* sema) { // $137+ = std/builtin.zig chain char std_path[1024]; snprintf(std_path, sizeof(std_path), "%s/lib/std/std.zig", - sema->module_root); - uint32_t std_file_idx = ensureFileAnalyzedC(std_path); + sema->zcu->comp->config.module_root); + uint32_t std_file_idx = ensureFileAnalyzedC(sema, std_path); uint32_t start_file_idx = UINT32_MAX; if (std_file_idx != UINT32_MAX) { @@ -12673,27 +12654,31 @@ SemaFuncAirList semaAnalyze(Sema* sema) { // → loads debug.zig, creates assert entries // Ported from upstream: comptime blocks are evaluated via // analyzeComptimeUnit after scanning the namespace. - uint32_t std_ns_idx = s_file_namespace[std_file_idx]; - const SemaNamespace* std_ns = &s_namespaces[std_ns_idx]; + uint32_t std_ns_idx = sema->zcu->file_namespaces[std_file_idx]; + const ZcuNamespace* std_ns + = &sema->zcu->namespaces[std_ns_idx]; for (uint32_t ci = 0; ci < std_ns->comptime_decl_count; ci++) { analyzeComptimeUnit( - std_file_idx, std_ns->comptime_decls[ci]); + sema, std_file_idx, std_ns->comptime_decls[ci]); } // Find start_file_idx for root module resolution below. // Find start module by checking which file has the // same root type as the start import. Try resolving // the nav first; if it already has a resolved_type // from the comptime eval, use it directly. - uint32_t start_nav = findNavInNamespace(std_ns_idx, "start"); + uint32_t start_nav + = findNavInNamespace(sema, std_ns_idx, "start"); if (start_nav != UINT32_MAX) { // If comptime eval didn't set resolved_type, // resolve it now. - if (ipGetNav(start_nav)->resolved_type == IP_INDEX_NONE) - (void)ensureNavValUpToDate(start_nav); - const Nav* sn = ipGetNav(start_nav); + if (ipGetNav(sema->ip, start_nav)->resolved_type + == IP_INDEX_NONE) + (void)ensureNavValUpToDate(sema, start_nav); + const Nav* sn = ipGetNav(sema->ip, start_nav); // Find which file the start nav resolved to. - for (uint32_t fi = 0; fi < s_num_loaded_modules; fi++) { - if (s_file_root_type[fi] == sn->resolved_type) { + for (uint32_t fi = 0; fi < sema->zcu->num_files; fi++) { + if (sema->zcu->file_root_types[fi] + == sn->resolved_type) { start_file_idx = fi; break; } @@ -12702,64 +12687,69 @@ SemaFuncAirList semaAnalyze(Sema* sema) { } // Register the root module at the next available file_idx. - uint32_t root_file_idx = s_num_loaded_modules++; - LoadedModule* root_mod = &s_loaded_modules[root_file_idx]; + uint32_t root_file_idx = sema->zcu->num_files++; + ZcuFile* root_mod = &sema->zcu->files[root_file_idx]; memset(root_mod, 0, sizeof(*root_mod)); snprintf(root_mod->source_dir, sizeof(root_mod->source_dir), "%s", sema->source_dir); root_mod->zir = sema->code; root_mod->has_zir = true; root_mod->analyzed = true; - s_root_file_idx = root_file_idx; + sema->zcu->root_file_idx = root_file_idx; sema->file_idx = root_file_idx; - (void)createFileRootStructC(root_file_idx, &sema->code); + (void)createFileRootStructC(sema, root_file_idx, &sema->code); // Evaluate start.zig's comptime blocks. Set - // s_in_main_analysis so DECL_VAL resolves declarations + // sema->zcu->in_main_analysis so DECL_VAL resolves declarations // lazily (matching upstream's full comptime evaluation). if (start_file_idx != UINT32_MAX) { - s_in_main_analysis = true; - uint32_t start_ns = s_file_namespace[start_file_idx]; - const SemaNamespace* sns = &s_namespaces[start_ns]; + sema->zcu->in_main_analysis = true; + uint32_t start_ns = sema->zcu->file_namespaces[start_file_idx]; + const ZcuNamespace* sns = &sema->zcu->namespaces[start_ns]; for (uint32_t ci = 0; ci < sns->comptime_decl_count; ci++) { analyzeComptimeUnit( - start_file_idx, sns->comptime_decls[ci]); + sema, start_file_idx, sns->comptime_decls[ci]); } - s_in_main_analysis = false; + sema->zcu->in_main_analysis = false; } // Load the builtin module chain. if (std_file_idx != UINT32_MAX) { - s_std_file_idx = std_file_idx; - uint32_t std_ns_idx2 = s_file_namespace[std_file_idx]; + sema->zcu->std_file_idx = std_file_idx; + uint32_t std_ns_idx2 + = sema->zcu->file_namespaces[std_file_idx]; // Resolve start.zig's "builtin" import. if (start_file_idx != UINT32_MAX) { - uint32_t start_ns2 = s_file_namespace[start_file_idx]; - uint32_t sbn = findNavInNamespace(start_ns2, "builtin"); + uint32_t start_ns2 + = sema->zcu->file_namespaces[start_file_idx]; + uint32_t sbn + = findNavInNamespace(sema, start_ns2, "builtin"); if (sbn != UINT32_MAX) - (void)ensureNavValUpToDate(sbn); + (void)ensureNavValUpToDate(sema, sbn); } // Resolve std.zig's "builtin" import → loads // std/builtin.zig, creates ptr_nav. uint32_t builtin_nav - = findNavInNamespace(std_ns_idx2, "builtin"); + = findNavInNamespace(sema, std_ns_idx2, "builtin"); if (builtin_nav != UINT32_MAX) { - InternPoolIndex bval = ensureNavValUpToDate(builtin_nav); + InternPoolIndex bval + = ensureNavValUpToDate(sema, builtin_nav); if (bval != IP_INDEX_NONE) { - for (uint32_t fi = 0; fi < s_num_loaded_modules; + for (uint32_t fi = 0; fi < sema->zcu->num_files; fi++) { - if (s_file_root_type[fi] == bval) { - s_builtin_file_idx = fi; + if (sema->zcu->file_root_types[fi] == bval) { + sema->zcu->builtin_file_idx = fi; // Resolve std/builtin.zig's "builtin" // import only (CG builtin module). { - uint32_t bns = s_file_namespace[fi]; - uint32_t bn - = findNavInNamespace(bns, "builtin"); + uint32_t bns + = sema->zcu->file_namespaces[fi]; + uint32_t bn = findNavInNamespace( + sema, bns, "builtin"); if (bn != UINT32_MAX) - (void)ensureNavValUpToDate(bn); + (void)ensureNavValUpToDate(sema, bn); } break; } @@ -12768,37 +12758,38 @@ SemaFuncAirList semaAnalyze(Sema* sema) { } } - analyzeMemoizedStateC(); + analyzeMemoizedStateC(sema); // Re-evaluate start.zig comptime after analyzeMemoizedStateC // so that entries dedup with memoized state (matching upstream). if (start_file_idx != UINT32_MAX) { - s_in_main_analysis = true; - uint32_t start_ns3 = s_file_namespace[start_file_idx]; - const SemaNamespace* sns3 = &s_namespaces[start_ns3]; + sema->zcu->in_main_analysis = true; + uint32_t start_ns3 + = sema->zcu->file_namespaces[start_file_idx]; + const ZcuNamespace* sns3 = &sema->zcu->namespaces[start_ns3]; for (uint32_t ci = 0; ci < sns3->comptime_decl_count; ci++) { analyzeComptimeUnit( - start_file_idx, sns3->comptime_decls[ci]); + sema, start_file_idx, sns3->comptime_decls[ci]); } - s_in_main_analysis = false; + sema->zcu->in_main_analysis = false; } } else { // No module root — root module is file_idx=0. - if (s_num_loaded_modules == 0) { - s_num_loaded_modules = 1; - memset(&s_loaded_modules[0], 0, sizeof(s_loaded_modules[0])); + if (sema->zcu->num_files == 0) { + sema->zcu->num_files = 1; + memset(&sema->zcu->files[0], 0, sizeof(sema->zcu->files[0])); } - snprintf(s_loaded_modules[0].source_dir, - sizeof(s_loaded_modules[0].source_dir), "%s", + snprintf(sema->zcu->files[0].source_dir, + sizeof(sema->zcu->files[0].source_dir), "%s", sema->source_dir); - s_loaded_modules[0].zir = sema->code; - s_loaded_modules[0].has_zir = true; - s_loaded_modules[0].analyzed = true; - s_root_file_idx = 0; + sema->zcu->files[0].zir = sema->code; + sema->zcu->files[0].has_zir = true; + sema->zcu->files[0].analyzed = true; + sema->zcu->root_file_idx = 0; sema->file_idx = 0; - (void)createFileRootStructC(0, &sema->code); - resolveModuleDeclImports(0, 2); + (void)createFileRootStructC(sema, 0, &sema->code); + resolveModuleDeclImports(sema, 0, 2); } } @@ -12810,9 +12801,9 @@ SemaFuncAirList semaAnalyze(Sema* sema) { sema->code.inst_datas[0].extended.opcode == ZIR_EXT_STRUCT_DECL); uint32_t single_inst = 0; - s_in_main_analysis = true; + sema->zcu->in_main_analysis = true; (void)analyzeBodyInner(sema, &root_block, &single_inst, 1); - s_in_main_analysis = false; + sema->zcu->in_main_analysis = false; } semaBlockDeinit(&root_block); @@ -12820,9 +12811,9 @@ SemaFuncAirList semaAnalyze(Sema* sema) { // Clean up module tracking. The root module's ZIR is owned by // the caller (sema->code), so clear has_zir to prevent double-free. - if (s_num_loaded_modules > 0) - s_loaded_modules[s_root_file_idx].has_zir = false; - resetModuleTracking(); + if (sema->zcu->num_files > 0) + sema->zcu->files[sema->zcu->root_file_idx].has_zir = false; + resetModuleTracking(sema); // Free the module-level Air arrays from sema (they're empty for // comptime-only modules but allocated). diff --git a/stage0/sema.h b/stage0/sema.h index d57cb11e92..13eca5a745 100644 --- a/stage0/sema.h +++ b/stage0/sema.h @@ -10,6 +10,11 @@ #include #include +// Forward declaration — full definition in zcu.h, included by sema.c. +struct Zcu; + +#define MAX_EXPORTED_DECL_NAMES 16 + // --- InstMap --- // Maps ZIR instruction index -> AIR instruction ref. // Uses a flat array indexed by ZIR instruction index minus a start offset. @@ -109,24 +114,6 @@ typedef struct { uint32_t runtime_index; } ComptimeAlloc; -// --- SemaNamespace --- -// Groups declarations by owning type (file root struct, etc.). -// Ported from Zcu.Namespace. - -#define SEMA_NS_MAX_NAVS 1024 -#define SEMA_NS_MAX_COMPTIME 64 - -typedef struct { - InternPoolIndex owner_type; // type_struct IP index - uint32_t file_idx; // index into loaded modules - uint32_t pub_navs[SEMA_NS_MAX_NAVS]; - uint32_t pub_nav_count; - uint32_t priv_navs[SEMA_NS_MAX_NAVS]; - uint32_t priv_nav_count; - uint32_t comptime_decls[SEMA_NS_MAX_COMPTIME]; // ZIR inst indices - uint32_t comptime_decl_count; -} SemaNamespace; - // --- SemaFuncAir --- // Per-function Air result, produced during sema analysis. @@ -164,7 +151,8 @@ typedef struct { // generation. typedef struct Sema { - InternPool* ip; + InternPool* ip; // points to zcu->ip for convenient access + struct Zcu* zcu; // owning Zcu (set by semaInit) Zir code; uint8_t* air_inst_tags; // AirInstTag stored as uint8_t (matches Zig u8) AirInstData* air_inst_datas; @@ -194,6 +182,7 @@ typedef struct Sema { // Populated by analyzeBodyInner when processing comptime blocks // that contain @export. Used by zirFunc to decide whether to analyze // non-declaration-level-exported functions. + uint32_t exported_decl_names[MAX_EXPORTED_DECL_NAMES]; uint32_t num_exported_decl_names; // Declaration table: maps string_bytes index (name) to the ZIR // declaration instruction index. Built by zirStructDecl. @@ -204,10 +193,6 @@ typedef struct Sema { // Source directory for resolving relative imports. // Set by the caller before semaAnalyze. NULL = no import resolution. const char* source_dir; - // Module root directory for resolving non-relative imports - // (e.g. @import("std") → /lib/std/std.zig). - // Set by the caller before semaAnalyze. NULL = no std resolution. - const char* module_root; // Root FQN prefix for function name construction. // Function names are "{root_fqn}.funcName" (e.g. "empty_void_function.f"). // Must match the Zig compiler's module naming (filename stem). @@ -287,7 +272,7 @@ typedef struct Sema { // --- Function declarations --- -void semaInit(Sema* sema, InternPool* ip, Zir code); +void semaInit(Sema* sema, struct Zcu* zcu, Zir code); void semaDeinit(Sema* sema); SemaFuncAirList semaAnalyze(Sema* sema); void semaFuncAirListDeinit(SemaFuncAirList* list); diff --git a/stage0/sema_test.zig b/stage0/sema_test.zig index 8cb115730e..04b7aefe84 100644 --- a/stage0/sema_test.zig +++ b/stage0/sema_test.zig @@ -5,6 +5,7 @@ const std = @import("std"); pub const c = @cImport({ @cInclude("astgen.h"); @cInclude("sema.h"); + @cInclude("zcu.h"); }); // Helper to convert C #define integer constants (c_int) to u32 for comparison @@ -167,14 +168,14 @@ test "intern_pool: pointer types" { // --------------------------------------------------------------------------- const SemaCheckResult = struct { - c_ip: c.InternPool, + c_zcu: *c.Zcu, c_sema: c.Sema, c_func_air_list: c.SemaFuncAirList, fn deinit(self: *SemaCheckResult) void { c.semaFuncAirListDeinit(&self.c_func_air_list); c.semaDeinit(&self.c_sema); - c.ipDeinit(&self.c_ip); + c.zcuDeinit(self.c_zcu); } }; @@ -184,8 +185,16 @@ fn semaCheck(source: [:0]const u8) !SemaCheckResult { var c_zir = c.astGen(&c_ast); defer c.zirDeinit(&c_zir); var result: SemaCheckResult = undefined; - result.c_ip = c.ipInit(); - c.semaInit(&result.c_sema, &result.c_ip, c_zir); + var comp: c.Compilation = .{ .config = .{ + .module_root = null, + .target_cpu_arch = "wasm32", + .target_cpu_model = "lime1", + .object_format = "wasm", + .link_mode = "static", + .is_test = false, + } }; + result.c_zcu = c.zcuInit(&comp); + c.semaInit(&result.c_sema, result.c_zcu, c_zir); result.c_func_air_list = c.semaAnalyze(&result.c_sema); return result; } diff --git a/stage0/stages_test.zig b/stage0/stages_test.zig index 1fbb7eb327..bb7a7deb31 100644 --- a/stage0/stages_test.zig +++ b/stage0/stages_test.zig @@ -68,29 +68,34 @@ fn stagesCheck(gpa: Allocator, comptime path: []const u8, source: [:0]const u8) var module_root_buf: [std.fs.max_path_bytes:0]u8 = undefined; const module_root_path = std.fmt.bufPrintZ(&module_root_buf, "{s}", .{abs_repo_root}) catch unreachable; - var c_ip = sc.ipInit(); - defer sc.ipDeinit(&c_ip); + var comp: sc.Compilation = .{ .config = .{ + .module_root = module_root_path.ptr, + .target_cpu_arch = "wasm32", + .target_cpu_model = "lime1", + .object_format = "wasm", + .link_mode = "static", + .is_test = false, + } }; + const c_zcu = sc.zcuInit(&comp); + defer sc.zcuDeinit(c_zcu); var c_sema: sc.Sema = undefined; - sc.semaInit(&c_sema, &c_ip, @bitCast(c_zir)); + sc.semaInit(&c_sema, c_zcu, @bitCast(c_zir)); defer sc.semaDeinit(&c_sema); // Pre-generated AIR uses ReleaseSmall (strip=true), so match it. c_sema.strip = true; - // Set source_dir, module_root, root_fqn based on path prefix. + // Set source_dir, root_fqn based on path prefix. if (comptime std.mem.startsWith(u8, path, "stage0/")) { // Sema unit tests: set module_root to enable std/start/builtin // loading, matching the Zig compiler which always creates std // even with std_mod=null (Compilation.zig line 2196). c_sema.source_dir = source_dir_path.ptr; - c_sema.module_root = module_root_path.ptr; c_sema.root_fqn = comptime sema_test.pathStem(path); } else if (comptime std.mem.startsWith(u8, path, "lib/std/")) { c_sema.source_dir = source_dir_path.ptr; - c_sema.module_root = module_root_path.ptr; c_sema.root_fqn = "std"; c_sema.module_prefix = sema_test.pathToModulePrefix(path); } else { c_sema.source_dir = source_dir_path.ptr; - c_sema.module_root = module_root_path.ptr; c_sema.root_fqn = comptime sema_test.pathStem(path); } var c_func_air_list = sc.semaAnalyze(&c_sema); diff --git a/stage0/zcu.c b/stage0/zcu.c new file mode 100644 index 0000000000..27c64f276b --- /dev/null +++ b/stage0/zcu.c @@ -0,0 +1,30 @@ +#include "zcu.h" +#include + +Zcu* zcuInit(Compilation* comp) { + Zcu* zcu = (Zcu*)calloc(1, sizeof(Zcu)); + if (!zcu) + exit(1); + zcu->ip = ipInit(); + zcu->comp = comp; + // Initialize sentinel values. + zcu->std_file_idx = UINT32_MAX; + zcu->builtin_file_idx = UINT32_MAX; + zcu->cg_builtin_ns_idx = UINT32_MAX; + zcu->cg_builtin_nav = UINT32_MAX; + return zcu; +} + +void zcuDeinit(Zcu* zcu) { + // Free loaded file ASTs and ZIRs. + for (uint32_t i = 0; i < zcu->num_files; i++) { + ZcuFile* f = &zcu->files[i]; + if (f->has_zir) { + zirDeinit(&f->zir); + astDeinit(&f->ast); + } + } + ipDeinit(&zcu->ip); + // zcuAlloc uses calloc; free the struct itself. + free(zcu); +} diff --git a/stage0/zcu.h b/stage0/zcu.h new file mode 100644 index 0000000000..a20405f0d5 --- /dev/null +++ b/stage0/zcu.h @@ -0,0 +1,109 @@ +// zcu.h — ported from src/Zcu.zig + src/Zcu/PerThread.zig. +// Holds all module-level state for a compilation unit. +#ifndef _ZIG0_ZCU_H__ +#define _ZIG0_ZCU_H__ + +#include "ast.h" +#include "compilation.h" +#include "intern_pool.h" +#include "zir.h" +#include +#include + +// --- ZcuFile (matches Zcu.File) --- +// Per-source-file state. + +#define ZCU_MAX_FILES 512 + +typedef struct { + char path[1024]; // canonical file path + char source_dir[1024]; // directory containing this file + Zir zir; // parsed ZIR (inst_len>0 if loaded) + Ast ast; // AST (kept alive to own source memory) + bool has_zir; // true if zir/ast are populated + bool analyzed; // true if createFileRootStructC has been called +} ZcuFile; + +// --- ZcuNamespace (matches Zcu.Namespace) --- + +#define ZCU_NS_MAX_NAVS 1024 +#define ZCU_NS_MAX_COMPTIME 64 +#define ZCU_MAX_NAMESPACES 512 + +typedef struct { + InternPoolIndex owner_type; // type_struct IP index + uint32_t file_idx; // index into files[] + uint32_t pub_navs[ZCU_NS_MAX_NAVS]; + uint32_t pub_nav_count; + uint32_t priv_navs[ZCU_NS_MAX_NAVS]; + uint32_t priv_nav_count; + uint32_t comptime_decls[ZCU_NS_MAX_COMPTIME]; // ZIR inst indices + uint32_t comptime_decl_count; +} ZcuNamespace; + +// --- Zcu struct (matches Zcu.zig) --- +// Heap-allocated (use zcuInit/zcuDeinit); too large for stack. + +#define NUM_BUILTIN_DECL_MAIN 36 + +typedef struct Zcu { + InternPool ip; // owns IP; matches Zcu.intern_pool + + // --- File management (matches Zcu.import_table / Zcu.File) --- + ZcuFile files[ZCU_MAX_FILES]; // matches Zcu.files + uint32_t num_files; + uint32_t root_file_idx; + uint32_t std_file_idx; + uint32_t builtin_file_idx; + + // --- Builtin namespace/nav --- + uint32_t cg_builtin_ns_idx; // compiler-generated builtin namespace + uint32_t cg_builtin_nav; + + // --- Struct type hashing (C-specific) --- + uint32_t next_struct_hash; // unique hash counter for struct types + + // --- Analysis state --- + bool in_main_analysis; + uint32_t enum_force_intern_threshold; + + // --- Namespaces (matches Zcu.Namespace storage) --- + ZcuNamespace namespaces[ZCU_MAX_NAMESPACES]; + uint32_t num_namespaces; + InternPoolIndex file_root_types[ZCU_MAX_FILES]; + uint32_t file_namespaces[ZCU_MAX_FILES]; + + // --- Type/layout resolution tracking --- + bool struct_layout_resolved[4096]; + bool struct_fully_resolved[4096]; + bool union_fully_resolved[4096]; + InternPoolIndex union_tag_enums[256]; + InternPoolIndex union_tag_types[256]; + uint32_t num_union_tag_enums; + + // --- Memoized builtin state (matches Zcu.builtin_decl_values) --- + bool memoized_main_resolved; + bool full_memoized_resolved; + InternPoolIndex builtin_decl_values[NUM_BUILTIN_DECL_MAIN]; + + // --- Preamble IP range tracking (C-specific shard simulation) --- + uint32_t preamble_memoized_start; + uint32_t preamble_memoized_end; + uint32_t preamble_cc_start; + uint32_t preamble_cc_end; + uint32_t preamble_builtin_navs[5]; + uint32_t preamble_builtin_nav_count; + + // --- Compilation config --- + Compilation* comp; // back-pointer; matches Zcu.comp in Zig +} Zcu; + +// --- Function declarations --- + +// Allocate and initialize a Zcu on the heap (too large for stack). +Zcu* zcuInit(Compilation* comp); + +// Free all resources including the struct itself (matches zcuInit). +void zcuDeinit(Zcu* zcu); + +#endif diff --git a/stage0/zcu_per_thread.h b/stage0/zcu_per_thread.h new file mode 100644 index 0000000000..922bd293c8 --- /dev/null +++ b/stage0/zcu_per_thread.h @@ -0,0 +1,67 @@ +// zcu_per_thread.h — ported from src/Zcu/PerThread.zig. +// Functions for per-thread analysis orchestration. +#ifndef _ZIG0_ZCU_PER_THREAD_H__ +#define _ZIG0_ZCU_PER_THREAD_H__ + +#include "zcu.h" +#include "zir.h" +#include +#include + +// Forward declaration: avoid including sema.h here. +struct Sema; + +// These match PerThread.zig functions (taking Sema* for Zcu access): + +// Load, parse, and analyze an imported file. Returns the file index, +// or UINT32_MAX on failure. (matches PerThread.ensureFileAnalyzed) +uint32_t ensureFileAnalyzedC(struct Sema* sema, const char* full_path); + +// Create the root struct type for a file. (matches +// PerThread.createFileRootStruct) +InternPoolIndex createFileRootStructC( + struct Sema* sema, uint32_t file_idx, const Zir* zir); + +// Scan a namespace, building its Nav list. (matches PerThread.scanNamespace) +void scanNamespaceC(struct Sema* sema, uint32_t ns_idx, + const uint32_t* decl_insts, uint32_t decls_len, const Zir* zir); + +// Analyze a nav declaration's value. (matches PerThread.analyzeNavVal) +InternPoolIndex analyzeNavValC(struct Sema* sema, uint32_t nav_idx); + +// Resolve memoized state for .main builtins. (matches +// PerThread.analyzeMemoizedState) +void analyzeMemoizedStateC(struct Sema* sema); + +// Ensure a Nav's value is up to date. +InternPoolIndex ensureNavValUpToDate(struct Sema* sema, uint32_t nav_idx); + +// Resolve all 36 .main-stage builtins. (matches +// PerThread.ensureFullMemoizedState) +void ensureFullMemoizedStateC(struct Sema* sema); + +// Handle @import. (matches PerThread.importFile / doImport) +uint32_t doImport( + struct Sema* sema, const char* source_dir, const char* import_string); + +// Resolve struct layout (field offsets). +bool resolveStructLayoutC(struct Sema* sema, uint32_t nav_idx); + +// Resolve struct fully (field types). +void resolveStructFullyC(struct Sema* sema, uint32_t nav_idx); + +// Resolve union fully (field types + tag enum). +void resolveUnionFullyC(struct Sema* sema, uint32_t nav_idx); + +// Find namespace index for a type IP index. +uint32_t findNamespaceForType(struct Sema* sema, InternPoolIndex type_ip); + +// Find a nav in a namespace by name. Returns UINT32_MAX if not found. +uint32_t findNavInNamespace( + struct Sema* sema, uint32_t ns_idx, const char* name); + +// Analyze a comptime block at file scope. +void analyzeComptimeUnit( + struct Sema* sema, uint32_t file_idx, uint32_t comptime_decl); + +#endif diff --git a/stage0/zig0.c b/stage0/zig0.c index 2cd8d9f30c..bf29b999ba 100644 --- a/stage0/zig0.c +++ b/stage0/zig0.c @@ -1,9 +1,11 @@ #include "ast.h" #include "astgen.h" +#include "compilation.h" #include "intern_pool.h" #include "sema.h" #include "verbose_air.h" #include "verbose_intern_pool.h" +#include "zcu.h" #include "zir.h" #include @@ -44,19 +46,25 @@ static int zig0Run(const char* program, const char* source_dir, fprintf(stderr, "zir: %u instructions, %u extra, %u string bytes\n", zir.inst_len, zir.extra_len, zir.string_bytes_len); - InternPool ip = ipInit(); + Compilation comp; + comp.config.module_root = module_root; + comp.config.target_cpu_arch = "wasm32"; + comp.config.target_cpu_model = "lime1"; + comp.config.object_format = "wasm"; + comp.config.link_mode = "static"; + comp.config.is_test = false; + Zcu* zcu = zcuInit(&comp); Sema sema; - semaInit(&sema, &ip, zir); + semaInit(&sema, zcu, zir); sema.source_dir = source_dir; - sema.module_root = module_root; SemaFuncAirList func_airs = semaAnalyze(&sema); if (verbose_intern_pool) - verboseIpPrint(stderr, &ip); + verboseIpPrint(stderr, &zcu->ip); if (verbose_air) - verboseAirPrint(stderr, &func_airs, &ip); + verboseAirPrint(stderr, &func_airs, &zcu->ip); semaDeinit(&sema); semaFuncAirListDeinit(&func_airs); - ipDeinit(&ip); + zcuDeinit(zcu); zirDeinit(&zir); return 0; }