/* FUNCTION: Typechecker for terms and formulas
   *
   * TypeChecker: Assumes that the immediate Children of the input
   * ASTNode have been typechecked. This function is suitable in
   * scenarios like where you are building the ASTNode Tree, and you
   * typecheck as you go along. It is not suitable as a general
   * typechecker.
   *
   * If this returns, this ALWAYS returns true. If there is an error it
   * will call FatalError() and abort.
   */
  bool BVTypeCheck(const ASTNode& n)
  {
    Kind k = n.GetKind();
    //The children of bitvector terms are in turn bitvectors.
    const ASTVec& v = n.GetChildren();
    if (is_Term_kind(k))
      {
        switch (k)
          {
          case BVCONST:
            if (BITVECTOR_TYPE != n.GetType())
              FatalError("BVTypeCheck: The term t does not typecheck, where t = \n", n);
            break;
          case SYMBOL:
            return true;
          case ITE:
  			if (n.Degree() != 3)
  				FatalError("BVTypeCheck: should have exactly 3 args\n", n);
        	if (BOOLEAN_TYPE != n[0].GetType() || (n[1].GetType() != n[2].GetType()))
              FatalError("BVTypeCheck: The term t does not typecheck, where t = \n", n);
            if (n[1].GetValueWidth() != n[2].GetValueWidth())
              FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n", n);
            if (n[1].GetIndexWidth() != n[2].GetIndexWidth())
              FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n", n);
            break;
          case READ:
            if (n.GetChildren().size() !=2)
              FatalError("2 params to read.");
            if (n[0].GetIndexWidth() != n[1].GetValueWidth())
              {
                cerr << "Length of indexwidth of array: " << n[0] << " is : " << n[0].GetIndexWidth() << endl;
                cerr << "Length of the actual index is: " << n[1] << " is : " << n[1].GetValueWidth() << endl;
                FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n", n);
              }
            if (ARRAY_TYPE != n[0].GetType())
              FatalError("First parameter to read should be an array", n[0]);
            if (BITVECTOR_TYPE != n[1].GetType())
              FatalError("Second parameter to read should be a bitvector", n[1]);
            break;
          case WRITE:
            if (n.GetChildren().size() !=3)
              FatalError("3 params to write.");
            if (n[0].GetIndexWidth() != n[1].GetValueWidth())
              FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n", n);
            if (n[0].GetValueWidth() != n[2].GetValueWidth())
              FatalError("BVTypeCheck: valuewidth of array != length of actual value in the term t = \n", n);
            if (ARRAY_TYPE != n[0].GetType())
              FatalError("First parameter to read should be an array", n[0]);
            if (BITVECTOR_TYPE != n[1].GetType())
              FatalError("Second parameter to read should be a bitvector", n[1]);
            if (BITVECTOR_TYPE != n[2].GetType())
              FatalError("Third parameter to read should be a bitvector", n[2]);

            break;

          case BVDIV:
          case BVMOD:
          case BVSUB:

          case SBVDIV:
          case SBVREM:
          case SBVMOD:

          case BVLEFTSHIFT:
          case BVRIGHTSHIFT:
          case BVSRSHIFT:
          case BVVARSHIFT:
        	  if (n.Degree() != 2)
        		  FatalError("BVTypeCheck: should have exactly 2 args\n", n);
        	  // run on.
          case BVOR:
          case BVAND:
          case BVXOR:
          case BVNOR:
          case BVNAND:
          case BVXNOR:

          case BVPLUS:
          case BVMULT:
            {
              if (!(v.size() >= 2))
                FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must have at least two arguments\n", n);
              unsigned int width = n.GetValueWidth();
              for (ASTVec::const_iterator it = v.begin(), itend = v.end(); it != itend; it++)
                {
                  if (width != it->GetValueWidth())
                    {
                      cerr << "BVTypeCheck:Operands of bitwise-Booleans and BV arith operators must be of equal length\n";
                      cerr << n << endl;
                      cerr << "width of term:" << width << endl;
                      cerr << "width of offending operand:" << it->GetValueWidth() << endl;
                      FatalError("BVTypeCheck:Offending operand:\n", *it);
                    }
                  if (BITVECTOR_TYPE != it->GetType())
                    FatalError("BVTypeCheck: ChildNodes of bitvector-terms must be bitvectors\n", n);
                }
              break;
            }
          case BVSX:
          case BVZX:
			//in BVSX(n[0],len), the length of the BVSX term must be
			//greater than the length of n[0]
			if (n[0].GetValueWidth() > n.GetValueWidth()) {
				FatalError(
						"BVTypeCheck: BV[SZ]X(t,bv[sz]x_len) : length of 't' must be <= bv[sz]x_len\n",
						n);
			}
			if ((v.size() != 2))
				FatalError(
						"BVTypeCheck:BV[SZ]X must have two arguments. The second is the new width\n",
						n);
			break;

		case BVCONCAT:
			checkChildrenAreBV(v, n);
			if (n.Degree() != 2)
				FatalError("BVTypeCheck: should have exactly 2 args\n", n);
			if (n.GetValueWidth() != n[0].GetValueWidth()
					+ n[1].GetValueWidth())
				FatalError("BVTypeCheck:BVCONCAT: lengths do not add up\n", n);
			break;
		case BVUMINUS:
		case BVNEG:
			checkChildrenAreBV(v, n);
			if (n.Degree() != 1)
				FatalError("BVTypeCheck: should have exactly 1 args\n", n);
			break;
		case BVEXTRACT:
			checkChildrenAreBV(v, n);
			if (n.Degree() != 3)
				FatalError("BVTypeCheck: should have exactly 3 args\n", n);
			if (!(BVCONST == n[1].GetKind() && BVCONST == n[2].GetKind()))
				FatalError("BVTypeCheck: indices should be BVCONST\n", n);
			if (n.GetValueWidth() != n[1].GetUnsignedConst()
					- n[2].GetUnsignedConst() + 1)
				FatalError("BVTypeCheck: length mismatch\n", n);
			if (n[1].GetUnsignedConst() >= n[0].GetValueWidth())
				FatalError(
						"BVTypeCheck: Top index of select is greater or equal to the bitwidth.\n",
						n);
			break;
		default:
			cerr << _kind_names[k];
			FatalError("No type checking for type");
			break;
		}
      }
    else
      {
        if (!(is_Form_kind(k) && BOOLEAN_TYPE == n.GetType()))
          FatalError("BVTypeCheck: not a formula:", n);
        switch (k)
          {
          case TRUE:
          case FALSE:
          case SYMBOL:
            return true;
          case BOOLEXTRACT:
            checkChildrenAreBV(v, n);
            if (n.Degree() != 2)
              FatalError("BVTypeCheck: should have exactly 2 args\n", n);
            if (!(BVCONST == n[1].GetKind()))
              FatalError("BVTypeCheck: index should be BVCONST\n", n);
            if (n[1].GetUnsignedConst() >= n[0].GetValueWidth())
              FatalError("BVTypeCheck: index is greater or equal to the bitwidth.\n", n);
            break;
          case PARAMBOOL:
            if(2 != n.Degree())
              FatalError("BVTypeCheck: PARAMBOOL formula can have exactly two childNodes", n);
            break;
          case EQ:
  			if (n.Degree() != 2)
  				FatalError("BVTypeCheck: should have exactly 2 args\n", n);
        	if (!(n[0].GetValueWidth() == n[1].GetValueWidth() && n[0].GetIndexWidth() == n[1].GetIndexWidth()))
              {
                cerr << "valuewidth of lhs of EQ: " << n[0].GetValueWidth() << endl;
                cerr << "valuewidth of rhs of EQ: " << n[1].GetValueWidth() << endl;
                cerr << "indexwidth of lhs of EQ: " << n[0].GetIndexWidth() << endl;
                cerr << "indexwidth of rhs of EQ: " << n[1].GetIndexWidth() << endl;
                FatalError("BVTypeCheck: terms in atomic formulas must be of equal length", n);
              }
            break;
          case BVLT:
          case BVLE:
          case BVGT:
          case BVGE:
          case BVSLT:
          case BVSLE:
          case BVSGT:
          case BVSGE:
  			if (n.Degree() != 2)
  				FatalError("BVTypeCheck: should have exactly 2 args\n", n);
            if (BITVECTOR_TYPE != n[0].GetType() && BITVECTOR_TYPE != n[1].GetType())
              FatalError("BVTypeCheck: terms in atomic formulas must be bitvectors", n);
            if (n[0].GetValueWidth() != n[1].GetValueWidth())
              FatalError("BVTypeCheck: terms in atomic formulas must be of equal length", n);
            if (n[0].GetIndexWidth() != n[1].GetIndexWidth())
              FatalError("BVTypeCheck: terms in atomic formulas must be of equal length", n);
            break;
          case NOT:
            if (1 != n.Degree())
              FatalError("BVTypeCheck: NOT formula can have exactly one childNode", n);
            break;
          case AND:
          case OR:
          case XOR:
          case NAND:
          case NOR:
            if (2 > n.Degree())
              FatalError("BVTypeCheck: AND/OR/XOR/NAND/NOR: must have atleast 2 ChildNodes", n);
            break;
          case IFF:
          case IMPLIES:
            if (2 != n.Degree())
              FatalError("BVTypeCheck:IFF/IMPLIES must have exactly 2 ChildNodes", n);
            break;
          case ITE:
            if (3 != n.Degree())
              FatalError("BVTypeCheck:ITE must have exactly 3 ChildNodes", n);
            break;
          default:
            FatalError("BVTypeCheck: Unrecognized kind: ");
            break;
          }
      }
    return true;
  } //End of TypeCheck function
