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 template <typename T> 35 using TypeIsValid = std::bool_constant<std::is_pointer<T>::value>; 36 37 // Utility class to help memory management and perform an automatic cleaning. 38 template <typename T, unsigned N = 8> 39 class LVAutoSmallVector : public SmallVector<T, N> { 40 static_assert(TypeIsValid<T>::value, "T must be a pointer type"); 41 42 public: 43 using iterator = typename SmallVector<T, N>::iterator; 44 LVAutoSmallVector() : SmallVector<T, N>::SmallVector() {} 45 46 ~LVAutoSmallVector() { 47 // Destroy the constructed elements in the vector. 48 for (auto *Item : *this) 49 delete Item; 50 } 51 }; 52 53 // Used to record specific characteristics about the objects. 54 template <typename T> class LVProperties { 55 SmallBitVector Bits = SmallBitVector(static_cast<unsigned>(T::LastEntry) + 1); 56 57 public: 58 LVProperties() = default; 59 60 void set(T Idx) { Bits[static_cast<unsigned>(Idx)] = 1; } 61 void reset(T Idx) { Bits[static_cast<unsigned>(Idx)] = 0; } 62 bool get(T Idx) const { return Bits[static_cast<unsigned>(Idx)]; } 63 }; 64 65 // Generate get, set and reset 'bool' functions for LVProperties instances. 66 // FAMILY: instance name. 67 // ENUM: enumeration instance. 68 // FIELD: enumerator instance. 69 // F1, F2, F3: optional 'set' functions to be called. 70 #define BOOL_BIT(FAMILY, ENUM, FIELD) \ 71 bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); } \ 72 void set##FIELD() { FAMILY.set(ENUM::FIELD); } \ 73 void reset##FIELD() { FAMILY.reset(ENUM::FIELD); } 74 75 #define BOOL_BIT_1(FAMILY, ENUM, FIELD, F1) \ 76 bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); } \ 77 void set##FIELD() { \ 78 FAMILY.set(ENUM::FIELD); \ 79 set##F1(); \ 80 } \ 81 void reset##FIELD() { FAMILY.reset(ENUM::FIELD); } 82 83 #define BOOL_BIT_2(FAMILY, ENUM, FIELD, F1, F2) \ 84 bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); } \ 85 void set##FIELD() { \ 86 FAMILY.set(ENUM::FIELD); \ 87 set##F1(); \ 88 set##F2(); \ 89 } \ 90 void reset##FIELD() { FAMILY.reset(ENUM::FIELD); } 91 92 #define BOOL_BIT_3(FAMILY, ENUM, FIELD, F1, F2, F3) \ 93 bool get##FIELD() const { return FAMILY.get(ENUM::FIELD); } \ 94 void set##FIELD() { \ 95 FAMILY.set(ENUM::FIELD); \ 96 set##F1(); \ 97 set##F2(); \ 98 set##F3(); \ 99 } \ 100 void reset##FIELD() { FAMILY.reset(ENUM::FIELD); } 101 102 // Generate get, set and reset functions for 'properties'. 103 #define PROPERTY(ENUM, FIELD) BOOL_BIT(Properties, ENUM, FIELD) 104 #define PROPERTY_1(ENUM, FIELD, F1) BOOL_BIT_1(Properties, ENUM, FIELD, F1) 105 #define PROPERTY_2(ENUM, FIELD, F1, F2) \ 106 BOOL_BIT_2(Properties, ENUM, FIELD, F1, F2) 107 #define PROPERTY_3(ENUM, FIELD, F1, F2, F3) \ 108 BOOL_BIT_3(Properties, ENUM, FIELD, F1, F2, F3) 109 110 // Generate get, set and reset functions for 'kinds'. 111 #define KIND(ENUM, FIELD) BOOL_BIT(Kinds, ENUM, FIELD) 112 #define KIND_1(ENUM, FIELD, F1) BOOL_BIT_1(Kinds, ENUM, FIELD, F1) 113 #define KIND_2(ENUM, FIELD, F1, F2) BOOL_BIT_2(Kinds, ENUM, FIELD, F1, F2) 114 #define KIND_3(ENUM, FIELD, F1, F2, F3) \ 115 BOOL_BIT_3(Kinds, ENUM, FIELD, F1, F2, F3) 116 117 const int HEX_WIDTH = 12; 118 inline FormattedNumber hexValue(uint64_t N, unsigned Width = HEX_WIDTH, 119 bool Upper = false) { 120 return format_hex(N, Width, Upper); 121 } 122 123 // Output the hexadecimal representation of 'Value' using '[0x%08x]' format. 124 inline std::string hexString(uint64_t Value, size_t Width = HEX_WIDTH) { 125 std::string String; 126 raw_string_ostream Stream(String); 127 Stream << hexValue(Value, Width, false); 128 return Stream.str(); 129 } 130 131 // Get a hexadecimal string representation for the given value. 132 inline std::string hexSquareString(uint64_t Value) { 133 return (Twine("[") + Twine(hexString(Value)) + Twine("]")).str(); 134 } 135 136 // Return a string with the First and Others separated by spaces. 137 template <typename... Args> 138 std::string formatAttributes(const StringRef First, Args... Others) { 139 const auto List = {First, Others...}; 140 std::stringstream Stream; 141 size_t Size = 0; 142 for (const StringRef &Item : List) { 143 Stream << (Size ? " " : "") << Item.str(); 144 Size = Item.size(); 145 } 146 Stream << (Size ? " " : ""); 147 return Stream.str(); 148 } 149 150 // Add an item to a map with second being a list. 151 template <typename MapType, typename ListType, typename KeyType, 152 typename ValueType> 153 void addItem(MapType *Map, KeyType Key, ValueType Value) { 154 ListType *List = nullptr; 155 typename MapType::const_iterator Iter = Map->find(Key); 156 if (Iter != Map->end()) 157 List = Iter->second; 158 else { 159 List = new ListType(); 160 Map->emplace(Key, List); 161 } 162 List->push_back(Value); 163 } 164 165 // Delete the map contained list. 166 template <typename MapType> void deleteList(MapType &Map) { 167 for (typename MapType::const_reference Entry : Map) 168 delete Entry.second; 169 } 170 171 // Double map data structure. 172 template <typename FirstKeyType, typename SecondKeyType, typename ValueType> 173 class LVDoubleMap { 174 static_assert(std::is_pointer<ValueType>::value, 175 "ValueType must be a pointer."); 176 using LVSecondMapType = std::map<SecondKeyType, ValueType>; 177 using LVFirstMapType = std::map<FirstKeyType, LVSecondMapType *>; 178 using LVAuxMapType = std::map<SecondKeyType, FirstKeyType>; 179 using LVValueTypes = std::vector<ValueType>; 180 LVFirstMapType FirstMap; 181 LVAuxMapType AuxMap; 182 183 public: 184 LVDoubleMap() = default; 185 ~LVDoubleMap() { 186 for (auto &Entry : FirstMap) 187 delete Entry.second; 188 } 189 190 void add(FirstKeyType FirstKey, SecondKeyType SecondKey, ValueType Value) { 191 LVSecondMapType *SecondMap = nullptr; 192 typename LVFirstMapType::iterator FirstIter = FirstMap.find(FirstKey); 193 if (FirstIter == FirstMap.end()) { 194 SecondMap = new LVSecondMapType(); 195 FirstMap.emplace(FirstKey, SecondMap); 196 } else { 197 SecondMap = FirstIter->second; 198 } 199 200 assert(SecondMap && "SecondMap is null."); 201 if (SecondMap && SecondMap->find(SecondKey) == SecondMap->end()) 202 SecondMap->emplace(SecondKey, Value); 203 204 typename LVAuxMapType::iterator AuxIter = AuxMap.find(SecondKey); 205 if (AuxIter == AuxMap.end()) { 206 AuxMap.emplace(SecondKey, FirstKey); 207 } 208 } 209 210 LVSecondMapType *findMap(FirstKeyType FirstKey) const { 211 typename LVFirstMapType::const_iterator FirstIter = FirstMap.find(FirstKey); 212 if (FirstIter == FirstMap.end()) 213 return nullptr; 214 215 LVSecondMapType *SecondMap = FirstIter->second; 216 return SecondMap; 217 } 218 219 ValueType find(FirstKeyType FirstKey, SecondKeyType SecondKey) const { 220 LVSecondMapType *SecondMap = findMap(FirstKey); 221 if (!SecondMap) 222 return nullptr; 223 224 typename LVSecondMapType::const_iterator SecondIter = 225 SecondMap->find(SecondKey); 226 return (SecondIter != SecondMap->end()) ? SecondIter->second : nullptr; 227 } 228 229 ValueType find(SecondKeyType SecondKey) const { 230 typename LVAuxMapType::const_iterator AuxIter = AuxMap.find(SecondKey); 231 if (AuxIter == AuxMap.end()) 232 return nullptr; 233 return find(AuxIter->second, SecondKey); 234 } 235 236 // Return a vector with all the 'ValueType' values. 237 LVValueTypes find() const { 238 LVValueTypes Values; 239 if (FirstMap.empty()) 240 return Values; 241 for (typename LVFirstMapType::const_reference FirstEntry : FirstMap) { 242 LVSecondMapType *SecondMap = FirstEntry.second; 243 for (typename LVSecondMapType::const_reference SecondEntry : *SecondMap) 244 Values.push_back(SecondEntry.second); 245 } 246 return Values; 247 } 248 }; 249 250 // Unified and flattened pathnames. 251 std::string transformPath(StringRef Path); 252 std::string flattenedFilePath(StringRef Path); 253 254 inline std::string formattedKind(StringRef Kind) { 255 return (Twine("{") + Twine(Kind) + Twine("}")).str(); 256 } 257 258 inline std::string formattedName(StringRef Name) { 259 return (Twine("'") + Twine(Name) + Twine("'")).str(); 260 } 261 262 inline std::string formattedNames(StringRef Name1, StringRef Name2) { 263 return (Twine("'") + Twine(Name1) + Twine(Name2) + Twine("'")).str(); 264 } 265 266 // These are the values assigned to the debug location record IDs. 267 // See DebugInfo/CodeView/CodeViewSymbols.def. 268 // S_DEFRANGE 0x113f 269 // S_DEFRANGE_SUBFIELD 0x1140 270 // S_DEFRANGE_REGISTER 0x1141 271 // S_DEFRANGE_FRAMEPOINTER_REL 0x1142 272 // S_DEFRANGE_SUBFIELD_REGISTER 0x1143 273 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE 0x1144 274 // S_DEFRANGE_REGISTER_REL 0x1145 275 // When recording CodeView debug location, the above values are truncated 276 // to a uint8_t value in order to fit the 'OpCode' used for the logical 277 // debug location operations. 278 // Return the original CodeView enum value. 279 inline uint16_t getCodeViewOperationCode(uint8_t Code) { return 0x1100 | Code; } 280 281 } // end namespace logicalview 282 } // end namespace llvm 283 284 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSUPPORT_H 285