constraint.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003, Mike Van Emmerik
00003  *
00004  * See the file "LICENSE.TERMS" for information on usage and
00005  * redistribution of this file, and for a DISCLAIMER OF ALL
00006  * WARRANTIES.
00007  *
00008  */
00009 
00010 /*==============================================================================
00011  * FILE:       constraint.cpp
00012  * OVERVIEW:   Implementation of objects related to type constraints
00013  *============================================================================*/
00014 
00015 /*
00016  * $Revision: 1.19 $    // 1.16.6.1
00017  *
00018  * 22 Aug 03 - Mike: Created
00019  */
00020 
00021 #include "constraint.h"
00022 #include "managed.h"
00023 #include "exp.h"
00024 #include "boomerang.h"
00025 #include "log.h"
00026 #include <sstream>
00027 
00028 void ConstraintMap::print(std::ostream& os) {
00029     iterator kk;
00030     bool first = true;
00031     for (kk = cmap.begin(); kk != cmap.end(); kk++) {
00032         if (first) first = false;
00033         else os << ", ";
00034         os << kk->first << " = " << kk->second;
00035     }
00036     os << "\n";
00037 }
00038 
00039 extern char debug_buffer[];
00040 char* ConstraintMap::prints() {
00041     std::ostringstream ost;
00042     print(ost);
00043     strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
00044     debug_buffer[DEBUG_BUFSIZE-1] = '\0';
00045     return debug_buffer;
00046 }
00047 
00048 void ConstraintMap::makeUnion(ConstraintMap& o) {
00049     std::map<Exp*, Exp*, lessExpStar>::iterator it;
00050     std::pair<std::map<Exp*, Exp*, lessExpStar>::iterator, bool> ret;
00051     for (it = o.cmap.begin(); it != o.cmap.end(); it++) {
00052         // Note: *it is a std::pair<Exp*, Exp*>
00053         ret = cmap.insert(*it);
00054         // If an insertion occured, ret will be std::pair<where, true>
00055         // If no insertion occured, ret will be std::pair<where, false>
00056         if (ret.second == false) {
00057 //std::cerr << "ConstraintMap::makeUnion: want to overwrite " << ret.first->first
00058 // << " -> " << ret.first->second << " with " << it->first << " -> " << it->second << "\n";
00059             TypeVal* Tret = (TypeVal*)ret.first->second;
00060             Type* ty1 = Tret->getType();
00061             TypeVal* Toth = (TypeVal*)it->second;
00062             Type* ty2 = Toth->getType();
00063             if (ty1 && ty2 && *ty1 != *ty2) {
00064                 Tret->setType(ty1->mergeWith(ty2));
00065 //std::cerr << "Now " << ret.first->first << " -> " << ret.first->second << "\n"; 
00066             }
00067         }
00068     }
00069 }
00070 
00071 void ConstraintMap::insert(Exp* term) {
00072     assert(term->isEquality());
00073     Exp* lhs = ((Binary*)term)->getSubExp1();
00074     Exp* rhs = ((Binary*)term)->getSubExp2();
00075     cmap[lhs] = rhs;
00076 }
00077 
00078 
00079 void EquateMap::print(std::ostream& os) {
00080     iterator ee;
00081     for (ee = emap.begin(); ee != emap.end(); ee++) {
00082         os << "  " << ee->first << " = " << ee->second.prints();
00083     }
00084     os << "\n";
00085 }
00086 
00087 char* EquateMap::prints() {
00088     std::ostringstream ost;
00089     print(ost);
00090     strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
00091     debug_buffer[DEBUG_BUFSIZE-1] = '\0';
00092     return debug_buffer;
00093 }
00094 
00095 // Substitute the given constraints into this map
00096 void ConstraintMap::substitute(ConstraintMap& other) {
00097     std::map<Exp*, Exp*, lessExpStar>::iterator oo, cc;
00098     for (oo = other.cmap.begin(); oo != other.cmap.end(); oo++) {
00099         bool ch;
00100         for (cc = cmap.begin(); cc != cmap.end(); cc++) {
00101             Exp* newVal = cc->second->searchReplaceAll(oo->first, oo->second, ch);
00102             if (ch) {
00103                 if (*cc->first == *newVal)
00104                     // e.g. was <char*> = <alpha6> now <char*> = <char*>
00105                     cmap.erase(cc);
00106                 else
00107                     cmap[cc->first] = newVal;
00108             } else
00109                 // The existing value
00110                 newVal = cc->second;
00111             Exp* newKey = cc->first-> searchReplaceAll(oo->first, oo->second, ch);
00112             if (ch) {
00113                 cmap.erase(cc->first);
00114                 // Often end up with <char*> = <char*>
00115                 if (!(*newKey == *newVal))
00116                     cmap[newKey] = newVal;
00117             }
00118         }
00119     }
00120 }
00121 
00122 void ConstraintMap::substAlpha() {
00123     ConstraintMap alphaDefs;
00124     std::map<Exp*, Exp*, lessExpStar>::iterator cc;
00125     for (cc = cmap.begin(); cc != cmap.end(); cc++) {
00126         // Looking for entries with two TypeVals, where exactly one is an alpha
00127         if (!cc->first->isTypeVal() || !cc->second->isTypeVal())
00128             continue;
00129         Type *t1, *t2;
00130         t1 = ((TypeVal*)cc->first )->getType();
00131         t2 = ((TypeVal*)cc->second)->getType();
00132         int numAlpha = 0;
00133         if (t1->isPointerToAlpha()) numAlpha++;
00134         if (t2->isPointerToAlpha()) numAlpha++;
00135         if (numAlpha != 1)
00136             continue;
00137         // This is such an equality. Copy it to alphaDefs
00138         if (t1->isPointerToAlpha())
00139             alphaDefs.cmap[cc->first] = cc->second;
00140         else
00141             alphaDefs.cmap[cc->second] = cc->first;
00142     }
00143 
00144     // Remove these from the solution
00145     for (cc = alphaDefs.begin(); cc != alphaDefs.end(); cc++)
00146         cmap.erase(cc->first);
00147 
00148     // Now substitute into the remainder
00149     substitute(alphaDefs);
00150 }
00151 
00152 
00153 
00154 Constraints::~Constraints() {
00155     LocationSet::iterator cc;
00156     for (cc = conSet.begin(); cc != conSet.end(); cc++) {
00157         delete *cc;
00158     }
00159 }
00160 
00161 
00162 void Constraints::substIntoDisjuncts(ConstraintMap& in) {
00163     ConstraintMap::iterator kk;
00164     for (kk = in.begin(); kk != in.end(); kk++) {
00165         Exp* from = kk->first;
00166         Exp* to = kk->second;
00167         bool ch;
00168         std::list<Exp*>::iterator dd;
00169         for (dd = disjunctions.begin(); dd != disjunctions.end(); dd++) {
00170             (*dd)->searchReplaceAll(from, to, ch);
00171             *dd = (*dd)->simplifyConstraint();
00172         }
00173     }
00174     // Now do alpha substitution
00175     alphaSubst();
00176 }
00177 
00178 void Constraints::substIntoEquates(ConstraintMap& in) {
00179     // Substitute the fixed types into the equates. This may generate more
00180     // fixed types
00181     ConstraintMap extra;
00182     ConstraintMap cur = in;
00183     while (cur.size()) {
00184         extra.clear();
00185         ConstraintMap::iterator kk;
00186         for (kk = cur.begin(); kk != cur.end(); kk++) {
00187             Exp* lhs = kk->first;
00188             std::map<Exp*, LocationSet, lessExpStar>::iterator it = equates.find(lhs);
00189             if (it != equates.end()) {
00190                 // Possibly new constraints that
00191                 // typeof(elements in it->second) == val
00192                 Exp* val = kk->second;
00193                 LocationSet& ls = it->second;
00194                 LocationSet::iterator ll;
00195                 for (ll = ls.begin(); ll != ls.end(); ll++) {
00196                     ConstraintMap::iterator ff;
00197                     ff = fixed.find(*ll);
00198                     if (ff != fixed.end()) {
00199                         if (!unify(val, ff->second, extra)) {
00200                             if (VERBOSE || DEBUG_TA)
00201                                 LOG << "Constraint failure: " << *ll << " constrained to be " <<
00202                                     ((TypeVal*)val)->getType()->getCtype() << " and " <<
00203                                     ((TypeVal*)ff->second)->getType()->getCtype() << "\n";
00204                             return;
00205                         }
00206                     } else
00207                         extra[*ll] = val;   // A new constant constraint
00208                 }
00209                 if (((TypeVal*)val)->getType()->isComplete()) {
00210                     // We have a complete type equal to one or more variables
00211                     // Remove the equate, and generate more fixed
00212                     // e.g. Ta = Tb,Tc and Ta = K => Tb=K, Tc=K
00213                     for (ll = ls.begin(); ll != ls.end(); ll++) {
00214                         Exp* newFixed = new Binary(opEquals,
00215                             *ll,        // e.g. Tb
00216                             val);       // e.g. K
00217                             extra.insert(newFixed);
00218                     }
00219                     equates.erase(it);
00220                 }
00221             }
00222         }
00223         fixed.makeUnion(extra);
00224         cur = extra;    // Take care of any "ripple effect"
00225     }                   // Repeat until no ripples
00226 }
00227 
00228 // Get the next disjunct from this disjunction
00229 // Assumes that the remainder is of the for a or (b or c), or (a or b) or c
00230 // But NOT (a or b) or (c or d)
00231 // Could also be just a (a conjunction, or a single constraint)
00232 // Note: remainder is changed by this function
00233 Exp* nextDisjunct(Exp*& remainder) {
00234     if (remainder == NULL) return NULL;
00235     if (remainder->isDisjunction()) {
00236         Exp* d1 = ((Binary*)remainder)->getSubExp1();
00237         Exp* d2 = ((Binary*)remainder)->getSubExp2();
00238         if (d1->isDisjunction()) {
00239             remainder = d1;
00240             return d2;
00241         }
00242         remainder = d2;
00243         return d1;
00244     }
00245     // Else, we have one disjunct. Return it
00246     Exp* ret = remainder;
00247     remainder = NULL;
00248     return ret;
00249 }
00250 
00251 Exp* nextConjunct(Exp*& remainder) {
00252     if (remainder == NULL) return NULL;
00253     if (remainder->isConjunction()) {
00254         Exp* c1 = ((Binary*)remainder)->getSubExp1();
00255         Exp* c2 = ((Binary*)remainder)->getSubExp2();
00256         if (c1->isConjunction()) {
00257             remainder = c1;
00258             return c2;
00259         }
00260         remainder = c2;
00261         return c1;
00262     }
00263     // Else, we have one conjunct. Return it
00264     Exp* ret = remainder;
00265     remainder = NULL;
00266     return ret;
00267 }
00268 
00269 bool Constraints::solve(std::list<ConstraintMap>& solns) {
00270 LOG << conSet.size() << " constraints:";
00271 std::ostringstream os; conSet.print(os); LOG << os.str().c_str();
00272     // Replace Ta[loc] = ptr(alpha) with
00273     //         Tloc = alpha
00274     LocationSet::iterator cc;
00275     for (cc = conSet.begin(); cc != conSet.end(); cc++) {
00276         Exp* c = *cc;
00277         if (!c->isEquality()) continue;
00278         Exp* left = ((Binary*)c)->getSubExp1();
00279         if (!left->isTypeOf()) continue;
00280         Exp* leftSub = ((Unary*)left)->getSubExp1();
00281         if (!leftSub->isAddrOf()) continue;
00282         Exp* right = ((Binary*)c)->getSubExp2();
00283         if (!right->isTypeVal()) continue;
00284         Type* t = ((TypeVal*)right)->getType();
00285         if (!t->isPointer()) continue;
00286         // Don't modify a key in a map
00287         Exp* clone = c->clone();
00288         // left is typeof(addressof(something)) -> typeof(something)
00289         left = ((Binary*)clone)->getSubExp1();
00290         leftSub = ((Unary*)left)->getSubExp1();
00291         Exp* something = ((Unary*)leftSub)->getSubExp1();
00292         ((Unary*)left)->setSubExp1ND(something);
00293         ((Unary*)leftSub)->setSubExp1ND(NULL);
00294         delete leftSub;
00295         // right is <alpha*> -> <alpha>
00296         right = ((Binary*)clone)->getSubExp2();
00297         t = ((TypeVal*)right)->getType();
00298         ((TypeVal*)right)->setType(((PointerType*)t)->getPointsTo()->clone());
00299         delete t;
00300         conSet.remove(c);
00301         conSet.insert(clone);
00302         delete c;
00303     }
00304 
00305     // Sort constraints into a few categories. Disjunctions go to a special
00306     // list, always true is just ignored, and constraints of the form
00307     // typeof(x) = y (where y is a type value) go to a map called fixed.
00308     // Constraint terms of the form Tx = Ty go into a map of LocationSets
00309     // called equates for fast lookup
00310     for (cc = conSet.begin(); cc != conSet.end(); cc++) {
00311         Exp* c = *cc;
00312         if (c->isTrue()) continue;
00313         if (c->isFalse()) {
00314             if (VERBOSE || DEBUG_TA)
00315                 LOG << "Constraint failure: always false constraint\n";
00316             return false;
00317         }
00318         if (c->isDisjunction()) {
00319             disjunctions.push_back(c);
00320             continue;
00321         }
00322         // Break up conjunctions into terms
00323         Exp* rem = c, *term;
00324         while ((term = nextConjunct(rem)) != NULL) {
00325             assert(term->isEquality());
00326             Exp* lhs = ((Binary*)term)->getSubExp1();
00327             Exp* rhs = ((Binary*)term)->getSubExp2();
00328             if (rhs->isTypeOf()) {
00329                 // Of the form typeof(x) = typeof(z)
00330                 // Insert into equates 
00331                 equates.addEquate(lhs, rhs);
00332             } else {
00333                 // Of the form typeof(x) = <typeval>
00334                 // Insert into fixed
00335                 assert(rhs->isTypeVal());
00336                 fixed[lhs] = rhs;
00337             }
00338         }
00339     }
00340 
00341     {LOG << "\n" << (unsigned)disjunctions.size() << " disjunctions: "; std::list<Exp*>::iterator dd;
00342      for (dd = disjunctions.begin(); dd != disjunctions.end(); dd++) LOG << *dd << ",\n"; LOG << "\n";}
00343     LOG << fixed.size() << " fixed: " << fixed.prints();
00344     LOG << equates.size() << " equates: " << equates.prints();
00345 
00346     // Substitute the fixed types into the disjunctions
00347     substIntoDisjuncts(fixed);
00348 
00349     // Substitute the fixed types into the equates. This may generate more
00350     // fixed types
00351     substIntoEquates(fixed);
00352 
00353     LOG << "\nAfter substitute fixed into equates:\n";
00354     {LOG << "\n" << (unsigned)disjunctions.size() << " disjunctions: "; std::list<Exp*>::iterator dd;
00355      for (dd = disjunctions.begin(); dd != disjunctions.end(); dd++) LOG << *dd << ",\n"; LOG << "\n";}
00356     LOG << fixed.size() << " fixed: " << fixed.prints();
00357     LOG << equates.size() << " equates: " << equates.prints();
00358     // Substitute again the fixed types into the disjunctions
00359     // (since there may be more fixed types from the above)
00360     substIntoDisjuncts(fixed);
00361 
00362     LOG << "\nAfter second substitute fixed into disjunctions:\n";
00363     {LOG << "\n" << (unsigned)disjunctions.size() << " disjunctions: "; std::list<Exp*>::iterator dd;
00364      for (dd = disjunctions.begin(); dd != disjunctions.end(); dd++) LOG << *dd << ",\n"; LOG << "\n";}
00365     LOG << fixed.size() << " fixed: " << fixed.prints();
00366     LOG << equates.size() << " equates: " << equates.prints();
00367 
00368     ConstraintMap soln;
00369     bool ret = doSolve(disjunctions.begin(), soln, solns);
00370     if (ret) {
00371         // For each solution, we need to find disjunctions of the form
00372         // <alphaN> = <type>      or
00373         // <type>   = <alphaN>
00374         // and substitute these into each part of the solution
00375         std::list<ConstraintMap>::iterator it;
00376         for (it = solns.begin(); it != solns.end(); it++)
00377             it->substAlpha();
00378     }
00379     return ret;
00380 }
00381 
00382 static int level = 0;
00383 // Constraints up to but not including iterator it have been unified.
00384 // The current solution is soln
00385 // The set of all solutions is in solns
00386 bool Constraints::doSolve(std::list<Exp*>::iterator it, ConstraintMap& soln, std::list<ConstraintMap>& solns) {
00387 LOG << "Begin doSolve at level " << ++level << "\n";
00388 LOG << "Soln now: " << soln.prints() << "\n";
00389     if (it == disjunctions.end()) {
00390         // We have gotten to the end with no unification failures
00391         // Copy the current set of constraints as a solution
00392         //if (soln.size() == 0)
00393             // Awkward. There is a trivial solution, but we have no constraints
00394             // So make a constraint of always-true
00395             //soln.insert(new Terminal(opTrue));
00396         // Copy the fixed constraints
00397         soln.makeUnion(fixed);
00398         solns.push_back(soln);
00399 LOG << "Exiting doSolve at level " << level-- << " returning true\n";
00400         return true;
00401     }
00402 
00403     Exp* dj = *it;
00404     // Iterate through each disjunction d of dj
00405     Exp* rem1 = dj;       // Remainder
00406     bool anyUnified = false;
00407     Exp* d;
00408     while ((d = nextDisjunct(rem1)) != NULL) {
00409 LOG << " $$ d is " << d << ", rem1 is " << ((rem1==0)?"NULL":rem1->prints()) << " $$\n";
00410         // Match disjunct d against the fixed types; it could be compatible,
00411         // compatible and generate an additional constraint, or be
00412         // incompatible
00413         ConstraintMap extra;      // Just for this disjunct
00414         Exp* c;
00415         Exp* rem2 = d;
00416         bool unified = true;
00417         while ((c = nextConjunct(rem2)) != NULL) {
00418 LOG << "   $$ c is " << c << ", rem2 is " << ((rem2==0)?"NULL":rem2->prints()) << " $$\n";
00419             if (c->isFalse()) {
00420                 unified = false;
00421                 break;
00422             }
00423             assert(c->isEquality());
00424             Exp* lhs = ((Binary*)c)->getSubExp1();
00425             Exp* rhs = ((Binary*)c)->getSubExp2();
00426             extra.insert(lhs, rhs);
00427             ConstraintMap::iterator kk;
00428             kk = fixed.find(lhs);
00429             if (kk != fixed.end()) {
00430                 unified &= unify(rhs, kk->second, extra);
00431 LOG << "Unified now " << unified << "; extra now " << extra.prints() << "\n";
00432                 if (!unified) break;
00433             }
00434         }
00435         if (unified)
00436             // True if any disjuncts had all the conjuncts satisfied
00437             anyUnified = true;
00438         if (!unified) continue;
00439         // Use this disjunct
00440         // We can't just difference out extra if this fails; it may remove
00441         // elements from soln that should not be removed
00442         // So need a copy of the old set in oldSoln
00443         ConstraintMap oldSoln = soln;
00444         soln.makeUnion(extra);
00445         doSolve(++it, soln, solns);
00446         // Revert to the previous soln (whether doSolve returned true or not)
00447         // If this recursion did any good, it will have gotten to the end and
00448         // added the resultant soln to solns
00449         soln = oldSoln;
00450 LOG << "After doSolve returned: soln back to: " << soln.prints() << "\n";
00451         // Back to the current disjunction
00452         it--;
00453         // Continue for more disjuncts this disjunction
00454     }
00455     // We have run out of disjuncts. Return true if any disjuncts had no
00456     // unification failures
00457 LOG << "Exiting doSolve at level " << level-- << " returning " << anyUnified << "\n";
00458     return anyUnified;
00459 }
00460 
00461 bool Constraints::unify(Exp* x, Exp* y, ConstraintMap& extra) {
00462 LOG << "Unifying " << x << " with " << y << " result ";
00463     assert(x->isTypeVal());
00464     assert(y->isTypeVal());
00465     Type* xtype = ((TypeVal*)x)->getType();
00466     Type* ytype = ((TypeVal*)y)->getType();
00467     if (xtype->isPointer() && ytype->isPointer()) {
00468         Type* xPointsTo = ((PointerType*)xtype)->getPointsTo();
00469         Type* yPointsTo = ((PointerType*)ytype)->getPointsTo();
00470         if (((PointerType*)xtype)->pointsToAlpha() ||
00471             ((PointerType*)ytype)->pointsToAlpha()) {
00472             // A new constraint: xtype must be equal to ytype; at least
00473             // one of these is a variable type
00474             if (((PointerType*)xtype)->pointsToAlpha())
00475                 extra.constrain(xPointsTo, yPointsTo);
00476             else
00477                 extra.constrain(yPointsTo, xPointsTo);
00478 LOG << "true\n";
00479             return true;
00480         }
00481 LOG << (*xPointsTo == *yPointsTo) << "\n";
00482         return *xPointsTo == *yPointsTo;
00483     } else if (xtype->isSize()) {
00484         if (ytype->getSize() == 0) {   // Assume size=0 means unknown
00485 LOG << "true\n";
00486             return true;
00487         } else {
00488 LOG << (xtype->getSize() == ytype->getSize()) << "\n";
00489             return xtype->getSize() == ytype->getSize();
00490         }
00491     } else if (ytype->isSize()) {
00492         if (xtype->getSize() == 0) {   // Assume size=0 means unknown
00493 LOG << "true\n";
00494             return true;
00495         } else {
00496 LOG << (xtype->getSize() == ytype->getSize()) << "\n";
00497             return xtype->getSize() == ytype->getSize();
00498         }
00499     }
00500     // Otherwise, just compare the sizes
00501 LOG << (*xtype == *ytype) << "\n";
00502     return *xtype == *ytype;
00503 }
00504 
00505 void Constraints::alphaSubst() {
00506     std::list<Exp*>::iterator it;
00507     for (it = disjunctions.begin(); it != disjunctions.end(); it++) {
00508         // This should be a conjuction of terms
00509         if (!(*it)->isConjunction())
00510             // A single term will do no good...
00511             continue;
00512         // Look for a term like alphaX* == fixedType*
00513         Exp* temp = (*it)->clone();
00514         Exp* term;
00515         bool found = false;
00516         Exp* trm1 = NULL;
00517         Exp* trm2 = NULL;
00518         Type* t1 = NULL, *t2;
00519         while ((term = nextConjunct(temp)) != NULL) {
00520             if (!term->isEquality())
00521                 continue;
00522             trm1 = ((Binary*)term)->getSubExp1();
00523             if (!trm1->isTypeVal()) continue;
00524             trm2 = ((Binary*)term)->getSubExp2();
00525             if (!trm2->isTypeVal()) continue;
00526             // One of them has to be a pointer to an alpha
00527             t1 = ((TypeVal*)trm1)->getType();
00528             if (t1->isPointerToAlpha()) {
00529                 found = true;
00530                 break;
00531             }
00532             t2 = ((TypeVal*)trm2)->getType();
00533             if (t2->isPointerToAlpha()) {
00534                 found = true;
00535                 break;
00536             }
00537         }
00538         if (!found) continue;
00539         // We have a alpha value; get the value
00540         Exp* val, *alpha;
00541         if (t1->isPointerToAlpha()) {
00542             alpha = trm1;
00543             val = trm2;
00544         } else {
00545             val = trm1;
00546             alpha = trm2;
00547         }
00548         // Now substitute
00549         bool change;
00550         *it = (*it)->searchReplaceAll(alpha, val, change);
00551         *it = (*it)->simplifyConstraint();
00552     }
00553 }
00554 
00555 void Constraints::print(std::ostream& os) {
00556     os << "\n" << std::dec << (int)disjunctions.size() << " disjunctions: ";
00557     std::list<Exp*>::iterator dd;
00558     for (dd = disjunctions.begin(); dd != disjunctions.end(); dd++)
00559         os << *dd << ",\n";
00560     os << "\n";
00561     os << (int)fixed.size() << " fixed: ";
00562     fixed.print(os);
00563     os << (int)equates.size() << " equates: ";
00564     equates.print(os);
00565 }
00566 
00567 char* Constraints::prints() {
00568     std::ostringstream ost;
00569     print(ost);
00570     strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
00571     debug_buffer[DEBUG_BUFSIZE-1] = '\0';
00572     return debug_buffer;
00573 }

Generated on Tue Sep 19 21:18:15 2006 for Boomerang by  doxygen 1.4.6