Line data Source code
1 : //===- 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 :
32 : namespace llvm {
33 :
34 : // Forward declarations.
35 : class DiagnosticPrinter;
36 : class Function;
37 : class Instruction;
38 : class LLVMContext;
39 : class Module;
40 : class SMDiagnostic;
41 :
42 : /// Defines the different supported severity of a diagnostic.
43 : enum 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 : /// Defines the different supported kind of a diagnostic.
53 : /// This enum should be extended with a new ID for each added concrete subclass.
54 : enum 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 : /// 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.
90 : int getNextAvailablePluginDiagnosticKind();
91 :
92 : /// 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).
97 : class DiagnosticInfo {
98 : private:
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 :
104 : public:
105 : DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity)
106 406912 : : Kind(Kind), Severity(Severity) {}
107 :
108 0 : virtual ~DiagnosticInfo() = default;
109 :
110 0 : /* DiagnosticKind */ int getKind() const { return Kind; }
111 0 : 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 :
122 : using DiagnosticHandlerFunction = std::function<void(const DiagnosticInfo &)>;
123 :
124 : /// Diagnostic information for inline asm reporting.
125 : /// This is basically a message and an optional location.
126 : class DiagnosticInfoInlineAsm : public DiagnosticInfo {
127 : private:
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 :
135 : public:
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 84 : : 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 111 : : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
150 111 : 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 0 : unsigned getLocCookie() const { return LocCookie; }
161 0 : 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.
174 : class DiagnosticInfoResourceLimit : public DiagnosticInfo {
175 : private:
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 :
188 : public:
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 31 : : DiagnosticInfo(Kind, Severity), Fn(Fn), ResourceName(ResourceName),
197 29 : ResourceSize(ResourceSize), ResourceLimit(ResourceLimit) {}
198 :
199 0 : const Function &getFunction() const { return Fn; }
200 0 : const char *getResourceName() const { return ResourceName; }
201 0 : uint64_t getResourceSize() const { return ResourceSize; }
202 0 : 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 :
212 : class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit {
213 : public:
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 22 : DK_StackSize, StackLimit) {}
219 :
220 17 : 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.
230 : class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo {
231 : private:
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 :
237 : public:
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 50 : : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M),
243 50 : MetadataVersion(MetadataVersion) {}
244 :
245 0 : const Module &getModule() const { return M; }
246 0 : 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.
257 : class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo {
258 : private:
259 : /// The module that is concerned by this debug metadata version diagnostic.
260 : const Module &M;
261 :
262 : public:
263 : /// \p The module that is concerned by this debug metadata version diagnostic.
264 : DiagnosticInfoIgnoringInvalidDebugMetadata(
265 : const Module &M, DiagnosticSeverity Severity = DS_Warning)
266 50 : : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {}
267 :
268 0 : 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.
279 : class DiagnosticInfoSampleProfile : public DiagnosticInfo {
280 : public:
281 : DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum,
282 : const Twine &Msg,
283 : DiagnosticSeverity Severity = DS_Error)
284 16 : : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
285 16 : LineNum(LineNum), Msg(Msg) {}
286 : DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg,
287 : DiagnosticSeverity Severity = DS_Error)
288 4 : : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
289 4 : Msg(Msg) {}
290 : DiagnosticInfoSampleProfile(const Twine &Msg,
291 : DiagnosticSeverity Severity = DS_Error)
292 0 : : 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 0 : StringRef getFileName() const { return FileName; }
302 0 : unsigned getLineNum() const { return LineNum; }
303 0 : const Twine &getMsg() const { return Msg; }
304 :
305 : private:
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.
318 : class DiagnosticInfoPGOProfile : public DiagnosticInfo {
319 : public:
320 : DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg,
321 : DiagnosticSeverity Severity = DS_Error)
322 2 : : 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 0 : const char *getFileName() const { return FileName; }
332 0 : const Twine &getMsg() const { return Msg; }
333 :
334 : private:
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 :
342 : class DiagnosticLocation {
343 : StringRef Filename;
344 : unsigned Line = 0;
345 : unsigned Column = 0;
346 :
347 : public:
348 18926 : DiagnosticLocation() = default;
349 : DiagnosticLocation(const DebugLoc &DL);
350 : DiagnosticLocation(const DISubprogram *SP);
351 :
352 : bool isValid() const { return !Filename.empty(); }
353 0 : StringRef getFilename() const { return Filename; }
354 0 : unsigned getLine() const { return Line; }
355 0 : unsigned getColumn() const { return Column; }
356 : };
357 :
358 : /// Common features for diagnostics with an associated location.
359 : class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
360 : public:
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 3420630 : : 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 0 : const Function &getFunction() const { return Fn; }
382 841808 : DiagnosticLocation getLocation() const { return Loc; }
383 :
384 : private:
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 : /// Common features for diagnostics dealing with optimization remarks
393 : /// that are used by both IR and MIR passes.
394 1705292 : class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
395 : public:
396 : /// Used to set IsVerbose via the stream interface.
397 : struct setIsVerbose {};
398 :
399 : /// 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 : /// 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 2303306 : 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 5828300 : Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {};
418 : Argument(StringRef Key, int N);
419 : Argument(StringRef Key, float N);
420 : Argument(StringRef Key, long N);
421 : Argument(StringRef Key, long long N);
422 : Argument(StringRef Key, unsigned N);
423 : Argument(StringRef Key, unsigned long N);
424 : Argument(StringRef Key, unsigned long long N);
425 10 : Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
426 : Argument(StringRef Key, DebugLoc dl);
427 : };
428 :
429 : /// \p PassName is the name of the pass emitting this diagnostic. \p
430 : /// RemarkName is a textual identifier for the remark (single-word,
431 : /// camel-case). \p Fn is the function where the diagnostic is being emitted.
432 : /// \p Loc is the location information to use in the diagnostic. If line table
433 : /// information is available, the diagnostic will include the source code
434 : /// location.
435 : DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
436 : enum DiagnosticSeverity Severity,
437 : const char *PassName, StringRef RemarkName,
438 : const Function &Fn,
439 : const DiagnosticLocation &Loc)
440 1710162 : : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
441 3420324 : PassName(PassName), RemarkName(RemarkName) {}
442 :
443 : void insert(StringRef S);
444 : void insert(Argument A);
445 : void insert(setIsVerbose V);
446 : void insert(setExtraArgs EA);
447 :
448 : /// \see DiagnosticInfo::print.
449 : void print(DiagnosticPrinter &DP) const override;
450 :
451 : /// Return true if this optimization remark is enabled by one of
452 : /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed,
453 : /// or -pass-remarks-analysis). Note that this only handles the LLVM
454 : /// flags. We cannot access Clang flags from here (they are handled
455 : /// in BackendConsumer::OptimizationRemarkHandler).
456 : virtual bool isEnabled() const = 0;
457 :
458 0 : StringRef getPassName() const { return PassName; }
459 : std::string getMsg() const;
460 : Optional<uint64_t> getHotness() const { return Hotness; }
461 : void setHotness(Optional<uint64_t> H) { Hotness = H; }
462 :
463 0 : bool isVerbose() const { return IsVerbose; }
464 :
465 : static bool classof(const DiagnosticInfo *DI) {
466 1587864 : return (DI->getKind() >= DK_FirstRemark &&
467 2193446 : DI->getKind() <= DK_LastRemark) ||
468 604502 : (DI->getKind() >= DK_FirstMachineRemark &&
469 : DI->getKind() <= DK_LastMachineRemark);
470 : }
471 :
472 : bool isPassed() const {
473 1130210 : return (getKind() == DK_OptimizationRemark ||
474 : getKind() == DK_MachineOptimizationRemark);
475 : }
476 :
477 : bool isMissed() const {
478 1036536 : return (getKind() == DK_OptimizationRemarkMissed ||
479 : getKind() == DK_MachineOptimizationRemarkMissed);
480 : }
481 :
482 : bool isAnalysis() const {
483 : return (getKind() == DK_OptimizationRemarkAnalysis ||
484 : getKind() == DK_MachineOptimizationRemarkAnalysis);
485 : }
486 :
487 : protected:
488 : /// Name of the pass that triggers this report. If this matches the
489 : /// regular expression given in -Rpass=regexp, then the remark will
490 : /// be emitted.
491 : const char *PassName;
492 :
493 : /// Textual identifier for the remark (single-word, camel-case). Can be used
494 : /// by external tools reading the YAML output file for optimization remarks to
495 : /// identify the remark.
496 : StringRef RemarkName;
497 :
498 : /// If profile information is available, this is the number of times the
499 : /// corresponding code was executed in a profile instrumentation run.
500 : Optional<uint64_t> Hotness;
501 :
502 : /// Arguments collected via the streaming interface.
503 : SmallVector<Argument, 4> Args;
504 :
505 : /// The remark is expected to be noisy.
506 : bool IsVerbose = false;
507 :
508 : /// If positive, the index of the first argument that only appear in
509 : /// the optimization records and not in the remark printed in the compiler
510 : /// output.
511 : int FirstExtraArgIndex = -1;
512 :
513 : friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>;
514 : };
515 :
516 : /// Allow the insertion operator to return the actual remark type rather than a
517 : /// common base class. This allows returning the result of the insertion
518 : /// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah".
519 : template <class RemarkT>
520 : RemarkT &
521 : operator<<(RemarkT &R,
522 : typename std::enable_if<
523 : std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
524 : StringRef>::type S) {
525 2191373 : R.insert(S);
526 : return R;
527 : }
528 :
529 : /// Also allow r-value for the remark to allow insertion into a
530 : /// temporarily-constructed remark.
531 : template <class RemarkT>
532 : RemarkT &
533 : operator<<(RemarkT &&R,
534 : typename std::enable_if<
535 : std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
536 : StringRef>::type S) {
537 109864 : R.insert(S);
538 : return R;
539 : }
540 :
541 : template <class RemarkT>
542 : RemarkT &
543 616812 : operator<<(RemarkT &R,
544 : typename std::enable_if<
545 : std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
546 : DiagnosticInfoOptimizationBase::Argument>::type A) {
547 616812 : R.insert(A);
548 616812 : return R;
549 : }
550 0 :
551 : template <class RemarkT>
552 : RemarkT &
553 271 : operator<<(RemarkT &&R,
554 0 : typename std::enable_if<
555 0 : std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
556 : DiagnosticInfoOptimizationBase::Argument>::type A) {
557 271 : R.insert(A);
558 271 : return R;
559 : }
560 :
561 0 : template <class RemarkT>
562 0 : RemarkT &
563 : operator<<(RemarkT &R,
564 0 : typename std::enable_if<
565 : std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
566 : DiagnosticInfoOptimizationBase::setIsVerbose>::type V) {
567 150 : R.insert(V);
568 0 : return R;
569 0 : }
570 :
571 150 : template <class RemarkT>
572 150 : RemarkT &
573 : operator<<(RemarkT &&R,
574 69 : typename std::enable_if<
575 : std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
576 : DiagnosticInfoOptimizationBase::setIsVerbose>::type V) {
577 : R.insert(V);
578 69 : return R;
579 69 : }
580 :
581 87 : template <class RemarkT>
582 : RemarkT &
583 : operator<<(RemarkT &R,
584 : typename std::enable_if<
585 87 : std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
586 87 : DiagnosticInfoOptimizationBase::setExtraArgs>::type EA) {
587 : R.insert(EA);
588 6 : return R;
589 : }
590 :
591 0 : /// Common features for diagnostics dealing with optimization remarks
592 6 : /// that are used by IR passes.
593 6 : class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
594 : public:
595 0 : /// \p PassName is the name of the pass emitting this diagnostic. \p
596 0 : /// RemarkName is a textual identifier for the remark (single-word,
597 0 : /// camel-case). \p Fn is the function where the diagnostic is being emitted.
598 : /// \p Loc is the location information to use in the diagnostic. If line table
599 : /// information is available, the diagnostic will include the source code
600 : /// location. \p CodeRegion is IR value (currently basic block) that the
601 15 : /// optimization operates on. This is currently used to provide run-time
602 0 : /// hotness information with PGO.
603 : DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
604 : enum DiagnosticSeverity Severity,
605 : const char *PassName, StringRef RemarkName,
606 : const Function &Fn,
607 : const DiagnosticLocation &Loc,
608 : const Value *CodeRegion = nullptr)
609 1304085 : : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
610 : Loc),
611 1304085 : CodeRegion(CodeRegion) {}
612 :
613 : /// This is ctor variant allows a pass to build an optimization remark
614 : /// from an existing remark.
615 : ///
616 : /// This is useful when a transformation pass (e.g LV) wants to emit a remark
617 : /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
618 : /// remark. The string \p Prepend will be emitted before the original
619 : /// message.
620 33 : DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
621 : const DiagnosticInfoIROptimization &Orig)
622 33 : : DiagnosticInfoOptimizationBase(
623 33 : (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
624 : Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
625 66 : CodeRegion(Orig.getCodeRegion()) {
626 33 : *this << Prepend;
627 33 : std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
628 33 : }
629 :
630 : /// Legacy interface.
631 : /// \p PassName is the name of the pass emitting this diagnostic.
632 : /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
633 : /// the location information to use in the diagnostic. If line table
634 : /// information is available, the diagnostic will include the source code
635 : /// location. \p Msg is the message to show. Note that this class does not
636 : /// copy this message, so this reference must be valid for the whole life time
637 : /// of the diagnostic.
638 8 : DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
639 : enum DiagnosticSeverity Severity,
640 : const char *PassName, const Function &Fn,
641 : const DiagnosticLocation &Loc, const Twine &Msg)
642 8 : : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
643 16 : *this << Msg.str();
644 8 : }
645 :
646 0 : const Value *getCodeRegion() const { return CodeRegion; }
647 :
648 : static bool classof(const DiagnosticInfo *DI) {
649 : return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark;
650 : }
651 :
652 : private:
653 : /// The IR value (currently basic block) that the optimization operates on.
654 : /// This is currently used to provide run-time hotness information with PGO.
655 : const Value *CodeRegion;
656 : };
657 :
658 : /// Diagnostic information for applied optimization remarks.
659 : class OptimizationRemark : public DiagnosticInfoIROptimization {
660 : public:
661 : /// \p PassName is the name of the pass emitting this diagnostic. If this name
662 : /// matches the regular expression given in -Rpass=, then the diagnostic will
663 : /// be emitted. \p RemarkName is a textual identifier for the remark (single-
664 : /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the
665 : /// region that the optimization operates on (currently only block is
666 : /// supported).
667 : OptimizationRemark(const char *PassName, StringRef RemarkName,
668 : const DiagnosticLocation &Loc, const Value *CodeRegion);
669 :
670 : /// Same as above, but the debug location and code region are derived from \p
671 : /// Instr.
672 : OptimizationRemark(const char *PassName, StringRef RemarkName,
673 : const Instruction *Inst);
674 :
675 : /// Same as above, but the debug location and code region are derived from \p
676 : /// Func.
677 : OptimizationRemark(const char *PassName, StringRef RemarkName,
678 : const Function *Func);
679 :
680 : static bool classof(const DiagnosticInfo *DI) {
681 : return DI->getKind() == DK_OptimizationRemark;
682 : }
683 :
684 : /// \see DiagnosticInfoOptimizationBase::isEnabled.
685 : bool isEnabled() const override;
686 :
687 : private:
688 : /// This is deprecated now and only used by the function API below.
689 : /// \p PassName is the name of the pass emitting this diagnostic. If
690 : /// this name matches the regular expression given in -Rpass=, then the
691 : /// diagnostic will be emitted. \p Fn is the function where the diagnostic
692 : /// is being emitted. \p Loc is the location information to use in the
693 : /// diagnostic. If line table information is available, the diagnostic
694 87 : /// will include the source code location. \p Msg is the message to show.
695 : /// Note that this class does not copy this message, so this reference
696 : /// must be valid for the whole life time of the diagnostic.
697 : OptimizationRemark(const char *PassName, const Function &Fn,
698 : const DiagnosticLocation &Loc, const Twine &Msg)
699 : : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
700 : Fn, Loc, Msg) {}
701 : };
702 :
703 : /// Diagnostic information for missed-optimization remarks.
704 : class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
705 : public:
706 : /// \p PassName is the name of the pass emitting this diagnostic. If this name
707 : /// matches the regular expression given in -Rpass-missed=, then the
708 : /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
709 : /// remark (single-word, camel-case). \p Loc is the debug location and \p
710 : /// CodeRegion is the region that the optimization operates on (currently only
711 : /// block is supported).
712 : OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
713 : const DiagnosticLocation &Loc,
714 : const Value *CodeRegion);
715 :
716 : /// Same as above but \p Inst is used to derive code region and debug
717 : /// location.
718 : OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
719 : const Instruction *Inst);
720 :
721 : static bool classof(const DiagnosticInfo *DI) {
722 : return DI->getKind() == DK_OptimizationRemarkMissed;
723 : }
724 :
725 : /// \see DiagnosticInfoOptimizationBase::isEnabled.
726 : bool isEnabled() const override;
727 :
728 : private:
729 : /// This is deprecated now and only used by the function API below.
730 : /// \p PassName is the name of the pass emitting this diagnostic. If
731 : /// this name matches the regular expression given in -Rpass-missed=, then the
732 : /// diagnostic will be emitted. \p Fn is the function where the diagnostic
733 : /// is being emitted. \p Loc is the location information to use in the
734 : /// diagnostic. If line table information is available, the diagnostic
735 : /// will include the source code location. \p Msg is the message to show.
736 : /// Note that this class does not copy this message, so this reference
737 : /// must be valid for the whole life time of the diagnostic.
738 : OptimizationRemarkMissed(const char *PassName, const Function &Fn,
739 : const DiagnosticLocation &Loc, const Twine &Msg)
740 : : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
741 : PassName, Fn, Loc, Msg) {}
742 : };
743 :
744 : /// Diagnostic information for optimization analysis remarks.
745 6 : class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
746 : public:
747 : /// \p PassName is the name of the pass emitting this diagnostic. If this name
748 : /// matches the regular expression given in -Rpass-analysis=, then the
749 : /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
750 : /// remark (single-word, camel-case). \p Loc is the debug location and \p
751 : /// CodeRegion is the region that the optimization operates on (currently only
752 : /// block is supported).
753 : OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
754 : const DiagnosticLocation &Loc,
755 : const Value *CodeRegion);
756 :
757 : /// This is ctor variant allows a pass to build an optimization remark
758 : /// from an existing remark.
759 : ///
760 : /// This is useful when a transformation pass (e.g LV) wants to emit a remark
761 : /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
762 : /// remark. The string \p Prepend will be emitted before the original
763 : /// message.
764 : OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
765 : const OptimizationRemarkAnalysis &Orig)
766 : : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
767 :
768 : /// Same as above but \p Inst is used to derive code region and debug
769 : /// location.
770 : OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
771 : const Instruction *Inst);
772 :
773 : static bool classof(const DiagnosticInfo *DI) {
774 0 : return DI->getKind() == DK_OptimizationRemarkAnalysis;
775 : }
776 :
777 : /// \see DiagnosticInfoOptimizationBase::isEnabled.
778 : bool isEnabled() const override;
779 :
780 : static const char *AlwaysPrint;
781 :
782 22232 : bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; }
783 :
784 : protected:
785 : OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
786 : const Function &Fn, const DiagnosticLocation &Loc,
787 : const Twine &Msg)
788 : : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
789 :
790 : OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
791 : StringRef RemarkName,
792 : const DiagnosticLocation &Loc,
793 : const Value *CodeRegion);
794 :
795 : private:
796 : /// This is deprecated now and only used by the function API below.
797 : /// \p PassName is the name of the pass emitting this diagnostic. If
798 : /// this name matches the regular expression given in -Rpass-analysis=, then
799 : /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
800 : /// is being emitted. \p Loc is the location information to use in the
801 : /// diagnostic. If line table information is available, the diagnostic will
802 : /// include the source code location. \p Msg is the message to show. Note that
803 : /// this class does not copy this message, so this reference must be valid for
804 : /// the whole life time of the diagnostic.
805 : OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
806 : const DiagnosticLocation &Loc, const Twine &Msg)
807 : : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
808 : PassName, Fn, Loc, Msg) {}
809 : };
810 :
811 : /// Diagnostic information for optimization analysis remarks related to
812 : /// floating-point non-commutativity.
813 : class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
814 : public:
815 : /// \p PassName is the name of the pass emitting this diagnostic. If this name
816 : /// matches the regular expression given in -Rpass-analysis=, then the
817 : /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
818 : /// remark (single-word, camel-case). \p Loc is the debug location and \p
819 : /// CodeRegion is the region that the optimization operates on (currently only
820 : /// block is supported). The front-end will append its own message related to
821 : /// options that address floating-point non-commutativity.
822 : OptimizationRemarkAnalysisFPCommute(const char *PassName,
823 : StringRef RemarkName,
824 : const DiagnosticLocation &Loc,
825 : const Value *CodeRegion)
826 : : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
827 : PassName, RemarkName, Loc, CodeRegion) {}
828 :
829 : static bool classof(const DiagnosticInfo *DI) {
830 : return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
831 : }
832 :
833 : private:
834 : /// This is deprecated now and only used by the function API below.
835 : /// \p PassName is the name of the pass emitting this diagnostic. If
836 : /// this name matches the regular expression given in -Rpass-analysis=, then
837 : /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
838 : /// is being emitted. \p Loc is the location information to use in the
839 : /// diagnostic. If line table information is available, the diagnostic will
840 : /// include the source code location. \p Msg is the message to show. The
841 : /// front-end will append its own message related to options that address
842 : /// floating-point non-commutativity. Note that this class does not copy this
843 : /// message, so this reference must be valid for the whole life time of the
844 : /// diagnostic.
845 : OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
846 : const DiagnosticLocation &Loc,
847 : const Twine &Msg)
848 : : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
849 : PassName, Fn, Loc, Msg) {}
850 : };
851 :
852 : /// Diagnostic information for optimization analysis remarks related to
853 : /// pointer aliasing.
854 : class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
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 pointer aliasing legality.
863 : OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
864 : const DiagnosticLocation &Loc,
865 : const Value *CodeRegion)
866 : : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
867 : PassName, RemarkName, Loc, CodeRegion) {}
868 :
869 : static bool classof(const DiagnosticInfo *DI) {
870 : return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
871 : }
872 :
873 : private:
874 : /// This is deprecated now and only used by the function API below.
875 : /// \p PassName is the name of the pass emitting this diagnostic. If
876 : /// this name matches the regular expression given in -Rpass-analysis=, then
877 : /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
878 : /// is being emitted. \p Loc is the location information to use in the
879 : /// diagnostic. If line table information is available, the diagnostic will
880 : /// include the source code location. \p Msg is the message to show. The
881 : /// front-end will append its own message related to options that address
882 : /// pointer aliasing legality. Note that this class does not copy this
883 : /// message, so this reference must be valid for the whole life time of the
884 : /// diagnostic.
885 : OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
886 : const DiagnosticLocation &Loc,
887 : const Twine &Msg)
888 : : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
889 : PassName, Fn, Loc, Msg) {}
890 : };
891 :
892 : /// Diagnostic information for machine IR parser.
893 : class DiagnosticInfoMIRParser : public DiagnosticInfo {
894 : const SMDiagnostic &Diagnostic;
895 :
896 : public:
897 : DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
898 : const SMDiagnostic &Diagnostic)
899 120 : : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {}
900 :
901 : const SMDiagnostic &getDiagnostic() const { return Diagnostic; }
902 :
903 : void print(DiagnosticPrinter &DP) const override;
904 :
905 : static bool classof(const DiagnosticInfo *DI) {
906 : return DI->getKind() == DK_MIRParser;
907 : }
908 : };
909 :
910 : /// Diagnostic information for ISel fallback path.
911 : class DiagnosticInfoISelFallback : public DiagnosticInfo {
912 : /// The function that is concerned by this diagnostic.
913 : const Function &Fn;
914 :
915 : public:
916 : DiagnosticInfoISelFallback(const Function &Fn,
917 : DiagnosticSeverity Severity = DS_Warning)
918 103 : : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {}
919 :
920 0 : const Function &getFunction() const { return Fn; }
921 :
922 : void print(DiagnosticPrinter &DP) const override;
923 :
924 : static bool classof(const DiagnosticInfo *DI) {
925 : return DI->getKind() == DK_ISelFallback;
926 : }
927 : };
928 :
929 : // Create wrappers for C Binding types (see CBindingWrapping.h).
930 : DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
931 :
932 : /// Diagnostic information for optimization failures.
933 : class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
934 : public:
935 : /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
936 : /// the location information to use in the diagnostic. If line table
937 : /// information is available, the diagnostic will include the source code
938 : /// location. \p Msg is the message to show. Note that this class does not
939 : /// copy this message, so this reference must be valid for the whole life time
940 : /// of the diagnostic.
941 : DiagnosticInfoOptimizationFailure(const Function &Fn,
942 : const DiagnosticLocation &Loc,
943 : const Twine &Msg)
944 8 : : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
945 8 : nullptr, Fn, Loc, Msg) {}
946 :
947 : /// \p PassName is the name of the pass emitting this diagnostic. \p
948 : /// RemarkName is a textual identifier for the remark (single-word,
949 : /// camel-case). \p Loc is the debug location and \p CodeRegion is the
950 : /// region that the optimization operates on (currently basic block is
951 : /// supported).
952 : DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
953 : const DiagnosticLocation &Loc,
954 : const Value *CodeRegion);
955 :
956 : static bool classof(const DiagnosticInfo *DI) {
957 : return DI->getKind() == DK_OptimizationFailure;
958 : }
959 :
960 : /// \see DiagnosticInfoOptimizationBase::isEnabled.
961 : bool isEnabled() const override;
962 : };
963 :
964 : /// Diagnostic information for unsupported feature in backend.
965 2 : class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
966 : private:
967 : Twine Msg;
968 :
969 : public:
970 : /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
971 : /// the location information to use in the diagnostic. If line table
972 : /// information is available, the diagnostic will include the source code
973 : /// location. \p Msg is the message to show. Note that this class does not
974 : /// copy this message, so this reference must be valid for the whole life time
975 : /// of the diagnostic.
976 : DiagnosticInfoUnsupported(
977 : const Function &Fn, const Twine &Msg,
978 : const DiagnosticLocation &Loc = DiagnosticLocation(),
979 : DiagnosticSeverity Severity = DS_Error)
980 153 : : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
981 153 : Msg(Msg) {}
982 :
983 : static bool classof(const DiagnosticInfo *DI) {
984 : return DI->getKind() == DK_Unsupported;
985 : }
986 :
987 2 : const Twine &getMessage() const { return Msg; }
988 :
989 : void print(DiagnosticPrinter &DP) const override;
990 : };
991 :
992 : namespace yaml {
993 : template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
994 : static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
995 : };
996 : } // namespace yaml
997 :
998 : } // end namespace llvm
999 :
1000 : #endif // LLVM_IR_DIAGNOSTICINFO_H
|