Пример #1
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()
Пример #2
0
// Adds to the dependency graph that n0 depends on the variables in n1.
// It's not the transitive closure of the dependencies. Just the variables in the expression "n1".
// This is only needed as long as all the substitution rules haven't been written through.
  void
  SubstitutionMap::buildDepends(const ASTNode& n0, const ASTNode& n1)
  {
    if (n0.GetKind() != SYMBOL)
      return;

    if (n1.isConstant())
      return;

    vector<Symbols*> av;
    vars.VarSeenInTerm(vars.getSymbol(n1), rhs_visited, rhs, av);

    sort(av.begin(), av.end());
    for (int i = 0; i < av.size(); i++)
      {
      if (i != 0 && av[i] == av[i - 1])
        continue; // Treat it like a set of Symbol* in effect.

      ASTNodeSet* sym = (vars.TermsAlreadySeenMap.find(av[i])->second);
      if (rhsAlreadyAdded.find(sym) != rhsAlreadyAdded.end())
        continue;
      rhsAlreadyAdded.insert(sym);

      //cout << loopCount++ << " ";
      //cout << "initial" << rhs.size() << " Adding: " <<sym->size();
      rhs.insert(sym->begin(), sym->end());
      //cout << "final:" << rhs.size();
      //cout << "added:" << sym << endl;

      }

    assert(dependsOn.find(n0) == dependsOn.end());
    dependsOn.insert(make_pair(n0, vars.getSymbol(n1)));
  }
Пример #3
0
void STPMgr::printVarDeclsToStream(ostream& os, ASTNodeSet& ListOfDeclaredVars)
{
  for (ASTNodeSet::iterator i = ListOfDeclaredVars.begin(),
                            iend = ListOfDeclaredVars.end();
       i != iend; i++)
  {
    stp::ASTNode a = *i;
    switch (a.GetType())
    {
      case stp::BITVECTOR_TYPE:
        a.PL_Print(os);
        os << " : BITVECTOR(" << a.GetValueWidth() << ");" << endl;
        break;
      case stp::ARRAY_TYPE:
        a.PL_Print(os);
        os << " : ARRAY "
           << "BITVECTOR(" << a.GetIndexWidth() << ") OF ";
        os << "BITVECTOR(" << a.GetValueWidth() << ");" << endl;
        break;
      case stp::BOOLEAN_TYPE:
        a.PL_Print(os);
        os << " : BOOLEAN;" << endl;
        break;
      default:
        stp::FatalError("vc_printDeclsToStream: Unsupported type", a);
        break;
    }
  }
} // printVarDeclsToStream
Пример #4
0
  //this function looksup the "var to letexpr map" and returns the
  //corresponding letexpr. if there is no letexpr, then it simply
  //returns the var.
  ASTNode BeevMgr::ResolveID(const ASTNode& v) {
    if(v.GetKind() != SYMBOL) {
      return v;
    }

    if(_parser_symbol_table.find(v) != _parser_symbol_table.end()) {
      return v;
    }

    ASTNodeMap::iterator it;
    if((it =_letid_expr_map.find(v)) != _letid_expr_map.end()) {
      if(it->second == ASTUndefined) 
	FatalError("Unresolved Identifier: ",v);
      else
	return it->second;
    }

    //this is to mark the let-var as undefined. the let var is defined
    //only after the LetExprMgr has completed its work, and until then
    //'v' is undefined. 
    //
    //declared variables also get stored in this map, but there value
    //is ASTUndefined. This is really a hack. I don't know how to get
    //rid of this hack.
    _letid_expr_map[v] = ASTUndefined;
    return v;    
  }
Пример #5
0
void printVarDeclsToStream(ASTNodeSet& symbols, ostream& os)
{
	for (ASTNodeSet::const_iterator i = symbols.begin(), iend = symbols.end(); i
			!= iend; i++)
	{
      const BEEV::ASTNode& a = *i;
      os << "(declare-fun ";

      // Should be a symbol.
      assert(a.GetKind()== SYMBOL);
      os << "|";
      a.nodeprint(os);
      os << "|";

		switch (a.GetType())
		{
      case BEEV::BITVECTOR_TYPE:
    	  os << " () (";
    	  os << "_ BitVec " << a.GetValueWidth() << ")";

        break;
      case BEEV::ARRAY_TYPE:
    	  os << " () (";
    	  os << "Array (_ BitVec " << a.GetIndexWidth()  << ") (_ BitVec " << a.GetValueWidth() << ") )";
        break;
      case BEEV::BOOLEAN_TYPE:
        os << " () Bool ";
        break;
      default:
        BEEV::FatalError("printVarDeclsToStream: Unsupported type",a);
        break;
      }
  	  os << ")\n";
    }
  } //printVarDeclsToStream
