//===- DataStructure.h - Build data structure graphs ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file was developed by the LLVM research group and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Implement the LLVM data structure analysis library. // //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_DATA_STRUCTURE_H #define LLVM_ANALYSIS_DATA_STRUCTURE_H #include "llvm/Pass.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/hash_set" namespace llvm { class Type; class Instruction; class DSGraph; class DSNode; // FIXME: move this stuff to a private header namespace DataStructureAnalysis { /// isPointerType - Return true if this first class type is big enough to hold /// a pointer. /// bool isPointerType(const Type *Ty); } // LocalDataStructures - The analysis that computes the local data structure // graphs for all of the functions in the program. // // FIXME: This should be a Function pass that can be USED by a Pass, and would // be automatically preserved. Until we can do that, this is a Pass. // class LocalDataStructures : public ModulePass { // DSInfo, one graph for each function hash_map DSInfo; DSGraph *GlobalsGraph; public: ~LocalDataStructures() { releaseMemory(); } virtual bool runOnModule(Module &M); bool hasGraph(const Function &F) const { return DSInfo.find(const_cast(&F)) != DSInfo.end(); } /// getDSGraph - Return the data structure graph for the specified function. /// DSGraph &getDSGraph(const Function &F) const { hash_map::const_iterator I = DSInfo.find(const_cast(&F)); assert(I != DSInfo.end() && "Function not in module!"); return *I->second; } DSGraph &getGlobalsGraph() const { return *GlobalsGraph; } /// print - Print out the analysis results... /// void print(std::ostream &O, const Module *M) const; /// releaseMemory - if the pass pipeline is done with this pass, we can /// release our memory... /// virtual void releaseMemory(); /// getAnalysisUsage - This obviously provides a data structure graph. /// virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); } }; /// BUDataStructures - The analysis that computes the interprocedurally closed /// data structure graphs for all of the functions in the program. This pass /// only performs a "Bottom Up" propagation (hence the name). /// class BUDataStructures : public ModulePass { protected: // DSInfo, one graph for each function hash_map DSInfo; DSGraph *GlobalsGraph; hash_multimap ActualCallees; public: ~BUDataStructures() { releaseMemory(); } virtual bool runOnModule(Module &M); bool hasGraph(const Function &F) const { return DSInfo.find(const_cast(&F)) != DSInfo.end(); } /// getDSGraph - Return the data structure graph for the specified function. /// DSGraph &getDSGraph(const Function &F) const { hash_map::const_iterator I = DSInfo.find(const_cast(&F)); assert(I != DSInfo.end() && "Function not in module!"); return *I->second; } DSGraph &getGlobalsGraph() const { return *GlobalsGraph; } /// print - Print out the analysis results... /// void print(std::ostream &O, const Module *M) const; /// releaseMemory - if the pass pipeline is done with this pass, we can /// release our memory... /// virtual void releaseMemory(); virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); } typedef hash_multimap ActualCalleesTy; const ActualCalleesTy &getActualCallees() const { return ActualCallees; } private: void calculateGraph(DSGraph &G); void calculateReachableGraphs(Function *F); DSGraph &getOrCreateGraph(Function *F); unsigned calculateGraphs(Function *F, std::vector &Stack, unsigned &NextID, hash_map &ValMap); }; /// TDDataStructures - Analysis that computes new data structure graphs /// for each function using the closed graphs for the callers computed /// by the bottom-up pass. /// class TDDataStructures : public ModulePass { // DSInfo, one graph for each function hash_map DSInfo; hash_set ArgsRemainIncomplete; DSGraph *GlobalsGraph; public: ~TDDataStructures() { releaseMyMemory(); } virtual bool runOnModule(Module &M); bool hasGraph(const Function &F) const { return DSInfo.find(const_cast(&F)) != DSInfo.end(); } /// getDSGraph - Return the data structure graph for the specified function. /// DSGraph &getDSGraph(const Function &F) const { hash_map::const_iterator I = DSInfo.find(const_cast(&F)); assert(I != DSInfo.end() && "Function not in module!"); return *I->second; } DSGraph &getGlobalsGraph() const { return *GlobalsGraph; } /// print - Print out the analysis results... /// void print(std::ostream &O, const Module *M) const; /// If the pass pipeline is done with this pass, we can release our memory... /// virtual void releaseMyMemory(); /// getAnalysisUsage - This obviously provides a data structure graph. /// virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); } private: void markReachableFunctionsExternallyAccessible(DSNode *N, hash_set &Visited); void inlineGraphIntoCallees(DSGraph &G); DSGraph &getOrCreateDSGraph(Function &F); void ComputePostOrder(Function &F, hash_set &Visited, std::vector &PostOrder, const BUDataStructures::ActualCalleesTy &ActualCallees); }; /// CompleteBUDataStructures - This is the exact same as the bottom-up graphs, /// but we use take a completed call graph and inline all indirect callees into /// their callers graphs, making the result more useful for things like pool /// allocation. /// struct CompleteBUDataStructures : public BUDataStructures { virtual bool runOnModule(Module &M); bool hasGraph(const Function &F) const { return DSInfo.find(const_cast(&F)) != DSInfo.end(); } /// getDSGraph - Return the data structure graph for the specified function. /// DSGraph &getDSGraph(const Function &F) const { hash_map::const_iterator I = DSInfo.find(const_cast(&F)); assert(I != DSInfo.end() && "Function not in module!"); return *I->second; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); // FIXME: TEMPORARY (remove once finalization of indirect call sites in the // globals graph has been implemented in the BU pass) AU.addRequired(); } /// print - Print out the analysis results... /// void print(std::ostream &O, const Module *M) const; private: unsigned calculateSCCGraphs(DSGraph &FG, std::vector &Stack, unsigned &NextID, hash_map &ValMap); DSGraph &getOrCreateGraph(Function &F); void processGraph(DSGraph &G); }; } // End llvm namespace #endif