Repository navigation
Conversation
…d behaviour gen-c wrote the bare C operators for + - * / % << >>. Signed overflow, an out-of-range shift amount, a zero divisor and MIN / -1 are undefined in C, so the t27b differential test saw inc(INT_MAX) pass at -O0 and trap at -O2, and shr(1024, 40) do the opposite. Inside fn/test/bench/invariant bodies every arithmetic operator now lowers to a t27_* helper from one guarded prelude (C_ARITH_PRELUDE): + - * via __builtin_*_overflow, shifts check the amount, / % check the zero divisor and MIN / -1, the wrapping operators compute unsigned. Failure is __builtin_trap(). Module-scope initializers, literal-only arithmetic and array/string concatenation keep the infix spelling. ternary_mac accumulates with +% (the verifier models a wrapping i32); verify_igla_race and check_duplicate_agreement carry the prelude. Seals whose gen_hash_c changed are resealed. Closes #5974. Part of #5905. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d-arith # Conflicts: # .trinity/seals/Backend.json # .trinity/seals/BaseOps.json # .trinity/seals/BaseTypes.json # .trinity/seals/Fifo.json # .trinity/seals/FormulaDiscovery.json # .trinity/seals/FormulaEmbed.json # .trinity/seals/GF16.json # .trinity/seals/KnowledgeGraph.json # .trinity/seals/LrScheduler.json # .trinity/seals/Optimization.json # .trinity/seals/PackedVsa.json # .trinity/seals/PinsParser.json # .trinity/seals/SU2ChernSimons.json # .trinity/seals/SgdMomentum.json # .trinity/seals/TF3.json # .trinity/seals/TernaryHashTable.json # .trinity/seals/TernaryPatternMatching.json # .trinity/seals/TernarySearch.json # .trinity/seals/TestRunner.json # .trinity/seals/TriGraphBfs.json # .trinity/seals/TriHex.json # .trinity/seals/TriIo.json # .trinity/seals/TriReedSolomon.json # .trinity/seals/TriSha256.json # .trinity/seals/base_tritype-base.json # .trinity/seals/base_tritype-ops.json # .trinity/seals/bigint.json # .trinity/seals/chimera.json # .trinity/seals/compiler_Optimization.json # .trinity/seals/config-paths.json # .trinity/seals/config_config-paths.json # .trinity/seals/crypto_TriHex.json # .trinity/seals/crypto_TriReedSolomon.json # .trinity/seals/crypto_TriSha256.json # .trinity/seals/depin_depin.prove.json # .trinity/seals/forward_pass.json # .trinity/seals/fpga_Fifo.json # .trinity/seals/graph_KnowledgeGraph.json # .trinity/seals/graph_TriGraphBfs.json # .trinity/seals/hybrid_bigint.json # .trinity/seals/io_TriIo.json # .trinity/seals/isa_TernaryHashTable.json # .trinity/seals/isa_TernaryPatternMatching.json # .trinity/seals/isa_TernarySearch.json # .trinity/seals/isa_Tri27Machine.json # .trinity/seals/legacy_main_zig_handwritten.json # .trinity/seals/memory_FormulaEmbed.json # .trinity/seals/neural_forward_pass.json # .trinity/seals/nn_GatedLinearAttention.json # .trinity/seals/numeric_BigInt.json # .trinity/seals/numeric_triformat-gaternary.json # .trinity/seals/numeric_triformat-gf16.json # .trinity/seals/numeric_triformat-gfternary.json # .trinity/seals/numeric_triformat-tf3.json # .trinity/seals/optimizer_LrScheduler.json # .trinity/seals/optimizer_SgdMomentum.json # .trinity/seals/parser.json # .trinity/seals/parser_parser.json # .trinity/seals/physics_FormulaDiscovery.json # .trinity/seals/physics_SU2ChernSimons.json # .trinity/seals/physics_chimera.json # .trinity/seals/pins_PinsParser.json # .trinity/seals/prove.json # .trinity/seals/race_igla-race-backend.json # .trinity/seals/runner.json # .trinity/seals/runtime-execute.json # .trinity/seals/runtime-instance.json # .trinity/seals/runtime-process.json # .trinity/seals/runtime_runtime-execute.json # .trinity/seals/runtime_runtime-instance.json # .trinity/seals/runtime_runtime-process.json # .trinity/seals/server-mdns.json # .trinity/seals/server_server-mdns.json # .trinity/seals/skill_registry.json # .trinity/seals/skill_skill_registry.json # .trinity/seals/sync-schema.json # .trinity/seals/sync_sync-schema.json # .trinity/seals/ternary_hybrid_bigint.json # .trinity/seals/test_framework_runner.json # .trinity/seals/tools_Wp18GateSelfConsistentSelfTest.json # .trinity/seals/training_IGLALowBitTernary.json # .trinity/seals/triformat-gf16.json # .trinity/seals/triformat-tf3.json # .trinity/seals/tritype-base.json # .trinity/seals/tritype-ops.json # .trinity/seals/vsa_PackedVsa.json # .trinity/seals/vsa_core.json # .trinity/seals/vsa_simple_port-trin-vsa-simple.json # .trinity/seals/vsa_vsa_core.json # .trinity/seals/vsa_vsa_trinity_compat.json # .trinity/seals/zig_codegen.json # .trinity/seals/zig_zig_codegen.json # bootstrap/stage0/FROZEN_HASH
…st failures Specs whose seals master rewrote while this branch was open get the new gen_hash_c. ternary_shift and gft_generalize_demo are sealed with --force and ledgered as tests-fail: their Zig tests fail with the Zig output master already seals. clock_domain_tb and gf16_accel_tb get gen_hash_c only, because their own Zig test never terminates. Closes #5974. Part of #5905. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 4, 2026
Merged
Open
9 tasks
This was referenced Oct 4, 2026
This was referenced Oct 6, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
t27c gen-cemitted the bare C operators for+ - * / % << >>. C leaves signed overflow, a shift amount outside[0, width), a zero divisor andMIN / -1undefined, so the generated C gave different answers at different optimisation levels. The t27b differential test (#5905) found two cases:inc(INT_MAX)passed at -O0 and trapped at -O2, andshr(1024, 40)did the reverse. The language rule is #1659: plain+ - *trap on overflow and+% -% *%wrap. Zig and t27b trap mode already follow it.Inside fn, test, bench and invariant bodies, each arithmetic operator now becomes a call to a
t27_*helper. The helpers live in one guarded block,C_ARITH_PRELUDE, which is emitted only when a module uses one:+ - *use__builtin_*_overflow./and%check for a zero divisor and forMIN / -1.Every failure calls
__builtin_trap()._Genericpicks the width, and a GNU statement expression makes sure each operand is evaluated once.Three cases keep the infix form on purpose:
+with an array or string operand, which is concatenation.A bare literal shifted by a runtime amount (
(1 << n) - 1) takes the same width the Zig backend gives it: the declared type of the local it initializes, otherwise its suffix, otherwise u32 or u64 by magnitude.Functions changed in
bootstrap/src/compiler.rs:C_ARITH_PRELUDE,c_arith_helperCCodegen::{c_is_literal_arith, c_is_pure_lvalue, gen_c_macro_arg, c_scalar_int_type, c_shift_literal_base_type}gen_c_expr(ExprBinary),gen_c_stmt(StmtAssign compound and StmtLocal)gen_c_fn,gen_c_test,gen_c_bench,gen_c_invariant,gen_cBefore / after (t27b README reproducer)
inc_max(inc(2147483647))shr_big(shr(1024, 40))rem_neg(rem(-7, 2) == -1)After the change,
-fsanitize=undefinedreports nothing at -O0 or at -O2.Corpus effect
Measured against the master this branch started from:
gen-coutput.+that_Genericnow refuses.gf_decode_param_fp64test_decode_neg_infnow passes. Before, a 32-bit1 << 52was UB and made it fail.ternary_memorytest_ternary_word_write_read_tritnow traps. Zig traps here too, on an@intCastof -1 to u32.gf16_dot4test_intermediate_structurenow traps. Zig traps here too, on a u16 multiply overflow.specs/igla/race/ternary_mac.t27now accumulates withacc +% prod. This is a judgement call:tools/verify_igla_race.pymodels the accumulator as a wrapping i32 and drives it across the INT32 edges, so checked+trapped there, as the Zig output already did.verify_igla_race.pyandcheck_duplicate_agreement.pynow copy the prelude into the functions they extract.Verifiers that pass:
verify_igla_race,check_duplicate_agreement,verify_multitarget,verify_trainer_c.verify_exhaustiveonmaj3 tmul negate xor2 sign0 pack2: model == C == Rust on every input.Seals
899 seal files (536 specs) carry the new
gen_hash_c.check_seal_coverage.pyandcheck_seal_currency.pyboth pass.t27c seal --save.ternary_shift(2 seal files) andgft_generalize_demo(1) were sealed with--force. Their Zig tests already fail with exactly the Zig output master seals (gen_hash_zigis unchanged). They are ledgered astests-failintools/seal_baseline.txt.clock_domain_tbandgf16_accel_tb(4 seal files) had onlygen_hash_crewritten. Their own Zig test spins forever inwhile !sync_ready { tick_fast(); }, soseal --savenever returns. The other four hashes were checked equal before the rewrite.Tests
bootstrap/tests/c_checked_arith.rshas 5 tests:test_tuple_literal_and_destructuring_c, andtest_wrapping_ops_all_backends_1659, which now asserts thet27_w*lowering.cargo test --release -p t27c: every test binary passes exceptcore_selfhost. See below.Blocked:
core_selfhostfixpoint (#6041)#6041 landed on master while this PR was open. Its fixpoint requires
specs/compiler/core/t27core.t27, the self-hosted core, to write exactly the bytesgen-cwrites. With this change,gen-c(t27core.t27)lowers its 123 body operators tot27_*calls and emits the prelude. The core still writes infix C, socore(t27core.t27) != gen-c(t27core.t27). The core's own test blocks still pass when built from the new C. To make the fixpoint hold again, the core has to learn the same lowering:This PR does not edit the core. That work is a separate change to epic #5980. The PR is opened as a draft for that reason.
Not established
int(i8, u8, i16, u16) are promoted by C, so they are checked atintwidth and truncated on store. That is defined behaviour, but a u16 overflow that Zig traps only traps in C if it also overflowsint.+is not supported. With a pointer operand it is now a compile error, where before it was a pointer offset.verify_exhaustivewas run on the subset above, not on the full target list, which did not finish under machine load.ec1d9a61c. Master has moved since, and a final merge and reseal is needed before landing.Closes #5974. Part of #5905.
🤖 Generated with Claude Code