Skip to content

docs: record what callbacks accept per platform, and the arm64 aggreg… - #84

Open
unxed wants to merge 2 commits into
go-webgpu:mainfrom
unxed:feature/callback-abi-docs
Open

unxed wants to merge 2 commits into
go-webgpu:mainfrom
unxed:feature/callback-abi-docs

Conversation

@unxed

@unxed unxed commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

…ate gap

NewCallback answers an unsupported signature with a panic, and two of the three limits behind those panics are undocumented, so they read as bugs:

panic: ffi: unsupported callback argument type: struct
panic: ffi: Windows callbacks require uintptr-sized return type, got int32

docs/CALLBACK_ABI.md puts the three rows in one table -- amd64 Unix takes struct-by-value arguments, arm64 does not, Windows takes uintptr-sized arguments and one uintptr-sized result and nothing else -- and separates the limit that is permanent from the one that is not. Windows is the platform's own contract: NewCallback delegates to syscall.NewCallback, which accepts nothing more without cgo, and purego documents the same restriction. arm64 is unfinished work.

For that one the page carries what an implementer needs rather than a wish: where amd64 does the equivalent (callbackWrap's eightbyte classification in ffi/callback.go), the four AAPCS64 cases to cover, the two that are easy to get wrong -- a four-float32 HFA occupying S0-S3, i.e. the low halves of four V registers the frame stores as 64-bit slots, and register exhaustion sending the whole aggregate to the stack with no backfill -- and Apple's naturally aligned stack packing, which means any implementation has to be checked against both a Linux and an Apple toolchain. It also points at ffi/callback_struct_args_test.go as the model for testing classification with a hand-built frame, no C toolchain and no real foreign call needed.

Callers get the workaround in one line: take a pointer instead of a value.

The panic site in ffi/callback_arm64.go now points at the page, so the message someone actually sees leads to the explanation.

@codecov

codecov Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

unxed and others added 2 commits September 17, 2026 13:23
Both Android arm64 jobs now fail in "Set up Android SDK", before any goffi
code runs:

    Warning: Failed to find package 'tools'
    Error: The process '/usr/local/lib/android/sdk/cmdline-tools/16.0/bin/sdkmanager' failed with exit code 1

android-actions/setup-android@v3 defaults its `packages` input to
`tools platform-tools` and runs `sdkmanager <pkg>` for each entry. Google's
SDK repository index (repository2-3.xml) no longer contains a `tools`
package, while `platform-tools` and `cmdline-tools` are still listed, so
the `tools` call exits 1. The same breakage is tracked upstream in
android-actions/setup-android#537. The last green run of these jobs on main
was for c8f74c6 on 2026-09-10; the workflow has not changed since, and the
failure is identical on a docs-only PR.

Nothing in this workflow or in scripts/check-android-arm64.sh uses the
`tools` package. Pass `packages: platform-tools`, which keeps everything
the step installed before except the package that no longer exists. The
action still accepts licenses, exports ANDROID_HOME and puts sdkmanager on
PATH, which the following NDK step relies on.
…ate gap

NewCallback answers an unsupported signature with a panic, and two of the
three limits behind those panics are undocumented, so they read as bugs:

    panic: ffi: unsupported callback argument type: struct
    panic: ffi: Windows callbacks require uintptr-sized return type, got int32

docs/CALLBACK_ABI.md puts the three rows in one table -- amd64 Unix takes
struct-by-value arguments, arm64 does not, Windows takes uintptr-sized
arguments and one uintptr-sized result and nothing else -- and separates the
limit that is permanent from the one that is not. Windows is the platform's
own contract: NewCallback delegates to syscall.NewCallback, which accepts
nothing more without cgo, and purego documents the same restriction. arm64 is
unfinished work.

For that one the page carries what an implementer needs rather than a wish:
where amd64 does the equivalent (callbackWrap's eightbyte classification in
ffi/callback.go), the four AAPCS64 cases to cover, the two that are easy to
get wrong -- a four-float32 HFA occupying S0-S3, i.e. the low halves of four V
registers the frame stores as 64-bit slots, and register exhaustion sending
the whole aggregate to the stack with no backfill -- and Apple's naturally
aligned stack packing, which means any implementation has to be checked
against both a Linux and an Apple toolchain. It also points at
ffi/callback_struct_args_test.go as the model for testing classification with
a hand-built frame, no C toolchain and no real foreign call needed.

Callers get the workaround in one line: take a pointer instead of a value.

The panic site in ffi/callback_arm64.go now points at the page, so the message
someone actually sees leads to the explanation.
@unxed
unxed force-pushed the feature/callback-abi-docs branch from 3e1e0d1 to 3f9133f Compare September 25, 2026 16:31
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