X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fdebug.lisp;h=6463f64d1c8e9f2c68286286cfcfd6b2b3ed8153;hb=d40a76606c86722b0aef8179155f9f2840739b72;hp=6e20896bb1c997f092dd48e9b6ed2d4fa792791e;hpb=a530bbe337109d898d5b4a001fc8f1afa3b5dc39;p=sbcl.git diff --git a/src/compiler/debug.lisp b/src/compiler/debug.lisp index 6e20896..6463f64 100644 --- a/src/compiler/debug.lisp +++ b/src/compiler/debug.lisp @@ -12,9 +12,6 @@ (in-package "SB!C") -(file-comment - "$Header$") - (defvar *args* () #!+sb-doc "This variable is bound to the format arguments when an error is signalled @@ -42,8 +39,8 @@ One of :WARN, :ERROR or :NONE.") (declaim (type (member :warn :error :none) *burp-action*)) -;;; Called when something funny but possibly correct is noticed. Otherwise -;;; similar to Barf. +;;; Called when something funny but possibly correct is noticed. +;;; Otherwise similar to BARF. (declaim (ftype (function (string &rest t) (values)) burp)) (defun burp (string &rest *args*) (ecase *burp-action* @@ -52,31 +49,33 @@ (:none)) (values)) -;;; *Seen-Blocks* is a hashtable with true values for all blocks which appear -;;; in the DFO for one of the specified components. +;;; *SEEN-BLOCKS* is a hashtable with true values for all blocks which +;;; appear in the DFO for one of the specified components. +;;; +;;; *SEEN-FUNCTIONS* is similar, but records all the lambdas we +;;; reached by recursing on top level functions. (defvar *seen-blocks* (make-hash-table :test 'eq)) - -;;; *Seen-Functions* is similar, but records all the lambdas we reached by -;;; recursing on top-level functions. (defvar *seen-functions* (make-hash-table :test 'eq)) -;;; Barf if Node is in a block which wasn't reached during the graph walk. +;;; Barf if NODE is in a block which wasn't reached during the graph +;;; walk. (declaim (ftype (function (node) (values)) check-node-reached)) (defun check-node-reached (node) (unless (gethash (continuation-block (node-prev node)) *seen-blocks*) (barf "~S was not reached." node)) (values)) -;;; Check everything that we can think of for consistency. When a definite -;;; inconsistency is detected, we BARF. Possible problems just cause us to -;;; BURP. Our argument is a list of components, but we also look at the -;;; *FREE-VARIABLES*, *FREE-FUNCTIONS* and *CONSTANTS*. +;;; Check everything that we can think of for consistency. When a +;;; definite inconsistency is detected, we BARF. Possible problems +;;; just cause us to BURP. Our argument is a list of components, but +;;; we also look at the *FREE-VARIABLES*, *FREE-FUNCTIONS* and +;;; *CONSTANTS*. ;;; -;;; First we do a pre-pass which finds all the blocks and lambdas, testing -;;; that they are linked together properly and entering them in hashtables. -;;; Next, we iterate over the blocks again, looking at the actual code and -;;; control flow. Finally, we scan the global leaf hashtables, looking for -;;; lossage. +;;; First we do a pre-pass which finds all the CBLOCKs and CLAMBDAs, +;;; testing that they are linked together properly and entering them +;;; in hashtables. Next, we iterate over the blocks again, looking at +;;; the actual code and control flow. Finally, we scan the global leaf +;;; hashtables, looking for lossage. (declaim (ftype (function (list) (values)) check-ir1-consistency)) (defun check-ir1-consistency (components) (clrhash *seen-blocks*) @@ -109,43 +108,43 @@ |# )) - (check-function-consistency components) + (check-fun-consistency components) (dolist (c components) (do ((block (block-next (component-head c)) (block-next block))) ((null (block-next block))) (check-block-consistency block))) - (maphash #'(lambda (k v) - (declare (ignore k)) - (unless (or (constant-p v) - (and (global-var-p v) - (member (global-var-kind v) - '(:global :special :constant)))) - (barf "strange *FREE-VARIABLES* entry: ~S" v)) - (dolist (n (leaf-refs v)) - (check-node-reached n)) - (when (basic-var-p v) - (dolist (n (basic-var-sets v)) - (check-node-reached n)))) + (maphash (lambda (k v) + (declare (ignore k)) + (unless (or (constant-p v) + (and (global-var-p v) + (member (global-var-kind v) + '(:global :special)))) + (barf "strange *FREE-VARIABLES* entry: ~S" v)) + (dolist (n (leaf-refs v)) + (check-node-reached n)) + (when (basic-var-p v) + (dolist (n (basic-var-sets v)) + (check-node-reached n)))) *free-variables*) - (maphash #'(lambda (k v) - (declare (ignore k)) - (unless (constant-p v) - (barf "strange *CONSTANTS* entry: ~S" v)) - (dolist (n (leaf-refs v)) - (check-node-reached n))) + (maphash (lambda (k v) + (declare (ignore k)) + (unless (constant-p v) + (barf "strange *CONSTANTS* entry: ~S" v)) + (dolist (n (leaf-refs v)) + (check-node-reached n))) *constants*) - (maphash #'(lambda (k v) - (declare (ignore k)) - (unless (or (functional-p v) - (and (global-var-p v) - (eq (global-var-kind v) :global-function))) - (barf "strange *FREE-FUNCTIONS* entry: ~S" v)) - (dolist (n (leaf-refs v)) - (check-node-reached n))) + (maphash (lambda (k v) + (declare (ignore k)) + (unless (or (functional-p v) + (and (global-var-p v) + (eq (global-var-kind v) :global-function))) + (barf "strange *FREE-FUNCTIONS* entry: ~S" v)) + (dolist (n (leaf-refs v)) + (check-node-reached n))) *free-functions*) (clrhash *seen-functions*) (clrhash *seen-blocks*) @@ -161,26 +160,26 @@ (setf (gethash x *seen-functions*) t))) ;;; Check that the specified function has been seen. -(defun check-function-reached (fun where) +(defun check-fun-reached (fun where) (declare (type functional fun)) (unless (gethash fun *seen-functions*) (barf "unseen function ~S in ~S" fun where))) -;;; In a lambda, check that the associated nodes are in seen blocks. In an -;;; optional dispatch, check that the entry points were seen. If the function -;;; is deleted, ignore it. -(defun check-function-stuff (functional) +;;; In a CLAMBDA, check that the associated nodes are in seen blocks. +;;; In an OPTIONAL-DISPATCH, check that the entry points were seen. If +;;; the function is deleted, ignore it. +(defun check-fun-stuff (functional) (ecase (functional-kind functional) (:external - (let ((fun (functional-entry-function functional))) - (check-function-reached fun functional) + (let ((fun (functional-entry-fun functional))) + (check-fun-reached fun functional) (when (functional-kind fun) (barf "The function for XEP ~S has kind." functional)) - (unless (eq (functional-entry-function fun) functional) + (unless (eq (functional-entry-fun fun) functional) (barf "bad back-pointer in function for XEP ~S" functional)))) ((:let :mv-let :assignment) - (check-function-reached (lambda-home functional) functional) - (when (functional-entry-function functional) + (check-fun-reached (lambda-home functional) functional) + (when (functional-entry-fun functional) (barf "The LET ~S has entry function." functional)) (unless (member functional (lambda-lets (lambda-home functional))) (barf "The LET ~S is not in LETs for HOME." functional)) @@ -190,36 +189,34 @@ (when (lambda-lets functional) (barf "LETs in a LET: ~S" functional))) (:optional - (when (functional-entry-function functional) - (barf ":OPTIONAL ~S has an ENTRY-FUNCTION." functional)) + (when (functional-entry-fun functional) + (barf ":OPTIONAL ~S has an ENTRY-FUN." functional)) (let ((ef (lambda-optional-dispatch functional))) - (check-function-reached ef functional) + (check-fun-reached ef functional) (unless (or (member functional (optional-dispatch-entry-points ef)) (eq functional (optional-dispatch-more-entry ef)) (eq functional (optional-dispatch-main-entry ef))) (barf ":OPTIONAL ~S is not an e-p for its OPTIONAL-DISPATCH ~S." functional ef)))) - (:top-level - (unless (eq (functional-entry-function functional) functional) - (barf "The ENTRY-FUNCTION in ~S isn't a self-pointer." functional))) + (:toplevel + (unless (eq (functional-entry-fun functional) functional) + (barf "The ENTRY-FUN in ~S isn't a self-pointer." functional))) ((nil :escape :cleanup) - (let ((ef (functional-entry-function functional))) + (let ((ef (functional-entry-fun functional))) (when ef - (check-function-reached ef functional) + (check-fun-reached ef functional) (unless (eq (functional-kind ef) :external) - (barf "The ENTRY-FUNCTION in ~S isn't an XEP: ~S." - functional - ef))))) + (barf "The ENTRY-FUN in ~S isn't an XEP: ~S." functional ef))))) (:deleted - (return-from check-function-stuff))) + (return-from check-fun-stuff))) (case (functional-kind functional) - ((nil :optional :external :top-level :escape :cleanup) + ((nil :optional :external :toplevel :escape :cleanup) (when (lambda-p functional) (dolist (fun (lambda-lets functional)) (unless (eq (lambda-home fun) functional) (barf "The home in ~S is not ~S." fun functional)) - (check-function-reached fun functional)) + (check-fun-reached fun functional)) (unless (eq (lambda-home functional) functional) (barf "home not self-pointer in ~S" functional))))) @@ -239,19 +236,19 @@ (barf "HOME in ~S should be ~S." var functional)))) (optional-dispatch (dolist (ep (optional-dispatch-entry-points functional)) - (check-function-reached ep functional)) + (check-fun-reached ep functional)) (let ((more (optional-dispatch-more-entry functional))) - (when more (check-function-reached more functional))) - (check-function-reached (optional-dispatch-main-entry functional) - functional)))) + (when more (check-fun-reached more functional))) + (check-fun-reached (optional-dispatch-main-entry functional) + functional)))) -(defun check-function-consistency (components) +(defun check-fun-consistency (components) (dolist (c components) - (dolist (fun (component-new-functions c)) - (observe-functional fun)) + (dolist (new-fun (component-new-funs c)) + (observe-functional new-fun)) (dolist (fun (component-lambdas c)) (when (eq (functional-kind fun) :external) - (let ((ef (functional-entry-function fun))) + (let ((ef (functional-entry-fun fun))) (when (optional-dispatch-p ef) (observe-functional ef)))) (observe-functional fun) @@ -259,14 +256,14 @@ (observe-functional let)))) (dolist (c components) - (dolist (fun (component-new-functions c)) - (check-function-stuff fun)) + (dolist (new-fun (component-new-funs c)) + (check-fun-stuff new-fun)) (dolist (fun (component-lambdas c)) (when (eq (functional-kind fun) :deleted) (barf "deleted lambda ~S in Lambdas for ~S" fun c)) - (check-function-stuff fun) + (check-fun-stuff fun) (dolist (let (lambda-lets fun)) - (check-function-stuff let))))) + (check-fun-stuff let))))) ;;;; loop consistency checking @@ -319,9 +316,9 @@ |# -;;; Check a block for consistency at the general flow-graph level, and call -;;; Check-Node-Consistency on each node to locally check for semantic -;;; consistency. +;;; Check a block for consistency at the general flow-graph level, and +;;; call CHECK-NODE-CONSISTENCY on each node to locally check for +;;; semantic consistency. (declaim (ftype (function (cblock) (values)) check-block-consistency)) (defun check-block-consistency (block) @@ -336,7 +333,7 @@ (this-cont (block-start block)) (last (block-last block))) (unless fun-deleted - (check-function-reached fun block)) + (check-fun-reached fun block)) (when (not this-cont) (barf "~S has no START." block)) (when (not last) @@ -413,7 +410,7 @@ (check-block-successors block)) (values)) -;;; Check that Block is properly terminated. Each successor must be +;;; Check that BLOCK is properly terminated. Each successor must be ;;; accounted for by the type of the last node. (declaim (ftype (function (cblock) (values)) check-block-successors)) (defun check-block-successors (block) @@ -459,8 +456,8 @@ ;;;; node consistency checking -;;; Check that the Dest for Cont is the specified Node. We also mark the -;;; block Cont is in as Seen. +;;; Check that the DEST for CONT is the specified NODE. We also mark +;;; the block CONT is in as SEEN. (declaim (ftype (function (continuation node) (values)) check-dest)) (defun check-dest (cont node) (let ((kind (continuation-kind cont))) @@ -479,20 +476,20 @@ (barf "DEST for ~S should be ~S." cont node))))) (values)) -;;; This function deals with checking for consistency the type-dependent -;;; information in a node. +;;; This function deals with checking for consistency of the +;;; type-dependent information in a node. (defun check-node-consistency (node) (declare (type node node)) (etypecase node (ref (let ((leaf (ref-leaf node))) (when (functional-p leaf) - (if (eq (functional-kind leaf) :top-level-xep) + (if (eq (functional-kind leaf) :toplevel-xep) (unless (eq (component-kind (block-component (node-block node))) - :top-level) - (barf ":TOP-LEVEL-XEP ref in non-top-level component: ~S" + :toplevel) + (barf ":TOPLEVEL-XEP ref in non-top-level component: ~S" node)) - (check-function-reached leaf node))))) + (check-fun-reached leaf node))))) (basic-combination (check-dest (basic-combination-fun node) node) (dolist (arg (basic-combination-args node)) @@ -502,13 +499,20 @@ (combination-p node))) (barf "flushed arg not in local call: ~S" node)) (t - (let ((fun (ref-leaf (continuation-use - (basic-combination-fun node)))) - (pos (position arg (basic-combination-args node)))) - (check-type pos fixnum) ; to suppress warning -- WHN 19990311 - (when (leaf-refs (elt (lambda-vars fun) pos)) - (barf "flushed arg for referenced var in ~S" node)))))) - + (locally + ;; KLUDGE: In sbcl-0.6.11.37, the compiler doesn't like + ;; (DECLARE (TYPE INDEX POS)) after the inline expansion of + ;; POSITION. It compiles it correctly, but it issues a type + ;; mismatch warning because it can't eliminate the + ;; possibility that control will flow through the + ;; NIL-returning branch. So we punt here. -- WHN 2001-04-15 + (declare (notinline position)) + (let ((fun (ref-leaf (continuation-use + (basic-combination-fun node)))) + (pos (position arg (basic-combination-args node)))) + (declare (type index pos)) + (when (leaf-refs (elt (lambda-vars fun) pos)) + (barf "flushed arg for referenced var in ~S" node))))))) (let ((dest (continuation-dest (node-cont node)))) (when (and (return-p dest) (eq (basic-combination-kind node) :local) @@ -523,9 +527,9 @@ (cset (check-dest (set-value node) node)) (bind - (check-function-reached (bind-lambda node) node)) + (check-fun-reached (bind-lambda node) node)) (creturn - (check-function-reached (return-lambda node) node) + (check-fun-reached (return-lambda node) node) (check-dest (return-result node) node) (unless (eq (block-last (node-block node)) node) (barf "RETURN not at block end: ~S" node))) @@ -564,10 +568,10 @@ (num 0 (1+ num))) ((null ref) (when (< num count) - (barf "There should be at least ~D ~A in ~S, but are only ~D." + (barf "There should be at least ~W ~A in ~S, but there are only ~W." count what vop num)) (when (and (not more-p) (> num count)) - (barf "There should be ~D ~A in ~S, but are ~D." + (barf "There should be ~W ~A in ~S, but are ~W." count what vop num))) (unless (eq (tn-ref-vop ref) vop) (barf "VOP is ~S isn't ~S." ref vop)) @@ -639,9 +643,9 @@ (atypes (template-arg-types info)) (rtypes (template-result-types info))) (check-tn-refs (vop-args vop) vop nil - (count-if-not #'(lambda (x) - (and (consp x) - (eq (car x) :constant))) + (count-if-not (lambda (x) + (and (consp x) + (eq (car x) :constant))) atypes) (template-more-args-type info) "args") (check-tn-refs (vop-results vop) vop t @@ -710,8 +714,8 @@ (incf const)) (format stream - "~%TNs: ~D local, ~D temps, ~D constant, ~D env, ~D comp, ~D global.~@ - Wired: ~D, Unused: ~D. ~D block~:P, ~D global conflict~:P.~%" + "~%TNs: ~W local, ~W temps, ~W constant, ~W env, ~W comp, ~W global.~@ + Wired: ~W, Unused: ~W. ~W block~:P, ~W global conflict~:P.~%" local temps const environment comp global wired unused (ir2-block-count component) confs)) @@ -816,21 +820,18 @@ (barf "strange TN ~S in LTN map for ~S" tn block))))))) ;;; All TNs live at the beginning of an environment must be passing -;;; locations associated with that environment. We make an exception for wired -;;; TNs in XEP functions, since we randomly reference wired TNs to access the -;;; full call passing locations. +;;; locations associated with that environment. We make an exception +;;; for wired TNs in XEP functions, since we randomly reference wired +;;; TNs to access the full call passing locations. (defun check-environment-lifetimes (component) (dolist (fun (component-lambdas component)) - (let* ((env (lambda-environment fun)) - (2env (environment-info env)) + (let* ((env (lambda-physenv fun)) + (2env (physenv-info env)) (vars (lambda-vars fun)) - (closure (ir2-environment-environment 2env)) - (pc (ir2-environment-return-pc-pass 2env)) - (fp (ir2-environment-old-fp 2env)) - (2block (block-info - (node-block - (lambda-bind - (environment-function env)))))) + (closure (ir2-physenv-closure 2env)) + (pc (ir2-physenv-return-pc-pass 2env)) + (fp (ir2-physenv-old-fp 2env)) + (2block (block-info (lambda-block (physenv-lambda env))))) (do ((conf (ir2-block-global-tns 2block) (global-conflicts-next conf))) ((null conf)) @@ -838,16 +839,16 @@ (unless (or (eq (global-conflicts-kind conf) :write) (eq tn pc) (eq tn fp) - (and (external-entry-point-p fun) - (tn-offset tn)) + (and (xep-p fun) (tn-offset tn)) (member (tn-kind tn) '(:environment :debug-environment)) (member tn vars :key #'leaf-info) (member tn closure :key #'cdr)) (barf "strange TN live at head of ~S: ~S" env tn)))))) (values)) -;;; Check for some basic sanity in the TN conflict data structures, and also -;;; check that no TNs are unexpectedly live at environment entry. +;;; Check for some basic sanity in the TN conflict data structures, +;;; and also check that no TNs are unexpectedly live at environment +;;; entry. (defun check-life-consistency (component) (check-tn-conflicts component) (check-block-conflicts component) @@ -899,26 +900,16 @@ (def-frob *tn-id* *tn-ids* *id-tns* tn-id id-tn) (def-frob *label-id* *id-labels* *label-ids* label-id id-label)) -;;; Print out a terse one-line description of a leaf. +;;; Print a terse one-line description of LEAF. (defun print-leaf (leaf &optional (stream *standard-output*)) (declare (type leaf leaf) (type stream stream)) (etypecase leaf - (lambda-var (prin1 (leaf-name leaf) stream)) + (lambda-var (prin1 (leaf-debug-name leaf) stream)) (constant (format stream "'~S" (constant-value leaf))) (global-var - (format stream "~S {~A}" (leaf-name leaf) (global-var-kind leaf))) - (clambda - (format stream "lambda ~S ~S" (leaf-name leaf) - (mapcar #'leaf-name (lambda-vars leaf)))) - (optional-dispatch - (format stream "optional-dispatch ~S" (leaf-name leaf))) + (format stream "~S {~A}" (leaf-debug-name leaf) (global-var-kind leaf))) (functional - (assert (eq (functional-kind leaf) :top-level-xep)) - (format stream "TL-XEP ~S" - (let ((info (leaf-info leaf))) - (etypecase info - (entry-info (entry-info-name info)) - (byte-lambda-info :byte-compiled-entry))))))) + (format stream "~S ~S" (type-of leaf) (functional-debug-name leaf))))) ;;; Attempt to find a block given some thing that has to do with it. (declaim (ftype (function (t) cblock) block-or-lose)) @@ -933,7 +924,7 @@ (component (component-head thing)) #| (cloop (loop-head thing))|# (integer (continuation-block (num-cont thing))) - (functional (node-block (lambda-bind (main-entry thing)))) + (functional (lambda-block (main-entry thing))) (null (error "Bad thing: ~S." thing)) (symbol (block-or-lose (gethash thing *free-functions*))))) @@ -943,8 +934,8 @@ (format t " c~D" (cont-num cont)) (values)) -;;; Print out the nodes in Block in a format oriented toward representing -;;; what the code does. +;;; Print out the nodes in BLOCK in a format oriented toward +;;; representing what the code does. (defun print-nodes (block) (setq block (block-or-lose block)) (format t "~%block start c~D" (cont-num (block-start block))) @@ -996,7 +987,7 @@ (let ((succ (block-succ block))) (format t "successors~{ c~D~}~%" - (mapcar #'(lambda (x) (cont-num (block-start x))) succ))) + (mapcar (lambda (x) (cont-num (block-start x))) succ))) (values)) ;;; Print a useful representation of a TN. If the TN has a leaf, then do a @@ -1067,10 +1058,11 @@ (vop-next vop)) (number 0 (1+ number))) ((null vop)) - (format t "~D: " number) + (format t "~W: " number) (print-vop vop))) -;;; Like Print-Nodes, but dumps the IR2 representation of the code in Block. +;;; This is like PRINT-NODES, but dumps the IR2 representation of the +;;; code in BLOCK. (defun print-vops (block) (setq block (block-or-lose block)) (let ((2block (block-info block))) @@ -1086,8 +1078,8 @@ (print-ir2-block block)) (values)) -;;; Do a Print-Nodes on Block and all blocks reachable from it by successor -;;; links. +;;; Do a PRINT-NODES on BLOCK and all blocks reachable from it by +;;; successor links. (defun print-blocks (block) (setq block (block-or-lose block)) (do-blocks (block (block-component block) :both) @@ -1102,7 +1094,7 @@ (walk block)) (values)) -;;; Print all blocks in Block's component in DFO. +;;; Print all blocks in BLOCK's component in DFO. (defun print-all-blocks (thing) (do-blocks (block (block-component (block-or-lose thing))) (handler-case (print-nodes block) @@ -1112,7 +1104,7 @@ (defvar *list-conflicts-table* (make-hash-table :test 'eq)) -;;; Add all Always-Live TNs in Block to the conflicts. TN is ignored when +;;; Add all ALWAYS-LIVE TNs in Block to the conflicts. TN is ignored when ;;; it appears in the global conflicts. (defun add-always-live-tns (block tn) (declare (type ir2-block block) (type tn tn)) @@ -1136,19 +1128,18 @@ ;;; Make a list out of all of the recorded conflicts. (defun listify-conflicts-table () (collect ((res)) - (maphash #'(lambda (k v) - (declare (ignore v)) - (when k - (res k))) + (maphash (lambda (k v) + (declare (ignore v)) + (when k + (res k))) *list-conflicts-table*) (clrhash *list-conflicts-table*) (res))) +;;; Return a list of a the TNs that conflict with TN. Sort of, kind +;;; of. For debugging use only. Probably doesn't work on :COMPONENT TNs. (defun list-conflicts (tn) - #!+sb-doc - "Return a list of a the TNs that conflict with TN. Sort of, kind of. For - debugging use only. Probably doesn't work on :COMPONENT TNs." - (assert (member (tn-kind tn) '(:normal :environment :debug-environment))) + (aver (member (tn-kind tn) '(:normal :environment :debug-environment))) (let ((confs (tn-global-conflicts tn))) (cond (confs (clrhash *list-conflicts-table*)