]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Analysis/CFGPrinter.h
MFV r320905: Import upstream fix for CVE-2017-11103.
[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       SwitchInst::ConstCaseIt Case =
144           SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
145       OS << Case.getCaseValue()->getValue();
146       return OS.str();
147     }
148     return "";
149   }
150
151   /// Display the raw branch weights from PGO.
152   std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I,
153                                 const Function *F) {
154     const TerminatorInst *TI = Node->getTerminator();
155     if (TI->getNumSuccessors() == 1)
156       return "";
157
158     MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof);
159     if (!WeightsNode)
160       return "";
161
162     MDString *MDName = cast<MDString>(WeightsNode->getOperand(0));
163     if (MDName->getString() != "branch_weights")
164       return "";
165
166     unsigned OpNo = I.getSuccessorIndex() + 1;
167     if (OpNo >= WeightsNode->getNumOperands())
168       return "";
169     ConstantInt *Weight =
170         mdconst::dyn_extract<ConstantInt>(WeightsNode->getOperand(OpNo));
171     if (!Weight)
172       return "";
173
174     // Prepend a 'W' to indicate that this is a weight rather than the actual
175     // profile count (due to scaling).
176     Twine Attrs = "label=\"W:" + Twine(Weight->getZExtValue()) + "\"";
177     return Attrs.str();
178   }
179 };
180 } // End llvm namespace
181
182 namespace llvm {
183   class FunctionPass;
184   FunctionPass *createCFGPrinterLegacyPassPass ();
185   FunctionPass *createCFGOnlyPrinterLegacyPassPass ();
186 } // End llvm namespace
187
188 #endif