//===--- APINotesReader.cpp - API Notes Reader ------------------*- 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 implements the \c APINotesReader class that reads source
// API notes data providing additional information about source code as
// a separate input, such as the non-nil/nilable annotations for
// method parameters.
//
//===----------------------------------------------------------------------===//
#include "clang/APINotes/APINotesReader.h"
#include "APINotesFormat.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/OnDiskHashTable.h"

namespace clang {
namespace api_notes {
using namespace llvm::support;

namespace {
/// Deserialize a version tuple.
llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {
  uint8_t NumVersions = (*Data++) & 0x03;

  unsigned Major = endian::readNext<uint32_t, llvm::endianness::little>(Data);
  if (NumVersions == 0)
    return llvm::VersionTuple(Major);

  unsigned Minor = endian::readNext<uint32_t, llvm::endianness::little>(Data);
  if (NumVersions == 1)
    return llvm::VersionTuple(Major, Minor);

  unsigned Subminor =
      endian::readNext<uint32_t, llvm::endianness::little>(Data);
  if (NumVersions == 2)
    return llvm::VersionTuple(Major, Minor, Subminor);

  unsigned Build = endian::readNext<uint32_t, llvm::endianness::little>(Data);
  return llvm::VersionTuple(Major, Minor, Subminor, Build);
}

/// An on-disk hash table whose data is versioned based on the Swift version.
template <typename Derived, typename KeyType, typename UnversionedDataType>
class VersionedTableInfo {
public:
  using internal_key_type = KeyType;
  using external_key_type = KeyType;
  using data_type =
      llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
  using hash_value_type = size_t;
  using offset_type = unsigned;

  internal_key_type GetInternalKey(external_key_type Key) { return Key; }

  external_key_type GetExternalKey(internal_key_type Key) { return Key; }

  static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
    return LHS == RHS;
  }

  static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
    unsigned KeyLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    unsigned DataLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    return {KeyLength, DataLength};
  }

  static data_type ReadData(internal_key_type Key, const uint8_t *Data,
                            unsigned Length) {
    unsigned NumElements =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    data_type Result;
    Result.reserve(NumElements);
    for (unsigned i = 0; i != NumElements; ++i) {
      auto version = ReadVersionTuple(Data);
      const auto *DataBefore = Data;
      (void)DataBefore;
      auto UnversionedData = Derived::readUnversioned(Key, Data);
      assert(Data != DataBefore &&
             "Unversioned data reader didn't move pointer");
      Result.push_back({version, UnversionedData});
    }
    return Result;
  }
};

/// Read serialized CommonEntityInfo.
void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) {
  uint8_t UnavailableBits = *Data++;
  Info.Unavailable = (UnavailableBits >> 1) & 0x01;
  Info.UnavailableInSwift = UnavailableBits & 0x01;
  if ((UnavailableBits >> 2) & 0x01)
    Info.setSwiftPrivate(static_cast<bool>((UnavailableBits >> 3) & 0x01));

  unsigned MsgLength =
      endian::readNext<uint16_t, llvm::endianness::little>(Data);
  Info.UnavailableMsg =
      std::string(reinterpret_cast<const char *>(Data),
                  reinterpret_cast<const char *>(Data) + MsgLength);
  Data += MsgLength;

  unsigned SwiftNameLength =
      endian::readNext<uint16_t, llvm::endianness::little>(Data);
  Info.SwiftName =
      std::string(reinterpret_cast<const char *>(Data),
                  reinterpret_cast<const char *>(Data) + SwiftNameLength);
  Data += SwiftNameLength;
}

/// Read serialized CommonTypeInfo.
void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {
  ReadCommonEntityInfo(Data, Info);

  unsigned SwiftBridgeLength =
      endian::readNext<uint16_t, llvm::endianness::little>(Data);
  if (SwiftBridgeLength > 0) {
    Info.setSwiftBridge(std::string(reinterpret_cast<const char *>(Data),
                                    SwiftBridgeLength - 1));
    Data += SwiftBridgeLength - 1;
  }

  unsigned ErrorDomainLength =
      endian::readNext<uint16_t, llvm::endianness::little>(Data);
  if (ErrorDomainLength > 0) {
    Info.setNSErrorDomain(std::optional<std::string>(std::string(
        reinterpret_cast<const char *>(Data), ErrorDomainLength - 1)));
    Data += ErrorDomainLength - 1;
  }
}

