llvm-6502/lib/Analysis/RegionPrinter.cpp
Owen Anderson 081c34b725 Get rid of static constructors for pass registration. Instead, every pass exposes an initializeMyPassFunction(), which
must be called in the pass's constructor.  This function uses static dependency declarations to recursively initialize
the pass's dependencies.

Clients that only create passes through the createFooPass() APIs will require no changes.  Clients that want to use the
CommandLine options for passes will need to manually call the appropriate initialization functions in PassInitialization.h
before parsing commandline arguments.

I have tested this with all standard configurations of clang and llvm-gcc on Darwin.  It is possible that there are problems
with the static dependencies that will only be visible with non-standard options.  If you encounter any crash in pass
registration/creation, please send the testcase to me directly.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116820 91177308-0d34-0410-b5e6-96231b3b80d8
2010-10-19 17:21:58 +00:00

195 lines
6.0 KiB
C++

//===- RegionPrinter.cpp - Print regions tree pass ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Print out the region tree of a function using dotty/graphviz.
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Analysis/RegionPrinter.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/DOTGraphTraitsPass.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
/// onlySimpleRegion - Show only the simple regions in the RegionViewer.
static cl::opt<bool>
onlySimpleRegions("only-simple-regions",
cl::desc("Show only simple regions in the graphviz viewer"),
cl::Hidden,
cl::init(false));
namespace llvm {
template<>
struct DOTGraphTraits<RegionNode*> : public DefaultDOTGraphTraits {
DOTGraphTraits (bool isSimple=false)
: DefaultDOTGraphTraits(isSimple) {}
std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) {
if (!Node->isSubRegion()) {
BasicBlock *BB = Node->getNodeAs<BasicBlock>();
if (isSimple())
return DOTGraphTraits<const Function*>
::getSimpleNodeLabel(BB, BB->getParent());
else
return DOTGraphTraits<const Function*>
::getCompleteNodeLabel(BB, BB->getParent());
}
return "Not implemented";
}
};
template<>
struct DOTGraphTraits<RegionInfo*> : public DOTGraphTraits<RegionNode*> {
DOTGraphTraits (bool isSimple=false)
: DOTGraphTraits<RegionNode*>(isSimple) {}
static std::string getGraphName(RegionInfo *DT) {
return "Region Graph";
}
std::string getNodeLabel(RegionNode *Node, RegionInfo *G) {
return DOTGraphTraits<RegionNode*>::getNodeLabel(Node,
G->getTopLevelRegion());
}
// Print the cluster of the subregions. This groups the single basic blocks
// and adds a different background color for each group.
static void printRegionCluster(const Region *R, GraphWriter<RegionInfo*> &GW,
unsigned depth = 0) {
raw_ostream &O = GW.getOStream();
O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(R)
<< " {\n";
O.indent(2 * (depth + 1)) << "label = \"\";\n";
if (!onlySimpleRegions || R->isSimple()) {
O.indent(2 * (depth + 1)) << "style = filled;\n";
O.indent(2 * (depth + 1)) << "color = "
<< ((R->getDepth() * 2 % 12) + 1) << "\n";
} else {
O.indent(2 * (depth + 1)) << "style = solid;\n";
O.indent(2 * (depth + 1)) << "color = "
<< ((R->getDepth() * 2 % 12) + 2) << "\n";
}
for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI)
printRegionCluster(*RI, GW, depth + 1);
RegionInfo *RI = R->getRegionInfo();
for (Region::const_block_iterator BI = R->block_begin(),
BE = R->block_end(); BI != BE; ++BI) {
BasicBlock *BB = (*BI)->getNodeAs<BasicBlock>();
if (RI->getRegionFor(BB) == R)
O.indent(2 * (depth + 1)) << "Node"
<< static_cast<const void*>(RI->getTopLevelRegion()->getBBNode(BB))
<< ";\n";
}
O.indent(2 * depth) << "}\n";
}
static void addCustomGraphFeatures(const RegionInfo* RI,
GraphWriter<RegionInfo*> &GW) {
raw_ostream &O = GW.getOStream();
O << "\tcolorscheme = \"paired12\"\n";
printRegionCluster(RI->getTopLevelRegion(), GW, 4);
}
};
} //end namespace llvm
namespace {
struct RegionViewer
: public DOTGraphTraitsViewer<RegionInfo, false> {
static char ID;
RegionViewer() : DOTGraphTraitsViewer<RegionInfo, false>("reg", ID){
initializeRegionViewerPass(*PassRegistry::getPassRegistry());
}
};
char RegionViewer::ID = 0;
struct RegionOnlyViewer
: public DOTGraphTraitsViewer<RegionInfo, true> {
static char ID;
RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfo, true>("regonly", ID) {
initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry());
}
};
char RegionOnlyViewer::ID = 0;
struct RegionPrinter
: public DOTGraphTraitsPrinter<RegionInfo, false> {
static char ID;
RegionPrinter() :
DOTGraphTraitsPrinter<RegionInfo, false>("reg", ID) {
initializeRegionPrinterPass(*PassRegistry::getPassRegistry());
}
};
char RegionPrinter::ID = 0;
} //end anonymous namespace
INITIALIZE_PASS(RegionPrinter, "dot-regions",
"Print regions of function to 'dot' file", true, true)
INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function",
true, true)
INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only",
"View regions of function (with no function bodies)",
true, true)
namespace {
struct RegionOnlyPrinter
: public DOTGraphTraitsPrinter<RegionInfo, true> {
static char ID;
RegionOnlyPrinter() :
DOTGraphTraitsPrinter<RegionInfo, true>("reg", ID) {
initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry());
}
};
}
char RegionOnlyPrinter::ID = 0;
INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only",
"Print regions of function to 'dot' file "
"(with no function bodies)",
true, true)
FunctionPass* llvm::createRegionViewerPass() {
return new RegionViewer();
}
FunctionPass* llvm::createRegionOnlyViewerPass() {
return new RegionOnlyViewer();
}
FunctionPass* llvm::createRegionPrinterPass() {
return new RegionPrinter();
}
FunctionPass* llvm::createRegionOnlyPrinterPass() {
return new RegionOnlyPrinter();
}