Example #1
0
void transition_refinert::constrain_goto_transition(
  abstract_transition_relationt &abstract_transition_relation,
  const exprt &condition,
  bool negated)
{
  if(abstract_transition_relation.constraints.size()==0)
  { 
    exprt schoose("bp_schoose", bool_typet());
    schoose.copy_to_operands(false_exprt(), false_exprt());
    abstract_transition_relation.constraints.push_back(schoose);
  }

  // we are only maintaining ONE constraint here
  assert(abstract_transition_relation.constraints.size()==1);

  exprt &schoose=
    abstract_transition_relation.constraints.front();

  exprt &constraint=negated?(schoose.op1()):(schoose.op0()); 
  
  if(constraint.is_false())
  {
    constraint.id(ID_or);
    constraint.copy_to_operands(false_exprt());
  }

  constraint.copy_to_operands(condition);
}
Example #2
0
void summarizer_fw_termt::do_nontermination(
  const function_namet &function_name,
  local_SSAt &SSA,
  summaryt &summary)
{
  // calling context, invariant, function call summaries
  exprt::operandst cond;
  if(!summary.fw_invariant.is_nil())
    cond.push_back(summary.fw_invariant);
  if(!summary.fw_precondition.is_nil())
    cond.push_back(summary.fw_precondition);
  cond.push_back(ssa_inliner.get_summaries(SSA));

  if(!check_end_reachable(function_name, SSA, conjunction(cond)))
  {
    status() << "Function never terminates normally" << eom;

    if(summary.fw_precondition.is_true())
      summary.fw_transformer=false_exprt();
    else
      summary.fw_transformer=
        implies_exprt(summary.fw_precondition, false_exprt());

    summary.terminates=NO;
  }
}
Example #3
0
bool sat_path_enumeratort::next(patht &path)
{
  scratch_programt program(symbol_table);

  program.append(fixed);
  program.append(fixed);

  // Let's make sure that we get a path we have not seen before.
  for(std::list<distinguish_valuest>::iterator it=accelerated_paths.begin();
      it!=accelerated_paths.end();
      ++it)
  {
    exprt new_path=false_exprt();

    for(distinguish_valuest::iterator jt=it->begin();
        jt!=it->end();
        ++jt)
    {
      exprt distinguisher=jt->first;
      bool taken=jt->second;

      if(taken)
      {
        not_exprt negated(distinguisher);
        distinguisher.swap(negated);
      }

      or_exprt disjunct(new_path, distinguisher);
      new_path.swap(disjunct);
    }

    program.assume(new_path);
  }

  program.add_instruction(ASSERT)->guard=false_exprt();

  try
  {
    if(program.check_sat())
    {
#ifdef DEBUG
      std::cout << "Found a path" << std::endl;
#endif
      build_path(program, path);
      record_path(program);

      return true;
    }
  }
  catch(std::string s)
  {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  }
  catch(const char *s)
  {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  }

  return false;
}
Example #4
0
exprt interval_domaint::make_expression(const symbol_exprt &src) const
{
  if(is_int(src.type()))
  {
    int_mapt::const_iterator i_it=int_map.find(src.get_identifier());
    if(i_it==int_map.end()) return true_exprt();
    const integer_intervalt &interval=i_it->second;
    if(interval.is_top()) return true_exprt();
    if(interval.is_bottom()) return false_exprt();

    exprt::operandst conjuncts;

    if(interval.upper_set) 
    {
      exprt tmp=from_integer(interval.upper, src.type());
      conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp));
    }

    if(interval.lower_set) 
    {
      exprt tmp=from_integer(interval.lower, src.type());
      conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src));
    }
  
    return conjunction(conjuncts);
  }
  else if(is_float(src.type()))
  {
    float_mapt::const_iterator i_it=float_map.find(src.get_identifier());
    if(i_it==float_map.end()) return true_exprt();
    const ieee_float_intervalt &interval=i_it->second;
    if(interval.is_top()) return true_exprt();
    if(interval.is_bottom()) return false_exprt();

    exprt::operandst conjuncts;

    if(interval.upper_set) 
    {
      exprt tmp=interval.upper.to_expr();
      conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp));
    }

    if(interval.lower_set) 
    {
      exprt tmp=interval.lower.to_expr();
      conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src));
    }
  
    return conjunction(conjuncts);
  }
  else
    return true_exprt();
}
Example #5
0
const exprt qbf_squolem_coret::f_get(literalt l)
{
  if(squolem->isUniversal(l.var_no()))
  {
    assert(l.var_no()!=0);
    variable_mapt::const_iterator it=variable_map.find(l.var_no());

    if(it==variable_map.end())
      throw "Variable map error";

    const exprt &sym=it->second.first;
    unsigned index=it->second.second;

    exprt extract_expr(ID_extractbit, typet(ID_bool));
    extract_expr.copy_to_operands(sym);
    typet uint_type(ID_unsignedbv);
    uint_type.set(ID_width, 32);
    extract_expr.copy_to_operands(from_integer(index, uint_type));

    if(l.sign()) extract_expr.negate();

    return extract_expr;
  }

  function_cachet::const_iterator it=function_cache.find(l.var_no());
  if(it!=function_cache.end())
  {
    #if 0
    std::cout << "CACHE HIT for " << l.dimacs() << std::endl;
    #endif

    if(l.sign())
      return not_exprt(it->second);
    else
      return it->second;
  }
  else
  {
    WitnessStack *wsp = squolem->getModelFunction(Literal(l.dimacs()));
    exprt res;

    if(wsp==NULL || wsp->empty())
    {
//      res=exprt(ID_nondet_bool, typet(ID_bool));
      res=false_exprt(); // just set it to zero
    }
    else if(wsp->pSize<=wsp->nSize)
      res=f_get_cnf(wsp);
    else
      res=f_get_dnf(wsp);

    function_cache[l.var_no()] = res;

    if(l.sign())
      return not_exprt(res);
    else
      return res;
  }
}
Example #6
0
void predabs_domaint::initialize(valuet &value)
{
  templ_valuet &v=static_cast<templ_valuet&>(value);
  v.resize(templ.size());
  for(std::size_t row=0; row<templ.size(); ++row)
  {
    // start from top (we can only use a gfp solver for this domain)
    v[row]=false_exprt();
  }
}
Example #7
0
void goto_convertt::rewrite_boolean(exprt &expr)
{
  assert(expr.id()==ID_and || expr.id()==ID_or);
  
  if(!expr.is_boolean())
    throw "`"+expr.id_string()+"' "
          "must be Boolean, but got "+expr.pretty();

  // re-write "a && b" into nested a?b:0
  // re-write "a || b" into nested a?1:b

  exprt tmp;
  
  if(expr.id()==ID_and)
    tmp=true_exprt();
  else // ID_or
    tmp=false_exprt();
    
  exprt::operandst &ops=expr.operands();

  // start with last one
  for(int i=int(ops.size())-1; i>=0; i--)
  {
    exprt &op=ops[i];

    if(!op.is_boolean())
     throw "`"+expr.id_string()+"' takes Boolean "
           "operands only, but got "+op.pretty();

    if(expr.id()==ID_and)
    {
      if_exprt if_e(op, tmp, false_exprt());
      tmp.swap(if_e);
    }
    else // ID_or
    {
      if_exprt if_e(op, true_exprt(), tmp);
      tmp.swap(if_e);
    }
  }

  expr.swap(tmp);
}
Example #8
0
exprt ranking_synthesis_seneschalt::instantiate(void)
{
  exprt path = body.body_relation;

  if(!write_input_file(path))
    return nil_exprt();

  // make sure nothing is saved
  rank_relation = false_exprt();

  return true_exprt();
}
Example #9
0
void summarizer_bw_termt::do_nontermination(
  const function_namet &function_name,
  local_SSAt &SSA,
  const summaryt &old_summary,
  summaryt &summary)
{
  // calling context, invariant, function call summaries
  exprt::operandst cond;
  cond.push_back(old_summary.fw_invariant);
  cond.push_back(old_summary.fw_precondition);
  cond.push_back(ssa_inliner.get_summaries(SSA));
  ssa_inliner.get_summaries(SSA, false, cond, cond); // backward summaries

  if(!check_end_reachable(function_name, SSA, conjunction(cond)))
  {
    status() << "Function never terminates" << eom;
    summary.bw_transformer=false_exprt();
    summary.bw_precondition=false_exprt();
    summary.terminates=NO;
  }
}
Example #10
0
exprt disjunction(const exprt::operandst &op)
{
  if(op.empty())
    return false_exprt();
  else if(op.size()==1)
    return op.front();
  else
  {
    or_exprt result;
    result.operands()=op;
    return result;
  }
}
Example #11
0
/*******************************************************************\

Function: acdl_conflict_grapht::check_consistency

  Inputs:

 Outputs:

 Purpose:

\*******************************************************************/
void acdl_conflict_grapht::check_consistency()
{
#ifdef DEBUG
  std::cout << "Checking consistency of conflict graph" << std::endl;
#endif
  acdl_domaint::valuet val;
  for(unsigned i=0;i<prop_trail.size();i++) {
    // if there is a BOTTOM or false_exprt in the trail,
    // it should have been popped during backtracking
    assert(prop_trail[i]!=false_exprt());
  }
#ifdef DEBUG
  std::cout << "Conflict graph is consistent" << std::endl;
#endif
}
Example #12
0
void acceleratet::make_overflow_loc(
  goto_programt::targett loop_header,
  goto_programt::targett &loop_end,
  goto_programt::targett &overflow_loc)
{
  symbolt overflow_sym=utils.fresh_symbol("accelerate::overflow", bool_typet());
  const exprt &overflow_var=overflow_sym.symbol_expr();
  natural_loops_mutablet::natural_loopt &loop =
    natural_loops.loop_map[loop_header];
  overflow_instrumentert instrumenter(program, overflow_var, symbol_table);

  for(natural_loops_mutablet::natural_loopt::iterator it=loop.begin();
      it!=loop.end();
      ++it)
  {
    overflow_locs[*it]=goto_programt::targetst();
    goto_programt::targetst &added=overflow_locs[*it];

    instrumenter.add_overflow_checks(*it, added);
    loop.insert(added.begin(), added.end());
  }

  goto_programt::targett t=program.insert_after(loop_header);
  t->make_assignment();
  t->code=code_assignt(overflow_var, false_exprt());
  t->swap(*loop_header);
  loop.insert(t);
  overflow_locs[loop_header].push_back(t);

  goto_programt::instructiont s(SKIP);
  overflow_loc=program.insert_after(loop_end);
  *overflow_loc=s;
  overflow_loc->swap(*loop_end);
  loop.insert(overflow_loc);

  goto_programt::instructiont g(GOTO);
  g.guard=not_exprt(overflow_var);
  g.targets.push_back(overflow_loc);
  goto_programt::targett t2=program.insert_after(loop_end);
  *t2=g;
  t2->swap(*loop_end);
  overflow_locs[overflow_loc].push_back(t2);
  loop.insert(t2);

  goto_programt::targett tmp=overflow_loc;
  overflow_loc=loop_end;
  loop_end=tmp;
}
/// add axioms stating that the return value for two equal string should be the
/// same
/// \par parameters: function application with one string argument
/// \return a string expression
symbol_exprt string_constraint_generatort::add_axioms_for_intern(
  const function_application_exprt &f)
{
  string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]);
  const typet &return_type=f.type();
  typet index_type=str.length().type();

  // initialisation of the missing pool variable
  std::map<irep_idt, string_exprt>::iterator it;
  for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++)
    if(pool.find(it->second)==pool.end())
      pool[it->second]=fresh_symbol("pool", return_type);

  // intern(str)=s_0 || s_1 || ...
  // for each string s.
  //    intern(str)=intern(s) || |str|!=|s|
  //    || (|str|==|s| &&exists i<|s|. s[i]!=str[i])

  exprt disj=false_exprt();
  for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++)
    disj=or_exprt(
      disj, equal_exprt(pool[str], symbol_exprt(it->first, return_type)));

  axioms.push_back(disj);


  // WARNING: the specification may be incomplete or incorrect
  for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++)
    if(it->second!=str)
    {
      symbol_exprt i=fresh_exist_index("index_intern", index_type);
      axioms.push_back(
        or_exprt(
          equal_exprt(pool[it->second], pool[str]),
          or_exprt(
            not_exprt(str.axiom_for_has_same_length_as(it->second)),
            and_exprt(
              str.axiom_for_has_same_length_as(it->second),
              and_exprt(
                not_exprt(equal_exprt(str[i], it->second[i])),
                and_exprt(str.axiom_for_is_strictly_longer_than(i),
                          axiom_for_is_positive_index(i)))))));
    }

  return pool[str];
}
Example #14
0
void make_assertions_false(
  goto_functionst &goto_functions)
{
  for(goto_functionst::function_mapt::iterator
      f_it=goto_functions.function_map.begin();
      f_it!=goto_functions.function_map.end();
      f_it++)
  {
    goto_programt &goto_program=f_it->second.body;

    for(goto_programt::instructionst::iterator
        i_it=goto_program.instructions.begin();
        i_it!=goto_program.instructions.end();
        i_it++)
    {
      if(!i_it->is_assert()) continue;
      i_it->guard=false_exprt();
    }
  }
}
void string_instrumentationt::do_sprintf(
  goto_programt &dest,
  goto_programt::targett target,
  code_function_callt &call)
{
  const code_function_callt::argumentst &arguments=call.arguments();
    
  if(arguments.size()<2)
  {
    error().source_location=target->source_location;
    error() << "sprintf expected to have two or more arguments" << eom;
    throw 0;
  }
  
  goto_programt tmp;
  
  goto_programt::targett assertion=tmp.add_instruction();  
  assertion->source_location=target->source_location;
  assertion->source_location.set_property_class("string");  
  assertion->source_location.set_comment("sprintf buffer overflow");
  
  // in the abstract model, we have to report a 
  // (possibly false) positive here
  assertion->make_assertion(false_exprt());
  
  do_format_string_read(tmp, target, arguments, 1, 2, "sprintf");
  
  if(call.lhs().is_not_nil())
  {
    goto_programt::targett return_assignment=tmp.add_instruction(ASSIGN);
    return_assignment->source_location=target->source_location;
    
    exprt rhs=side_effect_expr_nondett(call.lhs().type());
    rhs.add_source_location()=target->source_location;
      
    return_assignment->code=code_assignt(call.lhs(), rhs);
  }
  
  target->make_skip();
  dest.insert_before_swap(target, tmp);
}
Example #16
0
const exprt qbf_squolem_coret::f_get_cnf(WitnessStack *wsp)
{
  Clause *p=wsp->negWits;

  if(!p) return exprt(ID_true, typet(ID_bool));

  exprt::operandst operands;

  while(p!=NULL)
  {
    exprt clause=or_exprt();

    for(unsigned i=0; i<p->size; i++)
    {
      const Literal &lit=p->literals[i];
      exprt subf = f_get(literalt(var(lit), isPositive(lit))); // negated!
      if(find(clause.operands().begin(), clause.operands().end(), subf)==
         clause.operands().end())
        clause.move_to_operands(subf);
    }

    if(clause.operands().empty())
      clause=false_exprt();
    else if(clause.operands().size()==1)
    {
      const exprt tmp=clause.op0();
      clause=tmp;
    }

    #if 0
    std::cout << "CLAUSE: " << clause << std::endl;
    #endif

    operands.push_back(clause);

    p=p->next;
  }

  return and_exprt(operands);
}
Example #17
0
exprt polynomial_acceleratort::precondition(patht &path) {
  exprt ret = false_exprt();

  for (patht::reverse_iterator r_it = path.rbegin();
       r_it != path.rend();
       ++r_it) {
    goto_programt::const_targett t = r_it->loc;

    if (t->is_assign()) {
      // XXX Need to check for aliasing...
      const code_assignt &assignment = to_code_assign(t->code);
      const exprt &lhs = assignment.lhs();
      const exprt &rhs = assignment.rhs();

      if (lhs.id() == ID_symbol) {
        replace_expr(lhs, rhs, ret);
      } else if (lhs.id() == ID_index ||
                 lhs.id() == ID_dereference) {
        continue;
      } else {
        throw "Couldn't take WP of " + expr2c(lhs, ns) + " = " + expr2c(rhs, ns);
      }
    } else if (t->is_assume() || t->is_assert()) {
      ret = implies_exprt(t->guard, ret);
    } else {
      // Ignore.
    }

    if (!r_it->guard.is_true() && !r_it->guard.is_nil()) {
      // The guard isn't constant true, so we need to accumulate that too.
      ret = implies_exprt(r_it->guard, ret);
    }
  }

  simplify(ret, ns);

  return ret;
}
Example #18
0
void goto_symext::replace_array_equal(exprt &expr)
{
  if(expr.id()==ID_array_equal)
  {
    assert(expr.operands().size()==2);
   
    // we expect two index expressions
    process_array_expr(expr.op0());
    process_array_expr(expr.op1());

    // type checking
    if(ns.follow(expr.op0().type())!=
       ns.follow(expr.op1().type()))
      expr=false_exprt();
    else
    {
      equal_exprt equality_expr(expr.op0(), expr.op1());
      expr.swap(equality_expr);
    }
  }

  Forall_operands(it, expr)
    replace_array_equal(*it);
}
Example #19
0
bool polynomial_acceleratort::fit_polynomial_sliced(goto_programt::instructionst &body,
                                                    exprt &var,
                                                    expr_sett &influence,
                                                    polynomialt &polynomial) {
  // These are the variables that var depends on with respect to the body.
  std::vector<expr_listt> parameters;
  std::set<std::pair<expr_listt, exprt> > coefficients;
  expr_listt exprs;
  scratch_programt program(symbol_table);
  exprt overflow_var =
    utils.fresh_symbol("polynomial::overflow", bool_typet()).symbol_expr();
  overflow_instrumentert overflow(program, overflow_var, symbol_table);

#ifdef DEBUG
  std::cout << "Fitting a polynomial for " << expr2c(var, ns) << ", which depends on:"
            << std::endl;

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    std::cout << expr2c(*it, ns) << std::endl;
  }
