Skip to content

purego: properly handle 64-bit integers on 32-bit arm - #491

Open
xakep666 wants to merge 1 commit into
ebitengine:mainfrom
xakep666:arm-alignment
Open

purego: properly handle 64-bit integers on 32-bit arm#491
xakep666 wants to merge 1 commit into
ebitengine:mainfrom
xakep666:arm-alignment

Conversation

@xakep666

@xakep666 xakep666 commented Aug 3, 2026

Copy link
Copy Markdown

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:

C.3 If the argument requires double-word alignment (8-byte), the NCRN is rounded up to the next even register number.
C.7 If the argument required double-word alignment (8-byte), then the NSAA is rounded up to the next double-word address.

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:

@xakep666
xakep666 force-pushed the arm-alignment branch 4 times, most recently from 83608f6 to 41c72af Compare August 3, 2026 19:35
@hajimehoshi
hajimehoshi requested a lite review from Copilot August 5, 2026 06:49

Copilot AI 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.

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, usesSlots is also derived from ty.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. Compute usesSlots from arg.Size() with ceil-division and advance floats by usesSlots when 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.

Comment thread func.go Outdated
Comment thread func.go
Comment thread func_test.go
@xakep666
xakep666 force-pushed the arm-alignment branch 2 times, most recently from a67e1b7 to 697f634 Compare August 5, 2026 20:07
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>
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.

64-bit arguments and return values are not fully supported on 32-bit ARM

2 participants