//===- ASTReaderInternals.h - AST Reader Internals --------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file provides internal definitions used in the AST reader.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
#define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H

#include "MultiOnDiskHashTable.h"
#include "clang/AST/DeclarationName.h"
#include "clang/Basic/LLVM.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/OnDiskHashTable.h"
#include <ctime>
#include <utility>

namespace clang {

class ASTReader;
class FileEntry;
struct HeaderFileInfo;
class HeaderSearch;
class ObjCMethodDecl;
class Module;

namespace serialization {

class ModuleFile;

namespace reader {

class ASTDeclContextNameLookupTraitBase {
protected:
  ASTReader &Reader;
  ModuleFile &F;

public:
  // Maximum number of lookup tables we allow before condensing the tables.
  static const int MaxTables = 4;

  /// The lookup result is a list of global declaration IDs.
  using data_type = SmallVector<GlobalDeclID, 4>;

  struct data_type_builder {
    data_type &Data;
    llvm::DenseSet<GlobalDeclID> Found;

    data_type_builder(data_type &D) : Data(D) {}

    void insert(GlobalDeclID ID) {
      // Just use a linear scan unless we have more than a few IDs.
      if (Found.empty() && !Data.empty()) {
        if (Data.size() <= 4) {
          for (auto I : Data)
            if (I == ID)
              return;
          Data.push_back(ID);
          return;
        }

        // Switch to tracking found IDs in the set.
        Found.insert_range(Data);
      }

      if (Found.insert(ID).second)
        Data.push_back(ID);
    }
  };
  using hash_value_type = unsigned;
  using offset_type = unsigned;
  using file_type = ModuleFile *;

protected:
  explicit ASTDeclContextNameLookupTraitBase(ASTReader &Reader, ModuleFile &F)
      : Reader(Reader), F(F) {}

public:
  static std::pair<unsigned, unsigned>
  ReadKeyDataLength(const unsigned char *&d);

  void ReadDataIntoImpl(const unsigned char *d, unsigned DataLen,
                        data_type_builder &Val);

  static void MergeDataInto(const data_type &From, data_type_builder &To) {
    To.Data.reserve(To.Data.size() + From.size());
    for (GlobalDeclID ID : From)
      To.insert(ID);
  }

  file_type ReadFileRef(const unsigned char *&d);

  DeclarationNameKey ReadKeyBase(const unsigned char *&d);
};

/// Class that performs name lookup into a DeclContext stored
/// in an AST file.
class ASTDeclContextNameLookupTrait : public ASTDeclContextNameLookupTraitBase {
public:
  explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F)
      : ASTDeclContextNameLookupTraitBase(Reader, F) {}

  using external_key_type = DeclarationName;
  using internal_key_type = DeclarationNameKey;

  static bool EqualKey(const internal_key_type &a, const internal_key_type &b) {
    return a == b;
  }

  static hash_value_type ComputeHash(const internal_key_type &Key) {
    return Key.getHash();
  }

  static internal_key_type GetInternalKey(const external_key_type &Name) {
    return Name;
  }

  internal_key_type ReadKey(const unsigned char *d, unsigned);

  void ReadDataInto(internal_key_type, const unsigned char *d,
                    unsigned DataLen, data_type_builder &Val);
};

struct DeclContextLookupTable {
  MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table;
};

class ModuleLocalNameLookupTrait : public ASTDeclContextNameLookupTraitBase {
public:
  explicit ModuleLocalNameLookupTrait(ASTReader &Reader, ModuleFile &F)
      : ASTDeclContextNameLookupTraitBase(Reader, F) {}

  using external_key_type = std::pair<DeclarationName, const Module *>;
  using internal_key_type = std::pair<DeclarationNameKey, unsigned>;

  static bool EqualKey(const internal_key_type &a, const internal_key_type &b) {
    return a == b;
  }

  static hash_value_type ComputeHash(const internal_key_type &Key);
  static internal_key_type GetInternalKey(const external_key_type &Key);