Exemple #2
0
bool BVTypeCheck_term_kind(const ASTNode& n, const Kind& k)
{
  // The children of bitvector terms are in turn bitvectors.
  const ASTVec& v = n.GetChildren();

  switch (k)
  {
    case BVCONST:
      if (BITVECTOR_TYPE != n.GetType())
        FatalError("BVTypeCheck: The term t does not typecheck, where t = \n",
                   n);
      break;

    case SYMBOL:
      return true;

    case ITE:
      if (n.Degree() != 3)
        FatalError("BVTypeCheck: should have exactly 3 args\n", n);
      if (BOOLEAN_TYPE != n[0].GetType() ||
          (n[1].GetType() != n[2].GetType()))
        FatalError("BVTypeCheck: The term t does not typecheck, where t = \n",
                   n);
      if (n[1].GetValueWidth() != n[2].GetValueWidth())
        FatalError("BVTypeCheck: length of THENbranch != length of "
                   "ELSEbranch in the term t = \n",
                   n);
      if (n[1].GetIndexWidth() != n[2].GetIndexWidth())
        FatalError("BVTypeCheck: length of THENbranch != length of "
                   "ELSEbranch in the term t = \n",
                   n);
      break;

    case READ:
      if (n.GetChildren().size() != 2)
        FatalError("2 params to read.");
      if (n[0].GetIndexWidth() != n[1].GetValueWidth())
      {
        cerr << "Length of indexwidth of array: " << n[0]
             << " is : " << n[0].GetIndexWidth() << endl;
        cerr << "Length of the actual index is: " << n[1]
             << " is : " << n[1].GetValueWidth() << endl;
        FatalError("BVTypeCheck: length of indexwidth of array != length of "
                   "actual index in the term t = \n",
                   n);
      }
      if (ARRAY_TYPE != n[0].GetType())
        FatalError("First parameter to read should be an array", n[0]);
      if (BITVECTOR_TYPE != n[1].GetType())
        FatalError("Second parameter to read should be a bitvector", n[1]);
      break;

    case WRITE:
      if (n.GetChildren().size() != 3)
        FatalError("3 params to write.");
      if (n[0].GetIndexWidth() != n[1].GetValueWidth())
        FatalError("BVTypeCheck: length of indexwidth of array != length of "
                   "actual index in the term t = \n",
                   n);
      if (n[0].GetValueWidth() != n[2].GetValueWidth())
        FatalError("BVTypeCheck: valuewidth of array != length of actual "
                   "value in the term t = \n",
                   n);
      if (ARRAY_TYPE != n[0].GetType())
        FatalError("First parameter to read should be an array", n[0]);
      if (BITVECTOR_TYPE != n[1].GetType())
        FatalError("Second parameter to read should be a bitvector", n[1]);
      if (BITVECTOR_TYPE != n[2].GetType())
        FatalError("Third parameter to read should be a bitvector", n[2]);
      break;

    case BVDIV:
    case BVMOD:
    case BVSUB:

    case SBVDIV:
    case SBVREM:
    case SBVMOD:

    case BVLEFTSHIFT:
    case BVRIGHTSHIFT:
    case BVSRSHIFT:
    case BVVARSHIFT:
      if (n.Degree() != 2)
        FatalError("BVTypeCheck: should have exactly 2 args\n", n);
    // run on.
    case BVOR:
    case BVAND:
    case BVXOR:
    case BVNOR:
    case BVNAND:
    case BVXNOR:

    case BVPLUS:
    case BVMULT:
    {
      if (!(v.size() >= 2))
        FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must "
                   "have at least two arguments\n",n);

      unsigned int width = n.GetValueWidth();
      for (ASTVec::const_iterator it = v.begin(), itend = v.end();
           it != itend; it++)
      {
        if (width != it->GetValueWidth())
        {
          cerr << "BVTypeCheck:Operands of bitwise-Booleans and BV arith "
                  "operators must be of equal length\n";
          cerr << n << endl;
          cerr << "width of term:" << width << endl;
          cerr << "width of offending operand:" << it->GetValueWidth()
               << endl;
          FatalError("BVTypeCheck:Offending operand:\n", *it);
        }
        if (BITVECTOR_TYPE != it->GetType())
          FatalError("BVTypeCheck: ChildNodes of bitvector-terms must be "
                     "bitvectors\n", n);
      }
      break;
    }
    case BVSX:
    case BVZX:
      // in BVSX(n[0],len), the length of the BVSX term must be
      // greater than the length of n[0]
      if (n[0].GetValueWidth() > n.GetValueWidth())
      {
        FatalError("BVTypeCheck: BV[SZ]X(t,bv[sz]x_len) : length of 't' must "
                   "be <= bv[sz]x_len\n", n);
      }
      if ((v.size() != 2))
        FatalError("BVTypeCheck:BV[SZ]X must have two arguments. The second "
                   "is the new width\n", n);
      break;

    case BVCONCAT:
      checkChildrenAreBV(v, n);
      if (n.Degree() != 2)
        FatalError("BVTypeCheck: should have exactly 2 args\n", n);
      if (n.GetValueWidth() != n[0].GetValueWidth() + n[1].GetValueWidth())
        FatalError("BVTypeCheck:BVCONCAT: lengths do not add up\n", n);
      break;

    case BVUMINUS:
    case BVNEG:
      checkChildrenAreBV(v, n);
      if (n.Degree() != 1)
        FatalError("BVTypeCheck: should have exactly 1 args\n", n);
      if (n.GetValueWidth() != n[0].GetValueWidth())
        FatalError("BVTypeCheck: should have same value width\n", n);
      break;

    case BVEXTRACT:
      checkChildrenAreBV(v, n);
      if (n.Degree() != 3)
        FatalError("BVTypeCheck: should have exactly 3 args\n", n);
      if (!(BVCONST == n[1].GetKind() && BVCONST == n[2].GetKind()))
        FatalError("BVTypeCheck: indices should be BVCONST\n", n);
      if (n.GetValueWidth() !=
          n[1].GetUnsignedConst() - n[2].GetUnsignedConst() + 1)
        FatalError("BVTypeCheck: length mismatch\n", n);
      if (n[1].GetUnsignedConst() >= n[0].GetValueWidth())
        FatalError("BVTypeCheck: Top index of select is greater or equal to "
                   "the bitwidth.\n",
                   n);
      break;

    default:
      cerr << _kind_names[k];
      FatalError("No type checking for type");
      break;
  }
  return true;
}
Exemple #3
0
bool BVTypeCheck_nonterm_kind(const ASTNode& n, const Kind& k)
{
  // The children of bitvector terms are in turn bitvectors.
  const ASTVec& v = n.GetChildren();

  if (!(is_Form_kind(k) && BOOLEAN_TYPE == n.GetType()))
    FatalError("BVTypeCheck: not a formula:", n);

  switch (k)
  {
    case TRUE:
    case FALSE:
    case SYMBOL:
      return true;

    case BOOLEXTRACT:
      checkChildrenAreBV(v, n);

      if (n.Degree() != 2)
        FatalError("BVTypeCheck: should have exactly 2 args\n", n);
      if (!(BVCONST == n[1].GetKind()))
        FatalError("BVTypeCheck: index should be BVCONST\n", n);
      if (n[1].GetUnsignedConst() >= n[0].GetValueWidth())
      {
        FatalError(
            "BVTypeCheck: index is greater or equal to the bitwidth.\n", n);
      }
      break;

    case PARAMBOOL:
      if (2 != n.Degree())
      {
        FatalError(
            "BVTypeCheck: PARAMBOOL formula can have exactly two childNodes",
            n);
      }
      break;

    case EQ:
      if (n.Degree() != 2)
        FatalError("BVTypeCheck: should have exactly 2 args\n", n);

      if (!(n[0].GetValueWidth() == n[1].GetValueWidth() &&
            n[0].GetIndexWidth() == n[1].GetIndexWidth()))
      {
        cerr << "valuewidth of lhs of EQ: " << n[0].GetValueWidth() << endl;
        cerr << "valuewidth of rhs of EQ: " << n[1].GetValueWidth() << endl;
        cerr << "indexwidth of lhs of EQ: " << n[0].GetIndexWidth() << endl;
        cerr << "indexwidth of rhs of EQ: " << n[1].GetIndexWidth() << endl;
        FatalError(
            "BVTypeCheck: terms in atomic formulas must be of equal length",
            n);
      }
      break;

    case BVLT:
    case BVLE:
    case BVGT:
    case BVGE:
    case BVSLT:
    case BVSLE:
    case BVSGT:
    case BVSGE:
      if (n.Degree() != 2)
        FatalError("BVTypeCheck: should have exactly 2 args\n", n);
      if (BITVECTOR_TYPE != n[0].GetType() &&
          BITVECTOR_TYPE != n[1].GetType())
      {
        FatalError("BVTypeCheck: terms in atomic formulas must be bitvectors"
                   ,n);
      }
      if (n[0].GetValueWidth() != n[1].GetValueWidth())
        FatalError(
            "BVTypeCheck: terms in atomic formulas must be of equal length",
            n);
      if (n[0].GetIndexWidth() != n[1].GetIndexWidth())
      {
        FatalError(
            "BVTypeCheck: terms in atomic formulas must be of equal length",
            n);
      }
      break;

    case NOT:
      if (1 != n.Degree())
      {
        FatalError("BVTypeCheck: NOT formula can have exactly one childNode",
                   n);
      }
      break;

    case AND:
    case OR:
    case XOR:
    case NAND:
    case NOR:
      if (2 > n.Degree())
      {
        FatalError("BVTypeCheck: AND/OR/XOR/NAND/NOR: must have atleast 2 "
                   "ChildNodes",
                   n);
      }
      break;

    case IFF:
    case IMPLIES:
      if (2 != n.Degree())
      {
        FatalError("BVTypeCheck:IFF/IMPLIES must have exactly 2 ChildNodes",
                   n);
      }
      break;

    case ITE:
      if (3 != n.Degree())
        FatalError("BVTypeCheck:ITE must have exactly 3 ChildNodes", n);
      break;

    default:
      FatalError("BVTypeCheck: Unrecognized kind: ");
      break;
  }
  return true;
}
  void SMTLIB2_Print1(ostream& os, const ASTNode n, int indentation, bool letize)
  {
    //os << spaces(indentation);
    //os << endl << spaces(indentation);
    if (!n.IsDefined())
      {
        FatalError("<undefined>");
        return;
      }

    //if this node is present in the letvar Map, then print the letvar
    //this is to print letvars for shared subterms inside the printing
    //of "(LET v0 = term1, v1=term1@term2,...
	if ((NodeLetVarMap1.find(n) != NodeLetVarMap1.end()) && !letize)
      {
		SMTLIB2_Print1(os, (NodeLetVarMap1[n]), indentation, letize);
        return;
      }

    //this is to print letvars for shared subterms inside the actual
    //term to be printed
	if ((NodeLetVarMap.find(n) != NodeLetVarMap.end()) && letize)
      {
		SMTLIB2_Print1(os, (NodeLetVarMap[n]), indentation, letize);
        return;
      }

    //otherwise print it normally
	const Kind kind = n.GetKind();
    const ASTVec &c = n.GetChildren();
    switch (kind)
      {
      case BITVECTOR:
      case BVCONST:
    	  outputBitVecSMTLIB2(n, os);
        break;
      case SYMBOL:
        os << "|";
        n.nodeprint(os);
        os << "|";
        break;
      case FALSE:
        os << "false";
        break;
      case NAND: // No NAND, NOR in smtlib format.
      case NOR:
    	  assert(c.size() ==2);
    	  os << "(" << "not ";
    	  if (NAND == kind )
    		  os << "(" << "and ";
    	  else
    		  os << "(" << "or ";
    	  SMTLIB2_Print1(os, c[0], 0, letize);
    	  os << " " ;
    	  SMTLIB2_Print1(os, c[1], 0, letize);
    	  os << "))";
    	  break;
      case TRUE:
        os << "true";
        break;
      case BVSX:
      case BVZX:
        {
          unsigned int amount = c[1].GetUnsignedConst();
          if (BVZX == kind)
            os << "((_ zero_extend ";
          else
            os << "((_ sign_extend ";

          os << (amount - c[0].GetValueWidth()) << ") ";
          SMTLIB2_Print1(os, c[0], indentation, letize);
          os << ")";
        }
        break;
      case BVEXTRACT:
        {
          unsigned int upper = c[1].GetUnsignedConst();
          unsigned int lower = c[2].GetUnsignedConst();
          assert(upper >= lower);
          os << "((_ extract " << upper << " " << lower << ") ";
          SMTLIB2_Print1(os, c[0], indentation, letize);
          os << ")";
        }
        break;
  	default:
  	{
  	    if ((kind == AND  || kind == OR|| kind == XOR) && n.Degree() == 1)
  	    {
  	    	FatalError("Wrong number of arguments to operation (must be >1).", n);
  	    }

  		// SMT-LIB only allows these functions to have two parameters.
  		if ((kind == AND  || kind == OR|| kind == XOR || BVPLUS == kind || kind == BVOR || kind == BVAND)  && n.Degree() > 2)
  		{
  			string close = "";

  			for (long int i =0; i < (long int)c.size()-1; i++)
  			{
  				os << "(" << functionToSMTLIBName(kind,false);
  				os << " ";
  				SMTLIB2_Print1(os, c[i], 0, letize);
  				os << " ";
  				close += ")";
  			}
  			SMTLIB2_Print1(os, c[c.size()-1], 0, letize);
  			os << close;
  		}
  		else
  		{
  			os << "(" << functionToSMTLIBName(kind,false);

  			ASTVec::const_iterator iend = c.end();
  			for (ASTVec::const_iterator i = c.begin(); i != iend; i++)
  			{
  				os << " ";
  				SMTLIB2_Print1(os, *i, 0, letize);
  			}

  			os << ")";
  		}
  	}
      }
  }
