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"
26 struct CFGViewerLegacyPass : public FunctionPass {
27 static char ID; // Pass identifcation, replacement for typeid
28 CFGViewerLegacyPass() : FunctionPass(ID) {
29 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
32 bool runOnFunction(Function &F) override {
37 void print(raw_ostream &OS, const Module* = nullptr) const override {}
39 void getAnalysisUsage(AnalysisUsage &AU) const override {
45 char CFGViewerLegacyPass::ID = 0;
46 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
48 PreservedAnalyses CFGViewerPass::run(Function &F,
49 FunctionAnalysisManager &AM) {
51 return PreservedAnalyses::all();
56 struct CFGOnlyViewerLegacyPass : public FunctionPass {
57 static char ID; // Pass identifcation, replacement for typeid
58 CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
59 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
62 bool runOnFunction(Function &F) override {
67 void print(raw_ostream &OS, const Module* = nullptr) const override {}
69 void getAnalysisUsage(AnalysisUsage &AU) const override {
75 char CFGOnlyViewerLegacyPass::ID = 0;
76 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
77 "View CFG of function (with no function bodies)", false, true)
79 PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
80 FunctionAnalysisManager &AM) {
82 return PreservedAnalyses::all();
85 static void writeCFGToDotFile(Function &F, bool CFGOnly = false) {
86 std::string Filename = ("cfg." + F.getName() + ".dot").str();
87 errs() << "Writing '" << Filename << "'...";
90 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
93 WriteGraph(File, (const Function*)&F, CFGOnly);
95 errs() << " error opening file for writing!";
100 struct CFGPrinterLegacyPass : public FunctionPass {
101 static char ID; // Pass identification, replacement for typeid
102 CFGPrinterLegacyPass() : FunctionPass(ID) {
103 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
106 bool runOnFunction(Function &F) override {
107 writeCFGToDotFile(F);
111 void print(raw_ostream &OS, const Module* = nullptr) const override {}
113 void getAnalysisUsage(AnalysisUsage &AU) const override {
114 AU.setPreservesAll();
119 char CFGPrinterLegacyPass::ID = 0;
120 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
123 PreservedAnalyses CFGPrinterPass::run(Function &F,
124 FunctionAnalysisManager &AM) {
125 writeCFGToDotFile(F);
126 return PreservedAnalyses::all();
130 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
131 static char ID; // Pass identification, replacement for typeid
132 CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
133 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
136 bool runOnFunction(Function &F) override {
137 writeCFGToDotFile(F, /*CFGOnly=*/true);
140 void print(raw_ostream &OS, const Module* = nullptr) const override {}
142 void getAnalysisUsage(AnalysisUsage &AU) const override {
143 AU.setPreservesAll();
148 char CFGOnlyPrinterLegacyPass::ID = 0;
149 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
150 "Print CFG of function to 'dot' file (with no function bodies)",
153 PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
154 FunctionAnalysisManager &AM) {
155 writeCFGToDotFile(F, /*CFGOnly=*/true);
156 return PreservedAnalyses::all();
159 /// viewCFG - This function is meant for use from the debugger. You can just
160 /// say 'call F->viewCFG()' and a ghostview window should pop up from the
161 /// program, displaying the CFG of the current function. This depends on there
162 /// being a 'dot' and 'gv' program in your path.
164 void Function::viewCFG() const {
165 ViewGraph(this, "cfg" + getName());
168 /// viewCFGOnly - This function is meant for use from the debugger. It works
169 /// just like viewCFG, but it does not include the contents of basic blocks
170 /// into the nodes, just the label. If you are only interested in the CFG
171 /// this can make the graph smaller.
173 void Function::viewCFGOnly() const {
174 ViewGraph(this, "cfg" + getName(), true);
177 FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
178 return new CFGPrinterLegacyPass();
181 FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
182 return new CFGOnlyPrinterLegacyPass();