312 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			312 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- DomPrinter.cpp - DOT printer for the dominance trees    ------------===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file defines '-dot-dom' and '-dot-postdom' analysis passes, which emit
 | 
						|
// a dom.<fnname>.dot or postdom.<fnname>.dot file for each function in the
 | 
						|
// program, with a graph of the dominance/postdominance tree of that
 | 
						|
// function.
 | 
						|
//
 | 
						|
// There are also passes available to directly call dotty ('-view-dom' or
 | 
						|
// '-view-postdom'). By appending '-only' like '-dot-dom-only' only the
 | 
						|
// names of the bbs are printed, but the content is hidden.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/Analysis/DomPrinter.h"
 | 
						|
#include "llvm/Analysis/DOTGraphTraitsPass.h"
 | 
						|
#include "llvm/Analysis/PostDominators.h"
 | 
						|
#include "llvm/InitializePasses.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
template<>
 | 
						|
struct DOTGraphTraits<DomTreeNode*> : public DefaultDOTGraphTraits {
 | 
						|
 | 
						|
  DOTGraphTraits (bool isSimple=false)
 | 
						|
    : DefaultDOTGraphTraits(isSimple) {}
 | 
						|
 | 
						|
  std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph) {
 | 
						|
 | 
						|
    BasicBlock *BB = Node->getBlock();
 | 
						|
 | 
						|
    if (!BB)
 | 
						|
      return "Post dominance root node";
 | 
						|
 | 
						|
 | 
						|
    if (isSimple())
 | 
						|
      return DOTGraphTraits<DOTFuncInfo *>
 | 
						|
        ::getSimpleNodeLabel(BB, nullptr);
 | 
						|
    else
 | 
						|
      return DOTGraphTraits<DOTFuncInfo *>
 | 
						|
        ::getCompleteNodeLabel(BB, nullptr);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct DOTGraphTraits<DominatorTree*> : public DOTGraphTraits<DomTreeNode*> {
 | 
						|
 | 
						|
  DOTGraphTraits (bool isSimple=false)
 | 
						|
    : DOTGraphTraits<DomTreeNode*>(isSimple) {}
 | 
						|
 | 
						|
  static std::string getGraphName(DominatorTree *DT) {
 | 
						|
    return "Dominator tree";
 | 
						|
  }
 | 
						|
 | 
						|
  std::string getNodeLabel(DomTreeNode *Node, DominatorTree *G) {
 | 
						|
    return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode());
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct DOTGraphTraits<PostDominatorTree*>
 | 
						|
  : public DOTGraphTraits<DomTreeNode*> {
 | 
						|
 | 
						|
  DOTGraphTraits (bool isSimple=false)
 | 
						|
    : DOTGraphTraits<DomTreeNode*>(isSimple) {}
 | 
						|
 | 
						|
  static std::string getGraphName(PostDominatorTree *DT) {
 | 
						|
    return "Post dominator tree";
 | 
						|
  }
 | 
						|
 | 
						|
  std::string getNodeLabel(DomTreeNode *Node, PostDominatorTree *G ) {
 | 
						|
    return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode());
 | 
						|
  }
 | 
						|
};
 | 
						|
}
 | 
						|
 | 
						|
PreservedAnalyses DomTreePrinterPass::run(Function &F,
 | 
						|
                                          FunctionAnalysisManager &AM) {
 | 
						|
  WriteDOTGraphToFile(F, &AM.getResult<DominatorTreeAnalysis>(F), "dom", false);
 | 
						|
  return PreservedAnalyses::all();
 | 
						|
}
 | 
						|
 | 
						|
PreservedAnalyses DomTreeOnlyPrinterPass::run(Function &F,
 | 
						|
                                              FunctionAnalysisManager &AM) {
 | 
						|
  WriteDOTGraphToFile(F, &AM.getResult<DominatorTreeAnalysis>(F), "domonly",
 | 
						|
                      true);
 | 
						|
  return PreservedAnalyses::all();
 | 
						|
}
 | 
						|
 | 
						|
void DominatorTree::viewGraph(const Twine &Name, const Twine &Title) {
 | 
						|
#ifndef NDEBUG
 | 
						|
  ViewGraph(this, Name, false, Title);
 | 
						|
#else
 | 
						|
  errs() << "DomTree dump not available, build with DEBUG\n";
 | 
						|
#endif  // NDEBUG
 | 
						|
}
 | 
						|
 | 
						|
void DominatorTree::viewGraph() {
 | 
						|
#ifndef NDEBUG
 | 
						|
  this->viewGraph("domtree", "Dominator Tree for function");
 | 
						|
#else
 | 
						|
  errs() << "DomTree dump not available, build with DEBUG\n";
 | 
						|
#endif  // NDEBUG
 | 
						|
}
 | 
						|
 | 
						|
