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