From: Christophe R. <cs...@ca...> - 2005-12-12 11:03:16
|
Richard M Kreuter <kr...@pr...> writes: > (1) I can't get %alien-funcall to work properly for a C function that > takes a 64-bit argument and returns a 64-bit value. Here's what > happens when I tried compiling unix-lseek (off_t is a 64-bit > quantity on NetBSD): I think I know what's going on. See below, for interspersed comments. > --- sbcl/src/code/unix.lisp 2005-10-12 11:12:17.000000000 -0400 > +++ sbcl-netbsd-ppc/src/code/unix.lisp 2005-12-10 20:49:56.000000000 -0500 > @@ -237,9 +237,17 @@ SYSCALL-FORM. Repeat evaluation of SYSCA > " > (declare (type unix-fd fd) > (type (integer 0 2) whence)) > - (let ((result (alien-funcall (extern-alien "lseek" (function off-t int off-t int)) > + (let ((result (alien-funcall (extern-alien "lseek" > + ;; I (RMK) can't make > + ;; %alien-funcall like > + ;; this alien function on > + ;; netbsd/ppc > + #!-(and netbsd ppc) > + (function off-t int off-t int) > + #!+(and netbsd ppc) > + (function int int off-t int)) > fd offset whence))) > - (if (minusp result ) > + (if (minusp result) > (values nil (get-errno)) > (values result 0)))) I think here you've possibly been tripped up by the notation: I had to read this a number of times before I realised what was happening. You've patched the type of lseek from (function off-t int off-t int) to (function int int off-t int); at first, I thought that this was to avoid your "hackaround" from being triggered, but in fact it's nothing of the kind. The first INT there is the return value, not an argument; you've changed the return value size, which explains the error message you're getting in warm init. So... > diff -purN -xCVS -x'*.d' -xcustomize-target-features.lisp sbcl/src/compiler/ppc/c-call.lisp sbcl-netbsd-ppc/src/compiler/ppc/c-call.lisp > --- sbcl/src/compiler/ppc/c-call.lisp 2005-11-06 08:25:50.000000000 -0500 > +++ sbcl-netbsd-ppc/src/compiler/ppc/c-call.lisp 2005-12-10 19:12:35.000000000 -0500 > @@ -238,7 +238,7 @@ > (alien-fun-type-result-type type) > #!+darwin (make-result-state)))))) > > -#!+darwin > +#!+(or darwin netbsd) > (deftransform %alien-funcall ((function type &rest args)) > (aver (sb!c::constant-lvar-p type)) > (let* ((type (sb!c::lvar-value type)) > @@ -262,6 +262,15 @@ > ;; 64-bit long long types are stored in > ;; consecutive locations, most significant word > ;; first (big-endian). > + ;; On NetBSD, 64-bit quantities seem to > + ;; need start in registers NLx, where x is > + ;; even. -- RMK 20051129 > + #!+netbsd > + (when (oddp (length (new-args))) > + (new-args 0) > + (new-arg-types > + (parse-alien-type '(unsigned 32) > + (sb!kernel:make-null-lexenv)))) > (new-args `(ash ,arg -32)) > (new-args `(logand ,arg #xffffffff)) > (if (alien-integer-type-signed type) ... this hackaround for 64-bit arguments is probably correct; however, you need to do a little bit more work: you also need to teach the compiler how to deal with two integer return values. This is done in !DEF-VM-SUPPORT-ROUTINE MAKE-CALL-OUT-TNS and in DEFINE-ALIEN-TYPE-METHOD INTEGER :RESULT-TN, both in c-call.lisp just above the %alien-funcall deftransform. I suspect that basically copying the #!+darwin clauses will make it work. Cheers, Christophe |