Пример #6
0
ASTNodeSet * VariablesInExpression::SetofVarsSeenInTerm(Symbols* symbol, bool& destruct)
{
	assert(symbol != NULL);

	SymbolPtrToNode::iterator it = TermsAlreadySeenMap.find(symbol);

	if ( it != TermsAlreadySeenMap.end())
		{
		destruct = false;
		return it->second;
		}

	SymbolPtrSet visited;

	ASTNodeSet *symbols = new ASTNodeSet();
	vector<Symbols*> av;
	VarSeenInTerm(symbol,visited,*symbols,av);

	for (size_t i =0; i < av.size();i++)
	{
		const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second;
		symbols->insert(sym.begin(), sym.end());
	}

	destruct = true;
	//TermsAlreadySeenMap.insert(make_pair(symbol,symbols));

	return symbols;
}
Пример #7
0
  // FUNC: This function maintains a map between LET-var names and
  // LET-expressions
  //
  //1. if the Let-var is already defined in the LET scope, then the
  //1. function returns an error.
  //
  //2. if the Let-var is already declared variable in the input, then
  //2. the function returns an error
  //
  //3. otherwise add the <var,letExpr> pair to the _letid_expr table.
  void BeevMgr::LetExprMgr(const ASTNode& var, const ASTNode& letExpr) {
    ASTNodeMap::iterator it;
    if(((it = _letid_expr_map.find(var)) != _letid_expr_map.end()) && 
       it->second != ASTUndefined) {      
      FatalError("LetExprMgr:The LET-var v has already been defined in this LET scope: v =", var);
    }

    if(_parser_symbol_table.find(var) != _parser_symbol_table.end()) {
      FatalError("LetExprMgr:This var is already declared. cannot redeclare as a letvar: v =", var);
    }

    _letid_expr_map[var] = letExpr;   
  }
Пример #8
0
bool containsArrayOps(const ASTNode& n, ASTNodeSet& visited)
{
	if (visited.find(n) != visited.end())
		return false;
	if (n.GetType() == ARRAY_TYPE)
		return true;

	for (int i =0; i < n.Degree();i++)
		if (containsArrayOps(n[i],visited))
			return true;

	visited.insert(n);
	return false;
}
Пример #9
0
bool VariablesInExpression::VarSeenInTerm(const ASTNode& var,
		const ASTNode& term) {
	// This only returns true if we are searching for variables that aren't arrays.
	assert(var.GetKind() == SYMBOL && var.GetIndexWidth() == 0);
	if (term.isConstant())
		return false;

	getSymbol(term);

	SymbolPtrSet visited;
	ASTNodeSet *symbols = new ASTNodeSet();
	vector<Symbols*> av;
	VarSeenInTerm(symbol_graph[term.GetNodeNum()], visited, *symbols, av);

	bool result = (symbols->count(var) != 0);

	//cerr << "visited:" << visited.size() << endl;
	//cerr << "av:" << av.size() << endl;
	//cerr << "Term is const" << term.isConstant() << endl;


	if (visited.size() > 250) // No use caching it, unless we've done some work.
	{
		sort(av.begin(), av.end());

		//cout << "===" << endl;
		for (size_t i = 0; i < av.size(); i++) {
			if (i!=0 && av[i] == av[i-1])
				continue;

			const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second;
			//cout << "set: " << i << " " << sym.size() << endl;
			symbols->insert(sym.begin(), sym.end());
		}
		TermsAlreadySeenMap.insert(make_pair(symbol_graph[term.GetNodeNum()], symbols));
		//cout << "finish" << symbols->size() << endl;
		//cout << "===" << endl;
		result = (symbols->count(var) != 0);
	} else {
		const int size = av.size();
		for (int i = 0; i < size; i++) {
			if (result)
				break;
			const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second;
			result |= (sym.find(var) != sym.end());
		}
		delete symbols;
	}
	return result;
}
Пример #10
0
// If n0 is replaced by n1 in the substitution map. Will it cause a loop?
// i.e. will the dependency graph be an acyclic graph still.
// For example, if we have x = F(y,z,w), it would make the substitutionMap loop
// if there's already z = F(x).
bool SubstitutionMap::loops(const ASTNode& n0, const ASTNode& n1)
{
  if (n0.GetKind() != SYMBOL)
    return false; // sometimes this function is called with constants on the
                  // lhs.

  if (n1.isConstant())
    return false; // constants contain no variables. Can't loop.

  // We are adding an edge FROM n0, so unless there is already an edge TO n0,
  // there is no change it can loop. Unless adding this would add a TO and FROM
  // edge.
  if (rhs.find(n0) == rhs.end())
  {
    return vars.VarSeenInTerm(n0, n1);
  }

  if (n1.GetKind() == SYMBOL && dependsOn.find(n1) == dependsOn.end())
    return false; // The rhs is a symbol and doesn't appear.

  if (debug_substn)
    cout << loopCount++ << endl;

  bool destruct = true;
  ASTNodeSet* dependN = vars.SetofVarsSeenInTerm(n1, destruct);

  if (debug_substn)
  {
    cout << n0 << " "
         << n1.GetNodeNum(); //<< " Expression size:" << bm->NodeSize(n1,true);
    cout << "Variables in expression: " << dependN->size() << endl;
  }

  set<ASTNode> depend(dependN->begin(), dependN->end());

  if (destruct)
    delete dependN;

  set<ASTNode> visited;
  loops_helper(depend, visited);

  bool loops = visited.find(n0) != visited.end();

  if (debug_substn)
    cout << "Visited:" << visited.size() << "Loops:" << loops << endl;

  return (loops);
}
Пример #11
0
// Builds a set of the SYMBOLS that were found under the "term". The symbols are the union of "found" and
// all the sets : TermsAlreadySeen(av[0]) union ... TermsAlreadySeen(av[n])".
void VariablesInExpression::VarSeenInTerm(Symbols* term, SymbolPtrSet& visited,
		ASTNodeSet& found, vector<Symbols*>& av) {
	if (visited.find(term) != visited.end()) {
		return;
	}

	if (term->isLeaf()) {
		found.insert(term->found);
		return;
	}

	visited.insert(term);

	SymbolPtrToNode::const_iterator it;
	if ((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
		// We've previously built the set of variables below this "symbols".
		// It's not added into "found" because its sometimes 70k variables
		// big, and if there are no other symbols discovered it's a terrible
		// waste to create a copy of the set. Instead we store (in effect)
		// a pointer to the set.
		av.push_back(term);
		return;
	}

	for (vector<Symbols*>::const_iterator it = term->children.begin(), itend =
			term->children.end(); it != itend; it++) {
		VarSeenInTerm(*it, visited, found, av);
	}

	return;
}//End of VarSeenInTerm
Пример #12
0
  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);
  }
