Summary
On synth v0.66.0, the falcon flight cascade compiles almost completely for
--target cortex-m7dp: 21 of 22 functions lower, including 1408- and
1468-byte ones. Exactly one declines — the exported tick — with:
GI-FPU-002: VFP register file exhausted (S0..S15 all live) — f32/f64 register
pressure exceeds the file; the backend retries with VFP spilling (#881) and
this surfaces only if that also fails
#881 is closed, so this is a report that the case it covers still reproduces
on the current release with a real workload.
Reproduce
synth compile falcon_cascade_cm.wasm --target cortex-m7dp --all-exports -o out.elf
The component is the published falcon cascade (pulseengine:falcon-cascade@0.10.0),
a single step export wrapping the whole flight core — IEKF estimator,
geometric SE(3) attitude, ADRC inner loop, mixer with rotor-out FDI, plus the
altitude and position loops. It is float-heavy by construction and the tick is
one large function after inlining.
Target sensitivity (same input, same synth)
| target |
functions skipped of 22 |
| cortex-m7dp |
1 (the tick only) |
| cortex-m4f |
3 |
| cortex-m7 |
3 |
| cortex-m3 (no FPU) |
16 |
What we tried on our side, and why it did not help
Register pressure is arguably ours, so we split the export into a thin
forwarder plus an #[inline(never)] body. The decline simply moved with the
body:
warning: skipping function 'func_1': ... GI-FPU-002 ...
Error: #1102: 1 retained function(s) relocate against function(s) this compile
DECLINED: 'controller@0.10.0#step' -> 'func_1'
So the pressure is inherent to the tick body — where FlightCore::step inlines
the full cascade — and not to the export boundary. Splitting at the seam cannot
fix it; it converts a partial object into an unlinkable one. Reducing it from
our side would mean forcing #[inline(never)] on the flight core's internal
stages, which changes the code we verify and fly, so we would rather ask first.
Question: is per-stage #[inline(never)] in the guest the intended remedy
for GI-FPU-002, or is VFP spilling expected to cover a tick of this size?
Credit where due — two refusals behaved exactly right
Both #952 (partial object) and #1102 (unlinkable object) exited non-zero
with an explicit explanation rather than shipping something a $? gate would
accept. That is the correct behaviour and it is what made this diagnosable in
one pass.
Context
Asked by a colleague evaluating the meld+synth firmware route for a Pixhawk
6X-RT / H7 airframe: "validate a trivial float path through
synth compile --cortex-m → Renode before committing the firmware rewrite to
the schedule." Trivial float paths lower correctly — verified vmul.f32,
vadd.f32, vdiv.f32, vsqrt.f32 with the hard-float ABI on m7dp — so #369
and #708 are genuinely fixed. This tick is the remaining gate.
Summary
On synth v0.66.0, the falcon flight cascade compiles almost completely for
--target cortex-m7dp: 21 of 22 functions lower, including 1408- and1468-byte ones. Exactly one declines — the exported tick — with:
#881is closed, so this is a report that the case it covers still reproduceson the current release with a real workload.
Reproduce
The component is the published falcon cascade (
pulseengine:falcon-cascade@0.10.0),a single
stepexport wrapping the whole flight core — IEKF estimator,geometric SE(3) attitude, ADRC inner loop, mixer with rotor-out FDI, plus the
altitude and position loops. It is float-heavy by construction and the tick is
one large function after inlining.
Target sensitivity (same input, same synth)
What we tried on our side, and why it did not help
Register pressure is arguably ours, so we split the export into a thin
forwarder plus an
#[inline(never)]body. The decline simply moved with thebody:
So the pressure is inherent to the tick body — where
FlightCore::stepinlinesthe full cascade — and not to the export boundary. Splitting at the seam cannot
fix it; it converts a partial object into an unlinkable one. Reducing it from
our side would mean forcing
#[inline(never)]on the flight core's internalstages, which changes the code we verify and fly, so we would rather ask first.
Question: is per-stage
#[inline(never)]in the guest the intended remedyfor GI-FPU-002, or is VFP spilling expected to cover a tick of this size?
Credit where due — two refusals behaved exactly right
Both
#952(partial object) and#1102(unlinkable object) exited non-zerowith an explicit explanation rather than shipping something a
$?gate wouldaccept. That is the correct behaviour and it is what made this diagnosable in
one pass.
Context
Asked by a colleague evaluating the meld+synth firmware route for a Pixhawk
6X-RT / H7 airframe: "validate a trivial float path through
synth compile --cortex-m→ Renode before committing the firmware rewrite tothe schedule." Trivial float paths lower correctly — verified
vmul.f32,vadd.f32,vdiv.f32,vsqrt.f32with the hard-float ABI on m7dp — so #369and #708 are genuinely fixed. This tick is the remaining gate.