xref: /freebsd/contrib/llvm-project/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- LVSupport.h ---------------------------------------------*- 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 support functions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
14 #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
15 
16 #include "llvm/ADT/Twine.h"
17 #include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h"
18 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/Path.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <bitset>
24 #include <cctype>
25 #include <map>
26 #include <sstream>
27 #include <type_traits>
28 
29 namespace llvm {
30 namespace logicalview {
31 
32 // Returns the unique string pool instance.
33 LLVM_ABI LVStringPool &getStringPool();
34 
35 using LVStringRefs = std::vector<StringRef>;
36 using LVLexicalComponent = std::tuple<StringRef, StringRef>;
37 using LVLexicalIndex =
38     std::tuple<LVStringRefs::size_type, LVStringRefs::size_type>;
39 
40 // Used to record specific characteristics about the objects.
41 template <typename T> class LVProperties {
42   static constexpr unsigned N_PROPS = static_cast<unsigned>(T::LastEntry);
43   // Use uint32_t as the underlying type if the `T` enum has at most 32
44   // enumerators; otherwise, fallback to the generic `std::bitset` case.
45   std::conditional_t<(N_PROPS > 32), std::bitset<N_PROPS>, uint32_t> Bits{};
46 
47 public:
48   LVProperties() = default;
49 
set(T Idx)50   void set(T Idx) {
51     if constexpr (std::is_same_v<decltype(Bits), uint32_t>)
52       Bits |= 1 << static_cast<unsigned>(Idx);
53     else
54       Bits.set(static_cast<unsigned>(Idx));
55   }
reset(T Idx)56   void reset(T Idx) {
57     if constexpr (std::is_same_v<decltype(Bits), uint32_t>)
58       Bits &= ~(1 << static_cast<unsigned>(Idx));
59     else
60       Bits.reset(static_cast<unsigned>(Idx));
61   }
get(T Idx)62   bool get(T Idx) const {
63     if constexpr (std::is_same_v<decltype(Bits), uint32_t>)
64       return Bits & (1 << static_cast<unsigned>(Idx));
65     else
66       return Bits[static_cast<unsigned>(Idx)];
67   }
68 };
69 
70 // Generate get, set and reset 'bool' functions for LVProperties instances.
71 // FAMILY: instance name.
72 // ENUM: enumeration instance.
73 // FIELD: enumerator instance.
74 // F1, F2, F3: optional 'set' functions to be called.
75 #define BOOL_BIT(FAMILY, ENUM, FIELD)                                          \
76   bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); }                  \
77   void set##FIELD() { FAMILY.set(ENUM::FIELD); }                               \
78   void reset##FIELD() { FAMILY.reset(ENUM::FIELD); }
79 
80 #define BOOL_BIT_1(FAMILY, ENUM, FIELD, F1)                                    \
81   bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); }                  \
82   void set##FIELD() {                                                          \
83     FAMILY.set(ENUM::FIELD);                                                   \
84     set##F1();                                                                 \
85   }                                                                            \
86   void reset##FIELD() { FAMILY.reset(ENUM::FIELD); }
87 
88 #define BOOL_BIT_2(FAMILY, ENUM, FIELD, F1, F2)                                \
89   bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); }                  \
90   void set##FIELD() {                                                          \
91     FAMILY.set(ENUM::FIELD);                                                   \
92     set##F1();                                                                 \
93     set##F2();                                                                 \
94   }                                                                            \
95   void reset##FIELD() { FAMILY.reset(ENUM::FIELD); }
96 
97 #define BOOL_BIT_3(FAMILY, ENUM, FIELD, F1, F2, F3)                            \
98   bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); }                  \
99   void set##FIELD() {                                                          \
100     FAMILY.set(ENUM::FIELD);                                                   \
101     set##F1();                                                                 \
102     set##F2();                                                                 \
103     set##F3();                                                                 \
104   }                                                                            \
105   void reset##FIELD() { FAMILY.reset(ENUM::FIELD); }
106 
107 // Generate get, set and reset functions for 'properties'.
108 #define PROPERTY(ENUM, FIELD) BOOL_BIT(Properties, ENUM, FIELD)
109 #define PROPERTY_1(ENUM, FIELD, F1) BOOL_BIT_1(Properties, ENUM, FIELD, F1)
110 #define PROPERTY_2(ENUM, FIELD, F1, F2)                                        \
111   BOOL_BIT_2(Properties, ENUM, FIELD, F1, F2)
112 #define PROPERTY_3(ENUM, FIELD, F1, F2, F3)                                    \
113   BOOL_BIT_3(Properties, ENUM, FIELD, F1, F2, F3)
114 
115 // Generate get, set and reset functions for 'kinds'.
116 #define KIND(ENUM, FIELD) BOOL_BIT(Kinds, ENUM, FIELD)
117 #define KIND_1(ENUM, FIELD, F1) BOOL_BIT_1(Kinds, ENUM, FIELD, F1)
118 #define KIND_2(ENUM, FIELD, F1, F2) BOOL_BIT_2(Kinds, ENUM, FIELD, F1, F2)
119 #define KIND_3(ENUM, FIELD, F1, F2, F3)                                        \
120   BOOL_BIT_3(Kinds, ENUM, FIELD, F1, F2, F3)
121 
122 const int HEX_WIDTH = 12;
123 inline FormattedNumber hexValue(uint64_t N, unsigned Width = HEX_WIDTH,
124                                 bool Upper = false) {
125   return format_hex(N, Width, Upper);
126 }
127 
128 // Output the hexadecimal representation of 'Value' using '[0x%08x]' format.
129 inline std::string hexString(uint64_t Value, size_t Width = HEX_WIDTH) {
130   std::string String;
131   raw_string_ostream Stream(String);
132   Stream << hexValue(Value, Width, false);
133   return String;
134 }
135 
136 // Get a hexadecimal string representation for the given value.
hexSquareString(uint64_t Value)137 inline std::string hexSquareString(uint64_t Value) {
138   return (Twine("[") + Twine(hexString(Value)) + Twine("]")).str();
139 }
140 
141 // Return a string with the First and Others separated by spaces.
142 template <typename... Args>
formatAttributes(const StringRef First,Args...Others)143 std::string formatAttributes(const StringRef First, Args... Others) {
144   const auto List = {First, Others...};
145   std::stringstream Stream;
146   size_t Size = 0;
147   for (const StringRef &Item : List) {
148     Stream << (Size ? " " : "") << Item.str();
149     Size = Item.size();
150   }
151   Stream << (Size ? " " : "");
152   return Stream.str();
153 }
154 
155 // Add an item to a map with second being a small vector.
156 template <typename MapType, typename KeyType, typename ValueType>
addItem(MapType * Map,KeyType Key,ValueType Value)157 void addItem(MapType *Map, KeyType Key, ValueType Value) {
158   (*Map)[Key].push_back(Value);
159 }
160 
161 // Double map data structure.
162 template <typename FirstKeyType, typename SecondKeyType, typename ValueType>
163 class LVDoubleMap {
164   static_assert(std::is_pointer<ValueType>::value,
165                 "ValueType must be a pointer.");
166   using LVSecondMapType = std::map<SecondKeyType, ValueType>;
167   using LVFirstMapType =
168       std::map<FirstKeyType, std::unique_ptr<LVSecondMapType>>;
169   using LVAuxMapType = std::map<SecondKeyType, FirstKeyType>;
170   using LVValueTypes = std::vector<ValueType>;
171   LVFirstMapType FirstMap;
172   LVAuxMapType AuxMap;
173 
174 public:
add(FirstKeyType FirstKey,SecondKeyType SecondKey,ValueType Value)175   void add(FirstKeyType FirstKey, SecondKeyType SecondKey, ValueType Value) {
176     typename LVFirstMapType::iterator FirstIter = FirstMap.find(FirstKey);
177     if (FirstIter == FirstMap.end()) {
178       auto SecondMapSP = std::make_unique<LVSecondMapType>();
179       SecondMapSP->emplace(SecondKey, Value);
180       FirstMap.emplace(FirstKey, std::move(SecondMapSP));
181     } else {
182       LVSecondMapType *SecondMap = FirstIter->second.get();
183       if (SecondMap->find(SecondKey) == SecondMap->end())
184         SecondMap->emplace(SecondKey, Value);
185     }
186 
187     typename LVAuxMapType::iterator AuxIter = AuxMap.find(SecondKey);
188     if (AuxIter == AuxMap.end()) {
189       AuxMap.emplace(SecondKey, FirstKey);
190     }
191   }
192 
findMap(FirstKeyType FirstKey)193   LVSecondMapType *findMap(FirstKeyType FirstKey) const {
194     typename LVFirstMapType::const_iterator FirstIter = FirstMap.find(FirstKey);
195     if (FirstIter == FirstMap.end())
196       return nullptr;
197 
198     return FirstIter->second.get();
199   }
200 
find(FirstKeyType FirstKey,SecondKeyType SecondKey)201   ValueType find(FirstKeyType FirstKey, SecondKeyType SecondKey) const {
202     LVSecondMapType *SecondMap = findMap(FirstKey);
203     if (!SecondMap)
204       return nullptr;
205 
206     typename LVSecondMapType::const_iterator SecondIter =
207         SecondMap->find(SecondKey);
208     return (SecondIter != SecondMap->end()) ? SecondIter->second : nullptr;
209   }
210 
find(SecondKeyType SecondKey)211   ValueType find(SecondKeyType SecondKey) const {
212     typename LVAuxMapType::const_iterator AuxIter = AuxMap.find(SecondKey);
213     if (AuxIter == AuxMap.end())
214       return nullptr;
215     return find(AuxIter->second, SecondKey);
216   }
217 
218   // Return a vector with all the 'ValueType' values.
find()219   LVValueTypes find() const {
220     LVValueTypes Values;
221     if (FirstMap.empty())
222       return Values;
223     for (typename LVFirstMapType::const_reference FirstEntry : FirstMap) {
224       LVSecondMapType &SecondMap = *FirstEntry.second;
225       for (typename LVSecondMapType::const_reference SecondEntry : SecondMap)
226         Values.push_back(SecondEntry.second);
227     }
228     return Values;
229   }
230 };
231 
232 // Unified and flattened pathnames.
233 LLVM_ABI std::string transformPath(StringRef Path);
234 LLVM_ABI std::string flattenedFilePath(StringRef Path);
235 
formattedKind(StringRef Kind)236 inline std::string formattedKind(StringRef Kind) {
237   return (Twine("{") + Twine(Kind) + Twine("}")).str();
238 }
239 
formattedName(StringRef Name)240 inline std::string formattedName(StringRef Name) {
241   return (Twine("'") + Twine(Name) + Twine("'")).str();
242 }
243 
formattedNames(StringRef Name1,StringRef Name2)244 inline std::string formattedNames(StringRef Name1, StringRef Name2) {
245   return (Twine("'") + Twine(Name1) + Twine(Name2) + Twine("'")).str();
246 }
247 
248 // The given string represents a symbol or type name with optional enclosing
249 // scopes, such as: name, name<..>, scope::name, scope::..::name, etc.
250 // The string can have multiple references to template instantiations.
251 // It returns the inner most component.
252 LLVM_ABI LVLexicalComponent getInnerComponent(StringRef Name);
253 LLVM_ABI LVStringRefs getAllLexicalComponents(StringRef Name);
254 LLVM_ABI std::string getScopedName(const LVStringRefs &Components,
255                                    StringRef BaseName = {});
256 
257 // These are the values assigned to the debug location record IDs.
258 // See DebugInfo/CodeView/CodeViewSymbols.def.
259 // S_DEFRANGE                               0x113f
260 // S_DEFRANGE_SUBFIELD                      0x1140
261 // S_DEFRANGE_REGISTER                      0x1141
262 // S_DEFRANGE_FRAMEPOINTER_REL              0x1142
263 // S_DEFRANGE_SUBFIELD_REGISTER             0x1143
264 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE   0x1144
265 // S_DEFRANGE_REGISTER_REL                  0x1145
266 // When recording CodeView debug location, the above values are truncated
267 // to a uint8_t value in order to fit the 'OpCode' used for the logical
268 // debug location operations.
269 // Return the original CodeView enum value.
getCodeViewOperationCode(uint8_t Code)270 inline uint16_t getCodeViewOperationCode(uint8_t Code) { return 0x1100 | Code; }
271 
272 } // end namespace logicalview
273 } // end namespace llvm
274 
275 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H
276