commit ae0ff31bac5cf62505b9e4855c7435a73ab3920a (tree)
parent 09df9ce9931d2c6aa95b83669209feed69b16356
Author: Motiejus <motiejus@jakstys.lt>
Date: Mon, 2 Mar 2026 01:12:47 +0000
sema: fix AddressSpace comptime_int false dedup for test 54
AddressSpace enum field values (comptime_int 0..23) go into C's single
IP hash table during memoized resolution. In the Zig compiler's sharded
IP, these entries are in a different shard and don't participate in dedup
during main analysis. CC tag values (0..12) ARE in Zig's local shard.
Use ipForceIntern for AddressSpace values >= 13 (the CC tag value count
for wasm32-wasi) to keep them out of the hash table. This prevents false
dedup where e.g. comptime_int(16) matches AddressSpace.flash1 instead of
creating a new entry.
Enables bitmask_shift_and.zig (test 54, num_passing=55).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -129,6 +129,17 @@ static bool s_config_is_test = false;
// 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
@@ -2910,12 +2921,21 @@ static InternPoolIndex resolveEnumDeclFromZir(
// 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).
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 = ipIntern(s_module_ip, ct);
+ InternPoolIndex ct_ip;
+ if (s_enum_force_intern_threshold > 0
+ && auto_val >= s_enum_force_intern_threshold) {
+ ct_ip = ipForceIntern(s_module_ip, ct);
+ } else {
+ ct_ip = ipIntern(s_module_ip, ct);
+ }
// Then coerce to tag type.
(void)coerceIntToTagType(ct_ip, int_tag_type);
} else if (int_tag_type != IP_INDEX_NONE) {
@@ -10372,6 +10392,23 @@ static void analyzeMemoizedStateC(void) {
// (ptr_type + ptr_nav + name) that the C sema previously created
// in zirFunc to compensate.
int memoized_limit = 5;
+
+ // 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.
+ // In the Zig compiler's sharded IP, these entries are in a different
+ // shard and don't participate in dedup during main analysis. However,
+ // CC tag enum values (created lazily during start.zig comptime) ARE
+ // in Zig's local shard and DO participate in dedup. For wasm32-wasi,
+ // the Zig compiler resolves 13 CC tag values (0..12). In C's single
+ // pool, AddressSpace values 0..12 serve as the dedup targets for
+ // those CC-range values. AddressSpace values >= 13 must NOT be in
+ // the hash table to prevent false dedup (e.g. comptime_int(16) =
+ // AddressSpace.flash1 must not match a function body literal 16).
+ // 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;
+
for (int i = 0; i < memoized_limit; i++) {
const BuiltinDeclEntry* entry = &s_builtin_decl_entries[i];
@@ -10412,6 +10449,10 @@ static void analyzeMemoizedStateC(void) {
// Struct/Union: skip (resolveTypeFullyC too deep).
}
}
+
+ // Disable the threshold after memoized resolution so future
+ // enum resolutions during main analysis use normal ipIntern.
+ s_enum_force_intern_threshold = 0;
}
// --- zirExport ---