Raymond Toy pushed to branch master at cmucl / cmucl
Commits:
-
0a35575a
by Raymond Toy at 2023-07-17T15:07:47+00:00
-
5d4b0622
by Raymond Toy at 2023-07-17T15:07:49+00:00
5 changed files:
- bin/run-tests.sh
- src/code/alieneval.lisp
- src/compiler/x86/c-call.lisp
- tests/issues.lisp
- + tests/test-return.c
Changes:
| ... | ... | @@ -47,6 +47,11 @@ function cleanup { |
| 47 | 47 | |
| 48 | 48 | trap cleanup EXIT
|
| 49 | 49 | |
| 50 | +# Compile up the C file that is used for testing alien funcalls to
|
|
| 51 | +# functions that return integer types of different lengths. We use
|
|
| 52 | +# gcc since clang isn't always available.
|
|
| 53 | +(cd tests; gcc -m32 -O3 -c test-return.c)
|
|
| 54 | + |
|
| 50 | 55 | if [ $# -eq 0 ]; then
|
| 51 | 56 | # No args so run all the tests
|
| 52 | 57 | $LISP -noinit -load tests/run-tests.lisp -eval '(cmucl-test-runner:run-all-tests)'
|
| ... | ... | @@ -170,6 +170,9 @@ |
| 170 | 170 | (alien-rep nil :type (or null function))
|
| 171 | 171 | (extract-gen nil :type (or null function))
|
| 172 | 172 | (deposit-gen nil :type (or null function))
|
| 173 | + ;;
|
|
| 174 | + ;; Method that accepts the alien type and the alien value. The
|
|
| 175 | + ;; method converts the alien value into an appropriate lisp value.
|
|
| 173 | 176 | (naturalize-gen nil :type (or null function))
|
| 174 | 177 | (deport-gen nil :type (or null function))
|
| 175 | 178 | ;; Cast?
|
| ... | ... | @@ -646,8 +649,26 @@ |
| 646 | 649 | |
| 647 | 650 | #-amd64
|
| 648 | 651 | (def-alien-type-method (integer :naturalize-gen) (type alien)
|
| 649 | - (declare (ignore type))
|
|
| 650 | - alien)
|
|
| 652 | + ;; Mask out any unwanted bits. Important if the C code returns
|
|
| 653 | + ;; values in %al, or %ax
|
|
| 654 | + (if (alien-integer-type-signed type)
|
|
| 655 | + (let ((val (gensym "VAL-")))
|
|
| 656 | + (case (alien-integer-type-bits type)
|
|
| 657 | + ;; First, get just the low part of the alien and then
|
|
| 658 | + ;; sign-extend it appropriately.
|
|
| 659 | + (8 `(let ((,val (ldb (byte 8 0) ,alien)))
|
|
| 660 | + (if (> ,val #x7f)
|
|
| 661 | + (- ,val #x100)
|
|
| 662 | + ,val)))
|
|
| 663 | + (16 `(let ((,val (ldb (byte 16 0) ,alien)))
|
|
| 664 | + (if (> ,val #x7fff)
|
|
| 665 | + (- ,val #x10000)
|
|
| 666 | + ,val)))
|
|
| 667 | + (t alien)))
|
|
| 668 | + (case (alien-integer-type-bits type)
|
|
| 669 | + (8 `(ldb (byte 8 0) (truly-the (unsigned-byte 32) ,alien)))
|
|
| 670 | + (16 `(ldb (byte 16 0) (truly-the (unsigned-byte 32) ,alien)))
|
|
| 671 | + (t alien))))
|
|
| 651 | 672 | |
| 652 | 673 | ;; signed numbers <= 32 bits need to be sign extended.
|
| 653 | 674 | ;; I really should use the movsxd instruction, but I don't
|
| ... | ... | @@ -694,8 +715,8 @@ |
| 694 | 715 | |
| 695 | 716 | (def-alien-type-class (boolean :include integer :include-args (signed)))
|
| 696 | 717 | |
| 697 | -(def-alien-type-translator boolean (&optional (bits vm:word-bits))
|
|
| 698 | - (make-alien-boolean-type :bits bits :signed nil))
|
|
| 718 | +(def-alien-type-translator boolean (&optional (bits 8))
|
|
| 719 | + (make-alien-boolean-type :bits bits :signed t))
|
|
| 699 | 720 | |
| 700 | 721 | (def-alien-type-method (boolean :unparse) (type)
|
| 701 | 722 | `(boolean ,(alien-boolean-type-bits type)))
|
| ... | ... | @@ -705,8 +726,10 @@ |
| 705 | 726 | `(member t nil))
|
| 706 | 727 | |
| 707 | 728 | (def-alien-type-method (boolean :naturalize-gen) (type alien)
|
| 708 | - (declare (ignore type))
|
|
| 709 | - `(not (zerop ,alien)))
|
|
| 729 | + ;; Mask out any unwanted bits. Important if the C code returns
|
|
| 730 | + ;; values in %al, or %ax
|
|
| 731 | + `(not (zerop (ldb (byte ,(alien-boolean-type-bits type) 0)
|
|
| 732 | + ,alien))))
|
|
| 710 | 733 | |
| 711 | 734 | (def-alien-type-method (boolean :deport-gen) (type value)
|
| 712 | 735 | (declare (ignore type))
|
| ... | ... | @@ -141,59 +141,78 @@ |
| 141 | 141 | (alien-function-type-result-type type)
|
| 142 | 142 | (make-result-state))))))
|
| 143 | 143 | |
| 144 | -(deftransform %alien-funcall ((function type &rest args))
|
|
| 145 | - (assert (c::constant-continuation-p type))
|
|
| 144 | +(defun %alien-funcall-aux (function type &rest args)
|
|
| 145 | + (declare (ignorable function type args))
|
|
| 146 | 146 | (let* ((type (c::continuation-value type))
|
| 147 | 147 | (arg-types (alien-function-type-arg-types type))
|
| 148 | 148 | (result-type (alien-function-type-result-type type)))
|
| 149 | 149 | (assert (= (length arg-types) (length args)))
|
| 150 | - (if (or (some #'(lambda (type)
|
|
| 151 | - (and (alien-integer-type-p type)
|
|
| 152 | - (> (alien::alien-integer-type-bits type) 32)))
|
|
| 153 | - arg-types)
|
|
| 154 | - (and (alien-integer-type-p result-type)
|
|
| 155 | - (> (alien::alien-integer-type-bits result-type) 32)))
|
|
| 156 | - (collect ((new-args) (lambda-vars) (new-arg-types))
|
|
| 157 | - (dolist (type arg-types)
|
|
| 158 | - (let ((arg (gensym)))
|
|
| 159 | - (lambda-vars arg)
|
|
| 160 | - (cond ((and (alien-integer-type-p type)
|
|
| 161 | - (> (alien::alien-integer-type-bits type) 32))
|
|
| 162 | - (new-args `(logand ,arg #xffffffff))
|
|
| 163 | - (new-args `(ash ,arg -32))
|
|
| 164 | - (new-arg-types (parse-alien-type '(unsigned 32)))
|
|
| 165 | - (if (alien-integer-type-signed type)
|
|
| 166 | - (new-arg-types (parse-alien-type '(signed 32)))
|
|
| 167 | - (new-arg-types (parse-alien-type '(unsigned 32)))))
|
|
| 168 | - (t
|
|
| 169 | - (new-args arg)
|
|
| 170 | - (new-arg-types type)))))
|
|
| 171 | - (cond ((and (alien-integer-type-p result-type)
|
|
| 172 | - (> (alien::alien-integer-type-bits result-type) 32))
|
|
| 173 | - (let ((new-result-type
|
|
| 174 | - (let ((alien::*values-type-okay* t))
|
|
| 175 | - (parse-alien-type
|
|
| 176 | - (if (alien-integer-type-signed result-type)
|
|
| 177 | - '(values (unsigned 32) (signed 32))
|
|
| 178 | - '(values (unsigned 32) (unsigned 32)))))))
|
|
| 179 | - `(lambda (function type ,@(lambda-vars))
|
|
| 180 | - (declare (ignore type))
|
|
| 181 | - (multiple-value-bind (low high)
|
|
| 182 | - (%alien-funcall function
|
|
| 183 | - ',(make-alien-function-type
|
|
| 184 | - :arg-types (new-arg-types)
|
|
| 185 | - :result-type new-result-type)
|
|
| 186 | - ,@(new-args))
|
|
| 187 | - (logior low (ash high 32))))))
|
|
| 150 | + (unless (or (some #'(lambda (type)
|
|
| 151 | + (and (alien-integer-type-p type)
|
|
| 152 | + (> (alien::alien-integer-type-bits type) 32)))
|
|
| 153 | + arg-types)
|
|
| 154 | + (and (alien-integer-type-p result-type)
|
|
| 155 | + (/= (alien::alien-integer-type-bits result-type) 32)))
|
|
| 156 | + (format t "give up~%")
|
|
| 157 | + (c::give-up))
|
|
| 158 | + (collect ((new-args) (lambda-vars) (new-arg-types))
|
|
| 159 | + (dolist (type arg-types)
|
|
| 160 | + (let ((arg (gensym)))
|
|
| 161 | + (lambda-vars arg)
|
|
| 162 | + (cond ((and (alien-integer-type-p type)
|
|
| 163 | + (> (alien::alien-integer-type-bits type) 32))
|
|
| 164 | + (new-args `(logand ,arg #xffffffff))
|
|
| 165 | + (new-args `(ash ,arg -32))
|
|
| 166 | + (new-arg-types (parse-alien-type '(unsigned 32)))
|
|
| 167 | + (if (alien-integer-type-signed type)
|
|
| 168 | + (new-arg-types (parse-alien-type '(signed 32)))
|
|
| 169 | + (new-arg-types (parse-alien-type '(unsigned 32)))))
|
|
| 188 | 170 | (t
|
| 189 | - `(lambda (function type ,@(lambda-vars))
|
|
| 190 | - (declare (ignore type))
|
|
| 191 | - (%alien-funcall function
|
|
| 192 | - ',(make-alien-function-type
|
|
| 193 | - :arg-types (new-arg-types)
|
|
| 194 | - :result-type result-type)
|
|
| 195 | - ,@(new-args))))))
|
|
| 196 | - (c::give-up))))
|
|
| 171 | + (new-args arg)
|
|
| 172 | + (new-arg-types type)))))
|
|
| 173 | + (cond ((and (alien-integer-type-p result-type)
|
|
| 174 | + (< (alien::alien-integer-type-bits result-type) 32))
|
|
| 175 | + (let ((new-result-type
|
|
| 176 | + (parse-alien-type
|
|
| 177 | + (if (alien-integer-type-signed result-type)
|
|
| 178 | + '(signed 32)
|
|
| 179 | + '(unsigned 32)))))
|
|
| 180 | + `(lambda (function type ,@(lambda-vars))
|
|
| 181 | + (declare (ignore type))
|
|
| 182 | + (%alien-funcall function
|
|
| 183 | + ',(make-alien-function-type
|
|
| 184 | + :arg-types (new-arg-types)
|
|
| 185 | + :result-type new-result-type)
|
|
| 186 | + ,@(new-args)))))
|
|
| 187 | + ((and (alien-integer-type-p result-type)
|
|
| 188 | + (> (alien::alien-integer-type-bits result-type) 32))
|
|
| 189 | + (let ((new-result-type
|
|
| 190 | + (let ((alien::*values-type-okay* t))
|
|
| 191 | + (parse-alien-type
|
|
| 192 | + (if (alien-integer-type-signed result-type)
|
|
| 193 | + '(values (unsigned 32) (signed 32))
|
|
| 194 | + '(values (unsigned 32) (unsigned 32)))))))
|
|
| 195 | + `(lambda (function type ,@(lambda-vars))
|
|
| 196 | + (declare (ignore type))
|
|
| 197 | + (multiple-value-bind (low high)
|
|
| 198 | + (%alien-funcall function
|
|
| 199 | + ',(make-alien-function-type
|
|
| 200 | + :arg-types (new-arg-types)
|
|
| 201 | + :result-type new-result-type)
|
|
| 202 | + ,@(new-args))
|
|
| 203 | + (logior low (ash high 32))))))
|
|
| 204 | + (t
|
|
| 205 | + `(lambda (function type ,@(lambda-vars))
|
|
| 206 | + (declare (ignore type))
|
|
| 207 | + (%alien-funcall function
|
|
| 208 | + ',(make-alien-function-type
|
|
| 209 | + :arg-types (new-arg-types)
|
|
| 210 | + :result-type result-type)
|
|
| 211 | + ,@(new-args))))))))
|
|
| 212 | + |
|
| 213 | +(deftransform %alien-funcall ((function type &rest args))
|
|
| 214 | + (assert (c::constant-continuation-p type))
|
|
| 215 | + (apply #'%alien-funcall-aux function type args))
|
|
| 197 | 216 | |
| 198 | 217 | (define-vop (foreign-symbol-code-address)
|
| 199 | 218 | (:translate #+linkage-table foreign-symbol-code-address
|
| ... | ... | @@ -997,3 +997,111 @@ |
| 997 | 997 | ;; This is the condition from the CLHS entry for enough-namestring
|
| 998 | 998 | (assert-equal (merge-pathnames enough defaults)
|
| 999 | 999 | (merge-pathnames (parse-namestring pathname nil defaults) defaults))))))
|
| 1000 | + |
|
| 1001 | +(define-test issue.242-load-foreign
|
|
| 1002 | + ;; load-foreign apparently returns NIL if it succeeds.
|
|
| 1003 | + (assert-true (eql nil (ext:load-foreign (merge-pathnames "test-return.o" *test-path*)))))
|
|
| 1004 | + |
|
| 1005 | +(alien:def-alien-variable "test_arg" c-call:int)
|
|
| 1006 | + |
|
| 1007 | +(define-test issue.242.test-alien-return-signed-char
|
|
| 1008 | + (:tag :issues)
|
|
| 1009 | + (flet ((fun (n)
|
|
| 1010 | + (setf test-arg n)
|
|
| 1011 | + (alien:alien-funcall
|
|
| 1012 | + (alien:extern-alien "int_to_signed_char"
|
|
| 1013 | + (function c-call:char))))
|
|
| 1014 | + (sign-extend (n)
|
|
| 1015 | + (let ((n (ldb (byte 8 0) n)))
|
|
| 1016 | + (if (> n #x7f)
|
|
| 1017 | + (- n #x100)
|
|
| 1018 | + n))))
|
|
| 1019 | + (dolist (x '(99 -99 1023 -1023))
|
|
| 1020 | + (assert-equal (sign-extend x) (fun x) x))))
|
|
| 1021 | + |
|
| 1022 | +(define-test issue.242.test-alien-return-signed-short
|
|
| 1023 | + (:tag :issues)
|
|
| 1024 | + (flet ((fun (n)
|
|
| 1025 | + (setf test-arg n)
|
|
| 1026 | + (alien:alien-funcall
|
|
| 1027 | + (alien:extern-alien "int_to_short"
|
|
| 1028 | + (function c-call:short))))
|
|
| 1029 | + (sign-extend (n)
|
|
| 1030 | + (let ((n (ldb (byte 16 0) n)))
|
|
| 1031 | + (if (> n #x7fff)
|
|
| 1032 | + (- n #x10000)
|
|
| 1033 | + n))))
|
|
| 1034 | + (dolist (x '(1023 -1023 100000 -100000))
|
|
| 1035 | + (assert-equal (sign-extend x) (fun x) x))))
|
|
| 1036 | + |
|
| 1037 | +(define-test issue.242.test-alien-return-signed-int
|
|
| 1038 | + (:tag :issues)
|
|
| 1039 | + (flet ((fun (n)
|
|
| 1040 | + (setf test-arg n)
|
|
| 1041 | + (alien:alien-funcall
|
|
| 1042 | + (alien:extern-alien "int_to_int"
|
|
| 1043 | + (function c-call:int)))))
|
|
| 1044 | + (dolist (x '(1023 -1023 #x7fffffff #x-80000000))
|
|
| 1045 | + (assert-equal x (fun x) x))))
|
|
| 1046 | + |
|
| 1047 | +(define-test issue.242.test-alien-return-unsigned-char
|
|
| 1048 | + (:tag :issues)
|
|
| 1049 | + (flet ((fun (n)
|
|
| 1050 | + (setf test-arg n)
|
|
| 1051 | + (alien:alien-funcall
|
|
| 1052 | + (alien:extern-alien "int_to_unsigned_char"
|
|
| 1053 | + (function c-call:unsigned-char))))
|
|
| 1054 | + (expected (n)
|
|
| 1055 | + (ldb (byte 8 0) n)))
|
|
| 1056 | + (dolist (x '(99 -99 1023 -1023))
|
|
| 1057 | + (assert-equal (expected x) (fun x) x))))
|
|
| 1058 | + |
|
| 1059 | +(define-test issue.242.test-alien-return-unsigned-short
|
|
| 1060 | + (:tag :issues)
|
|
| 1061 | + (flet ((fun (n)
|
|
| 1062 | + (setf test-arg n)
|
|
| 1063 | + (alien:alien-funcall
|
|
| 1064 | + (alien:extern-alien "int_to_unsigned_short"
|
|
| 1065 | + (function c-call:unsigned-short))))
|
|
| 1066 | + (expected (n)
|
|
| 1067 | + (ldb (byte 16 0) n)))
|
|
| 1068 | + (dolist (x '(1023 -1023 100000 -100000))
|
|
| 1069 | + (assert-equal (expected x) (fun x) x))))
|
|
| 1070 | + |
|
| 1071 | +(define-test issue.242.test-alien-return-unsigned-int
|
|
| 1072 | + (:tag :issues)
|
|
| 1073 | + (flet ((fun (n)
|
|
| 1074 | + (setf test-arg n)
|
|
| 1075 | + (alien:alien-funcall
|
|
| 1076 | + (alien:extern-alien "int_to_unsigned_int"
|
|
| 1077 | + (function c-call:unsigned-int))))
|
|
| 1078 | + (expected (n)
|
|
| 1079 | + (ldb (byte 32 0) n)))
|
|
| 1080 | + (dolist (x '(1023 -1023 #x7fffffff #x-80000000))
|
|
| 1081 | + (assert-equal (expected x) (fun x) x))))
|
|
| 1082 | + |
|
| 1083 | +(define-test issue.242.test-alien-return-bool
|
|
| 1084 | + (:tag :issues)
|
|
| 1085 | + (flet ((fun (n)
|
|
| 1086 | + (setf test-arg n)
|
|
| 1087 | + (alien:alien-funcall
|
|
| 1088 | + (alien:extern-alien "int_to_bool"
|
|
| 1089 | + (function c-call:char))))
|
|
| 1090 | + (expected (n)
|
|
| 1091 | + (if (zerop n)
|
|
| 1092 | + 0
|
|
| 1093 | + 1)))
|
|
| 1094 | + (dolist (x '(0 1 1000))
|
|
| 1095 | + (assert-equal (expected x) (fun x) x))))
|
|
| 1096 | + |
|
| 1097 | +(define-test issue.242.test-alien-return-bool.2
|
|
| 1098 | + (:tag :issues)
|
|
| 1099 | + (flet ((fun (n)
|
|
| 1100 | + (setf test-arg n)
|
|
| 1101 | + (alien:alien-funcall
|
|
| 1102 | + (alien:extern-alien "int_to_bool"
|
|
| 1103 | + (function alien:boolean))))
|
|
| 1104 | + (expected (n)
|
|
| 1105 | + (not (zerop n))))
|
|
| 1106 | + (dolist (x '(0 1 1000))
|
|
| 1107 | + (assert-equal (expected x) (fun x) x)))) |
| 1 | +#include <stdbool.h>
|
|
| 2 | + |
|
| 3 | +int test_arg;
|
|
| 4 | + |
|
| 5 | +signed char
|
|
| 6 | +int_to_signed_char()
|
|
| 7 | +{
|
|
| 8 | + return (signed char) test_arg;
|
|
| 9 | +}
|
|
| 10 | + |
|
| 11 | +short
|
|
| 12 | +int_to_short()
|
|
| 13 | +{
|
|
| 14 | + return (short) test_arg;
|
|
| 15 | +}
|
|
| 16 | + |
|
| 17 | +int
|
|
| 18 | +int_to_int()
|
|
| 19 | +{
|
|
| 20 | + return (int) test_arg;
|
|
| 21 | +}
|
|
| 22 | + |
|
| 23 | +unsigned char
|
|
| 24 | +int_to_unsigned_char()
|
|
| 25 | +{
|
|
| 26 | + return (unsigned char) test_arg;
|
|
| 27 | +}
|
|
| 28 | + |
|
| 29 | +unsigned short
|
|
| 30 | +int_to_unsigned_short()
|
|
| 31 | +{
|
|
| 32 | + return (unsigned short) test_arg;
|
|
| 33 | +}
|
|
| 34 | + |
|
| 35 | +unsigned int
|
|
| 36 | +int_to_unsigned_int()
|
|
| 37 | +{
|
|
| 38 | + return (unsigned int) test_arg;
|
|
| 39 | +}
|
|
| 40 | + |
|
| 41 | +_Bool int_to_bool()
|
|
| 42 | +{
|
|
| 43 | + return (_Bool) test_arg;
|
|
| 44 | +}
|
|
| 45 | + |