The zig test step previously compiled Zig code and linked C objects in
a single invocation. Since the Zig compiler hashes all link inputs
(including .o file content) into one cache key, changing -Dzig0-cc or
editing any C file invalidated the 6-minute Zig compilation cache.
Split into two steps: emit the Zig test code as an object (cached
independently of C objects), then link it with the C objects in a
separate executable step. Manually set up the test runner IPC protocol
via enableTestRunnerMode() to preserve build summary integration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a verbose_air_output field to Compilation that redirects verbose Air
dumps to a caller-provided writer instead of stderr. When set, liveness
is omitted from the output to support textual comparison in stage0 tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use Directories.init() to resolve ~/.cache/zig (global) and
.zig-cache (local) instead of a temp dir, re-using the same
resolution logic as src/main.zig (introspect module).
- Point zig_lib at zig-out/lib/zig/ (installed copy) instead of lib/
(source tree) to avoid "file exists in modules 'root' and 'std'"
when compiling files that live under lib/.
- Heap-allocate the thread pool to keep its address stable. Worker
threads reference the Pool's condvar/mutex; a by-value copy into
ZigSemaResult left them waiting on the original stack address while
deinit broadcast on the copy, causing a deadlock.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add zigSema helper (stage0/sema.zig) that creates a Compilation,
points it at a source file, and runs the full Zig sema pipeline.
Export Compilation and Package from test_exports.zig. Wire up in
stagesCheck to run Zig sema alongside C sema.
Not yet working: files under lib/ conflict with the auto-created
std module ("file exists in modules 'root' and 'std'"). The fix
(using .root = .none with absolute path) needs testing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add expectEqualAir() that validates the converted Zig Air matches
the original C Air (instruction count, tags, and extra data). Use it
in stagesCheck to verify the conversion is faithful for all corpus
files processed through the sema stage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract cSema(gpa, c_zir) as a reusable function that runs the full
C sema pipeline (init IP → init sema → analyze → convert to Zig Air)
and returns a SemaResult owning all resources. Update all sema tests
in sema_test.zig and stages_test.zig to use it, removing duplicated
pipeline setup code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add stage0/sema_c.zig that converts C Sema output (Air struct) to Zig's
Air type via MultiArrayList, with per-tag data dispatch. Update
stagesCheck to use the conversion, and extend the const x = 42 test to
verify both Air structure and InternPool contents.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add enough C sema handling so that `const x = 42;` interns the integer
value 42 in the InternPool, matching the Zig reference implementation.
- Add Declaration.Flags.Id helper functions (hasName, hasLibName,
hasTypeBody, hasValueBody, hasSpecialBodies) ported from Zir.zig
- Add zirInt handler to intern comptime integer values
- Add zirStructDecl handler to parse struct_decl extra payload,
iterate declarations, and analyze their value bodies
- Add cross-check test comparing C and Zig InternPool entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire src/test_exports.zig through build.zig so zig0 tests can import
the real Zig InternPool. Add a test that initializes both the C and Zig
InternPools and compares all 124 pre-interned entries index by index.
Also add rule to skill file: never run `zig build test` or bare
`zig build` (they test upstream Zig and take ages).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Combine two specialized skills (port-astgen for astgen_test.zig,
fix-stages for stages_test.zig) into a single parameterized skill
that takes any test file as input. Improvements over the originals:
- Config table maps test files to modifiable/reference files
- Flush accumulated passing tests before dispatching worker
- Fast test-zig0 for per-iteration verification, valgrind only in final check
- Worker budget (~15 cycles) to avoid context exhaustion
- Guard rail: skip test after 2 consecutive no-progress
- Worker truncates output (tail -50) and never reads whole reference files
- Handles all failure types: parser, AstGen, and sema
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add core Sema analysis infrastructure:
- InstMap operations: ensureSpaceForBody, get, put
- resolveInst: maps ZIR refs to AIR refs (pre-interned + inst_map)
- addAirInst: appends AIR instructions with auto-growth
- SemaBlock helpers: init, deinit, blockAddInst
- zirDbgStmt handler with comptime elision and coalescing
Implement analyzeBodyInner dispatch loop handling:
- dbg_stmt, break_inline, ret_implicit, extended (stub),
block_inline (recursive body analysis), declaration (skip)
- Default case maps unhandled instructions to void_type
Update semaAnalyze to set up root block, verify ZIR instruction 0
is struct_decl, exercise dispatch infrastructure, and transfer AIR
array ownership to returned Air struct.
Add smoke test for "fn foo() void {}" declarations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create sema_test.zig with:
- InternPool unit tests: pre-interned types/values, ipTypeOf,
ipIntern deduplication, new key interning, vector/pointer types
- Sema smoke tests: empty source and "const x = 0;" through
full C pipeline (parse → astgen → sema) without crashing
Wire sema_test.zig into test_all.zig.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split cppcheck into per-file checks (warning,style,performance,portability)
and a combined unusedFunction check across all C files. Remove dead code
(addExtraU32, rvalueDiscard, wipMembersNextDecl, wipMembersBodiesAppend,
findNextContainerMember, NodeContainerField). Wire up zig0Run to actually
call astParse/astGen and print stats, eliminating unusedFunction warnings
for the public API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace parser's fail() and astgen's flag-only SET_ERROR(ag) with a
single SET_ERROR(ctx, msg) macro in common.h that stores the error
message in ctx->err_buf and sets ctx->has_compile_errors. Both Parser
and AstGenCtx now carry the same err_buf[ERR_BUF_SIZE] field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add warn() for non-fatal parse errors (like Zig's Parse.warn)
- Implement finishAssignDestructureExpr for destructuring assignments
- Use parseBlockExpr instead of parseBlock in for/while statement bodies
- Use parseSingleAssignExpr in switch prongs
- Enable x86_64/CodeGen.zig corpus entry
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The @unionInit handler in builtinCallMultiArg was propagating the parent's
result info context (e.g. RI_CTX_RETURN) to the init value expression.
Upstream Zig creates a fresh ResultInfo with .ctx = .none. This caused
call flags mismatch (pop_error_return_trace) in return expressions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rlBuiltinCall was always returning false (not consuming result location).
The Zig reference marks @frameAddress as consuming the RL (workaround for
llvm/llvm-project#68409), which affects declaration codegen path (pointer
vs value based). Match the upstream behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The AST_NODE_CONTAINER_FIELD case in structDeclInner had an incorrect guard
`if (nd.rhs != 0)` before reading align/value from extra_data. Since rhs is
an extra_data index (not a node), 0 is a valid index. Removing the guard
fixes 3-5 missing instructions in files where the first extra_data entry
happens to be a container_field's align+value.
Also fix clang-format: addBuiltinValue arg wrapping, for-loop semicolons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Upgrade decimal_float_fits_f64() to use 128-bit integer arithmetic for the
algebraic round-trip test, handling mantissas up to ~38 significant digits.
This fixes float128-vs-float tag mismatches for values that fit in 128-bit
mantissa but overflow 64-bit.
Newly enabled: gpu, memmove, mulf3, udivmodei4, udivmod, scalar, ff,
p256_64, p256_scalar_64, p384_64, p384_scalar_64, secp256k1_64,
secp256k1_scalar_64, sha2, sha3, Decompress, testing, log10, log2, log,
rem_pio2f, rem_pio2_large, rem_pio2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
decimal_float_fits_f64() incorrectly returned true when a non-zero mantissa
(that had overflowed uint64_t) was converted to 0.0 by strtod. These values
do not fit in f64 and need f128 representation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix strtod underflow/overflow edge cases in decimal_float_fits_f64.
Enables 707 files across lib/std/, lib/compiler_rt/, src/, and more.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Define named constants for the three categories of optional sentinel
values, matching their Zig counterparts (?TokenIndex null,
?Node.Index null, Zir.Inst.OptionalIndex .none). This makes intent
explicit and prevents sentinel/zero confusion bugs like the one
fixed in 921a7021.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>