Home | History | Annotate | Download | only in Analysis
      1 //===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines a 'dot-cfg' analysis pass, which emits the
     11 // cfg.<fnname>.dot file for each function in the program, with a graph of the
     12 // CFG for that function.
     13 //
     14 // This file defines external functions that can be called to explicitly
     15 // instantiate the CFG printer.
     16 //
     17 //===----------------------------------------------------------------------===//
     18 
     19 #ifndef LLVM_ANALYSIS_CFGPRINTER_H
     20 #define LLVM_ANALYSIS_CFGPRINTER_H
     21 
     22 #include "llvm/IR/CFG.h"
     23 #include "llvm/IR/Constants.h"
     24 #include "llvm/IR/Function.h"
     25 #include "llvm/IR/Instructions.h"
     26 #include "llvm/IR/PassManager.h"
     27 #include "llvm/Support/GraphWriter.h"
     28 
     29 namespace llvm {
     30 class CFGViewerPass
     31     : public PassInfoMixin<CFGViewerPass> {
     32 public:
     33   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
     34 };
     35 
     36 class CFGOnlyViewerPass
     37     : public PassInfoMixin<CFGOnlyViewerPass> {
     38 public:
     39   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
     40 };
     41 
     42 class CFGPrinterPass
     43     : public PassInfoMixin<CFGPrinterPass> {
     44 public:
     45   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
     46 };
     47 
     48 class CFGOnlyPrinterPass
     49     : public PassInfoMixin<CFGOnlyPrinterPass> {
     50 public:
     51   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
     52 };
     53 
     54 template<>
     55 struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
     56 
     57   DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
     58 
     59   static std::string getGraphName(const Function *F) {
     60     return "CFG for '" + F->getName().str() + "' function";
     61   }
     62 
     63   static std::string getSimpleNodeLabel(const BasicBlock *Node,
     64                                         const Function *) {
     65     if (!Node->getName().empty())
     66       return Node->getName().str();
     67 
     68     std::string Str;
     69     raw_string_ostream OS(Str);
     70 
     71     Node->printAsOperand(OS, false);
     72     return OS.str();
     73   }
     74 
     75   static std::string getCompleteNodeLabel(const BasicBlock *Node,
     76                                           const Function *) {
     77     enum { MaxColumns = 80 };
     78     std::string Str;
     79     raw_string_ostream OS(Str);
     80 
     81     if (Node->getName().empty()) {
     82       Node->printAsOperand(OS, false);
     83       OS << ":";
     84     }
     85 
     86     OS << *Node;
     87     std::string OutStr = OS.str();
     88     if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
     89 
     90     // Process string output to make it nicer...
     91     unsigned ColNum = 0;
     92     unsigned LastSpace = 0;
     93     for (unsigned i = 0; i != OutStr.length(); ++i) {
     94       if (OutStr[i] == '\n') {                            // Left justify
     95         OutStr[i] = '\\';
     96         OutStr.insert(OutStr.begin()+i+1, 'l');
     97         ColNum = 0;
     98         LastSpace = 0;
     99       } else if (OutStr[i] == ';') {                      // Delete comments!
    100         unsigned Idx = OutStr.find('\n', i+1);            // Find end of line
    101         OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
    102         --i;
    103       } else if (ColNum == MaxColumns) {                  // Wrap lines.
    104         // Wrap very long names even though we can't find a space.
    105         if (!LastSpace)
    106           LastSpace = i;
    107         OutStr.insert(LastSpace, "\\l...");
    108         ColNum = i - LastSpace;
    109         LastSpace = 0;
    110         i += 3; // The loop will advance 'i' again.
    111       }
    112       else
    113         ++ColNum;
    114       if (OutStr[i] == ' ')
    115         LastSpace = i;
    116     }
    117     return OutStr;
    118   }
    119 
    120   std::string getNodeLabel(const BasicBlock *Node,
    121                            const Function *Graph) {
    122     if (isSimple())
    123       return getSimpleNodeLabel(Node, Graph);
    124     else
    125       return getCompleteNodeLabel(Node, Graph);
    126   }
    127 
    128   static std::string getEdgeSourceLabel(const BasicBlock *Node,
    129                                         succ_const_iterator I) {
    130     // Label source of conditional branches with "T" or "F"
    131     if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
    132       if (BI->isConditional())
    133         return (I == succ_begin(Node)) ? "T" : "F";
    134 
    135     // Label source of switch edges with the associated value.
    136     if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) {
    137       unsigned SuccNo = I.getSuccessorIndex();
    138 
    139       if (SuccNo == 0) return "def";
    140 
    141       std::string Str;
    142       raw_string_ostream OS(Str);
    143       auto Case = *SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
    144       OS << Case.getCaseValue()->getValue();
    145       return OS.str();
    146     }
    147     return "";
    148   }
    149 
    150   /// Display the raw branch weights from PGO.
    151   std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I,
    152                                 const Function *F) {
    153     const TerminatorInst *TI = Node->getTerminator();
    154     if (TI->getNumSuccessors() == 1)
    155       return "";
    156 
    157     MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof);
    158     if (!WeightsNode)
    159       return "";
    160 
    161     MDString *MDName = cast<MDString>(WeightsNode->getOperand(0));
    162     if (MDName->getString() != "branch_weights")
    163       return "";
    164 
    165     unsigned OpNo = I.getSuccessorIndex() + 1;
    166     if (OpNo >= WeightsNode->getNumOperands())
    167       return "";
    168     ConstantInt *Weight =
    169         mdconst::dyn_extract<ConstantInt>(WeightsNode->getOperand(OpNo));
    170     if (!Weight)
    171       return "";
    172 
    173     // Prepend a 'W' to indicate that this is a weight rather than the actual
    174     // profile count (due to scaling).
    175     Twine Attrs = "label=\"W:" + Twine(Weight->getZExtValue()) + "\"";
    176     return Attrs.str();
    177   }
    178 };
    179 } // End llvm namespace
    180 
    181 namespace llvm {
    182   class FunctionPass;
    183   FunctionPass *createCFGPrinterLegacyPassPass ();
    184   FunctionPass *createCFGOnlyPrinterLegacyPassPass ();
    185 } // End llvm namespace
    186 
    187 #endif
    188