1 //===--- ASTReaderInternals.h - AST Reader Internals ------------*- 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 // This file provides internal definitions used in the AST reader. 11 // 12 //===----------------------------------------------------------------------===// 13 #ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H 14 #define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H 15 16 #include "clang/AST/DeclarationName.h" 17 #include "clang/Serialization/ASTBitCodes.h" 18 #include "llvm/ADT/DenseSet.h" 19 #include "llvm/ADT/PointerUnion.h" 20 #include "llvm/ADT/TinyPtrVector.h" 21 #include "llvm/Support/Endian.h" 22 #include "llvm/Support/OnDiskHashTable.h" 23 #include "MultiOnDiskHashTable.h" 24 #include <utility> 25 26 namespace clang { 27 28 class ASTReader; 29 class HeaderSearch; 30 struct HeaderFileInfo; 31 class FileEntry; 32 33 namespace serialization { 34 35 class ModuleFile; 36 37 namespace reader { 38 39 /// \brief Class that performs name lookup into a DeclContext stored 40 /// in an AST file. 41 class ASTDeclContextNameLookupTrait { 42 ASTReader &Reader; 43 ModuleFile &F; 44 45 public: 46 // Maximum number of lookup tables we allow before condensing the tables. 47 static const int MaxTables = 4; 48 49 /// The lookup result is a list of global declaration IDs. 50 typedef llvm::SmallVector<DeclID, 4> data_type; 51 struct data_type_builder { 52 data_type &Data; 53 llvm::DenseSet<DeclID> Found; 54 55 data_type_builder(data_type &D) : Data(D) {} 56 void insert(DeclID ID) { 57 // Just use a linear scan unless we have more than a few IDs. 58 if (Found.empty() && !Data.empty()) { 59 if (Data.size() <= 4) { 60 for (auto I : Found) 61 if (I == ID) 62 return; 63 Data.push_back(ID); 64 return; 65 } 66 67 // Switch to tracking found IDs in the set. 68 Found.insert(Data.begin(), Data.end()); 69 } 70 71 if (Found.insert(ID).second) 72 Data.push_back(ID); 73 } 74 }; 75 typedef unsigned hash_value_type; 76 typedef unsigned offset_type; 77 typedef ModuleFile *file_type; 78 79 typedef DeclarationName external_key_type; 80 typedef DeclarationNameKey internal_key_type; 81 82 explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F) 83 : Reader(Reader), F(F) { } 84 85 static bool EqualKey(const internal_key_type &a, const internal_key_type &b) { 86 return a == b; 87 } 88 89 static hash_value_type ComputeHash(const internal_key_type &Key) { 90 return Key.getHash(); 91 } 92 static internal_key_type GetInternalKey(const external_key_type &Name) { 93 return Name; 94 } 95 96 static std::pair<unsigned, unsigned> 97 ReadKeyDataLength(const unsigned char *&d); 98 99 internal_key_type ReadKey(const unsigned char *d, unsigned); 100 101 void ReadDataInto(internal_key_type, const unsigned char *d, 102 unsigned DataLen, data_type_builder &Val); 103 104 static void MergeDataInto(const data_type &From, data_type_builder &To) { 105 To.Data.reserve(To.Data.size() + From.size()); 106 for (DeclID ID : From) 107 To.insert(ID); 108 } 109 110 file_type ReadFileRef(const unsigned char *&d); 111 }; 112 113 struct DeclContextLookupTable { 114 MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table; 115 116 // These look redundant, but don't remove them -- they work around MSVC 2013's 117 // inability to synthesize move operations. Without them, the 118 // MultiOnDiskHashTable will be copied (despite being move-only!). 119 DeclContextLookupTable() : Table() {} 120 DeclContextLookupTable(DeclContextLookupTable &&O) 121 : Table(std::move(O.Table)) {} 122 DeclContextLookupTable &operator=(DeclContextLookupTable &&O) { 123 Table = std::move(O.Table); 124 return *this; 125 } 126 }; 127 128 /// \brief Base class for the trait describing the on-disk hash table for the 129 /// identifiers in an AST file. 130 /// 131 /// This class is not useful by itself; rather, it provides common 132 /// functionality for accessing the on-disk hash table of identifiers 133 /// in an AST file. Different subclasses customize that functionality 134 /// based on what information they are interested in. Those subclasses 135 /// must provide the \c data_type typedef and the ReadData operation, 136 /// only. 137 class ASTIdentifierLookupTraitBase { 138 public: 139 typedef StringRef external_key_type; 140 typedef StringRef internal_key_type; 141 typedef unsigned hash_value_type; 142 typedef unsigned offset_type; 143 144 static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { 145 return a == b; 146 } 147 148 static hash_value_type ComputeHash(const internal_key_type& a); 149 150 static std::pair<unsigned, unsigned> 151 ReadKeyDataLength(const unsigned char*& d); 152 153 // This hopefully will just get inlined and removed by the optimizer. 154 static const internal_key_type& 155 GetInternalKey(const external_key_type& x) { return x; } 156 157 // This hopefully will just get inlined and removed by the optimizer. 158 static const external_key_type& 159 GetExternalKey(const internal_key_type& x) { return x; } 160 161 static internal_key_type ReadKey(const unsigned char* d, unsigned n); 162 }; 163 164 /// \brief Class that performs lookup for an identifier stored in an AST file. 165 class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase { 166 ASTReader &Reader; 167 ModuleFile &F; 168 169 // If we know the IdentifierInfo in advance, it is here and we will 170 // not build a new one. Used when deserializing information about an 171 // identifier that was constructed before the AST file was read. 172 IdentifierInfo *KnownII; 173 174 public: 175 typedef IdentifierInfo * data_type; 176 177 ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F, 178 IdentifierInfo *II = nullptr) 179 : Reader(Reader), F(F), KnownII(II) { } 180 181 data_type ReadData(const internal_key_type& k, 182 const unsigned char* d, 183 unsigned DataLen); 184 185 IdentID ReadIdentifierID(const unsigned char *d); 186 187 ASTReader &getReader() const { return Reader; } 188 }; 189 190 /// \brief The on-disk hash table used to contain information about 191 /// all of the identifiers in the program. 192 typedef llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait> 193 ASTIdentifierLookupTable; 194 195 /// \brief Class that performs lookup for a selector's entries in the global 196 /// method pool stored in an AST file. 197 class ASTSelectorLookupTrait { 198 ASTReader &Reader; 199 ModuleFile &F; 200 201 public: 202 struct data_type { 203 SelectorID ID; 204 unsigned InstanceBits; 205 unsigned FactoryBits; 206 bool InstanceHasMoreThanOneDecl; 207 bool FactoryHasMoreThanOneDecl; 208 SmallVector<ObjCMethodDecl *, 2> Instance; 209 SmallVector<ObjCMethodDecl *, 2> Factory; 210 }; 211 212 typedef Selector external_key_type; 213 typedef external_key_type internal_key_type; 214 typedef unsigned hash_value_type; 215 typedef unsigned offset_type; 216 217 ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F) 218 : Reader(Reader), F(F) { } 219 220 static bool EqualKey(const internal_key_type& a, 221 const internal_key_type& b) { 222 return a == b; 223 } 224 225 static hash_value_type ComputeHash(Selector Sel); 226 227 static const internal_key_type& 228 GetInternalKey(const external_key_type& x) { return x; } 229 230 static std::pair<unsigned, unsigned> 231 ReadKeyDataLength(const unsigned char*& d); 232 233 internal_key_type ReadKey(const unsigned char* d, unsigned); 234 data_type ReadData(Selector, const unsigned char* d, unsigned DataLen); 235 }; 236 237 /// \brief The on-disk hash table used for the global method pool. 238 typedef llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait> 239 ASTSelectorLookupTable; 240 241 /// \brief Trait class used to search the on-disk hash table containing all of 242 /// the header search information. 243 /// 244 /// The on-disk hash table contains a mapping from each header path to 245 /// information about that header (how many times it has been included, its 246 /// controlling macro, etc.). Note that we actually hash based on the size 247 /// and mtime, and support "deep" comparisons of file names based on current 248 /// inode numbers, so that the search can cope with non-normalized path names 249 /// and symlinks. 250 class HeaderFileInfoTrait { 251 ASTReader &Reader; 252 ModuleFile &M; 253 HeaderSearch *HS; 254 const char *FrameworkStrings; 255 256 public: 257 typedef const FileEntry *external_key_type; 258 259 struct internal_key_type { 260 off_t Size; 261 time_t ModTime; 262 const char *Filename; 263 bool Imported; 264 }; 265 typedef const internal_key_type &internal_key_ref; 266 267 typedef HeaderFileInfo data_type; 268 typedef unsigned hash_value_type; 269 typedef unsigned offset_type; 270 271 HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS, 272 const char *FrameworkStrings) 273 : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) { } 274 275 static hash_value_type ComputeHash(internal_key_ref ikey); 276 internal_key_type GetInternalKey(const FileEntry *FE); 277 bool EqualKey(internal_key_ref a, internal_key_ref b); 278 279 static std::pair<unsigned, unsigned> 280 ReadKeyDataLength(const unsigned char*& d); 281 282 static internal_key_type ReadKey(const unsigned char *d, unsigned); 283 284 data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen); 285 }; 286 287 /// \brief The on-disk hash table used for known header files. 288 typedef llvm::OnDiskChainedHashTable<HeaderFileInfoTrait> 289 HeaderFileInfoLookupTable; 290 291 } // end namespace clang::serialization::reader 292 } // end namespace clang::serialization 293 } // end namespace clang 294 295 296 #endif 297