Add complete ARM64 Windows (AArch64 WoA) support to SBCL. This
enables building and running SBCL natively on Windows 11 ARM devices.
Key design decisions:
- x18 register reserved as TEB pointer (Windows ARM64 ABI requirement),
matching the existing Darwin reservation
- Safepoint GC with fake_foreign_function_call to save register context
for precise stack scanning (ARM64 uses separate C and control stacks)
- VEH (Vectored Exception Handling) for ARM64, decoding BRK instructions
which Windows reports as EXCEPTION_ILLEGAL_INSTRUCTION
- sb_udivmodti4 takes hi/lo split arguments to avoid __uint128_t ABI
issues on LLP64 where unsigned long is 32 bits
- FP exception traps disabled (ARM64 Windows does not deliver FP
exceptions even with FPCR trap bits set)
- Dynamic space pages committed on demand (Windows reserves but does
not commit the full dynamic space upfront)
New files:
- src/runtime/Config.arm64-win32: Build configuration
- src/runtime/arm64-win32-os.c: OS layer (VEH, context access, FP)
- src/runtime/arm64-win32-os.h: Platform header
- .github/workflows/windows-arm64.yml: CI workflow
Modified files grouped by subsystem:
Runtime (ARM64-specific):
- arm64-arch.c: Windows memory APIs, LLP64-safe pointer storage,
sb_udivmodti4 split-argument ABI, static space NIL header guard
- arm64-assem.S: Windows calling conventions for call_into_lisp and
call_into_c, TlsGetValue for thread pointer, x18 reservation
Runtime (Windows general):
- win32-os.c: ARM64 safepoint page handling, BRK exception decode,
ARM64 VEH, dynamic space page commit, ARM64 debug printing
Compiler:
- vm.lisp: Reserve x18 on Windows (matching Darwin)
- c-call.lisp: Don't zero control-stack-pointer on Windows (not FFCA)
- parms.lisp: Address space layout for Windows ARM64
- tramps.lisp: Save CSP to thread for GC, don't zero CSP on Windows
- genesis.lisp: GC_SAFEPOINT_PAGE_ADDR for non-x86-64 platforms
- parms.lisp (generic): Update safepoint space comment
- debug-int.lisp: NFP handling for ARM64 Windows
- float-trap.lisp: Disable FP traps on ARM64 Windows
- coreparse.c: ARM64 guard for TEXT_SPACE_START assignment
Build system:
- make-config.sh: ARM64 Windows detection and feature flags
- make-windows-installer.sh: ARM64 architecture in installer
CI:
- linux-arm64.yml, mac.yml: Robustness fixes for repo naming
- windows-arm64.yml: New workflow for ARM64 Windows builds
Tests:
- subr.sh: Auto-detect sbcl.exe on Windows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CDPATH isn't supposed to be exported, but it can be; and POSIX says cd
should always use PWD after searching CDPATH, but some recent OS
releases still ship versions of /bin/sh that don't. So let's have our
build scripts continue to be explicit about where they're cd'ing to.
Deprecate QUIT. It occupies an uncomfortable niche between processes
and threads, and doesn't actually do what it says on the tin unless
you call it from the main thread.
SIGTERM now uses EXIT, and doesn't depend on sessions.
WITH-DEADLINE (:SECONDS NIL :OVERRIDE T) can now be used to ignore
deadlines.
JOIN-THREAD on the main thread now blocks indefinitely instead of
claiming the thread did not exit normally.
New functions:
* SB-EXT:EXIT. Always exits the process. Takes keywords :CODE,
:ABORT, and :TIMEOUT. Code is the exit status. Abort controls if
the exit is clean (unwind, exit-hooks, terminate other threads) or
dirty. Timeout controls how long to wait for other threads to
finish.
* SB-THREAD:RETURN-FROM-THREAD. Normal termination for current
thread -- equivalent to return from the thread function with the
specified values. Takes keyword :ALLOW-EXIT, which determines if
returning from the main thread is an error, or equivalent to
calling EXIT :CODE 0.
* SB-THREAD:ABORT-THREAD. Abnormal termination for current thread --
equivalent to invoking the initial ABORT restart estabilished by
MAKE-THREAD (previously known as TERMINATE-THREAD, but ANSI
recommends there to always be an ABORT restart.) Takes keyword
:ALLOW-EXIT, which determines if aborting the main thread is an
error, or equivalent to calling EXIT :CODE 1.
* SB-THREAD:MAIN-THREAD-P. Let's you determine if a given thread is
the main thread of the process. This is important for some
functions on some operating systems -- and RETURN-FROM-THREAD and
ABORT-THREAD also need it.
* SB-THREAD:MAIN-THREAD. Returns the main thread object. Convenient
for when you need to eg. load a foreign library in the main
thread.
* Added "free software & no warranty" summary to top of COPYING.
* tools-for-build/rtf.lisp turns COPYING into License.rtf needed
for the installer.
* tools-for-build/wxs.lisp generates the XML from which
the installer is built.
* refactor good-for-lisp pathname logic from make-target-contrib.sh
to sbcl-pwd.sh.
* make-windows-installer.sh builds sbcl.msi into output/,
assuming WiX (2.0) is installed in $PROGRAMFILES/WiX or
$WIX_PATH.
The installer installs sbcl.exe, sbcl.core, and contribs
into $PROGRAMFILES/Steel Bank Common Lisp/<sbcl-version>/
by default, though the location is configurable.
.lisp and .fasl files are associated with the installed
SBCL, action being to start SBCL and load the file.
The installation directory is added to PATH.
SBCL_HOME is set to the installation directory.
A shortcut is added to the start-menu. The shortcut refers
to the core explicitly, and will continue to work even if
a newer SBCL is installed.