1 //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines a '-dot-cfg' analysis pass, which emits the
11 // cfg.<fnname>.dot file for each function in the program, with a graph of the
12 // CFG for that function.
14 // The other main feature of this file is that it implements the
15 // Function::viewCFG method, which is useful for debugging passes which operate
18 //===----------------------------------------------------------------------===//
20 #include "llvm/Analysis/CFGPrinter.h"
21 #include "llvm/Pass.h"
22 #include "llvm/Support/FileSystem.h"
25 static cl::opt<std::string> CFGFuncName(
26 "cfg-func-name", cl::Hidden,
27 cl::desc("The name of a function (or its substring)"
28 " whose CFG is viewed/printed."));
31 struct CFGViewerLegacyPass : public FunctionPass {
32 static char ID; // Pass identifcation, replacement for typeid
33 CFGViewerLegacyPass() : FunctionPass(ID) {
34 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
37 bool runOnFunction(Function &F) override {
42 void print(raw_ostream &OS, const Module* = nullptr) const override {}
44 void getAnalysisUsage(AnalysisUsage &AU) const override {
50 char CFGViewerLegacyPass::ID = 0;
51 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
53 PreservedAnalyses CFGViewerPass::run(Function &F,
54 FunctionAnalysisManager &AM) {
56 return PreservedAnalyses::all();
61 struct CFGOnlyViewerLegacyPass : public FunctionPass {
62 static char ID; // Pass identifcation, replacement for typeid
63 CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
64 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
67 bool runOnFunction(Function &F) override {
72 void print(raw_ostream &OS, const Module* = nullptr) const override {}
74 void getAnalysisUsage(AnalysisUsage &AU) const override {
80 char CFGOnlyViewerLegacyPass::ID = 0;
81 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
82 "View CFG of function (with no function bodies)", false, true)
84 PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
85 FunctionAnalysisManager &AM) {
87 return PreservedAnalyses::all();
90 static void writeCFGToDotFile(Function &F, bool CFGOnly = false) {
91 if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
93 std::string Filename = ("cfg." + F.getName() + ".dot").str();
94 errs() << "Writing '" << Filename << "'...";
97 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
100 WriteGraph(File, (const Function*)&F, CFGOnly);
102 errs() << " error opening file for writing!";
107 struct CFGPrinterLegacyPass : public FunctionPass {
108 static char ID; // Pass identification, replacement for typeid
109 CFGPrinterLegacyPass() : FunctionPass(ID) {
110 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
113 bool runOnFunction(Function &F) override {
114 writeCFGToDotFile(F);
118 void print(raw_ostream &OS, const Module* = nullptr) const override {}
120 void getAnalysisUsage(AnalysisUsage &AU) const override {
121 AU.setPreservesAll();
126 char CFGPrinterLegacyPass::ID = 0;
127 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
130 PreservedAnalyses CFGPrinterPass::run(Function &F,
131 FunctionAnalysisManager &AM) {
132 writeCFGToDotFile(F);
133 return PreservedAnalyses::all();
137 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
138 static char ID; // Pass identification, replacement for typeid
139 CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
140 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
143 bool runOnFunction(Function &F) override {
144 writeCFGToDotFile(F, /*CFGOnly=*/true);
147 void print(raw_ostream &OS, const Module* = nullptr) const override {}
149 void getAnalysisUsage(AnalysisUsage &AU) const override {
150 AU.setPreservesAll();
155 char CFGOnlyPrinterLegacyPass::ID = 0;
156 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
157 "Print CFG of function to 'dot' file (with no function bodies)",
160 PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
161 FunctionAnalysisManager &AM) {
162 writeCFGToDotFile(F, /*CFGOnly=*/true);
163 return PreservedAnalyses::all();
166 /// viewCFG - This function is meant for use from the debugger. You can just
167 /// say 'call F->viewCFG()' and a ghostview window should pop up from the
168 /// program, displaying the CFG of the current function. This depends on there
169 /// being a 'dot' and 'gv' program in your path.
171 void Function::viewCFG() const {
172 if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
174 ViewGraph(this, "cfg" + getName());
177 /// viewCFGOnly - This function is meant for use from the debugger. It works
178 /// just like viewCFG, but it does not include the contents of basic blocks
179 /// into the nodes, just the label. If you are only interested in the CFG
180 /// this can make the graph smaller.
182 void Function::viewCFGOnly() const {
183 if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
185 ViewGraph(this, "cfg" + getName(), true);
188 FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
189 return new CFGPrinterLegacyPass();
192 FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
193 return new CFGOnlyPrinterLegacyPass();