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