Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- Debugify.h - Check debug info preservation in optimizations --------===//
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
/// \file Interface to the `debugify` synthetic/original debug info testing
10
/// utility.
11
///
12
//===----------------------------------------------------------------------===//
13
 
14
#ifndef LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
15
#define LLVM_TRANSFORMS_UTILS_DEBUGIFY_H
16
 
17
#include "llvm/ADT/MapVector.h"
18
#include "llvm/ADT/StringRef.h"
19
#include "llvm/Bitcode/BitcodeWriterPass.h"
20
#include "llvm/IR/IRPrintingPasses.h"
21
#include "llvm/IR/LegacyPassManager.h"
22
#include "llvm/IR/PassManager.h"
23
#include "llvm/IR/ValueHandle.h"
24
#include "llvm/Pass.h"
25
 
26
using DebugFnMap =
27
    llvm::MapVector<const llvm::Function *, const llvm::DISubprogram *>;
28
using DebugInstMap = llvm::MapVector<const llvm::Instruction *, bool>;
29
using DebugVarMap = llvm::MapVector<const llvm::DILocalVariable *, unsigned>;
30
using WeakInstValueMap =
31
    llvm::MapVector<const llvm::Instruction *, llvm::WeakVH>;
32
 
33
/// Used to track the Debug Info Metadata information.
34
struct DebugInfoPerPass {
35
  // This maps a function name to its associated DISubprogram.
36
  DebugFnMap DIFunctions;
37
  // This maps an instruction and the info about whether it has !dbg attached.
38
  DebugInstMap DILocations;
39
  // This tracks value (instruction) deletion. If an instruction gets deleted,
40
  // WeakVH nulls itself.
41
  WeakInstValueMap InstToDelete;
42
  // Maps variable into dbg users (#dbg values/declares for this variable).
43
  DebugVarMap DIVariables;
44
};
45
 
46
namespace llvm {
47
class DIBuilder;
48
 
49
/// Add synthesized debug information to a module.
50
///
51
/// \param M The module to add debug information to.
52
/// \param Functions A range of functions to add debug information to.
53
/// \param Banner A prefix string to add to debug/error messages.
54
/// \param ApplyToMF A call back that will add debug information to the
55
///                  MachineFunction for a Function. If nullptr, then the
56
///                  MachineFunction (if any) will not be modified.
57
bool applyDebugifyMetadata(
58
    Module &M, iterator_range<Module::iterator> Functions, StringRef Banner,
59
    std::function<bool(DIBuilder &, Function &)> ApplyToMF);
60
 
61
/// Strip out all of the metadata and debug info inserted by debugify. If no
62
/// llvm.debugify module-level named metadata is present, this is a no-op.
63
/// Returns true if any change was made.
64
bool stripDebugifyMetadata(Module &M);
65
 
66
/// Collect original debug information before a pass.
67
///
68
/// \param M The module to collect debug information from.
69
/// \param Functions A range of functions to collect debug information from.
70
/// \param DebugInfoBeforePass DI metadata before a pass.
71
/// \param Banner A prefix string to add to debug/error messages.
72
/// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
73
bool collectDebugInfoMetadata(Module &M,
74
                              iterator_range<Module::iterator> Functions,
75
                              DebugInfoPerPass &DebugInfoBeforePass,
76
                              StringRef Banner, StringRef NameOfWrappedPass);
77
 
78
/// Check original debug information after a pass.
79
///
80
/// \param M The module to collect debug information from.
81
/// \param Functions A range of functions to collect debug information from.
82
/// \param DebugInfoBeforePass DI metadata before a pass.
83
/// \param Banner A prefix string to add to debug/error messages.
84
/// \param NameOfWrappedPass A name of a pass to add to debug/error messages.
85
bool checkDebugInfoMetadata(Module &M,
86
                            iterator_range<Module::iterator> Functions,
87
                            DebugInfoPerPass &DebugInfoBeforePass,
88
                            StringRef Banner, StringRef NameOfWrappedPass,
89
                            StringRef OrigDIVerifyBugsReportFilePath);
90
} // namespace llvm
91
 
92
/// Used to check whether we track synthetic or original debug info.
93
enum class DebugifyMode { NoDebugify, SyntheticDebugInfo, OriginalDebugInfo };
94
 
95
llvm::ModulePass *createDebugifyModulePass(
96
    enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
97
    llvm::StringRef NameOfWrappedPass = "",
98
    DebugInfoPerPass *DebugInfoBeforePass = nullptr);