#endif

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    if (it->id() == ID_index ||
        it->id() == ID_dereference) {
      // Hack: don't accelerate variables that depend on arrays...
      return false;
    }

    exprs.clear();

    exprs.push_back(*it);
    parameters.push_back(exprs);

    exprs.push_back(loop_counter);
    parameters.push_back(exprs);
  }

  // N
  exprs.clear();
  exprs.push_back(loop_counter);
  parameters.push_back(exprs);

  // N^2
  exprs.push_back(loop_counter);
  //parameters.push_back(exprs);

  // Constant
  exprs.clear();
  parameters.push_back(exprs);

  if (!is_bitvector(var.type())) {
    // We don't really know how to accelerate non-bitvectors anyway...
    return false;
  }

  unsigned width=to_bitvector_type(var.type()).get_width();
  if(var.type().id()==ID_pointer)
    width=config.ansi_c.pointer_width;
  assert(width>0);

  for (std::vector<expr_listt>::iterator it = parameters.begin();
       it != parameters.end();
       ++it) {
    symbolt coeff = utils.fresh_symbol("polynomial::coeff",
        signedbv_typet(width));
    coefficients.insert(std::make_pair(*it, coeff.symbol_expr()));
  }

  // Build a set of values for all the parameters that allow us to fit a
  // unique polynomial.

  // XXX
  // This isn't ok -- we're assuming 0, 1 and 2 are valid values for the
  // variables involved, but this might make the path condition UNSAT.  Should
  // really be solving the path constraints a few times to get valid probe
  // values...

  std::map<exprt, int> values;

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    values[*it] = 0;
  }

