Example #1
0
void CNFMgr::convertFormulaToCNFNegOR(const ASTNode& varphi,
                                      ClauseList* defs)
{
    //****************************************
    // (neg) OR ~> UNION NOT
    //****************************************
    ASTVec::const_iterator it = varphi.GetChildren().begin();
    convertFormulaToCNF(*it, defs);
    ClauseList* psi = ClauseList::COPY(*(info[*it]->clausesneg));
    reduceMemoryFootprintNeg(*it);
    for (it++; it != varphi.GetChildren().end(); it++) {
        convertFormulaToCNF(*it, defs);
        CNFInfo* x = info[*it];

        if (sharesNeg(*x) != 1) {
            ClauseList::INPLACE_UNION(psi, *(x->clausesneg));
            reduceMemoryFootprintNeg(*it);
        } else {
            // If this is the only use of "clausesneg", no reason to make a copy.
            psi->insert(x->clausesneg);
            // Copied from reduceMemoryFootprintNeg
            delete x->clausesneg;
            x->clausesneg = NULL;
            if (x->clausespos == NULL) {
                delete x;
                info.erase(*it);
            }
        }

    }

    info[varphi]->clausesneg = psi;
} //End of convertFormulaToCNFNegOR()
Example #2
0
void CNFMgr::convertFormulaToCNFPosAND(const ASTNode& varphi,
                                       ClauseList* defs) {
    //****************************************
    // (pos) AND ~> UNION
    //****************************************

    ASTVec::const_iterator it = varphi.GetChildren().begin();
    convertFormulaToCNF(*it, defs);
    ClauseList* psi = ClauseList::COPY(*(info[*it]->clausespos));

    for (it++; it != varphi.GetChildren().end(); it++) {
        convertFormulaToCNF(*it, defs);
        CNFInfo* x = info[*it];

        if (sharesPos(*x) == 1) {
            psi->insert(x->clausespos);
            delete (x->clausespos);
            x->clausespos = NULL;
            if (x->clausesneg == NULL) {
                delete x;
                info.erase(*it);
            }
        } else {
            ClauseList::INPLACE_UNION(psi, *(x->clausespos));
            reduceMemoryFootprintPos(*it);
        }
    }
    if (renameAllSiblings)
    {
        assert(((unsigned)psi->size()) == varphi.GetChildren().size());
    }

    info[varphi]->clausespos = psi;
} //End of convertFormulaToCNFPosAND()
int main()
{
	AbstractSyntaxTree AST;

	ASTNode Root;
	Root.name = "Root";
	Root.type = "Node";
	Root.startLineCount = 1;
	Root.endLineCount = 0;
	AST.SetRoot(&Root);
	
	ASTNode N1;
	N1.name = "Node 1";
	N1.type = "Node";
	N1.startLineCount = 1;
	N1.endLineCount = 0;
	Root.GetChildren().push_back(&N1);
	
	ASTNode N2;
	N2.name = "Node 2";
	N2.type = "Node";
	N2.startLineCount = 1;
	N2.endLineCount = 0;
	N1.GetChildren().push_back(&N2);


	ASTNode N3;
	N3.name = "Node 3";
	N3.type = "Node";
	N3.startLineCount = 1;
	N3.endLineCount = 0;
	Root.GetChildren().push_back(&N3);	
	AST.TreeWalk(AST.GetRoot());
}
Example #4
0
void CNFMgr::convertFormulaToCNFPosPred(const ASTNode& varphi,
                                        ClauseList* defs)
{
    ASTVec psis;

    ASTVec::const_iterator it = varphi.GetChildren().begin();
    for (; it != varphi.GetChildren().end(); it++)
    {
        convertTermForCNF(*it, defs);
        psis.push_back(*(info[*it]->termforcnf));
    }

    info[varphi]->clausespos =
        SINGLETON(bm->CreateNode(varphi.GetKind(), psis));
} //End of convertFormulaToCNFPosPred()
Example #5
0
void CNFMgr::convertFormulaToCNFNegAND(const ASTNode& varphi,
                                       ClauseList* defs)
{
    bool renamesibs = false;
    ClauseList* clauses;
    ClauseList* psi;
    ClauseList* oldpsi;

    //****************************************
    // (neg) AND ~> PRODUCT NOT
    //****************************************

    ASTVec::const_iterator it = varphi.GetChildren().begin();
    convertFormulaToCNF(*it, defs);
    clauses = info[*it]->clausesneg;
    if (clauses->size() > 1)
    {
        renamesibs = true;
    }
    psi = ClauseList::COPY(*clauses);
    reduceMemoryFootprintNeg(*it);

    for (it++; it != varphi.GetChildren().end(); it++)
    {
        if (renamesibs)
        {
            setDoSibRenamingNeg(*(info[*it]));
        }
        convertFormulaToCNF(*it, defs);
        clauses = info[*it]->clausesneg;
        if (clauses->size() > 1)
        {
            renamesibs = true;
        }

        if (clauses->size() ==1)
            psi->INPLACE_PRODUCT(*clauses);
        else
        {
            oldpsi = psi;
            psi = ClauseList::PRODUCT(*psi, *clauses);
            DELETE(oldpsi);
        }
        reduceMemoryFootprintNeg(*it);
    }

    info[varphi]->clausesneg = psi;
} //End of convertFormulaToCNFNegAND()
Example #6
0
void LetizeNode(const ASTNode& n, ASTNodeSet& PLPrintNodeSet, bool smtlib1)
{
  const Kind kind = n.GetKind();

  if (kind == SYMBOL || kind == BVCONST || kind == FALSE || kind == TRUE)
    return;

  const ASTVec& c = n.GetChildren();
  for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
       it++)
  {
    const ASTNode& ccc = *it;

    const Kind k = ccc.GetKind();
    if (k == SYMBOL || k == BVCONST || k == FALSE || k == TRUE)
      continue;

    if (PLPrintNodeSet.find(ccc) == PLPrintNodeSet.end())
    {
      // If branch: if *it is not in NodeSet then,
      //
      // 1. add it to NodeSet
      //
      // 2. Letize its childNodes
      PLPrintNodeSet.insert(ccc);
      LetizeNode(ccc, PLPrintNodeSet, smtlib1);
    }
    else
    {
      // 0. Else branch: Node has been seen before
      //
      // 1. Check if the node has a corresponding letvar in the
      // 1. NodeLetVarMap.
      //
      // 2. if no, then create a new var and add it to the
      // 2. NodeLetVarMap
      if ((!smtlib1 || ccc.GetType() == BITVECTOR_TYPE) &&
          NodeLetVarMap.find(ccc) == NodeLetVarMap.end())
      {
        // Create a new symbol. Get some name. if it conflicts with a
        // declared name, too bad.
        int sz = NodeLetVarMap.size();
        std::ostringstream oss;
        oss << "?let_k_" << sz;

        ASTNode CurrentSymbol = n.GetSTPMgr()->CreateSymbol(
            oss.str().c_str(), n.GetIndexWidth(), n.GetValueWidth());
        /* If for some reason the variable being created here is
         * already declared by the user then the printed output will
         * not be a legal input to the system. too bad. I refuse to
         * check for this.  [Vijay is the author of this comment.]
         */

        NodeLetVarMap[ccc] = CurrentSymbol;
        std::pair<ASTNode, ASTNode> node_letvar_pair(CurrentSymbol, ccc);
        NodeLetVarVec.push_back(node_letvar_pair);
      }
    }
  }
} // end of LetizeNode()
// Method to find a particular node in tree. Returns its parent
ASTNode* AbstractSyntaxTree::FindNode(ASTNode* FindIt)
{
	if (this->Root == NULL)
		return NULL;

	// Maintaining a stack to traverse the Tree in DFS manner (non-recursive)
	std::stack<ASTNode*> DFSStack;

	// Maintaining a set of nodes which have been visited during traversal
	std::set<ASTNode*> Visited;

	DFSStack.push(this->Root);
	Visited.insert(this->Root);
	std::vector<ASTNode*> Children;
	while (!DFSStack.empty())
	{
		ASTNode* Top = DFSStack.top();
		DFSStack.pop();
		if ((*FindIt).IfEqual(*Top))
			return Top;
		Children = Top->GetChildren();
		for (ASTNode* child : Children)
		{
			if (Visited.find(child) == Visited.end())
			{
				DFSStack.push(child);
				Visited.insert(child);
			}
		}
	}
	return NULL;
}
Example #8
0
  void outputBitVecSMTLIB2(const ASTNode n, ostream& os)
  {
	const Kind k = n.GetKind();
    const ASTVec &c = n.GetChildren();
    ASTNode op;

    if (BITVECTOR == k)
      {
        op = c[0];
      }
    else if (BVCONST == k)
      {
        op = n;
      }
    else
      FatalError("nsadfsdaf");

    // CONSTANTBV::BitVector_to_Dec returns a signed representation by default.
    // Prepend with zero to convert to unsigned.

    os << "(_ bv";
	CBV unsign = CONSTANTBV::BitVector_Concat(
			n.GetSTPMgr()->CreateZeroConst(1).GetBVConst(), op.GetBVConst());
    unsigned char * str = CONSTANTBV::BitVector_to_Dec(unsign);
    CONSTANTBV::BitVector_Destroy(unsign);
    os << str << " " << op.GetValueWidth() << ")";
    CONSTANTBV::BitVector_Dispose(str);
  }
