xref: /freebsd/contrib/llvm-project/clang/lib/Serialization/ASTReaderInternals.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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