/** 
     *
     * @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);
    }
    /** 
     *
     * @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;  
    }
示例#3
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;
   }
}