X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fir1util.lisp;h=19e0adb3e8502e6806853b3e5c23b3045dae511b;hb=091f0c20d4661994be7be4cc707c2aba4ef86418;hp=7fa4abe3db9bd553f0406f273e1fb91d7682408e;hpb=79df11a5e57e23f1e079e60420ff6d058af7a725;p=sbcl.git diff --git a/src/compiler/ir1util.lisp b/src/compiler/ir1util.lisp index 7fa4abe..19e0adb 100644 --- a/src/compiler/ir1util.lisp +++ b/src/compiler/ir1util.lisp @@ -391,6 +391,34 @@ (awhen (node-lvar node) (lvar-dynamic-extent it))) +(defun flushable-combination-p (call) + (declare (combination call)) + (let ((kind (combination-kind call)) + (info (combination-fun-info call))) + (when (and (eq kind :known) (fun-info-p info)) + (let ((attr (fun-info-attributes info))) + (when (and (not (ir1-attributep attr call)) + ;; FIXME: For now, don't consider potentially flushable + ;; calls flushable when they have the CALL attribute. + ;; Someday we should look at the functional args to + ;; determine if they have any side effects. + (if (policy call (= safety 3)) + (ir1-attributep attr flushable) + (ir1-attributep attr unsafely-flushable))) + t))))) + +(defun note-no-stack-allocation (lvar &key flush) + (do-uses (use (principal-lvar lvar)) + (unless (or + ;; Don't complain about not being able to stack allocate constants. + (and (ref-p use) (constant-p (ref-leaf use))) + ;; If we're flushing, don't complain if we can flush the combination. + (and flush (combination-p use) (flushable-combination-p use))) + (let ((*compiler-error-context* use)) + (compiler-notify "could not stack allocate the result of ~S" + (find-original-source (node-source-path use))))))) + + (declaim (ftype (sfunction (node (member nil t :truly) &optional (or null component)) boolean) use-good-for-dx-p)) (declaim (ftype (sfunction (lvar (member nil t :truly) &optional (or null component)) @@ -415,9 +443,10 @@ (defun lvar-good-for-dx-p (lvar dx &optional component) (let ((uses (lvar-uses lvar))) (if (listp uses) - (every (lambda (use) - (use-good-for-dx-p use dx component)) - uses) + (when uses + (every (lambda (use) + (use-good-for-dx-p use dx component)) + uses)) (use-good-for-dx-p uses dx component)))) (defun known-dx-combination-p (use dx) @@ -1198,6 +1227,8 @@ (defun flush-dest (lvar) (declare (type (or lvar null) lvar)) (unless (null lvar) + (when (lvar-dynamic-extent lvar) + (note-no-stack-allocation lvar :flush t)) (setf (lvar-dest lvar) nil) (flush-lvar-externally-checkable-type lvar) (do-uses (use lvar) @@ -1554,9 +1585,9 @@ ;;; arguments. (defun splice-fun-args (lvar fun num-args) #!+sb-doc - "If LVAR is a call to FUN with NUM-ARGS args, change those arguments - to feed directly to the LVAR-DEST of LVAR, which must be a - combination." + "If LVAR is a call to FUN with NUM-ARGS args, change those arguments to feed +directly to the LVAR-DEST of LVAR, which must be a combination. If FUN +is :ANY, the function name is not checked." (declare (type lvar lvar) (type symbol fun) (type index num-args)) @@ -1566,7 +1597,8 @@ (unless (combination-p inside) (give-up-ir1-transform)) (let ((inside-fun (combination-fun inside))) - (unless (eq (lvar-fun-name inside-fun) fun) + (unless (or (eq fun :any) + (eq (lvar-fun-name inside-fun) fun)) (give-up-ir1-transform)) (let ((inside-args (combination-args inside))) (unless (= (length inside-args) num-args) @@ -1587,7 +1619,43 @@ (combination-kind inside) :known) (setf (node-derived-type inside) *wild-type*) (flush-dest lvar) - (values)))))) + inside-args))))) + +;;; Eliminate keyword arguments from the call (leaving the +;;; parameters in place. +;;; +;;; (FOO ... :BAR X :QUUX Y) +;;; becomes +;;; (FOO ... X Y) +;;; +;;; SPECS is a list of (:KEYWORD PARAMETER) specifications. +;;; Returns the list of specified parameters names in the +;;; order they appeared in the call. N-POSITIONAL is the +;;; number of positional arguments in th call. +(defun eliminate-keyword-args (call n-positional specs) + (let* ((specs (copy-tree specs)) + (all (combination-args call)) + (new-args (reverse (subseq all 0 n-positional))) + (key-args (subseq all n-positional)) + (parameters nil) + (flushed-keys nil)) + (loop while key-args + do (let* ((key (pop key-args)) + (val (pop key-args)) + (keyword (if (constant-lvar-p key) + (lvar-value key) + (give-up-ir1-transform))) + (spec (or (assoc keyword specs :test #'eq) + (give-up-ir1-transform)))) + (push val new-args) + (push key flushed-keys) + (push (second spec) parameters) + ;; In case of duplicate keys. + (setf (second spec) (gensym)))) + (dolist (key flushed-keys) + (flush-dest key)) + (setf (combination-args call) (reverse new-args)) + (reverse parameters))) (defun extract-fun-args (lvar fun num-args) (declare (type lvar lvar) @@ -2040,3 +2108,12 @@ (eq (global-var-kind leaf) :global-function) (not (null (member (leaf-source-name leaf) names :test #'equal)))))))) + +(defun lvar-matches (lvar &key fun-names arg-count) + (let ((use (lvar-use lvar))) + (and (combination-p use) + (or (not fun-names) + (member (combination-fun-source-name use) + fun-names :test #'eq)) + (or (not arg-count) + (= arg-count (length (combination-args use)))))))