From: Nikodemus S. <de...@us...> - 2005-11-06 13:26:02
|
Update of /cvsroot/sbcl/sbcl/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26445/tests Added Files: foreign-stack-alignment.impure.lisp stack-alignment-offset.c Log Message: 0.9.6.26: preserve stack alignment in callbacks on ppc * 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. --- NEW FILE: foreign-stack-alignment.impure.lisp --- ;;;; 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! --- NEW FILE: stack-alignment-offset.c --- /* 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; } |