purego: properly handle 64-bit integers on 32-bit arm - #491
Conversation
83608f6 to
41c72af
Compare
There was a problem hiding this comment.
Pull request overview
This PR targets ARM 32-bit ABI (AAPCS) correctness in purego, specifically ensuring 64-bit integer arguments are aligned/placed correctly and 64-bit return values are reconstructed correctly for both Go→C calls and C→Go callbacks.
Changes:
- Add ARM32-specific padding/alignment handling for 64-bit integer arguments during marshaling and callback argument decoding.
- Fix 64-bit return handling for calls and callbacks on 32-bit platforms (including ARM assembly trampoline support).
- Add ABI regression tests (C helpers + Go test cases) for previously failing ARM32 int64 patterns.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| testdata/abitest/abi_test.c | Adds C helpers to exercise ARM32 int64 alignment cases. |
| syscall_unix.go | Updates callback argument decoding to account for ARM32 int64 alignment and writes 64-bit callback results via helpers. |
| syscall_stackargs_s390x.go | Adds callbackArgs helpers for 64-bit results (arch-specific callbackArgs layout). |
| syscall_stackargs_ppc64le.go | Adds callbackArgs helpers for 64-bit results (arch-specific callbackArgs layout). |
| syscall_notstackargs.go | Adds 64-bit result helpers that split into two uintptrs on 32-bit platforms. |
| sys_unix_arm.s | Ensures callback trampoline returns both low/high words for 64-bit results via R0/R1. |
| func.go | Implements ARM32 padding logic for 64-bit args/returns and updates argument counting/validation. |
| func_test.go | Adds Go-side ABI tests that call the new C helpers and validate results. |
Suppressed comments (1)
func.go:187
- In the float case,
usesSlotsis also derived fromty.Size()and uses truncating division, which becomes 0 for float32 on 64-bit platforms and miscounts float64 on 32-bit ARM (where it consumes 2 slots). This can cause the argument-limit guard to be wrong. ComputeusesSlotsfromarg.Size()with ceil-division and advancefloatsbyusesSlotswhen the value stays in float registers.
case reflect.Float32, reflect.Float64:
usesSlots := int(ty.Size() / unsafe.Sizeof(uintptr(0)))
if isARMPaddingNeeded(ty, floats+stack) {
usesSlots++
}
if floats < floatArgRegs {
floats++
} else {
stack += usesSlots
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
697f634 to
c147207
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Suppressed comments (1)
syscall_stackargs_s390x.go:38
setInt64Result/setUint64Resultare duplicated across multiple arch files (e.g., s390x, ppc64le, and the generic notstackargs implementation). If the behavior is identical for all 64-bituintptrplatforms, consider factoring these into a shared file with an appropriate build tag (and keeping only the 32-bit word-splitting logic in the 32-bit build) to reduce repetition and the chance of future divergence.
func (c *callbackArgs) setInt64Result(result int64) {
c.result[0] = uintptr(result)
}
func (c *callbackArgs) setUint64Result(result uint64) {
c.result[0] = uintptr(result)
}
1. Obey 8-byte alignment on stack and even-register placement required by AAPCS. 2. Use two registers (R0, R1) to make function return value. This will work for '386' architecture too. 3. Add test cases. Co-authored-by: Hirador <63920290+Hirador@users.noreply.github.com>
|
Is this change mergeable now? I cannot start CI tests |
|
@hajimehoshi yes, tests can be started |
|
Is this PR really based on the latest main branch? |
|
@hajimehoshi should be. I'll try to rebase and push |

What issue is this addressing?
Closes #489
What type of issue is this addressing?
bug
What this PR does | solves
This PR adds handling of 64-bit arguments on 32-bit ARM cpus according to AAPCS requirements. Exact points:
Also it fixes handling of 64-bit return values for calls and callbacks on 32-bit platforms. Necessary assembly code is already present on 386 and I've added missing parts on arm.
Verification: