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" 170b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 18*5ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h" 190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 200b57cec5SDimitry Andric #include "llvm/Support/CBindingWrapping.h" 210b57cec5SDimitry Andric #include <string> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace llvm { 240b57cec5SDimitry Andric namespace remarks { 250b57cec5SDimitry Andric 268bcb0991SDimitry Andric /// The current version of the remark entry. 278bcb0991SDimitry Andric constexpr uint64_t CurrentRemarkVersion = 0; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric /// The debug location used to track a remark back to the source file. 300b57cec5SDimitry Andric struct RemarkLocation { 310b57cec5SDimitry Andric /// Absolute path of the source file corresponding to this remark. 320b57cec5SDimitry Andric StringRef SourceFilePath; 33480093f4SDimitry Andric unsigned SourceLine = 0; 34480093f4SDimitry Andric unsigned SourceColumn = 0; 350b57cec5SDimitry Andric }; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric // Create wrappers for C Binding types (see CBindingWrapping.h). 380b57cec5SDimitry Andric DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RemarkLocation, LLVMRemarkDebugLocRef) 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric /// A key-value pair with a debug location that is used to display the remarks 410b57cec5SDimitry Andric /// at the right place in the source. 420b57cec5SDimitry Andric struct Argument { 430b57cec5SDimitry Andric StringRef Key; 440b57cec5SDimitry Andric // FIXME: We might want to be able to store other types than strings here. 450b57cec5SDimitry Andric StringRef Val; 460b57cec5SDimitry Andric // If set, the debug location corresponding to the value. 470b57cec5SDimitry Andric Optional<RemarkLocation> Loc; 480b57cec5SDimitry Andric }; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // Create wrappers for C Binding types (see CBindingWrapping.h). 510b57cec5SDimitry Andric DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Argument, LLVMRemarkArgRef) 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric /// The type of the remark. 540b57cec5SDimitry Andric enum class Type { 550b57cec5SDimitry Andric Unknown, 560b57cec5SDimitry Andric Passed, 570b57cec5SDimitry Andric Missed, 580b57cec5SDimitry Andric Analysis, 590b57cec5SDimitry Andric AnalysisFPCommute, 600b57cec5SDimitry Andric AnalysisAliasing, 610b57cec5SDimitry Andric Failure, 628bcb0991SDimitry Andric First = Unknown, 638bcb0991SDimitry Andric Last = Failure 640b57cec5SDimitry Andric }; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric /// A remark type used for both emission and parsing. 670b57cec5SDimitry Andric struct Remark { 680b57cec5SDimitry Andric /// The type of the remark. 690b57cec5SDimitry Andric Type RemarkType = Type::Unknown; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric /// Name of the pass that triggers the emission of this remark. 720b57cec5SDimitry Andric StringRef PassName; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric /// Textual identifier for the remark (single-word, camel-case). Can be used 750b57cec5SDimitry Andric /// by external tools reading the output file for remarks to identify the 760b57cec5SDimitry Andric /// remark. 770b57cec5SDimitry Andric StringRef RemarkName; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Mangled name of the function that triggers the emssion of this remark. 800b57cec5SDimitry Andric StringRef FunctionName; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric /// The location in the source file of the remark. 830b57cec5SDimitry Andric Optional<RemarkLocation> Loc; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric /// If profile information is available, this is the number of times the 860b57cec5SDimitry Andric /// corresponding code was executed in a profile instrumentation run. 870b57cec5SDimitry Andric Optional<uint64_t> Hotness; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric /// Arguments collected via the streaming interface. 900b57cec5SDimitry Andric SmallVector<Argument, 5> Args; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric Remark() = default; 930b57cec5SDimitry Andric Remark(Remark &&) = default; 940b57cec5SDimitry Andric Remark &operator=(Remark &&) = default; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric /// Return a message composed from the arguments as a string. 970b57cec5SDimitry Andric std::string getArgsAsMsg() const; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric /// Clone this remark to explicitly ask for a copy. 1000b57cec5SDimitry Andric Remark clone() const { return *this; } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric private: 1030b57cec5SDimitry Andric /// In order to avoid unwanted copies, "delete" the copy constructor. 1040b57cec5SDimitry Andric /// If a copy is needed, it should be done through `Remark::clone()`. 1050b57cec5SDimitry Andric Remark(const Remark &) = default; 1060b57cec5SDimitry Andric Remark& operator=(const Remark &) = default; 1070b57cec5SDimitry Andric }; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // Create wrappers for C Binding types (see CBindingWrapping.h). 1100b57cec5SDimitry Andric DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Remark, LLVMRemarkEntryRef) 1110b57cec5SDimitry Andric 1128bcb0991SDimitry Andric /// Comparison operators for Remark objects and dependent objects. 113480093f4SDimitry Andric 114480093f4SDimitry Andric template <typename T> 115480093f4SDimitry Andric bool operator<(const Optional<T> &LHS, const Optional<T> &RHS) { 116480093f4SDimitry Andric // Sorting based on optionals should result in all `None` entries to appear 117480093f4SDimitry Andric // before the valid entries. For example, remarks with no debug location will 118480093f4SDimitry Andric // appear first. 119480093f4SDimitry Andric if (!LHS && !RHS) 120480093f4SDimitry Andric return false; 121480093f4SDimitry Andric if (!LHS && RHS) 122480093f4SDimitry Andric return true; 123480093f4SDimitry Andric if (LHS && !RHS) 124480093f4SDimitry Andric return false; 125480093f4SDimitry Andric return *LHS < *RHS; 126480093f4SDimitry Andric } 127480093f4SDimitry Andric 1288bcb0991SDimitry Andric inline bool operator==(const RemarkLocation &LHS, const RemarkLocation &RHS) { 1298bcb0991SDimitry Andric return LHS.SourceFilePath == RHS.SourceFilePath && 1308bcb0991SDimitry Andric LHS.SourceLine == RHS.SourceLine && 1318bcb0991SDimitry Andric LHS.SourceColumn == RHS.SourceColumn; 1328bcb0991SDimitry Andric } 1338bcb0991SDimitry Andric 1348bcb0991SDimitry Andric inline bool operator!=(const RemarkLocation &LHS, const RemarkLocation &RHS) { 1358bcb0991SDimitry Andric return !(LHS == RHS); 1368bcb0991SDimitry Andric } 1378bcb0991SDimitry Andric 138480093f4SDimitry Andric inline bool operator<(const RemarkLocation &LHS, const RemarkLocation &RHS) { 139480093f4SDimitry Andric return std::make_tuple(LHS.SourceFilePath, LHS.SourceLine, LHS.SourceColumn) < 140480093f4SDimitry Andric std::make_tuple(RHS.SourceFilePath, RHS.SourceLine, RHS.SourceColumn); 141480093f4SDimitry Andric } 142480093f4SDimitry Andric 1438bcb0991SDimitry Andric inline bool operator==(const Argument &LHS, const Argument &RHS) { 1448bcb0991SDimitry Andric return LHS.Key == RHS.Key && LHS.Val == RHS.Val && LHS.Loc == RHS.Loc; 1458bcb0991SDimitry Andric } 1468bcb0991SDimitry Andric 1478bcb0991SDimitry Andric inline bool operator!=(const Argument &LHS, const Argument &RHS) { 1488bcb0991SDimitry Andric return !(LHS == RHS); 1498bcb0991SDimitry Andric } 1508bcb0991SDimitry Andric 151480093f4SDimitry Andric inline bool operator<(const Argument &LHS, const Argument &RHS) { 152480093f4SDimitry Andric return std::make_tuple(LHS.Key, LHS.Val, LHS.Loc) < 153480093f4SDimitry Andric std::make_tuple(RHS.Key, RHS.Val, RHS.Loc); 154480093f4SDimitry Andric } 155480093f4SDimitry Andric 1568bcb0991SDimitry Andric inline bool operator==(const Remark &LHS, const Remark &RHS) { 1578bcb0991SDimitry Andric return LHS.RemarkType == RHS.RemarkType && LHS.PassName == RHS.PassName && 1588bcb0991SDimitry Andric LHS.RemarkName == RHS.RemarkName && 1598bcb0991SDimitry Andric LHS.FunctionName == RHS.FunctionName && LHS.Loc == RHS.Loc && 1608bcb0991SDimitry Andric LHS.Hotness == RHS.Hotness && LHS.Args == RHS.Args; 1618bcb0991SDimitry Andric } 1628bcb0991SDimitry Andric 1638bcb0991SDimitry Andric inline bool operator!=(const Remark &LHS, const Remark &RHS) { 1648bcb0991SDimitry Andric return !(LHS == RHS); 1658bcb0991SDimitry Andric } 1668bcb0991SDimitry Andric 167480093f4SDimitry Andric inline bool operator<(const Remark &LHS, const Remark &RHS) { 168480093f4SDimitry Andric return std::make_tuple(LHS.RemarkType, LHS.PassName, LHS.RemarkName, 169480093f4SDimitry Andric LHS.FunctionName, LHS.Loc, LHS.Hotness, LHS.Args) < 170480093f4SDimitry Andric std::make_tuple(RHS.RemarkType, RHS.PassName, RHS.RemarkName, 171480093f4SDimitry Andric RHS.FunctionName, RHS.Loc, RHS.Hotness, RHS.Args); 172480093f4SDimitry Andric } 173480093f4SDimitry Andric 1740b57cec5SDimitry Andric } // end namespace remarks 1750b57cec5SDimitry Andric } // end namespace llvm 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric #endif /* LLVM_REMARKS_REMARK_H */ 178