Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions bootstrap/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16668,6 +16668,25 @@ impl VerilogCodegen {
// in $signed() (Verilog sign-extends it into the wider signed
// context) and the unsigned operand is zero-extended one bit,
// $signed({1'b0, x}), so it stays non-negative.
// W-27: a RIGHT SHIFT of a signed value needs `>>>`.
// Verilog's `>>` fills with zeros whatever the operand
// is declared, and the repair below fires only on
// ordered relations, so no shift was ever fixed up. On
// `specs/igla/race/cordic_fixed.t27:42`, `x - (y >> shift)`
// with x=100, y=-64, shift=2 simulates to -16268 where
// the spec, C and Zig all say 116: y = 16'hFFC0 = 65472,
// 65472 >> 2 = 16368, 100 - 16368 = -16268.
//
// This project's own hand-written golden CORDIC RTL
// writes `y0 >>> 1` for the identical rotation, so the
// right operator was known and the expression path
// emitted it zero times across 559 generated modules.
let shift_signed = node.extra_op == ">>"
&& matches!(
self.expr_width_signed(&node.children[0]),
Some((_, true))
);
let op = if shift_signed { ">>>" } else { op };
let ordered_rel = matches!(op, "<" | "<=" | ">" | ">=");
let rel_signed = ordered_rel
&& match (
Expand Down
2 changes: 1 addition & 1 deletion bootstrap/stage0/FROZEN_HASH
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d08617f241b7aebdbef21636a651180b9b303ea20c1077452be83165e3a5b736
b109d745f01460f08fb2f8547d27a816dfecaff6c3f917da90f2f465c3daa86d
12 changes: 12 additions & 0 deletions docs/now/2026-08-30-a-signed-right-shift-needs-three-angles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# NOW -- A signed right shift needs three angle brackets (2026-08-30)

## The Verilog backend filled with zeros where the spec said sign (Refs #2860)

- `>>` was mapped to Verilog's `>>` unconditionally; Verilog's `>>` is LOGICAL and fills with zeros however the operand is declared
- the signedness repair the backend already has fires only on ordered relations `< <= > >=`, so no shift was ever fixed up
- simulated on the ACTUAL generated module: `cordic_x_next(100, -64, shift=2)` returned **-16268**; the spec, C and Zig all say **116**
- y = -64 is 16'hFFC0 = 65472; 65472 >> 2 = 16368; 100 - 16368 = -16268
- this project's own hand-written golden CORDIC RTL writes `y0 >>> 1` for the identical rotation, so the right operator was known and the expression path emitted it ZERO times across 559 modules
- `>>>` occurrences corpus-wide: 2 -> 369 across 48 specs; both of the old two were inside string literals
- iverilog acceptance unchanged 373/559 -- the wrong shift was always legal Verilog, which is why no gate could have caught it
- tempered, and the audit said so first: 42 of the 45 affected specs shift non-negative values today, so they are LATENT. The three igla/race CORDIC specs are value-corrupting now
Loading