Пример #13
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);
  }
} 
Пример #14
0
// Print in lisp format
ostream& Lisp_Print(ostream& os, const ASTNode& n, int indentation)
{
  // Clear the PrintMap
  Lisp_AlreadyPrintedSet.clear();
  Lisp_Print_indent(os, n, indentation);
  printf("\n");
  return os;
}
Пример #15
0
// Take the transitive closure of the varsToCheck. Storing the result in
// visited.
void SubstitutionMap::loops_helper(const set<ASTNode>& varsToCheck,
                                   set<ASTNode>& visited)
{
  set<ASTNode>::const_iterator visitedIt = visited.begin();

  set<ASTNode> toVisit;
  vector<ASTNode> visitedN;

  // for each variable.
  for (set<ASTNode>::const_iterator varIt = varsToCheck.begin();
       varIt != varsToCheck.end(); varIt++)
  {
    while (visitedIt != visited.end() && *visitedIt < *varIt)
      visitedIt++;

    if ((visitedIt != visited.end()) && *visitedIt == *varIt)
      continue;

    visitedN.push_back(*varIt);
    DependsType::iterator it;
    if ((it = dependsOn.find(*varIt)) != dependsOn.end())
    {
      Symbols* s = it->second;
      bool destruct;
      ASTNodeSet* varsSeen = vars.SetofVarsSeenInTerm(s, destruct);
      toVisit.insert(varsSeen->begin(), varsSeen->end());

      if (destruct)
        delete varsSeen;
    }
  }

  visited.insert(visitedN.begin(), visitedN.end());

  visitedN.clear();

  if (toVisit.size() != 0)
    loops_helper(toVisit, visited);
}
Пример #16
0
    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;
    }
Пример #17
0
/* Maintains a set of nodes that have already been seen. So that deeply shared
 * AND,OR operations are not
 * flattened multiple times.
 */
void FlattenKindNoDuplicates(const Kind k, const ASTVec& children,
                             ASTVec& flat_children,
                             ASTNodeSet& alreadyFlattened)
{
  const ASTVec::const_iterator ch_end = children.end();
  for (ASTVec::const_iterator it = children.begin(); it != ch_end; it++)
  {
    const Kind ck = it->GetKind();
    if (k == ck)
    {
      if (alreadyFlattened.find(*it) == alreadyFlattened.end())
      {
        alreadyFlattened.insert(*it);
        FlattenKindNoDuplicates(k, it->GetChildren(), flat_children,
                                alreadyFlattened);
      }
    }
    else
    {
      flat_children.push_back(*it);
    }
  }
}
Пример #18
0
void printSMTLIB1VarDeclsToStream(ASTNodeSet& symbols, ostream& os)
{
	for (ASTNodeSet::const_iterator i = symbols.begin(), iend = symbols.end(); i
			!= iend; i++)
	{
      const BEEV::ASTNode& a = *i;

      // Should be a symbol.
      assert(a.GetKind()== SYMBOL);

		switch (a.GetType())
		{
      case BEEV::BITVECTOR_TYPE:

        os << ":extrafuns (( ";
        a.nodeprint(os);
        os << " BitVec[" << a.GetValueWidth() << "]";
        os << " ))" << endl;
        break;
      case BEEV::ARRAY_TYPE:
        os << ":extrafuns (( ";
        a.nodeprint(os);
        os << " Array[" << a.GetIndexWidth();
        os << ":" << a.GetValueWidth() << "] ))" << endl;
        break;
      case BEEV::BOOLEAN_TYPE:
        os << ":extrapreds (( ";
        a.nodeprint(os);
        os << "))" << endl;
        break;
      default:
        BEEV::FatalError("printVarDeclsToStream: Unsupported type",a);
        break;
      }
    }
  } //printVarDeclsToStream
