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  

memorymodel.cc

Go to the documentation of this file.
00001 // $Id: memorymodel.cc,v 1.26 2003/08/08 15:16:29 toktb Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Daniel A. Jimenez
00011 //  Calvin Lin
00012 // 
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //  
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //  
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
00035 //
00036 // ----------------------------------------------------------------------
00037 
00038 #include "c_breeze.h"
00039 #include "ref_clone_changer.h"
00040 #include "memorymodel.h"
00041 #include "memoryblock.h"
00042 
00043 // ----------------------------------------------------------------------
00044 // Create a new memory model
00045 // ----------------------------------------------------------------------
00046 
00047 memoryModel::memoryModel()
00048   : _memory_blocks(),
00049     _ci_memory_blocks(),
00050     _string_constants(),
00051     Counter(0),
00052     Null(0),
00053     _string_constant(0),
00054     _unification_based(0)
00055 {
00056   // -- Create the special "null" object
00057 
00058   declNode * null_decl = new declNode("null",
00059                                       declNode::NONE,
00060                                       (typeNode *)0,
00061                                       (exprNode *)0,
00062                                       (exprNode *)0);
00063 
00064   Null = new memoryBlock(null_decl, true, (memoryBlock *)0, (procNode *)0);
00065 
00066   // -- Don't allow "null" to be modified
00067 
00068   Null->set_write_protected();
00069 
00070   pointerOptions::Unify_objects = 0; // TB_unify
00071 }
00072 
00073 memoryModel::~memoryModel()
00074 {
00075   // Delete all the memory blocks
00076 
00077   for (proc_memorymodel_map_p q = _memory_blocks.begin();
00078        q != _memory_blocks.end();
00079        ++q)
00080     {
00081       memorymodel_map & mm = (*q).second;
00082 
00083       for (memorymodel_map_p p = mm.begin();
00084            p != mm.end();
00085            ++p) {
00086         if(p->second->unifyType()) { // TB_unify
00087           set<procNode*> procs = p->second->unifyType()->procs();
00088           for(set<procNode*>::iterator q=procs.begin(); q!=procs.end(); q++)
00089             if(_unification_based->proctype(*q))
00090               _unification_based->proctype(*q)->block(NULL);
00091          }
00092         delete (*p).second;
00093       }
00094     }
00095 
00096   for (ci_memorymodel_map_p p = _ci_memory_blocks.begin();
00097        p != _ci_memory_blocks.end();
00098        ++p) {
00099     if(p->second->unifyType()) { // TB_unify
00100       for(set<procNode*>::iterator q=p->second->unifyType()->procs().begin();
00101           q!=p->second->unifyType()->procs().end(); q++) // TB_unify
00102         if(_unification_based->proctype(*q))
00103           _unification_based->proctype(*q)->block(NULL);
00104     }
00105     delete (*p).second;
00106   }
00107 
00108   // Delete the null object
00109 
00110   delete Null;
00111 }
00112 
00113 void memoryModel::clear()
00114 {
00115   for (proc_memorymodel_map_p q = _memory_blocks.begin();
00116        q != _memory_blocks.end();
00117        ++q)
00118     {
00119       memorymodel_map & mm = (*q).second;
00120 
00121       for (memorymodel_map_p p = mm.begin();
00122            p != mm.end();
00123            ++p)
00124         (*p).second->clear();
00125     }
00126 
00127   for (ci_memorymodel_map_p p = _ci_memory_blocks.begin();
00128        p != _ci_memory_blocks.end();
00129        ++p)
00130     (*p).second->clear();
00131 
00132   Null->clear();
00133 }
00134 
00135 int memoryModel::size()
00136 {
00137   int size = 0;
00138 
00139   for (proc_memorymodel_map_p q = _memory_blocks.begin();
00140        q != _memory_blocks.end();
00141        ++q)
00142     {
00143       memorymodel_map & mm = (*q).second;
00144 
00145       size += mm.size();
00146     }
00147 
00148   return size;
00149 }
00150 
00151 // ----------------------------------------------------------------------
00152 //   Look up memoryBlocks
00153 // ----------------------------------------------------------------------
00154 
00155 memoryBlock * memoryModel::lookup_variable(Location * location,
00156                                            declNode * decl,
00157                                            procNode * local_to)
00158 {
00159   // For local variables, we use the location as part of the index. For
00160   // global variables, set the location and local_to to NULL.
00161 
00162   procNode * owner = 0;
00163   Location * owner_loc = 0;
00164   bool is_array = false;
00165   bool is_struct_init = false;
00166   typeNode * ty = 0;
00167 
00168   if (decl) {
00169 
00170     // -- Local variables: make sure to exclude static local variables
00171     // which behave like globals.
00172 
00173     if (((decl->decl_location() == declNode::BLOCK) ||
00174          (decl->decl_location() == declNode::FORMAL)) &&
00175         (decl->storage_class() != declNode::STATIC))
00176       {
00177         owner = local_to;
00178         owner_loc = location;
00179       }
00180 
00181     ty = decl->no_tdef_type();
00182     if (ty && (ty->typ() == Array) &&
00183         (decl->decl_location() != declNode::FORMAL))
00184       is_array = true;
00185 
00186     if (ty && (ty->typ() == Struct) && decl->init())
00187       is_struct_init = true;
00188   }
00189 
00190   // See if it's already there
00191 
00192   memoryBlock * result = 0;
00193 
00194   if (pointerOptions::Context_insensitive_memory)
00195     result = lookup((stmtNode *)0, decl);
00196   else
00197     result = lookup(owner_loc, decl);
00198 
00199   if (result)
00200     return result;
00201 
00202   // --- Not found; create a new one. For local variables and formal
00203   // parameters, record the owning procedure.
00204 
00205   if (pointerOptions::Context_insensitive_memory)
00206     result = create_memory_object((stmtNode *)0, decl, false, 
00207                                   (memoryBlock *) 0, owner);
00208   else
00209     result = create_memory_object(owner_loc, decl, false, 
00210                                   (memoryBlock *) 0, owner);
00211 
00212   // -- Handle unification
00213 
00214   if(pointerOptions::Unification || _unification_based)
00215     result->set_unification(pointerOptions::Non_unify_types);
00216 
00217   // -- Handle flow sensitivity
00218 
00219   result->set_flow_sensitivity(pointerOptions::Flow_sensitive_objects);
00220 
00221   // --- Special case: for locally declared arrays, we need to create
00222   // memory blocks that represent the elements. For now, we'll have one
00223   // memory block for each dimension in the array.
00224 
00225   if (is_array)
00226     generate_array_elements_for(result);
00227 
00228   if (is_struct_init) {
00229     expr_list inits;
00230     inits.push_back(decl->init());
00231 
00232     sueNode * sue = (sueNode *) decl->no_tdef_type();
00233     initialize_struct(result, sue, inits);
00234   }
00235 
00236   return result;
00237 }
00238 
00239 memoryBlock *  memoryModel::lookup_heap_object(const string & name,
00240                                                stmtLocation * allocation_site,
00241                                                stmtNode * allocation_stmt,
00242                                                declNode * decl,
00243                                                bool synthetic_decl)
00244 {
00245   // -- Look up the block
00246 
00247   memoryBlock * result = 0;
00248 
00249   if (0) // pointerOptions::Context_insensitive_memory)
00250     result = lookup(allocation_stmt, decl);
00251   else
00252     result = lookup(allocation_site, decl);
00253 
00254   if (result)
00255     return result;
00256 
00257   /*
00258   // --- Not found; create a new one.
00259 
00260   declNode * the_decl = decl;
00261 
00262   if (synthetic_decl) {
00263 
00264     // -- Copy the synthetic declaration so there's no sharing. Otherwise,
00265     // we'll crash in the memoryBlock destructor.
00266 
00267     the_decl = new declNode(decl->name().c_str(),
00268                             declNode::NONE,
00269                             (typeNode *)0,
00270                             (exprNode *)0,
00271                             (exprNode *)0);
00272   }
00273   */
00274 
00275   if (0) // pointerOptions::Context_insensitive_memory)
00276     result = create_memory_object(allocation_stmt, decl, synthetic_decl, 0, 0,
00277                                   true);
00278   else
00279     result = create_memory_object(allocation_site, decl, synthetic_decl, 0, 0,
00280                                   0, true);
00281 
00282   // -- Flag the object as a heap object
00283 
00284   result->set_heap_object(allocation_site);
00285 
00286   // -- Force the name
00287 
00288   // result->set_name(name);
00289 
00290   // -- Handle unification
00291 
00292   if(pointerOptions::Unification || _unification_based)
00293     result->set_unification(pointerOptions::Non_unify_types);
00294 
00295   // -- Handle flow sensitivity: NOTE: make sure we do this *after* setting
00296   // the heap allocation flag above.
00297 
00298   result->set_flow_sensitivity(pointerOptions::Flow_sensitive_objects);
00299 
00300   return result;
00301 }
00302 
00307 memoryBlock * memoryModel::lookup_string_constant(constNode * the_string)
00308 {
00309   memoryBlock * result = 0;
00310 
00311   if (pointerOptions::One_string_constant) {
00312 
00313     if ( ! _string_constant) {
00314 
00315       // -- Make the one string constant object
00316       string fullname("__string_constant");
00317 
00318       declNode * the_decl = new declNode(fullname.c_str(),
00319                                          declNode::NONE,
00320                                          (typeNode *)0,
00321                                          (exprNode *)0,
00322                                          (exprNode *)0);
00323 
00324       // -- Create a memoryBlock
00325 
00326       bool is_synthetic = true;
00327 
00328       _string_constant = new memoryBlock(the_decl, is_synthetic,
00329                                          (memoryBlock *)0, (procNode *)0);
00330     
00331       // -- The contents of string constants are not modifiable
00332 
00333       _string_constant->set_write_protected();
00334       _string_constant->set_flow_insensitive();
00335     }
00336 
00337     result = _string_constant;
00338   }
00339   else {
00340 
00341     // -- Per-string constants: look them up by constNode
00342 
00343     string_constant_map_p p = _string_constants.find(the_string);
00344     if (p == _string_constants.end()) {
00345 
00346       // -- Not there, create a synthetic declaration for it
00347 
00348       char buf[50];
00349       
00350       sprintf(buf, "_%d", Counter);
00351       Counter++;
00352 
00353       string fullname = string("__string_#") + buf;
00354       
00355       declNode * the_decl = new declNode(fullname.c_str(),
00356                                          declNode::NONE,
00357                                          (typeNode *)0,
00358                                          (exprNode *)0,
00359                                          (exprNode *)0);
00360       
00361       // -- Create a memoryBlock
00362       
00363       bool is_synthetic = true;
00364       
00365       Unify_ECR *ecr = NULL;
00366       if(pointerOptions::Unification) {
00367         Alpha *alpha = _unification_based->string_alpha(the_string);
00368         if(alpha) {
00369           Unify_ECR *ecr = alpha->tao();
00370           if(ecr) result = ecr->type()->block();
00371         }
00372       }
00373 
00374       if(! result) {
00375         result = new memoryBlock(the_decl, is_synthetic,
00376                                  (memoryBlock *)0, (procNode *)0);
00377         if(ecr) {
00378           ecr->type()->block(result);
00379           result->unifyType(ecr->type());
00380         }
00381       }
00382       
00383       // -- Store it in the mapping
00384       
00385       _string_constants[the_string] = result;
00386       
00387       // -- The contents of string constants are not modifiable
00388       
00389       result->set_write_protected();
00390       result->set_flow_insensitive();
00391     }
00392     else {
00393       
00394       // -- It's there, so return it
00395       
00396       result = (*p).second;
00397     }
00398   }
00399 
00400   if (result == 0) {
00401     cout << "THIS IS BAD" << endl;
00402     abort();
00403   }
00404 
00405   return result;
00406 }
00407 
00408 memoryBlock * memoryModel::generate_su_field(const string & field_name,
00409                                              declNode * field_decl,
00410                                              memoryBlock * container)
00411 {
00412   // -- Set up the name as the concatenation of the container name plus the
00413   // field name
00414 
00415   string field_obj_name;
00416 
00417   if (field_decl)
00418     field_obj_name = field_decl->name(); // container->generate_su_field_name(field_decl->name());
00419   else
00420     field_obj_name = field_name; // container->generate_su_field_name(field_name);
00421 
00422   // -- Copy the field declaration so that we get a unique field object for
00423   // each struct/union.
00424 
00425   typeNode * type = 0;
00426   if (field_decl)
00427     type = (typeNode *) ref_clone_changer::clone(field_decl->type(), false);
00428   
00429   declNode * copy_decl = new declNode(field_obj_name.c_str(),
00430                                       declNode::NONE,
00431                                       type,
00432                                       (exprNode *)0,
00433                                       (exprNode *)0);
00434 
00435   if(field_decl) _copy_decl[copy_decl] = field_decl; // TB_unify
00436 
00437   // -- Create the new object, with the container argument
00438 
00439   memoryBlock * field =  create_memory_object((Location *)0, copy_decl, true,
00440                                               container, (procNode *)0,
00441                                               field_decl);
00442 
00443   // -- Handle unification
00444 
00445   if(pointerOptions::Unification || _unification_based)
00446     field->set_unification(pointerOptions::Non_unify_types);
00447 
00448   // -- Handle flow sensitivity
00449 
00450   field->set_flow_sensitivity(pointerOptions::Flow_sensitive_objects);
00451 
00452   // -- Handle fields that are arrays
00453 
00454   bool recursive_array = false;
00455   // if we're in unification mode and adaptation after 1st pass, and if the
00456   // container is not unified, it is possible that the field array's element is
00457   // actually the same as the container. If we now create new element, we would
00458   // end up with field[].field[].field[]....
00459   if(_unification_based && !pointerOptions::Unification &&
00460       !container->unifyType() ) {
00461     // check if the container is field[]. If so, do not create field[].field[].
00462     if(container->container() &&
00463        _copy_decl[container->container()->decl()] == field_decl)
00464       recursive_array = true;
00465   }
00466 
00467   if (field_decl &&
00468       field_decl->type() &&
00469       (field_decl->no_tdef_type()->typ() == Array) &&
00470       (! pointerOptions::Unification || /* TB */
00471        field_decl->decl_location() != declNode::SU) &&
00472       // are we in adaptation mode?
00473       (!(_unification_based && !pointerOptions::Unification) ||
00474        _unification_based->ecr(field_decl) ||
00475        !container->unifyType() && !recursive_array) ) {
00476     // explanation of above: proceed only if we're not running with
00477     // unification mode, or if we're in adaptation mode after 1st pass
00478     // (unify), there must be an ecr for the field (ie. field is in annotation,
00479     // or the container itself is not unified and no recursive array is
00480     // detected. Why: if proceed under the last conditions, there will be no
00481     // bound on the objects created e.g.  field[].field[].field[].....
00482 if(! pointerOptions::Unification &&
00483    field_decl->decl_location() == declNode::SU &&
00484    container->unifyType()) { // debug
00485   cout << "field_decl @" << field_decl->coord() << endl;
00486   if(_unification_based->ecr(field_decl))
00487     cout << * _unification_based->ecr(field_decl) << endl;
00488   cout << field << " field " << field->name() << endl;
00489   if(field->unifyType()) cout << * field->unifyType() << endl;
00490   cout << container << " container " << container->name() << endl;
00491   if(container->unifyType()) cout << * container->unifyType() << endl;
00492   pointerOptions::Verbose = true;
00493 }
00494     generate_array_elements_for(field);
00495 if(! pointerOptions::Unification &&
00496    field_decl->decl_location() == declNode::SU &&
00497    container->unifyType()) { // debug
00498 cout << "after generate_array_elemement\n";
00499 exit(1);
00500 }
00501   }
00502 
00503   return field;
00504 }
00505 
00506 // ----------------------------------------------------------------------
00507 //  Private methods
00508 // ----------------------------------------------------------------------
00509 
00510 memoryBlock * memoryModel::create_memory_object(Location * location,
00511                                                 declNode * decl,
00512                                                 bool synthetic_decl,
00513                                                 memoryBlock * container,
00514                                                 procNode * local_to,
00515                                                 declNode * org_field_decl,
00516                                                 bool is_alloc,
00517                                                 bool is_array_elt)
00518 {
00519   procNode * owner = 0;
00520 
00521   if (!decl)
00522     cout << "WARNING: Creating memoryBlock with no declaration." << endl;
00523 
00524   // --- Inherit the owner from the container, when appropriate
00525 
00526   if (container)
00527     owner = container->local_to();
00528   else
00529     owner = local_to;
00530 
00531   // --- Create the memory block. 
00532 
00533   memoryBlock * result = NULL;
00534   bool brand_new = false;
00535 
00536   Unify_ECR *ecr = NULL;
00537   if(_unification_based) {
00538     if(is_alloc) {
00539       stmtNode *site = ((stmtLocation*)location)->stmt();
00540       if(site->typ() == ThreeAddr) {
00541         ecr = _unification_based->ecr((threeAddrNode*) site);
00542       } else {
00543         ecr = _unification_based->ecr(decl);
00544       }
00545       assert(ecr);
00546     } else {
00547       ecr = _unification_based->ecr(decl);
00548       if(!ecr) {
00549         bool field_from_annotation = false;
00550         if(org_field_decl &&
00551            _unification_based->isField(org_field_decl, field_from_annotation)) {
00552 /*if (pointerOptions::Verbose) {
00553 cout << "container = " << container << " " << container->name() << " field="
00554      << org_field_decl->name() << " @" << org_field_decl->coord();
00555 if(container->unifyType()) cout << " " << *container->unifyType()->ecr();
00556 cout << endl;
00557 }*/
00558           ecr = _unification_based->ecrField(container->unifyType(),
00559                                              org_field_decl,
00560                                              field_from_annotation);
00561 /*if (pointerOptions::Verbose)
00562 if(container->unifyType())
00563 cout << "ecrField, struct " << container->name() << " now: "
00564      << *container->unifyType()->ecr() << endl; */
00565         } else if(is_array_elt && container->unifyType()) {
00566           // note: container has no unifyType if itself was created by
00567           // annotation.
00568           assert(container);
00569 /*if (pointerOptions::Verbose)
00570 cout << "array elt for " << decl->name()
00571      << " b4: " << * container->unifyType()->ecr() << endl;*/
00572           ecr = _unification_based->ecrDeref(container->unifyType());
00573 /*if (pointerOptions::Verbose)
00574 cout << " now: " << * container->unifyType()->ecr() << endl;*/
00575         }
00576       }
00577     }
00578 
00579     if(ecr) {
00580       bool non_unify;
00581       if(decl &&
00582          (decl->decl_location()==declNode::PROC ||
00583           decl->no_tdef_type() &&
00584           (decl->no_tdef_type()->typ() == Func ||
00585            decl->no_tdef_type()->typ() == Ptr &&
00586            decl->no_tdef_type()->no_tdef_type()->typ()==Func)))
00587         non_unify = true;
00588       else if(!pointerOptions::Unification) {
00589         if(is_alloc) {
00590           assert(location->kind() == Location::Statement);
00591           non_unify = is_in_non_unify_list(pointerOptions::Non_unify_types,
00592                                            ecr->type());
00593         } else if(container)
00594           non_unify = is_in_non_unify_list(pointerOptions::Non_unify_types,
00595                                            ecr->type());
00596         else
00597           non_unify = is_in_non_unify_list(pointerOptions::Non_unify_types,
00598                                            ecr->type());
00599       } else non_unify = false;
00600       if(non_unify) ecr=NULL; // do not use
00601     }
00602 
00603     if(ecr) {
00604       if(ecr->type()->is_bottom())
00605         _unification_based->ensure_no_bottom(ecr, decl, container ?
00606                                                         container->unifyType() :
00607                                                         NULL);
00608       result = ecr->type()->block();
00609     }
00610 
00611 /*else if (pointerOptions::Verbose) {
00612   cout << "no ecr for " << decl->name() << endl;
00613   if(container) {
00614     cout << "  container " << container << " " << container->name() << endl;
00615     if(container->unifyType())
00616       cout << "  container type " << * container->unifyType() << endl;
00617   }
00618   if(org_field_decl) {
00619     bool dummy;
00620     cout << "  is field @" << org_field_decl->coord() << " "
00621          << _unification_based->isField(org_field_decl, dummy)
00622          << endl;
00623   }
00624 }*/
00625   }
00626 
00627   if(!result) {
00628     result = new memoryBlock(decl, synthetic_decl, container, owner);
00629     if (pointerOptions::Verbose || pointerOptions::Show_stack) {
00630       cout << "new memoryBlock " << result << " for " << decl->name() << ": "
00631            << result->name() << endl;
00632       if (pointerOptions::Verbose)
00633         if(ecr) cout << "   ecr " << *ecr << endl;
00634     }
00635     brand_new = true;
00636     if(ecr) result->unifyType(ecr->type());
00637   }
00638 
00639   if(ecr && !ecr->type()->block())
00640     ecr->type()->block(result);
00641 
00642   // --- Add it to the model
00643 
00644   if(brand_new) {
00645     procNode * proc = 0;
00646 
00647     if (location)
00648       proc = Location::procedure(location)->proc();
00649     memorymodel_map & mm = _memory_blocks[proc];
00650 
00651     memorymodel_key key(location, decl);
00652     mm[key] = result;
00653   }
00654 
00655   return result;
00656 }
00657 
00658 // Context_insensitive_memory
00659 memoryBlock * memoryModel::create_memory_object(stmtNode * location,
00660                                                 declNode * decl,
00661                                                 bool synthetic_decl,
00662                                                 memoryBlock * container,
00663                                                 procNode * local_to,
00664                                                 bool is_alloc)
00665 {
00666   procNode * owner = 0;
00667 
00668   if (!decl)
00669     cout << "WARNING: Creating memoryBlock with no declaration." << endl;
00670 
00671   // --- Inherit the owner from the container, when appropriate
00672 
00673   if (container)
00674     owner = container->local_to();
00675   else
00676     owner = local_to;
00677 
00678   // --- Create the memory block. 
00679 
00680   memoryBlock * result = NULL;
00681   bool brand_new = false;
00682 
00683   Unify_ECR *ecr = NULL;
00684   if(_unification_based) {
00685     ecr = _unification_based->ecr(decl);
00686     if(ecr && !pointerOptions::Unification) {
00687       bool non_unify;
00688       assert(! is_alloc);
00689       if(decl &&
00690          (decl->decl_location()==declNode::PROC ||
00691           decl->no_tdef_type() &&
00692           (decl->no_tdef_type()->typ() == Func ||
00693            decl->no_tdef_type()->typ() == Ptr &&
00694            decl->no_tdef_type()->no_tdef_type()->typ()==Func)))
00695         non_unify = true;
00696       else if(container)
00697         non_unify = is_in_non_unify_list(pointerOptions::Non_unify_types,
00698                                          ecr->type());
00699       else
00700         non_unify = is_in_non_unify_list(pointerOptions::Non_unify_types,
00701                                          ecr->type());
00702       if(non_unify) ecr=NULL; // do not use
00703     }
00704 
00705     if(ecr) result = ecr->type()->block();
00706   }
00707 
00708   if(!result) {
00709     result = new memoryBlock(decl, synthetic_decl, container, owner);
00710     brand_new = true;
00711     if(ecr) result->unifyType(ecr->type());
00712   }
00713 
00714   if(ecr && !ecr->type()->block())
00715     ecr->type()->block(result);
00716 
00717   // --- Add it to the model
00718 
00719   if(brand_new) {
00720     ci_memorymodel_key key(location, decl);
00721     _ci_memory_blocks[key] = result;
00722   }
00723 
00724   return result;
00725 }
00726 
00744 void memoryModel::generate_array_elements_for(memoryBlock * array_object)
00745 {
00746   declNode * decl = array_object->decl();
00747 
00748   if (decl) {
00749     typeNode * curtype = array_object->decl()->no_tdef_type();
00750     memoryBlock * curblock = array_object;
00751     expr_list inits;
00752 
00753     // -- Handle initializers: this won't be perfect because it assumes
00754     // that the structure of the initializer matches the shape of the type
00755     // (which isn't strictly required by C semantics).
00756 
00757     if (decl->init() &&
00758         (decl->init()->typ() == Initializer))
00759       {
00760         initializerNode * initializer = (initializerNode *) decl->init();
00761         inits.push_back(initializer);
00762       }
00763 
00764     string suffix("[]");
00765 
00766     // -- Loop over all the dimensions of the array
00767 
00768     while (curtype && (curtype->typ() == Array)) {
00769 
00770       // -- Create a synthetic declNode to represent the array element (get
00771       // the type right).
00772 
00773       typeNode * type_clone = (typeNode *) ref_clone_changer::clone(curtype->type(), false);
00774 
00775       string name = decl->name() + suffix;
00776 
00777       declNode * fake_decl = new declNode(name.c_str(),
00778                                           declNode::NONE,
00779                                           type_clone,
00780                                           (exprNode *)0,
00781                                           (exprNode *)0);
00782 
00783       if(decl) _copy_decl[fake_decl] = decl; // TB_unify
00784 
00785       // -- Create a new memory object using the fake declaration. Set up
00786       // the new object as the array element of the block above it.
00787 
00788       memoryBlock * contents = create_memory_object((Location *)0, fake_decl, true,
00789                                                     curblock, (procNode *)0,
00790                                                     0, false, true);
00791 
00792       curblock->set_array_element(contents);
00793 
00794       // -- This object represents all elements:
00795 
00796       contents->set_indexed();
00797 
00798       // -- Handle unification
00799 
00800       if(pointerOptions::Unification || _unification_based)
00801         contents->set_unification(pointerOptions::Non_unify_types);
00802 
00803       // -- Handle flow sensitivity
00804 
00805       contents->set_flow_sensitivity(pointerOptions::Flow_sensitive_objects);
00806 
00807       // -- Move down in the initializer structure (probably not the most
00808       // efficient algorithm).
00809 
00810       expr_list new_inits;
00811       for (expr_list_p ip = inits.begin();
00812            ip != inits.end();
00813            ++ip)
00814         {
00815           exprNode * expr = (*ip);
00816           if (expr->typ() == Initializer) {
00817             initializerNode * initializer = (initializerNode *) expr;
00818             new_inits.insert(new_inits.end(),
00819                              initializer->exprs().begin(),
00820                              initializer->exprs().end());
00821           }
00822         }
00823 
00824       inits = new_inits;
00825       
00826       // -- Go to the next nesting level
00827     
00828       curtype = curtype->no_tdef_type();
00829       curblock = contents;
00830       suffix = suffix + "[]";
00831     }
00832 
00833     if (curtype &&
00834         ( ! inits.empty())) {
00835 
00836       if (pointerOptions::Verbose)
00837         cout << "FOUND initializers for " << array_object->name() << endl;
00838 
00839       if (curtype->typ() == Struct) {
00840         initialize_struct(curblock, (sueNode *) curtype, inits);
00841       }
00842       else {
00843 
00844         // -- Initialize an array
00845         
00846         for (expr_list_p p = inits.begin();
00847              p != inits.end();
00848              ++p)
00849           {
00850             exprNode * the_init = (*p);
00851             idNode * id = 0;
00852             bool is_addr = false;
00853             
00854             if (the_init->typ() == Id)
00855               id = (idNode *) the_init;
00856 
00857             if (the_init->typ() == Unary) {
00858               unaryNode * un = (unaryNode *) the_init;
00859               if (un->expr()->typ() == Id)
00860                 id = (idNode *) un->expr();
00861               is_addr = (un->op()->id() == Operator::ADDRESS);
00862             }
00863 
00864             if (id) {
00865 
00866               declNode * decl_init = id->decl();
00867               
00868               if (decl_init) {
00869                 
00870                 if(decl_init->type()->typ() == Func)
00871                   is_addr = true; //treat func as addr
00872                 
00873                 memoryBlock * rhs = lookup_variable((Location *)0,
00874                                                     decl_init,
00875                                                     (procNode *)0);
00876                 if (pointerOptions::Verbose)
00877                   cout << "Array init: Assign " << curblock->name() << " = " << rhs->name() << endl;
00878                 
00879                 memoryblock_set temp;
00880                 if(is_addr)
00881                   temp.insert(rhs);
00882                 else { // TB new. import from assignment_operator.
00883                   memoryUse * right_use = rhs->current_use();
00884                   if ( ! right_use)
00885                     right_use = rhs->use_at(procLocation::main());
00886                   memoryDef * rd = right_use->reaching_def();
00887                   if (rd) {
00888                     const memoryblock_set & rd_points_to = rd->points_to();
00889                     temp.insert(rd_points_to.begin(), rd_points_to.end());
00890                   }
00891 
00892                   // TB_unify
00893                   if(pointerOptions::Unification && _unification_based) {
00894                     UnifyType *right_type = rhs->unifyType();
00895                     if(right_type &&
00896                        (right_type->objTyp()==SIMPLE || right_type->objTyp()==OBJECT)) {
00897                       Unify_ECR *defer = _unification_based->ecrDeref(right_type);
00898                       if(defer && defer->type()->block())
00899                         temp.insert( defer->type()->block() );
00900                     }
00901                   }
00902                 }
00903 
00904                 bool ignore;
00905                 memoryDef *def = curblock->def_at(procLocation::main(), ignore);
00906                 def->add_pointers(temp);
00907               }
00908             }
00909           }
00910       }
00911     }
00912   }
00913 }
00914  
00915 // --- Lookup an object, returning null if one doesn't exist
00916 
00917 memoryBlock * memoryModel::lookup(Location * location, declNode * decl)
00918 {
00919   procNode * proc = 0;
00920 
00921   if (location)
00922     proc = Location::procedure(location)->proc();
00923 
00924   memorymodel_map & mm = _memory_blocks[proc];
00925 
00926   memorymodel_key key(location, decl);
00927 
00928   memorymodel_map_p p = mm.find(key);
00929   if (p != mm.end())
00930     return (*p).second;
00931   else
00932     return 0;
00933 }
00934 
00935 memoryBlock * memoryModel::lookup(stmtNode * location, declNode * decl)
00936 {
00937   ci_memorymodel_key key(location, decl);
00938 
00939   ci_memorymodel_map_p p = _ci_memory_blocks.find(key);
00940   if (p != _ci_memory_blocks.end())
00941     return (*p).second;
00942   else
00943     return 0;
00944 }
00945 
00946 bool memoryModel::is_in_non_unify_list(UnifyTypes & non_unify_types,
00947                                        UnifyType *obj)
00948 {
00949   assert(obj);
00950   UnifyTypes visited;
00951   return UnificationBasedPtr::reachable(obj, non_unify_types, visited);
00952 }
00953 
00954 
00955 
00956 // --- Update all the def-use chains at one time (only call this
00957 // once pointer analysis is complete)
00958 
00959 void memoryModel::update_def_use_chains()
00960 {
00961   // First pass: fix the def-use chains
00962 
00963   for (proc_memorymodel_map_p q = _memory_blocks.begin();
00964        q != _memory_blocks.end();
00965        ++q)
00966     {
00967       memorymodel_map & mm = (*q).second;
00968 
00969       for (memorymodel_map_p p = mm.begin();
00970            p != mm.end();
00971            ++p)
00972         ((*p).second)->update_def_use_chains();
00973     }
00974 
00975   for (ci_memorymodel_map_p p = _ci_memory_blocks.begin();
00976        p != _ci_memory_blocks.end();
00977        ++p)
00978     ((*p).second)->update_def_use_chains();
00979 
00980    // Second pass: prune out unnecessary defs and uses
00981   /*
00982   for (memorymodel_map_p p = _memory_blocks.begin();
00983        p != _memory_blocks.end();
00984        ++p)
00985     ((*p).second)->prune_defs_uses();
00986   */
00987 }
00988 
00989 // --- Print some statistics
00990 
00991 int num_defs_histogram[200];
00992 
00993 void memoryModel::stats(ostream & out)
00994 {
00995   out << "Memory model: " << endl;
00996   int block_count = _memory_blocks.size() + _ci_memory_blocks.size();
00997 
00998   out << "  memoryBlock : " << block_count << " objects x " 
00999       << sizeof(memoryBlock) << " bytes = " << block_count * sizeof(memoryBlock) 
01000       << " bytes. " << endl;
01001 
01002   long int global_defs = 0;
01003   long int global_merge_defs = 0;
01004   long int global_weak_defs = 0;
01005   long int global_uses = 0;
01006   long int global_merge_uses = 0;
01007 
01008   bool first = true;
01009 
01010   for (proc_memorymodel_map_p q = _memory_blocks.begin();
01011        q != _memory_blocks.end();
01012        ++q)
01013     {
01014       memorymodel_map & mm = (*q).second;
01015 
01016       for (memorymodel_map_cp p = mm.begin();
01017            p != mm.end();
01018            ++p)
01019         {
01020           memoryBlock * block = (*p).second;
01021           if (first) {
01022             block->stats(out, true,
01023                          global_defs, global_merge_defs, global_weak_defs,
01024                          global_uses, global_merge_uses);
01025             first = false;
01026           }
01027           block->stats(out, false,
01028                        global_defs, global_merge_defs, global_weak_defs,
01029                        global_uses, global_merge_uses);
01030         }
01031     }
01032 
01033   out << "-- Total def/use statistics ---- " << endl;
01034   out << "  Total defs:       " << global_defs << endl;
01035   out << "  Total merge defs: " << global_merge_defs << endl;
01036   out << "  Total weak defs:  " << global_weak_defs << endl;
01037   out << "  Total uses:       " << global_uses << endl;
01038   out << "  Total merge uses: " << global_merge_uses << endl;
01039 
01040   double d_defs = (double) global_defs;
01041   double d_weak = (double) global_weak_defs;
01042   double percent_weak = (d_weak / d_defs) * 100.0;
01043 
01044   out << "  Percent weak defs: " << percent_weak << endl;
01045   out << "-------------------------------- " << endl;
01046 
01047   /*
01048   for (int i = 0; i < 200; i++) num_defs_histogram[i] = 0;
01049 
01050   for (memorymodel_map_cp p = _memory_blocks.begin();
01051        p != _memory_blocks.end();
01052        ++p)
01053     {
01054       int index = ((*p).second)->num_defs();
01055       if (index > 199) index = 199;
01056       num_defs_histogram[index]++;
01057     }
01058 
01059   cout << " Number of defs/memoryBlock" << endl;
01060 
01061   for (int i = 0; i < 200; i++) {
01062     if (i%10 == 0)
01063       printf("\n%2d    ", i);
01064     printf("%5d ", num_defs_histogram[i]);
01065   }
01066   */
01067 }
01068 
01069 void memoryModel::print(ostream & o) const
01070 {
01071   for (proc_memorymodel_map_cp q = _memory_blocks.begin();
01072        q != _memory_blocks.end();
01073        ++q)
01074     {
01075       const memorymodel_map & mm = (*q).second;
01076 
01077       for (memorymodel_map_cp p = mm.begin();
01078            p != mm.end();
01079            ++p)
01080         ((*p).second)->print_def_use(o);
01081     }
01082 
01083   for (ci_memorymodel_map_cp p = _ci_memory_blocks.begin();
01084        p != _ci_memory_blocks.end();
01085        ++p)
01086     ((*p).second)->print_def_use(o);
01087 }
01088 
01093 void memoryModel::initialize_struct(memoryBlock * struct_object,
01094                                     sueNode * sue_type,
01095                                     expr_list & inits)
01096 {
01097   if (pointerOptions::Verbose)
01098     cout << "FOUND initializers for " << struct_object->name() << endl;
01099 
01100   suespecNode * spec = sue_type->spec();
01101   decl_list & fields = spec->fields();
01102 
01103   for (expr_list_p ip = inits.begin();
01104        ip != inits.end();
01105        ++ip)
01106     {
01107       exprNode * expr = (*ip);
01108       if (expr->typ() == Initializer) {
01109         initializerNode * initializer = (initializerNode *) expr;
01110         expr_list & field_inits = initializer->exprs();
01111 
01112         // -- Loop over the fields and the field inits together
01113 
01114         decl_list_p fp = fields.begin();
01115         expr_list_p fip = field_inits.begin();
01116         while ((fp != fields.end()) &&
01117                (fip != field_inits.end()))
01118           {
01119             declNode * field_decl = (*fp);
01120             exprNode * field_init = (*fip);
01121 
01122             idNode * id = 0;
01123             bool is_addr = false;
01124             
01125             if (field_init->typ() == Id)
01126               id = (idNode *) field_init;
01127 
01128             if (field_init->typ() == Unary) {
01129               unaryNode * un = (unaryNode *) field_init;
01130               if (un->expr()->typ() == Id)
01131                 id = (idNode *) un->expr();
01132               is_addr = (un->op()->id() == Operator::ADDRESS);
01133             }
01134 
01135             if (id) {
01136 
01137               declNode * decl_init = id->decl();
01138               
01139               if (decl_init) {
01140 
01141                 if(decl_init->type()->typ() == Func)
01142                   is_addr = true; //treat func as addr
01143                 
01144                 memoryblock_set results;
01145                 struct_object->dot(field_decl->name(),
01146                                    field_decl,
01147                                    *this,
01148                                    results);
01149                 memoryBlock * field = * (results.begin());
01150                 
01151                 memoryBlock * rhs = lookup_variable((Location *)0,
01152                                                     decl_init,
01153                                                     (procNode *)0);
01154                 if (pointerOptions::Verbose)
01155                   cout << "Field init: Assign " << field->name() << " = " << rhs->name() << endl;
01156                 
01157                 memoryblock_set temp;
01158                 if(is_addr)
01159                   temp.insert(rhs);
01160                 else { // TB new. import from assignment_operator.
01161                   memoryUse * right_use = rhs->current_use();
01162                   if ( ! right_use)
01163                     right_use = rhs->use_at(procLocation::main());
01164                   memoryDef * rd = right_use->reaching_def();
01165                   if (rd) {
01166                     const memoryblock_set & rd_points_to = rd->points_to();
01167                     temp.insert(rd_points_to.begin(), rd_points_to.end());
01168                   }
01169 
01170                   // TB_unify
01171                   if(pointerOptions::Unification && _unification_based) {
01172                     UnifyType *right_type = rhs->unifyType();
01173                     if(right_type &&
01174                        (right_type->objTyp()==SIMPLE || right_type->objTyp()==OBJECT)) {
01175                       Unify_ECR *defer = _unification_based->ecrDeref(right_type);
01176                       if(defer && defer->type()->block())
01177                         temp.insert( defer->type()->block() );
01178                     }
01179                   }
01180                 }
01181 
01182                 bool ignore;
01183                 memoryDef * def = field->def_at(procLocation::main(), ignore);
01184                 def->add_pointers(temp);
01185               }
01186             }
01187 
01188             fp++;
01189             fip++;
01190           }
01191       }
01192     }
01193 }

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