Commit Graph

35317 Commits

Author SHA1 Message Date
9487bd9acf sema: add comptime float folding to analyzeArithmetic
When both operands are comptime-known floats (IP_KEY_FLOAT entries,
including comptime_float and concrete float types), fold the result
at comptime instead of emitting a runtime AIR instruction.

Ported from Sema.zig analyzeArithmetic: resolveValue(casted_lhs/rhs)
path which evaluates comptime values via arith.add/sub/mul.

Handles ADD, SUB, MUL variants (including wrap/sat) for both
comptime_float × comptime_float and concrete float × float. Result
type is the wider of the two float types.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 09:18:22 +00:00
fad25d34f9 sema: fix semaCoerce comptime_int → float coercion
When semaCoerce encounters comptime_int → concrete float (or
comptime_float), it was incorrectly calling semaCoerceIntRef which
produces an IP_KEY_INT entry with a float type — wrong.

Fix by detecting the float target first: convert the integer value
to a double and intern an IP_KEY_FLOAT entry. This matches Sema.zig
coerce comptime_int → float path.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 09:15:02 +00:00
247b9a03e4 sema: fix resolvePeerTypes for concrete float types
When both operands are concrete float types (e.g. f32 + f64),
resolvePeerTypes returned the lhs type regardless of width.
Ported from Sema.zig peer_resolve_float strategy: return the
wider float type.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 09:13:42 +00:00
3fadb3583e sema: fix comptime_float handling in zirNegate, zirNegateWrap, zirAbs
zirNegate and zirNegateWrap: extend the float detection to include
IP_INDEX_COMPTIME_FLOAT_TYPE. Previously floatBits() returned 0 for
comptime_float, causing negate to fall through to integer path.
This fixes -(comptime_float) and -(comptime_float) wrap.

zirAbs: similarly extend float check to include comptime_float so
@abs on comptime_float values is properly folded at comptime.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 09:12:17 +00:00
b537605009 sema: fix zirCmpEq equality check to include sign for comptime ints
The comptime equality check compared only lo/hi magnitude fields,
ignoring is_negative. This meant (-5) == 5 would return true.

Fix by also checking lhs_neg == rhs_neg. Zero is never negative
(internComptimeInt already clears neg for zero values), so this
handles the -0 == 0 edge case correctly.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 09:09:35 +00:00
5e1ea76798 sema: fix zirCmp signed comparison for comptime integers
The comptime folding path in zirCmp used unsigned comparison of
the magnitude fields (lo/hi), ignoring the is_negative sign flag.
This gave wrong results for mixed-sign comparisons like (-5) < 3.

Replace with a proper signed 128-bit comparison that:
- If signs differ: negative < positive
- Both non-negative: compare magnitudes in ascending order
- Both negative: compare magnitudes in descending order (larger mag = smaller value)

Also derive equality separately for LTE/GTE cases.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 09:08:08 +00:00
2351a2217b sema: fix zirAbs comptime_int folding and typed signed int folding
zirAbs now folds @abs for comptime_int operands: absolute value is
simply clearing the is_negative flag. This matches Sema.zig which
treats comptime_int like float/comptime_float (result_ty = operand_ty)
and calls maybeConstantUnaryMath(Value.abs).

Also fold @abs for comptime-known typed signed integers: since the
result type is already unsigned, we just intern the magnitude (lo/hi)
with the unsigned result type and is_negative=false.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 09:06:32 +00:00
b4da5d7bd5 sema: fix zirBoolBr comptime fold, zirTypeofBuiltin want_safety
zirBoolBr: after analyzing the RHS body, if the result is
comptime-known and equals the short-circuit value (true for or,
false for and), fold the whole expression to the comptime result.
This matches Sema.zig lines 18167-18173.

zirTypeofBuiltin: set want_safety=false on the typeof block, matching
Sema.zig line 17941 which explicitly disables safety in typeof blocks.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 09:02:47 +00:00
7f478b70ea sema: fix sign-magnitude arithmetic for comptime integers
Several comptime folding paths in sema.c ignored the is_negative flag
of sign-magnitude InternPool integers:

- internComptimeInt: add `neg` parameter (was hardcoded false).
- analyzeArithmetic: implement sign-aware add/sub/mul via addSignedMag128
  helper. add(a,b) handles mixed signs by subtracting smaller magnitude;
  sub(a,b) = add(a,-b); mul result_neg = lhs_neg XOR rhs_neg.