Пример #19
0
namespace BEEV {
  //external parser table for declared symbols. Only symbols which are
  //declared are stored here.
  ASTNodeSet _parser_symbol_table;

  // FUNC: This function maintains a map between LET-var names and
  // LET-expressions
  //
  //1. if the Let-var is already defined in the LET scope, then the
  //1. function returns an error.
  //
  //2. if the Let-var is already declared variable in the input, then
  //2. the function returns an error
  //
  //3. otherwise add the <var,letExpr> pair to the _letid_expr table.
  void BeevMgr::LetExprMgr(const ASTNode& var, const ASTNode& letExpr) {
    ASTNodeMap::iterator it;
    if(((it = _letid_expr_map.find(var)) != _letid_expr_map.end()) && 
       it->second != ASTUndefined) {      
      FatalError("LetExprMgr:The LET-var v has already been defined in this LET scope: v =", var);
    }

    if(_parser_symbol_table.find(var) != _parser_symbol_table.end()) {
      FatalError("LetExprMgr:This var is already declared. cannot redeclare as a letvar: v =", var);
    }

    _letid_expr_map[var] = letExpr;   
  }

  //this function looksup the "var to letexpr map" and returns the
  //corresponding letexpr. if there is no letexpr, then it simply
  //returns the var.
  ASTNode BeevMgr::ResolveID(const ASTNode& v) {
    if(v.GetKind() != SYMBOL) {
      return v;
    }

    if(_parser_symbol_table.find(v) != _parser_symbol_table.end()) {
      return v;
    }

    ASTNodeMap::iterator it;
    if((it =_letid_expr_map.find(v)) != _letid_expr_map.end()) {
      if(it->second == ASTUndefined) 
	FatalError("Unresolved Identifier: ",v);
      else
	return it->second;
    }

    //this is to mark the let-var as undefined. the let var is defined
    //only after the LetExprMgr has completed its work, and until then
    //'v' is undefined. 
    //
    //declared variables also get stored in this map, but there value
    //is ASTUndefined. This is really a hack. I don't know how to get
    //rid of this hack.
    _letid_expr_map[v] = ASTUndefined;
    return v;    
  }
  
  // This function simply cleans up the LetID -> LetExpr Map.   
  void BeevMgr::CleanupLetIDMap(void) { 
    ASTNodeMap::iterator it = _letid_expr_map.begin();
    ASTNodeMap::iterator itend = _letid_expr_map.end();
    for(;it!=itend;it++) {
      if(it->second != ASTUndefined) {
	it->first.SetValueWidth(0);
	it->first.SetIndexWidth(0);
      }
    }
    _letid_expr_map.clear();
  }
};
Пример #20
0
/** Internal function to print in lisp format.  Assume newline
    and indentation printed already before first line.  Recursive
    calls will have newline & indent, though */
