master: arm64, struct-by-value: look at the stack when running out of GPRs

stassats via Sbcl-commits <[email protected]>
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  29a23fdce1b09fded20b4c4aba153839c2a4d4d8 (commit)
      from  4b3abf2f8c99f6a4a13c41b2b57b3a0ed326549e (commit)

- Log -----------------------------------------------------------------
commit 29a23fdce1b09fded20b4c4aba153839c2a4d4d8
Author: Stas Boukarev <[email protected]>
Date:   Thu Apr 23 07:56:43 2026 +0300

    arm64, struct-by-value: look at the stack when running out of GPRs
---
 src/compiler/arm64/c-call.lisp | 37 +++++++++++++++++++++++++++----------
 1 file changed, 27 insertions(+), 10 deletions(-)

diff --git a/src/compiler/arm64/c-call.lisp b/src/compiler/arm64/c-call.lisp
index 511d5ab33..1dfd30e90 100644
--- a/src/compiler/arm64/c-call.lisp
+++ b/src/compiler/arm64/c-call.lisp
@@ -718,22 +718,39 @@
                        ((multiple-value-bind (hfa-type hfa-count) (hfa-base-type type)
                           (when hfa-type
                             (let ((fp-size (if (eq hfa-type 'single-float) 4 8)))
-                              (dotimes (i hfa-count)
-                                (when (< fp-registers 8)
-                                  (inst str (make-tn fp-registers
-                                                     (if (eq hfa-type 'single-float)
-                                                         'single-reg
-                                                         'double-reg))
-                                        (@ nsp-tn (+ frame-offset (* i fp-size))))
-                                  (incf fp-registers))))
+                              (cond ((<= (+ fp-registers hfa-count) 8)
+                                     (dotimes (i hfa-count)
+                                       (inst str (make-tn fp-registers
+                                                          (if (eq hfa-type 'single-float)
+                                                              'single-reg
+                                                              'double-reg))
+                                             (@ nsp-tn (+ frame-offset (* i fp-size))))
+                                       (incf fp-registers)))
+                                    (t
+                                     (setf fp-registers 8)
+                                     (setf stack-argument-bytes (align-up stack-argument-bytes 8))
+                                     (loop for off below struct-bytes by 8
+                                           for remaining = (- struct-bytes off)
+                                           do (cond ((>= remaining 8)
+                                                     (inst ldr temp-tn (@ nsp-save-tn (+ stack-argument-bytes off)))
+                                                     (inst str temp-tn (@ nsp-tn (+ frame-offset off))))
+                                                    (t
+                                                     (inst ldr (32-bit-reg temp-tn) (@ nsp-save-tn (+ stack-argument-bytes off)))
+                                                     (inst str (32-bit-reg temp-tn) (@ nsp-tn (+ frame-offset off))))))
+                                     (incf stack-argument-bytes (align-up struct-bytes 8)))))
                             t)))
                        ;; Small non-HFA struct (<=16 bytes): passed in GPRs
                        (t
                         (let ((num-regs (ceiling struct-bytes 8)))
                           (dotimes (i num-regs)
                             (let ((gpr (pop gprs)))
-                              (when gpr
-                                (inst str gpr (@ nsp-tn (+ frame-offset (* i 8))))))))))
+                              (cond (gpr
+                                     (inst str gpr (@ nsp-tn (+ frame-offset (* i 8)))))
+                                    (t
+                                     (setf stack-argument-bytes (align-up stack-argument-bytes 8))
+                                     (inst ldr temp-tn (@ nsp-save-tn stack-argument-bytes))
+                                     (inst str temp-tn (@ nsp-tn (+ frame-offset (* i 8))))
+                                     (incf stack-argument-bytes 8))))))))
                      ;; Use word-aligned size for frame offset to match Lisp side
                      (incf frame-offset struct-bytes-aligned)))
                   (t

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.