99
llvm::FunctionPass *createDebugifyFunctionPass(
100
    enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
101
    llvm::StringRef NameOfWrappedPass = "",
102
    DebugInfoPerPass *DebugInfoBeforePass = nullptr);
103
 
104
class NewPMDebugifyPass : public llvm::PassInfoMixin<NewPMDebugifyPass> {
105
  llvm::StringRef NameOfWrappedPass;
106
  DebugInfoPerPass *DebugInfoBeforePass = nullptr;
107
  enum DebugifyMode Mode = DebugifyMode::NoDebugify;
108
public:
109
  NewPMDebugifyPass(
110
      enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
111
      llvm::StringRef NameOfWrappedPass = "",
112
      DebugInfoPerPass *DebugInfoBeforePass = nullptr)
113
      : NameOfWrappedPass(NameOfWrappedPass),
114
        DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode) {}
115
 
116
  llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
117
};
118
 
119
/// Track how much `debugify` information (in the `synthetic` mode only)
120
/// has been lost.
121
struct DebugifyStatistics {
122
  /// Number of missing dbg.values.
123
  unsigned NumDbgValuesMissing = 0;
124
 
125
  /// Number of dbg.values expected.
126
  unsigned NumDbgValuesExpected = 0;
127
 
128
  /// Number of instructions with empty debug locations.
129
  unsigned NumDbgLocsMissing = 0;
130
 
131
  /// Number of instructions expected to have debug locations.
132
  unsigned NumDbgLocsExpected = 0;
133
 
134
  /// Get the ratio of missing/expected dbg.values.
135
  float getMissingValueRatio() const {
136
    return float(NumDbgValuesMissing) / float(NumDbgLocsExpected);
137
  }
138
 
139
  /// Get the ratio of missing/expected instructions with locations.
140
  float getEmptyLocationRatio() const {
141
    return float(NumDbgLocsMissing) / float(NumDbgLocsExpected);
142
  }
143
};
144
 
145
/// Map pass names to a per-pass DebugifyStatistics instance.
146
using DebugifyStatsMap = llvm::MapVector<llvm::StringRef, DebugifyStatistics>;
147
 
148
llvm::ModulePass *createCheckDebugifyModulePass(
149
    bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
150
    DebugifyStatsMap *StatsMap = nullptr,
151
    enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
152
    DebugInfoPerPass *DebugInfoBeforePass = nullptr,
153
    llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
154
 
155
llvm::FunctionPass *createCheckDebugifyFunctionPass(
156
    bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
157
    DebugifyStatsMap *StatsMap = nullptr,
158
    enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
159
    DebugInfoPerPass *DebugInfoBeforePass = nullptr,
160
    llvm::StringRef OrigDIVerifyBugsReportFilePath = "");
161
 
162
class NewPMCheckDebugifyPass
163
    : public llvm::PassInfoMixin<NewPMCheckDebugifyPass> {
164
  llvm::StringRef NameOfWrappedPass;
165
  llvm::StringRef OrigDIVerifyBugsReportFilePath;
166
  DebugifyStatsMap *StatsMap;
167
  DebugInfoPerPass *DebugInfoBeforePass;
168
  enum DebugifyMode Mode;
169
  bool Strip;
170
public:
171
  NewPMCheckDebugifyPass(
172
      bool Strip = false, llvm::StringRef NameOfWrappedPass = "",
173
      DebugifyStatsMap *StatsMap = nullptr,
174
      enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
175
      DebugInfoPerPass *DebugInfoBeforePass = nullptr,
176
      llvm::StringRef OrigDIVerifyBugsReportFilePath = "")
177
      : NameOfWrappedPass(NameOfWrappedPass),
178
        OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
179
        StatsMap(StatsMap), DebugInfoBeforePass(DebugInfoBeforePass), Mode(Mode),
180
        Strip(Strip) {}
181
 
182
  llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
183
};
184
 
185
namespace llvm {
186
void exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map);
187
 
188
class DebugifyEachInstrumentation {
189
  llvm::StringRef OrigDIVerifyBugsReportFilePath = "";
190
  DebugInfoPerPass *DebugInfoBeforePass = nullptr;
191
  enum DebugifyMode Mode = DebugifyMode::NoDebugify;
192
  DebugifyStatsMap *DIStatsMap = nullptr;
193
 
194
public:
195
 
196
  void registerCallbacks(PassInstrumentationCallbacks &PIC);
197
  // Used within DebugifyMode::SyntheticDebugInfo mode.
198
  void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
199
  const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
200
  // Used within DebugifyMode::OriginalDebugInfo mode.
201
  void setDebugInfoBeforePass(DebugInfoPerPass &PerPassMap) {
202
    DebugInfoBeforePass = &PerPassMap;
203
  }
204
  DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
205
 
206
  void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
207
    OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
208
  }
209
  StringRef getOrigDIVerifyBugsReportFilePath() const {
210
    return OrigDIVerifyBugsReportFilePath;
211
  }
212
 
213
  void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
214
 
215
  bool isSyntheticDebugInfo() const {
216
    return Mode == DebugifyMode::SyntheticDebugInfo;
217
  }
218
  bool isOriginalDebugInfoMode() const {
219
    return Mode == DebugifyMode::OriginalDebugInfo;
220
  }
221
};
222
 
223
/// DebugifyCustomPassManager wraps each pass with the debugify passes if
224
/// needed.
225
/// NOTE: We support legacy custom pass manager only.
226
/// TODO: Add New PM support for custom pass manager.
227
class DebugifyCustomPassManager : public legacy::PassManager {
228
  StringRef OrigDIVerifyBugsReportFilePath;
229
  DebugifyStatsMap *DIStatsMap = nullptr;
230
  DebugInfoPerPass *DebugInfoBeforePass = nullptr;
231
  enum DebugifyMode Mode = DebugifyMode::NoDebugify;
232
 
233
public:
234
  using super = legacy::PassManager;
235
 
236
  void add(Pass *P) override {
237
    // Wrap each pass with (-check)-debugify passes if requested, making
238
    // exceptions for passes which shouldn't see -debugify instrumentation.
239
    bool WrapWithDebugify = Mode != DebugifyMode::NoDebugify &&
240
                            !P->getAsImmutablePass() && !isIRPrintingPass(P) &&
241
                            !isBitcodeWriterPass(P);
242
    if (!WrapWithDebugify) {
243
      super::add(P);
244
      return;
245
    }
246
 
247
    // Either apply -debugify/-check-debugify before/after each pass and collect
248
    // debug info loss statistics, or collect and check original debug info in
249
    // the optimizations.
250
    PassKind Kind = P->getPassKind();
251
    StringRef Name = P->getPassName();
252
 
253
    // TODO: Implement Debugify for LoopPass.
254
    switch (Kind) {
255
    case PT_Function:
256
      super::add(createDebugifyFunctionPass(Mode, Name, DebugInfoBeforePass));
257
      super::add(P);
258
      super::add(createCheckDebugifyFunctionPass(
259
          isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
260
          OrigDIVerifyBugsReportFilePath));
261
      break;
262
    case PT_Module:
263
      super::add(createDebugifyModulePass(Mode, Name, DebugInfoBeforePass));
264
      super::add(P);
265
      super::add(createCheckDebugifyModulePass(
266
          isSyntheticDebugInfo(), Name, DIStatsMap, Mode, DebugInfoBeforePass,
267
          OrigDIVerifyBugsReportFilePath));
268
      break;
269
    default:
270
      super::add(P);
271
      break;
272
    }
273
  }
274
 
275
  // Used within DebugifyMode::SyntheticDebugInfo mode.
276
  void setDIStatsMap(DebugifyStatsMap &StatMap) { DIStatsMap = &StatMap; }
277
  // Used within DebugifyMode::OriginalDebugInfo mode.
278
  void setDebugInfoBeforePass(DebugInfoPerPass &PerPassDI) {
279
    DebugInfoBeforePass = &PerPassDI;
280
  }
281
  void setOrigDIVerifyBugsReportFilePath(StringRef BugsReportFilePath) {
282
    OrigDIVerifyBugsReportFilePath = BugsReportFilePath;
283
  }
284
  StringRef getOrigDIVerifyBugsReportFilePath() const {
285
    return OrigDIVerifyBugsReportFilePath;
286
  }
287
 
288
  void setDebugifyMode(enum DebugifyMode M) { Mode = M; }
289
 
290
  bool isSyntheticDebugInfo() const {
291
    return Mode == DebugifyMode::SyntheticDebugInfo;
292
  }
293
  bool isOriginalDebugInfoMode() const {
294
    return Mode == DebugifyMode::OriginalDebugInfo;
295
  }
296
 
297
  const DebugifyStatsMap &getDebugifyStatsMap() const { return *DIStatsMap; }
298
  DebugInfoPerPass &getDebugInfoPerPass() { return *DebugInfoBeforePass; }
299
};
300
} // namespace llvm
301
 
302
#endif // LLVM_TRANSFORMS_UTILS_DEBUGIFY_H