xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Remarks/Remark.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- llvm/Remarks/Remark.h - The remark type -----------------*- C++/-*-===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines an abstraction for handling remarks.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_REMARKS_REMARK_H
14 #define LLVM_REMARKS_REMARK_H
15 
16 #include "llvm-c/Remarks.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Support/CBindingWrapping.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <optional>
23 #include <string>
24 
25 namespace llvm {
26 namespace remarks {
27 
28 /// The current version of the remark entry.
29 constexpr uint64_t CurrentRemarkVersion = 0;
30 
31 /// The debug location used to track a remark back to the source file.
32 struct RemarkLocation {
33   /// Absolute path of the source file corresponding to this remark.
34   StringRef SourceFilePath;
35   unsigned SourceLine = 0;
36   unsigned SourceColumn = 0;
37 
38   /// Implement operator<< on RemarkLocation.
39   LLVM_ABI void print(raw_ostream &OS) const;
40 };
41 
42 // Create wrappers for C Binding types (see CBindingWrapping.h).
43 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RemarkLocation, LLVMRemarkDebugLocRef)
44 
45 /// A key-value pair with a debug location that is used to display the remarks
46 /// at the right place in the source.
47 struct Argument {
48   StringRef Key;
49   // FIXME: We might want to be able to store other types than strings here.
50   StringRef Val;
51   // If set, the debug location corresponding to the value.
52   std::optional<RemarkLocation> Loc;
53 
54   /// Implement operator<< on Argument.
55   LLVM_ABI void print(raw_ostream &OS) const;
56   /// Return the value of argument as int.
57   LLVM_ABI std::optional<int> getValAsInt() const;
58   /// Check if the argument value can be parsed as int.
59   LLVM_ABI bool isValInt() const;
60 };
61 
62 // Create wrappers for C Binding types (see CBindingWrapping.h).
63 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Argument, LLVMRemarkArgRef)
64 
65 /// The type of the remark.
66 enum class Type {
67   Unknown,
68   Passed,
69   Missed,
70   Analysis,
71   AnalysisFPCommute,
72   AnalysisAliasing,
73   Failure,
74   First = Unknown,
75   Last = Failure
76 };
77 
typeToStr(Type Ty)78 inline StringRef typeToStr(Type Ty) {
79   switch (Ty) {
80   case Type::Unknown:
81     return "Unknown";
82   case Type::Missed:
83     return "Missed";
84   case Type::Passed:
85     return "Passed";
86   case Type::Analysis:
87     return "Analysis";
88   case Type::AnalysisFPCommute:
89     return "AnalysisFPCommute";
90   case Type::AnalysisAliasing:
91     return "AnalysisAliasing";
92   default:
93     return "Failure";
94   }
95 }
96 
97 /// A remark type used for both emission and parsing.
98 struct Remark {
99   /// The type of the remark.
100   Type RemarkType = Type::Unknown;
101 
102   /// Name of the pass that triggers the emission of this remark.
103   StringRef PassName;
104 
105   /// Textual identifier for the remark (single-word, camel-case). Can be used
106   /// by external tools reading the output file for remarks to identify the
107   /// remark.
108   StringRef RemarkName;
109 
110   /// Mangled name of the function that triggers the emssion of this remark.
111   StringRef FunctionName;
112 
113   /// The location in the source file of the remark.
114   std::optional<RemarkLocation> Loc;
115 
116   /// If profile information is available, this is the number of times the
117   /// corresponding code was executed in a profile instrumentation run.
118   std::optional<uint64_t> Hotness;
119 
120   /// Arguments collected via the streaming interface.
121   SmallVector<Argument, 5> Args;
122 
123   Remark() = default;
124   Remark(Remark &&) = default;
125   Remark &operator=(Remark &&) = default;
126 
127   /// Return a message composed from the arguments as a string.
128   LLVM_ABI std::string getArgsAsMsg() const;
129 
130   /// Clone this remark to explicitly ask for a copy.
cloneRemark131   Remark clone() const { return *this; }
132 
133   /// Implement operator<< on Remark.
134   LLVM_ABI void print(raw_ostream &OS) const;
135 
136 private:
137   /// In order to avoid unwanted copies, "delete" the copy constructor.
138   /// If a copy is needed, it should be done through `Remark::clone()`.
139   Remark(const Remark &) = default;
140   Remark& operator=(const Remark &) = default;
141 };
142 
143 // Create wrappers for C Binding types (see CBindingWrapping.h).
144 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Remark, LLVMRemarkEntryRef)
145 
146 /// Comparison operators for Remark objects and dependent objects.
147 
148 template <typename T>
149 bool operator<(const std::optional<T> &LHS, const std::optional<T> &RHS) {
150   // Sorting based on optionals should result in all `None` entries to appear
151   // before the valid entries. For example, remarks with no debug location will
152   // appear first.
153   if (!LHS && !RHS)
154     return false;
155   if (!LHS && RHS)
156     return true;
157   if (LHS && !RHS)
158     return false;
159   return *LHS < *RHS;
160 }
161 
162 inline bool operator==(const RemarkLocation &LHS, const RemarkLocation &RHS) {
163   return LHS.SourceFilePath == RHS.SourceFilePath &&
164          LHS.SourceLine == RHS.SourceLine &&
165          LHS.SourceColumn == RHS.SourceColumn;
166 }
167 
168 inline bool operator!=(const RemarkLocation &LHS, const RemarkLocation &RHS) {
169   return !(LHS == RHS);
170 }
171 
172 inline bool operator<(const RemarkLocation &LHS, const RemarkLocation &RHS) {
173   return std::make_tuple(LHS.SourceFilePath, LHS.SourceLine, LHS.SourceColumn) <
174          std::make_tuple(RHS.SourceFilePath, RHS.SourceLine, RHS.SourceColumn);
175 }
176 
177 inline bool operator==(const Argument &LHS, const Argument &RHS) {
178   return LHS.Key == RHS.Key && LHS.Val == RHS.Val && LHS.Loc == RHS.Loc;
179 }
180 
181 inline bool operator!=(const Argument &LHS, const Argument &RHS) {
182   return !(LHS == RHS);
183 }
184 
185 inline bool operator<(const Argument &LHS, const Argument &RHS) {
186   return std::make_tuple(LHS.Key, LHS.Val, LHS.Loc) <
187          std::make_tuple(RHS.Key, RHS.Val, RHS.Loc);
188 }
189 
190 inline bool operator==(const Remark &LHS, const Remark &RHS) {
191   return LHS.RemarkType == RHS.RemarkType && LHS.PassName == RHS.PassName &&
192          LHS.RemarkName == RHS.RemarkName &&
193          LHS.FunctionName == RHS.FunctionName && LHS.Loc == RHS.Loc &&
194          LHS.Hotness == RHS.Hotness && LHS.Args == RHS.Args;
195 }
196 
197 inline bool operator!=(const Remark &LHS, const Remark &RHS) {
198   return !(LHS == RHS);
199 }
200 
201 inline bool operator<(const Remark &LHS, const Remark &RHS) {
202   return std::make_tuple(LHS.RemarkType, LHS.PassName, LHS.RemarkName,
203                          LHS.FunctionName, LHS.Loc, LHS.Hotness, LHS.Args) <
204          std::make_tuple(RHS.RemarkType, RHS.PassName, RHS.RemarkName,
205                          RHS.FunctionName, RHS.Loc, RHS.Hotness, RHS.Args);
206 }
207 
208 inline raw_ostream &operator<<(raw_ostream &OS, const RemarkLocation &RLoc) {
209   RLoc.print(OS);
210   return OS;
211 }
212 
213 inline raw_ostream &operator<<(raw_ostream &OS, const Argument &Arg) {
214   Arg.print(OS);
215   return OS;
216 }
217 
218 inline raw_ostream &operator<<(raw_ostream &OS, const Remark &Remark) {
219   Remark.print(OS);
220   return OS;
221 }
222 
223 } // end namespace remarks
224 } // end namespace llvm
225 
226 #endif /* LLVM_REMARKS_REMARK_H */
227