void CallsTest::testIsCalls(){ Calls c; CallsExtractor extractor(&c); c.insertCalls(1,2); c.insertCalls(2,3); c.insertCalls(1,3); extractor.construct(); CPPUNIT_ASSERT_EQUAL(true,c.isCalls(1,2)); CPPUNIT_ASSERT_EQUAL(true,c.isCalls(2,3)); CPPUNIT_ASSERT_EQUAL(true,c.isCalls(1,3)); }
/** * Q: how can this be optimized? * @brief provides access to all call transitions with the given from state * and symbol in this collection of transitions * * @param - from: the desired from state for the call transitions * @param - sym: the desired symbol for the call transitions * @return the set of call transitions with the given from state and symbol * */ const TransitionStorage::Calls TransitionStorage::getCalls( State from, Symbol sym ) const { Calls result; Calls const & outgoing = T_info.callTrans(from); for( CallIterator cit = outgoing.begin(); cit != outgoing.end(); cit++ ) { if( getCallSym(*cit) == sym ) result.insert(*cit); } return result; }
void CallsTest::testGetAllCallers(){ Calls c; CallsExtractor extractor(&c); c.insertCalls(1,2); c.insertCalls(2,3); c.insertCalls(1,3); extractor.construct(); set<int> callers = c.getAllCallers(); CPPUNIT_ASSERT(callers.size()==2); std::set<int>::iterator itr = callers.begin(); CPPUNIT_ASSERT_EQUAL(1,*itr); itr++; CPPUNIT_ASSERT_EQUAL(2,*itr); return; }
void CallsTest::testEvaluateGetCallersStar(){ Calls c; CallsExtractor extractor(&c); c.insertCalls(1,2); c.insertCalls(2,3); c.insertCalls(1,4); c.insertCalls(4,5); extractor.construct(); set<int> callers = c.evaluateGetCallersStar(5); CPPUNIT_ASSERT(callers.size()==2); std::set<int>::iterator itr = callers.begin(); CPPUNIT_ASSERT_EQUAL(1,*itr); itr++; CPPUNIT_ASSERT_EQUAL(4,*itr); return; }
/** * * @brief removes all call transitions with the given symbol * * @param - sym: the symbol whose transitions to remove * @return false if no transitions were removed, true otherwise * */ bool TransitionStorage::removeCallTransSym( Symbol sym ) { Calls removeTrans; //Find transitions to remove. for( CallIterator cit = callTrans.begin(); cit != callTrans.end(); cit++ ) { if( getCallSym(*cit) == sym ) removeTrans.insert(*cit); } //Remove transitions. for( CallIterator rit = removeTrans.begin(); rit != removeTrans.end(); rit++ ) { removeCall(*rit); } return removeTrans.size() > 0; }
void CallsTest::testGetCalleeStar(){ Calls c; CallsExtractor extractor(&c); c.insertCalls(1,2); c.insertCalls(2,3); c.insertCalls(1,3); c.insertCalls(1,4); c.insertCalls(4,5); extractor.construct(); set<int> callees = c.getCalleeStar(1); CPPUNIT_ASSERT(callees.size()==4); std::set<int>::iterator itr = callees.begin(); CPPUNIT_ASSERT_EQUAL(2,*itr); itr++; CPPUNIT_ASSERT_EQUAL(3,*itr); itr++; CPPUNIT_ASSERT_EQUAL(4,*itr); itr++; CPPUNIT_ASSERT_EQUAL(5,*itr); return; }
void CallsTest::testInsertCalls(){ Calls c; CallsExtractor extractor(&c); c.insertCalls(1,2); c.insertCalls(2,3); c.insertCalls(1,3); c.insertCalls(1,4); c.insertCalls(4,5); extractor.construct(); CPPUNIT_ASSERT(c.isCalls(1,2)); CPPUNIT_ASSERT(c.isCalls(1,3)); CPPUNIT_ASSERT(c.isCalls(1,4)); CPPUNIT_ASSERT(c.isCalls(2,3)); CPPUNIT_ASSERT(c.isCalls(4,5)); CPPUNIT_ASSERT_EQUAL(5,c.getSize()); return; }
/** * * @brief removes all call transitions to or from the given state * * @param - state: the state whose transitions to remove * @return false if no transitions were removed, true otherwise * */ bool TransitionStorage::removeCallTransWith( State state ) { Calls outgoing = T_info.callTrans(state); Calls incoming = T_info.entryTrans(state); //Remove the transitions. for( CallIterator rit = outgoing.begin(); rit != outgoing.end(); rit++ ) { removeCall(*rit); } //Remove the transitions. for( CallIterator rit = incoming.begin(); rit != incoming.end(); rit++ ) { removeCall(*rit); } return (outgoing.size() > 0) || (incoming.size() > 0); }
void StackIRGenerator::checkAndFixStack(VirtualContext& context, const VirtualFunction& function) { using namespace SBIL; using namespace ByteCode; typedef std::vector<Instruction*> Calls; Calls calls; Blocks& blocks = getBlocks(); // fill the stack for ( std::size_t index = 0; index < blocks.size(); ++index ) { if ( !hasBlock(index) ) continue; Block* pblock = blocks[index]; Instruction* pinst = pblock->pstart; while ( pinst != NULL ) { SBIL::Opcode opcode = (SBIL::Opcode) INST_OPCODE(pinst->inst); switch ( opcode ) { case SBIL_call: case SBIL_call_interface: case SBIL_call_virt: case SBIL_call_native: { int instarg = INST_ARG(pinst->inst); const FunctionSymbol& symbol = static_cast<const FunctionSymbol&>(context.mProgram.getSymbolTable()[instarg]); for ( int arg = 0; arg < symbol.args; ++arg ) calls.pop_back(); // push return value if ( symbol.returns ) calls.push_back(pinst); } break; case SBIL_ldelem: { int size = INST_ARG(pinst->inst); for ( int elem = 0; elem < size; ++elem ) calls.pop_back(); // pop (object) & push (value) } break; case SBIL_stelem: { int size = INST_ARG(pinst->inst) + 2; for ( int elem = 0; elem < size; ++elem ) calls.pop_back(); } break; case SBIL_stlocal: { if ( pinst == pblock->pstart && pblock->pguard != NULL && pblock->guard_type == VirtualGuard::sCatch ) { // special case, as it could be that this is the storage of an exception which // is push on the stack whenever the it is thrown. break; } // Fall through to execute the normal code for this instruction } default: { int pop = stackinfo[opcode].pop; for ( int i = 0; i < pop; ++i ) calls.pop_back(); if ( stackinfo[opcode].push == 1 ) calls.push_back(pinst); } } pinst = pinst->next; } } // now see what indices are still there that need an additional pop // skip the return value at the top of the stack std::size_t size = calls.size() - (function.getReturnType().isVoid() ? 0 : 1); for ( std::size_t index = 0; index < size; ++index ) { Instruction* inst = new Instruction; inst->inst = MAKE_INST(SBIL_pop,0); inst->next = calls[index]->next; calls[index]->next = inst; } }