- zirDiv: pass correct sign to result (lhs_neg != rhs_neg).
- zirShl/zirShr: preserve lhs sign through comptime shift.
- zirMinMax: use isComptimeIntWide (128-bit) instead of isComptimeInt
  (64-bit) and implement full 128-bit signed comparison.
- semaTypeOf: add DIV_FLOOR, DIV_EXACT, DIV_FLOAT_OPTIMIZED, MOD, REM
  to the bin_op type-from-lhs group.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:58:42 +00:00
039a00606b sema: fix 128-bit byteswap logic and cppcheck false condition
Simplify the 128-bit case in zirByteSwap comptime folding:
- r_lo byte b ← val_hi byte (7-b)
- r_hi byte b ← val_lo byte (7-b)
Previous code had a dead `src < 8` check (always false).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:13:31 +00:00
326d51e30e sema: fix semaCoerce comptime_float → integer coercion
Add the float-to-integer coercion path: convert the float value to an
integer (truncating toward zero) and intern it with the target type.
Previously, comptime_float coercion to integer types was silently
ignored, returning the original float ref unchanged.

Also restructure the comptime_float case to explicitly separate
float→float from float→int paths.

Matches src/Sema.zig coerce: getCoerced(val, dst_ty) for float→int.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:08:28 +00:00
8538d0b27b sema: add comptime integer division folding to zirDiv
For comptime-known integer operands (64-bit case), compute the quotient
at comptime instead of emitting AIR. Matches src/Sema.zig zirDiv: arith.div
for comptime-known values.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:07:35 +00:00
d0e90b94e9 sema: fix zirBitCount comptime folding to use 128-bit wide values
Replace 64-bit isComptimeInt with 128-bit isComptimeIntWide for CLZ,
CTZ, and POPCOUNT comptime evaluation. Correctly handles integer types
wider than 64 bits (e.g. u128, i128).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:07:02 +00:00
2d62c61b70 sema: add comptime float folding to zirNegate
For comptime-known float operands, compute -val at comptime instead of
emitting AIR_INST_NEG. Matches src/Sema.zig zirNegate: arith.negateFloat
for comptime values, preserving negative zero semantics.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:06:09 +00:00
427b428db8 sema: add comptime folding to zirAbs for float operands
For comptime-known float operands, compute abs(val) at comptime
instead of emitting AIR. Matches src/Sema.zig zirAbs: maybeConstantUnaryMath
with Value.abs. Also extends to comptime_float type.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:05:34 +00:00
1ccc0e54d9 sema: add comptime folding to zirByteSwap
For comptime-known integer operands with bit-aligned widths, compute
the byte-swapped value at comptime rather than emitting AIR.
Matches src/Sema.zig zirByteSwap: arith.byteSwap() comptime path.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:05:02 +00:00
1a1a4d3d25 sema: fix zirNegateWrap float zero creation
For float operands, create IP_KEY_FLOAT(0.0) instead of IP_KEY_INT(0).
The previous code created an int zero with a float type, which is an
invalid IP entry. Matches src/Sema.zig zirNegateWrap: pt.intValue()
returns the appropriate zero for the scalar type.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:04:22 +00:00
15f5284082 sema: fix zirBitwise to coerce before comptime folding
Match upstream Sema.zig zirBitwise structure: resolve peer types and
coerce operands FIRST, then attempt comptime folding on the coerced
values. This ensures typed IP entries (e.g. u16(3)) are created as
side effects of coercion, matching Zig's IP entry sequence.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 08:03:52 +00:00
51cbaabe22 sema: port zirLoop from upstream Sema.zig
Implement runtime while/for loop handling:
- Reserve block_inst (outer) + loop_inst (inner) in advance
- Analyze loop body in loop_block
- If body ends noreturn: copy instructions to child_block (no repeat)
- Otherwise: add repeat instruction, set up loop_inst body in air_extra
- Resolve outer block via label merges (handles break-from-loop)

Matches src/Sema.zig zirLoop decomposition.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:45:22 +00:00
39b2e51a28 sema: fix resolveFuncRetType for single-instruction type refs
Use resolveZirTypeRef instead of returning void for instruction refs
in the single-instruction return type body case. This handles ptr_type,
int_type, array_type, etc. Matches upstream's resolveType call in zirFunc.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:39:33 +00:00
0028645557 sema: add shl_exact and shr_exact dispatch + fix shl comptime folding
- Dispatch ZIR_INST_SHL_EXACT → zirShl(..., AIR_INST_SHL_EXACT)
- Dispatch ZIR_INST_SHR_EXACT → zirShl(..., AIR_INST_SHR_EXACT)
- Fix comptime path in zirShl: shl_exact is a left-shift, not right-shift
- Add AIR_INST_SHL_EXACT/SHR_EXACT to semaTypeOf (bin_op.lhs type)