Example #9
0
// Check that the transformations have occurred.
void ArrayTransformer::assertTransformPostConditions(const ASTNode& term,
                                                     ASTNodeSet& visited)
{

  // I haven't measure whether this is the quickest way to do it?
  std::pair<ASTNodeSet::iterator, bool> p = visited.insert(term);
  if (!p.second)
    return;

  const Kind k = term.GetKind();

  // Check the array reads / writes have been removed
  assert(READ != k);
  assert(WRITE != k);

  // There should be no nodes left of type array.
  assert(0 == term.GetIndexWidth());

  const ASTVec& c = term.GetChildren();
  ASTVec::const_iterator it = c.begin();
  const ASTVec::const_iterator itend = c.end();
  for (; it != itend; it++)
  {
    assertTransformPostConditions(*it, visited);
  }
} 
Example #10
0
  ASTNode STPMgr::CreateSimpNot(const ASTNode& form)
  {
    Kind k = form.GetKind();
    switch (k)
      {
      case FALSE:
        {
          return ASTTrue;
        }
      case TRUE:
        {
          return ASTFalse;
        }
      case NOT:
        {
          return form[0];
        } // NOT NOT cancellation
      case XOR:
        {
          // Push negation down in this case.
          // FIXME: Separate pre-pass to push negation down?
          // CreateSimp should be local, and this isn't.
          // It isn't memoized.  Arg.
          ASTVec children = form.GetChildren();
          children[0] = CreateSimpNot(children[0]);
          return CreateSimpXor(children);
        }
      default:
        {
	  return CreateNode(NOT, form);
          //return CreateNode(XOR, ASTTrue, form);
        }
      }
  }
