blob: ab4c692e18b8b1a10da8250068b64a001404dcfc [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/IR/DiagnosticInfo.h - Diagnostic Declaration --------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8//
9// This file declares the different classes involved in low level diagnostics.
10//
11// Diagnostics reporting is still done as part of the LLVMContext.
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_IR_DIAGNOSTICINFO_H
15#define LLVM_IR_DIAGNOSTICINFO_H
16
17#include "llvm-c/Types.h"
18#include "llvm/ADT/Optional.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
22#include "llvm/IR/DebugLoc.h"
23#include "llvm/Support/CBindingWrapping.h"
24#include "llvm/Support/YAMLTraits.h"
25#include <algorithm>
26#include <cstdint>
27#include <functional>
28#include <iterator>
29#include <string>
30
31namespace llvm {
32
33// Forward declarations.
34class DiagnosticPrinter;
35class Function;
36class Instruction;
37class LLVMContext;
38class Module;
39class SMDiagnostic;
40
Andrew Scullcdfcccc2018-10-05 20:58:37 +010041/// Defines the different supported severity of a diagnostic.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010042enum DiagnosticSeverity : char {
43 DS_Error,
44 DS_Warning,
45 DS_Remark,
46 // A note attaches additional information to one of the previous diagnostic
47 // types.
48 DS_Note
49};
50
Andrew Scullcdfcccc2018-10-05 20:58:37 +010051/// Defines the different supported kind of a diagnostic.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010052/// This enum should be extended with a new ID for each added concrete subclass.
53enum DiagnosticKind {
54 DK_InlineAsm,
55 DK_ResourceLimit,
56 DK_StackSize,
57 DK_Linker,
58 DK_DebugMetadataVersion,
59 DK_DebugMetadataInvalid,
60 DK_ISelFallback,
61 DK_SampleProfile,
62 DK_OptimizationRemark,
63 DK_OptimizationRemarkMissed,
64 DK_OptimizationRemarkAnalysis,
65 DK_OptimizationRemarkAnalysisFPCommute,
66 DK_OptimizationRemarkAnalysisAliasing,
67 DK_OptimizationFailure,
68 DK_FirstRemark = DK_OptimizationRemark,
69 DK_LastRemark = DK_OptimizationFailure,
70 DK_MachineOptimizationRemark,
71 DK_MachineOptimizationRemarkMissed,
72 DK_MachineOptimizationRemarkAnalysis,
73 DK_FirstMachineRemark = DK_MachineOptimizationRemark,
74 DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis,
75 DK_MIRParser,
76 DK_PGOProfile,
77 DK_Unsupported,
78 DK_FirstPluginKind
79};
80
Andrew Scullcdfcccc2018-10-05 20:58:37 +010081/// Get the next available kind ID for a plugin diagnostic.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010082/// Each time this function is called, it returns a different number.
83/// Therefore, a plugin that wants to "identify" its own classes
84/// with a dynamic identifier, just have to use this method to get a new ID
85/// and assign it to each of its classes.
86/// The returned ID will be greater than or equal to DK_FirstPluginKind.
87/// Thus, the plugin identifiers will not conflict with the
88/// DiagnosticKind values.
89int getNextAvailablePluginDiagnosticKind();
90
Andrew Scullcdfcccc2018-10-05 20:58:37 +010091/// This is the base abstract class for diagnostic reporting in
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010092/// the backend.
93/// The print method must be overloaded by the subclasses to print a
94/// user-friendly message in the client of the backend (let us call it a
95/// frontend).
96class DiagnosticInfo {
97private:
98 /// Kind defines the kind of report this is about.
99 const /* DiagnosticKind */ int Kind;
100 /// Severity gives the severity of the diagnostic.
101 const DiagnosticSeverity Severity;
102
Andrew Walbran16937d02019-10-22 13:54:20 +0100103 virtual void anchor();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100104public:
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 {
Andrew Walbran16937d02019-10-22 13:54:20 +0100213 virtual void anchor() override;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100214public:
215 DiagnosticInfoStackSize(const Function &Fn, uint64_t StackSize,
216 DiagnosticSeverity Severity = DS_Warning,
217 uint64_t StackLimit = 0)
218 : DiagnosticInfoResourceLimit(Fn, "stack size", StackSize, Severity,
219 DK_StackSize, StackLimit) {}
220
221 uint64_t getStackSize() const { return getResourceSize(); }
222 uint64_t getStackLimit() const { return getResourceLimit(); }
223
224 static bool classof(const DiagnosticInfo *DI) {
225 return DI->getKind() == DK_StackSize;
226 }
227};
228
229/// Diagnostic information for debug metadata version reporting.
230/// This is basically a module and a version.
231class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo {
232private:
233 /// The module that is concerned by this debug metadata version diagnostic.
234 const Module &M;
235 /// The actual metadata version.
236 unsigned MetadataVersion;
237
238public:
239 /// \p The module that is concerned by this debug metadata version diagnostic.
240 /// \p The actual metadata version.
241 DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion,
242 DiagnosticSeverity Severity = DS_Warning)
243 : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M),
244 MetadataVersion(MetadataVersion) {}
245
246 const Module &getModule() const { return M; }
247 unsigned getMetadataVersion() const { return MetadataVersion; }
248
249 /// \see DiagnosticInfo::print.
250 void print(DiagnosticPrinter &DP) const override;
251
252 static bool classof(const DiagnosticInfo *DI) {
253 return DI->getKind() == DK_DebugMetadataVersion;
254 }
255};
256
257/// Diagnostic information for stripping invalid debug metadata.
258class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo {
259private:
260 /// The module that is concerned by this debug metadata version diagnostic.
261 const Module &M;
262
263public:
264 /// \p The module that is concerned by this debug metadata version diagnostic.
265 DiagnosticInfoIgnoringInvalidDebugMetadata(
266 const Module &M, DiagnosticSeverity Severity = DS_Warning)
267 : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {}
268
269 const Module &getModule() const { return M; }
270
271 /// \see DiagnosticInfo::print.
272 void print(DiagnosticPrinter &DP) const override;
273
274 static bool classof(const DiagnosticInfo *DI) {
275 return DI->getKind() == DK_DebugMetadataInvalid;
276 }
277};
278
279/// Diagnostic information for the sample profiler.
280class DiagnosticInfoSampleProfile : public DiagnosticInfo {
281public:
282 DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum,
283 const Twine &Msg,
284 DiagnosticSeverity Severity = DS_Error)
285 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
286 LineNum(LineNum), Msg(Msg) {}
287 DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg,
288 DiagnosticSeverity Severity = DS_Error)
289 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
290 Msg(Msg) {}
291 DiagnosticInfoSampleProfile(const Twine &Msg,
292 DiagnosticSeverity Severity = DS_Error)
293 : DiagnosticInfo(DK_SampleProfile, Severity), Msg(Msg) {}
294
295 /// \see DiagnosticInfo::print.
296 void print(DiagnosticPrinter &DP) const override;
297
298 static bool classof(const DiagnosticInfo *DI) {
299 return DI->getKind() == DK_SampleProfile;
300 }
301
302 StringRef getFileName() const { return FileName; }
303 unsigned getLineNum() const { return LineNum; }
304 const Twine &getMsg() const { return Msg; }
305
306private:
307 /// Name of the input file associated with this diagnostic.
308 StringRef FileName;
309
310 /// Line number where the diagnostic occurred. If 0, no line number will
311 /// be emitted in the message.
312 unsigned LineNum = 0;
313
314 /// Message to report.
315 const Twine &Msg;
316};
317
318/// Diagnostic information for the PGO profiler.
319class DiagnosticInfoPGOProfile : public DiagnosticInfo {
320public:
321 DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg,
322 DiagnosticSeverity Severity = DS_Error)
323 : DiagnosticInfo(DK_PGOProfile, Severity), FileName(FileName), Msg(Msg) {}
324
325 /// \see DiagnosticInfo::print.
326 void print(DiagnosticPrinter &DP) const override;
327
328 static bool classof(const DiagnosticInfo *DI) {
329 return DI->getKind() == DK_PGOProfile;
330 }
331
332 const char *getFileName() const { return FileName; }
333 const Twine &getMsg() const { return Msg; }
334
335private:
336 /// Name of the input file associated with this diagnostic.
337 const char *FileName;
338
339 /// Message to report.
340 const Twine &Msg;
341};
342
343class DiagnosticLocation {
Andrew Walbran16937d02019-10-22 13:54:20 +0100344 DIFile *File = nullptr;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100345 unsigned Line = 0;
346 unsigned Column = 0;
347
348public:
349 DiagnosticLocation() = default;
350 DiagnosticLocation(const DebugLoc &DL);
351 DiagnosticLocation(const DISubprogram *SP);
352
Andrew Walbran16937d02019-10-22 13:54:20 +0100353 bool isValid() const { return File; }
354 /// Return the full path to the file.
355 std::string getAbsolutePath() const;
356 /// Return the file name relative to the compilation directory.
357 StringRef getRelativePath() const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100358 unsigned getLine() const { return Line; }
359 unsigned getColumn() const { return Column; }
360};
361
362/// Common features for diagnostics with an associated location.
363class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
Andrew Walbran16937d02019-10-22 13:54:20 +0100364 virtual void anchor() override;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100365public:
366 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
367 /// the location information to use in the diagnostic.
368 DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind,
369 enum DiagnosticSeverity Severity,
370 const Function &Fn,
371 const DiagnosticLocation &Loc)
372 : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {}
373
374 /// Return true if location information is available for this diagnostic.
375 bool isLocationAvailable() const { return Loc.isValid(); }
376
377 /// Return a string with the location information for this diagnostic
378 /// in the format "file:line:col". If location information is not available,
379 /// it returns "<unknown>:0:0".
380 const std::string getLocationStr() const;
381
382 /// Return location information for this diagnostic in three parts:
Andrew Walbran16937d02019-10-22 13:54:20 +0100383 /// the relative source file path, line number and column.
384 void getLocation(StringRef &RelativePath, unsigned &Line,
385 unsigned &Column) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100386
Andrew Walbran16937d02019-10-22 13:54:20 +0100387 /// Return the absolute path tot the file.
388 std::string getAbsolutePath() const;
389
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100390 const Function &getFunction() const { return Fn; }
391 DiagnosticLocation getLocation() const { return Loc; }
392
393private:
394 /// Function where this diagnostic is triggered.
395 const Function &Fn;
396
397 /// Debug location where this diagnostic is triggered.
398 DiagnosticLocation Loc;
399};
400
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100401/// Common features for diagnostics dealing with optimization remarks
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100402/// that are used by both IR and MIR passes.
403class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
404public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100405 /// Used to set IsVerbose via the stream interface.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100406 struct setIsVerbose {};
407
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100408 /// When an instance of this is inserted into the stream, the arguments
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100409 /// following will not appear in the remark printed in the compiler output
410 /// (-Rpass) but only in the optimization record file
411 /// (-fsave-optimization-record).
412 struct setExtraArgs {};
413
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100414 /// Used in the streaming interface as the general argument type. It
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100415 /// internally converts everything into a key-value pair.
416 struct Argument {
417 std::string Key;
418 std::string Val;
419 // If set, the debug location corresponding to the value.
420 DiagnosticLocation Loc;
421
422 explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
423 Argument(StringRef Key, const Value *V);
424 Argument(StringRef Key, const Type *T);
425 Argument(StringRef Key, StringRef S);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100426 Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {};
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100427 Argument(StringRef Key, int N);
428 Argument(StringRef Key, float N);
429 Argument(StringRef Key, long N);
430 Argument(StringRef Key, long long N);
431 Argument(StringRef Key, unsigned N);
432 Argument(StringRef Key, unsigned long N);
433 Argument(StringRef Key, unsigned long long N);
434 Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
435 Argument(StringRef Key, DebugLoc dl);
436 };
437
438 /// \p PassName is the name of the pass emitting this diagnostic. \p
439 /// RemarkName is a textual identifier for the remark (single-word,
440 /// camel-case). \p Fn is the function where the diagnostic is being emitted.
441 /// \p Loc is the location information to use in the diagnostic. If line table
442 /// information is available, the diagnostic will include the source code
443 /// location.
444 DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
445 enum DiagnosticSeverity Severity,
446 const char *PassName, StringRef RemarkName,
447 const Function &Fn,
448 const DiagnosticLocation &Loc)
449 : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
450 PassName(PassName), RemarkName(RemarkName) {}
451
452 void insert(StringRef S);
453 void insert(Argument A);
454 void insert(setIsVerbose V);
455 void insert(setExtraArgs EA);
456
457 /// \see DiagnosticInfo::print.
458 void print(DiagnosticPrinter &DP) const override;
459
460 /// Return true if this optimization remark is enabled by one of
461 /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed,
462 /// or -pass-remarks-analysis). Note that this only handles the LLVM
463 /// flags. We cannot access Clang flags from here (they are handled
464 /// in BackendConsumer::OptimizationRemarkHandler).
465 virtual bool isEnabled() const = 0;
466
467 StringRef getPassName() const { return PassName; }
468 std::string getMsg() const;
469 Optional<uint64_t> getHotness() const { return Hotness; }
470 void setHotness(Optional<uint64_t> H) { Hotness = H; }
471
472 bool isVerbose() const { return IsVerbose; }
473
474 static bool classof(const DiagnosticInfo *DI) {
475 return (DI->getKind() >= DK_FirstRemark &&
476 DI->getKind() <= DK_LastRemark) ||
477 (DI->getKind() >= DK_FirstMachineRemark &&
478 DI->getKind() <= DK_LastMachineRemark);
479 }
480
481 bool isPassed() const {
482 return (getKind() == DK_OptimizationRemark ||
483 getKind() == DK_MachineOptimizationRemark);
484 }
485
486 bool isMissed() const {
487 return (getKind() == DK_OptimizationRemarkMissed ||
488 getKind() == DK_MachineOptimizationRemarkMissed);
489 }
490
491 bool isAnalysis() const {
492 return (getKind() == DK_OptimizationRemarkAnalysis ||
493 getKind() == DK_MachineOptimizationRemarkAnalysis);
494 }
495
496protected:
497 /// Name of the pass that triggers this report. If this matches the
498 /// regular expression given in -Rpass=regexp, then the remark will
499 /// be emitted.
500 const char *PassName;
501
502 /// Textual identifier for the remark (single-word, camel-case). Can be used
503 /// by external tools reading the YAML output file for optimization remarks to
504 /// identify the remark.
505 StringRef RemarkName;
506
507 /// If profile information is available, this is the number of times the
508 /// corresponding code was executed in a profile instrumentation run.
509 Optional<uint64_t> Hotness;
510
511 /// Arguments collected via the streaming interface.
512 SmallVector<Argument, 4> Args;
513
514 /// The remark is expected to be noisy.
515 bool IsVerbose = false;
516
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100517 /// If positive, the index of the first argument that only appear in
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100518 /// the optimization records and not in the remark printed in the compiler
519 /// output.
520 int FirstExtraArgIndex = -1;
521
522 friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>;
523};
524
525/// Allow the insertion operator to return the actual remark type rather than a
526/// common base class. This allows returning the result of the insertion
527/// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah".
528template <class RemarkT>
529RemarkT &
530operator<<(RemarkT &R,
531 typename std::enable_if<
532 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
533 StringRef>::type S) {
534 R.insert(S);
535 return R;
536}
537
538/// Also allow r-value for the remark to allow insertion into a
539/// temporarily-constructed remark.
540template <class RemarkT>
541RemarkT &
542operator<<(RemarkT &&R,
543 typename std::enable_if<
544 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
545 StringRef>::type S) {
546 R.insert(S);
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::Argument>::type A) {
566 R.insert(A);
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::setIsVerbose>::type V) {
586 R.insert(V);
587 return R;
588}
589
590template <class RemarkT>
591RemarkT &
592operator<<(RemarkT &R,
593 typename std::enable_if<
594 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
595 DiagnosticInfoOptimizationBase::setExtraArgs>::type EA) {
596 R.insert(EA);
597 return R;
598}
599
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100600/// Common features for diagnostics dealing with optimization remarks
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100601/// that are used by IR passes.
602class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
Andrew Walbran16937d02019-10-22 13:54:20 +0100603 virtual void anchor() override;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100604public:
605 /// \p PassName is the name of the pass emitting this diagnostic. \p
606 /// RemarkName is a textual identifier for the remark (single-word,
607 /// camel-case). \p Fn is the function where the diagnostic is being emitted.
608 /// \p Loc is the location information to use in the diagnostic. If line table
609 /// information is available, the diagnostic will include the source code
610 /// location. \p CodeRegion is IR value (currently basic block) that the
611 /// optimization operates on. This is currently used to provide run-time
612 /// hotness information with PGO.
613 DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
614 enum DiagnosticSeverity Severity,
615 const char *PassName, StringRef RemarkName,
616 const Function &Fn,
617 const DiagnosticLocation &Loc,
618 const Value *CodeRegion = nullptr)
619 : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
620 Loc),
621 CodeRegion(CodeRegion) {}
622
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100623 /// This is ctor variant allows a pass to build an optimization remark
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100624 /// from an existing remark.
625 ///
626 /// This is useful when a transformation pass (e.g LV) wants to emit a remark
627 /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
628 /// remark. The string \p Prepend will be emitted before the original
629 /// message.
630 DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
631 const DiagnosticInfoIROptimization &Orig)
632 : DiagnosticInfoOptimizationBase(
633 (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
634 Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
635 CodeRegion(Orig.getCodeRegion()) {
636 *this << Prepend;
637 std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
638 }
639
640 /// Legacy interface.
641 /// \p PassName is the name of the pass emitting this diagnostic.
642 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
643 /// the location information to use in the diagnostic. If line table
644 /// information is available, the diagnostic will include the source code
645 /// location. \p Msg is the message to show. Note that this class does not
646 /// copy this message, so this reference must be valid for the whole life time
647 /// of the diagnostic.
648 DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
649 enum DiagnosticSeverity Severity,
650 const char *PassName, const Function &Fn,
651 const DiagnosticLocation &Loc, const Twine &Msg)
652 : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
653 *this << Msg.str();
654 }
655
656 const Value *getCodeRegion() const { return CodeRegion; }
657
658 static bool classof(const DiagnosticInfo *DI) {
659 return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark;
660 }
661
662private:
663 /// The IR value (currently basic block) that the optimization operates on.
664 /// This is currently used to provide run-time hotness information with PGO.
665 const Value *CodeRegion;
666};
667
668/// Diagnostic information for applied optimization remarks.
669class OptimizationRemark : public DiagnosticInfoIROptimization {
670public:
671 /// \p PassName is the name of the pass emitting this diagnostic. If this name
672 /// matches the regular expression given in -Rpass=, then the diagnostic will
673 /// be emitted. \p RemarkName is a textual identifier for the remark (single-
674 /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the
675 /// region that the optimization operates on (currently only block is
676 /// supported).
677 OptimizationRemark(const char *PassName, StringRef RemarkName,
678 const DiagnosticLocation &Loc, const Value *CodeRegion);
679
680 /// Same as above, but the debug location and code region are derived from \p
681 /// Instr.
682 OptimizationRemark(const char *PassName, StringRef RemarkName,
683 const Instruction *Inst);
684
685 /// Same as above, but the debug location and code region are derived from \p
686 /// Func.
687 OptimizationRemark(const char *PassName, StringRef RemarkName,
688 const Function *Func);
689
690 static bool classof(const DiagnosticInfo *DI) {
691 return DI->getKind() == DK_OptimizationRemark;
692 }
693
694 /// \see DiagnosticInfoOptimizationBase::isEnabled.
695 bool isEnabled() const override;
696
697private:
698 /// This is deprecated now and only used by the function API below.
699 /// \p PassName is the name of the pass emitting this diagnostic. If
700 /// this name matches the regular expression given in -Rpass=, then the
701 /// diagnostic will be emitted. \p Fn is the function where the diagnostic
702 /// is being emitted. \p Loc is the location information to use in the
703 /// diagnostic. If line table information is available, the diagnostic
704 /// will include the source code location. \p Msg is the message to show.
705 /// Note that this class does not copy this message, so this reference
706 /// must be valid for the whole life time of the diagnostic.
707 OptimizationRemark(const char *PassName, const Function &Fn,
708 const DiagnosticLocation &Loc, const Twine &Msg)
709 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
710 Fn, Loc, Msg) {}
711};
712
713/// Diagnostic information for missed-optimization remarks.
714class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
715public:
716 /// \p PassName is the name of the pass emitting this diagnostic. If this name
717 /// matches the regular expression given in -Rpass-missed=, then the
718 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
719 /// remark (single-word, camel-case). \p Loc is the debug location and \p
720 /// CodeRegion is the region that the optimization operates on (currently only
721 /// block is supported).
722 OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
723 const DiagnosticLocation &Loc,
724 const Value *CodeRegion);
725
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100726 /// Same as above but \p Inst is used to derive code region and debug
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100727 /// location.
728 OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
729 const Instruction *Inst);
730
731 static bool classof(const DiagnosticInfo *DI) {
732 return DI->getKind() == DK_OptimizationRemarkMissed;
733 }
734
735 /// \see DiagnosticInfoOptimizationBase::isEnabled.
736 bool isEnabled() const override;
737
738private:
739 /// This is deprecated now and only used by the function API below.
740 /// \p PassName is the name of the pass emitting this diagnostic. If
741 /// this name matches the regular expression given in -Rpass-missed=, then the
742 /// diagnostic will be emitted. \p Fn is the function where the diagnostic
743 /// is being emitted. \p Loc is the location information to use in the
744 /// diagnostic. If line table information is available, the diagnostic
745 /// will include the source code location. \p Msg is the message to show.
746 /// Note that this class does not copy this message, so this reference
747 /// must be valid for the whole life time of the diagnostic.
748 OptimizationRemarkMissed(const char *PassName, const Function &Fn,
749 const DiagnosticLocation &Loc, const Twine &Msg)
750 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
751 PassName, Fn, Loc, Msg) {}
752};
753
754/// Diagnostic information for optimization analysis remarks.
755class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
756public:
757 /// \p PassName is the name of the pass emitting this diagnostic. If this name
758 /// matches the regular expression given in -Rpass-analysis=, then the
759 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
760 /// remark (single-word, camel-case). \p Loc is the debug location and \p
761 /// CodeRegion is the region that the optimization operates on (currently only
762 /// block is supported).
763 OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
764 const DiagnosticLocation &Loc,
765 const Value *CodeRegion);
766
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100767 /// This is ctor variant allows a pass to build an optimization remark
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100768 /// from an existing remark.
769 ///
770 /// This is useful when a transformation pass (e.g LV) wants to emit a remark
771 /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
772 /// remark. The string \p Prepend will be emitted before the original
773 /// message.
774 OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
775 const OptimizationRemarkAnalysis &Orig)
776 : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
777
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100778 /// Same as above but \p Inst is used to derive code region and debug
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100779 /// location.
780 OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
781 const Instruction *Inst);
782
783 static bool classof(const DiagnosticInfo *DI) {
784 return DI->getKind() == DK_OptimizationRemarkAnalysis;
785 }
786
787 /// \see DiagnosticInfoOptimizationBase::isEnabled.
788 bool isEnabled() const override;
789
790 static const char *AlwaysPrint;
791
792 bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; }
793
794protected:
795 OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
796 const Function &Fn, const DiagnosticLocation &Loc,
797 const Twine &Msg)
798 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
799
800 OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
801 StringRef RemarkName,
802 const DiagnosticLocation &Loc,
803 const Value *CodeRegion);
804
805private:
806 /// This is deprecated now and only used by the function API below.
807 /// \p PassName is the name of the pass emitting this diagnostic. If
808 /// this name matches the regular expression given in -Rpass-analysis=, then
809 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
810 /// is being emitted. \p Loc is the location information to use in the
811 /// diagnostic. If line table information is available, the diagnostic will
812 /// include the source code location. \p Msg is the message to show. Note that
813 /// this class does not copy this message, so this reference must be valid for
814 /// the whole life time of the diagnostic.
815 OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
816 const DiagnosticLocation &Loc, const Twine &Msg)
817 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
818 PassName, Fn, Loc, Msg) {}
819};
820
821/// Diagnostic information for optimization analysis remarks related to
822/// floating-point non-commutativity.
823class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
Andrew Walbran16937d02019-10-22 13:54:20 +0100824 virtual void anchor();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100825public:
826 /// \p PassName is the name of the pass emitting this diagnostic. If this name
827 /// matches the regular expression given in -Rpass-analysis=, then the
828 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
829 /// remark (single-word, camel-case). \p Loc is the debug location and \p
830 /// CodeRegion is the region that the optimization operates on (currently only
831 /// block is supported). The front-end will append its own message related to
832 /// options that address floating-point non-commutativity.
833 OptimizationRemarkAnalysisFPCommute(const char *PassName,
834 StringRef RemarkName,
835 const DiagnosticLocation &Loc,
836 const Value *CodeRegion)
837 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
838 PassName, RemarkName, Loc, CodeRegion) {}
839
840 static bool classof(const DiagnosticInfo *DI) {
841 return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
842 }
843
844private:
845 /// This is deprecated now and only used by the function API below.
846 /// \p PassName is the name of the pass emitting this diagnostic. If
847 /// this name matches the regular expression given in -Rpass-analysis=, then
848 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
849 /// is being emitted. \p Loc is the location information to use in the
850 /// diagnostic. If line table information is available, the diagnostic will
851 /// include the source code location. \p Msg is the message to show. The
852 /// front-end will append its own message related to options that address
853 /// floating-point non-commutativity. Note that this class does not copy this
854 /// message, so this reference must be valid for the whole life time of the
855 /// diagnostic.
856 OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
857 const DiagnosticLocation &Loc,
858 const Twine &Msg)
859 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
860 PassName, Fn, Loc, Msg) {}
861};
862
863/// Diagnostic information for optimization analysis remarks related to
864/// pointer aliasing.
865class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
Andrew Walbran16937d02019-10-22 13:54:20 +0100866 virtual void anchor();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100867public:
868 /// \p PassName is the name of the pass emitting this diagnostic. If this name
869 /// matches the regular expression given in -Rpass-analysis=, then the
870 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
871 /// remark (single-word, camel-case). \p Loc is the debug location and \p
872 /// CodeRegion is the region that the optimization operates on (currently only
873 /// block is supported). The front-end will append its own message related to
874 /// options that address pointer aliasing legality.
875 OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
876 const DiagnosticLocation &Loc,
877 const Value *CodeRegion)
878 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
879 PassName, RemarkName, Loc, CodeRegion) {}
880
881 static bool classof(const DiagnosticInfo *DI) {
882 return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
883 }
884
885private:
886 /// This is deprecated now and only used by the function API below.
887 /// \p PassName is the name of the pass emitting this diagnostic. If
888 /// this name matches the regular expression given in -Rpass-analysis=, then
889 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
890 /// is being emitted. \p Loc is the location information to use in the
891 /// diagnostic. If line table information is available, the diagnostic will
892 /// include the source code location. \p Msg is the message to show. The
893 /// front-end will append its own message related to options that address
894 /// pointer aliasing legality. Note that this class does not copy this
895 /// message, so this reference must be valid for the whole life time of the
896 /// diagnostic.
897 OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
898 const DiagnosticLocation &Loc,
899 const Twine &Msg)
900 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
901 PassName, Fn, Loc, Msg) {}
902};
903
904/// Diagnostic information for machine IR parser.
905class DiagnosticInfoMIRParser : public DiagnosticInfo {
906 const SMDiagnostic &Diagnostic;
907
908public:
909 DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
910 const SMDiagnostic &Diagnostic)
911 : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {}
912
913 const SMDiagnostic &getDiagnostic() const { return Diagnostic; }
914
915 void print(DiagnosticPrinter &DP) const override;
916
917 static bool classof(const DiagnosticInfo *DI) {
918 return DI->getKind() == DK_MIRParser;
919 }
920};
921
922/// Diagnostic information for ISel fallback path.
923class DiagnosticInfoISelFallback : public DiagnosticInfo {
924 /// The function that is concerned by this diagnostic.
925 const Function &Fn;
926
927public:
928 DiagnosticInfoISelFallback(const Function &Fn,
929 DiagnosticSeverity Severity = DS_Warning)
930 : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {}
931
932 const Function &getFunction() const { return Fn; }
933
934 void print(DiagnosticPrinter &DP) const override;
935
936 static bool classof(const DiagnosticInfo *DI) {
937 return DI->getKind() == DK_ISelFallback;
938 }
939};
940
941// Create wrappers for C Binding types (see CBindingWrapping.h).
942DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
943
944/// Diagnostic information for optimization failures.
945class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
946public:
947 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
948 /// the location information to use in the diagnostic. If line table
949 /// information is available, the diagnostic will include the source code
950 /// location. \p Msg is the message to show. Note that this class does not
951 /// copy this message, so this reference must be valid for the whole life time
952 /// of the diagnostic.
953 DiagnosticInfoOptimizationFailure(const Function &Fn,
954 const DiagnosticLocation &Loc,
955 const Twine &Msg)
956 : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
957 nullptr, Fn, Loc, Msg) {}
958
959 /// \p PassName is the name of the pass emitting this diagnostic. \p
960 /// RemarkName is a textual identifier for the remark (single-word,
961 /// camel-case). \p Loc is the debug location and \p CodeRegion is the
962 /// region that the optimization operates on (currently basic block is
963 /// supported).
964 DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
965 const DiagnosticLocation &Loc,
966 const Value *CodeRegion);
967
968 static bool classof(const DiagnosticInfo *DI) {
969 return DI->getKind() == DK_OptimizationFailure;
970 }
971
972 /// \see DiagnosticInfoOptimizationBase::isEnabled.
973 bool isEnabled() const override;
974};
975
976/// Diagnostic information for unsupported feature in backend.
977class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
978private:
979 Twine Msg;
980
981public:
982 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
983 /// the location information to use in the diagnostic. If line table
984 /// information is available, the diagnostic will include the source code
985 /// location. \p Msg is the message to show. Note that this class does not
986 /// copy this message, so this reference must be valid for the whole life time
987 /// of the diagnostic.
988 DiagnosticInfoUnsupported(
989 const Function &Fn, const Twine &Msg,
990 const DiagnosticLocation &Loc = DiagnosticLocation(),
991 DiagnosticSeverity Severity = DS_Error)
992 : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
993 Msg(Msg) {}
994
995 static bool classof(const DiagnosticInfo *DI) {
996 return DI->getKind() == DK_Unsupported;
997 }
998
999 const Twine &getMessage() const { return Msg; }
1000
1001 void print(DiagnosticPrinter &DP) const override;
1002};
1003
1004namespace yaml {
1005template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
1006 static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
1007};
1008} // namespace yaml
1009
1010} // end namespace llvm
1011
1012#endif // LLVM_IR_DIAGNOSTICINFO_H