Skip to content

Conversation

@teamchong
Copy link

Problem

Apple reserves CPU register x18 for TLS on ARM64. When generating AOT code for aarch64 on macOS, LLVM may use x18, causing crashes when the AOT code runs on macOS ARM64 (M1/M2/M3).

Solution

This patch makes three changes to properly handle macOS ARM64:

  1. Detect darwin/macho ABI - When explicit ABI is specified as "darwin" or "macho", use -apple- vendor string
  2. Detect darwin/apple in default triple - When auto-detecting platform, check for "darwin" or "apple" in the triple
  3. Add +reserve-x18 feature - Tell LLVM to reserve x18 register when targeting aarch64 on macOS hosts
#if (defined(__APPLE__) || defined(__MACH__)) && defined(BUILD_TARGET_AARCH64)
    if (is_aarch64) {
        // Append +reserve-x18 to features
    }
#endif

Testing

  • AOT compilation and execution on macOS ARM64 (M1/M2/M3) works correctly
  • No crashes from x18 register conflicts

Related

Apple reserves CPU register x18 for TLS on ARM64. When generating AOT
code for aarch64 on macOS, LLVM may use x18, causing crashes when the
AOT code runs on macOS ARM64 (M1/M2/M3).

This patch:
1. Detects darwin/macho ABI and sets correct vendor string
2. Detects darwin/apple in default triple for platform detection
3. Adds +reserve-x18 to LLVM target features for aarch64 on macOS

The fix only applies when compiling on macOS ARM64 hosts, ensuring
generated AOT code is compatible with Apple's platform requirements.
@lum1n0us
Copy link
Contributor

lum1n0us commented Jan 5, 2026

Thank you for reporting that.

Can you provide a test case to expose or verify the issue? If I understand correctly, macOS-15 with M1 (as mentioned in the GitHub documentation) is a suitable platform, right?

Add a standalone test to verify that the +reserve-x18 LLVM flag is
correctly applied when compiling AOT for macOS ARM64.

On macOS ARM64, x18 is reserved by Apple for TLS (Thread Local Storage).
Without the +reserve-x18 flag, LLVM may generate code that uses x18,
causing random SIGSEGV crashes (~80% crash rate in testing).

The test:
- Creates a WASM module with 24 local variables to stress register allocation
- Compiles to AOT with -O3 optimization (which would use x18 without the fix)
- Runs 1000 iterations to verify no crashes occur
- Only runs on macOS ARM64 (skipped on other platforms)

Test results:
- Without fix: 82/100 crash rate
- With fix: 0/100 crash rate (1000 iterations verified)
@teamchong
Copy link
Author

Thank you for reporting that.

Can you provide a test case to expose or verify the issue? If I understand correctly, macOS-15 with M1 (as mentioned in the GitHub documentation) is a suitable platform, right?

I've added a test case that:

  1. Creates a WASM module that stresses register allocation (24 local variables)
  2. Compiles to AOT with -O3 optimization
  3. Runs 1000 iterations to verify no crashes

Test results on M2 Mac:

  • Without fix: 828/1000 crash rate (SIGSEGV)
  • With fix: 0/1000 crash rate

The test only runs on macOS ARM64 (macos-15 runner) and is skipped on other platforms.

@teamchong teamchong force-pushed the fix-aarch64-macos-x18-reserve branch from 83723ae to 4fd87d8 Compare January 8, 2026 12:23
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.

2 participants