Example #11
0
void CNFMgr::convertFormulaToCNFNegXOR(const ASTNode& varphi,
                                       ClauseList* defs)
{
    //#ifdef FALSE
#if defined CRYPTOMINISAT__2
    CNFInfo * xx = info[varphi];
    if(NULL != xx
            && sharesPos(*xx) > 0
            && sharesNeg(*xx) > 0)
    {
        return;
    }

    ASTVec::const_iterator it = varphi.GetChildren().begin();
    ClausePtr xor_clause = new vector<const ASTNode*>();

    for (; it != varphi.GetChildren().end(); it++)
    {
        convertFormulaToCNF(*it, defs); // make pos and neg clause set

        //Creating a new variable name for each of the children of the
        //XOR node doRenamingPos(*it, defs);
        //doRenamingPos(*it, defs);
        doRenamingNeg(*it, defs);

        xor_clause->insert(xor_clause->end(),
                           ((*(info[*it]->clausespos)).asList()->front())->begin(),
                           ((*(info[*it]->clausespos)).asList()->front())->end());
    }
    doRenamingPosXor(varphi);
    //ClauseList* psi = convertFormulaToCNFPosXORAux(varphi, 0, defs);
    //info[varphi]->clausespos = psi;
    ASTNode varXorNode = GetNodeFrom_SINGLETON(info[varphi]->clausespos);
    ASTNode NotVarXorNode = bm->CreateNode(NOT, varXorNode);
    xor_clause->push_back(ASTNodeToASTNodePtr(NotVarXorNode));
    clausesxor->push_back(xor_clause);

    ASTVec::const_iterator it2 = varphi.GetChildren().begin();
    for (; it2 != varphi.GetChildren().end(); it2++) {
        reduceMemoryFootprintPos(*it2);
        reduceMemoryFootprintNeg(*it2);
    }
#else
    ASTVec::const_iterator it = varphi.GetChildren().begin();
    for (; it != varphi.GetChildren().end(); it++)
    {
        convertFormulaToCNF(*it, defs); // make pos and neg clause sets
    }
    ClauseList* psi = convertFormulaToCNFNegXORAux(varphi, 0, defs);
    info[varphi]->clausesneg = psi;
    ASTVec::const_iterator it2 = varphi.GetChildren().begin();
    for (; it2 != varphi.GetChildren().end(); it2++) {
        reduceMemoryFootprintPos(*it2);
        reduceMemoryFootprintNeg(*it2);
    }
#endif
} //End of convertFormulaToCNFNegXOR()
Example #12
0
void CNFMgr::scanTerm(const ASTNode& varphi)
{
    CNFInfo* x;

    //########################################
    // step 1, get the info associated with this node
    //########################################

    if (info.find(varphi) == info.end())
    {
        x = new CNFInfo();
        info[varphi] = x;
    }
    else
    {
        x = info[varphi];
    }

    //########################################
    // step 2, need two hits because of term ITEs.
    //########################################

    if (sharesPos(*x) == 2)
    {
        return;
    }

    //########################################
    // step 3, set appropriate data fields, always rename
    // term ITEs
    //########################################

    incrementSharesPos(*x);
    setIsTerm(*x);

    //########################################
    // step 4, recurse over children
    //########################################

    if (varphi.isAtom())
    {
        return;
    }
    else if (varphi.isITE())
    {
        scanFormula(varphi[0], true, false);
        scanFormula(varphi[0], false, false);
        scanTerm(varphi[1]);
        scanTerm(varphi[2]);
    }
    else
    {
        for (unsigned int i = 0; i < varphi.GetChildren().size(); i++)
        {
            scanTerm(varphi[i]);
        }
    }
}//End of scanterm()
Example #13
0
void CNFMgr::convertTermForCNF(const ASTNode& varphi, ClauseList* defs)
{
    CNFInfo* x = info[varphi];

    //########################################
    // step 1, done if we've already visited
    //########################################

    if (x->termforcnf != NULL)
    {
        return;
    }

    //########################################
    // step 2, ITE's always get renamed
    //########################################

    if (varphi.isITE())
    {
        x->termforcnf = doRenameITE(varphi, defs);
        reduceMemoryFootprintPos(varphi[0]);
        reduceMemoryFootprintNeg(varphi[0]);

    }
    else if (varphi.isAtom())
    {
        x->termforcnf = ASTNodeToASTNodePtr(varphi);
    }
    else
    {
        ASTVec psis;
        ASTVec::const_iterator it = varphi.GetChildren().begin();
        for (; it != varphi.GetChildren().end(); it++)
        {
            convertTermForCNF(*it, defs);
            psis.push_back(*(info[*it]->termforcnf));
        }

        ASTNode psi = bm->CreateNode(varphi.GetKind(), psis);
        psi.SetValueWidth(varphi.GetValueWidth());
        psi.SetIndexWidth(varphi.GetIndexWidth());
        x->termforcnf = ASTNodeToASTNodePtr(psi);
    }
} //End of convertTermForCNF()
Example #14
0
void CNFMgr::convertFormulaToCNFNegNAND(const ASTNode& varphi,
                                        ClauseList* defs)
{
    //****************************************
    // (neg) NAND ~> UNION
    //****************************************
    ASTVec::const_iterator it = varphi.GetChildren().begin();
    convertFormulaToCNF(*it, defs);
    ClauseList* psi = ClauseList::COPY(*(info[*it]->clausespos));
    reduceMemoryFootprintPos(*it);
    for (it++; it != varphi.GetChildren().end(); it++)
    {
        convertFormulaToCNF(*it, defs);
        ClauseList::INPLACE_UNION(psi, *(info[*it]->clausespos));
        reduceMemoryFootprintPos(*it);
    }

    info[varphi]->clausespos = psi;
} //End of convertFormulaToCNFNegNAND()
  // If there is a lot of sharing in the graph, this will take a long
  // time.  it doesn't mark subgraphs as already having been
  // typechecked.
  bool BVTypeCheckRecursive(const ASTNode& n)
  {
    const ASTVec& c = n.GetChildren();

    BVTypeCheck(n);

    for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++)
      BVTypeCheckRecursive(*it);

    return true;
  }
