Re: Add ARM64 Windows port

Stas Boukarev <[email protected]> Thu, 12 Feb 2026 22:33:09 +0300
Newsgroups gmane.lisp.steel-bank.devel
Message-ID <CAF63=12C+HgpAxd6hRP5MJi_zQcb5NwD3zh2a5=bq6Ndn+JWVg@mail.gmail.com>
I applied everything, but I haven't really reviewed the changes which
only touch windows-arm64, as they are now confined to that.
And I disabled the test suite on github actions, it hangs randomly.

On Thu, Feb 12, 2026 at 6:41 PM Masatoshi SANO <[email protected]> wrote:
>
> Thank you for the review, Stas. All points are valid and have been
> addressed. In particular, the csel removal was a real bug — you were
> right that multiple value returns do not restore CSP.
>
> Here is what changed (incremental patch attached):
>
> > Allocations functions can't trigger a GC, a GC is requested by
> > checking pseudo-atomic-interrupted.
>
> Agreed. The storew saving CSP in the alloc trampoline has been removed.
>
> > Why is the change to newspace_full_scavenge needed, it's not hidden
> > behind safepoint-specific ifdefs. Which test fails without that
> > change?
>
> It is now guarded by:
>   #if defined(LISP_FEATURE_SB_SAFEPOINT) && !defined(LISP_FEATURE_C_STACK_IS_CONTROL_STACK)
>
> This is needed for gethash-concurrency.pure.lisp on ARM64 with
> safepoints. Pinned from_space objects have their slots scavenged by
> neither scavenge_root_gens (requires gen >= from) nor the newspace scan
> (requires gen == new_space). On conservative platforms this is masked
> because stack scanning pins transitively reachable objects, but on
> precise platforms (ARM64) pinned objects can reference non-pinned
> from_space objects that must be explicitly transported.
>
> This is in patch 4/5, which can be dropped entirely if a different
> approach is preferred.
>
> > Then this should be conditioned at compile time.
>
> Fixed. Now uses #ifndef LISP_FEATURE_ARM64 instead of a runtime check.
>
> > #+sb-thread #-win32 is not a good way to combine conditionals.
>
> Fixed to #+(and sb-thread (not win32)).
>
> > This change is suspicious. Why is reg_CSP suddenly growing downward?
>
> The call_into_c changes are now confined behind #ifdef LISP_FEATURE_WIN32,
> with the original code path completely untouched for other platforms.
>
> On Windows ARM64 with safepoints, thread->control_stack_pointer cannot
> be zeroed to signal "in Lisp" state (it always holds the actual stack
> extent for GC scanning). So call_into_c needs to save/restore the
> previous thread CFP/CSP around the C call. The current implementation
> uses pre-decrement stores for this.
>
> > And multiple value returns certainly do not restore CSP.
>
> You are right. The csel removal in call_into_lisp was a bug in our
> patch. It has been restored unconditionally — the line is now identical
> to master.
>
> > Basically, don't make any changes to the existing code without tests,
> > confine them behind #ifdefs / #+.
>
> Agreed. All changes to existing code are now behind platform-specific
> guards (#ifdef LISP_FEATURE_WIN32, #-win32, or the safepoint guard).
> The non-Windows code paths are unchanged from master.
>
> Test results on Windows 11 ARM (Snapdragon) with this patch applied:
>   Success: 4036, Expected-failure: 20, Unexpected-failure: 5
>   All 5 unexpected failures are pre-existing (FP denormals, weak hash
>   table, sleep/safepoint), no new regressions.
>
> On Thu, Feb 12, 2026 at 3:38 PM Stas Boukarev <[email protected]> wrote:
>>
>> >                       ;; Update thread->control_stack_pointer to include the saved
>> >                      ;; Lisp registers so that scavenge_control_stack scans them
>> >                      ;; if GC is triggered by the C allocation function.
>>
>> Allocations functions can't trigger a GC, a GC is requested by
>> checking pseudo-atomic-interrupted.
>>
>> Why is the change to newspace_full_scavenge needed, it's not hidden
>> behind safepoint-specific ifdefs. Which test fails without that
>> change?
>>
>> >      // Unprotect the in-use ranges. Any page could be written during scavenge
>> >      // On some platforms (e.g., ARM64), fixedobj space may be disabled
>> >      // (FIXEDOBJ_SPACE_START=0, size=0), so skip the protection change.
>>
>> Then this should be conditioned at compile time.
>>
>> #+sb-thread #-win32 is not a good way to combine conditionals.
>>
>>
>>          // Build a Lisp stack frame.
>> -        // Can store two values above the stack pointer, interrupts
>> ignore them.
>> -        stp     reg_CFP, reg_LR, [reg_CSP]
>> -        add     reg_R10, reg_CSP, #2*8
>> +        // Save the current thread structure CFP/CSP first, then our
>> own CFP/LR.
>> +#ifdef LISP_FEATURE_SB_THREAD
>> + ldp     x3, x4, [reg_THREAD, THREAD_CONTROL_FRAME_POINTER_OFFSET]
>> // Load thread CFP/CSP
>> + stp     x3, x4, [reg_CSP, #-16]!  // Push thread CFP/CSP onto stack, CSP -= 16
>> +#endif
>> +        stp     reg_CFP, reg_LR, [reg_CSP, #-16]!  // Push our
>> CFP/LR, CSP -= 16
>> +        add     reg_R10, reg_CSP, #32  // R10 = original CSP (before
>> both pushes)
>>          mov     reg_LEXENV, reg_LR
>>
>> This change is suspicious. Why is reg_CSP suddenly growing downward?
>> And multiple value returns certainly do not restore CSP.
>>
>> Basically, don't make any changes to the existing code without tests,
>> confine them behind #ifdefs / #+.
>>
>> On Thu, Feb 12, 2026 at 8:33 AM Masatoshi SANO <[email protected]> wrote:
>> >
>> > This patch series adds ARM64 Windows (AArch64 WoA) support to SBCL.
>> > Built and tested on Windows 11 ARM using MSYS2 clangarm64 toolchain,
>> > cross-compiled from x86-64 Windows SBCL.
>> >
>> > Most tests pass.  Known failures:
>> >
>> > - gethash-concurrency.pure.lisp: ~80% pass rate.  Patch 4/5 adds
>> >   defensive workarounds but the root cause is likely ARM64 weak
>> >   memory ordering interacting with the hash table high-water-mark.
>> >   Patch 4/5 can be dropped if a different approach is preferred.
>> >
>> > - Floating-point denormal tests (pre-existing on ARM64)
>> >
>> > - sleepytests.pure.lisp hangs (safepoint interrupt delivery during
>> >   sleep, pre-existing on Windows safepoint builds)
>> >
>> > The patches are structured as follows:
>> >
>> >   1/5  align.h LLP64 truncation fix (Windows 64-bit general)
>> >   2/5  LLP64 type fixes and general bugs found during porting
>> >   3/5  GC fix for ARM64 safepoint builds with precise stack scanning
>> >   4/5  Defensive GC validation for concurrent hash table operations
>> >        (optional -- see above)
>> >   5/5  ARM64 Windows platform support
>> >
>> > Patches 1-2 fix bugs that affect existing platforms (Windows x86-64,
>> > or all platforms).  Patch 3 fixes a GC crash specific to ARM64
>> > safepoint builds with precise scanning (!C_STACK_IS_CONTROL_STACK).
>> > Patch 5 is the main platform port.
>> >
>> > _______________________________________________
>> > Sbcl-devel mailing list
>> > [email protected]
>> > https://lists.sourceforge.net/lists/listinfo/sbcl-devel


_______________________________________________
Sbcl-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-devel