C-Breeze
C Compiler Infrastructure

[ Project home page]

proceduredb.h

Go to the documentation of this file.
00001 // $Id: proceduredb.h,v 1.41 2003/09/29 14:23: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_PROCEDUREDB_H
00039 #define CBZ_PROCEDUREDB_H
00040 
00041 class memoryBlock;
00042 
00043 #include "pointeroptions.h"
00044 #include "location.h"
00045 #include "dfpreds.h"
00046 #include "memoryaccess.h"
00047 #include "worklist.h"
00048 #include "linker.h"
00049 #include "loops.h"
00050 #include "callgraph.h"
00051 #include "cbztimer.h"
00052 
00053 class procedureInfo;
00054 
00055 typedef set< procedureInfo * > procedureinfo_set;
00056 typedef procedureinfo_set::iterator procedureinfo_set_p;
00057 typedef procedureinfo_set::const_iterator procedureinfo_set_cp;
00058 
00059 typedef pair< basicblockNode *, basicblockNode *> cfg_edge_pair;
00060 typedef set< cfg_edge_pair > cfg_edge_set;
00061 typedef cfg_edge_set::iterator cfg_edge_set_p;
00062 
00076 class procedureInfo
00077 {
00078 public:
00079 
00080   typedef map< basicblockNode *, int > worklist_order_map;
00081   typedef worklist_order_map::iterator worklist_order_map_p;
00082 
00083   // -- This is a map from callsites to the caller
00084 
00085   typedef map< stmtLocation *, procedureInfo *> callsite_map;
00086   typedef callsite_map::iterator callsite_map_p;
00087   typedef callsite_map::const_iterator callsite_map_cp;
00088 
00089   typedef map< basicblockLocation *, memoryblock_set > mergepoint_map;
00090   typedef mergepoint_map::iterator mergepoint_map_p;
00091 
00092   // -- Pending changes
00093 
00094   typedef map< stmtLocation *, memoryblock_set> callsite_changes_map;
00095   typedef callsite_changes_map::iterator callsite_changes_map_p;
00096 
00097   // -- For use in counting contexts:
00098 
00099   typedef map< procedureInfo *, int > proc_int_map;
00100   typedef proc_int_map::iterator proc_int_map_p;
00101 
00102 private:
00103 
00106   procNode * _proc;
00107 
00110   workList _worklist;
00111 
00117   worklist_order_map _forward_worklist_order;
00118 
00123   vector< basicblockNode * > _forward_basicblock_order;
00124 
00130   worklist_order_map _backward_worklist_order;
00131 
00136   vector< basicblockNode * > _backward_basicblock_order;
00137 
00144   mergepoint_map _merge_points;
00145 
00152   DFPreds * _dominance_frontiers;
00153 
00160   loopTree * _loops;
00161 
00168   callsite_map _callsites;
00169 
00175   declNode * _return_variable;
00176 
00182   memoryBlock * _return_block; // TB
00183 
00188   returnNode * _return_stmt;
00189 
00197   bool _never_returns;
00198 
00218   callsite_changes_map _pending_changes;
00219 
00230   bool _context_insensitive;
00231 
00238   bool _prefer_context_sensitive;
00239 
00248   TREE procLocation * _only_context;
00249 
00260   memoryblock_set _external_inputs;
00261 
00271   memoryblock_set _external_outputs;
00272 
00274   map<memoryBlock*,memoryblock_set> _input_values; // TB
00275 
00276   typedef pair<memoryBlock*,stmtLocation*> block_loc_pair; // TB
00277 
00280   map<block_loc_pair,memoryblock_set> _input_site_values; // TB
00281 
00287   procedureinfo_set _ancestors, /*TB*/ _decestors;
00288 
00294   procedureInfo * _first_caller;
00295 
00300   procedureinfo_set _calls;
00301 
00306   bool _is_recursive;
00307 
00314   basicblock_set _blocks_to_skip;
00315 
00320   cfg_edge_set _active_edges;
00321 
00327   typedef map< basicblockNode *, basicblockNode * > true_branch_map;
00328   typedef true_branch_map::iterator true_branch_map_p;
00329 
00330   true_branch_map _true_branches;
00331 
00336   int _analysis_count;
00337 
00343   bool _verbose;
00344 
00350   cbzTimer _self_timer;
00351 
00357   cbzTimer _total_timer;
00358 
00360   int _cg_depth_min, _cg_depth_max; // TB
00361 
00363   int _cg_height_min, _cg_height_max; // TB
00364 
00365 public:
00366 
00367   // EDB: Added!
00370   DFPreds * dominance_frontiers() const { return _dominance_frontiers; }
00371   
00377   procedureInfo(procNode * the_proc);
00378 
00381   ~procedureInfo();
00382 
00389   void add_one_ancestor(procedureInfo *ancestor);
00390 
00397   void add_ancestor_set(procedureinfo_set & ancestors);
00398 
00405   void setup_call_at(procedureInfo * caller,
00406                      stmtLocation * callsite,
00407                      bool is_recursive_call,
00408                      bool multiple_target_call);
00409 
00420   inline procNode * proc() const { return _proc; }
00421 
00424   inline string & name() { return proc()->decl()->name(); }
00425 
00431   string qualified_name();
00432 
00435   const procedureinfo_set & ancestors() const { return _ancestors; }
00436 
00441   inline const procedureinfo_set & calls() const { return _calls; }
00442 
00445   inline const callsite_map & callsites() const { return _callsites; }
00446 
00449   inline procedureInfo * first_caller() const { return _first_caller; }
00450 
00456   inline bool is_recursive() const { return _is_recursive; }
00457 
00463   inline void set_recursive() { _is_recursive = true; }
00464 
00471   inline declNode * return_variable() const { return _return_variable; }
00472 
00477   inline memoryBlock * return_block() const { return _return_block; }
00478 
00483   inline void return_block(memoryBlock *r) { _return_block = r; }
00484 
00489   inline returnNode * return_stmt() const { return _return_stmt; }
00490 
00496   inline bool never_returns() const { return _never_returns; }
00497 
00504   inline void set_never_returns() { _never_returns = true; }
00505 
00513   void set_pending_changes(stmtLocation * callsite, memoryblock_set & changes);
00514 
00521   void get_pending_changes(stmtLocation * callsite, memoryblock_set & changes);
00522 
00538   procedureInfo * caller_at(stmtLocation * callsite);
00539 
00544   bool is_ancestor(procedureInfo * other);
00545 
00552   procLocation * procedure_location(stmtLocation * callsite);
00553 
00556 
00559   inline bool is_context_insensitive() const { return _context_insensitive; }
00560 
00563   inline bool prefer_context_sensitive() const { return _prefer_context_sensitive; }
00564 
00567   inline void set_prefer_context_sensitive() { _prefer_context_sensitive = true; }
00568 
00573   procLocation * get_context() const { return _only_context; }
00574 
00576 
00579 
00586   void setup_merge_point(memoryBlock * block_to_merge,
00587                          basicblockLocation * cur);
00588 
00594   memoryblock_set * lookup_merge_point(basicblockLocation * where);
00595 
00601   void check_merge_point(memoryBlock * block_to_merge,
00602                          basicblockLocation * cur);
00603 
00605 
00612 
00615   const memoryblock_set & external_inputs() const { return _external_inputs; }
00616 
00619   const memoryblock_set & external_outputs() const { return _external_outputs; }
00620 
00629   bool add_external_input(memoryBlock * block);
00630 
00641   bool add_external_output(memoryBlock * block);
00642  // TB
00644   void record_input_to_value(memoryBlock *block, stmtLocation *loc,
00645                              memoryblock_set points_to) {
00646     _input_values[block] = points_to;
00647     _input_site_values[block_loc_pair(block,loc)] = points_to;
00648   }
00649 
00651   // TB
00652   memoryblock_set input_to_value(memoryBlock *block) const {
00653     if(_input_values.find(block) == _input_values.end())
00654       return memoryblock_set();
00655     return _input_values.find(block)->second;
00656   }
00657 
00660   // TB
00661   memoryblock_set input_to_value(memoryBlock *block, stmtLocation *loc) const {
00662     block_loc_pair p(block,loc);
00663     if(_input_site_values.find(p) == _input_site_values.end())
00664       return memoryblock_set();
00665     return _input_site_values.find(p)->second;
00666   }
00667 
00669 
00672 
00677   basicblockNode * get_next_block(Direction dir);
00678 
00684   void add_block(basicblockNode * block, Direction dir);
00685 
00691   void add_reachable_blocks(basicblockNode * block, Direction dir);
00692 
00697   void add_all_blocks();
00698 
00704   void add_start_block(Direction dir);
00705 
00711   bool is_empty() const;
00712 
00718   void remove_branch_blocks(basicblockNode * cond,
00719                             basicblockNode * branch_taken,
00720                             basicblockNode * branch_not_taken);
00721 
00726   void update_conditional_worklist(basicblockNode * block,
00727                                    bool has_truth_value,
00728                                    bool which_branch);
00729 
00734   inline cfg_edge_set & active_edges() { return _active_edges; }
00735 
00737 
00740   inline int analysis_count() const { return _analysis_count; }
00741 
00744   inline void incr_analysis_count() { _analysis_count++; }
00745 
00748   inline bool is_verbose() const { return _verbose; }
00749 
00754   bool is_library_routine() { return (proc()->decl()->decl_location() == declNode::UNKNOWN); }
00755 
00758   void print(ostream & out);
00759 
00765   void stats(ostream & out);
00766 
00771   int count_calling_contexts();
00772 
00778   int procedure_size();
00779 
00782   void start_self_timer() { _self_timer.start(); }
00783 
00786   void stop_self_timer() { _self_timer.stop(); }
00787 
00790   double self_timer() { return _self_timer.time(); }
00791 
00794   void start_total_timer() { _total_timer.start(); }
00795 
00798   void stop_total_timer() { _total_timer.stop(); }
00799 
00802   double total_timer() { return _total_timer.time(); }
00803 
00804   // TB
00805   void update_cg_statistics_call(procedureInfo *callee);
00806   void update_cg_statistics_return(procedureInfo *callee);
00807   void get_cg_statistics(int &cg_depth_min, int &cg_depth_max,
00808                          int &cg_height_min, int &cg_height_max);
00809 
00810 private:
00811 
00816   int count_calling_contexts_rec(proc_int_map & count,
00817                                  stmtNode * callsite);
00818 
00825   void reverse_post_order(Direction dir,
00826                           basicblockNode * cur,
00827                           basicblock_set & visited,
00828                           basicblock_list & order);
00829 
00834   void dfs_dominators(Direction dir,
00835                       basicblockNode * cur,
00836                       basicblock_set & visited,
00837                       basicblock_list & order,
00838                       basicblock_list & rpo_order);
00839 
00840   int block_position(basicblockNode * block, Direction dir);
00841 
00842   basicblockNode * block_at(int position, Direction dir);
00843 
00844   void add_reachable_blocks_rec(Direction dir,
00845                                 basicblockNode * cur,
00846                                 worklist_set & temp, bool first); 
00847 };
00848 
00849 typedef map< procNode *, procedureInfo *> proc_info_map;
00850 typedef proc_info_map::iterator proc_info_map_p;
00851 
00852 typedef list< procedureInfo *> proc_info_list;
00853 typedef proc_info_list::iterator proc_info_list_p;
00854 
00855 typedef pair< stmtLocation *, procedureInfo * > procedurecall_pair;
00856 
00857 typedef list< procedurecall_pair> procedurecall_stack;
00858 typedef procedurecall_stack::iterator procedurecall_stack_p;
00859 typedef procedurecall_stack::const_iterator procedurecall_stack_cp;
00860 typedef procedurecall_stack::reverse_iterator procedurecall_stack_rp;
00861 typedef procedurecall_stack::const_reverse_iterator procedurecall_stack_crp;
00862 
00870 class procedureDB : public Walker
00871 {
00872 private:
00873 
00878   proc_info_map _procedures;
00879 
00882   callGraph * _callgraph;
00883 
00891   procedureinfo_set _need_reanalysis;
00892 
00895   procedureInfo * _root;
00896 
00902   procedurecall_stack _callstack;
00903 
00908   proc_info_list _worklist;
00909 
00910 public:
00911 
00916   procedureDB();
00917 
00920   ~procedureDB();
00921 
00929   void build(procNode * root, Linker & linker);
00930 
00935   void clear();
00936 
00939   void add_procedure(procNode * proc);
00940 
00944   procedureInfo * lookup(procNode * proc);
00945 
00950   inline const procedurecall_stack & callstack() const { return _callstack; }
00951 
00957   bool is_recursive_call(procedureInfo * callee,
00958                          int & num_instances);
00959 
00964   void setup_analysis();
00965 
00970   procedureInfo * next_procedure_on_worklist();
00971 
00976   bool is_procedure_on_worklist(procedureInfo * info);
00977 
00981   void add_procedure_to_worklist(procedureInfo * info);
00982 
00989   void call_to(stmtLocation * callsite, procedureInfo * callee);
00990 
00996   void return_from();
00997 
01003   bool is_visible_to_caller(procedureInfo * info,
01004                             memoryBlock * block);
01005 
01012   bool is_visible_to(procedureInfo * info,
01013                      memoryBlock * block);
01014 
01018   inline stmtLocation * current_callsite() { return _callstack.back().first; }
01019 
01024   procedureInfo * current_caller();
01025 
01030   void clear_call_stack();
01031 
01034   void print_call_stack(ostream & out);
01035 
01038   void progress_meter(ostream & out);
01039 
01047   void mark_for_reanalysis(procedureInfo * info,
01048                            stmtLocation * callsite,
01049                            bool include_self);
01050 
01055   void mark_one_for_reanalysis(procedureInfo * info);
01056 
01063   bool is_reanalysis_required(procedureInfo * info);
01064 
01067   void print_leftovers();
01068 
01076   int times_called(procedureInfo * info);
01077 
01080   void stats(ostream & out);
01081 
01084   int size() const { return _procedures.size(); }
01085 
01090   void number_of_procedures(int & total, int & analyzed,
01091                             int & context_insensitive,
01092                             int & recursive,
01093                             int & unanalyzed,
01094                             int & program_size);
01095 
01096 
01098   inline proc_info_map procedures() const { return _procedures; }
01099 };
01100 
01101 #endif // CBZ_PROCEDUREDB_H

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