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  

proceduredb.h

Go to the documentation of this file.
00001 // $Id: proceduredb.h,v 1.39 2003/08/07 23:14:33 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_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 
00181   returnNode * _return_stmt;
00182 
00190   bool _never_returns;
00191 
00211   callsite_changes_map _pending_changes;
00212 
00223   bool _context_insensitive;
00224 
00231   bool _prefer_context_sensitive;
00232 
00241   TREE procLocation * _only_context;
00242 
00253   memoryblock_set _external_inputs;
00254 
00264   memoryblock_set _external_outputs;
00265 
00271   procedureinfo_set _ancestors;
00272 
00278   procedureInfo * _first_caller;
00279 
00284   procedureinfo_set _calls;
00285 
00290   bool _is_recursive;
00291 
00298   basicblock_set _blocks_to_skip;
00299 
00304   cfg_edge_set _active_edges;
00305 
00311   typedef map< basicblockNode *, basicblockNode * > true_branch_map;
00312   typedef true_branch_map::iterator true_branch_map_p;
00313 
00314   true_branch_map _true_branches;
00315 
00320   int _analysis_count;
00321 
00327   bool _verbose;
00328 
00334   cbzTimer _self_timer;
00335 
00341   cbzTimer _total_timer;
00342 
00343 public:
00344 
00345   // EDB: Added!
00348   DFPreds * dominance_frontiers() const { return _dominance_frontiers; }
00349   
00355   procedureInfo(procNode * the_proc);
00356 
00359   ~procedureInfo();
00360 
00367   void add_ancestor_set(procedureinfo_set & ancestors);
00368 
00375   void setup_call_at(procedureInfo * caller,
00376                      stmtLocation * callsite,
00377                      bool is_recursive_call,
00378                      bool multiple_target_call);
00379 
00390   inline procNode * proc() const { return _proc; }
00391 
00394   inline string & name() { return proc()->decl()->name(); }
00395 
00401   string qualified_name();
00402 
00405   const procedureinfo_set & ancestors() const { return _ancestors; }
00406 
00411   inline const procedureinfo_set & calls() const { return _calls; }
00412 
00415   inline const callsite_map & callsites() const { return _callsites; }
00416 
00419   inline procedureInfo * first_caller() const { return _first_caller; }
00420 
00426   inline bool is_recursive() const { return _is_recursive; }
00427 
00433   inline void set_recursive() { _is_recursive = true; }
00434 
00441   inline declNode * return_variable() const { return _return_variable; }
00442 
00447   inline returnNode * return_stmt() const { return _return_stmt; }
00448 
00454   inline bool never_returns() const { return _never_returns; }
00455 
00462   inline void set_never_returns() { _never_returns = true; }
00463 
00471   void set_pending_changes(stmtLocation * callsite, memoryblock_set & changes);
00472 
00479   void get_pending_changes(stmtLocation * callsite, memoryblock_set & changes);
00480 
00496   procedureInfo * caller_at(stmtLocation * callsite);
00497 
00502   bool is_ancestor(procedureInfo * other);
00503 
00510   procLocation * procedure_location(stmtLocation * callsite);
00511 
00514 
00517   inline bool is_context_insensitive() const { return _context_insensitive; }
00518 
00521   inline bool prefer_context_sensitive() const { return _prefer_context_sensitive; }
00522 
00525   inline void set_prefer_context_sensitive() { _prefer_context_sensitive = true; }
00526 
00531   procLocation * get_context() const { return _only_context; }
00532 
00534 
00537 
00544   void setup_merge_point(memoryBlock * block_to_merge,
00545                          basicblockLocation * cur);
00546 
00552   memoryblock_set * lookup_merge_point(basicblockLocation * where);
00553 
00559   void check_merge_point(memoryBlock * block_to_merge,
00560                          basicblockLocation * cur);
00561 
00563 
00570 
00573   const memoryblock_set & external_inputs() const { return _external_inputs; }
00574 
00577   const memoryblock_set & external_outputs() const { return _external_outputs; }
00578 
00587   bool add_external_input(memoryBlock * block);
00588 
00599   bool add_external_output(memoryBlock * block);
00600 
00602 
00605 
00610   basicblockNode * get_next_block(Direction dir);
00611 
00617   void add_block(basicblockNode * block, Direction dir);
00618 
00624   void add_reachable_blocks(basicblockNode * block, Direction dir);
00625 
00630   void add_all_blocks();
00631 
00637   void add_start_block(Direction dir);
00638 
00644   bool is_empty() const;
00645 
00651   void remove_branch_blocks(basicblockNode * cond,
00652                             basicblockNode * branch_taken,
00653                             basicblockNode * branch_not_taken);
00654 
00659   void update_conditional_worklist(basicblockNode * block,
00660                                    bool has_truth_value,
00661                                    bool which_branch);
00662 
00667   inline cfg_edge_set & active_edges() { return _active_edges; }
00668 
00670 
00673   inline int analysis_count() const { return _analysis_count; }
00674 
00677   inline void incr_analysis_count() { _analysis_count++; }
00678 
00681   inline bool is_verbose() const { return _verbose; }
00682 
00687   bool is_library_routine() { return (proc()->decl()->decl_location() == declNode::UNKNOWN); }
00688 
00691   void print(ostream & out);
00692 
00698   void stats(ostream & out);
00699 
00704   int count_calling_contexts();
00705 
00711   int procedure_size();
00712 
00715   void start_self_timer() { _self_timer.start(); }
00716 
00719   void stop_self_timer() { _self_timer.stop(); }
00720 
00723   double self_timer() { return _self_timer.time(); }
00724 
00727   void start_total_timer() { _total_timer.start(); }
00728 
00731   void stop_total_timer() { _total_timer.stop(); }
00732 
00735   double total_timer() { return _total_timer.time(); }
00736 
00737 private:
00738 
00743   int count_calling_contexts_rec(proc_int_map & count,
00744                                  stmtNode * callsite);
00745 
00752   void reverse_post_order(Direction dir,
00753                           basicblockNode * cur,
00754                           basicblock_set & visited,
00755                           basicblock_list & order);
00756 
00761   void dfs_dominators(Direction dir,
00762                       basicblockNode * cur,
00763                       basicblock_set & visited,
00764                       basicblock_list & order,
00765                       basicblock_list & rpo_order);
00766 
00767   int block_position(basicblockNode * block, Direction dir);
00768 
00769   basicblockNode * block_at(int position, Direction dir);
00770 
00771   void add_reachable_blocks_rec(Direction dir,
00772                                 basicblockNode * cur,
00773                                 worklist_set & temp, bool first); 
00774 };
00775 
00776 typedef map< procNode *, procedureInfo *> proc_info_map;
00777 typedef proc_info_map::iterator proc_info_map_p;
00778 
00779 typedef list< procedureInfo *> proc_info_list;
00780 typedef proc_info_list::iterator proc_info_list_p;
00781 
00782 typedef pair< stmtLocation *, procedureInfo * > procedurecall_pair;
00783 
00784 typedef list< procedurecall_pair> procedurecall_stack;
00785 typedef procedurecall_stack::iterator procedurecall_stack_p;
00786 typedef procedurecall_stack::const_iterator procedurecall_stack_cp;
00787 typedef procedurecall_stack::reverse_iterator procedurecall_stack_rp;
00788 typedef procedurecall_stack::const_reverse_iterator procedurecall_stack_crp;
00789 
00797 class procedureDB : public Walker
00798 {
00799 private:
00800 
00805   proc_info_map _procedures;
00806 
00809   callGraph * _callgraph;
00810 
00818   procedureinfo_set _need_reanalysis;
00819 
00822   procedureInfo * _root;
00823 
00829   procedurecall_stack _callstack;
00830 
00835   proc_info_list _worklist;
00836 
00837 public:
00838 
00843   procedureDB();
00844 
00847   ~procedureDB();
00848 
00856   void build(procNode * root, Linker & linker);
00857 
00862   void clear();
00863 
00866   void add_procedure(procNode * proc);
00867 
00871   procedureInfo * lookup(procNode * proc);
00872 
00877   inline const procedurecall_stack & callstack() const { return _callstack; }
00878 
00884   bool is_recursive_call(procedureInfo * callee,
00885                          int & num_instances);
00886 
00891   void setup_analysis();
00892 
00897   procedureInfo * next_procedure_on_worklist();
00898 
00903   bool is_procedure_on_worklist(procedureInfo * info);
00904 
00908   void add_procedure_to_worklist(procedureInfo * info);
00909 
00916   void call_to(stmtLocation * callsite, procedureInfo * callee);
00917 
00923   void return_from();
00924 
00930   bool is_visible_to_caller(procedureInfo * info,
00931                             memoryBlock * block);
00932 
00939   bool is_visible_to(procedureInfo * info,
00940                      memoryBlock * block);
00941 
00945   inline stmtLocation * current_callsite() { return _callstack.back().first; }
00946 
00951   procedureInfo * current_caller();
00952 
00957   void clear_call_stack();
00958 
00961   void print_call_stack(ostream & out);
00962 
00965   void progress_meter(ostream & out);
00966 
00974   void mark_for_reanalysis(procedureInfo * info,
00975                            stmtLocation * callsite,
00976                            bool include_self);
00977 
00982   void mark_one_for_reanalysis(procedureInfo * info);
00983 
00990   bool is_reanalysis_required(procedureInfo * info);
00991 
00994   void print_leftovers();
00995 
01003   int times_called(procedureInfo * info);
01004 
01007   void stats(ostream & out);
01008 
01011   int size() const { return _procedures.size(); }
01012 
01017   void number_of_procedures(int & total, int & analyzed,
01018                             int & context_insensitive,
01019                             int & recursive,
01020                             int & unanalyzed,
01021                             int & program_size);
01022 
01023 };
01024 
01025 #endif // CBZ_PROCEDUREDB_H

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