bool remove_virtual_functionst::remove_virtual_functions(
  goto_programt &goto_program)
{
  bool did_something=false;

  Forall_goto_program_instructions(target, goto_program)
    if(target->is_function_call())
    {
      const code_function_callt &code=
        to_code_function_call(target->code);

      if(code.function().id()==ID_virtual_function)
      {
        remove_virtual_function(goto_program, target);
        did_something=true;
      }
    }

  if(did_something)
  {
    goto_program.update();
  }

  return did_something;
}
예제 #2
0
void string_instrumentationt::do_function_call(
  goto_programt &dest,
  goto_programt::targett target)
{
  code_function_callt &call=
    to_code_function_call(target->code);
  exprt &function=call.function();
  //const exprt &lhs=call.lhs();
  
  if(function.id()=="symbol")
  {
    const irep_idt &identifier=
      to_symbol_expr(function).get_identifier();

    if(identifier=="c::strcoll")
    {
    }
    else if(identifier=="c::strncmp")
      do_strncmp(dest, target, call);
    else if(identifier=="c::strxfrm")
    {
    }
    else if(identifier=="c::strchr")
      do_strchr(dest, target, call);
    else if(identifier=="c::strcspn")
    {
    }
    else if(identifier=="c::strpbrk")
    {
    }
    else if(identifier=="c::strrchr")
      do_strrchr(dest, target, call);
    else if(identifier=="c::strspn")
    {
    }
    else if(identifier=="c::strerror")
      do_strerror(dest, target, call);
    else if(identifier=="c::strstr")
      do_strstr(dest, target, call);
    else if(identifier=="c::strtok")
      do_strtok(dest, target, call);
    else if(identifier=="c::sprintf")
      do_sprintf(dest, target, call);
    else if(identifier=="c::snprintf")
      do_snprintf(dest, target, call);
    else if(identifier=="c::fscanf")
      do_fscanf(dest, target, call);
    
    dest.update();
  }
}
예제 #3
0
void loop_transformt::transform(goto_programt &goto_program)
{
  goto_program.compute_incoming_edges();

  // pass 1: simple stuff
  Forall_goto_program_instructions(it, goto_program)
    if(it->is_backwards_goto())
    {
      assert(it->targets.size()==1);

      goto_programt::targett begin = it->targets.front();
      goto_programt::targett end = it;

      split_multi_head(goto_program, begin, end);
      transform_do_while(goto_program, begin, end);
      move_returns(goto_program, begin, end);
    }

  // pass 2: loop simulation
  Forall_goto_program_instructions(it, goto_program)
    if(it->is_backwards_goto())
    {
      goto_programt::targett begin = it->targets.front();
      goto_programt::targett end = it;

      std::set<goto_programt::targett> entries;
      std::set<goto_programt::targett> exits;

      analyze(goto_program, begin, end, entries, exits);
      transform(goto_program, begin, end, entries, exits);

      it=end;
    }

  goto_program.update();

  #if 1
  // Another run for debugging
  forall_goto_program_instructions(it, goto_program)
    if(it->is_backwards_goto())
    {
      goto_programt::const_targett begin = it->targets.front();
      goto_programt::const_targett end = it;

      run_checks(goto_program, begin, end);
    }
  #endif
}
예제 #4
0
void loop_transformt::move_returns(
  goto_programt &program,
  goto_programt::targett begin,
  goto_programt::targett end)
{
  goto_programt::targett postend = end; postend++;

  std::list<goto_programt::targett> returns;

  for(goto_programt::targett it = begin;
      it!=end;
      it++)
  {
    if(it->is_return())
      returns.push_back(it);
  }

  if(returns.size()>0)
  {
    for(std::list<goto_programt::targett>::const_iterator it = returns.begin();
        it!=returns.end();
        it++)
    {

      goto_programt::targett newret = program.insert_before(postend);
      newret->swap(**it);
      newret->location_number = postend->location_number;      

      (*it)->make_goto(newret);
      // this creates far exits,
      // which will be fixed lateron
    }

    // fix the loop exit
    goto_programt::targett firstafter = end; firstafter++;
    goto_programt::targett loopexit = program.insert_before(firstafter);
    loopexit->make_goto(postend);
    
    program.update();
  }
}
예제 #5
0
void loop_transformt::transform_do_while(
  goto_programt &program,
  goto_programt::targett &begin,
  goto_programt::targett &end) const
{
  if(!end->guard.is_true())
  {
    #if 0
    std::cout << "TRANSFORM DO-WHILE" << std::endl;
    #endif

    goto_programt::targett next = end; next++;
    assert(next!=program.instructions.end());

    goto_programt::instructiont newguard;
    newguard.make_goto(next);
    newguard.guard = end->guard;
    newguard.guard.make_not();
    newguard.location = end->location;
    end->guard.make_true();

    unsigned ln = end->location_number; // doesn't get swapped
    program.insert_before_swap(end, newguard); // end now points to the new guard

    goto_programt::targett old_guard = end; old_guard++;
    end->location_number=ln;
    old_guard->location_number=ln;

    program.update();

    #if 0
    std::cout << "Transformed: " << std::endl;
    goto_programt::const_targett it = begin;
    for (;
         it!=end;
         it++)
      program.output_instruction(ns, "", std::cout, it);
    program.output_instruction(ns, "", std::cout, it);
    #endif
  }
}
예제 #6
0
void convert( const irept &irep, goto_programt &program )
{
  assert(irep.id()=="goto-program");

  program.instructions.clear();

  std::list< std::list<unsigned> > number_targets_list;

  // convert instructions back
  const irept::subt &subs = irep.get_sub();
  for (irept::subt::const_iterator it=subs.begin();
       it!=subs.end();
       it++)
  {
    program.instructions.push_back(goto_programt::instructiont());
    convert(*it, program.instructions.back());

    number_targets_list.push_back(std::list<unsigned>());
    const irept &targets=it->find(ID_targets);
    const irept::subt &tsubs=targets.get_sub();
    for (irept::subt::const_iterator tit=tsubs.begin();
         tit!=tsubs.end();
         tit++)
    {
      number_targets_list.back().push_back(
          unsafe_string2unsigned(tit->id_string()));
    }
  }

  program.compute_location_numbers();

  // resolve targets
  std::list< std::list<unsigned> >::iterator nit=
        number_targets_list.begin();
  for(goto_programt::instructionst::iterator lit=
        program.instructions.begin();
      lit!=program.instructions.end() && nit!=number_targets_list.end();
      lit++, nit++)
  {
    for (std::list<unsigned>::iterator tit=nit->begin();
         tit!=nit->end();
         tit++)
    {
      goto_programt::targett fit=program.instructions.begin();
      for(;fit!=program.instructions.end();fit++)
      {
        if (fit->location_number==*tit)
        {
          lit->targets.push_back(fit);
          break;
        }
      }

      if (fit==program.instructions.end())
      {
        std::cout << "Warning: could not resolve target link "
                  << "during irep->goto_program translation." << std::endl;
        throw 0;
      }
    }
  }

  program.update();
}
예제 #7
0
void loop_transformt::split_multi_head(
  goto_programt &program,
  goto_programt::targett begin,
  goto_programt::targett end)
{
  #if 0
  std::cout << "SPLIT MULTI-HEAD (" << begin->incoming_edges.size() <<
    ")" << std::endl;
  #endif

  unsigned dontmatter = 0;
  goto_programt::targett prev = begin; prev--;
  
  forall_incoming_edges(it, begin)  
  {
    if((*it)==prev) dontmatter++;
    else if((*it)==end) dontmatter++;
  }
  
  if(begin->incoming_edges.size() > dontmatter)
  {
    #if 0
    std::cout << "Splitting " << begin->incoming_edges.size() <<
      "-head" << std::endl;
    #endif

    goto_programt::targett newskip = program.insert_before(begin);

    newskip->make_skip();
    newskip->location_number = begin->location_number;
    newskip->function = begin->function;
    newskip->location = begin->location;

    // redirect gotos
    forall_incoming_edges(it, begin)    
    {
      const goto_programt::targett &from = *it;
      
      if(from!=prev && from!=end &&
         from->is_goto() &&
         from->targets.front()==begin) // gotos right before the loop
                                       // aren't necessarily jumping to begin
      {
        assert(from->targets.size()==1);
        
        from->targets.clear();
        from->targets.push_back(newskip);
      }
    }

    program.update();

    #if 0
    namespacet ns(context);
    std::cout << "Split loop: " << std::endl;
    goto_programt::const_targett it = newskip;
    for (;
         it!=end;
         it++)
      program.output_instruction(ns, "", std::cout, it);
    program.output_instruction(ns, "", std::cout, it);
    #endif

    assert(begin->incoming_edges.size()<=2);
  }
예제 #8
0
void convert(const xmlt &xml, goto_programt &goto_program)
{
  goto_program.clear();
  goto_programt::instructionst &instructions = goto_program.instructions;

  xmlt::elementst::const_iterator it = xml.elements.begin();
  for(; it != xml.elements.end(); it++)
  {
    goto_programt::targett inst = goto_program.add_instruction();
    inst->targets.clear();

    if(it->name=="goto")
    {
      inst->type = GOTO;
    }
    else if(it->name=="assume")
    {
      inst->type = ASSUME;
    }
    else if(it->name=="assert")
    {
      inst->type = ASSERT;
    }
    else if(it->name=="skip")
    {
      inst->type = SKIP;
    }
    else if(it->name=="end_function")
    {
      inst->type = END_FUNCTION;
    }
    else if(it->name=="location")
    {
      inst->type = LOCATION;
    }
    else if(it->name=="dead")
    {
      inst->type = DEAD;
    }
    else if(it->name=="atomic_begin")
    {
      inst->type = ATOMIC_BEGIN;
    }
    else if(it->name=="atomic_end")
    {
      inst->type = ATOMIC_END;
    }
    else if(it->name=="return")
    {
      inst->make_return();
    }
    else if(it->name=="instruction") // OTHER
    {
      inst->make_other();
    }
    else if(it->name=="assign")
    {
      inst->make_other();
      inst->type=ASSIGN;
    }
    else if(it->name=="functioncall")
    {
      inst->make_other();
      inst->type=FUNCTION_CALL;
    }
    else if(it->name=="thread_start")
    {
      inst->type = START_THREAD;
    }
    else if(it->name=="thread_end")
    {
      inst->type = END_THREAD;
    }
    else
    {
      std::cout << "Unknown instruction type encountered (" << it->name << ")";
      std::cout << std::endl;
      return;
    }

    xmlt::elementst::const_iterator eit = it->elements.begin();
    for(; eit != it->elements.end(); eit++)
    {
      if(eit->name=="location")
      {
        convert(*eit, inst->location);
      }
      else if(eit->name=="variables")
      {
      }
      else if(eit->name=="labels")
      {
        xmlt::elementst::const_iterator lit = eit->elements.begin();
        for(; lit != eit->elements.end(); lit++)
        {
          if(lit->name=="label")
          {
            std::string ls = lit->get_attribute("name");
            inst->labels.push_back(ls);
          }
          else
          {
            std::cout << "Unknown node in labels section." << std::endl;
            return;
          }
        }
      }
      else if(eit->name=="guard")
      {
        inst->guard.remove("value");
        convert(*eit, inst->guard);
      }
      else if(eit->name=="code")
      {
        convert(*eit, inst->code);
      }
      else if(eit->name=="targets")
      {
        // Don't do anything here, we'll need a second run for that
      }
      else if(eit->name=="comment")
      {
        inst->location.set("comment", eit->data);
      }
      else if(eit->name=="function")
      {
        inst->function = eit->data;
      }
    }
  }

  // assign line numbers
  goto_program.compute_location_numbers();

  // second run, for targets
  goto_programt::targett ins_it = instructions.begin();
  it = xml.elements.begin();
  for(; it != xml.elements.end() && ins_it!=instructions.end(); it++)
  {
    xmlt::elementst::const_iterator eit = it->elements.begin();
    for(; eit != it->elements.end(); eit++)
    {
      if(eit->name=="targets")
      {
        xmlt::elementst::const_iterator tit = eit->elements.begin();
        for(; tit != eit->elements.end(); tit++)
        {
          if(tit->name=="target")
          {
            goto_programt::targett tins =
              find_instruction(xml, instructions, tit->data);
            if(tins != instructions.end())
            {
              // Here we insert the iterators that somehow seem
              // to be strange afterwards (see line 87)
              ins_it->targets.push_back(tins);
            }
            else
            {
              std::cout << "Warning: instruction not found when "
              "resolving target links." << std::endl;
            }
          }
          else
          {
            std::cout << "Unknown node in targets section." << std::endl;
            return;
          }
        }
      }
    }
    ins_it++;
  }

  // resolve links
  goto_program.update();

  // std::cout << "TNI: " << goto_program.target_numbers.size() << std::endl;
}