/// Used to deserialize the on-disk identifier table.
class IdentifierTableInfo {
public:
  using internal_key_type = llvm::StringRef;
  using external_key_type = llvm::StringRef;
  using data_type = IdentifierID;
  using hash_value_type = uint32_t;
  using offset_type = unsigned;

  internal_key_type GetInternalKey(external_key_type Key) { return Key; }

  external_key_type GetExternalKey(internal_key_type Key) { return Key; }

  hash_value_type ComputeHash(internal_key_type Key) {
    return llvm::djbHash(Key);
  }

  static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
    return LHS == RHS;
  }

  static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
    unsigned KeyLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    unsigned DataLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    return {KeyLength, DataLength};
  }

  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    return llvm::StringRef(reinterpret_cast<const char *>(Data), Length);
  }

  static data_type ReadData(internal_key_type key, const uint8_t *Data,
                            unsigned Length) {
    return endian::readNext<uint32_t, llvm::endianness::little>(Data);
  }
};

/// Used to deserialize the on-disk Objective-C class table.
class ObjCContextIDTableInfo {
public:
  using internal_key_type = ContextTableKey;
  using external_key_type = internal_key_type;
  using data_type = unsigned;
  using hash_value_type = size_t;
  using offset_type = unsigned;

  internal_key_type GetInternalKey(external_key_type Key) { return Key; }

  external_key_type GetExternalKey(internal_key_type Key) { return Key; }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(Key.hashValue());
  }

  static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
    return LHS == RHS;
  }

  static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
    unsigned KeyLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    unsigned DataLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    return {KeyLength, DataLength};
  }

  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    auto ParentCtxID =
        endian::readNext<uint32_t, llvm::endianness::little>(Data);
    auto ContextKind =
        endian::readNext<uint8_t, llvm::endianness::little>(Data);
    auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    return {ParentCtxID, ContextKind, NameID};
  }

  static data_type ReadData(internal_key_type Key, const uint8_t *Data,
                            unsigned Length) {
    return endian::readNext<uint32_t, llvm::endianness::little>(Data);
  }
};

/// Used to deserialize the on-disk Objective-C property table.
class ObjCContextInfoTableInfo
    : public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
                                ObjCContextInfo> {
public:
  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    return endian::readNext<uint32_t, llvm::endianness::little>(Data);
  }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(llvm::hash_value(Key));
  }

  static ObjCContextInfo readUnversioned(internal_key_type Key,
                                         const uint8_t *&Data) {
    ObjCContextInfo Info;
    ReadCommonTypeInfo(Data, Info);
    uint8_t Payload = *Data++;

    if (Payload & 0x01)
      Info.setHasDesignatedInits(true);
    Payload = Payload >> 1;

    if (Payload & 0x4)
      Info.setDefaultNullability(static_cast<NullabilityKind>(Payload & 0x03));
    Payload >>= 3;

    if (Payload & (1 << 1))
      Info.setSwiftObjCMembers(Payload & 1);
    Payload >>= 2;

    if (Payload & (1 << 1))
      Info.setSwiftImportAsNonGeneric(Payload & 1);

    return Info;
  }
};

/// Read serialized VariableInfo.
void ReadVariableInfo(const uint8_t *&Data, VariableInfo &Info) {
  ReadCommonEntityInfo(Data, Info);
  if (*Data++) {
    Info.setNullabilityAudited(static_cast<NullabilityKind>(*Data));
  }
  ++Data;

  auto TypeLen = endian::readNext<uint16_t, llvm::endianness::little>(Data);
  Info.setType(std::string(Data, Data + TypeLen));
  Data += TypeLen;
}

/// Used to deserialize the on-disk Objective-C property table.
class ObjCPropertyTableInfo
    : public VersionedTableInfo<ObjCPropertyTableInfo,
                                std::tuple<uint32_t, uint32_t, uint8_t>,
                                ObjCPropertyInfo> {
public:
  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    char IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);
    return {ClassID, NameID, IsInstance};
  }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(llvm::hash_value(Key));
  }

  static ObjCPropertyInfo readUnversioned(internal_key_type Key,
                                          const uint8_t *&Data) {
    ObjCPropertyInfo Info;
    ReadVariableInfo(Data, Info);
    uint8_t Flags = *Data++;
    if (Flags & (1 << 0))
      Info.setSwiftImportAsAccessors(Flags & (1 << 1));
    return Info;
  }
};

