Skip to content

Fix stack-passed arguments on Darwin (AArch64)#5000

Open
flylai wants to merge 1 commit into
bytecodealliance:mainfrom
flylai:fix_fn_call
Open

Fix stack-passed arguments on Darwin (AArch64)#5000
flylai wants to merge 1 commit into
bytecodealliance:mainfrom
flylai:fix_fn_call

Conversation

@flylai

@flylai flylai commented Jul 19, 2026

Copy link
Copy Markdown

Summary

Fixes #4892.

On AArch64, Darwin uses a slightly different ABI from Linux for stack-passed arguments. In particular, Darwin sizes stack slots according to the actual argument size instead of always allocating 8-byte slots.

According to LLVM:
https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/AArch64/AArch64CallingConvention.td#L365-L368

// Darwin uses a calling convention which differs in only two ways
// from the standard one at this level:
//     + i128s (i.e. split i64s) don't need even registers.
//     + Stack slots are sized as needed rather than being at least 64-bit.

Linux ABI

When the number of function arguments exceeds the available argument registers, the remaining arguments are passed on the stack. Each stack-passed argument occupies an 8-byte stack slot, even for 32-bit values:

+-----------------------------------+ <--- sp
|   s0 (i32) [occupies 4 bytes]     | \
|   Padding  [4 bytes]              |  }-- 8-byte stack slot
+-----------------------------------+ <--- sp + 8
|   s1 (i32) [occupies 4 bytes]     | \
|   Padding  [4 bytes]              |  }-- 8-byte stack slot
+-----------------------------------+ <--- sp + 16
|   s2 (i64) [occupies 8 bytes]     | \
|                                   |  }-- 8-byte stack slot
+-----------------------------------+ <--- sp + 24

Darwin ABI

Darwin sizes stack slots according to the actual argument size, allowing adjacent 32-bit arguments to be packed without unnecessary padding:

+-----------------+-----------------+ <--- sp
|  s0 (i32) [4B]  |  s1 (i32) [4B]  |
+-----------------+-----------------+ <--- sp + 8
|  s2 (i64) [8B]                    |
|                                   |
+-----------------------------------+ <--- sp + 16

Test Results

before fix:

============> run test-invoke-native
=========================================
Starting Native Invoke Tests...
=========================================
Running run_test_i32_overflow...
  FAIL: line 374: expected 108, got 0
  FAIL: line 374: expected 109, got 108
  FAIL: line 374: expected 110, got 0
RESULT: FAIL

Running run_test_i64_overflow...
RESULT: PASS

Running run_test_i32_i32_i64_on_stack...
  FAIL: line 406: expected 308, got 0
  FAIL: line 408: expected 1234605616436508552, got 308
RESULT: FAIL

Running run_test_f32_overflow...
  FAIL: line 423: expected 409.000000, got 0.000000
  FAIL: line 423: expected 410.000000, got 409.000000
  FAIL: line 423: expected 411.000000, got 0.000000
RESULT: FAIL

Running run_test_f64_overflow...
RESULT: PASS

Running run_test_f32_f32_f64_on_stack...
  FAIL: line 457: expected 609.000000, got 0.000000
  FAIL: line 458: expected 999.888000, got 0.000000
RESULT: FAIL

Running run_test_mixed_overflow...
  FAIL: line 484: expected 808.000000, got 0.000000
  FAIL: line 485: expected 6148933456521300104, got 1145700352
  FAIL: line 486: expected 12345.678900, got 11982634940256485731267794306136873969953117937862608357662199969694965589666549254097237871668169277440.000000
RESULT: FAIL

Running run_test_i32_i64_alignment...
RESULT: PASS

Running run_test_unaligned_total_stack_size...
  FAIL: line 510: expected 71, got 0
  FAIL: line 511: expected 72, got 71
RESULT: FAIL

Running run_test_float_double_alignment...
RESULT: PASS

Running run_test_return_values...
RESULT: PASS

=========================================
Tests Summary: Passed: 5, Failed: 6
=========================================

after fix:

============> run test-invoke-native
=========================================
Starting Native Invoke Tests...
=========================================
Running run_test_i32_overflow...
RESULT: PASS

Running run_test_i64_overflow...
RESULT: PASS

Running run_test_i32_i32_i64_on_stack...
RESULT: PASS

Running run_test_f32_overflow...
RESULT: PASS

Running run_test_f64_overflow...
RESULT: PASS

Running run_test_f32_f32_f64_on_stack...
RESULT: PASS

Running run_test_mixed_overflow...
RESULT: PASS

Running run_test_i32_i64_alignment...
RESULT: PASS

Running run_test_unaligned_total_stack_size...
RESULT: PASS

Running run_test_float_double_alignment...
RESULT: PASS

Running run_test_return_values...
RESULT: PASS

=========================================
Tests Summary: Passed: 11, Failed: 0
=========================================

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.

InvokeNative fails to pass stack arguments correctly on AARCH64 Darwin

1 participant