ExpTest.cpp

Go to the documentation of this file.
00001 /*==============================================================================
00002  * FILE:       ExpTest.cc
00003  * OVERVIEW:   Provides the implementation for the ExpTest class, which
00004  *              tests the Exp and derived classes
00005  *============================================================================*/
00006 /*
00007  * $Revision: 1.37 $
00008  *
00009  * 05 Apr 02 - Mike: Fixed problems caused by lack of clone() calls
00010  * 09 Apr 02 - Mike: Compare, searchReplace
00011  * 14 Apr 02 - Mike: search and replace functions take Exp*, was Exp&
00012  * 27 Apr 02 - Mike: Added testDecideType
00013  * 09 Dec 02 - Mike: Added test for fixSuccessor
00014  * 13 Dec 02 - Mike: Added test for killFill()
00015  */
00016 
00017 #include "ExpTest.h"
00018 #include "statement.h"
00019 #include "visitor.h"
00020 #include <map>
00021 #include <sstream>      // Gcc >= 3.0 needed
00022 
00023 /*==============================================================================
00024  * FUNCTION:        ExpTest::registerTests
00025  * OVERVIEW:        Register the test functions in the given suite
00026  * PARAMETERS:      Pointer to the test suite
00027  * RETURNS:         <nothing>
00028  *============================================================================*/
00029 #define MYTEST(name) \
00030 suite->addTest(new CppUnit::TestCaller<ExpTest> ("testExp", \
00031     &ExpTest::name, *this))
00032 
00033 void ExpTest::registerTests(CppUnit::TestSuite* suite) {
00034 MYTEST(testFixSuccessor);
00035     MYTEST(test99);
00036     MYTEST(testFlt);
00037     MYTEST(testRegOf2);
00038     MYTEST(testBinaries);
00039     MYTEST(testUnaries);
00040     MYTEST(testIsAfpTerm);
00041     MYTEST(testCompare1);
00042     MYTEST(testCompare2);
00043     MYTEST(testCompare3);
00044     MYTEST(testCompare4);
00045     MYTEST(testCompare5);
00046     MYTEST(testCompare6);
00047     MYTEST(testSearchReplace1);
00048     MYTEST(testSearchReplace2);
00049     MYTEST(testSearchReplace3);
00050     MYTEST(testSearchReplace4);
00051     MYTEST(testSearch1);
00052     MYTEST(testSearch2);
00053     MYTEST(testSearch3);
00054     MYTEST(testSearchAll);
00055     MYTEST(testAccumulate);
00056     MYTEST(testPartitionTerms);
00057     MYTEST(testSimplifyArith);
00058     MYTEST(testSimplifyUnary);
00059     MYTEST(testSimplifyBinary);
00060     MYTEST(testSimplifyAddr);
00061     MYTEST(testSimpConstr);
00062 
00063     MYTEST(testLess);
00064     MYTEST(testMapOfExp);
00065     MYTEST(testList);
00066     MYTEST(testParen);
00067     MYTEST(testFixSuccessor);
00068     MYTEST(testKillFill);
00069     MYTEST(testAssociativity);
00070     MYTEST(testSubscriptVar);
00071     MYTEST(testTypeOf);
00072     MYTEST(testSetConscripts);
00073     MYTEST(testAddUsedLocs);
00074     MYTEST(testSubscriptVars);
00075     MYTEST(testVisitors);
00076 }
00077 
00078 int ExpTest::countTestCases () const
00079 { return 2; }   // ? What's this for?
00080 
00081 /*==============================================================================
00082  * FUNCTION:        ExpTest::setUp
00083  * OVERVIEW:        Set up some expressions for use with all the tests
00084  * NOTE:            Called before any tests
00085  * PARAMETERS:      <none>
00086  * RETURNS:         <nothing>
00087  *============================================================================*/
00088 void ExpTest::setUp () {
00089     m_99 = new Const(99);
00090     m_rof2 = new Location(opRegOf, new Const(2), NULL);
00091 }
00092 
00093 /*==============================================================================
00094  * FUNCTION:        ExpTest::tearDown
00095  * OVERVIEW:        Delete expressions created in setUp
00096  * NOTE:            Called after all tests
00097  * PARAMETERS:      <none>
00098  * RETURNS:         <nothing>
00099  *============================================================================*/
00100 void ExpTest::tearDown () {
00101     delete m_99;
00102     delete m_rof2;
00103 }
00104 
00105 /*==============================================================================
00106  * FUNCTION:        ExpTest::test99
00107  * OVERVIEW:        Test integer constant
00108  *============================================================================*/
00109 void ExpTest::test99 () {
00110     std::ostringstream ost;
00111     m_99->print(ost);
00112     CPPUNIT_ASSERT (std::string("99") == std::string(ost.str()));
00113 }
00114 
00115 /*============================================================================== * FUNCTION:        ExpTest::testFlt
00116  * OVERVIEW:        Test float constant
00117  *============================================================================*/void ExpTest::testFlt () {
00118     std::ostringstream ost;
00119     Const *c = new Const(3.14);
00120     c->print(ost);
00121     CPPUNIT_ASSERT_EQUAL (std::string("3.1400"), std::string(ost.str()));
00122     delete c;
00123 }
00124 
00125 /*==============================================================================
00126  * FUNCTION:        ExpTest::testRegOf2
00127  * OVERVIEW:        Tests r[2], which is used in many tests. Also tests opRegOf,
00128  *                  and ostream::operator&(Exp*)
00129  * NOTE:            r[2] prints as r2, as of June 2003
00130  *============================================================================*/
00131 void ExpTest::testRegOf2 () {
00132     std::ostringstream ost;
00133     ost << m_rof2;
00134     CPPUNIT_ASSERT_EQUAL (std::string("r2"), std::string(ost.str()));
00135 }
00136 
00137 /*==============================================================================
00138  * FUNCTION:        ExpTest::testBinaries
00139  * OVERVIEW:        Test opPlus, opMinus, etc
00140  *============================================================================*/
00141 void ExpTest::testBinaries () {
00142     std::ostringstream ost1;
00143     Binary* b = new Binary(opPlus, m_99->clone(), m_rof2->clone());
00144     b->print(ost1);
00145     CPPUNIT_ASSERT_EQUAL (std::string("99 + r2"), std::string(ost1.str()));
00146     delete b;
00147 
00148     std::ostringstream ost2;
00149     b = new Binary(opMinus, m_99->clone(), m_rof2->clone());
00150     b->print(ost2);
00151     CPPUNIT_ASSERT_EQUAL (std::string("99 - r2"), std::string(ost2.str()));
00152     delete b;
00153 
00154     std::ostringstream ost3;
00155     b = new Binary(opMult, m_99->clone(), m_rof2->clone());
00156     b->print(ost3);
00157     CPPUNIT_ASSERT_EQUAL (std::string("99 * r2"), std::string(ost3.str()));
00158     delete b;
00159 
00160     std::ostringstream ost4;
00161     b = new Binary(opDiv, m_99->clone(), m_rof2->clone());
00162     b->print(ost4);
00163     CPPUNIT_ASSERT_EQUAL (std::string("99 / r2"), std::string(ost4.str()));
00164     delete b;
00165 
00166     std::ostringstream ost5;
00167     b = new Binary(opMults, m_99->clone(), m_rof2->clone());
00168     b->print(ost5);
00169     CPPUNIT_ASSERT_EQUAL (std::string("99 *! r2"), std::string(ost5.str()));
00170     delete b;
00171 
00172     std::ostringstream ost6;
00173     b = new Binary(opDivs, m_99->clone(), m_rof2->clone());
00174     b->print(ost6);
00175     CPPUNIT_ASSERT_EQUAL (std::string("99 /! r2"), std::string(ost6.str()));
00176     delete b;
00177 
00178     std::ostringstream ost7;
00179     b = new Binary(opMod, m_99->clone(), m_rof2->clone());
00180     b->print(ost7);
00181     CPPUNIT_ASSERT_EQUAL (std::string("99 % r2"), std::string(ost7.str()));
00182     delete b;
00183 
00184     std::ostringstream ost8;
00185     b = new Binary(opMods, m_99->clone(), m_rof2->clone());
00186     b->print(ost8);
00187     CPPUNIT_ASSERT_EQUAL (std::string("99 %! r2"), std::string(ost8.str()));
00188     delete b;
00189 }
00190 
00191 /*==============================================================================
00192  * FUNCTION:        ExpTest::testUnaries
00193  * OVERVIEW:        Test LNot, unary minus, etc
00194  *============================================================================*/
00195 void ExpTest::testUnaries () {
00196     std::ostringstream ost1;
00197     Unary* u = new Unary(opNot, new Terminal(opZF));
00198     u->print(ost1);
00199     CPPUNIT_ASSERT_EQUAL (std::string("~%ZF"), std::string(ost1.str()));
00200     delete u;
00201 
00202     std::ostringstream ost2;
00203     u = new Unary(opLNot, new Terminal(opCF));
00204     u->print(ost2);
00205     CPPUNIT_ASSERT_EQUAL (std::string("L~%CF"), std::string(ost2.str()));
00206     delete u;
00207 
00208     std::ostringstream ost3;
00209     u = new Unary(opNeg, m_rof2->clone());
00210     u->print(ost3);
00211     CPPUNIT_ASSERT_EQUAL (std::string("-r2"), std::string(ost3.str()));
00212     delete u;
00213 
00214 }
00215 /*==============================================================================
00216  * FUNCTION:        ExpTest::testIsAfpTerm
00217  * OVERVIEW:        Test [ a[m[ ] %afp [+|- const]
00218  *============================================================================*/
00219 void ExpTest::testIsAfpTerm () {
00220     Terminal afp(opAFP);
00221     Binary plus(opPlus,   afp.clone(), new Const(-99));
00222     Binary minus(opMinus, afp.clone(), m_99->clone());
00223     CPPUNIT_ASSERT(   afp.  isAfpTerm());
00224     CPPUNIT_ASSERT(   plus. isAfpTerm());
00225     CPPUNIT_ASSERT(   minus.isAfpTerm());
00226     CPPUNIT_ASSERT(!m_99  ->isAfpTerm());
00227     CPPUNIT_ASSERT(!m_rof2->isAfpTerm());
00228     // Now with typed expressions
00229     TypedExp tafp(new IntegerType(), afp.clone());
00230     //Unary tafp  (opTypedExp, afp.clone());
00231     Unary tplus (opTypedExp, plus.clone());
00232     Unary tminus(opTypedExp, minus.clone());
00233     CPPUNIT_ASSERT(tafp.  isAfpTerm());
00234     CPPUNIT_ASSERT(tplus. isAfpTerm());
00235     CPPUNIT_ASSERT(tminus.isAfpTerm());
00236 }
00237 
00238 /*==============================================================================
00239  * FUNCTION:        ExpTest::testCompare1-6
00240  * OVERVIEW:        Test the operator== function
00241  *============================================================================*/
00242 void ExpTest::testCompare1 () {
00243     CPPUNIT_ASSERT(! (*m_99 == *m_rof2));
00244 }
00245 void ExpTest::testCompare2 () {
00246     Const nineNine(99);
00247     CPPUNIT_ASSERT(*m_99 == nineNine);
00248 }
00249 void ExpTest::testCompare3 () {
00250     Const minus(-99);
00251     CPPUNIT_ASSERT(! (*m_99 == minus));
00252 }
00253 void ExpTest::testCompare4 () {
00254     Location regOf2(opRegOf, new Const(2), NULL);
00255     CPPUNIT_ASSERT(regOf2 == *m_rof2);
00256 }
00257 void ExpTest::testCompare5 () {
00258     Binary one(opMult, m_99->clone(), m_rof2->clone());
00259     Binary two(opMult, m_rof2->clone(), m_99->clone());
00260     CPPUNIT_ASSERT(! (one == two) );
00261 }
00262 void ExpTest::testCompare6 () {
00263     Binary one(opMult, m_99->clone(), m_rof2->clone());
00264     Binary two(opMult, m_99->clone(), m_rof2->clone());
00265     CPPUNIT_ASSERT(  (one == two) );
00266 }
00267 
00268 /*==============================================================================
00269  * FUNCTION:        ExpTest::testSearchReplace1-4
00270  * OVERVIEW:        Test the searchReplace function
00271  *============================================================================*/
00272 void ExpTest::testSearchReplace1() {
00273     // Null test: should not replace. Also tests Ternary class
00274     Exp* p; bool change;
00275     p = new Ternary(opAt, m_rof2->clone(), new Const(15), new Const(8));
00276     p = p->searchReplace(m_99, m_rof2, change);
00277     std::string expected("r2@15:8");
00278     std::ostringstream ost;
00279     p->print(ost);
00280     std::string actual(ost.str());
00281     CPPUNIT_ASSERT_EQUAL(expected, actual);
00282     Ternary t2(*(Ternary*)p);
00283     CPPUNIT_ASSERT (*p == t2);
00284     p = p->searchReplaceAll(m_99, m_rof2, change);
00285     CPPUNIT_ASSERT (*p == t2);
00286     delete p;
00287 }
00288 
00289 void ExpTest::testSearchReplace2() {
00290     // Whole expression replacements
00291     bool change;
00292     Exp* p1 = new Const (55);
00293     Const p2(*(Const*)p1);
00294     Const c2(1234);
00295     p1 = p1->searchReplace(&p2, &c2, change);
00296     CPPUNIT_ASSERT(*p1 == c2);
00297     CPPUNIT_ASSERT(p1 != &c2);       // Pointers should not be same
00298     p1 = p1->searchReplace(&c2, m_rof2, change);
00299     CPPUNIT_ASSERT(*p1 == *m_rof2);
00300     delete p1;
00301 }
00302 
00303 void ExpTest::testSearchReplace3() {
00304     // Subexpression replacement
00305     bool change;
00306     Const two(2);
00307     Const three(3);
00308     Exp* p = m_rof2->clone();
00309     p = p->searchReplaceAll(&two, &three, change);
00310     std::string expected("r3");
00311     std::ostringstream ost;
00312     p->print(ost);
00313     std::string actual(ost.str());
00314     CPPUNIT_ASSERT_EQUAL(expected, actual);
00315     delete p;
00316 }
00317 void ExpTest::testSearchReplace4() {
00318     // Subexpression replacement with different subexpression form
00319     bool change;
00320     Const two(2);
00321     Exp* p = m_rof2->clone();
00322     // Note recursion. OK to use the all function, since it does the search
00323     // first.
00324     p = p->searchReplaceAll(&two, m_rof2, change);
00325     std::string expected("r[r2]");
00326     std::ostringstream ost;
00327     p->print(ost);
00328     std::string actual(ost.str());
00329     CPPUNIT_ASSERT_EQUAL(expected, actual);
00330     delete p;
00331 }
00332 
00333 /*==============================================================================
00334  * FUNCTION:        ExpTest::testSearch1-4
00335  * OVERVIEW:        Test the search function, including wildcards
00336  *============================================================================*/
00337 void ExpTest::testSearch1() {
00338     Const two(2);
00339     Exp* result;
00340     // Search inside r2 for const 2
00341     CPPUNIT_ASSERT(m_rof2->search(&two, result));
00342     CPPUNIT_ASSERT(*result == two);
00343 
00344     // Test for false positives
00345     CPPUNIT_ASSERT(! m_99->search(&two, result));
00346     CPPUNIT_ASSERT(! m_rof2->search(m_99, result));
00347 
00348     // Note: opDiv's enum has value 3
00349     Binary e(opMult, m_rof2->clone(), m_99->clone());   // r2 / 99
00350     Const three(3);
00351     CPPUNIT_ASSERT(! e.search(&three, result));
00352 }
00353 
00354 void ExpTest::testSearch2() {
00355     // Search using wildcards
00356     Binary e(opDivs, m_rof2->clone(), m_99->clone());   // r2 /! 99
00357     Exp* result;
00358     Location search(opRegOf, new Terminal(opWild), NULL);    // r[?]
00359     CPPUNIT_ASSERT(e.search(&search, result));
00360     CPPUNIT_ASSERT(*result == *m_rof2);             // Should be r2
00361 
00362     Const three(3);
00363     CPPUNIT_ASSERT(! e.search(&three, result));
00364     CPPUNIT_ASSERT(e.search(m_99, result));
00365 }
00366 
00367 void ExpTest::testSearch3() {
00368     // A more complex expression:
00369     // (r2 * 99) + (m[1000] * 4)
00370     Exp* result;
00371     Binary e(opPlus, new Binary(opMult, m_rof2->clone(), m_99->clone()),
00372         new Binary(opMult,
00373             Location::memOf(new Const(1000)),
00374             new Const(4)));
00375     Const four(4);
00376     Location mem1000(opMemOf, new Const(1000), NULL);
00377     Binary prod(opMult, m_rof2->clone(), m_99->clone());
00378     CPPUNIT_ASSERT(e.search(&four,   result));
00379     CPPUNIT_ASSERT(e.search(&mem1000,result));
00380     CPPUNIT_ASSERT(e.search(&prod,   result));
00381     CPPUNIT_ASSERT(e.search(m_99,  result));
00382     Const three(3);
00383     CPPUNIT_ASSERT(! e.search(&three, result));
00384 }
00385 
00386 void ExpTest::testSearchAll() {
00387     // A more complex expression:
00388     // (r2 * 99) + (r8 * 4)
00389     Location search(opRegOf, new Terminal(opWild), NULL);    // r[?]
00390     std::list<Exp*> result;
00391     Binary e(opPlus, new Binary(opMult, m_rof2->clone(), m_99->clone()),
00392         new Binary(opMult,
00393             Location::regOf(8),
00394             new Const(4)));
00395     CPPUNIT_ASSERT(e.searchAll(&search, result));
00396     CPPUNIT_ASSERT(result.size() == 2);
00397     CPPUNIT_ASSERT(*result.front() == *m_rof2);
00398     Location rof8(opRegOf, new Const(8), NULL);
00399     CPPUNIT_ASSERT(*result.back() == rof8);
00400 }
00401 /*==============================================================================
00402  * FUNCTION:        ExpTest::testAccumulate
00403  * OVERVIEW:        Test the Accumulate function
00404  *============================================================================*/
00405 void ExpTest::testAccumulate () {
00406     Location rof2(opRegOf, new Const(2), NULL);
00407     Const nineNine(99);
00408     // Zero terms
00409     std::list<Exp*> le;
00410     Exp* res = Exp::Accumulate(le);
00411     Const zero(0);
00412     CPPUNIT_ASSERT(*res == zero);
00413     delete res;
00414 
00415     // One term
00416     le.push_back(&rof2);
00417     res = Exp::Accumulate(le);
00418     CPPUNIT_ASSERT(*res == rof2);
00419     delete res;
00420 
00421     // Two terms
00422     Exp* nn = nineNine.clone();
00423     le.push_back(nn);
00424     res = Exp::Accumulate(le);
00425     Binary expected2(opPlus, rof2.clone(), nineNine.clone());
00426     CPPUNIT_ASSERT(*res == expected2);
00427     delete res;
00428 
00429     // Three terms, one repeated
00430     le.push_back(&nineNine);
00431     res = Exp::Accumulate(le);
00432     Binary expected3(opPlus, rof2.clone(),
00433         new Binary(opPlus, nineNine.clone(), nineNine.clone()));
00434     CPPUNIT_ASSERT(*res == expected3);
00435     delete res;
00436 
00437     // Four terms, one repeated
00438     Terminal afp(opAFP);
00439     le.push_back(&afp);
00440     res = Exp::Accumulate(le);
00441     Binary expected4(opPlus, rof2.clone(),
00442         new Binary(opPlus, nineNine.clone(), 
00443             new Binary(opPlus, nineNine.clone(), new Terminal(opAFP))));
00444     CPPUNIT_ASSERT(*res == expected4);
00445     delete res;
00446     delete nn;
00447 }  
00448 
00449 /*==============================================================================
00450  * FUNCTION:        ExpTest::testPartitionTerms
00451  * OVERVIEW:        Test the partitionTerms function
00452  *============================================================================*/
00453 void ExpTest::testPartitionTerms() {
00454     std::ostringstream ost;
00455     // afp + 108 + n - (afp + 92)
00456     Binary e(opMinus,
00457         new Binary(opPlus,
00458             new Binary(opPlus, new Terminal(opAFP), new Const(108)),
00459             new Unary(opVar, new Const("n"))),
00460         new Binary(opPlus, new Terminal(opAFP), new Const(92))
00461     );
00462     std::list<Exp*> positives, negatives;
00463     std::vector<int> integers;
00464     e.partitionTerms(positives, negatives, integers, false);
00465     Exp* res = Exp::Accumulate(positives);
00466     Binary expected1(opPlus, new Terminal(opAFP),
00467         new Unary(opVar, new Const("n")));
00468     CPPUNIT_ASSERT(*res == expected1);
00469     delete res;
00470 
00471     res = Exp::Accumulate(negatives);
00472     Terminal expected2(opAFP);
00473     CPPUNIT_ASSERT(*res == expected2);
00474     int size = integers.size();
00475     CPPUNIT_ASSERT_EQUAL(2, size);
00476     CPPUNIT_ASSERT_EQUAL(108, integers.front());
00477     CPPUNIT_ASSERT_EQUAL(-92, integers.back());
00478     delete res;
00479 }
00480 
00481 /*==============================================================================
00482  * FUNCTION:        ExpTest::testSimplifyArith
00483  * OVERVIEW:        Test the simplifyArith function
00484  *============================================================================*/
00485 void ExpTest::testSimplifyArith() {
00486     std::ostringstream ost;
00487     // afp + 108 + n - (afp + 92)
00488     Exp* e = new Binary(opMinus,
00489         new Binary(opPlus,
00490             new Binary(opPlus, new Terminal(opAFP), new Const(108)),
00491             new Unary(opVar, new Const("n"))),
00492         new Binary(opPlus, new Terminal(opAFP), new Const(92))
00493     );
00494     e = e->simplifyArith();
00495     e->print(ost);
00496     std::string expected ("v[n] + 16");
00497     CPPUNIT_ASSERT_EQUAL(expected, std::string(ost.str()));
00498     delete e;
00499 
00500     // m[(r28 + -4) + 8]
00501     Exp* mm = Location::memOf(
00502         new Binary(opPlus,
00503             new Binary(opPlus,
00504                 Location::regOf(28),
00505                 new Const(-4)),
00506             new Const(8)));
00507     mm = mm->simplifyArith();
00508     std::ostringstream ost2;
00509     mm->print(ost2);
00510     expected = "m[r28 + 4]";
00511     CPPUNIT_ASSERT_EQUAL(expected, std::string(ost2.str()));
00512     delete mm;
00513    
00514     // r24 + m[(r28 - 4) - 4] 
00515     mm = new Binary(opPlus,
00516         Location::regOf(24),
00517         Location::memOf(
00518             new Binary(opMinus,
00519                 new Binary(opMinus,
00520                     Location::regOf(28),
00521                     new Const(4)),
00522                 new Const(4))));
00523     mm = mm->simplifyArith();
00524     std::ostringstream ost3;
00525     mm->print(ost3);
00526     expected = "r24 + m[r28 - 8]";
00527     CPPUNIT_ASSERT_EQUAL(expected, std::string(ost3.str()));
00528     delete mm;
00529 }
00530 
00531 /*==============================================================================
00532  * FUNCTION:        ExpTest::testSimplifyUnary
00533  * OVERVIEW:        Test the simplifyArith function
00534  *============================================================================*/
00535 void ExpTest::testSimplifyUnary() {
00536     // Unaries with integer constant argument
00537     Exp* u = new Unary(opNeg, new Const (55));
00538     u = u->simplify();
00539     Const minus55(-55);
00540     CPPUNIT_ASSERT(*u == minus55);
00541     delete u;
00542 
00543     u = new Unary(opNot, new Const(0x55AA));
00544     u = u->simplify();
00545     Const exp((int)0xFFFFAA55);
00546     CPPUNIT_ASSERT(*u == exp);
00547     delete u;
00548 
00549     u = new Unary(opLNot, new Const(55));
00550     u = u->simplify();
00551     Const zero(0);
00552     CPPUNIT_ASSERT(*u == zero);
00553     delete u;
00554 
00555     u = new Unary(opLNot, zero.clone());
00556     u = u->simplify();
00557     Const one(1);
00558     CPPUNIT_ASSERT(*u == one);
00559     delete u;
00560 
00561     // Null test
00562     u = new Unary(opNeg, new Unary(opVar, new Const("abc")));
00563     Unary abc(opNeg, new Unary(opVar, new Const("abc")));
00564     CPPUNIT_ASSERT(*u == abc);
00565     delete u;
00566 }
00567 
00568 /*==============================================================================
00569  * FUNCTION:        ExpTest::testSimplifyBinary
00570  * OVERVIEW:        Test the simplifyArith function
00571  *============================================================================*/
00572 void ExpTest::testSimplifyBinary() {
00573     // Add integer consts
00574     Exp* b = new Binary(opPlus, new Const(2), new Const(3));
00575     b = b->simplify();
00576     Const five(5);
00577     CPPUNIT_ASSERT(*b == five);
00578     delete b;
00579 
00580     // Multiply integer consts
00581     b = new Binary(opMult, new Const(2), new Const(3));
00582     b = b->simplify();
00583     Const six(6);
00584     CPPUNIT_ASSERT(*b == six);
00585     delete b;
00586 
00587     // Shift left two integer constants
00588     b = new Binary(opShiftL, new Const(2), new Const(3));
00589     b = b->simplify();
00590     Const sixteen(16);
00591     CPPUNIT_ASSERT(*b == sixteen);
00592     delete b;
00593 
00594     // Shift right arithmetic two integer contants
00595     b = new Binary(opShiftRA, new Const(-144), new Const(3));
00596     b = b->simplify();
00597     Const minus18(-18);
00598     CPPUNIT_ASSERT(*b == minus18);
00599     delete b;
00600 
00601     // Bitwise XOR
00602     b = new Binary(opBitXor, new Const(0x55), new Const(0xF));
00603     b = b->simplify();
00604     Const fiveA(0x5A);
00605     CPPUNIT_ASSERT(*b == fiveA);
00606     delete b;
00607 
00608     // Xor with self
00609     b = new Binary(opBitXor, m_rof2->clone(), m_rof2->clone());
00610     b = b->simplify();
00611     Const zero(0);
00612     CPPUNIT_ASSERT(*b == zero);
00613     delete b;
00614 
00615     // Test commute
00616     // 77 * r2
00617     b = new Binary(opMults, new Const(77), m_rof2->clone());
00618     b = b->simplify();
00619     // r2 * 77
00620     Binary exp(opMults, m_rof2->clone(), new Const(77));
00621     CPPUNIT_ASSERT(*b == exp);
00622 
00623     // x*1
00624     ((Const*)b->getSubExp2())->setInt(1);
00625     b = b->simplify();
00626     CPPUNIT_ASSERT(*b == *m_rof2);
00627     delete b;
00628 
00629     // 0 | r2
00630     b = new Binary(opBitOr, new Const(0), m_rof2->clone());
00631     b = b->simplify();
00632     CPPUNIT_ASSERT(*b == *m_rof2);
00633     delete b;
00634 
00635     // Left shift by const
00636     b = new Binary(opShiftL, m_rof2->clone(), new Const(0));
00637     b = b->simplify();
00638     CPPUNIT_ASSERT(*b == *m_rof2);
00639     delete b;
00640 
00641     b = new Binary(opShiftL, m_rof2->clone(), new Const(2));
00642     b = b->simplify();
00643     Binary expb1(opMult, m_rof2->clone(), new Const(4));
00644     CPPUNIT_ASSERT(*b == expb1);
00645     delete b;
00646 
00647     // Add negative constant
00648     // r2 + -99
00649     b = new Binary(opPlus, m_rof2->clone(), new Const(-99));
00650     // r2 - 99
00651     Exp* expb2 = new Binary(opMinus, m_rof2->clone(), new Const(99));
00652     // As of June 2003, I've decided to go the old way. esp + -4 is just
00653     // too ugly, and all the code has to cope with pluses and minuses anyway,
00654     // just in case
00655 #define OLD_WAY 1
00656 #if OLD_WAY
00657     b = b->simplify();
00658 #else
00659     expb2 = expb2->simplify();
00660 #endif
00661     CPPUNIT_ASSERT(*b == *expb2);
00662     delete b; delete expb2;
00663 
00664     std::string expected("((0 + v[a]) - 0) | 0");
00665     std::ostringstream ost;
00666     Exp* e =
00667         new Binary(opBitOr,
00668             new Binary(opMinus,
00669                 new Binary(opPlus,
00670                     new Const(0),
00671                     new Unary(opVar,
00672                         new Const("a")
00673                     )
00674                 ),
00675                 new Const(0)
00676             ),
00677             new Const(0)
00678         );
00679     e->print(ost);
00680     CPPUNIT_ASSERT_EQUAL(expected, std::string(ost.str()));
00681     // The above should simplify to just "v[a]"
00682     e = e->simplify();
00683     Unary a(opVar, new Const("a"));
00684     expected = "v[a]";
00685     std::ostringstream ost2;
00686     e->print(ost2);
00687     CPPUNIT_ASSERT_EQUAL(expected, ost2.str());
00688     delete e;
00689 
00690     // r27 := m[r29 + -4]
00691     Assign* as = new Assign(
00692         Location::regOf(27),
00693         Location::memOf(
00694             new Binary(opPlus,
00695                 Location::regOf(29),
00696                 new Const(-4))));
00697     as->simplify();
00698     expected = "   0 *v* r27 := m[r29 - 4]";
00699     std::ostringstream ost3;
00700     as->print(ost3);
00701     CPPUNIT_ASSERT_EQUAL(expected, ost3.str());
00702     delete as;
00703 
00704     // (false and true) or (Tr24 = <int>)
00705     e = new Binary(opOr,
00706         new Binary(opAnd,
00707             new Terminal(opFalse),
00708             new Terminal(opTrue)),
00709         new Binary(opEquals,
00710             new Unary(opTypeOf, Location::regOf(24)),
00711             new TypeVal(new IntegerType(32, 1))));
00712     e = e->simplify();
00713     expected = "T[r24] = <int>";
00714     std::ostringstream ost4;
00715     e->print(ost4);
00716     CPPUNIT_ASSERT_EQUAL(expected, ost4.str());
00717     delete e;
00718 }
00719 
00720 /*==============================================================================
00721  * FUNCTION:        ExpTest::testSimplifyBinary
00722  * OVERVIEW:        Test the simplifyArith function
00723  *============================================================================*/
00724 void ExpTest::testSimplifyAddr() {
00725     // a[m[1000]] - a[m[r2]{64}]@0:15
00726     Exp* e = new Binary(opMinus,
00727         new Unary(opAddrOf,
00728             Location::memOf(
00729                 new Const(1000))),
00730         new Ternary(opAt,
00731             new Unary(opAddrOf,
00732                 new Binary(opSize,
00733                     new Const(64),
00734                     Location::memOf(
00735                         Location::regOf(2)
00736                             ))),
00737             new Const(0),
00738             new Const(15)));
00739     e = e->simplifyAddr();
00740     std::ostringstream ost;
00741     e->print(ost);
00742     std::string actual(ost.str());
00743     std::string expected("1000 - (r2@0:15)");
00744     CPPUNIT_ASSERT_EQUAL(expected, actual);
00745 
00746     // Now test at top level
00747     delete e;
00748     e = new Unary(opAddrOf,
00749         Location::memOf(
00750             new Const(1000)));
00751     expected = "1000";
00752     e = e->simplifyAddr();
00753     std::ostringstream ost2;
00754     e->print(ost2);
00755     actual = ost2.str();
00756     CPPUNIT_ASSERT_EQUAL(expected, actual);
00757     delete e;
00758 
00759 }
00760 
00761 /*==============================================================================
00762  * FUNCTION:        ExpTest::testSimpConstr
00763  * OVERVIEW:        Test the simplifyConstraint functions
00764  *============================================================================*/
00765 void ExpTest::testSimpConstr() {
00766     // After
00767     //   (T[local1{16}] = <int>) or (Tlocal1{16} = <alpha2*>)
00768     // gets substituted to
00769     //   (<char*> = <int>) or (<char*> = <alpha2*>)
00770     // it should simplify to
00771     //  <char*> = <alpha2*>
00772     Exp* e = new Binary(opOr,
00773         new Binary(opEquals,
00774             new TypeVal(new PointerType(new CharType())),
00775             new TypeVal(new IntegerType())),
00776         new Binary(opEquals,
00777             new TypeVal(new PointerType(new CharType())),
00778             new TypeVal(PointerType::newPtrAlpha())));
00779     e = e->simplifyConstraint();
00780     std::string expected("<char *> = <alpha0 *>");
00781     std::ostringstream ost;
00782     e->print(ost);
00783     std::string actual = ost.str();
00784     CPPUNIT_ASSERT_EQUAL(expected, actual);
00785     delete e;
00786 
00787     // Similarly,
00788     //   <char*> = <alpha0*>) and (T[134517848\1\] = <alpha0*>
00789     // becomes after alpha substitution
00790     //   (<char*> = <char*>) and (T[134517848\1\] = <char*>)
00791     // which should simplify to
00792     //   T[134517848\1\] = <char*>
00793     e = new Binary(opAnd,
00794         new Binary(opEquals,
00795             new TypeVal(new PointerType(new CharType())),
00796             new TypeVal(new PointerType(new CharType()))),
00797         new Binary(opEquals,
00798             new Unary(opTypeOf, new Const(0x123456)),
00799             new TypeVal(new PointerType(new CharType()))));
00800     e = e->simplifyConstraint();
00801     expected = "T[0x123456] = <char *>";
00802     std::ostringstream ost2;
00803     e->print(ost2);
00804     actual = ost2.str();
00805     CPPUNIT_ASSERT_EQUAL(expected, actual);
00806 }
00807 
00808 /*==============================================================================
00809  * FUNCTION:        ExpTest::testLess
00810  * OVERVIEW:        Various tests of the operator< function
00811  *============================================================================*/
00812 void ExpTest::testLess() {
00813     // Simple constants
00814     Const two(2), three(3), mThree(-3), twoPointTwo(2.2), threePointThree(3.3);
00815     Const mThreePointThree(-3.3);
00816     CPPUNIT_ASSERT(two < three);
00817     CPPUNIT_ASSERT(mThree < two);
00818     CPPUNIT_ASSERT(twoPointTwo < threePointThree);
00819     CPPUNIT_ASSERT(mThreePointThree < twoPointTwo);
00820     // Terminal
00821     Terminal afp(opAFP), agp(opAGP);
00822     if (opAFP < opAGP)
00823         CPPUNIT_ASSERT(afp < agp);
00824     else
00825         CPPUNIT_ASSERT(agp < afp);
00826     // Unary
00827     Unary negTwo(opNeg, new Const(2)), negThree(opNeg, new Const(3));
00828     // Note that the ordering is not arithmetic!
00829     CPPUNIT_ASSERT(negTwo < negThree);
00830     // Binary
00831     Binary twoByThr(opMult, new Const(2), new Const(3));
00832     Binary twoByFou(opMult, new Const(2), new Const(4));
00833     Binary thrByThr(opMult, new Const(3), new Const(3));
00834     CPPUNIT_ASSERT(twoByThr < twoByFou);
00835     CPPUNIT_ASSERT(twoByThr < thrByThr);
00836     // Ternary
00837     Ternary twoAtThrToFou(opAt, new Const(2), new Const(3), new Const(4));
00838     Ternary twoAtThrToFiv(opAt, new Const(2), new Const(3), new Const(5));
00839     CPPUNIT_ASSERT(twoAtThrToFou < twoAtThrToFiv);
00840     // TypedExp later
00841 }
00842 /*==============================================================================
00843  * FUNCTION:        ExpTest::testMapOfExp
00844  * OVERVIEW:        Test maps of Exp*s; exercises some comparison operators
00845  *============================================================================*/
00846 void ExpTest::testMapOfExp() {
00847     std::map<Exp*, int, lessExpStar> m;
00848     m[m_rof2] = 200;
00849     m[m_99] = 99;
00850     Exp* e = new Binary(opPlus, new Const(0),
00851         new Binary(opMinus,
00852             new Binary(opMult, new Const(2), new Const(3)),
00853             new Binary(opMult, new Const(4), new Const(5))));
00854     m[e] = -100;
00855     Location rof2(opRegOf, new Const(2), NULL);
00856     m[&rof2] = 2;            // Should overwrite
00857 
00858     int i = m.size();
00859     CPPUNIT_ASSERT_EQUAL(3, i); 
00860     i = m[m_rof2];
00861     CPPUNIT_ASSERT_EQUAL(2, i);
00862     i = m[&rof2];
00863     CPPUNIT_ASSERT_EQUAL(2, i);
00864     i = m[m_99];
00865     CPPUNIT_ASSERT_EQUAL(99, i);
00866     i = m[e];
00867     CPPUNIT_ASSERT_EQUAL(-100, i); 
00868     // When the map goes out of scope, the expressions pointed to still exist
00869     delete e;
00870 }
00871 
00872 /*==============================================================================
00873  * FUNCTION:        Exp::testList
00874  * OVERVIEW:        Test the opList creating and printing
00875  *============================================================================*/
00876 void ExpTest::testList () {
00877     std::ostringstream o0, o1, o2, o3, o4;
00878     Exp *l0, *l1, *l2, *l3, *l4;
00879     // Empty list
00880     l0 = new Binary(opList, new Terminal(opNil), new Terminal(opNil));
00881     o0 << l0;
00882     std::string expected0("");
00883     std::string actual0(o0.str());
00884     CPPUNIT_ASSERT_EQUAL(expected0, actual0);
00885     delete l0;
00886 
00887     // 1 element list
00888     l1 = new Binary(opList,
00889         new Location(opParam, new Const("a"), NULL),
00890         new Terminal(opNil));
00891     o1 << l1;
00892     std::string expected1("a");
00893     std::string actual1(o1.str());
00894     CPPUNIT_ASSERT_EQUAL(expected1, actual1);
00895     delete l1;
00896 
00897     // 2 element list
00898     l2 = new Binary(opList,
00899         new Location(opParam, new Const("a"), NULL),
00900         new Binary(opList,
00901             new Location(opParam, new Const("b"), NULL),
00902             new Terminal(opNil)));
00903     o2 << l2;
00904     std::string expected2("a, b");
00905     std::string actual2(o2.str());
00906     CPPUNIT_ASSERT_EQUAL(expected2, actual2);
00907     delete l2;
00908 
00909     // 3 element list
00910     l3 = new Binary(opList,
00911         new Location(opParam, new Const("a"), NULL),
00912         new Binary(opList,
00913             new Location(opParam, new Const("b"), NULL),
00914             new Binary(opList,
00915                 new Location(opParam, new Const("c"), NULL),
00916                 new Terminal(opNil))));
00917     o3 << l3;
00918     std::string expected3("a, b, c");
00919     std::string actual3(o3.str());
00920     CPPUNIT_ASSERT_EQUAL(expected3, actual3);
00921     delete l3;
00922 
00923     // 4 element list
00924     l4 = new Binary(opList,
00925         new Location(opParam, new Const("a"), NULL),
00926         new Binary(opList,
00927             new Location(opParam, new Const("b"), NULL),
00928             new Binary(opList,
00929                 new Location(opParam, new Const("c"), NULL),
00930                 new Binary(opList,
00931                     new Location(opParam, new Const("d"), NULL),
00932                     new Terminal(opNil)))));
00933     o4 << l4;
00934     std::string expected4("a, b, c, d");
00935     std::string actual4(o4.str());
00936     CPPUNIT_ASSERT_EQUAL(expected4, actual4);
00937     delete l4;
00938 }
00939 
00940 /*==============================================================================
00941  * FUNCTION:        ExpTest::testParens
00942  * OVERVIEW:        Test the printing of parentheses in complex expressions
00943  *============================================================================*/
00944 void ExpTest::testParen () {
00945     Assign a(
00946         Location::regOf(
00947             new Location(opParam, new Const("rd"), NULL)),
00948         new Binary(opBitAnd,
00949             Location::regOf(
00950                 new Location(opParam, new Const("rs1"), NULL)),
00951             new Binary(opMinus,
00952                 new Binary(opMinus,
00953                     new Const(0),
00954                     new Location(opParam, new Const("reg_or_imm"), NULL)),
00955                 new Const(1))));
00956     std::string expected("   0 *v* r[rd] := r[rs1] & ((0 - reg_or_imm) - 1)");
00957     std::ostringstream o;
00958     a.print(o);
00959     // a.createDotFile("andn.dot");
00960     std::string actual(o.str());
00961     CPPUNIT_ASSERT_EQUAL(expected, actual);
00962 }
00963 
00964 /*==============================================================================
00965  * FUNCTION:        ExpTest::testFixSuccessor
00966  * OVERVIEW:        Test succ(r[k]) == r[k+1]
00967  *============================================================================*/
00968 void ExpTest::testFixSuccessor() {
00969     // Trivial test (should not affect)
00970     Binary* b = new Binary(opMinus,
00971         m_99->clone(),
00972         m_rof2->clone());
00973     std::ostringstream o1;
00974     Exp* e = b->fixSuccessor();
00975     e->print(o1);
00976     std::string expected("99 - r2");
00977     std::string actual(o1.str());
00978     CPPUNIT_ASSERT_EQUAL(expected, actual);
00979     delete e;
00980     
00981     Unary* u = new Unary(opSuccessor,
00982         Location::regOf(2));
00983     std::ostringstream o2;
00984     e = u->fixSuccessor();
00985     e->print(o2);
00986     expected = "r3";
00987     actual = o2.str();
00988     CPPUNIT_ASSERT_EQUAL(expected, actual);
00989     delete e;
00990 }
00991 
00992 /*==============================================================================
00993  * FUNCTION:        ExpTest::testKillFill
00994  * OVERVIEW:        Test removal of zero fill, sign extend, truncates
00995  *============================================================================*/
00996 void ExpTest::testKillFill() {
00997     // r18 + sgnex(16,32,m[r16 + 16])
00998     Binary e(opPlus,
00999         Location::regOf(18),
01000         new Ternary(opSgnEx, new Const(16), new Const(32),
01001             Location::memOf(
01002                 new Binary(opPlus,
01003                     Location::regOf(16),
01004                     new Const(16)))));
01005     Exp* res = e.killFill();
01006     std::string expected("r18 + m[r16 + 16]");
01007     std::ostringstream ost1;
01008     res->print(ost1);
01009     std::string actual(ost1.str());
01010     CPPUNIT_ASSERT_EQUAL(expected, actual);
01011 
01012     // Note: e2 has to be a pointer, not a local Ternary, because it
01013     // gets changed at the top level (and so would die in its destructor)
01014     Ternary* e2 = new Ternary(opZfill, new Const(16), new Const(32),
01015             Location::memOf(
01016                 new Binary(opPlus,
01017                     Location::regOf(16),
01018                     new Const(16))));
01019     // Try again but at top level
01020     res = e2->killFill();
01021     expected = "m[r16 + 16]";
01022     std::ostringstream ost2;
01023     res->print(ost2);
01024     actual = ost2.str();
01025     CPPUNIT_ASSERT_EQUAL(expected, actual);
01026     delete res;
01027 
01028 }
01029 
01030 /*==============================================================================
01031  * FUNCTION:        ExpTest::testAssociativity
01032  * OVERVIEW:        Test that a+K+b is the same as a+b+K when each is simplified
01033  *============================================================================*/
01034 void ExpTest::testAssociativity() {
01035     
01036     // (r8 + m[m[r8 + 12] + -12]) + 12
01037     Binary e1(opPlus,
01038         new Binary(opPlus,
01039             Location::regOf(8),
01040             Location::memOf(
01041                 new Binary(opPlus,
01042                     Location::memOf(
01043                         new Binary(opPlus,
01044                             Location::regOf(8),
01045                             new Const(12))),
01046                     new Const(-12)))),
01047         new Const(12));
01048     // (r8 + 12) + m[m[r8 + 12] + -12]
01049     Binary e2(opPlus,
01050         new Binary(opPlus,
01051             Location::regOf(8),
01052             new Const(12)),
01053         Location::memOf(
01054             new Binary(opPlus,
01055                 Location::memOf(
01056                     new Binary(opPlus,
01057                         Location::regOf(8),
01058                         new Const(12))),
01059                 new Const(-12))));
01060     // Note: at one stage, simplifyArith was part of simplify().
01061     // Now call implifyArith() explicitly only where needed
01062     Exp* p1 = e1.simplify()->simplifyArith();
01063     Exp* p2 = e2.simplify()->simplifyArith();
01064     std::ostringstream os1, os2;
01065     p1->print(os1); p2->print(os2);
01066     std::string expected(os1.str());
01067     std::string actual  (os2.str());
01068     CPPUNIT_ASSERT_EQUAL(expected, actual);
01069 }
01070 
01071 /*==============================================================================
01072  * FUNCTION:        ExpTest::testSubscriptVar
01073  * OVERVIEW:        Test Assign::subscriptVar and thereby Exp::expSubscriptVar
01074  *============================================================================*/
01075 void ExpTest::testSubscriptVar() {
01076     // m[r28 - 4] := r28 + r29
01077     Exp* left = Location::memOf(
01078             new Binary(opMinus,
01079                 Location::regOf(28),
01080                 new Const(4)));
01081     Assign* ae = new Assign(
01082         left->clone(),
01083         new Binary(opPlus,
01084             Location::regOf(28),
01085             Location::regOf(29)));
01086 
01087     Statement* s = dynamic_cast<Statement*>(ae);
01088     // Subtest 1: should do nothing
01089     Exp* r28 = Location::regOf(28);
01090     Statement* def1 = dynamic_cast<Statement*>(new Assign(r28->clone(), r28->clone()));
01091     def1->setNumber(12);
01092     def1->subscriptVar(left, def1);           // Should do nothing
01093     std::string expected1;
01094     expected1 = "   0 *v* m[r28 - 4] := r28 + r29";
01095     std::ostringstream actual1;
01096     actual1 << s;
01097     CPPUNIT_ASSERT_EQUAL(expected1, actual1.str());
01098     // m[r28 - 4]
01099 
01100     // Subtest 2: Ordinary substitution, on LHS and RHS
01101     s->subscriptVar(r28, def1);
01102     std::string expected2("   0 *v* m[r28{12} - 4] := r28{12} + r29");
01103     std::ostringstream actual2;
01104     actual2 << s;
01105     CPPUNIT_ASSERT_EQUAL(expected2, actual2.str());
01106 
01107     // Subtest 3: change to a different definition
01108     // 99: r28 := 0
01109     // Note: behaviour has changed. Now, we don't allow re-renaming, so it should stay the same
01110     Statement* def3 = new Assign(Location::regOf(28), new Const(0));
01111     def3->setNumber(99);
01112     s->subscriptVar(r28, def3);
01113     std::string expected3("   0 *v* m[r28{12} - 4] := r28{12} + r29");
01114     std::ostringstream actual3;
01115     actual3 << s;
01116     CPPUNIT_ASSERT_EQUAL(expected3, actual3.str());
01117 
01118     delete ae; delete def1; delete def3; delete r28; delete left;
01119 }
01120 
01121 /*==============================================================================
01122  * FUNCTION:        ExpTest::testTypeOf
01123  * OVERVIEW:        Test opTypeOf and TypeVal (type values)
01124  *============================================================================*/
01125 void ExpTest::testTypeOf() {
01126     // Tr24{5} = Tr25{9}
01127     std::string expected1("T[r24{5}] = T[r25{9}]");
01128     Statement* s5 = new Assign;
01129     Statement* s9 = new Assign;
01130     s5->setNumber(5);
01131     s9->setNumber(9);
01132     Exp* e = new Binary(opEquals,
01133         new Unary(opTypeOf,
01134             new RefExp(Location::regOf(24), s5)),
01135         new Unary(opTypeOf,
01136             new RefExp(Location::regOf(25), s9)));
01137     std::ostringstream actual1;
01138     actual1 << e;
01139     CPPUNIT_ASSERT_EQUAL(expected1, actual1.str());
01140 
01141     // Tr24{5} = <float>
01142     std::string expected2("T[r24{5}] = <float>");
01143     delete e;
01144     Type* t = new FloatType(32);
01145     e = new Binary(opEquals,
01146         new Unary(opTypeOf,
01147             new RefExp(Location::regOf(24), s5)),
01148         new TypeVal(t));
01149     std::ostringstream actual2;
01150     actual2 << e;
01151     CPPUNIT_ASSERT_EQUAL(expected2, actual2.str());
01152 }
01153 /*==============================================================================
01154  * FUNCTION:        ExpTest::testSetConscript
01155  * OVERVIEW:        Test setting and printing of constant "subscripts"
01156  *============================================================================*/
01157 void ExpTest::testSetConscripts() {
01158     // m[1000] + 1000
01159     Exp* e = new Binary(opPlus,
01160         Location::memOf(
01161             new Const(1000), NULL),
01162         new Const(1000));
01163     e->setConscripts(0, false);
01164     std::string expected("m[1000\\1\\] + 1000\\2\\");
01165     std::ostringstream actual;
01166     actual << e;
01167     CPPUNIT_ASSERT_EQUAL(expected, actual.str());
01168 
01169     // Clear them
01170     e->setConscripts(0, true);
01171     expected = "m[1000] + 1000";
01172     std::ostringstream actual1;
01173     actual1 << e;
01174     CPPUNIT_ASSERT_EQUAL(expected, actual1.str());
01175 
01176     // m[r28 + 1000]
01177     e = Location::memOf(
01178         new Binary(opPlus,
01179             Location::regOf(28),
01180             new Const(1000)));
01181     e->setConscripts(0, false);
01182     expected = "m[r28 + 1000\\1\\]";
01183     std::ostringstream act2;
01184     act2 << e;
01185     CPPUNIT_ASSERT_EQUAL(expected, act2.str());
01186 
01187     // Clear
01188     e->setConscripts(0, true);
01189     expected = "m[r28 + 1000]";
01190     std::ostringstream act3;
01191     act3 << e;
01192     CPPUNIT_ASSERT_EQUAL(expected, act3.str());
01193 }
01194 
01195 /*==============================================================================
01196  * FUNCTION:        ExpTest::testAddUsedLocs
01197  * OVERVIEW:        Test finding the locations used by an expression
01198  *============================================================================*/
01199 void ExpTest::testAddUsedLocs() {
01200     // Null case
01201     Exp* e = new Terminal(opNil);
01202     LocationSet l;
01203     e->addUsedLocs(l);
01204     CPPUNIT_ASSERT(l.size() == 0);
01205 
01206     // Const: "foo"
01207     e = new Const("foo");
01208     e->addUsedLocs(l);
01209     CPPUNIT_ASSERT(l.size() == 0);
01210 
01211     // Simple terminal: %pc
01212     e = new Terminal(opPC);
01213     e->addUsedLocs(l);
01214     std::string expected = "%pc";
01215     std::ostringstream ost1;
01216     l.print(ost1);
01217     std::string actual = ost1.str();
01218     CPPUNIT_ASSERT_EQUAL(expected, actual);
01219 
01220     // Simple location: r28
01221     l.clear();
01222     e = Location::regOf(28);
01223     e->addUsedLocs(l);
01224     expected = "r28";
01225     std::ostringstream ost2;
01226     l.print(ost2);
01227     actual = ost2.str();
01228     CPPUNIT_ASSERT_EQUAL(expected, actual);
01229 
01230     // Memory location: m[r28-4]
01231     l.clear();
01232     e = Location::memOf(
01233         new Binary(opMinus,
01234             Location::regOf(28),
01235             new Const(4)));
01236     e->addUsedLocs(l);
01237     expected = "r28,\tm[r28 - 4]";
01238     std::ostringstream ost3;
01239     l.print(ost3);
01240     actual = ost3.str();
01241     CPPUNIT_ASSERT_EQUAL(expected, actual);
01242 
01243     // Unary: a[m[r28-4]]
01244     l.clear();
01245     e = new Unary(opAddrOf, e);
01246     e->addUsedLocs(l);
01247     expected = "r28,\tm[r28 - 4]";
01248     std::ostringstream ost4;
01249     l.print(ost4);
01250     actual = ost4.str();
01251     CPPUNIT_ASSERT_EQUAL(expected, actual);
01252 
01253     // Binary: r24 + r25
01254     l.clear();
01255     e = new Binary(opPlus,
01256         Location::regOf(24),
01257         Location::regOf(25));
01258     e->addUsedLocs(l);
01259     expected = "r24,\tr25";
01260     std::ostringstream ost5;
01261     l.print(ost5);
01262     actual = ost5.str();
01263     CPPUNIT_ASSERT_EQUAL(expected, actual);
01264 
01265     // Ternary: r24@r25:r26
01266     l.clear();
01267     e = new Ternary(opAt,
01268         Location::regOf(24),
01269         Location::regOf(25),
01270         Location::regOf(26));
01271     e->addUsedLocs(l);
01272     expected = "r24,\tr25,\tr26";
01273     std::ostringstream ost6;
01274     l.print(ost6);
01275     actual = ost6.str();
01276     CPPUNIT_ASSERT_EQUAL(expected, actual);
01277 
01278     // Simple RefExp: r28{2}
01279     l.clear();
01280     Assign a(e, e);
01281     a.setNumber(2);
01282     e = new RefExp(Location::regOf(28), &a);
01283     e->addUsedLocs(l);
01284     expected = "r28{2}";
01285     std::ostringstream ost7;
01286     l.print(ost7);
01287     actual = ost7.str();
01288     CPPUNIT_ASSERT_EQUAL(expected, actual);
01289 
01290     // RefExp: m[r28{2} - 4]{3}
01291     Assign t(e, e);
01292     t.setNumber(3);
01293     e = new RefExp(
01294         Location::memOf(
01295             new Binary(opMinus,
01296                 new RefExp(
01297                     Location::regOf(28), &a),
01298                 new Const(4))), &t);
01299     e->addUsedLocs(l);
01300     expected = "r28{2},\tm[r28{2} - 4]{3}";
01301     std::ostringstream ost8;
01302     l.print(ost8);
01303     actual = ost8.str();
01304     CPPUNIT_ASSERT_EQUAL(expected, actual);
01305 
01306 }
01307 
01308 /*==============================================================================
01309  * FUNCTION:        ExpTest::testSubscriptVars
01310  * OVERVIEW:        Test the subscripting of variables (locations)
01311  *============================================================================*/
01312 void ExpTest::testSubscriptVars() {
01313     // Null case: %pc
01314     Assign s9(new Terminal(opNil), new Terminal(opNil));
01315     s9.setNumber(9);
01316     Exp* search = Location::regOf(28);
01317     Exp* e = new Terminal(opPC);
01318     e = e->expSubscriptVar(search, &s9);
01319     std::string expected("%pc");
01320     std::ostringstream ost1;
01321     ost1 << e;
01322     std::string actual = ost1.str();
01323     CPPUNIT_ASSERT_EQUAL(expected, actual);
01324 
01325     // Simple case: r28
01326     e = search->clone();
01327     e = e->expSubscriptVar(search, &s9);
01328     expected = "r28{9}";
01329     std::ostringstream ost2;
01330     ost2 << e;
01331     actual = ost2.str();
01332     CPPUNIT_ASSERT_EQUAL(expected, actual);
01333 
01334     // A temp
01335     e = Location::tempOf(new Const("tmp1"));
01336     e = e->expSubscriptVar(e->clone(), &s9);
01337     expected = "tmp1{9}";
01338     std::ostringstream ost3;
01339     ost3 << e;
01340     actual = ost3.str();
01341     CPPUNIT_ASSERT_EQUAL(expected, actual);
01342 
01343     // m[r28] + r28
01344     e = new Binary(opPlus,
01345         Location::memOf(Location::regOf(28)),
01346         Location::regOf(28));
01347     e = e->expSubscriptVar(search, &s9);
01348     expected = "m[r28{9}] + r28{9}";
01349     std::ostringstream ost4;
01350     ost4 << e;
01351     actual = ost4.str();
01352     CPPUNIT_ASSERT_EQUAL(expected, actual);
01353 
01354     // RefExp: r28{7} -> r28{9}
01355     // Again, changed behaviour: don't resubscript any location
01356     Assign s7(new Terminal(opNil), new Terminal(opNil));
01357     s7.setNumber(7);
01358     e = new RefExp(search->clone(), &s7);
01359     e = e->expSubscriptVar(search, &s9);
01360     expected = "r28{7}";
01361     std::ostringstream ost5;
01362     ost5 << e;
01363     actual = ost5.str();
01364     CPPUNIT_ASSERT_EQUAL(expected, actual);
01365 
01366     // m[r28{7} + 4]{8}
01367     Assign s8(new Terminal(opNil), new Terminal(opNil));
01368     s8.setNumber(8);
01369     e = new RefExp(
01370         Location::memOf(
01371             new Binary(opPlus,
01372                 new RefExp(
01373                     Location::regOf(28), &s7),
01374                 new Const(4))), &s8);
01375     e = e->expSubscriptVar(search, &s9);
01376     expected = "m[r28{7} + 4]{8}";
01377     std::ostringstream ost6;
01378     ost6 << e;
01379     actual = ost6.str();
01380     CPPUNIT_ASSERT_EQUAL(expected, actual);
01381 
01382     // r24{7} with r24{7} and 0: should not change: RefExps should not compare
01383     // at the top level, only with their base expression (here r24, not r24{7})
01384     e = new RefExp(Location::regOf(24), &s7);
01385     e = e->expSubscriptVar(e->clone(), NULL);
01386     expected = "r24{7}";
01387     std::ostringstream ost7;
01388     ost7 << e;
01389     actual = ost7.str();
01390     CPPUNIT_ASSERT_EQUAL(expected, actual);
01391 
01392 
01393 }
01394 
01395 /*==============================================================================
01396  * FUNCTION:        ExpTest::testVisitors
01397  * OVERVIEW:        Test the FlagsFinder and BareMemofFinder visitors
01398  *============================================================================*/
01399 void ExpTest::testVisitors() {
01400     Assign s7(new Terminal(opNil), new Terminal(opNil));
01401     // m[SETTFLAGS(m[1000], r8)]{7}
01402     s7.setNumber(7);
01403     FlagsFinder ff;
01404     Exp* e1 = new RefExp(
01405         Location::memOf(
01406             new Binary(opFlagCall,
01407                 new Const("SETFFLAGS"),
01408                 new Binary(opList,
01409                     Location::memOf(        // A bare memof
01410                         new Const(0x1000)),
01411                     new Binary(opList,
01412                         Location::regOf(8),
01413                         new Terminal(opNil))))),
01414         &s7);
01415 
01416     // m[0x2000]
01417     Exp* e2 = Location::memOf(new Const(0x2000));
01418 
01419     // r1+m[1000]{7}*4
01420     Exp* e3 = new Binary(opPlus,
01421         Location::regOf(1),
01422         new Binary(opMult,
01423             new RefExp(
01424                 Location::memOf(new Const(1000)),
01425                 &s7),
01426             new Const(4)));
01427 
01428     int res = e1->containsFlags();
01429     CPPUNIT_ASSERT_EQUAL(1, res);
01430     res = e2->containsFlags();
01431     CPPUNIT_ASSERT_EQUAL(0, res);
01432     res = e3->containsFlags();
01433     CPPUNIT_ASSERT_EQUAL(0, res);
01434 
01435 #if 0               // No longer used
01436     res = e1->containsBareMemof();
01437     CPPUNIT_ASSERT_EQUAL(1, res);
01438     res = e2->containsBareMemof();
01439     CPPUNIT_ASSERT_EQUAL(1, res);
01440     res = e3->containsBareMemof();
01441     CPPUNIT_ASSERT_EQUAL(0, res);
01442 #endif
01443 }
01444 

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