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 | , |
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 | , |
71 | , |
72 | , |
73 | , |
74 | , |
75 | DK_OptimizationFailure, |
76 | = DK_OptimizationRemark, |
77 | = DK_OptimizationFailure, |
78 | , |
79 | , |
80 | , |
81 | = DK_MachineOptimizationRemark, |
82 | = 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 {}; |
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 , |
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 (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 () 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 ; |
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 = -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 | (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 , |
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(first: Orig.Args.begin(), last: Orig.Args.end(), result: std::back_inserter(x&: 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 : 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 | (const char *PassName, StringRef , |
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 | (const char *PassName, StringRef , |
703 | const Instruction *Inst); |
704 | |
705 | /// Same as above, but the debug location and code region are derived from \p |
706 | /// Func. |
707 | (const char *PassName, StringRef , |
708 | const Function *Func); |
709 | |
710 | static bool (const DiagnosticInfo *DI) { |
711 | return DI->getKind() == DK_OptimizationRemark; |
712 | } |
713 | |
714 | /// \see DiagnosticInfoOptimizationBase::isEnabled. |
715 | bool () 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 | (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 : 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 | (const char *PassName, StringRef , |
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 | (const char *PassName, StringRef , |
749 | const Instruction *Inst); |
750 | |
751 | /// Same as above but \p F is used to derive code region and debug |
752 | /// location. |
753 | (const char *PassName, StringRef , |
754 | const Function *F); |
755 | |
756 | static bool (const DiagnosticInfo *DI) { |
757 | return DI->getKind() == DK_OptimizationRemarkMissed; |
758 | } |
759 | |
760 | /// \see DiagnosticInfoOptimizationBase::isEnabled. |
761 | bool () 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 | (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 : 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 | (const char *PassName, StringRef , |
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 | (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 | (const char *PassName, StringRef , |
806 | const Instruction *Inst); |
807 | |
808 | /// Same as above but \p F is used to derive code region and debug |
809 | /// location. |
810 | (const char *PassName, StringRef , |
811 | const Function *F); |
812 | |
813 | static bool (const DiagnosticInfo *DI) { |
814 | return DI->getKind() == DK_OptimizationRemarkAnalysis; |
815 | } |
816 | |
817 | /// \see DiagnosticInfoOptimizationBase::isEnabled. |
818 | bool () const override; |
819 | |
820 | static const char *; |
821 | |
822 | bool () const { return getPassName() == AlwaysPrint; } |
823 | |
824 | protected: |
825 | (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 | (enum DiagnosticKind Kind, const char *PassName, |
831 | StringRef , |
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 | (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 : public OptimizationRemarkAnalysis { |
854 | void () 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 | (const char *PassName, |
864 | StringRef , |
865 | const DiagnosticLocation &Loc, |
866 | const Value *CodeRegion) |
867 | : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute, |
868 | PassName, RemarkName, Loc, CodeRegion) {} |
869 | |
870 | static bool (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 | (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 : public OptimizationRemarkAnalysis { |
896 | void () 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 | (const char *PassName, StringRef , |
906 | const DiagnosticLocation &Loc, |
907 | const Value *CodeRegion) |
908 | : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing, |
909 | PassName, RemarkName, Loc, CodeRegion) {} |
910 | |
911 | static bool (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 | (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 , |
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(DK: 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 |
1123 | |