Created
October 16, 2022 20:39
-
-
Save Trass3r/ec4f9050515c22c7efe4906da1899bfc to your computer and use it in GitHub Desktop.
Support for machine function cfg dot dump - https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130610/177469.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: include/llvm/Analysis/CFGPrinter.h | |
=================================================================== | |
--- include/llvm/Analysis/CFGPrinter.h (revision 177877) | |
+++ include/llvm/Analysis/CFGPrinter.h (working copy) | |
@@ -15,6 +15,7 @@ | |
#ifndef LLVM_ANALYSIS_CFGPRINTER_H | |
#define LLVM_ANALYSIS_CFGPRINTER_H | |
+#include "llvm/PassSupport.h" | |
#include "llvm/Assembly/Writer.h" | |
#include "llvm/IR/Constants.h" | |
#include "llvm/IR/Function.h" | |
@@ -103,12 +104,42 @@ struct DOTGraphTraits<const Function*> : | |
return ""; | |
} | |
}; | |
-} // End llvm namespace | |
-namespace llvm { | |
- class FunctionPass; | |
- FunctionPass *createCFGPrinterPass (); | |
- FunctionPass *createCFGOnlyPrinterPass (); | |
+template <class FC, bool CFGOnly> struct CFGPrinterBase { | |
+ CFGPrinterBase(const PassInfo *P = 0, const char *O = 0) : PI(P), Order(O) { | |
+ assert(!PI == !Order); | |
+ } | |
+ bool run(FC *F) { | |
+ std::string Filename = "cfg." + F->template getName().str(); | |
+ if (PI) | |
+ Filename = Filename + "." + Order + "." + PI->getPassArgument() + ".dot"; | |
+ else | |
+ Filename += ".dot"; | |
+ errs() << "Writing '" << Filename << "'..."; | |
+ | |
+ std::string ErrorInfo; | |
+ raw_fd_ostream File(Filename.c_str(), ErrorInfo); | |
+ | |
+ if (ErrorInfo.empty()) | |
+ WriteGraph(File, (const FC *)F, CFGOnly); | |
+ else | |
+ errs() << " error opening file for writing!"; | |
+ | |
+ errs() << "\n"; | |
+ return false; | |
+ } | |
+ | |
+private: | |
+ const PassInfo *PI; | |
+ const char *Order; | |
+}; | |
+ | |
+class FunctionPass; | |
+FunctionPass *createCFGPrinterPass(); | |
+FunctionPass *createCFGPrinterPass(const PassInfo *, const char *); | |
+FunctionPass *createCFGOnlyPrinterPass(); | |
+FunctionPass *createMachineCFGPrinterPass(const PassInfo *, const char *); | |
+FunctionPass *createMachineCFGOnlyPrinterPass(); | |
} // End llvm namespace | |
#endif | |
Index: include/llvm/Analysis/CFGPrinter.h | |
=================================================================== | |
--- include/llvm/Analysis/CFGPrinter.h (revision 183332) | |
+++ include/llvm/Analysis/CFGPrinter.h (working copy) | |
@@ -1,114 +0,0 @@ | |
-//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===// | |
-// | |
-// The LLVM Compiler Infrastructure | |
-// | |
-// This file is distributed under the University of Illinois Open Source | |
-// License. See LICENSE.TXT for details. | |
-// | |
-//===----------------------------------------------------------------------===// | |
-// | |
-// This file defines external functions that can be called to explicitly | |
-// instantiate the CFG printer. | |
-// | |
-//===----------------------------------------------------------------------===// | |
- | |
-#ifndef LLVM_ANALYSIS_CFGPRINTER_H | |
-#define LLVM_ANALYSIS_CFGPRINTER_H | |
- | |
-#include "llvm/Assembly/Writer.h" | |
-#include "llvm/IR/Constants.h" | |
-#include "llvm/IR/Function.h" | |
-#include "llvm/IR/Instructions.h" | |
-#include "llvm/Analysis/CFG.h" | |
-#include "llvm/Support/GraphWriter.h" | |
- | |
-namespace llvm { | |
-template<> | |
-struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { | |
- | |
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} | |
- | |
- static std::string getGraphName(const Function *F) { | |
- return "CFG for '" + F->getName().str() + "' function"; | |
- } | |
- | |
- static std::string getSimpleNodeLabel(const BasicBlock *Node, | |
- const Function *) { | |
- if (!Node->getName().empty()) | |
- return Node->getName().str(); | |
- | |
- std::string Str; | |
- raw_string_ostream OS(Str); | |
- | |
- WriteAsOperand(OS, Node, false); | |
- return OS.str(); | |
- } | |
- | |
- static std::string getCompleteNodeLabel(const BasicBlock *Node, | |
- const Function *) { | |
- std::string Str; | |
- raw_string_ostream OS(Str); | |
- | |
- if (Node->getName().empty()) { | |
- WriteAsOperand(OS, Node, false); | |
- OS << ":"; | |
- } | |
- | |
- OS << *Node; | |
- std::string OutStr = OS.str(); | |
- if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); | |
- | |
- // Process string output to make it nicer... | |
- for (unsigned i = 0; i != OutStr.length(); ++i) | |
- if (OutStr[i] == '\n') { // Left justify | |
- OutStr[i] = '\\'; | |
- OutStr.insert(OutStr.begin()+i+1, 'l'); | |
- } else if (OutStr[i] == ';') { // Delete comments! | |
- unsigned Idx = OutStr.find('\n', i+1); // Find end of line | |
- OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); | |
- --i; | |
- } | |
- | |
- return OutStr; | |
- } | |
- | |
- std::string getNodeLabel(const BasicBlock *Node, | |
- const Function *Graph) { | |
- if (isSimple()) | |
- return getSimpleNodeLabel(Node, Graph); | |
- else | |
- return getCompleteNodeLabel(Node, Graph); | |
- } | |
- | |
- static std::string getEdgeSourceLabel(const BasicBlock *Node, | |
- succ_const_iterator I) { | |
- // Label source of conditional branches with "T" or "F" | |
- if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator())) | |
- if (BI->isConditional()) | |
- return (I == succ_begin(Node)) ? "T" : "F"; | |
- | |
- // Label source of switch edges with the associated value. | |
- if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) { | |
- unsigned SuccNo = I.getSuccessorIndex(); | |
- | |
- if (SuccNo == 0) return "def"; | |
- | |
- std::string Str; | |
- raw_string_ostream OS(Str); | |
- SwitchInst::ConstCaseIt Case = | |
- SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); | |
- OS << Case.getCaseValue()->getValue(); | |
- return OS.str(); | |
- } | |
- return ""; | |
- } | |
-}; | |
-} // End llvm namespace | |
- | |
-namespace llvm { | |
- class FunctionPass; | |
- FunctionPass *createCFGPrinterPass (); | |
- FunctionPass *createCFGOnlyPrinterPass (); | |
-} // End llvm namespace | |
- | |
-#endif | |
Index: include/llvm/Analysis/DOTGraphTraitsPass.h | |
=================================================================== | |
--- include/llvm/Analysis/DOTGraphTraitsPass.h (revision 183332) | |
+++ include/llvm/Analysis/DOTGraphTraitsPass.h (working copy) | |
@@ -14,7 +14,7 @@ | |
#ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H | |
#define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H | |
-#include "llvm/Analysis/CFGPrinter.h" | |
+#include "llvm/Analysis/CFGPrinter.h" | |
#include "llvm/Pass.h" | |
namespace llvm { | |
Index: include/llvm/Pass.h | |
=================================================================== | |
--- include/llvm/Pass.h (revision 183332) | |
+++ include/llvm/Pass.h (working copy) | |
@@ -129,6 +129,11 @@ public: | |
virtual Pass *createPrinterPass(raw_ostream &O, | |
const std::string &Banner) const = 0; | |
+ /// createCFGPrinterPass - Get a Pass appropriate to print the CFG of functions | |
+ /// this pass operates. By default it returns Function CFG Printer pass. The | |
+ /// MachineFunction Pass overrides the definition. | |
+ virtual Pass *createCFGPrinterPass(const PassInfo *PI, const char *) const; | |
+ | |
/// Each pass is responsible for assigning a pass manager to itself. | |
/// PMS is the stack of available pass manager. | |
virtual void assignPassManager(PMStack &, | |
Index: include/llvm/CodeGen/MachineFunctionPass.h | |
=================================================================== | |
--- include/llvm/CodeGen/MachineFunctionPass.h (revision 183332) | |
+++ include/llvm/CodeGen/MachineFunctionPass.h (working copy) | |
@@ -51,6 +51,8 @@ private: | |
virtual Pass *createPrinterPass(raw_ostream &O, | |
const std::string &Banner) const; | |
+ virtual Pass *createCFGPrinterPass(const PassInfo *, const char *) const; | |
+ | |
virtual bool runOnFunction(Function &F); | |
}; | |
Index: lib/IR/PassManager.cpp | |
=================================================================== | |
--- lib/IR/PassManager.cpp (revision 183335) | |
+++ lib/IR/PassManager.cpp (working copy) | |
@@ -17,6 +17,7 @@ | |
#include "llvm/Assembly/Writer.h" | |
#include "llvm/IR/Module.h" | |
#include "llvm/PassManager.h" | |
+#include "llvm/Analysis/CFGPrinter.h" | |
#include "llvm/Support/CommandLine.h" | |
#include "llvm/Support/Debug.h" | |
#include "llvm/Support/ErrorHandling.h" | |
@@ -70,6 +71,16 @@ PrintAfter("print-after", | |
llvm::cl::desc("Print IR after specified passes"), | |
cl::Hidden); | |
+static PassOptionList | |
+DotCfgBefore("dot-cfg-before", | |
+ llvm::cl::desc("Dump CFG DOT file before specified passes"), | |
+ cl::Hidden); | |
+ | |
+static PassOptionList | |
+DotCfgAfter("dot-cfg-after", | |
+ llvm::cl::desc("Dump CFG DOT file after specified passes"), | |
+ cl::Hidden); | |
+ | |
static cl::opt<bool> | |
PrintBeforeAll("print-before-all", | |
llvm::cl::desc("Print IR before each pass"), | |
@@ -106,6 +117,18 @@ static bool ShouldPrintAfterPass(const P | |
return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter); | |
} | |
+/// This is a utility to check whether a pass should have DOT CFG dumped | |
+/// before it. | |
+static bool ShouldPrintCFGBeforePass(const PassInfo *PI) { | |
+ return ShouldPrintBeforeOrAfterPass(PI, DotCfgBefore); | |
+} | |
+ | |
+/// This is a utility to check whether a pass should have DOT CFG dumped | |
+/// after it. | |
+static bool ShouldPrintCFGAfterPass(const PassInfo *PI) { | |
+ return ShouldPrintBeforeOrAfterPass(PI, DotCfgAfter); | |
+} | |
+ | |
} // End of llvm namespace | |
/// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions | |
@@ -674,6 +697,12 @@ void PMTopLevelManager::schedulePass(Pas | |
PP->assignPassManager(activeStack, getTopLevelPassManagerType()); | |
} | |
+ if (PI && !PI->isAnalysis() && (P->getPassKind() != PT_Loop) && | |
+ ShouldPrintCFGBeforePass(PI)) { | |
+ Pass *PP = P->createCFGPrinterPass(PI, "before"); | |
+ PP->assignPassManager(activeStack, getTopLevelPassManagerType()); | |
+ } | |
+ | |
// Add the requested pass to the best available pass manager. | |
P->assignPassManager(activeStack, getTopLevelPassManagerType()); | |
@@ -682,6 +711,11 @@ void PMTopLevelManager::schedulePass(Pas | |
dbgs(), std::string("*** IR Dump After ") + P->getPassName() + " ***"); | |
PP->assignPassManager(activeStack, getTopLevelPassManagerType()); | |
} | |
+ | |
+ if (PI && !PI->isAnalysis() && ShouldPrintCFGAfterPass(PI)) { | |
+ Pass *PP = P->createCFGPrinterPass(PI, "after"); | |
+ PP->assignPassManager(activeStack, getTopLevelPassManagerType()); | |
+ } | |
} | |
/// Find the pass that implements Analysis AID. Search immutable | |
Index: lib/IR/Pass.cpp | |
=================================================================== | |
--- lib/IR/Pass.cpp (revision 183335) | |
+++ lib/IR/Pass.cpp (working copy) | |
@@ -16,6 +16,7 @@ | |
#include "llvm/Pass.h" | |
#include "llvm/Assembly/PrintModulePass.h" | |
#include "llvm/PassRegistry.h" | |
+#include "llvm/Analysis/CFGPrinter.h" | |
#include "llvm/Support/Debug.h" | |
#include "llvm/Support/PassNameParser.h" | |
#include "llvm/Support/raw_ostream.h" | |
@@ -63,6 +64,10 @@ const char *Pass::getPassName() const { | |
return "Unnamed pass: implement Pass::getPassName()"; | |
} | |
+Pass * Pass::createCFGPrinterPass(const PassInfo *PI, const char *O) const { | |
+ return llvm::createCFGPrinterPass(PI, O); | |
+} | |
+ | |
void Pass::preparePassManager(PMStack &) { | |
// By default, don't do anything. | |
} | |
Index: lib/Analysis/CFGPrinter.cpp | |
=================================================================== | |
--- lib/Analysis/CFGPrinter.cpp (revision 177877) | |
+++ lib/Analysis/CFGPrinter.cpp (working copy) | |
@@ -17,8 +17,10 @@ | |
// | |
//===----------------------------------------------------------------------===// | |
-#include "llvm/Analysis/CFGPrinter.h" | |
+#include "llvm/Analysis/CFGPrinter.h" | |
#include "llvm/Pass.h" | |
+#include "llvm/CodeGen/MachineFunction.h" | |
+#include "llvm/CodeGen/MachineFunctionPass.h" | |
using namespace llvm; | |
namespace { | |
@@ -69,69 +71,42 @@ INITIALIZE_PASS(CFGOnlyViewer, "view-cfg | |
"View CFG of function (with no function bodies)", false, true) | |
namespace { | |
- struct CFGPrinter : public FunctionPass { | |
- static char ID; // Pass identification, replacement for typeid | |
- CFGPrinter() : FunctionPass(ID) { | |
+template <bool CFGOnly> | |
+struct CFGPrinterT : public FunctionPass, | |
+ public CFGPrinterBase<Function, CFGOnly> { | |
+ | |
+ static char ID; // Pass identification, replacement for typeid | |
+ typedef CFGPrinterBase<Function, CFGOnly> BaseT; | |
+ | |
+ CFGPrinterT(const PassInfo *P = 0, const char *O = 0) | |
+ : FunctionPass(ID), BaseT(P, O) { | |
+ if (CFGOnly) | |
+ initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); | |
+ else | |
initializeCFGPrinterPass(*PassRegistry::getPassRegistry()); | |
- } | |
+ } | |
- virtual bool runOnFunction(Function &F) { | |
- std::string Filename = "cfg." + F.getName().str() + ".dot"; | |
- errs() << "Writing '" << Filename << "'..."; | |
- | |
- std::string ErrorInfo; | |
- raw_fd_ostream File(Filename.c_str(), ErrorInfo); | |
- | |
- if (ErrorInfo.empty()) | |
- WriteGraph(File, (const Function*)&F); | |
- else | |
- errs() << " error opening file for writing!"; | |
- errs() << "\n"; | |
- return false; | |
- } | |
+ virtual bool runOnFunction(Function &F) { return BaseT::run(&F); } | |
- void print(raw_ostream &OS, const Module* = 0) const {} | |
+ void print(raw_ostream &OS, const Module * = 0) const {} | |
- virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
- AU.setPreservesAll(); | |
- } | |
- }; | |
-} | |
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
+ AU.setPreservesAll(); | |
+ } | |
+}; | |
-char CFGPrinter::ID = 0; | |
-INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", | |
- false, true) | |
-namespace { | |
- struct CFGOnlyPrinter : public FunctionPass { | |
- static char ID; // Pass identification, replacement for typeid | |
- CFGOnlyPrinter() : FunctionPass(ID) { | |
- initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); | |
- } | |
- | |
- virtual bool runOnFunction(Function &F) { | |
- std::string Filename = "cfg." + F.getName().str() + ".dot"; | |
- errs() << "Writing '" << Filename << "'..."; | |
+template<bool CFGOnly> char CFGPrinterT<CFGOnly> ::ID = 0; | |
+template struct CFGPrinterT<true>; | |
+template struct CFGPrinterT<false>; | |
+typedef CFGPrinterT<true> CFGOnlyPrinter; | |
+typedef CFGPrinterT<false> CFGPrinter; | |
- std::string ErrorInfo; | |
- raw_fd_ostream File(Filename.c_str(), ErrorInfo); | |
- | |
- if (ErrorInfo.empty()) | |
- WriteGraph(File, (const Function*)&F, true); | |
- else | |
- errs() << " error opening file for writing!"; | |
- errs() << "\n"; | |
- return false; | |
- } | |
- void print(raw_ostream &OS, const Module* = 0) const {} | |
- | |
- virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
- AU.setPreservesAll(); | |
- } | |
- }; | |
} | |
-char CFGOnlyPrinter::ID = 0; | |
+INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", | |
+ false, true) | |
+ | |
INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only", | |
"Print CFG of function to 'dot' file (with no function bodies)", | |
false, true) | |
@@ -158,7 +133,10 @@ FunctionPass *llvm::createCFGPrinterPass | |
return new CFGPrinter(); | |
} | |
+FunctionPass *llvm::createCFGPrinterPass (const PassInfo *PI, const char *O) { | |
+ return new CFGPrinter(PI, O); | |
+} | |
+ | |
FunctionPass *llvm::createCFGOnlyPrinterPass () { | |
return new CFGOnlyPrinter(); | |
} | |
- | |
Index: lib/Analysis/CFGPrinter.cpp | |
=================================================================== | |
--- lib/Analysis/CFGPrinter.cpp (revision 183332) | |
+++ lib/Analysis/CFGPrinter.cpp (working copy) | |
@@ -1,164 +0,0 @@ | |
-//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===// | |
-// | |
-// The LLVM Compiler Infrastructure | |
-// | |
-// This file is distributed under the University of Illinois Open Source | |
-// License. See LICENSE.TXT for details. | |
-// | |
-//===----------------------------------------------------------------------===// | |
-// | |
-// This file defines a '-dot-cfg' analysis pass, which emits the | |
-// cfg.<fnname>.dot file for each function in the program, with a graph of the | |
-// CFG for that function. | |
-// | |
-// The other main feature of this file is that it implements the | |
-// Function::viewCFG method, which is useful for debugging passes which operate | |
-// on the CFG. | |
-// | |
-//===----------------------------------------------------------------------===// | |
- | |
-#include "llvm/Analysis/CFGPrinter.h" | |
-#include "llvm/Pass.h" | |
-using namespace llvm; | |
- | |
-namespace { | |
- struct CFGViewer : public FunctionPass { | |
- static char ID; // Pass identifcation, replacement for typeid | |
- CFGViewer() : FunctionPass(ID) { | |
- initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); | |
- } | |
- | |
- virtual bool runOnFunction(Function &F) { | |
- F.viewCFG(); | |
- return false; | |
- } | |
- | |
- void print(raw_ostream &OS, const Module* = 0) const {} | |
- | |
- virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
- AU.setPreservesAll(); | |
- } | |
- }; | |
-} | |
- | |
-char CFGViewer::ID = 0; | |
-INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true) | |
- | |
-namespace { | |
- struct CFGOnlyViewer : public FunctionPass { | |
- static char ID; // Pass identifcation, replacement for typeid | |
- CFGOnlyViewer() : FunctionPass(ID) { | |
- initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); | |
- } | |
- | |
- virtual bool runOnFunction(Function &F) { | |
- F.viewCFGOnly(); | |
- return false; | |
- } | |
- | |
- void print(raw_ostream &OS, const Module* = 0) const {} | |
- | |
- virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
- AU.setPreservesAll(); | |
- } | |
- }; | |
-} | |
- | |
-char CFGOnlyViewer::ID = 0; | |
-INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only", | |
- "View CFG of function (with no function bodies)", false, true) | |
- | |
-namespace { | |
- struct CFGPrinter : public FunctionPass { | |
- static char ID; // Pass identification, replacement for typeid | |
- CFGPrinter() : FunctionPass(ID) { | |
- initializeCFGPrinterPass(*PassRegistry::getPassRegistry()); | |
- } | |
- | |
- virtual bool runOnFunction(Function &F) { | |
- std::string Filename = "cfg." + F.getName().str() + ".dot"; | |
- errs() << "Writing '" << Filename << "'..."; | |
- | |
- std::string ErrorInfo; | |
- raw_fd_ostream File(Filename.c_str(), ErrorInfo); | |
- | |
- if (ErrorInfo.empty()) | |
- WriteGraph(File, (const Function*)&F); | |
- else | |
- errs() << " error opening file for writing!"; | |
- errs() << "\n"; | |
- return false; | |
- } | |
- | |
- void print(raw_ostream &OS, const Module* = 0) const {} | |
- | |
- virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
- AU.setPreservesAll(); | |
- } | |
- }; | |
-} | |
- | |
-char CFGPrinter::ID = 0; | |
-INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", | |
- false, true) | |
- | |
-namespace { | |
- struct CFGOnlyPrinter : public FunctionPass { | |
- static char ID; // Pass identification, replacement for typeid | |
- CFGOnlyPrinter() : FunctionPass(ID) { | |
- initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); | |
- } | |
- | |
- virtual bool runOnFunction(Function &F) { | |
- std::string Filename = "cfg." + F.getName().str() + ".dot"; | |
- errs() << "Writing '" << Filename << "'..."; | |
- | |
- std::string ErrorInfo; | |
- raw_fd_ostream File(Filename.c_str(), ErrorInfo); | |
- | |
- if (ErrorInfo.empty()) | |
- WriteGraph(File, (const Function*)&F, true); | |
- else | |
- errs() << " error opening file for writing!"; | |
- errs() << "\n"; | |
- return false; | |
- } | |
- void print(raw_ostream &OS, const Module* = 0) const {} | |
- | |
- virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
- AU.setPreservesAll(); | |
- } | |
- }; | |
-} | |
- | |
-char CFGOnlyPrinter::ID = 0; | |
-INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only", | |
- "Print CFG of function to 'dot' file (with no function bodies)", | |
- false, true) | |
- | |
-/// viewCFG - This function is meant for use from the debugger. You can just | |
-/// say 'call F->viewCFG()' and a ghostview window should pop up from the | |
-/// program, displaying the CFG of the current function. This depends on there | |
-/// being a 'dot' and 'gv' program in your path. | |
-/// | |
-void Function::viewCFG() const { | |
- ViewGraph(this, "cfg" + getName()); | |
-} | |
- | |
-/// viewCFGOnly - This function is meant for use from the debugger. It works | |
-/// just like viewCFG, but it does not include the contents of basic blocks | |
-/// into the nodes, just the label. If you are only interested in the CFG t | |
-/// his can make the graph smaller. | |
-/// | |
-void Function::viewCFGOnly() const { | |
- ViewGraph(this, "cfg" + getName(), true); | |
-} | |
- | |
-FunctionPass *llvm::createCFGPrinterPass () { | |
- return new CFGPrinter(); | |
-} | |
- | |
-FunctionPass *llvm::createCFGOnlyPrinterPass () { | |
- return new CFGOnlyPrinter(); | |
-} | |
- | |
Index: lib/CodeGen/MachineFunctionPass.cpp | |
=================================================================== | |
--- lib/CodeGen/MachineFunctionPass.cpp (revision 183335) | |
+++ lib/CodeGen/MachineFunctionPass.cpp (working copy) | |
@@ -16,6 +16,7 @@ | |
#include "llvm/CodeGen/MachineFunctionAnalysis.h" | |
#include "llvm/CodeGen/MachineFunctionPass.h" | |
#include "llvm/CodeGen/Passes.h" | |
+#include "llvm/Analysis/CFGPrinter.h" | |
using namespace llvm; | |
Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O, | |
@@ -23,6 +24,12 @@ Pass *MachineFunctionPass::createPrinter | |
return createMachineFunctionPrinterPass(O, Banner); | |
} | |
+Pass *MachineFunctionPass::createCFGPrinterPass(const PassInfo *PI, | |
+ const char *O) const { | |
+ | |
+ return createMachineCFGPrinterPass(PI, O); | |
+} | |
+ | |
bool MachineFunctionPass::runOnFunction(Function &F) { | |
// Do not codegen any 'available_externally' functions at all, they have | |
// definitions outside the translation unit. | |
Index: lib/CodeGen/MachineFunctionPrinterPass.cpp | |
=================================================================== | |
--- lib/CodeGen/MachineFunctionPrinterPass.cpp (revision 183335) | |
+++ lib/CodeGen/MachineFunctionPrinterPass.cpp (working copy) | |
@@ -15,6 +15,7 @@ | |
#include "llvm/CodeGen/MachineFunction.h" | |
#include "llvm/CodeGen/MachineFunctionPass.h" | |
#include "llvm/CodeGen/SlotIndexes.h" | |
+#include "llvm/Analysis/CFGPrinter.h" | |
#include "llvm/Support/Debug.h" | |
#include "llvm/Support/raw_ostream.h" | |
@@ -49,12 +50,54 @@ struct MachineFunctionPrinterPass : publ | |
}; | |
char MachineFunctionPrinterPass::ID = 0; | |
+ | |
+template <bool CFGOnly> | |
+struct MachineCFGPrinterT : public MachineFunctionPass, | |
+ public CFGPrinterBase<MachineFunction, CFGOnly> { | |
+ | |
+ static char ID; // Pass identification, replacement for typeid | |
+ typedef CFGPrinterBase<MachineFunction, CFGOnly> BaseT; | |
+ | |
+ MachineCFGPrinterT(const PassInfo *P = 0, const char *O = 0) | |
+ : MachineFunctionPass(ID), BaseT(P, O) { | |
+ if (CFGOnly) | |
+ initializeMachineCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); | |
+ else | |
+ initializeMachineCFGPrinterPass(*PassRegistry::getPassRegistry()); | |
+ } | |
+ | |
+ virtual bool runOnMachineFunction(MachineFunction &F) { | |
+ return BaseT::run(&F); | |
+ } | |
+ | |
+ void print(raw_ostream &OS, const Module * = 0) const {} | |
+ | |
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const { | |
+ AU.setPreservesAll(); | |
+ MachineFunctionPass::getAnalysisUsage(AU); | |
+ } | |
+}; | |
+ | |
+template <bool CFGOnly> char MachineCFGPrinterT<CFGOnly>::ID = 0; | |
+template struct MachineCFGPrinterT<true>; | |
+template struct MachineCFGPrinterT<false>; | |
+typedef MachineCFGPrinterT<true> MachineCFGOnlyPrinter; | |
+typedef MachineCFGPrinterT<false> MachineCFGPrinter; | |
+ | |
} | |
char &llvm::MachineFunctionPrinterPassID = MachineFunctionPrinterPass::ID; | |
INITIALIZE_PASS(MachineFunctionPrinterPass, "print-machineinstrs", | |
"Machine Function Printer", false, false) | |
+INITIALIZE_PASS(MachineCFGPrinter, "machine-dot-cfg", | |
+ "Print CFG of machine function to 'dot' file", false, true) | |
+INITIALIZE_PASS( | |
+ MachineCFGOnlyPrinter, "machine-dot-cfg-only", | |
+ "Print CFG of machine function to 'dot' file (with no function bodies)", | |
+ false, true) | |
+ | |
+ | |
namespace llvm { | |
/// Returns a newly-created MachineFunction Printer pass. The | |
/// default banner is empty. | |
@@ -64,4 +107,12 @@ MachineFunctionPass *createMachineFuncti | |
return new MachineFunctionPrinterPass(OS, Banner); | |
} | |
+FunctionPass *createMachineCFGPrinterPass (const PassInfo *PI, const char *O) { | |
+ return new MachineCFGPrinter(PI, O); | |
+} | |
+ | |
+FunctionPass *createMachineCFGOnlyPrinterPass () { | |
+ return new MachineCFGOnlyPrinter(); | |
+} | |
+ | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment