C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

unification.cc

Go to the documentation of this file.
00001 
00002 #include "unification.h"
00003 #include "linker.h"
00004 #include "memoryblock.h"
00005 #include "memorymodel.h"
00006 #include "location.h"
00007 
00008 static bool debug = false;
00009 
00010 //#define cx_vt
00011 
00012 #ifdef cx_vt
00013 int vt = 0, vt_e = 0; // debug
00014 #endif
00015 
00016 int UnificationBasedPtr::unify_points_to_max = 0;
00017 
00018 void Unify_Pendings::insert(Unify_Pending *p, bool is_new) {
00019 #define delete_and_return { \
00020   if(is_new) delete p; \
00021   return; \
00022 }
00023 
00024   // check for similar p already in _set.
00025   if(!is_new && _set.find(p) != _set.end()) return; // quick check
00026 
00027   if(p->typ() == Unify_Pending::cjoin) {
00028     Unify_ECR *e1 = (Unify_ECR*) p->arg2(),
00029               *e2 = (Unify_ECR*) p->arg3();
00030     if( e1->root() == e2->root() ) delete_and_return;
00031     // peek: if both objects pointing to same object, there is nothing more to
00032     // do in the future.
00033     if( e1->type()->objTyp()==OBJECT &&
00034         e2->type()->objTyp()==OBJECT &&
00035         e1->type()->object()->alpha->tao()->type() ==
00036         e2->type()->object()->alpha->tao()->type() ) {
00037       /*std::set<Unify_ECR*> e2_parents = e2->type()->object()->p.parents();
00038       e1->type()->object()->p.parents().insert(e2_parents.begin(),
00039                                                e2_parents.end());*/
00040       delete_and_return;
00041     }
00042 
00043   } else if(p->typ() == Unify_Pending::join_ECR) {
00044     Unify_ECR *e1 = (Unify_ECR*) p->arg1(),
00045               *e2 = (Unify_ECR*) p->arg2();
00046     if( e1->root() == e2->root() ) delete_and_return;
00047   }
00048 
00049   cleanup();
00050 
00051   std::set<Unify_Pending*> temp_set = _set;
00052   for(Pendings_p s=temp_set.begin(); s!=temp_set.end(); s++)
00053     if((*s)->typ() == p->typ()) {
00054       bool d1 = (*s)->arg1() != p->arg1(),
00055            d2 = (*s)->arg2() != p->arg2(),
00056            d3 = (*s)->arg3() != p->arg3();
00057       switch(p->typ()) {
00058         case Unify_Pending::cjoin:
00059           if(d1) {
00060             Unify_Size *s1 = (Unify_Size*) (*s)->arg1(),
00061                        *s2 = (Unify_Size*) p->arg1();
00062             if(s1->is_top()==s2->is_top() && s1->size()==s2->size())
00063               d1 = false;
00064           }
00065           // cannot just check ECR etc. due to their respective pendings.
00066           if(d2 && ((Unify_ECR*)(*s)->arg2())->root()
00067                    == ((Unify_ECR*)p->arg2())->root())
00068             d2 = false;
00069           if(d3 && ((Unify_ECR*)(*s)->arg3())->root()
00070                    == ((Unify_ECR*)p->arg3())->root())
00071             d3 = false;
00072 
00073           if(!d1 && !d2 && !d3) {
00074             // temporarily add p to this, so that in recursion, would quickly
00075             // skip case where this->insert(p) is called again.
00076             _set.insert(p);
00077             Unify_ECR *es = (Unify_ECR*) (*s)->arg2(),
00078                       *ep = (Unify_ECR*) p->arg2();
00079             if(es != ep) {
00080               std::set<Unify_Pending*> S = ep->pending().set();
00081               for(Pendings_p q=S.begin(); q!=S.end(); q++)
00082                 if(& es->pending()!=this && *q!=p) //prevent infinite recursion
00083                   es->pending().insert(*q,false);
00084             }
00085             es = (Unify_ECR*) (*s)->arg3();
00086             ep = (Unify_ECR*) p->arg3();
00087             if(es != ep) {
00088               std::set<Unify_Pending*> S = ep->pending().set();
00089               for(Pendings_p q=S.begin(); q!=S.end(); q++)
00090                 if(& es->pending()!=this && *q!=p) //prevent infinite recursion
00091                   es->pending().insert(*q,false);
00092             }
00093             _set.erase(p); // erase temporary add.
00094           }
00095           break;
00096 
00097         case Unify_Pending::join_ECR:
00098           if(d1) {
00099             Unify_ECR *es = (Unify_ECR*) (*s)->arg1(),
00100                 *ep = (Unify_ECR*) p->arg1();
00101             if(es->root() == ep->root() &&
00102                es->pending().set() == ep->pending().set())
00103               d1 = false;
00104           }
00105           if(d2) {
00106             Unify_ECR *es = (Unify_ECR*) (*s)->arg2(),
00107                      *ep = (Unify_ECR*) p->arg2();
00108             if(es->root() == ep->root() &&
00109                es->pending().set() == ep->pending().set())
00110               d2 = false;
00111           }
00112           /* do not try to merge in pendings as below, it cause much slowdown.
00113           if(!d1 && !d2) {
00114             // _set.insert(p);
00115             ECR *es = (ECR*) (*s)->arg1(),
00116                 *ep = (ECR*) p->arg1();
00117             if(es != ep) {
00118               std::set<Unify_Pending*> S = ep->pending().set();
00119               for(Pendings_p q=S.begin(); q!=S.end(); q++)
00120                 if(& es->pending()!=this && *q!=p) //prevent infinite recursion
00121                   es->pending().insert(*q);
00122             } 
00123             es = (ECR*) (*s)->arg2();
00124             ep = (ECR*) p->arg2();
00125             if(es != ep) {
00126               std::set<Unify_Pending*> S = ep->pending().set();
00127               for(Pendings_p q=S.begin(); q!=S.end(); q++)
00128                 if(& es->pending()!=this && *q!=p) //prevent infinite recursion
00129                   es->pending().insert(*q);
00130             }
00131             _set.erase(p); // erase temporary add.
00132           } */
00133           break;
00134         case Unify_Pending::join_Lambda:
00135           if(d1 && ((Lambda*)(*s)->arg1()) == (Lambda*)p->arg1())
00136             d1 = false;
00137           if(d2 && ((Lambda*)(*s)->arg2()) == (Lambda*)p->arg2())
00138             d2 = false;
00139           if(!d1 && !d2) {
00140             _set.insert(p); // temporary add
00141             Lambda *ls = (Lambda*) (*s)->arg1(),
00142                    *lp = (Lambda*) p->arg1();
00143             if(ls != lp) {
00144               std::set<Unify_Pending*> S = lp->pending().set();
00145               for(Pendings_p q=S.begin(); q!=S.end(); q++)
00146                 if(& ls->pending()!=this && *q!=p) //prevent infinite recursion
00147                   ls->pending().insert(*q,false);
00148             }
00149             ls = (Lambda*) (*s)->arg2();
00150             lp = (Lambda*) p->arg2();
00151             if(ls != lp) {
00152               std::set<Unify_Pending*> S = lp->pending().set();
00153               for(Pendings_p q=S.begin(); q!=S.end(); q++)
00154                 if(& ls->pending()!=this && *q!=p) //prevent infinite recursion
00155                   ls->pending().insert(*q,false);
00156             }
00157             _set.erase(p); // erase temporary add.
00158           }
00159           break;
00160         case Unify_Pending::collapse:
00161           if(d1 && ((Unify_ECR*)(*s)->arg1())->root()
00162                    == ((Unify_ECR*)p->arg1())->root()) {
00163             d1 = false;
00164             _set.insert(p);
00165             Unify_ECR *es = (Unify_ECR*) (*s)->arg1(),
00166                       *ep = (Unify_ECR*) p->arg1();
00167             if(es != ep) {
00168               std::set<Unify_Pending*> S = ep->pending().set();
00169               for(Pendings_p q=S.begin(); q!=S.end(); q++)
00170                 if(& es->pending()!=this && *q!=p) //prevent infinite recursion
00171                   es->pending().insert(*q,false);
00172             }
00173             _set.erase(p); // erase temporary add.
00174           }
00175           break;
00176         case Unify_Pending::makeunknown:
00177           if(d1) {
00178             Unify_Offset *os = (Unify_Offset*) (*s)->arg1(),
00179                          *op = (Unify_Offset*) p->arg1();
00180             if(os->value()==op->value()) {
00181               d1 = false;
00182               _set.insert(p); // temporary add
00183               std::set<Unify_Pending*> S = op->pending().set();
00184               for(Pendings_p q=S.begin(); q!=S.end(); q++)
00185                 if(& os->pending() != this && *q!=p)//prevent infinite recursion
00186                   os->pending().insert(*q,false);
00187               _set.erase(p); // erase temporary add.
00188             }
00189           }
00190       }
00191       if(!d1 && !d2 && !d3) delete_and_return;
00192     }
00193 
00194   _set.insert(p);
00195   cleaned = false;
00196 } // insert
00197 
00198 
00199 void Unify_Pendings::cleanup() {
00200   if(cleaned) return;
00201   std::set<Unify_Pending*> temp_set = _set;
00202   for(Pendings_p s=temp_set.begin(); s!=temp_set.end(); s++)
00203     switch((*s)->typ()) {
00204       case Unify_Pending::cjoin: {
00205         Unify_ECR *e1 = (Unify_ECR*) (*s)->arg2(),
00206                   *e2 = (Unify_ECR*) (*s)->arg3();
00207         // if both objects pointing to same object, there is nothing more to do
00208         // in the future.
00209         if( e1->type()->objTyp()==OBJECT &&
00210             e2->type()->objTyp()==OBJECT &&
00211             e1->type()->object()->alpha->tao()->type() ==
00212             e2->type()->object()->alpha->tao()->type() ) {
00213           /*std::set<Unify_ECR*> e2_parents = e2->type()->object()->p.parents();
00214           e1->type()->object()->p.parents().insert(e2_parents.begin(),
00215                                                    e2_parents.end());*/
00216           _set.erase(*s);
00217         } else if( e1->root() == e2->root())
00218           _set.erase(*s);
00219         break;
00220       }
00221       case Unify_Pending::join_ECR:
00222         if( ((Unify_ECR*) (*s)->arg1())->root() ==
00223             ((Unify_ECR*) (*s)->arg2())->root())
00224           _set.erase(*s);
00225         break;
00226     }
00227   cleaned = true;
00228 } // cleanup
00229 
00230 
00231 void Unify_Pending::print() const {
00232   switch(_typ) {
00233     case makeunknown:
00234       cout << "make_unknown(" << _arg1 << ")"; break;
00235     case join_ECR:
00236       cout << "join_ECR(" << ((Unify_ECR*)_arg1)->type()->id()
00237            << "," << ((Unify_ECR*)_arg2)->type()->id() << ")";
00238       break;
00239     case join_Lambda:
00240       cout << "join_Lambda(" << ((Lambda*)_arg1)->id() << ","
00241            << ((Lambda*)_arg2)->id() << ")";
00242       break;
00243     case cjoin:
00244       cout << "cjoin(" << ((Unify_Size*)_arg1)->str() << ","
00245            << ((Unify_ECR*)_arg2)->type()->id() << ","
00246            << ((Unify_ECR*)_arg3)->type()->id() << ")";
00247       break;
00248     case collapse:
00249       cout << "collapse(," << ((Unify_ECR*)_arg1)->type()->id() << ")";
00250   }
00251 } // Unify_Pending print
00252 
00253 
00254 
00255 Alpha::Alpha() : _tao(T_bottom->ecr()),
00256                  _offset(new Unify_Offset(Unify_Offset::zero)) {}
00257 
00258 
00259 bool Alpha::leq(Alpha *o, Unify_Size s) const {
00260   return _tao->type()->is_bottom() || _tao->type()->leq(o->_tao->type(),s)
00261                                    && _offset->leq(o->_offset);
00262 } // leq
00263 
00264 void Alpha::print() const {
00265   cout << "(" << _tao->type()->id() << "," << *_offset << ")";
00266 }
00267 
00268 int Lambda::id_count=0;
00269 
00270 Lambda *Lambda::bottom() {
00271   Lambda *_bottom = new Lambda();
00272   return _bottom;
00273 } // bottom
00274 
00275 
00276 void Lambda::settype(int n, int m, Unify_ECR **t, Unify_ECR *r, bool ellipsis) {
00277   assert(_is_bottom);
00278   _is_bottom=false; _n=n; _m=m; _ellipsis=ellipsis; _taos=t; _taoR=r;
00279 } // Lambda::settype
00280 
00281 
00282 void Lambda::addArg(int n) {
00283   if(n <= 0 || _ellipsis) return;
00284   Unify_ECR **new_taos = (Unify_ECR**) malloc((n+_n) * sizeof(Unify_ECR*));
00285   for(int i=0; i<_n; i++) new_taos[i] = _taos[i];
00286   for(int i=_n; i<n+_n; i++) new_taos[i] = T_bottom->ecr();
00287   free(_taos);
00288   _taos = new_taos;
00289   _n += n;
00290 }
00291 
00292 
00293 bool Lambda::equal(Lambda *o) const {
00294   if(is_bottom() && o->is_bottom()) return true;
00295   if(is_bottom() || o->is_bottom()) return false;
00296   if(n()!=o->n() || m()!=o->m()) return false;
00297   for(int i=0; i<n(); i++)
00298     if(tao(i)->type() != o->tao(i)->type()) return false;
00299   if(m())
00300     if(taoR()->type() != o->taoR()->type()) return false;
00301   return true;
00302 } // equal
00303 
00304 void Lambda::print() const {
00305   cout << id();
00306   if(is_bottom()) {
00307     cout << "-L_bot";
00308     return;
00309   }
00310   cout << "-lambda(" << _n << ":";
00311   for(int i=0; i<n(); i++)
00312     cout << tao(i)->type()->id() << ",";
00313   if(_ellipsis) cout << "...";
00314   if(_m) cout <<" + "<< taoR()->type()->id();
00315   cout << ")";
00316 }
00317 
00318 int Unify_Size::sizeOf(typeNode *ty) {
00319   assert(ty);
00320   switch(ty->typ()) {
00321     case Prim: {
00322       basic_type bt = ((primNode*)ty)->basic();
00323       if(bt == basic_type::Void || bt == basic_type::Ellipsis)
00324         return -1;
00325       return bt.size();
00326     }
00327     case Ptr: return sizeof(int*); // TBD ???
00328     case Array: {
00329       arrayNode *a = (arrayNode*) ty;
00330       if(a->dim() && a->dim()->typ()==Const) {
00331         int dim = ((constNode*)a->dim())->value().Integer();
00332         return sizeOf(a->type()) * dim;
00333       }
00334       return sizeof(int*); // conservative? TBD?
00335     }
00336     case Enum: return sizeof(unsigned int); // ???
00337     case Struct:
00338     case Union:
00339     case sueSpec: {
00340       suespecNode *spec = (ty->typ()==sueSpec) ? (suespecNode*) ty
00341                                                : ((sueNode*)ty)->spec();
00342       decl_list fields = spec->fields();
00343       int r = 0;
00344       for(decl_list_p d=fields.begin(); d!=fields.end(); d++) {
00345         int f = sizeOf((*d)->type());
00346         if(ty->typ()==Struct) r += f;
00347         else if(r>f) r=f;
00348       }
00349       return r;
00350     }
00351     case Func: {
00352       long p1 = sizeof(&sizeOf),
00353            p2 = sizeof(&sizeOfAssign);
00354       assert(p1 == p2); // test
00355       return p1;
00356     }
00357     case Tdef: return sizeOf(((tdefNode*)ty)->def());
00358     default: cout << ty->typ() << endl; assert(false);
00359   }
00360 } // sizeOf
00361 
00362 
00363 int Unify_Size::sizeOfAssign(threeAddrNode *t, Linker &linker,
00364                              UnificationBasedPtr *analyzer) {
00365   if(!t || !t->lhs()) return 0;
00366 
00367 #define size_operand(x,value) \
00368   /* could have use operandNode::type(), but that does not seem correct: does
00369    * not handle star(). */ \
00370   if(x->cast()) \
00371     value = Unify_Size::sizeOf(x->cast()); \
00372   else if(x->var()->typ() == Const) { \
00373     assert(!x->addr() && !x->star() && x->fields().empty()); \
00374     typeNode *ty = ((constNode*)x->var())->type(); \
00375     if(! x->index()) \
00376       value = Unify_Size::sizeOf(ty); \
00377     else { /* "some_str"[..] */ \
00378       assert(ty->typ() == Array); \
00379       value = Unify_Size::sizeOf(ty->type()); \
00380     } \
00381   } else { \
00382     /* precedence: star, field, index, addr. */ \
00383     typeNode *ty = ((idNode*)x->var())->decl()->type(); \
00384     int defers = 0; \
00385     if(x->star()) defers++; \
00386     if(! x->fields().empty()) { \
00387       assert(x->fields().back()->decl()); \
00388       ty = x->fields().back()->decl()->type(); \
00389       assert(ty); \
00390       defers=0; \
00391     } \
00392     if(x->index()) defers++; \
00393     if(x->addr()) defers--; \
00394     if(defers<0) value = sizeof(int*); /* ?? */ \
00395     else { \
00396       while(defers-->0) { \
00397         if(ty->typ()==Tdef) ty = ((tdefNode*)ty)->def(); \
00398         ty=ty->type(); \
00399       } \
00400       value = Unify_Size::sizeOf(ty); \
00401     } \
00402   }
00403 
00404   if(t->rhs1()->cast())
00405     return sizeOf(t->rhs1()->cast());
00406   if(t->op() && t->op()->id()==Operator::FUNC_CALL) {
00407     if(t->rhs1()->star()) { // call thru function pointer.
00408       // use lhs to determine value (may not be correct? TBD)
00409       int lhs;
00410       size_operand(t->lhs(), lhs)
00411       return lhs;
00412     } else {
00413       declNode *call = ((idNode*) t->rhs1()->var())->decl();
00414       procNode *proc = linker.lookup_procedure(call);
00415       if(!proc) proc = analyzer->synthetic_proc(call);
00416       if(! proc) {
00417         declNode *callee = ((idNode*)t->rhs1()->var())->decl();
00418         if(callee) {
00419           typeNode *type = callee->type()->follow_tdefs();
00420           if( type->typ() == Ptr ) {
00421             // call thru pointer. use lhs to determine value (correct? TBD)
00422             int lhs;
00423             size_operand(t->lhs(), lhs)
00424             return lhs;
00425           }
00426         }
00427       }
00428       if(! proc) return -1;
00429       return sizeOf( ((funcNode*)proc->decl()->type())->returns() );
00430     }
00431 
00432   } else if(! t->sizeof_type()) { // not function call, not sizeof()
00433     int rhs;
00434     size_operand(t->rhs1(), rhs)
00435     if(t->rhs2()) {
00436       assert(t->op());
00437       if(t->op()->is_comparison())
00438         rhs = sizeof(bool);
00439       else {
00440         assert(t->op()->is_arithmetic());
00441         int rhs2;
00442         size_operand(t->rhs2(), rhs2)
00443         if(rhs2 > rhs) rhs=rhs2; // take max ???
00444       }
00445     }
00446     return rhs;
00447   }
00448 } // sizeOfAssign
00449 
00450 
00451 string Unify_Size::str() const {
00452   if(_is_top) return "_top_";
00453   ostringstream ost;  ost << _size;
00454   return ost.str();
00455 }
00456 
00457 string Unify_Parents::str() const {
00458   if(_is_top) return "_top_";
00459   ostringstream ost;  ost << "{";
00460   for(set<Unify_ECR*>::const_iterator p=_parents.begin(); p!=_parents.end();
00461       p++) {
00462     if(p != _parents.begin()) ost << ",";
00463     ost << (*p)->type()->id();
00464   }
00465   ost << "}";
00466   return ost.str();
00467 } // str
00468 
00469 
00470 Unify_Structure::Unify_Structure(suespecNode *sue, EltMap _m, Unify_Size _s,
00471                                  Unify_Parents _p)
00472   : m(_m), s(_s), p(_p) {
00473   decl_list fields = sue->fields();
00474   assert(! fields.empty());
00475   if(sue->owner() == Struct) {
00476     for(decl_list_p f=fields.begin(); f!=fields.end(); f++) {
00477       declSet ds;  ds.insert(*f);
00478       fo.push_back(ds);
00479       fto.push_back((*f)->type());
00480     }
00481   } else {
00482     declSet ds;
00483     typeNode *type = NULL;
00484     for(decl_list_p d=fields.begin(); d!=fields.end(); d++) {
00485       ds.insert(*d);
00486       if(d==fields.begin())
00487         type = (*d)->type();
00488       else if(! UnificationBasedPtr::compatible_type((*d)->type(), type))
00489         type = NULL;
00490     }
00491     fo.push_back(ds);
00492     fto.push_back(type);
00493   }
00494 } // Unify_Structure
00495 
00496 
00497 Unify_ECR *Unify_Structure::get(declNode *field, Unify_ECR *container) {
00498 #define new_field_ECR(X, type, container) {\
00499     set<Unify_ECR*> ps;  ps.insert(container->root()); \
00500     Unify_Parents p(ps); \
00501     if(type) { \
00502       Unify_Size size(Unify_Size::sizeOf(type)); \
00503       X = (new UnifyType( new Unify_Blank(size,p)))->ecr(); \
00504     } else { \
00505       Unify_Size size; \
00506       X = (new UnifyType( new Unify_Blank(size,p)))->ecr(); \
00507     }}
00508 
00509   for(FieldOrder::iterator f=fo.begin(); f!=fo.end(); f++)
00510     if((*f).find(field) != (*f).end()) {
00511       if(! m[*f])
00512         new_field_ECR(m[*f], field->type(), container)
00513       return m[*f];
00514     }
00515   return NULL;
00516 } // get(decl)
00517 
00518 string Unify_Structure::map_str() {
00519   ostringstream ost;
00520   ost << "map: ";
00521   for(map<declSet,Unify_ECR*>::iterator p=m.begin(); p!=m.end(); p++) {
00522     assert(! p->first.empty());
00523     ost << "\n  <";
00524     if(p->first.size() > 10) {
00525       declNode *first = * p->first.begin();
00526       ost << first->name() << "-" << first->coord() << ",etc...";
00527     } else
00528       for(set<declNode*>::iterator d=p->first.begin(); d!=p->first.end(); d++)
00529         ost << (*d)->name() << ",";
00530     ost << ">|->";
00531     if(p->second) ost << p->second->type()->id();
00532     else ost << "NULL";
00533   }
00534   ost << endl;
00535   return ost.str();
00536 } // map_str
00537 
00538 
00539 string Unify_Structure::all_str() {
00540   ostringstream ost;
00541   ost << "FO: ";
00542   for(FieldOrder::iterator p=fo.begin(); p!=fo.end(); p++) {
00543     assert(! (*p).empty());
00544     ost << "\n  <";
00545     if(p->size() > 10) {
00546       declNode *first = * p->begin();
00547       ost << first->name() << "-" << first->coord() << ",etc...";
00548     } else
00549       for(set<declNode*>::iterator d=p->begin(); d!=p->end(); d++)
00550         ost << (*d)->name() << "-" << *d << "-" << (*d)->coord() << ",";
00551     ost << ">,";
00552   }
00553   ost << endl;
00554   return ost.str() + map_str();
00555 } // all_str
00556 
00557 // ==============================================================
00558 
00559 int Unify_ECR::id_count=0;
00560 set<Unify_ECR*> Unify_ECR::all_ECR;
00561 
00562 Unify_ECR::Unify_ECR(declNode *v, procNode *p)
00563 : _var(v), _proc(p), _parent(0), _root(this), _ndecestors(0), _id(id_count++) {
00564   all_ECR.insert(this);
00565 
00566   Unify_Size size(Unify_Size::sizeOf(v->type()));
00567   if(v->type()->typ() == Array && v->init() && v->init()->typ()==Initializer)
00568     size = Unify_Size( ((initializerNode*)v->init())->exprs().size() *
00569                        Unify_Size::sizeOf(v->type()->type()) );
00570   Unify_Parents par(false); // empty set of parents
00571   _type = new UnifyType( new Unify_Blank(size,par), this );
00572   _type->ecr(this);
00573 }
00574 
00575 Unify_ECR::Unify_ECR(UnifyType *t)
00576 : _var(NULL), _proc(NULL), _parent(0), _root(this), _ndecestors(0),
00577   _id(id_count++), _type(t) {
00578   all_ECR.insert(this);
00579 }
00580 
00581 UnifyType *Unify_ECR::type() { if(_parent) return root()->type(); return _type;}
00582 
00583 void Unify_ECR::type(UnifyType *t) {
00584   assert(t);
00585   if(_parent) { root()->type(t); return; }
00586   _type = t;
00587   assert(!_root || _root==this);
00588   _root = Union(t->ecr());
00589   assert(_root == this);
00590 }
00591 
00592 Unify_ECR * Unify_ECR::root() {
00593   if(! _parent) return this;
00594   if(! _root->_parent) return _root;
00595   return _root = _root->root();
00596 } // root
00597 
00598 Unify_ECR * Unify_ECR::Union(Unify_ECR *other) {
00599   if(!other) return root();
00600   Unify_ECR *r1 = root(),
00601       *r2 = other->root();
00602   if(r1 == r2) return r1;
00603   if( r1->_ndecestors < r2->_ndecestors ) {
00604     // make r1 point to r2
00605     r1->_parent = r1->_root = r2;
00606     r2->_children.insert(r1);
00607     r2->_ndecestors += r1->_ndecestors;
00608     return r2;
00609   } else {
00610     r2->_parent = r2->_root = r1;
00611     r1->_children.insert(r2);
00612     r1->_ndecestors += r2->_ndecestors;
00613     return r1;
00614   }
00615 } // Union
00616 
00617 
00618 decl_list Unify_ECR::all_decls() const {
00619   decl_list ds;
00620   if(_var) ds.push_back(_var);
00621   for(set<Unify_ECR*>::const_iterator c=_children.begin(); c!=_children.end();
00622       c++) {
00623     decl_list more = (*c)->all_decls();
00624     ds.merge(more);
00625   }
00626   return ds;
00627 } // all_decls
00628 
00629 #define huge_pending 1400
00630 
00631 #ifdef cx_vt
00632 bool check_28920 = false;
00633 #define parentsOf(t) \
00634   ((t->objTyp()==OBJECT) ? t->object()->p.parents() : \
00635    (t->objTyp()==SIMPLE) ? t->simple()->p.parents() : \
00636    (t->objTyp()==STRUCTURE) ? t->structure()->p.parents() : \
00637    (t->objTyp()==BLANK) ? t->blank()->p.parents() : set<Unify_ECR*>() );
00638 #endif
00639 
00640 void Unify_ECR::print() {
00641 #ifdef cx_vt
00642 if(check_28920) {
00643   cout << id() << /*" r=" << root()->id() <<*/ "/" << *_type << " ";
00644   set<Unify_ECR*> P = parentsOf(_type);
00645   bool contain_25976 = false;
00646   for(set<Unify_ECR*>::iterator p=P.begin(); p!=P.end(); p++)
00647     if((*p)->type()->id() == vt) { contain_25976 = true; break; }
00648   cout << vt << " " << contain_25976 << endl;
00649   if(_parent) _parent->print();
00650   return;
00651 }
00652 #endif
00653 
00654   cout << /*"Tao-" << */id() << " r=" << root()->id() << "/" << *type();
00655   if(! _pending.empty())
00656     cout << " " << _pending.size() << " pendings";
00657   set<Unify_Pending*> P = _pending.set();
00658   if(!P.empty() && P.size() <= 30) {
00659     cout << " {";
00660     for(Pendings_p p=P.begin(); p!=P.end(); p++) {
00661       if(p!=P.begin()) cout << " ";
00662       if((*p)->is_served()) cout << "s-";
00663       cout << **p;
00664     }
00665     cout << "} ";
00666   }
00667 if(P.size() >= huge_pending) { // debug
00668 for(Pendings_p p=P.begin(); p!=P.end(); p++) {
00669   cout << " {" << **p << "} " << endl;
00670   if((*p)->typ() == Unify_Pending::cjoin)
00671     cout << "   " << * (Unify_ECR*) (*p)->arg3() << endl;
00672 }
00673  cout << "end huge " << P.size() << " pendings\n";
00674 exit(1);
00675 }
00676 }
00677 
00678 // ==============================================================
00679 
00680 int UnifyType::id_count=0;
00681 
00682 Unify_Size UnifyType::size() const {
00683   switch(obj_typ) {
00684     case BOTTOM: return Unify_Size(0);
00685     case SIMPLE: return simple()->s;
00686     case STRUCTURE: return structure()->s;
00687     case OBJECT: return object()->s;
00688     case BLANK: return blank()->s;
00689   }
00690 } // size
00691 
00692 
00693 void UnifyType::print() const {
00694   if(is_bottom()) {
00695     cout << id() << ":T_bot";
00696     goto remaining;
00697   }
00698   cout << id() << ":tao";
00699   switch(obj_typ) {
00700     case SIMPLE: {
00701       Unify_Simple *s = _tao.simple;
00702       cout << "(simple " << * s->alpha << ",";
00703       cout << * s->lambda << "," << s->s.str() <<","<< s->p.str() <<")";
00704       break;
00705     }
00706     case OBJECT: {
00707       Unify_Object *o = _tao.object;
00708       cout << "(object " << *o->alpha << ",";
00709       cout << * o->lambda << "," << o->s.str() <<","<< o->p.str();
00710       cout <<")";
00711       break;
00712     }
00713     case STRUCTURE: {
00714       Unify_Structure *s = _tao.structure;
00715       cout << "(struct {";
00716       for(EltMap::iterator m=s->m.begin(); m!=s->m.end(); m++)
00717         if(m->second) {
00718           cout << "<";
00719           declSet decls = m->first;
00720           for(declSet::iterator d=decls.begin(); d!=decls.end(); d++) {
00721             if(d!=decls.begin()) cout << ",";
00722             cout << (*d)->name();
00723           }
00724           cout << "->" << m->second->type()->id() << ">,";
00725         }
00726       cout << "}," << s->s.str() << "," + s->p.str() << ")";
00727       break;
00728     }
00729     case BLANK: {
00730       Unify_Blank *b = _tao.blank;
00731       cout << "(blank " << b->s.str() << "," + b->p.str() << ")";
00732     }
00733   }
00734 
00735 remaining:
00736   if(block()) cout << " block=" << block();
00737   if(! _procs.empty()) {
00738     cout << " " << _procs.size() << " procs";
00739     cout << "(";
00740     for(set<procNode*>::iterator p=_procs.begin(); p!=_procs.end(); p++)
00741       cout << (*p)->decl()->name() << ",";
00742     cout << ")";
00743   }
00744 } // print
00745 
00746 // ==============================================================
00747 class UnificationBasedPtr::findVarAssign : public Walker {
00748   // find number of times a variable is assigned to. The rhs must be a single
00749   // operand without addr.
00750 public:
00751   map<declNode*,int>  &_assignments;
00752   map<declNode*,bool> &_uses;
00753 
00754   findVarAssign(map<declNode*,int> &assignments, map<declNode*,bool> &uses)
00755   : _assignments(assignments), _uses(uses), Walker(Preorder,Subtree) {}
00756 
00757   void at_threeAddr(threeAddrNode *ta, Order) {
00758     if(ta->rhs1() && ta->rhs1()->var()->typ()==Id)
00759       _uses[((idNode*) ta->rhs1()->var())->decl()] = true;
00760     if(ta->rhs2() && ta->rhs2()->var()->typ()==Id)
00761       _uses[((idNode*) ta->rhs2()->var())->decl()] = true;
00762     for(operand_list_p a=ta->arg_list().begin(); a!=ta->arg_list().end(); a++)
00763       if((*a)->var()->typ() == Id)
00764       _uses[((idNode*)(*a)->var())->decl()] = true;
00765 
00766     if(!ta->lhs() || ta->lhs()->var()->typ() != Id) return;
00767     if(ta->lhs()->star() || ta->lhs()->index() || !ta->lhs()->fields().empty()){
00768       _uses[ ((idNode*)ta->lhs()->var())->decl() ] = true;
00769       return;
00770     }
00771     declNode *lhs = ((idNode*) ta->lhs()->var())->decl();
00772 
00773     bool rhs1_is_func = false;
00774     if(ta->rhs1() && ta->rhs1()->var()->typ()==Id) {
00775       operandNode *rhs1 = ta->rhs1();
00776       if(! rhs1->addr() && !rhs1->star() && !rhs1->index() &&
00777          rhs1->fields().empty() &&
00778          ((idNode*)rhs1->var())->decl()->no_tdef_type()->typ() == Func &&
00779          // explanation of below: see comment mergeOperand() or at_call().
00780          (!rhs1->cast() || rhs1->cast()->follow_tdefs()->typ()==Func))
00781         rhs1_is_func = true;
00782     }
00783 
00784     if(!ta->rhs1() || ta->rhs2() || ta->op() || ta->rhs1()->addr() ||
00785        ta->rhs1()->var()->typ() == Const || rhs1_is_func ||
00786        lhs->decl_location() != declNode::BLOCK ||
00787        lhs->storage_class() != declNode::NONE)
00788       _assignments[ lhs ] = 2; // not what we want.
00789     else
00790       _assignments[ lhs ] ++;
00791   }
00792   void at_operand(operandNode *opr, Order) {
00793     if(opr->var()->typ() != Id) return;
00794     if(opr->addr() && !opr->index() && !opr->star() && opr->fields().empty())
00795       _assignments[ ((idNode*)opr->var())->decl() ] = 2; // not what we want.
00796   }
00797   void at_conditiongoto(conditiongotoNode *c, Order) {
00798     if(c->left() && c->left()->typ()==Id)
00799       _uses[((idNode*) c->left())->decl()] = true;
00800     if(c->right() && c->right()->typ()==Id)
00801       _uses[((idNode*) c->right())->decl()] = true;
00802   }
00803 };
00804 
00805 // ==============================================================
00806 
00807 
00808 void UnificationBasedPtr::at_suespec(suespecNode *sue, Order ord) {
00809   if(ord==Postorder /*|| sue->owner() == Enum*/) return; // ignore
00810   if(_visited_sue.find(sue) != _visited_sue.end()) return;
00811   _visited_sue.insert(sue);
00812 
00813   // There could be multiple suespecNode for same struct/union definition (e.g.
00814   // when defined in a .h file included by multiple .c files). We want only
00815   // unique suespecNode, and their fields. Hence the hack:
00816   for(set<suespecNode*>::iterator s=_unique_sue.begin(); s!=_unique_sue.end();
00817       s++)
00818     if((*s)->owner() == sue->owner() &&
00819        (*s)->coord().to_string() == sue->coord().to_string() &&
00820        (*s)->fields().size() == sue->fields().size()) {
00821       // found a duplicate. But the field list could be different due to (eg.)
00822       // different #ifdef values. Go through list to check.
00823       decl_list fields1 = (*s)->fields(),
00824                 fields2 = sue->fields();
00825       bool all_same = true;
00826       for(decl_list_p f1=fields1.begin(), f2=fields2.begin();
00827           all_same && f1!=fields1.end(); f1++, f2++)
00828         // must check both name and coord.
00829         if((*f1)->name()!=(*f2)->name() ||
00830           (*f1)->coord().to_string()!=(*f2)->coord().to_string())
00831           all_same = false;
00832       if(all_same) {
00833         for(decl_list_p f1=fields1.begin(), f2=fields2.begin();
00834             f1!=fields1.end(); f1++, f2++) {
00835           assert((*f1)->name() == (*f2)->name() &&
00836                  (*f1)->coord().to_string() == (*f2)->coord().to_string());
00837           _unique_field_defn[*f2] = *f1;
00838         }
00839         return;
00840       }
00841     }
00842   _unique_sue.insert(sue);
00843 
00844   bool is_struct = (sue->owner() == Struct);
00845   decl_list pos;
00846   for(decl_list_p d=sue->fields().begin(); d!=sue->fields().end(); d++) {
00847     _unique_field_defn[*d] = *d;
00848     _field2sue[*d] = sue;
00849     if(! is_struct) pos.clear();
00850     pos.push_back(*d);
00851     _fieldpos[*d] = pos;
00852   }
00853 } // at_suespec
00854 
00855 
00856 void UnificationBasedPtr::at_proc(procNode *p, Order ord) {
00857   if(ord==Postorder) { cur_proc = NULL;  return; }
00858   _analyzed_proc.insert(p);
00859 
00860   findVarAssign fva(_assignments, _uses);
00861   p->walk(fva);
00862   _assignments[ p->return_decl() ] = 2; // exclude return var.
00863   _uses[ p->return_decl() ] = true;
00864 
00865   declNode *decl = p->decl();
00866 
00867   // p could be a forward declaration.
00868   procNode *actual_p = linker.lookup_procedure(decl);
00869   if(actual_p && p != actual_p)
00870     return; // if proceed will create ecr for wrong return_decl.
00871 
00872   cur_proc = p;
00873   if(_ecr[decl]) return; // already done
00874 
00875 //cout << "at_proc " << p->decl()->name() << " @" << p->coord() << endl;
00876   Unify_ECR *tao0 = _ecr[decl] = new Unify_ECR(decl, cur_proc);
00877   Unify_Size s(Unify_Size::sizeOf(decl->type()));
00878 
00879   funcNode *func = (funcNode*) decl->type();
00880   bool returns = ! func->returns()->is_void();
00881   decl_list formals = func->args();
00882   int n=formals.size(), m=returns?1:0;
00883   bool contain_ellipsis = false;
00884   // if no arg, in formals there is still a decl with type=void.
00885   if(n==1 && formals.front()->type()->is_void()) n=0;
00886   else if(n>0 && (formals.back()->type()->is_ellipsis() ||
00887                   is_va_list(formals.back()))) {
00888     contain_ellipsis = true;
00889   }
00890 
00891   ensure_sim_obj(tao0, s);
00892 
00893   // note: _proctype[p] must point to the new type after ensure_sim_obj().
00894   // But in order for createProcBlock() to work correctly, since _proctype[p]'s
00895   // ecr_no_root() is the new root of tao0, we must have _ecr[decl] point to
00896   // this new root, so that during Memory.lookup_variable(), we can use
00897   // _proctype[p] instead of old _ecr[decl]'s type(). Also must make sure the
00898   // type's ecr is the root.
00899   _proctype[p] = tao0->type();
00900   _ecr[decl] = tao0->root();
00901   tao0->type()->ecr( tao0->root() );
00902 
00903   UnifyType *taoT = tao0->type();
00904   is_Sim_Obj(taoT);
00905   Unify_Size s0 = Sim_Obj_Size(taoT);
00906   Lambda *lambda0 = Sim_Obj_Lambda(taoT);
00907   taoT->procs().insert(p);
00908 
00909   if(! s.leq(s0)) expand(tao0);
00910 
00911   if(lambda0->is_bottom()) {
00912     Unify_ECR **ecrs = (Unify_ECR**) malloc(n * sizeof(Unify_ECR*));
00913     for(int i=0; i<n; i++)
00914       ecrs[i] = T_bottom->ecr();
00915     settype(lambda0,n,m,ecrs, returns ? T_bottom->ecr() : NULL,
00916             contain_ellipsis);
00917   } else
00918     assert(lambda0->ellipsis() == contain_ellipsis);
00919 
00920   decl_list_p f=formals.begin();
00921   Unify_ECR *last = NULL;
00922   Unify_Size last_size;
00923   for(int i=0; i<n; i++, f++) {
00924     _uses[*f] = true; // mark it as used.
00925     assert(! _ecr[*f]); // ??
00926     if(i==n-1 && contain_ellipsis) {
00927       assert((*f)->type()->is_ellipsis() || is_va_list(*f));
00928       if(last) {
00929         assert(last->type()->objTyp()==BLANK);
00930         Unify_Blank *b = last->type()->blank();
00931         _ecr[*f] = (new UnifyType(new Unify_Blank(b->s,b->p)))->ecr();
00932       } else {
00933         _ecr[*f] = (new UnifyType(
00934                      new Unify_Blank(Unify_Size(),Unify_Parents(true))))->ecr();
00935       }
00936       _ecr[*f]->var(*f);
00937       _ecr[*f]->proc(cur_proc);
00938     } else {
00939       last_size = Unify_Size(Unify_Size::sizeOf((*f)->type()));
00940       _ecr[*f] = last = new Unify_ECR(*f, cur_proc);
00941     }
00942     cjoin(last_size, lambda0->tao(i), _ecr[*f]);
00943   }
00944 
00945   if(returns) {
00946     declNode *ret = cur_proc->return_decl();
00947     assert(ret);
00948     typeNode *ret_type = ret->no_tdef_type();
00949     Unify_Size ret_size = Unify_Size(Unify_Size::sizeOf(ret_type));
00950     assert(! _ecr[ret]); // ??
00951     Unify_ECR *ret_tao = _ecr[ret] = new Unify_ECR(ret, cur_proc);
00952     if(ret_type->typ() != Prim || annotation_returns_object(cur_proc))
00953       // new: ensure pointer
00954       ensure_sim_obj(ret_tao, ret_size);
00955     cjoin(ret_size, ret_tao, lambda0->taoR());
00956   }
00957 } // at_proc
00958 
00959 #define is_dismantler_tmp(name) ((name).find("__T") == 0)
00960 
00961 
00962 void UnificationBasedPtr::at_decl(declNode *decl, Order ord) {
00963   if(ord==Preorder || inside_call_func)
00964     return;
00965   // also want to skip formals defined in typedef,extern,etc. how: for valid
00966   // decl, it's _ecr must already be created by at_proc. So, always skip.
00967   declNode::Decl_location loc = decl->decl_location();
00968   if(loc == declNode::FORMAL) return;
00969 
00970   // _ecr[decl] already created for proc's formals args and return_decl().
00971   // (see at_proc())
00972   if(_ecr.find(decl) != _ecr.end()) return;
00973 
00974   if(loc == declNode::ENUM) {
00975     _uses[decl] = true;
00976     assert(_unique_field_defn[decl]);
00977     if(decl != _unique_field_defn[decl]) {
00978       declNode *unique = _unique_field_defn[decl];
00979       at_decl(unique, Postorder);
00980       assert(_ecr[unique]);
00981       _ecr[decl] = _ecr[unique];
00982       return;
00983     }
00984   }
00985 
00986   bool is_synthetic;
00987   declNode *real = linker.lookup_symbol(cur_unit, decl->name(),is_synthetic);
00988 
00989   // deal with func declaration without definition.
00990   if(real && real!=decl && decl->type()->typ() == real->type()->typ() &&
00991      (loc == real->decl_location() || real->decl_location()==declNode::PROC) ||
00992      // note: need above because possible that real!=decl yet not EXTERN (below)
00993      decl->storage_class() == declNode::EXTERN ||
00994      decl->type()->typ()==Func && (!cur_proc || loc==declNode::BLOCK)) {
00995     // process the actual definition now, if not already.
00996     if(real && real!=decl && decl->type()->typ() == real->type()->typ() &&
00997        (loc == real->decl_location() || real->decl_location()==declNode::PROC)){
00998       at_decl(real, Postorder);
00999       if(_ecr.find(real) != _ecr.end()) {
01000         _ecr[decl] = _ecr[real];
01001       }
01002       return;
01003     } else if(decl->type()->typ() == Func) {
01004       // create synthetic procNode for it.
01005       procNode *new_proc = create_synthetic_proc(decl);
01006       procNode *old_cur_proc = cur_proc;
01007       at_proc(new_proc, Preorder);
01008       cur_proc = old_cur_proc;
01009       return;
01010     }
01011   }
01012 
01013   if(loc == declNode::TOP) _uses[decl] = true;
01014 
01015   if ((loc == declNode::BLOCK /*|| loc == declNode::FORMAL*/ ||
01016        loc == declNode::ENUM ||
01017        loc == declNode::TOP /*|| loc == declNode::PROC*/) &&
01018       decl->storage_class() != declNode::TYPEDEF /*&&
01019       !(is_va_list(decl) || decl->type()->typ() == Prim &&
01020         (((primNode*)decl->type())->is_void() ||
01021          ((primNode*)decl->type())->is_ellipsis()))*/) {
01022     // note: proc decl are handled in at_proc().
01023     if( _assignments[decl] != 1 && _uses[decl] ) {
01024 /*cout << "decl " << decl->name() << "@" << decl->coord() << " loc="
01025      << decl->decl_location() << " sc=" << decl->storage_class()
01026      << " type=" << decl->type()->typ() << endl;*/
01027 assert(decl->name() != "");
01028       _ecr[decl] = new Unify_ECR(decl,cur_proc);
01029 //cout << "at_decl " << decl <<" "<< decl->name() <<" @"<< decl->coord() <<endl;
01030       if(is_dismantler_tmp(decl->name())) _dismantler_tmp++;
01031 
01032       if(decl->no_tdef_type()->typ() == Array &&
01033          decl->decl_location() != declNode::SU) {
01034         // inspired by memoryModel::generate_su_field()
01035         Unify_Size s(Unify_Size::sizeOf(decl->type()));
01036         ensure_sim_obj(_ecr[decl], s);
01037       }
01038 
01039       if(loc==declNode::BLOCK && is_va_list(decl)) {
01040         // make decl points to the va_list formal parameter of cur proc.
01041         assert(cur_proc);
01042         decl_list formals = ((funcNode*)cur_proc->decl()->type())->args();
01043         assert(formals.size()>=1);
01044         declNode *last_arg = formals.back();
01045         assert(last_arg->type()->is_ellipsis() || is_va_list(last_arg));
01046         assert(_ecr[last_arg]);
01047 
01048         Unify_Size s(Unify_Size::sizeOf(decl->type()));
01049         ensure_sim_obj(_ecr[decl], s);
01050         join(Sim_Obj_Alpha(_ecr[decl]->type())->tao(), _ecr[last_arg]);
01051       }
01052 
01053       if(decl->init() && decl->init()->typ() == Initializer)
01054         at_initializer((initializerNode*) decl->init(),
01055                        decl->no_tdef_type(),
01056                        _ecr[decl]);
01057 
01058       else if(decl->no_tdef_type()->typ() == Array) {
01059 #define ensure_parent_child(child, parent, child_type) { \
01060   switch(child->type()->objTyp()) { \
01061     case BOTTOM: { \
01062       Unify_Size child_size(Unify_Size::sizeOf(child_type)); \
01063       settype(child, new UnifyType(new Unify_Blank(child_size, \
01064                                                    Unify_Parents(false))));\
01065       /* fall through */ \
01066     } \
01067     case BLANK: child->type()->blank()->p.parents().insert(parent); break; \
01068     case SIMPLE: child->type()->simple()->p.parents().insert(parent); break; \
01069     case STRUCTURE: child->type()->structure()->p.parents().insert(parent); \
01070                     break; \
01071     case OBJECT: child->type()->object()->p.parents().insert(parent); \
01072   } }
01073 
01074         typeNode *curtype = decl->no_tdef_type();
01075         Unify_ECR *tao = _ecr[decl];
01076         while (curtype && (curtype->typ() == Array)) {
01077           exprNode *size = ((arrayNode*)curtype)->dim();
01078           curtype = curtype->no_tdef_type();
01079           Unify_Size array_size;
01080           if(size && size->typ()==Const)
01081             array_size = Unify_Size(((constNode*)size)->value().Integer()
01082                                     * Unify_Size::sizeOf(curtype));
01083           ensure_sim_obj(tao, array_size);
01084           Unify_ECR *child_tao = Sim_Obj_Alpha(tao->type())->tao();
01085           ensure_parent_child(child_tao, tao, curtype)
01086 
01087           if(curtype && curtype->typ() == Array)
01088             tao = child_tao;
01089         }
01090       }
01091 
01092       if(loc == declNode::TOP) annotation_init_global(decl);
01093 #ifdef cx_vt
01094 if(decl->name() == "switches") {
01095 cout << "at_decl " << decl->name() << " " << *_ecr[decl] << endl;
01096 debug = true;
01097 vt = _ecr[decl]->type()->id();
01098 vt_e = Sim_Obj_Alpha(_ecr[decl]->type())->tao()->type()->id();
01099 }
01100 #endif
01101     }
01102   }
01103 } // at_decl
01104 
01105 
01106 void UnificationBasedPtr::at_threeAddr(threeAddrNode *ta, Order ord) {
01107   if(ord==Postorder) {
01108     inside_call_func = false;
01109     return;
01110   }
01111 
01112 /*if(! ta->coord().is_unknown()) {
01113 string c = ta->coord().to_string();
01114 int line = ta->coord().line();
01115 if(c.find("vpath.c") < c.length())
01116   debug = (line>=500 && line<=918);
01117 else debug=false;
01118 } */
01119 
01120 //if(debug) {
01121 //cout << "at_threeAddr @" << ta->coord();
01122 //cout << "  "; output_context oc(cout); ta->output(oc,NULL); cout << endl;
01123 //}
01124 
01125   if(ta->op() && ta->op()->id() == Operator::FUNC_CALL) {
01126     Unify_Size s = Unify_Size(Unify_Size::sizeOfAssign(ta, linker, this));
01127     operandNode *call = ta->rhs1();
01128     assert(call->var()->typ() == Id);
01129     string call_name = ((idNode*)call->var())->name();
01130     if(! call->star() && (call_name=="malloc" || call_name=="calloc"))
01131       at_allocation(ta,s);
01132     else
01133       at_call(ta,s);
01134     inside_call_func = true;
01135 
01136   } else if(! ta->sizeof_type()) { // not function call, not sizeof()
01137     Unify_Size s = Unify_Size(Unify_Size::sizeOfAssign(ta, linker, this));
01138     assert(ta->lhs());
01139     if(ta->rhs1())
01140       mergeOperand(ta->lhs(), ta->rhs1(), s);
01141     if(ta->rhs2()) {
01142       mergeOperand(ta->lhs(), ta->rhs2(), s);
01143       // extra work if two rhs
01144       Unify_ECR *tao = ecr(ta->lhs(), s);
01145       if(tao) {
01146         ensure_sim_obj(tao, s);
01147         UnifyType *t = tao->type();
01148         is_Sim_Obj(t);
01149         Alpha *alpha = Sim_Obj_Alpha(t);
01150         if(alpha->offset()->value() == Unify_Offset::zero)
01151           make_unknown(alpha->offset());
01152       }
01153     }
01154   }
01155 //print_ecr();
01156 } // at_threeAddr
01157 
01158 
01159 
01160 void UnificationBasedPtr::mergeOperand(operandNode *lhs, operandNode *rhs,
01161                                        Unify_Size s) {
01162   bool rhs_is_str = false;
01163   if(rhs->var()->typ() == Const) {
01164     return;
01165     rhs_is_str = ((constNode*)rhs->var())->value().is_str();
01166   }
01167   assert(! lhs->addr());
01168 
01169   Unify_ECR *lhs_ecr = NULL;
01170   if(!lhs->index() && !lhs->star() && lhs->fields().empty()) {
01171     // simple id on the lhs
01172     declNode *lhs_decl = ((idNode*) lhs->var())->decl();
01173     if(! _uses[lhs_decl]) return;
01174     if(_assignments[lhs_decl] == 1) {
01175       assert(lhs_decl->decl_location() == declNode::BLOCK);
01176       assert(_ecr.find(lhs_decl) == _ecr.end());
01177       assert(! rhs->addr());
01178       assert(rhs->var()->typ() == Id || rhs_is_str);
01179       _ecr[lhs_decl] = ecr(rhs, s);
01180       if(_ecr[lhs_decl]) {
01181         if(! _ecr[lhs_decl]->var() ||
01182            is_dismantler_tmp(_ecr[lhs_decl]->var()->name())) {
01183           _ecr[lhs_decl]->var( lhs_decl );
01184           if(! _ecr[lhs_decl]->proc() &&
01185              lhs_decl->decl_location()==declNode::BLOCK)
01186             _ecr[lhs_decl]->proc( cur_proc );
01187         }
01188       } else
01189         _ecr.erase(lhs_decl);
01190       return;
01191     } else
01192       lhs_ecr = ecr(lhs, s);
01193   } else
01194     lhs_ecr = ecr(lhs, s);
01195   assert(lhs_ecr);
01196 
01197   if(rhs->var()->typ() != Id && !rhs_is_str) return; // cannot merge
01198 
01199   bool rhs_is_func = false;
01200   if(! rhs->addr() && !rhs->star() && !rhs->index() && rhs->fields().empty() &&
01201      ((idNode*)rhs->var())->decl()->no_tdef_type()->typ() == Func &&
01202      // if there is a cast to something other than Func, do not treat as
01203      // Func. For example, if callee is f(char *tag) and all it wants to do
01204      // with tag is to, say, store in some record, we want to treat actual
01205      // argument of tag as a normal pointer.
01206      (!rhs->cast() || rhs->cast()->follow_tdefs()->typ()==Func))
01207        rhs_is_func = true;
01208 
01209   if(rhs->addr() || rhs_is_str || rhs_is_func) {
01210     // case "..=&(y..)"
01211     ensure_sim_obj(lhs_ecr, s);
01212     if(rhs_is_func) rhs->addr(true); // temporary
01213     Alpha *rhs_alpha = alpha(rhs, s);
01214     if(rhs_is_func) rhs->addr(false); // set back
01215     Unify_Size s1 = Sim_Obj_Size(lhs_ecr->type());
01216     if(! s.leq(s1)) expand(lhs_ecr);
01217     join(rhs_alpha, Sim_Obj_Alpha(lhs_ecr->type()));
01218 
01219   } else {
01220     // case not "..=&y"
01221     Unify_ECR *rhs_ecr = ecr(rhs, s);
01222     cjoin(s, rhs_ecr, lhs_ecr);
01223   }
01224 } // mergeOperand
01225 
01226 
01227 Unify_ECR *UnificationBasedPtr::ecr(operandNode *opr, Unify_Size s,
01228                                     Unify_Offset **offset) {
01229   if(!opr || opr->var()->typ() != Id) return NULL;
01230   assert(! opr->addr());
01231   declNode *d = ((idNode*)opr->var())->decl();
01232   // if(d->decl_location() == declNode::ENUM) return NULL;
01233 //if(debug) {
01234 //cout << "ecr("; output_context oc(cout); opr->output(oc,NULL); cout << ")\n";
01235 //}
01236   Unify_ECR *E = ecr1(d);
01237   if(!E) return NULL;
01238 
01239   /* recall precedence: star, field, index, addr. */ \
01240 
01241   if(opr->star() && opr->fields().empty()) {
01242     // case when opr has star. Do not compute if has fields because E is
01243     // computed in different way.
01244     if(!opr->index())
01245       ensure_sim_obj(E, s);
01246     else { // dereference twice.
01247       idNode *id = (idNode*) opr->var();
01248       Unify_Size s1(Unify_Size::sizeOf(id->decl()->type()->type()));
01249       ensure_sim_obj(E, s1);
01250     }
01251     is_Sim_Obj(E->type());
01252     Alpha *alpha2 = Sim_Obj_Alpha(E->type());
01253     unless_zero(alpha2->offset(), alpha2->tao());
01254     E = alpha2->tao();
01255     if(offset) *offset = alpha2->offset();
01256   }
01257 //cout << "star done\n";
01258 
01259   if(! opr->fields().empty()) {
01260     indexNode *index = opr->index();
01261     opr->index(NULL); // temporarily
01262     id_list fields = opr->fields();
01263     opr->fields().clear(); // temporarily
01264     typeNode *cast = opr->cast();
01265     opr->cast(NULL); // temporarily
01266 
01267     int base_size;
01268     size_operand(opr, base_size)
01269     Unify_Offset *offset2 = NULL;
01270     Unify_ECR *base = ecr(opr, base_size, &offset2);
01271     if(!offset2) offset2 = new Unify_Offset(Unify_Offset::zero);
01272     opr->fields() = fields; // set back
01273     opr->cast(cast);
01274 //cout << "b4 field, base " << *base << endl;
01275 
01276     for(id_list_p f=fields.begin(); f!=fields.end(); f++) {
01277       /* Size base_Size(base_size);
01278       ensure_sim_obj(base, base_Size);
01279       opr_alpha = Sim_Obj_Alpha(base->type());
01280       ECR *tao2 = opr_alpha->tao(); */
01281       // in paper, compute tao2 from above because it uses "y->n" and base
01282       // is y. Here, we use '.' instead of "->", so tao2 is base.
01283       Unify_ECR *tao2 = base;
01284 //cout << "field " << (*f)->name() << " base " << *base << endl;
01285 //cout << "  tao2 " << *tao2 << endl;
01286       Unify_ECR *next_tao2 = NULL;
01287       Unify_Offset *next_offset2 = NULL;
01288       suespecNode *sue = field2sue((*f)->decl());
01289       assert(sue);
01290       if(offset2->value() == Unify_Offset::unknown) {
01291         collapse(tao2);
01292         next_tao2 = tao2->type()->object()->alpha->tao();//this & below are new
01293         if(! next_tao2)
01294           new_field_ECR( next_tao2, 0, tao2 )
01295         if(next_tao2 == tao2) break; // no point looping
01296         next_offset2 = new Unify_Offset(Unify_Offset::unknown);
01297       } else {
01298         declSet F;  F.insert((*f)->decl());
01299         unless_zero(offset2, tao2);
01300         if(tao2->type()->is_bottom() /* new */ ||
01301            tao2->type()->objTyp() == BLANK) {
01302           ensure_struct_obj(tao2, sue);
01303           /* wrong, cannot do make_compatible() and get() here, because tao2
01304            * now could be OBJECT due to its pendings being "served".
01305           make_compatible(F, st, tao2->root(), true);
01306           //opr_alpha= new Alpha(st->m[(*f)->decl()], new Offset(Offset::zero));
01307           next_tao2 = st->get(unique_field_defn((*f)->decl()), tao2);
01308           assert(next_tao2);
01309           next_offset2 = new Unify_Offset(Unify_Offset::zero); */
01310         } // else
01311         if(tao2->type()->objTyp() == STRUCTURE) {
01312           Unify_Structure *st = tao2->type()->structure();
01313           make_compatible(F, st, tao2, true);
01314           //opr_alpha= new Alpha(st->m[(*f)->decl()], new Offset(Offset::zero));
01315           next_tao2 = st->get(unique_field_defn((*f)->decl()), tao2);
01316           assert(next_tao2);
01317           next_offset2 = new Unify_Offset(Unify_Offset::zero);
01318         } else {
01319           ensure_struct_obj(tao2, sue);
01320           Unify_Size struct_size(Unify_Size::sizeOf(sue));
01321           promote(tao2, struct_size);
01322           // return opr_alpha;
01323           next_tao2 = tao2->type()->object()->alpha->tao();//this/below are new
01324           if(! next_tao2)
01325             new_field_ECR( next_tao2, 0, tao2)
01326           if(next_tao2 == tao2) break; // no point looping
01327           next_offset2 = new Unify_Offset(Unify_Offset::unknown);
01328         }
01329       }
01330       if(next_tao2) {
01331         base = next_tao2; // opr_alpha->tao();
01332         offset2 = next_offset2;
01333       }
01334       base_size = Unify_Size::sizeOf((*f)->decl()->type());
01335     }
01336 
01337     opr->index(index); // set back
01338     E = base; // opr_alpha->tao();
01339   }
01340 
01341   if(opr->index()) {
01342     // same as star?
01343     ensure_sim_obj(E, s);
01344     is_Sim_Obj(E->type());
01345     Alpha *alpha2 = Sim_Obj_Alpha(E->type());
01346     unless_zero(alpha2->offset(), alpha2->tao());
01347     if(offset && (*offset)->value() != Unify_Offset::unknown) {
01348       // note: do not explicitly set alpha2->offset() to be unknown. only
01349       // offset of opr need to be set to unknown if index is non-zero or
01350       // if alpha2->offset() is non-zero.
01351       // TBD: in broadway, when opr is not Const, can use constants (see
01352       // ptr analyzer) to check value.
01353       if(alpha2->offset()->value() == Unify_Offset::unknown ||
01354          opr->index()->typ()!=Const ||
01355          ((constNode*)opr->index())->value().Integer() != 0)
01356         (*offset)->value(Unify_Offset::unknown);
01357     }
01358     E = alpha2->tao();
01359   }
01360 
01361 //if(debug) {
01362 //output_context oc(cout);
01363 //cout << "ecr("; opr->output(oc,NULL); cout << ") is " << *E << endl;
01364 //}
01365   return E;
01366 } // ecr
01367 
01368 
01369 Unify_ECR *UnificationBasedPtr::ecr1(declNode *d) {
01370   Unify_ECR *E = _ecr[d];
01371   if(!E) {
01372     _ecr.erase(d); // clear empty entry.
01373     // this could happen if the var is actually a function or a global.
01374     if(d->type()->typ() == Func) {
01375       procNode *proc = linker.lookup_procedure(d);
01376       assert(proc); // ??
01377       procNode *old_cur_proc = cur_proc; // save
01378       at_proc(proc, Preorder);
01379       cur_proc = old_cur_proc; // set back
01380     } else if(_assignments[d] == 1 || !_uses[d])
01381       return NULL;
01382     else {
01383       assert(d->decl_location() == declNode::TOP ||
01384              d->decl_location() == declNode::ENUM);
01385       at_decl(d, Postorder);
01386     }
01387     E = _ecr[d];
01388     assert(E);
01389   }
01390   return E->root();
01391 } // ecr1
01392 
01393 
01394 Alpha *UnificationBasedPtr::alpha(operandNode *opr, Unify_Size s) {
01395 //cout << "alpha("; output_context oc(cout); opr->output(oc,NULL); cout <<")\n";
01396   if(opr->var()->typ() == Const) {
01397     return NULL;
01398     constNode *con = (constNode*) opr->var();
01399     assert(con->value().is_str());
01400     if(! _string_alpha[con]) {
01401       int len = strlen(con->value().Str());
01402       Unify_ECR *E = (new UnifyType( new Unify_Blank(Unify_Size(len),
01403                                      Unify_Parents(false))))->ecr();
01404       _string_alpha[con] = new Alpha(E, new Unify_Offset(Unify_Offset::zero));
01405     }
01406     return _string_alpha[con];
01407   }
01408 
01409   assert(opr->var()->typ() == Id);
01410   assert(opr->addr());
01411   opr->addr(false); // temporarily
01412 
01413   Unify_Offset * offset = new Unify_Offset(Unify_Offset::zero);
01414   Unify_ECR *E = ecr(opr, s, &offset);
01415   Alpha *alpha = new Alpha(E, offset);
01416 
01417   opr->addr(true); // set back
01418 
01419 //cout << "alpha("; opr->output(oc,NULL); cout << ") is " << *alpha << endl;
01420   return alpha;
01421 } // alpha
01422 
01423 
01424 void UnificationBasedPtr::at_allocation(threeAddrNode *ta, Unify_Size s) {
01425   if(_alloc[ta]) return;  // already handled.
01426   operandNode *lhs = ta->lhs();
01427   assert(lhs && lhs->var()->typ()==Id);
01428   declNode *lhs_decl = ((idNode*)lhs->var())->decl();
01429   Unify_ECR *x = _ecr[lhs_decl];
01430   if(! x) {
01431     // could be due to no uses of it. Force creation.
01432     _uses[lhs_decl] = true;
01433     _assignments[lhs_decl] = 2;
01434     bool i = inside_call_func;
01435     inside_call_func = false; // temporarily
01436     _ecr.erase(lhs_decl);
01437     at_decl(lhs_decl, Postorder);
01438     x = _ecr[lhs_decl];
01439     assert(x);
01440     inside_call_func = i;
01441   }
01442   ensure_sim_obj(x,s);
01443   UnifyType *t = x->type();
01444   is_Sim_Obj(t);
01445   Unify_Size s1 = Sim_Obj_Size(t);
01446   if(! s.leq(s1)) expand(x);
01447   Alpha *alpha1 = Sim_Obj_Alpha(t);
01448   if(alpha1->tao()->type()->is_bottom())
01449     settype(alpha1->tao(),
01450       new UnifyType(new Unify_Blank(Unify_Size(), Unify_Parents(false))));
01451   _alloc[ta] = alpha1->tao();
01452 } // at_allocation
01453 
01454 
01455 void UnificationBasedPtr::at_call(threeAddrNode *ta, Unify_Size s_m) {
01456   operandNode *call = ta->rhs1();
01457   assert(call->var()->typ() == Id);
01458   typeNode *call_expr_type = call->type()->follow_tdefs();
01459   bool is_func_ptr =
01460     call->star() || !call->fields().empty() || call->index() ||
01461     ((idNode*)call->var())->decl()->type()->follow_tdefs()->typ() == Ptr;
01462   declNode *callee = NULL;
01463 
01464   Unify_ECR *tao0;
01465 
01466   if(!is_func_ptr) {
01467     assert(call_expr_type->typ() == Func);
01468     Unify_Size s_c(Unify_Size::sizeOf(call_expr_type));
01469     tao0 = ecr(call, s_c);
01470     callee = ((idNode*)call->var())->decl();
01471     ensure_sim_obj(tao0, s_c);
01472   } else {
01473     Unify_Size s_c(Unify_Size::sizeOf(call_expr_type));
01474     tao0 = ecr(call, s_c);
01475     // need to dereference tao0 again to get the function.
01476     //if(tao0->type()->objTyp()==SIMPLE || tao0->type()->objTyp()==OBJECT)
01477     if(call_expr_type->typ() == Ptr) {
01478       call_expr_type = call_expr_type->type()->follow_tdefs();
01479       ensure_sim_obj(tao0, s_c);
01480       tao0 = Sim_Obj_Alpha(tao0->type())->tao();
01481     }
01482     assert(call_expr_type->typ() == Func);
01483     Unify_Size s_c1(Unify_Size::sizeOf(call_expr_type));
01484     ensure_sim_obj(tao0, s_c1);
01485   }
01486 
01487   UnifyType *taoT = tao0->type();
01488   is_Sim_Obj(taoT);
01489   Unify_Size s0 = Sim_Obj_Size(taoT);
01490   Lambda *lambda0 = Sim_Obj_Lambda(taoT);
01491 
01492   operand_list args = ta->arg_list();
01493   bool returns = ta->lhs();
01494   int n=args.size(), m=returns?1:0;
01495 
01496   bool is_synthetic_callee = false;
01497   procNode *proc = NULL;
01498   if(callee) {
01499     proc = linker.lookup_procedure(callee);
01500     if(!proc) {
01501       proc = _synthetic_proc[callee];
01502       assert(proc);
01503       is_synthetic_callee = true;
01504       // if(_skip_proc.find(proc) != _skip_proc.end()) return;
01505     }
01506   }
01507 
01508   if(!proc && lambda0->is_bottom()) {
01509     /*
01510     static bool func_ptr_error = false;
01511     if(!func_ptr_error) {
01512       cout << "Warning: call by function pointer, cannot resolve callee.\n";
01513       func_ptr_error = true;
01514     }*/
01515     _ptr_call[ta] = taoT;
01516     return;
01517   }
01518   if(!proc) _ptr_call[ta] = taoT; // update
01519 
01520   if(lambda0->is_bottom()) {
01521     assert(proc);
01522     funcNode *func = (funcNode*) proc->decl()->type();
01523     decl_list formals = func->args();
01524     int n=formals.size(), m=func->returns()->is_void()?0:1;
01525     Unify_ECR **ecrs = (Unify_ECR**) malloc(n * sizeof(Unify_ECR*));
01526     for(int i=0; i<n; i++)
01527       ecrs[i] = T_bottom->ecr();
01528     bool contain_ellipsis =
01529       !formals.empty() && 
01530       (is_va_list(formals.back()) || formals.back()->type()->is_ellipsis());
01531     settype(lambda0,n,m,ecrs, returns ? T_bottom->ecr() : NULL,
01532             contain_ellipsis);
01533   }
01534 
01535   if(is_func_ptr) {
01536     // is the target malloc?
01537     set<procNode*> procs = taoT->procs();
01538     for(set<procNode*>::iterator p=procs.begin(); p!=procs.end(); p++)
01539       if((*p)->decl()->name()=="malloc" || (*p)->decl()->name()=="calloc") {
01540         at_allocation(ta, s_m);
01541         break;
01542       }
01543   }
01544 
01545   // when procedure is synthetic...
01546   if(is_synthetic_callee) {
01547     // conservatively merge all operands. ??
01548     if(n>1) {// else what to do ??
01549       //cout << "Warning: unknown definition for procedure " << callee->name()
01550       //     << ", optimistically skipped call site's parameters.\n";
01551       // if(proc) _skip_proc.insert(proc);
01552       // note: we still want to run ecr()/alpha() on the arguments.
01553     }
01554     if(lambda0->n() < n)
01555       // we need more argument.
01556       lambda0->addArg(n - lambda0->n());
01557   }
01558 
01559   if(n == lambda0->n() || n+1>=lambda0->n() && lambda0->ellipsis() ||
01560      taoT->procs().size()>1) ; //okay
01561   else {
01562     cout << "Warning: more argument at callsite at " << ta->coord()
01563          << " than callee";
01564     if(callee) cout << " definition at " << callee->coord();
01565     cout << endl;
01566   }
01567 
01568   int i=0;
01569   for(operand_list_p arg=args.begin(); arg!=args.end(); arg++) {
01570     bool arg_is_str = false,
01571          arg_is_func = false;
01572     if((*arg)->var()->typ() == Const)
01573       ; //arg_is_str = ((constNode*)(*arg)->var())->value().is_str();
01574     else if(! (*arg)->addr()) {
01575       // no & in argument, but still possible it is a function ptr.
01576       typeNode *cast = (*arg)->cast();
01577       (*arg)->cast(NULL); // temporarily
01578       typeNode *arg_type = (*arg)->type()->follow_tdefs();
01579       (*arg)->cast(cast);
01580 /*if(arg_type->typ() == Func && (*arg)->cast() &&
01581    ((*arg)->cast()->follow_tdefs()->typ()!=Ptr ||
01582     (*arg)->cast()->no_tdef_type()->typ()!=Func)) {
01583   cout << ta->coord() << endl;
01584   cout << "here. debug cast.\n";
01585   assert(false);
01586 }*/
01587       if(arg_type->typ() == Func &&
01588          // hack: if there is a cast to something other than ptr to Func, do
01589          // not treat as Func. For example, if callee is f(char *tag) and all
01590          // it wants to do with tag is to, say, store in some record, we want
01591          // to treat actual argument of tag as a normal pointer.
01592          (!(*arg)->cast() ||
01593             (*arg)->cast()->follow_tdefs()->typ()==Ptr &&
01594             (*arg)->cast()->follow_tdefs()->no_tdef_type()->typ()==Func))
01595         arg_is_func = true;
01596     }
01597 
01598     if(i<lambda0->n() && ((*arg)->var()->typ() == Id || arg_is_str)) {
01599       Unify_Size s_i = Unify_Size(Unify_Size::sizeOf((*arg)->type()));
01600       Unify_ECR *lambda_tao = NULL;
01601       lambda_tao = lambda0->tao(i);
01602 
01603       if((*arg)->addr() || arg_is_str || arg_is_func) {
01604         if(arg_is_func) (*arg)->addr(true); // temporary
01605         // case "..=&y"
01606         Alpha *arg_alpha = alpha(*arg, s_i);
01607         if(lambda_tao) {
01608           ensure_sim_obj(lambda_tao, s_i);
01609           Unify_Size s1 = Sim_Obj_Size(lambda_tao->type());
01610           if(! s_i.leq(s1)) expand(lambda_tao);
01611           join(arg_alpha, Sim_Obj_Alpha(lambda_tao->type()));
01612         }
01613         annotation_call_arg(proc, i, (*arg)->type(), arg_alpha);
01614 
01615       } else {
01616         // case not "..=&y"
01617         Unify_ECR *arg_ecr = ecr(*arg, s_i);
01618         if(arg_ecr && lambda_tao) {
01619           cjoin(s_i, arg_ecr, lambda_tao);
01620         }
01621         annotation_call_arg(proc, i, (*arg)->type(), arg_ecr);
01622       }
01623     }
01624     if(arg_is_func) (*arg)->addr(false); // set back
01625 
01626     if(i+1 < lambda0->n()) i++;
01627     else if(! lambda0->ellipsis()) break; // error. don't do further.
01628   }
01629 
01630   if(returns) {
01631     if(lambda0->m()==0) {
01632       cout << "Warning: callsite at " << ta->coord() << " expecting return "
01633            << "value (due to cfg?) when callee has no return value";
01634       if(proc) cout << "(definition at " << proc->coord() << ")";
01635       cout << ".\n";
01636 
01637     } else {
01638       assert(ta->lhs()->var()->typ() == Id);
01639       declNode *ret = ((idNode*)ta->lhs()->var())->decl();
01640       Unify_ECR *ret_tao = NULL;
01641       if(_ecr.find(ret) != _ecr.end())
01642         ret_tao = _ecr[ret];
01643       if(ret->no_tdef_type()->typ() != Prim ||
01644          proc && annotation_returns_object(proc) ||
01645          !lambda0->taoR()->type()->is_bottom() &&
01646          lambda0->taoR()->type()->objTyp()!=BLANK) {
01647         // new: ensure pointer
01648         Unify_Size ret_size =
01649           Unify_Size(Unify_Size::sizeOf(ret->no_tdef_type()));
01650         if(ret_tao)
01651           ensure_sim_obj(ret_tao, ret_size);
01652         annotation_ret_val(proc, lambda0->taoR(), cur_unit);
01653       }
01654       Unify_Size s_m = Unify_Size(Unify_Size::sizeOfAssign(ta, linker, this));
01655       if(ret_tao)
01656         cjoin(s_m, lambda0->taoR(), ret_tao);
01657     }
01658   }
01659 } // at_call
01660 
01661 
01662 void UnificationBasedPtr::at_initializer(initializerNode *init,
01663                                          typeNode *init_type,
01664                                          Unify_ECR *init_ecr) {
01665   // inspired by memoryModel::generate_array_elements_for()
01666   typeNode * curtype = init_type->follow_tdefs();
01667   NodeType typ = curtype->typ();
01668   if(typ!=Struct && typ!=Union && typ!=Array) return; // nothing to do
01669   Unify_ECR *tao = init_ecr;
01670   assert(tao);
01671   expr_list inits;
01672   inits.push_back(init);
01673 //cout << "at_initializer @" << init->coord() << " tao " << *tao << endl;
01674 
01675   while (curtype && (curtype->typ() == Array)) {
01676     // -- Move down in the initializer structure (probably not the most
01677     // efficient algorithm).
01678 
01679     expr_list new_inits;
01680     for (expr_list_p ip = inits.begin(); ip != inits.end(); ++ip) {
01681       exprNode * expr = (*ip);
01682       if (expr->typ() == Initializer) {
01683         initializerNode * initializer = (initializerNode *) expr;
01684         new_inits.insert(new_inits.end(), initializer->exprs().begin(),
01685                          initializer->exprs().end());
01686       }
01687     }
01688 
01689     inits = new_inits;
01690     curtype = curtype->no_tdef_type();
01691     Unify_Size array_size(inits.size() * Unify_Size::sizeOf(curtype));
01692     ensure_sim_obj(tao, array_size);
01693     Unify_ECR *child_tao = Sim_Obj_Alpha(tao->type())->tao();
01694     ensure_parent_child(child_tao, tao, curtype)
01695 
01696     if(curtype && curtype->typ() == Array)
01697       tao = child_tao;
01698   }
01699 
01700   if (curtype && ! inits.empty()) {
01701 
01702     if (curtype->typ() == Struct || curtype->typ() == Union) {
01703       // Initialize a struct, as if "a.f = elt". Here, treat "a" as it has
01704       // offset zero, since it is actually "a[i]" which we know points to a
01705       // valid starting address of a struct. With this, can skip check on
01706       // type(offset2)==unknown below.
01707       Unify_ECR *tao2;
01708       if(curtype == init_type) // the init is struct init, no array.
01709         tao2 = init_ecr;
01710         // ignore unless_zero
01711       else {
01712         Alpha *alpha2 = Sim_Obj_Alpha(tao->type()); // array element a[i]
01713         tao2 = alpha2->tao();
01714         Unify_Offset *offset2 = alpha2->offset();
01715         unless_zero(offset2, tao2);
01716       }
01717 
01718       suespecNode * spec = ((sueNode*)curtype)->spec();
01719       at_suespec(spec, Preorder); // make sure
01720       decl_list & fields = spec->fields();
01721 
01722       // make sure same field of all elements are joined.
01723       map<declNode*,Unify_ECR*> rhs_unique;
01724 
01725       for (expr_list_p ip = inits.begin(); ip != inits.end(); ++ip) {
01726         exprNode * expr = (*ip);
01727         if (expr->typ() != Initializer) continue;
01728         initializerNode * initializer = (initializerNode *) expr;
01729         expr_list & field_inits = initializer->exprs();
01730 
01731         // -- Loop over the fields and the field inits together
01732         decl_list_p fp = fields.begin();
01733         expr_list_p fip = field_inits.begin();
01734         while((fp != fields.end()) && (fip != field_inits.end())) {
01735           declNode * field_decl = (*fp);
01736           exprNode * field_init = (*fip);
01737 
01738           // note: different treatment as in
01739           // memoryModel::generate_array_elements_for(), which assumes the
01740           // expression is a compiler-time static constant. Here we also handle
01741           // ADDRESS operator, useful if the expression is address of a func.
01742           idNode * id = 0;
01743           Unify_ECR *rhs_ecr = NULL;
01744           bool rhs_addr = false;
01745           if (field_init->typ() == Id)
01746             id = (idNode *) field_init;
01747           else if (field_init->typ() == Unary) {
01748             unaryNode * un = (unaryNode *) field_init;
01749             if (un->expr()->typ() == Id) 
01750               id = (idNode *) un->expr();
01751             rhs_addr = (un->op()->id() == Operator::ADDRESS);
01752           } else if(field_init->typ() == Const && 0 &&
01753                     ((constNode*)field_init)->value().is_str()) {
01754             constNode *con = (constNode*) field_init;
01755             if(! _string_alpha[con]) {
01756               int len = strlen(con->value().Str());
01757               Unify_ECR *E = (new UnifyType( new Unify_Blank(Unify_Size(len),
01758                                              Unify_Parents(false))))->ecr();
01759               _string_alpha[con] = new Alpha(E,
01760                                           new Unify_Offset(Unify_Offset::zero));
01761             }
01762             rhs_ecr = _string_alpha[con]->tao();
01763             rhs_addr = true;
01764           }
01765           if(id && id->decl() /*&&
01766              id->decl()->decl_location() != declNode::ENUM*/) {
01767             typeNode *field_type = field_decl->type();
01768             if(field_type->typ() == Struct ||
01769                field_type->typ() == Union ||
01770                field_type->typ() == Enum)
01771               at_suespec(((sueNode*)field_type)->spec(), Preorder);
01772             rhs_ecr = ecr1(id->decl());
01773             if(id->decl()->type()->typ() == Func)
01774               rhs_addr = true; //treat func as addr
01775           }
01776 
01777           if(rhs_ecr) {
01778             declSet F;  F.insert(field_decl);
01779             Unify_Structure *st;
01780             if(tao2->type()->is_bottom() /* new */ ||
01781                tao2->type()->objTyp() == BLANK) {
01782               suespecNode *sue = field2sue(field_decl);
01783               assert(sue);
01784               ensure_struct_obj(tao2, sue);
01785               // make_compatible(F, st, tao2, true);
01786             }
01787             if(tao2->type()->objTyp() == STRUCTURE) {
01788               st = tao2->type()->structure();
01789               make_compatible(F, st, tao2, true);
01790             } else assert(false); // possible?
01791             Unify_ECR *field_ecr = st->get(unique_field_defn(field_decl),
01792                                            tao2);
01793             assert(field_ecr);
01794 
01795             if(! rhs_addr) {
01796               Unify_Size rhs_size(Unify_Size::sizeOf(id->type()));
01797               cjoin(rhs_size, rhs_ecr, field_ecr);
01798               // make sure all init for same field are joined.
01799               if(!rhs_unique[field_decl]) rhs_unique[field_decl] = rhs_ecr;
01800               else join(rhs_unique[field_decl], rhs_ecr);
01801             } else {
01802               Unify_Size size(sizeof(int*)); // ??? address size
01803               ensure_sim_obj(field_ecr, size);
01804               UnifyType *field_t = field_ecr->type();
01805               if(! size.leq(Sim_Obj_Size(field_t)))
01806                 expand(field_ecr);
01807               Alpha *rhs_alpha = new Alpha(rhs_ecr, new Unify_Offset(
01808                                                       Unify_Offset::zero));
01809               join(rhs_alpha, Sim_Obj_Alpha(field_ecr->type()));
01810               delete rhs_alpha;
01811             }
01812 
01813           } else if(tao2->type()->is_bottom() ||
01814                     tao2->type()->objTyp() == BLANK) {
01815             // there are many reasons there is no rhs_ecr.
01816             suespecNode *sue = field2sue(field_decl);
01817             assert(sue);
01818             ensure_struct_obj(tao2, sue);
01819           }
01820 
01821           fp++;
01822           fip++;
01823         }
01824       }
01825 
01826     } else {
01827 //cout << "Array\n";
01828       // Initialize an array, as if "*array = elt";
01829       Alpha *alpha3 = Sim_Obj_Alpha(tao->type()); // array element
01830       Unify_ECR *tao3 = alpha3->tao();
01831       unless_zero(alpha3->offset(), tao3);
01832 
01833       Unify_ECR *rhs_unique=NULL; // make sure all elements are joined.
01834 
01835       for (expr_list_p p = inits.begin(); p != inits.end(); ++p) {
01836         exprNode * the_init = (*p);
01837         idNode * id = 0;
01838         Unify_ECR *rhs_ecr = NULL;
01839         bool rhs_addr = false;
01840 
01841         if (the_init->typ() == Id) id = (idNode *) the_init;
01842         else if (the_init->typ() == Unary) {
01843           unaryNode * un = (unaryNode *) the_init;
01844           if (un->expr()->typ() == Id)
01845             id = (idNode *) un->expr();
01846           rhs_addr = (un->op()->id() == Operator::ADDRESS);
01847         } else if(the_init->typ() == Const && 0 &&
01848                   ((constNode*)the_init)->value().is_str()) {
01849           constNode *con = (constNode*) the_init;
01850           if(! _string_alpha[con]) {
01851             int len = strlen(con->value().Str());
01852             Unify_ECR *E = (new UnifyType( new Unify_Blank(Unify_Size(len),
01853                                            Unify_Parents(false))))->ecr();
01854             _string_alpha[con] = new Alpha(E,
01855                                         new Unify_Offset(Unify_Offset::zero));
01856           }
01857           rhs_ecr = _string_alpha[con]->tao();
01858           rhs_addr = true;
01859         }
01860         if (id && id->decl() /*&&
01861             id->decl()->decl_location() != declNode::ENUM*/) {
01862           rhs_ecr = ecr1(id->decl());
01863           if(id->decl()->type()->typ() == Func)
01864             rhs_addr = true; //treat func as addr
01865         }
01866 
01867         if (rhs_ecr) {
01868           if(! rhs_addr) {
01869             Unify_Size rhs_size(Unify_Size::sizeOf(id->type()));
01870             cjoin(rhs_size, rhs_ecr, tao3);
01871             if(!rhs_unique) rhs_unique = rhs_ecr;
01872             else join(rhs_unique, rhs_ecr);
01873           } else {
01874             Unify_Size size(sizeof(int*)); // ??? address size
01875             ensure_sim_obj(tao3, size);
01876             UnifyType *tao3_t = tao3->type();
01877             if(! size.leq(Sim_Obj_Size(tao3_t)))
01878               expand(tao3);
01879             Alpha *rhs_alpha = new Alpha(rhs_ecr, new Unify_Offset(
01880                                                     Unify_Offset::zero));
01881             join(rhs_alpha, Sim_Obj_Alpha(tao3->type()));
01882             delete rhs_alpha;
01883           }
01884 
01885         } else if(curtype->follow_tdefs()->typ() == Ptr &&
01886                   tao3->type()->is_bottom()) {
01887           // there are many reasons there is no rhs_ecr. ensure tao3 is a
01888           // pointer type.
01889           Unify_Size size(sizeof(int*)); // ??? address size
01890           ensure_sim_obj(tao3, size);
01891           Unify_ECR *child = Sim_Obj_Alpha(tao3->type())->tao();
01892           ensure_parent_child(child, tao3, curtype)
01893         }
01894       } // inits
01895     } // Array
01896   }
01897 } // at_initializer
01898 
01899 
01900 // ==============================================================
01901 
01902 void UnificationBasedPtr::settype(Unify_ECR *e, UnifyType *t) {
01903   if(e->type() == t) return;
01904   if(e->type()->block()) {
01905     UnifyType *old_type = e->type();
01906     assert(! t->block() || old_type->block() == t->block()); // ??
01907     t->block(old_type->block());
01908     old_type->block(NULL);
01909     t->block()->unifyType(t);
01910   }
01911   e->type(t);
01912 
01913   set<Unify_Pending*> pending = e->pending().set();
01914   //e->pending().clear();
01915 bool big = pending.size() > huge_pending;
01916 if(big) cout << "settype " << pending.size() << " pendings\n";
01917 int not_served = 0;
01918   for(Pendings_p a=pending.begin(); a!=pending.end(); a++) {
01919     if((*a)->is_served()) continue;
01920 not_served++;
01921     if(finalizing) (*a)->served();
01922     switch((*a)->typ()) {
01923       case Unify_Pending::join_ECR:
01924 if(big)
01925  cout<< "join_ECR "<< *(Unify_ECR*) (*a)->arg1() <<"+"<< * (Unify_ECR*) (*a)->arg2() <<endl;
01926         join((Unify_ECR*) (*a)->arg1(), (Unify_ECR*) (*a)->arg2());
01927         break;
01928       case Unify_Pending::join_Lambda:
01929 if(big)
01930   cout << "join_Lambda " << *(Lambda*) (*a)->arg1() <<"+"
01931        << *(Lambda*) (*a)->arg2() << endl;
01932         join((Lambda*) (*a)->arg1(), (Lambda*) (*a)->arg2());
01933         break;
01934       case Unify_Pending::cjoin:
01935 if(big)
01936   cout << "cjoin " << ((Unify_Size*)(*a)->arg1())->size() << " "
01937        << *(Unify_ECR*) (*a)->arg2() <<"+"<< *(Unify_ECR*) (*a)->arg3() << endl;
01938         cjoin(* (Unify_Size*) (*a)->arg1(), (Unify_ECR*) (*a)->arg2(),
01939               (Unify_ECR*) (*a)->arg3());
01940         break;
01941       default: cout << (*a)->typ() << endl; assert(false);
01942     }
01943   }
01944 if(big) {
01945   cout << "not_served = " << not_served << endl;
01946   assert(false);
01947 }
01948 } // settype
01949 
01950 
01951 void UnificationBasedPtr::settype(Lambda *l, int n, int m, Unify_ECR **t,
01952                                   Unify_ECR *r, bool ellipsis) {
01953   l->settype(n,m,t,r,ellipsis);
01954   set<Unify_Pending*> pendings = l->pending().set();
01955   //_pending.clear();
01956   for(Pendings_p p=pendings.begin(); p!=pendings.end(); p++) {
01957     switch((*p)->typ()) {
01958       case Unify_Pending::join_Lambda:
01959         join((Lambda*) (*p)->arg1(), (Lambda*) (*p)->arg2());
01960         break;
01961       default: assert(false);
01962     }
01963   }
01964 } // settype(Lambda)
01965 
01966 
01967 void UnificationBasedPtr::join(Alpha *a1, Alpha *a2, bool *recursion_detected) {
01968   if(a1 == a2) return;
01969   if(a1->offset()->value() == Unify_Offset::zero) {
01970     if(new_pending) {
01971       a1->offset()->pending() = a2->offset()->pending();
01972       a1->offset()->pending().insert( new Unify_Pending(a2->offset()),true );
01973     }
01974   } else if(a2->offset()->value() == Unify_Offset::zero)
01975     make_unknown(a2->offset());
01976   join(a1->tao(), a2->tao(), recursion_detected);
01977 } // join
01978 
01979 
01980 void UnificationBasedPtr::join(Unify_ECR *e1, Unify_ECR *e2,
01981                                bool *recursion_detected) {
01982   assert(e1); assert(e2);
01983   if(e1 == e2) return;
01984 
01985   if(e1->root()==e2->root()) {
01986     if(!finalizing) return;
01987     // during finalize, continue even if e1,e2 share same root, because we need
01988     // to make sure their pendings are merged into the root (see below).
01989     // note: can only do this during finalize, else serving pendings without
01990     // marking them as served could lead to infinite loop.
01991   }
01992 
01993   // prevent infinite recursion.
01994   static set<pair<UnifyType*,UnifyType*> > stack;
01995   pair<UnifyType*,UnifyType*> ee(e1->type(),e2->type());
01996   if(stack.find(ee) != stack.end()) {
01997 //cout << "join recursion\n";
01998     if(recursion_detected) *recursion_detected = true;
01999     return; // recursion detected.
02000   }
02001   stack.insert(ee);
02002   if(recursion_detected) *recursion_detected = false;
02003 
02004 static int ID = 0; // debug
02005 int _id = ID++;
02006 /*if(debug) {
02007 cout << _id << " ";
02008 cout << "join " << *e1 << " + " << *e2 << endl;
02009 }*/
02010   bool force_no_pending = false;
02011   if(new_pending && finalizing)
02012     // we have already completed finalize, now in ecrDeref or ecrField.
02013     // we want to create new pending for bottom e1 only if e2 is also pending;
02014     // else do join immediately.
02015     force_no_pending = e1->type()->is_bottom() && e2->type()->is_bottom();
02016 
02017   if(new_pending && e1->type()->is_bottom() && !force_no_pending) {
02018     e1->pending().insert( new Unify_Pending(e1,e2),true );
02019   } else {
02020 set<procNode*> e1_procs = e1->type()->procs(),
02021                e2_procs = e2->type()->procs();
02022     UnifyType *e1_type = e1->type(),
02023               *e2_type = e2->type(),
02024               *new_type = unify(e1_type,e2_type); // have to do this first
02025     if(new_type == NULL) return; // cannot unify
02026     if(e1->type() != e1_type || e2->type() != e2_type) {
02027       // e1 or e2's type has changed during call to unify(). We can no longer
02028       // trust new_type to be the correct final type of their joins.
02029       join(e1, e2);
02030       return;
02031     }
02032 
02033     bool e1_changed = new_type!=e1->type(),
02034          e2_changed = new_type!=e2->type();
02035     e1->root()->pending().cleanup();
02036     if(e1->root() != e2->root()) e2->root()->pending().cleanup();
02037     set<Unify_Pending*> e1_pendings = e1->root()->pending().set(),
02038                         e2_pendings = e2->root()->pending().set();
02039     Unify_ECR *e = e1->Union(e2);
02040     // if(! finalizing) {
02041       set<Unify_Pending*> new_pendings;
02042       if(e==e1)      new_pendings = e2_pendings;
02043       else if(e==e2) new_pendings = e1_pendings;
02044       else {
02045         new_pendings = e1_pendings;
02046         new_pendings.insert(e2_pendings.begin(), e2_pendings.end());
02047       }
02048       for(Pendings_p p=new_pendings.begin(); p!=new_pendings.end(); p++)
02049         e->pending().insert(*p,false);
02050 
02051       if(serve_again) { // new
02052         // we are in finalizing mode, though we may have temporarily set the
02053         // flag off in cjoin().
02054         if(e1_changed)
02055           for(Pendings_p p=e1_pendings.begin(); p!=e1_pendings.end(); p++)
02056             if((*p)->is_served()) {
02057               (*p)->un_served();
02058               more_pending.insert(*p);
02059             }
02060         if(e2_changed)
02061           for(Pendings_p p=e2_pendings.begin(); p!=e2_pendings.end(); p++)
02062             if((*p)->is_served()) {
02063               (*p)->un_served();
02064               more_pending.insert(*p);
02065             }
02066       }
02067     // }
02068     // wrong: e->type(e1->type());
02069     settype(e, new_type);
02070 set<procNode*> e_procs = e->type()->procs();
02071 for(set<procNode*>::iterator p=e1_procs.begin(); p!=e1_procs.end(); p++)
02072   if(e_procs.find(*p) == e_procs.end()) {
02073 cout << _id << " ";
02074     cout << (*p)->decl()->name() << endl;
02075     cout << *e1 << "\n + " << *e2 << "\n -> " << *e << endl;
02076     cout << "new_type " << *new_type << endl;
02077     assert(false);
02078   }
02079 for(set<procNode*>::iterator p=e2_procs.begin(); p!=e2_procs.end(); p++)
02080   if(e_procs.find(*p) == e_procs.end()) {
02081 cout << _id << " ";
02082     cout << (*p)->decl()->name() << endl;
02083     cout << *e1 << "\n + " << *e2 << "\n -> " << *e << endl;
02084     cout << "new_type " << *new_type << endl;
02085     assert(false);
02086   }
02087 /*if(debug) {
02088 cout << _id << " ";
02089 cout << "joined " << *e << endl;
02090 }*/
02091 
02092   }
02093   stack.erase(ee);
02094 } // join
02095 
02096 
02097 void UnificationBasedPtr::join(Lambda *l1, Lambda *l2) {
02098   assert(l1 && l2);
02099   if(l1 == l2) return;
02100 //cout << "join Lambdas " << *l1 << " + " << *l2 << endl;
02101   if(l1->is_bottom() && new_pending) {
02102     l1->pending().insert( new Unify_Pending(l1,l2),true );
02103   } else if(l2->is_bottom() && new_pending) {
02104     l2->pending().insert( new Unify_Pending(l1,l2),true );
02105   } else if(!l1->is_bottom() && !l2->is_bottom()) {
02106     // this join() is called from cjoin() and unify(). What happen there is
02107     // that two types of are cjoin/unify and the two types involves have Lambda
02108     // to be joined. Those two types are either SIMPLE or OBJECT, which means
02109     // they are pointers to some functions (l1 and l2). In C, it is possible
02110     // that function pointers may point to functions of different signatures.
02111     // So l1 and l2 need not have same n() and m().
02112     l2->addArg(l1->n() - l2->n());
02113     l1->addArg(l2->n() - l1->n());
02114     int t = l1->n() < l2->n() ? l1->n() : l2->n();
02115     for(int i=0; i<t; i++) {
02116       Unify_ECR *e1 = l1->tao(i),
02117                 *e2 = l2->tao(i);
02118       if(! e1->type()->is_bottom())
02119         join(e1, e2);
02120       else if(! e2->type()->is_bottom())
02121         join(e2, e1);
02122       else {
02123         join(e1, e2);
02124         // rightfully, join both ways because we don't know which one will
02125         // become non-bottom first, and we want to make sure the pendings will
02126         // lead one to become non-bottom when the other is changed.  Instead of
02127         // call join() which will have no effect, explicitly add pending.
02128         e2->pending().insert( new Unify_Pending(e2,e1),true );
02129       }
02130       l1->tao(i,e1->root());  l2->tao(i,e1->root());
02131     }
02132 
02133     if(l1->m()>0 && l2->m()>0) {
02134       Unify_ECR *e1 = l1->taoR(),
02135                 *e2 = l2->taoR();
02136       if(! e1->type()->is_bottom())
02137         join(e1, e2);
02138       else if(! e2->type()->is_bottom())
02139         join(e2, e1);
02140       else {
02141         join(e1, e2);
02142         e2->pending().insert( new Unify_Pending(e2,e1),true );
02143       }
02144       l1->taoR(e1->root());  l2->taoR(e1->root());
02145     }
02146 
02147     if(finalizing) {
02148       set<Unify_Pending*> pendings = l1->pending().set(),
02149                           more = l2->pending().set();
02150       pendings.insert(more.begin(), more.end());
02151       for(Pendings_p p=pendings.begin(); p!=pendings.end(); p++) {
02152         if((*p)->is_served()) continue;
02153         (*p)->served();
02154         switch((*p)->typ()) {
02155           case Unify_Pending::join_Lambda:
02156             join((Lambda*) (*p)->arg1(), (Lambda*) (*p)->arg2());
02157             break;
02158           default: assert(false);
02159         }
02160       }
02161     }
02162 
02163   } else if(!l1->is_bottom() || !l2->is_bottom()) {
02164     assert(! new_pending);
02165     Lambda *bot, *non_bot;
02166     if( l1->is_bottom() ) { bot = l1; non_bot = l2; }
02167     else { bot = l2; non_bot = l1; }
02168     Unify_ECR **taos = (Unify_ECR**) malloc(non_bot->n() * sizeof(Unify_ECR*));
02169     for(int i=0; i<non_bot->n(); i++) taos[i] = non_bot->tao(i);
02170     settype(bot, non_bot->n(), non_bot->m(), taos,
02171             non_bot->m()>0 ? non_bot->taoR() : NULL, non_bot->ellipsis());
02172   }
02173 //cout << "joined Lambdas " << *l1 << " + " << *l2 << endl;
02174 } // join
02175 
02176 
02177 void UnificationBasedPtr::ensure_sim_obj(Unify_ECR *tao, Unify_Size &s) {
02178   if(tao->type()->is_bottom()) {
02179     Unify_Parents par(false); // empty set of parents
02180     settype(tao, new UnifyType(new Unify_Simple(new Alpha(), L_bottom,
02181                                                 s, par)));
02182     return;
02183   }
02184   switch(tao->type()->objTyp()) {
02185     case BLANK: {
02186       Unify_Blank *b = tao->type()->blank();
02187       settype(tao, new UnifyType(new Unify_Simple(new Alpha(), L_bottom,
02188                                                   b->s, b->p)));
02189       if(! s.leq(b->s)) expand(tao);
02190       break;
02191     }
02192     case SIMPLE: {
02193       Unify_Simple *si = tao->type()->simple();
02194       if(! s.leq(si->s)) expand(tao);
02195       break;
02196     }
02197     case STRUCTURE: {
02198       Unify_Structure *st = tao->type()->structure();
02199       promote(tao, st->s);
02200     }
02201     // case OBJECT:
02202   }
02203 } // ensure_sim_obj
02204 
02205 
02206 void UnificationBasedPtr::ensure_no_bottom(Unify_ECR *tao, declNode *decl,
02207                                            UnifyType *parent) {
02208   if(! tao->type()->is_bottom()) return;
02209 
02210   Unify_Size s;
02211   if(decl && decl->type()) s = Unify_Size(Unify_Size::sizeOf(decl->type()));
02212   Unify_Parents p(false);
02213   if(parent) p.parents().insert(parent->ecr());
02214   settype(tao, new UnifyType(new Unify_Blank(s, p)));
02215 } // ensure_no_bottom
02216 
02217 
02218 Unify_Structure *UnificationBasedPtr::ensure_struct_obj(Unify_ECR *tao,
02219                                                         suespecNode *sue,
02220                                                         bool redo_pending) {
02221   assert(sue);
02222   Object_Typ typ = tao->type()->objTyp();
02223   if(typ == STRUCTURE) return tao->type()->structure();
02224   if(tao->type()->is_bottom() || typ == BLANK) {
02225     Unify_Structure *st;
02226     if(tao->type()->is_bottom()) {
02227       Unify_Size struct_size(Unify_Size::sizeOf(sue));
02228       st = new Unify_Structure(sue, EltMap(), struct_size,
02229                                Unify_Parents(false));
02230     } else {
02231       Unify_Blank *blank = tao->type()->blank();
02232       st = new Unify_Structure(sue, EltMap(), blank->s, blank->p);
02233     }
02234     UnifyType *tao_type = tao->type();
02235     UnifyType *st_type = new UnifyType(st);
02236 
02237     if(redo_pending) {
02238       typeNode *c_type = NULL;
02239       memoryBlock *m = tao->type()->block();
02240       if(m && m->decl())
02241         c_type = m->decl()->type();
02242       Unify_Size size;
02243       if(c_type) size = Unify_Size(Unify_Size::sizeOf(c_type));
02244 
02245       // reset pending so that they are processed again.
02246       set<Unify_Pending*> pending = tao->pending().set();
02247       for(Pendings_p a=pending.begin(); a!=pending.end(); a++) {
02248         (*a)->un_served();
02249         if((*a)->typ() == Unify_Pending::cjoin &&
02250            ! ((Unify_Size*) (*a)->arg1())->leq(size)) {
02251           // in cjoin(), above condition will lead to expand() instad of
02252           // join/settype, the desired result. set size to top to prevent this.
02253           size = Unify_Size();
02254           if(tao->type()->objTyp() == BLANK)
02255             // do this to ensure_sim_obj use new size
02256             tao->type()->blank()->s= size;
02257         }
02258       }
02259     }
02260 
02261     if(tao->type() != tao_type) // tao's type has changed.
02262       return ensure_struct_obj(tao, sue, redo_pending);
02263     settype(tao, st_type);
02264     return st;
02265   } else { // case SIMPLE and OBJECT
02266     Unify_Size struct_size(Unify_Size::sizeOf(sue));
02267     promote(tao, struct_size);
02268     return NULL;
02269   }
02270 } // ensure_struct_obj
02271 
02272 
02273 void UnificationBasedPtr::expand(Unify_ECR *e) {
02274   /*settype(e, unify(e->type(), new UnifyType(new Unify_Blank(Unify_Size(),
02275                                                     Unify_Parents(false)))));*/
02276   UnifyType *T = e->type(), // remember
02277             *U = unify(T, new UnifyType(new Unify_Blank(Unify_Size(),
02278                                                         Unify_Parents(false))));
02279   while(T != e->type()) // has e->type() changed?
02280     U = unify(T = e->type(), U);
02281   settype(e, U);
02282 } // expand
02283 
02284 
02285 void UnificationBasedPtr::promote(Unify_ECR *e, Unify_Size &s) {
02286   if(e->type()->objTyp() == OBJECT && s.leq(e->type()->object()->s))
02287     return;
02288   /*settype(e, unify(e->type(),
02289                    new UnifyType(new Unify_Object(new Alpha(), L_bottom,
02290                                                   s, Unify_Parents(false)))));
02291   */
02292   UnifyType *T = e->type(), // remember
02293             *U = unify(T, new UnifyType(new Unify_Object(new Alpha(), L_bottom,
02294                                                     s, Unify_Parents(false))));
02295   while(T != e->type()) // has e->type() changed?
02296     U = unify(T = e->type(), U);
02297   settype(e, U);
02298 } // promote
02299 
02300 
02301 void UnificationBasedPtr::collapse(Unify_ECR *e) {
02302   if(e->type()->objTyp() == OBJECT) {
02303     Unify_Size s;
02304     if(s.leq(e->type()->object()->s)) return;
02305   }
02306   /*settype(e, unify(e->type(),
02307                    new UnifyType(new Unify_Object(new Alpha(), L_bottom,
02308                                                   Unify_Size(),
02309                                                   Unify_Parents(true)))));*/
02310 
02311   UnifyType *T = e->type(), // remember
02312             *U = unify(T, new UnifyType(new Unify_Object(new Alpha(), L_bottom,
02313                                                         Unify_Size(),
02314                                                         Unify_Parents(true))));
02315   while(T != e->type()) // has e->type() changed?
02316     U = unify(T = e->type(), U);
02317   settype(e, U);
02318 } // collapse
02319 
02320 
02321 void UnificationBasedPtr::make_unknown(Unify_Offset *o) {
02322   if(o->value() == Unify_Offset::zero) return; // note: pendings are served.
02323   o->value(Unify_Offset::unknown);
02324   set<Unify_Pending*> pending = o->pending().set();
02325   //o->pending().clear();
02326   for(Pendings_p a=pending.begin(); a!=pending.end(); a++) {
02327     if((*a)->is_served()) continue;
02328     if(finalizing) (*a)->served();
02329     switch((*a)->typ()) {
02330       case Unify_Pending::collapse:
02331         collapse((Unify_ECR*) (*a)->arg1());
02332         break;
02333       case Unify_Pending::makeunknown:
02334         if((Unify_Offset*) (*a)->arg1() != o)
02335           make_unknown((Unify_Offset*) (*a)->arg1());
02336         break;
02337     }
02338   }
02339 } // make_unknown
02340 
02341 void UnificationBasedPtr::unless_zero(Unify_Offset *o, Unify_ECR *tao) {
02342   if(o->value() == Unify_Offset::zero) {
02343     if(new_pending)
02344       o->pending().insert( new Unify_Pending(tao),true );
02345   } else
02346     collapse(tao);
02347 } // unless_zero
02348 
02349 void UnificationBasedPtr::cjoin(Unify_Size &s, Unify_ECR *e1, Unify_ECR *e2) {
02350   if(!e1 || !e2) return;
02351   if(e1 == e2 || e1->root()==e2->root()) return;
02352 
02353   // prevent infinite recursion.
02354   static set<pair<UnifyType*,UnifyType*> > stack;
02355   pair<UnifyType*,UnifyType*> ee(e1->type(),e2->type());
02356   if(stack.find(ee) != stack.end()) {
02357 //cout << "cjoin recursion\n";
02358     return; // recursion detected.
02359   }
02360   stack.insert(ee);
02361 
02362   // peek: if both objects pointing to same object, there is nothing more to do
02363   // in the future.
02364   bool force_no_pending = e1->type()->objTyp()==OBJECT &&
02365                           e2->type()->objTyp()==OBJECT &&
02366                           e1->type()->object()->alpha->tao()->type() ==
02367                           e2->type()->object()->alpha->tao()->type();
02368 
02369   if(new_pending && !force_no_pending)
02370     e1->pending().insert( new Unify_Pending(s,e1,e2),true );
02371 
02372   if(e1->type()->is_bottom()) {
02373     stack.erase(ee);
02374     return;
02375   }
02376 /*if(debug)
02377 cout << "cjoin " << *e1 << "+" << *e2 << endl;*/
02378 
02379   Object_Typ e2_typ = e2->type()->objTyp();
02380 
02381   switch(e1->type()->objTyp()) {
02382     case BLANK: {
02383       Unify_Blank *b1 = e1->type()->blank();
02384       if(! s.leq(b1->s))
02385         expand(e1);
02386       else if(e2->type()->is_bottom())
02387         settype(e2, new UnifyType(new Unify_Blank(s, Unify_Parents(false))));
02388       else if(! s.leq(e2->type()->size()))
02389         expand(e2);
02390       break;
02391     } // BLANK
02392 
02393     case SIMPLE: {
02394       Unify_Simple *sim1 = e1->type()->simple();
02395       if(! s.leq(sim1->s))
02396         expand(e1);
02397       else if(e2->type()->is_bottom())
02398         settype(e2, new UnifyType(new Unify_Simple(sim1->alpha, sim1->lambda,
02399                                                    s, Unify_Parents(false))));
02400       else {
02401         switch(e2->type()->objTyp()) {
02402           case BLANK: {
02403             Unify_Blank *b2 = e2->type()->blank();
02404             settype(e2, new UnifyType(new Unify_Simple(sim1->alpha,sim1->lambda,
02405                                                        b2->s, b2->p)));
02406             if(! s.leq(b2->s))
02407               expand(e2);
02408             break;
02409           }
02410           case SIMPLE: {
02411             Unify_Simple *sim2 = e2->type()->simple();
02412             join(sim1->alpha, sim2->alpha);
02413             join(sim1->lambda, sim2->lambda);
02414             if(! s.leq(sim2->s))
02415               expand(e2);
02416             break;
02417           }
02418           case STRUCTURE:
02419             promote(e2, e2->type()->structure()->s);
02420             if(!finalizing && !serve_again) break; // new
02421           case OBJECT: {
02422             Unify_Object *o = e2->type()->object();
02423             // note: does not check if o has size top and empty parents.
02424             join(sim1->alpha, o->alpha);
02425             join(sim1->lambda, o->lambda);
02426           }
02427         }
02428       }
02429       break;
02430     } // SIMPLE
02431 
02432     case STRUCTURE: {
02433       Unify_Structure *st1 = e1->type()->structure();
02434       if(! s.leq(st1->s))
02435         expand(e1);
02436       else if(e2->type()->is_bottom())
02437         settype(e2, new UnifyType(
02438                       new Unify_Structure(st1->fo, st1->fto, st1->m, s,
02439                                           Unify_Parents(false))));
02440       else {
02441         switch(e2->type()->objTyp()) {
02442           case BLANK: {
02443             Unify_Blank *b2 = e2->type()->blank();
02444             settype(e2, new UnifyType(
02445                           new Unify_Structure(st1->fo, st1->fto, st1->m, b2->s,
02446                                               b2->p)));
02447             if(! s.leq(b2->s))
02448               expand(e2);
02449             break;
02450           }
02451           case SIMPLE:
02452             promote(e2, e2->type()->simple()->s);
02453             if(finalizing || serve_again) goto STRUCTURE_OBJECT; // new
02454             break;
02455           case STRUCTURE: {
02456             Unify_Structure *st2 = e2->type()->structure();
02457             bool all_compatible = true;
02458             if(s.leq(st2->s)) {
02459               // check all x in dom(st1->m)
02460               for(EltMap::iterator x=st1->m.begin(); x!=st1->m.end(); x++)
02461                 if(! make_compatible(x->first, st2, e2))
02462                 { all_compatible = false; break; }
02463             } else all_compatible = false;
02464             if(all_compatible)
02465               for(EltMap::iterator x=st1->m.begin(); x!=st1->m.end(); x++) {
02466                 declNode *one_field = unique_field_defn(* x->first.begin());
02467                 Unify_Size s_x(Unify_Size::sizeOf(one_field->type()));
02468                 cjoin(s_x, x->second, st2->get(one_field, e2));
02469               }
02470             else
02471               expand(e2);
02472             break;
02473           }
02474           case OBJECT: {
02475 STRUCTURE_OBJECT:
02476             // note: does not check if e2 has size top and empty parents.
02477             for(EltMap::iterator x=st1->m.begin(); x!=st1->m.end(); x++) {
02478               Unify_Size s_x(Unify_Size::sizeOf((*x->first.begin())->type()));
02479               cjoin(s_x, x->second, e2);
02480             }
02481           }
02482         }
02483       }
02484       break;
02485     } // STRUCTURE
02486 
02487     case OBJECT: {
02488       Unify_Object *o1 = e1->type()->object();
02489       if(! s.leq(o1->s)) expand(e1); // new
02490       //if(o1->s.is_top() && o1->p.empty()) {
02491       // note: does not check if o1,o2 has size top and empty parents.
02492         if(finalizing || serve_again) // new
02493           promote(e2,s); // ensure e2 is OBJECT
02494         // bool do_join = false;
02495         Unify_Object *o2 = NULL;
02496         if(e2->type()->objTyp()==OBJECT) {
02497           o2 = e2->type()->object();
02498           // if(o2->s.is_top() && o2->p.empty()) do_join = true;
02499         }
02500         if(/*do_join ||*/ o2 /*&& finalizing*/) {
02501           bool f = finalizing;
02502           finalizing = false; // so that new pending can be generated.
02503           if(! s.leq(o2->s)) expand(e2); // new
02504           join(o1->alpha, o2->alpha);
02505           join(o1->lambda, o2->lambda);
02506           finalizing = f;
02507 
02508         } /*else if(finalizing) {
02509           //settype(e2, unify(e1->type(), e2->type())); // new
02510           join(e1, e2); // new
02511         } */ else
02512           promote(e2,s);
02513 
02514       /*} else if(finalizing) {
02515         settype(e2, unify(e1->type(), e2->type())); // new
02516       } */
02517     } // OBJECT
02518   }
02519 
02520   if(serve_again && e2_typ != e2->type()->objTyp()) { // new
02521     // e2 has been promoted, and we are in finalize mode. Any pending in e2 may
02522     // need to be served again. Need to get all pendings from e2's root.
02523     set<Unify_Pending*> pending = e2->root()->pending().set();
02524     for(Pendings_p p=pending.begin(); p!=pending.end(); p++)
02525       if((*p)->is_served()) {
02526         (*p)->un_served();
02527         more_pending.insert(*p);
02528       }
02529   }
02530 
02531 /*if(debug)
02532 cout << "  after cjoin " << *e1 << "+" << *e2 << endl;*/
02533   stack.erase(ee);
02534 } // cjoin
02535 
02536 
02537 UnifyType *UnificationBasedPtr::unify(UnifyType *t1, UnifyType *t2) {
02538   if(t1 == t2) return t1;
02539 
02540 #define return_unify(t) { \
02541   UnifyType *T = (t)->ecr()->type(); /* need to do (?) this because t could have
02542                                   a new root type as we recurse into joins. */ \
02543   memoryBlock *block = t1->block() ? t1->block() : t2->block(); \
02544   if(! T->block()) T->block(block); \
02545   else assert(T->block()==block); \
02546   \
02547   if(t1 != T) T->procs().insert(t1->procs().begin(), t1->procs().end()); \
02548   if(t2 != T) T->procs().insert(t2->procs().begin(), t2->procs().end()); \
02549   \
02550   return T; \
02551 }
02552 
02553   if(t1->block() && t2->block()) {
02554     cout << "cannot unify " << *t1 << " + " << *t2 << endl;
02555     cout << "  " << *t1->ecr() << " + " << *t2->ecr() << endl;
02556     cout << "  " << t1->block()->name() << " + " << t2->block()->name() << endl;
02557     assert(false);
02558     return NULL; // do not unify. or what? TBD?
02559   }
02560 
02561   Object_Typ ty1 = t1->objTyp(),
02562              ty2 = t2->objTyp(),
02563              result_ty;
02564   if(ty1 == BOTTOM) return_unify( t2 )
02565   if(ty2 == BOTTOM) return_unify( t1 )
02566 
02567 #define max_Lambda(t1, ty1, t2, ty2, l) \
02568   if(t1->is_bottom() || ty1==STRUCTURE || ty1==BLANK) { \
02569     is_Sim_Obj(t2); \
02570     l = Sim_Obj_Lambda(t2); \
02571   } else if(t2->is_bottom() || ty2==STRUCTURE || ty2==BLANK) { \
02572     is_Sim_Obj(t1); \
02573     l = Sim_Obj_Lambda(t1); \
02574   } else { \
02575     l = Sim_Obj_Lambda(t1); \
02576     Lambda *l2 = Sim_Obj_Lambda(t2); \
02577     if(l->leq(l2)) l=l2; \
02578     else if(l2->leq(l)) ; \
02579     else join(l,l2); \
02580   }
02581 
02582 #define sizeOfType(t,ty) \
02583   ((ty==OBJECT) ? t->object()->s : \
02584    (ty==SIMPLE) ? t->simple()->s : \
02585    (ty==STRUCTURE) ? t->structure()->s : \
02586    (ty==BLANK) ? t->blank()->s : Unify_Size())
02587 
02588 #define max_Size(t1, ty1, t2, ty2, s) \
02589   if(t1->is_bottom()) \
02590     s = sizeOfType(t2,ty2); \
02591   else if(t2->is_bottom()) \
02592     s = sizeOfType(t1,ty1); \
02593   else { \
02594     s = sizeOfType(t1,ty1); \
02595     Unify_Size s2 = sizeOfType(t2,ty2); \
02596     if(s.is_top()) ; \
02597     else if(s2.is_top()) s=s2; \
02598     else if( s.size() < s2.size() ) s=s2; \
02599   }
02600 
02601 #define parentsOfType(t,ty) \
02602   ((ty==OBJECT) ? t->object()->p : \
02603    (ty==SIMPLE) ? t->simple()->p : \
02604    (ty==STRUCTURE) ? t->structure()->p : \
02605    (ty==BLANK) ? t->blank()->p : Unify_Parents(true))
02606 
02607 #define max_Parents(t1, ty1, t2, ty2, p) \
02608   if(t1->is_bottom()) \
02609     p = parentsOfType(t2,ty2); \
02610   else if(t2->is_bottom()) \
02611     p = parentsOfType(t1,ty1); \
02612   else { \
02613     Unify_Parents p1 = parentsOfType(t1,ty1), \
02614                   p2 = parentsOfType(t2,ty2); \
02615     for(set<Unify_ECR*>::iterator P=p1.parents().begin(); \
02616         P!=p1.parents().end(); P++)\
02617       p.parents().insert((*P)->root()); \
02618     for(set<Unify_ECR*>::iterator P=p2.parents().begin(); \
02619         P!=p2.parents().end(); P++)\
02620       p.parents().insert((*P)->root()); \
02621     if(!p1.is_top() || ! p2.is_top()) p.top(false); \
02622   }
02623 
02624   if(ty1==OBJECT || ty2==OBJECT || ty1==STRUCTURE && ty2==SIMPLE ||
02625      ty2==STRUCTURE && ty1==SIMPLE)
02626     result_ty = OBJECT;
02627   else if(ty1==SIMPLE || ty2==SIMPLE)
02628     result_ty = SIMPLE;
02629   else if(ty1==STRUCTURE || ty2==STRUCTURE)
02630     result_ty = STRUCTURE;
02631   else if(ty1==BLANK || ty2==BLANK)
02632     result_ty = BLANK;
02633   else result_ty = BOTTOM;
02634 
02635 /*cout << "unify " << *t1 << " + " << *t2 << " result_ty="
02636      << (result_ty==SIMPLE ? "SIMPLE\n" :
02637          result_ty==OBJECT ? "OBJECT\n" :
02638          result_ty==STRUCTURE ? "STRUCTURE\n" :
02639          result_ty==BLANK ? "BLANK\n" : "BOTTOM\n");*/
02640 
02641   if(result_ty==SIMPLE || result_ty==OBJECT) {
02642     Unify_Size s;
02643     max_Size(t1,ty1,t2,ty2,s)
02644     Alpha *alpha;
02645     bool recursion_detected;
02646     if(ty1!=SIMPLE && ty1!=OBJECT)
02647       alpha = Sim_Obj_Alpha(t2);
02648     else if(ty2!=SIMPLE && ty2!=OBJECT)
02649       alpha = Sim_Obj_Alpha(t1);
02650     else {
02651       Alpha *a1 = Sim_Obj_Alpha(t1),
02652             *a2 = Sim_Obj_Alpha(t2);
02653       if(a2->offset()->value() == Unify_Offset::unknown)
02654         join(a2,a1,&recursion_detected); //treat a2 as rhs
02655       else
02656         join(a1,a2,&recursion_detected);
02657       // note: obtain alpha below only after above joins. Pick the one that
02658       // contain the root of tao, so that it also contains the union of their
02659       // pendings.
02660       if(a1->tao()->root() == a1->tao())      alpha = a1;
02661       else if(a2->tao()->root() == a2->tao()) alpha = a2;
02662       else alpha = new Alpha(a1->tao()->root(), a1->offset());
02663     }
02664     Lambda *lambda;
02665     max_Lambda(t1,ty1,t2,ty2,lambda)
02666     Unify_Parents p(true);
02667     max_Parents(t1,ty1,t2,ty2,p);
02668 
02669     if(result_ty==SIMPLE) {
02670       if(ty1==SIMPLE) {
02671         Unify_Simple *s1 = t1->simple();
02672         if((s1->alpha->equal(alpha) || s1->alpha->tao()->type()->is_bottom()) &&
02673            s1->lambda->equal(lambda) && s1->s.equal(s) && s1->p.equal(p))
02674           return_unify( t1 )
02675       }
02676       if(ty2==SIMPLE) {
02677         Unify_Simple *s2 = t2->simple();
02678         if((s2->alpha->equal(alpha) || s2->alpha->tao()->type()->is_bottom()) &&
02679            s2->lambda->equal(lambda) && s2->s.equal(s) && s2->p.equal(p))
02680           return_unify( t2 )
02681       }
02682       if(ty1==SIMPLE && ty2==SIMPLE && recursion_detected) {
02683         // this happens only (?) when alpha is not joined from a1,a2 due to
02684         // recursion in join(). This happens when, e.g. we try to unify two
02685         // structures with pointer fields pointing back to the structures.
02686         t1->simple()->p = p;
02687         return_unify( t1 ) // arbitrary return, doesn't matter.
02688       }
02689       if(ty1==SIMPLE && !recursion_detected) {
02690         Unify_Simple *s1 = t1->simple();
02691         s1->lambda = lambda;
02692         s1->s = s;
02693         s1->p = p;
02694         return_unify( t1 )
02695       } else if(ty2==SIMPLE && !recursion_detected) {
02696         Unify_Simple *s2 = t2->simple();
02697         s2->lambda = lambda;
02698         s2->s = s;
02699         s2->p = p;
02700         return_unify( t2 )
02701       }
02702       Unify_Simple *sim = new Unify_Simple(alpha, lambda, s, p);
02703       return_unify( new UnifyType(sim) )
02704 
02705     } else { // result_ty is OBJECT
02706       Unify_ECR *field = NULL;
02707 #define consolidate_struct_fields(struc,result) {\
02708     EltMap map = struc->m; \
02709     for(EltMap::iterator m=map.begin(); m!=map.end(); m++) \
02710       if(m->second) { \
02711         if(result) join(result, m->second); \
02712         else result = m->second; \
02713       } \
02714   }
02715 
02716 #define consolidate_sim_obj_fields(alpha,result) {\
02717     if(result) join(result,alpha->tao()); \
02718     else result = alpha->tao(); \
02719   }
02720 
02721       if(ty1==STRUCTURE) consolidate_struct_fields(t1->structure(), field)
02722       else if(ty1==SIMPLE || ty1==OBJECT)
02723         consolidate_sim_obj_fields(Sim_Obj_Alpha(t1), field)
02724       if(ty2==STRUCTURE) consolidate_struct_fields(t2->structure(), field)
02725       else if(ty2==SIMPLE || ty2==OBJECT)
02726         consolidate_sim_obj_fields(Sim_Obj_Alpha(t2), field)
02727 
02728       if(ty1==OBJECT) {
02729         Unify_Object *o1 = t1->object();
02730         if((o1->alpha->equal(alpha) || o1->alpha->tao()->type()->is_bottom()) &&
02731            o1->lambda->equal(lambda) && o1->s.equal(s) && o1->p.equal(p))
02732           return_unify( t1 )
02733       }
02734       if(ty2==OBJECT) {
02735         Unify_Object *o2 = t2->object();
02736         if((o2->alpha->equal(alpha) || o2->alpha->tao()->type()->is_bottom()) &&
02737            o2->lambda->equal(lambda) && o2->s.equal(s) && o2->p.equal(p))
02738           return_unify( t2 )
02739       }
02740       if(ty1==OBJECT && ty2==OBJECT && recursion_detected) {
02741         // this happens only (?) when alpha is not joined from a1,a2 due to
02742         // recursion in join(). This happens when, e.g. we try to unify two
02743         // structures with pointer fields pointing back to the structures.
02744         t1->object()->p = p;
02745         return_unify( t1 ) // arbitrary return, doesn't matter.
02746       }
02747       if(ty1==OBJECT && !recursion_detected) {
02748         Unify_Object *o1 = t1->object();
02749         o1->lambda = lambda;
02750         o1->s = s;
02751         o1->p = p;
02752         return_unify( t1 )
02753       } else if(ty2==OBJECT && !recursion_detected) {
02754         Unify_Object *o2 = t2->object();
02755         o2->lambda = lambda;
02756         o2->s = s;
02757         o2->p = p;
02758         return_unify( t2 )
02759       }
02760       Unify_Object *obj = new Unify_Object(alpha, lambda, s, p);
02761       return_unify( new UnifyType(obj) )
02762     }
02763 
02764   } else if(result_ty==STRUCTURE) {
02765     Unify_Size s;
02766     max_Size(t1,ty1,t2,ty2,s)
02767     Unify_Parents p(true);
02768     max_Parents(t1,ty1,t2,ty2,p);
02769 
02770     EltMap m;
02771     FieldOrder fo;
02772     FieldTypeOrder fto;
02773     if(ty1!=STRUCTURE) {
02774       t2->structure()->s = s;
02775       t2->structure()->p = p;
02776       return_unify( t2 )
02777     } else if(ty2!=STRUCTURE) {
02778       t1->structure()->s = s;
02779       t1->structure()->p = p;
02780       return_unify( t1 )
02781     } else {
02782       Unify_Structure *s = new Unify_Structure(FieldOrder(), FieldTypeOrder(),
02783                                                EltMap(), Unify_Size(), p);
02784       merge_EltMap(t1, t2, s);
02785       return_unify( new UnifyType(s) )
02786     }
02787 
02788 
02789   } else if(result_ty==BLANK) {
02790     Unify_Size s;
02791     max_Size(t1,ty1,t2,ty2,s)
02792     Unify_Parents p(true);
02793     max_Parents(t1,ty1,t2,ty2,p);
02794     if(ty1==BLANK) {
02795       Unify_Blank *b1 = t1->blank();
02796       if(b1->s.equal(s) && b1->p.equal(p)) return_unify( t1 )
02797     }
02798     if(ty2==BLANK) {
02799       Unify_Blank *b2 = t2->blank();
02800       if(b2->s.equal(s) && b2->p.equal(p)) return_unify( t2 )
02801     }
02802     if(ty1==BLANK) {
02803       Unify_Blank *b1 = t1->blank();
02804       b1->s = s;
02805       b1->p = p;
02806       return_unify( t1 )
02807     } else {
02808       Unify_Blank *b2 = t2->blank();
02809       b2->s = s;
02810       b2->p = p;
02811       return_unify( t2 )
02812     }
02813     // return new UnifyType(new Blank(s, p));
02814   } else // both are BOTTOM
02815     return_unify( t1 )
02816 } // unify
02817 
02818 
02819 void UnificationBasedPtr::merge_EltMap(UnifyType *t1, UnifyType *t2,
02820                                        Unify_Structure *s) {
02821 //cout << "merge_EltMap\n";
02822   /* The paper does not give details, but it appears that, say, the structure
02823    * definitions are respectively
02824    *   m1 = { int, int, int* }
02825    *   m2 = { int, int, float, float* }
02826    * then the result should be
02827    *   s->m  = { int, int, _everything_else_ }
02828    * i.e. the prefix is the common prefix of both m1,m2, then everything else
02829    * are merged.
02830    */
02831 
02832   assert(t1->objTyp()==STRUCTURE && t2->objTyp()==STRUCTURE);
02833   EltMap m1 = t1->structure()->m,
02834          m2 = t2->structure()->m;
02835   FieldOrder fo1 = t1->structure()->fo,
02836              fo2 = t2->structure()->fo;
02837 
02838   for(FieldOrder::iterator f1=fo1.begin(); f1!=fo1.end(); f1++) {
02839     make_compatible(*f1,s,t1->ecr(),true);
02840     if(! m1[*f1]) continue;
02841     declNode *one_field = * f1->begin();
02842     FieldOrder::iterator fo=s->fo.begin();
02843     while(fo!=s->fo.end() && fo->find(one_field)==fo->end())
02844       fo++;
02845     assert(fo!=s->fo.end());
02846     join(m1[*f1], s->m[*fo]);
02847   }
02848 
02849   for(FieldOrder::iterator f2=fo2.begin(); f2!=fo2.end(); f2++) {
02850     make_compatible(*f2,s,t2->ecr(),true);
02851     if(! m2[*f2]) continue;
02852     declNode *one_field = * f2->begin();
02853     FieldOrder::iterator fo=s->fo.begin();
02854     while(fo!=s->fo.end() && fo->find(one_field)==fo->end())
02855       fo++;
02856     assert(fo!=s->fo.end());
02857     join(m2[*f2], s->m[*fo]);
02858   }
02859 } // merge_EltMap
02860 
02861 
02862 bool UnificationBasedPtr::make_compatible(declSet n, Unify_Structure *s,
02863                                           Unify_ECR *container, bool force) {
02864   { // ensure we use the unique fields.
02865   declSet n1 = n; // make a copy
02866   for(declSet::iterator d=n1.begin(); d!=n1.end(); d++)
02867     if(_unique_field_defn[*d] != *d) {
02868       n.erase(*d);
02869       n.insert(_unique_field_defn[*d]);
02870     }
02871   }
02872 
02873   if(find(s->fo.begin(), s->fo.end(), n) != s->fo.end()) return true;
02874   container = container->root();
02875 
02876 /*cout << "make_compatible ";
02877 for(declSet::iterator d=n.begin(); d!=n.end(); d++)
02878   cout << (*d)->name() << "@" << (*d)->coord() << " ";
02879  cout << "\n  container:" << *container << endl; */
02880 
02881   assert(! n.empty());
02882 
02883   if(s->fo.empty()) { // not yet set
02884     suespecNode *sue = _field2sue[* n.begin()];
02885     decl_list fields = sue->fields();
02886     assert(! fields.empty());
02887     if(sue->owner() == Struct) {
02888       for(decl_list_p d=fields.begin(); d!=fields.end(); d++) {
02889         declSet ds;  ds.insert(*d);
02890         s->fo.push_back(ds);
02891         s->fto.push_back((*d)->type());
02892         assert(! s->m[ds]);
02893         new_field_ECR(s->m[ds], (*d)->type(), container)
02894       }
02895     } else {
02896       declSet ds;
02897       typeNode *type = NULL;
02898       for(decl_list_p d=fields.begin(); d!=fields.end(); d++) {
02899         ds.insert(*d);
02900         if(d==fields.begin()) type = (*d)->type();
02901         else if(! compatible_type((*d)->type(), type)) type = NULL;
02902       }
02903       s->fo.push_back(ds);
02904       s->fto.push_back(type);
02905       assert(s->m.empty());
02906       new_field_ECR(s->m[ds], type, container);
02907     }
02908     return true;
02909   }
02910 
02911   decl_list n_pos; // see comment below.
02912   for(declSet::iterator d=n.begin(); d!=n.end(); d++) {
02913 //cout << (*d)->name() << " " << *d << " @" << (*d)->coord() << endl;
02914     if(d==n.begin()) n_pos = _fieldpos[*d];
02915     /*else if(_field2sue[*d] == _field2sue[* n.begin()]) {
02916       cout << s->all_str();
02917       for(FieldOrder::iterator fo=s->fo.begin(); fo!=s->fo.end(); fo++)
02918         cout << (*fo == n);
02919       cout << "\nn:";
02920       for(declSet::iterator d1=n.begin(); d1!=n.end(); d1++)
02921         cout << "  " << (*d1)->name() << " @" << (*d1)->coord() << endl;
02922       assert(false); // possible?
02923       n_pos = _fieldpos[*d];
02924     } else {
02925       if(n_pos.size() != _fieldpos[*d].size()) {
02926         cout << "n_pos:\n";
02927         for(decl_list_p d1=n_pos.begin(); d1!=n_pos.end(); d1++)
02928           cout << "    " << (*d1)->name() << "@" << (*d1)->coord() << endl;
02929         cout << "_fieldpos:\n";
02930         for(decl_list_p d1=_fieldpos[*d].begin(); d1!=_fieldpos[*d].end(); d1++)
02931           cout << "    " << (*d1)->name() << "@" << (*d1)->coord() << endl;
02932       }
02933       assert(n_pos.size() == _fieldpos[*d].size());
02934     }*/
02935     // above is wrong. the fields in n could come from same sue (they are
02936     // merged). Whether they belong to same sue or not, we want to know the
02937     // common prefix in each sue; hence we want n_pos to be the _fieldpos of
02938     // smallest size:
02939     else if(_fieldpos[*d].size() < n_pos.size())
02940       n_pos = _fieldpos[*d];
02941   }
02942 
02943 /*{
02944   cout << "#n_pos=" << n_pos.size() << endl;
02945   cout << "b4 change. " << s->all_str();
02946   cout << "\nfield_type_order: ";
02947   for(FieldTypeOrder::iterator fto=s->fto.begin(); fto!=s->fto.end(); fto++) {
02948     if(*fto) {
02949       output_context oc(cout);
02950       (*fto)->output(oc,NULL); cout << ",";
02951     } else cout << "nil,";
02952   }
02953   cout << endl;
02954 } */
02955 
02956   assert(s->fo.size() == s->fto.size());
02957   FieldOrder::iterator fo=s->fo.begin();
02958   FieldTypeOrder::iterator to=s->fto.begin();
02959   Unify_ECR *previously_merged = NULL;
02960 
02961 
02962   for(decl_list_p n1=n_pos.begin(); n1!=n_pos.end(); n1++) {
02963 
02964 /*cout << "n1=" << (*n1)->name() << " fo={";
02965 for(declSet::iterator d=fo->begin(); d!=fo->end(); d++) cout << (*d)->name() << ",";
02966  cout << "}\n"; */
02967 
02968 #define insert_into_set(set, Dp) { \
02969   if(Dp == n_pos.back()) set->insert(n.begin(), n.end()); \
02970   else                   set->insert(Dp); \
02971   if(Dp != n_pos.front()) { \
02972     /* insert other fields preceding each field in n. */ \
02973     for(declSet::iterator N=n.begin(); N!=n.end(); N++) { \
02974       decl_list all_fields = _field2sue[*N]->fields(); \
02975       FieldOrder::iterator fo1 = s->fo.begin(); \
02976       for(decl_list_p f=all_fields.begin(); f!=all_fields.end(); f++) { \
02977         if(_fieldpos[*f].size() >= _fieldpos[Dp].size()) break; \
02978         else { \
02979           Unify_ECR *E = s->m[*fo1]; \
02980           s->m.erase(*fo1); \
02981           fo1->insert(*f); \
02982           s->m[*fo1] = E; \
02983           break; \
02984         } \
02985         if(++fo1==s->fo.end()) break; \
02986       } \
02987     } \
02988   } \
02989 }
02990 
02991     bool merge = false;
02992     typeNode *field_type = (to==s->fto.end()) ? NULL : *to;
02993 //cout << "  field_type " << field_type << endl;
02994     if(field_type == NULL || !compatible_type((*n1)->type(), field_type)) {
02995 //cout << "!compatible_type\n";
02996       if(!force) return false;
02997       // merge
02998       declSet * ds;
02999       if(to!=s->fto.end()) {
03000         *to = NULL;
03001         ds = &(*fo);
03002       } else {
03003         s->fto.back() = NULL;
03004         ds = & s->fo.back();
03005       }
03006       if(s->m.find(*ds) != s->m.end()) {
03007         Unify_ECR *E = s->m[*ds];
03008         s->m.erase(*ds);
03009         insert_into_set(ds,*n1)
03010         s->m[*ds] = E;
03011       } else
03012         insert_into_set(ds,*n1)
03013       if(previously_merged) {
03014         if(s->m[*ds])
03015           join(s->m[*ds], previously_merged); // TBD: or use cjoin?
03016         else
03017           s->m[*ds] = previously_merged;
03018       } else if(! s->m[*ds])
03019         new_field_ECR(s->m[*ds], field_type, container)
03020       previously_merged = s->m[*ds];
03021     } else { // compatible types
03022       if(s->m.find(*fo) == s->m.end()) {
03023         insert_into_set(fo,*n1)
03024         new_field_ECR(s->m[*fo], field_type, container)
03025       } else {
03026         Unify_ECR *E = s->m[*fo];
03027         s->m.erase(*fo);
03028         insert_into_set(fo,*n1)
03029         s->m[*fo] = E;
03030       }
03031     }
03032 
03033     if(*n1 == n_pos.back() && ! previously_merged && fo!=s->fo.end()) {
03034       // we are about to finish this loop. Before that, need to check if
03035       // anything in n is in later fo, and if so, need to merge.
03036       // Check this now before fo is incremented.
03037       bool n_in_later_fo = false;
03038       FieldOrder::iterator fo1 = fo; fo1++; // next after fo
03039       while(!n_in_later_fo && fo1!=s->fo.end()) {
03040         for(declSet::iterator d=n.begin(); d!=n.end(); d++)
03041           if(fo1->find(*d) != fo1->end()) { n_in_later_fo=true; break; }
03042         fo1++;
03043       }
03044       if(n_in_later_fo)
03045         previously_merged = s->m[*fo]; // enable merge.
03046     }
03047 
03048     if(!previously_merged && fo != s->fo.end()) { fo++; to++; }
03049 /*cout << "n1 done, m=";
03050 for(EltMap::iterator m=s->m.begin(); m!=s->m.end(); m++)
03051   if(m->second) {
03052     cout << "<";
03053     declSet decls = m->first;
03054     for(declSet::iterator d=decls.begin(); d!=decls.end(); d++) {
03055       if(d!=decls.begin()) cout << ",";
03056       cout << (*d)->name();
03057     }
03058     cout << "->" << m->second->type()->id() << ">,";
03059   }
03060  cout << endl; */
03061   }
03062 
03063 
03064   if(previously_merged) {
03065     if(fo != s->fo.end()) {
03066 //cout << "fo " << fo->size() << endl;
03067       while(s->fo.back() != *fo) {
03068         declSet back = s->fo.back();
03069         s->m.erase(*fo);
03070         if(s->m.find(back) != s->m.end()) { // merge previously_merged and back
03071           Unify_ECR *E2 = s->m[back];
03072           s->m.erase(back);
03073           join(previously_merged, E2);
03074           previously_merged = previously_merged->root();
03075         }
03076         (*fo).insert(back.begin(), back.end());
03077         s->m[*fo] = previously_merged;
03078         s->fo.pop_back();
03079         s->fto.pop_back();
03080       }
03081     }
03082 
03083     // if n is not the last field of its structure, need to merge all in.
03084     for(declSet::iterator N=n.begin(); N!=n.end(); N++) {
03085       if(_field2sue[*N]->fields().back() != *N) {
03086 //cout << "N = " << (*N)->name() << endl;
03087         declSet & back = s->fo.back();
03088         assert(back.find(*N) != back.end());
03089         assert(previously_merged == s->m[back]);
03090         s->m.erase(back);
03091         decl_list fields = _field2sue[*N]->fields();
03092         for(decl_list::reverse_iterator f=fields.rbegin();
03093             f!=fields.rend() && *f!=*N; f++)
03094           back.insert(*f);
03095         s->m[back] = previously_merged;
03096       }
03097     }
03098   }
03099 
03100 #define CX_INVARIANT
03101 #ifdef CX_INVARIANT
03102 { int error = 0;
03103   if(s->fo.size() != s->fto.size()) error = 1; // unmatch size
03104   int pos = 1;
03105   for(fo=s->fo.begin(); !error && fo!=s->fo.end(); fo++, pos++) {
03106     if(s->m.find(*fo) != s->m.end() && !s->m[*fo]) error=2; // null entry
03107     for(declSet::iterator d=fo->begin(); !error && d!=fo->end(); d++) {
03108       if(_fieldpos[*d].size() < pos) error=3; // wrong _fieldpos
03109       decl_list all_fields = _field2sue[*d]->fields();
03110       if(_fieldpos[*d].size() > pos) { // *d is merged field.
03111         for(decl_list_p f=all_fields.begin(); !error && f!=all_fields.end();f++)
03112           if(_fieldpos[*f].size() >= pos &&
03113              fo->find(*f) == fo->end()) {
03114             error=4; // *f not inside fo, should be in same as *d.
03115             cout << "d " << (*d)->name() << " @" << (*d)->coord() << endl;
03116             cout << "f " << (*f)->name() << " @" << (*f)->coord() << endl;
03117           }
03118       }
03119       for(decl_list_p f=all_fields.begin(); !error && f!=all_fields.end();f++)
03120         if(_fieldpos[*f].size() < pos) { // *f is merged, possibly diff struct
03121           int pos1 = 1;
03122           FieldOrder::iterator fo1 = s->fo.begin();
03123           while(pos1 < _fieldpos[*f].size()) { fo1++; pos1++; }
03124           if(fo1->find(*f) == fo1->end()) { // *f is not in right s->fo
03125             error=5;
03126             cout << "f " << (*f)->name() << " @" << (*f)->coord() << endl;
03127           }
03128         }
03129     }
03130   }
03131   for(map<declSet,Unify_ECR*>::iterator m=s->m.begin(); !error && m!=s->m.end();
03132       m++) {
03133     if(! m->second) error=6; // empty entry
03134     else if(find(s->fo.begin(), s->fo.end(), m->first) == s->fo.end())
03135       error=7; // the declSet not in fo
03136   }
03137   if(error) {
03138     cout << s->all_str();
03139     cout << "error=" << error << endl;
03140     if(cur_proc) cout << "cur_proc @" << cur_proc->coord() << endl;
03141     assert(false);
03142   }
03143 }
03144 #endif
03145 
03146   return true;
03147 } // make_compatible
03148 
03149 
03150 bool UnificationBasedPtr::compatible_type(typeNode *t1, typeNode *t2) {
03151   // easiest: the types must be the same.
03152   if(!t1 || !t2) return false;
03153   if(t1 == t2) return true;
03154   if(t1->typ() != t2->typ()) return false;
03155   switch(t1->typ()) {
03156     case Prim: return ((primNode*)t1)->basic() == ((primNode*)t1)->basic();
03157     case Struct:
03158     case Union: return ((sueNode*)t1)->spec() == ((sueNode*)t2)->spec();
03159     case Ptr: return compatible_type(t1->type(), t2->type());
03160     case Func: return true; // TBD???
03161     case Array: {
03162       arrayNode *a1 = (arrayNode*) t1,
03163                 *a2 = (arrayNode*) t2;
03164       if(!compatible_type(a1->type(), a2->type())) return false;
03165       return (a1->dim() && a1->dim()->typ()==Const &&
03166               a2->dim() && a2->dim()->typ()==Const &&
03167               ((constNode*)a1->dim())->value().Integer() ==
03168               ((constNode*)a2->dim())->value().Integer());
03169     }
03170     case Tdef:
03171       return compatible_type(((tdefNode*)t1)->def(), ((tdefNode*)t2)->def());
03172     default: cout << t1->typ() << "@" << t1->coord() << " & "
03173                   << t2->typ() << "@" << t2->coord() << endl;
03174              assert(false);
03175   }
03176 } // compatible_type
03177 
03178 
03179 
03180 void UnificationBasedPtr::finalize() {
03181 //cout << "finalize\n";
03182 
03183   bool completed_once = false;
03184   serve_again = true;
03185   do {
03186     // the default, original value, in case this loop is re-iterated.
03187     finalizing = false;
03188     new_pending = true;
03189 
03190   // deal with _ptr_call first.
03191 //cout << "finalize deal with _ptr_call\n";
03192     map<threeAddrNode*,UnifyType*> ptr_call_set = _ptr_call;
03193     bool change = false;
03194     for(map<threeAddrNode*,UnifyType*>::iterator pc = ptr_call_set.begin();
03195         pc != ptr_call_set.end(); pc++) {
03196       threeAddrNode *the_call = pc->first;
03197       UnifyType *type = pc->second;
03198       assert(type);
03199       is_Sim_Obj(type); // still a Simple or Object ?
03200 /*cout << "at_call again ? " << the_call->coord() << " " << *type << endl;
03201   cout << "  " << *type << endl;
03202   cout << "  " << *Sim_Obj_Lambda(type) << endl; */
03203       if(type->ecr()->type() != type || // type has changed
03204          ! Sim_Obj_Lambda(type)->is_bottom()) { // no longer a bottom
03205         Unify_Size s = Unify_Size(Unify_Size::sizeOfAssign(the_call, linker,
03206                                                            this));
03207 /*cout << "at_call again " << the_call->coord() << " "
03208      << (type->ecr()->type() != type) << (! Sim_Obj_Lambda(type)->is_bottom())
03209      << endl;
03210 if(type->ecr()->type() != type) cout << "  new type " << *type->ecr() <<endl;*/
03211         at_call(the_call, s);
03212         if(_ptr_call.find(the_call) == _ptr_call.end() ||
03213            _ptr_call[the_call] != type)
03214           change = true;
03215       }
03216     }
03217     if(completed_once && !change) break;
03218 
03219 //debug = true;
03220 //cout << "actual finalize\n";
03221     finalizing = true;
03222     new_pending = false;
03223     set<Unify_ECR*> all_ecr = Unify_ECR::allECR();
03224     for(set<Unify_ECR*>::iterator e=all_ecr.begin(); e!=all_ecr.end(); e++) {
03225       set<Unify_Pending*> pending = (*e)->pending().set();
03226       // more for Lambda pendings
03227       if((*e)->type()->objTyp()==SIMPLE || (*e)->type()->objTyp()==OBJECT) {
03228         set<Unify_Pending*> more= Sim_Obj_Lambda((*e)->type())->pending().set();
03229         pending.insert(more.begin(), more.end());
03230       }
03231 repeat:
03232       for(Pendings_p p=pending.begin(); p!=pending.end(); p++) {
03233         if((*p)->is_served()) continue;
03234         (*p)->served();
03235         switch((*p)->typ()) {
03236           case Unify_Pending::collapse:
03237             collapse((Unify_ECR*) (*p)->arg1());
03238             break;
03239           case Unify_Pending::makeunknown:
03240             make_unknown((Unify_Offset*) (*p)->arg1());
03241             break;
03242           case Unify_Pending::join_ECR:
03243             join((Unify_ECR*) (*p)->arg1(), (Unify_ECR*) (*p)->arg2());
03244             break;
03245           case Unify_Pending::join_Lambda:
03246             join((Lambda*) (*p)->arg1(), (Lambda*) (*p)->arg2());
03247             break;
03248           case Unify_Pending::cjoin:
03249             cjoin(*(Unify_Size*) (*p)->arg1(), (Unify_ECR*)(*p)->arg2(),
03250                   (Unify_ECR*)(*p)->arg3());
03251             // delete (Unify_Size*) (*p)->arg1();
03252             break;
03253           default: assert(false);
03254         }
03255       }
03256       if(! more_pending.empty()) {
03257 //cout << "finalize: " << more_pending.size() << " more pendings\n";
03258         pending = more_pending;
03259         more_pending.clear();
03260         goto repeat;
03261       }
03262       //(*e)->pending().clear();
03263     }
03264 
03265     completed_once = true;
03266   } while(true);
03267 
03268   new_pending = true;
03269 } // finalize
03270 
03271 // ==============================================================
03272 
03273 Unify_ECR *UnificationBasedPtr::ecrField(UnifyType *container, declNode *field,
03274                                          bool field_from_annotation) {
03275   if(!container) return NULL;
03276 
03277   if(field_from_annotation && ! _unique_field_defn[field]) {
03278     if(container->objTyp() == OBJECT)
03279       return container->object()->alpha->tao();
03280     if(container->objTyp() != STRUCTURE) return NULL; // cannot do anything
03281     Unify_Structure *st = container->structure();
03282     string field_name = field->name(); // get rid of any prefix
03283     int pos = field_name.rfind(".");
03284     if(pos > 0) field_name = field_name.substr(pos+1, string::npos);
03285 
03286     declNode *unique_field = NULL;
03287     for(FieldOrder::iterator f=st->fo.begin(); f!=st->fo.end(); f++)
03288       for(declSet::iterator d=f->begin(); d!=f->end(); d++)
03289         if((*d)->name() == field_name) {
03290           if(! unique_field) unique_field = *d;
03291           else return NULL; // no unique field.
03292         }
03293     if(unique_field) _unique_field_defn[field] = unique_field;
03294   }
03295 
03296   field = _unique_field_defn[field];
03297 
03298   if(container->is_bottom() || container->objTyp() == BLANK) {
03299     suespecNode *sue = field2sue(field);
03300     assert(sue);
03301     Unify_Structure *st = ensure_struct_obj(container->ecr(), sue, true);
03302 
03303     if(container->ecr()->type() != container) {
03304       // changed. need to update.
03305       //memoryBlock *m = container->block();
03306       container = container->ecr()->type();
03307       /*if(m) { // m could be null if call from process_struct_rule().
03308         m->unifyType(new_container);
03309         new_container->block(m);
03310         container->block(NULL);
03311       }*/
03312     }
03313     declSet F;  F.insert(field);
03314     if(st && container->objTyp()==STRUCTURE)
03315       // !st happens when container->ecr()->type()!=container, when
03316       // container refers to a procedure. See createProcBlock.
03317       make_compatible(F, st, container->ecr(), true);
03318     // fall through
03319   }
03320 
03321   if(container->objTyp() == SIMPLE) {
03322     promote(container->ecr(), container->simple()->s);
03323     if(container->ecr()->type() != container) {
03324       //memoryBlock *m = container->block();
03325       container = container->ecr()->type();
03326       /*if(m) {
03327         m->unifyType(new_container);
03328         new_container->block(m);
03329         container->block(NULL);
03330       }*/
03331     }
03332   }
03333 
03334   if(container->objTyp() == OBJECT)
03335     return container->object()->alpha->tao();
03336 
03337   assert(container->objTyp() == STRUCTURE); // ???
03338   return container->structure()->get(field, container->ecr());
03339 } // ecrField
03340 
03341 
03342 Unify_ECR *UnificationBasedPtr::ecrDeref(UnifyType *container) {
03343   if(!container) return NULL;
03344   if(container->is_bottom() || container->objTyp() == BLANK) {
03345     // how is this possible: an array is never dereferenced except in
03346     // broadway's annotation.
03347     typeNode *c_type = NULL;
03348     memoryBlock *m = container->block();
03349     if(m && m->decl())
03350       c_type = m->decl()->type();
03351     Unify_Size size;
03352     if(c_type) size = Unify_Size(Unify_Size::sizeOf(c_type));
03353 
03354     // reset pending so that they are processed again.
03355     set<Unify_Pending*> pending = container->ecr()->pending().set();
03356     for(Pendings_p a=pending.begin(); a!=pending.end(); a++) {
03357       (*a)->un_served();
03358       if((*a)->typ() == Unify_Pending::cjoin &&
03359          ! ((Unify_Size*) (*a)->arg1())->leq(size)) {
03360         // in cjoin(), above condition will lead to expand() instad of
03361         // join/settype, the desired result. set size to top to prevent this.
03362         size = Unify_Size();
03363         if(container->objTyp() == BLANK)
03364           container->blank()->s = size; //do this to ensure_sim_obj use new size
03365       }
03366     }
03367     
03368     ensure_sim_obj(container->ecr(), size);
03369     if(container->ecr()->type() != container) {
03370       // changed. need to update.
03371       container = container->ecr()->type();
03372       /*m->unifyType(new_container);
03373       new_container->block(m);
03374       container->block(NULL);*/
03375     }
03376   }
03377   assert(container->objTyp() == SIMPLE || container->objTyp() == OBJECT); //???
03378   if(container->objTyp() == SIMPLE)
03379     return container->simple()->alpha->tao();
03380   else
03381     return container->object()->alpha->tao();
03382 } // ecrDeref
03383 
03384 
03385 void UnificationBasedPtr::createProcBlock(procNode *proc, memoryModel &Memory,
03386                                           procLocation *cur_loc) {
03387   declNode *p_decl = proc->decl();
03388   UnifyType *p_type = proctype(proc);
03389   Unify_ECR *proc_ecr = p_type->ecr_no_root(), // do not use ecr(proc->decl())
03390             *parent = proc_ecr->parent();
03391   UnifyType *org_type = proc_ecr->type();
03392   proc_ecr->parent(NULL);
03393   proc_ecr->type(p_type);
03394   memoryBlock *b = Memory.lookup_variable(cur_loc, p_decl, cur_loc->proc());
03395   proc_ecr->parent(parent);
03396   if(! parent) proc_ecr->type(org_type);
03397   assert(proc_ecr->type() == org_type);
03398 
03399   if(p_type->block()) assert(p_type->block() == b);
03400   else p_type->block(b);
03401 } // createProcBlock
03402 
03403 
03404 bool UnificationBasedPtr::reachable(UnifyType *src, UnifyTypes & targets,
03405                                     UnifyTypes & visited) {
03406   assert(src);
03407   if(visited.find(src) != visited.end()) return false;
03408   visited.insert(src);
03409   if(targets.find(src) != targets.end()) return true;
03410   if(src->is_bottom()) return false;
03411   switch(src->objTyp()) {
03412     case BLANK: return false;
03413     case SIMPLE:
03414     case OBJECT: {
03415       bool r = reachable(Sim_Obj_Alpha(src)->tao()->type(), targets, visited);
03416       if(r) targets.insert(src);
03417       return r;
03418     }
03419     case STRUCTURE: {
03420       EltMap map = src->structure()->m;
03421       for(EltMap::iterator m=map.begin(); m!=map.end(); m++)
03422         if(m->second && reachable(m->second->type(), targets, visited)) {
03423           targets.insert(src);
03424           return true;
03425         }
03426       return false;
03427     }
03428   }
03429 } // reachable
03430 
03431 
03432 // ==============================================================
03433 
03434 set<Unify_ECR*> UnificationBasedPtr::unique_ecr() const {
03435   set<Unify_ECR*> r;
03436   for(map<declNode*,Unify_ECR*>::const_iterator m=_ecr.begin(); m!=_ecr.end();
03437       m++)
03438     if(m->second) r.insert(m->second->root());
03439   return r;
03440 } // unique_ecr
03441 
03442 
03443 void UnificationBasedPtr::print_ecr() {
03444   cout << "all Unify_ECR:\n";
03445   set<Unify_ECR*> all_ecrs=Unify_ECR::allECR(), vars;
03446   set<UnifyType*> type_printed;
03447   map<UnifyType*,decl_list> points_to; // what points to same obj?
03448 
03449   for(map<declNode*, Unify_ECR*>::iterator m=_ecr.begin(); m!=_ecr.end(); m++) {
03450 #define print_one_ecr(E) \
03451   (E)->print(); \
03452   cout << endl;
03453 
03454     Unify_ECR *E = m->second;
03455     assert(E && m->first);
03456     if(m->first->decl_location() == declNode::TOP && E->var() != m->first) {
03457       assert(_ecr.find(E->var()) != _ecr.end());
03458       continue;
03459     }
03460 
03461     cout << "  ";
03462     if(m->first->decl_location() == declNode::TOP) cout << "(global)::";
03463     cout << m->first->name() << "(";
03464     if(E->proc() && E->proc()->decl()!=E->var())
03465       cout << E->proc()->decl()->name() << ".";
03466     if(E->var()->type() && E->var()->type()->is_ellipsis() ||
03467        is_va_list(E->var()))
03468       cout << "<...>: ";
03469     else
03470       cout << E->var()->name() <<"): ";
03471     print_one_ecr(E)
03472     type_printed.insert(E->type());
03473 
03474     vars.insert(E);
03475 //debug  all_ecrs.erase(E);
03476 
03477     UnifyType *ty = E->type();
03478     if(ty->objTyp()==OBJECT || ty->objTyp()==SIMPLE) {
03479       if(ty->objTyp()==OBJECT)
03480         ty = ty->object()->alpha->tao()->type();
03481       else
03482         ty = ty->simple()->alpha->tao()->type();
03483       points_to[ty].push_back(m->first);
03484     }
03485   }
03486 
03487 #ifdef cx_vt
03488 for(set<Unify_ECR*>::iterator e=all_ecrs.begin(); e!=all_ecrs.end(); e++)
03489   if((*e)->type()->id() == vt_e) {
03490     check_28920 = true;
03491     (*e)->print();
03492     check_28920 = false;
03493   }
03494 for(map<declNode*, Unify_ECR*>::iterator m=_ecr.begin(); m!=_ecr.end(); m++) {
03495   if(m->first->type() && m->first->type()->typ() == Array &&
03496      m->first->decl_location() != declNode::FORMAL) {
03497     Unify_ECR *parent = m->second;
03498     if(parent->type()->objTyp() != SIMPLE && parent->type()->objTyp() !=OBJECT)
03499       cout << m->first->name() << "@" << m->first->coord() << " " << *parent
03500            << endl;
03501     is_Sim_Obj(parent->type());
03502     Unify_ECR *child = Sim_Obj_Alpha(parent->type())->tao();
03503     set<Unify_ECR*> parents = parentsOf(child->type());
03504     bool contain_parent = false;
03505     for(set<Unify_ECR*>::iterator p=parents.begin(); p!=parents.end(); p++)
03506       if((*p)->type() == parent->type()) { contain_parent=true; break; }
03507 if(m->first->name() == "switches")
03508   cout << "switches " << *parent << " child " << *child << " contain "
03509        << contain_parent << endl;
03510     if(!contain_parent) {
03511       vt_e = child->type()->id();
03512       vt = parent->type()->id();
03513       cout << *child << " does not contain parent " << *parent << endl;
03514       check_28920 = true;
03515       child->print();
03516       check_28920 = false;
03517     }
03518   }
03519 }
03520 #endif
03521 
03522 
03523   map<int,int> n_src; // statistics: how many objects have n pointers to it?
03524   // print vars that points to same object.
03525   for(map<UnifyType*,decl_list>::iterator p=points_to.begin();
03526       p!=points_to.end(); p++)
03527     if(p->second.size() > 1) {
03528       for(decl_list_p d=p->second.begin(); d!=p->second.end(); d++)
03529         cout << (*d)->name() << ",";
03530       cout << " point-to " << * p->first << endl;
03531       n_src[p->second.size()] ++;
03532     } else n_src[1]++;
03533 
03534   // print more types
03535   for(set<Unify_ECR*>::iterator e=all_ecrs.begin(); e!=all_ecrs.end(); e++) {
03536     if(type_printed.find((*e)->type()) != type_printed.end()) continue;
03537     type_printed.insert((*e)->type());
03538     cout << "  ";
03539     print_one_ecr(*e)
03540   }
03541 
03542   /* print root chains
03543   cout << "ECR roots: ";
03544   for(set<ECR*>::iterator e=vars.begin(); e!=vars.end(); e++) {
03545     ECR *p = *e;
03546     cout << "(";
03547     while(p) {
03548       cout << p->id();
03549       p = p->parent();
03550       if(p) cout << " ";
03551     }
03552     cout << ") ";
03553   }
03554   cout << endl;*/
03555 
03556   // print statistic: n_src
03557   cout << "#ptrs to one obj  #such objs\n"
03558        << "----------------  ----------\n";
03559   for(map<int,int>::iterator m=n_src.begin(); m!=n_src.end(); m++)
03560     cout << m->first << "\t\t\t" << m->second << endl;
03561 
03562   cout << "number of tmp vars created by dismantler = " << _dismantler_tmp
03563        << endl;
03564 //exit(1);
03565 } // print_ecr
03566 
03567 
03568 bool UnificationBasedPtr::is_va_list(declNode * decl) {
03569   // -- Look for }variables whose type is typedef va_list
03570 
03571   if (decl->type() && (decl->type()->typ() == Tdef)) {
03572     string name = ((tdefNode *) decl->type())->name();
03573     if (name == "va_list")
03574     return true;
03575     if (name == "__builtin_va_alist_t")
03576       return true;
03577     if (name == "__gnuc_va_list")
03578       return true;
03579   }
03580 
03581   return false;
03582 } // is_va_list
03583 
03584 
03585 procNode *UnificationBasedPtr::create_synthetic_proc(declNode * decl) {
03586 //cout << "new synthetic proc " << decl->name() << "@" << decl->coord() << endl;
03587   if(_synthetic_proc[decl]) return _synthetic_proc[decl];
03588   assert(decl->type() && decl->type()->typ()==Func);
03589   procNode *new_proc = _synthetic_proc[decl] = new procNode(decl, NULL);
03590   if(! ((funcNode*)decl->type())->returns()->is_void()) {
03591     declNode *ret = new declNode("__ret", declNode::NONE,
03592                                  ((funcNode*)decl->type())->returns(),
03593                                  NULL, NULL);
03594     new_proc->return_decl( ret );
03595   }
03596   return new_proc;
03597 } // create_synthetic_proc
03598 
03599 UnificationBasedPtr *UnificationBasedPtr::analyze_all(Linker &linker) {
03600   cbzTimer unify_timer;
03601   unify_timer.start();
03602   UnificationBasedPtr *U = new UnificationBasedPtr(linker);
03603   for(unit_list_p u=CBZ::Program.begin(); u!=CBZ::Program.end(); u++)
03604     (*u)->walk(*U);
03605   U->finalize();
03606   unify_timer.stop();
03607   double t(unify_timer);
03608   cout << "STAT-unification-time              " << t << endl;
03609   return U;
03610 }
03611 
03612 // ==============================================================
03613 
03614 class testUnify : public Phase {
03615   void run() {
03616     CBZ::PrintLineOffset = true;
03617     Linker linker;
03618     linker.link();
03619     UnificationBasedPtr *U = UnificationBasedPtr::analyze_all(linker);
03620     cout << "UnificationBasedPtr done\n";
03621     U->print_ecr();
03622 
03623     /*
03624     set<ECR*> ecrs = U->unique_ecr();
03625     for(set<ECR*>::iterator e=ecrs.begin(); e!=ecrs.end(); e++) {
03626       cout << "ECR: ";
03627       decl_list vars = (*e)->all_decls();
03628       for(decl_list_p v=vars.begin(); v!=vars.end(); v++) {
03629         ECR *ve = U->ecr(*v);
03630         if(ve->proc()) cout << ve->proc()->decl()->name() << ".";
03631         cout << (*v)->name() << ", ";
03632       }
03633       cout << endl;
03634     }*/
03635     cout << "unify done\n";
03636   }
03637 };
03638 
03639 Phases unify_phase("unify", new testUnify());
03640 
03641 
03642 // to-do
03643 // - distinguishable components of struct. section~3, eg. in fig 1

Generated on August 27, 2003
Back to the C-Breeze home page