Beispiel #1
0
bool state_projectiont::is_new(const statet &state, bool use_cache)
{
  // get the right map
  assert(!state.data().previous.is_null());
  
  state_listt &state_list=
    state_map[state.data().previous_PC];

  // first try syntactically
  
  for(state_listt::const_iterator
      it=state_list.begin();
      it!=state_list.end();
      it++)
    if(is_syntactically_equal(*it, state))
      return false; // not new
      
  // now try expensive comparison

  for(state_listt::const_iterator
      it=state_list.begin();
      it!=state_list.end();
      it++)
    if(is_equal(*it, state, use_cache))
    {
      // put into list anyways
      state_list.push_back(state);
      return false; // not new
    }

  // not found, it's new  
  state_list.push_back(state);
  
  return true;
}
Beispiel #2
0
bool path_searcht::drop_state(const statet &state) const
{
  // depth
  if(depth_limit!=-1 && state.get_depth()>depth_limit) return true;
  
  // context bound
  if(context_bound!=-1 && state.get_no_thread_interleavings()) return true;
  
  // unwinding limit -- loops
  if(unwind_limit!=-1 && state.get_instruction()->is_backwards_goto())
  {
    for(path_symex_statet::unwinding_mapt::const_iterator
        it=state.unwinding_map.begin();
        it!=state.unwinding_map.end();
        it++)
      if(it->second>unwind_limit)
        return true;
  }
  
  // unwinding limit -- recursion
  if(unwind_limit!=-1 && state.get_instruction()->is_function_call())
  {
    for(path_symex_statet::recursion_mapt::const_iterator
        it=state.recursion_map.begin();
        it!=state.recursion_map.end();
        it++)
      if(it->second>unwind_limit)
        return true;
  }
  
  return false;
}
Beispiel #3
0
void simulator_ctt::compute_goto_successors(
  const statet &state,
  queuet &queue)
{
  const instructiont &instruction=*state.data().threads.front().PC;
  unsigned count=0;

  // must have target
  assert(!instruction.targets.empty());

  formulat instantiated_guard=
    instantiate(state, 0, instruction.guard);

  formulat new_guard_taken;

  if(instantiated_guard.is_true())
    new_guard_taken=state.data().guard;
  else
  {
    new_guard_taken=formula_container.gen_and(
      instantiated_guard,
      state.data().guard);

    formulat new_guard_not_taken=formula_container.gen_and(
      formula_container.gen_not(instantiated_guard),
      state.data().guard);

    // do "guard is false" case

    statet new_state=state;
    new_state.data_w().threads.front().PC++;
    new_state.data_w().guard=new_guard_not_taken;
    new_state.data_w().taken=false;
    new_state.set_previous(state, 0);
    queue.add(new_state);

    count++;
  }

  for(program_formulat::formula_goto_programt::
        instructiont::targetst::const_iterator
      t_it=instruction.targets.begin();
      t_it!=instruction.targets.end();
      t_it++)
  {
    statet new_state=state;
    new_state.data_w().threads.front().PC=*t_it;
    new_state.data_w().guard=new_guard_taken;
    new_state.data_w().taken=true;
    new_state.set_previous(state, 0);
    queue.add(new_state);

    count++;
  }
  
  if(count>=2) path_counter+=count-1;
}
Beispiel #4
0
void path_searcht::do_show_vcc(
  statet &state,
  const namespacet &ns)
{
  // keep statistics
  number_of_VCCs++;
  
  const goto_programt::instructiont &instruction=
    *state.get_instruction();
    
  mstreamt &out=result();

  if(instruction.location.is_not_nil())
    out << instruction.location << "\n";
  
  if(instruction.location.get_comment()!="")
    out << instruction.location.get_comment() << "\n";
    
  unsigned count=1;
  
  std::vector<path_symex_step_reft> steps;
  state.history.build_history(steps);

  for(std::vector<path_symex_step_reft>::const_iterator
      s_it=steps.begin();
      s_it!=steps.end();
      s_it++)
  {      
    if((*s_it)->guard.is_not_nil())
    {
      std::string string_value=from_expr(ns, "", (*s_it)->guard);
      out << "{-" << count << "} " << string_value << "\n";
      count++;
    }

    if((*s_it)->ssa_rhs.is_not_nil())
    {
      equal_exprt equality((*s_it)->ssa_lhs, (*s_it)->ssa_rhs);
      std::string string_value=from_expr(ns, "", equality);
      out << "{-" << count << "} " << string_value << "\n";
      count++;
    }
  }

  out << "|--------------------------" << "\n";
  
  exprt assertion=state.read(instruction.guard);

  out << "{" << 1 << "} "
      << from_expr(ns, "", assertion) << "\n";

  if(!assertion.is_true())
    number_of_VCCs_after_simplification++;
  
  out << eom;
}
Beispiel #5
0
void simulatort::explore(
  const statet &state,
  queuet &queue)
{
  #ifdef DEBUG
  std::cout << "simulatort::explore1\n";
  #endif

  #if 0
  std::cout << "/////////////////////////////////////////////// "
            << "\n";

  for(unsigned thread=0; thread<program_formula.threads.size(); thread++)
  {
    std::cout << "Thread " << thread << " Location: ";
    if(state.data().PCs[thread]==
       program_formula.threads[thread].formula_goto_program.instructions.end())
      std::cout << "END" << std::endl;
    else
    {
      instructiont &instruction=*state.data().PCs[thread];
      std::cout << location_string(instruction.location) << std::endl;
    }
  }
  std::cout << std::endl;
  #endif

  // dump it if the guard is false
  if(state.data().guard.is_false())
    return;
    
  #ifdef DEBUG
  std::cout << "simulatort::explore2\n";
  #endif
  
  if(history.check_history(
    state, enable_qbf_cache, enable_small_history))
  {
    // we have seen it already
    #ifdef DEBUG
    std::cout << ">>>>>>>>>>>>>>>>>>>>>>>> SEEN ALREADY\n";
    #endif
    return;
  }
  
  #ifdef DEBUG
  std::cout << "simulatort::explore3\n";
  #endif
  
  compute_successor_states(state, true, queue);
  
  #ifdef DEBUG
  std::cout << "simulatort::explore4\n";
  #endif
}
Beispiel #6
0
void simulator_ctt::execute_assume(
  statet &state,
  const program_formulat::formula_goto_programt::instructiont &instruction)
{
  formulat condition=
    instantiate(state, 0, instruction.guard);
    
  if(condition.is_true()) return;

  // just add it to the guard
  state.data_w().guard=
    formula_container.gen_and(state.data_w().guard, condition);
}
Beispiel #7
0
void path_searcht::do_show_vcc(statet &state)
{
  // keep statistics
  number_of_VCCs++;

  const goto_programt::instructiont &instruction=
    *state.get_instruction();

  mstreamt &out=result();

  if(instruction.source_location.is_not_nil())
    out << instruction.source_location << '\n';

  if(instruction.source_location.get_comment()!="")
    out << instruction.source_location.get_comment() << '\n';

  unsigned count=1;

  std::vector<path_symex_step_reft> steps;
  state.history.build_history(steps);

  for(const auto &step_ref : steps)
  {
    if(step_ref->guard.is_not_nil())
    {
      std::string string_value=from_expr(ns, "", step_ref->guard);
      out << "{-" << count << "} " << string_value << '\n';
      count++;
    }

    if(step_ref->ssa_rhs.is_not_nil())
    {
      equal_exprt equality(step_ref->ssa_lhs, step_ref->ssa_rhs);
      std::string string_value=from_expr(ns, "", equality);
      out << "{-" << count << "} " << string_value << '\n';
      count++;
    }
  }

  out << "|--------------------------" << '\n';

  exprt assertion=state.read(instruction.guard);

  out << "{" << 1 << "} "
      << from_expr(ns, "", assertion) << '\n';

  if(!assertion.is_true())
    number_of_VCCs_after_simplification++;

  out << eom;
}
Beispiel #8
0
void goto_symext::symex_dead(statet &state)
{
    const goto_programt::instructiont &instruction=*state.source.pc;

    const codet &code=to_code(instruction.code);

    if(code.operands().size()!=1)
        throw "dead expects one operand";

    if(code.op0().id()!=ID_symbol)
        throw "dead expects symbol as first operand";

    // We increase the L2 renaming to make these non-deterministic.
    // We also prevent propagation of old values.

    ssa_exprt ssa(to_symbol_expr(code.op0()));
    state.rename(ssa, ns, goto_symex_statet::L1);

    // in case of pointers, put something into the value set
    if(ns.follow(code.op0().type()).id()==ID_pointer)
    {
        exprt failed=
            get_failed_symbol(to_symbol_expr(code.op0()), ns);

        exprt rhs;

        if(failed.is_not_nil())
        {
            address_of_exprt address_of_expr;
            address_of_expr.object()=failed;
            address_of_expr.type()=code.op0().type();
            rhs=address_of_expr;
        }
        else
            rhs=exprt(ID_invalid);

        state.rename(rhs, ns, goto_symex_statet::L1);
        state.value_set.assign(ssa, rhs, ns, true, false);
    }

    ssa_exprt ssa_lhs=to_ssa_expr(ssa);
    const irep_idt &l1_identifier=ssa_lhs.get_identifier();

    // prevent propagation
    state.propagation.remove(l1_identifier);

    // L2 renaming
    if(state.level2.current_names.find(l1_identifier)!=
            state.level2.current_names.end())
        state.level2.increase_counter(l1_identifier);
}
Beispiel #9
0
void goto_symext::operator()(
  statet &state,
  const goto_functionst &goto_functions,
  const goto_programt &goto_program)
{
  assert(!goto_program.instructions.empty());

  state.source=symex_targett::sourcet(goto_program);
  assert(!state.threads.empty());
  assert(!state.call_stack().empty());
  state.top().end_of_function=--goto_program.instructions.end();
  state.top().calling_location.pc=state.top().end_of_function;
  state.symex_target=&target;
  state.dirty=new dirtyt(goto_functions);

  assert(state.top().end_of_function->is_end_function());

  while(!state.call_stack().empty())
  {
    symex_step(goto_functions, state);

    // is there another thread to execute?
    if(state.call_stack().empty() &&
       state.source.thread_nr+1<state.threads.size())
    {
      unsigned t=state.source.thread_nr+1;
      // std::cout << "********* Now executing thread " << t << std::endl;
      state.switch_to_thread(t);
    }
  }

  delete state.dirty;
  state.dirty=0;
}
Beispiel #10
0
void goto_symext::vcc(
  const exprt &vcc_expr,
  const std::string &msg,
  statet &state)
{
  total_vccs++;

  exprt expr=vcc_expr;

  // we are willing to re-write some quantified expressions
  rewrite_quantifiers(expr, state);

  // now rename, enables propagation
  state.rename(expr, ns);

  // now try simplifier on it
  do_simplify(expr);

  if(expr.is_true())
    return;

  state.guard.guard_expr(expr);

  remaining_vccs++;
  target.assertion(state.guard.as_expr(), expr, msg, state.source);
}
Beispiel #11
0
void path_searcht::check_assertion(
  statet &state,
  const namespacet &ns)
{
  // keep statistics
  number_of_VCCs++;
  
  const goto_programt::instructiont &instruction=
    *state.get_instruction();

  irep_idt property_name=instruction.location.get_property_id();
  property_entryt &property_entry=property_map[property_name];
  
  if(property_entry.status==FAIL)
    return; // already failed
  else if(property_entry.status==NOT_REACHED)
    property_entry.status=PASS; // well, for now!

  // the assertion in SSA
  exprt assertion=
    state.read(instruction.guard);

  if(assertion.is_true()) return; // no error, trivially

  // keep statistics
  number_of_VCCs_after_simplification++;
  
  status() << "Checking property " << property_name << eom;

  // take the time
  absolute_timet sat_start_time=current_time();

  satcheckt satcheck;
  bv_pointerst bv_pointers(ns, satcheck);
  
  satcheck.set_message_handler(get_message_handler());
  bv_pointers.set_message_handler(get_message_handler());

  if(!state.check_assertion(bv_pointers))
  {
    build_goto_trace(state, bv_pointers, property_entry.error_trace);
    property_entry.status=FAIL;
    number_of_failed_properties++;
  }
  
  sat_time+=current_time()-sat_start_time;
}
Beispiel #12
0
void goto_symext::dereference(
  exprt &expr,
  statet &state,
  const bool write)
{
  // The expression needs to be renamed to level 1
  // in order to distinguish addresses of local variables
  // from different frames. Would be enough to rename
  // symbols whose address is taken.
  assert(!state.call_stack().empty());
  state.rename(expr, ns, goto_symex_statet::L1);

  // start the recursion!
  guardt guard;
  dereference_rec(expr, state, guard, write);
  // dereferencing may introduce new symbol_exprt
  // (like __CPROVER_memory)
  state.rename(expr, ns, goto_symex_statet::L1);
}
void shared_accesst::rw_sets(
				statet& state,
				std::vector<bool>& is_shared,
				std::vector<sharedt::sett>& reads, 
				std::vector<sharedt::sett>& writes)
{
  
  unsigned nr_threads=state.threads.size();
  
  reads.clear();
  reads.resize(nr_threads);

  writes.clear();
  writes.resize(nr_threads);

  is_shared.clear();
  is_shared.resize(nr_threads, false);

  if(state.atomic_section_count)
  {
    return;
  }

  sharedt shared(state);

  unsigned current_thread=state.get_current_thread();

  for(unsigned 
      thr=0;
      thr<nr_threads;
      ++thr)
  {		
    if(state.threads[thr].active)
    {
      state.set_current_thread(thr);
      shared(reads[thr], writes[thr]);
      is_shared[thr]=!(reads[thr].empty() && writes[thr].empty());
    }                     
  }
  
  state.set_current_thread(current_thread);
}
Beispiel #14
0
bool state_projectiont::is_syntactically_equal(
  const statet &old_state,
  const statet &new_state)
{
  if(old_state.data().guard!=new_state.data().guard)
    return false;
  
  unsigned v=0;
  
  for(program_formulat::variablest::const_iterator
      it=program_formula.variables.begin();
      it!=program_formula.variables.end();
      it++, v++)
  {
    if(it->is_global)
    {
      assert(v<old_state.data().globals.size());
      assert(v<new_state.data().globals.size());

      if(old_state.data().globals[v]!=
         new_state.data().globals[v])
        return false;
    }
  }
  
  return true;  
}
Beispiel #15
0
void simulator_ctt::execute_assert(
  statet &state,
  const program_formulat::formula_goto_programt::instructiont &instruction)
{
  std::cout << "CHECKING ASSERTION\n";

  formulat condition=
    instantiate(state, 0, instruction.guard);
    
  formulat property=
    formula_container.gen_and(
      state.data().guard,
      formula_container.gen_not(condition));

  // see if it is reachable
  if(!property.is_false() &&
     is_satisfiable(property))
  {
    tracet trace;

    compute_trace(state, trace, true);
    dump_trace(trace, instruction);
    std::cout << "Assertion violated" << std::endl;
    std::cout << std::endl;

    error_state_found=true;
  }
  
  #if 0
  else
  {
    // otherwise, treat this like an assumption
    state.data_w().guard=
      formula_container.gen_and(state.data().guard, condition);
  }
  #endif
}
Beispiel #16
0
void simulator_ctt::execute_assign(
  statet &state,
  const program_formulat::formula_goto_programt::instructiont &instruction)
{
  statet new_state(state);
  
  new_state.detatch();

  for(program_formulat::assignst::const_iterator
      it=instruction.code.assigns.begin();
      it!=instruction.code.assigns.end();
      it++)
    if(it->in_use)
    {
      assert(it->variable<program_formula.variables.size());

      new_state.data_w().set_var(
        it->variable,
        0,
        instantiate(state, 0, it->value));
    }
  
  // do constraint
  formulat instantiated_constraint=
    instantiate(
      state,
      new_state,
      0,
      instruction.code.constraint);

  new_state.data_w().guard=
    formula_container.gen_and(
      state.data_w().guard,
      instantiated_constraint);
  
  state.swap(new_state);
}
Beispiel #17
0
/// decide whether to drop a state
bool path_searcht::drop_state(const statet &state)
{
  goto_programt::const_targett pc=state.get_instruction();

  // depth limit
  if(depth_limit_set && state.get_depth()>depth_limit)
    return true;

  // context bound
  if(context_bound_set && state.get_no_thread_interleavings()>context_bound)
    return true;

  // branch bound
  if(branch_bound_set && state.get_no_branches()>branch_bound)
    return true;

  // unwinding limit -- loops
  if(unwind_limit_set && state.get_instruction()->is_backwards_goto())
  {
    for(const auto &loop_info : state.unwinding_map)
      if(loop_info.second>unwind_limit)
        return true;
  }

  // unwinding limit -- recursion
  if(unwind_limit_set && state.get_instruction()->is_function_call())
  {
    for(const auto &rec_info : state.recursion_map)
      if(rec_info.second>unwind_limit)
        return true;
  }

  if(pc->is_assume() &&
     simplify_expr(pc->guard, ns).is_false())
  {
    debug() << "aborting path on assume(false) at "
            << pc->source_location
            << " thread " << state.get_current_thread();

    const irep_idt &c=pc->source_location.get_comment();
    if(!c.empty())
      debug() << ": " << c;

    debug() << eom;

    return true;
  }

  return false;
}
Beispiel #18
0
bool path_searcht::is_feasible(statet &state)
{
  status() << "Feasibility check" << eom;

  // take the time
  absolute_timet sat_start_time=current_time();

  satcheckt satcheck;
  bv_pointerst bv_pointers(ns, satcheck);
  
  satcheck.set_message_handler(get_message_handler());
  bv_pointers.set_message_handler(get_message_handler());

  bool result=state.is_feasible(bv_pointers);
  
  sat_time+=current_time()-sat_start_time;
  
  return result;
}
Beispiel #19
0
void simulator_ctt::execute_functioncall(
  const statet &state,
  edget &edge)
{
  const program_formulat::formula_goto_programt::instructiont
    &instruction=*state.data().threads.front().PC;
  const irep_idt &function_id=instruction.code.function;
  
  // find in program formula
  program_formulat::function_mapt::const_iterator
    f_it=program_formula.function_map.find(function_id);

  assert(f_it!=program_formula.function_map.end());
  
  const program_formulat::functiont &f=f_it->second;

  // produce a start state
  
  statet start_state(state);
  statet::threadt &thread=start_state.data_w().threads.back();
  
  // adjust PC
  thread.program=&(f.body);
  thread.PC=thread.start_pc();
  
  // assign args
  assert(instruction.code.function_args.size()==f.args.size());
  
  for(unsigned i=0; i<f.args.size(); i++)
  {
    formulat formula=instruction.code.function_args[i];
    formula=instantiate(state, 0, formula);
    start_state.data_w().set_var(f.args[i], 0, formula);
  }

  std::cout << "Adding edge for " << function_id << std::endl;
  
  // add edge
  edget &f_edge=new_edge(function_id, start_state);
  
  f_edge.calls.push_back(conft(edge, state));
}
Beispiel #20
0
void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
{
  // We increase the L2 renaming to make these non-deterministic.
  // We also prevent propagation of old values.

  ssa_exprt ssa(expr);
  state.rename(ssa, ns, goto_symex_statet::L1);
  const irep_idt &l1_identifier=ssa.get_identifier();

  // rename type to L2
  state.rename(ssa.type(), l1_identifier, ns);
  ssa.update_type();

  // in case of pointers, put something into the value set
  if(ns.follow(expr.type()).id()==ID_pointer)
  {
    exprt failed=
      get_failed_symbol(expr, ns);

    exprt rhs;

    if(failed.is_not_nil())
    {
      address_of_exprt address_of_expr;
      address_of_expr.object()=failed;
      address_of_expr.type()=expr.type();
      rhs=address_of_expr;
    }
    else
      rhs=exprt(ID_invalid);

    state.rename(rhs, ns, goto_symex_statet::L1);
    state.value_set.assign(ssa, rhs, ns, true, false);
  }

  // prevent propagation
  state.propagation.remove(l1_identifier);

  // L2 renaming
  // inlining may yield multiple declarations of the same identifier
  // within the same L1 context
  if(state.level2.current_names.find(l1_identifier)==
     state.level2.current_names.end())
    state.level2.current_names[l1_identifier]=std::make_pair(ssa, 0);
  state.level2.increase_counter(l1_identifier);
  const bool record_events=state.record_events;
  state.record_events=false;
  state.rename(ssa, ns);
  state.record_events=record_events;

  // we hide the declaration of auxiliary variables
  // and if the statement itself is hidden
  bool hidden=
    ns.lookup(expr.get_identifier()).is_auxiliary ||
    state.top().hidden_function ||
    state.source.pc->source_location.get_hide();

  target.decl(
    state.guard.as_expr(),
    ssa,
    state.source,
    hidden?symex_targett::HIDDEN:symex_targett::STATE);

  assert(state.dirty);
  if((*state.dirty)(ssa.get_object_name()) &&
     state.atomic_section_id==0)
    target.shared_write(
      state.guard.as_expr(),
      ssa,
      state.atomic_section_id,
      state.source);
}
Beispiel #21
0
void goto_symext::symex_step(
  const goto_functionst &goto_functions,
  statet &state)
{
  #if 0
  std::cout << "\ninstruction type is " << state.source.pc->type << '\n';
  std::cout << "Location: " << state.source.pc->source_location << '\n';
  std::cout << "Guard: " << from_expr(ns, "", state.guard.as_expr()) << '\n';
  std::cout << "Code: " << from_expr(ns, "", state.source.pc->code) << '\n';
  #endif

  assert(!state.threads.empty());
  assert(!state.call_stack().empty());

  const goto_programt::instructiont &instruction=*state.source.pc;

  merge_gotos(state);

  // depth exceeded?
  {
    unsigned max_depth=options.get_unsigned_int_option("depth");
    if(max_depth!=0 && state.depth>max_depth)
      state.guard.add(false_exprt());
    state.depth++;
  }

  // actually do instruction
  switch(instruction.type)
  {
  case SKIP:
    if(!state.guard.is_false())
      target.location(state.guard.as_expr(), state.source);
    state.source.pc++;
    break;

  case END_FUNCTION:
    // do even if state.guard.is_false() to clear out frame created
    // in symex_start_thread
    symex_end_of_function(state);
    state.source.pc++;
    break;

  case LOCATION:
    if(!state.guard.is_false())
      target.location(state.guard.as_expr(), state.source);
    state.source.pc++;
    break;

  case GOTO:
    symex_goto(state);
    break;

  case ASSUME:
    if(!state.guard.is_false())
    {
      exprt tmp=instruction.guard;
      clean_expr(tmp, state, false);
      state.rename(tmp, ns);
      symex_assume(state, tmp);
    }

    state.source.pc++;
    break;

  case ASSERT:
    if(!state.guard.is_false())
    {
      std::string msg=id2string(state.source.pc->source_location.get_comment());
      if(msg=="")
        msg="assertion";
      exprt tmp(instruction.guard);
      clean_expr(tmp, state, false);
      vcc(tmp, msg, state);
    }

    state.source.pc++;
    break;

  case RETURN:
    if(!state.guard.is_false())
      return_assignment(state);

    state.source.pc++;
    break;

  case ASSIGN:
    if(!state.guard.is_false())
      symex_assign_rec(state, to_code_assign(instruction.code));

    state.source.pc++;
    break;

  case FUNCTION_CALL:
    if(!state.guard.is_false())
    {
      code_function_callt deref_code=
        to_code_function_call(instruction.code);

      if(deref_code.lhs().is_not_nil())
        clean_expr(deref_code.lhs(), state, true);

      clean_expr(deref_code.function(), state, false);

      Forall_expr(it, deref_code.arguments())
        clean_expr(*it, state, false);

      symex_function_call(goto_functions, state, deref_code);
    }
    else
      state.source.pc++;
    break;

  case OTHER:
    if(!state.guard.is_false())
      symex_other(goto_functions, state);

    state.source.pc++;
    break;

  case DECL:
    if(!state.guard.is_false())
      symex_decl(state);

    state.source.pc++;
    break;

  case DEAD:
    symex_dead(state);
    state.source.pc++;
    break;

  case START_THREAD:
    symex_start_thread(state);
    state.source.pc++;
    break;

  case END_THREAD:
    // behaves like assume(0);
    if(!state.guard.is_false())
      state.guard.add(false_exprt());
    state.source.pc++;
    break;

  case ATOMIC_BEGIN:
    symex_atomic_begin(state);
    state.source.pc++;
    break;

  case ATOMIC_END:
    symex_atomic_end(state);
    state.source.pc++;
    break;

  case CATCH:
    symex_catch(state);
    state.source.pc++;
    break;

  case THROW:
    symex_throw(state);
    state.source.pc++;
    break;

  case NO_INSTRUCTION_TYPE:
    throw "symex got NO_INSTRUCTION";

  default:
    throw "symex got unexpected instruction";
  }
}
Beispiel #22
0
bool match(
  formula_containert &container,
  const statet &state,
  const std::map<vart, bool> &values)
{
  // do the reset
  container.reset_prop();

  // build the SAT instance
  satcheckt satcheck;

  // 1st, the guard must hold
  {
    literalt l=state.data().guard.convert(satcheck);
    satcheck.l_set_to(l, true);
  }

  #if 0
  std::cout << "G: ";
  state.data().guard.output(std::cout);
  std::cout << std::endl;
  #endif
  
  // 2nd, the values must match
  for(std::map<vart, bool>::const_iterator
      it=values.begin();
      it!=values.end();
      it++)
  {
    const vart &var=it->first;
    formulat f=state.data().get_var(var.var_nr, var.thread_nr);
    literalt l=f.convert(satcheck);
    satcheck.l_set_to(l, it->second);
    
    #if 0
    std::cout << "V: ";
    state.data().values[v].output(std::cout);
    std::cout << std::endl;
    #endif
  }
  
  std::cout << "Running " << satcheck.solver_text() << ", "
            << satcheck.no_variables() << " variables, "
            << satcheck.no_clauses() << " clauses" << std::endl;

  switch(satcheck.prop_solve())
  {
  case propt::P_SATISFIABLE:
    // oh! match!
    return true;
    
  case propt::P_UNSATISFIABLE:
    // nah, no match
    return false;
    
  default:;
    assert(false);
  }

  assert(false);
  return false;
}
void goto_symext::symex_decl(statet &state)
{
  const goto_programt::instructiont &instruction=*state.source.pc;

  const codet &code=to_code(instruction.code);

  if(code.operands().size()==2)
    throw "two-operand decl not supported here";

  if(code.operands().size()!=1)
    throw "decl expects one operand";
  
  if(code.op0().id()!=ID_symbol)
    throw "decl expects symbol as first operand";

  // We increase the L2 renaming to make these non-deterministic.
  // We also prevent propagation of old values.
  
  const irep_idt &identifier=
    to_symbol_expr(code.op0()).get_identifier();
    
  const irep_idt l1_identifier=
    state.rename(identifier, ns, goto_symex_statet::L1);
    
  // prevent propagation
  state.propagation.remove(l1_identifier);

  // L2 renaming
  unsigned new_count=state.level2.current_count(l1_identifier)+1;
  state.level2.rename(l1_identifier, new_count);
    
  // in case of pointers, put something into the value set
  if(ns.follow(code.op0().type()).id()==ID_pointer)
  {
    exprt failed=
      get_failed_symbol(to_symbol_expr(code.op0()), ns);
    
    exprt rhs;
    
    if(failed.is_not_nil())
    {
      address_of_exprt address_of_expr;
      address_of_expr.object()=failed;
      address_of_expr.type()=code.op0().type();
      rhs=address_of_expr;
    }
    else
      rhs=exprt(ID_invalid);
    
    symbol_exprt l1_lhs;
    l1_lhs.type()=code.op0().type();
    l1_lhs.set_identifier(l1_identifier);
    state.rename(rhs, ns, goto_symex_statet::L1);
    state.value_set.assign(l1_lhs, rhs, ns);
  }
  
  // record the declaration
  symbol_exprt original_lhs=to_symbol_expr(code.op0());
  symbol_exprt ssa_lhs=original_lhs;
  state.rename(ssa_lhs, ns);
  
  target.decl(
    state.guard,
    ssa_lhs, original_lhs,
    state.source);
}
Beispiel #24
0
void simulator_ctt::execute_instruction(
  statet &state,
  const program_formulat::formula_goto_programt::instructiont &instruction)
{
  switch(instruction.type)
  {
  case GOTO:
    assert(false);
    // done somewhere else
    break;

  case ASSUME:
    execute_assume(state, instruction);
    break;

  case ASSERT:
    execute_assert(state, instruction);
    break;

  case ASSIGN:
    execute_assign(state, instruction);
    break;
    
  case FUNCTION_CALL:
    assert(false); // done somewhere else
    break;

  case OTHER:
    assert(false);
    break;

  case SKIP:
  case LOCATION:
  case END_FUNCTION:
    // do nothing
    break;
    
  case START_THREAD:
    throw "start_thread is not supported";
    break;
    
  case END_THREAD:
    assert(false);
    break;
    
  case ATOMIC_BEGIN:
    state.data_w().in_atomic_section=true;
    break;
    
  case ATOMIC_END:
    state.data_w().in_atomic_section=false;
    break;
    
  case DEAD:
    break;
    
  case RETURN:
    assert(false); // done somewhere else
    break;
    
  default:
    std::cerr << instruction.type << std::endl;
    assert(false);  
  }
}
Beispiel #25
0
void simulator_ctt::execute_return(const statet &state, edget &edge)
{
  // compute vector of return values
  std::vector<formulat> return_values;
  
  bool have_return=!state.data().threads.front().is_at_end();

  if(have_return)
  {
    const program_formulat::formula_goto_programt::instructiont
      &return_instruction=*state.data().threads.front().PC;
    
    return_values.resize(return_instruction.code.assigns.size());

    for(unsigned i=0; i<return_values.size(); i++)
    {
      formulat f1=return_instruction.code.assigns[i].value;
      formulat f2=instantiate(state, 0, f1);
      return_values[i]=f2;
    }
  }

  // propagate to all call sites
  for(callst::const_iterator it=edge.calls.begin();
      it!=edge.calls.end();
      it++)
  {
    const conft &conf=*it;

    // save PC
    const_targett PC=conf.state.data().threads.front().PC;

    const program_formulat::formula_goto_programt::instructiont
      &call_instruction=*PC;

    // get return PC
    PC++;

    statet new_state=state;
    
    // set PC to return location
    new_state.data_w().threads.front().PC=PC;
    new_state.data_w().threads.front().program=
      conf.state.data().threads.front().program;

    if(!call_instruction.code.function_lhs.empty())
    {
      if(have_return)
      {
        assert(call_instruction.code.function_lhs.size()==
               return_values.size());
        
        // do return value
        for(unsigned i=0; i<return_values.size(); i++)
        {
          if(call_instruction.code.function_lhs[i].in_use)
          {
            unsigned lhs=call_instruction.code.function_lhs[i].variable;
            new_state.data_w().set_var(lhs, 0, return_values[i]);
          }
        }
      }
    }
    
    std::cout << "Adding to queue of " << conf.edge->function << std::endl;
    
    // put it into the right queue
    conf.edge->queue.add(new_state);
    
    // make sure this is noticed
    active_edges.insert(conf.edge);
  }
}