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