ostream& Lisp_Print1(ostream& os, const ASTNode& n, int indentation)
{
  if (!n.IsDefined())
  {
    os << "<undefined>";
    return os;
  }
  Kind kind = n.GetKind();
  // FIXME: figure out how to avoid symbols with same names as kinds.
  //    if (kind == READ) {
  //      const ASTVec &children = GetChildren();
  //      children[0].LispPrint1(os, indentation);
  //  os << "[" << children[1] << "]";
  //    } else
  if (kind == BOOLEXTRACT)
  {
    const ASTVec& children = n.GetChildren();
    // child 0 is a symbol.  Print without the NodeNum.
    os << n.GetNodeNum() << ":";

    children[0].nodeprint(os, true);
    os << "{";
    children[1].nodeprint(os, true);
    os << "}";
  }
  else if (kind == NOT)
  {
    const ASTVec& children = n.GetChildren();
    os << n.GetNodeNum() << ":";
    os << "(NOT ";
    Lisp_Print1(os, children[0], indentation);
    os << ")";
  }
  else if (n.Degree() == 0)
  {
    // Symbol or a kind with no children print as index:NAME if shared,
    // even if they have been printed before.
    os << n.GetNodeNum() << ":";
    n.nodeprint(os, true);
    // os << "(" << _int_node_ptr->_ref_count << ")";
    // os << "{" << GetValueWidth() << "}";
  }
  else if (Lisp_AlreadyPrintedSet.find(n) != Lisp_AlreadyPrintedSet.end())
  {
    // print non-symbols as "[index]" if seen before.
    os << "[" << n.GetNodeNum() << "]";
    //         << "(" << _int_node_ptr->_ref_count << ")";
  }
  else
  {
    Lisp_AlreadyPrintedSet.insert(n);
    const ASTVec& children = n.GetChildren();
    os << n.GetNodeNum() << ":"
       //<< "(" << _int_node_ptr->_ref_count << ")"
       << "(" << kind << " ";
    // os << "{" << GetValueWidth() << "}";
    ASTVec::const_iterator iend = children.end();
    for (ASTVec::const_iterator i = children.begin(); i != iend; i++)
    {
      Lisp_Print_indent(os, *i, indentation + 2);
    }
    os << ")";
  }
  return os;
}
Пример #21
0
namespace printer
{

using std::string;
using namespace BEEV;

ASTNodeSet Lisp_AlreadyPrintedSet;
ostream& Lisp_Print_indent(ostream& os, const ASTNode& n, int indentation);

/** Internal function to print in lisp format.  Assume newline
    and indentation printed already before first line.  Recursive
    calls will have newline & indent, though */
ostream& Lisp_Print1(ostream& os, const ASTNode& n, int indentation)
{
  if (!n.IsDefined())
  {
    os << "<undefined>";
    return os;
  }
  Kind kind = n.GetKind();
  // FIXME: figure out how to avoid symbols with same names as kinds.
  //    if (kind == READ) {
  //      const ASTVec &children = GetChildren();
  //      children[0].LispPrint1(os, indentation);
  //  os << "[" << children[1] << "]";
  //    } else
  if (kind == BOOLEXTRACT)
  {
    const ASTVec& children = n.GetChildren();
    // child 0 is a symbol.  Print without the NodeNum.
    os << n.GetNodeNum() << ":";

    children[0].nodeprint(os, true);
    os << "{";
    children[1].nodeprint(os, true);
    os << "}";
  }
  else if (kind == NOT)
  {
    const ASTVec& children = n.GetChildren();
    os << n.GetNodeNum() << ":";
    os << "(NOT ";
    Lisp_Print1(os, children[0], indentation);
    os << ")";
  }
  else if (n.Degree() == 0)
  {
    // Symbol or a kind with no children print as index:NAME if shared,
    // even if they have been printed before.
    os << n.GetNodeNum() << ":";
    n.nodeprint(os, true);
    // os << "(" << _int_node_ptr->_ref_count << ")";
    // os << "{" << GetValueWidth() << "}";
  }
  else if (Lisp_AlreadyPrintedSet.find(n) != Lisp_AlreadyPrintedSet.end())
  {
    // print non-symbols as "[index]" if seen before.
    os << "[" << n.GetNodeNum() << "]";
    //         << "(" << _int_node_ptr->_ref_count << ")";
  }
  else
  {
    Lisp_AlreadyPrintedSet.insert(n);
    const ASTVec& children = n.GetChildren();
    os << n.GetNodeNum() << ":"
       //<< "(" << _int_node_ptr->_ref_count << ")"
       << "(" << kind << " ";
    // os << "{" << GetValueWidth() << "}";
    ASTVec::const_iterator iend = children.end();
    for (ASTVec::const_iterator i = children.begin(); i != iend; i++)
    {
      Lisp_Print_indent(os, *i, indentation + 2);
    }
    os << ")";
  }
  return os;
}

// Print in lisp format
ostream& Lisp_Print(ostream& os, const ASTNode& n, int indentation)
{
  // Clear the PrintMap
  Lisp_AlreadyPrintedSet.clear();
  Lisp_Print_indent(os, n, indentation);
  printf("\n");
  return os;
}

// Print newline and indentation, then print the thing.
ostream& Lisp_Print_indent(ostream& os, const ASTNode& n, int indentation)
{
  os << std::endl << spaces(indentation);
  Lisp_Print1(os, n, indentation);
  return os;
}
}
Пример #22
0
  ASTNode
  RemoveUnconstrained::topLevel_other(const ASTNode &n, Simplifier *simplifier)
  {
    if (n.GetKind() == SYMBOL)
      return n; // top level is an unconstrained symbol/.

    simplifier_convenient = simplifier;

    ASTNodeSet noCheck; // We don't want to check some expensive nodes over and over again.

    vector<MutableASTNode*> variable_array;

    MutableASTNode* topMutable = MutableASTNode::build(n);

    vector<MutableASTNode*> extracts;
    topMutable->getDisjointExtractVariables(extracts);
    if (extracts.size() > 0)
      {
          splitExtractOnly(extracts);
      }

    topMutable->getAllUnconstrainedVariables(variable_array);

    for (int i =0; i < variable_array.size() ; i++)
      {
        // Don't make this is a reference. If the vector gets resized, it will point to
        // memory that no longer contains the object.
        MutableASTNode& muteNode = *variable_array[i];

        const ASTNode var = muteNode.n;
        assert(var.GetKind() == SYMBOL);

        if (!muteNode.isUnconstrained())
          continue;

        MutableASTNode& muteParent = muteNode.getParent();

        if (noCheck.find(muteParent.n) != noCheck.end())
          {
            continue;
          }

        vector <MutableASTNode*> mutable_children = muteParent.children;

        //nb. The children might be dirty. i.e. not have substitutions written through them yet.
        ASTVec children;
        children.reserve(mutable_children.size());
        for (int j = 0; j <mutable_children.size(); j++ )
          children.push_back(mutable_children[j]->n);

        const size_t numberOfChildren = children.size();
        const Kind kind = muteNode.getParent().n.GetKind();
        unsigned width = muteNode.getParent().n.GetValueWidth();
        unsigned indexWidth = muteNode.getParent().n.GetIndexWidth();

        ASTNode other;
        MutableASTNode* muteOther;

          if(numberOfChildren == 2)
          {
            if (children[0] != var)
              {
                other = children[0];
                muteOther = mutable_children[0];
              }
            else
              {
                other = children[1];
                muteOther = mutable_children[1];
              }

            if (kind != AND && kind != OR && kind != BVOR && kind != BVAND)
              if (other == var)
                continue; // Most rules don't like duplicate variables.
          }
        else
          {
            if (kind != AND && kind != OR && kind != BVOR && kind != BVAND)
              {
                  int found = 0;

                  for (int i = 0; i < numberOfChildren; i++)
                    {
                      if (children[i] == var)
                        found++;
                   }

                    if (found != 1)
                      continue; // Most rules don't like duplicate variables.
              }
          }

          /*
          cout << i << " " << kind << " " << variable_array.size() <<  " " << mutable_children.size() << endl;
          cout << "children[0]" << children[0] << endl;
          cout << "children[1]" << children[1] << endl;
          cout << muteParent.n << endl;

           */

        switch (kind)
          {
        case BVCONCAT:
          assert(numberOfChildren == 2);
          if (mutable_children[0]->isUnconstrained() && (mutable_children[1]->isUnconstrained()))
            {
              ASTNode v =replaceParentWithFresh(muteParent, variable_array);

              ASTNode top_lhs = bm.CreateBVConst(32, width - 1);
              ASTNode bottom_lhs = bm.CreateBVConst(32, children[1].GetValueWidth());

              ASTNode top_rhs = bm.CreateBVConst(32, children[1].GetValueWidth()- 1);
              ASTNode bottom_rhs = bm.CreateBVConst(32, 0);

              ASTNode lhs = nf->CreateTerm(BVEXTRACT, children[0].GetValueWidth(), v,top_lhs, bottom_lhs);
              ASTNode rhs = nf->CreateTerm(BVEXTRACT, children[1].GetValueWidth(), v,top_rhs, bottom_rhs);

              replace(children[0],lhs);
              replace(children[1],rhs);
            }
          break;
        case NOT:
          {
            ASTNode v =replaceParentWithFresh(muteParent, variable_array);
            replace(children[0], nf->CreateNode(NOT, v));
          }
          break;

        case BVUMINUS:
        case BVNEG:
          {
            assert(numberOfChildren ==1);
            ASTNode v =replaceParentWithFresh(muteParent, variable_array);
            replace(var, nf->CreateTerm(kind, width,v));
          }
          break;

        case BVSGT:
        case BVSGE:
        case BVGT:
        case BVGE:
          {
            width = var.GetValueWidth();
            if (width ==1)
              continue; // Hard to get right, not used often.

            ASTNode biggestNumber, smallestNumber;

            if (kind == BVSGT || kind == BVSGE)
              {
                // 011111111 (most positive number.)
                CBV max = CONSTANTBV::BitVector_Create(width, false);
                CONSTANTBV::BitVector_Fill(max);
                CONSTANTBV::BitVector_Bit_Off(max, width - 1);
                biggestNumber = bm.CreateBVConst(max, width);

                // 1000000000 (most negative number.)
                max = CONSTANTBV::BitVector_Create(width, true);
                CONSTANTBV::BitVector_Bit_On(max, width - 1);
                smallestNumber = bm.CreateBVConst(max, width);
              }
            else if (kind == BVGT || kind == BVGE)
              {
                biggestNumber = bm.CreateMaxConst(width);
                smallestNumber =  bm.CreateZeroConst(width);
              }
            else
              FatalError("SDFA!@S");


            ASTNode c1,c2;
            if (kind == BVSGT || kind == BVGT)
              {
                c1= biggestNumber;
                c2 = smallestNumber;
              }
            else if (kind == BVSGE || kind == BVGE)
              {
                c1= smallestNumber;
                c2 = biggestNumber;
              }
            else
              FatalError("SDFA!@S");

            if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode lhs = nf->CreateTerm(ITE, width, v, bm.CreateOneConst(width), bm.CreateZeroConst(width));
                ASTNode rhs = nf->CreateTerm(ITE, width, v, bm.CreateZeroConst(width), bm.CreateOneConst(width));
                replace(children[0], lhs);
                replace(children[1], rhs);
              }
            else if (children[0] == var && children[1].isConstant())
              {
                if (children[1] == c1)
                  continue; // always false. Or always false.

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateTerm(ITE, width, v,biggestNumber, smallestNumber);
                replace(var, rhs);
              }
            else if (children[1] == var && children[0].isConstant())
              {
                if (children[0] == c2)
                  continue;  // always false. Or always false.

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateTerm(ITE, width, v, smallestNumber, biggestNumber);
                replace(var, rhs);
              }
            else // One side is a variable. The other is anything.
              {
            	 bool varOnLHS = (var == children[0]);

                // All the ASTNode vars need to map to their existing MutableASTNodes. So we collect all the variables
                vector<MutableASTNode*> vars;
                set<MutableASTNode*> visited;
                muteOther->getAllVariablesRecursively(vars, visited);
                visited.clear();

                map<ASTNode, MutableASTNode *> create;
                for (vector<MutableASTNode*>::iterator it = vars.begin(); it != vars.end();it++)
                  create.insert(make_pair((*it)->n, *it));
                vars.clear();

                ASTNode v= bm.CreateFreshVariable(0, 0, "STP_INTERNAL_comparison");

                ASTNode rhs;
                ASTNode n;
                if (varOnLHS)
                  {
                    rhs = nf->CreateTerm(ITE, width, v, biggestNumber, smallestNumber);

                    if (kind == BVSGE || kind == BVGE)
                      n= nf->CreateNode(OR, v, nf->CreateNode(EQ, mutable_children[1]->toASTNode(nf), c1));
                    else
                      n= nf->CreateNode(AND, v, nf->CreateNode(NOT,nf->CreateNode(EQ, mutable_children[1]->toASTNode(nf), c1)));
                  }
                else
                  {
                    rhs = nf->CreateTerm(ITE, width, v, smallestNumber, biggestNumber);

                    if (kind == BVSGE || kind == BVGE)
                      n= nf->CreateNode(OR, v, nf->CreateNode(EQ, mutable_children[0]->toASTNode(nf), c2));
                    else
                      n= nf->CreateNode(AND, v, nf->CreateNode(NOT,nf->CreateNode(EQ, mutable_children[0]->toASTNode(nf), c2)));
                  }
                replace(var, rhs);
                MutableASTNode *newN = MutableASTNode::build(n,create);
                muteParent.replaceWithAnotherNode(newN);
                //assert(muteParent.checkInvariant());
              }
          }
          break;


        case AND:
        case OR:
        case BVOR:
        case BVAND:
          {
            if (allChildrenAreUnconstrained(mutable_children))
              {
                ASTNodeSet already;
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                for (int i =0; i < numberOfChildren;i++)
                  {
                    /* to avoid problems with:
                    734:(AND
                    732:unconstrained_4
                    716:unconstrained_2
                    732:unconstrained_4)
                    */
                    if (already.find(children[i]) == already.end())
                      {
                        replace(children[i], v);
                        already.insert(children[i]);
                      }
                  }
              }
            else
              {
                // Hack. ff.stp has a 325k node conjunction
                // So we check if all the children are unconstrained each time
                // we find a new unconstrained conjunct. This means that if
                // eventually all the nodes become unconstrained we will miss it
                // and not rewrite the AND to a fresh unconstrained variable.

                if (mutable_children.size() > 200)
                  noCheck.insert(muteParent.n);
              }
          }
          break;

        case XOR:
        case BVXOR:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTVec others;
                for (int i = 0; i < numberOfChildren; i++)
                {
                    if (children[i] !=var)
                        others.push_back(mutable_children[i]->toASTNode(nf));
                }
                assert(others.size() +1 == numberOfChildren);
                assert(others.size() >=1);

                if (kind == XOR)
              {
                ASTNode xorNode = nf->CreateNode(XOR, others);
                replace(var, nf->CreateNode(XOR, v, xorNode));
              }
            else
              {
                ASTNode xorNode ;
                if (others.size() > 1 )
                  xorNode = nf->CreateTerm(BVXOR, width, others);
                else
                  xorNode = others[0];

                replace(var, nf->CreateTerm(BVXOR, width, v, xorNode));
              }
              }
           break;

        case ITE:
              {
                if (indexWidth > 0)
                  continue; // don't do arrays.

                if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained() && children[0] != children[1])
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.ASTTrue);
                    replace(children[1], v);

                  }
                else if (mutable_children[0]->isUnconstrained() && mutable_children[2]->isUnconstrained() && children[0] != children[2])
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.ASTFalse);
                    replace(children[2], v);
                  }
                else if (mutable_children[1]->isUnconstrained() && mutable_children[2]->isUnconstrained())
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[1], v);
                    if (children[1] != children[2])
                      replace(children[2], v);
                  }
              }
              break;
        case BVLEFTSHIFT:
        case BVRIGHTSHIFT:
        case BVSRSHIFT:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
                  {
                     assert(children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateZeroConst(width));
                     replace(children[0], v);
                  }
              }
             break;

        case BVMOD:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained() && bm.UserFlags.isSet("unconstrained-bvmod", "0") )
                  {
                     assert (children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateZeroConst(width));
                     replace(children[0], v);
                  }
              }
             break;


        case BVDIV:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
                  {
                     assert (children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateOneConst(width));
                     replace(children[0], v);
                  }
              }
             break;
        case BVMULT:
              {
                 assert(numberOfChildren == 2);

                if (mutable_children[1]->isUnconstrained() && mutable_children[0]->isUnconstrained()) // both are unconstrained
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.CreateOneConst(width));
                    replace(children[1], v);
                  }

                if (other.isConstant() && simplifier->BVConstIsOdd(other))
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    ASTNode inverse = simplifier->MultiplicativeInverse(other);
                    ASTNode rhs = nf->CreateTerm(BVMULT, width, inverse, v);
                    replace(var, rhs);
                  }

                break;
        case IFF:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateNode(ITE, v, muteOther->toASTNode(nf), nf->CreateNode(NOT, muteOther->toASTNode(nf)));
                replace(var, rhs);
              }
          break;
        case EQ:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                width = var.GetValueWidth();
                ASTNode rhs = nf->CreateTerm(ITE, width, v, muteOther->toASTNode(nf), nf->CreateTerm(BVPLUS, width, muteOther->toASTNode(nf),
                    bm.CreateOneConst(width)));

                replace(var, rhs);
              }
          break;
        case BVSUB:
          {
            assert(numberOfChildren == 2);

            ASTNode v =replaceParentWithFresh(muteParent, variable_array);

            ASTNode rhs;

            if (children[0] == var)
              rhs= nf->CreateTerm(BVPLUS, width, v, muteOther->toASTNode(nf));
            if (children[1] == var)
              rhs= nf->CreateTerm(BVSUB, width, muteOther->toASTNode(nf), v);

            replace(var, rhs);
          }
          break;

        case BVPLUS:
              {
                ASTVec other;
                for (int i = 0; i < children.size(); i++)
                  if (children[i] != var)
                    other.push_back(mutable_children[i]->toASTNode(nf));

                assert(other.size() == children.size()-1);
                assert(other.size() >=1);

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs;
                if (other.size() > 1)
                  rhs = nf->CreateTerm(BVSUB, width, v, nf->CreateTerm(BVPLUS, width, other));
                else
                  rhs = nf->CreateTerm(BVSUB, width, v, other[0]);

                replace(var, rhs);
              }
           break;
        case BVEXTRACT:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                const unsigned resultWidth = width;
                const unsigned operandWidth = var.GetValueWidth();
                assert(children[0] == var); // It can't be anywhere else.

                // Create Fresh variables to pad the LHS and RHS.
                const unsigned high = children[1].GetUnsignedConst();
                const unsigned low = children[2].GetUnsignedConst();
                assert(high >=low);

                const int rhsSize = low;
                const int lhsSize = operandWidth - high - 1;

                ASTNode current = v;
                int newWidth = v.GetValueWidth();

                if (lhsSize > 0)
                  {
                    ASTNode lhsFresh = bm.CreateFreshVariable(0, lhsSize, "lhs_padding");
                    current = nf->CreateTerm(BVCONCAT, newWidth + lhsSize, lhsFresh, current);
                    newWidth += lhsSize;
                  }

                if (rhsSize > 0)
                  {
                    ASTNode rhsFresh = bm.CreateFreshVariable(0, rhsSize, "rhs_padding");
                    current = nf->CreateTerm(BVCONCAT, newWidth + rhsSize, current, rhsFresh);
                    newWidth += rhsSize;
                  }

                assert(newWidth == operandWidth);
                replace(var, current);
              }
        break;
        default:
          {
            //cerr << "!!!!" << kind << endl;
          }

            //        cerr << var;
              //      cerr << parent;

              }
          }
      }

    ASTNode result = topMutable->toASTNode(nf);
    topMutable->cleanup();
    //cout << result;
    return result;
  }
Пример #23
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);
  }
}