Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- llvm/IR/DiagnosticInfo.h - Diagnostic Declaration --------*- 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 declares the different classes involved in low level diagnostics. |
||
10 | // |
||
11 | // Diagnostics reporting is still done as part of the LLVMContext. |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_IR_DIAGNOSTICINFO_H |
||
15 | #define LLVM_IR_DIAGNOSTICINFO_H |
||
16 | |||
17 | #include "llvm-c/Types.h" |
||
18 | #include "llvm/ADT/ArrayRef.h" |
||
19 | #include "llvm/ADT/SmallVector.h" |
||
20 | #include "llvm/ADT/StringRef.h" |
||
21 | #include "llvm/ADT/Twine.h" |
||
22 | #include "llvm/IR/DebugLoc.h" |
||
23 | #include "llvm/Support/CBindingWrapping.h" |
||
24 | #include "llvm/Support/ErrorHandling.h" |
||
25 | #include "llvm/Support/SourceMgr.h" |
||
26 | #include "llvm/Support/TypeSize.h" |
||
27 | #include <algorithm> |
||
28 | #include <cstdint> |
||
29 | #include <functional> |
||
30 | #include <iterator> |
||
31 | #include <optional> |
||
32 | #include <string> |
||
33 | |||
34 | namespace llvm { |
||
35 | |||
36 | // Forward declarations. |
||
37 | class DiagnosticPrinter; |
||
38 | class DIFile; |
||
39 | class DISubprogram; |
||
40 | class CallInst; |
||
41 | class Function; |
||
42 | class Instruction; |
||
43 | class InstructionCost; |
||
44 | class Module; |
||
45 | class Type; |
||
46 | class Value; |
||
47 | |||
48 | /// Defines the different supported severity of a diagnostic. |
||
49 | enum DiagnosticSeverity : char { |
||
50 | DS_Error, |
||
51 | DS_Warning, |
||
52 | DS_Remark, |
||
53 | // A note attaches additional information to one of the previous diagnostic |
||
54 | // types. |
||
55 | DS_Note |
||
56 | }; |
||
57 | |||
58 | /// Defines the different supported kind of a diagnostic. |
||
59 | /// This enum should be extended with a new ID for each added concrete subclass. |
||
60 | enum DiagnosticKind { |
||
61 | DK_InlineAsm, |
||
62 | DK_ResourceLimit, |
||
63 | DK_StackSize, |
||
64 | DK_Linker, |
||
65 | DK_Lowering, |
||
66 | DK_DebugMetadataVersion, |
||
67 | DK_DebugMetadataInvalid, |
||
68 | DK_ISelFallback, |
||
69 | DK_SampleProfile, |
||
70 | DK_OptimizationRemark, |
||
71 | DK_OptimizationRemarkMissed, |
||
72 | DK_OptimizationRemarkAnalysis, |
||
73 | DK_OptimizationRemarkAnalysisFPCommute, |
||
74 | DK_OptimizationRemarkAnalysisAliasing, |
||
75 | DK_OptimizationFailure, |
||
76 | DK_FirstRemark = DK_OptimizationRemark, |
||
77 | DK_LastRemark = DK_OptimizationFailure, |
||
78 | DK_MachineOptimizationRemark, |
||
79 | DK_MachineOptimizationRemarkMissed, |
||
80 | DK_MachineOptimizationRemarkAnalysis, |
||
81 | DK_FirstMachineRemark = DK_MachineOptimizationRemark, |
||
82 | DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis, |
||
83 | DK_MIRParser, |
||
84 | DK_PGOProfile, |
||
85 | DK_Unsupported, |
||
86 | DK_SrcMgr, |
||
87 | DK_DontCall, |
||
88 | DK_MisExpect, |
||
89 | DK_FirstPluginKind // Must be last value to work with |
||
90 | // getNextAvailablePluginDiagnosticKind |
||
91 | }; |
||
92 | |||
93 | /// Get the next available kind ID for a plugin diagnostic. |
||
94 | /// Each time this function is called, it returns a different number. |
||
95 | /// Therefore, a plugin that wants to "identify" its own classes |
||
96 | /// with a dynamic identifier, just have to use this method to get a new ID |
||
97 | /// and assign it to each of its classes. |
||
98 | /// The returned ID will be greater than or equal to DK_FirstPluginKind. |
||
99 | /// Thus, the plugin identifiers will not conflict with the |
||
100 | /// DiagnosticKind values. |
||
101 | int getNextAvailablePluginDiagnosticKind(); |
||
102 | |||
103 | /// This is the base abstract class for diagnostic reporting in |
||
104 | /// the backend. |
||
105 | /// The print method must be overloaded by the subclasses to print a |
||
106 | /// user-friendly message in the client of the backend (let us call it a |
||
107 | /// frontend). |
||
108 | class DiagnosticInfo { |
||
109 | private: |
||
110 | /// Kind defines the kind of report this is about. |
||
111 | const /* DiagnosticKind */ int Kind; |
||
112 | /// Severity gives the severity of the diagnostic. |
||
113 | const DiagnosticSeverity Severity; |
||
114 | |||
115 | virtual void anchor(); |
||
116 | public: |
||
117 | DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity) |
||
118 | : Kind(Kind), Severity(Severity) {} |
||
119 | |||
120 | virtual ~DiagnosticInfo() = default; |
||
121 | |||
122 | /* DiagnosticKind */ int getKind() const { return Kind; } |
||
123 | DiagnosticSeverity getSeverity() const { return Severity; } |
||
124 | |||
125 | /// Print using the given \p DP a user-friendly message. |
||
126 | /// This is the default message that will be printed to the user. |
||
127 | /// It is used when the frontend does not directly take advantage |
||
128 | /// of the information contained in fields of the subclasses. |
||
129 | /// The printed message must not end with '.' nor start with a severity |
||
130 | /// keyword. |
||
131 | virtual void print(DiagnosticPrinter &DP) const = 0; |
||
132 | }; |
||
133 | |||
134 | using DiagnosticHandlerFunction = std::function<void(const DiagnosticInfo &)>; |
||
135 | |||
136 | /// Diagnostic information for inline asm reporting. |
||
137 | /// This is basically a message and an optional location. |
||
138 | class DiagnosticInfoInlineAsm : public DiagnosticInfo { |
||
139 | private: |
||
140 | /// Optional line information. 0 if not set. |
||
141 | uint64_t LocCookie = 0; |
||
142 | /// Message to be reported. |
||
143 | const Twine &MsgStr; |
||
144 | /// Optional origin of the problem. |
||
145 | const Instruction *Instr = nullptr; |
||
146 | |||
147 | public: |
||
148 | /// \p MsgStr is the message to be reported to the frontend. |
||
149 | /// This class does not copy \p MsgStr, therefore the reference must be valid |
||
150 | /// for the whole life time of the Diagnostic. |
||
151 | DiagnosticInfoInlineAsm(const Twine &MsgStr, |
||
152 | DiagnosticSeverity Severity = DS_Error) |
||
153 | : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr) {} |
||
154 | |||
155 | /// \p LocCookie if non-zero gives the line number for this report. |
||
156 | /// \p MsgStr gives the message. |
||
157 | /// This class does not copy \p MsgStr, therefore the reference must be valid |
||
158 | /// for the whole life time of the Diagnostic. |
||
159 | DiagnosticInfoInlineAsm(uint64_t LocCookie, const Twine &MsgStr, |
||
160 | DiagnosticSeverity Severity = DS_Error) |
||
161 | : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie), |
||
162 | MsgStr(MsgStr) {} |
||
163 | |||
164 | /// \p Instr gives the original instruction that triggered the diagnostic. |
||
165 | /// \p MsgStr gives the message. |
||
166 | /// This class does not copy \p MsgStr, therefore the reference must be valid |
||
167 | /// for the whole life time of the Diagnostic. |
||
168 | /// Same for \p I. |
||
169 | DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr, |
||
170 | DiagnosticSeverity Severity = DS_Error); |
||
171 | |||
172 | uint64_t getLocCookie() const { return LocCookie; } |
||
173 | const Twine &getMsgStr() const { return MsgStr; } |
||
174 | const Instruction *getInstruction() const { return Instr; } |
||
175 | |||
176 | /// \see DiagnosticInfo::print. |
||
177 | void print(DiagnosticPrinter &DP) const override; |
||
178 | |||
179 | static bool classof(const DiagnosticInfo *DI) { |
||
180 | return DI->getKind() == DK_InlineAsm; |
||
181 | } |
||
182 | }; |
||
183 | |||
184 | /// Diagnostic information for debug metadata version reporting. |
||
185 | /// This is basically a module and a version. |
||
186 | class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo { |
||
187 | private: |
||
188 | /// The module that is concerned by this debug metadata version diagnostic. |
||
189 | const Module &M; |
||
190 | /// The actual metadata version. |
||
191 | unsigned MetadataVersion; |
||
192 | |||
193 | public: |
||
194 | /// \p The module that is concerned by this debug metadata version diagnostic. |
||
195 | /// \p The actual metadata version. |
||
196 | DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion, |
||
197 | DiagnosticSeverity Severity = DS_Warning) |
||
198 | : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M), |
||
199 | MetadataVersion(MetadataVersion) {} |
||
200 | |||
201 | const Module &getModule() const { return M; } |
||
202 | unsigned getMetadataVersion() const { return MetadataVersion; } |
||
203 | |||
204 | /// \see DiagnosticInfo::print. |
||
205 | void print(DiagnosticPrinter &DP) const override; |
||
206 | |||
207 | static bool classof(const DiagnosticInfo *DI) { |
||
208 | return DI->getKind() == DK_DebugMetadataVersion; |
||
209 | } |
||
210 | }; |
||
211 | |||
212 | /// Diagnostic information for stripping invalid debug metadata. |
||
213 | class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo { |
||
214 | private: |
||
215 | /// The module that is concerned by this debug metadata version diagnostic. |
||
216 | const Module &M; |
||
217 | |||
218 | public: |
||
219 | /// \p The module that is concerned by this debug metadata version diagnostic. |
||
220 | DiagnosticInfoIgnoringInvalidDebugMetadata( |
||
221 | const Module &M, DiagnosticSeverity Severity = DS_Warning) |
||
222 | : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {} |
||
223 | |||
224 | const Module &getModule() const { return M; } |
||
225 | |||
226 | /// \see DiagnosticInfo::print. |
||
227 | void print(DiagnosticPrinter &DP) const override; |
||
228 | |||
229 | static bool classof(const DiagnosticInfo *DI) { |
||
230 | return DI->getKind() == DK_DebugMetadataInvalid; |
||
231 | } |
||
232 | }; |
||
233 | |||
234 | /// Diagnostic information for the sample profiler. |
||
235 | class DiagnosticInfoSampleProfile : public DiagnosticInfo { |
||
236 | public: |
||
237 | DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum, |
||
238 | const Twine &Msg, |
||
239 | DiagnosticSeverity Severity = DS_Error) |
||
240 | : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), |
||
241 | LineNum(LineNum), Msg(Msg) {} |
||
242 | DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg, |
||
243 | DiagnosticSeverity Severity = DS_Error) |
||
244 | : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), |
||
245 | Msg(Msg) {} |
||
246 | DiagnosticInfoSampleProfile(const Twine &Msg, |
||
247 | DiagnosticSeverity Severity = DS_Error) |
||
248 | : DiagnosticInfo(DK_SampleProfile, Severity), Msg(Msg) {} |
||
249 | |||
250 | /// \see DiagnosticInfo::print. |
||
251 | void print(DiagnosticPrinter &DP) const override; |
||
252 | |||
253 | static bool classof(const DiagnosticInfo *DI) { |
||
254 | return DI->getKind() == DK_SampleProfile; |
||
255 | } |
||
256 | |||
257 | StringRef getFileName() const { return FileName; } |
||
258 | unsigned getLineNum() const { return LineNum; } |
||
259 | const Twine &getMsg() const { return Msg; } |
||
260 | |||
261 | private: |
||
262 | /// Name of the input file associated with this diagnostic. |
||
263 | StringRef FileName; |
||
264 | |||
265 | /// Line number where the diagnostic occurred. If 0, no line number will |
||
266 | /// be emitted in the message. |
||
267 | unsigned LineNum = 0; |
||
268 | |||
269 | /// Message to report. |
||
270 | const Twine &Msg; |
||
271 | }; |
||
272 | |||
273 | /// Diagnostic information for the PGO profiler. |
||
274 | class DiagnosticInfoPGOProfile : public DiagnosticInfo { |
||
275 | public: |
||
276 | DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg, |
||
277 | DiagnosticSeverity Severity = DS_Error) |
||
278 | : DiagnosticInfo(DK_PGOProfile, Severity), FileName(FileName), Msg(Msg) {} |
||
279 | |||
280 | /// \see DiagnosticInfo::print. |
||
281 | void print(DiagnosticPrinter &DP) const override; |
||
282 | |||
283 | static bool classof(const DiagnosticInfo *DI) { |
||
284 | return DI->getKind() == DK_PGOProfile; |
||
285 | } |
||
286 | |||
287 | const char *getFileName() const { return FileName; } |
||
288 | const Twine &getMsg() const { return Msg; } |
||
289 | |||
290 | private: |
||
291 | /// Name of the input file associated with this diagnostic. |
||
292 | const char *FileName; |
||
293 | |||
294 | /// Message to report. |
||
295 | const Twine &Msg; |
||
296 | }; |
||
297 | |||
298 | class DiagnosticLocation { |
||
299 | DIFile *File = nullptr; |
||
300 | unsigned Line = 0; |
||
301 | unsigned Column = 0; |
||
302 | |||
303 | public: |
||
304 | DiagnosticLocation() = default; |
||
305 | DiagnosticLocation(const DebugLoc &DL); |
||
306 | DiagnosticLocation(const DISubprogram *SP); |
||
307 | |||
308 | bool isValid() const { return File; } |
||
309 | /// Return the full path to the file. |
||
310 | std::string getAbsolutePath() const; |
||
311 | /// Return the file name relative to the compilation directory. |
||
312 | StringRef getRelativePath() const; |
||
313 | unsigned getLine() const { return Line; } |
||
314 | unsigned getColumn() const { return Column; } |
||
315 | }; |
||
316 | |||
317 | /// Common features for diagnostics with an associated location. |
||
318 | class DiagnosticInfoWithLocationBase : public DiagnosticInfo { |
||
319 | void anchor() override; |
||
320 | public: |
||
321 | /// \p Fn is the function where the diagnostic is being emitted. \p Loc is |
||
322 | /// the location information to use in the diagnostic. |
||
323 | DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind, |
||
324 | enum DiagnosticSeverity Severity, |
||
325 | const Function &Fn, |
||
326 | const DiagnosticLocation &Loc) |
||
327 | : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {} |
||
328 | |||
329 | /// Return true if location information is available for this diagnostic. |
||
330 | bool isLocationAvailable() const { return Loc.isValid(); } |
||
331 | |||
332 | /// Return a string with the location information for this diagnostic |
||
333 | /// in the format "file:line:col". If location information is not available, |
||
334 | /// it returns "<unknown>:0:0". |
||
335 | std::string getLocationStr() const; |
||
336 | |||
337 | /// Return location information for this diagnostic in three parts: |
||
338 | /// the relative source file path, line number and column. |
||
339 | void getLocation(StringRef &RelativePath, unsigned &Line, |
||
340 | unsigned &Column) const; |
||
341 | |||
342 | /// Return the absolute path tot the file. |
||
343 | std::string getAbsolutePath() const; |
||
344 | |||
345 | const Function &getFunction() const { return Fn; } |
||
346 | DiagnosticLocation getLocation() const { return Loc; } |
||
347 | |||
348 | private: |
||
349 | /// Function where this diagnostic is triggered. |
||
350 | const Function &Fn; |
||
351 | |||
352 | /// Debug location where this diagnostic is triggered. |
||
353 | DiagnosticLocation Loc; |
||
354 | }; |
||
355 | |||
356 | /// Diagnostic information for stack size etc. reporting. |
||
357 | /// This is basically a function and a size. |
||
358 | class DiagnosticInfoResourceLimit : public DiagnosticInfoWithLocationBase { |
||
359 | private: |
||
360 | /// The function that is concerned by this resource limit diagnostic. |
||
361 | const Function &Fn; |
||
362 | |||
363 | /// Description of the resource type (e.g. stack size) |
||
364 | const char *ResourceName; |
||
365 | |||
366 | /// The computed size usage |
||
367 | uint64_t ResourceSize; |
||
368 | |||
369 | // Threshould passed |
||
370 | uint64_t ResourceLimit; |
||
371 | |||
372 | public: |
||
373 | /// \p The function that is concerned by this stack size diagnostic. |
||
374 | /// \p The computed stack size. |
||
375 | DiagnosticInfoResourceLimit(const Function &Fn, const char *ResourceName, |
||
376 | uint64_t ResourceSize, uint64_t ResourceLimit, |
||
377 | DiagnosticSeverity Severity = DS_Warning, |
||
378 | DiagnosticKind Kind = DK_ResourceLimit); |
||
379 | |||
380 | const Function &getFunction() const { return Fn; } |
||
381 | const char *getResourceName() const { return ResourceName; } |
||
382 | uint64_t getResourceSize() const { return ResourceSize; } |
||
383 | uint64_t getResourceLimit() const { return ResourceLimit; } |
||
384 | |||
385 | /// \see DiagnosticInfo::print. |
||
386 | void print(DiagnosticPrinter &DP) const override; |
||
387 | |||
388 | static bool classof(const DiagnosticInfo *DI) { |
||
389 | return DI->getKind() == DK_ResourceLimit || DI->getKind() == DK_StackSize; |
||
390 | } |
||
391 | }; |
||
392 | |||
393 | class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit { |
||
394 | void anchor() override; |
||
395 | |||
396 | public: |
||
397 | DiagnosticInfoStackSize(const Function &Fn, uint64_t StackSize, |
||
398 | uint64_t StackLimit, |
||
399 | DiagnosticSeverity Severity = DS_Warning) |
||
400 | : DiagnosticInfoResourceLimit(Fn, "stack frame size", StackSize, |
||
401 | StackLimit, Severity, DK_StackSize) {} |
||
402 | |||
403 | uint64_t getStackSize() const { return getResourceSize(); } |
||
404 | uint64_t getStackLimit() const { return getResourceLimit(); } |
||
405 | |||
406 | static bool classof(const DiagnosticInfo *DI) { |
||
407 | return DI->getKind() == DK_StackSize; |
||
408 | } |
||
409 | }; |
||
410 | |||
411 | /// Common features for diagnostics dealing with optimization remarks |
||
412 | /// that are used by both IR and MIR passes. |
||
413 | class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase { |
||
414 | public: |
||
415 | /// Used to set IsVerbose via the stream interface. |
||
416 | struct setIsVerbose {}; |
||
417 | |||
418 | /// When an instance of this is inserted into the stream, the arguments |
||
419 | /// following will not appear in the remark printed in the compiler output |
||
420 | /// (-Rpass) but only in the optimization record file |
||
421 | /// (-fsave-optimization-record). |
||
422 | struct setExtraArgs {}; |
||
423 | |||
424 | /// Used in the streaming interface as the general argument type. It |
||
425 | /// internally converts everything into a key-value pair. |
||
426 | struct Argument { |
||
427 | std::string Key; |
||
428 | std::string Val; |
||
429 | // If set, the debug location corresponding to the value. |
||
430 | DiagnosticLocation Loc; |
||
431 | |||
432 | explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {} |
||
433 | Argument(StringRef Key, const Value *V); |
||
434 | Argument(StringRef Key, const Type *T); |
||
435 | Argument(StringRef Key, StringRef S); |
||
436 | Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {}; |
||
437 | Argument(StringRef Key, int N); |
||
438 | Argument(StringRef Key, float N); |
||
439 | Argument(StringRef Key, long N); |
||
440 | Argument(StringRef Key, long long N); |
||
441 | Argument(StringRef Key, unsigned N); |
||
442 | Argument(StringRef Key, unsigned long N); |
||
443 | Argument(StringRef Key, unsigned long long N); |
||
444 | Argument(StringRef Key, ElementCount EC); |
||
445 | Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {} |
||
446 | Argument(StringRef Key, DebugLoc dl); |
||
447 | Argument(StringRef Key, InstructionCost C); |
||
448 | }; |
||
449 | |||
450 | /// \p PassName is the name of the pass emitting this diagnostic. \p |
||
451 | /// RemarkName is a textual identifier for the remark (single-word, |
||
452 | /// camel-case). \p Fn is the function where the diagnostic is being emitted. |
||
453 | /// \p Loc is the location information to use in the diagnostic. If line table |
||
454 | /// information is available, the diagnostic will include the source code |
||
455 | /// location. |
||
456 | DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind, |
||
457 | enum DiagnosticSeverity Severity, |
||
458 | const char *PassName, StringRef RemarkName, |
||
459 | const Function &Fn, |
||
460 | const DiagnosticLocation &Loc) |
||
461 | : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc), |
||
462 | PassName(PassName), RemarkName(RemarkName) {} |
||
463 | |||
464 | void insert(StringRef S); |
||
465 | void insert(Argument A); |
||
466 | void insert(setIsVerbose V); |
||
467 | void insert(setExtraArgs EA); |
||
468 | |||
469 | /// \see DiagnosticInfo::print. |
||
470 | void print(DiagnosticPrinter &DP) const override; |
||
471 | |||
472 | /// Return true if this optimization remark is enabled by one of |
||
473 | /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed, |
||
474 | /// or -pass-remarks-analysis). Note that this only handles the LLVM |
||
475 | /// flags. We cannot access Clang flags from here (they are handled |
||
476 | /// in BackendConsumer::OptimizationRemarkHandler). |
||
477 | virtual bool isEnabled() const = 0; |
||
478 | |||
479 | StringRef getPassName() const { return PassName; } |
||
480 | StringRef getRemarkName() const { return RemarkName; } |
||
481 | std::string getMsg() const; |
||
482 | std::optional<uint64_t> getHotness() const { return Hotness; } |
||
483 | void setHotness(std::optional<uint64_t> H) { Hotness = H; } |
||
484 | |||
485 | bool isVerbose() const { return IsVerbose; } |
||
486 | |||
487 | ArrayRef<Argument> getArgs() const { return Args; } |
||
488 | |||
489 | static bool classof(const DiagnosticInfo *DI) { |
||
490 | return (DI->getKind() >= DK_FirstRemark && |
||
491 | DI->getKind() <= DK_LastRemark) || |
||
492 | (DI->getKind() >= DK_FirstMachineRemark && |
||
493 | DI->getKind() <= DK_LastMachineRemark); |
||
494 | } |
||
495 | |||
496 | bool isPassed() const { |
||
497 | return (getKind() == DK_OptimizationRemark || |
||
498 | getKind() == DK_MachineOptimizationRemark); |
||
499 | } |
||
500 | |||
501 | bool isMissed() const { |
||
502 | return (getKind() == DK_OptimizationRemarkMissed || |
||
503 | getKind() == DK_MachineOptimizationRemarkMissed); |
||
504 | } |
||
505 | |||
506 | bool isAnalysis() const { |
||
507 | return (getKind() == DK_OptimizationRemarkAnalysis || |
||
508 | getKind() == DK_MachineOptimizationRemarkAnalysis); |
||
509 | } |
||
510 | |||
511 | protected: |
||
512 | /// Name of the pass that triggers this report. If this matches the |
||
513 | /// regular expression given in -Rpass=regexp, then the remark will |
||
514 | /// be emitted. |
||
515 | const char *PassName; |
||
516 | |||
517 | /// Textual identifier for the remark (single-word, camel-case). Can be used |
||
518 | /// by external tools reading the output file for optimization remarks to |
||
519 | /// identify the remark. |
||
520 | StringRef RemarkName; |
||
521 | |||
522 | /// If profile information is available, this is the number of times the |
||
523 | /// corresponding code was executed in a profile instrumentation run. |
||
524 | std::optional<uint64_t> Hotness; |
||
525 | |||
526 | /// Arguments collected via the streaming interface. |
||
527 | SmallVector<Argument, 4> Args; |
||
528 | |||
529 | /// The remark is expected to be noisy. |
||
530 | bool IsVerbose = false; |
||
531 | |||
532 | /// If positive, the index of the first argument that only appear in |
||
533 | /// the optimization records and not in the remark printed in the compiler |
||
534 | /// output. |
||
535 | int FirstExtraArgIndex = -1; |
||
536 | }; |
||
537 | |||
538 | /// Allow the insertion operator to return the actual remark type rather than a |
||
539 | /// common base class. This allows returning the result of the insertion |
||
540 | /// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah". |
||
541 | template <class RemarkT> |
||
542 | RemarkT & |
||
543 | operator<<(RemarkT &R, |
||
544 | std::enable_if_t< |
||
545 | std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, |
||
546 | StringRef> |
||
547 | S) { |
||
548 | R.insert(S); |
||
549 | return R; |
||
550 | } |
||
551 | |||
552 | /// Also allow r-value for the remark to allow insertion into a |
||
553 | /// temporarily-constructed remark. |
||
554 | template <class RemarkT> |
||
555 | RemarkT & |
||
556 | operator<<(RemarkT &&R, |
||
557 | std::enable_if_t< |
||
558 | std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, |
||
559 | StringRef> |
||
560 | S) { |
||
561 | R.insert(S); |
||
562 | return R; |
||
563 | } |
||
564 | |||
565 | template <class RemarkT> |
||
566 | RemarkT & |
||
567 | operator<<(RemarkT &R, |
||
568 | std::enable_if_t< |
||
569 | std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, |
||
570 | DiagnosticInfoOptimizationBase::Argument> |
||
571 | A) { |
||
572 | R.insert(A); |
||
573 | return R; |
||
574 | } |
||
575 | |||
576 | template <class RemarkT> |
||
577 | RemarkT & |
||
578 | operator<<(RemarkT &&R, |
||
579 | std::enable_if_t< |
||
580 | std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, |
||
581 | DiagnosticInfoOptimizationBase::Argument> |
||
582 | A) { |
||
583 | R.insert(A); |
||
584 | return R; |
||
585 | } |
||
586 | |||
587 | template <class RemarkT> |
||
588 | RemarkT & |
||
589 | operator<<(RemarkT &R, |
||
590 | std::enable_if_t< |
||
591 | std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, |
||
592 | DiagnosticInfoOptimizationBase::setIsVerbose> |
||
593 | V) { |
||
594 | R.insert(V); |
||
595 | return R; |
||
596 | } |
||
597 | |||
598 | template <class RemarkT> |
||
599 | RemarkT & |
||
600 | operator<<(RemarkT &&R, |
||
601 | std::enable_if_t< |
||
602 | std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, |
||
603 | DiagnosticInfoOptimizationBase::setIsVerbose> |
||
604 | V) { |
||
605 | R.insert(V); |
||
606 | return R; |
||
607 | } |
||
608 | |||
609 | template <class RemarkT> |
||
610 | RemarkT & |
||
611 | operator<<(RemarkT &R, |
||
612 | std::enable_if_t< |
||
613 | std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, |
||
614 | DiagnosticInfoOptimizationBase::setExtraArgs> |
||
615 | EA) { |
||
616 | R.insert(EA); |
||
617 | return R; |
||
618 | } |
||
619 | |||
620 | /// Common features for diagnostics dealing with optimization remarks |
||
621 | /// that are used by IR passes. |
||
622 | class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase { |
||
623 | void anchor() override; |
||
624 | public: |
||
625 | /// \p PassName is the name of the pass emitting this diagnostic. \p |
||
626 | /// RemarkName is a textual identifier for the remark (single-word, |
||
627 | /// camel-case). \p Fn is the function where the diagnostic is being emitted. |
||
628 | /// \p Loc is the location information to use in the diagnostic. If line table |
||
629 | /// information is available, the diagnostic will include the source code |
||
630 | /// location. \p CodeRegion is IR value (currently basic block) that the |
||
631 | /// optimization operates on. This is currently used to provide run-time |
||
632 | /// hotness information with PGO. |
||
633 | DiagnosticInfoIROptimization(enum DiagnosticKind Kind, |
||
634 | enum DiagnosticSeverity Severity, |
||
635 | const char *PassName, StringRef RemarkName, |
||
636 | const Function &Fn, |
||
637 | const DiagnosticLocation &Loc, |
||
638 | const Value *CodeRegion = nullptr) |
||
639 | : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn, |
||
640 | Loc), |
||
641 | CodeRegion(CodeRegion) {} |
||
642 | |||
643 | /// This is ctor variant allows a pass to build an optimization remark |
||
644 | /// from an existing remark. |
||
645 | /// |
||
646 | /// This is useful when a transformation pass (e.g LV) wants to emit a remark |
||
647 | /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis |
||
648 | /// remark. The string \p Prepend will be emitted before the original |
||
649 | /// message. |
||
650 | DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend, |
||
651 | const DiagnosticInfoIROptimization &Orig) |
||
652 | : DiagnosticInfoOptimizationBase( |
||
653 | (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName, |
||
654 | Orig.RemarkName, Orig.getFunction(), Orig.getLocation()), |
||
655 | CodeRegion(Orig.getCodeRegion()) { |
||
656 | *this << Prepend; |
||
657 | std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args)); |
||
658 | } |
||
659 | |||
660 | /// Legacy interface. |
||
661 | /// \p PassName is the name of the pass emitting this diagnostic. |
||
662 | /// \p Fn is the function where the diagnostic is being emitted. \p Loc is |
||
663 | /// the location information to use in the diagnostic. If line table |
||
664 | /// information is available, the diagnostic will include the source code |
||
665 | /// location. \p Msg is the message to show. Note that this class does not |
||
666 | /// copy this message, so this reference must be valid for the whole life time |
||
667 | /// of the diagnostic. |
||
668 | DiagnosticInfoIROptimization(enum DiagnosticKind Kind, |
||
669 | enum DiagnosticSeverity Severity, |
||
670 | const char *PassName, const Function &Fn, |
||
671 | const DiagnosticLocation &Loc, const Twine &Msg) |
||
672 | : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) { |
||
673 | *this << Msg.str(); |
||
674 | } |
||
675 | |||
676 | const Value *getCodeRegion() const { return CodeRegion; } |
||
677 | |||
678 | static bool classof(const DiagnosticInfo *DI) { |
||
679 | return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark; |
||
680 | } |
||
681 | |||
682 | private: |
||
683 | /// The IR value (currently basic block) that the optimization operates on. |
||
684 | /// This is currently used to provide run-time hotness information with PGO. |
||
685 | const Value *CodeRegion = nullptr; |
||
686 | }; |
||
687 | |||
688 | /// Diagnostic information for applied optimization remarks. |
||
689 | class OptimizationRemark : public DiagnosticInfoIROptimization { |
||
690 | public: |
||
691 | /// \p PassName is the name of the pass emitting this diagnostic. If this name |
||
692 | /// matches the regular expression given in -Rpass=, then the diagnostic will |
||
693 | /// be emitted. \p RemarkName is a textual identifier for the remark (single- |
||
694 | /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the |
||
695 | /// region that the optimization operates on (currently only block is |
||
696 | /// supported). |
||
697 | OptimizationRemark(const char *PassName, StringRef RemarkName, |
||
698 | const DiagnosticLocation &Loc, const Value *CodeRegion); |
||
699 | |||
700 | /// Same as above, but the debug location and code region are derived from \p |
||
701 | /// Instr. |
||
702 | OptimizationRemark(const char *PassName, StringRef RemarkName, |
||
703 | const Instruction *Inst); |
||
704 | |||
705 | /// Same as above, but the debug location and code region are derived from \p |
||
706 | /// Func. |
||
707 | OptimizationRemark(const char *PassName, StringRef RemarkName, |
||
708 | const Function *Func); |
||
709 | |||
710 | static bool classof(const DiagnosticInfo *DI) { |
||
711 | return DI->getKind() == DK_OptimizationRemark; |
||
712 | } |
||
713 | |||
714 | /// \see DiagnosticInfoOptimizationBase::isEnabled. |
||
715 | bool isEnabled() const override; |
||
716 | |||
717 | private: |
||
718 | /// This is deprecated now and only used by the function API below. |
||
719 | /// \p PassName is the name of the pass emitting this diagnostic. If |
||
720 | /// this name matches the regular expression given in -Rpass=, then the |
||
721 | /// diagnostic will be emitted. \p Fn is the function where the diagnostic |
||
722 | /// is being emitted. \p Loc is the location information to use in the |
||
723 | /// diagnostic. If line table information is available, the diagnostic |
||
724 | /// will include the source code location. \p Msg is the message to show. |
||
725 | /// Note that this class does not copy this message, so this reference |
||
726 | /// must be valid for the whole life time of the diagnostic. |
||
727 | OptimizationRemark(const char *PassName, const Function &Fn, |
||
728 | const DiagnosticLocation &Loc, const Twine &Msg) |
||
729 | : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, |
||
730 | Fn, Loc, Msg) {} |
||
731 | }; |
||
732 | |||
733 | /// Diagnostic information for missed-optimization remarks. |
||
734 | class OptimizationRemarkMissed : public DiagnosticInfoIROptimization { |
||
735 | public: |
||
736 | /// \p PassName is the name of the pass emitting this diagnostic. If this name |
||
737 | /// matches the regular expression given in -Rpass-missed=, then the |
||
738 | /// diagnostic will be emitted. \p RemarkName is a textual identifier for the |
||
739 | /// remark (single-word, camel-case). \p Loc is the debug location and \p |
||
740 | /// CodeRegion is the region that the optimization operates on (currently only |
||
741 | /// block is supported). |
||
742 | OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, |
||
743 | const DiagnosticLocation &Loc, |
||
744 | const Value *CodeRegion); |
||
745 | |||
746 | /// Same as above but \p Inst is used to derive code region and debug |
||
747 | /// location. |
||
748 | OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, |
||
749 | const Instruction *Inst); |
||
750 | |||
751 | /// Same as above but \p F is used to derive code region and debug |
||
752 | /// location. |
||
753 | OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, |
||
754 | const Function *F); |
||
755 | |||
756 | static bool classof(const DiagnosticInfo *DI) { |
||
757 | return DI->getKind() == DK_OptimizationRemarkMissed; |
||
758 | } |
||
759 | |||
760 | /// \see DiagnosticInfoOptimizationBase::isEnabled. |
||
761 | bool isEnabled() const override; |
||
762 | |||
763 | private: |
||
764 | /// This is deprecated now and only used by the function API below. |
||
765 | /// \p PassName is the name of the pass emitting this diagnostic. If |
||
766 | /// this name matches the regular expression given in -Rpass-missed=, then the |
||
767 | /// diagnostic will be emitted. \p Fn is the function where the diagnostic |
||
768 | /// is being emitted. \p Loc is the location information to use in the |
||
769 | /// diagnostic. If line table information is available, the diagnostic |
||
770 | /// will include the source code location. \p Msg is the message to show. |
||
771 | /// Note that this class does not copy this message, so this reference |
||
772 | /// must be valid for the whole life time of the diagnostic. |
||
773 | OptimizationRemarkMissed(const char *PassName, const Function &Fn, |
||
774 | const DiagnosticLocation &Loc, const Twine &Msg) |
||
775 | : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark, |
||
776 | PassName, Fn, Loc, Msg) {} |
||
777 | }; |
||
778 | |||
779 | /// Diagnostic information for optimization analysis remarks. |
||
780 | class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization { |
||
781 | public: |
||
782 | /// \p PassName is the name of the pass emitting this diagnostic. If this name |
||
783 | /// matches the regular expression given in -Rpass-analysis=, then the |
||
784 | /// diagnostic will be emitted. \p RemarkName is a textual identifier for the |
||
785 | /// remark (single-word, camel-case). \p Loc is the debug location and \p |
||
786 | /// CodeRegion is the region that the optimization operates on (currently only |
||
787 | /// block is supported). |
||
788 | OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, |
||
789 | const DiagnosticLocation &Loc, |
||
790 | const Value *CodeRegion); |
||
791 | |||
792 | /// This is ctor variant allows a pass to build an optimization remark |
||
793 | /// from an existing remark. |
||
794 | /// |
||
795 | /// This is useful when a transformation pass (e.g LV) wants to emit a remark |
||
796 | /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis |
||
797 | /// remark. The string \p Prepend will be emitted before the original |
||
798 | /// message. |
||
799 | OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend, |
||
800 | const OptimizationRemarkAnalysis &Orig) |
||
801 | : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {} |
||
802 | |||
803 | /// Same as above but \p Inst is used to derive code region and debug |
||
804 | /// location. |
||
805 | OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, |
||
806 | const Instruction *Inst); |
||
807 | |||
808 | /// Same as above but \p F is used to derive code region and debug |
||
809 | /// location. |
||
810 | OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, |
||
811 | const Function *F); |
||
812 | |||
813 | static bool classof(const DiagnosticInfo *DI) { |
||
814 | return DI->getKind() == DK_OptimizationRemarkAnalysis; |
||
815 | } |
||
816 | |||
817 | /// \see DiagnosticInfoOptimizationBase::isEnabled. |
||
818 | bool isEnabled() const override; |
||
819 | |||
820 | static const char *AlwaysPrint; |
||
821 | |||
822 | bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; } |
||
823 | |||
824 | protected: |
||
825 | OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName, |
||
826 | const Function &Fn, const DiagnosticLocation &Loc, |
||
827 | const Twine &Msg) |
||
828 | : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {} |
||
829 | |||
830 | OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName, |
||
831 | StringRef RemarkName, |
||
832 | const DiagnosticLocation &Loc, |
||
833 | const Value *CodeRegion); |
||
834 | |||
835 | private: |
||
836 | /// This is deprecated now and only used by the function API below. |
||
837 | /// \p PassName is the name of the pass emitting this diagnostic. If |
||
838 | /// this name matches the regular expression given in -Rpass-analysis=, then |
||
839 | /// the diagnostic will be emitted. \p Fn is the function where the diagnostic |
||
840 | /// is being emitted. \p Loc is the location information to use in the |
||
841 | /// diagnostic. If line table information is available, the diagnostic will |
||
842 | /// include the source code location. \p Msg is the message to show. Note that |
||
843 | /// this class does not copy this message, so this reference must be valid for |
||
844 | /// the whole life time of the diagnostic. |
||
845 | OptimizationRemarkAnalysis(const char *PassName, const Function &Fn, |
||
846 | const DiagnosticLocation &Loc, const Twine &Msg) |
||
847 | : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark, |
||
848 | PassName, Fn, Loc, Msg) {} |
||
849 | }; |
||
850 | |||
851 | /// Diagnostic information for optimization analysis remarks related to |
||
852 | /// floating-point non-commutativity. |
||
853 | class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis { |
||
854 | void anchor() override; |
||
855 | public: |
||
856 | /// \p PassName is the name of the pass emitting this diagnostic. If this name |
||
857 | /// matches the regular expression given in -Rpass-analysis=, then the |
||
858 | /// diagnostic will be emitted. \p RemarkName is a textual identifier for the |
||
859 | /// remark (single-word, camel-case). \p Loc is the debug location and \p |
||
860 | /// CodeRegion is the region that the optimization operates on (currently only |
||
861 | /// block is supported). The front-end will append its own message related to |
||
862 | /// options that address floating-point non-commutativity. |
||
863 | OptimizationRemarkAnalysisFPCommute(const char *PassName, |
||
864 | StringRef RemarkName, |
||
865 | const DiagnosticLocation &Loc, |
||
866 | const Value *CodeRegion) |
||
867 | : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute, |
||
868 | PassName, RemarkName, Loc, CodeRegion) {} |
||
869 | |||
870 | static bool classof(const DiagnosticInfo *DI) { |
||
871 | return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute; |
||
872 | } |
||
873 | |||
874 | private: |
||
875 | /// This is deprecated now and only used by the function API below. |
||
876 | /// \p PassName is the name of the pass emitting this diagnostic. If |
||
877 | /// this name matches the regular expression given in -Rpass-analysis=, then |
||
878 | /// the diagnostic will be emitted. \p Fn is the function where the diagnostic |
||
879 | /// is being emitted. \p Loc is the location information to use in the |
||
880 | /// diagnostic. If line table information is available, the diagnostic will |
||
881 | /// include the source code location. \p Msg is the message to show. The |
||
882 | /// front-end will append its own message related to options that address |
||
883 | /// floating-point non-commutativity. Note that this class does not copy this |
||
884 | /// message, so this reference must be valid for the whole life time of the |
||
885 | /// diagnostic. |
||
886 | OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn, |
||
887 | const DiagnosticLocation &Loc, |
||
888 | const Twine &Msg) |
||
889 | : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute, |
||
890 | PassName, Fn, Loc, Msg) {} |
||
891 | }; |
||
892 | |||
893 | /// Diagnostic information for optimization analysis remarks related to |
||
894 | /// pointer aliasing. |
||
895 | class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis { |
||
896 | void anchor() override; |
||
897 | public: |
||
898 | /// \p PassName is the name of the pass emitting this diagnostic. If this name |
||
899 | /// matches the regular expression given in -Rpass-analysis=, then the |
||
900 | /// diagnostic will be emitted. \p RemarkName is a textual identifier for the |
||
901 | /// remark (single-word, camel-case). \p Loc is the debug location and \p |
||
902 | /// CodeRegion is the region that the optimization operates on (currently only |
||
903 | /// block is supported). The front-end will append its own message related to |
||
904 | /// options that address pointer aliasing legality. |
||
905 | OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName, |
||
906 | const DiagnosticLocation &Loc, |
||
907 | const Value *CodeRegion) |
||
908 | : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing, |
||
909 | PassName, RemarkName, Loc, CodeRegion) {} |
||
910 | |||
911 | static bool classof(const DiagnosticInfo *DI) { |
||
912 | return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing; |
||
913 | } |
||
914 | |||
915 | private: |
||
916 | /// This is deprecated now and only used by the function API below. |
||
917 | /// \p PassName is the name of the pass emitting this diagnostic. If |
||
918 | /// this name matches the regular expression given in -Rpass-analysis=, then |
||
919 | /// the diagnostic will be emitted. \p Fn is the function where the diagnostic |
||
920 | /// is being emitted. \p Loc is the location information to use in the |
||
921 | /// diagnostic. If line table information is available, the diagnostic will |
||
922 | /// include the source code location. \p Msg is the message to show. The |
||
923 | /// front-end will append its own message related to options that address |
||
924 | /// pointer aliasing legality. Note that this class does not copy this |
||
925 | /// message, so this reference must be valid for the whole life time of the |
||
926 | /// diagnostic. |
||
927 | OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn, |
||
928 | const DiagnosticLocation &Loc, |
||
929 | const Twine &Msg) |
||
930 | : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing, |
||
931 | PassName, Fn, Loc, Msg) {} |
||
932 | }; |
||
933 | |||
934 | /// Diagnostic information for machine IR parser. |
||
935 | // FIXME: Remove this, use DiagnosticInfoSrcMgr instead. |
||
936 | class DiagnosticInfoMIRParser : public DiagnosticInfo { |
||
937 | const SMDiagnostic &Diagnostic; |
||
938 | |||
939 | public: |
||
940 | DiagnosticInfoMIRParser(DiagnosticSeverity Severity, |
||
941 | const SMDiagnostic &Diagnostic) |
||
942 | : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {} |
||
943 | |||
944 | const SMDiagnostic &getDiagnostic() const { return Diagnostic; } |
||
945 | |||
946 | void print(DiagnosticPrinter &DP) const override; |
||
947 | |||
948 | static bool classof(const DiagnosticInfo *DI) { |
||
949 | return DI->getKind() == DK_MIRParser; |
||
950 | } |
||
951 | }; |
||
952 | |||
953 | /// Diagnostic information for ISel fallback path. |
||
954 | class DiagnosticInfoISelFallback : public DiagnosticInfo { |
||
955 | /// The function that is concerned by this diagnostic. |
||
956 | const Function &Fn; |
||
957 | |||
958 | public: |
||
959 | DiagnosticInfoISelFallback(const Function &Fn, |
||
960 | DiagnosticSeverity Severity = DS_Warning) |
||
961 | : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {} |
||
962 | |||
963 | const Function &getFunction() const { return Fn; } |
||
964 | |||
965 | void print(DiagnosticPrinter &DP) const override; |
||
966 | |||
967 | static bool classof(const DiagnosticInfo *DI) { |
||
968 | return DI->getKind() == DK_ISelFallback; |
||
969 | } |
||
970 | }; |
||
971 | |||
972 | // Create wrappers for C Binding types (see CBindingWrapping.h). |
||
973 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef) |
||
974 | |||
975 | /// Diagnostic information for optimization failures. |
||
976 | class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization { |
||
977 | public: |
||
978 | /// \p Fn is the function where the diagnostic is being emitted. \p Loc is |
||
979 | /// the location information to use in the diagnostic. If line table |
||
980 | /// information is available, the diagnostic will include the source code |
||
981 | /// location. \p Msg is the message to show. Note that this class does not |
||
982 | /// copy this message, so this reference must be valid for the whole life time |
||
983 | /// of the diagnostic. |
||
984 | DiagnosticInfoOptimizationFailure(const Function &Fn, |
||
985 | const DiagnosticLocation &Loc, |
||
986 | const Twine &Msg) |
||
987 | : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning, |
||
988 | nullptr, Fn, Loc, Msg) {} |
||
989 | |||
990 | /// \p PassName is the name of the pass emitting this diagnostic. \p |
||
991 | /// RemarkName is a textual identifier for the remark (single-word, |
||
992 | /// camel-case). \p Loc is the debug location and \p CodeRegion is the |
||
993 | /// region that the optimization operates on (currently basic block is |
||
994 | /// supported). |
||
995 | DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName, |
||
996 | const DiagnosticLocation &Loc, |
||
997 | const Value *CodeRegion); |
||
998 | |||
999 | static bool classof(const DiagnosticInfo *DI) { |
||
1000 | return DI->getKind() == DK_OptimizationFailure; |
||
1001 | } |
||
1002 | |||
1003 | /// \see DiagnosticInfoOptimizationBase::isEnabled. |
||
1004 | bool isEnabled() const override; |
||
1005 | }; |
||
1006 | |||
1007 | /// Diagnostic information for unsupported feature in backend. |
||
1008 | class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase { |
||
1009 | private: |
||
1010 | Twine Msg; |
||
1011 | |||
1012 | public: |
||
1013 | /// \p Fn is the function where the diagnostic is being emitted. \p Loc is |
||
1014 | /// the location information to use in the diagnostic. If line table |
||
1015 | /// information is available, the diagnostic will include the source code |
||
1016 | /// location. \p Msg is the message to show. Note that this class does not |
||
1017 | /// copy this message, so this reference must be valid for the whole life time |
||
1018 | /// of the diagnostic. |
||
1019 | DiagnosticInfoUnsupported( |
||
1020 | const Function &Fn, const Twine &Msg, |
||
1021 | const DiagnosticLocation &Loc = DiagnosticLocation(), |
||
1022 | DiagnosticSeverity Severity = DS_Error) |
||
1023 | : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc), |
||
1024 | Msg(Msg) {} |
||
1025 | |||
1026 | static bool classof(const DiagnosticInfo *DI) { |
||
1027 | return DI->getKind() == DK_Unsupported; |
||
1028 | } |
||
1029 | |||
1030 | const Twine &getMessage() const { return Msg; } |
||
1031 | |||
1032 | void print(DiagnosticPrinter &DP) const override; |
||
1033 | }; |
||
1034 | |||
1035 | /// Diagnostic information for MisExpect analysis. |
||
1036 | class DiagnosticInfoMisExpect : public DiagnosticInfoWithLocationBase { |
||
1037 | public: |
||
1038 | DiagnosticInfoMisExpect(const Instruction *Inst, Twine &Msg); |
||
1039 | |||
1040 | /// \see DiagnosticInfo::print. |
||
1041 | void print(DiagnosticPrinter &DP) const override; |
||
1042 | |||
1043 | static bool classof(const DiagnosticInfo *DI) { |
||
1044 | return DI->getKind() == DK_MisExpect; |
||
1045 | } |
||
1046 | |||
1047 | const Twine &getMsg() const { return Msg; } |
||
1048 | |||
1049 | private: |
||
1050 | /// Message to report. |
||
1051 | const Twine &Msg; |
||
1052 | }; |
||
1053 | |||
1054 | static DiagnosticSeverity getDiagnosticSeverity(SourceMgr::DiagKind DK) { |
||
1055 | switch (DK) { |
||
1056 | case llvm::SourceMgr::DK_Error: |
||
1057 | return DS_Error; |
||
1058 | break; |
||
1059 | case llvm::SourceMgr::DK_Warning: |
||
1060 | return DS_Warning; |
||
1061 | break; |
||
1062 | case llvm::SourceMgr::DK_Note: |
||
1063 | return DS_Note; |
||
1064 | break; |
||
1065 | case llvm::SourceMgr::DK_Remark: |
||
1066 | return DS_Remark; |
||
1067 | break; |
||
1068 | } |
||
1069 | llvm_unreachable("unknown SourceMgr::DiagKind"); |
||
1070 | } |
||
1071 | |||
1072 | /// Diagnostic information for SMDiagnostic reporting. |
||
1073 | class DiagnosticInfoSrcMgr : public DiagnosticInfo { |
||
1074 | const SMDiagnostic &Diagnostic; |
||
1075 | StringRef ModName; |
||
1076 | |||
1077 | // For inlineasm !srcloc translation. |
||
1078 | bool InlineAsmDiag; |
||
1079 | unsigned LocCookie; |
||
1080 | |||
1081 | public: |
||
1082 | DiagnosticInfoSrcMgr(const SMDiagnostic &Diagnostic, StringRef ModName, |
||
1083 | bool InlineAsmDiag = true, unsigned LocCookie = 0) |
||
1084 | : DiagnosticInfo(DK_SrcMgr, getDiagnosticSeverity(Diagnostic.getKind())), |
||
1085 | Diagnostic(Diagnostic), ModName(ModName), InlineAsmDiag(InlineAsmDiag), |
||
1086 | LocCookie(LocCookie) {} |
||
1087 | |||
1088 | StringRef getModuleName() const { return ModName; } |
||
1089 | bool isInlineAsmDiag() const { return InlineAsmDiag; } |
||
1090 | const SMDiagnostic &getSMDiag() const { return Diagnostic; } |
||
1091 | unsigned getLocCookie() const { return LocCookie; } |
||
1092 | void print(DiagnosticPrinter &DP) const override; |
||
1093 | |||
1094 | static bool classof(const DiagnosticInfo *DI) { |
||
1095 | return DI->getKind() == DK_SrcMgr; |
||
1096 | } |
||
1097 | }; |
||
1098 | |||
1099 | void diagnoseDontCall(const CallInst &CI); |
||
1100 | |||
1101 | class DiagnosticInfoDontCall : public DiagnosticInfo { |
||
1102 | StringRef CalleeName; |
||
1103 | StringRef Note; |
||
1104 | unsigned LocCookie; |
||
1105 | |||
1106 | public: |
||
1107 | DiagnosticInfoDontCall(StringRef CalleeName, StringRef Note, |
||
1108 | DiagnosticSeverity DS, unsigned LocCookie) |
||
1109 | : DiagnosticInfo(DK_DontCall, DS), CalleeName(CalleeName), Note(Note), |
||
1110 | LocCookie(LocCookie) {} |
||
1111 | StringRef getFunctionName() const { return CalleeName; } |
||
1112 | StringRef getNote() const { return Note; } |
||
1113 | unsigned getLocCookie() const { return LocCookie; } |
||
1114 | void print(DiagnosticPrinter &DP) const override; |
||
1115 | static bool classof(const DiagnosticInfo *DI) { |
||
1116 | return DI->getKind() == DK_DontCall; |
||
1117 | } |
||
1118 | }; |
||
1119 | |||
1120 | } // end namespace llvm |
||
1121 | |||
1122 | #endif // LLVM_IR_DIAGNOSTICINFO_H |