1 //==- SymbolCache.h - Cache of native symbols and ids ------------*- 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 #ifndef LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H 10 #define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H 11 12 #include "llvm/ADT/DenseMap.h" 13 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 14 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 15 #include "llvm/DebugInfo/CodeView/TypeRecord.h" 16 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" 17 #include "llvm/Support/Allocator.h" 18 19 #include <memory> 20 #include <vector> 21 22 namespace llvm { 23 namespace pdb { 24 class DbiStream; 25 class PDBFile; 26 27 class SymbolCache { 28 NativeSession &Session; 29 DbiStream *Dbi = nullptr; 30 31 /// Cache of all stable symbols, indexed by SymIndexId. Just because a 32 /// symbol has been parsed does not imply that it will be stable and have 33 /// an Id. Id allocation is an implementation, with the only guarantee 34 /// being that once an Id is allocated, the symbol can be assumed to be 35 /// cached. 36 std::vector<std::unique_ptr<NativeRawSymbol>> Cache; 37 38 /// For type records from the TPI stream which have been paresd and cached, 39 /// stores a mapping to SymIndexId of the cached symbol. 40 DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId; 41 42 /// For field list members which have been parsed and cached, stores a mapping 43 /// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the 44 /// cached symbol. 45 DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId> 46 FieldListMembersToSymbolId; 47 48 /// List of SymIndexIds for each compiland, indexed by compiland index as they 49 /// appear in the PDB file. 50 std::vector<SymIndexId> Compilands; 51 52 /// Map from global symbol offset to SymIndexId. 53 DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId; 54 55 SymIndexId createSymbolPlaceholder() { 56 SymIndexId Id = Cache.size(); 57 Cache.push_back(nullptr); 58 return Id; 59 } 60 61 template <typename ConcreteSymbolT, typename CVRecordT, typename... Args> 62 SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT, 63 Args &&... ConstructorArgs) { 64 CVRecordT Record; 65 if (auto EC = 66 codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) { 67 consumeError(std::move(EC)); 68 return 0; 69 } 70 71 return createSymbol<ConcreteSymbolT>( 72 TI, std::move(Record), std::forward<Args>(ConstructorArgs)...); 73 } 74 75 SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI, 76 codeview::CVType CVT); 77 78 SymIndexId createSimpleType(codeview::TypeIndex TI, 79 codeview::ModifierOptions Mods); 80 81 public: 82 SymbolCache(NativeSession &Session, DbiStream *Dbi); 83 84 template <typename ConcreteSymbolT, typename... Args> 85 SymIndexId createSymbol(Args &&... ConstructorArgs) { 86 SymIndexId Id = Cache.size(); 87 88 // Initial construction must not access the cache, since it must be done 89 // atomically. 90 auto Result = std::make_unique<ConcreteSymbolT>( 91 Session, Id, std::forward<Args>(ConstructorArgs)...); 92 Result->SymbolId = Id; 93 94 NativeRawSymbol *NRS = static_cast<NativeRawSymbol *>(Result.get()); 95 Cache.push_back(std::move(Result)); 96 97 // After the item is in the cache, we can do further initialization which 98 // is then allowed to access the cache. 99 NRS->initialize(); 100 return Id; 101 } 102 103 std::unique_ptr<IPDBEnumSymbols> 104 createTypeEnumerator(codeview::TypeLeafKind Kind); 105 106 std::unique_ptr<IPDBEnumSymbols> 107 createTypeEnumerator(std::vector<codeview::TypeLeafKind> Kinds); 108 109 std::unique_ptr<IPDBEnumSymbols> 110 createGlobalsEnumerator(codeview::SymbolKind Kind); 111 112 SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); 113 114 template <typename ConcreteSymbolT, typename... Args> 115 SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI, 116 uint32_t Index, 117 Args &&... ConstructorArgs) { 118 SymIndexId SymId = Cache.size(); 119 std::pair<codeview::TypeIndex, uint32_t> Key{FieldListTI, Index}; 120 auto Result = FieldListMembersToSymbolId.try_emplace(Key, SymId); 121 if (Result.second) 122 SymId = 123 createSymbol<ConcreteSymbolT>(std::forward<Args>(ConstructorArgs)...); 124 else 125 SymId = Result.first->second; 126 return SymId; 127 } 128 129 SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset); 130 131 std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index); 132 uint32_t getNumCompilands() const; 133 134 std::unique_ptr<PDBSymbol> getSymbolById(SymIndexId SymbolId) const; 135 136 NativeRawSymbol &getNativeSymbolById(SymIndexId SymbolId) const; 137 138 template <typename ConcreteT> 139 ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const { 140 return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId)); 141 } 142 }; 143 144 } // namespace pdb 145 } // namespace llvm 146 147 #endif 148