// If the bits are totally fixed, then return a new matching ASTNode. ASTNode bitsToNode(const ASTNode& node, const FixedBits& bits) { ASTNode result; STPMgr & beev = *node.GetSTPMgr(); assert (bits.isTotallyFixed()); assert (!node.isConstant()); // Peformance. Shouldn't waste time calling it on constants. if (node.GetType() == BOOLEAN_TYPE) { if (bits.getValue(0)) { result = beev.CreateNode(TRUE); } else { result = beev.CreateNode(FALSE); } } else if (node.GetType() == BITVECTOR_TYPE) { result = beev.CreateBVConst(bits.GetBVConst(), node.GetValueWidth()); } else FatalError("sadf234s"); assert(result.isConstant()); return result; }
// Adds to the dependency graph that n0 depends on the variables in n1. // It's not the transitive closure of the dependencies. Just the variables in the expression "n1". // This is only needed as long as all the substitution rules haven't been written through. void SubstitutionMap::buildDepends(const ASTNode& n0, const ASTNode& n1) { if (n0.GetKind() != SYMBOL) return; if (n1.isConstant()) return; vector<Symbols*> av; vars.VarSeenInTerm(vars.getSymbol(n1), rhs_visited, rhs, av); sort(av.begin(), av.end()); for (int i = 0; i < av.size(); i++) { if (i != 0 && av[i] == av[i - 1]) continue; // Treat it like a set of Symbol* in effect. ASTNodeSet* sym = (vars.TermsAlreadySeenMap.find(av[i])->second); if (rhsAlreadyAdded.find(sym) != rhsAlreadyAdded.end()) continue; rhsAlreadyAdded.insert(sym); //cout << loopCount++ << " "; //cout << "initial" << rhs.size() << " Adding: " <<sym->size(); rhs.insert(sym->begin(), sym->end()); //cout << "final:" << rhs.size(); //cout << "added:" << sym << endl; } assert(dependsOn.find(n0) == dependsOn.end()); dependsOn.insert(make_pair(n0, vars.getSymbol(n1))); }
bool VariablesInExpression::VarSeenInTerm(const ASTNode& var, const ASTNode& term) { // This only returns true if we are searching for variables that aren't arrays. assert(var.GetKind() == SYMBOL && var.GetIndexWidth() == 0); if (term.isConstant()) return false; getSymbol(term); SymbolPtrSet visited; ASTNodeSet *symbols = new ASTNodeSet(); vector<Symbols*> av; VarSeenInTerm(symbol_graph[term.GetNodeNum()], visited, *symbols, av); bool result = (symbols->count(var) != 0); //cerr << "visited:" << visited.size() << endl; //cerr << "av:" << av.size() << endl; //cerr << "Term is const" << term.isConstant() << endl; if (visited.size() > 250) // No use caching it, unless we've done some work. { sort(av.begin(), av.end()); //cout << "===" << endl; for (size_t i = 0; i < av.size(); i++) { if (i!=0 && av[i] == av[i-1]) continue; const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second; //cout << "set: " << i << " " << sym.size() << endl; symbols->insert(sym.begin(), sym.end()); } TermsAlreadySeenMap.insert(make_pair(symbol_graph[term.GetNodeNum()], symbols)); //cout << "finish" << symbols->size() << endl; //cout << "===" << endl; result = (symbols->count(var) != 0); } else { const int size = av.size(); for (int i = 0; i < size; i++) { if (result) break; const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second; result |= (sym.find(var) != sym.end()); } delete symbols; } return result; }
// If n0 is replaced by n1 in the substitution map. Will it cause a loop? // i.e. will the dependency graph be an acyclic graph still. // For example, if we have x = F(y,z,w), it would make the substitutionMap loop // if there's already z = F(x). bool SubstitutionMap::loops(const ASTNode& n0, const ASTNode& n1) { if (n0.GetKind() != SYMBOL) return false; // sometimes this function is called with constants on the // lhs. if (n1.isConstant()) return false; // constants contain no variables. Can't loop. // We are adding an edge FROM n0, so unless there is already an edge TO n0, // there is no change it can loop. Unless adding this would add a TO and FROM // edge. if (rhs.find(n0) == rhs.end()) { return vars.VarSeenInTerm(n0, n1); } if (n1.GetKind() == SYMBOL && dependsOn.find(n1) == dependsOn.end()) return false; // The rhs is a symbol and doesn't appear. if (debug_substn) cout << loopCount++ << endl; bool destruct = true; ASTNodeSet* dependN = vars.SetofVarsSeenInTerm(n1, destruct); if (debug_substn) { cout << n0 << " " << n1.GetNodeNum(); //<< " Expression size:" << bm->NodeSize(n1,true); cout << "Variables in expression: " << dependN->size() << endl; } set<ASTNode> depend(dependN->begin(), dependN->end()); if (destruct) delete dependN; set<ASTNode> visited; loops_helper(depend, visited); bool loops = visited.find(n0) != visited.end(); if (debug_substn) cout << "Visited:" << visited.size() << "Loops:" << loops << endl; return (loops); }
void getSatVariables(const ASTNode& a, vector<unsigned>& v_a, SATSolver& SatSolver, ToSATBase::ASTNodeToSATVar& satVar) { ToSATBase::ASTNodeToSATVar::iterator it = satVar.find(a); if (it != satVar.end()) v_a = it->second; else if (!a.isConstant()) { assert(a.GetKind() == SYMBOL); // It was ommitted from the initial problem, so assign it freshly. for (unsigned i = 0; i < a.GetValueWidth(); i++) { uint32_t v = SatSolver.newVar(); // We probably don't want the variable eliminated. SatSolver.setFrozen(v); v_a.push_back(v); } satVar.insert(make_pair(a, v_a)); } }
void FindPureLiterals::build(const ASTNode& n, polarity_type polarity) { if (n.isConstant()) return; map<ASTNode, polarity_type>::iterator it = nodeToPolarity.find(n); if (it != nodeToPolarity.end()) { int lookupPolarity = it->second; if ((polarity | lookupPolarity) == lookupPolarity) return; // already traversed. it->second |= polarity; } else { nodeToPolarity.insert(std::make_pair(n, polarity)); } const Kind k = n.GetKind(); switch (k) { case AND: case OR: for (size_t i = 0; i < n.Degree(); i++) build(n[i], polarity); break; case NOT: polarity = swap(polarity); build(n[0], polarity); break; default: polarity = bothPolarity; // both for (size_t i = 0; i < n.Degree(); i++) build(n[i], polarity); break; } }
ASTNode RemoveUnconstrained::topLevel_other(const ASTNode &n, Simplifier *simplifier) { if (n.GetKind() == SYMBOL) return n; // top level is an unconstrained symbol/. simplifier_convenient = simplifier; ASTNodeSet noCheck; // We don't want to check some expensive nodes over and over again. vector<MutableASTNode*> variable_array; MutableASTNode* topMutable = MutableASTNode::build(n); vector<MutableASTNode*> extracts; topMutable->getDisjointExtractVariables(extracts); if (extracts.size() > 0) { splitExtractOnly(extracts); } topMutable->getAllUnconstrainedVariables(variable_array); for (int i =0; i < variable_array.size() ; i++) { // Don't make this is a reference. If the vector gets resized, it will point to // memory that no longer contains the object. MutableASTNode& muteNode = *variable_array[i]; const ASTNode var = muteNode.n; assert(var.GetKind() == SYMBOL); if (!muteNode.isUnconstrained()) continue; MutableASTNode& muteParent = muteNode.getParent(); if (noCheck.find(muteParent.n) != noCheck.end()) { continue; } vector <MutableASTNode*> mutable_children = muteParent.children; //nb. The children might be dirty. i.e. not have substitutions written through them yet. ASTVec children; children.reserve(mutable_children.size()); for (int j = 0; j <mutable_children.size(); j++ ) children.push_back(mutable_children[j]->n); const size_t numberOfChildren = children.size(); const Kind kind = muteNode.getParent().n.GetKind(); unsigned width = muteNode.getParent().n.GetValueWidth(); unsigned indexWidth = muteNode.getParent().n.GetIndexWidth(); ASTNode other; MutableASTNode* muteOther; if(numberOfChildren == 2) { if (children[0] != var) { other = children[0]; muteOther = mutable_children[0]; } else { other = children[1]; muteOther = mutable_children[1]; } if (kind != AND && kind != OR && kind != BVOR && kind != BVAND) if (other == var) continue; // Most rules don't like duplicate variables. } else { if (kind != AND && kind != OR && kind != BVOR && kind != BVAND) { int found = 0; for (int i = 0; i < numberOfChildren; i++) { if (children[i] == var) found++; } if (found != 1) continue; // Most rules don't like duplicate variables. } } /* cout << i << " " << kind << " " << variable_array.size() << " " << mutable_children.size() << endl; cout << "children[0]" << children[0] << endl; cout << "children[1]" << children[1] << endl; cout << muteParent.n << endl; */ switch (kind) { case BVCONCAT: assert(numberOfChildren == 2); if (mutable_children[0]->isUnconstrained() && (mutable_children[1]->isUnconstrained())) { ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTNode top_lhs = bm.CreateBVConst(32, width - 1); ASTNode bottom_lhs = bm.CreateBVConst(32, children[1].GetValueWidth()); ASTNode top_rhs = bm.CreateBVConst(32, children[1].GetValueWidth()- 1); ASTNode bottom_rhs = bm.CreateBVConst(32, 0); ASTNode lhs = nf->CreateTerm(BVEXTRACT, children[0].GetValueWidth(), v,top_lhs, bottom_lhs); ASTNode rhs = nf->CreateTerm(BVEXTRACT, children[1].GetValueWidth(), v,top_rhs, bottom_rhs); replace(children[0],lhs); replace(children[1],rhs); } break; case NOT: { ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(children[0], nf->CreateNode(NOT, v)); } break; case BVUMINUS: case BVNEG: { assert(numberOfChildren ==1); ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(var, nf->CreateTerm(kind, width,v)); } break; case BVSGT: case BVSGE: case BVGT: case BVGE: { width = var.GetValueWidth(); if (width ==1) continue; // Hard to get right, not used often. ASTNode biggestNumber, smallestNumber; if (kind == BVSGT || kind == BVSGE) { // 011111111 (most positive number.) CBV max = CONSTANTBV::BitVector_Create(width, false); CONSTANTBV::BitVector_Fill(max); CONSTANTBV::BitVector_Bit_Off(max, width - 1); biggestNumber = bm.CreateBVConst(max, width); // 1000000000 (most negative number.) max = CONSTANTBV::BitVector_Create(width, true); CONSTANTBV::BitVector_Bit_On(max, width - 1); smallestNumber = bm.CreateBVConst(max, width); } else if (kind == BVGT || kind == BVGE) { biggestNumber = bm.CreateMaxConst(width); smallestNumber = bm.CreateZeroConst(width); } else FatalError("SDFA!@S"); ASTNode c1,c2; if (kind == BVSGT || kind == BVGT) { c1= biggestNumber; c2 = smallestNumber; } else if (kind == BVSGE || kind == BVGE) { c1= smallestNumber; c2 = biggestNumber; } else FatalError("SDFA!@S"); if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained()) { ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTNode lhs = nf->CreateTerm(ITE, width, v, bm.CreateOneConst(width), bm.CreateZeroConst(width)); ASTNode rhs = nf->CreateTerm(ITE, width, v, bm.CreateZeroConst(width), bm.CreateOneConst(width)); replace(children[0], lhs); replace(children[1], rhs); } else if (children[0] == var && children[1].isConstant()) { if (children[1] == c1) continue; // always false. Or always false. ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTNode rhs = nf->CreateTerm(ITE, width, v,biggestNumber, smallestNumber); replace(var, rhs); } else if (children[1] == var && children[0].isConstant()) { if (children[0] == c2) continue; // always false. Or always false. ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTNode rhs = nf->CreateTerm(ITE, width, v, smallestNumber, biggestNumber); replace(var, rhs); } else // One side is a variable. The other is anything. { bool varOnLHS = (var == children[0]); // All the ASTNode vars need to map to their existing MutableASTNodes. So we collect all the variables vector<MutableASTNode*> vars; set<MutableASTNode*> visited; muteOther->getAllVariablesRecursively(vars, visited); visited.clear(); map<ASTNode, MutableASTNode *> create; for (vector<MutableASTNode*>::iterator it = vars.begin(); it != vars.end();it++) create.insert(make_pair((*it)->n, *it)); vars.clear(); ASTNode v= bm.CreateFreshVariable(0, 0, "STP_INTERNAL_comparison"); ASTNode rhs; ASTNode n; if (varOnLHS) { rhs = nf->CreateTerm(ITE, width, v, biggestNumber, smallestNumber); if (kind == BVSGE || kind == BVGE) n= nf->CreateNode(OR, v, nf->CreateNode(EQ, mutable_children[1]->toASTNode(nf), c1)); else n= nf->CreateNode(AND, v, nf->CreateNode(NOT,nf->CreateNode(EQ, mutable_children[1]->toASTNode(nf), c1))); } else { rhs = nf->CreateTerm(ITE, width, v, smallestNumber, biggestNumber); if (kind == BVSGE || kind == BVGE) n= nf->CreateNode(OR, v, nf->CreateNode(EQ, mutable_children[0]->toASTNode(nf), c2)); else n= nf->CreateNode(AND, v, nf->CreateNode(NOT,nf->CreateNode(EQ, mutable_children[0]->toASTNode(nf), c2))); } replace(var, rhs); MutableASTNode *newN = MutableASTNode::build(n,create); muteParent.replaceWithAnotherNode(newN); //assert(muteParent.checkInvariant()); } } break; case AND: case OR: case BVOR: case BVAND: { if (allChildrenAreUnconstrained(mutable_children)) { ASTNodeSet already; ASTNode v =replaceParentWithFresh(muteParent, variable_array); for (int i =0; i < numberOfChildren;i++) { /* to avoid problems with: 734:(AND 732:unconstrained_4 716:unconstrained_2 732:unconstrained_4) */ if (already.find(children[i]) == already.end()) { replace(children[i], v); already.insert(children[i]); } } } else { // Hack. ff.stp has a 325k node conjunction // So we check if all the children are unconstrained each time // we find a new unconstrained conjunct. This means that if // eventually all the nodes become unconstrained we will miss it // and not rewrite the AND to a fresh unconstrained variable. if (mutable_children.size() > 200) noCheck.insert(muteParent.n); } } break; case XOR: case BVXOR: { ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTVec others; for (int i = 0; i < numberOfChildren; i++) { if (children[i] !=var) others.push_back(mutable_children[i]->toASTNode(nf)); } assert(others.size() +1 == numberOfChildren); assert(others.size() >=1); if (kind == XOR) { ASTNode xorNode = nf->CreateNode(XOR, others); replace(var, nf->CreateNode(XOR, v, xorNode)); } else { ASTNode xorNode ; if (others.size() > 1 ) xorNode = nf->CreateTerm(BVXOR, width, others); else xorNode = others[0]; replace(var, nf->CreateTerm(BVXOR, width, v, xorNode)); } } break; case ITE: { if (indexWidth > 0) continue; // don't do arrays. if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained() && children[0] != children[1]) { ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(children[0], bm.ASTTrue); replace(children[1], v); } else if (mutable_children[0]->isUnconstrained() && mutable_children[2]->isUnconstrained() && children[0] != children[2]) { ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(children[0], bm.ASTFalse); replace(children[2], v); } else if (mutable_children[1]->isUnconstrained() && mutable_children[2]->isUnconstrained()) { ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(children[1], v); if (children[1] != children[2]) replace(children[2], v); } } break; case BVLEFTSHIFT: case BVRIGHTSHIFT: case BVSRSHIFT: { assert(numberOfChildren == 2); if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained()) { assert(children[0] != children[1]); ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(children[1], bm.CreateZeroConst(width)); replace(children[0], v); } } break; case BVMOD: { assert(numberOfChildren == 2); if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained() && bm.UserFlags.isSet("unconstrained-bvmod", "0") ) { assert (children[0] != children[1]); ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(children[1], bm.CreateZeroConst(width)); replace(children[0], v); } } break; case BVDIV: { assert(numberOfChildren == 2); if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained()) { assert (children[0] != children[1]); ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(children[1], bm.CreateOneConst(width)); replace(children[0], v); } } break; case BVMULT: { assert(numberOfChildren == 2); if (mutable_children[1]->isUnconstrained() && mutable_children[0]->isUnconstrained()) // both are unconstrained { ASTNode v =replaceParentWithFresh(muteParent, variable_array); replace(children[0], bm.CreateOneConst(width)); replace(children[1], v); } if (other.isConstant() && simplifier->BVConstIsOdd(other)) { ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTNode inverse = simplifier->MultiplicativeInverse(other); ASTNode rhs = nf->CreateTerm(BVMULT, width, inverse, v); replace(var, rhs); } break; case IFF: { ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTNode rhs = nf->CreateNode(ITE, v, muteOther->toASTNode(nf), nf->CreateNode(NOT, muteOther->toASTNode(nf))); replace(var, rhs); } break; case EQ: { ASTNode v =replaceParentWithFresh(muteParent, variable_array); width = var.GetValueWidth(); ASTNode rhs = nf->CreateTerm(ITE, width, v, muteOther->toASTNode(nf), nf->CreateTerm(BVPLUS, width, muteOther->toASTNode(nf), bm.CreateOneConst(width))); replace(var, rhs); } break; case BVSUB: { assert(numberOfChildren == 2); ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTNode rhs; if (children[0] == var) rhs= nf->CreateTerm(BVPLUS, width, v, muteOther->toASTNode(nf)); if (children[1] == var) rhs= nf->CreateTerm(BVSUB, width, muteOther->toASTNode(nf), v); replace(var, rhs); } break; case BVPLUS: { ASTVec other; for (int i = 0; i < children.size(); i++) if (children[i] != var) other.push_back(mutable_children[i]->toASTNode(nf)); assert(other.size() == children.size()-1); assert(other.size() >=1); ASTNode v =replaceParentWithFresh(muteParent, variable_array); ASTNode rhs; if (other.size() > 1) rhs = nf->CreateTerm(BVSUB, width, v, nf->CreateTerm(BVPLUS, width, other)); else rhs = nf->CreateTerm(BVSUB, width, v, other[0]); replace(var, rhs); } break; case BVEXTRACT: { ASTNode v =replaceParentWithFresh(muteParent, variable_array); const unsigned resultWidth = width; const unsigned operandWidth = var.GetValueWidth(); assert(children[0] == var); // It can't be anywhere else. // Create Fresh variables to pad the LHS and RHS. const unsigned high = children[1].GetUnsignedConst(); const unsigned low = children[2].GetUnsignedConst(); assert(high >=low); const int rhsSize = low; const int lhsSize = operandWidth - high - 1; ASTNode current = v; int newWidth = v.GetValueWidth(); if (lhsSize > 0) { ASTNode lhsFresh = bm.CreateFreshVariable(0, lhsSize, "lhs_padding"); current = nf->CreateTerm(BVCONCAT, newWidth + lhsSize, lhsFresh, current); newWidth += lhsSize; } if (rhsSize > 0) { ASTNode rhsFresh = bm.CreateFreshVariable(0, rhsSize, "rhs_padding"); current = nf->CreateTerm(BVCONCAT, newWidth + rhsSize, current, rhsFresh); newWidth += rhsSize; } assert(newWidth == operandWidth); replace(var, current); } break; default: { //cerr << "!!!!" << kind << endl; } // cerr << var; // cerr << parent; } } } ASTNode result = topMutable->toASTNode(nf); topMutable->cleanup(); //cout << result; return result; }
// This function adds the clauses to constrain that "a" and "b" equal a fresh // variable // (which it returns). // Because it's used to create array axionms (a=b)-> (c=d), it can be // used to only add one of the two polarities. Minisat::Var getEquals(SATSolver& SatSolver, const ASTNode& a, const ASTNode& b, ToSATBase::ASTNodeToSATVar& satVar, Polarity polary = BOTH) { const unsigned width = a.GetValueWidth(); assert(width == b.GetValueWidth()); assert(!a.isConstant() || !b.isConstant()); vector<unsigned> v_a; vector<unsigned> v_b; getSatVariables(a, v_a, SatSolver, satVar); getSatVariables(b, v_b, SatSolver, satVar); // The only time v_a or v_b will be empty is if "a" resp. "b" is a constant. if (v_a.size() == width && v_b.size() == width) { SATSolver::vec_literals all; const int result = SatSolver.newVar(); for (unsigned i = 0; i < width; i++) { SATSolver::vec_literals s; if (polary != RIGHT_ONLY) { int nv0 = SatSolver.newVar(); s.push(SATSolver::mkLit(v_a[i], true)); s.push(SATSolver::mkLit(v_b[i], true)); s.push(SATSolver::mkLit(nv0, false)); SatSolver.addClause(s); s.clear(); s.push(SATSolver::mkLit(v_a[i], false)); s.push(SATSolver::mkLit(v_b[i], false)); s.push(SATSolver::mkLit(nv0, false)); SatSolver.addClause(s); s.clear(); all.push(SATSolver::mkLit(nv0, true)); } if (polary != LEFT_ONLY) { s.push(SATSolver::mkLit(v_a[i], true)); s.push(SATSolver::mkLit(v_b[i], false)); s.push(SATSolver::mkLit(result, true)); SatSolver.addClause(s); s.clear(); s.push(SATSolver::mkLit(v_a[i], false)); s.push(SATSolver::mkLit(v_b[i], true)); s.push(SATSolver::mkLit(result, true)); SatSolver.addClause(s); s.clear(); } } if (all.size() > 0) { all.push(SATSolver::mkLit(result, false)); SatSolver.addClause(all); } return result; } else if ((v_a.size() == 0) ^ (v_b.size() == 0)) { ASTNode constant = a.isConstant() ? a : b; vector<unsigned> vec = v_a.size() == 0 ? v_b : v_a; assert(constant.isConstant()); assert(vec.size() == width); SATSolver::vec_literals all; const int result = SatSolver.newVar(); all.push(SATSolver::mkLit(result, false)); CBV v = constant.GetBVConst(); for (unsigned i = 0; i < width; i++) { if (polary != RIGHT_ONLY) { if (CONSTANTBV::BitVector_bit_test(v, i)) all.push(SATSolver::mkLit(vec[i], true)); else all.push(SATSolver::mkLit(vec[i], false)); } if (polary != LEFT_ONLY) { SATSolver::vec_literals p; p.push(SATSolver::mkLit(result, true)); if (CONSTANTBV::BitVector_bit_test(v, i)) p.push(SATSolver::mkLit(vec[i], false)); else p.push(SATSolver::mkLit(vec[i], true)); SatSolver.addClause(p); } } if (all.size() > 1) SatSolver.addClause(all); return result; } else { FatalError("Unexpected, both must be constants.."); exit(-1); } }
int numberOfConstants() const { return ((index0.isConstant() ? 1 : 0) + (index1.isConstant() ? 1 : 0) + (index0.isConstant() ? 1 : 0) + (index1.isConstant() ? 1 : 0)); }
void Gen68k::codeInstr(InstructionETPB* bInstr){ registerStack->init(); switch(bInstr->getNat()){ case INS_DECLARATION: break; case INS_UNKNOWN: break; case INS_AFFECTATION: Operande68k* ExprArbrAff; //=registerStack->front(); Operande68k* ExprArbrAffected; int nG,nD; nG=getNbRegArith(bInstr->getAssignmentExprAssigned(),NO_REG); nD=getNbRegArith(bInstr->getAssignmentExprTree(),NO_REG); if (nD >= nG){ codeArith(bInstr->getAssignmentExprTree(),NO_REG,&ExprArbrAff); registerStack->allocate(ExprArbrAff); codeArith(bInstr->getAssignmentExprAssigned(),NO_DADR,&ExprArbrAffected); registerStack->freeOperand(ExprArbrAff); ilCoder.add(MOVE,ExprArbrAff,ExprArbrAffected,getSize(bInstr->getAssignmentExprAssigned())); } else{ codeArith(bInstr->getAssignmentExprAssigned(),NO_DADR,&ExprArbrAffected); registerStack->allocate(ExprArbrAffected); codeArith(bInstr->getAssignmentExprTree(),NO_REG,&ExprArbrAff); registerStack->freeOperand(ExprArbrAffected); ilCoder.add(MOVE,ExprArbrAff,ExprArbrAffected,getSize(bInstr->getAssignmentExprAssigned())); } break; case INS_RETURN: Operande68k* OpResReturn; if (bInstr->getExprReturn()){ codeArith(bInstr->getExprReturn(),NO_REG,&OpResReturn); ilCoder.add(MOVE,OpResReturn,ilCoder.createOp(D0),getSize(bInstr->getExprReturn())); } if (currentStackVariablesSize) ilCoder.add(ADD,ilCoder.createOpVal(currentStackVariablesSize),ilCoder.createOp(SP_REG),SZ_L); ilCoder.add(RTS); returnInstrAsLastInstr = true; break; case INS_CALL: int somme; ASTNode* CallNoeud; somme=0; // la somme des tailles de ce qui est pouss? dans la pile size_op68k SizeOfArgument; CallNoeud=bInstr->getExprFunctionCall(); Operande68k* Op2; for (int i=CallNoeud->getSuccNmbr()-1;i>=0;i--){ SizeOfArgument=getSize(*CallNoeud->getSuccPtr(i)); somme+=(int)SizeOfArgument; codeArith(*CallNoeud->getSuccPtr(i),NO_REG,&Op2); ilCoder.add(MOVE,Op2,ilCoder.createOp(A7,false,true),SizeOfArgument); virtualStack.pushToStack(SizeOfArgument); } ilCoder.add(BSR,ilCoder.createOpLabel(CallNoeud->getTag()->GetIdentif()),SZ_NA); if (somme){ ilCoder.add(ADD,ilCoder.createOpVal(somme),ilCoder.createOp(SP_REG),SZ_L); } //virtualStack.display(); for (int i=CallNoeud->getSuccNmbr()-1;i>=0;i--){ virtualStack.pop(); //virtualStack.display(); } break; case INS_STRUCT_FOR: ASTNode* initExpr; ASTNode* finExpr; ASTNode* stepExpr; ASTNode* varExpr; Operande68k* EtiqForDebTest; Operande68k* EtiqForFin; size_op68k SizeVarIter; Operande68k* TexpTO; Collection* CorpsFor; initExpr = bInstr->getForExprInitTree(); finExpr = bInstr->getForExprToTree(); stepExpr = bInstr->getForExprStepTree(); varExpr = bInstr->getForExprAssigned(); CorpsFor = bInstr->getForBody(); SizeVarIter =getSize(varExpr); EtiqForDebTest = ilCoder.createOpLabel(); EtiqForFin = ilCoder.createOpLabel(); // --------------------------------------------------- // Affectation initiale // --------------------------------------------------- nG=getNbRegArith(varExpr,NO_REG); nD=getNbRegArith(initExpr,NO_REG); if (nD >= nG){ codeArith(initExpr,NO_REG,&ExprArbrAff); registerStack->allocate(ExprArbrAff); codeArith(varExpr,NO_DADR,&ExprArbrAffected); registerStack->freeOperand(ExprArbrAff); ilCoder.add(MOVE,ExprArbrAff,ExprArbrAffected,SizeVarIter); } else{ codeArith(varExpr,NO_DADR,&ExprArbrAffected); registerStack->allocate(ExprArbrAffected); codeArith(initExpr,NO_REG,&ExprArbrAff); registerStack->freeOperand(ExprArbrAffected); ilCoder.add(MOVE,ExprArbrAff,ExprArbrAffected,SizeVarIter); } // --------------------------------------------------- // Evaluation de l'expression d'arriv?e // --------------------------------------------------- // temporaire sur la pile qui va contenir la valeur de l'expression d'arriv?e TO TexpTO=registerStack->allocateTemp(SizeVarIter); codeArith(finExpr,NO_REG,&ExprArbrAff); //registerStack->allocate(ExprArbrAff); ilCoder.add(MOVE,ExprArbrAff,TexpTO,SizeVarIter); //registerStack->freeOperand(ExprArbrAff); // --------------------------------------------------- // Test de la condition d'arriv? // --------------------------------------------------- ilCoder.addLabel(EtiqForDebTest->val.valLabel); // cas 1: pas de step if (stepExpr == NULL){ codeArith(varExpr,NO_REG,&ExprArbrAffected); ilCoder.add(CMP,TexpTO,ExprArbrAffected,SizeVarIter); ilCoder.add(BGT,EtiqForFin,SZ_NA); codeInstr(CorpsFor); // iterateur = iterateur+1 sous entendu codeArith(varExpr,NO_DADR,&ExprArbrAffected); ilCoder.add(ADD,ilCoder.createOpVal(1),ExprArbrAffected,SizeVarIter); ilCoder.add(BRA,EtiqForDebTest,SZ_NA); } // cas 2: step constante else if (stepExpr->isConstant()){ int constStepVal; constStepVal = atoi(stepExpr->getTag()->GetIdentif()); codeArith(varExpr,NO_REG,&ExprArbrAffected); ilCoder.add(CMP,TexpTO,ExprArbrAffected,SizeVarIter); if (constStepVal < 0){ ilCoder.add(BLT,EtiqForFin,SZ_NA); } else { ilCoder.add(BGT,EtiqForFin,SZ_NA); } codeInstr(CorpsFor); // iterateur = iterateur+cte sous entendu codeArith(varExpr,NO_DADR,&ExprArbrAffected); ilCoder.add(ADD,ilCoder.createOpVal(constStepVal),ExprArbrAffected,SizeVarIter); ilCoder.add(BRA,EtiqForDebTest,SZ_NA); } // cas 3: step non-constante else { //Operande68k* EtiqNegStep; //Operande68k* EtiqForDebCorps; //EtiqForFin = ilCoder.createOpLabel(); } ilCoder.addLabel(EtiqForFin->val.valLabel); registerStack->freeTemp(TexpTO,SizeVarIter); // on libere le temporaire qui contient l'expression de fin break; case INS_STRUCT_DOLPWH: // do ... loop while (condition) Collection* CorpsDo; ASTNode* exprDo; Operande68k* EtiqDebut; CorpsDo = bInstr->getDoBody(); exprDo = bInstr->getDoExprCondition(); EtiqDebut = ilCoder.createOpLabel(); ilCoder.addLabel(EtiqDebut->val.valLabel); codeInstr(CorpsDo); codeBool(exprDo,true,true,EtiqDebut,false,false); break; case INS_STRUCT_DOWH: // do while (condition) .... loop Collection* CorpsWhile; ASTNode* exprWhile; Operande68k* EtiqWhileDebut; Operande68k* EtiqWhileFin; CorpsWhile = bInstr->getDoBody(); exprWhile = bInstr->getDoExprCondition(); EtiqWhileDebut = ilCoder.createOpLabel(); EtiqWhileFin = ilCoder.createOpLabel(); // juste avant le test de la condition ilCoder.add(BRA,EtiqWhileFin,SZ_NA); // on va directement voir le test ilCoder.addLabel(EtiqWhileDebut->val.valLabel); codeInstr(CorpsWhile); ilCoder.addLabel(EtiqWhileFin->val.valLabel); codeBool(exprWhile,true,true,EtiqWhileDebut,false,false); break; case INS_IF: ASTNode* exprIf; exprIf = bInstr->getIfExprTree(); //printf("codeInstr IF\n"); //printf("Expression du If:\n"); //exprIf->display(); Operande68k* EtiqFinCorpsIF = ilCoder.createOpLabel(); Operande68k* EtiqFinLocalCorpsElseIf; Operande68k* EtiqDebutElse=NULL; // utilis? s'il y a des elseIf et un else Operande68k* EtiqFinBloc; Collection* InstrCorpsIf = bInstr->getIfIfBody(); Collection* InstrCorpsElse = bInstr->getIfElseBody(); Collection* listExprElseIf = bInstr->getIfExprElseIf(); Collection* listCorpsElseIf = bInstr->getIfElseIfBody(); ColIterator iterExprElseIf; ColIterator iterCorpsElseIf; listExprElseIf->bindIterator(&iterExprElseIf); listCorpsElseIf->bindIterator(&iterCorpsElseIf); Collection* InstrCorpsElseIf; ASTNode* exprElseIf; // ------------------------------------------------------- // Codage de expression de IF // ------------------------------------------------------- codeBool(exprIf,true,false,EtiqFinCorpsIF,false,false); // le dernier false n'a aucun impact normalement // ------------------------------------------------------- // Codage de corps de IF // ------------------------------------------------------- codeInstr(InstrCorpsIf); if (!InstrCorpsElse->estVide() || !listExprElseIf->estVide() ){ EtiqFinBloc = ilCoder.createOpLabel(); ilCoder.add(BRA,EtiqFinBloc,SZ_NA); // on ajoute un saut ? tout ? la fin s'il y a un else ou des elseif } // ------------------------------------------------------- // label fin corps If // ------------------------------------------------------- ilCoder.addLabel(EtiqFinCorpsIF->val.valLabel); // ------------------------------------------------------- // Codage des ELSE IF // ------------------------------------------------------- while(iterExprElseIf.elemExists()){ exprElseIf=(ASTNode*)iterExprElseIf.getNext(); InstrCorpsElseIf=(Collection*)iterCorpsElseIf.getNext(); if (iterExprElseIf.elemExists()) { // le suivant existe EtiqFinLocalCorpsElseIf = ilCoder.createOpLabel(); // donc nouvelle etiquette } else { // dernier element EtiqDebutElse = ilCoder.createOpLabel(); EtiqFinLocalCorpsElseIf=EtiqDebutElse; // on utilise l'etiquette de fin de tout le bloc IF } // ------------------------------------------------------- // Codage de expression de ElseIF // ------------------------------------------------------- codeBool(exprElseIf,true,false,EtiqFinLocalCorpsElseIf,false,false); // ------------------------------------------------------- // Codage de corps de ElseIF // ------------------------------------------------------- codeInstr(InstrCorpsElseIf); if (!InstrCorpsElse->estVide()){ // il existe un Else, il ne faut pas executer son corps, donc saut ? la fin ilCoder.add(BRA,EtiqFinBloc,SZ_NA); } if (iterExprElseIf.elemExists()) { // le suivant ElseIf existe, on avait cr?e une nouvelle ?tiquette ilCoder.addLabel(EtiqFinLocalCorpsElseIf->val.valLabel); // label fin corps ElseIf } } // ------------------------------------------------------- // Codage de corps de ELSE // ------------------------------------------------------- if (EtiqDebutElse) { // un elseif a cr?e une ?tiquette debut Else ilCoder.addLabel(EtiqDebutElse->val.valLabel); // label fin corps ElseIf } codeInstr(InstrCorpsElse); // ------------------------------------------------------- // label fin Global // ------------------------------------------------------- if (!InstrCorpsElse->estVide() || !listExprElseIf->estVide()){ ilCoder.addLabel(EtiqFinBloc->val.valLabel); // label fin corps Else } break; } }
Result dispatchToTransferFunctions(const Kind k, vector<FixedBits*>& children, FixedBits& output, const ASTNode n, MultiplicationStatsMap * msm) { Result result = NO_CHANGE; assert(!n.isConstant()); Result(*transfer)(vector<FixedBits*>&, FixedBits&); switch (k) { case READ: case WRITE: // do nothing. Seems difficult to track properly. return NO_CHANGE; break; #define MAPTFN(caseV, FN) case caseV: transfer = FN; break; // Shifting MAPTFN(BVLEFTSHIFT, bvLeftShiftBothWays) MAPTFN(BVRIGHTSHIFT, bvRightShiftBothWays) MAPTFN(BVSRSHIFT, bvArithmeticRightShiftBothWays) // Unsigned Comparison. MAPTFN(BVLT,bvLessThanBothWays) MAPTFN(BVLE,bvLessThanEqualsBothWays) MAPTFN(BVGT, bvGreaterThanBothWays) MAPTFN(BVGE, bvGreaterThanEqualsBothWays) // Signed Comparison. MAPTFN(BVSLT, bvSignedLessThanBothWays) MAPTFN(BVSGT,bvSignedGreaterThanBothWays) MAPTFN(BVSLE, bvSignedLessThanEqualsBothWays) MAPTFN(BVSGE, bvSignedGreaterThanEqualsBothWays) // Logic. MAPTFN(XOR,bvXorBothWays) MAPTFN(BVXOR, bvXorBothWays) MAPTFN(OR, bvOrBothWays) MAPTFN(BVOR, bvOrBothWays) MAPTFN(AND,bvAndBothWays) MAPTFN(BVAND,bvAndBothWays) MAPTFN(IFF, bvEqualsBothWays) MAPTFN(EQ, bvEqualsBothWays) MAPTFN(IMPLIES,bvImpliesBothWays) MAPTFN(NOT,bvNotBothWays) MAPTFN(BVNEG, bvNotBothWays) // OTHER MAPTFN(BVZX, bvZeroExtendBothWays) MAPTFN(BVSX, bvSignExtendBothWays) MAPTFN(BVUMINUS,bvUnaryMinusBothWays) MAPTFN(BVEXTRACT,bvExtractBothWays) MAPTFN(BVPLUS, bvAddBothWays) MAPTFN(BVSUB, bvSubtractBothWays) MAPTFN(ITE,bvITEBothWays) MAPTFN(BVCONCAT, bvConcatBothWays) #ifdef WITHCBITP case BVMULT: // handled specially later. case BVDIV: case BVMOD: case SBVDIV: case SBVREM: case SBVMOD: transfer = NULL; break; #endif default: { notHandled(k); return NO_CHANGE; } } #undef MAPTFN bool mult_like = false; #ifdef WITHCBITP // safe approximation to no overflow multiplication. if (k == BVMULT) { MultiplicationStats ms; result = bvMultiplyBothWays(children, output, n.GetSTPMgr(),&ms); if (CONFLICT != result) msm->map[n] = ms; mult_like=true; } else if (k == BVDIV) { result = bvUnsignedDivisionBothWays(children, output, n.GetSTPMgr()); mult_like=true; } else if (k == BVMOD) { result = bvUnsignedModulusBothWays(children, output, n.GetSTPMgr()); mult_like=true; } else if (k == SBVDIV) { result = bvSignedDivisionBothWays(children, output, n.GetSTPMgr()); mult_like=true; } else if (k == SBVREM) { result = bvSignedRemainderBothWays(children, output, n.GetSTPMgr()); mult_like=true; } else if (k == SBVMOD) { result = bvSignedModulusBothWays(children, output, n.GetSTPMgr()); mult_like=true; } else #endif result = transfer(children, output); if (mult_like && output_mult_like) { cerr << output << "="; cerr << *children[0] << k; cerr << *children[1] << std::endl; } return result; }
// NB: This expects that the constructor was called with teh same node. Sorry. ASTNode ConstantBitPropagation::topLevelBothWays(const ASTNode& top) { assert(top.GetSTPMgr()->UserFlags.bitConstantProp_flag); assert (BOOLEAN_TYPE == top.GetType()); propagate(); status = NO_CHANGE; //Determine what must always be true. ASTNodeMap fromTo = getAllFixed(); if (debug_cBitProp_messages) { cerr << "Number removed by bottom UP:" << fromTo.size() << endl; } setNodeToTrue(top); if (debug_cBitProp_messages) { cerr << "starting propagation" << endl; printNodeWithFixings(); cerr << "Initial Tree:" << endl; cerr << top; } propagate(); if (debug_cBitProp_messages) { cerr << "status:" << status <<endl; cerr << "ended propagation" << endl; printNodeWithFixings(); } // propagate may have stopped with a conflict. if (CONFLICT == status) return top.GetSTPMgr()->CreateNode(FALSE); ASTVec toConjoin; // go through the fixedBits. If a node is entirely fixed. // "and" it onto the top. Creates redundancy. Check that the // node doesn't already depend on "top" directly. for (NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it = fixedMap->map->begin(); it != fixedMap->map->end(); it++) // iterates through all the pairs of node->fixedBits. { const FixedBits& bits = *it->second; if (!bits.isTotallyFixed()) continue; const ASTNode& node = (it->first); // Don't constrain nodes we already know all about. if (node.isConstant()) continue; // other nodes will contain the same information (the extract doesn't change the fixings). if (BVEXTRACT == node.GetKind() || BVCONCAT == node.GetKind()) continue; // toAssign: conjoin it with the top level. // toReplace: replace all references to it (except the one conjoined to the top) with this. ASTNode propositionToAssert; ASTNode constantToReplaceWith; // skip the assigning and replacing. bool doAssign = true; { // If it is already contained in the fromTo map, then it's one of the values // that have fully been determined (previously). Not conjoined. if (fromTo.find(node) != fromTo.end()) continue; ASTNode constNode = bitsToNode(node,bits); if (node.GetType() == BOOLEAN_TYPE) { if (SYMBOL == node.GetKind()) { bool r = simplifier->UpdateSubstitutionMap(node, constNode); assert(r); doAssign = false; } else if (bits.getValue(0)) { propositionToAssert = node; constantToReplaceWith = constNode; } else { propositionToAssert = nf->CreateNode(NOT, node); constantToReplaceWith = constNode; } } else if (node.GetType() == BITVECTOR_TYPE) { assert(((unsigned)bits.getWidth()) == node.GetValueWidth()); if (SYMBOL == node.GetKind()) { bool r = simplifier->UpdateSubstitutionMap(node, constNode); assert(r); doAssign = false; } else { propositionToAssert = nf->CreateNode(EQ, node, constNode); constantToReplaceWith = constNode; } } else FatalError("sadf234s"); } if (doAssign && top != propositionToAssert && !dependents->nodeDependsOn(top, propositionToAssert)) { assert(!constantToReplaceWith.IsNull()); assert(constantToReplaceWith.isConstant()); assert(propositionToAssert.GetType() == BOOLEAN_TYPE); assert(node.GetValueWidth() == constantToReplaceWith.GetValueWidth()); fromTo.insert(make_pair(node, constantToReplaceWith)); toConjoin.push_back(propositionToAssert); } } // Write the constants into the main graph. ASTNodeMap cache; ASTNode result = SubstitutionMap::replace(top, fromTo, cache,nf); if (0 != toConjoin.size()) { // It doesn't happen very often. But the "toConjoin" might contain a variable // that was added to the substitution map (because the value was determined just now // during propagation. ASTNode conjunct = (1 == toConjoin.size())? toConjoin[0]: nf->CreateNode(AND,toConjoin); conjunct = simplifier->applySubstitutionMap(conjunct); result = nf->CreateNode(AND, result, conjunct); // conjoin the new conditions. } if (debug_print_graph_after) { ofstream file; file.open("afterCbitp.gdl"); PrintingHackfixedMap = fixedMap; printer::GDL_Print(file,top,&toString); file.close(); } assert(BVTypeCheck(result)); assert(status != CONFLICT); // conflict should have been seen earlier. return result; }