00001 /* 00002 * Copyright (C) 1998-2001, The University of Queensland 00003 * Copyright (C) 2000-2001, Sun Microsystems, Inc 00004 * Copyright (C) 2002, Trent Waddington 00005 * 00006 * See the file "LICENSE.TERMS" for information on usage and 00007 * redistribution of this file, and for a DISCLAIMER OF ALL 00008 * WARRANTIES. 00009 * 00010 */ 00011 00012 /*============================================================================== 00013 * FILE: rtl.cc 00014 * OVERVIEW: Implementation of the classes that describe a low level RTL ( 00015 * register transfer list) 00016 *============================================================================*/ 00017 00018 /* 00019 * $Revision: 1.38 $ // 1.33.2.3 00020 * 00021 * 08 Apr 02 - Mike: Changes for boomerang 00022 * 13 May 02 - Mike: expList is no longer a pointer 00023 * 15 May 02 - Mike: Fixed a nasty bug in updateExp (when update with same 00024 * expression as existing) 00025 * 25 Jul 02 - Mike: RTL is now list of Statements 00026 */ 00027 00028 #include <assert.h> 00029 #if defined(_MSC_VER) && _MSC_VER <= 1200 00030 #pragma warning(disable:4786) 00031 #endif 00032 00033 #include <iomanip> // For setfill 00034 #include <sstream> 00035 #include "types.h" 00036 #include "statement.h" 00037 #include "exp.h" 00038 #include "type.h" 00039 #include "register.h" 00040 #include "cfg.h" 00041 #include "proc.h" // For printing proc names 00042 #include "rtl.h" 00043 #include "prog.h" 00044 #include "hllcode.h" 00045 #include "util.h" 00046 #include "boomerang.h" 00047 #include "visitor.h" 00048 #include "log.h" 00049 // For some reason, MSVC 5.00 complains about use of undefined types a lot 00050 #if defined(_MSC_VER) && _MSC_VER <= 1100 00051 #include "signature.h" // For MSVC 5.00 00052 #endif 00053 00054 /****************************************************************************** 00055 * RTL methods. 00056 * Class RTL represents low-level register transfer lists. 00057 *****************************************************************************/ 00058 00059 /*============================================================================== 00060 * FUNCTION: RTL::RTL 00061 * OVERVIEW: Constructor. 00062 * PARAMETERS: <none> 00063 * RETURNS: N/a 00064 *============================================================================*/ 00065 RTL::RTL() 00066 : nativeAddr(0) 00067 { } 00068 00069 /*============================================================================== 00070 * FUNCTION: RTL::RTL 00071 * OVERVIEW: Constructor. 00072 * PARAMETERS: instNativeAddr - the native address of the instruction 00073 * listExp - ptr to existing list of Exps 00074 * RETURNS: N/a 00075 *============================================================================*/ 00076 RTL::RTL(ADDRESS instNativeAddr, std::list<Statement*>* listStmt /*= NULL*/) 00077 : nativeAddr(instNativeAddr) { 00078 if (listStmt) 00079 stmtList = *listStmt; 00080 } 00081 00082 /*============================================================================== 00083 * FUNCTION: RTL::RTL 00084 * OVERVIEW: Copy constructor. A deep clone is made of the given object 00085 * so that the lists of Exps do not share memory. 00086 * PARAMETERS: other: RTL to copy from 00087 * RETURNS: N/a 00088 *============================================================================*/ 00089 RTL::RTL(const RTL& other) : nativeAddr(other.nativeAddr) { 00090 std::list<Statement*>::const_iterator it; 00091 for (it = other.stmtList.begin(); it != other.stmtList.end(); it++) { 00092 stmtList.push_back((*it)->clone()); 00093 } 00094 } 00095 00096 /*============================================================================== 00097 * FUNCTION: RTL::~RTL 00098 * OVERVIEW: Destructor. 00099 * PARAMETERS: <none> 00100 * RETURNS: N/a 00101 *============================================================================*/ 00102 RTL::~RTL() { } 00103 00104 /*============================================================================== 00105 * FUNCTION: RTL::operator= 00106 * OVERVIEW: Assignment copy (deep). 00107 * PARAMETERS: other - RTL to copy 00108 * RETURNS: a reference to this object 00109 *============================================================================*/ 00110 RTL& RTL::operator=(RTL& other) { 00111 if (this != &other) { 00112 // Do a deep copy always 00113 iterator it; 00114 for (it = other.stmtList.begin(); it != other.stmtList.end(); it++) 00115 stmtList.push_back((*it)->clone()); 00116 00117 nativeAddr = other.nativeAddr; 00118 } 00119 return *this; 00120 } 00121 00122 /*============================================================================== 00123 * FUNCTION: RTL:clone 00124 * OVERVIEW: Deep copy clone; deleting the clone will not affect this 00125 * RTL object 00126 * PARAMETERS: <none> 00127 * RETURNS: Pointer to a new RTL that is a clone of this one 00128 *============================================================================*/ 00129 RTL* RTL::clone() { 00130 std::list<Statement*> le; 00131 iterator it; 00132 00133 for (it = stmtList.begin(); it != stmtList.end(); it++) { 00134 le.push_back((*it)->clone()); 00135 } 00136 00137 RTL* ret = new RTL(nativeAddr, &le); 00138 return ret; 00139 } 00140 00141 // visit this RTL, and all its Statements 00142 bool RTL::accept(StmtVisitor* visitor) { 00143 // Might want to do something at the RTL level: 00144 if (!visitor->visit(this)) return false; 00145 iterator it; 00146 for (it = stmtList.begin(); it != stmtList.end(); it++) { 00147 if (! (*it)->accept(visitor)) return false; 00148 } 00149 return true; 00150 } 00151 00152 /*============================================================================== 00153 * FUNCTION: RTL::deepCopyList 00154 * OVERVIEW: Make a copy of this RTLs list of Exp* to the given list 00155 * PARAMETERS: Ref to empty list to copy to 00156 * RETURNS: Nothing 00157 *============================================================================*/ 00158 void RTL::deepCopyList(std::list<Statement*>& dest) { 00159 std::list<Statement*>::iterator it; 00160 00161 for (it = stmtList.begin(); it != stmtList.end(); it++) { 00162 dest.push_back((*it)->clone()); 00163 } 00164 } 00165 00166 /*============================================================================== 00167 * FUNCTION: RTL::appendStmt 00168 * OVERVIEW: Append the given Statement at the end of this RTL 00169 * NOTE: Exception: Leaves any flag call at the end (so may push exp 00170 * to second last position, instead of last) 00171 * NOTE: stmt is NOT copied. This is different to how UQBT was! 00172 * PARAMETERS: s: pointer to Statement to append 00173 * RETURNS: Nothing 00174 *============================================================================*/ 00175 void RTL::appendStmt(Statement* s) { 00176 if (stmtList.size()) { 00177 if (stmtList.back()->isFlagAssgn()) { 00178 iterator it = stmtList.end(); 00179 stmtList.insert(--it, s); 00180 return; 00181 } 00182 } 00183 stmtList.push_back(s); 00184 } 00185 00186 /*============================================================================== 00187 * FUNCTION: RTL::prependStmt 00188 * OVERVIEW: Prepend the given Statement at the start of this RTL 00189 * NOTE: No clone of the statement is made. This is different to how UQBT was 00190 * PARAMETERS: s: Ptr to Statement to prepend 00191 * RETURNS: Nothing 00192 *============================================================================*/ 00193 void RTL::prependStmt(Statement* s) { 00194 stmtList.push_front(s); 00195 } 00196 00197 /*============================================================================== 00198 * FUNCTION: RTL::appendListStmt 00199 * OVERVIEW: Append a given list of Statements to this RTL 00200 * NOTE: A copy of the Statements in le are appended 00201 * PARAMETERS: rtl: list of Exps to insert 00202 * RETURNS: Nothing 00203 *============================================================================*/ 00204 void RTL::appendListStmt(std::list<Statement*>& le) { 00205 iterator it; 00206 for (it = le.begin(); it != le.end(); it++) { 00207 stmtList.insert(stmtList.end(), (*it)->clone()); 00208 } 00209 } 00210 00211 /*============================================================================== 00212 * FUNCTION: RTL::appendRTL 00213 * OVERVIEW: Append the Statemens of another RTL to this object 00214 * NOTE: A copy of the Statements in r are appended 00215 * PARAMETERS: r: reterence to RTL whose Exps we are to insert 00216 * RETURNS: Nothing 00217 *============================================================================*/ 00218 void RTL::appendRTL(RTL& r) { 00219 appendListStmt(r.stmtList); 00220 } 00221 00222 /*============================================================================== 00223 * FUNCTION: RTL::insertStmt 00224 * OVERVIEW: Insert the given Statement before index i 00225 * NOTE: No copy of stmt is made. This is different to UQBT 00226 * PARAMETERS: s: pointer to the Statement to insert 00227 * i: position to insert before (0 = first) 00228 * RETURNS: Nothing 00229 *============================================================================*/ 00230 void RTL::insertStmt(Statement* s, unsigned i) { 00231 // Check that position i is not out of bounds 00232 assert (i < stmtList.size() || stmtList.size() == 0); 00233 00234 // Find the position 00235 iterator pp = stmtList.begin(); 00236 for (; i > 0; i--, pp++); 00237 00238 // Do the insertion 00239 stmtList.insert(pp, s); 00240 } 00241 00242 void RTL::insertStmt(Statement* s, iterator it) { 00243 stmtList.insert(it, s); 00244 } 00245 00246 /*============================================================================== 00247 * FUNCTION: RTL::updateStmt 00248 * OVERVIEW: Replace the ith Statement with the given one 00249 * PARAMETERS: s: pointer to the new Exp 00250 * i: index of Exp position (0 = first) 00251 * RETURNS: Nothing 00252 *============================================================================*/ 00253 void RTL::updateStmt(Statement *s, unsigned i) { 00254 // Check that position i is not out of bounds 00255 assert (i < stmtList.size()); 00256 00257 // Find the position 00258 iterator pp = stmtList.begin(); 00259 for (; i > 0; i--, pp++); 00260 00261 // Note that sometimes we might update even when we don't know if it's 00262 // needed, e.g. after a searchReplace. 00263 // In that case, don't update, and especially don't delete the existing 00264 // statement (because it's also the one we are updating!) 00265 if (*pp != s) { 00266 // Do the update 00267 if (*pp) ;//delete *pp; 00268 *pp = s; 00269 } 00270 } 00271 00272 void RTL::deleteStmt(unsigned i) { 00273 // check that position i is not out of bounds 00274 assert (i < stmtList.size()); 00275 00276 // find the position 00277 iterator pp = stmtList.begin(); 00278 for (; i > 0; i--, pp++); 00279 00280 // do the delete 00281 stmtList.erase(pp); 00282 } 00283 00284 void RTL::deleteLastStmt() { 00285 assert(stmtList.size()); 00286 stmtList.erase(--stmtList.end()); 00287 } 00288 00289 void RTL::replaceLastStmt(Statement* repl) { 00290 assert(stmtList.size()); 00291 Statement*& last = stmtList.back(); 00292 last = repl; 00293 } 00294 00295 00296 /*============================================================================== 00297 * FUNCTION: RTL::getNumStmt 00298 * OVERVIEW: Get the number of Statements in this RTL 00299 * PARAMETERS: None 00300 * RETURNS: Integer number of Statements 00301 *============================================================================*/ 00302 int RTL::getNumStmt() { 00303 return stmtList.size(); 00304 } 00305 00306 /*============================================================================== 00307 * FUNCTION: RTL::at 00308 * OVERVIEW: Provides indexing on a list. Changed from operator[] so that 00309 * we keep in mind it is linear in its execution time. 00310 * PARAMETERS: i - the index of the element we want (0 = first) 00311 * RETURNS: the element at the given index or NULL if the index is out 00312 * of bounds 00313 *============================================================================*/ 00314 Statement* RTL::elementAt(unsigned i) { 00315 iterator it; 00316 for (it = stmtList.begin(); i > 0 && it != stmtList.end(); i--, it++); 00317 if (it == stmtList.end()) { 00318 return NULL; 00319 } 00320 return *it; 00321 } 00322 00323 /*============================================================================== 00324 * FUNCTION: RTL::print 00325 * OVERVIEW: Prints this object to a stream in text form. 00326 * PARAMETERS: os - stream to output to (often cout or cerr) 00327 * RETURNS: <nothing> 00328 *============================================================================*/ 00329 void RTL::print(std::ostream& os /*= cout*/, bool html /*=false*/) { 00330 00331 if (html) 00332 os << "<tr><td>"; 00333 // print out the instruction address of this RTL 00334 os << std::hex << std::setfill('0') << std::setw(8) << nativeAddr; 00335 os << std::dec << std::setfill(' '); // Ugh - why is this needed? 00336 if (html) 00337 os << "</td>"; 00338 00339 // Print the statements 00340 // First line has 8 extra chars as above 00341 bool bFirst = true; 00342 iterator ss; 00343 for (ss = stmtList.begin(); ss != stmtList.end(); ss++) { 00344 Statement* stmt = *ss; 00345 if (html) { 00346 if (!bFirst) os << "<tr><td></td>"; 00347 os << "<td width=\"50\" align=\"center\">"; 00348 } else { 00349 if (bFirst) os << " "; 00350 else os << std::setw(9) << " "; 00351 } 00352 if (stmt) stmt->print(os, html); 00353 // Note: we only put newlines where needed. So none at the end of 00354 // Statement::print; one here to separate from other statements 00355 if (html) 00356 os << "</td></tr>"; 00357 os << "\n"; 00358 bFirst = false; 00359 } 00360 if (stmtList.empty()) os << std::endl; // New line for NOP 00361 } 00362 00363 void RTL::dump() { 00364 print(std::cerr); 00365 } 00366 00367 extern char debug_buffer[]; 00368 00369 char* RTL::prints() { 00370 std::ostringstream ost; 00371 print(ost); 00372 strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1); 00373 debug_buffer[DEBUG_BUFSIZE-1] = '\0'; 00374 return debug_buffer; 00375 } 00376 00377 /*============================================================================== 00378 * FUNCTION: operator<< 00379 * OVERVIEW: Output operator for RTL* 00380 * Just makes it easier to use e.g. std::cerr << myRTLptr 00381 * PARAMETERS: os: output stream to send to 00382 * p: ptr to RTL to print to the stream 00383 * RETURNS: copy of os (for concatenation) 00384 *============================================================================*/ 00385 std::ostream& operator<<(std::ostream& os, RTL* r) { 00386 if (r == NULL) {os << "NULL "; return os;} 00387 r->print(os); 00388 return os; 00389 } 00390 00391 /*============================================================================== 00392 * FUNCTION: RTL::updateAddress 00393 * OVERVIEW: Set the nativeAddr field 00394 * PARAMETERS: Native address 00395 * RETURNS: Nothing 00396 *============================================================================*/ 00397 void RTL::updateAddress(ADDRESS addr) { 00398 nativeAddr = addr; 00399 } 00400 00401 /*============================================================================== 00402 * FUNCTION: RTL::searchReplace 00403 * OVERVIEW: Replace all instances of search with replace. 00404 * PARAMETERS: search - ptr to an expression to search for 00405 * replace - ptr to the expression with which to replace it 00406 * RETURNS: <nothing> 00407 *============================================================================*/ 00408 bool RTL::searchAndReplace(Exp* search, Exp* replace) { 00409 bool ch = false; 00410 for (iterator it = stmtList.begin(); it != stmtList.end(); it++) 00411 ch |= (*it)->searchAndReplace(search, replace); 00412 return ch; 00413 } 00414 00415 /*============================================================================== 00416 * FUNCTION: RTL::searchAll 00417 * OVERVIEW: Find all instances of the search expression 00418 * PARAMETERS: search - a location to search for 00419 * result - a list which will have any matching exprs 00420 * appended to it 00421 * RETURNS: true if there were any matches 00422 *============================================================================*/ 00423 bool RTL::searchAll(Exp* search, std::list<Exp *> &result) { 00424 bool found = false; 00425 for (iterator it = stmtList.begin(); it != stmtList.end(); it++) { 00426 Statement *e = *it; 00427 Exp* res; 00428 if (e->search(search, res)) { 00429 found = true; 00430 result.push_back(res); 00431 } 00432 } 00433 return found; 00434 } 00435 00436 /*============================================================================== 00437 * FUNCTION: RTL::clear 00438 * OVERVIEW: Clear the list of Exps 00439 * PARAMETERS: None 00440 * RETURNS: Nothing 00441 *============================================================================*/ 00442 void RTL::clear() { 00443 stmtList.clear(); 00444 } 00445 00446 /*============================================================================== 00447 * FUNCTION: RTL::insertAssign 00448 * OVERVIEW: Prepends or appends an assignment to the front or back of 00449 * this RTL 00450 * NOTE: Is this really used? What about types? 00451 * ASSUMES: Assumes that pLhs and pRhs are "new" Exp's that are 00452 * not part of other Exps. (Otherwise, there will be problems 00453 * when deleting this Exp) 00454 * If size == -1, assumes there is already at least one assign- 00455 * ment in this RTL 00456 * PARAMETERS: pLhs: ptr to Exp to place on LHS 00457 * pRhs: ptr to Exp to place on the RHS 00458 * prep: true if prepend (else append) 00459 * type: type of the transfer, or NULL 00460 * RETURNS: <nothing> 00461 *============================================================================*/ 00462 void RTL::insertAssign(Exp* pLhs, Exp* pRhs, bool prep, 00463 Type* type /*= NULL */) { 00464 // Generate the assignment expression 00465 Assign* asgn = new Assign(type, pLhs, pRhs); 00466 if (prep) 00467 prependStmt(asgn); 00468 else 00469 appendStmt(asgn); 00470 } 00471 00472 /*============================================================================== 00473 * FUNCTION: RTL::insertAfterTemps 00474 * OVERVIEW: Inserts an assignment at or near the top of this RTL, after 00475 * any assignments to temporaries. If the last assignment 00476 * is to a temp, the insertion is done before that last 00477 * assignment 00478 * ASSUMES: Assumes that ssLhs and ssRhs are "new" Exp's that are 00479 * not part of other Exps. (Otherwise, there will be problems 00480 * when deleting this Exp) 00481 * If type == NULL, assumes there is already at least one 00482 * assignment in this RTL (?) 00483 * NOTE: Hopefully this is only a temporary measure 00484 * PARAMETERS: pLhs: ptr to Exp to place on LHS 00485 * pRhs: ptr to Exp to place on the RHS 00486 * size: size of the transfer, or -1 to be the same as the 00487 * first assign this RTL 00488 * RETURNS: <nothing> 00489 *============================================================================*/ 00490 void RTL::insertAfterTemps(Exp* pLhs, Exp* pRhs, Type* type /* NULL */) { 00491 iterator it; 00492 // First skip all assignments with temps on LHS 00493 for (it = stmtList.begin(); it != stmtList.end(); it++) { 00494 Statement *s = *it; 00495 if (!s->isAssign()) 00496 break; 00497 Exp* LHS = ((Assign*)s)->getLeft(); 00498 if (LHS->isTemp()) 00499 break; 00500 } 00501 00502 // Now check if the next Stmt is an assignment 00503 if ((it == stmtList.end()) || !(*it)->isAssign()) { 00504 // There isn't an assignment following. Use the previous Exp to insert 00505 // before 00506 if (it != stmtList.begin()) 00507 it--; 00508 } 00509 00510 if (type == NULL) 00511 type = getType(); 00512 00513 // Generate the assignment expression 00514 Assign* asgn = new Assign(type, pLhs, pRhs); 00515 00516 // Insert before "it" 00517 stmtList.insert(it, asgn); 00518 } 00519 00520 /*============================================================================== 00521 * FUNCTION: RTL::getType 00522 * OVERVIEW: Get the "type" for this RTL. Just gets the type of 00523 * the first assignment Exp 00524 * NOTE: The type of the first assign may not be the type that you 00525 * want! 00526 * PARAMETERS: None 00527 * RETURNS: A pointer to the type 00528 *============================================================================*/ 00529 Type* RTL::getType() { 00530 iterator it; 00531 for (it = stmtList.begin(); it != stmtList.end(); it++) { 00532 Statement *e = *it; 00533 if (e->isAssign()) 00534 return ((Assign*)e)->getType(); 00535 } 00536 return new IntegerType(); // Default to 32 bit integer if no assignments 00537 } 00538 00539 /*============================================================================== 00540 * FUNCTION: RTL::areFlagsAffected 00541 * OVERVIEW: Return true if this RTL affects the condition codes 00542 * NOTE: Assumes that if there is a flag call Exp, then it is the last 00543 * PARAMETERS: None 00544 * RETURNS: Boolean as above 00545 *============================================================================*/ 00546 bool RTL::areFlagsAffected() { 00547 if (stmtList.size() == 0) return false; 00548 // Get an iterator to the last RT 00549 iterator it = stmtList.end(); 00550 if (it == stmtList.begin()) 00551 return false; // Not expressions at all 00552 it--; // Will now point to the end of the list 00553 Statement *e = *it; 00554 // If it is a flag call, then the CCs are affected 00555 return e->isFlagAssgn(); 00556 } 00557 00558 void RTL::generateCode(HLLCode *hll, BasicBlock *pbb, int indLevel) { 00559 for (iterator it = stmtList.begin(); 00560 it != stmtList.end(); it++) { 00561 (*it)->generateCode(hll, pbb, indLevel); 00562 } 00563 } 00564 00565 void RTL::simplify() { 00566 for (iterator it = stmtList.begin(); it != stmtList.end(); /*it++*/) { 00567 Statement *s = *it; 00568 s->simplify(); 00569 if (s->isBranch()) { 00570 Exp *cond = ((BranchStatement*)s)->getCondExpr(); 00571 if (cond && cond->getOper() == opIntConst) { 00572 if (((Const*)cond)->getInt() == 0) { 00573 if (VERBOSE) 00574 LOG << "removing branch with false condition at " << getAddress() << " " << *it << "\n"; 00575 it = stmtList.erase(it); 00576 continue; 00577 } else { 00578 if (VERBOSE) 00579 LOG << "replacing branch with true condition with goto at " << getAddress() << " " << *it << 00580 "\n"; 00581 *it = new GotoStatement(((BranchStatement*)s)->getFixedDest()); 00582 } 00583 } 00584 } else if (s->isAssign()) { 00585 Exp* guard = ((Assign*)s)->getGuard(); 00586 if (guard && (guard->isFalse() || guard->isIntConst() && ((Const*)guard)->getInt() == 0)) { 00587 // This assignment statement can be deleted 00588 if (VERBOSE) 00589 LOG << "removing assignment with false guard at " << getAddress() << " " << *it << "\n"; 00590 it = stmtList.erase(it); 00591 continue; 00592 } 00593 } 00594 it++; 00595 } 00596 } 00597 00598 /*============================================================================== 00599 * FUNCTION: RTL::isCompare 00600 * OVERVIEW: Return true if this is an unmodified compare instruction 00601 * of a register with an operand 00602 * NOTE: Will also match a subtract if the flags are set 00603 * NOTE: expOperand, if set, is not cloned 00604 * NOTE: Assumes that the first subtract on the RHS is the actual 00605 * compare operation 00606 * PARAMETERS: iReg: ref to integer to set with the register index 00607 * expOperand: ref to ptr to expression of operand 00608 * RETURNS: True if found 00609 *============================================================================*/ 00610 bool RTL::isCompare(int& iReg, Exp*& expOperand) { 00611 // Expect to see a subtract, then a setting of the flags 00612 // Dest of subtract should be a register (could be the always zero register) 00613 if (getNumStmt() < 2) return false; 00614 // Could be first some assignments to temporaries 00615 // But the actual compare could also be an assignment to a temporary 00616 // So we search for the first RHS with an opMinus, that has a LHS to 00617 // a register (whether a temporary or a machine register) 00618 int i=0; 00619 Exp* rhs; 00620 Statement* cur; 00621 do { 00622 cur = elementAt(i); 00623 if (cur->getKind() != STMT_ASSIGN) return false; 00624 rhs = ((Assign*)cur)->getRight(); 00625 i++; 00626 } while (rhs->getOper() != opMinus && i < getNumStmt()); 00627 if (rhs->getOper() != opMinus) return false; 00628 // We have a subtract assigning to a register. 00629 // Check if there is a subflags last 00630 Statement* last = elementAt(getNumStmt()-1); 00631 if (!last->isFlagAssgn()) return false; 00632 Exp* sub = ((Binary*)rhs)->getSubExp1(); 00633 // Should be a compare of a register and something (probably a constant) 00634 if (!sub->isRegOf()) return false; 00635 // Set the register and operand expression, and return true 00636 iReg = ((Const*)((Unary*)sub)->getSubExp1())->getInt(); 00637 expOperand = ((Binary*)rhs)->getSubExp2(); 00638 return true; 00639 } 00640 00641 bool RTL::isGoto() { 00642 if (stmtList.empty()) return false; 00643 Statement* last = stmtList.back(); 00644 return last->getKind() == STMT_GOTO; 00645 } 00646 00647 bool RTL::isBranch() { 00648 if (stmtList.empty()) return false; 00649 Statement* last = stmtList.back(); 00650 return last->getKind() == STMT_BRANCH; 00651 } 00652 00653 bool RTL::isCall() { 00654 if (stmtList.empty()) return false; 00655 Statement* last = stmtList.back(); 00656 return last->getKind() == STMT_CALL; 00657 } 00658 00659 // Use this slow function when you can't be sure that the HL Statement is last 00660 Statement* RTL::getHlStmt() { 00661 reverse_iterator rit; 00662 for (rit = stmtList.rbegin(); rit != stmtList.rend(); rit++) { 00663 if ((*rit)->getKind() != STMT_ASSIGN) 00664 return *rit; 00665 } 00666 return NULL; 00667 } 00668 00669 int RTL::setConscripts(int n, bool bClear) { 00670 StmtConscriptSetter ssc(n, bClear); 00671 accept(&ssc); 00672 return ssc.getLast(); 00673 }