]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Analysis/CFGPrinter.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / Analysis / CFGPrinter.h
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 Instruction *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     return ("label=\"W:" + Twine(Weight->getZExtValue()) + "\"").str();
176   }
177 };
178 } // End llvm namespace
179
180 namespace llvm {
181   class FunctionPass;
182   FunctionPass *createCFGPrinterLegacyPassPass ();
183   FunctionPass *createCFGOnlyPrinterLegacyPassPass ();
184 } // End llvm namespace
185
186 #endif