//===- 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 "Support/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 Pass { // DSInfo, one graph for each function hash_map DSInfo; DSGraph *GlobalsGraph; public: ~LocalDataStructures() { releaseMemory(); } virtual bool run(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 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 Pass { protected: // DSInfo, one graph for each function hash_map DSInfo; DSGraph *GlobalsGraph; hash_multimap ActualCallees; public: ~BUDataStructures() { releaseMemory(); } virtual bool run(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 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 Pass { // DSInfo, one graph for each function hash_map DSInfo; hash_set ArgsRemainIncomplete; DSGraph *GlobalsGraph; public: ~TDDataStructures() { releaseMyMemory(); } virtual bool run(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 run(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