/* FUNCTION: Typechecker for terms and formulas * * TypeChecker: Assumes that the immediate Children of the input * ASTNode have been typechecked. This function is suitable in * scenarios like where you are building the ASTNode Tree, and you * typecheck as you go along. It is not suitable as a general * typechecker. * * If this returns, this ALWAYS returns true. If there is an error it * will call FatalError() and abort. */ bool BVTypeCheck(const ASTNode& n) { Kind k = n.GetKind(); //The children of bitvector terms are in turn bitvectors. const ASTVec& v = n.GetChildren(); if (is_Term_kind(k)) { switch (k) { case BVCONST: if (BITVECTOR_TYPE != n.GetType()) FatalError("BVTypeCheck: The term t does not typecheck, where t = \n", n); break; case SYMBOL: return true; case ITE: if (n.Degree() != 3) FatalError("BVTypeCheck: should have exactly 3 args\n", n); if (BOOLEAN_TYPE != n[0].GetType() || (n[1].GetType() != n[2].GetType())) FatalError("BVTypeCheck: The term t does not typecheck, where t = \n", n); if (n[1].GetValueWidth() != n[2].GetValueWidth()) FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n", n); if (n[1].GetIndexWidth() != n[2].GetIndexWidth()) FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n", n); break; case READ: if (n.GetChildren().size() !=2) FatalError("2 params to read."); if (n[0].GetIndexWidth() != n[1].GetValueWidth()) { cerr << "Length of indexwidth of array: " << n[0] << " is : " << n[0].GetIndexWidth() << endl; cerr << "Length of the actual index is: " << n[1] << " is : " << n[1].GetValueWidth() << endl; FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n", n); } if (ARRAY_TYPE != n[0].GetType()) FatalError("First parameter to read should be an array", n[0]); if (BITVECTOR_TYPE != n[1].GetType()) FatalError("Second parameter to read should be a bitvector", n[1]); break; case WRITE: if (n.GetChildren().size() !=3) FatalError("3 params to write."); if (n[0].GetIndexWidth() != n[1].GetValueWidth()) FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n", n); if (n[0].GetValueWidth() != n[2].GetValueWidth()) FatalError("BVTypeCheck: valuewidth of array != length of actual value in the term t = \n", n); if (ARRAY_TYPE != n[0].GetType()) FatalError("First parameter to read should be an array", n[0]); if (BITVECTOR_TYPE != n[1].GetType()) FatalError("Second parameter to read should be a bitvector", n[1]); if (BITVECTOR_TYPE != n[2].GetType()) FatalError("Third parameter to read should be a bitvector", n[2]); break; case BVDIV: case BVMOD: case BVSUB: case SBVDIV: case SBVREM: case SBVMOD: case BVLEFTSHIFT: case BVRIGHTSHIFT: case BVSRSHIFT: case BVVARSHIFT: if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); // run on. case BVOR: case BVAND: case BVXOR: case BVNOR: case BVNAND: case BVXNOR: case BVPLUS: case BVMULT: { if (!(v.size() >= 2)) FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must have at least two arguments\n", n); unsigned int width = n.GetValueWidth(); for (ASTVec::const_iterator it = v.begin(), itend = v.end(); it != itend; it++) { if (width != it->GetValueWidth()) { cerr << "BVTypeCheck:Operands of bitwise-Booleans and BV arith operators must be of equal length\n"; cerr << n << endl; cerr << "width of term:" << width << endl; cerr << "width of offending operand:" << it->GetValueWidth() << endl; FatalError("BVTypeCheck:Offending operand:\n", *it); } if (BITVECTOR_TYPE != it->GetType()) FatalError("BVTypeCheck: ChildNodes of bitvector-terms must be bitvectors\n", n); } break; } case BVSX: case BVZX: //in BVSX(n[0],len), the length of the BVSX term must be //greater than the length of n[0] if (n[0].GetValueWidth() > n.GetValueWidth()) { FatalError( "BVTypeCheck: BV[SZ]X(t,bv[sz]x_len) : length of 't' must be <= bv[sz]x_len\n", n); } if ((v.size() != 2)) FatalError( "BVTypeCheck:BV[SZ]X must have two arguments. The second is the new width\n", n); break; case BVCONCAT: checkChildrenAreBV(v, n); if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); if (n.GetValueWidth() != n[0].GetValueWidth() + n[1].GetValueWidth()) FatalError("BVTypeCheck:BVCONCAT: lengths do not add up\n", n); break; case BVUMINUS: case BVNEG: checkChildrenAreBV(v, n); if (n.Degree() != 1) FatalError("BVTypeCheck: should have exactly 1 args\n", n); break; case BVEXTRACT: checkChildrenAreBV(v, n); if (n.Degree() != 3) FatalError("BVTypeCheck: should have exactly 3 args\n", n); if (!(BVCONST == n[1].GetKind() && BVCONST == n[2].GetKind())) FatalError("BVTypeCheck: indices should be BVCONST\n", n); if (n.GetValueWidth() != n[1].GetUnsignedConst() - n[2].GetUnsignedConst() + 1) FatalError("BVTypeCheck: length mismatch\n", n); if (n[1].GetUnsignedConst() >= n[0].GetValueWidth()) FatalError( "BVTypeCheck: Top index of select is greater or equal to the bitwidth.\n", n); break; default: cerr << _kind_names[k]; FatalError("No type checking for type"); break; } } else { if (!(is_Form_kind(k) && BOOLEAN_TYPE == n.GetType())) FatalError("BVTypeCheck: not a formula:", n); switch (k) { case TRUE: case FALSE: case SYMBOL: return true; case BOOLEXTRACT: checkChildrenAreBV(v, n); if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); if (!(BVCONST == n[1].GetKind())) FatalError("BVTypeCheck: index should be BVCONST\n", n); if (n[1].GetUnsignedConst() >= n[0].GetValueWidth()) FatalError("BVTypeCheck: index is greater or equal to the bitwidth.\n", n); break; case PARAMBOOL: if(2 != n.Degree()) FatalError("BVTypeCheck: PARAMBOOL formula can have exactly two childNodes", n); break; case EQ: if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); if (!(n[0].GetValueWidth() == n[1].GetValueWidth() && n[0].GetIndexWidth() == n[1].GetIndexWidth())) { cerr << "valuewidth of lhs of EQ: " << n[0].GetValueWidth() << endl; cerr << "valuewidth of rhs of EQ: " << n[1].GetValueWidth() << endl; cerr << "indexwidth of lhs of EQ: " << n[0].GetIndexWidth() << endl; cerr << "indexwidth of rhs of EQ: " << n[1].GetIndexWidth() << endl; FatalError("BVTypeCheck: terms in atomic formulas must be of equal length", n); } break; case BVLT: case BVLE: case BVGT: case BVGE: case BVSLT: case BVSLE: case BVSGT: case BVSGE: if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); if (BITVECTOR_TYPE != n[0].GetType() && BITVECTOR_TYPE != n[1].GetType()) FatalError("BVTypeCheck: terms in atomic formulas must be bitvectors", n); if (n[0].GetValueWidth() != n[1].GetValueWidth()) FatalError("BVTypeCheck: terms in atomic formulas must be of equal length", n); if (n[0].GetIndexWidth() != n[1].GetIndexWidth()) FatalError("BVTypeCheck: terms in atomic formulas must be of equal length", n); break; case NOT: if (1 != n.Degree()) FatalError("BVTypeCheck: NOT formula can have exactly one childNode", n); break; case AND: case OR: case XOR: case NAND: case NOR: if (2 > n.Degree()) FatalError("BVTypeCheck: AND/OR/XOR/NAND/NOR: must have atleast 2 ChildNodes", n); break; case IFF: case IMPLIES: if (2 != n.Degree()) FatalError("BVTypeCheck:IFF/IMPLIES must have exactly 2 ChildNodes", n); break; case ITE: if (3 != n.Degree()) FatalError("BVTypeCheck:ITE must have exactly 3 ChildNodes", n); break; default: FatalError("BVTypeCheck: Unrecognized kind: "); break; } } return true; } //End of TypeCheck function
bool BVTypeCheck_term_kind(const ASTNode& n, const Kind& k) { // The children of bitvector terms are in turn bitvectors. const ASTVec& v = n.GetChildren(); switch (k) { case BVCONST: if (BITVECTOR_TYPE != n.GetType()) FatalError("BVTypeCheck: The term t does not typecheck, where t = \n", n); break; case SYMBOL: return true; case ITE: if (n.Degree() != 3) FatalError("BVTypeCheck: should have exactly 3 args\n", n); if (BOOLEAN_TYPE != n[0].GetType() || (n[1].GetType() != n[2].GetType())) FatalError("BVTypeCheck: The term t does not typecheck, where t = \n", n); if (n[1].GetValueWidth() != n[2].GetValueWidth()) FatalError("BVTypeCheck: length of THENbranch != length of " "ELSEbranch in the term t = \n", n); if (n[1].GetIndexWidth() != n[2].GetIndexWidth()) FatalError("BVTypeCheck: length of THENbranch != length of " "ELSEbranch in the term t = \n", n); break; case READ: if (n.GetChildren().size() != 2) FatalError("2 params to read."); if (n[0].GetIndexWidth() != n[1].GetValueWidth()) { cerr << "Length of indexwidth of array: " << n[0] << " is : " << n[0].GetIndexWidth() << endl; cerr << "Length of the actual index is: " << n[1] << " is : " << n[1].GetValueWidth() << endl; FatalError("BVTypeCheck: length of indexwidth of array != length of " "actual index in the term t = \n", n); } if (ARRAY_TYPE != n[0].GetType()) FatalError("First parameter to read should be an array", n[0]); if (BITVECTOR_TYPE != n[1].GetType()) FatalError("Second parameter to read should be a bitvector", n[1]); break; case WRITE: if (n.GetChildren().size() != 3) FatalError("3 params to write."); if (n[0].GetIndexWidth() != n[1].GetValueWidth()) FatalError("BVTypeCheck: length of indexwidth of array != length of " "actual index in the term t = \n", n); if (n[0].GetValueWidth() != n[2].GetValueWidth()) FatalError("BVTypeCheck: valuewidth of array != length of actual " "value in the term t = \n", n); if (ARRAY_TYPE != n[0].GetType()) FatalError("First parameter to read should be an array", n[0]); if (BITVECTOR_TYPE != n[1].GetType()) FatalError("Second parameter to read should be a bitvector", n[1]); if (BITVECTOR_TYPE != n[2].GetType()) FatalError("Third parameter to read should be a bitvector", n[2]); break; case BVDIV: case BVMOD: case BVSUB: case SBVDIV: case SBVREM: case SBVMOD: case BVLEFTSHIFT: case BVRIGHTSHIFT: case BVSRSHIFT: case BVVARSHIFT: if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); // run on. case BVOR: case BVAND: case BVXOR: case BVNOR: case BVNAND: case BVXNOR: case BVPLUS: case BVMULT: { if (!(v.size() >= 2)) FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must " "have at least two arguments\n",n); unsigned int width = n.GetValueWidth(); for (ASTVec::const_iterator it = v.begin(), itend = v.end(); it != itend; it++) { if (width != it->GetValueWidth()) { cerr << "BVTypeCheck:Operands of bitwise-Booleans and BV arith " "operators must be of equal length\n"; cerr << n << endl; cerr << "width of term:" << width << endl; cerr << "width of offending operand:" << it->GetValueWidth() << endl; FatalError("BVTypeCheck:Offending operand:\n", *it); } if (BITVECTOR_TYPE != it->GetType()) FatalError("BVTypeCheck: ChildNodes of bitvector-terms must be " "bitvectors\n", n); } break; } case BVSX: case BVZX: // in BVSX(n[0],len), the length of the BVSX term must be // greater than the length of n[0] if (n[0].GetValueWidth() > n.GetValueWidth()) { FatalError("BVTypeCheck: BV[SZ]X(t,bv[sz]x_len) : length of 't' must " "be <= bv[sz]x_len\n", n); } if ((v.size() != 2)) FatalError("BVTypeCheck:BV[SZ]X must have two arguments. The second " "is the new width\n", n); break; case BVCONCAT: checkChildrenAreBV(v, n); if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); if (n.GetValueWidth() != n[0].GetValueWidth() + n[1].GetValueWidth()) FatalError("BVTypeCheck:BVCONCAT: lengths do not add up\n", n); break; case BVUMINUS: case BVNEG: checkChildrenAreBV(v, n); if (n.Degree() != 1) FatalError("BVTypeCheck: should have exactly 1 args\n", n); if (n.GetValueWidth() != n[0].GetValueWidth()) FatalError("BVTypeCheck: should have same value width\n", n); break; case BVEXTRACT: checkChildrenAreBV(v, n); if (n.Degree() != 3) FatalError("BVTypeCheck: should have exactly 3 args\n", n); if (!(BVCONST == n[1].GetKind() && BVCONST == n[2].GetKind())) FatalError("BVTypeCheck: indices should be BVCONST\n", n); if (n.GetValueWidth() != n[1].GetUnsignedConst() - n[2].GetUnsignedConst() + 1) FatalError("BVTypeCheck: length mismatch\n", n); if (n[1].GetUnsignedConst() >= n[0].GetValueWidth()) FatalError("BVTypeCheck: Top index of select is greater or equal to " "the bitwidth.\n", n); break; default: cerr << _kind_names[k]; FatalError("No type checking for type"); break; } return true; }
bool BVTypeCheck_nonterm_kind(const ASTNode& n, const Kind& k) { // The children of bitvector terms are in turn bitvectors. const ASTVec& v = n.GetChildren(); if (!(is_Form_kind(k) && BOOLEAN_TYPE == n.GetType())) FatalError("BVTypeCheck: not a formula:", n); switch (k) { case TRUE: case FALSE: case SYMBOL: return true; case BOOLEXTRACT: checkChildrenAreBV(v, n); if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); if (!(BVCONST == n[1].GetKind())) FatalError("BVTypeCheck: index should be BVCONST\n", n); if (n[1].GetUnsignedConst() >= n[0].GetValueWidth()) { FatalError( "BVTypeCheck: index is greater or equal to the bitwidth.\n", n); } break; case PARAMBOOL: if (2 != n.Degree()) { FatalError( "BVTypeCheck: PARAMBOOL formula can have exactly two childNodes", n); } break; case EQ: if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); if (!(n[0].GetValueWidth() == n[1].GetValueWidth() && n[0].GetIndexWidth() == n[1].GetIndexWidth())) { cerr << "valuewidth of lhs of EQ: " << n[0].GetValueWidth() << endl; cerr << "valuewidth of rhs of EQ: " << n[1].GetValueWidth() << endl; cerr << "indexwidth of lhs of EQ: " << n[0].GetIndexWidth() << endl; cerr << "indexwidth of rhs of EQ: " << n[1].GetIndexWidth() << endl; FatalError( "BVTypeCheck: terms in atomic formulas must be of equal length", n); } break; case BVLT: case BVLE: case BVGT: case BVGE: case BVSLT: case BVSLE: case BVSGT: case BVSGE: if (n.Degree() != 2) FatalError("BVTypeCheck: should have exactly 2 args\n", n); if (BITVECTOR_TYPE != n[0].GetType() && BITVECTOR_TYPE != n[1].GetType()) { FatalError("BVTypeCheck: terms in atomic formulas must be bitvectors" ,n); } if (n[0].GetValueWidth() != n[1].GetValueWidth()) FatalError( "BVTypeCheck: terms in atomic formulas must be of equal length", n); if (n[0].GetIndexWidth() != n[1].GetIndexWidth()) { FatalError( "BVTypeCheck: terms in atomic formulas must be of equal length", n); } break; case NOT: if (1 != n.Degree()) { FatalError("BVTypeCheck: NOT formula can have exactly one childNode", n); } break; case AND: case OR: case XOR: case NAND: case NOR: if (2 > n.Degree()) { FatalError("BVTypeCheck: AND/OR/XOR/NAND/NOR: must have atleast 2 " "ChildNodes", n); } break; case IFF: case IMPLIES: if (2 != n.Degree()) { FatalError("BVTypeCheck:IFF/IMPLIES must have exactly 2 ChildNodes", n); } break; case ITE: if (3 != n.Degree()) FatalError("BVTypeCheck:ITE must have exactly 3 ChildNodes", n); break; default: FatalError("BVTypeCheck: Unrecognized kind: "); break; } return true; }
void SMTLIB2_Print1(ostream& os, const ASTNode n, int indentation, bool letize) { //os << spaces(indentation); //os << endl << spaces(indentation); if (!n.IsDefined()) { FatalError("<undefined>"); return; } //if this node is present in the letvar Map, then print the letvar //this is to print letvars for shared subterms inside the printing //of "(LET v0 = term1, v1=term1@term2,... if ((NodeLetVarMap1.find(n) != NodeLetVarMap1.end()) && !letize) { SMTLIB2_Print1(os, (NodeLetVarMap1[n]), indentation, letize); return; } //this is to print letvars for shared subterms inside the actual //term to be printed if ((NodeLetVarMap.find(n) != NodeLetVarMap.end()) && letize) { SMTLIB2_Print1(os, (NodeLetVarMap[n]), indentation, letize); return; } //otherwise print it normally const Kind kind = n.GetKind(); const ASTVec &c = n.GetChildren(); switch (kind) { case BITVECTOR: case BVCONST: outputBitVecSMTLIB2(n, os); break; case SYMBOL: os << "|"; n.nodeprint(os); os << "|"; break; case FALSE: os << "false"; break; case NAND: // No NAND, NOR in smtlib format. case NOR: assert(c.size() ==2); os << "(" << "not "; if (NAND == kind ) os << "(" << "and "; else os << "(" << "or "; SMTLIB2_Print1(os, c[0], 0, letize); os << " " ; SMTLIB2_Print1(os, c[1], 0, letize); os << "))"; break; case TRUE: os << "true"; break; case BVSX: case BVZX: { unsigned int amount = c[1].GetUnsignedConst(); if (BVZX == kind) os << "((_ zero_extend "; else os << "((_ sign_extend "; os << (amount - c[0].GetValueWidth()) << ") "; SMTLIB2_Print1(os, c[0], indentation, letize); os << ")"; } break; case BVEXTRACT: { unsigned int upper = c[1].GetUnsignedConst(); unsigned int lower = c[2].GetUnsignedConst(); assert(upper >= lower); os << "((_ extract " << upper << " " << lower << ") "; SMTLIB2_Print1(os, c[0], indentation, letize); os << ")"; } break; default: { if ((kind == AND || kind == OR|| kind == XOR) && n.Degree() == 1) { FatalError("Wrong number of arguments to operation (must be >1).", n); } // SMT-LIB only allows these functions to have two parameters. if ((kind == AND || kind == OR|| kind == XOR || BVPLUS == kind || kind == BVOR || kind == BVAND) && n.Degree() > 2) { string close = ""; for (long int i =0; i < (long int)c.size()-1; i++) { os << "(" << functionToSMTLIBName(kind,false); os << " "; SMTLIB2_Print1(os, c[i], 0, letize); os << " "; close += ")"; } SMTLIB2_Print1(os, c[c.size()-1], 0, letize); os << close; } else { os << "(" << functionToSMTLIBName(kind,false); ASTVec::const_iterator iend = c.end(); for (ASTVec::const_iterator i = c.begin(); i != iend; i++) { os << " "; SMTLIB2_Print1(os, *i, 0, letize); } os << ")"; } } } }
string Bench_Print1(ostream &os, const ASTNode& n, map<ASTNode, string> *alreadyOutput) { assert(((n.GetKind() == SYMBOL) || (n.GetKind() == BVCONST) || n.GetValueWidth() <= 1)); assert(!n.IsNull()); map<ASTNode, string>::iterator it; if ((it = alreadyOutput->find(n)) != alreadyOutput->end()) return it->second; if (n.GetKind() == BVCONST) { (*alreadyOutput)[n] = bvconstToString(n); return (*alreadyOutput)[n]; } if (n.GetKind() == SYMBOL) { (*alreadyOutput)[n] = symbolToString(n); return (*alreadyOutput)[n]; } if (n.GetKind() == TRUE) { return "vdd"; } if (n.GetKind() == FALSE) { return "gnd"; } if (n.GetKind() == BVGETBIT) { assert(n[1].GetKind() == BVCONST); std::stringstream nn; nn << Bench_Print1(os, n[0], alreadyOutput) << "_" << Bench_Print1(os, n[1], alreadyOutput); (*alreadyOutput)[n] = nn.str(); return (*alreadyOutput)[n]; } std::stringstream nodeNameSS; nodeNameSS << "n" << n.GetNodeNum(); string thisNode = nodeNameSS.str(); (*alreadyOutput)[n] = thisNode; assert(n.Degree() > 0); std::stringstream output; // The bench format doesn't accept propositional ITEs. if (n.GetKind() == ITE) { assert(n.Degree() == 3); string p = Bench_Print1(os, n[0], alreadyOutput); string p1 = Bench_Print1(os, n[1], alreadyOutput); string p2 = Bench_Print1(os, n[2], alreadyOutput); os << thisNode << "_1 = AND(" << p << "," << p1 << ")" << endl; os << thisNode << "_2" << " = NOT(" << p << ")," << endl; os << thisNode << "_3" << " = AND(" << thisNode << "_2" << "," << p2 << ")" << endl; os << thisNode << "=" << "OR(," << thisNode << "_1" << "," << thisNode << "_3)" << endl; } else { if (n.Degree() > 2) { assert(n.GetKind() == AND || n.GetKind() == XOR || n.GetKind() == OR); // must be associative. std::deque<string> names; for (unsigned i = 0; i < n.Degree(); i++) names.push_back(Bench_Print1(os, n[i], alreadyOutput)); int id = 0; while (names.size() > 2) { string a = names.front(); names.pop_front(); string b = names.front(); names.pop_front(); std::stringstream thisName; thisName << thisNode << "___" << id++; output << thisName.str() << "=" << name(n.GetKind()) << "(" << a << "," << b << ")" << endl; names.push_back(thisName.str()); } assert(names.size() == 2); // last two now. string a = names.front(); names.pop_front(); string b = names.front(); names.pop_front(); output << thisNode << "=" << name(n.GetKind()) << "(" << a << "," << b << ")" << endl; os << output.str(); } else { output << thisNode << "=" << name(n.GetKind()) << "("; for (unsigned i = 0; i < n.Degree(); i++) { if (i >= 1) output << " , "; output << Bench_Print1(os, n[i], alreadyOutput); } os << output.str() << ")" << endl; } } return thisNode; }
ASTNode ArrayTransformer::TransformTerm(const ASTNode& term) { assert(TransformMap != NULL); const Kind k = term.GetKind(); if (!is_Term_kind(k)) FatalError("TransformTerm: Illegal kind: You have input a nonterm:", term, k); ASTNodeMap::const_iterator iter; if ((iter = TransformMap->find(term)) != TransformMap->end()) return iter->second; ASTNode result; switch (k) { case SYMBOL: case BVCONST: { result = term; break; } case WRITE: FatalError("TransformTerm: this kind is not supported", term); break; case READ: result = TransformArrayRead(term); break; case ITE: { ASTNode cond = term[0]; ASTNode thn = term[1]; ASTNode els = term[2]; cond = TransformFormula(cond); if (ASTTrue == cond) result = TransformTerm(thn); else if (ASTFalse == cond) result = TransformTerm(els); else { thn = TransformTerm(thn); els = TransformTerm(els); if (bm->UserFlags.optimize_flag) result = simp->CreateSimplifiedTermITE(cond, thn, els); else result = nf->CreateTerm(ITE, thn.GetValueWidth(), cond, thn, els); } assert(result.GetIndexWidth() == term.GetIndexWidth()); break; } default: { const ASTVec& c = term.GetChildren(); ASTVec::const_iterator it = c.begin(); ASTVec::const_iterator itend = c.end(); const unsigned width = term.GetValueWidth(); const unsigned indexwidth = term.GetIndexWidth(); ASTVec o; o.reserve(c.size()); for (; it != itend; it++) { o.push_back(TransformTerm(*it)); } if (c != o) { result = nf->CreateArrayTerm(k, indexwidth, width, o); } else result = term; } break; } if (term.Degree() > 0) (*TransformMap)[term] = result; if (term.GetValueWidth() != result.GetValueWidth()) FatalError("TransformTerm: " "result and input terms are of different length", result); if (term.GetIndexWidth() != result.GetIndexWidth()) { std::cerr << "TransformTerm: input term is : " << term << std::endl; FatalError("TransformTerm: " "result & input terms have different index length", result); } return result; }
// This doesn't rewrite changes through properly so needs to have a substitution // applied to its output. ASTNode PropagateEqualities::propagate(const ASTNode& a, ArrayTransformer* at) { ASTNode output; // if the variable has been solved for, then simply return it if (simp->InsideSubstitutionMap(a, output)) return output; if (!alreadyVisited.insert(a.GetNodeNum()).second) { return a; } output = a; // traverse a and populate the SubstitutionMap const Kind k = a.GetKind(); if (SYMBOL == k && BOOLEAN_TYPE == a.GetType()) { bool updated = simp->UpdateSubstitutionMap(a, ASTTrue); output = updated ? ASTTrue : a; } else if (NOT == k) { bool updated = searchXOR(a[0], ASTFalse); output = updated ? ASTTrue : a; } else if (IFF == k || EQ == k) { const ASTVec& c = a.GetChildren(); if (c[0] == c[1]) return ASTTrue; bool updated = simp->UpdateSubstitutionMap(c[0], c[1]); if (updated) { // fill the arrayname readindices vector if e0 is a // READ(Arr,index) and index is a BVCONST int to; if ((to = TermOrder(c[0], c[1])) == 1 && c[0].GetKind() == READ) at->FillUp_ArrReadIndex_Vec(c[0], c[1]); else if (to == -1 && c[1].GetKind() == READ) at->FillUp_ArrReadIndex_Vec(c[1], c[0]); } if (!updated) updated = searchTerm(c[0], c[1]); if (!updated) updated = searchTerm(c[1], c[0]); output = updated ? ASTTrue : a; } else if (XOR == k) { bool updated = searchXOR(a, ASTTrue); output = updated ? ASTTrue : a; if (updated) return output; // The below block should be subsumed by the searchXOR function which // generalises it. // So the below block should never do anything.. #ifndef NDEBUG if (a.Degree() != 2) return output; int to = TermOrder(a[0], a[1]); if (0 == to) { if (a[0].GetKind() == NOT && a[0][0].GetKind() == EQ && a[0][0][0].GetValueWidth() == 1 && a[0][0][1].GetKind() == SYMBOL) { // (XOR (NOT(= (1 v))) ... ) const ASTNode& symbol = a[0][0][1]; const ASTNode newN = nf->CreateTerm( ITE, 1, a[1], a[0][0][0], nf->CreateTerm(BVNEG, 1, a[0][0][0])); if (simp->UpdateSolverMap(symbol, newN)) { assert(false); output = ASTTrue; } } else if (a[1].GetKind() == NOT && a[1][0].GetKind() == EQ && a[1][0][0].GetValueWidth() == 1 && a[1][0][1].GetKind() == SYMBOL) { const ASTNode& symbol = a[1][0][1]; const ASTNode newN = nf->CreateTerm( ITE, 1, a[0], a[1][0][0], nf->CreateTerm(BVNEG, 1, a[1][0][0])); if (simp->UpdateSolverMap(symbol, newN)) { assert(false); output = ASTTrue; } } else if (a[0].GetKind() == EQ && a[0][0].GetValueWidth() == 1 && a[0][1].GetKind() == SYMBOL) { // XOR ((= 1 v) ... ) const ASTNode& symbol = a[0][1]; const ASTNode newN = nf->CreateTerm( ITE, 1, a[1], nf->CreateTerm(BVNEG, 1, a[0][0]), a[0][0]); if (simp->UpdateSolverMap(symbol, newN)) { assert(false); output = ASTTrue; } } else if (a[1].GetKind() == EQ && a[1][0].GetValueWidth() == 1 && a[1][1].GetKind() == SYMBOL) { const ASTNode& symbol = a[1][1]; const ASTNode newN = nf->CreateTerm( ITE, 1, a[0], nf->CreateTerm(BVNEG, 1, a[1][0]), a[1][0]); if (simp->UpdateSolverMap(symbol, newN)) { assert(false); output = ASTTrue; } } else return output; } else { ASTNode symbol, rhs; if (to == 1) { symbol = a[0]; rhs = a[1]; } else { symbol = a[1]; rhs = a[0]; } assert(symbol.GetKind() == SYMBOL); if (simp->UpdateSolverMap(symbol, nf->CreateNode(NOT, rhs))) { assert(false); output = ASTTrue; } } #endif } else if (AND == k) { const ASTVec& c = a.GetChildren(); ASTVec o; o.reserve(c.size()); for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++) { if (always_true) simp->UpdateAlwaysTrueFormSet(*it); ASTNode aaa = propagate(*it, at); if (ASTTrue != aaa) { if (ASTFalse == aaa) return ASTFalse; else o.push_back(aaa); } } if (o.size() == 0) output = ASTTrue; else if (o.size() == 1) output = o[0]; else if (o != c) output = nf->CreateNode(AND, o); else output = a; } return output; }
/******************************************************** * TransformFormula() * * Get rid of DIV/MODs, ARRAY read/writes, FOR constructs ********************************************************/ ASTNode ArrayTransformer::TransformFormula(const ASTNode& simpleForm) { assert(TransformMap != NULL); const 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::const_iterator iter; if ((iter = TransformMap->find(simpleForm)) != TransformMap->end()) return iter->second; ASTNode result; switch (k) { case TRUE: case FALSE: { result = simpleForm; break; } case NOT: { ASTVec c; c.push_back(TransformFormula(simpleForm[0])); result = nf->CreateNode(NOT, c); break; } case BOOLEXTRACT: { ASTVec c; c.push_back(TransformTerm(simpleForm[0])); c.push_back(simpleForm[1]); result = nf->CreateNode(BOOLEXTRACT, c); break; } case BVLT: case BVLE: case BVGT: case BVGE: case BVSLT: case BVSLE: case BVSGT: case BVSGE: { ASTVec c; c.push_back(TransformTerm(simpleForm[0])); c.push_back(TransformTerm(simpleForm[1])); result = nf->CreateNode(k, c); break; } case EQ: { ASTNode term1 = TransformTerm(simpleForm[0]); ASTNode term2 = TransformTerm(simpleForm[1]); if (bm->UserFlags.optimize_flag) result = simp->CreateSimplifiedEQ(term1, term2); else result = nf->CreateNode(EQ, term1, term2); break; } case AND: // These could shortcut. Not sure if the extra effort is // justified. case OR: case NAND: case NOR: case IFF: case XOR: case ITE: case IMPLIES: { ASTVec vec; vec.reserve(simpleForm.Degree()); for (ASTVec::const_iterator it = simpleForm.begin(), itend = simpleForm.end(); it != itend; it++) { vec.push_back(TransformFormula(*it)); } result = nf->CreateNode(k, vec); break; } case PARAMBOOL: { // If the parameteric boolean variable is of the form // VAR(const), then convert it into a Boolean variable of the // form "VAR(const)". // // Else if the paramteric boolean variable is of the form // VAR(expression), then simply return it if (BVCONST == simpleForm[1].GetKind()) { result = bm->NewParameterized_BooleanVar(simpleForm[0], simpleForm[1]); } else { result = simpleForm; } break; } default: { if (k == SYMBOL && BOOLEAN_TYPE == simpleForm.GetType()) result = simpleForm; else { FatalError("TransformFormula: Illegal kind: ", ASTUndefined, k); std::cerr << "The input is: " << simpleForm << std::endl; std::cerr << "The valuewidth of input is : " << simpleForm.GetValueWidth() << std::endl; } break; } } assert(!result.IsNull()); if (simpleForm.Degree() > 0) (*TransformMap)[simpleForm] = result; return result; }
ASTNode ArrayTransformer::TransformTerm(const ASTNode& term) { assert(TransformMap != NULL); const Kind k = term.GetKind(); if (!is_Term_kind(k)) FatalError("TransformTerm: Illegal kind: You have input a nonterm:", term, k); ASTNodeMap::const_iterator iter; if ((iter = TransformMap->find(term)) != TransformMap->end()) return iter->second; ASTNode result; switch (k) { case SYMBOL: case BVCONST: { result = term; break; } case WRITE: FatalError("TransformTerm: this kind is not supported", term); break; case READ: result = TransformArrayRead(term); break; case ITE: { ASTNode cond = term[0]; ASTNode thn = term[1]; ASTNode els = term[2]; cond = TransformFormula(cond); if (ASTTrue == cond) result = TransformTerm(thn); else if (ASTFalse == cond) result = TransformTerm(els); else { thn = TransformTerm(thn); els = TransformTerm(els); result = simp->CreateSimplifiedTermITE(cond, thn, els); } assert(result.GetIndexWidth() ==term.GetIndexWidth()); break; } default: { const ASTVec& c = term.GetChildren(); ASTVec::const_iterator it = c.begin(); ASTVec::const_iterator itend = c.end(); const unsigned width = term.GetValueWidth(); const unsigned indexwidth = term.GetIndexWidth(); ASTVec o; o.reserve(c.size()); for (; it != itend; it++) { o.push_back(TransformTerm(*it)); } if (c!=o) { result = nf->CreateArrayTerm(k,indexwidth, width, o); } else result = term; const Kind k = result.GetKind(); if (BVDIV == k || BVMOD == k || SBVDIV == k || SBVREM == k || SBVMOD == k) { // I had this as a reference, but that was wrong. Because // "result" gets over-written in the next block, result[1], may // get a reference count of zero, so be garbage collected. const ASTNode bottom = result[1]; if (SBVDIV == result.GetKind() || SBVREM == result.GetKind() || SBVMOD == result.GetKind()) { result = TranslateSignedDivModRem(result); } if (bm->UserFlags.division_by_zero_returns_one_flag) { // This is a difficult rule to introduce in other // places because it's recursive. i.e. result is // embedded unchanged inside the result. unsigned inputValueWidth = result.GetValueWidth(); ASTNode zero = bm->CreateZeroConst(inputValueWidth); ASTNode one = bm->CreateOneConst(inputValueWidth); result = nf->CreateTerm(ITE, inputValueWidth, nf->CreateNode(EQ, zero, bottom), one, result); //return result; if (bm->UserFlags.optimize_flag) return simp->SimplifyTerm_TopLevel(result); else return result; } } } break; } if (term.Degree() > 0) (*TransformMap)[term] = result; if (term.GetValueWidth() != result.GetValueWidth()) FatalError("TransformTerm: "\ "result and input terms are of different length", result); if (term.GetIndexWidth() != result.GetIndexWidth()) { cerr << "TransformTerm: input term is : " << term << endl; FatalError("TransformTerm: "\ "result & input terms have different index length", result); } return result; } //End of TransformTerm
//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
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; }
void ConstantBitPropagation::scheduleDown(const ASTNode& n) { for (int i = 0; i < n.Degree(); i++) workList->push(n[i]); }