Example #1
0
  ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
    ASTNode OutputNode;
    Kind k = t.GetKind();

    if(CheckSolverMap(t,OutputNode))
      return OutputNode;
    OutputNode = t;

    unsigned int inputwidth = t.GetValueWidth();
    unsigned int outputwidth = inputwidth;
    CBV output = NULL;

    CBV tmp0 = NULL;
    CBV tmp1 = NULL;

    //saving some typing. BVPLUS does not use these variables. if the
    //input BVPLUS has two nodes, then we want to avoid setting these
    //variables.
    if(1 == t.Degree() ){
      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
    }else if(2 == t.Degree() && k != BVPLUS ) {
      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
      tmp1 = BVConstEvaluator(t[1]).GetBVConst();
    }

    switch(k) {
    case UNDEFINED:
    case READ:
    case WRITE:
    case SYMBOL:
      FatalError("BVConstEvaluator: term is not a constant-term",t);
      break;
    case BVCONST:
      //FIXME Handle this special case better
      OutputNode = t;
      break;
    case BVNEG:{
      output = CONSTANTBV::BitVector_Create(inputwidth,true);
      CONSTANTBV::Set_Complement(output,tmp0);
      OutputNode = CreateBVConst(output,outputwidth);
      break;
    }
    case BVSX: {
      output = CONSTANTBV::BitVector_Create(inputwidth,true);
      //unsigned * out0 = BVConstEvaluator(t[0]).GetBVConst();
      unsigned t0_width = t[0].GetValueWidth();
      if(inputwidth == t0_width) {
        CONSTANTBV::BitVector_Copy(output, tmp0);
        OutputNode = CreateBVConst(output, outputwidth);    
      }
      else {
        bool topbit_sign = (CONSTANTBV::BitVector_Sign(tmp0) < 0 );

        if(topbit_sign){
          CONSTANTBV::BitVector_Fill(output);
        }
        CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, t0_width);
        OutputNode = CreateBVConst(output, outputwidth);    
      }
      break;
    }
    case BVAND: {
      output = CONSTANTBV::BitVector_Create(inputwidth,true);
      CONSTANTBV::Set_Intersection(output,tmp0,tmp1);
      OutputNode = CreateBVConst(output, outputwidth);
      break;
    }
    case BVOR: {
      output = CONSTANTBV::BitVector_Create(inputwidth,true);
      CONSTANTBV::Set_Union(output,tmp0,tmp1);
      OutputNode = CreateBVConst(output, outputwidth);
      break;
    }
    case BVXOR: {
      output = CONSTANTBV::BitVector_Create(inputwidth,true);
      CONSTANTBV::Set_ExclusiveOr(output,tmp0,tmp1);
      OutputNode = CreateBVConst(output, outputwidth);
      break;
    }
    case BVSUB: {
      output = CONSTANTBV::BitVector_Create(inputwidth,true);
      bool carry = false;
      CONSTANTBV::BitVector_sub(output,tmp0,tmp1,&carry);
      OutputNode = CreateBVConst(output, outputwidth);    
      break;
    }
    case BVUMINUS: {
      output = CONSTANTBV::BitVector_Create(inputwidth,true);
      CONSTANTBV::BitVector_Negate(output, tmp0);
      OutputNode = CreateBVConst(output, outputwidth);    
      break;
    }
    case BVEXTRACT: {
      output = CONSTANTBV::BitVector_Create(inputwidth,true);
      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
      unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
      unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
      unsigned int len = hi-low+1;

      CONSTANTBV::BitVector_Destroy(output);
      output = CONSTANTBV::BitVector_Create(len, false);
      CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, low, len);
      outputwidth = len;
      OutputNode = CreateBVConst(output, outputwidth);
      break;
    }
    //FIXME Only 2 inputs?
    case BVCONCAT: {
       output = CONSTANTBV::BitVector_Create(inputwidth,true);
      unsigned t0_width = t[0].GetValueWidth();
      unsigned t1_width = t[1].GetValueWidth();
      CONSTANTBV::BitVector_Destroy(output);
      
      output = CONSTANTBV::BitVector_Concat(tmp0, tmp1);
      outputwidth = t0_width + t1_width;
      OutputNode = CreateBVConst(output, outputwidth);
      
      break;
    }
    case BVMULT: {
       output = CONSTANTBV::BitVector_Create(inputwidth,true);
      CBV tmp = CONSTANTBV::BitVector_Create(2*inputwidth,true);
      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(tmp,tmp0,tmp1);
      
      if(0 != e) {
        BVConstEvaluatorError(e,t);
      }
      //FIXME WHAT IS MY OUTPUT???? THE SECOND HALF of tmp?
      //CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, inputwidth, inputwidth);
      CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, 0, inputwidth);
      OutputNode = CreateBVConst(output, outputwidth);
      CONSTANTBV::BitVector_Destroy(tmp);
      break;
    }
    case BVPLUS: {
       output = CONSTANTBV::BitVector_Create(inputwidth,true);
      bool carry = false;
      ASTVec c = t.GetChildren();
      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
	CBV kk = BVConstEvaluator(*it).GetBVConst();
	CONSTANTBV::BitVector_add(output,output,kk,&carry);
	carry = false;
	//CONSTANTBV::BitVector_Destroy(kk);
      }
      OutputNode = CreateBVConst(output, outputwidth);
      break;
    }
    //FIXME ANOTHER SPECIAL CASE
    case SBVDIV:
    case SBVMOD:{
      OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
      break;
    }
    case BVDIV: 
    case BVMOD: {
      CBV quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
      CBV remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
      
      // tmp0 is dividend, tmp1 is the divisor
      //All parameters to BitVector_Div_Pos must be distinct unlike BitVector_Divide
      //FIXME the contents of the second parameter to Div_Pos is destroyed
      //As tmp0 is currently the same as the copy belonging to an ASTNode t[0]
      //this must be copied.
      tmp0 = CONSTANTBV::BitVector_Clone(tmp0);      
      CONSTANTBV::ErrCode e= CONSTANTBV::BitVector_Div_Pos(quotient,tmp0,tmp1,remainder);
      CONSTANTBV::BitVector_Destroy(tmp0);
      
      if(0 != e) {
	//error printing
	if(counterexample_checking_during_refinement) {
          output = CONSTANTBV::BitVector_Create(inputwidth,true);
	  OutputNode = CreateBVConst(output, outputwidth);
	  bvdiv_exception_occured = true;
          
          //  CONSTANTBV::BitVector_Destroy(output);
	  break;
	}
	else {
	  BVConstEvaluatorError(e,t);
	}
      } //end of error printing

      //FIXME Not very standard in the current scheme
      if(BVDIV == k){
        OutputNode = CreateBVConst(quotient, outputwidth);
        CONSTANTBV::BitVector_Destroy(remainder);
      }else{
        OutputNode = CreateBVConst(remainder, outputwidth);
        CONSTANTBV::BitVector_Destroy(quotient);
      }

      break;
    }
    case ITE:
      if(ASTTrue == t[0])
	OutputNode = BVConstEvaluator(t[1]);
      else if(ASTFalse == t[0])
	OutputNode = BVConstEvaluator(t[2]);
      else
	FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t);
      break;
    case EQ: 
      if(CONSTANTBV::BitVector_equal(tmp0,tmp1))
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case NEQ:
      if(!CONSTANTBV::BitVector_equal(tmp0,tmp1))
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case BVLT:
      if(-1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1))
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case BVLE: {
      int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1);
      if(comp <= 0)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    }
    case BVGT:
      if(1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1))
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case BVGE: {
      int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1);
      if(comp >= 0)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    } 
    case BVSLT:
      if(-1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1))
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case BVSLE: {
      signed int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1);
      if(comp <= 0)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    }
    case BVSGT:
      if(1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1))
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case BVSGE: {
      int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1);
      if(comp >= 0)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    } 
    default:
      FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
      break;
    }
