diff options
Diffstat (limited to 'stp')
42 files changed, 0 insertions, 20687 deletions
diff --git a/stp/AST/AST.cpp b/stp/AST/AST.cpp deleted file mode 100644 index 63319de9..00000000 --- a/stp/AST/AST.cpp +++ /dev/null @@ -1,1579 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -#include "AST.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; - - //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::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 *ASTNode::GetName() const { - if (GetKind() != SYMBOL) - FatalError("GetName: Called GetName on a non-symbol: ", *this); - return ((ASTSymbol *) _int_node_ptr)->GetName(); - } - - // Print in lisp format - ostream &ASTNode::LispPrint(ostream &os, int indentation) const { - // Clear the PrintMap - BeevMgr& bm = GetBeevMgr(); - bm.AlreadyPrintedSet.clear(); - return LispPrint_indent(os, indentation); - } - - // 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: - // - //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 - // - //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; - } - - //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 SBVMOD: - 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: - 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 == 0 || width > (sizeof(unsigned long long int)<<3)) - FatalError("CreateBVConst: trying to create a bvconst of width: ", ASTUndefined, width); - - CBV bv = CONSTANTBV::BitVector_Create(width, true); - - // Copy bvconst in using at most MaxChunkSize chunks, starting with the - // least significant bits. - const uint32_t MaxChunkSize = 32; - for (unsigned offset = 0; offset != width;) { - uint32_t numbits = std::min(MaxChunkSize, width - offset); - uint32_t mask = ~0 >> (32 - numbits); - CONSTANTBV::BitVector_Chunk_Store(bv, numbits, offset, - (bvconst >> offset) & mask); - offset += numbits; - } - - return CreateBVConst(bv, 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 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; - } - - // 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. - 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() && - BITVECTOR_TYPE != n[1].GetType() && - BITVECTOR_TYPE != 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::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; - default: - for(ASTVec::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++) { - 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++) { - 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); - } - - 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(); - } -} // end namespace - diff --git a/stp/AST/AST.h b/stp/AST/AST.h deleted file mode 100644 index 3052107f..00000000 --- a/stp/AST/AST.h +++ /dev/null @@ -1,1806 +0,0 @@ -// -*- c++ -*- -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ - -#ifndef AST_H -#define AST_H -#include <vector> -#ifdef EXT_HASH_MAP -#include <ext/hash_set> -#include <ext/hash_map> -#else -#include <hash_set> -#include <hash_map> -#endif -#include <iostream> -#include <sstream> -#include <string> -#include <map> -#include <set> -#include "ASTUtil.h" -#include "ASTKind.h" -#include "../sat/Solver.h" -#include "../sat/SolverTypes.h" -#include <cstdlib> -#include <stdint.h> -#ifndef NATIVE_C_ARITH -#include "../constantbv/constantbv.h" -#endif -/***************************************************************************** - * LIST OF CLASSES DECLARED IN THIS FILE: - * - * class BeevMgr; - * class ASTNode; - * class ASTInternal; - * class ASTInterior; - * class ASTSymbol; - * class ASTBVConst; - *****************************************************************************/ -namespace BEEV { - using namespace std; - using namespace MINISAT; -#ifdef EXT_HASH_MAP - 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 vector<ASTNode>; - //Print the arguments in lisp format. - friend ostream &LispPrintVec(ostream &os, - const ASTVec &v, int indentation = 0); - - private: - // FIXME: make this into a reference? - ASTInternal * _int_node_ptr; // The real data. - - // Usual constructor. - ASTNode(ASTInternal *in); - - //Check if it points to a null node - bool IsNull () const { return _int_node_ptr == NULL; } - - //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); - } - - /* 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: - // This is for sorting by expression number (used in Boolean - //optimization) - friend bool exprless(const ASTNode n1, const ASTNode n2) { - Kind k1 = n1.GetKind(); - Kind k2 = n2.GetKind(); - - if(BVCONST == k1 && BVCONST != k2){ - return true; - } - if(BVCONST != k1 && BVCONST == k2){ - return false; - } - - if(SYMBOL == k1 && SYMBOL != k2) { - return true; - } - - if(SYMBOL != k1 && SYMBOL == k2) { - return false; - } - - return (n1.GetNodeNum() < n2.GetNodeNum()); - }//end of exprless - - // 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; - - 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 *GetName() const; - - //Get the BVCONST value -#ifndef NATIVE_C_ARITH - CBV GetBVConst() const; -#else - 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. - size_t Hash() const{ - return (size_t) _int_node_ptr; - //return GetNodeNum(); - } - - // 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); - bool exprless(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; - - 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; } -#else - 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 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. - virtual void nodeprint(ostream& os) { 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. - virtual void nodeprint(ostream& os) { - 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{ - hash<char*> h; - 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 *GetName() const{return _name;} - - // Print function for symbol -- return name */ - virtual void nodeprint(ostream& os) { 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 - virtual void nodeprint(ostream& os) { - unsigned char *res; - const char *prefix; - - if (_value_width%4 == 0) { - res = CONSTANTBV::BitVector_to_Hex(_bvconst); - prefix = "0hex"; - } else { - res = CONSTANTBV::BitVector_to_Bin(_bvconst); - 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 DEPRICATED - //Do not use in the future - 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) *((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) { - 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(""); - } - 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) { } - - 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. -#ifndef SMTLIB - inline ASTNode::ASTNode(ASTInternal *in) : _int_node_ptr(in) { - if (in) in->IncRef(); - } -#else - 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. - -#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; - } -#else - 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(); - } - } -#else - // 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. -#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; -#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; -#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); - - 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 ASTVec * 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(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); - 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 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::SolverStats& stats); - - //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. - 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); - 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)), - SimplifyMap(INITIAL_SIMPLIFY_MAP_SIZE), - SimplifyNegMap(INITIAL_SIMPLIFY_MAP_SIZE), - 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; - }; - - //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 -#endif diff --git a/stp/AST/ASTKind.cpp b/stp/AST/ASTKind.cpp deleted file mode 100644 index 9a2392c9..00000000 --- a/stp/AST/ASTKind.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Generated automatically by genkinds.h from ASTKind.kinds Sun Apr 4 19:39:09 2010. -// Do not edit -namespace BEEV { -const char * _kind_names[] = { - "UNDEFINED", - "SYMBOL", - "BVCONST", - "BVNEG", - "BVCONCAT", - "BVOR", - "BVAND", - "BVXOR", - "BVNAND", - "BVNOR", - "BVXNOR", - "BVEXTRACT", - "BVLEFTSHIFT", - "BVRIGHTSHIFT", - "BVSRSHIFT", - "BVVARSHIFT", - "BVPLUS", - "BVSUB", - "BVUMINUS", - "BVMULTINVERSE", - "BVMULT", - "BVDIV", - "BVMOD", - "SBVDIV", - "SBVMOD", - "BVSX", - "BOOLVEC", - "ITE", - "BVGETBIT", - "BVLT", - "BVLE", - "BVGT", - "BVGE", - "BVSLT", - "BVSLE", - "BVSGT", - "BVSGE", - "EQ", - "NEQ", - "FALSE", - "TRUE", - "NOT", - "AND", - "OR", - "NAND", - "NOR", - "XOR", - "IFF", - "IMPLIES", - "READ", - "WRITE", - "ARRAY", - "BITVECTOR", - "BOOLEAN", -}; - -unsigned char _kind_categories[] = { - 0, - 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 3, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 1, - 1, - 0, - 0, - 0, -}; - -} // end namespace diff --git a/stp/AST/ASTKind.h b/stp/AST/ASTKind.h deleted file mode 100644 index 2480b6e6..00000000 --- a/stp/AST/ASTKind.h +++ /dev/null @@ -1,79 +0,0 @@ -// -*- c++ -*- -#ifndef TESTKINDS_H -#define TESTKINDS_H -// Generated automatically by genkinds.pl from ASTKind.kinds Sun Apr 4 19:39:09 2010. -// Do not edit -namespace BEEV { - typedef enum { - UNDEFINED, - SYMBOL, - BVCONST, - BVNEG, - BVCONCAT, - BVOR, - BVAND, - BVXOR, - BVNAND, - BVNOR, - BVXNOR, - BVEXTRACT, - BVLEFTSHIFT, - BVRIGHTSHIFT, - BVSRSHIFT, - BVVARSHIFT, - BVPLUS, - BVSUB, - BVUMINUS, - BVMULTINVERSE, - BVMULT, - BVDIV, - BVMOD, - SBVDIV, - SBVMOD, - BVSX, - BOOLVEC, - ITE, - BVGETBIT, - BVLT, - BVLE, - BVGT, - BVGE, - BVSLT, - BVSLE, - BVSGT, - BVSGE, - EQ, - NEQ, - FALSE, - TRUE, - NOT, - AND, - OR, - NAND, - NOR, - XOR, - IFF, - IMPLIES, - READ, - WRITE, - ARRAY, - BITVECTOR, - BOOLEAN -} Kind; - -extern unsigned char _kind_categories[]; - -inline bool is_Term_kind(Kind k) { return (_kind_categories[k] & 1); } - -inline bool is_Form_kind(Kind k) { return (_kind_categories[k] & 2); } - -extern const char *_kind_names[]; - -/** Prints symbolic name of kind */ -inline ostream& operator<<(ostream &os, const Kind &kind) { os << _kind_names[kind]; return os; } - - -} // end namespace - - -#endif diff --git a/stp/AST/ASTKind.kinds b/stp/AST/ASTKind.kinds deleted file mode 100644 index 03112eb8..00000000 --- a/stp/AST/ASTKind.kinds +++ /dev/null @@ -1,71 +0,0 @@ -#Please refer LICENSE FILE in the home directory for licensing information -# name minkids maxkids cat1 cat2 ... -Categories: Term Form - -# Leaf nodes. -UNDEFINED 0 0 -SYMBOL 0 0 Term Form - -# These always produce terms -BVCONST 0 0 Term -BVNEG 1 1 Term -BVCONCAT 2 - Term -BVOR 1 - Term -BVAND 1 - Term -BVXOR 1 - Term -BVNAND 1 - Term -BVNOR 1 - Term -BVXNOR 1 - Term -BVEXTRACT 3 3 Term -BVLEFTSHIFT 3 3 Term -BVRIGHTSHIFT 3 3 Term -BVSRSHIFT 3 3 Term -BVVARSHIFT 3 3 Term -BVPLUS 1 - Term -BVSUB 2 2 Term -BVUMINUS 1 1 Term -BVMULTINVERSE 1 1 Term -BVMULT 1 - Term -BVDIV 2 2 Term -BVMOD 2 2 Term -SBVDIV 2 2 Term -SBVMOD 2 2 Term -BVSX 1 1 Term -BOOLVEC 0 - Term - -# Formula OR term, depending on context -ITE 3 3 Term Form - -# These produce formulas. -BVGETBIT 2 2 Form -BVLT 2 2 Form -BVLE 2 2 Form -BVGT 2 2 Form -BVGE 2 2 Form -BVSLT 2 2 Form -BVSLE 2 2 Form -BVSGT 2 2 Form -BVSGE 2 2 Form -EQ 2 2 Form -NEQ 2 2 Form -FALSE 0 0 Form -TRUE 0 0 Form -NOT 1 1 Form -AND 1 - Form -OR 1 - Form -NAND 1 - Form -NOR 1 - Form -XOR 1 - Form -IFF 1 - Form -IMPLIES 2 2 Form - -# array operations -READ 2 2 Term -WRITE 3 3 Term - -#Types: These kinds are used only in the API. Once processed inside -#the API, they are never used again in the system -ARRAY 0 0 -BITVECTOR 0 0 -BOOLEAN 0 0 - diff --git a/stp/AST/ASTUtil.cpp b/stp/AST/ASTUtil.cpp deleted file mode 100644 index ecb54a4a..00000000 --- a/stp/AST/ASTUtil.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -#include "ASTUtil.h" -#include <ostream> - -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) { - if(!stats) - return; - static function_counters s; - - if(!strcmp(functionname,"print_func_stats")) { - cout << endl; - for(hash_map<const char*,int,hash<const char*>,eqstr>::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 diff --git a/stp/AST/ASTUtil.h b/stp/AST/ASTUtil.h deleted file mode 100644 index c90ee0ce..00000000 --- a/stp/AST/ASTUtil.h +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -#ifndef ASTUTIL_H -#define ASTUTIL_H - -#include <cstring> -#include <iostream> -#include <vector> -#ifdef EXT_HASH_MAP -#include <ext/hash_set> -#include <ext/hash_map> -#else -#include <hash_set> -#include <hash_map> -#endif - -using namespace std; -namespace BEEV { -#ifdef EXT_HASH_MAP - using namespace __gnu_cxx; -#endif - //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 - extern bool stats; - //print DAG nodes - extern bool print_nodes; - //tentative global var to allow for variable activity optimization - //in the SAT solver. deprecated. - extern bool variable_activity_optimize; - //run STP in optimized mode - extern bool optimize; - //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. - extern bool arrayread_refinement; - //switch to control write refinements - extern bool arraywrite_refinement; - //check the counterexample against the original input to STP - extern bool check_counterexample; - //construct the counterexample in terms of original variable based - //on the counterexample returned by SAT solver - extern bool construct_counterexample; - extern bool print_counterexample; - //if this option is true then print the way dawson wants using a - //different printer. do not use this printer. - extern bool print_arrayval_declaredorder; - //flag to decide whether to print "valid/invalid" or not - extern bool print_output; - //do linear search in the array values of an input array. experimental - extern bool linear_search; - //print the variable order chosen by the sat solver while it is - //solving. - extern bool print_sat_varorder; - //turn on word level bitvector solver - extern bool wordlevel_solve; - //XOR flattening optimizations. - extern bool xor_flatten; - //this flag indicates that the BVSolver() succeeded - extern bool toplevel_solved; - //the smtlib parser has been turned on - extern bool smtlib_parser_enable; - //print the input back - extern bool print_STPinput_back; - - extern void (*vc_error_hdlr)(const char* err_msg); - /*Spacer class is basically just an int, but the new class allows - overloading of << with a special definition that prints the int as - that many spaces. */ - class Spacer { - public: - int _spaces; - Spacer(int spaces) { _spaces = spaces; } - friend ostream& operator<<(ostream& os, const Spacer &ind); - }; - - inline Spacer spaces(int width) { - Spacer sp(width); - return sp; - } - - struct eqstr { - bool operator()(const char* s1, const char* s2) const { - return strcmp(s1, s2) == 0; - } - }; - - typedef hash_map<const char*,int, - hash<const char *>,eqstr> function_counters; - void CountersAndStats(const char * functionname); - - //global function which accepts an integer and looks up the - //corresponding ASTNode and prints a char* of that ASTNode - void Convert_MINISATVar_To_ASTNode_Print(int minisat_var, - int decision, int polarity=0); -} // end namespace. -#endif diff --git a/stp/AST/BitBlast.cpp b/stp/AST/BitBlast.cpp deleted file mode 100644 index de78ec74..00000000 --- a/stp/AST/BitBlast.cpp +++ /dev/null @@ -1,812 +0,0 @@ -/******************************************************************** - * AUTHORS: David L. Dill, Vijay Ganesh - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -// BitBlast -- convert bitvector terms and formulas to boolean -// formulas. A term is something that can represent a multi-bit -// bitvector, such as BVPLUS or BVXOR (or a BV variable or constant). -// A formula (form) represents a boolean value, such as EQ or BVLE. -// Bit blasting a term representing an n-bit bitvector with BBTerm -// yields a vector of n boolean formulas (returning ASTVec). -// Bit blasting a formula returns a single boolean formula (type ASTNode). - -// A bitblasted term is a vector of ASTNodes for formulas. -// The 0th element of the vector corresponds to bit 0 -- the low-order bit. - -#include "AST.h" -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. -// FIXME: Check resource limits and generate an exception when exceeded. -// FIXME: THis does a lot of unnecessary copying of vectors. -// Had to be careful not to modify memoized vectors! -// FIXME: Might be some redundant variables. - -// accepts a term, and returns a vector of bitblasted bits(ASTVec) - -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; - - 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 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& 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++, bb_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 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 - const ASTNode& bbkids = BBTerm(term[0]); - unsigned int high = GetUnsignedConst(term[1]); - unsigned int low = GetUnsignedConst(term[2]); - - 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)); - 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; - 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); - 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; - } -#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); -#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); - -} - -// bit blast a formula (boolean term). Result is one bit wide, -// so it returns a single ASTNode. -// FIXME: Add IsNegated flag. -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: - 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: { - 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: { - // Common code for binary operations - // FIXME: This ought to be in a semantic analysis phase. - const ASTNode left = BBTerm(form[0]); - const ASTNode right = BBTerm(form[1]); - if (left.Degree() != right.Degree()) { - cerr << "BBForm: Size mismatch" << endl << form[0] << endl << form[1] << endl; - FatalError("",ASTUndefined); - } - result = BBEQ(left.GetChildren(), right.GetChildren()); - 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; - -} - -// Stores result - x in result, destructively -void BeevMgr::BBSub(ASTVec& result, const ASTVec& y) -{ - 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; -} - -// Increment bit-blasted vector and return result. -ASTVec BeevMgr::BBInc(ASTVec& x) -{ - 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) -{ - // 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; -} - -// Compute unary minus -ASTVec BeevMgr::BBUminus(const ASTVec& x) -{ - 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; -} - -// This implements a variant of binary long division. -// q and r are "out" parameters. rwidth puts a bound on the -// 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); - } -} - -// 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; -} -// 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; -} - - -// 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 -// to this by swapping args or complementing the result bit. -// FIXME: If this were done MSB first, it would enable a fast exit sometimes -// when the MSB is constant, deciding the result without looking at the rest -// 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; -} - -// Left shift by 1 within fixed field inserting zeros at LSB. -// Writes result into first argument. -// 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); -} - -// 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. -} - - -// 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; -} - -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); -} -} // BEEV namespace diff --git a/stp/AST/Makefile b/stp/AST/Makefile deleted file mode 100644 index c3b54672..00000000 --- a/stp/AST/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -#===-- stp/AST/Makefile ------------------------------------*- Makefile -*--===# -# -# The KLEE Symbolic Virtual Machine -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -LEVEL=../.. - -LIBRARYNAME=stp_AST -DONT_BUILD_RELINKED=1 -BUILD_ARCHIVE=1 - -include $(LEVEL)/Makefile.common - -# HACK: Force -Wno-deprecated for ext container use. -CXX.Flags += -Wno-deprecated diff --git a/stp/AST/STLport_config.h b/stp/AST/STLport_config.h deleted file mode 100644 index 9b7bc14f..00000000 --- a/stp/AST/STLport_config.h +++ /dev/null @@ -1,20 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -// STLport debug checking, if we use STLport threads flag is to get -// rid of link errors, since iostreams compiles with threads. alloc -// and uninitialized are extra checks Later on, if used with Purify or -// Valgrind, may want to set flags to prevent reporting of false -// leaks. For some reason, _STLP_THREADS works on the command line -// but not here (?) -#define _STLP_THREADS -#define _STLP_DEBUG 1 -#define _STLP_DEBUG_LEVEL _STLP_STANDARD_DBG_LEVEL -#define _STLP_DEBUG_ALLOC 1 -#define _STLP_DEBUG_UNINITIALIZED 1 diff --git a/stp/AST/SimpBool.cpp b/stp/AST/SimpBool.cpp deleted file mode 100644 index 67f9825d..00000000 --- a/stp/AST/SimpBool.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: April, 2006 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ - -// -*- c++ -*- - -// Simplifying create methods for Boolean operations. -// These are only very simple local simplifications. - -// This is somewhat redundant with Vijay's simplifier code. They -// need to be merged. -// FIXME: control with optimize flag. - -static bool _trace_simpbool = 0; -static bool _disable_simpbool = 0; - -#include "AST.h" - -// SMTLIB experimental hack. Try allocating a single stack here for -// 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. IFF is not associative, so this makes - // flattening much easier. - 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); - } - - - 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); - } - - ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, ASTVec &children) { - - if (_trace_simpbool) { - cout << "========" << endl << "CreateSimpAndOr " << (IsAnd ? "AND " : "OR ") ; - lpvec(children); - cout << endl; - } - - ASTVec new_children; - - // sort so that identical nodes occur in sequential runs, followed by - // their negations. - - SortByExprNum(children); - - ASTNode annihilator = (IsAnd ? ASTFalse : ASTTrue); - ASTNode identity = (IsAnd ? ASTTrue : ASTFalse); - - ASTNode retval; - - ASTVec::const_iterator it_end = children.end(); - ASTVec::const_iterator next_it; - for(ASTVec::const_iterator it = 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; - } - - - // Constant children are accumulated in "accumconst". - ASTNode BeevMgr::CreateSimpXor(ASTVec &children) { - - if (_trace_simpbool) { - cout << "========" << endl - << "CreateSimpXor "; - lpvec(children); - cout << endl; - } - - // Change this not to init to children if flattening code is present. - // ASTVec flat_children = children; // empty vector - - ASTVec flat_children; // empty vector - - ASTVec::const_iterator it_end = children.end(); - - if (xor_flatten) { - - bool fflag = 0; // ***Temp debugging - - // Experimental flattening code. - - for(ASTVec::iterator it = children.begin(); it != it_end; it++) { - Kind ck = it->GetKind(); - const ASTVec &gchildren = it->GetChildren(); - if (XOR == ck) { - fflag = 1; - // 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: " << endl; - lpvec(children); - - cout << "--------" << endl; - cout << "Flattening result: " << endl; - lpvec(flat_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; - } - - // 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; - } -} // BEEV namespace diff --git a/stp/AST/ToCNF.cpp b/stp/AST/ToCNF.cpp deleted file mode 100644 index 2a18b3f5..00000000 --- a/stp/AST/ToCNF.cpp +++ /dev/null @@ -1,506 +0,0 @@ -/******************************************************************** - * AUTHORS: David L. Dill, Vijay Ganesh - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -// THEORY: This code translates an arbitrary Boolean DAG, generated by -// the BitBlast.cpp, to an equi-satisfiable CNF formula. There are -// four kinds of variables in the CNF formula: (1) propositional -// variables from the original formula; (2) BVGETBIT formulas from the -// original formula (a precondition is that the BVGETBIT can only be -// applied to bitvector-valued variables, array reads, or -// uninterpreted functions); (3) TRUE; or (4) representative variables -// (see below). Each literal in the CNF formula is one of these or -// its negation. - -// It is convenient (though not perfectly efficient) to be able to add -// TRUE and FALSE constants to clauses, which is not allowed in CNF. -// So, there is a "dummy variable" representing TRUE, which is used in -// its place (so FALSE is represented by the negation of the dummy -// var). The CNF formula has a unit clause containing this dummy -// variable, so that any satisfying assignment must make the dummy var -// TRUE. - -// Every sub-formula of the input formula has a "representative -// literal." A truth assignment satisfies the CNF formula iff the -// restriction of that assignment to the original variables satisfies -// the original formula, AND the rep lits have the same truth values -// as the subformulas they represent in the original formula. In the -// trivial cases, the representative literal is the input variable, or -// dummy true var, or its negation. Representative literals may be -// negated variables -- essentially, only AND formulas are translated, -// and everything else is handled by rewriting or negating formulas. -// The representative for (NOT alpha) is the negation of the -// representative for alpha. - -// The translation is performed by ToCNF_int, which traverses the original -// formula. ToCNF adds clauses that constrain the representative variables -// to be equal to the truth values of the formulas they represent. -// ToCNF always returns a literal whose value must be equivalent to the formula -// it translated. In trivial cases, this literal is a literal from the original -// formula, or the dummy true/false literals. If the formula is of the form -// (not alpha), ToCNF_int negates the literal representing alpha (which may -// itself be a negative literal) and returns it. Otherwise, ToCNF_int assigns -// a new rep var, adds the clauses, and returns the new var. ToCNF_int is -// memoized so that it doesn't assign more than one variable to a subformula, -// and to prevent exponential numbers of redundant visits to shared subformulas. - -// In reality, only AND/OR/NOT formulas are translated directly. Everything -// else (XOR, IFF, IMPLIES) is rewritten on-the-fly into these forms. I -// could have done that in bit-blasting, but I thought that, in the future, -// we might be able to translate these operations differently in different -// contexts to optimize the CNF formula. - -// FIXME: Inspection of the clauses is kind of horrifying. In -// addition to true/false, there are duplicate literals and duplicate -// clauses all over the place. -#include "AST.h" -static bool CNF_trace = false; -namespace BEEV { -/** Statistics class. Total number of variables is best tracked in - ToSAT. Number of clauses is just cll.size() */ - -class CNFstats { -public: - int _num_new_rep_vars; - int _num_clauses; - - // constructor - CNFstats() : _num_new_rep_vars(0), _num_clauses(0) {} - - void printStats() { - if(stats) { - cout << "ToCNF statistics:" << endl; - cout << "Number of new representative variables: " - << _num_new_rep_vars << endl; - cout << "Number of new clauses: " - << _num_clauses << endl; - } - } - -}; - - -/** This class contains private data and function members for the - CNF conversion */ -class CNFMgr { - - friend class BeevMgr; - -public: - - // Needed in the body of BeevMgr::ToCNF. It's not visible outside - // this file, though. - ASTNode dummy_true_var; - - // CNF Pre-pass - ASTNodeMap ToCNFPrePassMemo; - - // CNF Memo Table. - ASTNodeMap CNFMemo; - - -private: - - // Pointer back to BeevMgr with the node tables, etc. - BeevMgr *bm; - - // For ToCNF conversion. This holds a dummy variable representing - // "True". It is added as a unit clause, so that it will be assigned - // to true and propagated immediately by any CNF solver. - - ASTNode dummy_false_var; // not of dummy_true_var - - CNFstats stats; - - // constructor - CNFMgr(BeevMgr *bmgr) - { - bm = bmgr; - - // Dummy variable so TRUE can be a literal. - dummy_true_var = bm->CreateSymbol("*TrueDummy*"); - dummy_false_var = bm->CreateSimpNot(dummy_true_var); - } - - // Returns true iff result has been memoized. - // if it returns true, result is returned in by-ref parameter "result" - // Consider just putitng this in-line. - bool CNFIsMemoized(ASTNode &form, ASTNode &result) - { - ASTNodeMap::iterator it = CNFMemo.find(form); - if (it != CNFMemo.end()) { - result = it->second; //already there. Just return it. - return true; - } - else { - return false; - } - } - - - // Convert a big XOR to a bunch of AND/ORs. Assumes subformulas have - // already been converted. - ASTNode convertXORs(ASTVec children) - { - ASTNode accum = children[0]; - ASTVec::iterator itend = children.end(); - for (ASTVec::iterator it = children.begin()+1; it < itend; it++) { - // a XOR b -> (a | b) & (!a | !b) - - // For each XOR node with k children, creates approximately - // 5*(k-1) nodes. AND + 2 OR + 2 NOT. - - ASTNode or1 = bm->CreateNode(OR, accum, *it); - ASTNode or2 = bm->CreateNode(OR, bm->CreateSimpNot(accum), bm->CreateSimpNot(*it)); - accum = bm->CreateNode(AND, or1, or2); - - } - - return accum; - } - - - // Do preliminary transformations on bitblasted formula to make - // CNF conversion easier. - // Converts XORs to AND/OR form. - ASTNode ToCNFPrePass(const ASTNode &form) - { - - // Check memo table - ASTNodeMap::iterator mem_it = ToCNFPrePassMemo.find(form); - if (mem_it != ToCNFPrePassMemo.end()) { - return mem_it->second; - } - - ASTNode result; - - ASTVec new_children; - ASTVec::const_iterator endit = form.end(); - for (ASTVec::const_iterator it = form.begin(); it != endit; it++) { - ASTNode ch = ToCNFPrePass(*it); - new_children.push_back(ch); - } - - Kind k = form.GetKind(); - - switch (k) { - case FALSE: - case TRUE: - case SYMBOL: - case BVGETBIT: { - result = form; - break; - } - case XOR: { - // convertXORs can only be called once per XOR node. - result = convertXORs(new_children); - - // cout << "convertXORs num args: " << new_children.size() << endl; - // temporary node for node count. - // ASTNode tmp = bm->CreateNode(XOR, new_children ); - // cout << "convertXORs size of [" << form.GetNodeNum() << "] " << bm->NodeSize(form, true) << endl; - // cout << "convertXORs before size: " << bm->NodeSize(tmp, true) << endl; - // cout << "convertXORs after size: " << bm->NodeSize(result, true) << endl; - break; - } - default: { - // Be cautious about using CreateSimpForm -- It makes big xors! - result = bm->CreateNode(k, new_children); - } - } - -// cout << "================" << endl -// << "ToCNFPrePass:" << form << endl -// << "----------------" << endl -// << "ToCNFPrePass Result:" << result << endl; - - return (ToCNFPrePassMemo[form] = result); - - } - - // Memoize and return formula value - ASTNode CNFMemoize(ASTNode& form, ASTNode result) - { - CNFMemo[form] = result; - return result; - } - - - // Create a representative variable for an original formula. - // The convention is that the variable will have the same truth - // value as the expression numbered "num." - ASTNode RepLit(const char *name, int exprnum) - { - // FIXME: can this be done more efficiently with string type? - ostringstream oss; - oss << name << "{" << exprnum << "}"; - ASTNode t = bm->CreateSymbol(oss.str().c_str()); - - // Track how many we're generating. - stats._num_new_rep_vars++; - - //ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0)) - t.SetIndexWidth(0); - t.SetValueWidth(0); - return t; - } - - // Handle the cases where it's necessary to do n children. - // This code translates ANDs, and converts NAND, NOR, OR by negating - // the inputs or outputs of the AND. - ASTNode ToCNF_AndLike(Kind k, BeevMgr::ClauseList& cll, ASTNode form) - { - // Build vectors of positive and negative rep lits for children - ASTVec kidlits(0); - ASTVec negkidlits(0); - ASTVec::const_iterator kids_end = form.end(); - for (ASTVec::const_iterator it = form.begin(); it != kids_end; it++) { - ASTNode kidreplit = ToCNF_int(cll, *it); - kidlits.push_back(kidreplit); - negkidlits.push_back(bm->CreateSimpNot(kidreplit)); - } - - ASTNode replit; - // translate the AND, negating inputs as appropriate. - if (k == OR || k == NOR) { - replit = ToCNF_AND(cll, form.GetNodeNum(), negkidlits, kidlits); - } - else { - replit = ToCNF_AND(cll, form.GetNodeNum(), kidlits, negkidlits); - } - - // Reduce NAND/OR to AND by negating result. - if (k == NAND || k == OR) { - return CNFMemoize(form, bm->CreateSimpNot(replit)); - } - else { - return CNFMemoize(form, replit); - } - } - - ASTNode ToCNF_AND(BeevMgr::ClauseList& cll, int nodenum, ASTVec& kidlits, ASTVec& negkidlits) - { - // Translate an AND, given rep lits for children - // Build clauses for (replit <-> a AND b AND c) - - ASTNode replit = RepLit("cnf", nodenum); - ASTNode notreplit = bm->CreateSimpNot(replit); - - if (CNF_trace) { - cout << "Translating AND" << endl << "-----------------------" << endl - << "Rep lit =" << replit << endl - << "-----------------------"; - } - - // (a AND b AND c -> replit) == (~a OR ~b OR ~c OR replit) - BeevMgr::ClausePtr clp = new ASTVec(negkidlits); - clp->push_back(replit); - - if (CNF_trace) { - LispPrintVec(cout, *clp, 0); - cout << endl << "-----------------------" << endl; - } - - cll.push_back(clp); - - // (replit -> (a AND b AND c)) == - // (~replit OR a) AND (~replit OR b) AND (~replit OR c) - ASTVec::const_iterator kidlits_end = kidlits.end(); - for (ASTVec::iterator it = kidlits.begin(); it != kidlits_end; it++) { - clp = new ASTVec(); - clp->push_back(notreplit); - clp->push_back(*it); - - if (CNF_trace) { - LispPrintVec(cout, *clp, 0); - cout << endl << "-----------------------" << endl; - } - - cll.push_back(clp); - } - - return replit; - } - -public: - - /** Builds clauses globally and returns a literal. - The literal can be a leaf from the expression, or a rep var - made up to represent the subexpression. */ - ASTNode ToCNF_int(BeevMgr::BeevMgr::ClauseList& cll, ASTNode form) { - // FIXME: assert indexwidth= 0, valuewidth = 1 - - // FIXME: rewriting is top-down, which is not efficient. - // It rewrites the top node of the tree, then does the children. - // Either rewrite in a separate pass, or translate children - // before rewriting somehow (might require handling rep lits - // as though they were real lits, which is probably ok). - - // Return memoized value if seen before. - ASTNode result; - Kind k = form.GetKind(); - - if (CNFIsMemoized(form, result)) { - return result; - } - - switch (k) { - // handle the trivial cases here. If none apply, call the - // heavy-duty function. If a constant or literal, just return - // without creating a clause. - case FALSE: { - result = dummy_false_var; - break; - } - case TRUE: { - result = dummy_true_var; - break; - } - case SYMBOL: - case BVGETBIT: { - result = form; - break; - } - - case NOT: { - ASTNode replit = ToCNF_int(cll, form[0]); - result = bm->CreateSimpNot(replit); - break; - } - - // For these, I can't think of anything better than expanding into ANDs/ORs - case ITE: { - // (ite a b c) == (~a OR b) AND (a OR c) - ASTNode l = bm->CreateNode(OR, bm->CreateSimpNot(form[0]), form[1]); - ASTNode r = bm->CreateNode(OR, form[0], form[2]); - ASTNode andor = bm->CreateNode(AND, l, r); - if (CNF_trace) { - cout << "Rewriting " << form << endl - << "to" << andor << endl - << "-------------------" << endl; - } - result = ToCNF_int(cll, andor); - break; - } - case IMPLIES: { - // Just rewrite into (~a OR b) - ASTNode l = bm->CreateSimpNot(form[0]); - ASTNode andor = bm->CreateNode(OR, l, form[1]); - if (CNF_trace) { - cout << "Rewriting " << form << endl - << "to" << andor << endl - << "-------------------" << endl; - } - result = ToCNF_int(cll, andor); - break; - } - case XOR: { - FatalError("ToCNF_int: XORs should have been converted to AND/OR by this point."); - break; - } - - case IFF: { - FatalError("BitBlaster failed to eliminate all IFFs."); - break; - } - - case AND: - case OR: - case NOR: - case NAND: { - result = ToCNF_AndLike(k, cll, form); - break; - } - default: - cerr << "ToCNF: can't handle this kind: " << k << endl; - FatalError(""); - } - - if (CNF_trace) { - cout << "ToCNF_int: Literal " << result << " represents formula " << - form << endl << "---------------" << endl; - } - - return CNFMemoize(form, result); - } //end of ToCNF_int() - - -}; // end of CNFMgr class - - // These are the bodies of functions in the BeevMgr that are part of - // the public interface. - - // Debug printing function. - 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; - LispPrintVec(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; - } - - // Top level conversion function - BeevMgr::ClauseList *BeevMgr::ToCNF(const ASTNode& form) - { - - // FIXME: This is leaked as well. - CNFMgr *cm = new CNFMgr(this); - - // Prepass - ASTNode form1 = cm->ToCNFPrePass(form); - - // cout << "Number of nodes after ToCNFPrePass" << NodeSize(form1, true) << endl; - - // cout << "ToCNF: After ToCNFPrePass" << form1 << endl; - - // FIXME: Assert CNFMemo is empty. - - // The clause list we will be building up. - // FIXME: This is never freed. - ClauseList *cllp = new ClauseList(); - - BeevMgr::ClausePtr dummy_true_unit_clause = new ASTVec(); - dummy_true_unit_clause->push_back(cm->dummy_true_var); - cllp->push_back(dummy_true_unit_clause); - - // This is where the translation happens. - ASTNode toplit = cm->ToCNF_int(*cllp, form1); - - // Add the top literal as a unit clause, since it must - // be true when original formula is satsfied. - BeevMgr::ClausePtr clp = new ASTVec(0); - clp->push_back(toplit); - cllp->push_back(clp); - - cm->stats._num_clauses = cllp->size(); - cm->stats.printStats(); - - RepLitMap = cm->CNFMemo; // Save memo table for debugging (DD 1/13/07). - - cm->CNFMemo.clear(); // Important to do this so nodes get freed. - - delete cm; - - return cllp; - } - -} // end namespace diff --git a/stp/AST/ToSAT.cpp b/stp/AST/ToSAT.cpp deleted file mode 100644 index 3ad21f93..00000000 --- a/stp/AST/ToSAT.cpp +++ /dev/null @@ -1,1386 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- -#include "AST.h" -#include "ASTUtil.h" -#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. - */ - 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) - { - 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 - newS.turnOffSubsumption(); - - // (*i) is an ASTVec-ptr which denotes an ASTclause - for(; i!=iend; i++) { - //Clause for the SATSolver - MINISAT::vec<MINISAT::Lit> satSolverClause; - - //now iterate through the internals of the ASTclause itself - ASTVec::const_iterator j = (*i)->begin(), jend = (*i)->end(); - //j is a disjunct in the ASTclause (*i) - for(;j!=jend;j++) { - - bool negate = (NOT == j->GetKind()) ? true : false; - ASTNode n = negate ? (*j)[0] : *j; - - //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.stats); - return false; - } - - if(!newS.simplifyDB(false)) { - PrintStats(newS.stats); - return false; - } - } - - // if input is UNSAT return false, else return true - if(!newS.simplifyDB(false)) { - PrintStats(newS.stats); - 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.stats); - if (newS.okay()) - return true; - else - return false; - } - - // GLOBAL FUNCTION: Prints statistics from the MINISAT Solver - void BeevMgr::PrintStats(MINISAT::SolverStats& s) { - if(!stats) - return; - double cpu_time = MINISAT::cpuTime(); - MINISAT::int64 mem_used = MINISAT::memUsed(); - printf("restarts : %"I64_fmt"\n", s.starts); - printf("conflicts : %-12"I64_fmt" (%.0f /sec)\n", s.conflicts , s.conflicts /cpu_time); - printf("decisions : %-12"I64_fmt" (%.0f /sec)\n", s.decisions , s.decisions /cpu_time); - printf("propagations : %-12"I64_fmt" (%.0f /sec)\n", s.propagations, s.propagations/cpu_time); - printf("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) printf("Memory used : %.2f MB\n", mem_used / 1048576.0); - printf("CPU time : %g s\n", cpu_time); - fflush(stdout); - } - - // 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 if (newS.model[satvar] == MINISAT::l_False){ - // False - return ASTFalse; - } - else { - return (rand() > 4096) ? ASTTrue : 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); - } - 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; - } - - } - } - - 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 - CounterExampleMap[s] = ASTFalse; - } - } - } - } - } - - //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); - } - 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]; - 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); - } - 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; - } //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! - - 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; - } - } - //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"; - } - } - } - 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::TopLevelSAT( const ASTNode& inputasserts, const ASTNode& query) { - /******start solving**********/ - ASTNode q = CreateNode(AND, inputasserts, CreateNode(NOT,query)); - 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); - //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; - } - - //call SAT and check the result - 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) { - if(!arrayread_refinement) - FatalError("SATBased_ArrayReadRefinement: Control should not reach here"); - - ASTVec FalseAxiomsVec, RemainingAxiomsVec; - RemainingAxiomsVec.push_back(ASTTrue); - FalseAxiomsVec.push_back(ASTTrue); - - //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); - int res2 = CallSAT_ResultCheck(newS,FalseAxioms,orig_input); - 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(); - //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 = CallSAT_ResultCheck(newS,writeAxiom,orig_input); - 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 - - //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"; - // } - - bool sat = toSATandSolve(newS,*cllp); - // Temporary debugging call. - // CheckBBandCNF(newS, BBFormula); - - DeleteClauseList(cllp); - 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 - - - //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(true_iff_valid) { - ValidFlag = true; - if(print_output) { - if(smtlib_parser_enable) - cout << "unsat\n"; - else - cout << "Valid.\n"; - } - } - else { - ValidFlag = false; - if(print_output) { - if(smtlib_parser_enable) - cout << "sat\n"; - else - cout << "Invalid.\n"; - } - } - } -} //end of namespace BEEV diff --git a/stp/AST/Transform.cpp b/stp/AST/Transform.cpp deleted file mode 100644 index 598b831e..00000000 --- a/stp/AST/Transform.cpp +++ /dev/null @@ -1,492 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -#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(!(SBVMOD == 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() || 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; - } - //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 diff --git a/stp/AST/genkinds.pl b/stp/AST/genkinds.pl deleted file mode 100755 index 672481ad..00000000 --- a/stp/AST/genkinds.pl +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/perl -w - -#AUTHORS: Vijay Ganesh, David L. Dill BEGIN DATE: November, 2005 -#LICENSE: Please view LICENSE file in the home dir of this Program -#given a file containing kind names, one per line produces .h and .cpp -#files for the kinds. - -#globals -@kindnames = (); -$minkids = 0; -$maxkids = 0; -@cat_bits = (); -@category_names = (); -%cat_index = (); - -$now = localtime time; - -sub read_kind_defs { - open(KFILE, "< ASTKind.kinds") || die "Cannot open .kinds file: $!\n"; - @kindlines = <KFILE>; - close(KFILE) -} - -# create lists of things indexed by kinds. -sub split_fields { - my $kind_cat_bits; - # matches anything with three whitespace-delimited alphanumeric fields, - # followed by rest of line. Automatically ignores lines beginning with '#' and blank lines. - for (@kindlines) { - if (/Categories:\s+(.*)/) { - @category_names = split(/\s+/, $1); - $i = 0; - for (@category_names) { - $cat_index{$_} = $i++; - # print "cat_index{$_} = $i\n"; - } - } - elsif (/^(\w+)\s+(\w+)\s+(\w+|-)\s+(.*)/) { - push(@kindnames, $1); - push(@minkids, $2); - push(@maxkids, $3); - @kind_cats = split(/\s+/, $4); - # build a bit vector of categories. - $kind_cat_bits = 0; - for (@kind_cats) { - $kind_cat_bits |= (1 << int($cat_index{$_})); - } - push(@cat_bits, $kind_cat_bits); - } - } -} - -sub gen_h_file { - open(HFILE, "> ASTKind.h") || die "Cannot open .h file: $!\n"; - - print HFILE - "// -*- c++ -*-\n", - "#ifndef TESTKINDS_H\n", - "#define TESTKINDS_H\n", - "// Generated automatically by genkinds.pl from ASTKind.kinds $now.\n", - "// Do not edit\n", - "namespace BEEV {\n typedef enum {\n"; - - for (@kindnames) { - print HFILE " $_,\n"; - } - - print HFILE - "} Kind;\n\n", - "extern unsigned char _kind_categories[];\n\n"; - - # For category named "cat", generate functions "bool is_cat_kind(k);" - - - for (@category_names) { - my $catname = $_; - my $kind_cat_bit = (1 << int($cat_index{$catname})); - print HFILE "inline bool is_", $catname, "_kind(Kind k) { return (_kind_categories[k] & $kind_cat_bit); }\n\n" - } - - print HFILE - "extern const char *_kind_names[];\n\n", - "/** Prints symbolic name of kind */\n", - "inline ostream& operator<<(ostream &os, const Kind &kind) { os << _kind_names[kind]; return os; }\n", - "\n\n", - "} // end namespace\n", - "\n\n#endif\n"; - - close(HFILE); -} - -# generate the .cpp file - -sub gen_cpp_file { - open(CPPFILE, "> ASTKind.cpp") || die "Cannot open .h file: $!\n"; - - print CPPFILE - "// Generated automatically by genkinds.h from ASTKind.kinds $now.\n", - "// Do not edit\n", - "namespace BEEV {\n", - "const char * _kind_names[] = {\n"; - for (@kindnames) { - print CPPFILE " \"$_\",\n"; - } - print CPPFILE "};\n\n"; - - # category bits - print CPPFILE - "unsigned char _kind_categories[] = {\n"; - for (@cat_bits) { - print CPPFILE " $_,\n"; - } - print CPPFILE - "};\n", - "\n} // end namespace\n"; - - close(CPPFILE); -} - -&read_kind_defs; -&split_fields; -&gen_h_file; -&gen_cpp_file; diff --git a/stp/INSTALL b/stp/INSTALL deleted file mode 100644 index 12cee121..00000000 --- a/stp/INSTALL +++ /dev/null @@ -1,10 +0,0 @@ -1. To install STP perform the following steps on your Unix/GNU-Linux/MacOS X commandline: - -./configure --with-prefix=$HOME (or another installation directory) -make clean -make -make install - -2. To test the system after installation: - -make regressall \ No newline at end of file diff --git a/stp/LICENSE b/stp/LICENSE deleted file mode 100644 index 41029509..00000000 --- a/stp/LICENSE +++ /dev/null @@ -1,17 +0,0 @@ -/*****************************************************************************/ -/* AUTHORS: Vijay Ganesh, David L. Dill DATE: Nov 2005 */ -/*****************************************************************************/ -/* Copyright (C) 2005 by the Board of Trustees of Leland Stanford */ -/* Junior University. */ -/* */ -/* License to use, copy, modify, sell and/or distribute this software */ -/* and its documentation for any purpose is hereby granted without */ -/* royalty, subject to the terms and conditions defined in the \ref */ -/* LICENSE file provided with this distribution. In particular: */ -/* */ -/* - The above copyright notice and this permission notice must appear */ -/* in all copies of the software and related documentation. */ -/* */ -/* - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES, */ -/* EXPRESSED OR IMPLIED. USE IT AT YOUR OWN RISK. */ -/*****************************************************************************/ diff --git a/stp/Makefile b/stp/Makefile deleted file mode 100644 index c863d5b4..00000000 --- a/stp/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -#===-- stp/Makefile ----------------------------------------*- Makefile -*--===# -# -# The KLEE Symbolic Virtual Machine -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -LEVEL=.. - -PARALLEL_DIRS := AST bitvec c_interface constantbv sat simplifier - -include $(LEVEL)/Makefile.common diff --git a/stp/README b/stp/README deleted file mode 100644 index da0f9b96..00000000 --- a/stp/README +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************** - * PROGRAM NAME: STP (Simple Theorem Prover) - * - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ - -Install -------- -See INSTALL file in the home dir of this program - -Authors -------- -Vijay Ganesh, Stanford University, Stanford, CA, USA -David L. Dill, Stanford University, Stanford, CA, USA -Tim King, Stanford University, Stanford, CA, USA - -Makefiles and configuration scripts ------------------------------------- -Cristian Cadar, Stanford University, Stanford, CA, USA -Paul Twohey, Stanford University, Stanford, CA, USA -Sergey Berezin, ATG Synopsys, Mountain View, CA, USA -Clark Barrett, New York University, New York, NY, USA diff --git a/stp/bitvec/Makefile b/stp/bitvec/Makefile deleted file mode 100644 index 2652be1d..00000000 --- a/stp/bitvec/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -#===-- stp/bitvec/Makefile ---------------------------------*- Makefile -*--===# -# -# The KLEE Symbolic Virtual Machine -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -LEVEL=../.. - -LIBRARYNAME=stp_bitvec -DONT_BUILD_RELINKED=1 -BUILD_ARCHIVE=1 - -include $(LEVEL)/Makefile.common - -# HACK: Force -Wno-deprecated for ext container use. -CXX.Flags += -Wno-deprecated diff --git a/stp/bitvec/consteval.cpp b/stp/bitvec/consteval.cpp deleted file mode 100644 index 8fa652cf..00000000 --- a/stp/bitvec/consteval.cpp +++ /dev/null @@ -1,1044 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -#include "../AST/AST.h" -#include "../AST/ASTUtil.h" -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); - } - -#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 BVAND: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - CONSTANTBV::Set_Intersection(output,tmp0,tmp1); - OutputNode = CreateBVConst(output, outputwidth); - break; - } - case BVOR: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - CONSTANTBV::Set_Union(output,tmp0,tmp1); - OutputNode = CreateBVConst(output, outputwidth); - break; - } - case BVXOR: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - CONSTANTBV::Set_ExclusiveOr(output,tmp0,tmp1); - OutputNode = CreateBVConst(output, outputwidth); - break; - } - case BVSUB: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - bool carry = false; - CONSTANTBV::BitVector_sub(output,tmp0,tmp1,&carry); - OutputNode = CreateBVConst(output, outputwidth); - break; - } - case BVUMINUS: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - CONSTANTBV::BitVector_Negate(output, tmp0); - OutputNode = CreateBVConst(output, outputwidth); - break; - } - case BVEXTRACT: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - tmp0 = BVConstEvaluator(t[0]).GetBVConst(); - unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1])); - unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2])); - unsigned int len = hi-low+1; - - CONSTANTBV::BitVector_Destroy(output); - output = CONSTANTBV::BitVector_Create(len, false); - CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, low, len); - outputwidth = len; - OutputNode = CreateBVConst(output, outputwidth); - break; - } - //FIXME Only 2 inputs? - case BVCONCAT: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - unsigned t0_width = t[0].GetValueWidth(); - unsigned t1_width = t[1].GetValueWidth(); - CONSTANTBV::BitVector_Destroy(output); - - output = CONSTANTBV::BitVector_Concat(tmp0, tmp1); - outputwidth = t0_width + t1_width; - OutputNode = CreateBVConst(output, outputwidth); - - break; - } - case BVMULT: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - CBV tmp = CONSTANTBV::BitVector_Create(2*inputwidth,true); - CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(tmp,tmp0,tmp1); - - if(0 != e) { - BVConstEvaluatorError(e,t); - } - //FIXME WHAT IS MY OUTPUT???? THE SECOND HALF of tmp? - //CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, inputwidth, inputwidth); - CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, 0, inputwidth); - OutputNode = CreateBVConst(output, outputwidth); - CONSTANTBV::BitVector_Destroy(tmp); - break; - } - case BVPLUS: { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - bool carry = false; - ASTVec c = t.GetChildren(); - for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) { - CBV kk = BVConstEvaluator(*it).GetBVConst(); - CONSTANTBV::BitVector_add(output,output,kk,&carry); - carry = false; - //CONSTANTBV::BitVector_Destroy(kk); - } - OutputNode = CreateBVConst(output, outputwidth); - break; - } - //FIXME ANOTHER SPECIAL CASE - case SBVDIV: - case SBVMOD:{ - OutputNode = BVConstEvaluator(TranslateSignedDivMod(t)); - break; - } - case BVDIV: - case BVMOD: { - CBV quotient = CONSTANTBV::BitVector_Create(inputwidth,true); - CBV remainder = CONSTANTBV::BitVector_Create(inputwidth,true); - - // tmp0 is dividend, tmp1 is the divisor - //All parameters to BitVector_Div_Pos must be distinct unlike BitVector_Divide - //FIXME the contents of the second parameter to Div_Pos is destroyed - //As tmp0 is currently the same as the copy belonging to an ASTNode t[0] - //this must be copied. - tmp0 = CONSTANTBV::BitVector_Clone(tmp0); - CONSTANTBV::ErrCode e= CONSTANTBV::BitVector_Div_Pos(quotient,tmp0,tmp1,remainder); - CONSTANTBV::BitVector_Destroy(tmp0); - - if(0 != e) { - //error printing - if(counterexample_checking_during_refinement) { - output = CONSTANTBV::BitVector_Create(inputwidth,true); - OutputNode = CreateBVConst(output, outputwidth); - bvdiv_exception_occured = true; - - // CONSTANTBV::BitVector_Destroy(output); - break; - } - else { - BVConstEvaluatorError(e,t); - } - } //end of error printing - - //FIXME Not very standard in the current scheme - if(BVDIV == k){ - OutputNode = CreateBVConst(quotient, outputwidth); - CONSTANTBV::BitVector_Destroy(remainder); - }else{ - OutputNode = CreateBVConst(remainder, outputwidth); - CONSTANTBV::BitVector_Destroy(quotient); - } - - break; - } - case ITE: - if(ASTTrue == t[0]) - OutputNode = BVConstEvaluator(t[1]); - else if(ASTFalse == t[0]) - OutputNode = BVConstEvaluator(t[2]); - else - FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t); - break; - case EQ: - if(CONSTANTBV::BitVector_equal(tmp0,tmp1)) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case NEQ: - if(!CONSTANTBV::BitVector_equal(tmp0,tmp1)) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case BVLT: - if(-1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1)) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case BVLE: { - int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1); - if(comp <= 0) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - case BVGT: - if(1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1)) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case BVGE: { - int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1); - if(comp >= 0) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - case BVSLT: - if(-1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1)) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case BVSLE: { - signed int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1); - if(comp <= 0) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - case BVSGT: - if(1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1)) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case BVSGE: { - int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1); - if(comp >= 0) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - default: - FatalError("BVConstEvaluator: The input kind is not supported yet:",t); - break; - } -/* - if(BVCONST != k){ - cerr<<inputwidth<<endl; - cerr<<"------------------------"<<endl; - t.LispPrint(cerr); - cerr<<endl; - OutputNode.LispPrint(cerr); - cerr<<endl<<"------------------------"<<endl; - } -*/ - UpdateSolverMap(t,OutputNode); - //UpdateSimplifyMap(t,OutputNode,false); - return OutputNode; - } -#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 SBVMOD: { - output = BVConstEvaluator(TranslateSignedDivMod(t)).GetBVConst(); - break; - } - case BVDIV: { - if(0 == t1.GetBVConst()) { - //if denominator is 0 then - // (if refinement is ON then output is set to 0) - // (else produce a fatal error) - if(counterexample_checking_during_refinement) { - output = 0; - bvdiv_exception_occured = true; - break; - } - else { - FatalError("BVConstEvaluator: divide by zero not allowed:",t); - } - } - - output = t0.GetBVConst() / t1.GetBVConst(); - //64 bit mask - unsigned long long int mask = 0xffffffffffffffffLL; - mask = mask >> (64 - inputwidth); - output &= mask; - break; - } - case BVMOD: { - if(0 == t1.GetBVConst()) { - //if denominator is 0 then - // (if refinement is ON then output is set to 0) - // (else produce a fatal error) - if(counterexample_checking_during_refinement) { - output = 0; - bvdiv_exception_occured = true; - break; - } - else { - FatalError("BVConstEvaluator: divide by zero not allowed:",t); - } - } - - output = t0.GetBVConst() % t1.GetBVConst(); - //64 bit mask - unsigned long long int mask = 0xffffffffffffffffLL; - mask = mask >> (64 - inputwidth); - output &= mask; - break; - } - case ITE: - if(ASTTrue == t[0]) - OutputNode = BVConstEvaluator(t[1]); - else if(ASTFalse == t[0]) - OutputNode = BVConstEvaluator(t[2]); - else - FatalError("BVConstEvaluator:" - "ITE condiional must be either TRUE or FALSE:",t); - break; - case EQ: - if(t0.GetBVConst() == t1.GetBVConst()) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case NEQ: - if(t0.GetBVConst() != t1.GetBVConst()) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - break; - case BVLT: { - unsigned long long n0 = t0.GetBVConst(); - unsigned long long n1 = t1.GetBVConst(); - if(n0 < n1) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - case BVLE: - if(t0.GetBVConst() <= t1.GetBVConst()) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case BVGT: - if(t0.GetBVConst() > t1.GetBVConst()) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case BVGE: - if(t0.GetBVConst() >= t1.GetBVConst()) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - case BVSLT: { - signed long long int n0 = SXBVConst64(t0); - signed long long int n1 = SXBVConst64(t1); - if(n0 < n1) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - case BVSLE: { - signed long long int n0 = SXBVConst64(t0); - signed long long int n1 = SXBVConst64(t1); - if(n0 <= n1) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - case BVSGT: { - signed long long int n0 = SXBVConst64(t0); - signed long long int n1 = SXBVConst64(t1); - if(n0 > n1) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - case BVSGE: { - signed long long int n0 = SXBVConst64(t0); - signed long long int n1 = SXBVConst64(t1); - if(n0 >= n1) - OutputNode = ASTTrue; - else - OutputNode = ASTFalse; - break; - } - default: - FatalError("BVConstEvaluator: The input kind is not supported yet:",t); - break; - } - - if(ASTTrue != OutputNode && ASTFalse != OutputNode) - OutputNode = CreateBVConst(inputwidth, output); - UpdateSolverMap(t,OutputNode); - //UpdateSimplifyMap(t,OutputNode,false); - return OutputNode; - } //End of BVConstEvaluator -#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 SBVMOD: { - 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 diff --git a/stp/c_interface/Makefile b/stp/c_interface/Makefile deleted file mode 100644 index 29b9006b..00000000 --- a/stp/c_interface/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -#===-- stp/c_interface/Makefile ----------------------------*- Makefile -*--===# -# -# The KLEE Symbolic Virtual Machine -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -LEVEL=../.. - -LIBRARYNAME=stp_c_interface -DONT_BUILD_RELINKED=1 -BUILD_ARCHIVE=1 - -include $(LEVEL)/Makefile.common - -# HACK: Force -Wno-deprecated for ext container use. -CXX.Flags += -Wno-deprecated diff --git a/stp/c_interface/c_interface.cpp b/stp/c_interface/c_interface.cpp deleted file mode 100644 index 52c4df21..00000000 --- a/stp/c_interface/c_interface.cpp +++ /dev/null @@ -1,1548 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- -#include "c_interface.h" - -#include <cstdlib> -#include <cassert> -#include <ostream> -#include <iostream> -#include "fdstream.h" -#include "../AST/AST.h" - -//These typedefs lower the effort of using the keyboard to type (too -//many overloaded meanings of the word type) -typedef BEEV::ASTNode node; -typedef BEEV::ASTNode* nodestar; -typedef BEEV::BeevMgr* bmstar; -typedef BEEV::ASTVec nodelist; -typedef BEEV::CompleteCounterExample* CompleteCEStar; -BEEV::ASTVec *decls = NULL; -//vector<BEEV::ASTNode *> created_exprs; -bool cinterface_exprdelete_on = false; - -void vc_setFlags(char c) { - std::string helpstring = "Usage: stp [-option] [infile]\n\n"; - helpstring += "-r : switch refinement off (optimizations are ON by default)\n"; - helpstring += "-w : switch wordlevel solver off (optimizations are ON by default)\n"; - helpstring += "-a : switch optimizations off (optimizations are ON by default)\n"; - helpstring += "-s : print function statistics\n"; - helpstring += "-v : print nodes \n"; - helpstring += "-c : construct counterexample\n"; - helpstring += "-d : check counterexample\n"; - helpstring += "-p : print counterexample\n"; - helpstring += "-h : help\n"; - - switch(c) { - case 'a' : - BEEV::optimize = false; - BEEV::wordlevel_solve = false; - break; - case 'b': - BEEV::print_STPinput_back = true; - break; - case 'c': - BEEV::construct_counterexample = true; - break; - case 'd': - BEEV::construct_counterexample = true; - BEEV::check_counterexample = true; - break; - case 'e': - BEEV::variable_activity_optimize = true; - break; - case 'f': - BEEV::smtlib_parser_enable = true; - break; - case 'h': - cout << helpstring; - BEEV::FatalError(""); - break; - case 'l' : - BEEV::linear_search = true; - break; - case 'n': - BEEV::print_output = true; - break; - case 'p': - BEEV::print_counterexample = true; - break; - case 'q': - BEEV::print_arrayval_declaredorder = true; - break; - case 'r': - BEEV::arrayread_refinement = false; - break; - case 's' : - BEEV::stats = true; - break; - case 'u': - BEEV::arraywrite_refinement = true; - break; - case 'v' : - BEEV::print_nodes = true; - break; - case 'w': - BEEV::wordlevel_solve = false; - break; - case 'x': - cinterface_exprdelete_on = true; - break; - case 'z': - BEEV::print_sat_varorder = true; - break; - default: - std::string s = "C_interface: vc_setFlags: Unrecognized commandline flag:\n"; - s += helpstring; - BEEV::FatalError(s.c_str()); - break; - } -} - -//Create a validity Checker. This is the global BeevMgr -VC vc_createValidityChecker(void) { - vc_setFlags('d'); -#ifdef NATIVE_C_ARITH -#else - CONSTANTBV::ErrCode c = CONSTANTBV::BitVector_Boot(); - if(0 != c) { - cout << CONSTANTBV::BitVector_Error(c) << endl; - return 0; - } -#endif - bmstar bm = new BEEV::BeevMgr(); - decls = new BEEV::ASTVec(); - //created_exprs.clear(); - return (VC)bm; -} - -// Expr I/O -void vc_printExpr(VC vc, Expr e) { - //do not print in lisp mode - //bmstar b = (bmstar)vc; - BEEV::ASTNode q = (*(nodestar)e); - // b->Begin_RemoveWrites = true; - // BEEV::ASTNode q = b->SimplifyFormula_TopLevel(*((nodestar)e),false); - // b->Begin_RemoveWrites = false; - q.PL_Print(cout); -} - -void vc_printExprFile(VC vc, Expr e, int fd) { - fdostream os(fd); - ((nodestar)e)->PL_Print(os); - //os.flush(); -} - -static void vc_printVarDeclsToStream(VC vc, ostream &os) { - for(BEEV::ASTVec::iterator i = decls->begin(),iend=decls->end();i!=iend;i++) { - node a = *i; - switch(a.GetType()) { - case BEEV::BITVECTOR_TYPE: - a.PL_Print(os); - os << " : BITVECTOR(" << a.GetValueWidth() << ");" << endl; - break; - case BEEV::ARRAY_TYPE: - a.PL_Print(os); - os << " : ARRAY " << "BITVECTOR(" << a.GetIndexWidth() << ") OF "; - os << "BITVECTOR(" << a.GetValueWidth() << ");" << endl; - break; - case BEEV::BOOLEAN_TYPE: - a.PL_Print(os); - os << " : BOOLEAN;" << endl; - break; - default: - BEEV::FatalError("vc_printDeclsToStream: Unsupported type",a); - break; - } - } -} - -void vc_printVarDecls(VC vc) { - vc_printVarDeclsToStream(vc, cout); -} - -static void vc_printAssertsToStream(VC vc, ostream &os, int simplify_print) { - bmstar b = (bmstar)vc; - BEEV::ASTVec v = b->GetAsserts(); - for(BEEV::ASTVec::iterator i=v.begin(),iend=v.end();i!=iend;i++) { - b->Begin_RemoveWrites = true; - BEEV::ASTNode q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(*i,false) : *i; - q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(q,false) : q; - b->Begin_RemoveWrites = false; - os << "ASSERT( "; - q.PL_Print(os); - os << ");" << endl; - } -} - -void vc_printAsserts(VC vc, int simplify_print) { - vc_printAssertsToStream(vc, cout, simplify_print); -} - -void vc_printQueryStateToBuffer(VC vc, Expr e, char **buf, unsigned long *len, int simplify_print){ - assert(vc); - assert(e); - assert(buf); - assert(len); - bmstar b = (bmstar)vc; - - // formate the state of the query - stringstream os; - vc_printVarDeclsToStream(vc, os); - os << "%----------------------------------------------------" << endl; - vc_printAssertsToStream(vc, os, simplify_print); - os << "%----------------------------------------------------" << endl; - os << "QUERY( "; - b->Begin_RemoveWrites = true; - BEEV::ASTNode q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(*((nodestar)e),false) : *(nodestar)e; - b->Begin_RemoveWrites = false; - q.PL_Print(os); - os << " );" << endl; - - // convert to a c buffer - string s = os.str(); - const char *cstr = s.c_str(); - unsigned long size = s.size() + 1; // number of chars + terminating null - *buf = (char *)malloc(size); - if (!(*buf)) { - fprintf(stderr, "malloc(%lu) failed.", size); - assert(*buf); - } - *len = size; - memcpy(*buf, cstr, size); -} - -void vc_printCounterExampleToBuffer(VC vc, char **buf, unsigned long *len) { - assert(vc); - assert(buf); - assert(len); - bmstar b = (bmstar)vc; - - // formate the state of the query - std::ostringstream os; - BEEV::print_counterexample = true; - os << "COUNTEREXAMPLE BEGIN: \n"; - b->PrintCounterExample(true,os); - os << "COUNTEREXAMPLE END: \n"; - - // convert to a c buffer - string s = os.str(); - const char *cstr = s.c_str(); - unsigned long size = s.size() + 1; // number of chars + terminating null - *buf = (char *)malloc(size); - if (!(*buf)) { - fprintf(stderr, "malloc(%lu) failed.", size); - assert(*buf); - } - *len = size; - memcpy(*buf, cstr, size); -} - -void vc_printExprToBuffer(VC vc, Expr e, char **buf, unsigned long * len) { - stringstream os; - //bmstar b = (bmstar)vc; - BEEV::ASTNode q = *((nodestar)e); - // b->Begin_RemoveWrites = true; - // BEEV::ASTNode q = b->SimplifyFormula_TopLevel(*((nodestar)e),false); - // b->Begin_RemoveWrites = false; - q.PL_Print(os); - //((nodestar)e)->PL_Print(os); - string s = os.str(); - const char * cstr = s.c_str(); - unsigned long size = s.size() + 1; // number of chars + terminating null - *buf = (char *)malloc(size); - *len = size; - memcpy(*buf, cstr, size); -} - -void vc_printQuery(VC vc){ - ostream& os = std::cout; - bmstar b = (bmstar)vc; - os << "QUERY("; - //b->Begin_RemoveWrites = true; - //BEEV::ASTNode q = b->SimplifyFormula_TopLevel(b->GetQuery(),false); - BEEV::ASTNode q = b->GetQuery(); - //b->Begin_RemoveWrites = false; - q.PL_Print(os); - // b->GetQuery().PL_Print(os); - os << ");" << endl; -} - -///////////////////////////////////////////////////////////////////////////// -// Array-related methods // -///////////////////////////////////////////////////////////////////////////// -//! Create an array type -Type vc_arrayType(VC vc, Type typeIndex, Type typeData) { - bmstar b = (bmstar)vc; - nodestar ti = (nodestar)typeIndex; - nodestar td = (nodestar)typeData; - - if(!(ti->GetKind() == BEEV::BITVECTOR && (*ti)[0].GetKind() == BEEV::BVCONST)) - BEEV::FatalError("Tyring to build array whose indextype i is not a BITVECTOR, where i = ",*ti); - if(!(td->GetKind() == BEEV::BITVECTOR && (*td)[0].GetKind() == BEEV::BVCONST)) - BEEV::FatalError("Trying to build an array whose valuetype v is not a BITVECTOR. where a = ",*td); - nodestar output = new node(b->CreateNode(BEEV::ARRAY,(*ti)[0],(*td)[0])); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return (Type)output; -} - -//! Create an expression for the value of array at the given index -Expr vc_readExpr(VC vc, Expr array, Expr index) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)array; - nodestar i = (nodestar)index; - - b->BVTypeCheck(*a); - b->BVTypeCheck(*i); - node o = b->CreateTerm(BEEV::READ,a->GetValueWidth(),*a,*i); - b->BVTypeCheck(o); - - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -// //! Array update; equivalent to "array WITH [index] := newValue" -Expr vc_writeExpr(VC vc, Expr array, Expr index, Expr newValue) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)array; - nodestar i = (nodestar)index; - nodestar n = (nodestar)newValue; - - b->BVTypeCheck(*a); - b->BVTypeCheck(*i); - b->BVTypeCheck(*n); - node o = b->CreateTerm(BEEV::WRITE,a->GetValueWidth(),*a,*i,*n); - o.SetIndexWidth(a->GetIndexWidth()); - b->BVTypeCheck(o); - - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -///////////////////////////////////////////////////////////////////////////// -// Context-related methods // -///////////////////////////////////////////////////////////////////////////// -//! Assert a new formula in the current context. -/*! The formula must have Boolean type. */ -void vc_assertFormula(VC vc, Expr e) { - nodestar a = (nodestar)e; - bmstar b = (bmstar)vc; - - if(!BEEV::is_Form_kind(a->GetKind())) - BEEV::FatalError("Trying to assert a NON formula: ",*a); - - b->BVTypeCheck(*a); - b->AddAssert(*a); -} - -//! Check validity of e in the current context. -/*! If the result is true, then the resulting context is the same as - * the starting context. If the result is false, then the resulting - * context is a context in which e is false. e must have Boolean - * type. */ -int vc_query(VC vc, Expr e) { - nodestar a = (nodestar)e; - bmstar b = (bmstar)vc; - - if(!BEEV::is_Form_kind(a->GetKind())) - BEEV::FatalError("CInterface: Trying to QUERY a NON formula: ",*a); - - b->BVTypeCheck(*a); - b->AddQuery(*a); - - const BEEV::ASTVec v = b->GetAsserts(); - node o; - if(!v.empty()) { - if(v.size()==1) - return b->TopLevelSAT(v[0],*a); - else - return b->TopLevelSAT(b->CreateNode(BEEV::AND,v),*a); - } - else - return b->TopLevelSAT(b->CreateNode(BEEV::TRUE),*a); -} - -void vc_push(VC vc) { - bmstar b = (bmstar)vc; - b->ClearAllCaches(); - b->Push(); -} - -void vc_pop(VC vc) { - bmstar b = (bmstar)vc; - b->Pop(); -} - -void vc_printCounterExample(VC vc) { - bmstar b = (bmstar)vc; - BEEV::print_counterexample = true; - cout << "COUNTEREXAMPLE BEGIN: \n"; - b->PrintCounterExample(true); - cout << "COUNTEREXAMPLE END: \n"; -} - -// //! Return the counterexample after a failed query. -// /*! This method should only be called after a query which returns -// * false. It will try to return the simplest possible set of -// * assertions which are sufficient to make the queried expression -// * false. The caller is responsible for freeing the array when -// * finished with it. -// */ - -Expr vc_getCounterExample(VC vc, Expr e) { - nodestar a = (nodestar)e; - bmstar b = (bmstar)vc; - - bool t = false; - if(b->CounterExampleSize()) - t = true; - nodestar output = new node(b->GetCounterExample(t, *a)); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -int vc_counterexample_size(VC vc) { - bmstar b = (bmstar)vc; - return b->CounterExampleSize(); -} - -WholeCounterExample vc_getWholeCounterExample(VC vc) { - bmstar b = (bmstar)vc; - CompleteCEStar c = - new BEEV::CompleteCounterExample(b->GetCompleteCounterExample(), b); - return c; -} - -Expr vc_getTermFromCounterExample(VC vc, Expr e, CompleteCEStar cc) { - //bmstar b = (bmstar)vc; - nodestar n = (nodestar)e; - CompleteCEStar c = (CompleteCEStar)cc; - - nodestar output = new node(c->GetCounterExample(*n)); - return output; -} - -int vc_getBVLength(VC vc, Expr ex) { - nodestar e = (nodestar)ex; - - if(BEEV::BITVECTOR_TYPE != e->GetType()) { - BEEV::FatalError("c_interface: vc_GetBVLength: Input expression must be a bit-vector"); - } - - return e->GetValueWidth(); -} // end of vc_getBVLength - -///////////////////////////////////////////////////////////////////////////// -// Expr Creation methods // -///////////////////////////////////////////////////////////////////////////// -//! Create a variable with a given name and type -/*! The type cannot be a function type. */ -Expr vc_varExpr1(VC vc, char* name, - int indexwidth, int valuewidth) { - bmstar b = (bmstar)vc; - - node o = b->CreateSymbol(name); - o.SetIndexWidth(indexwidth); - o.SetValueWidth(valuewidth); - - nodestar output = new node(o); - ////if(cinterface_exprdelete_on) created_exprs.push_back(output); - b->BVTypeCheck(*output); - - //store the decls in a vector for printing purposes - decls->push_back(o); - return output; -} - -Expr vc_varExpr(VC vc, char * name, Type type) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)type; - - node o = b->CreateSymbol(name); - switch(a->GetKind()) { - case BEEV::BITVECTOR: - o.SetIndexWidth(0); - o.SetValueWidth(GetUnsignedConst((*a)[0])); - break; - case BEEV::ARRAY: - o.SetIndexWidth(GetUnsignedConst((*a)[0])); - o.SetValueWidth(GetUnsignedConst((*a)[1])); - break; - case BEEV::BOOLEAN: - o.SetIndexWidth(0); - o.SetValueWidth(0); - break; - default: - BEEV::FatalError("CInterface: vc_varExpr: Unsupported type",*a); - break; - } - nodestar output = new node(o); - ////if(cinterface_exprdelete_on) created_exprs.push_back(output); - b->BVTypeCheck(*output); - - //store the decls in a vector for printing purposes - decls->push_back(o); - return output; -} - -//! Create an equality expression. The two children must have the -//same type. -Expr vc_eqExpr(VC vc, Expr ccc0, Expr ccc1) { - bmstar b = (bmstar)vc; - - nodestar a = (nodestar)ccc0; - nodestar aa = (nodestar)ccc1; - b->BVTypeCheck(*a); - b->BVTypeCheck(*aa); - node o = b->CreateNode(BEEV::EQ,*a,*aa); - - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_boolType(VC vc) { - bmstar b = (bmstar)vc; - - node o = b->CreateNode(BEEV::BOOLEAN); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -///////////////////////////////////////////////////////////////////////////// -// BOOLEAN EXPR Creation methods // -///////////////////////////////////////////////////////////////////////////// -// The following functions create Boolean expressions. The children -// provided as arguments must be of type Boolean. -Expr vc_trueExpr(VC vc) { - bmstar b = (bmstar)vc; - node c = b->CreateNode(BEEV::TRUE); - - nodestar d = new node(c); - //if(cinterface_exprdelete_on) created_exprs.push_back(d); - return d; -} - -Expr vc_falseExpr(VC vc) { - bmstar b = (bmstar)vc; - node c = b->CreateNode(BEEV::FALSE); - - nodestar d = new node(c); - //if(cinterface_exprdelete_on) created_exprs.push_back(d); - return d; -} - -Expr vc_notExpr(VC vc, Expr ccc) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)ccc; - - node o = b->CreateNode(BEEV::NOT,*a); - b->BVTypeCheck(o); - - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_andExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - node o = b->CreateNode(BEEV::AND,*l,*r); - b->BVTypeCheck(o); - - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_orExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - node o = b->CreateNode(BEEV::OR,*l,*r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_andExprN(VC vc, Expr* cc, int n) { - bmstar b = (bmstar)vc; - nodestar * c = (nodestar *)cc; - nodelist d; - - for(int i =0; i < n; i++) - d.push_back(*c[i]); - - node o = b->CreateNode(BEEV::AND,d); - b->BVTypeCheck(o); - - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - - -Expr vc_orExprN(VC vc, Expr* cc, int n) { - bmstar b = (bmstar)vc; - nodestar * c = (nodestar *)cc; - nodelist d; - - for(int i =0; i < n; i++) - d.push_back(*c[i]); - - node o = b->CreateNode(BEEV::OR,d); - b->BVTypeCheck(o); - - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_iteExpr(VC vc, Expr cond, Expr thenpart, Expr elsepart){ - bmstar b = (bmstar)vc; - nodestar c = (nodestar)cond; - nodestar t = (nodestar)thenpart; - nodestar e = (nodestar)elsepart; - - b->BVTypeCheck(*c); - b->BVTypeCheck(*t); - b->BVTypeCheck(*e); - node o; - //if the user asks for a formula then produce a formula, else - //prodcue a term - if(BEEV::BOOLEAN_TYPE == t->GetType()) - o = b->CreateNode(BEEV::ITE,*c,*t,*e); - else { - o = b->CreateTerm(BEEV::ITE,t->GetValueWidth(),*c,*t,*e); - o.SetIndexWidth(t->GetIndexWidth()); - } - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_impliesExpr(VC vc, Expr antecedent, Expr consequent){ - bmstar b = (bmstar)vc; - nodestar c = (nodestar)antecedent; - nodestar t = (nodestar)consequent; - - b->BVTypeCheck(*c); - b->BVTypeCheck(*t); - node o; - - o = b->CreateNode(BEEV::IMPLIES,*c,*t); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_iffExpr(VC vc, Expr e0, Expr e1){ - bmstar b = (bmstar)vc; - nodestar c = (nodestar)e0; - nodestar t = (nodestar)e1; - - b->BVTypeCheck(*c); - b->BVTypeCheck(*t); - node o; - - o = b->CreateNode(BEEV::IFF,*c,*t); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_boolToBVExpr(VC vc, Expr form) { - bmstar b = (bmstar)vc; - nodestar c = (nodestar)form; - - b->BVTypeCheck(*c); - if(!is_Form_kind(c->GetKind())) - BEEV::FatalError("CInterface: vc_BoolToBVExpr: You have input a NON formula:",*c); - - node o; - node one = b->CreateOneConst(1); - node zero = b->CreateZeroConst(1); - o = b->CreateTerm(BEEV::ITE,1,*c,one,zero); - - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -///////////////////////////////////////////////////////////////////////////// -// BITVECTOR EXPR Creation methods // -///////////////////////////////////////////////////////////////////////////// -Type vc_bvType(VC vc, int num_bits) { - bmstar b = (bmstar)vc; - - if(!(0 < num_bits)) - BEEV::FatalError("CInterface: number of bits in a bvtype must be a positive integer:", - b->CreateNode(BEEV::UNDEFINED)); - - node e = b->CreateBVConst(32, num_bits); - nodestar output = new node(b->CreateNode(BEEV::BITVECTOR,e)); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Type vc_bv32Type(VC vc) { - return vc_bvType(vc,32); -} - - -Expr vc_bvConstExprFromStr(VC vc, char* binary_repr) { - bmstar b = (bmstar)vc; - - node n = b->CreateBVConst(binary_repr,2); - b->BVTypeCheck(n); - nodestar output = new node(n); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvConstExprFromInt(VC vc, - int n_bits, - unsigned int value) { - bmstar b = (bmstar)vc; - - unsigned long long int v = (unsigned long long int)value; - node n = b->CreateBVConst(n_bits, v); - b->BVTypeCheck(n); - nodestar output = new node(n); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvConstExprFromLL(VC vc, - int n_bits, - unsigned long long value) { - bmstar b = (bmstar)vc; - - node n = b->CreateBVConst(n_bits, value); - b->BVTypeCheck(n); - nodestar output = new node(n); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvConcatExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = - b->CreateTerm(BEEV::BVCONCAT, - l->GetValueWidth()+ r->GetValueWidth(),*l,*r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvPlusExpr(VC vc, int n_bits, Expr left, Expr right){ - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::BVPLUS,n_bits, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - - -Expr vc_bv32PlusExpr(VC vc, Expr left, Expr right) { - return vc_bvPlusExpr(vc, 32, left, right); -} - - -Expr vc_bvMinusExpr(VC vc, int n_bits, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::BVSUB,n_bits, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - - -Expr vc_bv32MinusExpr(VC vc, Expr left, Expr right) { - return vc_bvMinusExpr(vc, 32, left, right); -} - - -Expr vc_bvMultExpr(VC vc, int n_bits, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::BVMULT,n_bits, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvDivExpr(VC vc, int n_bits, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::BVDIV,n_bits, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvModExpr(VC vc, int n_bits, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::BVMOD,n_bits, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_sbvDivExpr(VC vc, int n_bits, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::SBVDIV,n_bits, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_sbvModExpr(VC vc, int n_bits, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::SBVMOD,n_bits, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bv32MultExpr(VC vc, Expr left, Expr right) { - return vc_bvMultExpr(vc, 32, left, right); -} - - -// unsigned comparators -Expr vc_bvLtExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateNode(BEEV::BVLT, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvLeExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateNode(BEEV::BVLE, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvGtExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateNode(BEEV::BVGT, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvGeExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateNode(BEEV::BVGE, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -// signed comparators -Expr vc_sbvLtExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateNode(BEEV::BVSLT, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_sbvLeExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateNode(BEEV::BVSLE, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_sbvGtExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateNode(BEEV::BVSGT, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_sbvGeExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateNode(BEEV::BVSGE, *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvUMinusExpr(VC vc, Expr ccc) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)ccc; - b->BVTypeCheck(*a); - - node o = b->CreateTerm(BEEV::BVUMINUS, a->GetValueWidth(), *a); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -// bitwise operations: these are terms not formulas -Expr vc_bvAndExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::BVAND, (*l).GetValueWidth(), *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvOrExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::BVOR, (*l).GetValueWidth(), *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvXorExpr(VC vc, Expr left, Expr right) { - bmstar b = (bmstar)vc; - nodestar l = (nodestar)left; - nodestar r = (nodestar)right; - - b->BVTypeCheck(*l); - b->BVTypeCheck(*r); - node o = b->CreateTerm(BEEV::BVXOR, (*l).GetValueWidth(), *l, *r); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvNotExpr(VC vc, Expr ccc) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)ccc; - - b->BVTypeCheck(*a); - node o = b->CreateTerm(BEEV::BVNEG, a->GetValueWidth(), *a); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvLeftShiftExpr(VC vc, int sh_amt, Expr ccc) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)ccc; - b->BVTypeCheck(*a); - - //convert leftshift to bvconcat - if(0 != sh_amt) { - node len = b->CreateBVConst(sh_amt, 0); - node o = b->CreateTerm(BEEV::BVCONCAT, a->GetValueWidth() + sh_amt, *a, len); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; - } - else - return a; -} - -Expr vc_bvRightShiftExpr(VC vc, int sh_amt, Expr ccc) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)ccc; - b->BVTypeCheck(*a); - - unsigned int w = a->GetValueWidth(); - //the amount by which you are rightshifting - //is less-than/equal-to the length of input - //bitvector - if(0 < (unsigned)sh_amt && (unsigned)sh_amt <= w) { - node len = b->CreateBVConst(sh_amt, 0); - node hi = b->CreateBVConst(32,w-1); - node low = b->CreateBVConst(32,sh_amt); - node extract = b->CreateTerm(BEEV::BVEXTRACT,w-sh_amt,*a,hi,low); - - node n = b->CreateTerm(BEEV::BVCONCAT, w,len, extract); - b->BVTypeCheck(n); - nodestar output = new node(n); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; - } - else if(sh_amt == 0) - return a; - else { - if(0== w) - BEEV::FatalError("CInterface: vc_bvRightShiftExpr: cannot have a bitvector of length 0:",*a); - nodestar output = new node(b->CreateBVConst(w,0)); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; - } -} - -/* Same as vc_bvLeftShift only that the answer in 32 bits long */ -Expr vc_bv32LeftShiftExpr(VC vc, int sh_amt, Expr child) { - return vc_bvExtract(vc, vc_bvLeftShiftExpr(vc, sh_amt, child), 31, 0); -} - -/* Same as vc_bvRightShift only that the answer in 32 bits long */ -Expr vc_bv32RightShiftExpr(VC vc, int sh_amt, Expr child) { - return vc_bvExtract(vc, vc_bvRightShiftExpr(vc, sh_amt, child), 31, 0); -} - - -Expr vc_bvVar32LeftShiftExpr(VC vc, Expr sh_amt, Expr child) { - Expr ifpart; - Expr thenpart; - Expr elsepart = vc_trueExpr(vc); - Expr ite = vc_trueExpr(vc); - - for(int count=32; count >= 0; count--){ - if(count != 32) { - ifpart = vc_eqExpr(vc, sh_amt, - vc_bvConstExprFromInt(vc, 32, count)); - thenpart = vc_bvExtract(vc, - vc_bvLeftShiftExpr(vc, count, child), - 31, 0); - - ite = vc_iteExpr(vc,ifpart,thenpart,elsepart); - elsepart = ite; - } - else - elsepart = vc_bvConstExprFromInt(vc,32, 0); - } - return ite; -} - -Expr vc_bvVar32DivByPowOfTwoExpr(VC vc, Expr child, Expr rhs) { - Expr ifpart; - Expr thenpart; - Expr elsepart = vc_trueExpr(vc); - Expr ite = vc_trueExpr(vc); - - for(int count=32; count >= 0; count--){ - if(count != 32) { - ifpart = vc_eqExpr(vc, rhs, - vc_bvConstExprFromInt(vc, 32, 1 << count)); - thenpart = vc_bvRightShiftExpr(vc, count, child); - ite = vc_iteExpr(vc,ifpart,thenpart,elsepart); - elsepart = ite; - } else { - elsepart = vc_bvConstExprFromInt(vc,32, 0); - } - } - return ite; -} - -Expr vc_bvVar32RightShiftExpr(VC vc, Expr sh_amt, Expr child) { - Expr ifpart; - Expr thenpart; - Expr elsepart = vc_trueExpr(vc); - Expr ite = vc_trueExpr(vc); - - for(int count=32; count >= 0; count--){ - if(count != 32) { - ifpart = vc_eqExpr(vc, sh_amt, - vc_bvConstExprFromInt(vc, 32, count)); - thenpart = vc_bvRightShiftExpr(vc, count, child); - ite = vc_iteExpr(vc,ifpart,thenpart,elsepart); - elsepart = ite; - } else { - elsepart = vc_bvConstExprFromInt(vc,32, 0); - } - } - return ite; -} - -Expr vc_bvExtract(VC vc, Expr ccc, int hi_num, int low_num) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)ccc; - b->BVTypeCheck(*a); - - node hi = b->CreateBVConst(32,hi_num); - node low = b->CreateBVConst(32,low_num); - node o = b->CreateTerm(BEEV::BVEXTRACT,hi_num-low_num+1,*a,hi,low); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvBoolExtract(VC vc, Expr ccc, int bit_num) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)ccc; - b->BVTypeCheck(*a); - - node bit = b->CreateBVConst(32,bit_num); - //node o = b->CreateNode(BEEV::BVGETBIT,*a,bit); - node zero = b->CreateBVConst(1,0); - node oo = b->CreateTerm(BEEV::BVEXTRACT,1,*a,bit,bit); - node o = b->CreateNode(BEEV::EQ,oo,zero); - b->BVTypeCheck(o); - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -Expr vc_bvSignExtend(VC vc, Expr ccc, int nbits) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)ccc; - - //width of the expr which is being sign extended. nbits is the - //resulting length of the signextended expr - b->BVTypeCheck(*a); - - unsigned exprlen = a->GetValueWidth(); - unsigned outputlen = nbits; - node n; - if(exprlen >= outputlen) { - //extract - node hi = b->CreateBVConst(32,outputlen-1); - node low = b->CreateBVConst(32,0); - n = b->CreateTerm(BEEV::BVEXTRACT,nbits,*a,hi,low); - b->BVTypeCheck(n); - } - else { - //sign extend - BEEV::ASTNode width = b->CreateBVConst(32,nbits); - n = b->CreateTerm(BEEV::BVSX,nbits,*a, width); - } - - b->BVTypeCheck(n); - nodestar output = new node(n); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; -} - -//! Return an int from a constant bitvector expression -int getBVInt(Expr e) { - //bmstar b = (bmstar)vc; - nodestar a = (nodestar)e; - - if(BEEV::BVCONST != a->GetKind()) - BEEV::FatalError("CInterface: getBVInt: Attempting to extract int value from a NON-constant BITVECTOR: ",*a); - return (int)GetUnsignedConst(*a); -} - -//! Return an unsigned int from a constant bitvector expression -unsigned int getBVUnsigned(Expr e) { - //bmstar b = (bmstar)vc; - nodestar a = (nodestar)e; - - if(BEEV::BVCONST != a->GetKind()) - BEEV::FatalError("getBVUnsigned: Attempting to extract int value from a NON-constant BITVECTOR: ",*a); - return (unsigned int)GetUnsignedConst(*a); -} - -//! Return an unsigned long long int from a constant bitvector expression -unsigned long long int getBVUnsignedLongLong(Expr e) { - //bmstar b = (bmstar)vc; - nodestar a = (nodestar)e; - - if(BEEV::BVCONST != a->GetKind()) - BEEV::FatalError("getBVUnsigned: Attempting to extract int value from a NON-constant BITVECTOR: ",*a); -#ifdef NATIVE_C_ARITH - return (unsigned long long int)a->GetBVConst(); -#else - unsigned* bv = a->GetBVConst(); - - char * str_bv = (char *)CONSTANTBV::BitVector_to_Bin(bv); - unsigned long long int tmp = strtoull(str_bv,NULL,2); - CONSTANTBV::BitVector_Dispose((unsigned char *)str_bv); - return tmp; -#endif -} - - -Expr vc_simplify(VC vc, Expr e) { - bmstar b = (bmstar)vc; - nodestar a = (nodestar)e; - - if(BEEV::BOOLEAN_TYPE == a->GetType()) { - nodestar output = new node(b->SimplifyFormula_TopLevel(*a,false)); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - b->Begin_RemoveWrites = true; - output = new node(b->SimplifyFormula_TopLevel(*output,false)); - b->Begin_RemoveWrites = false; - return output; - } - else { - nodestar output = new node(b->SimplifyTerm(*a)); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - b->Begin_RemoveWrites = true; - output = new node(b->SimplifyTerm(*output)); - b->Begin_RemoveWrites = false; - return output; - } -} - -/* C pointer support: C interface to support C memory arrays in CVCL */ -Expr vc_bvCreateMemoryArray(VC vc, char * arrayName) { - Type bv8 = vc_bvType(vc,8); - Type bv32 = vc_bvType(vc,32); - - Type malloced_mem0 = vc_arrayType(vc,bv32,bv8); - return vc_varExpr(vc, arrayName, malloced_mem0); -} - -Expr vc_bvReadMemoryArray(VC vc, - Expr array, - Expr byteIndex, int numOfBytes) { - if(!(numOfBytes > 0)) - BEEV::FatalError("numOfBytes must be greater than 0"); - - if(numOfBytes == 1) - return vc_readExpr(vc,array,byteIndex); - else { - int count = 1; - Expr a = vc_readExpr(vc,array,byteIndex); - while(--numOfBytes > 0) { - Expr b = vc_readExpr(vc,array, - /*vc_simplify(vc, */ - vc_bvPlusExpr(vc, 32, - byteIndex, - vc_bvConstExprFromInt(vc,32,count)))/*)*/; - a = vc_bvConcatExpr(vc,b,a); - count++; - } - return a; - } -} - -Expr vc_bvWriteToMemoryArray(VC vc, - Expr array, Expr byteIndex, - Expr element, int numOfBytes) { - if(!(numOfBytes > 0)) - BEEV::FatalError("numOfBytes must be greater than 0"); - - int newBitsPerElem = numOfBytes*8; - if(numOfBytes == 1) - return vc_writeExpr(vc, array, byteIndex, element); - else { - int count = 1; - int hi = newBitsPerElem - 1; - int low = newBitsPerElem - 8; - int low_elem = 0; - int hi_elem = low_elem + 7; - Expr c = vc_bvExtract(vc, element, hi_elem, low_elem); - Expr newarray = vc_writeExpr(vc, array, byteIndex, c); - while(--numOfBytes > 0) { - hi = low-1; - low = low-8; - - low_elem = low_elem + 8; - hi_elem = low_elem + 7; - - c = vc_bvExtract(vc, element, hi_elem, low_elem); - newarray = - vc_writeExpr(vc, newarray, - vc_bvPlusExpr(vc, 32, byteIndex, vc_bvConstExprFromInt(vc,32,count)), - c); - count++; - } - return newarray; - } -} - -Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value){ - return vc_bvConstExprFromInt(vc, 32, value); -} - - -#if 0 -static char *val_to_binary_str(unsigned nbits, unsigned long long val) { - char s[65]; - - assert(nbits < sizeof s); - strcpy(s, ""); - while(nbits-- > 0) { - if((val >> nbits) & 1) - strcat(s, "1"); - else - strcat(s, "0"); - } - return strdup(s); -} -#endif - -char* exprString(Expr e){ - stringstream ss; - ((nodestar)e)->PL_Print(ss,0); - string s = ss.str(); - char *copy = strdup(s.c_str()); - return copy; -} - -char* typeString(Type t){ - stringstream ss; - ((nodestar)t)->PL_Print(ss,0); - - string s = ss.str(); - char *copy = strdup(s.c_str()); - return copy; -} - -Expr getChild(Expr e, int i){ - nodestar a = (nodestar)e; - - BEEV::ASTVec c = a->GetChildren(); - if ((unsigned)i < c.size()) { - BEEV::ASTNode o = c[i]; - nodestar output = new node(o); - //if(cinterface_exprdelete_on) created_exprs.push_back(output); - return output; - } - else - BEEV::FatalError("getChild: Error accessing childNode in expression: ",*a); - return a; -} - -void vc_registerErrorHandler(void (*error_hdlr)(const char* err_msg)) { - BEEV::vc_error_hdlr = error_hdlr; -} - - -int vc_getHashQueryStateToBuffer(VC vc, Expr query) { - assert(vc); - assert(query); - bmstar b = (bmstar)vc; - nodestar qry = (nodestar)query; - BEEV::ASTVec v = b->GetAsserts(); - BEEV::ASTNode out = b->CreateNode(BEEV::AND,b->CreateNode(BEEV::NOT,*qry),v); - return out.Hash(); -} - -Type vc_getType(VC vc, Expr ex) { - nodestar e = (nodestar)ex; - - switch(e->GetType()) { - case BEEV::BOOLEAN_TYPE: - return vc_boolType(vc); - break; - case BEEV::BITVECTOR_TYPE: - return vc_bvType(vc,e->GetValueWidth()); - break; - case BEEV::ARRAY_TYPE: { - Type typeindex = vc_bvType(vc,e->GetIndexWidth()); - Type typedata = vc_bvType(vc,e->GetValueWidth()); - return vc_arrayType(vc,typeindex,typedata); - break; - } - default: - BEEV::FatalError("c_interface: vc_GetType: expression with bad typing: please check your expression construction"); - return vc_boolType(vc); - break; - } -}// end of vc_gettype() - -//!if e is TRUE then return 1; if e is FALSE then return 0; otherwise -//return -1 -int vc_isBool(Expr e) { - nodestar input = (nodestar)e; - if(BEEV::TRUE == input->GetKind()) { - return 1; - } - - if(BEEV::FALSE == input->GetKind()) { - return 0; - } - - return -1; -} - -void vc_Destroy(VC vc) { - bmstar b = (bmstar)vc; - // for(std::vector<BEEV::ASTNode *>::iterator it=created_exprs.begin(), - // itend=created_exprs.end();it!=itend;it++) { - // BEEV::ASTNode * aaa = *it; - // delete aaa; - // } - delete decls; - delete b; -} - -void vc_DeleteExpr(Expr e) { - nodestar input = (nodestar)e; - //bmstar b = (bmstar)vc; - delete input; -} - -exprkind_t getExprKind(Expr e) { - nodestar input = (nodestar)e; - return (exprkind_t)(input->GetKind()); -} - -int getDegree (Expr e) { - nodestar input = (nodestar)e; - return input->Degree(); -} - -int getBVLength(Expr ex) { - nodestar e = (nodestar)ex; - - if(BEEV::BITVECTOR_TYPE != e->GetType()) { - BEEV::FatalError("c_interface: vc_GetBVLength: Input expression must be a bit-vector"); - } - - return e->GetValueWidth(); -} - -type_t getType (Expr ex) { - nodestar e = (nodestar)ex; - - return (type_t)(e->GetType()); -} - -int getVWidth (Expr ex) { - nodestar e = (nodestar)ex; - - return e->GetValueWidth(); -} - -int getIWidth (Expr ex) { - nodestar e = (nodestar)ex; - - return e->GetIndexWidth(); -} - -void vc_printCounterExampleFile(VC vc, int fd) { - fdostream os(fd); - bmstar b = (bmstar)vc; - BEEV::print_counterexample = true; - os << "COUNTEREXAMPLE BEGIN: \n"; - b->PrintCounterExample(true, os); - os << "COUNTEREXAMPLE END: \n"; -} - -const char* exprName(Expr e){ - return ((nodestar)e)->GetName(); -} - -int getExprID (Expr ex) { - BEEV::ASTNode q = (*(nodestar)ex); - - return q.GetNodeNum(); -} diff --git a/stp/c_interface/c_interface.h b/stp/c_interface/c_interface.h deleted file mode 100644 index a2fa8cd7..00000000 --- a/stp/c_interface/c_interface.h +++ /dev/null @@ -1,401 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * License to use, copy, modify, sell and/or distribute this software - * and its documentation for any purpose is hereby granted without - * royalty, subject to the terms and conditions defined in the \ref - * LICENSE file provided with this distribution. In particular: - * - * - The above copyright notice and this permission notice must appear - * in all copies of the software and related documentation. - * - * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES, - * EXPRESSED OR IMPLIED. USE IT AT YOUR OWN RISK. - ********************************************************************/ -// -*- c++ -*- -#ifndef _cvcl__include__c_interface_h_ -#define _cvcl__include__c_interface_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef STP_STRONG_TYPING -#else - //This gives absolutely no pointer typing at compile-time. Most C - //users prefer this over stronger typing. User is the king. A - //stronger typed interface is in the works. - typedef void* VC; - typedef void* Expr; - typedef void* Type; - typedef void* WholeCounterExample; -#endif - - // o : optimizations - // c : check counterexample - // p : print counterexample - // h : help - // s : stats - // v : print nodes - void vc_setFlags(char c); - - //! Flags can be NULL - VC vc_createValidityChecker(void); - - // Basic types - Type vc_boolType(VC vc); - - //! Create an array type - Type vc_arrayType(VC vc, Type typeIndex, Type typeData); - - ///////////////////////////////////////////////////////////////////////////// - // Expr manipulation methods // - ///////////////////////////////////////////////////////////////////////////// - - //! Create a variable with a given name and type - /*! The type cannot be a function type. The var name can contain - only variables, numerals and underscore. If you use any other - symbol, you will get a segfault. */ - Expr vc_varExpr(VC vc, char * name, Type type); - - //The var name can contain only variables, numerals and - //underscore. If you use any other symbol, you will get a segfault. - Expr vc_varExpr1(VC vc, char* name, - int indexwidth, int valuewidth); - - //! Get the expression and type associated with a name. - /*! If there is no such Expr, a NULL Expr is returned. */ - //Expr vc_lookupVar(VC vc, char* name, Type* type); - - //! Get the type of the Expr. - Type vc_getType(VC vc, Expr e); - - int vc_getBVLength(VC vc, Expr e); - - //! Create an equality expression. The two children must have the same type. - Expr vc_eqExpr(VC vc, Expr child0, Expr child1); - - // Boolean expressions - - // The following functions create Boolean expressions. The children - // provided as arguments must be of type Boolean (except for the - // function vc_iteExpr(). In the case of vc_iteExpr() the - // conditional must always be Boolean, but the ifthenpart - // (resp. elsepart) can be bit-vector or Boolean type. But, the - // ifthenpart and elsepart must be both of the same type) - Expr vc_trueExpr(VC vc); - Expr vc_falseExpr(VC vc); - Expr vc_notExpr(VC vc, Expr child); - Expr vc_andExpr(VC vc, Expr left, Expr right); - Expr vc_andExprN(VC vc, Expr* children, int numOfChildNodes); - Expr vc_orExpr(VC vc, Expr left, Expr right); - Expr vc_orExprN(VC vc, Expr* children, int numOfChildNodes); - Expr vc_impliesExpr(VC vc, Expr hyp, Expr conc); - Expr vc_iffExpr(VC vc, Expr left, Expr right); - //The output type of vc_iteExpr can be Boolean (formula-level ite) - //or bit-vector (word-level ite) - Expr vc_iteExpr(VC vc, Expr conditional, Expr ifthenpart, Expr elsepart); - - //Boolean to single bit BV Expression - Expr vc_boolToBVExpr(VC vc, Expr form); - - // Arrays - - //! Create an expression for the value of array at the given index - Expr vc_readExpr(VC vc, Expr array, Expr index); - - //! Array update; equivalent to "array WITH [index] := newValue" - Expr vc_writeExpr(VC vc, Expr array, Expr index, Expr newValue); - - // Expr I/O - //! Expr vc_parseExpr(VC vc, char* s); - - //! Prints 'e' to stdout. - void vc_printExpr(VC vc, Expr e); - - //! Prints 'e' into an open file descriptor 'fd' - void vc_printExprFile(VC vc, Expr e, int fd); - - //! Prints state of 'vc' into malloc'd buffer '*buf' and stores the - // length into '*len'. It is the responsibility of the caller to - // free the buffer. - //void vc_printStateToBuffer(VC vc, char **buf, unsigned long *len); - - //! Prints 'e' to malloc'd buffer '*buf'. Sets '*len' to the length of - // the buffer. It is the responsibility of the caller to free the buffer. - void vc_printExprToBuffer(VC vc, Expr e, char **buf, unsigned long * len); - - //! Prints counterexample to stdout. - void vc_printCounterExample(VC vc); - - //! Prints variable declarations to stdout. - void vc_printVarDecls(VC vc); - - //! Prints asserts to stdout. The flag simplify_print must be set to - //"1" if you wish simplification to occur dring printing. It must be - //set to "0" otherwise - void vc_printAsserts(VC vc, int simplify_print); - - //! Prints the state of the query to malloc'd buffer '*buf' and - //stores ! the length of the buffer to '*len'. It is the - //responsibility of the caller to free the buffer. The flag - //simplify_print must be set to "1" if you wish simplification to - //occur dring printing. It must be set to "0" otherwise - void vc_printQueryStateToBuffer(VC vc, Expr e, - char **buf, unsigned long *len, int simplify_print); - - //! Similar to vc_printQueryStateToBuffer() - void vc_printCounterExampleToBuffer(VC vc, char **buf,unsigned long *len); - - //! Prints query to stdout. - void vc_printQuery(VC vc); - - ///////////////////////////////////////////////////////////////////////////// - // Context-related methods // - ///////////////////////////////////////////////////////////////////////////// - - //! Assert a new formula in the current context. - /*! The formula must have Boolean type. */ - void vc_assertFormula(VC vc, Expr e); - - //! Simplify e with respect to the current context - Expr vc_simplify(VC vc, Expr e); - - //! Check validity of e in the current context. e must be a FORMULA - // - //if returned 0 then input is INVALID. - // - //if returned 1 then input is VALID - // - //if returned 2 then ERROR - int vc_query(VC vc, Expr e); - - //! Return the counterexample after a failed query. - Expr vc_getCounterExample(VC vc, Expr e); - - //! get size of counterexample, i.e. the number of variables/array - //locations in the counterexample. - int vc_counterexample_size(VC vc); - - //! Checkpoint the current context and increase the scope level - void vc_push(VC vc); - - //! Restore the current context to its state at the last checkpoint - void vc_pop(VC vc); - - //! Return an int from a constant bitvector expression - int getBVInt(Expr e); - //! Return an unsigned int from a constant bitvector expression - unsigned int getBVUnsigned(Expr e); - //! Return an unsigned long long int from a constant bitvector expressions - unsigned long long int getBVUnsignedLongLong(Expr e); - - /**************************/ - /* BIT VECTOR OPERATIONS */ - /**************************/ - Type vc_bvType(VC vc, int no_bits); - Type vc_bv32Type(VC vc); - - Expr vc_bvConstExprFromStr(VC vc, char* binary_repr); - Expr vc_bvConstExprFromInt(VC vc, int n_bits, unsigned int value); - Expr vc_bvConstExprFromLL(VC vc, int n_bits, unsigned long long value); - Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value); - - Expr vc_bvConcatExpr(VC vc, Expr left, Expr right); - Expr vc_bvPlusExpr(VC vc, int n_bits, Expr left, Expr right); - Expr vc_bv32PlusExpr(VC vc, Expr left, Expr right); - Expr vc_bvMinusExpr(VC vc, int n_bits, Expr left, Expr right); - Expr vc_bv32MinusExpr(VC vc, Expr left, Expr right); - Expr vc_bvMultExpr(VC vc, int n_bits, Expr left, Expr right); - Expr vc_bv32MultExpr(VC vc, Expr left, Expr right); - // left divided by right i.e. left/right - Expr vc_bvDivExpr(VC vc, int n_bits, Expr left, Expr right); - // left modulo right i.e. left%right - Expr vc_bvModExpr(VC vc, int n_bits, Expr left, Expr right); - // signed left divided by right i.e. left/right - Expr vc_sbvDivExpr(VC vc, int n_bits, Expr left, Expr right); - // signed left modulo right i.e. left%right - Expr vc_sbvModExpr(VC vc, int n_bits, Expr left, Expr right); - - Expr vc_bvLtExpr(VC vc, Expr left, Expr right); - Expr vc_bvLeExpr(VC vc, Expr left, Expr right); - Expr vc_bvGtExpr(VC vc, Expr left, Expr right); - Expr vc_bvGeExpr(VC vc, Expr left, Expr right); - - Expr vc_sbvLtExpr(VC vc, Expr left, Expr right); - Expr vc_sbvLeExpr(VC vc, Expr left, Expr right); - Expr vc_sbvGtExpr(VC vc, Expr left, Expr right); - Expr vc_sbvGeExpr(VC vc, Expr left, Expr right); - - Expr vc_bvUMinusExpr(VC vc, Expr child); - - // bitwise operations: these are terms not formulas - Expr vc_bvAndExpr(VC vc, Expr left, Expr right); - Expr vc_bvOrExpr(VC vc, Expr left, Expr right); - Expr vc_bvXorExpr(VC vc, Expr left, Expr right); - Expr vc_bvNotExpr(VC vc, Expr child); - - Expr vc_bvLeftShiftExpr(VC vc, int sh_amt, Expr child); - Expr vc_bvRightShiftExpr(VC vc, int sh_amt, Expr child); - /* Same as vc_bvLeftShift only that the answer in 32 bits long */ - Expr vc_bv32LeftShiftExpr(VC vc, int sh_amt, Expr child); - /* Same as vc_bvRightShift only that the answer in 32 bits long */ - Expr vc_bv32RightShiftExpr(VC vc, int sh_amt, Expr child); - Expr vc_bvVar32LeftShiftExpr(VC vc, Expr sh_amt, Expr child); - Expr vc_bvVar32RightShiftExpr(VC vc, Expr sh_amt, Expr child); - Expr vc_bvVar32DivByPowOfTwoExpr(VC vc, Expr child, Expr rhs); - - Expr vc_bvExtract(VC vc, Expr child, int high_bit_no, int low_bit_no); - - //accepts a bitvector and position, and returns a boolean - //corresponding to that position. More precisely, it return the - //equation (x[bit_no:bit_no] = 0) - //FIXME = 1 ? - Expr vc_bvBoolExtract(VC vc, Expr x, int bit_no); - Expr vc_bvSignExtend(VC vc, Expr child, int nbits); - - /*C pointer support: C interface to support C memory arrays in CVCL */ - Expr vc_bvCreateMemoryArray(VC vc, char * arrayName); - Expr vc_bvReadMemoryArray(VC vc, - Expr array, Expr byteIndex, int numOfBytes); - Expr vc_bvWriteToMemoryArray(VC vc, - Expr array, Expr byteIndex, - Expr element, int numOfBytes); - Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value); - - // return a string representation of the Expr e. The caller is responsible - // for deallocating the string with free() - char* exprString(Expr e); - - // return a string representation of the Type t. The caller is responsible - // for deallocating the string with free() - char* typeString(Type t); - - Expr getChild(Expr e, int i); - - //1.if input expr is TRUE then the function returns 1; - // - //2.if input expr is FALSE then function returns 0; - // - //3.otherwise the function returns -1 - int vc_isBool(Expr e); - - /* Register the given error handler to be called for each fatal error.*/ - void vc_registerErrorHandler(void (*error_hdlr)(const char* err_msg)); - - int vc_getHashQueryStateToBuffer(VC vc, Expr query); - - //destroys the STP instance, and removes all the created expressions - void vc_Destroy(VC vc); - - //deletes the expression e - void vc_DeleteExpr(Expr e); - - //Get the whole counterexample from the current context - WholeCounterExample vc_getWholeCounterExample(VC vc); - - //Get the value of a term expression from the CounterExample - Expr vc_getTermFromCounterExample(VC vc, Expr e, WholeCounterExample c); - - //Kinds of Expr - enum exprkind_t{ - UNDEFINED, - SYMBOL, - BVCONST, - BVNEG, - BVCONCAT, - BVOR, - BVAND, - BVXOR, - BVNAND, - BVNOR, - BVXNOR, - BVEXTRACT, - BVLEFTSHIFT, - BVRIGHTSHIFT, - BVSRSHIFT, - BVVARSHIFT, - BVPLUS, - BVSUB, - BVUMINUS, - BVMULTINVERSE, - BVMULT, - BVDIV, - BVMOD, - SBVDIV, - SBVMOD, - BVSX, - BOOLVEC, - ITE, - BVGETBIT, - BVLT, - BVLE, - BVGT, - BVGE, - BVSLT, - BVSLE, - BVSGT, - BVSGE, - EQ, - NEQ, - FALSE, - TRUE, - NOT, - AND, - OR, - NAND, - NOR, - XOR, - IFF, - IMPLIES, - READ, - WRITE, - ARRAY, - BITVECTOR, - BOOLEAN - }; - - // type of expression - enum type_t { - BOOLEAN_TYPE = 0, - BITVECTOR_TYPE, - ARRAY_TYPE, - UNKNOWN_TYPE - }; - - // get the kind of the expression - exprkind_t getExprKind (Expr e); - - // get the number of children nodes - int getDegree (Expr e); - - // get the bv length - int getBVLength(Expr e); - - // get expression type - type_t getType (Expr e); - - // get value bit width - int getVWidth (Expr e); - - // get index bit width - int getIWidth (Expr e); - - // Prints counterexample to an open file descriptor 'fd' - void vc_printCounterExampleFile(VC vc, int fd); - - // get name of expression. must be a variable. - const char* exprName(Expr e); - - // get the node ID of an Expr. - int getExprID (Expr ex); - -#ifdef __cplusplus -} -#endif - -#endif - - diff --git a/stp/c_interface/fdstream.h b/stp/c_interface/fdstream.h deleted file mode 100644 index 2cff613c..00000000 --- a/stp/c_interface/fdstream.h +++ /dev/null @@ -1,186 +0,0 @@ -/*! @brief The following code declares classes to read from and write to - * file descriptore or file handles. - * - * See - * http://www.josuttis.com/cppcode - * for details and the latest version. - * - * - open: - * - integrating BUFSIZ on some systems? - * - optimized reading of multiple characters - * - stream for reading AND writing - * - i18n - * - * (C) Copyright Nicolai M. Josuttis 2001. - * Permission to copy, use, modify, sell and distribute this software - * is granted provided this copyright notice appears in all copies. - * This software is provided "as is" without express or implied - * warranty, and with no claim as to its suitability for any purpose. - * - * Version: Jul 28, 2002 - * History: - * Jul 28, 2002: bugfix memcpy() => memmove() - * fdinbuf::underflow(): cast for return statements - * Aug 05, 2001: first public version - */ -#ifndef BOOST_FDSTREAM_HPP -#define BOOST_FDSTREAM_HPP - -#include <istream> -#include <ostream> -#include <streambuf> - - -// for EOF: -#include <cstdio> -// for memmove(): -#include <cstring> - - -// low-level read and write functions -#ifdef _MSC_VER -# include <io.h> -#else -# include <unistd.h> -//extern "C" { -// int write (int fd, const char* buf, int num); -// int read (int fd, char* buf, int num); -//} -#endif - - -// BEGIN namespace BOOST -namespace std { - - -/************************************************************ - * fdostream - * - a stream that writes on a file descriptor - ************************************************************/ - - -class fdoutbuf : public std::streambuf { - protected: - int fd; // file descriptor - public: - // constructor - fdoutbuf (int _fd) : fd(_fd) { - } - protected: - // write one character - virtual int_type overflow (int_type c) { - if (c != EOF) { - char z = c; - if (write (fd, &z, 1) != 1) { - return EOF; - } - } - return c; - } - // write multiple characters - virtual - std::streamsize xsputn (const char* s, - std::streamsize num) { - return write(fd,s,num); - } -}; - -class fdostream : public std::ostream { - protected: - fdoutbuf buf; - public: - fdostream (int fd) : std::ostream(0), buf(fd) { - rdbuf(&buf); - } -}; - - -/************************************************************ - * fdistream - * - a stream that reads on a file descriptor - ************************************************************/ - -class fdinbuf : public std::streambuf { - protected: - int fd; // file descriptor - protected: - /* data buffer: - * - at most, pbSize characters in putback area plus - * - at most, bufSize characters in ordinary read buffer - */ - static const int pbSize = 4; // size of putback area - static const int bufSize = 1024; // size of the data buffer - char buffer[bufSize+pbSize]; // data buffer - - public: - /* constructor - * - initialize file descriptor - * - initialize empty data buffer - * - no putback area - * => force underflow() - */ - fdinbuf (int _fd) : fd(_fd) { - setg (buffer+pbSize, // beginning of putback area - buffer+pbSize, // read position - buffer+pbSize); // end position - } - - protected: - // insert new characters into the buffer - virtual int_type underflow () { -#ifndef _MSC_VER - using std::memmove; -#endif - - // is read position before end of buffer? - if (gptr() < egptr()) { - return traits_type::to_int_type(*gptr()); - } - - /* process size of putback area - * - use number of characters read - * - but at most size of putback area - */ - int numPutback; - numPutback = gptr() - eback(); - if (numPutback > pbSize) { - numPutback = pbSize; - } - - /* copy up to pbSize characters previously read into - * the putback area - */ - memmove (buffer+(pbSize-numPutback), gptr()-numPutback, - numPutback); - - // read at most bufSize new characters - int num; - num = read (fd, buffer+pbSize, bufSize); - if (num <= 0) { - // ERROR or EOF - return EOF; - } - - // reset buffer pointers - setg (buffer+(pbSize-numPutback), // beginning of putback area - buffer+pbSize, // read position - buffer+pbSize+num); // end of buffer - - // return next character - return traits_type::to_int_type(*gptr()); - } -}; - -class fdistream : public std::istream { - protected: - fdinbuf buf; - public: - fdistream (int fd) : std::istream(0), buf(fd) { - rdbuf(&buf); - } -}; - - -} // END namespace boost - -#endif /*BOOST_FDSTREAM_HPP*/ diff --git a/stp/constantbv/Makefile b/stp/constantbv/Makefile deleted file mode 100644 index ee8155cf..00000000 --- a/stp/constantbv/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -#===-- stp/constantbv/Makefile -----------------------------*- Makefile -*--===# -# -# The KLEE Symbolic Virtual Machine -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -LEVEL=../.. - -LIBRARYNAME=stp_constantbv -DONT_BUILD_RELINKED=1 -BUILD_ARCHIVE=1 - -include $(LEVEL)/Makefile.common diff --git a/stp/constantbv/constantbv.cpp b/stp/constantbv/constantbv.cpp deleted file mode 100644 index e01fa0ac..00000000 --- a/stp/constantbv/constantbv.cpp +++ /dev/null @@ -1,3571 +0,0 @@ -/*****************************************************************************/ -/* AUTHOR: */ -/*****************************************************************************/ -/* */ -/* Steffen Beyer */ -/* mailto:sb@engelschall.com */ -/* http://www.engelschall.com/u/sb/download/ */ -/* */ -/*****************************************************************************/ -/* COPYRIGHT: */ -/*****************************************************************************/ -/* */ -/* Copyright (c) 1995 - 2004 by Steffen Beyer. */ -/* All rights reserved. */ -/* */ -/*****************************************************************************/ -/* LICENSE: */ -/*****************************************************************************/ -/* */ -/* This library is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU Library General Public */ -/* License as published by the Free Software Foundation; either */ -/* version 2 of the License, || (at your option) any later version. */ -/* */ -/* This library is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY || FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ -/* Library General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU Library General Public */ -/* License along with this library; if not, write to the */ -/* Free Software Foundation, Inc., */ -/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* */ -/* || download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */ -/* */ -/*****************************************************************************/ - -/*****************************************************************************/ -/* MODULE NAME: constantbv.cpp MODULE TYPE:constantbv*/ -/*****************************************************************************/ -/* MODULE IMPORTS: */ -/*****************************************************************************/ -#include <stdio.h> -#include <stdlib.h> /* MODULE TYPE: (sys) */ -#include <limits.h> /* MODULE TYPE: (sys) */ -#include <string.h> /* MODULE TYPE: (sys) */ -#include <ctype.h> /* MODULE TYPE: (sys) */ -#include "constantbv.h" - -namespace CONSTANTBV { -/*****************************************************************************/ -/* MODULE IMPLEMENTATION: */ -/*****************************************************************************/ - /**********************************************/ - /* global implementation-intrinsic constants: */ - /**********************************************/ - -#define BIT_VECTOR_HIDDEN_WORDS 3 - - /*****************************************************************/ - /* global machine-dependent constants (set by "BitVector_Boot"): */ - /*****************************************************************/ - -static unsigned int BITS; /* = # of bits in machine word (must be power of 2) */ -static unsigned int MODMASK; /* = BITS - 1 (mask for calculating modulo BITS) */ -static unsigned int LOGBITS; /* = ld(BITS) (logarithmus dualis) */ -static unsigned int FACTOR; /* = ld(BITS / 8) (ld of # of bytes) */ - -static unsigned int LSB = 1; /* = mask for least significant bit */ -static unsigned int MSB; /* = mask for most significant bit */ - -static unsigned int LONGBITS; /* = # of bits in unsigned long */ - -static unsigned int LOG10; /* = logarithm to base 10 of BITS - 1 */ -static unsigned int EXP10; /* = largest possible power of 10 in signed int */ - - /********************************************************************/ - /* global bit mask table for fast access (set by "BitVector_Boot"): */ - /********************************************************************/ - -static unsigned int * BITMASKTAB; - - /*****************************/ - /* global macro definitions: */ - /*****************************/ - -#define BIT_VECTOR_ZERO_WORDS(target,count) \ - while (count-- > 0) *target++ = 0; - -#define BIT_VECTOR_FILL_WORDS(target,fill,count) \ - while (count-- > 0) *target++ = fill; - -#define BIT_VECTOR_FLIP_WORDS(target,flip,count) \ - while (count-- > 0) *target++ ^= flip; - -#define BIT_VECTOR_COPY_WORDS(target,source,count) \ - while (count-- > 0) *target++ = *source++; - -#define BIT_VECTOR_BACK_WORDS(target,source,count) \ - { target += count; source += count; while (count-- > 0) *--target = *--source; } - -#define BIT_VECTOR_CLR_BIT(address,index) \ - *(address+(index>>LOGBITS)) &= ~ BITMASKTAB[index & MODMASK]; - -#define BIT_VECTOR_SET_BIT(address,index) \ - *(address+(index>>LOGBITS)) |= BITMASKTAB[index & MODMASK]; - -#define BIT_VECTOR_TST_BIT(address,index) \ - ((*(address+(index>>LOGBITS)) & BITMASKTAB[index & MODMASK]) != 0) - -#define BIT_VECTOR_FLP_BIT(address,index,mask) \ - (mask = BITMASKTAB[index & MODMASK]), \ - (((*(addr+(index>>LOGBITS)) ^= mask) & mask) != 0) - -#define BIT_VECTOR_DIGITIZE(type,value,digit) \ - value = (type) ((digit = value) / 10); \ - digit -= value * 10; \ - digit += (type) '0'; - - /*********************************************************/ - /* private low-level functions (potentially dangerous!): */ - /*********************************************************/ - -static unsigned int power10(unsigned int x) { - unsigned int y = 1; - - while (x-- > 0) y *= 10; - return(y); -} - -static void BIT_VECTOR_zro_words(unsigned int * addr, unsigned int count) { - BIT_VECTOR_ZERO_WORDS(addr,count) -} - -static void BIT_VECTOR_cpy_words(unsigned int * target, - unsigned int * source, unsigned int count) { - BIT_VECTOR_COPY_WORDS(target,source,count) -} - -static void BIT_VECTOR_mov_words(unsigned int * target, - unsigned int * source, unsigned int count) { - if (target != source) { - if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count) - else BIT_VECTOR_BACK_WORDS(target,source,count) - } -} - -static void BIT_VECTOR_ins_words(unsigned int * addr, - unsigned int total, unsigned int count, boolean clear) { - unsigned int length; - - if ((total > 0) && (count > 0)) { - if (count > total) count = total; - length = total - count; - if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length); - if (clear) BIT_VECTOR_zro_words(addr,count); - } -} - -static void BIT_VECTOR_del_words(unsigned int * addr, - unsigned int total, unsigned int count, boolean clear) { - unsigned int length; - - if ((total > 0) && (count > 0)) { - if (count > total) count = total; - length = total - count; - if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length); - if (clear) BIT_VECTOR_zro_words(addr+length,count); - } -} - -static void BIT_VECTOR_reverse(unsigned char * string, unsigned int length) { - unsigned char * last; - unsigned char temp; - - if (length > 1) { - last = string + length - 1; - while (string < last) { - temp = *string; - *string = *last; - *last = temp; - string++; - last--; - } - } -} - -static unsigned int BIT_VECTOR_int2str(unsigned char * string, unsigned int value) { - unsigned int length; - unsigned int digit; - unsigned char * work; - - work = string; - if (value > 0) { - length = 0; - while (value > 0) { - BIT_VECTOR_DIGITIZE(unsigned int,value,digit) - *work++ = (unsigned char) digit; - length++; - } - BIT_VECTOR_reverse(string,length); - } - else { - length = 1; - *work++ = (unsigned char) '0'; - } - return(length); -} - -static unsigned int BIT_VECTOR_str2int(unsigned char * string, unsigned int *value) { - unsigned int length; - unsigned int digit; - - *value = 0; - length = 0; - digit = (unsigned int) *string++; - /* separate because isdigit() is likely a macro! */ - while (isdigit((int)digit) != 0) { - length++; - digit -= (unsigned int) '0'; - if (*value) *value *= 10; - *value += digit; - digit = (unsigned int) *string++; - } - return(length); -} - - /********************************************/ - /* routine to convert error code to string: */ - /********************************************/ - -unsigned char * BitVector_Error(ErrCode error) { - switch (error) { - case ErrCode_Ok: return( (unsigned char *) NULL ); break; - case ErrCode_Type: return( (unsigned char *) ERRCODE_TYPE ); break; - case ErrCode_Bits: return( (unsigned char *) ERRCODE_BITS ); break; - case ErrCode_Word: return( (unsigned char *) ERRCODE_WORD ); break; - case ErrCode_Long: return( (unsigned char *) ERRCODE_LONG ); break; - case ErrCode_Powr: return( (unsigned char *) ERRCODE_POWR ); break; - case ErrCode_Loga: return( (unsigned char *) ERRCODE_LOGA ); break; - case ErrCode_Null: return( (unsigned char *) ERRCODE_NULL ); break; - case ErrCode_Indx: return( (unsigned char *) ERRCODE_INDX ); break; - case ErrCode_Ordr: return( (unsigned char *) ERRCODE_ORDR ); break; - case ErrCode_Size: return( (unsigned char *) ERRCODE_SIZE ); break; - case ErrCode_Pars: return( (unsigned char *) ERRCODE_PARS ); break; - case ErrCode_Ovfl: return( (unsigned char *) ERRCODE_OVFL ); break; - case ErrCode_Same: return( (unsigned char *) ERRCODE_SAME ); break; - case ErrCode_Expo: return( (unsigned char *) ERRCODE_EXPO ); break; - case ErrCode_Zero: return( (unsigned char *) ERRCODE_ZERO ); break; - default: return( (unsigned char *) ERRCODE_OOPS ); break; - } -} - - /*****************************************/ - /* automatic self-configuration routine: */ - /*****************************************/ - - /*******************************************************/ - /* */ - /* MUST be called once prior to any other function */ - /* to initialize the machine dependent constants */ - /* of this package! (But call only ONCE, or you */ - /* will suffer memory leaks!) */ - /* */ - /*******************************************************/ - -ErrCode BitVector_Boot(void) { - unsigned long longsample = 1L; - unsigned int sample = LSB; - unsigned int lsb; - - if (sizeof(unsigned int) > sizeof(size_t)) return(ErrCode_Type); - - BITS = 1; - while (sample <<= 1) BITS++; /* determine # of bits in a machine word */ - - if (BITS != (sizeof(unsigned int) << 3)) return(ErrCode_Bits); - - if (BITS < 16) return(ErrCode_Word); - - LONGBITS = 1; - while (longsample <<= 1) LONGBITS++; /* = # of bits in an unsigned long */ - - if (BITS > LONGBITS) return(ErrCode_Long); - - LOGBITS = 0; - sample = BITS; - lsb = (sample & LSB); - while ((sample >>= 1) && (! lsb)) { - LOGBITS++; - lsb = (sample & LSB); - } - - if (sample) return(ErrCode_Powr); /* # of bits is not a power of 2! */ - - if (BITS != (LSB << LOGBITS)) return(ErrCode_Loga); - - MODMASK = BITS - 1; - FACTOR = LOGBITS - 3; /* ld(BITS / 8) = ld(BITS) - ld(8) = ld(BITS) - 3 */ - MSB = (LSB << MODMASK); - - BITMASKTAB = (unsigned int * ) malloc((size_t) (BITS << FACTOR)); - - if (BITMASKTAB == NULL) return(ErrCode_Null); - - for ( sample = 0; sample < BITS; sample++ ) { - BITMASKTAB[sample] = (LSB << sample); - } - - LOG10 = (unsigned int) (MODMASK * 0.30103); /* = (BITS - 1) * ( ln 2 / ln 10 ) */ - EXP10 = power10(LOG10); - - return(ErrCode_Ok); -} - -unsigned int BitVector_Size(unsigned int bits) { /* bit vector size (# of words) */ - unsigned int size; - - size = bits >> LOGBITS; - if (bits & MODMASK) size++; - return(size); -} - -unsigned int BitVector_Mask(unsigned int bits) /* bit vector mask (unused bits) */ -{ - unsigned int mask; - - mask = bits & MODMASK; - if (mask) mask = (unsigned int) ~(~0L << mask); else mask = (unsigned int) ~0L; - return(mask); -} - -unsigned char * BitVector_Version(void) -{ - return((unsigned char *)"6.4"); -} - -unsigned int BitVector_Word_Bits(void) -{ - return(BITS); -} - -unsigned int BitVector_Long_Bits(void) -{ - return(LONGBITS); -} - -/********************************************************************/ -/* */ -/* WARNING: Do not "free()" constant character strings, i.e., */ -/* don't call "BitVector_Dispose()" for strings returned */ -/* by "BitVector_Error()" or "BitVector_Version()"! */ -/* */ -/* ONLY call this function for strings allocated with "malloc()", */ -/* i.e., the strings returned by the functions "BitVector_to_*()" */ -/* and "BitVector_Block_Read()"! */ -/* */ -/********************************************************************/ - -void BitVector_Dispose(unsigned char * string) /* free string */ -{ - if (string != NULL) free((void *) string); -} - -void BitVector_Destroy(unsigned int * addr) /* free bitvec */ -{ - if (addr != NULL) - { - addr -= BIT_VECTOR_HIDDEN_WORDS; - free((void *) addr); - } -} - -void BitVector_Destroy_List(unsigned int * * list, unsigned int count) /* free list */ -{ - unsigned int * * slot; - - if (list != NULL) - { - slot = list; - while (count-- > 0) - { - BitVector_Destroy(*slot++); - } - free((void *) list); - } -} - -unsigned int * BitVector_Create(unsigned int bits, boolean clear) /* malloc */ -{ - unsigned int size; - unsigned int mask; - unsigned int bytes; - unsigned int * addr; - unsigned int * zero; - - size = BitVector_Size(bits); - mask = BitVector_Mask(bits); - bytes = (size + BIT_VECTOR_HIDDEN_WORDS) << FACTOR; - addr = (unsigned int * ) malloc((size_t) bytes); - if (addr != NULL) - { - *addr++ = bits; - *addr++ = size; - *addr++ = mask; - if (clear) - { - zero = addr; - BIT_VECTOR_ZERO_WORDS(zero,size) - } - } - return(addr); -} - -unsigned int * * BitVector_Create_List(unsigned int bits, boolean clear, unsigned int count) -{ - unsigned int * * list = NULL; - unsigned int * * slot; - unsigned int * addr; - unsigned int i; - - if (count > 0) - { - list = (unsigned int * * ) malloc(sizeof(unsigned int * ) * count); - if (list != NULL) - { - slot = list; - for ( i = 0; i < count; i++ ) - { - addr = BitVector_Create(bits,clear); - if (addr == NULL) - { - BitVector_Destroy_List(list,i); - return(NULL); - } - *slot++ = addr; - } - } - } - return(list); -} - -unsigned int * BitVector_Resize(unsigned int * oldaddr, unsigned int bits) /* realloc */ -{ - unsigned int bytes; - unsigned int oldsize; - unsigned int oldmask; - unsigned int newsize; - unsigned int newmask; - unsigned int * newaddr; - unsigned int * source; - unsigned int * target; - - oldsize = size_(oldaddr); - oldmask = mask_(oldaddr); - newsize = BitVector_Size(bits); - newmask = BitVector_Mask(bits); - if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask; - if (newsize <= oldsize) - { - newaddr = oldaddr; - bits_(newaddr) = bits; - size_(newaddr) = newsize; - mask_(newaddr) = newmask; - if (newsize > 0) *(newaddr+newsize-1) &= newmask; - } - else - { - bytes = (newsize + BIT_VECTOR_HIDDEN_WORDS) << FACTOR; - newaddr = (unsigned int * ) malloc((size_t) bytes); - if (newaddr != NULL) - { - *newaddr++ = bits; - *newaddr++ = newsize; - *newaddr++ = newmask; - target = newaddr; - source = oldaddr; - newsize -= oldsize; - BIT_VECTOR_COPY_WORDS(target,source,oldsize) - BIT_VECTOR_ZERO_WORDS(target,newsize) - } - BitVector_Destroy(oldaddr); - } - return(newaddr); -} - -unsigned int * BitVector_Shadow(unsigned int * addr) /* makes new, same size but empty */ -{ - return( BitVector_Create(bits_(addr),true) ); -} - -unsigned int * BitVector_Clone(unsigned int * addr) /* makes exact duplicate */ -{ - unsigned int bits; - unsigned int * twin; - - bits = bits_(addr); - twin = BitVector_Create(bits,false); - if ((twin != NULL) && (bits > 0)) - BIT_VECTOR_cpy_words(twin,addr,size_(addr)); - return(twin); -} - -unsigned int * BitVector_Concat(unsigned int * X, unsigned int * Y) /* returns concatenation */ -{ - /* BEWARE that X = most significant part, Y = least significant part! */ - - unsigned int bitsX; - unsigned int bitsY; - unsigned int bitsZ; - unsigned int * Z; - - bitsX = bits_(X); - bitsY = bits_(Y); - bitsZ = bitsX + bitsY; - Z = BitVector_Create(bitsZ,false); - if ((Z != NULL) && (bitsZ > 0)) - { - BIT_VECTOR_cpy_words(Z,Y,size_(Y)); - BitVector_Interval_Copy(Z,X,bitsY,0,bitsX); - *(Z+size_(Z)-1) &= mask_(Z); - } - return(Z); -} - -void BitVector_Copy(unsigned int * X, unsigned int * Y) /* X = Y */ -{ - unsigned int sizeX = size_(X); - unsigned int sizeY = size_(Y); - unsigned int maskX = mask_(X); - unsigned int maskY = mask_(Y); - unsigned int fill = 0; - unsigned int * lastX; - unsigned int * lastY; - - if ((X != Y) && (sizeX > 0)) - { - lastX = X + sizeX - 1; - if (sizeY > 0) - { - lastY = Y + sizeY - 1; - if ( (*lastY & (maskY & ~ (maskY >> 1))) == 0 ) *lastY &= maskY; - else - { - fill = (unsigned int) ~0L; - *lastY |= ~ maskY; - } - while ((sizeX > 0) && (sizeY > 0)) - { - *X++ = *Y++; - sizeX--; - sizeY--; - } - *lastY &= maskY; - } - while (sizeX-- > 0) *X++ = fill; - *lastX &= maskX; - } -} - -void BitVector_Empty(unsigned int * addr) /* X = {} clr all */ -{ - unsigned int size = size_(addr); - - BIT_VECTOR_ZERO_WORDS(addr,size) -} - -void BitVector_Fill(unsigned int * addr) /* X = ~{} set all */ -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int fill = (unsigned int) ~0L; - - if (size > 0) - { - BIT_VECTOR_FILL_WORDS(addr,fill,size) - *(--addr) &= mask; - } -} - -void BitVector_Flip(unsigned int * addr) /* X = ~X flip all */ -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int flip = (unsigned int) ~0L; - - if (size > 0) - { - BIT_VECTOR_FLIP_WORDS(addr,flip,size) - *(--addr) &= mask; - } -} - -void BitVector_Primes(unsigned int * addr) -{ - unsigned int bits = bits_(addr); - unsigned int size = size_(addr); - unsigned int * work; - unsigned int temp; - unsigned int i,j; - - if (size > 0) - { - temp = 0xAAAA; - i = BITS >> 4; - while (--i > 0) - { - temp <<= 16; - temp |= 0xAAAA; - } - i = size; - work = addr; - *work++ = temp ^ 0x0006; - while (--i > 0) *work++ = temp; - for ( i = 3; (j = i * i) < bits; i += 2 ) - { - for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j) - } - *(addr+size-1) &= mask_(addr); - } -} - -void BitVector_Reverse(unsigned int * X, unsigned int * Y) -{ - unsigned int bits = bits_(X); - unsigned int mask; - unsigned int bit; - unsigned int value; - - if (bits > 0) - { - if (X == Y) BitVector_Interval_Reverse(X,0,bits-1); - else if (bits == bits_(Y)) - { -/* mask = mask_(Y); */ -/* mask &= ~ (mask >> 1); */ - mask = BITMASKTAB[(bits-1) & MODMASK]; - Y += size_(Y) - 1; - value = 0; - bit = LSB; - while (bits-- > 0) - { - if ((*Y & mask) != 0) - { - value |= bit; - } - if (! (mask >>= 1)) - { - Y--; - mask = MSB; - } - if (! (bit <<= 1)) - { - *X++ = value; - value = 0; - bit = LSB; - } - } - if (bit > LSB) *X = value; - } - } -} - -void BitVector_Interval_Empty(unsigned int * addr, unsigned int lower, unsigned int upper) -{ /* X = X \ [lower..upper] */ - unsigned int bits = bits_(addr); - unsigned int size = size_(addr); - unsigned int * loaddr; - unsigned int * hiaddr; - unsigned int lobase; - unsigned int hibase; - unsigned int lomask; - unsigned int himask; - unsigned int diff; - - if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper)) - { - lobase = lower >> LOGBITS; - hibase = upper >> LOGBITS; - diff = hibase - lobase; - loaddr = addr + lobase; - hiaddr = addr + hibase; - - lomask = (unsigned int) (~0L << (lower & MODMASK)); - himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1); - - if (diff == 0) - { - *loaddr &= ~ (lomask & himask); - } - else - { - *loaddr++ &= ~ lomask; - while (--diff > 0) - { - *loaddr++ = 0; - } - *hiaddr &= ~ himask; - } - } -} - -void BitVector_Interval_Fill(unsigned int * addr, unsigned int lower, unsigned int upper) -{ /* X = X + [lower..upper] */ - unsigned int bits = bits_(addr); - unsigned int size = size_(addr); - unsigned int fill = (unsigned int) ~0L; - unsigned int * loaddr; - unsigned int * hiaddr; - unsigned int lobase; - unsigned int hibase; - unsigned int lomask; - unsigned int himask; - unsigned int diff; - - if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper)) - { - lobase = lower >> LOGBITS; - hibase = upper >> LOGBITS; - diff = hibase - lobase; - loaddr = addr + lobase; - hiaddr = addr + hibase; - - lomask = (unsigned int) (~0L << (lower & MODMASK)); - himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1); - - if (diff == 0) - { - *loaddr |= (lomask & himask); - } - else - { - *loaddr++ |= lomask; - while (--diff > 0) - { - *loaddr++ = fill; - } - *hiaddr |= himask; - } - *(addr+size-1) &= mask_(addr); - } -} - -void BitVector_Interval_Flip(unsigned int * addr, unsigned int lower, unsigned int upper) -{ /* X = X ^ [lower..upper] */ - unsigned int bits = bits_(addr); - unsigned int size = size_(addr); - unsigned int flip = (unsigned int) ~0L; - unsigned int * loaddr; - unsigned int * hiaddr; - unsigned int lobase; - unsigned int hibase; - unsigned int lomask; - unsigned int himask; - unsigned int diff; - - if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper)) - { - lobase = lower >> LOGBITS; - hibase = upper >> LOGBITS; - diff = hibase - lobase; - loaddr = addr + lobase; - hiaddr = addr + hibase; - - lomask = (unsigned int) (~0L << (lower & MODMASK)); - himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1); - - if (diff == 0) - { - *loaddr ^= (lomask & himask); - } - else - { - *loaddr++ ^= lomask; - while (--diff > 0) - { - *loaddr++ ^= flip; - } - *hiaddr ^= himask; - } - *(addr+size-1) &= mask_(addr); - } -} - -void BitVector_Interval_Reverse(unsigned int * addr, unsigned int lower, unsigned int upper) -{ - unsigned int bits = bits_(addr); - unsigned int * loaddr; - unsigned int * hiaddr; - unsigned int lomask; - unsigned int himask; - - if ((bits > 0) && (lower < bits) && (upper < bits) && (lower < upper)) - { - loaddr = addr + (lower >> LOGBITS); - hiaddr = addr + (upper >> LOGBITS); - lomask = BITMASKTAB[lower & MODMASK]; - himask = BITMASKTAB[upper & MODMASK]; - for ( bits = upper - lower + 1; bits > 1; bits -= 2 ) - { - if (((*loaddr & lomask) != 0) ^ ((*hiaddr & himask) != 0)) - { - *loaddr ^= lomask; /* swap bits only if they differ! */ - *hiaddr ^= himask; - } - if (! (lomask <<= 1)) - { - lomask = LSB; - loaddr++; - } - if (! (himask >>= 1)) - { - himask = MSB; - hiaddr--; - } - } - } -} - -boolean BitVector_interval_scan_inc(unsigned int * addr, unsigned int start, - unsigned int * min, unsigned int * max) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int offset; - unsigned int bitmask; - unsigned int value; - boolean empty; - - if ((size == 0) || (start >= bits_(addr))) return(false); - - *min = start; - *max = start; - - offset = start >> LOGBITS; - - *(addr+size-1) &= mask; - - addr += offset; - size -= offset; - - bitmask = BITMASKTAB[start & MODMASK]; - mask = ~ (bitmask | (bitmask - 1)); - - value = *addr++; - if ((value & bitmask) == 0) - { - value &= mask; - if (value == 0) - { - offset++; - empty = true; - while (empty && (--size > 0)) - { - if ((value = *addr++)) empty = false; else offset++; - } - if (empty) return(false); - } - start = offset << LOGBITS; - bitmask = LSB; - mask = value; - while (! (mask & LSB)) - { - bitmask <<= 1; - mask >>= 1; - start++; - } - mask = ~ (bitmask | (bitmask - 1)); - *min = start; - *max = start; - } - value = ~ value; - value &= mask; - if (value == 0) - { - offset++; - empty = true; - while (empty && (--size > 0)) - { - if ((value = ~ *addr++)) empty = false; else offset++; - } - if (empty) value = LSB; - } - start = offset << LOGBITS; - while (! (value & LSB)) - { - value >>= 1; - start++; - } - *max = --start; - return(true); -} - -boolean BitVector_interval_scan_dec(unsigned int * addr, unsigned int start, - unsigned int * min, unsigned int * max) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int offset; - unsigned int bitmask; - unsigned int value; - boolean empty; - - if ((size == 0) || (start >= bits_(addr))) return(false); - - *min = start; - *max = start; - - offset = start >> LOGBITS; - - if (offset >= size) return(false); - - *(addr+size-1) &= mask; - - addr += offset; - size = ++offset; - - bitmask = BITMASKTAB[start & MODMASK]; - mask = (bitmask - 1); - - value = *addr--; - if ((value & bitmask) == 0) - { - value &= mask; - if (value == 0) - { - offset--; - empty = true; - while (empty && (--size > 0)) - { - if ((value = *addr--)) empty = false; else offset--; - } - if (empty) return(false); - } - start = offset << LOGBITS; - bitmask = MSB; - mask = value; - while (! (mask & MSB)) - { - bitmask >>= 1; - mask <<= 1; - start--; - } - mask = (bitmask - 1); - *max = --start; - *min = start; - } - value = ~ value; - value &= mask; - if (value == 0) - { - offset--; - empty = true; - while (empty && (--size > 0)) - { - if ((value = ~ *addr--)) empty = false; else offset--; - } - if (empty) value = MSB; - } - start = offset << LOGBITS; - while (! (value & MSB)) - { - value <<= 1; - start--; - } - *min = start; - return(true); -} - -void BitVector_Interval_Copy(unsigned int * X, unsigned int * Y, unsigned int Xoffset, - unsigned int Yoffset, unsigned int length) -{ - unsigned int bitsX = bits_(X); - unsigned int bitsY = bits_(Y); - unsigned int source = 0; /* silence compiler warning */ - unsigned int target = 0; /* silence compiler warning */ - unsigned int s_lo_base; - unsigned int s_hi_base; - unsigned int s_lo_bit; - unsigned int s_hi_bit; - unsigned int s_base; - unsigned int s_lower = 0; /* silence compiler warning */ - unsigned int s_upper = 0; /* silence compiler warning */ - unsigned int s_bits; - unsigned int s_min; - unsigned int s_max; - unsigned int t_lo_base; - unsigned int t_hi_base; - unsigned int t_lo_bit; - unsigned int t_hi_bit; - unsigned int t_base; - unsigned int t_lower = 0; /* silence compiler warning */ - unsigned int t_upper = 0; /* silence compiler warning */ - unsigned int t_bits; - unsigned int t_min; - unsigned int mask; - unsigned int bits; - unsigned int select; - boolean ascending; - boolean notfirst; - unsigned int * Z = X; - - if ((length > 0) && (Xoffset < bitsX) && (Yoffset < bitsY)) - { - if ((Xoffset + length) > bitsX) length = bitsX - Xoffset; - if ((Yoffset + length) > bitsY) length = bitsY - Yoffset; - - ascending = (Xoffset <= Yoffset); - - s_lo_base = Yoffset >> LOGBITS; - s_lo_bit = Yoffset & MODMASK; - Yoffset += --length; - s_hi_base = Yoffset >> LOGBITS; - s_hi_bit = Yoffset & MODMASK; - - t_lo_base = Xoffset >> LOGBITS; - t_lo_bit = Xoffset & MODMASK; - Xoffset += length; - t_hi_base = Xoffset >> LOGBITS; - t_hi_bit = Xoffset & MODMASK; - - if (ascending) - { - s_base = s_lo_base; - t_base = t_lo_base; - } - else - { - s_base = s_hi_base; - t_base = t_hi_base; - } - s_bits = 0; - t_bits = 0; - Y += s_base; - X += t_base; - notfirst = false; - while (true) - { - if (t_bits == 0) - { - if (notfirst) - { - *X = target; - if (ascending) - { - if (t_base == t_hi_base) break; - t_base++; - X++; - } - else - { - if (t_base == t_lo_base) break; - t_base--; - X--; - } - } - select = ((t_base == t_hi_base) << 1) | (t_base == t_lo_base); - switch (select) - { - case 0: - t_lower = 0; - t_upper = BITS - 1; - t_bits = BITS; - target = 0; - break; - case 1: - t_lower = t_lo_bit; - t_upper = BITS - 1; - t_bits = BITS - t_lo_bit; - mask = (unsigned int) (~0L << t_lower); - target = *X & ~ mask; - break; - case 2: - t_lower = 0; - t_upper = t_hi_bit; - t_bits = t_hi_bit + 1; - mask = (unsigned int) ((~0L << t_upper) << 1); - target = *X & mask; - break; - case 3: - t_lower = t_lo_bit; - t_upper = t_hi_bit; - t_bits = t_hi_bit - t_lo_bit + 1; - mask = (unsigned int) (~0L << t_lower); - mask &= (unsigned int) ~((~0L << t_upper) << 1); - target = *X & ~ mask; - break; - } - } - if (s_bits == 0) - { - if (notfirst) - { - if (ascending) - { - if (s_base == s_hi_base) break; - s_base++; - Y++; - } - else - { - if (s_base == s_lo_base) break; - s_base--; - Y--; - } - } - source = *Y; - select = ((s_base == s_hi_base) << 1) | (s_base == s_lo_base); - switch (select) - { - case 0: - s_lower = 0; - s_upper = BITS - 1; - s_bits = BITS; - break; - case 1: - s_lower = s_lo_bit; - s_upper = BITS - 1; - s_bits = BITS - s_lo_bit; - break; - case 2: - s_lower = 0; - s_upper = s_hi_bit; - s_bits = s_hi_bit + 1; - break; - case 3: - s_lower = s_lo_bit; - s_upper = s_hi_bit; - s_bits = s_hi_bit - s_lo_bit + 1; - break; - } - } - notfirst = true; - if (s_bits > t_bits) - { - bits = t_bits - 1; - if (ascending) - { - s_min = s_lower; - s_max = s_lower + bits; - } - else - { - s_max = s_upper; - s_min = s_upper - bits; - } - t_min = t_lower; - } - else - { - bits = s_bits - 1; - if (ascending) t_min = t_lower; - else t_min = t_upper - bits; - s_min = s_lower; - s_max = s_upper; - } - bits++; - mask = (unsigned int) (~0L << s_min); - mask &= (unsigned int) ~((~0L << s_max) << 1); - if (s_min == t_min) target |= (source & mask); - else - { - if (s_min < t_min) target |= (source & mask) << (t_min-s_min); - else target |= (source & mask) >> (s_min-t_min); - } - if (ascending) - { - s_lower += bits; - t_lower += bits; - } - else - { - s_upper -= bits; - t_upper -= bits; - } - s_bits -= bits; - t_bits -= bits; - } - *(Z+size_(Z)-1) &= mask_(Z); - } -} - - -unsigned int * BitVector_Interval_Substitute(unsigned int * X, unsigned int * Y, - unsigned int Xoffset, unsigned int Xlength, - unsigned int Yoffset, unsigned int Ylength) -{ - unsigned int Xbits = bits_(X); - unsigned int Ybits = bits_(Y); - unsigned int limit; - unsigned int diff; - - if ((Xoffset <= Xbits) && (Yoffset <= Ybits)) - { - limit = Xoffset + Xlength; - if (limit > Xbits) - { - limit = Xbits; - Xlength = Xbits - Xoffset; - } - if ((Yoffset + Ylength) > Ybits) - { - Ylength = Ybits - Yoffset; - } - if (Xlength == Ylength) - { - if ((Ylength > 0) && ((X != Y) || (Xoffset != Yoffset))) - { - BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); - } - } - else /* Xlength != Ylength */ - { - if (Xlength > Ylength) - { - diff = Xlength - Ylength; - if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); - if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,false); - if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL); - } - else /* Ylength > Xlength ==> Ylength > 0 */ - { - diff = Ylength - Xlength; - if (X != Y) - { - if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL); - if (limit < Xbits) BitVector_Insert(X,limit,diff,false); - BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); - } - else /* in-place */ - { - if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL); - if (limit >= Xbits) - { - BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); - } - else /* limit < Xbits */ - { - BitVector_Insert(X,limit,diff,false); - if ((Yoffset+Ylength) <= limit) - { - BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); - } - else /* overlaps or lies above critical area */ - { - if (limit <= Yoffset) - { - Yoffset += diff; - BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); - } - else /* Yoffset < limit */ - { - Xlength = limit - Yoffset; - BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength); - Yoffset = Xoffset + Ylength; /* = limit + diff */ - Xoffset += Xlength; - Ylength -= Xlength; - BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); - } - } - } - } - } - } - } - return(X); -} - -boolean BitVector_is_empty(unsigned int * addr) /* X == {} ? */ -{ - unsigned int size = size_(addr); - boolean r = true; - - if (size > 0) - { - *(addr+size-1) &= mask_(addr); - while (r && (size-- > 0)) r = ( *addr++ == 0 ); - } - return(r); -} - -boolean BitVector_is_full(unsigned int * addr) /* X == ~{} ? */ -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - boolean r = false; - unsigned int * last; - - if (size > 0) - { - r = true; - last = addr + size - 1; - *last |= ~ mask; - while (r && (size-- > 0)) r = ( ~ *addr++ == 0 ); - *last &= mask; - } - return(r); -} - -boolean BitVector_equal(unsigned int * X, unsigned int * Y) /* X == Y ? */ -{ - unsigned int size = size_(X); - unsigned int mask = mask_(X); - boolean r = false; - - if (bits_(X) == bits_(Y)) - { - r = true; - if (size > 0) - { - *(X+size-1) &= mask; - *(Y+size-1) &= mask; - while (r && (size-- > 0)) r = (*X++ == *Y++); - } - } - return(r); -} - -/* X <,=,> Y ? : unsigned */ -signed int BitVector_Lexicompare(unsigned int * X, unsigned int * Y) { - unsigned int bitsX = bits_(X); - unsigned int bitsY = bits_(Y); - unsigned int size = size_(X); - boolean r = true; - - if (bitsX == bitsY) { - if (size > 0) { - X += size; - Y += size; - while (r && (size-- > 0)) r = (*(--X) == *(--Y)); - } - if (r) return((signed int) 0); - else { - if (*X < *Y) return((signed int) -1); else return((signed int) 1); - } - } - else { - if (bitsX < bitsY) return((signed int) -1); else return((signed int) 1); - } -} - -signed int BitVector_Compare(unsigned int * X, unsigned int * Y) /* X <,=,> Y ? */ -{ /* signed */ - unsigned int bitsX = bits_(X); - unsigned int bitsY = bits_(Y); - unsigned int size = size_(X); - unsigned int mask = mask_(X); - unsigned int sign; - boolean r = true; - - if (bitsX == bitsY) - { - if (size > 0) - { - X += size; - Y += size; - mask &= ~ (mask >> 1); - if ((sign = (*(X-1) & mask)) != (*(Y-1) & mask)) - { - if (sign) return((signed int) -1); else return((signed int) 1); - } - while (r && (size-- > 0)) r = (*(--X) == *(--Y)); - } - if (r) return((signed int) 0); - else - { - if (*X < *Y) return((signed int) -1); else return((signed int) 1); - } - } - else - { - if (bitsX < bitsY) return((signed int) -1); else return((signed int) 1); - } -} - -size_t BitVector_Hash(unsigned int * addr) -{ - unsigned int bits = bits_(addr); - unsigned int size = size_(addr); - unsigned int value; - unsigned int count; - unsigned int digit; - unsigned int length; - - size_t result = 0; - - length = bits >> 2; - if (bits & 0x0003) length++; - if (size > 0) - { - *(addr+size-1) &= mask_(addr); - while ((size-- > 0) && (length > 0)) - { - value = *addr++; - count = BITS >> 2; - while ((count-- > 0) && (length > 0)) - { - digit = value & 0x000F; - if (digit > 9) digit += (unsigned int) 'A' - 10; - else digit += (unsigned int) '0'; - result = 5*result + digit; length--; - if ((count > 0) && (length > 0)) value >>= 4; - } - } - } - return result; -} - - -unsigned char * BitVector_to_Hex(unsigned int * addr) -{ - unsigned int bits = bits_(addr); - unsigned int size = size_(addr); - unsigned int value; - unsigned int count; - unsigned int digit; - unsigned int length; - unsigned char * string; - - length = bits >> 2; - if (bits & 0x0003) length++; - string = (unsigned char *) malloc((size_t) (length+1)); - if (string == NULL) return(NULL); - string += length; - *string = (unsigned char) '\0'; - if (size > 0) - { - *(addr+size-1) &= mask_(addr); - while ((size-- > 0) && (length > 0)) - { - value = *addr++; - count = BITS >> 2; - while ((count-- > 0) && (length > 0)) - { - digit = value & 0x000F; - if (digit > 9) digit += (unsigned int) 'A' - 10; - else digit += (unsigned int) '0'; - *(--string) = (unsigned char) digit; length--; - if ((count > 0) && (length > 0)) value >>= 4; - } - } - } - return(string); -} - -ErrCode BitVector_from_Hex(unsigned int * addr, unsigned char * string) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - boolean ok = true; - unsigned int length; - unsigned int value; - unsigned int count; - int digit; - - if (size > 0) - { - length = strlen((char *) string); - string += length; - while (size-- > 0) - { - value = 0; - for ( count = 0; (ok && (length > 0) && (count < BITS)); count += 4 ) - { - digit = (int) *(--string); length--; - /* separate because toupper() is likely a macro! */ - digit = toupper(digit); - if ((ok = (isxdigit(digit) != 0))) - { - if (digit >= (int) 'A') digit -= (int) 'A' - 10; - else digit -= (int) '0'; - value |= (((unsigned int) digit) << count); - } - } - *addr++ = value; - } - *(--addr) &= mask; - } - if (ok) return(ErrCode_Ok); - else return(ErrCode_Pars); -} - -unsigned char * BitVector_to_Bin(unsigned int * addr) -{ - unsigned int size = size_(addr); - unsigned int value; - unsigned int count; - unsigned int digit; - unsigned int length; - unsigned char * string; - - length = bits_(addr); - string = (unsigned char *) malloc((size_t) (length+1)); - if (string == NULL) return(NULL); - string += length; - *string = (unsigned char) '\0'; - if (size > 0) - { - *(addr+size-1) &= mask_(addr); - while (size-- > 0) - { - value = *addr++; - count = BITS; - if (count > length) count = length; - while (count-- > 0) - { - digit = value & 0x0001; - digit += (unsigned int) '0'; - *(--string) = (unsigned char) digit; length--; - if (count > 0) value >>= 1; - } - } - } - return(string); -} - -ErrCode BitVector_from_Bin(unsigned int * addr, unsigned char * string) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - boolean ok = true; - unsigned int length; - unsigned int value; - unsigned int count; - int digit; - - if (size > 0) - { - length = strlen((char *) string); - string += length; - while (size-- > 0) - { - value = 0; - for ( count = 0; (ok && (length > 0) && (count < BITS)); count++ ) - { - digit = (int) *(--string); length--; - switch (digit) - { - case (int) '0': - break; - case (int) '1': - value |= BITMASKTAB[count]; - break; - default: - ok = false; - break; - } - } - *addr++ = value; - } - *(--addr) &= mask; - } - if (ok) return(ErrCode_Ok); - else return(ErrCode_Pars); -} - -unsigned char * BitVector_to_Dec(unsigned int * addr) -{ - unsigned int bits = bits_(addr); - unsigned int length; - unsigned int digits; - unsigned int count; - unsigned int q; - unsigned int r; - boolean loop; - unsigned char * result; - unsigned char * string; - unsigned int * quot; - unsigned int * rest; - unsigned int * temp; - unsigned int * base; - signed int sign; - - length = (unsigned int) (bits / 3.3); /* digits = bits * ln(2) / ln(10) */ - length += 2; /* compensate for truncating & provide space for minus sign */ - result = (unsigned char *) malloc((size_t) (length+1)); /* remember the '\0'! */ - if (result == NULL) return(NULL); - string = result; - sign = BitVector_Sign(addr); - if ((bits < 4) || (sign == 0)) - { - if (bits > 0) digits = *addr; else digits = (unsigned int) 0; - if (sign < 0) digits = ((unsigned int)(-((signed int)digits))) & mask_(addr); - *string++ = (unsigned char) digits + (unsigned char) '0'; - digits = 1; - } - else - { - quot = BitVector_Create(bits,false); - if (quot == NULL) - { - BitVector_Dispose(result); - return(NULL); - } - rest = BitVector_Create(bits,false); - if (rest == NULL) - { - BitVector_Dispose(result); - BitVector_Destroy(quot); - return(NULL); - } - temp = BitVector_Create(bits,false); - if (temp == NULL) - { - BitVector_Dispose(result); - BitVector_Destroy(quot); - BitVector_Destroy(rest); - return(NULL); - } - base = BitVector_Create(bits,true); - if (base == NULL) - { - BitVector_Dispose(result); - BitVector_Destroy(quot); - BitVector_Destroy(rest); - BitVector_Destroy(temp); - return(NULL); - } - if (sign < 0) BitVector_Negate(quot,addr); - else BitVector_Copy(quot,addr); - digits = 0; - *base = EXP10; - loop = (bits >= BITS); - do - { - if (loop) - { - BitVector_Copy(temp,quot); - if (BitVector_Div_Pos(quot,temp,base,rest)) - { - BitVector_Dispose(result); /* emergency exit */ - BitVector_Destroy(quot); - BitVector_Destroy(rest); /* should never occur */ - BitVector_Destroy(temp); /* under normal operation */ - BitVector_Destroy(base); - return(NULL); - } - loop = ! BitVector_is_empty(quot); - q = *rest; - } - else q = *quot; - count = LOG10; - while (((loop && (count-- > 0)) || ((! loop) && (q != 0))) && - (digits < length)) - { - if (q != 0) - { - BIT_VECTOR_DIGITIZE(unsigned int,q,r) - } - else r = (unsigned int) '0'; - *string++ = (unsigned char) r; - digits++; - } - } - while (loop && (digits < length)); - BitVector_Destroy(quot); - BitVector_Destroy(rest); - BitVector_Destroy(temp); - BitVector_Destroy(base); - } - if ((sign < 0) && (digits < length)) - { - *string++ = (unsigned char) '-'; - digits++; - } - *string = (unsigned char) '\0'; - BIT_VECTOR_reverse(result,digits); - return(result); -} - -ErrCode BitVector_from_Dec(unsigned int * addr, unsigned char * string) -{ - ErrCode error = ErrCode_Ok; - unsigned int bits = bits_(addr); - unsigned int mask = mask_(addr); - boolean init = (bits > BITS); - boolean minus; - boolean shift; - boolean carry; - unsigned int * term; - unsigned int * base; - unsigned int * prod; - unsigned int * rank; - unsigned int * temp; - unsigned int accu; - unsigned int powr; - unsigned int count; - unsigned int length; - int digit; - - if (bits > 0) - { - length = strlen((char *) string); - if (length == 0) return(ErrCode_Pars); - digit = (int) *string; - if ((minus = (digit == (int) '-')) || - (digit == (int) '+')) - { - string++; - if (--length == 0) return(ErrCode_Pars); - } - string += length; - term = BitVector_Create(BITS,false); - if (term == NULL) - { - return(ErrCode_Null); - } - base = BitVector_Create(BITS,false); - if (base == NULL) - { - BitVector_Destroy(term); - return(ErrCode_Null); - } - prod = BitVector_Create(bits,init); - if (prod == NULL) - { - BitVector_Destroy(term); - BitVector_Destroy(base); - return(ErrCode_Null); - } - rank = BitVector_Create(bits,init); - if (rank == NULL) - { - BitVector_Destroy(term); - BitVector_Destroy(base); - BitVector_Destroy(prod); - return(ErrCode_Null); - } - temp = BitVector_Create(bits,false); - if (temp == NULL) - { - BitVector_Destroy(term); - BitVector_Destroy(base); - BitVector_Destroy(prod); - BitVector_Destroy(rank); - return(ErrCode_Null); - } - BitVector_Empty(addr); - *base = EXP10; - shift = false; - while ((! error) && (length > 0)) - { - accu = 0; - powr = 1; - count = LOG10; - while ((! error) && (length > 0) && (count-- > 0)) - { - digit = (int) *(--string); length--; - /* separate because isdigit() is likely a macro! */ - if (isdigit(digit) != 0) - { - accu += ((unsigned int) digit - (unsigned int) '0') * powr; - powr *= 10; - } - else error = ErrCode_Pars; - } - if (! error) - { - if (shift) - { - *term = accu; - BitVector_Copy(temp,rank); - error = BitVector_Mul_Pos(prod,temp,term,false); - } - else - { - *prod = accu; - if ((! init) && ((accu & ~ mask) != 0)) error = ErrCode_Ovfl; - } - if (! error) - { - carry = false; - BitVector_compute(addr,addr,prod,false,&carry); - /* ignores sign change (= overflow) but ! */ - /* numbers too large (= carry) for resulting bit vector */ - if (carry) error = ErrCode_Ovfl; - else - { - if (length > 0) - { - if (shift) - { - BitVector_Copy(temp,rank); - error = BitVector_Mul_Pos(rank,temp,base,false); - } - else - { - *rank = *base; - shift = true; - } - } - } - } - } - } - BitVector_Destroy(term); - BitVector_Destroy(base); - BitVector_Destroy(prod); - BitVector_Destroy(rank); - BitVector_Destroy(temp); - if (! error && minus) - { - BitVector_Negate(addr,addr); - if ((*(addr + size_(addr) - 1) & mask & ~ (mask >> 1)) == 0) - error = ErrCode_Ovfl; - } - } - return(error); -} - -unsigned char * BitVector_to_Enum(unsigned int * addr) -{ - unsigned int bits = bits_(addr); - unsigned int sample; - unsigned int length; - unsigned int digits; - unsigned int factor; - unsigned int power; - unsigned int start; - unsigned int min; - unsigned int max; - unsigned char * string; - unsigned char * target; - boolean comma; - - if (bits > 0) - { - sample = bits - 1; /* greatest possible index */ - length = 2; /* account for index 0 && terminating '\0' */ - digits = 1; /* account for intervening dashes && commas */ - factor = 1; - power = 10; - while (sample >= (power-1)) - { - length += ++digits * factor * 6; /* 9,90,900,9000,... (9*2/3 = 6) */ - factor = power; - power *= 10; - } - if (sample > --factor) - { - sample -= factor; - factor = (unsigned int) ( sample / 3 ); - factor = (factor << 1) + (sample - (factor * 3)); - length += ++digits * factor; - } - } - else length = 1; - string = (unsigned char *) malloc((size_t) length); - if (string == NULL) return(NULL); - start = 0; - comma = false; - target = string; - while ((start < bits) && BitVector_interval_scan_inc(addr,start,&min,&max)) - { - start = max + 2; - if (comma) *target++ = (unsigned char) ','; - if (min == max) - { - target += BIT_VECTOR_int2str(target,min); - } - else - { - if (min+1 == max) - { - target += BIT_VECTOR_int2str(target,min); - *target++ = (unsigned char) ','; - target += BIT_VECTOR_int2str(target,max); - } - else - { - target += BIT_VECTOR_int2str(target,min); - *target++ = (unsigned char) '-'; - target += BIT_VECTOR_int2str(target,max); - } - } - comma = true; - } - *target = (unsigned char) '\0'; - return(string); -} - -ErrCode BitVector_from_Enum(unsigned int * addr, unsigned char * string) -{ - ErrCode error = ErrCode_Ok; - unsigned int bits = bits_(addr); - unsigned int state = 1; - unsigned int token; - unsigned int index = 0; - unsigned int start = 0; /* silence compiler warning */ - - if (bits > 0) - { - BitVector_Empty(addr); - while ((! error) && (state != 0)) - { - token = (unsigned int) *string; - /* separate because isdigit() is likely a macro! */ - if (isdigit((int)token) != 0) - { - string += BIT_VECTOR_str2int(string,&index); - if (index < bits) token = (unsigned int) '0'; - else error = ErrCode_Indx; - } - else string++; - if (! error) - switch (state) - { - case 1: - switch (token) - { - case (unsigned int) '0': - state = 2; - break; - case (unsigned int) '\0': - state = 0; - break; - default: - error = ErrCode_Pars; - break; - } - break; - case 2: - switch (token) - { - case (unsigned int) '-': - start = index; - state = 3; - break; - case (unsigned int) ',': - BIT_VECTOR_SET_BIT(addr,index) - state = 5; - break; - case (unsigned int) '\0': - BIT_VECTOR_SET_BIT(addr,index) - state = 0; - break; - default: - error = ErrCode_Pars; - break; - } - break; - case 3: - switch (token) - { - case (unsigned int) '0': - if (start < index) - BitVector_Interval_Fill(addr,start,index); - else if (start == index) - BIT_VECTOR_SET_BIT(addr,index) - else error = ErrCode_Ordr; - state = 4; - break; - default: - error = ErrCode_Pars; - break; - } - break; - case 4: - switch (token) - { - case (unsigned int) ',': - state = 5; - break; - case (unsigned int) '\0': - state = 0; - break; - default: - error = ErrCode_Pars; - break; - } - break; - case 5: - switch (token) - { - case (unsigned int) '0': - state = 2; - break; - default: - error = ErrCode_Pars; - break; - } - break; - } - } - } - return(error); -} - -void BitVector_Bit_Off(unsigned int * addr, unsigned int index) /* X = X \ {x} */ -{ - if (index < bits_(addr)) BIT_VECTOR_CLR_BIT(addr,index) -} - -void BitVector_Bit_On(unsigned int * addr, unsigned int index) /* X = X + {x} */ -{ - if (index < bits_(addr)) BIT_VECTOR_SET_BIT(addr,index) -} - -boolean BitVector_bit_flip(unsigned int * addr, unsigned int index) /* X=(X+{x})\(X*{x}) */ -{ - unsigned int mask; - - if (index < bits_(addr)) return( BIT_VECTOR_FLP_BIT(addr,index,mask) ); - else return( false ); -} - -boolean BitVector_bit_test(unsigned int * addr, unsigned int index) /* {x} in X ? */ -{ - if (index < bits_(addr)) return( BIT_VECTOR_TST_BIT(addr,index) ); - else return( false ); -} - -void BitVector_Bit_Copy(unsigned int * addr, unsigned int index, boolean bit) -{ - if (index < bits_(addr)) - { - if (bit) BIT_VECTOR_SET_BIT(addr,index) - else BIT_VECTOR_CLR_BIT(addr,index) - } -} - -void BitVector_LSB(unsigned int * addr, boolean bit) -{ - if (bits_(addr) > 0) - { - if (bit) *addr |= LSB; - else *addr &= ~ LSB; - } -} - -void BitVector_MSB(unsigned int * addr, boolean bit) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - - if (size-- > 0) - { - if (bit) *(addr+size) |= mask & ~ (mask >> 1); - else *(addr+size) &= ~ mask | (mask >> 1); - } -} - -boolean BitVector_lsb_(unsigned int * addr) -{ - if (size_(addr) > 0) return( (*addr & LSB) != 0 ); - else return( false ); -} - -boolean BitVector_msb_(unsigned int * addr) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - - if (size-- > 0) - return( (*(addr+size) & (mask & ~ (mask >> 1))) != 0 ); - else - return( false ); -} - -boolean BitVector_rotate_left(unsigned int * addr) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int msb; - boolean carry_in; - boolean carry_out = false; - - if (size > 0) - { - msb = mask & ~ (mask >> 1); - carry_in = ((*(addr+size-1) & msb) != 0); - while (size-- > 1) - { - carry_out = ((*addr & MSB) != 0); - *addr <<= 1; - if (carry_in) *addr |= LSB; - carry_in = carry_out; - addr++; - } - carry_out = ((*addr & msb) != 0); - *addr <<= 1; - if (carry_in) *addr |= LSB; - *addr &= mask; - } - return(carry_out); -} - -boolean BitVector_rotate_right(unsigned int * addr) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int msb; - boolean carry_in; - boolean carry_out = false; - - if (size > 0) - { - msb = mask & ~ (mask >> 1); - carry_in = ((*addr & LSB) != 0); - addr += size-1; - *addr &= mask; - carry_out = ((*addr & LSB) != 0); - *addr >>= 1; - if (carry_in) *addr |= msb; - carry_in = carry_out; - addr--; - size--; - while (size-- > 0) - { - carry_out = ((*addr & LSB) != 0); - *addr >>= 1; - if (carry_in) *addr |= MSB; - carry_in = carry_out; - addr--; - } - } - return(carry_out); -} - -boolean BitVector_shift_left(unsigned int * addr, boolean carry_in) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int msb; - boolean carry_out = carry_in; - - if (size > 0) - { - msb = mask & ~ (mask >> 1); - while (size-- > 1) - { - carry_out = ((*addr & MSB) != 0); - *addr <<= 1; - if (carry_in) *addr |= LSB; - carry_in = carry_out; - addr++; - } - carry_out = ((*addr & msb) != 0); - *addr <<= 1; - if (carry_in) *addr |= LSB; - *addr &= mask; - } - return(carry_out); -} - -boolean BitVector_shift_right(unsigned int * addr, boolean carry_in) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int msb; - boolean carry_out = carry_in; - - if (size > 0) - { - msb = mask & ~ (mask >> 1); - addr += size-1; - *addr &= mask; - carry_out = ((*addr & LSB) != 0); - *addr >>= 1; - if (carry_in) *addr |= msb; - carry_in = carry_out; - addr--; - size--; - while (size-- > 0) - { - carry_out = ((*addr & LSB) != 0); - *addr >>= 1; - if (carry_in) *addr |= MSB; - carry_in = carry_out; - addr--; - } - } - return(carry_out); -} - -void BitVector_Move_Left(unsigned int * addr, unsigned int bits) -{ - unsigned int count; - unsigned int words; - - if (bits > 0) - { - count = bits & MODMASK; - words = bits >> LOGBITS; - if (bits >= bits_(addr)) BitVector_Empty(addr); - else - { - while (count-- > 0) BitVector_shift_left(addr,0); - BitVector_Word_Insert(addr,0,words,true); - } - } -} - -void BitVector_Move_Right(unsigned int * addr, unsigned int bits) -{ - unsigned int count; - unsigned int words; - - if (bits > 0) - { - count = bits & MODMASK; - words = bits >> LOGBITS; - if (bits >= bits_(addr)) BitVector_Empty(addr); - else - { - while (count-- > 0) BitVector_shift_right(addr,0); - BitVector_Word_Delete(addr,0,words,true); - } - } -} - -void BitVector_Insert(unsigned int * addr, unsigned int offset, unsigned int count, boolean clear) -{ - unsigned int bits = bits_(addr); - unsigned int last; - - if ((count > 0) && (offset < bits)) - { - last = offset + count; - if (last < bits) - { - BitVector_Interval_Copy(addr,addr,last,offset,(bits-last)); - } - else last = bits; - if (clear) BitVector_Interval_Empty(addr,offset,(last-1)); - } -} - -void BitVector_Delete(unsigned int * addr, unsigned int offset, unsigned int count, boolean clear) -{ - unsigned int bits = bits_(addr); - unsigned int last; - - if ((count > 0) && (offset < bits)) - { - last = offset + count; - if (last < bits) - { - BitVector_Interval_Copy(addr,addr,offset,last,(bits-last)); - } - else count = bits - offset; - if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1)); - } -} - -boolean BitVector_increment(unsigned int * addr) /* X++ */ -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int * last = addr + size - 1; - boolean carry = true; - - if (size > 0) - { - *last |= ~ mask; - while (carry && (size-- > 0)) - { - carry = (++(*addr++) == 0); - } - *last &= mask; - } - return(carry); -} - -boolean BitVector_decrement(unsigned int * addr) /* X-- */ -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int * last = addr + size - 1; - boolean carry = true; - - if (size > 0) - { - *last &= mask; - while (carry && (size-- > 0)) - { - carry = (*addr == 0); - --(*addr++); - } - *last &= mask; - } - return(carry); -} - -boolean BitVector_compute(unsigned int * X, unsigned int * Y, unsigned int * Z, boolean minus, boolean *carry) -{ - unsigned int size = size_(X); - unsigned int mask = mask_(X); - unsigned int vv = 0; - unsigned int cc; - unsigned int mm; - unsigned int yy; - unsigned int zz; - unsigned int lo; - unsigned int hi; - - if (size > 0) - { - if (minus) cc = (*carry == 0); - else cc = (*carry != 0); - /* deal with (size-1) least significant full words first: */ - while (--size > 0) - { - yy = *Y++; - if (minus) zz = (unsigned int) ~ ( Z ? *Z++ : 0 ); - else zz = (unsigned int) ( Z ? *Z++ : 0 ); - lo = (yy & LSB) + (zz & LSB) + cc; - hi = (yy >> 1) + (zz >> 1) + (lo >> 1); - cc = ((hi & MSB) != 0); - *X++ = (hi << 1) | (lo & LSB); - } - /* deal with most significant word (may be used only partially): */ - yy = *Y & mask; - if (minus) zz = (unsigned int) ~ ( Z ? *Z : 0 ); - else zz = (unsigned int) ( Z ? *Z : 0 ); - zz &= mask; - if (mask == LSB) /* special case, only one bit used */ - { - vv = cc; - lo = yy + zz + cc; - cc = (lo >> 1); - vv ^= cc; - *X = lo & LSB; - } - else - { - if (~ mask) /* not all bits are used, but more than one */ - { - mm = (mask >> 1); - vv = (yy & mm) + (zz & mm) + cc; - mm = mask & ~ mm; - lo = yy + zz + cc; - cc = (lo >> 1); - vv ^= cc; - vv &= mm; - cc &= mm; - *X = lo & mask; - } - else /* other special case, all bits are used */ - { - mm = ~ MSB; - lo = (yy & mm) + (zz & mm) + cc; - vv = lo & MSB; - hi = ((yy & MSB) >> 1) + ((zz & MSB) >> 1) + (vv >> 1); - cc = hi & MSB; - vv ^= cc; - *X = (hi << 1) | (lo & mm); - } - } - if (minus) *carry = (cc == 0); - else *carry = (cc != 0); - } - return(vv != 0); -} - -boolean BitVector_add(unsigned int * X, unsigned int * Y, unsigned int * Z, boolean *carry) -{ - return(BitVector_compute(X,Y,Z,false,carry)); -} - -boolean BitVector_sub(unsigned int * X, unsigned int * Y, unsigned int * Z, boolean *carry) -{ - return(BitVector_compute(X,Y,Z,true,carry)); -} - -boolean BitVector_inc(unsigned int * X, unsigned int * Y) -{ - boolean carry = true; - - return(BitVector_compute(X,Y,NULL,false,&carry)); -} - -boolean BitVector_dec(unsigned int * X, unsigned int * Y) -{ - boolean carry = true; - - return(BitVector_compute(X,Y,NULL,true,&carry)); -} - -void BitVector_Negate(unsigned int * X, unsigned int * Y) -{ - unsigned int size = size_(X); - unsigned int mask = mask_(X); - boolean carry = true; - - if (size > 0) - { - while (size-- > 0) - { - *X = ~ *Y++; - if (carry) - { - carry = (++(*X) == 0); - } - X++; - } - *(--X) &= mask; - } -} - -void BitVector_Absolute(unsigned int * X, unsigned int * Y) -{ - unsigned int size = size_(Y); - unsigned int mask = mask_(Y); - - if (size > 0) - { - if (*(Y+size-1) & (mask & ~ (mask >> 1))) BitVector_Negate(X,Y); - else BitVector_Copy(X,Y); - } -} - -// FIXME: What the hell does the return value of this mean? -// It returns 0, 1, or -1 under mysterious circumstances. -signed int BitVector_Sign(unsigned int * addr) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int * last = addr + size - 1; - boolean r = true; - - if (size > 0) - { - *last &= mask; - while (r && (size-- > 0)) r = ( *addr++ == 0 ); - } - if (r) return((signed int) 0); - else - { - if (*last & (mask & ~ (mask >> 1))) return((signed int) -1); - else return((signed int) 1); - } -} - -ErrCode BitVector_Mul_Pos(unsigned int * X, unsigned int * Y, unsigned int * Z, boolean strict) -{ - unsigned int mask; - unsigned int limit; - unsigned int count; - signed long last; - unsigned int * sign; - boolean carry; - boolean overflow; - boolean ok = true; - - /* - Requirements: - - X, Y && Z must be distinct - - X && Y must have equal sizes (whereas Z may be any size!) - - Z should always contain the SMALLER of the two factors Y && Z - Constraints: - - The contents of Y (&& of X, of course) are destroyed - (only Z is preserved!) - */ - - if ((X == Y) || (X == Z) || (Y == Z)) return(ErrCode_Same); - if (bits_(X) != bits_(Y)) return(ErrCode_Size); - BitVector_Empty(X); - if (BitVector_is_empty(Y)) return(ErrCode_Ok); /* exit also taken if bits_(Y)==0 */ - if ((last = Set_Max(Z)) < 0L) return(ErrCode_Ok); - limit = (unsigned int) last; - sign = Y + size_(Y) - 1; - mask = mask_(Y); - *sign &= mask; - mask &= ~ (mask >> 1); - for ( count = 0; (ok && (count <= limit)); count++ ) - { - if ( BIT_VECTOR_TST_BIT(Z,count) ) - { - carry = false; - overflow = BitVector_compute(X,X,Y,false,&carry); - if (strict) ok = ! (carry || overflow); - else ok = ! carry; - } - if (ok && (count < limit)) - { - carry = BitVector_shift_left(Y,0); - if (strict) - { - overflow = ((*sign & mask) != 0); - ok = ! (carry || overflow); - } - else ok = ! carry; - } - } - if (ok) return(ErrCode_Ok); else return(ErrCode_Ovfl); -} - -ErrCode BitVector_Multiply(unsigned int * X, unsigned int * Y, unsigned int * Z) -{ - ErrCode error = ErrCode_Ok; - unsigned int bit_x = bits_(X); - unsigned int bit_y = bits_(Y); - unsigned int bit_z = bits_(Z); - unsigned int size; - unsigned int mask; - unsigned int msb; - unsigned int * ptr_y; - unsigned int * ptr_z; - boolean sgn_x; - boolean sgn_y; - boolean sgn_z; - boolean zero; - unsigned int * A; - unsigned int * B; - - /* - Requirements: - - Y && Z must have equal sizes - - X must have at least the same size as Y && Z but may be larger (!) - Features: - - The contents of Y && Z are preserved - - X may be identical with Y or Z (or both!) - (in-place multiplication is possible!) - */ - - if ((bit_y != bit_z) || (bit_x < bit_y)) return(ErrCode_Size); - if (BitVector_is_empty(Y) || BitVector_is_empty(Z)) - { - BitVector_Empty(X); - } - else - { - A = BitVector_Create(bit_y,false); - if (A == NULL) return(ErrCode_Null); - B = BitVector_Create(bit_z,false); - if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); } - size = size_(Y); - mask = mask_(Y); - msb = (mask & ~ (mask >> 1)); - sgn_y = (((*(Y+size-1) &= mask) & msb) != 0); - sgn_z = (((*(Z+size-1) &= mask) & msb) != 0); - sgn_x = sgn_y ^ sgn_z; - if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y); - if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z); - ptr_y = A + size; - ptr_z = B + size; - zero = true; - while (zero && (size-- > 0)) - { - zero &= (*(--ptr_y) == 0); - zero &= (*(--ptr_z) == 0); - } - if (*ptr_y > *ptr_z) - { - if (bit_x > bit_y) - { - A = BitVector_Resize(A,bit_x); - if (A == NULL) { BitVector_Destroy(B); return(ErrCode_Null); } - } - error = BitVector_Mul_Pos(X,A,B,true); - } - else - { - if (bit_x > bit_z) - { - B = BitVector_Resize(B,bit_x); - if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); } - } - error = BitVector_Mul_Pos(X,B,A,true); - } - if ((! error) && sgn_x) BitVector_Negate(X,X); - BitVector_Destroy(A); - BitVector_Destroy(B); - } - return(error); -} - -ErrCode BitVector_Div_Pos(unsigned int * Q, unsigned int * X, unsigned int * Y, unsigned int * R) -{ - unsigned int bits = bits_(Q); - unsigned int mask; - unsigned int * addr; - signed long last; - boolean flag; - boolean copy = false; /* flags whether valid rest is in R (0) || X (1) */ - - /* - Requirements: - - All bit vectors must have equal sizes - - Q, X, Y && R must all be distinct bit vectors - - Y must be non-zero (of course!) - Constraints: - - The contents of X (&& Q && R, of course) are destroyed - (only Y is preserved!) - */ - - if ((bits != bits_(X)) || (bits != bits_(Y)) || (bits != bits_(R))) - return(ErrCode_Size); - if ((Q == X) || (Q == Y) || (Q == R) || (X == Y) || (X == R) || (Y == R)) - return(ErrCode_Same); - if (BitVector_is_empty(Y)) - return(ErrCode_Zero); - - BitVector_Empty(R); - BitVector_Copy(Q,X); - if ((last = Set_Max(Q)) < 0L) return(ErrCode_Ok); - bits = (unsigned int) ++last; - while (bits-- > 0) - { - addr = Q + (bits >> LOGBITS); - mask = BITMASKTAB[bits & MODMASK]; - flag = ((*addr & mask) != 0); - if (copy) - { - BitVector_shift_left(X,flag); - flag = false; - BitVector_compute(R,X,Y,true,&flag); - } - else - { - BitVector_shift_left(R,flag); - flag = false; - BitVector_compute(X,R,Y,true,&flag); - } - if (flag) *addr &= ~ mask; - else - { - *addr |= mask; - copy = ! copy; - } - } - if (copy) BitVector_Copy(R,X); - return(ErrCode_Ok); -} - -ErrCode BitVector_Divide(unsigned int * Q, unsigned int * X, unsigned int * Y, unsigned int * R) -{ - ErrCode error = ErrCode_Ok; - unsigned int bits = bits_(Q); - unsigned int size = size_(Q); - unsigned int mask = mask_(Q); - unsigned int msb = (mask & ~ (mask >> 1)); - boolean sgn_q; - boolean sgn_x; - boolean sgn_y; - unsigned int * A; - unsigned int * B; - - /* - Requirements: - - All bit vectors must have equal sizes - - Q && R must be two distinct bit vectors - - Y must be non-zero (of course!) - Features: - - The contents of X && Y are preserved - - Q may be identical with X || Y (or both) - (in-place division is possible!) - - R may be identical with X || Y (or both) - (but not identical with Q!) - */ - - if ((bits != bits_(X)) || (bits != bits_(Y)) || (bits != bits_(R))) - return(ErrCode_Size); - if (Q == R) - return(ErrCode_Same); - if (BitVector_is_empty(Y)) - return(ErrCode_Zero); - - if (BitVector_is_empty(X)) - { - BitVector_Empty(Q); - BitVector_Empty(R); - } - else - { - A = BitVector_Create(bits,false); - if (A == NULL) return(ErrCode_Null); - B = BitVector_Create(bits,false); - if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); } - size--; - sgn_x = (((*(X+size) &= mask) & msb) != 0); - sgn_y = (((*(Y+size) &= mask) & msb) != 0); - sgn_q = sgn_x ^ sgn_y; - if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X); - if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y); - if (! (error = BitVector_Div_Pos(Q,A,B,R))) - { - if (sgn_q) BitVector_Negate(Q,Q); - if (sgn_x) BitVector_Negate(R,R); - } - BitVector_Destroy(A); - BitVector_Destroy(B); - } - return(error); -} - -ErrCode BitVector_GCD(unsigned int * X, unsigned int * Y, unsigned int * Z) -{ - ErrCode error = ErrCode_Ok; - unsigned int bits = bits_(X); - unsigned int size = size_(X); - unsigned int mask = mask_(X); - unsigned int msb = (mask & ~ (mask >> 1)); - boolean sgn_a; - boolean sgn_b; - boolean sgn_r; - unsigned int * Q; - unsigned int * R; - unsigned int * A; - unsigned int * B; - unsigned int * T; - - /* - Requirements: - - All bit vectors must have equal sizes - Features: - - The contents of Y && Z are preserved - - X may be identical with Y || Z (or both) - (in-place is possible!) - - GCD(0,z) == GCD(z,0) == z - - negative values are h&&led correctly - */ - - if ((bits != bits_(Y)) || (bits != bits_(Z))) return(ErrCode_Size); - if (BitVector_is_empty(Y)) - { - if (X != Z) BitVector_Copy(X,Z); - return(ErrCode_Ok); - } - if (BitVector_is_empty(Z)) - { - if (X != Y) BitVector_Copy(X,Y); - return(ErrCode_Ok); - } - Q = BitVector_Create(bits,false); - if (Q == NULL) - { - return(ErrCode_Null); - } - R = BitVector_Create(bits,false); - if (R == NULL) - { - BitVector_Destroy(Q); - return(ErrCode_Null); - } - A = BitVector_Create(bits,false); - if (A == NULL) - { - BitVector_Destroy(Q); - BitVector_Destroy(R); - return(ErrCode_Null); - } - B = BitVector_Create(bits,false); - if (B == NULL) - { - BitVector_Destroy(Q); - BitVector_Destroy(R); - BitVector_Destroy(A); - return(ErrCode_Null); - } - size--; - sgn_a = (((*(Y+size) &= mask) & msb) != 0); - sgn_b = (((*(Z+size) &= mask) & msb) != 0); - if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y); - if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z); - while (! error) - { - if (! (error = BitVector_Div_Pos(Q,A,B,R))) - { - if (BitVector_is_empty(R)) break; - T = A; sgn_r = sgn_a; - A = B; sgn_a = sgn_b; - B = R; sgn_b = sgn_r; - R = T; - } - } - if (! error) - { - if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B); - } - BitVector_Destroy(Q); - BitVector_Destroy(R); - BitVector_Destroy(A); - BitVector_Destroy(B); - return(error); -} - -ErrCode BitVector_GCD2(unsigned int * U, unsigned int * V, unsigned int * W, unsigned int * X, unsigned int * Y) -{ - ErrCode error = ErrCode_Ok; - unsigned int bits = bits_(U); - unsigned int size = size_(U); - unsigned int mask = mask_(U); - unsigned int msb = (mask & ~ (mask >> 1)); - boolean minus; - boolean carry; - boolean sgn_q; - boolean sgn_r; - boolean sgn_a; - boolean sgn_b; - boolean sgn_x; - boolean sgn_y; - unsigned int * * L; - unsigned int * Q; - unsigned int * R; - unsigned int * A; - unsigned int * B; - unsigned int * T; - unsigned int * X1; - unsigned int * X2; - unsigned int * X3; - unsigned int * Y1; - unsigned int * Y2; - unsigned int * Y3; - unsigned int * Z; - - /* - Requirements: - - All bit vectors must have equal sizes - - U, V, && W must all be distinct bit vectors - Features: - - The contents of X && Y are preserved - - U, V && W may be identical with X || Y (or both, - provided that U, V && W are mutually distinct) - (i.e., in-place is possible!) - - GCD(0,z) == GCD(z,0) == z - - negative values are h&&led correctly - */ - - if ((bits != bits_(V)) || - (bits != bits_(W)) || - (bits != bits_(X)) || - (bits != bits_(Y))) - { - return(ErrCode_Size); - } - if ((U == V) || (U == W) || (V == W)) - { - return(ErrCode_Same); - } - if (BitVector_is_empty(X)) - { - if (U != Y) BitVector_Copy(U,Y); - BitVector_Empty(V); - BitVector_Empty(W); - *W = 1; - return(ErrCode_Ok); - } - if (BitVector_is_empty(Y)) - { - if (U != X) BitVector_Copy(U,X); - BitVector_Empty(V); - BitVector_Empty(W); - *V = 1; - return(ErrCode_Ok); - } - if ((L = BitVector_Create_List(bits,false,11)) == NULL) - { - return(ErrCode_Null); - } - Q = L[0]; - R = L[1]; - A = L[2]; - B = L[3]; - X1 = L[4]; - X2 = L[5]; - X3 = L[6]; - Y1 = L[7]; - Y2 = L[8]; - Y3 = L[9]; - Z = L[10]; - size--; - sgn_a = (((*(X+size) &= mask) & msb) != 0); - sgn_b = (((*(Y+size) &= mask) & msb) != 0); - if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X); - if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y); - BitVector_Empty(X1); - BitVector_Empty(X2); - *X1 = 1; - BitVector_Empty(Y1); - BitVector_Empty(Y2); - *Y2 = 1; - sgn_x = false; - sgn_y = false; - while (! error) - { - if ((error = BitVector_Div_Pos(Q,A,B,R))) - { - break; - } - if (BitVector_is_empty(R)) - { - break; - } - sgn_q = sgn_a ^ sgn_b; - - if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2); - if ((error = BitVector_Mul_Pos(X3,Z,Q,true))) - { - break; - } - minus = ! (sgn_x ^ sgn_q); - carry = 0; - if (BitVector_compute(X3,X1,X3,minus,&carry)) - { - error = ErrCode_Ovfl; - break; - } - sgn_x = (((*(X3+size) &= mask) & msb) != 0); - - if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2); - if ((error = BitVector_Mul_Pos(Y3,Z,Q,true))) - { - break; - } - minus = ! (sgn_y ^ sgn_q); - carry = 0; - if (BitVector_compute(Y3,Y1,Y3,minus,&carry)) - { - error = ErrCode_Ovfl; - break; - } - sgn_y = (((*(Y3+size) &= mask) & msb) != 0); - - T = A; sgn_r = sgn_a; - A = B; sgn_a = sgn_b; - B = R; sgn_b = sgn_r; - R = T; - - T = X1; - X1 = X2; - X2 = X3; - X3 = T; - - T = Y1; - Y1 = Y2; - Y2 = Y3; - Y3 = T; - } - if (! error) - { - if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B); - BitVector_Copy(V,X2); - BitVector_Copy(W,Y2); - } - BitVector_Destroy_List(L,11); - return(error); -} - -ErrCode BitVector_Power(unsigned int * X, unsigned int * Y, unsigned int * Z) -{ - ErrCode error = ErrCode_Ok; - unsigned int bits = bits_(X); - boolean first = true; - signed long last; - unsigned int limit; - unsigned int count; - unsigned int * T; - - /* - Requirements: - - X must have at least the same size as Y but may be larger (!) - - X may not be identical with Z - - Z must be positive - Features: - - The contents of Y && Z are preserved - */ - - if (X == Z) return(ErrCode_Same); - if (bits < bits_(Y)) return(ErrCode_Size); - if (BitVector_msb_(Z)) return(ErrCode_Expo); - if ((last = Set_Max(Z)) < 0L) - { - if (bits < 2) return(ErrCode_Ovfl); - BitVector_Empty(X); - *X |= LSB; - return(ErrCode_Ok); /* anything ^ 0 == 1 */ - } - if (BitVector_is_empty(Y)) - { - if (X != Y) BitVector_Empty(X); - return(ErrCode_Ok); /* 0 ^ anything ! zero == 0 */ - } - T = BitVector_Create(bits,false); - if (T == NULL) return(ErrCode_Null); - limit = (unsigned int) last; - for ( count = 0; ((!error) && (count <= limit)); count++ ) - { - if ( BIT_VECTOR_TST_BIT(Z,count) ) - { - if (first) - { - first = false; - if (count) { BitVector_Copy(X,T); } - else { if (X != Y) BitVector_Copy(X,Y); } - } - else error = BitVector_Multiply(X,T,X); /* order important because T > X */ - } - if ((!error) && (count < limit)) - { - if (count) error = BitVector_Multiply(T,T,T); - else error = BitVector_Multiply(T,Y,Y); - } - } - BitVector_Destroy(T); - return(error); -} - -void BitVector_Block_Store(unsigned int * addr, unsigned char * buffer, unsigned int length) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int value; - unsigned int count; - - /* provide translation for independence of endian-ness: */ - if (size > 0) - { - while (size-- > 0) - { - value = 0; - for ( count = 0; (length > 0) && (count < BITS); count += 8 ) - { - value |= (((unsigned int) *buffer++) << count); length--; - } - *addr++ = value; - } - *(--addr) &= mask; - } -} - -unsigned char * BitVector_Block_Read(unsigned int * addr, unsigned int * length) -{ - unsigned int size = size_(addr); - unsigned int value; - unsigned int count; - unsigned char * buffer; - unsigned char * target; - - /* provide translation for independence of endian-ness: */ - *length = size << FACTOR; - buffer = (unsigned char *) malloc((size_t) ((*length)+1)); - if (buffer == NULL) return(NULL); - target = buffer; - if (size > 0) - { - *(addr+size-1) &= mask_(addr); - while (size-- > 0) - { - value = *addr++; - count = BITS >> 3; - while (count-- > 0) - { - *target++ = (unsigned char) (value & 0x00FF); - if (count > 0) value >>= 8; - } - } - } - *target = (unsigned char) '\0'; - return(buffer); -} - -void BitVector_Word_Store(unsigned int * addr, unsigned int offset, unsigned int value) -{ - unsigned int size = size_(addr); - - if (size > 0) - { - if (offset < size) *(addr+offset) = value; - *(addr+size-1) &= mask_(addr); - } -} - -unsigned int BitVector_Word_Read(unsigned int * addr, unsigned int offset) -{ - unsigned int size = size_(addr); - - if (size > 0) - { - *(addr+size-1) &= mask_(addr); - if (offset < size) return( *(addr+offset) ); - } - return( (unsigned int) 0 ); -} - -void BitVector_Word_Insert(unsigned int * addr, unsigned int offset, unsigned int count, - boolean clear) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int * last = addr+size-1; - - if (size > 0) - { - *last &= mask; - if (offset > size) offset = size; - BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear); - *last &= mask; - } -} - -void BitVector_Word_Delete(unsigned int * addr, unsigned int offset, unsigned int count, - boolean clear) -{ - unsigned int size = size_(addr); - unsigned int mask = mask_(addr); - unsigned int * last = addr+size-1; - - if (size > 0) - { - *last &= mask; - if (offset > size) offset = size; - BIT_VECTOR_del_words(addr+offset,size-offset,count,clear); - *last &= mask; - } -} - -void BitVector_Chunk_Store(unsigned int * addr, unsigned int chunksize, unsigned int offset, - unsigned long value) -{ - unsigned int bits = bits_(addr); - unsigned int mask; - unsigned int temp; - - if ((chunksize > 0) && (offset < bits)) - { - if (chunksize > LONGBITS) chunksize = LONGBITS; - if ((offset + chunksize) > bits) chunksize = bits - offset; - addr += offset >> LOGBITS; - offset &= MODMASK; - while (chunksize > 0) - { - mask = (unsigned int) (~0L << offset); - bits = offset + chunksize; - if (bits < BITS) - { - mask &= (unsigned int) ~(~0L << bits); - bits = chunksize; - } - else bits = BITS - offset; - temp = (unsigned int) (value << offset); - temp &= mask; - *addr &= ~ mask; - *addr++ |= temp; - value >>= bits; - chunksize -= bits; - offset = 0; - } - } -} - -unsigned long BitVector_Chunk_Read(unsigned int * addr, unsigned int chunksize, unsigned int offset) -{ - unsigned int bits = bits_(addr); - unsigned int chunkbits = 0; - unsigned long value = 0L; - unsigned long temp; - unsigned int mask; - - if ((chunksize > 0) && (offset < bits)) - { - if (chunksize > LONGBITS) chunksize = LONGBITS; - if ((offset + chunksize) > bits) chunksize = bits - offset; - addr += offset >> LOGBITS; - offset &= MODMASK; - while (chunksize > 0) - { - bits = offset + chunksize; - if (bits < BITS) - { - mask = (unsigned int) ~(~0L << bits); - bits = chunksize; - } - else - { - mask = (unsigned int) ~0L; - bits = BITS - offset; - } - temp = (unsigned long) ((*addr++ & mask) >> offset); - value |= temp << chunkbits; - chunkbits += bits; - chunksize -= bits; - offset = 0; - } - } - return(value); -} - - /*******************/ - /* set operations: */ - /*******************/ - -void Set_Union(unsigned int * X, unsigned int * Y, unsigned int * Z) /* X = Y + Z */ -{ - unsigned int bits = bits_(X); - unsigned int size = size_(X); - unsigned int mask = mask_(X); - - if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z))) - { - while (size-- > 0) *X++ = *Y++ | *Z++; - *(--X) &= mask; - } -} - -void Set_Intersection(unsigned int * X, unsigned int * Y, unsigned int * Z) /* X = Y * Z */ -{ - unsigned int bits = bits_(X); - unsigned int size = size_(X); - unsigned int mask = mask_(X); - - if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z))) - { - while (size-- > 0) *X++ = *Y++ & *Z++; - *(--X) &= mask; - } -} - -void Set_Difference(unsigned int * X, unsigned int * Y, unsigned int * Z) /* X = Y \ Z */ -{ - unsigned int bits = bits_(X); - unsigned int size = size_(X); - unsigned int mask = mask_(X); - - if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z))) - { - while (size-- > 0) *X++ = *Y++ & ~ *Z++; - *(--X) &= mask; - } -} - -void Set_ExclusiveOr(unsigned int * X, unsigned int * Y, unsigned int * Z) /* X=(Y+Z)\(Y*Z) */ -{ - unsigned int bits = bits_(X); - unsigned int size = size_(X); - unsigned int mask = mask_(X); - - if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z))) - { - while (size-- > 0) *X++ = *Y++ ^ *Z++; - *(--X) &= mask; - } -} - -void Set_Complement(unsigned int * X, unsigned int * Y) /* X = ~Y */ -{ - unsigned int size = size_(X); - unsigned int mask = mask_(X); - - if ((size > 0) && (bits_(X) == bits_(Y))) - { - while (size-- > 0) *X++ = ~ *Y++; - *(--X) &= mask; - } -} - - /******************/ - /* set functions: */ - /******************/ - -boolean Set_subset(unsigned int * X, unsigned int * Y) /* X subset Y ? */ -{ - unsigned int size = size_(X); - boolean r = false; - - if ((size > 0) && (bits_(X) == bits_(Y))) - { - r = true; - while (r && (size-- > 0)) r = ((*X++ & ~ *Y++) == 0); - } - return(r); -} - -unsigned int Set_Norm(unsigned int * addr) /* = | X | */ -{ - unsigned char * byte; - unsigned int bytes; - unsigned int n; - - byte = (unsigned char *) addr; - bytes = size_(addr) << FACTOR; - n = 0; - while (bytes-- > 0) - { - n += BitVector_BYTENORM[*byte++]; - } - return(n); -} - -unsigned int Set_Norm2(unsigned int * addr) /* = | X | */ -{ - unsigned int size = size_(addr); - unsigned int w0,w1; - unsigned int n,k; - - n = 0; - while (size-- > 0) - { - k = 0; - w1 = ~ (w0 = *addr++); - while (w0 && w1) - { - w0 &= w0 - 1; - w1 &= w1 - 1; - k++; - } - if (w0 == 0) n += k; - else n += BITS - k; - } - return(n); -} - -unsigned int Set_Norm3(unsigned int * addr) /* = | X | */ -{ - unsigned int size = size_(addr); - unsigned int count = 0; - unsigned int c; - - while (size-- > 0) - { - c = *addr++; - while (c) - { - c &= c - 1; - count++; - } - } - return(count); -} - -signed long Set_Min(unsigned int * addr) /* = min(X) */ -{ - boolean empty = true; - unsigned int size = size_(addr); - unsigned int i = 0; - unsigned int c = 0; /* silence compiler warning */ - - while (empty && (size-- > 0)) - { - if ((c = *addr++)) empty = false; else i++; - } - if (empty) return((signed long) LONG_MAX); /* plus infinity */ - i <<= LOGBITS; - while (! (c & LSB)) - { - c >>= 1; - i++; - } - return((signed long) i); -} - -signed long Set_Max(unsigned int * addr) /* = max(X) */ -{ - boolean empty = true; - unsigned int size = size_(addr); - unsigned int i = size; - unsigned int c = 0; /* silence compiler warning */ - - addr += size-1; - while (empty && (size-- > 0)) - { - if ((c = *addr--)) empty = false; else i--; - } - if (empty) return((signed long) LONG_MIN); /* minus infinity */ - i <<= LOGBITS; - while (! (c & MSB)) - { - c <<= 1; - i--; - } - return((signed long) --i); -} - - /**********************************/ - /* matrix-of-booleans operations: */ - /**********************************/ - -void Matrix_Multiplication(unsigned int * X, unsigned int rowsX, unsigned int colsX, - unsigned int * Y, unsigned int rowsY, unsigned int colsY, - unsigned int * Z, unsigned int rowsZ, unsigned int colsZ) -{ - unsigned int i; - unsigned int j; - unsigned int k; - unsigned int indxX; - unsigned int indxY; - unsigned int indxZ; - unsigned int termX; - unsigned int termY; - unsigned int sum; - - if ((colsY == rowsZ) && (rowsX == rowsY) && (colsX == colsZ) && - (bits_(X) == rowsX*colsX) && - (bits_(Y) == rowsY*colsY) && - (bits_(Z) == rowsZ*colsZ)) - { - for ( i = 0; i < rowsY; i++ ) - { - termX = i * colsX; - termY = i * colsY; - for ( j = 0; j < colsZ; j++ ) - { - indxX = termX + j; - sum = 0; - for ( k = 0; k < colsY; k++ ) - { - indxY = termY + k; - indxZ = k * colsZ + j; - if ( BIT_VECTOR_TST_BIT(Y,indxY) & - BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1; - } - if (sum) BIT_VECTOR_SET_BIT(X,indxX) - else BIT_VECTOR_CLR_BIT(X,indxX) - } - } - } -} - -void Matrix_Product(unsigned int * X, unsigned int rowsX, unsigned int colsX, - unsigned int * Y, unsigned int rowsY, unsigned int colsY, - unsigned int * Z, unsigned int rowsZ, unsigned int colsZ) -{ - unsigned int i; - unsigned int j; - unsigned int k; - unsigned int indxX; - unsigned int indxY; - unsigned int indxZ; - unsigned int termX; - unsigned int termY; - unsigned int sum; - - if ((colsY == rowsZ) && (rowsX == rowsY) && (colsX == colsZ) && - (bits_(X) == rowsX*colsX) && - (bits_(Y) == rowsY*colsY) && - (bits_(Z) == rowsZ*colsZ)) - { - for ( i = 0; i < rowsY; i++ ) - { - termX = i * colsX; - termY = i * colsY; - for ( j = 0; j < colsZ; j++ ) - { - indxX = termX + j; - sum = 0; - for ( k = 0; k < colsY; k++ ) - { - indxY = termY + k; - indxZ = k * colsZ + j; - if ( BIT_VECTOR_TST_BIT(Y,indxY) & - BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1; - } - if (sum) BIT_VECTOR_SET_BIT(X,indxX) - else BIT_VECTOR_CLR_BIT(X,indxX) - } - } - } -} - -void Matrix_Closure(unsigned int * addr, unsigned int rows, unsigned int cols) -{ - unsigned int i; - unsigned int j; - unsigned int k; - unsigned int ii; - unsigned int ij; - unsigned int ik; - unsigned int kj; - unsigned int termi; - unsigned int termk; - - if ((rows == cols) && (bits_(addr) == rows*cols)) - { - for ( i = 0; i < rows; i++ ) - { - ii = i * cols + i; - BIT_VECTOR_SET_BIT(addr,ii) - } - for ( k = 0; k < rows; k++ ) - { - termk = k * cols; - for ( i = 0; i < rows; i++ ) - { - termi = i * cols; - ik = termi + k; - for ( j = 0; j < rows; j++ ) - { - ij = termi + j; - kj = termk + j; - if ( BIT_VECTOR_TST_BIT(addr,ik) & - BIT_VECTOR_TST_BIT(addr,kj) ) - BIT_VECTOR_SET_BIT(addr,ij) - } - } - } - } -} - -void Matrix_Transpose(unsigned int * X, unsigned int rowsX, unsigned int colsX, - unsigned int * Y, unsigned int rowsY, unsigned int colsY) -{ - unsigned int i; - unsigned int j; - unsigned int ii; - unsigned int ij; - unsigned int ji; - unsigned int addii; - unsigned int addij; - unsigned int addji; - unsigned int bitii; - unsigned int bitij; - unsigned int bitji; - unsigned int termi; - unsigned int termj; - boolean swap; - - /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */ - - if ((rowsX == colsY) && (colsX == rowsY) && - (bits_(X) == rowsX*colsX) && - (bits_(Y) == rowsY*colsY)) - { - if (rowsY == colsY) /* in-place is possible! */ - { - for ( i = 0; i < rowsY; i++ ) - { - termi = i * colsY; - for ( j = 0; j < i; j++ ) - { - termj = j * colsX; - ij = termi + j; - ji = termj + i; - addij = ij >> LOGBITS; - addji = ji >> LOGBITS; - bitij = BITMASKTAB[ij & MODMASK]; - bitji = BITMASKTAB[ji & MODMASK]; - swap = ((*(Y+addij) & bitij) != 0); - if ((*(Y+addji) & bitji) != 0) - *(X+addij) |= bitij; - else - *(X+addij) &= ~ bitij; - if (swap) - *(X+addji) |= bitji; - else - *(X+addji) &= ~ bitji; - } - ii = termi + i; - addii = ii >> LOGBITS; - bitii = BITMASKTAB[ii & MODMASK]; - if ((*(Y+addii) & bitii) != 0) - *(X+addii) |= bitii; - else - *(X+addii) &= ~ bitii; - } - } - else /* rowsX != colsX, in-place is ~ possible! */ - { - for ( i = 0; i < rowsY; i++ ) - { - termi = i * colsY; - for ( j = 0; j < colsY; j++ ) - { - termj = j * colsX; - ij = termi + j; - ji = termj + i; - addij = ij >> LOGBITS; - addji = ji >> LOGBITS; - bitij = BITMASKTAB[ij & MODMASK]; - bitji = BITMASKTAB[ji & MODMASK]; - if ((*(Y+addij) & bitij) != 0) - *(X+addji) |= bitji; - else - *(X+addji) &= ~ bitji; - } - } - } - } -} -} //end of namespace CONSTANTBV diff --git a/stp/constantbv/constantbv.h b/stp/constantbv/constantbv.h deleted file mode 100644 index bd64132d..00000000 --- a/stp/constantbv/constantbv.h +++ /dev/null @@ -1,316 +0,0 @@ -#ifndef MODULE_BIT_VECTOR -#define MODULE_BIT_VECTOR -/*****************************************************************************/ -/* AUTHOR: */ -/*****************************************************************************/ -/* */ -/* Steffen Beyer */ -/* mailto:sb@engelschall.com */ -/* http://www.engelschall.com/u/sb/download/ */ -/* */ -/*****************************************************************************/ -/* COPYRIGHT: */ -/*****************************************************************************/ -/* */ -/* Copyright (c) 1995 - 2004 by Steffen Beyer. */ -/* All rights reserved. */ -/* */ -/*****************************************************************************/ -/* LICENSE: */ -/*****************************************************************************/ -/* */ -/* This library is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU Library General Public */ -/* License as published by the Free Software Foundation; either */ -/* version 2 of the License, or (at your option) any later version. */ -/* */ -/* This library is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ -/* Library General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU Library General Public */ -/* License along with this library; if not, write to the */ -/* Free Software Foundation, Inc., */ -/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* */ -/* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */ -/* */ -/*****************************************************************************/ - - -/*****************************************************************************/ -/* MODULE NAME: BitVector.h MODULE TYPE: (adt) */ -/*****************************************************************************/ -/* MODULE IMPORTS: */ -/*****************************************************************************/ -#include <stdlib.h> /* MODULE TYPE: (sys) */ -#include <limits.h> /* MODULE TYPE: (sys) */ -#include <string.h> /* MODULE TYPE: (sys) */ -#include <ctype.h> /* MODULE TYPE: (sys) */ -/*****************************************************************************/ -/* MODULE INTERFACE: */ -/*****************************************************************************/ - -namespace CONSTANTBV { - -#ifdef __cplusplus - extern "C" { - typedef bool boolean; -#else - typedef enum { false = (0!=0), true = (0==0) } boolean; -#endif - - typedef enum { - ErrCode_Ok = 0, /* everything went allright */ - ErrCode_Type, /* types word and size_t have incompatible sizes */ - ErrCode_Bits, /* bits of word and sizeof(word) are inconsistent */ - ErrCode_Word, /* size of word is less than 16 bits */ - ErrCode_Long, /* size of word is greater than size of long */ - ErrCode_Powr, /* number of bits of word is not a power of two */ - ErrCode_Loga, /* error in calculation of logarithm */ - ErrCode_Null, /* unable to allocate memory */ - ErrCode_Indx, /* index out of range */ - ErrCode_Ordr, /* minimum > maximum index */ - ErrCode_Size, /* bit vector size mismatch */ - ErrCode_Pars, /* input string syntax error */ - ErrCode_Ovfl, /* numeric overflow error */ - ErrCode_Same, /* operands must be distinct */ - ErrCode_Expo, /* exponent must be positive */ - ErrCode_Zero /* division by zero error */ - } ErrCode; - - - /* ===> MISCELLANEOUS BASIC FUNCTIONS: <=== */ - unsigned char * BitVector_Error(ErrCode error); /* return string for err code */ - ErrCode BitVector_Boot (void); /* 0 = ok, 1..7 = error */ - unsigned int BitVector_Size(unsigned int bits); /* bit vector size (# of words) */ - unsigned int BitVector_Mask(unsigned int bits); /* bit vector mask (unused bits) */ - - /* ===> CLASS METHODS: <=== */ - unsigned char * BitVector_Version(void); /* return version string */ - unsigned int BitVector_Word_Bits(void); /* return # of bits in machine word */ - unsigned int BitVector_Long_Bits(void); /* return # of bits in unsigned long */ - - /* ===> CONSTRUCTOR METHODS: <=== */ - unsigned int * BitVector_Create (unsigned int bits, boolean clear); /* malloc */ - unsigned int ** BitVector_Create_List (unsigned int bits, boolean clear, unsigned int count); - unsigned int * BitVector_Resize (unsigned int * oldaddr, unsigned int bits); /* realloc */ - unsigned int * BitVector_Shadow (unsigned int * addr); /* make new same size but empty */ - unsigned int * BitVector_Clone (unsigned int * addr); /* make exact duplicate */ - unsigned int * BitVector_Concat (unsigned int * X, unsigned int * Y); /* return concatenation */ - - /* ===> DESTRUCTOR METHODS: <=== */ - void BitVector_Dispose (unsigned char * string); /* string */ - void BitVector_Destroy (unsigned int * addr); /* bitvec */ - void BitVector_Destroy_List (unsigned int * * list, unsigned int count); /* list */ - - /* ===> OBJECT METHODS: <=== */ - - /* ===> bit vector hash: */ - size_t BitVector_Hash (unsigned int * X); - - /* ===> bit vector copy function: */ - void BitVector_Copy (unsigned int * X, unsigned int * Y); /* X := Y */ - - /* ===> bit vector initialization: */ - void BitVector_Empty (unsigned int * addr); /* X = {} */ - void BitVector_Fill (unsigned int * addr); /* X = ~{} */ - void BitVector_Flip (unsigned int * addr); /* X = ~X */ - void BitVector_Primes (unsigned int * addr); - - /* ===> miscellaneous functions: */ - void BitVector_Reverse (unsigned int * X, unsigned int * Y); - - /* ===> bit vector interval operations and functions: */ - void BitVector_Interval_Empty (unsigned int * addr, unsigned int lower, unsigned int upper); - void BitVector_Interval_Fill (unsigned int * addr, unsigned int lower, unsigned int upper); - void BitVector_Interval_Flip (unsigned int * addr, unsigned int lower, unsigned int upper); - void BitVector_Interval_Reverse (unsigned int * addr, unsigned int lower, unsigned int upper); - - boolean BitVector_interval_scan_inc (unsigned int * addr, unsigned int start, - unsigned int * min, unsigned int * max); - boolean BitVector_interval_scan_dec (unsigned int * addr, unsigned int start, - unsigned int * min, unsigned int * max); - void BitVector_Interval_Copy (unsigned int * X, unsigned int * Y, - unsigned int Xoffset, unsigned int Yoffset, unsigned int length); - unsigned int * BitVector_Interval_Substitute(unsigned int * X, unsigned int * Y, - unsigned int Xoffset, unsigned int Xlength, - unsigned int Yoffset, unsigned int Ylength); - - /* ===> bit vector test functions: */ - boolean BitVector_is_empty (unsigned int * addr); /* X == {} ? */ - boolean BitVector_is_full (unsigned int * addr); /* X == ~{} ? */ - boolean BitVector_equal (unsigned int * X, unsigned int * Y); /* X == Y ? */ - signed int BitVector_Lexicompare (unsigned int * X, unsigned int * Y); /* X <,=,> Y ? */ - signed int BitVector_Compare (unsigned int * X, unsigned int * Y); /* X <,=,> Y ? */ - - /* ===> bit vector string conversion functions: */ - unsigned char * BitVector_to_Hex (unsigned int * addr); - ErrCode BitVector_from_Hex (unsigned int * addr, unsigned char * string); - unsigned char * BitVector_to_Bin (unsigned int * addr); - ErrCode BitVector_from_Bin (unsigned int * addr, unsigned char * string); - unsigned char * BitVector_to_Dec (unsigned int * addr); - ErrCode BitVector_from_Dec (unsigned int * addr, unsigned char * string); - unsigned char * BitVector_to_Enum (unsigned int * addr); - ErrCode BitVector_from_Enum (unsigned int * addr, unsigned char * string); - - /* ===> bit vector bit operations, functions & tests: */ - void BitVector_Bit_Off (unsigned int * addr, unsigned int index); /* X = X \ {x} */ - void BitVector_Bit_On (unsigned int * addr, unsigned int index); /* X = X + {x} */ - boolean BitVector_bit_flip (unsigned int * addr, unsigned int index); /* (X+{x})\(X*{x}) */ - boolean BitVector_bit_test (unsigned int * addr, unsigned int index); /* {x} in X ? */ - void BitVector_Bit_Copy (unsigned int * addr, unsigned int index, boolean bit); - - /* ===> bit vector bit shift & rotate functions: */ - void BitVector_LSB (unsigned int * addr, boolean bit); - void BitVector_MSB (unsigned int * addr, boolean bit); - boolean BitVector_lsb_ (unsigned int * addr); - boolean BitVector_msb_ (unsigned int * addr); - boolean BitVector_rotate_left (unsigned int * addr); - boolean BitVector_rotate_right (unsigned int * addr); - boolean BitVector_shift_left (unsigned int * addr, boolean carry_in); - boolean BitVector_shift_right (unsigned int * addr, boolean carry_in); - void BitVector_Move_Left (unsigned int * addr, unsigned int bits); - void BitVector_Move_Right (unsigned int * addr, unsigned int bits); - - /* ===> bit vector insert/delete bits: */ - void BitVector_Insert (unsigned int * addr, - unsigned int offset, unsigned int count, boolean clear); - void BitVector_Delete (unsigned int * addr, - unsigned int offset, unsigned int count, boolean clear); - - /* ===> bit vector arithmetic: */ - boolean BitVector_increment (unsigned int * addr); /* X++ */ - boolean BitVector_decrement (unsigned int * addr); /* X-- */ - boolean BitVector_compute (unsigned int * X, unsigned int * Y, - unsigned int * Z, boolean minus, boolean *carry); - boolean BitVector_add (unsigned int * X, - unsigned int * Y, unsigned int * Z, boolean *carry); - boolean BitVector_sub (unsigned int * X, - unsigned int * Y, unsigned int * Z, boolean *carry); /* X = Y-Z*/ - boolean BitVector_inc (unsigned int * X, unsigned int * Y); - boolean BitVector_dec (unsigned int * X, unsigned int * Y); - - void BitVector_Negate (unsigned int * X, unsigned int * Y); - void BitVector_Absolute (unsigned int * X, unsigned int * Y); - signed int BitVector_Sign (unsigned int * addr); - ErrCode BitVector_Mul_Pos (unsigned int * X, - unsigned int * Y, unsigned int * Z, boolean strict); - ErrCode BitVector_Multiply (unsigned int * X, unsigned int * Y, unsigned int * Z); - ErrCode BitVector_Div_Pos (unsigned int * Q, unsigned int * X, unsigned int * Y, unsigned int * R); - ErrCode BitVector_Divide (unsigned int * Q, unsigned int * X, unsigned int * Y, unsigned int * R); - ErrCode BitVector_GCD (unsigned int * X, unsigned int * Y, unsigned int * Z); - ErrCode BitVector_GCD2 (unsigned int * U, unsigned int * V, unsigned int * W, /* O */ - unsigned int * X, unsigned int * Y); /* I */ - ErrCode BitVector_Power (unsigned int * X, unsigned int * Y, unsigned int * Z); - - /* ===> direct memory access functions: */ - void BitVector_Block_Store (unsigned int * addr, - unsigned char * buffer, unsigned int length); - unsigned char * BitVector_Block_Read (unsigned int * addr, unsigned int * length); - - /* ===> word array functions: */ - void BitVector_Word_Store (unsigned int * addr, unsigned int offset, unsigned int value); - unsigned int BitVector_Word_Read (unsigned int * addr, unsigned int offset); - void BitVector_Word_Insert (unsigned int * addr, - unsigned int offset, unsigned int count, boolean clear); - void BitVector_Word_Delete (unsigned int * addr, - unsigned int offset, unsigned int count, boolean clear); - - /* ===> arbitrary size chunk functions: */ - void BitVector_Chunk_Store (unsigned int * addr, unsigned int chunksize, - unsigned int offset, unsigned long value); - unsigned long BitVector_Chunk_Read (unsigned int * addr, - unsigned int chunksize,unsigned int offset); - - /* ===> set operations: */ - void Set_Union (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y + Z */ - void Set_Intersection (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y * Z */ - void Set_Difference (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y \ Z */ - void Set_ExclusiveOr (unsigned int * X, unsigned int * Y, unsigned int * Z); /*(Y+Z)\(Y*Z)*/ - void Set_Complement (unsigned int * X, unsigned int * Y); /* X = ~Y */ - - /* ===> set functions: */ - boolean Set_subset (unsigned int * X, unsigned int * Y); /* X in Y ? */ - unsigned int Set_Norm (unsigned int * addr); /* = | X | */ - unsigned int Set_Norm2 (unsigned int * addr); /* = | X | */ - unsigned int Set_Norm3 (unsigned int * addr); /* = | X | */ - signed long Set_Min (unsigned int * addr); /* = min(X) */ - signed long Set_Max (unsigned int * addr); /* = max(X) */ - - /* ===> matrix-of-booleans operations: */ - void Matrix_Multiplication (unsigned int * X, unsigned int rowsX, unsigned int colsX, - unsigned int * Y, unsigned int rowsY, unsigned int colsY, - unsigned int * Z, unsigned int rowsZ, unsigned int colsZ); - void Matrix_Product (unsigned int * X, unsigned int rowsX, unsigned int colsX, - unsigned int * Y, unsigned int rowsY, unsigned int colsY, - unsigned int * Z, unsigned int rowsZ, unsigned int colsZ); - void Matrix_Closure (unsigned int * addr, unsigned int rows, unsigned int cols); - void Matrix_Transpose (unsigned int * X, unsigned int rowsX, unsigned int colsX, - unsigned int * Y, unsigned int rowsY, unsigned int colsY); - - /*****************************************************************************/ - /* MODULE RESOURCES: */ - /*****************************************************************************/ -#define bits_(BitVector) *(BitVector-3) -#define size_(BitVector) *(BitVector-2) -#define mask_(BitVector) *(BitVector-1) - -#define ERRCODE_TYPE "sizeof(word) > sizeof(size_t)" -#define ERRCODE_BITS "bits(word) != sizeof(word)*8" -#define ERRCODE_WORD "bits(word) < 16" -#define ERRCODE_LONG "bits(word) > bits(long)" -#define ERRCODE_POWR "bits(word) != 2^x" -#define ERRCODE_LOGA "bits(word) != 2^ld(bits(word))" -#define ERRCODE_NULL "unable to allocate memory" -#define ERRCODE_INDX "index out of range" -#define ERRCODE_ORDR "minimum > maximum index" -#define ERRCODE_SIZE "bit vector size mismatch" -#define ERRCODE_PARS "input string syntax error" -#define ERRCODE_OVFL "numeric overflow error" -#define ERRCODE_SAME "result vector(s) must be distinct" -#define ERRCODE_EXPO "exponent must be positive" -#define ERRCODE_ZERO "division by zero error" -#define ERRCODE_OOPS "unexpected internal error - please contact author" - - const unsigned int BitVector_BYTENORM[256] = { - 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, /* 0x00 */ - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x10 */ - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x20 */ - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x30 */ - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x40 */ - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x50 */ - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x60 */ - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0x70 */ - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x80 */ - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x90 */ - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xA0 */ - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xB0 */ - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xC0 */ - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xD0 */ - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xE0 */ - 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, - 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 /* 0xF0 */ - }; -#ifdef __cplusplus - } -#endif -} //end of namespace CONSTANTBV -#endif - diff --git a/stp/sat/Global.h b/stp/sat/Global.h deleted file mode 100644 index deaf8c24..00000000 --- a/stp/sat/Global.h +++ /dev/null @@ -1,255 +0,0 @@ -/****************************************************************************************[Global.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#ifndef Global_h -#define Global_h - -#include <cassert> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <new> - -// PKT: needs to be outside namespace MINISAT or mac os x compilation breaks -#ifdef _MSC_VER -#else -#include <unistd.h> -#endif - -namespace MINISAT { -//================================================================================================= -// Basic Types & Minor Things: - -// DWD: This is needed on darwin. -typedef unsigned int uint; - -#ifdef _MSC_VER - -typedef INT64 int64; -typedef UINT64 uint64; -typedef INT_PTR intp; -typedef UINT_PTR uintp; -#define I64_fmt "I64d" -#else - -typedef long long int64; -typedef unsigned long long uint64; -typedef __PTRDIFF_TYPE__ intp; -typedef unsigned __PTRDIFF_TYPE__ uintp; -#define I64_fmt "lld" -#endif - -template<class T> static inline T min(T x, T y) { return (x < y) ? x : y; } -template<class T> static inline T max(T x, T y) { return (x > y) ? x : y; } - -template <bool> struct STATIC_ASSERTION_FAILURE; -template <> struct STATIC_ASSERTION_FAILURE<true>{}; -#define TEMPLATE_FAIL STATIC_ASSERTION_FAILURE<false>() - - -//================================================================================================= -// 'malloc()'-style memory allocation -- never returns NULL; aborts instead: - - -template<class T> static inline T* xmalloc(size_t size) { - T* tmp = (T*)malloc(size * sizeof(T)); - assert(size == 0 || tmp != NULL); - return tmp; } - -template<class T> static inline T* xrealloc(T* ptr, size_t size) { - T* tmp = (T*)realloc((void*)ptr, size * sizeof(T)); - assert(size == 0 || tmp != NULL); - return tmp; } - -template<class T> static inline void xfree(T *ptr) { - if (ptr != NULL) free((void*)ptr); } - - -//================================================================================================= -// Random numbers: - - -// Returns a random float 0 <= x < 1. Seed must never be 0. -static inline double drand(double& seed) { - seed *= 1389796; - int q = (int)(seed / 2147483647); - seed -= (double)q * 2147483647; - return seed / 2147483647; } - -// Returns a random integer 0 <= x < size. Seed must never be 0. -static inline int irand(double& seed, int size) { - return (int)(drand(seed) * size); } - - -//================================================================================================= -// 'vec' -- automatically resizable arrays (via 'push()' method): - - -// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc) - -template<class T> -class vec { - T* data; - int sz; - int cap; - - void init(int size, const T& pad); - void grow(int min_cap); - -public: - // Types: - typedef int Key; - typedef T Datum; - - // Constructors: - vec(void) : data(NULL) , sz(0) , cap(0) { } - vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); } - vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); } - vec(T* array, int size) : data(array), sz(size), cap(size) { } // (takes ownership of array -- will be deallocated with 'xfree()') - ~vec(void) { clear(true); } - - // Ownership of underlying array: - T* release (void) { T* ret = data; data = NULL; sz = 0; cap = 0; return ret; } - operator T* (void) { return data; } // (unsafe but convenient) - operator const T* (void) const { return data; } - - // Size operations: - int size (void) const { return sz; } - void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); } - void pop (void) { sz--, data[sz].~T(); } - void growTo (int size); - void growTo (int size, const T& pad); - void clear (bool dealloc = false); - void capacity (int size) { grow(size); } - - // Stack interface: - void push (void) { if (sz == cap) grow(sz+1); new (&data[sz]) T() ; sz++; } - void push (const T& elem) { if (sz == cap) grow(sz+1); new (&data[sz]) T(elem); sz++; } - const T& last (void) const { return data[sz-1]; } - T& last (void) { return data[sz-1]; } - - // Vector interface: - const T& operator [] (int index) const { return data[index]; } - T& operator [] (int index) { return data[index]; } - - // Don't allow copying (error prone): - vec<T>& operator = (vec<T>& other) { TEMPLATE_FAIL; } - vec (vec<T>& other) { TEMPLATE_FAIL; } - - // Duplicatation (preferred instead): - void copyTo(vec<T>& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) new (©[i]) T(data[i]); } - void moveTo(vec<T>& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } -}; - -template<class T> -void vec<T>::grow(int min_cap) { - if (min_cap <= cap) return; - if (cap == 0) cap = (min_cap >= 2) ? min_cap : 2; - else do cap = (cap*3+1) >> 1; while (cap < min_cap); - data = xrealloc(data, cap); } - -template<class T> -void vec<T>::growTo(int size, const T& pad) { - if (sz >= size) return; - grow(size); - for (int i = sz; i < size; i++) new (&data[i]) T(pad); - sz = size; } - -template<class T> -void vec<T>::growTo(int size) { - if (sz >= size) return; - grow(size); - for (int i = sz; i < size; i++) new (&data[i]) T(); - sz = size; } - -template<class T> -void vec<T>::clear(bool dealloc) { - if (data != NULL){ - for (int i = 0; i < sz; i++) data[i].~T(); - sz = 0; - if (dealloc) xfree(data), data = NULL, cap = 0; } } - - -//================================================================================================= -// Useful functions on vectors - - -template<class V, class T> -void remove(V& ts, const T& t) -{ - int j = 0; - for (; j < ts.size() && ts[j] != t; j++) ; - assert(j < ts.size()); - for (; j < ts.size()-1; j++) ts[j] = ts[j+1]; - ts.pop(); -} - - -template<class V, class T> -bool find(V& ts, const T& t) -{ - int j = 0; - for (; j < ts.size() && ts[j] != t; j++) ; - return j < ts.size(); -} - -//================================================================================================= -// Lifted booleans: - - -class lbool { - int value; - explicit lbool(int v) : value(v) { } - -public: - lbool() : value(0) { } - lbool(bool x) : value((int)x*2-1) { } - int toInt(void) const { return value; } - - bool operator == (const lbool& other) const { return value == other.value; } - bool operator != (const lbool& other) const { return value != other.value; } - lbool operator ~ (void) const { return lbool(-value); } - - friend int toInt (lbool l); - friend lbool toLbool(int v); -}; -inline int toInt (lbool l) { return l.toInt(); } -inline lbool toLbool(int v) { return lbool(v); } - -const lbool l_True = toLbool( 1); -const lbool l_False = toLbool(-1); -const lbool l_Undef = toLbool( 0); - - -//================================================================================================= -// Relation operators -- extend definitions from '==' and '<' - - -#ifndef __SGI_STL_INTERNAL_RELOPS // (be aware of SGI's STL implementation...) -#define __SGI_STL_INTERNAL_RELOPS -template <class T> static inline bool operator != (const T& x, const T& y) { return !(x == y); } -template <class T> static inline bool operator > (const T& x, const T& y) { return y < x; } -template <class T> static inline bool operator <= (const T& x, const T& y) { return !(y < x); } -template <class T> static inline bool operator >= (const T& x, const T& y) { return !(x < y); } -#endif - - -//================================================================================================= -} -#endif diff --git a/stp/sat/Heap.h b/stp/sat/Heap.h deleted file mode 100644 index e3a82dd0..00000000 --- a/stp/sat/Heap.h +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************************[Heap.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#ifndef Heap_h -#define Heap_h - -#include "../AST/ASTUtil.h" -namespace MINISAT { - -//================================================================================================= - - -static inline int left (int i) { return i+i; } -static inline int right (int i) { return i+i + 1; } -static inline int parent(int i) { return i >> 1; } - -template<class C> -class Heap { - public: - C comp; - vec<int> heap; // heap of ints - vec<int> indices; // int -> index in heap - - inline void percolateUp(int i) - { - int x = heap[i]; - while (parent(i) != 0 && comp(x,heap[parent(i)])){ - heap[i] = heap[parent(i)]; - indices[heap[i]] = i; - i = parent(i); - } - heap [i] = x; - indices[x] = i; - } - - inline void percolateDown(int i) - { - int x = heap[i]; - while (left(i) < heap.size()){ - int child = right(i) < heap.size() && comp(heap[right(i)],heap[left(i)]) ? right(i) : left(i); - if (!comp(heap[child],x)) break; - heap[i] = heap[child]; - indices[heap[i]] = i; - i = child; - } - heap [i] = x; - indices[x] = i; - } - - bool ok(int n) const { - return n >= 0 && n < (int)indices.size(); } - - public: - Heap(C c) : comp(c) { heap.push(-1); } - - void setBounds (int size) { assert(size >= 0); indices.growTo(size,0); } - void increase (int n) { assert(ok(n)); assert(inHeap(n)); percolateUp(indices[n]); } - bool inHeap (int n) const { assert(ok(n)); return indices[n] != 0; } - int size () const { return heap.size()-1; } - bool empty () const { return size() == 0; } - - - void insert(int n) { - assert(!inHeap(n)); - assert(ok(n)); - indices[n] = heap.size(); - heap.push(n); - percolateUp(indices[n]); - } - - - int getmin() { - //printing heap - if(BEEV::print_sat_varorder) { - // fprintf(stderr, "Vijay: heap before getmin: "); - // for (uint i = 1; i < (uint)heap.size(); i++) - // fprintf(stderr, "%d ", heap[i]); - // fprintf(stderr, "\n"); - } - - int r = heap[1]; - heap[1] = heap.last(); - indices[heap[1]] = 1; - indices[r] = 0; - heap.pop(); - if (heap.size() > 1) - percolateDown(1); - return r; - } - - // fool proof variant of insert/increase - void update (int n) { - //fprintf(stderr, "update heap: "); - //for (uint i = 1; i < (uint)heap.size(); i++) - // fprintf(stderr, "%d ", heap[i]); - //fprintf(stderr, "\n"); - setBounds(n+1); - if (!inHeap(n)) - insert(n); - else { - percolateUp(indices[n]); - percolateDown(indices[n]); - } - } - - - bool heapProperty() { - return heapProperty(1); } - - - bool heapProperty(int i) { - return i >= heap.size() - || ((parent(i) == 0 || !comp(heap[i],heap[parent(i)])) && heapProperty(left(i)) && heapProperty(right(i))); } - - template <class F> void filter(const F& filt) { - int i,j; - for (i = j = 1; i < heap.size(); i++) - if (filt(heap[i])){ - heap[j] = heap[i]; - indices[heap[i]] = j++; - }else - indices[heap[i]] = 0; - - heap.shrink(i - j); - for (int i = heap.size() / 2; i >= 1; i--) - percolateDown(i); - - assert(heapProperty()); - } - -}; - -//================================================================================================= -} -#endif diff --git a/stp/sat/LICENSE b/stp/sat/LICENSE deleted file mode 100644 index 590930bc..00000000 --- a/stp/sat/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/stp/sat/Makefile b/stp/sat/Makefile deleted file mode 100644 index 25bb867f..00000000 --- a/stp/sat/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -#===-- stp/sat/Makefile -----------------------------------*- Makefile -*--===# -# -# The KLEE Symbolic Virtual Machine -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -LEVEL=../.. - -LIBRARYNAME=stp_sat -DONT_BUILD_RELINKED=1 -BUILD_ARCHIVE=1 - -include $(LEVEL)/Makefile.common - -# HACK: Force -Wno-deprecated for ext container use. -CXX.Flags += -Wno-deprecated diff --git a/stp/sat/Simplifier.cpp b/stp/sat/Simplifier.cpp deleted file mode 100644 index 2e709066..00000000 --- a/stp/sat/Simplifier.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/************************************************************************************[Simplifier.C] -MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#include "Solver.h" - -namespace MINISAT { - -static const int grow = 0; - -//#define WEAKEN -//#define MATING -//#define ASSYMM - -bool Solver::assymmetricBranching(Clause& c) -{ - assert(decisionLevel() == 0); - - //fprintf(stderr, "assymmetric branching on clause: "); printClause(c); fprintf(stderr, "\n"); - if (satisfied(c)){ - //fprintf(stderr, "subsumed.\n"); - return true; } - - int old; - vec<Lit> copy; for (int i = 0; i < c.size(); i++) copy.push(c[i]); - - do { - assert(copy.size() == c.size()); - - old = copy.size(); - - //fprintf(stderr, "checking that clause is normalized\n"); - //for (int i = 0; i < copy.size(); i++) - // assert(value(copy[i]) == l_Undef); - - for (int i = 0; i < copy.size(); i++){ - trail_lim.push(trail.size()); - //fprintf(stderr, " -- trying to delete literal "); printLit(copy[i]); - for (int j = 0; j < copy.size(); j++) - if (j != i) - check(enqueue(~copy[j])); - - if (propagate() != NULL){ - //fprintf(stderr, " succeeded\n"); - cancelUntil(0); - Lit l = copy[i]; - assert(find(copy, l)); - remove(copy, l); - if (!strengthen(c, l)) - return false; - i--; - - if (c.size() == 1) - return propagate() == NULL; - else - assert(qhead == trail.size()); - } - else - //fprintf(stderr, " failed\n"); - - cancelUntil(0); - } - - //} while (false); - } while (copy.size() < old); - - return true; -} - -// Returns FALSE if clause is always satisfied ('out_clause' should not be used). -//bool Solver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause) -bool Solver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause) -{ - stats.merges++; - - bool ps_smallest = _ps.size() < _qs.size(); - const Clause& ps = ps_smallest ? _qs : _ps; - const Clause& qs = ps_smallest ? _ps : _qs; - - for (int i = 0; i < qs.size(); i++){ - if (var(qs[i]) != v){ - for (int j = 0; j < ps.size(); j++) - if (var(ps[j]) == var(qs[i])) { - if (ps[j] == ~qs[i]) - return false; - else - goto next; - } - out_clause.push(qs[i]); - } - next:; - } - - for (int i = 0; i < ps.size(); i++) - if (var(ps[i]) != v) - out_clause.push(ps[i]); - - return true; -} - - -void Solver::gather(vec<Clause*>& clauses) -{ - //fprintf(stderr, "Gathering clauses for backwards subsumption\n"); - int ntouched = 0; - assert(touched.size() == occurs.size()); - clauses.clear(); - for (int i = 0; i < touched.size(); i++) - if (touched[i]){ - const vec<Clause*>& cs = getOccurs(i); - ntouched++; - for (int j = 0; j < cs.size(); j++) - if (cs[j]->mark() == 0){ - clauses.push(cs[j]); - cs[j]->mark(2); - } - touched[i] = 0; - } - - //fprintf(stderr, "Touched variables %d of %d yields %d clauses to check\n", ntouched, touched.size(), clauses.size()); - for (int i = 0; i < clauses.size(); i++) - clauses[i]->mark(0); -} - - -/*_________________________________________________________________________________________________ -| -| subsumes : (_c : ClauseId) (c : Clause&) (_d : ClauseId) (d : Clause&) -> bool -| -| Description: -| Checks if c subsumes d, and at the same time, if c can be used to simplify d by subsumption -| resolution. -| -| Input: -| Indices into the 'clauses' vector _c, _d, and references to the corresponding clauses c, d. -| -| Result: -| lit_Error - No subsumption or simplification -| lit_Undef - Clause c subsumes d -| l - The literal l can be deleted from d -|________________________________________________________________________________________________@*/ -inline Lit Solver::subsumes(const Clause& c, const Clause& d) -{ - stats.subsumption_checks++; - if (d.size() < c.size() || (c.abstraction() & ~d.abstraction()) != 0) - return lit_Error; - - Lit ret = lit_Undef; - - for (int i = 0; i < c.size(); i++) { - // search for c[i] or ~c[i] - for (int j = 0; j < d.size(); j++) - if (c[i] == d[j]) - goto ok; - else if (ret == lit_Undef && c[i] == ~d[j]){ - ret = c[i]; - goto ok; - } - - // did not find it - stats.subsumption_misses++; - return lit_Error; - ok:; - } - - return ret; -} - - -// Backward subsumption + backward subsumption resolution -bool Solver::backwardSubsumptionCheck() -{ - while (subsumption_queue.size() > 0 || qhead < trail.size()){ - - // if propagation queue is non empty, take the first literal and - // create a dummy unit clause - if (qhead < trail.size()){ - Lit l = trail[qhead++]; - (*bwdsub_tmpunit)[0] = l; - assert(bwdsub_tmpunit->mark() == 0); - subsumption_queue.push(bwdsub_tmpunit); - } - Clause& c = *subsumption_queue.last(); subsumption_queue.pop(); - - if (c.mark()) - continue; - - if (c.size() == 1 && !enqueue(c[0])) - return false; - - // (1) find best variable to scan - Var best = var(c[0]); - for (int i = 1; i < c.size(); i++) - if (occurs[var(c[i])].size() < occurs[best].size()) - best = var(c[i]); - - // (2) search all candidates - const vec<Clause*>& cs = getOccurs(best); - - for (int j = 0; j < cs.size(); j++) - if (cs[j] != &c){ - if (cs[j]->mark()) - continue; - if (c.mark()) - break; - - //fprintf(stderr, "backward candidate "); printClause(*cs[j]); fprintf(stderr, "\n"); - Lit l = subsumes(c, *cs[j]); - if (l == lit_Undef){ - //fprintf(stderr, "clause backwards subsumed\n"); - //fprintf(stderr, " >> clause %d: ", cs[j]->mark()); printClause(*cs[j]); fprintf(stderr, "\n"); - //fprintf(stderr, " >> clause %d: ", c.mark()); printClause(c); fprintf(stderr, "\n"); - removeClause(*cs[j], false); - }else if (l != lit_Error){ - //fprintf(stderr, "backwards subsumption resolution\n"); - //fprintf(stderr, " >> clause %d: ", cs[j]->mark()); printClause(*cs[j]); fprintf(stderr, "\n"); - //fprintf(stderr, " >> clause %d: ", c.mark()); printClause(c); fprintf(stderr, "\n"); - - assert(cs[j]->size() > 1); - assert(find(*cs[j], ~l)); - - subsumption_queue.push(cs[j]); - if (!strengthen(*cs[j], ~l)) - return false; - - // did current candidate get deleted from cs? then check candidate at index j again - if (var(l) == best) - j--; - } - } - } - - return true; -} - - -bool Solver::eliminateVar(Var v, bool fail) -{ - assert(hasVarProp(v, p_frozen)); - - vec<Clause*> pos, neg; - const vec<Clause*>& cls = getOccurs(v); - - if (value(v) != l_Undef || cls.size() == 0) - return true; - - //fprintf(stderr, "trying to eliminate var %d\n", v+1); - for (int i = 0; i < cls.size(); i++){ - //fprintf(stderr, "clause: "); printClause(*cls[i]); fprintf(stderr, "\n"); - if (find(*cls[i], Lit(v))) - pos.push(cls[i]); - else{ - assert(find(*cls[i], ~Lit(v))); - neg.push(cls[i]); - } - } - -#ifdef WEAKEN - vec<int> posc(pos.size(), 0); - vec<int> negc(neg.size(), 0); -#endif - // check if number of clauses decreases - int cnt = 0; - vec<Lit> resolvent; - for (int i = 0; i < pos.size(); i++) - for (int j = 0; j < neg.size(); j++){ - resolvent.clear(); - if (merge(*pos[i], *neg[j], v, resolvent)){ - cnt++; -#ifdef WEAKEN - posc[i]++; - negc[j]++; -#endif - } -#ifndef WEAKEN - if (cnt > cls.size() + grow) - return true; -#else -#ifdef MATING - if (cnt > cls.size() + grow) - if (posc[i] > 0) - break; -#endif -#endif - assert(pos.size() <= n_occ[toInt(Lit(v))]); - assert(neg.size() <= n_occ[toInt(~Lit(v))]); - } - -#ifdef WEAKEN -#ifdef MATING - for (int i = 0; i < neg.size(); i++) - if (negc[i] == 0) - for (int j = 0; j < pos.size(); j++){ - resolvent.clear(); - if (merge(*neg[i], *pos[j], v, resolvent)){ - negc[i]++; - break; - } - } -#endif - for (int i = 0; i < pos.size(); i++) - if (posc[i] == 0) - removeClause(*pos[i], false); - - for (int i = 0; i < neg.size(); i++) - if (negc[i] == 0) - removeClause(*neg[i], false); - - if (cnt > cls.size() + grow) - return true; -#endif - //if (pos.size() != n_occ[toInt(Lit(v))]) - // fprintf(stderr, "pos.size() = %d, n_occ[toInt(Lit(v))] = %d\n", pos.size(), n_occ[toInt(Lit(v))]); - assert(pos.size() == n_occ[toInt(Lit(v))]); - //if (neg.size() != n_occ[toInt(~Lit(v))]) - // fprintf(stderr, "neg.size() = %d, n_occ[toInt(Lit(v))] = %d\n", neg.size(), n_occ[toInt(Lit(v))]); - assert(neg.size() == n_occ[toInt(~Lit(v))]); - assert(cnt <= cls.size() + grow); - setVarProp(v, p_decisionvar, false); - - // produce clauses in cross product - int top = clauses.size(); - for (int i = 0; i < pos.size(); i++) - for (int j = 0; j < neg.size(); j++){ - resolvent.clear(); -#ifdef WEAKEN - if (pos[i]->mark() == 1) - break; - if (neg[j]->mark() == 1) - continue; -#endif - - if (merge(*pos[i], *neg[j], v, resolvent)){ - int i, j; - for (i = j = 0; i < resolvent.size(); i++) - if (value(resolvent[i]) == l_True) - goto next; - else if (value(resolvent[i]) == l_Undef) - resolvent[j++] = resolvent[i]; - resolvent.shrink(i - j); - - if (resolvent.size() == 1){ - if (!enqueue(resolvent[0])) - return false; - }else{ - int apa = clauses.size(); - check(newClause(resolvent, false, true)); - assert(apa + 1 == clauses.size()); - } - } - next:; - } - - if (fail){ - fprintf(stderr, "eliminated var %d, %d <= %d\n", v+1, cnt, cls.size()); - fprintf(stderr, "previous clauses:\n"); - for (int i = 0; i < cls.size(); i++){ - printClause(*cls[i]); - fprintf(stderr, "\n"); - } - - fprintf(stderr, "new clauses:\n"); - for (int i = top; i < clauses.size(); i++){ - printClause(*clauses[i]); - fprintf(stderr, "\n"); - } - - assert(0); } - - //fprintf(stderr, "eliminated var %d, %d <= %d\n", v+1, cnt, cls.size()); - //fprintf(stderr, "previous clauses:\n"); - //for (int i = 0; i < cls.size(); i++){ - // printClause(*cls[i]); - // fprintf(stderr, "\n"); - //} - // - //fprintf(stderr, "new clauses:\n"); - //for (int i = top; i < clauses.size(); i++){ - // printClause(*clauses[i]); - // fprintf(stderr, "\n"); - //} - - // delete + store old clauses - eliminated_var.push(v); - eliminated_lim.push(eliminated.size()); - for (int i = 0; i < cls.size(); i++){ - eliminated.push(Clause_new(*cls[i])); - -#ifdef WEAKEN - if (cls[i]->mark() == 0) -#endif - removeClause(*cls[i], false); - - } - - assert(subsumption_queue.size() == 0); - for (int i = top; i < clauses.size(); i++) -#ifdef ASSYMM - if (clauses[i]->mark() == 0) - if (!assymmetricBranching(*clauses[i])) - return false; - else - subsumption_queue.push(clauses[i]); -#else - if (clauses[i]->mark() == 0) - subsumption_queue.push(clauses[i]); -#endif - - return backwardSubsumptionCheck(); -} - - -void Solver::extendModel() -{ - assert(eliminated_var.size() == eliminated_lim.size()); - for (int i = eliminated_var.size()-1; i >= 0; i--){ - Var v = eliminated_var[i]; - Lit l = lit_Undef; - - //fprintf(stderr, "extending var %d\n", v+1); - - for (int j = eliminated_lim[i]; j < (i+1 >= eliminated_lim.size() ? eliminated.size() : eliminated_lim[i+1]); j++){ - assert(j < eliminated.size()); - Clause& c = *eliminated[j]; - - //fprintf(stderr, "checking clause: "); printClause(c); fprintf(stderr, "\n"); - - for (int k = 0; k < c.size(); k++) - if (var(c[k]) == v) - l = c[k]; - else if (value(c[k]) != l_False) - goto next; - - assert(l != lit_Undef); - //fprintf(stderr, "Fixing var %d to %d\n", v+1, !sign(l)); - - assigns[v] = toInt(lbool(!sign(l))); - break; - - next:; - } - - if (value(v) == l_Undef) - assigns[v] = toInt(l_True); - } -} - - -bool Solver::eliminate() -{ - assert(subsumption); - - int cnt = 0; - //fprintf(stderr, "eliminating variables\n"); - -#ifdef INVARIANTS - // check that all clauses are simplified - fprintf(stderr, "Checking that all clauses are normalized prior to variable elimination\n"); - for (int i = 0; i < clauses.size(); i++) - if (clauses[i]->mark() == 0){ - Clause& c = *clauses[i]; - for (int j = 0; j < c.size(); j++) - assert(value(c[j]) == l_Undef); - } - fprintf(stderr, "done.\n"); -#endif - - for (;;){ - gather(subsumption_queue); - - if (subsumption_queue.size() == 0 && heap.size() == 0) - break; - - //fprintf(stderr, "backwards subsumption: %10d\n", subsumption_queue.size()); - if (!backwardSubsumptionCheck()) - return false; - - //fprintf(stderr, "variable elimination: %10d\n", heap.size()); - cnt = 0; - for (;;){ - assert(!heap.empty() || heap.size() == 0); - if (heap.empty()) - break; - - Var elim = heap.getmin(); - - assert(hasVarProp(elim, p_frozen)); - - //for (int i = 1; i < heap.heap.size(); i++) - // assert(heap.comp(elim, heap.heap[i]) || !heap.comp(elim, heap.heap[i])); - - //if (cnt++ % 100 == 0) - // fprintf(stderr, "left %10d\r", heap.size()); - - if (!eliminateVar(elim)) - return false; - } - } -#ifdef INVARIANTS - // check that no more subsumption is possible - fprintf(stderr, "Checking that no more subsumption is possible\n"); - cnt = 0; - for (int i = 0; i < clauses.size(); i++){ - if (cnt++ % 1000 == 0) - fprintf(stderr, "left %10d\r", clauses.size() - i); - for (int j = 0; j < i; j++) - assert(clauses[i]->mark() || - clauses[j]->mark() || - subsumes(*clauses[i], *clauses[j]) == lit_Error); - } - fprintf(stderr, "done.\n"); - - // check that no more elimination is possible - fprintf(stderr, "Checking that no more elimination is possible\n"); - for (int i = 0; i < nVars(); i++){ - if (hasVarProp(i, p_frozen)) - eliminateVar(i, true); - } - fprintf(stderr, "done.\n"); - -#endif - - assert(qhead == trail.size()); - - return true; -} -} diff --git a/stp/sat/Solver.cpp b/stp/sat/Solver.cpp deleted file mode 100644 index 9761c719..00000000 --- a/stp/sat/Solver.cpp +++ /dev/null @@ -1,813 +0,0 @@ -/****************************************************************************************[Solver.C] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#include "Solver.h" -#include "Sort.h" -#include <cmath> - -namespace MINISAT { -//================================================================================================= -// Operations on clauses: - - -/*_________________________________________________________________________________________________ -| -| newClause : (ps : const vec<Lit>&) (learnt : bool) -> [void] -| -| Description: -| Allocate and add a new clause to the SAT solvers clause database. -| -| Input: -| ps - The new clause as a vector of literals. -| learnt - Is the clause a learnt clause? For learnt clauses, 'ps[0]' is assumed to be the -| asserting literal. An appropriate 'enqueue()' operation will be performed on this -| literal. One of the watches will always be on this literal, the other will be set to -| the literal with the highest decision level. -| -| Effect: -| Activity heuristics are updated. -|________________________________________________________________________________________________@*/ -bool Solver::newClause(const vec<Lit>& ps_, bool learnt, bool normalized) -{ - vec<Lit> qs; - if (!learnt && !normalized){ - assert(decisionLevel() == 0); - ps_.copyTo(qs); // Make a copy of the input vector. - - // Remove duplicates: - sortUnique(qs); - - // Check if clause is satisfied: - for (int i = 0; i < qs.size()-1; i++){ - if (qs[i] == ~qs[i+1]) - return true; } - for (int i = 0; i < qs.size(); i++){ - if (value(qs[i]) == l_True) - return true; } - - // Remove false literals: - int i, j; - for (i = j = 0; i < qs.size(); i++) - if (value(qs[i]) != l_False) - qs[j++] = qs[i]; - qs.shrink(i - j); - } - const vec<Lit>& ps = learnt || normalized ? ps_ : qs; // 'ps' is now the (possibly) reduced vector of literals. - - if (ps.size() == 0) - return false; - else if (ps.size() == 1){ - assert(decisionLevel() == 0); - return enqueue(ps[0]); - }else{ - // Allocate clause: - Clause* c = Clause_new(ps, learnt); - - if (learnt){ - // Put the second watch on the first literal with highest decision level: - // (requires that this method is called at the level where the clause is asserting!) - int i; - for (i = 1; i < ps.size() && position(trailpos[var(ps[i])]) < trail_lim.last(); i++) - ; - (*c)[1] = ps[i]; - (*c)[i] = ps[1]; - - // Bump, enqueue, store clause: - claBumpActivity(*c); // (newly learnt clauses should be considered active) - check(enqueue((*c)[0], c)); - learnts.push(c); - stats.learnts_literals += c->size(); - }else{ - // Store clause: - clauses.push(c); - stats.clauses_literals += c->size(); - - if (subsumption){ - c->calcAbstraction(); - for (int i = 0; i < c->size(); i++){ - assert(!find(occurs[var((*c)[i])], c)); - occurs[var((*c)[i])].push(c); - n_occ[toInt((*c)[i])]++; - touched[var((*c)[i])] = 1; - - if (heap.inHeap(var((*c)[i]))) - updateHeap(var((*c)[i])); - } - } - - } - // Watch clause: - watches[toInt(~(*c)[0])].push(c); - watches[toInt(~(*c)[1])].push(c); - } - - return true; -} - - -// Disposes a clauses and removes it from watcher lists. NOTE! -// Low-level; does NOT change the 'clauses' and 'learnts' vector. -// -void Solver::removeClause(Clause& c, bool dealloc) -{ - //fprintf(stderr, "delete %d: ", _c); printClause(c); fprintf(stderr, "\n"); - assert(c.mark() == 0); - - if (c.size() > 1){ - assert(find(watches[toInt(~c[0])], &c)); - assert(find(watches[toInt(~c[1])], &c)); - remove(watches[toInt(~c[0])], &c); - remove(watches[toInt(~c[1])], &c); } - - if (c.learnt()) stats.learnts_literals -= c.size(); - else stats.clauses_literals -= c.size(); - - if (subsumption && !c.learnt()){ - for (int i = 0; i < c.size(); i++){ - if (dealloc){ - assert(find(occurs[var(c[i])], &c)); - remove(occurs[var(c[i])], &c); - } - n_occ[toInt(c[i])]--; - updateHeap(var(c[i])); - } - } - - if (dealloc) - xfree(&c); - else - c.mark(1); -} - - -bool Solver::satisfied(Clause& c) const -{ - for (int i = 0; i < c.size(); i++) - if (value(c[i]) == l_True) - return true; - return false; } - - -bool Solver::strengthen(Clause& c, Lit l) -{ - assert(decisionLevel() == 0); - assert(c.size() > 1); - assert(c.mark() == 0); - - assert(toInt(~c[0]) < watches.size()); - assert(toInt(~c[1]) < watches.size()); - - assert(find(watches[toInt(~c[0])], &c)); - assert(find(watches[toInt(~c[1])], &c)); - assert(find(c,l)); - - if (c.learnt()) stats.learnts_literals -= 1; - else stats.clauses_literals -= 1; - - if (c[0] == l || c[1] == l){ - assert(find(watches[toInt(~l)], &c)); - remove(c,l); - remove(watches[toInt(~l)], &c); - if (c.size() > 1){ - assert(!find(watches[toInt(~c[1])], &c)); - watches[toInt(~c[1])].push(&c); } - else { - assert(find(watches[toInt(~c[0])], &c)); - remove(watches[toInt(~c[0])], &c); - removeClause(c, false); - } - } - else - remove(c,l); - - assert(c.size() == 1 || find(watches[toInt(~c[0])], &c)); - assert(c.size() == 1 || find(watches[toInt(~c[1])], &c)); - - if (subsumption){ - assert(find(occurs[var(l)], &c)); - remove(occurs[var(l)], &c); - assert(!find(occurs[var(l)], &c)); - - c.calcAbstraction(); - - n_occ[toInt(l)]--; - updateHeap(var(l)); - } - - return c.size() == 1 ? enqueue(c[0]) : true; -} - - -//================================================================================================= -// Minor methods: - - -// Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be -// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result). -// -Var Solver::newVar(bool polarity, bool dvar) { - int index; - index = nVars(); - watches .push(); // (list for positive literal) - watches .push(); // (list for negative literal) - reason .push(NULL); - assigns .push(toInt(l_Undef)); - trailpos .push(TrailPos(0,0)); - activity .push(0); - order .newVar(polarity,dvar); - seen .push(0); - touched .push(0); - if (subsumption){ - occurs .push(); - n_occ .push(0); - n_occ .push(0); - heap .setBounds(index+1); - } - return index; } - - -// Returns FALSE if immediate conflict. -bool Solver::assume(Lit p) { - trail_lim.push(trail.size()); - return enqueue(p); } - - -// Revert to the state at given level. -void Solver::cancelUntil(int level) { - if (decisionLevel() > level){ - for (int c = trail.size()-1; c >= trail_lim[level]; c--){ - Var x = var(trail[c]); - assigns[x] = toInt(l_Undef); - reason [x] = NULL; - order.undo(x); } - qhead = trail_lim[level]; - trail.shrink(trail.size() - trail_lim[level]); - trail_lim.shrink(trail_lim.size() - level); - } -} - - -//================================================================================================= -// Major methods: - - -/*_________________________________________________________________________________________________ -| -| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void] -| -| Description: -| Analyze conflict and produce a reason clause. -| -| Pre-conditions: -| * 'out_learnt' is assumed to be cleared. -| * Current decision level must be greater than root level. -| -| Post-conditions: -| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. -| -| Effect: -| Will undo part of the trail, upto but not beyond the assumption of the current decision level. -|________________________________________________________________________________________________@*/ -void Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel) -{ - int pathC = 0; - int btpos = -1; - Lit p = lit_Undef; - - // Generate conflict clause: - // - out_learnt.push(); // (leave room for the asserting literal) - int index = trail.size()-1; - do{ - assert(confl != NULL); // (otherwise should be UIP) - Clause& c = *confl; - - if (c.learnt()) - claBumpActivity(c); - - for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ - Lit q = c[j]; - if (!seen[var(q)] && position(trailpos[var(q)]) >= trail_lim[0]){ - varBumpActivity(q); - seen[var(q)] = 1; - if (position(trailpos[var(q)]) >= trail_lim.last()) - pathC++; - else{ - out_learnt.push(q); - btpos = max(btpos, position(trailpos[var(q)])); - } - } - } - - // Select next clause to look at: - while (!seen[var(trail[index--])]) ; - p = trail[index+1]; - confl = reason[var(p)]; - seen[var(p)] = 0; - pathC--; - - }while (pathC > 0); - out_learnt[0] = ~p; - - // Find correct backtrack level - for (out_btlevel = trail_lim.size()-1; out_btlevel > 0 && trail_lim[out_btlevel-1] > btpos; out_btlevel--) - ; - - int i, j; - if (expensive_ccmin){ - // Simplify conflict clause (a lot): - // - uint min_level = 0; - for (i = 1; i < out_learnt.size(); i++) - min_level |= abstractLevel(trailpos[var(out_learnt[i])]); // (maintain an abstraction of levels involved in conflict) - - out_learnt.copyTo(analyze_toclear); - for (i = j = 1; i < out_learnt.size(); i++) - if (reason[var(out_learnt[i])] == NULL || !analyze_removable(out_learnt[i], min_level)) - out_learnt[j++] = out_learnt[i]; - }else{ - // Simplify conflict clause (a little): - // - out_learnt.copyTo(analyze_toclear); - for (i = j = 1; i < out_learnt.size(); i++){ - Clause& c = *reason[var(out_learnt[i])]; - for (int k = 1; k < c.size(); k++) - if (!seen[var(c[k])] && position(trailpos[var(c[k])]) >= trail_lim[0]){ - out_learnt[j++] = out_learnt[i]; - break; } - } - } - - stats.max_literals += out_learnt.size(); - out_learnt.shrink(i - j); - stats.tot_literals += out_learnt.size(); - - for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) -} - - -// Check if 'p' can be removed. 'min_level' is used to abort early if visiting literals at a level that cannot be removed. -// -bool Solver::analyze_removable(Lit p, uint min_level) -{ - analyze_stack.clear(); analyze_stack.push(p); - int top = analyze_toclear.size(); - while (analyze_stack.size() > 0){ - assert(reason[var(analyze_stack.last())] != NULL); - Clause& c = *reason[var(analyze_stack.last())]; analyze_stack.pop(); - - for (int i = 1; i < c.size(); i++){ - Lit p = c[i]; - TrailPos tp = trailpos[var(p)]; - if (!seen[var(p)] && position(tp) >= trail_lim[0]){ - if (reason[var(p)] != NULL && (abstractLevel(tp) & min_level) != 0){ - seen[var(p)] = 1; - analyze_stack.push(p); - analyze_toclear.push(p); - }else{ - for (int j = top; j < analyze_toclear.size(); j++) - seen[var(analyze_toclear[j])] = 0; - analyze_toclear.shrink(analyze_toclear.size() - top); - return false; - } - } - } - } - - return true; -} - - -/*_________________________________________________________________________________________________ -| -| analyzeFinal : (p : Lit) -> [void] -| -| Description: -| Specialized analysis procedure to express the final conflict in terms of assumptions. -| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and -| stores the result in 'out_conflict'. -|________________________________________________________________________________________________@*/ -void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict) -{ - out_conflict.clear(); - out_conflict.push(p); - - if (decisionLevel() == 0) - return; - - seen[var(p)] = 1; - - int start = position(trailpos[var(p)]); - for (int i = start; i >= trail_lim[0]; i--){ - Var x = var(trail[i]); - if (seen[x]){ - if (reason[x] == NULL){ - assert(position(trailpos[x]) >= trail_lim[0]); - out_conflict.push(~trail[i]); - }else{ - Clause& c = *reason[x]; - for (int j = 1; j < c.size(); j++) - if (position(trailpos[var(c[j])]) >= trail_lim[0]) - seen[var(c[j])] = 1; - } - seen[x] = 0; - } - } -} - - -/*_________________________________________________________________________________________________ -| -| enqueue : (p : Lit) (from : Clause*) -> [bool] -| -| Description: -| Puts a new fact on the propagation queue as well as immediately updating the variable's value. -| Should a conflict arise, FALSE is returned. -| -| Input: -| p - The fact to enqueue -| from - [Optional] Fact propagated from this (currently) unit clause. Stored in 'reason[]'. -| Default value is NULL (no reason). -| -| Output: -| TRUE if fact was enqueued without conflict, FALSE otherwise. -|________________________________________________________________________________________________@*/ -bool Solver::enqueue(Lit p, Clause* from) -{ - - if (value(p) != l_Undef) - return value(p) != l_False; - else{ - assigns [var(p)] = toInt(lbool(!sign(p))); - trailpos[var(p)] = TrailPos(trail.size(),decisionLevel()); - reason [var(p)] = from; - trail.push(p); - return true; - } -} - - -/*_________________________________________________________________________________________________ -| -| propagate : [void] -> [Clause*] -| -| Description: -| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, -| otherwise NULL. -| -| Post-conditions: -| * the propagation queue is empty, even if there was a conflict. -|________________________________________________________________________________________________@*/ -Clause* Solver::propagate() -{ - if (decisionLevel() == 0 && subsumption) - return backwardSubsumptionCheck() ? NULL : propagate_tmpempty; - - Clause* confl = NULL; - //fprintf(stderr, "propagate, qhead = %d, qtail = %d\n", qhead, qtail); - while (qhead < trail.size()){ - stats.propagations++; - simpDB_props--; - - Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. - vec<Clause*>& ws = watches[toInt(p)]; - Clause **i, **j, **end; - - for (i = j = (Clause**)ws, end = i + ws.size(); i != end;){ - Clause& c = **i++; - - // Make sure the false literal is data[1]: - Lit false_lit = ~p; - if (c[0] == false_lit) - c[0] = c[1], c[1] = false_lit; - - assert(c[1] == false_lit); - - // If 0th watch is true, then clause is already satisfied. - Lit first = c[0]; - if (value(first) == l_True){ - *j++ = &c; - }else{ - // Look for new watch: - for (int k = 2; k < c.size(); k++) - if (value(c[k]) != l_False){ - c[1] = c[k]; c[k] = false_lit; - watches[toInt(~c[1])].push(&c); - goto FoundWatch; } - - // Did not find watch -- clause is unit under assignment: - *j++ = &c; - if (!enqueue(first, &c)){ - confl = &c; - qhead = trail.size(); - // Copy the remaining watches: - while (i < end) - *j++ = *i++; - } - FoundWatch:; - } - } - ws.shrink(i - j); - } - - return confl; -} - - -/*_________________________________________________________________________________________________ -| -| reduceDB : () -> [void] -| -| Description: -| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked -| clauses are clauses that are reason to some assignment. Binary clauses are never removed. -|________________________________________________________________________________________________@*/ -struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } }; -void Solver::reduceDB() -{ - int i, j; - double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity - - sort(learnts, reduceDB_lt()); - for (i = j = 0; i < learnts.size() / 2; i++){ - if (learnts[i]->size() > 2 && !locked(*learnts[i])) - removeClause(*learnts[i]); - else - learnts[j++] = learnts[i]; - } - for (; i < learnts.size(); i++){ - if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() < extra_lim) - removeClause(*learnts[i]); - else - learnts[j++] = learnts[i]; - } - learnts.shrink(i - j); -} - - -/*_________________________________________________________________________________________________ -| -| simplifyDB : [void] -> [bool] -| -| Description: -| Simplify the clause database according to the current top-level assigment. Currently, the only -| thing done here is the removal of satisfied clauses, but more things can be put here. -|________________________________________________________________________________________________@*/ -bool Solver::simplifyDB(bool expensive) -{ - assert(decisionLevel() == 0); - if (!ok || propagate() != NULL) - return ok = false; - - if (nAssigns() == simpDB_assigns || - (!subsumption && simpDB_props > 0)) // (nothing has changed or preformed a simplification too recently) - return true; - - if (subsumption){ - if (expensive && !eliminate()) - return ok = false; - - // Move this cleanup code to its own method ? - int i , j; - vec<Var> dirty; - for (i = 0; i < clauses.size(); i++) - if (clauses[i]->mark() == 1){ - Clause& c = *clauses[i]; - for (int k = 0; k < c.size(); k++) - if (!seen[var(c[k])]){ - seen[var(c[k])] = 1; - dirty.push(var(c[k])); - } - } - - for (i = 0; i < dirty.size(); i++){ - cleanOcc(dirty[i]); - seen[dirty[i]] = 0; - } - - for (i = j = 0; i < clauses.size(); i++) - if (clauses[i]->mark() == 1) - xfree(clauses[i]); - else - clauses[j++] = clauses[i]; - clauses.shrink(i - j); - } - - // Remove satisfied clauses: - for (int type = 0; type < (subsumption ? 1 : 2); type++){ // (only scan learnt clauses if subsumption is on) - vec<Clause*>& cs = type ? learnts : clauses; - int j = 0; - for (int i = 0; i < cs.size(); i++){ - assert(cs[i]->mark() == 0); - if (satisfied(*cs[i])) - removeClause(*cs[i]); - else - cs[j++] = cs[i]; - } - cs.shrink(cs.size()-j); - } - order.cleanup(); - - simpDB_assigns = nAssigns(); - simpDB_props = stats.clauses_literals + stats.learnts_literals; // (shouldn't depend on 'stats' really, but it will do for now) - - return true; -} - - -/*_________________________________________________________________________________________________ -| -| search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool] -| -| Description: -| Search for a model the specified number of conflicts, keeping the number of learnt clauses -| below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to -| indicate infinity. -| -| Output: -| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If -| all variables are decision variables, this means that the clause set is satisfiable. 'l_False' -| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. -|________________________________________________________________________________________________@*/ -lbool Solver::search(int nof_conflicts, int nof_learnts) -{ - assert(ok); - int backtrack_level; - int conflictC = 0; - vec<Lit> learnt_clause; - - stats.starts++; - var_decay = 1 / params.var_decay; - cla_decay = 1 / params.clause_decay; - - for (;;){ - Clause* confl = propagate(); - if (confl != NULL){ - // CONFLICT - stats.conflicts++; conflictC++; - if (decisionLevel() == 0) return l_False; - - learnt_clause.clear(); - analyze(confl, learnt_clause, backtrack_level); - cancelUntil(backtrack_level); - newClause(learnt_clause, true); - varDecayActivity(); - claDecayActivity(); - - }else{ - // NO CONFLICT - - if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ - // Reached bound on number of conflicts: - progress_estimate = progressEstimate(); - cancelUntil(0); - return l_Undef; } - - // Simplify the set of problem clauses: - if (decisionLevel() == 0 && !simplifyDB()) - return l_False; - - if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts) - // Reduce the set of learnt clauses: - reduceDB(); - - Lit next = lit_Undef; - - if (decisionLevel() < assumptions.size()){ - // Perform user provided assumption: - next = assumptions[decisionLevel()]; - if (value(next) == l_False){ - analyzeFinal(~next, conflict); - return l_False; } - }else{ - // New variable decision: - stats.decisions++; - next = order.select(params.random_var_freq, decisionLevel()); - } - if (next == lit_Undef) - // Model found: - return l_True; - - check(assume(next)); - } - } -} - - -// Return search-space coverage. Not extremely reliable. -// -double Solver::progressEstimate() -{ - double progress = 0; - double F = 1.0 / nVars(); - - for (int i = 0; i <= decisionLevel(); i++){ - int beg = i == 0 ? 0 : trail_lim[i - 1]; - int end = i == decisionLevel() ? trail.size() : trail_lim[i]; - progress += pow(F, i) * (end - beg); - } - - return progress / nVars(); -} - - -// Divide all variable activities by 1e100. -// -void Solver::varRescaleActivity() -{ - for (int i = 0; i < nVars(); i++) - activity[i] *= 1e-100; - var_inc *= 1e-100; -} - - -// Divide all constraint activities by 1e100. -// -void Solver::claRescaleActivity() -{ - for (int i = 0; i < learnts.size(); i++) - learnts[i]->activity() *= 1e-20; - cla_inc *= 1e-20; -} - - -/*_________________________________________________________________________________________________ -| -| solve : (assumps : const vec<Lit>&) -> [bool] -| -| Description: -| Top-level solve. -|________________________________________________________________________________________________@*/ -bool Solver::solve(const vec<Lit>& assumps) -{ - model.clear(); - conflict.clear(); - - if (!simplifyDB(true)) return false; - - - double nof_conflicts = params.restart_first; - double nof_learnts = nClauses() * params.learntsize_factor; - lbool status = l_Undef; - assumps.copyTo(assumptions); - - if (verbosity >= 1){ - printf("==================================[MINISAT]====================================\n"); - printf("| Conflicts | ORIGINAL | LEARNT | Progress |\n"); - printf("| | Vars Clauses Literals | Limit Clauses Lit/Cl | |\n"); - printf("===============================================================================\n"); - } - - // Search: - while (status == l_Undef){ - if (verbosity >= 1) - //printf("| %9d | %7d %8d | %7d %7d %8d %7.1f | %6.3f %% |\n", (int)stats.conflicts, nClauses(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (int)stats.learnts_literals, (double)stats.learnts_literals/nLearnts(), progress_estimate*100); - printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", (int)stats.conflicts, order.size(), nClauses(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (double)stats.learnts_literals/nLearnts(), progress_estimate*100); - status = search((int)nof_conflicts, (int)nof_learnts); - nof_conflicts *= params.restart_inc; - nof_learnts *= params.learntsize_inc; - } - - if (verbosity >= 1) { - printf("==============================================================================\n"); - fflush(stdout); - } - - if (status == l_True){ - // Copy model: - extendModel(); -#if 1 - //fprintf(stderr, "Verifying model.\n"); - for (int i = 0; i < clauses.size(); i++) - assert(satisfied(*clauses[i])); - for (int i = 0; i < eliminated.size(); i++) - assert(satisfied(*eliminated[i])); -#endif - model.growTo(nVars()); - for (int i = 0; i < nVars(); i++) model[i] = value(i); - }else{ - assert(status == l_False); - if (conflict.size() == 0) - ok = false; - } - - cancelUntil(0); - return status == l_True; -} -} //end of MINISAT namespace diff --git a/stp/sat/Solver.h b/stp/sat/Solver.h deleted file mode 100644 index 0a6dc87e..00000000 --- a/stp/sat/Solver.h +++ /dev/null @@ -1,356 +0,0 @@ -/****************************************************************************************[Solver.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#ifndef Solver_h -#define Solver_h - -#include "SolverTypes.h" -#include "VarOrder.h" - -namespace MINISAT { - -//================================================================================================= -// Solver -- the main class: -struct SolverStats { - int64 starts, decisions, propagations, conflicts; - int64 clauses_literals, learnts_literals, max_literals, tot_literals; - int64 subsumption_checks, subsumption_misses, merges; - SolverStats() : - starts(0), decisions(0), propagations(0), conflicts(0) - , clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0) - , subsumption_checks(0), subsumption_misses(0), merges(0) - { } -}; - - -struct SearchParams { - double var_decay, clause_decay, random_var_freq; - double restart_inc, learntsize_inc, learntsize_factor; - int restart_first; - - SearchParams(double v = 0.95, double c = 0.999, double r = 0.02, - double ri = 1.5, double li = 1.1, double lf = (double)1/(double)3, - int rf = 100) : - var_decay(v), clause_decay(c), random_var_freq(r), - restart_inc(ri), learntsize_inc(li), learntsize_factor(lf), - restart_first(rf) { } -}; - - struct ElimLt { - const vec<int>& n_occ; - - ElimLt(const vec<int>& no) : n_occ(no) {} - int cost (Var x) const { return n_occ[toInt(Lit(x))] * n_occ[toInt(~Lit(x))]; } - bool operator()(Var x, Var y) const { return cost(x) < cost(y); } - }; - -class Solver { -protected: - // Solver state: - bool ok; // If FALSE,the constraints are already unsatisfiable. - // No part of solver state may be used! - vec<Clause*> clauses; // List of problem clauses. - vec<Clause*> learnts; // List of learnt clauses. - int n_bin_clauses; // Keep track of number of binary clauses "inlined" into the watcher lists (we do this primarily to get identical behavior to the version without the binary clauses trick). - double cla_inc; // Amount to bump next clause with. - double cla_decay; // INVERSE decay factor for clause activity: stores 1/decay. - - vec<double> activity; // A heuristic measurement of the activity of a variable. - double var_inc; // Amount to bump next variable with. - double var_decay; // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order. - VarOrder order; // Keeps track of the decision variable order. - vec<char> properties; // TODO: describe!!! - - vec<vec<Clause*> > watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). - vec<char> assigns; // The current assignments (lbool:s stored as char:s). - vec<Lit> trail; // Assignment stack; stores all assigments made in the order they were made. - vec<int> trail_lim; // Separator indices for different decision levels in 'trail'. - vec<Clause*> reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none. - vec<TrailPos> trailpos; // 'trailpos[var]' contains the position in the trail at wich the assigment was made. - int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat). - int simpDB_assigns; // Number of top-level assignments since last execution of 'simplifyDB()'. - int64 simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplifyDB()'. - vec<Lit> assumptions; // Current set of assumptions provided to solve by the user. - - bool subsumption; - vec<char> touched; - vec<vec<Clause*> > occurs; - vec<int> n_occ; - Heap<ElimLt> heap; - vec<Clause*> subsumption_queue; - - vec<Clause*> eliminated; - vec<int> eliminated_lim; - vec<Var> eliminated_var; - - // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is - // used, exept 'seen' wich is used in several places. - // - vec<char> seen; - vec<Lit> analyze_stack; - vec<Lit> analyze_toclear; - Clause* propagate_tmpempty; - Clause* propagate_tmpbin; - Clause* analyze_tmpbin; - Clause* bwdsub_tmpunit; - - vec<Lit> addBinary_tmp; - vec<Lit> addTernary_tmp; - - // Main internal methods: - // - bool assume (Lit p); - void cancelUntil (int level); - void record (const vec<Lit>& clause); - - void analyze (Clause* confl, vec<Lit>& out_learnt, int& out_btlevel); // (bt = backtrack) - bool analyze_removable(Lit p, uint min_level); // (helper method for 'analyze()') - void analyzeFinal (Lit p, vec<Lit>& out_conflict); - bool enqueue (Lit fact, Clause* from = NULL); - Clause* propagate (); - void reduceDB (); - Lit pickBranchLit (); - lbool search (int nof_conflicts, int nof_learnts); - double progressEstimate (); - - // Variable properties: - void setVarProp (Var v, uint prop, bool b) { order.setVarProp(v, prop, b); } - bool hasVarProp (Var v, uint prop) const { return order.hasVarProp(v, prop); } - void updateHeap (Var v) { - if (hasVarProp(v, p_frozen)) - heap.update(v); } - - // Simplification methods: - // - void cleanOcc (Var v) { - assert(subsumption); - vec<Clause*>& occ = occurs[v]; - int i, j; - for (i = j = 0; i < occ.size(); i++) - if (occ[i]->mark() != 1) - occ[j++] = occ[i]; - occ.shrink(i - j); - } - - vec<Clause*>& getOccurs (Var x) { cleanOcc(x); return occurs[x]; } - void gather (vec<Clause*>& clauses); - Lit subsumes (const Clause& c, const Clause& d); - bool assymmetricBranching (Clause& c); - bool merge (const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause); - - bool backwardSubsumptionCheck (); - bool eliminateVar (Var v, bool fail = false); - bool eliminate (); - void extendModel (); - - // Activity: - // - void varBumpActivity(Lit p) { - if (var_decay < 0) return; // (negative decay means static variable order -- don't bump) - if ( (activity[var(p)] += var_inc) > 1e100 ) varRescaleActivity(); - order.update(var(p)); } - void varDecayActivity () { if (var_decay >= 0) var_inc *= var_decay; } - void varRescaleActivity(); - void claDecayActivity () { cla_inc *= cla_decay; } - void claRescaleActivity(); - - // Operations on clauses: - // - bool newClause(const vec<Lit>& ps, bool learnt = false, bool normalized = false); - void claBumpActivity (Clause& c) { if ( (c.activity() += cla_inc) > 1e20 ) claRescaleActivity(); } - bool locked (const Clause& c) const { return reason[var(c[0])] == &c; } - bool satisfied (Clause& c) const; - bool strengthen (Clause& c, Lit l); - void removeClause (Clause& c, bool dealloc = true); - - int decisionLevel() const { return trail_lim.size(); } - -public: - Solver() : ok (true) - , n_bin_clauses (0) - , cla_inc (1) - , cla_decay (1) - , var_inc (1) - , var_decay (1) - , order (assigns, activity) - , qhead (0) - , simpDB_assigns (-1) - , simpDB_props (0) - , subsumption (true) - , heap (n_occ) - , params () - , expensive_ccmin (true) - , verbosity (0) - , progress_estimate(0) - { - vec<Lit> dummy(2,lit_Undef); - propagate_tmpbin = Clause_new(dummy); - analyze_tmpbin = Clause_new(dummy); - dummy.pop(); - bwdsub_tmpunit = Clause_new(dummy); - dummy.pop(); - propagate_tmpempty = Clause_new(dummy); - addBinary_tmp .growTo(2); - addTernary_tmp.growTo(3); - } - - ~Solver() { - xfree(propagate_tmpbin); - xfree(analyze_tmpbin); - xfree(bwdsub_tmpunit); - xfree(propagate_tmpempty); - for (int i = 0; i < eliminated.size(); i++) xfree(eliminated[i]); - for (int i = 0; i < learnts.size(); i++) xfree(learnts[i]); - for (int i = 0; i < clauses.size(); i++) xfree(clauses[i]); } - - // Helpers: (semi-internal) - // - lbool value(Var x) const { return toLbool(assigns[x]); } - lbool value(Lit p) const { return sign(p) ? ~toLbool(assigns[var(p)]) : toLbool(assigns[var(p)]); } - - int nAssigns() { return trail.size(); } - int nClauses() { return clauses.size(); } - int nLearnts() { return learnts.size(); } - int nConflicts() { return (int)stats.conflicts; } - - // Statistics: (read-only member variable) - // - SolverStats stats; - - // Mode of operation: - // - SearchParams params; // Restart frequency etc. - bool expensive_ccmin; // Controls conflict clause minimization. TRUE by default. - int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything - - // Problem specification: - // - Var newVar (bool polarity = true, bool dvar = true); - int nVars () { return assigns.size(); } - bool addUnit (Lit p) { return ok && (ok = enqueue(p)); } - bool addBinary (Lit p, Lit q) { addBinary_tmp [0] = p; addBinary_tmp [1] = q; return addClause(addBinary_tmp); } - bool addTernary(Lit p, Lit q, Lit r) { addTernary_tmp[0] = p; addTernary_tmp[1] = q; addTernary_tmp[2] = r; return addClause(addTernary_tmp); } - bool addClause (const vec<Lit>& ps) { if (ok && !newClause(ps)) ok = false; return ok; } - - // Variable mode: - // - void freezeVar (Var v) { setVarProp(v, p_frozen, true); updateHeap(v); } - - // Solving: - // - bool okay () { return ok; } // FALSE means solver is in a conflicting state - bool simplifyDB (bool expensive = true); - bool solve (const vec<Lit>& assumps); - bool solve () { vec<Lit> tmp; return solve(tmp); } - void turnOffSubsumption() { - subsumption = false; - occurs.clear(true); - n_occ.clear(true); - } - - double progress_estimate; // Set by 'search()'. - vec<lbool> model; // If problem is satisfiable, this vector contains the model (if any). - vec<Lit> conflict; // If problem is unsatisfiable (possibly under assumptions), this vector represent the conflict clause expressed in the assumptions. - - double returnActivity(int i) { return activity[i];} - void updateInitialActivity(int i, double act) {activity[i] = act; order.heap.update(i);} -}; - - -//================================================================================================= -// Debug: - - -#define L_LIT "%sx%d" -#define L_lit(p) sign(p)?"~":"", var(p) - -// Just like 'assert()' but expression will be evaluated in the release version as well. -inline void check(bool expr) { assert(expr); } - -static void printLit(Lit l) -{ - fprintf(stderr, "%s%d", sign(l) ? "-" : "", var(l)+1); -} - -template<class C> -static void printClause(const C& c) -{ - for (int i = 0; i < c.size(); i++){ - printLit(c[i]); - fprintf(stderr, " "); - } -} - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#ifdef _MSC_VER - -#include <ctime> - -static inline double cpuTime(void) { - return (double)clock() / CLOCKS_PER_SEC; } - -static inline int64 memUsed() { - return 0; } - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#else - -#include <sys/time.h> -#include <sys/resource.h> - -static inline double cpuTime(void) { - struct rusage ru; - getrusage(RUSAGE_SELF, &ru); - return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } - -#if defined(__linux__) || defined(__CYGWIN__) -static inline int memReadStat(int field) -{ - char name[256]; - pid_t pid = getpid(); - sprintf(name, "/proc/%d/statm", pid); - FILE* in = fopen(name, "rb"); - if (in == NULL) return 0; - int value; - for (; field >= 0; field--) { - int res = fscanf(in, "%d", &value); - (void) res; - } - fclose(in); - return value; -} - -static inline int64 memUsed() { return (int64)memReadStat(0) * (int64)getpagesize(); } -#else -// use this by default. Mac OS X (Darwin) does not define an os type -//defined(__FreeBSD__) - -static inline int64 memUsed(void) { - struct rusage ru; - getrusage(RUSAGE_SELF, &ru); - return ru.ru_maxrss*1024; } - -#endif - -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#endif - -//================================================================================================= -} -#endif diff --git a/stp/sat/SolverTypes.h b/stp/sat/SolverTypes.h deleted file mode 100644 index fe15a968..00000000 --- a/stp/sat/SolverTypes.h +++ /dev/null @@ -1,132 +0,0 @@ -/***********************************************************************************[SolverTypes.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - - -#ifndef SolverTypes_h -#define SolverTypes_h - -#include "Global.h" - -namespace MINISAT { - -//================================================================================================= -// Variables, literals, clause IDs: - - -// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N, -// so that they can be used as array indices. - -typedef int Var; -#define var_Undef (-1) - - -struct Lit { - int x; - - Lit() : x(2*var_Undef) { } // (lit_Undef) - explicit Lit(Var var, bool sign = false) : x((var+var) + (int)sign) { } -}; - -// Don't use these for constructing/deconstructing literals. Use the normal constructors instead. -inline int toInt (Lit p) { return p.x; } // A "toInt" method that guarantees small, positive integers suitable for array indexing. -inline Lit toLit (int i) { Lit p; p.x = i; return p; } // Inverse of 'toInt()' - -inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; } -inline bool sign (Lit p) { return p.x & 1; } -inline int var (Lit p) { return p.x >> 1; } -inline Lit unsign (Lit p) { Lit q; q.x = p.x & ~1; return q; } -inline Lit id (Lit p, bool sgn) { Lit q; q.x = p.x ^ (int)sgn; return q; } - -inline bool operator == (Lit p, Lit q) { return toInt(p) == toInt(q); } -inline bool operator != (Lit p, Lit q) { return toInt(p) != toInt(q); } -inline bool operator < (Lit p, Lit q) { return toInt(p) < toInt(q); } // '<' guarantees that p, ~p are adjacent in the ordering. - - -const Lit lit_Undef(var_Undef, false); // }- Useful special constants. -const Lit lit_Error(var_Undef, true ); // } - - -//================================================================================================= -// Clause -- a simple class for representing a clause: - -class Clause { - uint size_etc; - union { float act; uint abst; } apa; - Lit data[1]; -public: - // NOTE: This constructor cannot be used directly (doesn't allocate enough memory). - template<class V> - Clause(const V& ps, bool learnt) { - size_etc = (ps.size() << 3) | (uint)learnt; - for (int i = 0; i < ps.size(); i++) data[i] = ps[i]; - if (learnt) apa.act = 0; else apa.abst = 0; } - - // -- use this function instead: - template<class V> - friend Clause* Clause_new(const V& ps, bool learnt = false) { - assert(sizeof(Lit) == sizeof(uint)); - assert(sizeof(float) == sizeof(uint)); - - size_t aux_size = 0; - if (ps.size() > 0) - aux_size = sizeof(uint)*(ps.size() - 1); - - void* mem = xmalloc<char>(sizeof(Clause) + aux_size); - return new (mem) Clause(ps, learnt); } - - int size () const { return size_etc >> 3; } - void shrink (int i) { assert(i <= size()); size_etc = (((size_etc >> 3) - i) << 3) | (size_etc & 7); } - void pop () { shrink(1); } - bool learnt () const { return size_etc & 1; } - uint mark () const { return (size_etc >> 1) & 3; } - void mark (uint m) { size_etc = (size_etc & ~6) | ((m & 3) << 1); } - Lit operator [] (int i) const { return data[i]; } - Lit& operator [] (int i) { return data[i]; } - - float& activity () { return apa.act; } - - uint abstraction () const { return apa.abst; } - - void calcAbstraction() { - uint abstraction = 0; - for (int i = 0; i < size(); i++) - abstraction |= 1 << (var(data[i]) & 31); - apa.abst = abstraction; } -}; - - -//================================================================================================= -// TrailPos -- Stores an index into the trail as well as an approximation of a level. This data -// is recorded for each assigment. (Replaces the old level information) - - -class TrailPos { - int tp; - public: - explicit TrailPos(int index, int level) : tp( (index << 5) + (level & 31) ) { } - - friend int abstractLevel(const TrailPos& p) { return 1 << (p.tp & 31); } - friend int position (const TrailPos& p) { return p.tp >> 5; } - - bool operator == (TrailPos other) const { return tp == other.tp; } - bool operator < (TrailPos other) const { return tp < other.tp; } -}; - -} -#endif diff --git a/stp/sat/Sort.h b/stp/sat/Sort.h deleted file mode 100644 index 9def2990..00000000 --- a/stp/sat/Sort.h +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************************[Sort.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#ifndef Sort_h -#define Sort_h - - -namespace MINISAT { -//================================================================================================= - - -template<class T> -struct LessThan_default { - bool operator () (T x, T y) { return x < y; } -}; - - -//================================================================================================= - - -template <class T, class LessThan> -void selectionSort(T* array, int size, LessThan lt) -{ - int i, j, best_i; - T tmp; - - for (i = 0; i < size-1; i++){ - best_i = i; - for (j = i+1; j < size; j++){ - if (lt(array[j], array[best_i])) - best_i = j; - } - tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; - } -} -template <class T> static inline void selectionSort(T* array, int size) { - selectionSort(array, size, LessThan_default<T>()); } - - -template <class T, class LessThan> -void sort(T* array, int size, LessThan lt, double& seed) -{ - if (size <= 15) - selectionSort(array, size, lt); - - else{ - T pivot = array[irand(seed, size)]; - T tmp; - int i = -1; - int j = size; - - for(;;){ - do i++; while(lt(array[i], pivot)); - do j--; while(lt(pivot, array[j])); - - if (i >= j) break; - - tmp = array[i]; array[i] = array[j]; array[j] = tmp; - } - - sort(array , i , lt, seed); - sort(&array[i], size-i, lt, seed); - } -} -template <class T, class LessThan> void sort(T* array, int size, LessThan lt) { - double seed = 91648253; sort(array, size, lt, seed); } -template <class T> static inline void sort(T* array, int size) { - sort(array, size, LessThan_default<T>()); } - - -template <class T, class LessThan> -void sortUnique(T* array, int& size, LessThan lt) -{ - int i, j; - T last; - - if (size == 0) return; - - sort(array, size, lt); - - i = 1; - last = array[0]; - for (j = 1; j < size; j++){ - if (lt(last, array[j])){ - last = array[i] = array[j]; - i++; } - } - - size = i; -} -template <class T> static inline void sortUnique(T* array, int& size) { - sortUnique(array, size, LessThan_default<T>()); } - - -//================================================================================================= -// For 'vec's: - - -template <class T, class LessThan> void sort(vec<T>& v, LessThan lt) { - sort((T*)v, v.size(), lt); } -template <class T> void sort(vec<T>& v) { - sort(v, LessThan_default<T>()); } - - -template <class T, class LessThan> void sortUnique(vec<T>& v, LessThan lt) { - int size = v.size(); - T* data = v.release(); - sortUnique(data, size, lt); - v.~vec<T>(); - new (&v) vec<T>(data, size); } -template <class T> void sortUnique(vec<T>& v) { - sortUnique(v, LessThan_default<T>()); } - - -//================================================================================================= -} -#endif diff --git a/stp/sat/VarOrder.h b/stp/sat/VarOrder.h deleted file mode 100644 index 6d2a40f0..00000000 --- a/stp/sat/VarOrder.h +++ /dev/null @@ -1,146 +0,0 @@ -/**************************************************************************************[VarOrder.h] -MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ - -#ifndef VarOrder_h -#define VarOrder_h - -#include "SolverTypes.h" -#include "Solver.h" -#include "Heap.h" -#include "../AST/ASTUtil.h" - -namespace MINISAT { - //================================================================================================= - - struct VarOrder_lt { - const vec<double>& activity; - bool operator () (Var x, Var y) { return activity[x] > activity[y]; } - VarOrder_lt(const vec<double>& act) : activity(act) { } - }; - - - enum { p_decisionvar = 0, p_polarity = 1, p_frozen = 2, p_dontcare = 3 }; - - - class VarOrder { - const vec<char>& assigns; // var->val. Pointer to external assignment table. - const vec<double>& activity; // var->act. Pointer to external activity table. - vec<char> properties; - //Heap<VarOrder_lt> heap; - //double random_seed; // For the internal random number generator - - friend class VarFilter; - public: - //FIXME: Vijay: delete after experiments - Heap<VarOrder_lt> heap; - double random_seed; // For the internal random number generator - //FIXME ENDS HERE - - VarOrder(const vec<char>& ass, const vec<double>& act) : - assigns(ass), activity(act), heap(VarOrder_lt(act)), random_seed(2007) - //assigns(ass), activity(act), heap(VarOrder_lt(act)) - { } - - int size () { return heap.size(); } - void setVarProp (Var v, uint prop, bool b) { properties[v] = (properties[v] & ~(1 << prop)) | (b << prop); } - bool hasVarProp (Var v, uint prop) const { return properties[v] & (1 << prop); } - inline void cleanup (); - - inline void newVar(bool polarity, bool dvar); - inline void update(Var x); // Called when variable increased in activity. - inline void undo(Var x); // Called when variable is unassigned and may be selected again. - //Selects a new, unassigned variable (or 'var_Undef' if none exists). - inline Lit select(double random_freq =.0, int decision_level = 0); - }; - - - struct VarFilter { - const VarOrder& o; - VarFilter(const VarOrder& _o) : o(_o) {} - bool operator()(Var v) const { return toLbool(o.assigns[v]) == l_Undef && o.hasVarProp(v, p_decisionvar); } - //bool operator()(Var v) const { return toLbool(o.assigns[v]) == l_Undef; } - }; - - void VarOrder::cleanup() - { - VarFilter f(*this); - heap.filter(f); - } - - void VarOrder::newVar(bool polarity, bool dvar) - { - Var v = assigns.size()-1; - heap.setBounds(v+1); - properties.push(0); - setVarProp(v, p_decisionvar, dvar); - setVarProp(v, p_polarity, polarity); - undo(v); - } - - - void VarOrder::update(Var x) - { - if (heap.inHeap(x)) - heap.increase(x); - } - - - void VarOrder::undo(Var x) - { - if (!heap.inHeap(x) && hasVarProp(x, p_decisionvar)) - heap.insert(x); - } - - - Lit VarOrder::select(double random_var_freq, int decision_level) - { - Var next = var_Undef; - - if (drand(random_seed) < random_var_freq && !heap.empty()) - next = irand(random_seed,assigns.size()); - - // Activity based decision: - while (next == var_Undef || toLbool(assigns[next]) != l_Undef || !hasVarProp(next, p_decisionvar)) - if (heap.empty()){ - next = var_Undef; - break; - }else - next = heap.getmin(); - - //printing - if(BEEV::print_sat_varorder) { - if (next != var_Undef) { - BEEV::Convert_MINISATVar_To_ASTNode_Print(next, - decision_level, - hasVarProp(next, p_polarity)); - // fprintf(stderr,"var = %d, prop = %d, decision = %d, polarity = %d, frozen = %d\n", - // next+1, properties[next], hasVarProp(next, p_decisionvar), - // hasVarProp(next, p_polarity), hasVarProp(next, p_frozen)); - } - else - fprintf(stderr, "var = undef\n"); - } - - return next == var_Undef ? lit_Undef : Lit(next, hasVarProp(next, p_polarity)); - } - - - //================================================================================================= -} -#endif diff --git a/stp/simplifier/Makefile b/stp/simplifier/Makefile deleted file mode 100644 index 7aeb3ffc..00000000 --- a/stp/simplifier/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -#===-- stp/simplifier/Makefile -----------------------------*- Makefile -*--===# -# -# The KLEE Symbolic Virtual Machine -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -LEVEL=../.. - -LIBRARYNAME=stp_simplifier -DONT_BUILD_RELINKED=1 -BUILD_ARCHIVE=1 - -include $(LEVEL)/Makefile.common - -# HACK: Force -Wno-deprecated for ext container use. -CXX.Flags += -Wno-deprecated diff --git a/stp/simplifier/bvsolver.cpp b/stp/simplifier/bvsolver.cpp deleted file mode 100644 index 369251db..00000000 --- a/stp/simplifier/bvsolver.cpp +++ /dev/null @@ -1,714 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -#include "../AST/AST.h" -#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 { - 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; - } - } - 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; - } - 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; - } - - 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 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; - } - - //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 diff --git a/stp/simplifier/bvsolver.h b/stp/simplifier/bvsolver.h deleted file mode 100644 index 8df32042..00000000 --- a/stp/simplifier/bvsolver.h +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -#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(); - } - - //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 diff --git a/stp/simplifier/simplifier.cpp b/stp/simplifier/simplifier.cpp deleted file mode 100644 index c0519e83..00000000 --- a/stp/simplifier/simplifier.cpp +++ /dev/null @@ -1,2495 +0,0 @@ -/******************************************************************** - * AUTHORS: Vijay Ganesh, David L. Dill - * - * BEGIN DATE: November, 2005 - * - * LICENSE: Please view LICENSE file in the home dir of this Program - ********************************************************************/ -// -*- c++ -*- - -#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(k1 == SYMBOL) - 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 - ) - || - k2 == SYMBOL - )) - 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) { - SimplifyMap.clear(); - SimplifyNegMap.clear(); - ASTNode out = SimplifyFormula(b,pushNeg); - SimplifyMap.clear(); - SimplifyNegMap.clear(); - 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))) { - SortByExprNum(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 - 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::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(); - SortByExprNum(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); - } - } - - 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) { - SimplifyMap.clear(); - SimplifyNegMap.clear(); - ASTNode out = SimplifyTerm(b); - SimplifyNegMap.clear(); - SimplifyMap.clear(); - 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; - } - - BVTypeCheck(inputterm); - ASTNode output; - 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: - case BVPLUS:{ - if(BVMULT == k && 2 != inputterm.Degree()) { - FatalError("SimplifyTerm: We assume that BVMULT is binary",inputterm); - } - - ASTVec c = FlattenOneLevel(inputterm).GetChildren(); - SortByExprNum(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 - SortByExprNum(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(); - SortByExprNum(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 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(); - SortByExprNum(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: - SortByExprNum(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 arr1 = SimplifyTerm(inputterm[0][1]); - ASTNode arr2 = SimplifyTerm(inputterm[0][2]); - - ASTNode index = SimplifyTerm(inputterm[1]); - - ASTNode read1 = CreateTerm(READ,inputValueWidth,arr1,index); - ASTNode read2 = CreateTerm(READ,inputValueWidth,arr2,index); - 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 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("SimplifyTerm: Control should never reach here:", inputterm, k); - return inputterm; - break; - } - - //memoize - UpdateSimplifyMap(inputterm,output,false); - //cerr << "SimplifyTerm: output" << output << endl; - return output; - } //end of SimplifyTerm() - - - //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) { - //Don't do the check in optimized mode - if(optimize) - return; - - if(NodeSize(a,true) < 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; - } - - 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(); - SortByExprNum(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(); - SortByExprNum(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(); - SortByExprNum(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(); - SortByExprNum(c); - if(SYMBOL != c[0].GetKind() || - VarSeenInTerm(c[0],SimplifyFormula_NoRemoveWrites(c[1],false))) { - return a; - } - bool updated = UpdateSubstitutionMap(c[0],c[1]); - 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(); - SortByExprNum(c); - FillUp_ArrReadIndex_Vec(c[0],c[1]); - - if(SYMBOL == c[0].GetKind() && - VarSeenInTerm(c[0],SimplifyTerm(c[1]))) { - return a; - } - - if(1 == TermOrder(c[0],c[1]) && - READ == c[0].GetKind() && - VarSeenInTerm(c[0][0],SimplifyTerm(c[1]))) { - return a; - } - bool updated = UpdateSubstitutionMap(c[0],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); - } - 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; - } -} //end of namespace |