Coverage Report

Created: 2019-07-24 05:18

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