X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FCFGPrinter.cpp;h=143220ce38800544b29cbdd92b20dc8dea643355;hb=053372dc3c25c5442b7349c612104e15c41233e8;hp=4d6819d4fa4d67c16cc22a57fab7ab6307e882bd;hpb=a75b3ef9a8b1c88a362eed65f7527d0dc1e54b54;p=oota-llvm.git diff --git a/lib/Analysis/CFGPrinter.cpp b/lib/Analysis/CFGPrinter.cpp index 4d6819d4fa4..143220ce388 100644 --- a/lib/Analysis/CFGPrinter.cpp +++ b/lib/Analysis/CFGPrinter.cpp @@ -1,13 +1,13 @@ //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===// -// +// // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// //===----------------------------------------------------------------------===// // -// This file defines a '-print-cfg' analysis pass, which emits the +// This file defines a '-dot-cfg' analysis pass, which emits the // cfg..dot file for each function in the program, with a graph of the // CFG for that function. // @@ -17,14 +17,19 @@ // //===----------------------------------------------------------------------===// -#include "Support/GraphWriter.h" -#include "llvm/Pass.h" #include "llvm/Function.h" -#include "llvm/iTerminators.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/CFGPrinter.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Config/config.h" +#include #include #include +using namespace llvm; /// CFGOnly flag - This is used to control whether or not the CFG graph printer /// prints out the contents of basic blocks or not. This is acceptable because @@ -32,6 +37,7 @@ /// static bool CFGOnly = false; +namespace llvm { template<> struct DOTGraphTraits : public DefaultDOTGraphTraits { static std::string getGraphName(const Function *F) { @@ -40,14 +46,20 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { static std::string getNodeLabel(const BasicBlock *Node, const Function *Graph) { - if (CFGOnly && !Node->getName().empty()) return Node->getName() + ":"; + if (CFGOnly && !Node->getName().empty()) + return Node->getName() + ":"; std::ostringstream Out; if (CFGOnly) { - WriteAsOperand(Out, Node, false, true); + WriteAsOperand(Out, Node, false); return Out.str(); } + if (Node->getName().empty()) { + WriteAsOperand(Out, Node, false); + Out << ":"; + } + Out << *Node; std::string OutStr = Out.str(); if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); @@ -66,10 +78,6 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { return OutStr; } - static std::string getNodeAttributes(const BasicBlock *N) { - return "fontname=Courier"; - } - static std::string getEdgeSourceLabel(const BasicBlock *Node, succ_const_iterator I) { // Label source of conditional branches with "T" or "F" @@ -79,35 +87,109 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { return ""; } }; +} + +namespace { + struct VISIBILITY_HIDDEN CFGViewer : public FunctionPass { + static char ID; // Pass identifcation, replacement for typeid + CFGViewer() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F) { + F.viewCFG(); + return false; + } + + void print(std::ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGViewer::ID = 0; +static RegisterPass +V0("view-cfg", "View CFG of function", false, true); namespace { - struct CFGPrinter : public FunctionPass { + struct VISIBILITY_HIDDEN CFGOnlyViewer : public FunctionPass { + static char ID; // Pass identifcation, replacement for typeid + CFGOnlyViewer() : FunctionPass(&ID) {} + + virtual bool runOnFunction(Function &F) { + CFGOnly = true; + F.viewCFG(); + CFGOnly = false; + return false; + } + + void print(std::ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGOnlyViewer::ID = 0; +static RegisterPass +V1("view-cfg-only", + "View CFG of function (with no function bodies)", false, true); + +namespace { + struct VISIBILITY_HIDDEN CFGPrinter : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + CFGPrinter() : FunctionPass(&ID) {} + explicit CFGPrinter(void *pid) : FunctionPass(pid) {} + virtual bool runOnFunction(Function &F) { std::string Filename = "cfg." + F.getName() + ".dot"; - std::cerr << "Writing '" << Filename << "'..."; + cerr << "Writing '" << Filename << "'..."; std::ofstream File(Filename.c_str()); - + if (File.good()) WriteGraph(File, (const Function*)&F); else - std::cerr << " error opening file for writing!"; - std::cerr << "\n"; + cerr << " error opening file for writing!"; + cerr << "\n"; return false; } - void print(std::ostream &OS) const {} - + void print(std::ostream &OS, const Module* = 0) const {} + virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); } }; +} - RegisterAnalysis P1("print-cfg", - "Print CFG of function to 'dot' file"); -}; +char CFGPrinter::ID = 0; +static RegisterPass +P1("dot-cfg", "Print CFG of function to 'dot' file", false, true); +namespace { + struct VISIBILITY_HIDDEN CFGOnlyPrinter : public CFGPrinter { + static char ID; // Pass identification, replacement for typeid + CFGOnlyPrinter() : CFGPrinter(&ID) {} + virtual bool runOnFunction(Function &F) { + bool OldCFGOnly = CFGOnly; + CFGOnly = true; + CFGPrinter::runOnFunction(F); + CFGOnly = OldCFGOnly; + return false; + } + void print(std::ostream &OS, const Module* = 0) const {} + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} +char CFGOnlyPrinter::ID = 0; +static RegisterPass +P2("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 @@ -115,27 +197,7 @@ namespace { /// being a 'dot' and 'gv' program in your path. /// void Function::viewCFG() const { - std::string Filename = "/tmp/cfg." + getName() + ".dot"; - std::cerr << "Writing '" << Filename << "'... "; - std::ofstream F(Filename.c_str()); - - if (!F.good()) { - std::cerr << " error opening file for writing!\n"; - return; - } - - WriteGraph(F, this); - F.close(); - std::cerr << "\n"; - - std::cerr << "Running 'dot' program... " << std::flush; - if (system(("dot -Tps " + Filename + " > /tmp/cfg.tempgraph.ps").c_str())) { - std::cerr << "Error running dot: 'dot' not in path?\n"; - } else { - std::cerr << "\n"; - system("gv /tmp/cfg.tempgraph.ps"); - } - system(("rm " + Filename + " /tmp/cfg.tempgraph.ps").c_str()); + ViewGraph(this, "cfg" + getName()); } /// viewCFGOnly - This function is meant for use from the debugger. It works @@ -148,3 +210,12 @@ void Function::viewCFGOnly() const { viewCFG(); CFGOnly = false; } + +FunctionPass *llvm::createCFGPrinterPass () { + return new CFGPrinter(); +} + +FunctionPass *llvm::createCFGOnlyPrinterPass () { + return new CFGOnlyPrinter(); +} +