Skip to content

Document the complete embedder layout contract for --relocatable on Cortex-M: R9 is specified, the linear-memory base is not #1131

Description

@avrabe

Ask: document the complete embedder layout contract for --relocatable on Cortex-M

jess is at the point of actually running a --relocatable cascade object on an emulated RT1176, and I've hit the one part of the contract I can't find written down. Rather than reverse-engineer it from disassembly and risk building on a guess, I'd rather ask.

Where I am

Following your documented remedy chain, the full 5-stage falcon cascade lowers cleanly:

synth v0.60.0, meld 0.52 --pack-rebase -> loom 1.4.0
  cortex-m7dp  --relocatable --embedder-data-init --embedder-global-init  exit 0, 0 skips, 5/5 stages, 0 external symbols
  cortex-m4f   same                                                       exit 0, 0 skips, 5/5 stages, 3 external symbols

The three m4f externals are __aeabi_f2lz / __aeabi_l2f / __aeabi_ul2f, all resolved from stock arm-none-eabi libgcc — that half is closed and jess links it clean.

I've also discharged both declared obligations rather than just acknowledging them: extracted the module's 13 active data segments (43,005 B) and 12 non-zero global initialisers into linkable freestanding C, verified byte-for-byte against wasmtime's own instantiated memory (segments) and against a raw binary parse of the global section (globals), and linked the result beside the ARM object with 0 undefined.

What I can't find documented

--embedder-global-init's help text says, precisely and usefully:

the documented contract assigns only the table BASE (R9) to the embedder

and the --stack-placement text says:

with --relocatablethe linker/harness owns the layout

Both are clear. What I can't find is how the harness communicates the linear-memory base.

Measured on the m4f object:

  • no data relocations at all — every relocation is R_ARM_THM_CALL (inter-function calls plus the three AEABI helpers). So no external symbol supplies a base.
  • r9 appears 20 times, consistent with the documented globals-table base.
  • loads/stores go through [fp, ip] (r11/r12) and sp — so there is clearly a base-register convention for linear memory, but nothing in --help names it.

So concretely:

  1. Which register carries the linear-memory base on the --relocatable Cortex-M pathip? fp? Something the harness sets once before the first call, like R9?
  2. When must it be established — same rule as R9 ("before any export runs"), or per-call?
  3. Are R9 and the linmem base independent, or is the globals table expected at a fixed offset from linmem?
  4. Any alignment or minimum-extent requirement on the region the harness reserves?

A short "embedder ABI" block in compile --help alongside the two --embedder-* flags would settle it. Those flags already tell an integrator what state to supply; this is the missing where to put it, and without it the two obligations can be met perfectly and the image still fault on its first load.

Why I'm asking rather than measuring

I can recover this from disassembly, and I nearly did. But an ABI inferred from one object on one target is exactly the kind of thing that looks right until a different module shifts a register allocation — and jess would be encoding it into an on-target harness that later carries safety-case evidence. I'd rather build to a stated contract.

This is also the last thing between jess and executing the lowered cascade on an emulated core with correct initialisation, which would be the first real end-to-end check of the whole meld → loom → synth chain against relay's SIL reference. Happy to write the harness against whatever you specify and report the result either way.

Prior art in this thread

For context on how the obligations landed: jess treats the --embedder-* flags as promises rather than configuration, since they emit byte-identical code — an image that declares them and doesn't keep them reads uninitialised memory silently. That framing came from your own help text and it's been useful; a documented base-register contract would complete it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions