1 //===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines a 'dot-cfg' analysis pass, which emits the
10 // cfg.<fnname>.dot file for each function in the program, with a graph of the
11 // CFG for that function.
13 // This file defines external functions that can be called to explicitly
14 // instantiate the CFG printer.
16 //===----------------------------------------------------------------------===//
18 #ifndef LLVM_ANALYSIS_CFGPRINTER_H
19 #define LLVM_ANALYSIS_CFGPRINTER_H
21 #include "llvm/IR/CFG.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/Instructions.h"
25 #include "llvm/IR/PassManager.h"
26 #include "llvm/Support/GraphWriter.h"
30 : public PassInfoMixin
<CFGViewerPass
> {
32 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
);
35 class CFGOnlyViewerPass
36 : public PassInfoMixin
<CFGOnlyViewerPass
> {
38 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
);
42 : public PassInfoMixin
<CFGPrinterPass
> {
44 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
);
47 class CFGOnlyPrinterPass
48 : public PassInfoMixin
<CFGOnlyPrinterPass
> {
50 PreservedAnalyses
run(Function
&F
, FunctionAnalysisManager
&AM
);
54 struct DOTGraphTraits
<const Function
*> : public DefaultDOTGraphTraits
{
56 DOTGraphTraits (bool isSimple
=false) : DefaultDOTGraphTraits(isSimple
) {}
58 static std::string
getGraphName(const Function
*F
) {
59 return "CFG for '" + F
->getName().str() + "' function";
62 static std::string
getSimpleNodeLabel(const BasicBlock
*Node
,
64 if (!Node
->getName().empty())
65 return Node
->getName().str();
68 raw_string_ostream
OS(Str
);
70 Node
->printAsOperand(OS
, false);
74 static std::string
getCompleteNodeLabel(const BasicBlock
*Node
,
76 enum { MaxColumns
= 80 };
78 raw_string_ostream
OS(Str
);
80 if (Node
->getName().empty()) {
81 Node
->printAsOperand(OS
, false);
86 std::string OutStr
= OS
.str();
87 if (OutStr
[0] == '\n') OutStr
.erase(OutStr
.begin());
89 // Process string output to make it nicer...
91 unsigned LastSpace
= 0;
92 for (unsigned i
= 0; i
!= OutStr
.length(); ++i
) {
93 if (OutStr
[i
] == '\n') { // Left justify
95 OutStr
.insert(OutStr
.begin()+i
+1, 'l');
98 } else if (OutStr
[i
] == ';') { // Delete comments!
99 unsigned Idx
= OutStr
.find('\n', i
+1); // Find end of line
100 OutStr
.erase(OutStr
.begin()+i
, OutStr
.begin()+Idx
);
102 } else if (ColNum
== MaxColumns
) { // Wrap lines.
103 // Wrap very long names even though we can't find a space.
106 OutStr
.insert(LastSpace
, "\\l...");
107 ColNum
= i
- LastSpace
;
109 i
+= 3; // The loop will advance 'i' again.
113 if (OutStr
[i
] == ' ')
119 std::string
getNodeLabel(const BasicBlock
*Node
,
120 const Function
*Graph
) {
122 return getSimpleNodeLabel(Node
, Graph
);
124 return getCompleteNodeLabel(Node
, Graph
);
127 static std::string
getEdgeSourceLabel(const BasicBlock
*Node
,
128 succ_const_iterator I
) {
129 // Label source of conditional branches with "T" or "F"
130 if (const BranchInst
*BI
= dyn_cast
<BranchInst
>(Node
->getTerminator()))
131 if (BI
->isConditional())
132 return (I
== succ_begin(Node
)) ? "T" : "F";
134 // Label source of switch edges with the associated value.
135 if (const SwitchInst
*SI
= dyn_cast
<SwitchInst
>(Node
->getTerminator())) {
136 unsigned SuccNo
= I
.getSuccessorIndex();
138 if (SuccNo
== 0) return "def";
141 raw_string_ostream
OS(Str
);
142 auto Case
= *SwitchInst::ConstCaseIt::fromSuccessorIndex(SI
, SuccNo
);
143 OS
<< Case
.getCaseValue()->getValue();
149 /// Display the raw branch weights from PGO.
150 std::string
getEdgeAttributes(const BasicBlock
*Node
, succ_const_iterator I
,
152 const Instruction
*TI
= Node
->getTerminator();
153 if (TI
->getNumSuccessors() == 1)
156 MDNode
*WeightsNode
= TI
->getMetadata(LLVMContext::MD_prof
);
160 MDString
*MDName
= cast
<MDString
>(WeightsNode
->getOperand(0));
161 if (MDName
->getString() != "branch_weights")
164 unsigned OpNo
= I
.getSuccessorIndex() + 1;
165 if (OpNo
>= WeightsNode
->getNumOperands())
167 ConstantInt
*Weight
=
168 mdconst::dyn_extract
<ConstantInt
>(WeightsNode
->getOperand(OpNo
));
172 // Prepend a 'W' to indicate that this is a weight rather than the actual
173 // profile count (due to scaling).
174 return ("label=\"W:" + Twine(Weight
->getZExtValue()) + "\"").str();
177 } // End llvm namespace
181 FunctionPass
*createCFGPrinterLegacyPassPass ();
182 FunctionPass
*createCFGOnlyPrinterLegacyPassPass ();
183 } // End llvm namespace