basicblock.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1997-2001, The University of Queensland
00003  * Copyright (C) 2000-2001, Sun Microsystems, Inc
00004  * Copyright (C) 2002, Trent Waddington
00005  *
00006  * See the file "LICENSE.TERMS" for information on usage and
00007  * redistribution of this file, and for a DISCLAIMER OF ALL
00008  * WARRANTIES.
00009  *
00010  */
00011 
00012 /*==============================================================================
00013  * FILE:     basicblock.cc
00014  * OVERVIEW: Implementation of the BasicBlock class.
00015  *============================================================================*/
00016 
00017 /*
00018  * $Revision: 1.138 $   // 1.93.2.8
00019  * Dec 97 - created by Mike
00020  * 18 Apr 02 - Mike: Changes for boomerang
00021  * 04 Dec 02 - Mike: Added isJmpZ
00022  * 09 Jan 02 - Mike: Untabbed, reformatted
00023  * 17 Jun 03 - Mike: Fixed an apparent error in generateCode (getCond)
00024  * 14 Jun 05 - Mike: Don't add redundant out edges to an N-way BB if some jump table entries repeat
00025 */
00026 
00027 
00028 /*==============================================================================
00029  * Dependencies.
00030  *============================================================================*/
00031 
00032 #include <assert.h>
00033 #if defined(_MSC_VER) && _MSC_VER <= 1200
00034 #pragma warning(disable:4786)
00035 #endif 
00036 
00037 #include "gc.h"
00038 #include "types.h"
00039 #include "statement.h"
00040 #include "exp.h"
00041 #include "cfg.h"
00042 #include "register.h"
00043 #include "rtl.h"
00044 #include "hllcode.h"
00045 #include "proc.h"
00046 #include "prog.h"
00047 #include "util.h"
00048 #include "boomerang.h"
00049 #include "type.h"
00050 #include "log.h"
00051 #include "visitor.h"
00052 
00053 
00054 /**********************************
00055  * BasicBlock methods
00056  **********************************/
00057 
00058 /*==============================================================================
00059  * FUNCTION:        BasicBlock::BasicBlock
00060  * OVERVIEW:        Constructor.
00061  * PARAMETERS:      <none>
00062  * RETURNS:         <nothing>
00063  *============================================================================*/
00064 BasicBlock::BasicBlock()
00065     :
00066         m_DFTfirst(0), m_DFTlast(0),
00067         m_structType(NONE), m_loopCondType(NONE),
00068         m_loopHead(NULL), m_caseHead(NULL),
00069         m_condFollow(NULL), m_loopFollow(NULL),
00070         m_latchNode(NULL),
00071         m_nodeType(INVALID),
00072         m_pRtls(NULL),
00073         m_iLabelNum(0),
00074         m_labelneeded(false),
00075         m_bIncomplete(true),
00076         m_bJumpReqd(false),
00077         m_iNumInEdges(0),
00078         m_iNumOutEdges(0),
00079         m_iTraversed(false),
00080 // From Doug's code
00081 ord(-1), revOrd(-1), inEdgesVisited(0), numForwardInEdges(-1), traversed(UNTRAVERSED), hllLabel(false), indentLevel(0),
00082 immPDom(NULL), loopHead(NULL), caseHead(NULL), condFollow(NULL), loopFollow(NULL), latchNode(NULL), sType(Seq), 
00083 usType(Structured),
00084 // Others
00085         overlappedRegProcessingDone(false)
00086 {
00087 }
00088 
00089 /*==============================================================================
00090  * FUNCTION:        BasicBlock::~BasicBlock
00091  * OVERVIEW:        Destructor.
00092  * PARAMETERS:      <none>
00093  * RETURNS:         <nothing>
00094  *============================================================================*/
00095 BasicBlock::~BasicBlock() {
00096     if (m_pRtls)
00097     {
00098         // Delete the RTLs
00099         for (std::list<RTL*>::iterator it = m_pRtls->begin(); it != m_pRtls->end(); it++)
00100         {
00101             if (*it)
00102             {
00103                 delete *it;
00104             }
00105         }
00106 
00107         // and delete the list
00108         delete m_pRtls;
00109         m_pRtls = NULL;
00110     }
00111 }
00112 
00113 
00114 /*==============================================================================
00115  * FUNCTION:        BasicBlock::BasicBlock
00116  * OVERVIEW:        Copy constructor.    
00117  * PARAMETERS:      bb - the BB to copy from
00118  * RETURNS:         <nothing>
00119  *============================================================================*/
00120 BasicBlock::BasicBlock(const BasicBlock& bb)
00121     :   m_DFTfirst(0), m_DFTlast(0),
00122         m_structType(bb.m_structType), m_loopCondType(bb.m_loopCondType),
00123         m_loopHead(bb.m_loopHead), m_caseHead(bb.m_caseHead),
00124         m_condFollow(bb.m_condFollow), m_loopFollow(bb.m_loopFollow),
00125         m_latchNode(bb.m_latchNode),
00126         m_nodeType(bb.m_nodeType),
00127         m_pRtls(NULL),
00128         m_iLabelNum(bb.m_iLabelNum),
00129         m_labelneeded(false),
00130         m_bIncomplete(bb.m_bIncomplete),
00131         m_bJumpReqd(bb.m_bJumpReqd),
00132         m_InEdges(bb.m_InEdges),
00133         m_OutEdges(bb.m_OutEdges),
00134         m_iNumInEdges(bb.m_iNumInEdges),
00135         m_iNumOutEdges(bb.m_iNumOutEdges),
00136         m_iTraversed(false),
00137 // From Doug's code
00138 ord(bb.ord), revOrd(bb.revOrd), inEdgesVisited(bb.inEdgesVisited), numForwardInEdges(bb.numForwardInEdges),
00139 traversed(bb.traversed), hllLabel(bb.hllLabel), indentLevel(bb.indentLevel), immPDom(bb.immPDom), loopHead(bb.loopHead),
00140 caseHead(bb.caseHead), condFollow(bb.condFollow), loopFollow(bb.loopFollow), latchNode(bb.latchNode), sType(bb.sType),
00141 usType(bb.usType) 
00142 {
00143     setRTLs(bb.m_pRtls);
00144 }
00145 
00146 /*==============================================================================
00147  * FUNCTION:        BasicBlock::BasicBlock
00148  * OVERVIEW:        Private constructor.
00149  * PARAMETERS:      pRtls -
00150  *                  bbType -
00151  *                  iNumOutEdges -
00152  * RETURNS:         <nothing>
00153  *============================================================================*/
00154 BasicBlock::BasicBlock(std::list<RTL*>* pRtls, BBTYPE bbType, int iNumOutEdges)
00155     :   m_DFTfirst(0), m_DFTlast(0),
00156         m_structType(NONE), m_loopCondType(NONE),
00157         m_loopHead(NULL), m_caseHead(NULL),
00158         m_condFollow(NULL), m_loopFollow(NULL),
00159         m_latchNode(NULL),  
00160         m_nodeType(bbType),
00161         m_pRtls(NULL),
00162         m_iLabelNum(0),
00163         m_labelneeded(false),
00164         m_bIncomplete(false),
00165         m_bJumpReqd(false),
00166         m_iNumInEdges(0),
00167         m_iNumOutEdges(iNumOutEdges),
00168         m_iTraversed(false),
00169 // From Doug's code
00170 ord(-1), revOrd(-1), inEdgesVisited(0), numForwardInEdges(-1), traversed(UNTRAVERSED), hllLabel(false), indentLevel(0),
00171 immPDom(NULL), loopHead(NULL), caseHead(NULL), condFollow(NULL), loopFollow(NULL), latchNode(NULL), sType(Seq),
00172 usType(Structured) 
00173 {
00174     m_OutEdges.reserve(iNumOutEdges);               // Reserve the space; values added with AddOutEdge()
00175 
00176     // Set the RTLs
00177     setRTLs(pRtls);
00178 
00179 }
00180 
00181 /*==============================================================================
00182  * FUNCTION:        BasicBlock::getLabel
00183  * OVERVIEW:        Returns nonzero if this BB has a label, in the sense that a label is required in the translated
00184  *                      source code
00185  * PARAMETERS:      <none>
00186  * RETURNS:         An integer unique to this BB, or zero
00187  *============================================================================*/
00188 int BasicBlock::getLabel() {
00189     return m_iLabelNum;
00190 }
00191 
00192 bool BasicBlock::isCaseOption() {
00193     if (caseHead)
00194         for (unsigned int i = 0; i < caseHead->getOutEdges().size() - 1; i++)
00195             if (caseHead->getOutEdge(i) == this) 
00196                 return true;
00197     return false;
00198 }
00199 
00200 /*==============================================================================
00201  * FUNCTION:        BasicBlock::isTraversed
00202  * OVERVIEW:        Returns nonzero if this BB has been traversed
00203  * PARAMETERS:      <none>
00204  * RETURNS:         True if traversed
00205  *============================================================================*/
00206 bool BasicBlock::isTraversed() {
00207     return m_iTraversed;
00208 }
00209 
00210 /*==============================================================================
00211  * FUNCTION:        BasicBlock::setTraversed
00212  * OVERVIEW:        Sets the traversed flag
00213  * PARAMETERS:      bTraversed: true to set this BB to traversed
00214  * RETURNS:         <nothing>
00215  *============================================================================*/
00216 void BasicBlock::setTraversed(bool bTraversed) {
00217     m_iTraversed = bTraversed;
00218 }
00219 
00220 /*==============================================================================
00221  * FUNCTION:        BasicBlock::setRTLs
00222  * OVERVIEW:        Sets the RTLs for a basic block. This is the only place that the RTLs for a block must be set as we
00223  *                      need to add the back link for a call instruction to its enclosing BB.
00224  * PARAMETERS:      rtls - a list of RTLs
00225  * RETURNS:         <nothing>
00226  *============================================================================*/
00227 void BasicBlock::setRTLs(std::list<RTL*>* rtls) {
00228     // should we delete old ones here?  breaks some things - trent
00229     m_pRtls = rtls;
00230 
00231     // Used to set the link between the last instruction (a call) and this BB if this is a call BB
00232 }
00233 
00234 /*==============================================================================
00235  * FUNCTION:        BasicBlock::getType
00236  * OVERVIEW:        Return the type of the basic block.
00237  * PARAMETERS:      <none>
00238  * RETURNS:         the type of the basic block
00239  *============================================================================*/
00240 BBTYPE BasicBlock::getType() {
00241     return m_nodeType;
00242 }
00243 
00244 /*==============================================================================
00245  * FUNCTION:        BasicBlock::updateType
00246  * OVERVIEW:        Update the type and number of out edges. Used for example where a COMPJUMP type is updated to an
00247  *                      NWAY when a switch idiom is discovered.
00248  * PARAMETERS:      bbType - the new type
00249  *                  iNumOutEdges - new number of inedges
00250  * RETURNS:         <nothing>
00251  *============================================================================*/
00252 void BasicBlock::updateType(BBTYPE bbType, int iNumOutEdges) {
00253     m_nodeType = bbType;
00254     m_iNumOutEdges = iNumOutEdges;
00255     //m_OutEdges.resize(iNumOutEdges);
00256 }
00257 
00258 /*==============================================================================
00259  * FUNCTION:        BasicBlock::setJumpReqd
00260  * OVERVIEW:        Sets the "jump required" bit. This means that this BB is an orphan (not generated from input code),
00261  *                      and that the "fall through" out edge needs to be implemented as a jump
00262  * PARAMETERS:      <none>
00263  * RETURNS:         <nothing>
00264  *============================================================================*/
00265 void BasicBlock::setJumpReqd() {
00266     m_bJumpReqd = true;
00267 }
00268 
00269 /*==============================================================================
00270  * FUNCTION:        BasicBlock::isJumpReqd
00271  * OVERVIEW:        Returns the "jump required" bit. See above for details
00272  * PARAMETERS:      <none>
00273  * RETURNS:         True if a jump is required
00274  *============================================================================*/
00275 bool BasicBlock::isJumpReqd() {
00276     return m_bJumpReqd;
00277 }
00278 
00279 /*==============================================================================
00280  * FUNCTION:        BasicBlock::prints
00281  * OVERVIEW:        Print to a static string (for debugging) 
00282  * PARAMETERS:      <none>
00283  * RETURNS:         Address of the static buffer
00284  *============================================================================*/
00285 char debug_buffer[DEBUG_BUFSIZE];
00286 
00287 char* BasicBlock::prints() { 
00288     std::ostringstream ost; 
00289     print(ost); 
00290     // Static buffer might have overflowed if we used it directly, hence we just copy and print the first
00291     // DEBUG_BUFSIZE-1 bytes
00292     strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
00293     debug_buffer[DEBUG_BUFSIZE-1] = '\0';
00294     return debug_buffer; 
00295 }
00296 
00297 void BasicBlock::dump() {
00298     print(std::cerr);
00299 }
00300 
00301 /*==============================================================================
00302  * FUNCTION:        BasicBlock::print()
00303  * OVERVIEW:        Display the whole BB to the given stream
00304  *                  Used for "-R" option, and handy for debugging
00305  * PARAMETERS:      os - stream to output to
00306  * RETURNS:         <nothing>
00307  *============================================================================*/
00308 void BasicBlock::print(std::ostream& os, bool html) {
00309     if (html)
00310         os << "<br>";
00311     if (m_iLabelNum) os << "L" << std::dec << m_iLabelNum << ": ";
00312     switch(m_nodeType) {
00313         case ONEWAY:    os << "Oneway BB"; break;
00314         case TWOWAY:    os << "Twoway BB"; break;
00315         case NWAY:      os << "Nway BB"; break;
00316         case CALL:      os << "Call BB"; break;
00317         case RET:       os << "Ret BB"; break;
00318         case FALL:      os << "Fall BB"; break;
00319         case COMPJUMP:  os << "Computed jump BB"; break;
00320         case COMPCALL:  os << "Computed call BB"; break;
00321         case INVALID:   os << "Invalid BB"; break;
00322     }
00323     os << ":\n";
00324     os << "in edges: ";
00325     for (unsigned int i = 0; i < m_InEdges.size(); i++)
00326         os << std::hex << m_InEdges[i]->getHiAddr() << " ";
00327     os << std::dec << "\n";
00328     os << "out edges: ";
00329     for (unsigned int i = 0; i < m_OutEdges.size(); i++)
00330         os << std::hex << m_OutEdges[i]->getLowAddr() << " ";
00331     os << std::dec << "\n";
00332     if (m_pRtls) {                  // Can be zero if e.g. INVALID
00333         if (html)
00334             os << "<table>\n";
00335         std::list<RTL*>::iterator rit;
00336         for (rit = m_pRtls->begin(); rit != m_pRtls->end(); rit++) {
00337             (*rit)->print(os, html);
00338         }
00339         if (html)
00340             os << "</table>\n";
00341     }
00342     if (m_bJumpReqd) {
00343         if (html)
00344             os << "<br>";
00345         os << "Synthetic out edge(s) to ";
00346         for (int i=0; i < m_iNumOutEdges; i++) {
00347             PBB outEdge = m_OutEdges[i];
00348             if (outEdge && outEdge->m_iLabelNum)
00349                 os << "L" << std::dec << outEdge->m_iLabelNum << " ";
00350         }
00351         os << std::endl;
00352     }
00353 }
00354 
00355 void BasicBlock::printToLog() {
00356     std::ostringstream ost;
00357     print(ost);
00358     LOG << ost.str().c_str();
00359 }
00360 
00361 bool BasicBlock::isBackEdge(int inEdge) {
00362     PBB in = m_InEdges[inEdge];
00363     return this == in || (m_DFTfirst < in->m_DFTfirst && m_DFTlast > in->m_DFTlast);
00364 }
00365 
00366 
00367 // Another attempt at printing BBs that gdb doesn't like to print
00368 void printBB(PBB bb) {
00369     bb->print(std::cerr);
00370 }
00371 
00372 /*==============================================================================
00373  * FUNCTION:        BasicBlock::getLowAddr
00374  * OVERVIEW:        Get the lowest real address associated with this BB. Note that although this is usually the address
00375  *                      of the first RTL, it is not always so. For example, if the BB contains just a delayed branch,
00376  *                      and the delay instruction for the branch does not affect the branch, so the delay instruction is
00377  *                      copied in front of the branch instruction. Its address will be UpdateAddress()d to 0, since it
00378  *                      is "not really there", so the low address for this BB will be the address of the branch.
00379  * PARAMETERS:      <none>
00380  * RETURNS:         the lowest real address associated with this BB
00381  *============================================================================*/
00382 ADDRESS BasicBlock::getLowAddr() {
00383     if (m_pRtls == NULL || m_pRtls->size() == 0) return 0;
00384     ADDRESS a = m_pRtls->front()->getAddress();
00385     if ((a == 0) && (m_pRtls->size() > 1)) {
00386         std::list<RTL*>::iterator it = m_pRtls->begin();
00387         ADDRESS add2 = (*++it)->getAddress();
00388         // This is a bit of a hack for 286 programs, whose main actually starts at offset 0. A better solution would be
00389         // to change orphan BBs' addresses to NO_ADDRESS, but I suspect that this will cause many problems. MVE
00390         if (add2 < 0x10)
00391             // Assume that 0 is the real address
00392             return 0;
00393         return add2;
00394     }
00395     return a;
00396 }
00397 
00398 /*==============================================================================
00399  * FUNCTION:        BasicBlock::getHiAddr
00400  * OVERVIEW:        Get the highest address associated with this BB. This is
00401  *                  always the address associated with the last RTL.
00402  * PARAMETERS:      <none>
00403  * RETURNS:         <nothing>
00404  *============================================================================*/
00405 ADDRESS BasicBlock::getHiAddr() {
00406     assert(m_pRtls != NULL);
00407     return m_pRtls->back()->getAddress();
00408 }
00409 
00410 /*==============================================================================
00411  * FUNCTION:        BasicBlock::getRTLs
00412  * OVERVIEW:        Get pointer to the list of RTL*.
00413  * PARAMETERS:      <none>
00414  * RETURNS:         <nothing>
00415  *============================================================================*/
00416 std::list<RTL*>* BasicBlock::getRTLs() {
00417     return m_pRtls;
00418 }
00419 
00420 RTL* BasicBlock::getRTLWithStatement(Statement *stmt)
00421 {
00422     if (m_pRtls == NULL)
00423         return NULL;
00424     for (std::list<RTL*>::iterator it = m_pRtls->begin(); it != m_pRtls->end(); it++) {
00425         RTL *rtl = *it;
00426         for (std::list<Statement*>::iterator it1 = rtl->getList().begin(); it1 != rtl->getList().end(); it1++)
00427             if (*it1 == stmt)
00428                 return rtl;
00429     }
00430     return NULL;
00431 }
00432 
00433 /*==============================================================================
00434  * FUNCTION:        BasicBlock::getInEdges
00435  * OVERVIEW:        Get a constant reference to the vector of in edges.
00436  * PARAMETERS:      <none>
00437  * RETURNS:         a constant reference to the vector of in edges
00438  *============================================================================*/
00439 std::vector<PBB>& BasicBlock::getInEdges() {
00440     return m_InEdges;
00441 }
00442 
00443 /*==============================================================================
00444  * FUNCTION:        BasicBlock::getOutEdges
00445  * OVERVIEW:        Get a constant reference to the vector of out edges.
00446  * PARAMETERS:      <none>
00447  * RETURNS:         a constant reference to the vector of out edges
00448  *============================================================================*/
00449 std::vector<PBB>& BasicBlock::getOutEdges() {
00450     return m_OutEdges;
00451 }
00452 
00453 /*==============================================================================
00454  * FUNCTION:        BasicBlock::setInEdge
00455  * OVERVIEW:        Change the given in-edge (0 is first) to the given value
00456  *                  Needed for example when duplicating BBs
00457  * PARAMETERS:      i: index (0 based) of in-edge to change
00458  *                  pNewInEdge: pointer to BB that will be a new parent
00459  * RETURNS:         <nothing>
00460  *============================================================================*/
00461 void BasicBlock::setInEdge(int i, PBB pNewInEdge) {
00462     m_InEdges[i] = pNewInEdge;
00463 }
00464 
00465 /*==============================================================================
00466  * FUNCTION:        BasicBlock::setOutEdge
00467  * OVERVIEW:        Change the given out-edge (0 is first) to the given value
00468  *                  Needed for example when duplicating BBs
00469  * NOTE:            Cannot add an additional out-edge with this function; use addOutEdge for this rare case
00470  * PARAMETERS:      i: index (0 based) of out-edge to change
00471  *                  pNewOutEdge: pointer to BB that will be the new successor
00472  * RETURNS:         <nothing>
00473  *============================================================================*/
00474 void BasicBlock::setOutEdge(int i, PBB pNewOutEdge) {
00475     if (m_OutEdges.size() == 0) {
00476         assert(i == 0);
00477         m_OutEdges.push_back(pNewOutEdge);
00478     } else {
00479         assert(i < (int)m_OutEdges.size());
00480         m_OutEdges[i] = pNewOutEdge;
00481     }
00482 }
00483 
00484 /*==============================================================================
00485  * FUNCTION:        BasicBlock::getOutEdge
00486  * OVERVIEW:        Returns the i-th out edge of this BB; counting starts at 0
00487  * NOTE:            
00488  * PARAMETERS:      i: index (0 based) of the desired out edge
00489  * RETURNS:         the i-th out edge; 0 if there is no such out edge
00490  *============================================================================*/
00491 PBB BasicBlock::getOutEdge(unsigned int i) {
00492     if (i < m_OutEdges.size()) return m_OutEdges[i];
00493     else return 0;
00494 }
00495 
00496 /*==============================================================================
00497  * FUNCTION:        BasicBlock::getCorrectOutEdge
00498  * OVERVIEW:        given an address this method returns the corresponding
00499  *                  out edge
00500  * NOTE:            
00501  * PARAMETERS:      a: the address
00502  * RETURNS:         
00503  *============================================================================*/
00504 
00505 PBB BasicBlock::getCorrectOutEdge(ADDRESS a) {
00506     std::vector<PBB>::iterator it;
00507     for (it = m_OutEdges.begin(); it != m_OutEdges.end(); it++) {
00508         if ((*it)->getLowAddr() == a) return *it; 
00509     }
00510     return 0;
00511 }
00512 
00513 
00514 /*==============================================================================
00515  * FUNCTION:        BasicBlock::addInEdge
00516  * OVERVIEW:        Add the given in-edge
00517  *                  Needed for example when duplicating BBs
00518  * PARAMETERS:      pNewInEdge: pointer to BB that will be a new parent
00519  * RETURNS:         <nothing>
00520  *============================================================================*/
00521 void BasicBlock::addInEdge(PBB pNewInEdge) {
00522     m_InEdges.push_back(pNewInEdge);
00523     m_iNumInEdges++;
00524 }
00525 
00526 /*==============================================================================
00527  * FUNCTION:        BasicBlock::deleteInEdge
00528  * OVERVIEW:        Delete the in-edge from the given BB
00529  *                  Needed for example when duplicating BBs
00530  * PARAMETERS:      it: iterator to BB that will no longer be a parent
00531  * SIDE EFFECTS:    The iterator argument is incremented.
00532  * USAGE:           It should be used like this:
00533  *                      if (pred) deleteInEdge(it) else it++;
00534  * RETURNS:         <nothing>
00535  *============================================================================*/
00536 void BasicBlock::deleteInEdge(std::vector<PBB>::iterator& it) {
00537     it = m_InEdges.erase(it);
00538     m_iNumInEdges--;
00539 }
00540 
00541 void BasicBlock::deleteInEdge(PBB edge) {
00542     for (std::vector<PBB>::iterator it = m_InEdges.begin(); 
00543          it != m_InEdges.end(); it++) {
00544         if (*it == edge) {
00545             deleteInEdge(it);
00546             break;
00547         }
00548     }
00549 }
00550 
00551 void BasicBlock::deleteEdge(PBB edge) {
00552     edge->deleteInEdge(this);
00553     for (std::vector<PBB>::iterator it = m_OutEdges.begin(); 
00554          it != m_OutEdges.end(); it++) {
00555         if (*it == edge) {
00556             m_OutEdges.erase(it);
00557             m_iNumOutEdges--;
00558             break;
00559         }
00560     }
00561 }
00562 
00563 /*==============================================================================
00564  * FUNCTION:        BasicBlock::DFTOrder
00565  * OVERVIEW:        Traverse this node and recurse on its children in a depth first manner. Records the times at which
00566  *                      this node was first visited and last visited
00567  * PARAMETERS:      first - the number of nodes that have been visited
00568  *                  last - the number of nodes that have been visited for the last time during this traversal
00569  * RETURNS:         the number of nodes (including this one) that were traversed from this node
00570  *============================================================================*/
00571 unsigned BasicBlock::DFTOrder(int& first, int& last) {
00572     first++;
00573     m_DFTfirst = first;
00574 
00575     unsigned numTraversed = 1;
00576     m_iTraversed = true;
00577 
00578     for (std::vector<PBB>::iterator it = m_OutEdges.begin(); it != m_OutEdges.end(); it++) {
00579         PBB child = *it;
00580         if (child->m_iTraversed == false)
00581             numTraversed = numTraversed + child->DFTOrder(first,last);
00582     }
00583 
00584     last++;
00585     m_DFTlast = last;
00586 
00587     return numTraversed;
00588 }
00589 
00590 /*==============================================================================
00591  * FUNCTION:    BasicBlock::RevDFTOrder
00592  * OVERVIEW:    Traverse this node and recurse on its parents in a reverse depth first manner.
00593  *                  Records the times at which this node was first visited and last visited
00594  * PARAMETERS:  first - the number of nodes that have been visited
00595  *              last - the number of nodes that have been visited for the last time during this traversal
00596  * RETURNS:     the number of nodes (including this one) that were traversed from this node
00597  *============================================================================*/
00598 unsigned BasicBlock::RevDFTOrder(int& first, int& last) {
00599     first++;
00600     m_DFTrevfirst = first;
00601 
00602     unsigned numTraversed = 1;
00603     m_iTraversed = true;
00604 
00605     for (std::vector<PBB>::iterator it = m_InEdges.begin(); it != m_InEdges.end();
00606          it++) {
00607 
00608         PBB parent = *it;
00609         if (parent->m_iTraversed == false)
00610             numTraversed = numTraversed + parent->RevDFTOrder(first,last);
00611     }
00612 
00613     last++;
00614     m_DFTrevlast = last;
00615 
00616     return numTraversed;
00617 }
00618 
00619 /*==============================================================================
00620  * FUNCTION:        BasicBlock::lessAddress
00621  * OVERVIEW:        Static comparison function that returns true if the first BB has an address less than the second BB.
00622  * PARAMETERS:      bb1 - first BB
00623  *                  bb2 - last BB
00624  * RETURNS:         bb1.address < bb2.address
00625  *============================================================================*/
00626 bool BasicBlock::lessAddress(PBB bb1, PBB bb2) {
00627     return bb1->getLowAddr() < bb2->getLowAddr();
00628 }
00629 
00630 /*==============================================================================
00631  * FUNCTION:        BasicBlock::lessFirstDFT
00632  * OVERVIEW:        Static comparison function that returns true if the first BB has DFT first order less than the
00633  *                      second BB.
00634  * PARAMETERS:      bb1 - first BB
00635  *                  bb2 - last BB
00636  * RETURNS:         bb1.first_DFS < bb2.first_DFS
00637  *============================================================================*/
00638 bool BasicBlock::lessFirstDFT(PBB bb1, PBB bb2) {
00639     return bb1->m_DFTfirst < bb2->m_DFTfirst;
00640 }
00641 
00642 
00643 /*==============================================================================
00644  * FUNCTION:        BasicBlock::lessLastDFT
00645  * OVERVIEW:        Static comparison function that returns true if the first BB has DFT first order less than the
00646  *                      second BB.
00647  * PARAMETERS:      bb1 - first BB
00648  *                  bb2 - last BB
00649  * RETURNS:         bb1.last_DFS < bb2.last_DFS
00650  *============================================================================*/
00651 bool BasicBlock::lessLastDFT(PBB bb1, PBB bb2) {
00652     return bb1->m_DFTlast < bb2->m_DFTlast;
00653 }
00654 
00655 /*==============================================================================
00656  * FUNCTION:        BasicBlock::getCallDest
00657  * OVERVIEW:        Get the destination of the call, if this is a CALL BB with
00658  *                      a fixed dest. Otherwise, return -1
00659  * PARAMETERS:      <none>
00660  * RETURNS:         Native destination of the call, or -1
00661  *============================================================================*/
00662 ADDRESS BasicBlock::getCallDest() {
00663     if (m_nodeType != CALL)
00664         return (ADDRESS)-1;
00665     if (m_pRtls->size() == 0)
00666         return (ADDRESS)-1;
00667     RTL* lastRtl = m_pRtls->back();
00668     RTL::reverse_iterator rit;
00669     std::list<Statement*>& sl = lastRtl->getList();
00670     for (rit = sl.rbegin(); rit != sl.rend(); rit++) {
00671         if ((*rit)->getKind() == STMT_CALL)
00672             return ((CallStatement*)(*rit))->getFixedDest();
00673     }
00674     return (ADDRESS)-1;
00675 }
00676 
00677 Proc *BasicBlock::getCallDestProc() {
00678     if (m_nodeType != CALL)
00679         return 0;
00680     if (m_pRtls->size() == 0)
00681         return 0;
00682     RTL* lastRtl = m_pRtls->back();
00683     RTL::reverse_iterator it;
00684     std::list<Statement*>& sl = lastRtl->getList();
00685     for (it = sl.rbegin(); it != sl.rend(); it++) {
00686         if ((*it)->getKind() == STMT_CALL)
00687             return ((CallStatement*)(*it))->getDestProc();
00688     }
00689     return 0;
00690 }
00691 
00692 //
00693 // Get First/Next Statement in a BB
00694 //
00695 Statement* BasicBlock::getFirstStmt(rtlit& rit, StatementList::iterator& sit) {
00696     if (m_pRtls == NULL) return NULL;
00697     rit = m_pRtls->begin();
00698     while (rit != m_pRtls->end()) {
00699         RTL* rtl = *rit;
00700         sit = rtl->getList().begin();
00701         if (sit != rtl->getList().end())
00702             return *sit;
00703         rit++;
00704     }
00705     return NULL;
00706 }
00707 
00708 Statement* BasicBlock::getNextStmt(rtlit& rit, StatementList::iterator& sit) {
00709     if (++sit != (*rit)->getList().end())
00710         return *sit;                        // End of current RTL not reached, so return next
00711     // Else, find next non-empty RTL & return its first statement
00712     do {
00713         if (++rit == m_pRtls->end())
00714             return NULL;                    // End of all RTLs reached, return null Statement
00715     } while ((*rit)->getNumStmt() == 0);    // Ignore all RTLs with no statements
00716     sit = (*rit)->getList().begin();        // Point to 1st statement at start of next RTL
00717     return *sit;                            // Return first statement
00718 }
00719 
00720 Statement* BasicBlock::getPrevStmt(rtlrit& rit, StatementList::reverse_iterator& sit) {
00721     if (++sit != (*rit)->getList().rend())
00722         return *sit;            // Beginning of current RTL not reached, so return next
00723     // Else, find prev non-empty RTL & return its last statement
00724     do {
00725         if (++rit == m_pRtls->rend())
00726             return NULL;                    // End of all RTLs reached, return null Statement
00727     } while ((*rit)->getNumStmt() == 0);    // Ignore all RTLs with no statements
00728     sit = (*rit)->getList().rbegin();       // Point to last statement at end of prev RTL
00729     return *sit;                            // Return last statement
00730 }
00731 
00732 Statement* BasicBlock::getLastStmt(rtlrit& rit, StatementList::reverse_iterator& sit) {
00733     if (m_pRtls == NULL) return NULL;
00734     rit = m_pRtls->rbegin();
00735     while (rit != m_pRtls->rend()) {
00736         RTL* rtl = *rit;
00737         sit = rtl->getList().rbegin();
00738         if (sit != rtl->getList().rend())
00739             return *sit;
00740         rit++;
00741     }
00742     return NULL;
00743 }
00744 
00745 Statement* BasicBlock::getFirstStmt() {
00746     rtlit rit;
00747     StatementList::iterator sit;
00748     if (m_pRtls == NULL) return NULL;
00749     rit = m_pRtls->begin();
00750     while (rit != m_pRtls->end()) {
00751         RTL* rtl = *rit;
00752         sit = rtl->getList().begin();
00753         if (sit != rtl->getList().end())
00754             return *sit;
00755         rit++;
00756     }
00757     return NULL;
00758 }
00759 Statement* BasicBlock::getLastStmt() {
00760     rtlrit rit;
00761     StatementList::reverse_iterator sit;
00762     if (m_pRtls == NULL) return NULL;
00763     rit = m_pRtls->rbegin();
00764     while (rit != m_pRtls->rend()) {
00765         RTL* rtl = *rit;
00766         sit = rtl->getList().rbegin();
00767         if (sit != rtl->getList().rend())
00768             return *sit;
00769         rit++;
00770     }
00771     return NULL;
00772 }
00773 
00774 void BasicBlock::getStatements(StatementList &stmts)
00775 {
00776     std::list<RTL*> *rtls = getRTLs();
00777     if (rtls) {
00778         for (std::list<RTL*>::iterator rit = rtls->begin(); rit != rtls->end(); rit++) {
00779             RTL *rtl = *rit;
00780             for (RTL::iterator it = rtl->getList().begin(); it != rtl->getList().end(); it++) {
00781                 if ((*it)->getBB() == NULL)
00782                     (*it)->setBB(this);
00783                 stmts.append(*it);
00784             }
00785         }
00786     }
00787 }
00788 
00789 /*
00790  * Structuring and code generation.
00791  *
00792  * This code is whole heartly based on AST by Doug Simon. Portions may be copyright to him and are available under a BSD
00793  * style license.
00794  *
00795  * Adapted for Boomerang by Trent Waddington, 20 June 2002.
00796  *
00797  */
00798 
00799 /* Get the condition */
00800 Exp *BasicBlock::getCond() throw(LastStatementNotABranchError) {
00801     // the condition will be in the last rtl
00802     assert(m_pRtls);
00803     RTL *last = m_pRtls->back();
00804     // it should contain a BranchStatement
00805     BranchStatement* bs = (BranchStatement*)last->getHlStmt();
00806     if (bs && bs->getKind() == STMT_BRANCH)
00807         return bs->getCondExpr();
00808     if (VERBOSE)
00809         LOG << "throwing LastStatementNotABranchError\n";
00810     throw LastStatementNotABranchError(last->getHlStmt());
00811 }
00812 
00813 /* Get the destiantion, if any */
00814 Exp *BasicBlock::getDest() throw(LastStatementNotAGotoError) {
00815     // The destianation will be in the last rtl
00816     assert(m_pRtls);
00817     RTL *lastRtl = m_pRtls->back();
00818     // It should contain a GotoStatement or derived class
00819     Statement* lastStmt = lastRtl->getHlStmt();
00820     CaseStatement* cs = dynamic_cast<CaseStatement*>(lastStmt);
00821     if (cs) {
00822         // Get the expression from the switch info
00823         SWITCH_INFO* si = cs->getSwitchInfo();
00824         if (si)
00825             return si->pSwitchVar;
00826     } else {
00827         GotoStatement* gs = dynamic_cast<GotoStatement*>(lastStmt);
00828         if (gs)
00829             return gs->getDest();
00830     }
00831     if (VERBOSE)
00832         LOG << "throwing LastStatementNotAGotoError\n";
00833     throw LastStatementNotAGotoError(lastStmt);
00834 }
00835 
00836 void BasicBlock::setCond(Exp *e) throw(LastStatementNotABranchError) {
00837     // the condition will be in the last rtl
00838     assert(m_pRtls);
00839     RTL *last = m_pRtls->back();
00840     // it should contain a BranchStatement
00841     std::list<Statement*>& sl = last->getList();
00842     RTL::reverse_iterator it;
00843     assert(sl.size());
00844     for (it = sl.rbegin(); it != sl.rend(); it++) {
00845         if ((*it)->getKind() == STMT_BRANCH) {
00846             ((BranchStatement*)(*it))->setCondExpr(e);
00847             return;
00848         }
00849     }
00850     throw LastStatementNotABranchError(NULL);
00851 }
00852 
00853 /* Check for branch if equal relation */
00854 bool BasicBlock::isJmpZ(PBB dest) {
00855     // The condition will be in the last rtl
00856     assert(m_pRtls);
00857     RTL *last = m_pRtls->back();
00858     // it should contain a BranchStatement
00859     std::list<Statement*>& sl = last->getList();
00860     std::list<Statement*>::reverse_iterator it;
00861     assert(sl.size());
00862     for (it = sl.rbegin(); it != sl.rend(); it++) {
00863         if ((*it)->getKind() == STMT_BRANCH) {
00864             BRANCH_TYPE jt = ((BranchStatement*)(*it))->getCond();
00865             if ((jt != BRANCH_JE) && (jt != BRANCH_JNE)) return false;
00866             PBB trueEdge = m_OutEdges[0];
00867             if (jt == BRANCH_JE)
00868             return dest == trueEdge;
00869             else {
00870                 PBB falseEdge = m_OutEdges[1];
00871                 return dest == falseEdge;
00872             }
00873         }
00874     }
00875     assert(0);
00876     return false;
00877 }
00878 
00879 /* Get the loop body */
00880 BasicBlock *BasicBlock::getLoopBody() {
00881     assert(m_structType == PRETESTLOOP || m_structType == POSTTESTLOOP || m_structType == ENDLESSLOOP);
00882     assert(m_iNumOutEdges == 2);
00883     if (m_OutEdges[0] != m_loopFollow)
00884         return m_OutEdges[0];
00885     return m_OutEdges[1];
00886 }
00887 
00888 bool BasicBlock::isAncestorOf(BasicBlock *other) {           
00889     return ((loopStamps[0] < other->loopStamps[0] && 
00890              loopStamps[1] > other->loopStamps[1]) ||
00891             (revLoopStamps[0] < other->revLoopStamps[0] && 
00892              revLoopStamps[1] > other->revLoopStamps[1]));
00893 /*  return (m_DFTfirst < other->m_DFTfirst && m_DFTlast > other->m_DFTlast) ||
00894     (m_DFTrevlast < other->m_DFTrevlast &&
00895      m_DFTrevfirst > other->m_DFTrevfirst);*/
00896 }
00897 
00898 void BasicBlock::simplify() {
00899     if (m_pRtls)
00900         for (std::list<RTL*>::iterator it = m_pRtls->begin(); it != m_pRtls->end(); it++)
00901             (*it)->simplify();
00902     if (m_nodeType == TWOWAY) {
00903         if (m_pRtls == NULL || m_pRtls->size() == 0) {
00904             m_nodeType = FALL;
00905         } else {
00906             RTL *last = m_pRtls->back();
00907             if (last->getNumStmt() == 0) {
00908                 m_nodeType = FALL;
00909             } else if (last->elementAt(last->getNumStmt()-1)->isGoto()) {
00910                 m_nodeType = ONEWAY;
00911             } else if (!last->elementAt(last->getNumStmt()-1)->isBranch()) {
00912                 m_nodeType = FALL;
00913             }
00914         }
00915         if (m_nodeType == FALL) {
00916             // set out edges to be the second one
00917             if (VERBOSE) {
00918                 LOG << "turning TWOWAY into FALL: " 
00919                     << m_OutEdges[0]->getLowAddr() << " " 
00920                     << m_OutEdges[1]->getLowAddr() << "\n";
00921             }
00922             PBB redundant = m_OutEdges[0];
00923             m_OutEdges[0] = m_OutEdges[1];
00924             m_OutEdges.resize(1);
00925             m_iNumOutEdges = 1;
00926             if (VERBOSE)
00927                 LOG << "redundant edge to " << redundant->getLowAddr() << " inedges: ";
00928             std::vector<PBB> rinedges = redundant->m_InEdges;
00929             redundant->m_InEdges.clear();
00930             for (unsigned i = 0; i < rinedges.size(); i++) {
00931                 if (VERBOSE)
00932                     LOG << rinedges[i]->getLowAddr() << " ";
00933                 if (rinedges[i] != this)
00934                     redundant->m_InEdges.push_back(rinedges[i]);
00935                 else {
00936                     if (VERBOSE)
00937                         LOG << "(ignored) ";
00938                 }
00939             }
00940             if (VERBOSE)
00941                 LOG << "\n";
00942             redundant->m_iNumInEdges = redundant->m_InEdges.size();
00943             if (VERBOSE)
00944                 LOG << "   after: " << m_OutEdges[0]->getLowAddr() << "\n";
00945         }
00946         if (m_nodeType == ONEWAY) {
00947             // set out edges to be the first one
00948             if (VERBOSE) {
00949                 LOG << "turning TWOWAY into ONEWAY: " 
00950                     << m_OutEdges[0]->getLowAddr() << " " 
00951                     << m_OutEdges[1]->getLowAddr() << "\n";
00952             }
00953             PBB redundant = m_OutEdges[1];
00954             m_OutEdges.resize(1);
00955             m_iNumOutEdges = 1;
00956             if (VERBOSE)
00957                 LOG << "redundant edge to " << redundant->getLowAddr() << " inedges: ";
00958             std::vector<PBB> rinedges = redundant->m_InEdges;
00959             redundant->m_InEdges.clear();
00960             for (unsigned i = 0; i < rinedges.size(); i++) {
00961                 if (VERBOSE)
00962                     LOG << rinedges[i]->getLowAddr() << " ";
00963                 if (rinedges[i] != this)
00964                     redundant->m_InEdges.push_back(rinedges[i]);
00965                 else {
00966                     if (VERBOSE)
00967                         LOG << "(ignored) ";
00968                 }
00969             }
00970             if (VERBOSE)
00971                 LOG << "\n";
00972             redundant->m_iNumInEdges = redundant->m_InEdges.size();
00973             if (VERBOSE)
00974                 LOG << "   after: " << m_OutEdges[0]->getLowAddr() << "\n";
00975         }
00976     }
00977 }
00978         
00979 bool BasicBlock::hasBackEdgeTo(BasicBlock* dest) {
00980 //  assert(HasEdgeTo(dest) || dest == this);
00981     return dest == this || dest->isAncestorOf(this);
00982 }
00983 
00984 // Return true if every parent (i.e. forward in edge source) of this node has 
00985 // had its code generated
00986 bool BasicBlock::allParentsGenerated()
00987 {
00988     for (unsigned int i = 0; i < m_InEdges.size(); i++)
00989         if (!m_InEdges[i]->hasBackEdgeTo(this) && 
00990             m_InEdges[i]->traversed != DFS_CODEGEN)
00991             return false;
00992     return true;
00993 }
00994 
00995 // Emits a goto statement (at the correct indentation level) with the destination label for dest. Also places the label
00996 // just before the destination code if it isn't already there.  If the goto is to the return block, it would be nice to
00997 // emit a 'return' instead (but would have to duplicate the other code in that return BB).  Also, 'continue' and 'break'
00998 // statements are used instead if possible
00999 void BasicBlock::emitGotoAndLabel(HLLCode *hll, int indLevel, PBB dest)
01000 {
01001     if (loopHead && (loopHead == dest || loopHead->loopFollow == dest)) {
01002         if (loopHead == dest)
01003             hll->AddContinue(indLevel);
01004         else
01005             hll->AddBreak(indLevel);
01006     } else {
01007         hll->AddGoto(indLevel, dest->ord);
01008 
01009         dest->hllLabel = true;
01010     }
01011 }
01012 
01013 // Generates code for each non CTI (except procedure calls) statement within the block.
01014 void BasicBlock::WriteBB(HLLCode *hll, int indLevel)
01015 {
01016     if (DEBUG_GEN)
01017         LOG << "Generating code for BB at " << getLowAddr() << "\n";
01018 
01019     // Allocate space for a label to be generated for this node and add this to the generated code. The actual label can
01020     // then be generated now or back patched later
01021     hll->AddLabel(indLevel, ord);
01022 
01023     if (m_pRtls) {
01024         for (std::list<RTL*>::iterator it = m_pRtls->begin(); it != m_pRtls->end(); it++) {
01025             if (DEBUG_GEN)
01026                 LOG << (*it)->getAddress() << "\t";
01027             (*it)->generateCode(hll, this, indLevel);
01028         }
01029         if (DEBUG_GEN)
01030             LOG << "\n";
01031     }
01032 
01033     // save the indentation level that this node was written at
01034     indentLevel = indLevel;
01035 }
01036 
01037 void BasicBlock::generateCode(HLLCode *hll, int indLevel, PBB latch, 
01038     std::list<PBB> &followSet, std::list<PBB> &gotoSet, UserProc* proc) {
01039     // If this is the follow for the most nested enclosing conditional, then don't generate anything. Otherwise if it is
01040     // in the follow set generate a goto to the follow
01041     PBB enclFollow = followSet.size() == 0 ? NULL : followSet.back();
01042 
01043     if (isIn(gotoSet, this) && !isLatchNode() && 
01044             ((latch && latch->loopHead && this == latch->loopHead->loopFollow) || 
01045             !allParentsGenerated())) {
01046         emitGotoAndLabel(hll, indLevel, this);
01047         return;
01048     } else if (isIn(followSet, this)) {
01049         if (this != enclFollow) {
01050             emitGotoAndLabel(hll, indLevel, this);
01051             return;
01052         } else return;
01053     }
01054 
01055     // Has this node already been generated?
01056     if (traversed == DFS_CODEGEN) {
01057         // this should only occur for a loop over a single block
01058         // FIXME: is this true? Perl_list (0x8068028) in the SPEC 2000 perlbmk seems to have a case with sType = Cond,
01059         // lType == PreTested, and latchNod == 0
01060         //assert(sType == Loop && lType == PostTested && latchNode == this);
01061         return;
01062     } else
01063         traversed = DFS_CODEGEN;
01064 
01065     // if this is a latchNode and the current indentation level is the same as the first node in the loop, then this
01066     // write out its body and return otherwise generate a goto
01067     if (isLatchNode())
01068         if (latch && latch->loopHead &&
01069                 indLevel == latch->loopHead->indentLevel + (latch->loopHead->lType == PreTested ? 1 : 0)) {
01070             WriteBB(hll, indLevel);
01071             return;
01072         } else {
01073             // unset its traversed flag
01074             traversed = UNTRAVERSED;
01075 
01076             emitGotoAndLabel(hll, indLevel, this);
01077             return;
01078         }
01079 
01080     PBB child = NULL;
01081     switch(sType) {
01082         case Loop:
01083         case LoopCond:
01084             // add the follow of the loop (if it exists) to the follow set
01085             if (loopFollow)
01086                 followSet.push_back(loopFollow);
01087 
01088             if (lType == PreTested) {
01089                 assert(latchNode->m_OutEdges.size() == 1);
01090 
01091                 // write the body of the block (excluding the predicate)
01092                 WriteBB(hll, indLevel);
01093 
01094                 // write the 'while' predicate
01095                 Exp *cond = getCond();
01096                 if (m_OutEdges[BTHEN] == loopFollow) {
01097                     cond = new Unary(opNot, cond);
01098                     cond = cond->simplify();
01099                 }
01100                 hll->AddPretestedLoopHeader(indLevel, cond);
01101 
01102                 // write the code for the body of the loop
01103                 PBB loopBody = (m_OutEdges[BELSE] == loopFollow) ? m_OutEdges[BTHEN] : m_OutEdges[BELSE];
01104                 loopBody->generateCode(hll, indLevel + 1, latchNode, followSet, gotoSet, proc);
01105 
01106                 // if code has not been generated for the latch node, generate it now
01107                 if (latchNode->traversed != DFS_CODEGEN) {
01108                     latchNode->traversed = DFS_CODEGEN;
01109                     latchNode->WriteBB(hll, indLevel+1);
01110                 }
01111 
01112                 // rewrite the body of the block (excluding the predicate) at the next nesting level after making sure
01113                 // another label won't be generated
01114                 hllLabel = false;
01115                 WriteBB(hll, indLevel+1);
01116 
01117                 // write the loop tail
01118                 hll->AddPretestedLoopEnd(indLevel);
01119             } else {
01120                 // write the loop header
01121                 if (lType == Endless)
01122                     hll->AddEndlessLoopHeader(indLevel);
01123                 else
01124                     hll->AddPosttestedLoopHeader(indLevel);
01125 
01126                 // if this is also a conditional header, then generate code for the conditional. Otherwise generate code
01127                 // for the loop body.
01128                 if (sType == LoopCond) {
01129                     // set the necessary flags so that generateCode can successfully be called again on this node
01130                     sType = Cond;
01131                     traversed = UNTRAVERSED;
01132                     generateCode(hll, indLevel + 1, latchNode, followSet, gotoSet, proc);
01133                 } else {
01134                     WriteBB(hll, indLevel+1);
01135 
01136                     // write the code for the body of the loop
01137                     m_OutEdges[0]->generateCode(hll, indLevel + 1, latchNode, followSet, gotoSet, proc);
01138                 }
01139 
01140                 if (lType == PostTested) {
01141                     // if code has not been generated for the latch node, generate it now
01142                     if (latchNode->traversed != DFS_CODEGEN) {
01143                         latchNode->traversed = DFS_CODEGEN;
01144                         latchNode->WriteBB(hll, indLevel+1);
01145                     }
01146                         
01147                     //hll->AddPosttestedLoopEnd(indLevel, getCond());
01148                     // MVE: the above seems to fail when there is a call in the middle of the loop (so loop is 2 BBs)
01149                     // Just a wild stab:
01150                     hll->AddPosttestedLoopEnd(indLevel, latchNode->getCond());
01151                 } else {
01152                     assert(lType == Endless);
01153 
01154                     // if code has not been generated for the latch node, generate it now
01155                     if (latchNode->traversed != DFS_CODEGEN) {
01156                         latchNode->traversed = DFS_CODEGEN;
01157                         latchNode->WriteBB(hll, indLevel+1);
01158                     }
01159 
01160                     // write the closing bracket for an endless loop
01161                     hll->AddEndlessLoopEnd(indLevel);
01162                 }
01163             }
01164 
01165             // write the code for the follow of the loop (if it exists)
01166             if (loopFollow) {
01167                 // remove the follow from the follow set
01168                 followSet.resize(followSet.size()-1);
01169 
01170                 if (loopFollow->traversed != DFS_CODEGEN)
01171                     loopFollow->generateCode(hll, indLevel, latch, followSet, gotoSet, proc);
01172                 else
01173                     emitGotoAndLabel(hll, indLevel, loopFollow);
01174             }
01175             break;
01176 
01177         case Cond:
01178         {
01179             // reset this back to LoopCond if it was originally of this type
01180             if (latchNode)
01181                 sType = LoopCond;
01182 
01183             // for 2 way conditional headers that are effectively jumps into 
01184             // or out of a loop or case body, we will need a new follow node
01185             PBB tmpCondFollow = NULL;
01186 
01187             // keep track of how many nodes were added to the goto set so that 
01188             // the correct number are removed
01189             int gotoTotal = 0;
01190 
01191             // add the follow to the follow set if this is a case header
01192             if (cType == Case)
01193                 followSet.push_back(condFollow);
01194             else if (cType != Case && condFollow) {
01195                 // For a structured two conditional header, its follow is 
01196                 // added to the follow set
01197                 //myLoopHead = (sType == LoopCond ? this : loopHead);
01198 
01199                 if (usType == Structured)
01200                     followSet.push_back(condFollow);
01201         
01202                 // Otherwise, for a jump into/outof a loop body, the follow is added to the goto set.
01203                 // The temporary follow is set for any unstructured conditional header branch that is within the 
01204                 // same loop and case.
01205                 else {
01206                     if (usType == JumpInOutLoop) {
01207                         // define the loop header to be compared against
01208                             PBB myLoopHead = (sType == LoopCond ? this : loopHead);
01209                         gotoSet.push_back(condFollow);
01210                         gotoTotal++;
01211         
01212                         // also add the current latch node, and the loop header of the follow if they exist
01213                         if (latch) {
01214                             gotoSet.push_back(latch);
01215                             gotoTotal++;
01216                         }
01217                         
01218                         if (condFollow->loopHead && condFollow->loopHead != myLoopHead) {
01219                             gotoSet.push_back(condFollow->loopHead);
01220                             gotoTotal++;
01221                         }
01222                     }
01223 
01224                     if (cType == IfThen)
01225                         tmpCondFollow = m_OutEdges[BELSE];
01226                     else
01227                         tmpCondFollow = m_OutEdges[BTHEN];
01228 
01229                     // for a jump into a case, the temp follow is added to the follow set
01230                     if (usType == JumpIntoCase)
01231                         followSet.push_back(tmpCondFollow);
01232                 }
01233             }
01234 
01235             // write the body of the block (excluding the predicate)
01236             WriteBB(hll, indLevel);
01237 
01238             // write the conditional header 
01239             SWITCH_INFO* psi = NULL;                    // Init to NULL to suppress a warning
01240             if (cType == Case) {
01241                 // The CaseStatement will be in the last RTL this BB
01242                 RTL* last = m_pRtls->back();
01243                 CaseStatement* cs = (CaseStatement*)last->getHlStmt();
01244                 psi = cs->getSwitchInfo();
01245                 // Write the switch header (i.e. "switch(var) {")
01246                 hll->AddCaseCondHeader(indLevel, psi->pSwitchVar);
01247             } else {
01248                 Exp *cond = getCond();
01249                 if (cond == NULL)
01250                     cond = new Const(0xfeedface);  // hack, but better than a crash
01251                 if (cType == IfElse) {
01252                     cond = new Unary(opNot, cond->clone());
01253                     cond = cond->simplify();
01254                 }
01255                 if (cType == IfThenElse)
01256                     hll->AddIfElseCondHeader(indLevel, cond);
01257                 else
01258                     hll->AddIfCondHeader(indLevel, cond);
01259             }
01260 
01261             // write code for the body of the conditional
01262             if (cType != Case) {
01263                 PBB succ = (cType == IfElse ? m_OutEdges[BELSE] : m_OutEdges[BTHEN]);
01264 
01265                 // emit a goto statement if the first clause has already been 
01266                 // generated or it is the follow of this node's enclosing loop
01267                 if (succ->traversed == DFS_CODEGEN || (loopHead && succ == loopHead->loopFollow))
01268                     emitGotoAndLabel(hll, indLevel + 1, succ);
01269                 else        
01270                     succ->generateCode(hll, indLevel + 1, latch, followSet, gotoSet, proc);
01271 
01272                 // generate the else clause if necessary
01273                 if (cType == IfThenElse) {
01274                     // generate the 'else' keyword and matching brackets
01275                     hll->AddIfElseCondOption(indLevel);
01276 
01277                     succ = m_OutEdges[BELSE];
01278 
01279                     // emit a goto statement if the second clause has already 
01280                     // been generated
01281                     if (succ->traversed == DFS_CODEGEN)
01282                         emitGotoAndLabel(hll, indLevel + 1, succ);
01283                     else
01284                         succ->generateCode(hll, indLevel + 1, latch, followSet, gotoSet, proc);
01285 
01286                     // generate the closing bracket
01287                     hll->AddIfElseCondEnd(indLevel);
01288                 } else {
01289                     // generate the closing bracket
01290                     hll->AddIfCondEnd(indLevel);
01291                 }
01292             } else { // case header
01293                 // TODO: linearly emitting each branch of the switch does not result
01294                 //       in optimal fall-through.
01295                 // generate code for each out branch
01296                 for (unsigned int i = 0; i < m_OutEdges.size(); i++) {
01297                     // emit a case label
01298                     // FIXME: Not valid for all switch types
01299                     Const caseVal(0);
01300                     if (psi->chForm == 'F')                         // "Fortran" style?
01301                         caseVal.setInt(((int*)psi->uTable)[i]);     // Yes, use the table value itself
01302                                                                     // Note that uTable has the address of an int array
01303                     else
01304                         caseVal.setInt((int)(psi->iLower+i));
01305                     hll->AddCaseCondOption(indLevel, &caseVal);
01306 
01307                     // generate code for the current outedge
01308                     PBB succ = m_OutEdges[i];
01309 //assert(succ->caseHead == this || succ == condFollow || HasBackEdgeTo(succ));
01310                     if (succ->traversed == DFS_CODEGEN)
01311                         emitGotoAndLabel(hll, indLevel + 1, succ);
01312                     else {
01313                         succ->generateCode(hll, indLevel + 1, latch, followSet, gotoSet, proc);
01314                     }
01315                 }
01316                 // generate the closing bracket
01317                 hll->AddCaseCondEnd(indLevel);
01318             }
01319 
01320 
01321             // do all the follow stuff if this conditional had one
01322             if (condFollow) {
01323                 // remove the original follow from the follow set if it was 
01324                 // added by this header
01325                 if (usType == Structured || usType == JumpIntoCase) {
01326                     assert(gotoTotal == 0);
01327                     followSet.resize(followSet.size()-1);
01328                 } else // remove all the nodes added to the goto set
01329                     for (int i = 0; i < gotoTotal; i++)
01330                         gotoSet.resize(gotoSet.size()-1);
01331 
01332                 // do the code generation (or goto emitting) for the new conditional follow if it exists, otherwise do
01333                 // it for the original follow
01334                 if (!tmpCondFollow)
01335                     tmpCondFollow = condFollow;
01336                         
01337                 if (tmpCondFollow->traversed == DFS_CODEGEN)
01338                     emitGotoAndLabel(hll, indLevel, tmpCondFollow);
01339                 else
01340                     tmpCondFollow->generateCode(hll, indLevel, latch, followSet, gotoSet, proc);
01341             }
01342             break;
01343         } 
01344         case Seq:
01345             // generate code for the body of this block
01346             WriteBB(hll, indLevel);
01347 
01348             // return if this is the 'return' block (i.e. has no out edges) after emmitting a 'return' statement
01349             if (getType() == RET) {
01350                 // This should be emited now, like a normal statement
01351                 //hll->AddReturnStatement(indLevel, getReturnVal());
01352                 return;
01353             }
01354 
01355             // return if this doesn't have any out edges (emit a warning)
01356             if (m_OutEdges.size() == 0) {
01357                 std::cerr << "WARNING: no out edge for this BB in " << proc->getName() << ":\n";
01358                 this->print(std::cerr);
01359                 std::cerr << std::endl;
01360                 if (m_nodeType == COMPJUMP) {
01361                     std::ostringstream ost;
01362                     assert(m_pRtls->size());
01363                     RTL* lastRTL = m_pRtls->back();
01364                     assert(lastRTL->getNumStmt());
01365                     GotoStatement* gs = (GotoStatement*)lastRTL->elementAt(lastRTL->getNumStmt()-1);
01366                     ost << "goto " << gs->getDest();
01367                     hll->AddLineComment((char*)ost.str().c_str());
01368                 }
01369                 return;
01370             }
01371 
01372             child = m_OutEdges[0];
01373             if (m_OutEdges.size() != 1) {
01374                 PBB other = m_OutEdges[1];
01375                 LOG << "found seq with more than one outedge!\n";
01376                 if (getDest()->isIntConst() &&
01377                         ((Const*)getDest())->getInt() == (int)child->getLowAddr()) {
01378                     other = child;
01379                     child = m_OutEdges[1];
01380                     LOG << "taken branch is first out edge\n";
01381                 }
01382 
01383                 try {
01384                     hll->AddIfCondHeader(indLevel, getCond());
01385                     if (other->traversed == DFS_CODEGEN)
01386                         emitGotoAndLabel(hll, indLevel+1, other);
01387                     else
01388                         other->generateCode(hll, indLevel+1, latch, followSet, gotoSet, proc);
01389                     hll->AddIfCondEnd(indLevel);
01390                 } catch (LastStatementNotABranchError &) {
01391                     LOG << "last statement is not a cond, don't know what to do with this.\n";
01392                 }
01393             }
01394 
01395             // generate code for its successor if it hasn't already been visited and is in the same loop/case and is not
01396             // the latch for the current most enclosing loop.    The only exception for generating it when it is not in
01397             // the same loop is when it is only reached from this node
01398             if (child->traversed == DFS_CODEGEN || 
01399                     ((child->loopHead != loopHead) && (!child->allParentsGenerated() || 
01400                     isIn(followSet, child))) ||
01401                     (latch && latch->loopHead && latch->loopHead->loopFollow == child) ||
01402                     !(caseHead == child->caseHead || 
01403                     (caseHead && child == caseHead->condFollow)))
01404                 emitGotoAndLabel(hll, indLevel, child);
01405             else {
01406                 if (caseHead && child == caseHead->condFollow) {
01407                     // generate the 'break' statement
01408                     hll->AddCaseCondOptionEnd(indLevel);
01409                 } else if (caseHead == NULL || caseHead != child->caseHead || !child->isCaseOption())
01410                     child->generateCode(hll, indLevel, latch, followSet, gotoSet, proc);
01411             }
01412             break;
01413         default:
01414             std::cerr << "unhandled sType " << (int)sType << "\n";
01415     }
01416 }
01417 
01418 // Get the destination proc
01419 // Note: this must be a call BB!
01420 Proc* BasicBlock::getDestProc() {
01421     // The last Statement of the last RTL should be a CallStatement
01422     CallStatement* call = (CallStatement*)(m_pRtls->back()->getHlStmt());
01423     assert(call->getKind() == STMT_CALL);
01424     Proc* proc = call->getDestProc();
01425     if (proc == NULL) {
01426         std::cerr << "Indirect calls not handled yet\n";
01427         assert(0);
01428     }
01429     return proc;
01430 }
01431 
01432 void BasicBlock::setLoopStamps(int &time, std::vector<PBB> &order) {
01433     // timestamp the current node with the current time and set its traversed 
01434     // flag
01435     traversed = DFS_LNUM;
01436     loopStamps[0] = time;
01437 
01438     // recurse on unvisited children and set inedges for all children
01439     for (unsigned int i = 0; i < m_OutEdges.size(); i++) {
01440         // set the in edge from this child to its parent (the current node)
01441         // (not done here, might be a problem)
01442         // outEdges[i]->inEdges.Add(this);
01443 
01444         // recurse on this child if it hasn't already been visited
01445         if (m_OutEdges[i]->traversed != DFS_LNUM)
01446             m_OutEdges[i]->setLoopStamps(++time, order);
01447     }
01448 
01449     // set the the second loopStamp value
01450     loopStamps[1] = ++time;
01451 
01452     // add this node to the ordering structure as well as recording its position within the ordering
01453     ord = order.size();
01454     order.push_back(this);
01455 }
01456 
01457 void BasicBlock::setRevLoopStamps(int &time)
01458 {
01459     // timestamp the current node with the current time and set its traversed flag
01460     traversed = DFS_RNUM;
01461     revLoopStamps[0] = time;
01462 
01463     // recurse on the unvisited children in reverse order
01464     for (int i = m_OutEdges.size() - 1; i >= 0; i--) {
01465         // recurse on this child if it hasn't already been visited
01466         if (m_OutEdges[i]->traversed != DFS_RNUM)
01467             m_OutEdges[i]->setRevLoopStamps(++time);
01468     }
01469 
01470     // set the the second loopStamp value
01471     revLoopStamps[1] = ++time;
01472 }
01473 
01474 void BasicBlock::setRevOrder(std::vector<PBB> &order)
01475 {
01476     // Set this node as having been traversed during the post domimator DFS ordering traversal
01477     traversed = DFS_PDOM;
01478         
01479     // recurse on unvisited children 
01480     for (unsigned int i = 0; i < m_InEdges.size(); i++)
01481         if (m_InEdges[i]->traversed != DFS_PDOM)
01482             m_InEdges[i]->setRevOrder(order);
01483 
01484     // add this node to the ordering structure and record the post dom. order of this node as its index within this
01485     // ordering structure
01486     revOrd = order.size();
01487     order.push_back(this);
01488 }
01489 
01490 void BasicBlock::setCaseHead(PBB head, PBB follow) 
01491 {
01492     assert(!caseHead);
01493 
01494     traversed = DFS_CASE;
01495 
01496     // don't tag this node if it is the case header under investigation 
01497     if (this != head)
01498         caseHead = head;
01499 
01500     // if this is a nested case header, then it's member nodes will already have been tagged so skip straight to its
01501     // follow
01502     if (getType() == NWAY && this != head) {
01503         if (condFollow && condFollow->traversed != DFS_CASE && condFollow != follow)
01504             condFollow->setCaseHead(head, follow);
01505     } else
01506         // traverse each child of this node that:
01507         //   i) isn't on a back-edge,
01508         //  ii) hasn't already been traversed in a case tagging traversal and,
01509         // iii) isn't the follow node.
01510         for (unsigned int i = 0; i < m_OutEdges.size(); i++)
01511             if (!hasBackEdgeTo(m_OutEdges[i]) && 
01512                 m_OutEdges[i]->traversed != DFS_CASE && 
01513                 m_OutEdges[i] != follow)
01514                 m_OutEdges[i]->setCaseHead(head, follow);
01515 }
01516 
01517 void BasicBlock::setStructType(structType s) {
01518     // if this is a conditional header, determine exactly which type of conditional header it is (i.e. switch, if-then,
01519     // if-then-else etc.)
01520     if (s == Cond) {
01521         if (getType() == NWAY) 
01522             cType = Case;
01523         else if (m_OutEdges[BELSE] == condFollow)
01524             cType = IfThen;
01525         else if (m_OutEdges[BTHEN] == condFollow)
01526             cType = IfElse;
01527         else
01528             cType = IfThenElse;
01529     }
01530 
01531     sType = s;
01532 }
01533 
01534 void BasicBlock::setUnstructType(unstructType us) {
01535     assert((sType == Cond || sType == LoopCond) && cType != Case);
01536     usType = us;
01537 }
01538 
01539 unstructType BasicBlock::getUnstructType() {
01540     assert((sType == Cond || sType == LoopCond) && cType != Case);
01541     return usType;
01542 }
01543 
01544 void BasicBlock::setLoopType(loopType l) {
01545     assert (sType == Loop || sType == LoopCond);
01546     lType = l;
01547 
01548     // set the structured class (back to) just Loop if the loop type is PreTested OR it's PostTested and is a single
01549     // block loop
01550     if (lType == PreTested || (lType == PostTested && this == latchNode))
01551         sType = Loop;
01552 }
01553 
01554 loopType BasicBlock::getLoopType() {
01555     assert (sType == Loop || sType == LoopCond);
01556     return lType;
01557 }
01558 
01559 void BasicBlock::setCondType(condType c) {
01560     assert (sType == Cond || sType == LoopCond);
01561     cType = c;
01562 }
01563 
01564 condType BasicBlock::getCondType() {
01565     assert (sType == Cond || sType == LoopCond);
01566     return cType;
01567 }
01568 
01569 bool BasicBlock::inLoop(PBB header, PBB latch) {
01570     assert(header->latchNode == latch);
01571     assert(header == latch || 
01572         ((header->loopStamps[0] > latch->loopStamps[0] && latch->loopStamps[1] > header->loopStamps[1]) ||
01573         (header->loopStamps[0] < latch->loopStamps[0] && latch->loopStamps[1] < header->loopStamps[1])));
01574     // this node is in the loop if it is the latch node OR
01575     // this node is within the header and the latch is within this when using the forward loop stamps OR
01576     // this node is within the header and the latch is within this when using the reverse loop stamps 
01577     return this == latch ||
01578         (header->loopStamps[0] < loopStamps[0] && loopStamps[1] < header->loopStamps[1] &&
01579         loopStamps[0] < latch->loopStamps[0] && latch->loopStamps[1] < loopStamps[1]) ||
01580         (header->revLoopStamps[0] < revLoopStamps[0] && revLoopStamps[1] < header->revLoopStamps[1] &&
01581         revLoopStamps[0] < latch->revLoopStamps[0] && latch->revLoopStamps[1] < revLoopStamps[1]);
01582 }
01583 
01584 // Return the first statement number as a string.
01585 // Used in dotty file generation
01586 char* BasicBlock::getStmtNumber() {
01587     static char ret[12];
01588     rtlit rit; StatementList::iterator sit;
01589     Statement* first = getFirstStmt(rit, sit);
01590     if (first)
01591         sprintf(ret, "%d", first->getNumber());
01592     else
01593         sprintf(ret, "bb%x", (unsigned)this);
01594     return ret;
01595 } 
01596 
01597 // Prepend an assignment (usually a PhiAssign or ImplicitAssign)
01598 // Proc is the enclosing Proc
01599 void BasicBlock::prependStmt(Statement* s, UserProc* proc) {
01600     // Check the first RTL (if any)
01601     s->setBB(this);
01602     s->setProc(proc);
01603     if (m_pRtls->size()) {
01604         RTL* rtl = m_pRtls->front();
01605         if (rtl->getAddress() == 0) {
01606             // Append to this RTL
01607             rtl->appendStmt(s);
01608             return;
01609         }
01610     }
01611     // Otherwise, prepend a new RTL
01612     std::list<Statement*> listStmt;
01613     listStmt.push_back(s);
01614     RTL* rtl = new RTL(0, &listStmt);
01615     m_pRtls->push_front(rtl);
01616 }
01617 
01618 ////////////////////////////////////////////////////
01619 
01620 // Check for overlap of liveness between the currently live locations (liveLocs) and the set of locations in ls
01621 // Also check for type conflicts if DFA_TYPE_ANALYSIS
01622 // This is a helper function that is not directly declated in the BasicBlock class
01623 void checkForOverlap(LocationSet& liveLocs, LocationSet& ls, ConnectionGraph& ig, UserProc* proc) {
01624     // For each location to be considered
01625     LocationSet::iterator uu;
01626     for (uu = ls.begin(); uu != ls.end(); uu++) {
01627         Exp* u = (Exp*)*uu;
01628         if (!u->isSubscript()) continue;            // Only interested in subscripted vars
01629         RefExp* r = (RefExp*)u;
01630         // Interference if we can find a live variable which differs only in the reference
01631         Exp *dr;
01632         if (liveLocs.findDifferentRef(r, dr)) {
01633             // We have an interference between r and dr. Record it
01634             ig.connect(r, dr);
01635             if (VERBOSE || DEBUG_LIVENESS)
01636                 LOG << "interference of " << dr << " with " << r << "\n";
01637         }
01638         // Add the uses one at a time. Note: don't use makeUnion, because then we don't discover interferences
01639         // from the same statement, e.g.  blah := r24{2} + r24{3}
01640         liveLocs.insert(u);
01641     }
01642 }
01643 
01644 bool BasicBlock::calcLiveness(ConnectionGraph& ig, UserProc* myProc) {
01645     // Start with the liveness at the bottom of the BB
01646     LocationSet liveLocs, phiLocs;
01647     getLiveOut(liveLocs, phiLocs);
01648     // Do the livensses that result from phi statements at successors first.
01649     // FIXME: document why this is necessary
01650     checkForOverlap(liveLocs, phiLocs, ig, myProc);
01651     // For each RTL in this BB
01652     std::list<RTL*>::reverse_iterator rit;
01653     if (m_pRtls)  // this can be NULL
01654     for (rit = m_pRtls->rbegin(); rit != m_pRtls->rend(); rit++) {
01655         std::list<Statement*>& stmts = (*rit)->getList();
01656         std::list<Statement*>::reverse_iterator sit;
01657         // For each statement this RTL
01658         for (sit = stmts.rbegin(); sit != stmts.rend(); sit++) {
01659             Statement* s = *sit;
01660             LocationSet defs;
01661             s->getDefinitions(defs);
01662             // The definitions don't have refs yet
01663             defs.addSubscript(s /* , myProc->getCFG() */);
01664 #if 0       // I used to think it necessary to consider definitions as a special case. However, I now believe that
01665             // this was either an error of implementation (e.g. it didn't seem to correctly consider the livenesses
01666             // causesd by phis) or something to do with renaming but not propagating certain memory locations.
01667             // The idea is now to clearly divide locations into those that can be renamed and propagated, and those
01668             // which are not renamed or propagated. (Check this.)
01669 
01670             // Also consider it an interference if we define a location that is the same base variable. This can happen
01671             // when there is a definition that is unused but for whatever reason not eliminated
01672             // This check is done at the "bottom" of the statement, i.e. before we add s's uses and remove s's
01673             // definitions to liveLocs
01674             // Note that phi assignments don't count
01675             if (!s->isPhi())
01676                 checkForOverlap(liveLocs, defs, ig, myProc, false);
01677 #endif
01678             // Definitions kill uses. Now we are moving to the "top" of statement s
01679             liveLocs.makeDiff(defs);
01680             // Phi functions are a special case. The operands of phi functions are uses, but they don't interfere
01681             // with each other (since they come via different BBs). However, we don't want to put these uses into
01682             // liveLocs, because then the livenesses will flow to all predecessors. Only the appropriate livenesses
01683             // from the appropriate phi parameter should flow to the predecessor. This is done in getLiveOut()
01684             if (s->isPhi()) continue;
01685             // Check for livenesses that overlap
01686             LocationSet uses;
01687             s->addUsedLocs(uses);
01688             checkForOverlap(liveLocs, uses, ig, myProc);
01689             if (DEBUG_LIVENESS)
01690                 LOG << " ## liveness: at top of " << s << ", liveLocs is " << liveLocs.prints() << "\n";
01691         }
01692     }
01693     // liveIn is what we calculated last time
01694     if (!(liveLocs == liveIn)) {
01695         liveIn = liveLocs;
01696         return true;        // A change
01697     } else
01698         // No change
01699         return false;
01700 }
01701 
01702 // Locations that are live at the end of this BB are the union of the locations that are live at the start of its
01703 // successors
01704 // liveout gets all the livenesses, and phiLocs gets a subset of these, which are due to phi statements at the top of
01705 // successors
01706 void BasicBlock::getLiveOut(LocationSet &liveout, LocationSet& phiLocs) {
01707     liveout.clear();
01708     for (unsigned i = 0; i < m_OutEdges.size(); i++) {
01709         PBB currBB = m_OutEdges[i];
01710         // First add the non-phi liveness
01711         liveout.makeUnion(currBB->liveIn);
01712         int j = currBB->whichPred(this);
01713         // The first RTL will have the phi functions, if any
01714         if (currBB->m_pRtls == NULL || currBB->m_pRtls->size() == 0)
01715             continue;
01716         RTL* phiRtl = currBB->m_pRtls->front();
01717         std::list<Statement*>& stmts = phiRtl->getList();
01718         std::list<Statement*>::iterator it;
01719         for (it = stmts.begin(); it != stmts.end(); it++) {
01720             // Only interested in phi assignments. Note that it is possible that some phi assignments have been
01721             // converted to ordinary assignments. So the below is a continue, not a break.
01722             if (!(*it)->isPhi()) continue;
01723             PhiAssign* pa = (PhiAssign*)*it;
01724             // Get the jth operand to the phi function; it has a use from BB *this
01725             Statement* def = pa->getStmtAt(j);
01726             RefExp* r = new RefExp(pa->getLeft()->clone(), def);
01727             liveout.insert(r);
01728             phiLocs.insert(r);
01729             if (DEBUG_LIVENESS)
01730                 LOG << " ## Liveness: adding " << r << " due to ref to phi " << *it << " in BB at " << getLowAddr() <<
01731                     "\n";
01732         }
01733     }
01734 }
01735 
01736 // Basically the "whichPred" function as per Briggs, Cooper, et al (and presumably "Cryton, Ferante, Rosen, Wegman, and
01737 // Zadek").  Return -1 if not found
01738 int BasicBlock::whichPred(PBB pred) {
01739     int n = m_InEdges.size();
01740     for (int i=0; i < n; i++) {
01741         if (m_InEdges[i] == pred)
01742             return i;
01743     }
01744     assert(0);
01745     return -1;
01746 }
01747 
01748 //  //  //  //  //  //  //  //  //  //  //  //  //
01749 //                                              //
01750 //       Indirect jump and call analyses        //
01751 //                                              //
01752 //  //  //  //  //  //  //  //  //  //  //  //  //
01753 
01754 // Switch High Level patterns
01755 
01756 // With array processing, we get a new form, call it form 'a' (don't confuse with form 'A'):
01757 // Pattern: <base>{}[<index>]{} where <index> could be <var> - <Kmin>
01758 static Exp* forma = new RefExp(
01759         new Binary(opArrayIndex,
01760             new RefExp(
01761                 new Terminal(opWild),
01762                 (Statement*)-1),
01763             new Terminal(opWild)),
01764         (Statement*)-1);
01765 
01766 // Pattern: m[<expr> * 4 + T ]
01767 static Exp* formA   = Location::memOf(
01768         new Binary(opPlus,
01769             new Binary(opMult,
01770                 new Terminal(opWild),
01771                 new Const(4)),
01772             new Terminal(opWildIntConst)));
01773 
01774 // With array processing, we get a new form, call it form 'o' (don't confuse with form 'O'):
01775 // Pattern: <base>{}[<index>]{} where <index> could be <var> - <Kmin>
01776 // NOT COMPLETED YET!
01777 static Exp* formo = new RefExp(
01778         new Binary(opArrayIndex,
01779             new RefExp(
01780                 new Terminal(opWild),
01781                 (Statement*)-1),
01782             new Terminal(opWild)),
01783         (Statement*)-1);
01784 
01785 // Pattern: m[<expr> * 4 + T ] + T
01786 static Exp* formO = new Binary(opPlus,
01787     Location::memOf(
01788         new Binary(opPlus,
01789             new Binary(opMult,
01790                 new Terminal(opWild),
01791                 new Const(4)),
01792             new Terminal(opWildIntConst))),
01793     new Terminal(opWildIntConst));
01794 
01795 // Pattern: %pc + m[%pc  + (<expr> * 4) + k]
01796 // where k is a small constant, typically 28 or 20
01797 static Exp* formR = new Binary(opPlus,
01798     new Terminal(opPC),
01799     Location::memOf(new Binary(opPlus,
01800         new Terminal(opPC),
01801         new Binary(opPlus,
01802             new Binary(opMult,
01803                 new Terminal(opWild),
01804                 new Const(4)),
01805             new Const(opWildIntConst)))));
01806 
01807 // Pattern: %pc + m[%pc + ((<expr> * 4) - k)] - k
01808 // where k is a smallish constant, e.g. 288 (/usr/bin/vi 2.6, 0c4233c).
01809 static Exp* formr = new Binary(opPlus,
01810     new Terminal(opPC),
01811     Location::memOf(new Binary(opPlus,
01812         new Terminal(opPC),
01813         new Binary(opMinus,
01814             new Binary(opMult,
01815                 new Terminal(opWild),
01816                 new Const(4)),
01817         new Terminal(opWildIntConst)))));
01818 
01819 static Exp* hlForms[] = {forma, formA, formo, formO, formR, formr};
01820 static char chForms[] = {  'a',  'A',   'o',   'O',   'R',   'r'};
01821 
01822 void init_basicblock() {
01823 #ifndef NO_GARBAGE_COLLECTOR
01824     Exp** gc_pointers = (Exp**) GC_MALLOC_UNCOLLECTABLE(6 * sizeof(Exp*));
01825     gc_pointers[0] = forma;
01826     gc_pointers[1] = formA;
01827     gc_pointers[2] = formo;
01828     gc_pointers[3] = formO;
01829     gc_pointers[4] = formR;
01830     gc_pointers[5] = formr;
01831 #endif
01832 }
01833 
01834 // Vcall high level patterns
01835 // Pattern 0: global<wild>[0]
01836 static Binary* vfc_funcptr = new Binary(opArrayIndex,
01837     new Location(opGlobal,
01838         new Terminal(opWildStrConst), NULL),
01839     new Const(0));
01840 
01841 // Pattern 1: m[ m[ <expr> + K1 ] + K2 ]
01842 // K1 is vtable offset, K2 is virtual function offset (could come from m[A2], if A2 is in read-only memory
01843 static Location* vfc_both = Location::memOf(
01844     new Binary(opPlus,
01845         Location::memOf(
01846             new Binary(opPlus,
01847                 new Terminal(opWild),
01848                 new Terminal(opWildIntConst))),
01849             new Terminal(opWildIntConst)));
01850  
01851 // Pattern 2: m[ m[ <expr> ] + K2]
01852 static Location* vfc_vto = Location::memOf(
01853     new Binary(opPlus,
01854         Location::memOf(
01855             new Terminal(opWild)),
01856             new Terminal(opWildIntConst)));
01857 
01858 // Pattern 3: m[ m[ <expr> + K1] ]
01859 Location* vfc_vfo = Location::memOf(
01860     Location::memOf(
01861         new Binary(opPlus,
01862             new Terminal(opWild),
01863             new Terminal(opWildIntConst))));
01864 
01865 // Pattern 4: m[ m[ <expr> ] ]
01866 Location* vfc_none = Location::memOf(
01867     Location::memOf(
01868         new Terminal(opWild)));
01869 
01870 static Exp* hlVfc[] = {vfc_funcptr, vfc_both, vfc_vto, vfc_vfo, vfc_none};
01871 
01872 void findSwParams(char form, Exp* e, Exp*& expr, ADDRESS& T) {
01873     switch (form) {
01874         case 'a': {
01875             // Pattern: <base>{}[<index>]{}
01876             e = ((RefExp*)e)->getSubExp1();
01877             Exp* base = ((Binary*)e)->getSubExp1();
01878             if (base->isSubscript())
01879                 base = ((RefExp*)base)->getSubExp1();
01880             Exp* con = ((Location*)base)->getSubExp1();
01881             char* gloName = ((Const*)con)->getStr();
01882             UserProc* p = ((Location*)base)->getProc();
01883             Prog* prog = p->getProg();
01884             T = (ADDRESS)prog->getGlobalAddr(gloName);
01885             expr = ((Binary*)e)->getSubExp2();
01886             break;
01887         }
01888         case 'A': {
01889             // Pattern: m[<expr> * 4 + T ]
01890             if (e->isSubscript()) e = e->getSubExp1();
01891             // b will be (<expr> * 4) + T
01892             Binary* b = (Binary*)((Location*)e)->getSubExp1();
01893             Const* TT = (Const*)b->getSubExp2();
01894             T = (ADDRESS)TT->getInt();
01895             b = (Binary*)b->getSubExp1();   // b is now <expr> * 4
01896             expr = b->getSubExp1();
01897             break;
01898         }
01899         case 'O': {     // Form O
01900             // Pattern: m[<expr> * 4 + T ] + T
01901             T = ((Const*)((Binary*)e)->getSubExp2())->getInt();
01902             // l = m[<expr> * 4 + T ]:
01903             Exp* l = ((Binary*)e)->getSubExp1();
01904             if (l->isSubscript()) l = l->getSubExp1();
01905             // b = <expr> * 4 + T:
01906             Binary* b = (Binary*)((Location*)l)->getSubExp1();
01907             // b = <expr> * 4:
01908             b = (Binary*)b->getSubExp1();
01909             // expr = <expr>:
01910             expr = b->getSubExp1();
01911             break;
01912         }
01913         case 'R': {
01914             // Pattern: %pc + m[%pc  + (<expr> * 4) + k]
01915             T = 0;      // ?
01916             // l = m[%pc  + (<expr> * 4) + k]:
01917             Exp* l = ((Binary*)e)->getSubExp2();
01918             if (l->isSubscript()) l = l->getSubExp1();
01919             // b = %pc  + (<expr> * 4) + k:
01920             Binary* b = (Binary*)((Location*)l)->getSubExp1();
01921             // b = (<expr> * 4) + k:
01922             b = (Binary*)b->getSubExp2();
01923             // b = <expr> * 4:
01924             b = (Binary*)b->getSubExp1();
01925             // expr = <expr>:
01926             expr = b->getSubExp1();
01927             break;
01928         }
01929         case 'r': {
01930             // Pattern: %pc + m[%pc + ((<expr> * 4) - k)] - k
01931             T = 0;      // ?
01932             // b = %pc + m[%pc + ((<expr> * 4) - k)]:
01933             Binary* b = (Binary*)((Binary*)e)->getSubExp1();
01934             // l = m[%pc + ((<expr> * 4) - k)]:
01935             Exp* l = b->getSubExp2();
01936             if (l->isSubscript()) l = l->getSubExp1();
01937             // b = %pc + ((<expr> * 4) - k)
01938             b = (Binary*)((Location*)l)->getSubExp1();
01939             // b = ((<expr> * 4) - k):
01940             b = (Binary*)b->getSubExp2();
01941             // b = <expr> * 4:
01942             b = (Binary*)b->getSubExp1();
01943             // expr = <expr>
01944             expr = b->getSubExp1();
01945             break;
01946         }
01947         default:
01948             expr = NULL;
01949             T = NO_ADDRESS;
01950     }
01951 }
01952 
01953 // Find the number of cases for this switch statement. Assumes that there is a compare and branch around the indirect
01954 // branch. Note: fails test/sparc/switchAnd_cc because of the and instruction, and the compare that is outside is not
01955 // the compare for the upper bound. Note that you CAN have an and and still a test for an upper bound. So this needs
01956 // tightening.
01957 // TMN: It also needs to check for and handle the double indirect case; where there is one array (of e.g. ubyte)
01958 // that is indexed by the actual switch value, then the value from that array is used as an index into the array of
01959 // code pointers.
01960 int BasicBlock::findNumCases() {
01961     std::vector<PBB>::iterator it;
01962     for (it = m_InEdges.begin(); it != m_InEdges.end(); it++) {     // For each in-edge
01963         if ((*it)->m_nodeType != TWOWAY)                            // look for a two-way BB
01964             continue;                                               // Ignore all others
01965         assert((*it)->m_pRtls->size());
01966         RTL* lastRtl = (*it)->m_pRtls->back();
01967         assert(lastRtl->getNumStmt() >= 1);
01968         BranchStatement* lastStmt = (BranchStatement*)lastRtl->elementAt(lastRtl->getNumStmt()-1);
01969         Exp* pCond = lastStmt->getCondExpr();
01970         if (pCond->getArity() != 2) continue;
01971         Exp* rhs = ((Binary*)pCond)->getSubExp2();
01972         if (!rhs->isIntConst()) continue;
01973         int k = ((Const*)rhs)->getInt();
01974         OPER op = pCond->getOper();
01975         if (op == opGtr || op == opGtrUns)
01976             return k+1;
01977         if (op == opGtrEq || op == opGtrEqUns)
01978             return k;
01979         if (op == opLess || op == opLessUns)
01980             return k;
01981         if (op == opLessEq || op == opLessEqUns)
01982             return k+1;
01983     }
01984     LOG << "Could not find number of cases for n-way at address " << getLowAddr() << "\n";
01985     return 3;        // Bald faced guess if all else fails
01986 }
01987 
01988 // Find all the possible constant values that the location defined by s could be assigned with
01989 void findConstantValues(Statement* s, std::list<int>& dests) {
01990     if (s == NULL) return;
01991     if (s->isPhi()) {
01992         // For each definition, recurse
01993         PhiAssign::Definitions::iterator it;
01994         for (it = ((PhiAssign*)s)->begin(); it != ((PhiAssign*)s)->end(); it++)
01995             findConstantValues(it->def, dests);
01996     }
01997     else if (s->isAssign()) {
01998         Exp* rhs = ((Assign*)s)->getRight();
01999         if (rhs->isIntConst())
02000             dests.push_back(((Const*)rhs)->getInt());
02001     }
02002 }
02003 
02004 // Find any BBs of type COMPJUMP or COMPCALL. If found, analyse, and if possible decode extra code and return true
02005 bool BasicBlock::decodeIndirectJmp(UserProc* proc) {
02006 #define CHECK_REAL_PHI_LOOPS 0
02007 #if CHECK_REAL_PHI_LOOPS
02008     rtlit rit; StatementList::iterator sit;
02009     Statement* s = getFirstStmt(rit, sit);
02010     for (s=getFirstStmt(rit, sit); s; s = getNextStmt(rit, sit)) {
02011         if (!s->isPhi()) continue;
02012         Statement* originalPhi = s;
02013         StatementSet workSet, seenSet;
02014         workSet.insert(s);
02015         seenSet.insert(s);
02016         do {
02017             PhiAssign* pi = (PhiAssign*)*workSet.begin();
02018             workSet.remove(pi);
02019             PhiAssign::Definitions::iterator it;
02020             for (it = pi->begin(); it != pi->end(); it++) {
02021                 if (it->def == NULL) continue;
02022                 if (!it->def->isPhi()) continue;
02023                 if (seenSet.exists(it->def)) {
02024                     std::cerr << "Real phi loop involving statements " << originalPhi->getNumber() << " and " <<
02025                         pi->getNumber() << "\n";
02026                     break;
02027                 } else {
02028                     workSet.insert(it->def);
02029                     seenSet.insert(it->def);
02030                 }
02031             }
02032         } while (workSet.size());
02033     }
02034 #endif
02035 
02036     if (m_nodeType == COMPJUMP) {
02037         assert(m_pRtls->size());
02038         RTL* lastRtl = m_pRtls->back();
02039         if (DEBUG_SWITCH)
02040             LOG << "decodeIndirectJmp: " << lastRtl->prints();
02041         assert(lastRtl->getNumStmt() >= 1);
02042         CaseStatement* lastStmt = (CaseStatement*)lastRtl->elementAt(lastRtl->getNumStmt()-1);
02043         // Note: some programs might not have the case expression propagated to, because of the -l switch (?)
02044         // We used to use ordinary propagation here to get the memory expression, but now it refuses to propagate memofs
02045         // because of the alias safety issue. Eventually, we should use an alias-safe incremental propagation, but for
02046         // now we'll assume no alias problems and force the propagation
02047         bool convert;
02048         lastStmt->propagateTo(convert, NULL, NULL, true /* force */);
02049         Exp* e = lastStmt->getDest();
02050         int n = sizeof(hlForms) / sizeof(Exp*);
02051         char form = 0;
02052         for (int i=0; i < n; i++) {
02053             if (*e *= *hlForms[i]) {        // *= compare ignores subscripts
02054                 form = chForms[i];
02055                 if (DEBUG_SWITCH)
02056                     LOG << "indirect jump matches form " << form << "\n";
02057                 break;
02058             }
02059         }
02060         if (form) {
02061             SWITCH_INFO* swi = new SWITCH_INFO;
02062             swi->chForm = form;
02063             ADDRESS T;
02064             Exp* expr;
02065             findSwParams(form, e, expr, T);
02066             if (expr) {
02067                 swi->uTable = T;
02068                 swi->iNumTable = findNumCases();
02069 #if 1 // TMN: Added actual control of the array members, to possibly truncate what findNumCases()
02070     // thinks is the number of cases, when finding the first array element not pointing to code.
02071                 if (form == 'A') {
02072                     Prog* prog = proc->getProg();
02073                     for (int iPtr = 0; iPtr < swi->iNumTable; ++iPtr) {
02074                         ADDRESS uSwitch = prog->readNative4(swi->uTable + iPtr*4);
02075                         if (uSwitch >= prog->getLimitTextHigh() ||
02076                             uSwitch <  prog->getLimitTextLow())
02077                         {
02078                             if (DEBUG_SWITCH)
02079                                 LOG << "Truncating type A indirect jump array to " << iPtr << " entries "
02080                                        "due to finding an array entry pointing outside valid code\n";
02081                             // Found an array that isn't a pointer-to-code. Assume array has ended.
02082                             swi->iNumTable = iPtr;
02083                             break;
02084                         }
02085                     }
02086                 }
02087                 assert(swi->iNumTable > 0);
02088 #endif
02089                 swi->iUpper = swi->iNumTable-1;
02090                 if (expr->getOper() == opMinus && ((Binary*)expr)->getSubExp2()->isIntConst()) {
02091                     swi->iLower = ((Const*)((Binary*)expr)->getSubExp2())->getInt();
02092                     swi->iUpper += swi->iLower;
02093                     expr = ((Binary*)expr)->getSubExp1();
02094                 } else
02095                     swi->iLower = 0;
02096                 swi->pSwitchVar = expr;
02097                 lastStmt->setDest((Exp*)NULL);
02098                 lastStmt->setSwitchInfo(swi);
02099                 return swi->iNumTable != 0;
02100             }
02101         } else {
02102             // Did not match a switch pattern. Perhaps it is a Fortran style goto with constants at the leaves of the
02103             // phi tree. Basically, a location with a reference, e.g. m[r28{-} - 16]{87}
02104             if (e->isSubscript()) {
02105                 Exp* sub = ((RefExp*)e)->getSubExp1();
02106                 if (sub->isLocation()) {
02107                     // Yes, we have <location>{ref}. Follow the tree and store the constant values that <location>
02108                     // could be assigned to in dests
02109                     std::list<int> dests;
02110                     findConstantValues(((RefExp*)e)->getDef(), dests);
02111                     // The switch info wants an array of native addresses
02112                     int n = dests.size();
02113                     if (n) {
02114                         int* destArray = new int[n];
02115                         std::list<int>::iterator ii = dests.begin();
02116                         for (int i=0; i < n; i++)
02117                             destArray[i] = *ii++;
02118                         SWITCH_INFO* swi = new SWITCH_INFO;
02119                         swi->chForm = 'F';                  // The "Fortran" form
02120                         swi->pSwitchVar = e;
02121                         swi->uTable = (ADDRESS)destArray;   // Abuse the uTable member as a pointer
02122                         swi->iNumTable = n;
02123                         swi->iLower = 1;                    // Not used, except to compute
02124                         swi->iUpper = n;                    // the number of options
02125                         lastStmt->setDest((Exp*)NULL);
02126                         lastStmt->setSwitchInfo(swi);
02127                         return true;
02128                     }
02129                 }
02130             }
02131         }
02132         return false;
02133     } else if (m_nodeType == COMPCALL) {
02134         assert(m_pRtls->size());
02135         RTL* lastRtl = m_pRtls->back();
02136         if (DEBUG_SWITCH)
02137             LOG << "decodeIndirectJmp: COMPCALL:\n" << lastRtl->prints() << "\n";
02138         assert(lastRtl->getNumStmt() >= 1);
02139         CallStatement* lastStmt = (CallStatement*)lastRtl->elementAt(lastRtl->getNumStmt()-1);
02140         Exp* e = lastStmt->getDest();
02141         // Indirect calls may sometimes not be propagated to, because of limited propagation (-l switch).
02142         // Propagate to e, but only keep the changes if the expression matches (don't want excessive propagation to
02143         // a genuine function pointer expression, even though it's hard to imagine).
02144         e = e->propagateAll();
02145         // We also want to replace any m[K]{-} with the actual constant from the (presumably) read-only data section
02146         ConstGlobalConverter cgc(proc->getProg());
02147         e = e->accept(&cgc);
02148         // Simplify the result, e.g. for m[m[(r24{16} + m[0x8048d74]{-}) + 12]{-}]{-} get
02149         // m[m[(r24{16} + 20) + 12]{-}]{-}, want m[m[r24{16} + 32]{-}]{-}. Note also that making the
02150         // ConstGlobalConverter a simplifying expression modifier won't work in this case, since the simplifying
02151         // converter will only simplify the direct parent of the changed expression (which is r24{16} + 20).
02152         e = e->simplify();
02153         if (DEBUG_SWITCH)
02154             LOG << "decodeIndirect: propagated and const global converted call expression is " << e << "\n";
02155 
02156         int n = sizeof(hlVfc) / sizeof(Exp*);
02157         bool recognised = false;
02158         int i;
02159         for (i=0; i < n; i++) {
02160             if (*e *= *hlVfc[i]) {          // *= compare ignores subscripts
02161                 recognised = true;
02162                 if (DEBUG_SWITCH)
02163                     LOG << "indirect call matches form " << i << "\n";
02164                 break;
02165             }
02166         }
02167         if (!recognised) return false;
02168         lastStmt->setDest(e);               // Keep the changes to the indirect call expression
02169         int K1, K2;
02170         Exp *vtExp, *t1;
02171         Prog* prog = proc->getProg();
02172         switch (i) {
02173             case 0: {
02174                 // This is basically an indirection on a global function pointer.  If it is initialised, we have a
02175                 // decodable entry point.  Note: it could also be a library function (e.g. Windows)
02176                 // Pattern 0: global<name>{0}[0]{0}
02177                 K2 = 0;
02178                 if (e->isSubscript()) e = e->getSubExp1();
02179                 e = ((Binary*)e)->getSubExp1();             // e is global<name>{0}[0]
02180                 if (e->isArrayIndex() &&
02181                         (t1 = ((Binary*)e)->getSubExp2(), t1->isIntConst()) &&
02182                         ((Const*)t1)->getInt() == 0)
02183                     e = ((Binary*)e)->getSubExp1();             // e is global<name>{0}
02184                 if (e->isSubscript()) e = e->getSubExp1();  // e is global<name>
02185                 Const* con = (Const*)((Location*)e)->getSubExp1(); // e is <name>
02186                 Global* glo = prog->getGlobal(con->getStr());
02187                 assert(glo);
02188                 // Set the type to pointer to function, if not already
02189                 Type* ty = glo->getType();
02190                 if (!ty->isPointer() && !((PointerType*)ty)->getPointsTo()->isFunc())
02191                     glo->setType(new PointerType(new FuncType()));
02192                 ADDRESS addr = glo->getAddress();
02193                 // FIXME: not sure how to find K1 from here. I think we need to find the earliest(?) entry in the data
02194                 // map that overlaps with addr
02195                 // For now, let K1 = 0:
02196                 K1 = 0;
02197                 vtExp = new Const(addr);
02198                 break;
02199             }
02200             case 1: {
02201                 // Example pattern: e = m[m[r27{25} + 8]{-} + 8]{-}
02202                 if (e->isSubscript())
02203                     e = ((RefExp*)e)->getSubExp1();
02204                 e = ((Location*)e)->getSubExp1();       // e = m[r27{25} + 8]{-} + 8
02205                 Exp* rhs = ((Binary*)e)->getSubExp2();  // rhs = 8
02206                 K2 = ((Const*)rhs)->getInt();
02207                 Exp* lhs = ((Binary*)e)->getSubExp1();  // lhs = m[r27{25} + 8]{-}
02208                 if (lhs->isSubscript())
02209                     lhs = ((RefExp*)lhs)->getSubExp1(); // lhs = m[r27{25} + 8]
02210                 vtExp = lhs;
02211                 lhs = ((Unary*)lhs)->getSubExp1();      // lhs =   r27{25} + 8
02212                 //Exp* object = ((Binary*)lhs)->getSubExp1();
02213                 Exp* CK1 = ((Binary*)lhs)->getSubExp2();
02214                 K1 = ((Const*)CK1)->getInt();
02215                 break;
02216             }
02217             case 2: {
02218                 // Example pattern: e = m[m[r27{25}]{-} + 8]{-}
02219                 if (e->isSubscript())
02220                     e = ((RefExp*)e)->getSubExp1();
02221                 e = ((Location*)e)->getSubExp1();       // e = m[r27{25}]{-} + 8
02222                 Exp* rhs = ((Binary*)e)->getSubExp2();  // rhs = 8
02223                 K2 = ((Const*)rhs)->getInt();
02224                 Exp* lhs = ((Binary*)e)->getSubExp1();  // lhs = m[r27{25}]{-}
02225                 if (lhs->isSubscript())
02226                     lhs = ((RefExp*)lhs)->getSubExp1(); // lhs = m[r27{25}]
02227                 vtExp = lhs;
02228                 K1 = 0;
02229                 break;
02230             }
02231             case 3: {
02232                 // Example pattern: e = m[m[r27{25} + 8]{-}]{-}
02233                 if (e->isSubscript())
02234                     e = ((RefExp*)e)->getSubExp1();
02235                 e = ((Location*)e)->getSubExp1();       // e = m[r27{25} + 8]{-}
02236                 K2 = 0;
02237                 if (e->isSubscript())
02238                     e = ((RefExp*)e)->getSubExp1();     // e = m[r27{25} + 8]
02239                 vtExp = e;
02240                 Exp* lhs = ((Unary*)e)->getSubExp1();       // lhs =   r27{25} + 8
02241                 // Exp* object = ((Binary*)lhs)->getSubExp1();
02242                 Exp* CK1 = ((Binary*)lhs)->getSubExp2();
02243                 K1 = ((Const*)CK1)->getInt();
02244                 break;
02245             }
02246             case 4: {
02247                 // Example pattern: e = m[m[r27{25}]{-}]{-}
02248                 if (e->isSubscript())
02249                     e = ((RefExp*)e)->getSubExp1();
02250                 e = ((Location*)e)->getSubExp1();       // e = m[r27{25}]{-}
02251                 K2 = 0;
02252                 if (e->isSubscript())
02253                     e = ((RefExp*)e)->getSubExp1();     // e = m[r27{25}]
02254                 vtExp = e;
02255                 K1 = 0;
02256                 // Exp* object = ((Unary*)e)->getSubExp1();
02257                 break;
02258             }
02259             default:
02260                 K1 = K2 = -1;           // Suppress warnings
02261                 vtExp = (Exp*)-1;
02262         }
02263         if (DEBUG_SWITCH)
02264             LOG << "form " << i << ": from statement " << lastStmt->getNumber() << " get e = " << lastStmt->getDest() <<
02265                 ", K1 = " << K1 << ", K2 = " << K2 << ", vtExp = " << vtExp << "\n";
02266         // The vt expression might not be a constant yet, because of expressions not fully propagated, or because of
02267         // m[K] in the expression (fixed with the ConstGlobalConverter).  If so, look it up in the defCollector in the
02268         // call
02269         vtExp = lastStmt->findDefFor(vtExp);
02270         if (vtExp && DEBUG_SWITCH)
02271             LOG << "VT expression boils down to this: " << vtExp << "\n";
02272 
02273         // Danger. For now, only do if -ic given
02274         bool decodeThru = Boomerang::get()->decodeThruIndCall;
02275         if (decodeThru && vtExp && vtExp->isIntConst()) {
02276             int addr = ((Const*)vtExp)->getInt();
02277             ADDRESS pfunc = prog->readNative4(addr);
02278             if (prog->findProc(pfunc) == NULL) {
02279                 // A new, undecoded procedure
02280                 if (Boomerang::get()->noDecodeChildren)
02281                     return false;
02282                 prog->decodeEntryPoint(pfunc);
02283                 // Since this was not decoded, this is a significant change, and we want to redecode the current
02284                 // function now that the callee has been decoded
02285                 return true;
02286             }
02287         }
02288     }
02289     return false;
02290 }
02291 
02292 /*==============================================================================
02293  * FUNCTION:    processSwitch
02294  * OVERVIEW:    Called when a switch has been identified. Visits the destinations of the switch, adds out edges to the
02295  *              BB, etc
02296  * NOTE:        Used to be called as soon as a switch statement is discovered, but this causes decoded but unanalysed
02297  *              BBs (statements not numbered, locations not SSA renamed etc) to appear in the CFG. This caused problems
02298  *              when there were nested switch statements. Now only called when re-decoding a switch statement
02299  * PARAMETERS:  proc - Pointer to the UserProc object for this code
02300  * RETURNS:     <nothing>
02301  *============================================================================*/
02302 void BasicBlock::processSwitch(UserProc* proc) {
02303 
02304     RTL* last = m_pRtls->back();
02305     CaseStatement* lastStmt = (CaseStatement*)last->getHlStmt();
02306     SWITCH_INFO* si = lastStmt->getSwitchInfo();
02307 
02308     if (Boomerang::get()->debugSwitch) {
02309         LOG << "processing switch statement type " << si->chForm << " with table at 0x" << si->uTable << ", ";
02310         if (si->iNumTable)
02311             LOG << si->iNumTable << " entries, ";
02312         LOG << "lo= " << si->iLower << ", hi= " << si->iUpper << "\n";
02313     }
02314     ADDRESS uSwitch;
02315     int iNumOut, iNum;
02316     iNumOut = si->iUpper-si->iLower+1;
02317     iNum = iNumOut;
02318     // Emit an NWAY BB instead of the COMPJUMP. Also update the number of out edges.
02319     updateType(NWAY, iNumOut);
02320     
02321     Prog* prog = proc->getProg();
02322     Cfg* cfg = proc->getCFG();
02323     // Where there are repeated switch cases, we have repeated out-edges from the BB. Example:
02324     // switch (x) {
02325     //   case 3: case 5:
02326     //      do something;
02327     //      break;
02328     //   case 4: case 10:
02329     //      do something else
02330     // ... }
02331     // The switch statement is emitted assuming one out-edge for each switch value, which is assumed to be iLower+i
02332     // for the ith zero-based case. It may be that the code for case 5 above will be a goto to the code for case 3,
02333     // but a smarter back end could group them
02334     std::list<ADDRESS> dests;
02335     for (int i=0; i < iNum; i++) {
02336         // Get the destination address from the switch table.
02337         if (si->chForm == 'H') {
02338             int iValue = prog->readNative4(si->uTable + i*2);
02339             if (iValue == -1) continue;
02340             uSwitch =prog->readNative4(si->uTable + i*8 + 4);
02341         }
02342         else if (si->chForm == 'F')
02343             uSwitch = ((int*)si->uTable)[i];
02344         else
02345             uSwitch = prog->readNative4(si->uTable + i*4);
02346         if ((si->chForm == 'O') || (si->chForm == 'R') || (si->chForm == 'r'))
02347             // Offset: add table address to make a real pointer to code.  For type R, the table is relative to the
02348             // branch, so take iOffset. For others, iOffset is 0, so no harm
02349             uSwitch += si->uTable - si->iOffset;
02350         if (uSwitch < prog->getLimitTextHigh()) {
02351             //tq.visit(cfg, uSwitch, this);
02352             cfg->addOutEdge(this, uSwitch, true);
02353             // Remember to decode the newly discovered switch code arms, if necessary
02354             // Don't do it right now, in case there are recursive switch statements (e.g. app7win.exe from
02355             // hackthissite.org)
02356             dests.push_back(uSwitch);
02357         } else {
02358             LOG << "switch table entry branches to past end of text section " << uSwitch << "\n";
02359 #if 1       // TMN: If we reached an array entry pointing outside the program text, we can be quite confident the array
02360             // has ended. Don't try to pull any more data from it.
02361             LOG << "Assuming the end of the pointer-array has been reached at index " << i << "\n";
02362             // TODO: Elevate this logic to the code calculating iNumTable, but still leave this code as a safeguard.
02363             // Q: Should iNumOut and m_iNumOutEdges really be adjusted (iNum - i) ?
02364 //          assert(iNumOut        >= (iNum - i));
02365             assert(m_iNumOutEdges >= (iNum - i));
02366 //          iNumOut        -= (iNum - i);
02367             m_iNumOutEdges -= (iNum - i);
02368             break;
02369 #else
02370             iNumOut--;
02371             m_iNumOutEdges--;       // FIXME: where is this set?
02372 #endif
02373         }
02374     }
02375     // Decode the newly discovered switch code arms, if any, and if not already decoded
02376     std::list<ADDRESS>::iterator dd;
02377     int count = 0;
02378     for (dd = dests.begin(); dd != dests.end(); ++dd) {
02379         char tmp[1024];
02380         count++;
02381         sprintf(tmp, "before decoding fragment %i of %i (%x)", count, dests.size(), *dd);
02382         Boomerang::get()->alert_decompile_debug_point(proc, tmp);
02383         prog->decodeFragment(proc, *dd);
02384     }
02385 }
02386 
02387 // Change the BB enclosing stmt from type COMPCALL to CALL
02388 bool BasicBlock::undoComputedBB(Statement* stmt) {
02389     RTL* last = m_pRtls->back();
02390     std::list<Statement*>& list = last->getList();
02391     std::list<Statement*>::reverse_iterator rr;
02392     for (rr = list.rbegin(); rr != list.rend(); rr++) {
02393         if (*rr == stmt) {
02394             m_nodeType = CALL;
02395             LOG << "undoComputedBB for statement " << stmt << "\n";
02396             return true;
02397         }
02398     }
02399     return false;
02400 }
02401 

Generated on Tue Sep 19 21:18:14 2006 for Boomerang by  doxygen 1.4.6