home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / compiler / debug.lisp < prev    next >
Encoding:
Text File  |  1992-04-03  |  43.2 KB  |  1,340 lines

  1. ;;; -*- Package: C; Log: C.Log -*-
  2. ;;;
  3. ;;; **********************************************************************
  4. ;;; This code was written as part of the CMU Common Lisp project at
  5. ;;; Carnegie Mellon University, and has been placed in the public domain.
  6. ;;; If you want to use this code or any part of CMU Common Lisp, please contact
  7. ;;; Scott Fahlman or slisp-group@cs.cmu.edu.
  8. ;;;
  9. (ext:file-comment
  10.   "$Header: debug.lisp,v 1.18 92/04/02 15:30:34 ram Exp $")
  11. ;;;
  12. ;;; **********************************************************************
  13. ;;;
  14. ;;;    Utilities for debugging the compiler.  Currently contains only stuff for
  15. ;;; checking the consistency of the IR1.
  16. ;;; 
  17. ;;; Written by Rob MacLachlan
  18. ;;;
  19. (in-package 'c)
  20.  
  21. (defvar *args* ()
  22.   "This variable is bound to the format arguments when an error is signalled
  23.   by Barf or Burp.")
  24.  
  25. ;;; Barf  --  Interface
  26. ;;;
  27. ;;;    A definite inconsistency has been detected.  Signal an error with
  28. ;;; *args* bound to the list of the format args.
  29. ;;;
  30. (proclaim '(function barf (string &rest t) void))
  31. (defun barf (string &rest *args*)
  32.   (apply #'cerror "Skip this error." string *args*))
  33.  
  34. (defvar *burp-action* :warn
  35.   "Action taken by the Burp function when a possible compiler bug is detected.
  36.   One of :Warn, :Error or :None.")
  37.  
  38. (proclaim '(type (member :warn :error :none) *burp-action*))
  39.  
  40. ;;; Burp  --  Interface
  41. ;;;
  42. ;;;    Called when something funny but possibly correct is noticed.  Otherwise
  43. ;;; similar to Barf.
  44. ;;;
  45. (proclaim '(function burp (string &rest t) void))
  46. (defun burp (string &rest *args*)
  47.   (ecase *burp-action*
  48.     (:warn (apply #'warn string *args*))
  49.     (:error (apply #'cerror "press on anyway." string *args*))
  50.     (:none)))
  51.  
  52.  
  53. ;;; *Seen-Blocks* is a hashtable with true values for all blocks which appear
  54. ;;; in the DFO for one of the specified components.
  55. ;;;
  56. (defvar *seen-blocks* (make-hash-table :test #'eq))
  57.  
  58. ;;; *Seen-Functions* is similar, but records all the lambdas we reached by
  59. ;;; recursing on top-level functions.
  60. ;;;
  61. (defvar *seen-functions* (make-hash-table :test #'eq))
  62.  
  63.  
  64. ;;; Check-Node-Reached  --  Internal
  65. ;;;
  66. ;;;    Barf if Node is in a block which wasn't reached during the graph
  67. ;;; walk.
  68. ;;;
  69. (proclaim '(function check-node-reached (node) void))
  70. (defun check-node-reached (node)
  71.   (unless (gethash (continuation-block (node-prev node)) *seen-blocks*)
  72.     (barf "~S was not reached." node)))
  73.  
  74.  
  75. ;;; Check-IR1-Consistency  --  Interface
  76. ;;;
  77. ;;;    Check everything that we can think of for consistency.  When a definite
  78. ;;; inconsistency is detected, we Barf.  Possible problems just cause us to
  79. ;;; Burp.  Our argument is a list of components, but we also look at the
  80. ;;; *free-variables*, *free-functions* and *constants*.
  81. ;;;
  82. ;;;    First we do a pre-pass which finds all the blocks and lambdas, testing
  83. ;;; that they are linked together properly and entering them in hashtables.
  84. ;;; Next, we iterate over the blocks again, looking at the actual code and
  85. ;;; control flow.  Finally, we scan the global leaf hashtables, looking for
  86. ;;; lossage.
  87. ;;;
  88. (proclaim '(function check-ir1-consistency (list) void))
  89. (defun check-ir1-consistency (components)
  90.   (clrhash *seen-blocks*)
  91.   (clrhash *seen-functions*)
  92.   (dolist (c components)
  93.     (let* ((head (component-head c))
  94.        (tail (component-tail c)))
  95.       (unless (and (null (block-pred head)) (null (block-succ tail)))
  96.     (barf "~S malformed." c))
  97.  
  98.       (do ((prev nil block)
  99.        (block head (block-next block)))
  100.       ((null block)
  101.        (unless (eq prev tail)
  102.          (barf "Wrong Tail for DFO, ~S in ~S." prev c)))
  103.     (setf (gethash block *seen-blocks*) t)
  104.     (unless (eq (block-prev block) prev)
  105.       (barf "Bad Prev for ~S, should be ~S." block prev))
  106.     (unless (or (eq block tail)
  107.             (eq (block-component block) c))
  108.       (barf "~S is not in ~S." block c)))
  109. #|
  110.       (when (or (loop-blocks c) (loop-inferiors c))
  111.     (do-blocks (block c :both)
  112.       (setf (block-flag block) nil))
  113.     (check-loop-consistency c nil)
  114.     (do-blocks (block c :both)
  115.       (unless (block-flag block)
  116.         (barf "~S was not in any loop." block))))
  117. |#
  118.     ))
  119.  
  120.   (check-function-consistency components)
  121.  
  122.   (dolist (c components)
  123.     (do ((block (block-next (component-head c)) (block-next block)))
  124.     ((null (block-next block)))
  125.       (check-block-consistency block)))
  126.  
  127.       
  128.   (maphash #'(lambda (k v)
  129.            (declare (ignore k))
  130.            (unless (or (constant-p v)
  131.                (and (global-var-p v)
  132.                 (member (global-var-kind v)
  133.                     '(:global :special :constant))))
  134.          (barf "Strange *free-variables* entry: ~S." v))
  135.            (dolist (n (leaf-refs v))
  136.          (check-node-reached n))
  137.            (when (basic-var-p v)
  138.          (dolist (n (basic-var-sets v))
  139.            (check-node-reached n))))
  140.        *free-variables*)
  141.  
  142.   (maphash #'(lambda (k v)
  143.            (declare (ignore k))
  144.            (unless (constant-p v)
  145.          (barf "Strange *constants* entry: ~S." v))
  146.            (dolist (n (leaf-refs v))
  147.          (check-node-reached n)))
  148.        *constants*)
  149.  
  150.   (maphash #'(lambda (k v)
  151.            (declare (ignore k))
  152.            (unless (or (functional-p v)
  153.                (and (global-var-p v)
  154.                 (eq (global-var-kind v) :global-function)))
  155.          (barf "Strange *free-functions* entry: ~S." v))
  156.            (dolist (n (leaf-refs v))
  157.          (check-node-reached n)))
  158.        *free-functions*)
  159.   (clrhash *seen-functions*)
  160.   (clrhash *seen-blocks*)
  161.   (values))
  162.  
  163.  
  164. ;;;; Function consistency checking:
  165.  
  166. ;;; Observe-Functional  --  Internal
  167. ;;;
  168. (defun observe-functional (x)
  169.   (declare (type functional x))
  170.   (when (gethash x *seen-functions*)
  171.     (barf "~S seen more than once." x))
  172.   (unless (eq (functional-kind x) :deleted)
  173.     (setf (gethash x *seen-functions*) t)))
  174.  
  175.  
  176. ;;; Check-Function-Reached  --  Internal
  177. ;;;
  178. ;;;    Check that the specified function has been seen. 
  179. ;;;
  180. (defun check-function-reached (fun where)
  181.   (declare (type functional fun))
  182.   (unless (gethash fun *seen-functions*)
  183.     (barf "Unseen function ~S in ~S." fun where)))
  184.  
  185.  
  186. ;;; Check-Function-Stuff  --  Internal
  187. ;;;
  188. ;;;    In a lambda, check that the associated nodes are in seen blocks.  In an
  189. ;;; optional dispatch, check that the entry points were seen.  If the function
  190. ;;; is deleted, ignore it.
  191. ;;;
  192. (defun check-function-stuff (functional)
  193.   (ecase (functional-kind functional)
  194.     (:external
  195.      (let ((fun (functional-entry-function functional)))
  196.        (check-function-reached fun functional)
  197.        (when (functional-kind fun)
  198.      (barf "Function for XEP ~S has kind." functional))
  199.        (unless (eq (functional-entry-function fun) functional)
  200.      (barf "Bad back-pointer in function for XEP ~S." functional))))
  201.     ((:let :mv-let :assignment)
  202.      (check-function-reached (lambda-home functional) functional)
  203.      (when (functional-entry-function functional)
  204.        (barf "Let ~S has entry function." functional))
  205.      (unless (member functional (lambda-lets (lambda-home functional)))
  206.        (barf "Let ~S not in Lets for Home." functional))
  207.      (unless (eq (functional-kind functional) :assignment)
  208.        (when (rest (leaf-refs functional))
  209.      (barf "Let ~S has multiple refernces." functional)))
  210.      (when (lambda-lets functional)
  211.        (barf "Lets in a Let: ~S." functional)))
  212.     (:optional
  213.      (when (functional-entry-function functional)
  214.        (barf ":Optional ~S has an ENTRY-FUNCTION." functional))
  215.      (let ((ef (lambda-optional-dispatch functional)))
  216.        (check-function-reached ef functional)
  217.        (unless (or (member functional (optional-dispatch-entry-points ef))
  218.            (eq functional (optional-dispatch-more-entry ef))
  219.            (eq functional (optional-dispatch-main-entry ef)))
  220.      (barf ":Optional ~S not an e-p for its OPTIONAL-DISPATCH ~S." 
  221.            functional ef))))
  222.     (:top-level
  223.      (unless (eq (functional-entry-function functional) functional)
  224.        (barf "Entry-Function is ~S isn't a self-pointer." functional)))
  225.     ((nil :escape :cleanup)
  226.      (let ((ef (functional-entry-function functional)))
  227.        (when ef
  228.      (check-function-reached ef functional)
  229.      (unless (eq (functional-kind ef) :external)
  230.        (barf "Entry-Function in ~S isn't an XEP: ~S." functional ef)))))
  231.     (:deleted
  232.      (return-from check-function-stuff)))
  233.  
  234.   (case (functional-kind functional)
  235.     ((nil :optional :external :top-level :escape :cleanup)
  236.      (when (lambda-p functional)
  237.        (dolist (fun (lambda-lets functional))
  238.      (unless (eq (lambda-home fun) functional)
  239.        (barf "Home in ~S not ~S." fun functional))
  240.      (check-function-reached fun functional))
  241.        (unless (eq (lambda-home functional) functional)
  242.      (barf "Home not self-pointer in ~S." functional)))))
  243.        
  244.   (etypecase functional
  245.     (clambda
  246.      (when (lambda-bind functional)
  247.        (check-node-reached (lambda-bind functional)))
  248.      (when (lambda-return functional)
  249.        (check-node-reached (lambda-return functional)))
  250.      
  251.      (dolist (var (lambda-vars functional))
  252.        (dolist (ref (leaf-refs var))
  253.      (check-node-reached ref))
  254.        (dolist (set (basic-var-sets var))
  255.      (check-node-reached set))
  256.        (unless (eq (lambda-var-home var) functional)
  257.      (barf "HOME in ~S should be ~S." var functional))))
  258.     (optional-dispatch
  259.      (dolist (ep (optional-dispatch-entry-points functional))
  260.        (check-function-reached ep functional))
  261.      (let ((more (optional-dispatch-more-entry functional)))
  262.        (when more (check-function-reached more functional)))
  263.      (check-function-reached (optional-dispatch-main-entry functional)
  264.                  functional)))))
  265.  
  266.  
  267. ;;; Check-Function-Consistency  --  Internal
  268. ;;;
  269. (defun check-function-consistency (components)
  270.   (dolist (c components)
  271.     (dolist (fun (component-new-functions c))
  272.       (observe-functional fun))
  273.     (dolist (fun (component-lambdas c))
  274.       (when (eq (functional-kind fun) :external)
  275.     (let ((ef (functional-entry-function fun)))
  276.       (when (optional-dispatch-p ef)
  277.         (observe-functional ef))))
  278.       (observe-functional fun)
  279.       (dolist (let (lambda-lets fun))
  280.     (observe-functional let))))
  281.  
  282.   (dolist (c components)
  283.     (dolist (fun (component-new-functions c))
  284.       (check-function-stuff fun))
  285.     (dolist (fun (component-lambdas c))
  286.       (when (eq (functional-kind fun) :deleted)
  287.     (barf "Deleted lambda ~S in Lambdas for ~S." fun c))
  288.       (check-function-stuff fun)
  289.       (dolist (let (lambda-lets fun))
  290.     (check-function-stuff let)))))
  291.  
  292.  
  293. ;;;; Loop consistency checking:
  294.  
  295. #|
  296. ;;; Check-Loop-Consistency  --  Internal
  297. ;;;
  298. ;;;    Descend through the loop nesting and check that the tree is well-formed
  299. ;;; and that all blocks in the loops are known blocks.  We also mark each block
  300. ;;; that we see so that we can do a check later to detect blocks that weren't
  301. ;;; in any loop.
  302. ;;;
  303. (proclaim '(function check-loop-consistency (loop (or loop null)) void))
  304. (defun check-loop-consistency (loop superior)
  305.   (unless (eq (loop-superior loop) superior)
  306.     (barf "Wrong superior in ~S, should be ~S." loop superior))
  307.   (when (and superior
  308.          (/= (loop-depth loop) (1+ (loop-depth superior))))
  309.     (barf "Wrong depth in ~S." loop))
  310.  
  311.   (dolist (tail (loop-tail loop))
  312.     (check-loop-block tail loop))
  313.   (dolist (exit (loop-exits loop))
  314.     (check-loop-block exit loop))
  315.   (check-loop-block (loop-head loop) loop)
  316.   (unless (eq (block-loop (loop-head loop)) loop)
  317.     (barf "Head of ~S is not directly in the loop." loop))
  318.  
  319.   (do ((block (loop-blocks loop) (block-loop-next block)))
  320.       ((null block))
  321.     (setf (block-flag block) t)
  322.     (unless (gethash block *seen-blocks*)
  323.       (barf "Unseen block ~S in Blocks for ~S." block loop))
  324.     (unless (eq (block-loop block) loop)
  325.       (barf "Wrong Loop in ~S, should be ~S." block loop)))
  326.  
  327.   (dolist (inferior (loop-inferiors loop))
  328.     (check-loop-consistency inferior loop)))
  329.  
  330.  
  331. ;;; Check-Loop-Block  --  Internal
  332. ;;;
  333. ;;;    Check that Block is either in Loop or an inferior.
  334. ;;;
  335. (proclaim '(function check-loop-block (block loop) void))
  336. (defun check-loop-block (block loop)
  337.   (unless (gethash block *seen-blocks*)
  338.     (barf "Unseen block ~S in loop info for ~S." block loop))
  339.   (labels ((walk (l)
  340.          (if (eq (block-loop block) l)
  341.          t
  342.          (dolist (inferior (loop-inferiors l) nil)
  343.            (when (walk inferior) (return t))))))
  344.     (unless (walk loop)
  345.       (barf "~S in loop info for ~S but not in the loop." block loop))))
  346.  
  347. |#
  348.  
  349.  
  350. ;;; Check-Block-Consistency  --  Internal
  351. ;;;
  352. ;;;    Check a block for consistency at the general flow-graph level, and call
  353. ;;; Check-Node-Consistency on each node to locally check for semantic
  354. ;;; consistency.
  355. ;;;
  356. (proclaim '(function check-block-consistency (cblock) void))
  357. (defun check-block-consistency (block)
  358.  
  359.   (dolist (pred (block-pred block))
  360.     (unless (gethash pred *seen-blocks*)
  361.       (barf "Unseen predecessor ~S in ~S." pred block))
  362.     (unless (member block (block-succ pred))
  363.       (barf "Bad predecessor link ~S in ~S." pred block)))
  364.  
  365.   (let* ((fun (block-home-lambda block))
  366.      (fun-deleted (eq (functional-kind fun) :deleted))
  367.      (this-cont (block-start block))
  368.      (last (block-last block)))
  369.     (unless fun-deleted
  370.       (check-function-reached fun block))
  371.     (when (not this-cont)
  372.       (barf "~S has no START." block))
  373.     (when (not last)
  374.       (barf "~S has no LAST." block))
  375.     (unless (eq (continuation-kind this-cont) :block-start)
  376.       (barf "Start of ~S has wrong kind." block))
  377.  
  378.     (let ((use (continuation-use this-cont))
  379.       (uses (block-start-uses block)))
  380.       (when (and (null use) (= (length uses) 1))
  381.     (barf "~S has unique use, but no USE." this-cont))
  382.       (dolist (node uses)
  383.     (unless (eq (node-cont node) this-cont)
  384.       (barf "Use ~S for START in ~S has wrong CONT." node block))
  385.     (check-node-reached node)))
  386.  
  387.     (let* ((last-cont (node-cont last))
  388.        (cont-block (continuation-block last-cont))
  389.        (dest (continuation-dest last-cont)))
  390.       (ecase (continuation-kind last-cont)
  391.     (:deleted)
  392.     (:deleted-block-start
  393.      (let ((dest (continuation-dest last-cont)))
  394.        (when dest
  395.          (check-node-reached dest)))
  396.      (unless (member last (block-start-uses cont-block))
  397.        (barf "Last in ~S is missing from uses of it's Cont." block)))
  398.     (:block-start
  399.      (check-node-reached (continuation-next last-cont))
  400.      (unless (member last (block-start-uses cont-block))
  401.        (barf "Last in ~S is missing from uses of it's Cont." block)))
  402.     (:inside-block
  403.      (unless (eq cont-block block)
  404.        (barf "Cont of Last in ~S is in a different block." block))
  405.      (unless (eq (continuation-use last-cont) last)
  406.        (barf "Use is not Last in Cont of Last in ~S." block))
  407.      (when (continuation-next last-cont)
  408.        (barf "Cont of Last has a Next in ~S." block))))
  409.  
  410.       (when dest
  411.     (check-node-reached dest)))
  412.  
  413.     (loop    
  414.       (unless (eq (continuation-block this-cont) block)
  415.     (barf "BLOCK in ~S should be ~S." this-cont block))
  416.       
  417.       (let ((dest (continuation-dest this-cont)))
  418.     (when dest
  419.       (check-node-reached dest)))
  420.       
  421.       (let ((node (continuation-next this-cont)))
  422.     (unless (node-p node)
  423.       (barf "~S has strange next." this-cont))
  424.     (unless (eq (node-prev node) this-cont)
  425.       (barf "PREV in ~S should be ~S." node this-cont))
  426.  
  427.     (unless fun-deleted
  428.       (check-node-consistency node))
  429.     
  430.     (let ((cont (node-cont node)))
  431.       (when (not cont)
  432.         (barf "~S has no CONT." node))
  433.       (when (eq node last) (return))
  434.       (unless (eq (continuation-kind cont) :inside-block)
  435.         (barf "Interior continuation ~S in ~S has wrong kind." cont block))
  436.       (unless (continuation-next cont)
  437.         (barf "~S has no NEXT." cont))
  438.       (unless (eq (continuation-use cont) node)
  439.         (barf "USE in ~S should be ~S." cont node))
  440.       (setq this-cont cont))))
  441.     
  442.     (check-block-successors block)))
  443.  
  444.  
  445. ;;; Check-Block-Successors  --  Internal
  446. ;;;
  447. ;;;    Check that Block is properly terminated.  Each successor must be
  448. ;;; accounted for by the type of the last node.
  449. ;;;
  450. (proclaim '(function check-block-successors (cblock) void))
  451. (defun check-block-successors (block)
  452.   (let ((last (block-last block))
  453.     (succ (block-succ block)))
  454.  
  455.     (let* ((comp (block-component block))
  456.        (tail (component-tail comp)))
  457.       (dolist (b succ)
  458.     (unless (gethash b *seen-blocks*)
  459.       (barf "Unseen successor ~S in ~S." b block))
  460.     (unless (member block (block-pred b))
  461.       (barf "Bad successor link ~S in ~S." b block))
  462.     (unless (eq (block-component b) comp)
  463.       (barf "Successor ~S in ~S is in a different component." b block))
  464.     (unless (or (not (eq b tail))
  465.             (typep last '(or creturn exit))
  466.             (and (basic-combination-p last)
  467.              (or (node-tail-p last)
  468.                  (eq (node-derived-type last) *empty-type*)
  469.                  (eq (continuation-asserted-type (node-cont last))
  470.                  *empty-type*))))
  471.       (barf "Component tail is successor of ~S when it shouldn't be."
  472.         block))))
  473.     
  474.     (typecase last
  475.       (cif
  476.        (unless (<= 1 (length succ) 2)
  477.      (barf "~S ends in an IF, but doesn't have one or two succesors."
  478.            block))
  479.        (unless (member (if-consequent last) succ) 
  480.      (barf "CONSEQUENT for ~S isn't in SUCC for ~S." last block))
  481.        (unless (member (if-alternative last) succ)
  482.      (barf "ALTERNATIVE for ~S isn't in SUCC for ~S." last block)))
  483.       (creturn
  484.        (unless (if (eq (functional-kind (return-lambda last)) :deleted)
  485.            (null succ)
  486.            (and (= (length succ) 1)
  487.             (eq (first succ)
  488.                 (component-tail (block-component block)))))
  489.      (barf "Strange successors for RETURN in ~S." block)))
  490.       (exit
  491.        (unless (<= (length succ) 1)
  492.      (barf "EXIT node has strange number of successors: ~S." last)))
  493.       (t
  494.        (unless (or (= (length succ) 1) (node-tail-p last)
  495.            (and (block-delete-p block) (null succ)))
  496.      (barf "~S ends in normal node, but doesn't have one successor."
  497.            block))))))
  498.  
  499.  
  500. ;;;; Node consistency checking:
  501.  
  502. ;;; Check-Dest  --  Internal
  503. ;;;
  504. ;;;    Check that the Dest for Cont is the specified Node.  We also mark the
  505. ;;; block Cont is in as Seen.
  506. ;;;
  507. (proclaim '(function check-dest (continuation node) void))
  508. (defun check-dest (cont node)
  509.   (let ((kind (continuation-kind cont)))
  510.     (ecase kind
  511.       (:deleted
  512.        (unless (block-delete-p (node-block node))
  513.      (barf "DEST ~S of deleted continuation ~S is not DELETE-P."
  514.            cont node)))
  515.       (:deleted-block-start
  516.        (unless (eq (continuation-dest cont) node)
  517.      (barf "DEST for ~S should be ~S." cont node)))
  518.       ((:inside-block :block-start)
  519.        (unless (gethash (continuation-block cont) *seen-blocks*)
  520.      (barf "~S receives ~S, which is in an unknown block." node cont))
  521.        (unless (eq (continuation-dest cont) node)
  522.      (barf "DEST for ~S should be ~S." cont node))))))
  523.  
  524.  
  525. ;;; Check-Node-Consistency  --  Internal
  526. ;;;
  527. ;;;    This function deals with checking for consistency the type-dependent
  528. ;;; information in a node.
  529. ;;;
  530. (defun check-node-consistency (node)
  531.   (declare (type node node))
  532.   (etypecase node
  533.     (ref
  534.      (let ((leaf (ref-leaf node)))
  535.        (when (functional-p leaf)
  536.      (if (eq (functional-kind leaf) :top-level-xep)
  537.          (unless (eq (component-kind (block-component (node-block node)))
  538.              :top-level)
  539.            (barf ":TOP-LEVEL-XEP ref in non-top-level component: ~S."
  540.              node))
  541.          (check-function-reached leaf node)))))
  542.     (basic-combination
  543.      (check-dest (basic-combination-fun node) node)
  544.      (dolist (arg (basic-combination-args node))
  545.        (cond
  546.     (arg (check-dest arg node))
  547.     ((not (and (eq (basic-combination-kind node) :local)
  548.            (combination-p node)))
  549.      (barf "Flushed arg not in local call: ~S." node))
  550.     (t
  551.      (let ((fun (ref-leaf (continuation-use
  552.                    (basic-combination-fun node)))))
  553.        (when (leaf-refs (elt (lambda-vars fun)
  554.                  (position arg (basic-combination-args node))))
  555.          (barf "Flushed arg for referenced var in ~S." node)))))))
  556.     (cif
  557.      (check-dest (if-test node) node)
  558.      (unless (eq (block-last (node-block node)) node)
  559.        (barf "IF not at block end: ~S" node)))
  560.     (cset
  561.      (check-dest (set-value node) node))
  562.     (bind
  563.      (check-function-reached (bind-lambda node) node))
  564.     (creturn
  565.      (check-function-reached (return-lambda node) node)
  566.      (check-dest (return-result node) node)
  567.      (unless (eq (block-last (node-block node)) node)
  568.        (barf "RETURN not at block end: ~S" node)))
  569.     (entry
  570.      (unless (member node (lambda-entries (node-home-lambda node)))
  571.        (barf "~S not in Entries for its home lambda." node))
  572.      (dolist (exit (entry-exits node))
  573.        (unless (node-deleted exit)
  574.      (check-node-reached node))))
  575.     (exit
  576.      (let ((entry (exit-entry node))
  577.        (value (exit-value node)))
  578.        (cond (entry
  579.           (check-node-reached entry)
  580.           (unless (member node (entry-exits entry))
  581.         (barf "~S not in its ENTRY's EXITS." node))
  582.           (when value
  583.         (check-dest value node)))
  584.          (t
  585.           (when value
  586.         (barf "~S has VALUE but no ENTRY." node)))))))
  587.        
  588.   (undefined-value))
  589.  
  590.  
  591. ;;;; IR2 consistency checking:
  592.  
  593.  
  594. ;;; Check-TN-Refs  --  Internal
  595. ;;;
  596. ;;;    Check for some kind of consistency in some Refs linked together by
  597. ;;; TN-Ref-Across.  VOP is the VOP that the references are in.  Write-P is the
  598. ;;; value of Write-P that should be present.  Count is the minimum number of
  599. ;;; operands expected.  If More-P is true, then any larger number will also be
  600. ;;; accepted.  What is a string describing the kind of operand in error
  601. ;;; messages.
  602. ;;;
  603. (defun check-tn-refs (refs vop write-p count more-p what)
  604.   (let ((vop-refs (vop-refs vop)))
  605.     (do ((ref refs (tn-ref-across ref))
  606.      (num 0 (1+ num)))
  607.     ((null ref)
  608.      (when (< num count)
  609.        (barf "Should be at least ~D ~A in ~S, but are only ~D."
  610.          count what vop num))
  611.      (when (and (not more-p) (> num count))
  612.        (barf "Should be ~D ~A in ~S, but are ~D."
  613.          count what vop num)))
  614.       (unless (eq (tn-ref-vop ref) vop)
  615.     (barf "VOP is ~S isn't ~S." ref vop))
  616.       (unless (eq (tn-ref-write-p ref) write-p)
  617.     (barf "Write-P in ~S isn't ~S." vop write-p))
  618.       (unless (find-in #'tn-ref-next-ref ref vop-refs)
  619.     (barf "~S not found in Refs for ~S." ref vop))
  620.       (unless (find-in #'tn-ref-next ref
  621.                (if (tn-ref-write-p ref)
  622.                (tn-writes (tn-ref-tn ref))
  623.                (tn-reads (tn-ref-tn ref))))
  624.     (barf "~S not found in reads/writes for its TN." ref))
  625.  
  626.       (let ((target (tn-ref-target ref)))
  627.     (when target
  628.       (unless (eq (tn-ref-write-p target) (not (tn-ref-write-p ref)))
  629.         (barf "Target for ~S isn't complementary write-p." ref))
  630.       (unless (find-in #'tn-ref-next-ref target vop-refs)
  631.         (barf "Target for ~S isn't in Refs for ~S." ref vop)))))))
  632.  
  633.  
  634. ;;; Check-VOP-Refs  --  Internal
  635. ;;;
  636. ;;;    Verify the sanity of the VOP-Refs slot in VOP.  This involves checking
  637. ;;; that each referenced TN appears as an argument, result or temp, and also
  638. ;;; basic checks for the plausibility of the specified ordering of the refs.
  639. ;;; 
  640. (defun check-vop-refs (vop)
  641.   (declare (type vop vop))
  642.   (do ((ref (vop-refs vop) (tn-ref-next-ref ref)))
  643.       ((null ref))
  644.     (cond
  645.      ((find-in #'tn-ref-across ref (vop-args vop)))
  646.      ((find-in #'tn-ref-across ref (vop-results vop)))
  647.      ((not (eq (tn-ref-vop ref) vop))
  648.       (barf "VOP in ~S isn't ~S." ref vop))
  649.      ((find-in #'tn-ref-across ref (vop-temps vop)))
  650.      ((tn-ref-write-p ref)
  651.       (barf "Stray ref that isn't a read: ~S." ref))
  652.      (t
  653.       (let* ((tn (tn-ref-tn ref))
  654.          (temp (find-in #'tn-ref-across tn (vop-temps vop)
  655.                 :key #'tn-ref-tn)))
  656.     (unless temp
  657.       (barf "Stray ref with no corresponding temp write: ~S." ref))
  658.     (unless (find-in #'tn-ref-next-ref temp (tn-ref-next-ref ref))
  659.       (barf "Read is after write for temp ~S in refs of ~S."
  660.         tn vop))))))
  661.   (undefined-value))
  662.  
  663.  
  664. ;;; Check-IR2-Block-Consistency  --  Internal
  665. ;;;
  666. ;;;    Check the basic sanity of the VOP linkage, then call some other
  667. ;;; functions to check on the TN-Refs.  We grab some info out of the VOP-Info
  668. ;;; to tell us what to expect.
  669. ;;; [### Check that operand type restrictions are met?]
  670. ;;;
  671. (defun check-ir2-block-consistency (2block)
  672.   (declare (type ir2-block 2block))
  673.   (do ((vop (ir2-block-start-vop 2block)
  674.         (vop-next vop))
  675.        (prev nil vop))
  676.       ((null vop)
  677.        (unless (eq prev (ir2-block-last-vop 2block))
  678.      (barf "Last VOP in ~S shoule be ~S." 2block prev)))
  679.     (unless (eq (vop-prev vop) prev)
  680.       (barf "Prev in ~S should be ~S." vop prev))
  681.  
  682.     (unless (eq (vop-block vop) 2block)
  683.       (barf "Block in ~S should be ~S." vop 2block))
  684.  
  685.     (check-vop-refs vop)
  686.  
  687.     (let* ((info (vop-info vop))
  688.        (atypes (template-arg-types info))
  689.        (rtypes (template-result-types info)))
  690.       (check-tn-refs (vop-args vop) vop nil
  691.              (count-if-not #'(lambda (x)
  692.                        (and (consp x)
  693.                         (eq (car x) :constant)))
  694.                    atypes)
  695.              (template-more-args-type info) "args")
  696.       (check-tn-refs (vop-results vop) vop t
  697.              (if (eq rtypes :conditional) 0 (length rtypes))
  698.              (template-more-results-type info) "results")
  699.       (check-tn-refs (vop-temps vop) vop t 0 t "temps")
  700.       (unless (= (length (vop-codegen-info vop))
  701.          (template-info-arg-count info))
  702.     (barf "Wrong number of codegen info args in ~S." vop))))
  703.   (undefined-value))
  704.  
  705.  
  706. ;;; Check-IR2-Consistency  --  Interface
  707. ;;;
  708. ;;;    Check stuff about the IR2 representation of Component.  This assumes the
  709. ;;; sanity of the basic flow graph.
  710. ;;;
  711. ;;; [### Also grovel global TN data structures?  Assume pack not
  712. ;;; done yet?  Have separate check-tn-consistency for pre-pack and
  713. ;;; check-pack-consistency for post-pack?]
  714. ;;;
  715. (defun check-ir2-consistency (component)
  716.   (declare (type component component))
  717.   (do-ir2-blocks (block component)
  718.     (check-ir2-block-consistency block))
  719.   (undefined-value))
  720.  
  721.  
  722. ;;;; Lifetime analysis checking:
  723.  
  724. ;;; Pre-Pack-TN-Stats  --  Interface
  725. ;;;
  726. ;;;    Dump some info about how many TNs there, and what the conflicts data
  727. ;;; structures are like.
  728. ;;;
  729. (defun pre-pack-tn-stats (component &optional (stream *compiler-error-output*))
  730.   (declare (type component component))
  731.   (let ((wired 0)
  732.     (global 0)
  733.     (local 0)
  734.     (confs 0)
  735.     (unused 0)
  736.     (const 0)
  737.     (temps 0)
  738.     (environment 0)
  739.     (comp 0))
  740.     (do-packed-tns (tn component)
  741.       (let ((reads (tn-reads tn))
  742.         (writes (tn-writes tn)))
  743.     (when (and reads writes
  744.            (not (tn-ref-next reads)) (not (tn-ref-next writes))
  745.            (eq (tn-ref-vop reads) (tn-ref-vop writes)))
  746.       (incf temps)))
  747.       (when (tn-offset tn)
  748.     (incf wired))
  749.       (unless (or (tn-reads tn) (tn-writes tn))
  750.     (incf unused))
  751.       (cond ((eq (tn-kind tn) :component)
  752.          (incf comp))
  753.         ((tn-global-conflicts tn)
  754.          (case (tn-kind tn)
  755.            ((:environment :debug-environment) (incf environment))
  756.            (t (incf global)))
  757.          (do ((conf (tn-global-conflicts tn)
  758.             (global-conflicts-tn-next conf)))
  759.          ((null conf))
  760.            (incf confs)))
  761.         (t
  762.          (incf local))))
  763.  
  764.     (do ((tn (ir2-component-constant-tns (component-info component))
  765.          (tn-next tn)))
  766.     ((null tn))
  767.       (incf const))
  768.  
  769.     (format stream
  770.      "~%TNs: ~D local, ~D temps, ~D constant, ~D env, ~D comp, ~D global.~@
  771.        Wired: ~D, Unused: ~D.  ~D block~:P, ~D global conflict~:P.~%"
  772.        local temps const environment comp global wired unused
  773.        (ir2-block-count component)
  774.        confs))
  775.   (undefined-value))
  776.  
  777.  
  778. ;;; Check-More-TN-Entry  --  Internal
  779. ;;;
  780. ;;;    If the entry in Local-TNs for TN in Block is :More, then do some checks
  781. ;;; for the validity of the usage.
  782. ;;;
  783. (defun check-more-tn-entry (tn block)
  784.   (let* ((vop (ir2-block-start-vop block))
  785.      (info (vop-info vop)))
  786.     (macrolet ((frob (more-p ops)
  787.          `(and (,more-p info)
  788.                (find-in #'tn-ref-across tn (,ops vop)
  789.                 :key #'tn-ref-tn))))
  790.       (unless (and (eq vop (ir2-block-last-vop block))
  791.            (or (frob template-more-args-type vop-args)
  792.                (frob template-more-results-type vop-results)))
  793.     (barf "Strange :More LTN entry for ~S in ~S." tn block))))
  794.   (undefined-value))
  795.  
  796.  
  797. ;;; Check-TN-Conflicts  --  Internal
  798. ;;;
  799. (defun check-tn-conflicts (component)
  800.   (do-packed-tns (tn component)
  801.     (unless (or (not (eq (tn-kind tn) :normal))
  802.         (tn-reads tn)
  803.         (tn-writes tn))
  804.       (barf "No references to ~S." tn))
  805.  
  806.     (unless (tn-sc tn) (barf "~S has no SC." tn))
  807.  
  808.     (let ((conf (tn-global-conflicts tn))
  809.       (kind (tn-kind tn)))
  810.       (cond
  811.        ((eq kind :component)
  812.     (unless (member tn (ir2-component-component-tns
  813.                 (component-info component)))
  814.       (barf "~S not in Component-TNs for ~S." tn component)))
  815.        (conf
  816.     (do ((conf conf (global-conflicts-tn-next conf))
  817.          (prev nil conf))
  818.         ((null conf))
  819.       (unless (eq (global-conflicts-tn conf) tn)
  820.         (barf "TN in ~S should be ~S." conf tn))
  821.  
  822.       (unless (eq (global-conflicts-kind conf) :live)
  823.         (let* ((block (global-conflicts-block conf))
  824.            (ltn (svref (ir2-block-local-tns block)
  825.                    (global-conflicts-number conf))))
  826.           (cond ((eq ltn tn))
  827.             ((eq ltn :more) (check-more-tn-entry tn block))
  828.             (t
  829.              (barf "~S wrong in LTN map for ~S." conf tn)))))
  830.  
  831.       (when prev
  832.         (unless (> (ir2-block-number (global-conflicts-block conf))
  833.                (ir2-block-number (global-conflicts-block prev)))
  834.           (barf "~S and ~S out of order." prev conf)))))
  835.        ((member (tn-kind tn) '(:constant :specified-save)))
  836.        (t
  837.     (let ((local (tn-local tn)))
  838.       (unless local
  839.         (barf "~S has no global conflicts, but isn't local either." tn))
  840.       (unless (eq (svref (ir2-block-local-tns local)
  841.                  (tn-local-number tn))
  842.               tn)
  843.         (barf "~S wrong in LTN map." tn))
  844.       (do ((ref (tn-reads tn) (tn-ref-next ref)))
  845.           ((null ref))
  846.         (unless (eq (vop-block (tn-ref-vop ref)) local)
  847.           (barf "~S has references in blocks other than its Local block."
  848.             tn)))
  849.       (do ((ref (tn-writes tn) (tn-ref-next ref)))
  850.           ((null ref))
  851.         (unless (eq (vop-block (tn-ref-vop ref)) local)
  852.           (barf "~S has references in blocks other than its Local block."
  853.             tn))))))))
  854.   (undefined-value))
  855.  
  856.  
  857. ;;; Check-Block-Conflicts  --  Internal
  858. ;;;
  859. (defun check-block-conflicts (component)
  860.   (do-ir2-blocks (block component)
  861.     (do ((conf (ir2-block-global-tns block)
  862.            (global-conflicts-next conf))
  863.      (prev nil conf))
  864.     ((null conf))
  865.       (when prev
  866.     (unless (> (tn-number (global-conflicts-tn conf))
  867.            (tn-number (global-conflicts-tn prev)))
  868.       (barf "~S and ~S out of order in ~S." prev conf block)))
  869.       
  870.       (unless (find-in #'global-conflicts-tn-next
  871.                conf
  872.                (tn-global-conflicts
  873.             (global-conflicts-tn conf)))
  874.     (barf "~S missing from global conflicts of its TN." conf)))
  875.     
  876.     (let ((map (ir2-block-local-tns block)))
  877.       (dotimes (i (ir2-block-local-tn-count block))
  878.     (let ((tn (svref map i)))
  879.       (unless (or (eq tn :more)
  880.               (null tn)
  881.               (tn-global-conflicts tn)
  882.               (eq (tn-local tn) block))
  883.         (barf "Strange TN ~S in LTN map for ~S." tn block)))))))))
  884.  
  885.  
  886. ;;; Check-Environment-Lifetimes  --  Internal
  887. ;;;
  888. ;;;    All TNs live at the beginning of an environment must be passing
  889. ;;; locations associated with that environment.  We make an exception for wired
  890. ;;; TNs in XEP functions, since we randomly reference wired TNs to access the
  891. ;;; full call passing locations.
  892. ;;;
  893. (defun check-environment-lifetimes (component)
  894.   (dolist (fun (component-lambdas component))
  895.     (let* ((env (lambda-environment fun))
  896.        (2env (environment-info env))
  897.        (vars (lambda-vars fun))
  898.        (closure (ir2-environment-environment 2env))
  899.        (pc (ir2-environment-return-pc-pass 2env))
  900.        (fp (ir2-environment-old-fp 2env))
  901.        (2block (block-info
  902.             (node-block
  903.              (lambda-bind
  904.               (environment-function env))))))
  905.       (do ((conf (ir2-block-global-tns 2block)
  906.          (global-conflicts-next conf)))
  907.       ((null conf))
  908.     (let ((tn (global-conflicts-tn conf)))
  909.       (unless (or (eq (global-conflicts-kind conf) :write)
  910.               (eq tn pc)
  911.               (eq tn fp)
  912.               (and (external-entry-point-p fun)
  913.                (tn-offset tn))
  914.               (member (tn-kind tn) '(:environment :debug-environment))
  915.               (member tn vars :key #'leaf-info)
  916.               (member tn closure :key #'cdr))
  917.         (barf "Strange TN live at head of ~S: ~S." env tn))))))
  918.   (undefined-value))
  919.  
  920.  
  921. ;;; Check-Life-Consistency  --  Interface
  922. ;;;
  923. ;;;    Check for some basic sanity in the TN conflict data structures, and also
  924. ;;; check that no TNs are unexpectedly live at environment entry.
  925. ;;;
  926. (defun check-life-consistency (component)
  927.   (check-tn-conflicts component)
  928.   (check-block-conflicts component)
  929.   (check-environment-lifetimes component))
  930.  
  931.  
  932. ;;;; Pack consistency checking:
  933.  
  934. ;;; CHECK-PACK-CONSISTENCY  --  Interface
  935. ;;;
  936. (defun check-pack-consistency (component)
  937.   (flet ((check (scs ops)
  938.        (do ((scs scs (cdr scs))
  939.         (op ops (tn-ref-across op)))
  940.            ((null scs))
  941.          (let ((load-tn (tn-ref-load-tn op)))
  942.            (unless (eq (svref (car scs)
  943.                   (sc-number
  944.                    (tn-sc
  945.                     (or load-tn (tn-ref-tn op)))))
  946.                t)
  947.          (barf "Operand restriction not satisfied: ~S." op))))))
  948.     (do-ir2-blocks (block component)
  949.       (do ((vop (ir2-block-last-vop block) (vop-prev vop)))
  950.       ((null vop))
  951.     (let ((info (vop-info vop)))
  952.       (check (vop-info-result-load-scs info) (vop-results vop))
  953.       (check (vop-info-arg-load-scs info) (vop-args vop))))))
  954.   (undefined-value))
  955.  
  956.  
  957. ;;;; Data structure dumping routines:
  958.  
  959. ;;; Continuation-Number, Number-Continuation, ID-TN, TN-ID  --  Interface
  960. ;;;
  961. ;;;    When we print Continuations and TNs, we assign them small numeric IDs so
  962. ;;; that we can get a handle on anonymous objects given a printout.
  963. ;;;
  964. (macrolet ((frob (counter vto vfrom fto ffrom)
  965.          `(progn
  966.         (defvar ,vto (make-hash-table :test #'eq))
  967.         (defvar ,vfrom (make-hash-table :test #'eql))
  968.         (proclaim '(hash-table ,vto ,vfrom))
  969.         (defvar ,counter 0)
  970.         (proclaim '(fixnum ,counter))
  971.         
  972.         (defun ,fto (x)
  973.           (or (gethash x ,vto)
  974.               (let ((num (incf ,counter)))
  975.             (setf (gethash num ,vfrom) x)
  976.             (setf (gethash x ,vto) num))))
  977.         
  978.         (defun ,ffrom (num)
  979.           (values (gethash num ,vfrom))))))
  980.   (frob *continuation-number*
  981.         *continuation-numbers* *number-continuations*
  982.         cont-num num-cont)
  983.   (frob *tn-id*
  984.         *tn-ids* *id-tns*
  985.         tn-id id-tn)
  986.   (frob *label-id*
  987.         *id-labels* *label-ids*
  988.         label-id id-label))
  989.  
  990. ;;; Print-Leaf  --  Internal
  991. ;;;
  992. ;;;    Print out a terse one-line description of a leaf.
  993. ;;;
  994. (defun print-leaf (leaf &optional (stream *standard-output*))
  995.   (declare (type leaf leaf) (type stream stream))
  996.   (etypecase leaf
  997.     (lambda-var (prin1 (leaf-name leaf) stream))
  998.     (constant (format stream "'~S" (constant-value leaf)))
  999.     (global-var
  1000.      (format stream "~S {~A}" (leaf-name leaf) (global-var-kind leaf)))
  1001.     (clambda
  1002.       (format stream "lambda ~S ~S" (leaf-name leaf)
  1003.           (mapcar #'leaf-name (lambda-vars leaf))))
  1004.     (optional-dispatch
  1005.      (format stream "optional-dispatch ~S" (leaf-name leaf)))
  1006.     (functional
  1007.      (assert (eq (functional-kind leaf) :top-level-xep))
  1008.      (format stream "TL-XEP ~S" (entry-info-name (leaf-info leaf))))))
  1009.  
  1010.  
  1011. ;;; Block-Or-Lose  --  Interface
  1012. ;;;
  1013. ;;;    Attempt to find a block given some thing that has to do with it.
  1014. ;;;
  1015. (proclaim '(function block-or-lose (t) cblock))
  1016. (defun block-or-lose (thing)
  1017.   (ctypecase thing
  1018.     (cblock thing)
  1019.     (ir2-block (ir2-block-block thing))
  1020.     (vop (block-or-lose (vop-block thing)))
  1021.     (tn-ref (block-or-lose (tn-ref-vop thing)))
  1022.     (continuation (continuation-block thing))
  1023.     (node (node-block thing))
  1024.     (component (component-head thing))
  1025. #|    (cloop (loop-head thing))|#
  1026.     (integer (continuation-block (num-cont thing)))
  1027.     (functional (node-block (lambda-bind (main-entry thing))))
  1028.     (null (error "Bad thing: ~S." thing))
  1029.     (symbol (block-or-lose (gethash thing *free-functions*)))))
  1030.  
  1031.  
  1032. ;;; Print-Continuation  --  Internal
  1033. ;;;
  1034. ;;;    Print cN.
  1035. ;;;
  1036. (defun print-continuation (cont)
  1037.   (declare (type continuation cont))
  1038.   (format t " c~D" (cont-num cont)))
  1039.   (undefined-value))
  1040.  
  1041.  
  1042. ;;; Print-Nodes  --  Interface
  1043. ;;;
  1044. ;;;    Print out the nodes in Block in a format oriented toward representing
  1045. ;;; what the code does. 
  1046. ;;;
  1047. (defun print-nodes (block)
  1048.   (setq block (block-or-lose block))
  1049.   (format t "~%block start c~D" (cont-num (block-start block)))
  1050.  
  1051.   (let ((last (block-last block)))
  1052.     (terpri)
  1053.     (do ((cont (block-start block) (node-cont (continuation-next cont))))
  1054.     (())
  1055.       (let ((node (continuation-next cont)))
  1056.     (format t "~3D: " (cont-num (node-cont node)))
  1057.     (etypecase node
  1058.       (ref (print-leaf (ref-leaf node)))
  1059.       (basic-combination
  1060.        (let ((kind (basic-combination-kind node)))
  1061.          (format t "~(~A ~A~) c~D"
  1062.              (if (function-info-p kind) "known" kind)
  1063.              (type-of node)
  1064.              (cont-num (basic-combination-fun node)))
  1065.          (dolist (arg (basic-combination-args node))
  1066.            (if arg
  1067.            (print-continuation arg)
  1068.            (format t " <none>")))))
  1069.       (cset
  1070.        (write-string "set ")
  1071.        (print-leaf (set-var node))
  1072.        (print-continuation (set-value node)))
  1073.       (cif
  1074.        (format t "if c~D" (cont-num (if-test node)))
  1075.        (print-continuation (block-start (if-consequent node)))
  1076.        (print-continuation (block-start (if-alternative node))))
  1077.       (bind
  1078.        (write-string "bind ")
  1079.        (print-leaf (bind-lambda node)))
  1080.       (creturn
  1081.        (format t "return c~D " (cont-num (return-result node)))
  1082.        (print-leaf (return-lambda node)))
  1083.       (entry
  1084.        (format t "entry ~S" (entry-exits node)))
  1085.       (exit
  1086.        (let ((value (exit-value node)))
  1087.          (cond (value
  1088.             (format t "exit c~D" (cont-num value)))
  1089.            ((exit-entry node)
  1090.             (format t "exit <no value>"))
  1091.            (t
  1092.             (format t "exit <degenerate>"))))))
  1093.     (terpri)
  1094.     (when (eq node last) (return)))))
  1095.  
  1096.   (let ((succ (block-succ block)))
  1097.     (format t "successors~{ c~D~}~%"
  1098.         (mapcar #'(lambda (x) (cont-num (block-start x))) succ)))
  1099.   (values))
  1100.  
  1101.  
  1102. ;;; Print-TN  --  Internal
  1103. ;;;
  1104. ;;;    Print a useful representation of a TN.  If the TN has a leaf, then do a
  1105. ;;; Print-Leaf on that, otherwise print a generated ID.
  1106. ;;;
  1107. (defun print-tn (tn &optional (stream *standard-output*))
  1108.   (declare (type tn tn))
  1109.   (let ((leaf (tn-leaf tn)))
  1110.     (cond (leaf
  1111.        (print-leaf leaf stream)
  1112.        (format stream "!~D" (tn-id tn)))
  1113.       (t
  1114.        (format stream "t~D" (tn-id tn))))
  1115.     (when (and (tn-sc tn) (tn-offset tn))
  1116.       (format stream "[~A]" (location-print-name tn)))))
  1117.  
  1118.  
  1119. ;;; Print-Operands  --  Internal
  1120. ;;;
  1121. ;;;    Print the TN-Refs representing some operands to a VOP, linked by
  1122. ;;; TN-Ref-Across.
  1123. ;;;
  1124. (defun print-operands (refs)
  1125.   (declare (type (or tn-ref null) refs))
  1126.   (pprint-logical-block (*standard-output* nil)
  1127.     (do ((ref refs (tn-ref-across ref)))
  1128.     ((null ref))
  1129.       (let ((tn (tn-ref-tn ref))
  1130.         (ltn (tn-ref-load-tn ref)))
  1131.     (cond ((not ltn)
  1132.            (print-tn tn))
  1133.           (t
  1134.            (print-tn tn)
  1135.            (princ (if (tn-ref-write-p ref) #\< #\>))
  1136.            (print-tn ltn)))
  1137.     (princ #\space)
  1138.     (pprint-newline :fill)))))
  1139.  
  1140.  
  1141. ;;; Print-Vop -- internal
  1142. ;;;
  1143. ;;; Print the vop, putting args, info and results on separate lines, if
  1144. ;;; necessary.
  1145. ;;;
  1146. (defun print-vop (vop)
  1147.   (pprint-logical-block (*standard-output* nil)
  1148.     (princ (vop-info-name (vop-info vop)))
  1149.     (princ #\space)
  1150.     (pprint-indent :current 0)
  1151.     (print-operands (vop-args vop))
  1152.     (pprint-newline :linear)
  1153.     (when (vop-codegen-info vop)
  1154.       (princ (with-output-to-string (stream)
  1155.            (let ((*print-level* 1)
  1156.              (*print-length* 3))
  1157.          (format stream "{~{~S~^ ~}} " (vop-codegen-info vop)))))
  1158.       (pprint-newline :linear))
  1159.     (when (vop-results vop)
  1160.       (princ "=> ")
  1161.       (print-operands (vop-results vop))))
  1162.   (terpri))
  1163.  
  1164. ;;; Print-IR2-Block  --  Internal
  1165. ;;;
  1166. ;;;    Print the VOPs in the specified IR2 block.
  1167. ;;;
  1168. (defun print-ir2-block (block)
  1169.   (declare (type ir2-block block))
  1170.   (cond
  1171.    ((eq (block-info (ir2-block-block block)) block)
  1172.     (format t "~%IR2 block start c~D~%"
  1173.         (cont-num (block-start (ir2-block-block block))))
  1174.     (let ((label (ir2-block-%label block)))
  1175.       (when label
  1176.     (format t "L~D:~%" (label-id label)))))
  1177.    (t
  1178.     (format t "<overflow>~%")))
  1179.  
  1180.   (do ((vop (ir2-block-start-vop block)
  1181.         (vop-next vop))
  1182.        (number 0 (1+ number)))
  1183.       ((null vop))
  1184.     (format t "~D: " number)
  1185.     (print-vop vop)))
  1186.  
  1187.  
  1188. ;;; Print-VOPs  --  Interface
  1189. ;;;
  1190. ;;;    Like Print-Nodes, but dumps the IR2 representation of the code in Block.
  1191. ;;;
  1192. (defun print-vops (block)
  1193.   (setq block (block-or-lose block))
  1194.   (let ((2block (block-info block)))
  1195.     (print-ir2-block 2block)
  1196.     (do ((b (ir2-block-next 2block) (ir2-block-next b)))
  1197.     ((not (eq (ir2-block-block b) block)))
  1198.       (print-ir2-block b)))
  1199.   (values))
  1200.  
  1201.  
  1202. ;;; Print-IR2-Blocks  --  Interface
  1203. ;;;
  1204. ;;;    Scan the IR2 blocks in emission order.
  1205. ;;;
  1206. (defun print-ir2-blocks (thing)
  1207.   (do-ir2-blocks (block (block-component (block-or-lose thing)))
  1208.     (print-ir2-block block))
  1209.   (values))
  1210.  
  1211.  
  1212. ;;; Print-Blocks  --  Interface
  1213. ;;;
  1214. ;;;    Do a Print-Nodes on Block and all blocks reachable from it by successor
  1215. ;;; links.
  1216. ;;;
  1217. (defun print-blocks (block)
  1218.   (setq block (block-or-lose block))
  1219.   (do-blocks (block (block-component block) :both)
  1220.     (setf (block-flag block) nil))
  1221.   (labels ((walk (block)
  1222.          (unless (block-flag block)
  1223.            (setf (block-flag block) t)
  1224.            (when (block-start block)
  1225.          (print-nodes block))
  1226.            (dolist (block (block-succ block))
  1227.          (walk block)))))
  1228.     (walk block))
  1229.   (values))
  1230.  
  1231.  
  1232. ;;; Print-All-Blocks  --  Interface
  1233. ;;;
  1234. ;;;    Print all blocks in Block's component in DFO.
  1235. ;;;
  1236. (defun print-all-blocks (thing)
  1237.   (do-blocks (block (block-component (block-or-lose thing)))
  1238.     (handler-case (print-nodes block)
  1239.       (error (condition)
  1240.         (format t "~&~A...~%" condition))))
  1241.   (values))
  1242.  
  1243.  
  1244. (defvar *list-conflicts-table* (make-hash-table :test #'eq))
  1245.  
  1246. ;;; Add-Always-Live-TNs  --  Internal
  1247. ;;;
  1248. ;;;    Add all Always-Live TNs in Block to the conflicts.  TN is ignored when
  1249. ;;; it appears in the global conflicts.
  1250. ;;;
  1251. (defun add-always-live-tns (block tn)
  1252.   (declare (type ir2-block block) (type tn tn))
  1253.   (do ((conf (ir2-block-global-tns block)
  1254.          (global-conflicts-next conf)))
  1255.       ((null conf))
  1256.     (when (eq (global-conflicts-kind conf) :live)
  1257.       (let ((btn (global-conflicts-tn conf)))
  1258.     (unless (eq btn tn)
  1259.       (setf (gethash btn *list-conflicts-table*) t)))))
  1260.   (undefined-value))
  1261.  
  1262.  
  1263. ;;; Add-All-Local-TNs  --  Internal
  1264. ;;;
  1265. ;;;    Add all local TNs in block to the conflicts.
  1266. ;;;
  1267. (defun add-all-local-tns (block)
  1268.   (declare (type ir2-block block))
  1269.   (let ((ltns (ir2-block-local-tns block)))
  1270.     (dotimes (i (ir2-block-local-tn-count block))
  1271.       (setf (gethash (svref ltns i) *list-conflicts-table*) t)))
  1272.   (undefined-value))
  1273.  
  1274.  
  1275. ;;; Listify-Conflicts-Table  --  Internal
  1276. ;;;
  1277. ;;;    Make a list out of all of the recorded conflicts.
  1278. ;;;
  1279. (defun listify-conflicts-table ()
  1280.   (collect ((res))
  1281.     (maphash #'(lambda (k v)
  1282.          (declare (ignore v))
  1283.          (when k
  1284.            (res k)))
  1285.          *list-conflicts-table*)
  1286.     (clrhash *list-conflicts-table*)
  1287.     (res)))
  1288.   
  1289.  
  1290. ;;;  List-Conflicts  --  Interface
  1291. ;;;
  1292. (defun list-conflicts (tn)
  1293.   "Return a list of a the TNs that conflict with TN.  Sort of, kind of.  For
  1294.   debugging use only.  Probably doesn't work on :COMPONENT TNs."
  1295.   (assert (member (tn-kind tn) '(:normal :environment :debug-environment)))
  1296.   (let ((confs (tn-global-conflicts tn)))
  1297.     (cond (confs
  1298.        (clrhash *list-conflicts-table*)
  1299.        (do ((conf confs (global-conflicts-tn-next conf)))
  1300.            ((null conf))
  1301.          (let ((block (global-conflicts-block conf)))
  1302.            (add-always-live-tns block tn)
  1303.            (if (eq (global-conflicts-kind conf) :live)
  1304.            (add-all-local-tns block)
  1305.            (let ((bconf (global-conflicts-conflicts conf))
  1306.              (ltns (ir2-block-local-tns block)))
  1307.              (dotimes (i (ir2-block-local-tn-count block))
  1308.                (when (/= (sbit bconf i) 0)
  1309.              (setf (gethash (svref ltns i) *list-conflicts-table*)
  1310.                    t)))))))
  1311.        (listify-conflicts-table))
  1312.       (t
  1313.        (let* ((block (tn-local tn))
  1314.           (ltns (ir2-block-local-tns block))
  1315.           (confs (tn-local-conflicts tn)))
  1316.          (collect ((res))
  1317.            (dotimes (i (ir2-block-local-tn-count block))
  1318.          (when (/= (sbit confs i) 0)
  1319.            (let ((tn (svref ltns i)))
  1320.              (when (and tn (not (eq tn :more))
  1321.                 (not (tn-global-conflicts tn)))
  1322.                (res tn)))))
  1323.            (do ((gtn (ir2-block-global-tns block)
  1324.              (global-conflicts-next gtn)))
  1325.            ((null gtn))
  1326.          (when (or (eq (global-conflicts-kind gtn) :live)
  1327.                (/= (sbit confs (global-conflicts-number gtn)) 0))
  1328.            (res (global-conflicts-tn gtn))))
  1329.            (res)))))))
  1330.  
  1331.  
  1332. ;;; Nth-VOP  --  Interface
  1333. ;;;
  1334. (defun nth-vop (thing n)
  1335.   "Return the Nth VOP in the IR2-Block pointed to by Thing."
  1336.   (let ((block (block-info (block-or-lose thing))))
  1337.     (do ((i 0 (1+ i))
  1338.      (vop (ir2-block-start-vop block) (vop-next vop)))
  1339.     ((= i n) vop))))
  1340.