0.9.6.26: preserve stack alignment in callbacks on ppc
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 6 Nov 2005 13:25:47 +0000 (13:25 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 6 Nov 2005 13:25:47 +0000 (13:25 +0000)
 * Merge patch from Cyrus Harmon (sbcl-devel 2005-11-04), plus slightly
   twisted tests.

 Note: This has been tested on ppc/darwin and x86/linux, but the new tests
 are active on all platforms -- using alignment requirements I've essentially
 guessed.

src/compiler/ppc/c-call.lisp
tests/foreign-stack-alignment.impure.lisp [new file with mode: 0644]
tests/stack-alignment-offset.c [new file with mode: 0644]
version.lisp-expr

index 7426c93..8f5820f 100644 (file)
                  ;; FIXME: magic constant, and probably n-args-bytes
                  (args-size (* 3 n-word-bytes))
                  ;; FIXME: n-frame-bytes?
-                 (frame-size
-                  (+ n-foreign-linkage-area-bytes n-return-area-bytes args-size)))
+                 (frame-size (logandc2 (+ n-foreign-linkage-area-bytes
+                                          n-return-area-bytes
+                                          args-size
+                                          +stack-alignment-bytes+)
+                                       +stack-alignment-bytes+)))
             (destructuring-bind (sp r0 arg1 arg2 arg3 arg4)
                 (mapcar #'make-gpr '(1 0 3 4 5 6))
               (flet ((load-address-into (reg addr)
diff --git a/tests/foreign-stack-alignment.impure.lisp b/tests/foreign-stack-alignment.impure.lisp
new file mode 100644 (file)
index 0000000..2ed55a3
--- /dev/null
@@ -0,0 +1,69 @@
+;;;; Testing the stack alignment of foreign calls. Uses stack-alignment-offset.c.
+
+;;;; 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.
+
+(use-package :sb-alien)
+
+;;; Callbacks are not part of the exported interface yet -- when they are this can
+;;; go away.
+(import 'sb-alien::alien-lambda)
+
+(defun run (program &rest arguments)
+  (let* ((proc nil)
+         (output
+          (with-output-to-string (s)
+            (setf proc (run-program program arguments
+                                    :search (not (eql #\. (char program 0)))
+                                    :output s)))))
+    (unless (zerop (process-exit-code proc))
+      (error "Bad exit code: ~S~%Output:~% ~S"
+             (process-exit-code proc)
+             output))
+    output))
+
+(defvar *required-alignment*
+  #+(and ppc darwin) 16
+  #+(and ppc linux) 16
+  #+(or mips x86-64) 8
+  #+x86 4
+  #-(or x86 x86-64 mips (and ppc (or darwin linux))) (error "Unknown platform"))
+
+;;;; Build the offset-tool as regular excutable, and run it with
+;;;; fork/exec, so that no lisp is on the stack. This is our known-good
+;;;; number.
+
+(run "cc" "stack-alignment-offset.c" "-o" "stack-alignment-offset")
+
+(defparameter *good-offset*
+  (parse-integer (run "./stack-alignment-offset"
+                      (princ-to-string *required-alignment*))))
+
+;;;; Build the tool again, this time as a shared object, and load it
+
+(run "cc" "stack-alignment-offset.c"
+     #+darwin "-bundle" #-darwin "-shared"
+     "-o" "stack-alignment-offset.so")
+
+(load-shared-object "stack-alignment-offset.so")
+
+(define-alien-routine stack-alignment-offset int (alignment int))
+(define-alien-routine trampoline int (callback (function int)))
+
+;;;; Now get the offset by calling from lisp, first with a regular foreign function
+;;;; call, then with an intervening callback.
+
+(assert (= *good-offset* (stack-alignment-offset *required-alignment*)))
+
+(assert (= *good-offset* (trampoline (alien-lambda int ()
+                                       (stack-alignment-offset *required-alignment*)))))
+
+;;;; success!
diff --git a/tests/stack-alignment-offset.c b/tests/stack-alignment-offset.c
new file mode 100644 (file)
index 0000000..fe0ad9c
--- /dev/null
@@ -0,0 +1,56 @@
+/* Compiled and run by foreign-stack-alignment.lisp
+ *
+ * stack_alignment_offset(int) returns the offset of the first argument from a
+ * given alignment. run (1) from main, to obtain the good value with no
+ * lisp involved (2) from lisp both with and without callbacks to see that
+ * we have not messed the alignment.
+ *
+ * trampoline(int(*)()) is here so that we can get callbacks on the
+ * stack too.
+ */
+
+/* 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* <nikodemus> bwahahahaaa!
+ * <Xophe> oh dear.  He's finally flipped
+ * <lisppaste> nikodemus pasted "stack_alignment_offset" at
+ *             http://paste.lisp.org/display/13231
+ * <Xophe> heh
+ * <Xophe> along with a big / * This code is really twisted * / comment :-)
+ * <antifuchs> gods.
+ */
+extern int
+stack_alignment_offset (int alignment)
+{
+    return ((unsigned int)&alignment) % alignment;
+}
+
+extern int
+trampoline (int(*callback)())
+{
+    return callback();
+}
+
+int main (int argc, char** argv)
+{
+    if (argc != 2) {
+        printf("wrong number of arguments: %d\n", argc-1);
+        return 1;
+    }
+
+    printf("%d\n", stack_alignment_offset(atoi(argv[1])));
+    return 0;
+}
index 3a322c0..5e8847e 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.9.6.25"
+"0.9.6.26"