Example #16
0
void CNFMgr::convertFormulaToCNFPosOR(const ASTNode& varphi,
                                      ClauseList* defs)
{
    bool renamesibs = false;
    ClauseList* clauses;
    ClauseList* psi;
    ClauseList* oldpsi;

    //****************************************
    // (pos) OR ~> PRODUCT
    //****************************************
    ASTVec::const_iterator it = varphi.GetChildren().begin();
    convertFormulaToCNF(*it, defs);
    clauses = info[*it]->clausespos;
    if (clauses->size() > 1)
    {
        renamesibs = true;
    }
    psi = ClauseList::COPY(*clauses);
    reduceMemoryFootprintPos(*it);

    for (it++; it != varphi.GetChildren().end(); it++)
    {
        if (renamesibs)
        {
            setDoSibRenamingPos(*(info[*it]));
        }
        convertFormulaToCNF(*it, defs);
        clauses = info[*it]->clausespos;
        if (clauses->size() > 1)
        {
            renamesibs = true;
        }
        oldpsi = psi;
        psi = ClauseList::PRODUCT(*psi, *clauses);
        reduceMemoryFootprintPos(*it);
        DELETE(oldpsi);
    }

    info[varphi]->clausespos = psi;
} //End of convertFormulaToCNFPosOR()
    bool
    ConstantBitPropagation::checkAtFixedPoint(const ASTNode& n, ASTNodeSet & visited)
    {
      if (status == CONFLICT)
        return true; // can't do anything.

      if (visited.find(n) != visited.end())
        return true;

      visited.insert(n);

      // get the current for the children.
      vector<FixedBits> childrenFixedBits;
      childrenFixedBits.reserve(n.GetChildren().size());

      // get a copy of the current fixing from the cache.
      for (unsigned i = 0; i < n.GetChildren().size(); i++)
        {
          childrenFixedBits.push_back(*getCurrentFixedBits(n[i]));
        }
      FixedBits current = *getCurrentFixedBits(n);
      FixedBits newBits = *getUpdatedFixedBits(n);

      assert(FixedBits::equals(newBits, current));

      for (int i = 0; i < n.Degree(); i++)
        {
          if (!FixedBits::equals(*getUpdatedFixedBits(n[i]),
              childrenFixedBits[i]))
            {
              cerr << "Not fixed point";
              assert(false);
            }

          checkAtFixedPoint(n[i], visited);
        }
      return true;
    }
  void buildListOfSymbols(const ASTNode& n, ASTNodeSet& visited,
  		ASTNodeSet& symbols)
  {
  	if (visited.find(n) != visited.end())
  		return; // already visited.

  	visited.insert(n);

  	if (n.GetKind() == SYMBOL)
  	{
  		symbols.insert(n);
  	}

  	for (unsigned i = 0; i < n.GetChildren().size(); i++)
  		buildListOfSymbols(n[i], visited, symbols);
  }
