commit 7c7f65625a2ec012cd42a963329098982a0c9c76 (tree)
parent 7b0bb54b5c8af3bcfca57432e43fd78cae36c703
Author: Motiejus <motiejus@jakstys.lt>
Date: Sat, 28 Feb 2026 16:56:05 +0000
sema: replace resolveBuiltinModuleChain with demand-driven import resolution
Replace the manual std → std/builtin.zig → CG builtin module chain
construction with targeted ensureNavValUpToDate calls that trigger the
same chain through normal import resolution:
1. Resolve start.zig's "builtin" import via ensureNavValUpToDate
2. Resolve std.zig's "builtin" import → loads std/builtin.zig
3. resolveModuleDeclImports on std/builtin.zig → resolves its "std"
and "builtin" imports, the latter creating CG builtin on demand
Add ensureCgBuiltinModule() that creates the virtual CG builtin module
on first @import("builtin") encounter. Add @import("root") handling
ported from PerThread.zig doImport.
Remove resolveBuiltinModuleChain (now dead code) and its hardcoded
path matching ("/std/std.zig") and IP index comments ($137-$141).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | stage0/sema.c | | | 194 | ++++++++++++++++++++++++++++++++----------------------------------------------- |
1 file changed, 78 insertions(+), 116 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -2301,7 +2301,35 @@ static InternPoolIndex createModuleStructType(void) {
return ipIntern(s_module_ip, key);
}
-// (ensureModuleStructType removed — replaced by ensureFileAnalyzedC)
+// Forward declaration for createNamespace (defined below).
+static uint32_t createNamespace(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) {
+ // Already created — return cached type.
+ if (s_cg_builtin_ns_idx != UINT32_MAX)
+ return s_namespaces[s_cg_builtin_ns_idx].owner_type;
+
+ if (!s_module_ip || s_num_loaded_modules >= MAX_LOADED_MODULES)
+ 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];
+ memset(cg_mod, 0, sizeof(*cg_mod));
+ snprintf(cg_mod->path, sizeof(cg_mod->path), "<builtin>");
+ 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;
+
+ return cg_struct;
+}
// --- Namespace creation ---
// Ported from Zcu.Namespace.
@@ -2570,107 +2598,7 @@ static uint32_t findNavInNamespace(uint32_t ns_idx, const char* name) {
// Forward declaration for resolveModuleDeclImports (used below).
static void resolveModuleDeclImports(uint32_t file_idx, uint32_t depth);
-// --- resolveBuiltinModuleChain ---
-// Ported from PerThread.zig analyzeMemoizedState (module loading part).
-// After the root module and its direct imports are loaded, this function
-// continues loading the module chain needed by @export resolution:
-// std → std/builtin.zig → compiler-generated builtin → ...
-// Creates type_struct and ptr_nav entries in the same order as the
-// Zig compiler's demand-driven analysis.
-
-static void resolveBuiltinModuleChain(uint32_t start_file_idx) {
- if (!s_module_ip || !s_global_module_root)
- return;
-
- // Find std module among loaded modules.
- uint32_t std_file_idx = UINT32_MAX;
- for (uint32_t i = 0; i < s_num_loaded_modules; i++) {
- const char* p = s_loaded_modules[i].path;
- size_t plen = strlen(p);
- // Match paths ending with "/std/std.zig" or "/std.zig"
- if (plen >= 12 && strcmp(p + plen - 12, "/std/std.zig") == 0) {
- std_file_idx = i;
- break;
- }
- }
- if (std_file_idx == UINT32_MAX)
- return;
- s_std_file_idx = std_file_idx;
-
- // Find `builtin` Nav in std's namespace.
- // In std.zig: `pub const builtin = @import("builtin.zig");`
- uint32_t std_ns_idx = s_file_namespace[std_file_idx];
- uint32_t builtin_nav = findNavInNamespace(std_ns_idx, "builtin");
- if (builtin_nav == UINT32_MAX)
- return;
-
- // Load std/builtin.zig → creates type_struct entry ($137).
- char builtin_path[1024];
- snprintf(builtin_path, sizeof(builtin_path), "%s/builtin.zig",
- s_loaded_modules[std_file_idx].source_dir);
- uint32_t builtin_file_idx = ensureFileAnalyzedC(builtin_path);
- if (builtin_file_idx == UINT32_MAX)
- return;
- s_builtin_file_idx = builtin_file_idx;
-
- InternPoolIndex ptr_type = internPtrConst(IP_INDEX_TYPE_TYPE);
-
- // $138: Create ptr_nav for `builtin` in start.zig's namespace.
- // start.zig has `const builtin = @import("builtin")` which is the
- // compiler-generated builtin. The Zig compiler evaluates this during
- // start.zig's comptime block processing.
- if (start_file_idx != UINT32_MAX) {
- uint32_t start_ns_idx = s_file_namespace[start_file_idx];
- uint32_t start_builtin_nav
- = findNavInNamespace(start_ns_idx, "builtin");
- if (start_builtin_nav != UINT32_MAX)
- (void)internNavPtr(ptr_type, start_builtin_nav);
- }
-
- // $139: Create ptr_nav for `std` in std/builtin.zig's namespace.
- uint32_t builtin_ns_idx = s_file_namespace[builtin_file_idx];
- uint32_t std_in_builtin_nav = findNavInNamespace(builtin_ns_idx, "std");
- if (std_in_builtin_nav != UINT32_MAX) {
- Nav* sNav = ipGetNav(std_in_builtin_nav);
- sNav->resolved_type = s_file_root_type[std_file_idx];
- (void)internNavPtr(ptr_type, std_in_builtin_nav);
- }
-
- // $140: Create CG builtin struct type.
- // std/builtin.zig imports @import("builtin") — the compiler-generated
- // builtin module. Create a type_struct for it even though we don't have
- // its source. The Zig compiler creates this struct in semaFile.
- uint32_t cg_builtin_nav_local
- = findNavInNamespace(builtin_ns_idx, "builtin");
- if (cg_builtin_nav_local != UINT32_MAX) {
- InternPoolIndex cg_struct = createModuleStructType();
-
- if (s_num_loaded_modules < MAX_LOADED_MODULES) {
- uint32_t cg_file_idx = s_num_loaded_modules++;
- LoadedModule* cg_mod = &s_loaded_modules[cg_file_idx];
- memset(cg_mod, 0, sizeof(*cg_mod));
- snprintf(cg_mod->path, sizeof(cg_mod->path), "<builtin>");
- 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;
-
- Nav* cgNav = ipGetNav(cg_builtin_nav_local);
- cgNav->resolved_type = cg_struct;
- // Save nav for deferred ptr_nav creation at $488.
- s_cg_builtin_nav = cg_builtin_nav_local;
- }
- }
-
- // $141: Create ptr_nav for `builtin` in std's namespace.
- // Deferred from earlier to match Zig compiler entry order.
- Nav* bNav = ipGetNav(builtin_nav);
- bNav->resolved_type = s_file_root_type[builtin_file_idx];
- (void)internNavPtr(ptr_type, builtin_nav);
-}
-
-// Forward declarations for functions used by resolveNamedImport.
+// 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,
@@ -4833,11 +4761,10 @@ static InternPoolIndex ensureNavValUpToDate(uint32_t nav_idx) {
= (const char*)&zir->string_bytes[path_idx];
// @import("builtin") — resolve to the compiler-generated
- // builtin module's root struct type.
+ // builtin module (created on demand).
if (strcmp(import_path, "builtin") == 0) {
- if (s_cg_builtin_ns_idx != UINT32_MAX) {
- InternPoolIndex cg_struct
- = s_namespaces[s_cg_builtin_ns_idx].owner_type;
+ InternPoolIndex cg_struct = ensureCgBuiltinModule();
+ if (cg_struct != IP_INDEX_NONE) {
Nav* wnav = ipGetNav(nav_idx);
wnav->resolved_type = cg_struct;
return cg_struct;
@@ -11412,12 +11339,12 @@ static bool analyzeBodyInner(
= findDeclImportPath(sema, decl_name_idx);
if (import_path) {
- if (strcmp(import_path, "builtin") == 0
- && s_cg_builtin_ns_idx != UINT32_MAX) {
+ if (strcmp(import_path, "builtin") == 0) {
// @import("builtin") — resolve to the CG
- // builtin module's root struct type.
- resolved
- = s_namespaces[s_cg_builtin_ns_idx].owner_type;
+ // builtin module (created on demand).
+ InternPoolIndex cg = ensureCgBuiltinModule();
+ if (cg != IP_INDEX_NONE)
+ resolved = cg;
} else if (strcmp(import_path, "root") == 0
&& s_root_file_idx != UINT32_MAX) {
// @import("root") — the user's root module.
@@ -11512,9 +11439,10 @@ static bool analyzeBodyInner(
= (const char*)&sema->code.string_bytes[path_idx];
InternPoolIndex result = IP_INDEX_VOID_VALUE;
- if (strcmp(import_path, "builtin") == 0
- && s_cg_builtin_ns_idx != UINT32_MAX) {
- result = s_namespaces[s_cg_builtin_ns_idx].owner_type;
+ if (strcmp(import_path, "builtin") == 0) {
+ InternPoolIndex cg = ensureCgBuiltinModule();
+ if (cg != IP_INDEX_NONE)
+ result = cg;
} else if (strcmp(import_path, "root") == 0
&& s_root_file_idx != UINT32_MAX) {
// @import("root") → the user's root module.
@@ -12238,8 +12166,42 @@ SemaFuncAirList semaAnalyze(Sema* sema) {
}
}
- // Load std/builtin.zig chain ($137+).
- resolveBuiltinModuleChain(start_file_idx);
+ // Load the builtin module chain by resolving specific
+ // import declarations, matching the upstream's memoized
+ // state analysis sequence.
+ // Ported from PerThread.zig analyzeMemoizedState.
+ if (std_file_idx != UINT32_MAX) {
+ s_std_file_idx = std_file_idx;
+ uint32_t std_ns_idx2 = s_file_namespace[std_file_idx];
+
+ // Resolve start.zig's "builtin" import ($138).
+ if (start_file_idx != UINT32_MAX) {
+ uint32_t start_ns = s_file_namespace[start_file_idx];
+ uint32_t sbn = findNavInNamespace(start_ns, "builtin");
+ if (sbn != UINT32_MAX)
+ (void)ensureNavValUpToDate(sbn);
+ }
+
+ // Resolve std.zig's "builtin" import → loads
+ // std/builtin.zig ($137), creates ptr_nav ($141).
+ uint32_t builtin_nav
+ = findNavInNamespace(std_ns_idx2, "builtin");
+ if (builtin_nav != UINT32_MAX) {
+ InternPoolIndex bval = ensureNavValUpToDate(builtin_nav);
+ if (bval != IP_INDEX_NONE) {
+ for (uint32_t fi = 0; fi < s_num_loaded_modules;
+ fi++) {
+ if (s_file_root_type[fi] == bval) {
+ s_builtin_file_idx = fi;
+ // Resolve std/builtin.zig's imports
+ // ($139 std, $140 CG builtin).
+ resolveModuleDeclImports(fi, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
} else {
// No module root — root module is file_idx=0.
if (s_num_loaded_modules == 0) {