/// Read serialized ParamInfo.
void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) {
  ReadVariableInfo(Data, Info);

  uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);
  if (auto RawConvention = Payload & 0x7) {
    auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
    Info.setRetainCountConvention(Convention);
  }
  Payload >>= 3;
  if (Payload & 0x01)
    Info.setNoEscape(Payload & 0x02);
  Payload >>= 2;
  assert(Payload == 0 && "Bad API notes");
}

/// Read serialized FunctionInfo.
void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) {
  ReadCommonEntityInfo(Data, Info);

  uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);
  if (auto RawConvention = Payload & 0x7) {
    auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
    Info.setRetainCountConvention(Convention);
  }
  Payload >>= 3;
  Info.NullabilityAudited = Payload & 0x1;
  Payload >>= 1;
  assert(Payload == 0 && "Bad API notes");

  Info.NumAdjustedNullable =
      endian::readNext<uint8_t, llvm::endianness::little>(Data);
  Info.NullabilityPayload =
      endian::readNext<uint64_t, llvm::endianness::little>(Data);

  unsigned NumParams =
      endian::readNext<uint16_t, llvm::endianness::little>(Data);
  while (NumParams > 0) {
    ParamInfo pi;
    ReadParamInfo(Data, pi);
    Info.Params.push_back(pi);
    --NumParams;
  }

  unsigned ResultTypeLen =
      endian::readNext<uint16_t, llvm::endianness::little>(Data);
  Info.ResultType = std::string(Data, Data + ResultTypeLen);
  Data += ResultTypeLen;
}

/// Used to deserialize the on-disk Objective-C method table.
class ObjCMethodTableInfo
    : public VersionedTableInfo<ObjCMethodTableInfo,
                                std::tuple<uint32_t, uint32_t, uint8_t>,
                                ObjCMethodInfo> {
public:
  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    auto SelectorID =
        endian::readNext<uint32_t, llvm::endianness::little>(Data);
    auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);
    return {ClassID, SelectorID, IsInstance};
  }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(llvm::hash_value(Key));
  }

  static ObjCMethodInfo readUnversioned(internal_key_type Key,
                                        const uint8_t *&Data) {
    ObjCMethodInfo Info;
    uint8_t Payload = *Data++;
    Info.RequiredInit = Payload & 0x01;
    Payload >>= 1;
    Info.DesignatedInit = Payload & 0x01;
    Payload >>= 1;

    ReadFunctionInfo(Data, Info);
    return Info;
  }
};

/// Used to deserialize the on-disk Objective-C selector table.
class ObjCSelectorTableInfo {
public:
  using internal_key_type = StoredObjCSelector;
  using external_key_type = internal_key_type;
  using data_type = SelectorID;
  using hash_value_type = unsigned;
  using offset_type = unsigned;

  internal_key_type GetInternalKey(external_key_type Key) { return Key; }

  external_key_type GetExternalKey(internal_key_type Key) { return Key; }

  hash_value_type ComputeHash(internal_key_type Key) {
    return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
  }

  static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
    return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);
  }

  static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
    unsigned KeyLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    unsigned DataLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    return {KeyLength, DataLength};
  }

  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    internal_key_type Key;
    Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(Data);
    unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
    for (unsigned i = 0; i != NumIdents; ++i) {
      Key.Identifiers.push_back(
          endian::readNext<uint32_t, llvm::endianness::little>(Data));
    }
    return Key;
  }

  static data_type ReadData(internal_key_type Key, const uint8_t *Data,
                            unsigned Length) {
    return endian::readNext<uint32_t, llvm::endianness::little>(Data);
  }
};

/// Used to deserialize the on-disk global variable table.
class GlobalVariableTableInfo
    : public VersionedTableInfo<GlobalVariableTableInfo, ContextTableKey,
                                GlobalVariableInfo> {
public:
  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    auto ContextKind =
        endian::readNext<uint8_t, llvm::endianness::little>(Data);
    auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    return {CtxID, ContextKind, NameID};
  }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(Key.hashValue());
  }

  static GlobalVariableInfo readUnversioned(internal_key_type Key,
                                            const uint8_t *&Data) {
    GlobalVariableInfo Info;
    ReadVariableInfo(Data, Info);
    return Info;
  }
};

