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; }
/* 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
/******************************************************** * 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; }