namespace {
 | 
						|
struct DominatorTreeWrapperPassAnalysisGraphTraits {
 | 
						|
  static DominatorTree *getGraph(DominatorTreeWrapperPass *DTWP) {
 | 
						|
    return &DTWP->getDomTree();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
struct DomViewer : public DOTGraphTraitsViewer<
 | 
						|
                       DominatorTreeWrapperPass, false, DominatorTree *,
 | 
						|
                       DominatorTreeWrapperPassAnalysisGraphTraits> {
 | 
						|
  static char ID;
 | 
						|
  DomViewer()
 | 
						|
      : DOTGraphTraitsViewer<DominatorTreeWrapperPass, false, DominatorTree *,
 | 
						|
                             DominatorTreeWrapperPassAnalysisGraphTraits>(
 | 
						|
            "dom", ID) {
 | 
						|
    initializeDomViewerPass(*PassRegistry::getPassRegistry());
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
struct DomOnlyViewer : public DOTGraphTraitsViewer<
 | 
						|
                           DominatorTreeWrapperPass, true, DominatorTree *,
 | 
						|
                           DominatorTreeWrapperPassAnalysisGraphTraits> {
 | 
						|
  static char ID;
 | 
						|
  DomOnlyViewer()
 | 
						|
      : DOTGraphTraitsViewer<DominatorTreeWrapperPass, true, DominatorTree *,
 | 
						|
                             DominatorTreeWrapperPassAnalysisGraphTraits>(
 | 
						|
            "domonly", ID) {
 | 
						|
    initializeDomOnlyViewerPass(*PassRegistry::getPassRegistry());
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
struct PostDominatorTreeWrapperPassAnalysisGraphTraits {
 | 
						|
  static PostDominatorTree *getGraph(PostDominatorTreeWrapperPass *PDTWP) {
 | 
						|
    return &PDTWP->getPostDomTree();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
struct PostDomViewer : public DOTGraphTraitsViewer<
 | 
						|
                          PostDominatorTreeWrapperPass, false,
 | 
						|
                          PostDominatorTree *,
 | 
						|
                          PostDominatorTreeWrapperPassAnalysisGraphTraits> {
 | 
						|
  static char ID;
 | 
						|
  PostDomViewer() :
 | 
						|
    DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, false,
 | 
						|
                         PostDominatorTree *,
 | 
						|
                         PostDominatorTreeWrapperPassAnalysisGraphTraits>(
 | 
						|
        "postdom", ID){
 | 
						|
      initializePostDomViewerPass(*PassRegistry::getPassRegistry());
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
struct PostDomOnlyViewer : public DOTGraphTraitsViewer<
 | 
						|
                            PostDominatorTreeWrapperPass, true,
 | 
						|
                            PostDominatorTree *,
 | 
						|
                            PostDominatorTreeWrapperPassAnalysisGraphTraits> {
 | 
						|
  static char ID;
 | 
						|
  PostDomOnlyViewer() :
 | 
						|
    DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, true,
 | 
						|
                         PostDominatorTree *,
 | 
						|
                         PostDominatorTreeWrapperPassAnalysisGraphTraits>(
 | 
						|
        "postdomonly", ID){
 | 
						|
      initializePostDomOnlyViewerPass(*PassRegistry::getPassRegistry());
 | 
						|
    }
 | 
						|
};
 | 
						|
} // end anonymous namespace
 | 
						|
 | 
						|
char DomViewer::ID = 0;
 | 
						|
INITIALIZE_PASS(DomViewer, "view-dom",
 | 
						|
                "View dominance tree of function", false, false)
 | 
						|
 | 
						|
char DomOnlyViewer::ID = 0;
 | 
						|
INITIALIZE_PASS(DomOnlyViewer, "view-dom-only",
 | 
						|
                "View dominance tree of function (with no function bodies)",
 | 
						|
                false, false)
 | 
						|
 | 
						|
char PostDomViewer::ID = 0;
 | 
						|
INITIALIZE_PASS(PostDomViewer, "view-postdom",
 | 
						|
                "View postdominance tree of function", false, false)
 | 
						|
 | 
						|
char PostDomOnlyViewer::ID = 0;
 | 
						|
INITIALIZE_PASS(PostDomOnlyViewer, "view-postdom-only",
 | 
						|
                "View postdominance tree of function "
 | 
						|
                "(with no function bodies)",
 | 
						|
                false, false)
 | 
						|
 | 
						|
namespace {
 | 
						|
struct DomPrinter : public DOTGraphTraitsPrinter<
 | 
						|
                        DominatorTreeWrapperPass, false, DominatorTree *,
 | 
						|
                        DominatorTreeWrapperPassAnalysisGraphTraits> {
 | 
						|
  static char ID;
 | 
						|
  DomPrinter()
 | 
						|
      : DOTGraphTraitsPrinter<DominatorTreeWrapperPass, false, DominatorTree *,
 | 
						|
                              DominatorTreeWrapperPassAnalysisGraphTraits>(
 | 
						|
            "dom", ID) {
 | 
						|
    initializeDomPrinterPass(*PassRegistry::getPassRegistry());
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
struct DomOnlyPrinter : public DOTGraphTraitsPrinter<
 | 
						|
                            DominatorTreeWrapperPass, true, DominatorTree *,
 | 
						|
                            DominatorTreeWrapperPassAnalysisGraphTraits> {
 | 
						|
  static char ID;
 | 
						|
  DomOnlyPrinter()
 | 
						|
      : DOTGraphTraitsPrinter<DominatorTreeWrapperPass, true, DominatorTree *,
 | 
						|
                              DominatorTreeWrapperPassAnalysisGraphTraits>(
 | 
						|
            "domonly", ID) {
 | 
						|
    initializeDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
struct PostDomPrinter
 | 
						|
  : public DOTGraphTraitsPrinter<
 | 
						|
                            PostDominatorTreeWrapperPass, false,
 | 
						|
                            PostDominatorTree *,
 | 
						|
                            PostDominatorTreeWrapperPassAnalysisGraphTraits> {
 | 
						|
  static char ID;
 | 
						|
  PostDomPrinter() :
 | 
						|
    DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, false,
 | 
						|
                          PostDominatorTree *,
 | 
						|
                          PostDominatorTreeWrapperPassAnalysisGraphTraits>(
 | 
						|
        "postdom", ID) {
 | 
						|
      initializePostDomPrinterPass(*PassRegistry::getPassRegistry());
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
struct PostDomOnlyPrinter
 | 
						|
  : public DOTGraphTraitsPrinter<
 | 
						|
                            PostDominatorTreeWrapperPass, true,
 | 
						|
                            PostDominatorTree *,
 | 
						|
                            PostDominatorTreeWrapperPassAnalysisGraphTraits> {
 | 
						|
  static char ID;
 | 
						|
  PostDomOnlyPrinter() :
 | 
						|
    DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, true,
 | 
						|
                          PostDominatorTree *,
 | 
						|
                          PostDominatorTreeWrapperPassAnalysisGraphTraits>(
 | 
						|
        "postdomonly", ID) {
 | 
						|
      initializePostDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
 | 
						|
    }
 | 
						|
};
 | 
						|
} // end anonymous namespace
 | 
						|
 | 
						|
 | 
						|
 | 
						|
char DomPrinter::ID = 0;
 | 
						|
INITIALIZE_PASS(DomPrinter, "dot-dom",
 | 
						|
                "Print dominance tree of function to 'dot' file",
 | 
						|
                false, false)
 | 
						|
 | 
						|
char DomOnlyPrinter::ID = 0;
 | 
						|
INITIALIZE_PASS(DomOnlyPrinter, "dot-dom-only",
 | 
						|
                "Print dominance tree of function to 'dot' file "
 | 
						|
                "(with no function bodies)",
 | 
						|
                false, false)
 | 
						|
 | 
						|
char PostDomPrinter::ID = 0;
 | 
						|
INITIALIZE_PASS(PostDomPrinter, "dot-postdom",
 | 
						|
                "Print postdominance tree of function to 'dot' file",
 | 
						|
                false, false)
 | 
						|
 | 
						|
char PostDomOnlyPrinter::ID = 0;
 | 
						|
INITIALIZE_PASS(PostDomOnlyPrinter, "dot-postdom-only",
 | 
						|
                "Print postdominance tree of function to 'dot' file "
 | 
						|
                "(with no function bodies)",
 | 
						|
                false, false)
 | 
						|
 | 
						|
// Create methods available outside of this file, to use them
 | 
						|
// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
 | 
						|
// the link time optimization.
 | 
						|
 | 
						|
FunctionPass *llvm::createDomPrinterPass() {
 | 
						|
  return new DomPrinter();
 | 
						|
}
 | 
						|
 | 
						|
FunctionPass *llvm::createDomOnlyPrinterPass() {
 | 
						|
  return new DomOnlyPrinter();
 | 
						|
}
 | 
						|
 | 
						|
FunctionPass *llvm::createDomViewerPass() {
 | 
						|
  return new DomViewer();
 | 
						|
}
 | 
						|
 | 
						|
FunctionPass *llvm::createDomOnlyViewerPass() {
 | 
						|
  return new DomOnlyViewer();
 | 
						|
}
 | 
						|
 | 
						|
FunctionPass *llvm::createPostDomPrinterPass() {
 | 
						|
  return new PostDomPrinter();
 | 
						|
}
 | 
						|
 | 
						|
FunctionPass *llvm::createPostDomOnlyPrinterPass() {
 | 
						|
  return new PostDomOnlyPrinter();
 | 
						|
}
 | 
						|
 | 
						|
FunctionPass *llvm::createPostDomViewerPass() {
 | 
						|
  return new PostDomViewer();
 | 
						|
}
 | 
						|
 | 
						|
FunctionPass *llvm::createPostDomOnlyViewerPass() {
 | 
						|
  return new PostDomOnlyViewer();
 | 
						|
}
 |