Example #19
0
  void Dot_Print1(ostream &os, const ASTNode n, hash_set<int> *alreadyOutput)
  {

    // check if this node has already been printed. If so return.
    if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end())
      return;

    alreadyOutput->insert(n.GetNodeNum());

    os << "n" << n.GetNodeNum() << "[label =\"";
    switch (n.GetKind())
      {
      case SYMBOL:
        n.nodeprint(os);
        break;

      case BITVECTOR:
      case BVCONST:
        outputBitVec(n, os);
        break;

      default:
        os << _kind_names[n.GetKind()];
      }

    os << "\"];" << endl;

    // print the edges to each child.
    ASTVec ch = n.GetChildren();
    ASTVec::iterator itend = ch.end();
    int i = 0;
    for (ASTVec::iterator it = ch.begin(); it < itend; it++)
      {
        os << "n" << n.GetNodeNum() 
           << " -> " << "n" 
           << it->GetNodeNum() 
           << "[label=" << i++ 
           << "];" << endl;
      }

    // print each of the children.
    for (ASTVec::iterator it = ch.begin(); it < itend; it++)
      {
        Dot_Print1(os, *it, alreadyOutput);
      }
  }
Example #20
0
  //UserGuided abstraction refinement
  SOLVER_RETURN_TYPE
  STP::
  UserGuided_AbsRefine(SATSolver& NewSolver,
		       const ASTNode& original_input)
  {
    ASTVec v = bm->GetAsserts_WithKey(0);
    if(v.empty())
      {
	FatalError("UserGuided_AbsRefine: Something is seriously wrong."\
		   "The input set is empty");
      }
    ASTNode sureAddInput = 
      (v.size() == 1) ? v[0] : bm->CreateNode(AND, v); 

    SOLVER_RETURN_TYPE res = SOLVER_UNDECIDED;
    res = TopLevelSTPAux(NewSolver, sureAddInput, original_input);
    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }
    
    //Do refinement here
    if(AND != original_input.GetKind())
      {
	FatalError("UserGuided_AbsRefine: The input must be an AND");
      }

    ASTVec RefineFormulasVec;
    ASTVec RemainingFormulasVec;
    ASTNode asttrue = bm->CreateNode(TRUE);
    ASTNode astfalse = bm->CreateNode(FALSE);
    for(int count=0; count < bm->UserFlags.num_absrefine; count++)
      {
	RemainingFormulasVec.clear();
	RemainingFormulasVec.push_back(asttrue);
	RefineFormulasVec.clear();	
	RefineFormulasVec.push_back(asttrue);
	ASTVec InputKids = original_input.GetChildren();
	for(ASTVec::iterator it = InputKids.begin(), itend = InputKids.end();
	    it!=itend;it++)
	  {
	    Ctr_Example->ClearComputeFormulaMap();
	    if(astfalse == Ctr_Example->ComputeFormulaUsingModel(*it))
	      {
		RefineFormulasVec.push_back(*it);
	      }
	    else
	      {
		RemainingFormulasVec.push_back(*it);
	      }
	  }
	ASTNode RefineFormulas =
	  (RefineFormulasVec.size() == 1) ?
	  RefineFormulasVec[0] : bm->CreateNode(AND, RefineFormulasVec);
	res = TopLevelSTPAux(NewSolver, RefineFormulas, original_input);
	if(SOLVER_UNDECIDED != res)
	  {
	    return res;
	  }
      }

    ASTNode RemainingFormulas = 
      (RemainingFormulasVec.size() == 1) ?
      RemainingFormulasVec[0] : bm->CreateNode(AND, RemainingFormulasVec);
    res = TopLevelSTPAux(NewSolver, RemainingFormulas, original_input);
    
    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }
    
    FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
	       "either a divide by zero in the input or a bug in STP");    
    return SOLVER_ERROR;
  } //End of UserGuided_AbsRefine()
Example #21
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;
  }
