C-Breeze
C Compiler Infrastructure

[ Project home page]

memoryaccess.h

Go to the documentation of this file.
00001 // $Id: memoryaccess.h,v 1.33 2003/08/07 23:14:23 pnav 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 #ifndef CBZ_MEMORYACCESS_H
00039 #define CBZ_MEMORYACCESS_H
00040 
00041 #include <set>
00042 #include "pointeroptions.h"
00043 #include "location.h"
00044 
00045 // microsoft compiler does not like this include
00046 #ifndef _MSC_VER
00047 #include <ext/hash_map>
00048 #include <ext/hash_set>
00049 #endif
00050 
00051 // -- Some forward declarations
00052 
00053 class memoryBlock;
00054 class memoryDef;
00055 class memoryUse;
00056 class memorydef_key;
00057 
00069 template< class T >
00070 class vector_set : public vector< T >
00071 {
00072 public:
00073 
00074   vector_set()
00075   {
00076     reserve(10);
00077   }
00078 
00079   inline void insert(T element)
00080     {
00081       int s = size();
00082       for (int i = 0; i < s; i++)
00083         if ((*this)[i] == element)
00084           return;
00085 
00086       // if (std::find(begin(), end(), element) == end())
00087 
00088       push_back(element);
00089     }
00090 
00091   inline void insert(typename vector< T >::const_iterator b,
00092                      typename vector< T >::const_iterator e)
00093     {
00094       for (typename vector< T >::const_iterator p = b;
00095            p != e;
00096            p++)
00097         insert(*p);
00098     }
00099 
00100   inline typename vector< T >::const_iterator find(T element) const {
00101     return std::find(begin(), end(), element);
00102   }
00103 
00104   inline typename vector< T >::iterator find(T element) {
00105     return std::find(begin(), end(), element);
00106   }
00107 };
00108 
00115 typedef vector_set< memoryBlock * > memoryblock_set;
00116 typedef memoryblock_set::iterator memoryblock_set_p;
00117 typedef memoryblock_set::const_iterator memoryblock_set_cp;
00118 
00127 typedef vector< memorydef_key > memorydef_list;
00128 typedef memorydef_list::iterator memorydef_list_p;
00129 typedef memorydef_list::const_iterator memorydef_list_cp;
00130 
00134 typedef set< memoryDef * > memorydef_set;
00135 typedef memorydef_set::iterator memorydef_set_p;
00136 typedef memorydef_set::const_iterator memorydef_set_cp;
00137 
00138 typedef map< Location *, memoryDef * > memorydef_location_map;
00139 typedef memorydef_location_map::iterator memorydef_location_map_p;
00140 typedef memorydef_location_map::const_iterator memorydef_location_map_cp;
00141 
00142 
00143 //typedef list< memoryUse *, memoryuse_alloc > memoryuse_list;
00144 typedef vector< memoryUse * /* , memoryuse_alloc */ > memoryuse_list;
00145 typedef memoryuse_list::iterator memoryuse_list_p;
00146 typedef memoryuse_list::const_iterator memoryuse_list_cp;
00147 
00148 typedef set< memoryUse * > memoryuse_set;
00149 typedef memoryuse_set::iterator memoryuse_set_p;
00150 typedef memoryuse_set::const_iterator memoryuse_set_cp;
00151 
00152 // ------------------------------------------------------------
00153 // memoryAccess
00154 // ------------------------------------------------------------
00155 
00158 typedef enum Multiplicity
00159     { Top, Deallocated, Unallocated, Single, Bounded, Unbounded, Error } Multiplicity;
00160 
00161 // Common base class for both defs and uses
00162 
00163 class memoryAccess : public PerClassHeap< PointersHeap >
00164 {
00165 public:
00166 
00167   static bool Verbose;
00168   static unsigned int def_count;
00169   static unsigned int use_count;
00170   static unsigned int merge_use_count;
00171 
00172   static void stats();
00173 
00174   typedef enum { MultipleLHS, HighMultiplicity, Forced } WeakReason;
00175 
00176 private:
00177 
00180   Location * _where;
00181 
00184   int _is_weak:1;
00185 
00188   int _multiplicity:8;
00189 
00192   int _search_for_def:1;
00193 
00196   int _active:1;
00197 
00200   memoryBlock * const _owner;
00201 
00207   //  memoryAssignment * _assignment;
00208 
00209 public:
00210 
00211   // --- Constructor
00212 
00213   memoryAccess(Location * where, memoryBlock * owner);
00214 
00215   // --- Fields
00216 
00217   inline Location * where() const { return _where; }
00218 
00219   inline bool is_weak() const { return _is_weak; }
00220   inline void set_weak(bool is) { _is_weak = is; }
00221 
00222   // --- Get and set the multiplicity
00223 
00224   inline Multiplicity multiplicity() const { return (Multiplicity)_multiplicity; }
00225   inline void set_multiplicity(Multiplicity lin) { _multiplicity = lin; }
00226 
00227   inline bool search_for_def() const { return _search_for_def; }
00228   inline void search_for_def(bool val) { _search_for_def = val; }
00229 
00230   inline bool is_active() const { return _active; }
00231   inline void set_active() { _active = true; }
00232   inline void set_inactive() { _active = false; }
00233 
00234   /*
00235   inline WeakReason why_weak() const { return _why_weak; }
00236   inline void set_why_weak(WeakReason reason) { _why_weak = reason; }
00237   */
00238   
00239   inline memoryBlock * owner() const { return _owner; }
00240 
00241   /*
00242   inline memoryAssignment * assignment() const { return _assignment; }
00243   inline void set_assignment(memoryAssignment * a) { _assignment = a; }
00244   */
00245 };
00246 
00247 
00248 // ------------------------------------------------------------
00249 // memoryDef
00250 // ------------------------------------------------------------
00251 
00252 // A memoryDef represents a single definition of (assignment to) a
00253 // particular memoryBlock. It records the place where the def occured,
00254 // and the object deing modified. In addition, it is used to record
00255 // the points-to values of any pointer objects.
00256 
00257 class memoryDef : public memoryAccess
00258 {
00259 private:
00260 
00263   // memoryuse_list _uses;
00264 
00267   memoryblock_set _points_to;
00268 
00271   // memoryDef * _previous;
00272 
00275   const constant * _value;
00276 
00284   memoryUse * _self_assign_use;
00285 
00286 public:
00287 
00288   // --- Constructor
00289 
00290   memoryDef(Location * where, memoryBlock * owner);
00291 
00292   // --- Destructor
00293 
00294   ~memoryDef();
00295 
00296   // --- Fields
00297 
00298   // inline memoryuse_list & uses() { return _uses; }
00299   inline const memoryblock_set & points_to() const { return _points_to; }
00300 
00301   // inline memoryDef * previous() const { return _previous; }
00302   // inline void set_previous(memoryDef * previous_def) { _previous = previous_def; }
00303 
00304   inline const constant * value() const { return _value; }
00305   inline void set_value(const constant * newval) { _value = newval; }
00306 
00307   // -- Self assign use
00308 
00309   inline memoryUse * self_assign_use() const { return _self_assign_use; }
00310   inline void set_self_assign_use(memoryUse * new_use) { _self_assign_use = new_use; }
00311 
00316   void add_pointers(const memoryblock_set & mbs);
00317 
00323   void clear_points_to();
00324 
00325   // --- Output
00326 
00327   void print(ostream & o) const;
00328 };
00329 
00330 // ------------------------------------------------------------
00331 // orderedDefs
00332 // ------------------------------------------------------------
00333 
00334 // An orderedDef object holds a sequence of memoryDefs in dominating
00335 // order (a particular def always comes before the defs that dominate
00336 // it).
00337 
00338 // -- Store each def along with the location and the subtree ID
00339 
00340 class memorydef_key
00341 {
00342 public:
00343 
00344   memoryDef * def;
00345   Location * location;
00346   // int subtree_id;
00347 
00348   memorydef_key(memoryDef * the_def)
00349     : def(the_def),
00350       location(the_def->where())
00351     // subtree_id(location->subtree_id())
00352   {}
00353 };
00354 
00355 class orderedUses;
00356 
00357 class orderedDefs
00358 {
00359 private:
00360 
00361   memorydef_list _defs;
00362 
00363   memorydef_location_map _quick_lookup;
00364 
00365 public:
00366 
00367   orderedDefs()
00368     : _defs(),
00369       _quick_lookup()
00370   {}
00371 
00372   // --- Return the list of defs
00373 
00374   const memorydef_list & def_list() const { return _defs; }
00375 
00376   // --- Find the memoryDef for a given program location
00377 
00378   memoryDef * find_def(Location * where);
00379 
00380   // --- Find the nearest strictly dominating memoryDef (use this to
00381   // find the reaching definition for a regular use.
00382 
00383   memoryDef * find_strictly_dominating_def(Location * where);
00384 
00385   // --- Find the nearest dominating memoryDef (use this to find the
00386   // reaching definition for a merge-point use.
00387 
00388   memoryDef * find_dominating_def(Location * where);
00389 
00390   // --- Add a new memoryDef in the proper place, and return a
00391   // reference to it. If there is already an entry for the given path,
00392   // just return that memoryDef.
00393 
00394   memoryDef * make_def_at(Location * where, memoryBlock * owner, bool & is_new);
00395 
00396   // --- Prune out unnecessary defs
00397 
00398   void prune(orderedUses & Uses);
00399 
00400   // --- Output
00401 
00402   void print(ostream & o) const;
00403 
00404   // --- Clear
00405 
00406   void clear();
00407 
00408   // --- Stats
00409 
00410   void stats(int & total_defs, int & merge_defs, int & weak_defs);
00411 
00412 };
00413 
00414 // ------------------------------------------------------------
00415 // memoryUse
00416 // ------------------------------------------------------------
00417 
00418 // A memoryUse represents a single use of the memoryBlock. It points
00419 // to the reaching definition (from the orderedDefs list). For merges
00420 // (phi functions) we create one for each of the control-flow
00421 // predecessors.
00422 
00423 class memoryUse : public memoryAccess
00424 {
00425 private:
00426 
00427   memoryDef * _reaching_def;
00428 
00429 public:
00430 
00431   // --- Constructor
00432 
00433   memoryUse(Location * where, memoryBlock * owner);
00434 
00435   // --- Destructor
00436 
00437   ~memoryUse();
00438 
00439   // --- Fields
00440 
00441   memoryDef * reaching_def() const { return _reaching_def; }
00442   void reaching_def(memoryDef * def);
00443 
00444   // --- Output
00445 
00446   void print(ostream & o) const;
00447 };
00448 
00449 
00450 typedef map< Location *, memoryUse * > memoryuse_map;
00451 typedef memoryuse_map::iterator memoryuse_map_p;
00452 typedef memoryuse_map::const_iterator memoryuse_map_cp;
00453 typedef memoryuse_map::value_type memoryuse_map_pair;
00454 
00455 typedef map< basicblockNode *, memoryUse *> pred_use_map;
00456 typedef pred_use_map::iterator pred_use_map_p;
00457 typedef pred_use_map::const_iterator pred_use_map_cp;
00458 
00459 typedef map< Location *, pred_use_map > merge_use_map;
00460 typedef merge_use_map::iterator merge_use_map_p;
00461 typedef merge_use_map::const_iterator merge_use_map_cp;
00462 
00463 // ------------------------------------------------------------
00464 // orderedUses
00465 // ------------------------------------------------------------
00466 
00467 class orderedUses
00468 {
00469 private:
00470 
00471   memoryuse_map _uses;
00472   merge_use_map _merge_uses;
00473   
00474 public:
00475 
00476   orderedUses()
00477     : _uses(),
00478       _merge_uses()
00479   {}
00480 
00481   // --- Find an existing use for the given location (doesn't work for
00482   // merge/phi functions).
00483 
00484   memoryUse * find_use(Location * where) const;
00485 
00486   // -- Find uses at (works for phi functions)
00487 
00488   void find_uses_at(Location * where, memoryuse_set & uses);
00489 
00490   // --- Add a new use for the given location, or return the existing
00491   // one.
00492 
00493   memoryUse * make_use_at(Location * where, memoryBlock * owner);
00494 
00495   // --- Add a new set of uses for a particular merge point: one use
00496   // for each control-flow predecessor, with the reaching definitions
00497   // set appropriately.
00498 
00499   const pred_use_map & make_merge_uses_at(basicblockLocation * where,
00500                                           memoryBlock * owner);
00501 
00502   // --- Update the def-use chains (only performed once at the end of
00503   // analysis by the memoryModel).
00504 
00505   void update_def_use_chains();
00506 
00512   void def_uses(memoryDef * def,
00513                 memoryuse_list & uses);
00514 
00515   // --- Prune uses for a particular location
00516 
00517   void prune(Location * where);
00518 
00519   // --- Output
00520 
00521   void print(ostream & o) const;
00522 
00523   // --- Clear
00524 
00525   void clear();
00526 
00527   // --- Stats
00528 
00529   void stats(int & total_uses, int & merge_uses);
00530 };
00531 
00532 // ----------------------------------------------------------------------
00533 // memoryAssignment
00534 // ----------------------------------------------------------------------
00535 
00536 class memoryAssignment : public PerClassHeap< PointersHeap >
00537 {
00538 private:
00539 
00544   Location * _where;
00545 
00550   memoryuse_set _uses;
00551 
00556   memorydef_set _defs;
00557 
00558 public:
00559 
00562   memoryAssignment(Location * where)
00563     : _where(),
00564       _uses(),
00565       _defs()
00566   {}
00567 
00570   inline Location * where() const { return _where; }
00571 
00574   inline void add_use(memoryUse * use) { _uses.insert(use); }
00575 
00578   inline void add_def(memoryDef * def) { _defs.insert(def); }
00579 
00582   inline const memoryuse_set & uses() const { return _uses; }
00583 
00586   inline const memorydef_set & defs() const { return _defs; }
00587 };
00588 
00589 // ----------------------------------------------------------------------
00590 //  Assignments
00591 // ----------------------------------------------------------------------
00592 
00593 typedef pair< Location *, memoryBlock *> assignment_key;
00594 
00595 typedef map< assignment_key, memoryAssignment * > assignment_map;
00596 typedef assignment_map::iterator assignment_map_p;
00597 
00598 class assignmentSet
00599 {
00600 private:
00601 
00604   assignment_map _assignments;
00605 
00606 public:
00607 
00610   assignmentSet()
00611     : _assignments()
00612   {}
00613 
00620   memoryAssignment * assignment_at(Location * where, memoryBlock * block,
00621                                    bool create);
00622 };
00623 
00624 #endif // CBZ_MEMORYACCESS_H
00625 

Generated on February 1, 2006
Back to the C-Breeze home page