#ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
#define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
#include "llvm/Analysis/CFGPrinter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GraphWriter.h"
namespace llvm {
template <typename Result, typename GraphT = Result *>
struct DefaultAnalysisGraphTraits {
static GraphT getGraph(Result R) { return &R; }
};
template <typename GraphT>
void viewGraphForFunction(Function &F, GraphT Graph, StringRef Name,
bool IsSimple) {
std::string GraphName = DOTGraphTraits<GraphT *>::getGraphName(&Graph);
ViewGraph(Graph, Name, IsSimple,
GraphName + " for '" + F.getName() + "' function");
}
template <typename AnalysisT, bool IsSimple,
typename GraphT = typename AnalysisT::Result *,
typename AnalysisGraphTraitsT =
DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>>
struct DOTGraphTraitsViewer
: PassInfoMixin<DOTGraphTraitsViewer<AnalysisT, IsSimple, GraphT,
AnalysisGraphTraitsT>> {
DOTGraphTraitsViewer(StringRef GraphName) : Name(GraphName) {}
virtual bool processFunction(Function &F,
const typename AnalysisT::Result &Result) {
return true;
}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
auto &Result = FAM.getResult<AnalysisT>(F);
if (!processFunction(F, Result))
return PreservedAnalyses::all();
GraphT Graph = AnalysisGraphTraitsT::getGraph(Result);
viewGraphForFunction(F, Graph, Name, IsSimple);
return PreservedAnalyses::all();
};
protected:
~DOTGraphTraitsViewer() {}
private:
StringRef Name;
};
template <typename GraphT>
void printGraphForFunction(Function &F, GraphT Graph, StringRef Name,
bool IsSimple) {
std::string Filename = Name.str() + "." + F.getName().str() + ".dot";
std::error_code EC;
errs() << "Writing '" << Filename << "'...";
raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
if (!EC)
WriteGraph(File, Graph, IsSimple,
GraphName + " for '" + F.getName() + "' function");
else
errs() << " error opening file for writing!";
errs() << "\n";
}
template <typename AnalysisT, bool IsSimple,
typename GraphT = typename AnalysisT::Result *,
typename AnalysisGraphTraitsT =
DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>>
struct DOTGraphTraitsPrinter
: PassInfoMixin<DOTGraphTraitsPrinter<AnalysisT, IsSimple, GraphT,
AnalysisGraphTraitsT>> {
DOTGraphTraitsPrinter(StringRef GraphName) : Name(GraphName) {}
virtual bool processFunction(Function &F,
const typename AnalysisT::Result &Result) {
return true;
}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
auto &Result = FAM.getResult<AnalysisT>(F);
if (!processFunction(F, Result))
return PreservedAnalyses::all();
GraphT Graph = AnalysisGraphTraitsT::getGraph(Result);
printGraphForFunction(F, Graph, Name, IsSimple);
return PreservedAnalyses::all();
};
protected:
~DOTGraphTraitsPrinter() {}
private:
StringRef Name;
};
template <typename AnalysisT, typename GraphT = AnalysisT *>
struct LegacyDefaultAnalysisGraphTraits {
static GraphT getGraph(AnalysisT *A) { return A; }
};
template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
typename AnalysisGraphTraitsT =
LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
class DOTGraphTraitsViewerWrapperPass : public FunctionPass {
public:
DOTGraphTraitsViewerWrapperPass(StringRef GraphName, char &ID)
: FunctionPass(ID), Name(GraphName) {}
virtual bool processFunction(Function &F, AnalysisT &Analysis) {
return true;
}
bool runOnFunction(Function &F) override {
auto &Analysis = getAnalysis<AnalysisT>();
if (!processFunction(F, Analysis))
return false;
GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
viewGraphForFunction(F, Graph, Name, IsSimple);
return false;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<AnalysisT>();
}
private:
std::string Name;
};
template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
typename AnalysisGraphTraitsT =
LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
class DOTGraphTraitsPrinterWrapperPass : public FunctionPass {
public:
DOTGraphTraitsPrinterWrapperPass(StringRef GraphName, char &ID)
: FunctionPass(ID), Name(GraphName) {}
virtual bool processFunction(Function &F, AnalysisT &Analysis) {
return true;
}
bool runOnFunction(Function &F) override {
auto &Analysis = getAnalysis<AnalysisT>();
if (!processFunction(F, Analysis))
return false;
GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
printGraphForFunction(F, Graph, Name, IsSimple);
return false;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<AnalysisT>();
}
private:
std::string Name;
};
template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
typename AnalysisGraphTraitsT =
LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
class DOTGraphTraitsModuleViewerWrapperPass : public ModulePass {
public:
DOTGraphTraitsModuleViewerWrapperPass(StringRef GraphName, char &ID)
: ModulePass(ID), Name(GraphName) {}
bool runOnModule(Module &M) override {
GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
ViewGraph(Graph, Name, IsSimple, Title);
return false;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<AnalysisT>();
}
private:
std::string Name;
};
template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
typename AnalysisGraphTraitsT =
LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
class DOTGraphTraitsModulePrinterWrapperPass : public ModulePass {
public:
DOTGraphTraitsModulePrinterWrapperPass(StringRef GraphName, char &ID)
: ModulePass(ID), Name(GraphName) {}
bool runOnModule(Module &M) override {
GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
std::string Filename = Name + ".dot";
std::error_code EC;
errs() << "Writing '" << Filename << "'...";
raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
if (!EC)
WriteGraph(File, Graph, IsSimple, Title);
else
errs() << " error opening file for writing!";
errs() << "\n";
return false;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<AnalysisT>();
}
private:
std::string Name;
};
template <typename GraphT>
void WriteDOTGraphToFile(Function &F, GraphT &&Graph,
std::string FileNamePrefix, bool IsSimple) {
std::string Filename = FileNamePrefix + "." + F.getName().str() + ".dot";
std::error_code EC;
errs() << "Writing '" << Filename << "'...";
raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
std::string Title = GraphName + " for '" + F.getName().str() + "' function";
if (!EC)
WriteGraph(File, Graph, IsSimple, Title);
else
errs() << " error opening file for writing!";
errs() << "\n";
}
}
#endif