/// Used to deserialize the on-disk global function table.
class GlobalFunctionTableInfo
    : public VersionedTableInfo<GlobalFunctionTableInfo, ContextTableKey,
                                GlobalFunctionInfo> {
public:
  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    auto ContextKind =
        endian::readNext<uint8_t, llvm::endianness::little>(Data);
    auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    return {CtxID, ContextKind, NameID};
  }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(Key.hashValue());
  }

  static GlobalFunctionInfo readUnversioned(internal_key_type Key,
                                            const uint8_t *&Data) {
    GlobalFunctionInfo Info;
    ReadFunctionInfo(Data, Info);
    return Info;
  }
};

/// Used to deserialize the on-disk enumerator table.
class EnumConstantTableInfo
    : public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
                                EnumConstantInfo> {
public:
  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    return NameID;
  }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(llvm::hash_value(Key));
  }

  static EnumConstantInfo readUnversioned(internal_key_type Key,
                                          const uint8_t *&Data) {
    EnumConstantInfo Info;
    ReadCommonEntityInfo(Data, Info);
    return Info;
  }
};

/// Used to deserialize the on-disk tag table.
class TagTableInfo
    : public VersionedTableInfo<TagTableInfo, ContextTableKey, TagInfo> {
public:
  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    auto ContextKind =
        endian::readNext<uint8_t, llvm::endianness::little>(Data);
    auto NameID =
        endian::readNext<IdentifierID, llvm::endianness::little>(Data);
    return {CtxID, ContextKind, NameID};
  }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(Key.hashValue());
  }

  static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {
    TagInfo Info;

    uint8_t Payload = *Data++;
    if (Payload & 1)
      Info.setFlagEnum(Payload & 2);
    Payload >>= 2;
    if (Payload > 0)
      Info.EnumExtensibility =
          static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);

    uint8_t Copyable =
        endian::readNext<uint8_t, llvm::endianness::little>(Data);
    if (Copyable == kSwiftNonCopyable)
      Info.setSwiftCopyable(std::optional(false));
    else if (Copyable == kSwiftCopyable)
      Info.setSwiftCopyable(std::optional(true));

    unsigned ImportAsLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    if (ImportAsLength > 0) {
      Info.SwiftImportAs =
          std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1);
      Data += ImportAsLength - 1;
    }
    unsigned RetainOpLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    if (RetainOpLength > 0) {
      Info.SwiftRetainOp =
          std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1);
      Data += RetainOpLength - 1;
    }
    unsigned ReleaseOpLength =
        endian::readNext<uint16_t, llvm::endianness::little>(Data);
    if (ReleaseOpLength > 0) {
      Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data),
                                        ReleaseOpLength - 1);
      Data += ReleaseOpLength - 1;
    }

    ReadCommonTypeInfo(Data, Info);
    return Info;
  }
};

/// Used to deserialize the on-disk typedef table.
class TypedefTableInfo
    : public VersionedTableInfo<TypedefTableInfo, ContextTableKey,
                                TypedefInfo> {
public:
  static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
    auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
    auto ContextKind =
        endian::readNext<uint8_t, llvm::endianness::little>(Data);
    auto nameID =
        endian::readNext<IdentifierID, llvm::endianness::little>(Data);
    return {CtxID, ContextKind, nameID};
  }

  hash_value_type ComputeHash(internal_key_type Key) {
    return static_cast<size_t>(Key.hashValue());
  }

  static TypedefInfo readUnversioned(internal_key_type Key,
                                     const uint8_t *&Data) {
    TypedefInfo Info;

    uint8_t Payload = *Data++;
    if (Payload > 0)
      Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);

    ReadCommonTypeInfo(Data, Info);
    return Info;
  }
};
} // end anonymous namespace

class APINotesReader::Implementation {
public:
  /// The input buffer for the API notes data.
  llvm::MemoryBuffer *InputBuffer;

  /// The Swift version to use for filtering.
  llvm::VersionTuple SwiftVersion;

  /// The name of the module that we read from the control block.
  std::string ModuleName;

  // The size and modification time of the source file from
  // which this API notes file was created, if known.
  std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime;

  using SerializedIdentifierTable =
      llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;

  /// The identifier table.
  std::unique_ptr<SerializedIdentifierTable> IdentifierTable;

  using SerializedObjCContextIDTable =
      llvm::OnDiskIterableChainedHashTable<ObjCContextIDTableInfo>;

