PageRenderTime 67ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 1ms

/db/statement.cpp

https://github.com/PrototypeX29A/boomerang
C++ | 5122 lines | 3885 code | 366 blank | 871 comment | 1381 complexity | 92b892dc0f15b915633bc027ee5d4e2a MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (C) 2002-2006, Trent Waddington and Mike Van Emmerik
  3. *
  4. * See the file "LICENSE.TERMS" for information on usage and
  5. * redistribution of this file, and for a DISCLAIMER OF ALL
  6. * WARRANTIES.
  7. *
  8. */
  9. /*==============================================================================
  10. * FILE: statement.cpp
  11. * OVERVIEW: Implementation of the Statement and related classes.
  12. * (Was dataflow.cpp a long time ago)
  13. *============================================================================*/
  14. /*
  15. * $Revision: 1.234 $ // 1.148.2.38
  16. * 03 Jul 02 - Trent: Created
  17. * 25 Jul 03 - Mike: dataflow.cpp, hrtl.cpp -> statement.cpp
  18. */
  19. /*==============================================================================
  20. * Dependencies.
  21. *============================================================================*/
  22. #include <assert.h>
  23. #include <iomanip> // For setfill etc
  24. #include <sstream>
  25. #include <algorithm>
  26. #include "statement.h"
  27. #include "exp.h"
  28. #include "cfg.h"
  29. #include "proc.h"
  30. #include "prog.h"
  31. #include "boomerang.h"
  32. #include "rtl.h" // For debugging code
  33. #include "util.h"
  34. #include "signature.h"
  35. #include "visitor.h"
  36. #include "dataflow.h"
  37. #include "log.h"
  38. #include <string.h>
  39. extern char debug_buffer[]; // For prints functions
  40. #if defined(_MSC_VER) && _MSC_VER < 1310 // Ugh - MSC 7.0 doesn't have advance
  41. #define my_advance(aa, n) \
  42. for (int zz = 0; zz < n; zz++) \
  43. aa++;
  44. #else
  45. #define my_advance(aa, n) \
  46. advance(aa, n);
  47. #endif
  48. void Statement::setProc(UserProc *p)
  49. {
  50. proc = p;
  51. LocationSet exps;
  52. addUsedLocs(exps);
  53. LocationSet defs;
  54. getDefinitions(defs);
  55. exps.makeUnion(defs);
  56. LocationSet::iterator ll;
  57. for (ll = exps.begin(); ll != exps.end(); ll++) {
  58. Location *l = dynamic_cast<Location*>(*ll);
  59. if (l) {
  60. l->setProc(p);
  61. }
  62. }
  63. }
  64. Exp *Statement::getExpAtLex(unsigned int begin, unsigned int end)
  65. {
  66. return NULL;
  67. }
  68. bool Statement::mayAlias(Exp *e1, Exp *e2, int size) {
  69. if (*e1 == *e2) return true;
  70. // Pass the expressions both ways. Saves checking things like m[exp] vs m[exp+K] and m[exp+K] vs m[exp] explicitly
  71. // (only need to check one of these cases)
  72. bool b = (calcMayAlias(e1, e2, size) && calcMayAlias(e2, e1, size));
  73. if (b && VERBOSE) {
  74. LOG << "May alias: " << e1 << " and " << e2 << " size " << size << "\n";
  75. }
  76. return b;
  77. }
  78. // returns true if e1 may alias e2
  79. bool Statement::calcMayAlias(Exp *e1, Exp *e2, int size) {
  80. // currently only considers memory aliasing..
  81. if (!e1->isMemOf() || !e2->isMemOf()) {
  82. return false;
  83. }
  84. Exp *e1a = e1->getSubExp1();
  85. Exp *e2a = e2->getSubExp1();
  86. // constant memory accesses
  87. if (e1a->isIntConst() && e2a->isIntConst()) {
  88. ADDRESS a1 = ((Const*)e1a)->getAddr();
  89. ADDRESS a2 = ((Const*)e2a)->getAddr();
  90. int diff = a1 - a2;
  91. if (diff < 0) diff = -diff;
  92. if (diff*8 >= size) return false;
  93. }
  94. // same left op constant memory accesses
  95. if (e1a->getArity() == 2 && e1a->getOper() == e2a->getOper() && e1a->getSubExp2()->isIntConst() &&
  96. e2a->getSubExp2()->isIntConst() && *e1a->getSubExp1() == *e2a->getSubExp1()) {
  97. int i1 = ((Const*)e1a->getSubExp2())->getInt();
  98. int i2 = ((Const*)e2a->getSubExp2())->getInt();
  99. int diff = i1 - i2;
  100. if (diff < 0) diff = -diff;
  101. if (diff*8 >= size) return false;
  102. }
  103. // [left] vs [left +/- constant] memory accesses
  104. if ((e2a->getOper() == opPlus || e2a->getOper() == opMinus) && *e1a == *e2a->getSubExp1() &&
  105. e2a->getSubExp2()->isIntConst()) {
  106. int i1 = 0;
  107. int i2 = ((Const*)e2a->getSubExp2())->getInt();
  108. int diff = i1 - i2;
  109. if (diff < 0) diff = -diff;
  110. if (diff*8 >= size) return false;
  111. }
  112. // Don't need [left +/- constant ] vs [left] because called twice with
  113. // args reversed
  114. return true;
  115. }
  116. RangeMap Statement::getInputRanges()
  117. {
  118. if (!isFirstStatementInBB()) {
  119. savedInputRanges = getPreviousStatementInBB()->getRanges();
  120. return savedInputRanges;
  121. }
  122. assert(pbb && pbb->getNumInEdges() <= 1);
  123. RangeMap input;
  124. if (pbb->getNumInEdges() == 0) {
  125. // setup input for start of procedure
  126. Range ra24(1, 0, 0, new Unary(opInitValueOf, Location::regOf(24)));
  127. Range ra25(1, 0, 0, new Unary(opInitValueOf, Location::regOf(25)));
  128. Range ra26(1, 0, 0, new Unary(opInitValueOf, Location::regOf(26)));
  129. Range ra27(1, 0, 0, new Unary(opInitValueOf, Location::regOf(27)));
  130. Range ra28(1, 0, 0, new Unary(opInitValueOf, Location::regOf(28)));
  131. Range ra29(1, 0, 0, new Unary(opInitValueOf, Location::regOf(29)));
  132. Range ra30(1, 0, 0, new Unary(opInitValueOf, Location::regOf(30)));
  133. Range ra31(1, 0, 0, new Unary(opInitValueOf, Location::regOf(31)));
  134. Range rpc(1, 0, 0, new Unary(opInitValueOf, new Terminal(opPC)));
  135. input.addRange(Location::regOf(24), ra24);
  136. input.addRange(Location::regOf(25), ra25);
  137. input.addRange(Location::regOf(26), ra26);
  138. input.addRange(Location::regOf(27), ra27);
  139. input.addRange(Location::regOf(28), ra28);
  140. input.addRange(Location::regOf(29), ra29);
  141. input.addRange(Location::regOf(30), ra30);
  142. input.addRange(Location::regOf(31), ra31);
  143. input.addRange(new Terminal(opPC), rpc);
  144. } else {
  145. PBB pred = pbb->getInEdges()[0];
  146. Statement *last = pred->getLastStmt();
  147. assert(last);
  148. if (pred->getNumOutEdges() != 2) {
  149. input = last->getRanges();
  150. } else {
  151. assert(pred->getNumOutEdges() == 2);
  152. assert(last->isBranch());
  153. input = ((BranchStatement*)last)->getRangesForOutEdgeTo(pbb);
  154. }
  155. }
  156. savedInputRanges = input;
  157. return input;
  158. }
  159. void Statement::updateRanges(RangeMap &output, std::list<Statement*> &execution_paths, bool notTaken)
  160. {
  161. if (!output.isSubset(notTaken ? ((BranchStatement*)this)->getRanges2Ref() : ranges)) {
  162. if (notTaken)
  163. ((BranchStatement*)this)->setRanges2(output);
  164. else
  165. ranges = output;
  166. if (isLastStatementInBB()) {
  167. if (pbb->getNumOutEdges()) {
  168. int arc = 0;
  169. if (isBranch()) {
  170. if (pbb->getOutEdge(0)->getLowAddr() != ((BranchStatement*)this)->getFixedDest())
  171. arc = 1;
  172. if (notTaken)
  173. arc ^= 1;
  174. }
  175. execution_paths.push_back(pbb->getOutEdge(arc)->getFirstStmt());
  176. }
  177. } else
  178. execution_paths.push_back(getNextStatementInBB());
  179. }
  180. }
  181. void Statement::rangeAnalysis(std::list<Statement*> &execution_paths)
  182. {
  183. RangeMap output = getInputRanges();
  184. updateRanges(output, execution_paths);
  185. }
  186. void Assign::rangeAnalysis(std::list<Statement*> &execution_paths)
  187. {
  188. RangeMap output = getInputRanges();
  189. Exp *a_lhs = lhs->clone();
  190. if (a_lhs->isFlags()) {
  191. // special hacks for flags
  192. assert(rhs->isFlagCall());
  193. Exp *a_rhs = rhs->clone();
  194. if (a_rhs->getSubExp2()->getSubExp1()->isMemOf())
  195. a_rhs->getSubExp2()->getSubExp1()->setSubExp1(
  196. output.substInto(a_rhs->getSubExp2()->getSubExp1()->getSubExp1()));
  197. if (!a_rhs->getSubExp2()->getSubExp2()->isTerminal() &&
  198. a_rhs->getSubExp2()->getSubExp2()->getSubExp1()->isMemOf())
  199. a_rhs->getSubExp2()->getSubExp2()->getSubExp1()->setSubExp1(
  200. output.substInto(a_rhs->getSubExp2()->getSubExp2()->getSubExp1()->getSubExp1()));
  201. Range ra(1, 0, 0, a_rhs);
  202. output.addRange(a_lhs, ra);
  203. } else {
  204. if (a_lhs->isMemOf())
  205. a_lhs->setSubExp1(output.substInto(a_lhs->getSubExp1()->clone()));
  206. Exp *a_rhs = output.substInto(rhs->clone());
  207. if (a_rhs->isMemOf() && a_rhs->getSubExp1()->getOper() == opInitValueOf &&
  208. a_rhs->getSubExp1()->getSubExp1()->isRegOfK() &&
  209. ((Const*)a_rhs->getSubExp1()->getSubExp1()->getSubExp1())->getInt() == 28)
  210. a_rhs = new Unary(opInitValueOf, new Terminal(opPC)); // nice hack
  211. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  212. LOG << "a_rhs is " << a_rhs << "\n";
  213. if (a_rhs->isMemOf() && a_rhs->getSubExp1()->isIntConst()) {
  214. ADDRESS c = ((Const*)a_rhs->getSubExp1())->getInt();
  215. if (proc->getProg()->isDynamicLinkedProcPointer(c)) {
  216. char *nam = (char*)proc->getProg()->GetDynamicProcName(c);
  217. if (nam) {
  218. a_rhs = new Const(nam);
  219. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  220. LOG << "a_rhs is a dynamic proc pointer to " << nam << "\n";
  221. }
  222. } else if (proc->getProg()->isReadOnly(c)) {
  223. switch(type->getSize()) {
  224. case 8:
  225. a_rhs = new Const(proc->getProg()->readNative1(c));
  226. break;
  227. case 16:
  228. a_rhs = new Const(proc->getProg()->readNative2(c));
  229. break;
  230. case 32:
  231. a_rhs = new Const(proc->getProg()->readNative4(c));
  232. break;
  233. default:
  234. LOG << "error: unhandled type size " << type->getSize() << " for reading native address\n";
  235. }
  236. } else
  237. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  238. LOG << c << " is not dynamically linked proc pointer or in read only memory\n";
  239. }
  240. if ((a_rhs->getOper() == opPlus || a_rhs->getOper() == opMinus) &&
  241. a_rhs->getSubExp2()->isIntConst() && output.hasRange(a_rhs->getSubExp1())) {
  242. Range &r = output.getRange(a_rhs->getSubExp1());
  243. int c = ((Const*)a_rhs->getSubExp2())->getInt();
  244. if (a_rhs->getOper() == opPlus) {
  245. Range ra(1, r.getLowerBound() != Range::MIN ? r.getLowerBound() + c : Range::MIN,
  246. r.getUpperBound() != Range::MAX? r.getUpperBound() + c : Range::MAX, r.getBase());
  247. output.addRange(a_lhs, ra);
  248. } else {
  249. Range ra(1, r.getLowerBound() != Range::MIN ? r.getLowerBound() - c : Range::MIN,
  250. r.getUpperBound() != Range::MAX ? r.getUpperBound() - c : Range::MAX, r.getBase());
  251. output.addRange(a_lhs, ra);
  252. }
  253. } else {
  254. if (output.hasRange(a_rhs)) {
  255. output.addRange(a_lhs, output.getRange(a_rhs));
  256. } else {
  257. Exp *result;
  258. if (a_rhs->getMemDepth() == 0 && !a_rhs->search(new Unary(opRegOf, new Terminal(opWild)), result) &&
  259. !a_rhs->search(new Unary(opTemp, new Terminal(opWild)), result)) {
  260. if (a_rhs->isIntConst()) {
  261. Range ra(1, ((Const*)a_rhs)->getInt(), ((Const*)a_rhs)->getInt(), new Const(0));
  262. output.addRange(a_lhs, ra);
  263. }
  264. else {
  265. Range ra(1, 0, 0, a_rhs);
  266. output.addRange(a_lhs, ra);
  267. }
  268. } else {
  269. Range empty;
  270. output.addRange(a_lhs, empty);
  271. }
  272. }
  273. }
  274. }
  275. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  276. LOG << "added " << a_lhs << " -> " << output.getRange(a_lhs) << "\n";
  277. updateRanges(output, execution_paths);
  278. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  279. LOG << this << "\n";
  280. }
  281. void BranchStatement::limitOutputWithCondition(RangeMap &output, Exp *e)
  282. {
  283. assert(e);
  284. if (output.hasRange(e->getSubExp1())) {
  285. Range &r = output.getRange(e->getSubExp1());
  286. if (e->getSubExp2()->isIntConst() && r.getBase()->isIntConst() && ((Const*)r.getBase())->getInt() == 0) {
  287. int c = ((Const*)e->getSubExp2())->getInt();
  288. switch(e->getOper()) {
  289. case opLess:
  290. case opLessUns: {
  291. Range ra(r.getStride(), r.getLowerBound() >= c ? c - 1 : r.getLowerBound(),
  292. r.getUpperBound() >= c ? c - 1 : r.getUpperBound(), r.getBase());
  293. output.addRange(e->getSubExp1(), ra);
  294. break;
  295. }
  296. case opLessEq:
  297. case opLessEqUns: {
  298. Range ra(r.getStride(), r.getLowerBound() > c ? c : r.getLowerBound(),
  299. r.getUpperBound() > c ? c : r.getUpperBound(), r.getBase());
  300. output.addRange(e->getSubExp1(), ra);
  301. break;
  302. }
  303. case opGtr:
  304. case opGtrUns: {
  305. Range ra(r.getStride(), r.getLowerBound() <= c ? c + 1 : r.getLowerBound(),
  306. r.getUpperBound() <= c ? c + 1 : r.getUpperBound(), r.getBase());
  307. output.addRange(e->getSubExp1(), ra);
  308. break;
  309. }
  310. case opGtrEq:
  311. case opGtrEqUns: {
  312. Range ra(r.getStride(), r.getLowerBound() < c ? c : r.getLowerBound(),
  313. r.getUpperBound() < c ? c : r.getUpperBound(), r.getBase());
  314. output.addRange(e->getSubExp1(), ra);
  315. break;
  316. }
  317. case opEquals: {
  318. Range ra(r.getStride(), c, c, r.getBase());
  319. output.addRange(e->getSubExp1(), ra);
  320. break;
  321. }
  322. case opNotEqual: {
  323. Range ra(r.getStride(), r.getLowerBound() == c ? c + 1 : r.getLowerBound(),
  324. r.getUpperBound() == c ? c - 1 : r.getUpperBound(), r.getBase());
  325. output.addRange(e->getSubExp1(), ra);
  326. break;
  327. }
  328. default:
  329. break;
  330. }
  331. }
  332. }
  333. }
  334. void BranchStatement::rangeAnalysis(std::list<Statement*> &execution_paths)
  335. {
  336. RangeMap output = getInputRanges();
  337. Exp *e = NULL;
  338. // try to hack up a useful expression for this branch
  339. OPER op = pCond->getOper();
  340. if (op == opLess || op == opLessEq || op == opGtr || op == opGtrEq ||
  341. op == opLessUns || op == opLessEqUns || op == opGtrUns || op == opGtrEqUns ||
  342. op == opEquals || op == opNotEqual) {
  343. if (pCond->getSubExp1()->isFlags() && output.hasRange(pCond->getSubExp1())) {
  344. Range &r = output.getRange(pCond->getSubExp1());
  345. if (r.getBase()->isFlagCall() &&
  346. r.getBase()->getSubExp2()->getOper() == opList &&
  347. r.getBase()->getSubExp2()->getSubExp2()->getOper() == opList) {
  348. e = new Binary(op, r.getBase()->getSubExp2()->getSubExp1()->clone(), r.getBase()->getSubExp2()->getSubExp2()->getSubExp1()->clone());
  349. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  350. LOG << "calculated condition " << e << "\n";
  351. }
  352. }
  353. }
  354. if (e)
  355. limitOutputWithCondition(output, e);
  356. updateRanges(output, execution_paths);
  357. output = getInputRanges();
  358. if (e)
  359. limitOutputWithCondition(output, (new Unary(opNot, e))->simplify());
  360. updateRanges(output, execution_paths, true);
  361. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  362. LOG << this << "\n";
  363. }
  364. void JunctionStatement::rangeAnalysis(std::list<Statement*> &execution_paths)
  365. {
  366. RangeMap input;
  367. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  368. LOG << "unioning {\n";
  369. for (int i = 0; i < pbb->getNumInEdges(); i++) {
  370. Statement *last = pbb->getInEdges()[i]->getLastStmt();
  371. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  372. LOG << " in BB: " << pbb->getInEdges()[i]->getLowAddr() << " " << last << "\n";
  373. if (last->isBranch()) {
  374. input.unionwith(((BranchStatement*)last)->getRangesForOutEdgeTo(pbb));
  375. } else {
  376. if (last->isCall()) {
  377. Proc *d = ((CallStatement*)last)->getDestProc();
  378. if (d && !d->isLib() && ((UserProc*)d)->getCFG()->findRetNode() == NULL) {
  379. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  380. LOG << "ignoring ranges from call to proc with no ret node\n";
  381. } else
  382. input.unionwith(last->getRanges());
  383. } else
  384. input.unionwith(last->getRanges());
  385. }
  386. }
  387. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  388. LOG << "}\n";
  389. if (!input.isSubset(ranges)) {
  390. RangeMap output = input;
  391. if (output.hasRange(Location::regOf(28))) {
  392. Range &r = output.getRange(Location::regOf(28));
  393. if (r.getLowerBound() != r.getUpperBound() && r.getLowerBound() != Range::MIN) {
  394. if (VERBOSE)
  395. LOG << "stack height assumption violated " << r << " my bb: " << pbb->getLowAddr() << "\n";
  396. proc->printToLog();
  397. assert(false);
  398. }
  399. }
  400. if (isLoopJunction()) {
  401. output = ranges;
  402. output.widenwith(input);
  403. }
  404. updateRanges(output, execution_paths);
  405. }
  406. if (VERBOSE && DEBUG_RANGE_ANALYSIS)
  407. LOG << this << "\n";
  408. }
  409. void CallStatement::rangeAnalysis(std::list<Statement*> &execution_paths)
  410. {
  411. RangeMap output = getInputRanges();
  412. if (this->procDest == NULL) {
  413. // note this assumes the call is only to one proc.. could be bad.
  414. Exp *d = output.substInto(getDest()->clone());
  415. if (d->isIntConst() || d->isStrConst()) {
  416. if (d->isIntConst()) {
  417. ADDRESS dest = ((Const*)d)->getInt();
  418. procDest = proc->getProg()->setNewProc(dest);
  419. } else {
  420. procDest = proc->getProg()->getLibraryProc(((Const*)d)->getStr());
  421. }
  422. if (procDest) {
  423. Signature *sig = procDest->getSignature();
  424. pDest = d;
  425. arguments.clear();
  426. for (unsigned i = 0; i < sig->getNumParams(); i++) {
  427. Exp* a = sig->getParamExp(i);
  428. Assign* as = new Assign(new VoidType(), a->clone(), a->clone());
  429. as->setProc(proc);
  430. as->setBB(pbb);
  431. arguments.append(as);
  432. }
  433. signature = procDest->getSignature()->clone();
  434. m_isComputed = false;
  435. proc->undoComputedBB(this);
  436. proc->addCallee(procDest);
  437. LOG << "replaced indirect call with call to " << procDest->getName() << "\n";
  438. }
  439. }
  440. }
  441. if (output.hasRange(Location::regOf(28))) {
  442. Range &r = output.getRange(Location::regOf(28));
  443. int c = 4;
  444. if (procDest == NULL) {
  445. LOG << "using push count hack to guess number of params\n";
  446. Statement *prev = this->getPreviousStatementInBB();
  447. while(prev) {
  448. if (prev->isAssign() && ((Assign*)prev)->getLeft()->isMemOf() &&
  449. ((Assign*)prev)->getLeft()->getSubExp1()->isRegOfK() &&
  450. ((Const*)((Assign*)prev)->getLeft()->getSubExp1()->getSubExp1())->getInt() == 28 &&
  451. ((Assign*)prev)->getRight()->getOper() != opPC) {
  452. c += 4;
  453. }
  454. prev = prev->getPreviousStatementInBB();
  455. }
  456. } else if (procDest->getSignature()->getConvention() == CONV_PASCAL)
  457. c += procDest->getSignature()->getNumParams() * 4;
  458. else if (!strncmp(procDest->getName(), "__imp_", 6)) {
  459. Statement *first = ((UserProc*)procDest)->getCFG()->getEntryBB()->getFirstStmt();
  460. assert(first && first->isCall());
  461. Proc *d = ((CallStatement*)first)->getDestProc();
  462. if (d->getSignature()->getConvention() == CONV_PASCAL)
  463. c += d->getSignature()->getNumParams() * 4;
  464. } else if (!procDest->isLib()) {
  465. UserProc *p = (UserProc*)procDest;
  466. if (VERBOSE) {
  467. LOG << "== checking for number of bytes popped ==\n";
  468. p->printToLog();
  469. LOG << "== end it ==\n";
  470. }
  471. Exp *eq = p->getProven(Location::regOf(28));
  472. if (eq) {
  473. if (VERBOSE)
  474. LOG << "found proven " << eq << "\n";
  475. if (eq->getOper() == opPlus && *eq->getSubExp1() == *Location::regOf(28) &&
  476. eq->getSubExp2()->isIntConst()) {
  477. c = ((Const*)eq->getSubExp2())->getInt();
  478. } else
  479. eq = NULL;
  480. }
  481. PBB retbb = p->getCFG()->findRetNode();
  482. if (retbb && eq == NULL) {
  483. Statement *last = retbb->getLastStmt();
  484. assert(last);
  485. if (last->isReturn()) {
  486. last->setBB(retbb);
  487. last = last->getPreviousStatementInBB();
  488. }
  489. if (last == NULL) {
  490. // call followed by a ret, sigh
  491. for (int i = 0; i < retbb->getNumInEdges(); i++) {
  492. last = retbb->getInEdges()[i]->getLastStmt();
  493. if (last->isCall())
  494. break;
  495. }
  496. if (last->isCall()) {
  497. Proc *d = ((CallStatement*)last)->getDestProc();
  498. if (d && d->getSignature()->getConvention() == CONV_PASCAL)
  499. c += d->getSignature()->getNumParams() * 4;
  500. }
  501. last = NULL;
  502. }
  503. if (last && last->isAssign()) {
  504. //LOG << "checking last statement " << last << " for number of bytes popped\n";
  505. Assign *a = (Assign*)last;
  506. assert(a->getLeft()->isRegOfK() && ((Const*)a->getLeft()->getSubExp1())->getInt() == 28);
  507. Exp *t = a->getRight()->clone()->simplifyArith();
  508. assert(t->getOper() == opPlus &&
  509. t->getSubExp1()->isRegOfK() &&
  510. ((Const*)t->getSubExp1()->getSubExp1())->getInt() == 28);
  511. assert(t->getSubExp2()->isIntConst());
  512. c = ((Const*)t->getSubExp2())->getInt();
  513. }
  514. }
  515. }
  516. Range ra(r.getStride(), r.getLowerBound() == Range::MIN ? Range::MIN : r.getLowerBound() + c,
  517. r.getUpperBound() == Range::MAX ? Range::MAX : r.getUpperBound() + c, r.getBase());
  518. output.addRange(Location::regOf(28), ra);
  519. }
  520. updateRanges(output, execution_paths);
  521. }
  522. bool JunctionStatement::isLoopJunction()
  523. {
  524. for (int i = 0; i < pbb->getNumInEdges(); i++)
  525. if (pbb->isBackEdge(i))
  526. return true;
  527. return false;
  528. }
  529. RangeMap &BranchStatement::getRangesForOutEdgeTo(PBB out)
  530. {
  531. assert(this->getFixedDest() != NO_ADDRESS);
  532. if (out->getLowAddr() == this->getFixedDest())
  533. return ranges;
  534. return ranges2;
  535. }
  536. bool Statement::isFirstStatementInBB()
  537. {
  538. assert(pbb);
  539. assert(pbb->getRTLs());
  540. assert(pbb->getRTLs()->size());
  541. assert(pbb->getRTLs()->front());
  542. assert(pbb->getRTLs()->front()->getList().size());
  543. return this == pbb->getRTLs()->front()->getList().front();
  544. }
  545. bool Statement::isLastStatementInBB()
  546. {
  547. assert(pbb);
  548. return this == pbb->getLastStmt();
  549. }
  550. Statement* Statement::getPreviousStatementInBB()
  551. {
  552. assert(pbb);
  553. std::list<RTL*> *rtls = pbb->getRTLs();
  554. assert(rtls);
  555. Statement *previous = NULL;
  556. for (std::list<RTL*>::iterator rit = rtls->begin(); rit != rtls->end(); rit++) {
  557. RTL *rtl = *rit;
  558. for (RTL::iterator it = rtl->getList().begin(); it != rtl->getList().end(); it++) {
  559. if (*it == this)
  560. return previous;
  561. previous = *it;
  562. }
  563. }
  564. return NULL;
  565. }
  566. Statement *Statement::getNextStatementInBB()
  567. {
  568. assert(pbb);
  569. std::list<RTL*> *rtls = pbb->getRTLs();
  570. assert(rtls);
  571. bool wantNext = false;
  572. for (std::list<RTL*>::iterator rit = rtls->begin(); rit != rtls->end(); rit++) {
  573. RTL *rtl = *rit;
  574. for (RTL::iterator it = rtl->getList().begin(); it != rtl->getList().end(); it++) {
  575. if (wantNext)
  576. return *it;
  577. if (*it == this)
  578. wantNext = true;
  579. }
  580. }
  581. return NULL;
  582. }
  583. /*==============================================================================
  584. * FUNCTION: operator<<
  585. * OVERVIEW: Output operator for Statement*
  586. * Just makes it easier to use e.g. std::cerr << myStmtStar
  587. * PARAMETERS: os: output stream to send to
  588. * p: ptr to Statement to print to the stream
  589. * RETURNS: copy of os (for concatenation)
  590. *============================================================================*/
  591. std::ostream& operator<<(std::ostream& os, Statement* s) {
  592. if (s == NULL) {os << "NULL "; return os;}
  593. s->print(os);
  594. return os;
  595. }
  596. bool Statement::isFlagAssgn() {
  597. if (kind != STMT_ASSIGN)
  598. return false;
  599. OPER op = ((Assign*)this)->getRight()->getOper();
  600. return (op == opFlagCall);
  601. }
  602. char* Statement::prints() {
  603. std::ostringstream ost;
  604. print(ost);
  605. strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
  606. debug_buffer[DEBUG_BUFSIZE-1] = '\0';
  607. return debug_buffer;
  608. }
  609. // This version prints much better in gdb
  610. void Statement::dump() {
  611. print(std::cerr);
  612. std::cerr << "\n";
  613. }
  614. /* This function is designed to find basic flag calls, plus in addition two variations seen with Pentium FP code.
  615. These variations involve ANDing and/or XORing with constants. So it should return true for these values of e:
  616. ADDFLAGS(...)
  617. SETFFLAGS(...) & 0x45
  618. (SETFFLAGS(...) & 0x45) ^ 0x40
  619. FIXME: this may not be needed any more...
  620. */
  621. bool hasSetFlags(Exp* e) {
  622. if (e->isFlagCall()) return true;
  623. OPER op = e->getOper();
  624. if (op != opBitAnd && op != opBitXor) return false;
  625. Exp* left = ((Binary*)e)->getSubExp1();
  626. Exp* right = ((Binary*)e)->getSubExp2();
  627. if (!right->isIntConst()) return false;
  628. if (left->isFlagCall()) {
  629. std::cerr << "hasSetFlags returns true with " << e << "\n";
  630. return true;
  631. }
  632. op = left->getOper();
  633. if (op != opBitAnd && op != opBitXor) return false;
  634. right = ((Binary*)left)->getSubExp2();
  635. left = ((Binary*)left)->getSubExp1();
  636. if (!right->isIntConst()) return false;
  637. bool ret = left->isFlagCall();
  638. if (ret)
  639. std::cerr << "hasSetFlags returns true with " << e << "\n";
  640. return ret;
  641. }
  642. // Return true if can propagate to Exp* e (must be a RefExp to return true)
  643. // Note: does not consider whether e is able to be renamed (from a memory Primitive point of view), only if the
  644. // definition can be propagated TO this stmt
  645. // Note: static member function
  646. bool Statement::canPropagateToExp(Exp*e) {
  647. if (!e->isSubscript()) return false;
  648. if (((RefExp*)e)->isImplicitDef())
  649. // Can't propagate statement "-" or "0" (implicit assignments)
  650. return false;
  651. Statement* def = ((RefExp*)e)->getDef();
  652. // if (def == this)
  653. // Don't propagate to self! Can happen with %pc's (?!)
  654. // return false;
  655. if (def->isNullStatement())
  656. // Don't propagate a null statement! Can happen with %pc's (would have no effect, and would infinitely loop)
  657. return false;
  658. if (!def->isAssign()) return false; // Only propagate ordinary assignments (so far)
  659. Assign* adef = (Assign*)def;
  660. if (adef->getType()->isArray()) {
  661. // Assigning to an array, don't propagate (Could be alias problems?)
  662. return false;
  663. }
  664. return true;
  665. }
  666. // Return true if any change; set convert if an indirect call statement is converted to direct (else unchanged)
  667. // destCounts is a set of maps from location to number of times it is used this proc
  668. // usedByDomPhi is a set of subscripted locations used in phi statements
  669. static int progress = 0;
  670. bool Statement::propagateTo(bool& convert, std::map<Exp*, int, lessExpStar>* destCounts /* = NULL */,
  671. LocationSet* usedByDomPhi /* = NULL */, bool force /* = false */) {
  672. if (++progress > 1000) {
  673. std::cerr << 'p' << std::flush;
  674. progress = 0;
  675. }
  676. bool change;
  677. int changes = 0;
  678. // int sp = proc->getSignature()->getStackRegister(proc->getProg());
  679. // Exp* regSp = Location::regOf(sp);
  680. int propMaxDepth = Boomerang::get()->propMaxDepth;
  681. do {
  682. LocationSet exps;
  683. addUsedLocs(exps, true); // True to also add uses from collectors. For example, want to propagate into
  684. // the reaching definitions of calls. Third parameter defaults to false, to
  685. // find all locations, not just those inside m[...]
  686. LocationSet::iterator ll;
  687. change = false; // True if changed this iteration of the do/while loop
  688. // Example: m[r24{10}] := r25{20} + m[r26{30}]
  689. // exps has r24{10}, r25{30}, m[r26{30}], r26{30}
  690. for (ll = exps.begin(); ll != exps.end(); ll++) {
  691. Exp* e = *ll;
  692. if (!canPropagateToExp(e))
  693. continue;
  694. Assign* def = (Assign*)((RefExp*)e)->getDef();
  695. Exp* rhs = def->getRight();
  696. // If force is true, ignore the fact that a memof should not be propagated (for switch analysis)
  697. if (rhs->containsBadMemof(proc) && !(force && rhs->isMemOf()))
  698. // Must never propagate unsubscripted memofs, or memofs that don't yet have symbols. You could be
  699. // propagating past a definition, thereby invalidating the IR
  700. continue;
  701. Exp* lhs = def->getLeft();
  702. if (EXPERIMENTAL) {
  703. #if 0
  704. // This is the old "don't propagate x=f(x)" heuristic. Hopefully it will work better now that we always
  705. // propagate into memofs etc. However, it might need a "and we're inside the right kind of loop"
  706. // condition
  707. LocationSet used;
  708. def->addUsedLocs(used);
  709. RefExp left(def->getLeft(), (Statement*)-1);
  710. RefExp *right = dynamic_cast<RefExp*>(def->getRight());
  711. // Beware of x := x{something else} (because we do want to do copy propagation)
  712. if (used.exists(&left) && !(right && *right->getSubExp1() == *left.getSubExp1()))
  713. // We have something like eax = eax + 1
  714. continue;
  715. #else
  716. // This is Mike's experimental propagation limiting heuristic. At present, it is:
  717. // for each component of def->rhs
  718. // test if the base expression is in the set usedByDomPhi
  719. // if so, check if this statement OW overwrites a parameter (like ebx = ebx-1)
  720. // if so, check for propagating past this overwriting statement, i.e.
  721. // domNum(def) <= domNum(OW) && dimNum(OW) < domNum(def)
  722. // if so, don't propagate (heuristic takes effect)
  723. if (usedByDomPhi) {
  724. LocationSet rhsComps;
  725. rhs->addUsedLocs(rhsComps);
  726. LocationSet::iterator rcit;
  727. bool doNotPropagate = false;
  728. for (rcit = rhsComps.begin(); rcit != rhsComps.end(); ++rcit) {
  729. if (!(*rcit)->isSubscript()) continue; // Sometimes %pc sneaks in
  730. Exp* rhsBase = ((RefExp*)*rcit)->getSubExp1();
  731. // We don't know the statement number for the one definition in usedInDomPhi that might exist,
  732. // so we use findNS()
  733. Exp* OW = usedByDomPhi->findNS(rhsBase);
  734. if (OW) {
  735. Statement* OWdef = ((RefExp*)OW)->getDef();
  736. if (!OWdef->isAssign()) continue;
  737. Exp* lhsOWdef = ((Assign*)OWdef)->getLeft();
  738. LocationSet OWcomps;
  739. def->addUsedLocs(OWcomps);
  740. LocationSet::iterator cc;
  741. bool isOverwrite = false;
  742. for (cc = OWcomps.begin(); cc != OWcomps.end(); ++cc) {
  743. if (**cc *= *lhsOWdef) {
  744. isOverwrite = true;
  745. break;
  746. }
  747. }
  748. if (isOverwrite) {
  749. // Now check for propagating a component past OWdef
  750. if (def->getDomNumber() <= OWdef->getDomNumber() &&
  751. OWdef->getDomNumber() < dominanceNum)
  752. // The heuristic kicks in
  753. doNotPropagate = true;
  754. break;
  755. }
  756. if (OW) std::cerr << "Ow is " << OW << "\n";
  757. }
  758. }
  759. if (doNotPropagate) {
  760. if (VERBOSE)
  761. LOG << "% propagation of " << def->getNumber() << " into " << number << " prevented by the "
  762. "propagate past overwriting statement in loop heuristic\n";
  763. continue;
  764. }
  765. }
  766. }
  767. #endif
  768. // Check if the -l flag (propMaxDepth) prevents this propagation
  769. if (destCounts && !lhs->isFlags()) { // Always propagate to %flags
  770. std::map<Exp*, int, lessExpStar>::iterator ff = destCounts->find(e);
  771. if (ff != destCounts->end() && ff->second > 1 && rhs->getComplexityDepth(proc) >= propMaxDepth) {
  772. if (!def->getRight()->containsFlags()) {
  773. // This propagation is prevented by the -l limit
  774. continue;
  775. }
  776. }
  777. }
  778. change |= doPropagateTo(e, def, convert);
  779. }
  780. } while (change && ++changes < 10);
  781. // Simplify is very costly, especially for calls. I hope that doing one simplify at the end will not affect any
  782. // result...
  783. simplify();
  784. return changes > 0; // Note: change is only for the last time around the do/while loop
  785. }
  786. // Experimental: may want to propagate flags first, without tests about complexity or the propagation limiting heuristic
  787. bool Statement::propagateFlagsTo() {
  788. bool change = false, convert;
  789. int changes = 0;
  790. do {
  791. LocationSet exps;
  792. addUsedLocs(exps, true);
  793. LocationSet::iterator ll;
  794. for (ll = exps.begin(); ll != exps.end(); ll++) {
  795. Exp* e = *ll;
  796. if (!e->isSubscript()) continue; // e.g. %pc
  797. Assign* def = (Assign*)((RefExp*)e)->getDef();
  798. if (def == NULL || !def->isAssign()) continue;
  799. Exp* base = ((RefExp*)e)->getSubExp1();
  800. if (base->isFlags() || base->isMainFlag()) {
  801. change |= doPropagateTo(e, def, convert);
  802. }
  803. }
  804. } while (change && ++changes < 10);
  805. simplify();
  806. return change;
  807. }
  808. // Parameter convert is set true if an indirect call is converted to direct
  809. // Return true if a change made
  810. // Note: this procedure does not control what part of this statement is propagated to
  811. // Propagate to e from definition statement def.
  812. // Set convert to true if convert a call from indirect to direct.
  813. bool Statement::doPropagateTo(Exp* e, Assign* def, bool& convert) {
  814. // Respect the -p N switch
  815. if (Boomerang::get()->numToPropagate >= 0) {
  816. if (Boomerang::get()->numToPropagate == 0) return false;
  817. Boomerang::get()->numToPropagate--;
  818. }
  819. if (VERBOSE)
  820. LOG << "propagating " << def << "\n" << " into " << this << "\n";
  821. bool change = replaceRef(e, def, convert);
  822. if (VERBOSE) {
  823. LOG << " result " << this << "\n\n";
  824. }
  825. return change;
  826. }
  827. // replace a use of def->getLeft() by def->getRight() in this statement
  828. // return true if change
  829. bool Statement::replaceRef(Exp* e, Assign *def, bool& convert) {
  830. Exp* rhs = def->getRight();
  831. assert(rhs);
  832. Exp* base = ((RefExp*)e)->getSubExp1();
  833. // Could be propagating %flags into %CF
  834. Exp* lhs = def->getLeft();
  835. if (base->getOper() == opCF && lhs->isFlags()) {
  836. if (!rhs->isFlagCall())
  837. return false;
  838. char* str = ((Const*)((Binary*)rhs)->getSubExp1())->getStr();
  839. if (strncmp("SUBFLAGS", str, 8) == 0) {
  840. /* When the carry flag is used bare, and was defined in a subtract of the form lhs - rhs, then CF has
  841. the value (lhs <u rhs). lhs and rhs are the first and second parameters of the flagcall.
  842. Note: the flagcall is a binary, with a Const (the name) and a list of expressions:
  843. defRhs
  844. / \
  845. Const opList
  846. "SUBFLAGS" / \
  847. P1 opList
  848. / \
  849. P2 opList
  850. / \
  851. P3 opNil
  852. */
  853. Exp* relExp = new Binary(opLessUns,
  854. ((Binary*)rhs)->getSubExp2()->getSubExp1(),
  855. ((Binary*)rhs)->getSubExp2()->getSubExp2()->getSubExp1());
  856. searchAndReplace(new RefExp(new Terminal(opCF), def), relExp, true);
  857. return true;
  858. }
  859. }
  860. // need something similar for %ZF
  861. if (base->getOper() == opZF && lhs->isFlags()) {
  862. if (!rhs->isFlagCall())
  863. return false;
  864. char* str = ((Const*)((Binary*)rhs)->getSubExp1())->getStr();
  865. if (strncmp("SUBFLAGS", str, 8) == 0) {
  866. // for zf we're only interested in if the result part of the subflags is equal to zero
  867. Exp* relExp = new Binary(opEquals,
  868. ((Binary*)rhs)->getSubExp2()->getSubExp2()->getSubExp2()->getSubExp1(),
  869. new Const(0));
  870. searchAndReplace(new RefExp(new Terminal(opZF), def), relExp, true);
  871. return true;
  872. }
  873. }
  874. // do the replacement
  875. //bool convert = doReplaceRef(re, rhs);
  876. bool ret = searchAndReplace(e, rhs, true); // Last parameter true to change collectors
  877. // assert(ret);
  878. if (ret && isCall()) {
  879. convert |= ((CallStatement*)this)->convertToDirect();
  880. }
  881. return ret;
  882. }
  883. bool Statement::isNullStatement() {
  884. if (kind != STMT_ASSIGN) return false;
  885. Exp* right = ((Assign*)this)->getRight();
  886. if (right->isSubscript()) {
  887. // Must refer to self to be null
  888. return this == ((RefExp*)right)->getDef();
  889. }
  890. else
  891. // Null if left == right
  892. return *((Assign*)this)->getLeft() == *right;
  893. }
  894. bool Statement::isFpush() {
  895. if (kind != STMT_ASSIGN) return false;
  896. return ((Assign*)this)->getRight()->getOper() == opFpush;
  897. }
  898. bool Statement::isFpop() {
  899. if (kind != STMT_ASSIGN) return false;
  900. return ((Assign*)this)->getRight()->getOper() == opFpop;
  901. }
  902. /*
  903. * This code was in hrtl.cpp
  904. * Classes derived from Statement
  905. */
  906. #if defined(_MSC_VER) && _MSC_VER <= 1200
  907. #pragma warning(disable:4786)
  908. #endif
  909. /******************************************************************************
  910. * GotoStatement methods
  911. *****************************************************************************/
  912. /*==============================================================================
  913. * FUNCTION: GotoStatement::GotoStatement
  914. * OVERVIEW: Constructor.
  915. * PARAMETERS: listStmt: a list of Statements (not the same as an RTL)
  916. * to serve as the initial list of statements
  917. * RETURNS: N/a
  918. *============================================================================*/
  919. GotoStatement::GotoStatement()
  920. : pDest(NULL), m_isComputed(false) {
  921. kind = STMT_GOTO;
  922. }
  923. /*==============================================================================
  924. * FUNCTION: GotoStatement::GotoStatement
  925. * OVERVIEW: Construct a jump to a fixed address
  926. * PARAMETERS: uDest: native address of destination
  927. * RETURNS: N/a
  928. *============================================================================*/
  929. GotoStatement::GotoStatement(ADDRESS uDest) : m_isComputed(false) {
  930. kind = STMT_GOTO;
  931. pDest = new Const(uDest);
  932. }
  933. /*==============================================================================
  934. * FUNCTION: GotoStatement::~GotoStatement
  935. * OVERVIEW: Destructor
  936. * PARAMETERS: None
  937. * RETURNS: N/a
  938. *============================================================================*/
  939. GotoStatement::~GotoStatement() {
  940. if (pDest) ;//delete pDest;
  941. }
  942. /*==============================================================================
  943. * FUNCTION: GotoStatement::getFixedDest
  944. * OVERVIEW: Get the fixed destination of this CTI. Assumes destination
  945. * simplication has already been done so that a fixed dest will
  946. * be of the Exp form:
  947. * opIntConst dest
  948. * PARAMETERS: <none>
  949. * RETURNS: Fixed dest or NO_ADDRESS if there isn't one
  950. *============================================================================*/
  951. ADDRESS GotoStatement::getFixedDest() {
  952. if (pDest->getOper() != opIntConst) return NO_ADDRESS;
  953. return ((Const*)pDest)->getAddr();
  954. }
  955. /*==============================================================================
  956. * FUNCTION: GotoStatement::setDest
  957. * OVERVIEW: Set the destination of this jump to be a given expression.
  958. * PARAMETERS: addr - the new fixed address
  959. * RETURNS: Nothing
  960. *============================================================================*/
  961. void GotoStatement::setDest(Exp* pd) {
  962. pDest = pd;
  963. }
  964. /*==============================================================================
  965. * FUNCTION: GotoStatement::setDest
  966. * OVERVIEW: Set the destination of this jump to be a given fixed address.
  967. * PARAMETERS: addr - the new fixed address
  968. * RETURNS: <nothing>
  969. *============================================================================*/
  970. void GotoStatement::setDest(ADDRESS addr) {
  971. // This fails in FrontSparcTest, do you really want it to Mike? -trent
  972. // assert(addr >= prog.limitTextLow && addr < prog.limitTextHigh);
  973. // Delete the old destination if there is one
  974. if (pDest != NULL)
  975. ;//delete pDest;
  976. pDest = new Const(addr);
  977. }
  978. /*==============================================================================
  979. * FUNCTION: GotoStatement::getDest
  980. * OVERVIEW: Returns the destination of this CTI.
  981. * PARAMETERS: None
  982. * RETURNS: Pointer to the SS representing the dest of this jump
  983. *============================================================================*/
  984. Exp* GotoStatement::getDest() {
  985. return pDest;
  986. }
  987. /*==============================================================================
  988. * FUNCTION: GotoStatement::adjustFixedDest
  989. * OVERVIEW: Adjust the destination of this CTI by a given amount. Causes
  990. * an error is this destination is not a fixed destination
  991. * (i.e. a constant offset).
  992. * PARAMETERS: delta - the amount to add to the destination (can be
  993. * negative)
  994. * RETURNS: <nothing>
  995. *============================================================================*/
  996. void GotoStatement::adjustFixedDest(int delta) {
  997. // Ensure that the destination is fixed.
  998. if (pDest == 0 || pDest->getOper() != opIntConst)
  999. LOG << "Can't adjust destination of non-static CTI\n";
  1000. ADDRESS dest = ((Const*)pDest)->getAddr();
  1001. ((Const*)pDest)->setAddr(dest + delta);
  1002. }
  1003. bool GotoStatement::search(Exp* search, Exp*& result) {
  1004. result = NULL;
  1005. if (pDest)
  1006. return pDest->search(search, result);
  1007. return false;
  1008. }
  1009. /*==============================================================================
  1010. * FUNCTION: GotoStatement::searchAndReplace
  1011. * OVERVIEW: Replace all instances of search with replace.
  1012. * PARAMETERS: search - a location to search for
  1013. * replace - the expression with which to replace it
  1014. * cc - ignored
  1015. * RETURNS: True if any change
  1016. *============================================================================*/
  1017. bool GotoStatement::searchAndReplace(Exp* search, Exp* replace, bool cc) {
  1018. bool change = false;
  1019. if (pDest) {
  1020. pDest = pDest->searchReplaceAll(search, replace, change);
  1021. }
  1022. return change;
  1023. }
  1024. /*==============================================================================
  1025. * FUNCTION: GotoStatement::searchAll
  1026. * OVERVIEW: Find all instances of the search expression
  1027. * PARAMETERS: search - a location to search for
  1028. * result - a list which will have any matching exprs
  1029. * appended to it
  1030. * RETURNS: true if there were any matches
  1031. *============================================================================*/
  1032. bool GotoStatement::searchAll(Exp* search, std::list<Exp*> &result) {
  1033. if (pDest) return pDest->searchAll(search, result);
  1034. return false;
  1035. }
  1036. /*==============================================================================
  1037. * FUNCTION: GotoStatement::print
  1038. * OVERVIEW: Display a text reprentation of this RTL to the given stream
  1039. * NOTE: Usually called from RTL::print, in which case the first 9
  1040. * chars of the print have already been output to os
  1041. * PARAMETERS: os: stream to write to
  1042. * RETURNS: Nothing
  1043. *============================================================================*/
  1044. void GotoStatement::print(std::ostream& os, bool html) {
  1045. os << std::setw(4) << std::dec << number << " ";
  1046. if (html) {
  1047. os << "</td><td>";
  1048. os << "<a name=\"stmt" << std::dec << number << "\">";
  1049. }
  1050. os << "GOTO ";
  1051. if (pDest == NULL)
  1052. os << "*no dest*";
  1053. else if (pDest->getOper() != opIntConst)
  1054. pDest->print(os);
  1055. else
  1056. os << "0x" << std::hex << getFixedDest();
  1057. if (html)
  1058. os << "</a></td>";
  1059. }
  1060. /*==============================================================================
  1061. * FUNCTION: GotoStatement::setIsComputed
  1062. * OVERVIEW: Sets the fact that this call is computed.
  1063. * NOTE: This should really be removed, once CaseStatement and
  1064. * HLNwayCall are implemented properly
  1065. * PARAMETERS: <none>
  1066. * RETURNS: <nothing>
  1067. *============================================================================*/
  1068. void GotoStatement::setIsComputed(bool b) {
  1069. m_isComputed = b;
  1070. }
  1071. /*==============================================================================
  1072. * FUNCTION: GotoStatement::isComputed
  1073. * OVERVIEW: Returns whether or not this call is computed.
  1074. * NOTE: This should really be removed, once CaseStatement and HLNwayCall
  1075. * are implemented properly
  1076. * PARAMETERS: <none>
  1077. * RETURNS: this call is computed
  1078. *============================================================================*/
  1079. bool GotoStatement::isComputed() {
  1080. return m_isComputed;
  1081. }
  1082. /*==============================================================================
  1083. * FUNCTION: GotoStatement::clone
  1084. * OVERVIEW: Deep copy clone
  1085. * PARAMETERS: <none>
  1086. * RETURNS: Pointer to a new Statement, a clone of this GotoStatement
  1087. *============================================================================*/
  1088. Statement* GotoStatement::clone() {
  1089. GotoStatement* ret = new GotoStatement();
  1090. ret->pDest = pDest->clone();
  1091. ret->m_isComputed = m_isComputed;
  1092. // Statement members
  1093. ret->pbb = pbb;
  1094. ret->proc = proc;
  1095. ret->number = number;
  1096. return ret;
  1097. }
  1098. // visit this Statement in the RTL
  1099. bool GotoStatement::accept(StmtVisitor* visitor) {
  1100. return visitor->visit(this);
  1101. }
  1102. void GotoStatement::generateCode(HLLCode *hll, BasicBlock *pbb, int indLevel) {
  1103. // dont generate any code for jumps, they will be handled by the BB
  1104. }
  1105. void GotoStatement::simplify() {
  1106. if (isComputed()) {
  1107. pDest = pDest->simplifyArith();
  1108. pDest = pDest->simplify();
  1109. }
  1110. }
  1111. /**********************************
  1112. * BranchStatement methods
  1113. **********************************/
  1114. /*==============================================================================
  1115. * FUNCTION: BranchStatement::BranchStatement
  1116. * OVERVIEW: Constructor.
  1117. * PARAMETERS: None
  1118. * RETURNS: N/a
  1119. *============================================================================*/
  1120. BranchStatement::BranchStatement() : jtCond((BRANCH_TYPE)0), pCond(NULL), bFloat(false), size(0) {
  1121. kind = STMT_BRANCH;
  1122. }
  1123. /*==============================================================================
  1124. * FUNCTION: BranchStatement::~BranchStatement
  1125. * OVERVIEW: Destructor
  1126. * PARAMETERS: None
  1127. * RETURNS: N/a
  1128. *============================================================================*/
  1129. BranchStatement::~BranchStatement() {
  1130. if (pCond)
  1131. ;//delete pCond;
  1132. }
  1133. /*==============================================================================
  1134. * FUNCTION: BranchStatement::setCondType
  1135. * OVERVIEW: Sets the BRANCH_TYPE of this jcond as well as the flag
  1136. * indicating whether or not the floating point condition codes
  1137. * are used.
  1138. * PARAMETERS: cond - the BRANCH_TYPE
  1139. * usesFloat - this condional jump checks the floating point
  1140. * condition codes
  1141. * RETURNS: a semantic string
  1142. *============================================================================*/
  1143. void BranchStatement::setCondType(BRANCH_TYPE cond, bool usesFloat /*= false*/) {
  1144. jtCond = cond;
  1145. bFloat = usesFloat;
  1146. // set pCond to a high level representation of this type
  1147. Exp* p = NULL;
  1148. switch(cond) {
  1149. case BRANCH_JE:
  1150. p = new Binary(opEquals, new Terminal(opFlags), new Const(0));
  1151. break;
  1152. case BRANCH_JNE:
  1153. p = new Binary(opNotEqual, new Terminal(opFlags), new Const(0));
  1154. break;
  1155. case BRANCH_JSL:
  1156. p = new Binary(opLess, new Terminal(opFlags), new Const(0));
  1157. break;
  1158. case BRANCH_JSLE:
  1159. p = new Binary(opLessEq, new Terminal(opFlags), new Const(0));
  1160. break;
  1161. case BRANCH_JSGE:
  1162. p = new Binary(opGtrEq, new Terminal(opFlags), new Const(0));
  1163. break;
  1164. case BRANCH_JSG:
  1165. p = new Binary(opGtr, new Terminal(opFlags), new Const(0));
  1166. break;
  1167. case BRANCH_JUL:
  1168. p = new Binary(opLessUns, new Terminal(opFlags), new Const(0));
  1169. break;
  1170. case BRANCH_JULE:
  1171. p = new Binary(opLessEqUns, new Terminal(opFlags), new Const(0));
  1172. break;
  1173. case BRANCH_JUGE:
  1174. p = new Binary(opGtrEqUns, new Terminal(opFlags), new Const(0));
  1175. break;
  1176. case BRANCH_JUG:
  1177. p = new Binary(opGtrUns, new Terminal(opFlags), new Const(0));
  1178. break;
  1179. case BRANCH_JMI:
  1180. p = new Binary(opLess, new Terminal(opFlags), new Const(0));
  1181. break;
  1182. case BRANCH_JPOS:
  1183. p = new Binary(opGtr, new Terminal(opFlags), new Const(0));
  1184. break;
  1185. case BRANCH_JOF:
  1186. p = new Binary(opLessUns, new Terminal(opFlags), new Const(0));
  1187. break;
  1188. case BRANCH_JNOF:
  1189. p = new Binary(opGtrUns, new Terminal(opFlags), new Const(0));
  1190. break;
  1191. case BRANCH_JPAR:
  1192. // Can't handle this properly here; leave an impossible expression involving %flags so propagation will
  1193. // still happen, and we can recognise this later in condToRelational()
  1194. // Update: these expressions seem to get ignored ???
  1195. p = new Binary(opEquals, new Terminal(opFlags), new Const(999));
  1196. break;
  1197. }
  1198. // this is such a hack.. preferably we should actually recognise SUBFLAGS32(..,..,..) > 0 instead of just
  1199. // SUBFLAGS32(..,..,..) but I'll leave this in here for the moment as it actually works.
  1200. if (!Boomerang::get()->noDecompile)
  1201. p = new Terminal(usesFloat ? opFflags : opFlags);
  1202. assert(p);
  1203. setCondExpr(p);
  1204. }
  1205. /*==============================================================================
  1206. * FUNCTION: BranchStatement::makeSigned
  1207. * OVERVIEW: Change this from an unsigned to a signed branch
  1208. * PARAMETERS: <none>
  1209. * RETURNS: <nothing>
  1210. *============================================================================*/
  1211. void BranchStatement::makeSigned() {
  1212. // Make this into a signed branch
  1213. switch (jtCond)
  1214. {
  1215. case BRANCH_JUL : jtCond = BRANCH_JSL; break;
  1216. case BRANCH_JULE: jtCond = BRANCH_JSLE; break;
  1217. case BRANCH_JUGE: jtCond = BRANCH_JSGE; break;
  1218. case BRANCH_JUG : jtCond = BRANCH_JSG; break;
  1219. default:
  1220. // Do nothing for other cases
  1221. break;
  1222. }
  1223. }
  1224. /*==============================================================================
  1225. * FUNCTION: BranchStatement::getCondExpr
  1226. * OVERVIEW: Return the SemStr expression containing the HL condition.
  1227. * PARAMETERS: <none>
  1228. * RETURNS: ptr to an expression
  1229. *============================================================================*/
  1230. Exp* BranchStatement::getCondExpr() {
  1231. return pCond;
  1232. }
  1233. /*==============================================================================
  1234. * FUNCTION: BranchStatement::setCondExpr
  1235. * OVERVIEW: Set the SemStr expression containing the HL condition.
  1236. * PARAMETERS: Pointer to Exp to set
  1237. * RETURNS: <nothing>
  1238. *============================================================================*/
  1239. void BranchStatement::setCondExpr(Exp* e) {
  1240. if (pCond) ;//delete pCond;
  1241. pCond = e;
  1242. }
  1243. PBB BranchStatement::getFallBB()
  1244. {
  1245. ADDRESS a = getFixedDest();
  1246. if (a == NO_ADDRESS)
  1247. return NULL;
  1248. if (pbb == NULL)
  1249. return NULL;
  1250. if (pbb->getNumOutEdges() != 2)
  1251. return NULL;
  1252. if (pbb->getOutEdge(0)->getLowAddr() == a)
  1253. return pbb->getOutEdge(1);
  1254. return pbb->getOutEdge(0);
  1255. }
  1256. // not that if you set the taken BB or fixed dest first, you will not be able to set the fall BB
  1257. void BranchStatement::setFallBB(PBB bb)
  1258. {
  1259. ADDRESS a = getFixedDest();
  1260. if (a == NO_ADDRESS)
  1261. return;
  1262. if (pbb == NULL)
  1263. return;
  1264. if (pbb->getNumOutEdges() != 2)
  1265. return;
  1266. if (pbb->getOutEdge(0)->getLowAddr() == a) {
  1267. pbb->getOutEdge(1)->deleteInEdge(pbb);
  1268. pbb->setOutEdge(1, bb);
  1269. bb->addInEdge(pbb);
  1270. } else {
  1271. pbb->getOutEdge(0)->deleteInEdge(pbb);
  1272. pbb->setOutEdge(0, bb);
  1273. bb->addInEdge(pbb);
  1274. }
  1275. }
  1276. PBB BranchStatement::getTakenBB()
  1277. {
  1278. ADDRESS a = getFixedDest();
  1279. if (a == NO_ADDRESS)
  1280. return NULL;
  1281. if (pbb == NULL)
  1282. return NULL;
  1283. if (pbb->getNumOutEdges() != 2)
  1284. return NULL;
  1285. if (pbb->getOutEdge(0)->getLowAddr() == a)
  1286. return pbb->getOutEdge(0);
  1287. return pbb->getOutEdge(1);
  1288. }
  1289. void BranchStatement::setTakenBB(PBB bb)
  1290. {
  1291. ADDRESS a = getFixedDest();
  1292. if (a == NO_ADDRESS)
  1293. return;
  1294. if (pbb == NULL)
  1295. return;
  1296. if (pbb->getNumOutEdges() != 2)
  1297. return;
  1298. if (pbb->getOutEdge(0)->getLowAddr() == a) {
  1299. pbb->getOutEdge(0)->deleteInEdge(pbb);
  1300. pbb->setOutEdge(0, bb);
  1301. bb->addInEdge(pbb);
  1302. } else {
  1303. pbb->getOutEdge(1)->deleteInEdge(pbb);
  1304. pbb->setOutEdge(1, bb);
  1305. bb->addInEdge(pbb);
  1306. }
  1307. }
  1308. bool BranchStatement::search(Exp* search, Exp*& result) {
  1309. if (pCond) return pCond->search(search, result);
  1310. result = NULL;
  1311. return false;
  1312. }
  1313. /*==============================================================================
  1314. * FUNCTION: BranchStatement::searchAndReplace
  1315. * OVERVIEW: Replace all instances of search with replace.
  1316. * PARAMETERS: search - a location to search for
  1317. * replace - the expression with which to replace it
  1318. * cc - ignored
  1319. * RETURNS: True if any change
  1320. *============================================================================*/
  1321. bool BranchStatement::searchAndReplace(Exp* search, Exp* replace, bool cc) {
  1322. GotoStatement::searchAndReplace(search, replace, cc);
  1323. bool change = false;
  1324. if (pCond)
  1325. pCond = pCond->searchReplaceAll(search, replace, change);
  1326. return change;
  1327. }
  1328. /*==============================================================================
  1329. * FUNCTION: BranchStatement::searchAll
  1330. * OVERVIEW: Find all instances of the search expression
  1331. * PARAMETERS: search - a location to search for
  1332. * result - a list which will have any matching exprs
  1333. * appended to it
  1334. * RETURNS: true if there were any matches
  1335. *============================================================================*/
  1336. bool BranchStatement::searchAll(Exp* search, std::list<Exp*> &result) {
  1337. if (pCond) return pCond->searchAll(search, result);
  1338. return false;
  1339. }
  1340. /*==============================================================================
  1341. * FUNCTION: BranchStatement::print
  1342. * OVERVIEW: Write a text representation to the given stream
  1343. * PARAMETERS: os: stream
  1344. * RETURNS: Nothing
  1345. *============================================================================*/
  1346. void BranchStatement::print(std::ostream& os, bool html) {
  1347. os << std::setw(4) << std::dec << number << " ";
  1348. if (html) {
  1349. os << "</td><td>";
  1350. os << "<a name=\"stmt" << std::dec << number << "\">";
  1351. }
  1352. os << "BRANCH ";
  1353. if (pDest == NULL)
  1354. os << "*no dest*";
  1355. else if (!pDest->isIntConst())
  1356. os << pDest;
  1357. else {
  1358. // Really we'd like to display the destination label here...
  1359. os << "0x" << std::hex << getFixedDest();
  1360. }
  1361. os << ", condition ";
  1362. switch (jtCond) {
  1363. case BRANCH_JE: os << "equals"; break;
  1364. ca

Large files files are truncated, but you can click here to view the full file