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