sbcl.sbcl/tests/subr.sh
SANO,Masatoshi aa0fa1c56e Add ARM64 Windows platform support
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>
2026-02-12 21:44:09 +03:00

194 lines
6.6 KiB
Bash

# To be sourced by shell scripts in the test suite.
# This software is part of the SBCL system. See the README file for
# more information.
#
# While most of SBCL is derived from the CMU CL system, the test
# files (like this one) were written from scratch after the fork
# from CMU CL.
#
# This software is in the public domain and is provided with
# absolutely no warranty. See the COPYING and CREDITS files for
# more information.
# Before sbcl-1.0.13 or so, we set up some environment variables to
# the absolute (POSIX) pathname naming the SBCL runtime, core, and
# home; but this runs afoul of the Bourne shell's repeated
# tokenization of its inputs, so now we use some shell functions.
. ../sbcl-pwd.sh
sbcl_pwd
# Make the shell bomb out whenever an unset shell variable is used.
# Note that scripts may toggle this if necessary.
set -u
# Initialize variables.
set -a # export all variables at assignment-time.
# Note: any script that uses the variables that name files should
# quote them (with double quotes), to contend with whitespace.
SBCL_HOME="${TEST_SBCL_HOME:-$SBCL_PWD/../obj/sbcl-home}"
SBCL_CORE="${TEST_SBCL_CORE:-$SBCL_PWD/../output/sbcl.core}"
# On Windows, the runtime is sbcl.exe; on Unix, it's sbcl
if [ -f "$SBCL_PWD/../src/runtime/sbcl.exe" ]; then
SBCL_RUNTIME="${TEST_SBCL_RUNTIME:-$SBCL_PWD/../src/runtime/sbcl.exe}"
else
SBCL_RUNTIME="${TEST_SBCL_RUNTIME:-$SBCL_PWD/../src/runtime/sbcl}"
fi
SBCL_ARGS="${TEST_SBCL_ARGS:---disable-ldb --noinform --no-sysinit --no-userinit --noprint --disable-debugger}"
# Tests should probably not care about their own name.
script_basename=`basename $0`
# Scripts that use this variable should quote it.
TEST_FILESTEM=`basename "${script_basename}" | sed -e 's/\.sh$//' -e 's/\./-/g'`
TEST_DIRECTORY="${SBCL_PWD}/${TEST_FILESTEM}-$$"
export TEST_DIRECTORY
# "Ten four" is the closest numerical slang I can find to "OK", so
# it's the Unix status value that we expect from a successful test.
# (Of course, zero is the usual success value, but we don't want to
# use that because SBCL returns that by default, so we might think
# we passed a test when in fact some error caused us to exit SBCL
# in a weird unexpected way. In contrast, 104 is unlikely to be
# returned unless we exit through the intended explicit "test
# successful" path.
EXIT_TEST_WIN=104
# Shell scripts in this test suite also return 104, so we need a
# convention for distinguishing successful execution of SBCL in one of
# our scripts.
EXIT_LISP_WIN=52
# Any test that exits with status 1 is an explicit failure.
EXIT_LOSE=1
LANG=C
LC_ALL=C
set +a
run_sbcl () (
set -u
if [ $# -gt 0 ]; then
"$SBCL_RUNTIME" --lose-on-corruption --core "$SBCL_CORE" $SBCL_ARGS --eval "(setf sb-ext:*evaluator-mode* :${TEST_SBCL_EVALUATOR_MODE:-compile})" "$@"
else
"$SBCL_RUNTIME" --lose-on-corruption --core "$SBCL_CORE" $SBCL_ARGS --eval "(setf sb-ext:*evaluator-mode* :${TEST_SBCL_EVALUATOR_MODE:-compile})"
fi
)
run_sbcl_with_args () (
set -u
"$SBCL_RUNTIME" --lose-on-corruption --core "$SBCL_CORE" "$@"
)
run_sbcl_with_core () (
set -u
core="$1"
shift
if [ $# -gt 0 ]; then
"$SBCL_RUNTIME" --lose-on-corruption --core "$core" "$@"
else
"$SBCL_RUNTIME" --lose-on-corruption --core "$core" $SBCL_ARGS --eval "(setf sb-ext:*evaluator-mode* :${TEST_SBCL_EVALUATOR_MODE:-compile})"
fi
)
# Most tests that run an SBCL have to check whether the child's exit
# status. Our convention is that SBCL exits with status
# $EXIT_LISP_WIN to indicate a successful run; but some tests can't do
# this (e.g., ones that end in S-L-A-D), or need to indicate some
# other ways of succeeding. So this routine takes a test name, the
# exit status of the child, and then an arbitrary number extra
# arguments that will be treated as status-code/message pairs for
# unusual successful ways for the inferior SBCL to exit. If the exit
# code of the SBCL isn't found in the status-codes, the calling script
# will exit with a failure code.
check_status_maybe_lose () {
testname=$1
status=$2
lose=1
if [ $status = $EXIT_LISP_WIN ]; then
echo "test $testname ok"
lose=0
else
shift; shift;
while [ $# -gt 0 ]; do
if [ $status = $1 ]; then
shift;
echo "test $testname ok $1"
lose=0
break
fi
shift; shift
done
fi
if [ $lose = 1 ]; then
echo "test $testname failed: $status"
exit $EXIT_LOSE
fi
unset lose
unset status
unset testname
}
# Picking an output dir is delayed until actually needed.
# In particular we can't read "$SBCL_SOFTWARE_TYPE" until after test-util
# assigns it into the environment, but this script is also sourced
# by run-tests.sh itself, which means that test-util hasn't done its thing.
#
pick_random_output_dir() {
# Avoid writing into the source tree as much as possible.
if [ "$SBCL_SOFTWARE_TYPE" != OpenBSD ]; then
# Don't try to run sbcl from /tmp on openbsd as it's unlikely to be
# mounted with wxallowed
# If a test doesn't create an executable core, it would work to use /tmp,
# but this utility is unaware of the intent of each test.
# This means that some tests might flake our, and/or leave junk in your tree.
base_dir=${TMPDIR:-/tmp}
else
base_dir="$SBCL_PWD"
fi
TEST_DIRECTORY="${base_dir}/${TEST_FILESTEM}-$$"
}
# Not every test needs to touch the file system, but enough do to have
# them consistently do so in subdirectories. Note that such tests
# should not change their exit action, or do so only very carefully.
use_test_subdirectory () { # not a "subdirectory" now, but don't feel like renaming
if test -d "$TEST_DIRECTORY"
then
cleanup_test_subdirectory
fi
pick_random_output_dir
mkdir "$TEST_DIRECTORY"
cd "$TEST_DIRECTORY"
trap "cleanup_test_subdirectory" EXIT
}
# FIXME: Is it really true that a test must alter the source tree? How pathetic.
# In particular, failures can occur in the :READDIR/DIRENT-NAME test of sb-posix
# when using parallel-exec, because "run-sbcl-test-NNNN" randomly appears
# in either the SB-POSIX:READDIR call or CL:DIRECTORY but not both.
use_test_subdirectory_in_source_tree () { # DON'T USE THIS!
if test -d "$TEST_DIRECTORY"
then
cleanup_test_subdirectory
fi
mkdir "$TEST_DIRECTORY"
cd "$TEST_DIRECTORY"
trap "cleanup_test_subdirectory" EXIT
}
# Do the above but without changing the current directory
create_test_subdirectory () {
if test -d "$TEST_DIRECTORY"
then
cleanup_test_subdirectory
fi
pick_random_output_dir
mkdir "$TEST_DIRECTORY"
trap "cleanup_test_subdirectory" EXIT
}
cleanup_test_subdirectory () {
cd "$SBCL_PWD"
( set -f; rm -r "$TEST_DIRECTORY" )
}