DiagnosticInfo.h 41 KB

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