  internal_key_type ReadKey(const unsigned char *d, unsigned);

  void ReadDataInto(internal_key_type, const unsigned char *d, unsigned DataLen,
                    data_type_builder &Val);
};

struct ModuleLocalLookupTable {
  MultiOnDiskHashTable<ModuleLocalNameLookupTrait> Table;
};

using LazySpecializationInfo = GlobalDeclID;

/// Class that performs lookup to specialized decls.
class LazySpecializationInfoLookupTrait {
  ASTReader &Reader;
  ModuleFile &F;

public:
  // Maximum number of lookup tables we allow before condensing the tables.
  static const int MaxTables = 4;

  /// The lookup result is a list of global declaration IDs.
  using data_type = SmallVector<LazySpecializationInfo, 4>;

  struct data_type_builder {
    data_type &Data;
    llvm::DenseSet<LazySpecializationInfo> Found;

    data_type_builder(data_type &D) : Data(D) {}

    void insert(LazySpecializationInfo Info) {
      // Just use a linear scan unless we have more than a few IDs.
      if (Found.empty() && !Data.empty()) {
        if (Data.size() <= 4) {
          for (auto I : Data)
            if (I == Info)
              return;
          Data.push_back(Info);
          return;
        }

        // Switch to tracking found IDs in the set.
        Found.insert_range(Data);
      }

      if (Found.insert(Info).second)
        Data.push_back(Info);
    }
  };
  using hash_value_type = unsigned;
  using offset_type = unsigned;
  using file_type = ModuleFile *;

  using external_key_type = unsigned;
  using internal_key_type = unsigned;

  explicit LazySpecializationInfoLookupTrait(ASTReader &Reader, ModuleFile &F)
      : Reader(Reader), F(F) {}

  static bool EqualKey(const internal_key_type &a, const internal_key_type &b) {
    return a == b;
  }

  static hash_value_type ComputeHash(const internal_key_type &Key) {
    return Key;
  }

  static internal_key_type GetInternalKey(const external_key_type &Name) {
    return Name;
  }

  static std::pair<unsigned, unsigned>
  ReadKeyDataLength(const unsigned char *&d);

  internal_key_type ReadKey(const unsigned char *d, unsigned);

  void ReadDataInto(internal_key_type, const unsigned char *d, unsigned DataLen,
                    data_type_builder &Val);

  static void MergeDataInto(const data_type &From, data_type_builder &To) {
    To.Data.reserve(To.Data.size() + From.size());
    for (LazySpecializationInfo Info : From)
      To.insert(Info);
  }

  file_type ReadFileRef(const unsigned char *&d);
};

struct LazySpecializationInfoLookupTable {
  MultiOnDiskHashTable<LazySpecializationInfoLookupTrait> Table;
};

/// Base class for the trait describing the on-disk hash table for the
/// identifiers in an AST file.
///
/// This class is not useful by itself; rather, it provides common
/// functionality for accessing the on-disk hash table of identifiers
/// in an AST file. Different subclasses customize that functionality
/// based on what information they are interested in. Those subclasses
/// must provide the \c data_type type and the ReadData operation, only.
class ASTIdentifierLookupTraitBase {
public:
  using external_key_type = StringRef;
  using internal_key_type = StringRef;
  using hash_value_type = unsigned;
  using offset_type = unsigned;

  static bool EqualKey(const internal_key_type& a, const internal_key_type& b) {
    return a == b;
  }

  static hash_value_type ComputeHash(const internal_key_type& a);

  static std::pair<unsigned, unsigned>
  ReadKeyDataLength(const unsigned char*& d);

  // This hopefully will just get inlined and removed by the optimizer.
  static const internal_key_type&
  GetInternalKey(const external_key_type& x) { return x; }

  // This hopefully will just get inlined and removed by the optimizer.
  static const external_key_type&
  GetExternalKey(const internal_key_type& x) { return x; }

  static internal_key_type ReadKey(const unsigned char* d, unsigned n);
};

/// Class that performs lookup for an identifier stored in an AST file.
class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase {
  ASTReader &Reader;
  ModuleFile &F;

  // If we know the IdentifierInfo in advance, it is here and we will
  // not build a new one. Used when deserializing information about an
  // identifier that was constructed before the AST file was read.
  IdentifierInfo *KnownII;

  bool hasMacroDefinitionInDependencies = false;

public:
  using data_type = IdentifierInfo *;

  ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F,
                           IdentifierInfo *II = nullptr)
      : Reader(Reader), F(F), KnownII(II) {}

  data_type ReadData(const internal_key_type& k,
                     const unsigned char* d,
                     unsigned DataLen);

  IdentifierID ReadIdentifierID(const unsigned char *d);

  ASTReader &getReader() const { return Reader; }

  bool hasMoreInformationInDependencies() const {
    return hasMacroDefinitionInDependencies;
  }
};

/// The on-disk hash table used to contain information about
/// all of the identifiers in the program.
using ASTIdentifierLookupTable =
    llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>;

/// Class that performs lookup for a selector's entries in the global
/// method pool stored in an AST file.
class ASTSelectorLookupTrait {
  ASTReader &Reader;
  ModuleFile &F;

public:
  struct data_type {
    SelectorID ID;
    unsigned InstanceBits;
    unsigned FactoryBits;
    bool InstanceHasMoreThanOneDecl;
    bool FactoryHasMoreThanOneDecl;
    SmallVector<ObjCMethodDecl *, 2> Instance;
    SmallVector<ObjCMethodDecl *, 2> Factory;
  };

  using external_key_type = Selector;
  using internal_key_type = external_key_type;
  using hash_value_type = unsigned;
  using offset_type = unsigned;

  ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F)
      : Reader(Reader), F(F) {}

  static bool EqualKey(const internal_key_type& a,
                       const internal_key_type& b) {
    return a == b;
  }

  static hash_value_type ComputeHash(Selector Sel);

  static const internal_key_type&
  GetInternalKey(const external_key_type& x) { return x; }

  static std::pair<unsigned, unsigned>
  ReadKeyDataLength(const unsigned char*& d);

  internal_key_type ReadKey(const unsigned char* d, unsigned);
  data_type ReadData(Selector, const unsigned char* d, unsigned DataLen);
};

/// The on-disk hash table used for the global method pool.
using ASTSelectorLookupTable =
    llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>;

/// Trait class used to search the on-disk hash table containing all of
/// the header search information.
///
/// The on-disk hash table contains a mapping from each header path to
/// information about that header (how many times it has been included, its
/// controlling macro, etc.). Note that we actually hash based on the size
/// and mtime, and support "deep" comparisons of file names based on current
/// inode numbers, so that the search can cope with non-normalized path names
/// and symlinks.
class HeaderFileInfoTrait {
  ASTReader &Reader;
  ModuleFile &M;

public:
  using external_key_type = FileEntryRef;

  struct internal_key_type {
    off_t Size;
    time_t ModTime;
    StringRef Filename;
    bool Imported;
  };

  using internal_key_ref = const internal_key_type &;

  using data_type = HeaderFileInfo;
  using hash_value_type = unsigned;
  using offset_type = unsigned;

  HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M)
      : Reader(Reader), M(M) {}

  static hash_value_type ComputeHash(internal_key_ref ikey);
  internal_key_type GetInternalKey(external_key_type ekey);
  bool EqualKey(internal_key_ref a, internal_key_ref b);

  static std::pair<unsigned, unsigned>
  ReadKeyDataLength(const unsigned char*& d);

  static internal_key_type ReadKey(const unsigned char *d, unsigned);

  data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen);

private:
  OptionalFileEntryRef getFile(const internal_key_type &Key);
};

/// The on-disk hash table used for known header files.
using HeaderFileInfoLookupTable =
    llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>;

} // namespace reader

} // namespace serialization

} // namespace clang

#endif // LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
