/// Dedicated fixture for the `smod(INT_MIN, -1)` LLVM-UB bug reported in /// paritytech/revive#524. /// /// The bug is that LLVM constant-folds `srem(INT_MIN, -1)` to poison (signed /// overflow UB), which then propagates through subsequent operations and /// often collapses to 0. EVM SMOD defines this case as 0, so a bare /// `smod(INT_MIN, -1)` would coincidentally agree; we XOR the result with a /// runtime calldata word so any divergence between the (defined) EVM value /// and the (poison-derived) PVM value becomes observable. /// /// **Important compilation details that make the bug actually surface here:** /// /// 1. Operands are written as Yul expressions (`shl(255, 1)`, `sar(58, shl(58, /// sub(0,1)))`) rather than raw `0x8000...` / `0xfff...` literals. revive's /// pipeline constant-evaluates raw literals before LLVM ever sees them, so /// no `srem` instruction with both literal operands reaches LLVM and the /// UB-fold opportunity vanishes. Yul expression operands force a real /// `srem` to appear in LLVM IR. /// /// 2. The function has a single execution path (no `switch` over many cases). /// Multi-case dispatchers exceed LLVM's inlining budget for the runtime /// `__revive_signed_remainder` function, so the CALL is preserved and /// evaluated at runtime via RISC-V `rem` (which is defined as 0 for the /// INT_MIN/-1 pair) — hiding the bug. With a single case the inliner /// inlines aggressively, exposing the bug. object "SmodIntMinNegOneBug" { code { let size := datasize("SmodIntMinNegOneBug_deployed") codecopy(0, dataoffset("SmodIntMinNegOneBug_deployed"), size) return(0, size) } object "SmodIntMinNegOneBug_deployed" { code { let tag := calldataload(0) let int_min := shl(255, 1) let neg_one := sar(58, shl(58, sub(0, 1))) mstore(0, xor(smod(int_min, neg_one), tag)) return(0, 32) } } }