master: x86-64, struct-by-value: coordinate arglist transforms

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  6a39892471ffe36d723cd07928bff3182bfd8ac5 (commit)
      from  6fff197f3513ef36f05bb919bd1861947434bdf8 (commit)

- Log -----------------------------------------------------------------
commit 6a39892471ffe36d723cd07928bff3182bfd8ac5
Author: Jesse Bouwman <[email protected]>
Date:   Mon Apr 27 14:05:06 2026 -0700

    x86-64, struct-by-value: coordinate arglist transforms
---
 src/compiler/x86-64/c-call.lisp         |  6 ++++++
 tests/alien-struct-by-value.c           | 15 +++++++++++++++
 tests/alien-struct-by-value.impure.lisp | 19 +++++++++++++++++++
 3 files changed, 40 insertions(+)

diff --git a/src/compiler/x86-64/c-call.lisp b/src/compiler/x86-64/c-call.lisp
index 7d20f433d..ef603ab17 100644
--- a/src/compiler/x86-64/c-call.lisp
+++ b/src/compiler/x86-64/c-call.lisp
@@ -520,6 +520,12 @@ Floats are passed in integer registers."
             (and (alien-integer-type-p result-type)
                  (> (sb-alien::alien-integer-type-bits result-type) 64)))
         (collect ((new-args) (lambda-vars) (new-arg-types))
+          ;; When the OUTER struct-return path injected a hidden
+          ;; buffer SAP as the first arg, thread it through.
+          (let ((buf-var (and large-struct-return-p (gensym "BUF"))))
+            (when buf-var
+              (lambda-vars buf-var)
+              (new-args buf-var)))
           (dolist (type arg-types)
             (let ((arg (gensym)))
               (lambda-vars arg)
diff --git a/tests/alien-struct-by-value.c b/tests/alien-struct-by-value.c
index a77cd7136..28f4de700 100644
--- a/tests/alien-struct-by-value.c
+++ b/tests/alien-struct-by-value.c
@@ -427,3 +427,18 @@ struct nest_di nest_di_make(double d, int i) {
   struct nest_di s; s.inner.d = d; s.inner.i = i; return s;
 }
 double nest_di_sum(struct nest_di s) { return s.inner.d + (double)s.inner.i; }
+
+/*
+ * Large struct return + __int128 argument.  Exercise interaction of
+ * hidden sret pointer (injected by the struct-return IR1 transform)
+ * and int128 splitting (rewrites the arg list): these must agree on
+ * whether the buffer arg is present.
+ */
+struct three_u64 { unsigned long long a, b, c; };
+struct three_u64 three_u64_from_u128(__uint128_t x) {
+  struct three_u64 s;
+  s.a = (unsigned long long) x;
+  s.b = (unsigned long long) (x >> 64);
+  s.c = s.a ^ s.b;
+  return s;
+}
diff --git a/tests/alien-struct-by-value.impure.lisp b/tests/alien-struct-by-value.impure.lisp
index c845d43e2..ae685f940 100644
--- a/tests/alien-struct-by-value.impure.lisp
+++ b/tests/alien-struct-by-value.impure.lisp
@@ -786,3 +786,22 @@
     (assert (= (slot (slot s 'inner) 'd) 3.5d0))
     (assert (= (slot (slot s 'inner) 'i) 7))
     (assert (= (nest-di-sum s) 10.5d0))))
+
+;;; Large struct return combined with an __int128 argument: the
+;;; struct-return IR1 transform injects a hidden sret-pointer arg
+;;; ahead of the original args; the int128-splitting transform
+;;; rewrites the arg list.
+#+x86-64
+(with-test (:name :struct-by-value-large-return-with-int128-arg)
+  (define-alien-routine three-u64-from-u128 (struct nil
+                                                    (a (unsigned 64))
+                                                    (b (unsigned 64))
+                                                    (c (unsigned 64)))
+    (x (unsigned 128)))
+  (let* ((low #x0123456789abcdef)
+         (high #xfedcba9876543210)
+         (x (logior low (ash high 64)))
+         (s (three-u64-from-u128 x)))
+    (assert (= (slot s 'a) low))
+    (assert (= (slot s 'b) high))
+    (assert (= (slot s 'c) (logxor low high)))))

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


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.