#ifdef DEBUG
  std::cout << "Fitting polynomial over " << values.size() << " variables" << std::endl;
#endif

  for (int n = 0; n <= 2; n++) {
    for (expr_sett::iterator it = influence.begin();
         it != influence.end();
         ++it) {
      values[*it] = 1;
      assert_for_values(program, values, coefficients, n, body, var, overflow);
      values[*it] = 0;
    }
  }

  // Now just need to assert the case where all values are 0 and all are 2.
  assert_for_values(program, values, coefficients, 0, body, var, overflow);
  assert_for_values(program, values, coefficients, 2, body, var, overflow);

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    values[*it] = 2;
  }

  assert_for_values(program, values, coefficients, 2, body, var, overflow);

#ifdef DEBUG
  std::cout << "Fitting polynomial with program:" << std::endl;
  program.output(ns, "", std::cout);
#endif

  // Now do an ASSERT(false) to grab a counterexample
  goto_programt::targett assertion = program.add_instruction(ASSERT);
  assertion->guard = false_exprt();


  // If the path is satisfiable, we've fitted a polynomial.  Extract the
  // relevant coefficients and return the expression.
  try {
    if (program.check_sat()) {
      utils.extract_polynomial(program, coefficients, polynomial);
      return true;
    }
  } catch (std::string s) {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  } catch (const char *s) {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  }

  return false;
}
void remove_virtual_functionst::remove_virtual_function(
  goto_programt &goto_program,
  goto_programt::targett target)
{
  const code_function_callt &code=
    to_code_function_call(target->code);

  const auto &vcall_source_loc=target->source_location;

  const exprt &function=code.function();
  assert(function.id()==ID_virtual_function);
  assert(!code.arguments().empty());

  functionst functions;
  get_functions(function, functions);

  if(functions.empty())
  {
    target->make_skip();
    return; // give up
  }

  // only one option?
  if(functions.size()==1)
  {
    assert(target->is_function_call());
    if(functions.begin()->symbol_expr==symbol_exprt())
      target->make_skip();
    else
      to_code_function_call(target->code).function()=
        functions.begin()->symbol_expr;
    return;
  }

  // the final target is a skip
  goto_programt final_skip;

  goto_programt::targett t_final=final_skip.add_instruction();
  t_final->source_location=vcall_source_loc;

  t_final->make_skip();

  // build the calls and gotos

  goto_programt new_code_calls;
  goto_programt new_code_gotos;

  exprt this_expr=code.arguments()[0];
  // If necessary, cast to the last candidate function to
  // get the object's clsid. By the structure of get_functions,
  // this is the parent of all other classes under consideration.
  const auto &base_classid=functions.back().class_id;
  const auto &base_function_symbol=functions.back().symbol_expr;
  symbol_typet suggested_type(base_classid);
  exprt c_id2=get_class_identifier_field(this_expr, suggested_type, ns);

  std::map<irep_idt, goto_programt::targett> calls;
  // Note backwards iteration, to get the least-derived candidate first.
  for(auto it=functions.crbegin(), itend=functions.crend(); it!=itend; ++it)
  {
    const auto &fun=*it;
    auto insertit=calls.insert(
      {fun.symbol_expr.get_identifier(), goto_programt::targett()});

    // Only create one call sequence per possible target:
    if(insertit.second)
    {
      goto_programt::targett t1=new_code_calls.add_instruction();
      t1->source_location=vcall_source_loc;
      if(!fun.symbol_expr.get_identifier().empty())
      {
      // call function
        t1->make_function_call(code);
        auto &newcall=to_code_function_call(t1->code);
        newcall.function()=fun.symbol_expr;
        pointer_typet need_type(symbol_typet(fun.symbol_expr.get(ID_C_class)));
        if(!type_eq(newcall.arguments()[0].type(), need_type, ns))
          newcall.arguments()[0].make_typecast(need_type);
      }
      else
      {
        // No definition for this type; shouldn't be possible...
        t1->make_assertion(false_exprt());
      }
      insertit.first->second=t1;
      // goto final
      goto_programt::targett t3=new_code_calls.add_instruction();
      t3->source_location=vcall_source_loc;
      t3->make_goto(t_final, true_exprt());
    }

    // If this calls the base function we just fall through.
    // Otherwise branch to the right call:
    if(fun.symbol_expr!=base_function_symbol)
    {
      exprt c_id1=constant_exprt(fun.class_id, string_typet());
      goto_programt::targett t4=new_code_gotos.add_instruction();
      t4->source_location=vcall_source_loc;
      t4->make_goto(insertit.first->second, equal_exprt(c_id1, c_id2));
    }
  }

  goto_programt new_code;

  // patch them all together
  new_code.destructive_append(new_code_gotos);
  new_code.destructive_append(new_code_calls);
  new_code.destructive_append(final_skip);

  // set locations
  Forall_goto_program_instructions(it, new_code)
  {
    const irep_idt property_class=it->source_location.get_property_class();
    const irep_idt comment=it->source_location.get_comment();
    it->source_location=target->source_location;
    it->function=target->function;
    if(!property_class.empty())
      it->source_location.set_property_class(property_class);
    if(!comment.empty())
      it->source_location.set_comment(comment);
  }

  goto_programt::targett next_target=target;
  next_target++;

  goto_program.destructive_insert(next_target, new_code);

  // finally, kill original invocation
  target->make_skip();
}
Example #21
0
exprt ranking_synthesis_qbf_bitwiset::instantiate_nothing(void)
{
  return false_exprt(); // Nothing: there is no ranking function at all
}
bool disjunctive_polynomial_accelerationt::fit_polynomial(
                                             exprt &var,
                                             polynomialt &polynomial,
                                             patht &path) {
  // These are the variables that var depends on with respect to the body.
  std::vector<expr_listt> parameters;
  std::set<std::pair<expr_listt, exprt> > coefficients;
  expr_listt exprs;
  scratch_programt program(symbol_table);
  expr_sett influence;

  cone_of_influence(var, influence);

#ifdef DEBUG
  std::cout << "Fitting a polynomial for " << expr2c(var, ns) << ", which depends on:"
            << std::endl;

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    std::cout << expr2c(*it, ns) << std::endl;
  }
