StatementTest.cpp

Go to the documentation of this file.
00001 /*==============================================================================
00002  * FILE:       StatementTest.cc
00003  * OVERVIEW:   Provides the implementation for the StatementTest class, which
00004  *              tests the dataflow subsystems
00005  *============================================================================*/
00006 /*
00007  * $Revision: 1.41 $
00008  *
00009  * 14 Jan 03 - Trent: Created
00010  * 17 Apr 03 - Mike: Added testRecursion to track down a nasty bug
00011  * 06 Jul 05 - Mike: Split testAddUsedLocs into six separate tests for Assign ... Bool
00012  */
00013 
00014 #define HELLO_PENTIUM      "test/pentium/hello"
00015 #define GLOBAL1_PENTIUM    "test/pentium/global1"
00016 
00017 #include "StatementTest.h"
00018 #include "cfg.h"
00019 #include "rtl.h"
00020 #include "pentiumfrontend.h"
00021 #include "boomerang.h"
00022 #include "exp.h"
00023 #include "managed.h"
00024 #include "log.h"
00025 #include "signature.h"
00026 
00027 #include <sstream>
00028 #include <map>
00029 
00030 class NullLogger : public Log {
00031 public:
00032     virtual Log &operator<<(const char *str) {
00033         // std::cerr << str;
00034         return *this;
00035     }
00036     virtual ~NullLogger() {};
00037 };
00038 /*==============================================================================
00039  * FUNCTION:        StatementTest::registerTests
00040  * OVERVIEW:        Register the test functions in the given suite
00041  * PARAMETERS:      Pointer to the test suite
00042  * RETURNS:         <nothing>
00043  *============================================================================*/
00044 #define MYTEST(name) \
00045 suite->addTest(new CppUnit::TestCaller<StatementTest> ("Statements", \
00046     &StatementTest::name, *this))
00047 
00048 void StatementTest::registerTests(CppUnit::TestSuite* suite) {
00049 
00050     MYTEST(testLocationSet);
00051     MYTEST(testWildLocationSet);
00052     MYTEST(testEmpty);
00053     MYTEST(testFlow);
00054     MYTEST(testKill);
00055     MYTEST(testUse);
00056     MYTEST(testUseOverKill);
00057     MYTEST(testUseOverBB);
00058     MYTEST(testUseKill);
00059     //MYTEST(testEndlessLoop);
00060     //MYTEST(testRecursion);
00061     //MYTEST(testExpand);
00062     MYTEST(testClone);
00063     MYTEST(testIsAssign);
00064     MYTEST(testIsFlagAssgn);
00065     MYTEST(testAddUsedLocsAssign);
00066     MYTEST(testAddUsedLocsBranch);
00067     MYTEST(testAddUsedLocsCase);
00068     MYTEST(testAddUsedLocsCall);
00069     MYTEST(testAddUsedLocsReturn);
00070     MYTEST(testAddUsedLocsBool);
00071     MYTEST(testSubscriptVars);
00072     MYTEST(testBypass);
00073     MYTEST(testStripSizes);
00074     MYTEST(testFindConstants);
00075 }
00076 
00077 int StatementTest::countTestCases () const
00078 { return 2; }   // ? What's this for?
00079 
00080 /*==============================================================================
00081  * FUNCTION:        StatementTest::setUp
00082  * OVERVIEW:        Set up some expressions for use with all the tests
00083  * NOTE:            Called before any tests
00084  * PARAMETERS:      <none>
00085  * RETURNS:         <nothing>
00086  *============================================================================*/
00087 static bool logset = false;
00088 void StatementTest::setUp () {
00089     if (!logset) {
00090         logset = true;
00091         Boomerang::get()->setLogger(new NullLogger());
00092     }
00093 }
00094 
00095 /*==============================================================================
00096  * FUNCTION:        StatementTest::tearDown
00097  * OVERVIEW:        Delete expressions created in setUp
00098  * NOTE:            Called after all tests
00099  * PARAMETERS:      <none>
00100  * RETURNS:         <nothing>
00101  *============================================================================*/
00102 void StatementTest::tearDown () {
00103 }
00104 
00105 /*==============================================================================
00106  * FUNCTION:        StatementTest::testEmpty
00107  * OVERVIEW:        
00108  *============================================================================*/
00109 void StatementTest::testEmpty () {
00110     // Force "verbose" flag (-v)
00111     Boomerang* boo = Boomerang::get();
00112     boo->vFlag = true;
00113     boo->setOutputDirectory("./unit_test/");
00114     boo->setLogger(new FileLogger());
00115 
00116     // create Prog
00117     Prog* prog = new Prog;
00118     BinaryFileFactory bff;
00119     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00120     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00121     prog->setFrontEnd(pFE);
00122 
00123     // create UserProc
00124     std::string name = "test";
00125     UserProc* proc = (UserProc*) prog->newProc("test", 0x123);
00126     // create CFG
00127     Cfg *cfg = proc->getCFG();
00128     std::list<RTL*>* pRtls = new std::list<RTL*>();
00129     std::list<Statement*>* ls = new std::list<Statement*>;
00130     ls->push_back(new ReturnStatement);
00131     pRtls->push_back(new RTL(0x123));
00132     PBB bb = cfg->newBB(pRtls, RET, 0);
00133     cfg->setEntryBB(bb);
00134     proc->setDecoded();     // We manually "decoded"
00135     // compute dataflow
00136     int indent = 0;
00137     proc->decompile(new ProcList, indent);
00138     // print cfg to a string
00139     std::ostringstream st;
00140     cfg->print(st);
00141     std::string s = st.str();
00142     // compare it to expected
00143     std::string expected = 
00144         "Ret BB:\n"
00145         "00000123\n\n";
00146     CPPUNIT_ASSERT_EQUAL(expected, s);
00147     // clean up
00148     delete prog;
00149 }
00150 
00151 /*==============================================================================
00152  * FUNCTION:        StatementTest::testFlow
00153  * OVERVIEW:        
00154  *============================================================================*/
00155 void StatementTest::testFlow () {
00156     // create Prog
00157     Prog* prog = new Prog;
00158     BinaryFileFactory bff;
00159     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00160     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00161     // We need a Prog object with a pBF (for getEarlyParamExp())
00162     prog->setFrontEnd(pFE);
00163 
00164     // create UserProc
00165     std::string name = "test";
00166     UserProc* proc = (UserProc*) prog->newProc("test", 0x123);
00167     // create CFG
00168     Cfg *cfg = proc->getCFG();
00169     std::list<RTL*>* pRtls = new std::list<RTL*>();
00170     RTL *rtl = new RTL();
00171     Assign *a = new Assign(Location::regOf(24), new Const(5));
00172     a->setProc(proc);
00173     a->setNumber(1);
00174     rtl->appendStmt(a);
00175     pRtls->push_back(rtl);
00176     PBB first = cfg->newBB(pRtls, FALL, 1);
00177     pRtls = new std::list<RTL*>();
00178     rtl = new RTL(0x123);
00179     ReturnStatement* rs = new ReturnStatement;
00180     rs->setNumber(2);
00181     rs->addReturn(new Assign(Location::regOf(24), new Const(5)));
00182     rtl->appendStmt(rs);
00183     pRtls->push_back(rtl);
00184     PBB ret = cfg->newBB(pRtls, RET, 0);
00185     first->setOutEdge(0, ret);
00186     ret->addInEdge(first);
00187     cfg->setEntryBB(first);     // Also sets exitBB; important!
00188     proc->setDecoded();
00189     // compute dataflow
00190     int indent = 0;
00191     proc->decompile(new ProcList, indent);
00192     // print cfg to a string
00193     std::ostringstream st;
00194     cfg->print(st);
00195     std::string s = st.str();
00196     // compare it to expected
00197     std::string expected;
00198     // The assignment to 5 gets propagated into the return, and the assignment
00199     // to r24 is removed
00200     expected =
00201         "Fall BB:\n"
00202         "00000000\n"
00203         "Ret BB:\n"
00204         "00000123    2 RET *v* r24 := 5\n"
00205         "              Modifieds: \n"
00206         "              Reaching definitions: r24=5\n\n";
00207 
00208     CPPUNIT_ASSERT_EQUAL(expected, s);
00209     // clean up
00210     delete prog;
00211 }
00212 
00213 /*==============================================================================
00214  * FUNCTION:        StatementTest::testKill
00215  * OVERVIEW:        
00216  *============================================================================*/
00217 void StatementTest::testKill () {
00218     // create Prog
00219     Prog* prog = new Prog;
00220     BinaryFileFactory bff;
00221     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00222     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00223     // We need a Prog object with a pBF (for getEarlyParamExp())
00224     prog->setFrontEnd(pFE);
00225     // create UserProc
00226     std::string name = "test";
00227     UserProc* proc = (UserProc*) prog->newProc("test", 0x123);
00228     // create CFG
00229     Cfg *cfg = proc->getCFG();
00230     std::list<RTL*>* pRtls = new std::list<RTL*>();
00231     RTL *rtl = new RTL();
00232     Assign *e = new Assign(Location::regOf(24),
00233                      new Const(5));
00234     e->setNumber(1);
00235     e->setProc(proc);
00236     rtl->appendStmt(e);
00237     e = new Assign(Location::regOf(24),
00238                   new Const(6));
00239     e->setNumber(2);
00240     e->setProc(proc);
00241     rtl->appendStmt(e);
00242     pRtls->push_back(rtl);
00243     PBB first = cfg->newBB(pRtls, FALL, 1);
00244     pRtls = new std::list<RTL*>();
00245     rtl = new RTL(0x123);
00246     ReturnStatement* rs = new ReturnStatement;
00247     rs->setNumber(3);
00248     rs->addReturn(new Assign(Location::regOf(24), new Const(0)));
00249     rtl->appendStmt(rs);
00250     pRtls->push_back(rtl);
00251     PBB ret = cfg->newBB(pRtls, RET, 0);
00252     first->setOutEdge(0, ret);
00253     ret->addInEdge(first);
00254     cfg->setEntryBB(first);
00255     proc->setDecoded();
00256     // compute dataflow
00257     int indent = 0;
00258     proc->decompile(new ProcList, indent);
00259     // print cfg to a string
00260     std::ostringstream st;
00261     cfg->print(st);
00262     std::string s = st.str();
00263     // compare it to expected
00264     std::string expected;
00265     expected =
00266         "Fall BB:\n"
00267         "00000000\n"
00268         "Ret BB:\n"
00269         "00000123    3 RET *v* r24 := 0\n"
00270         "              Modifieds: \n"
00271         "              Reaching definitions: r24=6\n\n";
00272 
00273     CPPUNIT_ASSERT_EQUAL(expected, s);
00274     // clean up
00275     delete prog;
00276 }
00277 
00278 /*==============================================================================
00279  * FUNCTION:        StatementTest::testUse
00280  * OVERVIEW:        
00281  *============================================================================*/
00282 void StatementTest::testUse () {
00283     // create Prog
00284     Prog* prog = new Prog;
00285     BinaryFileFactory bff;
00286     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00287     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00288     // We need a Prog object with a pBF (for getEarlyParamExp())
00289     prog->setFrontEnd(pFE);
00290     // create UserProc
00291     std::string name = "test";
00292     UserProc* proc = (UserProc*) prog->newProc("test", 0x123);
00293     // create CFG
00294     Cfg *cfg = proc->getCFG();
00295     std::list<RTL*>* pRtls = new std::list<RTL*>();
00296     RTL *rtl = new RTL();
00297     Assign *a = new Assign(Location::regOf(24), new Const(5));
00298     a->setNumber(1);
00299     a->setProc(proc);
00300     rtl->appendStmt(a);
00301     a = new Assign(Location::regOf(28), Location::regOf(24));
00302     a->setNumber(2);
00303     a->setProc(proc);
00304     rtl->appendStmt(a);
00305     pRtls->push_back(rtl);
00306     PBB first = cfg->newBB(pRtls, FALL, 1);
00307     pRtls = new std::list<RTL*>();
00308     rtl = new RTL(0x123);
00309     ReturnStatement* rs = new ReturnStatement;
00310     rs->setNumber(3);
00311     rs->addReturn(new Assign(Location::regOf(28), new Const(1000)));
00312     rtl->appendStmt(rs);
00313     pRtls->push_back(rtl);
00314     PBB ret = cfg->newBB(pRtls, RET, 0);
00315     first->setOutEdge(0, ret);
00316     ret->addInEdge(first);
00317     cfg->setEntryBB(first);
00318     proc->setDecoded();
00319     // compute dataflow
00320     int indent = 0;
00321     proc->decompile(new ProcList, indent);
00322     // print cfg to a string
00323     std::ostringstream st;
00324     cfg->print(st);
00325     std::string s = st.str();
00326     // compare it to expected
00327     std::string expected;
00328     expected =
00329         "Fall BB:\n"
00330         "00000000\n"
00331         "Ret BB:\n"
00332         "00000123    3 RET *v* r28 := 1000\n"
00333         "              Modifieds: \n"
00334         "              Reaching definitions: r24=5,   r28=5\n\n";
00335 
00336     CPPUNIT_ASSERT_EQUAL(expected, s);
00337     // clean up
00338     delete prog;
00339 }
00340 
00341 /*==============================================================================
00342  * FUNCTION:        StatementTest::testUseOverKill
00343  * OVERVIEW:        
00344  *============================================================================*/
00345 void StatementTest::testUseOverKill () {
00346     // create Prog
00347     Prog* prog = new Prog;
00348     BinaryFileFactory bff;
00349     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00350     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00351     // We need a Prog object with a pBF (for getEarlyParamExp())
00352     prog->setFrontEnd(pFE);
00353     // create UserProc
00354     std::string name = "test";
00355     UserProc* proc = (UserProc*) prog->newProc("test", 0x123);
00356     // create CFG
00357     Cfg *cfg = proc->getCFG();
00358     std::list<RTL*>* pRtls = new std::list<RTL*>();
00359     RTL *rtl = new RTL();
00360     Assign *e = new Assign(Location::regOf(24), new Const(5));
00361     e->setNumber(1);
00362     e->setProc(proc);
00363     rtl->appendStmt(e);
00364     e = new Assign(Location::regOf(24), new Const(6));
00365     e->setNumber(2);
00366     e->setProc(proc);
00367     rtl->appendStmt(e);
00368     e = new Assign(Location::regOf(28), Location::regOf(24));
00369     e->setNumber(3);
00370     e->setProc(proc);
00371     rtl->appendStmt(e);
00372     pRtls->push_back(rtl);
00373     PBB first = cfg->newBB(pRtls, FALL, 1);
00374     pRtls = new std::list<RTL*>();
00375     rtl = new RTL(0x123);
00376     ReturnStatement* rs = new ReturnStatement;
00377     rs->setNumber(4);
00378     rs->addReturn(new Assign(Location::regOf(24), new Const(0)));
00379     rtl->appendStmt(rs);
00380     pRtls->push_back(rtl);
00381     PBB ret = cfg->newBB(pRtls, RET, 0);
00382     first->setOutEdge(0, ret);
00383     ret->addInEdge(first);
00384     cfg->setEntryBB(first);
00385     proc->setDecoded();
00386     // compute dataflow
00387     int indent = 0;
00388     proc->decompile(new ProcList, indent);
00389     // print cfg to a string
00390     std::ostringstream st;
00391     cfg->print(st);
00392     std::string s = st.str();
00393     // compare it to expected
00394     std::string expected;
00395     expected = 
00396         "Fall BB:\n"
00397         "00000000\n"
00398         "Ret BB:\n"
00399         "00000123    4 RET *v* r24 := 0\n"
00400         "              Modifieds: \n"
00401         "              Reaching definitions: r24=6,   r28=6\n\n";
00402 
00403     CPPUNIT_ASSERT_EQUAL(expected, s);
00404     // clean up
00405     delete prog;
00406 }
00407 
00408 /*==============================================================================
00409  * FUNCTION:        StatementTest::testUseOverBB
00410  * OVERVIEW:        
00411  *============================================================================*/
00412 void StatementTest::testUseOverBB () {
00413     // create Prog
00414     Prog* prog = new Prog;
00415     BinaryFileFactory bff;
00416     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00417     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00418     // We need a Prog object with a pBF (for getEarlyParamExp())
00419     prog->setFrontEnd(pFE);
00420     // create UserProc
00421     std::string name = "test";
00422     UserProc* proc = (UserProc*) prog->newProc("test", 0x123);
00423     // create CFG
00424     Cfg *cfg = proc->getCFG();
00425     std::list<RTL*>* pRtls = new std::list<RTL*>();
00426     RTL *rtl = new RTL();
00427     Assign *a = new Assign(Location::regOf(24),
00428                      new Const(5));
00429     a->setNumber(1);
00430     a->setProc(proc);
00431     rtl->appendStmt(a);
00432     a = new Assign(Location::regOf(24), new Const(6));
00433     a->setNumber(2);
00434     a->setProc(proc);
00435     rtl->appendStmt(a);
00436     pRtls->push_back(rtl);
00437     PBB first = cfg->newBB(pRtls, FALL, 1);
00438     pRtls = new std::list<RTL*>();
00439     rtl = new RTL();
00440     a = new Assign(Location::regOf(28), Location::regOf(24));
00441     a->setNumber(3);
00442     a->setProc(proc);
00443     rtl->appendStmt(a);
00444     pRtls->push_back(rtl);
00445     rtl = new RTL(0x123);
00446     ReturnStatement* rs = new ReturnStatement;
00447     rs->setNumber(4);
00448     rs->addReturn(new Assign(Location::regOf(24), new Const(0)));
00449     rtl->appendStmt(rs);
00450     pRtls->push_back(rtl);
00451     PBB ret = cfg->newBB(pRtls, RET, 0);
00452     first->setOutEdge(0, ret);
00453     ret->addInEdge(first);
00454     cfg->setEntryBB(first);
00455     proc->setDecoded();
00456     // compute dataflow
00457     int indent = 0;
00458     proc->decompile(new ProcList, indent);
00459     // print cfg to a string
00460     std::ostringstream st;
00461     cfg->print(st);
00462     std::string s = st.str();
00463     // compare it to expected
00464     std::string expected;
00465     expected =
00466         "Fall BB:\n"
00467         "00000000\n"
00468         "Ret BB:\n"
00469         "00000000\n"
00470         "00000123    4 RET *v* r24 := 0\n"
00471         "              Modifieds: \n"
00472         "              Reaching definitions: r24=6,   r28=6\n\n";
00473 
00474     CPPUNIT_ASSERT_EQUAL(expected, s);
00475     // clean up
00476     delete prog;
00477 }
00478 
00479 /*==============================================================================
00480  * FUNCTION:        StatementTest::testUseKill
00481  * OVERVIEW:        
00482  *============================================================================*/
00483 void StatementTest::testUseKill () {
00484     // create Prog
00485     Prog* prog = new Prog;
00486     BinaryFileFactory bff;
00487     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00488     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00489     // We need a Prog object with a pBF (for getEarlyParamExp())
00490     prog->setFrontEnd(pFE);
00491     // create UserProc
00492     std::string name = "test";
00493     UserProc* proc = (UserProc*) prog->newProc("test", 0x123);
00494     // create CFG
00495     Cfg *cfg = proc->getCFG();
00496     std::list<RTL*>* pRtls = new std::list<RTL*>();
00497     RTL *rtl = new RTL();
00498     Assign *a = new Assign(Location::regOf(24), new Const(5));
00499     a->setNumber(1);
00500     a->setProc(proc);
00501     rtl->appendStmt(a);
00502     a = new Assign(Location::regOf(24),
00503             new Binary(opPlus,
00504                 Location::regOf(24),
00505                 new Const(1)));
00506     a->setNumber(2);
00507     a->setProc(proc);
00508     rtl->appendStmt(a);
00509     pRtls->push_back(rtl);
00510     PBB first = cfg->newBB(pRtls, FALL, 1);
00511     pRtls = new std::list<RTL*>();
00512     rtl = new RTL(0x123);
00513     ReturnStatement* rs = new ReturnStatement;
00514     rs->setNumber(3);
00515     rs->addReturn(new Assign(Location::regOf(24), new Const(0)));
00516     rtl->appendStmt(rs);
00517     pRtls->push_back(rtl);
00518     PBB ret = cfg->newBB(pRtls, RET, 0);
00519     first->setOutEdge(0, ret);
00520     ret->addInEdge(first);
00521     cfg->setEntryBB(first);
00522     proc->setDecoded();
00523     // compute dataflow
00524     int indent = 0;
00525     proc->decompile(new ProcList, indent);
00526     // print cfg to a string
00527     std::ostringstream st;
00528     cfg->print(st);
00529     std::string s = st.str();
00530     // compare it to expected
00531     std::string expected;
00532     expected  = 
00533         "Fall BB:\n"
00534         "00000000\n"
00535         "Ret BB:\n"
00536         "00000123    3 RET *v* r24 := 0\n"
00537         "              Modifieds: \n"
00538         "              Reaching definitions: r24=6\n\n";
00539 
00540     CPPUNIT_ASSERT_EQUAL(expected, s);
00541     // clean up
00542     delete prog;
00543 }
00544 
00545 /*==============================================================================
00546  * FUNCTION:        StatementTest::testEndlessLoop
00547  * OVERVIEW:        
00548  *============================================================================*/
00549 void StatementTest::testEndlessLoop () {
00550     // create Prog
00551     Prog* prog = new Prog;
00552     BinaryFileFactory bff;
00553     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00554     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00555     // We need a Prog object with a pBF (for getEarlyParamExp())
00556     prog->setFrontEnd(pFE);
00557     // create UserProc
00558     std::string name = "test";
00559     UserProc* proc = (UserProc*) prog->newProc("test", 0x123);
00560     // create CFG
00561     Cfg *cfg = proc->getCFG();
00562     std::list<RTL*>* pRtls = new std::list<RTL*>();
00563     RTL *rtl = new RTL();
00564     // r[24] := 5
00565     Assign *e = new Assign(Location::regOf(24),
00566                      new Const(5));
00567     e->setProc(proc);
00568     rtl->appendStmt(e);
00569     pRtls->push_back(rtl);
00570     PBB first = cfg->newBB(pRtls, FALL, 1);
00571     pRtls = new std::list<RTL*>();
00572     rtl = new RTL();
00573     // r[24] := r[24] + 1
00574     e = new Assign(Location::regOf(24),
00575             new Binary(opPlus,
00576                 Location::regOf(24),
00577                 new Const(1)));
00578     e->setProc(proc);
00579     rtl->appendStmt(e);
00580     pRtls->push_back(rtl);
00581     PBB body = cfg->newBB(pRtls, ONEWAY, 1);
00582     first->setOutEdge(0, body);
00583     body->addInEdge(first);
00584     body->setOutEdge(0, body);
00585     body->addInEdge(body);
00586     cfg->setEntryBB(first);
00587     proc->setDecoded();
00588     // compute dataflow
00589     int indent = 0;
00590     proc->decompile(new ProcList, indent);
00591     // print cfg to a string
00592     std::ostringstream st;
00593     cfg->print(st);
00594     std::string s = st.str();
00595     // compare it to expected
00596     std::string expected;
00597     expected =
00598       "Fall BB: reach in: \n"
00599       "00000000 *v* r[24] := 5\n"
00600       "Oneway BB:\n"
00601       "00000000 *v* r[24] := r[24] + 1   uses: ** r[24] := 5, "
00602       "*v* r[24] := r[24] + 1,    used by: ** r[24] := r[24] + 1, \n"
00603       "cfg reachExit: \n";
00604     CPPUNIT_ASSERT_EQUAL(expected, s);
00605     // clean up
00606     delete prog;
00607 }
00608 
00609 /*==============================================================================
00610  * FUNCTION:        StatementTest::testLocationSet
00611  * OVERVIEW:        
00612  *============================================================================*/
00613 void StatementTest::testLocationSet () {
00614     Location rof(opRegOf, new Const(12), NULL);     // r12
00615     Const& theReg = *(Const*)rof.getSubExp1();
00616     LocationSet ls;
00617     LocationSet::iterator ii;
00618     ls.insert(rof.clone());                         // ls has r12
00619     theReg.setInt(8);
00620     ls.insert(rof.clone());                         // ls has r8 r12
00621     theReg.setInt(31);
00622     ls.insert(rof.clone());                         // ls has r8 r12 r31
00623     theReg.setInt(24);
00624     ls.insert(rof.clone());                         // ls has r8 r12 r24 r31
00625     theReg.setInt(12);
00626     ls.insert(rof.clone());                         // Note: r12 already inserted
00627     int size = (int)ls.size();
00628     CPPUNIT_ASSERT_EQUAL(4, size);
00629     theReg.setInt(8);
00630     ii = ls.begin();
00631     CPPUNIT_ASSERT(rof == **ii);                    // First element should be r8
00632     theReg.setInt(12);
00633     Exp* e;
00634     e = *(++ii); CPPUNIT_ASSERT(rof == *e);         // Second should be r12
00635     theReg.setInt(24);
00636     e = *(++ii); CPPUNIT_ASSERT(rof == *e);         // Next should be r24
00637     theReg.setInt(31);
00638     e = *(++ii); CPPUNIT_ASSERT(rof == *e);         // Last should be r31
00639     Location mof(opMemOf,
00640         new Binary(opPlus,
00641             Location::regOf(14),
00642             new Const(4)), NULL);                   // m[r14 + 4]
00643     ls.insert(mof.clone());                         // ls should be r8 r12 r24 r31 m[r14 + 4]
00644     ls.insert(mof.clone());
00645     size = (int)ls.size();
00646     CPPUNIT_ASSERT_EQUAL(5, size);                  // Should have 5 elements
00647     ii = --ls.end();
00648     CPPUNIT_ASSERT(mof == **ii);                    // Last element should be m[r14 + 4] now
00649     LocationSet ls2 = ls;
00650     Exp* e2 = *ls2.begin();
00651     CPPUNIT_ASSERT(!(e2 == *ls.begin()));           // Must be cloned
00652     size = (int)ls2.size();
00653     CPPUNIT_ASSERT_EQUAL(5, size);
00654     theReg.setInt(8);
00655     CPPUNIT_ASSERT(rof == **ls2.begin());           // First elements should compare equal
00656     theReg.setInt(12);
00657     e = *(++ls2.begin());                           // Second element
00658     CPPUNIT_ASSERT(rof == *e);                      // ... should be r12
00659     Assign s10(new Const(0), new Const(0)), s20(new Const(0), new Const(0));
00660     s10.setNumber(10);
00661     s20.setNumber(20);
00662     RefExp* r1 = new RefExp(
00663         Location::regOf(8),
00664         &s10);
00665     RefExp* r2 = new RefExp(
00666         Location::regOf(8),
00667         &s20);
00668     ls.insert(r1);                  // ls now m[r14 + 4] r8 r12 r24 r31 r8{10} (not sure where r8{10} appears)
00669     size = (int)ls.size();
00670     CPPUNIT_ASSERT_EQUAL(6, size);
00671     Exp* dummy;
00672     CPPUNIT_ASSERT(!ls.findDifferentRef(r1, dummy));
00673     CPPUNIT_ASSERT( ls.findDifferentRef(r2, dummy));
00674 
00675     Exp* r8 = Location::regOf(8);
00676     CPPUNIT_ASSERT(! ls.existsImplicit(r8));
00677 
00678     RefExp r3(Location::regOf(8), NULL);
00679     ls.insert (&r3);
00680     std::cerr << ls.prints() << "\n";
00681     CPPUNIT_ASSERT(ls.existsImplicit(r8));
00682 
00683     ls.remove(&r3);
00684 
00685     ImplicitAssign zero(r8);
00686     RefExp r4(Location::regOf(8), &zero);
00687     ls.insert (&r4);
00688     std::cerr << ls.prints() << "\n";
00689     CPPUNIT_ASSERT(ls.existsImplicit(r8));
00690 }
00691 
00692 /*==============================================================================
00693  * FUNCTION:        StatementTest::testWildLocationSet
00694  * OVERVIEW:        
00695  *============================================================================*/
00696 void StatementTest::testWildLocationSet () {
00697     Location rof12(opRegOf, new Const(12), NULL);
00698     Location rof13(opRegOf, new Const(13), NULL);
00699     Assign a10, a20;
00700     a10.setNumber(10);
00701     a20.setNumber(20);
00702     RefExp r12_10(rof12.clone(), &a10);
00703     RefExp r12_20(rof12.clone(), &a20);
00704     RefExp r12_0 (rof12.clone(), NULL);
00705     RefExp r13_10(rof13.clone(), &a10);
00706     RefExp r13_20(rof13.clone(), &a20);
00707     RefExp r13_0 (rof13.clone(), NULL);
00708     RefExp r11_10(Location::regOf(11), &a10);
00709     RefExp r22_10(Location::regOf(22), &a10);
00710     LocationSet ls;
00711     ls.insert(&r12_10);
00712     ls.insert(&r12_20);
00713     ls.insert(&r12_0);
00714     ls.insert(&r13_10);
00715     ls.insert(&r13_20);
00716     ls.insert(&r13_0);
00717     RefExp wildr12(rof12.clone(), (Statement*)-1);
00718     CPPUNIT_ASSERT(ls.exists(&wildr12));
00719     RefExp wildr13(rof13.clone(), (Statement*)-1);
00720     CPPUNIT_ASSERT(ls.exists(&wildr13));
00721     RefExp wildr10(Location::regOf(10), (Statement*)-1);
00722     CPPUNIT_ASSERT(!ls.exists(&wildr10));
00723     // Test findDifferentRef
00724     Exp* x;
00725     CPPUNIT_ASSERT( ls.findDifferentRef(&r13_10, x));
00726     CPPUNIT_ASSERT( ls.findDifferentRef(&r13_20, x));
00727     CPPUNIT_ASSERT( ls.findDifferentRef(&r13_0 , x));
00728     CPPUNIT_ASSERT( ls.findDifferentRef(&r12_10, x));
00729     CPPUNIT_ASSERT( ls.findDifferentRef(&r12_20, x));
00730     CPPUNIT_ASSERT( ls.findDifferentRef(&r12_0 , x));
00731     // Next 4 should fail
00732     CPPUNIT_ASSERT(!ls.findDifferentRef(&r11_10, x));
00733     CPPUNIT_ASSERT(!ls.findDifferentRef(&r22_10, x));
00734     ls.insert(&r11_10);
00735     ls.insert(&r22_10);
00736     CPPUNIT_ASSERT(!ls.findDifferentRef(&r11_10, x));
00737     CPPUNIT_ASSERT(!ls.findDifferentRef(&r22_10, x));
00738 }
00739 
00740 /*==============================================================================
00741  * FUNCTION:        StatementTest::testRecursion
00742  * OVERVIEW:        Test push of argument (X86 style), then call self
00743  *============================================================================*/
00744 void StatementTest::testRecursion () {
00745     // create Prog
00746     Prog* prog = new Prog;
00747     BinaryFileFactory bff;
00748     BinaryFile *pBF = bff.Load(HELLO_PENTIUM);  // Don't actually use it
00749     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
00750     // We need a Prog object with a pBF (for getEarlyParamExp())
00751     prog->setFrontEnd(pFE);
00752     // create UserProc
00753     std::string name = "test";
00754     UserProc *proc = new UserProc(prog, name, 0);
00755     // create CFG
00756     Cfg *cfg = proc->getCFG();
00757     std::list<RTL*>* pRtls = new std::list<RTL*>();
00758     RTL *rtl = new RTL();
00759     // push bp
00760     // r28 := r28 + -4
00761     Assign *a = new Assign(Location::regOf(28),
00762         new Binary(opPlus,
00763             Location::regOf(28),
00764             new Const(-4)));
00765     rtl->appendStmt(a);
00766     // m[r28] := r29
00767     a = new Assign(
00768         Location::memOf(
00769             Location::regOf(28)),
00770         Location::regOf(29));
00771     rtl->appendStmt(a);
00772     pRtls->push_back(rtl);
00773     pRtls = new std::list<RTL*>();
00774     // push arg+1
00775     // r28 := r28 + -4
00776     a = new Assign(Location::regOf(28),
00777             new Binary(opPlus,
00778                 Location::regOf(28),
00779                 new Const(-4)));
00780     rtl->appendStmt(a);
00781     // Reference our parameter. At esp+0 is this arg; at esp+4 is old bp;
00782     // esp+8 is return address; esp+12 is our arg
00783     // m[r28] := m[r28+12] + 1
00784     a = new Assign(Location::memOf(Location::regOf(28)),
00785                      new Binary(opPlus,
00786                         Location::memOf(
00787                             new Binary(opPlus,
00788                                 Location::regOf(28),
00789                                 new Const(12))),
00790                         new Const(1)));
00791     a->setProc(proc);
00792     rtl->appendStmt(a);
00793     pRtls->push_back(rtl);
00794     PBB first = cfg->newBB(pRtls, FALL, 1);
00795 
00796     // The call BB
00797     pRtls = new std::list<RTL*>();
00798     rtl = new RTL(1);
00799     // r28 := r28 + -4
00800     a = new Assign(Location::regOf(28),
00801         new Binary(opPlus, Location::regOf(28), new Const(-4)));
00802     rtl->appendStmt(a);
00803     // m[r28] := pc
00804     a = new Assign(Location::memOf(Location::regOf(28)),
00805         new Terminal(opPC));
00806     rtl->appendStmt(a);
00807     // %pc := (%pc + 5) + 135893848
00808     a = new Assign(new Terminal(opPC),
00809         new Binary(opPlus,
00810             new Binary(opPlus,
00811                 new Terminal(opPC),
00812                 new Const(5)),
00813             new Const(135893848)));
00814     a->setProc(proc);
00815     rtl->appendStmt(a);
00816     pRtls->push_back(rtl);
00817     CallStatement* c = new CallStatement;
00818     rtl->appendStmt(c);
00819 #if 0
00820     // Vector of 1 arg
00821     std::vector<Exp*> args;
00822     // m[r[28]+8]
00823     Exp* a = Location::memOf( new Binary(opPlus,
00824       Location::regOf(28), new Const(8)));
00825     args.push_back(a);
00826     crtl->setArguments(args);
00827 #endif
00828     c->setDestProc(proc);        // Just call self
00829     PBB callbb = cfg->newBB(pRtls, CALL, 1);
00830     first->setOutEdge(0, callbb);
00831     callbb->addInEdge(first);
00832     callbb->setOutEdge(0, callbb);
00833     callbb->addInEdge(callbb);
00834 
00835     pRtls = new std::list<RTL*>();
00836     rtl = new RTL(0x123);
00837     rtl->appendStmt(new ReturnStatement);
00838     // This ReturnStatement requires the following two sets of semantics to pass the
00839     // tests for standard Pentium calling convention
00840     // pc = m[r28]
00841     a = new Assign(new Terminal(opPC),
00842         Location::memOf(
00843             Location::regOf(28)));
00844     rtl->appendStmt(a);
00845     // r28 = r28 + 4
00846     a = new Assign(Location::regOf(28),
00847         new Binary(opPlus,
00848             Location::regOf(28),
00849             new Const(4)));
00850     rtl->appendStmt(a);
00851     pRtls->push_back(rtl);
00852     PBB ret = cfg->newBB(pRtls, RET, 0);
00853     callbb->setOutEdge(0, ret);
00854     ret->addInEdge(callbb);
00855     cfg->setEntryBB(first);
00856 
00857     // decompile the "proc"
00858     prog->decompile();
00859     // print cfg to a string
00860     std::ostringstream st;
00861     cfg->print(st);
00862     std::string s = st.str();
00863     // compare it to expected
00864     std::string expected;
00865     expected =
00866       "Fall BB: reach in: \n"
00867       "00000000 ** r[24] := 5   uses:    used by: ** r[24] := r[24] + 1, \n"
00868       "00000000 ** r[24] := 5   uses:    used by: ** r[24] := r[24] + 1, \n"
00869       "Call BB: reach in: ** r[24] := 5, ** r[24] := r[24] + 1, \n"
00870       "00000001 ** r[24] := r[24] + 1   uses: ** r[24] := 5, "
00871       "** r[24] := r[24] + 1,    used by: ** r[24] := r[24] + 1, \n"
00872       "cfg reachExit: \n";
00873     CPPUNIT_ASSERT_EQUAL(expected, s);
00874     // clean up
00875     delete prog;
00876 }
00877 
00878 /*==============================================================================
00879  * FUNCTION:        StatamentTest::testClone
00880  * OVERVIEW:        Test cloning of Assigns (and exps)
00881  *============================================================================*/
00882 void StatementTest::testClone () {
00883     Assign* a1 = new Assign(
00884             Location::regOf(8),
00885             new Binary(opPlus,
00886                 Location::regOf(9),
00887                 new Const(99)));
00888     Assign* a2 = new Assign(new IntegerType(16, 1),
00889             new Location(opParam, new Const("x"), NULL),
00890             new Location(opParam, new Const("y"), NULL));
00891     Assign* a3 = new Assign(new IntegerType(16, -1),
00892             new Location(opParam, new Const("z"), NULL),
00893             new Location(opParam, new Const("q"), NULL));
00894     Statement* c1 = a1->clone();
00895     Statement* c2 = a2->clone();
00896     Statement* c3 = a3->clone();
00897     std::ostringstream o1, o2;
00898     a1->print(o1);
00899     delete a1;           // And c1 should still stand!
00900     c1->print(o2);
00901     a2->print(o1);
00902     c2->print(o2);
00903     a3->print(o1);
00904     c3->print(o2);
00905     std::string expected("   0 *v* r8 := r9 + 99   0 *i16* x := y"
00906         "   0 *u16* z := q");
00907     std::string act1(o1.str());
00908     std::string act2(o2.str());
00909     CPPUNIT_ASSERT_EQUAL(expected, act1); // Originals
00910     CPPUNIT_ASSERT_EQUAL(expected, act2); // Clones
00911 }
00912  
00913 /*==============================================================================
00914  * FUNCTION:        StatementTest::testIsAssign
00915  * OVERVIEW:        Test assignment test
00916  *============================================================================*/
00917 void StatementTest::testIsAssign () {
00918     std::ostringstream ost;
00919     // r2 := 99
00920     Assign a(
00921         Location::regOf(2),
00922         new Const(99));
00923     a.print(ost);
00924     std::string expected("   0 *v* r2 := 99");
00925     std::string actual (ost.str());
00926     CPPUNIT_ASSERT_EQUAL(expected, actual);
00927 //    CPPUNIT_ASSERT_EQUAL (std::string("*v* r2 := 99"), std::string(ost.str()));
00928     CPPUNIT_ASSERT(a.isAssign());
00929 
00930     CallStatement* c = new CallStatement;
00931     CPPUNIT_ASSERT(!c->isAssign());
00932 }
00933 
00934 /*==============================================================================
00935  * FUNCTION:        StatementTest::testIsFlagCall
00936  * OVERVIEW:        Test the isFlagAssgn function, and opFlagCall
00937  *============================================================================*/
00938 void StatementTest::testIsFlagAssgn () {
00939     std::ostringstream ost;
00940     // FLAG addFlags(r2 , 99)
00941     Assign fc(
00942         new Terminal(opFlags),
00943         new Binary (opFlagCall,
00944             new Const("addFlags"),
00945             new Binary(opList,
00946                 Location::regOf(2),
00947                 new Const(99))));
00948     CallStatement* call = new CallStatement;
00949     BranchStatement* br = new BranchStatement;
00950     Assign* as = new Assign(
00951         Location::regOf(9),
00952         new Binary(opPlus,
00953             Location::regOf(10),
00954             new Const(4)));
00955     fc.print(ost);
00956     std::string expected("   0 *v* %flags := addFlags( r2, 99 )");
00957     std::string actual(ost.str());
00958     CPPUNIT_ASSERT_EQUAL(expected, actual);
00959     CPPUNIT_ASSERT (    fc.isFlagAssgn());
00960     CPPUNIT_ASSERT (!call->isFlagAssgn());
00961     CPPUNIT_ASSERT (!  br->isFlagAssgn());
00962     CPPUNIT_ASSERT (!  as->isFlagAssgn());
00963     delete call; delete br;
00964 }
00965 
00966 /*==============================================================================
00967  * FUNCTION:        StatementTest::testAddUsedLocsAssign .. testAddUsedLocsBool
00968  * OVERVIEW:        Test the finding of locations used by this statement
00969  *============================================================================*/
00970 void StatementTest::testAddUsedLocsAssign() {
00971     // m[r28-4] := m[r28-8] * r26
00972     Assign* a = new Assign(
00973         Location::memOf(
00974             new Binary(opMinus,
00975                 Location::regOf(28),
00976                 new Const(4))),
00977         new Binary(opMult,
00978             Location::memOf(
00979                 new Binary(opMinus,
00980                     Location::regOf(28),
00981                     new Const(8))),
00982                 Location::regOf(26)));
00983     a->setNumber(1);
00984     LocationSet l;
00985     a->addUsedLocs(l);
00986     std::ostringstream ost1;
00987     l.print(ost1);
00988     std::string expected = "r26,\tr28,\tm[r28 - 8]";
00989     std::string actual = ost1.str();
00990     CPPUNIT_ASSERT_EQUAL(expected, actual);
00991 
00992     l.clear();
00993     GotoStatement* g = new GotoStatement();
00994     g->setNumber(55);
00995     g->setDest(Location::memOf(Location::regOf(26)));
00996     g->addUsedLocs(l);
00997     std::ostringstream ost2;
00998     l.print(ost2);
00999     expected = "r26,\tm[r26]";
01000     actual = ost2.str();
01001     CPPUNIT_ASSERT_EQUAL(expected, actual);
01002 }
01003 
01004 void StatementTest::testAddUsedLocsBranch() {
01005     // BranchStatement with dest m[r26{99}]{55}, condition %flags
01006     GotoStatement* g = new GotoStatement();
01007     g->setNumber(55);
01008     LocationSet l;
01009     BranchStatement* b = new BranchStatement;
01010     b->setNumber(99);
01011     b->setDest(
01012         new RefExp(
01013             Location::memOf(
01014                 new RefExp(
01015                     Location::regOf(26),
01016                     b)),
01017             g));
01018     b->setCondExpr(new Terminal(opFlags));
01019     b->addUsedLocs(l);
01020     std::ostringstream ost3;
01021     l.print(ost3);
01022     std::string expected("r26{99},\tm[r26{99}]{55},\t%flags");
01023     std::string actual(ost3.str());
01024     CPPUNIT_ASSERT_EQUAL(expected, actual);
01025 }
01026 
01027 void StatementTest::testAddUsedLocsCase() {
01028     // CaseStatement with pDest = m[r26], switchVar = m[r28 - 12]
01029     LocationSet l;
01030     CaseStatement* c = new CaseStatement;
01031     c->setDest(Location::memOf(Location::regOf(26)));
01032     SWITCH_INFO si;
01033     si.pSwitchVar = Location::memOf(
01034         new Binary(opMinus,
01035             Location::regOf(28),
01036             new Const(12)));
01037     c->setSwitchInfo(&si);
01038     c->addUsedLocs(l);
01039     std::ostringstream ost4;
01040     l.print(ost4);
01041     std::string expected("r26,\tr28,\tm[r28 - 12],\tm[r26]");
01042     std::string actual(ost4.str());
01043     CPPUNIT_ASSERT_EQUAL(expected, actual);
01044 }
01045 
01046 void StatementTest::testAddUsedLocsCall() {
01047     // CallStatement with pDest = m[r26], params = m[r27], r28{55}, defines r31, m[r24]
01048     LocationSet l;
01049     GotoStatement* g = new GotoStatement();
01050     g->setNumber(55);
01051     CallStatement* ca = new CallStatement;
01052     ca->setDest(Location::memOf(Location::regOf(26)));
01053     StatementList argl;
01054     argl.append(new Assign(Location::regOf(8), Location::memOf(Location::regOf(27))));
01055     argl.append(new Assign(Location::regOf(9), new RefExp(Location::regOf(28), g)));
01056     ca->setArguments(argl);
01057     ca->addDefine(new ImplicitAssign(Location::regOf(31)));
01058     ca->addDefine(new ImplicitAssign(Location::regOf(24)));
01059     ca->addUsedLocs(l);
01060     std::ostringstream ost5;
01061     l.print(ost5);
01062     std::string expected("r26,\tr27,\tm[r26],\tm[r27],\tr28{55}");
01063     std::string actual(ost5.str());
01064     CPPUNIT_ASSERT_EQUAL(expected, actual);
01065 
01066     // Now with uses in collector
01067 #if 0       // FIXME: to be completed
01068     l.clear();
01069     ca->addUsedLocs(l, true);
01070     std::ostringstream ost5f;
01071     l.print(ost5f);
01072     expected = "m[r26],\tm[r27],\tr26,\tr27,\tr28{55}";
01073     actual = ost5f.str();
01074     CPPUNIT_ASSERT_EQUAL(expected, actual);
01075 #endif
01076 }
01077     
01078 void StatementTest::testAddUsedLocsReturn() {
01079     // ReturnStatement with returns r31, m[r24], m[r25]{55} + r[26]{99}]
01080     LocationSet l;
01081     GotoStatement* g = new GotoStatement();
01082     g->setNumber(55);
01083     BranchStatement* b = new BranchStatement;
01084     b->setNumber(99);
01085     ReturnStatement* r = new ReturnStatement;
01086     r->addReturn(new Assign(Location::regOf(31), new Const(100)));
01087     r->addReturn(new Assign(Location::memOf(Location::regOf(24)), new Const(0)));
01088     r->addReturn(new Assign(
01089         Location::memOf(
01090             new Binary(opPlus,
01091                 new RefExp(Location::regOf(25), g),
01092                 new RefExp(Location::regOf(26), b))),
01093         new Const(5)));
01094     r->addUsedLocs(l);
01095     std::ostringstream ost6;
01096     l.print(ost6);
01097     std::string expected("r24,\tr25{55},\tr26{99}");
01098     std::string actual(ost6.str());
01099     CPPUNIT_ASSERT_EQUAL(expected, actual);
01100 }
01101 
01102 void StatementTest::testAddUsedLocsBool() {
01103     // Boolstatement with condition m[r24] = r25, dest m[r26]
01104     LocationSet l;
01105     BoolAssign* bs = new BoolAssign(8);
01106     bs->setCondExpr(new Binary(opEquals,
01107         Location::memOf(Location::regOf(24)),
01108         Location::regOf(25)));
01109     std::list<Statement*> stmts;
01110     Assign* a = new Assign(Location::memOf(Location::regOf(26)), new Terminal(opNil));
01111     stmts.push_back(a);
01112     bs->setLeftFromList(&stmts);
01113     bs->addUsedLocs(l);
01114     std::ostringstream ost7;
01115     l.print(ost7);
01116     std::string expected("r24,\tr25,\tr26,\tm[r24]");
01117     std::string actual(ost7.str());
01118     CPPUNIT_ASSERT_EQUAL(expected, actual);
01119 
01120     // m[local21 + 16] := phi{0, 372}
01121     l.clear();
01122     Exp* base = Location::memOf(
01123         new Binary(opPlus,
01124             Location::local("local21", NULL),
01125             new Const(16)));
01126     Assign s372(base, new Const(0));
01127     s372.setNumber(372);
01128     PhiAssign* pa = new PhiAssign(base);
01129     pa->putAt(0, NULL, base);
01130     pa->putAt(1, &s372, base);
01131     pa->addUsedLocs(l);
01132     // Note: phis were not considered to use blah if they ref m[blah], so local21 was not considered used
01133     expected = "m[local21 + 16]{-},\tm[local21 + 16]{372},\tlocal21";
01134     std::ostringstream ost8;
01135     l.print(ost8);
01136     actual = ost8.str();
01137     CPPUNIT_ASSERT_EQUAL(expected, actual);
01138 
01139     // m[r28{-} - 4] := -
01140     l.clear();
01141     ImplicitAssign* ia = new ImplicitAssign(Location::memOf(
01142         new Binary(opMinus,
01143             new RefExp(
01144                 Location::regOf(28),
01145                 NULL),
01146             new Const(4))));
01147     std::ostringstream ost9;
01148     ia->addUsedLocs(l);
01149     l.print(ost9);
01150     actual = ost9.str();
01151     expected = "r28{-}";
01152     CPPUNIT_ASSERT_EQUAL(expected, actual);
01153 
01154 }
01155 
01156 /*==============================================================================
01157  * FUNCTION:        StatementTest::testSubscriptVars
01158  * OVERVIEW:        Test the subscripting of locations in Statements
01159  *============================================================================*/
01160 void StatementTest::testSubscriptVars () {
01161     Exp* srch = Location::regOf(28);
01162     Assign s9(new Const(0), new Const(0));
01163     s9.setNumber(9);
01164 
01165     // m[r28-4] := m[r28-8] * r26
01166     Assign* a = new Assign(
01167         Location::memOf(
01168             new Binary(opMinus,
01169                 Location::regOf(28),
01170                 new Const(4))),
01171         new Binary(opMult,
01172             Location::memOf(
01173                 new Binary(opMinus,
01174                     Location::regOf(28),
01175                     new Const(8))),
01176                 Location::regOf(26)));
01177     a->setNumber(1);
01178     std::ostringstream ost1;
01179     a->subscriptVar(srch, &s9);
01180     ost1 << a;
01181     std::string expected = "   1 *v* m[r28{9} - 4] := m[r28{9} - 8] * r26";
01182     std::string actual(ost1.str());
01183     CPPUNIT_ASSERT_EQUAL(expected, actual);
01184 
01185     // GotoStatement
01186     GotoStatement* g = new GotoStatement();
01187     g->setNumber(55);
01188     g->setDest(Location::regOf(28));
01189     std::ostringstream ost2;
01190     g->subscriptVar(srch, &s9);
01191     ost2 << g;
01192     expected = "  55 GOTO r28{9}";
01193     actual = ost2.str();
01194     CPPUNIT_ASSERT_EQUAL(expected, actual);
01195 
01196     // BranchStatement with dest m[r26{99}]{55}, condition %flags
01197     BranchStatement* b = new BranchStatement;
01198     b->setNumber(99);
01199     Exp* srchb = Location::memOf(
01200                 new RefExp(
01201                     Location::regOf(26),
01202                     b));
01203     b->setDest(new RefExp(srchb, g));
01204     b->setCondExpr(new Terminal(opFlags));
01205     std::ostringstream ost3;
01206     b->subscriptVar(srchb, &s9);        // Should be ignored now: new behaviour
01207     b->subscriptVar(new Terminal(opFlags), g);
01208     ost3 << b;
01209     expected = "  99 BRANCH m[r26{99}]{55}, condition equals\n"
01210         "High level: %flags{55}";
01211     actual = ost3.str();
01212     CPPUNIT_ASSERT_EQUAL(expected, actual);
01213 
01214     // CaseStatement with pDest = m[r26], switchVar = m[r28 - 12]
01215     CaseStatement* c = new CaseStatement;
01216     c->setDest(Location::memOf(Location::regOf(26)));
01217     SWITCH_INFO si;
01218     si.pSwitchVar = Location::memOf(
01219         new Binary(opMinus,
01220             Location::regOf(28),
01221             new Const(12)));
01222     c->setSwitchInfo(&si);
01223     std::ostringstream ost4;
01224     c->subscriptVar(srch, &s9);
01225     ost4 << c;
01226     expected = "   0 SWITCH(m[r28{9} - 12])\n";
01227     actual = ost4.str();
01228     CPPUNIT_ASSERT_EQUAL(expected, actual);
01229 
01230     // CaseStatement (before recog) with pDest = r28, switchVar is NULL
01231     c->setDest(Location::regOf(28));
01232     c->setSwitchInfo(NULL);
01233     std::ostringstream ost4a;
01234     c->subscriptVar(srch, &s9);
01235     ost4a << c;
01236     expected = "   0 CASE [r28{9}]";
01237     actual = ost4a.str();
01238     CPPUNIT_ASSERT_EQUAL(expected, actual);
01239     
01240     // CallStatement with pDest = m[r26], params = m[r27], r28, defines r28, m[r28]
01241     CallStatement* ca = new CallStatement;
01242     ca->setDest(Location::memOf(Location::regOf(26)));
01243     StatementList argl;
01244     argl.append(new Assign(Location::memOf(Location::regOf(27)), new Const(1)));
01245     argl.append(new Assign(Location::regOf(28), new Const(2)));
01246     ca->setArguments(argl);
01247     ca->addDefine(new ImplicitAssign(Location::regOf(28)));
01248     ca->addDefine(new ImplicitAssign(Location::memOf(Location::regOf(28))));
01249     std::string name("dest");
01250     ca->setDestProc(new UserProc(new Prog(), name, 0x2000));    // Must have a dest to be non-childless
01251     ca->setCalleeReturn(new ReturnStatement);       // So it's not a childless call, and we can see the defs and params
01252     std::ostringstream ost5;
01253     ca->subscriptVar(srch, &s9);
01254     ost5 << ca;
01255     expected =
01256         "   0 {*v* r28, *v* m[r28]} := CALL dest(\n"
01257         "                *v* m[r27] := 1\n"
01258         "                *v* r28 := 2\n"
01259         "              )\n"
01260         "              Reaching definitions: \n"
01261         "              Live variables: ";       // ? No newline?
01262     actual = ost5.str();
01263     CPPUNIT_ASSERT_EQUAL(expected, actual);
01264 
01265     // CallStatement with pDest = r28, params = m[r27], r29, defines r31, m[r31]
01266     ca = new CallStatement;
01267     ca->setDest(Location::regOf(28));
01268     argl.clear();
01269     argl.append(new Assign(Location::memOf(Location::regOf(27)), new Const(1)));
01270     argl.append(new Assign(Location::regOf(29), new Const(2)));
01271     ca->setArguments(argl);
01272     ca->addDefine(new ImplicitAssign(Location::regOf(31)));
01273     ca->addDefine(new ImplicitAssign(Location::memOf(Location::regOf(31))));
01274     ca->setDestProc(new UserProc(new Prog(), name, 0x2000));    // Must have a dest to be non-childless
01275     ca->setCalleeReturn(new ReturnStatement);       // So it's not a childless call, and we can see the defs and params
01276     std::ostringstream ost5a;
01277     ca->subscriptVar(srch, &s9);
01278     ost5a << ca;
01279     expected =
01280         "   0 {*v* r31, *v* m[r31]} := CALL dest(\n"
01281         "                *v* m[r27] := 1\n"
01282         "                *v* r29 := 2\n"
01283         "              )\n"
01284         "              Reaching definitions: \n"
01285         "              Live variables: ";
01286     actual = ost5a.str();
01287     CPPUNIT_ASSERT_EQUAL(expected, actual);
01288 
01289 
01290     // ReturnStatement with returns r28, m[r28], m[r28]{55} + r[26]{99}]
01291     // FIXME: shouldn't this test have some propagation? Now, it seems it's just testing the print code!
01292     ReturnStatement* r = new ReturnStatement;
01293     r->addReturn(new Assign(Location::regOf(28), new Const(1000)));
01294     r->addReturn(new Assign(Location::memOf(Location::regOf(28)), new Const(2000)));
01295     r->addReturn(new Assign(
01296         Location::memOf(
01297             new Binary(opPlus,
01298                 new RefExp(Location::regOf(28), g),
01299                 new RefExp(Location::regOf(26), b))),
01300             new Const(100)));
01301     std::ostringstream ost6;
01302     r->subscriptVar(srch, &s9);     // New behaviour: gets ignored now
01303     ost6 << r;
01304     expected =
01305         "   0 RET *v* r28 := 1000,   *v* m[r28{9}] := 0x7d0,   *v* m[r28{55} + r26{99}] := 100\n"
01306         "              Modifieds: \n"
01307         "              Reaching definitions: ";
01308     actual = ost6.str();
01309     CPPUNIT_ASSERT_EQUAL(expected, actual);
01310 
01311     // Boolstatement with condition m[r28] = r28, dest m[r28]
01312     BoolAssign* bs = new BoolAssign(8);
01313     bs->setCondExpr(new Binary(opEquals,
01314         Location::memOf(Location::regOf(28)),
01315         Location::regOf(28)));
01316     bs->setLeft(Location::memOf(Location::regOf(28)));
01317     std::ostringstream ost7;
01318     bs->subscriptVar(srch, &s9);
01319     ost7 << bs;
01320     expected="   0 BOOL m[r28{9}] := CC(equals)\n"
01321         "High level: m[r28{9}] = r28{9}\n";
01322     actual = ost7.str();
01323     CPPUNIT_ASSERT_EQUAL(expected, actual);
01324 }
01325 
01326 /*==============================================================================
01327  * FUNCTION:        StatementTest::testBypass
01328  * OVERVIEW:        Test the visitor code that fixes references that were to locations defined by calls
01329  *============================================================================*/
01330 void StatementTest::testBypass () {
01331     Prog* prog = new Prog;
01332     BinaryFileFactory bff;
01333     BinaryFile *pBF = bff.Load(GLOBAL1_PENTIUM);
01334     FrontEnd *pFE = new PentiumFrontEnd(pBF, prog, &bff);
01335     Type::clearNamedTypes();
01336     prog->setFrontEnd(pFE);
01337     pFE->decode(prog, true);                // Decode main
01338     pFE->decode(prog, NO_ADDRESS);          // Decode anything undecoded
01339     bool gotMain;
01340     ADDRESS addr = pFE->getMainEntryPoint(gotMain);
01341     CPPUNIT_ASSERT (addr != NO_ADDRESS);
01342     UserProc* proc = (UserProc*) prog->findProc("foo2");
01343     assert(proc);
01344     proc->promoteSignature();           // Make sure it's a PentiumSignature (needed for bypassing)
01345     Cfg* cfg = proc->getCFG();
01346     // Sort by address
01347     cfg->sortByAddress();
01348     // Initialise statements
01349     proc->initStatements();
01350     // Compute dominance frontier
01351     proc->getDataFlow()->dominators(cfg);
01352     // Number the statements
01353     //int stmtNumber = 0;
01354     proc->numberStatements();
01355     proc->getDataFlow()->renameBlockVars(proc, 0, 0);       // Block 0, mem depth 0
01356     proc->getDataFlow()->renameBlockVars(proc, 0, 1);       // Block 0, mem depth 1
01357     // Find various needed statements
01358     StatementList stmts;
01359     proc->getStatements(stmts);
01360     StatementList::iterator it = stmts.begin();
01361     while (!(*it)->isCall())
01362         it++;
01363     CallStatement* call = (CallStatement*)*it;  // Statement 18, a call to printf
01364     call->setDestProc(proc);                    // A recursive call
01365     // std::cerr << "Call is "; call->dump();
01366     advance(it, 2);
01367     Statement* s20 = *it;                       // Statement 20
01368     // FIXME: Ugh. Somehow, statement 20 has already bypassed the call, and incorrectly from what I can see - MVE
01369     s20->bypass();                              // r28 should bypass the call
01370     // Make sure it's what we expect!
01371     std::string expected("  20 *32* r28 := r28{-} - 16");
01372     std::string actual;
01373     std::ostringstream ost1;
01374     ost1 << s20;
01375     actual = ost1.str();
01376     //CPPUNIT_ASSERT_EQUAL(expected, actual);
01377 #if 0   // No longer needed, but could maybe expand the test one day
01378     // Fake it to be known that r29 is preserved
01379     Exp* r29 = Location::regOf(29);
01380     proc->setProven(new Binary(opEquals, r29, r29->clone()));
01381     (*it)->bypass();
01382     // Now expect r29{30} to be r29{3}
01383     expected = "  22 *32* r24 := m[r29{3} + 8]{-}";
01384     std::ostringstream ost2;
01385     ost2 << *it;
01386     actual = ost2.str();
01387     CPPUNIT_ASSERT_EQUAL(expected, actual);
01388 #endif
01389     delete pFE;
01390 }
01391 
01392 /*==============================================================================
01393  * FUNCTION:        StatementTest::testStripSizes
01394  * OVERVIEW:        Test the visitor code that strips out size casts
01395  *============================================================================*/
01396 void StatementTest::testStripSizes () {
01397     // *v* r24 := m[zfill(8,32,local5) + param6]*8**8* / 16
01398     // The double size casting happens as a result of substitution
01399     Exp* lhs = Location::regOf(24);
01400     Exp* rhs = new Binary(opDiv,
01401         new Binary(opSize,
01402             new Const(8),
01403             new Binary(opSize,
01404                 new Const(8),
01405                 Location::memOf(
01406                     new Binary(opPlus,
01407                         new Ternary(opZfill,
01408                             new Const(8),
01409                             new Const(32),
01410                             Location::local("local5", NULL)),
01411                         Location::local("param6", NULL))))),
01412         new Const(16));
01413     Statement* s = new Assign(lhs, rhs);
01414     s->stripSizes();
01415     std::string expected(
01416       "   0 *v* r24 := m[zfill(8,32,local5) + param6] / 16");
01417     std::string actual;
01418     std::ostringstream ost;
01419     ost << s;
01420     actual = ost.str();
01421     CPPUNIT_ASSERT_EQUAL(expected, actual);
01422 }
01423 
01424 /*==============================================================================
01425  * FUNCTION:        StatementTest::testFindConstants
01426  * OVERVIEW:        Test the visitor code that finds constants
01427  *============================================================================*/
01428 void StatementTest::testFindConstants () {
01429     Statement* a = new Assign(
01430         Location::regOf(24),
01431         new Binary(opPlus,
01432             new Const(3),
01433             new Const(4)));
01434     std::list<Const*> lc;
01435     a->findConstants(lc);
01436     std::list<Const*>::iterator it;
01437     std::ostringstream ost1;
01438     for (it = lc.begin(); it != lc.end(); ) {
01439         ost1 << *it;
01440         if (++it != lc.end())
01441             ost1 << ", ";
01442     }
01443     std::string actual = ost1.str();
01444     std::string expected("3, 4");
01445     CPPUNIT_ASSERT_EQUAL(expected, actual);
01446 }

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