Matches src/Sema.zig: .shl_exact/.shr_exact both dispatched via zirShl.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:38:06 +00:00
83fc754af7 sema: fix cppcheck unreadVariable in zirCmpEq
The coerce calls create IP side effects; comparison uses captured
lhs_lo/rhs_lo values. Use (void)semaCoerce() to make intent explicit.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:32:49 +00:00
564c858bd4 sema: add AIR_INST_NEG/NEG_OPTIMIZED to semaTypeOf
These ty_op instructions were missing from the semaTypeOf dispatch,
needed for the float negation path added in zirNegate.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:29:08 +00:00
910c746ee2 sema: fix zirAbs result type for integer operands
- Unsigned int: @abs is identity, return operand directly
- Signed int: result type is the unsigned equivalent (toUnsigned)
- Float/comptime: unchanged (result_ty = operand_ty)

Matches src/Sema.zig zirAbs behavior.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:28:42 +00:00
d728da32f4 sema: add comptime folding to zirBoolNot
Fold bool_true → bool_false and bool_false → bool_true at comptime,
matching src/Sema.zig zirBoolNot behavior.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:27:28 +00:00
a86f23824a sema: rename semaResolvePeerTypes → resolvePeerTypes
Aligns with upstream src/Sema.zig naming. Pure rename, no behavioral change.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:27:04 +00:00
3a2913ce08 sema: split zirTyOpCast into zirIntCast + zirTruncate
Add zirIntCast() and zirTruncate() as named entry points matching
src/Sema.zig's decomposition. Rename shared implementation to
analyzeTyOpCast(). Update dispatch and call sites.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:26:38 +00:00
3991c4bf41 sema: extract analyzeArithmetic; split zirCmp/zirCmpEq
- Add analyzeArithmetic() worker matching upstream decomposition
- zirArithmetic() becomes a thin wrapper (extract operands + delegate)
- zirNegate/zirNegateWrap call analyzeArithmetic() directly
- zirNegate gains float branch (emit AIR_INST_NEG for float operands)
- Add zirCmp() for ordered comparisons (lt/lte/gt/gte)
- Add zirCmpEq() for equality comparisons (eq/neq)
- Update dispatch table to call zirCmp/zirCmpEq instead of zirArithmetic

Matches src/Sema.zig function decomposition: zirArithmetic → analyzeArithmetic,
zirCmp, zirCmpEq as separate entry points.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:25:36 +00:00
b90553615a sema: extract analyzeBitNot from zirBitNot
Matches upstream Sema.zig which has zirBitNot → analyzeBitNot
two-function decomposition. Pure extraction, no behavioral change.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-07 07:22:00 +00:00
5d6f9537f0 README: document exceptions 2026-03-07 09:11:48 +02:00
e1ec6d2ccf sema: fix skip_dedup_end and cc_start timing, clear 15 CC builtins (num_passing=100)
- Extend skip_dedup_end to full preamble items_len (not just
  preamble_memoized_end) so CC sub-type entries created by
  ensureCcMemoizedStateC are in the skip range
- Set preamble_cc_start AFTER CC union creation so main analysis
  creates fresh CC union via skip_dedup
- Clear all 15 CC-phase builtins (not just 5) for main shard re-resolution
- Reset cc_memoized_resolved so ensureCcMemoizedStateC re-runs in main

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 01:18:33 +00:00
364bdf2c5e sema: port arithmetic coercion, type dedup, CC memoized state, ptr_nav deferral (num_passing=100)
- Port Sema.zig analyzeArithmetic coercion: coerce both operands to
  result_ty when result is not comptime_int, creating typed intermediate
  IP entries that match the Zig compiler's output.
- Fix zirTypeofLog2IntType and zirShl to use ipIntern (dedup) instead
  of ipForceIntern, matching Zig's pt.intType which deduplicates via
  the global pool.
- Add cc_memoized_resolved / ensureCcMemoizedStateC for the CC phase of
  builtin resolution (builtins 0-14), analogous to PerThread's CC stage.
