summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-03-21 03:05:58 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-03-22 10:29:07 -0700
commitebbc7fb10c1763d81fadb6328e9f9f4b9f833b28 (patch)
tree820b334d14b4b8a8f8a6ebc14b452e120c2312ef
parent4836fb69ecb23561ae2462071aa15cf44f0eaa87 (diff)
downloadtxr-ebbc7fb10c1763d81fadb6328e9f9f4b9f833b28.tar.gz
txr-ebbc7fb10c1763d81fadb6328e9f9f4b9f833b28.tar.bz2
txr-ebbc7fb10c1763d81fadb6328e9f9f4b9f833b28.zip
ffi: support float type as variadic argument.
The float type promotes to double when passed as a variadic argument. This patch adds internal FFI types which models that promotion. It uses double for its C type, while still performing the range checks for float. Also, the types be-float and le-float are rejected from being variadic arguments. * share/txr/stdlib/ffi.tl (analyze-argtypes): Rewrite function, adding validation and substitution for the variadic part of the argument type list. Map float type to double, and reject be-float and le-float. * txr.1: Documented.
-rw-r--r--share/txr/stdlib/ffi.tl18
-rw-r--r--txr.159
2 files changed, 69 insertions, 8 deletions
diff --git a/share/txr/stdlib/ffi.tl b/share/txr/stdlib/ffi.tl
index e171cb47..480faf5d 100644
--- a/share/txr/stdlib/ffi.tl
+++ b/share/txr/stdlib/ffi.tl
@@ -54,12 +54,18 @@
(t exp)))
(defun sys:analyze-argtypes (form argtypes)
- (let ((p (posq : argtypes)))
- (when p
- (if (zerop p)
- (compile-error form "variadic with zero fixed arguments not allowed")
- (del [argtypes p])))
- (list* (length argtypes) p argtypes)))
+ (tree-bind (: ftypes vtypes) (split* argtypes (op where (op eq :)))
+ (when vtypes
+ (when (null ftypes)
+ (compile-error form "variadic with zero fixed arguments not allowed"))
+ (set vtypes
+ (collect-each ((vt vtypes))
+ (caseq vt
+ ((float) 'double)
+ ((be-float le-float)
+ (compile-error form "variadic argument cannot be of type ~s"
+ vt))))))
+ (list* (+ (len ftypes) (len vtypes)) (len ftypes) (append ftypes vtypes))))
(defmacro deffi (:form f :env e name fun-expr rettype argtypes)
diff --git a/txr.1 b/txr.1
index 4da6bf8e..ad295cde 100644
--- a/txr.1
+++ b/txr.1
@@ -72113,6 +72113,26 @@ descriptor, and
even if the return types and
argument types match.
+Note: unlike the
+.code deffi
+and
+.code deffi-cb
+macros,
+the
+.code ffi-make-call-desc
+function doesn't perform any special treatment of variadic parameter types.
+When any of the types
+.codn float ,
+.code be-float
+or
+.code le-float
+occur in the variadic portion of
+.metn argtypes ,
+it is unspecified whether a descriptor is successfully produced and returned
+or whether an exception is thrown. If a descriptor is successfully produced,
+and then subsequently used for making or accepting calls, the behavior is
+undefined.
+
.TP* Example:
.verb
@@ -72689,8 +72709,9 @@ symbol appears as one of the elements of
then the
.code deffi
form specifies a fixed call to a foreign function which is variadic. The
-argument types before the colon keyword are the fixed arguments. The types
-after the colon, if any, are the variadic arguments.
+argument types before the colon keyword are the types of the fixed arguments.
+The types after the colon, if any, are of the variadic arguments. Special
+considerations apply to some variadic argument types, described below.
The following syntactic variants are permitted of the
.meta fun-expr
@@ -72732,6 +72753,40 @@ macro.
.RE
.IP
+When the FFI type
+.code float
+is used as the type of a variadic parameter,
+.code deffi
+replaces it by the FFI type
+.codn double .
+This treatment is necessary because the C variadic argument mechanism promotes
+.code float
+values to
+.codn double .
+Note: due to this substitution, it is possible to pass floating-point values
+which are out of range of the
+.code float
+type, without any diagnosis. The behavior of is undefined in the
+Lisp-to-C direction, if the C function extracts an out-of-range
+.code double
+argument as if it were of type
+.codn float .
+
+The FFI types
+.code be-float
+and
+.code le-float
+cannot be used for specifying the types of a variadic argument. If any of
+these occur in that position,
+.code deffi
+throws an error.
+Rationale: these types are related to the C type
+.code float
+type, which requires promotion in variadic passing. Promotion cannot
+be performed on floating-point values whose byte order has been rearranged,
+because promotion is a value-preserving conversion.
+
+.IP
The result value of a
.code deffi
form is