  /// The Objective-C context ID table.
  std::unique_ptr<SerializedObjCContextIDTable> ObjCContextIDTable;

  using SerializedObjCContextInfoTable =
      llvm::OnDiskIterableChainedHashTable<ObjCContextInfoTableInfo>;

  /// The Objective-C context info table.
  std::unique_ptr<SerializedObjCContextInfoTable> ObjCContextInfoTable;

  using SerializedObjCPropertyTable =
      llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;

  /// The Objective-C property table.
  std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;

  using SerializedObjCMethodTable =
      llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;

  /// The Objective-C method table.
  std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;

  using SerializedObjCSelectorTable =
      llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;

  /// The Objective-C selector table.
  std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;

  using SerializedGlobalVariableTable =
      llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;

  /// The global variable table.
  std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;

  using SerializedGlobalFunctionTable =
      llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;

  /// The global function table.
  std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;

  using SerializedEnumConstantTable =
      llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;

  /// The enumerator table.
  std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;

  using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;

  /// The tag table.
  std::unique_ptr<SerializedTagTable> TagTable;

  using SerializedTypedefTable =
      llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;

  /// The typedef table.
  std::unique_ptr<SerializedTypedefTable> TypedefTable;

  /// Retrieve the identifier ID for the given string, or an empty
  /// optional if the string is unknown.
  std::optional<IdentifierID> getIdentifier(llvm::StringRef Str);

  /// Retrieve the selector ID for the given selector, or an empty
  /// optional if the string is unknown.
  std::optional<SelectorID> getSelector(ObjCSelectorRef Selector);

  bool readControlBlock(llvm::BitstreamCursor &Cursor,
                        llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,
                           llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readObjCContextBlock(llvm::BitstreamCursor &Cursor,
                            llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
                             llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
                           llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor,
                             llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,
                               llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
                               llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor,
                             llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readTagBlock(llvm::BitstreamCursor &Cursor,
                    llvm::SmallVectorImpl<uint64_t> &Scratch);
  bool readTypedefBlock(llvm::BitstreamCursor &Cursor,
                        llvm::SmallVectorImpl<uint64_t> &Scratch);
};

std::optional<IdentifierID>
APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) {
  if (!IdentifierTable)
    return std::nullopt;

  if (Str.empty())
    return IdentifierID(0);

  auto Known = IdentifierTable->find(Str);
  if (Known == IdentifierTable->end())
    return std::nullopt;

  return *Known;
}

std::optional<SelectorID>
APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) {
  if (!ObjCSelectorTable || !IdentifierTable)
    return std::nullopt;

  // Translate the identifiers.
  StoredObjCSelector Key;
  Key.NumArgs = Selector.NumArgs;
  for (auto Ident : Selector.Identifiers) {
    if (auto IdentID = getIdentifier(Ident)) {
      Key.Identifiers.push_back(*IdentID);
    } else {
      return std::nullopt;
    }
  }

  auto Known = ObjCSelectorTable->find(Key);
  if (Known == ObjCSelectorTable->end())
    return std::nullopt;

  return *Known;
}

bool APINotesReader::Implementation::readControlBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID))
    return true;

  bool SawMetadata = false;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();

  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown metadata sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();

    switch (Kind) {
    case control_block::METADATA:
      // Already saw metadata.
      if (SawMetadata)
        return true;

      if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)
        return true;

      SawMetadata = true;
      break;

    case control_block::MODULE_NAME:
      ModuleName = BlobData.str();
      break;

    case control_block::MODULE_OPTIONS:
      break;

    case control_block::SOURCE_FILE:
      SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
      break;

    default:
      // Unknown metadata record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return !SawMetadata;
}

