blob: b8fdae2fcadbeb88b05f34dd6171deed3e2ab39c [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
Andrew Scullcdfcccc2018-10-05 20:58:37 +010042/// Defines the different supported severity of a diagnostic.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010043enum 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +010052/// Defines the different supported kind of a diagnostic.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010053/// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +010082/// Get the next available kind ID for a plugin diagnostic.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010083/// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +010092/// This is the base abstract class for diagnostic reporting in
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010093/// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100392/// Common features for diagnostics dealing with optimization remarks
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100393/// that are used by both IR and MIR passes.
394class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
395public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100396 /// Used to set IsVerbose via the stream interface.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100397 struct setIsVerbose {};
398
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100399 /// When an instance of this is inserted into the stream, the arguments
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100400 /// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100405 /// Used in the streaming interface as the general argument type. It
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100406 /// 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);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100417 Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {};
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100418 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 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 : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
441 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 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 bool isVerbose() const { return IsVerbose; }
464
465 static bool classof(const DiagnosticInfo *DI) {
466 return (DI->getKind() >= DK_FirstRemark &&
467 DI->getKind() <= DK_LastRemark) ||
468 (DI->getKind() >= DK_FirstMachineRemark &&
469 DI->getKind() <= DK_LastMachineRemark);
470 }
471
472 bool isPassed() const {
473 return (getKind() == DK_OptimizationRemark ||
474 getKind() == DK_MachineOptimizationRemark);
475 }
476
477 bool isMissed() const {
478 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
487protected:
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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100508 /// If positive, the index of the first argument that only appear in
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100509 /// 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".
519template <class RemarkT>
520RemarkT &
521operator<<(RemarkT &R,
522 typename std::enable_if<
523 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
524 StringRef>::type S) {
525 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.
531template <class RemarkT>
532RemarkT &
533operator<<(RemarkT &&R,
534 typename std::enable_if<
535 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
536 StringRef>::type S) {
537 R.insert(S);
538 return R;
539}
540
541template <class RemarkT>
542RemarkT &
543operator<<(RemarkT &R,
544 typename std::enable_if<
545 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
546 DiagnosticInfoOptimizationBase::Argument>::type A) {
547 R.insert(A);
548 return R;
549}
550
551template <class RemarkT>
552RemarkT &
553operator<<(RemarkT &&R,
554 typename std::enable_if<
555 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
556 DiagnosticInfoOptimizationBase::Argument>::type A) {
557 R.insert(A);
558 return R;
559}
560
561template <class RemarkT>
562RemarkT &
563operator<<(RemarkT &R,
564 typename std::enable_if<
565 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
566 DiagnosticInfoOptimizationBase::setIsVerbose>::type V) {
567 R.insert(V);
568 return R;
569}
570
571template <class RemarkT>
572RemarkT &
573operator<<(RemarkT &&R,
574 typename std::enable_if<
575 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
576 DiagnosticInfoOptimizationBase::setIsVerbose>::type V) {
577 R.insert(V);
578 return R;
579}
580
581template <class RemarkT>
582RemarkT &
583operator<<(RemarkT &R,
584 typename std::enable_if<
585 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
586 DiagnosticInfoOptimizationBase::setExtraArgs>::type EA) {
587 R.insert(EA);
588 return R;
589}
590
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100591/// Common features for diagnostics dealing with optimization remarks
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100592/// that are used by IR passes.
593class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
594public:
595 /// \p PassName is the name of the pass emitting this diagnostic. \p
596 /// RemarkName is a textual identifier for the remark (single-word,
597 /// 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 /// optimization operates on. This is currently used to provide run-time
602 /// 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 : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
610 Loc),
611 CodeRegion(CodeRegion) {}
612
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100613 /// This is ctor variant allows a pass to build an optimization remark
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100614 /// 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 DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
621 const DiagnosticInfoIROptimization &Orig)
622 : DiagnosticInfoOptimizationBase(
623 (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
624 Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
625 CodeRegion(Orig.getCodeRegion()) {
626 *this << Prepend;
627 std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
628 }
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 DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
639 enum DiagnosticSeverity Severity,
640 const char *PassName, const Function &Fn,
641 const DiagnosticLocation &Loc, const Twine &Msg)
642 : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
643 *this << Msg.str();
644 }
645
646 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
652private:
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.
659class OptimizationRemark : public DiagnosticInfoIROptimization {
660public:
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
687private:
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 /// 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.
704class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
705public:
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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100716 /// Same as above but \p Inst is used to derive code region and debug
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100717 /// 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
728private:
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.
745class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
746public:
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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100757 /// This is ctor variant allows a pass to build an optimization remark
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100758 /// 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100768 /// Same as above but \p Inst is used to derive code region and debug
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100769 /// location.
770 OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
771 const Instruction *Inst);
772
773 static bool classof(const DiagnosticInfo *DI) {
774 return DI->getKind() == DK_OptimizationRemarkAnalysis;
775 }
776
777 /// \see DiagnosticInfoOptimizationBase::isEnabled.
778 bool isEnabled() const override;
779
780 static const char *AlwaysPrint;
781
782 bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; }
783
784protected:
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
795private:
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.
813class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
814public:
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
833private:
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.
854class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
855public:
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
873private:
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.
893class DiagnosticInfoMIRParser : public DiagnosticInfo {
894 const SMDiagnostic &Diagnostic;
895
896public:
897 DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
898 const SMDiagnostic &Diagnostic)
899 : 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.
911class DiagnosticInfoISelFallback : public DiagnosticInfo {
912 /// The function that is concerned by this diagnostic.
913 const Function &Fn;
914
915public:
916 DiagnosticInfoISelFallback(const Function &Fn,
917 DiagnosticSeverity Severity = DS_Warning)
918 : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {}
919
920 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).
930DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
931
932/// Diagnostic information for optimization failures.
933class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
934public:
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 : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
945 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.
965class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
966private:
967 Twine Msg;
968
969public:
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 : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
981 Msg(Msg) {}
982
983 static bool classof(const DiagnosticInfo *DI) {
984 return DI->getKind() == DK_Unsupported;
985 }
986
987 const Twine &getMessage() const { return Msg; }
988
989 void print(DiagnosticPrinter &DP) const override;
990};
991
992namespace yaml {
993template <> 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