Skip to content

fix: build callback_amd64.s on FreeBSD - #83

Merged
kolkov merged 1 commit into
go-webgpu:mainfrom
unxed:feature/freebsd-amd64-callback-asm
Oct 16, 2026
Merged

kolkov merged 1 commit into
go-webgpu:mainfrom
unxed:feature/freebsd-amd64-callback-asm

Conversation

@unxed

@unxed unxed commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

ffi/callback.go is built for (linux || darwin || freebsd) && amd64, but ffi/callback_amd64.s, which holds the 2000-entry trampoline table and callbackDispatcher, was built only for (linux || darwin) && amd64.

The Go side takes the table's address through a placeholder:

//go:linkname _callbackTrampoline github.com/go-webgpu/goffi/ffi.callbackTrampoline
var _callbackTrampoline byte

With the assembly excluded, that one-byte variable becomes the definition of ffi.callbackTrampoline. Nothing fails to compile or link. On a linked freebsd/amd64 consumer, go tool nm reports

D github.com/go-webgpu/goffi/ffi.callbackTrampoline

and no callbackDispatcher or callbackWrap at all, where linux/amd64 and freebsd/arm64 report T for all three. NewCallback therefore returns addresses computed from a data-segment byte, not code.

The dispatcher is plain System V AMD64 (the same ABI FreeBSD uses) and enters Go through crosscall2, which internal/fakecgo already provides on FreeBSD, so the fix is adding freebsd to the constraint.

The existing cross-compile job could not catch this: go build ./... links nothing, and the broken build compiles. scripts/check-callback- trampolines.sh links a small NewCallback consumer for every target whose callbacks come from goffi's own assembly (linux, darwin, freebsd x amd64, arm64) and fails unless the symbol is T. Run against the tree before this change it reports freebsd/amd64 as 'D'; after it, all six targets pass. The Cross-Compile job now runs it.

Not verified on a FreeBSD host; the evidence is the symbol table of the cross-linked binaries.

Refs: #76 (review)

@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
unxed force-pushed the feature/freebsd-amd64-callback-asm branch from 7768491 to 55f9278 Compare September 25, 2026 16:31
@kolkov kolkov added type: bug Something isn't working area: callbacks C-to-Go callback trampolines area: ci CI workflows, check scripts, branch protection platform: freebsd FreeBSD-specific arch: amd64 x86-64 specific (System V / Win64 ABI) labels Oct 15, 2026

@kolkov kolkov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up from the #76 review.

Verified locally (Go 1.27.1, linux/amd64 host):

  • Your scripts/check-callback-trampolines.sh run against current main fails exactly where it should: freebsd/amd64: ffi.callbackTrampoline has type 'B', want T. The other five targets are T.
  • On this branch all six targets report T.
  • go vet ./... and go test -count=1 ./... pass (CGO_ENABLED=0).

The gate is the valuable part here: a .s file with a narrower constraint than its .go counterpart compiles and links silently, and only the symbol type of a linked consumer shows it. Good catch on linking a real binary instead of relying on go build ./....

One nit for the CHANGELOG entry, since it's permanent text: the placeholder's symbol type depends on the toolchain and the binary — I see B (BSS) with Go 1.27.1 through your script and D in an ffi test binary built with Go 1.25.3. Could you word it as "a data symbol (B/D), not T" or similar? Not a blocker.

Approving. Please rebase onto main: #85 is merged, so the PR shrinks to its own commit, and #92 touched ci.yml, CHANGELOG.md and a comment in ffi/callback_amd64.s, so expect small conflicts there. After the rebase your PR also runs the new lint-on-every-target and native arm64/Intel-macOS test jobs.

@kolkov kolkov added status: review In code review priority: high Important for next release labels Oct 15, 2026
@kolkov kolkov added this to the v0.6.5 milestone Oct 15, 2026
ffi/callback.go is built for (linux || darwin || freebsd) && amd64, but
ffi/callback_amd64.s, which holds the 2000-entry trampoline table and
callbackDispatcher, was built only for (linux || darwin) && amd64.

The Go side takes the table's address through a placeholder:

    //go:linkname _callbackTrampoline github.com/go-webgpu/goffi/ffi.callbackTrampoline
    var _callbackTrampoline byte

With the assembly excluded, that one-byte variable becomes the definition
of ffi.callbackTrampoline. Nothing fails to compile or link. On a linked
freebsd/amd64 consumer, `go tool nm` reports

    D github.com/go-webgpu/goffi/ffi.callbackTrampoline

and no callbackDispatcher or callbackWrap at all, where linux/amd64 and
freebsd/arm64 report T for all three. NewCallback therefore returns
addresses computed from a data-segment byte, not code.

The dispatcher is plain System V AMD64 (the same ABI FreeBSD uses) and
enters Go through crosscall2, which internal/fakecgo already provides on
FreeBSD, so the fix is adding freebsd to the constraint.

The existing cross-compile job could not catch this: `go build ./...`
links nothing, and the broken build compiles. scripts/check-callback-
trampolines.sh links a small NewCallback consumer for every target whose
callbacks come from goffi's own assembly (linux, darwin, freebsd x amd64,
arm64) and fails unless the symbol is T. Run against the tree before this
change it reports freebsd/amd64 as 'D'; after it, all six targets pass.
The Cross-Compile job now runs it.

Not verified on a FreeBSD host; the evidence is the symbol table of the
cross-linked binaries.

Refs: go-webgpu#76 (review)
@kolkov
kolkov force-pushed the feature/freebsd-amd64-callback-asm branch from 55f9278 to afd2d40 Compare October 16, 2026 11:35
@kolkov

kolkov commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

I rebased this onto current main so it can go into v0.6.5. Your commit is unchanged apart from the conflict resolution: in ci.yml your trampoline check now runs after the FreeBSD/NetBSD step that #92 added, and in CHANGELOG.md your two entries moved to the end of the current [Unreleased] / Fixed list. The assembly and the script are byte-for-byte what you wrote. Thanks again for the fix!

@kolkov
kolkov merged commit 2e6091a into go-webgpu:main Oct 16, 2026
45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch: amd64 x86-64 specific (System V / Win64 ABI) area: callbacks C-to-Go callback trampolines area: ci CI workflows, check scripts, branch protection platform: freebsd FreeBSD-specific priority: high Important for next release status: review In code review type: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants