C-Breeze
C Compiler Infrastructure

[ Project home page]

memoryblock.h

Go to the documentation of this file.
00001 // $Id: memoryblock.h,v 1.31 2003/09/29 13:01:33 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 #ifndef CBZ_MEMORYBLOCK_H
00039 #define CBZ_MEMORYBLOCK_H
00040 
00041 #include "pointeroptions.h"
00042 #include "location.h"
00043 #include "memoryaccess.h"
00044 #include "proceduredb.h"
00045 #include "unification.h"
00046 
00047 #include <set>
00048 
00049 // ------------------------------------------------------------
00050 //  Memory block
00051 
00052 // Each object in memory that may be a pointer, or pointed to is
00053 // represented by a memoryBlock. 
00054 
00055 class memoryBlock;
00056 
00057 typedef list< memoryBlock * > memoryblock_list;
00058 typedef memoryblock_list::iterator memoryblock_list_p;
00059 
00060 typedef map< int, memoryBlock *, less< int > > component_map;
00061 typedef component_map::iterator component_map_p;
00062 typedef component_map::const_iterator component_map_cp;
00063 
00064 typedef vector< memoryBlock * > memoryblock_vector;
00065 typedef memoryblock_vector::iterator memoryblock_vector_p;
00066 
00067 // -- Keep track of the reaching objects that are combined at a
00068 // context-insensitive procedure call (the self-assignments generated when
00069 // this object is an external input).
00070 
00071 typedef map< stmtLocation *, memoryblock_set > callsite_objects_map;
00072 typedef callsite_objects_map::iterator callsite_objects_map_p;
00073 typedef callsite_objects_map::const_iterator callsite_objects_map_cp;
00074 
00075 typedef map< procNode *, callsite_objects_map > parameter_assign_map;
00076 typedef parameter_assign_map::iterator parameter_assign_map_p;
00077 
00078 class enumPropertyAnn;
00079 
00080 class memoryBlock : public PerClassHeap< PointersHeap >
00081 {
00082 public:
00083 
00084   typedef enum { Control_flow, Parameter_pass, Weak_update, Additive } DestructiveKind;
00085 
00086   typedef map< Location *, DestructiveKind > destructive_assignment_map;
00087   typedef destructive_assignment_map::iterator destructive_assignment_map_p;
00088   typedef destructive_assignment_map::const_iterator destructive_assignment_map_cp;
00089 
00090   typedef map< Location *, memoryblock_set > complicit_assignment_map;
00091   typedef complicit_assignment_map::iterator complicit_assignment_map_p;
00092   typedef complicit_assignment_map::const_iterator complicit_assignment_map_cp;
00093 
00094   static int memoryblock_count;
00095   static void stats();
00096 
00097 private:
00098 
00101   REF memoryBlock * _container;
00102 
00110 
00111   TREE orderedDefs Defs;
00112   TREE orderedUses Uses;
00113 
00115 
00124   parameter_assign_map _parameter_assignments;
00125 
00135   REF memoryUse * _current_use;
00136 
00149   REF memoryDef * _current_def;
00150 
00153   component_map  _components;
00154 
00160   declNode * _decl;
00161 
00168   int _synthetic_decl:1;
00169 
00175   int _write_protected:1;
00176 
00181   int _is_array:1;
00182 
00188   int _is_array_element:1;
00189 
00196   int _is_indexed:1;
00197 
00202   int _is_allocation_object:1;
00203 
00210   int _flow_sensitive:1;
00211 
00212   // TB_unify
00219   int _unify:1;
00220 
00227   int _single_assignment:1;
00228 
00233   int _is_return_value:1;
00234 
00241   procNode * _local_to;
00242 
00248   // string _name;
00249 
00255   stmtLocation * _allocation_site;
00256 
00264   // memoryDef * _initializer_def;
00265 
00273   memoryBlock * _allocation_object;
00274 
00280   // memoryDef * _only_def;
00281 
00287   // memoryUse * _only_use;
00288 
00295   procedureinfo_set _input_to;
00296 
00302   destructive_assignment_map _destructive_assignments;
00303 
00309   complicit_assignment_map _complicit_assignments;
00310 
00312   UnifyType *_unifytype; // TB_unify
00313 
00314 public:
00315 
00316   // --- These two members are just for Broadway
00317 
00324   enumPropertyAnn * property;
00325 
00331   memoryblock_vector property_blocks;
00332 
00333 private:
00334 
00335   friend class memoryModel;
00336 
00343   memoryBlock(declNode * decl, bool synthetic,
00344               memoryBlock * container,
00345               procNode * local_to);
00346 
00352   ~memoryBlock();
00353 
00354 public:
00355 
00360   void clear();
00361 
00362   // --- Data members
00363 
00364   declNode * decl() const { return _decl; }
00365   procNode * local_to() const { return _local_to; }
00366 
00367   bool is_synthetic_decl() const { return _synthetic_decl; }
00368 
00369   bool write_protected() const { return _write_protected; }
00370   void set_write_protected() { _write_protected = true; }
00371 
00372   bool is_indexed() const { return _is_indexed; }
00373   void set_indexed() { _is_indexed = true; }
00374 
00375   // void set_name(const string & new_name) { _name = new_name; }
00376 
00377   stmtLocation * allocation_site() const { return _allocation_site; }
00378   bool is_heap_object() const { return _allocation_site != 0; }
00379   void set_heap_object(stmtLocation * alloc_site) { _allocation_site = alloc_site; }
00380 
00381   bool is_allocation_object() const { return _is_allocation_object; }
00382 
00383   memoryUse * current_use() const { return _current_use; }
00384   memoryDef * current_def() const { return _current_def; }
00385 
00386   void reset_current_def_use(Location * unused);
00387 
00388   void set_current_def_use(Location * where);
00389 
00390   inline memoryBlock * container() const { return _container; }
00391 
00392   inline bool is_flow_sensitive() const { return _flow_sensitive; }
00393   inline void set_flow_sensitive() {
00394     _flow_sensitive = true;
00395     // cout << "SETFS: (0x" << this << ") " << name() << endl;
00396   }
00397   inline void set_flow_insensitive() { _flow_sensitive = false; }
00398 
00399   inline bool is_unify() const { return _unify; }
00400   inline void set_unify(bool flag) { _unify = flag; }
00401   inline UnifyType *unifyType() const { return _unifytype; }
00402   inline void unifyType(UnifyType *t) { _unifytype=t; }
00403 
00404   inline bool is_single_assignment() const { return _single_assignment; }
00405 
00406   inline bool is_return_value() const { return _is_return_value; }
00407   inline bool set_return_value() { _is_return_value = true; }
00408 
00409   // inline memoryDef * only_def() const { return _only_def; }
00410   // inline memoryUse * only_use() const { return _only_use; }
00411 
00412   inline procedureinfo_set & input_to() { return _input_to; }
00413 
00414   // --- Manage uses and defs
00415 
00422   memoryDef * def_at(Location * where, bool & is_new);
00423 
00430   memoryDef * nearest_def_at(Location * where);
00431 
00437   /*
00438   memoryDef * nearest_def_at(Location * where,
00439                              const procedurecall_stack & callstack);
00440   */
00441 
00448   memoryUse * use_at(Location * where);
00449 
00456   memoryDef * last_def_at(basicblockLocation * block);
00457 
00463   memoryDef * find_def_at(Location * where);
00464 
00470   memoryUse * find_use_at(Location * where);
00471 
00477   void find_uses_at(Location * where, memoryuse_set & uses);
00478 
00483   inline const memorydef_list & defs() const { return Defs.def_list(); }
00484 
00491   void add_parameter_assignment(procNode * proc, stmtLocation * callsite,
00492                                 memoryBlock * block);
00493 
00500   void add_parameter_assignment(procNode * proc, stmtLocation * callsite,
00501                                 memoryblock_set & blocks);
00502 
00507   const callsite_objects_map & parameter_assignments(procNode * proc)
00508     { return _parameter_assignments[proc]; }
00509 
00516   void apply_weak_update(Location * current,
00517                          memoryDef * previous_def,
00518                          memoryuse_set & uses);
00519 
00527   void setup_merge_uses_at(basicblockLocation * merge_location,
00528                            memoryDef * reaching_def,
00529                            basicblock_set & predecessors);
00530 
00540   void merge_uses_at(basicblockLocation * where,
00541                      memoryuse_list & uses,
00542                      cfg_edge_set & active_edges,
00543                      memoryDef * dominating_def,
00544                      bool computePointers);
00545 
00551   void reachable_blocks(Location * where,
00552                         bool has_use_here,
00553                         memoryblock_list & worklist,
00554                         memoryblock_set & already_seen,
00555                         memoryBlock * null,
00556                         bool components_only = false);
00557 
00564   memoryBlock * get_allocation_object(memoryModel & Memory);
00565 
00570   memoryBlock * allocation_object();
00571 
00578   Multiplicity at_allocation(Location * current,
00579                              memoryDef * reaching_def,
00580                              memoryblock_set & defs,
00581                              memoryuse_set & uses,
00582                              memoryblock_set & changes);
00583 
00590   Multiplicity at_deallocation(Location * current,
00591                                memoryDef * reaching_def,
00592                                memoryblock_set & defs,
00593                                memoryuse_set & uses,
00594                                memoryblock_set & changes);
00595 
00599 
00605   void add_destructive_assignment(Location * where, DestructiveKind cause);
00606 
00612   void add_complicit_assignment(Location * where, memoryblock_set & objects);
00613 
00619   void add_complicit_assignment(Location * where, memoryBlock * object);
00620 
00623   const destructive_assignment_map & destructive_assignments() const
00624   { return _destructive_assignments; }
00625 
00628   const complicit_assignment_map & complicit_assignments() const
00629   { return _complicit_assignments; }
00630 
00639   void add_to_flow_sensitive_list(flow_sensitive_set & flow_sensitive_objects);
00640 
00645   bool is_in_flow_sensitive_list(flow_sensitive_set & flow_sensitive_objects);
00646 
00653   void set_flow_sensitivity(flow_sensitive_set & flow_sensitive_objects);
00654 
00663   void add_to_non_unify_list(UnifyTypes & non_unify_types);
00670   void set_unification(UnifyTypes & unify_types);
00671 
00673 
00678   memoryBlock * top_most_container();
00679 
00680   // TB_unify
00681   /* @brief Get all parents. */
00682   memoryblock_set containers() const;
00683   memoryblock_set top_most_containers();
00684 
00687   static void print_multiplicity(Multiplicity m, ostream & out);  
00688 
00693   void def_uses(memoryDef * def,
00694                 memoryuse_list & uses);
00695 
00696   // --- Prune out unneeded uses and defs
00697 
00698   void prune_defs_uses();
00699 
00700   // --- Manage structure fields
00701 
00702   void dot(const string & field_name,
00703            declNode * field_decl,
00704            memoryModel & Memory,
00705            memoryblock_set & results);
00706 
00707   // --- Handle special array objects
00708 
00709   bool is_array() const { return _is_array; }
00710 
00711   bool is_array_element() const { return _is_array_element; }
00712 
00713   void set_array_element(memoryBlock * element);
00714 
00715   memoryBlock * get_array_element();
00716 
00717   memoryDef * setup_array_def();
00718 
00719   // --- Scoping
00720 
00721   bool in_scope(basicblockLocation * where) const;
00722 
00723   // --- Output
00724 
00725   friend ostream& operator<<(ostream & o, const memoryBlock & mb) {
00726     // mb.print(o, Path::always());
00727     return o;
00728   }
00729 
00730   // --- Pass after = true to see the points-to information after the
00731   // given statement has been executed.
00732 
00733   typedef enum { NAME_ONLY, CURRENT_VALUE, AFTER_ASSIGNMENT, ALL_VALUES } Output_mode;
00734 
00735   void print(ostream & o, Location * path, Output_mode mode = CURRENT_VALUE) const;
00736   string name() const;
00737 
00738   string generate_su_field_name(const string & field) const;
00739 
00740   void print_def_use(ostream & o) const;
00741 
00742   // --- Update the def-use chains (only performed once at the end of
00743   // analysis by the memoryModel).
00744 
00745   void update_def_use_chains();
00746 
00747   // --- Statistics
00748 
00749   void stats(ostream & out, bool header,
00750              long int & global_defs,
00751              long int & global_merge_defs,
00752              long int & global_weak_defs,
00753              long int & global_uses,
00754              long int & global_merge_uses);
00755   
00756 private:
00757 
00758   //  Structure field-name database
00759 
00760   // Since the number of possible field names is small, we keep them in
00761   // a database and then refer to them by number in the memoryBlock class.
00762 
00763   class FieldNameDB
00764   {
00765   private:
00766 
00767     typedef map< string, int, less< string > > field_name_map;
00768     typedef field_name_map::iterator field_name_map_p;
00769 
00770     field_name_map _fields;
00771     int _count;
00772 
00773   public:
00774 
00775     static int ArrayField;
00776 
00777     FieldNameDB()
00778       : _fields(),
00779         _count(0)
00780     {}
00781 
00782     // --- Get the index for a field name, create if needed
00783 
00784     int get_field(const string & name);
00785 
00786     // --- Reverse search: find the name for a particular index
00787 
00788     string field_name(int index);
00789 
00790     void stats() {
00791       cout << "  Field names: " << _count << endl;
00792     }
00793   };
00794 
00795   static FieldNameDB FieldNames;
00796 
00797   // TB_unify helper functionn.
00798   memoryblock_set top_most_containers(memoryblock_set &visited);
00799 };
00800 
00801 
00802 #endif // CBZ_MEMORYBLOCK_H

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