You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sadd disagrees in Zig: a shift by a negative count, and as u32 means two things #5506
tools/verify_multitarget.py compares smul and sadd across C, Rust, Zig and the Python GF-T model on 1744 seeded operand pairs. Its Zig branch (#4736) never ran: it asked for t27c gen- (no such subcommand), required a pub fn the generator never writes, and appended Zig that does not parse. With those fixed (#5505) and Zig 0.16.0, the comparison runs:
OK gft_smul.smul: C == Python model BIT-EXACT over 1744 operand pairs
OK gft_smul.smul: Rust == Python model BIT-EXACT over 1744 operand pairs
OK gft_smul.smul: Zig == Python model BIT-EXACT over 1744 operand pairs
OK gft_sadd.sadd: C == Python model BIT-EXACT over 1744 operand pairs
OK gft_sadd.sadd: Rust == Python model BIT-EXACT over 1744 operand pairs
Zig target run: exited -6 (signal 6)
thread panic: integer does not fit in destination type
m.zig:125:20 in magsub
FAIL gft_sadd.sadd: Zig backend failed to build/run
Two defects behind one panic
sadd calls magsub(ma, mb) before it knows the order (specs/ternary/gft_sadd.t27:65-66). When ma < mb the first call computes d = ho - lo_o < 0 and shifts by it (ls >> d, la << d), then its result is overwritten by magsub(mb, ma). In C a shift by a negative count is undefined behaviour; in Rust -O it is unchecked; both happen to discard the value. Zig in ReleaseSafe traps at @intCast(d). The same body is written 30 times across specs/ (duplicate ledger sadd 30).
as u32 from i32 means different things per backend. With the call order fixed locally, Zig traps one step later, at return @as(u32, @intCast((bsign << 16) | r));, first on the pair (256, 66047). The model returns -257 there (0xFFFFFEFF after masking): magsub produced a negative magnitude. C and Rust reproduce those bits because their as wraps; the Zig backend lowers as to @intCast, which refuses a negative value (bootstrap/src/compiler.rs, e.g. lines 8654 and 9868).
What is not decided here
Whether x as u32 is a wrapping reinterpretation (C/Rust) or a checked conversion (Zig) is a language decision; changing the Zig lowering moves gen_hash_zig for every spec that uses it.
Whether sadd(256, 66047) = 0xFFFFFEFF is a valid GF-T result or a model defect that C and Rust copy.
Until one of these lands, GF-T primitives agree across C + Rust + Zig + model fails for this reason, which is what it should say.
Activity
fix(ci): the Zig target of verify_multitarget runs (#5505)
fix(ci): ledger the fifteen ports that do not generate (#5550)
fix(gft): sadd orders before it subtracts, underflow is zero; seal cu…
Port gft_sadd_jtag.t27: the absorption boundary on silicon
Port fpga/verilog/gft_sadd_jtag.v (Verilog, 1 module) to specs/port/f…