Exemple #5
0
string Bench_Print1(ostream &os, const ASTNode& n,
		map<ASTNode, string> *alreadyOutput)
{

	assert(((n.GetKind() == SYMBOL) || (n.GetKind() == BVCONST) || n.GetValueWidth() <= 1));
	assert(!n.IsNull());

	map<ASTNode, string>::iterator it;
	if ((it = alreadyOutput->find(n)) != alreadyOutput->end())
		return it->second;

	if (n.GetKind() == BVCONST)
	{
		(*alreadyOutput)[n] = bvconstToString(n);
		return (*alreadyOutput)[n];
	}

	if (n.GetKind() == SYMBOL)
	{
		(*alreadyOutput)[n] = symbolToString(n);
		return (*alreadyOutput)[n];
	}

	if (n.GetKind() == TRUE)
		{
		return "vdd";
		}

	if (n.GetKind() == FALSE)
		{
		return "gnd";
		}

	if (n.GetKind() == BVGETBIT)
	{
		assert(n[1].GetKind() == BVCONST);
		std::stringstream nn;
		nn << Bench_Print1(os, n[0], alreadyOutput) << "_" << Bench_Print1(os, n[1], alreadyOutput);
		(*alreadyOutput)[n] = nn.str();
		return (*alreadyOutput)[n];
	}

	std::stringstream nodeNameSS;
	nodeNameSS << "n" << n.GetNodeNum();

	string thisNode = nodeNameSS.str();
	(*alreadyOutput)[n] = thisNode;

	assert(n.Degree() > 0);
	std::stringstream output;

	// The bench format doesn't accept propositional ITEs.
	if (n.GetKind() == ITE)
	{
		assert(n.Degree() == 3);
		string p = Bench_Print1(os, n[0], alreadyOutput);
		string p1 = Bench_Print1(os, n[1], alreadyOutput);
		string p2 = Bench_Print1(os, n[2], alreadyOutput);

		os << thisNode << "_1 = AND(" << p << "," << p1 << ")" << endl;
		os << thisNode << "_2" << " = NOT(" << p << ")," << endl;
		os << thisNode << "_3" << " = AND(" << thisNode << "_2"
				<< "," << p2 << ")" << endl;
		os << thisNode << "=" << "OR(," << thisNode << "_1" << ","
				<< thisNode << "_3)" << endl;
	}
	else
	{
		if (n.Degree() > 2)
		{
			assert(n.GetKind() == AND || n.GetKind() == XOR || n.GetKind() == OR); // must be associative.
			std::deque<string> names;

			for (unsigned i = 0; i < n.Degree(); i++)
				names.push_back(Bench_Print1(os, n[i], alreadyOutput));

			int id = 0;

			while (names.size() > 2)
			{
				string a = names.front();
				names.pop_front();

				string b = names.front();
				names.pop_front();

				std::stringstream thisName;
				thisName << thisNode << "___" << id++;

				output << thisName.str() << "=" << name(n.GetKind()) << "("
						<< a << "," << b << ")" << endl;

				names.push_back(thisName.str());
			}

			assert(names.size() == 2);
			// last two now.

			string a = names.front();
			names.pop_front();
			string b = names.front();
			names.pop_front();

			output << thisNode << "=" << name(n.GetKind()) << "(" << a
					<< "," << b << ")" << endl;
			os << output.str();
		}
		else
		{
			output << thisNode << "=" << name(n.GetKind()) << "(";
			for (unsigned i = 0; i < n.Degree(); i++)
			{
				if (i >= 1)
					output << " , ";
				output << Bench_Print1(os, n[i], alreadyOutput);

			}
			os << output.str() << ")" << endl;
		}
	}
	return thisNode;
}
Exemple #6
0
ASTNode ArrayTransformer::TransformTerm(const ASTNode& term)
{
  assert(TransformMap != NULL);

  const Kind k = term.GetKind();
  if (!is_Term_kind(k))
    FatalError("TransformTerm: Illegal kind: You have input a nonterm:", term,
               k);
  ASTNodeMap::const_iterator iter;
  if ((iter = TransformMap->find(term)) != TransformMap->end())
    return iter->second;

  ASTNode result;
  switch (k)
  {
    case SYMBOL:
    case BVCONST:
    {
      result = term;
      break;
    }
    case WRITE:
      FatalError("TransformTerm: this kind is not supported", term);
      break;
    case READ:
      result = TransformArrayRead(term);
      break;
    case ITE:
    {
      ASTNode cond = term[0];
      ASTNode thn = term[1];
      ASTNode els = term[2];
      cond = TransformFormula(cond);
      if (ASTTrue == cond)
        result = TransformTerm(thn);
      else if (ASTFalse == cond)
        result = TransformTerm(els);
      else
      {
        thn = TransformTerm(thn);
        els = TransformTerm(els);
        if (bm->UserFlags.optimize_flag)
          result = simp->CreateSimplifiedTermITE(cond, thn, els);
        else
          result = nf->CreateTerm(ITE, thn.GetValueWidth(), cond, thn, els);
      }
      assert(result.GetIndexWidth() == term.GetIndexWidth());
      break;
    }
    default:
    {
      const ASTVec& c = term.GetChildren();
      ASTVec::const_iterator it = c.begin();
      ASTVec::const_iterator itend = c.end();
      const unsigned width = term.GetValueWidth();
      const unsigned indexwidth = term.GetIndexWidth();
      ASTVec o;
      o.reserve(c.size());
      for (; it != itend; it++)
      {
        o.push_back(TransformTerm(*it));
      }

      if (c != o)
      {
        result = nf->CreateArrayTerm(k, indexwidth, width, o);
      }
      else
        result = term;
    }
    break;
  }

  if (term.Degree() > 0)
    (*TransformMap)[term] = result;
  if (term.GetValueWidth() != result.GetValueWidth())
    FatalError("TransformTerm: "
               "result and input terms are of different length",
               result);
  if (term.GetIndexWidth() != result.GetIndexWidth())
  {
    std::cerr << "TransformTerm: input term is : " << term << std::endl;
    FatalError("TransformTerm: "
               "result & input terms have different index length",
               result);
  }
  return result;
} 
// This doesn't rewrite changes through properly so needs to have a substitution
// applied to its output.
ASTNode PropagateEqualities::propagate(const ASTNode& a, ArrayTransformer* at)
{
  ASTNode output;
  // if the variable has been solved for, then simply return it
  if (simp->InsideSubstitutionMap(a, output))
    return output;

  if (!alreadyVisited.insert(a.GetNodeNum()).second)
  {
    return a;
  }

  output = a;

  // traverse a and populate the SubstitutionMap
  const Kind k = a.GetKind();
  if (SYMBOL == k && BOOLEAN_TYPE == a.GetType())
  {
    bool updated = simp->UpdateSubstitutionMap(a, ASTTrue);
    output = updated ? ASTTrue : a;
  }
  else if (NOT == k)
  {
    bool updated = searchXOR(a[0], ASTFalse);
    output = updated ? ASTTrue : a;
  }
  else if (IFF == k || EQ == k)
  {
    const ASTVec& c = a.GetChildren();

    if (c[0] == c[1])
      return ASTTrue;

    bool updated = simp->UpdateSubstitutionMap(c[0], c[1]);

    if (updated)
    {
      // fill the arrayname readindices vector if e0 is a
      // READ(Arr,index) and index is a BVCONST
      int to;
      if ((to = TermOrder(c[0], c[1])) == 1 && c[0].GetKind() == READ)
        at->FillUp_ArrReadIndex_Vec(c[0], c[1]);
      else if (to == -1 && c[1].GetKind() == READ)
        at->FillUp_ArrReadIndex_Vec(c[1], c[0]);
    }

    if (!updated)
      updated = searchTerm(c[0], c[1]);

    if (!updated)
      updated = searchTerm(c[1], c[0]);

    output = updated ? ASTTrue : a;
  }
  else if (XOR == k)
  {
    bool updated = searchXOR(a, ASTTrue);
    output = updated ? ASTTrue : a;

    if (updated)
      return output;

// The below block should be subsumed by the searchXOR function which
// generalises it.
// So the below block should never do anything..
#ifndef NDEBUG
    if (a.Degree() != 2)
      return output;

    int to = TermOrder(a[0], a[1]);
    if (0 == to)
    {
      if (a[0].GetKind() == NOT && a[0][0].GetKind() == EQ &&
          a[0][0][0].GetValueWidth() == 1 && a[0][0][1].GetKind() == SYMBOL)
      {
        // (XOR (NOT(= (1 v)))  ... )
        const ASTNode& symbol = a[0][0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[1], a[0][0][0], nf->CreateTerm(BVNEG, 1, a[0][0][0]));

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[1].GetKind() == NOT && a[1][0].GetKind() == EQ &&
               a[1][0][0].GetValueWidth() == 1 &&
               a[1][0][1].GetKind() == SYMBOL)
      {
        const ASTNode& symbol = a[1][0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[0], a[1][0][0], nf->CreateTerm(BVNEG, 1, a[1][0][0]));

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[0].GetKind() == EQ && a[0][0].GetValueWidth() == 1 &&
               a[0][1].GetKind() == SYMBOL)
      {
        // XOR ((= 1 v) ... )

        const ASTNode& symbol = a[0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[1], nf->CreateTerm(BVNEG, 1, a[0][0]), a[0][0]);

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[1].GetKind() == EQ && a[1][0].GetValueWidth() == 1 &&
               a[1][1].GetKind() == SYMBOL)
      {
        const ASTNode& symbol = a[1][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[0], nf->CreateTerm(BVNEG, 1, a[1][0]), a[1][0]);

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else
        return output;
    }
    else
    {
      ASTNode symbol, rhs;
      if (to == 1)
      {
        symbol = a[0];
        rhs = a[1];
      }
      else
      {
        symbol = a[1];
        rhs = a[0];
      }

      assert(symbol.GetKind() == SYMBOL);

      if (simp->UpdateSolverMap(symbol, nf->CreateNode(NOT, rhs)))
      {
        assert(false);
        output = ASTTrue;
      }
    }
#endif
  }
  else if (AND == k)
  {
    const ASTVec& c = a.GetChildren();
    ASTVec o;
    o.reserve(c.size());

    for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
         it++)
    {
      if (always_true)
        simp->UpdateAlwaysTrueFormSet(*it);
      ASTNode aaa = propagate(*it, at);

      if (ASTTrue != aaa)
      {
        if (ASTFalse == aaa)
          return ASTFalse;
        else
          o.push_back(aaa);
      }
    }
    if (o.size() == 0)
      output = ASTTrue;
    else if (o.size() == 1)
      output = o[0];
    else if (o != c)
      output = nf->CreateNode(AND, o);
    else
      output = a;
  }

  return output;
}
Exemple #8
0
/********************************************************
 * TransformFormula()
 *
 * Get rid of DIV/MODs, ARRAY read/writes, FOR constructs
 ********************************************************/
