From fa6db4be91670cc3531f2381e05741dc6a1c5a56 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 31 Jan 2002 00:46:09 +0000 Subject: [PATCH] Convert analyze over to use new pass framework for its analyses git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1607 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/analyze/analyze.cpp | 342 +++++++++++++++++++++----------------- 1 file changed, 193 insertions(+), 149 deletions(-) diff --git a/tools/analyze/analyze.cpp b/tools/analyze/analyze.cpp index 9241216f347..3bc2ee9e22e 100644 --- a/tools/analyze/analyze.cpp +++ b/tools/analyze/analyze.cpp @@ -1,4 +1,4 @@ -//===------------------------------------------------------------------------=== +//===----------------------------------------------------------------------===// // LLVM 'Analyze' UTILITY // // This utility is designed to print out the results of running various analysis @@ -8,14 +8,16 @@ // analyze --help - Output information about command line switches // analyze --quiet - Do not print analysis name before output // -//===------------------------------------------------------------------------=== +//===----------------------------------------------------------------------===// #include "llvm/Instruction.h" #include "llvm/Module.h" #include "llvm/Method.h" #include "llvm/iPHINode.h" +#include "llvm/PassManager.h" #include "llvm/Bytecode/Reader.h" #include "llvm/Assembly/Parser.h" +#include "llvm/Assembly/PrintModulePass.h" #include "llvm/Analysis/Writer.h" #include "llvm/Analysis/InstForest.h" #include "llvm/Analysis/Dominators.h" @@ -29,111 +31,168 @@ #include "Support/CommandLine.h" #include #include + using std::cout; -using std::cerr; -using std::pair; +using std::ostream; +using std::string; -static void PrintMethod(Method *M) { - cout << M; +static Module *CurrentModule; + +static void operator<<(ostream &O, const FindUsedTypes &FUT) { + FUT.printTypes(cout, CurrentModule); } -static void PrintIntervalPartition(Method *M) { - cout << cfg::IntervalPartition(M); +static void operator<<(ostream &O, const FindUnsafePointerTypes &FUPT) { + FUPT.printResults(CurrentModule, cout); } -static void PrintClassifiedExprs(Method *M) { - cout << "Classified expressions for: " << M->getName() << "\n"; - Method::inst_iterator I = M->inst_begin(), E = M->inst_end(); - for (; I != E; ++I) { - cout << *I; - if ((*I)->getType() == Type::VoidTy) continue; - analysis::ExprType R = analysis::ClassifyExpression(*I); - if (R.Var == *I) continue; // Doesn't tell us anything - cout << "\t\tExpr ="; - switch (R.ExprTy) { - case analysis::ExprType::ScaledLinear: - WriteAsOperand(cout << "(", (Value*)R.Scale) << " ) *"; - // fall through - case analysis::ExprType::Linear: - WriteAsOperand(cout << "(", R.Var) << " )"; - if (R.Offset == 0) break; - else cout << " +"; - // fall through - case analysis::ExprType::Constant: - if (R.Offset) WriteAsOperand(cout, (Value*)R.Offset); else cout << " 0"; - break; - } - cout << "\n\n"; +template +class PassPrinter; // Do not implement + +template +class PassPrinter : public Pass { + const string Message; + const AnalysisID ID; +public: + PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {} + + virtual bool run(Module *M) { + cout << Message << "\n" << getAnalysis(ID); + return false; } + + virtual void getAnalysisUsageInfo(Pass::AnalysisSet &Required, + Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + Required.push_back(ID); + } +}; + +template +class PassPrinter : public MethodPass { + const string Message; + const AnalysisID ID; +public: + PassPrinter(const string &M, AnalysisID id) : Message(M), ID(id) {} + + virtual bool runOnMethod(Method *M) { + cout << Message << " on method '" << M->getName() << "'\n" + << getAnalysis(ID); + return false; + } + + virtual void getAnalysisUsageInfo(Pass::AnalysisSet &Required, + Pass::AnalysisSet &Destroyed, + Pass::AnalysisSet &Provided) { + Required.push_back(ID); + } +}; + + + +template +Pass *New(const string &Message) { + return new PassPrinter(Message, ID); +} +template +Pass *New(const string &Message) { + return new PassPrinter(Message, PassName::ID); } -static void PrintInductionVariables(Method *M) { - cfg::LoopInfo LI(M); - for (Method::inst_iterator I = M->inst_begin(), E = M->inst_end(); - I != E; ++I) - if (PHINode *PN = dyn_cast(*I)) { - InductionVariable IV(PN, &LI); - if (IV.InductionType != InductionVariable::Unknown) - cout << IV; + + +Pass *NewPrintMethod(const string &Message) { + return new PrintMethodPass(Message, &std::cout); +} +Pass *NewPrintModule(const string &Message) { + return new PrintModulePass(&std::cout); +} + +struct InstForest : public MethodPass { + void doit(Method *M) { + cout << analysis::InstForest(M); + } +}; + +struct IndVars : public MethodPass { + void doit(Method *M) { + cfg::LoopInfo &LI = getAnalysis(); + for (Method::inst_iterator I = M->inst_begin(), E = M->inst_end(); + I != E; ++I) + if (PHINode *PN = dyn_cast(*I)) { + InductionVariable IV(PN, &LI); + if (IV.InductionType != InductionVariable::Unknown) + cout << IV; + } + } + + void getAnalysisUsageInfo(Pass::AnalysisSet &Req, + Pass::AnalysisSet &, Pass::AnalysisSet &) { + Req.push_back(cfg::LoopInfo::ID); + } +}; + +struct Exprs : public MethodPass { + static void doit(Method *M) { + cout << "Classified expressions for: " << M->getName() << "\n"; + Method::inst_iterator I = M->inst_begin(), E = M->inst_end(); + for (; I != E; ++I) { + cout << *I; + + if ((*I)->getType() == Type::VoidTy) continue; + analysis::ExprType R = analysis::ClassifyExpression(*I); + if (R.Var == *I) continue; // Doesn't tell us anything + + cout << "\t\tExpr ="; + switch (R.ExprTy) { + case analysis::ExprType::ScaledLinear: + WriteAsOperand(cout << "(", (Value*)R.Scale) << " ) *"; + // fall through + case analysis::ExprType::Linear: + WriteAsOperand(cout << "(", R.Var) << " )"; + if (R.Offset == 0) break; + else cout << " +"; + // fall through + case analysis::ExprType::Constant: + if (R.Offset) WriteAsOperand(cout, (Value*)R.Offset); else cout << " 0"; + break; + } + cout << "\n\n"; } -} + } +}; -static void PrintInstForest(Method *M) { - cout << analysis::InstForest(M); -} -static void PrintLoops(Method *M) { - cout << cfg::LoopInfo(M); -} -static void PrintCallGraph(Module *M) { - cout << cfg::CallGraph(M); +template +class PrinterPass : public TraitClass { + const string Message; +public: + PrinterPass(const string &M) : Message(M) {} + + virtual bool runOnMethod(Method *M) { + cout << Message << " on method '" << M->getName() << "'\n"; + + TraitClass::doit(M); + return false; + } +}; + + +template +Pass *Create(const string &Message) { + return new PassClass(Message); } -static void PrintUnsafePtrTypes(Module *M) { - FindUnsafePointerTypes FUPT; - FUPT.run(M); - FUPT.printResults(M, cout); -} - -static void PrintUsedTypes(Module *M) { - FindUsedTypes FUT; - FUT.run(M); - FUT.printTypes(cout, M); -} - -static void PrintDominatorSets(Method *M) { - cout << cfg::DominatorSet(M); -} -static void PrintImmediateDominators(Method *M) { - cout << cfg::ImmediateDominators(M); -} -static void PrintDominatorTree(Method *M) { - cout << cfg::DominatorTree(M); -} -static void PrintDominanceFrontier(Method *M) { - cout << cfg::DominanceFrontier(M); -} - -static void PrintPostDominatorSets(Method *M) { - cout << cfg::DominatorSet(M, true); -} -static void PrintImmediatePostDoms(Method *M) { - cout << cfg::ImmediateDominators(cfg::DominatorSet(M, true)); -} -static void PrintPostDomTree(Method *M) { - cout << cfg::DominatorTree(cfg::DominatorSet(M, true)); -} -static void PrintPostDomFrontier(Method *M) { - cout << cfg::DominanceFrontier(cfg::DominatorSet(M, true)); -} enum Ans { - PassDone, // Unique Marker - print, intervals, exprclassify, instforest, loops, indvars, callgraph, - printusedtypes, unsafepointertypes, + // global analyses + print, intervals, exprs, instforest, loops, indvars, + + // ip analyses + printmodule, callgraph, printusedtypes, unsafepointertypes, domset, idom, domtree, domfrontier, postdomset, postidom, postdomtree, postdomfrontier, @@ -143,12 +202,14 @@ cl::String InputFilename ("", "Load file to analyze", cl::NoFlags, "-"); cl::Flag Quiet ("q", "Don't print analysis pass names"); cl::Alias QuietA ("quiet", "Alias for -q", cl::NoFlags, Quiet); cl::EnumList AnalysesList(cl::NoFlags, - clEnumVal(print , "Print each Method"), + clEnumVal(print , "Print each method"), clEnumVal(intervals , "Print Interval Partitions"), - clEnumVal(exprclassify , "Classify Expressions"), + clEnumVal(exprs , "Classify Expressions"), clEnumVal(instforest , "Print Instruction Forest"), clEnumVal(loops , "Print Loops"), clEnumVal(indvars , "Print Induction Variables"), + + clEnumVal(printmodule , "Print entire module"), clEnumVal(callgraph , "Print Call Graph"), clEnumVal(printusedtypes , "Print Types Used by Module"), clEnumVal(unsafepointertypes, "Print Unsafe Pointer Types"), @@ -164,86 +225,69 @@ cl::EnumList AnalysesList(cl::NoFlags, clEnumVal(postdomfrontier, "Print Postdominance Frontier"), 0); + struct { enum Ans AnID; - void (*AnPtr)(Method *M); -} MethAnTable[] = { - { print , PrintMethod }, - { intervals , PrintIntervalPartition }, - { exprclassify , PrintClassifiedExprs }, - { instforest , PrintInstForest }, - { loops , PrintLoops }, - { indvars , PrintInductionVariables }, + Pass *(*PassConstructor)(const string &Message); +} AnTable[] = { + // Global analyses + { print , NewPrintMethod }, + { intervals , New }, + { loops , New }, + { instforest , Create > }, + { indvars , Create > }, + { exprs , Create > }, - { domset , PrintDominatorSets }, - { idom , PrintImmediateDominators }, - { domtree , PrintDominatorTree }, - { domfrontier , PrintDominanceFrontier }, + // IP Analyses... + { printmodule , NewPrintModule }, + { printusedtypes , New }, + { callgraph , New }, + { unsafepointertypes, New }, - { postdomset , PrintPostDominatorSets }, - { postidom , PrintImmediatePostDoms }, - { postdomtree , PrintPostDomTree }, - { postdomfrontier, PrintPostDomFrontier }, + // Dominator analyses + { domset , New }, + { idom , New }, + { domtree , New }, + { domfrontier , New }, + + { postdomset , New }, + { postidom , New }, + { postdomtree , New }, + { postdomfrontier , New }, }; -pair ModAnTable[] = { - pair(callgraph , PrintCallGraph), - pair(printusedtypes , PrintUsedTypes), - pair(unsafepointertypes, PrintUnsafePtrTypes), -}; - - - int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, " llvm analysis printer tool\n"); - Module *C = ParseBytecodeFile(InputFilename); - if (!C && !(C = ParseAssemblyFile(InputFilename))) { - cerr << "Input file didn't read correctly.\n"; + CurrentModule = ParseBytecodeFile(InputFilename); + if (!CurrentModule && !(CurrentModule = ParseAssemblyFile(InputFilename))) { + std::cerr << "Input file didn't read correctly.\n"; return 1; } - // Loop over all of the analyses looking for module level analyses to run... + // Create a PassManager to hold and optimize the collection of passes we are + // about to build... + // + PassManager Analyses; + + // Loop over all of the analyses looking for analyses to run... for (unsigned i = 0; i < AnalysesList.size(); ++i) { enum Ans AnalysisPass = AnalysesList[i]; - for (unsigned j = 0; j < sizeof(ModAnTable)/sizeof(ModAnTable[0]); ++j) { - if (ModAnTable[j].first == AnalysisPass) { + for (unsigned j = 0; j < sizeof(AnTable)/sizeof(AnTable[0]); ++j) { + if (AnTable[j].AnID == AnalysisPass) { + string Message; if (!Quiet) - cerr << "Running: " << AnalysesList.getArgDescription(AnalysisPass) - << " analysis on module!\n"; - ModAnTable[j].second(C); - AnalysesList[i] = PassDone; // Mark pass as complete so that we don't + Message = "\nRunning: '" + + string(AnalysesList.getArgDescription(AnalysisPass)) + "' analysis"; + Analyses.add(AnTable[j].PassConstructor(Message)); break; // get an error later } } } - // Loop over all of the methods in the module... - for (Module::iterator I = C->begin(), E = C->end(); I != E; ++I) { - Method *M = *I; - if (M->isExternal()) continue; + Analyses.run(CurrentModule); - for (unsigned i = 0; i < AnalysesList.size(); ++i) { - enum Ans AnalysisPass = AnalysesList[i]; - if (AnalysisPass == PassDone) continue; // Don't rerun module analyses - - // Loop over all of the analyses to be run... - unsigned j; - for (j = 0; j < sizeof(MethAnTable)/sizeof(MethAnTable[0]); ++j) { - if (AnalysisPass == MethAnTable[j].AnID) { - if (!Quiet) - cerr << "Running: " << AnalysesList.getArgDescription(AnalysisPass) - << " analysis on '" << ((Value*)M)->getName() << "'!\n"; - MethAnTable[j].AnPtr(M); - break; - } - } - if (j == sizeof(MethAnTable)/sizeof(MethAnTable[0])) - cerr << "Analysis tables inconsistent!\n"; - } - } - - delete C; + delete CurrentModule; return 0; }