/*
    if(BVCONST != k){
     cerr<<inputwidth<<endl;
     cerr<<"------------------------"<<endl;
     t.LispPrint(cerr);
     cerr<<endl;
     OutputNode.LispPrint(cerr);
     cerr<<endl<<"------------------------"<<endl;
    }
*/
    UpdateSolverMap(t,OutputNode);
    //UpdateSimplifyMap(t,OutputNode,false);
    return OutputNode;
  }
Example #2
0
  //FIXME: Ideally I would like the ASTNodes to be able to operate on
  //themselves (add, sub, concat, etc.) rather than doing a
  //GetBVConst() and then do the operation externally. For now,
  //this is the fastest path to completion.
  ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
    //cerr << "inside begin bcconstevaluator: " << t << endl;

    ASTNode OutputNode;
    if(CheckSolverMap(t,OutputNode))
      return OutputNode;
    OutputNode = ASTUndefined;

    Kind k = t.GetKind();
    unsigned long long int output = 0;
    unsigned inputwidth = t.GetValueWidth();
    ASTNode t0 = ASTUndefined;
    ASTNode t1 = ASTUndefined;
    if(2 == t.Degree()) {
      t0 = BVConstEvaluator(t[0]);
      t1 = BVConstEvaluator(t[1]);
    }
    switch(k) {
    case READ:
    case UNDEFINED:
    case WRITE:
    case SYMBOL:
      cerr << t;
      FatalError("BVConstEvaluator: term is not a constant-term",t);
      break;
    case BVCONST:
      return t;
      break;
    case BVNEG:
      //compute bitwise negation in C
      output = ~(BVConstEvaluator(t[0]).GetBVConst());
      break;
    case BVSX:
      output = SXBVConst64(BVConstEvaluator(t[0]));    
      break;
    case BVAND:
      output = t0.GetBVConst() & t1.GetBVConst();
      break;
    case BVOR:
      output = t0.GetBVConst() | t1.GetBVConst();
      break;
    case BVXOR:
      output = t0.GetBVConst() ^ t1.GetBVConst();
      break;
    case BVSUB:
      output = t0.GetBVConst() - t1.GetBVConst();
      break;
    case BVUMINUS:
      output = ~(BVConstEvaluator(t[0]).GetBVConst()) + 1;
      break;
    case BVEXTRACT: {
      unsigned long long int val = BVConstEvaluator(t[0]).GetBVConst();
      unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
      unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));

      if(!(0 <= hi <= 64))
	FatalError("ConstantEvaluator: hi bit in BVEXTRACT is > 32bits",t);
      if(!(0 <= low <= hi <= 64))
	FatalError("ConstantEvaluator: low bit in BVEXTRACT is > 32bits or hi",t);

      //64 bit mask.
      unsigned long long int mask1 = 0xffffffffffffffffLL;
      mask1 >>= 64-(hi+1);
      
      //extract val[hi:0]
      val &= mask1;
      //extract val[hi:low]
      val >>= low;
      output = val;
      break;
    }
    case BVCONCAT: {
      unsigned long long int q = BVConstEvaluator(t0).GetBVConst();
      unsigned long long int r = BVConstEvaluator(t1).GetBVConst();

      unsigned int qlen = t[0].GetValueWidth();
      unsigned int rlen = t[1].GetValueWidth();
      unsigned int slen = t.GetValueWidth();
      if(!(0 <  qlen + rlen  <= 64))
	FatalError("BVConstEvaluator:"
		   "lengths of childnodes of BVCONCAT are > 64:",t);

      //64 bit mask for q
      unsigned long long int qmask = 0xffffffffffffffffLL;     
      qmask >>= 64-qlen;
      //zero the useless bits of q
      q &= qmask;

      //64 bit mask for r
      unsigned long long int rmask = 0xffffffffffffffffLL;     
      rmask >>= 64-rlen;
      //zero the useless bits of r
      r &= rmask;
      
      //concatenate
      q <<= rlen;
      q |= r;

      //64 bit mask for output s
      unsigned long long int smask = 0xffffffffffffffffLL;
      smask >>= 64-slen;
      
      //currently q has the output
      output = q;      
      output &= smask;
      break;
    }
    case BVMULT: {
      output = t0.GetBVConst() * t1.GetBVConst();

      //64 bit mask
      unsigned long long int mask = 0xffffffffffffffffLL;
      mask = mask >> (64 - inputwidth);
      output &= mask;
      break;
    }
    case BVPLUS: {
      ASTVec c = t.GetChildren();
      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
	output += BVConstEvaluator(*it).GetBVConst();

      //64 bit mask
      unsigned long long int mask = 0xffffffffffffffffLL;
      mask = mask >> (64 -inputwidth);
      output &= mask;
      break;
    }
    case SBVDIV:
    case SBVMOD: {
      output = BVConstEvaluator(TranslateSignedDivMod(t)).GetBVConst();
      break;
    }
    case BVDIV: {
      if(0 == t1.GetBVConst()) {
	//if denominator is 0 then 
	//  (if refinement is ON then output is set to 0) 
	//   (else produce a fatal error)
	if(counterexample_checking_during_refinement) {
	  output = 0;
	  bvdiv_exception_occured = true;
	  break;
	}
	else {
	  FatalError("BVConstEvaluator: divide by zero not allowed:",t);
	}
      }

      output = t0.GetBVConst() / t1.GetBVConst();
      //64 bit mask
      unsigned long long int mask = 0xffffffffffffffffLL;
      mask = mask >> (64 - inputwidth);
      output &= mask;
      break;
    }
    case BVMOD: {
      if(0 == t1.GetBVConst()) {
	//if denominator is 0 then 
	//  (if refinement is ON then output is set to 0) 
	//   (else produce a fatal error)
	if(counterexample_checking_during_refinement) {
	  output = 0;
	  bvdiv_exception_occured = true;
	  break;
	}
	else {
	  FatalError("BVConstEvaluator: divide by zero not allowed:",t);
	}
      }

      output = t0.GetBVConst() % t1.GetBVConst();
      //64 bit mask
      unsigned long long int mask = 0xffffffffffffffffLL;
      mask = mask >> (64 - inputwidth);
      output &= mask;
      break;
    }
    case ITE:
      if(ASTTrue == t[0])
	OutputNode = BVConstEvaluator(t[1]);
      else if(ASTFalse == t[0])
	OutputNode = BVConstEvaluator(t[2]);
      else
	FatalError("BVConstEvaluator:" 
		   "ITE condiional must be either TRUE or FALSE:",t);
      break;
    case EQ:
      if(t0.GetBVConst() == t1.GetBVConst())
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case NEQ:
      if(t0.GetBVConst() != t1.GetBVConst())
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
      break;
    case BVLT: {
      unsigned long long n0 = t0.GetBVConst();
      unsigned long long n1 = t1.GetBVConst();
      if(n0 < n1)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    }
    case BVLE:
      if(t0.GetBVConst() <= t1.GetBVConst())
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case BVGT:
      if(t0.GetBVConst() > t1.GetBVConst())
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case BVGE:
      if(t0.GetBVConst() >= t1.GetBVConst())
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    case BVSLT: {
      signed long long int n0 = SXBVConst64(t0);
      signed long long int n1 = SXBVConst64(t1);
      if(n0 < n1)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    }
    case BVSLE: {
      signed long long int n0 = SXBVConst64(t0);
      signed long long int n1 = SXBVConst64(t1);
      if(n0 <= n1)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    }
    case BVSGT: {   
      signed long long int n0 = SXBVConst64(t0);
      signed long long int n1 = SXBVConst64(t1);
      if(n0 > n1)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    }
    case BVSGE: {   
      signed long long int n0 = SXBVConst64(t0);
      signed long long int n1 = SXBVConst64(t1);
      if(n0 >= n1)
	OutputNode = ASTTrue;
      else
	OutputNode = ASTFalse;
      break;
    }
    default:
      FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
      break;
    }    
   
    if(ASTTrue  != OutputNode && ASTFalse != OutputNode)
      OutputNode = CreateBVConst(inputwidth, output);
    UpdateSolverMap(t,OutputNode);
    //UpdateSimplifyMap(t,OutputNode,false);
    return OutputNode;
  } //End of BVConstEvaluator
