xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Remarks/Remark.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- llvm/Remarks/Remark.h - The remark type -----------------*- C++/-*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines an abstraction for handling remarks.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_REMARKS_REMARK_H
140b57cec5SDimitry Andric #define LLVM_REMARKS_REMARK_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm-c/Remarks.h"
175ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
190b57cec5SDimitry Andric #include "llvm/Support/CBindingWrapping.h"
20*06c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h"
21bdd1243dSDimitry Andric #include <optional>
220b57cec5SDimitry Andric #include <string>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric namespace remarks {
260b57cec5SDimitry Andric 
278bcb0991SDimitry Andric /// The current version of the remark entry.
288bcb0991SDimitry Andric constexpr uint64_t CurrentRemarkVersion = 0;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric /// The debug location used to track a remark back to the source file.
310b57cec5SDimitry Andric struct RemarkLocation {
320b57cec5SDimitry Andric   /// Absolute path of the source file corresponding to this remark.
330b57cec5SDimitry Andric   StringRef SourceFilePath;
34480093f4SDimitry Andric   unsigned SourceLine = 0;
35480093f4SDimitry Andric   unsigned SourceColumn = 0;
36*06c3fb27SDimitry Andric 
37*06c3fb27SDimitry Andric   /// Implement operator<< on RemarkLocation.
38*06c3fb27SDimitry Andric   void print(raw_ostream &OS) const;
390b57cec5SDimitry Andric };
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric // Create wrappers for C Binding types (see CBindingWrapping.h).
420b57cec5SDimitry Andric DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RemarkLocation, LLVMRemarkDebugLocRef)
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric /// A key-value pair with a debug location that is used to display the remarks
450b57cec5SDimitry Andric /// at the right place in the source.
460b57cec5SDimitry Andric struct Argument {
470b57cec5SDimitry Andric   StringRef Key;
480b57cec5SDimitry Andric   // FIXME: We might want to be able to store other types than strings here.
490b57cec5SDimitry Andric   StringRef Val;
500b57cec5SDimitry Andric   // If set, the debug location corresponding to the value.
51bdd1243dSDimitry Andric   std::optional<RemarkLocation> Loc;
52*06c3fb27SDimitry Andric 
53*06c3fb27SDimitry Andric   /// Implement operator<< on Argument.
54*06c3fb27SDimitry Andric   void print(raw_ostream &OS) const;
550b57cec5SDimitry Andric };
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric // Create wrappers for C Binding types (see CBindingWrapping.h).
580b57cec5SDimitry Andric DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Argument, LLVMRemarkArgRef)
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric /// The type of the remark.
610b57cec5SDimitry Andric enum class Type {
620b57cec5SDimitry Andric   Unknown,
630b57cec5SDimitry Andric   Passed,
640b57cec5SDimitry Andric   Missed,
650b57cec5SDimitry Andric   Analysis,
660b57cec5SDimitry Andric   AnalysisFPCommute,
670b57cec5SDimitry Andric   AnalysisAliasing,
680b57cec5SDimitry Andric   Failure,
698bcb0991SDimitry Andric   First = Unknown,
708bcb0991SDimitry Andric   Last = Failure
710b57cec5SDimitry Andric };
720b57cec5SDimitry Andric 
73*06c3fb27SDimitry Andric inline StringRef typeToStr(Type Ty) {
74*06c3fb27SDimitry Andric   switch (Ty) {
75*06c3fb27SDimitry Andric   case Type::Unknown:
76*06c3fb27SDimitry Andric     return "Unknown";
77*06c3fb27SDimitry Andric   case Type::Missed:
78*06c3fb27SDimitry Andric     return "Missed";
79*06c3fb27SDimitry Andric   case Type::Passed:
80*06c3fb27SDimitry Andric     return "Passed";
81*06c3fb27SDimitry Andric   case Type::Analysis:
82*06c3fb27SDimitry Andric     return "Analysis";
83*06c3fb27SDimitry Andric   case Type::AnalysisFPCommute:
84*06c3fb27SDimitry Andric     return "AnalysisFPCommute";
85*06c3fb27SDimitry Andric   case Type::AnalysisAliasing:
86*06c3fb27SDimitry Andric     return "AnalysisAliasing";
87*06c3fb27SDimitry Andric   default:
88*06c3fb27SDimitry Andric     return "Failure";
89*06c3fb27SDimitry Andric   }
90*06c3fb27SDimitry Andric }
91*06c3fb27SDimitry Andric 
920b57cec5SDimitry Andric /// A remark type used for both emission and parsing.
930b57cec5SDimitry Andric struct Remark {
940b57cec5SDimitry Andric   /// The type of the remark.
950b57cec5SDimitry Andric   Type RemarkType = Type::Unknown;
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   /// Name of the pass that triggers the emission of this remark.
980b57cec5SDimitry Andric   StringRef PassName;
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   /// Textual identifier for the remark (single-word, camel-case). Can be used
1010b57cec5SDimitry Andric   /// by external tools reading the output file for remarks to identify the
1020b57cec5SDimitry Andric   /// remark.
1030b57cec5SDimitry Andric   StringRef RemarkName;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   /// Mangled name of the function that triggers the emssion of this remark.
1060b57cec5SDimitry Andric   StringRef FunctionName;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   /// The location in the source file of the remark.
109bdd1243dSDimitry Andric   std::optional<RemarkLocation> Loc;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   /// If profile information is available, this is the number of times the
1120b57cec5SDimitry Andric   /// corresponding code was executed in a profile instrumentation run.
113bdd1243dSDimitry Andric   std::optional<uint64_t> Hotness;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   /// Arguments collected via the streaming interface.
1160b57cec5SDimitry Andric   SmallVector<Argument, 5> Args;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   Remark() = default;
1190b57cec5SDimitry Andric   Remark(Remark &&) = default;
1200b57cec5SDimitry Andric   Remark &operator=(Remark &&) = default;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   /// Return a message composed from the arguments as a string.
1230b57cec5SDimitry Andric   std::string getArgsAsMsg() const;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   /// Clone this remark to explicitly ask for a copy.
1260b57cec5SDimitry Andric   Remark clone() const { return *this; }
1270b57cec5SDimitry Andric 
128*06c3fb27SDimitry Andric   /// Implement operator<< on Remark.
129*06c3fb27SDimitry Andric   void print(raw_ostream &OS) const;
130*06c3fb27SDimitry Andric 
1310b57cec5SDimitry Andric private:
1320b57cec5SDimitry Andric   /// In order to avoid unwanted copies, "delete" the copy constructor.
1330b57cec5SDimitry Andric   /// If a copy is needed, it should be done through `Remark::clone()`.
1340b57cec5SDimitry Andric   Remark(const Remark &) = default;
1350b57cec5SDimitry Andric   Remark& operator=(const Remark &) = default;
1360b57cec5SDimitry Andric };
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric // Create wrappers for C Binding types (see CBindingWrapping.h).
1390b57cec5SDimitry Andric DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Remark, LLVMRemarkEntryRef)
1400b57cec5SDimitry Andric 
1418bcb0991SDimitry Andric /// Comparison operators for Remark objects and dependent objects.
142480093f4SDimitry Andric 
143480093f4SDimitry Andric template <typename T>
144bdd1243dSDimitry Andric bool operator<(const std::optional<T> &LHS, const std::optional<T> &RHS) {
145480093f4SDimitry Andric   // Sorting based on optionals should result in all `None` entries to appear
146480093f4SDimitry Andric   // before the valid entries. For example, remarks with no debug location will
147480093f4SDimitry Andric   // appear first.
148480093f4SDimitry Andric   if (!LHS && !RHS)
149480093f4SDimitry Andric     return false;
150480093f4SDimitry Andric   if (!LHS && RHS)
151480093f4SDimitry Andric     return true;
152480093f4SDimitry Andric   if (LHS && !RHS)
153480093f4SDimitry Andric     return false;
154480093f4SDimitry Andric   return *LHS < *RHS;
155480093f4SDimitry Andric }
156480093f4SDimitry Andric 
1578bcb0991SDimitry Andric inline bool operator==(const RemarkLocation &LHS, const RemarkLocation &RHS) {
1588bcb0991SDimitry Andric   return LHS.SourceFilePath == RHS.SourceFilePath &&
1598bcb0991SDimitry Andric          LHS.SourceLine == RHS.SourceLine &&
1608bcb0991SDimitry Andric          LHS.SourceColumn == RHS.SourceColumn;
1618bcb0991SDimitry Andric }
1628bcb0991SDimitry Andric 
1638bcb0991SDimitry Andric inline bool operator!=(const RemarkLocation &LHS, const RemarkLocation &RHS) {
1648bcb0991SDimitry Andric   return !(LHS == RHS);
1658bcb0991SDimitry Andric }
1668bcb0991SDimitry Andric 
167480093f4SDimitry Andric inline bool operator<(const RemarkLocation &LHS, const RemarkLocation &RHS) {
168480093f4SDimitry Andric   return std::make_tuple(LHS.SourceFilePath, LHS.SourceLine, LHS.SourceColumn) <
169480093f4SDimitry Andric          std::make_tuple(RHS.SourceFilePath, RHS.SourceLine, RHS.SourceColumn);
170480093f4SDimitry Andric }
171480093f4SDimitry Andric 
1728bcb0991SDimitry Andric inline bool operator==(const Argument &LHS, const Argument &RHS) {
1738bcb0991SDimitry Andric   return LHS.Key == RHS.Key && LHS.Val == RHS.Val && LHS.Loc == RHS.Loc;
1748bcb0991SDimitry Andric }
1758bcb0991SDimitry Andric 
1768bcb0991SDimitry Andric inline bool operator!=(const Argument &LHS, const Argument &RHS) {
1778bcb0991SDimitry Andric   return !(LHS == RHS);
1788bcb0991SDimitry Andric }
1798bcb0991SDimitry Andric 
180480093f4SDimitry Andric inline bool operator<(const Argument &LHS, const Argument &RHS) {
181480093f4SDimitry Andric   return std::make_tuple(LHS.Key, LHS.Val, LHS.Loc) <
182480093f4SDimitry Andric          std::make_tuple(RHS.Key, RHS.Val, RHS.Loc);
183480093f4SDimitry Andric }
184480093f4SDimitry Andric 
1858bcb0991SDimitry Andric inline bool operator==(const Remark &LHS, const Remark &RHS) {
1868bcb0991SDimitry Andric   return LHS.RemarkType == RHS.RemarkType && LHS.PassName == RHS.PassName &&
1878bcb0991SDimitry Andric          LHS.RemarkName == RHS.RemarkName &&
1888bcb0991SDimitry Andric          LHS.FunctionName == RHS.FunctionName && LHS.Loc == RHS.Loc &&
1898bcb0991SDimitry Andric          LHS.Hotness == RHS.Hotness && LHS.Args == RHS.Args;
1908bcb0991SDimitry Andric }
1918bcb0991SDimitry Andric 
1928bcb0991SDimitry Andric inline bool operator!=(const Remark &LHS, const Remark &RHS) {
1938bcb0991SDimitry Andric   return !(LHS == RHS);
1948bcb0991SDimitry Andric }
1958bcb0991SDimitry Andric 
196480093f4SDimitry Andric inline bool operator<(const Remark &LHS, const Remark &RHS) {
197480093f4SDimitry Andric   return std::make_tuple(LHS.RemarkType, LHS.PassName, LHS.RemarkName,
198480093f4SDimitry Andric                          LHS.FunctionName, LHS.Loc, LHS.Hotness, LHS.Args) <
199480093f4SDimitry Andric          std::make_tuple(RHS.RemarkType, RHS.PassName, RHS.RemarkName,
200480093f4SDimitry Andric                          RHS.FunctionName, RHS.Loc, RHS.Hotness, RHS.Args);
201480093f4SDimitry Andric }
202480093f4SDimitry Andric 
203*06c3fb27SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const RemarkLocation &RLoc) {
204*06c3fb27SDimitry Andric   RLoc.print(OS);
205*06c3fb27SDimitry Andric   return OS;
206*06c3fb27SDimitry Andric }
207*06c3fb27SDimitry Andric 
208*06c3fb27SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const Argument &Arg) {
209*06c3fb27SDimitry Andric   Arg.print(OS);
210*06c3fb27SDimitry Andric   return OS;
211*06c3fb27SDimitry Andric }
212*06c3fb27SDimitry Andric 
213*06c3fb27SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const Remark &Remark) {
214*06c3fb27SDimitry Andric   Remark.print(OS);
215*06c3fb27SDimitry Andric   return OS;
216*06c3fb27SDimitry Andric }
217*06c3fb27SDimitry Andric 
2180b57cec5SDimitry Andric } // end namespace remarks
2190b57cec5SDimitry Andric } // end namespace llvm
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric #endif /* LLVM_REMARKS_REMARK_H */
222