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