(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))
(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)
(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)
;;; 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))
(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)
(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)
(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)))))))