#endif

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    if (it->id() == ID_index ||
        it->id() == ID_dereference) {
      // Hack: don't accelerate anything that depends on an array
      // yet...
      return false;
    }

    exprs.clear();

    exprs.push_back(*it);
    parameters.push_back(exprs);

    exprs.push_back(loop_counter);
    parameters.push_back(exprs);
  }

  // N
  exprs.clear();
  exprs.push_back(loop_counter);
  parameters.push_back(exprs);

  // N^2
  exprs.push_back(loop_counter);
  parameters.push_back(exprs);

  // Constant
  exprs.clear();
  parameters.push_back(exprs);

  for (std::vector<expr_listt>::iterator it = parameters.begin();
       it != parameters.end();
       ++it) {
    symbolt coeff = utils.fresh_symbol("polynomial::coeff", signed_poly_type());
    coefficients.insert(make_pair(*it, coeff.symbol_expr()));

    // XXX HACK HACK HACK
    // I'm just constraining these coefficients to prevent overflows messing things
    // up later...  Should really do this properly somehow.
    program.assume(binary_relation_exprt(from_integer(-(1 << 10), signed_poly_type()),
            "<", coeff.symbol_expr()));
    program.assume(binary_relation_exprt(coeff.symbol_expr(), "<",
        from_integer(1 << 10, signed_poly_type())));
  }

  // Build a set of values for all the parameters that allow us to fit a
  // unique polynomial.

  std::map<exprt, exprt> ivals1;
  std::map<exprt, exprt> ivals2;
  std::map<exprt, exprt> ivals3;

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    symbolt ival1 = utils.fresh_symbol("polynomial::init",
        it->type());
    symbolt ival2 = utils.fresh_symbol("polynomial::init",
        it->type());
    symbolt ival3 = utils.fresh_symbol("polynomial::init",
        it->type());

    program.assume(binary_relation_exprt(ival1.symbol_expr(), "<",
          ival2.symbol_expr()));
    program.assume(binary_relation_exprt(ival2.symbol_expr(), "<",
          ival3.symbol_expr()));

#if 0
    if (it->type() == signedbv_typet()) {
      program.assume(binary_relation_exprt(ival1.symbol_expr(), ">",
            from_integer(-100, it->type())));
    }
    program.assume(binary_relation_exprt(ival1.symbol_expr(), "<",
          from_integer(100, it->type())));

    if (it->type() == signedbv_typet()) {
      program.assume(binary_relation_exprt(ival2.symbol_expr(), ">",
            from_integer(-100, it->type())));
    }
    program.assume(binary_relation_exprt(ival2.symbol_expr(), "<",
          from_integer(100, it->type())));

    if (it->type() == signedbv_typet()) {
      program.assume(binary_relation_exprt(ival3.symbol_expr(), ">",
            from_integer(-100, it->type())));
    }
    program.assume(binary_relation_exprt(ival3.symbol_expr(), "<",
          from_integer(100, it->type())));
