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