1 //===- DataStructure.h - Build data structure graphs ------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Implement the LLVM data structure analysis library.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_ANALYSIS_DATA_STRUCTURE_H
15 #define LLVM_ANALYSIS_DATA_STRUCTURE_H
17 #include "llvm/Pass.h"
18 #include "llvm/Target/TargetData.h"
19 #include "llvm/ADT/hash_map"
20 #include "llvm/ADT/hash_set"
29 // FIXME: move this stuff to a private header
30 namespace DataStructureAnalysis {
31 /// isPointerType - Return true if this first class type is big enough to hold
34 bool isPointerType(const Type *Ty);
38 // LocalDataStructures - The analysis that computes the local data structure
39 // graphs for all of the functions in the program.
41 // FIXME: This should be a Function pass that can be USED by a Pass, and would
42 // be automatically preserved. Until we can do that, this is a Pass.
44 class LocalDataStructures : public ModulePass {
45 // DSInfo, one graph for each function
46 hash_map<Function*, DSGraph*> DSInfo;
47 DSGraph *GlobalsGraph;
49 ~LocalDataStructures() { releaseMemory(); }
51 virtual bool runOnModule(Module &M);
53 bool hasGraph(const Function &F) const {
54 return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
57 /// getDSGraph - Return the data structure graph for the specified function.
59 DSGraph &getDSGraph(const Function &F) const {
60 hash_map<Function*, DSGraph*>::const_iterator I =
61 DSInfo.find(const_cast<Function*>(&F));
62 assert(I != DSInfo.end() && "Function not in module!");
66 DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
68 /// print - Print out the analysis results...
70 void print(std::ostream &O, const Module *M) const;
72 /// releaseMemory - if the pass pipeline is done with this pass, we can
73 /// release our memory...
75 virtual void releaseMemory();
77 /// getAnalysisUsage - This obviously provides a data structure graph.
79 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
81 AU.addRequired<TargetData>();
86 /// BUDataStructures - The analysis that computes the interprocedurally closed
87 /// data structure graphs for all of the functions in the program. This pass
88 /// only performs a "Bottom Up" propagation (hence the name).
90 class BUDataStructures : public ModulePass {
92 // DSInfo, one graph for each function
93 hash_map<Function*, DSGraph*> DSInfo;
94 DSGraph *GlobalsGraph;
95 hash_multimap<Instruction*, Function*> ActualCallees;
97 ~BUDataStructures() { releaseMemory(); }
99 virtual bool runOnModule(Module &M);
101 bool hasGraph(const Function &F) const {
102 return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
105 /// getDSGraph - Return the data structure graph for the specified function.
107 DSGraph &getDSGraph(const Function &F) const {
108 hash_map<Function*, DSGraph*>::const_iterator I =
109 DSInfo.find(const_cast<Function*>(&F));
110 assert(I != DSInfo.end() && "Function not in module!");
114 DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
116 /// print - Print out the analysis results...
118 void print(std::ostream &O, const Module *M) const;
120 /// releaseMemory - if the pass pipeline is done with this pass, we can
121 /// release our memory...
123 virtual void releaseMemory();
125 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
126 AU.setPreservesAll();
127 AU.addRequired<LocalDataStructures>();
130 typedef hash_multimap<Instruction*, Function*> ActualCalleesTy;
131 const ActualCalleesTy &getActualCallees() const {
132 return ActualCallees;
136 void calculateGraph(DSGraph &G);
138 void calculateReachableGraphs(Function *F);
141 DSGraph &getOrCreateGraph(Function *F);
143 unsigned calculateGraphs(Function *F, std::vector<Function*> &Stack,
145 hash_map<Function*, unsigned> &ValMap);
149 /// TDDataStructures - Analysis that computes new data structure graphs
150 /// for each function using the closed graphs for the callers computed
151 /// by the bottom-up pass.
153 class TDDataStructures : public ModulePass {
154 // DSInfo, one graph for each function
155 hash_map<Function*, DSGraph*> DSInfo;
156 hash_set<Function*> ArgsRemainIncomplete;
157 DSGraph *GlobalsGraph;
159 ~TDDataStructures() { releaseMyMemory(); }
161 virtual bool runOnModule(Module &M);
163 bool hasGraph(const Function &F) const {
164 return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
167 /// getDSGraph - Return the data structure graph for the specified function.
169 DSGraph &getDSGraph(const Function &F) const {
170 hash_map<Function*, DSGraph*>::const_iterator I =
171 DSInfo.find(const_cast<Function*>(&F));
172 assert(I != DSInfo.end() && "Function not in module!");
176 DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
178 /// print - Print out the analysis results...
180 void print(std::ostream &O, const Module *M) const;
182 /// If the pass pipeline is done with this pass, we can release our memory...
184 virtual void releaseMyMemory();
186 /// getAnalysisUsage - This obviously provides a data structure graph.
188 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
189 AU.setPreservesAll();
190 AU.addRequired<BUDataStructures>();
194 void markReachableFunctionsExternallyAccessible(DSNode *N,
195 hash_set<DSNode*> &Visited);
197 void inlineGraphIntoCallees(DSGraph &G);
198 DSGraph &getOrCreateDSGraph(Function &F);
199 void ComputePostOrder(Function &F, hash_set<DSGraph*> &Visited,
200 std::vector<DSGraph*> &PostOrder,
201 const BUDataStructures::ActualCalleesTy &ActualCallees);
205 /// CompleteBUDataStructures - This is the exact same as the bottom-up graphs,
206 /// but we use take a completed call graph and inline all indirect callees into
207 /// their callers graphs, making the result more useful for things like pool
210 struct CompleteBUDataStructures : public BUDataStructures {
211 virtual bool runOnModule(Module &M);
213 bool hasGraph(const Function &F) const {
214 return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
217 /// getDSGraph - Return the data structure graph for the specified function.
219 DSGraph &getDSGraph(const Function &F) const {
220 hash_map<Function*, DSGraph*>::const_iterator I =
221 DSInfo.find(const_cast<Function*>(&F));
222 assert(I != DSInfo.end() && "Function not in module!");
226 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
227 AU.setPreservesAll();
228 AU.addRequired<BUDataStructures>();
230 // FIXME: TEMPORARY (remove once finalization of indirect call sites in the
231 // globals graph has been implemented in the BU pass)
232 AU.addRequired<TDDataStructures>();
235 /// print - Print out the analysis results...
237 void print(std::ostream &O, const Module *M) const;
240 unsigned calculateSCCGraphs(DSGraph &FG, std::vector<DSGraph*> &Stack,
242 hash_map<DSGraph*, unsigned> &ValMap);
243 DSGraph &getOrCreateGraph(Function &F);
244 void processGraph(DSGraph &G);
247 } // End llvm namespace