chllcode.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002-2006, 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 WARRANTIES.
00006  *
00007  */
00008 
00009 /*==============================================================================
00010  * FILE:       chllcode.cpp
00011  * OVERVIEW:   Concrete backend class for the "C" high level language
00012  *             This class is provides methods which are specific for the C language binding.
00013  *             I guess this will be the most popular output language unless we do C++.
00014  *============================================================================*/
00015 
00016 /*
00017  * $Revision: 1.128 $   // 1.90.2.16
00018  * 20 Jun 02 - Trent: Quick and dirty implementation for debugging
00019  * 28 Jun 02 - Trent: Starting to look better
00020  * 22 May 03 - Mike: delete -> free() to keep valgrind happy
00021  * 16 Apr 04 - Mike: char[] replaced by ostringstreams
00022  * 18 Jan 06 - Gerard: several changes for prettier output, better logging of warnings and errors
00023  */
00024 
00025 #include <assert.h>
00026 #if defined(_MSC_VER) && _MSC_VER <= 1200
00027 #pragma warning(disable:4786)
00028 #endif
00029 #if defined(_MSC_VER) && _MSC_VER >= 1400
00030 #pragma warning(disable:4996)       // Warnings about e.g. _strdup deprecated in VS 2005
00031 #endif
00032 
00033 #include "cfg.h"
00034 #include "statement.h"
00035 #include "exp.h"
00036 #include "proc.h"
00037 #include "prog.h"
00038 #include "hllcode.h"
00039 #include "chllcode.h"
00040 #include "signature.h"
00041 #include "boomerang.h"
00042 #include "type.h"
00043 #include "util.h"
00044 #include "log.h"
00045 #include <sstream>
00046 
00047 extern char *operStrings[];
00048 
00049 /// Empty constructor, calls HLLCode()
00050 CHLLCode::CHLLCode() : HLLCode()
00051 {   
00052 }
00053 
00054 /// Empty constructor, calls HLLCode(p)
00055 CHLLCode::CHLLCode(UserProc *p) : HLLCode(p)
00056 {   
00057 }
00058 
00059 /// Empty destructor
00060 CHLLCode::~CHLLCode()
00061 {
00062 }
00063 
00064 /// Output 4 * \a indLevel spaces to \a str
00065 void CHLLCode::indent(std::ostringstream& str, int indLevel) {
00066     // Can probably do more efficiently
00067     for (int i=0; i < indLevel; i++)
00068         str << "    ";
00069 }
00070 
00071 /**
00072  * Append code for the given expression \a exp to stream \a str.
00073  * 
00074  * \param str       The stream to output to.
00075  * \param ext       The expresson to output.
00076  * \param curPrec   The current operator precedence. Add parens around this expression if necessary.
00077  * \param uns       If true, cast operands to unsigned if necessary.
00078  *
00079  * \todo This function is 800+ lines, and should possibly be split up.
00080  */
00081 static int progress = 0;
00082 void CHLLCode::appendExp(std::ostringstream& str, Exp *exp, PREC curPrec, bool uns /* = false */ ) {
00083     if (exp == NULL) return;                // ?
00084 
00085     if (++progress > 500) {
00086         std::cerr << 'g' << std::flush;
00087         progress = 0;
00088     }
00089 
00090     OPER op = exp->getOper();
00091 
00092 #if SYMS_IN_BACK_END                // Should no longer be any unmapped symbols by the back end
00093     // Check if it's mapped to a symbol
00094     if (m_proc && !exp->isTypedExp()) {         // Beware: lookupSym will match (cast)r24 to local0, stripping the cast!
00095         char* sym = m_proc->lookupSym(exp);
00096         if (sym) {
00097             str << sym;
00098             return;
00099         }
00100     }
00101 #endif
00102 
00103     Const   *c = (Const*)exp;
00104     Unary   *u = (Unary*)exp;
00105     Binary  *b = (Binary*)exp;
00106     Ternary *t = (Ternary*)exp;
00107     
00108     switch(op) {
00109         case opIntConst: {
00110             int K = c->getInt();
00111             if (uns && K < 0) {
00112                 // An unsigned constant. Use some heuristics
00113                 unsigned rem = (unsigned)K % 100;
00114                 if (rem == 0 || rem == 99 || K > -128) {
00115                     // A multiple of 100, or one less; use 4000000000U style
00116                     char num[16];
00117                     sprintf(num, "%u", K);
00118                     str << num << "U";
00119                 } else {
00120                     // Output it in 0xF0000000 style
00121                     str << "0x" << std::hex << K;
00122                 }
00123             } else {
00124                 if (c->getType() && c->getType()->isChar()) {
00125                     if (c->getInt() == '\a')
00126                         str << "'\\a'";
00127                     else if (c->getInt() == '\b')
00128                         str << "'\\b'";
00129                     else if (c->getInt() == '\f')
00130                         str << "'\\f'";
00131                     else if (c->getInt() == '\n')
00132                         str << "'\\n'";
00133                     else if (c->getInt() == '\r')
00134                         str << "'\\r'";
00135                     else if (c->getInt() == '\t')
00136                         str << "'\\t'";
00137                     else if (c->getInt() == '\v')
00138                         str << "'\\v'";
00139                     else if (c->getInt() == '\\')
00140                         str << "'\\\\'";
00141                     else if (c->getInt() == '\?')
00142                         str << "'\\?'";
00143                     else if (c->getInt() == '\'')
00144                         str << "'\\''";
00145                     else if (c->getInt() == '\"')
00146                         str << "'\\\"'";
00147                     else
00148                         str << "'" << (char)c->getInt() << "'";
00149                 } else {
00150                     // More heuristics
00151                     int K = c->getInt();
00152                     if (-2048 < K && K < 2048)
00153                         str << std::dec << K;           // Just a plain vanilla int
00154                     else
00155                         str << "0x" << std::hex << K;   // 0x2000 style
00156                 }
00157             }
00158             break;
00159         }
00160         case opLongConst:
00161             //str << std::dec << c->getLong() << "LL"; break;
00162 #if defined(_MSC_VER) && _MSC_VER <= 1200   // tamlin:
00163             if ((__int64)c->getLong() < -1000i64 || (__int64)c->getLong() > 1000i64)
00164                 str << "0x" << std::hex << c->getLong() << std::dec << "i64";
00165             else
00166                 str << std::dec << c->getLong() << "i64";
00167 #else
00168             if ((long long)c->getLong() < -1000LL || (long long)c->getLong() > 1000LL)
00169                 str << "0x" << std::hex << c->getLong() << std::dec << "LL";
00170             else
00171                 str << std::dec << c->getLong() << "LL";
00172 #endif
00173             break;
00174         case opFltConst: {
00175             //str.precision(4);     // What to do with precision here? Would be nice to avoid 1.00000 or 0.99999
00176             std::ostringstream ost;
00177             ost << c->getFlt();
00178             std::string s = ost.str();
00179             str << s;
00180             if (s.find('.') == std::string::npos)
00181                 str << ".";         // Show that it is a float
00182             break;
00183         }
00184         case opStrConst:
00185             // escape string:
00186             str << "\"" << escapeStr(c->getStr()) << "\"";
00187             break;
00188         case opFuncConst:
00189             str << c->getFuncName(); break;
00190         case opAddrOf: {
00191             Exp* sub = u->getSubExp1();
00192 #if 0       // Suspect only ADHOC TA
00193             if (sub->getType() && sub->getType()->isArray()) {
00194                 appendExp(str, sub, curPrec);
00195                 break;
00196             }
00197 #endif
00198             if (sub->isGlobal()) {
00199                 Prog* prog = m_proc->getProg();
00200                 Const* con = (Const*)((Unary*)sub)->getSubExp1();
00201                 Type* gt = prog->getGlobalType(con->getStr());
00202                 if (gt && (gt->isArray() || (gt->isPointer() && gt->asPointer()->getPointsTo()->isChar()))) {
00203                     // Special C requirement: don't emit "&" for address of an array or char*
00204                     appendExp(str, sub, curPrec);
00205                     break;
00206                 }
00207             }
00208 #if SYMS_IN_BACK_END
00209             if (sub->isMemOf() && m_proc->lookupSym(sub) == NULL) { // }
00210 #else
00211             if (sub->isMemOf()) {
00212 #endif
00213 
00214                 // Avoid &*(type*)sub, just emit sub
00215                 appendExp(str, sub->getSubExp1(), PREC_UNARY);
00216             } else {
00217                 openParen(str, curPrec, PREC_UNARY);
00218                 str << "&";
00219                 appendExp(str, sub, PREC_UNARY);
00220                 closeParen(str, curPrec, PREC_UNARY);
00221             }
00222             break;
00223         }
00224         case opParam:
00225         case opGlobal:
00226         case opLocal:
00227             c = dynamic_cast<Const*>(u->getSubExp1());
00228             assert(c && c->getOper() == opStrConst);
00229             str << c->getStr();
00230             break;
00231         case opEquals:
00232             {
00233                 openParen(str, curPrec, PREC_EQUAL);
00234                 appendExp(str, b->getSubExp1(), PREC_EQUAL);
00235                 str << " == ";
00236 #if 0           // Suspect only for ADHOC TA
00237                 Type *ty = b->getSubExp1()->getType();
00238                 if (ty && ty->isPointer() && b->getSubExp2()->isIntConst() && ((Const*)b->getSubExp2())->getInt() == 0)
00239                     str << "NULL";
00240                 else
00241 #endif
00242                     appendExp(str, b->getSubExp2(), PREC_EQUAL);                
00243                 closeParen(str, curPrec, PREC_EQUAL);
00244             }
00245             break;
00246         case opNotEqual:
00247             {
00248                 openParen(str, curPrec, PREC_EQUAL);
00249                 appendExp(str, b->getSubExp1(), PREC_EQUAL);
00250                 str << " != ";
00251 #if 0           // Suspect only for ADHOC_TA
00252                 Type *ty = b->getSubExp1()->getType();
00253                 if (ty && ty->isPointer() && b->getSubExp2()->isIntConst() && ((Const*)b->getSubExp2())->getInt() == 0)
00254                     str << "NULL";
00255                 else
00256 #endif
00257                     appendExp(str, b->getSubExp2(), PREC_EQUAL);
00258                 closeParen(str, curPrec, PREC_EQUAL);
00259             }
00260             break;
00261         case opLess:
00262         case opLessUns:
00263             openParen(str, curPrec, PREC_REL);
00264             appendExp(str, b->getSubExp1(), PREC_REL, op == opLessUns);
00265             str << " < ";
00266             appendExp(str, b->getSubExp2(), PREC_REL, op == opLessUns);
00267             closeParen(str, curPrec, PREC_REL);
00268             break;
00269         case opGtr:
00270         case opGtrUns:
00271             openParen(str, curPrec, PREC_REL);
00272             appendExp(str, b->getSubExp1(), PREC_REL, op == opGtrUns);
00273             str << " > ";
00274             appendExp(str, b->getSubExp2(), PREC_REL, op == opGtrUns);
00275             closeParen(str, curPrec, PREC_REL);
00276             break;
00277         case opLessEq:
00278         case opLessEqUns:
00279             openParen(str, curPrec, PREC_REL);
00280             appendExp(str, b->getSubExp1(), PREC_REL, op == opLessEqUns);
00281             str << " <= ";
00282             appendExp(str, b->getSubExp2(), PREC_REL, op == opLessEqUns);
00283             closeParen(str, curPrec, PREC_REL);
00284             break;
00285         case opGtrEq:
00286         case opGtrEqUns:
00287             openParen(str, curPrec, PREC_REL);
00288             appendExp(str, b->getSubExp1(), PREC_REL, op == opGtrEqUns);
00289             str << " >= ";
00290             appendExp(str, b->getSubExp2(), PREC_REL, op == opGtrEqUns);
00291             closeParen(str, curPrec, PREC_REL);
00292             break;
00293         case opAnd:
00294             openParen(str, curPrec, PREC_LOG_AND);
00295             appendExp(str, b->getSubExp1(), PREC_LOG_AND);
00296             str << " && ";
00297             appendExp(str, b->getSubExp2(), PREC_LOG_AND);
00298             closeParen(str, curPrec, PREC_LOG_AND);
00299             break;
00300         case opOr:
00301             openParen(str, curPrec, PREC_LOG_OR);
00302             appendExp(str, b->getSubExp1(), PREC_LOG_OR);
00303             str << " || ";
00304             appendExp(str, b->getSubExp2(), PREC_LOG_OR);
00305             closeParen(str, curPrec, PREC_LOG_OR);
00306             break;
00307         case opBitAnd:
00308             openParen(str, curPrec, PREC_BIT_AND);
00309             appendExp(str, b->getSubExp1(), PREC_BIT_AND);
00310             str << " & ";
00311             if (b->getSubExp2()->getOper() == opIntConst) {
00312                 // print it 0x2000 style
00313                 str << "0x" << std::hex << ((Const*)b->getSubExp2())->getInt();
00314             } else {
00315                 appendExp(str, b->getSubExp2(), PREC_BIT_AND);
00316             }
00317             closeParen(str, curPrec, PREC_BIT_AND);
00318             break;
00319         case opBitOr:
00320             openParen(str, curPrec, PREC_BIT_IOR);
00321             appendExp(str, b->getSubExp1(), PREC_BIT_IOR);
00322             str << " | ";
00323             appendExp(str, b->getSubExp2(), PREC_BIT_IOR);
00324             closeParen(str, curPrec, PREC_BIT_IOR);
00325             break;
00326         case opBitXor:
00327             openParen(str, curPrec, PREC_BIT_XOR);
00328             appendExp(str, b->getSubExp1(), PREC_BIT_XOR);
00329             str << " ^ ";
00330             appendExp(str, b->getSubExp2(), PREC_BIT_XOR);
00331             closeParen(str, curPrec, PREC_BIT_XOR);
00332             break;
00333         case opNot:
00334             openParen(str, curPrec, PREC_UNARY);
00335             str << " !";
00336             appendExp(str, u->getSubExp1(), PREC_UNARY);
00337             closeParen(str, curPrec, PREC_UNARY);
00338             break;
00339         case opLNot:
00340             openParen(str, curPrec, PREC_UNARY);
00341             appendExp(str, u->getSubExp1(), PREC_UNARY);
00342             closeParen(str, curPrec, PREC_UNARY);
00343             break;
00344         case opNeg:
00345         case opFNeg:
00346             openParen(str, curPrec, PREC_UNARY);
00347             appendExp(str, u->getSubExp1(), PREC_UNARY);
00348             closeParen(str, curPrec, PREC_UNARY);
00349             break;
00350         case opAt:
00351         {
00352             // I guess that most people will find this easier to read
00353             // s1 >> last & 0xMASK
00354             openParen(str, curPrec, PREC_BIT_AND);
00355             appendExp(str, t->getSubExp1(), PREC_BIT_SHIFT);
00356             Const* first = (Const*) t->getSubExp2();
00357             Const* last = (Const*) t->getSubExp3();
00358             str << " >> ";
00359             appendExp(str, last, PREC_BIT_SHIFT);
00360             str << " & ";
00361             
00362             unsigned int mask = (1 << (first->getInt() - last->getInt() + 1)) - 1;
00363             if ( mask < 10)
00364                 // print 0x3 as 3
00365                 str << mask;
00366             else {
00367                 str << "0x" << std::hex << mask;
00368             }
00369             closeParen(str, curPrec, PREC_BIT_AND);     
00370             break;
00371         }
00372         case opPlus:
00373             openParen(str, curPrec, PREC_ADD);
00374             appendExp(str, b->getSubExp1(), PREC_ADD);
00375             str << " + ";
00376             appendExp(str, b->getSubExp2(), PREC_ADD);
00377             closeParen(str, curPrec, PREC_ADD);
00378             break;
00379         case opMinus:
00380             openParen(str, curPrec, PREC_ADD);
00381             appendExp(str, b->getSubExp1(), PREC_ADD);
00382             str << " - ";
00383             appendExp(str, b->getSubExp2(), PREC_ADD);
00384             closeParen(str, curPrec, PREC_ADD);
00385             break;
00386         case opMemOf:
00387             if (Boomerang::get()->noDecompile) {
00388                 str << "MEMOF(";
00389                 appendExp(str, u->getSubExp1(), PREC_NONE);
00390                 str << ")";
00391                 break;
00392             }
00393             openParen(str, curPrec, PREC_UNARY);
00394             // annotateMemofs should have added a cast if it was needed
00395             str << "*";
00396             appendExp(str, u->getSubExp1(), PREC_UNARY);
00397             closeParen(str, curPrec, PREC_UNARY);
00398             break;
00399         case opRegOf:
00400             {
00401                 // MVE: this can likely go
00402                 if (VERBOSE)
00403                     LOG << "WARNING: CHLLCode::appendExp: case opRegOf is deprecated\n";
00404                 if (u->getSubExp1()->getOper() == opTemp) {
00405                     // The great debate: r[tmpb] vs tmpb
00406                     str << "tmp";
00407                     break;
00408                 }
00409                 assert(u->getSubExp1()->getOper() == opIntConst);
00410                 const char *n = m_proc->getProg()->getRegName(
00411                                     ((Const*)u->getSubExp1())->getInt());
00412                 if (n) {
00413                     if (n[0] == '%')
00414                         str << n+1;
00415                     else
00416                         str << n;
00417                 } else {
00418 // What is this doing in the back end???
00419                     str << "r[";
00420                     appendExp(str, u->getSubExp1(), PREC_NONE);
00421                     str << "]";
00422                 }
00423             }
00424             break;
00425         case opTemp:
00426             // Should never see this; temps should be mapped to locals now so that they get declared
00427             if (VERBOSE)
00428                 LOG << "WARNING: CHLLCode::appendExp: case opTemp is deprecated\n";
00429             // Emit the temp name, e.g. "tmp1"
00430             str << ((Const*)u->getSubExp1())->getStr();
00431             break;
00432         case opItof:
00433             // MVE: needs work: float/double/long double.
00434             str << "(float)";
00435             openParen(str, curPrec, PREC_UNARY);
00436             appendExp(str, t->getSubExp3(), PREC_UNARY);
00437             closeParen(str, curPrec, PREC_UNARY);
00438             break;
00439         case opFsize:
00440    // MVE: needs work!
00441             if (Boomerang::get()->noDecompile && t->getSubExp3()->isMemOf()) {
00442                 assert(t->getSubExp1()->isIntConst());
00443                 if (((Const*)t->getSubExp1())->getInt() == 32)
00444                     str << "FLOAT_MEMOF(";
00445                 else
00446                     str << "DOUBLE_MEMOF(";
00447                 appendExp(str, t->getSubExp3()->getSubExp1(), PREC_NONE);
00448                 str << ")";
00449                 break;
00450             }
00451             appendExp(str, t->getSubExp3(), curPrec);
00452             break;
00453         case opMult:
00454         case opMults:       // FIXME: check types
00455             openParen(str, curPrec, PREC_MULT);
00456             appendExp(str, b->getSubExp1(), PREC_MULT);
00457             str << " * ";
00458             appendExp(str, b->getSubExp2(), PREC_MULT);
00459             closeParen(str, curPrec, PREC_MULT);
00460             break;
00461         case opDiv:
00462         case opDivs:        // FIXME: check types
00463             openParen(str, curPrec, PREC_MULT);
00464             appendExp(str, b->getSubExp1(), PREC_MULT);
00465             str << " / ";
00466             appendExp(str, b->getSubExp2(), PREC_MULT);
00467             closeParen(str, curPrec, PREC_MULT);
00468             break;
00469         case opMod:
00470         case opMods:        // Fixme: check types
00471             openParen(str, curPrec, PREC_MULT);
00472             appendExp(str, b->getSubExp1(), PREC_MULT);
00473             str << " % ";
00474             appendExp(str, b->getSubExp2(), PREC_MULT);
00475             closeParen(str, curPrec, PREC_MULT);
00476             break;
00477         case opShiftL:
00478             openParen(str, curPrec, PREC_BIT_SHIFT);
00479             appendExp(str, b->getSubExp1(), PREC_BIT_SHIFT);
00480             str << " << ";
00481             appendExp(str, b->getSubExp2(), PREC_BIT_SHIFT);
00482             closeParen(str, curPrec, PREC_BIT_SHIFT);
00483             break;
00484         case opShiftR:
00485         case opShiftRA:
00486             openParen(str, curPrec, PREC_BIT_SHIFT);
00487             appendExp(str, b->getSubExp1(), PREC_BIT_SHIFT);
00488             str << " >> ";
00489             appendExp(str, b->getSubExp2(), PREC_BIT_SHIFT);
00490             closeParen(str, curPrec, PREC_BIT_SHIFT);
00491             break;
00492         case opTern:
00493             openParen(str, curPrec, PREC_COND);
00494             str << " (";
00495             appendExp(str, t->getSubExp1(), PREC_NONE);
00496             str << ") ? ";
00497             appendExp(str, t->getSubExp2(), PREC_COND);
00498             str << " : ";
00499             appendExp(str, t->getSubExp3(), PREC_COND);
00500             closeParen(str, curPrec, PREC_COND);
00501             break;
00502         case opFPlus:
00503         case opFPlusd:
00504         case opFPlusq:
00505             openParen(str, curPrec, PREC_ADD);
00506             appendExp(str, b->getSubExp1(), PREC_ADD);
00507             str << " + ";
00508             appendExp(str, b->getSubExp2(), PREC_ADD);
00509             closeParen(str, curPrec, PREC_ADD);
00510             break;
00511         case opFMinus:
00512         case opFMinusd:
00513         case opFMinusq:
00514             openParen(str, curPrec, PREC_ADD);
00515             appendExp(str, b->getSubExp1(), PREC_ADD);
00516             str << " - ";
00517             appendExp(str, b->getSubExp2(), PREC_ADD);
00518             closeParen(str, curPrec, PREC_ADD);
00519             break;
00520         case opFMult:
00521         case opFMultd:
00522         case opFMultq:
00523             openParen(str, curPrec, PREC_MULT);
00524             appendExp(str, b->getSubExp1(), PREC_MULT);
00525             str << " * ";
00526             appendExp(str, b->getSubExp2(), PREC_MULT);
00527             closeParen(str, curPrec, PREC_MULT);
00528             break;
00529         case opFDiv:
00530         case opFDivd:
00531         case opFDivq:
00532             openParen(str, curPrec, PREC_MULT);
00533             appendExp(str, b->getSubExp1(), PREC_MULT);
00534             str << " / ";
00535             appendExp(str, b->getSubExp2(), PREC_MULT);
00536             closeParen(str, curPrec, PREC_MULT);
00537             break;
00538         case opFround:
00539             // Note: we need roundf or roundl depending on size of operands
00540             str << "round(";        // Note: math.h required
00541             appendExp(str, u->getSubExp1(), PREC_NONE);
00542             str << ")";
00543             break;
00544         case opFtrunc:
00545             // Note: we need truncf or truncl depending on size of operands
00546             str << "trunc(";        // Note: math.h required
00547             appendExp(str, u->getSubExp1(), PREC_NONE);
00548             str << ")";
00549             break;
00550         case opFabs:
00551             str << "fabs(";
00552             appendExp(str, u->getSubExp1(), PREC_NONE);
00553             str << ")";
00554             break;
00555         case opFtoi:
00556             // Should check size!
00557             str << "(int)";
00558             appendExp(str, u->getSubExp3(), PREC_UNARY);
00559             break;
00560         case opRotateL:
00561         str << "ROTL(";
00562             appendExp(str, u->getSubExp1(), PREC_UNARY);
00563         str << ")";
00564         break;
00565         case opRotateR:
00566         str << "ROTR(";
00567             appendExp(str, u->getSubExp1(), PREC_UNARY);
00568         str << ")";
00569         break;
00570         case opRotateLC:
00571         str << "ROTLC(";
00572             appendExp(str, u->getSubExp1(), PREC_UNARY);
00573         str << ")";
00574         break;
00575         case opRotateRC:
00576         str << "ROTRC(";
00577             appendExp(str, u->getSubExp1(), PREC_UNARY);
00578         str << ")";
00579         break;
00580         case opSize:
00581             {
00582                 /*Type *ty = new IntegerType(((Const*)b->getSubExp1())->getInt(), 1);
00583                 str << "*(" << ty->getCtype(true) << " *)";
00584                 appendExp(str, new Unary(opAddrOf, b->getSubExp2()), PREC_UNARY);*/
00585                 appendExp(str, b->getSubExp2(), PREC_UNARY);
00586             }
00587             break;
00588         case opFMultsd:
00589         case opFMultdq:
00590         case opSQRTs:
00591         case opSQRTd:
00592         case opSQRTq:
00593         case opSignExt:
00594         case opTargetInst:
00595         case opNamedExp:
00596         case opGuard:
00597         case opVar:
00598         case opArg:
00599         case opExpand:      
00600         case opCastIntStar:
00601         case opPostVar:
00602         case opForceInt:
00603         case opForceFlt:
00604         case opFpush:
00605         case opFpop:
00606         case opLoge:
00607         case opSqrt:
00608         case opExecute:
00609         case opAFP:
00610         case opAGP:
00611             // not implemented
00612             LOG << "WARNING: CHLLCode::appendExp: case " << operStrings[exp->getOper()] << " not implemented\n";
00613             //assert(false);
00614             break;
00615         case opFlagCall:
00616             {
00617                 assert(b->getSubExp1()->getOper() == opStrConst);
00618                 str << ((Const*)b->getSubExp1())->getStr();
00619                 str << "(";
00620                 Binary *l = (Binary*)b->getSubExp2();
00621                 for (; l && l->getOper() == opList; 
00622                      l = (Binary*)l->getSubExp2()) {
00623                     appendExp(str, l->getSubExp1(), PREC_NONE);
00624                     if (l->getSubExp2()->getOper() == opList)
00625                         str << ", ";
00626                 }
00627                 str << ")";
00628             } 
00629             break;
00630         case opList:
00631             {
00632                 int elems_on_line = 0; // try to limit line lengths
00633                 Exp* e2 = b->getSubExp2();
00634                 str << "{ ";
00635                 if (b->getSubExp1()->getOper() == opList)
00636                     str << "\n ";
00637                 while (e2->getOper() == opList)
00638                 {
00639                     appendExp(str, b->getSubExp1(), PREC_NONE, uns);
00640                     ++elems_on_line;
00641                     if (b->getSubExp1()->getOper() == opList || elems_on_line >= 16 /* completely arbitrary, but better than nothing*/)
00642                     {
00643                         str << ",\n ";
00644                         elems_on_line = 0;
00645                     } else {
00646                         str << ", ";
00647                     }
00648                     b = static_cast<Binary*>(e2);
00649                     e2 = b->getSubExp2();
00650                 }
00651                 appendExp(str, b->getSubExp1(), PREC_NONE, uns);
00652                 str << " }";
00653             }
00654             break;
00655         case opFlags:
00656             str << "flags"; break;
00657         case opPC:
00658             str << "pc"; break;
00659             break;
00660         case opZfill:
00661             // MVE: this is a temporary hack... needs cast?
00662             //sprintf(s, "/* zfill %d->%d */ ",
00663             //  ((Const*)t->getSubExp1())->getInt(),
00664             //  ((Const*)t->getSubExp2())->getInt());
00665             //strcat(str, s); */
00666             if (t->getSubExp3()->isMemOf() && 
00667                     t->getSubExp1()->isIntConst() &&
00668                     t->getSubExp2()->isIntConst() &&
00669                     ((Const*)t->getSubExp2())->getInt() == 32) {
00670                 unsigned sz = (unsigned)((Const*)t->getSubExp1())->getInt();
00671                 if (sz == 8 || sz == 16) {
00672                     bool close = false;
00673                     str << "*";
00674 #if 0               // Suspect ADHOC TA only
00675                     Type *ty = t->getSubExp3()->getSubExp1()->getType();
00676                     if (ty == NULL || !ty->isPointer() || 
00677                             !ty->asPointer()->getPointsTo()->isInteger() ||
00678                             ty->asPointer()->getPointsTo()->asInteger()->getSize() != sz) {
00679 #endif
00680                         str << "(unsigned ";
00681                         if (sz == 8)
00682                             str << "char";
00683                         else 
00684                             str << "short";
00685                         str << "*)";
00686                         openParen(str, curPrec, PREC_UNARY);
00687                         close = true;
00688 #if 0       // ADHOC TA as above
00689                     }
00690 #endif
00691                     appendExp(str, t->getSubExp3()->getSubExp1(), PREC_UNARY);
00692                     if (close)
00693                         closeParen(str, curPrec, PREC_UNARY);
00694                     break;
00695                 }
00696             }
00697             if (VERBOSE)
00698                 LOG << "WARNING: CHLLCode::appendExp: case opZfill is deprecated\n";
00699             str << "(";
00700             appendExp(str, t->getSubExp3(), PREC_NONE);
00701             str << ")";
00702             break;
00703 
00704         case opTypedExp: {
00705 #if SYMS_IN_BACK_END
00706             Exp* b = u->getSubExp1();                   // Base expression
00707             char* sym = m_proc->lookupSym(exp);         // Check for (cast)sym
00708             if (sym) {
00709                 str << "(";
00710                 appendType(str, ((TypedExp*)u)->getType());
00711                 str << ")" << sym;
00712                 break;
00713             }
00714 #endif
00715             if (u->getSubExp1()->getOper() == opTypedExp &&
00716                     *((TypedExp*)u)->getType() == *((TypedExp*)u->getSubExp1())->getType()) {
00717                 // We have (type)(type)x: recurse with type(x)
00718                 appendExp(str, u->getSubExp1(), curPrec);
00719             } else if (u->getSubExp1()->getOper() == opMemOf) {
00720                 // We have (tt)m[x]
00721 #if 0           // ADHOC TA
00722                 PointerType *pty = dynamic_cast<PointerType*>(u->getSubExp1()->getSubExp1()->getType());
00723 #else
00724                 PointerType* pty = NULL;
00725 #endif
00726                 // pty = T(x)
00727                 Type *tt = ((TypedExp*)u)->getType();
00728                 if (pty != NULL && (*pty->getPointsTo() == *tt ||
00729                         (tt->isSize() && pty->getPointsTo()->getSize() == tt->getSize())))
00730                     str << "*";
00731                 else {
00732                     if (Boomerang::get()->noDecompile) {
00733                         if (tt && tt->isFloat()) {
00734                             if (tt->asFloat()->getSize() == 32)
00735                                 str << "FLOAT_MEMOF";
00736                             else
00737                                 str << "DOUBLE_MEMOF";
00738                         } else 
00739                             str << "MEMOF";
00740                     } else {
00741                         str << "*(";
00742                         appendType(str, tt);
00743                         str << "*)";
00744                     }
00745                 }
00746                 openParen(str, curPrec, PREC_UNARY);
00747                 // Emit x
00748                 appendExp(str, ((Location*)((TypedExp*)u)->getSubExp1())->getSubExp1(), PREC_UNARY);
00749                 closeParen(str, curPrec, PREC_UNARY);
00750             } else {
00751                 // Check for (tt)b where tt is a pointer; could be &local
00752                 Type* tt = ((TypedExp*)u)->getType();
00753                 if (dynamic_cast<PointerType*>(tt)) {
00754 #if SYMS_IN_BACK_END
00755                     char* sym = m_proc->lookupSym(Location::memOf(b));
00756                     if (sym) {
00757                         openParen(str, curPrec, PREC_UNARY);
00758                         str << "&" << sym;
00759                         closeParen(str, curPrec, PREC_UNARY);
00760                         break;
00761                     }
00762 #endif
00763                 }
00764                 // Otherwise, fall back to (tt)b
00765                 str << "(";
00766                 appendType(str, tt);
00767                 str << ")";
00768                 openParen(str, curPrec, PREC_UNARY);
00769                 appendExp(str, u->getSubExp1(), PREC_UNARY);
00770                 closeParen(str, curPrec, PREC_UNARY);
00771             }
00772             break;
00773         }
00774         case opSgnEx: 
00775         case opTruncs: {
00776             Exp* s = t->getSubExp3();
00777             int toSize = ((Const*)t->getSubExp2())->getInt();
00778             switch (toSize) {
00779                 case 8:     str << "(char) "; break;
00780                 case 16:    str << "(short) "; break;
00781                 case 64:    str << "(long long) "; break;
00782                 default:    str << "(int) "; break;
00783             }
00784             appendExp(str, s, curPrec);
00785             break;
00786         }
00787         case opTruncu: {
00788             Exp* s = t->getSubExp3();
00789             int toSize = ((Const*)t->getSubExp2())->getInt();
00790             switch (toSize) {
00791                 case 8:     str << "(unsigned char) "; break;
00792                 case 16:    str << "(unsigned short) "; break;
00793                 case 64:    str << "(unsigned long long) "; break;
00794                 default:    str << "(unsigned int) "; break;
00795             }
00796             appendExp(str, s, curPrec);
00797             break;
00798         }
00799         case opMachFtr: {
00800             str << "/* machine specific */ (int) ";
00801             Exp* sub = u->getSubExp1();
00802             assert(sub->isStrConst());
00803             char* s = ((Const*)sub)->getStr();
00804             if (s[0] == '%')        // e.g. %Y
00805                 str << s+1;         // Just use Y
00806             else
00807                 str << s;
00808             break;
00809         }
00810         case opFflags:
00811             str << "/* Fflags() */ "; break;
00812         case opPow:
00813             str << "pow(";
00814             appendExp(str, b->getSubExp1(), PREC_COMMA);
00815             str << ", ";
00816             appendExp(str, b->getSubExp2(), PREC_COMMA);
00817             str << ")";
00818             break;
00819         case opLog2:
00820             str << "log2(";
00821             appendExp(str, u->getSubExp1(), PREC_NONE);
00822             str << ")";
00823             break;
00824         case opLog10:
00825             str << "log10(";
00826             appendExp(str, u->getSubExp1(), PREC_NONE);
00827             str << ")";
00828             break;
00829         case opSin:
00830             str << "sin(";
00831             appendExp(str, u->getSubExp1(), PREC_NONE);
00832             str << ")";
00833             break;
00834         case opCos:
00835             str << "cos(";
00836             appendExp(str, u->getSubExp1(), PREC_NONE);
00837             str << ")";
00838             break;
00839         case opTan:
00840             str << "tan(";
00841             appendExp(str, u->getSubExp1(), PREC_NONE);
00842             str << ")";
00843             break;
00844         case opArcTan:
00845             str << "atan(";
00846             appendExp(str, u->getSubExp1(), PREC_NONE);
00847             str << ")";
00848             break;
00849         case opSubscript:
00850             appendExp(str, u->getSubExp1(), curPrec);
00851             if (VERBOSE)
00852                 LOG << "ERROR: CHLLCode::appendExp: subscript in code generation of proc " <<
00853                     m_proc->getName() << " exp (without subscript): " << str.str().c_str()
00854                     << "\n";
00855             //assert(false);
00856             break;
00857         case opMemberAccess:
00858             {
00859 #if 0           // ADHOC TA
00860                 Type *ty = b->getSubExp1()->getType();
00861 #else
00862                 Type* ty = NULL;
00863 #endif
00864                 if (ty == NULL) {
00865                     LOG << "type failure: no type for subexp1 of " << b << "\n";
00866                     //ty = b->getSubExp1()->getType();
00867                     // No idea why this is hitting! - trentw
00868                     // str << "/* type failure */ ";
00869                     // break;
00870                 }
00871                 // Trent: what were you thinking here? Fails for things like
00872                 // local11.lhHeight (where local11 is a register)
00873                 // Mike: it shouldn't!  local11 should have a compound type
00874                 //assert(ty->resolvesToCompound());
00875                 if (b->getSubExp1()->getOper() == opMemOf) {
00876                     appendExp(str, b->getSubExp1()->getSubExp1(), PREC_PRIM);
00877                     str << "->";
00878                 } else {
00879                     appendExp(str, b->getSubExp1(), PREC_PRIM);
00880                     str << ".";
00881                 }
00882                 str << ((Const*)b->getSubExp2())->getStr();
00883             }
00884             break;
00885         case opArrayIndex:
00886             openParen(str, curPrec, PREC_PRIM);
00887             if (b->getSubExp1()->isMemOf()) {
00888 #if 0           // ADHOC TA
00889                 Type *ty = b->getSubExp1()->getSubExp1()->getType();
00890 #else
00891                 Type* ty = NULL;
00892 #endif
00893                 if (ty && ty->resolvesToPointer() && 
00894                         ty->asPointer()->getPointsTo()->resolvesToArray()) {
00895                     // a pointer to an array is automatically dereferenced in C
00896                     appendExp(str, b->getSubExp1()->getSubExp1(), PREC_PRIM);
00897                 } else
00898                     appendExp(str, b->getSubExp1(), PREC_PRIM);
00899             } else
00900                 appendExp(str, b->getSubExp1(), PREC_PRIM);
00901             closeParen(str, curPrec, PREC_PRIM);
00902             str << "[";
00903             appendExp(str, b->getSubExp2(), PREC_PRIM);
00904             str << "]";
00905             break;
00906         case opDefineAll:
00907             str << "<all>";
00908             if (VERBOSE)
00909                 LOG << "ERROR: should not see opDefineAll in codegen\n";
00910             break;
00911         default:
00912             // others
00913             OPER op = exp->getOper();
00914             if (op >= opZF) {
00915                 // Machine flags; can occasionally be manipulated individually
00916                 // Chop off the "op" part
00917                 str << operStrings[op]+2;
00918                 break;
00919             }
00920             LOG << "ERROR: CHLLCode::appendExp: case " << operStrings[op] << " not implemented\n";
00921             //assert(false);
00922     }
00923 
00924 }
00925 
00926 /// Print the type represented by \a typ to \a str.
00927 void CHLLCode::appendType(std::ostringstream& str, Type *typ)
00928 {
00929     if (typ == NULL) {
00930         str << "int";           // Default type for C
00931         return;
00932     }
00933     if (typ->resolvesToPointer() && 
00934             typ->asPointer()->getPointsTo()->resolvesToArray()) {
00935         // C programmers prefer to see pointers to arrays as pointers
00936         // to the first element of the array.  They then use syntactic
00937         // sugar to access a pointer as if it were an array.
00938         typ = new PointerType(typ->asPointer()->getPointsTo()->asArray()->getBaseType());
00939     }
00940     str << typ->getCtype(true);
00941 }
00942 
00943 /**
00944  * Print the indented type to \a str.
00945  */
00946 void CHLLCode::appendTypeIdent(std::ostringstream& str, Type *typ, const char *ident) {
00947     if (typ == NULL) return;
00948     if (typ->isPointer() && typ->asPointer()->getPointsTo()->isArray()) {
00949         appendType(str, typ->asPointer()->getPointsTo()->asArray()->getBaseType());
00950         str << " *" << ident;
00951     } else if (typ->isPointer()) {
00952         appendType(str, typ);
00953         str << ident;
00954     } else if (typ->isArray()) {
00955         ArrayType *a = typ->asArray();
00956         appendTypeIdent(str, a->getBaseType(), ident);
00957         str << "[";
00958         if (!a->isUnbounded())
00959             str << a->getLength();
00960         str << "]";
00961     } else if (typ->isVoid()) {
00962         // Can happen in e.g. twoproc, where really need global parameter and return analysis
00963 #if 1 // TMN: Stop crashes by this workaround
00964         if (ident == NULL) {
00965             static const char szFoo[] = "unknownVoidType";
00966             ident = szFoo;
00967         }
00968 #endif
00969         LOG << "WARNING: CHLLCode::appendTypeIdent: declaring type void as int for " << ident << "\n";
00970         str << "int " << ident;
00971     } else {
00972         appendType(str, typ);
00973         str << " " << (ident ? ident : "<null>");
00974     }   
00975 }
00976 
00977 /// Remove all generated code.
00978 void CHLLCode::reset() {
00979     lines.clear();
00980 }
00981 
00982 /// Adds: while( \a cond) {
00983 void CHLLCode::AddPretestedLoopHeader(int indLevel, Exp *cond) {
00984     std::ostringstream s;
00985     indent(s, indLevel);
00986     s << "while (";
00987     appendExp(s, cond, PREC_NONE);
00988     s << ") {";
00989     // Note: removing the strdup() causes weird problems.
00990     // Looks to me that it should work (with no real operator delete(),
00991     // and garbage collecting...
00992     appendLine(s);
00993 }
00994 
00995 /// Adds: }
00996 void CHLLCode::AddPretestedLoopEnd(int indLevel) {
00997     std::ostringstream s;
00998     indent(s, indLevel);
00999     s << "}";
01000     appendLine(s);
01001 }
01002 
01003 /// Adds: for(;;) {
01004 void CHLLCode::AddEndlessLoopHeader(int indLevel) {
01005     std::ostringstream s;
01006     indent(s, indLevel);
01007     s << "for(;;) {";
01008     appendLine(s);
01009 }
01010 
01011 /// Adds: }
01012 void CHLLCode::AddEndlessLoopEnd(int indLevel) {
01013     std::ostringstream s;
01014     indent(s, indLevel);
01015     s << "}";
01016     appendLine(s);
01017 }
01018 
01019 /// Adds: do {
01020 void CHLLCode::AddPosttestedLoopHeader(int indLevel) {
01021     std::ostringstream s;
01022     indent(s, indLevel);
01023     s << "do {";
01024     appendLine(s);
01025 }
01026 
01027 /// Adds: } while (\a cond);
01028 void CHLLCode::AddPosttestedLoopEnd(int indLevel, Exp *cond)
01029 {
01030     std::ostringstream s;
01031     indent(s, indLevel);
01032     s << "} while (";
01033     appendExp(s, cond, PREC_NONE);
01034     s << ");";
01035     appendLine(s);
01036 }
01037 
01038 /// Adds: switch(\a cond) {
01039 void CHLLCode::AddCaseCondHeader(int indLevel, Exp *cond)
01040 {
01041     std::ostringstream s;
01042     indent(s, indLevel);
01043     s << "switch(";
01044     appendExp(s, cond, PREC_NONE);
01045     s << ") {";
01046     appendLine(s);
01047 }
01048 
01049 /// Adds: case \a opt :
01050 void CHLLCode::AddCaseCondOption(int indLevel, Exp *opt)
01051 {
01052     std::ostringstream s;
01053     indent(s, indLevel);
01054     s << "case ";
01055     appendExp(s, opt, PREC_NONE);
01056     s << ":";
01057     appendLine(s);
01058 }
01059 
01060 /// Adds: break;
01061 void CHLLCode::AddCaseCondOptionEnd(int indLevel)
01062 {
01063     std::ostringstream s;
01064     indent(s, indLevel);
01065     s << "break;";
01066     appendLine(s);
01067 }
01068 
01069 /// Adds: default:
01070 void CHLLCode::AddCaseCondElse(int indLevel)
01071 {
01072     std::ostringstream s;
01073     indent(s, indLevel);
01074     s << "default:";
01075     appendLine(s);
01076 }
01077 
01078 /// Adds: }
01079 void CHLLCode::AddCaseCondEnd(int indLevel)
01080 {
01081     std::ostringstream s;
01082     indent(s, indLevel);
01083     s << "}";
01084     appendLine(s);
01085 }
01086 
01087 /// Adds: if(\a cond) {
01088 void CHLLCode::AddIfCondHeader(int indLevel, Exp *cond) {
01089     std::ostringstream s;
01090     indent(s, indLevel);
01091     s << "if (";
01092     appendExp(s, cond, PREC_NONE);
01093     s << ") {";
01094     appendLine(s);
01095 }
01096 
01097 /// Adds: }
01098 void CHLLCode::AddIfCondEnd(int indLevel) {
01099     std::ostringstream s;
01100     indent(s, indLevel);
01101     s << "}";
01102     appendLine(s);
01103 }
01104 
01105 /// Adds: if(\a cond) {
01106 void CHLLCode::AddIfElseCondHeader(int indLevel, Exp *cond) {
01107     std::ostringstream s;
01108     indent(s, indLevel);
01109     s << "if (";
01110     appendExp(s, cond, PREC_NONE);
01111     s << ") {";
01112     appendLine(s);
01113 }
01114 
01115 /// Adds: } else {
01116 void CHLLCode::AddIfElseCondOption(int indLevel) {
01117     std::ostringstream s;
01118     indent(s, indLevel);
01119     s << "} else {";
01120     appendLine(s);
01121 }
01122 
01123 /// Adds: }
01124 void CHLLCode::AddIfElseCondEnd(int indLevel) {
01125     std::ostringstream s;
01126     indent(s, indLevel);
01127     s << "}";
01128     appendLine(s);
01129 }
01130 
01131 /// Adds: goto L \em ord
01132 void CHLLCode::AddGoto(int indLevel, int ord) {
01133     std::ostringstream s;
01134     indent(s, indLevel);
01135     s << "goto L" << std::dec << ord << ";";
01136     appendLine(s);
01137     usedLabels.insert(ord);
01138 }
01139 
01140 /**
01141  * Removes labels from the code which are not in usedLabels.
01142  * \param maxOrd UNUSED
01143  */
01144 void CHLLCode::RemoveUnusedLabels(int maxOrd) {
01145     for (std::list<char *>::iterator it = lines.begin(); it != lines.end();) {
01146         if ((*it)[0] == 'L' && strchr(*it, ':')) {
01147             char *s = strdup(*it);
01148             *strchr(s, ':') = 0;
01149             int n = atoi(s+1);
01150             if (usedLabels.find(n) == usedLabels.end()) {
01151                 it = lines.erase(it);
01152                 continue;
01153             }
01154         }
01155         it++;
01156     }
01157 }
01158 
01159 /// Adds: continue;
01160 void CHLLCode::AddContinue(int indLevel) {
01161     std::ostringstream s;
01162     indent(s, indLevel);
01163     s << "continue;";
01164     appendLine(s);
01165 }
01166 
01167 /// Adds: break;
01168 void CHLLCode::AddBreak(int indLevel) {
01169     std::ostringstream s;
01170     indent(s, indLevel);
01171     s << "break;";
01172     appendLine(s);
01173 }
01174 
01175 /// Adds: L \a ord :
01176 void CHLLCode::AddLabel(int indLevel, int ord) {
01177     std::ostringstream s;
01178     s << "L" << std::dec << ord << ":";
01179     appendLine(s);
01180 }
01181 
01182 /// Search for the label L \a ord and remove it from the generated code.
01183 void CHLLCode::RemoveLabel(int ord) {
01184     std::ostringstream s;
01185     s << "L" << std::dec << ord << ":";
01186     for (std::list<char*>::iterator it = lines.begin(); it != lines.end(); it++) {
01187         if (!strcmp(*it, s.str().c_str())) {
01188             lines.erase(it);
01189             break;
01190         }
01191     }
01192 }
01193 
01194 
01195 bool isBareMemof(Exp* e, UserProc* proc) {
01196     if (!e->isMemOf()) return false;
01197 #if SYMS_IN_BACK_END
01198     // Check if it maps to a symbol
01199     char* sym = proc->lookupSym(e);
01200     if (sym == NULL)
01201         sym = proc->lookupSym(e->getSubExp1());
01202     return sym == NULL;         // Only a bare memof if it is not a symbol
01203 #else
01204     return true;
01205 #endif
01206 }
01207 
01208 /// Prints an assignment expression.
01209 void CHLLCode::AddAssignmentStatement(int indLevel, Assign *asgn) {
01210     // Gerard: shouldn't these  3 types of statements be removed earlier?
01211     if (asgn->getLeft()->getOper() == opPC)
01212         return;                     // Never want to see assignments to %PC
01213     Exp *result;
01214     if (asgn->getRight()->search(new Terminal(opPC), result)) // Gerard: what's this?
01215         return;
01216     // ok I want this now
01217     //if (asgn->getLeft()->isFlags())
01218     //  return;
01219 
01220     std::ostringstream s;
01221     indent(s, indLevel);
01222     Type* asgnType = asgn->getType();
01223     Exp* lhs = asgn->getLeft();
01224     Exp* rhs = asgn->getRight();
01225     UserProc* proc = asgn->getProc();
01226 
01227     if (*lhs == *rhs)
01228         return;    // never want to see a = a;
01229 
01230     if (Boomerang::get()->noDecompile && isBareMemof(rhs, proc) && lhs->getOper() == opRegOf &&
01231             m_proc->getProg()->getFrontEndId() == PLAT_SPARC) {
01232         // add some fsize hints to rhs
01233         if (((Const*)lhs->getSubExp1())->getInt() >= 32 && ((Const*)lhs->getSubExp1())->getInt() <= 63)
01234             rhs = new Ternary(opFsize, new Const(32), new Const(32), rhs);
01235         else if (((Const*)lhs->getSubExp1())->getInt() >= 64 && ((Const*)lhs->getSubExp1())->getInt() <= 87)
01236             rhs = new Ternary(opFsize, new Const(64), new Const(64), rhs);
01237     }
01238 
01239     if (Boomerang::get()->noDecompile && isBareMemof(lhs, proc)) {
01240         if (asgnType && asgnType->isFloat()) {
01241             if (asgnType->asFloat()->getSize() == 32)
01242                 s << "FLOAT_";
01243             else
01244                 s << "DOUBLE_";
01245         } else if (rhs->getOper() == opFsize) {
01246             if (((Const*)rhs->getSubExp2())->getInt() == 32)
01247                 s << "FLOAT_";
01248             else
01249                 s << "DOUBLE_";
01250         } else if (rhs->getOper() == opRegOf && m_proc->getProg()->getFrontEndId() == PLAT_SPARC) {
01251             // yes, this is a hack
01252             if (((Const*)rhs->getSubExp1())->getInt() >= 32 &&
01253                 ((Const*)rhs->getSubExp1())->getInt() <= 63)
01254                 s << "FLOAT_";
01255             else if (((Const*)rhs->getSubExp1())->getInt() >= 64 &&
01256                 ((Const*)rhs->getSubExp1())->getInt() <= 87)
01257                 s << "DOUBLE_";
01258         }
01259 
01260         s << "MEMASSIGN(";
01261         appendExp(s, lhs->getSubExp1(), PREC_UNARY);
01262         s << ", ";
01263         appendExp(s, rhs, PREC_UNARY);
01264         s << ");";
01265         appendLine(s);
01266         return;
01267     }
01268     
01269     if (isBareMemof(lhs, proc) && asgnType && !asgnType->isVoid()) 
01270         appendExp(s,
01271             new TypedExp(
01272                 asgnType,
01273                 lhs), PREC_ASSIGN);
01274     else if (lhs->getOper() == opGlobal && asgn->getType()->isArray())
01275         appendExp(s, new Binary(opArrayIndex,
01276             lhs,
01277             new Const(0)), PREC_ASSIGN);
01278     else if (lhs->getOper() == opAt &&
01279             ((Ternary*)lhs)->getSubExp2()->isIntConst() &&
01280             ((Ternary*)lhs)->getSubExp3()->isIntConst()) {
01281         // exp1@[n:m] := rhs -> exp1 = exp1 & mask | rhs << m  where mask = ~((1 << m-n+1)-1)
01282         Exp* exp1 = ((Ternary*)lhs)->getSubExp1();
01283         int n = ((Const*)((Ternary*)lhs)->getSubExp2())->getInt();
01284         int m = ((Const*)((Ternary*)lhs)->getSubExp3())->getInt();
01285         appendExp(s, exp1, PREC_ASSIGN);
01286         s << " = ";
01287         int mask = ~(((1 << (m-n+1))-1) << m);          // MSVC winges without most of these parentheses
01288         rhs = new Binary(opBitAnd,
01289             exp1,
01290             new Binary(opBitOr,
01291                 new Const(mask),
01292                 new Binary(opShiftL,
01293                     rhs,
01294                     new Const(m))));
01295         rhs = rhs->simplify();
01296         appendExp(s, rhs, PREC_ASSIGN);
01297         s << ";";
01298         appendLine(s);
01299         return;
01300     } else
01301         appendExp(s, lhs, PREC_ASSIGN);         // Ordinary LHS
01302     if (rhs->getOper() == opPlus && 
01303             *rhs->getSubExp1() == *lhs) {
01304         // C has special syntax for this, eg += and ++
01305         // however it's not always acceptable for assigns to m[] (?)
01306         if (rhs->getSubExp2()->isIntConst() && 
01307                 (((Const*)rhs->getSubExp2())->getInt() == 1 ||
01308                  (asgn->getType()->isPointer() &&
01309                  asgn->getType()->asPointer()->getPointsTo()->getSize()==
01310                     (unsigned) ((Const*)rhs->getSubExp2())->getInt() * 8)))
01311             s << "++";
01312         else {
01313             s << " += ";
01314             appendExp(s, rhs->getSubExp2(), PREC_ASSIGN);
01315         }
01316     } else {
01317         s << " = ";
01318         appendExp(s, rhs, PREC_ASSIGN);
01319     }
01320     s << ";";
01321     appendLine(s);
01322 }
01323 
01324 /**
01325  * Adds a call to \a proc.
01326  *
01327  * \param indLevel      A string containing spaces to the indentation level.
01328  * \param proc          The Proc the call is to.
01329  * \param name          The name the Proc has.
01330  * \param args          The arguments to the call.
01331  * \param results       The variable that will receive the return value of the function.
01332  *
01333  * \todo                Remove the \a name parameter and use Proc::getName()
01334  * \todo                Add assingment for when the function returns a struct.
01335  */
01336 void CHLLCode::AddCallStatement(int indLevel, Proc *proc, const char *name, StatementList &args, StatementList* results)
01337 {
01338     std::ostringstream s;
01339     indent(s, indLevel);
01340     if (results->size() >= 1) {
01341         // FIXME: Needs changing if more than one real result (return a struct)
01342         Exp* firstRet = ((Assignment*)*results->begin())->getLeft();
01343         appendExp(s, firstRet, PREC_ASSIGN);
01344         s << " = ";
01345     }
01346     s << name << "(";
01347     StatementList::iterator ss;
01348     bool first = true;
01349     int n = 0;
01350     for (ss = args.begin(); ss != args.end(); ++ss, ++n) {
01351         if (first)
01352             first = false;
01353         else
01354             s << ", ";
01355         Type *t = ((Assign*)*ss)->getType();
01356         Exp* arg = ((Assign*)*ss)->getRight();
01357         bool ok = true;
01358         if (t && t->isPointer() && ((PointerType*)t)->getPointsTo()->isFunc() && arg->isIntConst()) {
01359             Proc *p = proc->getProg()->findProc(((Const*)arg)->getInt());
01360             if (p) {
01361                 s << p->getName();
01362                 ok = false;
01363             }
01364         }
01365         if (ok) {
01366             bool needclose = false;
01367             if (Boomerang::get()->noDecompile && proc->getSignature()->getParamType(n) &&
01368                     proc->getSignature()->getParamType(n)->isPointer()) {
01369                 s << "ADDR(";
01370                 needclose = true;
01371             }
01372             appendExp(s, arg, PREC_COMMA);
01373             if (needclose)
01374                 s << ")";
01375         }
01376     }
01377     s << ");";
01378     if (results->size() > 1) {
01379         bool first = true;
01380         s << " /* Warning: also results in ";
01381         for (ss = ++results->begin(); ss != results->end(); ++ss) {
01382             if (first)
01383                 first = false;
01384             else
01385                 s << ", ";
01386             appendExp(s, ((Assignment*)*ss)->getLeft(), PREC_COMMA);
01387         }
01388         s << " */";
01389     }
01390             
01391     appendLine(s);
01392 }
01393 
01394 /**
01395  * Adds an indirect call to \a exp.
01396  * \see AddCallStatement
01397  * \param results UNUSED
01398  * \todo Add the use of \a results like AddCallStatement.
01399  */
01400 // Ugh - almost the same as the above, but it needs to take an expression, // not a Proc*
01401 void CHLLCode::AddIndCallStatement(int indLevel, Exp *exp, StatementList &args, StatementList* results) {
01402 //  FIXME: Need to use 'results', since we can infer some defines...
01403     std::ostringstream s;
01404     indent(s, indLevel);
01405     s << "(*";
01406     appendExp(s, exp, PREC_NONE);
01407     s << ")(";
01408     StatementList::iterator ss;
01409     bool first = true;
01410     for (ss = args.begin(); ss != args.end(); ++ss) {
01411         if (first)
01412             first = false;
01413         else
01414             s << ", ";
01415         Exp* arg = ((Assign*)*ss)->getRight();
01416         appendExp(s, arg, PREC_COMMA);
01417     }
01418     s << ");";
01419     appendLine(s);
01420 }
01421 
01422 
01423 /**
01424  * Adds a return statement and returns the first expression in \a rets.
01425  * \todo This should be returning a struct if more than one real return value.
01426  */
01427 void CHLLCode::AddReturnStatement(int indLevel, StatementList* rets) {
01428     // FIXME: should be returning a struct of more than one real return */
01429     // The stack pointer is wanted as a define in calls, and so appears in returns, but needs to be removed here
01430     StatementList::iterator rr;
01431     std::ostringstream s;
01432     indent(s, indLevel);
01433     s << "return";
01434     int n = rets->size();
01435 
01436     if (n == 0 && Boomerang::get()->noDecompile && m_proc->getSignature()->getNumReturns() > 0)
01437         s << " eax";
01438     
01439     if (n >= 1) {
01440         s << " ";
01441         appendExp(s, ((Assign*)*rets->begin())->getRight(), PREC_NONE);
01442     }
01443     s << ";";
01444 
01445     if (n > 0) {
01446         if (n > 1)
01447             s << " /* WARNING: Also returning: ";
01448         bool first = true;
01449         for (rr = ++rets->begin(); rr != rets->end(); ++rr) {
01450             if (first)
01451                 first = false;
01452             else
01453                 s << ", ";
01454             appendExp(s, ((Assign*)*rr)->getLeft(), PREC_NONE);
01455             s << " := ";
01456             appendExp(s, ((Assign*)*rr)->getRight(), PREC_NONE);
01457         }
01458         if (n > 1)
01459             s << " */";
01460     }
01461     appendLine(s);
01462 }
01463 
01464 /**
01465  * Print the start of a function, and also as a comment its address.
01466  */
01467 void CHLLCode::AddProcStart(UserProc* proc) {
01468     std::ostringstream s;
01469     s << "// address: 0x" << std::hex << proc->getNativeAddress() << std::dec; 
01470     appendLine(s);
01471     AddProcDec(proc, true);
01472 }
01473 
01474 /// Add a prototype (for forward declaration)
01475 void CHLLCode::AddPrototype(UserProc* proc) {
01476     AddProcDec(proc, false);
01477 }
01478 
01479 /**
01480  * Print the declaration of a function.
01481  * \param open  False if this is just a prototype and ";" should be printed instead of "{"
01482  */
01483 void CHLLCode::AddProcDec(UserProc* proc, bool open) {
01484     std::ostringstream s;
01485     ReturnStatement* returns = proc->getTheReturnStatement();
01486     Type *retType = NULL;
01487     if (proc->getSignature()->isForced()) {
01488         if (proc->getSignature()->getNumReturns() == 0)
01489             s << "void "; 
01490         else {
01491             unsigned int n = 0;
01492             Exp *e = proc->getSignature()->getReturnExp(0);
01493             if (e->isRegN(Signature::getStackRegister(proc->getProg())))
01494                 n = 1;
01495             if (n < proc->getSignature()->getNumReturns())
01496                 retType = proc->getSignature()->getReturnType(n);
01497             if (retType == NULL)
01498                 s << "void ";
01499         }
01500     } else if (returns == NULL || returns->getNumReturns() == 0) {
01501         s << "void ";
01502     } else {
01503         Assign* firstRet = (Assign*)*returns->begin();
01504         retType = firstRet->getType();
01505         if (retType == NULL || retType->isVoid())
01506             // There is a real return; make it integer (Remove with AD HOC type analysis)
01507             retType = new IntegerType();
01508     }
01509     if (retType) {
01510         appendType(s, retType);
01511         if (!retType->isPointer())  // NOTE: assumes type *proc( style
01512             s << " ";
01513     }
01514     s << proc->getName() << "(";
01515     StatementList& parameters = proc->getParameters();
01516     StatementList::iterator pp;
01517     
01518     if (parameters.size() > 10 && open) {
01519         LOG << "Warning: CHLLCode::AddProcDec: Proc " << proc->getName() << " has " << (int)parameters.size() <<
01520             " parameters\n";
01521     }
01522     
01523     bool first = true;
01524     for (pp = parameters.begin(); pp != parameters.end(); ++pp) {
01525         if (first)
01526             first = false;
01527         else
01528             s << ", ";
01529         Assign* as = (Assign*)*pp;
01530         Exp* left = as->getLeft();
01531         Type *ty = as->getType();
01532         if (ty == NULL) {
01533             if (VERBOSE)
01534                 LOG << "ERROR in CHLLCode::AddProcDec: no type for parameter " << left << "!\n";
01535             ty = new IntegerType();
01536         }
01537         char* name;
01538         if (left->isParam())
01539             name = ((Const*)((Location*)left)->getSubExp1())->getStr();
01540         else {
01541             LOG << "ERROR: parameter " << left << " is not opParam!\n";
01542             name = "??";
01543         }
01544         if (ty->isPointer() && ((PointerType*)ty)->getPointsTo()->isArray()) {
01545             // C does this by default when you pass an array, i.e. you pass &array meaning array
01546             // Replace all m[param] with foo, param with foo, then foo with param
01547             ty = ((PointerType*)ty)->getPointsTo();
01548             Exp *foo = new Const("foo123412341234");
01549             m_proc->searchAndReplace(Location::memOf(left, NULL), foo);
01550             m_proc->searchAndReplace(left, foo);
01551             m_proc->searchAndReplace(foo, left);
01552         }
01553         appendTypeIdent(s, ty, name);
01554     }
01555     s << ")";
01556     if (open)
01557         s << " {";
01558     else
01559         s << ";";
01560     appendLine(s);
01561 }
01562 
01563 /// Adds: }
01564 void CHLLCode::AddProcEnd() {
01565     appendLine("}");
01566     appendLine("");
01567 }
01568 
01569 /**
01570  * Declare a local variable.
01571  * \param last  true if an empty line should be added.
01572  */
01573 void CHLLCode::AddLocal(const char *name, Type *type, bool last) {
01574     std::ostringstream s;
01575     indent(s, 1);
01576     appendTypeIdent(s, type, name);
01577     Exp *e = m_proc->expFromSymbol(name);
01578     if (e) {
01579         // ? Should never see subscripts in the back end!
01580         if (e->getOper() == opSubscript && ((RefExp*)e)->isImplicitDef() &&
01581             (e->getSubExp1()->getOper() == opParam ||
01582              e->getSubExp1()->getOper() == opGlobal)) {
01583             s << " = ";
01584             appendExp(s, e->getSubExp1(), PREC_NONE);
01585             s << ";";
01586         } else {
01587             s << "; \t\t// ";
01588             e->print(s);
01589         }
01590     } else
01591         s << ";";
01592     appendLine(s);
01593     locals[name] = type->clone();
01594     if (last)
01595         appendLine("");
01596 }
01597 
01598 /**
01599  * Add the declaration for a global.
01600  * \param init  The initial value of the global.
01601  */
01602 void CHLLCode::AddGlobal(const char *name, Type *type, Exp *init) {
01603     std::ostringstream s;
01604     // Check for array types. These are declared differently in C than
01605     // they are printed
01606     if (type->isArray()) {
01607         // Get the component type
01608         Type* base = ((ArrayType*)type)->getBaseType();
01609         appendType(s, base);
01610         s << " " << name << "[" << std::dec << ((ArrayType*)type)->getLength() << "]";
01611     } else if (type->isPointer() &&
01612       ((PointerType*)type)->getPointsTo()->resolvesToFunc()) {
01613         // These are even more different to declare than to print. Example:
01614         // void (void)* global0 = foo__1B;   ->
01615         // void (*global0)(void) = foo__1B;
01616         PointerType* pt = (PointerType*)type;
01617         FuncType* ft = (FuncType*)pt->getPointsTo();
01618         const char *ret, *param;
01619         ft->getReturnAndParam(ret, param);
01620         s << ret << "(*" << name << ")" << param;
01621     } else {
01622         appendType(s, type);
01623         s << " " << name;
01624     }
01625     if (init && !init->isNil()) {
01626         s << " = ";
01627         Type *base_type = type->isArray() ? type->asArray()->getBaseType() : type; 
01628         appendExp(s, init, PREC_ASSIGN, base_type->isInteger() ? !base_type->asInteger()->isSigned() : false);
01629     }
01630     s << ";";
01631     if (type->isSize())
01632         s << "// " << type->getSize() / 8 << " bytes";
01633     appendLine(s);
01634 }
01635 
01636 /// Dump all generated code to \a os.
01637 void CHLLCode::print(std::ostream &os) {
01638     for (std::list<char*>::iterator it = lines.begin(); it != lines.end(); it++) 
01639          os << *it << std::endl;
01640     if (m_proc == NULL)
01641         os << std::endl;
01642 }
01643 
01644 /// Adds one line of comment to the code.
01645 void CHLLCode::AddLineComment(char* cmt) {
01646     std::ostringstream s;
01647     s << "/* " << cmt << "*/";
01648     appendLine(s);
01649 }
01650 
01651 // Private helper functions, to reduce redundant code, and
01652 // have a single place to put a breakpoint on.
01653 void CHLLCode::appendLine(const std::ostringstream& ostr) {
01654     appendLine(ostr.str());
01655 }
01656 
01657 void CHLLCode::appendLine(const std::string& s) {
01658     lines.push_back(strdup(s.c_str()));
01659 }
01660 

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