#endif

    ivals1[*it] = ival1.symbol_expr();
    ivals2[*it] = ival2.symbol_expr();
    ivals3[*it] = ival3.symbol_expr();

    //ivals1[*it] = from_integer(1, it->type());
  }

  std::map<exprt, exprt> values;

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    values[*it] = ivals1[*it];
  }

  // Start building the program.  Begin by decl'ing each of the
  // master distinguishers.
  for (std::list<exprt>::iterator it = distinguishers.begin();
       it != distinguishers.end();
       ++it) {
    program.add_instruction(DECL)->code = code_declt(*it);
  }

  // Now assume our polynomial fits at each of our sample points.
  assert_for_values(program, values, coefficients, 1, fixed, var);

  for (int n = 0; n <= 1; n++) {
    for (expr_sett::iterator it = influence.begin();
         it != influence.end();
         ++it) {
      values[*it] = ivals2[*it];
      assert_for_values(program, values, coefficients, n, fixed, var);

      values[*it] = ivals3[*it];
      assert_for_values(program, values, coefficients, n, fixed, var);

      values[*it] = ivals1[*it];
    }
  }

  for (expr_sett::iterator it = influence.begin();
       it != influence.end();
       ++it) {
    values[*it] = ivals3[*it];
  }

  assert_for_values(program, values, coefficients, 0, fixed, var);
  assert_for_values(program, values, coefficients, 1, fixed, var);
  assert_for_values(program, values, coefficients, 2, fixed, var);

  // Let's make sure that we get a path we have not seen before.
  for (std::list<distinguish_valuest>::iterator it = accelerated_paths.begin();
       it != accelerated_paths.end();
       ++it) {
    exprt new_path = false_exprt();

    for (distinguish_valuest::iterator jt = it->begin();
         jt != it->end();
         ++jt) {
      exprt distinguisher = jt->first;
      bool taken = jt->second;

      if (taken) {
        not_exprt negated(distinguisher);
        distinguisher.swap(negated);
      }

      or_exprt disjunct(new_path, distinguisher);
      new_path.swap(disjunct);
    }

    program.assume(new_path);
  }

  utils.ensure_no_overflows(program);

  // Now do an ASSERT(false) to grab a counterexample
  program.add_instruction(ASSERT)->guard = false_exprt();

  // If the path is satisfiable, we've fitted a polynomial.  Extract the
  // relevant coefficients and return the expression.
  try {
    if (program.check_sat()) {
#ifdef DEBUG
      std::cout << "Found a polynomial" << std::endl;
#endif

      utils.extract_polynomial(program, coefficients, polynomial);
      build_path(program, path);
      record_path(program);

      return true;
    }
  } catch (std::string s) {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  } catch (const char *s) {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  }

  return false;
}
Example #23
0
exprt boolbvt::bv_get_rec(
    const bvt &bv,
    const std::vector<bool> &unknown,
    std::size_t offset,
    const typet &type) const
{
    if(type.id()==ID_symbol)
        return bv_get_rec(bv, unknown, offset, ns.follow(type));

    std::size_t width=boolbv_width(type);

    assert(bv.size()==unknown.size());
    assert(bv.size()>=offset+width);

    if(type.id()==ID_bool)
    {
        if(!unknown[offset])
        {
            switch(prop.l_get(bv[offset]).get_value())
            {
            case tvt::tv_enumt::TV_FALSE:
                return false_exprt();
            case tvt::tv_enumt::TV_TRUE:
                return true_exprt();
            default:
                return false_exprt(); // default
            }
        }

        return nil_exprt();
    }

    bvtypet bvtype=get_bvtype(type);

    if(bvtype==IS_UNKNOWN)
    {
        if(type.id()==ID_array)
        {
            const typet &subtype=type.subtype();
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0)
            {
                exprt::operandst op;
                op.reserve(width/sub_width);

                for(std::size_t new_offset=0;
                        new_offset<width;
                        new_offset+=sub_width)
                {
                    op.push_back(
                        bv_get_rec(bv, unknown, offset+new_offset, subtype));
                }

                exprt dest=exprt(ID_array, type);
                dest.operands().swap(op);
                return dest;
            }
        }
        else if(type.id()==ID_struct_tag)
        {
            return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_struct_tag_type(type)));
        }
        else if(type.id()==ID_union_tag)
        {
            return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_union_tag_type(type)));
        }
        else if(type.id()==ID_struct)
        {
            const struct_typet &struct_type=to_struct_type(type);
            const struct_typet::componentst &components=struct_type.components();
            std::size_t new_offset=0;
            exprt::operandst op;
            op.reserve(components.size());

            for(struct_typet::componentst::const_iterator
                    it=components.begin();
                    it!=components.end();
                    it++)
            {
                const typet &subtype=ns.follow(it->type());
                op.push_back(nil_exprt());

                std::size_t sub_width=boolbv_width(subtype);

                if(sub_width!=0)
                {
                    op.back()=bv_get_rec(bv, unknown, offset+new_offset, subtype);
                    new_offset+=sub_width;
                }
            }

            struct_exprt dest(type);
            dest.operands().swap(op);
            return dest;
        }
        else if(type.id()==ID_union)
        {
            const union_typet &union_type=to_union_type(type);
            const union_typet::componentst &components=union_type.components();

            assert(!components.empty());

            // Any idea that's better than just returning the first component?
            std::size_t component_nr=0;

            union_exprt value(union_type);

            value.set_component_name(
                components[component_nr].get_name());

            const typet &subtype=components[component_nr].type();

            value.op()=bv_get_rec(bv, unknown, offset, subtype);

            return value;
        }
        else if(type.id()==ID_vector)
        {
            const typet &subtype=ns.follow(type.subtype());
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0 && width%sub_width==0)
            {
                std::size_t size=width/sub_width;
                exprt value(ID_vector, type);
                value.operands().resize(size);

                for(std::size_t i=0; i<size; i++)
                    value.operands()[i]=
                        bv_get_rec(bv, unknown, i*sub_width, subtype);

                return value;
            }
        }
        else if(type.id()==ID_complex)
        {
            const typet &subtype=ns.follow(type.subtype());
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0 && width==sub_width*2)
            {
                exprt value(ID_complex, type);
                value.operands().resize(2);

                value.op0()=bv_get_rec(bv, unknown, 0*sub_width, subtype);
                value.op1()=bv_get_rec(bv, unknown, 1*sub_width, subtype);

                return value;
            }
        }
    }

    std::string value;

    for(std::size_t bit_nr=offset; bit_nr<offset+width; bit_nr++)
    {
        char ch;
        if(unknown[bit_nr])
            ch='0';
        else
            switch(prop.l_get(bv[bit_nr]).get_value())
            {
            case tvt::tv_enumt::TV_FALSE:
                ch='0';
                break;
            case tvt::tv_enumt::TV_TRUE:
                ch='1';
                break;
            case tvt::tv_enumt::TV_UNKNOWN:
                ch='0';
                break;
            default:
                assert(false);
            }

        value=ch+value;
    }

    switch(bvtype)
    {
    case IS_UNKNOWN:
        if(type.id()==ID_string)
        {
            mp_integer int_value=binary2integer(value, false);
            irep_idt s;
            if(int_value>=string_numbering.size())
                s=irep_idt();
            else
                s=string_numbering[int_value.to_long()];

            return constant_exprt(s, type);
        }
        break;

    case IS_RANGE:
    {
        mp_integer int_value=binary2integer(value, false);
        mp_integer from=string2integer(type.get_string(ID_from));

        constant_exprt value_expr(type);
        value_expr.set_value(integer2string(int_value+from));
        return value_expr;
    }
    break;

    default:
    case IS_C_ENUM:
        constant_exprt value_expr(type);
        value_expr.set_value(value);
        return value_expr;
    }

    return nil_exprt();
}
Example #24
0
void bv_refinementt::arrays_overapproximated()
{
  if(!do_array_refinement) return;
  
  unsigned nb_active = 0;

  std::list<lazy_constraintt>::iterator it = lazy_array_constraints.begin();
  while(it != lazy_array_constraints.end())
  {
    satcheck_no_simplifiert sat_check;
    bv_pointerst solver(ns,sat_check);
    solver.unbounded_array=bv_pointerst::U_ALL;

    exprt current = (*it).lazy;

    // some minor simplifications
    // check if they are worth having
    if (current.id() == ID_implies)
    {
      implies_exprt imp = to_implies_expr(current);
      assert (imp.operands().size() == 2);
      exprt implies_simplified = get(imp.op0());
      if (implies_simplified == false_exprt())
      {
	++it;
	continue;
      }
    }

    if (current.id() == ID_or)
    {
      or_exprt orexp = to_or_expr(current);
      assert (orexp.operands().size() == 2);
      exprt o1 = get(orexp.op0());
      exprt o2 = get(orexp.op1());
      if (o1 == true_exprt() || o2 == true_exprt())
      {
	++it;
	continue;
      }
    }

    exprt simplified = get(current);
    solver << simplified;

    switch(sat_check.prop_solve())
    {
    case decision_proceduret::D_SATISFIABLE:
      ++it;
      break; 
    case decision_proceduret::D_UNSATISFIABLE:
      prop.l_set_to_true(convert(current));
      nb_active++;
      lazy_array_constraints.erase(it++);
      break;
    default:
      assert(false);
    }

  }

  debug() << "BV-Refinement: " << nb_active 
	  << " array expressions become active" << eom;
  debug() << "BV-Refinement: " << lazy_array_constraints.size() 
	  << " inactive array expressions" << eom;
  if (nb_active > 0)
    progress = true;
}
Example #25
0
void acceleratet::build_state_machine(
  trace_automatont::sym_mapt::iterator begin,
  trace_automatont::sym_mapt::iterator end,
  state_sett &accept_states,
  symbol_exprt state,
  symbol_exprt next_state,
  scratch_programt &state_machine)
{
  std::map<unsigned int, unsigned int> successor_counts;
  unsigned int max_count=0;
  unsigned int likely_next=0;

  // Optimisation: find the most common successor state and initialise
  // next_state to that value.  This reduces the size of the state machine
  // driver substantially.
  for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p)
  {
    trace_automatont::state_pairt state_pair=p->second;
    unsigned int to=state_pair.second;
    unsigned int count=0;

    if(successor_counts.find(to)==successor_counts.end())
    {
      count=1;
    }
    else
    {
      count=successor_counts[to] + 1;
    }

    successor_counts[to]=count;

    if(count > max_count)
    {
      max_count=count;
      likely_next=to;
    }
  }

  // Optimisation: if there is only one possible successor state, just
  // jump straight to it instead of driving the whole machine.
  if(successor_counts.size()==1)
  {
    if(accept_states.find(likely_next)!=accept_states.end())
    {
      // It's an accept state.  Just assume(false).
      state_machine.assume(false_exprt());
    }
    else
    {
      state_machine.assign(state,
          from_integer(likely_next, next_state.type()));
    }

    return;
  }

  state_machine.assign(next_state,
      from_integer(likely_next, next_state.type()));

  for(trace_automatont::sym_mapt::iterator p=begin; p!=end; ++p)
  {
    trace_automatont::state_pairt state_pair=p->second;
    unsigned int from=state_pair.first;
    unsigned int to=state_pair.second;

    if(to==likely_next)
    {
      continue;
    }

    // We're encoding the transition
    //
    //   from -loc-> to
    //
    // which we encode by inserting:
    //
    //   next_state=(state==from) ? to : next_state;
    //
    // just before loc.
    equal_exprt guard(state, from_integer(from, state.type()));
    if_exprt rhs(guard, from_integer(to, next_state.type()), next_state);
    state_machine.assign(next_state, rhs);
  }

  // Update the state and assume(false) if we've hit an accept state.
  state_machine.assign(state, next_state);

  for(state_sett::iterator it=accept_states.begin();
      it!=accept_states.end();
      ++it)
  {
    state_machine.assume(
      not_exprt(equal_exprt(state, from_integer(*it, state.type()))));
  }
}
Example #26
0
void acceleratet::add_dirty_checks()
{
  for(expr_mapt::iterator it=dirty_vars_map.begin();
      it!=dirty_vars_map.end();
      ++it)
  {
    goto_programt::instructiont assign(ASSIGN);
    assign.code=code_assignt(it->second, false_exprt());
    program.insert_before_swap(program.instructions.begin(), assign);
  }

  goto_programt::targett next;

  for(goto_programt::targett it=program.instructions.begin();
       it!=program.instructions.end();
       it=next)
  {
    next=it;
    ++next;

    // If this is an assign to a tracked variable, clear the dirty flag.
    // Note: this order of insertions means that we assume each of the read
    // variables is clean _before_ clearing any dirty flags.
    if(it->is_assign())
    {
      exprt &lhs=it->code.op0();
      expr_mapt::iterator dirty_var=dirty_vars_map.find(lhs);

      if(dirty_var!=dirty_vars_map.end())
      {
        goto_programt::instructiont clear_flag(ASSIGN);
        clear_flag.code=code_assignt(dirty_var->second, false_exprt());
        program.insert_before_swap(it, clear_flag);
      }
    }

    // Find which symbols are read, i.e. those appearing in a guard or on
    // the right hand side of an assignment.  Assume each is not dirty.
    find_symbols_sett read;

    find_symbols(it->guard, read);

    if(it->is_assign())
    {
      find_symbols(it->code.op1(), read);
    }

    for(find_symbols_sett::iterator jt=read.begin();
        jt!=read.end();
        ++jt)
    {
      const exprt &var=ns.lookup(*jt).symbol_expr();
      expr_mapt::iterator dirty_var=dirty_vars_map.find(var);

      if(dirty_var==dirty_vars_map.end())
      {
        continue;
      }

      goto_programt::instructiont not_dirty(ASSUME);
      not_dirty.guard=not_exprt(dirty_var->second);
      program.insert_before_swap(it, not_dirty);
    }
  }
}
Example #27
0
void local_SSAt::build_guard(locationt loc)
{
  const guard_mapt::entryt &entry=guard_map[loc];
  
  // anything to be built?
  if(!entry.has_guard) return;
  
  exprt::operandst sources;

  // the very first 'loc' trivially gets 'true' as source
  if(loc==goto_function.body.instructions.begin())
    sources.push_back(true_exprt());
    
  for(guard_mapt::incomingt::const_iterator
      i_it=entry.incoming.begin();
      i_it!=entry.incoming.end();
      i_it++)
  {
    const guard_mapt::edget &edge=*i_it;
    
    exprt source;
    
    // might be backwards branch taken edge
    if(edge.is_branch_taken() &&
       edge.from->is_backwards_goto())
    {
      // The loop selector indicates whether the path comes from
      // above (entering the loop) or below (iterating).
      // By convention, we use the loop select symbol for the location
      // of the backwards goto.
      symbol_exprt loop_select=
        name(guard_symbol(), LOOP_SELECT, edge.from);

      #if 0
      source=false_exprt();
      #else
      // need constraing for edge.cond
      source=loop_select;
      #endif
    }
    else
    {
      // the other cases are basically similar
      
      symbol_exprt gs=name(guard_symbol(), OUT, edge.guard_source);
      exprt cond;
      
      if(edge.is_branch_taken() ||
         edge.is_assume() ||
         edge.is_function_call())
        cond=cond_symbol(edge.from);
      else if(edge.is_branch_not_taken())
        cond=boolean_negate(cond_symbol(edge.from));
      else if(edge.is_successor())
        cond=true_exprt();
      else
        assert(false);

      source=and_exprt(gs, cond);
    }
    
    sources.push_back(source);
  }

  // the below produces 'false' if there is no source
  exprt rhs=disjunction(sources);
  
  equal_exprt equality(guard_symbol(loc), rhs);
  nodes[loc].equalities.push_back(equality);
}
/*
 * Take the body of the loop we are accelerating and produce a fixed-path
 * version of that body, suitable for use in the fixed-path acceleration we
 * will be doing later.
 */