Example #22
0
// Translates signed BVDIV,BVMOD and BVREM into unsigned variety
ASTNode ArrayTransformer::TranslateSignedDivModRem(const ASTNode& in,
                                                   NodeFactory* nf, STPMgr* bm)
{
  assert(in.GetChildren().size() == 2);

  const ASTNode& dividend = in[0];
  const ASTNode& divisor = in[1];
  const unsigned len = in.GetValueWidth();

  ASTNode hi1 = bm->CreateBVConst(32, len - 1);
  ASTNode one = bm->CreateOneConst(1);
  ASTNode zero = bm->CreateZeroConst(1);
  // create the condition for the dividend
  ASTNode cond_dividend =
      nf->CreateNode(EQ, one, nf->CreateTerm(BVEXTRACT, 1, dividend, hi1, hi1));
  // create the condition for the divisor
  ASTNode cond_divisor =
      nf->CreateNode(EQ, one, nf->CreateTerm(BVEXTRACT, 1, divisor, hi1, hi1));

  if (SBVREM == in.GetKind())
  {
    // BVMOD is an expensive operation. So have the fewest bvmods
    // possible. Just one.

    // Take absolute value.
    ASTNode pos_dividend =
        nf->CreateTerm(ITE, len, cond_dividend,
                       nf->CreateTerm(BVUMINUS, len, dividend), dividend);
    ASTNode pos_divisor =
        nf->CreateTerm(ITE, len, cond_divisor,
                       nf->CreateTerm(BVUMINUS, len, divisor), divisor);

    // create the modulus term
    ASTNode modnode = nf->CreateTerm(BVMOD, len, pos_dividend, pos_divisor);

    // If the dividend is <0 take the unary minus.
    ASTNode n = nf->CreateTerm(ITE, len, cond_dividend,
                               nf->CreateTerm(BVUMINUS, len, modnode), modnode);
    return n;
  }

  // This is the modulus of dividing rounding to -infinity.
  else if (SBVMOD == in.GetKind())
  {

    /*
    (bvsmod s t) abbreviates
        (let ((?msb_s ((_ extract |m-1| |m-1|) s))
          (?msb_t ((_ extract |m-1| |m-1|) t)))
        (let ((abs_s (ite (= ?msb_s #b0) s (bvneg s)))
            (abs_t (ite (= ?msb_t #b0) t (bvneg t))))
          (let ((u (bvurem abs_s abs_t)))
          (ite (= u (_ bv0 m))
             u
          (ite (and (= ?msb_s #b0) (= ?msb_t #b0))
             u
          (ite (and (= ?msb_s #b1) (= ?msb_t #b0))
             (bvadd (bvneg u) t)
          (ite (and (= ?msb_s #b0) (= ?msb_t #b1))
             (bvadd u t)
             (bvneg u))))))))
     */

    // Take absolute value.
    ASTNode pos_dividend =
        nf->CreateTerm(ITE, len, cond_dividend,
                       nf->CreateTerm(BVUMINUS, len, dividend), dividend);
    ASTNode pos_divisor =
        nf->CreateTerm(ITE, len, cond_divisor,
                       nf->CreateTerm(BVUMINUS, len, divisor), divisor);

    ASTNode urem_node = nf->CreateTerm(BVMOD, len, pos_dividend, pos_divisor);

    // If the dividend is <0, then we negate the whole thing.
    ASTNode rev_node =
        nf->CreateTerm(ITE, len, cond_dividend,
                       nf->CreateTerm(BVUMINUS, len, urem_node), urem_node);

    // if It's XOR <0, and it doesn't perfectly divide, then add t (not its
    // absolute value).
    ASTNode xor_node = nf->CreateNode(XOR, cond_dividend, cond_divisor);
    ASTNode neZ = nf->CreateNode(
        NOT, nf->CreateNode(EQ, rev_node,
                            bm->CreateZeroConst(divisor.GetValueWidth())));
    ASTNode cond = nf->CreateNode(AND, xor_node, neZ);
    ASTNode n = nf->CreateTerm(ITE, len, cond,
                               nf->CreateTerm(BVPLUS, len, rev_node, divisor),
                               rev_node);

    return n;
  }
  else if (SBVDIV == in.GetKind())
  {
    // now handle the BVDIV case
    // if topBit(dividend) is 1 and topBit(divisor) is 0
    //
    // then output is -BVDIV(-dividend,divisor)
    //
    // elseif topBit(dividend) is 0 and topBit(divisor) is 1
    //
    // then output is -BVDIV(dividend,-divisor)
    //
    // elseif topBit(dividend) is 1 and topBit(divisor) is 1
    //
    // then output is BVDIV(-dividend,-divisor)
    //
    // else simply output BVDIV(dividend,divisor)

    // Take absolute value.
    ASTNode pos_dividend =
        nf->CreateTerm(ITE, len, cond_dividend,
                       nf->CreateTerm(BVUMINUS, len, dividend), dividend);
    ASTNode pos_divisor =
        nf->CreateTerm(ITE, len, cond_divisor,
                       nf->CreateTerm(BVUMINUS, len, divisor), divisor);

    ASTNode divnode = nf->CreateTerm(BVDIV, len, pos_dividend, pos_divisor);

    // A little confusing. Only negate the result if they are XOR <0.
    ASTNode xor_node = nf->CreateNode(XOR, cond_dividend, cond_divisor);
    ASTNode n = nf->CreateTerm(ITE, len, xor_node,
                               nf->CreateTerm(BVUMINUS, len, divnode), divnode);

    return n;
  }

  FatalError("TranslateSignedDivModRem:"
             "input must be signed DIV/MOD/REM",
             in);
  return bm->ASTUndefined;

}
  /* 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
Example #24
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;
}
Example #25
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;
} 
Example #26
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;
}
Example #27
0
// helper function for printing C code (copied from PL_Print1())
void C_Print1(ostream& os, const ASTNode n, int indentation, bool letize)
{

  unsigned int upper, lower, num_bytes;
  Kind LHSkind, RHSkind;

  // os << spaces(indentation);
  // os << endl << spaces(indentation);
  if (!n.IsDefined())
  {
    os << "<undefined>";
    return;
  }

  // if this node is present in the letvar Map, then print the letvar
  STPMgr* bm = n.GetSTPMgr();

  // this is to print letvars for shared subterms inside the printing
  // of "(LET v0 = term1, v1=term1@term2,...
  if ((bm->NodeLetVarMap1.find(n) != bm->NodeLetVarMap1.end()) && !letize)
  {
    C_Print1(os, (bm->NodeLetVarMap1[n]), indentation, letize);
    return;
  }

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

  // otherwise print it normally
  Kind kind = n.GetKind();
  const ASTVec& c = n.GetChildren();
  switch (kind)
  {
    case BOOLEXTRACT:
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      C_Print1(os, c[0], indentation, letize);
      os << "{";
      C_Print1(os, c[1], indentation, letize);
      os << "}";
      break;
    case BITVECTOR:
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "BITVECTOR(";
      unsigned char* str;
      str = CONSTANTBV::BitVector_to_Hex(c[0].GetBVConst());
      os << str << ")";
      CONSTANTBV::BitVector_Dispose(str);
      break;
    case BOOLEAN:
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "BOOLEAN";
      break;
    case FALSE:
      os << "0";
      break;
    case TRUE:
      os << "1";
      break;
    case BVCONST:
    case SYMBOL:
      // print in C friendly format:
      n.nodeprint(os, true);
      break;
    case READ:
      C_Print1(os, c[0], indentation, letize);
      os << "[";
      C_Print1(os, c[1], indentation, letize);
      os << "]";
      break;
    case WRITE:
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " WITH [";
      C_Print1(os, c[1], indentation, letize);
      os << "] := ";
      C_Print1(os, c[2], indentation, letize);
      os << ")";
      os << endl;
      break;
    case BVUMINUS:
      os << kind << "( ";
      C_Print1(os, c[0], indentation, letize);
      os << ")";
      break;
    case NOT:
      os << "!(";
      C_Print1(os, c[0], indentation, letize);
      os << ") " << endl;
      break;
    case BVNEG:
      os << " ~(";
      C_Print1(os, c[0], indentation, letize);
      os << ")";
      break;
    case BVCONCAT:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " @ ";
      C_Print1(os, c[1], indentation, letize);
      os << ")" << endl;
      break;
    case BVOR:
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " | ";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVAND:
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " & ";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVEXTRACT:

      // we only accept indices that are byte-aligned
      // (e.g., [15:8], [23:16])
      // and round down to byte indices rather than bit indices
      upper = c[1].GetUnsignedConst();
      lower = c[2].GetUnsignedConst();
      assert(upper > lower);
      assert(lower % 8 == 0);
      assert((upper + 1) % 8 == 0);
      num_bytes = (upper - lower + 1) / 8;
      assert(num_bytes > 0);

      // for multi-byte extraction, use the ADDRESS
      if (num_bytes > 1)
      {
        os << "&";
        C_Print1(os, c[0], indentation, letize);
        os << "[" << lower / 8 << "]";
      }
      // for single-byte extraction, use the VALUE
      else
      {
        C_Print1(os, c[0], indentation, letize);
        os << "[" << lower / 8 << "]";
      }

      break;
    case BVLEFTSHIFT:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " << ";
      os << c[1].GetUnsignedConst();
      os << ")";
      break;
    case BVRIGHTSHIFT:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " >> ";
      os << c[1].GetUnsignedConst();
      os << ")";
      break;
    case BVMULT:
    case BVSUB:
    case BVPLUS:
    case SBVDIV:
    case SBVREM:
    case BVDIV:
    case BVMOD:
      os << kind << "(";
      os << n.GetValueWidth();
      for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
           it++)
      {
        os << ", " << endl;
        C_Print1(os, *it, indentation, letize);
      }
      os << ")" << endl;
      break;
    case ITE:
      os << "if (";
      C_Print1(os, c[0], indentation, letize);
      os << ")" << endl;
      os << "{";
      C_Print1(os, c[1], indentation, letize);
      os << endl << "} else {";
      C_Print1(os, c[2], indentation, letize);
      os << endl << "}";
      break;
    case BVLT:
      // convert to UNSIGNED before doing comparison!
      os << "((unsigned char)";
      C_Print1(os, c[0], indentation, letize);
      os << " < ";
      os << "(unsigned char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVLE:
      // convert to UNSIGNED before doing comparison!
      os << "((unsigned char)";
      C_Print1(os, c[0], indentation, letize);
      os << " <= ";
      os << "(unsigned char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVGT:
      // convert to UNSIGNED before doing comparison!
      os << "((unsigned char)";
      C_Print1(os, c[0], indentation, letize);
      os << " > ";
      os << "(unsigned char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVGE:
      // convert to UNSIGNED before doing comparison!
      os << "((unsigned char)";
      C_Print1(os, c[0], indentation, letize);
      os << " >= ";
      os << "(unsigned char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVXOR:
    case BVNAND:
    case BVNOR:
    case BVXNOR:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      break;
    case BVSLT:
      // convert to SIGNED before doing comparison!
      os << "((signed char)";
      C_Print1(os, c[0], indentation, letize);
      os << " < ";
      os << "(signed char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVSLE:
      // convert to SIGNED before doing comparison!
      os << "((signed char)";
      C_Print1(os, c[0], indentation, letize);
      os << " <= ";
      os << "(signed char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVSGT:
      // convert to SIGNED before doing comparison!
      os << "((signed char)";
      C_Print1(os, c[0], indentation, letize);
      os << " > ";
      os << "(signed char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVSGE:
      // convert to SIGNED before doing comparison!
      os << "((signed char)";
      C_Print1(os, c[0], indentation, letize);
      os << " >= ";
      os << "(signed char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case EQ:
      // tricky tricky ... if it's a single-byte comparison,
      // simply do ==, but if it's multi-byte, must do memcmp
      LHSkind = c[0].GetKind();
      RHSkind = c[1].GetKind();

      num_bytes = 0;

      // try to figure out whether it's a single-byte or multi-byte
      // comparison
      if (LHSkind == BVEXTRACT)
      {
        upper = c[0].GetChildren()[1].GetUnsignedConst();
        lower = c[0].GetChildren()[2].GetUnsignedConst();
        num_bytes = (upper - lower + 1) / 8;
      }
      else if (RHSkind == BVEXTRACT)
      {
        upper = c[1].GetChildren()[1].GetUnsignedConst();
        lower = c[1].GetChildren()[2].GetUnsignedConst();
        num_bytes = (upper - lower + 1) / 8;
      }

      if (num_bytes > 1)
      {
        os << "(memcmp(";
        C_Print1(os, c[0], indentation, letize);
        os << ", ";
        C_Print1(os, c[1], indentation, letize);
        os << ", ";
        os << num_bytes;
        os << ") == 0)";
      }
      else if (num_bytes == 1)
      {
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << " == ";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
      }
      else
      {
        FatalError("C_Print1: ugh problem in implementing ==");
      }

      break;
    case AND:
    case OR:
    case NAND:
    case NOR:
    case XOR:
    {
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      ASTVec::const_iterator it = c.begin();
      ASTVec::const_iterator itend = c.end();

      it++;
      for (; it != itend; it++)
      {
        switch (kind)
        {
          case AND:
            os << " && ";
            break;
          case OR:
            os << " || ";
            break;
          case NAND:
            FatalError("unsupported boolean type in C_Print1");
            break;
          case NOR:
            FatalError("unsupported boolean type in C_Print1");
            break;
          case XOR:
            FatalError("unsupported boolean type in C_Print1");
            break;
          default:
            FatalError("unsupported boolean type in C_Print1");
        }
        C_Print1(os, *it, indentation, letize);
      }
      os << ")";
      break;
    }
    case IFF:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << ")";
      os << " <=> ";
      os << "(";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      os << ")";
      os << endl;
      break;
    case IMPLIES:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << ")";
      os << " => ";
      os << "(";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      os << ")";
      os << endl;
      break;
    case BVSX:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);

      os << kind << "(";
      C_Print1(os, c[0], indentation, letize);
      os << ",";
      os << n.GetValueWidth();
      os << ")" << endl;
      break;
    default:
      // remember to use LispPrinter here. Otherwise this function will
      // go into an infinite loop. Recall that "<<" is overloaded to
      // the lisp printer. FatalError uses lispprinter
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      break;
  }
} // end of C_Print1()
// 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;
}
Example #29
0
  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 << ")";
  		}
  	}
      }
  }
Example #30
0
void GDL_Print1(ostream& os, const ASTNode& n, hash_set<int>* alreadyOutput,
                string (*annotate)(const ASTNode&))
{
  // check if this node has already been printed. If so return.
  if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end())
    return;

  alreadyOutput->insert(n.GetNodeNum());

  os << "node: { title:\"n" << n.GetNodeNum() << "\" label: \"";
  switch (n.GetKind())
  {
    case SYMBOL:
      n.nodeprint(os);
      break;

    case BITVECTOR:
    case BVCONST:
      outputBitVec(n, os);
      break;

    default:
      os << _kind_names[n.GetKind()];
  }

  os << annotate(n);
  os << "\"}" << endl;

  // print the edges to each child.
  const ASTVec ch = n.GetChildren();
  const ASTVec::const_iterator itend = ch.end();

  // If a node has the child 'TRUE' twice, we only want to output one TRUE node.
  ASTNodeSet constantOutput;

  int i = 0;
  for (ASTVec::const_iterator it = ch.begin(); it < itend; it++)
  {
    std::stringstream label;

    if (!isCommutative(n.GetKind()))
      label << " label:\"" << i << "\"";

    if (it->isConstant())
    {
      std::stringstream ss;
      ss << n.GetNodeNum() << "_" << it->GetNodeNum();

      if (constantOutput.end() == constantOutput.find(*it))
      {
        os << "node: { title:\"n";

        os << ss.str() << "\" label: \"";
        if (it->GetType() == BEEV::BOOLEAN_TYPE)
          os << _kind_names[it->GetKind()];
        else
          outputBitVec(*it, os);
        os << "\"}" << endl;
        constantOutput.insert(*it);
      }

      os << "edge: { source:\"n" << n.GetNodeNum() << "\" target: \""
         << "n" << ss.str() << "\"" << label.str() << "}" << endl;
    }
    else
      os << "edge: { source:\"n" << n.GetNodeNum() << "\" target: \""
         << "n" << it->GetNodeNum() << "\"" << label.str() << "}" << endl;
    i++;
  }

  // print each of the children.
  for (ASTVec::const_iterator it = ch.begin(); it < itend; it++)
  {
    if (!it->isConstant())
      GDL_Print1(os, *it, alreadyOutput, annotate);
  }
}