diff --git a/src/cmp/cmpcall.lsp b/src/cmp/cmpcall.lsp index 510998437..153e92d41 100644 --- a/src/cmp/cmpcall.lsp +++ b/src/cmp/cmpcall.lsp @@ -18,10 +18,12 @@ (in-package "COMPILER") (defun unoptimized-long-call (fun arguments) - (let ((frame (gensym))) + (let ((frame (gensym)) + (f-arg (gensym))) `(with-stack ,frame - ,@(loop for i in arguments collect `(stack-push ,frame ,i)) - (si::apply-from-stack-frame ,frame ,fun)))) + (let ((,f-arg ,fun)) + ,@(loop for i in arguments collect `(stack-push ,frame ,i)) + (si::apply-from-stack-frame ,frame ,f-arg))))) (defun unoptimized-funcall (fun arguments) (let ((l (length arguments))) diff --git a/src/tests/normal-tests/compiler.lsp b/src/tests/normal-tests/compiler.lsp index 18317f48b..ee960b529 100644 --- a/src/tests/normal-tests/compiler.lsp +++ b/src/tests/normal-tests/compiler.lsp @@ -1583,3 +1583,26 @@ (finishes (run-1)) (finishes (run-2)) (finishes (run-3))) + +;;; Date 2020-01-12 +;;; URL: https://gitlab.com/embeddable-common-lisp/ecl/issues/550 +;;; Description +;;; +;;; When we invoke an unopitmized long call (that is we apply from +;;; a stack frame), function argument is evaluated after the +;;; arguments what is wrong for operators where function is the +;;; first argument (and should be evaluated first). +(test cmp.0074.c-arguments-limit.evaluation-rule + (flet ((make-fn (n) + `(lambda () + (let ((se-var '())) + (funcall (prog1 #'list (push :fun se-var)) + ,@(list* `(push :arg se-var) + (make-list (1- n)))) + (nreverse se-var)))) + (check-fn (form) + (is (equal '(:fun :arg) (funcall (compile nil form)))))) + (check-fn (make-fn 10)) + (check-fn (make-fn (1+ si::c-arguments-limit))) + (check-fn (make-fn (1- si::c-arguments-limit))) + (check-fn (make-fn si::c-arguments-limit))))