From 72a6aaf189b6390bc2bce661155239373f6b906d Mon Sep 17 00:00:00 2001 From: Kaz Kylheku <kaz@kylheku.com> Date: Fri, 22 Oct 2021 22:30:43 -0700 Subject: ffi: deffi, deffi-cb: eliminate generated globals. The immediate problem is that with-dyn-lib creates a defvarl, but deffi uses load-time forms to refer to that. In compiled code, these load-time evaluations will occur before the defvarl exists. The conceptual problem is that with-dyn-lib might not be a top-level form. It can be conditionally executed, as it happens in stdlib/doc-syms.tl, which is now broken. Let's not use load-time, but straight lexical environments. * stdlib/ffi.tl (with-dyn-lib): Translate to a simple let which binds sys:ffi-lib as a lexical variable. (sys:with-dyn-lib-check): Use lexical-var-p to test what sys:ffi-lib is lexically bound as a variable. (deffi, sys:deffi-cb-expander): Instead of gloval defvarl variables, bind the needed pieces to lexical variables, placing the generated defun into that scope. --- stdlib/ffi.tl | 52 +++++++++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) (limited to 'stdlib') diff --git a/stdlib/ffi.tl b/stdlib/ffi.tl index 7ca45bf1..28bf3405 100644 --- a/stdlib/ffi.tl +++ b/stdlib/ffi.tl @@ -31,14 +31,11 @@ (t spec))) (defmacro with-dyn-lib (lib . body) - (let ((keep-var (gensym "lib-"))) - ^(prog1 - (defvarl ,keep-var (sys:dlib-expr ,lib)) - (symacrolet ((sys:ffi-lib ,keep-var)) - ,*body)))) + ^(let ((sys:ffi-lib (sys:dlib-expr ,lib))) + ,*body)) (defun sys:with-dyn-lib-check (f e ref) - (when (eq (macroexpand 'sys:ffi-lib e) 'sys:ffi-lib) + (unless (lexical-var-p e 'sys:ffi-lib) (compile-warning f "simple ref ~s requires ~s" ref 'with-dyn-lib))) @@ -71,22 +68,18 @@ (defmacro deffi (:form f :env e name fun-expr rettype argtypes) (let ((fun-ref (sys:expand-sym-ref f e fun-expr)) - (ret-type-sym (gensym "ret-type-")) - (arg-types-sym (gensym "arg-types-")) - (call-desc-sym (gensym "call-desc-")) - (fun-sym (gensym "ffi-fun-"))) + (fun-sym (gensym "fun-")) + (desc-sym (gensym "desc-"))) (tree-bind (nargs nfixed . argtypes) (sys:analyze-argtypes f argtypes) (let ((arg-syms (take nargs (gun (gensym))))) - ^(progn - (defvarl ,ret-type-sym (ffi-type-compile ',rettype)) - (defvarl ,arg-types-sym [mapcar ffi-type-compile ',argtypes]) - (defvarl ,call-desc-sym (ffi-make-call-desc ,nargs ,nfixed - ,ret-type-sym - ,arg-types-sym - ',name)) - (defvarl ,fun-sym ,fun-ref) + ^(let ((,fun-sym ,fun-ref) + (,desc-sym (ffi-make-call-desc ,nargs ,nfixed + (ffi-type-compile ',rettype) + [mapcar ffi-type-compile + ',argtypes] + ',name))) (defun ,name ,arg-syms - (ffi-call ,fun-sym ,call-desc-sym ,*arg-syms))))))) + (ffi-call ,fun-sym ,desc-sym ,*arg-syms))))))) (defmacro deffi-type (name type-expr) ^(ffi-typedef ',name (ffi-type-compile ',type-expr))) @@ -95,20 +88,17 @@ ^(ffi-typedef ',name (ffi-type-compile ',type-expr))) (defun sys:deffi-cb-expander (f name rettype argtypes safe-p abort-retval) - (let ((ret-type-sym (gensym "ret-type-")) - (arg-types-sym (gensym "arg-types-")) - (call-desc-sym (gensym "call-desc-")) - (fun-sym (gensym "fun-"))) + (let ((fun-sym (gensym "fun-")) + (desc-sym (gensym "desc-"))) (tree-bind (nargs nvariadic . argtypes) (sys:analyze-argtypes f argtypes) - ^(progn - (defvarl ,ret-type-sym (ffi-type-compile ',rettype)) - (defvarl ,arg-types-sym [mapcar ffi-type-compile ',argtypes]) - (defvarl ,call-desc-sym (ffi-make-call-desc ,nargs ,nvariadic - ,ret-type-sym - ,arg-types-sym - ',name)) + ^(let ((,desc-sym (ffi-make-call-desc ,nargs ,nvariadic + (ffi-type-compile ',rettype) + [mapcar ffi-type-compile + ',argtypes] + ',name))) (defun ,name (,fun-sym) - [ffi-make-closure ,fun-sym ,call-desc-sym ,safe-p ,abort-retval]))))) + [ffi-make-closure ,fun-sym ,desc-sym + ,safe-p ,abort-retval]))))) (defmacro deffi-cb (:form f name rettype argtypes : abort-retval) (sys:deffi-cb-expander f name rettype argtypes t abort-retval)) -- cgit v1.2.3