C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

location.cc

Go to the documentation of this file.
00001 // $Id: location.cc,v 1.23 2003/08/08 15:16:29 toktb Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Daniel A. Jimenez
00011 //  Calvin Lin
00012 // 
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //  
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //  
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
00035 //
00036 // ----------------------------------------------------------------------
00037 
00038 #include "c_breeze.h"
00039 #include "location.h"
00040 #include <limits>
00041 
00042 // ------------------------------------------------------------
00043 // Location
00044 // ------------------------------------------------------------
00045 
00046 unsigned int Location::stmt_count = 0;
00047 unsigned int Location::block_count = 0;
00048 unsigned int Location::proc_count = 0;
00049 unsigned int Location::dom_calls = 0;
00050 
00051 unsigned int Location::current_subtree_id = 0;
00052 unsigned int Location::current_tree_number = 0;
00053 
00054 Location::Location(Location * parent, LocationKind kind)
00055   : _parent(parent),
00056     _kind(kind),
00057     _num_children(0),
00058     _dominator(0),
00059     _tree_min(0),
00060     _tree_max(numeric_limits<unsigned int>::max())
00061 {
00062 
00063 #ifdef OLD_DOMINATOR_TEST
00064 
00065   _depth = parent ? parent->depth() + 1 : 0;
00066   _dominates_exit = 0;
00067   _not_basicblock = (kind != BasicBlock);
00068   _not_procedure = (kind != Procedure);
00069 
00070 #endif
00071 
00072   if (parent)
00073     _subtree_id = parent->subtree_id();
00074 }
00075 
00076 void Location::set_dominator(Location * d)
00077 {
00078   // -- Set the dominator
00079 
00080   _dominator = d;
00081 
00082   // -- Note the presence of the child on the dominator
00083 
00084   d->increment_children();
00085 }
00086 
00087 void Location::clear_dominator()
00088 {
00089   // -- Note the removal of the child on the dominator
00090 
00091   _dominator->decrement_children();
00092   
00093   // -- Clear the dominator
00094 
00095   _dominator = 0;
00096 }
00097 
00098 
00099 // Dominance tests
00100 
00101 bool Location::strictly_dominates(const Location * dom, const Location * cur)
00102 {
00103   // Quick short-circuits
00104 
00105   if (dom == cur)
00106     return false;
00107 
00108   // Don't bother comparing locations in disconnected subtrees (this only
00109   // occurs with context insensitive analysis).
00110 
00111   if (dom->subtree_id() != cur->subtree_id())
00112     return false;
00113 
00114 #ifdef OLD_DOMINATOR_TEST
00115 
00116   bool old_dominates = old_strictly_dominates(dom, cur);
00117 
00118 #endif
00119 
00120   dom_calls++;
00121 
00122   bool new_dominates = false;
00123 
00124   unsigned int dom_min = dom->tree_min();
00125   unsigned int cur_min = cur->tree_min();
00126   unsigned int dom_max = dom->tree_max();
00127   unsigned int cur_max = cur->tree_max();
00128 
00129   // if (dom_max == 0) dom_max = numeric_limits<unsigned int>::max();
00130   // if (cur_max == 0) cur_max = numeric_limits<unsigned int>::max();
00131  
00132   if ((dom_min < cur_min) && (cur_max <= dom_max))
00133     new_dominates = true;
00134 
00135   /*
00136   if (dom_min < cur_min) {
00137     dom_max = dom->tree_max();
00138     cur_max = cur->tree_max();
00139     if (dom_max == 0) dom_max = numeric_limits<unsigned int>::max();
00140     if (cur_max == 0) cur_max = numeric_limits<unsigned int>::max();
00141 
00142     if (cur_max <= dom_max)
00143       new_dominates = true;
00144   }
00145   */
00146 
00147 #ifdef OLD_DOMINATOR_TEST
00148 
00149   if (new_dominates != old_dominates) {
00150     cout << "TEST FAILED for " 
00151          << * dom << "(" << dom->tree_min() << " - " << dom->tree_max() << ")" << endl;
00152     
00153     if (old_dominates)
00154       cout << "          DOM " << endl;
00155     else
00156       cout << "          NOT DOM " << endl;
00157     
00158     cout << "                " << * cur << "(" << cur->tree_min() << " - " << cur->tree_max() << ")" << endl;
00159   }
00160 
00161 #endif
00162 
00163   return new_dominates;
00164 }
00165   
00166 #ifdef OLD_DOMINATOR_TEST
00167 
00168 bool Location::old_strictly_dominates(const Location * dom, const Location * cur)
00169 {
00170   // Quick short-circuits
00171 
00172   if (dom == cur)
00173     return false;
00174 
00175   // Don't bother comparing locations in disconnected subtrees (this only
00176   // occurs with context insensitive analysis).
00177 
00178   if (dom->subtree_id() != cur->subtree_id())
00179     return false;
00180 
00181   // Special case: main function entry point dominates everything
00182 
00183   if (dom == procLocation::main())
00184     return true;
00185 
00186   if (cur == procLocation::main())
00187     return false;
00188 
00189   dom_calls++;
00190 
00191   // Get to the same level in the context chain (side-effects dom_p and
00192   // cur_p by moving up the chain until they are at the same depth).
00193 
00194   const Location * dom_p = dom;
00195   const Location * cur_p = cur;
00196 
00197   unsigned int depth_dom = dom_p->depth();
00198   unsigned int depth_cur = cur_p->depth();
00199   unsigned int max_depth = (depth_dom > depth_cur) ? depth_dom : depth_cur;
00200 
00201   // -- The following flags are used whenever we need to move up in the
00202   // dominating location. For a location inside a procedure to dominate a
00203   // location outside that procedure, it must dominate the exit of the
00204   // procedure. Therefore, at each procedure boundary we cross, we need to
00205   // know that the basic block from which we came dominates the exit.
00206 
00207   // The algorithm works as follows:
00208   //   1. dom_exit is initially set to 1
00209   //   2. local_dom_exit is true when the last basic block
00210   //      visited dominates the exit.
00211   //   3. not_procedure_boundary is true as long as we have
00212   //      never crossed a procedure boundary
00213   // => dom_exit is true if it was previously true, and if
00214   //      either we have never crossed a boundary, or the
00215   //      last basic block visited dominates its exit.
00216 
00217   unsigned int dom_exit = 1;
00218   unsigned int local_dom_exit = 0;
00219   unsigned int not_procedure_boundary = 1;
00220 
00221   while ((depth_dom > depth_cur) & dom_exit) {
00222 
00223     // -- At each basic block, reset local_dom_exit
00224 
00225     local_dom_exit &= dom_p->_not_basicblock;
00226 
00227     // -- Whenever we hit a basic block, record whether it dominates the
00228     // exit. Since dominates_exit() is false for all other nodes, they
00229     // don't affect the value.
00230 
00231     local_dom_exit |= dom_p->dominates_exit();
00232 
00233     // -- Record whether we have NOT hit a procedure boundary. This value
00234     // starts out true, but once we hit a procedure boundary it turns
00235     // false, and stays that way. That tells the algorithm that it's
00236     // important to check for dominates_exit.
00237 
00238     not_procedure_boundary &= dom_p->_not_procedure;
00239 
00240     // -- Compute dom_exit: either the most recently visited basic block
00241     // must dominate the exit, or we have not crossed a procedure boundary
00242     // yet. Once this value is false, it stays false.
00243 
00244     dom_exit &= (local_dom_exit | not_procedure_boundary );
00245 
00246     // -- Move up
00247 
00248     dom_p = dom_p->parent();
00249     depth_dom--;
00250   }
00251 
00252   // -- Short circuit: if dom_exit is false, then we crossed a procedure
00253   // boundary in which the basic block we came from didn't dominate the
00254   // exit node: therefore, it cannot dominate the input location.
00255 
00256   if ( ! dom_exit )
00257     return false;
00258 
00259   while (depth_cur > depth_dom) {
00260     cur_p = cur_p->parent();
00261     depth_cur--;
00262   }
00263 
00264   // --- One is a prefix of the other; use the special rules described
00265   // in the header file.
00266 
00267   if (dom_p == cur_p) {
00268     if (dom->depth() > cur->depth()) {
00269       // Dom is the descendant -- it only dominates ancestor
00270       // statements.
00271 
00272       return (cur->kind() == Statement);
00273     }
00274     else {
00275       // Dom is the ancestor -- it always dominates, unless it is a
00276       // statement.
00277 
00278       return (dom->kind() != Statement);
00279     }
00280   }
00281 
00282   // --- Find a common parent
00283 
00284   const Location * dom_next = dom_p->parent();
00285   const Location * cur_next = cur_p->parent();
00286 
00287   while ((dom_next != cur_next) & dom_exit) {
00288 
00289     // -- Use the same algorithm to determine whether dom_p dominates the
00290     // exit of any procedure that we cross.
00291 
00292     local_dom_exit &= dom_p->_not_basicblock;
00293     local_dom_exit |= dom_p->dominates_exit();
00294     not_procedure_boundary &= dom_p->_not_procedure;
00295     dom_exit &= (local_dom_exit | not_procedure_boundary );
00296 
00297     // -- Move up
00298 
00299     dom_p = dom_next;
00300     dom_next = dom_p->parent();
00301 
00302     cur_p = cur_next;
00303     cur_next = cur_p->parent();
00304   }
00305 
00306   // --- Same short-circuit:
00307 
00308   if ( ! dom_exit )
00309     return false;
00310 
00311   // --- Found a common parent, so test dominance locally
00312 
00313   if (dom_p->kind() == Statement) {
00314     stmtLocation * dom_s = (stmtLocation *) dom_p;
00315     stmtLocation * cur_s = (stmtLocation *) cur_p;
00316 
00317     return (dom_s->stmt_num() < cur_s->stmt_num());
00318   }
00319 
00320   if (dom_p->kind() == BasicBlock) {
00321     basicblockLocation * dom_b = (basicblockLocation *) dom_p;
00322     basicblockLocation * cur_b = (basicblockLocation *) cur_p;
00323 
00324     return Dominators::dominates(dom_b->block(), cur_b->block());
00325   }
00326 
00327   // --- This shouldn't happen
00328 
00329   // --- HOWEVER, with context insensitivity, it can
00330 
00331   return false;
00332 
00333   cerr << "ERROR: Cannot determine path dominance." << endl;
00334   cerr << "   Dom  : " << *dom << " depth = " << dom->depth() << endl;
00335   if (dom_p)
00336     cerr << "   DomP : " << *dom_p << " depth = " << dom_p->depth() << endl;
00337   cerr << "   Cur  : " << *cur << " depth = " << cur->depth() << endl;
00338   if (cur_p)
00339     cerr << "   CurP : " << *cur_p << " depth = " << cur_p->depth() << endl;
00340   
00341   return false;
00342 }
00343 
00344 Location * Location::common_parent(Location * one,
00345                                    Location * two)
00346 {
00347   if (one == two)
00348     return one;
00349 
00350   // Get to the same level in the context chain (side-effects one_p and
00351   // two_p by moving up the chain until they are at the same depth).
00352 
00353   Location * one_p = one;
00354   Location * two_p = two;
00355 
00356   unsigned int depth_one = one_p->depth();
00357   unsigned int depth_two = two_p->depth();
00358   unsigned int max_depth = (depth_one > depth_two) ? depth_one : depth_two;
00359 
00360   while (depth_one > depth_two) {
00361     one_p = one_p->parent();
00362     depth_one--;
00363   }
00364 
00365   while (depth_two > depth_one) {
00366     two_p = two_p->parent();
00367     depth_two--;
00368   }
00369 
00370   // --- One is a prefix of the other; return it
00371 
00372   if (one_p == two_p)
00373     return one_p;
00374 
00375   // --- Find a common parent
00376 
00377   Location * one_next = one_p->parent();
00378   Location * two_next = two_p->parent();
00379 
00380   while (one_next != two_next) {
00381 
00382     one_p = one_next;
00383     one_next = one_p->parent();
00384 
00385     two_p = two_next;
00386     two_next = two_p->parent();
00387   }
00388 
00389   return one_p;
00390 }
00391 
00392 #endif
00393 
00394 
00395 procLocation * Location::procedure(Location * where)
00396 {
00397   if (where->kind() == Procedure)
00398     return (procLocation *) where;
00399 
00400   if (where->kind() == Statement) {
00401     stmtLocation * stmt = (stmtLocation *) where;
00402     return stmt->block_location()->proc_location();
00403   }
00404 
00405   if (where->kind() == BasicBlock) {
00406     basicblockLocation * block = (basicblockLocation *) where;
00407     return block->proc_location();
00408   }
00409 
00410   return 0;
00411 }
00412 
00413 bool Location::is_prefix(const Location * prefix, const Location * longer)
00414 {
00415   while (longer) {
00416     if (longer == prefix)
00417       return true;
00418     longer = longer->parent();
00419   }
00420 
00421   return false;
00422 }
00423 
00424 void Location::stats()
00425 {
00426   cout << "  stmtLocation : " << stmt_count << " objects x " 
00427        << sizeof(stmtLocation) << " bytes = " << stmt_count * sizeof(stmtLocation) 
00428        << " bytes. " << endl;
00429 
00430   cout << "  basicblockLocation : " << block_count << " objects x " 
00431        << sizeof(basicblockLocation) << " bytes = " << block_count * sizeof(basicblockLocation) 
00432        << " bytes. " << endl;
00433 
00434   cout << "  procLocation : " << proc_count << " objects x " 
00435        << sizeof(procLocation) << " bytes = " << proc_count * sizeof(procLocation) 
00436        << " bytes. " << endl;
00437 
00438 }
00439   
00440 
00441 bool Location::dominates(const Location * dom, const Location * cur)
00442 {
00443   if (dom == cur)
00444     return true;
00445 
00446   return strictly_dominates(dom, cur);
00447 }
00448 
00449 Location::~Location()
00450 {
00451 }
00452 
00453 // ------------------------------------------------------------
00454 //  Tree numbering algorithm
00455 // ------------------------------------------------------------
00456 
00457 void Location::visit()
00458 {
00459   if (tree_min() == 0) {
00460 
00461     set_tree_min(next_tree_number());
00462 
00463     /*
00464     cout << "set tree min = " << tree_min() << " for " << *this;
00465     if (dominator())
00466       cout << " IDOM = " << * dominator() << endl;
00467     else
00468       cout << " (No dominator)" << endl;
00469     */
00470   }
00471 }
00472 
00473 
00474 void Location::finish()
00475 {
00476   if ((tree_max() == numeric_limits<unsigned int>::max()) &&
00477       (num_children() == 0))
00478     {
00479       // -- Dominator leaf node: start setting tree max values
00480 
00481       unsigned int cur_max = tree_min();
00482       Location * cur_node = this;
00483       Location * cur_dom;
00484 
00485       do {
00486         cur_node->set_tree_max(next_tree_number());
00487         cur_dom = cur_node->dominator();
00488 
00489         /*
00490         cout << "set tree max = " << cur_node->tree_max() << " for " << * cur_node;
00491         if (cur_dom)
00492           cout << " IDOM = " << * cur_dom << endl;
00493         else
00494           cout << " (No dominator)" << endl;
00495         */
00496 
00497         cur_node = cur_dom;
00498 
00499         if (cur_node)
00500           cur_node->decrement_children();
00501 
00502       } while (cur_node &&
00503                (cur_node->num_children() == 0));
00504     }
00505 }
00506 
00507 // ------------------------------------------------------------
00508 // stmtLocation
00509 // ------------------------------------------------------------
00510 
00511 stmtLocation::stmtLocation(basicblockLocation * parent)
00512   : Location(parent, Statement),
00513     _stmt_num(0),
00514     _calls(0)
00515 {
00516   Location::stmt_count++;
00517 }
00518 
00519 // At a call-site : look up the procLocation, creating it if
00520 // necessary.
00521 
00522 void stmtLocation::setup_cs_call(procNode * proc)
00523 {
00524   if(_calls && _calls->proc() != proc) { // TB need a new _calls
00525     _calls = _all_calls[proc];
00526   }
00527 
00528   if (! _calls) {
00529     _calls = _all_calls[proc] = new procLocation(this, proc, false);
00530 
00531     // -- Set tree numbering on the new procLocation
00532 
00533     _calls->visit();
00534 
00535     // -- The new procedure is dominated by the old dominator of the
00536     // statement.
00537 
00538     _calls->set_dominator(dominator());
00539     clear_dominator();
00540 
00541     // -- Reset the tree min (it will be fixed later)
00542 
00543     set_tree_min(0);
00544 
00545     // cout << "un  tree_min = 0 for " << *this << endl;
00546 
00547     // -- The statement itself is now dominated by the exit of the
00548     // procedure.
00549 
00550     set_dominator(_calls->last());
00551   }
00552 }
00553 
00559 procLocation * stmtLocation::remove_call()
00560 {
00561   procLocation * out = 0;
00562 
00563   if (_calls) {
00564 
00565     // -- Disconnect the pointers
00566 
00567     out = _calls;
00568     out->remove_from_tree();
00569     _calls = 0;
00570 
00571     // -- Undo the dominator links from setup_call()
00572 
00573     set_dominator(out->dominator());
00574     out->clear_dominator();
00575 
00576     // -- Number the stmtLocation now, if it needs it. This is critical for
00577     // handling recursive procedures.
00578 
00579     visit();
00580   }
00581 
00582   return out;
00583 }
00584 
00589 /* TB: remove.
00590 callNode * stmtLocation::callnode()
00591 {
00592   stmtNode * the_stmt = stmt();
00593   callNode * call = findCallNodeWalker::find(the_stmt);
00594 
00595   / * -- This doesn't work any more...
00596   if (the_stmt->typ() == Expr) {
00597     exprstmtNode * es = (exprstmtNode *) the_stmt;
00598     exprNode * e = es->expr();
00599     if (e) {
00600       if (e->typ() == Call)
00601         call = (callNode *)e;
00602       if (e->typ() == Binary) {
00603         binaryNode * b = (binaryNode *) e;
00604         if (b->right()->typ() == Call)
00605           call = (callNode *) b->right();
00606       }
00607     }
00608   }
00609   * /
00610 
00611   return call;
00612 } */
00613 
00614 // Check for the presence of a function call
00615 
00616 bool stmtLocation::is_present(const procNode * proc) const
00617 {
00618   const procLocation * procl = block_location()->proc_location();
00619   if (procl->proc() == proc)
00620     return true;
00621 
00622   if (procl->stmt_location())
00623     return procl->stmt_location()->is_present(proc);
00624 
00625   return false;
00626 }
00627 
00628 void stmtLocation::adjust_depth()
00629 {
00630 #ifdef OLD_DOMINATOR_TEST
00631 
00632   // -- Adjust the depth here
00633   
00634   _depth = _parent->depth() + 1;
00635 
00636 #endif
00637 
00638   // -- Fix the subtree ID
00639 
00640   _subtree_id = _parent->subtree_id();
00641 
00642   // -- Visit the called procedure
00643  
00644   if (_calls)
00645     _calls->adjust_depth();
00646 }
00647 
00648 // Output
00649 
00650 void stmtLocation::print(ostream & o) const
00651 {
00652 
00653 }
00654 
00655 void stmtLocation::print_path(ostream & o) const
00656 {
00657   block_location()->print_path(o);
00658   o << ':' << _stmt_num << '(' << _stmt->coord() << ')';
00659 }
00660 
00661 void stmtLocation::print_callsite(ostream & o) const
00662 {
00663   basicblockLocation * bb = block_location();
00664   procLocation * p = bb->proc_location();
00665 
00666   o << p->proc()->decl()->name() 
00667     << ':' << bb->block()->dfn()
00668     << ':' << _stmt_num;
00669 }
00670 
00671 // Destructor
00672 
00673 stmtLocation::~stmtLocation()
00674 {
00675   // If this is a call-site, delete the called procedure location
00676 
00677   if (_calls)
00678     delete _calls;
00679 
00680   Location::stmt_count--;
00681 }
00682 
00683 // ------------------------------------------------------------
00684 // basicblockLocation
00685 // ------------------------------------------------------------
00686 
00687 basicblockLocation::basicblockLocation(procLocation * parent,
00688                                        basicblockNode * block)
00689   : Location(parent, BasicBlock),
00690     _block(block),
00691     _statements(block->stmts().size(), stmtLocation(this))
00692 {
00693   basicblockNode * exit = parent->proc()->exit();
00694 
00695 #ifdef OLD_DOMINATOR_TEST
00696 
00697   // -- Figure out if this block dominates the exit
00698 
00699   _dominates_exit = Dominators::dominates(block , exit);
00700 
00701 #endif
00702 
00703   // -- First statement is dominated by the basic block itself.
00704 
00705   Location * cur_dom = this;
00706 
00707   // -- Set all the statement numbers and stmtNode pointers
00708 
00709   stmt_list & stmts = block->stmts();
00710   unsigned int num = 0;
00711 
00712   for (stmt_list_p p = stmts.begin();
00713        p != stmts.end();
00714        ++p)
00715     {
00716       stmtLocation * cur_stmt = & _statements[num];
00717       cur_stmt->stmt_num(num);
00718       cur_stmt->stmt(*p);
00719       num++;
00720 
00721       // -- Each subsequent statement is dominated by the previous
00722       // statement.
00723 
00724       cur_stmt->set_dominator(cur_dom);
00725       cur_dom = cur_stmt;
00726     }
00727 
00728   Location::block_count++;
00729   Location::stmt_count += block->stmts().size();
00730 }
00731 
00732 void basicblockLocation::adjust_depth()
00733 {
00734 
00735 #ifdef OLD_DOMINATOR_TEST
00736 
00737   // -- Adjust the depth here
00738 
00739   _depth = _parent->depth() + 1;
00740 
00741 #endif
00742 
00743   // -- Fix the subtree ID
00744 
00745   _subtree_id = _parent->subtree_id();
00746 
00747   // -- Visit the statements
00748 
00749   unsigned int size = _statements.size();
00750 
00751   for (unsigned int i = 0; i < size ; i++)
00752     _statements[i].adjust_depth();
00753 }
00754 
00755 // Output
00756 
00757 void basicblockLocation::print(ostream & o) const
00758 {
00759 
00760 }
00761 
00762 void basicblockLocation::print_path(ostream & o) const
00763 {
00764   proc_location()->print_path(o);
00765   o << ':' << block()->dfn();
00766 }
00767 
00768 // Destructor
00769 
00770 basicblockLocation::~basicblockLocation()
00771 {
00772   Location::block_count--;
00773   // stmtLocation takes care of this: Location::stmt_count -= block()->stmts().size() - 1;
00774 }
00775 
00776 // ------------------------------------------------------------
00777 // procLocation
00778 // ------------------------------------------------------------
00779 
00780 procLocation * procLocation::Main = 0;
00781 
00782 static unsigned int progress_counter = 0;
00783 
00784 procLocation::procLocation(stmtLocation * parent,
00785                            procNode * proc,
00786                            bool context_insensitive)
00787   : Location(parent, Procedure),
00788     _proc(proc),
00789     _basicblocks()
00790 {
00791   Location::proc_count++;
00792 
00793   if (! parent) {
00794 
00795     // -- The only function with no parent should be the main function
00796 
00797     Main = this;
00798 
00799     current_subtree_id = 0;
00800     _subtree_id = current_subtree_id;
00801 
00802     // -- Main function starts the tree numbering at 1
00803 
00804     current_tree_number = 0;
00805     set_tree_min(next_tree_number());
00806   }
00807 
00808   /*
00809   // -- At context sensitive callsites, just create a single node that
00810   // represents the call. We use this to attach uses and defs that pass
00811   // external inputs and outputs from the context.
00812 
00813   if (is_context_insensitive)
00814     return;
00815   */
00816 
00817   // Set up each basic block
00818 
00819   stmt_list & stmts = proc->body()->stmts();
00820   for (stmt_list_p p = stmts.begin();
00821        p != stmts.end();
00822        ++p)
00823     {
00824       basicblockNode * block = (basicblockNode *) *p;
00825 
00826       // -- Make a new basic block (including statements)
00827 
00828       basicblockLocation * block_loc = new basicblockLocation(this, block);
00829 
00830       // -- Store it
00831 
00832       _basicblocks[block] = block_loc;
00833     }
00834 
00835   progress_counter++;
00836 
00837   // -- Progress counter is now in the pointer analyzer
00838   // if (progress_counter % 100 == 0)
00839   //  cout << "Progress: " << progress_counter << " at " << *this << endl;
00840 
00841   // -- Set up the dominators
00842 
00843   for (basicblock_location_map_p p = _basicblocks.begin();
00844        p != _basicblocks.end();
00845        ++p)
00846     {
00847       basicblockNode * bb = (*p).first;
00848       basicblockLocation * block_loc = (*p).second;
00849 
00850       // -- The entry block is dominated by the procLocation
00851 
00852       if (bb == proc->entry())
00853         block_loc->set_dominator(this);
00854       else {
00855 
00856         // -- All other blocks are dominated by the last statement in the
00857         // dominating block.
00858 
00859         basicblockNode * dom = bb->parent();
00860         basicblockLocation * dom_loc = lookup_block(dom);
00861         block_loc->set_dominator(dom_loc->last());
00862       }
00863     }
00864 
00865   // -- For context-insensitive procedures, remove the structure from the
00866   // tree immediately and assign the proper subtree numbers.
00867 
00868   if (context_insensitive)
00869     remove_from_tree();
00870 }
00871 
00872 /*
00873 Location * procLocation::parent() const
00874 {
00875   return _parent;
00876 }
00877 */
00878 
00879 basicblockLocation * procLocation::lookup_block(basicblockNode * block) const
00880 {
00881   basicblock_location_map_cp p = _basicblocks.find(block);
00882   return (*p).second; // Should never == _basicblocks.end()
00883 }
00884 
00885 procLocation * procLocation::parent_proc() const
00886 {
00887   if (_parent) {
00888     stmtLocation * parent2 = (stmtLocation *) _parent;
00889     return parent2->block_location()->proc_location();
00890   }
00891   else
00892     return 0;
00893 }
00894 
00895 // -- Find the last statement
00896 
00897 stmtLocation * procLocation::last()
00898 {
00899   basicblockNode * the_exit = _proc->exit();
00900   basicblockLocation * the_exit_location = lookup_block(the_exit);
00901   return the_exit_location->last();
00902 }
00903 
00909 void procLocation::remove_from_tree()
00910 {
00911   // -- Disconnect the parent
00912 
00913   _parent = 0;
00914 
00915   // -- Get a new subtree ID
00916 
00917   current_subtree_id++;
00918   _subtree_id = current_subtree_id;
00919 
00920   // -- Adjust the depth numbers and assign the new subtree ID
00921 
00922   adjust_depth();
00923 }
00924 
00925 void procLocation::adjust_depth()
00926 {
00927 
00928 #ifdef OLD_DOMINATOR_TEST
00929 
00930   // -- Adjust the depth here
00931 
00932   if (_parent)
00933     _depth = _parent->depth() + 1;
00934   else
00935     _depth = 0;
00936 
00937 #endif
00938 
00939 
00940   if (_parent) {
00941 
00942     // -- Fix the subtree ID
00943 
00944     _subtree_id = _parent->subtree_id();
00945   }
00946 
00947   // -- Visit all the basic blocks
00948 
00949   for (basicblock_location_map_p p = _basicblocks.begin();
00950        p != _basicblocks.end();
00951        ++p)
00952     (*p).second->adjust_depth();
00953 }
00954 
00955 // Output
00956 
00957 void procLocation::print(ostream & o) const
00958 {
00959 
00960 }
00961 
00962 void procLocation::print_path(ostream & o) const
00963 {
00964   if (stmt_location()) {
00965     stmt_location()->print_path(o);
00966     o << '/';
00967   }
00968   o << _proc->decl()->name();
00969 }
00970 
00971 // Destructor
00972 
00973 procLocation::~procLocation()
00974 {
00975   // Delete all the contained basic blocks
00976 
00977   for (basicblock_location_map_p p = _basicblocks.begin();
00978        p != _basicblocks.end();
00979        ++p)
00980     delete (*p).second;
00981 
00982   progress_counter--;
00983 
00984   // Handle the main
00985 
00986   if (this == Main)
00987     Main = 0;
00988 
00989   Location::proc_count--;
00990 }

Generated on August 27, 2003
Back to the C-Breeze home page