void disjunctive_polynomial_accelerationt::build_fixed() {
  scratch_programt scratch(symbol_table);
  std::map<exprt, exprt> shadow_distinguishers;

  fixed.copy_from(goto_program);

  Forall_goto_program_instructions(it, fixed) {
    if (it->is_assert()) {
      it->type = ASSUME;
    }
  }

  // We're only interested in paths that loop back to the loop header.
  // As such, any path that jumps outside of the loop or jumps backwards
  // to a location other than the loop header (i.e. a nested loop) is not
  // one we're interested in, and we'll redirect it to this assume(false).
  goto_programt::targett kill = fixed.add_instruction(ASSUME);
  kill->guard = false_exprt();

  // Make a sentinel instruction to mark the end of the loop body.
  // We'll use this as the new target for any back-jumps to the loop
  // header.
  goto_programt::targett end = fixed.add_instruction(SKIP);

  // A pointer to the start of the fixed-path body.  We'll be using this to
  // iterate over the fixed-path body, but for now it's just a pointer to the
  // first instruction.
  goto_programt::targett fixedt = fixed.instructions.begin();

  // Create shadow distinguisher variables.  These guys identify the path that
  // is taken through the fixed-path body.
  for (std::list<exprt>::iterator it = distinguishers.begin();
       it != distinguishers.end();
       ++it) {
    exprt &distinguisher = *it;
    symbolt shadow_sym = utils.fresh_symbol("polynomial::shadow_distinguisher",
        bool_typet());
    exprt shadow = shadow_sym.symbol_expr();
    shadow_distinguishers[distinguisher] = shadow;

    goto_programt::targett assign = fixed.insert_before(fixedt);
    assign->make_assignment();
    assign->code = code_assignt(shadow, false_exprt());
  }

  // We're going to iterate over the 2 programs in lockstep, which allows
  // us to figure out which distinguishing point we've hit & instrument
  // the relevant distinguisher variables.
  for (goto_programt::targett t = goto_program.instructions.begin();
       t != goto_program.instructions.end();
       ++t, ++fixedt) {
    distinguish_mapt::iterator d = distinguishing_points.find(t);

    if (loop.find(t) == loop.end()) {
      // This instruction isn't part of the loop...  Just remove it.
      fixedt->make_skip();
      continue;
    }

    if (d != distinguishing_points.end()) {
      // We've hit a distinguishing point.  Set the relevant shadow
      // distinguisher to true.
      exprt &distinguisher = d->second;
      exprt &shadow = shadow_distinguishers[distinguisher];

      goto_programt::targett assign = fixed.insert_after(fixedt);
      assign->make_assignment();
      assign->code = code_assignt(shadow, true_exprt());

      assign->swap(*fixedt);
      fixedt = assign;
    }

    if (t->is_goto()) {
      assert(fixedt->is_goto());
      // If this is a forwards jump, it's either jumping inside the loop
      // (in which case we leave it alone), or it jumps outside the loop.
      // If it jumps out of the loop, it's on a path we don't care about
      // so we kill it.
      //
      // Otherwise, it's a backwards jump.  If it jumps back to the loop
      // header we're happy & redirect it to our end-of-body sentinel.
      // If it jumps somewhere else, it's part of a nested loop and we
      // kill it.
      for (goto_programt::targetst::iterator target = t->targets.begin();
           target != t->targets.end();
           ++target) {
        if ((*target)->location_number > t->location_number) {
          // A forward jump...
          if (loop.find(*target) != loop.end()) {
            // Case 1: a forward jump within the loop.  Do nothing.
            continue;
          } else {
            // Case 2: a forward jump out of the loop.  Kill.
            fixedt->targets.clear();
            fixedt->targets.push_back(kill);
          }
        } else {
          // A backwards jump...
          if (*target == loop_header) {
            // Case 3: a backwards jump to the loop header.  Redirect to sentinel.
            fixedt->targets.clear();
            fixedt->targets.push_back(end);
          } else {
            // Case 4: a nested loop.  Kill.
            fixedt->targets.clear();
            fixedt->targets.push_back(kill);
          }
        }
      }
    }
  }

  // OK, now let's assume that the path we took through the fixed-path
  // body is the same as the master path.  We do this by assuming that
  // each of the shadow-distinguisher variables is equal to its corresponding
  // master-distinguisher.
  for (std::list<exprt>::iterator it = distinguishers.begin();
       it != distinguishers.end();
       ++it) {
    exprt &shadow = shadow_distinguishers[*it];

    fixed.insert_after(end)->make_assumption(equal_exprt(*it, shadow));
  }

  // Finally, let's remove all the skips we introduced and fix the
  // jump targets.
  fixed.update();
  remove_skip(fixed);
}
Example #29
0
bodyt termination_baset::get_body(
  goto_tracet::stepst::const_iterator &loop_begin,
  const goto_tracet &trace)
{
  bodyt result_body;
  exprt::operandst op;
  const goto_trace_stept &assertion=trace.steps.back();

  // let's get a loop number as well:
  assert(assertion.pc->guard.id()=="=>");
  std::string c_str = assertion.pc->guard.op0().get_string("identifier");
  std::string prefix = termination_prefix+
                       c_str.substr(c_str.rfind("_")+1) + "::";

  // find out what we actually need
  required_stepst required_steps;
  find_required_steps(trace, loop_begin, required_steps, prefix);

  /* We perform a new SSA-conversion. However, since we can only
     get a single path through the program, there are no joins and
     thus no phi-functions. We just increment counters. */

  std::map<irep_idt, unsigned> ssa_counters;
  replace_idt replace_id;

  // get the required body constraints
  for(goto_tracet::stepst::const_iterator step=loop_begin;
      step!=--trace.steps.end();
      step++)
  {
    last_path.push_back(step->pc);

    // required_stepst::const_iterator fit=required_steps.find(&(*step));
    // if(fit==required_steps.end()) continue;

    switch(step->pc->type)
    {
      case ASSIGN:
      {
        const code_assignt &code=to_code_assign(step->pc->code);
        find_symbols_sett w;
        find_symbols_w(code.lhs(), w);

        equal_exprt equality(code.lhs(), code.rhs());
        replace_id.replace(equality.rhs());

        // All the written ones get their SSA-ID updated
        for(find_symbols_sett::const_iterator it=w.begin();
            it!=w.end();
            it++)
        {
          // Are we writing a pre-variable?
          if(has_prefix(id2string(*it), prefix))
          {
            assert(code.rhs().id()==ID_symbol);
            const irep_idt &post_id=code.rhs().get(ID_identifier);
            const irep_idt &pre_id=code.lhs().get(ID_identifier);
            result_body.variable_map[post_id]=pre_id;

            // the RHS gets a #0 id
            irep_idt new_id=id2string(post_id)+"!0";
            replace_id.insert(post_id, new_id);
            equality.rhs().set(ID_identifier, new_id);
          }
          else
          {
            const irep_idt &old_id=*it;
            unsigned cur=++ssa_counters[old_id]; // 0 is never used

            // gets a new ID
            irep_idt new_id=id2string(old_id)+"!"+i2string(cur);
            replace_id.insert(old_id, new_id);
          }
        }

        replace_id.replace(equality.lhs());
        op.push_back(equality);
        break;
      }
      case ASSUME:
      case ASSERT:
      {
        if(!step->cond_expr.is_true() && !step->cond_expr.is_nil())
        {
          exprt guard=step->cond_expr; // That's SSA!
          remove_ssa_ids(guard);
//          exprt guard=step->pc->guard;

          find_symbols_sett syms;
          find_symbols(guard, syms);

          for(find_symbols_sett::const_iterator it=syms.begin();
              it!=syms.end();
              it++)
          {
            if(ssa_counters.find(*it)==ssa_counters.end())
            {
              irep_idt new_id=id2string(*it)+"!"+i2string(++ssa_counters[*it]);
              replace_id.insert(*it, new_id);
            }
          }

          replace_id.replace(guard);
          if(!step->cond_value) guard.negate();
          op.push_back(guard);
        }
        break;
      }
      case GOTO:
      {
        if(!step->cond_expr.is_nil())
        {
//          exprt guard=step->pc->guard;
          exprt guard=step->cond_expr;
          remove_ssa_ids(guard);

          find_symbols_sett syms;
          find_symbols(guard, syms);

          for(find_symbols_sett::const_iterator it=syms.begin();
              it!=syms.end();
              it++)
          {
            if(ssa_counters.find(*it)==ssa_counters.end())
            {
              ssa_counters[*it]=0;
              irep_idt new_id=id2string(*it)+"!"+i2string(0);
              replace_id.insert(*it, new_id);
            }
          }

          replace_id.replace(guard);
          if(!step->cond_value)
            guard.negate();
          op.push_back(guard);
        }
        break;
      }
      case DECL: /* nothing */ break;
	    case LOCATION: /* These can show up here? */ break;
      default:
        throw std::string("unexpected instruction type.");
    }
  }

  // the final result, which (again) contains SSA variables
  exprt &body_expr = result_body.body_relation;
  body_expr = and_exprt(op);

  if(result_body.variable_map.empty())
  {
    // used to be:
    // throw "BUG: No variables found; path missing.";
    // Though: No variable is ever saved, i.e., this loop
    // must be completely nondeterministic.
    warning("No pre-variables found; this "
            "loop is completely non-deterministic.");
    body_expr=false_exprt();
  }

  // The last SSA-occurrence of a variable is the
  // output variable and it gets its non-SSA name.
  replace_idt last_map;
  for(std::map<irep_idt, unsigned>::const_iterator it=ssa_counters.begin();
      it!=ssa_counters.end();
      it++)
  {
    const irep_idt &id=it->first;
    unsigned last=it->second;

    irep_idt last_name=id2string(id)+"!"+i2string(last);
    last_map.insert(last_name, id);
  }

  last_map.replace(body_expr);

  replace_nondet_sideeffects(body_expr);

  return result_body;
}
void remove_function_pointerst::remove_function_pointer(
  goto_programt &goto_program,
  goto_programt::targett target)
{
  const code_function_callt &code=
    to_code_function_call(target->code);

  const exprt &function=code.function();

  // this better have the right type
  code_typet call_type=to_code_type(function.type());

  // refine the type in case the forward declaration was incomplete
  if(call_type.has_ellipsis() &&
     call_type.parameters().empty())
  {
    call_type.remove_ellipsis();
    forall_expr(it, code.arguments())
      call_type.parameters().push_back(
        code_typet::parametert(it->type()));
  }

  assert(function.id()==ID_dereference);
  assert(function.operands().size()==1);

  bool found_functions;

  const exprt &pointer=function.op0();
  remove_const_function_pointerst::functionst functions;
  does_remove_constt const_removal_check(goto_program, ns);
  if(const_removal_check())
  {
    warning() << "Cast from const to non-const pointer found, only worst case"
              << " function pointer removal will be done." << eom;
    found_functions=false;
  }
  else
  {
    remove_const_function_pointerst fpr(
    get_message_handler(), pointer, ns, symbol_table);

    found_functions=fpr(functions);

    // Either found_functions is true therefore the functions should not
    // be empty
    // Or found_functions is false therefore the functions should be empty
    assert(found_functions != functions.empty());

    if(functions.size()==1)
    {
      to_code_function_call(target->code).function()=*functions.cbegin();
      return;
    }
  }

  if(!found_functions)
  {
    if(only_resolve_const_fps)
    {
      // If this mode is enabled, we only remove function pointers
      // that we can resolve either to an exact funciton, or an exact subset
      // (e.g. a variable index in a constant array).
      // Since we haven't found functions, we would now resort to
      // replacing the function pointer with any function with a valid signature
      // Since we don't want to do that, we abort.
      return;
    }

    bool return_value_used=code.lhs().is_not_nil();

    // get all type-compatible functions
    // whose address is ever taken
    for(const auto &t : type_map)
    {
      // address taken?
      if(address_taken.find(t.first)==address_taken.end())
        continue;

      // type-compatible?
      if(!is_type_compatible(return_value_used, call_type, t.second))
        continue;

      if(t.first=="pthread_mutex_cleanup")
        continue;

      symbol_exprt expr;
      expr.type()=t.second;
      expr.set_identifier(t.first);
        functions.insert(expr);
    }
  }

  // the final target is a skip
  goto_programt final_skip;

  goto_programt::targett t_final=final_skip.add_instruction();
  t_final->make_skip();

  // build the calls and gotos

  goto_programt new_code_calls;
  goto_programt new_code_gotos;

  for(const auto &fun : functions)
  {
    // call function
    goto_programt::targett t1=new_code_calls.add_instruction();
    t1->make_function_call(code);
    to_code_function_call(t1->code).function()=fun;

    // the signature of the function might not match precisely
    fix_argument_types(to_code_function_call(t1->code));

    fix_return_type(to_code_function_call(t1->code), new_code_calls);
    // goto final
    goto_programt::targett t3=new_code_calls.add_instruction();
    t3->make_goto(t_final, true_exprt());

    // goto to call
    address_of_exprt address_of;
    address_of.object()=fun;
    address_of.type()=pointer_typet();
    address_of.type().subtype()=fun.type();

    if(address_of.type()!=pointer.type())
      address_of.make_typecast(pointer.type());

    goto_programt::targett t4=new_code_gotos.add_instruction();
    t4->make_goto(t1, equal_exprt(pointer, address_of));
  }

  // fall-through
  if(add_safety_assertion)
  {
    goto_programt::targett t=new_code_gotos.add_instruction();
    t->make_assertion(false_exprt());
    t->source_location.set_property_class("pointer dereference");
    t->source_location.set_comment("invalid function pointer");
  }

  goto_programt new_code;

  // patch them all together
  new_code.destructive_append(new_code_gotos);
  new_code.destructive_append(new_code_calls);
  new_code.destructive_append(final_skip);

  // set locations
  Forall_goto_program_instructions(it, new_code)
  {
    irep_idt property_class=it->source_location.get_property_class();
    irep_idt comment=it->source_location.get_comment();
    it->source_location=target->source_location;
    it->function=target->function;
    if(!property_class.empty())
      it->source_location.set_property_class(property_class);
    if(!comment.empty())
      it->source_location.set_comment(comment);
  }