Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 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 <optional> |
||
| 21 | #include <string> |
||
| 22 | |||
| 23 | namespace llvm { |
||
| 24 | namespace remarks { |
||
| 25 | |||
| 26 | /// The current version of the remark entry. |
||
| 27 | constexpr uint64_t CurrentRemarkVersion = 0; |
||
| 28 | |||
| 29 | /// The debug location used to track a remark back to the source file. |
||
| 30 | struct RemarkLocation { |
||
| 31 | /// Absolute path of the source file corresponding to this remark. |
||
| 32 | StringRef SourceFilePath; |
||
| 33 | unsigned SourceLine = 0; |
||
| 34 | unsigned SourceColumn = 0; |
||
| 35 | }; |
||
| 36 | |||
| 37 | // Create wrappers for C Binding types (see CBindingWrapping.h). |
||
| 38 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RemarkLocation, LLVMRemarkDebugLocRef) |
||
| 39 | |||
| 40 | /// A key-value pair with a debug location that is used to display the remarks |
||
| 41 | /// at the right place in the source. |
||
| 42 | struct Argument { |
||
| 43 | StringRef Key; |
||
| 44 | // FIXME: We might want to be able to store other types than strings here. |
||
| 45 | StringRef Val; |
||
| 46 | // If set, the debug location corresponding to the value. |
||
| 47 | std::optional<RemarkLocation> Loc; |
||
| 48 | }; |
||
| 49 | |||
| 50 | // Create wrappers for C Binding types (see CBindingWrapping.h). |
||
| 51 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Argument, LLVMRemarkArgRef) |
||
| 52 | |||
| 53 | /// The type of the remark. |
||
| 54 | enum class Type { |
||
| 55 | Unknown, |
||
| 56 | Passed, |
||
| 57 | Missed, |
||
| 58 | Analysis, |
||
| 59 | AnalysisFPCommute, |
||
| 60 | AnalysisAliasing, |
||
| 61 | Failure, |
||
| 62 | First = Unknown, |
||
| 63 | Last = Failure |
||
| 64 | }; |
||
| 65 | |||
| 66 | /// A remark type used for both emission and parsing. |
||
| 67 | struct Remark { |
||
| 68 | /// The type of the remark. |
||
| 69 | Type RemarkType = Type::Unknown; |
||
| 70 | |||
| 71 | /// Name of the pass that triggers the emission of this remark. |
||
| 72 | StringRef PassName; |
||
| 73 | |||
| 74 | /// Textual identifier for the remark (single-word, camel-case). Can be used |
||
| 75 | /// by external tools reading the output file for remarks to identify the |
||
| 76 | /// remark. |
||
| 77 | StringRef RemarkName; |
||
| 78 | |||
| 79 | /// Mangled name of the function that triggers the emssion of this remark. |
||
| 80 | StringRef FunctionName; |
||
| 81 | |||
| 82 | /// The location in the source file of the remark. |
||
| 83 | std::optional<RemarkLocation> Loc; |
||
| 84 | |||
| 85 | /// If profile information is available, this is the number of times the |
||
| 86 | /// corresponding code was executed in a profile instrumentation run. |
||
| 87 | std::optional<uint64_t> Hotness; |
||
| 88 | |||
| 89 | /// Arguments collected via the streaming interface. |
||
| 90 | SmallVector<Argument, 5> Args; |
||
| 91 | |||
| 92 | Remark() = default; |
||
| 93 | Remark(Remark &&) = default; |
||
| 94 | Remark &operator=(Remark &&) = default; |
||
| 95 | |||
| 96 | /// Return a message composed from the arguments as a string. |
||
| 97 | std::string getArgsAsMsg() const; |
||
| 98 | |||
| 99 | /// Clone this remark to explicitly ask for a copy. |
||
| 100 | Remark clone() const { return *this; } |
||
| 101 | |||
| 102 | private: |
||
| 103 | /// In order to avoid unwanted copies, "delete" the copy constructor. |
||
| 104 | /// If a copy is needed, it should be done through `Remark::clone()`. |
||
| 105 | Remark(const Remark &) = default; |
||
| 106 | Remark& operator=(const Remark &) = default; |
||
| 107 | }; |
||
| 108 | |||
| 109 | // Create wrappers for C Binding types (see CBindingWrapping.h). |
||
| 110 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Remark, LLVMRemarkEntryRef) |
||
| 111 | |||
| 112 | /// Comparison operators for Remark objects and dependent objects. |
||
| 113 | |||
| 114 | template <typename T> |
||
| 115 | bool operator<(const std::optional<T> &LHS, const std::optional<T> &RHS) { |
||
| 116 | // Sorting based on optionals should result in all `None` entries to appear |
||
| 117 | // before the valid entries. For example, remarks with no debug location will |
||
| 118 | // appear first. |
||
| 119 | if (!LHS && !RHS) |
||
| 120 | return false; |
||
| 121 | if (!LHS && RHS) |
||
| 122 | return true; |
||
| 123 | if (LHS && !RHS) |
||
| 124 | return false; |
||
| 125 | return *LHS < *RHS; |
||
| 126 | } |
||
| 127 | |||
| 128 | inline bool operator==(const RemarkLocation &LHS, const RemarkLocation &RHS) { |
||
| 129 | return LHS.SourceFilePath == RHS.SourceFilePath && |
||
| 130 | LHS.SourceLine == RHS.SourceLine && |
||
| 131 | LHS.SourceColumn == RHS.SourceColumn; |
||
| 132 | } |
||
| 133 | |||
| 134 | inline bool operator!=(const RemarkLocation &LHS, const RemarkLocation &RHS) { |
||
| 135 | return !(LHS == RHS); |
||
| 136 | } |
||
| 137 | |||
| 138 | inline bool operator<(const RemarkLocation &LHS, const RemarkLocation &RHS) { |
||
| 139 | return std::make_tuple(LHS.SourceFilePath, LHS.SourceLine, LHS.SourceColumn) < |
||
| 140 | std::make_tuple(RHS.SourceFilePath, RHS.SourceLine, RHS.SourceColumn); |
||
| 141 | } |
||
| 142 | |||
| 143 | inline bool operator==(const Argument &LHS, const Argument &RHS) { |
||
| 144 | return LHS.Key == RHS.Key && LHS.Val == RHS.Val && LHS.Loc == RHS.Loc; |
||
| 145 | } |
||
| 146 | |||
| 147 | inline bool operator!=(const Argument &LHS, const Argument &RHS) { |
||
| 148 | return !(LHS == RHS); |
||
| 149 | } |
||
| 150 | |||
| 151 | inline bool operator<(const Argument &LHS, const Argument &RHS) { |
||
| 152 | return std::make_tuple(LHS.Key, LHS.Val, LHS.Loc) < |
||
| 153 | std::make_tuple(RHS.Key, RHS.Val, RHS.Loc); |
||
| 154 | } |
||
| 155 | |||
| 156 | inline bool operator==(const Remark &LHS, const Remark &RHS) { |
||
| 157 | return LHS.RemarkType == RHS.RemarkType && LHS.PassName == RHS.PassName && |
||
| 158 | LHS.RemarkName == RHS.RemarkName && |
||
| 159 | LHS.FunctionName == RHS.FunctionName && LHS.Loc == RHS.Loc && |
||
| 160 | LHS.Hotness == RHS.Hotness && LHS.Args == RHS.Args; |
||
| 161 | } |
||
| 162 | |||
| 163 | inline bool operator!=(const Remark &LHS, const Remark &RHS) { |
||
| 164 | return !(LHS == RHS); |
||
| 165 | } |
||
| 166 | |||
| 167 | inline bool operator<(const Remark &LHS, const Remark &RHS) { |
||
| 168 | return std::make_tuple(LHS.RemarkType, LHS.PassName, LHS.RemarkName, |
||
| 169 | LHS.FunctionName, LHS.Loc, LHS.Hotness, LHS.Args) < |
||
| 170 | std::make_tuple(RHS.RemarkType, RHS.PassName, RHS.RemarkName, |
||
| 171 | RHS.FunctionName, RHS.Loc, RHS.Hotness, RHS.Args); |
||
| 172 | } |
||
| 173 | |||
| 174 | } // end namespace remarks |
||
| 175 | } // end namespace llvm |
||
| 176 | |||
| 177 | #endif /* LLVM_REMARKS_REMARK_H */ |