Example #1
0
/**
 * Return the smallest type that both t1 and t2 can be cast to without losing
 * information.
 *
 * e.g.
 *
 * join_types(unsignedbv_typet(32), unsignedbv_typet(16))=unsignedbv_typet(32)
 * join_types(signedbv_typet(16), unsignedbv_typet(16))=signedbv_typet(17)
 * join_types(signedbv_typet(32), signedbv_typet(32))=signedbv_typet(32)
 */
typet join_types(const typet &t1, const typet &t2)
{
  // Handle the simple case first...
  if(t1==t2)
  {
    return t1;
  }

  // OK, they're not the same type.  Are they both bitvectors?
  if(is_bitvector(t1) && is_bitvector(t2))
  {
    // They are.  That makes things easy!  There are three cases to consider:
    // both types are unsigned, both types are signed or there's one of each.

    bitvector_typet b1=to_bitvector_type(t1);
    bitvector_typet b2=to_bitvector_type(t2);

    if(is_unsigned(b1) && is_unsigned(b2))
    {
      // We just need to take the max of their widths.
      std::size_t width=std::max(b1.get_width(), b2.get_width());
      return unsignedbv_typet(width);
    }
    else if(is_signed(b1) && is_signed(b2))
    {
      // Again, just need to take the max of the widths.
      std::size_t width=std::max(b1.get_width(), b2.get_width());
      return signedbv_typet(width);
    }
    else
    {
      // This is the (slightly) tricky case.  If we have a signed and an
      // unsigned type, we're going to return a signed type.  And to cast
      // an unsigned type to a signed type, we need the signed type to be
      // at least one bit wider than the unsigned type we're casting from.
      std::size_t signed_width=is_signed(t1) ? b1.get_width() :
                                                 b2.get_width();
      std::size_t unsigned_width=is_signed(t1) ? b2.get_width() :
                                                   b1.get_width();
      // unsigned_width++;

      std::size_t width=std::max(signed_width, unsigned_width);

      return signedbv_typet(width);
    }
  }

  std::cerr << "Tried to join types: "
            << t1.pretty() << " and " << t2.pretty()
            << '\n';
  assert(!"Couldn't join types");
}
Example #2
0
typet signed_char_type()
{
  typet result=signedbv_typet(config.ansi_c.char_width);

  result.set(ID_C_c_type, ID_signed_char);
  
  return result;
}
Example #3
0
typet wchar_t_type()
{
  typet result;
  
  if(config.ansi_c.wchar_t_is_unsigned)
    result=unsignedbv_typet(config.ansi_c.wchar_t_width);
  else
    result=signedbv_typet(config.ansi_c.wchar_t_width);

  result.set(ID_C_c_type, ID_wchar_t);

  return result;
}
Example #4
0
symbolt scratch_programt::fresh_symbol(string base) {
  string name = base + "_" + i2string(num_symbols++);
  symbolt ret;
  ret.module = "scratch";
  ret.name = name;
  ret.base_name = name;
  ret.pretty_name = name;
  ret.type = signedbv_typet(32);

  shadow_symbol_table.add(ret);

  return ret;
}
Example #5
0
void object_descriptor_exprt::build(
  const exprt &expr,
  const namespacet &ns)
{
  assert(object().id()==ID_unknown);
  object()=expr;

  if(offset().id()==ID_unknown)
    offset()=from_integer(0, signedbv_typet(config.ansi_c.pointer_width));

  build_object_descriptor_rec(ns, expr, *this);

  assert(root_object().type().id()!=ID_empty);
}
Example #6
0
typet char_type()
{
  typet result;

  // this can be signed or unsigned, depending on the architecture

  if(config.ansi_c.char_is_unsigned)
    result=unsignedbv_typet(config.ansi_c.char_width);
  else
    result=signedbv_typet(config.ansi_c.char_width);

  // There are 3 char types, i.e., this one is
  // different from either signed char or unsigned char!
    
  result.set(ID_C_c_type, ID_char);
    
  return result;
}
Example #7
0
exprt ranking_synthesis_satt::coefficient(const exprt &expr)
{
  assert(expr.id()==ID_symbol);

  exprt &entry = coefficient_map[expr];

  if(entry==exprt())
  {
    irep_idt ident=expr.get_string(ID_identifier) + "$C";

    // set up a new coefficient
    entry.id(ID_symbol);
    entry.set(ID_identifier, ident);

    // adjust the coefficient type
    entry.type()=signedbv_typet(2); //expr.type();
  }

  return entry;
}
Example #8
0
typet signed_short_int_type()
{
  typet result=signedbv_typet(config.ansi_c.short_int_width);
  result.set(ID_C_c_type, ID_signed_short_int);
  return result;
}
Example #9
0
typet gcc_signed_int128_type()
{
  typet result=signedbv_typet(128);
  result.set(ID_C_c_type, ID_signed_int128);
  return result;
}
Example #10
0
typet java_short_type()
{
  return signedbv_typet(16);
}
Example #11
0
typet java_long_type()
{
  return signedbv_typet(64);
}
Example #12
0
typet java_int_type()
{
  return signedbv_typet(32);
}
Example #13
0
typet bv_spect::to_type() const
{
  if(is_signed) return signedbv_typet(width);
  return unsignedbv_typet(width);
}
Example #14
0
void c_typecastt::implicit_typecast_arithmetic(
  exprt &expr1,
  exprt &expr2)
{
  const typet &type1=ns.follow(expr1.type());
  const typet &type2=ns.follow(expr2.type());

  c_typet c_type1=minimum_promotion(type1),
          c_type2=minimum_promotion(type2);

  c_typet max_type=std::max(c_type1, c_type2);

  if(max_type==LARGE_SIGNED_INT || max_type==LARGE_UNSIGNED_INT)
  {
    // get the biggest width of both
    unsigned width1=type1.get_int(ID_width);
    unsigned width2=type2.get_int(ID_width);
    
    // produce type
    typet result_type;

    if(width1==width2)
    {
      if(max_type==LARGE_SIGNED_INT)
        result_type=signedbv_typet(width1);
      else
        result_type=unsignedbv_typet(width1);
    }
    else if(width1>width2)
      result_type=type1;
    else // width1<width2
      result_type=type2;

    do_typecast(expr1, result_type);
    do_typecast(expr2, result_type);
    
    return;
  }
  else if(max_type==COMPLEX)
  {
    if(c_type1==COMPLEX && c_type2==COMPLEX)
    {
      // promote to the one with bigger subtype
      if(get_c_type(type1.subtype())>get_c_type(type2.subtype()))
        do_typecast(expr2, type1);
      else
        do_typecast(expr1, type2);
    }
    else if(c_type1==COMPLEX)
    {
      assert(c_type1==COMPLEX && c_type2!=COMPLEX);
      do_typecast(expr2, type1.subtype());
      do_typecast(expr2, type1);
    }
    else
    {
      assert(c_type1!=COMPLEX && c_type2==COMPLEX);
      do_typecast(expr1, type2.subtype());
      do_typecast(expr1, type2);
    }

    return;
  }
  else if(max_type==SINGLE || max_type==DOUBLE ||
          max_type==LONGDOUBLE || max_type==FLOAT128)
  {
    // Special-case optimisation:
    // If we have two non-standard sized floats, don't do implicit type
    // promotion if we can possibly avoid it.
    if(type1==type2)
      return;
  }

  implicit_typecast_arithmetic(expr1, max_type);
  implicit_typecast_arithmetic(expr2, max_type);

  if(max_type==PTR)
  {
    if(c_type1==VOIDPTR)
      do_typecast(expr1, expr2.type());
    
    if(c_type2==VOIDPTR)
      do_typecast(expr2, expr1.type());
  }
}
Example #15
0
void c_typecastt::implicit_typecast_arithmetic(
  exprt &expr1,
  exprt &expr2)
{
  const typet &type1=ns.follow(expr1.type());
  const typet &type2=ns.follow(expr2.type());

  c_typet c_type1=get_c_type(type1),
          c_type2=get_c_type(type2);

  c_typet max_type=std::max(c_type1, c_type2);

  // "If an int can represent all values of the original type, the
  // value is converted to an int; otherwise, it is converted to
  // an unsigned int."
  
  // The second case can arise if we promote any unsigned type
  // that is as large as unsigned int.

  if(config.ansi_c.short_int_width==config.ansi_c.int_width &&
     max_type==USHORT)
    max_type=UINT;
  else if(config.ansi_c.char_width==config.ansi_c.int_width &&
          max_type==UCHAR)
    max_type=UINT;
  else
    max_type=std::max(max_type, INT);

  if(max_type==LARGE_SIGNED_INT || max_type==LARGE_UNSIGNED_INT)
  {
    // get the biggest width of both
    unsigned width1=type1.get_int(ID_width);
    unsigned width2=type2.get_int(ID_width);
    
    // produce type
    typet result_type;

    if(width1==width2)
    {
      if(max_type==LARGE_SIGNED_INT)
        result_type=signedbv_typet(width1);
      else
        result_type=unsignedbv_typet(width1);
    }
    else if(width1>width2)
      result_type=type1;
    else // width1<width2
      result_type=type2;

    do_typecast(expr1, result_type);
    do_typecast(expr2, result_type);
    
    return;
  }
  else if(max_type==COMPLEX)
  {
    if(c_type1==COMPLEX && c_type2==COMPLEX)
    {
      // promote to the one with bigger subtype
      if(get_c_type(type1.subtype())>get_c_type(type2.subtype()))
        do_typecast(expr2, type1);
      else
        do_typecast(expr1, type2);
    }
    else if(c_type1==COMPLEX)
    {
      assert(c_type1==COMPLEX && c_type2!=COMPLEX);
      do_typecast(expr2, type1.subtype());
      do_typecast(expr2, type1);
    }
    else
    {
      assert(c_type1!=COMPLEX && c_type2==COMPLEX);
      do_typecast(expr1, type2.subtype());
      do_typecast(expr1, type2);
    }

    return;
  }
    
  implicit_typecast_arithmetic(expr1, max_type);
  implicit_typecast_arithmetic(expr2, max_type);
  
  if(max_type==PTR)
  {
    if(c_type1==VOIDPTR)
      do_typecast(expr1, expr2.type());
    
    if(c_type2==VOIDPTR)
      do_typecast(expr2, expr1.type());
  }
}
Example #16
0
signedbv_typet signed_poly_type()
{
  return signedbv_typet(config.ansi_c.int_width);
}
Example #17
0
typet java_byte_type()
{
  return signedbv_typet(8);
}
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 #19
0
bool equality_domaint::adapt_types(exprt &v1, exprt &v2)
{
  // signed, unsigned integers
  if((v1.type().id()==ID_signedbv || v1.type().id()==ID_unsignedbv) &&
     (v2.type().id()==ID_signedbv || v2.type().id()==ID_unsignedbv))
  {
    unsigned size1=0, size2=0;
    if(v1.type().id()==ID_signedbv)
      size1=to_signedbv_type(v1.type()).get_width();
    if(v1.type().id()==ID_unsignedbv)
      size1=to_unsignedbv_type(v1.type()).get_width();
    if(v2.type().id()==ID_signedbv)
      size2=to_signedbv_type(v2.type()).get_width();
    if(v2.type().id()==ID_unsignedbv)
      size2=to_unsignedbv_type(v2.type()).get_width();

    if(v1.type().id()==v2.type().id())
    {
      if(size1==size2)
        return true;

      typet new_type=v1.type();
      if(new_type.id()==ID_signedbv)
        to_signedbv_type(new_type).set_width(std::max(size1, size2));
      else // if(new_type.id()==ID_unsignedbv)
        to_unsignedbv_type(new_type).set_width(std::max(size1, size2));

      if(size1>size2)
        v2=typecast_exprt(v2, new_type);
      else
        v1=typecast_exprt(v1, new_type);
      return true;
    }

    // types are different
    typet new_type=signedbv_typet(std::max(size1, size2)+1);
    v1=typecast_exprt(v1, new_type);
    v2=typecast_exprt(v2, new_type);
    return true;
  }

  // pointer equality
  if(v1.type().id()==ID_pointer && v2.type().id()==ID_pointer)
  {
    if(to_pointer_type(v1.type()).subtype()==
       to_pointer_type(v2.type()).subtype())
      return true;
    return false;
  }

  if(v1.id()==ID_index || v2.id()==ID_index)
  {
#if 0
    std::cout << "v1: " << v1 << std::endl;
    std::cout << "v2: " << v2 << std::endl;
#endif
    // TODO: implement
    return false;
  }

  return false; // types incompatible
}
Example #20
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;
}
Example #21
0
exprt ranking_synthesis_satt::instantiate(void)
{
  find_largest_constant(body.body_relation);

  binary_relation_exprt toplevel_and("and");

  toplevel_and.lhs() = body.body_relation; // that's R(x,x')

  exprt function;
  replace_mapt pre_replace_map;
      
  bool first=true;
  
  for(bodyt::variable_mapt::const_iterator it=body.variable_map.begin();
      it!=body.variable_map.end();
      it++)
  {
    if(used_variables.find(it->first)==used_variables.end())
      continue;
    
    exprt var=symbol_exprt(it->first, ns.lookup(it->first).type);
    pre_replace_map[var] = // save the corresponding pre-var
            symbol_exprt(it->second, ns.lookup(it->second).type);
    
    adjust_type(var.type());
    const typet type=var.type();

    exprt coef=coefficient(var);    

    unsigned width=safe_width(var, ns);
    assert(width!=0);

    exprt term("*", typet(""));
    term.copy_to_operands(coef, var);

    if(first)
    {
      function=term;
      first=false;
    }
    else
    {
//      cast_up(function, term);
      exprt t("+", typet(""));
      t.move_to_operands(function, term);
      function = t;
    }
  }
  
  if(first) // non of the interesting variables was used - bail out!
  {
    debug("Completely non-deterministic template; "
           "this loop does not terminate.");
    return false_exprt();
  }

//  if(!largest_constant.is_zero())
//  {
//    // add the largest constant
//    symbol_exprt lc_sym("termination::LC", largest_constant.type());
//    exprt lc=largest_constant;
//    exprt lcc=coefficient(lc_sym);
////    cast_up(lc, lcc);
//    exprt m("*", typet(""));
//    m.move_to_operands(lcc, lc);
//
////    cast_up(function, m);
//    exprt t("+", typet(""));
//    t.move_to_operands(function, m);
//    function = t;
//  }

  // add a constant term
  symbol_exprt const_sym("termination::constant", signedbv_typet(2));
  exprt cc=coefficient(const_sym);

//  cast_up(function, cc);
  exprt t2("+", typet(""));
  t2.move_to_operands(function, cc);
  function=t2;
      
  contextt context;
  ansi_c_parse_treet pt;
  rankfunction_typecheckt typecheck(pt, context, ns, *message_handler);

  try
  {
    typecheck.typecheck_expr(function);
  }
  catch (...)
  {
    throw "TC ERROR";
  }
  

  exprt pre_function = function;
  replace_expr(pre_replace_map, pre_function);

  // save the relation for later
  rank_relation = binary_relation_exprt(function, "<", pre_function);
  
  // base_type(rank_relation, ns);

  toplevel_and.rhs()=not_exprt(rank_relation);

  return toplevel_and;
}