Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wn_tree_util.h
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 //-*-c++-*-
00037 // INTERFACE: wn_tree_util.h
00038 #ifndef wn_tree_util_INCLUDED
00039 #define wn_tree_util_INCLUDED "wn_tree_util.h"
00040 // ====================================================================
00041 // ====================================================================
00042 //
00043 //
00044 // Revision history:
00045 //  14-Aug-97 - Original Version 
00046 //
00047 // Description:
00048 //
00049 // ======================= WN tree walk routines =======================
00050 //  - wn_tree_util.h defines interface to tree walk functions.
00051 //
00052 //  - defines a tree iterator class WN_TREE_ITER which satisfies 
00053 //    the requirements of an STL FORWARD ITERATOR 
00054 //
00055 //  - defines a tree container WN_TREE_CONTAINER which satisfies
00056 //    the requirements of an STL FORWARD CONTAINER
00057 //
00058 //  - NOTE : We prefer that you use the WN_TREE_CONTAINER 
00059 //    over the WN_TREE_ITERATOR since the interface/algorithms are cleaner
00060 //    
00061 // Benefits of using the tree container:
00062 // (A) clean interface
00063 // (B) Ability to use STL algorithms which operate on Fwd Containers
00064 // (C) efficient: it doesn't "push" unless it has to, 
00065 //                it uses kid_index to efficiently access next kid
00066 //                it pre-allocates for the vector (fewer reallocs)
00067 // (D) generic :  it allows parameterized tree traversal: PRE/POST-ORDER
00068 //                it allows us to skip siblings of nodes
00069 //                it allows us to abort tree walk in middle (use stl find_if)
00070 //
00071 // Qn: WHEN is it BEST to USE the tree container defined here?
00072 // Ans: 
00073 //  (A) If you traverse but not modify a whirl tree
00074 //  - eg If you are traversing whirl trees computing summary information
00075 //  - eg If you are searching for whirl patterns in a whirl tree
00076 //  (B) If you modify only the children of the node you are currently visiting
00077 //  - eg Replace ICALL by CALL
00078 // ====================================================================
00079 // included files
00080 // ======================================================================
00081 #include <utility>                     // pair template
00082 #include <algorithm>                   // which includes algobase which has
00083                                        // the function "distance"
00084 #include <vector>                      // represent stack as vector of pairs
00085 #include <iterator>                    // for forward_iterator_tag
00086 #include <functional>                  // for != etc
00087 #include "defs.h"                      // INT etc
00088 #include "wn.h"                        // whirl node
00089 #include "cxx_memory.h"                // for CXX_NEW etc
00090 // ======================================================================
00091 // TYPEDEFS, DEFINES, FORWARD_DEFINITIONS and EXTERN interfaces
00092 // ======================================================================
00093 
00094 // typedef TRAV_ORDER needs to be exposed to the user
00095 // IN_ORDER doesn't make sense for whirl trees (they are not binary trees)
00096 
00097 enum TRAV_ORDER {
00098   PRE_ORDER=0,
00099   POST_ORDER=1
00100 };
00101 
00102 // ======================================================================
00103 // 
00104 // This file contains the routines necessary for whirl tree operations
00105 // a. tree walk: WN_WALK_TREE
00106 // b. tree copy: WN_COPY_TREE
00107 // .... for later: WN_INSERT, WN_DELETE, .....
00108 
00109 // Exported classes
00110 // 
00111 
00112 // WN_TREE_ITER: tree iterator helper class
00113 //     This class has data members 
00114 //     - WN *_wn  (since the WN_TREE_ITER container OWNS its elements we keep
00115 //                 pointers to whirl nodes inside the container)
00116 //     -  _parent is a stack of pairs
00117 //     - kid_index part of pair is used for determining "next" for non-block 
00118 //     - WN* part of the pair is the parent wn
00119 //     - template value parameter, TRAV_ORDER represents PRE/POSI_ORDER
00120 //     - Note: IN_ORDER traversal doesn't make much sense since whirl
00121 //             trees are not binary (or for that matter n-ary for fixed n)
00122 
00123 // member functions
00124 //     WN_TREE_next, WN_TREE_next_skip, etc, etc
00125 //
00126 
00127 // ======================================================================
00128 
00129 // class WN_TREE_ITER: parameterized by how you traverse tree
00130 // a. PRE_ORDER
00131 // b. POST_ORDER
00132 //    the default value (16) chosen for stack size indicates the 
00133 //    "expected depth" of the whirl tree: 
00134 //   TRAVERSAL ORDER examples
00135 //   eg if the tree is:
00136 //                   1
00137 //                2     3
00138 //              4  5   6
00139 //                7 8
00140 //
00141 // (a) its depth is 4 (the Depth function returns the actual tree depth)
00142 // (b)* the pre-order traversal order is: 1 2 4 5 7 8 3 6
00143 //    * when traversing 5 the stack will have [<1,0> <2,1>
00144 //    * when traversing 7 the stack will have [<1,0> <2,1> <5,0>
00145 //    * when traversing 7, "next" returns 8 and "next_skip" returns 3
00146 // (c)* the post-order traversal order is: 4 7 8 5 2 6 3 1
00147 //    * when traversing 5 the stack will have [<1,0> <2,1>
00148 //    * when traversing 7 the stack will have [<1,0> <2,1> <5,0>
00149 // (d)* the in-order traversal doesn't make sense for non-binary trees
00150 
00151 
00152 // ======================================================================
00153 // Base class shared by both traversal order interators
00154 // We need this to get partial specialization work
00155 // ======================================================================
00156 
00157 using std::vector;
00158 using std::pair;
00159 
00160 
00161 template <class WHIRL>
00162 class WN_TREE_ITER_base
00163 {
00164 
00165   // WN_TREE_ITER contains a stack of pairs where
00166   // each stack element is a pair consisting of a whirl node and a
00167   // kid_index (specifying which kid the whirl node is (of its parent)
00168   // kid_index is used only for non-block parent and is -1 if parent is block 
00169 
00170 
00171   // The next typedefs are for
00172   // STL forward iterator requirements (see STL/iterator.h)
00173 
00174 public:
00175 
00176   typedef WN_TREE_ITER_base<WHIRL>  self;
00177   typedef std::forward_iterator_tag iterator_category;
00178   typedef WHIRL                     value_type;
00179   typedef ptrdiff_t                 difference_type;
00180   typedef value_type*               pointer;
00181   typedef const value_type&         const_reference;
00182   typedef value_type&               reference;
00183   typedef vector<pair<WHIRL,INT32> > WN_STACK;
00184 
00185 protected:
00186 
00187   WHIRL                        _wn;     // whirl node to iterate over;
00188   WN_STACK                     _parent; // whirl node's internal stack
00189 
00190 
00191 public:
00192   // access functions  
00193 
00194   WHIRL Wn(void)                        const      {return _wn;}
00195   const WN_STACK& Parent(void)          const      {return _parent;}
00196 
00197   // set functions
00198 
00199   void Set_wn(WHIRL wn2)                           { _wn = wn2;}
00200   void Set_parent(const WN_STACK& parent2)         {_parent = parent2;}
00201 
00202   INT  Get_kid_index(void) const {  return (_parent.back()).second;}          
00203 
00204 protected:
00205   // Utility functions 
00206   void Set_kid_index(INT i)      {  (_parent.back()).second = i;}    
00207   INT  Inc_kid_index(void)       {  return (++((_parent.back()).second));}
00208 
00209   // Push() for stack
00210   // push _wn onto _parent stack
00211   // _wn becomes its next descendent 
00212   // NOTE: you only push a node if it has descendents
00213   // Thus, it is incorrect to call this fn with leaf nodes or empty blocks.
00214 
00215   void Push () {
00216     Is_True (_wn != NULL, ("Bad tree node"));
00217     Is_True (((WN_operator (_wn) == OPR_BLOCK) && WN_first (_wn)) ||
00218              !OPCODE_is_leaf (WN_opcode (_wn)),
00219              ("Push only applies to nodes with descendents"));;
00220   
00221     if (WN_operator (_wn) == OPR_BLOCK) {
00222       _parent.push_back (std::make_pair (_wn, -1));
00223       Set_wn (WN_first (_wn));
00224     } else {
00225       _parent.push_back (std::make_pair (_wn, 0));
00226       Set_wn (WN_kid0 (_wn));
00227     } 
00228   }                                         
00229 
00230 public:
00231 
00232   // pop stack, and update parent with parent_wn
00233   void Pop () {
00234     Is_True(! _parent.empty(),("Cannot pop empty stack"));
00235     Set_wn (Get_parent_wn ());
00236     _parent.pop_back ();
00237   }
00238   
00239   WHIRL Get_parent_wn(void) const { 
00240     return _parent.empty () ? NULL : (_parent.back()).first;
00241   }
00242 
00243   inline INT Depth()             { return 1+ _parent.size();} // Depth() >= 1
00244 
00245   // Constructors
00246 
00247   // (a) For PRE_ORDER traversal,  the stack is empty upon startup whereas
00248   //     for POST_ORDER traversal, the stack has all nodes upto leftmost leaf
00249   // (b) A tree node is pushed on the stack ONLY if it has children
00250 
00251   // (c) INVARIANT relationship between _wn and _parent_stack:
00252   //     parent_wn =  1st(top(_parent))     kid_index = 2nd(top(_parent))
00253   //     1. If (parent_wn) is a BLOCK 
00254   //          then _wn is "a" kid of parent_wn;
00255   //     2. else /* parent_wn has kids */
00256   //          then _wn is WN_Kid(parent_wn,kid_index)
00257 
00258   // used for creating a "null" iterator via conversion from 0
00259   // we can thus write (tree_iter != 0)
00260 
00261   WN_TREE_ITER_base(): _wn(NULL)    {}
00262 
00263   // use the constructor  when you need to specify default stack size
00264 
00265   WN_TREE_ITER_base (WHIRL wn2) : _wn(wn2) {}
00266 
00267   // operators to fulfill forward Iterator requirements
00268   reference   operator*()     { return *_wn; }
00269   
00270   // eraxxon 2004.11.30: GCC 3.4.3 is complaining that it cannot find
00271   // the corresonding declaration... am I missing something? However,
00272   // this doesn't need to be a friend anyway.
00273 #if 0  
00274   friend bool operator==<WHIRL>(const self &x, const self & y); // def'd below
00275 #endif
00276   
00277   // replace the current node by another
00278   void Replace (WHIRL new_wn) {
00279     WHIRL parent = Get_parent_wn ();
00280     Is_True (parent != NULL, ("can't replace a node without a parent"));
00281     if (WN_operator (parent) == OPR_BLOCK) {
00282       Is_True (OPERATOR_has_next_prev (WN_operator (new_wn)),
00283                ("Invalid opcode passed to TREE_ITER::Replace ()"));
00284       if (WN_first (parent) == _wn) {
00285         WN_first (parent) = new_wn;
00286         WN_prev (new_wn) = NULL;
00287         WN_next (new_wn) = WN_next (_wn);
00288         if (WN_next (_wn) == NULL)
00289           WN_last (parent) = new_wn;
00290         else
00291           WN_prev (WN_next (_wn)) = new_wn;
00292       } else if (WN_last (parent) == _wn) {
00293         WN_last (parent) = new_wn;
00294         WN_next (new_wn) = NULL;
00295         WN_prev (new_wn) = WN_prev (_wn);
00296         if (WN_prev (_wn) == NULL)
00297           WN_first (parent) = new_wn;
00298         else
00299           WN_next (WN_prev (_wn)) = new_wn;
00300       } else {
00301         WN_prev (new_wn) = WN_prev (_wn);
00302         WN_next (WN_prev (_wn)) = new_wn;
00303         WN_next (new_wn) = WN_next (_wn);
00304         WN_prev (WN_next (_wn)) = new_wn;
00305       }
00306     } else {
00307       WN_kid (parent, Get_kid_index ()) = new_wn;
00308     }
00309     _wn = new_wn;
00310   }
00311 
00312 
00313 }; // class WN_TREE_ITER_base
00314 
00315 
00316 // Equality is just a test of equality on WN *
00317 // equality is only defined on two tree-iterators which have SAME TRAV ORDER
00318 // equality satisfies (it1 == it2) <==> (&*it1 == &*it2)
00319 template <class WHIRL>
00320 bool operator==(const WN_TREE_ITER_base<WHIRL> &x,
00321                 const WN_TREE_ITER_base<WHIRL> &y) {
00322   return (x.Wn() == y.Wn());
00323 }
00324 
00325 template <class WHIRL>
00326 bool operator!=(const WN_TREE_ITER_base<WHIRL> &x,
00327                 const WN_TREE_ITER_base<WHIRL> &y) {
00328   return (x.Wn() != y.Wn());
00329 }
00330 
00331 // ======================================================================
00332 
00333 // dummy template to parameterize the traversal order.
00334 // only the specialized versions defined below are used.
00335 template <TRAV_ORDER order, class WHIRL = WN*>
00336 class WN_TREE_ITER : public WN_TREE_ITER_base<WHIRL>
00337 {
00338 }; // WN_TREE_ITER
00339 
00340 
00341 // ======================================================================
00342 // preorder traversal iterator
00343 // ======================================================================
00344 template <class WHIRL>
00345 class WN_TREE_ITER<PRE_ORDER, WHIRL> : public WN_TREE_ITER_base<WHIRL>
00346 {
00347 public:
00348   WN_TREE_ITER () : WN_TREE_ITER_base<WHIRL> () {}
00349   
00350   WN_TREE_ITER (WHIRL wn) : WN_TREE_ITER_base<WHIRL> (wn) {}
00351 
00352   // tree related functions
00353 
00354   // Unwind starts from a node and keeps popping tree nodes off stack 
00355   // until you've reached the "next" node of the leaf node. 
00356   // Unwind starts from leaf except in "print" 
00357   void Unwind();
00358 
00359 
00360   void WN_TREE_next ();                 // next for preorder
00361 
00362   // WN_TREE_next_skip return the next sibling, ie 
00363   // a. "abort" the tree walk of any children
00364   // b. Go to the next (right) sibling if it exists
00365   //    else go to the next (right) sibling of parent's, etc..
00366   void WN_TREE_next_skip () {       
00367     Unwind ();
00368   }
00369 
00370   // skip to the next sibling of the nth parent.
00371   // i.e., when depth == 1, skip to the next sibling of the parent
00372   // when depth == 2, skip to the next sibling of the grandparent, etc.
00373   void Skip (UINT depth = 0) {
00374     while (depth > 0 && !this->_parent.empty ()) {
00375       this->Pop ();
00376       --depth;
00377     }
00378     WN_TREE_next_skip ();
00379   }
00380 
00381   // delete the current node
00382   void Delete () {
00383     WHIRL parent = this->Get_parent_wn ();
00384     Is_True (parent, ("cannot delete nodes without a parent"));
00385     Is_True (WN_operator (parent) == OPR_BLOCK,
00386              ("can only delete nodes under a OPR_BLOCK"));
00387     WHIRL _next = WN_next (this->_wn);
00388     WHIRL _prev = WN_prev (this->_wn);
00389     if (WN_first (parent) == this->_wn) {
00390       WN_first (parent) = _next;
00391       if (_next == NULL)
00392         WN_last (parent) = NULL;
00393       else
00394         WN_prev (_next) = _prev;
00395     } else if (WN_last (parent) == this->_wn) {
00396       WN_last (parent) = _prev;
00397       if (_prev == NULL)
00398         WN_first (parent) = NULL;
00399       else
00400         WN_next (_prev) = _next;
00401     } else {
00402       WN_prev (_next) = _prev;
00403       WN_next (_prev) = _next;
00404     }
00405     this->_wn = _next;
00406     if (this->_wn == NULL) {
00407       this->Pop ();
00408       Skip (0);
00409     }
00410   }
00411 
00412   // Insert a node before the current node, after insertion, current node
00413   // points to the new node
00414   void Insert (WHIRL node) {
00415     WHIRL parent = this->Get_parent_wn ();
00416     Is_True (parent, ("cannot insert to nodes without a parent"));
00417     Is_True (WN_operator (parent) == OPR_BLOCK,
00418              ("can only insert before nodes under a OPR_BLOCK"));
00419     WHIRL _prev = WN_prev (this->_wn);
00420     WN_prev (node) = _prev;
00421     if (_prev == NULL)
00422       WN_first (parent) = node;
00423     else
00424       WN_next (_prev) = node;
00425     WN_next (node) = this->_wn;
00426     WN_prev (this->_wn) = node;
00427     this->_wn = node;
00428   }
00429 
00430   // tree related "iterators"
00431   
00432   WN_TREE_ITER_base<WHIRL> & operator++() { 
00433     WN_TREE_next(); 
00434     return *this;
00435   } // pre
00436   
00437   WN_TREE_ITER_base<WHIRL> operator++(INT) {
00438     WN_TREE_ITER_base<WHIRL> tmp = *this;
00439     WN_TREE_next();
00440     return tmp;
00441   }
00442 }; // WN_TREE_ITER<PRE_ORDER, WHIRL>
00443 
00444 
00445 // Unwind keeps popping parent_stack untill you reach a parent_whirl_node 
00446 // for which the _wn (child) is NOT the "last" (rightmost) child. Unwind 
00447 // sets _wn to the "next" child of this parent_whirl_node
00448 // unwind the "stack" until we reach the "next" or the END
00449 template <class WHIRL>
00450 void
00451 WN_TREE_ITER<PRE_ORDER, WHIRL>::Unwind() {
00452 
00453   // unwind "unwinds the stack"
00454   BOOL done = FALSE;
00455   while (!done) {
00456     WHIRL wn = this->Wn();
00457     Is_True(wn != 0,("Bad tree node"));
00458 
00459     WHIRL parent_wn = this->Get_parent_wn();
00460     if (parent_wn == NULL) {
00461       // reached end of unwind
00462       this->Set_wn(NULL);
00463       return;
00464     }
00465     
00466     if (WN_operator(parent_wn) == OPR_BLOCK) {
00467       if (WN_next(wn)) {
00468         this->Set_wn(WN_next(wn));
00469         done = TRUE;
00470       }
00471       else // all stmts in a block processed ==> go back up
00472         this->Pop(); // Pop(parent_wn) + MORE WORK NEEDED
00473     } 
00474     else { // parent is NON_BLOCK ie increment kid_count to get next sibling
00475       // eraxxon, 2004.07.12: In special circumstances, some nodes may
00476       // have NULL children.  For example, a call with missing
00477       // optional Fortran parameters is currently represented as a
00478       // CALL node with NULL PARM nodes.
00479       BOOL usedNextChild = FALSE;
00480       INT indx = this->Get_kid_index();
00481       while ((0 <= indx) && (indx < WN_kid_count(parent_wn) - 1)) {
00482         indx = this->Inc_kid_index();
00483         WN* kid = WN_kid(parent_wn, indx);
00484         if (kid) {
00485           this->Set_wn(kid);
00486           usedNextChild = TRUE;
00487           done = TRUE;
00488           break;
00489         }
00490       }
00491       if (!usedNextChild) {
00492         this->Pop(); // Pop(parent_wn) + MORE WORK NEEDED
00493       }
00494     } // else parent is NON_BLOCK
00495   } // while (!done)
00496 }  // Unwind
00497 
00498 
00499 // Specialization of WN_TREE_next() for PRE_ORDER
00500 
00501 template <class WHIRL>
00502 void
00503 WN_TREE_ITER<PRE_ORDER, WHIRL>::WN_TREE_next ()
00504 {
00505   Is_True(this->_wn != 0, ("Bad tree node"));
00506   if (WN_operator(this->_wn) == OPR_BLOCK) {
00507     if (WN_first(this->_wn)) // go down
00508       this->Push();  
00509     else              // go back up
00510       Unwind(); // Pop(parent_wn) + MORE WORK NEEDED
00511 
00512   } // if (OPCODE_OPERATOR(WN_opcode(wn)) == OPR_BLOCK)
00513   else { // not a block ==> look at kid_count to determine where to go
00514     BOOL goingDown=FALSE;
00515     INT wnKidCount=WN_kid_count(this->_wn);
00516     if (wnKidCount != 0) { 
00517       INT32 thisKid=0;
00518       while (!goingDown && thisKid<wnKidCount) { 
00519         WN* kid = WN_kid(this->_wn, thisKid);
00520         if (kid) {
00521           this->_parent.push_back (std::make_pair (this->_wn, thisKid));
00522           this->Set_wn(kid);
00523           goingDown = TRUE;
00524         }
00525         ++thisKid;
00526       }
00527     }
00528     if (! goingDown)  // go sideways (if parent is BLOCK) or UP otherwise
00529       Unwind(); // Pop(parent_wn) + MORE WORK NEEDED
00530   }
00531 }
00532 
00533 
00534 // ======================================================================
00535 // postorder traversal iterator
00536 // ======================================================================
00537 template <class WHIRL>
00538 class WN_TREE_ITER<POST_ORDER, WHIRL> : public WN_TREE_ITER_base<WHIRL>
00539 {
00540 public:
00541   // tree related functions
00542 
00543   // Wind keeps pushing a tree node on stack and going down its leftmost
00544   // child until you reach a "leaf"
00545   void Wind();
00546 
00547 
00548   void WN_TREE_next ();                 // next for preorder
00549 
00550   // tree related "iterators"
00551   
00552   WN_TREE_ITER_base<WHIRL> & operator++() { 
00553     WN_TREE_next();
00554     return *this;
00555   } // pre
00556   
00557   WN_TREE_ITER_base<WHIRL> operator++(INT) {
00558     WN_TREE_ITER_base<WHIRL> tmp = *this;
00559     WN_TREE_next();
00560     return tmp;
00561   }
00562 
00563   // constructors
00564   
00565   WN_TREE_ITER () : WN_TREE_ITER_base<WHIRL> () {}
00566   
00567   WN_TREE_ITER (WHIRL wn) : WN_TREE_ITER_base<WHIRL> (wn) {
00568 
00569     Wind ();                            // Wind initializes stack and _wn
00570                                         // to the "first" element based on
00571                                         // the traversal order 
00572   }
00573 
00574 }; // WN_TREE_ITER<POST_ORDER, WHIRL>
00575 
00576 
00577 // Wind takes a whirl node and keeps pushing it and going down its leftmost
00578 // child until it gets to a leaf node.
00579 // Wind is mainly for determining the FIRST node to be traversed.
00580 // (a) We've got to go traversing DOWN a whirl tree; 
00581 //     wind the "stack" until we reach a LEAF (empty BLOCK or leaf_node)
00582 template <class WHIRL>
00583 void
00584 WN_TREE_ITER<POST_ORDER, WHIRL>::Wind ()
00585 {
00586   Is_True(this->_wn != 0,("Bad tree node"));
00587   BOOL done = FALSE;
00588   while (!done) {
00589 
00590     if (WN_operator(this->_wn) == OPR_BLOCK) {
00591       if (WN_first(this->_wn)) 
00592         this->Push();
00593       else // leaf block 
00594         done = TRUE;
00595     } else { // parent is NON_BLOCK ie increment kid_count to get next sibling
00596       if ((WN_kid_count(this->_wn) == 0) || (!WN_kid0(this->_wn)))
00597         // leaf node
00598         done = TRUE;
00599       else 
00600         this->Push();
00601     }
00602   } // while (!done)
00603 } // Wind
00604 
00605 
00606     
00607 // Specialization of WN_TREE_next() for POST_ORDER
00608 
00609 template <class WHIRL>
00610 void
00611 WN_TREE_ITER<POST_ORDER, WHIRL>::WN_TREE_next ()
00612 {
00613   Is_True(this->_wn != 0, ("Bad tree node"));
00614   
00615   WHIRL parent_wn = this->Get_parent_wn();
00616   if (parent_wn == NULL) {
00617     // reached end of recursion
00618     this->Set_wn(NULL);
00619     return;
00620   }
00621     
00622   if (WN_operator(parent_wn) == OPR_BLOCK) {
00623     if (WN_next(this->_wn)) { // go sideways
00624       Set_wn(WN_next(this->_wn));
00625       Wind();
00626     }
00627     else              // go back up
00628       this->Pop(); // Pop(parent_wn) 
00629   } // if (OPCODE_OPERATOR(WN_opcode(wn)) == OPR_BLOCK)
00630   else { // not a block ==> look at kid_count to determine where to go
00631     // eraxxon, 2004.07.12: In special circumstances, some nodes may
00632     // have NULL children.  For example, a call with missing
00633     // optional Fortran parameters is currently represented as a
00634     // CALL node with NULL PARM nodes.
00635     BOOL usedNextChild = FALSE;
00636     INT indx = this->Get_kid_index();
00637     while ((0 <= indx) && (indx < WN_kid_count(parent_wn) - 1)) {
00638       indx = this->Inc_kid_index();
00639       WN* kid = WN_kid(parent_wn, indx);
00640       if (kid) {
00641         this->Set_wn(kid);
00642         Wind();
00643         usedNextChild = TRUE;
00644         break;
00645       }
00646     }
00647     if (!usedNextChild) {
00648       this->Pop(); // Pop(parent_wn) 
00649     }
00650   } // else 
00651 }
00652 
00653 // shorthand for commonly used iterator
00654 typedef WN_TREE_ITER<PRE_ORDER, WN*> TREE_ITER;
00655 typedef WN_TREE_ITER<PRE_ORDER, const WN*> CONST_TREE_ITER;
00656 
00657 // ======================================================================
00658 
00659 // WN_TREE_CONTAINER: is a model of a forward container
00660 // class WN_TREE_CONTAINER: parameterized by how you traverse tree
00661 // a. PRE_ORDER
00662 // b. POST_ORDER
00663 
00664 template <TRAV_ORDER order = PRE_ORDER>
00665 class WN_TREE_CONTAINER {
00666 public:
00667   typedef WN                                   value_type;
00668   typedef WN_TREE_ITER<order, WN*>             iterator;
00669   typedef WN_TREE_ITER<order, const WN*>       const_iterator;
00670   typedef value_type *                         pointer;
00671   typedef value_type &                         reference;
00672   typedef const value_type &                   const_reference;
00673   typedef size_t                               size_type;
00674   typedef ptrdiff_t                            difference_type;
00675 
00676   typedef WN_TREE_CONTAINER<order>             self;
00677 protected:
00678   iterator _start;
00679   iterator _finish;
00680   WN *     _root;
00681 
00682 public:
00683   iterator       begin()          { return _start;}
00684   const_iterator begin() const    { return _start;}
00685   iterator       end()            { return _finish;}
00686   const_iterator end()   const    { return _finish;}
00687   bool           empty() const    { return begin() == end(); }
00688 
00689   WN *           Root()  const    { return _root;}
00690 
00691   // operators to fulfill Fwd Container requirements defined below
00692 
00693   // eraxxon 2004.11.30: GCC 3.4.3 is complaining that it cannot find
00694   // the corresonding declaration... am I missing something? However,
00695   // this doesn't need to be a friend anyway.
00696 #if 0
00697   friend bool operator==<TRAV_ORDER>(const self &x, const self & y);
00698 #endif
00699 
00700   // WARNING: size is linear time, don't use it unless you have to
00701   size_type size()          const { return std::distance(begin(), end());}
00702   size_type      max_size() const { return size();} // fix_sized container
00703 
00704   // constructors
00705   WN_TREE_CONTAINER() : _start(0), _finish (0), _root(NULL) {}
00706   WN_TREE_CONTAINER(WN *w) :
00707     _start (iterator(w)), _finish (iterator()), _root (w) {
00708     Is_True(w!=0,("Bad Tree Root"));
00709   }
00710   WN_TREE_CONTAINER(const WN* w) :
00711     _start (const_iterator(w)), _finish (const_iterator()), _root (w) {
00712     Is_True(w!=0,("Bad Tree Root"));
00713   }
00714                                        
00715 }; // class WN_TREE_CONTAINER
00716 
00717 // (1) equality on container is elementwise equality (linear time) on
00718 // containers with the SAME traversal order
00719 // (2) WARNING: equality is linear time, don't use it unless you have to
00720 // (3) equality on container should not be invoked unless
00721 // you want WHIRL_NODE* equality to mean WN_equiv as is done for now
00722 // (4) if you can come up with a reasonable (better than WN_equiv) definition
00723 // of equality on WN*, please replace the defn below and let tk know
00724 // (5) I believe the operator== is not meaningful and will remove it 
00725 // unless anyone who uses the tree container convinces me that operator== 
00726 // can be reasonably defined form WN_TREE_CONTAINER
00727 
00728 template <TRAV_ORDER trav_order >
00729 bool
00730 operator== (const WN_TREE_CONTAINER<trav_order> &x,
00731             const WN_TREE_CONTAINER<trav_order> &y) {
00732   typedef typename WN_TREE_CONTAINER<trav_order >::const_iterator
00733     container_node;
00734   container_node xptr = x.begin();
00735   container_node yptr = y.begin();
00736   while (xptr.Wn() && yptr.Wn() &&  WN_Equiv(xptr.Wn(),yptr.Wn())) {
00737     ++xptr;
00738     ++yptr;
00739   }
00740   return ((xptr.Wn() == 0) && (yptr.Wn() == 0));
00741 }
00742 
00743 // ======================================================================
00744 // convenient macros for the "last" tree_iterator
00745 // ======================================================================
00746 // this is a WN_TREE_ITER<..> with _wn == NULL
00747 // Note: this is the ONLY WN_TREE_ITER object whose _wn is NULL
00748 //     : ++ (or WN_TREE_next) is NOT defined on this object
00749 
00750 #define LAST_PRE_ORDER_ITER (WN_TREE_ITER<PRE_ORDER, WN*> ())
00751 #define LAST_POST_ORDER_ITER (WN_TREE_ITER<POST_ORDER, WN*> ())
00752 #define LAST_PRE_ORDER_CONST_ITER (WN_TREE_ITER<PRE_ORDER, const WN*> ())
00753 #define LAST_POST_ORDER_CONST_ITER (WN_TREE_ITER<POST_ORDER, const WN*> ())
00754 
00755 // ======================================================================
00756 // TREE_WALK: external interface
00757 // ======================================================================
00758 
00759 // WN_TREE_walk interface:
00760 //  - walk the whirl tree "wn"
00761 //  - apply "op" to each whirl node in the tree
00762 //  - "trav_order" specifies order of tree traversal (defaults to PRE_ORDER)
00763 //  - use parent map OR stack to iterate over tree nodes (defaults to stack)
00764 //
00765 
00766 // ======================================================================
00767 // PRE-ORDER TRAVERSAL : root, left-subtree, right-subtree
00768 // POST-ORDER TRAVERSAL: left-subtree, right-subtree, root
00769 // ======================================================================
00770 
00771 
00772 
00773 template <class OPERATION, class WHIRL, TRAV_ORDER trav_order>
00774 OPERATION&
00775 WN_TREE_walk (WHIRL wn, OPERATION& op,
00776               const WN_TREE_ITER<trav_order, WHIRL>& last_iter)
00777 {
00778   // legality check
00779   Is_True(wn != 0, ("Bad tree node"));
00780   // create tree iterator
00781   // use stack of default size
00782   WN_TREE_ITER<trav_order, WHIRL> tree_iter(wn);
00783   while (tree_iter!=last_iter) {
00784     // apply op and go to next node
00785     op(tree_iter.Wn());    
00786     ++tree_iter;
00787   }
00788   return op;
00789 }
00790   
00791 
00792 // One for PRE_ORDER
00793 template <class OPERATION, class WHIRL>
00794 OPERATION&
00795 WN_TREE_walk_pre_order (WHIRL wn, OPERATION& op) {
00796   return WN_TREE_walk(wn, op, WN_TREE_ITER<PRE_ORDER, WHIRL> ());
00797 }
00798 
00799 // One for post_order
00800 template <class OPERATION, class WHIRL>
00801 OPERATION& WN_TREE_walk_post_order(WHIRL wn, OPERATION& op) {
00802   return WN_TREE_walk(wn, op, WN_TREE_ITER<POST_ORDER, WHIRL> ());
00803 }
00804 
00805 
00806 // ======================================================================
00807 // Function object examples for use with tree traversal
00808 // ======================================================================
00809 
00810 // function object example: print the whirl opcode
00811 struct WN_OPCODE_print {
00812   void  operator()(WN* wn) {
00813     printf("%s\n",OPCODE_name(WN_opcode(wn)));
00814   }
00815 };
00816 
00817 // function object example: count the number of whirl nodes
00818 struct WN_count {
00819   INT num_nodes;
00820   WN_count() : num_nodes(0){}
00821   void  operator()(WN* ) {
00822     ++num_nodes;
00823   }
00824 };
00825 
00826 // ======================================================================
00827 //  Some examples of usage of the TREE_ITERATOR/TREE_CONTAINER
00828 // ======================================================================
00829 // All examples are illustrated using BOTH the iterator and containers
00830 // The container incarnations have cleaner interface/algorithms and 
00831 // hence should be preferred over the iterator incarnations
00832 // (A1)
00833 // WN_TREE_walk_pre_order (wn, WN_OPCODE_print()); PRE_ORDER TRAV print opcode
00834 // WN_TREE_walk_post_order(wn, WN_OPCODE_print()); POST_ORDER TRAV print opcode
00835 // (A2) The above examples using a tree container
00836 //  WN_TREE_CONTAINER<PRE_ORDER>  wcpre(wn);
00837 //  WN_TREE_CONTAINER<POST_ORDER> wcpost(wn);
00838 //  WN_TREE_CONTAINER<PRE_ORDER> ::iterator wipre;
00839 //  WN_TREE_CONTAINER<POST_ORDER>::iterator wipost;
00840 // for (wipre=wcpre.begin(); wipre != wcpre.end(); ++wipre)
00841 //    WN_OPCODE_print(wipre.Wn());
00842 // for (wipost=wcpost.begin(); wipost != wcpost.end(); ++wipost)
00843 //    WN_OPCODE_print(wipost.Wn());
00844 
00845 // (B1)
00846 // next statement prints the number of nodes in the whirl tree
00847 // printf("Number of tree nodes = %d\n",
00848 //       WN_TREE_walk_pre_order (wn, WN_count()).num_nodes)
00849 // (B2) The above example using a tree container
00850 //  WN_count countpre;
00851 //  WN_count countpost;
00852 //    
00853 //  for (wipre = wcpre.begin();  wipre !=  wcpre.end(); ++wipre)  
00854 //    countpre(wipre.Wn());
00855 //  for (wipost = wcpost.begin(); wipost != wcpost.end(); ++wipost)
00856 //    countpost(wipost.Wn());
00857 //  Assert(countpre.num_nodes == countpost.num_nodes)
00858 
00859 // ======================================================================
00860 // Some function objects that can be useful
00861 // (C1) count the number of STIDs in the whirl tree
00862 // struct WN_count_STID {
00863 //  INT num_nodes;
00864 //  WN_count_STID() : num_nodes(0){}
00865 //  void  operator()(WN* wn) {
00866 //    if (OPCODE_operator(WN_OPCODE(wn)) ==OPR_STID)
00867 //            ++num_nodes;
00868 //  }
00869 // };
00870 // 
00871 // printf("Number of STID nodes = %d\n",
00872 //         WN_TREE_walk_pre_order (wn, WN_count_STID()).num_nodes)
00873 // 
00874 // (C2) The above example using a tree container
00875 //  WN_count_STID countstid;
00876 //  for (wipre = wcpre.begin();  wipre !=  wcpre.end(); ++wipre)  
00877 //    countstid(wipre.Wn());
00878 // printf("Number of STID nodes = %d\n",countstid.num_nodes)
00879 // (D1) Does a whirl tree have EH regions?
00880 // 
00881 // struct WN_EH_region_check {
00882 //  BOOL found;
00883 //  WN_EH_region_check() : found(FALSE){}
00884 //  void  operator()(WN* wn) {
00885 //        found = found || ((WN_operator(wn) == OPR_REGION) 
00886 //                          && WN_region_is_EH(wn))
00887 //  }
00888 // };
00889 // Use:
00890 // BOOL WN_HAS_EH_REGION (WN* wn) { 
00891 //      return WN_TREE_walk_pre_order (wn, WN_EH_region_check()).found;
00892 // }
00893 //
00894 //  if (WN_HAS_EH_REGION (wn))
00895 //    printf("wn has EH REGIONS\n");
00896 //  else
00897 //    printf("wn doesn't have EH REGIONS\n");    
00898 
00899 // ======================================================================
00900 // Using STL algorithms with the tree iterator
00901 // ======================================================================
00902 // Note: operator* on WN_TREE_ITER<..> returns a WN  (not a WN*)
00903 // Hence the predicates used in the algorithms (eg find_if) should
00904 // take a WN as an argument.
00905 //
00906 // - First the predicate definition
00907 // bool is_stid(WN w) { return (WN_operator(&w) == OPR_STID);}
00908 //
00909 // - Next, its usage 
00910 //  printf("First stid subtree in the tree\n");
00911 //  WN_TREE_CONTAINER<PRE_ORDER>::iterator it = 
00912 //    find_if(wcpre.begin(), wcpre.end(),is_stid);
00913 //  if (it.Wn())
00914 //    WN_TREE_dump_tree(it.Wn());
00915 
00916 
00917 #endif // wn_tree_util_INCLUDED
00918 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines