summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Analysis/LazyCallGraph.h12
-rw-r--r--llvm/lib/Analysis/LazyCallGraph.cpp32
-rw-r--r--llvm/lib/Passes/PassRegistry.def1
3 files changed, 45 insertions, 0 deletions
diff --git a/llvm/include/llvm/Analysis/LazyCallGraph.h b/llvm/include/llvm/Analysis/LazyCallGraph.h
index 3e63bf59f6c..34d854c78fe 100644
--- a/llvm/include/llvm/Analysis/LazyCallGraph.h
+++ b/llvm/include/llvm/Analysis/LazyCallGraph.h
@@ -925,6 +925,18 @@ public:
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
+/// A pass which prints the call graph as a DOT file to a \c raw_ostream.
+///
+/// This is primarily useful for visualization purposes.
+class LazyCallGraphDOTPrinterPass
+ : public PassInfoMixin<LazyCallGraphDOTPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit LazyCallGraphDOTPrinterPass(raw_ostream &OS);
+
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+};
}
#endif
diff --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp
index 36425c99adc..a153333e79a 100644
--- a/llvm/lib/Analysis/LazyCallGraph.cpp
+++ b/llvm/lib/Analysis/LazyCallGraph.cpp
@@ -14,6 +14,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -1545,3 +1546,34 @@ PreservedAnalyses LazyCallGraphPrinterPass::run(Module &M,
return PreservedAnalyses::all();
}
+
+LazyCallGraphDOTPrinterPass::LazyCallGraphDOTPrinterPass(raw_ostream &OS)
+ : OS(OS) {}
+
+static void printNodeDOT(raw_ostream &OS, LazyCallGraph::Node &N) {
+ std::string Name = "\"" + DOT::EscapeString(N.getFunction().getName()) + "\"";
+
+ for (const LazyCallGraph::Edge &E : N) {
+ OS << " " << Name << " -> \""
+ << DOT::EscapeString(E.getFunction().getName()) << "\"";
+ if (!E.isCall()) // It is a ref edge.
+ OS << " [style=dashed,label=\"ref\"]";
+ OS << ";\n";
+ }
+
+ OS << "\n";
+}
+
+PreservedAnalyses LazyCallGraphDOTPrinterPass::run(Module &M,
+ ModuleAnalysisManager &AM) {
+ LazyCallGraph &G = AM.getResult<LazyCallGraphAnalysis>(M);
+
+ OS << "digraph \"" << DOT::EscapeString(M.getModuleIdentifier()) << "\" {\n";
+
+ for (Function &F : M)
+ printNodeDOT(OS, G.get(F));
+
+ OS << "}\n";
+
+ return PreservedAnalyses::all();
+}
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index e84f3933db8..18b50ddcc20 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -57,6 +57,7 @@ MODULE_PASS("print-profile-summary", ProfileSummaryPrinterPass(dbgs()))
MODULE_PASS("print-callgraph", CallGraphPrinterPass(dbgs()))
MODULE_PASS("print", PrintModulePass(dbgs()))
MODULE_PASS("print-lcg", LazyCallGraphPrinterPass(dbgs()))
+MODULE_PASS("print-lcg-dot", LazyCallGraphDOTPrinterPass(dbgs()))
MODULE_PASS("rpo-functionattrs", ReversePostOrderFunctionAttrsPass())
MODULE_PASS("sample-profile", SampleProfileLoaderPass())
MODULE_PASS("strip-dead-prototypes", StripDeadPrototypesPass())
OpenPOWER on IntegriCloud