Skip to content

abi-diff --asm: assembly-level triage of every target; findings 40-43 - #36

Merged
zmaril merged 2 commits into
mainfrom
mirth/abi-asm
Oct 10, 2026
Merged

zmaril merged 2 commits into
mainfrom
mirth/abi-asm

Conversation

@zmaril

@zmaril zmaril commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

What

mirth-lab abi-diff --asm decides the IR-level differences that abi-diff reports by checking where each argument and the return value actually end up.

  • Bodies: each generated function stores every parameter to an extern volatile global and returns a volatile load, so every argument's lowering is observable.
  • Each side's own backend: both sides are compiled to MIR after instruction selection.
    • rustc: -Cllvm-args=-stop-after=finalize-isel (its --emit=asm output is then MIR).
    • clang: -mllvm -stop-after=finalize-isel.
    • clang is given rustc's FPU (-mfpu), soft-float ABI (-mabi=aapcs-soft) and relocation model (-fPIC/-fno-pic).
  • What is compared:
    • the incoming physical registers in argument order, one name per register-file location;
    • the incoming stack slots read, clipped to the area outside the register home area;
    • the registers the return reads.
  • Verdicts: an IR difference with the same placement counts as equivalent. A signext/zeroext difference on an integer narrower than a register stays a finding, because placement cannot show an extension contract.

Validation on the 21 main targets

  • Finding 20 shows a placement difference.
  • Finding 19 and #163911 keep the same placement; they are extension contracts and stay findings.
  • Nothing else differs.
  • The PowerPC64 inreg float, previously labelled "needs a run", has the same placement in all 40 cases, so it is equivalent.
  • The default mode (without --asm) produces the same output as before.

--asm --all, seeds 1–3, 312 targets

  • Equivalent: thousands of IR differences (parameter attributes, parameter types, calling conventions, returns).
  • Harness artifacts, now fixed:
    • clang's default armv7r CPU has no FPU;
    • soft-float AArch64 needs aapcs-soft;
    • MIPS PIC code receives its address in $t9.
  • Every remaining placement difference is classified in a new "Assembly-level triage" table under check 14 in docs/checks.md. Each class gets a verdict and the evidence for it; GCC behaviour cited from source or documentation is marked as not run.

Findings (facts only, under docs/hunt/)

# what tier
40 mips64 (n64): narrow integer extern "C" arguments lose signext/zeroext, so a Rust caller no longer extends them (sll/seb replaced by nop). Regression from #163653, merged 2026-10-04: nightly-2026-07-18 and 1.98.0 are fine, nightly-2026-10-06 is affected. 3
41 thumbv7a Windows: homogeneous float aggregates are passed in core registers and returned through memory, where clang uses s0/s1. rustc applies the VFP aggregate rules only to eabihf targets. 3
42 32-bit PowerPC FreeBSD/NetBSD/OpenBSD/HelenOS: aggregates of up to 8 bytes are returned through memory, where clang returns them in r3/r4. 3
43 m68k: repr(C) alignment of i64 is 4 and of f64 8, where GCC's documented default is 2. 3

Other results:

  • nvptx64-nvidia-cuda: this target's Rust side was always skipped. The skip is the known ICE #163497, reachable from a plain extern "C" return of an align(32) struct since 1.90.0.
  • Numbering: findings are numbered 40–43 because mirth-lab rustdoc-diff (check 6): rustdoc consistency; findings 33-39 #34 uses 33–39. They may need renumbering if other branches land first.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QXiEXbESemwqMLYKaWLDbT

zmaril and others added 2 commits October 10, 2026 10:37
…erences; triage of every target; findings 40-43

Each generated function stores its parameters to extern volatile globals and returns a volatile
load; both sides are compiled to MIR after instruction selection by their own backend (rustc
-Cllvm-args=-stop-after=finalize-isel, clang -mllvm -stop-after=finalize-isel, clang given
rustc's FPU, soft-float ABI and relocation model) and the incoming registers, stack slots and
return registers are compared. Validated on the main targets (finding 20 differs, findings 19 and
#163911 keep their placement, nothing else differs; the ppc64 inreg float is equivalent).

--all, seeds 1-3: thousands of IR differences are equivalent; what remains is classified in
docs/checks.md. Findings: 40 mips64 narrow integer arguments lose signext/zeroext (regression from
#163653), 41 thumbv7a Windows homogeneous float aggregates not in VFP registers, 42 32-bit
PowerPC BSDs return small structs through memory, 43 m68k repr(C) alignment of i64/f64.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXiEXbESemwqMLYKaWLDbT
… from a plain extern "C" return of an align(32) struct, since 1.90.0)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXiEXbESemwqMLYKaWLDbT
@zmaril
zmaril merged commit c8b4aa6 into main Oct 10, 2026
0 of 3 checks passed
@zmaril

zmaril commented Oct 10, 2026

Copy link
Copy Markdown
Contributor Author

Merged into main together with #33–#38; renumbered at merge so finding numbers are unique: findings 40–43 are now 44–47 (docs/hunt.md).

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