(setf (car args) nil)))
(values))
-(defun handle-nested-dynamic-extent-lvars (lvar)
+(defun handle-nested-dynamic-extent-lvars (dx lvar)
(let ((uses (lvar-uses lvar)))
- ;; Stack analysis wants DX value generators to end their
- ;; blocks. Uses of mupltiple used LVARs already end their blocks,
- ;; so we just need to process used-once LVARs.
+ ;; DX value generators must end their blocks: see UPDATE-UVL-LIVE-SETS.
+ ;; Uses of mupltiple-use LVARs already end their blocks, so we just need
+ ;; to process uses of single-use LVARs.
(when (node-p uses)
(node-ends-block uses))
;; If this LVAR's USE is good for DX, it is either a CAST, or it
(flet ((recurse (use)
(etypecase use
(cast
- (handle-nested-dynamic-extent-lvars (cast-value use)))
+ (handle-nested-dynamic-extent-lvars dx (cast-value use)))
(combination
(loop for arg in (combination-args use)
- when (lvar-good-for-dx-p arg)
- append (handle-nested-dynamic-extent-lvars arg))))))
+ when (lvar-good-for-dx-p arg dx)
+ append (handle-nested-dynamic-extent-lvars dx arg))))))
(cons lvar
(if (listp uses)
(loop for use in uses
- when (use-good-for-dx-p use)
+ when (use-good-for-dx-p use dx)
nconc (recurse use))
- (when (use-good-for-dx-p uses)
+ (when (use-good-for-dx-p uses dx)
(recurse uses)))))))
(defun recognize-dynamic-extent-lvars (call fun)
(declare (type combination call) (type clambda fun))
(loop for arg in (basic-combination-args call)
- and var in (lambda-vars fun)
- when (and arg (lambda-var-dynamic-extent var)
- (not (lvar-dynamic-extent arg)))
- append (handle-nested-dynamic-extent-lvars arg) into dx-lvars
+ for var in (lambda-vars fun)
+ for dx = (lambda-var-dynamic-extent var)
+ when (and dx arg (not (lvar-dynamic-extent arg)))
+ append (handle-nested-dynamic-extent-lvars dx arg) into dx-lvars
finally (when dx-lvars
- ;; A call to non-LET with DX args must end its block,
- ;; otherwise stack analysis will not see the combination and
- ;; the associated cleanup/entry.
- (unless (eq :let (functional-kind fun))
- (node-ends-block call))
- (binding* ((before-ctran (node-prev call))
- (nil (ensure-block-start before-ctran))
- (block (ctran-block before-ctran))
- (new-call-ctran (make-ctran :kind :inside-block
- :next call
- :block block))
- (entry (with-ir1-environment-from-node call
- (make-entry :prev before-ctran
- :next new-call-ctran)))
- (cleanup (make-cleanup :kind :dynamic-extent
- :mess-up entry
- :info dx-lvars)))
- (setf (node-prev call) new-call-ctran)
- (setf (ctran-next before-ctran) entry)
- (setf (ctran-use new-call-ctran) entry)
+ ;; Stack analysis requires that the CALL ends the block, so
+ ;; that MAP-BLOCK-NLXES sees the cleanup we insert here.
+ (node-ends-block call)
+ (let* ((entry (with-ir1-environment-from-node call
+ (make-entry)))
+ (cleanup (make-cleanup :kind :dynamic-extent
+ :mess-up entry
+ :info dx-lvars)))
(setf (entry-cleanup entry) cleanup)
+ (insert-node-before call entry)
(setf (node-lexenv call)
(make-lexenv :default (node-lexenv call)
:cleanup cleanup))