00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
00093
00094 typedef map< stmtLocation *, memoryblock_set> callsite_changes_map;
00095 typedef callsite_changes_map::iterator callsite_changes_map_p;
00096
00097
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
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