Skip to content

riscv64: Restore the IR types 7576d04 widened - #90

Open
zardus wants to merge 1 commit into
masterfrom
feature/riscv64-ir-types
Open

riscv64: Restore the IR types 7576d04 widened#90
zardus wants to merge 1 commit into
masterfrom
feature/riscv64-ir-types

Conversation

@zardus

@zardus zardus commented Aug 13, 2026

Copy link
Copy Markdown
Member

THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS

7576d04 ("riscv: fix instructions that use the unsupported Ity_1 data type") widened three
Ity_I1 temporaries to Ity_I64/Ity_I32 without adapting what is assigned to them, so six
instruction forms now fail the IR sanity check and libVEX reports the whole block as
Ijk_NoDecode:

  • sc.w / sc.d. IRStmt_LLSC's result type is fixed by the IR contract:
    pub/libvex_ir.h says "STOREDATA != NULL (SC): transfer type = type of STOREDATA, and
    RESULT :: Ity_I1". Widening the temp makes the statement itself invalid, and no other
    encoding of a store-conditional exists. guest_arm64_toIR.c builds the same sequence with
    Ity_I1 and Iop_1Uto64, which is what this restores.
  • feq.s / flt.s / feq.d / flt.d. Their Iop_CmpEQ32 yields Ity_I1 into an Ity_I32
    temp. The fle case in the same switch already wraps its comparisons in Iop_1Uto32; feq
    and flt now do the same.

Before, on master:

sc.d a3, a1, (s2)   af36b918   size=0 jumpkind=Ijk_NoDecode
sc.w a3, a1, (s2)   af26b918   size=0 jumpkind=Ijk_NoDecode
feq.s a0, fa0, fa1  5325b5a0   size=0 jumpkind=Ijk_NoDecode
flt.s a0, fa0, fa1  5315b5a0   size=0 jumpkind=Ijk_NoDecode
feq.d a0, fa0, fa1  5325b5a2   size=0 jumpkind=Ijk_NoDecode
flt.d a0, fa0, fa1  5315b5a2   size=0 jumpkind=Ijk_NoDecode
fle.s a0, fa0, fa1  5305b5a0   size=4 jumpkind=Ijk_Boring

with vex: the 'impossible' happened: sanityCheckFail: exiting due to bad IR and
ERROR = Ist.LLSC(SC).result: not :: Ity_I1 on stderr. After, all six decode.

The visible cost is in angr: a RISC-V block that runs into one of these becomes undecodable
bytes, and CFGFast's linear scan then restarts two bytes into the four-byte instruction, so
blocks begin in the middle of instructions. Over a corpus sweep this accounted for the whole
RISC-V share of that symptom.

Consumed by angr/pyvex#566, which carries the regression tests. Fixes angr/pyvex#516,
whose diagnosis covers flt only.

Validation: angr/pyvex#566 (comment)

IRStmt_LLSC's result is Ity_I1 whenever storedata is non-NULL; pub/libvex_ir.h
states it and guest_arm64_toIR.c builds the same store-conditional that way.
Widening the temp to Ity_I64 made the statement fail the IR sanity check, so
sc.w and sc.d stopped decoding at all.

feq and flt assign an Ity_I1 comparison into the Ity_I32 temp they share with
fle, which wraps its own comparisons in Iop_1Uto32. They now do the same, in
both the F and the D extension.

All six forms reported Ijk_NoDecode with size 0 before this; a RISC-V block that
runs into one becomes undecodable bytes, and angr's linear scan restarts inside
the instruction.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RISC-V flt.s and flt.d instructions cause IR sanity check failure

1 participant