10b57cec5SDimitry Andric //===- ASTReaderInternals.h - AST Reader Internals --------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file provides internal definitions used in the AST reader. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H 140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "MultiOnDiskHashTable.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclarationName.h" 180b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 190b57cec5SDimitry Andric #include "clang/Serialization/ASTBitCodes.h" 200b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 220b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 230b57cec5SDimitry Andric #include "llvm/Support/OnDiskHashTable.h" 240b57cec5SDimitry Andric #include <ctime> 250b57cec5SDimitry Andric #include <utility> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric namespace clang { 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric class ASTReader; 300b57cec5SDimitry Andric class FileEntry; 310b57cec5SDimitry Andric struct HeaderFileInfo; 320b57cec5SDimitry Andric class HeaderSearch; 330b57cec5SDimitry Andric class ObjCMethodDecl; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric namespace serialization { 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric class ModuleFile; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric namespace reader { 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric /// Class that performs name lookup into a DeclContext stored 420b57cec5SDimitry Andric /// in an AST file. 430b57cec5SDimitry Andric class ASTDeclContextNameLookupTrait { 440b57cec5SDimitry Andric ASTReader &Reader; 450b57cec5SDimitry Andric ModuleFile &F; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric public: 480b57cec5SDimitry Andric // Maximum number of lookup tables we allow before condensing the tables. 490b57cec5SDimitry Andric static const int MaxTables = 4; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric /// The lookup result is a list of global declaration IDs. 52*0fca6ea1SDimitry Andric using data_type = SmallVector<GlobalDeclID, 4>; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric struct data_type_builder { 550b57cec5SDimitry Andric data_type &Data; 56*0fca6ea1SDimitry Andric llvm::DenseSet<GlobalDeclID> Found; 570b57cec5SDimitry Andric data_type_builderdata_type_builder580b57cec5SDimitry Andric data_type_builder(data_type &D) : Data(D) {} 590b57cec5SDimitry Andric insertdata_type_builder60*0fca6ea1SDimitry Andric void insert(GlobalDeclID ID) { 610b57cec5SDimitry Andric // Just use a linear scan unless we have more than a few IDs. 620b57cec5SDimitry Andric if (Found.empty() && !Data.empty()) { 630b57cec5SDimitry Andric if (Data.size() <= 4) { 640b57cec5SDimitry Andric for (auto I : Found) 650b57cec5SDimitry Andric if (I == ID) 660b57cec5SDimitry Andric return; 670b57cec5SDimitry Andric Data.push_back(ID); 680b57cec5SDimitry Andric return; 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric // Switch to tracking found IDs in the set. 720b57cec5SDimitry Andric Found.insert(Data.begin(), Data.end()); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric if (Found.insert(ID).second) 760b57cec5SDimitry Andric Data.push_back(ID); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric }; 790b57cec5SDimitry Andric using hash_value_type = unsigned; 800b57cec5SDimitry Andric using offset_type = unsigned; 810b57cec5SDimitry Andric using file_type = ModuleFile *; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric using external_key_type = DeclarationName; 840b57cec5SDimitry Andric using internal_key_type = DeclarationNameKey; 850b57cec5SDimitry Andric ASTDeclContextNameLookupTrait(ASTReader & Reader,ModuleFile & F)860b57cec5SDimitry Andric explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F) 870b57cec5SDimitry Andric : Reader(Reader), F(F) {} 880b57cec5SDimitry Andric EqualKey(const internal_key_type & a,const internal_key_type & b)890b57cec5SDimitry Andric static bool EqualKey(const internal_key_type &a, const internal_key_type &b) { 900b57cec5SDimitry Andric return a == b; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric ComputeHash(const internal_key_type & Key)930b57cec5SDimitry Andric static hash_value_type ComputeHash(const internal_key_type &Key) { 940b57cec5SDimitry Andric return Key.getHash(); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric GetInternalKey(const external_key_type & Name)970b57cec5SDimitry Andric static internal_key_type GetInternalKey(const external_key_type &Name) { 980b57cec5SDimitry Andric return Name; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric static std::pair<unsigned, unsigned> 1020b57cec5SDimitry Andric ReadKeyDataLength(const unsigned char *&d); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric internal_key_type ReadKey(const unsigned char *d, unsigned); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric void ReadDataInto(internal_key_type, const unsigned char *d, 1070b57cec5SDimitry Andric unsigned DataLen, data_type_builder &Val); 1080b57cec5SDimitry Andric MergeDataInto(const data_type & From,data_type_builder & To)1090b57cec5SDimitry Andric static void MergeDataInto(const data_type &From, data_type_builder &To) { 1100b57cec5SDimitry Andric To.Data.reserve(To.Data.size() + From.size()); 111*0fca6ea1SDimitry Andric for (GlobalDeclID ID : From) 1120b57cec5SDimitry Andric To.insert(ID); 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric file_type ReadFileRef(const unsigned char *&d); 1160b57cec5SDimitry Andric }; 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric struct DeclContextLookupTable { 1190b57cec5SDimitry Andric MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table; 1200b57cec5SDimitry Andric }; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /// Base class for the trait describing the on-disk hash table for the 1230b57cec5SDimitry Andric /// identifiers in an AST file. 1240b57cec5SDimitry Andric /// 1250b57cec5SDimitry Andric /// This class is not useful by itself; rather, it provides common 1260b57cec5SDimitry Andric /// functionality for accessing the on-disk hash table of identifiers 1270b57cec5SDimitry Andric /// in an AST file. Different subclasses customize that functionality 1280b57cec5SDimitry Andric /// based on what information they are interested in. Those subclasses 1290b57cec5SDimitry Andric /// must provide the \c data_type type and the ReadData operation, only. 1300b57cec5SDimitry Andric class ASTIdentifierLookupTraitBase { 1310b57cec5SDimitry Andric public: 1320b57cec5SDimitry Andric using external_key_type = StringRef; 1330b57cec5SDimitry Andric using internal_key_type = StringRef; 1340b57cec5SDimitry Andric using hash_value_type = unsigned; 1350b57cec5SDimitry Andric using offset_type = unsigned; 1360b57cec5SDimitry Andric EqualKey(const internal_key_type & a,const internal_key_type & b)1370b57cec5SDimitry Andric static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { 1380b57cec5SDimitry Andric return a == b; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric static hash_value_type ComputeHash(const internal_key_type& a); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric static std::pair<unsigned, unsigned> 1440b57cec5SDimitry Andric ReadKeyDataLength(const unsigned char*& d); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric // This hopefully will just get inlined and removed by the optimizer. 1470b57cec5SDimitry Andric static const internal_key_type& GetInternalKey(const external_key_type & x)1480b57cec5SDimitry Andric GetInternalKey(const external_key_type& x) { return x; } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric // This hopefully will just get inlined and removed by the optimizer. 1510b57cec5SDimitry Andric static const external_key_type& GetExternalKey(const internal_key_type & x)1520b57cec5SDimitry Andric GetExternalKey(const internal_key_type& x) { return x; } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric static internal_key_type ReadKey(const unsigned char* d, unsigned n); 1550b57cec5SDimitry Andric }; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric /// Class that performs lookup for an identifier stored in an AST file. 1580b57cec5SDimitry Andric class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase { 1590b57cec5SDimitry Andric ASTReader &Reader; 1600b57cec5SDimitry Andric ModuleFile &F; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // If we know the IdentifierInfo in advance, it is here and we will 1630b57cec5SDimitry Andric // not build a new one. Used when deserializing information about an 1640b57cec5SDimitry Andric // identifier that was constructed before the AST file was read. 1650b57cec5SDimitry Andric IdentifierInfo *KnownII; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric public: 1680b57cec5SDimitry Andric using data_type = IdentifierInfo *; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F, 1710b57cec5SDimitry Andric IdentifierInfo *II = nullptr) Reader(Reader)1720b57cec5SDimitry Andric : Reader(Reader), F(F), KnownII(II) {} 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric data_type ReadData(const internal_key_type& k, 1750b57cec5SDimitry Andric const unsigned char* d, 1760b57cec5SDimitry Andric unsigned DataLen); 1770b57cec5SDimitry Andric 178*0fca6ea1SDimitry Andric IdentifierID ReadIdentifierID(const unsigned char *d); 1790b57cec5SDimitry Andric getReader()1800b57cec5SDimitry Andric ASTReader &getReader() const { return Reader; } 1810b57cec5SDimitry Andric }; 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric /// The on-disk hash table used to contain information about 1840b57cec5SDimitry Andric /// all of the identifiers in the program. 1850b57cec5SDimitry Andric using ASTIdentifierLookupTable = 1860b57cec5SDimitry Andric llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric /// Class that performs lookup for a selector's entries in the global 1890b57cec5SDimitry Andric /// method pool stored in an AST file. 1900b57cec5SDimitry Andric class ASTSelectorLookupTrait { 1910b57cec5SDimitry Andric ASTReader &Reader; 1920b57cec5SDimitry Andric ModuleFile &F; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric public: 1950b57cec5SDimitry Andric struct data_type { 1960b57cec5SDimitry Andric SelectorID ID; 1970b57cec5SDimitry Andric unsigned InstanceBits; 1980b57cec5SDimitry Andric unsigned FactoryBits; 1990b57cec5SDimitry Andric bool InstanceHasMoreThanOneDecl; 2000b57cec5SDimitry Andric bool FactoryHasMoreThanOneDecl; 2010b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 2> Instance; 2020b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 2> Factory; 2030b57cec5SDimitry Andric }; 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric using external_key_type = Selector; 2060b57cec5SDimitry Andric using internal_key_type = external_key_type; 2070b57cec5SDimitry Andric using hash_value_type = unsigned; 2080b57cec5SDimitry Andric using offset_type = unsigned; 2090b57cec5SDimitry Andric ASTSelectorLookupTrait(ASTReader & Reader,ModuleFile & F)2100b57cec5SDimitry Andric ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F) 2110b57cec5SDimitry Andric : Reader(Reader), F(F) {} 2120b57cec5SDimitry Andric EqualKey(const internal_key_type & a,const internal_key_type & b)2130b57cec5SDimitry Andric static bool EqualKey(const internal_key_type& a, 2140b57cec5SDimitry Andric const internal_key_type& b) { 2150b57cec5SDimitry Andric return a == b; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric static hash_value_type ComputeHash(Selector Sel); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric static const internal_key_type& GetInternalKey(const external_key_type & x)2210b57cec5SDimitry Andric GetInternalKey(const external_key_type& x) { return x; } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric static std::pair<unsigned, unsigned> 2240b57cec5SDimitry Andric ReadKeyDataLength(const unsigned char*& d); 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric internal_key_type ReadKey(const unsigned char* d, unsigned); 2270b57cec5SDimitry Andric data_type ReadData(Selector, const unsigned char* d, unsigned DataLen); 2280b57cec5SDimitry Andric }; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric /// The on-disk hash table used for the global method pool. 2310b57cec5SDimitry Andric using ASTSelectorLookupTable = 2320b57cec5SDimitry Andric llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>; 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric /// Trait class used to search the on-disk hash table containing all of 2350b57cec5SDimitry Andric /// the header search information. 2360b57cec5SDimitry Andric /// 2370b57cec5SDimitry Andric /// The on-disk hash table contains a mapping from each header path to 2380b57cec5SDimitry Andric /// information about that header (how many times it has been included, its 2390b57cec5SDimitry Andric /// controlling macro, etc.). Note that we actually hash based on the size 2400b57cec5SDimitry Andric /// and mtime, and support "deep" comparisons of file names based on current 2410b57cec5SDimitry Andric /// inode numbers, so that the search can cope with non-normalized path names 2420b57cec5SDimitry Andric /// and symlinks. 2430b57cec5SDimitry Andric class HeaderFileInfoTrait { 2440b57cec5SDimitry Andric ASTReader &Reader; 2450b57cec5SDimitry Andric ModuleFile &M; 2460b57cec5SDimitry Andric HeaderSearch *HS; 2470b57cec5SDimitry Andric const char *FrameworkStrings; 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric public: 2505f757f3fSDimitry Andric using external_key_type = FileEntryRef; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric struct internal_key_type { 2530b57cec5SDimitry Andric off_t Size; 2540b57cec5SDimitry Andric time_t ModTime; 2550b57cec5SDimitry Andric StringRef Filename; 2560b57cec5SDimitry Andric bool Imported; 2570b57cec5SDimitry Andric }; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric using internal_key_ref = const internal_key_type &; 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric using data_type = HeaderFileInfo; 2620b57cec5SDimitry Andric using hash_value_type = unsigned; 2630b57cec5SDimitry Andric using offset_type = unsigned; 2640b57cec5SDimitry Andric HeaderFileInfoTrait(ASTReader & Reader,ModuleFile & M,HeaderSearch * HS,const char * FrameworkStrings)2650b57cec5SDimitry Andric HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS, 2660b57cec5SDimitry Andric const char *FrameworkStrings) 2670b57cec5SDimitry Andric : Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) {} 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric static hash_value_type ComputeHash(internal_key_ref ikey); 2705f757f3fSDimitry Andric internal_key_type GetInternalKey(external_key_type ekey); 2710b57cec5SDimitry Andric bool EqualKey(internal_key_ref a, internal_key_ref b); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric static std::pair<unsigned, unsigned> 2740b57cec5SDimitry Andric ReadKeyDataLength(const unsigned char*& d); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric static internal_key_type ReadKey(const unsigned char *d, unsigned); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen); 27906c3fb27SDimitry Andric 28006c3fb27SDimitry Andric private: 28106c3fb27SDimitry Andric const FileEntry *getFile(const internal_key_type &Key); 2820b57cec5SDimitry Andric }; 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric /// The on-disk hash table used for known header files. 2850b57cec5SDimitry Andric using HeaderFileInfoLookupTable = 2860b57cec5SDimitry Andric llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>; 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric } // namespace reader 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric } // namespace serialization 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric } // namespace clang 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H 295