Line data Source code
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 :
56 0 : SymIndexId createSymbolPlaceholder() {
57 0 : SymIndexId Id = Cache.size();
58 0 : Cache.push_back(nullptr);
59 0 : return Id;
60 : }
61 :
62 : template <typename ConcreteSymbolT, typename CVRecordT, typename... Args>
63 323 : SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT,
64 : Args &&... ConstructorArgs) {
65 : CVRecordT Record;
66 646 : if (auto EC =
67 : codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) {
68 0 : consumeError(std::move(EC));
69 : return 0;
70 : }
71 :
72 : return createSymbol<ConcreteSymbolT>(
73 323 : TI, std::move(Record), std::forward<Args>(ConstructorArgs)...);
74 : }
75 0 :
76 : SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
77 : codeview::CVType CVT);
78 0 :
79 : SymIndexId createSimpleType(codeview::TypeIndex TI,
80 0 : codeview::ModifierOptions Mods);
81 :
82 : public:
83 : SymbolCache(NativeSession &Session, DbiStream *Dbi);
84 :
85 0 : template <typename ConcreteSymbolT, typename... Args>
86 183 : SymIndexId createSymbol(Args &&... ConstructorArgs) {
87 269 : SymIndexId Id = Cache.size();
88 :
89 : // Initial construction must not access the cache, since it must be done
90 172 : // atomically.
91 183 : auto Result = llvm::make_unique<ConcreteSymbolT>(
92 0 : Session, Id, std::forward<Args>(ConstructorArgs)...);
93 183 : Result->SymbolId = Id;
94 :
95 : NativeRawSymbol *NRS = static_cast<NativeRawSymbol *>(Result.get());
96 183 : Cache.push_back(std::move(Result));
97 86 :
98 : // After the item is in the cache, we can do further initialization which
99 36 : // is then allowed to access the cache.
100 183 : NRS->initialize();
101 183 : return Id;
102 72 : }
103 :
104 0 : std::unique_ptr<IPDBEnumSymbols>
105 : createTypeEnumerator(codeview::TypeLeafKind Kind);
106 :
107 : std::unique_ptr<IPDBEnumSymbols>
108 : createTypeEnumerator(std::vector<codeview::TypeLeafKind> Kinds);
109 36 :
110 : std::unique_ptr<IPDBEnumSymbols>
111 73 : createGlobalsEnumerator(codeview::SymbolKind Kind);
112 :
113 : SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
114 146 :
115 : template <typename ConcreteSymbolT, typename... Args>
116 178 : SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
117 : uint32_t Index,
118 : Args &&... ConstructorArgs) {
119 356 : SymIndexId SymId = Cache.size();
120 : std::pair<codeview::TypeIndex, uint32_t> Key{FieldListTI, Index};
121 251 : auto Result = FieldListMembersToSymbolId.try_emplace(Key, SymId);
122 178 : if (Result.second)
123 168 : SymId =
124 : createSymbol<ConcreteSymbolT>(std::forward<Args>(ConstructorArgs)...);
125 : else
126 16 : SymId = Result.first->second;
127 178 : return SymId;
128 0 : }
129 :
130 : SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
131 :
132 : std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
133 2 : uint32_t getNumCompilands() const;
134 :
135 74 : std::unique_ptr<PDBSymbol> getSymbolById(SymIndexId SymbolId) const;
136 :
137 : NativeRawSymbol &getNativeSymbolById(SymIndexId SymbolId) const;
138 148 :
139 : template <typename ConcreteT>
140 0 : ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const {
141 197 : return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId));
142 : }
143 : };
144 :
145 74 : } // namespace pdb
146 : } // namespace llvm
147 2 :
148 : #endif
|