commit 8ace7b4efb4478f3c7a24fd0a4bccf7ab89cc54a
parent dbed4e112a29d1493ee3b7a73a44ba7e33956cf3
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 17 Jun 2026 05:39:11 -0700
doc(ARM32): add a single-source-of-truth Core checklist
Consolidate the remaining work into one scannable checklist near the top: Core
outstanding (AEABI self-build / GNU numeric labels, full coro runtime fault,
kit-compiled reset stub, .ARM.attributes, inline-asm real-mnemonics via asm.c),
Core done, and Follow-on variants/polish. Reconcile the stale §1-§5 checkboxes
(§1 + §2 tail/memmove/varargs/hints now [x]; §3 rt-self-build marked PARTIAL) and
point them at the new checklist.
Diffstat:
| M | doc/plan/ARM32.md | | | 82 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
1 file changed, 69 insertions(+), 13 deletions(-)
diff --git a/doc/plan/ARM32.md b/doc/plan/ARM32.md
@@ -14,6 +14,56 @@ AEABI alias layer (GNU numeric local labels), the full coro runtime fault, the
kit-compiled reset stub, and `.ARM.attributes` remaining. See the §3 status and
"Remaining work" below.
+## Core checklist — remaining items (single source of truth)
+
+What is left to call the arm32 **core** complete, plus the follow-on variants
+that are explicitly out of "core" scope. This list is authoritative; the prose
+"Remaining work" §1–§5 below is the original design rationale (its done items
+are now checked there too).
+
+**Core — outstanding** (all are §3 toolchain / §2 inline asm):
+- [ ] **AEABI alias layer self-build** — re-enable `RT_arm-eabi-thumb2_AEABI =
+ thumb2`. Blocked on **GNU numeric local labels** (`1:` / `1f` / `1b`) in
+ `kit as`, which the soft-float compare helpers (`DEFINE_AEABI_DCMP/FCMP`)
+ use. Everything else in `aeabi_thumb2.S` already assembles with kit.
+- [ ] **Full coroutine runtime** — `coro_init`/`coro_resume`/`coro_yield` faults
+ on bare-metal arm32 (a `coro/coro.c`-level static-stack/TLS layout
+ interaction; the switch/trampoline asm itself is byte-correct and
+ setjmp/longjmp round-trips). The coro layer self-builds; this is the
+ runtime correctness gap.
+- [ ] **kit-compiled Cortex-M reset stub** — replace the clang-assembled
+ `start.S` in `test/lib/exec_bare.sh` (rewrite off literal pools / post-
+ indexed `[rN],#4` to MOVW/MOVT + explicit add, or add those asm forms;
+ needs BKPT — present — and the semihosting exit sequence).
+- [ ] **`.ARM.attributes`** — emit the minimal Tag_ABI build-attributes section
+ (Tag_CPU_arch=ARMv7-M, Tag_THUMB_ISA_use, Tag_ABI_VFP_args=base, …) in
+ `src/obj/elf/emit.c` for external-toolchain interop.
+- [ ] **Inline asm real mnemonics via `asm.c`** — route `asm_block` (case 20 and
+ friends) through the descriptor-driven assembler instead of the minimal
+ template runner, so arbitrary Thumb-2 mnemonics work (operand binding for
+ r/i/m/=&r/inout/clobbers already lands; this is the template-run seam).
+
+**Core — done** (closed; details under "Residual reds" + §1/§2 below):
+- [x] Unified wide/addressing memory layer; i64/wide stores to global/frame
+ (§1). [x] Tail/sibling calls, `@memmove`, varargs edge cases, wide hint
+ intrinsics (§2). [x] The five -O0/-O1 edge reds 112/123/124/140/154.
+ [x] Inline-asm operand binding (case 20 green). [x] coro **layer** self-
+ builds with kit-as (save/restore verified). [x] `kit as` hardening: cmp/mov
+ `#imm`, SP-relative add/str/ldr + high-reg T3, UDF, `;` separator,
+ `#imm`-in-macro, `__ELF__`/empty `__USER_LABEL_PREFIX__`, soft-float
+ `__ARM_FP` undefined.
+
+**Follow-on variants / polish** (NOT required for "core"; the `variant` seam, §4/§5):
+- [ ] Hard-float (FPv4-SP, `arm-none-eabihf`): VFP codegen + softfp/hard axis.
+- [ ] DSP / ARMv7E-M saturating + packed-SIMD behind the `dsp` feature.
+- [ ] ARMv6-M / Thumb-1 (no IT / MOVW-MOVT / hardware divide / 32-bit Thumb).
+- [ ] Full `-mcpu`/`-march`/`-mfpu`/`-mfloat-abi` parsing + the complete
+ `__ARM_FEATURE_*` predefined-macro set.
+- [ ] Multi-threaded TLS (variant-I tp-relative; replaces TLS-as-static).
+- [ ] 16-bit-encoding density + shifted-register-operand peephole (toward tcc).
+- [ ] (cosmetic) disassembler renders shifted-MOV (`mov.w rd,rs,lsl #N`) as plain
+ `mov` — encodings are correct; listings lose the shift.
+
## Status — 2026-06-16 — Phase 2b — memory/frame/ABI correctness landed
The arm32 backend is a working -O0/-O1 Cortex-M C toolchain: it compiles, links
@@ -144,6 +194,10 @@ checklist below.
## Remaining work — design these correctly; do NOT keep patching
+> For the scannable list of what is left, see the **Core checklist** near the top
+> — it is the single source of truth. The §1–§5 below are the original design
+> rationale, with done items checked in place.
+
Phase 2 surfaced a clear lesson. Several separate correctness bugs — a branch
placeholder addend, two scratch-register clobbers (`str lr,[lr]`;
ip-resident-base clobber), and an incomplete wide-access split — all lived in the
@@ -158,12 +212,12 @@ i64/wide-store-to-global bug in §1 is the latest). **The items below must be do
as coherent, correct-by-construction designs, not as more spot patches.** Each
names the design, not a workaround.
-### 1. Correctness — the wide / addressing memory layer (highest priority)
-- [ ] **i64/wide stores to global/static addresses, and an i64 struct field at a
+### 1. Correctness — the wide / addressing memory layer (DONE — Phase 2b)
+- [x] **i64/wide stores to global/static addresses, and an i64 struct field at a
non-zero offset, are miscompiled** (i64 global *reads* work; *writes* do
not). Located: the 8-byte split's high lane + the GLOBAL-base
address/offset + scratch selection are not uniform across base kinds.
-- [ ] **Design:** one memory-access lowering, correct by construction —
+- [x] **Design:** one memory-access lowering, correct by construction —
(a) a single address-resolver that maps any `NativeAddr` × byte offset ×
width to a legal `(base, in-range-offset)`, or materializes the full
effective address once into a *reserved* scratch, choosing a scratch that
@@ -174,24 +228,26 @@ names the design, not a workaround.
place. This retires the ad-hoc `lr`/`ip` rescue paths added during Phase 2.
### 2. Functional features — real implementations, not stubs
-- [ ] **Tail / sibling calls** (`arm_emit_call` panics on `CG_CALL_TAIL`) —
+- [x] **Tail / sibling calls** (`arm_emit_call` panics on `CG_CALL_TAIL`) —
AAPCS tail-call lowering (epilogue-before-jump, in-place arg shuffle,
`BX`/`B.W` to the callee) covering musttail / sret / variadic forms.
-- [ ] **`@memmove`** — overlap-safe, direction-aware copy (compare dst vs src),
+- [x] **`@memmove`** — overlap-safe, direction-aware copy (compare dst vs src),
sharing the granule engine with `copy_bytes`.
-- [ ] **Varargs edge cases** — mixed int/fp/i64, stack-arg + result-on-stack:
+- [x] **Varargs edge cases** — mixed int/fp/i64, stack-arg + result-on-stack:
complete `va_arg` over the unified arg window, validated against the
GP-save-area layout (no per-width special cases).
-- [ ] **Wide (i64) hint intrinsics** — `@expect`/`assume_aligned` on 8-byte
+- [x] **Wide (i64) hint intrinsics** — `@expect`/`assume_aligned` on 8-byte
values currently move only the low lane; fold them through the wide path.
-- [ ] **Full inline asm** — route `asm_block` through the real descriptor-driven
- assembler instead of the minimal template runner.
+- [ ] **Full inline asm** — operand binding (r/i/m/=&r/inout/clobbers) lands and
+ case 20 is green on the minimal template runner; routing real mnemonics
+ through the descriptor-driven assembler is the remaining piece (Core
+ checklist, top).
### 3. Toolchain / runtime completeness
-- [ ] **kit-self-built rt with no exclusions** — grow the descriptor-driven
- assembler to cover the M-profile system + hand-written-asm idioms, then
- re-enable the AEABI alias layer + coroutine register-switch asm (`AEABI`/
- `CORO` in `mk/rt.mk` + the driver's `kRtSrcArm32`), which are clang-only now.
+- [ ] **kit-self-built rt with no exclusions** — PARTIAL: the coroutine layer
+ (`CORO` in `mk/rt.mk`) now self-builds with kit-as; the AEABI alias layer
+ (`AEABI`) is still clang-only, blocked on GNU numeric local labels (Core
+ checklist, top). The full coroutine runtime also still faults at run time.
- [ ] **Multi-threaded TLS** — replace single-thread TLS-as-static with a real
variant-I tp-relative model (software thread pointer + reset-stub seed).