bool APINotesReader::Implementation::readIdentifierBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();

  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case identifier_block::IDENTIFIER_DATA: {
      // Already saw identifier table.
      if (IdentifierTable)
        return true;

      uint32_t tableOffset;
      identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      IdentifierTable.reset(SerializedIdentifierTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readObjCContextBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();

  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case objc_context_block::OBJC_CONTEXT_ID_DATA: {
      // Already saw Objective-C context ID table.
      if (ObjCContextIDTable)
        return true;

      uint32_t tableOffset;
      objc_context_block::ObjCContextIDLayout::readRecord(Scratch, tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      ObjCContextIDTable.reset(SerializedObjCContextIDTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    case objc_context_block::OBJC_CONTEXT_INFO_DATA: {
      // Already saw Objective-C context info table.
      if (ObjCContextInfoTable)
        return true;

      uint32_t tableOffset;
      objc_context_block::ObjCContextInfoLayout::readRecord(Scratch,
                                                            tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      ObjCContextInfoTable.reset(SerializedObjCContextInfoTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readObjCPropertyBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();

  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case objc_property_block::OBJC_PROPERTY_DATA: {
      // Already saw Objective-C property table.
      if (ObjCPropertyTable)
        return true;

      uint32_t tableOffset;
      objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,
                                                              tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readObjCMethodBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();
  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case objc_method_block::OBJC_METHOD_DATA: {
      // Already saw Objective-C method table.
      if (ObjCMethodTable)
        return true;

      uint32_t tableOffset;
      objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      ObjCMethodTable.reset(SerializedObjCMethodTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readObjCSelectorBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();
  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case objc_selector_block::OBJC_SELECTOR_DATA: {
      // Already saw Objective-C selector table.
      if (ObjCSelectorTable)
        return true;

      uint32_t tableOffset;
      objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,
                                                              tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readGlobalVariableBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();
  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case global_variable_block::GLOBAL_VARIABLE_DATA: {
      // Already saw global variable table.
      if (GlobalVariableTable)
        return true;

      uint32_t tableOffset;
      global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,
                                                                  tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readGlobalFunctionBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();
  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case global_function_block::GLOBAL_FUNCTION_DATA: {
      // Already saw global function table.
      if (GlobalFunctionTable)
        return true;

      uint32_t tableOffset;
      global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,
                                                                  tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readEnumConstantBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();
  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case enum_constant_block::ENUM_CONSTANT_DATA: {
      // Already saw enumerator table.
      if (EnumConstantTable)
        return true;

      uint32_t tableOffset;
      enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,
                                                              tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      EnumConstantTable.reset(SerializedEnumConstantTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readTagBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(TAG_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();
  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case tag_block::TAG_DATA: {
      // Already saw tag table.
      if (TagTable)
        return true;

      uint32_t tableOffset;
      tag_block::TagDataLayout::readRecord(Scratch, tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      TagTable.reset(SerializedTagTable::Create(base + tableOffset,
                                                base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

bool APINotesReader::Implementation::readTypedefBlock(
    llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
  if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID))
    return true;

  llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
  if (!MaybeNext) {
    // FIXME this drops the error on the floor.
    consumeError(MaybeNext.takeError());
    return false;
  }
  llvm::BitstreamEntry Next = MaybeNext.get();
  while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
    if (Next.Kind == llvm::BitstreamEntry::Error)
      return true;

    if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
      // Unknown sub-block, possibly for use by a future version of the
      // API notes format.
      if (Cursor.SkipBlock())
        return true;

      MaybeNext = Cursor.advance();
      if (!MaybeNext) {
        // FIXME this drops the error on the floor.
        consumeError(MaybeNext.takeError());
        return false;
      }
      Next = MaybeNext.get();
      continue;
    }

    Scratch.clear();
    llvm::StringRef BlobData;
    llvm::Expected<unsigned> MaybeKind =
        Cursor.readRecord(Next.ID, Scratch, &BlobData);
    if (!MaybeKind) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeKind.takeError());
      return false;
    }
    unsigned Kind = MaybeKind.get();
    switch (Kind) {
    case typedef_block::TYPEDEF_DATA: {
      // Already saw typedef table.
      if (TypedefTable)
        return true;

      uint32_t tableOffset;
      typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);
      auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

      TypedefTable.reset(SerializedTypedefTable::Create(
          base + tableOffset, base + sizeof(uint32_t), base));
      break;
    }

    default:
      // Unknown record, possibly for use by a future version of the
      // module format.
      break;
    }

    MaybeNext = Cursor.advance();
    if (!MaybeNext) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeNext.takeError());
      return false;
    }
    Next = MaybeNext.get();
  }

  return false;
}

APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
                               llvm::VersionTuple SwiftVersion, bool &Failed)
    : Implementation(new class Implementation) {
  Failed = false;

  // Initialize the input buffer.
  Implementation->InputBuffer = InputBuffer;
  Implementation->SwiftVersion = SwiftVersion;
  llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);

  // Validate signature.
  for (auto byte : API_NOTES_SIGNATURE) {
    if (Cursor.AtEndOfStream()) {
      Failed = true;
      return;
    }
    if (llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead =
            Cursor.Read(8)) {
      if (maybeRead.get() != byte) {
        Failed = true;
        return;
      }
    } else {
      // FIXME this drops the error on the floor.
      consumeError(maybeRead.takeError());
      Failed = true;
      return;
    }
  }

  // Look at all of the blocks.
  bool HasValidControlBlock = false;
  llvm::SmallVector<uint64_t, 64> Scratch;
  while (!Cursor.AtEndOfStream()) {
    llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();
    if (!MaybeTopLevelEntry) {
      // FIXME this drops the error on the floor.
      consumeError(MaybeTopLevelEntry.takeError());
      Failed = true;
      return;
    }
    llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();

    if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
      break;

    switch (TopLevelEntry.ID) {
    case llvm::bitc::BLOCKINFO_BLOCK_ID:
      if (!Cursor.ReadBlockInfoBlock()) {
        Failed = true;
        break;
      }
      break;

    case CONTROL_BLOCK_ID:
      // Only allow a single control block.
      if (HasValidControlBlock ||
          Implementation->readControlBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }

      HasValidControlBlock = true;
      break;

    case IDENTIFIER_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readIdentifierBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    case OBJC_CONTEXT_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readObjCContextBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }

      break;

    case OBJC_PROPERTY_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    case OBJC_METHOD_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readObjCMethodBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    case OBJC_SELECTOR_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    case GLOBAL_VARIABLE_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    case GLOBAL_FUNCTION_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    case ENUM_CONSTANT_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readEnumConstantBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    case TAG_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readTagBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    case TYPEDEF_BLOCK_ID:
      if (!HasValidControlBlock ||
          Implementation->readTypedefBlock(Cursor, Scratch)) {
        Failed = true;
        return;
      }
      break;

    default:
      // Unknown top-level block, possibly for use by a future version of the
      // module format.
      if (Cursor.SkipBlock()) {
        Failed = true;
        return;
      }
      break;
    }
  }

  if (!Cursor.AtEndOfStream()) {
    Failed = true;
    return;
  }
}

APINotesReader::~APINotesReader() { delete Implementation->InputBuffer; }

std::unique_ptr<APINotesReader>
APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
                       llvm::VersionTuple SwiftVersion) {
  bool Failed = false;
  std::unique_ptr<APINotesReader> Reader(
      new APINotesReader(InputBuffer.release(), SwiftVersion, Failed));
  if (Failed)
    return nullptr;

  return Reader;
}

template <typename T>
APINotesReader::VersionedInfo<T>::VersionedInfo(
    llvm::VersionTuple Version,
    llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)
    : Results(std::move(R)) {

  assert(!Results.empty());
  assert(std::is_sorted(
      Results.begin(), Results.end(),
      [](const std::pair<llvm::VersionTuple, T> &left,
         const std::pair<llvm::VersionTuple, T> &right) -> bool {
        assert(left.first != right.first && "two entries for the same version");
        return left.first < right.first;
      }));

  Selected = std::nullopt;
  for (unsigned i = 0, n = Results.size(); i != n; ++i) {
    if (!Version.empty() && Results[i].first >= Version) {
      // If the current version is "4", then entries for 4 are better than
      // entries for 5, but both are valid. Because entries are sorted, we get
      // that behavior by picking the first match.
      Selected = i;
      break;
    }
  }

  // If we didn't find a match but we have an unversioned result, use the
  // unversioned result. This will always be the first entry because we encode
  // it as version 0.
  if (!Selected && Results[0].first.empty())
    Selected = 0;
}

auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
    -> std::optional<ContextID> {
  if (!Implementation->ObjCContextIDTable)
    return std::nullopt;

  std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
  if (!ClassID)
    return std::nullopt;

  // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
  // context.
  auto KnownID = Implementation->ObjCContextIDTable->find(
      ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
  if (KnownID == Implementation->ObjCContextIDTable->end())
    return std::nullopt;

  return ContextID(*KnownID);
}

auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
    -> VersionedInfo<ObjCContextInfo> {
  if (!Implementation->ObjCContextInfoTable)
    return std::nullopt;

  std::optional<ContextID> CtxID = lookupObjCClassID(Name);
  if (!CtxID)
    return std::nullopt;

  auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
  if (KnownInfo == Implementation->ObjCContextInfoTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *KnownInfo};
}

auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)
    -> std::optional<ContextID> {
  if (!Implementation->ObjCContextIDTable)
    return std::nullopt;

  std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
  if (!classID)
    return std::nullopt;

  // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
  // context.
  auto KnownID = Implementation->ObjCContextIDTable->find(
      ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
  if (KnownID == Implementation->ObjCContextIDTable->end())
    return std::nullopt;

  return ContextID(*KnownID);
}

auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)
    -> VersionedInfo<ObjCContextInfo> {
  if (!Implementation->ObjCContextInfoTable)
    return std::nullopt;

  std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
  if (!CtxID)
    return std::nullopt;

  auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
  if (KnownInfo == Implementation->ObjCContextInfoTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *KnownInfo};
}

auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,
                                        bool IsInstance)
    -> VersionedInfo<ObjCPropertyInfo> {
  if (!Implementation->ObjCPropertyTable)
    return std::nullopt;

  std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name);
  if (!PropertyID)
    return std::nullopt;

  auto Known = Implementation->ObjCPropertyTable->find(
      std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance));
  if (Known == Implementation->ObjCPropertyTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *Known};
}

auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
                                      bool IsInstanceMethod)
    -> VersionedInfo<ObjCMethodInfo> {
  if (!Implementation->ObjCMethodTable)
    return std::nullopt;

  std::optional<SelectorID> SelID = Implementation->getSelector(Selector);
  if (!SelID)
    return std::nullopt;

  auto Known = Implementation->ObjCMethodTable->find(
      ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
                                             IsInstanceMethod});
  if (Known == Implementation->ObjCMethodTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *Known};
}

auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name,
                                          std::optional<Context> Ctx)
    -> VersionedInfo<GlobalVariableInfo> {
  if (!Implementation->GlobalVariableTable)
    return std::nullopt;

  std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
  if (!NameID)
    return std::nullopt;

  ContextTableKey Key(Ctx, *NameID);

  auto Known = Implementation->GlobalVariableTable->find(Key);
  if (Known == Implementation->GlobalVariableTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *Known};
}

auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,
                                          std::optional<Context> Ctx)
    -> VersionedInfo<GlobalFunctionInfo> {
  if (!Implementation->GlobalFunctionTable)
    return std::nullopt;

  std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
  if (!NameID)
    return std::nullopt;

  ContextTableKey Key(Ctx, *NameID);

  auto Known = Implementation->GlobalFunctionTable->find(Key);
  if (Known == Implementation->GlobalFunctionTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *Known};
}

auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
    -> VersionedInfo<EnumConstantInfo> {
  if (!Implementation->EnumConstantTable)
    return std::nullopt;

  std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
  if (!NameID)
    return std::nullopt;

  auto Known = Implementation->EnumConstantTable->find(*NameID);
  if (Known == Implementation->EnumConstantTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *Known};
}

auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
    -> VersionedInfo<TagInfo> {
  if (!Implementation->TagTable)
    return std::nullopt;

  std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
  if (!NameID)
    return std::nullopt;

  ContextTableKey Key(Ctx, *NameID);

  auto Known = Implementation->TagTable->find(Key);
  if (Known == Implementation->TagTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *Known};
}

auto APINotesReader::lookupTypedef(llvm::StringRef Name,
                                   std::optional<Context> Ctx)
    -> VersionedInfo<TypedefInfo> {
  if (!Implementation->TypedefTable)
    return std::nullopt;

  std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
  if (!NameID)
    return std::nullopt;

  ContextTableKey Key(Ctx, *NameID);

  auto Known = Implementation->TypedefTable->find(Key);
  if (Known == Implementation->TypedefTable->end())
    return std::nullopt;

  return {Implementation->SwiftVersion, *Known};
}

auto APINotesReader::lookupNamespaceID(
    llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
    -> std::optional<ContextID> {
  if (!Implementation->ObjCContextIDTable)
    return std::nullopt;

  std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
  if (!NamespaceID)
    return std::nullopt;

  uint32_t RawParentNamespaceID =
      ParentNamespaceID ? ParentNamespaceID->Value : -1;
  auto KnownID = Implementation->ObjCContextIDTable->find(
      {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
  if (KnownID == Implementation->ObjCContextIDTable->end())
    return std::nullopt;

  return ContextID(*KnownID);
}

} // namespace api_notes
} // namespace clang