ASTNode ArrayTransformer::TransformFormula(const ASTNode& simpleForm)
{
  assert(TransformMap != NULL);

  const Kind k = simpleForm.GetKind();
  if (!(is_Form_kind(k) && BOOLEAN_TYPE == simpleForm.GetType()))
  {
    // FIXME: "You have inputted a NON-formula"?
    FatalError("TransformFormula:"
               "You have input a NON-formula",
               simpleForm);
  }

  ASTNodeMap::const_iterator iter;
  if ((iter = TransformMap->find(simpleForm)) != TransformMap->end())
    return iter->second;

  ASTNode result;

  switch (k)
  {
    case TRUE:
    case FALSE:
    {
      result = simpleForm;
      break;
    }
    case NOT:
    {
      ASTVec c;
      c.push_back(TransformFormula(simpleForm[0]));
      result = nf->CreateNode(NOT, c);
      break;
    }
    case BOOLEXTRACT:
    {
      ASTVec c;
      c.push_back(TransformTerm(simpleForm[0]));
      c.push_back(simpleForm[1]);
      result = nf->CreateNode(BOOLEXTRACT, c);
      break;
    }
    case BVLT:
    case BVLE:
    case BVGT:
    case BVGE:
    case BVSLT:
    case BVSLE:
    case BVSGT:
    case BVSGE:
    {
      ASTVec c;
      c.push_back(TransformTerm(simpleForm[0]));
      c.push_back(TransformTerm(simpleForm[1]));
      result = nf->CreateNode(k, c);
      break;
    }
    case EQ:
    {
      ASTNode term1 = TransformTerm(simpleForm[0]);
      ASTNode term2 = TransformTerm(simpleForm[1]);
      if (bm->UserFlags.optimize_flag)
        result = simp->CreateSimplifiedEQ(term1, term2);
      else
        result = nf->CreateNode(EQ, term1, term2);
      break;
    }
    case AND: // These could shortcut. Not sure if the extra effort is
              // justified.
    case OR:
    case NAND:
    case NOR:
    case IFF:
    case XOR:
    case ITE:
    case IMPLIES:
    {
      ASTVec vec;
      vec.reserve(simpleForm.Degree());

      for (ASTVec::const_iterator it = simpleForm.begin(),
                                  itend = simpleForm.end();
           it != itend; it++)
      {
        vec.push_back(TransformFormula(*it));
      }

      result = nf->CreateNode(k, vec);
      break;
    }
    case PARAMBOOL:
    {
      // If the parameteric boolean variable is of the form
      // VAR(const), then convert it into a Boolean variable of the
      // form "VAR(const)".
      //
      // Else if the paramteric boolean variable is of the form
      // VAR(expression), then simply return it
      if (BVCONST == simpleForm[1].GetKind())
      {
        result = bm->NewParameterized_BooleanVar(simpleForm[0], simpleForm[1]);
      }
      else
      {
        result = simpleForm;
      }
      break;
    }
    default:
    {
      if (k == SYMBOL && BOOLEAN_TYPE == simpleForm.GetType())
        result = simpleForm;
      else
      {
        FatalError("TransformFormula: Illegal kind: ", ASTUndefined, k);
        std::cerr << "The input is: " << simpleForm << std::endl;
        std::cerr << "The valuewidth of input is : "
                  << simpleForm.GetValueWidth() << std::endl;
      }
      break;
    }
  }

  assert(!result.IsNull());
  if (simpleForm.Degree() > 0)
    (*TransformMap)[simpleForm] = result;
  return result;
} 
Exemple #9
0
  ASTNode ArrayTransformer::TransformTerm(const ASTNode& term)
  {
    assert(TransformMap != NULL);

    const Kind k = term.GetKind();
    if (!is_Term_kind(k))
      FatalError("TransformTerm: Illegal kind: You have input a nonterm:", 
                 term, k);
    ASTNodeMap::const_iterator iter;
    if ((iter = TransformMap->find(term)) != TransformMap->end())
      return iter->second;

    ASTNode result;
    switch (k)
      {
      case SYMBOL:
      case BVCONST:
      {
          result = term;
          break;
        }
      case WRITE:
        FatalError("TransformTerm: this kind is not supported", term);
        break;
      case READ:
        result = TransformArrayRead(term);
        break;
      case ITE:
        {
          ASTNode cond = term[0];
          ASTNode thn = term[1];
          ASTNode els = term[2];
          cond = TransformFormula(cond);
          if (ASTTrue == cond)
        	  result = TransformTerm(thn);
          else if (ASTFalse == cond)
        	  result = TransformTerm(els);
          else
          {
        	  thn = TransformTerm(thn);
        	  els = TransformTerm(els);
        	  result = simp->CreateSimplifiedTermITE(cond, thn, els);
          }
          assert(result.GetIndexWidth() ==term.GetIndexWidth());
          break;
        }
      default:
        {
          const ASTVec& c = term.GetChildren();
          ASTVec::const_iterator it = c.begin();
          ASTVec::const_iterator itend = c.end();
          const unsigned width = term.GetValueWidth();
          const unsigned indexwidth = term.GetIndexWidth();
          ASTVec o;
          o.reserve(c.size());
          for (; it != itend; it++)
            {
              o.push_back(TransformTerm(*it));
            }

          if (c!=o)
          {
        	  result = nf->CreateArrayTerm(k,indexwidth, width, o);
          }
          else
        	  result = term;

          const Kind k = result.GetKind();

          if (BVDIV == k 
              || BVMOD == k 
              || SBVDIV == k 
              || SBVREM == k 
              || SBVMOD == k)
            {

              // I had this as a reference, but that was wrong. Because
              // "result" gets over-written in the next block, result[1], may
              // get a reference count of zero, so be garbage collected.
              const ASTNode bottom = result[1];

              if (SBVDIV == result.GetKind() 
                  || SBVREM == result.GetKind() 
                  || SBVMOD == result.GetKind())
                {
                  result = TranslateSignedDivModRem(result);
                }

              if (bm->UserFlags.division_by_zero_returns_one_flag)
                {
                  // This is a difficult rule to introduce in other
                  // places because it's recursive. i.e.  result is
                  // embedded unchanged inside the result.

                  unsigned inputValueWidth = result.GetValueWidth();
                  ASTNode zero = bm->CreateZeroConst(inputValueWidth);
                  ASTNode one = bm->CreateOneConst(inputValueWidth);
                  result = 
                    nf->CreateTerm(ITE, inputValueWidth,
                                   nf->CreateNode(EQ, zero, bottom),
                                   one, result);

                  //return result;
                  if (bm->UserFlags.optimize_flag)
                      return simp->SimplifyTerm_TopLevel(result);
                  else
                  	return result;

                }
            }
        }
        break;
      }

    if (term.Degree() > 0)
      (*TransformMap)[term] = result;
    if (term.GetValueWidth() != result.GetValueWidth())
      FatalError("TransformTerm: "\
                 "result and input terms are of different length", result);
    if (term.GetIndexWidth() != result.GetIndexWidth())
      {
        cerr << "TransformTerm: input term is : " << term << endl;
        FatalError("TransformTerm: "\
                   "result & input terms have different index length", result);
      }
    return result;
  } //End of TransformTerm
Exemple #10
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
Exemple #11
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;
  }
 void
 ConstantBitPropagation::scheduleDown(const ASTNode& n)
 {
   for (int i = 0; i < n.Degree(); i++)
     workList->push(n[i]);
 }