Example #3
0
ASTNode SubstitutionMap::replace(const ASTNode& n, ASTNodeMap& fromTo,
                                 ASTNodeMap& cache, NodeFactory* nf,
                                 bool stopAtArrays, bool preventInfinite)
{
  const Kind k = n.GetKind();
  if (k == BVCONST || k == TRUE || k == FALSE)
    return n;

  ASTNodeMap::const_iterator it;

  if ((it = cache.find(n)) != cache.end())
    return it->second;

  if ((it = fromTo.find(n)) != fromTo.end())
  {
    const ASTNode& r = it->second;
    assert(r.GetIndexWidth() == n.GetIndexWidth());

    if (preventInfinite)
      cache.insert(make_pair(n, r));

    ASTNode replaced =
        replace(r, fromTo, cache, nf, stopAtArrays, preventInfinite);
    if (replaced != r)
    {
      fromTo.erase(n);
      fromTo[n] = replaced;
    }

    if (preventInfinite)
      cache.erase(n);

    cache.insert(make_pair(n, replaced));
    return replaced;
  }

  // These can't be created like regular nodes are
  if (k == SYMBOL)
    return n;

  const unsigned int indexWidth = n.GetIndexWidth();
  if (stopAtArrays && indexWidth > 0) // is an array.
  {
    return n;
  }

  const ASTVec& children = n.GetChildren();
  assert(children.size() > 0);
  // Should have no leaves left here.

  ASTVec new_children;
  new_children.reserve(children.size());

  for (ASTVec::const_iterator it = children.begin(); it != children.end(); it++)
  {
    new_children.push_back(
        replace(*it, fromTo, cache, nf, stopAtArrays, preventInfinite));
  }

  assert(new_children.size() == children.size());

  // This code short-cuts if the children are the same. Nodes with the same
  // children,
  // won't have necessarily given the same node if the simplifyingNodeFactory is
  // enabled
  // now, but wasn't enabled when the node was created. Shortcutting saves lots
  // of time.
  if (new_children == children)
  {
    cache.insert(make_pair(n, n));
    return n;
  }

  ASTNode result;
  const unsigned int valueWidth = n.GetValueWidth();

  if (valueWidth == 0) // n.GetType() == BOOLEAN_TYPE
  {
    result = nf->CreateNode(k, new_children);
  }
  else
  {
    // If the index and value width aren't saved, they are reset sometimes (??)
    result = nf->CreateArrayTerm(k, indexWidth, valueWidth, new_children);
  }

  // We may have created something that should be mapped. For instance,
  // if n is READ(A, x), and the fromTo is: {x==0, READ(A,0) == 1}, then
  // by here the result will be READ(A,0). Which needs to be mapped again..
  // I hope that this makes it idempotent.

  if (fromTo.find(result) != fromTo.end())
  {
    // map n->result, if running replace() on result gives us 'n', it will not
    // infinite loop.
    // This is only currently required for the bitblast equivalence stuff.
    if (preventInfinite)
      cache.insert(make_pair(n, result));

    result = replace(result, fromTo, cache, nf, stopAtArrays, preventInfinite);
  }

  assert(result.GetValueWidth() == valueWidth);
  assert(result.GetIndexWidth() == indexWidth);

  // If there is already an "n" element in the cache, the maps semantics are to
  // ignore the next insertion.
  if (preventInfinite)
    cache.erase(n);

  cache.insert(make_pair(n, result));
  return result;
}