xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Remarks/Remark.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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"
2006c3fb27SDimitry 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;
3606c3fb27SDimitry Andric 
3706c3fb27SDimitry Andric   /// Implement operator<< on RemarkLocation.
3806c3fb27SDimitry 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;
5206c3fb27SDimitry Andric 
5306c3fb27SDimitry Andric   /// Implement operator<< on Argument.
5406c3fb27SDimitry Andric   void print(raw_ostream &OS) const;
55*5f757f3fSDimitry Andric   /// Return the value of argument as int.
56*5f757f3fSDimitry Andric   std::optional<int> getValAsInt() const;
57*5f757f3fSDimitry Andric   /// Check if the argument value can be parsed as int.
58*5f757f3fSDimitry Andric   bool isValInt() const;
590b57cec5SDimitry Andric };
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric // Create wrappers for C Binding types (see CBindingWrapping.h).
620b57cec5SDimitry Andric DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Argument, LLVMRemarkArgRef)
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric /// The type of the remark.
650b57cec5SDimitry Andric enum class Type {
660b57cec5SDimitry Andric   Unknown,
670b57cec5SDimitry Andric   Passed,
680b57cec5SDimitry Andric   Missed,
690b57cec5SDimitry Andric   Analysis,
700b57cec5SDimitry Andric   AnalysisFPCommute,
710b57cec5SDimitry Andric   AnalysisAliasing,
720b57cec5SDimitry Andric   Failure,
738bcb0991SDimitry Andric   First = Unknown,
748bcb0991SDimitry Andric   Last = Failure
750b57cec5SDimitry Andric };
760b57cec5SDimitry Andric 
7706c3fb27SDimitry Andric inline StringRef typeToStr(Type Ty) {
7806c3fb27SDimitry Andric   switch (Ty) {
7906c3fb27SDimitry Andric   case Type::Unknown:
8006c3fb27SDimitry Andric     return "Unknown";
8106c3fb27SDimitry Andric   case Type::Missed:
8206c3fb27SDimitry Andric     return "Missed";
8306c3fb27SDimitry Andric   case Type::Passed:
8406c3fb27SDimitry Andric     return "Passed";
8506c3fb27SDimitry Andric   case Type::Analysis:
8606c3fb27SDimitry Andric     return "Analysis";
8706c3fb27SDimitry Andric   case Type::AnalysisFPCommute:
8806c3fb27SDimitry Andric     return "AnalysisFPCommute";
8906c3fb27SDimitry Andric   case Type::AnalysisAliasing:
9006c3fb27SDimitry Andric     return "AnalysisAliasing";
9106c3fb27SDimitry Andric   default:
9206c3fb27SDimitry Andric     return "Failure";
9306c3fb27SDimitry Andric   }
9406c3fb27SDimitry Andric }
9506c3fb27SDimitry Andric 
960b57cec5SDimitry Andric /// A remark type used for both emission and parsing.
970b57cec5SDimitry Andric struct Remark {
980b57cec5SDimitry Andric   /// The type of the remark.
990b57cec5SDimitry Andric   Type RemarkType = Type::Unknown;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   /// Name of the pass that triggers the emission of this remark.
1020b57cec5SDimitry Andric   StringRef PassName;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   /// Textual identifier for the remark (single-word, camel-case). Can be used
1050b57cec5SDimitry Andric   /// by external tools reading the output file for remarks to identify the
1060b57cec5SDimitry Andric   /// remark.
1070b57cec5SDimitry Andric   StringRef RemarkName;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   /// Mangled name of the function that triggers the emssion of this remark.
1100b57cec5SDimitry Andric   StringRef FunctionName;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   /// The location in the source file of the remark.
113bdd1243dSDimitry Andric   std::optional<RemarkLocation> Loc;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   /// If profile information is available, this is the number of times the
1160b57cec5SDimitry Andric   /// corresponding code was executed in a profile instrumentation run.
117bdd1243dSDimitry Andric   std::optional<uint64_t> Hotness;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   /// Arguments collected via the streaming interface.
1200b57cec5SDimitry Andric   SmallVector<Argument, 5> Args;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   Remark() = default;
1230b57cec5SDimitry Andric   Remark(Remark &&) = default;
1240b57cec5SDimitry Andric   Remark &operator=(Remark &&) = default;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   /// Return a message composed from the arguments as a string.
1270b57cec5SDimitry Andric   std::string getArgsAsMsg() const;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   /// Clone this remark to explicitly ask for a copy.
1300b57cec5SDimitry Andric   Remark clone() const { return *this; }
1310b57cec5SDimitry Andric 
13206c3fb27SDimitry Andric   /// Implement operator<< on Remark.
13306c3fb27SDimitry Andric   void print(raw_ostream &OS) const;
13406c3fb27SDimitry Andric 
1350b57cec5SDimitry Andric private:
1360b57cec5SDimitry Andric   /// In order to avoid unwanted copies, "delete" the copy constructor.
1370b57cec5SDimitry Andric   /// If a copy is needed, it should be done through `Remark::clone()`.
1380b57cec5SDimitry Andric   Remark(const Remark &) = default;
1390b57cec5SDimitry Andric   Remark& operator=(const Remark &) = default;
1400b57cec5SDimitry Andric };
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric // Create wrappers for C Binding types (see CBindingWrapping.h).
1430b57cec5SDimitry Andric DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Remark, LLVMRemarkEntryRef)
1440b57cec5SDimitry Andric 
1458bcb0991SDimitry Andric /// Comparison operators for Remark objects and dependent objects.
146480093f4SDimitry Andric 
147480093f4SDimitry Andric template <typename T>
148bdd1243dSDimitry Andric bool operator<(const std::optional<T> &LHS, const std::optional<T> &RHS) {
149480093f4SDimitry Andric   // Sorting based on optionals should result in all `None` entries to appear
150480093f4SDimitry Andric   // before the valid entries. For example, remarks with no debug location will
151480093f4SDimitry Andric   // appear first.
152480093f4SDimitry Andric   if (!LHS && !RHS)
153480093f4SDimitry Andric     return false;
154480093f4SDimitry Andric   if (!LHS && RHS)
155480093f4SDimitry Andric     return true;
156480093f4SDimitry Andric   if (LHS && !RHS)
157480093f4SDimitry Andric     return false;
158480093f4SDimitry Andric   return *LHS < *RHS;
159480093f4SDimitry Andric }
160480093f4SDimitry Andric 
1618bcb0991SDimitry Andric inline bool operator==(const RemarkLocation &LHS, const RemarkLocation &RHS) {
1628bcb0991SDimitry Andric   return LHS.SourceFilePath == RHS.SourceFilePath &&
1638bcb0991SDimitry Andric          LHS.SourceLine == RHS.SourceLine &&
1648bcb0991SDimitry Andric          LHS.SourceColumn == RHS.SourceColumn;
1658bcb0991SDimitry Andric }
1668bcb0991SDimitry Andric 
1678bcb0991SDimitry Andric inline bool operator!=(const RemarkLocation &LHS, const RemarkLocation &RHS) {
1688bcb0991SDimitry Andric   return !(LHS == RHS);
1698bcb0991SDimitry Andric }
1708bcb0991SDimitry Andric 
171480093f4SDimitry Andric inline bool operator<(const RemarkLocation &LHS, const RemarkLocation &RHS) {
172480093f4SDimitry Andric   return std::make_tuple(LHS.SourceFilePath, LHS.SourceLine, LHS.SourceColumn) <
173480093f4SDimitry Andric          std::make_tuple(RHS.SourceFilePath, RHS.SourceLine, RHS.SourceColumn);
174480093f4SDimitry Andric }
175480093f4SDimitry Andric 
1768bcb0991SDimitry Andric inline bool operator==(const Argument &LHS, const Argument &RHS) {
1778bcb0991SDimitry Andric   return LHS.Key == RHS.Key && LHS.Val == RHS.Val && LHS.Loc == RHS.Loc;
1788bcb0991SDimitry Andric }
1798bcb0991SDimitry Andric 
1808bcb0991SDimitry Andric inline bool operator!=(const Argument &LHS, const Argument &RHS) {
1818bcb0991SDimitry Andric   return !(LHS == RHS);
1828bcb0991SDimitry Andric }
1838bcb0991SDimitry Andric 
184480093f4SDimitry Andric inline bool operator<(const Argument &LHS, const Argument &RHS) {
185480093f4SDimitry Andric   return std::make_tuple(LHS.Key, LHS.Val, LHS.Loc) <
186480093f4SDimitry Andric          std::make_tuple(RHS.Key, RHS.Val, RHS.Loc);
187480093f4SDimitry Andric }
188480093f4SDimitry Andric 
1898bcb0991SDimitry Andric inline bool operator==(const Remark &LHS, const Remark &RHS) {
1908bcb0991SDimitry Andric   return LHS.RemarkType == RHS.RemarkType && LHS.PassName == RHS.PassName &&
1918bcb0991SDimitry Andric          LHS.RemarkName == RHS.RemarkName &&
1928bcb0991SDimitry Andric          LHS.FunctionName == RHS.FunctionName && LHS.Loc == RHS.Loc &&
1938bcb0991SDimitry Andric          LHS.Hotness == RHS.Hotness && LHS.Args == RHS.Args;
1948bcb0991SDimitry Andric }
1958bcb0991SDimitry Andric 
1968bcb0991SDimitry Andric inline bool operator!=(const Remark &LHS, const Remark &RHS) {
1978bcb0991SDimitry Andric   return !(LHS == RHS);
1988bcb0991SDimitry Andric }
1998bcb0991SDimitry Andric 
200480093f4SDimitry Andric inline bool operator<(const Remark &LHS, const Remark &RHS) {
201480093f4SDimitry Andric   return std::make_tuple(LHS.RemarkType, LHS.PassName, LHS.RemarkName,
202480093f4SDimitry Andric                          LHS.FunctionName, LHS.Loc, LHS.Hotness, LHS.Args) <
203480093f4SDimitry Andric          std::make_tuple(RHS.RemarkType, RHS.PassName, RHS.RemarkName,
204480093f4SDimitry Andric                          RHS.FunctionName, RHS.Loc, RHS.Hotness, RHS.Args);
205480093f4SDimitry Andric }
206480093f4SDimitry Andric 
20706c3fb27SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const RemarkLocation &RLoc) {
20806c3fb27SDimitry Andric   RLoc.print(OS);
20906c3fb27SDimitry Andric   return OS;
21006c3fb27SDimitry Andric }
21106c3fb27SDimitry Andric 
21206c3fb27SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const Argument &Arg) {
21306c3fb27SDimitry Andric   Arg.print(OS);
21406c3fb27SDimitry Andric   return OS;
21506c3fb27SDimitry Andric }
21606c3fb27SDimitry Andric 
21706c3fb27SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const Remark &Remark) {
21806c3fb27SDimitry Andric   Remark.print(OS);
21906c3fb27SDimitry Andric   return OS;
22006c3fb27SDimitry Andric }
22106c3fb27SDimitry Andric 
2220b57cec5SDimitry Andric } // end namespace remarks
2230b57cec5SDimitry Andric } // end namespace llvm
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric #endif /* LLVM_REMARKS_REMARK_H */
226