Skip to content

feature: M4-portability half of GI-FPU-002 RESOLVED — full cascade lowers 5/5 on m4f; jess's obligation is 3 AEABI symbols, verified linkable (AFD-046) - #193

Merged
avrabe merged 1 commit into
mainfrom
feature/m4-lowering-closed
Aug 27, 2026
Merged

feature: M4-portability half of GI-FPU-002 RESOLVED — full cascade lowers 5/5 on m4f; jess's obligation is 3 AEABI symbols, verified linkable (AFD-046)#193
avrabe merged 1 commit into
mainfrom
feature/m4-lowering-closed

Conversation

@avrabe

@avrabe avrabe commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

The M4 lowering path is closed for the full cascade

The loop asked whether synth#881's "--builtins / M4-portability half" was still unresolved in practice, and to re-file if so. It is resolved. Nothing needs re-filing — it needs jess keeping two promises.

The self-contained path's 3 skips are correct behaviour, not a defect

synth refuses to emit f64 on a single-precision FPU (#369), declining func_4, position#tick and rate#tick on m4f. Its own message names the remedy: route the i64↔f32 conversions through the AEABI builtins with --relocatable (#1069).

Following that walks a chain of three honest-refusal gates, each handing jess an obligation rather than failing quietly:

--relocatable             -> refuses #1041: 13 active data segments not materialised
+ --embedder-data-init    -> refuses #1052: 12 global initialisers do not reach the object
+ --embedder-global-init  -> exit 0, ZERO skips, 5/5 stages

Result

falcon v1.135.0 · meld 0.52 --pack-rebase → loom 1.4.0 → synth v0.60

core exit skips stages external symbols
cortex-m7dp 0 0 5/5 0
cortex-m4f 0 0 5/5 3
cortex-m3 1 12 soft-float; falcon was never targeted there

jess's entire M4 link obligation is three symbols: __aeabi_f2lz, __aeabi_l2f, __aeabi_ul2f. m7dp needs none — it has the double-precision FPU.

"It lowers" is not "it works", so the obligation was discharged

All three are defined in stock arm-none-eabi libgcc (thumb/v7e-m+fp/hard); arm-none-eabi-ld -r returns 0 with zero undefined remaining, and all 5 stages are still T in the linked object.

Negative control, asserted by the oracle: linking without libgcc leaves exactly those 3 undefined. Without it, "0 undefined" would be vacuous — an empty nm is also what a broken object prints. tools/lowering/m4-matrix.sh fails if the negative control comes back empty.

A silent misreport in the oracle, caught by its own negative control

The first version used mapfile, which doesn't exist in macOS's bash 3.2, and printed <none> for a symbol list that actually had three entries. Step 5 contradicted step 2, which is how it surfaced. Replaced with a portable read, and the script now hard-fails on an empty list rather than printing a reassuring placeholder.

Two promises jess now owes — real, not paperwork

The flags emit byte-identical code; they only convert a refusal into an acknowledgement. jess must populate memory 0's active data segments and seed the R9 globals table before any export runs. If it doesn't, every load from the initialised region and every global.get reads whatever the target memory holds — the gale#278 0xFF class. That is the next concrete implementation item.

Release-watch: falcon-v1.135.0 — clean, no regression

10/10 digests match; 8/10 pass the publish gate; numerically identical to v1.134.1 (torque tx=1 ty=0.472507507 tz=-0.147003502 thrust=0.5), and the composed flight-app returns the same 2147484996.

A controlled comparison was run before suspecting a regression: v1.134.1 and v1.135.0 give the same 3 m4f skips under an identical pipeline, so the skip count is a property of the path, not the release. My first matrix run looked like a regression purely because I'd omitted loom.

The two new artifacts — cascade-stream-composed (2.8 MB, wasi:cli/*) and cascade-stream-fused (211 KB core module) — are P3 async-stream artifacts (stream-new, task-return, stream-cancel-*). They fail C3/C1 respectively, which is expected for host-side artifacts and is not reported as a defect. Worth relay confirming the intended consumer, since these are the first shipped P3 artifacts in the stack.

Also confirmed: meld#390 reproduces identically with v1.135.0 components, ruling out the falcon build as a variable. Reported on that issue.

🤖 Generated with Claude Code

https://claude.ai/code/session_017EKh2onUHpWSUiAEqWxfy2

…cade lowers 5/5 on m4f, and jess's obligation is 3 AEABI symbols, verified linkable (AFD-046)

The loop asked whether synth#881's "--builtins / M4-portability half" was still unresolved in
practice, to be re-filed if so. IT IS RESOLVED. Nothing needs re-filing; it needs jess keeping two
promises.

The self-contained path still declines 3 functions on m4f, and that is CORRECT — synth refuses to
emit f64 on a single-precision FPU (#369). Its own message names the remedy: route the i64<->f32
conversions through the AEABI builtins with --relocatable (#1069).

Following that remedy walks a chain of THREE honest-refusal gates, each handing jess an obligation
rather than failing quietly:

  --relocatable            -> refuses #1041: 13 active data segments not materialised
  + --embedder-data-init   -> refuses #1052: 12 global initialisers do not reach the object
  + --embedder-global-init -> exit 0, ZERO skips, 5/5 stages

MEASURED (falcon v1.135.0, meld 0.52 --pack-rebase -> loom 1.4.0 -> synth v0.60):
  cortex-m7dp   exit 0   0 skips   5/5 stages   0 external symbols
  cortex-m4f    exit 0   0 skips   5/5 stages   3 external symbols
  cortex-m3     exit 1   12 skips             (soft-float; falcon was never targeted there)

JESS'S ENTIRE M4 LINK OBLIGATION IS THREE SYMBOLS: __aeabi_f2lz, __aeabi_l2f, __aeabi_ul2f.
m7dp needs NONE — it has the double-precision FPU.

"IT LOWERS" IS NOT "IT WORKS", so the obligation was DISCHARGED rather than described: all three are
defined in stock arm-none-eabi libgcc (thumb/v7e-m+fp/hard), `arm-none-eabi-ld -r` returns 0 with
ZERO undefined remaining, and all 5 stages are still T in the linked object.

NEGATIVE CONTROL, asserted by the oracle: linking WITHOUT libgcc leaves exactly those 3 undefined.
Without it, "0 undefined" is vacuous — an empty nm is also what a broken object prints. The script
FAILS if the negative control comes back empty.

A SILENT MISREPORT IN THE ORACLE, CAUGHT BY ITS OWN NEGATIVE CONTROL: the first version used
`mapfile`, which does not exist in macOS's bash 3.2, and printed "<none>" for a symbol list that
actually had three entries. Step 5 contradicted step 2, which is how it surfaced. Replaced with a
portable read, and the script now hard-fails if the list is empty.

TWO PROMISES JESS NOW OWES AT INSTANTIATION — real, not paperwork. The flags emit BYTE-IDENTICAL
code; they only convert a refusal into an acknowledgement. jess must populate memory 0's active data
segments and seed the R9 globals table before any export runs, or every load from the initialised
region reads whatever the target memory holds (the gale#278 0xFF class).

RELEASE-WATCH, falcon-v1.135.0 — CLEAN, NO REGRESSION: 10/10 digests match, 8/10 pass the publish
gate, numerically IDENTICAL to v1.134.1, composed flight-app returns the same 2147484996. A
CONTROLLED COMPARISON was run before suspecting a regression: both releases give the same 3 m4f
skips under an identical pipeline, so the count is a property of the path, not the release.

The two new artifacts (cascade-stream-composed 2.8 MB with wasi:cli, cascade-stream-fused 211 KB
core module) are P3 async-STREAM artifacts. They fail C3/C1, which is EXPECTED for host-side
artifacts and is NOT reported as a defect.

rivet validate PASS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@avrabe
avrabe merged commit 3b9581e into main Aug 27, 2026
5 checks passed
@avrabe
avrabe deleted the feature/m4-lowering-closed branch August 27, 2026 23:06
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.

1 participant