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