Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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