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