/******************************************************************** * AUTHORS: Vijay Ganesh, David L. Dill * * BEGIN DATE: November, 2005 * 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 "stp/AST/AST.h" #include "stp/STPManager/STP.h" #include namespace stp { uint8_t ASTNode::getIteration() const { return _int_node_ptr->iteration; } void ASTNode::setIteration(uint8_t v) const { _int_node_ptr->iteration = v; } STPMgr* ASTNode::GetSTPMgr() const { return _int_node_ptr->nodeManager; } // Constructor; // // creates a new pointer, increments refcount of pointed-to object. ASTNode::ASTNode(ASTInternal* in) : _int_node_ptr(in) { if (in) { in->IncRef(); } } //#define ASTNODE_COUNT_OPS #ifdef ASTNODE_COUNT_OPS THREAD_LOCAL int ASTNode::copy = 0; THREAD_LOCAL int ASTNode::move = 0; THREAD_LOCAL int ASTNode::assign = 0; THREAD_LOCAL int ASTNode::destroy = 0; THREAD_LOCAL int ASTNode::assign_move = 0; #endif //Maintain _ref_count ASTNode::ASTNode(const ASTNode& n) : _int_node_ptr(n._int_node_ptr) { #ifdef ASTNODE_COUNT_OPS if (++copy % 1000000 == 0) std::cerr << "copy" << copy << std::endl; #endif if (n._int_node_ptr) { n._int_node_ptr->IncRef(); } } ASTNode::ASTNode(ASTNode&& other) noexcept : _int_node_ptr(other._int_node_ptr) { #ifdef ASTNODE_COUNT_OPS if (++move % 1000000 == 0) std::cerr << "move" << move << std::endl; #endif other._int_node_ptr = 0; } ASTNode& ASTNode::operator=(ASTNode&& n) { #ifdef ASTNODE_COUNT_OPS if (++assign_move % 1000000 == 0) std::cerr << "assign_move" << assign_move << std::endl; #endif if (_int_node_ptr) _int_node_ptr->DecRef(); _int_node_ptr = n._int_node_ptr; n._int_node_ptr = 0; return *this; } // ASTNode accessor function. Kind ASTNode::GetKind() const { // cout << "GetKind: " << _int_node_ptr; return _int_node_ptr->GetKind(); } // Declared here because of same ordering problem as GetKind. const ASTVec& ASTNode::GetChildren() const { return _int_node_ptr->GetChildren(); } // Access node number unsigned ASTNode::GetNodeNum() const { return _int_node_ptr->GetNodeNum(); } unsigned int ASTNode::GetIndexWidth() const { return _int_node_ptr->getIndexWidth(); } void ASTNode::SetIndexWidth(unsigned int _iw) const { _int_node_ptr->setIndexWidth(_iw); } unsigned int ASTNode::GetValueWidth() const { return _int_node_ptr->getValueWidth(); } void ASTNode::SetValueWidth(unsigned int vw) const { _int_node_ptr->setValueWidth(vw); } // return the type of the ASTNode: // // 0 iff BOOLEAN; 1 iff BITVECTOR; 2 iff ARRAY; 3 iff UNKNOWN; types ASTNode::GetType() const { if ((GetIndexWidth() == 0) && (GetValueWidth() == 0)) return BOOLEAN_TYPE; if ((GetIndexWidth() == 0) && (GetValueWidth() > 0)) return BITVECTOR_TYPE; if ((GetIndexWidth() > 0) && (GetValueWidth() > 0)) return ARRAY_TYPE; return UNKNOWN_TYPE; } ASTNode& ASTNode::operator=(const ASTNode& n) { #ifdef ASTNODE_COUNT_OPS if (++assign % 1000000 == 0) std::cerr << "assign" << assign << std::endl; #endif 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; } ASTNode::~ASTNode() { #ifdef ASTNODE_COUNT_OPS if (destroy++ % 1000000 == 0) std::cerr << "destroy" << destroy << std::endl; #endif if (_int_node_ptr) { _int_node_ptr->DecRef(); } } // Print the node void ASTNode::nodeprint(ostream& os, bool c_friendly) const { _int_node_ptr->nodeprint(os, c_friendly); } // 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(); } // Get the value of bvconst from a bvconst. It's an error if kind // != BVCONST Treat the result as const (the compiler can't enforce // it). CBV ASTNode::GetBVConst() const { if (GetKind() != BVCONST) FatalError("GetBVConst: non bitvector-constant: ", *this); return ((ASTBVConst*)_int_node_ptr)->GetBVConst(); } unsigned int ASTNode::GetUnsignedConst() const { const ASTNode& n = *this; assert(BVCONST == n.GetKind()); if (sizeof(unsigned int) * 8 < n.GetValueWidth()) { // It may only contain a small value in a bit type, // which fits nicely into an unsigned int. This is // common for functions like: bvshl(bv1[128], // bv1[128]) where both operands have the same type. signed long maxBit = CONSTANTBV::Set_Max(n.GetBVConst()); if (maxBit >= ((signed long)sizeof(unsigned int)) * 8) { n.LispPrint(std::cerr); // print the node so they can find it. FatalError("GetUnsignedConst: cannot convert bvconst " "of length greater than 32 to unsigned int"); } } return (unsigned int)*((unsigned int*)n.GetBVConst()); } size_t ASTNode::Hash() const { return (_int_node_ptr ? _int_node_ptr->node_uid : 0); } void ASTNode::NFASTPrint(int l, int max, int prefix) const { //**************************************** // stop //**************************************** if (l > max) { return; } //**************************************** // print //**************************************** printf("[%10d]", 0); for (int i = 0; i < prefix; i++) { printf(" "); } std::cout << GetKind(); printf("\n"); //**************************************** // recurse //**************************************** const ASTVec& children = GetChildren(); ASTVec::const_iterator it = children.begin(); for (; it != children.end(); it++) { it->NFASTPrint(l + 1, max, prefix + 1); } } bool ASTNode::isSimplfied() const { return _int_node_ptr->isSimplified(); } void ASTNode::hasBeenSimplfied() const { _int_node_ptr->hasBeenSimplified(); } // traverse "*this", and construct "let variables" for terms that // occur more than once in "*this". void ASTNode::LetizeNode(STPMgr* bm) const { if (isAtom()) return; 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 bm->PLPrintNodeSet.insert(ccc); // debugging // cerr << ccc; ccc.LetizeNode(bm); } else { if (ccc.isAtom()) 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(); std::ostringstream oss; oss << "let_k_" << sz; ASTNode CurrentSymbol = bm->CreateSymbol( oss.str().c_str(), this->GetIndexWidth(), this->GetValueWidth()); /* If for some reason the variable being created here is * already declared by the user then the printed output will * not be a legal input to the system. too bad. I refuse to * check for this. */ bm->NodeLetVarMap[ccc] = CurrentSymbol; std::pair node_letvar_pair(CurrentSymbol, ccc); bm->NodeLetVarVec.push_back(node_letvar_pair); } } } } } //end of namespace