#include <assert.h>
-namespace BEEV {
- //some global variables that are set through commandline options. it
- //is best that these variables remain global. Default values set
- //here
- //
- //collect statistics on certain functions
- bool stats = false;
- //print DAG nodes
- bool print_nodes = false;
- //tentative global var to allow for variable activity optimization
- //in the SAT solver. deprecated.
- bool variable_activity_optimize = false;
- //run STP in optimized mode
- bool optimize = true;
- //do sat refinement, i.e. underconstraint the problem, and feed to
- //SAT. if this works, great. else, add a set of suitable constraints
- //to re-constraint the problem correctly, and call SAT again, until
- //all constraints have been added.
- bool arrayread_refinement = true;
- //flag to control write refinement
- bool arraywrite_refinement = true;
- //check the counterexample against the original input to STP
- bool check_counterexample = false;
- //construct the counterexample in terms of original variable based
- //on the counterexample returned by SAT solver
- bool construct_counterexample = true;
- bool print_counterexample = false;
- //if this option is true then print the way dawson wants using a
- //different printer. do not use this printer.
- bool print_arrayval_declaredorder = false;
- //flag to decide whether to print "valid/invalid" or not
- bool print_output = false;
- //do linear search in the array values of an input array. experimental
- bool linear_search = false;
- //print the variable order chosen by the sat solver while it is
- //solving.
- bool print_sat_varorder = false;
- //turn on word level bitvector solver
- bool wordlevel_solve = true;
- //turn off XOR flattening
- bool xor_flatten = false;
-
- //the smtlib parser has been turned on
- bool smtlib_parser_enable = false;
- //print the input back
- bool print_STPinput_back = false;
-
- enum BEEV::inputStatus input_status = NOT_DECLARED;
-
- // Used only in smtlib lexer/parser
- ASTNode SingleBitOne;
- ASTNode SingleBitZero;
-
- //global BEEVMGR for the parser
- BeevMgr * globalBeevMgr_for_parser;
-
- void (*vc_error_hdlr)(const char* err_msg) = NULL;
- /** This is reusable empty vector, for representing empty children arrays */
- ASTVec _empty_ASTVec;
- ////////////////////////////////////////////////////////////////
- // ASTInternal members
- ////////////////////////////////////////////////////////////////
- /** Trivial but virtual destructor */
- ASTInternal::~ASTInternal() { }
-
- ////////////////////////////////////////////////////////////////
- // ASTInterior members
- ////////////////////////////////////////////////////////////////
- /** Copy constructor */
- // ASTInterior::ASTInterior(const ASTInterior &int_node)
- // {
- // _kind = int_node._kind;
- // _children = int_node._children;
- // }
-
- /** Trivial but virtual destructor */
- ASTInterior::~ASTInterior() { }
-
- // FIXME: Darn it! I think this ends up copying the children twice!
- /** Either return an old node or create it if it doesn't exist.
- Note that nodes are physically allocated in the hash table. */
-
- // There is an inelegance here that I don't know how to solve. I'd
- // like to heap allocate and do some other initialization on keys only
- // if they aren't in the hash table. It would be great if the
- // "insert" method took a "creator" class so that I could do that
- // between when it notices that the key is not there and when it
- // inserts it. Alternatively, it would be great if I could insert the
- // temporary key and replace it if it actually got inserted. But STL
- // hash_set doesn't have the creator feature and paternalistically
- // declares that keys are immutable, even though (it seems to me) that
- // they could be mutated if the hash value and eq values did not
- // change.
-
- ASTInterior *BeevMgr::LookupOrCreateInterior(ASTInterior *n_ptr) {
- ASTInteriorSet::iterator it;
-
- if ((it = _interior_unique_table.find(n_ptr)) == _interior_unique_table.end()) {
- // Make a new ASTInterior node
- // We want (NOT alpha) always to have alpha.nodenum + 1.
- if (n_ptr->GetKind() == NOT) {
- n_ptr->SetNodeNum(n_ptr->GetChildren()[0].GetNodeNum()+1);
- }
- else {
- n_ptr->SetNodeNum(NewNodeNum());
- }
- pair<ASTInteriorSet::const_iterator, bool> p = _interior_unique_table.insert(n_ptr);
- return *(p.first);
- }
- else
- // Delete the temporary node, and return the found node.
- delete n_ptr;
- return *it;
- }
-
- size_t ASTInterior::ASTInteriorHasher::operator() (const ASTInterior *int_node_ptr) const {
- //size_t hashval = 0;
- size_t hashval = ((size_t) int_node_ptr->GetKind());
- const ASTVec &ch = int_node_ptr->GetChildren();
- ASTVec::const_iterator iend = ch.end();
- for (ASTVec::const_iterator i = ch.begin(); i != iend; i++) {
- //Using "One at a time hash" by Bob Jenkins
- hashval += i->Hash();
- hashval += (hashval << 10);
- hashval ^= (hashval >> 6);
- }
-
- hashval += (hashval << 3);
- hashval ^= (hashval >> 11);
- hashval += (hashval << 15);
- return hashval;
- //return hashval += ((size_t) int_node_ptr->GetKind());
- }
-
-
- void ASTInterior::CleanUp() {
- // cout << "Deleting node " << this->GetNodeNum() << endl;
- _bm._interior_unique_table.erase(this);
- delete this;
- }
-
- ////////////////////////////////////////////////////////////////
- // ASTNode members
- ////////////////////////////////////////////////////////////////
- //ASTNode constructors are inlined in AST.h
- bool ASTNode::IsAlreadyPrinted() const {
- BeevMgr &bm = GetBeevMgr();
- return (bm.AlreadyPrintedSet.find(*this) != bm.AlreadyPrintedSet.end());
- }
-
- void ASTNode::nodeprint(ostream& os, bool c_friendly) const
- {
+namespace BEEV
+{
+//some global variables that are set through commandline options. it
+//is best that these variables remain global. Default values set
+//here
+//
+//collect statistics on certain functions
+bool stats = false;
+//print DAG nodes
+bool print_nodes = false;
+//tentative global var to allow for variable activity optimization
+//in the SAT solver. deprecated.
+bool variable_activity_optimize = false;
+//run STP in optimized mode
+bool optimize = true;
+//do sat refinement, i.e. underconstraint the problem, and feed to
+//SAT. if this works, great. else, add a set of suitable constraints
+//to re-constraint the problem correctly, and call SAT again, until
+//all constraints have been added.
+bool arrayread_refinement = true;
+//flag to control write refinement
+bool arraywrite_refinement = true;
+//check the counterexample against the original input to STP
+bool check_counterexample = false;
+//construct the counterexample in terms of original variable based
+//on the counterexample returned by SAT solver
+bool construct_counterexample = true;
+bool print_counterexample = false;
+//if this option is true then print the way dawson wants using a
+//different printer. do not use this printer.
+bool print_arrayval_declaredorder = false;
+//flag to decide whether to print "valid/invalid" or not
+bool print_output = false;
+//do linear search in the array values of an input array. experimental
+bool linear_search = false;
+//print the variable order chosen by the sat solver while it is
+//solving.
+bool print_sat_varorder = false;
+//turn on word level bitvector solver
+bool wordlevel_solve = true;
+//turn off XOR flattening
+bool xor_flatten = false;
+
+//the smtlib parser has been turned on
+bool smtlib_parser_enable = false;
+//print the input back
+bool print_STPinput_back = false;
+
+enum BEEV::inputStatus input_status = NOT_DECLARED;
+
+// Used only in smtlib lexer/parser
+ASTNode SingleBitOne;
+ASTNode SingleBitZero;
+
+//global BEEVMGR for the parser
+BeevMgr * globalBeevMgr_for_parser;
+
+void (*vc_error_hdlr)(const char* err_msg) = NULL;
+/** This is reusable empty vector, for representing empty children arrays */
+ASTVec _empty_ASTVec;
+////////////////////////////////////////////////////////////////
+// ASTInternal members
+////////////////////////////////////////////////////////////////
+/** Trivial but virtual destructor */
+ASTInternal::~ASTInternal()
+{
+}
+
+////////////////////////////////////////////////////////////////
+// ASTInterior members
+////////////////////////////////////////////////////////////////
+/** Copy constructor */
+// ASTInterior::ASTInterior(const ASTInterior &int_node)
+// {
+// _kind = int_node._kind;
+// _children = int_node._children;
+// }
+
+/** Trivial but virtual destructor */
+ASTInterior::~ASTInterior()
+{
+}
+
+// FIXME: Darn it! I think this ends up copying the children twice!
+/** Either return an old node or create it if it doesn't exist.
+ Note that nodes are physically allocated in the hash table. */
+
+// There is an inelegance here that I don't know how to solve. I'd
+// like to heap allocate and do some other initialization on keys only
+// if they aren't in the hash table. It would be great if the
+// "insert" method took a "creator" class so that I could do that
+// between when it notices that the key is not there and when it
+// inserts it. Alternatively, it would be great if I could insert the
+// temporary key and replace it if it actually got inserted. But STL
+// hash_set doesn't have the creator feature and paternalistically
+// declares that keys are immutable, even though (it seems to me) that
+// they could be mutated if the hash value and eq values did not
+// change.
+
+ASTInterior *BeevMgr::LookupOrCreateInterior(ASTInterior *n_ptr)
+{
+ ASTInteriorSet::iterator it;
+
+ if ((it = _interior_unique_table.find(n_ptr)) == _interior_unique_table.end())
+ {
+ // Make a new ASTInterior node
+ // We want (NOT alpha) always to have alpha.nodenum + 1.
+ if (n_ptr->GetKind() == NOT)
+ {
+ n_ptr->SetNodeNum(n_ptr->GetChildren()[0].GetNodeNum() + 1);
+ }
+ else
+ {
+ n_ptr->SetNodeNum(NewNodeNum());
+ }
+ pair<ASTInteriorSet::const_iterator, bool> p = _interior_unique_table.insert(n_ptr);
+ return *(p.first);
+ }
+ else
+ // Delete the temporary node, and return the found node.
+ delete n_ptr;
+ return *it;
+}
+
+size_t ASTInterior::ASTInteriorHasher::operator()(const ASTInterior *int_node_ptr) const
+{
+ //size_t hashval = 0;
+ size_t hashval = ((size_t) int_node_ptr->GetKind());
+ const ASTVec &ch = int_node_ptr->GetChildren();
+ ASTVec::const_iterator iend = ch.end();
+ for (ASTVec::const_iterator i = ch.begin(); i != iend; i++)
+ {
+ //Using "One at a time hash" by Bob Jenkins
+ hashval += i->Hash();
+ hashval += (hashval << 10);
+ hashval ^= (hashval >> 6);
+ }
+
+ hashval += (hashval << 3);
+ hashval ^= (hashval >> 11);
+ hashval += (hashval << 15);
+ return hashval;
+ //return hashval += ((size_t) int_node_ptr->GetKind());
+}
+
+void ASTInterior::CleanUp()
+{
+ // cout << "Deleting node " << this->GetNodeNum() << endl;
+ _bm._interior_unique_table.erase(this);
+ delete this;
+}
+
+////////////////////////////////////////////////////////////////
+// ASTNode members
+////////////////////////////////////////////////////////////////
+//ASTNode constructors are inlined in AST.h
+bool ASTNode::IsAlreadyPrinted() const
+{
+ BeevMgr &bm = GetBeevMgr();
+ return (bm.AlreadyPrintedSet.find(*this) != bm.AlreadyPrintedSet.end());
+}
+
+void ASTNode::nodeprint(ostream& os, bool c_friendly) const
+{
_int_node_ptr->nodeprint(os, c_friendly);
- }
-
- void ASTNode::MarkAlreadyPrinted() const {
- // FIXME: Fetching BeevMgr is annoying. Can we put this in lispprinter class?
- BeevMgr &bm = GetBeevMgr();
- bm.AlreadyPrintedSet.insert(*this);
- }
-
- // Get the name from a symbol (char *). It's an error if kind != SYMBOL
- const char * const ASTNode::GetName() const {
- if (GetKind() != SYMBOL)
- FatalError("GetName: Called GetName on a non-symbol: ", *this);
- return ((ASTSymbol *) _int_node_ptr)->GetName();
- }
-
- void ASTNode::NFASTPrint(int l, int max, int prefix) const {
- //****************************************
- // stop
- //****************************************
- if(l > max){
- return;
- }
-
- //****************************************
- // print
- //****************************************
- printf("[%10d]", 0);
- for(int i = 0; i < prefix; i++){
- printf(" ");
- }
- cout << GetKind();
- printf("\n");
-
- //****************************************
- // recurse
- //****************************************
-
- const ASTVec &children = GetChildren();
- ASTVec::const_iterator it = children.begin();
- for(; it != children.end(); it++) {
- it->NFASTPrint(l+1, max, prefix+1);
- }
- }
-
- // Print in lisp format
- ostream &ASTNode::LispPrint(ostream &os, int indentation) const {
- // Clear the PrintMap
- BeevMgr& bm = GetBeevMgr();
- bm.AlreadyPrintedSet.clear();
- LispPrint_indent(os, indentation);
- printf("\n");
- return os;
- }
-
- // Print newline and indentation, then print the thing.
- ostream &ASTNode::LispPrint_indent(ostream &os,
- int indentation) const
- {
- os << endl << spaces(indentation);
- LispPrint1(os, indentation);
- return os;
- }
-
- /** Internal function to print in lisp format. Assume newline
- and indentation printed already before first line. Recursive
- calls will have newline & indent, though */
- ostream &ASTNode::LispPrint1(ostream &os, int indentation) const {
- if (!IsDefined()) {
- os << "<undefined>";
- return os;
- }
- Kind kind = 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 == BVGETBIT) {
- const ASTVec &children = GetChildren();
- // child 0 is a symbol. Print without the NodeNum.
- os << GetNodeNum() << ":";
-
-
-
- children[0]._int_node_ptr->nodeprint(os);
- //os << "{" << children[1].GetBVConst() << "}";
- os << "{";
- children[1]._int_node_ptr->nodeprint(os);
- os << "}";
- } else if (kind == NOT) {
- const ASTVec &children = GetChildren();
- os << GetNodeNum() << ":";
- os << "(NOT ";
- children[0].LispPrint1(os, indentation);
- os << ")";
- }
- else if (Degree() == 0) {
- // Symbol or a kind with no children print as index:NAME if shared,
- // even if they have been printed before.
- os << GetNodeNum() << ":";
- _int_node_ptr->nodeprint(os);
- // os << "(" << _int_node_ptr->_ref_count << ")";
- // os << "{" << GetValueWidth() << "}";
- }
- else if (IsAlreadyPrinted()) {
- // print non-symbols as "[index]" if seen before.
- os << "[" << GetNodeNum() << "]";
- // << "(" << _int_node_ptr->_ref_count << ")";
- }
- else {
- MarkAlreadyPrinted();
- const ASTVec &children = GetChildren();
- os << 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++) {
- i->LispPrint_indent(os, indentation+2);
+}
+
+void ASTNode::MarkAlreadyPrinted() const
+{
+ // FIXME: Fetching BeevMgr is annoying. Can we put this in lispprinter class?
+ BeevMgr &bm = GetBeevMgr();
+ bm.AlreadyPrintedSet.insert(*this);
+}
+
+// Get the name from a symbol (char *). It's an error if kind != SYMBOL
+const char * const ASTNode::GetName() const
+{
+ if (GetKind() != SYMBOL)
+ FatalError("GetName: Called GetName on a non-symbol: ", *this);
+ return ((ASTSymbol *) _int_node_ptr)->GetName();
+}
+
+void ASTNode::NFASTPrint(int l, int max, int prefix) const
+{
+ //****************************************
+ // stop
+ //****************************************
+ if (l > max)
+ {
+ return;
}
- os << ")";
- }
- return os;
- }
-
- //print in PRESENTATION LANGUAGE
- //
- //two pass algorithm:
- //
- //1. In the first pass, letize this Node, N: i.e. if a node
- //1. appears more than once in N, then record this fact.
- //
- //2. In the second pass print a "global let" and then print N
- //2. as follows: Every occurence of a node occuring more than
- //2. once is replaced with the corresponding let variable.
- ostream& ASTNode::PL_Print(ostream &os,
- int indentation) const {
- // Clear the PrintMap
- BeevMgr& bm = GetBeevMgr();
- bm.PLPrintNodeSet.clear();
- bm.NodeLetVarMap.clear();
- bm.NodeLetVarVec.clear();
- bm.NodeLetVarMap1.clear();
-
- //pass 1: letize the node
- LetizeNode();
-
- //pass 2:
- //
- //2. print all the let variables and their counterpart expressions
- //2. as follows (LET var1 = expr1, var2 = expr2, ...
- //
- //3. Then print the Node itself, replacing every occurence of
- //3. expr1 with var1, expr2 with var2, ...
- //os << "(";
- if(0 < bm.NodeLetVarMap.size()) {
- //ASTNodeMap::iterator it=bm.NodeLetVarMap.begin();
- //ASTNodeMap::iterator itend=bm.NodeLetVarMap.end();
- std::vector<pair<ASTNode,ASTNode> >::iterator it = bm.NodeLetVarVec.begin();
- std::vector<pair<ASTNode,ASTNode> >::iterator itend = bm.NodeLetVarVec.end();
-
- os << "(LET ";
- //print the let var first
- it->first.PL_Print1(os,indentation,false);
- os << " = ";
- //print the expr
- it->second.PL_Print1(os,indentation,false);
-
- //update the second map for proper printing of LET
- bm.NodeLetVarMap1[it->second] = it->first;
-
- for(it++;it!=itend;it++) {
- os << "," << endl;
- //print the let var first
- it->first.PL_Print1(os,indentation,false);
- os << " = ";
- //print the expr
- it->second.PL_Print1(os,indentation,false);
-
- //update the second map for proper printing of LET
- bm.NodeLetVarMap1[it->second] = it->first;
- }
-
- os << " IN " << endl;
- PL_Print1(os,indentation, true);
- os << ") ";
- }
- else
- PL_Print1(os,indentation, false);
- //os << " )";
- os << " ";
- return os;
- } //end of PL_Print()
-
- //traverse "*this", and construct "let variables" for terms that
- //occur more than once in "*this".
- void ASTNode::LetizeNode(void) const {
- Kind kind = this->GetKind();
-
- if(kind == SYMBOL ||
- kind == BVCONST ||
- kind == FALSE ||
- kind == TRUE)
- return;
-
- //FIXME: this is ugly.
- BeevMgr& bm = GetBeevMgr();
- const ASTVec &c = this->GetChildren();
- for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++){
- ASTNode ccc = *it;
- if(bm.PLPrintNodeSet.find(ccc) == bm.PLPrintNodeSet.end()){
- //If branch: if *it is not in NodeSet then,
- //
- //1. add it to NodeSet
- //
- //2. Letize its childNodes
-
- //FIXME: Fetching BeevMgr is annoying. Can we put this in
- //some kind of a printer class
- bm.PLPrintNodeSet.insert(ccc);
- //debugging
- //cerr << ccc;
- ccc.LetizeNode();
- }
- else{
- Kind k = ccc.GetKind();
- if(k == SYMBOL ||
- k == BVCONST ||
- k == FALSE ||
- k == TRUE)
- continue;
-
- //0. Else branch: Node has been seen before
+
+ //****************************************
+ // print
+ //****************************************
+ printf("[%10d]", 0);
+ for (int i = 0; i < prefix; i++)
+ {
+ printf(" ");
+ }
+ cout << GetKind();
+ printf("\n");
+
+ //****************************************
+ // recurse
+ //****************************************
+
+ const ASTVec &children = GetChildren();
+ ASTVec::const_iterator it = children.begin();
+ for (; it != children.end(); it++)
+ {
+ it->NFASTPrint(l + 1, max, prefix + 1);
+ }
+}
+
+// Print in lisp format
+ostream &ASTNode::LispPrint(ostream &os, int indentation) const
+{
+ // Clear the PrintMap
+ BeevMgr& bm = GetBeevMgr();
+ bm.AlreadyPrintedSet.clear();
+ LispPrint_indent(os, indentation);
+ printf("\n");
+ return os;
+}
+
+// Print newline and indentation, then print the thing.
+ostream &ASTNode::LispPrint_indent(ostream &os, int indentation) const
+{
+ os << endl << spaces(indentation);
+ LispPrint1(os, indentation);
+ return os;
+}
+
+/** Internal function to print in lisp format. Assume newline
+ and indentation printed already before first line. Recursive
+ calls will have newline & indent, though */
+ostream &ASTNode::LispPrint1(ostream &os, int indentation) const
+{
+ if (!IsDefined())
+ {
+ os << "<undefined>";
+ return os;
+ }
+ Kind kind = 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 == BVGETBIT)
+ {
+ const ASTVec &children = GetChildren();
+ // child 0 is a symbol. Print without the NodeNum.
+ os << GetNodeNum() << ":";
+
+ children[0]._int_node_ptr->nodeprint(os);
+ //os << "{" << children[1].GetBVConst() << "}";
+ os << "{";
+ children[1]._int_node_ptr->nodeprint(os);
+ os << "}";
+ }
+ else if (kind == NOT)
+ {
+ const ASTVec &children = GetChildren();
+ os << GetNodeNum() << ":";
+ os << "(NOT ";
+ children[0].LispPrint1(os, indentation);
+ os << ")";
+ }
+ else if (Degree() == 0)
+ {
+ // Symbol or a kind with no children print as index:NAME if shared,
+ // even if they have been printed before.
+ os << GetNodeNum() << ":";
+ _int_node_ptr->nodeprint(os);
+ // os << "(" << _int_node_ptr->_ref_count << ")";
+ // os << "{" << GetValueWidth() << "}";
+ }
+ else if (IsAlreadyPrinted())
+ {
+ // print non-symbols as "[index]" if seen before.
+ os << "[" << GetNodeNum() << "]";
+ // << "(" << _int_node_ptr->_ref_count << ")";
+ }
+ else
+ {
+ MarkAlreadyPrinted();
+ const ASTVec &children = GetChildren();
+ os << 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++)
+ {
+ i->LispPrint_indent(os, indentation + 2);
+ }
+ os << ")";
+ }
+ return os;
+}
+
+//print in PRESENTATION LANGUAGE
+//
+//two pass algorithm:
+//
+//1. In the first pass, letize this Node, N: i.e. if a node
+//1. appears more than once in N, then record this fact.
+//
+//2. In the second pass print a "global let" and then print N
+//2. as follows: Every occurence of a node occuring more than
+//2. once is replaced with the corresponding let variable.
+ostream& ASTNode::PL_Print(ostream &os, int indentation) const
+{
+ // Clear the PrintMap
+ BeevMgr& bm = GetBeevMgr();
+ bm.PLPrintNodeSet.clear();
+ bm.NodeLetVarMap.clear();
+ bm.NodeLetVarVec.clear();
+ bm.NodeLetVarMap1.clear();
+
+ //pass 1: letize the node
+ LetizeNode();
+
+ //pass 2:
//
- //1. Check if the node has a corresponding letvar in the
- //1. NodeLetVarMap.
+ //2. print all the let variables and their counterpart expressions
+ //2. as follows (LET var1 = expr1, var2 = expr2, ...
//
- //2. if no, then create a new var and add it to the
- //2. NodeLetVarMap
- if(bm.NodeLetVarMap.find(ccc) == bm.NodeLetVarMap.end()) {
- //Create a new symbol. Get some name. if it conflicts with a
- //declared name, too bad.
- int sz = bm.NodeLetVarMap.size();
- ostringstream oss;
- oss << "let_k_" << sz;
-
- ASTNode CurrentSymbol = bm.CreateSymbol(oss.str().c_str());
- CurrentSymbol.SetValueWidth(this->GetValueWidth());
- CurrentSymbol.SetIndexWidth(this->GetIndexWidth());
- /* 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.]
- */
-
- bm.NodeLetVarMap[ccc] = CurrentSymbol;
- std::pair<ASTNode,ASTNode> node_letvar_pair(CurrentSymbol,ccc);
- bm.NodeLetVarVec.push_back(node_letvar_pair);
+ //3. Then print the Node itself, replacing every occurence of
+ //3. expr1 with var1, expr2 with var2, ...
+ //os << "(";
+ if (0 < bm.NodeLetVarMap.size())
+ {
+ //ASTNodeMap::iterator it=bm.NodeLetVarMap.begin();
+ //ASTNodeMap::iterator itend=bm.NodeLetVarMap.end();
+ std::vector<pair<ASTNode, ASTNode> >::iterator it = bm.NodeLetVarVec.begin();
+ std::vector<pair<ASTNode, ASTNode> >::iterator itend = bm.NodeLetVarVec.end();
+
+ os << "(LET ";
+ //print the let var first
+ it->first.PL_Print1(os, indentation, false);
+ os << " = ";
+ //print the expr
+ it->second.PL_Print1(os, indentation, false);
+
+ //update the second map for proper printing of LET
+ bm.NodeLetVarMap1[it->second] = it->first;
+
+ for (it++; it != itend; it++)
+ {
+ os << "," << endl;
+ //print the let var first
+ it->first.PL_Print1(os, indentation, false);
+ os << " = ";
+ //print the expr
+ it->second.PL_Print1(os, indentation, false);
+
+ //update the second map for proper printing of LET
+ bm.NodeLetVarMap1[it->second] = it->first;
+ }
+
+ os << " IN " << endl;
+ PL_Print1(os, indentation, true);
+ os << ") ";
+ }
+ else
+ PL_Print1(os, indentation, false);
+ //os << " )";
+ os << " ";
+ return os;
+} //end of PL_Print()
+
+//traverse "*this", and construct "let variables" for terms that
+//occur more than once in "*this".
+void ASTNode::LetizeNode(void) const
+{
+ Kind kind = this->GetKind();
+
+ if (kind == SYMBOL || kind == BVCONST || kind == FALSE || kind == TRUE)
+ return;
+
+ //FIXME: this is ugly.
+ BeevMgr& bm = GetBeevMgr();
+ const ASTVec &c = this->GetChildren();
+ for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode ccc = *it;
+ if (bm.PLPrintNodeSet.find(ccc) == bm.PLPrintNodeSet.end())
+ {
+ //If branch: if *it is not in NodeSet then,
+ //
+ //1. add it to NodeSet
+ //
+ //2. Letize its childNodes
+
+ //FIXME: Fetching BeevMgr is annoying. Can we put this in
+ //some kind of a printer class
+ bm.PLPrintNodeSet.insert(ccc);
+ //debugging
+ //cerr << ccc;
+ ccc.LetizeNode();
+ }
+ else
+ {
+ Kind k = ccc.GetKind();
+ if (k == SYMBOL || k == BVCONST || k == FALSE || k == TRUE)
+ continue;
+
+ //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 (bm.NodeLetVarMap.find(ccc) == bm.NodeLetVarMap.end())
+ {
+ //Create a new symbol. Get some name. if it conflicts with a
+ //declared name, too bad.
+ int sz = bm.NodeLetVarMap.size();
+ ostringstream oss;
+ oss << "let_k_" << sz;
+
+ ASTNode CurrentSymbol = bm.CreateSymbol(oss.str().c_str());
+ CurrentSymbol.SetValueWidth(this->GetValueWidth());
+ CurrentSymbol.SetIndexWidth(this->GetIndexWidth());
+ /* 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.]
+ */
+
+ bm.NodeLetVarMap[ccc] = CurrentSymbol;
+ std::pair<ASTNode, ASTNode> node_letvar_pair(CurrentSymbol, ccc);
+ bm.NodeLetVarVec.push_back(node_letvar_pair);
+ }
+ }
+ }
+} //end of LetizeNode()
+
+void ASTNode::PL_Print1(ostream& os, int indentation, bool letize) const
+{
+ //os << spaces(indentation);
+ //os << endl << spaces(indentation);
+ if (!IsDefined())
+ {
+ os << "<undefined>";
+ return;
+ }
+
+ //if this node is present in the letvar Map, then print the letvar
+ BeevMgr &bm = GetBeevMgr();
+
+ //this is to print letvars for shared subterms inside the printing
+ //of "(LET v0 = term1, v1=term1@term2,...
+ if ((bm.NodeLetVarMap1.find(*this) != bm.NodeLetVarMap1.end()) && !letize)
+ {
+ (bm.NodeLetVarMap1[*this]).PL_Print1(os, indentation, letize);
+ return;
}
- }
- }
- } //end of LetizeNode()
-
- void ASTNode::PL_Print1(ostream& os,
- int indentation,
- bool letize) const {
- //os << spaces(indentation);
- //os << endl << spaces(indentation);
- if (!IsDefined()) {
- os << "<undefined>";
- return;
- }
-
- //if this node is present in the letvar Map, then print the letvar
- BeevMgr &bm = GetBeevMgr();
-
- //this is to print letvars for shared subterms inside the printing
- //of "(LET v0 = term1, v1=term1@term2,...
- if((bm.NodeLetVarMap1.find(*this) != bm.NodeLetVarMap1.end()) && !letize) {
- (bm.NodeLetVarMap1[*this]).PL_Print1(os,indentation,letize);
- return;
- }
-
- //this is to print letvars for shared subterms inside the actual
- //term to be printed
- if((bm.NodeLetVarMap.find(*this) != bm.NodeLetVarMap.end()) && letize) {
- (bm.NodeLetVarMap[*this]).PL_Print1(os,indentation,letize);
- return;
- }
-
- //otherwise print it normally
- Kind kind = GetKind();
- const ASTVec &c = GetChildren();
- switch(kind) {
- case BVGETBIT:
- c[0].PL_Print1(os,indentation,letize);
- os << "{";
- c[1].PL_Print1(os,indentation,letize);
- os << "}";
- break;
- case BITVECTOR:
- os << "BITVECTOR(";
- unsigned char * str;
- str = CONSTANTBV::BitVector_to_Hex(c[0].GetBVConst());
- os << str << ")";
- CONSTANTBV::BitVector_Dispose(str);
- break;
- case BOOLEAN:
- os << "BOOLEAN";
- break;
- case FALSE:
- case TRUE:
- os << kind;
- break;
- case BVCONST:
- case SYMBOL:
- _int_node_ptr->nodeprint(os);
- break;
- case READ:
- c[0].PL_Print1(os, indentation,letize);
- os << "[";
- c[1].PL_Print1(os,indentation,letize);
- os << "]";
- break;
- case WRITE:
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << " WITH [";
- c[1].PL_Print1(os,indentation,letize);
- os << "] := ";
- c[2].PL_Print1(os,indentation,letize);
- os << ")";
- os << endl;
- break;
- case BVUMINUS:
- os << kind << "( ";
- c[0].PL_Print1(os,indentation,letize);
- os << ")";
- break;
- case NOT:
- os << "NOT(";
- c[0].PL_Print1(os,indentation,letize);
- os << ") " << endl;
- break;
- case BVNEG:
- os << " ~(";
- c[0].PL_Print1(os,indentation,letize);
- os << ")";
- break;
- case BVCONCAT:
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << " @ ";
- c[1].PL_Print1(os,indentation,letize);
- os << ")" << endl;
- break;
- case BVOR:
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << " | ";
- c[1].PL_Print1(os,indentation,letize);
- os << ")";
- break;
- case BVAND:
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << " & ";
- c[1].PL_Print1(os,indentation,letize);
- os << ")";
- break;
- case BVEXTRACT:
- c[0].PL_Print1(os,indentation,letize);
- os << "[";
- os << GetUnsignedConst(c[1]);
- os << ":";
- os << GetUnsignedConst(c[2]);
- os << "]";
- break;
- case BVLEFTSHIFT:
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << " << ";
- os << GetUnsignedConst(c[1]);
- os << ")";
- break;
- case BVRIGHTSHIFT:
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << " >> ";
- os << GetUnsignedConst(c[1]);
- os << ")";
- break;
- case BVMULT:
- case BVSUB:
- case BVPLUS:
- case SBVDIV:
- case SBVREM:
- case BVDIV:
- case BVMOD:
- os << kind << "(";
- os << this->GetValueWidth();
- for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- os << ", " << endl;
- it->PL_Print1(os,indentation,letize);
- }
- os << ")" << endl;
- break;
- case ITE:
- os << "IF(";
- c[0].PL_Print1(os,indentation,letize);
- os << ")" << endl;
- os << "THEN ";
- c[1].PL_Print1(os,indentation,letize);
- os << endl << "ELSE ";
- c[2].PL_Print1(os,indentation,letize);
- os << endl << "ENDIF";
- break;
- case BVLT:
- case BVLE:
- case BVGT:
- case BVGE:
- case BVXOR:
- case BVNAND:
- case BVNOR:
- case BVXNOR:
- os << kind << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << ",";
- c[1].PL_Print1(os,indentation,letize);
- os << ")" << endl;
- break;
- case BVSLT:
- os << "SBVLT" << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << ",";
- c[1].PL_Print1(os,indentation,letize);
- os << ")" << endl;
- break;
- case BVSLE:
- os << "SBVLE" << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << ",";
- c[1].PL_Print1(os,indentation,letize);
- os << ")" << endl;
- break;
- case BVSGT:
- os << "SBVGT" << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << ",";
- c[1].PL_Print1(os,indentation,letize);
- os << ")" << endl;
- break;
- case BVSGE:
- os << "SBVGE" << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << ",";
- c[1].PL_Print1(os,indentation,letize);
- os << ")" << endl;
- break;
- case EQ:
- c[0].PL_Print1(os,indentation,letize);
- os << " = ";
- c[1].PL_Print1(os,indentation,letize);
- os << endl;
- break;
- case NEQ:
- c[0].PL_Print1(os,indentation,letize);
- os << " /= ";
- c[1].PL_Print1(os,indentation,letize);
- os << endl;
- break;
- case AND:
- case OR:
- case NAND:
- case NOR:
- case XOR: {
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- ASTVec::const_iterator it=c.begin();
- ASTVec::const_iterator itend=c.end();
-
- it++;
- for(;it!=itend;it++) {
- os << " " << kind << " ";
- it->PL_Print1(os,indentation,letize);
- os << endl;
- }
- os << ")";
- break;
- }
- case IFF:
- os << "(";
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << ")";
- os << " <=> ";
- os << "(";
- c[1].PL_Print1(os,indentation,letize);
- os << ")";
- os << ")";
- os << endl;
- break;
- case IMPLIES:
- os << "(";
- os << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << ")";
- os << " => ";
- os << "(";
- c[1].PL_Print1(os,indentation,letize);
- os << ")";
- os << ")";
- os << endl;
- break;
- case BVSX:
- case BVZX:
- os << kind << "(";
- c[0].PL_Print1(os,indentation,letize);
- os << ",";
- os << this->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("PL_Print1: printing not implemented for this kind: ",*this);
- break;
- }
- } //end of PL_Print1()
-
- ////////////////////////////////////////////////////////////////
- // BeevMgr members
- ////////////////////////////////////////////////////////////////
- ASTNode BeevMgr::CreateNode(Kind kind, const ASTVec & back_children) {
- // create a new node. Children will be modified.
- ASTInterior *n_ptr = new ASTInterior(kind, *this);
-
- // insert all of children at end of new_children.
- ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
- return n;
- }
-
- ASTNode BeevMgr::CreateNode(Kind kind,
- const ASTNode& child0,
- const ASTVec & back_children) {
-
- ASTInterior *n_ptr = new ASTInterior(kind, *this);
- ASTVec &front_children = n_ptr->_children;
- front_children.push_back(child0);
- ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
- return n;
- }
-
- ASTNode BeevMgr::CreateNode(Kind kind,
- const ASTNode& child0,
- const ASTNode& child1,
- const ASTVec & back_children) {
-
- ASTInterior *n_ptr = new ASTInterior(kind, *this);
- ASTVec &front_children = n_ptr->_children;
- front_children.push_back(child0);
- front_children.push_back(child1);
- ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
- return n;
- }
-
-
- ASTNode BeevMgr::CreateNode(Kind kind,
- const ASTNode& child0,
- const ASTNode& child1,
- const ASTNode& child2,
- const ASTVec & back_children) {
- ASTInterior *n_ptr = new ASTInterior(kind, *this);
- ASTVec &front_children = n_ptr->_children;
- front_children.push_back(child0);
- front_children.push_back(child1);
- front_children.push_back(child2);
- ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
- return n;
- }
-
-
- ASTInterior *BeevMgr::CreateInteriorNode(Kind kind,
- // children array of this node will be modified.
- ASTInterior *n_ptr,
- const ASTVec & back_children) {
-
- // insert back_children at end of front_children
- ASTVec &front_children = n_ptr->_children;
-
- front_children.insert(front_children.end(), back_children.begin(), back_children.end());
-
- // check for undefined nodes.
- ASTVec::const_iterator it_end = front_children.end();
- for (ASTVec::const_iterator it = front_children.begin(); it != it_end; it++) {
- if (it->IsNull())
- FatalError("CreateInteriorNode: Undefined childnode in CreateInteriorNode: ", ASTUndefined);
- }
-
- return LookupOrCreateInterior(n_ptr);
- }
-
- /** Trivial but virtual destructor */
- ASTSymbol::~ASTSymbol() {}
-
- ostream &operator<<(ostream &os, const ASTNodeMap &nmap)
- {
- ASTNodeMap::const_iterator iend = nmap.end();
- for (ASTNodeMap::const_iterator i = nmap.begin(); i!=iend; i++) {
- os << "Key: " << i->first << endl;
- os << "Value: " << i->second << endl;
- }
- return os;
- }
-
- ////////////////////////////////////////////////////////////////
- // BeevMgr member functions to create ASTSymbol and ASTBVConst
- ////////////////////////////////////////////////////////////////
- ASTNode BeevMgr::CreateSymbol(const char * const name)
- {
- ASTSymbol temp_sym(name, *this);
- ASTNode n(LookupOrCreateSymbol(temp_sym));
- return n;
- }
+
+ //this is to print letvars for shared subterms inside the actual
+ //term to be printed
+ if ((bm.NodeLetVarMap.find(*this) != bm.NodeLetVarMap.end()) && letize)
+ {
+ (bm.NodeLetVarMap[*this]).PL_Print1(os, indentation, letize);
+ return;
+ }
+
+ //otherwise print it normally
+ Kind kind = GetKind();
+ const ASTVec &c = GetChildren();
+ switch (kind)
+ {
+ case BVGETBIT:
+ c[0].PL_Print1(os, indentation, letize);
+ os << "{";
+ c[1].PL_Print1(os, indentation, letize);
+ os << "}";
+ break;
+ case BITVECTOR:
+ os << "BITVECTOR(";
+ unsigned char * str;
+ str = CONSTANTBV::BitVector_to_Hex(c[0].GetBVConst());
+ os << str << ")";
+ CONSTANTBV::BitVector_Dispose(str);
+ break;
+ case BOOLEAN:
+ os << "BOOLEAN";
+ break;
+ case FALSE:
+ case TRUE:
+ os << kind;
+ break;
+ case BVCONST:
+ case SYMBOL:
+ _int_node_ptr->nodeprint(os);
+ break;
+ case READ:
+ c[0].PL_Print1(os, indentation, letize);
+ os << "[";
+ c[1].PL_Print1(os, indentation, letize);
+ os << "]";
+ break;
+ case WRITE:
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << " WITH [";
+ c[1].PL_Print1(os, indentation, letize);
+ os << "] := ";
+ c[2].PL_Print1(os, indentation, letize);
+ os << ")";
+ os << endl;
+ break;
+ case BVUMINUS:
+ os << kind << "( ";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ")";
+ break;
+ case NOT:
+ os << "NOT(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ") " << endl;
+ break;
+ case BVNEG:
+ os << " ~(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ")";
+ break;
+ case BVCONCAT:
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << " @ ";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")" << endl;
+ break;
+ case BVOR:
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << " | ";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")";
+ break;
+ case BVAND:
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << " & ";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")";
+ break;
+ case BVEXTRACT:
+ c[0].PL_Print1(os, indentation, letize);
+ os << "[";
+ os << GetUnsignedConst(c[1]);
+ os << ":";
+ os << GetUnsignedConst(c[2]);
+ os << "]";
+ break;
+ case BVLEFTSHIFT:
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << " << ";
+ os << GetUnsignedConst(c[1]);
+ os << ")";
+ break;
+ case BVRIGHTSHIFT:
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << " >> ";
+ os << GetUnsignedConst(c[1]);
+ os << ")";
+ break;
+ case BVMULT:
+ case BVSUB:
+ case BVPLUS:
+ case SBVDIV:
+ case SBVREM:
+ case BVDIV:
+ case BVMOD:
+ os << kind << "(";
+ os << this->GetValueWidth();
+ for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ os << ", " << endl;
+ it->PL_Print1(os, indentation, letize);
+ }
+ os << ")" << endl;
+ break;
+ case ITE:
+ os << "IF(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ")" << endl;
+ os << "THEN ";
+ c[1].PL_Print1(os, indentation, letize);
+ os << endl << "ELSE ";
+ c[2].PL_Print1(os, indentation, letize);
+ os << endl << "ENDIF";
+ break;
+ case BVLT:
+ case BVLE:
+ case BVGT:
+ case BVGE:
+ case BVXOR:
+ case BVNAND:
+ case BVNOR:
+ case BVXNOR:
+ os << kind << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ",";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")" << endl;
+ break;
+ case BVSLT:
+ os << "SBVLT" << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ",";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")" << endl;
+ break;
+ case BVSLE:
+ os << "SBVLE" << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ",";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")" << endl;
+ break;
+ case BVSGT:
+ os << "SBVGT" << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ",";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")" << endl;
+ break;
+ case BVSGE:
+ os << "SBVGE" << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ",";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")" << endl;
+ break;
+ case EQ:
+ c[0].PL_Print1(os, indentation, letize);
+ os << " = ";
+ c[1].PL_Print1(os, indentation, letize);
+ os << endl;
+ break;
+ case NEQ:
+ c[0].PL_Print1(os, indentation, letize);
+ os << " /= ";
+ c[1].PL_Print1(os, indentation, letize);
+ os << endl;
+ break;
+ case AND:
+ case OR:
+ case NAND:
+ case NOR:
+ case XOR:
+ {
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ ASTVec::const_iterator it = c.begin();
+ ASTVec::const_iterator itend = c.end();
+
+ it++;
+ for (; it != itend; it++)
+ {
+ os << " " << kind << " ";
+ it->PL_Print1(os, indentation, letize);
+ os << endl;
+ }
+ os << ")";
+ break;
+ }
+ case IFF:
+ os << "(";
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ")";
+ os << " <=> ";
+ os << "(";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")";
+ os << ")";
+ os << endl;
+ break;
+ case IMPLIES:
+ os << "(";
+ os << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ")";
+ os << " => ";
+ os << "(";
+ c[1].PL_Print1(os, indentation, letize);
+ os << ")";
+ os << ")";
+ os << endl;
+ break;
+ case BVSX:
+ case BVZX:
+ os << kind << "(";
+ c[0].PL_Print1(os, indentation, letize);
+ os << ",";
+ os << this->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("PL_Print1: printing not implemented for this kind: ", *this);
+ break;
+ }
+} //end of PL_Print1()
+
+////////////////////////////////////////////////////////////////
+// BeevMgr members
+////////////////////////////////////////////////////////////////
+ASTNode BeevMgr::CreateNode(Kind kind, const ASTVec & back_children)
+{
+ // create a new node. Children will be modified.
+ ASTInterior *n_ptr = new ASTInterior(kind, *this);
+
+ // insert all of children at end of new_children.
+ ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+ return n;
+}
+
+ASTNode BeevMgr::CreateNode(Kind kind, const ASTNode& child0, const ASTVec & back_children)
+{
+
+ ASTInterior *n_ptr = new ASTInterior(kind, *this);
+ ASTVec &front_children = n_ptr->_children;
+ front_children.push_back(child0);
+ ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+ return n;
+}
+
+ASTNode BeevMgr::CreateNode(Kind kind, const ASTNode& child0, const ASTNode& child1, const ASTVec & back_children)
+{
+
+ ASTInterior *n_ptr = new ASTInterior(kind, *this);
+ ASTVec &front_children = n_ptr->_children;
+ front_children.push_back(child0);
+ front_children.push_back(child1);
+ ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+ return n;
+}
+
+ASTNode BeevMgr::CreateNode(Kind kind, const ASTNode& child0, const ASTNode& child1, const ASTNode& child2, const ASTVec & back_children)
+{
+ ASTInterior *n_ptr = new ASTInterior(kind, *this);
+ ASTVec &front_children = n_ptr->_children;
+ front_children.push_back(child0);
+ front_children.push_back(child1);
+ front_children.push_back(child2);
+ ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+ return n;
+}
+
+ASTInterior *BeevMgr::CreateInteriorNode(Kind kind,
+// children array of this node will be modified.
+ ASTInterior *n_ptr,
+ const ASTVec & back_children)
+{
+
+ // insert back_children at end of front_children
+ ASTVec &front_children = n_ptr->_children;
+
+ front_children.insert(front_children.end(), back_children.begin(), back_children.end());
+
+ // check for undefined nodes.
+ ASTVec::const_iterator it_end = front_children.end();
+ for (ASTVec::const_iterator it = front_children.begin(); it != it_end; it++)
+ {
+ if (it->IsNull())
+ FatalError("CreateInteriorNode: Undefined childnode in CreateInteriorNode: ", ASTUndefined);
+ }
+
+ return LookupOrCreateInterior(n_ptr);
+}
+
+/** Trivial but virtual destructor */
+ASTSymbol::~ASTSymbol()
+{
+}
+
+ostream &operator<<(ostream &os, const ASTNodeMap &nmap)
+{
+ ASTNodeMap::const_iterator iend = nmap.end();
+ for (ASTNodeMap::const_iterator i = nmap.begin(); i != iend; i++)
+ {
+ os << "Key: " << i->first << endl;
+ os << "Value: " << i->second << endl;
+ }
+ return os;
+}
+
+////////////////////////////////////////////////////////////////
+// BeevMgr member functions to create ASTSymbol and ASTBVConst
+////////////////////////////////////////////////////////////////
+ASTNode BeevMgr::CreateSymbol(const char * const name)
+{
+ ASTSymbol temp_sym(name, *this);
+ ASTNode n(LookupOrCreateSymbol(temp_sym));
+ return n;
+}
#ifndef NATIVE_C_ARITH
- //Create a ASTBVConst node
- ASTNode BeevMgr::CreateBVConst(unsigned int width,
- unsigned long long int bvconst){
- if(width > (sizeof(unsigned long long int)<<3) || width <= 0)
- FatalError("CreateBVConst: trying to create a bvconst of width: ", ASTUndefined, width);
-
-
- CBV bv = CONSTANTBV::BitVector_Create(width, true);
- unsigned long c_val = (~((unsigned long)0)) & bvconst;
- unsigned int copied = 0;
-
- // sizeof(unsigned long) returns the number of bytes in unsigned
- // long. In order to convert it to bits, we need to shift left by
- // 3. Hence, sizeof(unsigned long) << 3
-
- //The algo below works as follows: It starts by copying the
- //lower-order bits of the input "bvconst" in chunks of size =
- //number of bits in unsigned long. The variable "copied" keeps
- //track of the number of chunks copied so far
-
- while(copied + (sizeof(unsigned long)<<3) < width){
- CONSTANTBV::BitVector_Chunk_Store(bv, sizeof(unsigned long)<<3,copied,c_val);
- bvconst = bvconst >> (sizeof(unsigned long) << 3);
- c_val = (~((unsigned long)0)) & bvconst;
- copied += sizeof(unsigned long) << 3;
- }
- CONSTANTBV::BitVector_Chunk_Store(bv,width - copied,copied,c_val);
- return CreateBVConst(bv,width);
- }
-
- ASTNode BeevMgr::CreateBVConst(string*& strval, int base, int bit_width) {
-
- if(!(2 == base || 10 == base || 16 == base))
- {
- FatalError("CreateBVConst: unsupported base: ",ASTUndefined,base);
- }
-
- //checking if the input is in the correct format
- CBV bv = CONSTANTBV::BitVector_Create(bit_width,true);
- CONSTANTBV::ErrCode e;
- if(2 == base){
- e = CONSTANTBV::BitVector_from_Bin(bv, (unsigned char*) strval->c_str());
- }else if(10 == base){
- e = CONSTANTBV::BitVector_from_Dec(bv, (unsigned char*) strval->c_str());
- }else if(16 == base){
- e = CONSTANTBV::BitVector_from_Hex(bv, (unsigned char*) strval->c_str());
- }else{
- e = CONSTANTBV::ErrCode_Pars;
- }
-
- if(0 != e) {
- cerr << "CreateBVConst: " << BitVector_Error(e);
- FatalError("",ASTUndefined);
- }
-
- return CreateBVConst(bv, bit_width);
- }
-
-
-
- //Create a ASTBVConst node from std::string
- ASTNode BeevMgr::CreateBVConst(const char* const strval, int base) {
- size_t width = strlen((const char *)strval);
- if(!(2 == base || 10 == base || 16 == base)){
- FatalError("CreateBVConst: unsupported base: ",ASTUndefined,base);
- }
- //FIXME Tim: Earlier versions of the code assume that the length of
- //binary strings is 32 bits.
- if(10 == base) width = 32;
- if(16 == base) width = width * 4;
-
- //checking if the input is in the correct format
- CBV bv = CONSTANTBV::BitVector_Create(width,true);
- CONSTANTBV::ErrCode e;
- if(2 == base){
- e = CONSTANTBV::BitVector_from_Bin(bv, (unsigned char*)strval);
- }else if(10 == base){
- e = CONSTANTBV::BitVector_from_Dec(bv, (unsigned char*)strval);
- }else if(16 == base){
- e = CONSTANTBV::BitVector_from_Hex(bv, (unsigned char*)strval);
- }else{
- e = CONSTANTBV::ErrCode_Pars;
- }
-
- if(0 != e) {
- cerr << "CreateBVConst: " << BitVector_Error(e);
- FatalError("",ASTUndefined);
- }
-
- //FIXME
- return CreateBVConst(bv, width);
- }
-
-
- //FIXME Code currently assumes that it will destroy the bitvector passed to it
- ASTNode BeevMgr::CreateBVConst(CBV bv, unsigned width){
- ASTBVConst temp_bvconst(bv, width, *this);
- ASTNode n(LookupOrCreateBVConst(temp_bvconst));
-
- CONSTANTBV::BitVector_Destroy(bv);
-
- return n;
- }
-
- ASTNode BeevMgr::CreateZeroConst(unsigned width) {
- CBV z = CONSTANTBV::BitVector_Create(width, true);
- return CreateBVConst(z, width);
- }
-
- ASTNode BeevMgr::CreateOneConst(unsigned width) {
- CBV o = CONSTANTBV::BitVector_Create(width, true);
- CONSTANTBV::BitVector_increment(o);
-
- return CreateBVConst(o,width);
- }
-
- ASTNode BeevMgr::CreateTwoConst(unsigned width) {
- CBV two = CONSTANTBV::BitVector_Create(width, true);
- CONSTANTBV::BitVector_increment(two);
- CONSTANTBV::BitVector_increment(two);
-
- return CreateBVConst(two,width);
- }
-
- ASTNode BeevMgr::CreateMaxConst(unsigned width) {
- CBV max = CONSTANTBV::BitVector_Create(width, false);
- CONSTANTBV::BitVector_Fill(max);
-
- return CreateBVConst(max,width);
- }
-
- //To ensure unique BVConst nodes, lookup the node in unique-table
- //before creating a new one.
- ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s) {
- ASTBVConst *s_ptr = &s; // it's a temporary key.
-
- // Do an explicit lookup to see if we need to create a copy of the string.
- ASTBVConstSet::const_iterator it;
- if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end()) {
- // Make a new ASTBVConst with duplicated string (can't assign
- // _name because it's const). Can cast the iterator to
- // non-const -- carefully.
-
- ASTBVConst * s_copy = new ASTBVConst(s);
- s_copy->SetNodeNum(NewNodeNum());
-
- pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_copy);
- return *p.first;
- }
- else{
- // return symbol found in table.
- return *it;
- }
- }
-
- // Inline because we need to wait until unique_table is defined
- void ASTBVConst::CleanUp() {
- // cout << "Deleting node " << this->GetNodeNum() << endl;
- _bm._bvconst_unique_table.erase(this);
- delete this;
- }
-
- // Get the value of bvconst from a bvconst. It's an error if kind != BVCONST
- CBV const ASTNode::GetBVConst() const {
- if(GetKind() != BVCONST)
- FatalError("GetBVConst: non bitvector-constant: ",*this);
- return ((ASTBVConst *) _int_node_ptr)->GetBVConst();
- }
+//Create a ASTBVConst node
+ASTNode BeevMgr::CreateBVConst(unsigned int width, unsigned long long int bvconst)
+{
+ if (width > (sizeof(unsigned long long int) << 3) || width <= 0)
+ FatalError("CreateBVConst: trying to create a bvconst of width: ", ASTUndefined, width);
+
+ CBV bv = CONSTANTBV::BitVector_Create(width, true);
+ unsigned long c_val = (~((unsigned long) 0)) & bvconst;
+ unsigned int copied = 0;
+
+ // sizeof(unsigned long) returns the number of bytes in unsigned
+ // long. In order to convert it to bits, we need to shift left by
+ // 3. Hence, sizeof(unsigned long) << 3
+
+ //The algo below works as follows: It starts by copying the
+ //lower-order bits of the input "bvconst" in chunks of size =
+ //number of bits in unsigned long. The variable "copied" keeps
+ //track of the number of chunks copied so far
+
+ while (copied + (sizeof(unsigned long) << 3) < width)
+ {
+ CONSTANTBV::BitVector_Chunk_Store(bv, sizeof(unsigned long) << 3, copied, c_val);
+ bvconst = bvconst >> (sizeof(unsigned long) << 3);
+ c_val = (~((unsigned long) 0)) & bvconst;
+ copied += sizeof(unsigned long) << 3;
+ }
+ CONSTANTBV::BitVector_Chunk_Store(bv, width - copied, copied, c_val);
+ return CreateBVConst(bv, width);
+}
+
+ASTNode BeevMgr::CreateBVConst(string*& strval, int base, int bit_width)
+{
+
+ if (!(2 == base || 10 == base || 16 == base))
+ {
+ FatalError("CreateBVConst: unsupported base: ", ASTUndefined, base);
+ }
+
+ //checking if the input is in the correct format
+ CBV bv = CONSTANTBV::BitVector_Create(bit_width, true);
+ CONSTANTBV::ErrCode e;
+ if (2 == base)
+ {
+ e = CONSTANTBV::BitVector_from_Bin(bv, (unsigned char*) strval->c_str());
+ }
+ else if (10 == base)
+ {
+ e = CONSTANTBV::BitVector_from_Dec(bv, (unsigned char*) strval->c_str());
+ }
+ else if (16 == base)
+ {
+ e = CONSTANTBV::BitVector_from_Hex(bv, (unsigned char*) strval->c_str());
+ }
+ else
+ {
+ e = CONSTANTBV::ErrCode_Pars;
+ }
+
+ if (0 != e)
+ {
+ cerr << "CreateBVConst: " << BitVector_Error(e);
+ FatalError("", ASTUndefined);
+ }
+
+ return CreateBVConst(bv, bit_width);
+}
+
+//Create a ASTBVConst node from std::string
+ASTNode BeevMgr::CreateBVConst(const char* const strval, int base)
+{
+ size_t width = strlen((const char *) strval);
+ if (!(2 == base || 10 == base || 16 == base))
+ {
+ FatalError("CreateBVConst: unsupported base: ", ASTUndefined, base);
+ }
+ //FIXME Tim: Earlier versions of the code assume that the length of
+ //binary strings is 32 bits.
+ if (10 == base)
+ width = 32;
+ if (16 == base)
+ width = width * 4;
+
+ //checking if the input is in the correct format
+ CBV bv = CONSTANTBV::BitVector_Create(width, true);
+ CONSTANTBV::ErrCode e;
+ if (2 == base)
+ {
+ e = CONSTANTBV::BitVector_from_Bin(bv, (unsigned char*) strval);
+ }
+ else if (10 == base)
+ {
+ e = CONSTANTBV::BitVector_from_Dec(bv, (unsigned char*) strval);
+ }
+ else if (16 == base)
+ {
+ e = CONSTANTBV::BitVector_from_Hex(bv, (unsigned char*) strval);
+ }
+ else
+ {
+ e = CONSTANTBV::ErrCode_Pars;
+ }
+
+ if (0 != e)
+ {
+ cerr << "CreateBVConst: " << BitVector_Error(e);
+ FatalError("", ASTUndefined);
+ }
+
+ //FIXME
+ return CreateBVConst(bv, width);
+}
+
+//FIXME Code currently assumes that it will destroy the bitvector passed to it
+ASTNode BeevMgr::CreateBVConst(CBV bv, unsigned width)
+{
+ ASTBVConst temp_bvconst(bv, width, *this);
+ ASTNode n(LookupOrCreateBVConst(temp_bvconst));
+
+ CONSTANTBV::BitVector_Destroy(bv);
+
+ return n;
+}
+
+ASTNode BeevMgr::CreateZeroConst(unsigned width)
+{
+ CBV z = CONSTANTBV::BitVector_Create(width, true);
+ return CreateBVConst(z, width);
+}
+
+ASTNode BeevMgr::CreateOneConst(unsigned width)
+{
+ CBV o = CONSTANTBV::BitVector_Create(width, true);
+ CONSTANTBV::BitVector_increment(o);
+
+ return CreateBVConst(o, width);
+}
+
+ASTNode BeevMgr::CreateTwoConst(unsigned width)
+{
+ CBV two = CONSTANTBV::BitVector_Create(width, true);
+ CONSTANTBV::BitVector_increment(two);
+ CONSTANTBV::BitVector_increment(two);
+
+ return CreateBVConst(two, width);
+}
+
+ASTNode BeevMgr::CreateMaxConst(unsigned width)
+{
+ CBV max = CONSTANTBV::BitVector_Create(width, false);
+ CONSTANTBV::BitVector_Fill(max);
+
+ return CreateBVConst(max, width);
+}
+
+//To ensure unique BVConst nodes, lookup the node in unique-table
+//before creating a new one.
+ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s)
+{
+ ASTBVConst *s_ptr = &s; // it's a temporary key.
+
+ // Do an explicit lookup to see if we need to create a copy of the string.
+ ASTBVConstSet::const_iterator it;
+ if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end())
+ {
+ // Make a new ASTBVConst with duplicated string (can't assign
+ // _name because it's const). Can cast the iterator to
+ // non-const -- carefully.
+
+ ASTBVConst * s_copy = new ASTBVConst(s);
+ s_copy->SetNodeNum(NewNodeNum());
+
+ pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_copy);
+ return *p.first;
+ }
+ else
+ {
+ // return symbol found in table.
+ return *it;
+ }
+}
+
+// Inline because we need to wait until unique_table is defined
+void ASTBVConst::CleanUp()
+{
+ // cout << "Deleting node " << this->GetNodeNum() << endl;
+ _bm._bvconst_unique_table.erase(this);
+ delete this;
+}
+
+// Get the value of bvconst from a bvconst. It's an error if kind != BVCONST
+CBV const ASTNode::GetBVConst() const
+{
+ if (GetKind() != BVCONST)
+ FatalError("GetBVConst: non bitvector-constant: ", *this);
+ return ((ASTBVConst *) _int_node_ptr)->GetBVConst();
+}
#else
- //Create a ASTBVConst node
- ASTNode BeevMgr::CreateBVConst(const unsigned int width,
- const unsigned long long int bvconst) {
- if(width > 64 || width <= 0)
- FatalError("Fatal Error: CreateBVConst: trying to create a bvconst of width:", ASTUndefined, width);
-
- //64 bit mask
- unsigned long long int mask = 0xffffffffffffffffLL;
- mask = mask >> (64 - width);
-
- unsigned long long int bv = bvconst;
- bv = bv & mask;
-
- ASTBVConst temp_bvconst(bv, *this);
- temp_bvconst._value_width = width;
- ASTNode n(LookupOrCreateBVConst(temp_bvconst));
- n.SetValueWidth(width);
- n.SetIndexWidth(0);
- return n;
- }
- //Create a ASTBVConst node from std::string
- ASTNode BeevMgr::CreateBVConst(const char* strval, int base) {
- if(!(base == 2 || base == 16 || base == 10))
- FatalError("CreateBVConst: This base is not supported: ", ASTUndefined, base);
-
- if(10 != base) {
- unsigned int width = (base == 2) ? strlen(strval) : strlen(strval)*4;
- unsigned long long int val = strtoull(strval, NULL, base);
- ASTNode bvcon = CreateBVConst(width, val);
- return bvcon;
- }
- else {
- //this is an ugly hack to accomodate SMTLIB format
- //restrictions. SMTLIB format represents bitvector constants in
- //base 10 (what a terrible idea, but i have no choice but to
- //support it), and make an implicit assumption that the length
- //is 32 (another terrible idea).
- unsigned width = 32;
- unsigned long long int val = strtoull(strval, NULL, base);
- ASTNode bvcon = CreateBVConst(width, val);
- return bvcon;
- }
- }
-
- //To ensure unique BVConst nodes, lookup the node in unique-table
- //before creating a new one.
- ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s) {
- ASTBVConst *s_ptr = &s; // it's a temporary key.
-
- // Do an explicit lookup to see if we need to create a copy of the
- // string.
- ASTBVConstSet::const_iterator it;
- if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end()) {
- // Make a new ASTBVConst. Can cast the iterator to non-const --
- // carefully.
- unsigned int width = s_ptr->_value_width;
- ASTBVConst * s_ptr1 = new ASTBVConst(s_ptr->GetBVConst(), *this);
- s_ptr1->SetNodeNum(NewNodeNum());
- s_ptr1->_value_width = width;
- pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_ptr1);
- return *p.first;
- }
- else
- // return BVConst found in table.
- return *it;
- }
-
- // Inline because we need to wait until unique_table is defined
- void ASTBVConst::CleanUp() {
- // cout << "Deleting node " << this->GetNodeNum() << endl;
- _bm._bvconst_unique_table.erase(this);
- delete this;
- }
-
- // Get the value of bvconst from a bvconst. It's an error if kind
- // != BVCONST
- unsigned long long int ASTNode::GetBVConst() const {
- if(GetKind() != BVCONST)
- FatalError("GetBVConst: non bitvector-constant: ", *this);
- return ((ASTBVConstTmp *) _int_node_ptr)->GetBVConst();
- }
-
- ASTNode BeevMgr::CreateZeroConst(unsigned width) {
- return CreateBVConst(width,0);
- }
-
- ASTNode BeevMgr::CreateOneConst(unsigned width) {
- return CreateBVConst(width,1);
- }
-
- ASTNode BeevMgr::CreateTwoConst(unsigned width) {
- return CreateBVConst(width,2);
- }
-
- ASTNode BeevMgr::CreateMaxConst(unsigned width) {
- std::string s;
- s.insert(s.end(),width,'1');
- return CreateBVConst(s.c_str(),2);
- }
-
-#endif
-
- // FIXME: _name is now a constant field, and this assigns to it
- // because it tries not to copy the string unless it needs to. How
- // do I avoid copying children in ASTInterior? Perhaps I don't!
-
- // Note: There seems to be a limitation of hash_set, in that insert
- // returns a const iterator to the value. That prevents us from
- // modifying the name (in a hash-preserving way) after the symbol is
- // inserted. FIXME: Is there a way to do this with insert? Need a
- // function to make a new object in the middle of insert. Read STL
- // documentation.
-
- ASTSymbol *BeevMgr::LookupOrCreateSymbol(ASTSymbol& s) {
- ASTSymbol *s_ptr = &s; // it's a temporary key.
-
- // Do an explicit lookup to see if we need to create a copy of the string.
- ASTSymbolSet::const_iterator it;
- if ((it = _symbol_unique_table.find(s_ptr)) == _symbol_unique_table.end()) {
- // Make a new ASTSymbol with duplicated string (can't assign
- // _name because it's const). Can cast the iterator to
- // non-const -- carefully.
- //std::string strname(s_ptr->GetName());
- ASTSymbol * s_ptr1 = new ASTSymbol(strdup(s_ptr->GetName()), *this);
- s_ptr1->SetNodeNum(NewNodeNum());
- s_ptr1->_value_width = s_ptr->_value_width;
- pair<ASTSymbolSet::const_iterator, bool> p = _symbol_unique_table.insert(s_ptr1);
- return *p.first;
- }
- else
- // return symbol found in table.
- return *it;
- }
-
- bool BeevMgr::LookupSymbol(ASTSymbol& s) {
- ASTSymbol* s_ptr = &s; // it's a temporary key.
-
- if(_symbol_unique_table.find(s_ptr) == _symbol_unique_table.end())
- return false;
- else
- return true;
- }
-
- // Inline because we need to wait until unique_table is defined
- void ASTSymbol::CleanUp() {
- // cout << "Deleting node " << this->GetNodeNum() << endl;
- _bm._symbol_unique_table.erase(this);
- //FIXME This is a HUGE free to invoke.
- //TEST IT!
- free((char*) this->_name);
- delete this;
- }
-
- ////////////////////////////////////////////////////////////////
- //
- // IO manipulators for Lisp format printing of AST.
- //
- ////////////////////////////////////////////////////////////////
-
- // FIXME: Additional controls
- // * Print node numbers (addresses/nums)
- // * Printlength limit
- // * Printdepth limit
-
- /** Print a vector of ASTNodes in lisp format */
- ostream &LispPrintVec(ostream &os, const ASTVec &v, int indentation)
- {
- // Print the children
- ASTVec::const_iterator iend = v.end();
- for (ASTVec::const_iterator i = v.begin(); i != iend; i++) {
- i->LispPrint_indent(os, indentation);
- }
- return os;
- }
-
- ostream &LispPrintVecSpecial(ostream &os, const vector<const ASTNode*> &v, int indentation)
- {
- // Print the children
- vector<const ASTNode*>::const_iterator iend = v.end();
- for (vector<const ASTNode*>::const_iterator i = v.begin(); i != iend; i++) {
- (*i)->LispPrint_indent(os, indentation);
- }
- return os;
- }
-
- // FIXME: Made non-ref in the hope that it would work better.
- void lp(ASTNode node)
- {
- cout << lisp(node) << endl;
- }
-
- void lpvec(const ASTVec &vec)
- {
- vec[0].GetBeevMgr().AlreadyPrintedSet.clear();
- LispPrintVec(cout, vec, 0);
- cout << endl;
- }
-
- // Copy constructor. Maintain _ref_count
- ASTNode::ASTNode(const ASTNode &n) : _int_node_ptr(n._int_node_ptr) {
-#ifndef SMTLIB
- if (n._int_node_ptr) {
- n._int_node_ptr->IncRef();
- }
+//Create a ASTBVConst node
+ASTNode BeevMgr::CreateBVConst(const unsigned int width,
+ const unsigned long long int bvconst)
+{
+ if(width > 64 || width <= 0)
+ FatalError("Fatal Error: CreateBVConst: trying to create a bvconst of width:", ASTUndefined, width);
+
+ //64 bit mask
+ unsigned long long int mask = 0xffffffffffffffffLL;
+ mask = mask >> (64 - width);
+
+ unsigned long long int bv = bvconst;
+ bv = bv & mask;
+
+ ASTBVConst temp_bvconst(bv, *this);
+ temp_bvconst._value_width = width;
+ ASTNode n(LookupOrCreateBVConst(temp_bvconst));
+ n.SetValueWidth(width);
+ n.SetIndexWidth(0);
+ return n;
+}
+//Create a ASTBVConst node from std::string
+ASTNode BeevMgr::CreateBVConst(const char* strval, int base)
+{
+ if(!(base == 2 || base == 16 || base == 10))
+ FatalError("CreateBVConst: This base is not supported: ", ASTUndefined, base);
+
+ if(10 != base)
+ {
+ unsigned int width = (base == 2) ? strlen(strval) : strlen(strval)*4;
+ unsigned long long int val = strtoull(strval, NULL, base);
+ ASTNode bvcon = CreateBVConst(width, val);
+ return bvcon;
+ }
+ else
+ {
+ //this is an ugly hack to accomodate SMTLIB format
+ //restrictions. SMTLIB format represents bitvector constants in
+ //base 10 (what a terrible idea, but i have no choice but to
+ //support it), and make an implicit assumption that the length
+ //is 32 (another terrible idea).
+ unsigned width = 32;
+ unsigned long long int val = strtoull(strval, NULL, base);
+ ASTNode bvcon = CreateBVConst(width, val);
+ return bvcon;
+ }
+}
+
+//To ensure unique BVConst nodes, lookup the node in unique-table
+//before creating a new one.
+ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s)
+{
+ ASTBVConst *s_ptr = &s; // it's a temporary key.
+
+ // Do an explicit lookup to see if we need to create a copy of the
+ // string.
+ ASTBVConstSet::const_iterator it;
+ if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end())
+ {
+ // Make a new ASTBVConst. Can cast the iterator to non-const --
+ // carefully.
+ unsigned int width = s_ptr->_value_width;
+ ASTBVConst * s_ptr1 = new ASTBVConst(s_ptr->GetBVConst(), *this);
+ s_ptr1->SetNodeNum(NewNodeNum());
+ s_ptr1->_value_width = width;
+ pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_ptr1);
+ return *p.first;
+ }
+ else
+ // return BVConst found in table.
+ return *it;
+}
+
+// Inline because we need to wait until unique_table is defined
+void ASTBVConst::CleanUp()
+{
+ // cout << "Deleting node " << this->GetNodeNum() << endl;
+ _bm._bvconst_unique_table.erase(this);
+ delete this;
+}
+
+// Get the value of bvconst from a bvconst. It's an error if kind
+// != BVCONST
+unsigned long long int ASTNode::GetBVConst() const
+{
+ if(GetKind() != BVCONST)
+ FatalError("GetBVConst: non bitvector-constant: ", *this);
+ return ((ASTBVConstTmp *) _int_node_ptr)->GetBVConst();
+}
+
+ASTNode BeevMgr::CreateZeroConst(unsigned width)
+{
+ return CreateBVConst(width,0);
+}
+
+ASTNode BeevMgr::CreateOneConst(unsigned width)
+{
+ return CreateBVConst(width,1);
+}
+
+ASTNode BeevMgr::CreateTwoConst(unsigned width)
+{
+ return CreateBVConst(width,2);
+}
+
+ASTNode BeevMgr::CreateMaxConst(unsigned width)
+{
+ std::string s;
+ s.insert(s.end(),width,'1');
+ return CreateBVConst(s.c_str(),2);
+}
+
+#endif
+
+// FIXME: _name is now a constant field, and this assigns to it
+// because it tries not to copy the string unless it needs to. How
+// do I avoid copying children in ASTInterior? Perhaps I don't!
+
+// Note: There seems to be a limitation of hash_set, in that insert
+// returns a const iterator to the value. That prevents us from
+// modifying the name (in a hash-preserving way) after the symbol is
+// inserted. FIXME: Is there a way to do this with insert? Need a
+// function to make a new object in the middle of insert. Read STL
+// documentation.
+
+ASTSymbol *BeevMgr::LookupOrCreateSymbol(ASTSymbol& s)
+{
+ ASTSymbol *s_ptr = &s; // it's a temporary key.
+
+ // Do an explicit lookup to see if we need to create a copy of the string.
+ ASTSymbolSet::const_iterator it;
+ if ((it = _symbol_unique_table.find(s_ptr)) == _symbol_unique_table.end())
+ {
+ // Make a new ASTSymbol with duplicated string (can't assign
+ // _name because it's const). Can cast the iterator to
+ // non-const -- carefully.
+ //std::string strname(s_ptr->GetName());
+ ASTSymbol * s_ptr1 = new ASTSymbol(strdup(s_ptr->GetName()), *this);
+ s_ptr1->SetNodeNum(NewNodeNum());
+ s_ptr1->_value_width = s_ptr->_value_width;
+ pair<ASTSymbolSet::const_iterator, bool> p = _symbol_unique_table.insert(s_ptr1);
+ return *p.first;
+ }
+ else
+ // return symbol found in table.
+ return *it;
+}
+
+bool BeevMgr::LookupSymbol(ASTSymbol& s)
+{
+ ASTSymbol* s_ptr = &s; // it's a temporary key.
+
+ if (_symbol_unique_table.find(s_ptr) == _symbol_unique_table.end())
+ return false;
+ else
+ return true;
+}
+
+// Inline because we need to wait until unique_table is defined
+void ASTSymbol::CleanUp()
+{
+ // cout << "Deleting node " << this->GetNodeNum() << endl;
+ _bm._symbol_unique_table.erase(this);
+ //FIXME This is a HUGE free to invoke.
+ //TEST IT!
+ free((char*) this->_name);
+ delete this;
+}
+
+////////////////////////////////////////////////////////////////
+//
+// IO manipulators for Lisp format printing of AST.
+//
+////////////////////////////////////////////////////////////////
+
+// FIXME: Additional controls
+// * Print node numbers (addresses/nums)
+// * Printlength limit
+// * Printdepth limit
+
+/** Print a vector of ASTNodes in lisp format */
+ostream &LispPrintVec(ostream &os, const ASTVec &v, int indentation)
+{
+ // Print the children
+ ASTVec::const_iterator iend = v.end();
+ for (ASTVec::const_iterator i = v.begin(); i != iend; i++)
+ {
+ i->LispPrint_indent(os, indentation);
+ }
+ return os;
+}
+
+ostream &LispPrintVecSpecial(ostream &os, const vector<const ASTNode*> &v, int indentation)
+{
+ // Print the children
+ vector<const ASTNode*>::const_iterator iend = v.end();
+ for (vector<const ASTNode*>::const_iterator i = v.begin(); i != iend; i++)
+ {
+ (*i)->LispPrint_indent(os, indentation);
+ }
+ return os;
+}
+
+// FIXME: Made non-ref in the hope that it would work better.
+void lp(ASTNode node)
+{
+ cout << lisp(node) << endl;
+}
+
+void lpvec(const ASTVec &vec)
+{
+ vec[0].GetBeevMgr().AlreadyPrintedSet.clear();
+ LispPrintVec(cout, vec, 0);
+ cout << endl;
+}
+
+// Copy constructor. Maintain _ref_count
+ASTNode::ASTNode(const ASTNode &n) :
+ _int_node_ptr(n._int_node_ptr)
+{
+#ifndef SMTLIB
+ if (n._int_node_ptr)
+ {
+ n._int_node_ptr->IncRef();
+ }
#endif
- }
-
-
- /* 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
- */
- void BeevMgr::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;
- case ITE:
- 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[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);
+}
+
+/* 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
+ */
+void BeevMgr::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;
+ case ITE:
+ 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[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);
+ }
+ break;
+ case 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);
+ break;
+ case BVOR:
+ case BVAND:
+ case BVXOR:
+ case BVNOR:
+ case BVNAND:
+ case BVXNOR:
+ case BVPLUS:
+ case BVMULT:
+ case BVDIV:
+ case BVMOD:
+ case BVSUB:
+ {
+ if (!(v.size() >= 2))
+ FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must have atleast 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:
+ //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: BVSX(t,bvsx_len) : length of 't' must be <= bvsx_len\n", n);
+ }
+ break;
+
+ case BVZX:
+ //in BVZX(n[0],len), the length of the BVZX term must be
+ //greater than the length of n[0]
+ if (n[0].GetValueWidth() > n.GetValueWidth())
+ {
+ FatalError("BVTypeCheck: BVZX(t,bvzx_len) : length of 't' must be <= bvzx_len\n", n);
+ }
+ break;
+
+ default:
+ for (ASTVec::const_iterator it = v.begin(), itend = v.end(); it != itend; it++)
+ if (BITVECTOR_TYPE != it->GetType())
+ {
+ cerr << "The type is: " << it->GetType() << endl;
+ FatalError("BVTypeCheck:ChildNodes of bitvector-terms must be bitvectors\n", n);
+ }
+ break;
+ }
+
+ switch (k)
+ {
+ case BVCONCAT:
+ 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:
+ if (n.Degree() != 1)
+ FatalError("BVTypeCheck: should have exactly 1 args\n", n);
+ break;
+ case BVEXTRACT:
+ 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() != GetUnsignedConst(n[1]) - GetUnsignedConst(n[2]) + 1)
+ FatalError("BVTypeCheck: length mismatch\n", n);
+ break;
+ case BVLEFTSHIFT:
+ case BVRIGHTSHIFT:
+ if (n.Degree() != 2)
+ FatalError("BVTypeCheck: should have exactly 2 args\n", n);
+ break;
+ //case BVVARSHIFT:
+ //case BVSRSHIFT:
+ break;
+ default:
+ 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;
+ case EQ:
+ case NEQ:
+ 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 (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: ", ASTUndefined);
+ break;
+ }
+ }
+} //End of TypeCheck function
+
+//add an assertion to the current logical context
+void BeevMgr::AddAssert(const ASTNode& assert)
+{
+ if (!(is_Form_kind(assert.GetKind()) && BOOLEAN_TYPE == assert.GetType()))
+ {
+ FatalError("AddAssert:Trying to assert a non-formula:", assert);
+ }
+
+ ASTVec * v;
+ //if the stack of ASTVec is not empty, then take the top ASTVec
+ //and add the input assert to it
+ if (!_asserts.empty())
+ {
+ v = _asserts.back();
+ //v->push_back(TransformFormula(assert));
+ v->push_back(assert);
+ }
+ else
+ {
+ //else create a logical context, and add it to the top of the
+ //stack
+ v = new ASTVec();
+ //v->push_back(TransformFormula(assert));
+ v->push_back(assert);
+ _asserts.push_back(v);
+ }
+}
+
+void BeevMgr::Push(void)
+{
+ ASTVec * v;
+ v = new ASTVec();
+ _asserts.push_back(v);
+}
+
+void BeevMgr::Pop(void)
+{
+ if (!_asserts.empty())
+ {
+ ASTVec * c = _asserts.back();
+ //by calling the clear function we ensure that the ref count is
+ //decremented for the ASTNodes stored in c
+ c->clear();
+ delete c;
+ _asserts.pop_back();
+ }
+}
+
+void BeevMgr::AddQuery(const ASTNode& q)
+{
+ //_current_query = TransformFormula(q);
+ //cerr << "\nThe current query is: " << q << endl;
+ _current_query = q;
+}
+
+const ASTNode BeevMgr::PopQuery()
+{
+ ASTNode q = _current_query;
+ _current_query = ASTTrue;
+ return q;
+}
+
+const ASTNode BeevMgr::GetQuery()
+{
+ return _current_query;
+}
+
+const ASTVec BeevMgr::GetAsserts(void)
+{
+ vector<ASTVec *>::iterator it = _asserts.begin();
+ vector<ASTVec *>::iterator itend = _asserts.end();
+
+ ASTVec v;
+ for (; it != itend; it++)
+ {
+ if (!(*it)->empty())
+ v.insert(v.end(), (*it)->begin(), (*it)->end());
+ }
+ return v;
+}
+
+//Create a new variable of ValueWidth 'n'
+ASTNode BeevMgr::NewArrayVar(unsigned int index, unsigned int value)
+{
+ std::string c("v");
+ char d[32];
+ sprintf(d, "%d", _symbol_count++);
+ std::string ccc(d);
+ c += "_writearray_" + ccc;
+
+ ASTNode CurrentSymbol = CreateSymbol(c.c_str());
+ CurrentSymbol.SetValueWidth(value);
+ CurrentSymbol.SetIndexWidth(index);
+ return CurrentSymbol;
+} //end of NewArrayVar()
+
+
+//Create a new variable of ValueWidth 'n'
+ASTNode BeevMgr::NewVar(unsigned int value)
+{
+ std::string c("v");
+ char d[32];
+ sprintf(d, "%d", _symbol_count++);
+ std::string ccc(d);
+ c += "_new_stp_var_" + ccc;
+
+ ASTNode CurrentSymbol = CreateSymbol(c.c_str());
+ CurrentSymbol.SetValueWidth(value);
+ CurrentSymbol.SetIndexWidth(0);
+ _introduced_symbols.insert(CurrentSymbol);
+ return CurrentSymbol;
+} //end of NewVar()
+
+//prints statistics for the ASTNode
+void BeevMgr::ASTNodeStats(const char * c, const ASTNode& a)
+{
+ if (!stats)
+ return;
+
+ StatInfoSet.clear();
+ //print node size:
+ cout << endl << "Printing: " << c;
+ if (print_nodes)
+ {
+ //a.PL_Print(cout,0);
+ //cout << endl;
+ cout << a << endl;
+ }
+ cout << "Node size is: ";
+ cout << NodeSize(a) << endl << endl;
+}
+
+unsigned int BeevMgr::NodeSize(const ASTNode& a, bool clearStatInfo)
+{
+ if (clearStatInfo)
+ StatInfoSet.clear();
+
+ ASTNodeSet::iterator it;
+ if ((it = StatInfoSet.find(a)) != StatInfoSet.end())
+ //has already been counted
+ return 0;
+
+ //record that you have seen this node already
+ StatInfoSet.insert(a);
+
+ //leaf node has a size of 1
+ if (a.Degree() == 0)
+ return 1;
+
+ unsigned newn = 1;
+ ASTVec c = a.GetChildren();
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ newn += NodeSize(*it);
+ return newn;
+}
+
+void BeevMgr::ClearAllTables(void)
+{
+ //clear all tables before calling toplevelsat
+ _ASTNode_to_SATVar.clear();
+ _SATVar_to_AST.clear();
+
+ for (ASTtoBitvectorMap::iterator it = _ASTNode_to_Bitvector.begin(), itend = _ASTNode_to_Bitvector.end(); it != itend; it++)
+ {
+ (it->second)->clear();
+ delete (it->second);
+ }
+ _ASTNode_to_Bitvector.clear();
+
+ /* OLD Destructor
+ * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
+ ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+ ivec->second.clear();
+ }*/
+
+ /*What should I do here? For ASTNodes?
+ * for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
+ ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+ ivec->second.clear();
+ }*/
+ BBTermMemo.clear();
+ BBFormMemo.clear();
+ NodeLetVarMap.clear();
+ NodeLetVarMap1.clear();
+ PLPrintNodeSet.clear();
+ AlreadyPrintedSet.clear();
+ SimplifyMap->clear();
+ SimplifyNegMap->clear();
+ SolverMap.clear();
+ AlwaysTrueFormMap.clear();
+ _arrayread_ite.clear();
+ _arrayread_symbol.clear();
+ _introduced_symbols.clear();
+ TransformMap.clear();
+ _letid_expr_map->clear();
+ CounterExampleMap.clear();
+ ComputeFormulaMap.clear();
+ StatInfoSet.clear();
+
+ // for(std::vector<ASTVec *>::iterator it=_asserts.begin(),
+ // itend=_asserts.end();it!=itend;it++) {
+ // (*it)->clear();
+ // }
+ _asserts.clear();
+ for (ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), iset_end = _arrayname_readindices.end(); iset != iset_end; iset++)
+ {
+ iset->second.clear();
+ }
+
+ _arrayname_readindices.clear();
+ _interior_unique_table.clear();
+ _symbol_unique_table.clear();
+ _bvconst_unique_table.clear();
+}
+
+void BeevMgr::ClearAllCaches(void)
+{
+ //clear all tables before calling toplevelsat
+ _ASTNode_to_SATVar.clear();
+ _SATVar_to_AST.clear();
+
+ for (ASTtoBitvectorMap::iterator it = _ASTNode_to_Bitvector.begin(), itend = _ASTNode_to_Bitvector.end(); it != itend; it++)
+ {
+ (it->second)->clear();
+ delete (it->second);
+ }
+ _ASTNode_to_Bitvector.clear();
+
+ /*OLD destructor
+ * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
+ ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+ ivec->second.clear();
+ }*/
+
+ /*What should I do here?
+ *for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
+ ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+ ivec->second.clear();
+ }*/
+ BBTermMemo.clear();
+ BBFormMemo.clear();
+ NodeLetVarMap.clear();
+ NodeLetVarMap1.clear();
+ PLPrintNodeSet.clear();
+ AlreadyPrintedSet.clear();
+ SimplifyMap->clear();
+ SimplifyNegMap->clear();
+ SolverMap.clear();
+ AlwaysTrueFormMap.clear();
+ _arrayread_ite.clear();
+ _arrayread_symbol.clear();
+ _introduced_symbols.clear();
+ TransformMap.clear();
+ _letid_expr_map->clear();
+ CounterExampleMap.clear();
+ ComputeFormulaMap.clear();
+ StatInfoSet.clear();
+
+ for (ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), iset_end = _arrayname_readindices.end(); iset != iset_end; iset++)
+ {
+ iset->second.clear();
+ }
+
+ _arrayname_readindices.clear();
+ //_interior_unique_table.clear();
+ //_symbol_unique_table.clear();
+ //_bvconst_unique_table.clear();
+}
+
+void BeevMgr::CopySolverMap_To_CounterExample(void)
+{
+ if (!SolverMap.empty())
+ {
+ CounterExampleMap.insert(SolverMap.begin(), SolverMap.end());
}
- break;
- case 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);
- break;
- case BVOR:
- case BVAND:
- case BVXOR:
- case BVNOR:
- case BVNAND:
- case BVXNOR:
- case BVPLUS:
- case BVMULT:
- case BVDIV:
- case BVMOD:
- case BVSUB: {
- if(!(v.size() >= 2))
- FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must have atleast 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);
+}
+
+void FatalError(const char * str, const ASTNode& a, int w)
+{
+ if (a.GetKind() != UNDEFINED)
+ {
+ cerr << "Fatal Error: " << str << endl << a << endl;
+ cerr << w << endl;
}
- break;
- }
- case BVSX:
- //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: BVSX(t,bvsx_len) : length of 't' must be <= bvsx_len\n",n);
- }
- break;
-
- case BVZX:
- //in BVZX(n[0],len), the length of the BVZX term must be
- //greater than the length of n[0]
- if(n[0].GetValueWidth() > n.GetValueWidth()) {
- FatalError("BVTypeCheck: BVZX(t,bvzx_len) : length of 't' must be <= bvzx_len\n",n);
+ else
+ {
+ cerr << "Fatal Error: " << str << endl;
+ cerr << w << endl;
}
- break;
-
- default:
- for(ASTVec::const_iterator it=v.begin(),itend=v.end();it!=itend;it++)
- if(BITVECTOR_TYPE != it->GetType()) {
- cerr << "The type is: " << it->GetType() << endl;
- FatalError("BVTypeCheck:ChildNodes of bitvector-terms must be bitvectors\n",n);
- }
- break;
- }
-
- switch(k) {
- case BVCONCAT:
- 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:
- if(n.Degree() != 1)
- FatalError("BVTypeCheck: should have exactly 1 args\n",n);
- break;
- case BVEXTRACT:
- 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() != GetUnsignedConst(n[1])- GetUnsignedConst(n[2])+1)
- FatalError("BVTypeCheck: length mismatch\n",n);
- break;
- case BVLEFTSHIFT:
- case BVRIGHTSHIFT:
- if(n.Degree() != 2)
- FatalError("BVTypeCheck: should have exactly 2 args\n",n);
- break;
- //case BVVARSHIFT:
- //case BVSRSHIFT:
- break;
- default:
- 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;
- case EQ:
- case NEQ:
- 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);
+ if (vc_error_hdlr)
+ vc_error_hdlr(str);
+ exit(-1);
+ //assert(0);
+}
+
+void FatalError(const char * str)
+{
+ cerr << "Fatal Error: " << str << endl;
+ if (vc_error_hdlr)
+ vc_error_hdlr(str);
+ exit(-1);
+ //assert(0);
+}
+
+//Variable Order Printer: A global function which converts a MINISAT
+//var into a ASTNODE var. It then prints this var along with
+//variable order dcisions taken by MINISAT.
+void Convert_MINISATVar_To_ASTNode_Print(int minisat_var, int decision_level, int polarity)
+{
+ BEEV::ASTNode vv = globalBeevMgr_for_parser->_SATVar_to_AST[minisat_var];
+ cout << spaces(decision_level);
+ if (polarity)
+ {
+ cout << "!";
}
- break;
- case BVLT:
- case BVLE:
- case BVGT:
- case BVGE:
- case BVSLT:
- case BVSLE:
- case BVSGT:
- case BVSGE:
- 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: ",ASTUndefined);
- break;
- }
- }
- } //End of TypeCheck function
-
- //add an assertion to the current logical context
- void BeevMgr::AddAssert(const ASTNode& assert) {
- if(!(is_Form_kind(assert.GetKind()) && BOOLEAN_TYPE == assert.GetType())) {
- FatalError("AddAssert:Trying to assert a non-formula:",assert);
- }
-
- ASTVec * v;
- //if the stack of ASTVec is not empty, then take the top ASTVec
- //and add the input assert to it
- if(!_asserts.empty()) {
- v = _asserts.back();
- //v->push_back(TransformFormula(assert));
- v->push_back(assert);
- }
- else {
- //else create a logical context, and add it to the top of the
- //stack
- v = new ASTVec();
- //v->push_back(TransformFormula(assert));
- v->push_back(assert);
- _asserts.push_back(v);
- }
- }
-
- void BeevMgr::Push(void) {
- ASTVec * v;
- v = new ASTVec();
- _asserts.push_back(v);
- }
-
- void BeevMgr::Pop(void) {
- if(!_asserts.empty()) {
- ASTVec * c = _asserts.back();
- //by calling the clear function we ensure that the ref count is
- //decremented for the ASTNodes stored in c
- c->clear();
- delete c;
- _asserts.pop_back();
- }
- }
-
- void BeevMgr::AddQuery(const ASTNode& q) {
- //_current_query = TransformFormula(q);
- //cerr << "\nThe current query is: " << q << endl;
- _current_query = q;
- }
-
- const ASTNode BeevMgr::PopQuery() {
- ASTNode q = _current_query;
- _current_query = ASTTrue;
- return q;
- }
-
- const ASTNode BeevMgr::GetQuery() {
- return _current_query;
- }
-
- const ASTVec BeevMgr::GetAsserts(void) {
- vector<ASTVec *>::iterator it = _asserts.begin();
- vector<ASTVec *>::iterator itend = _asserts.end();
-
- ASTVec v;
- for(;it!=itend;it++) {
- if(!(*it)->empty())
- v.insert(v.end(),(*it)->begin(),(*it)->end());
- }
- return v;
- }
-
- //Create a new variable of ValueWidth 'n'
- ASTNode BeevMgr::NewArrayVar(unsigned int index, unsigned int value) {
- std:: string c("v");
- char d[32];
- sprintf(d,"%d",_symbol_count++);
- std::string ccc(d);
- c += "_writearray_" + ccc;
-
- ASTNode CurrentSymbol = CreateSymbol(c.c_str());
- CurrentSymbol.SetValueWidth(value);
- CurrentSymbol.SetIndexWidth(index);
- return CurrentSymbol;
- } //end of NewArrayVar()
-
-
- //Create a new variable of ValueWidth 'n'
- ASTNode BeevMgr::NewVar(unsigned int value) {
- std:: string c("v");
- char d[32];
- sprintf(d,"%d",_symbol_count++);
- std::string ccc(d);
- c += "_new_stp_var_" + ccc;
-
- ASTNode CurrentSymbol = CreateSymbol(c.c_str());
- CurrentSymbol.SetValueWidth(value);
- CurrentSymbol.SetIndexWidth(0);
- _introduced_symbols.insert(CurrentSymbol);
- return CurrentSymbol;
- } //end of NewVar()
-
- //prints statistics for the ASTNode
- void BeevMgr::ASTNodeStats(const char * c, const ASTNode& a){
- if(!stats)
- return;
-
- StatInfoSet.clear();
- //print node size:
- cout << endl << "Printing: " << c;
- if(print_nodes) {
- //a.PL_Print(cout,0);
- //cout << endl;
- cout << a << endl;
- }
- cout << "Node size is: ";
- cout << NodeSize(a) << endl << endl;
- }
-
- unsigned int BeevMgr::NodeSize(const ASTNode& a, bool clearStatInfo) {
- if(clearStatInfo)
- StatInfoSet.clear();
-
- ASTNodeSet::iterator it;
- if((it = StatInfoSet.find(a)) != StatInfoSet.end())
- //has already been counted
- return 0;
-
- //record that you have seen this node already
- StatInfoSet.insert(a);
-
- //leaf node has a size of 1
- if(a.Degree() == 0)
- return 1;
-
- unsigned newn = 1;
- ASTVec c = a.GetChildren();
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
- newn += NodeSize(*it);
- return newn;
- }
-
- void BeevMgr::ClearAllTables(void) {
- //clear all tables before calling toplevelsat
- _ASTNode_to_SATVar.clear();
- _SATVar_to_AST.clear();
-
- for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),
- itend=_ASTNode_to_Bitvector.end();it!=itend;it++) {
- (it->second)->clear();
- delete (it->second);
- }
- _ASTNode_to_Bitvector.clear();
-
- /* OLD Destructor
- * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
- ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
- ivec->second.clear();
- }*/
-
- /*What should I do here? For ASTNodes?
- * for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
- ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
- ivec->second.clear();
- }*/
- BBTermMemo.clear();
- BBFormMemo.clear();
- NodeLetVarMap.clear();
- NodeLetVarMap1.clear();
- PLPrintNodeSet.clear();
- AlreadyPrintedSet.clear();
- SimplifyMap->clear();
- SimplifyNegMap->clear();
- SolverMap.clear();
- AlwaysTrueFormMap.clear();
- _arrayread_ite.clear();
- _arrayread_symbol.clear();
- _introduced_symbols.clear();
- TransformMap.clear();
- _letid_expr_map->clear();
- CounterExampleMap.clear();
- ComputeFormulaMap.clear();
- StatInfoSet.clear();
-
- // for(std::vector<ASTVec *>::iterator it=_asserts.begin(),
- // itend=_asserts.end();it!=itend;it++) {
- // (*it)->clear();
- // }
- _asserts.clear();
- for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(),
- iset_end = _arrayname_readindices.end();
- iset!=iset_end;iset++) {
- iset->second.clear();
- }
-
- _arrayname_readindices.clear();
- _interior_unique_table.clear();
- _symbol_unique_table.clear();
- _bvconst_unique_table.clear();
- }
-
- void BeevMgr::ClearAllCaches(void) {
- //clear all tables before calling toplevelsat
- _ASTNode_to_SATVar.clear();
- _SATVar_to_AST.clear();
-
-
- for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),
- itend=_ASTNode_to_Bitvector.end();it!=itend;it++) {
- (it->second)->clear();
- delete (it->second);
- }
- _ASTNode_to_Bitvector.clear();
-
- /*OLD destructor
- * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
- ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
- ivec->second.clear();
- }*/
-
- /*What should I do here?
- *for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
- ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
- ivec->second.clear();
- }*/
- BBTermMemo.clear();
- BBFormMemo.clear();
- NodeLetVarMap.clear();
- NodeLetVarMap1.clear();
- PLPrintNodeSet.clear();
- AlreadyPrintedSet.clear();
- SimplifyMap->clear();
- SimplifyNegMap->clear();
- SolverMap.clear();
- AlwaysTrueFormMap.clear();
- _arrayread_ite.clear();
- _arrayread_symbol.clear();
- _introduced_symbols.clear();
- TransformMap.clear();
- _letid_expr_map->clear();
- CounterExampleMap.clear();
- ComputeFormulaMap.clear();
- StatInfoSet.clear();
-
- for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(),
- iset_end = _arrayname_readindices.end();
- iset!=iset_end;iset++) {
- iset->second.clear();
- }
-
- _arrayname_readindices.clear();
- //_interior_unique_table.clear();
- //_symbol_unique_table.clear();
- //_bvconst_unique_table.clear();
- }
-
- void BeevMgr::CopySolverMap_To_CounterExample(void) {
- if(!SolverMap.empty()) {
- CounterExampleMap.insert(SolverMap.begin(),SolverMap.end());
- }
- }
-
- void FatalError(const char * str, const ASTNode& a, int w) {
- if(a.GetKind() != UNDEFINED) {
- cerr << "Fatal Error: " << str << endl << a << endl;
- cerr << w << endl;
- }
- else {
- cerr << "Fatal Error: " << str << endl;
- cerr << w << endl;
- }
- if (vc_error_hdlr)
- vc_error_hdlr(str);
- exit(-1);
- //assert(0);
- }
-
- void FatalError(const char * str) {
- cerr << "Fatal Error: " << str << endl;
- if (vc_error_hdlr)
- vc_error_hdlr(str);
- exit(-1);
- //assert(0);
- }
-
- //Variable Order Printer: A global function which converts a MINISAT
- //var into a ASTNODE var. It then prints this var along with
- //variable order dcisions taken by MINISAT.
- void Convert_MINISATVar_To_ASTNode_Print(int minisat_var,
- int decision_level, int polarity) {
- BEEV::ASTNode vv = globalBeevMgr_for_parser->_SATVar_to_AST[minisat_var];
- cout << spaces(decision_level);
- if(polarity) {
- cout << "!";
- }
- vv.PL_Print(cout,0);
- cout << endl;
- }
-
- void SortByExprNum(ASTVec& v) {
- sort(v.begin(), v.end(), exprless);
- }
-
- void SortByArith(ASTVec& v) {
- sort(v.begin(), v.end(), arithless);
- }
-
- bool isAtomic(Kind kind) {
- if(TRUE == kind ||
- FALSE == kind ||
- EQ == kind ||
- NEQ == kind ||
- BVLT == kind ||
- BVLE == kind ||
- BVGT == kind ||
- BVGE == kind ||
- BVSLT == kind ||
- BVSLE == kind ||
- BVSGT == kind ||
- BVSGE == kind ||
- SYMBOL == kind ||
- BVGETBIT == kind)
- return true;
- return false;
- }
-
- BeevMgr::~BeevMgr() {
- ClearAllTables();
-
- delete SimplifyMap;
+ vv.PL_Print(cout, 0);
+ cout << endl;
+}
+
+void SortByExprNum(ASTVec& v)
+{
+ sort(v.begin(), v.end(), exprless);
+}
+
+void SortByArith(ASTVec& v)
+{
+ sort(v.begin(), v.end(), arithless);
+}
+
+bool isAtomic(Kind kind)
+{
+ if (TRUE == kind || FALSE == kind || EQ == kind || NEQ == kind || BVLT == kind || BVLE == kind || BVGT == kind || BVGE == kind || BVSLT == kind
+ || BVSLE == kind || BVSGT == kind || BVSGE == kind || SYMBOL == kind || BVGETBIT == kind)
+ return true;
+ return false;
+}
+
+BeevMgr::~BeevMgr()
+{
+ ClearAllTables();
+
+ delete SimplifyMap;
delete SimplifyNegMap;
- delete _letid_expr_map;
- }
+ delete _letid_expr_map;
+}
-}; // end namespace
+}
+; // end namespace
#ifndef AST_H
#define AST_H
-
#include <vector>
#ifdef EXT_HASH_MAP
#include <ext/hash_set>
#include "../constantbv/constantbv.h"
#endif
-
-
/*****************************************************************************
* LIST OF CLASSES DECLARED IN THIS FILE:
*
- * class BeevMgr;
- * class ASTNode;
- * class ASTInternal;
- * class ASTInterior;
+ * class BeevMgr;
+ * class ASTNode;
+ * class ASTInternal;
+ * class ASTInterior;
* class ASTSymbol;
* class ASTBVConst;
*****************************************************************************/
-namespace BEEV {
- using namespace std;
- using namespace MINISAT;
+namespace BEEV
+{
+using namespace std;
+using namespace MINISAT;
#ifdef EXT_HASH_MAP
- using namespace __gnu_cxx;
+using namespace __gnu_cxx;
#endif
- //return types for the GetType() function in ASTNode class
- enum types {
- BOOLEAN_TYPE = 0,
- BITVECTOR_TYPE,
- ARRAY_TYPE,
- UNKNOWN_TYPE
- };
-
- class BeevMgr;
- class ASTNode;
- class ASTInternal;
- class ASTInterior;
- class ASTSymbol;
- class ASTBVConst;
- class BVSolver;
-
- //Vector of ASTNodes, used for child nodes among other things.
- typedef vector<ASTNode> ASTVec;
- extern ASTVec _empty_ASTVec;
- extern BeevMgr * globalBeevMgr_for_parser;
-
- typedef unsigned int * CBV;
-
- /***************************************************************************/
- /* Class ASTNode: Smart pointer to actual ASTNode internal datastructure. */
- /***************************************************************************/
- class ASTNode {
- friend class BeevMgr;
- friend class CNFMgr;
- friend class ASTInterior;
- friend class vector<ASTNode>;
- //Print the arguments in lisp format.
- friend ostream &LispPrintVec(ostream &os,
- const ASTVec &v, int indentation = 0);
- friend ostream &LispPrintVecSpecial(ostream &os,
- const vector<const ASTNode*> &v, int indentation = 0);
-
- private:
- // FIXME: make this into a reference?
- ASTInternal * _int_node_ptr; // The real data.
-
- // Usual constructor.
- ASTNode(ASTInternal *in);
-
- //Equal iff ASTIntNode pointers are the same.
- friend bool operator==(const ASTNode node1, const ASTNode node2){
- return ((size_t) node1._int_node_ptr) == ((size_t) node2._int_node_ptr);
- }
-
- //MKK: This shouldn't be necessary, but for some inexplicable reason I
- //cannot get ToSAT.cpp to compile. The differences between the old files
- //(AST.h, ToSAT.cpp) and the new files are very minor, mostly Solver ->
- //Solver, and so the compiler errors are difficult to understand.
- friend bool operator!=(const ASTNode node1, const ASTNode node2){
- return ! (node1 == node2);
- //return ((size_t) node1._int_node_ptr) == ((size_t) node2._int_node_ptr);
- }
-
- /* FIXME: Nondeterministic code *** */
- /** questionable pointer comparison function */
- friend bool operator<(const ASTNode node1, const ASTNode node2){
- return ((size_t) node1._int_node_ptr) < ((size_t) node2._int_node_ptr);
- }
-
- public:
- //Check if it points to a null node
- bool IsNull () const { return _int_node_ptr == NULL; }
-
- // This is for sorting by expression number (used in Boolean
- //optimization).
- // With any ordering operation, the properties of the order
- // need to be carefully specified. In this case, we just
- // need identical exprs to be consecutive, and (NOT x) to
- // follow "x" immediately. For some time, this function was
- // "arithless" (below), which separates x and (NOT x) in some
- // cases.
- // DO NOT MODIFY WITHOUT CHECKING WITH DAVID DILL FIRST!
- friend bool exprless(const ASTNode n1, const ASTNode n2) {
- return (n1.GetNodeNum() < n2.GetNodeNum());
- } // end of exprless
-
- // This is for sorting by arithmetic expressions (for
- // combining like terms, etc.)
- friend bool arithless(const ASTNode n1, const ASTNode n2) {
- Kind k1 = n1.GetKind();
- Kind k2 = n2.GetKind();
-
- if (n1 == n2) {
- // necessary for "strict weak ordering"
- return false;
- }
- else if (BVCONST == k1 && BVCONST != k2) {
- // put consts first
- return true;
- }
- else if (BVCONST != k1 && BVCONST == k2) {
- // put consts first
- return false;
- }
- else if (SYMBOL == k1 && SYMBOL != k2) {
- // put symbols next
- return true;
- }
- else if (SYMBOL != k1 && SYMBOL == k2) {
- // put symbols next
- return false;
- }
- else {
- // otherwise, sort by exprnum (descendents will appear
- // before ancestors).
- return (n1.GetNodeNum() < n2.GetNodeNum());
- }
- } //end of arithless
-
- // Internal lisp-form printer that does not clear _node_print_table
- ostream &LispPrint1(ostream &os, int indentation) const;
-
- ostream &LispPrint_indent(ostream &os, int indentation) const;
-
- // For lisp DAG printing. Has it been printed already, so we can
- // just print the node number?
- bool IsAlreadyPrinted() const;
- void MarkAlreadyPrinted() const;
-
- // delegates to the ASTInternal node.
- void nodeprint(ostream& os, bool c_friendly = false) const;
-
-
- public:
- // Default constructor. This gets used when declaring an ASTVec
- // of a given size, in the hash table, etc. For faster
- // refcounting, create a symbol node for NULL. Give it a big
- // initial refcount. Never free it. also check, for ref-count
- // overflow?
- ASTNode() : _int_node_ptr(NULL) { };
-
- // Copy constructor
- ASTNode(const ASTNode &n);
-
- // Destructor
- ~ASTNode();
-
- // Assignment (for ref counting)
- ASTNode& operator=(const ASTNode& n);
-
- BeevMgr &GetBeevMgr() const;
-
- // Access node number
- int GetNodeNum() const;
-
- // Access kind. Inlined later because of declaration ordering problems.
- Kind GetKind() const;
-
- // access Children
- const ASTVec &GetChildren() const;
-
- // Return the number of child nodes
- size_t Degree() const{
- return GetChildren().size();
- };
-
- // Get indexth childNode.
- const ASTNode operator[](size_t index) const {
- return GetChildren()[index];
- };
-
- // Get begin() iterator for child nodes
- ASTVec::const_iterator begin() const{
- return GetChildren().begin();
- };
-
- // Get end() iterator for child nodes
- ASTVec::const_iterator end() const{
- return GetChildren().end();
- };
-
- //Get back() element for child nodes
- const ASTNode back() const{
- return GetChildren().back();
- };
-
- // Get the name from a symbol (char *). It's an error if kind != SYMBOL
- const char * const GetName() const;
-
- //Get the BVCONST value
+//return types for the GetType() function in ASTNode class
+enum types
+{
+ BOOLEAN_TYPE = 0, BITVECTOR_TYPE, ARRAY_TYPE, UNKNOWN_TYPE
+};
+
+class BeevMgr;
+class ASTNode;
+class ASTInternal;
+class ASTInterior;
+class ASTSymbol;
+class ASTBVConst;
+class BVSolver;
+
+//Vector of ASTNodes, used for child nodes among other things.
+typedef vector<ASTNode> ASTVec;
+extern ASTVec _empty_ASTVec;
+extern BeevMgr * globalBeevMgr_for_parser;
+
+typedef unsigned int * CBV;
+
+/***************************************************************************/
+/* Class ASTNode: Smart pointer to actual ASTNode internal datastructure. */
+/***************************************************************************/
+class ASTNode
+{
+ friend class BeevMgr;
+ friend class CNFMgr;
+ friend class ASTInterior;
+ friend class vector<ASTNode> ;
+ //Print the arguments in lisp format.
+ friend ostream &LispPrintVec(ostream &os, const ASTVec &v, int indentation = 0);
+ friend ostream &LispPrintVecSpecial(ostream &os, const vector<const ASTNode*> &v, int indentation = 0);
+
+private:
+ // FIXME: make this into a reference?
+ ASTInternal * _int_node_ptr; // The real data.
+
+ // Usual constructor.
+ ASTNode(ASTInternal *in);
+
+ //Equal iff ASTIntNode pointers are the same.
+ friend bool operator==(const ASTNode node1, const ASTNode node2)
+ {
+ return ((size_t) node1._int_node_ptr) == ((size_t) node2._int_node_ptr);
+ }
+
+ //MKK: This shouldn't be necessary, but for some inexplicable reason I
+ //cannot get ToSAT.cpp to compile. The differences between the old files
+ //(AST.h, ToSAT.cpp) and the new files are very minor, mostly Solver ->
+ //Solver, and so the compiler errors are difficult to understand.
+ friend bool operator!=(const ASTNode node1, const ASTNode node2)
+ {
+ return !(node1 == node2);
+ //return ((size_t) node1._int_node_ptr) == ((size_t) node2._int_node_ptr);
+ }
+
+ /* FIXME: Nondeterministic code *** */
+ /** questionable pointer comparison function */
+ friend bool operator<(const ASTNode node1, const ASTNode node2)
+ {
+ return ((size_t) node1._int_node_ptr) < ((size_t) node2._int_node_ptr);
+ }
+
+public:
+ //Check if it points to a null node
+ bool IsNull() const
+ {
+ return _int_node_ptr == NULL;
+ }
+
+ // This is for sorting by expression number (used in Boolean
+ //optimization).
+ // With any ordering operation, the properties of the order
+ // need to be carefully specified. In this case, we just
+ // need identical exprs to be consecutive, and (NOT x) to
+ // follow "x" immediately. For some time, this function was
+ // "arithless" (below), which separates x and (NOT x) in some
+ // cases.
+ // DO NOT MODIFY WITHOUT CHECKING WITH DAVID DILL FIRST!
+ friend bool exprless(const ASTNode n1, const ASTNode n2)
+ {
+ return (n1.GetNodeNum() < n2.GetNodeNum());
+ } // end of exprless
+
+ // This is for sorting by arithmetic expressions (for
+ // combining like terms, etc.)
+ friend bool arithless(const ASTNode n1, const ASTNode n2)
+ {
+ Kind k1 = n1.GetKind();
+ Kind k2 = n2.GetKind();
+
+ if (n1 == n2)
+ {
+ // necessary for "strict weak ordering"
+ return false;
+ }
+ else if (BVCONST == k1 && BVCONST != k2)
+ {
+ // put consts first
+ return true;
+ }
+ else if (BVCONST != k1 && BVCONST == k2)
+ {
+ // put consts first
+ return false;
+ }
+ else if (SYMBOL == k1 && SYMBOL != k2)
+ {
+ // put symbols next
+ return true;
+ }
+ else if (SYMBOL != k1 && SYMBOL == k2)
+ {
+ // put symbols next
+ return false;
+ }
+ else
+ {
+ // otherwise, sort by exprnum (descendents will appear
+ // before ancestors).
+ return (n1.GetNodeNum() < n2.GetNodeNum());
+ }
+ } //end of arithless
+
+ // Internal lisp-form printer that does not clear _node_print_table
+ ostream &LispPrint1(ostream &os, int indentation) const;
+
+ ostream &LispPrint_indent(ostream &os, int indentation) const;
+
+ // For lisp DAG printing. Has it been printed already, so we can
+ // just print the node number?
+ bool IsAlreadyPrinted() const;
+ void MarkAlreadyPrinted() const;
+
+ // delegates to the ASTInternal node.
+ void nodeprint(ostream& os, bool c_friendly = false) const;
+
+public:
+ // Default constructor. This gets used when declaring an ASTVec
+ // of a given size, in the hash table, etc. For faster
+ // refcounting, create a symbol node for NULL. Give it a big
+ // initial refcount. Never free it. also check, for ref-count
+ // overflow?
+ ASTNode() :
+ _int_node_ptr(NULL)
+ {
+ }
+ ;
+
+ // Copy constructor
+ ASTNode(const ASTNode &n);
+
+ // Destructor
+ ~ASTNode();
+
+ // Assignment (for ref counting)
+ ASTNode& operator=(const ASTNode& n);
+
+ BeevMgr &GetBeevMgr() const;
+
+ // Access node number
+ int GetNodeNum() const;
+
+ // Access kind. Inlined later because of declaration ordering problems.
+ Kind GetKind() const;
+
+ // access Children
+ const ASTVec &GetChildren() const;
+
+ // Return the number of child nodes
+ size_t Degree() const
+ {
+ return GetChildren().size();
+ }
+ ;
+
+ // Get indexth childNode.
+ const ASTNode operator[](size_t index) const
+ {
+ return GetChildren()[index];
+ }
+ ;
+
+ // Get begin() iterator for child nodes
+ ASTVec::const_iterator begin() const
+ {
+ return GetChildren().begin();
+ }
+ ;
+
+ // Get end() iterator for child nodes
+ ASTVec::const_iterator end() const
+ {
+ return GetChildren().end();
+ }
+ ;
+
+ //Get back() element for child nodes
+ const ASTNode back() const
+ {
+ return GetChildren().back();
+ }
+ ;
+
+ // Get the name from a symbol (char *). It's an error if kind != SYMBOL
+ const char * const GetName() const;
+
+ //Get the BVCONST value
#ifndef NATIVE_C_ARITH
- const CBV GetBVConst() const;
+ const CBV GetBVConst() const;
#else
- unsigned long long int GetBVConst() const;
+ unsigned long long int GetBVConst() const;
#endif
- /*ASTNode is of type BV <==> ((indexwidth=0)&&(valuewidth>0))
- *
- *ASTNode is of type ARRAY <==> ((indexwidth>0)&&(valuewidth>0))
- *
- *ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
- *
- *both indexwidth and valuewidth should never be less than 0
- */
- unsigned int GetIndexWidth () const;
-
- // FIXME: This function is dangerous. Try to eliminate it's use.
- void SetIndexWidth (unsigned int iw) const;
-
- unsigned int GetValueWidth () const;
-
- // FIXME: This function is dangerous. Try to eliminate it's use.
- void SetValueWidth (unsigned int vw) const;
-
- //return the type of the ASTNode
- //0 iff BOOLEAN
- //1 iff BITVECTOR
- //2 iff ARRAY
-
- /*ASTNode is of type BV <==> ((indexwidth=0)&&(valuewidth>0))
- *
- *ASTNode is of type ARRAY <==> ((indexwidth>0)&&(valuewidth>0))
- *
- *ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
- *
- *both indexwidth and valuewidth should never be less than 0
- */
- types GetType(void) const;
-
- // Hash is pointer value of _int_node_ptr.
- const size_t Hash() const{
- return (size_t) _int_node_ptr;
- //return GetNodeNum();
- }
-
- void NFASTPrint(int l, int max, int prefix) const;
-
- // lisp-form printer
- ostream& LispPrint(ostream &os, int indentation = 0) const;
-
- //Presentation Language Printer
- ostream& PL_Print(ostream &os, int indentation = 0) const;
-
- void PL_Print1(ostream &os, int indentation = 0, bool b = false) const;
-
- //Construct let variables for shared subterms
- void LetizeNode(void) const;
-
- // Attempt to define something that will work in the gdb
- friend void lp(ASTNode &node);
- friend void lpvec(const ASTVec &vec);
-
- friend ostream &operator<<(ostream &os, const ASTNode &node) {
- node.LispPrint(os, 0);
- return os;
- };
-
- // Check whether the ASTNode points to anything. Undefined nodes
- // are created by the default constructor. In binding table (for
- // lambda args, etc.), undefined nodes are used to represent
- // deleted entries.
- bool IsDefined() const { return _int_node_ptr != NULL; }
-
- /* Hasher class for STL hash_maps and hash_sets that use ASTNodes
- * as keys. Needs to be public so people can define hash tables
- * (and use ASTNodeMap class)*/
- class ASTNodeHasher {
- public:
- size_t operator() (const ASTNode& n) const{
- return (size_t) n._int_node_ptr;
- //return (size_t)n.GetNodeNum();
- };
- }; //End of ASTNodeHasher
-
- /* Equality for ASTNode hash_set and hash_map. Returns true iff
- * internal pointers are the same. Needs to be public so people
- * can define hash tables (and use ASTNodeSet class)*/
- class ASTNodeEqual {
- public:
- bool operator()(const ASTNode& n1, const ASTNode& n2) const{
- return (n1._int_node_ptr == n2._int_node_ptr);
- }
- }; //End of ASTNodeEqual
- }; //End of Class ASTNode
-
- void FatalError(const char * str, const ASTNode& a, int w = 0);
- void FatalError(const char * str);
- void SortByExprNum(ASTVec& c);
- void SortByArith(ASTVec& c);
- bool exprless(const ASTNode n1, const ASTNode n2);
- bool arithless(const ASTNode n1, const ASTNode n2);
- bool isAtomic(Kind k);
-
- /***************************************************************************/
- /* Class ASTInternal:Abstract base class for internal node representation.*/
- /* Requires Kind and ChildNodes so same traversal works */
- /* on all nodes. */
- /***************************************************************************/
- class ASTInternal {
-
- friend class ASTNode;
- friend class CNFMgr;
-
- protected:
-
- // reference count.
- int _ref_count;
-
- // Kind. It's a type tag and the operator.
- Kind _kind;
-
- // The vector of children (*** should this be in ASTInterior? ***)
- ASTVec _children;
-
- // Manager object. Having this backpointer means it's easy to
- // find the manager when we need it.
- BeevMgr &_bm;
-
- //Nodenum is a unique positive integer for the node. The nodenum
- //of a node should always be greater than its descendents (which
- //is easily achieved by incrementing the number each time a new
- //node is created).
- int _node_num;
-
- // Length of bitvector type for array index. The term is an
- // array iff this is positive. Otherwise, the term is a bitvector
- // or a bit.
- unsigned int _index_width;
-
- // Length of bitvector type for scalar value or array element.
- // If this is one, the term represents a single bit (same as a bitvector
- // of length 1). It must be 1 or greater.
- unsigned int _value_width;
-
- // Increment refcount.
+ /*ASTNode is of type BV <==> ((indexwidth=0)&&(valuewidth>0))
+ *
+ *ASTNode is of type ARRAY <==> ((indexwidth>0)&&(valuewidth>0))
+ *
+ *ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
+ *
+ *both indexwidth and valuewidth should never be less than 0
+ */
+ unsigned int GetIndexWidth() const;
+
+ // FIXME: This function is dangerous. Try to eliminate it's use.
+ void SetIndexWidth(unsigned int iw) const;
+
+ unsigned int GetValueWidth() const;
+
+ // FIXME: This function is dangerous. Try to eliminate it's use.
+ void SetValueWidth(unsigned int vw) const;
+
+ //return the type of the ASTNode
+ //0 iff BOOLEAN
+ //1 iff BITVECTOR
+ //2 iff ARRAY
+
+ /*ASTNode is of type BV <==> ((indexwidth=0)&&(valuewidth>0))
+ *
+ *ASTNode is of type ARRAY <==> ((indexwidth>0)&&(valuewidth>0))
+ *
+ *ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
+ *
+ *both indexwidth and valuewidth should never be less than 0
+ */
+ types GetType(void) const;
+
+ // Hash is pointer value of _int_node_ptr.
+ const size_t Hash() const
+ {
+ return (size_t) _int_node_ptr;
+ //return GetNodeNum();
+ }
+
+ void NFASTPrint(int l, int max, int prefix) const;
+
+ // lisp-form printer
+ ostream& LispPrint(ostream &os, int indentation = 0) const;
+
+ //Presentation Language Printer
+ ostream& PL_Print(ostream &os, int indentation = 0) const;
+
+ void PL_Print1(ostream &os, int indentation = 0, bool b = false) const;
+
+ //Construct let variables for shared subterms
+ void LetizeNode(void) const;
+
+ // Attempt to define something that will work in the gdb
+ friend void lp(ASTNode &node);
+ friend void lpvec(const ASTVec &vec);
+
+ friend ostream &operator<<(ostream &os, const ASTNode &node)
+ {
+ node.LispPrint(os, 0);
+ return os;
+ }
+ ;
+
+ // Check whether the ASTNode points to anything. Undefined nodes
+ // are created by the default constructor. In binding table (for
+ // lambda args, etc.), undefined nodes are used to represent
+ // deleted entries.
+ bool IsDefined() const
+ {
+ return _int_node_ptr != NULL;
+ }
+
+ /* Hasher class for STL hash_maps and hash_sets that use ASTNodes
+ * as keys. Needs to be public so people can define hash tables
+ * (and use ASTNodeMap class)*/
+ class ASTNodeHasher
+ {
+ public:
+ size_t operator()(const ASTNode& n) const
+ {
+ return (size_t) n._int_node_ptr;
+ //return (size_t)n.GetNodeNum();
+ }
+ ;
+ }; //End of ASTNodeHasher
+
+ /* Equality for ASTNode hash_set and hash_map. Returns true iff
+ * internal pointers are the same. Needs to be public so people
+ * can define hash tables (and use ASTNodeSet class)*/
+ class ASTNodeEqual
+ {
+ public:
+ bool operator()(const ASTNode& n1, const ASTNode& n2) const
+ {
+ return (n1._int_node_ptr == n2._int_node_ptr);
+ }
+ }; //End of ASTNodeEqual
+}; //End of Class ASTNode
+
+void FatalError(const char * str, const ASTNode& a, int w = 0);
+void FatalError(const char * str);
+void SortByExprNum(ASTVec& c);
+void SortByArith(ASTVec& c);
+bool exprless(const ASTNode n1, const ASTNode n2);
+bool arithless(const ASTNode n1, const ASTNode n2);
+bool isAtomic(Kind k);
+
+/***************************************************************************/
+/* Class ASTInternal:Abstract base class for internal node representation.*/
+/* Requires Kind and ChildNodes so same traversal works */
+/* on all nodes. */
+/***************************************************************************/
+class ASTInternal
+{
+
+ friend class ASTNode;
+ friend class CNFMgr;
+
+protected:
+
+ // reference count.
+ int _ref_count;
+
+ // Kind. It's a type tag and the operator.
+ Kind _kind;
+
+ // The vector of children (*** should this be in ASTInterior? ***)
+ ASTVec _children;
+
+ // Manager object. Having this backpointer means it's easy to
+ // find the manager when we need it.
+ BeevMgr &_bm;
+
+ //Nodenum is a unique positive integer for the node. The nodenum
+ //of a node should always be greater than its descendents (which
+ //is easily achieved by incrementing the number each time a new
+ //node is created).
+ int _node_num;
+
+ // Length of bitvector type for array index. The term is an
+ // array iff this is positive. Otherwise, the term is a bitvector
+ // or a bit.
+ unsigned int _index_width;
+
+ // Length of bitvector type for scalar value or array element.
+ // If this is one, the term represents a single bit (same as a bitvector
+ // of length 1). It must be 1 or greater.
+ unsigned int _value_width;
+
+ // Increment refcount.
#ifndef SMTLIB
- void IncRef() {
- ++_ref_count;
- }
+ void IncRef()
+ {
+ ++_ref_count;
+ }
#else
- void IncRef() { }
+ void IncRef()
+ {}
#endif
- // DecRef is a potentially expensive, because it has to delete
- // the node from the unique table, in addition to freeing it.
- // FIXME: Consider putting in a backpointer (iterator) to the hash
- // table entry so it can be deleted without looking it up again.
- void DecRef();
-
- virtual const Kind GetKind() const { return _kind; }
-
- virtual ASTVec const &GetChildren() const { return _children; }
-
- int GetNodeNum() const { return _node_num; }
-
- void SetNodeNum(int nn) { _node_num = nn; };
-
- // Constructor (bm only)
- ASTInternal(BeevMgr &bm, int nodenum = 0) :
- _ref_count(0),
- _kind(UNDEFINED),
- _bm(bm),
- _node_num(nodenum),
- _index_width(0),
- _value_width(0) { }
-
- // Constructor (kind only, empty children, int nodenum)
- ASTInternal(Kind kind, BeevMgr &bm, int nodenum = 0) :
- _ref_count(0),
- _kind(kind),
- _bm(bm),
- _node_num(nodenum),
- _index_width(0),
- _value_width(0) { }
-
- // Constructor (kind and children). This copies the contents of
- // the child nodes.
- // FIXME: is there a way to avoid repeating these?
- ASTInternal(Kind kind, const ASTVec &children, BeevMgr &bm, int nodenum = 0) :
- _ref_count(0),
- _kind(kind),
- _children(children),
- _bm(bm),
- _node_num(nodenum),
- _index_width(0),
- _value_width(0) { }
-
- // Copy constructor. This copies the contents of the child nodes
- // array, along with everything else. Assigning the smart pointer,
- // ASTNode, does NOT invoke this; This should only be used for
- // temporary hash keys before uniquefication.
- // FIXME: I don't think children need to be copied.
- ASTInternal(const ASTInternal &int_node, int nodenum = 0) :
- _ref_count(0),
- _kind(int_node._kind),
- _children(int_node._children),
- _bm(int_node._bm),
- _node_num(int_node._node_num),
- _index_width(int_node._index_width),
- _value_width(int_node._value_width) { }
-
- // Copying assign operator. Also copies contents of children.
- ASTInternal& operator=(const ASTInternal &int_node);
-
- // Cleanup function for removing from hash table
- virtual void CleanUp() = 0;
-
- // Destructor (does nothing, but is declared virtual here.
- virtual ~ASTInternal();
-
- // Abstract virtual print function for internal node.
- // (c_friendly is for printing hex. numbers that C compilers will accept)
- virtual void nodeprint(ostream& os, bool c_friendly = false) { os << "*"; };
- }; //End of Class ASTInternal
-
- // FIXME: Should children be only in interior node type?
- /***************************************************************************
- Class ASTInterior: Internal representation of an interior
- ASTNode. Generally, these nodes should have at least one
- child
- ***************************************************************************/
- class ASTInterior : public ASTInternal {
-
- friend class BeevMgr;
- friend class ASTNodeHasher;
- friend class ASTNodeEqual;
-
- private:
-
- // Hasher for ASTInterior pointer nodes
- class ASTInteriorHasher {
- public:
- size_t operator()(const ASTInterior *int_node_ptr) const;
- };
-
- // Equality for ASTInterior nodes
- class ASTInteriorEqual {
- public:
- bool operator()(const ASTInterior *int_node_ptr1,
- const ASTInterior *int_node_ptr2) const{
- return (*int_node_ptr1 == *int_node_ptr2);
- }
- };
-
- // Used in Equality class for hash tables
- friend bool operator==(const ASTInterior &int_node1,
- const ASTInterior &int_node2){
- return (int_node1._kind == int_node2._kind) &&
- (int_node1._children == int_node2._children);
- }
-
- // Call this when deleting a node that has been stored in the
- // the unique table
- virtual void CleanUp();
-
- // Returns kinds. "lispprinter" handles printing of parenthesis
- // and childnodes.
- // (c_friendly is for printing hex. numbers that C compilers will accept)
- virtual void nodeprint(ostream& os, bool c_friendly = false) {
- os << _kind_names[_kind];
- }
- public:
-
- // FIXME: This should not be public, but has to be because the
- // ASTInterior hash table insists on it. I can't seem to make the
- // private destructor visible to hash_set. It does not even work
- // to put "friend class hash_set<ASTInterior, ...>" in here.
-
- // Basic constructors
- ASTInterior(Kind kind, BeevMgr &bm) :
- ASTInternal(kind, bm) { }
-
- ASTInterior(Kind kind, ASTVec &children, BeevMgr &bm) :
- ASTInternal(kind, children, bm) { }
-
- //Copy constructor. This copies the contents of the child nodes
- //array, along with everything else. Assigning the smart pointer,
- //ASTNode, does NOT invoke this.
- ASTInterior(const ASTInterior &int_node) : ASTInternal(int_node) { }
-
- // Destructor (does nothing, but is declared virtual here.
- virtual ~ASTInterior();
-
- }; //End of ASTNodeInterior
-
-
- /***************************************************************************/
- /* Class ASTSymbol: Class to represent internals of Symbol node. */
- /***************************************************************************/
- class ASTSymbol : public ASTInternal{
- friend class BeevMgr;
- friend class ASTNode;
- friend class ASTNodeHasher;
- friend class ASTNodeEqual;
-
- private:
- // The name of the symbol
- const char * const _name;
-
- class ASTSymbolHasher{
- public:
- size_t operator() (const ASTSymbol *sym_ptr) const{
+ // DecRef is a potentially expensive, because it has to delete
+ // the node from the unique table, in addition to freeing it.
+ // FIXME: Consider putting in a backpointer (iterator) to the hash
+ // table entry so it can be deleted without looking it up again.
+ void DecRef();
+
+ virtual const Kind GetKind() const
+ {
+ return _kind;
+ }
+
+ virtual ASTVec const &GetChildren() const
+ {
+ return _children;
+ }
+
+ int GetNodeNum() const
+ {
+ return _node_num;
+ }
+
+ void SetNodeNum(int nn)
+ {
+ _node_num = nn;
+ }
+ ;
+
+ // Constructor (bm only)
+ ASTInternal(BeevMgr &bm, int nodenum = 0) :
+ _ref_count(0), _kind(UNDEFINED), _bm(bm), _node_num(nodenum), _index_width(0), _value_width(0)
+ {
+ }
+
+ // Constructor (kind only, empty children, int nodenum)
+ ASTInternal(Kind kind, BeevMgr &bm, int nodenum = 0) :
+ _ref_count(0), _kind(kind), _bm(bm), _node_num(nodenum), _index_width(0), _value_width(0)
+ {
+ }
+
+ // Constructor (kind and children). This copies the contents of
+ // the child nodes.
+ // FIXME: is there a way to avoid repeating these?
+ ASTInternal(Kind kind, const ASTVec &children, BeevMgr &bm, int nodenum = 0) :
+ _ref_count(0), _kind(kind), _children(children), _bm(bm), _node_num(nodenum), _index_width(0), _value_width(0)
+ {
+ }
+
+ // Copy constructor. This copies the contents of the child nodes
+ // array, along with everything else. Assigning the smart pointer,
+ // ASTNode, does NOT invoke this; This should only be used for
+ // temporary hash keys before uniquefication.
+ // FIXME: I don't think children need to be copied.
+ ASTInternal(const ASTInternal &int_node, int nodenum = 0) :
+ _ref_count(0), _kind(int_node._kind), _children(int_node._children), _bm(int_node._bm), _node_num(int_node._node_num), _index_width(
+ int_node._index_width), _value_width(int_node._value_width)
+ {
+ }
+
+ // Copying assign operator. Also copies contents of children.
+ ASTInternal& operator=(const ASTInternal &int_node);
+
+ // Cleanup function for removing from hash table
+ virtual void CleanUp() = 0;
+
+ // Destructor (does nothing, but is declared virtual here.
+ virtual ~ASTInternal();
+
+ // Abstract virtual print function for internal node.
+ // (c_friendly is for printing hex. numbers that C compilers will accept)
+ virtual void nodeprint(ostream& os, bool c_friendly = false)
+ {
+ os << "*";
+ }
+ ;
+}; //End of Class ASTInternal
+
+// FIXME: Should children be only in interior node type?
+/***************************************************************************
+ Class ASTInterior: Internal representation of an interior
+ ASTNode. Generally, these nodes should have at least one
+ child
+ ***************************************************************************/
+class ASTInterior: public ASTInternal
+{
+
+ friend class BeevMgr;
+ friend class ASTNodeHasher;
+ friend class ASTNodeEqual;
+
+private:
+
+ // Hasher for ASTInterior pointer nodes
+ class ASTInteriorHasher
+ {
+ public:
+ size_t operator()(const ASTInterior *int_node_ptr) const;
+ };
+
+ // Equality for ASTInterior nodes
+ class ASTInteriorEqual
+ {
+ public:
+ bool operator()(const ASTInterior *int_node_ptr1, const ASTInterior *int_node_ptr2) const
+ {
+ return (*int_node_ptr1 == *int_node_ptr2);
+ }
+ };
+
+ // Used in Equality class for hash tables
+ friend bool operator==(const ASTInterior &int_node1, const ASTInterior &int_node2)
+ {
+ return (int_node1._kind == int_node2._kind) && (int_node1._children == int_node2._children);
+ }
+
+ // Call this when deleting a node that has been stored in the
+ // the unique table
+ virtual void CleanUp();
+
+ // Returns kinds. "lispprinter" handles printing of parenthesis
+ // and childnodes.
+ // (c_friendly is for printing hex. numbers that C compilers will accept)
+ virtual void nodeprint(ostream& os, bool c_friendly = false)
+ {
+ os << _kind_names[_kind];
+ }
+public:
+
+ // FIXME: This should not be public, but has to be because the
+ // ASTInterior hash table insists on it. I can't seem to make the
+ // private destructor visible to hash_set. It does not even work
+ // to put "friend class hash_set<ASTInterior, ...>" in here.
+
+ // Basic constructors
+ ASTInterior(Kind kind, BeevMgr &bm) :
+ ASTInternal(kind, bm)
+ {
+ }
+
+ ASTInterior(Kind kind, ASTVec &children, BeevMgr &bm) :
+ ASTInternal(kind, children, bm)
+ {
+ }
+
+ //Copy constructor. This copies the contents of the child nodes
+ //array, along with everything else. Assigning the smart pointer,
+ //ASTNode, does NOT invoke this.
+ ASTInterior(const ASTInterior &int_node) :
+ ASTInternal(int_node)
+ {
+ }
+
+ // Destructor (does nothing, but is declared virtual here.
+ virtual ~ASTInterior();
+
+}; //End of ASTNodeInterior
+
+
+/***************************************************************************/
+/* Class ASTSymbol: Class to represent internals of Symbol node. */
+/***************************************************************************/
+class ASTSymbol: public ASTInternal
+{
+ friend class BeevMgr;
+ friend class ASTNode;
+ friend class ASTNodeHasher;
+ friend class ASTNodeEqual;
+
+private:
+ // The name of the symbol
+ const char * const _name;
+
+ class ASTSymbolHasher
+ {
+ public:
+ size_t operator()(const ASTSymbol *sym_ptr) const
+ {
#ifdef TR1_UNORDERED_MAP
- tr1::hash<string> h;
+ tr1::hash<string> h;
#else
- hash<char*> h;
+ hash<char*> h;
#endif
- return h(sym_ptr->_name);
- };
- };
-
- // Equality for ASTInternal nodes
- class ASTSymbolEqual{
- public:
- bool operator()(const ASTSymbol *sym_ptr1, const ASTSymbol *sym_ptr2) const{
- return (*sym_ptr1 == *sym_ptr2);
- }
- };
-
- friend bool operator==(const ASTSymbol &sym1, const ASTSymbol &sym2){
- return (strcmp(sym1._name, sym2._name) == 0);
- }
-
- const char * const GetName() const{return _name;}
-
- // Print function for symbol -- return name */
- // (c_friendly is for printing hex. numbers that C compilers will accept)
- virtual void nodeprint(ostream& os, bool c_friendly = false) { os << _name;}
-
- // Call this when deleting a node that has been stored in the
- // the unique table
- virtual void CleanUp();
-
- public:
-
- // Default constructor
- ASTSymbol(BeevMgr &bm) : ASTInternal(bm), _name(NULL) { }
-
- // Constructor. This does NOT copy its argument.
- ASTSymbol(const char * const name, BeevMgr &bm) : ASTInternal(SYMBOL, bm),
- _name(name) { }
-
- // Destructor (does nothing, but is declared virtual here.
- virtual ~ASTSymbol();
-
- // Copy constructor
- // FIXME: seems to be calling default constructor for astinternal
- ASTSymbol(const ASTSymbol &sym) :
- ASTInternal(sym._kind, sym._children, sym._bm),
- _name(sym._name) { }
- }; //End of ASTSymbol
-
-
- /***************************************************************************/
- /* Class ASTBVConst: Class to represent internals of a bitvectorconst */
- /***************************************************************************/
+ return h(sym_ptr->_name);
+ }
+ ;
+ };
+
+ // Equality for ASTInternal nodes
+ class ASTSymbolEqual
+ {
+ public:
+ bool operator()(const ASTSymbol *sym_ptr1, const ASTSymbol *sym_ptr2) const
+ {
+ return (*sym_ptr1 == *sym_ptr2);
+ }
+ };
+
+ friend bool operator==(const ASTSymbol &sym1, const ASTSymbol &sym2)
+ {
+ return (strcmp(sym1._name, sym2._name) == 0);
+ }
+
+ const char * const GetName() const
+ {
+ return _name;
+ }
+
+ // Print function for symbol -- return name */
+ // (c_friendly is for printing hex. numbers that C compilers will accept)
+ virtual void nodeprint(ostream& os, bool c_friendly = false)
+ {
+ os << _name;
+ }
+
+ // Call this when deleting a node that has been stored in the
+ // the unique table
+ virtual void CleanUp();
+
+public:
+
+ // Default constructor
+ ASTSymbol(BeevMgr &bm) :
+ ASTInternal(bm), _name(NULL)
+ {
+ }
+
+ // Constructor. This does NOT copy its argument.
+ ASTSymbol(const char * const name, BeevMgr &bm) :
+ ASTInternal(SYMBOL, bm), _name(name)
+ {
+ }
+
+ // Destructor (does nothing, but is declared virtual here.
+ virtual ~ASTSymbol();
+
+ // Copy constructor
+ // FIXME: seems to be calling default constructor for astinternal
+ ASTSymbol(const ASTSymbol &sym) :
+ ASTInternal(sym._kind, sym._children, sym._bm), _name(sym._name)
+ {
+ }
+}; //End of ASTSymbol
+
+
+/***************************************************************************/
+/* Class ASTBVConst: Class to represent internals of a bitvectorconst */
+/***************************************************************************/
#ifndef NATIVE_C_ARITH
- class ASTBVConst : public ASTInternal {
- friend class BeevMgr;
- friend class ASTNode;
- friend class ASTNodeHasher;
- friend class ASTNodeEqual;
-
- private:
- //This is the private copy of a bvconst currently
- //This should not be changed at any point
- CBV _bvconst;
-
- class ASTBVConstHasher{
- public:
- size_t operator() (const ASTBVConst * bvc) const {
- return CONSTANTBV::BitVector_Hash(bvc->_bvconst);
- };
- };
-
- class ASTBVConstEqual{
- public:
- bool operator()(const ASTBVConst * bvc1, const ASTBVConst * bvc2) const {
- if( bvc1->_value_width != bvc2->_value_width){
- return false;
- }
- return (0==CONSTANTBV::BitVector_Compare(bvc1->_bvconst,bvc2->_bvconst));
- }
- };
-
- //FIXME Keep an eye on this function
- ASTBVConst(CBV bv, unsigned int width, BeevMgr &bm) :
- ASTInternal(BVCONST, bm)
- {
- _bvconst = CONSTANTBV::BitVector_Clone(bv);
- _value_width = width;
- }
-
- friend bool operator==(const ASTBVConst &bvc1, const ASTBVConst &bvc2){
- if(bvc1._value_width != bvc2._value_width)
- return false;
- return (0==CONSTANTBV::BitVector_Compare(bvc1._bvconst,bvc2._bvconst));
- }
- // Call this when deleting a node that has been stored in the
- // the unique table
- virtual void CleanUp();
-
- // Print function for bvconst -- return _bvconst value in bin format
- // (c_friendly is for printing hex. numbers that C compilers will accept)
- virtual void nodeprint(ostream& os, bool c_friendly = false) {
- unsigned char *res;
- const char *prefix;
-
- if (_value_width%4 == 0) {
- res = CONSTANTBV::BitVector_to_Hex(_bvconst);
- if (c_friendly) {
- prefix = "0x";
- }
- else {
- prefix = "0hex";
- }
- } else {
- res = CONSTANTBV::BitVector_to_Bin(_bvconst);
- if (c_friendly) {
- prefix = "0b";
- }
- else {
- prefix = "0bin";
- }
- }
- if (NULL == res) {
- os << "nodeprint: BVCONST : could not convert to string" << _bvconst;
- FatalError("");
- }
- os << prefix << res;
- CONSTANTBV::BitVector_Dispose(res);
- }
-
- // Copy constructor.
- ASTBVConst(const ASTBVConst &sym) :
- ASTInternal(sym._kind, sym._children, sym._bm)
- {
- _bvconst = CONSTANTBV::BitVector_Clone(sym._bvconst);
- _value_width = sym._value_width;
- }
-
- public:
- virtual ~ASTBVConst(){
- CONSTANTBV::BitVector_Destroy(_bvconst);
- }
-
- CBV GetBVConst() const {return _bvconst;}
- }; //End of ASTBVConst
-
-
- //FIXME This function is DEPRECATED
- //Do not use in the future
- inline unsigned int GetUnsignedConst(const ASTNode n)
- {
- if(sizeof(unsigned int) * 8 <= n.GetValueWidth())
- {
- // It may only contain a small value in a bit type, which fits nicely into an unsigned int.
- // This is common for functions like: bvshl(bv1[128], bv1[128])
- // where both operands have the same type.
- signed long maxBit = CONSTANTBV::Set_Max(n.GetBVConst());
- if (maxBit >= ((signed long) sizeof(unsigned int)) * 8 )
- {
- n.LispPrint(cerr); //print the node so they can find it.
- FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int");
- }
- }
- return (unsigned int) *((unsigned int *)n.GetBVConst());
- }
+class ASTBVConst: public ASTInternal
+{
+ friend class BeevMgr;
+ friend class ASTNode;
+ friend class ASTNodeHasher;
+ friend class ASTNodeEqual;
+
+private:
+ //This is the private copy of a bvconst currently
+ //This should not be changed at any point
+ CBV _bvconst;
+
+ class ASTBVConstHasher
+ {
+ public:
+ size_t operator()(const ASTBVConst * bvc) const
+ {
+ return CONSTANTBV::BitVector_Hash(bvc->_bvconst);
+ }
+ ;
+ };
+
+ class ASTBVConstEqual
+ {
+ public:
+ bool operator()(const ASTBVConst * bvc1, const ASTBVConst * bvc2) const
+ {
+ if (bvc1->_value_width != bvc2->_value_width)
+ {
+ return false;
+ }
+ return (0 == CONSTANTBV::BitVector_Compare(bvc1->_bvconst, bvc2->_bvconst));
+ }
+ };
+
+ //FIXME Keep an eye on this function
+ ASTBVConst(CBV bv, unsigned int width, BeevMgr &bm) :
+ ASTInternal(BVCONST, bm)
+ {
+ _bvconst = CONSTANTBV::BitVector_Clone(bv);
+ _value_width = width;
+ }
+
+ friend bool operator==(const ASTBVConst &bvc1, const ASTBVConst &bvc2)
+ {
+ if (bvc1._value_width != bvc2._value_width)
+ return false;
+ return (0 == CONSTANTBV::BitVector_Compare(bvc1._bvconst, bvc2._bvconst));
+ }
+ // Call this when deleting a node that has been stored in the
+ // the unique table
+ virtual void CleanUp();
+
+ // Print function for bvconst -- return _bvconst value in bin format
+ // (c_friendly is for printing hex. numbers that C compilers will accept)
+ virtual void nodeprint(ostream& os, bool c_friendly = false)
+ {
+ unsigned char *res;
+ const char *prefix;
+
+ if (_value_width % 4 == 0)
+ {
+ res = CONSTANTBV::BitVector_to_Hex(_bvconst);
+ if (c_friendly)
+ {
+ prefix = "0x";
+ }
+ else
+ {
+ prefix = "0hex";
+ }
+ }
+ else
+ {
+ res = CONSTANTBV::BitVector_to_Bin(_bvconst);
+ if (c_friendly)
+ {
+ prefix = "0b";
+ }
+ else
+ {
+ prefix = "0bin";
+ }
+ }
+ if (NULL == res)
+ {
+ os << "nodeprint: BVCONST : could not convert to string" << _bvconst;
+ FatalError("");
+ }
+ os << prefix << res;
+ CONSTANTBV::BitVector_Dispose(res);
+ }
+
+ // Copy constructor.
+ ASTBVConst(const ASTBVConst &sym) :
+ ASTInternal(sym._kind, sym._children, sym._bm)
+ {
+ _bvconst = CONSTANTBV::BitVector_Clone(sym._bvconst);
+ _value_width = sym._value_width;
+ }
+
+public:
+ virtual ~ASTBVConst()
+ {
+ CONSTANTBV::BitVector_Destroy(_bvconst);
+ }
+
+ CBV GetBVConst() const
+ {
+ return _bvconst;
+ }
+}; //End of ASTBVConst
+
+
+//FIXME This function is DEPRECATED
+//Do not use in the future
+inline unsigned int GetUnsignedConst(const ASTNode n)
+{
+ if (sizeof(unsigned int) * 8 <= n.GetValueWidth())
+ {
+ // It may only contain a small value in a bit type, which fits nicely into an unsigned int.
+ // This is common for functions like: bvshl(bv1[128], bv1[128])
+ // where both operands have the same type.
+ signed long maxBit = CONSTANTBV::Set_Max(n.GetBVConst());
+ if (maxBit >= ((signed long) sizeof(unsigned int)) * 8)
+ {
+ n.LispPrint(cerr); //print the node so they can find it.
+ FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int");
+ }
+ }
+ return (unsigned int) *((unsigned int *) n.GetBVConst());
+}
#else
- class ASTBVConst : public ASTInternal {
- friend class BeevMgr;
- friend class ASTNode;
- friend class ASTNodeHasher;
- friend class ASTNodeEqual;
-
- private:
- // the bitvector contents. bitvector contents will be in two
- // modes. one mode where all bitvectors are NATIVE and in this
- // mode we use native unsigned long long int to represent the
- // 32/64 bitvectors. The other for arbitrary length bitvector
- // operations.
- const unsigned long long int _bvconst;
-
- class ASTBVConstHasher{
- public:
- size_t operator() (const ASTBVConst * bvc) const{
- //Thomas Wang's 64 bit Mix Function
- unsigned long long int key(bvc->_bvconst);
- key += ~(key << 32);
- key ^= (key >> 22);
- key += ~(key << 13);
- key ^= (key >> 8);
- key += (key << 3);
- key ^= (key >> 15);
- key += ~(key << 27);
- key ^= (key >> 31);
-
- size_t return_key = key;
- return return_key;
- };
- };
-
- class ASTBVConstEqual{
- public:
- bool operator()(const ASTBVConst * bvc1, const ASTBVConst * bvc2) const {
- return ((bvc1->_bvconst == bvc2->_bvconst)
- && (bvc1->_value_width == bvc2->_value_width));
- }
- };
-
- // Call this when deleting a node that has been stored in the
- // the unique table
- virtual void CleanUp();
- public:
- // Default constructor
- ASTBVConst(const unsigned long long int bv, BeevMgr &bm) :
- ASTInternal(BVCONST, bm), _bvconst(bv) {
- }
-
- // Copy constructor. FIXME: figure out how this is supposed to
- // work.
- ASTBVConst(const ASTBVConst &sym) :
- ASTInternal(sym._kind, sym._children, sym._bm),
- _bvconst(sym._bvconst) {
- _value_width = sym._value_width;
- }
-
- // Destructor (does nothing, but is declared virtual here)
- virtual ~ASTBVConst() { }
-
- friend bool operator==(const ASTBVConst &sym1, const ASTBVConst &sym2){
- return ((sym1._bvconst == sym2._bvconst) &&
- (sym1._value_width == sym2._value_width));
- }
-
- // Print function for bvconst -- return _bvconst value in binary format
- virtual void nodeprint(ostream& os, bool c_friendly = false) {
- string s = "0bin";
- unsigned long long int bitmask = 0x8000000000000000LL;
- bitmask = bitmask >> (64-_value_width);
-
- for (; bitmask > 0; bitmask >>= 1)
- s += (_bvconst & bitmask) ? '1' : '0';
- os << s;
- }
-
- unsigned long long int GetBVConst() const {return _bvconst;}
- }; //End of ASTBVConst
-
- //return value of bvconst
- inline unsigned int GetUnsignedConst(const ASTNode n) {
- if(32 < n.GetValueWidth())
- FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");
- return (unsigned int)n.GetBVConst();
- }
+class ASTBVConst : public ASTInternal
+{
+ friend class BeevMgr;
+ friend class ASTNode;
+ friend class ASTNodeHasher;
+ friend class ASTNodeEqual;
+
+private:
+ // the bitvector contents. bitvector contents will be in two
+ // modes. one mode where all bitvectors are NATIVE and in this
+ // mode we use native unsigned long long int to represent the
+ // 32/64 bitvectors. The other for arbitrary length bitvector
+ // operations.
+ const unsigned long long int _bvconst;
+
+ class ASTBVConstHasher
+ {
+ public:
+ size_t operator() (const ASTBVConst * bvc) const
+ {
+ //Thomas Wang's 64 bit Mix Function
+ unsigned long long int key(bvc->_bvconst);
+ key += ~(key << 32);
+ key ^= (key >> 22);
+ key += ~(key << 13);
+ key ^= (key >> 8);
+ key += (key << 3);
+ key ^= (key >> 15);
+ key += ~(key << 27);
+ key ^= (key >> 31);
+
+ size_t return_key = key;
+ return return_key;
+ };
+ };
+
+ class ASTBVConstEqual
+ {
+ public:
+ bool operator()(const ASTBVConst * bvc1, const ASTBVConst * bvc2) const
+ {
+ return ((bvc1->_bvconst == bvc2->_bvconst)
+ && (bvc1->_value_width == bvc2->_value_width));
+ }
+ };
+
+ // Call this when deleting a node that has been stored in the
+ // the unique table
+ virtual void CleanUp();
+public:
+ // Default constructor
+ ASTBVConst(const unsigned long long int bv, BeevMgr &bm) :
+ ASTInternal(BVCONST, bm), _bvconst(bv)
+ {
+ }
+
+ // Copy constructor. FIXME: figure out how this is supposed to
+ // work.
+ ASTBVConst(const ASTBVConst &sym) :
+ ASTInternal(sym._kind, sym._children, sym._bm),
+ _bvconst(sym._bvconst)
+ {
+ _value_width = sym._value_width;
+ }
+
+ // Destructor (does nothing, but is declared virtual here)
+ virtual ~ASTBVConst()
+ {}
+
+ friend bool operator==(const ASTBVConst &sym1, const ASTBVConst &sym2)
+ {
+ return ((sym1._bvconst == sym2._bvconst) &&
+ (sym1._value_width == sym2._value_width));
+ }
+
+ // Print function for bvconst -- return _bvconst value in binary format
+ virtual void nodeprint(ostream& os, bool c_friendly = false)
+ {
+ string s = "0bin";
+ unsigned long long int bitmask = 0x8000000000000000LL;
+ bitmask = bitmask >> (64-_value_width);
+
+ for (; bitmask > 0; bitmask >>= 1)
+ s += (_bvconst & bitmask) ? '1' : '0';
+ os << s;
+ }
+
+ unsigned long long int GetBVConst() const
+ { return _bvconst;}
+}; //End of ASTBVConst
+
+//return value of bvconst
+inline unsigned int GetUnsignedConst(const ASTNode n)
+{
+ if(32 < n.GetValueWidth())
+ FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");
+ return (unsigned int)n.GetBVConst();
+}
#endif
/*
-#else
- // the bitvector contents. bitvector contents will be in two
- // modes. one mode where all bitvectors are NATIVE and in this mode
- // we use native unsigned long long int to represent the 32/64
- // bitvectors. The other for arbitrary length bitvector operations.
-
- //BVCONST defined for arbitrary length bitvectors
- class ASTBVConst : public ASTInternal{
- friend class BeevMgr;
- friend class ASTNode;
- friend class ASTNodeHasher;
- friend class ASTNodeEqual;
-
- private:
- const char * const _bvconst;
-
- class ASTBVConstHasher{
- public:
- size_t operator() (const ASTBVConst * bvc) const{
- hash<char*> h;
- return h(bvc->_bvconst);
- };
- };
-
- class ASTBVConstEqual{
- public:
- bool operator()(const ASTBVConst * bvc1, const ASTBVConst * bvc2) const {
- if(bvc1->_value_width != bvc2->_value_width)
- return false;
- return (0 == strncmp(bvc1->_bvconst,bvc2->_bvconst,bvc1->_value_width));
- }
- };
-
- ASTBVConst(const char * bv, BeevMgr &bm) :
- ASTInternal(BVCONST, bm), _bvconst(bv) {
- //_value_width = strlen(bv);
- }
-
- friend bool operator==(const ASTBVConst &bvc1, const ASTBVConst &bvc2){
- if(bvc1._value_width != bvc2._value_width)
- return false;
- return (0 == strncmp(bvc1._bvconst,bvc2._bvconst,bvc1._value_width));
- }
-
- // Call this when deleting a node that has been stored in the
- // the unique table
- virtual void CleanUp();
-
- // Print function for bvconst -- return _bvconst value in binary format
- virtual void nodeprint(ostream& os) {
- if(_value_width%4 == 0) {
- unsigned int * iii = CONSTANTBV::BitVector_Create(_value_width,true);
- CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(iii,(unsigned char*)_bvconst);
- //error printing
- if(0 != e) {
- os << "nodeprint: BVCONST : wrong hex value: " << BitVector_Error(e);
- FatalError("");
+ #else
+ // the bitvector contents. bitvector contents will be in two
+ // modes. one mode where all bitvectors are NATIVE and in this mode
+ // we use native unsigned long long int to represent the 32/64
+ // bitvectors. The other for arbitrary length bitvector operations.
+
+ //BVCONST defined for arbitrary length bitvectors
+ class ASTBVConst : public ASTInternal{
+ friend class BeevMgr;
+ friend class ASTNode;
+ friend class ASTNodeHasher;
+ friend class ASTNodeEqual;
+
+ private:
+ const char * const _bvconst;
+
+ class ASTBVConstHasher{
+ public:
+ size_t operator() (const ASTBVConst * bvc) const{
+ hash<char*> h;
+ return h(bvc->_bvconst);
+ };
+ };
+
+ class ASTBVConstEqual{
+ public:
+ bool operator()(const ASTBVConst * bvc1, const ASTBVConst * bvc2) const {
+ if(bvc1->_value_width != bvc2->_value_width)
+ return false;
+ return (0 == strncmp(bvc1->_bvconst,bvc2->_bvconst,bvc1->_value_width));
+ }
+ };
+
+ ASTBVConst(const char * bv, BeevMgr &bm) :
+ ASTInternal(BVCONST, bm), _bvconst(bv) {
+ //_value_width = strlen(bv);
+ }
+
+ friend bool operator==(const ASTBVConst &bvc1, const ASTBVConst &bvc2){
+ if(bvc1._value_width != bvc2._value_width)
+ return false;
+ return (0 == strncmp(bvc1._bvconst,bvc2._bvconst,bvc1._value_width));
+ }
+
+ // Call this when deleting a node that has been stored in the
+ // the unique table
+ virtual void CleanUp();
+
+ // Print function for bvconst -- return _bvconst value in binary format
+ virtual void nodeprint(ostream& os) {
+ if(_value_width%4 == 0) {
+ unsigned int * iii = CONSTANTBV::BitVector_Create(_value_width,true);
+ CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(iii,(unsigned char*)_bvconst);
+ //error printing
+ if(0 != e) {
+ os << "nodeprint: BVCONST : wrong hex value: " << BitVector_Error(e);
+ FatalError("");
+ }
+ unsigned char * ccc = CONSTANTBV::BitVector_to_Hex(iii);
+ os << "0hex" << ccc;
+ CONSTANTBV::BitVector_Destroy(iii);
+ }
+ else {
+ std::string s(_bvconst,_value_width);
+ s = "0bin" + s;
+ os << s;
+ }
+ }
+
+ // Copy constructor.
+ ASTBVConst(const ASTBVConst &sym) : ASTInternal(sym._kind, sym._children, sym._bm),_bvconst(sym._bvconst) {
+ //checking if the input is in the correct format
+ for(unsigned int jj=0;jj<sym._value_width;jj++)
+ if(!(sym._bvconst[jj] == '0' || sym._bvconst[jj] == '1')) {
+ cerr << "Fatal Error: wrong input to ASTBVConst copy constructor:" << sym._bvconst << endl;
+ FatalError("");
+ }
+ _value_width = sym._value_width;
+ }
+ public:
+ // Destructor (does nothing, but is declared virtual here)
+ virtual ~ASTBVConst(){}
+
+ const char * const GetBVConst() const {return _bvconst;}
+ }; //End of ASTBVConst
+
+ unsigned int * ConvertToCONSTANTBV(const char * s);
+
+ //return value of bvconst
+ inline unsigned int GetUnsignedConst(const ASTNode n) {
+ if(32 < n.GetValueWidth())
+ FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");
+ std::string s(n.GetBVConst(), n.GetValueWidth());
+ unsigned int output = strtoul(s.c_str(),NULL,2);
+ return output;
+ } //end of ASTBVConst class
+ #endif
+ */
+/***************************************************************************
+ * Typedef ASTNodeMap: This is a hash table from ASTNodes to ASTNodes.
+ * It is very convenient for attributes that are not speed-critical
+ **************************************************************************/
+// These are generally useful for storing ASTNodes or attributes thereof
+// Hash table from ASTNodes to ASTNodes
+typedef hash_map<ASTNode, ASTNode, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTNodeMap;
+
+// Function to dump contents of ASTNodeMap
+ostream &operator<<(ostream &os, const ASTNodeMap &nmap);
+
+/***************************************************************************
+ Typedef ASTNodeSet: This is a hash set of ASTNodes. Very useful
+ for representing things like "visited nodes"
+ ***************************************************************************/
+typedef hash_set<ASTNode, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTNodeSet;
+
+typedef hash_multiset<ASTNode, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTNodeMultiSet;
+
+//external parser table for declared symbols.
+//FIXME: move to a more appropriate place
+extern ASTNodeSet _parser_symbol_table;
+
+/***************************************************************************
+ Class LispPrinter: iomanipulator for printing ASTNode or ASTVec
+ ***************************************************************************/
+class LispPrinter
+{
+
+public:
+ ASTNode _node;
+
+ // number of spaces to print before first real character of
+ // object.
+ int _indentation;
+
+ // FIXME: pass ASTNode by reference
+ // Constructor to build the LispPrinter object
+ LispPrinter(ASTNode node, int indentation) :
+ _node(node), _indentation(indentation)
+ {
}
- unsigned char * ccc = CONSTANTBV::BitVector_to_Hex(iii);
- os << "0hex" << ccc;
- CONSTANTBV::BitVector_Destroy(iii);
- }
- else {
- std::string s(_bvconst,_value_width);
- s = "0bin" + s;
- os << s;
- }
- }
-
- // Copy constructor.
- ASTBVConst(const ASTBVConst &sym) : ASTInternal(sym._kind, sym._children, sym._bm),_bvconst(sym._bvconst) {
- //checking if the input is in the correct format
- for(unsigned int jj=0;jj<sym._value_width;jj++)
- if(!(sym._bvconst[jj] == '0' || sym._bvconst[jj] == '1')) {
- cerr << "Fatal Error: wrong input to ASTBVConst copy constructor:" << sym._bvconst << endl;
- FatalError("");
+
+ friend ostream &operator<<(ostream &os, const LispPrinter &lp)
+ {
+ return lp._node.LispPrint(os, lp._indentation);
}
- _value_width = sym._value_width;
- }
- public:
- // Destructor (does nothing, but is declared virtual here)
- virtual ~ASTBVConst(){}
-
- const char * const GetBVConst() const {return _bvconst;}
- }; //End of ASTBVConst
-
- unsigned int * ConvertToCONSTANTBV(const char * s);
-
- //return value of bvconst
- inline unsigned int GetUnsignedConst(const ASTNode n) {
- if(32 < n.GetValueWidth())
- FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");
- std::string s(n.GetBVConst(), n.GetValueWidth());
- unsigned int output = strtoul(s.c_str(),NULL,2);
- return output;
- } //end of ASTBVConst class
-#endif
-*/
- /***************************************************************************
- * Typedef ASTNodeMap: This is a hash table from ASTNodes to ASTNodes.
- * It is very convenient for attributes that are not speed-critical
- **************************************************************************/
- // These are generally useful for storing ASTNodes or attributes thereof
- // Hash table from ASTNodes to ASTNodes
- typedef hash_map<ASTNode, ASTNode,
- ASTNode::ASTNodeHasher,
- ASTNode::ASTNodeEqual> ASTNodeMap;
-
- // Function to dump contents of ASTNodeMap
- ostream &operator<<(ostream &os, const ASTNodeMap &nmap);
-
- /***************************************************************************
- Typedef ASTNodeSet: This is a hash set of ASTNodes. Very useful
- for representing things like "visited nodes"
- ***************************************************************************/
- typedef hash_set<ASTNode,
- ASTNode::ASTNodeHasher,
- ASTNode::ASTNodeEqual> ASTNodeSet;
-
- typedef hash_multiset<ASTNode,
- ASTNode::ASTNodeHasher,
- ASTNode::ASTNodeEqual> ASTNodeMultiSet;
-
- //external parser table for declared symbols.
- //FIXME: move to a more appropriate place
- extern ASTNodeSet _parser_symbol_table;
-
- /***************************************************************************
- Class LispPrinter: iomanipulator for printing ASTNode or ASTVec
- ***************************************************************************/
- class LispPrinter {
-
- public:
- ASTNode _node;
-
- // number of spaces to print before first real character of
- // object.
- int _indentation;
-
- // FIXME: pass ASTNode by reference
- // Constructor to build the LispPrinter object
- LispPrinter(ASTNode node, int indentation): _node(node), _indentation(indentation) { }
-
- friend ostream &operator<<(ostream &os, const LispPrinter &lp){
- return lp._node.LispPrint(os, lp._indentation);
- };
-
- }; //End of ListPrinter
-
- //This is the IO manipulator. It builds an object of class
- //"LispPrinter" that has a special overloaded "<<" operator.
- inline LispPrinter lisp(const ASTNode &node, int indentation = 0){
- LispPrinter lp(node, indentation);
- return lp;
- }
-
- /***************************************************************************/
- /* Class LispVecPrinter:iomanipulator for printing vector of ASTNodes */
- /***************************************************************************/
- class LispVecPrinter {
-
- public:
- const ASTVec * _vec;
- // number of spaces to print before first real
- // character of object.
- int _indentation;
-
- // Constructor to build the LispPrinter object
- LispVecPrinter(const ASTVec &vec, int indentation){
- _vec = &vec; _indentation = indentation;
- }
-
- friend ostream &operator<<(ostream &os, const LispVecPrinter &lvp){
- LispPrintVec(os, *lvp._vec, lvp._indentation);
- return os;
- };
- }; //End of Class ListVecPrinter
-
- //iomanipulator. builds an object of class "LisPrinter" that has a
- //special overloaded "<<" operator.
- inline LispVecPrinter lisp(const ASTVec &vec, int indentation = 0){
- LispVecPrinter lvp(vec, indentation);
- return lvp;
- }
-
-
- /*****************************************************************
- * INLINE METHODS from various classed, declared here because of
- * dependencies on classes that are declared later.
- *****************************************************************/
- // ASTNode accessor function.
- inline Kind ASTNode::GetKind() const {
- //cout << "GetKind: " << _int_node_ptr;
- return _int_node_ptr->GetKind();
- }
-
- // FIXME: should be const ASTVec const?
- // Declared here because of same ordering problem as GetKind.
- inline const ASTVec &ASTNode::GetChildren() const {
- return _int_node_ptr->GetChildren();
- }
-
- // Access node number
- inline int ASTNode::GetNodeNum() const {
- return _int_node_ptr->_node_num;
- }
-
- inline unsigned int ASTNode::GetIndexWidth () const {
- return _int_node_ptr->_index_width;
- }
-
- inline void ASTNode::SetIndexWidth (unsigned int iw) const {
- _int_node_ptr->_index_width = iw;
- }
-
- inline unsigned int ASTNode::GetValueWidth () const {
- return _int_node_ptr->_value_width;
- }
-
- inline void ASTNode::SetValueWidth (unsigned int vw) const {
- _int_node_ptr->_value_width = vw;
- }
-
- //return the type of the ASTNode: 0 iff BOOLEAN; 1 iff BITVECTOR; 2
- //iff ARRAY; 3 iff UNKNOWN;
- inline types ASTNode::GetType() const {
- if((GetIndexWidth() == 0) && (GetValueWidth() == 0)) //BOOLEAN
- return BOOLEAN_TYPE;
- if((GetIndexWidth() == 0) && (GetValueWidth() > 0)) //BITVECTOR
- return BITVECTOR_TYPE;
- if((GetIndexWidth() > 0) && (GetValueWidth() > 0)) //ARRAY
- return ARRAY_TYPE;
- return UNKNOWN_TYPE;
- }
-
- // Constructor; creates a new pointer, increments refcount of
- // pointed-to object.
+ ;
+
+}; //End of ListPrinter
+
+//This is the IO manipulator. It builds an object of class
+//"LispPrinter" that has a special overloaded "<<" operator.
+inline LispPrinter lisp(const ASTNode &node, int indentation = 0)
+{
+ LispPrinter lp(node, indentation);
+ return lp;
+}
+
+/***************************************************************************/
+/* Class LispVecPrinter:iomanipulator for printing vector of ASTNodes */
+/***************************************************************************/
+class LispVecPrinter
+{
+
+public:
+ const ASTVec * _vec;
+ // number of spaces to print before first real
+ // character of object.
+ int _indentation;
+
+ // Constructor to build the LispPrinter object
+ LispVecPrinter(const ASTVec &vec, int indentation)
+ {
+ _vec = &vec;
+ _indentation = indentation;
+ }
+
+ friend ostream &operator<<(ostream &os, const LispVecPrinter &lvp)
+ {
+ LispPrintVec(os, *lvp._vec, lvp._indentation);
+ return os;
+ }
+ ;
+}; //End of Class ListVecPrinter
+
+//iomanipulator. builds an object of class "LisPrinter" that has a
+//special overloaded "<<" operator.
+inline LispVecPrinter lisp(const ASTVec &vec, int indentation = 0)
+{
+ LispVecPrinter lvp(vec, indentation);
+ return lvp;
+}
+
+/*****************************************************************
+ * INLINE METHODS from various classed, declared here because of
+ * dependencies on classes that are declared later.
+ *****************************************************************/
+// ASTNode accessor function.
+inline Kind ASTNode::GetKind() const
+{
+ //cout << "GetKind: " << _int_node_ptr;
+ return _int_node_ptr->GetKind();
+}
+
+// FIXME: should be const ASTVec const?
+// Declared here because of same ordering problem as GetKind.
+inline const ASTVec &ASTNode::GetChildren() const
+{
+ return _int_node_ptr->GetChildren();
+}
+
+// Access node number
+inline int ASTNode::GetNodeNum() const
+{
+ return _int_node_ptr->_node_num;
+}
+
+inline unsigned int ASTNode::GetIndexWidth() const
+{
+ return _int_node_ptr->_index_width;
+}
+
+inline void ASTNode::SetIndexWidth(unsigned int iw) const
+{
+ _int_node_ptr->_index_width = iw;
+}
+
+inline unsigned int ASTNode::GetValueWidth() const
+{
+ return _int_node_ptr->_value_width;
+}
+
+inline void ASTNode::SetValueWidth(unsigned int vw) const
+{
+ _int_node_ptr->_value_width = vw;
+}
+
+//return the type of the ASTNode: 0 iff BOOLEAN; 1 iff BITVECTOR; 2
+//iff ARRAY; 3 iff UNKNOWN;
+inline types ASTNode::GetType() const
+{
+ if ((GetIndexWidth() == 0) && (GetValueWidth() == 0)) //BOOLEAN
+ return BOOLEAN_TYPE;
+ if ((GetIndexWidth() == 0) && (GetValueWidth() > 0)) //BITVECTOR
+ return BITVECTOR_TYPE;
+ if ((GetIndexWidth() > 0) && (GetValueWidth() > 0)) //ARRAY
+ return ARRAY_TYPE;
+ return UNKNOWN_TYPE;
+}
+
+// Constructor; creates a new pointer, increments refcount of
+// pointed-to object.
#ifndef SMTLIB
- inline ASTNode::ASTNode(ASTInternal *in) : _int_node_ptr(in) {
- if (in) in->IncRef();
- }
+inline ASTNode::ASTNode(ASTInternal *in) :
+ _int_node_ptr(in)
+{
+ if (in)
+ in->IncRef();
+}
#else
- inline ASTNode::ASTNode(ASTInternal *in) : _int_node_ptr(in) { };
+inline ASTNode::ASTNode(ASTInternal *in) : _int_node_ptr(in)
+{};
#endif
- // Assignment. Increment refcount of new value, decrement refcount
- // of old value and destroy if this was the last pointer. FIXME:
- // accelerate this by creating an intnode with a ref counter instead
- // of pointing to NULL. Need a special check in CleanUp to make
- // sure the null node never gets freed.
+// Assignment. Increment refcount of new value, decrement refcount
+// of old value and destroy if this was the last pointer. FIXME:
+// accelerate this by creating an intnode with a ref counter instead
+// of pointing to NULL. Need a special check in CleanUp to make
+// sure the null node never gets freed.
#ifndef SMTLIB
- inline ASTNode& ASTNode::operator=(const ASTNode& n) {
- if (n._int_node_ptr) {
- n._int_node_ptr->IncRef();
- }
- if (_int_node_ptr) {
- _int_node_ptr->DecRef();
- }
- _int_node_ptr = n._int_node_ptr;
- return *this;
- }
+inline ASTNode& ASTNode::operator=(const ASTNode& n)
+{
+ if (n._int_node_ptr)
+ {
+ n._int_node_ptr->IncRef();
+ }
+ if (_int_node_ptr)
+ {
+ _int_node_ptr->DecRef();
+ }
+ _int_node_ptr = n._int_node_ptr;
+ return *this;
+}
#else
- inline ASTNode& ASTNode::operator=(const ASTNode& n) {
- _int_node_ptr = n._int_node_ptr;
- return *this;
- }
+inline ASTNode& ASTNode::operator=(const ASTNode& n)
+{
+ _int_node_ptr = n._int_node_ptr;
+ return *this;
+}
#endif
#ifndef SMTLIB
- inline void ASTInternal::DecRef()
- {
- if (--_ref_count == 0) {
- // Delete node from unique table and kill it.
- CleanUp();
- }
- }
-
- // Destructor
- inline ASTNode::~ASTNode()
- {
- if (_int_node_ptr) {
- _int_node_ptr->DecRef();
- }
- };
+inline void ASTInternal::DecRef()
+{
+ if (--_ref_count == 0)
+ {
+ // Delete node from unique table and kill it.
+ CleanUp();
+ }
+}
+
+// Destructor
+inline ASTNode::~ASTNode()
+{
+ if (_int_node_ptr)
+ {
+ _int_node_ptr->DecRef();
+ }
+}
+;
#else
- // No refcounting
- inline void ASTInternal::DecRef()
- {
- }
-
- // Destructor
- inline ASTNode::~ASTNode()
- {
- };
+// No refcounting
+inline void ASTInternal::DecRef()
+{
+}
+
+// Destructor
+inline ASTNode::~ASTNode()
+{
+};
#endif
- inline BeevMgr& ASTNode::GetBeevMgr() const { return _int_node_ptr->_bm; }
-
- /***************************************************************************
- * Class BeevMgr. This holds all "global" variables for the system, such as
- * unique tables for the various kinds of nodes.
- ***************************************************************************/
- class BeevMgr {
- friend class ASTNode; // ASTNode modifies AlreadyPrintedSet
- // in BeevMgr
- friend class ASTInterior;
- friend class ASTBVConst;
- friend class ASTSymbol;
-
- // FIXME: The values appear to be the same regardless of the value of SMTLIB
- // initial hash table sizes, to save time on resizing.
+inline BeevMgr& ASTNode::GetBeevMgr() const
+{
+ return _int_node_ptr->_bm;
+}
+
+/***************************************************************************
+ * Class BeevMgr. This holds all "global" variables for the system, such as
+ * unique tables for the various kinds of nodes.
+ ***************************************************************************/
+class BeevMgr
+{
+ friend class ASTNode; // ASTNode modifies AlreadyPrintedSet
+ // in BeevMgr
+ friend class ASTInterior;
+ friend class ASTBVConst;
+ friend class ASTSymbol;
+
+ // FIXME: The values appear to be the same regardless of the value of SMTLIB
+ // initial hash table sizes, to save time on resizing.
#ifdef SMTLIB
- static const int INITIAL_INTERIOR_UNIQUE_TABLE_SIZE = 100;
- static const int INITIAL_SYMBOL_UNIQUE_TABLE_SIZE = 100;
- static const int INITIAL_BVCONST_UNIQUE_TABLE_SIZE = 100;
- static const int INITIAL_BBTERM_MEMO_TABLE_SIZE = 100;
- static const int INITIAL_BBFORM_MEMO_TABLE_SIZE = 100;
-
- static const int INITIAL_SIMPLIFY_MAP_SIZE = 100;
- static const int INITIAL_SOLVER_MAP_SIZE = 100;
- static const int INITIAL_ARRAYREAD_SYMBOL_SIZE = 100;
- static const int INITIAL_INTRODUCED_SYMBOLS_SIZE = 100;
+ static const int INITIAL_INTERIOR_UNIQUE_TABLE_SIZE = 100;
+ static const int INITIAL_SYMBOL_UNIQUE_TABLE_SIZE = 100;
+ static const int INITIAL_BVCONST_UNIQUE_TABLE_SIZE = 100;
+ static const int INITIAL_BBTERM_MEMO_TABLE_SIZE = 100;
+ static const int INITIAL_BBFORM_MEMO_TABLE_SIZE = 100;
+
+ static const int INITIAL_SIMPLIFY_MAP_SIZE = 100;
+ static const int INITIAL_SOLVER_MAP_SIZE = 100;
+ static const int INITIAL_ARRAYREAD_SYMBOL_SIZE = 100;
+ static const int INITIAL_INTRODUCED_SYMBOLS_SIZE = 100;
#else
- // these are the STL defaults
- static const int INITIAL_INTERIOR_UNIQUE_TABLE_SIZE = 100;
- static const int INITIAL_SYMBOL_UNIQUE_TABLE_SIZE = 100;
- static const int INITIAL_BVCONST_UNIQUE_TABLE_SIZE = 100;
- static const int INITIAL_BBTERM_MEMO_TABLE_SIZE = 100;
- static const int INITIAL_BBFORM_MEMO_TABLE_SIZE = 100;
-
- static const int INITIAL_SIMPLIFY_MAP_SIZE = 100;
- static const int INITIAL_SOLVER_MAP_SIZE = 100;
- static const int INITIAL_ARRAYREAD_SYMBOL_SIZE = 100;
- static const int INITIAL_INTRODUCED_SYMBOLS_SIZE = 100;
+ // these are the STL defaults
+ static const int INITIAL_INTERIOR_UNIQUE_TABLE_SIZE = 100;
+ static const int INITIAL_SYMBOL_UNIQUE_TABLE_SIZE = 100;
+ static const int INITIAL_BVCONST_UNIQUE_TABLE_SIZE = 100;
+ static const int INITIAL_BBTERM_MEMO_TABLE_SIZE = 100;
+ static const int INITIAL_BBFORM_MEMO_TABLE_SIZE = 100;
+
+ static const int INITIAL_SIMPLIFY_MAP_SIZE = 100;
+ static const int INITIAL_SOLVER_MAP_SIZE = 100;
+ static const int INITIAL_ARRAYREAD_SYMBOL_SIZE = 100;
+ static const int INITIAL_INTRODUCED_SYMBOLS_SIZE = 100;
#endif
- private:
- // Typedef for unique Interior node table.
- typedef hash_set<ASTInterior *,
- ASTInterior::ASTInteriorHasher,
- ASTInterior::ASTInteriorEqual> ASTInteriorSet;
-
- // Typedef for unique Symbol node (leaf) table.
- typedef hash_set<ASTSymbol *,
- ASTSymbol::ASTSymbolHasher,
- ASTSymbol::ASTSymbolEqual> ASTSymbolSet;
-
- // Unique tables to share nodes whenever possible.
- ASTInteriorSet _interior_unique_table;
- //The _symbol_unique_table is also the symbol table to be used
- //during parsing/semantic analysis
- ASTSymbolSet _symbol_unique_table;
-
- //Typedef for unique BVConst node (leaf) table.
- typedef hash_set<ASTBVConst *,
- ASTBVConst::ASTBVConstHasher,
- ASTBVConst::ASTBVConstEqual> ASTBVConstSet;
-
- //table to uniquefy bvconst
- ASTBVConstSet _bvconst_unique_table;
-
- // type of memo table.
- typedef hash_map<ASTNode, ASTVec,
- ASTNode::ASTNodeHasher,
- ASTNode::ASTNodeEqual> ASTNodeToVecMap;
-
- typedef hash_map<ASTNode,ASTNodeSet,
- ASTNode::ASTNodeHasher,
- ASTNode::ASTNodeEqual> ASTNodeToSetMap;
-
- // Memo table for bit blasted terms. If a node has already been
- // bitblasted, it is mapped to a vector of Boolean formulas for
- // the bits.
-
- //OLD: ASTNodeToVecMap BBTermMemo;
- ASTNodeMap BBTermMemo;
-
- // Memo table for bit blasted formulas. If a node has already
- // been bitblasted, it is mapped to a node representing the
- // bitblasted equivalent
- ASTNodeMap BBFormMemo;
-
- //public:
- // Get vector of Boolean formulas for sum of two
- // vectors of Boolean formulas
- void BBPlus2(ASTVec& sum, const ASTVec& y, ASTNode cin);
- // Increment
- ASTVec BBInc(ASTVec& x);
- // Add one bit to a vector of bits.
- ASTVec BBAddOneBit(ASTVec& x, ASTNode cin);
- // Bitwise complement
- ASTVec BBNeg(const ASTVec& x);
- // Unary minus
- ASTVec BBUminus(const ASTVec& x);
- // Multiply.
- ASTVec BBMult(const ASTVec& x, const ASTVec& y);
- // AND each bit of vector y with single bit b and return the result.
- // (used in BBMult)
- ASTVec BBAndBit(const ASTVec& y, ASTNode b);
- // Returns ASTVec for result - y. This destroys "result".
- void BBSub(ASTVec& result, const ASTVec& y);
- // build ITE's (ITE cond then[i] else[i]) for each i.
- ASTVec BBITE(const ASTNode& cond,
- const ASTVec& thn, const ASTVec& els);
- // Build a vector of zeros.
- ASTVec BBfill(unsigned int width, ASTNode fillval);
- // build an EQ formula
- ASTNode BBEQ(const ASTVec& left, const ASTVec& right);
-
- // This implements a variant of binary long division.
- // q and r are "out" parameters. rwidth puts a bound on the
- // recursion depth. Unsigned only, for now.
- void BBDivMod(const ASTVec &y,
- const ASTVec &x,
- ASTVec &q,
- ASTVec &r,
- unsigned int rwidth);
-
- // Return formula for majority function of three formulas.
- ASTNode Majority(const ASTNode& a, const ASTNode& b, const ASTNode& c);
-
- // Internal bit blasting routines.
- ASTNode BBBVLE(const ASTVec& x, const ASTVec& y, bool is_signed);
-
- // Return bit-blasted form for BVLE, BVGE, BVGT, SBLE, etc.
- ASTNode BBcompare(const ASTNode& form);
-
- // Left and right shift one. Writes into x.
- void BBLShift(ASTVec& x);
- void BBRShift(ASTVec& x);
-
- void BBLShift(ASTVec& x, unsigned int shift);
- void BBRShift(ASTVec& x, unsigned int shift);
-
- public:
- // Simplifying create functions
- ASTNode CreateSimpForm(Kind kind, ASTVec &children);
- ASTNode CreateSimpForm(Kind kind, const ASTNode& child0);
- ASTNode CreateSimpForm(Kind kind,
- const ASTNode& child0,
- const ASTNode& child1);
- ASTNode CreateSimpForm(Kind kind,
- const ASTNode& child0,
- const ASTNode& child1,
- const ASTNode& child2);
-
- ASTNode CreateSimpNot(const ASTNode& form);
-
- // These are for internal use only.
- // FIXME: Find a way to make this local to SimpBool, so they're
- // not in AST.h
- ASTNode CreateSimpXor(const ASTNode& form1,
- const ASTNode& form2);
- ASTNode CreateSimpXor(ASTVec &children);
- ASTNode CreateSimpAndOr(bool isAnd,
- const ASTNode& form1,
- const ASTNode& form2);
- ASTNode CreateSimpAndOr(bool IsAnd, ASTVec &children);
- ASTNode CreateSimpFormITE(const ASTNode& child0,
- const ASTNode& child1,
- const ASTNode& child2);
-
-
- // Declarations of BitBlaster functions (BitBlast.cpp)
- public:
- // Adds or removes a NOT as necessary to negate a literal.
- ASTNode Negate(const ASTNode& form);
-
- // Bit blast a bitvector term. The term must have a kind for a
- // bitvector term. Result is a ref to a vector of formula nodes
- // representing the boolean formula.
- const ASTNode BBTerm(const ASTNode& term);
-
- const ASTNode BBForm(const ASTNode& formula);
-
- // Declarations of CNF conversion (ToCNF.cpp)
- public:
- // ToCNF converts a bit-blasted Boolean formula to Conjunctive
- // Normal Form, suitable for many SAT solvers. Our CNF representation
- // is an STL vector of STL vectors, for independence from any particular
- // SAT solver's representation. There needs to be a separate driver to
- // convert our clauselist to the representation used by the SAT solver.
- // Currently, there is only one such solver and its driver is "ToSAT"
-
- // Datatype for clauses
- typedef vector<const ASTNode*>* ClausePtr;
-
- // Datatype for Clauselists
- typedef vector<ClausePtr> ClauseList;
-
- // Convert a Boolean formula to an equisatisfiable CNF formula.
- ClauseList *ToCNF(const ASTNode& form);
-
- // Print function for debugging
- void PrintClauseList(ostream& os, ClauseList& cll);
-
- // Free the clause list and all its clauses.
- void DeleteClauseList(BeevMgr::ClauseList *cllp);
-
- // Map from formulas to representative literals, for debugging.
- ASTNodeMap RepLitMap;
-
- private:
- // Global for assigning new node numbers.
- int _max_node_num;
-
- const ASTNode ASTFalse, ASTTrue, ASTUndefined;
-
- // I just did this so I could put it in as a fake return value in
- // methods that return a ASTNode &, to make -Wall shut up.
- ASTNode dummy_node;
-
- //BeevMgr Constructor, Destructor and other misc. functions
- public:
-
- int NewNodeNum() { _max_node_num += 2; return _max_node_num; }
-
- // Table for DAG printing.
- ASTNodeSet AlreadyPrintedSet;
-
- //Tables for Presentation language printing
-
- //Nodes seen so far
- ASTNodeSet PLPrintNodeSet;
-
- //Map from ASTNodes to LetVars
- ASTNodeMap NodeLetVarMap;
-
- //This is a vector which stores the Node to LetVars pairs. It
- //allows for sorted printing, as opposed to NodeLetVarMap
- std::vector<pair<ASTNode,ASTNode> > NodeLetVarVec;
-
- //a partial Map from ASTNodes to LetVars. Needed in order to
- //correctly print shared subterms inside the LET itself
- ASTNodeMap NodeLetVarMap1;
-
- //functions to lookup nodes from the memo tables. these should be
- //private.
- private:
- //Destructively appends back_child nodes to front_child nodes.
- //If back_child nodes is NULL, no appending is done. back_child
- //nodes are not modified. Then it returns the hashed copy of the
- //node, which is created if necessary.
- ASTInterior *CreateInteriorNode(Kind kind,
- ASTInterior *new_node,
- // this is destructively modified.
- const ASTVec & back_children = _empty_ASTVec);
-
- // Create unique ASTInterior node.
- ASTInterior *LookupOrCreateInterior(ASTInterior *n);
-
- // Create unique ASTSymbol node.
- ASTSymbol *LookupOrCreateSymbol(ASTSymbol& s);
-
- // Called whenever we want to make sure that the Symbol is
- // declared during semantic analysis
- bool LookupSymbol(ASTSymbol& s);
-
- // Called by ASTNode constructors to uniqueify ASTBVConst
- ASTBVConst *LookupOrCreateBVConst(ASTBVConst& s);
-
- //Public functions for CreateNodes and Createterms
- public:
- // Create and return an ASTNode for a symbol
- ASTNode CreateSymbol(const char * const name);
-
- // Create and return an ASTNode for a symbol
- // Width is number of bits.
- ASTNode CreateBVConst(string*& strval, int base, int bit_width);
- ASTNode CreateBVConst(unsigned int width, unsigned long long int bvconst);
- ASTNode CreateZeroConst(unsigned int width);
- ASTNode CreateOneConst(unsigned int width);
- ASTNode CreateTwoConst(unsigned int width);
- ASTNode CreateMaxConst(unsigned int width);
-
-
- // Create and return an ASTNode for a symbol
- // Optional base was a problem because 0 could be an int or char *,
- // so CreateBVConst was ambiguous.
- ASTNode CreateBVConst(const char *strval, int base);
-
- //FIXME This is a dangerous function
- ASTNode CreateBVConst(CBV bv, unsigned width);
-
- // Create and return an interior ASTNode
- ASTNode CreateNode(Kind kind, const ASTVec &children = _empty_ASTVec);
-
- ASTNode CreateNode(Kind kind,
- const ASTNode& child0,
- const ASTVec &children = _empty_ASTVec);
-
- ASTNode CreateNode(Kind kind,
- const ASTNode& child0,
- const ASTNode& child1,
- const ASTVec &children = _empty_ASTVec);
-
- ASTNode CreateNode(Kind kind,
- const ASTNode& child0,
- const ASTNode& child1,
- const ASTNode& child2,
- const ASTVec &children = _empty_ASTVec);
-
- // Create and return an ASTNode for a term
- inline ASTNode CreateTerm(Kind kind,
- unsigned int width,
- const ASTVec &children = _empty_ASTVec) {
- if(!is_Term_kind(kind))
- FatalError("CreateTerm: Illegal kind to CreateTerm:",ASTUndefined, kind);
- ASTNode n = CreateNode(kind, children);
- n.SetValueWidth(width);
-
- //by default we assume that the term is a Bitvector. If
- //necessary the indexwidth can be changed later
- n.SetIndexWidth(0);
- return n;
- }
-
- inline ASTNode CreateTerm(Kind kind,
- unsigned int width,
- const ASTNode& child0,
- const ASTVec &children = _empty_ASTVec) {
- if(!is_Term_kind(kind))
- FatalError("CreateTerm: Illegal kind to CreateTerm:",ASTUndefined, kind);
- ASTNode n = CreateNode(kind, child0, children);
- n.SetValueWidth(width);
- return n;
- }
-
- inline ASTNode CreateTerm(Kind kind,
- unsigned int width,
- const ASTNode& child0,
- const ASTNode& child1,
- const ASTVec &children = _empty_ASTVec) {
- if(!is_Term_kind(kind))
- FatalError("CreateTerm: Illegal kind to CreateTerm:",ASTUndefined, kind);
- ASTNode n = CreateNode(kind, child0, child1, children);
- n.SetValueWidth(width);
- return n;
- }
-
- inline ASTNode CreateTerm(Kind kind,
- unsigned int width,
- const ASTNode& child0,
- const ASTNode& child1,
- const ASTNode& child2,
- const ASTVec &children = _empty_ASTVec) {
- if(!is_Term_kind(kind))
- FatalError("CreateTerm: Illegal kind to CreateTerm:",ASTUndefined, kind);
- ASTNode n = CreateNode(kind, child0, child1, child2, children);
- n.SetValueWidth(width);
- return n;
- }
-
- ASTNode SimplifyFormula_NoRemoveWrites(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyFormula_TopLevel(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyFormula(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyTerm_TopLevel(const ASTNode& b);
- ASTNode SimplifyTerm(const ASTNode& a);
- ASTNode SimplifyTermAux(const ASTNode& a);
- void CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output);
- private:
- //memo table for simplifcation
- ASTNodeMap *SimplifyMap;
- ASTNodeMap *SimplifyNegMap;
- ASTNodeMap SolverMap;
- ASTNodeSet AlwaysTrueFormMap;
- ASTNodeMap MultInverseMap;
-
- public:
- ASTNode SimplifyAtomicFormula(const ASTNode& a, bool pushNeg);
- ASTNode CreateSimplifiedEQ(const ASTNode& t1, const ASTNode& t2);
- ASTNode ITEOpt_InEqs(const ASTNode& in1);
- ASTNode CreateSimplifiedTermITE(const ASTNode& t1, const ASTNode& t2, const ASTNode& t3);
- ASTNode CreateSimplifiedFormulaITE(const ASTNode& in0, const ASTNode& in1, const ASTNode& in2);
- ASTNode CreateSimplifiedINEQ(Kind k, const ASTNode& a0, const ASTNode& a1, bool pushNeg);
- ASTNode SimplifyNotFormula(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyAndOrFormula(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyXorFormula(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyNandFormula(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyNorFormula(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyImpliesFormula(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyIffFormula(const ASTNode& a, bool pushNeg);
- ASTNode SimplifyIteFormula(const ASTNode& a, bool pushNeg);
- ASTNode FlattenOneLevel(const ASTNode& a);
- ASTNode FlattenAndOr(const ASTNode& a);
- ASTNode CombineLikeTerms(const ASTNode& a);
- ASTNode LhsMinusRhs(const ASTNode& eq);
- ASTNode DistributeMultOverPlus(const ASTNode& a,
- bool startdistribution=false);
- ASTNode ConvertBVSXToITE(const ASTNode& a);
- //checks if the input constant is odd or not
- bool BVConstIsOdd(const ASTNode& c);
- //computes the multiplicatve inverse of the input
- ASTNode MultiplicativeInverse(const ASTNode& c);
-
- void ClearAllTables(void);
- void ClearAllCaches(void);
- int BeforeSAT_ResultCheck(const ASTNode& q);
- int CallSAT_ResultCheck(MINISAT::Solver& newS,
- const ASTNode& q, const ASTNode& orig_input);
- int SATBased_ArrayReadRefinement(MINISAT::Solver& newS,
- const ASTNode& q, const ASTNode& orig_input);
- int SATBased_ArrayWriteRefinement(MINISAT::Solver& newS, const ASTNode& orig_input);
- //creates array write axiom only for the input term or formula, if
- //necessary. If there are no axioms to produce then it simply
- //generates TRUE
- ASTNode Create_ArrayWriteAxioms(const ASTNode& array_readoverwrite_term, const ASTNode& array_newname);
- ASTVec ArrayWrite_RemainingAxioms;
- //variable indicates that counterexample will now be checked by
- //the counterexample checker, and hence simplifyterm must switch
- //off certain optimizations. In particular, array write
- //optimizations
- bool start_abstracting;
- bool Begin_RemoveWrites;
- bool SimplifyWrites_InPlace_Flag;
-
- void CopySolverMap_To_CounterExample(void);
- //int LinearSearch(const ASTNode& orig_input);
- //Datastructures and functions needed for counterexample
- //generation, and interface with MINISAT
- private:
- /* MAP: This is a map from ASTNodes to MINISAT::Vars.
- *
- * The map is populated while ASTclauses are read from the AST
- * ClauseList returned by CNF converter. For every new boolean
- * variable in ASTClause a new MINISAT::Var is created (these vars
- * typedefs for ints)
- */
- typedef hash_map<ASTNode, MINISAT::Var,
- ASTNode::ASTNodeHasher,
- ASTNode::ASTNodeEqual> ASTtoSATMap;
- ASTtoSATMap _ASTNode_to_SATVar;
-
-
- public:
- //converts the clause to SAT and calls SAT solver
- bool toSATandSolve(MINISAT::Solver& S, ClauseList& cll);
-
- ///print SAT solver statistics
- void PrintStats(MINISAT::Solver& stats);
-
- //from v8
- int TopLevelSATAux(const ASTNode& query);
-
- //##################################################
- //##################################################
-
- //accepts query and returns the answer. if query is valid, return
- //true, else return false. Automatically constructs counterexample
- //for invalid queries, and prints them upon request.
- int TopLevelSAT(const ASTNode& query, const ASTNode& asserts);
-
- // Debugging function to find problems in BitBlast and ToCNF.
- // See body in ToSAT.cpp for more explanation.
- ASTNode CheckBBandCNF(MINISAT::Solver& newS, ASTNode form);
-
- // Internal recursive body of above.
- ASTNode CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form);
-
- // Helper function for CheckBBandCNF
- ASTNode SymbolTruthValue(MINISAT::Solver &newS, ASTNode form);
-
- //looksup a MINISAT var from the minisat-var memo-table. if none
- //exists, then creates one.
- const MINISAT::Var LookupOrCreateSATVar(MINISAT::Solver& S, const ASTNode& n);
-
- // Memo table for CheckBBandCNF debugging function
- ASTNodeMap CheckBBandCNFMemo;
-
-
- //Data structures for Array Read Transformations
- private:
- /* MAP: This is a map from Array Names to list of array-read
- * indices in the input. This map is used by the TransformArray()
- * function
- *
- * This map is useful in converting array reads into nested ITE
- * constructs. Suppose there are two array reads in the input
- * Read(A,i) and Read(A,j). Then Read(A,i) is replaced with a
- * symbolic constant, say v1, and Read(A,j) is replaced with the
- * following ITE:
- *
- * ITE(i=j,v1,v2)
- */
- //CAUTION: I tried using a set instead of vector for
- //readindicies. for some odd reason the performance went down
- //considerably. this is totally inexplicable.
- ASTNodeToVecMap _arrayname_readindices;
-
- /* MAP: This is a map from Array Names to nested ITE constructs,
- * which are built as described below. This map is used by the
- * TransformArray() function
- *
- * This map is useful in converting array reads into nested ITE
- * constructs. Suppose there are two array reads in the input
- * Read(A,i) and Read(A,j). Then Read(A,i) is replaced with a
- * symbolic constant, say v1, and Read(A,j) is replaced with the
- * following ITE:
- *
- * ITE(i=j,v1,v2)
- */
- ASTNodeMap _arrayread_ite;
-
- /*MAP: This is a map from array-reads to symbolic constants. This
- *map is used by the TransformArray()
- */
- ASTNodeMap _arrayread_symbol;
-
- ASTNodeSet _introduced_symbols;
-
- /*Memoization map for TransformFormula/TransformTerm/TransformArray function
- */
- ASTNodeMap TransformMap;
-
- //count to keep track of new symbolic constants introduced
- //corresponding to Array Reads
- unsigned int _symbol_count;
-
- //Formula/Term Transformers. Let Expr Manager, Type Checker
- public:
- //Functions that Transform ASTNodes
- ASTNode TransformFormula(const ASTNode& query);
- ASTNode TransformTerm(const ASTNode& term);
- ASTNode TransformArray(const ASTNode& term);
- ASTNode TranslateSignedDivMod(const ASTNode& term);
-
- //LET Management
- private:
- // MAP: This map is from bound IDs that occur in LETs to
- // expression. The map is useful in checking replacing the IDs
- // with the corresponding expressions.
- ASTNodeMap *_letid_expr_map;
- public:
-
- ASTNode ResolveID(const ASTNode& var);
-
- //Functions that are used to manage LET expressions
- void LetExprMgr(const ASTNode& var, const ASTNode& letExpr);
-
- //Delete Letid Map
- void CleanupLetIDMap(void);
-
- //Allocate LetID map
- void InitializeLetIDMap(void);
-
- //Substitute Let-vars with LetExprs
- ASTNode SubstituteLetExpr(ASTNode inExpr);
-
- /* MAP: This is a map from MINISAT::Vars to ASTNodes
- *
- * This is a reverse map, useful in constructing
- * counterexamples. MINISAT returns a model in terms of MINISAT
- * Vars, and this map helps us convert it to a model over ASTNode
- * variables.
- */
- vector<ASTNode> _SATVar_to_AST;
-
- private:
- /* MAP: This is a map from ASTNodes to vectors of bits
- *
- * This map is used in constructing and printing
- * counterexamples. MINISAT returns values for each bit (a
- * BVGETBIT Node), and this maps allows us to assemble the bits
- * into bitvectors.
- */
- typedef hash_map<ASTNode, hash_map<unsigned int, bool> *,
- ASTNode::ASTNodeHasher,
- ASTNode::ASTNodeEqual> ASTtoBitvectorMap;
- ASTtoBitvectorMap _ASTNode_to_Bitvector;
-
- //Data structure that holds the counter-model
- ASTNodeMap CounterExampleMap;
-
- //Checks if the counter_example is ok. In order for the
- //counter_example to be ok, Every assert must evaluate to true
- //w.r.t couner_example and the query must evaluate to
- //false. Otherwise the counter_example is bogus.
- void CheckCounterExample(bool t);
-
- //Converts a vector of bools to a BVConst
- ASTNode BoolVectoBVConst(hash_map<unsigned,bool> * w, unsigned int l);
-
- //accepts a term and turns it into a constant-term w.r.t counter_example
- ASTNode TermToConstTermUsingModel(const ASTNode& term, bool ArrayReadFlag = true);
- ASTNode Expand_ReadOverWrite_UsingModel(const ASTNode& term, bool ArrayReadFlag = true);
- //Computes the truth value of a formula w.r.t counter_example
- ASTNode ComputeFormulaUsingModel(const ASTNode& form);
-
- //Replaces WRITE(Arr,i,val) with ITE(j=i, val, READ(Arr,j))
- ASTNode RemoveWrites_TopLevel(const ASTNode& term);
- ASTNode RemoveWrites(const ASTNode& term);
- ASTNode SimplifyWrites_InPlace(const ASTNode& term);
- ASTNode ReadOverWrite_To_ITE(const ASTNode& term);
-
- ASTNode NewArrayVar(unsigned int index, unsigned int value);
- ASTNode NewVar(unsigned int valuewidth);
- //For ArrayWrite Abstraction: map from read-over-write term to
- //newname.
- ASTNodeMap ReadOverWrite_NewName_Map;
- //For ArrayWrite Refinement: Map new arraynames to Read-Over-Write
- //terms
- ASTNodeMap NewName_ReadOverWrite_Map;
-
- public:
- //print the STP solver output
- void PrintOutput(bool true_iff_valid);
-
- //Converts MINISAT counterexample into an AST memotable (i.e. the
- //function populates the datastructure CounterExampleMap)
- void ConstructCounterExample(MINISAT::Solver& S);
-
- //Prints the counterexample to stdout
- void PrintCounterExample(bool t,std::ostream& os=cout);
-
- //Prints the counterexample to stdout
- void PrintCounterExample_InOrder(bool t);
-
- //queries the counterexample, and returns the value corresponding
- //to e
- ASTNode GetCounterExample(bool t, const ASTNode& e);
-
- int CounterExampleSize(void) const {return CounterExampleMap.size();}
-
- //FIXME: This is bloody dangerous function. Hack attack to take
- //care of requests from users who want to store complete
- //counter-examples in their own data structures.
- ASTNodeMap GetCompleteCounterExample() {return CounterExampleMap;}
-
- // prints MINISAT assigment one bit at a time, for debugging.
- void PrintSATModel(MINISAT::Solver& S);
-
- //accepts constant input and normalizes it.
- ASTNode BVConstEvaluator(const ASTNode& t);
-
- //FUNCTION 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
- void BVTypeCheck(const ASTNode& n);
-
- private:
- //stack of Logical Context. each entry in the stack is a logical
- //context. A logical context is a vector of assertions. The
- //logical context is represented by a ptr to a vector of
- //assertions in that logical context. Logical contexts are created
- //by PUSH/POP
- std::vector<ASTVec *> _asserts;
- //The query for the current logical context.
- ASTNode _current_query;
-
- //this flag, when true, indicates that counterexample is being
- //checked by the counterexample checker
- bool counterexample_checking_during_refinement;
-
- //this flag indicates as to whether the input has been determined to
- //be valid or not by this tool
- bool ValidFlag;
-
- //this flag, when true, indicates that a BVDIV divide by zero
- //exception occured. However, the program must not exit with a
- //fatalerror. Instead, it should evaluate the whole formula (which
- //contains the BVDIV term) to be FALSE.
- bool bvdiv_exception_occured;
-
- public:
- //set of functions that manipulate Logical Contexts.
- //
- //add an assertion to the current logical context
- void AddAssert(const ASTNode& assert);
- void Push(void);
- void Pop(void);
- void AddQuery(const ASTNode& q);
- const ASTNode PopQuery();
- const ASTNode GetQuery();
- const ASTVec GetAsserts(void);
-
- //reports node size. Second arg is "clearstatinfo", whatever that is.
- unsigned int NodeSize(const ASTNode& a, bool t = false);
-
- private:
- //This memo map is used by the ComputeFormulaUsingModel()
- ASTNodeMap ComputeFormulaMap;
- //Map for statiscal purposes
- ASTNodeSet StatInfoSet;
-
-
- ASTNodeMap TermsAlreadySeenMap;
- ASTNode CreateSubstitutionMap(const ASTNode& a);
- public:
- //prints statistics for the ASTNode. can add a prefix string c
- void ASTNodeStats(const char * c, const ASTNode& a);
-
- //substitution
- bool CheckSubstitutionMap(const ASTNode& a, ASTNode& output);
- bool CheckSubstitutionMap(const ASTNode& a);
- bool UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1);
- //if (a > b) in the termorder, then return 1
- //elseif (a < b) in the termorder, then return -1
- //else return 0
- int TermOrder(const ASTNode& a, const ASTNode& b);
- //fill the arrayname_readindices vector if e0 is a READ(Arr,index)
- //and index is a BVCONST
- void FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1);
- bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
-
- //functions for checking and updating simplifcation map
- bool CheckSimplifyMap(const ASTNode& key, ASTNode& output, bool pushNeg);
- void UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg);
- void ResetSimplifyMaps();
- bool CheckAlwaysTrueFormMap(const ASTNode& key);
- void UpdateAlwaysTrueFormMap(const ASTNode& val);
- bool CheckMultInverseMap(const ASTNode& key, ASTNode& output);
- void UpdateMultInverseMap(const ASTNode& key, const ASTNode& value);
-
- //Map for solved variables
- bool CheckSolverMap(const ASTNode& a, ASTNode& output);
- bool CheckSolverMap(const ASTNode& a);
- bool UpdateSolverMap(const ASTNode& e0, const ASTNode& e1);
-
- public:
- //FIXME: HACK_ATTACK. this vector was hacked into the code to
- //support a special request by Dawson' group. They want the
- //counterexample to be printed in the order of variables declared.
- //TO BE COMMENTED LATER (say by 1st week of march,2006)
- ASTVec _special_print_set;
-
-
- //prints the initial activity levels of variables
- //void PrintActivityLevels_Of_SATVars(char * init_msg, MINISAT::Solver& newS);
-
- //this function biases the activity levels of MINISAT variables.
- //void ChangeActivityLevels_Of_SATVars(MINISAT::Solver& n);
-
- // Constructor
- BeevMgr() : _interior_unique_table(INITIAL_INTERIOR_UNIQUE_TABLE_SIZE),
- _symbol_unique_table(INITIAL_SYMBOL_UNIQUE_TABLE_SIZE),
- _bvconst_unique_table(INITIAL_BVCONST_UNIQUE_TABLE_SIZE),
- BBTermMemo(INITIAL_BBTERM_MEMO_TABLE_SIZE),
- BBFormMemo(INITIAL_BBFORM_MEMO_TABLE_SIZE),
- _max_node_num(0),
- ASTFalse(CreateNode(FALSE)),
- ASTTrue(CreateNode(TRUE)),
- ASTUndefined(CreateNode(UNDEFINED)),
- SolverMap(INITIAL_SOLVER_MAP_SIZE),
- _arrayread_symbol(INITIAL_ARRAYREAD_SYMBOL_SIZE),
- _introduced_symbols(INITIAL_INTRODUCED_SYMBOLS_SIZE),
- _symbol_count(0) {
- _current_query = ASTUndefined;
- ValidFlag = false;
- bvdiv_exception_occured = false;
- counterexample_checking_during_refinement = false;
- start_abstracting = false;
- Begin_RemoveWrites = false;
- SimplifyWrites_InPlace_Flag = false;
- SimplifyMap = new ASTNodeMap(INITIAL_SIMPLIFY_MAP_SIZE);
- SimplifyNegMap = new ASTNodeMap(INITIAL_SIMPLIFY_MAP_SIZE);
- _letid_expr_map = new ASTNodeMap(INITIAL_INTRODUCED_SYMBOLS_SIZE);
- };
-
- //destructor
- ~BeevMgr();
- }; //End of Class BeevMgr
-
-
- class CompleteCounterExample {
- ASTNodeMap counterexample;
- BeevMgr * bv;
- public:
- CompleteCounterExample(ASTNodeMap a, BeevMgr* beev) : counterexample(a), bv(beev){}
- ASTNode GetCounterExample(ASTNode e) {
- if(BOOLEAN_TYPE == e.GetType() && SYMBOL != e.GetKind()) {
- FatalError("You must input a term or propositional variables\n",e);
- }
- if(counterexample.find(e) != counterexample.end()) {
- return counterexample[e];
- }
- else {
- if(SYMBOL == e.GetKind() && BOOLEAN_TYPE == e.GetType()) {
- return bv->CreateNode(BEEV::FALSE);
+private:
+ // Typedef for unique Interior node table.
+ typedef hash_set<ASTInterior *, ASTInterior::ASTInteriorHasher, ASTInterior::ASTInteriorEqual> ASTInteriorSet;
+
+ // Typedef for unique Symbol node (leaf) table.
+ typedef hash_set<ASTSymbol *, ASTSymbol::ASTSymbolHasher, ASTSymbol::ASTSymbolEqual> ASTSymbolSet;
+
+ // Unique tables to share nodes whenever possible.
+ ASTInteriorSet _interior_unique_table;
+ //The _symbol_unique_table is also the symbol table to be used
+ //during parsing/semantic analysis
+ ASTSymbolSet _symbol_unique_table;
+
+ //Typedef for unique BVConst node (leaf) table.
+ typedef hash_set<ASTBVConst *, ASTBVConst::ASTBVConstHasher, ASTBVConst::ASTBVConstEqual> ASTBVConstSet;
+
+ //table to uniquefy bvconst
+ ASTBVConstSet _bvconst_unique_table;
+
+ // type of memo table.
+ typedef hash_map<ASTNode, ASTVec, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTNodeToVecMap;
+
+ typedef hash_map<ASTNode, ASTNodeSet, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTNodeToSetMap;
+
+ // Memo table for bit blasted terms. If a node has already been
+ // bitblasted, it is mapped to a vector of Boolean formulas for
+ // the bits.
+
+ //OLD: ASTNodeToVecMap BBTermMemo;
+ ASTNodeMap BBTermMemo;
+
+ // Memo table for bit blasted formulas. If a node has already
+ // been bitblasted, it is mapped to a node representing the
+ // bitblasted equivalent
+ ASTNodeMap BBFormMemo;
+
+ //public:
+ // Get vector of Boolean formulas for sum of two
+ // vectors of Boolean formulas
+ void BBPlus2(ASTVec& sum, const ASTVec& y, ASTNode cin);
+ // Increment
+ ASTVec BBInc(ASTVec& x);
+ // Add one bit to a vector of bits.
+ ASTVec BBAddOneBit(ASTVec& x, ASTNode cin);
+ // Bitwise complement
+ ASTVec BBNeg(const ASTVec& x);
+ // Unary minus
+ ASTVec BBUminus(const ASTVec& x);
+ // Multiply.
+ ASTVec BBMult(const ASTVec& x, const ASTVec& y);
+ // AND each bit of vector y with single bit b and return the result.
+ // (used in BBMult)
+ ASTVec BBAndBit(const ASTVec& y, ASTNode b);
+ // Returns ASTVec for result - y. This destroys "result".
+ void BBSub(ASTVec& result, const ASTVec& y);
+ // build ITE's (ITE cond then[i] else[i]) for each i.
+ ASTVec BBITE(const ASTNode& cond, const ASTVec& thn, const ASTVec& els);
+ // Build a vector of zeros.
+ ASTVec BBfill(unsigned int width, ASTNode fillval);
+ // build an EQ formula
+ ASTNode BBEQ(const ASTVec& left, const ASTVec& right);
+
+ // This implements a variant of binary long division.
+ // q and r are "out" parameters. rwidth puts a bound on the
+ // recursion depth. Unsigned only, for now.
+ void BBDivMod(const ASTVec &y, const ASTVec &x, ASTVec &q, ASTVec &r, unsigned int rwidth);
+
+ // Return formula for majority function of three formulas.
+ ASTNode Majority(const ASTNode& a, const ASTNode& b, const ASTNode& c);
+
+ // Internal bit blasting routines.
+ ASTNode BBBVLE(const ASTVec& x, const ASTVec& y, bool is_signed);
+
+ // Return bit-blasted form for BVLE, BVGE, BVGT, SBLE, etc.
+ ASTNode BBcompare(const ASTNode& form);
+
+ // Left and right shift one. Writes into x.
+ void BBLShift(ASTVec& x);
+ void BBRShift(ASTVec& x);
+
+ void BBLShift(ASTVec& x, unsigned int shift);
+ void BBRShift(ASTVec& x, unsigned int shift);
+
+public:
+ // Simplifying create functions
+ ASTNode CreateSimpForm(Kind kind, ASTVec &children);
+ ASTNode CreateSimpForm(Kind kind, const ASTNode& child0);
+ ASTNode CreateSimpForm(Kind kind, const ASTNode& child0, const ASTNode& child1);
+ ASTNode CreateSimpForm(Kind kind, const ASTNode& child0, const ASTNode& child1, const ASTNode& child2);
+
+ ASTNode CreateSimpNot(const ASTNode& form);
+
+ // These are for internal use only.
+ // FIXME: Find a way to make this local to SimpBool, so they're
+ // not in AST.h
+ ASTNode CreateSimpXor(const ASTNode& form1, const ASTNode& form2);
+ ASTNode CreateSimpXor(ASTVec &children);
+ ASTNode CreateSimpAndOr(bool isAnd, const ASTNode& form1, const ASTNode& form2);
+ ASTNode CreateSimpAndOr(bool IsAnd, ASTVec &children);
+ ASTNode CreateSimpFormITE(const ASTNode& child0, const ASTNode& child1, const ASTNode& child2);
+
+ // Declarations of BitBlaster functions (BitBlast.cpp)
+public:
+ // Adds or removes a NOT as necessary to negate a literal.
+ ASTNode Negate(const ASTNode& form);
+
+ // Bit blast a bitvector term. The term must have a kind for a
+ // bitvector term. Result is a ref to a vector of formula nodes
+ // representing the boolean formula.
+ const ASTNode BBTerm(const ASTNode& term);
+
+ const ASTNode BBForm(const ASTNode& formula);
+
+ // Declarations of CNF conversion (ToCNF.cpp)
+public:
+ // ToCNF converts a bit-blasted Boolean formula to Conjunctive
+ // Normal Form, suitable for many SAT solvers. Our CNF representation
+ // is an STL vector of STL vectors, for independence from any particular
+ // SAT solver's representation. There needs to be a separate driver to
+ // convert our clauselist to the representation used by the SAT solver.
+ // Currently, there is only one such solver and its driver is "ToSAT"
+
+ // Datatype for clauses
+ typedef vector<const ASTNode*>* ClausePtr;
+
+ // Datatype for Clauselists
+ typedef vector<ClausePtr> ClauseList;
+
+ // Convert a Boolean formula to an equisatisfiable CNF formula.
+ ClauseList *ToCNF(const ASTNode& form);
+
+ // Print function for debugging
+ void PrintClauseList(ostream& os, ClauseList& cll);
+
+ // Free the clause list and all its clauses.
+ void DeleteClauseList(BeevMgr::ClauseList *cllp);
+
+ // Map from formulas to representative literals, for debugging.
+ ASTNodeMap RepLitMap;
+
+private:
+ // Global for assigning new node numbers.
+ int _max_node_num;
+
+ const ASTNode ASTFalse, ASTTrue, ASTUndefined;
+
+ // I just did this so I could put it in as a fake return value in
+ // methods that return a ASTNode &, to make -Wall shut up.
+ ASTNode dummy_node;
+
+ //BeevMgr Constructor, Destructor and other misc. functions
+public:
+
+ int NewNodeNum()
+ {
+ _max_node_num += 2;
+ return _max_node_num;
}
- if(SYMBOL == e.GetKind()) {
- ASTNode z = bv->CreateZeroConst(e.GetValueWidth());
- return z;
+ // Table for DAG printing.
+ ASTNodeSet AlreadyPrintedSet;
+
+ //Tables for Presentation language printing
+
+ //Nodes seen so far
+ ASTNodeSet PLPrintNodeSet;
+
+ //Map from ASTNodes to LetVars
+ ASTNodeMap NodeLetVarMap;
+
+ //This is a vector which stores the Node to LetVars pairs. It
+ //allows for sorted printing, as opposed to NodeLetVarMap
+ std::vector<pair<ASTNode, ASTNode> > NodeLetVarVec;
+
+ //a partial Map from ASTNodes to LetVars. Needed in order to
+ //correctly print shared subterms inside the LET itself
+ ASTNodeMap NodeLetVarMap1;
+
+ //functions to lookup nodes from the memo tables. these should be
+ //private.
+private:
+ //Destructively appends back_child nodes to front_child nodes.
+ //If back_child nodes is NULL, no appending is done. back_child
+ //nodes are not modified. Then it returns the hashed copy of the
+ //node, which is created if necessary.
+ ASTInterior *CreateInteriorNode(Kind kind, ASTInterior *new_node,
+ // this is destructively modified.
+ const ASTVec & back_children = _empty_ASTVec);
+
+ // Create unique ASTInterior node.
+ ASTInterior *LookupOrCreateInterior(ASTInterior *n);
+
+ // Create unique ASTSymbol node.
+ ASTSymbol *LookupOrCreateSymbol(ASTSymbol& s);
+
+ // Called whenever we want to make sure that the Symbol is
+ // declared during semantic analysis
+ bool LookupSymbol(ASTSymbol& s);
+
+ // Called by ASTNode constructors to uniqueify ASTBVConst
+ ASTBVConst *LookupOrCreateBVConst(ASTBVConst& s);
+
+ //Public functions for CreateNodes and Createterms
+public:
+ // Create and return an ASTNode for a symbol
+ ASTNode CreateSymbol(const char * const name);
+
+ // Create and return an ASTNode for a symbol
+ // Width is number of bits.
+ ASTNode CreateBVConst(string*& strval, int base, int bit_width);
+ ASTNode CreateBVConst(unsigned int width, unsigned long long int bvconst);
+ ASTNode CreateZeroConst(unsigned int width);
+ ASTNode CreateOneConst(unsigned int width);
+ ASTNode CreateTwoConst(unsigned int width);
+ ASTNode CreateMaxConst(unsigned int width);
+
+ // Create and return an ASTNode for a symbol
+ // Optional base was a problem because 0 could be an int or char *,
+ // so CreateBVConst was ambiguous.
+ ASTNode CreateBVConst(const char *strval, int base);
+
+ //FIXME This is a dangerous function
+ ASTNode CreateBVConst(CBV bv, unsigned width);
+
+ // Create and return an interior ASTNode
+ ASTNode CreateNode(Kind kind, const ASTVec &children = _empty_ASTVec);
+
+ ASTNode CreateNode(Kind kind, const ASTNode& child0, const ASTVec &children = _empty_ASTVec);
+
+ ASTNode CreateNode(Kind kind, const ASTNode& child0, const ASTNode& child1, const ASTVec &children = _empty_ASTVec);
+
+ ASTNode CreateNode(Kind kind, const ASTNode& child0, const ASTNode& child1, const ASTNode& child2, const ASTVec &children = _empty_ASTVec);
+
+ // Create and return an ASTNode for a term
+ inline ASTNode CreateTerm(Kind kind, unsigned int width, const ASTVec &children = _empty_ASTVec)
+ {
+ if (!is_Term_kind(kind))
+ FatalError("CreateTerm: Illegal kind to CreateTerm:", ASTUndefined, kind);
+ ASTNode n = CreateNode(kind, children);
+ n.SetValueWidth(width);
+
+ //by default we assume that the term is a Bitvector. If
+ //necessary the indexwidth can be changed later
+ n.SetIndexWidth(0);
+ return n;
+ }
+
+ inline ASTNode CreateTerm(Kind kind, unsigned int width, const ASTNode& child0, const ASTVec &children = _empty_ASTVec)
+ {
+ if (!is_Term_kind(kind))
+ FatalError("CreateTerm: Illegal kind to CreateTerm:", ASTUndefined, kind);
+ ASTNode n = CreateNode(kind, child0, children);
+ n.SetValueWidth(width);
+ return n;
+ }
+
+ inline ASTNode CreateTerm(Kind kind, unsigned int width, const ASTNode& child0, const ASTNode& child1, const ASTVec &children = _empty_ASTVec)
+ {
+ if (!is_Term_kind(kind))
+ FatalError("CreateTerm: Illegal kind to CreateTerm:", ASTUndefined, kind);
+ ASTNode n = CreateNode(kind, child0, child1, children);
+ n.SetValueWidth(width);
+ return n;
+ }
+
+ inline ASTNode CreateTerm(Kind kind,
+ unsigned int width,
+ const ASTNode& child0,
+ const ASTNode& child1,
+ const ASTNode& child2,
+ const ASTVec &children = _empty_ASTVec)
+ {
+ if (!is_Term_kind(kind))
+ FatalError("CreateTerm: Illegal kind to CreateTerm:", ASTUndefined, kind);
+ ASTNode n = CreateNode(kind, child0, child1, child2, children);
+ n.SetValueWidth(width);
+ return n;
}
- return e;
- }
- }
- };
+ ASTNode SimplifyFormula_NoRemoveWrites(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyFormula_TopLevel(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyFormula(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyTerm_TopLevel(const ASTNode& b);
+ ASTNode SimplifyTerm(const ASTNode& a);
+ ASTNode SimplifyTermAux(const ASTNode& a);
+ void CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output);
+private:
+ //memo table for simplifcation
+ ASTNodeMap *SimplifyMap;
+ ASTNodeMap *SimplifyNegMap;
+ ASTNodeMap SolverMap;
+ ASTNodeSet AlwaysTrueFormMap;
+ ASTNodeMap MultInverseMap;
+
+public:
+ ASTNode SimplifyAtomicFormula(const ASTNode& a, bool pushNeg);
+ ASTNode CreateSimplifiedEQ(const ASTNode& t1, const ASTNode& t2);
+ ASTNode ITEOpt_InEqs(const ASTNode& in1);
+ ASTNode CreateSimplifiedTermITE(const ASTNode& t1, const ASTNode& t2, const ASTNode& t3);
+ ASTNode CreateSimplifiedFormulaITE(const ASTNode& in0, const ASTNode& in1, const ASTNode& in2);
+ ASTNode CreateSimplifiedINEQ(Kind k, const ASTNode& a0, const ASTNode& a1, bool pushNeg);
+ ASTNode SimplifyNotFormula(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyAndOrFormula(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyXorFormula(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyNandFormula(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyNorFormula(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyImpliesFormula(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyIffFormula(const ASTNode& a, bool pushNeg);
+ ASTNode SimplifyIteFormula(const ASTNode& a, bool pushNeg);
+ ASTNode FlattenOneLevel(const ASTNode& a);
+ ASTNode FlattenAndOr(const ASTNode& a);
+ ASTNode CombineLikeTerms(const ASTNode& a);
+ ASTNode LhsMinusRhs(const ASTNode& eq);
+ ASTNode DistributeMultOverPlus(const ASTNode& a, bool startdistribution = false);
+ ASTNode ConvertBVSXToITE(const ASTNode& a);
+ //checks if the input constant is odd or not
+ bool BVConstIsOdd(const ASTNode& c);
+ //computes the multiplicatve inverse of the input
+ ASTNode MultiplicativeInverse(const ASTNode& c);
+
+ void ClearAllTables(void);
+ void ClearAllCaches(void);
+ int BeforeSAT_ResultCheck(const ASTNode& q);
+ int CallSAT_ResultCheck(MINISAT::Solver& newS, const ASTNode& q, const ASTNode& orig_input);
+ int SATBased_ArrayReadRefinement(MINISAT::Solver& newS, const ASTNode& q, const ASTNode& orig_input);
+ int SATBased_ArrayWriteRefinement(MINISAT::Solver& newS, const ASTNode& orig_input);
+ //creates array write axiom only for the input term or formula, if
+ //necessary. If there are no axioms to produce then it simply
+ //generates TRUE
+ ASTNode Create_ArrayWriteAxioms(const ASTNode& array_readoverwrite_term, const ASTNode& array_newname);
+ ASTVec ArrayWrite_RemainingAxioms;
+ //variable indicates that counterexample will now be checked by
+ //the counterexample checker, and hence simplifyterm must switch
+ //off certain optimizations. In particular, array write
+ //optimizations
+ bool start_abstracting;
+ bool Begin_RemoveWrites;
+ bool SimplifyWrites_InPlace_Flag;
+
+ void CopySolverMap_To_CounterExample(void);
+ //int LinearSearch(const ASTNode& orig_input);
+ //Datastructures and functions needed for counterexample
+ //generation, and interface with MINISAT
+private:
+ /* MAP: This is a map from ASTNodes to MINISAT::Vars.
+ *
+ * The map is populated while ASTclauses are read from the AST
+ * ClauseList returned by CNF converter. For every new boolean
+ * variable in ASTClause a new MINISAT::Var is created (these vars
+ * typedefs for ints)
+ */
+ typedef hash_map<ASTNode, MINISAT::Var, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTtoSATMap;
+ ASTtoSATMap _ASTNode_to_SATVar;
+
+public:
+ //converts the clause to SAT and calls SAT solver
+ bool toSATandSolve(MINISAT::Solver& S, ClauseList& cll);
+
+ ///print SAT solver statistics
+ void PrintStats(MINISAT::Solver& stats);
+
+ //from v8
+ int TopLevelSATAux(const ASTNode& query);
+
+ //##################################################
+ //##################################################
+
+ //accepts query and returns the answer. if query is valid, return
+ //true, else return false. Automatically constructs counterexample
+ //for invalid queries, and prints them upon request.
+ int TopLevelSAT(const ASTNode& query, const ASTNode& asserts);
+
+ // Debugging function to find problems in BitBlast and ToCNF.
+ // See body in ToSAT.cpp for more explanation.
+ ASTNode CheckBBandCNF(MINISAT::Solver& newS, ASTNode form);
+
+ // Internal recursive body of above.
+ ASTNode CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form);
+
+ // Helper function for CheckBBandCNF
+ ASTNode SymbolTruthValue(MINISAT::Solver &newS, ASTNode form);
+
+ //looksup a MINISAT var from the minisat-var memo-table. if none
+ //exists, then creates one.
+ const MINISAT::Var LookupOrCreateSATVar(MINISAT::Solver& S, const ASTNode& n);
+
+ // Memo table for CheckBBandCNF debugging function
+ ASTNodeMap CheckBBandCNFMemo;
+
+ //Data structures for Array Read Transformations
+private:
+ /* MAP: This is a map from Array Names to list of array-read
+ * indices in the input. This map is used by the TransformArray()
+ * function
+ *
+ * This map is useful in converting array reads into nested ITE
+ * constructs. Suppose there are two array reads in the input
+ * Read(A,i) and Read(A,j). Then Read(A,i) is replaced with a
+ * symbolic constant, say v1, and Read(A,j) is replaced with the
+ * following ITE:
+ *
+ * ITE(i=j,v1,v2)
+ */
+ //CAUTION: I tried using a set instead of vector for
+ //readindicies. for some odd reason the performance went down
+ //considerably. this is totally inexplicable.
+ ASTNodeToVecMap _arrayname_readindices;
+
+ /* MAP: This is a map from Array Names to nested ITE constructs,
+ * which are built as described below. This map is used by the
+ * TransformArray() function
+ *
+ * This map is useful in converting array reads into nested ITE
+ * constructs. Suppose there are two array reads in the input
+ * Read(A,i) and Read(A,j). Then Read(A,i) is replaced with a
+ * symbolic constant, say v1, and Read(A,j) is replaced with the
+ * following ITE:
+ *
+ * ITE(i=j,v1,v2)
+ */
+ ASTNodeMap _arrayread_ite;
+
+ /*MAP: This is a map from array-reads to symbolic constants. This
+ *map is used by the TransformArray()
+ */
+ ASTNodeMap _arrayread_symbol;
+
+ ASTNodeSet _introduced_symbols;
+
+ /*Memoization map for TransformFormula/TransformTerm/TransformArray function
+ */
+ ASTNodeMap TransformMap;
+
+ //count to keep track of new symbolic constants introduced
+ //corresponding to Array Reads
+ unsigned int _symbol_count;
+
+ //Formula/Term Transformers. Let Expr Manager, Type Checker
+public:
+ //Functions that Transform ASTNodes
+ ASTNode TransformFormula(const ASTNode& query);
+ ASTNode TransformTerm(const ASTNode& term);
+ ASTNode TransformArray(const ASTNode& term);
+ ASTNode TranslateSignedDivMod(const ASTNode& term);
+
+ //LET Management
+private:
+ // MAP: This map is from bound IDs that occur in LETs to
+ // expression. The map is useful in checking replacing the IDs
+ // with the corresponding expressions.
+ ASTNodeMap *_letid_expr_map;
+public:
+
+ ASTNode ResolveID(const ASTNode& var);
+
+ //Functions that are used to manage LET expressions
+ void LetExprMgr(const ASTNode& var, const ASTNode& letExpr);
+
+ //Delete Letid Map
+ void CleanupLetIDMap(void);
+
+ //Allocate LetID map
+ void InitializeLetIDMap(void);
+
+ //Substitute Let-vars with LetExprs
+ ASTNode SubstituteLetExpr(ASTNode inExpr);
+
+ /* MAP: This is a map from MINISAT::Vars to ASTNodes
+ *
+ * This is a reverse map, useful in constructing
+ * counterexamples. MINISAT returns a model in terms of MINISAT
+ * Vars, and this map helps us convert it to a model over ASTNode
+ * variables.
+ */
+ vector<ASTNode> _SATVar_to_AST;
+
+private:
+ /* MAP: This is a map from ASTNodes to vectors of bits
+ *
+ * This map is used in constructing and printing
+ * counterexamples. MINISAT returns values for each bit (a
+ * BVGETBIT Node), and this maps allows us to assemble the bits
+ * into bitvectors.
+ */
+ typedef hash_map<ASTNode, hash_map<unsigned int, bool> *, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTtoBitvectorMap;
+ ASTtoBitvectorMap _ASTNode_to_Bitvector;
+
+ //Data structure that holds the counter-model
+ ASTNodeMap CounterExampleMap;
+
+ //Checks if the counter_example is ok. In order for the
+ //counter_example to be ok, Every assert must evaluate to true
+ //w.r.t couner_example and the query must evaluate to
+ //false. Otherwise the counter_example is bogus.
+ void CheckCounterExample(bool t);
+
+ //Converts a vector of bools to a BVConst
+ ASTNode BoolVectoBVConst(hash_map<unsigned, bool> * w, unsigned int l);
+
+ //accepts a term and turns it into a constant-term w.r.t counter_example
+ ASTNode TermToConstTermUsingModel(const ASTNode& term, bool ArrayReadFlag = true);
+ ASTNode Expand_ReadOverWrite_UsingModel(const ASTNode& term, bool ArrayReadFlag = true);
+ //Computes the truth value of a formula w.r.t counter_example
+ ASTNode ComputeFormulaUsingModel(const ASTNode& form);
+
+ //Replaces WRITE(Arr,i,val) with ITE(j=i, val, READ(Arr,j))
+ ASTNode RemoveWrites_TopLevel(const ASTNode& term);
+ ASTNode RemoveWrites(const ASTNode& term);
+ ASTNode SimplifyWrites_InPlace(const ASTNode& term);
+ ASTNode ReadOverWrite_To_ITE(const ASTNode& term);
+
+ ASTNode NewArrayVar(unsigned int index, unsigned int value);
+ ASTNode NewVar(unsigned int valuewidth);
+ //For ArrayWrite Abstraction: map from read-over-write term to
+ //newname.
+ ASTNodeMap ReadOverWrite_NewName_Map;
+ //For ArrayWrite Refinement: Map new arraynames to Read-Over-Write
+ //terms
+ ASTNodeMap NewName_ReadOverWrite_Map;
+
+public:
+ //print the STP solver output
+ void PrintOutput(bool true_iff_valid);
+
+ //Converts MINISAT counterexample into an AST memotable (i.e. the
+ //function populates the datastructure CounterExampleMap)
+ void ConstructCounterExample(MINISAT::Solver& S);
+
+ //Prints the counterexample to stdout
+ void PrintCounterExample(bool t, std::ostream& os = cout);
+
+ //Prints the counterexample to stdout
+ void PrintCounterExample_InOrder(bool t);
+
+ //queries the counterexample, and returns the value corresponding
+ //to e
+ ASTNode GetCounterExample(bool t, const ASTNode& e);
+
+ int CounterExampleSize(void) const
+ {
+ return CounterExampleMap.size();
+ }
+
+ //FIXME: This is bloody dangerous function. Hack attack to take
+ //care of requests from users who want to store complete
+ //counter-examples in their own data structures.
+ ASTNodeMap GetCompleteCounterExample()
+ {
+ return CounterExampleMap;
+ }
+
+ // prints MINISAT assigment one bit at a time, for debugging.
+ void PrintSATModel(MINISAT::Solver& S);
+
+ //accepts constant input and normalizes it.
+ ASTNode BVConstEvaluator(const ASTNode& t);
+
+ //FUNCTION 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
+ void BVTypeCheck(const ASTNode& n);
+
+private:
+ //stack of Logical Context. each entry in the stack is a logical
+ //context. A logical context is a vector of assertions. The
+ //logical context is represented by a ptr to a vector of
+ //assertions in that logical context. Logical contexts are created
+ //by PUSH/POP
+ std::vector<ASTVec *> _asserts;
+ //The query for the current logical context.
+ ASTNode _current_query;
+
+ //this flag, when true, indicates that counterexample is being
+ //checked by the counterexample checker
+ bool counterexample_checking_during_refinement;
+
+ //this flag indicates as to whether the input has been determined to
+ //be valid or not by this tool
+ bool ValidFlag;
+
+ //this flag, when true, indicates that a BVDIV divide by zero
+ //exception occured. However, the program must not exit with a
+ //fatalerror. Instead, it should evaluate the whole formula (which
+ //contains the BVDIV term) to be FALSE.
+ bool bvdiv_exception_occured;
+
+public:
+ //set of functions that manipulate Logical Contexts.
+ //
+ //add an assertion to the current logical context
+ void AddAssert(const ASTNode& assert);
+ void Push(void);
+ void Pop(void);
+ void AddQuery(const ASTNode& q);
+ const ASTNode PopQuery();
+ const ASTNode GetQuery();
+ const ASTVec GetAsserts(void);
+
+ //reports node size. Second arg is "clearstatinfo", whatever that is.
+ unsigned int NodeSize(const ASTNode& a, bool t = false);
+
+private:
+ //This memo map is used by the ComputeFormulaUsingModel()
+ ASTNodeMap ComputeFormulaMap;
+ //Map for statiscal purposes
+ ASTNodeSet StatInfoSet;
+
+ ASTNodeMap TermsAlreadySeenMap;
+ ASTNode CreateSubstitutionMap(const ASTNode& a);
+public:
+ //prints statistics for the ASTNode. can add a prefix string c
+ void ASTNodeStats(const char * c, const ASTNode& a);
+
+ //substitution
+ bool CheckSubstitutionMap(const ASTNode& a, ASTNode& output);
+ bool CheckSubstitutionMap(const ASTNode& a);
+ bool UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1);
+ //if (a > b) in the termorder, then return 1
+ //elseif (a < b) in the termorder, then return -1
+ //else return 0
+ int TermOrder(const ASTNode& a, const ASTNode& b);
+ //fill the arrayname_readindices vector if e0 is a READ(Arr,index)
+ //and index is a BVCONST
+ void FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1);
+ bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
+
+ //functions for checking and updating simplifcation map
+ bool CheckSimplifyMap(const ASTNode& key, ASTNode& output, bool pushNeg);
+ void UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg);
+ void ResetSimplifyMaps();
+ bool CheckAlwaysTrueFormMap(const ASTNode& key);
+ void UpdateAlwaysTrueFormMap(const ASTNode& val);
+ bool CheckMultInverseMap(const ASTNode& key, ASTNode& output);
+ void UpdateMultInverseMap(const ASTNode& key, const ASTNode& value);
+
+ //Map for solved variables
+ bool CheckSolverMap(const ASTNode& a, ASTNode& output);
+ bool CheckSolverMap(const ASTNode& a);
+ bool UpdateSolverMap(const ASTNode& e0, const ASTNode& e1);
+
+public:
+ //FIXME: HACK_ATTACK. this vector was hacked into the code to
+ //support a special request by Dawson' group. They want the
+ //counterexample to be printed in the order of variables declared.
+ //TO BE COMMENTED LATER (say by 1st week of march,2006)
+ ASTVec _special_print_set;
+
+ //prints the initial activity levels of variables
+ //void PrintActivityLevels_Of_SATVars(char * init_msg, MINISAT::Solver& newS);
+
+ //this function biases the activity levels of MINISAT variables.
+ //void ChangeActivityLevels_Of_SATVars(MINISAT::Solver& n);
+
+ // Constructor
+ BeevMgr() :
+ _interior_unique_table(INITIAL_INTERIOR_UNIQUE_TABLE_SIZE), _symbol_unique_table(INITIAL_SYMBOL_UNIQUE_TABLE_SIZE), _bvconst_unique_table(
+ INITIAL_BVCONST_UNIQUE_TABLE_SIZE), BBTermMemo(INITIAL_BBTERM_MEMO_TABLE_SIZE), BBFormMemo(INITIAL_BBFORM_MEMO_TABLE_SIZE),
+ _max_node_num(0), ASTFalse(CreateNode(FALSE)), ASTTrue(CreateNode(TRUE)), ASTUndefined(CreateNode(UNDEFINED)), SolverMap(
+ INITIAL_SOLVER_MAP_SIZE), _arrayread_symbol(INITIAL_ARRAYREAD_SYMBOL_SIZE), _introduced_symbols(
+ INITIAL_INTRODUCED_SYMBOLS_SIZE), _symbol_count(0)
+ {
+ _current_query = ASTUndefined;
+ ValidFlag = false;
+ bvdiv_exception_occured = false;
+ counterexample_checking_during_refinement = false;
+ start_abstracting = false;
+ Begin_RemoveWrites = false;
+ SimplifyWrites_InPlace_Flag = false;
+ SimplifyMap = new ASTNodeMap(INITIAL_SIMPLIFY_MAP_SIZE);
+ SimplifyNegMap = new ASTNodeMap(INITIAL_SIMPLIFY_MAP_SIZE);
+ _letid_expr_map = new ASTNodeMap(INITIAL_INTRODUCED_SYMBOLS_SIZE);
+ }
+ ;
+
+ //destructor
+ ~BeevMgr();
+}; //End of Class BeevMgr
+
+
+class CompleteCounterExample
+{
+ ASTNodeMap counterexample;
+ BeevMgr * bv;
+public:
+ CompleteCounterExample(ASTNodeMap a, BeevMgr* beev) :
+ counterexample(a), bv(beev)
+ {
+ }
+ ASTNode GetCounterExample(ASTNode e)
+ {
+ if (BOOLEAN_TYPE == e.GetType() && SYMBOL != e.GetKind())
+ {
+ FatalError("You must input a term or propositional variables\n", e);
+ }
+ if (counterexample.find(e) != counterexample.end())
+ {
+ return counterexample[e];
+ }
+ else
+ {
+ if (SYMBOL == e.GetKind() && BOOLEAN_TYPE == e.GetType())
+ {
+ return bv->CreateNode(BEEV::FALSE);
+ }
+
+ if (SYMBOL == e.GetKind())
+ {
+ ASTNode z = bv->CreateZeroConst(e.GetValueWidth());
+ return z;
+ }
+
+ return e;
+ }
+ }
+};
-}; // end namespace BEEV
+}
+; // end namespace BEEV
#endif
// -*- c++ -*-
#include "ASTUtil.h"
-namespace BEEV {
- ostream &operator<<(ostream &os, const Spacer &sp) {
- // Instead of wrapping lines with hundreds of spaces, prints
- // a "+" at the beginning of the line for each wrap-around.
- // so lines print like: +14+ (XOR ...
- int blanks = sp._spaces % 60;
- int wraps = sp._spaces / 60;
- if (wraps > 0) {
- os << "+" << wraps;
- }
- for (int i = 0; i < blanks; i++)
- os << " ";
- return os;
- }
-
- //this function accepts the name of a function (as a char *), and
- //records some stats about it. if the input is "print_func_stats",
- //the function will then print the stats that it has collected.
- void CountersAndStats(const char * functionname) {
- static function_counters s;
+namespace BEEV
+{
+ostream &operator<<(ostream &os, const Spacer &sp)
+{
+ // Instead of wrapping lines with hundreds of spaces, prints
+ // a "+" at the beginning of the line for each wrap-around.
+ // so lines print like: +14+ (XOR ...
+ int blanks = sp._spaces % 60;
+ int wraps = sp._spaces / 60;
+ if (wraps > 0)
+ {
+ os << "+" << wraps;
+ }
+ for (int i = 0; i < blanks; i++)
+ os << " ";
+ return os;
+}
- if (stats) {
+//this function accepts the name of a function (as a char *), and
+//records some stats about it. if the input is "print_func_stats",
+//the function will then print the stats that it has collected.
+void CountersAndStats(const char * functionname)
+{
+ static function_counters s;
- if(!strcmp(functionname,"print_func_stats")) {
- cout << endl;
- for(function_counters::iterator it=s.begin(),itend=s.end();
- it!=itend;it++)
- cout << "Number of times the function: " << it->first << ": is called: " << it->second << endl;
- return;
- }
- s[functionname] += 1;
+ if (stats)
+ {
- }
- }
-};// end of namespace
+ if (!strcmp(functionname, "print_func_stats"))
+ {
+ cout << endl;
+ for (function_counters::iterator it = s.begin(), itend = s.end(); it != itend; it++)
+ cout << "Number of times the function: " << it->first << ": is called: " << it->second << endl;
+ return;
+ }
+ s[functionname] += 1;
+
+ }
+}
+}
+;// end of namespace
// The 0th element of the vector corresponds to bit 0 -- the low-order bit.
#include "AST.h"
-namespace BEEV {
- // extern void lpvec(ASTVec &vec);
+namespace BEEV
+{
+// extern void lpvec(ASTVec &vec);
// FIXME: Assert no zero-length bit vectors!!!
// FIXME: Need top-level functions that create and destroy the memo tables.
ASTNode ASTJunk;
-const ASTNode BeevMgr::BBTerm(const ASTNode& term) {
-
-
- //CHANGED TermMemo is now an ASTNodeMap. Based on BBFormMemo
- ASTNodeMap::iterator it = BBTermMemo.find(term);
- if (it != BBTermMemo.end()) {
- // already there. Just return it.
- return it->second;
- }
-
-// ASTNode& result = ASTJunk;
- ASTNode result;
-
- /*
- bool weregood = false;
- if(term.GetNodeNum() == 17408){
- weregood = true;
- }
- */
-
-
- Kind k = term.GetKind();
- if (!is_Term_kind(k))
- FatalError("BBTerm: Illegal kind to BBTerm",term);
-
- ASTVec::const_iterator kids_end = term.end();
- unsigned int num_bits = term.GetValueWidth();
- switch (k) {
- case BVNEG: {
- // bitwise complement
- // bitblast the child.
- //FIXME Uses a tempory const ASTNode
- const ASTNode& bbkids = BBTerm(term[0]);
- result = CreateNode(BOOLVEC, BBNeg(bbkids.GetChildren()));
- break;
- }
-
- case BVLEFTSHIFT:
- {
- if (BVCONST == term[1].GetKind())
- {
- // Constant shifts should be removed during simplification.
- unsigned int shift = GetUnsignedConst(term[1]);
-
- ASTNode term0 = BBTerm(term[0]);
- ASTVec children(term0.GetChildren()); // mutable copy of the children.
- BBLShift(children, shift);
-
- result = CreateNode(BOOLVEC, children);
- }
- else
- {
- // Barrel shifter
- const ASTVec& bbarg1 = BBTerm(term[0]).GetChildren();
- const ASTVec& bbarg2 = BBTerm(term[1]).GetChildren();
-
- ASTVec temp_result(bbarg1);
-
- for (unsigned int i =0; i < bbarg2.size(); i++)
+const ASTNode BeevMgr::BBTerm(const ASTNode& term)
+{
+
+ //CHANGED TermMemo is now an ASTNodeMap. Based on BBFormMemo
+ ASTNodeMap::iterator it = BBTermMemo.find(term);
+ if (it != BBTermMemo.end())
+ {
+ // already there. Just return it.
+ return it->second;
+ }
+
+ // ASTNode& result = ASTJunk;
+ ASTNode result;
+
+ /*
+ bool weregood = false;
+ if(term.GetNodeNum() == 17408){
+ weregood = true;
+ }
+ */
+
+ Kind k = term.GetKind();
+ if (!is_Term_kind(k))
+ FatalError("BBTerm: Illegal kind to BBTerm", term);
+
+ ASTVec::const_iterator kids_end = term.end();
+ unsigned int num_bits = term.GetValueWidth();
+ switch (k)
+ {
+ case BVNEG:
{
- if (bbarg2[i] == ASTFalse)
- continue; // Not shifting by anything.
-
- unsigned int shift_amount = 1 << i;
-
- bool done = false;
-
- for (unsigned int j=temp_result.size()-1; !done; j--)
+ // bitwise complement
+ // bitblast the child.
+ //FIXME Uses a tempory const ASTNode
+ const ASTNode& bbkids = BBTerm(term[0]);
+ result = CreateNode(BOOLVEC, BBNeg(bbkids.GetChildren()));
+ break;
+ }
+
+ case BVLEFTSHIFT:
+ {
+ if (BVCONST == term[1].GetKind())
+ {
+ // Constant shifts should be removed during simplification.
+ unsigned int shift = GetUnsignedConst(term[1]);
+
+ ASTNode term0 = BBTerm(term[0]);
+ ASTVec children(term0.GetChildren()); // mutable copy of the children.
+ BBLShift(children, shift);
+
+ result = CreateNode(BOOLVEC, children);
+ }
+ else
{
- if (j < shift_amount)
- temp_result[j] = CreateSimpForm(ITE, bbarg2[i],ASTFalse,temp_result[j]);
- else
- temp_result[j] = CreateSimpForm(ITE, bbarg2[i],temp_result[j-shift_amount],temp_result[j]);
-
- // want the loop to finish after j=0, but when j=0, j-1 == MAX_INT. Hence this weird idiom.
- if (j ==0)
- done = true;
+ // Barrel shifter
+ const ASTVec& bbarg1 = BBTerm(term[0]).GetChildren();
+ const ASTVec& bbarg2 = BBTerm(term[1]).GetChildren();
+
+ ASTVec temp_result(bbarg1);
+
+ for (unsigned int i = 0; i < bbarg2.size(); i++)
+ {
+ if (bbarg2[i] == ASTFalse)
+ continue; // Not shifting by anything.
+
+ unsigned int shift_amount = 1 << i;
+
+ bool done = false;
+
+ for (unsigned int j = temp_result.size() - 1; !done; j--)
+ {
+ if (j < shift_amount)
+ temp_result[j] = CreateSimpForm(ITE, bbarg2[i], ASTFalse, temp_result[j]);
+ else
+ temp_result[j] = CreateSimpForm(ITE, bbarg2[i], temp_result[j - shift_amount], temp_result[j]);
+
+ // want the loop to finish after j=0, but when j=0, j-1 == MAX_INT. Hence this weird idiom.
+ if (j == 0)
+ done = true;
+ }
+ }
+
+ result = CreateNode(BOOLVEC, temp_result);
}
+ break;
}
- result = CreateNode(BOOLVEC, temp_result);
- }
- break;
- }
-
- case BVRIGHTSHIFT:
- {
- if (BVCONST == term[1].GetKind())
- {
- // Constant shifts should be removed during simplification.
-
- unsigned int shift = GetUnsignedConst(term[1]);
-
- ASTNode term0 = BBTerm(term[0]);
- ASTVec children(term0.GetChildren()); // mutable copy of the children.
- BBRShift(children, shift);
-
- result = CreateNode(BOOLVEC, children);
- }
- else
- {
- // Barrel shifter
- const ASTVec& bbarg1 = BBTerm(term[0]).GetChildren();
- const ASTVec& bbarg2 = BBTerm(term[1]).GetChildren();
-
- ASTVec temp_result(bbarg1);
-
- for (unsigned int i =0; i < bbarg2.size(); i++)
- {
- if (bbarg2[i] == ASTFalse)
- continue; // Not shifting by anything.
-
- unsigned int shift_amount = 1 << i;
-
- bool done = false;
-
- for (unsigned int j=0; j < temp_result.size(); j++)
- {
- if (j + shift_amount >= temp_result.size())
- temp_result[j] = CreateSimpForm(ITE, bbarg2[i],ASTFalse,temp_result[j]);
- else
- temp_result[j] = CreateSimpForm(ITE, bbarg2[i],temp_result[j+shift_amount],temp_result[j]);
-
- if (j ==0)
- done = true;
- }
- }
-
-
- result = CreateNode(BOOLVEC, temp_result);
-
- /* cerr << result << endl;
- cerr << term[0] << endl;
- cerr << term[1] << endl;
- cerr << "right shift. Node size is:" << NodeSize(result) << endl;
- cerr << "input size: " << NodeSize(term[0]) << " " << NodeSize(term[1]) << endl;
- */
- }
- }
- break;
-
-
-
- case BVSRSHIFT:
- case BVVARSHIFT:
- FatalError("BBTerm: These kinds have not been implemented in the BitBlaster: ", term);
- break;
- case ITE: {
- // Term version of ITE.
-
- // Blast the args
- // FIXME Uses temporary const ASTNodes and an ASTVec&
- //const ASTNode& cond = BBForm(term[0]);
- const ASTNode& cond = BBForm(term[0]);
- const ASTNode& thn = BBTerm(term[1]);
- const ASTNode& els = BBTerm(term[2]);
- result =
- CreateNode(BOOLVEC, BBITE(cond, thn.GetChildren(), els.GetChildren()));
- break;
- }
-
-
- case BVSX: {
- // Replicate high-order bit as many times as necessary.
- // Arg 0 is expression to be sign extended.
- const ASTNode& arg = term[0];
- unsigned long result_width = term.GetValueWidth();
- unsigned long arg_width = arg.GetValueWidth();
- //FIXME Uses a temporary const ASTNode reference
- const ASTNode& bbarg = BBTerm(arg);
-
- if (result_width == arg_width) {
- //nothing to sign extend
- break;
- }
- else {
- //we need to sign extend
- const ASTNode& msbX = bbarg.back();
- //const ASTNode& msb1 = msbX;
-
- ASTVec ccc = msbX.GetChildren();
- const ASTNode& msb = CreateSimpForm(msbX.GetKind(),ccc);
-
- // Old version
- // ASTNode msb = bbarg.back();
- // const ASTNode msb1 = msb;
-
- // ASTVec ccc = msb.GetChildren();
- // msb = CreateSimpForm(msb.GetKind(),ccc);
-
- // DD 1/14/07 Simplify silently drops all but first two args of XOR.
- // I expanded XOR to N args with flattening optimization.
- // This bug took 2 days to track down!
-
- // msb = SimplifyFormula(msb,false);
-
- // cout << "!!!!!!!!!!!!!!!!" << endl
- // << "Simplify msb:" << msb2 << endl
- // << "Simplify result:" << msb << endl;
-
- //FIXME Dynamically allocate the result vector?
- //Is this doing multiple copies?
- //ASTVec& tmp_res = *(new ASTVec(result_width));
- ASTVec tmp_res(result_width);
-
- //FIXME Should these be gotten from result?
- ASTVec::const_iterator bb_it = bbarg.begin();
- ASTVec::iterator res_it = tmp_res.begin();
- ASTVec::iterator res_ext = res_it+arg_width; // first bit of extended part
- ASTVec::iterator res_end = tmp_res.end();
- // copy LSBs directly from bbvec
- for( ; res_it < res_ext; (res_it++, bb_it++)) {
- *res_it = *bb_it;
- }
- // repeat MSB to fill up rest of result.
- for( ; res_it < res_end; (res_it++)) {
- *res_it = msb;
- }
-
- //Temporary debugging code
- // cout << "Sign extending:" << endl
- // << " Vec ";
- // lpvec( bbarg.GetChildren() );
- // cout << " Extended to ";
- // lp(result);
- // cout << endl;
-
- result = CreateNode(BOOLVEC, tmp_res);
-
- break;
- }
- }
-
- case BVZX: {
- // Fill the high-order bits with as many zeroes as needed.
- // Arg 0 is expression to be sign extended.
- const ASTNode& arg = term[0];
- unsigned long result_width = term.GetValueWidth();
- unsigned long arg_width = arg.GetValueWidth();
-
- //FIXME Uses a temporary const ASTNode reference
- const ASTNode& bbarg = BBTerm(arg);
- ASTVec tmp_res(result_width);
-
- //FIXME Should these be gotten from result?
- ASTVec::const_iterator bb_it = bbarg.begin();
- ASTVec::iterator res_it = tmp_res.begin();
- ASTVec::iterator res_ext = res_it+arg_width; // first bit of extended part
- ASTVec::iterator res_end = tmp_res.end();
- // copy LSBs directly from bbvec
- for( ; res_it < res_ext; (res_it++, bb_it++)) {
- *res_it = *bb_it;
- }
- // repeat zero to fill up rest of result.
- for( ; res_it < res_end; (res_it++)) {
- *res_it = ASTFalse;
- }
-
- // Temporary debugging code
- // cout << "Zero extending:" << endl
- // << " Vec ";
- // lpvec( bbarg.GetChildren() );
- // cout << " Extended to ";
- // cout << result;
- // cout << endl;
-
- result = CreateNode(BOOLVEC, tmp_res);
-
- break;
- }
-
-
-
-
- case BVEXTRACT: {
- // bitblast the child, then extract the relevant bits.
- // Note: This could be optimized by not bitblasting the bits
- // that aren't fetched. But that would be tricky, especially
- // with memo-ization.
-
- //FIXME Using const ASTNode w/out reference
- /*
- if(weregood){
- printf("spot01\n");
- term[0].LispPrint(cout, 0);
- }
- */
- const ASTNode& bbkids = BBTerm(term[0]);
- /*
- if(weregood){
- printf("spot02, kids:\n");
- bbkids.LispPrint(cout, 0);
- }
- */
- unsigned int high = GetUnsignedConst(term[1]);
- /*
- if(weregood){
- printf("spot03, high: %d\n", high);
- }
- */
- unsigned int low = GetUnsignedConst(term[2]);
- /*
- if(weregood){
- printf("spot04, low: %d\n", low);
- }
- */
-
- ASTVec::const_iterator bbkfit = bbkids.begin();
- // I should have used pointers to ASTVec, to avoid this crock
-
- //FIXME Creates a new local ASTVec and does the CreateNode from that
- result = CreateNode(BOOLVEC, ASTVec(bbkfit+low, bbkfit+high+1));
- /*
- if(weregood){
- printf("spot05\n");
- }
- */
- break;
- }
- case BVCONCAT: {
- //FIXME Using temporary const ASTNodes
- const ASTNode& vec1 = BBTerm(term[0]);
- const ASTNode& vec2 = BBTerm(term[1]);
-
- //FIXME This has to be an unnessecary copy and a memory leak
- //Leaking ASTVec tmp_res = *(new ASTVec(vec2.GetChildren()));
- ASTVec tmp_res(vec2.GetChildren());
- tmp_res.insert(tmp_res.end(), vec1.begin(), vec1.end());
- result = CreateNode(BOOLVEC, tmp_res);
- break;
- }
- case BVPLUS: {
- // ASSERT: at least one child.
- // ASSERT: all children and result are the same size.
- // Previous phase must make sure this is true.
- // Add children pairwise and accumulate in BBsum
-
- // FIXME: Unnecessary array copies.
- ASTVec::const_iterator it = term.begin();
- ASTVec tmp_res = BBTerm(*it).GetChildren();
- for (++it; it < kids_end; it++) {
- const ASTVec& tmp = BBTerm(*it).GetChildren();
- BBPlus2(tmp_res, tmp, ASTFalse);
- }
-
- result = CreateNode(BOOLVEC, tmp_res);
- break;
- }
- case BVUMINUS: {
- //FIXME Using const ASTNode reference
- const ASTNode& bbkid = BBTerm(term[0]);
- result = CreateNode(BOOLVEC, BBUminus(bbkid.GetChildren()));
- break;
- }
- case BVSUB: {
- // complement of subtrahend
- // copy, since BBSub writes into it.
-
- //FIXME: Unnecessary array copies?
- ASTVec tmp_res = BBTerm(term[0]).GetChildren();
-
- const ASTVec& bbkid1 = BBTerm(term[1]).GetChildren();
- BBSub(tmp_res, bbkid1);
- result = CreateNode(BOOLVEC, tmp_res);
- break;
- }
- case BVMULT: {
- // ASSERT 2 arguments, same length, result is same length.
-
- const ASTNode& t0 = term[0];
- const ASTNode& t1 = term[1];
-
- const ASTNode& mpcd1 = BBTerm(t0);
- const ASTNode& mpcd2 = BBTerm(t1);
- //Reverese the order of the nodes w/out the need for temporaries
- //This is needed because t0 an t1 must be const
- if ((BVCONST != t0.GetKind()) && (BVCONST == t1.GetKind())) {
- result = CreateNode(BOOLVEC,
- BBMult(mpcd2.GetChildren(), mpcd1.GetChildren()) );
- }else{
- result = CreateNode(BOOLVEC,
- BBMult(mpcd1.GetChildren(), mpcd2.GetChildren()) );
- }
- break;
- }
- case BVDIV:
- case BVMOD: {
- const ASTNode& dvdd = BBTerm(term[0]);
- const ASTNode& dvsr = BBTerm(term[1]);
- unsigned int width = dvdd.Degree();
- ASTVec q(width);
- ASTVec r(width);
- BBDivMod(dvdd.GetChildren(), dvsr.GetChildren(), q, r, width);
- if (k == BVDIV)
- result = CreateNode(BOOLVEC, q);
- else
- result = CreateNode(BOOLVEC, r);
- break;
- }
- // n-ary bitwise operators.
- case BVXOR:
- case BVXNOR:
- case BVAND:
- case BVOR:
- case BVNOR:
- case BVNAND: {
- // Add children pairwise and accumulate in BBsum
- ASTVec::const_iterator it = term.begin();
- Kind bk = UNDEFINED; // Kind of individual bit op.
- switch (k) {
- case BVXOR: bk = XOR; break;
- case BVXNOR: bk = IFF; break;
- case BVAND: bk = AND; break;
- case BVOR: bk = OR; break;
- case BVNOR: bk = NOR; break;
- case BVNAND: bk = NAND; break;
- default:
- FatalError("BBTerm: Illegal kind to BBTerm",term);
- break;
- }
-
- // Sum is destructively modified in the loop, so make a copy of value
- // returned by BBTerm.
- ASTNode temp = BBTerm(*it);
- ASTVec sum(temp.GetChildren()); // First operand.
-
- // Iterate over remaining bitvector term operands
- for (++it; it < kids_end; it++) {
- //FIXME FIXME FIXME: Why does using a temp. var change the behavior?
- temp = BBTerm(*it);
- const ASTVec& y = temp.GetChildren();
-
- // Iterate over bits
- // FIXME: Why is this not using an iterator???
- int n = y.size();
- for (int i = 0; i < n; i++) {
- sum[i] = CreateSimpForm(bk, sum[i], y[i]);
- }
- }
- result = CreateNode(BOOLVEC, sum);
- break;
- }
- case SYMBOL: {
- // ASSERT: IndexWidth = 0? Semantic analysis should check.
- //Leaking ASTVec& bbvec = *(new ASTVec);
-
- //FIXME Why is isn't this ASTVEC bbvec(num_bits) ?
- ASTVec bbvec;
- /*
- if(term.GetNodeNum() == 17132){
- weregood = true;
- }
- */
-
- /*
- if(weregood){
- printf("number of bits for node 17132: %d\n", num_bits);
- }
- */
- for (unsigned int i = 0; i < num_bits; i++) {
- ASTNode bit_node =
- CreateNode(BVGETBIT, term, CreateBVConst(32,i));
- bbvec.push_back(bit_node);
- }
- result = CreateNode(BOOLVEC, bbvec);
- /*
- if(weregood){
- printf("done\n");
- }
- */
- break;
- }
- case BVCONST: {
- ASTVec tmp_res(num_bits);
+ case BVRIGHTSHIFT:
+ {
+ if (BVCONST == term[1].GetKind())
+ {
+ // Constant shifts should be removed during simplification.
+
+ unsigned int shift = GetUnsignedConst(term[1]);
+
+ ASTNode term0 = BBTerm(term[0]);
+ ASTVec children(term0.GetChildren()); // mutable copy of the children.
+ BBRShift(children, shift);
+
+ result = CreateNode(BOOLVEC, children);
+ }
+ else
+ {
+ // Barrel shifter
+ const ASTVec& bbarg1 = BBTerm(term[0]).GetChildren();
+ const ASTVec& bbarg2 = BBTerm(term[1]).GetChildren();
+
+ ASTVec temp_result(bbarg1);
+
+ for (unsigned int i = 0; i < bbarg2.size(); i++)
+ {
+ if (bbarg2[i] == ASTFalse)
+ continue; // Not shifting by anything.
+
+ unsigned int shift_amount = 1 << i;
+
+ bool done = false;
+
+ for (unsigned int j = 0; j < temp_result.size(); j++)
+ {
+ if (j + shift_amount >= temp_result.size())
+ temp_result[j] = CreateSimpForm(ITE, bbarg2[i], ASTFalse, temp_result[j]);
+ else
+ temp_result[j] = CreateSimpForm(ITE, bbarg2[i], temp_result[j + shift_amount], temp_result[j]);
+
+ if (j == 0)
+ done = true;
+ }
+ }
+
+ result = CreateNode(BOOLVEC, temp_result);
+
+ /* cerr << result << endl;
+ cerr << term[0] << endl;
+ cerr << term[1] << endl;
+ cerr << "right shift. Node size is:" << NodeSize(result) << endl;
+ cerr << "input size: " << NodeSize(term[0]) << " " << NodeSize(term[1]) << endl;
+ */
+ }
+ }
+ break;
+
+ case BVSRSHIFT:
+ case BVVARSHIFT:
+ FatalError("BBTerm: These kinds have not been implemented in the BitBlaster: ", term);
+ break;
+ case ITE:
+ {
+ // Term version of ITE.
+
+ // Blast the args
+ // FIXME Uses temporary const ASTNodes and an ASTVec&
+ //const ASTNode& cond = BBForm(term[0]);
+ const ASTNode& cond = BBForm(term[0]);
+ const ASTNode& thn = BBTerm(term[1]);
+ const ASTNode& els = BBTerm(term[2]);
+ result = CreateNode(BOOLVEC, BBITE(cond, thn.GetChildren(), els.GetChildren()));
+ break;
+ }
+
+ case BVSX:
+ {
+ // Replicate high-order bit as many times as necessary.
+ // Arg 0 is expression to be sign extended.
+ const ASTNode& arg = term[0];
+ unsigned long result_width = term.GetValueWidth();
+ unsigned long arg_width = arg.GetValueWidth();
+ //FIXME Uses a temporary const ASTNode reference
+ const ASTNode& bbarg = BBTerm(arg);
+
+ if (result_width == arg_width)
+ {
+ //nothing to sign extend
+ break;
+ }
+ else
+ {
+ //we need to sign extend
+ const ASTNode& msbX = bbarg.back();
+ //const ASTNode& msb1 = msbX;
+
+ ASTVec ccc = msbX.GetChildren();
+ const ASTNode& msb = CreateSimpForm(msbX.GetKind(), ccc);
+
+ // Old version
+ // ASTNode msb = bbarg.back();
+ // const ASTNode msb1 = msb;
+
+ // ASTVec ccc = msb.GetChildren();
+ // msb = CreateSimpForm(msb.GetKind(),ccc);
+
+ // DD 1/14/07 Simplify silently drops all but first two args of XOR.
+ // I expanded XOR to N args with flattening optimization.
+ // This bug took 2 days to track down!
+
+ // msb = SimplifyFormula(msb,false);
+
+ // cout << "!!!!!!!!!!!!!!!!" << endl
+ // << "Simplify msb:" << msb2 << endl
+ // << "Simplify result:" << msb << endl;
+
+ //FIXME Dynamically allocate the result vector?
+ //Is this doing multiple copies?
+ //ASTVec& tmp_res = *(new ASTVec(result_width));
+ ASTVec tmp_res(result_width);
+
+ //FIXME Should these be gotten from result?
+ ASTVec::const_iterator bb_it = bbarg.begin();
+ ASTVec::iterator res_it = tmp_res.begin();
+ ASTVec::iterator res_ext = res_it + arg_width; // first bit of extended part
+ ASTVec::iterator res_end = tmp_res.end();
+ // copy LSBs directly from bbvec
+ for (; res_it < res_ext; (res_it++, bb_it++))
+ {
+ *res_it = *bb_it;
+ }
+ // repeat MSB to fill up rest of result.
+ for (; res_it < res_end; (res_it++))
+ {
+ *res_it = msb;
+ }
+
+ //Temporary debugging code
+ // cout << "Sign extending:" << endl
+ // << " Vec ";
+ // lpvec( bbarg.GetChildren() );
+ // cout << " Extended to ";
+ // lp(result);
+ // cout << endl;
+
+ result = CreateNode(BOOLVEC, tmp_res);
+
+ break;
+ }
+ }
+
+ case BVZX:
+ {
+ // Fill the high-order bits with as many zeroes as needed.
+ // Arg 0 is expression to be sign extended.
+ const ASTNode& arg = term[0];
+ unsigned long result_width = term.GetValueWidth();
+ unsigned long arg_width = arg.GetValueWidth();
+
+ //FIXME Uses a temporary const ASTNode reference
+ const ASTNode& bbarg = BBTerm(arg);
+ ASTVec tmp_res(result_width);
+
+ //FIXME Should these be gotten from result?
+ ASTVec::const_iterator bb_it = bbarg.begin();
+ ASTVec::iterator res_it = tmp_res.begin();
+ ASTVec::iterator res_ext = res_it + arg_width; // first bit of extended part
+ ASTVec::iterator res_end = tmp_res.end();
+ // copy LSBs directly from bbvec
+ for (; res_it < res_ext; (res_it++, bb_it++))
+ {
+ *res_it = *bb_it;
+ }
+ // repeat zero to fill up rest of result.
+ for (; res_it < res_end; (res_it++))
+ {
+ *res_it = ASTFalse;
+ }
+
+ // Temporary debugging code
+ // cout << "Zero extending:" << endl
+ // << " Vec ";
+ // lpvec( bbarg.GetChildren() );
+ // cout << " Extended to ";
+ // cout << result;
+ // cout << endl;
+
+ result = CreateNode(BOOLVEC, tmp_res);
+
+ break;
+ }
+
+ case BVEXTRACT:
+ {
+ // bitblast the child, then extract the relevant bits.
+ // Note: This could be optimized by not bitblasting the bits
+ // that aren't fetched. But that would be tricky, especially
+ // with memo-ization.
+
+ //FIXME Using const ASTNode w/out reference
+ /*
+ if(weregood){
+ printf("spot01\n");
+ term[0].LispPrint(cout, 0);
+ }
+ */
+ const ASTNode& bbkids = BBTerm(term[0]);
+ /*
+ if(weregood){
+ printf("spot02, kids:\n");
+ bbkids.LispPrint(cout, 0);
+ }
+ */
+ unsigned int high = GetUnsignedConst(term[1]);
+ /*
+ if(weregood){
+ printf("spot03, high: %d\n", high);
+ }
+ */
+ unsigned int low = GetUnsignedConst(term[2]);
+ /*
+ if(weregood){
+ printf("spot04, low: %d\n", low);
+ }
+ */
+
+ ASTVec::const_iterator bbkfit = bbkids.begin();
+ // I should have used pointers to ASTVec, to avoid this crock
+
+ //FIXME Creates a new local ASTVec and does the CreateNode from that
+ result = CreateNode(BOOLVEC, ASTVec(bbkfit + low, bbkfit + high + 1));
+ /*
+ if(weregood){
+ printf("spot05\n");
+ }
+ */
+ break;
+ }
+ case BVCONCAT:
+ {
+ //FIXME Using temporary const ASTNodes
+ const ASTNode& vec1 = BBTerm(term[0]);
+ const ASTNode& vec2 = BBTerm(term[1]);
+
+ //FIXME This has to be an unnessecary copy and a memory leak
+ //Leaking ASTVec tmp_res = *(new ASTVec(vec2.GetChildren()));
+ ASTVec tmp_res(vec2.GetChildren());
+ tmp_res.insert(tmp_res.end(), vec1.begin(), vec1.end());
+ result = CreateNode(BOOLVEC, tmp_res);
+ break;
+ }
+ case BVPLUS:
+ {
+ // ASSERT: at least one child.
+ // ASSERT: all children and result are the same size.
+ // Previous phase must make sure this is true.
+ // Add children pairwise and accumulate in BBsum
+
+ // FIXME: Unnecessary array copies.
+ ASTVec::const_iterator it = term.begin();
+ ASTVec tmp_res = BBTerm(*it).GetChildren();
+ for (++it; it < kids_end; it++)
+ {
+ const ASTVec& tmp = BBTerm(*it).GetChildren();
+ BBPlus2(tmp_res, tmp, ASTFalse);
+ }
+
+ result = CreateNode(BOOLVEC, tmp_res);
+ break;
+ }
+ case BVUMINUS:
+ {
+ //FIXME Using const ASTNode reference
+ const ASTNode& bbkid = BBTerm(term[0]);
+ result = CreateNode(BOOLVEC, BBUminus(bbkid.GetChildren()));
+ break;
+ }
+ case BVSUB:
+ {
+ // complement of subtrahend
+ // copy, since BBSub writes into it.
+
+ //FIXME: Unnecessary array copies?
+ ASTVec tmp_res = BBTerm(term[0]).GetChildren();
+
+ const ASTVec& bbkid1 = BBTerm(term[1]).GetChildren();
+ BBSub(tmp_res, bbkid1);
+ result = CreateNode(BOOLVEC, tmp_res);
+ break;
+ }
+ case BVMULT:
+ {
+ // ASSERT 2 arguments, same length, result is same length.
+
+ const ASTNode& t0 = term[0];
+ const ASTNode& t1 = term[1];
+
+ const ASTNode& mpcd1 = BBTerm(t0);
+ const ASTNode& mpcd2 = BBTerm(t1);
+ //Reverese the order of the nodes w/out the need for temporaries
+ //This is needed because t0 an t1 must be const
+ if ((BVCONST != t0.GetKind()) && (BVCONST == t1.GetKind()))
+ {
+ result = CreateNode(BOOLVEC, BBMult(mpcd2.GetChildren(), mpcd1.GetChildren()));
+ }
+ else
+ {
+ result = CreateNode(BOOLVEC, BBMult(mpcd1.GetChildren(), mpcd2.GetChildren()));
+ }
+ break;
+ }
+ case BVDIV:
+ case BVMOD:
+ {
+ const ASTNode& dvdd = BBTerm(term[0]);
+ const ASTNode& dvsr = BBTerm(term[1]);
+ unsigned int width = dvdd.Degree();
+ ASTVec q(width);
+ ASTVec r(width);
+ BBDivMod(dvdd.GetChildren(), dvsr.GetChildren(), q, r, width);
+ if (k == BVDIV)
+ result = CreateNode(BOOLVEC, q);
+ else
+ result = CreateNode(BOOLVEC, r);
+ break;
+ }
+ // n-ary bitwise operators.
+ case BVXOR:
+ case BVXNOR:
+ case BVAND:
+ case BVOR:
+ case BVNOR:
+ case BVNAND:
+ {
+ // Add children pairwise and accumulate in BBsum
+ ASTVec::const_iterator it = term.begin();
+ Kind bk = UNDEFINED; // Kind of individual bit op.
+ switch (k)
+ {
+ case BVXOR:
+ bk = XOR;
+ break;
+ case BVXNOR:
+ bk = IFF;
+ break;
+ case BVAND:
+ bk = AND;
+ break;
+ case BVOR:
+ bk = OR;
+ break;
+ case BVNOR:
+ bk = NOR;
+ break;
+ case BVNAND:
+ bk = NAND;
+ break;
+ default:
+ FatalError("BBTerm: Illegal kind to BBTerm", term);
+ break;
+ }
+
+ // Sum is destructively modified in the loop, so make a copy of value
+ // returned by BBTerm.
+ ASTNode temp = BBTerm(*it);
+ ASTVec sum(temp.GetChildren()); // First operand.
+
+ // Iterate over remaining bitvector term operands
+ for (++it; it < kids_end; it++)
+ {
+ //FIXME FIXME FIXME: Why does using a temp. var change the behavior?
+ temp = BBTerm(*it);
+ const ASTVec& y = temp.GetChildren();
+
+ // Iterate over bits
+ // FIXME: Why is this not using an iterator???
+ int n = y.size();
+ for (int i = 0; i < n; i++)
+ {
+ sum[i] = CreateSimpForm(bk, sum[i], y[i]);
+ }
+ }
+ result = CreateNode(BOOLVEC, sum);
+ break;
+ }
+ case SYMBOL:
+ {
+ // ASSERT: IndexWidth = 0? Semantic analysis should check.
+ //Leaking ASTVec& bbvec = *(new ASTVec);
+
+ //FIXME Why is isn't this ASTVEC bbvec(num_bits) ?
+ ASTVec bbvec;
+ /*
+ if(term.GetNodeNum() == 17132){
+ weregood = true;
+ }
+ */
+
+ /*
+ if(weregood){
+ printf("number of bits for node 17132: %d\n", num_bits);
+ }
+ */
+ for (unsigned int i = 0; i < num_bits; i++)
+ {
+ ASTNode bit_node = CreateNode(BVGETBIT, term, CreateBVConst(32, i));
+ bbvec.push_back(bit_node);
+ }
+ result = CreateNode(BOOLVEC, bbvec);
+ /*
+ if(weregood){
+ printf("done\n");
+ }
+ */
+ break;
+ }
+ case BVCONST:
+ {
+ ASTVec tmp_res(num_bits);
#ifndef NATIVE_C_ARITH
- CBV bv = term.GetBVConst();
- for(unsigned int i = 0; i < num_bits; i++){
- tmp_res[i] = CONSTANTBV::BitVector_bit_test(bv,i) ? ASTTrue : ASTFalse;
- }
+ CBV bv = term.GetBVConst();
+ for (unsigned int i = 0; i < num_bits; i++)
+ {
+ tmp_res[i] = CONSTANTBV::BitVector_bit_test(bv, i) ? ASTTrue : ASTFalse;
+ }
#else
- const unsigned long long int c = term.GetBVConst();
- unsigned long long int bitmask = 0x00000000000000001LL;
- for (unsigned int i = 0; i < num_bits; i++, bitmask <<= 1)
- tmp_res[i] = ((c & (bitmask)) ? ASTTrue : ASTFalse);
+ const unsigned long long int c = term.GetBVConst();
+ unsigned long long int bitmask = 0x00000000000000001LL;
+ for (unsigned int i = 0; i < num_bits; i++, bitmask <<= 1)
+ tmp_res[i] = ((c & (bitmask)) ? ASTTrue : ASTFalse);
#endif
- result = CreateNode(BOOLVEC, tmp_res);
- break;
- }
- case BOOLVEC: {
- cerr << "Hit a boolvec! what to do?" << endl;
- break;
- }
- default:
- FatalError("BBTerm: Illegal kind to BBTerm",term);
- }
-
- //if(result == ASTJunk)
- // cout<<"result does not change"<<endl;
- // cout << "================" << endl << "BBTerm:" << term << endl;
- // cout << "----------------" << endl << "BBTerm result:";
- // lpvec(result);
- // cout << endl;
-
- return (BBTermMemo[term] = result);
+ result = CreateNode(BOOLVEC, tmp_res);
+ break;
+ }
+ case BOOLVEC:
+ {
+ cerr << "Hit a boolvec! what to do?" << endl;
+ break;
+ }
+ default:
+ FatalError("BBTerm: Illegal kind to BBTerm", term);
+ }
+
+ //if(result == ASTJunk)
+ // cout<<"result does not change"<<endl;
+ // cout << "================" << endl << "BBTerm:" << term << endl;
+ // cout << "----------------" << endl << "BBTerm result:";
+ // lpvec(result);
+ // cout << endl;
+
+ return (BBTermMemo[term] = result);
}
const ASTNode BeevMgr::BBForm(const ASTNode& form)
{
- ASTNodeMap::iterator it = BBFormMemo.find(form);
- if (it != BBFormMemo.end()) {
- // already there. Just return it.
- return it->second;
- }
-
- ASTNode result = ASTUndefined;
-
- Kind k = form.GetKind();
- if (!is_Form_kind(k)) {
- FatalError("BBForm: Illegal kind: ",form);
- }
-
- // Not returning until end, and memoizing everything, makes it easier
- // to trace coherently.
-
- // Various special cases
- switch (k) {
- case TRUE:
- case FALSE: {
- result = form;
- break;
- }
-
- case SYMBOL:
- //printf("bit-blasting SYMBOL\n");
- if (form.GetType() != BOOLEAN_TYPE) {
- FatalError("BBForm: Symbol represents more than one bit", form);
- }
-
- result = form;
- break;
-
- case BVGETBIT: {
- // exactly two children
- const ASTNode bbchild = BBTerm(form[0]);
- unsigned int index = GetUnsignedConst(form[1]);
- result = bbchild[index];
- break;
- }
-
- case NOT:
- result = CreateSimpNot(BBForm(form[0]));
- break;
-
- case ITE:
- // FIXME: SHould this be CreateSimpITE?
- result = CreateNode(ITE, BBForm(form[0]), BBForm(form[1]), BBForm(form[2]));
- break;
-
- case AND:
- case OR:
- case NAND:
- case NOR:
- case IFF:
- case XOR:
- case IMPLIES: {
- //printf("bit-blasting AND or OR\n");
- ASTVec bbkids; // bit-blasted children (formulas)
-
- // FIXME: Put in fast exits for AND/OR/NAND/NOR/IMPLIES
- ASTVec::const_iterator kids_end = form.end();
- for (ASTVec::const_iterator it = form.begin(); it != kids_end; it++) {
- bbkids.push_back(BBForm(*it));
- }
- result = CreateSimpForm(k, bbkids);
- break;
- }
-
- case NEQ: {
- ASTNode bbkid = BBForm(CreateNode(EQ, form.GetChildren()));
- result = CreateSimpNot(bbkid);
- break;
- }
-
- case EQ: {
- //printf("bit-blasting EQ\n");
- //form.LispPrint(cout, 0);
- // Common code for binary operations
- // FIXME: This ought to be in a semantic analysis phase.
- //printf("spot01\n");
- const ASTNode left = BBTerm(form[0]);
- //printf("spot02\n");
- const ASTNode right = BBTerm(form[1]);
- //printf("spot03\n");
- if (left.Degree() != right.Degree()) {
- cerr << "BBForm: Size mismatch" << endl << form[0] << endl << form[1] << endl;
- FatalError("",ASTUndefined);
- }
- result = BBEQ(left.GetChildren(), right.GetChildren());
- //printf("spot04\n");
- break;
- }
-
- case BVLE:
- case BVGE:
- case BVGT:
- case BVLT:
- case BVSLE:
- case BVSGE:
- case BVSGT:
- case BVSLT: {
- result = BBcompare(form);
- break;
- }
- default:
- FatalError("BBForm: Illegal kind: ", form);
- break;
- }
-
- // cout << "================" << endl
- // << "BBForm: " << form << endl
- // << "----------------" << endl
- // << "BBForm Result: " << result << endl;
-
- return (BBFormMemo[form] = result);
+ ASTNodeMap::iterator it = BBFormMemo.find(form);
+ if (it != BBFormMemo.end())
+ {
+ // already there. Just return it.
+ return it->second;
+ }
+
+ ASTNode result = ASTUndefined;
+
+ Kind k = form.GetKind();
+ if (!is_Form_kind(k))
+ {
+ FatalError("BBForm: Illegal kind: ", form);
+ }
+
+ // Not returning until end, and memoizing everything, makes it easier
+ // to trace coherently.
+
+ // Various special cases
+ switch (k)
+ {
+ case TRUE:
+ case FALSE:
+ {
+ result = form;
+ break;
+ }
+
+ case SYMBOL:
+ //printf("bit-blasting SYMBOL\n");
+ if (form.GetType() != BOOLEAN_TYPE)
+ {
+ FatalError("BBForm: Symbol represents more than one bit", form);
+ }
+
+ result = form;
+ break;
+
+ case BVGETBIT:
+ {
+ // exactly two children
+ const ASTNode bbchild = BBTerm(form[0]);
+ unsigned int index = GetUnsignedConst(form[1]);
+ result = bbchild[index];
+ break;
+ }
+
+ case NOT:
+ result = CreateSimpNot(BBForm(form[0]));
+ break;
+
+ case ITE:
+ // FIXME: SHould this be CreateSimpITE?
+ result = CreateNode(ITE, BBForm(form[0]), BBForm(form[1]), BBForm(form[2]));
+ break;
+
+ case AND:
+ case OR:
+ case NAND:
+ case NOR:
+ case IFF:
+ case XOR:
+ case IMPLIES:
+ {
+ //printf("bit-blasting AND or OR\n");
+ ASTVec bbkids; // bit-blasted children (formulas)
+
+ // FIXME: Put in fast exits for AND/OR/NAND/NOR/IMPLIES
+ ASTVec::const_iterator kids_end = form.end();
+ for (ASTVec::const_iterator it = form.begin(); it != kids_end; it++)
+ {
+ bbkids.push_back(BBForm(*it));
+ }
+ result = CreateSimpForm(k, bbkids);
+ break;
+ }
+
+ case NEQ:
+ {
+ ASTNode bbkid = BBForm(CreateNode(EQ, form.GetChildren()));
+ result = CreateSimpNot(bbkid);
+ break;
+ }
+
+ case EQ:
+ {
+ //printf("bit-blasting EQ\n");
+ //form.LispPrint(cout, 0);
+ // Common code for binary operations
+ // FIXME: This ought to be in a semantic analysis phase.
+ //printf("spot01\n");
+ const ASTNode left = BBTerm(form[0]);
+ //printf("spot02\n");
+ const ASTNode right = BBTerm(form[1]);
+ //printf("spot03\n");
+ if (left.Degree() != right.Degree())
+ {
+ cerr << "BBForm: Size mismatch" << endl << form[0] << endl << form[1] << endl;
+ FatalError("", ASTUndefined);
+ }
+ result = BBEQ(left.GetChildren(), right.GetChildren());
+ //printf("spot04\n");
+ break;
+ }
+
+ case BVLE:
+ case BVGE:
+ case BVGT:
+ case BVLT:
+ case BVSLE:
+ case BVSGE:
+ case BVSGT:
+ case BVSLT:
+ {
+ result = BBcompare(form);
+ break;
+ }
+ default:
+ FatalError("BBForm: Illegal kind: ", form);
+ break;
+ }
+
+ // cout << "================" << endl
+ // << "BBForm: " << form << endl
+ // << "----------------" << endl
+ // << "BBForm Result: " << result << endl;
+
+ return (BBFormMemo[form] = result);
}
-
+
// Bit blast a sum of two equal length BVs.
// Update sum vector destructively with new sum.
void BeevMgr::BBPlus2(ASTVec& sum, const ASTVec& y, ASTNode cin)
{
-// cout << "Bitblasting plus. Operand 1: " << endl;
-// lpvec(sum);
-// cout << endl << " operand 2: " << endl;
-// lpvec(y);
-// cout << endl << "carry: " << endl << cin << endl;
-
-
- int n = sum.size();
- // ASSERT: y.size() == x.size()
- // FIXME: Don't bother computing i+1 carry, which is discarded.
- for (int i = 0; i < n; i++) {
- ASTNode nextcin = Majority(sum[i], y[i], cin);
- sum[i] = CreateSimpForm(XOR, CreateSimpForm(XOR, sum[i], y[i]), cin);
- cin = nextcin;
- }
-
-// cout << "----------------" << endl << "Result: " << endl;
-// lpvec(sum);
-// cout << endl;
+ // cout << "Bitblasting plus. Operand 1: " << endl;
+ // lpvec(sum);
+ // cout << endl << " operand 2: " << endl;
+ // lpvec(y);
+ // cout << endl << "carry: " << endl << cin << endl;
+
+
+ int n = sum.size();
+ // ASSERT: y.size() == x.size()
+ // FIXME: Don't bother computing i+1 carry, which is discarded.
+ for (int i = 0; i < n; i++)
+ {
+ ASTNode nextcin = Majority(sum[i], y[i], cin);
+ sum[i] = CreateSimpForm(XOR, CreateSimpForm(XOR, sum[i], y[i]), cin);
+ cin = nextcin;
+ }
+
+ // cout << "----------------" << endl << "Result: " << endl;
+ // lpvec(sum);
+ // cout << endl;
}
// Stores result - x in result, destructively
void BeevMgr::BBSub(ASTVec& result, const ASTVec& y)
{
- ASTVec compsubtrahend = BBNeg(y);
- BBPlus2(result, compsubtrahend, ASTTrue);
+ ASTVec compsubtrahend = BBNeg(y);
+ BBPlus2(result, compsubtrahend, ASTTrue);
}
// Add one bit
ASTVec BeevMgr::BBAddOneBit(ASTVec& x, ASTNode cin)
{
- ASTVec result = ASTVec(0);
- ASTVec::const_iterator itend = x.end();
- for (ASTVec::const_iterator it = x.begin(); it < itend; it++) {
- ASTNode nextcin = CreateSimpForm(AND, *it, cin);
- result.push_back(CreateSimpForm(XOR, *it, cin));
- cin = nextcin;
- }
- // FIXME: unnecessary array copy on return?
- return result;
+ ASTVec result = ASTVec(0);
+ ASTVec::const_iterator itend = x.end();
+ for (ASTVec::const_iterator it = x.begin(); it < itend; it++)
+ {
+ ASTNode nextcin = CreateSimpForm(AND, *it, cin);
+ result.push_back(CreateSimpForm(XOR, *it, cin));
+ cin = nextcin;
+ }
+ // FIXME: unnecessary array copy on return?
+ return result;
}
// Increment bit-blasted vector and return result.
ASTVec BeevMgr::BBInc(ASTVec& x)
{
- return BBAddOneBit(x, ASTTrue);
+ return BBAddOneBit(x, ASTTrue);
}
// Return formula for majority function of three bits.
// Pass arguments by reference to reduce refcounting.
-ASTNode BeevMgr::Majority(const ASTNode& a, const ASTNode& b,const ASTNode& c)
+ASTNode BeevMgr::Majority(const ASTNode& a, const ASTNode& b, const ASTNode& c)
{
- // Checking explicitly for constant a, b and c could
- // be more efficient, because they are repeated in the logic.
- if (ASTTrue == a) {
- return CreateSimpForm(OR, b, c);
- }
- else if (ASTFalse == a) {
- return CreateSimpForm(AND, b, c);
- }
- else if (ASTTrue == b) {
- return CreateSimpForm(OR, a, c);
- }
- else if (ASTFalse == b) {
- return CreateSimpForm(AND, a, c);
- }
- else if (ASTTrue == c) {
- return CreateSimpForm(OR, a, b);
- }
- else if (ASTFalse == c) {
- return CreateSimpForm(AND, a, b);
- }
- // there are lots more simplifications, but I'm not sure they're
- // worth doing explicitly (e.g., a = b, a = ~b, etc.)
- else {
- return
- CreateSimpForm(OR,
- CreateSimpForm(AND, a, b),
- CreateSimpForm(AND, b, c),
- CreateSimpForm(AND, a, c));
- }
+ // Checking explicitly for constant a, b and c could
+ // be more efficient, because they are repeated in the logic.
+ if (ASTTrue == a)
+ {
+ return CreateSimpForm(OR, b, c);
+ }
+ else if (ASTFalse == a)
+ {
+ return CreateSimpForm(AND, b, c);
+ }
+ else if (ASTTrue == b)
+ {
+ return CreateSimpForm(OR, a, c);
+ }
+ else if (ASTFalse == b)
+ {
+ return CreateSimpForm(AND, a, c);
+ }
+ else if (ASTTrue == c)
+ {
+ return CreateSimpForm(OR, a, b);
+ }
+ else if (ASTFalse == c)
+ {
+ return CreateSimpForm(AND, a, b);
+ }
+ // there are lots more simplifications, but I'm not sure they're
+ // worth doing explicitly (e.g., a = b, a = ~b, etc.)
+ else
+ {
+ return CreateSimpForm(OR, CreateSimpForm(AND, a, b), CreateSimpForm(AND, b, c), CreateSimpForm(AND, a, c));
+ }
}
-
// Bitwise complement
ASTVec BeevMgr::BBNeg(const ASTVec& x)
{
- ASTVec result = ASTVec(0); // FIXME: faster to preallocate n entries?
- // Negate each bit.
- ASTVec::const_iterator xend = x.end();
- for (ASTVec::const_iterator it = x.begin(); it < xend; it++) {
- result.push_back(CreateSimpNot(*it));
- }
- // FIXME: unecessary array copy when it returns?
- return result;
+ ASTVec result = ASTVec(0); // FIXME: faster to preallocate n entries?
+ // Negate each bit.
+ ASTVec::const_iterator xend = x.end();
+ for (ASTVec::const_iterator it = x.begin(); it < xend; it++)
+ {
+ result.push_back(CreateSimpNot(*it));
+ }
+ // FIXME: unecessary array copy when it returns?
+ return result;
}
// Compute unary minus
ASTVec BeevMgr::BBUminus(const ASTVec& x)
{
- ASTVec xneg = BBNeg(x);
- return BBInc(xneg);
+ ASTVec xneg = BBNeg(x);
+ return BBInc(xneg);
}
// Multiply two bitblasted numbers
ASTVec BeevMgr::BBMult(const ASTVec& x, const ASTVec& y)
{
- ASTVec ycopy(y);
- ASTVec::const_iterator xend = x.end();
- ASTVec::const_iterator xit = x.begin();
- // start prod with first partial product.
- // FIXME: This is unnecessary. Clean it up.
- ASTVec prod = ASTVec(BBAndBit(y, *xit));
- // start loop at next bit.
- for(xit++; xit < xend; xit++) {
- // shift first
- BBLShift(ycopy);
-
- if (ASTFalse == *xit) {
- // If this bit is zero, the partial product will
- // be zero. No reason to add that in.
- continue;
- }
-
- ASTVec pprod = BBAndBit(ycopy, *xit);
- // accumulate in the product.
- BBPlus2(prod, pprod, ASTFalse);
- }
- return prod;
+ ASTVec ycopy(y);
+ ASTVec::const_iterator xend = x.end();
+ ASTVec::const_iterator xit = x.begin();
+ // start prod with first partial product.
+ // FIXME: This is unnecessary. Clean it up.
+ ASTVec prod = ASTVec(BBAndBit(y, *xit));
+ // start loop at next bit.
+ for (xit++; xit < xend; xit++)
+ {
+ // shift first
+ BBLShift(ycopy);
+
+ if (ASTFalse == *xit)
+ {
+ // If this bit is zero, the partial product will
+ // be zero. No reason to add that in.
+ continue;
+ }
+
+ ASTVec pprod = BBAndBit(ycopy, *xit);
+ // accumulate in the product.
+ BBPlus2(prod, pprod, ASTFalse);
+ }
+ return prod;
}
// This implements a variant of binary long division.
// recursion depth.
void BeevMgr::BBDivMod(const ASTVec &y, const ASTVec &x, ASTVec &q, ASTVec &r, unsigned int rwidth)
{
- unsigned int width = y.size();
- if (rwidth == 0) {
- // When we have shifted the entire width, y is guaranteed to be 0.
- q = BBfill(width, ASTFalse);
- r = BBfill(width, ASTFalse);
- }
- else {
- ASTVec q1, r1;
- ASTVec yrshift1(y);
- BBRShift(yrshift1);
-
- // recursively divide y/2 by x.
- BBDivMod(yrshift1, x, q1, r1, rwidth-1);
-
- ASTVec q1lshift1(q1);
- BBLShift(q1lshift1);
-
- ASTVec r1lshift1(r1);
- BBLShift(r1lshift1);
-
- ASTVec r1lshift1plusyodd = BBAddOneBit(r1lshift1, y[0]);
- ASTVec rminusx(r1lshift1plusyodd);
- BBSub(rminusx, x);
-
- // Adjusted q, r values when when r is too large.
- ASTNode rtoolarge = BBBVLE(x, r1lshift1plusyodd, false);
- ASTVec ygtrxqval = BBITE(rtoolarge, BBInc(q1lshift1), q1lshift1);
- ASTVec ygtrxrval = BBITE(rtoolarge, rminusx, r1lshift1plusyodd);
-
- // q & r values when y >= x
- ASTNode yeqx = BBEQ(y, x);
- // *** Problem: the bbfill for qval is wrong. Should be 1, not -1.
- ASTVec one = BBfill(width, ASTFalse);
- one[0] = ASTTrue;
- ASTVec notylessxqval = BBITE(yeqx, one, ygtrxqval);
- ASTVec notylessxrval = BBITE(yeqx, BBfill(width, ASTFalse), ygtrxrval);
- // y < x <=> not x >= y.
- ASTNode ylessx = CreateSimpNot(BBBVLE(x, y, false));
- // final values of q and r
- q = BBITE(ylessx, BBfill(width, ASTFalse), notylessxqval);
- r = BBITE(ylessx, y, notylessxrval);
- }
+ unsigned int width = y.size();
+ if (rwidth == 0)
+ {
+ // When we have shifted the entire width, y is guaranteed to be 0.
+ q = BBfill(width, ASTFalse);
+ r = BBfill(width, ASTFalse);
+ }
+ else
+ {
+ ASTVec q1, r1;
+ ASTVec yrshift1(y);
+ BBRShift(yrshift1);
+
+ // recursively divide y/2 by x.
+ BBDivMod(yrshift1, x, q1, r1, rwidth - 1);
+
+ ASTVec q1lshift1(q1);
+ BBLShift(q1lshift1);
+
+ ASTVec r1lshift1(r1);
+ BBLShift(r1lshift1);
+
+ ASTVec r1lshift1plusyodd = BBAddOneBit(r1lshift1, y[0]);
+ ASTVec rminusx(r1lshift1plusyodd);
+ BBSub(rminusx, x);
+
+ // Adjusted q, r values when when r is too large.
+ ASTNode rtoolarge = BBBVLE(x, r1lshift1plusyodd, false);
+ ASTVec ygtrxqval = BBITE(rtoolarge, BBInc(q1lshift1), q1lshift1);
+ ASTVec ygtrxrval = BBITE(rtoolarge, rminusx, r1lshift1plusyodd);
+
+ // q & r values when y >= x
+ ASTNode yeqx = BBEQ(y, x);
+ // *** Problem: the bbfill for qval is wrong. Should be 1, not -1.
+ ASTVec one = BBfill(width, ASTFalse);
+ one[0] = ASTTrue;
+ ASTVec notylessxqval = BBITE(yeqx, one, ygtrxqval);
+ ASTVec notylessxrval = BBITE(yeqx, BBfill(width, ASTFalse), ygtrxrval);
+ // y < x <=> not x >= y.
+ ASTNode ylessx = CreateSimpNot(BBBVLE(x, y, false));
+ // final values of q and r
+ q = BBITE(ylessx, BBfill(width, ASTFalse), notylessxqval);
+ r = BBITE(ylessx, y, notylessxrval);
+ }
}
// build ITE's (ITE cond then[i] else[i]) for each i.
ASTVec BeevMgr::BBITE(const ASTNode& cond, const ASTVec& thn, const ASTVec& els)
{
- // Fast exits.
- if (ASTTrue == cond) {
- return thn;
- }
- else if (ASTFalse == cond) {
- return els;
- }
-
- ASTVec result(0);
- ASTVec::const_iterator th_it_end = thn.end();
- ASTVec::const_iterator el_it = els.begin();
- for (ASTVec::const_iterator th_it = thn.begin(); th_it < th_it_end; th_it++, el_it++) {
- result.push_back(CreateSimpForm(ITE, cond, *th_it, *el_it));
- }
- return result;
+ // Fast exits.
+ if (ASTTrue == cond)
+ {
+ return thn;
+ }
+ else if (ASTFalse == cond)
+ {
+ return els;
+ }
+
+ ASTVec result(0);
+ ASTVec::const_iterator th_it_end = thn.end();
+ ASTVec::const_iterator el_it = els.begin();
+ for (ASTVec::const_iterator th_it = thn.begin(); th_it < th_it_end; th_it++, el_it++)
+ {
+ result.push_back(CreateSimpForm(ITE, cond, *th_it, *el_it));
+ }
+ return result;
}
// AND each bit of vector y with single bit b and return the result.
ASTVec BeevMgr::BBAndBit(const ASTVec& y, ASTNode b)
{
- ASTVec result(0);
-
- if (ASTTrue == b) {
- return y;
- }
- // FIXME: put in fast exits when b is constant 0.
-
- ASTVec::const_iterator yend = y.end();
- for(ASTVec::const_iterator yit = y.begin(); yit < yend; yit++) {
- result.push_back(CreateSimpForm(AND, *yit, b));
- }
- return result;
-}
+ ASTVec result(0);
+
+ if (ASTTrue == b)
+ {
+ return y;
+ }
+ // FIXME: put in fast exits when b is constant 0.
+ ASTVec::const_iterator yend = y.end();
+ for (ASTVec::const_iterator yit = y.begin(); yit < yend; yit++)
+ {
+ result.push_back(CreateSimpForm(AND, *yit, b));
+ }
+ return result;
+}
// Workhorse for comparison routines. This does a signed BVLE if is_signed
// is true, else it's unsigned. All other comparison operators can be reduced
// of the bits.
ASTNode BeevMgr::BBBVLE(const ASTVec& left, const ASTVec& right, bool is_signed)
{
- // "thisbit" represents BVLE of the suffixes of the BVs
- // from that position . if R < L, return TRUE, else if L < R
- // return FALSE, else return BVLE of lower-order bits. MSB is
- // treated separately, because signed comparison is done by
- // complementing the MSB of each BV, then doing an unsigned
- // comparison.
- ASTVec::const_iterator lit = left.begin();
- ASTVec::const_iterator litend = left.end();
- ASTVec::const_iterator rit = right.begin();
- ASTNode prevbit = ASTTrue;
- for ( ; lit < litend-1; lit++, rit++) {
- ASTNode neglit = CreateSimpNot(*lit);
- ASTNode thisbit =
- CreateSimpForm(OR,
- CreateSimpForm(AND,neglit,*rit), // TRUE if l < r
- CreateSimpForm(AND,
- CreateSimpForm(OR, neglit, *rit), // false if not equal
- prevbit)); // else prevbit
- prevbit = thisbit;
- }
-
- // Handle MSB -- negate MSBs if signed comparison
- // FIXME: make into refs after it's debugged.
- ASTNode lmsb = *lit;
- ASTNode rmsb = *rit;
- if (is_signed) {
- lmsb = CreateSimpNot(*lit);
- rmsb = CreateSimpNot(*rit);
- }
-
- ASTNode neglmsb = CreateSimpNot(lmsb);
- ASTNode msb =
- CreateSimpForm(OR,
- CreateSimpForm(AND,neglmsb, rmsb), // TRUE if l < r
- CreateSimpForm(AND,
- CreateSimpForm(OR, neglmsb, rmsb), // false if not equal
- prevbit)); // else prevbit
- return msb;
+ // "thisbit" represents BVLE of the suffixes of the BVs
+ // from that position . if R < L, return TRUE, else if L < R
+ // return FALSE, else return BVLE of lower-order bits. MSB is
+ // treated separately, because signed comparison is done by
+ // complementing the MSB of each BV, then doing an unsigned
+ // comparison.
+ ASTVec::const_iterator lit = left.begin();
+ ASTVec::const_iterator litend = left.end();
+ ASTVec::const_iterator rit = right.begin();
+ ASTNode prevbit = ASTTrue;
+ for (; lit < litend - 1; lit++, rit++)
+ {
+ ASTNode neglit = CreateSimpNot(*lit);
+ ASTNode thisbit = CreateSimpForm(OR, CreateSimpForm(AND, neglit, *rit), // TRUE if l < r
+ CreateSimpForm(AND, CreateSimpForm(OR, neglit, *rit), // false if not equal
+ prevbit)); // else prevbit
+ prevbit = thisbit;
+ }
+
+ // Handle MSB -- negate MSBs if signed comparison
+ // FIXME: make into refs after it's debugged.
+ ASTNode lmsb = *lit;
+ ASTNode rmsb = *rit;
+ if (is_signed)
+ {
+ lmsb = CreateSimpNot(*lit);
+ rmsb = CreateSimpNot(*rit);
+ }
+
+ ASTNode neglmsb = CreateSimpNot(lmsb);
+ ASTNode msb = CreateSimpForm(OR, CreateSimpForm(AND, neglmsb, rmsb), // TRUE if l < r
+ CreateSimpForm(AND, CreateSimpForm(OR, neglmsb, rmsb), // false if not equal
+ prevbit)); // else prevbit
+ return msb;
}
// Left shift by 1 within fixed field inserting zeros at LSB.
// Fixme: generalize to n bits
void BeevMgr::BBLShift(ASTVec& x)
{
- // left shift x (destructively) within width.
- // loop backwards so that copy to self works correctly. (DON'T use STL insert!)
- ASTVec::iterator xbeg = x.begin();
- for(ASTVec::iterator xit = x.end()-1; xit > xbeg; xit--) {
- *xit = *(xit-1);
- }
- *xbeg = ASTFalse; // new LSB is zero.
- // cout << "Shifted result" << endl;
- // lpvec(x);
+ // left shift x (destructively) within width.
+ // loop backwards so that copy to self works correctly. (DON'T use STL insert!)
+ ASTVec::iterator xbeg = x.begin();
+ for (ASTVec::iterator xit = x.end() - 1; xit > xbeg; xit--)
+ {
+ *xit = *(xit - 1);
+ }
+ *xbeg = ASTFalse; // new LSB is zero.
+ // cout << "Shifted result" << endl;
+ // lpvec(x);
}
// Left shift within fixed field inserting zeros at LSB.
// Writes result into first argument.
- void BeevMgr::BBLShift(ASTVec& x, unsigned int shift)
+void BeevMgr::BBLShift(ASTVec& x, unsigned int shift)
{
- // left shift x (destructively) within width.
- // loop backwards so that copy to self works correctly. (DON'T use STL insert!)
- ASTVec::iterator xbeg = x.begin();
- ASTVec::iterator xit = x.end()-1;
- for(; xit >= xbeg; xit--) {
- if (xit-shift >= xbeg)
- *xit = *(xit-shift);
- else
- *xit= ASTFalse; // new LSB is zero.
- }
+ // left shift x (destructively) within width.
+ // loop backwards so that copy to self works correctly. (DON'T use STL insert!)
+ ASTVec::iterator xbeg = x.begin();
+ ASTVec::iterator xit = x.end() - 1;
+ for (; xit >= xbeg; xit--)
+ {
+ if (xit - shift >= xbeg)
+ *xit = *(xit - shift);
+ else
+ *xit = ASTFalse; // new LSB is zero.
+ }
}
// Right shift within fixed field inserting zeros at MSB.
// Writes result into first argument.
- void BeevMgr::BBRShift(ASTVec& x, unsigned int shift)
+void BeevMgr::BBRShift(ASTVec& x, unsigned int shift)
{
- // right shift x (destructively) within width.
- ASTVec::iterator xend = x.end();
- ASTVec::iterator xit = x.begin();
- for(; xit < xend; xit++) {
- if (xit+shift < xend)
- *xit = *(xit+shift);
- else
- *xit= ASTFalse; // new MSB is zero.
- }
+ // right shift x (destructively) within width.
+ ASTVec::iterator xend = x.end();
+ ASTVec::iterator xit = x.begin();
+ for (; xit < xend; xit++)
+ {
+ if (xit + shift < xend)
+ *xit = *(xit + shift);
+ else
+ *xit = ASTFalse; // new MSB is zero.
+ }
}
-
-
-
// Right shift by 1 within fixed field, inserting new zeros at MSB.
// Writes result into first argument.
// Fixme: generalize to n bits.
void BeevMgr::BBRShift(ASTVec& x)
{
- ASTVec::iterator xend = x.end() - 1;
- ASTVec::iterator xit = x.begin();
- for( ; xit < xend; xit++) {
- *xit = *(xit+1);
- }
- *xit = ASTFalse; // new MSB is zero.
+ ASTVec::iterator xend = x.end() - 1;
+ ASTVec::iterator xit = x.begin();
+ for (; xit < xend; xit++)
+ {
+ *xit = *(xit + 1);
+ }
+ *xit = ASTFalse; // new MSB is zero.
}
-// Return bit-blasted form for BVLE, BVGE, BVGT, SBLE, etc.
-ASTNode BeevMgr::BBcompare(const ASTNode& form) {
- const ASTNode lnode = BBTerm(form[0]);
- const ASTNode rnode = BBTerm(form[1]);
- const ASTVec& left = lnode.GetChildren();
- const ASTVec& right = rnode.GetChildren();
-
- //const ASTVec& left = BBTerm(form[0]).GetChildren();
- //const ASTVec& right = BBTerm(form[1]).GetChildren();
-
- Kind k = form.GetKind();
- switch(k) {
- case BVLE: { return BBBVLE(left, right, false); break; }
- case BVGE: { return BBBVLE(right, left, false); break; }
- case BVGT: { return CreateSimpNot(BBBVLE(left, right, false)); break; }
- case BVLT: { return CreateSimpNot(BBBVLE(right, left, false)); break; }
- case BVSLE: { return BBBVLE(left, right, true); break; }
- case BVSGE: { return BBBVLE(right, left, true); break; }
- case BVSGT: { return CreateSimpNot(BBBVLE(left, right, true)); break; }
- case BVSLT: { return CreateSimpNot(BBBVLE(right, left, true)); break; }
- default:
- cerr << "BBCompare: Illegal kind" << form << endl;
- FatalError("",ASTUndefined);
- }
- return ASTUndefined;
+// Return bit-blasted form for BVLE, BVGE, BVGT, SBLE, etc.
+ASTNode BeevMgr::BBcompare(const ASTNode& form)
+{
+ const ASTNode lnode = BBTerm(form[0]);
+ const ASTNode rnode = BBTerm(form[1]);
+ const ASTVec& left = lnode.GetChildren();
+ const ASTVec& right = rnode.GetChildren();
+
+ //const ASTVec& left = BBTerm(form[0]).GetChildren();
+ //const ASTVec& right = BBTerm(form[1]).GetChildren();
+
+ Kind k = form.GetKind();
+ switch (k)
+ {
+ case BVLE:
+ {
+ return BBBVLE(left, right, false);
+ break;
+ }
+ case BVGE:
+ {
+ return BBBVLE(right, left, false);
+ break;
+ }
+ case BVGT:
+ {
+ return CreateSimpNot(BBBVLE(left, right, false));
+ break;
+ }
+ case BVLT:
+ {
+ return CreateSimpNot(BBBVLE(right, left, false));
+ break;
+ }
+ case BVSLE:
+ {
+ return BBBVLE(left, right, true);
+ break;
+ }
+ case BVSGE:
+ {
+ return BBBVLE(right, left, true);
+ break;
+ }
+ case BVSGT:
+ {
+ return CreateSimpNot(BBBVLE(left, right, true));
+ break;
+ }
+ case BVSLT:
+ {
+ return CreateSimpNot(BBBVLE(right, left, true));
+ break;
+ }
+ default:
+ cerr << "BBCompare: Illegal kind" << form << endl;
+ FatalError("", ASTUndefined);
+ }
+ return ASTUndefined;
}
-
// return a vector with n copies of fillval
ASTVec BeevMgr::BBfill(unsigned int width, ASTNode fillval)
{
- ASTVec zvec(width, fillval);
- return zvec;
+ ASTVec zvec(width, fillval);
+ return zvec;
}
ASTNode BeevMgr::BBEQ(const ASTVec& left, const ASTVec& right)
{
- ASTVec andvec;
- ASTVec::const_iterator lit = left.begin();
- ASTVec::const_iterator litend = left.end();
- ASTVec::const_iterator rit = right.begin();
-
- if(left.size() > 1) {
- for(; lit != litend; lit++, rit++) {
- ASTNode biteq = CreateSimpForm(IFF, *lit, *rit);
- // fast path exit
- if (biteq == ASTFalse) {
- return ASTFalse;
- }
- else {
- andvec.push_back(biteq);
- }
- }
- ASTNode n = CreateSimpForm(AND, andvec);
- return n;
- }
- else
- return CreateSimpForm(IFF,*lit,*rit);
+ ASTVec andvec;
+ ASTVec::const_iterator lit = left.begin();
+ ASTVec::const_iterator litend = left.end();
+ ASTVec::const_iterator rit = right.begin();
+
+ if (left.size() > 1)
+ {
+ for (; lit != litend; lit++, rit++)
+ {
+ ASTNode biteq = CreateSimpForm(IFF, *lit, *rit);
+ // fast path exit
+ if (biteq == ASTFalse)
+ {
+ return ASTFalse;
+ }
+ else
+ {
+ andvec.push_back(biteq);
+ }
+ }
+ ASTNode n = CreateSimpForm(AND, andvec);
+ return n;
+ }
+ else
+ return CreateSimpForm(IFF, *lit, *rit);
}
} // BEEV namespace
// children to reduce growing of vectors.
//BEEV::ASTVec child_stack;
-namespace BEEV {
-
- ASTNode BeevMgr::CreateSimpForm(Kind kind, ASTVec &children = _empty_ASTVec) {
- if (_disable_simpbool) {
- return CreateNode(kind, children);
- }
- else {
- switch (kind) {
- case NOT: return CreateSimpNot(children[0]); break;
- case AND: return CreateSimpAndOr(1, children); break;
- case OR: return CreateSimpAndOr(0, children); break;
- case NAND: return CreateSimpNot(CreateSimpAndOr(1, children)); break;
- case NOR: return CreateSimpNot(CreateSimpAndOr(0, children)); break;
- case IFF: {
- // Not sure children can ever be empty, but what the heck.
- // if (children.size() == 0) {
- // return ASTTrue;
- // }
- // Convert IFF to XOR ASAP to simplify flattening.
- children[0] = CreateSimpNot(children[0]);
- return CreateSimpXor(children); break;
- }
- case XOR:
- return CreateSimpXor(children); break;
- // FIXME: Earlier, check that this only has two arguments
- case IMPLIES: return CreateSimpAndOr(0, CreateSimpNot(children[0]), children[1]); break;
- case ITE: return CreateSimpFormITE(children[0], children[1], children[2]);
- default: return CreateNode(kind, children);
- }
- }
- }
-
- // specialized versions
-
- ASTNode BeevMgr::CreateSimpForm(Kind kind,
- const ASTNode& child0) {
- ASTVec children;
- //child_stack.clear(); // could just reset top pointer.
- children.push_back(child0);
- //child_stack.push_back(child0);
- return CreateSimpForm(kind, children);
- //return CreateSimpForm(kind, child_stack);
- }
-
- ASTNode BeevMgr::CreateSimpForm(Kind kind,
- const ASTNode& child0,
- const ASTNode& child1) {
- ASTVec children;
- //child_stack.clear(); // could just reset top pointer.
- children.push_back(child0);
- //child_stack.push_back(child0);
- children.push_back(child1);
- //child_stack.push_back(child1);
- return CreateSimpForm(kind, children);
- //return CreateSimpForm(kind, child_stack);
- }
-
-
- ASTNode BeevMgr::CreateSimpForm(Kind kind,
- const ASTNode& child0,
- const ASTNode& child1,
- const ASTNode& child2) {
- ASTVec children;
- //child_stack.clear(); // could just reset top pointer.
- children.push_back(child0);
- //child_stack.push_back(child0);
- children.push_back(child1);
- //child_stack.push_back(child1);
- children.push_back(child2);
- //child_stack.push_back(child2);
- return CreateSimpForm(kind, children);
- //return CreateSimpForm(kind, child_stack);
- }
-
- ASTNode BeevMgr::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); }
- }
- }
-
- // I don't think this is even called, since it called
- // CreateSimpAndOr instead of CreateSimpXor until 1/9/07 with no
- // ill effects. Calls seem to go to the version that takes a vector
- // of children.
- ASTNode BeevMgr::CreateSimpXor(const ASTNode& form1, const ASTNode& form2) {
- ASTVec children;
- children.push_back(form1);
- children.push_back(form2);
- return CreateSimpXor(children);
- }
-
- // Flatten (k ... (k ci cj) ...) to (k ... ci cj ...)
- // This is local to this file.
- ASTVec FlattenKind(Kind k, ASTVec &children) {
-
- ASTVec flat_children;
-
- ASTVec::const_iterator ch_end = children.end();
-
- bool fflag = 0; // ***Temp debugging
-
- // Experimental flattening code.
-
- for(ASTVec::iterator it = children.begin(); it != ch_end; it++) {
- Kind ck = it->GetKind();
- const ASTVec &gchildren = it->GetChildren();
- if (k == ck) {
- fflag = 1; // For selective debug printing (below).
- // append grandchildren to children
- flat_children.insert(flat_children.end(), gchildren.begin(), gchildren.end());
- }
- else {
- flat_children.push_back(*it);
- }
- }
-
- if (_trace_simpbool && fflag) {
- cout << "========" << endl;
- cout << "Flattening " << k << ":" << endl;
- lpvec(children);
-
- cout << "--------" << endl;
- cout << "Flattening result: " << endl;
- lpvec(flat_children);
- }
-
- // FIXME: This unnecessarily copies the array.
- return flat_children;
- }
-
- ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, const ASTNode& form1, const ASTNode& form2) {
- ASTVec children;
- children.push_back(form1);
- children.push_back(form2);
- return CreateSimpAndOr(IsAnd, children);
- }
-
- // FIXME: Could also handle (AND ... (NOT (OR ...) ...)
- ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, ASTVec &children) {
-
- Kind k = IsAnd ? AND : OR;
-
- if (_trace_simpbool) {
- cout << "========" << endl << "CreateSimpAndOr " << k << " ";
- lpvec(children);
- cout << endl;
- }
-
- ASTVec new_children;
-
- ASTVec flat_children;
- if (xor_flatten) {
- flat_children = FlattenKind(k, children);
- }
- else {
- flat_children = children;
- }
-
- // sort so that identical nodes occur in sequential runs, followed by
- // their negations.
- SortByExprNum(flat_children);
-
- ASTNode annihilator = (IsAnd ? ASTFalse : ASTTrue);
- ASTNode identity = (IsAnd ? ASTTrue : ASTFalse);
-
- ASTNode retval;
-
- ASTVec::const_iterator it_end = flat_children.end();
- ASTVec::const_iterator next_it;
- for(ASTVec::const_iterator it = flat_children.begin(); it != it_end; it = next_it) {
- next_it = it + 1;
- bool nextexists = (next_it < it_end);
-
- if (*it == annihilator) {
- retval = annihilator;
- if (_trace_simpbool) {
- cout << "returns " << retval << endl;
+namespace BEEV
+{
+
+ASTNode BeevMgr::CreateSimpForm(Kind kind, ASTVec &children = _empty_ASTVec)
+{
+ if (_disable_simpbool)
+ {
+ return CreateNode(kind, children);
+ }
+ else
+ {
+ switch (kind)
+ {
+ case NOT:
+ return CreateSimpNot(children[0]);
+ break;
+ case AND:
+ return CreateSimpAndOr(1, children);
+ break;
+ case OR:
+ return CreateSimpAndOr(0, children);
+ break;
+ case NAND:
+ return CreateSimpNot(CreateSimpAndOr(1, children));
+ break;
+ case NOR:
+ return CreateSimpNot(CreateSimpAndOr(0, children));
+ break;
+ case IFF:
+ {
+ // Not sure children can ever be empty, but what the heck.
+ // if (children.size() == 0) {
+ // return ASTTrue;
+ // }
+ // Convert IFF to XOR ASAP to simplify flattening.
+ children[0] = CreateSimpNot(children[0]);
+ return CreateSimpXor(children);
+ break;
+ }
+ case XOR:
+ return CreateSimpXor(children);
+ break;
+ // FIXME: Earlier, check that this only has two arguments
+ case IMPLIES:
+ return CreateSimpAndOr(0, CreateSimpNot(children[0]), children[1]);
+ break;
+ case ITE:
+ return CreateSimpFormITE(children[0], children[1], children[2]);
+ default:
+ return CreateNode(kind, children);
+ }
+ }
+}
+
+// specialized versions
+
+ASTNode BeevMgr::CreateSimpForm(Kind kind, const ASTNode& child0)
+{
+ ASTVec children;
+ //child_stack.clear(); // could just reset top pointer.
+ children.push_back(child0);
+ //child_stack.push_back(child0);
+ return CreateSimpForm(kind, children);
+ //return CreateSimpForm(kind, child_stack);
+}
+
+ASTNode BeevMgr::CreateSimpForm(Kind kind, const ASTNode& child0, const ASTNode& child1)
+{
+ ASTVec children;
+ //child_stack.clear(); // could just reset top pointer.
+ children.push_back(child0);
+ //child_stack.push_back(child0);
+ children.push_back(child1);
+ //child_stack.push_back(child1);
+ return CreateSimpForm(kind, children);
+ //return CreateSimpForm(kind, child_stack);
+}
+
+ASTNode BeevMgr::CreateSimpForm(Kind kind, const ASTNode& child0, const ASTNode& child1, const ASTNode& child2)
+{
+ ASTVec children;
+ //child_stack.clear(); // could just reset top pointer.
+ children.push_back(child0);
+ //child_stack.push_back(child0);
+ children.push_back(child1);
+ //child_stack.push_back(child1);
+ children.push_back(child2);
+ //child_stack.push_back(child2);
+ return CreateSimpForm(kind, children);
+ //return CreateSimpForm(kind, child_stack);
+}
+
+ASTNode BeevMgr::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);
+ }
+ }
+}
+
+// I don't think this is even called, since it called
+// CreateSimpAndOr instead of CreateSimpXor until 1/9/07 with no
+// ill effects. Calls seem to go to the version that takes a vector
+// of children.
+ASTNode BeevMgr::CreateSimpXor(const ASTNode& form1, const ASTNode& form2)
+{
+ ASTVec children;
+ children.push_back(form1);
+ children.push_back(form2);
+ return CreateSimpXor(children);
+}
+
+// Flatten (k ... (k ci cj) ...) to (k ... ci cj ...)
+// This is local to this file.
+ASTVec FlattenKind(Kind k, ASTVec &children)
+{
+
+ ASTVec flat_children;
+
+ ASTVec::const_iterator ch_end = children.end();
+
+ bool fflag = 0; // ***Temp debugging
+
+ // Experimental flattening code.
+
+ for (ASTVec::iterator it = children.begin(); it != ch_end; it++)
+ {
+ Kind ck = it->GetKind();
+ const ASTVec &gchildren = it->GetChildren();
+ if (k == ck)
+ {
+ fflag = 1; // For selective debug printing (below).
+ // append grandchildren to children
+ flat_children.insert(flat_children.end(), gchildren.begin(), gchildren.end());
+ }
+ else
+ {
+ flat_children.push_back(*it);
+ }
+ }
+
+ if (_trace_simpbool && fflag)
+ {
+ cout << "========" << endl;
+ cout << "Flattening " << k << ":" << endl;
+ lpvec(children);
+
+ cout << "--------" << endl;
+ cout << "Flattening result: " << endl;
+ lpvec(flat_children);
+ }
+
+ // FIXME: This unnecessarily copies the array.
+ return flat_children;
+}
+
+ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, const ASTNode& form1, const ASTNode& form2)
+{
+ ASTVec children;
+ children.push_back(form1);
+ children.push_back(form2);
+ return CreateSimpAndOr(IsAnd, children);
+}
+
+// FIXME: Could also handle (AND ... (NOT (OR ...) ...)
+ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, ASTVec &children)
+{
+
+ Kind k = IsAnd ? AND : OR;
+
+ if (_trace_simpbool)
+ {
+ cout << "========" << endl << "CreateSimpAndOr " << k << " ";
+ lpvec(children);
+ cout << endl;
+ }
+
+ ASTVec new_children;
+
+ ASTVec flat_children;
+ if (xor_flatten)
+ {
+ flat_children = FlattenKind(k, children);
+ }
+ else
+ {
+ flat_children = children;
+ }
+
+ // sort so that identical nodes occur in sequential runs, followed by
+ // their negations.
+ SortByExprNum(flat_children);
+
+ ASTNode annihilator = (IsAnd ? ASTFalse : ASTTrue);
+ ASTNode identity = (IsAnd ? ASTTrue : ASTFalse);
+
+ ASTNode retval;
+
+ ASTVec::const_iterator it_end = flat_children.end();
+ ASTVec::const_iterator next_it;
+ for (ASTVec::const_iterator it = flat_children.begin(); it != it_end; it = next_it)
+ {
+ next_it = it + 1;
+ bool nextexists = (next_it < it_end);
+
+ if (*it == annihilator)
+ {
+ retval = annihilator;
+ if (_trace_simpbool)
+ {
+ cout << "returns " << retval << endl;
+ }
+ return retval;
+ }
+ else if (*it == identity)
+ {
+ // just drop it
+ }
+ else if (nextexists && (*next_it == *it))
+ {
+ // drop it
+ // cout << "Dropping [" << it->GetNodeNum() << "]" << endl;
+ }
+ else if (nextexists && (next_it->GetKind() == NOT) && ((*next_it)[0] == *it))
+ {
+ // form and negation -- return FALSE for AND, TRUE for OR.
+ retval = annihilator;
+ // cout << "X and/or NOT X" << endl;
+ if (_trace_simpbool)
+ {
+ cout << "returns " << retval << endl;
+ }
+ return retval;
+ }
+ else
+ {
+ // add to children
+ new_children.push_back(*it);
+ }
+ }
+
+ // If we get here, we saw no annihilators, and children should
+ // be only the non-True nodes.
+ if (new_children.size() < 2)
+ {
+ if (0 == new_children.size())
+ {
+ retval = identity;
+ }
+ else
+ {
+ // there is just one child
+ retval = new_children[0];
+ }
+ }
+ else
+ {
+ // 2 or more children. Create a new node.
+ retval = CreateNode(IsAnd ? AND : OR, new_children);
+ }
+ if (_trace_simpbool)
+ {
+ cout << "returns " << retval << endl;
}
return retval;
- }
- else if (*it == identity) {
- // just drop it
- }
- else if (nextexists && (*next_it == *it)) {
- // drop it
- // cout << "Dropping [" << it->GetNodeNum() << "]" << endl;
- }
- else if (nextexists && (next_it->GetKind() == NOT) && ((*next_it)[0] == *it)) {
- // form and negation -- return FALSE for AND, TRUE for OR.
- retval = annihilator;
- // cout << "X and/or NOT X" << endl;
- if (_trace_simpbool) {
- cout << "returns " << retval << endl;
+}
+
+// Constant children are accumulated in "accumconst".
+ASTNode BeevMgr::CreateSimpXor(ASTVec &children)
+{
+
+ if (_trace_simpbool)
+ {
+ cout << "========" << endl << "CreateSimpXor ";
+ lpvec(children);
+ cout << endl;
+ }
+
+ ASTVec flat_children; // empty vector
+ ASTVec::const_iterator it_end = children.end();
+
+ if (xor_flatten)
+ {
+ flat_children = FlattenKind(XOR, children);
+ }
+ else
+ {
+ flat_children = children;
+ }
+
+ // sort so that identical nodes occur in sequential runs, followed by
+ // their negations.
+ SortByExprNum(flat_children);
+
+ ASTNode retval;
+
+ // This is the C Boolean value of all constant args seen. It is initially
+ // 0. TRUE children cause it to change value.
+ bool accumconst = 0;
+
+ ASTVec new_children;
+
+ it_end = flat_children.end();
+ ASTVec::iterator next_it;
+ for (ASTVec::iterator it = flat_children.begin(); it != it_end; it++)
+ {
+ next_it = it + 1;
+ bool nextexists = (next_it < it_end);
+
+ if (ASTTrue == *it)
+ {
+ accumconst = !accumconst;
+ }
+ else if (ASTFalse == *it)
+ {
+ // Ignore it
+ }
+ else if (nextexists && (*next_it == *it))
+ {
+ // x XOR x = FALSE. Skip current, write "false" into next_it
+ // so that it gets tossed, too.
+ *next_it = ASTFalse;
+ }
+ else if (nextexists && (next_it->GetKind() == NOT) && ((*next_it)[0] == *it))
+ {
+ // x XOR NOT x = TRUE. Skip current, write "true" into next_it
+ // so that it gets tossed, too.
+ *next_it = ASTTrue;
+ }
+ else if (NOT == it->GetKind())
+ {
+ // If child is (NOT alpha), we can flip accumconst and use alpha.
+ // This is ok because (NOT alpha) == TRUE XOR alpha
+ accumconst = !accumconst;
+ // CreateSimpNot just takes child of not.
+ new_children.push_back(CreateSimpNot(*it));
+ }
+ else
+ {
+ new_children.push_back(*it);
+ }
+ }
+
+ // Children should be non-constant.
+ if (new_children.size() < 2)
+ {
+ if (0 == new_children.size())
+ {
+ // XOR(TRUE, FALSE) -- accumconst will be 1.
+ if (accumconst)
+ {
+ retval = ASTTrue;
+ }
+ else
+ {
+ retval = ASTFalse;
+ }
+ }
+ else
+ {
+ // there is just one child
+ // XOR(x, TRUE) -- accumconst will be 1.
+ if (accumconst)
+ {
+ retval = CreateSimpNot(new_children[0]);
+ }
+ else
+ {
+ retval = new_children[0];
+ }
+ }
+ }
+ else
+ {
+ // negate first child if accumconst == 1
+ if (accumconst)
+ {
+ new_children[0] = CreateSimpNot(new_children[0]);
+ }
+ retval = CreateNode(XOR, new_children);
+ }
+
+ if (_trace_simpbool)
+ {
+ cout << "returns " << retval << endl;
}
return retval;
- }
- else {
- // add to children
- new_children.push_back(*it);
- }
- }
-
- // If we get here, we saw no annihilators, and children should
- // be only the non-True nodes.
- if (new_children.size() < 2) {
- if (0 == new_children.size()) {
- retval = identity;
- }
- else {
- // there is just one child
- retval = new_children[0];
- }
- }
- else {
- // 2 or more children. Create a new node.
- retval = CreateNode(IsAnd ? AND : OR, new_children);
- }
- if (_trace_simpbool) {
- cout << "returns " << retval << endl;
- }
- return retval;
- }
-
- // Constant children are accumulated in "accumconst".
- ASTNode BeevMgr::CreateSimpXor(ASTVec &children) {
-
- if (_trace_simpbool) {
- cout << "========" << endl
- << "CreateSimpXor ";
- lpvec(children);
- cout << endl;
- }
-
- ASTVec flat_children; // empty vector
- ASTVec::const_iterator it_end = children.end();
-
- if (xor_flatten) {
- flat_children = FlattenKind(XOR, children);
- }
- else {
- flat_children = children;
- }
-
- // sort so that identical nodes occur in sequential runs, followed by
- // their negations.
- SortByExprNum(flat_children);
-
- ASTNode retval;
-
- // This is the C Boolean value of all constant args seen. It is initially
- // 0. TRUE children cause it to change value.
- bool accumconst = 0;
-
- ASTVec new_children;
-
- it_end = flat_children.end();
- ASTVec::iterator next_it;
- for(ASTVec::iterator it = flat_children.begin(); it != it_end; it++) {
- next_it = it + 1;
- bool nextexists = (next_it < it_end);
-
- if (ASTTrue == *it) {
- accumconst = !accumconst;
- }
- else if (ASTFalse == *it) {
- // Ignore it
- }
- else if (nextexists && (*next_it == *it)) {
- // x XOR x = FALSE. Skip current, write "false" into next_it
- // so that it gets tossed, too.
- *next_it = ASTFalse;
- }
- else if (nextexists && (next_it->GetKind() == NOT) && ((*next_it)[0] == *it)) {
- // x XOR NOT x = TRUE. Skip current, write "true" into next_it
- // so that it gets tossed, too.
- *next_it = ASTTrue;
- }
- else if (NOT == it->GetKind()) {
- // If child is (NOT alpha), we can flip accumconst and use alpha.
- // This is ok because (NOT alpha) == TRUE XOR alpha
- accumconst = !accumconst;
- // CreateSimpNot just takes child of not.
- new_children.push_back(CreateSimpNot(*it));
- }
- else {
- new_children.push_back(*it);
- }
- }
-
- // Children should be non-constant.
- if (new_children.size() < 2) {
- if (0 == new_children.size()) {
- // XOR(TRUE, FALSE) -- accumconst will be 1.
- if (accumconst) {
- retval = ASTTrue;
+}
+
+// FIXME: How do I know whether ITE is a formula or not?
+ASTNode BeevMgr::CreateSimpFormITE(const ASTNode& child0, const ASTNode& child1, const ASTNode& child2)
+{
+
+ ASTNode retval;
+
+ if (_trace_simpbool)
+ {
+ cout << "========" << endl << "CreateSimpFormITE " << child0 << child1 << child2 << endl;
+ }
+
+ if (ASTTrue == child0)
+ {
+ retval = child1;
+ }
+ else if (ASTFalse == child0)
+ {
+ retval = child2;
+ }
+ else if (child1 == child2)
+ {
+ retval = child1;
+ }
+ // ITE(x, TRUE, y ) == x OR y
+ else if (ASTTrue == child1)
+ {
+ retval = CreateSimpAndOr(0, child0, child2);
}
- else {
- retval = ASTFalse;
+ // ITE(x, FALSE, y ) == (!x AND y)
+ else if (ASTFalse == child1)
+ {
+ retval = CreateSimpAndOr(1, CreateSimpNot(child0), child2);
}
- }
- else {
- // there is just one child
- // XOR(x, TRUE) -- accumconst will be 1.
- if (accumconst) {
- retval = CreateSimpNot(new_children[0]);
+ // ITE(x, y, TRUE ) == (!x OR y)
+ else if (ASTTrue == child2)
+ {
+ retval = CreateSimpAndOr(0, CreateSimpNot(child0), child1);
}
- else {
- retval = new_children[0];
+ // ITE(x, y, FALSE ) == (x AND y)
+ else if (ASTFalse == child2)
+ {
+ retval = CreateSimpAndOr(1, child0, child1);
}
- }
- }
- else {
- // negate first child if accumconst == 1
- if (accumconst) {
- new_children[0] = CreateSimpNot(new_children[0]);
- }
- retval = CreateNode(XOR, new_children);
- }
-
- if (_trace_simpbool) {
- cout << "returns " << retval << endl;
- }
- return retval;
- }
-
- // FIXME: How do I know whether ITE is a formula or not?
- ASTNode BeevMgr::CreateSimpFormITE(const ASTNode& child0,
- const ASTNode& child1,
- const ASTNode& child2) {
-
- ASTNode retval;
-
- if (_trace_simpbool) {
- cout << "========" << endl << "CreateSimpFormITE "
- << child0
- << child1
- << child2 << endl;
- }
-
- if (ASTTrue == child0) {
- retval = child1;
- }
- else if (ASTFalse == child0) {
- retval = child2;
- }
- else if (child1 == child2) {
- retval = child1;
- }
- // ITE(x, TRUE, y ) == x OR y
- else if (ASTTrue == child1) {
- retval = CreateSimpAndOr(0, child0, child2);
- }
- // ITE(x, FALSE, y ) == (!x AND y)
- else if (ASTFalse == child1) {
- retval = CreateSimpAndOr(1, CreateSimpNot(child0), child2);
- }
- // ITE(x, y, TRUE ) == (!x OR y)
- else if (ASTTrue == child2) {
- retval = CreateSimpAndOr(0, CreateSimpNot(child0), child1);
- }
- // ITE(x, y, FALSE ) == (x AND y)
- else if (ASTFalse == child2) {
- retval = CreateSimpAndOr(1, child0, child1);
- }
- // ITE (x, !y, y) == x XOR y
-// else if (NOT == child1.GetKind() && (child1[0] == child2)) {
-// retval = CreateSimpXor(child0, child2);
-// }
-// // ITE (x, y, !y) == x IFF y. I think other cases are covered
-// // by XOR/IFF optimizations
-// else if (NOT == child2.GetKind() && (child2[0] == child1)) {
-// retval = CreateSimpXor(CreateSimpNot(child0), child2);
-// }
- else {
- retval = CreateNode(ITE, child0, child1, child2);
- }
-
- if (_trace_simpbool) {
- cout << "returns " << retval << endl;
- }
-
- return retval;
- }
+ // ITE (x, !y, y) == x XOR y
+ // else if (NOT == child1.GetKind() && (child1[0] == child2)) {
+ // retval = CreateSimpXor(child0, child2);
+ // }
+ // // ITE (x, y, !y) == x IFF y. I think other cases are covered
+ // // by XOR/IFF optimizations
+ // else if (NOT == child2.GetKind() && (child2[0] == child1)) {
+ // retval = CreateSimpXor(CreateSimpNot(child0), child2);
+ // }
+ else
+ {
+ retval = CreateNode(ITE, child0, child1, child2);
+ }
+
+ if (_trace_simpbool)
+ {
+ cout << "returns " << retval << endl;
+ }
+
+ return retval;
+}
} // BEEV namespace
#include "AST.h"
#include "../simplifier/bvsolver.h"
-namespace BEEV {
+namespace BEEV
+{
-class CNFMgr {
+class CNFMgr
+{
public:
- //########################################
- //########################################
- // constructor
+ //########################################
+ //########################################
+ // constructor
- CNFMgr(BeevMgr *bmgr){
- bm = bmgr;
- }
+ CNFMgr(BeevMgr *bmgr)
+ {
+ bm = bmgr;
+ }
- //########################################
- //########################################
- // destructor
+ //########################################
+ //########################################
+ // destructor
- ~CNFMgr(){
- ASTNodeToASTNodePtrMap::const_iterator it1 = store.begin();
- for(; it1 != store.end(); it1++){
- delete it1->second;
- }
+ ~CNFMgr()
+ {
+ ASTNodeToASTNodePtrMap::const_iterator it1 = store.begin();
+ for (; it1 != store.end(); it1++)
+ {
+ delete it1->second;
+ }
- store.clear();
+ store.clear();
- }
+ }
- //########################################
- //########################################
- // top-level conversion function
+ //########################################
+ //########################################
+ // top-level conversion function
+
+ BeevMgr::ClauseList* convertToCNF(const ASTNode& varphi)
+ {
+ scanFormula(varphi, true);
+ ASTNode dummy_true_var = bm->CreateSymbol("*TrueDummy*");
+ BeevMgr::ClauseList* defs = SINGLETON(dummy_true_var);
+ convertFormulaToCNF(varphi, defs);
+ BeevMgr::ClauseList* top = info[varphi]->clausespos;
+ defs->insert(defs->begin() + 1, top->begin(), top->end());
+
+ cleanup(varphi);
+ return defs;
+ }
- BeevMgr::ClauseList* convertToCNF(const ASTNode& varphi){
- scanFormula(varphi, true);
- ASTNode dummy_true_var = bm->CreateSymbol("*TrueDummy*");
- BeevMgr::ClauseList* defs = SINGLETON(dummy_true_var);
- convertFormulaToCNF(varphi, defs);
- BeevMgr::ClauseList* top = info[varphi]->clausespos;
- defs->insert(defs->begin() + 1, top->begin(), top->end());
+ void DELETE(BeevMgr::ClauseList* varphi)
+ {
+ BeevMgr::ClauseList::const_iterator it = varphi->begin();
+ for (; it != varphi->end(); it++)
+ {
+ delete *it;
+ }
- cleanup(varphi);
- return defs;
- }
+ delete varphi;
+ }
- void DELETE(BeevMgr::ClauseList* varphi){
- BeevMgr::ClauseList::const_iterator it = varphi->begin();
- for(; it != varphi->end(); it++){
- delete *it;
- }
+private:
- delete varphi;
- }
+ //########################################
+ //########################################
+ // data types
+
+ // for the meaning of control bits, see "utilities for contol bits".
+ typedef struct
+ {
+ int control;
+ BeevMgr::ClauseList* clausespos;
+ union
+ {
+ BeevMgr::ClauseList* clausesneg;
+ ASTNode* termforcnf;
+ };
+ } CNFInfo;
+
+ typedef hash_map<ASTNode, CNFInfo*, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTNodeToCNFInfoMap;
+
+ typedef hash_map<ASTNode, ASTNode*, ASTNode::ASTNodeHasher, ASTNode::ASTNodeEqual> ASTNodeToASTNodePtrMap;
+
+ //########################################
+ //########################################
+ // this is the data
+
+ BeevMgr *bm;
+ ASTNodeToCNFInfoMap info;
+ ASTNodeToASTNodePtrMap store;
+
+ //########################################
+ //########################################
+ // utility predicates
+
+ bool isAtom(const ASTNode& varphi)
+ {
+ bool result;
+
+ Kind k = varphi.GetKind();
+ switch (k)
+ {
+ case TRUE:
+ {
+ result = true;
+ break;
+ }
+ case FALSE:
+ {
+ result = true;
+ break;
+ }
+ case SYMBOL:
+ {
+ result = true;
+ break;
+ }
+ case BVCONST:
+ {
+ result = true;
+ break;
+ }
+ default:
+ {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+ }
-private:
+ bool isPred(const ASTNode& varphi)
+ {
+ bool result;
+
+ Kind k = varphi.GetKind();
+ switch (k)
+ {
+ case BVLT:
+ {
+ result = true;
+ break;
+ }
+ case BVLE:
+ {
+ result = true;
+ break;
+ }
+ case BVGT:
+ {
+ result = true;
+ break;
+ }
+ case BVGE:
+ {
+ result = true;
+ break;
+ }
+ case BVSLT:
+ {
+ result = true;
+ break;
+ }
+ case BVSLE:
+ {
+ result = true;
+ break;
+ }
+ case BVSGT:
+ {
+ result = true;
+ break;
+ }
+ case BVSGE:
+ {
+ result = true;
+ break;
+ }
+ case EQ:
+ {
+ result = true;
+ break;
+ }
+ case NEQ:
+ {
+ result = true;
+ break;
+ }
+ default:
+ {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ bool isITE(const ASTNode& varphi)
+ {
+ bool result;
+
+ Kind k = varphi.GetKind();
+ switch (k)
+ {
+ case ITE:
+ {
+ result = true;
+ break;
+ }
+ default:
+ {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ bool onChildDoPos(const ASTNode& varphi, unsigned int idx)
+ {
+ bool result = true;
+
+ Kind k = varphi.GetKind();
+ switch (k)
+ {
+ case NOT:
+ {
+ result = false;
+ break;
+ }
+ case NAND:
+ {
+ result = false;
+ break;
+ }
+ case NOR:
+ {
+ result = false;
+ break;
+ }
+ case IMPLIES:
+ {
+ if (idx == 0)
+ {
+ result = false;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ bool onChildDoNeg(const ASTNode& varphi, unsigned int idx)
+ {
+ bool result = false;
+
+ Kind k = varphi.GetKind();
+ switch (k)
+ {
+ case NOT:
+ {
+ result = true;
+ break;
+ }
+ case NAND:
+ {
+ result = true;
+ break;
+ }
+ case NOR:
+ {
+ result = true;
+ break;
+ }
+ case XOR:
+ {
+ result = true;
+ break;
+ }
+ case IFF:
+ {
+ result = true;
+ break;
+ }
+ case IMPLIES:
+ {
+ if (idx == 0)
+ {
+ result = true;
+ }
+ break;
+ }
+ case ITE:
+ {
+ if (idx == 0)
+ {
+ result = true;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ //########################################
+ //########################################
+ //utilities for control bits.
+
+ void initializeCNFInfo(CNFInfo& x)
+ {
+ x.control = 0;
+ x.clausespos = NULL;
+ x.clausesneg = NULL;
+ }
+
+ void incrementSharesPos(CNFInfo& x)
+ {
+ x.control += ((x.control & 3) < 2) ? 1 : 0;
+ }
+
+ int sharesPos(CNFInfo& x)
+ {
+ return (x.control & 3);
+ }
+
+ void incrementSharesNeg(CNFInfo& x)
+ {
+ x.control += ((x.control & 12) < 8) ? 4 : 0;
+ }
+
+ int sharesNeg(CNFInfo& x)
+ {
+ return ((x.control & 12) >> 2);
+ }
+
+ void setControlBit(CNFInfo& x, unsigned int idx)
+ {
+ x.control |= (1 << idx);
+ }
+
+ bool getControlBit(CNFInfo& x, unsigned int idx)
+ {
+ bool result = false;
+
+ if (x.control & (1 << idx))
+ {
+
+ result = true;
+ }
+
+ return result;
+ }
+
+ void setIsTerm(CNFInfo& x)
+ {
+ setControlBit(x, 4);
+ }
+
+ bool isTerm(CNFInfo& x)
+ {
+ return getControlBit(x, 4);
+ }
+
+ void setDoRenamePos(CNFInfo& x)
+ {
+ setControlBit(x, 5);
+ }
+
+ bool doRenamePos(CNFInfo& x)
+ {
+ return getControlBit(x, 5);
+ }
+
+ void setWasRenamedPos(CNFInfo& x)
+ {
+ setControlBit(x, 6);
+ }
+
+ bool wasRenamedPos(CNFInfo& x)
+ {
+ return getControlBit(x, 6);
+ }
+
+ void setDoRenameNeg(CNFInfo& x)
+ {
+ setControlBit(x, 7);
+ }
+
+ bool doRenameNeg(CNFInfo& x)
+ {
+ return getControlBit(x, 7);
+ }
+
+ void setWasRenamedNeg(CNFInfo& x)
+ {
+ setControlBit(x, 8);
+ }
+
+ bool wasRenamedNeg(CNFInfo& x)
+ {
+ return getControlBit(x, 8);
+ }
+
+ void setDoSibRenamingPos(CNFInfo& x)
+ {
+ setControlBit(x, 9);
+ }
+
+ bool doSibRenamingPos(CNFInfo& x)
+ {
+ return getControlBit(x, 9);
+ }
+
+ void setDoSibRenamingNeg(CNFInfo& x)
+ {
+ setControlBit(x, 10);
+ }
+
+ bool doSibRenamingNeg(CNFInfo& x)
+ {
+ return getControlBit(x, 10);
+ }
+
+ void setWasVisited(CNFInfo& x)
+ {
+ setControlBit(x, 11);
+ }
+
+ bool wasVisited(CNFInfo& x)
+ {
+ return getControlBit(x, 11);
+ }
+
+ //########################################
+ //########################################
+ //utilities for clause sets
+
+
+ BeevMgr::ClauseList* COPY(const BeevMgr::ClauseList& varphi)
+ {
+ BeevMgr::ClauseList* psi = new BeevMgr::ClauseList();
+
+ BeevMgr::ClauseList::const_iterator it = varphi.begin();
+ for (; it != varphi.end(); it++)
+ {
+ psi->push_back(new vector<const ASTNode*> (**it));
+ }
+
+ return psi;
+ }
+
+ BeevMgr::ClauseList* SINGLETON(const ASTNode& varphi)
+ {
+ ASTNode* copy = ASTNodeToASTNodePtr(varphi);
+
+ BeevMgr::ClausePtr clause = new vector<const ASTNode*> ();
+ clause->push_back(copy);
+
+ BeevMgr::ClauseList* psi = new BeevMgr::ClauseList();
+ psi->push_back(clause);
+ return psi;
+ }
+
+ BeevMgr::ClauseList* UNION(const BeevMgr::ClauseList& varphi1, const BeevMgr::ClauseList& varphi2)
+ {
+
+ BeevMgr::ClauseList* psi1 = COPY(varphi1);
+ BeevMgr::ClauseList* psi2 = COPY(varphi2);
+ psi1->insert(psi1->end(), psi2->begin(), psi2->end());
+ delete psi2;
+
+ return psi1;
+
+ }
+
+ void INPLACE_UNION(BeevMgr::ClauseList* varphi1, const BeevMgr::ClauseList& varphi2)
+ {
+
+ BeevMgr::ClauseList* psi2 = COPY(varphi2);
+ varphi1->insert(varphi1->end(), psi2->begin(), psi2->end());
+ delete psi2;
+ }
+
+ void NOCOPY_INPLACE_UNION(BeevMgr::ClauseList* varphi1, BeevMgr::ClauseList* varphi2)
+ {
+
+ varphi1->insert(varphi1->end(), varphi2->begin(), varphi2->end());
+ delete varphi2;
+ }
+
+ BeevMgr::ClauseList* PRODUCT(const BeevMgr::ClauseList& varphi1, const BeevMgr::ClauseList& varphi2)
+ {
+
+ BeevMgr::ClauseList* psi = new BeevMgr::ClauseList();
+
+ BeevMgr::ClauseList::const_iterator it1 = varphi1.begin();
+ for (; it1 != varphi1.end(); it1++)
+ {
+ BeevMgr::ClausePtr clause1 = *it1;
+ BeevMgr::ClauseList::const_iterator it2 = varphi2.begin();
+ for (; it2 != varphi2.end(); it2++)
+ {
+ BeevMgr::ClausePtr clause2 = *it2;
+ BeevMgr::ClausePtr clause = new vector<const ASTNode*> ();
+ clause->insert(clause->end(), clause1->begin(), clause1->end());
+ clause->insert(clause->end(), clause2->begin(), clause2->end());
+ psi->push_back(clause);
+ }
+ }
+
+ return psi;
+ }
+
+ //########################################
+ //########################################
+ //prep. for cnf conversion
+
+ void scanFormula(const ASTNode& varphi, bool isPos)
+ {
+
+ CNFInfo* x;
+
+ //########################################
+ // step 1, get the info associated with this node
+ //########################################
+
+ if (info.find(varphi) == info.end())
+ {
+ x = new CNFInfo();
+ initializeCNFInfo(*x);
+ info[varphi] = x;
+ }
+ else
+ {
+ x = info[varphi];
+ }
+
+ //########################################
+ // step 2, we only need to know if shares >= 2
+ //########################################
+
+ if (isPos && sharesPos(*x) == 2)
+ {
+ return;
+ }
+
+ if (!isPos && sharesNeg(*x) == 2)
+ {
+ return;
+ }
+
+ //########################################
+ // step 3, set appropriate information fields
+ //########################################
+
+ if (isPos)
+ {
+ incrementSharesPos(*x);
+ }
+
+ if (!isPos)
+ {
+ incrementSharesNeg(*x);
+ }
+
+ //########################################
+ // step 4, recurse over children
+ //########################################
+
+ if (isAtom(varphi))
+ {
+ return;
+ }
+ else if (isPred(varphi))
+ {
+ for (unsigned int i = 0; i < varphi.GetChildren().size(); i++)
+ {
+ scanTerm(varphi[i]);
+ }
+ }
+ else
+ {
+ for (unsigned int i = 0; i < varphi.GetChildren().size(); i++)
+ {
+ if (onChildDoPos(varphi, i))
+ {
+ scanFormula(varphi[i], isPos);
+ }
+ if (onChildDoNeg(varphi, i))
+ {
+ scanFormula(varphi[i], !isPos);
+ }
+ }
+ }
+ }
+
+ void scanTerm(const ASTNode& varphi)
+ {
+
+ CNFInfo* x;
+
+ //########################################
+ // step 1, get the info associated with this node
+ //########################################
+
+ if (info.find(varphi) == info.end())
+ {
+ x = new CNFInfo();
+ initializeCNFInfo(*x);
+ 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 (isAtom(varphi))
+ {
+ return;
+ }
+ else if (isITE(varphi))
+ {
+ scanFormula(varphi[0], true);
+ scanFormula(varphi[0], false);
+ scanTerm(varphi[1]);
+ scanTerm(varphi[2]);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < varphi.GetChildren().size(); i++)
+ {
+ scanTerm(varphi[i]);
+ }
+ }
+ }
+
+ //########################################
+ //########################################
+ // main cnf conversion function
+
+ void convertFormulaToCNF(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+
+ CNFInfo* x = info[varphi];
+
+ //########################################
+ // divert to special case if term (word-level cnf)
+
+ if (isTerm(*x))
+ {
+ convertTermForCNF(varphi, defs);
+ setWasVisited(*x);
+ return;
+ }
+
+ //########################################
+ // do work
+
+ if (sharesPos(*x) > 0 && !wasVisited(*x))
+ {
+ convertFormulaToCNFPosCases(varphi, defs);
+ }
+
+ if (x->clausespos != NULL && x->clausespos->size() > 1)
+ {
+ if (doSibRenamingPos(*x) || sharesPos(*x) > 1)
+ {
+ doRenamingPos(varphi, defs);
+ }
+ }
+
+ if (sharesNeg(*x) > 0 && !wasVisited(*x))
+ {
+ convertFormulaToCNFNegCases(varphi, defs);
+ }
+
+ if (x->clausesneg != NULL && x->clausesneg->size() > 1)
+ {
+ if (doSibRenamingNeg(*x) || sharesNeg(*x) > 1)
+ {
+ doRenamingNeg(varphi, defs);
+ }
+ }
+
+ //########################################
+ //mark that we've already done the hard work
+
+ setWasVisited(*x);
+ }
+
+ void convertTermForCNF(const ASTNode& varphi, BeevMgr::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 (isITE(varphi))
+ {
+ x->termforcnf = doRenameITE(varphi, defs);
+ reduceMemoryFootprintPos(varphi[0]);
+ reduceMemoryFootprintNeg(varphi[0]);
+
+ }
+ else if (isAtom(varphi))
+ {
+ 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);
+ }
+ }
+
+ //########################################
+ //########################################
+ // functions for renaming nodes during cnf conversion
+
+ ASTNode* doRenameITE(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+
+ ASTNode psi;
+
+ //########################################
+ // step 1, old "RepLit" code
+ //########################################
+
+ ostringstream oss;
+ oss << "cnf" << "{" << varphi.GetNodeNum() << "}";
+ psi = bm->CreateSymbol(oss.str().c_str());
+
+ //########################################
+ // step 2, set widths appropriately
+ //########################################
- //########################################
- //########################################
- // data types
-
- // for the meaning of control bits, see "utilities for contol bits".
- typedef struct {
- int control;
- BeevMgr::ClauseList* clausespos;
- union {BeevMgr::ClauseList* clausesneg; ASTNode* termforcnf;};
- } CNFInfo;
-
- typedef hash_map< ASTNode
- , CNFInfo*
- , ASTNode::ASTNodeHasher
- , ASTNode::ASTNodeEqual
- > ASTNodeToCNFInfoMap;
-
- typedef hash_map< ASTNode
- , ASTNode*
- , ASTNode::ASTNodeHasher
- , ASTNode::ASTNodeEqual
- > ASTNodeToASTNodePtrMap;
-
-
- //########################################
- //########################################
- // this is the data
-
- BeevMgr *bm;
- ASTNodeToCNFInfoMap info;
- ASTNodeToASTNodePtrMap store;
-
- //########################################
- //########################################
- // utility predicates
-
- bool isAtom(const ASTNode& varphi){
- bool result;
-
- Kind k = varphi.GetKind();
- switch(k){
- case TRUE: {
- result = true;
- break;
- }
- case FALSE: {
- result = true;
- break;
- }
- case SYMBOL: {
- result = true;
- break;
- }
- case BVCONST: {
- result = true;
- break;
- }
- default: {
- result = false;
- break;
- }
- }
-
- return result;
- }
-
- bool isPred(const ASTNode& varphi){
- bool result;
-
- Kind k = varphi.GetKind();
- switch(k){
- case BVLT: {
- result = true;
- break;
- }
- case BVLE: {
- result = true;
- break;
- }
- case BVGT: {
- result = true;
- break;
- }
- case BVGE: {
- result = true;
- break;
- }
- case BVSLT: {
- result = true;
- break;
- }
- case BVSLE: {
- result = true;
- break;
- }
- case BVSGT: {
- result = true;
- break;
- }
- case BVSGE: {
- result = true;
- break;
- }
- case EQ: {
- result = true;
- break;
- }
- case NEQ: {
- result = true;
- break;
- }
- default: {
- result = false;
- break;
- }
- }
-
- return result;
- }
-
- bool isITE(const ASTNode& varphi){
- bool result;
-
- Kind k = varphi.GetKind();
- switch(k){
- case ITE: {
- result = true;
- break;
- }
- default: {
- result = false;
- break;
- }
- }
-
- return result;
- }
-
-
- bool onChildDoPos(const ASTNode& varphi, unsigned int idx){
- bool result = true;
-
- Kind k = varphi.GetKind();
- switch(k){
- case NOT: {
- result = false;
- break;
- }
- case NAND: {
- result = false;
- break;
- }
- case NOR: {
- result = false;
- break;
- }
- case IMPLIES: {
- if(idx == 0){
- result = false;
- }
- break;
- }
- default: {
- break;
- }
- }
-
- return result;
- }
-
- bool onChildDoNeg(const ASTNode& varphi, unsigned int idx){
- bool result = false;
-
- Kind k = varphi.GetKind();
- switch(k){
- case NOT: {
- result = true;
- break;
- }
- case NAND: {
- result = true;
- break;
- }
- case NOR: {
- result = true;
- break;
- }
- case XOR: {
- result = true;
- break;
- }
- case IFF: {
- result = true;
- break;
- }
- case IMPLIES: {
- if(idx == 0){
- result = true;
- }
- break;
- }
- case ITE: {
- if(idx == 0){
- result = true;
- }
- break;
- }
- default: {
- break;
- }
- }
-
- return result;
- }
-
- //########################################
- //########################################
- //utilities for control bits.
-
- void initializeCNFInfo(CNFInfo& x){
- x.control = 0;
- x.clausespos = NULL;
- x.clausesneg = NULL;
- }
-
- void incrementSharesPos(CNFInfo& x){
- x.control += ((x.control & 3) < 2) ? 1 : 0;
- }
-
- int sharesPos(CNFInfo& x){
- return (x.control & 3);
- }
-
- void incrementSharesNeg(CNFInfo& x){
- x.control += ((x.control & 12) < 8) ? 4 : 0;
- }
-
- int sharesNeg(CNFInfo& x){
- return ((x.control & 12) >> 2);
- }
-
- void setControlBit(CNFInfo& x, unsigned int idx){
- x.control |= (1 << idx);
- }
-
- bool getControlBit(CNFInfo& x, unsigned int idx){
- bool result = false;
-
- if(x.control & (1 << idx)){
-
- result = true;
- }
-
- return result;
- }
-
- void setIsTerm(CNFInfo& x){
- setControlBit(x, 4);
- }
-
- bool isTerm(CNFInfo& x){
- return getControlBit(x, 4);
- }
-
- void setDoRenamePos(CNFInfo& x){
- setControlBit(x, 5);
- }
-
- bool doRenamePos(CNFInfo& x){
- return getControlBit(x, 5);
- }
-
- void setWasRenamedPos(CNFInfo& x){
- setControlBit(x, 6);
- }
-
- bool wasRenamedPos(CNFInfo& x){
- return getControlBit(x, 6);
- }
-
- void setDoRenameNeg(CNFInfo& x){
- setControlBit(x, 7);
- }
-
- bool doRenameNeg(CNFInfo& x){
- return getControlBit(x, 7);
- }
-
- void setWasRenamedNeg(CNFInfo& x){
- setControlBit(x, 8);
- }
-
- bool wasRenamedNeg(CNFInfo& x){
- return getControlBit(x, 8);
- }
-
- void setDoSibRenamingPos(CNFInfo& x){
- setControlBit(x, 9);
- }
-
- bool doSibRenamingPos(CNFInfo& x){
- return getControlBit(x, 9);
- }
-
- void setDoSibRenamingNeg(CNFInfo& x){
- setControlBit(x, 10);
- }
+ psi.SetValueWidth(varphi.GetValueWidth());
+ psi.SetIndexWidth(varphi.GetIndexWidth());
- bool doSibRenamingNeg(CNFInfo& x){
- return getControlBit(x, 10);
- }
+ //########################################
+ // step 3, recurse over children
+ //########################################
- void setWasVisited(CNFInfo& x){
- setControlBit(x, 11);
- }
+ convertFormulaToCNF(varphi[0], defs);
+ convertTermForCNF(varphi[1], defs);
+ ASTNode t1 = *(info[varphi[1]]->termforcnf);
+ convertTermForCNF(varphi[2], defs);
+ ASTNode t2 = *(info[varphi[2]]->termforcnf);
- bool wasVisited(CNFInfo& x){
- return getControlBit(x, 11);
- }
+ //########################################
+ // step 4, add def clauses
+ //########################################
- //########################################
- //########################################
- //utilities for clause sets
+ BeevMgr::ClauseList* cl1 = SINGLETON(bm->CreateNode(EQ, psi, t1));
+ BeevMgr::ClauseList* cl2 = PRODUCT(*(info[varphi[0]]->clausesneg), *cl1);
+ DELETE(cl1);
+ defs->insert(defs->end(), cl2->begin(), cl2->end());
+ BeevMgr::ClauseList* cl3 = SINGLETON(bm->CreateNode(EQ, psi, t2));
+ BeevMgr::ClauseList* cl4 = PRODUCT(*(info[varphi[0]]->clausespos), *cl3);
+ DELETE(cl3);
+ defs->insert(defs->end(), cl4->begin(), cl4->end());
- BeevMgr::ClauseList* COPY(const BeevMgr::ClauseList& varphi){
- BeevMgr::ClauseList* psi = new BeevMgr::ClauseList();
+ return ASTNodeToASTNodePtr(psi);
+ }
+
+ void doRenamingPos(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+
+ CNFInfo* x = info[varphi];
+
+ //########################################
+ // step 1, calc new variable
+ //########################################
+
+ ostringstream oss;
+ oss << "cnf" << "{" << varphi.GetNodeNum() << "}";
+ ASTNode psi = bm->CreateSymbol(oss.str().c_str());
+
+ //########################################
+ // step 2, add defs
+ //########################################
+
+ BeevMgr::ClauseList* cl1;
+ cl1 = SINGLETON(bm->CreateNode(NOT, psi));
+ BeevMgr::ClauseList* cl2 = PRODUCT(*(info[varphi]->clausespos), *cl1);
+ defs->insert(defs->end(), cl2->begin(), cl2->end());
+ DELETE(info[varphi]->clausespos);
+ DELETE(cl1);
+ delete cl2;
+
+ //########################################
+ // step 3, update info[varphi]
+ //########################################
+
+ x->clausespos = SINGLETON(psi);
+ setWasRenamedPos(*x);
+ }
+
+ void doRenamingNeg(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+
+ CNFInfo* x = info[varphi];
+
+ //########################################
+ // step 2, calc new variable
+ //########################################
- BeevMgr::ClauseList::const_iterator it = varphi.begin();
- for(; it != varphi.end(); it++){
- psi->push_back(new vector<const ASTNode*>(**it));
- }
+ ostringstream oss;
+ oss << "cnf" << "{" << varphi.GetNodeNum() << "}";
+ ASTNode psi = bm->CreateSymbol(oss.str().c_str());
- return psi;
- }
+ //########################################
+ // step 3, add defs
+ //########################################
- BeevMgr::ClauseList* SINGLETON(const ASTNode& varphi){
- ASTNode* copy = ASTNodeToASTNodePtr(varphi);
+ BeevMgr::ClauseList* cl1;
+ cl1 = SINGLETON(psi);
+ BeevMgr::ClauseList* cl2 = PRODUCT(*(info[varphi]->clausesneg), *cl1);
+ defs->insert(defs->end(), cl2->begin(), cl2->end());
+ DELETE(info[varphi]->clausesneg);
+ DELETE(cl1);
+ delete cl2;
- BeevMgr::ClausePtr clause = new vector<const ASTNode*>();
- clause->push_back(copy);
+ //########################################
+ // step 4, update info[varphi]
+ //########################################
+
+ x->clausesneg = SINGLETON(bm->CreateNode(NOT, psi));
+ setWasRenamedNeg(*x);
+
+ }
+
+ //########################################
+ //########################################
+ //main switch for individual cnf conversion cases
+
+ void convertFormulaToCNFPosCases(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+
+ if (isPred(varphi))
+ {
+ convertFormulaToCNFPosPred(varphi, defs);
+ return;
+ }
+
+ Kind k = varphi.GetKind();
+ switch (k)
+ {
+ case FALSE:
+ {
+ convertFormulaToCNFPosFALSE(varphi, defs);
+ break;
+ }
+ case TRUE:
+ {
+ convertFormulaToCNFPosTRUE(varphi, defs);
+ break;
+ }
+ case BVGETBIT:
+ {
+ convertFormulaToCNFPosBVGETBIT(varphi, defs);
+ break;
+ }
+ case SYMBOL:
+ {
+ convertFormulaToCNFPosSYMBOL(varphi, defs);
+ break;
+ }
+ case NOT:
+ {
+ convertFormulaToCNFPosNOT(varphi, defs);
+ break;
+ }
+ case AND:
+ {
+ convertFormulaToCNFPosAND(varphi, defs);
+ break;
+ }
+ case NAND:
+ {
+ convertFormulaToCNFPosNAND(varphi, defs);
+ break;
+ }
+ case OR:
+ {
+ convertFormulaToCNFPosOR(varphi, defs);
+ break;
+ }
+ case NOR:
+ {
+ convertFormulaToCNFPosNOR(varphi, defs);
+ break;
+ }
+ case XOR:
+ {
+ convertFormulaToCNFPosXOR(varphi, defs);
+ break;
+ }
+ case IMPLIES:
+ {
+ convertFormulaToCNFPosIMPLIES(varphi, defs);
+ break;
+ }
+ case ITE:
+ {
+ convertFormulaToCNFPosITE(varphi, defs);
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "convertFormulaToCNFPosCases: doesn't handle kind %d\n", k);
+ FatalError("");
+ }
+ }
+ }
+
+ void convertFormulaToCNFNegCases(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+
+ if (isPred(varphi))
+ {
+ convertFormulaToCNFNegPred(varphi, defs);
+ return;
+ }
+
+ Kind k = varphi.GetKind();
+ switch (k)
+ {
+ case FALSE:
+ {
+ convertFormulaToCNFNegFALSE(varphi, defs);
+ break;
+ }
+ case TRUE:
+ {
+ convertFormulaToCNFNegTRUE(varphi, defs);
+ break;
+ }
+ case BVGETBIT:
+ {
+ convertFormulaToCNFNegBVGETBIT(varphi, defs);
+ break;
+ }
+ case SYMBOL:
+ {
+ convertFormulaToCNFNegSYMBOL(varphi, defs);
+ break;
+ }
+ case NOT:
+ {
+ convertFormulaToCNFNegNOT(varphi, defs);
+ break;
+ }
+ case AND:
+ {
+ convertFormulaToCNFNegAND(varphi, defs);
+ break;
+ }
+ case NAND:
+ {
+ convertFormulaToCNFNegNAND(varphi, defs);
+ break;
+ }
+ case OR:
+ {
+ convertFormulaToCNFNegOR(varphi, defs);
+ break;
+ }
+ case NOR:
+ {
+ convertFormulaToCNFNegNOR(varphi, defs);
+ break;
+ }
+ case XOR:
+ {
+ convertFormulaToCNFNegXOR(varphi, defs);
+ break;
+ }
+ case IMPLIES:
+ {
+ convertFormulaToCNFNegIMPLIES(varphi, defs);
+ break;
+ }
+ case ITE:
+ {
+ convertFormulaToCNFNegITE(varphi, defs);
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "convertFormulaToCNFNegCases: doesn't handle kind %d\n", k);
+ FatalError("");
+ }
+ }
+ }
+
+ //########################################
+ //########################################
+ // individual cnf conversion cases
+
+ void convertFormulaToCNFPosPred(const ASTNode& varphi, BeevMgr::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));
+ }
- BeevMgr::ClauseList* psi = new BeevMgr::ClauseList();
- psi->push_back(clause);
- return psi;
- }
+ void convertFormulaToCNFPosFALSE(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ ASTNode dummy_false_var = bm->CreateNode(NOT, bm->CreateSymbol("*TrueDummy*"));
+ info[varphi]->clausespos = SINGLETON(dummy_false_var);
+ }
+
+ void convertFormulaToCNFPosTRUE(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ ASTNode dummy_true_var = bm->CreateSymbol("*TrueDummy*");
+ info[varphi]->clausespos = SINGLETON(dummy_true_var);
+ }
+
+ void convertFormulaToCNFPosBVGETBIT(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ info[varphi]->clausespos = SINGLETON(varphi);
+ }
+
+ void convertFormulaToCNFPosSYMBOL(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ info[varphi]->clausespos = SINGLETON(varphi);
+ }
+
+ void convertFormulaToCNFPosNOT(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ convertFormulaToCNF(varphi[0], defs);
+ info[varphi]->clausespos = COPY(*(info[varphi[0]]->clausesneg));
+ reduceMemoryFootprintNeg(varphi[0]);
+ }
+
+ void convertFormulaToCNFPosAND(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ //****************************************
+ // (pos) AND ~> UNION
+ //****************************************
+ ASTVec::const_iterator it = varphi.GetChildren().begin();
+ convertFormulaToCNF(*it, defs);
+ BeevMgr::ClauseList* psi = COPY(*(info[*it]->clausespos));
+ for (it++; it != varphi.GetChildren().end(); it++)
+ {
+ convertFormulaToCNF(*it, defs);
+ INPLACE_UNION(psi, *(info[*it]->clausespos));
+ reduceMemoryFootprintPos(*it);
+ }
+
+ info[varphi]->clausespos = psi;
+ }
+
+ void convertFormulaToCNFPosNAND(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ bool renamesibs = false;
+ BeevMgr::ClauseList* clauses;
+ BeevMgr::ClauseList* psi;
+ BeevMgr::ClauseList* oldpsi;
+
+ //****************************************
+ // (pos) NAND ~> PRODUCT NOT
+ //****************************************
+
+ ASTVec::const_iterator it = varphi.GetChildren().begin();
+ convertFormulaToCNF(*it, defs);
+ clauses = info[*it]->clausesneg;
+ if (clauses->size() > 1)
+ {
+ renamesibs = true;
+ }
+ psi = 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;
+ }
+ oldpsi = psi;
+ psi = PRODUCT(*psi, *clauses);
+ reduceMemoryFootprintNeg(*it);
+ DELETE(oldpsi);
+ }
+
+ info[varphi]->clausespos = psi;
+ }
+
+ void convertFormulaToCNFPosOR(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ bool renamesibs = false;
+ BeevMgr::ClauseList* clauses;
+ BeevMgr::ClauseList* psi;
+ BeevMgr::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 = 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 = PRODUCT(*psi, *clauses);
+ reduceMemoryFootprintPos(*it);
+ DELETE(oldpsi);
+ }
+
+ info[varphi]->clausespos = psi;
+ }
+
+ void convertFormulaToCNFPosNOR(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ //****************************************
+ // (pos) NOR ~> UNION NOT
+ //****************************************
+ ASTVec::const_iterator it = varphi.GetChildren().begin();
+ convertFormulaToCNF(*it, defs);
+ BeevMgr::ClauseList* psi = COPY(*(info[*it]->clausesneg));
+ reduceMemoryFootprintNeg(*it);
+ for (it++; it != varphi.GetChildren().end(); it++)
+ {
+ convertFormulaToCNF(*it, defs);
+ INPLACE_UNION(psi, *(info[*it]->clausesneg));
+ reduceMemoryFootprintNeg(*it);
+ }
+
+ info[varphi]->clausespos = psi;
+ }
+
+ void convertFormulaToCNFPosIMPLIES(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ //****************************************
+ // (pos) IMPLIES ~> PRODUCT NOT [0] ; [1]
+ //****************************************
+ CNFInfo* x0 = info[varphi[0]];
+ CNFInfo* x1 = info[varphi[1]];
+ convertFormulaToCNF(varphi[0], defs);
+ if (x0->clausesneg->size() > 1)
+ {
+ setDoSibRenamingPos(*x1);
+ }
+ convertFormulaToCNF(varphi[1], defs);
+ BeevMgr::ClauseList* psi = PRODUCT(*(x0->clausesneg), *(x1->clausespos));
+ reduceMemoryFootprintNeg(varphi[0]);
+ reduceMemoryFootprintPos(varphi[1]);
+ info[varphi]->clausespos = psi;
+ }
+
+ void convertFormulaToCNFPosITE(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ //****************************************
+ // (pos) ITE ~> UNION (PRODUCT NOT [0] ; [1])
+ // ; (PRODUCT [0] ; [2])
+ //****************************************
+ CNFInfo* x0 = info[varphi[0]];
+ CNFInfo* x1 = info[varphi[1]];
+ CNFInfo* x2 = info[varphi[2]];
+ convertFormulaToCNF(varphi[0], defs);
+ if (x0->clausesneg->size() > 1)
+ {
+ setDoSibRenamingPos(*x1);
+ }
+ convertFormulaToCNF(varphi[1], defs);
+ if (x0->clausespos->size() > 1)
+ {
+ setDoSibRenamingPos(*x2);
+ }
+ convertFormulaToCNF(varphi[2], defs);
+ BeevMgr::ClauseList* psi1 = PRODUCT(*(x0->clausesneg), *(x1->clausespos));
+ BeevMgr::ClauseList* psi2 = PRODUCT(*(x0->clausespos), *(x2->clausespos));
+ NOCOPY_INPLACE_UNION(psi1, psi2);
+ reduceMemoryFootprintNeg(varphi[0]);
+ reduceMemoryFootprintPos(varphi[1]);
+ reduceMemoryFootprintPos(varphi[0]);
+ reduceMemoryFootprintPos(varphi[2]);
+
+ info[varphi]->clausespos = psi1;
+ }
+
+ void convertFormulaToCNFPosXOR(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ BeevMgr::ClauseList* psi = convertFormulaToCNFPosXORAux(varphi, 0, defs);
+ info[varphi]->clausespos = psi;
+ }
+
+ BeevMgr::ClauseList* convertFormulaToCNFPosXORAux(const ASTNode& varphi, unsigned int idx, BeevMgr::ClauseList* defs)
+ {
+
+ bool renamesibs;
+ BeevMgr::ClauseList* psi;
+ BeevMgr::ClauseList* psi1;
+ BeevMgr::ClauseList* psi2;
+
+ if (idx == varphi.GetChildren().size() - 2)
+ {
+ //****************************************
+ // (pos) XOR ~> UNION
+ // (PRODUCT [idx] ; [idx+1])
+ // ; (PRODUCT NOT [idx] ; NOT [idx+1])
+ //****************************************
+ convertFormulaToCNF(varphi[idx], defs);
+ renamesibs = (info[varphi[idx]]->clausespos)->size() > 1 ? true : false;
+ if (renamesibs)
+ {
+ setDoSibRenamingPos(*info[varphi[idx + 1]]);
+ }
+ renamesibs = (info[varphi[idx]]->clausesneg)->size() > 1 ? true : false;
+ if (renamesibs)
+ {
+ setDoSibRenamingNeg(*info[varphi[idx + 1]]);
+ }
+ convertFormulaToCNF(varphi[idx + 1], defs);
+
+ psi1 = PRODUCT(*(info[varphi[idx]]->clausespos), *(info[varphi[idx + 1]]->clausespos));
+ psi2 = PRODUCT(*(info[varphi[idx]]->clausesneg), *(info[varphi[idx + 1]]->clausesneg));
+ NOCOPY_INPLACE_UNION(psi1, psi2);
+ reduceMemoryFootprintPos(varphi[idx]);
+ reduceMemoryFootprintPos(varphi[idx + 1]);
+ reduceMemoryFootprintNeg(varphi[idx]);
+ reduceMemoryFootprintNeg(varphi[idx + 1]);
+
+ psi = psi1;
+ }
+ else
+ {
+ //****************************************
+ // (pos) XOR ~> UNION
+ // (PRODUCT [idx] ; XOR [idx+1..])
+ // ; (PRODUCT NOT [idx] ; NOT XOR [idx+1..])
+ //****************************************
+ BeevMgr::ClauseList* theta1;
+ theta1 = convertFormulaToCNFPosXORAux(varphi, idx + 1, defs);
+ renamesibs = theta1->size() > 1 ? true : false;
+ if (renamesibs)
+ {
+ setDoSibRenamingPos(*info[varphi[idx]]);
+ }
+ BeevMgr::ClauseList* theta2;
+ theta2 = convertFormulaToCNFNegXORAux(varphi, idx + 1, defs);
+ renamesibs = theta2->size() > 1 ? true : false;
+ if (renamesibs)
+ {
+ setDoSibRenamingNeg(*info[varphi[idx]]);
+ }
+ convertFormulaToCNF(varphi[idx], defs);
+
+ psi1 = PRODUCT(*(info[varphi[idx]]->clausespos), *theta1);
+ psi2 = PRODUCT(*(info[varphi[idx]]->clausesneg), *theta2);
+ DELETE(theta1);
+ DELETE(theta2);
+ NOCOPY_INPLACE_UNION(psi1, psi2);
+ reduceMemoryFootprintPos(varphi[idx]);
+ reduceMemoryFootprintNeg(varphi[idx]);
+
+ psi = psi1;
+ }
+
+ return psi;
+ }
- BeevMgr::ClauseList* UNION(const BeevMgr::ClauseList& varphi1
- , const BeevMgr::ClauseList& varphi2){
-
- BeevMgr::ClauseList* psi1 = COPY(varphi1);
- BeevMgr::ClauseList* psi2 = COPY(varphi2);
- psi1->insert(psi1->end(), psi2->begin(), psi2->end());
- delete psi2;
-
- return psi1;
-
- }
-
- void INPLACE_UNION(BeevMgr::ClauseList* varphi1
- , const BeevMgr::ClauseList& varphi2){
-
- BeevMgr::ClauseList* psi2 = COPY(varphi2);
- varphi1->insert(varphi1->end(), psi2->begin(), psi2->end());
- delete psi2;
- }
-
- void NOCOPY_INPLACE_UNION(BeevMgr::ClauseList* varphi1
- , BeevMgr::ClauseList* varphi2){
-
- varphi1->insert(varphi1->end(), varphi2->begin(), varphi2->end());
- delete varphi2;
- }
-
- BeevMgr::ClauseList* PRODUCT(const BeevMgr::ClauseList& varphi1
- , const BeevMgr::ClauseList& varphi2){
-
- BeevMgr::ClauseList* psi = new BeevMgr::ClauseList();
-
- BeevMgr::ClauseList::const_iterator it1 = varphi1.begin();
- for(; it1 != varphi1.end(); it1++){
- BeevMgr::ClausePtr clause1 = *it1;
- BeevMgr::ClauseList::const_iterator it2 = varphi2.begin();
- for(; it2 != varphi2.end(); it2++){
- BeevMgr::ClausePtr clause2 = *it2;
- BeevMgr::ClausePtr clause = new vector<const ASTNode*>();
- clause->insert(clause->end()
- , clause1->begin()
- , clause1->end()
- );
- clause->insert(clause->end()
- , clause2->begin()
- , clause2->end()
- );
- psi->push_back(clause);
- }
- }
-
- return psi;
- }
-
- //########################################
- //########################################
- //prep. for cnf conversion
-
- void scanFormula(const ASTNode& varphi, bool isPos){
-
- CNFInfo* x;
-
- //########################################
- // step 1, get the info associated with this node
- //########################################
-
- if(info.find(varphi) == info.end()){
- x = new CNFInfo();
- initializeCNFInfo(*x);
- info[varphi] = x;
- } else {
- x = info[varphi];
- }
-
- //########################################
- // step 2, we only need to know if shares >= 2
- //########################################
-
- if(isPos && sharesPos(*x) == 2){
- return;
- }
-
- if(!isPos && sharesNeg(*x) == 2){
- return;
- }
-
- //########################################
- // step 3, set appropriate information fields
- //########################################
-
- if(isPos){
- incrementSharesPos(*x);
- }
-
- if(!isPos){
- incrementSharesNeg(*x);
- }
-
- //########################################
- // step 4, recurse over children
- //########################################
-
- if(isAtom(varphi)){
- return;
- } else if(isPred(varphi)){
- for(unsigned int i = 0; i < varphi.GetChildren().size(); i++){
- scanTerm(varphi[i]);
- }
- } else {
- for(unsigned int i = 0; i < varphi.GetChildren().size(); i++){
- if(onChildDoPos(varphi, i)){
- scanFormula(varphi[i], isPos);
- }
- if(onChildDoNeg(varphi, i)){
- scanFormula(varphi[i], !isPos);
- }
- }
- }
- }
-
- void scanTerm(const ASTNode& varphi){
-
- CNFInfo* x;
-
- //########################################
- // step 1, get the info associated with this node
- //########################################
-
- if(info.find(varphi) == info.end()){
- x = new CNFInfo();
- initializeCNFInfo(*x);
- 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(isAtom(varphi)){
- return;
- } else if(isITE(varphi)){
- scanFormula(varphi[0], true);
- scanFormula(varphi[0], false);
- scanTerm(varphi[1]);
- scanTerm(varphi[2]);
- } else {
- for(unsigned int i = 0; i < varphi.GetChildren().size(); i++){
- scanTerm(varphi[i]);
- }
- }
- }
-
- //########################################
- //########################################
- // main cnf conversion function
-
- void convertFormulaToCNF(const ASTNode& varphi, BeevMgr::ClauseList* defs){
-
- CNFInfo* x = info[varphi];
-
- //########################################
- // divert to special case if term (word-level cnf)
-
- if(isTerm(*x)){
- convertTermForCNF(varphi, defs);
- setWasVisited(*x);
- return;
- }
-
- //########################################
- // do work
-
- if(sharesPos(*x) > 0 && !wasVisited(*x)){
- convertFormulaToCNFPosCases(varphi, defs);
- }
-
- if(x->clausespos != NULL && x->clausespos->size() > 1){
- if(doSibRenamingPos(*x) || sharesPos(*x) > 1){
- doRenamingPos(varphi, defs);
- }
- }
-
- if(sharesNeg(*x) > 0 && !wasVisited(*x)){
- convertFormulaToCNFNegCases(varphi, defs);
- }
-
- if(x->clausesneg != NULL && x->clausesneg->size() > 1){
- if(doSibRenamingNeg(*x) || sharesNeg(*x) > 1){
- doRenamingNeg(varphi, defs);
- }
- }
-
- //########################################
- //mark that we've already done the hard work
-
- setWasVisited(*x);
- }
-
- void convertTermForCNF(const ASTNode& varphi, BeevMgr::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(isITE(varphi)){
- x->termforcnf = doRenameITE(varphi, defs);
- reduceMemoryFootprintPos(varphi[0]);
- reduceMemoryFootprintNeg(varphi[0]);
-
- } else if(isAtom(varphi)){
- 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);
- }
- }
-
- //########################################
- //########################################
- // functions for renaming nodes during cnf conversion
-
- ASTNode* doRenameITE(const ASTNode& varphi, BeevMgr::ClauseList* defs){
-
- ASTNode psi;
-
- //########################################
- // step 1, old "RepLit" code
- //########################################
-
- ostringstream oss;
- oss << "cnf" << "{" << varphi.GetNodeNum() << "}";
- psi = bm->CreateSymbol(oss.str().c_str());
-
- //########################################
- // step 2, set widths appropriately
- //########################################
-
- psi.SetValueWidth(varphi.GetValueWidth());
- psi.SetIndexWidth(varphi.GetIndexWidth());
-
- //########################################
- // step 3, recurse over children
- //########################################
-
- convertFormulaToCNF(varphi[0], defs);
- convertTermForCNF(varphi[1], defs);
- ASTNode t1 = *(info[varphi[1]]->termforcnf);
- convertTermForCNF(varphi[2], defs);
- ASTNode t2 = *(info[varphi[2]]->termforcnf);
-
- //########################################
- // step 4, add def clauses
- //########################################
-
- BeevMgr::ClauseList* cl1 = SINGLETON(bm->CreateNode(EQ, psi, t1));
- BeevMgr::ClauseList* cl2 = PRODUCT(*(info[varphi[0]]->clausesneg), *cl1);
- DELETE(cl1);
- defs->insert(defs->end(), cl2->begin(), cl2->end());
-
- BeevMgr::ClauseList* cl3 = SINGLETON(bm->CreateNode(EQ, psi, t2));
- BeevMgr::ClauseList* cl4 = PRODUCT(*(info[varphi[0]]->clausespos), *cl3);
- DELETE(cl3);
- defs->insert(defs->end(), cl4->begin(), cl4->end());
-
- return ASTNodeToASTNodePtr(psi);
- }
-
- void doRenamingPos(const ASTNode& varphi, BeevMgr::ClauseList* defs){
-
- CNFInfo* x = info[varphi];
-
- //########################################
- // step 1, calc new variable
- //########################################
-
- ostringstream oss;
- oss << "cnf" << "{" << varphi.GetNodeNum() << "}";
- ASTNode psi = bm->CreateSymbol(oss.str().c_str());
-
- //########################################
- // step 2, add defs
- //########################################
-
- BeevMgr::ClauseList* cl1;
- cl1 = SINGLETON(bm->CreateNode(NOT, psi));
- BeevMgr::ClauseList* cl2 = PRODUCT(*(info[varphi]->clausespos), *cl1);
- defs->insert(defs->end(), cl2->begin(), cl2->end());
- DELETE(info[varphi]->clausespos);
- DELETE(cl1);
- delete cl2;
-
- //########################################
- // step 3, update info[varphi]
- //########################################
-
- x->clausespos = SINGLETON(psi);
- setWasRenamedPos(*x);
- }
-
- void doRenamingNeg(const ASTNode& varphi, BeevMgr::ClauseList* defs){
-
- CNFInfo* x = info[varphi];
-
- //########################################
- // step 2, calc new variable
- //########################################
-
- ostringstream oss;
- oss << "cnf" << "{" << varphi.GetNodeNum() << "}";
- ASTNode psi = bm->CreateSymbol(oss.str().c_str());
-
- //########################################
- // step 3, add defs
- //########################################
-
- BeevMgr::ClauseList* cl1;
- cl1 = SINGLETON(psi);
- BeevMgr::ClauseList* cl2 = PRODUCT(*(info[varphi]->clausesneg), *cl1);
- defs->insert(defs->end(), cl2->begin(), cl2->end());
- DELETE(info[varphi]->clausesneg);
- DELETE(cl1);
- delete cl2;
-
- //########################################
- // step 4, update info[varphi]
- //########################################
-
- x->clausesneg = SINGLETON(bm->CreateNode(NOT, psi));
- setWasRenamedNeg(*x);
-
- }
-
- //########################################
- //########################################
- //main switch for individual cnf conversion cases
-
- void convertFormulaToCNFPosCases(const ASTNode& varphi, BeevMgr::ClauseList* defs){
-
- if(isPred(varphi)){
- convertFormulaToCNFPosPred(varphi, defs);
- return;
- }
-
-
- Kind k = varphi.GetKind();
- switch ( k ){
- case FALSE: {
- convertFormulaToCNFPosFALSE(varphi, defs);
- break;
- }
- case TRUE: {
- convertFormulaToCNFPosTRUE(varphi, defs);
- break;
- }
- case BVGETBIT: {
- convertFormulaToCNFPosBVGETBIT(varphi, defs);
- break;
- }
- case SYMBOL: {
- convertFormulaToCNFPosSYMBOL(varphi, defs);
- break;
- }
- case NOT: {
- convertFormulaToCNFPosNOT(varphi, defs);
- break;
- }
- case AND: {
- convertFormulaToCNFPosAND(varphi, defs);
- break;
- }
- case NAND: {
- convertFormulaToCNFPosNAND(varphi, defs);
- break;
- }
- case OR: {
- convertFormulaToCNFPosOR(varphi, defs);
- break;
- }
- case NOR: {
- convertFormulaToCNFPosNOR(varphi, defs);
- break;
- }
- case XOR: {
- convertFormulaToCNFPosXOR(varphi, defs);
- break;
- }
- case IMPLIES: {
- convertFormulaToCNFPosIMPLIES(varphi, defs);
- break;
- }
- case ITE: {
- convertFormulaToCNFPosITE(varphi, defs);
- break;
- }
- default: {
- fprintf(stderr, "convertFormulaToCNFPosCases: doesn't handle kind %d\n", k);
- FatalError("");
- }
- }
- }
-
- void convertFormulaToCNFNegCases(const ASTNode& varphi, BeevMgr::ClauseList* defs){
-
- if(isPred(varphi)){
- convertFormulaToCNFNegPred(varphi, defs);
- return;
- }
-
-
- Kind k = varphi.GetKind();
- switch ( k ){
- case FALSE: {
- convertFormulaToCNFNegFALSE(varphi, defs);
- break;
- }
- case TRUE: {
- convertFormulaToCNFNegTRUE(varphi, defs);
- break;
- }
- case BVGETBIT: {
- convertFormulaToCNFNegBVGETBIT(varphi, defs);
- break;
- }
- case SYMBOL: {
- convertFormulaToCNFNegSYMBOL(varphi, defs);
- break;
- }
- case NOT: {
- convertFormulaToCNFNegNOT(varphi, defs);
- break;
- }
- case AND: {
- convertFormulaToCNFNegAND(varphi, defs);
- break;
- }
- case NAND: {
- convertFormulaToCNFNegNAND(varphi, defs);
- break;
- }
- case OR: {
- convertFormulaToCNFNegOR(varphi, defs);
- break;
- }
- case NOR: {
- convertFormulaToCNFNegNOR(varphi, defs);
- break;
- }
- case XOR: {
- convertFormulaToCNFNegXOR(varphi, defs);
- break;
- }
- case IMPLIES: {
- convertFormulaToCNFNegIMPLIES(varphi, defs);
- break;
- }
- case ITE: {
- convertFormulaToCNFNegITE(varphi, defs);
- break;
- }
- default: {
- fprintf(stderr, "convertFormulaToCNFNegCases: doesn't handle kind %d\n", k);
- FatalError("");
- }
- }
- }
-
- //########################################
- //########################################
- // individual cnf conversion cases
-
- void convertFormulaToCNFPosPred(const ASTNode& varphi, BeevMgr::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));
- }
-
- void convertFormulaToCNFPosFALSE(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- ASTNode dummy_false_var = bm->CreateNode(NOT, bm->CreateSymbol("*TrueDummy*"));
- info[varphi]->clausespos = SINGLETON(dummy_false_var);
- }
-
- void convertFormulaToCNFPosTRUE(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- ASTNode dummy_true_var = bm->CreateSymbol("*TrueDummy*");
- info[varphi]->clausespos = SINGLETON(dummy_true_var);
- }
-
- void convertFormulaToCNFPosBVGETBIT(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- info[varphi]->clausespos = SINGLETON(varphi);
- }
-
- void convertFormulaToCNFPosSYMBOL(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- info[varphi]->clausespos = SINGLETON(varphi);
- }
-
- void convertFormulaToCNFPosNOT(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- convertFormulaToCNF(varphi[0], defs);
- info[varphi]->clausespos = COPY(*(info[varphi[0]]->clausesneg));
- reduceMemoryFootprintNeg(varphi[0]);
- }
-
- void convertFormulaToCNFPosAND(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- //****************************************
- // (pos) AND ~> UNION
- //****************************************
- ASTVec::const_iterator it = varphi.GetChildren().begin();
- convertFormulaToCNF(*it, defs);
- BeevMgr::ClauseList* psi = COPY(*(info[*it]->clausespos));
- for(it++; it != varphi.GetChildren().end(); it++){
- convertFormulaToCNF(*it, defs);
- INPLACE_UNION(psi, *(info[*it]->clausespos));
- reduceMemoryFootprintPos(*it);
- }
-
- info[varphi]->clausespos = psi;
- }
-
- void convertFormulaToCNFPosNAND(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- bool renamesibs = false;
- BeevMgr::ClauseList* clauses;
- BeevMgr::ClauseList* psi;
- BeevMgr::ClauseList* oldpsi;
-
- //****************************************
- // (pos) NAND ~> PRODUCT NOT
- //****************************************
-
- ASTVec::const_iterator it = varphi.GetChildren().begin();
- convertFormulaToCNF(*it, defs);
- clauses = info[*it]->clausesneg;
- if(clauses->size() > 1){
- renamesibs = true;
- }
- psi = 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;
- }
- oldpsi = psi;
- psi = PRODUCT(*psi, *clauses);
- reduceMemoryFootprintNeg(*it);
- DELETE(oldpsi);
- }
-
- info[varphi]->clausespos = psi;
- }
-
- void convertFormulaToCNFPosOR(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- bool renamesibs = false;
- BeevMgr::ClauseList* clauses;
- BeevMgr::ClauseList* psi;
- BeevMgr::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 = 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 = PRODUCT(*psi, *clauses);
- reduceMemoryFootprintPos(*it);
- DELETE(oldpsi);
- }
-
- info[varphi]->clausespos = psi;
- }
-
- void convertFormulaToCNFPosNOR(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- //****************************************
- // (pos) NOR ~> UNION NOT
- //****************************************
- ASTVec::const_iterator it = varphi.GetChildren().begin();
- convertFormulaToCNF(*it, defs);
- BeevMgr::ClauseList* psi = COPY(*(info[*it]->clausesneg));
- reduceMemoryFootprintNeg(*it);
- for(it++; it != varphi.GetChildren().end(); it++){
- convertFormulaToCNF(*it, defs);
- INPLACE_UNION(psi, *(info[*it]->clausesneg));
- reduceMemoryFootprintNeg(*it);
- }
-
- info[varphi]->clausespos = psi;
- }
-
- void convertFormulaToCNFPosIMPLIES(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- //****************************************
- // (pos) IMPLIES ~> PRODUCT NOT [0] ; [1]
- //****************************************
- CNFInfo* x0 = info[varphi[0]];
- CNFInfo* x1 = info[varphi[1]];
- convertFormulaToCNF(varphi[0], defs);
- if(x0->clausesneg->size() > 1){
- setDoSibRenamingPos(*x1);
- }
- convertFormulaToCNF(varphi[1], defs);
- BeevMgr::ClauseList* psi =
- PRODUCT(*(x0->clausesneg), *(x1->clausespos));
- reduceMemoryFootprintNeg(varphi[0]);
- reduceMemoryFootprintPos(varphi[1]);
- info[varphi]->clausespos = psi;
- }
-
- void convertFormulaToCNFPosITE(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- //****************************************
- // (pos) ITE ~> UNION (PRODUCT NOT [0] ; [1])
- // ; (PRODUCT [0] ; [2])
- //****************************************
- CNFInfo* x0 = info[varphi[0]];
- CNFInfo* x1 = info[varphi[1]];
- CNFInfo* x2 = info[varphi[2]];
- convertFormulaToCNF(varphi[0], defs);
- if(x0->clausesneg->size() > 1){
- setDoSibRenamingPos(*x1);
- }
- convertFormulaToCNF(varphi[1], defs);
- if(x0->clausespos->size() > 1){
- setDoSibRenamingPos(*x2);
- }
- convertFormulaToCNF(varphi[2], defs);
- BeevMgr::ClauseList* psi1 = PRODUCT(*(x0->clausesneg)
- , *(x1->clausespos));
- BeevMgr::ClauseList* psi2 = PRODUCT(*(x0->clausespos)
- , *(x2->clausespos));
- NOCOPY_INPLACE_UNION(psi1, psi2);
- reduceMemoryFootprintNeg(varphi[0]);
- reduceMemoryFootprintPos(varphi[1]);
- reduceMemoryFootprintPos(varphi[0]);
- reduceMemoryFootprintPos(varphi[2]);
-
- info[varphi]->clausespos = psi1;
- }
-
- void convertFormulaToCNFPosXOR(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- BeevMgr::ClauseList* psi = convertFormulaToCNFPosXORAux(varphi, 0, defs);
- info[varphi]->clausespos = psi;
- }
-
- BeevMgr::ClauseList* convertFormulaToCNFPosXORAux(const ASTNode& varphi
- , unsigned int idx, BeevMgr::ClauseList* defs){
-
- bool renamesibs;
- BeevMgr::ClauseList* psi;
- BeevMgr::ClauseList* psi1;
- BeevMgr::ClauseList* psi2;
-
- if(idx == varphi.GetChildren().size() - 2){
- //****************************************
- // (pos) XOR ~> UNION
- // (PRODUCT [idx] ; [idx+1])
- // ; (PRODUCT NOT [idx] ; NOT [idx+1])
- //****************************************
- convertFormulaToCNF(varphi[idx], defs);
- renamesibs = (info[varphi[idx]]->clausespos)->size() > 1 ? true : false;
- if(renamesibs){
- setDoSibRenamingPos(*info[varphi[idx+1]]);
- }
- renamesibs = (info[varphi[idx]]->clausesneg)->size() > 1 ? true : false;
- if(renamesibs){
- setDoSibRenamingNeg(*info[varphi[idx+1]]);
- }
- convertFormulaToCNF(varphi[idx+1], defs);
-
- psi1 = PRODUCT(*(info[varphi[idx]]->clausespos), *(info[varphi[idx+1]]->clausespos));
- psi2 = PRODUCT(*(info[varphi[idx]]->clausesneg), *(info[varphi[idx+1]]->clausesneg));
- NOCOPY_INPLACE_UNION(psi1, psi2);
- reduceMemoryFootprintPos(varphi[idx]);
- reduceMemoryFootprintPos(varphi[idx+1]);
- reduceMemoryFootprintNeg(varphi[idx]);
- reduceMemoryFootprintNeg(varphi[idx+1]);
-
- psi = psi1;
- } else {
- //****************************************
- // (pos) XOR ~> UNION
- // (PRODUCT [idx] ; XOR [idx+1..])
- // ; (PRODUCT NOT [idx] ; NOT XOR [idx+1..])
- //****************************************
- BeevMgr::ClauseList* theta1;
- theta1 = convertFormulaToCNFPosXORAux(varphi, idx+1, defs);
- renamesibs = theta1->size() > 1 ? true : false;
- if(renamesibs){
- setDoSibRenamingPos(*info[varphi[idx]]);
- }
- BeevMgr::ClauseList* theta2;
- theta2 = convertFormulaToCNFNegXORAux(varphi, idx+1, defs);
- renamesibs = theta2->size() > 1 ? true : false;
- if(renamesibs){
- setDoSibRenamingNeg(*info[varphi[idx]]);
- }
- convertFormulaToCNF(varphi[idx], defs);
-
- psi1 = PRODUCT(*(info[varphi[idx]]->clausespos), *theta1);
- psi2 = PRODUCT(*(info[varphi[idx]]->clausesneg), *theta2);
- DELETE(theta1);
- DELETE(theta2);
- NOCOPY_INPLACE_UNION(psi1, psi2);
- reduceMemoryFootprintPos(varphi[idx]);
- reduceMemoryFootprintNeg(varphi[idx]);
-
- psi = psi1;
- }
-
- return psi;
- }
-
- void convertFormulaToCNFNegPred(const ASTNode& varphi, BeevMgr::ClauseList* defs){
-
- ASTVec psis;
-
- ASTVec::const_iterator it = varphi.GetChildren().begin();
- for(; it != varphi.GetChildren().end(); it++){
- convertFormulaToCNF(*it, defs);
- psis.push_back(*(info[*it]->termforcnf));
- }
-
- info[varphi]->clausesneg = SINGLETON(bm->CreateNode(NOT, bm->CreateNode(varphi.GetKind(), psis)));
- }
-
- void convertFormulaToCNFNegFALSE(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- ASTNode dummy_true_var = bm->CreateSymbol("*TrueDummy*");
- info[varphi]->clausesneg = SINGLETON(dummy_true_var);
- }
-
- void convertFormulaToCNFNegTRUE(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- ASTNode dummy_false_var = bm->CreateNode(NOT, bm->CreateSymbol("*TrueDummy*"));
- info[varphi]->clausesneg = SINGLETON(dummy_false_var);
- }
-
- void convertFormulaToCNFNegBVGETBIT(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- BeevMgr::ClauseList* psi = SINGLETON(bm->CreateNode(NOT, varphi));
- info[varphi]->clausesneg = psi;
- }
-
- void convertFormulaToCNFNegSYMBOL(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- info[varphi]->clausesneg = SINGLETON(bm->CreateNode(NOT, varphi));
- }
-
- void convertFormulaToCNFNegNOT(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- convertFormulaToCNF(varphi[0], defs);
- info[varphi]->clausesneg = COPY(*(info[varphi[0]]->clausespos));
- reduceMemoryFootprintPos(varphi[0]);
- }
-
- void convertFormulaToCNFNegAND(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- bool renamesibs = false;
- BeevMgr::ClauseList* clauses;
- BeevMgr::ClauseList* psi;
- BeevMgr::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 = 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;
- }
- oldpsi = psi;
- psi = PRODUCT(*psi, *clauses);
- reduceMemoryFootprintNeg(*it);
- DELETE(oldpsi);
- }
-
- info[varphi]->clausesneg = psi;
- }
-
- void convertFormulaToCNFNegNAND(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- //****************************************
- // (neg) NAND ~> UNION
- //****************************************
- ASTVec::const_iterator it = varphi.GetChildren().begin();
- convertFormulaToCNF(*it, defs);
- BeevMgr::ClauseList* psi = COPY(*(info[*it]->clausespos));
- reduceMemoryFootprintPos(*it);
- for(it++; it != varphi.GetChildren().end(); it++){
- convertFormulaToCNF(*it, defs);
- INPLACE_UNION(psi, *(info[*it]->clausespos));
- reduceMemoryFootprintPos(*it);
- }
-
- info[varphi]->clausespos = psi;
- }
-
- void convertFormulaToCNFNegOR(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- //****************************************
- // (neg) OR ~> UNION NOT
- //****************************************
- ASTVec::const_iterator it = varphi.GetChildren().begin();
- convertFormulaToCNF(*it, defs);
- BeevMgr::ClauseList* psi = COPY(*(info[*it]->clausesneg));
- reduceMemoryFootprintNeg(*it);
- for(it++; it != varphi.GetChildren().end(); it++){
- convertFormulaToCNF(*it, defs);
- INPLACE_UNION(psi, *(info[*it]->clausesneg));
- reduceMemoryFootprintNeg(*it);
- }
-
- info[varphi]->clausesneg = psi;
- }
-
- void convertFormulaToCNFNegNOR(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- bool renamesibs = false;
- BeevMgr::ClauseList* clauses;
- BeevMgr::ClauseList* psi;
- BeevMgr::ClauseList* oldpsi;
-
- //****************************************
- // (neg) NOR ~> PRODUCT
- //****************************************
- ASTVec::const_iterator it = varphi.GetChildren().begin();
- convertFormulaToCNF(*it, defs);
- clauses = info[*it]->clausespos;
- if(clauses->size() > 1){
- renamesibs = true;
- }
- psi = 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 = PRODUCT(*psi, *clauses);
- reduceMemoryFootprintPos(*it);
- DELETE(oldpsi);
- }
-
- info[varphi]->clausesneg = psi;
- }
-
- void convertFormulaToCNFNegIMPLIES(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- //****************************************
- // (neg) IMPLIES ~> UNION [0] ; NOT [1]
- //****************************************
- CNFInfo* x0 = info[varphi[0]];
- CNFInfo* x1 = info[varphi[1]];
- convertFormulaToCNF(varphi[0], defs);
- convertFormulaToCNF(varphi[1], defs);
- BeevMgr::ClauseList* psi =
- UNION(*(x0->clausespos), *(x1->clausesneg));
- info[varphi]->clausesneg = psi;
- reduceMemoryFootprintPos(varphi[0]);
- reduceMemoryFootprintNeg(varphi[1]);
- }
-
- void convertFormulaToCNFNegITE(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- //****************************************
- // (neg) ITE ~> UNION (PRODUCT NOT [0] ; NOT [1])
- // ; (PRODUCT [0] ; NOT [2])
- //****************************************
- CNFInfo* x0 = info[varphi[0]];
- CNFInfo* x1 = info[varphi[1]];
- CNFInfo* x2 = info[varphi[2]];
- convertFormulaToCNF(varphi[0], defs);
- if(x0->clausesneg->size() > 1){
- setDoSibRenamingNeg(*x1);
- }
- convertFormulaToCNF(varphi[1], defs);
- if(x0->clausespos->size() > 1){
- setDoSibRenamingNeg(*x2);
- }
- convertFormulaToCNF(varphi[2], defs);
- BeevMgr::ClauseList* psi1 = PRODUCT(*(x0->clausesneg)
- , *(x1->clausesneg));
- BeevMgr::ClauseList* psi2 = PRODUCT(*(x0->clausespos)
- , *(x2->clausesneg));
- NOCOPY_INPLACE_UNION(psi1, psi2);
- reduceMemoryFootprintNeg(varphi[0]);
- reduceMemoryFootprintNeg(varphi[1]);
- reduceMemoryFootprintPos(varphi[0]);
- reduceMemoryFootprintNeg(varphi[2]);
-
- info[varphi]->clausesneg = psi1;
- }
-
- void convertFormulaToCNFNegXOR(const ASTNode& varphi, BeevMgr::ClauseList* defs){
- BeevMgr::ClauseList* psi = convertFormulaToCNFNegXORAux(varphi, 0, defs);
- info[varphi]->clausesneg = psi;
- }
-
- BeevMgr::ClauseList* convertFormulaToCNFNegXORAux(const ASTNode& varphi
- , unsigned int idx, BeevMgr::ClauseList* defs){
-
- bool renamesibs;
- BeevMgr::ClauseList* psi;
- BeevMgr::ClauseList* psi1;
- BeevMgr::ClauseList* psi2;
-
- if(idx == varphi.GetChildren().size() - 2){
-
- //****************************************
- // (neg) XOR ~> UNION
- // (PRODUCT NOT [idx] ; [idx+1])
- // ; (PRODUCT [idx] ; NOT [idx+1])
- //****************************************
- convertFormulaToCNF(varphi[idx], defs);
- renamesibs = (info[varphi[idx]]->clausesneg)->size() > 1 ? true : false;
- if(renamesibs){
- setDoSibRenamingPos(*info[varphi[idx+1]]);
- }
- convertFormulaToCNF(varphi[idx+1], defs);
-
-
- convertFormulaToCNF(varphi[idx], defs);
- renamesibs = (info[varphi[idx]]->clausespos)->size() > 1 ? true : false;
- if(renamesibs){
- setDoSibRenamingNeg(*info[varphi[idx+1]]);
- }
- convertFormulaToCNF(varphi[idx+1], defs);
-
- psi1 = PRODUCT(*(info[varphi[idx]]->clausesneg), *(info[varphi[idx+1]]->clausespos));
- psi2 = PRODUCT(*(info[varphi[idx]]->clausespos), *(info[varphi[idx+1]]->clausesneg));
- NOCOPY_INPLACE_UNION(psi1, psi2);
- reduceMemoryFootprintNeg(varphi[idx]);
- reduceMemoryFootprintPos(varphi[idx+1]);
- reduceMemoryFootprintPos(varphi[idx]);
- reduceMemoryFootprintNeg(varphi[idx+1]);
-
- psi = psi1;
- } else {
-
- //****************************************
- // (neg) XOR ~> UNION
- // (PRODUCT NOT [idx] ; XOR [idx+1..])
- // ; (PRODUCT [idx] ; NOT XOR [idx+1..])
- //****************************************
- BeevMgr::ClauseList* theta1;
- theta1 = convertFormulaToCNFPosXORAux(varphi, idx+1, defs);
- renamesibs = theta1->size() > 1 ? true : false;
- if(renamesibs){
- setDoSibRenamingNeg(*info[varphi[idx]]);
- }
- convertFormulaToCNF(varphi[idx], defs);
-
-
- BeevMgr::ClauseList* theta2;
- theta2 = convertFormulaToCNFNegXORAux(varphi, idx+1, defs);
- renamesibs = theta2->size() > 1 ? true : false;
- if(renamesibs){
- setDoSibRenamingPos(*info[varphi[idx]]);
- }
- convertFormulaToCNF(varphi[idx], defs);
-
- psi1 = PRODUCT(*(info[varphi[idx]]->clausesneg), *theta1);
- psi2 = PRODUCT(*(info[varphi[idx]]->clausespos), *theta2);
- DELETE(theta1);
- DELETE(theta2);
- NOCOPY_INPLACE_UNION(psi1, psi2);
- reduceMemoryFootprintNeg(varphi[idx]);
- reduceMemoryFootprintPos(varphi[idx]);
-
- psi = psi1;
- }
-
- return psi;
- }
-
- //########################################
- //########################################
- // utilities for reclaiming memory.
-
- void reduceMemoryFootprintPos(const ASTNode& varphi){
-
- CNFInfo* x = info[varphi];
- if(sharesPos(*x) == 1){
- DELETE(x->clausespos);
- x->clausespos = NULL;
- if(x->clausesneg == NULL){
- delete x;
- info.erase(varphi);
- }
- }
- }
-
- void reduceMemoryFootprintNeg(const ASTNode& varphi){
-
- CNFInfo* x = info[varphi];
- if(sharesNeg(*x) == 1){
- DELETE(x->clausesneg);
- x->clausesneg = NULL;
- if(x->clausespos == NULL){
- delete x;
- info.erase(varphi);
- }
- }
- }
-
- //########################################
- //########################################
-
- ASTNode* ASTNodeToASTNodePtr(const ASTNode& varphi){
- ASTNode* psi;
-
- if(store.find(varphi) != store.end()){
- psi = store[varphi];
- } else {
- psi = new ASTNode(varphi);
- store[varphi] = psi;
- }
-
- return psi;
- }
-
- //########################################
- //########################################
-
- void cleanup(const ASTNode& varphi){
- delete info[varphi]->clausespos;
- info.erase(varphi);
-
- ASTNodeToCNFInfoMap::const_iterator it1 = info.begin();
- for(; it1 != info.end(); it1++){
- CNFInfo* x = it1->second;
- if(x->clausespos != NULL){
- DELETE(x->clausespos);
- }
- if(x->clausesneg != NULL){
- if(!isTerm(*x)){
- DELETE(x->clausesneg);
- }
- }
- delete x;
- }
-
- info.clear();
- }
+ void convertFormulaToCNFNegPred(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+
+ ASTVec psis;
+
+ ASTVec::const_iterator it = varphi.GetChildren().begin();
+ for (; it != varphi.GetChildren().end(); it++)
+ {
+ convertFormulaToCNF(*it, defs);
+ psis.push_back(*(info[*it]->termforcnf));
+ }
+
+ info[varphi]->clausesneg = SINGLETON(bm->CreateNode(NOT, bm->CreateNode(varphi.GetKind(), psis)));
+ }
+
+ void convertFormulaToCNFNegFALSE(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ ASTNode dummy_true_var = bm->CreateSymbol("*TrueDummy*");
+ info[varphi]->clausesneg = SINGLETON(dummy_true_var);
+ }
+
+ void convertFormulaToCNFNegTRUE(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ ASTNode dummy_false_var = bm->CreateNode(NOT, bm->CreateSymbol("*TrueDummy*"));
+ info[varphi]->clausesneg = SINGLETON(dummy_false_var);
+ }
+
+ void convertFormulaToCNFNegBVGETBIT(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ BeevMgr::ClauseList* psi = SINGLETON(bm->CreateNode(NOT, varphi));
+ info[varphi]->clausesneg = psi;
+ }
+
+ void convertFormulaToCNFNegSYMBOL(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ info[varphi]->clausesneg = SINGLETON(bm->CreateNode(NOT, varphi));
+ }
+
+ void convertFormulaToCNFNegNOT(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ convertFormulaToCNF(varphi[0], defs);
+ info[varphi]->clausesneg = COPY(*(info[varphi[0]]->clausespos));
+ reduceMemoryFootprintPos(varphi[0]);
+ }
+
+ void convertFormulaToCNFNegAND(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ bool renamesibs = false;
+ BeevMgr::ClauseList* clauses;
+ BeevMgr::ClauseList* psi;
+ BeevMgr::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 = 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;
+ }
+ oldpsi = psi;
+ psi = PRODUCT(*psi, *clauses);
+ reduceMemoryFootprintNeg(*it);
+ DELETE(oldpsi);
+ }
+
+ info[varphi]->clausesneg = psi;
+ }
+
+ void convertFormulaToCNFNegNAND(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ //****************************************
+ // (neg) NAND ~> UNION
+ //****************************************
+ ASTVec::const_iterator it = varphi.GetChildren().begin();
+ convertFormulaToCNF(*it, defs);
+ BeevMgr::ClauseList* psi = COPY(*(info[*it]->clausespos));
+ reduceMemoryFootprintPos(*it);
+ for (it++; it != varphi.GetChildren().end(); it++)
+ {
+ convertFormulaToCNF(*it, defs);
+ INPLACE_UNION(psi, *(info[*it]->clausespos));
+ reduceMemoryFootprintPos(*it);
+ }
+
+ info[varphi]->clausespos = psi;
+ }
+
+ void convertFormulaToCNFNegOR(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ //****************************************
+ // (neg) OR ~> UNION NOT
+ //****************************************
+ ASTVec::const_iterator it = varphi.GetChildren().begin();
+ convertFormulaToCNF(*it, defs);
+ BeevMgr::ClauseList* psi = COPY(*(info[*it]->clausesneg));
+ reduceMemoryFootprintNeg(*it);
+ for (it++; it != varphi.GetChildren().end(); it++)
+ {
+ convertFormulaToCNF(*it, defs);
+ INPLACE_UNION(psi, *(info[*it]->clausesneg));
+ reduceMemoryFootprintNeg(*it);
+ }
+
+ info[varphi]->clausesneg = psi;
+ }
+
+ void convertFormulaToCNFNegNOR(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ bool renamesibs = false;
+ BeevMgr::ClauseList* clauses;
+ BeevMgr::ClauseList* psi;
+ BeevMgr::ClauseList* oldpsi;
+
+ //****************************************
+ // (neg) NOR ~> PRODUCT
+ //****************************************
+ ASTVec::const_iterator it = varphi.GetChildren().begin();
+ convertFormulaToCNF(*it, defs);
+ clauses = info[*it]->clausespos;
+ if (clauses->size() > 1)
+ {
+ renamesibs = true;
+ }
+ psi = 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 = PRODUCT(*psi, *clauses);
+ reduceMemoryFootprintPos(*it);
+ DELETE(oldpsi);
+ }
+
+ info[varphi]->clausesneg = psi;
+ }
+
+ void convertFormulaToCNFNegIMPLIES(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ //****************************************
+ // (neg) IMPLIES ~> UNION [0] ; NOT [1]
+ //****************************************
+ CNFInfo* x0 = info[varphi[0]];
+ CNFInfo* x1 = info[varphi[1]];
+ convertFormulaToCNF(varphi[0], defs);
+ convertFormulaToCNF(varphi[1], defs);
+ BeevMgr::ClauseList* psi = UNION(*(x0->clausespos), *(x1->clausesneg));
+ info[varphi]->clausesneg = psi;
+ reduceMemoryFootprintPos(varphi[0]);
+ reduceMemoryFootprintNeg(varphi[1]);
+ }
+
+ void convertFormulaToCNFNegITE(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ //****************************************
+ // (neg) ITE ~> UNION (PRODUCT NOT [0] ; NOT [1])
+ // ; (PRODUCT [0] ; NOT [2])
+ //****************************************
+ CNFInfo* x0 = info[varphi[0]];
+ CNFInfo* x1 = info[varphi[1]];
+ CNFInfo* x2 = info[varphi[2]];
+ convertFormulaToCNF(varphi[0], defs);
+ if (x0->clausesneg->size() > 1)
+ {
+ setDoSibRenamingNeg(*x1);
+ }
+ convertFormulaToCNF(varphi[1], defs);
+ if (x0->clausespos->size() > 1)
+ {
+ setDoSibRenamingNeg(*x2);
+ }
+ convertFormulaToCNF(varphi[2], defs);
+ BeevMgr::ClauseList* psi1 = PRODUCT(*(x0->clausesneg), *(x1->clausesneg));
+ BeevMgr::ClauseList* psi2 = PRODUCT(*(x0->clausespos), *(x2->clausesneg));
+ NOCOPY_INPLACE_UNION(psi1, psi2);
+ reduceMemoryFootprintNeg(varphi[0]);
+ reduceMemoryFootprintNeg(varphi[1]);
+ reduceMemoryFootprintPos(varphi[0]);
+ reduceMemoryFootprintNeg(varphi[2]);
+
+ info[varphi]->clausesneg = psi1;
+ }
+
+ void convertFormulaToCNFNegXOR(const ASTNode& varphi, BeevMgr::ClauseList* defs)
+ {
+ BeevMgr::ClauseList* psi = convertFormulaToCNFNegXORAux(varphi, 0, defs);
+ info[varphi]->clausesneg = psi;
+ }
+
+ BeevMgr::ClauseList* convertFormulaToCNFNegXORAux(const ASTNode& varphi, unsigned int idx, BeevMgr::ClauseList* defs)
+ {
+
+ bool renamesibs;
+ BeevMgr::ClauseList* psi;
+ BeevMgr::ClauseList* psi1;
+ BeevMgr::ClauseList* psi2;
+
+ if (idx == varphi.GetChildren().size() - 2)
+ {
+
+ //****************************************
+ // (neg) XOR ~> UNION
+ // (PRODUCT NOT [idx] ; [idx+1])
+ // ; (PRODUCT [idx] ; NOT [idx+1])
+ //****************************************
+ convertFormulaToCNF(varphi[idx], defs);
+ renamesibs = (info[varphi[idx]]->clausesneg)->size() > 1 ? true : false;
+ if (renamesibs)
+ {
+ setDoSibRenamingPos(*info[varphi[idx + 1]]);
+ }
+ convertFormulaToCNF(varphi[idx + 1], defs);
+
+ convertFormulaToCNF(varphi[idx], defs);
+ renamesibs = (info[varphi[idx]]->clausespos)->size() > 1 ? true : false;
+ if (renamesibs)
+ {
+ setDoSibRenamingNeg(*info[varphi[idx + 1]]);
+ }
+ convertFormulaToCNF(varphi[idx + 1], defs);
+
+ psi1 = PRODUCT(*(info[varphi[idx]]->clausesneg), *(info[varphi[idx + 1]]->clausespos));
+ psi2 = PRODUCT(*(info[varphi[idx]]->clausespos), *(info[varphi[idx + 1]]->clausesneg));
+ NOCOPY_INPLACE_UNION(psi1, psi2);
+ reduceMemoryFootprintNeg(varphi[idx]);
+ reduceMemoryFootprintPos(varphi[idx + 1]);
+ reduceMemoryFootprintPos(varphi[idx]);
+ reduceMemoryFootprintNeg(varphi[idx + 1]);
+
+ psi = psi1;
+ }
+ else
+ {
+
+ //****************************************
+ // (neg) XOR ~> UNION
+ // (PRODUCT NOT [idx] ; XOR [idx+1..])
+ // ; (PRODUCT [idx] ; NOT XOR [idx+1..])
+ //****************************************
+ BeevMgr::ClauseList* theta1;
+ theta1 = convertFormulaToCNFPosXORAux(varphi, idx + 1, defs);
+ renamesibs = theta1->size() > 1 ? true : false;
+ if (renamesibs)
+ {
+ setDoSibRenamingNeg(*info[varphi[idx]]);
+ }
+ convertFormulaToCNF(varphi[idx], defs);
+
+ BeevMgr::ClauseList* theta2;
+ theta2 = convertFormulaToCNFNegXORAux(varphi, idx + 1, defs);
+ renamesibs = theta2->size() > 1 ? true : false;
+ if (renamesibs)
+ {
+ setDoSibRenamingPos(*info[varphi[idx]]);
+ }
+ convertFormulaToCNF(varphi[idx], defs);
+
+ psi1 = PRODUCT(*(info[varphi[idx]]->clausesneg), *theta1);
+ psi2 = PRODUCT(*(info[varphi[idx]]->clausespos), *theta2);
+ DELETE(theta1);
+ DELETE(theta2);
+ NOCOPY_INPLACE_UNION(psi1, psi2);
+ reduceMemoryFootprintNeg(varphi[idx]);
+ reduceMemoryFootprintPos(varphi[idx]);
+
+ psi = psi1;
+ }
+
+ return psi;
+ }
+
+ //########################################
+ //########################################
+ // utilities for reclaiming memory.
+
+ void reduceMemoryFootprintPos(const ASTNode& varphi)
+ {
+
+ CNFInfo* x = info[varphi];
+ if (sharesPos(*x) == 1)
+ {
+ DELETE(x->clausespos);
+ x->clausespos = NULL;
+ if (x->clausesneg == NULL)
+ {
+ delete x;
+ info.erase(varphi);
+ }
+ }
+ }
+
+ void reduceMemoryFootprintNeg(const ASTNode& varphi)
+ {
+
+ CNFInfo* x = info[varphi];
+ if (sharesNeg(*x) == 1)
+ {
+ DELETE(x->clausesneg);
+ x->clausesneg = NULL;
+ if (x->clausespos == NULL)
+ {
+ delete x;
+ info.erase(varphi);
+ }
+ }
+ }
+
+ //########################################
+ //########################################
+
+ ASTNode* ASTNodeToASTNodePtr(const ASTNode& varphi)
+ {
+ ASTNode* psi;
+
+ if (store.find(varphi) != store.end())
+ {
+ psi = store[varphi];
+ }
+ else
+ {
+ psi = new ASTNode(varphi);
+ store[varphi] = psi;
+ }
+
+ return psi;
+ }
+
+ //########################################
+ //########################################
+
+ void cleanup(const ASTNode& varphi)
+ {
+ delete info[varphi]->clausespos;
+ info.erase(varphi);
+
+ ASTNodeToCNFInfoMap::const_iterator it1 = info.begin();
+ for (; it1 != info.end(); it1++)
+ {
+ CNFInfo* x = it1->second;
+ if (x->clausespos != NULL)
+ {
+ DELETE(x->clausespos);
+ }
+ if (x->clausesneg != NULL)
+ {
+ if (!isTerm(*x))
+ {
+ DELETE(x->clausesneg);
+ }
+ }
+ delete x;
+ }
+
+ info.clear();
+ }
}; // end of CNFMgr class
- int BeevMgr::TopLevelSAT( const ASTNode& inputasserts, const ASTNode& query) {
-
- ASTNode q = CreateNode(AND, inputasserts, CreateNode(NOT,query));
- return TopLevelSATAux(q);
- }
-
- //############################################################
- //############################################################
-
-
- void BeevMgr::PrintClauseList(ostream& os, BeevMgr::ClauseList& cll)
- {
- int num_clauses = cll.size();
- os << "Clauses: " << endl << "=========================================" << endl;
- for(int i=0; i < num_clauses; i++) {
- os << "Clause " << i << endl
- << "-------------------------------------------" << endl;
- LispPrintVecSpecial(os, *cll[i], 0);
- os << endl
- << "-------------------------------------------" << endl;
- }
- }
-
- void BeevMgr::DeleteClauseList(BeevMgr::ClauseList *cllp)
- {
- BeevMgr::ClauseList::const_iterator iend = cllp->end();
- for (BeevMgr::ClauseList::const_iterator i = cllp->begin(); i < iend; i++) {
- delete *i;
- }
- delete cllp;
- }
-
- int BeevMgr::CallSAT_ResultCheck(MINISAT::Solver& newS,
- const ASTNode& q, const ASTNode& orig_input) {
- ASTNode BBFormula = BBForm(q);
- CNFMgr* cm = new CNFMgr(this);
- ClauseList* cl = cm->convertToCNF(BBFormula);
- if(stats)
- cerr << "Number of clauses:" << cl->size() << endl;
- //PrintClauseList(cout, *cl);
- bool sat = toSATandSolve(newS,*cl);
- cm->DELETE(cl);
- delete cm;
-
- if(!sat) {
- PrintOutput(true);
- return 1;
- }
- else if(newS.okay()) {
- CounterExampleMap.clear();
- ConstructCounterExample(newS);
- if (stats && print_nodes) {
- PrintSATModel(newS);
- }
- //check if the counterexample is good or not
- ComputeFormulaMap.clear();
- if(counterexample_checking_during_refinement)
- bvdiv_exception_occured = false;
- ASTNode orig_result = ComputeFormulaUsingModel(orig_input);
- if(!(ASTTrue == orig_result || ASTFalse == orig_result))
- FatalError("TopLevelSat: Original input must compute to true or false against model");
-
-// if(!arrayread_refinement && !(ASTTrue == orig_result)) {
-// print_counterexample = true;
-// PrintCounterExample(true);
-// FatalError("counterexample bogus : arrayread_refinement is switched off: "
-// "EITHER all LA axioms have not been added OR bitblaster() or ToCNF()"
-// "or satsolver() or counterexamplechecker() have a bug");
-// }
-
- // if the counterexample is indeed a good one, then return
- // invalid
- if(ASTTrue == orig_result) {
- //CheckCounterExample(newS.okay());
- PrintOutput(false);
- PrintCounterExample(newS.okay());
- PrintCounterExample_InOrder(newS.okay());
- return 0;
- }
- // counterexample is bogus: flag it
- else {
- if(stats && print_nodes) {
- cout << "Supposedly bogus one: \n";
- bool tmp = print_counterexample;
- print_counterexample = true;
- PrintCounterExample(true);
- print_counterexample = tmp;
- }
-
- return 2;
- }
- }
- else {
- PrintOutput(true);
- return -100;
- }
- } //end of CALLSAT_ResultCheck
+int BeevMgr::TopLevelSAT(const ASTNode& inputasserts, const ASTNode& query)
+{
+
+ ASTNode q = CreateNode(AND, inputasserts, CreateNode(NOT, query));
+ return TopLevelSATAux(q);
+}
+
+//############################################################
+//############################################################
+
+
+void BeevMgr::PrintClauseList(ostream& os, BeevMgr::ClauseList& cll)
+{
+ int num_clauses = cll.size();
+ os << "Clauses: " << endl << "=========================================" << endl;
+ for (int i = 0; i < num_clauses; i++)
+ {
+ os << "Clause " << i << endl << "-------------------------------------------" << endl;
+ LispPrintVecSpecial(os, *cll[i], 0);
+ os << endl << "-------------------------------------------" << endl;
+ }
+}
+
+void BeevMgr::DeleteClauseList(BeevMgr::ClauseList *cllp)
+{
+ BeevMgr::ClauseList::const_iterator iend = cllp->end();
+ for (BeevMgr::ClauseList::const_iterator i = cllp->begin(); i < iend; i++)
+ {
+ delete *i;
+ }
+ delete cllp;
+}
+
+int BeevMgr::CallSAT_ResultCheck(MINISAT::Solver& newS, const ASTNode& q, const ASTNode& orig_input)
+{
+ ASTNode BBFormula = BBForm(q);
+ CNFMgr* cm = new CNFMgr(this);
+ ClauseList* cl = cm->convertToCNF(BBFormula);
+ if (stats)
+ cerr << "Number of clauses:" << cl->size() << endl;
+ //PrintClauseList(cout, *cl);
+ bool sat = toSATandSolve(newS, *cl);
+ cm->DELETE(cl);
+ delete cm;
+
+ if (!sat)
+ {
+ PrintOutput(true);
+ return 1;
+ }
+ else if (newS.okay())
+ {
+ CounterExampleMap.clear();
+ ConstructCounterExample(newS);
+ if (stats && print_nodes)
+ {
+ PrintSATModel(newS);
+ }
+ //check if the counterexample is good or not
+ ComputeFormulaMap.clear();
+ if (counterexample_checking_during_refinement)
+ bvdiv_exception_occured = false;
+ ASTNode orig_result = ComputeFormulaUsingModel(orig_input);
+ if (!(ASTTrue == orig_result || ASTFalse == orig_result))
+ FatalError("TopLevelSat: Original input must compute to true or false against model");
+
+ // if(!arrayread_refinement && !(ASTTrue == orig_result)) {
+ // print_counterexample = true;
+ // PrintCounterExample(true);
+ // FatalError("counterexample bogus : arrayread_refinement is switched off: "
+ // "EITHER all LA axioms have not been added OR bitblaster() or ToCNF()"
+ // "or satsolver() or counterexamplechecker() have a bug");
+ // }
+
+ // if the counterexample is indeed a good one, then return
+ // invalid
+ if (ASTTrue == orig_result)
+ {
+ //CheckCounterExample(newS.okay());
+ PrintOutput(false);
+ PrintCounterExample(newS.okay());
+ PrintCounterExample_InOrder(newS.okay());
+ return 0;
+ }
+ // counterexample is bogus: flag it
+ else
+ {
+ if (stats && print_nodes)
+ {
+ cout << "Supposedly bogus one: \n";
+ bool tmp = print_counterexample;
+ print_counterexample = true;
+ PrintCounterExample(true);
+ print_counterexample = tmp;
+ }
+
+ return 2;
+ }
+ }
+ else
+ {
+ PrintOutput(true);
+ return -100;
+ }
+} //end of CALLSAT_ResultCheck
} // end namespace
#include "../simplifier/bvsolver.h"
#include <math.h>
+namespace BEEV
+{
+/* FUNCTION: lookup or create a new MINISAT literal
+ * lookup or create new MINISAT Vars from the global MAP
+ * _ASTNode_to_SATVar.
+ */
+const MINISAT::Var BeevMgr::LookupOrCreateSATVar(MINISAT::Solver& newS, const ASTNode& n)
+{
+ ASTtoSATMap::iterator it;
+ MINISAT::Var v;
+
+ //look for the symbol in the global map from ASTNodes to ints. if
+ //not found, create a S.newVar(), else use the existing one.
+ if ((it = _ASTNode_to_SATVar.find(n)) == _ASTNode_to_SATVar.end())
+ {
+ v = newS.newVar();
+ _ASTNode_to_SATVar[n] = v;
+
+ //ASSUMPTION: I am assuming that the newS.newVar() call increments v
+ //by 1 each time it is called, and the initial value of a
+ //MINISAT::Var is 0.
+ _SATVar_to_AST.push_back(n);
+ }
+ else
+ v = it->second;
+ return v;
+}
+
+/* FUNCTION: convert ASTClauses to MINISAT clauses and solve.
+ * Accepts ASTClauses and converts them to MINISAT clauses. Then adds
+ * the newly minted MINISAT clauses to the local SAT instance, and
+ * calls solve(). If solve returns unsat, then stop and return
+ * unsat. else continue.
+ */
+// FIXME: Still need to deal with TRUE/FALSE in clauses!
+//bool BeevMgr::toSATandSolve(MINISAT::Solver& newS, BeevMgr::ClauseList& cll, ASTNodeToIntMap& heuristic)
+bool BeevMgr::toSATandSolve(MINISAT::Solver& newS, BeevMgr::ClauseList& cll)
+{
+ CountersAndStats("SAT Solver");
+
+ //iterate through the list (conjunction) of ASTclauses cll
+ BeevMgr::ClauseList::const_iterator i = cll.begin(), iend = cll.end();
+
+ if (i == iend)
+ FatalError("toSATandSolve: Nothing to Solve", ASTUndefined);
+
+ //turnOffSubsumption
+ // MKK: My understanding is that the rougly equivalent effect is had
+ // through setting the second argument of MINISAT::Solver::solve to
+ // true
+ //newS.turnOffSubsumption();
+
+ // (*i) is an ASTVec-ptr which denotes an ASTclause
+ //****************************************
+ // *i = vector<const ASTNode*>*
+ //****************************************
+ for (; i != iend; i++)
+ {
+ //Clause for the SATSolver
+ MINISAT::vec<MINISAT::Lit> satSolverClause;
+
+ //now iterate through the internals of the ASTclause itself
+ vector<const ASTNode*>::const_iterator j = (*i)->begin(), jend = (*i)->end();
+ //j is a disjunct in the ASTclause (*i)
+ for (; j != jend; j++)
+ {
+ ASTNode node = **j;
+
+ bool negate = (NOT == node.GetKind()) ? true : false;
+ ASTNode n = negate ? node[0] : node;
+
+ //Lookup or create the MINISAT::Var corresponding to the Booelan
+ //ASTNode Variable, and push into sat Solver clause
+ MINISAT::Var v = LookupOrCreateSATVar(newS, n);
+ MINISAT::Lit l(v, negate);
+ satSolverClause.push(l);
+ }
+ newS.addClause(satSolverClause);
+ // clause printing.
+ // (printClause<MINISAT::vec<MINISAT::Lit> >)(satSolverClause);
+ // cout << " 0 ";
+ // cout << endl;
+
+ if (newS.okay())
+ {
+ continue;
+ }
+ else
+ {
+ PrintStats(newS);
+ return false;
+ }
+
+ if (!newS.simplify())
+ {
+ PrintStats(newS);
+ return false;
+ }
+ }
+
+ // if input is UNSAT return false, else return true
+ if (!newS.simplify())
+ {
+ PrintStats(newS);
+ return false;
+ }
+
+ //PrintActivityLevels_Of_SATVars("Before SAT:",newS);
+ //ChangeActivityLevels_Of_SATVars(newS);
+ //PrintActivityLevels_Of_SATVars("Before SAT and after initial bias:",newS);
+ newS.solve();
+ //PrintActivityLevels_Of_SATVars("After SAT",newS);
-namespace BEEV {
- /* FUNCTION: lookup or create a new MINISAT literal
- * lookup or create new MINISAT Vars from the global MAP
- * _ASTNode_to_SATVar.
- */
- const MINISAT::Var BeevMgr::LookupOrCreateSATVar(MINISAT::Solver& newS, const ASTNode& n) {
- ASTtoSATMap::iterator it;
- MINISAT::Var v;
-
- //look for the symbol in the global map from ASTNodes to ints. if
- //not found, create a S.newVar(), else use the existing one.
- if((it = _ASTNode_to_SATVar.find(n)) == _ASTNode_to_SATVar.end()) {
- v = newS.newVar();
- _ASTNode_to_SATVar[n] = v;
-
- //ASSUMPTION: I am assuming that the newS.newVar() call increments v
- //by 1 each time it is called, and the initial value of a
- //MINISAT::Var is 0.
- _SATVar_to_AST.push_back(n);
- }
- else
- v = it->second;
- return v;
- }
-
- /* FUNCTION: convert ASTClauses to MINISAT clauses and solve.
- * Accepts ASTClauses and converts them to MINISAT clauses. Then adds
- * the newly minted MINISAT clauses to the local SAT instance, and
- * calls solve(). If solve returns unsat, then stop and return
- * unsat. else continue.
- */
- // FIXME: Still need to deal with TRUE/FALSE in clauses!
- //bool BeevMgr::toSATandSolve(MINISAT::Solver& newS, BeevMgr::ClauseList& cll, ASTNodeToIntMap& heuristic)
- bool BeevMgr::toSATandSolve(MINISAT::Solver& newS, BeevMgr::ClauseList& cll)
- {
- CountersAndStats("SAT Solver");
-
- //iterate through the list (conjunction) of ASTclauses cll
- BeevMgr::ClauseList::const_iterator i = cll.begin(), iend = cll.end();
-
- if(i == iend)
- FatalError("toSATandSolve: Nothing to Solve",ASTUndefined);
-
- //turnOffSubsumption
- // MKK: My understanding is that the rougly equivalent effect is had
- // through setting the second argument of MINISAT::Solver::solve to
- // true
- //newS.turnOffSubsumption();
-
- // (*i) is an ASTVec-ptr which denotes an ASTclause
- //****************************************
- // *i = vector<const ASTNode*>*
- //****************************************
- for(; i!=iend; i++) {
- //Clause for the SATSolver
- MINISAT::vec<MINISAT::Lit> satSolverClause;
-
- //now iterate through the internals of the ASTclause itself
- vector<const ASTNode*>::const_iterator j = (*i)->begin(), jend = (*i)->end();
- //j is a disjunct in the ASTclause (*i)
- for(;j!=jend;j++) {
- ASTNode node = **j;
-
- bool negate = (NOT == node.GetKind()) ? true : false;
- ASTNode n = negate ? node[0] : node;
-
- //Lookup or create the MINISAT::Var corresponding to the Booelan
- //ASTNode Variable, and push into sat Solver clause
- MINISAT::Var v = LookupOrCreateSATVar(newS,n);
- MINISAT::Lit l(v, negate);
- satSolverClause.push(l);
- }
- newS.addClause(satSolverClause);
- // clause printing.
- // (printClause<MINISAT::vec<MINISAT::Lit> >)(satSolverClause);
- // cout << " 0 ";
- // cout << endl;
-
- if(newS.okay()) {
- continue;
- }
- else {
PrintStats(newS);
- return false;
- }
-
- if(!newS.simplify()) {
- PrintStats(newS);
- return false;
- }
- }
-
- // if input is UNSAT return false, else return true
- if(!newS.simplify()) {
- PrintStats(newS);
- return false;
- }
-
- //PrintActivityLevels_Of_SATVars("Before SAT:",newS);
- //ChangeActivityLevels_Of_SATVars(newS);
- //PrintActivityLevels_Of_SATVars("Before SAT and after initial bias:",newS);
- newS.solve();
- //PrintActivityLevels_Of_SATVars("After SAT",newS);
-
- PrintStats(newS);
- if (newS.okay())
- return true;
- else
- return false;
- }
-
- // GLOBAL FUNCTION: Prints statistics from the MINISAT Solver
- void BeevMgr::PrintStats(MINISAT::Solver& s) {
- if(!stats)
- return;
- double cpu_time = MINISAT::cpuTime();
- uint64_t mem_used = MINISAT::memUsed();
- /*
- reportf("restarts : %"I64_fmt"\n", s.starts);
- reportf("conflicts : %-12"I64_fmt" (%.0f /sec)\n", s.conflicts , s.conflicts /cpu_time);
- reportf("decisions : %-12"I64_fmt" (%.0f /sec)\n", s.decisions , s.decisions /cpu_time);
- reportf("propagations : %-12"I64_fmt" (%.0f /sec)\n", s.propagations, s.propagations/cpu_time);
- reportf("conflict literals : %-12"I64_fmt" (%4.2f %% deleted)\n",
- s.tot_literals,
- (s.max_literals - s.tot_literals)*100 / (double)s.max_literals);
- */
- if (mem_used != 0) reportf("Memory used : %.2f MB\n", mem_used / 1048576.0);
- reportf("CPU time : %g s\n", cpu_time);
- }
-
- // Prints Satisfying assignment directly, for debugging.
- void BeevMgr::PrintSATModel(MINISAT::Solver& newS) {
- if(!newS.okay())
- FatalError("PrintSATModel: NO COUNTEREXAMPLE TO PRINT",ASTUndefined);
- // FIXME: Don't put tests like this in the print functions. The print functions
- // should print unconditionally. Put a conditional around the call if you don't
- // want them to print
- if(!(stats && print_nodes))
- return;
-
- int num_vars = newS.nVars();
- cout << "Satisfying assignment: " << endl;
- for (int i = 0; i < num_vars; i++) {
- if (newS.model[i] == MINISAT::l_True) {
- ASTNode s = _SATVar_to_AST[i];
- cout << s << endl;
- }
- else if (newS.model[i] == MINISAT::l_False) {
- ASTNode s = _SATVar_to_AST[i];
- cout << CreateNode(NOT, s) << endl;
- }
- }
- }
-
-
- // Looks up truth value of ASTNode SYMBOL in MINISAT satisfying assignment.
- // Returns ASTTrue if true, ASTFalse if false or undefined.
- ASTNode BeevMgr::SymbolTruthValue(MINISAT::Solver &newS, ASTNode form)
- {
- MINISAT::Var satvar = _ASTNode_to_SATVar[form];
- if (newS.model[satvar] == MINISAT::l_True) {
- return ASTTrue;
- }
- else {
- // False or undefined.
- return ASTFalse;
- }
- }
-
-
- // This function is for debugging problems with BitBlast and especially
- // ToCNF. It evaluates the bit-blasted formula in the satisfying
- // assignment. While doing that, it checks that every subformula has
- // the same truth value as its representative literal, if it has one.
- // If this condition is violated, it halts immediately (on the leftmost
- // lowest term).
- // Use CreateSimpForm to evaluate, even though it's expensive, so that
- // we can use the partial truth assignment.
- ASTNode BeevMgr::CheckBBandCNF(MINISAT::Solver& newS, ASTNode form)
- {
- // Clear memo table (in case newS has changed).
- CheckBBandCNFMemo.clear();
- // Call recursive version that does the work.
- return CheckBBandCNF_int(newS, form);
- }
-
- // Recursive body CheckBBandCNF
- // FIXME: Modify this to just check if result is true, and print mismatch
- // if not. Might have a trace flag for the other stuff.
- ASTNode BeevMgr::CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form)
- {
-
- // cout << "++++++++++++++++" << endl << "CheckBBandCNF_int form = " <<
- // form << endl;
-
- ASTNodeMap::iterator memoit = CheckBBandCNFMemo.find(form);
- if (memoit != CheckBBandCNFMemo.end()) {
- // found it. Return memoized value.
- return memoit->second;
- }
-
- ASTNode result; // return value, to memoize.
-
- Kind k = form.GetKind();
- switch (k) {
- case TRUE:
- case FALSE: {
- return form;
- break;
- }
- case SYMBOL:
- case BVGETBIT: {
- // Look up the truth value
- // ASTNode -> Sat -> Truthvalue -> ASTTrue or ASTFalse;
- // FIXME: Could make up a fresh var in undefined case.
-
- result = SymbolTruthValue(newS, form);
-
- cout << "================" << endl << "Checking BB formula:" << form << endl;
- cout << "----------------" << endl << "Result:" << result << endl;
-
- break;
- }
- default: {
- // Evaluate the children recursively.
- ASTVec eval_children;
- ASTVec ch = form.GetChildren();
- ASTVec::iterator itend = ch.end();
- for(ASTVec::iterator it = ch.begin(); it < itend; it++) {
- eval_children.push_back(CheckBBandCNF_int(newS, *it));
- }
- result = CreateSimpForm(k, eval_children);
-
- cout << "================" << endl << "Checking BB formula:" << form << endl;
- cout << "----------------" << endl << "Result:" << result << endl;
-
- ASTNode replit_eval;
- // Compare with replit, if there is one.
- ASTNodeMap::iterator replit_it = RepLitMap.find(form);
- if (replit_it != RepLitMap.end()) {
- ASTNode replit = RepLitMap[form];
- // Replit is symbol or not symbol.
- if (SYMBOL == replit.GetKind()) {
- replit_eval = SymbolTruthValue(newS, replit);
+ if (newS.okay())
+ return true;
+ else
+ return false;
+}
+
+// GLOBAL FUNCTION: Prints statistics from the MINISAT Solver
+void BeevMgr::PrintStats(MINISAT::Solver& s)
+{
+ if (!stats)
+ return;
+ double cpu_time = MINISAT::cpuTime();
+ uint64_t mem_used = MINISAT::memUsed();
+ /*
+ reportf("restarts : %"I64_fmt"\n", s.starts);
+ reportf("conflicts : %-12"I64_fmt" (%.0f /sec)\n", s.conflicts , s.conflicts /cpu_time);
+ reportf("decisions : %-12"I64_fmt" (%.0f /sec)\n", s.decisions , s.decisions /cpu_time);
+ reportf("propagations : %-12"I64_fmt" (%.0f /sec)\n", s.propagations, s.propagations/cpu_time);
+ reportf("conflict literals : %-12"I64_fmt" (%4.2f %% deleted)\n",
+ s.tot_literals,
+ (s.max_literals - s.tot_literals)*100 / (double)s.max_literals);
+ */
+ if (mem_used != 0)
+ reportf("Memory used : %.2f MB\n", mem_used / 1048576.0);
+ reportf("CPU time : %g s\n", cpu_time);
+}
+
+// Prints Satisfying assignment directly, for debugging.
+void BeevMgr::PrintSATModel(MINISAT::Solver& newS)
+{
+ if (!newS.okay())
+ FatalError("PrintSATModel: NO COUNTEREXAMPLE TO PRINT", ASTUndefined);
+ // FIXME: Don't put tests like this in the print functions. The print functions
+ // should print unconditionally. Put a conditional around the call if you don't
+ // want them to print
+ if (!(stats && print_nodes))
+ return;
+
+ int num_vars = newS.nVars();
+ cout << "Satisfying assignment: " << endl;
+ for (int i = 0; i < num_vars; i++)
+ {
+ if (newS.model[i] == MINISAT::l_True)
+ {
+ ASTNode s = _SATVar_to_AST[i];
+ cout << s << endl;
+ }
+ else if (newS.model[i] == MINISAT::l_False)
+ {
+ ASTNode s = _SATVar_to_AST[i];
+ cout << CreateNode(NOT, s) << endl;
+ }
+ }
+}
+
+// Looks up truth value of ASTNode SYMBOL in MINISAT satisfying assignment.
+// Returns ASTTrue if true, ASTFalse if false or undefined.
+ASTNode BeevMgr::SymbolTruthValue(MINISAT::Solver &newS, ASTNode form)
+{
+ MINISAT::Var satvar = _ASTNode_to_SATVar[form];
+ if (newS.model[satvar] == MINISAT::l_True)
+ {
+ return ASTTrue;
}
- else {
- // It's (NOT sym). Get value of sym and complement.
- replit_eval = CreateSimpNot(SymbolTruthValue(newS, replit[0]));
+ else
+ {
+ // False or undefined.
+ return ASTFalse;
+ }
+}
+
+// This function is for debugging problems with BitBlast and especially
+// ToCNF. It evaluates the bit-blasted formula in the satisfying
+// assignment. While doing that, it checks that every subformula has
+// the same truth value as its representative literal, if it has one.
+// If this condition is violated, it halts immediately (on the leftmost
+// lowest term).
+// Use CreateSimpForm to evaluate, even though it's expensive, so that
+// we can use the partial truth assignment.
+ASTNode BeevMgr::CheckBBandCNF(MINISAT::Solver& newS, ASTNode form)
+{
+ // Clear memo table (in case newS has changed).
+ CheckBBandCNFMemo.clear();
+ // Call recursive version that does the work.
+ return CheckBBandCNF_int(newS, form);
+}
+
+// Recursive body CheckBBandCNF
+// FIXME: Modify this to just check if result is true, and print mismatch
+// if not. Might have a trace flag for the other stuff.
+ASTNode BeevMgr::CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form)
+{
+
+ // cout << "++++++++++++++++" << endl << "CheckBBandCNF_int form = " <<
+ // form << endl;
+
+ ASTNodeMap::iterator memoit = CheckBBandCNFMemo.find(form);
+ if (memoit != CheckBBandCNFMemo.end())
+ {
+ // found it. Return memoized value.
+ return memoit->second;
}
- cout << "----------------" << endl << "Rep lit: " << replit << endl;
- cout << "----------------" << endl << "Rep lit value: " << replit_eval << endl;
+ ASTNode result; // return value, to memoize.
+
+ Kind k = form.GetKind();
+ switch (k)
+ {
+ case TRUE:
+ case FALSE:
+ {
+ return form;
+ break;
+ }
+ case SYMBOL:
+ case BVGETBIT:
+ {
+ // Look up the truth value
+ // ASTNode -> Sat -> Truthvalue -> ASTTrue or ASTFalse;
+ // FIXME: Could make up a fresh var in undefined case.
+
+ result = SymbolTruthValue(newS, form);
+
+ cout << "================" << endl << "Checking BB formula:" << form << endl;
+ cout << "----------------" << endl << "Result:" << result << endl;
- if (result != replit_eval) {
- // Hit the panic button.
- FatalError("Truth value of BitBlasted formula disagrees with representative literal in CNF.");
+ break;
+ }
+ default:
+ {
+ // Evaluate the children recursively.
+ ASTVec eval_children;
+ ASTVec ch = form.GetChildren();
+ ASTVec::iterator itend = ch.end();
+ for (ASTVec::iterator it = ch.begin(); it < itend; it++)
+ {
+ eval_children.push_back(CheckBBandCNF_int(newS, *it));
+ }
+ result = CreateSimpForm(k, eval_children);
+
+ cout << "================" << endl << "Checking BB formula:" << form << endl;
+ cout << "----------------" << endl << "Result:" << result << endl;
+
+ ASTNode replit_eval;
+ // Compare with replit, if there is one.
+ ASTNodeMap::iterator replit_it = RepLitMap.find(form);
+ if (replit_it != RepLitMap.end())
+ {
+ ASTNode replit = RepLitMap[form];
+ // Replit is symbol or not symbol.
+ if (SYMBOL == replit.GetKind())
+ {
+ replit_eval = SymbolTruthValue(newS, replit);
+ }
+ else
+ {
+ // It's (NOT sym). Get value of sym and complement.
+ replit_eval = CreateSimpNot(SymbolTruthValue(newS, replit[0]));
+ }
+
+ cout << "----------------" << endl << "Rep lit: " << replit << endl;
+ cout << "----------------" << endl << "Rep lit value: " << replit_eval << endl;
+
+ if (result != replit_eval)
+ {
+ // Hit the panic button.
+ FatalError("Truth value of BitBlasted formula disagrees with representative literal in CNF.");
+ }
+ }
+ else
+ {
+ cout << "----------------" << endl << "No rep lit" << endl;
+ }
+
+ }
}
- }
- else {
- cout << "----------------" << endl << "No rep lit" << endl;
- }
-
- }
- }
-
- return (CheckBBandCNFMemo[form] = result);
- }
-
- /*FUNCTION: constructs counterexample from MINISAT counterexample
- * step1 : iterate through MINISAT counterexample and assemble the
- * bits for each AST term. Store it in a map from ASTNode to vector
- * of bools (bits).
- *
- * step2: Iterate over the map from ASTNodes->Vector-of-Bools and
- * populate the CounterExampleMap data structure (ASTNode -> BVConst)
- */
- void BeevMgr::ConstructCounterExample(MINISAT::Solver& newS) {
- //iterate over MINISAT counterexample and construct a map from AST
- //terms to vector of bools. We need this iteration step because
- //MINISAT might return the various bits of a term out of
- //order. Therfore, we need to collect all the bits and assemble
- //them properly
-
- if(!newS.okay())
- return;
- if(!construct_counterexample)
- return;
-
- CopySolverMap_To_CounterExample();
- for (int i = 0; i < newS.nVars(); i++) {
- //Make sure that the MINISAT::Var is defined
- if (newS.model[i] != MINISAT::l_Undef) {
-
- //mapping from MINISAT::Vars to ASTNodes. We do not need to
- //print MINISAT vars or CNF vars.
- ASTNode s = _SATVar_to_AST[i];
-
- //assemble the counterexample here
- if(s.GetKind() == BVGETBIT && s[0].GetKind() == SYMBOL) {
- ASTNode symbol = s[0];
- unsigned int symbolWidth = symbol.GetValueWidth();
-
- //'v' is the map from bit-index to bit-value
- hash_map<unsigned,bool> * v;
- if(_ASTNode_to_Bitvector.find(symbol) == _ASTNode_to_Bitvector.end())
- _ASTNode_to_Bitvector[symbol] = new hash_map<unsigned,bool>(symbolWidth);
-
- //v holds the map from bit-index to bit-value
- v = _ASTNode_to_Bitvector[symbol];
-
- //kk is the index of BVGETBIT
- unsigned int kk = GetUnsignedConst(s[1]);
-
- //Collect the bits of 'symbol' and store in v. Store in reverse order.
- if(newS.model[i]==MINISAT::l_True)
- (*v)[(symbolWidth-1) - kk] = true;
- else
- (*v)[(symbolWidth-1) - kk] = false;
+
+ return (CheckBBandCNFMemo[form] = result);
+}
+
+/*FUNCTION: constructs counterexample from MINISAT counterexample
+ * step1 : iterate through MINISAT counterexample and assemble the
+ * bits for each AST term. Store it in a map from ASTNode to vector
+ * of bools (bits).
+ *
+ * step2: Iterate over the map from ASTNodes->Vector-of-Bools and
+ * populate the CounterExampleMap data structure (ASTNode -> BVConst)
+ */
+void BeevMgr::ConstructCounterExample(MINISAT::Solver& newS)
+{
+ //iterate over MINISAT counterexample and construct a map from AST
+ //terms to vector of bools. We need this iteration step because
+ //MINISAT might return the various bits of a term out of
+ //order. Therfore, we need to collect all the bits and assemble
+ //them properly
+
+ if (!newS.okay())
+ return;
+ if (!construct_counterexample)
+ return;
+
+ CopySolverMap_To_CounterExample();
+ for (int i = 0; i < newS.nVars(); i++)
+ {
+ //Make sure that the MINISAT::Var is defined
+ if (newS.model[i] != MINISAT::l_Undef)
+ {
+
+ //mapping from MINISAT::Vars to ASTNodes. We do not need to
+ //print MINISAT vars or CNF vars.
+ ASTNode s = _SATVar_to_AST[i];
+
+ //assemble the counterexample here
+ if (s.GetKind() == BVGETBIT && s[0].GetKind() == SYMBOL)
+ {
+ ASTNode symbol = s[0];
+ unsigned int symbolWidth = symbol.GetValueWidth();
+
+ //'v' is the map from bit-index to bit-value
+ hash_map<unsigned, bool> * v;
+ if (_ASTNode_to_Bitvector.find(symbol) == _ASTNode_to_Bitvector.end())
+ _ASTNode_to_Bitvector[symbol] = new hash_map<unsigned, bool> (symbolWidth);
+
+ //v holds the map from bit-index to bit-value
+ v = _ASTNode_to_Bitvector[symbol];
+
+ //kk is the index of BVGETBIT
+ unsigned int kk = GetUnsignedConst(s[1]);
+
+ //Collect the bits of 'symbol' and store in v. Store in reverse order.
+ if (newS.model[i] == MINISAT::l_True)
+ (*v)[(symbolWidth - 1) - kk] = true;
+ else
+ (*v)[(symbolWidth - 1) - kk] = false;
+ }
+ else
+ {
+ if (s.GetKind() == SYMBOL && s.GetType() == BOOLEAN_TYPE)
+ {
+ const char * zz = s.GetName();
+ //if the variables are not cnf variables then add them to the counterexample
+ if (0 != strncmp("cnf", zz, 3) && 0 != strcmp("*TrueDummy*", zz))
+ {
+ if (newS.model[i] == MINISAT::l_True)
+ CounterExampleMap[s] = ASTTrue;
+ else if (newS.model[i] == MINISAT::l_False)
+ CounterExampleMap[s] = ASTFalse;
+ else
+ {
+ int seed = 10000;
+ srand(seed);
+ CounterExampleMap[s] = (rand() > seed) ? ASTFalse : ASTTrue;
+ }
+ }
+ }
+ }
+ }
}
- else {
- if(s.GetKind() == SYMBOL && s.GetType() == BOOLEAN_TYPE) {
- const char * zz = s.GetName();
- //if the variables are not cnf variables then add them to the counterexample
- if(0 != strncmp("cnf",zz,3) && 0 != strcmp("*TrueDummy*",zz)) {
- if(newS.model[i]==MINISAT::l_True)
- CounterExampleMap[s] = ASTTrue;
- else if(newS.model[i]==MINISAT::l_False)
- CounterExampleMap[s] = ASTFalse;
- else {
- int seed = 10000;
- srand(seed);
- CounterExampleMap[s] = (rand() > seed) ? ASTFalse : ASTTrue;
- }
- }
- }
+
+ //iterate over the ASTNode_to_Bitvector data-struct and construct
+ //the the aggregate value of the bitvector, and populate the
+ //CounterExampleMap datastructure
+ for (ASTtoBitvectorMap::iterator it = _ASTNode_to_Bitvector.begin(), itend = _ASTNode_to_Bitvector.end(); it != itend; it++)
+ {
+ ASTNode var = it->first;
+ //debugging
+ //cerr << var;
+ if (SYMBOL != var.GetKind())
+ FatalError("ConstructCounterExample: error while constructing counterexample: not a variable: ", var);
+
+ //construct the bitvector value
+ hash_map<unsigned, bool> * w = it->second;
+ ASTNode value = BoolVectoBVConst(w, var.GetValueWidth());
+ //debugging
+ //cerr << value;
+
+ //populate the counterexample datastructure. add only scalars
+ //variables which were declared in the input and newly
+ //introduced variables for array reads
+ CounterExampleMap[var] = value;
}
- }
- }
-
- //iterate over the ASTNode_to_Bitvector data-struct and construct
- //the the aggregate value of the bitvector, and populate the
- //CounterExampleMap datastructure
- for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),itend=_ASTNode_to_Bitvector.end();
- it!=itend;it++) {
- ASTNode var = it->first;
- //debugging
- //cerr << var;
- if(SYMBOL != var.GetKind())
- FatalError("ConstructCounterExample: error while constructing counterexample: not a variable: ",var);
-
- //construct the bitvector value
- hash_map<unsigned,bool> * w = it->second;
- ASTNode value = BoolVectoBVConst(w, var.GetValueWidth());
- //debugging
- //cerr << value;
-
- //populate the counterexample datastructure. add only scalars
- //variables which were declared in the input and newly
- //introduced variables for array reads
- CounterExampleMap[var] = value;
- }
-
- //In this loop, we compute the value of each array read, the
- //corresponding ITE against the counterexample generated above.
- for(ASTNodeMap::iterator it=_arrayread_ite.begin(),itend=_arrayread_ite.end();
- it!=itend;it++){
- //the array read
- ASTNode arrayread = it->first;
- ASTNode value_ite = _arrayread_ite[arrayread];
-
- //convert it to a constant array-read and store it in the
- //counter-example. First convert the index into a constant. then
- //construct the appropriate array-read and store it in the
- //counterexample
- ASTNode arrayread_index = TermToConstTermUsingModel(arrayread[1]);
- ASTNode key = CreateTerm(READ,arrayread.GetValueWidth(),arrayread[0],arrayread_index);
-
- //Get the ITE corresponding to the array-read and convert it
- //to a constant against the model
- ASTNode value = TermToConstTermUsingModel(value_ite);
- //save the result in the counter_example
- if(!CheckSubstitutionMap(key))
- CounterExampleMap[key] = value;
- }
- } //End of ConstructCounterExample
-
- // FUNCTION: accepts a non-constant term, and returns the
- // corresponding constant term with respect to a model.
- //
- // term READ(A,i) is treated as follows:
- //
- //1. If (the boolean variable 'ArrayReadFlag' is true && ArrayRead
- //1. has value in counterexample), then return the value of the
- //1. arrayread.
- //
- //2. If (the boolean variable 'ArrayReadFlag' is true && ArrayRead
- //2. doesn't have value in counterexample), then return the
- //2. arrayread itself (normalized such that arrayread has a constant
- //2. index)
- //
- //3. If (the boolean variable 'ArrayReadFlag' is false) && ArrayRead
- //3. has a value in the counterexample then return the value of the
- //3. arrayread.
- //
- //4. If (the boolean variable 'ArrayReadFlag' is false) && ArrayRead
- //4. doesn't have a value in the counterexample then return 0 as the
- //4. value of the arrayread.
- ASTNode BeevMgr::TermToConstTermUsingModel(const ASTNode& t, bool ArrayReadFlag) {
- Begin_RemoveWrites = false;
- SimplifyWrites_InPlace_Flag = false;
- //ASTNode term = SimplifyTerm(t);
- ASTNode term = t;
- Kind k = term.GetKind();
-
-
- //cerr << "Input to TermToConstTermUsingModel: " << term << endl;
- if(!is_Term_kind(k)) {
- FatalError("TermToConstTermUsingModel: The input is not a term: ",term);
- }
- if(k == WRITE) {
- FatalError("TermToConstTermUsingModel: The input has wrong kind: WRITE : ",term);
- }
- if(k == SYMBOL && BOOLEAN_TYPE == term.GetType()) {
- FatalError("TermToConstTermUsingModel: The input has wrong kind: Propositional variable : ",term);
- }
-
- ASTNodeMap::iterator it1;
- if((it1 = CounterExampleMap.find(term)) != CounterExampleMap.end()) {
- ASTNode val = it1->second;
- if(BVCONST != val.GetKind()) {
- //CounterExampleMap has two maps rolled into
- //one. SubstitutionMap and SolverMap.
- //
- //recursion is fine here. There are two maps that are checked
- //here. One is the substitutionmap. We garuntee that the value
- //of a key in the substitutionmap is always a constant.
- //
- //in the SolverMap we garuntee that "term" does not occur in
- //the value part of the map
- if(term == val) {
- FatalError("TermToConstTermUsingModel: The input term is stored as-is "
- "in the CounterExample: Not ok: ",term);
+
+ //In this loop, we compute the value of each array read, the
+ //corresponding ITE against the counterexample generated above.
+ for (ASTNodeMap::iterator it = _arrayread_ite.begin(), itend = _arrayread_ite.end(); it != itend; it++)
+ {
+ //the array read
+ ASTNode arrayread = it->first;
+ ASTNode value_ite = _arrayread_ite[arrayread];
+
+ //convert it to a constant array-read and store it in the
+ //counter-example. First convert the index into a constant. then
+ //construct the appropriate array-read and store it in the
+ //counterexample
+ ASTNode arrayread_index = TermToConstTermUsingModel(arrayread[1]);
+ ASTNode key = CreateTerm(READ, arrayread.GetValueWidth(), arrayread[0], arrayread_index);
+
+ //Get the ITE corresponding to the array-read and convert it
+ //to a constant against the model
+ ASTNode value = TermToConstTermUsingModel(value_ite);
+ //save the result in the counter_example
+ if (!CheckSubstitutionMap(key))
+ CounterExampleMap[key] = value;
+ }
+} //End of ConstructCounterExample
+
+// FUNCTION: accepts a non-constant term, and returns the
+// corresponding constant term with respect to a model.
+//
+// term READ(A,i) is treated as follows:
+//
+//1. If (the boolean variable 'ArrayReadFlag' is true && ArrayRead
+//1. has value in counterexample), then return the value of the
+//1. arrayread.
+//
+//2. If (the boolean variable 'ArrayReadFlag' is true && ArrayRead
+//2. doesn't have value in counterexample), then return the
+//2. arrayread itself (normalized such that arrayread has a constant
+//2. index)
+//
+//3. If (the boolean variable 'ArrayReadFlag' is false) && ArrayRead
+//3. has a value in the counterexample then return the value of the
+//3. arrayread.
+//
+//4. If (the boolean variable 'ArrayReadFlag' is false) && ArrayRead
+//4. doesn't have a value in the counterexample then return 0 as the
+//4. value of the arrayread.
+ASTNode BeevMgr::TermToConstTermUsingModel(const ASTNode& t, bool ArrayReadFlag)
+{
+ Begin_RemoveWrites = false;
+ SimplifyWrites_InPlace_Flag = false;
+ //ASTNode term = SimplifyTerm(t);
+ ASTNode term = t;
+ Kind k = term.GetKind();
+
+ //cerr << "Input to TermToConstTermUsingModel: " << term << endl;
+ if (!is_Term_kind(k))
+ {
+ FatalError("TermToConstTermUsingModel: The input is not a term: ", term);
+ }
+ if (k == WRITE)
+ {
+ FatalError("TermToConstTermUsingModel: The input has wrong kind: WRITE : ", term);
}
- return TermToConstTermUsingModel(val,ArrayReadFlag);
- }
- else {
- return val;
- }
- }
-
- ASTNode output;
- switch(k) {
- case BVCONST:
- output = term;
- break;
- case SYMBOL: {
- if(term.GetType() == ARRAY_TYPE) {
- return term;
- }
-
- //when all else fails set symbol values to some constant by
- //default. if the variable is queried the second time then add 1
- //to and return the new value.
- ASTNode zero = CreateZeroConst(term.GetValueWidth());
- output = zero;
- break;
- }
- case READ: {
- ASTNode arrName = term[0];
- ASTNode index = term[1];
- if(0 == arrName.GetIndexWidth()) {
- FatalError("TermToConstTermUsingModel: array has 0 index width: ",arrName);
- }
-
- //READ over a WRITE
- if(WRITE == arrName.GetKind()) {
- ASTNode wrtterm = Expand_ReadOverWrite_UsingModel(term, ArrayReadFlag);
- if(wrtterm == term) {
- FatalError("TermToConstTermUsingModel: Read_Over_Write term must be expanded into an ITE", term);
+ if (k == SYMBOL && BOOLEAN_TYPE == term.GetType())
+ {
+ FatalError("TermToConstTermUsingModel: The input has wrong kind: Propositional variable : ", term);
}
- ASTNode rtterm = TermToConstTermUsingModel(wrtterm,ArrayReadFlag);
- return rtterm;
- }
- //READ over an ITE
- if(ITE == arrName.GetKind()) {
- arrName = TermToConstTermUsingModel(arrName,ArrayReadFlag);
- }
-
- ASTNode modelentry;
- if(CounterExampleMap.find(index) != CounterExampleMap.end()) {
- //index has a const value in the CounterExampleMap
- //ASTNode indexVal = CounterExampleMap[index];
- ASTNode indexVal = TermToConstTermUsingModel(CounterExampleMap[index], ArrayReadFlag);
- modelentry = CreateTerm(READ, arrName.GetValueWidth(), arrName, indexVal);
- }
- else {
- //index does not have a const value in the CounterExampleMap. compute it.
- ASTNode indexconstval = TermToConstTermUsingModel(index,ArrayReadFlag);
- //update model with value of the index
- //CounterExampleMap[index] = indexconstval;
- modelentry = CreateTerm(READ,arrName.GetValueWidth(), arrName,indexconstval);
- }
- //modelentry is now an arrayread over a constant index
- BVTypeCheck(modelentry);
-
- //if a value exists in the CounterExampleMap then return it
- if(CounterExampleMap.find(modelentry) != CounterExampleMap.end()) {
- output = TermToConstTermUsingModel(CounterExampleMap[modelentry],ArrayReadFlag);
- }
- else if(ArrayReadFlag) {
- //return the array read over a constantindex
- output = modelentry;
- }
- else {
- //when all else fails set symbol values to some constant by
- //default. if the variable is queried the second time then add 1
- //to and return the new value.
- ASTNode zero = CreateZeroConst(modelentry.GetValueWidth());
- output = zero;
- }
- break;
- }
- case ITE: {
- ASTNode condcompute = ComputeFormulaUsingModel(term[0]);
- if(ASTTrue == condcompute) {
- output = TermToConstTermUsingModel(term[1],ArrayReadFlag);
- }
- else if(ASTFalse == condcompute) {
- output = TermToConstTermUsingModel(term[2],ArrayReadFlag);
- }
- else {
- cerr << "TermToConstTermUsingModel: termITE: value of conditional is wrong: " << condcompute << endl;
- FatalError(" TermToConstTermUsingModel: termITE: cannot compute ITE conditional against model: ",term);
- }
- break;
- }
- default: {
- ASTVec c = term.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode ff = TermToConstTermUsingModel(*it,ArrayReadFlag);
- o.push_back(ff);
- }
- output = CreateTerm(k,term.GetValueWidth(),o);
- //output is a CONST expression. compute its value and store it
- //in the CounterExampleMap
- ASTNode oo = BVConstEvaluator(output);
- //the return value
- output = oo;
- break;
- }
- }
-
- //when this flag is false, we should compute the arrayread to a
- //constant. this constant is stored in the counter_example
- //datastructure
- if(!ArrayReadFlag) {
- CounterExampleMap[term] = output;
- }
-
- //cerr << "Output to TermToConstTermUsingModel: " << output << endl;
- return output;
- } //End of TermToConstTermUsingModel
-
- //Expands read-over-write by evaluating (readIndex=writeIndex) for
- //every writeindex until, either it evaluates to TRUE or all
- //(readIndex=writeIndex) evaluate to FALSE
- ASTNode BeevMgr::Expand_ReadOverWrite_UsingModel(const ASTNode& term, bool arrayread_flag) {
- if(READ != term.GetKind() &&
- WRITE != term[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
- }
-
- ASTNode output;
- ASTNodeMap::iterator it1;
- if((it1 = CounterExampleMap.find(term)) != CounterExampleMap.end()) {
- ASTNode val = it1->second;
- if(BVCONST != val.GetKind()) {
- //recursion is fine here. There are two maps that are checked
- //here. One is the substitutionmap. We garuntee that the value
- //of a key in the substitutionmap is always a constant.
- if(term == val) {
- FatalError("TermToConstTermUsingModel: The input term is stored as-is "
- "in the CounterExample: Not ok: ",term);
+
+ ASTNodeMap::iterator it1;
+ if ((it1 = CounterExampleMap.find(term)) != CounterExampleMap.end())
+ {
+ ASTNode val = it1->second;
+ if (BVCONST != val.GetKind())
+ {
+ //CounterExampleMap has two maps rolled into
+ //one. SubstitutionMap and SolverMap.
+ //
+ //recursion is fine here. There are two maps that are checked
+ //here. One is the substitutionmap. We garuntee that the value
+ //of a key in the substitutionmap is always a constant.
+ //
+ //in the SolverMap we garuntee that "term" does not occur in
+ //the value part of the map
+ if (term == val)
+ {
+ FatalError("TermToConstTermUsingModel: The input term is stored as-is "
+ "in the CounterExample: Not ok: ", term);
+ }
+ return TermToConstTermUsingModel(val, ArrayReadFlag);
+ }
+ else
+ {
+ return val;
+ }
+ }
+
+ ASTNode output;
+ switch (k)
+ {
+ case BVCONST:
+ output = term;
+ break;
+ case SYMBOL:
+ {
+ if (term.GetType() == ARRAY_TYPE)
+ {
+ return term;
+ }
+
+ //when all else fails set symbol values to some constant by
+ //default. if the variable is queried the second time then add 1
+ //to and return the new value.
+ ASTNode zero = CreateZeroConst(term.GetValueWidth());
+ output = zero;
+ break;
+ }
+ case READ:
+ {
+ ASTNode arrName = term[0];
+ ASTNode index = term[1];
+ if (0 == arrName.GetIndexWidth())
+ {
+ FatalError("TermToConstTermUsingModel: array has 0 index width: ", arrName);
+ }
+
+ //READ over a WRITE
+ if (WRITE == arrName.GetKind())
+ {
+ ASTNode wrtterm = Expand_ReadOverWrite_UsingModel(term, ArrayReadFlag);
+ if (wrtterm == term)
+ {
+ FatalError("TermToConstTermUsingModel: Read_Over_Write term must be expanded into an ITE", term);
+ }
+ ASTNode rtterm = TermToConstTermUsingModel(wrtterm, ArrayReadFlag);
+ return rtterm;
+ }
+ //READ over an ITE
+ if (ITE == arrName.GetKind())
+ {
+ arrName = TermToConstTermUsingModel(arrName, ArrayReadFlag);
+ }
+
+ ASTNode modelentry;
+ if (CounterExampleMap.find(index) != CounterExampleMap.end())
+ {
+ //index has a const value in the CounterExampleMap
+ //ASTNode indexVal = CounterExampleMap[index];
+ ASTNode indexVal = TermToConstTermUsingModel(CounterExampleMap[index], ArrayReadFlag);
+ modelentry = CreateTerm(READ, arrName.GetValueWidth(), arrName, indexVal);
+ }
+ else
+ {
+ //index does not have a const value in the CounterExampleMap. compute it.
+ ASTNode indexconstval = TermToConstTermUsingModel(index, ArrayReadFlag);
+ //update model with value of the index
+ //CounterExampleMap[index] = indexconstval;
+ modelentry = CreateTerm(READ, arrName.GetValueWidth(), arrName, indexconstval);
+ }
+ //modelentry is now an arrayread over a constant index
+ BVTypeCheck(modelentry);
+
+ //if a value exists in the CounterExampleMap then return it
+ if (CounterExampleMap.find(modelentry) != CounterExampleMap.end())
+ {
+ output = TermToConstTermUsingModel(CounterExampleMap[modelentry], ArrayReadFlag);
+ }
+ else if (ArrayReadFlag)
+ {
+ //return the array read over a constantindex
+ output = modelentry;
+ }
+ else
+ {
+ //when all else fails set symbol values to some constant by
+ //default. if the variable is queried the second time then add 1
+ //to and return the new value.
+ ASTNode zero = CreateZeroConst(modelentry.GetValueWidth());
+ output = zero;
+ }
+ break;
+ }
+ case ITE:
+ {
+ ASTNode condcompute = ComputeFormulaUsingModel(term[0]);
+ if (ASTTrue == condcompute)
+ {
+ output = TermToConstTermUsingModel(term[1], ArrayReadFlag);
+ }
+ else if (ASTFalse == condcompute)
+ {
+ output = TermToConstTermUsingModel(term[2], ArrayReadFlag);
+ }
+ else
+ {
+ cerr << "TermToConstTermUsingModel: termITE: value of conditional is wrong: " << condcompute << endl;
+ FatalError(" TermToConstTermUsingModel: termITE: cannot compute ITE conditional against model: ", term);
+ }
+ break;
+ }
+ default:
+ {
+ ASTVec c = term.GetChildren();
+ ASTVec o;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode ff = TermToConstTermUsingModel(*it, ArrayReadFlag);
+ o.push_back(ff);
+ }
+ output = CreateTerm(k, term.GetValueWidth(), o);
+ //output is a CONST expression. compute its value and store it
+ //in the CounterExampleMap
+ ASTNode oo = BVConstEvaluator(output);
+ //the return value
+ output = oo;
+ break;
+ }
}
- return TermToConstTermUsingModel(val,arrayread_flag);
- }
- else {
- return val;
- }
- }
-
- unsigned int width = term.GetValueWidth();
- ASTNode writeA = ASTTrue;
- ASTNode newRead = term;
- ASTNode readIndex = TermToConstTermUsingModel(newRead[1],false);
- //iteratively expand read-over-write, and evaluate against the
- //model at every iteration
- do {
- ASTNode write = newRead[0];
- writeA = write[0];
- ASTNode writeIndex = TermToConstTermUsingModel(write[1],false);
- ASTNode writeVal = TermToConstTermUsingModel(write[2],false);
-
- ASTNode cond = ComputeFormulaUsingModel(CreateSimplifiedEQ(writeIndex,readIndex));
- if(ASTTrue == cond) {
- //found the write-value. return it
- output = writeVal;
+
+ //when this flag is false, we should compute the arrayread to a
+ //constant. this constant is stored in the counter_example
+ //datastructure
+ if (!ArrayReadFlag)
+ {
+ CounterExampleMap[term] = output;
+ }
+
+ //cerr << "Output to TermToConstTermUsingModel: " << output << endl;
+ return output;
+} //End of TermToConstTermUsingModel
+
+//Expands read-over-write by evaluating (readIndex=writeIndex) for
+//every writeindex until, either it evaluates to TRUE or all
+//(readIndex=writeIndex) evaluate to FALSE
+ASTNode BeevMgr::Expand_ReadOverWrite_UsingModel(const ASTNode& term, bool arrayread_flag)
+{
+ if (READ != term.GetKind() && WRITE != term[0].GetKind())
+ {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE", term);
+ }
+
+ ASTNode output;
+ ASTNodeMap::iterator it1;
+ if ((it1 = CounterExampleMap.find(term)) != CounterExampleMap.end())
+ {
+ ASTNode val = it1->second;
+ if (BVCONST != val.GetKind())
+ {
+ //recursion is fine here. There are two maps that are checked
+ //here. One is the substitutionmap. We garuntee that the value
+ //of a key in the substitutionmap is always a constant.
+ if (term == val)
+ {
+ FatalError("TermToConstTermUsingModel: The input term is stored as-is "
+ "in the CounterExample: Not ok: ", term);
+ }
+ return TermToConstTermUsingModel(val, arrayread_flag);
+ }
+ else
+ {
+ return val;
+ }
+ }
+
+ unsigned int width = term.GetValueWidth();
+ ASTNode writeA = ASTTrue;
+ ASTNode newRead = term;
+ ASTNode readIndex = TermToConstTermUsingModel(newRead[1], false);
+ //iteratively expand read-over-write, and evaluate against the
+ //model at every iteration
+ do
+ {
+ ASTNode write = newRead[0];
+ writeA = write[0];
+ ASTNode writeIndex = TermToConstTermUsingModel(write[1], false);
+ ASTNode writeVal = TermToConstTermUsingModel(write[2], false);
+
+ ASTNode cond = ComputeFormulaUsingModel(CreateSimplifiedEQ(writeIndex, readIndex));
+ if (ASTTrue == cond)
+ {
+ //found the write-value. return it
+ output = writeVal;
+ CounterExampleMap[term] = output;
+ return output;
+ }
+
+ newRead = CreateTerm(READ, width, writeA, readIndex);
+ } while (READ == newRead.GetKind() && WRITE == newRead[0].GetKind());
+
+ output = TermToConstTermUsingModel(newRead, arrayread_flag);
+
+ //memoize
CounterExampleMap[term] = output;
return output;
- }
-
- newRead = CreateTerm(READ,width,writeA,readIndex);
- } while(READ == newRead.GetKind() && WRITE == newRead[0].GetKind());
-
- output = TermToConstTermUsingModel(newRead,arrayread_flag);
-
- //memoize
- CounterExampleMap[term] = output;
- return output;
- } //Exand_ReadOverWrite_To_ITE_UsingModel()
-
- /* FUNCTION: accepts a non-constant formula, and checks if the
- * formula is ASTTrue or ASTFalse w.r.t to a model
- */
- ASTNode BeevMgr::ComputeFormulaUsingModel(const ASTNode& form) {
- ASTNode in = form;
- Kind k = form.GetKind();
- if(!(is_Form_kind(k) && BOOLEAN_TYPE == form.GetType())) {
- FatalError(" ComputeConstFormUsingModel: The input is a non-formula: ", form);
- }
-
- //cerr << "Input to ComputeFormulaUsingModel:" << form << endl;
- ASTNodeMap::iterator it1;
- if((it1 = ComputeFormulaMap.find(form)) != ComputeFormulaMap.end()) {
- ASTNode res = it1->second;
- if(ASTTrue == res || ASTFalse == res) {
- return res;
- }
- else {
- FatalError("ComputeFormulaUsingModel: The value of a formula must be TRUE or FALSE:", form);
- }
- }
-
- ASTNode t0,t1;
- ASTNode output = ASTFalse;
- switch(k) {
- case TRUE:
- case FALSE:
- output = form;
- break;
- case SYMBOL:
- if(BOOLEAN_TYPE != form.GetType())
- FatalError(" ComputeFormulaUsingModel: Non-Boolean variables are not formulas",form);
- if(CounterExampleMap.find(form) != CounterExampleMap.end()) {
- ASTNode counterexample_val = CounterExampleMap[form];
- if(!VarSeenInTerm(form,counterexample_val)) {
- output = ComputeFormulaUsingModel(counterexample_val);
+} //Exand_ReadOverWrite_To_ITE_UsingModel()
+
+/* FUNCTION: accepts a non-constant formula, and checks if the
+ * formula is ASTTrue or ASTFalse w.r.t to a model
+ */
+ASTNode BeevMgr::ComputeFormulaUsingModel(const ASTNode& form)
+{
+ ASTNode in = form;
+ Kind k = form.GetKind();
+ if (!(is_Form_kind(k) && BOOLEAN_TYPE == form.GetType()))
+ {
+ FatalError(" ComputeConstFormUsingModel: The input is a non-formula: ", form);
+ }
+
+ //cerr << "Input to ComputeFormulaUsingModel:" << form << endl;
+ ASTNodeMap::iterator it1;
+ if ((it1 = ComputeFormulaMap.find(form)) != ComputeFormulaMap.end())
+ {
+ ASTNode res = it1->second;
+ if (ASTTrue == res || ASTFalse == res)
+ {
+ return res;
+ }
+ else
+ {
+ FatalError("ComputeFormulaUsingModel: The value of a formula must be TRUE or FALSE:", form);
+ }
+ }
+
+ ASTNode t0, t1;
+ ASTNode output = ASTFalse;
+ switch (k)
+ {
+ case TRUE:
+ case FALSE:
+ output = form;
+ break;
+ case SYMBOL:
+ if (BOOLEAN_TYPE != form.GetType())
+ FatalError(" ComputeFormulaUsingModel: Non-Boolean variables are not formulas", form);
+ if (CounterExampleMap.find(form) != CounterExampleMap.end())
+ {
+ ASTNode counterexample_val = CounterExampleMap[form];
+ if (!VarSeenInTerm(form, counterexample_val))
+ {
+ output = ComputeFormulaUsingModel(counterexample_val);
+ }
+ else
+ {
+ output = counterexample_val;
+ }
+ }
+ else
+ output = ASTFalse;
+ break;
+ case EQ:
+ case NEQ:
+ case BVLT:
+ case BVLE:
+ case BVGT:
+ case BVGE:
+ case BVSLT:
+ case BVSLE:
+ case BVSGT:
+ case BVSGE:
+ //convert form[0] into a constant term
+ t0 = TermToConstTermUsingModel(form[0], false);
+ //convert form[0] into a constant term
+ t1 = TermToConstTermUsingModel(form[1], false);
+ output = BVConstEvaluator(CreateNode(k, t0, t1));
+
+ //evaluate formula to false if bvdiv execption occurs while
+ //counterexample is being checked during refinement.
+ if (bvdiv_exception_occured && counterexample_checking_during_refinement)
+ {
+ output = ASTFalse;
+ }
+ break;
+ case NAND:
+ {
+ ASTNode o = ASTTrue;
+ for (ASTVec::const_iterator it = form.begin(), itend = form.end(); it != itend; it++)
+ if (ASTFalse == ComputeFormulaUsingModel(*it))
+ {
+ o = ASTFalse;
+ break;
+ }
+ if (o == ASTTrue)
+ output = ASTFalse;
+ else
+ output = ASTTrue;
+ break;
+ }
+ case NOR:
+ {
+ ASTNode o = ASTFalse;
+ for (ASTVec::const_iterator it = form.begin(), itend = form.end(); it != itend; it++)
+ if (ASTTrue == ComputeFormulaUsingModel(*it))
+ {
+ o = ASTTrue;
+ break;
+ }
+ if (o == ASTTrue)
+ output = ASTFalse;
+ else
+ output = ASTTrue;
+ break;
+ }
+ case NOT:
+ if (ASTTrue == ComputeFormulaUsingModel(form[0]))
+ output = ASTFalse;
+ else
+ output = ASTTrue;
+ break;
+ case OR:
+ for (ASTVec::const_iterator it = form.begin(), itend = form.end(); it != itend; it++)
+ if (ASTTrue == ComputeFormulaUsingModel(*it))
+ output = ASTTrue;
+ break;
+ case AND:
+ output = ASTTrue;
+ for (ASTVec::const_iterator it = form.begin(), itend = form.end(); it != itend; it++)
+ {
+ if (ASTFalse == ComputeFormulaUsingModel(*it))
+ {
+ output = ASTFalse;
+ break;
+ }
+ }
+ break;
+ case XOR:
+ t0 = ComputeFormulaUsingModel(form[0]);
+ t1 = ComputeFormulaUsingModel(form[1]);
+ if ((ASTTrue == t0 && ASTTrue == t1) || (ASTFalse == t0 && ASTFalse == t1))
+ output = ASTFalse;
+ else
+ output = ASTTrue;
+ break;
+ case IFF:
+ t0 = ComputeFormulaUsingModel(form[0]);
+ t1 = ComputeFormulaUsingModel(form[1]);
+ if ((ASTTrue == t0 && ASTTrue == t1) || (ASTFalse == t0 && ASTFalse == t1))
+ output = ASTTrue;
+ else
+ output = ASTFalse;
+ break;
+ case IMPLIES:
+ t0 = ComputeFormulaUsingModel(form[0]);
+ t1 = ComputeFormulaUsingModel(form[1]);
+ if ((ASTFalse == t0) || (ASTTrue == t0 && ASTTrue == t1))
+ output = ASTTrue;
+ else
+ output = ASTFalse;
+ break;
+ case ITE:
+ t0 = ComputeFormulaUsingModel(form[0]);
+ if (ASTTrue == t0)
+ output = ComputeFormulaUsingModel(form[1]);
+ else if (ASTFalse == t0)
+ output = ComputeFormulaUsingModel(form[2]);
+ else
+ FatalError("ComputeFormulaUsingModel: ITE: something is wrong with the formula: ", form);
+ break;
+ default:
+ FatalError(" ComputeFormulaUsingModel: the kind has not been implemented", ASTUndefined);
+ break;
+ }
+
+ //cout << "ComputeFormulaUsingModel output is:" << output << endl;
+ ComputeFormulaMap[form] = output;
+ return output;
+}
+
+void BeevMgr::CheckCounterExample(bool t)
+{
+ // FIXME: Code is more useful if enable flags are check OUTSIDE the method.
+ // If I want to check a counterexample somewhere, I don't want to have to set
+ // the flag in order to make it actualy happen!
+
+ printf("checking counterexample\n");
+ if (!check_counterexample)
+ {
+ return;
+ }
+
+ //input is valid, no counterexample to check
+ if (ValidFlag)
+ return;
+
+ //t is true if SAT solver generated a counterexample, else it is false
+ if (!t)
+ FatalError("CheckCounterExample: No CounterExample to check", ASTUndefined);
+ const ASTVec c = GetAsserts();
+ for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ if (ASTFalse == ComputeFormulaUsingModel(*it))
+ FatalError("CheckCounterExample:counterexample bogus:"
+ "assert evaluates to FALSE under counterexample: NOT OK", *it);
+
+ if (ASTTrue == ComputeFormulaUsingModel(_current_query))
+ FatalError("CheckCounterExample:counterexample bogus:"
+ "query evaluates to TRUE under counterexample: NOT OK", _current_query);
+}
+
+/* FUNCTION: prints a counterexample for INVALID inputs. iterate
+ * through the CounterExampleMap data structure and print it to
+ * stdout
+ */
+void BeevMgr::PrintCounterExample(bool t, std::ostream& os)
+{
+ //global command-line option
+ // FIXME: This should always print the counterexample. If you want
+ // to turn it off, check the switch at the point of call.
+ if (!print_counterexample)
+ {
+ return;
+ }
+
+ //input is valid, no counterexample to print
+ if (ValidFlag)
+ {
+ return;
+ }
+
+ //if this option is true then print the way dawson wants using a
+ //different printer. do not use this printer.
+ if (print_arrayval_declaredorder)
+ {
+ return;
+ }
+
+ //t is true if SAT solver generated a counterexample, else it is
+ //false
+ if (!t)
+ {
+ cerr << "PrintCounterExample: No CounterExample to print: " << endl;
+ return;
+ }
+
+ //os << "\nCOUNTEREXAMPLE: \n" << endl;
+ ASTNodeMap::iterator it = CounterExampleMap.begin();
+ ASTNodeMap::iterator itend = CounterExampleMap.end();
+ for (; it != itend; it++)
+ {
+ ASTNode f = it->first;
+ ASTNode se = it->second;
+
+ if (ARRAY_TYPE == se.GetType())
+ {
+ FatalError("TermToConstTermUsingModel: entry in counterexample is an arraytype. bogus:", se);
+ }
+
+ //skip over introduced variables
+ if (f.GetKind() == SYMBOL && (_introduced_symbols.find(f) != _introduced_symbols.end()))
+ continue;
+ if (f.GetKind() == SYMBOL || (f.GetKind() == READ && f[0].GetKind() == SYMBOL && f[1].GetKind() == BVCONST))
+ {
+ os << "ASSERT( ";
+ f.PL_Print(os, 0);
+ os << " = ";
+ if (BITVECTOR_TYPE == se.GetType())
+ {
+ TermToConstTermUsingModel(se, false).PL_Print(os, 0);
+ }
+ else
+ {
+ se.PL_Print(os, 0);
+ }
+ os << " );" << endl;
+ }
}
- else {
- output = counterexample_val;
+ //os << "\nEND OF COUNTEREXAMPLE" << endl;
+} //End of PrintCounterExample
+
+/* iterate through the CounterExampleMap data structure and print it
+ * to stdout. this function prints only the declared array variables
+ * IN the ORDER in which they were declared. It also assumes that
+ * the variables are of the form 'varname_number'. otherwise it will
+ * not print anything. This function was specifically written for
+ * Dawson Engler's group (bug finding research group at Stanford)
+ */
+void BeevMgr::PrintCounterExample_InOrder(bool t)
+{
+ //global command-line option to print counterexample. we do not
+ //want both counterexample printers to print at the sametime.
+ // FIXME: This should always print the counterexample. If you want
+ // to turn it off, check the switch at the point of call.
+ if (print_counterexample)
+ return;
+
+ //input is valid, no counterexample to print
+ if (ValidFlag)
+ return;
+
+ //print if the commandline option is '-q'. allows printing the
+ //counterexample in order.
+ if (!print_arrayval_declaredorder)
+ return;
+
+ //t is true if SAT solver generated a counterexample, else it is
+ //false
+ if (!t)
+ {
+ cerr << "PrintCounterExample: No CounterExample to print: " << endl;
+ return;
}
- }
- else
- output = ASTFalse;
- break;
- case EQ:
- case NEQ:
- case BVLT:
- case BVLE:
- case BVGT:
- case BVGE:
- case BVSLT:
- case BVSLE:
- case BVSGT:
- case BVSGE:
- //convert form[0] into a constant term
- t0 = TermToConstTermUsingModel(form[0],false);
- //convert form[0] into a constant term
- t1 = TermToConstTermUsingModel(form[1],false);
- output = BVConstEvaluator(CreateNode(k,t0,t1));
-
- //evaluate formula to false if bvdiv execption occurs while
- //counterexample is being checked during refinement.
- if(bvdiv_exception_occured &&
- counterexample_checking_during_refinement) {
- output = ASTFalse;
- }
- break;
- case NAND: {
- ASTNode o = ASTTrue;
- for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++)
- if(ASTFalse == ComputeFormulaUsingModel(*it)) {
- o = ASTFalse;
- break;
- }
- if(o == ASTTrue)
- output = ASTFalse;
- else
- output = ASTTrue;
- break;
- }
- case NOR: {
- ASTNode o = ASTFalse;
- for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++)
- if(ASTTrue == ComputeFormulaUsingModel(*it)) {
- o = ASTTrue;
- break;
+
+ //vector to store the integer values
+ std::vector<int> out_int;
+ cout << "% ";
+ for (ASTVec::iterator it = _special_print_set.begin(), itend = _special_print_set.end(); it != itend; it++)
+ {
+ if (ARRAY_TYPE == it->GetType())
+ {
+ //get the name of the variable
+ const char * c = it->GetName();
+ std::string ss(c);
+ if (!(0 == strncmp(ss.c_str(), "ini_", 4)))
+ continue;
+ reverse(ss.begin(), ss.end());
+
+ //cout << "debugging: " << ss;
+ size_t pos = ss.find('_', 0);
+ if (!((0 < pos) && (pos < ss.size())))
+ continue;
+
+ //get the associated length
+ std::string sss = ss.substr(0, pos);
+ reverse(sss.begin(), sss.end());
+ int n = atoi(sss.c_str());
+
+ it->PL_Print(cout, 2);
+ for (int j = 0; j < n; j++)
+ {
+ ASTNode index = CreateBVConst(it->GetIndexWidth(), j);
+ ASTNode readexpr = CreateTerm(READ, it->GetValueWidth(), *it, index);
+ ASTNode val = GetCounterExample(t, readexpr);
+ //cout << "ASSERT( ";
+ //cout << " = ";
+ out_int.push_back(GetUnsignedConst(val));
+ //cout << "\n";
+ }
+ }
}
- if(o == ASTTrue)
- output = ASTFalse;
- else
- output = ASTTrue;
- break;
- }
- case NOT:
- if(ASTTrue == ComputeFormulaUsingModel(form[0]))
- output = ASTFalse;
- else
- output = ASTTrue;
- break;
- case OR:
- for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++)
- if(ASTTrue == ComputeFormulaUsingModel(*it))
- output = ASTTrue;
- break;
- case AND:
- output = ASTTrue;
- for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++) {
- if(ASTFalse == ComputeFormulaUsingModel(*it)) {
- output = ASTFalse;
- break;
+ cout << endl;
+ for (unsigned int jj = 0; jj < out_int.size(); jj++)
+ cout << out_int[jj] << endl;
+ cout << endl;
+} //End of PrintCounterExample_InOrder
+
+/* FUNCTION: queries the CounterExampleMap object with 'expr' and
+ * returns the corresponding counterexample value.
+ */
+ASTNode BeevMgr::GetCounterExample(bool t, const ASTNode& expr)
+{
+ //input is valid, no counterexample to get
+ if (ValidFlag)
+ return ASTUndefined;
+
+ if (BOOLEAN_TYPE == expr.GetType())
+ {
+ return ComputeFormulaUsingModel(expr);
}
- }
- break;
- case XOR:
- t0 = ComputeFormulaUsingModel(form[0]);
- t1 = ComputeFormulaUsingModel(form[1]);
- if((ASTTrue == t0 && ASTTrue == t1) || (ASTFalse == t0 && ASTFalse == t1))
- output = ASTFalse;
- else
- output = ASTTrue;
- break;
- case IFF:
- t0 = ComputeFormulaUsingModel(form[0]);
- t1 = ComputeFormulaUsingModel(form[1]);
- if((ASTTrue == t0 && ASTTrue == t1) || (ASTFalse == t0 && ASTFalse == t1))
- output = ASTTrue;
- else
- output = ASTFalse;
- break;
- case IMPLIES:
- t0 = ComputeFormulaUsingModel(form[0]);
- t1 = ComputeFormulaUsingModel(form[1]);
- if((ASTFalse == t0) || (ASTTrue == t0 && ASTTrue == t1))
- output = ASTTrue;
- else
- output = ASTFalse;
- break;
- case ITE:
- t0 = ComputeFormulaUsingModel(form[0]);
- if(ASTTrue == t0)
- output = ComputeFormulaUsingModel(form[1]);
- else if(ASTFalse == t0)
- output = ComputeFormulaUsingModel(form[2]);
- else
- FatalError("ComputeFormulaUsingModel: ITE: something is wrong with the formula: ",form);
- break;
- default:
- FatalError(" ComputeFormulaUsingModel: the kind has not been implemented", ASTUndefined);
- break;
- }
-
- //cout << "ComputeFormulaUsingModel output is:" << output << endl;
- ComputeFormulaMap[form] = output;
- return output;
- }
-
- void BeevMgr::CheckCounterExample(bool t) {
- // FIXME: Code is more useful if enable flags are check OUTSIDE the method.
- // If I want to check a counterexample somewhere, I don't want to have to set
- // the flag in order to make it actualy happen!
-
- printf("checking counterexample\n");
- if(!check_counterexample) {
- return;
- }
-
- //input is valid, no counterexample to check
- if(ValidFlag)
- return;
-
- //t is true if SAT solver generated a counterexample, else it is false
- if(!t)
- FatalError("CheckCounterExample: No CounterExample to check", ASTUndefined);
- const ASTVec c = GetAsserts();
- for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++)
- if(ASTFalse == ComputeFormulaUsingModel(*it))
- FatalError("CheckCounterExample:counterexample bogus:"\
- "assert evaluates to FALSE under counterexample: NOT OK",*it);
-
- if(ASTTrue == ComputeFormulaUsingModel(_current_query))
- FatalError("CheckCounterExample:counterexample bogus:"\
- "query evaluates to TRUE under counterexample: NOT OK",_current_query);
- }
-
- /* FUNCTION: prints a counterexample for INVALID inputs. iterate
- * through the CounterExampleMap data structure and print it to
- * stdout
- */
- void BeevMgr::PrintCounterExample(bool t, std::ostream& os) {
- //global command-line option
- // FIXME: This should always print the counterexample. If you want
- // to turn it off, check the switch at the point of call.
- if(!print_counterexample){
- return;
- }
-
- //input is valid, no counterexample to print
- if(ValidFlag){
- return;
- }
-
- //if this option is true then print the way dawson wants using a
- //different printer. do not use this printer.
- if(print_arrayval_declaredorder){
- return;
- }
-
- //t is true if SAT solver generated a counterexample, else it is
- //false
- if(!t) {
- cerr << "PrintCounterExample: No CounterExample to print: " << endl;
- return;
- }
-
- //os << "\nCOUNTEREXAMPLE: \n" << endl;
- ASTNodeMap::iterator it = CounterExampleMap.begin();
- ASTNodeMap::iterator itend = CounterExampleMap.end();
- for(;it!=itend;it++) {
- ASTNode f = it->first;
- ASTNode se = it->second;
-
- if(ARRAY_TYPE == se.GetType()) {
- FatalError("TermToConstTermUsingModel: entry in counterexample is an arraytype. bogus:",se);
- }
-
- //skip over introduced variables
- if(f.GetKind() == SYMBOL && (_introduced_symbols.find(f) != _introduced_symbols.end()))
- continue;
- if(f.GetKind() == SYMBOL ||
- (f.GetKind() == READ && f[0].GetKind() == SYMBOL && f[1].GetKind() == BVCONST)) {
- os << "ASSERT( ";
- f.PL_Print(os,0);
- os << " = ";
- if(BITVECTOR_TYPE == se.GetType()) {
- TermToConstTermUsingModel(se,false).PL_Print(os,0);
+
+ if (BVCONST == expr.GetKind())
+ {
+ return expr;
}
- else {
- se.PL_Print(os,0);
+
+ ASTNodeMap::iterator it;
+ ASTNode output;
+ if ((it = CounterExampleMap.find(expr)) != CounterExampleMap.end())
+ output = TermToConstTermUsingModel(CounterExampleMap[expr], false);
+ else
+ output = CreateZeroConst(expr.GetValueWidth());
+ return output;
+} //End of GetCounterExample
+
+//##################################################
+//##################################################
+
+// FIXME: Don't use numeric codes. Use an enum type!
+//Acceps a query, calls the SAT solver and generates Valid/InValid.
+//if returned 0 then input is INVALID
+//if returned 1 then input is VALID
+//if returned 2 then ERROR
+int BeevMgr::TopLevelSATAux(const ASTNode& inputasserts)
+{
+ ASTNode q = inputasserts;
+ ASTNode orig_input = q;
+ ASTNodeStats("input asserts and query: ", q);
+
+ ASTNode newq = q;
+ //round of substitution, solving, and simplification. ensures that
+ //DAG is minimized as much as possibly, and ideally should
+ //garuntee that all liketerms in BVPLUSes have been combined.
+ BVSolver bvsolver(this);
+ SimplifyWrites_InPlace_Flag = false;
+ Begin_RemoveWrites = false;
+ start_abstracting = false;
+ TermsAlreadySeenMap.clear();
+ do
+ {
+ q = newq;
+ newq = CreateSubstitutionMap(newq);
+ //printf("##################################################\n");
+ //ASTNodeStats("after pure substitution: ", newq);
+ newq = SimplifyFormula_TopLevel(newq, false);
+ //ASTNodeStats("after simplification: ", newq);
+ newq = bvsolver.TopLevelBVSolve(newq);
+ //ASTNodeStats("after solving: ", newq);
+ } while (q != newq);
+
+ ASTNodeStats("Before SimplifyWrites_Inplace begins: ", newq);
+ SimplifyWrites_InPlace_Flag = true;
+ Begin_RemoveWrites = false;
+ start_abstracting = false;
+ TermsAlreadySeenMap.clear();
+ do
+ {
+ q = newq;
+ newq = CreateSubstitutionMap(newq);
+ //ASTNodeStats("after pure substitution: ", newq);
+ newq = SimplifyFormula_TopLevel(newq, false);
+ //ASTNodeStats("after simplification: ", newq);
+ newq = bvsolver.TopLevelBVSolve(newq);
+ //ASTNodeStats("after solving: ", newq);
+ } while (q != newq);
+ ASTNodeStats("After SimplifyWrites_Inplace: ", newq);
+
+ start_abstracting = (arraywrite_refinement) ? true : false;
+ SimplifyWrites_InPlace_Flag = false;
+ Begin_RemoveWrites = (start_abstracting) ? false : true;
+ if (start_abstracting)
+ {
+ ASTNodeStats("before abstraction round begins: ", newq);
}
- os << " );" << endl;
- }
- }
- //os << "\nEND OF COUNTEREXAMPLE" << endl;
- } //End of PrintCounterExample
-
- /* iterate through the CounterExampleMap data structure and print it
- * to stdout. this function prints only the declared array variables
- * IN the ORDER in which they were declared. It also assumes that
- * the variables are of the form 'varname_number'. otherwise it will
- * not print anything. This function was specifically written for
- * Dawson Engler's group (bug finding research group at Stanford)
- */
- void BeevMgr::PrintCounterExample_InOrder(bool t) {
- //global command-line option to print counterexample. we do not
- //want both counterexample printers to print at the sametime.
- // FIXME: This should always print the counterexample. If you want
- // to turn it off, check the switch at the point of call.
- if(print_counterexample)
- return;
-
- //input is valid, no counterexample to print
- if(ValidFlag)
- return;
-
- //print if the commandline option is '-q'. allows printing the
- //counterexample in order.
- if(!print_arrayval_declaredorder)
- return;
-
- //t is true if SAT solver generated a counterexample, else it is
- //false
- if(!t) {
- cerr << "PrintCounterExample: No CounterExample to print: " << endl;
- return;
- }
-
- //vector to store the integer values
- std::vector<int> out_int;
- cout << "% ";
- for(ASTVec::iterator it=_special_print_set.begin(),itend=_special_print_set.end();
- it!=itend;it++) {
- if(ARRAY_TYPE == it->GetType()) {
- //get the name of the variable
- const char * c = it->GetName();
- std::string ss(c);
- if(!(0 == strncmp(ss.c_str(),"ini_",4)))
- continue;
- reverse(ss.begin(),ss.end());
-
- //cout << "debugging: " << ss;
- size_t pos = ss.find('_',0);
- if(!((0 < pos) && (pos < ss.size())))
- continue;
-
- //get the associated length
- std::string sss = ss.substr(0,pos);
- reverse(sss.begin(),sss.end());
- int n = atoi(sss.c_str());
-
- it->PL_Print(cout,2);
- for(int j=0;j < n; j++) {
- ASTNode index = CreateBVConst(it->GetIndexWidth(),j);
- ASTNode readexpr = CreateTerm(READ,it->GetValueWidth(),*it,index);
- ASTNode val = GetCounterExample(t, readexpr);
- //cout << "ASSERT( ";
- //cout << " = ";
- out_int.push_back(GetUnsignedConst(val));
- //cout << "\n";
+
+ TermsAlreadySeenMap.clear();
+ do
+ {
+ q = newq;
+ //newq = CreateSubstitutionMap(newq);
+ //Begin_RemoveWrites = true;
+ //ASTNodeStats("after pure substitution: ", newq);
+ newq = SimplifyFormula_TopLevel(newq, false);
+ //ASTNodeStats("after simplification: ", newq);
+ //newq = bvsolver.TopLevelBVSolve(newq);
+ //ASTNodeStats("after solving: ", newq);
+ } while (q != newq);
+
+ if (start_abstracting)
+ {
+ ASTNodeStats("After abstraction: ", newq);
}
- }
- }
- cout << endl;
- for(unsigned int jj=0; jj < out_int.size();jj++)
- cout << out_int[jj] << endl;
- cout << endl;
- } //End of PrintCounterExample_InOrder
-
- /* FUNCTION: queries the CounterExampleMap object with 'expr' and
- * returns the corresponding counterexample value.
- */
- ASTNode BeevMgr::GetCounterExample(bool t, const ASTNode& expr) {
- //input is valid, no counterexample to get
- if(ValidFlag)
- return ASTUndefined;
-
- if(BOOLEAN_TYPE == expr.GetType()) {
- return ComputeFormulaUsingModel(expr);
- }
-
- if(BVCONST == expr.GetKind()) {
- return expr;
- }
-
- ASTNodeMap::iterator it;
- ASTNode output;
- if((it = CounterExampleMap.find(expr)) != CounterExampleMap.end())
- output = TermToConstTermUsingModel(CounterExampleMap[expr],false);
- else
- output = CreateZeroConst(expr.GetValueWidth());
- return output;
- } //End of GetCounterExample
-
- //##################################################
- //##################################################
-
- // FIXME: Don't use numeric codes. Use an enum type!
- //Acceps a query, calls the SAT solver and generates Valid/InValid.
- //if returned 0 then input is INVALID
- //if returned 1 then input is VALID
- //if returned 2 then ERROR
- int BeevMgr::TopLevelSATAux( const ASTNode& inputasserts) {
- ASTNode q = inputasserts;
- ASTNode orig_input = q;
- ASTNodeStats("input asserts and query: ", q);
-
- ASTNode newq = q;
- //round of substitution, solving, and simplification. ensures that
- //DAG is minimized as much as possibly, and ideally should
- //garuntee that all liketerms in BVPLUSes have been combined.
- BVSolver bvsolver(this);
- SimplifyWrites_InPlace_Flag = false;
- Begin_RemoveWrites = false;
- start_abstracting = false;
- TermsAlreadySeenMap.clear();
- do {
- q = newq;
- newq = CreateSubstitutionMap(newq);
- //printf("##################################################\n");
- //ASTNodeStats("after pure substitution: ", newq);
- newq = SimplifyFormula_TopLevel(newq,false);
- //ASTNodeStats("after simplification: ", newq);
- newq = bvsolver.TopLevelBVSolve(newq);
- //ASTNodeStats("after solving: ", newq);
- }while(q!=newq);
-
-
- ASTNodeStats("Before SimplifyWrites_Inplace begins: ", newq);
- SimplifyWrites_InPlace_Flag = true;
- Begin_RemoveWrites = false;
- start_abstracting = false;
- TermsAlreadySeenMap.clear();
- do {
- q = newq;
- newq = CreateSubstitutionMap(newq);
- //ASTNodeStats("after pure substitution: ", newq);
- newq = SimplifyFormula_TopLevel(newq,false);
- //ASTNodeStats("after simplification: ", newq);
- newq = bvsolver.TopLevelBVSolve(newq);
- //ASTNodeStats("after solving: ", newq);
- }while(q!=newq);
- ASTNodeStats("After SimplifyWrites_Inplace: ", newq);
-
- start_abstracting = (arraywrite_refinement) ? true : false;
- SimplifyWrites_InPlace_Flag = false;
- Begin_RemoveWrites = (start_abstracting) ? false : true;
- if(start_abstracting) {
- ASTNodeStats("before abstraction round begins: ", newq);
- }
-
- TermsAlreadySeenMap.clear();
- do {
- q = newq;
- //newq = CreateSubstitutionMap(newq);
- //Begin_RemoveWrites = true;
- //ASTNodeStats("after pure substitution: ", newq);
- newq = SimplifyFormula_TopLevel(newq,false);
- //ASTNodeStats("after simplification: ", newq);
- //newq = bvsolver.TopLevelBVSolve(newq);
- //ASTNodeStats("after solving: ", newq);
- }while(q!=newq);
-
- if(start_abstracting) {
- ASTNodeStats("After abstraction: ", newq);
- }
- start_abstracting = false;
- SimplifyWrites_InPlace_Flag = false;
- Begin_RemoveWrites = false;
-
- newq = TransformFormula(newq);
- ASTNodeStats("after transformation: ", newq);
- TermsAlreadySeenMap.clear();
-
- int res;
- //solver instantiated here
- MINISAT::Solver newS;
- if(arrayread_refinement) {
- counterexample_checking_during_refinement = true;
- }
-
- res = CallSAT_ResultCheck(newS,newq,orig_input);
- if(2 != res) {
- CountersAndStats("print_func_stats");
- return res;
- }
-
- res = SATBased_ArrayReadRefinement(newS,newq,orig_input);
- if(2 != res) {
- CountersAndStats("print_func_stats");
- return res;
- }
-
- res = SATBased_ArrayWriteRefinement(newS,orig_input);
- if(2 != res) {
- CountersAndStats("print_func_stats");
- return res;
- }
-
- res = SATBased_ArrayReadRefinement(newS,newq,orig_input);
- if(2 != res) {
- CountersAndStats("print_func_stats");
- return res;
- }
-
- FatalError("TopLevelSAT: reached the end without proper conclusion:"
- "either a divide by zero in the input or a bug in STP");
- //bogus return to make the compiler shut up
- return 2;
- } //End of TopLevelSAT
-
- //go over the list of indices for each array, and generate Leibnitz
- //axioms. Then assert these axioms into the SAT solver. Check if the
- //addition of the new constraints has made the bogus counterexample
- //go away. if yes, return the correct answer. if no, continue adding
- //Leibnitz axioms systematically.
- // FIXME: What it really does is, for each array, loop over each index i.
- // inside that loop, it finds all the true and false axioms with i as first
- // index. When it's got them all, it adds the false axioms to the formula
- // and re-solves, and returns if the result is correct. Otherwise, it
- // goes on to the next index.
- // If it gets through all the indices without a correct result (which I think
- // is impossible, but this is pretty confusing), it then solves with all
- // the true axioms, too.
- // This is not the most obvious way to do it, and I don't know how it
- // compares with other approaches (e.g., one false axiom at a time or
- // all the false axioms each time).
- int BeevMgr::SATBased_ArrayReadRefinement(MINISAT::Solver& newS,
- const ASTNode& q, const ASTNode& orig_input) {
- //printf("doing array read refinement\n");
- if(!arrayread_refinement)
- FatalError("SATBased_ArrayReadRefinement: Control should not reach here");
-
- ASTVec FalseAxiomsVec, RemainingAxiomsVec;
- RemainingAxiomsVec.push_back(ASTTrue);
- FalseAxiomsVec.push_back(ASTTrue);
- unsigned int oldFalseAxiomsSize = 0;
-
- //in these loops we try to construct Leibnitz axioms and add it to
- //the solve(). We add only those axioms that are false in the
- //current counterexample. we keep adding the axioms until there
- //are no more axioms to add
- //
- //for each array, fetch its list of indices seen so far
- for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), iset_end = _arrayname_readindices.end();
- iset!=iset_end;iset++) {
- ASTVec listOfIndices = iset->second;
- //loop over the list of indices for the array and create LA, and add to q
- for(ASTVec::iterator it=listOfIndices.begin(),itend=listOfIndices.end();it!=itend;it++) {
- if(BVCONST == it->GetKind()) {
- continue;
- }
-
- ASTNode the_index = *it;
- //get the arrayname
- ASTNode ArrName = iset->first;
- // if(SYMBOL != ArrName.GetKind())
- // FatalError("SATBased_ArrayReadRefinement: arrname is not a SYMBOL",ArrName);
- ASTNode arr_read1 = CreateTerm(READ, ArrName.GetValueWidth(), ArrName, the_index);
- //get the variable corresponding to the array_read1
- ASTNode arrsym1 = _arrayread_symbol[arr_read1];
- if(!(SYMBOL == arrsym1.GetKind() || BVCONST == arrsym1.GetKind()))
- FatalError("TopLevelSAT: refinementloop:term arrsym1 corresponding to READ must be a var", arrsym1);
-
- //we have nonconst index here. create Leibnitz axiom for it
- //w.r.t every index in listOfIndices
- for(ASTVec::iterator it1=listOfIndices.begin(),itend1=listOfIndices.end();
- it1!=itend1;it1++) {
- ASTNode compare_index = *it1;
- //do not compare with yourself
- if(the_index == compare_index)
- continue;
-
- //prepare for SAT LOOP
- //first construct the antecedent for the LA axiom
- ASTNode eqOfIndices =
- (exprless(the_index,compare_index)) ?
- CreateSimplifiedEQ(the_index,compare_index) : CreateSimplifiedEQ(compare_index,the_index);
-
- ASTNode arr_read2 = CreateTerm(READ, ArrName.GetValueWidth(), ArrName, compare_index);
- //get the variable corresponding to the array_read2
- ASTNode arrsym2 = _arrayread_symbol[arr_read2];
- if(!(SYMBOL == arrsym2.GetKind() || BVCONST == arrsym2.GetKind()))
- FatalError("TopLevelSAT: refinement loop:"
- "term arrsym2 corresponding to READ must be a var", arrsym2);
-
- ASTNode eqOfReads = CreateSimplifiedEQ(arrsym1,arrsym2);
- //construct appropriate Leibnitz axiom
- ASTNode LeibnitzAxiom = CreateNode(IMPLIES, eqOfIndices, eqOfReads);
- if(ASTFalse == ComputeFormulaUsingModel(LeibnitzAxiom))
- //FalseAxioms = CreateNode(AND,FalseAxioms,LeibnitzAxiom);
- FalseAxiomsVec.push_back(LeibnitzAxiom);
- else
- //RemainingAxioms = CreateNode(AND,RemainingAxioms,LeibnitzAxiom);
- RemainingAxiomsVec.push_back(LeibnitzAxiom);
+ start_abstracting = false;
+ SimplifyWrites_InPlace_Flag = false;
+ Begin_RemoveWrites = false;
+
+ newq = TransformFormula(newq);
+ ASTNodeStats("after transformation: ", newq);
+ TermsAlreadySeenMap.clear();
+
+ int res;
+ //solver instantiated here
+ MINISAT::Solver newS;
+ if (arrayread_refinement)
+ {
+ counterexample_checking_during_refinement = true;
}
- ASTNode FalseAxioms = (FalseAxiomsVec.size()>1) ? CreateNode(AND,FalseAxiomsVec) : FalseAxiomsVec[0];
- ASTNodeStats("adding false readaxioms to SAT: ", FalseAxioms);
- //printf("spot 01\n");
- int res2 = 2;
- if(FalseAxiomsVec.size() > oldFalseAxiomsSize){
- res2 = CallSAT_ResultCheck(newS,FalseAxioms,orig_input);
- oldFalseAxiomsSize = FalseAxiomsVec.size();
- }
- //printf("spot 02, res2 = %d\n", res2);
- if(2!=res2) {
- return res2;
- }
- }
- }
- ASTNode RemainingAxioms = (RemainingAxiomsVec.size()>1) ? CreateNode(AND,RemainingAxiomsVec):RemainingAxiomsVec[0];
- ASTNodeStats("adding remaining readaxioms to SAT: ", RemainingAxioms);
- return CallSAT_ResultCheck(newS,RemainingAxioms,orig_input);
- } //end of SATBased_ArrayReadRefinement
-
- ASTNode BeevMgr::Create_ArrayWriteAxioms(const ASTNode& term, const ASTNode& newvar) {
- if(READ != term.GetKind() && WRITE != term[0].GetKind()) {
- FatalError("Create_ArrayWriteAxioms: Input must be a READ over a WRITE",term);
- }
-
- ASTNode lhs = newvar;
- ASTNode rhs = term;
- ASTNode arraywrite_axiom = CreateSimplifiedEQ(lhs,rhs);
- return arraywrite_axiom;
- }//end of Create_ArrayWriteAxioms()
-
- int BeevMgr::SATBased_ArrayWriteRefinement(MINISAT::Solver& newS, const ASTNode& orig_input) {
- ASTNode writeAxiom;
- ASTNodeMap::iterator it = ReadOverWrite_NewName_Map.begin();
- ASTNodeMap::iterator itend = ReadOverWrite_NewName_Map.end();
- unsigned int oldFalseAxiomsSize = 0;
- //int count = 0;
- //int num_write_axioms = ReadOverWrite_NewName_Map.size();
-
- ASTVec FalseAxioms, RemainingAxioms;
- FalseAxioms.push_back(ASTTrue);
- RemainingAxioms.push_back(ASTTrue);
- for(;it!=itend;it++) {
- //Guided refinement starts here
- ComputeFormulaMap.clear();
- writeAxiom = Create_ArrayWriteAxioms(it->first,it->second);
- if(ASTFalse == ComputeFormulaUsingModel(writeAxiom)) {
- writeAxiom = TransformFormula(writeAxiom);
- FalseAxioms.push_back(writeAxiom);
- }
- else {
- writeAxiom = TransformFormula(writeAxiom);
- RemainingAxioms.push_back(writeAxiom);
- }
- }
-
- writeAxiom = (FalseAxioms.size() != 1) ? CreateNode(AND,FalseAxioms) : FalseAxioms[0];
- ASTNodeStats("adding false writeaxiom to SAT: ", writeAxiom);
- int res2 = 2;
- if(FalseAxioms.size() > oldFalseAxiomsSize){
- res2 = CallSAT_ResultCheck(newS,writeAxiom,orig_input);
- oldFalseAxiomsSize = FalseAxioms.size();
- }
- if(2!=res2) {
- return res2;
- }
-
- writeAxiom = (RemainingAxioms.size() != 1) ? CreateNode(AND,RemainingAxioms) : RemainingAxioms[0];
- ASTNodeStats("adding remaining writeaxiom to SAT: ", writeAxiom);
- res2 = CallSAT_ResultCheck(newS,writeAxiom,orig_input);
- if(2!=res2) {
- return res2;
- }
-
- return 2;
- } //end of SATBased_ArrayWriteRefinement
-#ifdef PHONY
- //Check result after calling SAT FIXME: Document arguments in
- //comments, and give them meaningful names. How is anyone supposed
- //to know what "q" is?
- int BeevMgr::CallSAT_ResultCheck(MINISAT::Solver& newS,
- const ASTNode& q, const ASTNode& orig_input) {
- //Bitblast, CNF, call SAT now
- ASTNode BBFormula = BBForm(q);
- //ASTNodeStats("after bitblasting", BBFormula);
- //ClauseList *cllp = ToCNF(BBFormula);
- // if(stats && print_nodes) {
- // cout << "\nClause list" << endl;
- // PrintClauseList(cout, *cllp);
- // cerr << "\n finished printing clauselist\n";
- // }
-
- //****************************************
- // TOCNF CONVERSION
- //****************************************
- CNFMgr *cm = new CNFMgr(this);
-
- ClauseList* cllp = new ClauseList();
- cm->NOCOPY_INPLACE_UNION(cllp, cm->SINGLETON(cm->dummy_true_var));
- cm->CountSharesPos(BBFormula);
- cm->ToCNFModRenamingPos(BBFormula);
- cm->INPLACE_UNION(cllp, *((cm->ClausesPos)[BBFormula]));
- cm->AddDefs(cllp);
- //****************************************
- // TOCNF CONVERSION
- //****************************************
-
- bool sat = toSATandSolve(newS,*cllp);
- // Temporary debugging call.
- // CheckBBandCNF(newS, BBFormula);
-
- //****************************************
- // TOCNF CLEANUP
- //****************************************
- cm->CLEAR();
- cm->DELETE(cllp);
- delete cm;
- //****************************************
- // TOCNF CLEANUP
- //****************************************
-
- if(!sat) {
- PrintOutput(true);
- return 1;
- }
- else if(newS.okay()) {
- CounterExampleMap.clear();
- ConstructCounterExample(newS);
- if (stats && print_nodes) {
- PrintSATModel(newS);
- }
- //check if the counterexample is good or not
- ComputeFormulaMap.clear();
- if(counterexample_checking_during_refinement)
- bvdiv_exception_occured = false;
- ASTNode orig_result = ComputeFormulaUsingModel(orig_input);
- if(!(ASTTrue == orig_result || ASTFalse == orig_result))
- FatalError("TopLevelSat: Original input must compute to true or false against model");
-
-// if(!arrayread_refinement && !(ASTTrue == orig_result)) {
-// print_counterexample = true;
-// PrintCounterExample(true);
-// FatalError("counterexample bogus : arrayread_refinement is switched off: "
-// "EITHER all LA axioms have not been added OR bitblaster() or ToCNF()"
-// "or satsolver() or counterexamplechecker() have a bug");
-// }
-
- // if the counterexample is indeed a good one, then return
- // invalid
- if(ASTTrue == orig_result) {
- CheckCounterExample(newS.okay());
- PrintOutput(false);
- PrintCounterExample(newS.okay());
- PrintCounterExample_InOrder(newS.okay());
- return 0;
- }
- // counterexample is bogus: flag it
- else {
- if(stats && print_nodes) {
- cout << "Supposedly bogus one: \n";
- bool tmp = print_counterexample;
- print_counterexample = true;
- PrintCounterExample(true);
- print_counterexample = tmp;
+ res = CallSAT_ResultCheck(newS, newq, orig_input);
+ if (2 != res)
+ {
+ CountersAndStats("print_func_stats");
+ return res;
}
+ res = SATBased_ArrayReadRefinement(newS, newq, orig_input);
+ if (2 != res)
+ {
+ CountersAndStats("print_func_stats");
+ return res;
+ }
+
+ res = SATBased_ArrayWriteRefinement(newS, orig_input);
+ if (2 != res)
+ {
+ CountersAndStats("print_func_stats");
+ return res;
+ }
+
+ res = SATBased_ArrayReadRefinement(newS, newq, orig_input);
+ if (2 != res)
+ {
+ CountersAndStats("print_func_stats");
+ return res;
+ }
+
+ FatalError("TopLevelSAT: reached the end without proper conclusion:"
+ "either a divide by zero in the input or a bug in STP");
+ //bogus return to make the compiler shut up
return 2;
- }
- }
- else {
- PrintOutput(true);
- return -100;
- }
- } //end of CALLSAT_ResultCheck
-#endif
+} //End of TopLevelSAT
+
+//go over the list of indices for each array, and generate Leibnitz
+//axioms. Then assert these axioms into the SAT solver. Check if the
+//addition of the new constraints has made the bogus counterexample
+//go away. if yes, return the correct answer. if no, continue adding
+//Leibnitz axioms systematically.
+// FIXME: What it really does is, for each array, loop over each index i.
+// inside that loop, it finds all the true and false axioms with i as first
+// index. When it's got them all, it adds the false axioms to the formula
+// and re-solves, and returns if the result is correct. Otherwise, it
+// goes on to the next index.
+// If it gets through all the indices without a correct result (which I think
+// is impossible, but this is pretty confusing), it then solves with all
+// the true axioms, too.
+// This is not the most obvious way to do it, and I don't know how it
+// compares with other approaches (e.g., one false axiom at a time or
+// all the false axioms each time).
+int BeevMgr::SATBased_ArrayReadRefinement(MINISAT::Solver& newS, const ASTNode& q, const ASTNode& orig_input)
+{
+ //printf("doing array read refinement\n");
+ if (!arrayread_refinement)
+ FatalError("SATBased_ArrayReadRefinement: Control should not reach here");
+
+ ASTVec FalseAxiomsVec, RemainingAxiomsVec;
+ RemainingAxiomsVec.push_back(ASTTrue);
+ FalseAxiomsVec.push_back(ASTTrue);
+ unsigned int oldFalseAxiomsSize = 0;
+
+ //in these loops we try to construct Leibnitz axioms and add it to
+ //the solve(). We add only those axioms that are false in the
+ //current counterexample. we keep adding the axioms until there
+ //are no more axioms to add
+ //
+ //for each array, fetch its list of indices seen so far
+ for (ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), iset_end = _arrayname_readindices.end(); iset != iset_end; iset++)
+ {
+ ASTVec listOfIndices = iset->second;
+ //loop over the list of indices for the array and create LA, and add to q
+ for (ASTVec::iterator it = listOfIndices.begin(), itend = listOfIndices.end(); it != itend; it++)
+ {
+ if (BVCONST == it->GetKind())
+ {
+ continue;
+ }
+
+ ASTNode the_index = *it;
+ //get the arrayname
+ ASTNode ArrName = iset->first;
+ // if(SYMBOL != ArrName.GetKind())
+ // FatalError("SATBased_ArrayReadRefinement: arrname is not a SYMBOL",ArrName);
+ ASTNode arr_read1 = CreateTerm(READ, ArrName.GetValueWidth(), ArrName, the_index);
+ //get the variable corresponding to the array_read1
+ ASTNode arrsym1 = _arrayread_symbol[arr_read1];
+ if (!(SYMBOL == arrsym1.GetKind() || BVCONST == arrsym1.GetKind()))
+ FatalError("TopLevelSAT: refinementloop:term arrsym1 corresponding to READ must be a var", arrsym1);
+
+ //we have nonconst index here. create Leibnitz axiom for it
+ //w.r.t every index in listOfIndices
+ for (ASTVec::iterator it1 = listOfIndices.begin(), itend1 = listOfIndices.end(); it1 != itend1; it1++)
+ {
+ ASTNode compare_index = *it1;
+ //do not compare with yourself
+ if (the_index == compare_index)
+ continue;
+
+ //prepare for SAT LOOP
+ //first construct the antecedent for the LA axiom
+ ASTNode eqOfIndices = (exprless(the_index, compare_index)) ? CreateSimplifiedEQ(the_index, compare_index) : CreateSimplifiedEQ(
+ compare_index, the_index);
+
+ ASTNode arr_read2 = CreateTerm(READ, ArrName.GetValueWidth(), ArrName, compare_index);
+ //get the variable corresponding to the array_read2
+ ASTNode arrsym2 = _arrayread_symbol[arr_read2];
+ if (!(SYMBOL == arrsym2.GetKind() || BVCONST == arrsym2.GetKind()))
+ FatalError("TopLevelSAT: refinement loop:"
+ "term arrsym2 corresponding to READ must be a var", arrsym2);
+
+ ASTNode eqOfReads = CreateSimplifiedEQ(arrsym1, arrsym2);
+ //construct appropriate Leibnitz axiom
+ ASTNode LeibnitzAxiom = CreateNode(IMPLIES, eqOfIndices, eqOfReads);
+ if (ASTFalse == ComputeFormulaUsingModel(LeibnitzAxiom))
+ //FalseAxioms = CreateNode(AND,FalseAxioms,LeibnitzAxiom);
+ FalseAxiomsVec.push_back(LeibnitzAxiom);
+ else
+ //RemainingAxioms = CreateNode(AND,RemainingAxioms,LeibnitzAxiom);
+ RemainingAxiomsVec.push_back(LeibnitzAxiom);
+ }
+ ASTNode FalseAxioms = (FalseAxiomsVec.size() > 1) ? CreateNode(AND, FalseAxiomsVec) : FalseAxiomsVec[0];
+ ASTNodeStats("adding false readaxioms to SAT: ", FalseAxioms);
+ //printf("spot 01\n");
+ int res2 = 2;
+ if (FalseAxiomsVec.size() > oldFalseAxiomsSize)
+ {
+ res2 = CallSAT_ResultCheck(newS, FalseAxioms, orig_input);
+ oldFalseAxiomsSize = FalseAxiomsVec.size();
+ }
+ //printf("spot 02, res2 = %d\n", res2);
+ if (2 != res2)
+ {
+ return res2;
+ }
+ }
+ }
+ ASTNode RemainingAxioms = (RemainingAxiomsVec.size() > 1) ? CreateNode(AND, RemainingAxiomsVec) : RemainingAxiomsVec[0];
+ ASTNodeStats("adding remaining readaxioms to SAT: ", RemainingAxioms);
+ return CallSAT_ResultCheck(newS, RemainingAxioms, orig_input);
+} //end of SATBased_ArrayReadRefinement
+
+ASTNode BeevMgr::Create_ArrayWriteAxioms(const ASTNode& term, const ASTNode& newvar)
+{
+ if (READ != term.GetKind() && WRITE != term[0].GetKind())
+ {
+ FatalError("Create_ArrayWriteAxioms: Input must be a READ over a WRITE", term);
+ }
+ ASTNode lhs = newvar;
+ ASTNode rhs = term;
+ ASTNode arraywrite_axiom = CreateSimplifiedEQ(lhs, rhs);
+ return arraywrite_axiom;
+}//end of Create_ArrayWriteAxioms()
+
+int BeevMgr::SATBased_ArrayWriteRefinement(MINISAT::Solver& newS, const ASTNode& orig_input)
+{
+ ASTNode writeAxiom;
+ ASTNodeMap::iterator it = ReadOverWrite_NewName_Map.begin();
+ ASTNodeMap::iterator itend = ReadOverWrite_NewName_Map.end();
+ unsigned int oldFalseAxiomsSize = 0;
+ //int count = 0;
+ //int num_write_axioms = ReadOverWrite_NewName_Map.size();
+
+ ASTVec FalseAxioms, RemainingAxioms;
+ FalseAxioms.push_back(ASTTrue);
+ RemainingAxioms.push_back(ASTTrue);
+ for (; it != itend; it++)
+ {
+ //Guided refinement starts here
+ ComputeFormulaMap.clear();
+ writeAxiom = Create_ArrayWriteAxioms(it->first, it->second);
+ if (ASTFalse == ComputeFormulaUsingModel(writeAxiom))
+ {
+ writeAxiom = TransformFormula(writeAxiom);
+ FalseAxioms.push_back(writeAxiom);
+ }
+ else
+ {
+ writeAxiom = TransformFormula(writeAxiom);
+ RemainingAxioms.push_back(writeAxiom);
+ }
+ }
+
+ writeAxiom = (FalseAxioms.size() != 1) ? CreateNode(AND, FalseAxioms) : FalseAxioms[0];
+ ASTNodeStats("adding false writeaxiom to SAT: ", writeAxiom);
+ int res2 = 2;
+ if (FalseAxioms.size() > oldFalseAxiomsSize)
+ {
+ res2 = CallSAT_ResultCheck(newS, writeAxiom, orig_input);
+ oldFalseAxiomsSize = FalseAxioms.size();
+ }
+ if (2 != res2)
+ {
+ return res2;
+ }
+
+ writeAxiom = (RemainingAxioms.size() != 1) ? CreateNode(AND, RemainingAxioms) : RemainingAxioms[0];
+ ASTNodeStats("adding remaining writeaxiom to SAT: ", writeAxiom);
+ res2 = CallSAT_ResultCheck(newS, writeAxiom, orig_input);
+ if (2 != res2)
+ {
+ return res2;
+ }
+
+ return 2;
+} //end of SATBased_ArrayWriteRefinement
- //FUNCTION: this function accepts a boolvector and returns a BVConst
- ASTNode BeevMgr::BoolVectoBVConst(hash_map<unsigned,bool> * w, unsigned int l) {
- unsigned len = w->size();
- if(l < len)
- FatalError("BoolVectorBVConst : length of bitvector does not match hash_map size:",ASTUndefined,l);
- std::string cc;
- for(unsigned int jj = 0; jj < l; jj++) {
- if((*w)[jj] == true)
- cc += '1';
- else if((*w)[jj] == false)
- cc += '0';
- else
- cc += '0';
- }
- return CreateBVConst(cc.c_str(),2);
- }
-
- /*
- void BeevMgr::PrintActivityLevels_Of_SATVars(char * init_msg, MINISAT::Solver& newS) {
- if(!print_sat_varorder)
- return;
-
- ASTtoSATMap::iterator itbegin = _ASTNode_to_SATVar.begin();
- ASTtoSATMap::iterator itend = _ASTNode_to_SATVar.end();
-
- cout << init_msg;
- cout << ": Printing activity levels of variables\n";
- for(ASTtoSATMap::iterator it=itbegin;it!=itend;it++){
- cout << (it->second) << " : ";
- (it->first).PL_Print(cout,0);
- cout << " : ";
- cout << newS.returnActivity(it->second) << endl;
- }
- }
-
- //this function biases the activity levels of MINISAT variables.
- void BeevMgr::ChangeActivityLevels_Of_SATVars(MINISAT::Solver& newS) {
- if(!variable_activity_optimize)
- return;
-
- ASTtoSATMap::iterator itbegin = _ASTNode_to_SATVar.begin();
- ASTtoSATMap::iterator itend = _ASTNode_to_SATVar.end();
-
- unsigned int index=1;
- double base = 2;
- for(ASTtoSATMap::iterator it=itbegin;it!=itend;it++){
- ASTNode n = it->first;
-
- if(BVGETBIT == n.GetKind() || NOT == n.GetKind()) {
- if(BVGETBIT == n.GetKind())
- index = GetUnsignedConst(n[1]);
- else if (NOT == n.GetKind() && BVGETBIT == n[0].GetKind())
- index = GetUnsignedConst(n[0][1]);
- else
- index = 0;
- double initial_activity = pow(base,(double)index);
- newS.updateInitialActivity(it->second,initial_activity);
- }
- else {
- double initial_activity = pow(base,pow(base,(double)index));
- newS.updateInitialActivity(it->second,initial_activity);
- }
- }
- }
- */
-
- //This function prints the output of the STP solver
- void BeevMgr::PrintOutput(bool true_iff_valid) {
- //self-explanatory
- if(print_output) {
- if(smtlib_parser_enable)
- {
- if (true_iff_valid && (BEEV::input_status == TO_BE_SATISFIABLE))
- {
- cerr << "Warning. Expected satisfiable, FOUND unsatisfiable" << endl;
- }
- else
- if (!true_iff_valid && (BEEV::input_status == TO_BE_UNSATISFIABLE))
+#ifdef PHONY
+//Check result after calling SAT FIXME: Document arguments in
+//comments, and give them meaningful names. How is anyone supposed
+//to know what "q" is?
+int BeevMgr::CallSAT_ResultCheck(MINISAT::Solver& newS,
+ const ASTNode& q, const ASTNode& orig_input)
+{
+ //Bitblast, CNF, call SAT now
+ ASTNode BBFormula = BBForm(q);
+ //ASTNodeStats("after bitblasting", BBFormula);
+ //ClauseList *cllp = ToCNF(BBFormula);
+ // if(stats && print_nodes) {
+ // cout << "\nClause list" << endl;
+ // PrintClauseList(cout, *cllp);
+ // cerr << "\n finished printing clauselist\n";
+ // }
+
+ //****************************************
+ // TOCNF CONVERSION
+ //****************************************
+ CNFMgr *cm = new CNFMgr(this);
+
+ ClauseList* cllp = new ClauseList();
+ cm->NOCOPY_INPLACE_UNION(cllp, cm->SINGLETON(cm->dummy_true_var));
+ cm->CountSharesPos(BBFormula);
+ cm->ToCNFModRenamingPos(BBFormula);
+ cm->INPLACE_UNION(cllp, *((cm->ClausesPos)[BBFormula]));
+ cm->AddDefs(cllp);
+ //****************************************
+ // TOCNF CONVERSION
+ //****************************************
+
+ bool sat = toSATandSolve(newS,*cllp);
+ // Temporary debugging call.
+ // CheckBBandCNF(newS, BBFormula);
+
+ //****************************************
+ // TOCNF CLEANUP
+ //****************************************
+ cm->CLEAR();
+ cm->DELETE(cllp);
+ delete cm;
+ //****************************************
+ // TOCNF CLEANUP
+ //****************************************
+
+ if(!sat)
+ {
+ PrintOutput(true);
+ return 1;
+ }
+ else if(newS.okay())
+ {
+ CounterExampleMap.clear();
+ ConstructCounterExample(newS);
+ if (stats && print_nodes)
{
- cerr << "Warning. Expected unsatisfiable, FOUND satisfiable" << endl;
+ PrintSATModel(newS);
}
- }
- }
-
- if(true_iff_valid) {
- ValidFlag = true;
- if(print_output) {
- if(smtlib_parser_enable)
- cout << "unsat\n";
+ //check if the counterexample is good or not
+ ComputeFormulaMap.clear();
+ if(counterexample_checking_during_refinement)
+ bvdiv_exception_occured = false;
+ ASTNode orig_result = ComputeFormulaUsingModel(orig_input);
+ if(!(ASTTrue == orig_result || ASTFalse == orig_result))
+ FatalError("TopLevelSat: Original input must compute to true or false against model");
+
+ // if(!arrayread_refinement && !(ASTTrue == orig_result)) {
+ // print_counterexample = true;
+ // PrintCounterExample(true);
+ // FatalError("counterexample bogus : arrayread_refinement is switched off: "
+ // "EITHER all LA axioms have not been added OR bitblaster() or ToCNF()"
+ // "or satsolver() or counterexamplechecker() have a bug");
+ // }
+
+ // if the counterexample is indeed a good one, then return
+ // invalid
+ if(ASTTrue == orig_result)
+ {
+ CheckCounterExample(newS.okay());
+ PrintOutput(false);
+ PrintCounterExample(newS.okay());
+ PrintCounterExample_InOrder(newS.okay());
+ return 0;
+ }
+ // counterexample is bogus: flag it
+
+ else
+ {
+ if(stats && print_nodes)
+ {
+ cout << "Supposedly bogus one: \n";
+ bool tmp = print_counterexample;
+ print_counterexample = true;
+ PrintCounterExample(true);
+ print_counterexample = tmp;
+ }
+
+ return 2;
+ }
+ }
else
- cout << "Valid.\n";
- }
- }
- else {
- ValidFlag = false;
- if(print_output) {
- if(smtlib_parser_enable)
- cout << "sat\n";
+ {
+ PrintOutput(true);
+ return -100;
+ }
+} //end of CALLSAT_ResultCheck
+#endif
+
+//FUNCTION: this function accepts a boolvector and returns a BVConst
+ASTNode BeevMgr::BoolVectoBVConst(hash_map<unsigned, bool> * w, unsigned int l)
+{
+ unsigned len = w->size();
+ if (l < len)
+ FatalError("BoolVectorBVConst : length of bitvector does not match hash_map size:", ASTUndefined, l);
+ std::string cc;
+ for (unsigned int jj = 0; jj < l; jj++)
+ {
+ if ((*w)[jj] == true)
+ cc += '1';
+ else if ((*w)[jj] == false)
+ cc += '0';
+ else
+ cc += '0';
+ }
+ return CreateBVConst(cc.c_str(), 2);
+}
+
+/*
+ void BeevMgr::PrintActivityLevels_Of_SATVars(char * init_msg, MINISAT::Solver& newS) {
+ if(!print_sat_varorder)
+ return;
+
+ ASTtoSATMap::iterator itbegin = _ASTNode_to_SATVar.begin();
+ ASTtoSATMap::iterator itend = _ASTNode_to_SATVar.end();
+
+ cout << init_msg;
+ cout << ": Printing activity levels of variables\n";
+ for(ASTtoSATMap::iterator it=itbegin;it!=itend;it++){
+ cout << (it->second) << " : ";
+ (it->first).PL_Print(cout,0);
+ cout << " : ";
+ cout << newS.returnActivity(it->second) << endl;
+ }
+ }
+
+ //this function biases the activity levels of MINISAT variables.
+ void BeevMgr::ChangeActivityLevels_Of_SATVars(MINISAT::Solver& newS) {
+ if(!variable_activity_optimize)
+ return;
+
+ ASTtoSATMap::iterator itbegin = _ASTNode_to_SATVar.begin();
+ ASTtoSATMap::iterator itend = _ASTNode_to_SATVar.end();
+
+ unsigned int index=1;
+ double base = 2;
+ for(ASTtoSATMap::iterator it=itbegin;it!=itend;it++){
+ ASTNode n = it->first;
+
+ if(BVGETBIT == n.GetKind() || NOT == n.GetKind()) {
+ if(BVGETBIT == n.GetKind())
+ index = GetUnsignedConst(n[1]);
+ else if (NOT == n.GetKind() && BVGETBIT == n[0].GetKind())
+ index = GetUnsignedConst(n[0][1]);
+ else
+ index = 0;
+ double initial_activity = pow(base,(double)index);
+ newS.updateInitialActivity(it->second,initial_activity);
+ }
+ else {
+ double initial_activity = pow(base,pow(base,(double)index));
+ newS.updateInitialActivity(it->second,initial_activity);
+ }
+ }
+ }
+ */
+
+//This function prints the output of the STP solver
+void BeevMgr::PrintOutput(bool true_iff_valid)
+{
+ //self-explanatory
+ if (print_output)
+ {
+ if (smtlib_parser_enable)
+ {
+ if (true_iff_valid && (BEEV::input_status == TO_BE_SATISFIABLE))
+ {
+ cerr << "Warning. Expected satisfiable, FOUND unsatisfiable" << endl;
+ }
+ else if (!true_iff_valid && (BEEV::input_status == TO_BE_UNSATISFIABLE))
+ {
+ cerr << "Warning. Expected unsatisfiable, FOUND satisfiable" << endl;
+ }
+ }
+ }
+
+ if (true_iff_valid)
+ {
+ ValidFlag = true;
+ if (print_output)
+ {
+ if (smtlib_parser_enable)
+ cout << "unsat\n";
+ else
+ cout << "Valid.\n";
+ }
+ }
else
- cout << "Invalid.\n";
- }
- }
- }
-}; //end of namespace BEEV
+ {
+ ValidFlag = false;
+ if (print_output)
+ {
+ if (smtlib_parser_enable)
+ cout << "sat\n";
+ else
+ cout << "Invalid.\n";
+ }
+ }
+}
+}
+; //end of namespace BEEV
#include "AST.h"
#include <stdlib.h>
#include <stdio.h>
-namespace BEEV {
-
- //Translates signed BVDIV/BVMOD into unsigned variety
- ASTNode BeevMgr::TranslateSignedDivMod(const ASTNode& in) {
- if(!(SBVREM == in.GetKind() || SBVDIV == in.GetKind())) {
- FatalError("TranslateSignedDivMod: input must be signed DIV/MOD\n",in);
- }
-
- ASTNode dividend = in[0];
- ASTNode divisor = in[1];
- unsigned len = in.GetValueWidth();
-
- ASTNode hi1 = CreateBVConst(32,len-1);
- ASTNode one = CreateOneConst(1);
- ASTNode zero = CreateZeroConst(1);
- // create the condition for the dividend
- ASTNode cond_dividend = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1));
- // create the condition for the divisor
- ASTNode cond_divisor = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1));
-
- if(SBVREM == in.GetKind()) {
- //if(TopBit(dividend)==1)
- //
- //then -BVMOD(-dividend,abs(divisor))
- //
- //else BVMOD(dividend,abs(divisor))
-
- //create the condition and conditional for the divisor
- ASTNode pos_divisor = CreateTerm(ITE,len,cond_divisor,CreateTerm(BVUMINUS,len,divisor),divisor);
-
- //create the modulus term for each case
- ASTNode modnode = CreateTerm(BVMOD,len,dividend,pos_divisor);
- ASTNode minus_modnode = CreateTerm(BVMOD,len,CreateTerm(BVUMINUS,len,dividend),pos_divisor);
- minus_modnode = CreateTerm(BVUMINUS,len,minus_modnode);
-
- //put everything together, simplify, and return
- ASTNode n = CreateTerm(ITE,len,cond_dividend,minus_modnode,modnode);
- return SimplifyTerm_TopLevel(n);
- }
-
- if(SBVMOD == in.GetKind()) {
- // (let (?msb_s (extract[|m-1|:|m-1|] s))
- // (let (?msb_t (extract[|m-1|:|m-1|] t))
- // (ite (and (= ?msb_s bit0) (= ?msb_t bit0))
- // (bvurem s t)
- // (ite (and (= ?msb_s bit1) (= ?msb_t bit0))
- // (bvadd (bvneg (bvurem (bvneg s) t)) t)
- // (ite (and (= ?msb_s bit0) (= ?msb_t bit1))
- // (bvadd (bvurem s (bvneg t)) t)
- // (bvneg (bvurem (bvneg s) (bvneg t)))))))
- ASTNode & s = dividend;
- ASTNode & t = divisor;
- ASTNode & msb_s = cond_dividend;
- ASTNode & msb_t = cond_divisor;
-
- ASTNode isSPos = CreateNode(EQ, msb_s, zero); // (= ?msb_s bit0)
- ASTNode isSNeg = CreateNode(EQ, msb_s, one); // (= ?msb_s bit1)
- ASTNode isTPos = CreateNode(EQ, msb_t, zero); // (= ?msb_t bit0)
- ASTNode isTNeg = CreateNode(EQ, msb_t, one); // (= ?msb_t bit1)
-
- ASTNode negS = CreateTerm(BVUMINUS, len, s); // (bvneg s)
- ASTNode negT = CreateTerm(BVUMINUS, len, t); // (bvneg s)
-
- // (bvneg (bvurem (bvneg s) (bvneg t)))
- ASTNode branch4 = CreateTerm(BVUMINUS, len, CreateTerm(BVMOD, len, negS, negT));
- // (bvadd (bvurem s (bvneg t)) t)
- ASTNode branch3 = CreateTerm(BVPLUS, len, CreateTerm(BVMOD, len, s, negT), t);
- // (bvadd (bvneg (bvurem (bvneg s) t)) t)
- ASTNode branch2 = CreateTerm(BVPLUS, len, CreateTerm(BVUMINUS, len, CreateTerm(BVMOD, len, negS, t)), t);
- // (bvurem s t)
- ASTNode branch1 = CreateTerm(BVMOD, len, s, t);
-
- ASTNode ite3 = CreateTerm(ITE, len, CreateNode(AND, isSPos, isTNeg), branch3, branch4);
- ASTNode ite2 = CreateTerm(ITE, len, CreateNode(AND, isSNeg, isTPos), branch2, ite3);
- ASTNode ite1 = CreateTerm(ITE, len, CreateNode(AND, isSPos, isTPos), branch1, ite2);
-
- return SimplifyTerm_TopLevel(ite1);
- }
-
- //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)
- ASTNode divnode = CreateTerm(BVDIV, len, dividend, divisor);
-
- ASTNode cond1 = CreateNode(AND,
- CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
- CreateNode(EQ,one, CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
- ASTNode minus_divnode1 = CreateTerm(BVDIV,len,
- dividend,
- CreateTerm(BVUMINUS,len,divisor));
- minus_divnode1 = CreateTerm(BVUMINUS,len,minus_divnode1);
-
- ASTNode cond2 = CreateNode(AND,
- CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
- CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
- ASTNode minus_divnode2 = CreateTerm(BVDIV,len,
- CreateTerm(BVUMINUS,len,dividend),
- divisor);
- minus_divnode2 = CreateTerm(BVUMINUS,len,minus_divnode2);
-
- ASTNode cond3 = CreateNode(AND,
- CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
- CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
- ASTNode minus_divnode3 = CreateTerm(BVDIV,len,
- CreateTerm(BVUMINUS,len,dividend),
- CreateTerm(BVUMINUS,len,divisor));
- ASTNode n = CreateTerm(ITE,len,
- cond1,
- minus_divnode1,
- CreateTerm(ITE,len,
- cond2,
- minus_divnode2,
- CreateTerm(ITE,len,
- cond3,
- minus_divnode3,
- divnode)));
- return SimplifyTerm_TopLevel(n);
- }//end of TranslateSignedDivMod()
-
- /*
- //Translates signed BVDIV/BVMOD into unsigned variety
- ASTNode BeevMgr::TranslateSignedDivMod(const ASTNode& in) {
- if(!(SBVREM == in.GetKind() || SBVDIV == in.GetKind())) {
- FatalError("TranslateSignedDivMod: input must be signed DIV/MOD\n",in);
- }
-
- ASTNode dividend = in[0];
- ASTNode divisor = in[1];
- unsigned len = in.GetValueWidth();
- if(SBVMOD == in.GetKind()) {
- //if(TopBit(dividend)==1)
- //
- //then -BVMOD(-dividend,abs(divisor))
- //
- //else BVMOD(dividend,abs(divisor))
-
- //create the condition for the dividend
- ASTNode hi1 = CreateBVConst(32,len-1);
- ASTNode one = CreateOneConst(1);
- ASTNode cond = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1));
-
- //create the condition and conditional for the divisor
- ASTNode cond_divisor = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1));
- ASTNode pos_divisor = CreateTerm(ITE,len,cond_divisor,CreateTerm(BVUMINUS,len,divisor),divisor);
-
- //create the modulus term for each case
- ASTNode modnode = CreateTerm(BVMOD,len,dividend,pos_divisor);
- ASTNode minus_modnode = CreateTerm(BVMOD,len,CreateTerm(BVUMINUS,len,dividend),pos_divisor);
- minus_modnode = CreateTerm(BVUMINUS,len,minus_modnode);
-
- //put everything together, simplify, and return
- ASTNode n = CreateTerm(ITE,len,cond,minus_modnode,modnode);
- return SimplifyTerm_TopLevel(n);
- }
-
- //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)
- ASTNode hi1 = CreateBVConst(32,len-1);
- ASTNode zero = CreateZeroConst(1);
- ASTNode one = CreateOneConst(1);
- ASTNode divnode = CreateTerm(BVDIV, len, dividend, divisor);
-
- ASTNode cond1 = CreateNode(AND,
- CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
- CreateNode(EQ,one, CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
- ASTNode minus_divnode1 = CreateTerm(BVDIV,len,
- dividend,
- CreateTerm(BVUMINUS,len,divisor));
- minus_divnode1 = CreateTerm(BVUMINUS,len,minus_divnode1);
-
- ASTNode cond2 = CreateNode(AND,
- CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
- CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
- ASTNode minus_divnode2 = CreateTerm(BVDIV,len,
- CreateTerm(BVUMINUS,len,dividend),
- divisor);
- minus_divnode2 = CreateTerm(BVUMINUS,len,minus_divnode2);
-
- ASTNode cond3 = CreateNode(AND,
- CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
- CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
- ASTNode minus_divnode3 = CreateTerm(BVDIV,len,
- CreateTerm(BVUMINUS,len,dividend),
- CreateTerm(BVUMINUS,len,divisor));
- ASTNode n = CreateTerm(ITE,len,
- cond1,
- minus_divnode1,
- CreateTerm(ITE,len,
- cond2,
- minus_divnode2,
- CreateTerm(ITE,len,
- cond3,
- minus_divnode3,
- divnode)));
- return SimplifyTerm_TopLevel(n);
- }//end of TranslateSignedDivMod()
- */
-
- ASTNode BeevMgr::TransformFormula(const ASTNode& form) {
- ASTNode result;
-
- ASTNode simpleForm = form;
- Kind k = simpleForm.GetKind();
- if(!(is_Form_kind(k) && BOOLEAN_TYPE == simpleForm.GetType())) {
- //FIXME: "You have inputted a NON-formula"?
- FatalError("TransformFormula: You have input a NON-formula",simpleForm);
- }
-
- ASTNodeMap::iterator iter;
- if((iter = TransformMap.find(simpleForm)) != TransformMap.end())
- return iter->second;
-
- switch(k) {
- case TRUE:
- case FALSE: {
- result = simpleForm;
- break;
- }
- case NOT: {
- ASTVec c;
- c.push_back(TransformFormula(simpleForm[0]));
- result = CreateNode(NOT,c);
- break;
- }
- case BVLT:
- case BVLE:
- case BVGT:
- case BVGE:
- case BVSLT:
- case BVSLE:
- case BVSGT:
- case BVSGE:
- case NEQ: {
- ASTVec c;
- c.push_back(TransformTerm(simpleForm[0]));
- c.push_back(TransformTerm(simpleForm[1]));
- result = CreateNode(k,c);
- break;
- }
- case EQ: {
- ASTNode term1 = TransformTerm(simpleForm[0]);
- ASTNode term2 = TransformTerm(simpleForm[1]);
- result = CreateSimplifiedEQ(term1,term2);
- break;
- }
- case AND:
- case OR:
- case NAND:
- case NOR:
- case IFF:
- case XOR:
- case ITE:
- case IMPLIES: {
- ASTVec vec;
- ASTNode o;
- for (ASTVec::const_iterator it = simpleForm.begin(),itend=simpleForm.end(); it != itend; it++){
- o = TransformFormula(*it);
- vec.push_back(o);
- }
-
- result = CreateNode(k, vec);
- break;
- }
- default:
- if(k == SYMBOL && BOOLEAN_TYPE == simpleForm.GetType())
- result = simpleForm;
- else {
- cerr << "The input is: " << simpleForm << endl;
- cerr << "The valuewidth of input is : " << simpleForm.GetValueWidth() << endl;
- FatalError("TransformFormula: Illegal kind: ",ASTUndefined, k);
- }
- break;
- }
- //BVTypeCheck(result);
- TransformMap[simpleForm] = result;
- return result;
- } //End of TransformFormula
-
- ASTNode BeevMgr::TransformTerm(const ASTNode& inputterm) {
- ASTNode result;
- ASTNode term = inputterm;
-
- Kind k = term.GetKind();
- if(!is_Term_kind(k))
- FatalError("TransformTerm: Illegal kind: You have input a nonterm:", inputterm, k);
- ASTNodeMap::iterator iter;
- if((iter = TransformMap.find(term)) != TransformMap.end())
- return iter->second;
- switch(k) {
- case SYMBOL: {
- // ASTNodeMap::iterator itsym;
-// if((itsym = CounterExampleMap.find(term)) != CounterExampleMap.end())
-// result = itsym->second;
-// else
- result = term;
- break;
- }
- case BVCONST:
- result = term;
- break;
- case WRITE:
- FatalError("TransformTerm: this kind is not supported",term);
- break;
- case READ:
- result = TransformArray(term);
- break;
- case ITE: {
- ASTNode cond = term[0];
- ASTNode thn = term[1];
- ASTNode els = term[2];
- cond = TransformFormula(cond);
- thn = TransformTerm(thn);
- els = TransformTerm(els);
- //result = CreateTerm(ITE,term.GetValueWidth(),cond,thn,els);
- result = CreateSimplifiedTermITE(cond,thn,els);
- result.SetIndexWidth(term.GetIndexWidth());
- break;
- }
- default: {
- ASTVec c = term.GetChildren();
- ASTVec::iterator it = c.begin();
- ASTVec::iterator itend = c.end();
- unsigned width = term.GetValueWidth();
- unsigned indexwidth = term.GetIndexWidth();
- ASTVec o;
- for(;it!=itend;it++) {
- o.push_back(TransformTerm(*it));
- }
-
- result = CreateTerm(k,width,o);
- result.SetIndexWidth(indexwidth);
-
- if(SBVDIV == result.GetKind() || SBVREM == result.GetKind() || SBVMOD == result.GetKind()) {
- result = TranslateSignedDivMod(result);
- }
- break;
- }
- }
-
- TransformMap[term] = result;
- if(term.GetValueWidth() != result.GetValueWidth())
- FatalError("TransformTerm: result and input terms are of different length", result);
- if(term.GetIndexWidth() != result.GetIndexWidth()) {
- cerr << "TransformTerm: input term is : " << term << endl;
- FatalError("TransformTerm: result and input terms have different index length", result);
- }
- return result;
- } //End of TransformTerm
-
- /* This function transforms Array Reads, Read over Writes, Read over
- * ITEs into flattened form.
- *
- * Transform1: Suppose there are two array reads in the input
- * Read(A,i) and Read(A,j) over the same array. Then Read(A,i) is
- * replaced with a symbolic constant, say v1, and Read(A,j) is
- * replaced with the following ITE:
- *
- * ITE(i=j,v1,v2)
- *
- * Transform2:
- *
- * Transform3:
- */
- ASTNode BeevMgr::TransformArray(const ASTNode& term) {
- ASTNode result = term;
-
- unsigned int width = term.GetValueWidth();
- Kind k = term.GetKind();
- if (!is_Term_kind(k))
- FatalError("TransformArray: Illegal kind: You have input a nonterm:", ASTUndefined, k);
- ASTNodeMap::iterator iter;
- if((iter = TransformMap.find(term)) != TransformMap.end())
- return iter->second;
-
- switch(k) {
- //'term' is of the form READ(arrName, readIndex)
- case READ: {
- ASTNode arrName = term[0];
- switch (arrName.GetKind()) {
- case SYMBOL: {
- /* input is of the form: READ(A, readIndex)
- *
- * output is of the from: A1, if this is the first READ over A
- *
- * ITE(previous_readIndex=readIndex,A1,A2)
- *
- * .....
- */
-
- // Recursively transform read index, which may also contain reads.
- ASTNode readIndex = TransformTerm(term[1]);
- ASTNode processedTerm = CreateTerm(READ,width,arrName,readIndex);
-
- //check if the 'processedTerm' has a corresponding ITE construct
- //already. if so, return it. else continue processing.
- ASTNodeMap::iterator it;
- if((it = _arrayread_ite.find(processedTerm)) != _arrayread_ite.end()) {
- result = it->second;
- break;
+namespace BEEV
+{
+
+//Translates signed BVDIV/BVMOD into unsigned variety
+ASTNode BeevMgr::TranslateSignedDivMod(const ASTNode& in)
+{
+ if (!(SBVREM == in.GetKind() || SBVDIV == in.GetKind()))
+ {
+ FatalError("TranslateSignedDivMod: input must be signed DIV/MOD\n", in);
}
- //Constructing Symbolic variable corresponding to 'processedTerm'
- ASTNode CurrentSymbol;
- ASTNodeMap::iterator it1;
- // First, check if read index is constant and it has a constant value in the substitution map.
- if(CheckSubstitutionMap(processedTerm,CurrentSymbol)) {
- _arrayread_symbol[processedTerm] = CurrentSymbol;
+
+ ASTNode dividend = in[0];
+ ASTNode divisor = in[1];
+ unsigned len = in.GetValueWidth();
+
+ ASTNode hi1 = CreateBVConst(32, len - 1);
+ ASTNode one = CreateOneConst(1);
+ ASTNode zero = CreateZeroConst(1);
+ // create the condition for the dividend
+ ASTNode cond_dividend = CreateNode(EQ, one, CreateTerm(BVEXTRACT, 1, dividend, hi1, hi1));
+ // create the condition for the divisor
+ ASTNode cond_divisor = CreateNode(EQ, one, CreateTerm(BVEXTRACT, 1, divisor, hi1, hi1));
+
+ if (SBVREM == in.GetKind())
+ {
+ //if(TopBit(dividend)==1)
+ //
+ //then -BVMOD(-dividend,abs(divisor))
+ //
+ //else BVMOD(dividend,abs(divisor))
+
+ //create the condition and conditional for the divisor
+ ASTNode pos_divisor = CreateTerm(ITE, len, cond_divisor, CreateTerm(BVUMINUS, len, divisor), divisor);
+
+ //create the modulus term for each case
+ ASTNode modnode = CreateTerm(BVMOD, len, dividend, pos_divisor);
+ ASTNode minus_modnode = CreateTerm(BVMOD, len, CreateTerm(BVUMINUS, len, dividend), pos_divisor);
+ minus_modnode = CreateTerm(BVUMINUS, len, minus_modnode);
+
+ //put everything together, simplify, and return
+ ASTNode n = CreateTerm(ITE, len, cond_dividend, minus_modnode, modnode);
+ return SimplifyTerm_TopLevel(n);
}
- // Check if it already has an abstract variable.
- else if((it1 = _arrayread_symbol.find(processedTerm)) != _arrayread_symbol.end()) {
- CurrentSymbol = it1->second;
+
+ if (SBVMOD == in.GetKind())
+ {
+ // (let (?msb_s (extract[|m-1|:|m-1|] s))
+ // (let (?msb_t (extract[|m-1|:|m-1|] t))
+ // (ite (and (= ?msb_s bit0) (= ?msb_t bit0))
+ // (bvurem s t)
+ // (ite (and (= ?msb_s bit1) (= ?msb_t bit0))
+ // (bvadd (bvneg (bvurem (bvneg s) t)) t)
+ // (ite (and (= ?msb_s bit0) (= ?msb_t bit1))
+ // (bvadd (bvurem s (bvneg t)) t)
+ // (bvneg (bvurem (bvneg s) (bvneg t)))))))
+ ASTNode & s = dividend;
+ ASTNode & t = divisor;
+ ASTNode & msb_s = cond_dividend;
+ ASTNode & msb_t = cond_divisor;
+
+ ASTNode isSPos = CreateNode(EQ, msb_s, zero); // (= ?msb_s bit0)
+ ASTNode isSNeg = CreateNode(EQ, msb_s, one); // (= ?msb_s bit1)
+ ASTNode isTPos = CreateNode(EQ, msb_t, zero); // (= ?msb_t bit0)
+ ASTNode isTNeg = CreateNode(EQ, msb_t, one); // (= ?msb_t bit1)
+
+ ASTNode negS = CreateTerm(BVUMINUS, len, s); // (bvneg s)
+ ASTNode negT = CreateTerm(BVUMINUS, len, t); // (bvneg s)
+
+ // (bvneg (bvurem (bvneg s) (bvneg t)))
+ ASTNode branch4 = CreateTerm(BVUMINUS, len, CreateTerm(BVMOD, len, negS, negT));
+ // (bvadd (bvurem s (bvneg t)) t)
+ ASTNode branch3 = CreateTerm(BVPLUS, len, CreateTerm(BVMOD, len, s, negT), t);
+ // (bvadd (bvneg (bvurem (bvneg s) t)) t)
+ ASTNode branch2 = CreateTerm(BVPLUS, len, CreateTerm(BVUMINUS, len, CreateTerm(BVMOD, len, negS, t)), t);
+ // (bvurem s t)
+ ASTNode branch1 = CreateTerm(BVMOD, len, s, t);
+
+ ASTNode ite3 = CreateTerm(ITE, len, CreateNode(AND, isSPos, isTNeg), branch3, branch4);
+ ASTNode ite2 = CreateTerm(ITE, len, CreateNode(AND, isSNeg, isTPos), branch2, ite3);
+ ASTNode ite1 = CreateTerm(ITE, len, CreateNode(AND, isSPos, isTPos), branch1, ite2);
+
+ return SimplifyTerm_TopLevel(ite1);
}
- else {
- // Make up a new abstract variable.
- // FIXME: Make this into a method (there already may BE a method) and
- // get rid of the fixed-length buffer!
- //build symbolic name corresponding to array read. The symbolic
- //name has 2 components: stringname, and a count
- const char * b = arrName.GetName();
- std::string c(b);
- char d[32];
- sprintf(d,"%d",_symbol_count++);
- std::string ccc(d);
- c += "array_" + ccc;
-
- CurrentSymbol = CreateSymbol(c.c_str());
- CurrentSymbol.SetValueWidth(processedTerm.GetValueWidth());
- CurrentSymbol.SetIndexWidth(processedTerm.GetIndexWidth());
- _arrayread_symbol[processedTerm] = CurrentSymbol;
+
+ //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)
+ ASTNode divnode = CreateTerm(BVDIV, len, dividend, divisor);
+
+ ASTNode cond1 = CreateNode(AND, CreateNode(EQ, zero, CreateTerm(BVEXTRACT, 1, dividend, hi1, hi1)), CreateNode(EQ, one, CreateTerm(BVEXTRACT, 1,
+ divisor, hi1, hi1)));
+ ASTNode minus_divnode1 = CreateTerm(BVDIV, len, dividend, CreateTerm(BVUMINUS, len, divisor));
+ minus_divnode1 = CreateTerm(BVUMINUS, len, minus_divnode1);
+
+ ASTNode cond2 = CreateNode(AND, CreateNode(EQ, one, CreateTerm(BVEXTRACT, 1, dividend, hi1, hi1)), CreateNode(EQ, zero, CreateTerm(BVEXTRACT, 1,
+ divisor, hi1, hi1)));
+ ASTNode minus_divnode2 = CreateTerm(BVDIV, len, CreateTerm(BVUMINUS, len, dividend), divisor);
+ minus_divnode2 = CreateTerm(BVUMINUS, len, minus_divnode2);
+
+ ASTNode cond3 = CreateNode(AND, CreateNode(EQ, one, CreateTerm(BVEXTRACT, 1, dividend, hi1, hi1)), CreateNode(EQ, one, CreateTerm(BVEXTRACT, 1,
+ divisor, hi1, hi1)));
+ ASTNode minus_divnode3 = CreateTerm(BVDIV, len, CreateTerm(BVUMINUS, len, dividend), CreateTerm(BVUMINUS, len, divisor));
+ ASTNode n = CreateTerm(ITE, len, cond1, minus_divnode1, CreateTerm(ITE, len, cond2, minus_divnode2, CreateTerm(ITE, len, cond3, minus_divnode3,
+ divnode)));
+ return SimplifyTerm_TopLevel(n);
+}//end of TranslateSignedDivMod()
+
+/*
+ //Translates signed BVDIV/BVMOD into unsigned variety
+ ASTNode BeevMgr::TranslateSignedDivMod(const ASTNode& in) {
+ if(!(SBVREM == in.GetKind() || SBVDIV == in.GetKind())) {
+ FatalError("TranslateSignedDivMod: input must be signed DIV/MOD\n",in);
+ }
+
+ ASTNode dividend = in[0];
+ ASTNode divisor = in[1];
+ unsigned len = in.GetValueWidth();
+ if(SBVMOD == in.GetKind()) {
+ //if(TopBit(dividend)==1)
+ //
+ //then -BVMOD(-dividend,abs(divisor))
+ //
+ //else BVMOD(dividend,abs(divisor))
+
+ //create the condition for the dividend
+ ASTNode hi1 = CreateBVConst(32,len-1);
+ ASTNode one = CreateOneConst(1);
+ ASTNode cond = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1));
+
+ //create the condition and conditional for the divisor
+ ASTNode cond_divisor = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1));
+ ASTNode pos_divisor = CreateTerm(ITE,len,cond_divisor,CreateTerm(BVUMINUS,len,divisor),divisor);
+
+ //create the modulus term for each case
+ ASTNode modnode = CreateTerm(BVMOD,len,dividend,pos_divisor);
+ ASTNode minus_modnode = CreateTerm(BVMOD,len,CreateTerm(BVUMINUS,len,dividend),pos_divisor);
+ minus_modnode = CreateTerm(BVUMINUS,len,minus_modnode);
+
+ //put everything together, simplify, and return
+ ASTNode n = CreateTerm(ITE,len,cond,minus_modnode,modnode);
+ return SimplifyTerm_TopLevel(n);
+ }
+
+ //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)
+ ASTNode hi1 = CreateBVConst(32,len-1);
+ ASTNode zero = CreateZeroConst(1);
+ ASTNode one = CreateOneConst(1);
+ ASTNode divnode = CreateTerm(BVDIV, len, dividend, divisor);
+
+ ASTNode cond1 = CreateNode(AND,
+ CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+ CreateNode(EQ,one, CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+ ASTNode minus_divnode1 = CreateTerm(BVDIV,len,
+ dividend,
+ CreateTerm(BVUMINUS,len,divisor));
+ minus_divnode1 = CreateTerm(BVUMINUS,len,minus_divnode1);
+
+ ASTNode cond2 = CreateNode(AND,
+ CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+ CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+ ASTNode minus_divnode2 = CreateTerm(BVDIV,len,
+ CreateTerm(BVUMINUS,len,dividend),
+ divisor);
+ minus_divnode2 = CreateTerm(BVUMINUS,len,minus_divnode2);
+
+ ASTNode cond3 = CreateNode(AND,
+ CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+ CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+ ASTNode minus_divnode3 = CreateTerm(BVDIV,len,
+ CreateTerm(BVUMINUS,len,dividend),
+ CreateTerm(BVUMINUS,len,divisor));
+ ASTNode n = CreateTerm(ITE,len,
+ cond1,
+ minus_divnode1,
+ CreateTerm(ITE,len,
+ cond2,
+ minus_divnode2,
+ CreateTerm(ITE,len,
+ cond3,
+ minus_divnode3,
+ divnode)));
+ return SimplifyTerm_TopLevel(n);
+ }//end of TranslateSignedDivMod()
+ */
+
+ASTNode BeevMgr::TransformFormula(const ASTNode& form)
+{
+ ASTNode result;
+
+ ASTNode simpleForm = form;
+ Kind k = simpleForm.GetKind();
+ if (!(is_Form_kind(k) && BOOLEAN_TYPE == simpleForm.GetType()))
+ {
+ //FIXME: "You have inputted a NON-formula"?
+ FatalError("TransformFormula: You have input a NON-formula", simpleForm);
}
-
- //list of array-read indices corresponding to arrName, seen while
- //traversing the AST tree. we need this list to construct the ITEs
- // Dill: we hope to make this irrelevant. Harmless for now.
- ASTVec readIndices = _arrayname_readindices[arrName];
-
- //construct the ITE structure for this array-read
- ASTNode ite = CurrentSymbol;
- _introduced_symbols.insert(CurrentSymbol);
- BVTypeCheck(ite);
-
- if(arrayread_refinement) {
- // ite is really a variable here; it is an ite in the
- // else-branch
- result = ite;
+
+ ASTNodeMap::iterator iter;
+ if ((iter = TransformMap.find(simpleForm)) != TransformMap.end())
+ return iter->second;
+
+ switch (k)
+ {
+ case TRUE:
+ case FALSE:
+ {
+ result = simpleForm;
+ break;
+ }
+ case NOT:
+ {
+ ASTVec c;
+ c.push_back(TransformFormula(simpleForm[0]));
+ result = CreateNode(NOT, c);
+ break;
+ }
+ case BVLT:
+ case BVLE:
+ case BVGT:
+ case BVGE:
+ case BVSLT:
+ case BVSLE:
+ case BVSGT:
+ case BVSGE:
+ case NEQ:
+ {
+ ASTVec c;
+ c.push_back(TransformTerm(simpleForm[0]));
+ c.push_back(TransformTerm(simpleForm[1]));
+ result = CreateNode(k, c);
+ break;
+ }
+ case EQ:
+ {
+ ASTNode term1 = TransformTerm(simpleForm[0]);
+ ASTNode term2 = TransformTerm(simpleForm[1]);
+ result = CreateSimplifiedEQ(term1, term2);
+ break;
+ }
+ case AND:
+ case OR:
+ case NAND:
+ case NOR:
+ case IFF:
+ case XOR:
+ case ITE:
+ case IMPLIES:
+ {
+ ASTVec vec;
+ ASTNode o;
+ for (ASTVec::const_iterator it = simpleForm.begin(), itend = simpleForm.end(); it != itend; it++)
+ {
+ o = TransformFormula(*it);
+ vec.push_back(o);
+ }
+
+ result = CreateNode(k, vec);
+ break;
+ }
+ default:
+ if (k == SYMBOL && BOOLEAN_TYPE == simpleForm.GetType())
+ result = simpleForm;
+ else
+ {
+ cerr << "The input is: " << simpleForm << endl;
+ cerr << "The valuewidth of input is : " << simpleForm.GetValueWidth() << endl;
+ FatalError("TransformFormula: Illegal kind: ", ASTUndefined, k);
+ }
+ break;
}
- else {
- // Full Seshia transform if we're not doing read refinement.
- //do not loop if the current readIndex is a BVCONST
- // if(BVCONST == term[1].GetKind() && !SeenNonConstReadIndex && optimize) {
- // result = ite;
- // }
- // else {
- //else part: SET the SeenNonConstReadIndex var, and do the hard work
- //SeenNonConstReadIndex = true;
- ASTVec::reverse_iterator it2=readIndices.rbegin();
- ASTVec::reverse_iterator it2end=readIndices.rend();
- for(;it2!=it2end;it2++) {
- ASTNode cond = CreateSimplifiedEQ(readIndex,*it2);
- if(ASTFalse == cond)
- continue;
-
- ASTNode arrRead = CreateTerm(READ,width,arrName,*it2);
- //Good idea to TypeCheck internally constructed nodes
- BVTypeCheck(arrRead);
-
- ASTNode arrayreadSymbol = _arrayread_symbol[arrRead];
- if(arrayreadSymbol.IsNull())
- FatalError("TransformArray:symbolic variable for processedTerm, p,"
- "does not exist:p = ",arrRead);
- ite = CreateSimplifiedTermITE(cond,arrayreadSymbol,ite);
- }
- result = ite;
- //}
+ //BVTypeCheck(result);
+ TransformMap[simpleForm] = result;
+ return result;
+} //End of TransformFormula
+
+ASTNode BeevMgr::TransformTerm(const ASTNode& inputterm)
+{
+ ASTNode result;
+ ASTNode term = inputterm;
+
+ Kind k = term.GetKind();
+ if (!is_Term_kind(k))
+ FatalError("TransformTerm: Illegal kind: You have input a nonterm:", inputterm, k);
+ ASTNodeMap::iterator iter;
+ if ((iter = TransformMap.find(term)) != TransformMap.end())
+ return iter->second;
+ switch (k)
+ {
+ case SYMBOL:
+ {
+ // ASTNodeMap::iterator itsym;
+ // if((itsym = CounterExampleMap.find(term)) != CounterExampleMap.end())
+ // result = itsym->second;
+ // else
+ result = term;
+ break;
+ }
+ case BVCONST:
+ result = term;
+ break;
+ case WRITE:
+ FatalError("TransformTerm: this kind is not supported", term);
+ break;
+ case READ:
+ result = TransformArray(term);
+ break;
+ case ITE:
+ {
+ ASTNode cond = term[0];
+ ASTNode thn = term[1];
+ ASTNode els = term[2];
+ cond = TransformFormula(cond);
+ thn = TransformTerm(thn);
+ els = TransformTerm(els);
+ //result = CreateTerm(ITE,term.GetValueWidth(),cond,thn,els);
+ result = CreateSimplifiedTermITE(cond, thn, els);
+ result.SetIndexWidth(term.GetIndexWidth());
+ break;
+ }
+ default:
+ {
+ ASTVec c = term.GetChildren();
+ ASTVec::iterator it = c.begin();
+ ASTVec::iterator itend = c.end();
+ unsigned width = term.GetValueWidth();
+ unsigned indexwidth = term.GetIndexWidth();
+ ASTVec o;
+ for (; it != itend; it++)
+ {
+ o.push_back(TransformTerm(*it));
+ }
+
+ result = CreateTerm(k, width, o);
+ result.SetIndexWidth(indexwidth);
+
+ if (SBVDIV == result.GetKind() || SBVREM == result.GetKind() || SBVMOD == result.GetKind())
+ {
+ result = TranslateSignedDivMod(result);
+ }
+ break;
+ }
}
-
- _arrayname_readindices[arrName].push_back(readIndex);
- //save the ite corresponding to 'processedTerm'
- _arrayread_ite[processedTerm] = result;
- break;
- } //end of READ over a SYMBOL
- case WRITE:{
- /* The input to this case is: READ((WRITE A i val) j)
- *
- * The output of this case is: ITE( (= i j) val (READ A i))
- */
-
- /* 1. arrName or term[0] is infact a WRITE(A,i,val) expression
- *
- * 2. term[1] is the read-index j
- *
- * 3. arrName[0] is the new arrName i.e. A. A can be either a
- SYMBOL or a nested WRITE. no other possibility
- *
- * 4. arrName[1] is the WRITE index i.e. i
- *
- * 5. arrName[2] is the WRITE value i.e. val (val can inturn
- * be an array read)
- */
- ASTNode readIndex = TransformTerm(term[1]);
- ASTNode writeIndex = TransformTerm(arrName[1]);
- ASTNode writeVal = TransformTerm(arrName[2]);
-
- if(!(SYMBOL == arrName[0].GetKind() ||
- WRITE == arrName[0].GetKind()))
- FatalError("TransformArray: An array write is being attempted on a non-array:",term);
- if(ARRAY_TYPE != arrName[0].GetType())
- FatalError("TransformArray: An array write is being attempted on a non-array:",term);
-
- ASTNode cond = CreateSimplifiedEQ(writeIndex,readIndex);
- //TypeCheck internally created node
- BVTypeCheck(cond);
- ASTNode readTerm = CreateTerm(READ,width,arrName[0],readIndex);
- //TypeCheck internally created node
- BVTypeCheck(readTerm);
- ASTNode readPushedIn = TransformArray(readTerm);
- //TypeCheck internally created node
- BVTypeCheck(readPushedIn);
- //result = CreateTerm(ITE, arrName[0].GetValueWidth(),cond,writeVal,readPushedIn);
- result = CreateSimplifiedTermITE(cond,writeVal,readPushedIn);
-
- //Good idea to typecheck terms created inside the system
- BVTypeCheck(result);
- break;
- } //end of READ over a WRITE
- case ITE: {
- /* READ((ITE cond thn els) j)
- *
- * is transformed into
- *
- * (ITE cond (READ thn j) (READ els j))
- */
-
- //(ITE cond thn els)
- ASTNode term0 = term[0];
- //READINDEX j
- ASTNode j = TransformTerm(term[1]);
-
- ASTNode cond = term0[0];
- //first array
- ASTNode t01 = term0[1];
- //second array
- ASTNode t02 = term0[2];
-
- cond = TransformFormula(cond);
- ASTNode thn = TransformTerm(t01);
- ASTNode els = TransformTerm(t02);
-
- if(!(t01.GetValueWidth() == t02.GetValueWidth() &&
- t01.GetValueWidth() == thn.GetValueWidth() &&
- t01.GetValueWidth() == els.GetValueWidth()))
- FatalError("TransformArray: length of THENbranch != length of ELSEbranch in the term t = \n",term);
-
- if(!(t01.GetIndexWidth() == t02.GetIndexWidth() &&
- t01.GetIndexWidth() == thn.GetIndexWidth() &&
- t01.GetIndexWidth() == els.GetIndexWidth()))
- FatalError("TransformArray: length of THENbranch != length of ELSEbranch in the term t = \n",term);
-
- //(READ thn j)
- ASTNode thnRead = CreateTerm(READ,width,thn,j);
- BVTypeCheck(thnRead);
- thnRead = TransformArray(thnRead);
-
- //(READ els j)
- ASTNode elsRead = CreateTerm(READ,width,els,j);
- BVTypeCheck(elsRead);
- elsRead = TransformArray(elsRead);
-
- //(ITE cond (READ thn j) (READ els j))
- result = CreateSimplifiedTermITE(cond,thnRead,elsRead);
- BVTypeCheck(result);
- break;
- }
- default:
- FatalError("TransformArray: The READ is NOT over SYMBOL/WRITE/ITE",term);
- break;
- }
- break;
- } //end of READ switch
- default:
- FatalError("TransformArray: input term is of wrong kind: ",ASTUndefined);
- break;
- }
-
- TransformMap[term] = result;
- return result;
- } //end of TransformArray()
+
+ TransformMap[term] = result;
+ if (term.GetValueWidth() != result.GetValueWidth())
+ FatalError("TransformTerm: result and input terms are of different length", result);
+ if (term.GetIndexWidth() != result.GetIndexWidth())
+ {
+ cerr << "TransformTerm: input term is : " << term << endl;
+ FatalError("TransformTerm: result and input terms have different index length", result);
+ }
+ return result;
+} //End of TransformTerm
+
+/* This function transforms Array Reads, Read over Writes, Read over
+ * ITEs into flattened form.
+ *
+ * Transform1: Suppose there are two array reads in the input
+ * Read(A,i) and Read(A,j) over the same array. Then Read(A,i) is
+ * replaced with a symbolic constant, say v1, and Read(A,j) is
+ * replaced with the following ITE:
+ *
+ * ITE(i=j,v1,v2)
+ *
+ * Transform2:
+ *
+ * Transform3:
+ */
+ASTNode BeevMgr::TransformArray(const ASTNode& term)
+{
+ ASTNode result = term;
+
+ unsigned int width = term.GetValueWidth();
+ Kind k = term.GetKind();
+ if (!is_Term_kind(k))
+ FatalError("TransformArray: Illegal kind: You have input a nonterm:", ASTUndefined, k);
+ ASTNodeMap::iterator iter;
+ if ((iter = TransformMap.find(term)) != TransformMap.end())
+ return iter->second;
+
+ switch (k)
+ {
+ //'term' is of the form READ(arrName, readIndex)
+ case READ:
+ {
+ ASTNode arrName = term[0];
+ switch (arrName.GetKind())
+ {
+ case SYMBOL:
+ {
+ /* input is of the form: READ(A, readIndex)
+ *
+ * output is of the from: A1, if this is the first READ over A
+ *
+ * ITE(previous_readIndex=readIndex,A1,A2)
+ *
+ * .....
+ */
+
+ // Recursively transform read index, which may also contain reads.
+ ASTNode readIndex = TransformTerm(term[1]);
+ ASTNode processedTerm = CreateTerm(READ, width, arrName, readIndex);
+
+ //check if the 'processedTerm' has a corresponding ITE construct
+ //already. if so, return it. else continue processing.
+ ASTNodeMap::iterator it;
+ if ((it = _arrayread_ite.find(processedTerm)) != _arrayread_ite.end())
+ {
+ result = it->second;
+ break;
+ }
+ //Constructing Symbolic variable corresponding to 'processedTerm'
+ ASTNode CurrentSymbol;
+ ASTNodeMap::iterator it1;
+ // First, check if read index is constant and it has a constant value in the substitution map.
+ if (CheckSubstitutionMap(processedTerm, CurrentSymbol))
+ {
+ _arrayread_symbol[processedTerm] = CurrentSymbol;
+ }
+ // Check if it already has an abstract variable.
+ else if ((it1 = _arrayread_symbol.find(processedTerm)) != _arrayread_symbol.end())
+ {
+ CurrentSymbol = it1->second;
+ }
+ else
+ {
+ // Make up a new abstract variable.
+ // FIXME: Make this into a method (there already may BE a method) and
+ // get rid of the fixed-length buffer!
+ //build symbolic name corresponding to array read. The symbolic
+ //name has 2 components: stringname, and a count
+ const char * b = arrName.GetName();
+ std::string c(b);
+ char d[32];
+ sprintf(d, "%d", _symbol_count++);
+ std::string ccc(d);
+ c += "array_" + ccc;
+
+ CurrentSymbol = CreateSymbol(c.c_str());
+ CurrentSymbol.SetValueWidth(processedTerm.GetValueWidth());
+ CurrentSymbol.SetIndexWidth(processedTerm.GetIndexWidth());
+ _arrayread_symbol[processedTerm] = CurrentSymbol;
+ }
+
+ //list of array-read indices corresponding to arrName, seen while
+ //traversing the AST tree. we need this list to construct the ITEs
+ // Dill: we hope to make this irrelevant. Harmless for now.
+ ASTVec readIndices = _arrayname_readindices[arrName];
+
+ //construct the ITE structure for this array-read
+ ASTNode ite = CurrentSymbol;
+ _introduced_symbols.insert(CurrentSymbol);
+ BVTypeCheck(ite);
+
+ if (arrayread_refinement)
+ {
+ // ite is really a variable here; it is an ite in the
+ // else-branch
+ result = ite;
+ }
+ else
+ {
+ // Full Seshia transform if we're not doing read refinement.
+ //do not loop if the current readIndex is a BVCONST
+ // if(BVCONST == term[1].GetKind() && !SeenNonConstReadIndex && optimize) {
+ // result = ite;
+ // }
+ // else {
+ //else part: SET the SeenNonConstReadIndex var, and do the hard work
+ //SeenNonConstReadIndex = true;
+ ASTVec::reverse_iterator it2 = readIndices.rbegin();
+ ASTVec::reverse_iterator it2end = readIndices.rend();
+ for (; it2 != it2end; it2++)
+ {
+ ASTNode cond = CreateSimplifiedEQ(readIndex, *it2);
+ if (ASTFalse == cond)
+ continue;
+
+ ASTNode arrRead = CreateTerm(READ, width, arrName, *it2);
+ //Good idea to TypeCheck internally constructed nodes
+ BVTypeCheck(arrRead);
+
+ ASTNode arrayreadSymbol = _arrayread_symbol[arrRead];
+ if (arrayreadSymbol.IsNull())
+ FatalError("TransformArray:symbolic variable for processedTerm, p,"
+ "does not exist:p = ", arrRead);
+ ite = CreateSimplifiedTermITE(cond, arrayreadSymbol, ite);
+ }
+ result = ite;
+ //}
+ }
+
+ _arrayname_readindices[arrName].push_back(readIndex);
+ //save the ite corresponding to 'processedTerm'
+ _arrayread_ite[processedTerm] = result;
+ break;
+ } //end of READ over a SYMBOL
+ case WRITE:
+ {
+ /* The input to this case is: READ((WRITE A i val) j)
+ *
+ * The output of this case is: ITE( (= i j) val (READ A i))
+ */
+
+ /* 1. arrName or term[0] is infact a WRITE(A,i,val) expression
+ *
+ * 2. term[1] is the read-index j
+ *
+ * 3. arrName[0] is the new arrName i.e. A. A can be either a
+ SYMBOL or a nested WRITE. no other possibility
+ *
+ * 4. arrName[1] is the WRITE index i.e. i
+ *
+ * 5. arrName[2] is the WRITE value i.e. val (val can inturn
+ * be an array read)
+ */
+ ASTNode readIndex = TransformTerm(term[1]);
+ ASTNode writeIndex = TransformTerm(arrName[1]);
+ ASTNode writeVal = TransformTerm(arrName[2]);
+
+ if (!(SYMBOL == arrName[0].GetKind() || WRITE == arrName[0].GetKind()))
+ FatalError("TransformArray: An array write is being attempted on a non-array:", term);
+ if (ARRAY_TYPE != arrName[0].GetType())
+ FatalError("TransformArray: An array write is being attempted on a non-array:", term);
+
+ ASTNode cond = CreateSimplifiedEQ(writeIndex, readIndex);
+ //TypeCheck internally created node
+ BVTypeCheck(cond);
+ ASTNode readTerm = CreateTerm(READ, width, arrName[0], readIndex);
+ //TypeCheck internally created node
+ BVTypeCheck(readTerm);
+ ASTNode readPushedIn = TransformArray(readTerm);
+ //TypeCheck internally created node
+ BVTypeCheck(readPushedIn);
+ //result = CreateTerm(ITE, arrName[0].GetValueWidth(),cond,writeVal,readPushedIn);
+ result = CreateSimplifiedTermITE(cond, writeVal, readPushedIn);
+
+ //Good idea to typecheck terms created inside the system
+ BVTypeCheck(result);
+ break;
+ } //end of READ over a WRITE
+ case ITE:
+ {
+ /* READ((ITE cond thn els) j)
+ *
+ * is transformed into
+ *
+ * (ITE cond (READ thn j) (READ els j))
+ */
+
+ //(ITE cond thn els)
+ ASTNode term0 = term[0];
+ //READINDEX j
+ ASTNode j = TransformTerm(term[1]);
+
+ ASTNode cond = term0[0];
+ //first array
+ ASTNode t01 = term0[1];
+ //second array
+ ASTNode t02 = term0[2];
+
+ cond = TransformFormula(cond);
+ ASTNode thn = TransformTerm(t01);
+ ASTNode els = TransformTerm(t02);
+
+ if (!(t01.GetValueWidth() == t02.GetValueWidth() && t01.GetValueWidth() == thn.GetValueWidth() && t01.GetValueWidth()
+ == els.GetValueWidth()))
+ FatalError("TransformArray: length of THENbranch != length of ELSEbranch in the term t = \n", term);
+
+ if (!(t01.GetIndexWidth() == t02.GetIndexWidth() && t01.GetIndexWidth() == thn.GetIndexWidth() && t01.GetIndexWidth()
+ == els.GetIndexWidth()))
+ FatalError("TransformArray: length of THENbranch != length of ELSEbranch in the term t = \n", term);
+
+ //(READ thn j)
+ ASTNode thnRead = CreateTerm(READ, width, thn, j);
+ BVTypeCheck(thnRead);
+ thnRead = TransformArray(thnRead);
+
+ //(READ els j)
+ ASTNode elsRead = CreateTerm(READ, width, els, j);
+ BVTypeCheck(elsRead);
+ elsRead = TransformArray(elsRead);
+
+ //(ITE cond (READ thn j) (READ els j))
+ result = CreateSimplifiedTermITE(cond, thnRead, elsRead);
+ BVTypeCheck(result);
+ break;
+ }
+ default:
+ FatalError("TransformArray: The READ is NOT over SYMBOL/WRITE/ITE", term);
+ break;
+ }
+ break;
+ } //end of READ switch
+ default:
+ FatalError("TransformArray: input term is of wrong kind: ", ASTUndefined);
+ break;
+ }
+
+ TransformMap[term] = result;
+ return result;
+} //end of TransformArray()
} //end of namespace BEEV
int main()
{
- BeevMgr * bm = new BeevMgr();
- ASTNode s1 = bm->CreateSymbol("foo");
- s1 = bm->CreateSymbol("foo1");
- s1 = bm->CreateSymbol("foo2");
- ASTNode s2 = bm->CreateSymbol("bar");
- cout << "s1" << s1 << endl;
- cout << "s2" << s2 << endl;
+ BeevMgr * bm = new BeevMgr();
+ ASTNode s1 = bm->CreateSymbol("foo");
+ s1 = bm->CreateSymbol("foo1");
+ s1 = bm->CreateSymbol("foo2");
+ ASTNode s2 = bm->CreateSymbol("bar");
+ cout << "s1" << s1 << endl;
+ cout << "s2" << s2 << endl;
- ASTNode b1 = bm->CreateBVConst(5,12);
- ASTNode b2 = bm->CreateBVConst(6,36);
- cout << "b1: " << b1 << endl;
- cout << "b2: " << b2 << endl;
+ ASTNode b1 = bm->CreateBVConst(5, 12);
+ ASTNode b2 = bm->CreateBVConst(6, 36);
+ cout << "b1: " << b1 << endl;
+ cout << "b2: " << b2 << endl;
- ASTNode a1 = bm->CreateNode(EQ, s1, s2);
- ASTNode a2 = bm->CreateNode(AND, s1, s2);
- a1 = bm->CreateNode(OR, s1, s2);
- ASTNode a3 = bm->CreateNode(IMPLIES, a1, a2);
- ASTNode a4 = bm->CreateNode(IMPLIES, s1, a2);
- cout << "a3" << a3 << endl;
- cout << "a4" << a4 << endl;
- return 0;
+ ASTNode a1 = bm->CreateNode(EQ, s1, s2);
+ ASTNode a2 = bm->CreateNode(AND, s1, s2);
+ a1 = bm->CreateNode(OR, s1, s2);
+ ASTNode a3 = bm->CreateNode(IMPLIES, a1, a2);
+ ASTNode a4 = bm->CreateNode(IMPLIES, s1, a2);
+ cout << "a3" << a3 << endl;
+ cout << "a4" << a4 << endl;
+ return 0;
}
int main()
{
- const int size = 32;
-
- BeevMgr *bm = new BeevMgr();
- ASTNode s1 = bm->CreateSymbol("x");
- s1.SetValueWidth(size);
- cout << "s1" << s1 << endl;
- ASTNode s2 = bm->CreateSymbol("y");
- s2.SetValueWidth(size);
- cout << "s2" << s2 << endl;
- ASTNode s3 = bm->CreateSymbol("z");
- s3.SetValueWidth(size);
- cout << "s3" << s3 << endl;
-
- ASTNode c1 = bm->CreateBVConst(size,0);
- cout << "c1" << c1 << endl;
- ASTVec bbc1 = bm->BBTerm(c1);
- cout << "bitblasted c1 " << endl;
- LispPrintVec(cout, bbc1, 0);
- cout << endl;
- bm->AlreadyPrintedSet.clear();
-
- ASTNode c2 = bm->CreateBVConst(size,1);
- c2.SetValueWidth(size);
- cout << "c2" << c2 << endl;
- ASTVec bbc2 = bm->BBTerm(c2);
- cout << "bitblasted c2 " << endl;
- LispPrintVec(cout, bbc2, 0);
- cout << endl;
- bm->AlreadyPrintedSet.clear();
-
- ASTNode c3 = bm->CreateBVConst(size, 0xFFFFFFFF);
- c3.SetValueWidth(size);
- cout << "c3" << c3 << endl;
- ASTVec bbc3 = bm->BBTerm(c3);
- cout << "bitblasted c3 " << endl;
- LispPrintVec(cout, bbc3, 0);
- cout << endl;
- bm->AlreadyPrintedSet.clear();
-
- ASTNode c4 = bm->CreateBVConst(size, 0xAAAAAAAA);
- c4.SetValueWidth(size);
- cout << "c4" << c4 << endl;
- ASTVec bbc4 = bm->BBTerm(c4);
- cout << "bitblasted c4 " << endl;
- LispPrintVec(cout, bbc4, 0);
- cout << endl;
- bm->AlreadyPrintedSet.clear();
-
-// ASTNode b1 = bm->CreateBVConst(12);
-// ASTNode b2 = bm->CreateBVConst(36);
-// cout << "b1: " << b1 << endl;
-// cout << "b2: " << b2 << endl;
-
- ASTNode a1 = bm->CreateNode(BVPLUS, s1, s2);
- a1.SetValueWidth(size);
-
- ASTVec& bba1 = bm->BBTerm(a1);
- cout << "bitblasted a1 " << endl;
- LispPrintVec(cout, bba1, 0);
- cout << endl;
- bm->AlreadyPrintedSet.clear();
-
- ASTNode a2 = bm->CreateNode(BVPLUS, s1, s2, s3);
- a1.SetValueWidth(2);
-
- ASTVec& bba2 = bm->BBTerm(a2);
- cout << "bitblasted a2 " << endl;
- LispPrintVec(cout, bba2, 0);
- cout << endl;
- bm->AlreadyPrintedSet.clear();
-
- ASTNode a3 = bm->CreateNode(BVXOR, s1, s2);
- a3.SetValueWidth(2);
-
- ASTVec& bba3 = bm->BBTerm(a3);
- cout << "bitblasted a3 " << endl;
- LispPrintVec(cout, bba3, 0);
- cout << endl;
- bm->AlreadyPrintedSet.clear();
-
- ASTNode a4 = bm->CreateNode(EQ, s1, s2);
- ASTNode bba4 = bm->BBForm(a4);
- cout << "bitblasted a4 " << endl << bba4 << endl;
-
- ASTNode a5 = bm->CreateNode(BVLE, s1, s2);
- ASTNode bba5 = bm->BBForm(a5);
- cout << "bitblasted a5 " << endl << bba5 << endl;
-
- return 0;
+ const int size = 32;
+
+ BeevMgr *bm = new BeevMgr();
+ ASTNode s1 = bm->CreateSymbol("x");
+ s1.SetValueWidth(size);
+ cout << "s1" << s1 << endl;
+ ASTNode s2 = bm->CreateSymbol("y");
+ s2.SetValueWidth(size);
+ cout << "s2" << s2 << endl;
+ ASTNode s3 = bm->CreateSymbol("z");
+ s3.SetValueWidth(size);
+ cout << "s3" << s3 << endl;
+
+ ASTNode c1 = bm->CreateBVConst(size, 0);
+ cout << "c1" << c1 << endl;
+ ASTVec bbc1 = bm->BBTerm(c1);
+ cout << "bitblasted c1 " << endl;
+ LispPrintVec(cout, bbc1, 0);
+ cout << endl;
+ bm->AlreadyPrintedSet.clear();
+
+ ASTNode c2 = bm->CreateBVConst(size, 1);
+ c2.SetValueWidth(size);
+ cout << "c2" << c2 << endl;
+ ASTVec bbc2 = bm->BBTerm(c2);
+ cout << "bitblasted c2 " << endl;
+ LispPrintVec(cout, bbc2, 0);
+ cout << endl;
+ bm->AlreadyPrintedSet.clear();
+
+ ASTNode c3 = bm->CreateBVConst(size, 0xFFFFFFFF);
+ c3.SetValueWidth(size);
+ cout << "c3" << c3 << endl;
+ ASTVec bbc3 = bm->BBTerm(c3);
+ cout << "bitblasted c3 " << endl;
+ LispPrintVec(cout, bbc3, 0);
+ cout << endl;
+ bm->AlreadyPrintedSet.clear();
+
+ ASTNode c4 = bm->CreateBVConst(size, 0xAAAAAAAA);
+ c4.SetValueWidth(size);
+ cout << "c4" << c4 << endl;
+ ASTVec bbc4 = bm->BBTerm(c4);
+ cout << "bitblasted c4 " << endl;
+ LispPrintVec(cout, bbc4, 0);
+ cout << endl;
+ bm->AlreadyPrintedSet.clear();
+
+ // ASTNode b1 = bm->CreateBVConst(12);
+ // ASTNode b2 = bm->CreateBVConst(36);
+ // cout << "b1: " << b1 << endl;
+ // cout << "b2: " << b2 << endl;
+
+ ASTNode a1 = bm->CreateNode(BVPLUS, s1, s2);
+ a1.SetValueWidth(size);
+
+ ASTVec& bba1 = bm->BBTerm(a1);
+ cout << "bitblasted a1 " << endl;
+ LispPrintVec(cout, bba1, 0);
+ cout << endl;
+ bm->AlreadyPrintedSet.clear();
+
+ ASTNode a2 = bm->CreateNode(BVPLUS, s1, s2, s3);
+ a1.SetValueWidth(2);
+
+ ASTVec& bba2 = bm->BBTerm(a2);
+ cout << "bitblasted a2 " << endl;
+ LispPrintVec(cout, bba2, 0);
+ cout << endl;
+ bm->AlreadyPrintedSet.clear();
+
+ ASTNode a3 = bm->CreateNode(BVXOR, s1, s2);
+ a3.SetValueWidth(2);
+
+ ASTVec& bba3 = bm->BBTerm(a3);
+ cout << "bitblasted a3 " << endl;
+ LispPrintVec(cout, bba3, 0);
+ cout << endl;
+ bm->AlreadyPrintedSet.clear();
+
+ ASTNode a4 = bm->CreateNode(EQ, s1, s2);
+ ASTNode bba4 = bm->BBForm(a4);
+ cout << "bitblasted a4 " << endl << bba4 << endl;
+
+ ASTNode a5 = bm->CreateNode(BVLE, s1, s2);
+ ASTNode bba5 = bm->BBForm(a5);
+ cout << "bitblasted a5 " << endl << bba5 << endl;
+
+ return 0;
}
int main()
{
- const int size = 1;
-
- BeevMgr *bm = new BeevMgr();
- ASTNode s1 = bm->CreateSymbol("x");
- s1.SetValueWidth(size);
-
- cout << "s1" << s1 << endl;
- ASTNode s2 = bm->CreateSymbol("y");
- s2.SetValueWidth(size);
-
- cout << "s2" << s2 << endl;
- ASTNode s3 = bm->CreateSymbol("z");
- s3.SetValueWidth(size);
-
- cout << "s3" << s3 << endl;
-
- ASTNode bbs1 = bm->BBForm(s1);
- cout << "bitblasted s1" << endl << bbs1 << endl;
- bm->PrintClauseList(cout, bm->ToCNF(bbs1));
-
- ASTNode a2 = bm->CreateNode(AND, s1, s2);
- ASTNode bba2 = bm->BBForm(a2);
- cout << "bitblasted a2" << endl << bba2 << endl;
- bm->PrintClauseList(cout, bm->ToCNF(bba2));
-
- ASTNode a3 = bm->CreateNode(OR, s1, s2);
- ASTNode bba3 = bm->BBForm(a3);
- cout << "bitblasted a3" << endl << bba3 << endl;
- bm->PrintClauseList(cout, bm->ToCNF(bba3));
-
- ASTNode a4 = bm->CreateNode(EQ, s1, s2);
- ASTNode bba4 = bm->BBForm(a4);
- cout << "bitblasted a4 " << endl << bba4 << endl;
-
- bm->PrintClauseList(cout, bm->ToCNF(bba4));
+ const int size = 1;
+
+ BeevMgr *bm = new BeevMgr();
+ ASTNode s1 = bm->CreateSymbol("x");
+ s1.SetValueWidth(size);
+
+ cout << "s1" << s1 << endl;
+ ASTNode s2 = bm->CreateSymbol("y");
+ s2.SetValueWidth(size);
+
+ cout << "s2" << s2 << endl;
+ ASTNode s3 = bm->CreateSymbol("z");
+ s3.SetValueWidth(size);
+
+ cout << "s3" << s3 << endl;
+
+ ASTNode bbs1 = bm->BBForm(s1);
+ cout << "bitblasted s1" << endl << bbs1 << endl;
+ bm->PrintClauseList(cout, bm->ToCNF(bbs1));
+
+ ASTNode a2 = bm->CreateNode(AND, s1, s2);
+ ASTNode bba2 = bm->BBForm(a2);
+ cout << "bitblasted a2" << endl << bba2 << endl;
+ bm->PrintClauseList(cout, bm->ToCNF(bba2));
+
+ ASTNode a3 = bm->CreateNode(OR, s1, s2);
+ ASTNode bba3 = bm->BBForm(a3);
+ cout << "bitblasted a3" << endl << bba3 << endl;
+ bm->PrintClauseList(cout, bm->ToCNF(bba3));
+
+ ASTNode a4 = bm->CreateNode(EQ, s1, s2);
+ ASTNode bba4 = bm->BBForm(a4);
+ cout << "bitblasted a4 " << endl << bba4 << endl;
+
+ bm->PrintClauseList(cout, bm->ToCNF(bba4));
}
#include "printers.h"
-namespace printer {
+namespace printer
+{
using std::string;
using namespace BEEV;
-
// printer for C code (copied from PL_Print())
// TODO: this does not fully implement printing of all of the STP
// language - FatalError calls inserted for unimplemented
// FatalError("C_Print1: printing not implemented for this kind: ",*this);
// helper function for printing C code (copied from PL_Print1())
-void C_Print1(ostream& os, const ASTNode n, int indentation, bool letize) {
+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()) {
+ if (!n.IsDefined())
+ {
os << "<undefined>";
return;
}
//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) {
+ 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) {
+ 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) {
+ switch (kind)
+ {
case BVGETBIT:
FatalError("C_Print1: printing not implemented for this kind: ", n);
C_Print1(os, c[0], indentation, letize);
case BVCONCAT:
FatalError("C_Print1: printing not implemented for this kind: ", n); // stopgap for un-implemented features
os << "(";
- C_Print1(os,c[0], indentation, letize);
+ C_Print1(os, c[0], indentation, letize);
os << " @ ";
C_Print1(os, c[1], indentation, letize);
os << ")" << endl;
assert (num_bytes > 0);
// for multi-byte extraction, use the ADDRESS
- if (num_bytes > 1) {
+ if (num_bytes > 1)
+ {
os << "&";
C_Print1(os, c[0], indentation, letize);
os << "[" << lower / 8 << "]";
}
// for single-byte extraction, use the VALUE
- else {
+ else
+ {
C_Print1(os, c[0], indentation, letize);
os << "[" << lower / 8 << "]";
}
case BVRIGHTSHIFT:
FatalError("C_Print1: printing not implemented for this kind: ", n); // stopgap for un-implemented features
os << "(";
- C_Print1(os,c[0], indentation, letize);
+ C_Print1(os, c[0], indentation, letize);
os << " >> ";
os << GetUnsignedConst(c[1]);
os << ")";
case BVMOD:
os << kind << "(";
os << n.GetValueWidth();
- for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++) {
+ for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
os << ", " << endl;
C_Print1(os, *it, indentation, letize);
}
// try to figure out whether it's a single-byte or multi-byte
// comparison
- if (LHSkind == BVEXTRACT) {
+ if (LHSkind == BVEXTRACT)
+ {
upper = GetUnsignedConst(c[0].GetChildren()[1]);
lower = GetUnsignedConst(c[0].GetChildren()[2]);
num_bytes = (upper - lower + 1) / 8;
}
- else if (RHSkind == BVEXTRACT) {
+ else if (RHSkind == BVEXTRACT)
+ {
upper = GetUnsignedConst(c[1].GetChildren()[1]);
lower = GetUnsignedConst(c[1].GetChildren()[2]);
num_bytes = (upper - lower + 1) / 8;
}
- if (num_bytes > 1) {
+ if (num_bytes > 1)
+ {
os << "(memcmp(";
- C_Print1(os,c[0], indentation, letize);
+ 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) {
+ else if (num_bytes == 1)
+ {
os << "(";
C_Print1(os, c[0], indentation, letize);
os << " == ";
C_Print1(os, c[1], indentation, letize);
os << ")";
}
- else {
+ else
+ {
FatalError("C_Print1: ugh problem in implementing ==");
}
case OR:
case NAND:
case NOR:
- case XOR: {
+ 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) {
+ for (; it != itend; it++)
+ {
+ switch (kind)
+ {
case AND:
os << " && ";
break;
FatalError("C_Print1: printing not implemented for this kind: ", n); // stopgap for un-implemented features
os << "(";
os << "(";
- C_Print1(os,c[0], indentation, letize);
+ C_Print1(os, c[0], indentation, letize);
os << ")";
os << " <=> ";
os << "(";
- C_Print1(os,c[1], indentation, letize);
+ C_Print1(os, c[1], indentation, letize);
os << ")";
os << ")";
os << endl;
FatalError("C_Print1: printing not implemented for this kind: ", n); // stopgap for un-implemented features
os << "(";
os << "(";
- C_Print1(os, c[0],indentation, letize);
+ C_Print1(os, c[0], indentation, letize);
os << ")";
os << " => ";
os << "(";
FatalError("C_Print1: printing not implemented for this kind: ", n); // stopgap for un-implemented features
os << kind << "(";
- C_Print1(os, c[0],indentation, letize);
+ C_Print1(os, c[0], indentation, letize);
os << ",";
os << n.GetValueWidth();
os << ")" << endl;
//2. In the second pass print a "global let" and then print N
//2. as follows: Every occurence of a node occuring more than
//2. once is replaced with the corresponding let variable.
-ostream& C_Print(ostream &os, const ASTNode n, int indentation) {
+ostream& C_Print(ostream &os, const ASTNode n, int indentation)
+{
// Clear the PrintMap
BeevMgr& bm = n.GetBeevMgr();
bm.PLPrintNodeSet.clear();
//3. Then print the Node itself, replacing every occurence of
//3. expr1 with var1, expr2 with var2, ...
//os << "(";
- if (0 < bm.NodeLetVarMap.size()) {
+ if (0 < bm.NodeLetVarMap.size())
+ {
//ASTNodeMap::iterator it=bm.NodeLetVarMap.begin();
//ASTNodeMap::iterator itend=bm.NodeLetVarMap.end();
std::vector<pair<ASTNode, ASTNode> >::iterator it = bm.NodeLetVarVec.begin();
// start a new block to create new static scope
os << "{" << endl;
- for (; it != itend; it++) {
+ for (; it != itend; it++)
+ {
// see if it's a BVEXTRACT, and if so, whether it's multi-byte
- if (it->second.GetKind() == BVEXTRACT) {
+ if (it->second.GetKind() == BVEXTRACT)
+ {
upper = GetUnsignedConst(it->second.GetChildren()[1]);
lower = GetUnsignedConst(it->second.GetChildren()[2]);
num_bytes = (upper - lower + 1) / 8;
}
//print the let var first
- if (num_bytes > 1) {
+ if (num_bytes > 1)
+ {
// for multi-byte assignment, use 'memcpy' and array notation
os << "unsigned char ";
- C_Print1(os, it->first,indentation, false);
+ C_Print1(os, it->first, indentation, false);
os << "[" << num_bytes << "]; ";
os << "memcpy(";
- C_Print1(os,it->first, indentation, false);
+ C_Print1(os, it->first, indentation, false);
os << ", ";
//print the expr
- C_Print1(os,it->second, indentation, false);
+ C_Print1(os, it->second, indentation, false);
os << ", " << num_bytes << ");";
}
- else {
+ else
+ {
// for single-byte assignment, use '='
os << "unsigned char ";
- C_Print1(os, it->first,indentation, false);
+ C_Print1(os, it->first, indentation, false);
os << " = ";
//print the expr
- C_Print1(os, it->second,indentation, false);
+ C_Print1(os, it->second, indentation, false);
os << ";" << endl;
}
os << ";" << endl << "}";
}
- else {
+ else
+ {
os << "stp_assert ";
C_Print1(os, n, indentation, false);
os << ";";
#include "printers.h"
-namespace printer {
+namespace printer
+{
using std::string;
using namespace BEEV;
string functionToSMTLIBName(const BEEV::Kind k);
void SMTLIB_Print1(ostream& os, const BEEV::ASTNode n, int indentation, bool letize);
-void outputBitVec(const ASTNode n, ostream& os) {
+void outputBitVec(const ASTNode n, ostream& os)
+{
Kind k = n.GetKind();
const ASTVec &c = n.GetChildren();
ASTNode op;
- if (BITVECTOR == k) {
+ if (BITVECTOR == k)
+ {
op = c[0];
}
- else if (BVCONST == k) {
+ else if (BVCONST == k)
+ {
op = n;
}
else
CONSTANTBV::BitVector_Dispose(str);
}
-void SMTLIB_Print1(ostream& os, const ASTNode n, int indentation, bool letize) {
+void SMTLIB_Print1(ostream& os, const ASTNode n, int indentation, bool letize)
+{
//os << spaces(indentation);
//os << endl << spaces(indentation);
- if (!n.IsDefined()) {
+ if (!n.IsDefined())
+ {
os << "<undefined>";
return;
}
//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) {
+ if ((bm.NodeLetVarMap1.find(n) != bm.NodeLetVarMap1.end()) && !letize)
+ {
SMTLIB_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) {
+ if ((bm.NodeLetVarMap.find(n) != bm.NodeLetVarMap.end()) && letize)
+ {
SMTLIB_Print1(os, (bm.NodeLetVarMap[n]), indentation, letize);
return;
}
//otherwise print it normally
Kind kind = n.GetKind();
const ASTVec &c = n.GetChildren();
- switch (kind) {
+ switch (kind)
+ {
case BITVECTOR:
case BVCONST:
outputBitVec(n, os);
break;
case BVSX:
- case BVZX: {
+ case BVZX:
+ {
unsigned int amount = GetUnsignedConst(c[1]);
if (BVZX == kind)
os << "(zero_extend[";
os << ")";
}
break;
- case BVEXTRACT: {
+ case BVEXTRACT:
+ {
unsigned int upper = GetUnsignedConst(c[1]);
unsigned int lower = GetUnsignedConst(c[2]);
assert(upper >= lower);
os << ")";
}
break;
- default: {
+ default:
+ {
os << "(" << functionToSMTLIBName(kind);
ASTVec::const_iterator iend = c.end();
- for (ASTVec::const_iterator i = c.begin(); i != iend; i++) {
+ for (ASTVec::const_iterator i = c.begin(); i != iend; i++)
+ {
os << " ";
SMTLIB_Print1(os, *i, 0, letize);
}
}
// copied from Presentation Langauge printer.
-ostream& SMTLIB_Print(ostream &os, const ASTNode n, const int indentation) {
+ostream& SMTLIB_Print(ostream &os, const ASTNode n, const int indentation)
+{
// Clear the PrintMap
BeevMgr& bm = n.GetBeevMgr();
bm.PLPrintNodeSet.clear();
//3. Then print the Node itself, replacing every occurence of
//3. expr1 with var1, expr2 with var2, ...
//os << "(";
- if (0 < bm.NodeLetVarMap.size()) {
+ if (0 < bm.NodeLetVarMap.size())
+ {
//ASTNodeMap::iterator it=bm.NodeLetVarMap.begin();
//ASTNodeMap::iterator itend=bm.NodeLetVarMap.end();
std::vector<pair<ASTNode, ASTNode> >::iterator it = bm.NodeLetVarVec.begin();
//update the second map for proper printing of LET
bm.NodeLetVarMap1[it->second] = it->first;
- for (it++; it != itend; it++) {
+ for (it++; it != itend; it++)
+ {
os << "," << endl;
//print the let var first
SMTLIB_Print1(os, it->first, indentation, false);
return os;
}
-string functionToSMTLIBName(const Kind k) {
- switch (k) {
+string functionToSMTLIBName(const Kind k)
+{
+ switch (k)
+ {
case AND:
case BVAND:
case BVNAND:
case SBVREM:
return "bvsrem";
- default: {
+ default:
+ {
cerr << "Unknown name when outputting:";
FatalError(_kind_names[k]);
return ""; // to quieten compiler/
* Outputs in DOT graph format. Can be layed out by the dotty/neato tools.
*/
-namespace printer {
+namespace printer
+{
using std::string;
using namespace BEEV;
void outputBitVec(const ASTNode n, ostream& os);
-void Dot_Print1(ostream &os, const ASTNode n, hash_set<int> *alreadyOutput) {
+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())
alreadyOutput->insert(n.GetNodeNum());
os << "n" << n.GetNodeNum() << "[label =\"";
- switch(n.GetKind())
+ switch (n.GetKind())
{
case SYMBOL:
n.nodeprint(os);
os << _kind_names[n.GetKind()];
}
-
- os << "\"];" << endl;
-
+ 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);
- }
+ 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);
+ }
}
-ostream& Dot_Print(ostream &os, const ASTNode n) {
+ostream& Dot_Print(ostream &os, const ASTNode n)
+{
os << "digraph G{" << endl;
#include "../ASTUtil.h"
#include "../ASTKind.h"
-
namespace printer
{
- ostream& Dot_Print(ostream &os, const BEEV::ASTNode n);
- ostream& SMTLIB_Print(ostream &os, const BEEV::ASTNode n, const int indentation=0);
- ostream& C_Print(ostream &os, const BEEV::ASTNode n, const int indentation=0);
+ostream& Dot_Print(ostream &os, const BEEV::ASTNode n);
+ostream& SMTLIB_Print(ostream &os, const BEEV::ASTNode n, const int indentation = 0);
+ostream& C_Print(ostream &os, const BEEV::ASTNode n, const int indentation = 0);
}
#endif /* PRINTERS_H_ */
#include "../AST/AST.h"
#include "../AST/ASTUtil.h"
-namespace BEEV {
+namespace BEEV
+{
- //error printing
- static void BVConstEvaluatorError(CONSTANTBV::ErrCode e, const ASTNode& t){
- std::string ss("BVConstEvaluator:");
- ss += (const char*)BitVector_Error(e);
- FatalError(ss.c_str(), t);
- }
+//error printing
+static void BVConstEvaluatorError(CONSTANTBV::ErrCode e, const ASTNode& t)
+{
+ std::string ss("BVConstEvaluator:");
+ ss += (const char*) BitVector_Error(e);
+ FatalError(ss.c_str(), t);
+}
#ifndef NATIVE_C_ARITH
- ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
- ASTNode OutputNode;
- Kind k = t.GetKind();
-
- if(CheckSolverMap(t,OutputNode))
- return OutputNode;
- OutputNode = t;
-
- unsigned int inputwidth = t.GetValueWidth();
- unsigned int outputwidth = inputwidth;
- CBV output = NULL;
-
- CBV tmp0 = NULL;
- CBV tmp1 = NULL;
-
- //saving some typing. BVPLUS does not use these variables. if the
- //input BVPLUS has two nodes, then we want to avoid setting these
- //variables.
- if(1 == t.Degree() ){
- tmp0 = BVConstEvaluator(t[0]).GetBVConst();
- }else if(2 == t.Degree() && k != BVPLUS ) {
- tmp0 = BVConstEvaluator(t[0]).GetBVConst();
- tmp1 = BVConstEvaluator(t[1]).GetBVConst();
- }
-
- switch(k) {
- case UNDEFINED:
- case READ:
- case WRITE:
- case SYMBOL:
- FatalError("BVConstEvaluator: term is not a constant-term",t);
- break;
- case BVCONST:
- //FIXME Handle this special case better
- OutputNode = t;
- break;
- case BVNEG:{
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- CONSTANTBV::Set_Complement(output,tmp0);
- OutputNode = CreateBVConst(output,outputwidth);
- break;
- }
- case BVSX: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- //unsigned * out0 = BVConstEvaluator(t[0]).GetBVConst();
- unsigned t0_width = t[0].GetValueWidth();
- if(inputwidth == t0_width) {
- CONSTANTBV::BitVector_Copy(output, tmp0);
- OutputNode = CreateBVConst(output, outputwidth);
- }
- else {
- bool topbit_sign = (CONSTANTBV::BitVector_Sign(tmp0) < 0 );
-
- if(topbit_sign){
- CONSTANTBV::BitVector_Fill(output);
- }
- CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, t0_width);
- OutputNode = CreateBVConst(output, outputwidth);
- }
- break;
- }
-
- case BVZX: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- unsigned t0_width = t[0].GetValueWidth();
- if(inputwidth == t0_width) {
- CONSTANTBV::BitVector_Copy(output, tmp0);
- OutputNode = CreateBVConst(output, outputwidth);
- }
- else {
- CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, t0_width);
- OutputNode = CreateBVConst(output, outputwidth);
- }
- break;
- }
-
-
- case BVLEFTSHIFT:
- {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
-
- // the shift is destructive, get a copy.
- CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, inputwidth);
-
- // get the number of bits to shift it.
- unsigned int shift = GetUnsignedConst(BVConstEvaluator(t[1]));
-
- CONSTANTBV::BitVector_Move_Left(output,shift);
- OutputNode = CreateBVConst(output,outputwidth);
- break;
- }
- case BVRIGHTSHIFT:
- {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
-
- // the shift is destructive, get a copy.
- CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, inputwidth);
-
- // get the number of bits to shift it.
- unsigned int shift = GetUnsignedConst(BVConstEvaluator(t[1]));
-
- CONSTANTBV::BitVector_Move_Right(output,shift);
- OutputNode = CreateBVConst(output,outputwidth);
- break;
- }
-
-
- case BVAND: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- CONSTANTBV::Set_Intersection(output,tmp0,tmp1);
- OutputNode = CreateBVConst(output, outputwidth);
- break;
- }
- case BVOR: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- CONSTANTBV::Set_Union(output,tmp0,tmp1);
- OutputNode = CreateBVConst(output, outputwidth);
- break;
- }
- case BVXOR: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- CONSTANTBV::Set_ExclusiveOr(output,tmp0,tmp1);
- OutputNode = CreateBVConst(output, outputwidth);
- break;
- }
- case BVSUB: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- bool carry = false;
- CONSTANTBV::BitVector_sub(output,tmp0,tmp1,&carry);
- OutputNode = CreateBVConst(output, outputwidth);
- break;
- }
- case BVUMINUS: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- CONSTANTBV::BitVector_Negate(output, tmp0);
- OutputNode = CreateBVConst(output, outputwidth);
- break;
- }
- case BVEXTRACT: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- tmp0 = BVConstEvaluator(t[0]).GetBVConst();
- unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
- unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
- unsigned int len = hi-low+1;
-
- CONSTANTBV::BitVector_Destroy(output);
- output = CONSTANTBV::BitVector_Create(len, false);
- CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, low, len);
- outputwidth = len;
- OutputNode = CreateBVConst(output, outputwidth);
- break;
- }
- //FIXME Only 2 inputs?
- case BVCONCAT: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- unsigned t0_width = t[0].GetValueWidth();
- unsigned t1_width = t[1].GetValueWidth();
- CONSTANTBV::BitVector_Destroy(output);
-
- output = CONSTANTBV::BitVector_Concat(tmp0, tmp1);
- outputwidth = t0_width + t1_width;
- OutputNode = CreateBVConst(output, outputwidth);
-
- break;
- }
- case BVMULT: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- CBV tmp = CONSTANTBV::BitVector_Create(2*inputwidth,true);
- CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(tmp,tmp0,tmp1);
-
- if(0 != e) {
- BVConstEvaluatorError(e,t);
- }
- //FIXME WHAT IS MY OUTPUT???? THE SECOND HALF of tmp?
- //CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, inputwidth, inputwidth);
- CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, 0, inputwidth);
- OutputNode = CreateBVConst(output, outputwidth);
- CONSTANTBV::BitVector_Destroy(tmp);
- break;
- }
- case BVPLUS: {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- bool carry = false;
- ASTVec c = t.GetChildren();
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- CBV kk = BVConstEvaluator(*it).GetBVConst();
- CONSTANTBV::BitVector_add(output,output,kk,&carry);
- carry = false;
- //CONSTANTBV::BitVector_Destroy(kk);
- }
- OutputNode = CreateBVConst(output, outputwidth);
- break;
- }
- //FIXME ANOTHER SPECIAL CASE
- case SBVDIV:
- case SBVREM:{
- OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
- break;
- }
- case BVDIV:
- case BVMOD: {
- CBV quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
- CBV remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
-
- // tmp0 is dividend, tmp1 is the divisor
- //All parameters to BitVector_Div_Pos must be distinct unlike BitVector_Divide
- //FIXME the contents of the second parameter to Div_Pos is destroyed
- //As tmp0 is currently the same as the copy belonging to an ASTNode t[0]
- //this must be copied.
- tmp0 = CONSTANTBV::BitVector_Clone(tmp0);
- CONSTANTBV::ErrCode e= CONSTANTBV::BitVector_Div_Pos(quotient,tmp0,tmp1,remainder);
- CONSTANTBV::BitVector_Destroy(tmp0);
-
- if(0 != e) {
- //error printing
- if(counterexample_checking_during_refinement) {
- output = CONSTANTBV::BitVector_Create(inputwidth,true);
- OutputNode = CreateBVConst(output, outputwidth);
- bvdiv_exception_occured = true;
-
- // CONSTANTBV::BitVector_Destroy(output);
- break;
+ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t)
+{
+ ASTNode OutputNode;
+ Kind k = t.GetKind();
+
+ if (CheckSolverMap(t, OutputNode))
+ return OutputNode;
+ OutputNode = t;
+
+ unsigned int inputwidth = t.GetValueWidth();
+ unsigned int outputwidth = inputwidth;
+ CBV output = NULL;
+
+ CBV tmp0 = NULL;
+ CBV tmp1 = NULL;
+
+ //saving some typing. BVPLUS does not use these variables. if the
+ //input BVPLUS has two nodes, then we want to avoid setting these
+ //variables.
+ if (1 == t.Degree())
+ {
+ tmp0 = BVConstEvaluator(t[0]).GetBVConst();
}
- else {
- BVConstEvaluatorError(e,t);
+ else if (2 == t.Degree() && k != BVPLUS)
+ {
+ tmp0 = BVConstEvaluator(t[0]).GetBVConst();
+ tmp1 = BVConstEvaluator(t[1]).GetBVConst();
}
- } //end of error printing
-
- //FIXME Not very standard in the current scheme
- if(BVDIV == k){
- OutputNode = CreateBVConst(quotient, outputwidth);
- CONSTANTBV::BitVector_Destroy(remainder);
- }else{
- OutputNode = CreateBVConst(remainder, outputwidth);
- CONSTANTBV::BitVector_Destroy(quotient);
- }
-
- break;
- }
- case ITE:
- if(ASTTrue == t[0])
- OutputNode = BVConstEvaluator(t[1]);
- else if(ASTFalse == t[0])
- OutputNode = BVConstEvaluator(t[2]);
- else
- FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t);
- break;
- case EQ:
- if(CONSTANTBV::BitVector_equal(tmp0,tmp1))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case NEQ:
- if(!CONSTANTBV::BitVector_equal(tmp0,tmp1))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVLT:
- if(-1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVLE: {
- int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1);
- if(comp <= 0)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVGT:
- if(1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVGE: {
- int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1);
- if(comp >= 0)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVSLT:
- if(-1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVSLE: {
- signed int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1);
- if(comp <= 0)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVSGT:
- if(1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVSGE: {
- int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1);
- if(comp >= 0)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- default:
- FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
- break;
- }
-/*
- if(BVCONST != k){
- cerr<<inputwidth<<endl;
- cerr<<"------------------------"<<endl;
- t.LispPrint(cerr);
- cerr<<endl;
- OutputNode.LispPrint(cerr);
- cerr<<endl<<"------------------------"<<endl;
- }
-*/
- UpdateSolverMap(t,OutputNode);
- //UpdateSimplifyMap(t,OutputNode,false);
- return OutputNode;
- }
-#else
- //accepts 64 bit BVConst and sign extends it
- static unsigned long long int SXBVConst64(const ASTNode& t) {
- unsigned long long int c = t.GetBVConst();
- unsigned int len = t.GetValueWidth();
-
- unsigned long long int mask = 1;
- mask = mask << len-1;
-
- bool TopBit = (c & mask) ? true : false;
- if(!TopBit) return c;
-
- unsigned long long int sign = 0xffffffffffffffffLL;
- sign = sign << len-1;
-
- return (c | sign);
- }
-
- //FIXME: Ideally I would like the ASTNodes to be able to operate on
- //themselves (add, sub, concat, etc.) rather than doing a
- //GetBVConst() and then do the operation externally. For now,
- //this is the fastest path to completion.
- ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
- //cerr << "inside begin bcconstevaluator: " << t << endl;
-
- ASTNode OutputNode;
- if(CheckSolverMap(t,OutputNode))
- return OutputNode;
- OutputNode = ASTUndefined;
-
- Kind k = t.GetKind();
- unsigned long long int output = 0;
- unsigned inputwidth = t.GetValueWidth();
- ASTNode t0 = ASTUndefined;
- ASTNode t1 = ASTUndefined;
- if(2 == t.Degree()) {
- t0 = BVConstEvaluator(t[0]);
- t1 = BVConstEvaluator(t[1]);
- }
- switch(k) {
- case READ:
- case UNDEFINED:
- case WRITE:
- case SYMBOL:
- cerr << t;
- FatalError("BVConstEvaluator: term is not a constant-term",t);
- break;
- case BVCONST:
- return t;
- break;
- case BVNEG:
- //compute bitwise negation in C
- output = ~(BVConstEvaluator(t[0]).GetBVConst());
- break;
- case BVSX:
- output = SXBVConst64(BVConstEvaluator(t[0]));
- break;
- case BVAND:
- output = t0.GetBVConst() & t1.GetBVConst();
- break;
- case BVOR:
- output = t0.GetBVConst() | t1.GetBVConst();
- break;
- case BVXOR:
- output = t0.GetBVConst() ^ t1.GetBVConst();
- break;
- case BVSUB:
- output = t0.GetBVConst() - t1.GetBVConst();
- break;
- case BVUMINUS:
- output = ~(BVConstEvaluator(t[0]).GetBVConst()) + 1;
- break;
- case BVEXTRACT: {
- unsigned long long int val = BVConstEvaluator(t[0]).GetBVConst();
- unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
- unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
-
- if(!(0 <= hi <= 64))
- FatalError("ConstantEvaluator: hi bit in BVEXTRACT is > 32bits",t);
- if(!(0 <= low <= hi <= 64))
- FatalError("ConstantEvaluator: low bit in BVEXTRACT is > 32bits or hi",t);
-
- //64 bit mask.
- unsigned long long int mask1 = 0xffffffffffffffffLL;
- mask1 >>= 64-(hi+1);
-
- //extract val[hi:0]
- val &= mask1;
- //extract val[hi:low]
- val >>= low;
- output = val;
- break;
- }
- case BVCONCAT: {
- unsigned long long int q = BVConstEvaluator(t0).GetBVConst();
- unsigned long long int r = BVConstEvaluator(t1).GetBVConst();
-
- unsigned int qlen = t[0].GetValueWidth();
- unsigned int rlen = t[1].GetValueWidth();
- unsigned int slen = t.GetValueWidth();
- if(!(0 < qlen + rlen <= 64))
- FatalError("BVConstEvaluator:"
- "lengths of childnodes of BVCONCAT are > 64:",t);
-
- //64 bit mask for q
- unsigned long long int qmask = 0xffffffffffffffffLL;
- qmask >>= 64-qlen;
- //zero the useless bits of q
- q &= qmask;
-
- //64 bit mask for r
- unsigned long long int rmask = 0xffffffffffffffffLL;
- rmask >>= 64-rlen;
- //zero the useless bits of r
- r &= rmask;
-
- //concatenate
- q <<= rlen;
- q |= r;
-
- //64 bit mask for output s
- unsigned long long int smask = 0xffffffffffffffffLL;
- smask >>= 64-slen;
-
- //currently q has the output
- output = q;
- output &= smask;
- break;
- }
- case BVMULT: {
- output = t0.GetBVConst() * t1.GetBVConst();
-
- //64 bit mask
- unsigned long long int mask = 0xffffffffffffffffLL;
- mask = mask >> (64 - inputwidth);
- output &= mask;
- break;
- }
- case BVPLUS: {
- ASTVec c = t.GetChildren();
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
- output += BVConstEvaluator(*it).GetBVConst();
-
- //64 bit mask
- unsigned long long int mask = 0xffffffffffffffffLL;
- mask = mask >> (64 -inputwidth);
- output &= mask;
- break;
- }
- case SBVDIV:
- case SBVREM: {
- output = BVConstEvaluator(TranslateSignedDivMod(t)).GetBVConst();
- break;
- }
- case BVDIV: {
- if(0 == t1.GetBVConst()) {
- //if denominator is 0 then
- // (if refinement is ON then output is set to 0)
- // (else produce a fatal error)
- if(counterexample_checking_during_refinement) {
- output = 0;
- bvdiv_exception_occured = true;
- break;
- }
- else {
- FatalError("BVConstEvaluator: divide by zero not allowed:",t);
+
+ switch (k)
+ {
+ case UNDEFINED:
+ case READ:
+ case WRITE:
+ case SYMBOL:
+ FatalError("BVConstEvaluator: term is not a constant-term", t);
+ break;
+ case BVCONST:
+ //FIXME Handle this special case better
+ OutputNode = t;
+ break;
+ case BVNEG:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ CONSTANTBV::Set_Complement(output, tmp0);
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ case BVSX:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ //unsigned * out0 = BVConstEvaluator(t[0]).GetBVConst();
+ unsigned t0_width = t[0].GetValueWidth();
+ if (inputwidth == t0_width)
+ {
+ CONSTANTBV::BitVector_Copy(output, tmp0);
+ OutputNode = CreateBVConst(output, outputwidth);
+ }
+ else
+ {
+ bool topbit_sign = (CONSTANTBV::BitVector_Sign(tmp0) < 0);
+
+ if (topbit_sign)
+ {
+ CONSTANTBV::BitVector_Fill(output);
+ }
+ CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, t0_width);
+ OutputNode = CreateBVConst(output, outputwidth);
+ }
+ break;
+ }
+
+ case BVZX:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ unsigned t0_width = t[0].GetValueWidth();
+ if (inputwidth == t0_width)
+ {
+ CONSTANTBV::BitVector_Copy(output, tmp0);
+ OutputNode = CreateBVConst(output, outputwidth);
+ }
+ else
+ {
+ CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, t0_width);
+ OutputNode = CreateBVConst(output, outputwidth);
+ }
+ break;
+ }
+
+ case BVLEFTSHIFT:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+
+ // the shift is destructive, get a copy.
+ CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, inputwidth);
+
+ // get the number of bits to shift it.
+ unsigned int shift = GetUnsignedConst(BVConstEvaluator(t[1]));
+
+ CONSTANTBV::BitVector_Move_Left(output, shift);
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ case BVRIGHTSHIFT:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+
+ // the shift is destructive, get a copy.
+ CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, inputwidth);
+
+ // get the number of bits to shift it.
+ unsigned int shift = GetUnsignedConst(BVConstEvaluator(t[1]));
+
+ CONSTANTBV::BitVector_Move_Right(output, shift);
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+
+ case BVAND:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ CONSTANTBV::Set_Intersection(output, tmp0, tmp1);
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ case BVOR:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ CONSTANTBV::Set_Union(output, tmp0, tmp1);
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ case BVXOR:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ CONSTANTBV::Set_ExclusiveOr(output, tmp0, tmp1);
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ case BVSUB:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ bool carry = false;
+ CONSTANTBV::BitVector_sub(output, tmp0, tmp1, &carry);
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ case BVUMINUS:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ CONSTANTBV::BitVector_Negate(output, tmp0);
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ case BVEXTRACT:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ tmp0 = BVConstEvaluator(t[0]).GetBVConst();
+ unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+ unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+ unsigned int len = hi - low + 1;
+
+ CONSTANTBV::BitVector_Destroy(output);
+ output = CONSTANTBV::BitVector_Create(len, false);
+ CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, low, len);
+ outputwidth = len;
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ //FIXME Only 2 inputs?
+ case BVCONCAT:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ unsigned t0_width = t[0].GetValueWidth();
+ unsigned t1_width = t[1].GetValueWidth();
+ CONSTANTBV::BitVector_Destroy(output);
+
+ output = CONSTANTBV::BitVector_Concat(tmp0, tmp1);
+ outputwidth = t0_width + t1_width;
+ OutputNode = CreateBVConst(output, outputwidth);
+
+ break;
+ }
+ case BVMULT:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ CBV tmp = CONSTANTBV::BitVector_Create(2* inputwidth , true);
+ CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(tmp, tmp0, tmp1);
+
+ if (0 != e)
+ {
+ BVConstEvaluatorError(e, t);
+ }
+ //FIXME WHAT IS MY OUTPUT???? THE SECOND HALF of tmp?
+ //CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, inputwidth, inputwidth);
+ CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, 0, inputwidth);
+ OutputNode = CreateBVConst(output, outputwidth);
+ CONSTANTBV::BitVector_Destroy(tmp);
+ break;
+ }
+ case BVPLUS:
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ bool carry = false;
+ ASTVec c = t.GetChildren();
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ CBV kk = BVConstEvaluator(*it).GetBVConst();
+ CONSTANTBV::BitVector_add(output, output, kk, &carry);
+ carry = false;
+ //CONSTANTBV::BitVector_Destroy(kk);
+ }
+ OutputNode = CreateBVConst(output, outputwidth);
+ break;
+ }
+ //FIXME ANOTHER SPECIAL CASE
+ case SBVDIV:
+ case SBVREM:
+ {
+ OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
+ break;
+ }
+ case BVDIV:
+ case BVMOD:
+ {
+ CBV quotient = CONSTANTBV::BitVector_Create(inputwidth, true);
+ CBV remainder = CONSTANTBV::BitVector_Create(inputwidth, true);
+
+ // tmp0 is dividend, tmp1 is the divisor
+ //All parameters to BitVector_Div_Pos must be distinct unlike BitVector_Divide
+ //FIXME the contents of the second parameter to Div_Pos is destroyed
+ //As tmp0 is currently the same as the copy belonging to an ASTNode t[0]
+ //this must be copied.
+ tmp0 = CONSTANTBV::BitVector_Clone(tmp0);
+ CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient, tmp0, tmp1, remainder);
+ CONSTANTBV::BitVector_Destroy(tmp0);
+
+ if (0 != e)
+ {
+ //error printing
+ if (counterexample_checking_during_refinement)
+ {
+ output = CONSTANTBV::BitVector_Create(inputwidth, true);
+ OutputNode = CreateBVConst(output, outputwidth);
+ bvdiv_exception_occured = true;
+
+ // CONSTANTBV::BitVector_Destroy(output);
+ break;
+ }
+ else
+ {
+ BVConstEvaluatorError(e, t);
+ }
+ } //end of error printing
+
+ //FIXME Not very standard in the current scheme
+ if (BVDIV == k)
+ {
+ OutputNode = CreateBVConst(quotient, outputwidth);
+ CONSTANTBV::BitVector_Destroy(remainder);
+ }
+ else
+ {
+ OutputNode = CreateBVConst(remainder, outputwidth);
+ CONSTANTBV::BitVector_Destroy(quotient);
+ }
+
+ break;
+ }
+ case ITE:
+ if (ASTTrue == t[0])
+ OutputNode = BVConstEvaluator(t[1]);
+ else if (ASTFalse == t[0])
+ OutputNode = BVConstEvaluator(t[2]);
+ else
+ FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:", t);
+ break;
+ case EQ:
+ if (CONSTANTBV::BitVector_equal(tmp0, tmp1))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case NEQ:
+ if (!CONSTANTBV::BitVector_equal(tmp0, tmp1))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVLT:
+ if (-1 == CONSTANTBV::BitVector_Lexicompare(tmp0, tmp1))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVLE:
+ {
+ int comp = CONSTANTBV::BitVector_Lexicompare(tmp0, tmp1);
+ if (comp <= 0)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVGT:
+ if (1 == CONSTANTBV::BitVector_Lexicompare(tmp0, tmp1))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVGE:
+ {
+ int comp = CONSTANTBV::BitVector_Lexicompare(tmp0, tmp1);
+ if (comp >= 0)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVSLT:
+ if (-1 == CONSTANTBV::BitVector_Compare(tmp0, tmp1))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVSLE:
+ {
+ signed int comp = CONSTANTBV::BitVector_Compare(tmp0, tmp1);
+ if (comp <= 0)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVSGT:
+ if (1 == CONSTANTBV::BitVector_Compare(tmp0, tmp1))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVSGE:
+ {
+ int comp = CONSTANTBV::BitVector_Compare(tmp0, tmp1);
+ if (comp >= 0)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ default:
+ FatalError("BVConstEvaluator: The input kind is not supported yet:", t);
+ break;
}
- }
-
- output = t0.GetBVConst() / t1.GetBVConst();
- //64 bit mask
- unsigned long long int mask = 0xffffffffffffffffLL;
- mask = mask >> (64 - inputwidth);
- output &= mask;
- break;
- }
- case BVMOD: {
- if(0 == t1.GetBVConst()) {
- //if denominator is 0 then
- // (if refinement is ON then output is set to 0)
- // (else produce a fatal error)
- if(counterexample_checking_during_refinement) {
- output = 0;
- bvdiv_exception_occured = true;
- break;
+ /*
+ if(BVCONST != k){
+ cerr<<inputwidth<<endl;
+ cerr<<"------------------------"<<endl;
+ t.LispPrint(cerr);
+ cerr<<endl;
+ OutputNode.LispPrint(cerr);
+ cerr<<endl<<"------------------------"<<endl;
+ }
+ */
+ UpdateSolverMap(t, OutputNode);
+ //UpdateSimplifyMap(t,OutputNode,false);
+ return OutputNode;
+}
+#else
+//accepts 64 bit BVConst and sign extends it
+static unsigned long long int SXBVConst64(const ASTNode& t)
+{
+ unsigned long long int c = t.GetBVConst();
+ unsigned int len = t.GetValueWidth();
+
+ unsigned long long int mask = 1;
+ mask = mask << len-1;
+
+ bool TopBit = (c & mask) ? true : false;
+ if(!TopBit) return c;
+
+ unsigned long long int sign = 0xffffffffffffffffLL;
+ sign = sign << len-1;
+
+ return (c | sign);
+}
+
+//FIXME: Ideally I would like the ASTNodes to be able to operate on
+//themselves (add, sub, concat, etc.) rather than doing a
+//GetBVConst() and then do the operation externally. For now,
+//this is the fastest path to completion.
+ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t)
+{
+ //cerr << "inside begin bcconstevaluator: " << t << endl;
+
+ ASTNode OutputNode;
+ if(CheckSolverMap(t,OutputNode))
+ return OutputNode;
+ OutputNode = ASTUndefined;
+
+ Kind k = t.GetKind();
+ unsigned long long int output = 0;
+ unsigned inputwidth = t.GetValueWidth();
+ ASTNode t0 = ASTUndefined;
+ ASTNode t1 = ASTUndefined;
+ if(2 == t.Degree())
+ {
+ t0 = BVConstEvaluator(t[0]);
+ t1 = BVConstEvaluator(t[1]);
}
- else {
- FatalError("BVConstEvaluator: divide by zero not allowed:",t);
+ switch(k)
+ {
+ case READ:
+ case UNDEFINED:
+ case WRITE:
+ case SYMBOL:
+ cerr << t;
+ FatalError("BVConstEvaluator: term is not a constant-term",t);
+ break;
+ case BVCONST:
+ return t;
+ break;
+ case BVNEG:
+ //compute bitwise negation in C
+ output = ~(BVConstEvaluator(t[0]).GetBVConst());
+ break;
+ case BVSX:
+ output = SXBVConst64(BVConstEvaluator(t[0]));
+ break;
+ case BVAND:
+ output = t0.GetBVConst() & t1.GetBVConst();
+ break;
+ case BVOR:
+ output = t0.GetBVConst() | t1.GetBVConst();
+ break;
+ case BVXOR:
+ output = t0.GetBVConst() ^ t1.GetBVConst();
+ break;
+ case BVSUB:
+ output = t0.GetBVConst() - t1.GetBVConst();
+ break;
+ case BVUMINUS:
+ output = ~(BVConstEvaluator(t[0]).GetBVConst()) + 1;
+ break;
+ case BVEXTRACT:
+ {
+ unsigned long long int val = BVConstEvaluator(t[0]).GetBVConst();
+ unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+ unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+
+ if(!(0 <= hi <= 64))
+ FatalError("ConstantEvaluator: hi bit in BVEXTRACT is > 32bits",t);
+ if(!(0 <= low <= hi <= 64))
+ FatalError("ConstantEvaluator: low bit in BVEXTRACT is > 32bits or hi",t);
+
+ //64 bit mask.
+ unsigned long long int mask1 = 0xffffffffffffffffLL;
+ mask1 >>= 64-(hi+1);
+
+ //extract val[hi:0]
+ val &= mask1;
+ //extract val[hi:low]
+ val >>= low;
+ output = val;
+ break;
+ }
+ case BVCONCAT:
+ {
+ unsigned long long int q = BVConstEvaluator(t0).GetBVConst();
+ unsigned long long int r = BVConstEvaluator(t1).GetBVConst();
+
+ unsigned int qlen = t[0].GetValueWidth();
+ unsigned int rlen = t[1].GetValueWidth();
+ unsigned int slen = t.GetValueWidth();
+ if(!(0 < qlen + rlen <= 64))
+ FatalError("BVConstEvaluator:"
+ "lengths of childnodes of BVCONCAT are > 64:",t);
+
+ //64 bit mask for q
+ unsigned long long int qmask = 0xffffffffffffffffLL;
+ qmask >>= 64-qlen;
+ //zero the useless bits of q
+ q &= qmask;
+
+ //64 bit mask for r
+ unsigned long long int rmask = 0xffffffffffffffffLL;
+ rmask >>= 64-rlen;
+ //zero the useless bits of r
+ r &= rmask;
+
+ //concatenate
+ q <<= rlen;
+ q |= r;
+
+ //64 bit mask for output s
+ unsigned long long int smask = 0xffffffffffffffffLL;
+ smask >>= 64-slen;
+
+ //currently q has the output
+ output = q;
+ output &= smask;
+ break;
+ }
+ case BVMULT:
+ {
+ output = t0.GetBVConst() * t1.GetBVConst();
+
+ //64 bit mask
+ unsigned long long int mask = 0xffffffffffffffffLL;
+ mask = mask >> (64 - inputwidth);
+ output &= mask;
+ break;
+ }
+ case BVPLUS:
+ {
+ ASTVec c = t.GetChildren();
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
+ output += BVConstEvaluator(*it).GetBVConst();
+
+ //64 bit mask
+ unsigned long long int mask = 0xffffffffffffffffLL;
+ mask = mask >> (64 -inputwidth);
+ output &= mask;
+ break;
+ }
+ case SBVDIV:
+ case SBVREM:
+ {
+ output = BVConstEvaluator(TranslateSignedDivMod(t)).GetBVConst();
+ break;
+ }
+ case BVDIV:
+ {
+ if(0 == t1.GetBVConst())
+ {
+ //if denominator is 0 then
+ // (if refinement is ON then output is set to 0)
+ // (else produce a fatal error)
+ if(counterexample_checking_during_refinement)
+ {
+ output = 0;
+ bvdiv_exception_occured = true;
+ break;
+ }
+ else
+ {
+ FatalError("BVConstEvaluator: divide by zero not allowed:",t);
+ }
+ }
+
+ output = t0.GetBVConst() / t1.GetBVConst();
+ //64 bit mask
+ unsigned long long int mask = 0xffffffffffffffffLL;
+ mask = mask >> (64 - inputwidth);
+ output &= mask;
+ break;
+ }
+ case BVMOD:
+ {
+ if(0 == t1.GetBVConst())
+ {
+ //if denominator is 0 then
+ // (if refinement is ON then output is set to 0)
+ // (else produce a fatal error)
+ if(counterexample_checking_during_refinement)
+ {
+ output = 0;
+ bvdiv_exception_occured = true;
+ break;
+ }
+ else
+ {
+ FatalError("BVConstEvaluator: divide by zero not allowed:",t);
+ }
+ }
+
+ output = t0.GetBVConst() % t1.GetBVConst();
+ //64 bit mask
+ unsigned long long int mask = 0xffffffffffffffffLL;
+ mask = mask >> (64 - inputwidth);
+ output &= mask;
+ break;
+ }
+ case ITE:
+ if(ASTTrue == t[0])
+ OutputNode = BVConstEvaluator(t[1]);
+ else if(ASTFalse == t[0])
+ OutputNode = BVConstEvaluator(t[2]);
+ else
+ FatalError("BVConstEvaluator:"
+ "ITE condiional must be either TRUE or FALSE:",t);
+ break;
+ case EQ:
+ if(t0.GetBVConst() == t1.GetBVConst())
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case NEQ:
+ if(t0.GetBVConst() != t1.GetBVConst())
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ break;
+ case BVLT:
+ {
+ unsigned long long n0 = t0.GetBVConst();
+ unsigned long long n1 = t1.GetBVConst();
+ if(n0 < n1)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVLE:
+ if(t0.GetBVConst() <= t1.GetBVConst())
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVGT:
+ if(t0.GetBVConst() > t1.GetBVConst())
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVGE:
+ if(t0.GetBVConst() >= t1.GetBVConst())
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVSLT:
+ {
+ signed long long int n0 = SXBVConst64(t0);
+ signed long long int n1 = SXBVConst64(t1);
+ if(n0 < n1)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVSLE:
+ {
+ signed long long int n0 = SXBVConst64(t0);
+ signed long long int n1 = SXBVConst64(t1);
+ if(n0 <= n1)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVSGT:
+ {
+ signed long long int n0 = SXBVConst64(t0);
+ signed long long int n1 = SXBVConst64(t1);
+ if(n0 > n1)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVSGE:
+ {
+ signed long long int n0 = SXBVConst64(t0);
+ signed long long int n1 = SXBVConst64(t1);
+ if(n0 >= n1)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ default:
+ FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
+ break;
}
- }
-
- output = t0.GetBVConst() % t1.GetBVConst();
- //64 bit mask
- unsigned long long int mask = 0xffffffffffffffffLL;
- mask = mask >> (64 - inputwidth);
- output &= mask;
- break;
- }
- case ITE:
- if(ASTTrue == t[0])
- OutputNode = BVConstEvaluator(t[1]);
- else if(ASTFalse == t[0])
- OutputNode = BVConstEvaluator(t[2]);
- else
- FatalError("BVConstEvaluator:"
- "ITE condiional must be either TRUE or FALSE:",t);
- break;
- case EQ:
- if(t0.GetBVConst() == t1.GetBVConst())
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case NEQ:
- if(t0.GetBVConst() != t1.GetBVConst())
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- break;
- case BVLT: {
- unsigned long long n0 = t0.GetBVConst();
- unsigned long long n1 = t1.GetBVConst();
- if(n0 < n1)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVLE:
- if(t0.GetBVConst() <= t1.GetBVConst())
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVGT:
- if(t0.GetBVConst() > t1.GetBVConst())
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVGE:
- if(t0.GetBVConst() >= t1.GetBVConst())
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVSLT: {
- signed long long int n0 = SXBVConst64(t0);
- signed long long int n1 = SXBVConst64(t1);
- if(n0 < n1)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVSLE: {
- signed long long int n0 = SXBVConst64(t0);
- signed long long int n1 = SXBVConst64(t1);
- if(n0 <= n1)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVSGT: {
- signed long long int n0 = SXBVConst64(t0);
- signed long long int n1 = SXBVConst64(t1);
- if(n0 > n1)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVSGE: {
- signed long long int n0 = SXBVConst64(t0);
- signed long long int n1 = SXBVConst64(t1);
- if(n0 >= n1)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- default:
- FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
- break;
- }
-
- if(ASTTrue != OutputNode && ASTFalse != OutputNode)
- OutputNode = CreateBVConst(inputwidth, output);
- UpdateSolverMap(t,OutputNode);
- //UpdateSimplifyMap(t,OutputNode,false);
- return OutputNode;
- } //End of BVConstEvaluator
+
+ if(ASTTrue != OutputNode && ASTFalse != OutputNode)
+ OutputNode = CreateBVConst(inputwidth, output);
+ UpdateSolverMap(t,OutputNode);
+ //UpdateSimplifyMap(t,OutputNode,false);
+ return OutputNode;
+} //End of BVConstEvaluator
#endif
//In the block below is the old string based version
//It is included here as an easy reference while the current code is being worked on.
/*
- ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
- ASTNode OutputNode;
- Kind k = t.GetKind();
-
- if(CheckSolverMap(t,OutputNode))
- return OutputNode;
- OutputNode = t;
-
- unsigned int inputwidth = t.GetValueWidth();
- unsigned * output = CONSTANTBV::BitVector_Create(inputwidth,true);
- unsigned * One = CONSTANTBV::BitVector_Create(inputwidth,true);
- CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(One, (unsigned char*)"1");
- //error printing
- if(0 != e) {
- std::string ss("BVConstEvaluator:");
- ss += (const char*)BitVector_Error(e);
- FatalError(ss.c_str(), t);
- }
-
- unsigned * Zero = CONSTANTBV::BitVector_Create(inputwidth,true);
- unsigned int * iii = One;
- unsigned int * jjj = Zero;
-
- //saving some typing. BVPLUS does not use these variables. if the
- //input BVPLUS has two nodes, then we want to avoid setting these
- //variables.
- if(2 == t.Degree() && k != BVPLUS && k != BVCONCAT) {
- iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
- jjj = ConvertToCONSTANTBV(BVConstEvaluator(t[1]).GetBVConst());
- }
-
- char * cccc;
- switch(k) {
- case UNDEFINED:
- case READ:
- case WRITE:
- case SYMBOL:
- FatalError("BVConstEvaluator: term is not a constant-term",t);
- break;
- case BVCONST:
- OutputNode = t;
- break;
- case BVNEG:{
- //AARON
- if (iii != One) free(iii);
- //AARON
-
- iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
- CONSTANTBV::Set_Complement(output,iii);
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
- OutputNode = CreateBVConst(cccc,2);
- break;
- }
- case BVSX: {
- unsigned * out0 = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
- unsigned t0_width = t[0].GetValueWidth();
- if(inputwidth == t0_width) {
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(out0);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- //AARON
-
- CONSTANTBV::BitVector_Destroy(out0);
- }
- else {
- // FIXME: (Dill) I'm guessing that BitVector sign returns 1 if the
- // number is positive, 0 if 0, and -1 if negative. But I'm only
- // guessing.
- signed int topbit_sign = (CONSTANTBV::BitVector_Sign(out0) < 0);
- //out1 is the sign-extension bits
- unsigned * out1 = CONSTANTBV::BitVector_Create(inputwidth-t0_width,true);
- if(topbit_sign)
- CONSTANTBV::BitVector_Fill(out1);
-
- //AARON
- CONSTANTBV::BitVector_Destroy(output);
- //AARON
-
- output = CONSTANTBV::BitVector_Concat(out1,out0);
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- //AARON
-
- CONSTANTBV::BitVector_Destroy(out0);
- CONSTANTBV::BitVector_Destroy(out1);
- }
- break;
- }
- case BVAND: {
- CONSTANTBV::Set_Intersection(output,iii,jjj);
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- //AARON
-
- break;
- }
- case BVOR: {
- CONSTANTBV::Set_Union(output,iii,jjj);
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- //AARON
-
- break;
- }
- case BVXOR: {
- CONSTANTBV::Set_ExclusiveOr(output,iii,jjj);
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- //AARON
-
- break;
- }
- case BVSUB: {
- bool carry = false;
- CONSTANTBV::BitVector_sub(output,iii,jjj,&carry);
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- //AARON
-
- break;
- }
- case BVUMINUS: {
- bool carry = false;
-
- //AARON
- if (iii != One) free(iii);
- //AARON
-
- iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
- CONSTANTBV::Set_Complement(output,iii);
- CONSTANTBV::BitVector_add(output,output,One,&carry);
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- //AARON
-
- break;
- }
- case BVEXTRACT: {
- string s(BVConstEvaluator(t[0]).GetBVConst());
- unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
- unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
-
- //length of substr to chop
- unsigned int len = hi-low+1;
- //distance from MSB
- hi = s.size()-1 - hi;
- string ss = s.substr(hi,len);
- OutputNode = CreateBVConst(ss.c_str(),2);
- break;
- }
- case BVCONCAT: {
- string s(BVConstEvaluator(t[0]).GetBVConst());
- string r(BVConstEvaluator(t[1]).GetBVConst());
-
- string q(s+r);
- OutputNode = CreateBVConst(q.c_str(),2);
- break;
- }
- case BVMULT: {
- unsigned * output1 = CONSTANTBV::BitVector_Create(2*inputwidth,true);
- CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(output1,iii,jjj);
- //error printing
- if(0 != e) {
- std::string ss("BVConstEvaluator:");
- ss += (const char*)BitVector_Error(e);
- //destroy all the CONSTANTBV bitvectors
- CONSTANTBV::BitVector_Destroy(iii);
- CONSTANTBV::BitVector_Destroy(jjj);
- CONSTANTBV::BitVector_Destroy(One);
- CONSTANTBV::BitVector_Destroy(Zero);
- FatalError(ss.c_str(), t);
- }
-
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output1);
- std::string s(cccc);
-
- //AARON
- free(cccc);
- //AARON
-
- s = s.substr(inputwidth,inputwidth);
- OutputNode = CreateBVConst(s.c_str(),2);
- CONSTANTBV::BitVector_Destroy(output1);
- break;
- }
- case BVPLUS: {
- bool carry = false;
- ASTVec c = t.GetChildren();
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- unsigned int * kk = ConvertToCONSTANTBV(BVConstEvaluator(*it).GetBVConst());
- CONSTANTBV::BitVector_add(output,output,kk,&carry);
- carry = false;
- CONSTANTBV::BitVector_Destroy(kk);
- }
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- //AARON
-
- break;
- }
- case SBVDIV:
- case SBVREM: {
- OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
- break;
- }
- case BVDIV: {
- unsigned * quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
- unsigned * remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
- // iii is dividend, jjj is the divisor
- CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient,iii,jjj,remainder);
-
- if(0 != e) {
- //error printing
- if(counterexample_checking_during_refinement) {
- OutputNode = CreateZeroConst(inputwidth);
- bvdiv_exception_occured = true;
- break;
- }
- else {
- std::string ss("BVConstEvaluator:");
- ss += (const char*)BitVector_Error(e);
- //destroy all the CONSTANTBV bitvectors
- CONSTANTBV::BitVector_Destroy(iii);
- CONSTANTBV::BitVector_Destroy(jjj);
- CONSTANTBV::BitVector_Destroy(One);
- CONSTANTBV::BitVector_Destroy(Zero);
-
- //AARON
- iii = jjj = One = Zero = NULL;
- //AARON
-
- FatalError(ss.c_str(), t);
- }
- } //end of error printing
-
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(quotient);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- CONSTANTBV::BitVector_Destroy(quotient);
- CONSTANTBV::BitVector_Destroy(remainder);
- //AARON
-
- break;
- }
- case BVMOD: {
- unsigned * quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
- unsigned * remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
- // iii is dividend, jjj is the divisor
- CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient,iii,jjj,remainder);
-
- if(0 != e) {
- //error printing
- if(counterexample_checking_during_refinement) {
- OutputNode = CreateZeroConst(inputwidth);
- bvdiv_exception_occured = true;
- break;
- }
- else {
- std::string ss("BVConstEvaluator:");
- ss += (const char*)BitVector_Error(e);
- //destroy all the CONSTANTBV bitvectors
- CONSTANTBV::BitVector_Destroy(iii);
- CONSTANTBV::BitVector_Destroy(jjj);
- CONSTANTBV::BitVector_Destroy(One);
- CONSTANTBV::BitVector_Destroy(Zero);
-
- //AARON
- iii = jjj = One = Zero = NULL;
- //AARON
-
- FatalError(ss.c_str(), t);
- }
- } //end of errory printing
-
- cccc = (char *)CONSTANTBV::BitVector_to_Bin(remainder);
- OutputNode = CreateBVConst(cccc,2);
-
- //AARON
- free(cccc);
- CONSTANTBV::BitVector_Destroy(quotient);
- CONSTANTBV::BitVector_Destroy(remainder);
- //AARON
-
- break;
- }
- case ITE:
- if(ASTTrue == t[0])
- OutputNode = BVConstEvaluator(t[1]);
- else if(ASTFalse == t[0])
- OutputNode = BVConstEvaluator(t[2]);
- else
- FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t);
- break;
- case EQ:
- if(CONSTANTBV::BitVector_equal(iii,jjj))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case NEQ:
- if(!CONSTANTBV::BitVector_equal(iii,jjj))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVLT:
- if(-1 == CONSTANTBV::BitVector_Lexicompare(iii,jjj))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVLE: {
- int comp = CONSTANTBV::BitVector_Lexicompare(iii,jjj);
- if(comp <= 0)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVGT:
- if(1 == CONSTANTBV::BitVector_Lexicompare(iii,jjj))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVGE: {
- int comp = CONSTANTBV::BitVector_Lexicompare(iii,jjj);
- if(comp >= 0)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVSLT:
- if(-1 == CONSTANTBV::BitVector_Compare(iii,jjj))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVSLE: {
- signed int comp = CONSTANTBV::BitVector_Compare(iii,jjj);
- if(comp <= 0)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- case BVSGT:
- if(1 == CONSTANTBV::BitVector_Compare(iii,jjj))
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- case BVSGE: {
- int comp = CONSTANTBV::BitVector_Compare(iii,jjj);
- if(comp >= 0)
- OutputNode = ASTTrue;
- else
- OutputNode = ASTFalse;
- break;
- }
- default:
- FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
- break;
- }
-
-
-
- // //destroy all the CONSTANTBV bitvectors
-// CONSTANTBV::BitVector_Destroy(iii);
-// CONSTANTBV::BitVector_Destroy(jjj);
-// CONSTANTBV::BitVector_Destroy(output);
-
-// if(k == BVNEG || k == BVUMINUS)
-// CONSTANTBV::BitVector_Destroy(One);
-// else if(k == BVAND || k == BVOR || k == BVXOR || k == BVSUB ||
-// k == BVMULT || k == EQ || k == NEQ || k == BVLT ||
-// k == BVLE || k == BVGT || k == BVGE || k == BVSLT ||
-// k == BVSLE || k == BVSGT || k == BVSGE) {
-// CONSTANTBV::BitVector_Destroy(One);
-// CONSTANTBV::BitVector_Destroy(Zero);
-// }
-
- //AARON
- if (output != NULL) CONSTANTBV::BitVector_Destroy(output);
- if (One != NULL) CONSTANTBV::BitVector_Destroy(One);
- if (Zero != NULL) CONSTANTBV::BitVector_Destroy(Zero);
- if (iii != NULL && iii != One) CONSTANTBV::BitVector_Destroy(iii);
- if (jjj != NULL && jjj != Zero) CONSTANTBV::BitVector_Destroy(jjj);
- //AARON
-
- UpdateSolverMap(t,OutputNode);
- //UpdateSimplifyMap(t,OutputNode,false);
- return OutputNode;
- }
-
-
- unsigned int * ConvertToCONSTANTBV(const char * s) {
- unsigned int length = strlen(s);
- unsigned char * ccc = (unsigned char *)s;
- unsigned * iii = CONSTANTBV::BitVector_Create(length,true);
- CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(iii,ccc);
- //error printing
- if(0 != e) {
- cerr << "ConverToCONSTANTBV: wrong bin value: " << BitVector_Error(e);
- FatalError("");
- }
-
- return iii;
- }
-*/
-}; //end of namespace BEEV
+ ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
+ ASTNode OutputNode;
+ Kind k = t.GetKind();
+
+ if(CheckSolverMap(t,OutputNode))
+ return OutputNode;
+ OutputNode = t;
+
+ unsigned int inputwidth = t.GetValueWidth();
+ unsigned * output = CONSTANTBV::BitVector_Create(inputwidth,true);
+ unsigned * One = CONSTANTBV::BitVector_Create(inputwidth,true);
+ CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(One, (unsigned char*)"1");
+ //error printing
+ if(0 != e) {
+ std::string ss("BVConstEvaluator:");
+ ss += (const char*)BitVector_Error(e);
+ FatalError(ss.c_str(), t);
+ }
+
+ unsigned * Zero = CONSTANTBV::BitVector_Create(inputwidth,true);
+ unsigned int * iii = One;
+ unsigned int * jjj = Zero;
+
+ //saving some typing. BVPLUS does not use these variables. if the
+ //input BVPLUS has two nodes, then we want to avoid setting these
+ //variables.
+ if(2 == t.Degree() && k != BVPLUS && k != BVCONCAT) {
+ iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+ jjj = ConvertToCONSTANTBV(BVConstEvaluator(t[1]).GetBVConst());
+ }
+
+ char * cccc;
+ switch(k) {
+ case UNDEFINED:
+ case READ:
+ case WRITE:
+ case SYMBOL:
+ FatalError("BVConstEvaluator: term is not a constant-term",t);
+ break;
+ case BVCONST:
+ OutputNode = t;
+ break;
+ case BVNEG:{
+ //AARON
+ if (iii != One) free(iii);
+ //AARON
+
+ iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+ CONSTANTBV::Set_Complement(output,iii);
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+ OutputNode = CreateBVConst(cccc,2);
+ break;
+ }
+ case BVSX: {
+ unsigned * out0 = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+ unsigned t0_width = t[0].GetValueWidth();
+ if(inputwidth == t0_width) {
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(out0);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ CONSTANTBV::BitVector_Destroy(out0);
+ }
+ else {
+ // FIXME: (Dill) I'm guessing that BitVector sign returns 1 if the
+ // number is positive, 0 if 0, and -1 if negative. But I'm only
+ // guessing.
+ signed int topbit_sign = (CONSTANTBV::BitVector_Sign(out0) < 0);
+ //out1 is the sign-extension bits
+ unsigned * out1 = CONSTANTBV::BitVector_Create(inputwidth-t0_width,true);
+ if(topbit_sign)
+ CONSTANTBV::BitVector_Fill(out1);
+
+ //AARON
+ CONSTANTBV::BitVector_Destroy(output);
+ //AARON
+
+ output = CONSTANTBV::BitVector_Concat(out1,out0);
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ CONSTANTBV::BitVector_Destroy(out0);
+ CONSTANTBV::BitVector_Destroy(out1);
+ }
+ break;
+ }
+ case BVAND: {
+ CONSTANTBV::Set_Intersection(output,iii,jjj);
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ break;
+ }
+ case BVOR: {
+ CONSTANTBV::Set_Union(output,iii,jjj);
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ break;
+ }
+ case BVXOR: {
+ CONSTANTBV::Set_ExclusiveOr(output,iii,jjj);
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ break;
+ }
+ case BVSUB: {
+ bool carry = false;
+ CONSTANTBV::BitVector_sub(output,iii,jjj,&carry);
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ break;
+ }
+ case BVUMINUS: {
+ bool carry = false;
+
+ //AARON
+ if (iii != One) free(iii);
+ //AARON
+
+ iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+ CONSTANTBV::Set_Complement(output,iii);
+ CONSTANTBV::BitVector_add(output,output,One,&carry);
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ break;
+ }
+ case BVEXTRACT: {
+ string s(BVConstEvaluator(t[0]).GetBVConst());
+ unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+ unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+
+ //length of substr to chop
+ unsigned int len = hi-low+1;
+ //distance from MSB
+ hi = s.size()-1 - hi;
+ string ss = s.substr(hi,len);
+ OutputNode = CreateBVConst(ss.c_str(),2);
+ break;
+ }
+ case BVCONCAT: {
+ string s(BVConstEvaluator(t[0]).GetBVConst());
+ string r(BVConstEvaluator(t[1]).GetBVConst());
+
+ string q(s+r);
+ OutputNode = CreateBVConst(q.c_str(),2);
+ break;
+ }
+ case BVMULT: {
+ unsigned * output1 = CONSTANTBV::BitVector_Create(2*inputwidth,true);
+ CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(output1,iii,jjj);
+ //error printing
+ if(0 != e) {
+ std::string ss("BVConstEvaluator:");
+ ss += (const char*)BitVector_Error(e);
+ //destroy all the CONSTANTBV bitvectors
+ CONSTANTBV::BitVector_Destroy(iii);
+ CONSTANTBV::BitVector_Destroy(jjj);
+ CONSTANTBV::BitVector_Destroy(One);
+ CONSTANTBV::BitVector_Destroy(Zero);
+ FatalError(ss.c_str(), t);
+ }
+
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output1);
+ std::string s(cccc);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ s = s.substr(inputwidth,inputwidth);
+ OutputNode = CreateBVConst(s.c_str(),2);
+ CONSTANTBV::BitVector_Destroy(output1);
+ break;
+ }
+ case BVPLUS: {
+ bool carry = false;
+ ASTVec c = t.GetChildren();
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ unsigned int * kk = ConvertToCONSTANTBV(BVConstEvaluator(*it).GetBVConst());
+ CONSTANTBV::BitVector_add(output,output,kk,&carry);
+ carry = false;
+ CONSTANTBV::BitVector_Destroy(kk);
+ }
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ //AARON
+
+ break;
+ }
+ case SBVDIV:
+ case SBVREM: {
+ OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
+ break;
+ }
+ case BVDIV: {
+ unsigned * quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
+ unsigned * remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
+ // iii is dividend, jjj is the divisor
+ CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient,iii,jjj,remainder);
+
+ if(0 != e) {
+ //error printing
+ if(counterexample_checking_during_refinement) {
+ OutputNode = CreateZeroConst(inputwidth);
+ bvdiv_exception_occured = true;
+ break;
+ }
+ else {
+ std::string ss("BVConstEvaluator:");
+ ss += (const char*)BitVector_Error(e);
+ //destroy all the CONSTANTBV bitvectors
+ CONSTANTBV::BitVector_Destroy(iii);
+ CONSTANTBV::BitVector_Destroy(jjj);
+ CONSTANTBV::BitVector_Destroy(One);
+ CONSTANTBV::BitVector_Destroy(Zero);
+
+ //AARON
+ iii = jjj = One = Zero = NULL;
+ //AARON
+
+ FatalError(ss.c_str(), t);
+ }
+ } //end of error printing
+
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(quotient);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ CONSTANTBV::BitVector_Destroy(quotient);
+ CONSTANTBV::BitVector_Destroy(remainder);
+ //AARON
+
+ break;
+ }
+ case BVMOD: {
+ unsigned * quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
+ unsigned * remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
+ // iii is dividend, jjj is the divisor
+ CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient,iii,jjj,remainder);
+
+ if(0 != e) {
+ //error printing
+ if(counterexample_checking_during_refinement) {
+ OutputNode = CreateZeroConst(inputwidth);
+ bvdiv_exception_occured = true;
+ break;
+ }
+ else {
+ std::string ss("BVConstEvaluator:");
+ ss += (const char*)BitVector_Error(e);
+ //destroy all the CONSTANTBV bitvectors
+ CONSTANTBV::BitVector_Destroy(iii);
+ CONSTANTBV::BitVector_Destroy(jjj);
+ CONSTANTBV::BitVector_Destroy(One);
+ CONSTANTBV::BitVector_Destroy(Zero);
+
+ //AARON
+ iii = jjj = One = Zero = NULL;
+ //AARON
+
+ FatalError(ss.c_str(), t);
+ }
+ } //end of errory printing
+
+ cccc = (char *)CONSTANTBV::BitVector_to_Bin(remainder);
+ OutputNode = CreateBVConst(cccc,2);
+
+ //AARON
+ free(cccc);
+ CONSTANTBV::BitVector_Destroy(quotient);
+ CONSTANTBV::BitVector_Destroy(remainder);
+ //AARON
+
+ break;
+ }
+ case ITE:
+ if(ASTTrue == t[0])
+ OutputNode = BVConstEvaluator(t[1]);
+ else if(ASTFalse == t[0])
+ OutputNode = BVConstEvaluator(t[2]);
+ else
+ FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t);
+ break;
+ case EQ:
+ if(CONSTANTBV::BitVector_equal(iii,jjj))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case NEQ:
+ if(!CONSTANTBV::BitVector_equal(iii,jjj))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVLT:
+ if(-1 == CONSTANTBV::BitVector_Lexicompare(iii,jjj))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVLE: {
+ int comp = CONSTANTBV::BitVector_Lexicompare(iii,jjj);
+ if(comp <= 0)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVGT:
+ if(1 == CONSTANTBV::BitVector_Lexicompare(iii,jjj))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVGE: {
+ int comp = CONSTANTBV::BitVector_Lexicompare(iii,jjj);
+ if(comp >= 0)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVSLT:
+ if(-1 == CONSTANTBV::BitVector_Compare(iii,jjj))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVSLE: {
+ signed int comp = CONSTANTBV::BitVector_Compare(iii,jjj);
+ if(comp <= 0)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ case BVSGT:
+ if(1 == CONSTANTBV::BitVector_Compare(iii,jjj))
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ case BVSGE: {
+ int comp = CONSTANTBV::BitVector_Compare(iii,jjj);
+ if(comp >= 0)
+ OutputNode = ASTTrue;
+ else
+ OutputNode = ASTFalse;
+ break;
+ }
+ default:
+ FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
+ break;
+ }
+
+
+
+ // //destroy all the CONSTANTBV bitvectors
+ // CONSTANTBV::BitVector_Destroy(iii);
+ // CONSTANTBV::BitVector_Destroy(jjj);
+ // CONSTANTBV::BitVector_Destroy(output);
+
+ // if(k == BVNEG || k == BVUMINUS)
+ // CONSTANTBV::BitVector_Destroy(One);
+ // else if(k == BVAND || k == BVOR || k == BVXOR || k == BVSUB ||
+ // k == BVMULT || k == EQ || k == NEQ || k == BVLT ||
+ // k == BVLE || k == BVGT || k == BVGE || k == BVSLT ||
+ // k == BVSLE || k == BVSGT || k == BVSGE) {
+ // CONSTANTBV::BitVector_Destroy(One);
+ // CONSTANTBV::BitVector_Destroy(Zero);
+ // }
+
+ //AARON
+ if (output != NULL) CONSTANTBV::BitVector_Destroy(output);
+ if (One != NULL) CONSTANTBV::BitVector_Destroy(One);
+ if (Zero != NULL) CONSTANTBV::BitVector_Destroy(Zero);
+ if (iii != NULL && iii != One) CONSTANTBV::BitVector_Destroy(iii);
+ if (jjj != NULL && jjj != Zero) CONSTANTBV::BitVector_Destroy(jjj);
+ //AARON
+
+ UpdateSolverMap(t,OutputNode);
+ //UpdateSimplifyMap(t,OutputNode,false);
+ return OutputNode;
+ }
+
+
+ unsigned int * ConvertToCONSTANTBV(const char * s) {
+ unsigned int length = strlen(s);
+ unsigned char * ccc = (unsigned char *)s;
+ unsigned * iii = CONSTANTBV::BitVector_Create(length,true);
+ CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(iii,ccc);
+ //error printing
+ if(0 != e) {
+ cerr << "ConverToCONSTANTBV: wrong bin value: " << BitVector_Error(e);
+ FatalError("");
+ }
+
+ return iii;
+ }
+ */
+}
+; //end of namespace BEEV
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="1">
+<profile kind="CodeFormatterProfile" name="BSD/Allman - without wrapping" version="1">
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.lineSplit" value="150"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_enumerator_list" value="48"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_declarator_list" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration" value="80"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_block" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_expression_list" value="0"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_compact_if" value="0"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration" value="80"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.tabulation.char" value="tab"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_switch" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments" value="do not insert"/>
+</profile>
+</profiles>
#include "../AST/ASTUtil.h"
#include "bvsolver.h"
- //This file contains the implementation of member functions of
- //bvsolver class, which represents the bitvector arithmetic linear
- //solver. Please also refer the STP's CAV 2007 paper for the
- //complete description of the linear solver algorithm
- //
- //The bitvector solver is a partial solver, i.e. it does not solve
- //for all variables in the system of equations. it is
- //best-effort. it relies on the SAT solver to be complete.
- //
- //The BVSolver assumes that the input equations are normalized, and
- //have liketerms combined etc.
- //
- //0. Traverse top-down over the input DAG, looking for a conjunction
- //0. of equations. if you find one, then for each equation in the
- //0. conjunction, do the following steps.
- //
- //1. check for Linearity of the input equation
- //
- //2. Solve for a "chosen" variable. The variable should occur
- //2. exactly once and must have an odd coeff. Refer STP's CAV 2007
- //2. paper for actual solving procedure
- //
- //4. Outside the solver, Substitute and Re-normalize the input DAG
-namespace BEEV {
- //check the solver map for 'key'. If key is present, then return the
- //value by reference in the argument 'output'
- bool BVSolver::CheckAlreadySolvedMap(const ASTNode& key, ASTNode& output) {
- ASTNodeMap::iterator it;
- if((it = FormulasAlreadySolvedMap.find(key)) != FormulasAlreadySolvedMap.end()) {
- output = it->second;
- return true;
- }
- return false;
- } //CheckAlreadySolvedMap()
-
- void BVSolver::UpdateAlreadySolvedMap(const ASTNode& key, const ASTNode& value) {
- FormulasAlreadySolvedMap[key] = value;
- } //end of UpdateAlreadySolvedMap()
-
- //FIXME This is doing way more arithmetic than it needs to.
- //accepts an even number "in", and splits it into an odd number and
- //a power of 2. i.e " in = b.(2^k) ". returns the odd number, and
- //the power of two by reference
- ASTNode BVSolver::SplitEven_into_Oddnum_PowerOf2(const ASTNode& in,
- unsigned int& number_shifts) {
- if(BVCONST != in.GetKind() || _bm->BVConstIsOdd(in)) {
- FatalError("BVSolver:SplitNum_Odd_PowerOf2: input must be a BVCONST and even\n",in);
- }
-
- unsigned int len = in.GetValueWidth();
- ASTNode zero = _bm->CreateZeroConst(len);
- ASTNode two = _bm->CreateTwoConst(len);
- ASTNode div_by_2 = in;
- ASTNode mod_by_2 =
- _bm->BVConstEvaluator(_bm->CreateTerm(BVMOD,len,div_by_2,two));
- while(mod_by_2 == zero) {
- div_by_2 =
- _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,div_by_2,two));
- number_shifts++;
- mod_by_2 =
- _bm->BVConstEvaluator(_bm->CreateTerm(BVMOD,len,div_by_2,two));
- }
- return div_by_2;
- } //end of SplitEven_into_Oddnum_PowerOf2()
-
- //Checks if there are any ARRAYREADS in the term, after the
- //alreadyseenmap is cleared, i.e. traversing a new term altogether
- bool BVSolver::CheckForArrayReads_TopLevel(const ASTNode& term) {
- TermsAlreadySeenMap.clear();
- return CheckForArrayReads(term);
- }
-
- //Checks if there are any ARRAYREADS in the term
- bool BVSolver::CheckForArrayReads(const ASTNode& term) {
- ASTNode a = term;
- ASTNodeMap::iterator it;
- if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
- //if the term has been seen, then simply return true, else
- //return false
- if(ASTTrue == (it->second)) {
- return true;
- }
- else {
+//This file contains the implementation of member functions of
+//bvsolver class, which represents the bitvector arithmetic linear
+//solver. Please also refer the STP's CAV 2007 paper for the
+//complete description of the linear solver algorithm
+//
+//The bitvector solver is a partial solver, i.e. it does not solve
+//for all variables in the system of equations. it is
+//best-effort. it relies on the SAT solver to be complete.
+//
+//The BVSolver assumes that the input equations are normalized, and
+//have liketerms combined etc.
+//
+//0. Traverse top-down over the input DAG, looking for a conjunction
+//0. of equations. if you find one, then for each equation in the
+//0. conjunction, do the following steps.
+//
+//1. check for Linearity of the input equation
+//
+//2. Solve for a "chosen" variable. The variable should occur
+//2. exactly once and must have an odd coeff. Refer STP's CAV 2007
+//2. paper for actual solving procedure
+//
+//4. Outside the solver, Substitute and Re-normalize the input DAG
+namespace BEEV
+{
+//check the solver map for 'key'. If key is present, then return the
+//value by reference in the argument 'output'
+bool BVSolver::CheckAlreadySolvedMap(const ASTNode& key, ASTNode& output)
+{
+ ASTNodeMap::iterator it;
+ if ((it = FormulasAlreadySolvedMap.find(key)) != FormulasAlreadySolvedMap.end())
+ {
+ output = it->second;
+ return true;
+ }
return false;
- }
- }
-
- switch(term.GetKind()) {
- case READ:
- //an array read has been seen. Make an entry in the map and
- //return true
- TermsAlreadySeenMap[term] = ASTTrue;
- return true;
- default: {
- ASTVec c = term.GetChildren();
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- if(CheckForArrayReads(*it)) {
- return true;
+} //CheckAlreadySolvedMap()
+
+void BVSolver::UpdateAlreadySolvedMap(const ASTNode& key, const ASTNode& value)
+{
+ FormulasAlreadySolvedMap[key] = value;
+} //end of UpdateAlreadySolvedMap()
+
+//FIXME This is doing way more arithmetic than it needs to.
+//accepts an even number "in", and splits it into an odd number and
+//a power of 2. i.e " in = b.(2^k) ". returns the odd number, and
+//the power of two by reference
+ASTNode BVSolver::SplitEven_into_Oddnum_PowerOf2(const ASTNode& in, unsigned int& number_shifts)
+{
+ if (BVCONST != in.GetKind() || _bm->BVConstIsOdd(in))
+ {
+ FatalError("BVSolver:SplitNum_Odd_PowerOf2: input must be a BVCONST and even\n", in);
}
- }
- break;
- }
- }
-
- //If control is here, then it means that no arrayread was seen for
- //the input 'term'. Make an entry in the map with the term as key
- //and FALSE as value.
- TermsAlreadySeenMap[term] = ASTFalse;
- return false;
- } //end of CheckForArrayReads()
-
- //check the solver map for 'key'. If key is present, then return the
- //value by reference in the argument 'output'
- bool BeevMgr::CheckSolverMap(const ASTNode& key, ASTNode& output) {
- ASTNodeMap::iterator it;
- if((it = SolverMap.find(key)) != SolverMap.end()) {
- output = it->second;
- return true;
- }
- return false;
- } //end of CheckSolverMap()
-
- bool BeevMgr::CheckSolverMap(const ASTNode& key) {
- if(SolverMap.find(key) != SolverMap.end())
- return true;
- else
- return false;
- } //end of CheckSolverMap()
-
- //update solvermap with (key,value) pair
- bool BeevMgr::UpdateSolverMap(const ASTNode& key, const ASTNode& value) {
- ASTNode var = (BVEXTRACT == key.GetKind()) ? key[0] : key;
- if(!CheckSolverMap(var) && key != value) {
- SolverMap[key] = value;
- return true;
- }
- return false;
- } //end of UpdateSolverMap()
-
- //collects the vars in the term 'lhs' into the multiset Vars
- void BVSolver::VarsInTheTerm_TopLevel(const ASTNode& lhs, ASTNodeMultiSet& Vars) {
- TermsAlreadySeenMap.clear();
- VarsInTheTerm(lhs,Vars);
- }
-
- //collects the vars in the term 'lhs' into the multiset Vars
- void BVSolver::VarsInTheTerm(const ASTNode& term, ASTNodeMultiSet& Vars) {
- ASTNode a = term;
- ASTNodeMap::iterator it;
- if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
- //if the term has been seen, then simply return
- return;
- }
-
- switch(term.GetKind()) {
- case BVCONST:
- return;
- case SYMBOL:
- //cerr << "debugging: symbol added: " << term << endl;
- Vars.insert(term);
- break;
- case READ:
- //skip the arrayname, provided the arrayname is a SYMBOL
- if(SYMBOL == term[0].GetKind()) {
- VarsInTheTerm(term[1],Vars);
- }
- else {
- VarsInTheTerm(term[0],Vars);
- VarsInTheTerm(term[1],Vars);
- }
- break;
- default: {
- ASTVec c = term.GetChildren();
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- VarsInTheTerm(*it,Vars);
- }
- break;
- }
- }
-
- //ensures that you don't double count. if you have seen the term
- //once, then memoize
- TermsAlreadySeenMap[term] = ASTTrue;
- return;
- } //end of VarsInTheTerm()
-
- bool BVSolver::DoNotSolveThis(const ASTNode& var) {
- if(DoNotSolve_TheseVars.find(var) != DoNotSolve_TheseVars.end()) {
- return true;
- }
- return false;
- }
-
- //chooses a variable in the lhs and returns the chosen variable
- ASTNode BVSolver::ChooseMonom(const ASTNode& eq, ASTNode& modifiedlhs) {
- if(!(EQ == eq.GetKind() && BVPLUS == eq[0].GetKind())) {
- FatalError("ChooseMonom: input must be a EQ",eq);
- }
-
- ASTNode lhs = eq[0];
- ASTNode rhs = eq[1];
- ASTNode zero = _bm->CreateZeroConst(32);
-
- //collect all the vars in the lhs and rhs
- ASTNodeMultiSet Vars;
- VarsInTheTerm_TopLevel(lhs,Vars);
-
- //handle BVPLUS case
- ASTVec c = lhs.GetChildren();
- ASTVec o;
- ASTNode outmonom = _bm->CreateNode(UNDEFINED);
- bool chosen_symbol = false;
- bool chosen_odd = false;
-
- //choose variables with no coeffs
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode monom = *it;
- if(SYMBOL == monom.GetKind() &&
- Vars.count(monom) == 1 &&
- !_bm->VarSeenInTerm(monom,rhs) &&
- !DoNotSolveThis(monom) &&
- !chosen_symbol) {
- outmonom = monom;
- chosen_symbol = true;
- }
- else if(BVUMINUS == monom.GetKind() &&
- SYMBOL == monom[0].GetKind() &&
- Vars.count(monom[0]) == 1 &&
- !DoNotSolveThis(monom[0]) &&
- !_bm->VarSeenInTerm(monom[0],rhs) &&
- !chosen_symbol) {
- //cerr << "Chosen Monom: " << monom << endl;
- outmonom = monom;
- chosen_symbol = true;
- }
- else {
- o.push_back(monom);
- }
- }
-
- //try to choose only odd coeffed variables first
- if(!chosen_symbol) {
- o.clear();
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode monom = *it;
- ASTNode var = (BVMULT == monom.GetKind()) ? monom[1] : _bm->CreateNode(UNDEFINED);
-
- if(BVMULT == monom.GetKind() &&
- BVCONST == monom[0].GetKind() &&
- _bm->BVConstIsOdd(monom[0]) &&
- ((SYMBOL == var.GetKind() &&
- Vars.count(var) == 1)
- ||
- (BVEXTRACT == var.GetKind() &&
- SYMBOL == var[0].GetKind() &&
- BVCONST == var[1].GetKind() &&
- zero == var[2] &&
- !_bm->VarSeenInTerm(var[0],rhs) &&
- !DoNotSolveThis(var[0]))
- ) &&
- !DoNotSolveThis(var) &&
- !_bm->VarSeenInTerm(var,rhs) &&
- !chosen_odd) {
- //monom[0] is odd.
- outmonom = monom;
- chosen_odd = true;
+
+ unsigned int len = in.GetValueWidth();
+ ASTNode zero = _bm->CreateZeroConst(len);
+ ASTNode two = _bm->CreateTwoConst(len);
+ ASTNode div_by_2 = in;
+ ASTNode mod_by_2 = _bm->BVConstEvaluator(_bm->CreateTerm(BVMOD, len, div_by_2, two));
+ while (mod_by_2 == zero)
+ {
+ div_by_2 = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV, len, div_by_2, two));
+ number_shifts++;
+ mod_by_2 = _bm->BVConstEvaluator(_bm->CreateTerm(BVMOD, len, div_by_2, two));
}
- else {
- o.push_back(monom);
+ return div_by_2;
+} //end of SplitEven_into_Oddnum_PowerOf2()
+
+//Checks if there are any ARRAYREADS in the term, after the
+//alreadyseenmap is cleared, i.e. traversing a new term altogether
+bool BVSolver::CheckForArrayReads_TopLevel(const ASTNode& term)
+{
+ TermsAlreadySeenMap.clear();
+ return CheckForArrayReads(term);
+}
+
+//Checks if there are any ARRAYREADS in the term
+bool BVSolver::CheckForArrayReads(const ASTNode& term)
+{
+ ASTNode a = term;
+ ASTNodeMap::iterator it;
+ if ((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end())
+ {
+ //if the term has been seen, then simply return true, else
+ //return false
+ if (ASTTrue == (it->second))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
- }
- }
-
- modifiedlhs = (o.size() > 1) ? _bm->CreateTerm(BVPLUS,lhs.GetValueWidth(),o) : o[0];
- return outmonom;
- } //end of choosemonom()
-
- //solver function which solves for variables with odd coefficient
- ASTNode BVSolver::BVSolve_Odd(const ASTNode& input) {
- ASTNode eq = input;
- //cerr << "Input to BVSolve_Odd()" << eq << endl;
- if(!(wordlevel_solve && EQ == eq.GetKind())) {
- return input;
- }
-
- ASTNode output = input;
- if(CheckAlreadySolvedMap(input,output)) {
- return output;
- }
-
- //get the lhs and the rhs, and case-split on the lhs kind
- ASTNode lhs = eq[0];
- ASTNode rhs = eq[1];
- if(BVPLUS == lhs.GetKind()) {
- ASTNode chosen_monom = _bm->CreateNode(UNDEFINED);
- ASTNode leftover_lhs;
-
- //choose monom makes sure that it gets only those vars that
- //occur exactly once in lhs and rhs put together
- chosen_monom = ChooseMonom(eq, leftover_lhs);
- if(chosen_monom == _bm->CreateNode(UNDEFINED)) {
- //no monomial was chosen
- return eq;
- }
-
- //if control is here then it means that a monom was chosen
- //
- //construct: rhs - (lhs without the chosen monom)
- unsigned int len = lhs.GetValueWidth();
- leftover_lhs = _bm->SimplifyTerm_TopLevel(_bm->CreateTerm(BVUMINUS,len,leftover_lhs));
- ASTNode newrhs = _bm->SimplifyTerm(_bm->CreateTerm(BVPLUS,len,rhs,leftover_lhs));
- lhs = chosen_monom;
- rhs = newrhs;
- } //end of if(BVPLUS ...)
-
- if(BVUMINUS == lhs.GetKind()) {
- //equation is of the form (-lhs0) = rhs
- ASTNode lhs0 = lhs[0];
- rhs = _bm->SimplifyTerm(_bm->CreateTerm(BVUMINUS,rhs.GetValueWidth(),rhs));
- lhs = lhs0;
- }
-
- switch(lhs.GetKind()) {
- case SYMBOL: {
- //input is of the form x = rhs first make sure that the lhs
- //symbol does not occur on the rhs or that it has not been
- //solved for
- if(_bm->VarSeenInTerm(lhs,rhs)) {
- //found the lhs in the rhs. Abort!
- DoNotSolve_TheseVars.insert(lhs);
- return eq;
- }
-
- //rhs should not have arrayreads in it. it complicates matters
- //during transformation
- // if(CheckForArrayReads_TopLevel(rhs)) {
- // return eq;
- // }
-
- DoNotSolve_TheseVars.insert(lhs);
- if(!_bm->UpdateSolverMap(lhs,rhs)) {
- return eq;
- }
-
- output = ASTTrue;
- break;
- }
- case BVEXTRACT: {
- ASTNode zero = _bm->CreateZeroConst(32);
-
- if(!(SYMBOL == lhs[0].GetKind() &&
- BVCONST == lhs[1].GetKind() &&
- zero == lhs[2] &&
- !_bm->VarSeenInTerm(lhs[0],rhs) &&
- !DoNotSolveThis(lhs[0]))) {
- return eq;
- }
-
- if(_bm->VarSeenInTerm(lhs[0],rhs)) {
- DoNotSolve_TheseVars.insert(lhs[0]);
- return eq;
- }
-
- DoNotSolve_TheseVars.insert(lhs[0]);
- if(!_bm->UpdateSolverMap(lhs,rhs)) {
- return eq;
- }
-
- //if the extract of x[i:0] = t is entered into the solvermap,
- //then also add another entry for x = x1@t
- ASTNode var = lhs[0];
- ASTNode newvar = NewVar(var.GetValueWidth() - lhs.GetValueWidth());
- newvar = _bm->CreateTerm(BVCONCAT,var.GetValueWidth(),newvar,rhs);
- _bm->UpdateSolverMap(var,newvar);
- output = ASTTrue;
- break;
- }
- case BVMULT: {
- //the input is of the form a*x = t. If 'a' is odd, then compute
- //its multiplicative inverse a^-1, multiply 't' with it, and
- //update the solver map
- if(BVCONST != lhs[0].GetKind()) {
- return eq;
- }
-
- if(!(SYMBOL == lhs[1].GetKind() ||
- (BVEXTRACT == lhs[1].GetKind() &&
- SYMBOL == lhs[1][0].GetKind()))) {
- return eq;
- }
- bool ChosenVar_Is_Extract = (BVEXTRACT == lhs[1].GetKind()) ? true : false;
+ switch (term.GetKind())
+ {
+ case READ:
+ //an array read has been seen. Make an entry in the map and
+ //return true
+ TermsAlreadySeenMap[term] = ASTTrue;
+ return true;
+ default:
+ {
+ ASTVec c = term.GetChildren();
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ if (CheckForArrayReads(*it))
+ {
+ return true;
+ }
+ }
+ break;
+ }
+ }
- //if coeff is even, then we know that all the coeffs in the eqn
- //are even. Simply return the eqn
- if(!_bm->BVConstIsOdd(lhs[0])) {
- return eq;
- }
-
- ASTNode a = _bm->MultiplicativeInverse(lhs[0]);
- ASTNode chosenvar = (BVEXTRACT == lhs[1].GetKind()) ? lhs[1][0] : lhs[1];
- ASTNode chosenvar_value =
- _bm->SimplifyTerm(_bm->CreateTerm(BVMULT,rhs.GetValueWidth(),a,rhs));
-
- //if chosenvar is seen in chosenvar_value then abort
- if(_bm->VarSeenInTerm(chosenvar,chosenvar_value)) {
- //abort solving
- DoNotSolve_TheseVars.insert(lhs);
- return eq;
- }
-
- //rhs should not have arrayreads in it. it complicates matters
- //during transformation
- // if(CheckForArrayReads_TopLevel(chosenvar_value)) {
- // return eq;
- // }
-
- //found a variable to solve
- DoNotSolve_TheseVars.insert(chosenvar);
- chosenvar = lhs[1];
- if(!_bm->UpdateSolverMap(chosenvar,chosenvar_value)) {
- return eq;
- }
-
- if(ChosenVar_Is_Extract) {
- ASTNode var = lhs[1][0];
- ASTNode newvar = NewVar(var.GetValueWidth() - lhs[1].GetValueWidth());
- newvar = _bm->CreateTerm(BVCONCAT,var.GetValueWidth(),newvar,chosenvar_value);
- _bm->UpdateSolverMap(var,newvar);
- }
- output = ASTTrue;
- break;
- }
- default:
- output = eq;
- break;
- }
-
- UpdateAlreadySolvedMap(input,output);
- return output;
- } //end of BVSolve_Odd()
-
- //Create a new variable of ValueWidth 'n'
- ASTNode BVSolver::NewVar(unsigned int n) {
- std:: string c("v");
- char d[32];
- sprintf(d,"%d",_symbol_count++);
- std::string ccc(d);
- c += "_solver_" + ccc;
-
- ASTNode CurrentSymbol = _bm->CreateSymbol(c.c_str());
- CurrentSymbol.SetValueWidth(n);
- CurrentSymbol.SetIndexWidth(0);
- return CurrentSymbol;
- } //end of NewVar()
-
- //The toplevel bvsolver(). Checks if the formula has already been
- //solved. If not, the solver() is invoked. If yes, then simply drop
- //the formula
- ASTNode BVSolver::TopLevelBVSolve(const ASTNode& input) {
- if(!wordlevel_solve) {
- return input;
- }
-
- Kind k = input.GetKind();
- if(!(EQ == k || AND == k)) {
- return input;
- }
-
- ASTNode output = input;
- if(CheckAlreadySolvedMap(input,output)) {
- //output is TRUE. The formula is thus dropped
- return output;
- }
- ASTVec o;
- ASTVec c;
- if(EQ == k)
- c.push_back(input);
- else
- c = input.GetChildren();
- ASTVec eveneqns;
- ASTNode solved = ASTFalse;
- for(ASTVec::iterator it = c.begin(), itend = c.end();it != itend;it++) {
- //_bm->ASTNodeStats("Printing before calling simplifyformula inside the solver:", *it);
- ASTNode aaa = (ASTTrue == solved && EQ == it->GetKind()) ? _bm->SimplifyFormula(*it,false) : *it;
- //ASTNode aaa = *it;
- //_bm->ASTNodeStats("Printing after calling simplifyformula inside the solver:", aaa);
- aaa = BVSolve_Odd(aaa);
- //_bm->ASTNodeStats("Printing after oddsolver:", aaa);
- bool even = false;
- aaa = CheckEvenEqn(aaa, even);
- if(even) {
- eveneqns.push_back(aaa);
- }
- else {
- if(ASTTrue != aaa) {
- o.push_back(aaa);
+ //If control is here, then it means that no arrayread was seen for
+ //the input 'term'. Make an entry in the map with the term as key
+ //and FALSE as value.
+ TermsAlreadySeenMap[term] = ASTFalse;
+ return false;
+} //end of CheckForArrayReads()
+
+//check the solver map for 'key'. If key is present, then return the
+//value by reference in the argument 'output'
+bool BeevMgr::CheckSolverMap(const ASTNode& key, ASTNode& output)
+{
+ ASTNodeMap::iterator it;
+ if ((it = SolverMap.find(key)) != SolverMap.end())
+ {
+ output = it->second;
+ return true;
+ }
+ return false;
+} //end of CheckSolverMap()
+
+bool BeevMgr::CheckSolverMap(const ASTNode& key)
+{
+ if (SolverMap.find(key) != SolverMap.end())
+ return true;
+ else
+ return false;
+} //end of CheckSolverMap()
+
+//update solvermap with (key,value) pair
+bool BeevMgr::UpdateSolverMap(const ASTNode& key, const ASTNode& value)
+{
+ ASTNode var = (BVEXTRACT == key.GetKind()) ? key[0] : key;
+ if (!CheckSolverMap(var) && key != value)
+ {
+ SolverMap[key] = value;
+ return true;
+ }
+ return false;
+} //end of UpdateSolverMap()
+
+//collects the vars in the term 'lhs' into the multiset Vars
+void BVSolver::VarsInTheTerm_TopLevel(const ASTNode& lhs, ASTNodeMultiSet& Vars)
+{
+ TermsAlreadySeenMap.clear();
+ VarsInTheTerm(lhs, Vars);
+}
+
+//collects the vars in the term 'lhs' into the multiset Vars
+void BVSolver::VarsInTheTerm(const ASTNode& term, ASTNodeMultiSet& Vars)
+{
+ ASTNode a = term;
+ ASTNodeMap::iterator it;
+ if ((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end())
+ {
+ //if the term has been seen, then simply return
+ return;
+ }
+
+ switch (term.GetKind())
+ {
+ case BVCONST:
+ return;
+ case SYMBOL:
+ //cerr << "debugging: symbol added: " << term << endl;
+ Vars.insert(term);
+ break;
+ case READ:
+ //skip the arrayname, provided the arrayname is a SYMBOL
+ if (SYMBOL == term[0].GetKind())
+ {
+ VarsInTheTerm(term[1], Vars);
+ }
+ else
+ {
+ VarsInTheTerm(term[0], Vars);
+ VarsInTheTerm(term[1], Vars);
+ }
+ break;
+ default:
+ {
+ ASTVec c = term.GetChildren();
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ VarsInTheTerm(*it, Vars);
+ }
+ break;
+ }
+ }
+
+ //ensures that you don't double count. if you have seen the term
+ //once, then memoize
+ TermsAlreadySeenMap[term] = ASTTrue;
+ return;
+} //end of VarsInTheTerm()
+
+bool BVSolver::DoNotSolveThis(const ASTNode& var)
+{
+ if (DoNotSolve_TheseVars.find(var) != DoNotSolve_TheseVars.end())
+ {
+ return true;
+ }
+ return false;
+}
+
+//chooses a variable in the lhs and returns the chosen variable
+ASTNode BVSolver::ChooseMonom(const ASTNode& eq, ASTNode& modifiedlhs)
+{
+ if (!(EQ == eq.GetKind() && BVPLUS == eq[0].GetKind()))
+ {
+ FatalError("ChooseMonom: input must be a EQ", eq);
+ }
+
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ ASTNode zero = _bm->CreateZeroConst(32);
+
+ //collect all the vars in the lhs and rhs
+ ASTNodeMultiSet Vars;
+ VarsInTheTerm_TopLevel(lhs, Vars);
+
+ //handle BVPLUS case
+ ASTVec c = lhs.GetChildren();
+ ASTVec o;
+ ASTNode outmonom = _bm->CreateNode(UNDEFINED);
+ bool chosen_symbol = false;
+ bool chosen_odd = false;
+
+ //choose variables with no coeffs
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode monom = *it;
+ if (SYMBOL == monom.GetKind() && Vars.count(monom) == 1 && !_bm->VarSeenInTerm(monom, rhs) && !DoNotSolveThis(monom) && !chosen_symbol)
+ {
+ outmonom = monom;
+ chosen_symbol = true;
+ }
+ else if (BVUMINUS == monom.GetKind() && SYMBOL == monom[0].GetKind() && Vars.count(monom[0]) == 1 && !DoNotSolveThis(monom[0])
+ && !_bm->VarSeenInTerm(monom[0], rhs) && !chosen_symbol)
+ {
+ //cerr << "Chosen Monom: " << monom << endl;
+ outmonom = monom;
+ chosen_symbol = true;
+ }
+ else
+ {
+ o.push_back(monom);
+ }
+ }
+
+ //try to choose only odd coeffed variables first
+ if (!chosen_symbol)
+ {
+ o.clear();
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode monom = *it;
+ ASTNode var = (BVMULT == monom.GetKind()) ? monom[1] : _bm->CreateNode(UNDEFINED);
+
+ if (BVMULT == monom.GetKind() && BVCONST == monom[0].GetKind() && _bm->BVConstIsOdd(monom[0]) && ((SYMBOL == var.GetKind() && Vars.count(
+ var) == 1) || (BVEXTRACT == var.GetKind() && SYMBOL == var[0].GetKind() && BVCONST == var[1].GetKind() && zero == var[2]
+ && !_bm->VarSeenInTerm(var[0], rhs) && !DoNotSolveThis(var[0]))) && !DoNotSolveThis(var) && !_bm->VarSeenInTerm(var, rhs)
+ && !chosen_odd)
+ {
+ //monom[0] is odd.
+ outmonom = monom;
+ chosen_odd = true;
+ }
+ else
+ {
+ o.push_back(monom);
+ }
+ }
+ }
+
+ modifiedlhs = (o.size() > 1) ? _bm->CreateTerm(BVPLUS, lhs.GetValueWidth(), o) : o[0];
+ return outmonom;
+} //end of choosemonom()
+
+//solver function which solves for variables with odd coefficient
+ASTNode BVSolver::BVSolve_Odd(const ASTNode& input)
+{
+ ASTNode eq = input;
+ //cerr << "Input to BVSolve_Odd()" << eq << endl;
+ if (!(wordlevel_solve && EQ == eq.GetKind()))
+ {
+ return input;
}
- }
- solved = aaa;
- }
-
- ASTNode evens;
- if(eveneqns.size() > 0) {
- //if there is a system of even equations then solve them
- evens = (eveneqns.size() > 1) ? _bm->CreateNode(AND,eveneqns) : eveneqns[0];
- //evens = _bm->SimplifyFormula(evens,false);
- evens = BVSolve_Even(evens);
- _bm->ASTNodeStats("Printing after evensolver:", evens);
- }
- else {
- evens = ASTTrue;
- }
- output = (o.size() > 0) ? ((o.size() > 1) ? _bm->CreateNode(AND,o) : o[0]) : ASTTrue;
- output = _bm->CreateNode(AND,output,evens);
-
- UpdateAlreadySolvedMap(input,output);
- return output;
- } //end of TopLevelBVSolve()
-
- ASTNode BVSolver::CheckEvenEqn(const ASTNode& input, bool& evenflag) {
- ASTNode eq = input;
- //cerr << "Input to BVSolve_Odd()" << eq << endl;
- if(!(wordlevel_solve && EQ == eq.GetKind())) {
- evenflag = false;
- return eq;
- }
-
- ASTNode lhs = eq[0];
- ASTNode rhs = eq[1];
- ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
- //lhs must be a BVPLUS, and rhs must be a BVCONST
- if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
- evenflag = false;
- return eq;
- }
-
- ASTVec lhs_c = lhs.GetChildren();
- ASTNode savetheconst = rhs;
- for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
- ASTNode aaa = *it;
- Kind itk = aaa.GetKind();
-
- if(BVCONST == itk){
- //check later if the constant is even or not
- savetheconst = aaa;
- continue;
- }
-
- if(!(BVMULT == itk &&
- BVCONST == aaa[0].GetKind() &&
- SYMBOL == aaa[1].GetKind() &&
- !_bm->BVConstIsOdd(aaa[0]))) {
- //If the monomials of the lhs are NOT of the form 'a*x' where
- //'a' is even, then return the false
- evenflag = false;
+
+ ASTNode output = input;
+ if (CheckAlreadySolvedMap(input, output))
+ {
+ return output;
+ }
+
+ //get the lhs and the rhs, and case-split on the lhs kind
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ if (BVPLUS == lhs.GetKind())
+ {
+ ASTNode chosen_monom = _bm->CreateNode(UNDEFINED);
+ ASTNode leftover_lhs;
+
+ //choose monom makes sure that it gets only those vars that
+ //occur exactly once in lhs and rhs put together
+ chosen_monom = ChooseMonom(eq, leftover_lhs);
+ if (chosen_monom == _bm->CreateNode(UNDEFINED))
+ {
+ //no monomial was chosen
+ return eq;
+ }
+
+ //if control is here then it means that a monom was chosen
+ //
+ //construct: rhs - (lhs without the chosen monom)
+ unsigned int len = lhs.GetValueWidth();
+ leftover_lhs = _bm->SimplifyTerm_TopLevel(_bm->CreateTerm(BVUMINUS, len, leftover_lhs));
+ ASTNode newrhs = _bm->SimplifyTerm(_bm->CreateTerm(BVPLUS, len, rhs, leftover_lhs));
+ lhs = chosen_monom;
+ rhs = newrhs;
+ } //end of if(BVPLUS ...)
+
+ if (BVUMINUS == lhs.GetKind())
+ {
+ //equation is of the form (-lhs0) = rhs
+ ASTNode lhs0 = lhs[0];
+ rhs = _bm->SimplifyTerm(_bm->CreateTerm(BVUMINUS, rhs.GetValueWidth(), rhs));
+ lhs = lhs0;
+ }
+
+ switch (lhs.GetKind())
+ {
+ case SYMBOL:
+ {
+ //input is of the form x = rhs first make sure that the lhs
+ //symbol does not occur on the rhs or that it has not been
+ //solved for
+ if (_bm->VarSeenInTerm(lhs, rhs))
+ {
+ //found the lhs in the rhs. Abort!
+ DoNotSolve_TheseVars.insert(lhs);
+ return eq;
+ }
+
+ //rhs should not have arrayreads in it. it complicates matters
+ //during transformation
+ // if(CheckForArrayReads_TopLevel(rhs)) {
+ // return eq;
+ // }
+
+ DoNotSolve_TheseVars.insert(lhs);
+ if (!_bm->UpdateSolverMap(lhs, rhs))
+ {
+ return eq;
+ }
+
+ output = ASTTrue;
+ break;
+ }
+ case BVEXTRACT:
+ {
+ ASTNode zero = _bm->CreateZeroConst(32);
+
+ if (!(SYMBOL == lhs[0].GetKind() && BVCONST == lhs[1].GetKind() && zero == lhs[2] && !_bm->VarSeenInTerm(lhs[0], rhs) && !DoNotSolveThis(
+ lhs[0])))
+ {
+ return eq;
+ }
+
+ if (_bm->VarSeenInTerm(lhs[0], rhs))
+ {
+ DoNotSolve_TheseVars.insert(lhs[0]);
+ return eq;
+ }
+
+ DoNotSolve_TheseVars.insert(lhs[0]);
+ if (!_bm->UpdateSolverMap(lhs, rhs))
+ {
+ return eq;
+ }
+
+ //if the extract of x[i:0] = t is entered into the solvermap,
+ //then also add another entry for x = x1@t
+ ASTNode var = lhs[0];
+ ASTNode newvar = NewVar(var.GetValueWidth() - lhs.GetValueWidth());
+ newvar = _bm->CreateTerm(BVCONCAT, var.GetValueWidth(), newvar, rhs);
+ _bm->UpdateSolverMap(var, newvar);
+ output = ASTTrue;
+ break;
+ }
+ case BVMULT:
+ {
+ //the input is of the form a*x = t. If 'a' is odd, then compute
+ //its multiplicative inverse a^-1, multiply 't' with it, and
+ //update the solver map
+ if (BVCONST != lhs[0].GetKind())
+ {
+ return eq;
+ }
+
+ if (!(SYMBOL == lhs[1].GetKind() || (BVEXTRACT == lhs[1].GetKind() && SYMBOL == lhs[1][0].GetKind())))
+ {
+ return eq;
+ }
+
+ bool ChosenVar_Is_Extract = (BVEXTRACT == lhs[1].GetKind()) ? true : false;
+
+ //if coeff is even, then we know that all the coeffs in the eqn
+ //are even. Simply return the eqn
+ if (!_bm->BVConstIsOdd(lhs[0]))
+ {
+ return eq;
+ }
+
+ ASTNode a = _bm->MultiplicativeInverse(lhs[0]);
+ ASTNode chosenvar = (BVEXTRACT == lhs[1].GetKind()) ? lhs[1][0] : lhs[1];
+ ASTNode chosenvar_value = _bm->SimplifyTerm(_bm->CreateTerm(BVMULT, rhs.GetValueWidth(), a, rhs));
+
+ //if chosenvar is seen in chosenvar_value then abort
+ if (_bm->VarSeenInTerm(chosenvar, chosenvar_value))
+ {
+ //abort solving
+ DoNotSolve_TheseVars.insert(lhs);
+ return eq;
+ }
+
+ //rhs should not have arrayreads in it. it complicates matters
+ //during transformation
+ // if(CheckForArrayReads_TopLevel(chosenvar_value)) {
+ // return eq;
+ // }
+
+ //found a variable to solve
+ DoNotSolve_TheseVars.insert(chosenvar);
+ chosenvar = lhs[1];
+ if (!_bm->UpdateSolverMap(chosenvar, chosenvar_value))
+ {
+ return eq;
+ }
+
+ if (ChosenVar_Is_Extract)
+ {
+ ASTNode var = lhs[1][0];
+ ASTNode newvar = NewVar(var.GetValueWidth() - lhs[1].GetValueWidth());
+ newvar = _bm->CreateTerm(BVCONCAT, var.GetValueWidth(), newvar, chosenvar_value);
+ _bm->UpdateSolverMap(var, newvar);
+ }
+ output = ASTTrue;
+ break;
+ }
+ default:
+ output = eq;
+ break;
+ }
+
+ UpdateAlreadySolvedMap(input, output);
+ return output;
+} //end of BVSolve_Odd()
+
+//Create a new variable of ValueWidth 'n'
+ASTNode BVSolver::NewVar(unsigned int n)
+{
+ std::string c("v");
+ char d[32];
+ sprintf(d, "%d", _symbol_count++);
+ std::string ccc(d);
+ c += "_solver_" + ccc;
+
+ ASTNode CurrentSymbol = _bm->CreateSymbol(c.c_str());
+ CurrentSymbol.SetValueWidth(n);
+ CurrentSymbol.SetIndexWidth(0);
+ return CurrentSymbol;
+} //end of NewVar()
+
+//The toplevel bvsolver(). Checks if the formula has already been
+//solved. If not, the solver() is invoked. If yes, then simply drop
+//the formula
+ASTNode BVSolver::TopLevelBVSolve(const ASTNode& input)
+{
+ if (!wordlevel_solve)
+ {
+ return input;
+ }
+
+ Kind k = input.GetKind();
+ if (!(EQ == k || AND == k))
+ {
+ return input;
+ }
+
+ ASTNode output = input;
+ if (CheckAlreadySolvedMap(input, output))
+ {
+ //output is TRUE. The formula is thus dropped
+ return output;
+ }
+ ASTVec o;
+ ASTVec c;
+ if (EQ == k)
+ c.push_back(input);
+ else
+ c = input.GetChildren();
+ ASTVec eveneqns;
+ ASTNode solved = ASTFalse;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ //_bm->ASTNodeStats("Printing before calling simplifyformula inside the solver:", *it);
+ ASTNode aaa = (ASTTrue == solved && EQ == it->GetKind()) ? _bm->SimplifyFormula(*it, false) : *it;
+ //ASTNode aaa = *it;
+ //_bm->ASTNodeStats("Printing after calling simplifyformula inside the solver:", aaa);
+ aaa = BVSolve_Odd(aaa);
+ //_bm->ASTNodeStats("Printing after oddsolver:", aaa);
+ bool even = false;
+ aaa = CheckEvenEqn(aaa, even);
+ if (even)
+ {
+ eveneqns.push_back(aaa);
+ }
+ else
+ {
+ if (ASTTrue != aaa)
+ {
+ o.push_back(aaa);
+ }
+ }
+ solved = aaa;
+ }
+
+ ASTNode evens;
+ if (eveneqns.size() > 0)
+ {
+ //if there is a system of even equations then solve them
+ evens = (eveneqns.size() > 1) ? _bm->CreateNode(AND, eveneqns) : eveneqns[0];
+ //evens = _bm->SimplifyFormula(evens,false);
+ evens = BVSolve_Even(evens);
+ _bm->ASTNodeStats("Printing after evensolver:", evens);
+ }
+ else
+ {
+ evens = ASTTrue;
+ }
+ output = (o.size() > 0) ? ((o.size() > 1) ? _bm->CreateNode(AND, o) : o[0]) : ASTTrue;
+ output = _bm->CreateNode(AND, output, evens);
+
+ UpdateAlreadySolvedMap(input, output);
+ return output;
+} //end of TopLevelBVSolve()
+
+ASTNode BVSolver::CheckEvenEqn(const ASTNode& input, bool& evenflag)
+{
+ ASTNode eq = input;
+ //cerr << "Input to BVSolve_Odd()" << eq << endl;
+ if (!(wordlevel_solve && EQ == eq.GetKind()))
+ {
+ evenflag = false;
+ return eq;
+ }
+
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+ //lhs must be a BVPLUS, and rhs must be a BVCONST
+ if (!(BVPLUS == lhs.GetKind() && zero == rhs))
+ {
+ evenflag = false;
+ return eq;
+ }
+
+ ASTVec lhs_c = lhs.GetChildren();
+ ASTNode savetheconst = rhs;
+ for (ASTVec::iterator it = lhs_c.begin(), itend = lhs_c.end(); it != itend; it++)
+ {
+ ASTNode aaa = *it;
+ Kind itk = aaa.GetKind();
+
+ if (BVCONST == itk)
+ {
+ //check later if the constant is even or not
+ savetheconst = aaa;
+ continue;
+ }
+
+ if (!(BVMULT == itk && BVCONST == aaa[0].GetKind() && SYMBOL == aaa[1].GetKind() && !_bm->BVConstIsOdd(aaa[0])))
+ {
+ //If the monomials of the lhs are NOT of the form 'a*x' where
+ //'a' is even, then return the false
+ evenflag = false;
+ return eq;
+ }
+ }//end of for loop
+
+ //if control is here then it means that all coeffs are even. the
+ //only remaining thing is to check if the constant is even or not
+ if (_bm->BVConstIsOdd(savetheconst))
+ {
+ //the constant turned out to be odd. we have UNSAT eqn
+ evenflag = false;
+ return ASTFalse;
+ }
+
+ //all is clear. the eqn in even, through and through
+ evenflag = true;
return eq;
- }
- }//end of for loop
-
- //if control is here then it means that all coeffs are even. the
- //only remaining thing is to check if the constant is even or not
- if(_bm->BVConstIsOdd(savetheconst)) {
- //the constant turned out to be odd. we have UNSAT eqn
- evenflag = false;
- return ASTFalse;
- }
-
- //all is clear. the eqn in even, through and through
- evenflag = true;
- return eq;
- } //end of CheckEvenEqn
-
- //solve an eqn whose monomials have only even coefficients
- ASTNode BVSolver::BVSolve_Even(const ASTNode& input) {
- if(!wordlevel_solve) {
- return input;
- }
-
- if(!(EQ == input.GetKind() || AND == input.GetKind())) {
- return input;
- }
-
- ASTNode output;
- if(CheckAlreadySolvedMap(input,output)) {
- return output;
- }
-
- ASTVec input_c;
- if(EQ == input.GetKind()) {
- input_c.push_back(input);
- }
- else {
- input_c = input.GetChildren();
- }
-
- //power_of_2 holds the exponent of 2 in the coeff
- unsigned int power_of_2 = 0;
- //we need this additional variable to find the lowest power of 2
- unsigned int power_of_2_lowest = 0xffffffff;
- //the monom which has the least power of 2 in the coeff
- ASTNode monom_with_best_coeff;
- for(ASTVec::iterator jt=input_c.begin(),jtend=input_c.end();jt!=jtend;jt++) {
- ASTNode eq = *jt;
- ASTNode lhs = eq[0];
- ASTNode rhs = eq[1];
- ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
- //lhs must be a BVPLUS, and rhs must be a BVCONST
- if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
- return input;
- }
-
- ASTVec lhs_c = lhs.GetChildren();
- ASTNode odd;
- for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
- ASTNode aaa = *it;
- Kind itk = aaa.GetKind();
- if(!(BVCONST == itk &&
- !_bm->BVConstIsOdd(aaa)) &&
- !(BVMULT == itk &&
- BVCONST == aaa[0].GetKind() &&
- SYMBOL == aaa[1].GetKind() &&
- !_bm->BVConstIsOdd(aaa[0]))) {
- //If the monomials of the lhs are NOT of the form 'a*x' or 'a'
- //where 'a' is even, then return the eqn
- return input;
+} //end of CheckEvenEqn
+
+//solve an eqn whose monomials have only even coefficients
+ASTNode BVSolver::BVSolve_Even(const ASTNode& input)
+{
+ if (!wordlevel_solve)
+ {
+ return input;
+ }
+
+ if (!(EQ == input.GetKind() || AND == input.GetKind()))
+ {
+ return input;
}
-
- //we are gauranteed that if control is here then the monomial is
- //of the form 'a*x' or 'a', where 'a' is even
- ASTNode coeff = (BVCONST == itk) ? aaa : aaa[0];
- odd = SplitEven_into_Oddnum_PowerOf2(coeff,power_of_2);
- if(power_of_2 < power_of_2_lowest) {
- power_of_2_lowest = power_of_2;
- monom_with_best_coeff = aaa;
+
+ ASTNode output;
+ if (CheckAlreadySolvedMap(input, output))
+ {
+ return output;
}
- power_of_2 = 0;
- }//end of inner for loop
- } //end of outer for loop
-
- //get the exponent
- power_of_2 = power_of_2_lowest;
-
- //if control is here, we are gauranteed that we have chosen a
- //monomial with fewest powers of 2
- ASTVec formula_out;
- for(ASTVec::iterator jt=input_c.begin(),jtend=input_c.end();jt!=jtend;jt++) {
- ASTNode eq = *jt;
- ASTNode lhs = eq[0];
- ASTNode rhs = eq[1];
- ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
- //lhs must be a BVPLUS, and rhs must be a BVCONST
- if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
- return input;
- }
-
- unsigned len = lhs.GetValueWidth();
- ASTNode hi = _bm->CreateBVConst(32,len-1);
- ASTNode low = _bm->CreateBVConst(32,len - power_of_2);
- ASTNode low_minus_one = _bm->CreateBVConst(32,len - power_of_2 - 1);
- ASTNode low_zero = _bm->CreateZeroConst(32);
- unsigned newlen = len - power_of_2;
- ASTNode two_const = _bm->CreateTwoConst(len);
-
- unsigned count = power_of_2;
- ASTNode two = two_const;
- while(--count) {
- two = _bm->BVConstEvaluator(_bm->CreateTerm(BVMULT,len,two_const,two));
- }
- ASTVec lhs_c = lhs.GetChildren();
- ASTVec lhs_out;
- for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
- ASTNode aaa = *it;
- Kind itk = aaa.GetKind();
- if(BVCONST == itk) {
- aaa = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,aaa,two));
- aaa = _bm->BVConstEvaluator(_bm->CreateTerm(BVEXTRACT,newlen,aaa,low_minus_one,low_zero));
+
+ ASTVec input_c;
+ if (EQ == input.GetKind())
+ {
+ input_c.push_back(input);
}
- else {
- //it must be of the form a*x
- ASTNode coeff = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,aaa[0],two));
- coeff = _bm->BVConstEvaluator(_bm->CreateTerm(BVEXTRACT,newlen,coeff,low_minus_one,low_zero));
- ASTNode upper_x, lower_x;
- //upper_x = _bm->SimplifyTerm(_bm->CreateTerm(BVEXTRACT, power_of_2, aaa[1], hi, low));
- lower_x = _bm->SimplifyTerm(_bm->CreateTerm(BVEXTRACT, newlen,aaa[1],low_minus_one,low_zero));
- aaa = _bm->CreateTerm(BVMULT,newlen,coeff,lower_x);
+ else
+ {
+ input_c = input.GetChildren();
}
- lhs_out.push_back(aaa);
- }//end of inner forloop()
- rhs = _bm->CreateZeroConst(newlen);
- lhs = _bm->CreateTerm(BVPLUS,newlen,lhs_out);
- formula_out.push_back(_bm->CreateSimplifiedEQ(lhs,rhs));
- } //end of outer forloop()
-
- output =
- (formula_out.size() > 0) ? (formula_out.size() > 1) ? _bm->CreateNode(AND,formula_out) : formula_out[0] : ASTTrue;
-
- UpdateAlreadySolvedMap(input,output);
- return output;
- } //end of BVSolve_Even()
-};//end of namespace BEEV
+
+ //power_of_2 holds the exponent of 2 in the coeff
+ unsigned int power_of_2 = 0;
+ //we need this additional variable to find the lowest power of 2
+ unsigned int power_of_2_lowest = 0xffffffff;
+ //the monom which has the least power of 2 in the coeff
+ ASTNode monom_with_best_coeff;
+ for (ASTVec::iterator jt = input_c.begin(), jtend = input_c.end(); jt != jtend; jt++)
+ {
+ ASTNode eq = *jt;
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+ //lhs must be a BVPLUS, and rhs must be a BVCONST
+ if (!(BVPLUS == lhs.GetKind() && zero == rhs))
+ {
+ return input;
+ }
+
+ ASTVec lhs_c = lhs.GetChildren();
+ ASTNode odd;
+ for (ASTVec::iterator it = lhs_c.begin(), itend = lhs_c.end(); it != itend; it++)
+ {
+ ASTNode aaa = *it;
+ Kind itk = aaa.GetKind();
+ if (!(BVCONST == itk && !_bm->BVConstIsOdd(aaa)) && !(BVMULT == itk && BVCONST == aaa[0].GetKind() && SYMBOL == aaa[1].GetKind()
+ && !_bm->BVConstIsOdd(aaa[0])))
+ {
+ //If the monomials of the lhs are NOT of the form 'a*x' or 'a'
+ //where 'a' is even, then return the eqn
+ return input;
+ }
+
+ //we are gauranteed that if control is here then the monomial is
+ //of the form 'a*x' or 'a', where 'a' is even
+ ASTNode coeff = (BVCONST == itk) ? aaa : aaa[0];
+ odd = SplitEven_into_Oddnum_PowerOf2(coeff, power_of_2);
+ if (power_of_2 < power_of_2_lowest)
+ {
+ power_of_2_lowest = power_of_2;
+ monom_with_best_coeff = aaa;
+ }
+ power_of_2 = 0;
+ }//end of inner for loop
+ } //end of outer for loop
+
+ //get the exponent
+ power_of_2 = power_of_2_lowest;
+
+ //if control is here, we are gauranteed that we have chosen a
+ //monomial with fewest powers of 2
+ ASTVec formula_out;
+ for (ASTVec::iterator jt = input_c.begin(), jtend = input_c.end(); jt != jtend; jt++)
+ {
+ ASTNode eq = *jt;
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+ //lhs must be a BVPLUS, and rhs must be a BVCONST
+ if (!(BVPLUS == lhs.GetKind() && zero == rhs))
+ {
+ return input;
+ }
+
+ unsigned len = lhs.GetValueWidth();
+ ASTNode hi = _bm->CreateBVConst(32, len - 1);
+ ASTNode low = _bm->CreateBVConst(32, len - power_of_2);
+ ASTNode low_minus_one = _bm->CreateBVConst(32, len - power_of_2 - 1);
+ ASTNode low_zero = _bm->CreateZeroConst(32);
+ unsigned newlen = len - power_of_2;
+ ASTNode two_const = _bm->CreateTwoConst(len);
+
+ unsigned count = power_of_2;
+ ASTNode two = two_const;
+ while (--count)
+ {
+ two = _bm->BVConstEvaluator(_bm->CreateTerm(BVMULT, len, two_const, two));
+ }
+ ASTVec lhs_c = lhs.GetChildren();
+ ASTVec lhs_out;
+ for (ASTVec::iterator it = lhs_c.begin(), itend = lhs_c.end(); it != itend; it++)
+ {
+ ASTNode aaa = *it;
+ Kind itk = aaa.GetKind();
+ if (BVCONST == itk)
+ {
+ aaa = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV, len, aaa, two));
+ aaa = _bm->BVConstEvaluator(_bm->CreateTerm(BVEXTRACT, newlen, aaa, low_minus_one, low_zero));
+ }
+ else
+ {
+ //it must be of the form a*x
+ ASTNode coeff = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV, len, aaa[0], two));
+ coeff = _bm->BVConstEvaluator(_bm->CreateTerm(BVEXTRACT, newlen, coeff, low_minus_one, low_zero));
+ ASTNode upper_x, lower_x;
+ //upper_x = _bm->SimplifyTerm(_bm->CreateTerm(BVEXTRACT, power_of_2, aaa[1], hi, low));
+ lower_x = _bm->SimplifyTerm(_bm->CreateTerm(BVEXTRACT, newlen, aaa[1], low_minus_one, low_zero));
+ aaa = _bm->CreateTerm(BVMULT, newlen, coeff, lower_x);
+ }
+ lhs_out.push_back(aaa);
+ }//end of inner forloop()
+ rhs = _bm->CreateZeroConst(newlen);
+ lhs = _bm->CreateTerm(BVPLUS, newlen, lhs_out);
+ formula_out.push_back(_bm->CreateSimplifiedEQ(lhs, rhs));
+ } //end of outer forloop()
+
+ output = (formula_out.size() > 0) ? (formula_out.size() > 1) ? _bm->CreateNode(AND, formula_out) : formula_out[0] : ASTTrue;
+
+ UpdateAlreadySolvedMap(input, output);
+ return output;
+} //end of BVSolve_Even()
+}
+;//end of namespace BEEV
#include "../AST/AST.h"
#include "../AST/ASTUtil.h"
-namespace BEEV {
-
- //This class represents the bitvector arithmetic linear solver.
- //
- //The bitvector solver is a partial solver, i.e. it does not solve
- //for all variables in the system of equations. it is
- //best-effort. it relies on the SAT solver to be complete.
- //
- //The BVSolver assumes that the input equations are normalized, and
- //have liketerms combined etc.
- //
- //0. Traverse top-down over the input DAG, looking for a conjunction
- //0. of equations. if you find one, then for each equation in the
- //0. conjunction, do the following steps.
- //
- //1. check for Linearity of the input equation
- //
- //2. Solve for a "chosen" variable. The variable should occur
- //2. exactly once and must have an odd coeff. Refer STP's CAV 2007
- //2. paper for actual solving procedure
- //
- //4. Outside the solver, Substitute and Re-normalize the input DAG
- class BVSolver {
- //Ptr to toplevel manager that manages bit-vector expressions
- //(i.e. construct various kinds of expressions), and also has
- //member functions that simplify bit-vector expressions
- BeevMgr * _bm;
- ASTNode ASTTrue, ASTFalse;
-
- //Those formulas which have already been solved. If the same
- //formula occurs twice then do not solve the second occurence, and
- //instead drop it
- ASTNodeMap FormulasAlreadySolvedMap;
-
- //this map is useful while traversing terms and uniquely
- //identifying variables in the those terms. Prevents double
- //counting.
- ASTNodeMap TermsAlreadySeenMap;
- ASTNodeMap TermsAlreadySeenMap_ForArrays;
-
- //count is used in the creation of new variables
- unsigned int _symbol_count;
-
- //solved variables list: If a variable has been solved for then do
- //not solve for it again
- ASTNodeSet DoNotSolve_TheseVars;
-
- //checks if var has been solved for or not. if yes, then return
- //true else return false
- bool DoNotSolveThis(const ASTNode& var);
-
- //traverses a term, and creates a multiset of all variables in the
- //term. Does memoization to avoid double counting.
- void VarsInTheTerm(const ASTNode& lhs, ASTNodeMultiSet& v);
- void VarsInTheTerm_TopLevel(const ASTNode& lhs, ASTNodeMultiSet& v);
-
- //choose a suitable var from the term
- ASTNode ChooseMonom(const ASTNode& eq, ASTNode& modifiedterm);
- //accepts an equation and solves for a variable or a monom in it
- ASTNode BVSolve_Odd(const ASTNode& eq);
-
- //solves equations of the form a*x=t where 'a' is even. Has a
- //return value, unlike the normal BVSolve()
- ASTNode BVSolve_Even(const ASTNode& eq);
- ASTNode CheckEvenEqn(const ASTNode& input, bool& evenflag);
-
- //Checks for arrayreads in a term. if yes then returns true, else
- //return false
- bool CheckForArrayReads(const ASTNode& term);
- bool CheckForArrayReads_TopLevel(const ASTNode& term);
-
- //Creates new variables used in solving
- ASTNode NewVar(unsigned int n);
-
- //this function return true if the var occurs in term, else the
- //function returns false
- bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
-
- //takes an even number "in" as input, and returns an odd number
- //(return value) and a power of 2 (as number_shifts by reference),
- //such that in = (odd_number * power_of_2).
- //
- //Refer STP's CAV 2007 (or Clark Barrett's 1998 paper on
- //bit-vector arithmetic published in DAC 1998) paper for precise
- //understanding of the algorithm
- ASTNode SplitEven_into_Oddnum_PowerOf2(const ASTNode& in, unsigned int& number_shifts);
-
- //Once a formula has been solved, then update the alreadysolvedmap
- //with the formula, and the solved value. The solved value can be
- //described using the following example: Suppose input to the
- //solver is
- //
- // input key: x = 2 AND y = x + t
- //
- // output value: y = 2 + t
- void UpdateAlreadySolvedMap(const ASTNode& key, const ASTNode& value);
-
- //This function checks if the key (formula) has already been
- //solved for.
- //
- //If yes it returns TRUE and fills the "output" with the
- //solved-value (call by reference argument),
- //
- //else returns FALSE
- bool CheckAlreadySolvedMap(const ASTNode& key, ASTNode& output);
- public:
- //constructor
- BVSolver(BeevMgr * bm) : _bm(bm), _symbol_count(0) {
- ASTTrue = _bm->CreateNode(TRUE);
- ASTFalse = _bm->CreateNode(FALSE);
- };
-
- //Destructor
- ~BVSolver() {
- TermsAlreadySeenMap.clear();
- DoNotSolve_TheseVars.clear();
- FormulasAlreadySolvedMap.clear();
- TermsAlreadySeenMap_ForArrays.clear();
- }
-
- //Top Level Solver: Goes over the input DAG, identifies the
- //equation to be solved, solves them,
- ASTNode TopLevelBVSolve(const ASTNode& a);
- }; //end of class bvsolver
-};//end of namespace BEEV
+namespace BEEV
+{
+
+//This class represents the bitvector arithmetic linear solver.
+//
+//The bitvector solver is a partial solver, i.e. it does not solve
+//for all variables in the system of equations. it is
+//best-effort. it relies on the SAT solver to be complete.
+//
+//The BVSolver assumes that the input equations are normalized, and
+//have liketerms combined etc.
+//
+//0. Traverse top-down over the input DAG, looking for a conjunction
+//0. of equations. if you find one, then for each equation in the
+//0. conjunction, do the following steps.
+//
+//1. check for Linearity of the input equation
+//
+//2. Solve for a "chosen" variable. The variable should occur
+//2. exactly once and must have an odd coeff. Refer STP's CAV 2007
+//2. paper for actual solving procedure
+//
+//4. Outside the solver, Substitute and Re-normalize the input DAG
+class BVSolver
+{
+ //Ptr to toplevel manager that manages bit-vector expressions
+ //(i.e. construct various kinds of expressions), and also has
+ //member functions that simplify bit-vector expressions
+ BeevMgr * _bm;
+ ASTNode ASTTrue, ASTFalse;
+
+ //Those formulas which have already been solved. If the same
+ //formula occurs twice then do not solve the second occurence, and
+ //instead drop it
+ ASTNodeMap FormulasAlreadySolvedMap;
+
+ //this map is useful while traversing terms and uniquely
+ //identifying variables in the those terms. Prevents double
+ //counting.
+ ASTNodeMap TermsAlreadySeenMap;
+ ASTNodeMap TermsAlreadySeenMap_ForArrays;
+
+ //count is used in the creation of new variables
+ unsigned int _symbol_count;
+
+ //solved variables list: If a variable has been solved for then do
+ //not solve for it again
+ ASTNodeSet DoNotSolve_TheseVars;
+
+ //checks if var has been solved for or not. if yes, then return
+ //true else return false
+ bool DoNotSolveThis(const ASTNode& var);
+
+ //traverses a term, and creates a multiset of all variables in the
+ //term. Does memoization to avoid double counting.
+ void VarsInTheTerm(const ASTNode& lhs, ASTNodeMultiSet& v);
+ void VarsInTheTerm_TopLevel(const ASTNode& lhs, ASTNodeMultiSet& v);
+
+ //choose a suitable var from the term
+ ASTNode ChooseMonom(const ASTNode& eq, ASTNode& modifiedterm);
+ //accepts an equation and solves for a variable or a monom in it
+ ASTNode BVSolve_Odd(const ASTNode& eq);
+
+ //solves equations of the form a*x=t where 'a' is even. Has a
+ //return value, unlike the normal BVSolve()
+ ASTNode BVSolve_Even(const ASTNode& eq);
+ ASTNode CheckEvenEqn(const ASTNode& input, bool& evenflag);
+
+ //Checks for arrayreads in a term. if yes then returns true, else
+ //return false
+ bool CheckForArrayReads(const ASTNode& term);
+ bool CheckForArrayReads_TopLevel(const ASTNode& term);
+
+ //Creates new variables used in solving
+ ASTNode NewVar(unsigned int n);
+
+ //this function return true if the var occurs in term, else the
+ //function returns false
+ bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
+
+ //takes an even number "in" as input, and returns an odd number
+ //(return value) and a power of 2 (as number_shifts by reference),
+ //such that in = (odd_number * power_of_2).
+ //
+ //Refer STP's CAV 2007 (or Clark Barrett's 1998 paper on
+ //bit-vector arithmetic published in DAC 1998) paper for precise
+ //understanding of the algorithm
+ ASTNode SplitEven_into_Oddnum_PowerOf2(const ASTNode& in, unsigned int& number_shifts);
+
+ //Once a formula has been solved, then update the alreadysolvedmap
+ //with the formula, and the solved value. The solved value can be
+ //described using the following example: Suppose input to the
+ //solver is
+ //
+ // input key: x = 2 AND y = x + t
+ //
+ // output value: y = 2 + t
+ void UpdateAlreadySolvedMap(const ASTNode& key, const ASTNode& value);
+
+ //This function checks if the key (formula) has already been
+ //solved for.
+ //
+ //If yes it returns TRUE and fills the "output" with the
+ //solved-value (call by reference argument),
+ //
+ //else returns FALSE
+ bool CheckAlreadySolvedMap(const ASTNode& key, ASTNode& output);
+public:
+ //constructor
+ BVSolver(BeevMgr * bm) :
+ _bm(bm), _symbol_count(0)
+ {
+ ASTTrue = _bm->CreateNode(TRUE);
+ ASTFalse = _bm->CreateNode(FALSE);
+ }
+ ;
+
+ //Destructor
+ ~BVSolver()
+ {
+ TermsAlreadySeenMap.clear();
+ DoNotSolve_TheseVars.clear();
+ FormulasAlreadySolvedMap.clear();
+ TermsAlreadySeenMap_ForArrays.clear();
+ }
+
+ //Top Level Solver: Goes over the input DAG, identifies the
+ //equation to be solved, solves them,
+ ASTNode TopLevelBVSolve(const ASTNode& a);
+}; //end of class bvsolver
+}
+;//end of namespace BEEV
#include "../AST/AST.h"
#include "../AST/ASTUtil.h"
-namespace BEEV {
-
- bool BeevMgr::CheckSimplifyMap(const ASTNode& key,
- ASTNode& output, bool pushNeg) {
- ASTNodeMap::iterator it, itend;
- it = pushNeg ? SimplifyNegMap->find(key) : SimplifyMap->find(key);
- itend = pushNeg ? SimplifyNegMap->end() : SimplifyMap->end();
-
- if(it != itend) {
- output = it->second;
- CountersAndStats("Successful_CheckSimplifyMap");
- return true;
- }
-
- if(pushNeg && (it = SimplifyMap->find(key)) != SimplifyMap->end()) {
- output =
- (ASTFalse == it->second) ?
- ASTTrue :
- (ASTTrue == it->second) ? ASTFalse : CreateNode(NOT, it->second);
- CountersAndStats("2nd_Successful_CheckSimplifyMap");
- return true;
- }
-
- return false;
- }
-
- void BeevMgr::UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg) {
- if(pushNeg)
- (*SimplifyNegMap)[key] = value;
- else
- (*SimplifyMap)[key] = value;
- }
-
- bool BeevMgr::CheckSubstitutionMap(const ASTNode& key, ASTNode& output) {
- ASTNodeMap::iterator it;
- if((it = SolverMap.find(key)) != SolverMap.end()) {
- output = it->second;
- return true;
- }
- return false;
- }
-
- bool BeevMgr::CheckSubstitutionMap(const ASTNode& key) {
- if(SolverMap.find(key) != SolverMap.end())
- return true;
- else
- return false;
- }
-
- bool BeevMgr::UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1) {
- int i = TermOrder(e0,e1);
- if(0 == i)
- return false;
-
- //e0 is of the form READ(Arr,const), and e1 is const, or
- //e0 is of the form var, and e1 is const
- if(1 == i && !CheckSubstitutionMap(e0)) {
- SolverMap[e0] = e1;
- return true;
- }
-
- //e1 is of the form READ(Arr,const), and e0 is const, or
- //e1 is of the form var, and e0 is const
- if (-1 == i && !CheckSubstitutionMap(e1)) {
- SolverMap[e1] = e0;
- return true;
- }
-
- return false;
- }
-
- bool BeevMgr::CheckMultInverseMap(const ASTNode& key, ASTNode& output) {
- ASTNodeMap::iterator it;
- if((it = MultInverseMap.find(key)) != MultInverseMap.end()) {
- output = it->second;
- return true;
- }
- return false;
- }
-
- void BeevMgr::UpdateMultInverseMap(const ASTNode& key, const ASTNode& value) {
- MultInverseMap[key] = value;
- }
-
-
- bool BeevMgr::CheckAlwaysTrueFormMap(const ASTNode& key) {
- ASTNodeSet::iterator it = AlwaysTrueFormMap.find(key);
- ASTNodeSet::iterator itend = AlwaysTrueFormMap.end();
-
- if(it != itend) {
- //cerr << "found:" << *it << endl;
- CountersAndStats("Successful_CheckAlwaysTrueFormMap");
- return true;
- }
-
- return false;
- }
-
- void BeevMgr::UpdateAlwaysTrueFormMap(const ASTNode& key) {
- AlwaysTrueFormMap.insert(key);
- }
-
- //if a is READ(Arr,const) or SYMBOL, and b is BVCONST then return 1
- //if b is READ(Arr,const) or SYMBOL, and a is BVCONST then return -1
- //
- //else return 0 by default
- int BeevMgr::TermOrder(const ASTNode& a, const ASTNode& b) {
- Kind k1 = a.GetKind();
- Kind k2 = b.GetKind();
-
- //a is of the form READ(Arr,const), and b is const, or
- //a is of the form var, and b is const
- if((k1 == READ
- &&
- a[0].GetKind() == SYMBOL &&
- a[1].GetKind() == BVCONST
- )
- &&
- (k2 == BVCONST)
- )
- return 1;
-
- if(SYMBOL == k1 && (BVCONST == k2 || TRUE == k2 || FALSE == k2))
- return 1;
-
- //b is of the form READ(Arr,const), and a is const, or
- //b is of the form var, and a is const
- if((k1 == BVCONST)
- &&
- ((k2 == READ
- &&
- b[0].GetKind() == SYMBOL &&
- b[1].GetKind() == BVCONST
- )
- ))
- return -1;
-
- if(SYMBOL == k2 && (BVCONST == k1 || TRUE == k1 || FALSE == k1))
- return -1;
-
- return 0;
- }
-
- //This function records all the const-indices seen so far for each
- //array. It populates the map '_arrayname_readindices' whose key is
- //the arrayname, and vlaue is a vector of read-indices.
- //
- //fill the arrayname_readindices vector if e0 is a READ(Arr,index)
- //and index is a BVCONST.
- //
- //Since these arrayreads are being nuked and recorded in the
- //substitutionmap, we have to also record the fact that each
- //arrayread (e0 is of the form READ(Arr,const) here is represented
- //by a BVCONST (e1). This is necessary for later Leibnitz Axiom
- //generation
- void BeevMgr::FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1) {
- int i = TermOrder(e0,e1);
- if(0 == i) return;
-
- if(1 == i && e0.GetKind() != SYMBOL && !CheckSubstitutionMap(e0)) {
- _arrayname_readindices[e0[0]].push_back(e0[1]);
- //e0 is the array read : READ(A,i) and e1 is a bvconst
- _arrayread_symbol[e0] = e1;
- return;
- }
- if(-1 == i && e1.GetKind() != SYMBOL && !CheckSubstitutionMap(e1)) {
- _arrayname_readindices[e1[0]].push_back(e1[1]);
- //e0 is the array read : READ(A,i) and e1 is a bvconst
- _arrayread_symbol[e1] = e0;
- return;
- }
- }
-
- ASTNode BeevMgr::SimplifyFormula_NoRemoveWrites(const ASTNode& b, bool pushNeg) {
- Begin_RemoveWrites = false;
- ASTNode out = SimplifyFormula(b,pushNeg);
- return out;
- }
-
- ASTNode BeevMgr::SimplifyFormula_TopLevel(const ASTNode& b, bool pushNeg) {
- ResetSimplifyMaps();
- ASTNode out = SimplifyFormula(b,pushNeg);
- ResetSimplifyMaps();
- return out;
- }
-
- ASTNode BeevMgr::SimplifyFormula(const ASTNode& b, bool pushNeg){
- if(!optimize)
- return b;
-
- Kind kind = b.GetKind();
- if(BOOLEAN_TYPE != b.GetType()) {
- FatalError(" SimplifyFormula: You have input a nonformula kind: ",ASTUndefined,kind);
- }
-
- ASTNode a = b;
- ASTVec ca = a.GetChildren();
- if(!(IMPLIES == kind ||
- ITE == kind ||
- isAtomic(kind))) {
- SortByArith(ca);
- a = CreateNode(kind,ca);
- }
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- switch(kind){
- case AND:
- case OR:
- output = SimplifyAndOrFormula(a,pushNeg);
- break;
- case NOT:
- output = SimplifyNotFormula(a,pushNeg);
- break;
- case XOR:
- output = SimplifyXorFormula(a,pushNeg);
- break;
- case NAND:
- output = SimplifyNandFormula(a,pushNeg);
- break;
- case NOR:
- output = SimplifyNorFormula(a,pushNeg);
- break;
- case IFF:
- output = SimplifyIffFormula(a,pushNeg);
- break;
- case IMPLIES:
- output = SimplifyImpliesFormula(a,pushNeg);
- break;
- case ITE:
- output = SimplifyIteFormula(a,pushNeg);
- break;
- default:
- //kind can be EQ,NEQ,BVLT,BVLE,... or a propositional variable
- output = SimplifyAtomicFormula(a,pushNeg);
- //output = pushNeg ? CreateNode(NOT,a) : a;
- break;
- }
-
- //memoize
- UpdateSimplifyMap(a,output, pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyAtomicFormula(const ASTNode& a, bool pushNeg) {
- if(!optimize) {
- return a;
- }
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg)) {
- return output;
- }
-
- ASTNode left,right;
- if(a.Degree() == 2) {
- //cerr << "Input to simplifyterm: left: " << a[0] << endl;
- left = SimplifyTerm(a[0]);
- //cerr << "Output of simplifyterm:left: " << left << endl;
- //cerr << "Input to simplifyterm: right: " << a[1] << endl;
- right = SimplifyTerm(a[1]);
- //cerr << "Output of simplifyterm:left: " << right << endl;
- }
-
- Kind kind = a.GetKind();
- switch(kind) {
- case TRUE:
- output = pushNeg ? ASTFalse : ASTTrue;
- break;
- case FALSE:
- output = pushNeg ? ASTTrue : ASTFalse;
- break;
- case SYMBOL:
- if(!CheckSolverMap(a,output)) {
- output = a;
- }
- output = pushNeg ? CreateNode(NOT,output) : output;
- break;
- case BVGETBIT: {
- ASTNode term = SimplifyTerm(a[0]);
- ASTNode thebit = a[1];
- ASTNode zero = CreateZeroConst(1);
- ASTNode one = CreateOneConst(1);
- ASTNode getthebit = SimplifyTerm(CreateTerm(BVEXTRACT,1,term,thebit,thebit));
- if(getthebit == zero)
- output = pushNeg ? ASTTrue : ASTFalse;
- else if(getthebit == one)
- output = pushNeg ? ASTFalse : ASTTrue;
- else {
- output = CreateNode(BVGETBIT,term,thebit);
- output = pushNeg ? CreateNode(NOT,output) : output;
- }
- break;
- }
- case EQ:{
- output = CreateSimplifiedEQ(left,right);
- output = LhsMinusRhs(output);
- output = ITEOpt_InEqs(output);
- if(output == ASTTrue)
- output = pushNeg ? ASTFalse : ASTTrue;
- else if (output == ASTFalse)
- output = pushNeg ? ASTTrue : ASTFalse;
- else
- output = pushNeg ? CreateNode(NOT,output) : output;
- break;
- }
- case NEQ: {
- output = CreateSimplifiedEQ(left,right);
- output = LhsMinusRhs(output);
- if(output == ASTTrue)
- output = pushNeg ? ASTTrue : ASTFalse;
- else if (output == ASTFalse)
- output = pushNeg ? ASTFalse : ASTTrue;
- else
- output = pushNeg ? output : CreateNode(NOT,output);
- break;
- }
- case BVLT:
- case BVLE:
- case BVGT:
- case BVGE:
- case BVSLT:
- case BVSLE:
- case BVSGT:
- case BVSGE: {
- //output = CreateNode(kind,left,right);
- //output = pushNeg ? CreateNode(NOT,output) : output;
- output = CreateSimplifiedINEQ(kind,left,right,pushNeg);
- break;
- }
- default:
- FatalError("SimplifyAtomicFormula: NO atomic formula of the kind: ",ASTUndefined,kind);
- break;
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- } //end of SimplifyAtomicFormula()
-
- ASTNode BeevMgr::CreateSimplifiedINEQ(Kind k,
- const ASTNode& left,
- const ASTNode& right,
- bool pushNeg) {
- ASTNode output;
- if(BVCONST == left.GetKind() && BVCONST == right.GetKind()) {
- output = BVConstEvaluator(CreateNode(k,left,right));
- output = pushNeg ? (ASTFalse == output) ? ASTTrue : ASTFalse : output;
- return output;
- }
-
- unsigned len = left.GetValueWidth();
- ASTNode zero = CreateZeroConst(len);
- ASTNode one = CreateOneConst(len);
- ASTNode max = CreateMaxConst(len);
- switch(k){
- case BVLT:
- if(right == zero) {
- output = pushNeg ? ASTTrue : ASTFalse;
- }
- else if(left == right) {
- output = pushNeg ? ASTTrue : ASTFalse;
- }
- else if(one == right) {
- output = CreateSimplifiedEQ(left,zero);
- output = pushNeg ? CreateNode(NOT,output) : output;
- }
- else {
- output = pushNeg ? CreateNode(BVLE,right,left) : CreateNode(BVLT,left,right);
- }
- break;
- case BVLE:
- if(left == zero) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else if(left == right) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else if(max == right) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else if(zero == right) {
- output = CreateSimplifiedEQ(left,zero);
- output = pushNeg ? CreateNode(NOT,output) : output;
- }
- else {
- output = pushNeg ? CreateNode(BVLT,right,left) : CreateNode(BVLE,left,right);
- }
- break;
- case BVGT:
- if(left == zero) {
- output = pushNeg ? ASTTrue : ASTFalse;
- }
- else if(left == right) {
- output = pushNeg ? ASTTrue : ASTFalse;
- }
- else {
- output = pushNeg ? CreateNode(BVLE,left,right) : CreateNode(BVLT,right,left);
- }
- break;
- case BVGE:
- if(right == zero) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else if(left == right) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else {
- output = pushNeg ? CreateNode(BVLT,left,right) : CreateNode(BVLE,right,left);
- }
- break;
- case BVSLT:
- case BVSLE:
- case BVSGE:
- case BVSGT: {
- output = CreateNode(k,left,right);
- output = pushNeg ? CreateNode(NOT,output) : output;
- }
- break;
- default:
- FatalError("Wrong Kind");
- break;
- }
-
- return output;
- }
-
- //takes care of some simple ITE Optimizations in the context of equations
- ASTNode BeevMgr::ITEOpt_InEqs(const ASTNode& in) {
- CountersAndStats("ITEOpts_InEqs");
-
- if(!(EQ == in.GetKind() && optimize)) {
- return in;
- }
-
- ASTNode output;
- if(CheckSimplifyMap(in,output,false)) {
- return output;
- }
-
- ASTNode in1 = in[0];
- ASTNode in2 = in[1];
- Kind k1 = in1.GetKind();
- Kind k2 = in2.GetKind();
- if(in1 == in2) {
- //terms are syntactically the same
- output = ASTTrue;
- }
- else if(BVCONST == k1 && BVCONST == k2) {
- //here the terms are definitely not syntactically equal but may
- //be semantically equal.
- output = ASTFalse;
- }
- else if(ITE == k1 &&
- BVCONST == in1[1].GetKind() &&
- BVCONST == in1[2].GetKind() && BVCONST == k2) {
- //if one side is a BVCONST and the other side is an ITE over
- //BVCONST then we can do the following optimization:
- //
- // c = ITE(cond,c,d) <=> cond
- //
- // similarly ITE(cond,c,d) = c <=> cond
- //
- // c = ITE(cond,d,c) <=> NOT(cond)
- //
- //similarly ITE(cond,d,c) = d <=> NOT(cond)
- ASTNode cond = in1[0];
- if(in1[1] == in2) {
- //ITE(cond, c, d) = c <=> cond
- output = cond;
- }
- else if(in1[2] == in2) {
- cond = SimplifyFormula(cond,true);
- output = cond;
- }
- else {
- //last resort is to CreateNode
- output = CreateNode(EQ,in1,in2);
- }
- }
- else if(ITE == k2 &&
- BVCONST == in2[1].GetKind() &&
- BVCONST == in2[2].GetKind() && BVCONST == k1) {
- ASTNode cond = in2[0];
- if(in2[1] == in1) {
- //ITE(cond, c, d) = c <=> cond
- output = cond;
- }
- else if(in2[2] == in1) {
- cond = SimplifyFormula(cond,true);
- output = cond;
- }
- else {
+namespace BEEV
+{
+
+bool BeevMgr::CheckSimplifyMap(const ASTNode& key, ASTNode& output, bool pushNeg)
+{
+ ASTNodeMap::iterator it, itend;
+ it = pushNeg ? SimplifyNegMap->find(key) : SimplifyMap->find(key);
+ itend = pushNeg ? SimplifyNegMap->end() : SimplifyMap->end();
+
+ if (it != itend)
+ {
+ output = it->second;
+ CountersAndStats("Successful_CheckSimplifyMap");
+ return true;
+ }
+
+ if (pushNeg && (it = SimplifyMap->find(key)) != SimplifyMap->end())
+ {
+ output = (ASTFalse == it->second) ? ASTTrue : (ASTTrue == it->second) ? ASTFalse : CreateNode(NOT, it->second);
+ CountersAndStats("2nd_Successful_CheckSimplifyMap");
+ return true;
+ }
+
+ return false;
+}
+
+void BeevMgr::UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg)
+{
+ if (pushNeg)
+ (*SimplifyNegMap)[key] = value;
+ else
+ (*SimplifyMap)[key] = value;
+}
+
+bool BeevMgr::CheckSubstitutionMap(const ASTNode& key, ASTNode& output)
+{
+ ASTNodeMap::iterator it;
+ if ((it = SolverMap.find(key)) != SolverMap.end())
+ {
+ output = it->second;
+ return true;
+ }
+ return false;
+}
+
+bool BeevMgr::CheckSubstitutionMap(const ASTNode& key)
+{
+ if (SolverMap.find(key) != SolverMap.end())
+ return true;
+ else
+ return false;
+}
+
+bool BeevMgr::UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1)
+{
+ int i = TermOrder(e0, e1);
+ if (0 == i)
+ return false;
+
+ //e0 is of the form READ(Arr,const), and e1 is const, or
+ //e0 is of the form var, and e1 is const
+ if (1 == i && !CheckSubstitutionMap(e0))
+ {
+ SolverMap[e0] = e1;
+ return true;
+ }
+
+ //e1 is of the form READ(Arr,const), and e0 is const, or
+ //e1 is of the form var, and e0 is const
+ if (-1 == i && !CheckSubstitutionMap(e1))
+ {
+ SolverMap[e1] = e0;
+ return true;
+ }
+
+ return false;
+}
+
+bool BeevMgr::CheckMultInverseMap(const ASTNode& key, ASTNode& output)
+{
+ ASTNodeMap::iterator it;
+ if ((it = MultInverseMap.find(key)) != MultInverseMap.end())
+ {
+ output = it->second;
+ return true;
+ }
+ return false;
+}
+
+void BeevMgr::UpdateMultInverseMap(const ASTNode& key, const ASTNode& value)
+{
+ MultInverseMap[key] = value;
+}
+
+bool BeevMgr::CheckAlwaysTrueFormMap(const ASTNode& key)
+{
+ ASTNodeSet::iterator it = AlwaysTrueFormMap.find(key);
+ ASTNodeSet::iterator itend = AlwaysTrueFormMap.end();
+
+ if (it != itend)
+ {
+ //cerr << "found:" << *it << endl;
+ CountersAndStats("Successful_CheckAlwaysTrueFormMap");
+ return true;
+ }
+
+ return false;
+}
+
+void BeevMgr::UpdateAlwaysTrueFormMap(const ASTNode& key)
+{
+ AlwaysTrueFormMap.insert(key);
+}
+
+//if a is READ(Arr,const) or SYMBOL, and b is BVCONST then return 1
+//if b is READ(Arr,const) or SYMBOL, and a is BVCONST then return -1
+//
+//else return 0 by default
+int BeevMgr::TermOrder(const ASTNode& a, const ASTNode& b)
+{
+ Kind k1 = a.GetKind();
+ Kind k2 = b.GetKind();
+
+ //a is of the form READ(Arr,const), and b is const, or
+ //a is of the form var, and b is const
+ if ((k1 == READ && a[0].GetKind() == SYMBOL && a[1].GetKind() == BVCONST) && (k2 == BVCONST))
+ return 1;
+
+ if (SYMBOL == k1 && (BVCONST == k2 || TRUE == k2 || FALSE == k2))
+ return 1;
+
+ //b is of the form READ(Arr,const), and a is const, or
+ //b is of the form var, and a is const
+ if ((k1 == BVCONST) && ((k2 == READ && b[0].GetKind() == SYMBOL && b[1].GetKind() == BVCONST)))
+ return -1;
+
+ if (SYMBOL == k2 && (BVCONST == k1 || TRUE == k1 || FALSE == k1))
+ return -1;
+
+ return 0;
+}
+
+//This function records all the const-indices seen so far for each
+//array. It populates the map '_arrayname_readindices' whose key is
+//the arrayname, and vlaue is a vector of read-indices.
+//
+//fill the arrayname_readindices vector if e0 is a READ(Arr,index)
+//and index is a BVCONST.
+//
+//Since these arrayreads are being nuked and recorded in the
+//substitutionmap, we have to also record the fact that each
+//arrayread (e0 is of the form READ(Arr,const) here is represented
+//by a BVCONST (e1). This is necessary for later Leibnitz Axiom
+//generation
+void BeevMgr::FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1)
+{
+ int i = TermOrder(e0, e1);
+ if (0 == i)
+ return;
+
+ if (1 == i && e0.GetKind() != SYMBOL && !CheckSubstitutionMap(e0))
+ {
+ _arrayname_readindices[e0[0]].push_back(e0[1]);
+ //e0 is the array read : READ(A,i) and e1 is a bvconst
+ _arrayread_symbol[e0] = e1;
+ return;
+ }
+ if (-1 == i && e1.GetKind() != SYMBOL && !CheckSubstitutionMap(e1))
+ {
+ _arrayname_readindices[e1[0]].push_back(e1[1]);
+ //e0 is the array read : READ(A,i) and e1 is a bvconst
+ _arrayread_symbol[e1] = e0;
+ return;
+ }
+}
+
+ASTNode BeevMgr::SimplifyFormula_NoRemoveWrites(const ASTNode& b, bool pushNeg)
+{
+ Begin_RemoveWrites = false;
+ ASTNode out = SimplifyFormula(b, pushNeg);
+ return out;
+}
+
+ASTNode BeevMgr::SimplifyFormula_TopLevel(const ASTNode& b, bool pushNeg)
+{
+ ResetSimplifyMaps();
+ ASTNode out = SimplifyFormula(b, pushNeg);
+ ResetSimplifyMaps();
+ return out;
+}
+
+ASTNode BeevMgr::SimplifyFormula(const ASTNode& b, bool pushNeg)
+{
+ if (!optimize)
+ return b;
+
+ Kind kind = b.GetKind();
+ if (BOOLEAN_TYPE != b.GetType())
+ {
+ FatalError(" SimplifyFormula: You have input a nonformula kind: ", ASTUndefined, kind);
+ }
+
+ ASTNode a = b;
+ ASTVec ca = a.GetChildren();
+ if (!(IMPLIES == kind || ITE == kind || isAtomic(kind)))
+ {
+ SortByArith(ca);
+ a = CreateNode(kind, ca);
+ }
+
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, pushNeg))
+ return output;
+
+ switch (kind)
+ {
+ case AND:
+ case OR:
+ output = SimplifyAndOrFormula(a, pushNeg);
+ break;
+ case NOT:
+ output = SimplifyNotFormula(a, pushNeg);
+ break;
+ case XOR:
+ output = SimplifyXorFormula(a, pushNeg);
+ break;
+ case NAND:
+ output = SimplifyNandFormula(a, pushNeg);
+ break;
+ case NOR:
+ output = SimplifyNorFormula(a, pushNeg);
+ break;
+ case IFF:
+ output = SimplifyIffFormula(a, pushNeg);
+ break;
+ case IMPLIES:
+ output = SimplifyImpliesFormula(a, pushNeg);
+ break;
+ case ITE:
+ output = SimplifyIteFormula(a, pushNeg);
+ break;
+ default:
+ //kind can be EQ,NEQ,BVLT,BVLE,... or a propositional variable
+ output = SimplifyAtomicFormula(a, pushNeg);
+ //output = pushNeg ? CreateNode(NOT,a) : a;
+ break;
+ }
+
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
+ return output;
+}
+
+ASTNode BeevMgr::SimplifyAtomicFormula(const ASTNode& a, bool pushNeg)
+{
+ if (!optimize)
+ {
+ return a;
+ }
+
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, pushNeg))
+ {
+ return output;
+ }
+
+ ASTNode left, right;
+ if (a.Degree() == 2)
+ {
+ //cerr << "Input to simplifyterm: left: " << a[0] << endl;
+ left = SimplifyTerm(a[0]);
+ //cerr << "Output of simplifyterm:left: " << left << endl;
+ //cerr << "Input to simplifyterm: right: " << a[1] << endl;
+ right = SimplifyTerm(a[1]);
+ //cerr << "Output of simplifyterm:left: " << right << endl;
+ }
+
+ Kind kind = a.GetKind();
+ switch (kind)
+ {
+ case TRUE:
+ output = pushNeg ? ASTFalse : ASTTrue;
+ break;
+ case FALSE:
+ output = pushNeg ? ASTTrue : ASTFalse;
+ break;
+ case SYMBOL:
+ if (!CheckSolverMap(a, output))
+ {
+ output = a;
+ }
+ output = pushNeg ? CreateNode(NOT, output) : output;
+ break;
+ case BVGETBIT:
+ {
+ ASTNode term = SimplifyTerm(a[0]);
+ ASTNode thebit = a[1];
+ ASTNode zero = CreateZeroConst(1);
+ ASTNode one = CreateOneConst(1);
+ ASTNode getthebit = SimplifyTerm(CreateTerm(BVEXTRACT, 1, term, thebit, thebit));
+ if (getthebit == zero)
+ output = pushNeg ? ASTTrue : ASTFalse;
+ else if (getthebit == one)
+ output = pushNeg ? ASTFalse : ASTTrue;
+ else
+ {
+ output = CreateNode(BVGETBIT, term, thebit);
+ output = pushNeg ? CreateNode(NOT, output) : output;
+ }
+ break;
+ }
+ case EQ:
+ {
+ output = CreateSimplifiedEQ(left, right);
+ output = LhsMinusRhs(output);
+ output = ITEOpt_InEqs(output);
+ if (output == ASTTrue)
+ output = pushNeg ? ASTFalse : ASTTrue;
+ else if (output == ASTFalse)
+ output = pushNeg ? ASTTrue : ASTFalse;
+ else
+ output = pushNeg ? CreateNode(NOT, output) : output;
+ break;
+ }
+ case NEQ:
+ {
+ output = CreateSimplifiedEQ(left, right);
+ output = LhsMinusRhs(output);
+ if (output == ASTTrue)
+ output = pushNeg ? ASTTrue : ASTFalse;
+ else if (output == ASTFalse)
+ output = pushNeg ? ASTFalse : ASTTrue;
+ else
+ output = pushNeg ? output : CreateNode(NOT, output);
+ break;
+ }
+ case BVLT:
+ case BVLE:
+ case BVGT:
+ case BVGE:
+ case BVSLT:
+ case BVSLE:
+ case BVSGT:
+ case BVSGE:
+ {
+ //output = CreateNode(kind,left,right);
+ //output = pushNeg ? CreateNode(NOT,output) : output;
+ output = CreateSimplifiedINEQ(kind, left, right, pushNeg);
+ break;
+ }
+ default:
+ FatalError("SimplifyAtomicFormula: NO atomic formula of the kind: ", ASTUndefined, kind);
+ break;
+ }
+
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
+ return output;
+} //end of SimplifyAtomicFormula()
+
+ASTNode BeevMgr::CreateSimplifiedINEQ(Kind k, const ASTNode& left, const ASTNode& right, bool pushNeg)
+{
+ ASTNode output;
+ if (BVCONST == left.GetKind() && BVCONST == right.GetKind())
+ {
+ output = BVConstEvaluator(CreateNode(k, left, right));
+ output = pushNeg ? (ASTFalse == output) ? ASTTrue : ASTFalse : output;
+ return output;
+ }
+
+ unsigned len = left.GetValueWidth();
+ ASTNode zero = CreateZeroConst(len);
+ ASTNode one = CreateOneConst(len);
+ ASTNode max = CreateMaxConst(len);
+ switch (k)
+ {
+ case BVLT:
+ if (right == zero)
+ {
+ output = pushNeg ? ASTTrue : ASTFalse;
+ }
+ else if (left == right)
+ {
+ output = pushNeg ? ASTTrue : ASTFalse;
+ }
+ else if (one == right)
+ {
+ output = CreateSimplifiedEQ(left, zero);
+ output = pushNeg ? CreateNode(NOT, output) : output;
+ }
+ else
+ {
+ output = pushNeg ? CreateNode(BVLE, right, left) : CreateNode(BVLT, left, right);
+ }
+ break;
+ case BVLE:
+ if (left == zero)
+ {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else if (left == right)
+ {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else if (max == right)
+ {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else if (zero == right)
+ {
+ output = CreateSimplifiedEQ(left, zero);
+ output = pushNeg ? CreateNode(NOT, output) : output;
+ }
+ else
+ {
+ output = pushNeg ? CreateNode(BVLT, right, left) : CreateNode(BVLE, left, right);
+ }
+ break;
+ case BVGT:
+ if (left == zero)
+ {
+ output = pushNeg ? ASTTrue : ASTFalse;
+ }
+ else if (left == right)
+ {
+ output = pushNeg ? ASTTrue : ASTFalse;
+ }
+ else
+ {
+ output = pushNeg ? CreateNode(BVLE, left, right) : CreateNode(BVLT, right, left);
+ }
+ break;
+ case BVGE:
+ if (right == zero)
+ {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else if (left == right)
+ {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else
+ {
+ output = pushNeg ? CreateNode(BVLT, left, right) : CreateNode(BVLE, right, left);
+ }
+ break;
+ case BVSLT:
+ case BVSLE:
+ case BVSGE:
+ case BVSGT:
+ {
+ output = CreateNode(k, left, right);
+ output = pushNeg ? CreateNode(NOT, output) : output;
+ }
+ break;
+ default:
+ FatalError("Wrong Kind");
+ break;
+ }
+
+ return output;
+}
+
+//takes care of some simple ITE Optimizations in the context of equations
+ASTNode BeevMgr::ITEOpt_InEqs(const ASTNode& in)
+{
+ CountersAndStats("ITEOpts_InEqs");
+
+ if (!(EQ == in.GetKind() && optimize))
+ {
+ return in;
+ }
+
+ ASTNode output;
+ if (CheckSimplifyMap(in, output, false))
+ {
+ return output;
+ }
+
+ ASTNode in1 = in[0];
+ ASTNode in2 = in[1];
+ Kind k1 = in1.GetKind();
+ Kind k2 = in2.GetKind();
+ if (in1 == in2)
+ {
+ //terms are syntactically the same
+ output = ASTTrue;
+ }
+ else if (BVCONST == k1 && BVCONST == k2)
+ {
+ //here the terms are definitely not syntactically equal but may
+ //be semantically equal.
+ output = ASTFalse;
+ }
+ else if (ITE == k1 && BVCONST == in1[1].GetKind() && BVCONST == in1[2].GetKind() && BVCONST == k2)
+ {
+ //if one side is a BVCONST and the other side is an ITE over
+ //BVCONST then we can do the following optimization:
+ //
+ // c = ITE(cond,c,d) <=> cond
+ //
+ // similarly ITE(cond,c,d) = c <=> cond
+ //
+ // c = ITE(cond,d,c) <=> NOT(cond)
+ //
+ //similarly ITE(cond,d,c) = d <=> NOT(cond)
+ ASTNode cond = in1[0];
+ if (in1[1] == in2)
+ {
+ //ITE(cond, c, d) = c <=> cond
+ output = cond;
+ }
+ else if (in1[2] == in2)
+ {
+ cond = SimplifyFormula(cond, true);
+ output = cond;
+ }
+ else
+ {
+ //last resort is to CreateNode
+ output = CreateNode(EQ, in1, in2);
+ }
+ }
+ else if (ITE == k2 && BVCONST == in2[1].GetKind() && BVCONST == in2[2].GetKind() && BVCONST == k1)
+ {
+ ASTNode cond = in2[0];
+ if (in2[1] == in1)
+ {
+ //ITE(cond, c, d) = c <=> cond
+ output = cond;
+ }
+ else if (in2[2] == in1)
+ {
+ cond = SimplifyFormula(cond, true);
+ output = cond;
+ }
+ else
+ {
+ //last resort is to CreateNode
+ output = CreateNode(EQ, in1, in2);
+ }
+ }
+ else
+ {
+ //last resort is to CreateNode
+ output = CreateNode(EQ, in1, in2);
+ }
+
+ UpdateSimplifyMap(in, output, false);
+ return output;
+} //End of ITEOpts_InEqs()
+
+//Tries to simplify the input to TRUE/FALSE. if it fails, then
+//return the constructed equality
+ASTNode BeevMgr::CreateSimplifiedEQ(const ASTNode& in1, const ASTNode& in2)
+{
+ CountersAndStats("CreateSimplifiedEQ");
+ Kind k1 = in1.GetKind();
+ Kind k2 = in2.GetKind();
+
+ if (!optimize)
+ {
+ return CreateNode(EQ, in1, in2);
+ }
+
+ if (in1 == in2)
+ //terms are syntactically the same
+ return ASTTrue;
+
+ //here the terms are definitely not syntactically equal but may be
+ //semantically equal.
+ if (BVCONST == k1 && BVCONST == k2)
+ return ASTFalse;
+
//last resort is to CreateNode
- output = CreateNode(EQ,in1,in2);
- }
- }
- else {
- //last resort is to CreateNode
- output = CreateNode(EQ,in1,in2);
- }
-
- UpdateSimplifyMap(in,output,false);
- return output;
- } //End of ITEOpts_InEqs()
-
- //Tries to simplify the input to TRUE/FALSE. if it fails, then
- //return the constructed equality
- ASTNode BeevMgr::CreateSimplifiedEQ(const ASTNode& in1, const ASTNode& in2) {
- CountersAndStats("CreateSimplifiedEQ");
- Kind k1 = in1.GetKind();
- Kind k2 = in2.GetKind();
-
- if(!optimize) {
- return CreateNode(EQ,in1,in2);
- }
-
- if(in1 == in2)
- //terms are syntactically the same
- return ASTTrue;
-
- //here the terms are definitely not syntactically equal but may be
- //semantically equal.
- if(BVCONST == k1 && BVCONST == k2)
- return ASTFalse;
-
-
- //last resort is to CreateNode
- return CreateNode(EQ,in1,in2);
- }
-
- //accepts cond == t1, then part is t2, and else part is t3
- ASTNode BeevMgr::CreateSimplifiedTermITE(const ASTNode& in0,
- const ASTNode& in1, const ASTNode& in2) {
- ASTNode t0 = in0;
- ASTNode t1 = in1;
- ASTNode t2 = in2;
- CountersAndStats("CreateSimplifiedITE");
- if(!optimize) {
- if(t1.GetValueWidth() != t2.GetValueWidth()) {
- cerr << "t2 is : = " << t2;
- FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match",t1);
- }
- if(t1.GetIndexWidth() != t2.GetIndexWidth()) {
- cerr << "t2 is : = " << t2;
- FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match",t1);
- }
- return CreateTerm(ITE,t1.GetValueWidth(),t0,t1,t2);
- }
-
- if(t0 == ASTTrue)
- return t1;
- if (t0 == ASTFalse)
- return t2;
- if(t1 == t2)
- return t1;
- if(CheckAlwaysTrueFormMap(t0)) {
- return t1;
- }
- if(CheckAlwaysTrueFormMap(CreateNode(NOT,t0)) ||
- (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
- return t2;
- }
-
- return CreateTerm(ITE,t1.GetValueWidth(),t0,t1,t2);
- }
-
-ASTNode BeevMgr::CreateSimplifiedFormulaITE(const ASTNode& in0, const ASTNode& in1, const ASTNode& in2) {
+ return CreateNode(EQ, in1, in2);
+}
+
+//accepts cond == t1, then part is t2, and else part is t3
+ASTNode BeevMgr::CreateSimplifiedTermITE(const ASTNode& in0, const ASTNode& in1, const ASTNode& in2)
+{
+ ASTNode t0 = in0;
+ ASTNode t1 = in1;
+ ASTNode t2 = in2;
+ CountersAndStats("CreateSimplifiedITE");
+ if (!optimize)
+ {
+ if (t1.GetValueWidth() != t2.GetValueWidth())
+ {
+ cerr << "t2 is : = " << t2;
+ FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match", t1);
+ }
+ if (t1.GetIndexWidth() != t2.GetIndexWidth())
+ {
+ cerr << "t2 is : = " << t2;
+ FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match", t1);
+ }
+ return CreateTerm(ITE, t1.GetValueWidth(), t0, t1, t2);
+ }
+
+ if (t0 == ASTTrue)
+ return t1;
+ if (t0 == ASTFalse)
+ return t2;
+ if (t1 == t2)
+ return t1;
+ if (CheckAlwaysTrueFormMap(t0))
+ {
+ return t1;
+ }
+ if (CheckAlwaysTrueFormMap(CreateNode(NOT, t0)) || (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0])))
+ {
+ return t2;
+ }
+
+ return CreateTerm(ITE, t1.GetValueWidth(), t0, t1, t2);
+}
+
+ASTNode BeevMgr::CreateSimplifiedFormulaITE(const ASTNode& in0, const ASTNode& in1, const ASTNode& in2)
+{
ASTNode t0 = in0;
ASTNode t1 = in1;
ASTNode t2 = in2;
CountersAndStats("CreateSimplifiedFormulaITE");
- if (optimize) {
+ if (optimize)
+ {
if (t0 == ASTTrue)
return t1;
if (t0 == ASTFalse)
return t2;
if (t1 == t2)
return t1;
- if (CheckAlwaysTrueFormMap(t0)) {
+ if (CheckAlwaysTrueFormMap(t0))
+ {
return t1;
}
- if (CheckAlwaysTrueFormMap(CreateNode(NOT, t0)) || (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
+ if (CheckAlwaysTrueFormMap(CreateNode(NOT, t0)) || (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0])))
+ {
return t2;
}
}
return result;
}
+ASTNode BeevMgr::SimplifyAndOrFormula(const ASTNode& a, bool pushNeg)
+{
+ ASTNode output;
+ //cerr << "input:\n" << a << endl;
+
+ if (CheckSimplifyMap(a, output, pushNeg))
+ return output;
+
+ ASTVec c, outvec;
+ c = a.GetChildren();
+ ASTNode flat = FlattenOneLevel(a);
+ c = flat.GetChildren();
+ SortByArith(c);
+
+ Kind k = a.GetKind();
+ bool isAnd = (k == AND) ? true : false;
+
+ ASTNode annihilator = isAnd ? (pushNeg ? ASTTrue : ASTFalse) : (pushNeg ? ASTFalse : ASTTrue);
+
+ ASTNode identity = isAnd ? (pushNeg ? ASTFalse : ASTTrue) : (pushNeg ? ASTTrue : ASTFalse);
+
+ //do the work
+ ASTVec::const_iterator next_it;
+ for (ASTVec::const_iterator i = c.begin(), iend = c.end(); i != iend; i++)
+ {
+ ASTNode aaa = *i;
+ next_it = i + 1;
+ bool nextexists = (next_it < iend);
+
+ aaa = SimplifyFormula(aaa, pushNeg);
+ if (annihilator == aaa)
+ {
+ //memoize
+ UpdateSimplifyMap(*i, annihilator, pushNeg);
+ UpdateSimplifyMap(a, annihilator, pushNeg);
+ //cerr << "annihilator1: output:\n" << annihilator << endl;
+ return annihilator;
+ }
+ ASTNode bbb = ASTFalse;
+ if (nextexists)
+ {
+ bbb = SimplifyFormula(*next_it, pushNeg);
+ }
+ if (nextexists && bbb == aaa)
+ {
+ //skip the duplicate aaa. *next_it will be included
+ }
+ else if (nextexists && ((bbb.GetKind() == NOT && bbb[0] == aaa)))
+ {
+ //memoize
+ UpdateSimplifyMap(a, annihilator, pushNeg);
+ //cerr << "annihilator2: output:\n" << annihilator << endl;
+ return annihilator;
+ }
+ else if (identity == aaa)
+ {
+ // //drop identites
+ }
+ else if ((!isAnd && !pushNeg) || (isAnd && pushNeg))
+ {
+ outvec.push_back(aaa);
+ }
+ else if ((isAnd && !pushNeg) || (!isAnd && pushNeg))
+ {
+ outvec.push_back(aaa);
+ }
+ else
+ {
+ outvec.push_back(aaa);
+ }
+ }
- ASTNode BeevMgr::SimplifyAndOrFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- //cerr << "input:\n" << a << endl;
-
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
+ switch (outvec.size())
+ {
+ case 0:
+ {
+ //only identities were dropped
+ output = identity;
+ break;
+ }
+ case 1:
+ {
+ output = SimplifyFormula(outvec[0], false);
+ break;
+ }
+ default:
+ {
+ output = (isAnd) ? (pushNeg ? CreateNode(OR, outvec) : CreateNode(AND, outvec)) : (pushNeg ? CreateNode(AND, outvec) : CreateNode(OR,
+ outvec));
+ //output = FlattenOneLevel(output);
+ break;
+ }
+ }
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
+ //cerr << "output:\n" << output << endl;
+ return output;
+} //end of SimplifyAndOrFormula
- ASTVec c, outvec;
- c = a.GetChildren();
- ASTNode flat = FlattenOneLevel(a);
- c = flat.GetChildren();
- SortByArith(c);
- Kind k = a.GetKind();
- bool isAnd = (k == AND) ? true : false;
+ASTNode BeevMgr::SimplifyNotFormula(const ASTNode& a, bool pushNeg)
+{
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, pushNeg))
+ return output;
+
+ if (!(a.Degree() == 1 && NOT == a.GetKind()))
+ FatalError("SimplifyNotFormula: input vector with more than 1 node", ASTUndefined);
+
+ //if pushNeg is set then there is NOT on top
+ unsigned int NotCount = pushNeg ? 1 : 0;
+ ASTNode o = a;
+ //count the number of NOTs in 'a'
+ while (NOT == o.GetKind())
+ {
+ o = o[0];
+ NotCount++;
+ }
- ASTNode annihilator = isAnd ?
- (pushNeg ? ASTTrue : ASTFalse):
- (pushNeg ? ASTFalse : ASTTrue);
+ //pushnegation if there are odd number of NOTs
+ bool pn = (NotCount % 2 == 0) ? false : true;
- ASTNode identity = isAnd ?
- (pushNeg ? ASTFalse : ASTTrue):
- (pushNeg ? ASTTrue : ASTFalse);
+ if (CheckAlwaysTrueFormMap(o))
+ {
+ output = pn ? ASTFalse : ASTTrue;
+ return output;
+ }
- //do the work
- ASTVec::const_iterator next_it;
- for(ASTVec::const_iterator i=c.begin(),iend=c.end();i!=iend;i++) {
- ASTNode aaa = *i;
- next_it = i+1;
- bool nextexists = (next_it < iend);
+ if (CheckSimplifyMap(o, output, pn))
+ {
+ return output;
+ }
- aaa = SimplifyFormula(aaa,pushNeg);
- if(annihilator == aaa) {
- //memoize
- UpdateSimplifyMap(*i,annihilator,pushNeg);
- UpdateSimplifyMap(a, annihilator,pushNeg);
- //cerr << "annihilator1: output:\n" << annihilator << endl;
- return annihilator;
- }
- ASTNode bbb = ASTFalse;
- if(nextexists) {
- bbb = SimplifyFormula(*next_it,pushNeg);
- }
- if(nextexists && bbb == aaa) {
- //skip the duplicate aaa. *next_it will be included
- }
- else if(nextexists &&
- ((bbb.GetKind() == NOT && bbb[0] == aaa))) {
- //memoize
- UpdateSimplifyMap(a, annihilator,pushNeg);
- //cerr << "annihilator2: output:\n" << annihilator << endl;
- return annihilator;
- }
- else if(identity == aaa) {
- // //drop identites
- }
- else if((!isAnd && !pushNeg) ||
- (isAnd && pushNeg)) {
- outvec.push_back(aaa);
- }
- else if((isAnd && !pushNeg) ||
- (!isAnd && pushNeg)) {
- outvec.push_back(aaa);
- }
- else {
- outvec.push_back(aaa);
- }
- }
-
- switch(outvec.size()) {
- case 0: {
- //only identities were dropped
- output = identity;
- break;
- }
- case 1: {
- output = SimplifyFormula(outvec[0],false);
- break;
- }
- default: {
- output = (isAnd) ?
- (pushNeg ? CreateNode(OR,outvec) : CreateNode(AND,outvec)):
- (pushNeg ? CreateNode(AND,outvec) : CreateNode(OR,outvec));
- //output = FlattenOneLevel(output);
- break;
- }
- }
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- //cerr << "output:\n" << output << endl;
- return output;
- } //end of SimplifyAndOrFormula
-
-
- ASTNode BeevMgr::SimplifyNotFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- if(!(a.Degree() == 1 && NOT == a.GetKind()))
- FatalError("SimplifyNotFormula: input vector with more than 1 node",ASTUndefined);
-
- //if pushNeg is set then there is NOT on top
- unsigned int NotCount = pushNeg ? 1 : 0;
- ASTNode o = a;
- //count the number of NOTs in 'a'
- while(NOT == o.GetKind()) {
- o = o[0];
- NotCount++;
- }
-
- //pushnegation if there are odd number of NOTs
- bool pn = (NotCount % 2 == 0) ? false : true;
-
- if(CheckAlwaysTrueFormMap(o)) {
- output = pn ? ASTFalse : ASTTrue;
- return output;
- }
-
- if(CheckSimplifyMap(o,output,pn)) {
- return output;
- }
-
- if (ASTTrue == o) {
- output = pn ? ASTFalse : ASTTrue;
- }
- else if (ASTFalse == o) {
- output = pn ? ASTTrue : ASTFalse;
- }
- else {
- output = SimplifyFormula(o,pn);
- }
- //memoize
- UpdateSimplifyMap(o,output,pn);
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyXorFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- if (a.GetChildren().size() > 2) {
- FatalError("Simplify got an XOR with more than two children.");
- }
-
- ASTNode a0 = SimplifyFormula(a[0],false);
- ASTNode a1 = SimplifyFormula(a[1],false);
- output = pushNeg ? CreateNode(IFF,a0,a1) : CreateNode(XOR,a0,a1);
-
- if(XOR == output.GetKind()) {
- a0 = output[0];
- a1 = output[1];
- if(a0 == a1)
- output = ASTFalse;
- else if(a0 == ASTTrue && a1 == ASTFalse ||
- a0 == ASTFalse && a1 == ASTTrue)
- output = ASTTrue;
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyNandFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output,a0,a1;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- //the two NOTs cancel out
- if(pushNeg) {
- a0 = SimplifyFormula(a[0],false);
- a1 = SimplifyFormula(a[1],false);
- output = CreateNode(AND,a0,a1);
- }
- else {
- //push the NOT implicit in the NAND
- a0 = SimplifyFormula(a[0],true);
- a1 = SimplifyFormula(a[1],true);
- output = CreateNode(OR,a0,a1);
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyNorFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output,a0,a1;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- //the two NOTs cancel out
- if(pushNeg) {
- a0 = SimplifyFormula(a[0],false);
- a1 = SimplifyFormula(a[1],false);
- output = CreateNode(OR,a0,a1);
- }
- else {
- //push the NOT implicit in the NAND
- a0 = SimplifyFormula(a[0],true);
- a1 = SimplifyFormula(a[1],true);
- output = CreateNode(AND,a0,a1);
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyImpliesFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- if(!(a.Degree()==2 && IMPLIES==a.GetKind()))
- FatalError("SimplifyImpliesFormula: vector with wrong num of nodes",ASTUndefined);
-
- ASTNode c0,c1;
- if(pushNeg) {
- c0 = SimplifyFormula(a[0],false);
- c1 = SimplifyFormula(a[1],true);
- output = CreateNode(AND,c0,c1);
- }
- else {
- c0 = SimplifyFormula(a[0],false);
- c1 = SimplifyFormula(a[1],false);
- if(ASTFalse == c0) {
- output = ASTTrue;
- }
- else if (ASTTrue == c0) {
- output = c1;
- }
- else if (c0 == c1) {
- output = ASTTrue;
- }
- else if(CheckAlwaysTrueFormMap(c0)) {
- // c0 AND (~c0 OR c1) <==> c1
- //
- //applying modus ponens
- output = c1;
- }
- else if(CheckAlwaysTrueFormMap(c1) ||
- CheckAlwaysTrueFormMap(CreateNode(NOT,c0)) ||
- (NOT == c0.GetKind() && CheckAlwaysTrueFormMap(c0[0]))) {
- //(~c0 AND (~c0 OR c1)) <==> TRUE
- //
- //(c0 AND ~c0->c1) <==> TRUE
- output = ASTTrue;
- }
- else if (CheckAlwaysTrueFormMap(CreateNode(NOT,c1)) ||
- (NOT == c1.GetKind() && CheckAlwaysTrueFormMap(c1[0]))) {
- //(~c1 AND c0->c1) <==> (~c1 AND ~c1->~c0) <==> ~c0
- //(c1 AND c0->~c1) <==> (c1 AND c1->~c0) <==> ~c0
- output = CreateNode(NOT,c0);
- }
- else {
- if(NOT == c0.GetKind()) {
- output = CreateNode(OR,c0[0],c1);
- }
- else {
- output = CreateNode(OR,CreateNode(NOT,c0),c1);
- }
- }
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyIffFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- if(!(a.Degree()==2 && IFF==a.GetKind()))
- FatalError("SimplifyIffFormula: vector with wrong num of nodes",ASTUndefined);
-
- ASTNode c0 = a[0];
- ASTNode c1 = SimplifyFormula(a[1],false);
-
- if(pushNeg)
- c0 = SimplifyFormula(c0,true);
- else
- c0 = SimplifyFormula(c0,false);
-
- if(ASTTrue == c0) {
- output = c1;
- }
- else if (ASTFalse == c0) {
- output = SimplifyFormula(c1,true);
- }
- else if (ASTTrue == c1) {
- output = c0;
- }
- else if (ASTFalse == c1) {
- output = SimplifyFormula(c0,true);
- }
- else if (c0 == c1) {
- output = ASTTrue;
- }
- else if((NOT == c0.GetKind() && c0[0] == c1) ||
- (NOT == c1.GetKind() && c0 == c1[0])) {
- output = ASTFalse;
- }
- else if(CheckAlwaysTrueFormMap(c0)) {
- output = c1;
- }
- else if(CheckAlwaysTrueFormMap(c1)) {
- output = c0;
- }
- else if(CheckAlwaysTrueFormMap(CreateNode(NOT,c0))) {
- output = CreateNode(NOT,c1);
- }
- else if(CheckAlwaysTrueFormMap(CreateNode(NOT,c1))) {
- output = CreateNode(NOT,c0);
- }
- else {
- output = CreateNode(IFF,c0,c1);
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyIteFormula(const ASTNode& b, bool pushNeg) {
- if(!optimize)
- return b;
-
- ASTNode output;
- if(CheckSimplifyMap(b,output,pushNeg))
- return output;
-
- if(!(b.Degree() == 3 && ITE == b.GetKind()))
- FatalError("SimplifyIteFormula: vector with wrong num of nodes",ASTUndefined);
-
- ASTNode a = b;
- ASTNode t0 = SimplifyFormula(a[0],false);
- ASTNode t1,t2;
- if(pushNeg) {
- t1 = SimplifyFormula(a[1],true);
- t2 = SimplifyFormula(a[2],true);
- }
- else {
- t1 = SimplifyFormula(a[1],false);
- t2 = SimplifyFormula(a[2],false);
- }
-
- if(ASTTrue == t0) {
- output = t1;
- }
- else if (ASTFalse == t0) {
- output = t2;
- }
- else if (t1 == t2) {
- output = t1;
- }
- else if(ASTTrue == t1 && ASTFalse == t2) {
- output = t0;
- }
- else if(ASTFalse == t1 && ASTTrue == t2) {
- output = SimplifyFormula(t0,true);
- }
- else if(ASTTrue == t1) {
- output = CreateNode(OR,t0,t2);
- }
- else if(ASTFalse == t1) {
- output = CreateNode(AND,CreateNode(NOT,t0),t2);
- }
- else if(ASTTrue == t2) {
- output = CreateNode(OR,CreateNode(NOT,t0),t1);
- }
- else if(ASTFalse == t2) {
- output = CreateNode(AND,t0,t1);
- }
- else if(CheckAlwaysTrueFormMap(t0)) {
- output = t1;
- }
- else if(CheckAlwaysTrueFormMap(CreateNode(NOT,t0)) ||
- (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
- output = t2;
- }
- else {
- output = CreateNode(ITE,t0,t1,t2);
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- //one level deep flattening
- ASTNode BeevMgr::FlattenOneLevel(const ASTNode& a) {
- Kind k = a.GetKind();
- if(!(BVPLUS == k ||
- AND == k || OR == k
- //|| BVAND == k
- //|| BVOR == k
- )
- ) {
- return a;
- }
-
- ASTNode output;
- // if(CheckSimplifyMap(a,output,false)) {
- // //check memo table
- // //cerr << "output of SimplifyTerm Cache: " << output << endl;
- // return output;
- // }
-
- ASTVec c = a.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = *it;
- if(k == aaa.GetKind()) {
- ASTVec ac = aaa.GetChildren();
- o.insert(o.end(),ac.begin(),ac.end());
- }
- else
- o.push_back(aaa);
- }
-
- if(is_Form_kind(k))
- output = CreateNode(k,o);
- else
- output = CreateTerm(k,a.GetValueWidth(),o);
-
- //UpdateSimplifyMap(a,output,false);
- return output;
- //memoize
- } //end of flattenonelevel()
-
- ASTNode BeevMgr::SimplifyTerm_TopLevel(const ASTNode& b) {
- ResetSimplifyMaps();
- ASTNode out = SimplifyTerm(b);
- ResetSimplifyMaps();
- return out;
- }
-
- //This function simplifies terms based on their kind
- ASTNode BeevMgr::SimplifyTerm(const ASTNode& inputterm) {
- //cout << "SimplifyTerm: input: " << a << endl;
- if(!optimize) {
- return inputterm;
- }
-
- ASTNode output;
- BVTypeCheck(inputterm);
-
- //########################################
- //########################################
-
- if(wordlevel_solve && CheckSolverMap(inputterm,output)) {
- //cout << "SimplifyTerm: output: " << output << endl;
- return SimplifyTerm(output);
- }
-
-
- if(CheckSimplifyMap(inputterm,output,false)) {
- //cerr << "output of SimplifyTerm Cache: " << output << endl;
- return output;
- }
- //########################################
- //########################################
-
- Kind k = inputterm.GetKind();
- if(!is_Term_kind(k)) {
- FatalError("SimplifyTerm: You have input a Non-term",ASTUndefined);
- }
-
- unsigned int inputValueWidth = inputterm.GetValueWidth();
- switch(k) {
- case BVCONST:
- output = inputterm;
- break;
- case SYMBOL:
- if(CheckSolverMap(inputterm,output)) {
- return SimplifyTerm(output);
- }
- output = inputterm;
- break;
- case BVMULT:
- {
- if(2 != inputterm.Degree())
- {
- FatalError("SimplifyTerm: We assume that BVMULT is binary",inputterm);
- }
-
- // Described nicely by Warren, Hacker's Delight pg 135.
- // Turn sequences of one bits into subtractions.
- // 28*x == 32x - 4x (two instructions), rather than 16x+ 8x+ 4x.
- // When fully implemented. I.e. supporting sequences of 1 anywhere.
- // Other simplifications will try to fold these back in. So need to be careful
- // about when the simplifications are applied. But in this version it won't
- // be simplified down by anything else.
-
-
- // This (temporary) version only simplifies if all the left most bits are set.
- // All the leftmost bits being set simplifies very nicely down.
- const ASTNode& n0 = inputterm.GetChildren()[0];
- const ASTNode& n1 = inputterm.GetChildren()[1];
-
- // This implementation has two problems.
- // 1) It causes a segfault for cmu-model15,16,17
- // 2) It doesn't count the number of bits saved, so if there is a single
- // leading bit it will invert it. Even though that will take more shifts
- // and adds when it's finally done.
-
- // disabled.
- if (false && (BVCONST == n0.GetKind()) ^ (BVCONST == n1.GetKind()))
- {
- CBV constant = (BVCONST == n0.GetKind())? n0.GetBVConst(): n1.GetBVConst();
- ASTNode other = (BVCONST == n0.GetKind())? n1: n0;
-
- int startSequence = 0;
- for (unsigned int i = 0; i < inputValueWidth; i++)
- {
- if (!CONSTANTBV::BitVector_bit_test(constant,i))
- startSequence = i;
- }
-
- if((inputValueWidth - startSequence) > 3)
- {
- // turn off all bits from "startSequence to the end", then add one.
- CBV maskedPlusOne = CONSTANTBV::BitVector_Create(inputValueWidth,true);
- for (int i=0; i < startSequence;i++)
- {
- if (!CONSTANTBV::BitVector_bit_test(constant,i)) // swap
- CONSTANTBV::BitVector_Bit_On(maskedPlusOne, i);
- }
- CONSTANTBV::BitVector_increment(maskedPlusOne);
- ASTNode temp = CreateTerm(BVMULT,inputValueWidth, CreateBVConst(maskedPlusOne,inputValueWidth),other);
- output = CreateTerm(BVNEG, inputValueWidth, temp);
- }
- }
-
- }
- if(NULL != output)
- break;
-
- case BVPLUS:{
-
- ASTVec c = FlattenOneLevel(inputterm).GetChildren();
- SortByArith(c);
- ASTVec constkids, nonconstkids;
-
- //go through the childnodes, and separate constant and
- //nonconstant nodes. combine the constant nodes using the
- //constevaluator. if the resultant constant is zero and k ==
- //BVPLUS, then ignore it (similarily for 1 and BVMULT). else,
- //add the computed constant to the nonconst vector, flatten,
- //sort, and create BVPLUS/BVMULT and return
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST == aaa.GetKind()) {
- constkids.push_back(aaa);
- }
- else {
- nonconstkids.push_back(aaa);
- }
- }
-
- ASTNode one = CreateOneConst(inputValueWidth);
- ASTNode max = CreateMaxConst(inputValueWidth);
- ASTNode zero = CreateZeroConst(inputValueWidth);
-
- //initialize constoutput to zero, in case there are no elements
- //in constkids
- ASTNode constoutput = (k == BVPLUS) ? zero : one;
-
- if(1 == constkids.size()) {
- //only one element in constkids
- constoutput = constkids[0];
- }
- else if (1 < constkids.size()) {
- //many elements in constkids. simplify it
- constoutput = CreateTerm(k,inputterm.GetValueWidth(),constkids);
- constoutput = BVConstEvaluator(constoutput);
- }
-
- if(BVMULT == k && zero == constoutput) {
- output = zero;
- }
- else if(BVMULT == k &&
- 1 == nonconstkids.size() &&
- constoutput == max) {
- //useful special case opt: when input is BVMULT(max_const,t),
- //then output = BVUMINUS(t). this is easier on the bitblaster
- output = CreateTerm(BVUMINUS,inputValueWidth,nonconstkids);
- }
- else {
- if(0 < nonconstkids.size()) {
- //nonconstkids is not empty. First, combine const and
- //nonconstkids
- if(BVPLUS == k && constoutput != zero) {
- nonconstkids.push_back(constoutput);
- }
- else if(BVMULT == k && constoutput != one) {
- nonconstkids.push_back(constoutput);
- }
-
- if(1 == nonconstkids.size()) {
- //exactly one element in nonconstkids. output is exactly
- //nonconstkids[0]
- output = nonconstkids[0];
- }
- else {
- //more than 1 element in nonconstkids. create BVPLUS term
- SortByArith(nonconstkids);
- output = CreateTerm(k,inputValueWidth,nonconstkids);
- output = FlattenOneLevel(output);
- output = DistributeMultOverPlus(output,true);
- output = CombineLikeTerms(output);
- }
- }
- else {
- //nonconstkids was empty, all childnodes were constant, hence
- //constoutput is the output.
- output = constoutput;
- }
- }
- if(BVMULT == output.GetKind()
- || BVPLUS == output.GetKind()
- ) {
- ASTVec d = output.GetChildren();
- SortByArith(d);
- output = CreateTerm(output.GetKind(),output.GetValueWidth(),d);
- }
- break;
- }
- case BVSUB: {
- ASTVec c = inputterm.GetChildren();
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- ASTNode a1 = SimplifyTerm(inputterm[1]);
- unsigned int l = inputValueWidth;
- if(a0 == a1)
- output = CreateZeroConst(l);
- else {
- //covert x-y into x+(-y) and simplify. this transformation
- //triggers more simplifications
- //
- a1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a1));
- output = SimplifyTerm(CreateTerm(BVPLUS,l,a0,a1));
- }
- break;
- }
- case BVUMINUS: {
- //important to treat BVUMINUS as a special case, because it
- //helps in arithmetic transformations. e.g. x + BVUMINUS(x) is
- //actually 0. One way to reveal this fact is to strip bvuminus
- //out, and replace with something else so that combineliketerms
- //can catch this fact.
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- Kind k1 = a0.GetKind();
- unsigned int l = a0.GetValueWidth();
- ASTNode one = CreateOneConst(l);
- switch(k1) {
- case BVUMINUS:
- output = a0[0];
- break;
- case BVCONST: {
- output = BVConstEvaluator(CreateTerm(BVUMINUS,l,a0));
- break;
- }
- case BVNEG: {
- output = SimplifyTerm(CreateTerm(BVPLUS,l,a0[0],one));
- break;
- }
- case BVMULT: {
- if(BVUMINUS == a0[0].GetKind()) {
- output = CreateTerm(BVMULT,l,a0[0][0],a0[1]);
- }
- else if(BVUMINUS == a0[1].GetKind()) {
- output = CreateTerm(BVMULT,l,a0[0],a0[1][0]);
- }
- else {
- ASTNode a00 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[0]));
- output = CreateTerm(BVMULT,l,a00,a0[1]);
- }
- break;
- }
- case BVPLUS: {
- //push BVUMINUS over all the monomials of BVPLUS. Simplify
- //along the way
- //
- //BVUMINUS(a1x1 + a2x2 + ...) <=> BVPLUS(BVUMINUS(a1x1) +
- //BVUMINUS(a2x2) + ...
- ASTVec c = a0.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- //Simplify(BVUMINUS(a1x1))
- ASTNode aaa = SimplifyTerm(CreateTerm(BVUMINUS,l,*it));
- o.push_back(aaa);
- }
- //simplify the bvplus
- output = SimplifyTerm(CreateTerm(BVPLUS,l,o));
- break;
- }
- case BVSUB: {
- //BVUMINUS(BVSUB(x,y)) <=> BVSUB(y,x)
- output = SimplifyTerm(CreateTerm(BVSUB,l,a0[1],a0[0]));
- break;
- }
- case ITE: {
- //BVUMINUS(ITE(c,t1,t2)) <==> ITE(c,BVUMINUS(t1),BVUMINUS(t2))
- ASTNode c = a0[0];
- ASTNode t1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[1]));
- ASTNode t2 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[2]));
- output = CreateSimplifiedTermITE(c,t1,t2);
- break;
- }
- default: {
- output = CreateTerm(BVUMINUS,l,a0);
- break;
- }
- }
- break;
- }
- case BVEXTRACT:{
- //it is important to take care of wordlevel transformation in
- //BVEXTRACT. it exposes oppurtunities for later simplification
- //and solving (variable elimination)
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- Kind k1 = a0.GetKind();
- unsigned int a_len = inputValueWidth;
-
- //indices for BVEXTRACT
- ASTNode i = inputterm[1];
- ASTNode j = inputterm[2];
- ASTNode zero = CreateBVConst(32,0);
- //recall that the indices of BVEXTRACT are always 32 bits
- //long. therefore doing a GetBVUnsigned is ok.
- unsigned int i_val = GetUnsignedConst(i);
- unsigned int j_val = GetUnsignedConst(j);
-
- // a0[i:0] and len(a0)=i+1, then return a0
- if(0 == j_val && a_len == a0.GetValueWidth())
- return a0;
-
- switch(k1) {
- case BVCONST: {
- //extract the constant
- output = BVConstEvaluator(CreateTerm(BVEXTRACT,a_len,a0,i,j));
- break;
- }
- case BVCONCAT:{
- //assumes concatenation is binary
- //
- //input is of the form a0[i:j]
- //
- //a0 is the conatentation t@u, and a0[0] is t, and a0[1] is u
- ASTNode t = a0[0];
- ASTNode u = a0[1];
- unsigned int len_a0 = a0.GetValueWidth();
- unsigned int len_u = u.GetValueWidth();
-
- if(len_u > i_val) {
- //Apply the following rule:
- // (t@u)[i:j] <==> u[i:j], if len(u) > i
- //
- output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
- }
- else if(len_a0 > i_val && j_val >= len_u) {
- //Apply the rule:
- // (t@u)[i:j] <==> t[i-len_u:j-len_u], if len(t@u) > i >= j >= len(u)
- i = CreateBVConst(32, i_val - len_u);
- j = CreateBVConst(32, j_val - len_u);
- output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- }
- else {
- //Apply the rule:
- // (t@u)[i:j] <==> t[i-len_u:0] @ u[len_u-1:j]
- i = CreateBVConst(32,i_val-len_u);
- ASTNode m = CreateBVConst(32, len_u-1);
- t = SimplifyTerm(CreateTerm(BVEXTRACT,i_val-len_u+1,t,i,zero));
- u = SimplifyTerm(CreateTerm(BVEXTRACT,len_u-j_val,u,m,j));
- output = CreateTerm(BVCONCAT,a_len,t,u);
- }
- break;
- }
- case BVPLUS:
- case BVMULT: {
- // (BVMULT(n,t,u))[i:j] <==> BVMULT(i+1,t[i:0],u[i:0])[i:j]
- //similar rule for BVPLUS
- ASTVec c = a0.GetChildren();
- ASTVec o;
- for(ASTVec::iterator jt=c.begin(),jtend=c.end();jt!=jtend;jt++) {
- ASTNode aaa = *jt;
- aaa = SimplifyTerm(CreateTerm(BVEXTRACT,i_val+1,aaa,i,zero));
- o.push_back(aaa);
- }
- output = CreateTerm(a0.GetKind(),i_val+1,o);
- if(j_val != 0) {
- //add extraction only if j is not zero
- output = CreateTerm(BVEXTRACT,a_len,output,i,j);
- }
- break;
- }
- case BVAND:
- case BVOR:
- case BVXOR: {
- //assumes these operators are binary
- //
- // (t op u)[i:j] <==> t[i:j] op u[i:j]
- ASTNode t = a0[0];
- ASTNode u = a0[1];
- t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- u = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
- BVTypeCheck(t);
- BVTypeCheck(u);
- output = CreateTerm(k1,a_len,t,u);
- break;
- }
- case BVNEG:{
- // (~t)[i:j] <==> ~(t[i:j])
- ASTNode t = a0[0];
- t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- output = CreateTerm(BVNEG,a_len,t);
- break;
- }
- // case BVSX:{
-// //(BVSX(t,n)[i:j] <==> BVSX(t,i+1), if n >= i+1 and j=0
-// ASTNode t = a0[0];
-// unsigned int bvsx_len = a0.GetValueWidth();
-// if(bvsx_len < a_len) {
-// FatalError("SimplifyTerm: BVEXTRACT over BVSX:"
-// "the length of BVSX term must be greater than extract-len",inputterm);
-// }
-// if(j != zero) {
-// output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
-// }
-// else {
-// output = CreateTerm(BVSX,a_len,t,CreateBVConst(32,a_len));
-// }
-// break;
-// }
- case ITE: {
- ASTNode t0 = a0[0];
- ASTNode t1 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[1],i,j));
- ASTNode t2 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[2],i,j));
- output = CreateSimplifiedTermITE(t0,t1,t2);
- break;
- }
- default: {
- output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
- break;
- }
- }
- break;
- }
- case BVNEG: {
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- unsigned len = inputValueWidth;
- switch(a0.GetKind()) {
- case BVCONST:
- output = BVConstEvaluator(CreateTerm(BVNEG,len,a0));
- break;
- case BVNEG:
- output = a0[0];
- break;
- // case ITE: {
-// ASTNode cond = a0[0];
-// ASTNode thenpart = SimplifyTerm(CreateTerm(BVNEG,len,a0[1]));
-// ASTNode elsepart = SimplifyTerm(CreateTerm(BVNEG,len,a0[2]));
-// output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
-// break;
-// }
- default:
- output = CreateTerm(BVNEG,len,a0);
- break;
- }
- break;
- }
-
- case BVZX:
- {
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- if (a0.GetKind() == BVCONST)
- output = BVConstEvaluator(CreateTerm(BVZX,inputValueWidth,a0,inputterm[1]));
+ if (ASTTrue == o)
+ {
+ output = pn ? ASTFalse : ASTTrue;
+ }
+ else if (ASTFalse == o)
+ {
+ output = pn ? ASTTrue : ASTFalse;
+ }
else
- output = CreateTerm(BVZX,inputValueWidth,a0,inputterm[1]);
- }
- break;
-
-
- case BVSX:{
- //a0 is the expr which is being sign extended
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- //a1 represents the length of the term BVSX(a0)
- ASTNode a1 = inputterm[1];
- //output length of the BVSX term
- unsigned len = inputValueWidth;
-
- if(a0.GetValueWidth() == len) {
- //nothing to signextend
- return a0;
- }
-
- switch(a0.GetKind()) {
- case BVCONST:
- output = BVConstEvaluator(CreateTerm(BVSX,len,a0,a1));
- break;
- case BVNEG:
- output = CreateTerm(a0.GetKind(),len,CreateTerm(BVSX,len,a0[0],a1));
- break;
- case BVAND:
- case BVOR:
- //assuming BVAND and BVOR are binary
- output = CreateTerm(a0.GetKind(),len,
- CreateTerm(BVSX,len,a0[0],a1),
- CreateTerm(BVSX,len,a0[1],a1));
- break;
- case BVPLUS: {
- //BVSX(m,BVPLUS(n,BVSX(t1),BVSX(t2))) <==> BVPLUS(m,BVSX(m,t1),BVSX(m,t2))
- ASTVec c = a0.GetChildren();
- bool returnflag = false;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- if(BVSX != it->GetKind()) {
- returnflag = true;
- break;
- }
- }
- if(returnflag) {
- output = CreateTerm(BVSX,len,a0,a1);
- }
- else {
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(CreateTerm(BVSX,len,*it,a1));
- o.push_back(aaa);
- }
- output = CreateTerm(a0.GetKind(),len,o);
- }
- break;
- }
- case BVSX: {
- //if you have BVSX(m,BVSX(n,a)) then you can drop the inner
- //BVSX provided m is greater than n.
- a0 = SimplifyTerm(a0[0]);
- output = CreateTerm(BVSX,len,a0,a1);
- break;
- }
- case ITE: {
- ASTNode cond = a0[0];
- ASTNode thenpart = SimplifyTerm(CreateTerm(BVSX,len,a0[1],a1));
- ASTNode elsepart = SimplifyTerm(CreateTerm(BVSX,len,a0[2],a1));
- output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
- break;
- }
- default:
- output = CreateTerm(BVSX,len,a0,a1);
- break;
- }
- break;
- }
- case BVAND:
- case BVOR:{
- ASTNode max = CreateMaxConst(inputValueWidth);
- ASTNode zero = CreateZeroConst(inputValueWidth);
-
- ASTNode identity = (BVAND == k) ? max : zero;
- ASTNode annihilator = (BVAND == k) ? zero : max;
- ASTVec c = FlattenOneLevel(inputterm).GetChildren();
- SortByArith(c);
- ASTVec o;
- bool constant = true;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST != aaa.GetKind()) {
- constant = false;
- }
-
- if(aaa == annihilator) {
- output = annihilator;
- //memoize
- UpdateSimplifyMap(inputterm,output,false);
- //cerr << "output of SimplifyTerm: " << output << endl;
- return output;
- }
-
- if(aaa != identity) {
- o.push_back(aaa);
- }
- }
-
- switch(o.size()) {
- case 0:
- output = identity;
- break;
- case 1:
- output = o[0];
- break;
- default:
- SortByArith(o);
- output = CreateTerm(k,inputValueWidth,o);
- if(constant) {
- output = BVConstEvaluator(output);
- }
- break;
- }
- break;
- }
- case BVCONCAT:{
- ASTNode t = SimplifyTerm(inputterm[0]);
- ASTNode u = SimplifyTerm(inputterm[1]);
- Kind tkind = t.GetKind();
- Kind ukind = u.GetKind();
-
-
- if(BVCONST == tkind && BVCONST == ukind) {
- output = BVConstEvaluator(CreateTerm(BVCONCAT,inputValueWidth,t,u));
- }
- else if(BVEXTRACT == tkind &&
- BVEXTRACT == ukind &&
- t[0] == u[0]) {
- //to handle the case x[m:n]@x[n-1:k] <==> x[m:k]
- ASTNode t_hi = t[1];
- ASTNode t_low = t[2];
- ASTNode u_hi = u[1];
- ASTNode u_low = u[2];
- ASTNode c = BVConstEvaluator(CreateTerm(BVPLUS,32,u_hi,CreateOneConst(32)));
- if(t_low == c) {
- output = CreateTerm(BVEXTRACT,inputValueWidth,t[0],t_hi,u_low);
- }
- else {
- output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
- }
- }
- else {
- output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
- }
- break;
- }
- case BVXOR:
- case BVXNOR:
- case BVNAND:
- case BVNOR:
- case BVLEFTSHIFT:
- case BVRIGHTSHIFT:
- case BVVARSHIFT:
- case BVSRSHIFT:
- case BVDIV:
- case BVMOD: {
- ASTVec c = inputterm.GetChildren();
- ASTVec o;
- bool constant = true;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST != aaa.GetKind()) {
- constant = false;
- }
- o.push_back(aaa);
- }
- output = CreateTerm(k,inputValueWidth,o);
- if(constant)
- output = BVConstEvaluator(output);
- break;
- }
- case READ: {
- ASTNode out1;
- //process only if not in the substitution map. simplifymap
- //has been checked already
- if(!CheckSubstitutionMap(inputterm,out1)) {
- if(WRITE == inputterm[0].GetKind()) {
- //get rid of all writes
- ASTNode nowrites = RemoveWrites_TopLevel(inputterm);
- out1 = nowrites;
- }
- else if (ITE == inputterm[0].GetKind()){
- ASTNode cond = SimplifyFormula(inputterm[0][0],false);
- ASTNode index = SimplifyTerm(inputterm[1]);
-
- ASTNode read1 = CreateTerm(READ,inputValueWidth,inputterm[0][1],index);
- ASTNode read2 = CreateTerm(READ,inputValueWidth,inputterm[0][2],index);
-
- read1 = SimplifyTerm(read1);
- read2 = SimplifyTerm(read2);
- out1 = CreateSimplifiedTermITE(cond,read1,read2);
- }
- else {
- //arr is a SYMBOL for sure
- ASTNode arr = inputterm[0];
- ASTNode index = SimplifyTerm(inputterm[1]);
- out1 = CreateTerm(READ,inputValueWidth,arr,index);
- }
- }
- //it is possible that after all the procesing the READ term
- //reduces to READ(Symbol,const) and hence we should check the
- //substitutionmap once again.
- if(!CheckSubstitutionMap(out1,output))
- output = out1;
- break;
- }
- case ITE: {
- ASTNode t0 = SimplifyFormula(inputterm[0],false);
- ASTNode t1 = SimplifyTerm(inputterm[1]);
- ASTNode t2 = SimplifyTerm(inputterm[2]);
- output = CreateSimplifiedTermITE(t0,t1,t2);
- break;
- }
- case SBVREM:
- case SBVDIV: {
- ASTVec c = inputterm.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- o.push_back(aaa);
- }
- output = CreateTerm(k,inputValueWidth,o);
- break;
- }
- case WRITE:
- default:
- FatalError("SimplifyTerm: Control should never reach here:", inputterm, k);
- return inputterm;
- break;
- }
- assert(NULL != output);
+ {
+ output = SimplifyFormula(o, pn);
+ }
+ //memoize
+ UpdateSimplifyMap(o, output, pn);
+ UpdateSimplifyMap(a, output, pushNeg);
+ return output;
+}
+ASTNode BeevMgr::SimplifyXorFormula(const ASTNode& a, bool pushNeg)
+{
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, pushNeg))
+ return output;
- //memoize
- UpdateSimplifyMap(inputterm,output,false);
- //cerr << "SimplifyTerm: output" << output << endl;
- // CheckSimplifyInvariant(inputterm,output);
-
- return output;
- } //end of SimplifyTerm()
-
- ASTNode BeevMgr::SimplifyTermAux(const ASTNode& inputterm) {
- //cout << "SimplifyTerm: input: " << a << endl;
- if(!optimize) {
- return inputterm;
- }
-
- ASTNode output;
- BVTypeCheck(inputterm);
-
- //########################################
- //########################################
-
- if(wordlevel_solve && CheckSolverMap(inputterm,output)) {
- //cout << "SimplifyTerm: output: " << output << endl;
- return SimplifyTermAux(output);
- }
-
- Kind k = inputterm.GetKind();
- if(!is_Term_kind(k)) {
- FatalError("SimplifyTerm: You have input a Non-term",ASTUndefined);
- }
-
- unsigned int inputValueWidth = inputterm.GetValueWidth();
- switch(k) {
- case BVCONST:
- output = inputterm;
- break;
- case SYMBOL:
- if(CheckSolverMap(inputterm,output)) {
- return SimplifyTerm(output);
- }
- output = inputterm;
- break;
- case BVMULT:
- case BVPLUS:{
- if(BVMULT == k && 2 != inputterm.Degree()) {
- FatalError("SimplifyTerm: We assume that BVMULT is binary",inputterm);
- }
-
- ASTVec c = FlattenOneLevel(inputterm).GetChildren();
- SortByArith(c);
- ASTVec constkids, nonconstkids;
-
- //go through the childnodes, and separate constant and
- //nonconstant nodes. combine the constant nodes using the
- //constevaluator. if the resultant constant is zero and k ==
- //BVPLUS, then ignore it (similarily for 1 and BVMULT). else,
- //add the computed constant to the nonconst vector, flatten,
- //sort, and create BVPLUS/BVMULT and return
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST == aaa.GetKind()) {
- constkids.push_back(aaa);
- }
- else {
- nonconstkids.push_back(aaa);
- }
- }
-
- ASTNode one = CreateOneConst(inputValueWidth);
- ASTNode max = CreateMaxConst(inputValueWidth);
- ASTNode zero = CreateZeroConst(inputValueWidth);
-
- //initialize constoutput to zero, in case there are no elements
- //in constkids
- ASTNode constoutput = (k == BVPLUS) ? zero : one;
-
- if(1 == constkids.size()) {
- //only one element in constkids
- constoutput = constkids[0];
- }
- else if (1 < constkids.size()) {
- //many elements in constkids. simplify it
- constoutput = CreateTerm(k,inputterm.GetValueWidth(),constkids);
- constoutput = BVConstEvaluator(constoutput);
- }
-
- if(BVMULT == k && zero == constoutput) {
- output = zero;
- }
- else if(BVMULT == k &&
- 1 == nonconstkids.size() &&
- constoutput == max) {
- //useful special case opt: when input is BVMULT(max_const,t),
- //then output = BVUMINUS(t). this is easier on the bitblaster
- output = CreateTerm(BVUMINUS,inputValueWidth,nonconstkids);
- }
- else {
- if(0 < nonconstkids.size()) {
- //nonconstkids is not empty. First, combine const and
- //nonconstkids
- if(BVPLUS == k && constoutput != zero) {
- nonconstkids.push_back(constoutput);
- }
- else if(BVMULT == k && constoutput != one) {
- nonconstkids.push_back(constoutput);
- }
-
- if(1 == nonconstkids.size()) {
- //exactly one element in nonconstkids. output is exactly
- //nonconstkids[0]
- output = nonconstkids[0];
- }
- else {
- //more than 1 element in nonconstkids. create BVPLUS term
- SortByArith(nonconstkids);
- output = CreateTerm(k,inputValueWidth,nonconstkids);
- output = FlattenOneLevel(output);
- output = DistributeMultOverPlus(output,true);
- output = CombineLikeTerms(output);
- }
- }
- else {
- //nonconstkids was empty, all childnodes were constant, hence
- //constoutput is the output.
- output = constoutput;
- }
- }
- if(BVMULT == output.GetKind()
- || BVPLUS == output.GetKind()
- ) {
- ASTVec d = output.GetChildren();
- SortByArith(d);
- output = CreateTerm(output.GetKind(),output.GetValueWidth(),d);
- }
- break;
- }
- case BVSUB: {
- ASTVec c = inputterm.GetChildren();
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- ASTNode a1 = SimplifyTerm(inputterm[1]);
- unsigned int l = inputValueWidth;
- if(a0 == a1)
- output = CreateZeroConst(l);
- else {
- //covert x-y into x+(-y) and simplify. this transformation
- //triggers more simplifications
- //
- a1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a1));
- output = SimplifyTerm(CreateTerm(BVPLUS,l,a0,a1));
- }
- break;
- }
- case BVUMINUS: {
- //important to treat BVUMINUS as a special case, because it
- //helps in arithmetic transformations. e.g. x + BVUMINUS(x) is
- //actually 0. One way to reveal this fact is to strip bvuminus
- //out, and replace with something else so that combineliketerms
- //can catch this fact.
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- Kind k1 = a0.GetKind();
- unsigned int l = a0.GetValueWidth();
- ASTNode one = CreateOneConst(l);
- switch(k1) {
- case BVUMINUS:
- output = a0[0];
- break;
- case BVCONST: {
- output = BVConstEvaluator(CreateTerm(BVUMINUS,l,a0));
- break;
- }
- case BVNEG: {
- output = SimplifyTerm(CreateTerm(BVPLUS,l,a0[0],one));
- break;
- }
- case BVMULT: {
- if(BVUMINUS == a0[0].GetKind()) {
- output = CreateTerm(BVMULT,l,a0[0][0],a0[1]);
- }
- else if(BVUMINUS == a0[1].GetKind()) {
- output = CreateTerm(BVMULT,l,a0[0],a0[1][0]);
- }
- else {
- ASTNode a00 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[0]));
- output = CreateTerm(BVMULT,l,a00,a0[1]);
- }
- break;
- }
- case BVPLUS: {
- //push BVUMINUS over all the monomials of BVPLUS. Simplify
- //along the way
- //
- //BVUMINUS(a1x1 + a2x2 + ...) <=> BVPLUS(BVUMINUS(a1x1) +
- //BVUMINUS(a2x2) + ...
- ASTVec c = a0.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- //Simplify(BVUMINUS(a1x1))
- ASTNode aaa = SimplifyTerm(CreateTerm(BVUMINUS,l,*it));
- o.push_back(aaa);
- }
- //simplify the bvplus
- output = SimplifyTerm(CreateTerm(BVPLUS,l,o));
- break;
- }
- case BVSUB: {
- //BVUMINUS(BVSUB(x,y)) <=> BVSUB(y,x)
- output = SimplifyTerm(CreateTerm(BVSUB,l,a0[1],a0[0]));
- break;
- }
- case ITE: {
- //BVUMINUS(ITE(c,t1,t2)) <==> ITE(c,BVUMINUS(t1),BVUMINUS(t2))
- ASTNode c = a0[0];
- ASTNode t1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[1]));
- ASTNode t2 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[2]));
- output = CreateSimplifiedTermITE(c,t1,t2);
- break;
- }
- default: {
- output = CreateTerm(BVUMINUS,l,a0);
- break;
- }
- }
- break;
- }
- case BVEXTRACT:{
- //it is important to take care of wordlevel transformation in
- //BVEXTRACT. it exposes oppurtunities for later simplification
- //and solving (variable elimination)
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- Kind k1 = a0.GetKind();
- unsigned int a_len = inputValueWidth;
-
- //indices for BVEXTRACT
- ASTNode i = inputterm[1];
- ASTNode j = inputterm[2];
- ASTNode zero = CreateBVConst(32,0);
- //recall that the indices of BVEXTRACT are always 32 bits
- //long. therefore doing a GetBVUnsigned is ok.
- unsigned int i_val = GetUnsignedConst(i);
- unsigned int j_val = GetUnsignedConst(j);
-
- // a0[i:0] and len(a0)=i+1, then return a0
- if(0 == j_val && a_len == a0.GetValueWidth())
- return a0;
-
- switch(k1) {
- case BVCONST: {
- //extract the constant
- output = BVConstEvaluator(CreateTerm(BVEXTRACT,a_len,a0,i,j));
- break;
- }
- case BVCONCAT:{
- //assumes concatenation is binary
- //
- //input is of the form a0[i:j]
- //
- //a0 is the conatentation t@u, and a0[0] is t, and a0[1] is u
- ASTNode t = a0[0];
- ASTNode u = a0[1];
- unsigned int len_a0 = a0.GetValueWidth();
- unsigned int len_u = u.GetValueWidth();
-
- if(len_u > i_val) {
- //Apply the following rule:
- // (t@u)[i:j] <==> u[i:j], if len(u) > i
- //
- output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
- }
- else if(len_a0 > i_val && j_val >= len_u) {
- //Apply the rule:
- // (t@u)[i:j] <==> t[i-len_u:j-len_u], if len(t@u) > i >= j >= len(u)
- i = CreateBVConst(32, i_val - len_u);
- j = CreateBVConst(32, j_val - len_u);
- output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- }
- else {
- //Apply the rule:
- // (t@u)[i:j] <==> t[i-len_u:0] @ u[len_u-1:j]
- i = CreateBVConst(32,i_val-len_u);
- ASTNode m = CreateBVConst(32, len_u-1);
- t = SimplifyTerm(CreateTerm(BVEXTRACT,i_val-len_u+1,t,i,zero));
- u = SimplifyTerm(CreateTerm(BVEXTRACT,len_u-j_val,u,m,j));
- output = CreateTerm(BVCONCAT,a_len,t,u);
- }
- break;
- }
- case BVPLUS:
- case BVMULT: {
- // (BVMULT(n,t,u))[i:j] <==> BVMULT(i+1,t[i:0],u[i:0])[i:j]
- //similar rule for BVPLUS
- ASTVec c = a0.GetChildren();
- ASTVec o;
- for(ASTVec::iterator jt=c.begin(),jtend=c.end();jt!=jtend;jt++) {
- ASTNode aaa = *jt;
- aaa = SimplifyTerm(CreateTerm(BVEXTRACT,i_val+1,aaa,i,zero));
- o.push_back(aaa);
- }
- output = CreateTerm(a0.GetKind(),i_val+1,o);
- if(j_val != 0) {
- //add extraction only if j is not zero
- output = CreateTerm(BVEXTRACT,a_len,output,i,j);
- }
- break;
- }
- case BVAND:
- case BVOR:
- case BVXOR: {
- //assumes these operators are binary
- //
- // (t op u)[i:j] <==> t[i:j] op u[i:j]
- ASTNode t = a0[0];
- ASTNode u = a0[1];
- t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- u = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
- BVTypeCheck(t);
- BVTypeCheck(u);
- output = CreateTerm(k1,a_len,t,u);
- break;
- }
- case BVNEG:{
- // (~t)[i:j] <==> ~(t[i:j])
- ASTNode t = a0[0];
- t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- output = CreateTerm(BVNEG,a_len,t);
- break;
- }
- // case BVSX:{
-// //(BVSX(t,n)[i:j] <==> BVSX(t,i+1), if n >= i+1 and j=0
-// ASTNode t = a0[0];
-// unsigned int bvsx_len = a0.GetValueWidth();
-// if(bvsx_len < a_len) {
-// FatalError("SimplifyTerm: BVEXTRACT over BVSX:"
-// "the length of BVSX term must be greater than extract-len",inputterm);
-// }
-// if(j != zero) {
-// output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
-// }
-// else {
-// output = CreateTerm(BVSX,a_len,t,CreateBVConst(32,a_len));
-// }
-// break;
-// }
- case ITE: {
- ASTNode t0 = a0[0];
- ASTNode t1 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[1],i,j));
- ASTNode t2 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[2],i,j));
- output = CreateSimplifiedTermITE(t0,t1,t2);
- break;
- }
- default: {
- output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
- break;
- }
- }
- break;
- }
- case BVNEG: {
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- unsigned len = inputValueWidth;
- switch(a0.GetKind()) {
- case BVCONST:
- output = BVConstEvaluator(CreateTerm(BVNEG,len,a0));
- break;
- case BVNEG:
- output = a0[0];
- break;
- // case ITE: {
-// ASTNode cond = a0[0];
-// ASTNode thenpart = SimplifyTerm(CreateTerm(BVNEG,len,a0[1]));
-// ASTNode elsepart = SimplifyTerm(CreateTerm(BVNEG,len,a0[2]));
-// output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
-// break;
-// }
- default:
- output = CreateTerm(BVNEG,len,a0);
- break;
- }
- break;
- }
- case BVZX:
- {
- //a0 is the expr which is being zero extended
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- //a1 represents the length of the term BVZX(a0)
- ASTNode a1 = inputterm[1];
- //output length of the BVSX term
- unsigned len = inputValueWidth;
-
- output = CreateTerm(BVZX,len,a0,a1);
- break;
- }
- break;
-
- case BVSX:{
- //a0 is the expr which is being sign extended
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- //a1 represents the length of the term BVSX(a0)
- ASTNode a1 = inputterm[1];
- //output length of the BVSX term
- unsigned len = inputValueWidth;
-
- if(a0.GetValueWidth() == len) {
- //nothing to signextend
- return a0;
- }
-
- switch(a0.GetKind()) {
- case BVCONST:
- output = BVConstEvaluator(CreateTerm(BVSX,len,a0,a1));
- break;
- case BVNEG:
- output = CreateTerm(a0.GetKind(),len,CreateTerm(BVSX,len,a0[0],a1));
- break;
- case BVAND:
- case BVOR:
- //assuming BVAND and BVOR are binary
- output = CreateTerm(a0.GetKind(),len,
- CreateTerm(BVSX,len,a0[0],a1),
- CreateTerm(BVSX,len,a0[1],a1));
- break;
- case BVPLUS: {
- //BVSX(m,BVPLUS(n,BVSX(t1),BVSX(t2))) <==> BVPLUS(m,BVSX(m,t1),BVSX(m,t2))
- ASTVec c = a0.GetChildren();
- bool returnflag = false;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- if(BVSX != it->GetKind()) {
- returnflag = true;
- break;
- }
- }
- if(returnflag) {
- output = CreateTerm(BVSX,len,a0,a1);
- }
- else {
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(CreateTerm(BVSX,len,*it,a1));
- o.push_back(aaa);
- }
- output = CreateTerm(a0.GetKind(),len,o);
- }
- break;
- }
- case BVSX: {
- //if you have BVSX(m,BVSX(n,a)) then you can drop the inner
- //BVSX provided m is greater than n.
- a0 = SimplifyTerm(a0[0]);
- output = CreateTerm(BVSX,len,a0,a1);
- break;
- }
- case ITE: {
- ASTNode cond = a0[0];
- ASTNode thenpart = SimplifyTerm(CreateTerm(BVSX,len,a0[1],a1));
- ASTNode elsepart = SimplifyTerm(CreateTerm(BVSX,len,a0[2],a1));
- output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
- break;
- }
- default:
- output = CreateTerm(BVSX,len,a0,a1);
- break;
- }
- break;
- }
- case BVAND:
- case BVOR:{
- ASTNode max = CreateMaxConst(inputValueWidth);
- ASTNode zero = CreateZeroConst(inputValueWidth);
-
- ASTNode identity = (BVAND == k) ? max : zero;
- ASTNode annihilator = (BVAND == k) ? zero : max;
- ASTVec c = FlattenOneLevel(inputterm).GetChildren();
- SortByArith(c);
- ASTVec o;
- bool constant = true;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST != aaa.GetKind()) {
- constant = false;
- }
-
- if(aaa == annihilator) {
- output = annihilator;
- return output;
- }
-
- if(aaa != identity) {
- o.push_back(aaa);
- }
- }
-
- switch(o.size()) {
- case 0:
- output = identity;
- break;
- case 1:
- output = o[0];
- break;
- default:
- SortByArith(o);
- output = CreateTerm(k,inputValueWidth,o);
- if(constant) {
- output = BVConstEvaluator(output);
- }
- break;
- }
- break;
- }
- case BVCONCAT:{
- ASTNode t = SimplifyTerm(inputterm[0]);
- ASTNode u = SimplifyTerm(inputterm[1]);
- Kind tkind = t.GetKind();
- Kind ukind = u.GetKind();
-
-
- if(BVCONST == tkind && BVCONST == ukind) {
- output = BVConstEvaluator(CreateTerm(BVCONCAT,inputValueWidth,t,u));
- }
- else if(BVEXTRACT == tkind &&
- BVEXTRACT == ukind &&
- t[0] == u[0]) {
- //to handle the case x[m:n]@x[n-1:k] <==> x[m:k]
- ASTNode t_hi = t[1];
- ASTNode t_low = t[2];
- ASTNode u_hi = u[1];
- ASTNode u_low = u[2];
- ASTNode c = BVConstEvaluator(CreateTerm(BVPLUS,32,u_hi,CreateOneConst(32)));
- if(t_low == c) {
- output = CreateTerm(BVEXTRACT,inputValueWidth,t[0],t_hi,u_low);
- }
- else {
- output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
- }
- }
- else {
- output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
- }
- break;
- }
- case BVXOR:
- case BVXNOR:
- case BVNAND:
- case BVNOR:
- case BVLEFTSHIFT:
- case BVRIGHTSHIFT:
- case BVVARSHIFT:
- case BVSRSHIFT:
- case BVDIV:
- case BVMOD: {
- ASTVec c = inputterm.GetChildren();
- ASTVec o;
- bool constant = true;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST != aaa.GetKind()) {
- constant = false;
- }
- o.push_back(aaa);
- }
- output = CreateTerm(k,inputValueWidth,o);
- if(constant)
- output = BVConstEvaluator(output);
- break;
- }
- case READ: {
- ASTNode out1;
- //process only if not in the substitution map. simplifymap
- //has been checked already
- if(!CheckSubstitutionMap(inputterm,out1)) {
- if(WRITE == inputterm[0].GetKind()) {
- //get rid of all writes
- ASTNode nowrites = RemoveWrites_TopLevel(inputterm);
- out1 = nowrites;
- }
- else if (ITE == inputterm[0].GetKind()){
- ASTNode cond = SimplifyFormula(inputterm[0][0],false);
- ASTNode index = SimplifyTerm(inputterm[1]);
-
- ASTNode read1 = CreateTerm(READ,inputValueWidth,inputterm[0][1],index);
- ASTNode read2 = CreateTerm(READ,inputValueWidth,inputterm[0][2],index);
-
- read1 = SimplifyTerm(read1);
- read2 = SimplifyTerm(read2);
- out1 = CreateSimplifiedTermITE(cond,read1,read2);
- }
- else {
- //arr is a SYMBOL for sure
- ASTNode arr = inputterm[0];
- ASTNode index = SimplifyTerm(inputterm[1]);
- out1 = CreateTerm(READ,inputValueWidth,arr,index);
- }
- }
- //it is possible that after all the procesing the READ term
- //reduces to READ(Symbol,const) and hence we should check the
- //substitutionmap once again.
- if(!CheckSubstitutionMap(out1,output))
- output = out1;
- break;
- }
- case ITE: {
- ASTNode t0 = SimplifyFormula(inputterm[0],false);
- ASTNode t1 = SimplifyTerm(inputterm[1]);
- ASTNode t2 = SimplifyTerm(inputterm[2]);
- output = CreateSimplifiedTermITE(t0,t1,t2);
- break;
- }
- case SBVREM:
- case SBVMOD:
- case SBVDIV: {
- ASTVec c = inputterm.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- o.push_back(aaa);
- }
- output = CreateTerm(k,inputValueWidth,o);
- break;
- }
- case WRITE:
- default:
- FatalError("SimplifyTermAux: Control should never reach here:", inputterm, k);
- return inputterm;
- break;
- }
-
- return output;
- }
-
- //At the end of each simplification call, we want the output to be
- //always smaller or equal to the input in size.
- void BeevMgr::CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output) {
-
- if(NodeSize(a,true) + 1 < NodeSize(output,true)) {
- cerr << "lhs := " << a << endl;
- cerr << "NodeSize of lhs is: " << NodeSize(a, true) << endl;
- cerr << endl;
- cerr << "rhs := " << output << endl;
- cerr << "NodeSize of rhs is: " << NodeSize(output, true) << endl;
- // FatalError("SimplifyFormula: The nodesize shoudl decrease from lhs to rhs: ",ASTUndefined);
- }
- }
-
- //this function assumes that the input is a vector of childnodes of
- //a BVPLUS term. it combines like terms and returns a bvplus
- //term. e.g. 1.x + 2.x is converted to 3.x
- ASTNode BeevMgr::CombineLikeTerms(const ASTNode& a) {
- if(BVPLUS != a.GetKind())
- return a;
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,false)) {
- //check memo table
- //cerr << "output of SimplifyTerm Cache: " << output << endl;
- return output;
- }
-
- const ASTVec& c = a.GetChildren();
- //map from variables to vector of constants
- ASTNodeToVecMap vars_to_consts;
- //vector to hold constants
- ASTVec constkids;
- ASTVec outputvec;
-
- //useful constants
- unsigned int len = c[0].GetValueWidth();
- ASTNode one = CreateOneConst(len);
- ASTNode zero = CreateZeroConst(len);
- ASTNode max = CreateMaxConst(len);
-
- //go over the childnodes of the input bvplus, and collect like
- //terms in a map. the key of the map are the variables, and the
- //values are stored in a ASTVec
- for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++){
- ASTNode aaa = *it;
- if(SYMBOL == aaa.GetKind()) {
- vars_to_consts[aaa].push_back(one);
- }
- else if(BVMULT == aaa.GetKind() &&
- BVUMINUS == aaa[0].GetKind() &&
- BVCONST == aaa[0][0].GetKind()) {
- //(BVUMINUS(c))*(y) <==> compute(BVUMINUS(c))*y
- ASTNode compute_const = BVConstEvaluator(aaa[0]);
- vars_to_consts[aaa[1]].push_back(compute_const);
- }
- else if(BVMULT == aaa.GetKind() &&
- BVUMINUS == aaa[1].GetKind() &&
- BVCONST == aaa[0].GetKind()) {
- //c*(BVUMINUS(y)) <==> compute(BVUMINUS(c))*y
- ASTNode cccc = BVConstEvaluator(CreateTerm(BVUMINUS,len,aaa[0]));
- vars_to_consts[aaa[1][0]].push_back(cccc);
- }
- else if(BVMULT == aaa.GetKind() && BVCONST == aaa[0].GetKind()) {
- //assumes that BVMULT is binary
- vars_to_consts[aaa[1]].push_back(aaa[0]);
- }
- else if(BVMULT == aaa.GetKind() && BVUMINUS == aaa[0].GetKind()) {
- //(-1*x)*(y) <==> -1*(xy)
- ASTNode cccc = CreateTerm(BVMULT,len,aaa[0][0],aaa[1]);
- ASTVec cNodes = cccc.GetChildren();
- SortByArith(cNodes);
- vars_to_consts[cccc].push_back(max);
- }
- else if(BVMULT == aaa.GetKind() && BVUMINUS == aaa[1].GetKind()) {
- //x*(-1*y) <==> -1*(xy)
- ASTNode cccc = CreateTerm(BVMULT,len,aaa[0],aaa[1][0]);
- ASTVec cNodes = cccc.GetChildren();
- SortByArith(cNodes);
- vars_to_consts[cccc].push_back(max);
- }
- else if(BVCONST == aaa.GetKind()) {
- constkids.push_back(aaa);
- }
- else if(BVUMINUS == aaa.GetKind()) {
- //helps to convert BVUMINUS into a BVMULT. here the max
- //constant represents -1. this transformation allows us to
- //conclude that x + BVUMINUS(x) is 0.
- vars_to_consts[aaa[0]].push_back(max);
- }
- else
- vars_to_consts[aaa].push_back(one);
- } //end of for loop
-
- //go over the map from variables to vector of values. combine the
- //vector of values, multiply to the variable, and put the
- //resultant monomial in the output BVPLUS.
- for(ASTNodeToVecMap::iterator it=vars_to_consts.begin(),itend=vars_to_consts.end();
- it!=itend;it++){
- ASTVec ccc = it->second;
-
- ASTNode constant;
- if(1 < ccc.size()) {
- constant = CreateTerm(BVPLUS,ccc[0].GetValueWidth(),ccc);
- constant = BVConstEvaluator(constant);
- }
- else
- constant = ccc[0];
-
- //constant * var
- ASTNode monom;
- if(zero == constant)
- monom = zero;
- else if (one == constant)
- monom = it->first;
- else{
- monom =
- SimplifyTerm(CreateTerm(BVMULT,constant.GetValueWidth(),constant,it->first));
- }
- if(zero != monom) {
- outputvec.push_back(monom);
- }
- } //end of for loop
-
- if(constkids.size() > 1) {
- ASTNode output = CreateTerm(BVPLUS,constkids[0].GetValueWidth(),constkids);
- output = BVConstEvaluator(output);
- if(output != zero)
- outputvec.push_back(output);
- }
- else if (constkids.size() == 1) {
- if(constkids[0] != zero)
- outputvec.push_back(constkids[0]);
- }
-
- if (outputvec.size() > 1) {
- output = CreateTerm(BVPLUS,len,outputvec);
- }
- else if(outputvec.size() == 1) {
- output = outputvec[0];
- }
- else {
- output = zero;
- }
-
- //memoize
- //UpdateSimplifyMap(a,output,false);
- return output;
- } //end of CombineLikeTerms()
-
- //accepts lhs and rhs, and returns lhs - rhs = 0. The function
- //assumes that lhs and rhs have already been simplified. although
- //this assumption is not needed for correctness, it is essential for
- //performance. The function also assumes that lhs is a BVPLUS
- ASTNode BeevMgr::LhsMinusRhs(const ASTNode& eq) {
- //if input is not an equality, simply return it
- if(EQ != eq.GetKind())
- return eq;
-
- ASTNode lhs = eq[0];
- ASTNode rhs = eq[1];
- Kind k_lhs = lhs.GetKind();
- Kind k_rhs = rhs.GetKind();
- //either the lhs has to be a BVPLUS or the rhs has to be a
- //BVPLUS
- if(!(BVPLUS == k_lhs ||
- BVPLUS == k_rhs ||
- (BVMULT == k_lhs &&
- BVMULT == k_rhs)
- )) {
- return eq;
- }
-
- ASTNode output;
- if(CheckSimplifyMap(eq,output,false)) {
- //check memo table
- //cerr << "output of SimplifyTerm Cache: " << output << endl;
- return output;
- }
-
- //if the lhs is not a BVPLUS, but the rhs is a BVPLUS, then swap
- //the lhs and rhs
- bool swap_flag = false;
- if(BVPLUS != k_lhs && BVPLUS == k_rhs) {
- ASTNode swap = lhs;
- lhs = rhs;
- rhs = swap;
- swap_flag = true;
- }
-
- unsigned int len = lhs.GetValueWidth();
- ASTNode zero = CreateZeroConst(len);
- //right is -1*(rhs): Simplify(-1*rhs)
- rhs = SimplifyTerm(CreateTerm(BVUMINUS,len,rhs));
-
- ASTVec lvec = lhs.GetChildren();
- ASTVec rvec = rhs.GetChildren();
- ASTNode lhsplusrhs;
- if(BVPLUS != lhs.GetKind() && BVPLUS != rhs.GetKind()) {
- lhsplusrhs = CreateTerm(BVPLUS,len,lhs,rhs);
- }
- else if(BVPLUS == lhs.GetKind() && BVPLUS == rhs.GetKind()) {
- //combine the childnodes of the left and the right
- lvec.insert(lvec.end(),rvec.begin(),rvec.end());
- lhsplusrhs = CreateTerm(BVPLUS,len,lvec);
- }
- else if(BVPLUS == lhs.GetKind() && BVPLUS != rhs.GetKind()){
- lvec.push_back(rhs);
- lhsplusrhs = CreateTerm(BVPLUS,len,lvec);
- }
- else {
- //Control should never reach here
- FatalError("LhsMinusRhs: Control should never reach here\n");
- }
-
- //combine like terms
- output = CombineLikeTerms(lhsplusrhs);
- output = SimplifyTerm(output);
- //
- //Now make output into: lhs-rhs = 0
- output = CreateSimplifiedEQ(output,zero);
- //sort if BVPLUS
- if(BVPLUS == output.GetKind()) {
- ASTVec outv = output.GetChildren();
- SortByArith(outv);
- output = CreateTerm(BVPLUS,len,outv);
- }
-
- //memoize
- //UpdateSimplifyMap(eq,output,false);
- return output;
- } //end of LhsMinusRHS()
-
- //THis function accepts a BVMULT(t1,t2) and distributes the mult
- //over plus if either or both t1 and t2 are BVPLUSes.
- //
- // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
- //
- // (y1 + y2 + ...+ yn)*x <==> x*y1 + x*y2 + ... + x*yn
- //
- // The function assumes that the BVPLUSes have been flattened
- ASTNode BeevMgr::DistributeMultOverPlus(const ASTNode& a, bool startdistribution) {
- if(!startdistribution)
- return a;
- Kind k = a.GetKind();
- if(BVMULT != k)
- return a;
-
- ASTNode left = a[0];
- ASTNode right = a[1];
- Kind left_kind = left.GetKind();
- Kind right_kind = right.GetKind();
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,false)) {
- //check memo table
- //cerr << "output of SimplifyTerm Cache: " << output << endl;
- return output;
- }
-
- //special case optimization: c1*(c2*t1) <==> (c1*c2)*t1
- if(BVCONST == left_kind &&
- BVMULT == right_kind &&
- BVCONST == right[0].GetKind()) {
- ASTNode c = BVConstEvaluator(CreateTerm(BVMULT,a.GetValueWidth(),left,right[0]));
- c = CreateTerm(BVMULT,a.GetValueWidth(),c,right[1]);
- return c;
- left = c[0];
- right = c[1];
- left_kind = left.GetKind();
- right_kind = right.GetKind();
- }
-
- //special case optimization: c1*(t1*c2) <==> (c1*c2)*t1
- if(BVCONST == left_kind &&
- BVMULT == right_kind &&
- BVCONST == right[1].GetKind()) {
- ASTNode c = BVConstEvaluator(CreateTerm(BVMULT,a.GetValueWidth(),left,right[1]));
- c = CreateTerm(BVMULT,a.GetValueWidth(),c,right[0]);
- return c;
- left = c[0];
- right = c[1];
- left_kind = left.GetKind();
- right_kind = right.GetKind();
- }
-
- //atleast one of left or right have to be BVPLUS
- if(!(BVPLUS == left_kind || BVPLUS == right_kind)) {
- return a;
- }
-
- //if left is BVPLUS and right is not, then swap left and right. we
- //can do this since BVMULT is communtative
- ASTNode swap;
- if(BVPLUS == left_kind && BVPLUS != right_kind) {
- swap = left;
- left = right;
- right = swap;
- }
- left_kind = left.GetKind();
- right_kind = right.GetKind();
-
- //by this point we are gauranteed that right is a BVPLUS, but left
- //may not be
- ASTVec rightnodes = right.GetChildren();
- ASTVec outputvec;
- unsigned len = a.GetValueWidth();
- ASTNode zero = CreateZeroConst(len);
- ASTNode one = CreateOneConst(len);
- if(BVPLUS != left_kind) {
- //if the multiplier is not a BVPLUS then we have a special case
- // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
- if(zero == left) {
- outputvec.push_back(zero);
- }
- else if(one == left) {
- outputvec.push_back(left);
- }
- else {
- for(ASTVec::iterator j=rightnodes.begin(),jend=rightnodes.end();
- j!=jend;j++) {
- ASTNode out = SimplifyTerm(CreateTerm(BVMULT,len,left,*j));
- outputvec.push_back(out);
- }
- }
- }
- else {
- ASTVec leftnodes = left.GetChildren();
- // (x1 + x2 + ... + xm)*(y1 + y2 + ...+ yn) <==> x1*y1 + x1*y2 +
- // ... + x2*y1 + ... + xm*yn
- for(ASTVec::iterator i=leftnodes.begin(),iend=leftnodes.end();
- i!=iend;i++) {
- ASTNode multiplier = *i;
- for(ASTVec::iterator j=rightnodes.begin(),jend=rightnodes.end();
- j!=jend;j++) {
- ASTNode out = SimplifyTerm(CreateTerm(BVMULT,len,multiplier,*j));
- outputvec.push_back(out);
- }
- }
- }
-
- //compute output here
- if(outputvec.size() > 1) {
- output = CombineLikeTerms(CreateTerm(BVPLUS,len,outputvec));
- output = SimplifyTerm(output);
- }
- else
- output = SimplifyTerm(outputvec[0]);
-
- //memoize
- //UpdateSimplifyMap(a,output,false);
- return output;
- } //end of distributemultoverplus()
-
- //converts the BVSX(len, a0) operator into ITE( check top bit,
- //extend a0 by 1, extend a0 by 0)
- ASTNode BeevMgr::ConvertBVSXToITE(const ASTNode& a) {
- if(BVSX != a.GetKind())
- return a;
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,false)) {
- //check memo table
- //cerr << "output of ConvertBVSXToITE Cache: " << output << endl;
- return output;
- }
-
- ASTNode a0 = a[0];
- unsigned a_len = a.GetValueWidth();
- unsigned a0_len = a0.GetValueWidth();
-
- if(a0_len > a_len){
- FatalError("Trying to sign_extend a larger BV into a smaller BV");
- return ASTUndefined; //to stop the compiler from producing bogus warnings
- }
-
- //sign extend
- unsigned extensionlen = a_len-a0_len;
- if(0 == extensionlen) {
- UpdateSimplifyMap(a,output,false);
- return a;
- }
-
- std::string ones;
- for(unsigned c=0; c < extensionlen;c++)
- ones += '1';
- std::string zeros;
- for(unsigned c=0; c < extensionlen;c++)
- zeros += '0';
-
- //string of oness of length extensionlen
- BEEV::ASTNode BVOnes = CreateBVConst(ones.c_str(),2);
- //string of zeros of length extensionlen
- BEEV::ASTNode BVZeros = CreateBVConst(zeros.c_str(),2);
-
- //string of ones BVCONCAT a0
- BEEV::ASTNode concatOnes = CreateTerm(BEEV::BVCONCAT,a_len,BVOnes,a0);
- //string of zeros BVCONCAT a0
- BEEV::ASTNode concatZeros = CreateTerm(BEEV::BVCONCAT,a_len,BVZeros,a0);
-
- //extract top bit of a0
- BEEV::ASTNode hi = CreateBVConst(32,a0_len-1);
- BEEV::ASTNode low = CreateBVConst(32,a0_len-1);
- BEEV::ASTNode topBit = CreateTerm(BEEV::BVEXTRACT,1,a0,hi,low);
-
- //compare topBit of a0 with 0bin1
- BEEV::ASTNode condition = CreateSimplifiedEQ(CreateBVConst(1,1),topBit);
-
- //ITE(topbit = 0bin1, 0bin1111...a0, 0bin000...a0)
- output = CreateSimplifiedTermITE(condition,concatOnes,concatZeros);
- UpdateSimplifyMap(a,output,false);
- return output;
- } //end of ConvertBVSXToITE()
-
-
- ASTNode BeevMgr::RemoveWrites_TopLevel(const ASTNode& term) {
- if(READ != term.GetKind() && WRITE != term[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
- }
-
- if(!Begin_RemoveWrites &&
- !SimplifyWrites_InPlace_Flag &&
- !start_abstracting) {
- return term;
- }
- else if(!Begin_RemoveWrites &&
- SimplifyWrites_InPlace_Flag &&
- !start_abstracting) {
- //return term;
- return SimplifyWrites_InPlace(term);
- }
- else {
- return RemoveWrites(term);
- }
- } //end of RemoveWrites_TopLevel()
-
- ASTNode BeevMgr::SimplifyWrites_InPlace(const ASTNode& term) {
- ASTNodeMultiSet WriteIndicesSeenSoFar;
- bool SeenNonConstWriteIndex = false;
-
- if(READ != term.GetKind() &&
- WRITE != term[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
- }
-
- ASTNode output;
- if(CheckSimplifyMap(term,output,false)) {
- return output;
- }
-
- ASTVec writeIndices, writeValues;
- unsigned int width = term.GetValueWidth();
- ASTNode write = term[0];
- unsigned indexwidth = write.GetIndexWidth();
- ASTNode readIndex = SimplifyTerm(term[1]);
-
- do {
- ASTNode writeIndex = SimplifyTerm(write[1]);
- ASTNode writeVal = SimplifyTerm(write[2]);
-
- //compare the readIndex and the current writeIndex and see if they
- //simplify to TRUE or FALSE or UNDETERMINABLE at this stage
- ASTNode compare_readwrite_indices =
- SimplifyFormula(CreateSimplifiedEQ(writeIndex,readIndex),false);
-
- //if readIndex and writeIndex are equal
- if(ASTTrue == compare_readwrite_indices && !SeenNonConstWriteIndex) {
- UpdateSimplifyMap(term,writeVal,false);
- return writeVal;
- }
-
- if(!(ASTTrue == compare_readwrite_indices ||
- ASTFalse == compare_readwrite_indices)) {
- SeenNonConstWriteIndex = true;
- }
-
- //if (readIndex=writeIndex <=> FALSE)
- if(ASTFalse == compare_readwrite_indices
- ||
- (WriteIndicesSeenSoFar.find(writeIndex) != WriteIndicesSeenSoFar.end())
- ) {
- //drop the current level write
- //do nothing
- }
- else {
- writeIndices.push_back(writeIndex);
- writeValues.push_back(writeVal);
- }
-
- //record the write indices seen so far
- //if(BVCONST == writeIndex.GetKind()) {
- WriteIndicesSeenSoFar.insert(writeIndex);
- //}
-
- //Setup the write for the new iteration, one level inner write
- write = write[0];
- }while (SYMBOL != write.GetKind());
-
- ASTVec::reverse_iterator it_index = writeIndices.rbegin();
- ASTVec::reverse_iterator itend_index = writeIndices.rend();
- ASTVec::reverse_iterator it_values = writeValues.rbegin();
- ASTVec::reverse_iterator itend_values = writeValues.rend();
-
- //"write" must be a symbol at the control point before the
- //begining of the "for loop"
-
- for(;it_index!=itend_index;it_index++,it_values++) {
- write = CreateTerm(WRITE,width,write,*it_index,*it_values);
- write.SetIndexWidth(indexwidth);
- }
-
- output = CreateTerm(READ,width,write,readIndex);
- UpdateSimplifyMap(term,output,false);
- return output;
- } //end of SimplifyWrites_In_Place()
-
- //accepts a read over a write and returns a term without the write
- //READ(WRITE(A i val) j) <==> ITE(i=j,val,READ(A,j)). We use a memo
- //table for this function called RemoveWritesMemoMap
- ASTNode BeevMgr::RemoveWrites(const ASTNode& input) {
- //unsigned int width = input.GetValueWidth();
- if(READ != input.GetKind() || WRITE != input[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",input);
- }
-
- ASTNodeMap::iterator it;
- ASTNode output = input;
- if(CheckSimplifyMap(input,output,false)) {
- return output;
- }
-
- if(!start_abstracting && Begin_RemoveWrites) {
- output= ReadOverWrite_To_ITE(input);
- }
-
- if(start_abstracting) {
- ASTNode newVar;
- if(!CheckSimplifyMap(input,newVar,false)) {
- newVar = NewVar(input.GetValueWidth());
- ReadOverWrite_NewName_Map[input] = newVar;
- NewName_ReadOverWrite_Map[newVar] = input;
-
- UpdateSimplifyMap(input,newVar,false);
- ASTNodeStats("New Var Name which replace Read_Over_Write: ", newVar);
- }
- output = newVar;
- } //end of start_abstracting if condition
-
- //memoize
- UpdateSimplifyMap(input,output,false);
- return output;
- } //end of RemoveWrites()
-
- ASTNode BeevMgr::ReadOverWrite_To_ITE(const ASTNode& term) {
- unsigned int width = term.GetValueWidth();
- ASTNode input = term;
- if(READ != term.GetKind() || WRITE != term[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
- }
-
- ASTNodeMap::iterator it;
- ASTNode output;
- // if(CheckSimplifyMap(term,output,false)) {
- // return output;
- // }
-
- ASTNode partialITE = term;
- ASTNode writeA = ASTTrue;
- ASTNode oldRead = term;
- //iteratively expand read-over-write
- do {
- ASTNode write = input[0];
- ASTNode readIndex = SimplifyTerm(input[1]);
- //DO NOT CALL SimplifyTerm() on write[0]. You will go into an
- //infinite loop
- writeA = write[0];
- ASTNode writeIndex = SimplifyTerm(write[1]);
- ASTNode writeVal = SimplifyTerm(write[2]);
-
- ASTNode cond = SimplifyFormula(CreateSimplifiedEQ(writeIndex,readIndex),false);
- ASTNode newRead = CreateTerm(READ,width,writeA,readIndex);
- ASTNode newRead_memoized = newRead;
- if(CheckSimplifyMap(newRead, newRead_memoized,false)) {
- newRead = newRead_memoized;
- }
-
- if(ASTTrue == cond && (term == partialITE)) {
- //found the write-value in the first iteration itself. return
- //it
- output = writeVal;
- UpdateSimplifyMap(term,output,false);
- return output;
- }
-
- if(READ == partialITE.GetKind() && WRITE == partialITE[0].GetKind()) {
- //first iteration or (previous cond==ASTFALSE and partialITE is a "READ over WRITE")
- partialITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
- }
- else if (ITE == partialITE.GetKind()){
- //ITE(i1 = j, v1, R(A,j))
- ASTNode ElseITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
- //R(W(A,i1,v1),j) <==> ITE(i1 = j, v1, R(A,j))
- UpdateSimplifyMap(oldRead,ElseITE,false);
- //ITE(i2 = j, v2, R(W(A,i1,v1),j)) <==> ITE(i2 = j, v2, ITE(i1 = j, v1, R(A,j)))
- partialITE = SimplifyTerm(partialITE);
- }
- else {
- FatalError("RemoveWrites: Control should not reach here\n");
- }
-
- if(ASTTrue == cond) {
- //no more iterations required
- output = partialITE;
- UpdateSimplifyMap(term,output,false);
+ if (a.GetChildren().size() > 2)
+ {
+ FatalError("Simplify got an XOR with more than two children.");
+ }
+
+ ASTNode a0 = SimplifyFormula(a[0], false);
+ ASTNode a1 = SimplifyFormula(a[1], false);
+ output = pushNeg ? CreateNode(IFF, a0, a1) : CreateNode(XOR, a0, a1);
+
+ if (XOR == output.GetKind())
+ {
+ a0 = output[0];
+ a1 = output[1];
+ if (a0 == a1)
+ output = ASTFalse;
+ else if (a0 == ASTTrue && a1 == ASTFalse || a0 == ASTFalse && a1 == ASTTrue)
+ output = ASTTrue;
+ }
+
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
return output;
- }
+}
+
+ASTNode BeevMgr::SimplifyNandFormula(const ASTNode& a, bool pushNeg)
+{
+ ASTNode output, a0, a1;
+ if (CheckSimplifyMap(a, output, pushNeg))
+ return output;
+
+ //the two NOTs cancel out
+ if (pushNeg)
+ {
+ a0 = SimplifyFormula(a[0], false);
+ a1 = SimplifyFormula(a[1], false);
+ output = CreateNode(AND, a0, a1);
+ }
+ else
+ {
+ //push the NOT implicit in the NAND
+ a0 = SimplifyFormula(a[0], true);
+ a1 = SimplifyFormula(a[1], true);
+ output = CreateNode(OR, a0, a1);
+ }
- input = newRead;
- oldRead = newRead;
- } while(READ == input.GetKind() && WRITE == input[0].GetKind());
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
+ return output;
+}
- output = partialITE;
+ASTNode BeevMgr::SimplifyNorFormula(const ASTNode& a, bool pushNeg)
+{
+ ASTNode output, a0, a1;
+ if (CheckSimplifyMap(a, output, pushNeg))
+ return output;
+
+ //the two NOTs cancel out
+ if (pushNeg)
+ {
+ a0 = SimplifyFormula(a[0], false);
+ a1 = SimplifyFormula(a[1], false);
+ output = CreateNode(OR, a0, a1);
+ }
+ else
+ {
+ //push the NOT implicit in the NAND
+ a0 = SimplifyFormula(a[0], true);
+ a1 = SimplifyFormula(a[1], true);
+ output = CreateNode(AND, a0, a1);
+ }
- //memoize
- //UpdateSimplifyMap(term,output,false);
- return output;
- } //ReadOverWrite_To_ITE()
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
+ return output;
+}
- //compute the multiplicative inverse of the input
- ASTNode BeevMgr::MultiplicativeInverse(const ASTNode& d) {
- ASTNode c = d;
- if(BVCONST != c.GetKind()) {
- FatalError("Input must be a constant", c);
- }
+ASTNode BeevMgr::SimplifyImpliesFormula(const ASTNode& a, bool pushNeg)
+{
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, pushNeg))
+ return output;
+
+ if (!(a.Degree() == 2 && IMPLIES == a.GetKind()))
+ FatalError("SimplifyImpliesFormula: vector with wrong num of nodes", ASTUndefined);
+
+ ASTNode c0, c1;
+ if (pushNeg)
+ {
+ c0 = SimplifyFormula(a[0], false);
+ c1 = SimplifyFormula(a[1], true);
+ output = CreateNode(AND, c0, c1);
+ }
+ else
+ {
+ c0 = SimplifyFormula(a[0], false);
+ c1 = SimplifyFormula(a[1], false);
+ if (ASTFalse == c0)
+ {
+ output = ASTTrue;
+ }
+ else if (ASTTrue == c0)
+ {
+ output = c1;
+ }
+ else if (c0 == c1)
+ {
+ output = ASTTrue;
+ }
+ else if (CheckAlwaysTrueFormMap(c0))
+ {
+ // c0 AND (~c0 OR c1) <==> c1
+ //
+ //applying modus ponens
+ output = c1;
+ }
+ else if (CheckAlwaysTrueFormMap(c1) || CheckAlwaysTrueFormMap(CreateNode(NOT, c0)) || (NOT == c0.GetKind() && CheckAlwaysTrueFormMap(c0[0])))
+ {
+ //(~c0 AND (~c0 OR c1)) <==> TRUE
+ //
+ //(c0 AND ~c0->c1) <==> TRUE
+ output = ASTTrue;
+ }
+ else if (CheckAlwaysTrueFormMap(CreateNode(NOT, c1)) || (NOT == c1.GetKind() && CheckAlwaysTrueFormMap(c1[0])))
+ {
+ //(~c1 AND c0->c1) <==> (~c1 AND ~c1->~c0) <==> ~c0
+ //(c1 AND c0->~c1) <==> (c1 AND c1->~c0) <==> ~c0
+ output = CreateNode(NOT, c0);
+ }
+ else
+ {
+ if (NOT == c0.GetKind())
+ {
+ output = CreateNode(OR, c0[0], c1);
+ }
+ else
+ {
+ output = CreateNode(OR, CreateNode(NOT, c0), c1);
+ }
+ }
+ }
- if(!BVConstIsOdd(c)) {
- FatalError("MultiplicativeInverse: Input must be odd: ",c);
- }
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
+ return output;
+}
- //cerr << "input to multinverse function is: " << d << endl;
- ASTNode inverse;
- if(CheckMultInverseMap(d,inverse)) {
- //cerr << "found the inverse of: " << d << "and it is: " << inverse << endl;
- return inverse;
- }
+ASTNode BeevMgr::SimplifyIffFormula(const ASTNode& a, bool pushNeg)
+{
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, pushNeg))
+ return output;
- inverse = c;
- unsigned inputwidth = c.GetValueWidth();
+ if (!(a.Degree() == 2 && IFF == a.GetKind()))
+ FatalError("SimplifyIffFormula: vector with wrong num of nodes", ASTUndefined);
-#ifdef NATIVE_C_ARITH
- ASTNode one = CreateOneConst(inputwidth);
- while(c != one) {
- //c = c*c
- c = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,c,c));
- //inverse = invsere*c
- inverse = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,inverse,c));
- }
-#else
- //Compute the multiplicative inverse of c using the extended
- //euclidian algorithm
- //
- //create a '0' which is 1 bit long
- ASTNode onebit_zero = CreateZeroConst(1);
- //zero pad t0, i.e. 0 @ t0
- c = BVConstEvaluator(CreateTerm(BVCONCAT,inputwidth+1,onebit_zero,c));
-
- //construct 2^(inputwidth), i.e. a bitvector of length
- //'inputwidth+1', which is max(inputwidth)+1
- //
- //all 1's
- ASTNode max = CreateMaxConst(inputwidth);
- //zero pad max
- max = BVConstEvaluator(CreateTerm(BVCONCAT,inputwidth+1,onebit_zero,max));
- //Create a '1' which has leading zeros of length 'inputwidth'
- ASTNode inputwidthplusone_one = CreateOneConst(inputwidth+1);
- //add 1 to max
- max = CreateTerm(BVPLUS,inputwidth+1,max,inputwidthplusone_one);
- max = BVConstEvaluator(max);
-
- ASTNode zero = CreateZeroConst(inputwidth+1);
- ASTNode max_bvgt_0 = CreateNode(BVGT,max,zero);
- ASTNode quotient, remainder;
- ASTNode x, x1, x2;
-
- //x1 initialized to zero
- x1 = zero;
- //x2 initialized to one
- x2 = CreateOneConst(inputwidth+1);
- while (ASTTrue == BVConstEvaluator(max_bvgt_0)) {
- //quotient = (c divided by max)
- quotient = BVConstEvaluator(CreateTerm(BVDIV,inputwidth+1, c, max));
-
- //remainder of (c divided by max)
- remainder = BVConstEvaluator(CreateTerm(BVMOD,inputwidth+1, c, max));
-
- //x = x2 - q*x1
- x = CreateTerm(BVSUB,inputwidth+1,x2,CreateTerm(BVMULT,inputwidth+1,quotient,x1));
- x = BVConstEvaluator(x);
-
- //fix the inputs to the extended euclidian algo
- c = max;
- max = remainder;
- max_bvgt_0 = CreateNode(BVGT,max,zero);
-
- x2 = x1;
- x1 = x;
- }
-
- ASTNode hi = CreateBVConst(32,inputwidth-1);
- ASTNode low = CreateZeroConst(32);
- inverse = CreateTerm(BVEXTRACT,inputwidth,x2,hi,low);
- inverse = BVConstEvaluator(inverse);
-#endif
+ ASTNode c0 = a[0];
+ ASTNode c1 = SimplifyFormula(a[1], false);
- UpdateMultInverseMap(d,inverse);
- //cerr << "output of multinverse function is: " << inverse << endl;
- return inverse;
- } //end of MultiplicativeInverse()
-
- //returns true if the input is odd
- bool BeevMgr::BVConstIsOdd(const ASTNode& c) {
- if(BVCONST != c.GetKind()) {
- FatalError("Input must be a constant", c);
- }
-
- ASTNode zero = CreateZeroConst(1);
- ASTNode hi = CreateZeroConst(32);
- ASTNode low = hi;
- ASTNode lowestbit = CreateTerm(BVEXTRACT,1,c,hi,low);
- lowestbit = BVConstEvaluator(lowestbit);
-
- if(lowestbit == zero) {
- return false;
- }
- else {
- return true;
- }
- } //end of BVConstIsOdd()
-
- //The big substitution function
- ASTNode BeevMgr::CreateSubstitutionMap(const ASTNode& a){
- if(!optimize)
- return a;
-
- ASTNode output = a;
- //if the variable has been solved for, then simply return it
- if(CheckSolverMap(a,output))
- return output;
-
- //traverse a and populate the SubstitutionMap
- Kind k = a.GetKind();
- if(SYMBOL == k && BOOLEAN_TYPE == a.GetType()) {
- bool updated = UpdateSubstitutionMap(a,ASTTrue);
- output = updated ? ASTTrue : a;
- return output;
- }
- if(NOT == k
- && SYMBOL == a[0].GetKind()) {
- bool updated = UpdateSubstitutionMap(a[0],ASTFalse);
- output = updated ? ASTTrue : a;
- return output;
- }
-
- if(IFF == k) {
- ASTVec c = a.GetChildren();
- SortByArith(c);
- if(SYMBOL != c[0].GetKind() ||
- VarSeenInTerm(c[0],SimplifyFormula_NoRemoveWrites(c[1],false))) {
- return a;
- }
- bool updated = UpdateSubstitutionMap(c[0], SimplifyFormula(c[1],false));
- output = updated ? ASTTrue : a;
- return output;
- }
-
- if(EQ == k) {
- //fill the arrayname readindices vector if e0 is a
- //READ(Arr,index) and index is a BVCONST
- ASTVec c = a.GetChildren();
- SortByArith(c);
- FillUp_ArrReadIndex_Vec(c[0],c[1]);
-
- if(SYMBOL == c[0].GetKind() &&
- VarSeenInTerm(c[0],SimplifyTermAux(c[1]))) {
- return a;
- }
-
- if(1 == TermOrder(c[0],c[1]) &&
- READ == c[0].GetKind() &&
- VarSeenInTerm(c[0][0],SimplifyTermAux(c[1]))) {
- return a;
- }
- bool updated = UpdateSubstitutionMap(c[0], SimplifyTermAux(c[1]));
- output = updated ? ASTTrue : a;
- return output;
- }
-
- if(AND == k){
- ASTVec o;
- ASTVec c = a.GetChildren();
- for(ASTVec::iterator it = c.begin(),itend=c.end();it!=itend;it++) {
- UpdateAlwaysTrueFormMap(*it);
- ASTNode aaa = CreateSubstitutionMap(*it);
-
- if(ASTTrue != aaa) {
- if(ASTFalse == aaa)
- return ASTFalse;
- else
- o.push_back(aaa);
- }
- }
- if(o.size() == 0)
- return ASTTrue;
-
- if(o.size() == 1)
- return o[0];
-
- return CreateNode(AND,o);
- }
-
- //printf("I gave up on kind: %d node: %d\n", k, a.GetNodeNum());
- return output;
- } //end of CreateSubstitutionMap()
-
-
- bool BeevMgr::VarSeenInTerm(const ASTNode& var, const ASTNode& term) {
- if(READ == term.GetKind() &&
- WRITE == term[0].GetKind() && !Begin_RemoveWrites) {
- return false;
- }
-
- if(READ == term.GetKind() &&
- WRITE == term[0].GetKind() && Begin_RemoveWrites) {
- return true;
- }
-
- ASTNodeMap::iterator it;
- if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
- if(it->second == var) {
- return false;
- }
- }
-
- if(var == term) {
- return true;
- }
-
- for(ASTVec::const_iterator it=term.begin(),itend=term.end();it!=itend;it++){
- if(VarSeenInTerm(var,*it)) {
- return true;
- }
- else {
- TermsAlreadySeenMap[*it] = var;
- }
- }
-
- TermsAlreadySeenMap[term] = var;
- return false;
- }
+ if (pushNeg)
+ c0 = SimplifyFormula(c0, true);
+ else
+ c0 = SimplifyFormula(c0, false);
-// in ext/hash_map, and tr/unordered_map, there is no provision to shrink down
-// the number of buckets in a hash map. If the hash_map has previously held a
-// lot of data, then it will have a lot of buckets. Slowing down iterators and
-// clears() in particular.
-void BeevMgr::ResetSimplifyMaps()
-{
- delete SimplifyMap;
- SimplifyMap = new ASTNodeMap(INITIAL_SIMPLIFY_MAP_SIZE);
+ if (ASTTrue == c0)
+ {
+ output = c1;
+ }
+ else if (ASTFalse == c0)
+ {
+ output = SimplifyFormula(c1, true);
+ }
+ else if (ASTTrue == c1)
+ {
+ output = c0;
+ }
+ else if (ASTFalse == c1)
+ {
+ output = SimplifyFormula(c0, true);
+ }
+ else if (c0 == c1)
+ {
+ output = ASTTrue;
+ }
+ else if ((NOT == c0.GetKind() && c0[0] == c1) || (NOT == c1.GetKind() && c0 == c1[0]))
+ {
+ output = ASTFalse;
+ }
+ else if (CheckAlwaysTrueFormMap(c0))
+ {
+ output = c1;
+ }
+ else if (CheckAlwaysTrueFormMap(c1))
+ {
+ output = c0;
+ }
+ else if (CheckAlwaysTrueFormMap(CreateNode(NOT, c0)))
+ {
+ output = CreateNode(NOT, c1);
+ }
+ else if (CheckAlwaysTrueFormMap(CreateNode(NOT, c1)))
+ {
+ output = CreateNode(NOT, c0);
+ }
+ else
+ {
+ output = CreateNode(IFF, c0, c1);
+ }
- delete SimplifyNegMap;
- SimplifyNegMap = new ASTNodeMap(INITIAL_SIMPLIFY_MAP_SIZE);
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
+ return output;
}
+ASTNode BeevMgr::SimplifyIteFormula(const ASTNode& b, bool pushNeg)
+{
+ if (!optimize)
+ return b;
+
+ ASTNode output;
+ if (CheckSimplifyMap(b, output, pushNeg))
+ return output;
+
+ if (!(b.Degree() == 3 && ITE == b.GetKind()))
+ FatalError("SimplifyIteFormula: vector with wrong num of nodes", ASTUndefined);
+
+ ASTNode a = b;
+ ASTNode t0 = SimplifyFormula(a[0], false);
+ ASTNode t1, t2;
+ if (pushNeg)
+ {
+ t1 = SimplifyFormula(a[1], true);
+ t2 = SimplifyFormula(a[2], true);
+ }
+ else
+ {
+ t1 = SimplifyFormula(a[1], false);
+ t2 = SimplifyFormula(a[2], false);
+ }
+
+ if (ASTTrue == t0)
+ {
+ output = t1;
+ }
+ else if (ASTFalse == t0)
+ {
+ output = t2;
+ }
+ else if (t1 == t2)
+ {
+ output = t1;
+ }
+ else if (ASTTrue == t1 && ASTFalse == t2)
+ {
+ output = t0;
+ }
+ else if (ASTFalse == t1 && ASTTrue == t2)
+ {
+ output = SimplifyFormula(t0, true);
+ }
+ else if (ASTTrue == t1)
+ {
+ output = CreateNode(OR, t0, t2);
+ }
+ else if (ASTFalse == t1)
+ {
+ output = CreateNode(AND, CreateNode(NOT, t0), t2);
+ }
+ else if (ASTTrue == t2)
+ {
+ output = CreateNode(OR, CreateNode(NOT, t0), t1);
+ }
+ else if (ASTFalse == t2)
+ {
+ output = CreateNode(AND, t0, t1);
+ }
+ else if (CheckAlwaysTrueFormMap(t0))
+ {
+ output = t1;
+ }
+ else if (CheckAlwaysTrueFormMap(CreateNode(NOT, t0)) || (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0])))
+ {
+ output = t2;
+ }
+ else
+ {
+ output = CreateNode(ITE, t0, t1, t2);
+ }
+
+ //memoize
+ UpdateSimplifyMap(a, output, pushNeg);
+ return output;
+}
+
+//one level deep flattening
+ASTNode BeevMgr::FlattenOneLevel(const ASTNode& a)
+{
+ Kind k = a.GetKind();
+ if (!(BVPLUS == k || AND == k || OR == k
+ //|| BVAND == k
+ //|| BVOR == k
+ ))
+ {
+ return a;
+ }
+
+ ASTNode output;
+ // if(CheckSimplifyMap(a,output,false)) {
+ // //check memo table
+ // //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ // return output;
+ // }
+
+ ASTVec c = a.GetChildren();
+ ASTVec o;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = *it;
+ if (k == aaa.GetKind())
+ {
+ ASTVec ac = aaa.GetChildren();
+ o.insert(o.end(), ac.begin(), ac.end());
+ }
+ else
+ o.push_back(aaa);
+ }
+
+ if (is_Form_kind(k))
+ output = CreateNode(k, o);
+ else
+ output = CreateTerm(k, a.GetValueWidth(), o);
+
+ //UpdateSimplifyMap(a,output,false);
+ return output;
+ //memoize
+} //end of flattenonelevel()
+
+ASTNode BeevMgr::SimplifyTerm_TopLevel(const ASTNode& b)
+{
+ ResetSimplifyMaps();
+ ASTNode out = SimplifyTerm(b);
+ ResetSimplifyMaps();
+ return out;
+}
+
+//This function simplifies terms based on their kind
+ASTNode BeevMgr::SimplifyTerm(const ASTNode& inputterm)
+{
+ //cout << "SimplifyTerm: input: " << a << endl;
+ if (!optimize)
+ {
+ return inputterm;
+ }
+
+ ASTNode output;
+ BVTypeCheck(inputterm);
+
+ //########################################
+ //########################################
+
+ if (wordlevel_solve && CheckSolverMap(inputterm, output))
+ {
+ //cout << "SimplifyTerm: output: " << output << endl;
+ return SimplifyTerm(output);
+ }
+
+ if (CheckSimplifyMap(inputterm, output, false))
+ {
+ //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ return output;
+ }
+ //########################################
+ //########################################
+
+ Kind k = inputterm.GetKind();
+ if (!is_Term_kind(k))
+ {
+ FatalError("SimplifyTerm: You have input a Non-term", ASTUndefined);
+ }
+
+ unsigned int inputValueWidth = inputterm.GetValueWidth();
+ switch (k)
+ {
+ case BVCONST:
+ output = inputterm;
+ break;
+ case SYMBOL:
+ if (CheckSolverMap(inputterm, output))
+ {
+ return SimplifyTerm(output);
+ }
+ output = inputterm;
+ break;
+ case BVMULT:
+ {
+ if (2 != inputterm.Degree())
+ {
+ FatalError("SimplifyTerm: We assume that BVMULT is binary", inputterm);
+ }
+
+ // Described nicely by Warren, Hacker's Delight pg 135.
+ // Turn sequences of one bits into subtractions.
+ // 28*x == 32x - 4x (two instructions), rather than 16x+ 8x+ 4x.
+ // When fully implemented. I.e. supporting sequences of 1 anywhere.
+ // Other simplifications will try to fold these back in. So need to be careful
+ // about when the simplifications are applied. But in this version it won't
+ // be simplified down by anything else.
+
+
+ // This (temporary) version only simplifies if all the left most bits are set.
+ // All the leftmost bits being set simplifies very nicely down.
+ const ASTNode& n0 = inputterm.GetChildren()[0];
+ const ASTNode& n1 = inputterm.GetChildren()[1];
+
+ // This implementation has two problems.
+ // 1) It causes a segfault for cmu-model15,16,17
+ // 2) It doesn't count the number of bits saved, so if there is a single
+ // leading bit it will invert it. Even though that will take more shifts
+ // and adds when it's finally done.
+
+ // disabled.
+ if (false && (BVCONST == n0.GetKind()) ^ (BVCONST == n1.GetKind()))
+ {
+ CBV constant = (BVCONST == n0.GetKind()) ? n0.GetBVConst() : n1.GetBVConst();
+ ASTNode other = (BVCONST == n0.GetKind()) ? n1 : n0;
+
+ int startSequence = 0;
+ for (unsigned int i = 0; i < inputValueWidth; i++)
+ {
+ if (!CONSTANTBV::BitVector_bit_test(constant, i))
+ startSequence = i;
+ }
+
+ if ((inputValueWidth - startSequence) > 3)
+ {
+ // turn off all bits from "startSequence to the end", then add one.
+ CBV maskedPlusOne = CONSTANTBV::BitVector_Create(inputValueWidth, true);
+ for (int i = 0; i < startSequence; i++)
+ {
+ if (!CONSTANTBV::BitVector_bit_test(constant, i)) // swap
+ CONSTANTBV::BitVector_Bit_On(maskedPlusOne, i);
+ }
+ CONSTANTBV::BitVector_increment(maskedPlusOne);
+ ASTNode temp = CreateTerm(BVMULT, inputValueWidth, CreateBVConst(maskedPlusOne, inputValueWidth), other);
+ output = CreateTerm(BVNEG, inputValueWidth, temp);
+ }
+ }
+
+ }
+ if (NULL != output)
+ break;
+
+ case BVPLUS:
+ {
+
+ ASTVec c = FlattenOneLevel(inputterm).GetChildren();
+ SortByArith(c);
+ ASTVec constkids, nonconstkids;
+
+ //go through the childnodes, and separate constant and
+ //nonconstant nodes. combine the constant nodes using the
+ //constevaluator. if the resultant constant is zero and k ==
+ //BVPLUS, then ignore it (similarily for 1 and BVMULT). else,
+ //add the computed constant to the nonconst vector, flatten,
+ //sort, and create BVPLUS/BVMULT and return
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(*it);
+ if (BVCONST == aaa.GetKind())
+ {
+ constkids.push_back(aaa);
+ }
+ else
+ {
+ nonconstkids.push_back(aaa);
+ }
+ }
+
+ ASTNode one = CreateOneConst(inputValueWidth);
+ ASTNode max = CreateMaxConst(inputValueWidth);
+ ASTNode zero = CreateZeroConst(inputValueWidth);
+
+ //initialize constoutput to zero, in case there are no elements
+ //in constkids
+ ASTNode constoutput = (k == BVPLUS) ? zero : one;
+
+ if (1 == constkids.size())
+ {
+ //only one element in constkids
+ constoutput = constkids[0];
+ }
+ else if (1 < constkids.size())
+ {
+ //many elements in constkids. simplify it
+ constoutput = CreateTerm(k, inputterm.GetValueWidth(), constkids);
+ constoutput = BVConstEvaluator(constoutput);
+ }
+
+ if (BVMULT == k && zero == constoutput)
+ {
+ output = zero;
+ }
+ else if (BVMULT == k && 1 == nonconstkids.size() && constoutput == max)
+ {
+ //useful special case opt: when input is BVMULT(max_const,t),
+ //then output = BVUMINUS(t). this is easier on the bitblaster
+ output = CreateTerm(BVUMINUS, inputValueWidth, nonconstkids);
+ }
+ else
+ {
+ if (0 < nonconstkids.size())
+ {
+ //nonconstkids is not empty. First, combine const and
+ //nonconstkids
+ if (BVPLUS == k && constoutput != zero)
+ {
+ nonconstkids.push_back(constoutput);
+ }
+ else if (BVMULT == k && constoutput != one)
+ {
+ nonconstkids.push_back(constoutput);
+ }
+
+ if (1 == nonconstkids.size())
+ {
+ //exactly one element in nonconstkids. output is exactly
+ //nonconstkids[0]
+ output = nonconstkids[0];
+ }
+ else
+ {
+ //more than 1 element in nonconstkids. create BVPLUS term
+ SortByArith(nonconstkids);
+ output = CreateTerm(k, inputValueWidth, nonconstkids);
+ output = FlattenOneLevel(output);
+ output = DistributeMultOverPlus(output, true);
+ output = CombineLikeTerms(output);
+ }
+ }
+ else
+ {
+ //nonconstkids was empty, all childnodes were constant, hence
+ //constoutput is the output.
+ output = constoutput;
+ }
+ }
+ if (BVMULT == output.GetKind() || BVPLUS == output.GetKind())
+ {
+ ASTVec d = output.GetChildren();
+ SortByArith(d);
+ output = CreateTerm(output.GetKind(), output.GetValueWidth(), d);
+ }
+ break;
+ }
+ case BVSUB:
+ {
+ ASTVec c = inputterm.GetChildren();
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ ASTNode a1 = SimplifyTerm(inputterm[1]);
+ unsigned int l = inputValueWidth;
+ if (a0 == a1)
+ output = CreateZeroConst(l);
+ else
+ {
+ //covert x-y into x+(-y) and simplify. this transformation
+ //triggers more simplifications
+ //
+ a1 = SimplifyTerm(CreateTerm(BVUMINUS, l, a1));
+ output = SimplifyTerm(CreateTerm(BVPLUS, l, a0, a1));
+ }
+ break;
+ }
+ case BVUMINUS:
+ {
+ //important to treat BVUMINUS as a special case, because it
+ //helps in arithmetic transformations. e.g. x + BVUMINUS(x) is
+ //actually 0. One way to reveal this fact is to strip bvuminus
+ //out, and replace with something else so that combineliketerms
+ //can catch this fact.
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ Kind k1 = a0.GetKind();
+ unsigned int l = a0.GetValueWidth();
+ ASTNode one = CreateOneConst(l);
+ switch (k1)
+ {
+ case BVUMINUS:
+ output = a0[0];
+ break;
+ case BVCONST:
+ {
+ output = BVConstEvaluator(CreateTerm(BVUMINUS, l, a0));
+ break;
+ }
+ case BVNEG:
+ {
+ output = SimplifyTerm(CreateTerm(BVPLUS, l, a0[0], one));
+ break;
+ }
+ case BVMULT:
+ {
+ if (BVUMINUS == a0[0].GetKind())
+ {
+ output = CreateTerm(BVMULT, l, a0[0][0], a0[1]);
+ }
+ else if (BVUMINUS == a0[1].GetKind())
+ {
+ output = CreateTerm(BVMULT, l, a0[0], a0[1][0]);
+ }
+ else
+ {
+ ASTNode a00 = SimplifyTerm(CreateTerm(BVUMINUS, l, a0[0]));
+ output = CreateTerm(BVMULT, l, a00, a0[1]);
+ }
+ break;
+ }
+ case BVPLUS:
+ {
+ //push BVUMINUS over all the monomials of BVPLUS. Simplify
+ //along the way
+ //
+ //BVUMINUS(a1x1 + a2x2 + ...) <=> BVPLUS(BVUMINUS(a1x1) +
+ //BVUMINUS(a2x2) + ...
+ ASTVec c = a0.GetChildren();
+ ASTVec o;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ //Simplify(BVUMINUS(a1x1))
+ ASTNode aaa = SimplifyTerm(CreateTerm(BVUMINUS, l, *it));
+ o.push_back(aaa);
+ }
+ //simplify the bvplus
+ output = SimplifyTerm(CreateTerm(BVPLUS, l, o));
+ break;
+ }
+ case BVSUB:
+ {
+ //BVUMINUS(BVSUB(x,y)) <=> BVSUB(y,x)
+ output = SimplifyTerm(CreateTerm(BVSUB, l, a0[1], a0[0]));
+ break;
+ }
+ case ITE:
+ {
+ //BVUMINUS(ITE(c,t1,t2)) <==> ITE(c,BVUMINUS(t1),BVUMINUS(t2))
+ ASTNode c = a0[0];
+ ASTNode t1 = SimplifyTerm(CreateTerm(BVUMINUS, l, a0[1]));
+ ASTNode t2 = SimplifyTerm(CreateTerm(BVUMINUS, l, a0[2]));
+ output = CreateSimplifiedTermITE(c, t1, t2);
+ break;
+ }
+ default:
+ {
+ output = CreateTerm(BVUMINUS, l, a0);
+ break;
+ }
+ }
+ break;
+ }
+ case BVEXTRACT:
+ {
+ //it is important to take care of wordlevel transformation in
+ //BVEXTRACT. it exposes oppurtunities for later simplification
+ //and solving (variable elimination)
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ Kind k1 = a0.GetKind();
+ unsigned int a_len = inputValueWidth;
+
+ //indices for BVEXTRACT
+ ASTNode i = inputterm[1];
+ ASTNode j = inputterm[2];
+ ASTNode zero = CreateBVConst(32, 0);
+ //recall that the indices of BVEXTRACT are always 32 bits
+ //long. therefore doing a GetBVUnsigned is ok.
+ unsigned int i_val = GetUnsignedConst(i);
+ unsigned int j_val = GetUnsignedConst(j);
+
+ // a0[i:0] and len(a0)=i+1, then return a0
+ if (0 == j_val && a_len == a0.GetValueWidth())
+ return a0;
+
+ switch (k1)
+ {
+ case BVCONST:
+ {
+ //extract the constant
+ output = BVConstEvaluator(CreateTerm(BVEXTRACT, a_len, a0, i, j));
+ break;
+ }
+ case BVCONCAT:
+ {
+ //assumes concatenation is binary
+ //
+ //input is of the form a0[i:j]
+ //
+ //a0 is the conatentation t@u, and a0[0] is t, and a0[1] is u
+ ASTNode t = a0[0];
+ ASTNode u = a0[1];
+ unsigned int len_a0 = a0.GetValueWidth();
+ unsigned int len_u = u.GetValueWidth();
+
+ if (len_u > i_val)
+ {
+ //Apply the following rule:
+ // (t@u)[i:j] <==> u[i:j], if len(u) > i
+ //
+ output = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, u, i, j));
+ }
+ else if (len_a0 > i_val && j_val >= len_u)
+ {
+ //Apply the rule:
+ // (t@u)[i:j] <==> t[i-len_u:j-len_u], if len(t@u) > i >= j >= len(u)
+ i = CreateBVConst(32, i_val - len_u);
+ j = CreateBVConst(32, j_val - len_u);
+ output = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, t, i, j));
+ }
+ else
+ {
+ //Apply the rule:
+ // (t@u)[i:j] <==> t[i-len_u:0] @ u[len_u-1:j]
+ i = CreateBVConst(32, i_val - len_u);
+ ASTNode m = CreateBVConst(32, len_u - 1);
+ t = SimplifyTerm(CreateTerm(BVEXTRACT, i_val - len_u + 1, t, i, zero));
+ u = SimplifyTerm(CreateTerm(BVEXTRACT, len_u - j_val, u, m, j));
+ output = CreateTerm(BVCONCAT, a_len, t, u);
+ }
+ break;
+ }
+ case BVPLUS:
+ case BVMULT:
+ {
+ // (BVMULT(n,t,u))[i:j] <==> BVMULT(i+1,t[i:0],u[i:0])[i:j]
+ //similar rule for BVPLUS
+ ASTVec c = a0.GetChildren();
+ ASTVec o;
+ for (ASTVec::iterator jt = c.begin(), jtend = c.end(); jt != jtend; jt++)
+ {
+ ASTNode aaa = *jt;
+ aaa = SimplifyTerm(CreateTerm(BVEXTRACT, i_val + 1, aaa, i, zero));
+ o.push_back(aaa);
+ }
+ output = CreateTerm(a0.GetKind(), i_val + 1, o);
+ if (j_val != 0)
+ {
+ //add extraction only if j is not zero
+ output = CreateTerm(BVEXTRACT, a_len, output, i, j);
+ }
+ break;
+ }
+ case BVAND:
+ case BVOR:
+ case BVXOR:
+ {
+ //assumes these operators are binary
+ //
+ // (t op u)[i:j] <==> t[i:j] op u[i:j]
+ ASTNode t = a0[0];
+ ASTNode u = a0[1];
+ t = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, t, i, j));
+ u = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, u, i, j));
+ BVTypeCheck(t);
+ BVTypeCheck(u);
+ output = CreateTerm(k1, a_len, t, u);
+ break;
+ }
+ case BVNEG:
+ {
+ // (~t)[i:j] <==> ~(t[i:j])
+ ASTNode t = a0[0];
+ t = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, t, i, j));
+ output = CreateTerm(BVNEG, a_len, t);
+ break;
+ }
+ // case BVSX:{
+ // //(BVSX(t,n)[i:j] <==> BVSX(t,i+1), if n >= i+1 and j=0
+ // ASTNode t = a0[0];
+ // unsigned int bvsx_len = a0.GetValueWidth();
+ // if(bvsx_len < a_len) {
+ // FatalError("SimplifyTerm: BVEXTRACT over BVSX:"
+ // "the length of BVSX term must be greater than extract-len",inputterm);
+ // }
+ // if(j != zero) {
+ // output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
+ // }
+ // else {
+ // output = CreateTerm(BVSX,a_len,t,CreateBVConst(32,a_len));
+ // }
+ // break;
+ // }
+ case ITE:
+ {
+ ASTNode t0 = a0[0];
+ ASTNode t1 = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, a0[1], i, j));
+ ASTNode t2 = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, a0[2], i, j));
+ output = CreateSimplifiedTermITE(t0, t1, t2);
+ break;
+ }
+ default:
+ {
+ output = CreateTerm(BVEXTRACT, a_len, a0, i, j);
+ break;
+ }
+ }
+ break;
+ }
+ case BVNEG:
+ {
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ unsigned len = inputValueWidth;
+ switch (a0.GetKind())
+ {
+ case BVCONST:
+ output = BVConstEvaluator(CreateTerm(BVNEG, len, a0));
+ break;
+ case BVNEG:
+ output = a0[0];
+ break;
+ // case ITE: {
+ // ASTNode cond = a0[0];
+ // ASTNode thenpart = SimplifyTerm(CreateTerm(BVNEG,len,a0[1]));
+ // ASTNode elsepart = SimplifyTerm(CreateTerm(BVNEG,len,a0[2]));
+ // output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
+ // break;
+ // }
+ default:
+ output = CreateTerm(BVNEG, len, a0);
+ break;
+ }
+ break;
+ }
+
+ case BVZX:
+ {
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ if (a0.GetKind() == BVCONST)
+ output = BVConstEvaluator(CreateTerm(BVZX, inputValueWidth, a0, inputterm[1]));
+ else
+ output = CreateTerm(BVZX, inputValueWidth, a0, inputterm[1]);
+ }
+ break;
+
+ case BVSX:
+ {
+ //a0 is the expr which is being sign extended
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ //a1 represents the length of the term BVSX(a0)
+ ASTNode a1 = inputterm[1];
+ //output length of the BVSX term
+ unsigned len = inputValueWidth;
+
+ if (a0.GetValueWidth() == len)
+ {
+ //nothing to signextend
+ return a0;
+ }
+
+ switch (a0.GetKind())
+ {
+ case BVCONST:
+ output = BVConstEvaluator(CreateTerm(BVSX, len, a0, a1));
+ break;
+ case BVNEG:
+ output = CreateTerm(a0.GetKind(), len, CreateTerm(BVSX, len, a0[0], a1));
+ break;
+ case BVAND:
+ case BVOR:
+ //assuming BVAND and BVOR are binary
+ output = CreateTerm(a0.GetKind(), len, CreateTerm(BVSX, len, a0[0], a1), CreateTerm(BVSX, len, a0[1], a1));
+ break;
+ case BVPLUS:
+ {
+ //BVSX(m,BVPLUS(n,BVSX(t1),BVSX(t2))) <==> BVPLUS(m,BVSX(m,t1),BVSX(m,t2))
+ ASTVec c = a0.GetChildren();
+ bool returnflag = false;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ if (BVSX != it->GetKind())
+ {
+ returnflag = true;
+ break;
+ }
+ }
+ if (returnflag)
+ {
+ output = CreateTerm(BVSX, len, a0, a1);
+ }
+ else
+ {
+ ASTVec o;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(CreateTerm(BVSX, len, *it, a1));
+ o.push_back(aaa);
+ }
+ output = CreateTerm(a0.GetKind(), len, o);
+ }
+ break;
+ }
+ case BVSX:
+ {
+ //if you have BVSX(m,BVSX(n,a)) then you can drop the inner
+ //BVSX provided m is greater than n.
+ a0 = SimplifyTerm(a0[0]);
+ output = CreateTerm(BVSX, len, a0, a1);
+ break;
+ }
+ case ITE:
+ {
+ ASTNode cond = a0[0];
+ ASTNode thenpart = SimplifyTerm(CreateTerm(BVSX, len, a0[1], a1));
+ ASTNode elsepart = SimplifyTerm(CreateTerm(BVSX, len, a0[2], a1));
+ output = CreateSimplifiedTermITE(cond, thenpart, elsepart);
+ break;
+ }
+ default:
+ output = CreateTerm(BVSX, len, a0, a1);
+ break;
+ }
+ break;
+ }
+ case BVAND:
+ case BVOR:
+ {
+ ASTNode max = CreateMaxConst(inputValueWidth);
+ ASTNode zero = CreateZeroConst(inputValueWidth);
+
+ ASTNode identity = (BVAND == k) ? max : zero;
+ ASTNode annihilator = (BVAND == k) ? zero : max;
+ ASTVec c = FlattenOneLevel(inputterm).GetChildren();
+ SortByArith(c);
+ ASTVec o;
+ bool constant = true;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(*it);
+ if (BVCONST != aaa.GetKind())
+ {
+ constant = false;
+ }
+
+ if (aaa == annihilator)
+ {
+ output = annihilator;
+ //memoize
+ UpdateSimplifyMap(inputterm, output, false);
+ //cerr << "output of SimplifyTerm: " << output << endl;
+ return output;
+ }
+
+ if (aaa != identity)
+ {
+ o.push_back(aaa);
+ }
+ }
+
+ switch (o.size())
+ {
+ case 0:
+ output = identity;
+ break;
+ case 1:
+ output = o[0];
+ break;
+ default:
+ SortByArith(o);
+ output = CreateTerm(k, inputValueWidth, o);
+ if (constant)
+ {
+ output = BVConstEvaluator(output);
+ }
+ break;
+ }
+ break;
+ }
+ case BVCONCAT:
+ {
+ ASTNode t = SimplifyTerm(inputterm[0]);
+ ASTNode u = SimplifyTerm(inputterm[1]);
+ Kind tkind = t.GetKind();
+ Kind ukind = u.GetKind();
+
+ if (BVCONST == tkind && BVCONST == ukind)
+ {
+ output = BVConstEvaluator(CreateTerm(BVCONCAT, inputValueWidth, t, u));
+ }
+ else if (BVEXTRACT == tkind && BVEXTRACT == ukind && t[0] == u[0])
+ {
+ //to handle the case x[m:n]@x[n-1:k] <==> x[m:k]
+ ASTNode t_hi = t[1];
+ ASTNode t_low = t[2];
+ ASTNode u_hi = u[1];
+ ASTNode u_low = u[2];
+ ASTNode c = BVConstEvaluator(CreateTerm(BVPLUS, 32, u_hi, CreateOneConst(32)));
+ if (t_low == c)
+ {
+ output = CreateTerm(BVEXTRACT, inputValueWidth, t[0], t_hi, u_low);
+ }
+ else
+ {
+ output = CreateTerm(BVCONCAT, inputValueWidth, t, u);
+ }
+ }
+ else
+ {
+ output = CreateTerm(BVCONCAT, inputValueWidth, t, u);
+ }
+ break;
+ }
+ case BVXOR:
+ case BVXNOR:
+ case BVNAND:
+ case BVNOR:
+ case BVLEFTSHIFT:
+ case BVRIGHTSHIFT:
+ case BVVARSHIFT:
+ case BVSRSHIFT:
+ case BVDIV:
+ case BVMOD:
+ {
+ ASTVec c = inputterm.GetChildren();
+ ASTVec o;
+ bool constant = true;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(*it);
+ if (BVCONST != aaa.GetKind())
+ {
+ constant = false;
+ }
+ o.push_back(aaa);
+ }
+ output = CreateTerm(k, inputValueWidth, o);
+ if (constant)
+ output = BVConstEvaluator(output);
+ break;
+ }
+ case READ:
+ {
+ ASTNode out1;
+ //process only if not in the substitution map. simplifymap
+ //has been checked already
+ if (!CheckSubstitutionMap(inputterm, out1))
+ {
+ if (WRITE == inputterm[0].GetKind())
+ {
+ //get rid of all writes
+ ASTNode nowrites = RemoveWrites_TopLevel(inputterm);
+ out1 = nowrites;
+ }
+ else if (ITE == inputterm[0].GetKind())
+ {
+ ASTNode cond = SimplifyFormula(inputterm[0][0], false);
+ ASTNode index = SimplifyTerm(inputterm[1]);
+
+ ASTNode read1 = CreateTerm(READ, inputValueWidth, inputterm[0][1], index);
+ ASTNode read2 = CreateTerm(READ, inputValueWidth, inputterm[0][2], index);
+
+ read1 = SimplifyTerm(read1);
+ read2 = SimplifyTerm(read2);
+ out1 = CreateSimplifiedTermITE(cond, read1, read2);
+ }
+ else
+ {
+ //arr is a SYMBOL for sure
+ ASTNode arr = inputterm[0];
+ ASTNode index = SimplifyTerm(inputterm[1]);
+ out1 = CreateTerm(READ, inputValueWidth, arr, index);
+ }
+ }
+ //it is possible that after all the procesing the READ term
+ //reduces to READ(Symbol,const) and hence we should check the
+ //substitutionmap once again.
+ if (!CheckSubstitutionMap(out1, output))
+ output = out1;
+ break;
+ }
+ case ITE:
+ {
+ ASTNode t0 = SimplifyFormula(inputterm[0], false);
+ ASTNode t1 = SimplifyTerm(inputterm[1]);
+ ASTNode t2 = SimplifyTerm(inputterm[2]);
+ output = CreateSimplifiedTermITE(t0, t1, t2);
+ break;
+ }
+ case SBVREM:
+ case SBVDIV:
+ {
+ ASTVec c = inputterm.GetChildren();
+ ASTVec o;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(*it);
+ o.push_back(aaa);
+ }
+ output = CreateTerm(k, inputValueWidth, o);
+ break;
+ }
+ case WRITE:
+ default:
+ FatalError("SimplifyTerm: Control should never reach here:", inputterm, k);
+ return inputterm;
+ break;
+ }
+ assert(NULL != output);
+
+ //memoize
+ UpdateSimplifyMap(inputterm, output, false);
+ //cerr << "SimplifyTerm: output" << output << endl;
+ // CheckSimplifyInvariant(inputterm,output);
+
+ return output;
+} //end of SimplifyTerm()
+
+ASTNode BeevMgr::SimplifyTermAux(const ASTNode& inputterm)
+{
+ //cout << "SimplifyTerm: input: " << a << endl;
+ if (!optimize)
+ {
+ return inputterm;
+ }
+
+ ASTNode output;
+ BVTypeCheck(inputterm);
+
+ //########################################
+ //########################################
+
+ if (wordlevel_solve && CheckSolverMap(inputterm, output))
+ {
+ //cout << "SimplifyTerm: output: " << output << endl;
+ return SimplifyTermAux(output);
+ }
-};//end of namespace
+ Kind k = inputterm.GetKind();
+ if (!is_Term_kind(k))
+ {
+ FatalError("SimplifyTerm: You have input a Non-term", ASTUndefined);
+ }
+
+ unsigned int inputValueWidth = inputterm.GetValueWidth();
+ switch (k)
+ {
+ case BVCONST:
+ output = inputterm;
+ break;
+ case SYMBOL:
+ if (CheckSolverMap(inputterm, output))
+ {
+ return SimplifyTerm(output);
+ }
+ output = inputterm;
+ break;
+ case BVMULT:
+ case BVPLUS:
+ {
+ if (BVMULT == k && 2 != inputterm.Degree())
+ {
+ FatalError("SimplifyTerm: We assume that BVMULT is binary", inputterm);
+ }
+
+ ASTVec c = FlattenOneLevel(inputterm).GetChildren();
+ SortByArith(c);
+ ASTVec constkids, nonconstkids;
+
+ //go through the childnodes, and separate constant and
+ //nonconstant nodes. combine the constant nodes using the
+ //constevaluator. if the resultant constant is zero and k ==
+ //BVPLUS, then ignore it (similarily for 1 and BVMULT). else,
+ //add the computed constant to the nonconst vector, flatten,
+ //sort, and create BVPLUS/BVMULT and return
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(*it);
+ if (BVCONST == aaa.GetKind())
+ {
+ constkids.push_back(aaa);
+ }
+ else
+ {
+ nonconstkids.push_back(aaa);
+ }
+ }
+
+ ASTNode one = CreateOneConst(inputValueWidth);
+ ASTNode max = CreateMaxConst(inputValueWidth);
+ ASTNode zero = CreateZeroConst(inputValueWidth);
+
+ //initialize constoutput to zero, in case there are no elements
+ //in constkids
+ ASTNode constoutput = (k == BVPLUS) ? zero : one;
+
+ if (1 == constkids.size())
+ {
+ //only one element in constkids
+ constoutput = constkids[0];
+ }
+ else if (1 < constkids.size())
+ {
+ //many elements in constkids. simplify it
+ constoutput = CreateTerm(k, inputterm.GetValueWidth(), constkids);
+ constoutput = BVConstEvaluator(constoutput);
+ }
+
+ if (BVMULT == k && zero == constoutput)
+ {
+ output = zero;
+ }
+ else if (BVMULT == k && 1 == nonconstkids.size() && constoutput == max)
+ {
+ //useful special case opt: when input is BVMULT(max_const,t),
+ //then output = BVUMINUS(t). this is easier on the bitblaster
+ output = CreateTerm(BVUMINUS, inputValueWidth, nonconstkids);
+ }
+ else
+ {
+ if (0 < nonconstkids.size())
+ {
+ //nonconstkids is not empty. First, combine const and
+ //nonconstkids
+ if (BVPLUS == k && constoutput != zero)
+ {
+ nonconstkids.push_back(constoutput);
+ }
+ else if (BVMULT == k && constoutput != one)
+ {
+ nonconstkids.push_back(constoutput);
+ }
+
+ if (1 == nonconstkids.size())
+ {
+ //exactly one element in nonconstkids. output is exactly
+ //nonconstkids[0]
+ output = nonconstkids[0];
+ }
+ else
+ {
+ //more than 1 element in nonconstkids. create BVPLUS term
+ SortByArith(nonconstkids);
+ output = CreateTerm(k, inputValueWidth, nonconstkids);
+ output = FlattenOneLevel(output);
+ output = DistributeMultOverPlus(output, true);
+ output = CombineLikeTerms(output);
+ }
+ }
+ else
+ {
+ //nonconstkids was empty, all childnodes were constant, hence
+ //constoutput is the output.
+ output = constoutput;
+ }
+ }
+ if (BVMULT == output.GetKind() || BVPLUS == output.GetKind())
+ {
+ ASTVec d = output.GetChildren();
+ SortByArith(d);
+ output = CreateTerm(output.GetKind(), output.GetValueWidth(), d);
+ }
+ break;
+ }
+ case BVSUB:
+ {
+ ASTVec c = inputterm.GetChildren();
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ ASTNode a1 = SimplifyTerm(inputterm[1]);
+ unsigned int l = inputValueWidth;
+ if (a0 == a1)
+ output = CreateZeroConst(l);
+ else
+ {
+ //covert x-y into x+(-y) and simplify. this transformation
+ //triggers more simplifications
+ //
+ a1 = SimplifyTerm(CreateTerm(BVUMINUS, l, a1));
+ output = SimplifyTerm(CreateTerm(BVPLUS, l, a0, a1));
+ }
+ break;
+ }
+ case BVUMINUS:
+ {
+ //important to treat BVUMINUS as a special case, because it
+ //helps in arithmetic transformations. e.g. x + BVUMINUS(x) is
+ //actually 0. One way to reveal this fact is to strip bvuminus
+ //out, and replace with something else so that combineliketerms
+ //can catch this fact.
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ Kind k1 = a0.GetKind();
+ unsigned int l = a0.GetValueWidth();
+ ASTNode one = CreateOneConst(l);
+ switch (k1)
+ {
+ case BVUMINUS:
+ output = a0[0];
+ break;
+ case BVCONST:
+ {
+ output = BVConstEvaluator(CreateTerm(BVUMINUS, l, a0));
+ break;
+ }
+ case BVNEG:
+ {
+ output = SimplifyTerm(CreateTerm(BVPLUS, l, a0[0], one));
+ break;
+ }
+ case BVMULT:
+ {
+ if (BVUMINUS == a0[0].GetKind())
+ {
+ output = CreateTerm(BVMULT, l, a0[0][0], a0[1]);
+ }
+ else if (BVUMINUS == a0[1].GetKind())
+ {
+ output = CreateTerm(BVMULT, l, a0[0], a0[1][0]);
+ }
+ else
+ {
+ ASTNode a00 = SimplifyTerm(CreateTerm(BVUMINUS, l, a0[0]));
+ output = CreateTerm(BVMULT, l, a00, a0[1]);
+ }
+ break;
+ }
+ case BVPLUS:
+ {
+ //push BVUMINUS over all the monomials of BVPLUS. Simplify
+ //along the way
+ //
+ //BVUMINUS(a1x1 + a2x2 + ...) <=> BVPLUS(BVUMINUS(a1x1) +
+ //BVUMINUS(a2x2) + ...
+ ASTVec c = a0.GetChildren();
+ ASTVec o;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ //Simplify(BVUMINUS(a1x1))
+ ASTNode aaa = SimplifyTerm(CreateTerm(BVUMINUS, l, *it));
+ o.push_back(aaa);
+ }
+ //simplify the bvplus
+ output = SimplifyTerm(CreateTerm(BVPLUS, l, o));
+ break;
+ }
+ case BVSUB:
+ {
+ //BVUMINUS(BVSUB(x,y)) <=> BVSUB(y,x)
+ output = SimplifyTerm(CreateTerm(BVSUB, l, a0[1], a0[0]));
+ break;
+ }
+ case ITE:
+ {
+ //BVUMINUS(ITE(c,t1,t2)) <==> ITE(c,BVUMINUS(t1),BVUMINUS(t2))
+ ASTNode c = a0[0];
+ ASTNode t1 = SimplifyTerm(CreateTerm(BVUMINUS, l, a0[1]));
+ ASTNode t2 = SimplifyTerm(CreateTerm(BVUMINUS, l, a0[2]));
+ output = CreateSimplifiedTermITE(c, t1, t2);
+ break;
+ }
+ default:
+ {
+ output = CreateTerm(BVUMINUS, l, a0);
+ break;
+ }
+ }
+ break;
+ }
+ case BVEXTRACT:
+ {
+ //it is important to take care of wordlevel transformation in
+ //BVEXTRACT. it exposes oppurtunities for later simplification
+ //and solving (variable elimination)
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ Kind k1 = a0.GetKind();
+ unsigned int a_len = inputValueWidth;
+
+ //indices for BVEXTRACT
+ ASTNode i = inputterm[1];
+ ASTNode j = inputterm[2];
+ ASTNode zero = CreateBVConst(32, 0);
+ //recall that the indices of BVEXTRACT are always 32 bits
+ //long. therefore doing a GetBVUnsigned is ok.
+ unsigned int i_val = GetUnsignedConst(i);
+ unsigned int j_val = GetUnsignedConst(j);
+
+ // a0[i:0] and len(a0)=i+1, then return a0
+ if (0 == j_val && a_len == a0.GetValueWidth())
+ return a0;
+
+ switch (k1)
+ {
+ case BVCONST:
+ {
+ //extract the constant
+ output = BVConstEvaluator(CreateTerm(BVEXTRACT, a_len, a0, i, j));
+ break;
+ }
+ case BVCONCAT:
+ {
+ //assumes concatenation is binary
+ //
+ //input is of the form a0[i:j]
+ //
+ //a0 is the conatentation t@u, and a0[0] is t, and a0[1] is u
+ ASTNode t = a0[0];
+ ASTNode u = a0[1];
+ unsigned int len_a0 = a0.GetValueWidth();
+ unsigned int len_u = u.GetValueWidth();
+
+ if (len_u > i_val)
+ {
+ //Apply the following rule:
+ // (t@u)[i:j] <==> u[i:j], if len(u) > i
+ //
+ output = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, u, i, j));
+ }
+ else if (len_a0 > i_val && j_val >= len_u)
+ {
+ //Apply the rule:
+ // (t@u)[i:j] <==> t[i-len_u:j-len_u], if len(t@u) > i >= j >= len(u)
+ i = CreateBVConst(32, i_val - len_u);
+ j = CreateBVConst(32, j_val - len_u);
+ output = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, t, i, j));
+ }
+ else
+ {
+ //Apply the rule:
+ // (t@u)[i:j] <==> t[i-len_u:0] @ u[len_u-1:j]
+ i = CreateBVConst(32, i_val - len_u);
+ ASTNode m = CreateBVConst(32, len_u - 1);
+ t = SimplifyTerm(CreateTerm(BVEXTRACT, i_val - len_u + 1, t, i, zero));
+ u = SimplifyTerm(CreateTerm(BVEXTRACT, len_u - j_val, u, m, j));
+ output = CreateTerm(BVCONCAT, a_len, t, u);
+ }
+ break;
+ }
+ case BVPLUS:
+ case BVMULT:
+ {
+ // (BVMULT(n,t,u))[i:j] <==> BVMULT(i+1,t[i:0],u[i:0])[i:j]
+ //similar rule for BVPLUS
+ ASTVec c = a0.GetChildren();
+ ASTVec o;
+ for (ASTVec::iterator jt = c.begin(), jtend = c.end(); jt != jtend; jt++)
+ {
+ ASTNode aaa = *jt;
+ aaa = SimplifyTerm(CreateTerm(BVEXTRACT, i_val + 1, aaa, i, zero));
+ o.push_back(aaa);
+ }
+ output = CreateTerm(a0.GetKind(), i_val + 1, o);
+ if (j_val != 0)
+ {
+ //add extraction only if j is not zero
+ output = CreateTerm(BVEXTRACT, a_len, output, i, j);
+ }
+ break;
+ }
+ case BVAND:
+ case BVOR:
+ case BVXOR:
+ {
+ //assumes these operators are binary
+ //
+ // (t op u)[i:j] <==> t[i:j] op u[i:j]
+ ASTNode t = a0[0];
+ ASTNode u = a0[1];
+ t = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, t, i, j));
+ u = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, u, i, j));
+ BVTypeCheck(t);
+ BVTypeCheck(u);
+ output = CreateTerm(k1, a_len, t, u);
+ break;
+ }
+ case BVNEG:
+ {
+ // (~t)[i:j] <==> ~(t[i:j])
+ ASTNode t = a0[0];
+ t = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, t, i, j));
+ output = CreateTerm(BVNEG, a_len, t);
+ break;
+ }
+ // case BVSX:{
+ // //(BVSX(t,n)[i:j] <==> BVSX(t,i+1), if n >= i+1 and j=0
+ // ASTNode t = a0[0];
+ // unsigned int bvsx_len = a0.GetValueWidth();
+ // if(bvsx_len < a_len) {
+ // FatalError("SimplifyTerm: BVEXTRACT over BVSX:"
+ // "the length of BVSX term must be greater than extract-len",inputterm);
+ // }
+ // if(j != zero) {
+ // output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
+ // }
+ // else {
+ // output = CreateTerm(BVSX,a_len,t,CreateBVConst(32,a_len));
+ // }
+ // break;
+ // }
+ case ITE:
+ {
+ ASTNode t0 = a0[0];
+ ASTNode t1 = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, a0[1], i, j));
+ ASTNode t2 = SimplifyTerm(CreateTerm(BVEXTRACT, a_len, a0[2], i, j));
+ output = CreateSimplifiedTermITE(t0, t1, t2);
+ break;
+ }
+ default:
+ {
+ output = CreateTerm(BVEXTRACT, a_len, a0, i, j);
+ break;
+ }
+ }
+ break;
+ }
+ case BVNEG:
+ {
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ unsigned len = inputValueWidth;
+ switch (a0.GetKind())
+ {
+ case BVCONST:
+ output = BVConstEvaluator(CreateTerm(BVNEG, len, a0));
+ break;
+ case BVNEG:
+ output = a0[0];
+ break;
+ // case ITE: {
+ // ASTNode cond = a0[0];
+ // ASTNode thenpart = SimplifyTerm(CreateTerm(BVNEG,len,a0[1]));
+ // ASTNode elsepart = SimplifyTerm(CreateTerm(BVNEG,len,a0[2]));
+ // output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
+ // break;
+ // }
+ default:
+ output = CreateTerm(BVNEG, len, a0);
+ break;
+ }
+ break;
+ }
+ case BVZX:
+ {
+ //a0 is the expr which is being zero extended
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ //a1 represents the length of the term BVZX(a0)
+ ASTNode a1 = inputterm[1];
+ //output length of the BVSX term
+ unsigned len = inputValueWidth;
+
+ output = CreateTerm(BVZX, len, a0, a1);
+ break;
+ }
+ break;
+
+ case BVSX:
+ {
+ //a0 is the expr which is being sign extended
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ //a1 represents the length of the term BVSX(a0)
+ ASTNode a1 = inputterm[1];
+ //output length of the BVSX term
+ unsigned len = inputValueWidth;
+
+ if (a0.GetValueWidth() == len)
+ {
+ //nothing to signextend
+ return a0;
+ }
+
+ switch (a0.GetKind())
+ {
+ case BVCONST:
+ output = BVConstEvaluator(CreateTerm(BVSX, len, a0, a1));
+ break;
+ case BVNEG:
+ output = CreateTerm(a0.GetKind(), len, CreateTerm(BVSX, len, a0[0], a1));
+ break;
+ case BVAND:
+ case BVOR:
+ //assuming BVAND and BVOR are binary
+ output = CreateTerm(a0.GetKind(), len, CreateTerm(BVSX, len, a0[0], a1), CreateTerm(BVSX, len, a0[1], a1));
+ break;
+ case BVPLUS:
+ {
+ //BVSX(m,BVPLUS(n,BVSX(t1),BVSX(t2))) <==> BVPLUS(m,BVSX(m,t1),BVSX(m,t2))
+ ASTVec c = a0.GetChildren();
+ bool returnflag = false;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ if (BVSX != it->GetKind())
+ {
+ returnflag = true;
+ break;
+ }
+ }
+ if (returnflag)
+ {
+ output = CreateTerm(BVSX, len, a0, a1);
+ }
+ else
+ {
+ ASTVec o;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(CreateTerm(BVSX, len, *it, a1));
+ o.push_back(aaa);
+ }
+ output = CreateTerm(a0.GetKind(), len, o);
+ }
+ break;
+ }
+ case BVSX:
+ {
+ //if you have BVSX(m,BVSX(n,a)) then you can drop the inner
+ //BVSX provided m is greater than n.
+ a0 = SimplifyTerm(a0[0]);
+ output = CreateTerm(BVSX, len, a0, a1);
+ break;
+ }
+ case ITE:
+ {
+ ASTNode cond = a0[0];
+ ASTNode thenpart = SimplifyTerm(CreateTerm(BVSX, len, a0[1], a1));
+ ASTNode elsepart = SimplifyTerm(CreateTerm(BVSX, len, a0[2], a1));
+ output = CreateSimplifiedTermITE(cond, thenpart, elsepart);
+ break;
+ }
+ default:
+ output = CreateTerm(BVSX, len, a0, a1);
+ break;
+ }
+ break;
+ }
+ case BVAND:
+ case BVOR:
+ {
+ ASTNode max = CreateMaxConst(inputValueWidth);
+ ASTNode zero = CreateZeroConst(inputValueWidth);
+
+ ASTNode identity = (BVAND == k) ? max : zero;
+ ASTNode annihilator = (BVAND == k) ? zero : max;
+ ASTVec c = FlattenOneLevel(inputterm).GetChildren();
+ SortByArith(c);
+ ASTVec o;
+ bool constant = true;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(*it);
+ if (BVCONST != aaa.GetKind())
+ {
+ constant = false;
+ }
+
+ if (aaa == annihilator)
+ {
+ output = annihilator;
+ return output;
+ }
+
+ if (aaa != identity)
+ {
+ o.push_back(aaa);
+ }
+ }
+
+ switch (o.size())
+ {
+ case 0:
+ output = identity;
+ break;
+ case 1:
+ output = o[0];
+ break;
+ default:
+ SortByArith(o);
+ output = CreateTerm(k, inputValueWidth, o);
+ if (constant)
+ {
+ output = BVConstEvaluator(output);
+ }
+ break;
+ }
+ break;
+ }
+ case BVCONCAT:
+ {
+ ASTNode t = SimplifyTerm(inputterm[0]);
+ ASTNode u = SimplifyTerm(inputterm[1]);
+ Kind tkind = t.GetKind();
+ Kind ukind = u.GetKind();
+
+ if (BVCONST == tkind && BVCONST == ukind)
+ {
+ output = BVConstEvaluator(CreateTerm(BVCONCAT, inputValueWidth, t, u));
+ }
+ else if (BVEXTRACT == tkind && BVEXTRACT == ukind && t[0] == u[0])
+ {
+ //to handle the case x[m:n]@x[n-1:k] <==> x[m:k]
+ ASTNode t_hi = t[1];
+ ASTNode t_low = t[2];
+ ASTNode u_hi = u[1];
+ ASTNode u_low = u[2];
+ ASTNode c = BVConstEvaluator(CreateTerm(BVPLUS, 32, u_hi, CreateOneConst(32)));
+ if (t_low == c)
+ {
+ output = CreateTerm(BVEXTRACT, inputValueWidth, t[0], t_hi, u_low);
+ }
+ else
+ {
+ output = CreateTerm(BVCONCAT, inputValueWidth, t, u);
+ }
+ }
+ else
+ {
+ output = CreateTerm(BVCONCAT, inputValueWidth, t, u);
+ }
+ break;
+ }
+ case BVXOR:
+ case BVXNOR:
+ case BVNAND:
+ case BVNOR:
+ case BVLEFTSHIFT:
+ case BVRIGHTSHIFT:
+ case BVVARSHIFT:
+ case BVSRSHIFT:
+ case BVDIV:
+ case BVMOD:
+ {
+ ASTVec c = inputterm.GetChildren();
+ ASTVec o;
+ bool constant = true;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(*it);
+ if (BVCONST != aaa.GetKind())
+ {
+ constant = false;
+ }
+ o.push_back(aaa);
+ }
+ output = CreateTerm(k, inputValueWidth, o);
+ if (constant)
+ output = BVConstEvaluator(output);
+ break;
+ }
+ case READ:
+ {
+ ASTNode out1;
+ //process only if not in the substitution map. simplifymap
+ //has been checked already
+ if (!CheckSubstitutionMap(inputterm, out1))
+ {
+ if (WRITE == inputterm[0].GetKind())
+ {
+ //get rid of all writes
+ ASTNode nowrites = RemoveWrites_TopLevel(inputterm);
+ out1 = nowrites;
+ }
+ else if (ITE == inputterm[0].GetKind())
+ {
+ ASTNode cond = SimplifyFormula(inputterm[0][0], false);
+ ASTNode index = SimplifyTerm(inputterm[1]);
+
+ ASTNode read1 = CreateTerm(READ, inputValueWidth, inputterm[0][1], index);
+ ASTNode read2 = CreateTerm(READ, inputValueWidth, inputterm[0][2], index);
+
+ read1 = SimplifyTerm(read1);
+ read2 = SimplifyTerm(read2);
+ out1 = CreateSimplifiedTermITE(cond, read1, read2);
+ }
+ else
+ {
+ //arr is a SYMBOL for sure
+ ASTNode arr = inputterm[0];
+ ASTNode index = SimplifyTerm(inputterm[1]);
+ out1 = CreateTerm(READ, inputValueWidth, arr, index);
+ }
+ }
+ //it is possible that after all the procesing the READ term
+ //reduces to READ(Symbol,const) and hence we should check the
+ //substitutionmap once again.
+ if (!CheckSubstitutionMap(out1, output))
+ output = out1;
+ break;
+ }
+ case ITE:
+ {
+ ASTNode t0 = SimplifyFormula(inputterm[0], false);
+ ASTNode t1 = SimplifyTerm(inputterm[1]);
+ ASTNode t2 = SimplifyTerm(inputterm[2]);
+ output = CreateSimplifiedTermITE(t0, t1, t2);
+ break;
+ }
+ case SBVREM:
+ case SBVMOD:
+ case SBVDIV:
+ {
+ ASTVec c = inputterm.GetChildren();
+ ASTVec o;
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = SimplifyTerm(*it);
+ o.push_back(aaa);
+ }
+ output = CreateTerm(k, inputValueWidth, o);
+ break;
+ }
+ case WRITE:
+ default:
+ FatalError("SimplifyTermAux: Control should never reach here:", inputterm, k);
+ return inputterm;
+ break;
+ }
+
+ return output;
+}
+
+//At the end of each simplification call, we want the output to be
+//always smaller or equal to the input in size.
+void BeevMgr::CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output)
+{
+
+ if (NodeSize(a, true) + 1 < NodeSize(output, true))
+ {
+ cerr << "lhs := " << a << endl;
+ cerr << "NodeSize of lhs is: " << NodeSize(a, true) << endl;
+ cerr << endl;
+ cerr << "rhs := " << output << endl;
+ cerr << "NodeSize of rhs is: " << NodeSize(output, true) << endl;
+ // FatalError("SimplifyFormula: The nodesize shoudl decrease from lhs to rhs: ",ASTUndefined);
+ }
+}
+
+//this function assumes that the input is a vector of childnodes of
+//a BVPLUS term. it combines like terms and returns a bvplus
+//term. e.g. 1.x + 2.x is converted to 3.x
+ASTNode BeevMgr::CombineLikeTerms(const ASTNode& a)
+{
+ if (BVPLUS != a.GetKind())
+ return a;
+
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, false))
+ {
+ //check memo table
+ //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ return output;
+ }
+
+ const ASTVec& c = a.GetChildren();
+ //map from variables to vector of constants
+ ASTNodeToVecMap vars_to_consts;
+ //vector to hold constants
+ ASTVec constkids;
+ ASTVec outputvec;
+
+ //useful constants
+ unsigned int len = c[0].GetValueWidth();
+ ASTNode one = CreateOneConst(len);
+ ASTNode zero = CreateZeroConst(len);
+ ASTNode max = CreateMaxConst(len);
+
+ //go over the childnodes of the input bvplus, and collect like
+ //terms in a map. the key of the map are the variables, and the
+ //values are stored in a ASTVec
+ for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ ASTNode aaa = *it;
+ if (SYMBOL == aaa.GetKind())
+ {
+ vars_to_consts[aaa].push_back(one);
+ }
+ else if (BVMULT == aaa.GetKind() && BVUMINUS == aaa[0].GetKind() && BVCONST == aaa[0][0].GetKind())
+ {
+ //(BVUMINUS(c))*(y) <==> compute(BVUMINUS(c))*y
+ ASTNode compute_const = BVConstEvaluator(aaa[0]);
+ vars_to_consts[aaa[1]].push_back(compute_const);
+ }
+ else if (BVMULT == aaa.GetKind() && BVUMINUS == aaa[1].GetKind() && BVCONST == aaa[0].GetKind())
+ {
+ //c*(BVUMINUS(y)) <==> compute(BVUMINUS(c))*y
+ ASTNode cccc = BVConstEvaluator(CreateTerm(BVUMINUS, len, aaa[0]));
+ vars_to_consts[aaa[1][0]].push_back(cccc);
+ }
+ else if (BVMULT == aaa.GetKind() && BVCONST == aaa[0].GetKind())
+ {
+ //assumes that BVMULT is binary
+ vars_to_consts[aaa[1]].push_back(aaa[0]);
+ }
+ else if (BVMULT == aaa.GetKind() && BVUMINUS == aaa[0].GetKind())
+ {
+ //(-1*x)*(y) <==> -1*(xy)
+ ASTNode cccc = CreateTerm(BVMULT, len, aaa[0][0], aaa[1]);
+ ASTVec cNodes = cccc.GetChildren();
+ SortByArith(cNodes);
+ vars_to_consts[cccc].push_back(max);
+ }
+ else if (BVMULT == aaa.GetKind() && BVUMINUS == aaa[1].GetKind())
+ {
+ //x*(-1*y) <==> -1*(xy)
+ ASTNode cccc = CreateTerm(BVMULT, len, aaa[0], aaa[1][0]);
+ ASTVec cNodes = cccc.GetChildren();
+ SortByArith(cNodes);
+ vars_to_consts[cccc].push_back(max);
+ }
+ else if (BVCONST == aaa.GetKind())
+ {
+ constkids.push_back(aaa);
+ }
+ else if (BVUMINUS == aaa.GetKind())
+ {
+ //helps to convert BVUMINUS into a BVMULT. here the max
+ //constant represents -1. this transformation allows us to
+ //conclude that x + BVUMINUS(x) is 0.
+ vars_to_consts[aaa[0]].push_back(max);
+ }
+ else
+ vars_to_consts[aaa].push_back(one);
+ } //end of for loop
+
+ //go over the map from variables to vector of values. combine the
+ //vector of values, multiply to the variable, and put the
+ //resultant monomial in the output BVPLUS.
+ for (ASTNodeToVecMap::iterator it = vars_to_consts.begin(), itend = vars_to_consts.end(); it != itend; it++)
+ {
+ ASTVec ccc = it->second;
+
+ ASTNode constant;
+ if (1 < ccc.size())
+ {
+ constant = CreateTerm(BVPLUS, ccc[0].GetValueWidth(), ccc);
+ constant = BVConstEvaluator(constant);
+ }
+ else
+ constant = ccc[0];
+
+ //constant * var
+ ASTNode monom;
+ if (zero == constant)
+ monom = zero;
+ else if (one == constant)
+ monom = it->first;
+ else
+ {
+ monom = SimplifyTerm(CreateTerm(BVMULT, constant.GetValueWidth(), constant, it->first));
+ }
+ if (zero != monom)
+ {
+ outputvec.push_back(monom);
+ }
+ } //end of for loop
+
+ if (constkids.size() > 1)
+ {
+ ASTNode output = CreateTerm(BVPLUS, constkids[0].GetValueWidth(), constkids);
+ output = BVConstEvaluator(output);
+ if (output != zero)
+ outputvec.push_back(output);
+ }
+ else if (constkids.size() == 1)
+ {
+ if (constkids[0] != zero)
+ outputvec.push_back(constkids[0]);
+ }
+
+ if (outputvec.size() > 1)
+ {
+ output = CreateTerm(BVPLUS, len, outputvec);
+ }
+ else if (outputvec.size() == 1)
+ {
+ output = outputvec[0];
+ }
+ else
+ {
+ output = zero;
+ }
+
+ //memoize
+ //UpdateSimplifyMap(a,output,false);
+ return output;
+} //end of CombineLikeTerms()
+
+//accepts lhs and rhs, and returns lhs - rhs = 0. The function
+//assumes that lhs and rhs have already been simplified. although
+//this assumption is not needed for correctness, it is essential for
+//performance. The function also assumes that lhs is a BVPLUS
+ASTNode BeevMgr::LhsMinusRhs(const ASTNode& eq)
+{
+ //if input is not an equality, simply return it
+ if (EQ != eq.GetKind())
+ return eq;
+
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ Kind k_lhs = lhs.GetKind();
+ Kind k_rhs = rhs.GetKind();
+ //either the lhs has to be a BVPLUS or the rhs has to be a
+ //BVPLUS
+ if (!(BVPLUS == k_lhs || BVPLUS == k_rhs || (BVMULT == k_lhs && BVMULT == k_rhs)))
+ {
+ return eq;
+ }
+
+ ASTNode output;
+ if (CheckSimplifyMap(eq, output, false))
+ {
+ //check memo table
+ //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ return output;
+ }
+
+ //if the lhs is not a BVPLUS, but the rhs is a BVPLUS, then swap
+ //the lhs and rhs
+ bool swap_flag = false;
+ if (BVPLUS != k_lhs && BVPLUS == k_rhs)
+ {
+ ASTNode swap = lhs;
+ lhs = rhs;
+ rhs = swap;
+ swap_flag = true;
+ }
+
+ unsigned int len = lhs.GetValueWidth();
+ ASTNode zero = CreateZeroConst(len);
+ //right is -1*(rhs): Simplify(-1*rhs)
+ rhs = SimplifyTerm(CreateTerm(BVUMINUS, len, rhs));
+
+ ASTVec lvec = lhs.GetChildren();
+ ASTVec rvec = rhs.GetChildren();
+ ASTNode lhsplusrhs;
+ if (BVPLUS != lhs.GetKind() && BVPLUS != rhs.GetKind())
+ {
+ lhsplusrhs = CreateTerm(BVPLUS, len, lhs, rhs);
+ }
+ else if (BVPLUS == lhs.GetKind() && BVPLUS == rhs.GetKind())
+ {
+ //combine the childnodes of the left and the right
+ lvec.insert(lvec.end(), rvec.begin(), rvec.end());
+ lhsplusrhs = CreateTerm(BVPLUS, len, lvec);
+ }
+ else if (BVPLUS == lhs.GetKind() && BVPLUS != rhs.GetKind())
+ {
+ lvec.push_back(rhs);
+ lhsplusrhs = CreateTerm(BVPLUS, len, lvec);
+ }
+ else
+ {
+ //Control should never reach here
+ FatalError("LhsMinusRhs: Control should never reach here\n");
+ }
+
+ //combine like terms
+ output = CombineLikeTerms(lhsplusrhs);
+ output = SimplifyTerm(output);
+ //
+ //Now make output into: lhs-rhs = 0
+ output = CreateSimplifiedEQ(output, zero);
+ //sort if BVPLUS
+ if (BVPLUS == output.GetKind())
+ {
+ ASTVec outv = output.GetChildren();
+ SortByArith(outv);
+ output = CreateTerm(BVPLUS, len, outv);
+ }
+
+ //memoize
+ //UpdateSimplifyMap(eq,output,false);
+ return output;
+} //end of LhsMinusRHS()
+
+//THis function accepts a BVMULT(t1,t2) and distributes the mult
+//over plus if either or both t1 and t2 are BVPLUSes.
+//
+// x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
+//
+// (y1 + y2 + ...+ yn)*x <==> x*y1 + x*y2 + ... + x*yn
+//
+// The function assumes that the BVPLUSes have been flattened
+ASTNode BeevMgr::DistributeMultOverPlus(const ASTNode& a, bool startdistribution)
+{
+ if (!startdistribution)
+ return a;
+ Kind k = a.GetKind();
+ if (BVMULT != k)
+ return a;
+
+ ASTNode left = a[0];
+ ASTNode right = a[1];
+ Kind left_kind = left.GetKind();
+ Kind right_kind = right.GetKind();
+
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, false))
+ {
+ //check memo table
+ //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ return output;
+ }
+
+ //special case optimization: c1*(c2*t1) <==> (c1*c2)*t1
+ if (BVCONST == left_kind && BVMULT == right_kind && BVCONST == right[0].GetKind())
+ {
+ ASTNode c = BVConstEvaluator(CreateTerm(BVMULT, a.GetValueWidth(), left, right[0]));
+ c = CreateTerm(BVMULT, a.GetValueWidth(), c, right[1]);
+ return c;
+ left = c[0];
+ right = c[1];
+ left_kind = left.GetKind();
+ right_kind = right.GetKind();
+ }
+
+ //special case optimization: c1*(t1*c2) <==> (c1*c2)*t1
+ if (BVCONST == left_kind && BVMULT == right_kind && BVCONST == right[1].GetKind())
+ {
+ ASTNode c = BVConstEvaluator(CreateTerm(BVMULT, a.GetValueWidth(), left, right[1]));
+ c = CreateTerm(BVMULT, a.GetValueWidth(), c, right[0]);
+ return c;
+ left = c[0];
+ right = c[1];
+ left_kind = left.GetKind();
+ right_kind = right.GetKind();
+ }
+
+ //atleast one of left or right have to be BVPLUS
+ if (!(BVPLUS == left_kind || BVPLUS == right_kind))
+ {
+ return a;
+ }
+
+ //if left is BVPLUS and right is not, then swap left and right. we
+ //can do this since BVMULT is communtative
+ ASTNode swap;
+ if (BVPLUS == left_kind && BVPLUS != right_kind)
+ {
+ swap = left;
+ left = right;
+ right = swap;
+ }
+ left_kind = left.GetKind();
+ right_kind = right.GetKind();
+
+ //by this point we are gauranteed that right is a BVPLUS, but left
+ //may not be
+ ASTVec rightnodes = right.GetChildren();
+ ASTVec outputvec;
+ unsigned len = a.GetValueWidth();
+ ASTNode zero = CreateZeroConst(len);
+ ASTNode one = CreateOneConst(len);
+ if (BVPLUS != left_kind)
+ {
+ //if the multiplier is not a BVPLUS then we have a special case
+ // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
+ if (zero == left)
+ {
+ outputvec.push_back(zero);
+ }
+ else if (one == left)
+ {
+ outputvec.push_back(left);
+ }
+ else
+ {
+ for (ASTVec::iterator j = rightnodes.begin(), jend = rightnodes.end(); j != jend; j++)
+ {
+ ASTNode out = SimplifyTerm(CreateTerm(BVMULT, len, left, *j));
+ outputvec.push_back(out);
+ }
+ }
+ }
+ else
+ {
+ ASTVec leftnodes = left.GetChildren();
+ // (x1 + x2 + ... + xm)*(y1 + y2 + ...+ yn) <==> x1*y1 + x1*y2 +
+ // ... + x2*y1 + ... + xm*yn
+ for (ASTVec::iterator i = leftnodes.begin(), iend = leftnodes.end(); i != iend; i++)
+ {
+ ASTNode multiplier = *i;
+ for (ASTVec::iterator j = rightnodes.begin(), jend = rightnodes.end(); j != jend; j++)
+ {
+ ASTNode out = SimplifyTerm(CreateTerm(BVMULT, len, multiplier, *j));
+ outputvec.push_back(out);
+ }
+ }
+ }
+
+ //compute output here
+ if (outputvec.size() > 1)
+ {
+ output = CombineLikeTerms(CreateTerm(BVPLUS, len, outputvec));
+ output = SimplifyTerm(output);
+ }
+ else
+ output = SimplifyTerm(outputvec[0]);
+
+ //memoize
+ //UpdateSimplifyMap(a,output,false);
+ return output;
+} //end of distributemultoverplus()
+
+//converts the BVSX(len, a0) operator into ITE( check top bit,
+//extend a0 by 1, extend a0 by 0)
+ASTNode BeevMgr::ConvertBVSXToITE(const ASTNode& a)
+{
+ if (BVSX != a.GetKind())
+ return a;
+
+ ASTNode output;
+ if (CheckSimplifyMap(a, output, false))
+ {
+ //check memo table
+ //cerr << "output of ConvertBVSXToITE Cache: " << output << endl;
+ return output;
+ }
+
+ ASTNode a0 = a[0];
+ unsigned a_len = a.GetValueWidth();
+ unsigned a0_len = a0.GetValueWidth();
+
+ if (a0_len > a_len)
+ {
+ FatalError("Trying to sign_extend a larger BV into a smaller BV");
+ return ASTUndefined; //to stop the compiler from producing bogus warnings
+ }
+
+ //sign extend
+ unsigned extensionlen = a_len - a0_len;
+ if (0 == extensionlen)
+ {
+ UpdateSimplifyMap(a, output, false);
+ return a;
+ }
+
+ std::string ones;
+ for (unsigned c = 0; c < extensionlen; c++)
+ ones += '1';
+ std::string zeros;
+ for (unsigned c = 0; c < extensionlen; c++)
+ zeros += '0';
+
+ //string of oness of length extensionlen
+ BEEV::ASTNode BVOnes = CreateBVConst(ones.c_str(), 2);
+ //string of zeros of length extensionlen
+ BEEV::ASTNode BVZeros = CreateBVConst(zeros.c_str(), 2);
+
+ //string of ones BVCONCAT a0
+ BEEV::ASTNode concatOnes = CreateTerm(BEEV::BVCONCAT, a_len, BVOnes, a0);
+ //string of zeros BVCONCAT a0
+ BEEV::ASTNode concatZeros = CreateTerm(BEEV::BVCONCAT, a_len, BVZeros, a0);
+
+ //extract top bit of a0
+ BEEV::ASTNode hi = CreateBVConst(32, a0_len - 1);
+ BEEV::ASTNode low = CreateBVConst(32, a0_len - 1);
+ BEEV::ASTNode topBit = CreateTerm(BEEV::BVEXTRACT, 1, a0, hi, low);
+
+ //compare topBit of a0 with 0bin1
+ BEEV::ASTNode condition = CreateSimplifiedEQ(CreateBVConst(1, 1), topBit);
+
+ //ITE(topbit = 0bin1, 0bin1111...a0, 0bin000...a0)
+ output = CreateSimplifiedTermITE(condition, concatOnes, concatZeros);
+ UpdateSimplifyMap(a, output, false);
+ return output;
+} //end of ConvertBVSXToITE()
+
+
+ASTNode BeevMgr::RemoveWrites_TopLevel(const ASTNode& term)
+{
+ if (READ != term.GetKind() && WRITE != term[0].GetKind())
+ {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE", term);
+ }
+
+ if (!Begin_RemoveWrites && !SimplifyWrites_InPlace_Flag && !start_abstracting)
+ {
+ return term;
+ }
+ else if (!Begin_RemoveWrites && SimplifyWrites_InPlace_Flag && !start_abstracting)
+ {
+ //return term;
+ return SimplifyWrites_InPlace(term);
+ }
+ else
+ {
+ return RemoveWrites(term);
+ }
+} //end of RemoveWrites_TopLevel()
+
+ASTNode BeevMgr::SimplifyWrites_InPlace(const ASTNode& term)
+{
+ ASTNodeMultiSet WriteIndicesSeenSoFar;
+ bool SeenNonConstWriteIndex = false;
+
+ if (READ != term.GetKind() && WRITE != term[0].GetKind())
+ {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE", term);
+ }
+
+ ASTNode output;
+ if (CheckSimplifyMap(term, output, false))
+ {
+ return output;
+ }
+
+ ASTVec writeIndices, writeValues;
+ unsigned int width = term.GetValueWidth();
+ ASTNode write = term[0];
+ unsigned indexwidth = write.GetIndexWidth();
+ ASTNode readIndex = SimplifyTerm(term[1]);
+
+ do
+ {
+ ASTNode writeIndex = SimplifyTerm(write[1]);
+ ASTNode writeVal = SimplifyTerm(write[2]);
+
+ //compare the readIndex and the current writeIndex and see if they
+ //simplify to TRUE or FALSE or UNDETERMINABLE at this stage
+ ASTNode compare_readwrite_indices = SimplifyFormula(CreateSimplifiedEQ(writeIndex, readIndex), false);
+
+ //if readIndex and writeIndex are equal
+ if (ASTTrue == compare_readwrite_indices && !SeenNonConstWriteIndex)
+ {
+ UpdateSimplifyMap(term, writeVal, false);
+ return writeVal;
+ }
+
+ if (!(ASTTrue == compare_readwrite_indices || ASTFalse == compare_readwrite_indices))
+ {
+ SeenNonConstWriteIndex = true;
+ }
+
+ //if (readIndex=writeIndex <=> FALSE)
+ if (ASTFalse == compare_readwrite_indices || (WriteIndicesSeenSoFar.find(writeIndex) != WriteIndicesSeenSoFar.end()))
+ {
+ //drop the current level write
+ //do nothing
+ }
+ else
+ {
+ writeIndices.push_back(writeIndex);
+ writeValues.push_back(writeVal);
+ }
+
+ //record the write indices seen so far
+ //if(BVCONST == writeIndex.GetKind()) {
+ WriteIndicesSeenSoFar.insert(writeIndex);
+ //}
+
+ //Setup the write for the new iteration, one level inner write
+ write = write[0];
+ } while (SYMBOL != write.GetKind());
+
+ ASTVec::reverse_iterator it_index = writeIndices.rbegin();
+ ASTVec::reverse_iterator itend_index = writeIndices.rend();
+ ASTVec::reverse_iterator it_values = writeValues.rbegin();
+ ASTVec::reverse_iterator itend_values = writeValues.rend();
+
+ //"write" must be a symbol at the control point before the
+ //begining of the "for loop"
+
+ for (; it_index != itend_index; it_index++, it_values++)
+ {
+ write = CreateTerm(WRITE, width, write, *it_index, *it_values);
+ write.SetIndexWidth(indexwidth);
+ }
+
+ output = CreateTerm(READ, width, write, readIndex);
+ UpdateSimplifyMap(term, output, false);
+ return output;
+} //end of SimplifyWrites_In_Place()
+
+//accepts a read over a write and returns a term without the write
+//READ(WRITE(A i val) j) <==> ITE(i=j,val,READ(A,j)). We use a memo
+//table for this function called RemoveWritesMemoMap
+ASTNode BeevMgr::RemoveWrites(const ASTNode& input)
+{
+ //unsigned int width = input.GetValueWidth();
+ if (READ != input.GetKind() || WRITE != input[0].GetKind())
+ {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE", input);
+ }
+
+ ASTNodeMap::iterator it;
+ ASTNode output = input;
+ if (CheckSimplifyMap(input, output, false))
+ {
+ return output;
+ }
+
+ if (!start_abstracting && Begin_RemoveWrites)
+ {
+ output = ReadOverWrite_To_ITE(input);
+ }
+
+ if (start_abstracting)
+ {
+ ASTNode newVar;
+ if (!CheckSimplifyMap(input, newVar, false))
+ {
+ newVar = NewVar(input.GetValueWidth());
+ ReadOverWrite_NewName_Map[input] = newVar;
+ NewName_ReadOverWrite_Map[newVar] = input;
+
+ UpdateSimplifyMap(input, newVar, false);
+ ASTNodeStats("New Var Name which replace Read_Over_Write: ", newVar);
+ }
+ output = newVar;
+ } //end of start_abstracting if condition
+
+ //memoize
+ UpdateSimplifyMap(input, output, false);
+ return output;
+} //end of RemoveWrites()
+
+ASTNode BeevMgr::ReadOverWrite_To_ITE(const ASTNode& term)
+{
+ unsigned int width = term.GetValueWidth();
+ ASTNode input = term;
+ if (READ != term.GetKind() || WRITE != term[0].GetKind())
+ {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE", term);
+ }
+
+ ASTNodeMap::iterator it;
+ ASTNode output;
+ // if(CheckSimplifyMap(term,output,false)) {
+ // return output;
+ // }
+
+ ASTNode partialITE = term;
+ ASTNode writeA = ASTTrue;
+ ASTNode oldRead = term;
+ //iteratively expand read-over-write
+ do
+ {
+ ASTNode write = input[0];
+ ASTNode readIndex = SimplifyTerm(input[1]);
+ //DO NOT CALL SimplifyTerm() on write[0]. You will go into an
+ //infinite loop
+ writeA = write[0];
+ ASTNode writeIndex = SimplifyTerm(write[1]);
+ ASTNode writeVal = SimplifyTerm(write[2]);
+
+ ASTNode cond = SimplifyFormula(CreateSimplifiedEQ(writeIndex, readIndex), false);
+ ASTNode newRead = CreateTerm(READ, width, writeA, readIndex);
+ ASTNode newRead_memoized = newRead;
+ if (CheckSimplifyMap(newRead, newRead_memoized, false))
+ {
+ newRead = newRead_memoized;
+ }
+
+ if (ASTTrue == cond && (term == partialITE))
+ {
+ //found the write-value in the first iteration itself. return
+ //it
+ output = writeVal;
+ UpdateSimplifyMap(term, output, false);
+ return output;
+ }
+
+ if (READ == partialITE.GetKind() && WRITE == partialITE[0].GetKind())
+ {
+ //first iteration or (previous cond==ASTFALSE and partialITE is a "READ over WRITE")
+ partialITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
+ }
+ else if (ITE == partialITE.GetKind())
+ {
+ //ITE(i1 = j, v1, R(A,j))
+ ASTNode ElseITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
+ //R(W(A,i1,v1),j) <==> ITE(i1 = j, v1, R(A,j))
+ UpdateSimplifyMap(oldRead, ElseITE, false);
+ //ITE(i2 = j, v2, R(W(A,i1,v1),j)) <==> ITE(i2 = j, v2, ITE(i1 = j, v1, R(A,j)))
+ partialITE = SimplifyTerm(partialITE);
+ }
+ else
+ {
+ FatalError("RemoveWrites: Control should not reach here\n");
+ }
+
+ if (ASTTrue == cond)
+ {
+ //no more iterations required
+ output = partialITE;
+ UpdateSimplifyMap(term, output, false);
+ return output;
+ }
+
+ input = newRead;
+ oldRead = newRead;
+ } while (READ == input.GetKind() && WRITE == input[0].GetKind());
+
+ output = partialITE;
+
+ //memoize
+ //UpdateSimplifyMap(term,output,false);
+ return output;
+} //ReadOverWrite_To_ITE()
+
+//compute the multiplicative inverse of the input
+ASTNode BeevMgr::MultiplicativeInverse(const ASTNode& d)
+{
+ ASTNode c = d;
+ if (BVCONST != c.GetKind())
+ {
+ FatalError("Input must be a constant", c);
+ }
+
+ if (!BVConstIsOdd(c))
+ {
+ FatalError("MultiplicativeInverse: Input must be odd: ", c);
+ }
+
+ //cerr << "input to multinverse function is: " << d << endl;
+ ASTNode inverse;
+ if (CheckMultInverseMap(d, inverse))
+ {
+ //cerr << "found the inverse of: " << d << "and it is: " << inverse << endl;
+ return inverse;
+ }
+
+ inverse = c;
+ unsigned inputwidth = c.GetValueWidth();
+
+#ifdef NATIVE_C_ARITH
+ ASTNode one = CreateOneConst(inputwidth);
+ while(c != one)
+ {
+ //c = c*c
+ c = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,c,c));
+ //inverse = invsere*c
+ inverse = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,inverse,c));
+ }
+#else
+ //Compute the multiplicative inverse of c using the extended
+ //euclidian algorithm
+ //
+ //create a '0' which is 1 bit long
+ ASTNode onebit_zero = CreateZeroConst(1);
+ //zero pad t0, i.e. 0 @ t0
+ c = BVConstEvaluator(CreateTerm(BVCONCAT, inputwidth + 1, onebit_zero, c));
+
+ //construct 2^(inputwidth), i.e. a bitvector of length
+ //'inputwidth+1', which is max(inputwidth)+1
+ //
+ //all 1's
+ ASTNode max = CreateMaxConst(inputwidth);
+ //zero pad max
+ max = BVConstEvaluator(CreateTerm(BVCONCAT, inputwidth + 1, onebit_zero, max));
+ //Create a '1' which has leading zeros of length 'inputwidth'
+ ASTNode inputwidthplusone_one = CreateOneConst(inputwidth + 1);
+ //add 1 to max
+ max = CreateTerm(BVPLUS, inputwidth + 1, max, inputwidthplusone_one);
+ max = BVConstEvaluator(max);
+
+ ASTNode zero = CreateZeroConst(inputwidth + 1);
+ ASTNode max_bvgt_0 = CreateNode(BVGT, max, zero);
+ ASTNode quotient, remainder;
+ ASTNode x, x1, x2;
+
+ //x1 initialized to zero
+ x1 = zero;
+ //x2 initialized to one
+ x2 = CreateOneConst(inputwidth + 1);
+ while (ASTTrue == BVConstEvaluator(max_bvgt_0))
+ {
+ //quotient = (c divided by max)
+ quotient = BVConstEvaluator(CreateTerm(BVDIV, inputwidth + 1, c, max));
+
+ //remainder of (c divided by max)
+ remainder = BVConstEvaluator(CreateTerm(BVMOD, inputwidth + 1, c, max));
+
+ //x = x2 - q*x1
+ x = CreateTerm(BVSUB, inputwidth + 1, x2, CreateTerm(BVMULT, inputwidth + 1, quotient, x1));
+ x = BVConstEvaluator(x);
+
+ //fix the inputs to the extended euclidian algo
+ c = max;
+ max = remainder;
+ max_bvgt_0 = CreateNode(BVGT, max, zero);
+
+ x2 = x1;
+ x1 = x;
+ }
+
+ ASTNode hi = CreateBVConst(32, inputwidth - 1);
+ ASTNode low = CreateZeroConst(32);
+ inverse = CreateTerm(BVEXTRACT, inputwidth, x2, hi, low);
+ inverse = BVConstEvaluator(inverse);
+#endif
+
+ UpdateMultInverseMap(d, inverse);
+ //cerr << "output of multinverse function is: " << inverse << endl;
+ return inverse;
+} //end of MultiplicativeInverse()
+
+//returns true if the input is odd
+bool BeevMgr::BVConstIsOdd(const ASTNode& c)
+{
+ if (BVCONST != c.GetKind())
+ {
+ FatalError("Input must be a constant", c);
+ }
+
+ ASTNode zero = CreateZeroConst(1);
+ ASTNode hi = CreateZeroConst(32);
+ ASTNode low = hi;
+ ASTNode lowestbit = CreateTerm(BVEXTRACT, 1, c, hi, low);
+ lowestbit = BVConstEvaluator(lowestbit);
+
+ if (lowestbit == zero)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+} //end of BVConstIsOdd()
+
+//The big substitution function
+ASTNode BeevMgr::CreateSubstitutionMap(const ASTNode& a)
+{
+ if (!optimize)
+ return a;
+
+ ASTNode output = a;
+ //if the variable has been solved for, then simply return it
+ if (CheckSolverMap(a, output))
+ return output;
+
+ //traverse a and populate the SubstitutionMap
+ Kind k = a.GetKind();
+ if (SYMBOL == k && BOOLEAN_TYPE == a.GetType())
+ {
+ bool updated = UpdateSubstitutionMap(a, ASTTrue);
+ output = updated ? ASTTrue : a;
+ return output;
+ }
+ if (NOT == k && SYMBOL == a[0].GetKind())
+ {
+ bool updated = UpdateSubstitutionMap(a[0], ASTFalse);
+ output = updated ? ASTTrue : a;
+ return output;
+ }
+
+ if (IFF == k)
+ {
+ ASTVec c = a.GetChildren();
+ SortByArith(c);
+ if (SYMBOL != c[0].GetKind() || VarSeenInTerm(c[0], SimplifyFormula_NoRemoveWrites(c[1], false)))
+ {
+ return a;
+ }
+ bool updated = UpdateSubstitutionMap(c[0], SimplifyFormula(c[1], false));
+ output = updated ? ASTTrue : a;
+ return output;
+ }
+
+ if (EQ == k)
+ {
+ //fill the arrayname readindices vector if e0 is a
+ //READ(Arr,index) and index is a BVCONST
+ ASTVec c = a.GetChildren();
+ SortByArith(c);
+ FillUp_ArrReadIndex_Vec(c[0], c[1]);
+
+ if (SYMBOL == c[0].GetKind() && VarSeenInTerm(c[0], SimplifyTermAux(c[1])))
+ {
+ return a;
+ }
+
+ if (1 == TermOrder(c[0], c[1]) && READ == c[0].GetKind() && VarSeenInTerm(c[0][0], SimplifyTermAux(c[1])))
+ {
+ return a;
+ }
+ bool updated = UpdateSubstitutionMap(c[0], SimplifyTermAux(c[1]));
+ output = updated ? ASTTrue : a;
+ return output;
+ }
+
+ if (AND == k)
+ {
+ ASTVec o;
+ ASTVec c = a.GetChildren();
+ for (ASTVec::iterator it = c.begin(), itend = c.end(); it != itend; it++)
+ {
+ UpdateAlwaysTrueFormMap(*it);
+ ASTNode aaa = CreateSubstitutionMap(*it);
+
+ if (ASTTrue != aaa)
+ {
+ if (ASTFalse == aaa)
+ return ASTFalse;
+ else
+ o.push_back(aaa);
+ }
+ }
+ if (o.size() == 0)
+ return ASTTrue;
+
+ if (o.size() == 1)
+ return o[0];
+
+ return CreateNode(AND, o);
+ }
+
+ //printf("I gave up on kind: %d node: %d\n", k, a.GetNodeNum());
+ return output;
+} //end of CreateSubstitutionMap()
+
+
+bool BeevMgr::VarSeenInTerm(const ASTNode& var, const ASTNode& term)
+{
+ if (READ == term.GetKind() && WRITE == term[0].GetKind() && !Begin_RemoveWrites)
+ {
+ return false;
+ }
+
+ if (READ == term.GetKind() && WRITE == term[0].GetKind() && Begin_RemoveWrites)
+ {
+ return true;
+ }
+
+ ASTNodeMap::iterator it;
+ if ((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end())
+ {
+ if (it->second == var)
+ {
+ return false;
+ }
+ }
+
+ if (var == term)
+ {
+ return true;
+ }
+
+ for (ASTVec::const_iterator it = term.begin(), itend = term.end(); it != itend; it++)
+ {
+ if (VarSeenInTerm(var, *it))
+ {
+ return true;
+ }
+ else
+ {
+ TermsAlreadySeenMap[*it] = var;
+ }
+ }
+
+ TermsAlreadySeenMap[term] = var;
+ return false;
+}
+
+// in ext/hash_map, and tr/unordered_map, there is no provision to shrink down
+// the number of buckets in a hash map. If the hash_map has previously held a
+// lot of data, then it will have a lot of buckets. Slowing down iterators and
+// clears() in particular.
+void BeevMgr::ResetSimplifyMaps()
+{
+ delete SimplifyMap;
+ SimplifyMap = new ASTNodeMap(INITIAL_SIMPLIFY_MAP_SIZE);
+
+ delete SimplifyNegMap;
+ SimplifyNegMap = new ASTNodeMap(INITIAL_SIMPLIFY_MAP_SIZE);
+}
+
+}
+;//end of namespace