commit 1a947d3db434832ae30c7cedb1cfd364999dc078 (tree)
parent 8e876c92a8def88c4085db6ecc7b80f28237d1c2
Author: Motiejus <motiejus@jakstys.lt>
Date: Sun, 1 Mar 2026 17:38:04 +0000
stage0: fix comptime call frame and memoized_call entries
Two fixes for IP entry alignment with the Zig compiler:
1. Skip call frame setup (ptr_uav, undef, ptr_comptime_alloc) when
both parameter and return types are pre-interned. The Zig compiler
doesn't create these entries for trivial comptime calls like
debug.assert(true) where everything deduplicates to existing entries.
2. Create memoized_call entries even for void-returning functions.
The Zig compiler always creates memoized_call for comptime function
calls, including void results.
3. Don't create the dbg_inline_block func IP entry in comptime context
where no AIR is emitted. This removes a spurious func entry with
ty=0 that appeared in the IP sequence.
These fixes align entries $124-$135 between C sema and Zig compiler
for return_integer.zig. Remaining gap: 66 entries starting at $136.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | stage0/sema.c | | | 78 | +++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
1 file changed, 43 insertions(+), 35 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -6255,8 +6255,9 @@ static AirInstRef comptimeFieldCall(Sema* sema, SemaBlock* block,
// --- Call frame setup for comptime function calls ---
// Ported from Sema.zig analyzeCall comptime path.
// Creates: *const param_type, ptr_uav, *mut return_type, undef,
- // ptr_comptime_alloc. These must be created before body evaluation
- // to match the Zig compiler's IP entry order.
+ // ptr_comptime_alloc. These are only created when the types are
+ // non-pre-interned (the Zig compiler skips them for pre-interned
+ // types because they get deduped to existing entries).
{
// Get function type to extract return type.
const Nav* fn_nav_resolved = ipGetNav(fn_nav_idx);
@@ -6272,18 +6273,19 @@ static AirInstRef comptimeFieldCall(Sema* sema, SemaBlock* block,
// Set inner sema's return type so zirRetPtr/zirRetType
// produce the correct pointer type during body evaluation.
fn_sema.fn_ret_ty = ret_ty;
- // Create *const param_type (pointer to the parameter).
- InternPoolIndex param_ptr_ty = internPtrConst(obj_type);
- // Create ptr_uav wrapping the parameter value.
- (void)internPtrUav(param_ptr_ty, obj_ip);
- // Create *mut return_type for the return value alloc.
- InternPoolIndex ret_mut_ptr = internPtrMutable(ret_ty);
- // Create undef(return_type).
- (void)internUndef(ret_ty);
- // Create ptr_comptime_alloc for return value storage.
- InternPoolIndex ret_alloc
- = internPtrComptimeAlloc(ret_mut_ptr, 0);
- fn_sema.comptime_ret_ptr = ret_alloc;
+ // Only create call frame entries for non-pre-interned
+ // types. When both param and return types are pre-interned,
+ // 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 ret_alloc
+ = internPtrComptimeAlloc(ret_mut_ptr, 0);
+ fn_sema.comptime_ret_ptr = ret_alloc;
+ }
}
}
}
@@ -6320,22 +6322,23 @@ static AirInstRef comptimeFieldCall(Sema* sema, SemaBlock* block,
semaBlockDeinit(&fn_block);
semaDeinit(&fn_sema);
- // Create memoized_call entry if we got a real result.
+ // Create memoized_call entry for the comptime call result.
// Ported from Sema.zig analyzeCall comptime path (line 7889-7898).
- if (AIR_REF_IS_IP(result)) {
- InternPoolIndex result_ip = AIR_REF_TO_IP(result);
- if (result_ip != IP_INDEX_VOID_VALUE) {
- const Nav* fn_nav2 = ipGetNav(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) {
- 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);
- }
+ // The Zig compiler creates memoized_call even for void results.
+ {
+ 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);
+ InternPoolIndex func_ip = fn_nav2->resolved_type;
+ if (func_ip != IP_INDEX_NONE
+ && s_module_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);
}
}
@@ -7590,12 +7593,17 @@ static AirInstRef zirCall(
// Intern a func value for the dbg_inline_block's func field.
// The exact value doesn't matter for correctness; it just needs to be
// a unique IP index that the comparison can canonicalize.
- InternPoolKey func_key;
- memset(&func_key, 0, sizeof(func_key));
- func_key.tag = IP_KEY_FUNC;
- func_key.data.func_decl.owner_nav = func_inst;
- func_key.data.func_decl.ty = 0; // use ZIR inst as unique id
- InternPoolIndex func_ip = ipIntern(sema->ip, func_key);
+ // Only create when need_debug_scope is true (non-comptime, non-strip);
+ // in comptime context, no AIR is emitted so no IP entry is needed.
+ InternPoolIndex func_ip = IP_INDEX_NONE;
+ if (need_debug_scope) {
+ InternPoolKey func_key;
+ memset(&func_key, 0, sizeof(func_key));
+ func_key.tag = IP_KEY_FUNC;
+ func_key.data.func_decl.owner_nav = func_inst;
+ func_key.data.func_decl.ty = 0; // use ZIR inst as unique id
+ func_ip = ipIntern(sema->ip, func_key);
+ }
SemaBlockInlining inlining;
memset(&inlining, 0, sizeof(inlining));