- Add preamble_skip_ptr_nav flag to defer AS/CC ptr_nav creation to
  main analysis, matching Zig's sharded IP where preamble and main
  shards use different nav IDs.
- Extend ct_struct_vals.fields from 4 to 8 entries and store const char*
  name instead of string_bytes index, enabling zirFieldValComptime to
  access TypeInfo fields by name.
- Advance num_passing from 87 to 100.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 18:16:22 +00:00
d29f7da7ab sema: fix duplicate func_type/func_decl and deferred body analysis (num_passing=87)
Two fixes for test 86 (inline_fn_with_plus_eq_call_inside_two_conditionals):

1. Skip duplicate func_type/func_decl in zirFunc when ensureNavValUpToDate
   has already resolved the nav. Previously, ensureNavValUpToDate created
   entries with ipForceIntern (no hash table) and zirFunc re-created them
   with ipIntern (can't find existing), causing duplicates.

2. Defer non-generic body analysis from semaAnalyzeCall to match Zig's
   ensureFuncBodyAnalysisQueued ordering. Callee body analysis is queued
   and processed after the current function body completes, ensuring IP
   entry ordering matches the Zig compiler's work queue semantics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 09:30:19 +00:00
0e9bc3bf9b zig0_airgen_options: restrict what can be configured
1. `dev == .bootstrap` does not include wasm backend, no use.
2. different optimize modes _of the compiler_ (_not_ target) _should_
   not emit a different AIR. Thus if we want to `zig build test-zig0
   -Doptimize=ReleaseFast`, we most often mean to compile the test
   executable under this mode, but not `air_gen`, which will only emit
   the AIR for comparison.
2026-03-03 09:04:18 +00:00
4da900cbb8 stage0: fix enum_literal to store string index, not djb2 hash
zirEnumLiteral was storing simpleStringHash(name) — a djb2 hash — as the
enum_literal IP key field. Upstream Zig stores a NullTerminatedString index
(getOrPutString). All three read sites treat the field as a string table
index and dereference it into ip->string_bytes, so the hash value caused
silent out-of-bounds reads whenever enum_literal coercion, callconv, or
signedness parsing were exercised.

Replace simpleStringHash with ipGetOrPutString, matching upstream exactly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 08:43:16 +00:00
be50c806b8 rm unusedFunction check 2026-03-03 10:42:29 +02:00
5634dd5cae sema: deduplicate func_instance entries for repeated generic calls
Use ipIntern (not ipForceIntern) for func_instance so that multiple
calls to the same generic function with the same comptime args share
one IP entry. Fixes the two-generic-calls test case where Zig produces
one func_instance but C was producing two.

Bumps num_passing from 85 to 86.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 08:41:35 +00:00
a35da223fb sema: add func_instance support for generic function monomorphization
Port IP_KEY_FUNC_INSTANCE from upstream InternPool.getFuncInstance.
When a generic non-inline function is called, create a monomorphized
func_type (runtime params only) and a func_instance entry referencing
the generic owner's func_decl. This matches the Zig compiler's IP
entry sequence for generic instantiations.

Bumps num_passing from 84 to 85.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 08:30:41 +00:00
c69e558131 sema: extract semaAnalyzeCall from zirCall
Refactor to match upstream Sema.zig structure where zirCall handles
callee resolution and analyzeCall handles the actual call analysis.
The new semaAnalyzeCall function takes a CalleeResolution struct that
bundles cross-module state. No functional changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 08:04:04 +00:00
8b4d45bf30 sema: skip generic functions in Pass 2a
Generic functions (with comptime, anytype, or anytype_comptime params)
should not be compiled as standalone function bodies — they're resolved
via monomorphization when called with concrete types. Ported from
upstream: generic functions are excluded from analysis roots.

Detect comptime params by scanning the param body in the ZIR for
ZIR_INST_PARAM_COMPTIME, ZIR_INST_PARAM_ANYTYPE_COMPTIME, or
ZIR_INST_PARAM_ANYTYPE instruction tags.

Next blocker: test 84 (inline_fn_with_generic_call_inside_conditional)
has a monomorphization naming mismatch: C generates normalize__anon_503
while Zig generates normalize__anon_507. The IP index gap of 4 needs
investigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-03 07:47:33 +00:00
2cfd4ac668 sema: reuse callee func_decl for non-inline calls, bump 80→84
Fix non-inline function call to reuse the callee's existing func_decl
IP entry instead of creating a new one with func_inst as owner_nav.
Ported from upstream Sema.zig analyzeCall: func_val references the
resolved callee function, not a newly-created entry.

The callee is looked up by name in the file namespace. If the nav's
resolved_type already points to a func_decl (IP_KEY_FUNC), it's used
directly. Otherwise, the func_type from resolved_type is used to
construct and deduplicate the func_decl key.

Also fixes the coercion dedup fix from the previous commit: switched
semaCoerceIntRef from ipForceIntern to ipIntern now that skip_dedup
handles cross-shard separation.

Tests 80-83 now pass (call_inside_runtime_conditional, multi_func_call,
runtime_conditional_with_early_return, field_access_chain).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-03 07:41:10 +00:00
e6cda567d0 sema: port compareIntsOnlyPossibleResult, fix int coercion dedup, bump 75→80
Port compareIntsOnlyPossibleResult from upstream Sema.zig (line 32511):
when a comparison has one comptime operand, intern the other type's
min/max bounds as side effects. This matches the Zig compiler's
IP entry sequence for comparison operations.

Fix semaCoerceIntRef: switch from ipForceIntern to ipIntern for
integer type coercion. The cross-shard dedup issue is now handled
by the skip_dedup mechanism, so ipForceIntern is no longer needed.
Using ipIntern allows proper deduplication of identical coerced
values (e.g., two comparisons with `> 0` share the same int_u32(0)).

Tests 75-79 now pass (var_bitcast_and_if, shr_exact, nested_if,
conditional_bitwise_and, conditional_sub).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-03 07:33:39 +00:00
072929759e stage0: move PerThread functions from sema.c to zcu_per_thread.c
Completes the file layout refactoring to match Zig's src/ structure.
Functions from src/Zcu/PerThread.zig no longer live in sema.c.

Moved to zcu_per_thread.c (~1100 lines):
- Group A (PerThread.zig orchestration): ensureFileAnalyzedC,
  createFileRootStructC, scanNamespaceC, analyzeNavValC,
  analyzeMemoizedStateC, ensureFullMemoizedStateC, ensureNavValUpToDate,
  analyzeComptimeUnit, doImport, getBuiltinTypeC
- Group C (namespace/module helpers): createNamespace, findNavInNamespace,
  findNamespaceForType, findNavForIPIndex, findFileByPathSuffix
- Group D (PerThread type/value constructors): internPtrConst, internNavPtr,
  internPtrMutable, internUndef, internPtrComptimeAlloc, internPtrUav,
  internPtrField, internTypedInt, internEnumTag, internFuncType,
  internFuncDecl, internStrLit, coerceIntToTagType
- Also moved: BuiltinDeclEntry lookup table

sema.c now contains only src/Sema.zig functions (~11700 lines).

Supporting changes:
- sema.h: add DeclFlagsId enum, FuncZirInfo struct, CC_TAG_* defines,
  and declarations for Sema functions called by PerThread
- zcu_per_thread.h: updated with all public PerThread function declarations
- build.zig: add zcu_per_thread.c to source list

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 19:24:27 +00:00
2ed13b7b9d sema: add param types to func_type dedup, bump num_passing 73→75
Include parameter types in the func_type key for correct dedup. The
upstream Zig IP includes param types when interning function types;
C's simplified key previously used only (ret, param_count, cc) which
caused ipForceIntern to be needed (preventing dedup of identical
function signatures like fn(u32) u32 appearing in multiple exports).

Changes:
- Add param_types[8] inline array to FuncType struct
- Update ipHashKey and ipKeysEqual to include param types
- Update internFuncType to accept optional param_types array:
  when provided → ipIntern (correct dedup); when NULL → ipForceIntern
- Collect param types during export function resolution and pass to
  internFuncType for proper dedup

Tests 73-74 now pass (multiple_return_paths, nested_if_else_chain).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 18:24:02 +00:00
412316e708 sema: route shl_sat through zirShl, revert func_type dedup attempt
Route ZIR_INST_SHL_SAT through zirShl (not zirArithmetic) and add
comptime RHS coercion for shl_sat: shift amount is coerced to
smallestUnsignedInt(lhs_bits) matching upstream Sema.zig line 13996.
For u32 shifts, this creates u6(1) instead of u32(1).

Attempted to switch func_type from ipForceIntern to ipIntern for
dedup of identical function signatures (test 73: multiple_return_paths).
Reverted because C's func_type key doesn't include param types, causing
false dedup for functions with same (ret, count, cc) but different
param types (regression in test 30: store_to_pointer).

Next blocker: test 73 (multiple_return_paths.zig) — needs func_type
param types in hash/equality for correct dedup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 18:14:50 +00:00
f3ce1883d0 sema: fix shl_sat shift type coercion, bump num_passing 67→73
Port shl_sat shift amount coercion from upstream Sema.zig zirShl
(line 13996). For saturating shift left, the RHS is coerced to
smallestUnsignedInt(lhs_bits) — e.g. u6 for u32 operands (needs to
represent 0-32, not just 0-31).

Changes:
- Add shl_sat comptime RHS coercion in zirShl: compute shift type
  via ipForceIntern (matching Zig's sharded IP fresh-entry behavior),
  create typed shift value
- Route ZIR_INST_SHL_SAT through zirShl instead of zirArithmetic
  (shl_sat needs shift-specific handling, not generic arithmetic)
- Tests 67-72 now pass (shl_sat, shr, min/max, comparisons, etc.)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 18:04:35 +00:00
69a0486232 sema: fix shard simulation, bump num_passing 61→67
Fix the IP shard simulation to work for all main analysis, not just
during ensureFullMemoizedStateC. This fixes tests 61-66 (inline fn
tests and non-inline tests that reference types from preamble builtins).

Key changes:
- Move skip_dedup activation to the end of the preamble (after
  analyzeMemoizedStateC + start.zig comptime). Previously it was only
  set during ensureFullMemoizedStateC, missing tests that don't
  trigger full builtin resolution.
- Expand cc_keep range by 1 entry to include the CC ptr_nav that
  AddressSpace resolution creates as a side effect (fixing the
  1-entry excess for inline function tests).
- Remove skip_dedup clearing from ensureFullMemoizedStateC (it stays
  active for the entire main analysis).

Next blocker: test 67 (shl_sat.zig) — the shift amount type (u6 for
u32 operand) is not created. C stores the shift amount as u32(1)
instead of u6(1). Need to port shift amount type coercion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 17:54:04 +00:00
6390ee4b8a sema: narrow inline fn IP gap from 46 to 1 entry
Refine the IP shard simulation for test 61 (inline_call_with_xor):

- Add comptime_int exception to skip_dedup: comptime_int entries are
  shared across Zig's IP shards and should always dedup. Prevents 11
  extra entries from AddressSpace values 2-12 re-creation.

- Fix dbg_inline_block func entry: reuse the callee's existing
  func_decl IP index (found via nav zir_index match) instead of
  creating a new func entry. Ported from upstream Sema.zig line 7788:
  .func = func_val.?.toIntern().

- Fix cppcheck: const-qualify Nav pointer variables.

Gap reduced: 46 → 12 → 1 entry. The remaining 1-entry excess needs
investigation (likely a union_value or CC sub-entry mismatch).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 17:37:01 +00:00
5412f80b3e stage0: rename zcuAlloc→zcuInit, zcuDeinit frees struct, clean comments
- zcuAlloc → zcuInit (Init/Deinit pair convention)
- zcuDeinit now frees the struct itself (no separate free() needed)
- Remove zcuFree (redundant after zcuDeinit change)
- Clean zcu.h comments: remove "was:" references, keep Zig origin refs

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 16:51:15 +00:00
9cd2e0ff77 stage0: refactor globals into structs matching Zig architecture
Eliminates all 39 mutable static globals across sema.c (37) and
intern_pool.c (2). State is now held in properly-typed structs passed
as parameters, mirroring the Zig reference implementation layout.

New files matching Zig src/ layout:
- compilation.h: CompilationConfig + Compilation (matches Compilation.zig)
- zcu.h/zcu.c: ZcuFile, ZcuNamespace, Zcu, zcuInit/zcuDeinit (matches Zcu.zig)
- zcu_per_thread.h: forward declarations for PerThread-style functions

Key changes:
- InternPool gains navs[] (dynamically allocated) + nav_count/nav_cap;
  Nav functions now take InternPool* (was implicit via globals)
- Sema gains Zcu* zcu; semaInit now takes Zcu* instead of InternPool*
- All module-level state (files, namespaces, memoized state, config)
  moved from static globals into Zcu struct
- zig0.c creates Compilation + Zcu before semaInit
- Test files updated to use zcuInit/zcuDeinit API

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 16:44:27 +00:00