sslinst.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1997, Shane Sendall
00003  * Copyright (C) 1998-1999, David Ung
00004  * Copyright (C) 1998-2001, The University of Queensland
00005  * Copyright (C) 2001, Sun Microsystems, Inc
00006  * Copyright (C) 2002, Trent Waddington
00007  *
00008  * See the file "LICENSE.TERMS" for information on usage and
00009  * redistribution of this file, and for a DISCLAIMER OF ALL
00010  * WARRANTIES.
00011  *
00012  */
00013 
00014 /*==============================================================================
00015  * FILE:       sslinst.cc
00016  * OVERVIEW:   This file defines the classes used to represent the semantic
00017  *             definitions of instructions and given in a .ssl file.
00018  *============================================================================*/
00019  
00020 /*
00021  * $Revision: 1.28 $    // 1.27.2.2
00022  *
00023  * 27 Apr 02 - Mike: Mods for boomerang
00024  * 17 Jul 02 - Mike: readSSLFile resets internal state as well
00025  * 04 Feb 03 - Mike: Fixed a bug with instantiating NOP (could cause bus error?)
00026  * 22 May 03 - Mike: Fixed a small memory leak (char* opcode)
00027  * 16 Jul 04 - Mike: Simplify decoded semantics
00028  */
00029 
00030 /*==============================================================================
00031  * Dependencies.
00032  *============================================================================*/
00033 
00034 #include <assert.h>
00035 #if defined(_MSC_VER) && _MSC_VER <= 1200
00036 #pragma warning(disable:4786)
00037 #endif 
00038 
00039 #include <algorithm>    // For remove()
00040 #include "types.h"
00041 #include "statement.h"
00042 #include "exp.h"
00043 #include "register.h"
00044 #include "type.h"
00045 #include "rtl.h"
00046 #include "cfg.h"
00047 #include "proc.h"
00048 #include "prog.h"
00049 #include "sslparser.h"
00050 #include "boomerang.h"
00051 // For some reason, MSVC 5.00 complains about use of undefined types a lot
00052 #if defined(_MSC_VER) && _MSC_VER <= 1100
00053 #include "signature.h"      // For MSVC 5.00
00054 #endif
00055 
00056 
00057 //#define DEBUG_SSLPARSER 1
00058 
00059 /*==============================================================================
00060  * FUNCTION:        TableEntry::TableEntry
00061  * OVERVIEW:        Constructor
00062  * PARAMETERS:      <none>
00063  * RETURNS:         <nothing>
00064  *============================================================================*/
00065 TableEntry::TableEntry() { flags = 0; }
00066 
00067 /*==============================================================================
00068  * FUNCTION:        TableEntry::TableEntry
00069  * OVERVIEW:        Constructor
00070  * PARAMETERS:      p -
00071  *                  r - reference to a RTL
00072  * RETURNS:         <nothing>
00073  *============================================================================*/
00074 TableEntry::TableEntry(std::list<std::string>& p, RTL& r) : rtl(r)
00075 { 
00076     for (std::list<std::string>::iterator it = p.begin(); it != p.end(); it++)
00077         params.push_back(*it);
00078     flags = 0; 
00079 }
00080 
00081 /*==============================================================================
00082  * FUNCTION:        TableEntry::setParam
00083  * OVERVIEW:        Set the parameter list.
00084  * PARAMETERS:      p - a list of strings
00085  * RETURNS:         <nothing>
00086  *============================================================================*/
00087 void TableEntry::setParam(std::list<std::string>& p) { params = p; }
00088 
00089 /*==============================================================================
00090  * FUNCTION:        TableEntry::setRTL
00091  * OVERVIEW:        Set the RTL.
00092  * PARAMETERS:      r - a RTL
00093  * RETURNS:         <nothing>
00094  *============================================================================*/
00095 void TableEntry::setRTL(RTL& r) {
00096     rtl = r;
00097 }
00098 
00099 /*==============================================================================
00100  * FUNCTION:        TableEntry::operator=
00101  * OVERVIEW:        Sets the contents of this object with a deepcopy from another TableEntry object.  Note that this is
00102  *                  different from the semantics of operator= for an RTL which only does a shallow copy!
00103  * PARAMETERS:      other - the object to copy
00104  * RETURNS:         a reference to this object
00105  *============================================================================*/
00106 const TableEntry& TableEntry::operator=(const TableEntry& other) {
00107     for (std::list<std::string>::const_iterator it = other.params.begin(); it != other.params.end(); it++)
00108         params.push_back(*it);
00109     rtl = *(new RTL(other.rtl));
00110     return *this;
00111 }
00112 
00113 /*==============================================================================
00114  * FUNCTION:        TableEntry::appendRTL
00115  * OVERVIEW:        Appends an RTL to an exising TableEntry
00116  * PARAMETERS:      p: reference to list of formal parameters (as strings)
00117  *                  r: reference to RTL with list of Exps to append
00118  * RETURNS:         0 for success
00119  *============================================================================*/
00120 int TableEntry::appendRTL(std::list<std::string>& p, RTL& r) {
00121     bool match = (p.size() == params.size());
00122     std::list<std::string>::iterator a, b;
00123     for (a = params.begin(), b = p.begin(); match && (a != params.end()) && (b != p.end());
00124             match = (*a == *b), a++, b++)
00125         ;
00126     if (match) {
00127         rtl.appendRTL(r);
00128         return 0;
00129     }
00130     return -1;
00131 }
00132 
00133 /*==============================================================================
00134  * FUNCTION:        RTLInstDict::appendToDict
00135  * OVERVIEW:        Appends one RTL to the dictionary
00136  * PARAMETERS:      n: name of the instruction to add to
00137  *                  p: list of formal parameters (as strings) for the RTL to add
00138  *                  r: reference to the RTL to add
00139  * RETURNS:         0 for success
00140  *============================================================================*/
00141 int RTLInstDict::appendToDict(std::string &n, std::list<std::string>& p, RTL& r)
00142 {
00143     char *opcode = new char[n.size() + 1];
00144     strcpy(opcode, n.c_str());
00145     upperStr(opcode, opcode);
00146     std::remove(opcode, opcode+strlen(opcode)+1,'.');
00147     std::string s(opcode);
00148     //delete [] opcode;
00149    
00150     if (idict.find(s) == idict.end()) {
00151         idict[s] = TableEntry(p, r);
00152     } else {
00153         return idict[s].appendRTL(p, r);
00154     }
00155     return 0;
00156 }
00157 
00158 RTLInstDict::RTLInstDict()
00159 {
00160 }
00161 
00162 RTLInstDict::~RTLInstDict()
00163 {
00164 }
00165 
00166 /*==============================================================================
00167  * FUNCTION:        RTLInstDict::readSSLFile
00168  * OVERVIEW:        Read and parse the SSL file, and initialise the expanded instruction dictionary (this object).
00169  *                  This also reads and sets up the register map and flag functions.
00170  * PARAMETERS:      SSLFileName - the name of the file containing the SSL specification.
00171  * RETURNS:         the file was successfully read
00172  *============================================================================*/
00173 bool RTLInstDict::readSSLFile(const std::string& SSLFileName)
00174 {
00175     // emptying the rtl dictionary
00176     idict.erase(idict.begin(),idict.end());
00177     // Clear all state
00178     reset();
00179     
00180     // Attempt to Parse the SSL file
00181     SSLParser theParser(SSLFileName,
00182 #ifdef DEBUG_SSLPARSER
00183     true
00184 #else
00185     false
00186 #endif
00187 );
00188     if (theParser.theScanner == NULL)
00189         return false;
00190     addRegister( "%CTI", -1, 1, false );
00191     addRegister( "%NEXT", -1, 32, false );
00192     
00193     theParser.yyparse(*this);
00194 
00195     fixupParams();
00196 
00197     if (Boomerang::get()->debugDecoder) {
00198         std::cout << "\n=======Expanded RTL template dictionary=======\n";
00199         print();
00200         std::cout << "\n==============================================\n\n";
00201     }
00202     
00203     return true;
00204 }
00205 
00206 /*==============================================================================
00207  * FUNCTION:        RTLInstDict::addRegister
00208  * OVERVIEW:        Add a new register definition to the dictionary
00209  * PARAMETERS:      
00210  * RETURNS:         <nothing>
00211  *============================================================================*/
00212 void RTLInstDict::addRegister( const char *name, int id, int size, bool flt )
00213 {
00214     RegMap[name] = id;
00215     if( id == -1 ) {
00216         SpecialRegMap[name].s_name(name);
00217         SpecialRegMap[name].s_size(size);
00218         SpecialRegMap[name].s_float(flt);
00219         SpecialRegMap[name].s_address(NULL);
00220         SpecialRegMap[name].s_mappedIndex(-1);
00221         SpecialRegMap[name].s_mappedOffset(-1);
00222     } else {
00223         DetRegMap[id].s_name(name);
00224         DetRegMap[id].s_size(size);
00225         DetRegMap[id].s_float(flt);
00226         DetRegMap[id].s_address(NULL);
00227         DetRegMap[id].s_mappedIndex(-1);
00228         DetRegMap[id].s_mappedOffset(-1);
00229     }    
00230 }
00231 
00232 
00233 /*==============================================================================
00234  * FUNCTION:        RTLInstDict::print
00235  * OVERVIEW:        Print a textual representation of the dictionary.
00236  * PARAMETERS:      std::cout - stream used for printing
00237  * RETURNS:         <nothing>
00238  *============================================================================*/
00239 void RTLInstDict::print(std::ostream& os /*= std::cout*/)
00240 {
00241     for (std::map<std::string, TableEntry>::iterator p = idict.begin();
00242       p != idict.end(); p++) {
00243         // print the instruction name
00244         os << (*p).first << "  ";
00245 
00246         // print the parameters
00247         std::list<std::string>& params = (*p).second.params;
00248         int i = params.size();
00249         for (std::list<std::string>::iterator s = params.begin(); s != params.end(); s++,i--)
00250             os << *s << (i != 1 ? "," : "");
00251         os << "\n";
00252     
00253         // print the RTL
00254         RTL& rtlist = (*p).second.rtl;
00255         rtlist.print(os);
00256         os << "\n";
00257     }
00258 
00259 #if 0
00260     // Detailed register map
00261     os << "\nDetailed register map\n";
00262     std::map<int, Register, std::less<int> >::iterator rr;
00263     for (rr = DetRegMap.begin(); rr != DetRegMap.end(); rr++) {
00264         int n = rr->first;
00265         Register* pr = &rr->second;
00266         os << "number " << n <<
00267           " name " << pr->g_name() <<
00268           " size " << std::dec << pr->g_size() <<
00269           " address 0x" << std::hex << (unsigned)pr->g_address() <<
00270           " mappedIndex " << std::dec << pr->g_mappedIndex() <<
00271           " mappedOffset " << pr->g_mappedOffset() <<
00272           " flt " << pr->isFloat() << "\n";
00273     }
00274 #endif
00275 }
00276 
00277 /*==============================================================================
00278  * FUNCTION:         RTLInstDict::fixupParams
00279  * OVERVIEW:         Runs after the ssl file is parsed to fix up variant params
00280  *                   where the arms are lambdas.
00281  * PARAMETERS:       None
00282  * RETURNS:          Nothing
00283  *============================================================================*/
00284 void RTLInstDict::fixupParams( )
00285 {
00286     std::map<std::string,ParamEntry>::iterator param;
00287     int mark = 1;
00288     for( param = DetParamMap.begin(); param != DetParamMap.end(); param++ ) {
00289         param->second.mark = 0;
00290     }
00291     for( param = DetParamMap.begin(); param != DetParamMap.end(); param++ ) {
00292         std::list<std::string> funcParams;
00293         bool haveCount = false;
00294         if( param->second.kind == PARAM_VARIANT ) {
00295             fixupParamsSub( param->first, funcParams, haveCount, mark++ );
00296         }
00297     }
00298 }
00299 
00300 void RTLInstDict::fixupParamsSub( std::string s, std::list<std::string>& funcParams, bool& haveCount, int mark )
00301 {
00302     ParamEntry &param = DetParamMap[s];
00303 
00304     if( param.params.size() == 0 ) {
00305         std::cerr << "Error in SSL File: Variant operand " << s << " has no branches. Well that's really useful...\n";
00306         return;
00307     }
00308     if( param.mark == mark )
00309         return; /* Already seen this round. May indicate a cycle, but may not */
00310     
00311     param.mark = mark;
00312     
00313     for( std::list<std::string>::iterator it = param.params.begin();
00314          it != param.params.end(); it++ ) {
00315         ParamEntry &sub = DetParamMap[*it];
00316         if (sub.kind == PARAM_VARIANT ) {
00317             fixupParamsSub(*it, funcParams, haveCount, mark );
00318             if (!haveCount) { /* Empty branch? */
00319                 continue;
00320             }
00321         } else if (!haveCount ) {
00322             haveCount = true;
00323             char buf[10];
00324             for (unsigned i=1; i <= sub.funcParams.size(); i++ ) {
00325                 sprintf( buf, "__lp%d", i );
00326                 funcParams.push_back(buf);
00327             }
00328         }
00329 
00330         if (funcParams.size() != sub.funcParams.size() ) {
00331             std::cerr << "Error in SSL File: Variant operand " << s << " does not have a fixed number of functional "
00332                 "parameters:\n" << "Expected " << funcParams.size() << ", but branch " << *it << " has " <<
00333                 sub.funcParams.size() << ".\n";
00334         } else if (funcParams != sub.funcParams && sub.asgn != NULL ) {
00335             /* Rename so all the parameter names match */
00336             std::list<std::string>::iterator i,j;
00337             for( i = funcParams.begin(), j = sub.funcParams.begin(); i != funcParams.end(); i++, j++ ) {
00338                 Exp* match = Location::param(j->c_str());
00339                 Exp* replace = Location::param(i->c_str());
00340                 sub.asgn->searchAndReplace( match, replace );
00341             }
00342             sub.funcParams = funcParams;
00343         }
00344     }
00345 
00346 //    if( param.funcParams.size() != funcParams.size() )
00347 //        theSemTable.setItem( n, cFUNCTION, 0, 0, funcParams.size(),
00348 //                             theSemTable[n].sName.c_str() );
00349     param.funcParams = funcParams;
00350 }
00351 
00352 /*==============================================================================
00353  * FUNCTION:         RTLInstDict::getNumOperands
00354  * OVERVIEW:         Returns the signature of the given instruction.
00355  * PARAMETERS:       name -
00356  * RETURNS:          the signature (name + number of operands)
00357  *============================================================================*/
00358 std::pair<std::string,unsigned> RTLInstDict::getSignature(const char* name) {
00359     // Take the argument, convert it to upper case and remove any _'s and .'s
00360     char *opcode = new char[strlen(name) + 1];
00361     upperStr(name, opcode);
00362 //  std::remove(opcode,opcode+strlen(opcode)+1,'_');
00363     std::remove(opcode,opcode+strlen(opcode)+1,'.');
00364 
00365     // Look up the dictionary
00366     std::map<std::string,TableEntry>::iterator it = idict.find(opcode);
00367     if (it == idict.end()) {
00368         std::cerr << "Error: no entry for `" << name << "' in RTL dictionary\n";
00369         it = idict.find("NOP");     // At least, don't cause segfault
00370     } 
00371 
00372     std::pair<std::string, unsigned> ret;
00373     ret = std::pair<std::string,unsigned>(opcode,(it->second).params.size());
00374     //delete [] opcode;
00375     return ret;
00376 }
00377 
00378 /*==============================================================================
00379  * FUNCTION:         RTLInstDict::partialType
00380  * OVERVIEW:         Scan the Exp* pointed to by exp; if its top level operator indicates even a partial type, then set
00381  *                      the expression's type, and return true
00382  * NOTE:             This version only inspects one expression
00383  * PARAMETERS:       exp - points to a Exp* to be scanned
00384  *                   ty - ref to a Type object to put the partial type into
00385  * RETURNS:          True if a partial type is found
00386  *============================================================================*/
00387 bool RTLInstDict::partialType(Exp* exp, Type& ty)
00388 {
00389     if (exp->isSizeCast()) {
00390         ty = IntegerType(((Const*)((Binary*)exp)->getSubExp1())->getInt());
00391         return true;
00392     }
00393     if (exp->isFltConst()) {
00394         ty = FloatType(64);
00395         return true;
00396     }
00397     return false;
00398 }
00399 
00400 /*==============================================================================
00401  * FUNCTION:         RTLInstDict::instantiateRTL
00402  * OVERVIEW:         Returns an instance of a register transfer list for the instruction named 'name' with the actuals
00403  *                   given as the second parameter.
00404  * PARAMETERS:       name - the name of the instruction (must correspond to one defined in the SSL file).
00405  *                   actuals - the actual values
00406  * RETURNS:          the instantiated list of Exps
00407  *============================================================================*/
00408 std::list<Statement*>* RTLInstDict::instantiateRTL(std::string& name, ADDRESS natPC, std::vector<Exp*>& actuals) {
00409     // If -f is in force, use the fast (but not as precise) name instead
00410     const std::string* lname = &name;
00411     // FIXME: settings
00412 //    if (progOptions.fastInstr) {
00413 if (0) {
00414         std::map<std::string, std::string>::iterator itf = fastMap.find(name);
00415         if (itf != fastMap.end()) 
00416             lname = &itf->second;
00417     }
00418     // Retrieve the dictionary entry for the named instruction
00419     if ( idict.find(*lname) == idict.end() ) { /* lname is not in dictionary */
00420         std::cerr << "ERROR: unknown instruction " << *lname << " at 0x" << std::hex << natPC << ", ignoring.\n";
00421         return NULL;
00422     }
00423     TableEntry& entry = idict[*lname];
00424 
00425     return instantiateRTL( entry.rtl, natPC, entry.params, actuals );
00426 }
00427 
00428 /*==============================================================================
00429  * FUNCTION:         RTLInstDict::instantiateRTL
00430  * OVERVIEW:         Returns an instance of a register transfer list for the parameterized rtlist with the given formals
00431  *                   replaced with the actuals given as the third parameter.
00432  * PARAMETERS:       rtl - a register transfer list
00433  *                   params - a list of formal parameters
00434  *                   actuals - the actual parameter values
00435  * RETURNS:          the instantiated list of Exps
00436  *============================================================================*/
00437 std::list<Statement*>* RTLInstDict::instantiateRTL(RTL& rtl, ADDRESS natPC, std::list<std::string>& params,
00438         std::vector<Exp*>& actuals) {
00439     assert(params.size() == actuals.size());
00440 
00441     // Get a deep copy of the template RTL
00442     std::list<Statement*>* newList = new std::list<Statement*>();
00443     rtl.deepCopyList(*newList);
00444 
00445     // Iterate through each Statement of the new list of stmts
00446     std::list<Statement*>::iterator ss;
00447     for (ss = newList->begin(); ss != newList->end(); ss++) {
00448         // Search for the formals and replace them with the actuals
00449         std::list<std::string>::iterator param = params.begin();
00450         std::vector<Exp*>::const_iterator actual = actuals.begin();
00451         for (; param != params.end(); param++, actual++) {
00452             /* Simple parameter - just construct the formal to search for */
00453             Exp* formal = Location::param(param->c_str());
00454             (*ss)->searchAndReplace(formal, *actual);
00455             //delete formal;
00456         }
00457         (*ss)->fixSuccessor();
00458         if (Boomerang::get()->debugDecoder)
00459             std::cout << "          " << *ss << "\n";
00460     }
00461 
00462     transformPostVars( newList, true );
00463 
00464     // Perform simplifications, e.g. *1 in Pentium addressing modes
00465     for (ss = newList->begin(); ss != newList->end(); ss++) {
00466         (*ss)->simplify();
00467     }
00468 
00469     return newList;
00470 }
00471 
00472 /* Small struct for transformPostVars */
00473 class transPost {
00474 public:
00475     bool used;      // If the base expression (e.g. r[0]) is used
00476                     // Important because if not, we don't have to make any
00477                     // substitutions at all
00478     bool isNew;     // Not sure (MVE)
00479     Exp* tmp;       // The temp to replace r[0]' with
00480     Exp* post;      // The whole postvar expression. e.g. r[0]'
00481     Exp* base;      // The base expression (e.g. r[0])
00482     Type* type;     // The type of the temporary (needed for the final assign)
00483 };
00484 
00485 /*
00486  * Transform an RTL to eliminate any uses of post-variables. Note that the algorithm used expects to deal with simple
00487  * expressions as post vars, ie r[22], m[r[1]], generally things which aren't parameterized at a higher level. This is
00488  * ok for the translator (we do substitution first anyway), but may miss some optimizations for the emulator.
00489  * For the emulator, if parameters are detected within a postvar, we just force the temporary, which is always safe to
00490  * do.  (The parameter optimise is set to false for the emulator to achieve this).
00491  */
00492 
00493 std::list<Statement*>* RTLInstDict::transformPostVars(std::list<Statement*>* rts, bool optimise) {
00494     std::list<Statement*>::iterator rt;
00495 
00496     // Map from var (could be any expression really) to details
00497     std::map<Exp*,transPost,lessExpStar> vars;
00498     int tmpcount = 1;       // For making temp names unique
00499     // Exp* matchParam(1,idParam);  // ? Was never used anyway
00500 
00501 #ifdef DEBUG_POSTVAR
00502     std::cout << "Transforming from:\n";
00503     for (Exp_CIT p = rts->begin(); p != rts->end(); p++) {
00504         std::cout << setw(8) << " ";
00505         (*p)->print(std::cout);
00506         std::cout << "\n";
00507     }
00508 #endif
00509     
00510     // First pass: Scan for post-variables and usages of their referents
00511     for( rt = rts->begin(); rt != rts->end(); rt++ ) {
00512         // ss appears to be a list of expressions to be searched
00513         // It is either the LHS and RHS of an assignment, or it's the parameters of a flag call
00514         Binary* ss;
00515         if( (*rt)->isAssign()) {
00516             Exp* lhs = ((Assign*)*rt)->getLeft();
00517             Exp* rhs = ((Assign*)*rt)->getRight();
00518 
00519             // Look for assignments to post-variables
00520             if (lhs && lhs->isPostVar()) {
00521                 if( vars.find(lhs) == vars.end() ) {
00522                     // Add a record in the map for this postvar
00523                     transPost& el = vars[lhs];
00524                     el.used = false;
00525                     el.type = ((Assign*)*rt)->getType();
00526                     
00527                     // Constuct a temporary. We should probably be smarter and actually check that it's not otherwise
00528                     // used here.
00529                     std::string tmpname = el.type->getTempName() + (tmpcount++) + "post" ;
00530                     el.tmp = Location::tempOf(new Const((char*)tmpname.c_str()));
00531 
00532                     // Keep a copy of the referrent. For example, if the lhs is r[0]', base is r[0]
00533                     el.base = lhs->getSubExp1();
00534                     el.post = lhs;     // The whole post-var, e.g. r[0]'
00535                     el.isNew = true;
00536 
00537                     // The emulator generator sets optimise false
00538                     // I think this forces always generating the temps (MVE)
00539                     if( !optimise ) {
00540                         el.used = true;
00541                         el.isNew = false;
00542                     }
00543                     
00544                 }
00545             }
00546             // For an assignment, the two expressions to search are the left and right hand sides (could just put the
00547             // whole assignment on, I suppose)
00548             ss = new Binary(opList,
00549                 lhs->clone(),
00550                 new Binary(opList,
00551                     rhs->clone(),
00552                     new Terminal(opNil)));
00553         } else if( (*rt)->isFlagAssgn()) {
00554             // An opFlagCall is assumed to be a Binary with a string and an opList of parameters
00555             ss = (Binary*) ((Binary*)*rt)->getSubExp2();
00556         } else
00557             ss = NULL;
00558 
00559         /* Look for usages of post-variables' referents
00560          * Trickier than you'd think, as we need to make sure to skip over the post-variables themselves. ie match
00561          * r[0] but not r[0]'
00562          * Note: back with SemStrs, we could use a match expression which was a wildcard prepended to the base
00563          * expression; this would match either the base (r[0]) or the post-var (r[0]').
00564          * Can't really use this with Exps, so we search twice; once for the base, and once for the post, and if we
00565          * get more with the former, then we have a use of the base (consider r[0] + r[0]')
00566          */
00567         for (std::map<Exp*,transPost,lessExpStar>::iterator sr = vars.begin();
00568              sr != vars.end(); sr++ ) {
00569             if( sr->second.isNew ) {
00570                 // Make sure we don't match a var in its defining statement
00571                 sr->second.isNew = false;
00572                 continue;
00573             }
00574             Binary* cur;
00575             for (cur = ss; !cur->isNil(); cur = (Binary*)cur->getSubExp2()) {
00576                 if( sr->second.used )
00577                     break;      // Don't bother; already know it's used
00578                 Exp* s = cur->getSubExp1();
00579                 if( !s ) continue;
00580                 if( *s == *sr->second.base ) {
00581                     sr->second.used = true;
00582                     break;
00583                 }
00584                 std::list<Exp*> res1, res2;
00585                 s->searchAll( sr->second.base, res1 );
00586                 s->searchAll( sr->second.post, res2 );
00587                 // Each match of a post will also match the base.
00588                 // But if there is a bare (non-post) use of the base, there will be a result in res1 that is not in res2
00589                 if (res1.size() > res2.size())
00590                     sr->second.used = true;
00591             }
00592         }
00593     }
00594 
00595     // Second pass: Replace post-variables with temporaries where needed
00596     for ( rt = rts->begin(); rt != rts->end(); rt++ ) {
00597         for (std::map<Exp*,transPost,lessExpStar>::iterator sr = vars.begin();
00598           sr != vars.end(); sr++ ) {
00599             if( sr->second.used ) {
00600                 (*rt)->searchAndReplace(sr->first, sr->second.tmp);
00601             } else {
00602                 (*rt)->searchAndReplace(sr->first, sr->second.base);
00603             }
00604         }
00605     }
00606 
00607     // Finally: Append assignments where needed from temps to base vars
00608     // Example: esp' = esp-4; m[esp'] = modrm; FLAG(esp)
00609     // all the esp' are replaced with say tmp1, you need a "esp = tmp1" at the end to actually make the change
00610     for( std::map<Exp*,transPost,lessExpStar>::iterator sr = vars.begin();
00611       sr != vars.end(); sr++ ) {
00612         if( sr->second.used ) {
00613             Assign* te = new Assign(sr->second.type,
00614                     sr->second.base->clone(),
00615                     sr->second.tmp);
00616             rts->push_back( te );
00617         } else {
00618             // The temp is either used (uncloned) in the assignment, or is deleted here
00619             //delete sr->second.tmp;
00620         }
00621     }
00622 
00623 #ifdef DEBUG_POSTVAR
00624     std::cout << "\nTo =>\n";
00625     for (std::list<Exp*>::iterator p = rts->begin(); p != rts->end(); p++) {
00626         std::cout << setw(8) << " ";
00627         (*p)->print(std::cout);
00628         std::cout << "\n";
00629     }
00630     std::cout << "\n";
00631 #endif
00632 
00633     return rts;
00634 }
00635 
00636 // Call from test code if (e.g.) want to call readSSLFile() twice
00637 void RTLInstDict::reset() {
00638     RegMap.clear();
00639     DetRegMap.clear();
00640     SpecialRegMap.clear();
00641     ParamSet.clear();
00642     DetParamMap.clear();
00643     FlagFuncs.clear();
00644     DefMap.clear();
00645     AliasMap.clear();
00646     fastMap.clear();
00647     idict.clear();
00648     fetchExecCycle = 0;
00649 }

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