signature.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002, Trent Waddington
00003  *
00004  * See the file "LICENSE.TERMS" for information on usage and
00005  * redistribution of this file, and for a DISCLAIMER OF ALL
00006  * WARRANTIES.
00007  *
00008  */
00009 
00010 /*==============================================================================
00011  * FILE:       signature.cpp
00012  * OVERVIEW:   Implementation of the classes that describe a procedure signature
00013  *============================================================================*/
00014 
00015 /*
00016  * $Revision: 1.123 $   // 1.98.2.12
00017  * 
00018  * 15 Jul 02 - Trent: Created.
00019  * 18 Jul 02 - Mike: Changed addParameter's last param to deflt to "", not NULL
00020  * 02 Jan 03 - Mike: Fixed SPARC getParamExp and getArgExp
00021  * 09 Nov 04 - Mike: Fixed clone() functions
00022  * 01 Feb 05 - Mike: Parameters default to void type unless ad-hoc TA
00023  */
00024 
00025 #include <assert.h>
00026 #if defined(_MSC_VER) && _MSC_VER <= 1200
00027 #pragma warning(disable:4786)
00028 #endif 
00029 
00030 #include <string>
00031 #include <sstream>
00032 #include "type.h"
00033 #include "signature.h"
00034 #include "exp.h"
00035 #include "prog.h"
00036 #include "BinaryFile.h"
00037 #include "frontend.h"
00038 #include "signature.h"
00039 #include "util.h"
00040 #include "cfg.h"
00041 #include "proc.h"
00042 #include "boomerang.h"
00043 #include "log.h"
00044 #include "managed.h"
00045 
00046 extern char debug_buffer[];             // For prints()
00047 
00048 char* Signature::platformName(platform plat) {
00049     switch (plat) {
00050         case PLAT_PENTIUM:  return "pentium";
00051         case PLAT_SPARC:    return "sparc";
00052         case PLAT_M68K:     return "m68k";
00053         case PLAT_PARISC:   return "parisc";
00054         case PLAT_PPC:      return "ppc";
00055         case PLAT_MIPS:     return "mips";
00056         case PLAT_ST20:     return "st20";
00057         default:            return "???";
00058     }
00059 }
00060 
00061 char* Signature::conventionName(callconv cc) {
00062     switch (cc) {
00063         case CONV_C:        return "stdc";
00064         case CONV_PASCAL:   return "pascal";
00065         case CONV_THISCALL: return "thiscall";
00066         default:            return "??";
00067     }
00068 }
00069 
00070 namespace CallingConvention {
00071 
00072     class Win32Signature : public Signature {
00073     // Win32Signature is for non-thiscall signatures: all parameters pushed
00074     public:
00075                             Win32Signature(const char *nam);
00076                             Win32Signature(Signature &old);
00077         virtual             ~Win32Signature() { }
00078         virtual Signature   *clone();
00079         virtual bool        operator==(Signature& other);
00080         static  bool        qualified(UserProc *p, Signature &candidate);
00081 
00082         virtual void        addReturn(Type *type, Exp *e = NULL);
00083         virtual void        addParameter(Type *type, const char *nam = NULL, Exp *e = NULL, const char *boundMax = "");
00084         virtual Exp         *getArgumentExp(int n);
00085 
00086         virtual Signature   *promote(UserProc *p);
00087         virtual Exp         *getStackWildcard();
00088         virtual int         getStackRegister() throw(StackRegisterNotDefinedException) {return 28; }
00089         virtual Exp         *getProven(Exp *left);
00090         virtual bool        isPreserved(Exp* e);        // Return whether e is preserved by this proc
00091         virtual void        setLibraryDefines(StatementList* defs); // Set list of locations def'd by library calls
00092  
00093         virtual bool        isPromoted() {
00094                                 return true; }
00095         virtual platform    getPlatform() { return PLAT_PENTIUM; }
00096         virtual callconv    getConvention() { return CONV_PASCAL; }
00097     };  // class Win32Signature
00098 
00099     class Win32TcSignature : public Win32Signature {
00100     // Win32TcSignature is for "thiscall" signatures, i.e. those that have register ecx as the first parameter
00101     // Only needs to override a few member functions; the rest can inherit from Win32Signature
00102     public:
00103                             Win32TcSignature(const char *nam);
00104                             Win32TcSignature(Signature &old);
00105         virtual Exp         *getArgumentExp(int n);
00106         virtual Exp         *getProven(Exp* left);
00107         virtual Signature   *clone();
00108         virtual platform    getPlatform() { return PLAT_PENTIUM; }
00109         virtual callconv    getConvention() { return CONV_THISCALL; }
00110     };  // Class Win32TcSignature
00111 
00112 
00113     namespace StdC {
00114         class PentiumSignature : public Signature {
00115         public:
00116                                 PentiumSignature(const char *nam);
00117                                 PentiumSignature(Signature &old);
00118             virtual             ~PentiumSignature() { }
00119             virtual Signature   *clone(); 
00120             virtual bool        operator==(Signature& other);
00121             static  bool        qualified(UserProc *p, Signature &candidate);
00122 
00123             virtual void        addReturn(Type *type, Exp *e = NULL);
00124             virtual void        addParameter(Type *type, const char *nam = NULL, Exp *e = NULL, const char *boundMax = "");
00125             virtual Exp         *getArgumentExp(int n);
00126 
00127             virtual Signature   *promote(UserProc *p);
00128             virtual Exp         *getStackWildcard();
00129             virtual int         getStackRegister() throw(StackRegisterNotDefinedException) {return 28; }
00130             virtual Exp         *getProven(Exp *left);
00131             virtual bool        isPreserved(Exp* e);        // Return whether e is preserved by this proc
00132             virtual void        setLibraryDefines(StatementList* defs); // Set list of locations def'd by library calls
00133             virtual bool        isPromoted() { return true; }
00134             virtual platform    getPlatform() { return PLAT_PENTIUM; }
00135             virtual callconv    getConvention() { return CONV_C; }
00136             virtual bool        returnCompare(Assignment& a, Assignment& b);
00137             virtual bool        argumentCompare(Assignment& a, Assignment& b);
00138         };  // class PentiumSignature
00139 
00140         class SparcSignature : public Signature {
00141         public:
00142                                 SparcSignature(const char *nam);
00143                                 SparcSignature(Signature &old);
00144             virtual             ~SparcSignature() { }
00145             virtual Signature   *clone();
00146             virtual bool        operator==(Signature& other);
00147             static  bool        qualified(UserProc *p, Signature &candidate);
00148 
00149             virtual void        addReturn(Type *type, Exp *e = NULL);
00150             virtual void        addParameter(Type *type, const char *nam = NULL, Exp *e = NULL,
00151                                     const char *boundMax = "");
00152             virtual Exp         *getArgumentExp(int n);
00153 
00154             virtual Signature   *promote(UserProc *p);
00155             virtual Exp         *getStackWildcard();
00156             virtual int         getStackRegister() throw(StackRegisterNotDefinedException) {return 14; }
00157             virtual Exp         *getProven(Exp *left);
00158             virtual bool        isPreserved(Exp* e);        // Return whether e is preserved by this proc
00159             virtual void        setLibraryDefines(StatementList* defs); // Set list of locations def'd by library calls
00160             // Stack offsets can be negative (inherited) or positive:
00161             virtual bool        isLocalOffsetPositive() {return true;}
00162             // An override for testing locals
00163             virtual bool        isAddrOfStackLocal(Prog* prog, Exp* e);
00164             virtual bool        isPromoted() { return true; }
00165             virtual platform    getPlatform() { return PLAT_SPARC; }
00166             virtual callconv    getConvention() { return CONV_C; }
00167             virtual bool        returnCompare(Assignment& a, Assignment& b);
00168             virtual bool        argumentCompare(Assignment& a, Assignment& b);
00169         };  // class SparcSignature
00170 
00171         class SparcLibSignature : public SparcSignature {
00172         public:
00173                                 SparcLibSignature(const char *nam) : SparcSignature(nam) {}
00174                                 SparcLibSignature(Signature &old);
00175             virtual Signature   *clone();
00176             virtual Exp*        getProven(Exp* left);
00177         };  // class SparcLibSignature
00178 
00179         class PPCSignature : public Signature {
00180         public:
00181                                 PPCSignature(const char *name);
00182                                 PPCSignature(Signature& old);
00183             virtual             ~PPCSignature() { }
00184             virtual Signature   *clone();
00185             static  bool        qualified(UserProc *p, Signature &candidate);
00186             virtual void        addReturn(Type *type, Exp *e = NULL);
00187             virtual Exp         *getArgumentExp(int n);
00188             virtual void        addParameter(Type *type, const char *nam /*= NULL*/, Exp *e /*= NULL*/, const char *boundMax /*= ""*/);
00189             virtual Exp         *getStackWildcard();
00190             virtual int         getStackRegister() throw(StackRegisterNotDefinedException) {return 1; }
00191             virtual Exp         *getProven(Exp *left);
00192             virtual bool        isPreserved(Exp* e);        // Return whether e is preserved by this proc
00193             virtual void        setLibraryDefines(StatementList* defs); // Set list of locations def'd by library calls
00194             virtual bool        isLocalOffsetPositive() {return true;}
00195             virtual bool        isPromoted() { return true; }
00196             virtual platform    getPlatform() { return PLAT_PPC; }
00197             virtual callconv    getConvention() { return CONV_C; }
00198         };
00199         class ST20Signature : public Signature {
00200         public:
00201             ST20Signature(const char *name);
00202             ST20Signature(Signature &old);
00203             virtual ~ST20Signature() { }
00204             Signature *clone();
00205             virtual bool operator==(Signature& other);
00206             static bool qualified(UserProc *p, Signature &candidate);
00207 
00208             virtual void addReturn(Type *type, Exp *e = NULL);
00209             void addParameter(Type *type, const char *nam /*= NULL*/, Exp *e /*= NULL*/, const char *boundMax /*= ""*/);
00210             Exp *getArgumentExp(int n);
00211 
00212             virtual Signature *promote(UserProc *p);
00213             virtual Exp *getStackWildcard();
00214             virtual int  getStackRegister() throw(StackRegisterNotDefinedException) {return 3; }
00215             virtual Exp *getProven(Exp *left);
00216             virtual bool    isPromoted() { return true; }
00217             //virtual bool isLocalOffsetPositive() {return true;}
00218             virtual platform getPlatform() { return PLAT_ST20; }
00219             virtual callconv getConvention() { return CONV_C; }
00220         };
00221     };  // namespace StdC
00222 };  // namespace CallingConvention
00223 
00224 CallingConvention::Win32Signature::Win32Signature(const char *nam) : Signature(nam) {
00225     Signature::addReturn(Location::regOf(28));
00226     // Signature::addImplicitParameter(new PointerType(new IntegerType()), "esp",
00227     //                              Location::regOf(28), NULL);
00228 }
00229 
00230 CallingConvention::Win32Signature::Win32Signature(Signature &old) : Signature(old) {
00231 }
00232 
00233 CallingConvention::Win32TcSignature::Win32TcSignature(const char *nam) : Win32Signature(nam) {
00234     Signature::addReturn(Location::regOf(28));
00235     // Signature::addImplicitParameter(new PointerType(new IntegerType()), "esp",
00236     //                              Location::regOf(28), NULL);
00237 }
00238 
00239 CallingConvention::Win32TcSignature::Win32TcSignature(Signature &old) : Win32Signature(old) {
00240 }
00241 
00242 static void cloneVec(std::vector<Parameter*>& from, std::vector<Parameter*>& to) {
00243     unsigned n = from.size();
00244     to.resize(n);
00245     for (unsigned i=0; i < n; i++)
00246         to[i] = from[i]->clone();
00247 }
00248 
00249 static void cloneVec(Returns& from, Returns& to) {
00250     unsigned n = from.size();
00251     to.resize(n);
00252     for (unsigned i=0; i < n; i++)
00253         to[i] = from[i]->clone();
00254 }
00255 
00256 Parameter *hack;
00257 
00258 Parameter* Parameter::clone() {
00259     return new Parameter(type->clone(), name.c_str(), exp->clone(), boundMax.c_str());
00260 }
00261 
00262 void Parameter::setBoundMax(const char *nam) { 
00263     hack = this;
00264     boundMax = nam;
00265 }
00266 
00267 Signature *CallingConvention::Win32Signature::clone()
00268 {
00269     Win32Signature *n = new Win32Signature(name.c_str());
00270     cloneVec(params, n->params);
00271     // cloneVec(implicitParams, n->implicitParams);
00272     cloneVec(returns, n->returns);
00273     n->ellipsis = ellipsis;
00274     n->rettype = rettype->clone();
00275     n->preferedName = preferedName;
00276     if (preferedReturn) n->preferedReturn = preferedReturn->clone(); 
00277     else n->preferedReturn = NULL;
00278     n->preferedParams = preferedParams;
00279     return n;
00280 }
00281 
00282 Signature *CallingConvention::Win32TcSignature::clone()
00283 {
00284     Win32TcSignature *n = new Win32TcSignature(name.c_str());
00285     cloneVec(params, n->params);
00286     // cloneVec(implicitParams, n->implicitParams);
00287     cloneVec(returns, n->returns);
00288     n->ellipsis = ellipsis;
00289     n->rettype = rettype->clone();
00290     n->preferedName = preferedName;
00291     if (preferedReturn) n->preferedReturn = preferedReturn->clone(); 
00292     else n->preferedReturn = NULL;
00293     n->preferedParams = preferedParams;
00294     return n;
00295 }
00296 
00297 bool CallingConvention::Win32Signature::operator==(Signature& other)
00298 {
00299     return Signature::operator==(other);
00300 }
00301 
00302 static Exp* savedReturnLocation = Location::memOf(Location::regOf(28));
00303 static Exp* stackPlusFour = new Binary(opPlus,
00304     Location::regOf(28),
00305     new Const(4));
00306 
00307 bool CallingConvention::Win32Signature::qualified(UserProc *p, Signature &candidate) {
00308     platform plat = p->getProg()->getFrontEndId();
00309     if (plat != PLAT_PENTIUM || !p->getProg()->isWin32()) return false;
00310 
00311     if (VERBOSE)
00312         LOG << "consider promotion to stdc win32 signature for " << p->getName() << "\n";
00313 
00314     bool gotcorrectret1, gotcorrectret2 = false;
00315     Exp *provenPC = p->getProven(new Terminal(opPC));
00316     gotcorrectret1 = provenPC && (*provenPC == *savedReturnLocation);
00317     if (gotcorrectret1) {
00318         if (VERBOSE)
00319             LOG << "got pc = m[r[28]]\n";
00320         Exp *provenSP = p->getProven(Location::regOf(28));
00321         gotcorrectret2 = provenSP && *provenSP == *stackPlusFour;
00322         if (gotcorrectret2 && VERBOSE)
00323             LOG << "got r[28] = r[28] + 4\n";
00324     }
00325     if (VERBOSE)
00326         LOG << "qualified: " << (gotcorrectret1 && gotcorrectret2) << "\n";
00327     return gotcorrectret1 && gotcorrectret2;
00328 }
00329 
00330 void CallingConvention::Win32Signature::addReturn(Type *type, Exp *e)
00331 {
00332     if (type->isVoid())
00333         return;
00334     if (e == NULL) {
00335         if (type->isFloat())
00336             e = Location::regOf(32);
00337         else 
00338             e = Location::regOf(24);
00339     }
00340     Signature::addReturn(type, e);
00341 }
00342     
00343 void CallingConvention::Win32Signature::addParameter(Type *type, const char *nam /*= NULL*/, Exp *e /*= NULL*/, const char *boundMax /*= ""*/)
00344 {
00345     if (e == NULL) {
00346         e = getArgumentExp(params.size());
00347     }
00348     Signature::addParameter(type, nam, e, boundMax);
00349 }
00350 
00351 Exp *CallingConvention::Win32Signature::getArgumentExp(int n) {
00352     if (n < (int)params.size())
00353         return Signature::getArgumentExp(n);
00354     Exp *esp = Location::regOf(28);
00355     if (params.size() != 0 && *params[0]->getExp() == *esp)
00356         n--;
00357     Exp *e = Location::memOf(new Binary(opPlus, esp, new Const((n+1) * 4)));
00358     return e;
00359 }
00360 
00361 Exp* CallingConvention::Win32TcSignature::getArgumentExp(int n) {
00362     if (n < (int)params.size())
00363         return Signature::getArgumentExp(n);
00364     Exp *esp = Location::regOf(28);
00365     if (params.size() != 0 && *params[0]->getExp() == *esp)
00366         n--;
00367     if (n == 0)
00368         // It's the first parameter, register ecx
00369         return Location::regOf(25);
00370     // Else, it is m[esp+4n)]
00371     Exp *e = Location::memOf(new Binary(opPlus, esp, new Const(n * 4)));
00372     return e;
00373 }
00374 
00375 Signature *CallingConvention::Win32Signature::promote(UserProc *p)
00376 {
00377     // no promotions from win32 signature up, yet.
00378     // a possible thing to investigate would be COM objects
00379     return this;
00380 }
00381 
00382 Exp *CallingConvention::Win32Signature::getStackWildcard() {
00383     // Note: m[esp + -8] is simplified to m[esp - 8] now
00384     return Location::memOf(
00385         new Binary(opMinus,
00386             Location::regOf(28),
00387             new Terminal(opWild)));
00388 }
00389 
00390 Exp *CallingConvention::Win32Signature::getProven(Exp *left) {
00391     int nparams = params.size();
00392     if (nparams > 0 && *params[0]->getExp() == *Location::regOf(28)) {
00393         nparams--;
00394     }
00395     if (left->isRegOfK()) {
00396         switch (((Const*)left->getSubExp1())->getInt()) {
00397             case 28:    // esp
00398                 // Note: assumes callee pop... not true for cdecl functions!
00399                 return new Binary(opPlus, Location::regOf(28), 
00400                     new Const(4 + nparams*4));
00401             case 27:    // ebx
00402                 return Location::regOf(27);
00403             case 29:    // ebp
00404                 return Location::regOf(29);
00405             case 30:    // esi
00406                 return Location::regOf(30);
00407             case 31:    // edi
00408                 return Location::regOf(31);
00409             // there are other things that must be preserved here, look at calling convention
00410         }
00411     }
00412     return NULL;
00413 }
00414 
00415 bool CallingConvention::Win32Signature::isPreserved(Exp* e) {
00416     if (e->isRegOfK()) {
00417         switch (((Const*)e->getSubExp1())->getInt()) {
00418             case 29:        // ebp
00419             case 27:        // ebx
00420             case 30:        // esi
00421             case 31:        // edi
00422             case 3:         // bx
00423             case 5:         // bp
00424             case 6:         // si
00425             case 7:         // di
00426             case 11:        // bl
00427             case 15:        // bh
00428                 return true;
00429             default:
00430                 return false;
00431         }
00432     }
00433     return false;
00434 }
00435 
00436 // Return a list of locations defined by library calls
00437 void CallingConvention::Win32Signature::setLibraryDefines(StatementList* defs) {
00438     if (defs->size()) return;                   // Do only once
00439     Location* r24 = Location::regOf(24);        // eax
00440     Type* ty = new SizeType(32);
00441     if (returns.size() > 1) {                   // Ugh - note the stack pointer is the first return still
00442         ty = returns[1]->type;
00443 #if 0   // ADHOC TA
00444         if (ty->isFloat()) {
00445             Location* r32 = Location::regOf(32);                // Top of FP stack
00446             r32->setType(ty);
00447         } else
00448             r24->setType(ty);                                   // All others return in r24 (check!)
00449 #endif
00450     }
00451     defs->append(new ImplicitAssign(ty, r24));                      // eax
00452     defs->append(new ImplicitAssign(Location::regOf(25)));      // ecx
00453     defs->append(new ImplicitAssign(Location::regOf(26)));      // edx
00454     defs->append(new ImplicitAssign(Location::regOf(28)));      // esp
00455 }
00456 
00457 Exp *CallingConvention::Win32TcSignature::getProven(Exp *left)
00458 {
00459     if (left->isRegOfK()) {
00460         if (((Const*)left->getSubExp1())->getInt() == 28) {
00461             int nparams = params.size();
00462             if (nparams > 0 && *params[0]->getExp() == *Location::regOf(28)) {
00463                 nparams--;
00464             }
00465             // r28 += 4 + nparams*4 - 4     (-4 because ecx is register param)
00466             return new Binary(opPlus,
00467                 Location::regOf(28),
00468                 new Const(4 + nparams*4 - 4));
00469         }
00470     }
00471     // Else same as for standard Win32 signature
00472     return Win32Signature::getProven(left);
00473 }
00474 
00475 
00476 CallingConvention::StdC::PentiumSignature::PentiumSignature(const char *nam) : Signature(nam)
00477 {
00478     Signature::addReturn(Location::regOf(28));
00479     // Signature::addImplicitParameter(new PointerType(new IntegerType()), "esp",
00480     //                              Location::regOf(28), NULL);
00481 }
00482 
00483 CallingConvention::StdC::PentiumSignature::PentiumSignature(Signature &old) : Signature(old)
00484 {
00485 
00486 }
00487 
00488 Signature *CallingConvention::StdC::PentiumSignature::clone()
00489 {
00490     PentiumSignature *n = new PentiumSignature(name.c_str());
00491     cloneVec(params, n->params);
00492     // cloneVec(implicitParams, n->implicitParams);
00493     cloneVec(returns, n->returns);
00494     n->ellipsis = ellipsis;
00495     n->rettype = rettype->clone();
00496     n->preferedName = preferedName;
00497     if (preferedReturn) n->preferedReturn = preferedReturn->clone(); 
00498     else n->preferedReturn = NULL;
00499     n->preferedParams = preferedParams;
00500     n->unknown = unknown;
00501     return n;
00502 }
00503 
00504 bool CallingConvention::StdC::PentiumSignature::operator==(Signature& other)
00505 {
00506     return Signature::operator==(other);
00507 }
00508 
00509 
00510 // FIXME: This needs changing. Would like to check that pc=pc and sp=sp
00511 // (or maybe sp=sp+4) for qualifying procs. Need work to get there
00512 bool CallingConvention::StdC::PentiumSignature::qualified(UserProc *p, Signature &candidate) {
00513     platform plat = p->getProg()->getFrontEndId();
00514     if (plat != PLAT_PENTIUM) return false;
00515 
00516     if (VERBOSE)
00517         LOG << "consider promotion to stdc pentium signature for " << p->getName() << "\n";
00518 
00519 #if 1
00520     if (VERBOSE)
00521         LOG << "qualified: always true\n";
00522     return true;        // For now, always pass
00523 #else
00524     bool gotcorrectret1 = false;
00525     bool gotcorrectret2 = false;
00526     StatementList internal;
00527     //p->getInternalStatements(internal);
00528     internal.append(*p->getCFG()->getReachExit());
00529     StmtListIter it;
00530     for (Statement* s = internal.getFirst(it); s; s = internal.getNext(it)) {
00531         Assign *e = dynamic_cast<Assign*>(s);
00532         if (e == NULL) continue;
00533         if (e->getLeft()->getOper() == opPC) {
00534             if (e->getRight()->isMemOf() && e->getRight()->getSubExp1()->isRegOfN(28)) {
00535                 if (VERBOSE)
00536                     std::cerr << "got pc = m[r[28]]" << std::endl;
00537                 gotcorrectret1 = true;
00538             }
00539         } else if (e->getLeft()->isRegOfK() && 
00540                 ((Const*)e->getLeft()->getSubExp1())->getInt() == 28) {
00541             if (e->getRight()->getOper() == opPlus &&
00542                     e->getRight()->getSubExp1()->isRegOfN(28) &&
00543                     e->getRight()->getSubExp2()->isIntConst() &&
00544                     ((Const*)e->getRight()->getSubExp2())->getInt() == 4) {
00545                 if (VERBOSE)
00546                     std::cerr << "got r[28] = r[28] + 4" << std::endl;
00547                 gotcorrectret2 = true;
00548             }
00549         }
00550     }
00551     if (VERBOSE)
00552         LOG << "promotion: " << gotcorrectret1 && gotcorrectret2 << "\n";
00553     return gotcorrectret1 && gotcorrectret2;
00554 #endif
00555 }
00556 
00557 void CallingConvention::StdC::PentiumSignature::addReturn(Type *type, Exp *e)
00558 {
00559     if (type->isVoid())
00560         return;
00561     if (e == NULL) {
00562         if (type->isFloat())
00563             e = Location::regOf(32);
00564         else 
00565             e = Location::regOf(24);
00566     }
00567     Signature::addReturn(type, e);
00568 }
00569 
00570 void CallingConvention::StdC::PentiumSignature::addParameter(Type *type, const char *nam /*= NULL*/, Exp *e /*= NULL*/, const char *boundMax /*= ""*/)
00571 {
00572     if (e == NULL) {
00573         e = getArgumentExp(params.size());
00574     }
00575     Signature::addParameter(type, nam, e, boundMax);
00576 }
00577 
00578 Exp *CallingConvention::StdC::PentiumSignature::getArgumentExp(int n) {
00579     if (n < (int)params.size())
00580         return Signature::getArgumentExp(n);
00581     Exp *esp = Location::regOf(28);
00582     if (params.size() != 0 && *params[0]->getExp() == *esp)
00583         n--;
00584     Exp *e = Location::memOf(new Binary(opPlus, esp, new Const((n+1) * 4)));
00585     return e;
00586 }
00587 
00588 Signature *CallingConvention::StdC::PentiumSignature::promote(UserProc *p) {
00589     // No promotions from here up, obvious idea would be c++ name mangling  
00590     return this;
00591 }
00592 
00593 Exp *CallingConvention::StdC::PentiumSignature::getStackWildcard() {
00594     // Note: m[esp + -8] is simplified to m[esp - 8] now
00595     return Location::memOf(
00596         new Binary(opMinus,
00597             Location::regOf(28),
00598             new Terminal(opWild)));
00599 }
00600 
00601 Exp *CallingConvention::StdC::PentiumSignature::getProven(Exp *left) {
00602     if (left->isRegOfK()) {
00603         int r = ((Const*)left->getSubExp1())->getInt();
00604         switch (r) {
00605             case 28:    // esp
00606                 return new Binary(opPlus, Location::regOf(28), new Const(4));   // esp+4
00607             case 29: case 30: case 31: case 27:     // ebp, esi, edi, ebx
00608                 return Location::regOf(r);
00609         }
00610     }
00611     return NULL;
00612 }
00613 
00614 bool CallingConvention::StdC::PentiumSignature::isPreserved(Exp* e) {
00615     if (e->isRegOfK()) {
00616         switch (((Const*)e->getSubExp1())->getInt()) {
00617             case 29:        // ebp
00618             case 27:        // ebx
00619             case 30:        // esi
00620             case 31:        // edi
00621             case 3:         // bx
00622             case 5:         // bp
00623             case 6:         // si
00624             case 7:         // di
00625             case 11:        // bl
00626             case 15:        // bh
00627                 return true;
00628             default:
00629                 return false;
00630         }
00631     }
00632     return false;
00633 }
00634 
00635 // Return a list of locations defined by library calls
00636 void CallingConvention::StdC::PentiumSignature::setLibraryDefines(StatementList* defs) {
00637     if (defs->size()) return;                   // Do only once
00638     Location* r24 = Location::regOf(24);        // eax
00639     Type* ty = new SizeType(32);
00640     if (returns.size() > 1) {                   // Ugh - note the stack pointer is the first return still
00641         ty = returns[1]->type;
00642 #if 0       // ADHOC TA
00643         if (ty->isFloat()) {
00644             Location* r32 = Location::regOf(32);            // Top of FP stack
00645             r32->setType(ty);
00646         } else
00647             r24->setType(ty);                                   // All others return in r24 (check!)
00648 #endif
00649     }
00650     defs->append(new ImplicitAssign(ty, r24));                  // eax
00651     defs->append(new ImplicitAssign(Location::regOf(25)));      // ecx
00652     defs->append(new ImplicitAssign(Location::regOf(26)));      // edx
00653     defs->append(new ImplicitAssign(Location::regOf(28)));      // esp
00654 }
00655 
00656 CallingConvention::StdC::PPCSignature::PPCSignature(const char *nam) : Signature(nam) {
00657     Signature::addReturn(Location::regOf(1));
00658     // Signature::addImplicitParameter(new PointerType(new IntegerType()), "r1",
00659     //                              Location::regOf(1), NULL);
00660     // FIXME: Should also add m[r1+4] as an implicit parameter? Holds return address
00661 }
00662 
00663 CallingConvention::StdC::PPCSignature::PPCSignature(Signature& old) : Signature(old) {
00664 }
00665 
00666 Signature *CallingConvention::StdC::PPCSignature::clone() {
00667     PPCSignature *n = new PPCSignature(name.c_str());
00668     cloneVec(params, n->params);
00669     // n->implicitParams = implicitParams;
00670     cloneVec(returns, n->returns);
00671     n->ellipsis = ellipsis;
00672     n->rettype = rettype->clone();
00673     n->preferedName = preferedName;
00674     if (preferedReturn) n->preferedReturn = preferedReturn->clone(); 
00675     else n->preferedReturn = NULL;
00676     n->preferedParams = preferedParams;
00677     n->unknown = unknown;
00678     return n;
00679 }
00680 
00681 
00682 Exp *CallingConvention::StdC::PPCSignature::getArgumentExp(int n) {
00683     if (n < (int)params.size())
00684         return Signature::getArgumentExp(n);
00685     Exp *e;
00686     if (n >= 8) {
00687         // PPCs pass the ninth and subsequent parameters at m[%r1+8],
00688         // m[%r1+12], etc.
00689         e = Location::memOf(new Binary(opPlus,
00690             Location::regOf(1),
00691             new Const(8 + (n-8)*4)));
00692     } else
00693         e = Location::regOf((int)(3 + n));
00694     return e;
00695 }
00696 
00697 void CallingConvention::StdC::PPCSignature::addReturn(Type *type, Exp *e)
00698 {
00699     if (type->isVoid())
00700         return;
00701     if (e == NULL) {
00702         e = Location::regOf(3);
00703     }
00704     Signature::addReturn(type, e);
00705 }
00706 
00707 
00708 void CallingConvention::StdC::PPCSignature::addParameter(Type *type, const char *nam /*= NULL*/, Exp *e /*= NULL*/, const char *boundMax /*= ""*/) {
00709     if (e == NULL) {
00710         e = getArgumentExp(params.size());
00711     }
00712     Signature::addParameter(type, nam, e, boundMax);
00713 }
00714 
00715 Exp* CallingConvention::StdC::PPCSignature::getStackWildcard() {
00716     // m[r1 - WILD]
00717     return Location::memOf(
00718         new Binary(opMinus,
00719             Location::regOf(1),
00720             new Terminal(opWild)));
00721 }
00722 
00723 Exp *CallingConvention::StdC::PPCSignature::getProven(Exp* left) {
00724     if (left->isRegOfK()) {
00725         int r = ((Const*)((Location*)left)->getSubExp1())->getInt();
00726         switch (r) {
00727             case 1: // stack
00728                 return left;
00729         }
00730     }
00731     return NULL; 
00732 }
00733 
00734 bool CallingConvention::StdC::PPCSignature::isPreserved(Exp* e) {
00735     if (e->isRegOfK()) {
00736         int r = ((Const*)e->getSubExp1())->getInt();
00737         return r == 1;
00738     }
00739     return false;
00740 }
00741 
00742 // Return a list of locations defined by library calls
00743 void CallingConvention::StdC::PPCSignature::setLibraryDefines(StatementList* defs) {
00744     if (defs->size()) return;               // Do only once
00745     for (int r=3; r <= 12; ++r)
00746         defs->append(new ImplicitAssign(Location::regOf(r)));   // Registers 3-12 are volatile (caller save)
00747 }
00748 
00749 /// ST20 signatures
00750 
00751 CallingConvention::StdC::ST20Signature::ST20Signature(const char *nam) : Signature(nam) {
00752     Signature::addReturn(Location::regOf(3));
00753     // Signature::addImplicitParameter(new PointerType(new IntegerType()), "sp", Location::regOf(3), NULL);
00754     // FIXME: Should also add m[sp+0] as an implicit parameter? Holds return address
00755 }
00756 
00757 CallingConvention::StdC::ST20Signature::ST20Signature(Signature &old) : Signature(old)
00758 {
00759 
00760 }
00761 
00762 Signature *CallingConvention::StdC::ST20Signature::clone() {
00763     ST20Signature *n = new ST20Signature(name.c_str());
00764     n->params = params;
00765     n->returns = returns;
00766     n->ellipsis = ellipsis;
00767     n->rettype = rettype;
00768     n->preferedName = preferedName;
00769     n->preferedReturn = preferedReturn;
00770     n->preferedParams = preferedParams;
00771     n->unknown = unknown;
00772     return n;
00773 }
00774 
00775 bool CallingConvention::StdC::ST20Signature::operator==(Signature& other)
00776 {
00777     return Signature::operator==(other);
00778 }
00779 
00780 
00781 Exp *CallingConvention::StdC::ST20Signature::getArgumentExp(int n) {
00782     if (n < (int)params.size())
00783         return Signature::getArgumentExp(n);
00784     // m[%sp+4], etc.
00785     Exp *sp = Location::regOf(3);
00786     if (params.size() != 0 && *params[0]->getExp() == *sp)
00787         n--;
00788     Exp *e = Location::memOf(new Binary(opPlus, sp, new Const((n+1) * 4)));
00789     return e;
00790 }
00791 
00792 void CallingConvention::StdC::ST20Signature::addReturn(Type *type, Exp *e)
00793 {
00794     if (type->isVoid())
00795         return;
00796     if (e == NULL) {
00797         e = Location::regOf(0);
00798     }
00799     Signature::addReturn(type, e);
00800 }
00801 
00802 Signature *CallingConvention::StdC::ST20Signature::promote(UserProc *p) {
00803     // No promotions from here up, obvious idea would be c++ name mangling  
00804     return this;
00805 }
00806 
00807 void CallingConvention::StdC::ST20Signature::addParameter(Type *type, const char *nam /*= NULL*/, Exp *e /*= NULL*/, const char *boundMax /*= ""*/)
00808 {
00809     if (e == NULL) {
00810         e = getArgumentExp(params.size());
00811     }
00812     Signature::addParameter(type, nam, e, boundMax);
00813 }
00814 
00815 Exp* CallingConvention::StdC::ST20Signature::getStackWildcard() {
00816     // m[r1 - WILD]
00817     return Location::memOf(
00818         new Binary(opMinus,
00819             Location::regOf(3),
00820             new Terminal(opWild)));
00821 }
00822 
00823 #if 1
00824 Exp *CallingConvention::StdC::ST20Signature::getProven(Exp *left) {
00825     if (left->isRegOfK()) {
00826         int r = ((Const*)left->getSubExp1())->getInt();
00827         switch (r) {
00828             case 3:
00829                 //return new Binary(opPlus, Location::regOf(3), new Const(4));
00830                 return left;
00831             case 0: case 1: case 2:
00832                 //Registers A, B, and C are callee save
00833                 return Location::regOf(r);
00834         }
00835     }
00836     return NULL;
00837 }
00838 #else
00839 Exp *CallingConvention::StdC::ST20Signature::getProven(Exp* left) {
00840     if (left->isRegOfK()) {
00841         int r = ((Const*)((Location*)left)->getSubExp1())->getInt();
00842         switch (r) {
00843             case 3: // stack
00844                 return left;
00845         }
00846     }
00847     return NULL; 
00848 }
00849 #endif
00850 
00851 bool CallingConvention::StdC::ST20Signature::qualified(UserProc *p, Signature &candidate) {
00852     platform plat = p->getProg()->getFrontEndId();
00853     if (plat != PLAT_ST20) return false;
00854 
00855     if (VERBOSE)
00856         LOG << "consider promotion to stdc st20 signature for " << p->getName() << "\n";
00857 
00858     return true;
00859 }
00860 
00861 /*
00862 bool CallingConvention::StdC::PPCSignature::isAddrOfStackLocal(Prog* prog, Exp* e) {
00863     LOG << "doing PPC specific check on " << e << "\n";
00864     // special case for m[r1{-} + 4] which is used to store the return address in non-leaf procs.
00865     if (e->getOper() == opPlus && e->getSubExp1()->isSubscript() && 
00866         ((RefExp*)(e->getSubExp1()))->isImplicitDef() && e->getSubExp1()->getSubExp1()->isRegOfK() && 
00867         ((Const*)e->getSubExp1()->getSubExp1()->getSubExp1())->getInt() == 1 && e->getSubExp2()->isIntConst() &&
00868         ((Const*)e->getSubExp2())->getInt() == 4)
00869         return true;
00870     return Signature::isAddrOfStackLocal(prog, e);
00871 }
00872 */
00873 
00874 CallingConvention::StdC::SparcSignature::SparcSignature(const char *nam) : Signature(nam) {
00875     Signature::addReturn(Location::regOf(14));
00876     // Signature::addImplicitParameter(new PointerType(new IntegerType()), "sp",
00877     //                              Location::regOf(14), NULL);
00878 }
00879 
00880 CallingConvention::StdC::SparcSignature::SparcSignature(Signature &old) : Signature(old) {
00881 }
00882 
00883 Signature *CallingConvention::StdC::SparcSignature::clone() {
00884     SparcSignature *n = new SparcSignature(name.c_str());
00885     cloneVec(params, n->params);
00886     // cloneVec(implicitParams, n->implicitParams);
00887     cloneVec(returns, n->returns);
00888     n->ellipsis = ellipsis;
00889     n->rettype = rettype->clone();
00890     n->preferedName = preferedName;
00891     if (preferedReturn) n->preferedReturn = preferedReturn->clone(); 
00892     else n->preferedReturn = NULL;
00893     n->preferedParams = preferedParams;
00894     n->unknown = unknown;
00895     return n;
00896 }
00897 
00898 Signature *CallingConvention::StdC::SparcLibSignature::clone() {
00899     SparcLibSignature *n = new SparcLibSignature(name.c_str());
00900     cloneVec(params, n->params);
00901     // cloneVec(implicitParams, n->implicitParams);
00902     cloneVec(returns, n->returns);
00903     n->ellipsis = ellipsis;
00904     n->rettype = rettype->clone();
00905     n->preferedName = preferedName;
00906     if (preferedReturn) n->preferedReturn = preferedReturn->clone(); 
00907     else n->preferedReturn = NULL;
00908     n->preferedParams = preferedParams;
00909     return n;
00910 }
00911 
00912 bool CallingConvention::StdC::SparcSignature::operator==(Signature& other) {
00913     return Signature::operator==(other);
00914 }
00915 
00916 
00917 bool CallingConvention::StdC::SparcSignature::qualified(UserProc *p, Signature &candidate) {
00918     if (VERBOSE)
00919         LOG << "consider promotion to stdc sparc signature for " << p->getName() << "\n";
00920     
00921     platform plat = p->getProg()->getFrontEndId();
00922     if (plat != PLAT_SPARC) return false;
00923 
00924     if (VERBOSE)
00925         LOG << "Promoted to StdC::SparcSignature\n";
00926     
00927     return true;
00928 }
00929 
00930 bool CallingConvention::StdC::PPCSignature::qualified(UserProc *p, Signature &candidate) {
00931     if (VERBOSE)
00932         LOG << "consider promotion to stdc PPC signature for " << p->getName() << "\n";
00933     
00934     platform plat = p->getProg()->getFrontEndId();
00935     if (plat != PLAT_PPC) return false;
00936 
00937     if (VERBOSE)
00938         LOG << "Promoted to StdC::PPCSignature (always qualifies)\n";
00939     
00940     return true;
00941 }
00942 
00943 void CallingConvention::StdC::SparcSignature::addReturn(Type *type, Exp *e)
00944 {
00945     if (type->isVoid())
00946         return;
00947     if (e == NULL) {
00948         e = Location::regOf(8);
00949     }
00950     Signature::addReturn(type, e);
00951 }
00952 
00953 void CallingConvention::StdC::SparcSignature::addParameter(Type *type, const char *nam /*= NULL*/, Exp *e /*= NULL*/, const char *boundMax /*= ""*/) {
00954     if (e == NULL) {
00955         e = getArgumentExp(params.size());
00956     }
00957     Signature::addParameter(type, nam, e, boundMax);
00958 }
00959 
00960 Exp *CallingConvention::StdC::SparcSignature::getArgumentExp(int n) {
00961     if (n < (int)params.size())
00962         return Signature::getArgumentExp(n);
00963     Exp *e;
00964     if (n >= 6) {
00965         // SPARCs pass the seventh and subsequent parameters at m[%sp+92],
00966         // m[%esp+96], etc.
00967         e = Location::memOf(new Binary(opPlus,
00968             Location::regOf(14), // %o6 == %sp
00969             new Const(92 + (n-6)*4)));
00970     } else
00971         e = Location::regOf((int)(8 + n));
00972     return e;
00973 }
00974  
00975 Signature *CallingConvention::StdC::SparcSignature::promote(UserProc *p) {
00976     // no promotions from here up, obvious example would be name mangling
00977     return this;
00978 }
00979 
00980 Exp *CallingConvention::StdC::SparcSignature::getStackWildcard() {
00981     return Location::memOf(
00982         new Binary(opPlus,
00983             Location::regOf(14),
00984             new Terminal(opWild)));
00985 }
00986 
00987 Exp *CallingConvention::StdC::SparcSignature::getProven(Exp* left) {
00988     if (left->isRegOfK()) {
00989         int r = ((Const*)((Location*)left)->getSubExp1())->getInt();
00990         switch (r) {
00991             // These registers are preserved in Sparc: i0-i7 (24-31), sp (14)
00992             case 14:                                // sp
00993             case 24: case 25: case 26: case 27:     // i0-i3
00994             case 28: case 29: case 30: case 31:     // i4-i7
00995             // NOTE: Registers %g2 to %g4 are NOT preserved in ordinary application (non library) code
00996                 return left;
00997         }
00998     }
00999     return NULL; 
01000 }
01001 
01002 bool CallingConvention::StdC::SparcSignature::isPreserved(Exp* e) {
01003     if (e->isRegOfK()) {
01004         int r = ((Const*)((Location*)e)->getSubExp1())->getInt();
01005         switch (r) {
01006             // These registers are preserved in Sparc: i0-i7 (24-31), sp (14)
01007             case 14:                                // sp
01008             case 24: case 25: case 26: case 27:     // i0-i3
01009             case 28: case 29: case 30: case 31:     // i4-i7
01010             // NOTE: Registers %g2 to %g4 are NOT preserved in ordinary application (non library) code
01011                 return true;
01012             default:
01013                 return false;
01014         }
01015     }
01016     return false; 
01017 }
01018 
01019 // Return a list of locations defined by library calls
01020 void CallingConvention::StdC::SparcSignature::setLibraryDefines(StatementList* defs) {
01021     if (defs->size()) return;               // Do only once
01022     for (int r=8; r <= 15; ++r)
01023         defs->append(new ImplicitAssign(Location::regOf(r)));   // o0-o7 (r8-r15) modified
01024 }
01025 
01026 
01027 Exp *CallingConvention::StdC::SparcLibSignature::getProven(Exp* left) {
01028     if (left->isRegOfK()) {
01029         int r = ((Const*)((Location*)left)->getSubExp1())->getInt();
01030         switch (r) {
01031             // These registers are preserved in Sparc: i0-i7 (24-31), sp (14)
01032             case 14:
01033             case 24: case 25: case 26: case 27:
01034             case 28: case 29: case 30: case 31:
01035             // Also the "application global registers" g2-g4 (2-4) (preserved
01036             // by library functions, but apparently don't have to be preserved
01037             // by application code)
01038             case 2:  case 3:    case 4:         // g2-g4
01039             // The system global registers (g5-g7) are also preserved, but
01040             // should never be changed in an application anyway
01041                 return left;
01042         }
01043     }
01044     return NULL; 
01045 }
01046 
01047 
01048 
01049 Signature::Signature(const char *nam) : rettype(new VoidType()), ellipsis(false), unknown(true), forced(false),
01050         preferedReturn(NULL) {
01051     if (nam == NULL) 
01052         name = "<ANON>";
01053     else
01054         name = nam;
01055 }
01056 
01057 CustomSignature::CustomSignature(const char *nam) : Signature(nam), sp(0) {
01058 }
01059 
01060 void CustomSignature::setSP(int nsp)
01061 {
01062     sp = nsp;
01063     if (sp) {
01064         addReturn(Location::regOf(sp));
01065         // addImplicitParameter(new PointerType(new IntegerType()), "sp",
01066         //                          Location::regOf(sp), NULL);
01067     }
01068 }
01069 
01070 Signature *Signature::clone()
01071 {
01072     Signature *n = new Signature(name.c_str());
01073     cloneVec(params, n->params);
01074     // cloneVec(implicitParams, n->implicitParams);
01075     cloneVec(returns, n->returns);
01076     n->ellipsis = ellipsis;
01077     n->rettype = rettype->clone();
01078     n->preferedName = preferedName;
01079     if (preferedReturn) n->preferedReturn = preferedReturn->clone(); 
01080     else n->preferedReturn = NULL;
01081     n->preferedParams = preferedParams;
01082     n->unknown = unknown;
01083     n->sigFile = sigFile;
01084     return n;
01085 }
01086 
01087 Signature *CustomSignature::clone()
01088 {
01089     CustomSignature *n = new CustomSignature(name.c_str());
01090     cloneVec(params, n->params);
01091     // cloneVec(implicitParams, n->implicitParams);
01092     cloneVec(returns, n->returns);
01093     n->ellipsis = ellipsis;
01094     n->rettype = rettype->clone();
01095     n->sp = sp;
01096     n->preferedName = preferedName;
01097     if (preferedReturn) n->preferedReturn = preferedReturn->clone(); 
01098     else n->preferedReturn = NULL;
01099     n->preferedParams = preferedParams;
01100     return n;
01101 }
01102 
01103 
01104 bool Signature::operator==(Signature& other)
01105 {
01106     //if (name != other.name) return false;     // MVE: should the name be significant? I'm thinking no
01107     if (params.size() != other.params.size()) return false;
01108     // Only care about the first return location (at present)
01109     std::vector<Parameter*>::iterator it1, it2;
01110     for (it1 = params.begin(), it2 = other.params.begin(); it1 != params.end(); it1++, it2++)
01111         if (!(**it1 == **it2)) return false; 
01112     if (returns.size() != other.returns.size()) return false;
01113     std::vector<Return*>::iterator rr1, rr2;
01114     for (rr1 = returns.begin(), rr2 = other.returns.begin(); rr1 != returns.end(); ++rr1, ++rr2)
01115         if (!(**rr1 == **rr2)) return false; 
01116     return true;
01117 }
01118 
01119 const char *Signature::getName()
01120 {
01121     return name.c_str();
01122 }
01123 
01124 void Signature::setName(const char *nam)
01125 {
01126     name = nam;
01127 }
01128 
01129 void Signature::addParameter(const char *nam /*= NULL*/) {
01130     addParameter(new VoidType(), nam);
01131 }
01132 
01133 void Signature::addParameter(Exp *e, Type* ty) {
01134     addParameter(ty, NULL, e);
01135 }
01136 
01137 void Signature::addParameter(Type *type, const char *nam /*= NULL*/, Exp *e /*= NULL*/, const char *boundMax /*= ""*/) {
01138     if (e == NULL) {
01139         std::cerr << "No expression for parameter ";
01140         if (type == NULL)
01141             std::cerr << "<notype> ";
01142         else
01143             std::cerr << type->getCtype() << " ";
01144         if (nam == NULL)
01145             std::cerr << "<noname>";
01146         else
01147             std::cerr << nam;
01148         std::cerr << "\n";
01149         assert(e);  // Else get infinite mutual recursion with the below proc
01150     }
01151 
01152     std::string s;
01153     if (nam == NULL) {
01154         int n = params.size()+1;
01155         bool ok = false;
01156         while (!ok) {
01157             std::stringstream os;
01158             os << "param" << n << std::ends;
01159             s = os.str();
01160             ok = true;
01161             for (unsigned i = 0; i < params.size(); i++)
01162                 if (!strcmp(s.c_str(), params[i]->getName()))
01163                     ok = false;
01164             n++;
01165         }
01166         nam = s.c_str();
01167     }
01168     Parameter *p = new Parameter(type, nam, e, boundMax); 
01169     addParameter(p);
01170     // addImplicitParametersFor(p);
01171 }
01172 
01173 void Signature::addParameter(Parameter *param)
01174 {
01175     Type *ty = param->getType();
01176     const char *nam = param->getName();
01177     Exp *e = param->getExp();
01178 
01179     if (strlen(nam) == 0)
01180         nam = NULL;
01181 
01182     if (ty == NULL || e == NULL || nam == NULL) {
01183         addParameter(ty, nam, e, param->getBoundMax());
01184     } else
01185         params.push_back(param);
01186 }
01187 
01188 void Signature::removeParameter(Exp *e) {
01189     int i = findParam(e);
01190     if (i != -1)
01191         removeParameter(i);
01192 }
01193 
01194 void Signature::removeParameter(int i) {
01195     for (unsigned j = i+1; j < params.size(); j++)
01196         params[j-1] = params[j];
01197     params.resize(params.size()-1);
01198 }
01199 
01200 void Signature::setNumParams(int n) {
01201     if (n < (int)params.size()) {
01202         // truncate
01203         params.erase(params.begin() + n, params.end());
01204     } else {
01205         for (int i = params.size(); i < n; i++)
01206             addParameter();     
01207     }
01208 }
01209 
01210 const char *Signature::getParamName(int n) {
01211     assert(n < (int)params.size());
01212     return params[n]->getName();
01213 }
01214 
01215 Exp *Signature::getParamExp(int n) {
01216     assert(n < (int)params.size());
01217     return params[n]->getExp();
01218 }
01219 
01220 Type *Signature::getParamType(int n) {
01221     //assert(n < (int)params.size() || ellipsis);
01222     // With recursion, parameters not set yet. Hack for now:
01223     if (n >= (int)params.size()) return NULL;
01224     return params[n]->getType();
01225 }
01226 
01227 const char *Signature::getParamBoundMax(int n)
01228 {
01229     if (n >= (int)params.size()) return NULL;
01230     const char *s = params[n]->getBoundMax();
01231     if (strlen(s) == 0)
01232         return NULL;
01233     return s;
01234 }
01235 
01236 void Signature::setParamType(int n, Type *ty) {
01237     params[n]->setType(ty);
01238 }
01239 
01240 void Signature::setParamType(const char* nam, Type* ty) {
01241     int idx = findParam(nam);
01242     if (idx == -1) {
01243         LOG << "could not set type for unknown parameter " << nam << "\n";
01244         return;
01245     }
01246     params[idx]->setType(ty);
01247 }
01248 
01249 void Signature::setParamType(Exp* e, Type* ty) {
01250     int idx = findParam(e);
01251     if (idx == -1) {
01252         LOG << "could not set type for unknown parameter expression " << e << "\n";
01253         return;
01254     }
01255     params[idx]->setType(ty);
01256 }
01257 
01258 void Signature::setParamName(int n, const char *name)
01259 {
01260     params[n]->setName(name);
01261 }
01262 
01263 void Signature::setParamExp(int n, Exp *e)
01264 {
01265     params[n]->setExp(e);
01266 }
01267 
01268 // Return the index for the given expression, or -1 if not found
01269 int Signature::findParam(Exp *e) {
01270     for (unsigned i = 0; i < getNumParams(); i++)
01271         if (*getParamExp(i) == *e)
01272             return i;
01273     return -1;
01274 }
01275 
01276 void Signature::renameParam(const char *oldName, const char *newName)
01277 {
01278     for (unsigned i = 0; i < getNumParams(); i++)
01279         if (!strcmp(params[i]->getName(), oldName)) {
01280             params[i]->setName(newName);
01281             break;
01282         }
01283 }
01284 
01285 int Signature::findParam(const char *nam) {
01286     for (unsigned i = 0; i < getNumParams(); i++)
01287         if (!strcmp(getParamName(i), nam))
01288             return i;
01289     return -1;
01290 }
01291 
01292 int Signature::findReturn(Exp *e) {
01293     for (unsigned i = 0; i < getNumReturns(); i++)
01294         if (*returns[i]->exp == *e)
01295             return (int)i;
01296     return -1;
01297 }
01298 
01299 void Signature::addReturn(Type *type, Exp *exp) {
01300     assert(exp);
01301     addReturn(new Return(type, exp));
01302 }
01303 
01304 // Deprecated. Use the above version.
01305 void Signature::addReturn(Exp *exp) {
01306     //addReturn(exp->getType() ? exp->getType() : new IntegerType(), exp);
01307     addReturn(new VoidType(), exp);
01308 }
01309 
01310 void Signature::removeReturn(Exp *e)
01311 {
01312     int i = findReturn(e);
01313     if (i != -1) {
01314         for (unsigned j = i+1; j < returns.size(); j++)
01315             returns[j-1] = returns[j];
01316         returns.resize(returns.size()-1);
01317     }
01318 }
01319 
01320 void Signature::setReturnType(int n, Type *ty) {
01321     if (n < (int)returns.size())
01322         returns[n]->type = ty;
01323 }
01324 
01325 Exp *Signature::getArgumentExp(int n) {
01326     return getParamExp(n);
01327 }
01328 
01329 Signature *Signature::promote(UserProc *p) {
01330     // FIXME: the whole promotion idea needs a redesign...
01331     if (CallingConvention::Win32Signature::qualified(p, *this)) {
01332         Signature *sig = new CallingConvention::Win32Signature(*this);
01333 //      sig->analyse(p);
01334         delete this;
01335         return sig;
01336     }
01337 
01338     if (CallingConvention::StdC::PentiumSignature::qualified(p, *this)) {
01339         Signature *sig = new CallingConvention::StdC::PentiumSignature(*this);
01340 //      sig->analyse(p);
01341         delete this;
01342         return sig;
01343     }
01344 
01345     if (CallingConvention::StdC::SparcSignature::qualified(p, *this)) {
01346         Signature *sig = new CallingConvention::StdC::SparcSignature(*this);
01347 //      sig->analyse(p);
01348         delete this;
01349         return sig;
01350     }
01351 
01352     if (CallingConvention::StdC::PPCSignature::qualified(p, *this)) {
01353         Signature *sig = new CallingConvention::StdC::PPCSignature(*this);
01354 //      sig->analyse(p);
01355         delete this;
01356         return sig;
01357     }
01358 
01359     if (CallingConvention::StdC::ST20Signature::qualified(p, *this)) {
01360         Signature *sig = new CallingConvention::StdC::ST20Signature(*this);
01361 //      sig->analyse(p);
01362         delete this;
01363         return sig;
01364     }
01365 
01366     return this;
01367 }
01368 
01369 Signature *Signature::instantiate(platform plat, callconv cc, const char *nam) {
01370     switch (plat) {
01371         case PLAT_PENTIUM:
01372             if (cc == CONV_PASCAL)
01373                 // For now, assume the only pascal calling convention pentium signatures will be Windows
01374                 return new CallingConvention::Win32Signature(nam);
01375             else if (cc == CONV_THISCALL)
01376                 return new CallingConvention::Win32TcSignature(nam);
01377             else
01378                 return new CallingConvention::StdC::PentiumSignature(nam);
01379         case PLAT_SPARC:
01380             assert(cc == CONV_C);
01381             return new CallingConvention::StdC::SparcSignature(nam);
01382         case PLAT_PPC:
01383             return new CallingConvention::StdC::PPCSignature(nam);
01384         case PLAT_ST20:
01385             return new CallingConvention::StdC::ST20Signature(nam);
01386         // insert other conventions here
01387     default:
01388         std::cerr << "unknown signature: " << conventionName(cc) << " " << platformName(plat) << "\n";
01389         assert(false);
01390     }
01391     return NULL;
01392 }
01393 
01394 void Signature::print(std::ostream &out, bool html)
01395 {
01396     if (isForced())
01397         out << "*forced* ";
01398     if (returns.size() > 0) {
01399         out << "{ ";
01400         unsigned n = 0;
01401         for (Returns::iterator rr = returns.begin(); rr != returns.end(); rr++, n++) {
01402             out << (*rr)->type->getCtype() << " " << (*rr)->exp;
01403             if (n != returns.size() - 1)
01404                 out << ", ";
01405             else
01406                 out << " ";
01407         }
01408         out << "} ";
01409     } else
01410         out << "void ";
01411     out << name << "(";
01412     unsigned int i;
01413     for (i = 0; i < params.size(); i++) {
01414         out << params[i]->getType()->getCtype() << " " << params[i]->getName() << " " << params[i]->getExp();
01415         if (i != params.size()-1) out << ", ";
01416     }
01417     out << ")\n"; 
01418 }
01419 
01420 char* Signature::prints() {
01421     std::ostringstream ost;
01422     print(ost);
01423     strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
01424     debug_buffer[DEBUG_BUFSIZE-1] = '\0';
01425     return debug_buffer;
01426 }
01427 
01428 void Signature::printToLog()
01429 {
01430     std::ostringstream os;
01431     print(os);
01432     LOG << os.str().c_str();
01433 }
01434 
01435 bool Signature::usesNewParam(UserProc *p, Statement *stmt, bool checkreach, int &n) {
01436     n = getNumParams() - 1;
01437     if (VERBOSE) {
01438         std::cerr << "searching ";
01439         stmt->printAsUse(std::cerr);
01440         std::cerr << std::endl;
01441     }
01442     StatementSet reachin;
01443     //stmt->getReachIn(reachin, 2);
01444     for (int i = getNumParams(); i < 10; i++)
01445         if (stmt->usesExp(getParamExp(i))) {
01446             bool ok = true;
01447             if (checkreach) {
01448                 bool hasDef = false;
01449                     StatementSet::iterator it1;
01450                     for (it1 = reachin.begin(); it1 != reachin.end(); it1++) {
01451                         Assignment* as = (Assignment*)*it1;
01452                         if (as->isAssignment() && *as->getLeft() == *getParamExp(i)) {
01453                             hasDef = true; break; 
01454                         }
01455                     }
01456                     if (hasDef) ok = false;
01457             }
01458             if (ok) {
01459                 n = i;
01460             }
01461         }
01462     return n > ((int)getNumParams() - 1);
01463 }
01464 
01465 // Special for Mike: find the location where the first outgoing (actual) parameter is conventionally held
01466 Exp* Signature::getFirstArgLoc(Prog* prog) {
01467     MACHINE mach = prog->getMachine();
01468     switch (mach) {
01469         case MACHINE_SPARC: {
01470             CallingConvention::StdC::SparcSignature sig("");
01471             return sig.getArgumentExp(0);
01472         }
01473         case MACHINE_PENTIUM: {
01474             //CallingConvention::StdC::PentiumSignature sig("");
01475             //Exp* e = sig.getArgumentExp(0);
01476             // For now, need to work around how the above appears to be the wrong thing!
01477 Exp* e = Location::memOf(Location::regOf(28));
01478             return e;
01479         }
01480         case MACHINE_ST20: {
01481             CallingConvention::StdC::ST20Signature sig("");
01482             return sig.getArgumentExp(0);
01483             //return Location::regOf(0);
01484 
01485         }
01486         default:
01487             std::cerr << "Signature::getFirstArgLoc: machine not handled\n";
01488             assert(0);
01489     }
01490     return 0;
01491 }
01492 
01493 // A bit of a cludge. Problem is that we can't call the polymorphic getReturnExp() until signature promotion has
01494 // happened. For the switch logic, that happens way too late. So for now, we have this cludge.
01495 // This is very very hacky! (trent)
01496 /*static*/ Exp* Signature::getReturnExp2(BinaryFile* pBF) {
01497     switch (pBF->GetMachine()) {
01498         case MACHINE_SPARC: 
01499             return Location::regOf(8);
01500         case MACHINE_PENTIUM:
01501             return Location::regOf(24);
01502         case MACHINE_ST20: 
01503             return Location::regOf(0);
01504         default:
01505             std::cerr << "getReturnExp2: machine not handled\n";
01506             return NULL;
01507     }
01508     return NULL;
01509 }
01510 
01511 // Not very satisfying to do things this way. Problem is that the polymorphic CallingConvention objects are set up
01512 // very late in the decompilation. Get the set of registers that are not saved in library functions (or any
01513 // procedures that follow the calling convention)
01514 void Signature::setABIdefines(Prog* prog, StatementList* defs) {
01515     if (defs->size()) return;                   // Do only once
01516     MACHINE mach = prog->getMachine();
01517     switch (mach) {
01518         case MACHINE_PENTIUM: {
01519             defs->append(new ImplicitAssign(Location::regOf(24)));      // eax
01520             defs->append(new ImplicitAssign(Location::regOf(25)));      // ecx
01521             defs->append(new ImplicitAssign(Location::regOf(26)));      // edx
01522         }
01523         case MACHINE_SPARC: {
01524             for (int r=8; r <= 13; ++r)
01525                 defs->append(new ImplicitAssign(Location::regOf(r)));   // %o0-o5
01526             defs->append(new ImplicitAssign(Location::regOf(1)));       // %g1
01527         }
01528         case MACHINE_PPC: {
01529             for (int r=3; r <= 12; ++r)
01530                 defs->append(new ImplicitAssign(Location::regOf(r)));   // r3-r12
01531         }
01532         case MACHINE_ST20: {
01533             defs->append(new ImplicitAssign(Location::regOf(0)));       // A
01534             defs->append(new ImplicitAssign(Location::regOf(1)));       // B
01535             defs->append(new ImplicitAssign(Location::regOf(2)));       // C
01536         }
01537         default:
01538             break;
01539     }
01540 }
01541 
01542 // Get the expected argument location, based solely on the machine of the input program
01543 Exp* Signature::getEarlyParamExp(int n, Prog* prog) {
01544     MACHINE mach = prog->getMachine();
01545     switch (mach) {
01546         case MACHINE_SPARC: {
01547             CallingConvention::StdC::SparcSignature temp("");
01548             return temp.getParamExp(n);
01549         }
01550         case MACHINE_PENTIUM: {
01551             // Would we ever need Win32?
01552             CallingConvention::StdC::PentiumSignature temp("");
01553             return temp.getParamExp(n);
01554         }
01555         case MACHINE_ST20: {
01556             CallingConvention::StdC::ST20Signature temp("");
01557             return temp.getParamExp(n);
01558         }
01559         default:
01560             break;
01561     }
01562     assert(0);          // Machine not handled
01563     return NULL;
01564 }
01565 
01566 StatementList& Signature::getStdRetStmt(Prog* prog) {
01567     // pc := m[r[28]]
01568     static Assign pent1ret(
01569         new Terminal(opPC),
01570         Location::memOf(Location::regOf(28)));
01571     // r[28] := r[28] + 4
01572     static Assign pent2ret(
01573         Location::regOf(28),
01574         new Binary(opPlus,
01575             Location::regOf(28),
01576             new Const(4)));
01577     static Assign st20_1ret(
01578         new Terminal(opPC),
01579         Location::memOf(Location::regOf(3)));
01580     static Assign st20_2ret(
01581         Location::regOf(3),
01582         new Binary(opPlus,
01583             Location::regOf(3),
01584             new Const(16)));
01585     MACHINE mach = prog->getMachine();
01586     switch (mach) {
01587         case MACHINE_SPARC:
01588             break;              // No adjustment to stack pointer required
01589         case MACHINE_PENTIUM: {
01590             StatementList* sl = new StatementList;
01591             sl->append((Statement*)&pent1ret);
01592             sl->append((Statement*)&pent2ret);
01593             return *sl;
01594         }
01595         case MACHINE_ST20: {
01596             StatementList* sl = new StatementList;
01597             sl->append((Statement*)&st20_1ret);
01598             sl->append((Statement*)&st20_2ret);
01599             return *sl;
01600         }
01601         default:
01602             break;
01603     }
01604     return *new StatementList;
01605 }
01606 
01607 int Signature::getStackRegister() throw(StackRegisterNotDefinedException) {
01608     if (VERBOSE)
01609         LOG << "thowing StackRegisterNotDefinedException\n";
01610     throw StackRegisterNotDefinedException();
01611 }
01612 
01613 // Needed before the signature is promoted
01614 int Signature::getStackRegister(Prog* prog) throw(StackRegisterNotDefinedException) {
01615     MACHINE mach = prog->getMachine();
01616     switch (mach) {
01617         case MACHINE_SPARC:
01618             return 14;
01619         case MACHINE_PENTIUM:
01620             return 28;
01621         case MACHINE_PPC:
01622             return 1;
01623         case MACHINE_ST20:
01624             return 3;
01625         default:
01626             throw StackRegisterNotDefinedException();
01627     }
01628 }
01629 
01630 bool Signature::isStackLocal(Prog* prog, Exp *e) {
01631     // e must be m[...]
01632     if (e->isSubscript())
01633         return isStackLocal(prog, e->getSubExp1());
01634     if (!e->isMemOf()) return false;
01635     Exp* addr = ((Location*)e)->getSubExp1();
01636     return isAddrOfStackLocal(prog, addr);
01637 }
01638 
01639 bool Signature::isAddrOfStackLocal(Prog* prog, Exp *e) {
01640     OPER op = e->getOper();
01641     if (op == opAddrOf)
01642         return isStackLocal(prog, e->getSubExp1());
01643     // e must be sp -/+ K or just sp
01644     static Exp *sp = Location::regOf(getStackRegister(prog));
01645     if (op != opMinus && op != opPlus) {
01646         // Matches if e is sp or sp{0} or sp{-}
01647         return (*e == *sp ||
01648             e->isSubscript() && ((RefExp*)e)->isImplicitDef() && *((RefExp*)e)->getSubExp1() == *sp);
01649     }
01650     if (op == opMinus && !isLocalOffsetNegative()) return false;
01651     if (op == opPlus  && !isLocalOffsetPositive()) return false;
01652     Exp* sub1 = ((Binary*)e)->getSubExp1();
01653     Exp* sub2 = ((Binary*)e)->getSubExp2();
01654     // e must be <sub1> +- K
01655     if (!sub2->isIntConst()) return false;
01656     // first operand must be sp or sp{0} or sp{-}
01657     if (sub1->isSubscript()) {
01658         if (!((RefExp*)sub1)->isImplicitDef()) return false;
01659         sub1 = ((RefExp*)sub1)->getSubExp1();
01660     }
01661     return *sub1 == *sp;
01662 }
01663 
01664 // An override for the SPARC: [sp+0] .. [sp+88] are local variables (effectively), but [sp + >=92] are memory parameters
01665 bool CallingConvention::StdC::SparcSignature::isAddrOfStackLocal(Prog* prog, Exp* e) {
01666     OPER op = e->getOper();
01667     if (op == opAddrOf)
01668         return isStackLocal(prog, e->getSubExp1());
01669     // e must be sp -/+ K or just sp
01670     static Exp *sp = Location::regOf(14);
01671     if (op != opMinus && op != opPlus) {
01672         // Matches if e is sp or sp{0} or sp{-}
01673         return (*e == *sp ||
01674             e->isSubscript() && ((RefExp*)e)->isImplicitDef() && *((RefExp*)e)->getSubExp1() == *sp);
01675     }
01676     Exp* sub1 = ((Binary*)e)->getSubExp1();
01677     Exp* sub2 = ((Binary*)e)->getSubExp2();
01678     // e must be <sub1> +- K
01679     if (!sub2->isIntConst()) return false;
01680     // first operand must be sp or sp{0} or sp{-}
01681     if (sub1->isSubscript()) {
01682         if (!((RefExp*)sub1)->isImplicitDef()) return false;
01683         sub1 = ((RefExp*)sub1)->getSubExp1();
01684     }
01685     if (!(*sub1 == *sp)) return false;
01686     // SPARC specific test: K must be < 92; else it is a parameter
01687     int K = ((Const*)sub2)->getInt();
01688     return K < 92;
01689 }
01690 
01691 bool Parameter::operator==(Parameter& other) {
01692     if (!(*type == *other.type)) return false;
01693     // Do we really care about a parameter's name?
01694     if (!(name == other.name)) return false;
01695     if (!(*exp == *other.exp)) return false;
01696     return true;
01697 }
01698 
01699 //bool CallingConvention::StdC::HppaSignature::isLocalOffsetPositive() {
01700 //    return true;
01701 //}
01702 
01703 #if USING_MEMO
01704 class SignatureMemo : public Memo {
01705 public:
01706                 SignatureMemo(int m) : Memo(m) { }
01707 
01708     std::string name;       // name of procedure
01709     std::vector<Parameter*> params;
01710     // std::vector<ImplicitParameter*> implicitParams;
01711     Returns     returns;
01712     Type        *rettype;
01713     bool        ellipsis;
01714     Type        *preferedReturn;
01715     std::string preferedName;
01716     std::vector<int> preferedParams;
01717 };
01718 
01719 Memo *Signature::makeMemo(int mId)
01720 {
01721     SignatureMemo *m = new SignatureMemo(mId);
01722     m->name = name;
01723     m->params = params;
01724     // m->implicitParams = implicitParams;
01725     m->returns = returns;
01726     m->rettype = rettype;
01727     m->ellipsis = ellipsis;
01728     m->preferedReturn = preferedReturn;
01729     m->preferedName = preferedName;
01730     m->preferedParams = preferedParams;
01731 
01732     for (std::vector<Parameter*>::iterator it = params.begin(); it != params.end(); it++)
01733         (*it)->takeMemo(mId);
01734     // for (std::vector<ImplicitParameter*>::iterator it = implicitParams.begin(); it != implicitParams.end(); it++)
01735     //  (*it)->takeMemo(mId);
01736     for (Returns::iterator it = returns.begin(); it != returns.end(); it++)
01737         (*it)->takeMemo(mId);
01738     if (rettype)
01739         rettype->takeMemo(mId);
01740     if (preferedReturn)
01741         preferedReturn->takeMemo(mId);
01742     return m;
01743 }
01744 
01745 void Signature::readMemo(Memo *mm, bool dec)
01746 {
01747     SignatureMemo *m = dynamic_cast<SignatureMemo*>(mm);
01748 
01749     name = m->name;
01750     params = m->params;
01751     // implicitParams = m->implicitParams;
01752     returns = m->returns;
01753     rettype = m->rettype;
01754     ellipsis = m->ellipsis;
01755     preferedReturn = m->preferedReturn;
01756     preferedName = m->preferedName;
01757     preferedParams = m->preferedParams;
01758 
01759     for (std::vector<Parameter*>::iterator it = params.begin(); it != params.end(); it++)
01760         (*it)->restoreMemo(m->mId, dec);
01761     // for (std::vector<ImplicitParameter*>::iterator it = implicitParams.begin(); it != implicitParams.end(); it++)
01762     //  (*it)->restoreMemo(m->mId, dec);
01763     for (Returns::iterator it = returns.begin(); it != returns.end(); it++)
01764         (*it)->restoreMemo(m->mId, dec);
01765     if (rettype)
01766         rettype->restoreMemo(m->mId, dec);
01767     if (preferedReturn)
01768         preferedReturn->restoreMemo(m->mId, dec);
01769 }
01770 
01771 class ParameterMemo : public Memo {
01772 public:
01773     ParameterMemo(int m) : Memo(m) { }
01774 
01775     Type *type;
01776     std::string name;
01777     Exp *exp;
01778 };
01779 
01780 Memo *Parameter::makeMemo(int mId)
01781 {
01782     ParameterMemo *m = new ParameterMemo(mId);
01783 
01784     m->type = type;
01785     m->name = name;
01786     m->exp = exp;
01787 
01788     type->takeMemo(mId);
01789     exp->takeMemo(mId);
01790 
01791     return m;
01792 }
01793 
01794 void Parameter::readMemo(Memo *mm, bool dec)
01795 {
01796     ParameterMemo *m = dynamic_cast<ParameterMemo*>(mm);
01797     type = m->type;
01798     name = m->name;
01799     exp = m->exp;
01800 
01801     type->restoreMemo(m->mId, dec);
01802     exp->restoreMemo(m->mId, dec);
01803 }
01804 
01805 
01806 class ImplicitParameterMemo : public ParameterMemo {
01807 public:
01808     ImplicitParameterMemo(int m) : ParameterMemo(m) { }
01809 
01810     Parameter *parent;
01811 };
01812 
01813 Memo *ImplicitParameter::makeMemo(int mId)
01814 {
01815     ImplicitParameterMemo *m = new ImplicitParameterMemo(mId);
01816 
01817     m->type = getType();
01818     m->name = getName();
01819     m->exp = getExp();
01820     m->parent = parent;
01821 
01822     m->type->takeMemo(mId);
01823     m->exp->takeMemo(mId);
01824 
01825     return m;
01826 }
01827 
01828 void ImplicitParameter::readMemo(Memo *mm, bool dec)
01829 {
01830     ImplicitParameterMemo *m = dynamic_cast<ImplicitParameterMemo*>(mm);
01831     setType(m->type);
01832     setName(m->name.c_str());
01833     setExp(m->exp);
01834     parent = m->parent;
01835 
01836     m->type->restoreMemo(m->mId, dec);
01837     m->exp->restoreMemo(m->mId, dec);
01838 }
01839 #endif          // #if USING_MEMO
01840 
01841 bool Signature::isOpCompatStackLocal(OPER op) {
01842     if (op == opMinus) return isLocalOffsetNegative();
01843     if (op == opPlus) return isLocalOffsetPositive();
01844     return false;
01845 }
01846 
01847 bool Signature::returnCompare(Assignment& a, Assignment& b) {
01848     return *a.getLeft() < *b.getLeft();         // Default: sort by expression only, no explicit ordering
01849 }
01850 
01851 bool Signature::argumentCompare(Assignment& a, Assignment& b) {
01852     return *a.getLeft() < *b.getLeft();         // Default: sort by expression only, no explicit ordering
01853 }
01854 
01855 bool CallingConvention::StdC::PentiumSignature::returnCompare(Assignment& a, Assignment& b) {
01856     Exp* la = a.getLeft();
01857     Exp* lb = b.getLeft();
01858     // Eax is the preferred return location
01859     if (la->isRegN(24)) return true;        // r24 is less than anything
01860     if (lb->isRegN(24)) return false;       // Nothing is less than r24
01861 
01862     // Next best is r30 (floating point %st)
01863     if (la->isRegN(30)) return true;        // r30 is less than anything that's left
01864     if (lb->isRegN(30)) return false;       // Nothing left is less than r30
01865 
01866     // Else don't care about the order
01867     return *la < *lb;
01868 }
01869 
01870 static Unary spPlus64(opMemOf,
01871     new Binary(opPlus,
01872         Location::regOf(14),
01873         new Const(64)));
01874 bool CallingConvention::StdC::SparcSignature::returnCompare(Assignment& a, Assignment& b) {
01875     Exp* la = a.getLeft();
01876     Exp* lb = b.getLeft();
01877     // %o0 (r8) is the preferred return location
01878     if (la->isRegN(8)) return true;         // r24 is less than anything
01879     if (lb->isRegN(8)) return false;        // Nothing is less than r24
01880 
01881     // Next best is %f0 (r32)
01882     if (la->isRegN(32)) return true;        // r32 is less than anything that's left
01883     if (lb->isRegN(32)) return false;       // Nothing left is less than r32
01884 
01885     // Next best is %f0-1 (r64)
01886     if (la->isRegN(64)) return true;        // r64 is less than anything that's left
01887     if (lb->isRegN(64)) return false;       // Nothing left is less than r64
01888 
01889     // Next best is m[esp{-}+64]
01890     if (*la == spPlus64) return true;       // m[esp{-}+64] is less than anything that's left
01891     if (*lb == spPlus64) return false;      // Nothing left is less than m[esp{-}+64]
01892 
01893     // Else don't care about the order
01894     return *la < *lb;
01895 }
01896 
01897 // From m[sp +- K] return K (or -K for subtract). sp could be subscripted with {-}
01898 // Helper function for the below
01899 int stackOffset(Exp* e, int sp) {
01900     int ret = 0;
01901     if (e->isMemOf()) {
01902         Exp* sub = ((Location*)e)->getSubExp1();
01903         OPER op = sub->getOper();
01904         if (op == opPlus || op == opMinus) {
01905             Exp* op1 = ((Binary*)sub)->getSubExp1();
01906             if (op1->isSubscript())
01907                 op1 = ((RefExp*)op1)->getSubExp1();
01908             if (op1->isRegN(sp)) {
01909                 Exp* op2 = ((Binary*)sub)->getSubExp2();
01910                 if (op2->isIntConst())
01911                     ret = ((Const*)op2)->getInt();
01912                 if (op == opMinus)
01913                     ret = -ret;
01914             }
01915         }
01916     }
01917     return ret;
01918 }
01919 
01920 bool CallingConvention::StdC::PentiumSignature::argumentCompare(Assignment& a, Assignment& b) {
01921     Exp* la = a.getLeft();
01922     Exp* lb = b.getLeft();
01923     int ma = stackOffset(la, 28);
01924     int mb = stackOffset(lb, 28);
01925 
01926     if (ma && mb)
01927         return ma < mb;
01928     if (ma && !mb)
01929         return true;                        // m[sp-K] is less than anything else
01930     if (mb && !ma)
01931         return false;                       // Nothing else is less than m[sp-K]
01932 
01933     // Else don't care about the order
01934     return *la < *lb;
01935 }
01936 
01937 bool CallingConvention::StdC::SparcSignature::argumentCompare(Assignment& a, Assignment& b) {
01938     Exp* la = a.getLeft();
01939     Exp* lb = b.getLeft();
01940     // %o0-$o5 (r8-r13) are the preferred argument locations
01941     int ra = 0, rb = 0;
01942     if (la->isRegOf()) {
01943         int r = ((Const*)((Location*)la)->getSubExp1())->getInt();
01944         if (r >= 8 && r <= 13)
01945             ra = r;
01946     }
01947     if (lb->isRegOf()) {
01948         int r = ((Const*)((Location*)lb)->getSubExp1())->getInt();
01949         if (r >= 8 && r <= 13)
01950             rb = r;
01951     }
01952     if (ra && rb)
01953         return ra < rb;                     // Both r8-r13: compare within this set
01954     if (ra && rb == 0)
01955         return true;                        // r8-r13 less than anything else
01956     if (rb && ra == 0)
01957         return false;                       // Nothing else is less than r8-r13
01958 
01959     int ma = stackOffset(la, 30);
01960     int mb = stackOffset(lb, 30);
01961 
01962     if (ma && mb)
01963         return ma < mb;                     // Both m[sp + K]: order by memory offset
01964     if (ma && !mb)
01965         return true;                        // m[sp+K] less than anything left
01966     if (mb && !ma)
01967         return false;                       // nothing left is less than m[sp+K]
01968                 
01969     return *la < *lb;                       // Else order arbitrarily
01970 }
01971 
01972 // Class Return methods
01973 Return* Return::clone() {
01974     return new Return(type->clone(), exp->clone());
01975 }
01976 
01977 bool Return::operator==(Return& other) {
01978     if (!(*type == *other.type)) return false;
01979     if (!(*exp == *other.exp)) return false;
01980     return true;
01981 }
01982     
01983 #if USING_MEMO
01984 class ReturnMemo : public Memo {
01985 public:
01986     ReturnMemo(int m) : Memo(m) { }
01987 
01988     Type *type;
01989     Exp *exp;
01990 };
01991 
01992 Memo *Return::makeMemo(int mId)
01993 {
01994     ReturnMemo *m = new ReturnMemo(mId);
01995 
01996     m->type = type;
01997     m->exp = exp;
01998 
01999     type->takeMemo(mId);
02000     exp->takeMemo(mId);
02001 
02002     return m;
02003 }
02004 
02005 void Return::readMemo(Memo *mm, bool dec)
02006 {
02007     ReturnMemo *m = dynamic_cast<ReturnMemo*>(mm);
02008     type = m->type;
02009     exp = m->exp;
02010 
02011     type->restoreMemo(m->mId, dec);
02012     exp->restoreMemo(m->mId, dec);
02013 }
02014 #endif          // #if USING_MEMO
02015 
02016 Type* Signature::getTypeFor(Exp* e) {
02017     int n = returns.size();
02018     for (int i=0; i < n; ++i) {
02019         if (*returns[i]->exp == *e)
02020             return returns[i]->type;
02021     }
02022     return NULL;
02023 }

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