← board

IR_FRAME's documentation asserts a frame layout riscv32 does not use

The two artefacts

defs.inc:816, documenting IR_FRAME, states the property as universal:

Every pxx prologue pushes a real frame pointer and links it, so the saved-fp chain IS walkable: [fp] = the caller's fp, [fp + PtrSize] = the return address into the caller. get_pc_addr and get_caller_stackinfo are built from this op plus ordinary loads, so this is the ONLY op the backends need.

ir.inc:4977, above FramePrevFpOffset / FrameRetAddrOffset, states the opposite for one arm:

riscv32 is the odd one: s0 is left pointing at the BOTTOM of the frame, not above the saved pair, so its links are at +8/+12 rather than +0/+PtrSize. Assuming the common layout here would have silently walked into the locals.

Why this is worth a ticket even though nothing is broken

The lowering is correct: ir.inc:7607/7631/7639 build the walk from FrameRetAddrOffset / FramePrevFpOffset rather than from PtrSize, and ir_codegen_riscv32.inc:1264 carries a pointer to them. Checked; no defect in emitted code.

The defect is that defs.inc is the IR-op reference — the file a person adding a target or a frame intrinsic reads to learn what IR_FRAME guarantees — and it states a false universal with no exception and no pointer to the two accessors. The sentence "this is the ONLY op the backends need" actively discourages looking further. A new target with a riscv32-shaped prologue, or a new intrinsic built "from this op plus ordinary loads" as the doc invites, walks into the locals exactly as ir.inc warns — silently, which is the failure mode that comment exists to prevent.

Fix

One clause in defs.inc:816: the chain is walkable, but the offsets are per-target — ask FramePrevFpOffset / FrameRetAddrOffset (ir.inc), never assume +0/+PtrSize; riscv32 is +8/+12. Do not restate the layout table; there is already exactly one place it is written down and the point is to route readers to it.

Gate

Comment-only. make compiler/pascal26 (the fixedpoint) and nothing else.