sema: merge memoized state into single pass, matching Zig
Upstream Zig resolves ALL 36 builtins (0-35) in a single pass via analyzeMemoizedState(.main). The C sema previously split this into two passes (CC: 0-14, then main: 15-35), creating entries in different order than Zig. Merge into a single-pass approach: - Remove ensureCcMemoizedStateC and cc_memoized_resolved field - Rewrite ensureFullMemoizedStateC to clear all state and resolve all builtins 0-35 in one pass when shard simulation is active - This improves IP entry count alignment by ~122 entries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4764,6 +4764,8 @@ static void resolveStructFieldInitsC(Sema* sema, const Zir* zir,
|
||||
if (lit_name != NULL) {
|
||||
// Find matching enum type in the struct's namespace,
|
||||
// then fall back to the file root namespace.
|
||||
// Ported from Sema.zig structFieldInits → resolveInlineBody
|
||||
// → coerce path which resolves enum types on demand.
|
||||
uint32_t ns_search[2];
|
||||
ns_search[0] = struct_ns;
|
||||
ns_search[1] = sema->zcu->file_namespaces[file_idx];
|
||||
@@ -4772,7 +4774,8 @@ static void resolveStructFieldInitsC(Sema* sema, const Zir* zir,
|
||||
const ZcuNamespace* sns
|
||||
= &sema->zcu->namespaces[ns_search[nk]];
|
||||
for (uint32_t j = 0; j < sns->pub_nav_count; j++) {
|
||||
const Nav* enav = ipGetNav(sema->ip, sns->pub_navs[j]);
|
||||
uint32_t nav_j = sns->pub_navs[j];
|
||||
const Nav* enav = ipGetNav(sema->ip, nav_j);
|
||||
if (enav->resolved_type == IP_INDEX_NONE)
|
||||
continue;
|
||||
if (sema->ip->items[enav->resolved_type].tag
|
||||
@@ -14091,9 +14094,9 @@ SemaFuncAirList semaAnalyze(Sema* sema) {
|
||||
// IP these are in the preamble shard and are NOT visible to
|
||||
// main analysis, so main analysis creates fresh copies.
|
||||
//
|
||||
// Reset cc_memoized_resolved so ensureCcMemoizedStateC
|
||||
// Reset full_memoized_resolved so ensureFullMemoizedStateC
|
||||
// re-runs in main analysis with skip_dedup active, creating
|
||||
// fresh CC sub-type entries at main analysis IP indices.
|
||||
// fresh entries for all builtins at main analysis IP indices.
|
||||
if (sema->zcu->preamble_memoized_end
|
||||
> sema->zcu->preamble_memoized_start) {
|
||||
sema->ip->skip_dedup_start
|
||||
@@ -14101,7 +14104,7 @@ SemaFuncAirList semaAnalyze(Sema* sema) {
|
||||
sema->ip->skip_dedup_end = sema->ip->items_len;
|
||||
sema->ip->cc_keep_start = sema->zcu->preamble_cc_start;
|
||||
sema->ip->cc_keep_end = sema->zcu->preamble_cc_end;
|
||||
sema->zcu->cc_memoized_resolved = false;
|
||||
sema->zcu->full_memoized_resolved = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -83,8 +83,7 @@ typedef struct Zcu {
|
||||
|
||||
// --- Memoized builtin state (matches Zcu.builtin_decl_values) ---
|
||||
bool memoized_main_resolved;
|
||||
bool cc_memoized_resolved; // builtins 0-14 resolved (CC phase)
|
||||
bool full_memoized_resolved; // builtins 15-35 resolved (Type phase)
|
||||
bool full_memoized_resolved; // all builtins 0-35 resolved in main shard
|
||||
InternPoolIndex builtin_decl_values[NUM_BUILTIN_DECL_MAIN];
|
||||
|
||||
// --- Preamble IP range tracking (C-specific shard simulation) ---
|
||||
|
||||
@@ -1192,71 +1192,57 @@ void analyzeMemoizedStateC(Sema* sema) {
|
||||
sema->zcu->preamble_memoized_end = sema->ip->items_len;
|
||||
}
|
||||
|
||||
// Resolve builtins 0-14 (CC phase: Signedness through BranchHint).
|
||||
// Called when a function with explicit callconv body is resolved,
|
||||
// matching Zig's analyzeMemoizedState(.main) behavior: the cc body
|
||||
// evaluation calls getBuiltinType(.CallingConvention) which triggers
|
||||
// resolution of all CC-related builtins (0-14) before func_type is
|
||||
// created. Builtins 15-35 (Type and sub-types) are deferred until
|
||||
// actually needed (e.g. @typeInfo / @Type in function body analysis).
|
||||
void ensureCcMemoizedStateC(Sema* sema) {
|
||||
if (sema->zcu->cc_memoized_resolved)
|
||||
return;
|
||||
sema->zcu->cc_memoized_resolved = true;
|
||||
|
||||
// First ensure builtins 0-4 are resolved (preamble state).
|
||||
void ensureFullMemoizedStateC(Sema* sema) {
|
||||
// First ensure preamble builtins 0-4 are resolved.
|
||||
analyzeMemoizedStateC(sema);
|
||||
|
||||
if (sema->zcu->full_memoized_resolved)
|
||||
return;
|
||||
sema->zcu->full_memoized_resolved = true;
|
||||
|
||||
// Only do full resolution when shard simulation is active
|
||||
// (skip_dedup range set). During comptime analysis (before shard
|
||||
// simulation setup), the preamble builtins 0-4 are sufficient.
|
||||
if (sema->ip->skip_dedup_start >= sema->ip->skip_dedup_end)
|
||||
return;
|
||||
|
||||
if (sema->zcu->builtin_file_idx == UINT32_MAX)
|
||||
return;
|
||||
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. The skip_dedup range is
|
||||
// already set at preamble end (see preamble setup). Clear ALL navs
|
||||
// whose resolved_type points into the preamble shard, so that
|
||||
// ensureNavValUpToDate re-resolves them (including CC sub-type navs
|
||||
// like X86SysV etc.). Also clear struct/union/layout fully-resolved
|
||||
// flags so resolveUnionFullyC/resolveStructFullyC re-run for the
|
||||
// main shard — this creates CC enum_tag entries and struct field
|
||||
// layouts that Zig's per-shard IP emits during main analysis.
|
||||
if (sema->zcu->preamble_memoized_end
|
||||
> sema->zcu->preamble_memoized_start) {
|
||||
// Clear builtins 0-14 values so they're re-resolved fresh in
|
||||
// main analysis. Matches Zig's per-shard isolation where main
|
||||
// analysis creates fresh copies of all CC-phase builtins.
|
||||
for (int i = 0; i < 15 && i < NUM_BUILTIN_DECL_MAIN; i++)
|
||||
sema->zcu->builtin_decl_values[i] = IP_INDEX_NONE;
|
||||
// Shard simulation: clear ALL builtin values and nav state so
|
||||
// everything gets re-resolved as fresh entries in the main shard.
|
||||
// Matches Zig's sharded IP where main shard starts fresh.
|
||||
for (int i = 0; i < NUM_BUILTIN_DECL_MAIN; i++)
|
||||
sema->zcu->builtin_decl_values[i] = IP_INDEX_NONE;
|
||||
|
||||
// Clear nav resolved_type for ALL navs resolved during preamble.
|
||||
// Simulates Zig's per-shard isolation: main shard starts fresh.
|
||||
for (uint32_t n = 0; n < sema->ip->nav_count; n++) {
|
||||
Nav* nav_ptr = ipGetNav(sema->ip, n);
|
||||
if (nav_ptr->resolved_type != IP_INDEX_NONE
|
||||
&& nav_ptr->resolved_type >= sema->ip->skip_dedup_start
|
||||
&& nav_ptr->resolved_type < sema->ip->skip_dedup_end) {
|
||||
nav_ptr->resolved_type = IP_INDEX_NONE;
|
||||
}
|
||||
// Clear nav resolved_type for ALL navs resolved during preamble.
|
||||
// Simulates Zig's per-shard isolation: main shard starts fresh.
|
||||
for (uint32_t n = 0; n < sema->ip->nav_count; n++) {
|
||||
Nav* nav_ptr = ipGetNav(sema->ip, n);
|
||||
if (nav_ptr->resolved_type != IP_INDEX_NONE
|
||||
&& nav_ptr->resolved_type >= sema->ip->skip_dedup_start
|
||||
&& nav_ptr->resolved_type < sema->ip->skip_dedup_end) {
|
||||
nav_ptr->resolved_type = IP_INDEX_NONE;
|
||||
}
|
||||
|
||||
// Clear all struct/union/layout resolution flags so main analysis
|
||||
// re-resolves all types in the main shard (matches Zig sharding).
|
||||
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));
|
||||
}
|
||||
|
||||
// Resolve builtins 0-14 (Signedness through BranchHint):
|
||||
// ensureNavValUpToDate + resolveTypeFullyC per builtin.
|
||||
// Builtins 15-35 are handled by ensureFullMemoizedStateC after this.
|
||||
for (int i = 0; i < 15 && i < NUM_BUILTIN_DECL_MAIN; i++) {
|
||||
if (sema->zcu->builtin_decl_values[i] != IP_INDEX_NONE) {
|
||||
// Clear struct/union/layout resolution flags so main analysis
|
||||
// re-resolves all types in the main shard (matches Zig sharding).
|
||||
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));
|
||||
|
||||
// Single pass over ALL builtins 0-35, matching Zig's
|
||||
// analyzeMemoizedState which processes all .main-stage builtins
|
||||
// in one iteration. Ported from Sema.zig line 37531.
|
||||
for (int i = 0; i < NUM_BUILTIN_DECL_MAIN; i++) {
|
||||
if (sema->zcu->builtin_decl_values[i] != IP_INDEX_NONE)
|
||||
continue;
|
||||
}
|
||||
|
||||
const BuiltinDeclEntry* entry = &s_builtin_decl_entries[i];
|
||||
uint32_t lookup_ns;
|
||||
@@ -1289,67 +1275,6 @@ void ensureCcMemoizedStateC(Sema* sema) {
|
||||
}
|
||||
}
|
||||
|
||||
void ensureFullMemoizedStateC(Sema* sema) {
|
||||
// First resolve CC-phase builtins 0-14 (including preamble setup).
|
||||
// Matches Zig's ensureMemoizedStateUpToDate(.main) which processes
|
||||
// builtins 0-14 (CC phase) then builtins 15-35 (Type phase) in one pass.
|
||||
ensureCcMemoizedStateC(sema);
|
||||
|
||||
if (sema->zcu->full_memoized_resolved)
|
||||
return;
|
||||
sema->zcu->full_memoized_resolved = true;
|
||||
|
||||
if (sema->zcu->builtin_file_idx == UINT32_MAX)
|
||||
return;
|
||||
uint32_t builtin_ns
|
||||
= sema->zcu->file_namespaces[sema->zcu->builtin_file_idx];
|
||||
|
||||
// Resolve builtins 15-35 (Type and sub-types): ensureNavValUpToDate
|
||||
// + resolveTypeFullyC per builtin. Matches Zig's analyzeMemoizedState
|
||||
// which processes all .main-stage builtins in one pass.
|
||||
for (int i = 15; i < NUM_BUILTIN_DECL_MAIN; i++) {
|
||||
if (sema->zcu->builtin_decl_values[i] != IP_INDEX_NONE)
|
||||
continue;
|
||||
|
||||
const BuiltinDeclEntry* entry = &s_builtin_decl_entries[i];
|
||||
uint32_t lookup_ns;
|
||||
if (entry->parent_idx < 0) {
|
||||
lookup_ns = builtin_ns;
|
||||
} else {
|
||||
InternPoolIndex parent_type
|
||||
= sema->zcu->builtin_decl_values[entry->parent_idx];
|
||||
if (parent_type == IP_INDEX_NONE)
|
||||
continue;
|
||||
lookup_ns = findNamespaceForType(sema, parent_type);
|
||||
if (lookup_ns == UINT32_MAX)
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t nav = findNavInNamespace(sema, lookup_ns, entry->lookup_name);
|
||||
if (nav == UINT32_MAX)
|
||||
continue;
|
||||
|
||||
InternPoolIndex val = ensureNavValUpToDate(sema, nav);
|
||||
if (val == IP_INDEX_NONE)
|
||||
continue;
|
||||
|
||||
// Create ptr_type + ptr_nav matching Zig's analyzeNavRefInner.
|
||||
{
|
||||
InternPoolIndex child = entry->is_type ? IP_INDEX_TYPE_TYPE : val;
|
||||
InternPoolIndex ptr_ty = internPtrConst(sema, child);
|
||||
(void)internNavPtr(sema, ptr_ty, nav);
|
||||
}
|
||||
|
||||
sema->zcu->builtin_decl_values[i] = val;
|
||||
|
||||
// Immediately resolveFully for type builtins, matching Zig's
|
||||
// analyzeMemoizedState line 37560:
|
||||
// uncoerced_val.toType().resolveFully(pt).
|
||||
if (entry->is_type)
|
||||
resolveTypeFullyC(sema, val);
|
||||
}
|
||||
}
|
||||
|
||||
InternPoolIndex getBuiltinTypeC(Sema* sema, int builtin_idx) {
|
||||
ensureFullMemoizedStateC(sema);
|
||||
return sema->zcu->builtin_decl_values[builtin_idx];
|
||||
|
||||
@@ -39,13 +39,8 @@ void analyzeMemoizedStateC(struct Sema* sema);
|
||||
// (matches PerThread.ensureNavValUpToDate)
|
||||
InternPoolIndex ensureNavValUpToDate(struct Sema* sema, uint32_t nav_idx);
|
||||
|
||||
// Resolve builtins 0-14 (.main CC phase, analogous to the CC stage
|
||||
// of PerThread.analyzeMemoizedState). Called when cc body is evaluated.
|
||||
void ensureCcMemoizedStateC(struct Sema* sema);
|
||||
|
||||
// Resolve all 36 .main-stage builtins (calls ensureCcMemoizedStateC
|
||||
// for 0-14 then resolves 15-35).
|
||||
// (matches PerThread.ensureMemoizedStateUpToDate)
|
||||
// Resolve all 36 .main-stage builtins in a single pass.
|
||||
// (matches PerThread.ensureMemoizedStateUpToDate / analyzeMemoizedState)
|
||||
void ensureFullMemoizedStateC(struct Sema* sema);
|
||||
|
||||
// Handle @import. (matches PerThread.doImport)
|
||||
|
||||
Reference in New Issue
Block a user