ManagerCFG.cpp

Go to the documentation of this file.
00001 
00015 // standard headers
00016 
00017 #ifdef NO_STD_CHEADERS
00018 # include <stdlib.h>
00019 # include <string.h>
00020 # include <assert.h>
00021 #else
00022 # include <cstdlib>
00023 # include <cstring>
00024 # include <cassert>
00025 using namespace std; // For compatibility with non-std C headers
00026 #endif
00027 
00028 #include <iostream>
00029 using std::ostream;
00030 using std::endl;
00031 using std::cout;
00032 using std::cerr;
00033 #include <list>
00034 #include <set>
00035 #include <map>
00036 
00037 // Mint headers
00038 #include "ManagerCFG.hpp"
00039 
00040 
00041 namespace OA {
00042   namespace CFG {
00043 
00044 static bool debug = false;
00045 
00046   ManagerCFGStandard::ManagerCFGStandard (OA_ptr<CFGIRInterface> _ir,
00047                                 bool _build_stmt_level_cfg /* = false */ )
00048         : mIR(_ir), mBuildStmtLevelCFG(_build_stmt_level_cfg)
00049         {
00050  
00051        
00052              OA_DEBUG_CTRL_MACRO("DEBUG_ManagerCFG:ALL", debug);
00053              mFallThrough.clear();
00054         }
00055 
00056 
00057   OA_ptr<CFG> ManagerCFGStandard::performAnalysis(ProcHandle proc)
00058   {
00059     // get information from the ir interface
00060     bool return_statements_allowed = mIR->returnStatementsAllowed();
00061     // create a CFG that just has an entry and an exit node
00062     mCFG = new CFG();
00063     OA_ptr<NodesIteratorInterface> nodes_iter;
00064     // Create the unique entry node.
00065     OA_ptr<Node> entry; 
00066     entry = new Node();
00067     mCFG->setEntry(entry);
00068     mCFG->addNode(entry);
00069 
00070     // Create the actual start node where the first statements wil be added.
00071     OA_ptr<Node> r; r = new Node();
00072     mCFG->addNode(r);
00073     mCFG->connect (mCFG->getEntry(), r, FALLTHROUGH_EDGE);
00074     CFG::NodeLabelList exit_nodes;
00075     // some NodeLabelList's are OA_ptr's instead of passed around by reference
00076     // because some of the logic looks to see if the list is NULL
00077     OA_ptr<CFG::NodeLabelList> return_nodes;
00078     return_nodes = new CFG::NodeLabelList;
00079     OA_ptr<IRRegionStmtIterator> stmt_iterptr = mIR->procBody(proc);
00080     OA_ptr<CFG::NodeLabelList> nullList; nullList = NULL;
00081 
00082     if (return_statements_allowed) {
00083       build_block(r, stmt_iterptr, exit_nodes, nullList, return_nodes, nullList);
00084     } else {
00085       build_block(r, stmt_iterptr, exit_nodes, nullList, nullList, nullList);
00086     }
00087 
00088     // create unique exit node
00089     OA_ptr<Node> final; final = new Node();
00090     mCFG->addNode(final);
00091     mCFG->setExit(final);
00092     // connect the exit nodes to the final node
00093     mCFG->connect(exit_nodes, final);
00094     // return nodes also lead to the exit node of the sub-program
00095     mCFG->connect(*return_nodes, final);
00096     // finalize control flow for unstructured constructs
00097     HandleDelayedBranches();
00098     return mCFG;
00099 
00100   }
00101 
00102 
00103   //--------------------------------------------------------------------
00104   IRStmtType
00105   ManagerCFGStandard::build_block (OA_ptr<Node> prev_node,
00106                                 OA_ptr<IRRegionStmtIterator> si_ptr,
00107                                 std::list<CFG::NodeLabel>& exit_nodes,
00108                                 OA_ptr<std::list<CFG::NodeLabel> > break_nodes,
00109                                 OA_ptr<std::list<CFG::NodeLabel> > return_nodes,
00110                                 OA_ptr<std::list<CFG::NodeLabel> > continue_nodes)
00111   {
00112       std::list<CFG::NodeLabel> x_nodes;
00113 
00114       IRStmtType prev_statement = SIMPLE;
00115       while (si_ptr->isValid()) {
00116         StmtHandle stmt = si_ptr->current();
00117         if (debug) { std::cout << mIR->toString(stmt) << std::endl; }
00118        
00119         if (mIR->getLabel(stmt)) {
00120             StmtLabel lab = mIR->getLabel(stmt);
00121             OA_ptr<Node> new_node;
00122          
00123             if (mCFG->isLabelMappedToNode(lab)) {
00124                 new_node = mCFG->node_from_label(lab);
00125             } else if (! prev_node->empty()) {
00126                 new_node = new Node();
00127                 mCFG->addNode(new_node);
00128                 if(debug) {
00129                     cout << "\nCFG Node";
00130                     new_node->dump(cout , mIR);
00131                     cout << "\n";
00132                 }
00133                 mCFG->mapLabelToNode(lab,new_node);
00134 
00135             } else {
00136                 mCFG->mapLabelToNode(lab,prev_node);
00137                 new_node = prev_node;
00138             }
00139 
00140             if (prev_statement != SIMPLE && !new_node.ptrEqual(prev_node)) {
00141                 mCFG->connect(x_nodes, new_node);
00142             } else if (!prev_node.ptrEqual(NULL)
00143                      && !new_node.ptrEqual(prev_node))
00144             {
00145                 mCFG->connect(prev_node, new_node, FALLTHROUGH_EDGE);
00146             }
00147             x_nodes.clear();
00148             prev_node = new_node;
00149       
00150                   
00151          } else if (mBuildStmtLevelCFG) {
00152             if (!prev_node->empty()) {
00153                 OA_ptr<Node> new_node;
00154                 new_node = new Node();
00155                 mCFG->addNode(new_node);
00156                 if(debug) {
00157                     cout << "\n CFG Node";
00158                     new_node->dump(cout , mIR);
00159                     cout << "\n";
00160                 }
00161 
00162                
00163                 if (prev_statement == SIMPLE) {
00164                     mCFG->connect(prev_node, new_node, FALLTHROUGH_EDGE);
00165                 } else {
00166                    mCFG->connect(x_nodes, new_node);
00167                 }
00168                 prev_node = new_node;
00169             }  
00170             x_nodes.clear();
00171 
00172          } else if (prev_statement != SIMPLE) {
00173             // now we need to create a new CFG node
00174             prev_node = new Node();
00175             mCFG->addNode(prev_node);
00176             if(debug) {
00177                  cout << "\n CFG Node";
00178                  prev_node->dump(cout , mIR);
00179                  cout << "\n";
00180             }
00181 
00182 
00183             mCFG->connect(x_nodes, prev_node);
00184             x_nodes.clear();
00185          }
00186          prev_statement = build_stmt(prev_node, stmt, x_nodes, break_nodes,
00187                                                       return_nodes, continue_nodes);
00188          ++(*si_ptr);
00189       }  
00190 
00191        
00192       if (prev_statement == SIMPLE) {
00193         exit_nodes.push_back(CFG::NodeLabel(prev_node,
00194                          FALLTHROUGH_EDGE));
00195       } else {
00196         CFG::NodeLabelListIterator x_nodes_iter(x_nodes);
00197         while (x_nodes_iter.isValid()) {
00198           exit_nodes.push_back(x_nodes_iter.current());
00199           ++x_nodes_iter;
00200         }
00201       }
00202       
00203       return NONE;
00204   }
00205 
00206 
00207   //--------------------------------------------------------------------
00220 IRStmtType
00221 ManagerCFGStandard::build_stmt (OA_ptr<Node> prev_node,
00222     OA::StmtHandle stmt,
00223     std::list<CFG::NodeLabel>& exit_nodes,
00224     OA_ptr<std::list<CFG::NodeLabel> > break_nodes,
00225     OA_ptr<std::list<CFG::NodeLabel> > return_nodes,
00226     OA_ptr<std::list<CFG::NodeLabel> > continue_nodes)
00227 {
00228     switch (mIR->getCFGStmtType(stmt)) {
00229        case SIMPLE:
00230          {
00231             prev_node->add(stmt);
00232             if (debug) { std::cout << mIR->toString(stmt) << std::endl; }
00233             return SIMPLE;
00234          }
00235        case COMPOUND:
00236          {
00237             build_block(prev_node, mIR->getFirstInCompound(stmt), exit_nodes,
00238             break_nodes, return_nodes, continue_nodes);
00239             return COMPOUND;
00240          }
00241        case BREAK:
00242          {
00243             prev_node->add(stmt);
00244             if (break_nodes.ptrEqual(0)) {
00245                //  throw Unexpected_Break();
00246             } else {
00247                break_nodes->push_back(CFG::NodeLabel(prev_node,
00248                                BREAK_EDGE));
00249             }
00250             return BREAK;
00251          }
00252        case RETURN:
00253          {
00254             prev_node->add(stmt);
00255             if (return_nodes.ptrEqual(0)) {
00256                //throw Unexpected_Return();
00257             } else {
00258               return_nodes->push_back(CFG::NodeLabel(prev_node,
00259                                 RETURN_EDGE));
00260             }
00261            return RETURN;
00262          }
00263        case LOOP:
00264        {
00265            return build_CFG_loop (prev_node, stmt, exit_nodes, return_nodes);
00266        }
00267  
00268        case STRUCT_TWOWAY_CONDITIONAL:
00269        {
00270            return build_CFG_twoway_branch (prev_node, stmt, exit_nodes, break_nodes,
00271                                       return_nodes, continue_nodes);
00272        }
00273 
00274        case STRUCT_MULTIWAY_CONDITIONAL:
00275        {
00276             if (mIR->isBreakImplied(stmt)) {
00277                 return build_CFG_multiway_branch (prev_node, stmt, exit_nodes,
00278                                           break_nodes, return_nodes,
00279                                           continue_nodes);
00280             }else {
00281                 return build_CFG_multiway_branch_with_fallthrough (prev_node, stmt,                                           exit_nodes, return_nodes, continue_nodes);
00282             }
00283             
00284        } 
00285 
00286        case END_TESTED_LOOP:
00287        {
00288             return build_CFG_end_tested_loop (prev_node, stmt, exit_nodes, return_nodes);
00289        }
00290       
00291        case LOOP_CONTINUE:
00292        {
00293             prev_node->add(stmt);
00294             if (continue_nodes.ptrEqual(0)) {
00295       //         throw Unexpected_Continue();
00296             } else {
00297                  continue_nodes->push_back(CFG::NodeLabel(prev_node,
00298                                   CONTINUE_EDGE));
00299             }
00300             return LOOP_CONTINUE;
00301        }
00302        //
00303        // These unstructured constructs have the possibility of being
00304        // delayed branches (depending on the underlying machine). Those
00305        // without delay slots are handled now.  Those with delay slots
00306        // are just added as simple statements.  A post-processing step
00307        // will finalize control flow for them.
00308        //
00309        case UNCONDITIONAL_JUMP:
00310        {
00311             if (mIR->numberOfDelaySlots(stmt) == 0) {
00312                 return build_CFG_unconditional_jump (prev_node, stmt);
00313             } else {
00314                 prev_node->add(stmt);
00315                 return SIMPLE;
00316             }
00317        }
00318        case USTRUCT_TWOWAY_CONDITIONAL_T:
00319        case USTRUCT_TWOWAY_CONDITIONAL_F:
00320        {
00321              if (mIR->numberOfDelaySlots(stmt) == 0) {
00322                 return build_CFG_ustruct_twoway_branch (prev_node, stmt, exit_nodes);
00323              } else {
00324                 prev_node->add(stmt);
00325                 return SIMPLE;
00326              }
00327        }
00328       case UNCONDITIONAL_JUMP_I:
00329        {
00330             if (mIR->numberOfDelaySlots(stmt) == 0) {
00331                 return build_CFG_unconditional_jump_i (prev_node, stmt);
00332             } else {
00333                 prev_node->add(stmt);
00334                 return SIMPLE;
00335             }
00336        }
00337       case USTRUCT_MULTIWAY_CONDITIONAL:
00338        {    
00339            // Currently assume multiways don't have delay slots.
00340            assert(mIR->numberOfDelaySlots(stmt) == 0);
00341            return build_CFG_ustruct_multiway_branch (prev_node, stmt);
00342        }
00343            // FIXME: Unimplemented.
00344       case ALTERNATE_PROC_ENTRY:
00345        {
00346            cout << "FIXME: ALTERNATE_PROC_ENTRY not yet implemented" << endl;
00347            assert (0);
00348            return ALTERNATE_PROC_ENTRY;
00349        }
00350     default:
00351        {
00352            assert (0);
00353        }
00354 
00355  
00356     }
00357 }
00358 
00359 
00360 IRStmtType
00361 ManagerCFGStandard::build_CFG_loop(OA_ptr<Node> prev_node,
00362                                 StmtHandle th,
00363                                 std::list<CFG::NodeLabel>& exit_nodes,
00364                                 OA_ptr<std::list<CFG::NodeLabel> > return_nodes)
00365 {
00366     // If there is a header, (as in a "for" loop), it is assimilated in the
00367   // previous (prev_node) CFG node.  The condition needs a separate CFG node.
00368   // So, unless prev_node is empty (in which case that can become the
00369   // condition node) a new CFG node must be allocated for the loop condition.
00370   OA_ptr<Node> c;
00371 
00372   StmtHandle header = mIR->loopHeader(th);
00373   if (header) {
00374     prev_node->add(header);
00375   }
00376 
00377   // To handle C and Fortran loops in the simplest way we take the following
00378   // measures:
00379   //
00380   // If the number of loop iterations is defined
00381   // at loop entry (i.e. Fortran semantics), we add the loop statement
00382   // representative to the header node so that definitions from inside
00383   // the loop don't reach the condition and increment specifications
00384   // in the loop statement.
00385   //
00386   // On the other hand, if the number of iterations is not defined at
00387   // entry (i.e. C semantics), we add the loop statement to a node that
00388   // is inside the loop in the CFG so definitions inside the loop will
00389   // reach uses in the conditional test. for C style semantics, the
00390   // increment itself may be a separate statement. if so, it will appear
00391   // explicitly at the bottom of the loop.
00392 
00393   bool definedAtEntry =  mIR->loopIterationsDefinedAtEntry(th);
00394   if (definedAtEntry) {
00395     prev_node->add(th);
00396   }
00397   if (prev_node->empty()) {
00398     prev_node->add(th);
00399     c = prev_node;
00400   }
00401   else {
00402     c = new Node(th);
00403     mCFG->addNode(c);
00404     mCFG->connect(prev_node, c, FALLTHROUGH_EDGE);
00405   }
00406   exit_nodes.push_back(CFG::NodeLabel(c, FALSE_EDGE));
00407 
00408   // allocate a new CFG node for the loop body and recur
00409   std::list<CFG::NodeLabel> x_nodes;
00410   OA_ptr<IRRegionStmtIterator> body = mIR->loopBody(th);
00411   if (body->isValid() && body->current()) {
00412     OA_ptr<Node> b; 
00413     b = new Node();
00414     mCFG->addNode(b);
00415 
00416     if(debug)
00417     {
00418                  cout << "\n CFG Node";
00419                  b->dump(cout , mIR);
00420                  cout << "\n";
00421     }
00422 
00423  
00424 
00425     
00426     OA_ptr<std::list<CFG::NodeLabel> > break_statements, continue_statements;
00427     break_statements = new std::list<CFG::NodeLabel>;
00428     continue_statements = new std::list<CFG::NodeLabel>;
00429     if (build_block(b, body, x_nodes, break_statements, return_nodes,
00430                     continue_statements) == SIMPLE)
00431     {
00432       x_nodes.push_back(CFG::NodeLabel(b, FALLTHROUGH_EDGE));
00433     }
00434 
00435     mCFG->connect(c, b, TRUE_EDGE);
00436     CFG::NodeLabelListIterator break_iter(*break_statements);
00437     while (break_iter.isValid()) {
00438       exit_nodes.push_back(break_iter.current());
00439       ++break_iter;
00440     }
00441 
00442     CFG::NodeLabelListIterator continue_iter(*continue_statements);
00443     while (continue_iter.isValid()) {
00444       x_nodes.push_back(continue_iter.current());
00445       ++continue_iter;
00446     }
00447   }  else {// empty body
00448     x_nodes.push_back(CFG::NodeLabel(c, TRUE_EDGE));
00449   }
00450 
00451   // allocate a new CFG node for the increment part, if needed
00452   StmtHandle incr = mIR->getLoopIncrement(th);
00453   if (incr) {
00454     OA_ptr<Node> li; 
00455     li = new Node(incr);
00456     mCFG->addNode(li);
00457     mCFG->connect(x_nodes, li);
00458     mCFG->connect(li, c, FALLTHROUGH_EDGE);
00459   }
00460   else {
00461     mCFG->connect(x_nodes, c);
00462   }
00463 
00464   return LOOP;
00465 
00466  
00467 }
00468 
00469 
00470 //--------------------------------------------------------------------
00493 IRStmtType
00494 ManagerCFGStandard::build_CFG_twoway_branch (OA_ptr<Node> prev_node,
00495         StmtHandle th, std::list<CFG::NodeLabel>& exit_nodes,
00496         OA_ptr<std::list<CFG::NodeLabel> > break_nodes,
00497         OA_ptr<std::list<CFG::NodeLabel> > return_nodes,
00498         OA_ptr<std::list<CFG::NodeLabel> > continue_nodes)
00499 {
00500 
00501   if(debug)
00502   {
00503       std::cout << "Inside CFG::build_CFG_twoway_branch" << endl;
00504   }
00505  // add the if statement itself to the previous block. it represents
00506   // the conditional branch terminating the block.
00507   prev_node->add(th);
00508 
00509   // construct the CFG for the true block
00510   OA_ptr<Node> b;
00511   OA_ptr<IRRegionStmtIterator> true_body = mIR->trueBody(th);
00512   if (true_body->isValid() && true_body->current()) {
00513     b = new Node();
00514 
00515     if(debug)
00516     {
00517         std::cout << "True branch" << std::endl;
00518     }
00519 
00520     if(debug)
00521    {
00522        std::cout << "In CFG addNode" << std::endl;
00523        b->dump(cout , mIR);
00524    }
00525 
00526    mCFG->addNode(b);
00527 
00528    if(debug)
00529    {
00530        std::cout << "CFG addNode ends" << std::endl;
00531    }
00532 
00533     
00534     if (build_block(b, true_body, exit_nodes, break_nodes, return_nodes, continue_nodes) == SIMPLE)
00535       exit_nodes.push_back(CFG::NodeLabel(b, FALLTHROUGH_EDGE));
00536 
00537     mCFG->connect(prev_node, b, TRUE_EDGE);
00538   }
00539   else {
00540     // the body is empty
00541     b = 0;
00542     exit_nodes.push_back(CFG::NodeLabel(prev_node, TRUE_EDGE));
00543   }
00544 
00545  // handle the false block
00546   OA_ptr<IRRegionStmtIterator> false_body = mIR->elseBody(th);
00547   if (false_body->isValid() && false_body->current()) {
00548     OA_ptr<Node> c_body; c_body = new Node();
00549     if(debug)
00550     {
00551         std::cout << "false branch" << std::endl;
00552     }
00553 
00554     if(debug)
00555     {
00556        std::cout << "In CFG addNode" << std::endl;
00557        c_body->dump(cout , mIR);
00558     }
00559 
00560     mCFG->addNode(c_body);
00561 
00562     if(debug)
00563     {
00564       std::cout << "CFG addNode ends" << std::endl;
00565     }
00566 
00567     
00568     if (build_block(c_body, false_body, exit_nodes, break_nodes, return_nodes, continue_nodes) == SIMPLE)
00569       exit_nodes.push_back(CFG::NodeLabel(c_body, FALLTHROUGH_EDGE));
00570 
00571     mCFG->connect(prev_node, c_body, FALSE_EDGE);
00572   }
00573   else if (!b.ptrEqual(0)) // if b is 0 then the "condition" node has already been added to exit_nodes
00574     exit_nodes.push_back(CFG::NodeLabel(prev_node, FALSE_EDGE));
00575 
00576   return STRUCT_TWOWAY_CONDITIONAL;
00577 
00578   if(debug)
00579   {
00580       std::cout << "*****  CFG::build_CFG_twoway_branch *****" << endl;
00581   }
00582   
00583 }
00584 
00585 
00586 //--------------------------------------------------------------------
00608 IRStmtType
00609 ManagerCFGStandard::build_CFG_multiway_branch (OA_ptr<Node> prev_node,
00610         StmtHandle th, std::list<CFG::NodeLabel>& exit_nodes,
00611         OA_ptr<std::list<CFG::NodeLabel> > break_nodes,
00612         OA_ptr<std::list<CFG::NodeLabel> > return_nodes,
00613         OA_ptr<std::list<CFG::NodeLabel> > continue_nodes)
00614 {
00615    // add the switch statement to the previous block. the switch statement
00616   // represents the multi-way conditional branch terminating the block.
00617   prev_node->add(th);
00618 
00619   bool direct_drop = false;    // should there be a direct edge from the condition to exit?
00620   bool default_cond = false;   // is there a default case?
00621 
00622   // iterate over the multi-branches
00623   for (int bridx = 0; bridx < mIR->numMultiCases(th); bridx++) {
00624     OA_ptr<IRRegionStmtIterator> body = mIR->multiBody(th, bridx);
00625 
00626     // if there is an empty body then just make a direct drop, this is correct since
00627     // break is always implied
00628     if (body->isValid() && body->current()) {
00629       OA_ptr<Node> c; c = new Node();
00630       mCFG->addNode(c);
00631 
00632  if(debug)
00633                 {
00634                  cout << "\n build_CFG_multiway_branch CFG Node";
00635                  c->dump(cout , mIR);
00636                  cout << "\n";
00637                 }
00638 
00639 
00640       if (build_block(c, body, exit_nodes, break_nodes, return_nodes, continue_nodes) == SIMPLE)
00641       {
00642         exit_nodes.push_back(CFG::NodeLabel(c, FALLTHROUGH_EDGE));
00643       }
00644 
00645        // check if this is the catch all case
00646        if (mIR->isCatchAll(th,bridx)) {
00647            default_cond = true;
00648            mCFG->connect(prev_node, c, MULTIWAY_EDGE);
00649        } else {
00650            ExprHandle multiCond = mIR->getSMultiCondition(th, bridx);
00651            mCFG->connect(prev_node, c, MULTIWAY_EDGE, multiCond);
00652        }
00653        
00654        // there is an empty body with an implied break
00655      } else {
00656            direct_drop = true;
00657      }
00658   
00659    } /* for */
00660 
00661    // if we didn't find a catchall then there should be a direct drop
00662    if (default_cond == false) {
00663        direct_drop = true;
00664    }
00665    
00666    // direct drop is true iff there is not catchall or at least one multi-branch body is null
00667    if (direct_drop) {
00668        exit_nodes.push_back(CFG::NodeLabel(prev_node, FALLTHROUGH_EDGE));
00669    }
00670    
00671    return STRUCT_MULTIWAY_CONDITIONAL;
00672 
00673 }
00674 
00675 
00676 //--------------------------------------------------------------------
00677 
00678 
00679 //--------------------------------------------------------------------
00697 IRStmtType
00698 ManagerCFGStandard::build_CFG_multiway_branch_with_fallthrough (
00699        OA_ptr<Node> prev_node,
00700        StmtHandle th, std::list<CFG::NodeLabel>& exit_nodes,
00701        OA_ptr<std::list<CFG::NodeLabel> > return_nodes,
00702        OA_ptr<std::list<CFG::NodeLabel> > continue_nodes)
00703 {
00704      // add the switch statement to the previous block. the switch statement
00705      // represents the multi-way conditional branch terminating the block.
00706      prev_node->add(th);
00707      
00708      //bool direct_drop = true;   // should there be a direct edge from the condition to exit?
00709      bool empty_cond = false;     // is there an empty case?
00710      bool default_cond = false;   // is there a default case
00711     
00712     // We must create a new list of break statements since any breaks seen
00713     // in subtrees of this statement will exit this switch, not some other
00714     // enclosing construct.
00715     OA_ptr<std::list<CFG::NodeLabel> > break_switch_statements;
00716     break_switch_statements = new std::list<CFG::NodeLabel>;
00717 
00718    // Track the last case body processed so that fall-through
00719    // connections can be made This will be non-null whenever the
00720    // previous case falls through (i.e., did not end in a break
00721    // statement).  the case_exit_nodes list will contain all the exits
00722    // from the previous case block
00723    OA_ptr<Node> prev_case_node;
00724    prev_case_node = 0;
00725    std::list<CFG::NodeLabel> case_exit_nodes;
00726 
00727    // iterate over the multi-branches
00728    for (int bridx = 0; bridx < mIR->numMultiCases(th); bridx++) {
00729 
00730     OA_ptr<IRRegionStmtIterator> body = mIR->multiBody(th, bridx);
00731     //if (body->isValid() && body->current()) {
00732     OA_ptr<Node> c; c = new Node();
00733     mCFG->addNode(c);
00734 
00735  if(debug)
00736                 {
00737                  cout << "\n Add CFG multiway branch with_Fallthrough CFG Node";
00738                  c->dump(cout , mIR);
00739                  cout << "\n";
00740                 }
00741 
00742 
00743     
00744     break_switch_statements->clear();
00745     // If a previous case falls-through, connect all of its exit nodes
00746     // to the current case node.
00747     if (!prev_case_node.ptrEqual(NULL)) {
00748       mCFG->connect(case_exit_nodes, c);
00749       case_exit_nodes.clear();
00750       prev_case_node = 0;
00751     }
00752 
00753    // if there are statements in the case body then look for break
00754     if (body->isValid() && body->current()) {
00755       // A placeholder for exit nodes.  We don't want the case body to
00756       // be an exit from the switch construct unless there is a break.
00757       // Either the body will have a break statement that collects
00758       // exits or the exits will all be connected the next case node
00759       IRStmtType prev_case_statement = build_block(c, body, case_exit_nodes,
00760                                                    break_switch_statements,
00761                                                    return_nodes, continue_nodes);
00762 
00763       // if there wasn't a break statement then update case_exit_nodes
00764       if ( break_switch_statements->size() == 0 ) {
00765         prev_case_node = c;
00766         if (prev_case_statement == SIMPLE) {
00767           case_exit_nodes.push_back(CFG::NodeLabel(prev_case_node, FALLTHROUGH_EDGE));
00768         }
00769 
00770       // if we did see a break then this case node will not fall through to next case node
00771       } else {
00772         prev_case_node = 0;
00773 
00774         // There should only be one break, but iterate anyway.
00775         CFG::NodeLabelListIterator
00776             break_stmt_iter(*break_switch_statements);
00777         while (break_stmt_iter.isValid()) {
00778           exit_nodes.push_back(break_stmt_iter.current());
00779           ++break_stmt_iter;
00780         }
00781         //IMPROVEME: if the body only has a break than we can simplify
00782         //the CFG by adding a direct_drop edge and removing this CFG
00783         //node, if figure out how to do this just need to set
00784         //empty_cond to true
00785 
00786       }
00787 
00788     // if have an empty block, still have a CFG node because break is not implied
00789     } else {
00790       prev_case_node = c;
00791       case_exit_nodes.push_back(CFG::NodeLabel(prev_case_node, FALLTHROUGH_EDGE));
00792     }
00793 
00794     // check if this is the catch all case
00795     if (mIR->isCatchAll(th,bridx)) {
00796       default_cond = true;
00797       mCFG->connect(prev_node, c, MULTIWAY_EDGE);
00798     } else {
00799       ExprHandle multiCond = mIR->getSMultiCondition(th, bridx);
00800       mCFG->connect(prev_node, c, MULTIWAY_EDGE, multiCond);
00801     }
00802 
00803   } /* for */
00804 
00805   // if last condition didn't have a break then it won't be on
00806   // the exit_nodes stack and should be added
00807   if (!prev_case_node.ptrEqual(NULL)) {
00808     exit_nodes.push_back(CFG::NodeLabel(prev_case_node, FALLTHROUGH_EDGE));
00809   }
00810 
00811   // direct drop is true iff there is not catchall or at least one multi-branch body is null
00812   if ( !default_cond || empty_cond ) {
00813     exit_nodes.push_back(CFG::NodeLabel(prev_node, FALLTHROUGH_EDGE));
00814   }
00815 
00816   return STRUCT_MULTIWAY_CONDITIONAL;
00817            
00818 }
00819 
00820 
00821 //--------------------------------------------------------------------
00846 IRStmtType
00847 ManagerCFGStandard::build_CFG_end_tested_loop (OA_ptr<Node> prev_node,
00848                 StmtHandle th, std::list<CFG::NodeLabel>& exit_nodes,
00849                         OA_ptr<std::list<CFG::NodeLabel> > return_nodes)
00850 {
00851   // FIXME: New construct, partially tested.
00852   // New CFG nodes must be allocated for both the body and loop condition (we can re-use
00853   // prev_node for the body if it is empty).
00854   OA_ptr<Node> b; b = NULL;
00855   OA_ptr<Node> c; c = NULL;
00856 
00857  // Process the loop body.
00858   std::list<CFG::NodeLabel> x_nodes;
00859   OA_ptr<IRRegionStmtIterator> body = mIR->loopBody(th);
00860   if (body->isValid() && body->current()) {
00861     if (prev_node->empty()) {
00862       b = prev_node;
00863     } else {
00864       b = new Node();
00865       mCFG->addNode(b);
00866       mCFG->connect(prev_node, b, FALLTHROUGH_EDGE);
00867     }
00868     OA_ptr<std::list<CFG::NodeLabel> > break_statements, continue_statements;
00869     break_statements = new std::list<CFG::NodeLabel>;
00870     continue_statements = new std::list<CFG::NodeLabel>;
00871     if (build_block(b, body, x_nodes, break_statements, return_nodes, continue_statements) == SIMPLE) {
00872       x_nodes.push_back(CFG::NodeLabel(b, FALLTHROUGH_EDGE));
00873     }
00874 
00875     CFG::NodeLabelListIterator break_iter(*break_statements);
00876     while (break_iter.isValid()) {
00877       exit_nodes.push_back(break_iter.current());
00878       ++break_iter;
00879     }
00880 
00881     CFG::NodeLabelListIterator continue_iter(*continue_statements);
00882     while (continue_iter.isValid()) {
00883       x_nodes.push_back(continue_iter.current());
00884       ++continue_iter;
00885     }
00886   }
00887   else { // empty body
00888     // FIXME: c is NULL at this point...
00889     x_nodes.push_back(CFG::NodeLabel(c, TRUE_EDGE));
00890   }
00891 
00892   // Allocate a node for the condition and make the proper connections.
00893   c = new Node(th);
00894   mCFG->addNode(c);
00895   exit_nodes.push_back(CFG::NodeLabel(c, FALSE_EDGE));
00896   mCFG->connect(c, b, TRUE_EDGE);
00897   mCFG->connect(x_nodes, c);
00898 
00899   return END_TESTED_LOOP;
00900 
00901 }
00902 
00903 IRStmtType
00904 ManagerCFGStandard::build_CFG_unconditional_jump (
00905         OA_ptr<Node> prev_node,
00906         StmtHandle stmt)
00907 {
00908   // FIXME: New construct, partially tested.
00909   StmtLabel lab = mIR->getTargetLabel(stmt, 0);
00910   prev_node->add(stmt);
00911   mCFG->connect(prev_node, mCFG->node_from_label(lab), FALLTHROUGH_EDGE);
00912   return UNCONDITIONAL_JUMP;
00913 }
00914 
00915 
00916 //--------------------------------------------------------------------
00936 IRStmtType
00937 ManagerCFGStandard::build_CFG_ustruct_twoway_branch (OA_ptr<Node>
00938         prev_node, StmtHandle stmt,  std::list<CFG::NodeLabel>& exit_nodes)
00939 {
00940   // FIXME: New construct, partially untested.
00941   StmtLabel lab = mIR->getTargetLabel(stmt, 0);
00942   bool branch_on_true = (mIR->getCFGStmtType(stmt) == USTRUCT_TWOWAY_CONDITIONAL_T);
00943   prev_node->add(stmt);
00944   mCFG->connect(prev_node, mCFG->node_from_label(lab), (branch_on_true ? TRUE_EDGE : FALSE_EDGE));
00945 
00946   // This is so that the branch block will get connected to the fall-through block.
00947   exit_nodes.push_back(CFG::NodeLabel(prev_node, FALLTHROUGH_EDGE));  
00948 
00949   return mIR->getCFGStmtType(stmt);
00950 }
00951 //--------------------------------------------------------------------
00952 
00953 
00954 //--------------------------------------------------------------------
00977 IRStmtType
00978 ManagerCFGStandard::build_CFG_unconditional_jump_i (
00979         OA_ptr<Node> prev_node,
00980         StmtHandle stmt)
00981 {
00982   // Every label must be seen before all the edges can be added.
00983   // Just add this to the list of indirect jumps, which will have their
00984   // edges added later.
00985   cout << "FIXME: UNCONDITIONAL_JUMP_I not yet implemented" << endl;
00986   assert(0);
00987   return UNCONDITIONAL_JUMP_I;
00988 }
00989 //--------------------------------------------------------------------
00990 
00991 
00992 //--------------------------------------------------------------------
01020 IRStmtType
01021 ManagerCFGStandard::build_CFG_ustruct_multiway_branch (OA_ptr<Node>
01022         prev_node, StmtHandle stmt)
01023 {
01024   // FIXME: New construct, partially tested.
01025   // Add the multi-way statement to the previous block. It represents
01026   // the multi-way branch terminating the block (which holds the selector
01027   // expression).
01028   prev_node->add(stmt);
01029 
01030   // Connect the branch to each of its targets.
01031   for (int br = 0; br < mIR->numUMultiTargets(stmt); br++) {
01032     StmtLabel target_lab = mIR->getUMultiTargetLabel(stmt, br);
01033     ExprHandle cond_expr = mIR->getUMultiCondition(stmt, br);
01034     mCFG->connect(prev_node, mCFG->node_from_label(target_lab),
01035                   MULTIWAY_EDGE, cond_expr );
01036   }
01037 
01038   // If there is a default target, make the proper connections.
01039   StmtLabel default_lab = mIR->getUMultiCatchallLabel(stmt);
01040   if (default_lab) {
01041     mCFG->connect(prev_node, mCFG->node_from_label(default_lab),
01042                   MULTIWAY_EDGE /* , multiCond */);
01043   }
01044 
01045   return USTRUCT_MULTIWAY_CONDITIONAL;
01046 }
01047 
01048 
01049 //*****************************************************************************
01050 
01051 
01052 //*****************************************************************************
01053 //*****************************************************************************
01054 
01055 //*****************************************************************************
01056 // Refine the CFG to split blocks as necessary to handle delay slots, along
01057 // with branches and labels in delay slots
01058 //*****************************************************************************
01059 void
01060 ManagerCFGStandard::HandleDelayedBranches ()
01061 {
01062   //
01063   // Preconditions:
01064   //
01065   // On input to this routine, all nodes and edges resulting from
01066   // structured control flow are already present.  In addition, all
01067   // nodes and edges induced by labels are present. To be finalized
01068   // here are the unstructured control flow contructs.
01069   //
01070 
01071   //
01072   // Create the "basic" CFG.  This adds control flow for the first
01073   // branch in a block (after its 'k' delay slots).
01074   //
01075   createBasicCFG();
01076 
01077 #if 0 // FIXME: Disabled until its fixed.
01078   //
01079   // Finally, perform Waterman's worklist algorithm to finalize
01080   // control flow for the cases where branches are contained in
01081   // the delay slots of other branches.
01082   //
01083 
01084   // Place the start block of the procedure on the worklist
01085   Counterlist* emptyCounterList = new Counterlist;
01086   the_worklist->copyCountersToWorklist(Entry(), emptyCounterList);
01087 
01088   while (! the_worklist->isEmpty()) {
01089     for (i:NodesIterator nodes_iter(*this);
01090          (bool)nodes_iter && !the_worklist->isEmpty(); ++nodes_iter) {
01091       CFG::Node *node = dynamic_cast<CFG::Node*>((DGraph::Node*)nodes_iter);
01092       processBlock(node);
01093     }
01094   }
01095 #endif
01096 }
01097 
01098 
01099 void
01100 ManagerCFGStandard::createBasicCFG()
01101 {
01102   // Create and populate the block_list.
01103   // PLM I have to modify this
01104   std::set<OA_ptr<Node> > block_list;
01105  
01106   OA_ptr<DGraph::NodesIteratorInterface> nodes_iter = mCFG->getNodesIterator();
01107   for( ; nodes_iter->isValid(); ++(*nodes_iter))
01108   {
01109     OA_ptr<DGraph::NodeInterface> dnode = nodes_iter->current();  
01110     OA_ptr<Node> node = dnode.convert<Node>();   
01111 
01116     block_list.insert(node);
01117   }
01118   
01119 /*  for (NodesIterator nodes_iter(*mCFG); nodes_iter.isValid();
01120        ++nodes_iter)
01121   {
01122     OA_ptr<Node> node = nodes_iter.current();
01123     block_list.insert(node);
01124   }
01125 */
01126 
01127  // Process the blocks.
01128   while (block_list.size() > 0) {
01129     bool branch_found = false;
01130     int countdown = 0;
01131     StmtHandle stmt = 0;
01132     OA_ptr<Node> node = *block_list.begin();
01133     int numRemoved = block_list.erase(node);
01134     assert(numRemoved > 0);
01135 
01136     // Find first unstructured branch statement in this block.
01137    NodeStatementsIterator si(*node);
01138     for ( ; si.isValid(); ++si) {
01139       stmt = si.current();
01140       IRStmtType ty = mIR->getCFGStmtType(stmt);
01141       assert(ty != UNCONDITIONAL_JUMP_I);  // FIXME: Add support.
01142       if (ty == USTRUCT_TWOWAY_CONDITIONAL_T
01143           || ty == USTRUCT_TWOWAY_CONDITIONAL_F
01144           || ty == UNCONDITIONAL_JUMP) {
01145         branch_found = true;
01146         countdown = mIR->numberOfDelaySlots(stmt);
01147         break;
01148       } // if ty == branch
01149     } // For statements.
01150 
01151 
01152 
01153   // Only do this if countdown > 0, non-delayed branches are already
01154     // done in the main build routine.
01155     if (branch_found == true && countdown > 0) {
01156       // Move to end of this branch's delay slots.
01157       for ( ; si.isValid() && countdown > 0; ++si) {
01158         // FIXME: Need to check ParallelWithSuccessor, etc.
01159         --countdown;
01160       }
01161 
01162 
01163  if (countdown == 0) {
01164         //
01165         // Split the block just past its final delay slot.
01166         // Add the new block (the second piece of the original block) to
01167         // the block_list.
01168         // Add edges from the current block to the target(s) of the branch.
01169         //
01170         // FIXME: But before trying to do the split, check if the split point is
01171         // already at the end of the block.  This could happen if there
01172         // is a label just after the branch's final delay slot.
01173         //
01174         ++si;
01175         if (1 /* (bool)si == true */) {
01176           StmtHandle val = (si.isValid()) ? si.current() : (StmtHandle)0;
01177           OA_ptr<Node> newnode = mCFG->splitBlock (node, val);
01178           mFallThrough[node] = newnode;
01179           block_list.insert(newnode);
01180           IRStmtType ty = mIR->getCFGStmtType(stmt);
01181           if (ty == USTRUCT_TWOWAY_CONDITIONAL_T
01182               || ty == USTRUCT_TWOWAY_CONDITIONAL_F) {
01183             mCFG->connect(node, mCFG->getLabelBlock(mIR->getTargetLabel(stmt, 0)),
01184                     ty == USTRUCT_TWOWAY_CONDITIONAL_T ? TRUE_EDGE : FALSE_EDGE);
01185             mCFG->connect(node, newnode, FALLTHROUGH_EDGE);
01186           } else if (ty == UNCONDITIONAL_JUMP) {
01187             StmtLabel label = mIR->getTargetLabel(stmt, 0);
01188             OA_ptr<Node> nodeTmp = mCFG->getLabelBlock(label);
01189             mCFG->connect(node, nodeTmp, FALLTHROUGH_EDGE);
01190           } else {
01191             assert(0);
01192           }
01193         } // if (si)
01194       } // if (countdown == 0)
01195 
01196 
01197     } // if branch_found.
01198 
01199  if (branch_found == false || countdown > 0) {
01200       // ??? Add fall-thru edge from b (fixme, should already be there?).
01201       // Note, countdown > 0 can only happen if there was a label
01202       // in a delay slot.
01203     }
01204 
01205     
01206    } // While block_list.
01207 }
01208   
01209   
01210   } // end of namespace CFG
01211 } //end of namespace OA