//===-- APINotesWriter.cpp - API Notes Writer -------------------*- 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
//
//===----------------------------------------------------------------------===//

#include "clang/APINotes/APINotesWriter.h"
#include "APINotesFormat.h"
#include "clang/APINotes/Types.h"
#include "clang/Basic/FileManager.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/VersionTuple.h"

namespace clang {
namespace api_notes {
class APINotesWriter::Implementation {
  friend class APINotesWriter;

  template <typename T>
  using VersionedSmallVector =
      llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1>;

  std::string ModuleName;
  const FileEntry *SourceFile;

  /// Scratch space for bitstream writing.
  llvm::SmallVector<uint64_t, 64> Scratch;

  /// Mapping from strings to identifier IDs.
  llvm::StringMap<IdentifierID> IdentifierIDs;

  /// Information about contexts (Objective-C classes or protocols or C++
  /// namespaces).
  ///
  /// Indexed by the parent context ID, context kind and the identifier ID of
  /// this context and provides both the context ID and information describing
  /// the context within that module.
  llvm::DenseMap<ContextTableKey,
                 std::pair<unsigned, VersionedSmallVector<ContextInfo>>>
      Contexts;

  /// Information about parent contexts for each context.
  ///
  /// Indexed by context ID, provides the parent context ID.
  llvm::DenseMap<uint32_t, uint32_t> ParentContexts;

  /// Mapping from context IDs to the identifier ID holding the name.
  llvm::DenseMap<unsigned, unsigned> ContextNames;

  /// Information about Objective-C properties.
  ///
  /// Indexed by the context ID, property name, and whether this is an
  /// instance property.
  llvm::DenseMap<
      std::tuple<unsigned, unsigned, char>,
      llvm::SmallVector<std::pair<VersionTuple, ObjCPropertyInfo>, 1>>
      ObjCProperties;

  /// Information about C record fields.
  ///
  /// Indexed by the context ID and name ID.
  llvm::DenseMap<SingleDeclTableKey,
                 llvm::SmallVector<std::pair<VersionTuple, FieldInfo>, 1>>
      Fields;

  /// Information about Objective-C methods.
  ///
  /// Indexed by the context ID, selector ID, and Boolean (stored as a char)
  /// indicating whether this is a class or instance method.
  llvm::DenseMap<std::tuple<unsigned, unsigned, char>,
                 llvm::SmallVector<std::pair<VersionTuple, ObjCMethodInfo>, 1>>
      ObjCMethods;

  /// Information about C++ methods.
  ///
  /// Indexed by the context ID and name ID.
  llvm::DenseMap<SingleDeclTableKey,
                 llvm::SmallVector<std::pair<VersionTuple, CXXMethodInfo>, 1>>
      CXXMethods;

  /// Mapping from selectors to selector ID.
  llvm::DenseMap<StoredObjCSelector, SelectorID> SelectorIDs;

  /// Information about global variables.
  ///
  /// Indexed by the context ID, identifier ID.
  llvm::DenseMap<
      SingleDeclTableKey,
      llvm::SmallVector<std::pair<VersionTuple, GlobalVariableInfo>, 1>>
      GlobalVariables;

  /// Information about global functions.
  ///
  /// Indexed by the context ID, identifier ID.
  llvm::DenseMap<
      SingleDeclTableKey,
      llvm::SmallVector<std::pair<VersionTuple, GlobalFunctionInfo>, 1>>
      GlobalFunctions;

  /// Information about enumerators.
  ///
  /// Indexed by the identifier ID.
  llvm::DenseMap<
      unsigned, llvm::SmallVector<std::pair<VersionTuple, EnumConstantInfo>, 1>>
      EnumConstants;

  /// Information about tags.
  ///
  /// Indexed by the context ID, identifier ID.
  llvm::DenseMap<SingleDeclTableKey,
                 llvm::SmallVector<std::pair<VersionTuple, TagInfo>, 1>>
      Tags;

  /// Information about typedefs.
  ///
  /// Indexed by the context ID, identifier ID.
  llvm::DenseMap<SingleDeclTableKey,
                 llvm::SmallVector<std::pair<VersionTuple, TypedefInfo>, 1>>
      Typedefs;

  /// Retrieve the ID for the given identifier.
  IdentifierID getIdentifier(StringRef Identifier) {
    if (Identifier.empty())
      return 0;

    // Add to the identifier table if missing.
    return IdentifierIDs.try_emplace(Identifier, IdentifierIDs.size() + 1)
        .first->second;
  }

  /// Retrieve the ID for the given selector.
  SelectorID getSelector(ObjCSelectorRef SelectorRef) {
    // Translate the selector reference into a stored selector.
    StoredObjCSelector Selector;
    Selector.NumArgs = SelectorRef.NumArgs;
    Selector.Identifiers.reserve(SelectorRef.Identifiers.size());
    for (auto piece : SelectorRef.Identifiers)
      Selector.Identifiers.push_back(getIdentifier(piece));

    // Look for the stored selector.  Add to the selector table if missing.
    return SelectorIDs.try_emplace(Selector, SelectorIDs.size()).first->second;
  }

private:
  void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
  void writeControlBlock(llvm::BitstreamWriter &Stream);
  void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
  void writeContextBlock(llvm::BitstreamWriter &Stream);
  void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
  void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
  void writeCXXMethodBlock(llvm::BitstreamWriter &Stream);
  void writeFieldBlock(llvm::BitstreamWriter &Stream);
  void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
  void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream);
  void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream);
  void writeEnumConstantBlock(llvm::BitstreamWriter &Stream);
  void writeTagBlock(llvm::BitstreamWriter &Stream);
  void writeTypedefBlock(llvm::BitstreamWriter &Stream);

public:
  Implementation(llvm::StringRef ModuleName, const FileEntry *SF)
      : ModuleName(std::string(ModuleName)), SourceFile(SF) {}

  void writeToStream(llvm::raw_ostream &OS);
};

void APINotesWriter::Implementation::writeToStream(llvm::raw_ostream &OS) {
  llvm::SmallVector<char, 0> Buffer;

  {
    llvm::BitstreamWriter Stream(Buffer);

    // Emit the signature.
    for (unsigned char Byte : API_NOTES_SIGNATURE)
      Stream.Emit(Byte, 8);

    // Emit the blocks.
    writeBlockInfoBlock(Stream);
    writeControlBlock(Stream);
    writeIdentifierBlock(Stream);
    writeContextBlock(Stream);
    writeObjCPropertyBlock(Stream);
    writeObjCMethodBlock(Stream);
    writeCXXMethodBlock(Stream);
    writeFieldBlock(Stream);
    writeObjCSelectorBlock(Stream);
    writeGlobalVariableBlock(Stream);
    writeGlobalFunctionBlock(Stream);
    writeEnumConstantBlock(Stream);
    writeTagBlock(Stream);
    writeTypedefBlock(Stream);
  }

  OS.write(Buffer.data(), Buffer.size());
  OS.flush();
}

namespace {
/// Record the name of a block.
void emitBlockID(llvm::BitstreamWriter &Stream, unsigned ID,
                 llvm::StringRef Name) {
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
                    llvm::ArrayRef<unsigned>{ID});

  // Emit the block name if present.
  if (Name.empty())
    return;
  Stream.EmitRecord(
      llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
      llvm::ArrayRef<unsigned char>(
          const_cast<unsigned char *>(
              reinterpret_cast<const unsigned char *>(Name.data())),
          Name.size()));
}

/// Record the name of a record within a block.
void emitRecordID(llvm::BitstreamWriter &Stream, unsigned ID,
                  llvm::StringRef Name) {
  assert(ID < 256 && "can't fit record ID in next to name");

  llvm::SmallVector<unsigned char, 64> Buffer;
  Buffer.resize(Name.size() + 1);
  Buffer[0] = ID;
  memcpy(Buffer.data() + 1, Name.data(), Name.size());

  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer);
}
} // namespace

void APINotesWriter::Implementation::writeBlockInfoBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);

#define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block)
#define BLOCK_RECORD(NameSpace, Block)                                         \
  emitRecordID(Stream, NameSpace::Block, #Block)
  BLOCK(CONTROL_BLOCK);
  BLOCK_RECORD(control_block, METADATA);
  BLOCK_RECORD(control_block, MODULE_NAME);

  BLOCK(IDENTIFIER_BLOCK);
  BLOCK_RECORD(identifier_block, IDENTIFIER_DATA);

  BLOCK(OBJC_CONTEXT_BLOCK);
  BLOCK_RECORD(context_block, CONTEXT_ID_DATA);

  BLOCK(OBJC_PROPERTY_BLOCK);
  BLOCK_RECORD(objc_property_block, OBJC_PROPERTY_DATA);

  BLOCK(OBJC_METHOD_BLOCK);
  BLOCK_RECORD(objc_method_block, OBJC_METHOD_DATA);

  BLOCK(OBJC_SELECTOR_BLOCK);
  BLOCK_RECORD(objc_selector_block, OBJC_SELECTOR_DATA);

  BLOCK(GLOBAL_VARIABLE_BLOCK);
  BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA);

  BLOCK(GLOBAL_FUNCTION_BLOCK);
  BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA);
#undef BLOCK_RECORD
#undef BLOCK
}

void APINotesWriter::Implementation::writeControlBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, CONTROL_BLOCK_ID, 3);

  control_block::MetadataLayout Metadata(Stream);
  Metadata.emit(Scratch, VERSION_MAJOR, VERSION_MINOR);

  control_block::ModuleNameLayout ModuleName(Stream);
  ModuleName.emit(Scratch, this->ModuleName);

  if (SourceFile) {
    control_block::SourceFileLayout SourceFile(Stream);
    SourceFile.emit(Scratch, this->SourceFile->getSize(),
                    this->SourceFile->getModificationTime());
  }
}

namespace {
/// Used to serialize the on-disk identifier table.
class IdentifierTableInfo {
public:
  using key_type = StringRef;
  using key_type_ref = key_type;
  using data_type = IdentifierID;
  using data_type_ref = const data_type &;
  using hash_value_type = uint32_t;
  using offset_type = unsigned;

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

  std::pair<unsigned, unsigned>
  EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
    uint32_t KeyLength = Key.size();
    uint32_t DataLength = sizeof(uint32_t);

    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint16_t>(KeyLength);
    writer.write<uint16_t>(DataLength);
    return {KeyLength, DataLength};
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { OS << Key; }

  void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Data);
  }
};
} // namespace

void APINotesWriter::Implementation::writeIdentifierBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII restoreBlock(Stream, IDENTIFIER_BLOCK_ID, 3);

  if (IdentifierIDs.empty())
    return;

  llvm::SmallString<4096> HashTableBlob;
  uint32_t Offset;
  {
    llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo> Generator;
    for (auto &II : IdentifierIDs)
      Generator.insert(II.first(), II.second);

    llvm::raw_svector_ostream BlobStream(HashTableBlob);
    // Make sure that no bucket is at offset 0
    llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                           llvm::endianness::little);
    Offset = Generator.Emit(BlobStream);
  }

  identifier_block::IdentifierDataLayout IdentifierData(Stream);
  IdentifierData.emit(Scratch, Offset, HashTableBlob);
}

namespace {
/// Used to serialize the on-disk Objective-C context table.
class ContextIDTableInfo {
public:
  using key_type = ContextTableKey;
  using key_type_ref = key_type;
  using data_type = unsigned;
  using data_type_ref = const data_type &;
  using hash_value_type = size_t;
  using offset_type = unsigned;

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

  std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref,
                                                  data_type_ref) {
    uint32_t KeyLength = sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
    uint32_t DataLength = sizeof(uint32_t);

    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint16_t>(KeyLength);
    writer.write<uint16_t>(DataLength);
    return {KeyLength, DataLength};
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Key.parentContextID);
    writer.write<uint8_t>(Key.contextKind);
    writer.write<uint32_t>(Key.contextID);
  }

  void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Data);
  }
};

/// Localized helper to make a type dependent, thwarting template argument
/// deduction.
template <typename T> struct MakeDependent { typedef T Type; };

/// Retrieve the serialized size of the given VersionTuple, for use in
/// on-disk hash tables.
unsigned getVersionTupleSize(const VersionTuple &VT) {
  unsigned size = sizeof(uint8_t) + /*major*/ sizeof(uint32_t);
  if (VT.getMinor())
    size += sizeof(uint32_t);
  if (VT.getSubminor())
    size += sizeof(uint32_t);
  if (VT.getBuild())
    size += sizeof(uint32_t);
  return size;
}

/// Determine the size of an array of versioned information,
template <typename T>
unsigned getVersionedInfoSize(
    const llvm::SmallVectorImpl<std::pair<llvm::VersionTuple, T>> &VI,
    llvm::function_ref<unsigned(const typename MakeDependent<T>::Type &)>
        getInfoSize) {
  unsigned result = sizeof(uint16_t); // # of elements
  for (const auto &E : VI) {
    result += getVersionTupleSize(E.first);
    result += getInfoSize(E.second);
  }
  return result;
}

/// Emit a serialized representation of a version tuple.
void emitVersionTuple(raw_ostream &OS, const VersionTuple &VT) {
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);

  // First byte contains the number of components beyond the 'major' component.
  uint8_t descriptor;
  if (VT.getBuild())
    descriptor = 3;
  else if (VT.getSubminor())
    descriptor = 2;
  else if (VT.getMinor())
    descriptor = 1;
  else
    descriptor = 0;
  writer.write<uint8_t>(descriptor);

  // Write the components.
  writer.write<uint32_t>(VT.getMajor());
  if (auto minor = VT.getMinor())
    writer.write<uint32_t>(*minor);
  if (auto subminor = VT.getSubminor())
    writer.write<uint32_t>(*subminor);
  if (auto build = VT.getBuild())
    writer.write<uint32_t>(*build);
}

/// Emit versioned information.
template <typename T>
void emitVersionedInfo(
    raw_ostream &OS, llvm::SmallVectorImpl<std::pair<VersionTuple, T>> &VI,
    llvm::function_ref<void(raw_ostream &,
                            const typename MakeDependent<T>::Type &)>
        emitInfo) {
  std::sort(VI.begin(), VI.end(),
            [](const std::pair<VersionTuple, T> &LHS,
               const std::pair<VersionTuple, T> &RHS) -> bool {
              assert((&LHS == &RHS || LHS.first != RHS.first) &&
                     "two entries for the same version");
              return LHS.first < RHS.first;
            });

  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
  writer.write<uint16_t>(VI.size());
  for (const auto &E : VI) {
    emitVersionTuple(OS, E.first);
    emitInfo(OS, E.second);
  }
}

/// On-disk hash table info key base for handling versioned data.
template <typename Derived, typename KeyType, typename UnversionedDataType>
class VersionedTableInfo {
  Derived &asDerived() { return *static_cast<Derived *>(this); }

  const Derived &asDerived() const {
    return *static_cast<const Derived *>(this);
  }

public:
  using key_type = KeyType;
  using key_type_ref = key_type;
  using data_type =
      llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
  using data_type_ref = data_type &;
  using hash_value_type = size_t;
  using offset_type = unsigned;

  std::pair<unsigned, unsigned>
  EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref Data) {
    uint32_t KeyLength = asDerived().getKeyLength(Key);
    uint32_t DataLength =
        getVersionedInfoSize(Data, [this](const UnversionedDataType &UI) {
          return asDerived().getUnversionedInfoSize(UI);
        });

    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint16_t>(KeyLength);
    writer.write<uint16_t>(DataLength);
    return {KeyLength, DataLength};
  }

  void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
    emitVersionedInfo(
        OS, Data, [this](llvm::raw_ostream &OS, const UnversionedDataType &UI) {
          asDerived().emitUnversionedInfo(OS, UI);
        });
  }
};

/// Emit a serialized representation of the common entity information.
void emitCommonEntityInfo(raw_ostream &OS, const CommonEntityInfo &CEI) {
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);

  uint8_t payload = 0;
  if (auto safety = CEI.getSwiftSafety()) {
    payload = static_cast<unsigned>(*safety);
    payload <<= 1;
    payload |= 0x01;
  }
  payload <<= 2;
  if (auto swiftPrivate = CEI.isSwiftPrivate()) {
    payload |= 0x01;
    if (*swiftPrivate)
      payload |= 0x02;
  }
  payload <<= 1;
  payload |= CEI.Unavailable;
  payload <<= 1;
  payload |= CEI.UnavailableInSwift;

  writer.write<uint8_t>(payload);

  writer.write<uint16_t>(CEI.UnavailableMsg.size());
  OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());

  writer.write<uint16_t>(CEI.SwiftName.size());
  OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
}

/// Retrieve the serialized size of the given CommonEntityInfo, for use in
/// on-disk hash tables.
unsigned getCommonEntityInfoSize(const CommonEntityInfo &CEI) {
  return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
}

// Retrieve the serialized size of the given CommonTypeInfo, for use
// in on-disk hash tables.
unsigned getCommonTypeInfoSize(const CommonTypeInfo &CTI) {
  return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
         (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 2 +
         (CTI.getSwiftConformance() ? CTI.getSwiftConformance()->size() : 0) +
         getCommonEntityInfoSize(CTI);
}

/// Emit a serialized representation of the common type information.
void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
  emitCommonEntityInfo(OS, CTI);

  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
  if (auto swiftBridge = CTI.getSwiftBridge()) {
    writer.write<uint16_t>(swiftBridge->size() + 1);
    OS.write(swiftBridge->c_str(), swiftBridge->size());
  } else {
    writer.write<uint16_t>(0);
  }
  if (auto nsErrorDomain = CTI.getNSErrorDomain()) {
    writer.write<uint16_t>(nsErrorDomain->size() + 1);
    OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
  } else {
    writer.write<uint16_t>(0);
  }
  if (auto conformance = CTI.getSwiftConformance()) {
    writer.write<uint16_t>(conformance->size() + 1);
    OS.write(conformance->c_str(), conformance->size());
  } else {
    writer.write<uint16_t>(0);
  }
}

/// Used to serialize the on-disk Objective-C property table.
class ContextInfoTableInfo
    : public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
public:
  unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Key);
  }

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

  unsigned getUnversionedInfoSize(const ContextInfo &OCI) {
    return getCommonTypeInfoSize(OCI) + 1;
  }

  void emitUnversionedInfo(raw_ostream &OS, const ContextInfo &OCI) {
    emitCommonTypeInfo(OS, OCI);

    uint8_t payload = 0;
    if (auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
      payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
    payload <<= 2;
    if (auto swiftObjCMembers = OCI.getSwiftObjCMembers())
      payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
    payload <<= 3;
    if (auto nullable = OCI.getDefaultNullability())
      payload |= (0x01 << 2) | static_cast<uint8_t>(*nullable);
    payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);

    OS << payload;
  }
};
} // namespace

void APINotesWriter::Implementation::writeContextBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII restoreBlock(Stream, OBJC_CONTEXT_BLOCK_ID, 3);

  if (Contexts.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo> Generator;
      for (auto &OC : Contexts)
        Generator.insert(OC.first, OC.second.first);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    context_block::ContextIDLayout ContextID(Stream);
    ContextID.emit(Scratch, Offset, HashTableBlob);
  }

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo> Generator;
      for (auto &OC : Contexts)
        Generator.insert(OC.second.first, OC.second.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    context_block::ContextInfoLayout ContextInfo(Stream);
    ContextInfo.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
/// Retrieve the serialized size of the given VariableInfo, for use in
/// on-disk hash tables.
unsigned getVariableInfoSize(const VariableInfo &VI) {
  return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
}
unsigned getParamInfoSize(const ParamInfo &PI);

/// Emit a serialized representation of the variable information.
void emitVariableInfo(raw_ostream &OS, const VariableInfo &VI) {
  emitCommonEntityInfo(OS, VI);

  uint8_t bytes[2] = {0, 0};
  if (auto nullable = VI.getNullability()) {
    bytes[0] = 1;
    bytes[1] = static_cast<uint8_t>(*nullable);
  } else {
    // Nothing to do.
  }

  OS.write(reinterpret_cast<const char *>(bytes), 2);

  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
  writer.write<uint16_t>(VI.getType().size());
  OS.write(VI.getType().data(), VI.getType().size());
}

/// Used to serialize the on-disk Objective-C property table.
class ObjCPropertyTableInfo
    : public VersionedTableInfo<ObjCPropertyTableInfo,
                                std::tuple<unsigned, unsigned, char>,
                                ObjCPropertyInfo> {
public:
  unsigned getKeyLength(key_type_ref) {
    return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t);
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(std::get<0>(Key));
    writer.write<uint32_t>(std::get<1>(Key));
    writer.write<uint8_t>(std::get<2>(Key));
  }

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

  unsigned getUnversionedInfoSize(const ObjCPropertyInfo &OPI) {
    return getVariableInfoSize(OPI) + 1;
  }

  void emitUnversionedInfo(raw_ostream &OS, const ObjCPropertyInfo &OPI) {
    emitVariableInfo(OS, OPI);

    uint8_t flags = 0;
    if (auto value = OPI.getSwiftImportAsAccessors()) {
      flags |= 1 << 0;
      flags |= value.value() << 1;
    }
    OS << flags;
  }
};
} // namespace

void APINotesWriter::Implementation::writeObjCPropertyBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, OBJC_PROPERTY_BLOCK_ID, 3);

  if (ObjCProperties.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo> Generator;
      for (auto &OP : ObjCProperties)
        Generator.insert(OP.first, OP.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    objc_property_block::ObjCPropertyDataLayout ObjCPropertyData(Stream);
    ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
unsigned getFunctionInfoSize(const FunctionInfo &);
void emitFunctionInfo(llvm::raw_ostream &, const FunctionInfo &);
void emitParamInfo(raw_ostream &OS, const ParamInfo &PI);

/// Used to serialize the on-disk Objective-C method table.
class ObjCMethodTableInfo
    : public VersionedTableInfo<ObjCMethodTableInfo,
                                std::tuple<unsigned, unsigned, char>,
                                ObjCMethodInfo> {
public:
  unsigned getKeyLength(key_type_ref) {
    return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t);
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(std::get<0>(Key));
    writer.write<uint32_t>(std::get<1>(Key));
    writer.write<uint8_t>(std::get<2>(Key));
  }

  hash_value_type ComputeHash(key_type_ref key) {
    return static_cast<size_t>(llvm::hash_value(key));
  }

  unsigned getUnversionedInfoSize(const ObjCMethodInfo &OMI) {
    auto size = getFunctionInfoSize(OMI) + 1;
    if (OMI.Self)
      size += getParamInfoSize(*OMI.Self);
    return size;
  }

  void emitUnversionedInfo(raw_ostream &OS, const ObjCMethodInfo &OMI) {
    uint8_t flags = 0;
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    flags = (flags << 1) | OMI.DesignatedInit;
    flags = (flags << 1) | OMI.RequiredInit;
    flags = (flags << 1) | static_cast<bool>(OMI.Self);
    writer.write<uint8_t>(flags);

    emitFunctionInfo(OS, OMI);

    if (OMI.Self)
      emitParamInfo(OS, *OMI.Self);
  }
};

/// Used to serialize the on-disk C++ method table.
class CXXMethodTableInfo
    : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
                                CXXMethodInfo> {
public:
  unsigned getKeyLength(key_type_ref) {
    return sizeof(uint32_t) + sizeof(uint32_t);
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Key.parentContextID);
    writer.write<uint32_t>(Key.nameID);
  }

  hash_value_type ComputeHash(key_type_ref key) {
    return static_cast<size_t>(key.hashValue());
  }

  unsigned getUnversionedInfoSize(const CXXMethodInfo &MI) {
    auto size = getFunctionInfoSize(MI) + 1;
    if (MI.This)
      size += getParamInfoSize(*MI.This);
    return size;
  }

  void emitUnversionedInfo(raw_ostream &OS, const CXXMethodInfo &MI) {
    uint8_t flags = 0;
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    flags = (flags << 1) | static_cast<bool>(MI.This);
    writer.write<uint8_t>(flags);

    emitFunctionInfo(OS, MI);
    if (MI.This)
      emitParamInfo(OS, *MI.This);
  }
};
} // namespace

void APINotesWriter::Implementation::writeObjCMethodBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, OBJC_METHOD_BLOCK_ID, 3);

  if (ObjCMethods.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo> Generator;
      for (auto &OM : ObjCMethods)
        Generator.insert(OM.first, OM.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    objc_method_block::ObjCMethodDataLayout ObjCMethodData(Stream);
    ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
  }
}

void APINotesWriter::Implementation::writeCXXMethodBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, CXX_METHOD_BLOCK_ID, 3);

  if (CXXMethods.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo> Generator;
      for (auto &MD : CXXMethods)
        Generator.insert(MD.first, MD.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    cxx_method_block::CXXMethodDataLayout CXXMethodData(Stream);
    CXXMethodData.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
/// Used to serialize the on-disk C field table.
class FieldTableInfo
    : public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
public:
  unsigned getKeyLength(key_type_ref) {
    return sizeof(uint32_t) + sizeof(uint32_t);
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Key.parentContextID);
    writer.write<uint32_t>(Key.nameID);
  }

  hash_value_type ComputeHash(key_type_ref key) {
    return static_cast<size_t>(key.hashValue());
  }

  unsigned getUnversionedInfoSize(const FieldInfo &FI) {
    return getVariableInfoSize(FI);
  }

  void emitUnversionedInfo(raw_ostream &OS, const FieldInfo &FI) {
    emitVariableInfo(OS, FI);
  }
};
} // namespace

void APINotesWriter::Implementation::writeFieldBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, FIELD_BLOCK_ID, 3);

  if (Fields.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<FieldTableInfo> Generator;
      for (auto &FD : Fields)
        Generator.insert(FD.first, FD.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    field_block::FieldDataLayout FieldData(Stream);
    FieldData.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
/// Used to serialize the on-disk Objective-C selector table.
class ObjCSelectorTableInfo {
public:
  using key_type = StoredObjCSelector;
  using key_type_ref = const key_type &;
  using data_type = SelectorID;
  using data_type_ref = data_type;
  using hash_value_type = unsigned;
  using offset_type = unsigned;

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

  std::pair<unsigned, unsigned>
  EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
    uint32_t KeyLength =
        sizeof(uint16_t) + sizeof(uint32_t) * Key.Identifiers.size();
    uint32_t DataLength = sizeof(uint32_t);

    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint16_t>(KeyLength);
    writer.write<uint16_t>(DataLength);
    return {KeyLength, DataLength};
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint16_t>(Key.NumArgs);
    for (auto Identifier : Key.Identifiers)
      writer.write<uint32_t>(Identifier);
  }

  void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Data);
  }
};
} // namespace

void APINotesWriter::Implementation::writeObjCSelectorBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, OBJC_SELECTOR_BLOCK_ID, 3);

  if (SelectorIDs.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo> Generator;
      for (auto &S : SelectorIDs)
        Generator.insert(S.first, S.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    objc_selector_block::ObjCSelectorDataLayout ObjCSelectorData(Stream);
    ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
/// Used to serialize the on-disk global variable table.
class GlobalVariableTableInfo
    : public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
                                GlobalVariableInfo> {
public:
  unsigned getKeyLength(key_type_ref) {
    return sizeof(uint32_t) + sizeof(uint32_t);
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Key.parentContextID);
    writer.write<uint32_t>(Key.nameID);
  }

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

  unsigned getUnversionedInfoSize(const GlobalVariableInfo &GVI) {
    return getVariableInfoSize(GVI);
  }

  void emitUnversionedInfo(raw_ostream &OS, const GlobalVariableInfo &GVI) {
    emitVariableInfo(OS, GVI);
  }
};
} // namespace

void APINotesWriter::Implementation::writeGlobalVariableBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, GLOBAL_VARIABLE_BLOCK_ID, 3);

  if (GlobalVariables.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo> Generator;
      for (auto &GV : GlobalVariables)
        Generator.insert(GV.first, GV.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    global_variable_block::GlobalVariableDataLayout GlobalVariableData(Stream);
    GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
unsigned getParamInfoSize(const ParamInfo &PI) {
  return getVariableInfoSize(PI) + 1;
}

void emitParamInfo(raw_ostream &OS, const ParamInfo &PI) {
  emitVariableInfo(OS, PI);

  uint8_t flags = 0;
  if (auto noescape = PI.isNoEscape()) {
    flags |= 0x01;
    if (*noescape)
      flags |= 0x02;
  }
  flags <<= 2;
  if (auto lifetimebound = PI.isLifetimebound()) {
    flags |= 0x01;
    if (*lifetimebound)
      flags |= 0x02;
  }
  flags <<= 3;
  if (auto RCC = PI.getRetainCountConvention())
    flags |= static_cast<uint8_t>(RCC.value()) + 1;

  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
  writer.write<uint8_t>(flags);
}

/// Retrieve the serialized size of the given FunctionInfo, for use in on-disk
/// hash tables.
unsigned getFunctionInfoSize(const FunctionInfo &FI) {
  unsigned size = getCommonEntityInfoSize(FI) + 2 + sizeof(uint64_t);
  size += sizeof(uint16_t);
  for (const auto &P : FI.Params)
    size += getParamInfoSize(P);
  size += sizeof(uint16_t) + FI.ResultType.size();
  size += sizeof(uint16_t) + FI.SwiftReturnOwnership.size();
  return size;
}

/// Emit a serialized representation of the function information.
void emitFunctionInfo(raw_ostream &OS, const FunctionInfo &FI) {
  emitCommonEntityInfo(OS, FI);

  uint8_t flags = 0;
  flags |= FI.NullabilityAudited;
  flags <<= 3;
  if (auto RCC = FI.getRetainCountConvention())
    flags |= static_cast<uint8_t>(RCC.value()) + 1;

  llvm::support::endian::Writer writer(OS, llvm::endianness::little);

  writer.write<uint8_t>(flags);
  writer.write<uint8_t>(FI.NumAdjustedNullable);
  writer.write<uint64_t>(FI.NullabilityPayload);

  writer.write<uint16_t>(FI.Params.size());
  for (const auto &PI : FI.Params)
    emitParamInfo(OS, PI);

  writer.write<uint16_t>(FI.ResultType.size());
  writer.write(ArrayRef<char>{FI.ResultType});
  writer.write<uint16_t>(FI.SwiftReturnOwnership.size());
  writer.write(ArrayRef<char>{FI.SwiftReturnOwnership});
}

/// Used to serialize the on-disk global function table.
class GlobalFunctionTableInfo
    : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
                                GlobalFunctionInfo> {
public:
  unsigned getKeyLength(key_type_ref) {
    return sizeof(uint32_t) + sizeof(uint32_t);
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Key.parentContextID);
    writer.write<uint32_t>(Key.nameID);
  }

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

  unsigned getUnversionedInfoSize(const GlobalFunctionInfo &GFI) {
    return getFunctionInfoSize(GFI);
  }

  void emitUnversionedInfo(raw_ostream &OS, const GlobalFunctionInfo &GFI) {
    emitFunctionInfo(OS, GFI);
  }
};
} // namespace

void APINotesWriter::Implementation::writeGlobalFunctionBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, GLOBAL_FUNCTION_BLOCK_ID, 3);

  if (GlobalFunctions.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo> Generator;
      for (auto &F : GlobalFunctions)
        Generator.insert(F.first, F.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    global_function_block::GlobalFunctionDataLayout GlobalFunctionData(Stream);
    GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
/// Used to serialize the on-disk global enum constant.
class EnumConstantTableInfo
    : public VersionedTableInfo<EnumConstantTableInfo, unsigned,
                                EnumConstantInfo> {
public:
  unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Key);
  }

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

  unsigned getUnversionedInfoSize(const EnumConstantInfo &ECI) {
    return getCommonEntityInfoSize(ECI);
  }

  void emitUnversionedInfo(raw_ostream &OS, const EnumConstantInfo &ECI) {
    emitCommonEntityInfo(OS, ECI);
  }
};
} // namespace

void APINotesWriter::Implementation::writeEnumConstantBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, ENUM_CONSTANT_BLOCK_ID, 3);

  if (EnumConstants.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo> Generator;
      for (auto &EC : EnumConstants)
        Generator.insert(EC.first, EC.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    enum_constant_block::EnumConstantDataLayout EnumConstantData(Stream);
    EnumConstantData.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
template <typename Derived, typename UnversionedDataType>
class CommonTypeTableInfo
    : public VersionedTableInfo<Derived, SingleDeclTableKey,
                                UnversionedDataType> {
public:
  using key_type_ref = typename CommonTypeTableInfo::key_type_ref;
  using hash_value_type = typename CommonTypeTableInfo::hash_value_type;

  unsigned getKeyLength(key_type_ref) {
    return sizeof(uint32_t) + sizeof(IdentifierID);
  }

  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
    writer.write<uint32_t>(Key.parentContextID);
    writer.write<IdentifierID>(Key.nameID);
  }

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

  unsigned getUnversionedInfoSize(const UnversionedDataType &UDT) {
    return getCommonTypeInfoSize(UDT);
  }

  void emitUnversionedInfo(raw_ostream &OS, const UnversionedDataType &UDT) {
    emitCommonTypeInfo(OS, UDT);
  }
};

/// Used to serialize the on-disk tag table.
class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
public:
  unsigned getUnversionedInfoSize(const TagInfo &TI) {
    // clang-format off
    return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
           2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
           2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
           2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
           2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
           3 + getCommonTypeInfoSize(TI);
    // clang-format on
  }

  void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);

    uint8_t Flags = 0;
    if (auto extensibility = TI.EnumExtensibility) {
      Flags |= static_cast<uint8_t>(extensibility.value()) + 1;
      assert((Flags < (1 << 2)) && "must fit in two bits");
    }

    Flags <<= 2;
    if (auto value = TI.isFlagEnum())
      Flags |= (value.value() << 1 | 1 << 0);

    writer.write<uint8_t>(Flags);

    if (auto Copyable = TI.isSwiftCopyable())
      writer.write<uint8_t>(*Copyable ? kSwiftConforms : kSwiftDoesNotConform);
    else
      writer.write<uint8_t>(0);

    if (auto Escapable = TI.isSwiftEscapable())
      writer.write<uint8_t>(*Escapable ? kSwiftConforms : kSwiftDoesNotConform);
    else
      writer.write<uint8_t>(0);

    if (auto ImportAs = TI.SwiftImportAs) {
      writer.write<uint16_t>(ImportAs->size() + 1);
      OS.write(ImportAs->c_str(), ImportAs->size());
    } else {
      writer.write<uint16_t>(0);
    }
    if (auto RetainOp = TI.SwiftRetainOp) {
      writer.write<uint16_t>(RetainOp->size() + 1);
      OS.write(RetainOp->c_str(), RetainOp->size());
    } else {
      writer.write<uint16_t>(0);
    }
    if (auto ReleaseOp = TI.SwiftReleaseOp) {
      writer.write<uint16_t>(ReleaseOp->size() + 1);
      OS.write(ReleaseOp->c_str(), ReleaseOp->size());
    } else {
      writer.write<uint16_t>(0);
    }
    if (auto DefaultOwnership = TI.SwiftDefaultOwnership) {
      writer.write<uint16_t>(DefaultOwnership->size() + 1);
      OS.write(DefaultOwnership->c_str(), DefaultOwnership->size());
    } else {
      writer.write<uint16_t>(0);
    }
    if (auto DestroyOp = TI.SwiftDestroyOp) {
      writer.write<uint16_t>(DestroyOp->size() + 1);
      OS.write(DestroyOp->c_str(), DestroyOp->size());
    } else {
      writer.write<uint16_t>(0);
    }

    emitCommonTypeInfo(OS, TI);
  }
};
} // namespace

void APINotesWriter::Implementation::writeTagBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, TAG_BLOCK_ID, 3);

  if (Tags.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<TagTableInfo> Generator;
      for (auto &T : Tags)
        Generator.insert(T.first, T.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    tag_block::TagDataLayout TagData(Stream);
    TagData.emit(Scratch, Offset, HashTableBlob);
  }
}

namespace {
/// Used to serialize the on-disk typedef table.
class TypedefTableInfo
    : public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
public:
  unsigned getUnversionedInfoSize(const TypedefInfo &TI) {
    return 1 + getCommonTypeInfoSize(TI);
  }

  void emitUnversionedInfo(raw_ostream &OS, const TypedefInfo &TI) {
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);

    uint8_t Flags = 0;
    if (auto swiftWrapper = TI.SwiftWrapper)
      Flags |= static_cast<uint8_t>(*swiftWrapper) + 1;

    writer.write<uint8_t>(Flags);

    emitCommonTypeInfo(OS, TI);
  }
};
} // namespace

void APINotesWriter::Implementation::writeTypedefBlock(
    llvm::BitstreamWriter &Stream) {
  llvm::BCBlockRAII Scope(Stream, TYPEDEF_BLOCK_ID, 3);

  if (Typedefs.empty())
    return;

  {
    llvm::SmallString<4096> HashTableBlob;
    uint32_t Offset;
    {
      llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo> Generator;
      for (auto &T : Typedefs)
        Generator.insert(T.first, T.second);

      llvm::raw_svector_ostream BlobStream(HashTableBlob);
      // Make sure that no bucket is at offset 0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
                                             llvm::endianness::little);
      Offset = Generator.Emit(BlobStream);
    }

    typedef_block::TypedefDataLayout TypedefData(Stream);
    TypedefData.emit(Scratch, Offset, HashTableBlob);
  }
}

// APINotesWriter

APINotesWriter::APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF)
    : Implementation(new class Implementation(ModuleName, SF)) {}

APINotesWriter::~APINotesWriter() = default;

void APINotesWriter::writeToStream(llvm::raw_ostream &OS) {
  Implementation->writeToStream(OS);
}

ContextID APINotesWriter::addContext(std::optional<ContextID> ParentCtxID,
                                     llvm::StringRef Name, ContextKind Kind,
                                     const ContextInfo &Info,
                                     llvm::VersionTuple SwiftVersion) {
  IdentifierID NameID = Implementation->getIdentifier(Name);

  uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
  ContextTableKey Key(RawParentCtxID, static_cast<uint8_t>(Kind), NameID);
  auto Known = Implementation->Contexts.find(Key);
  if (Known == Implementation->Contexts.end()) {
    unsigned NextID = Implementation->Contexts.size() + 1;

    Implementation::VersionedSmallVector<ContextInfo> EmptyVersionedInfo;
    Known = Implementation->Contexts
                .insert(std::make_pair(
                    Key, std::make_pair(NextID, EmptyVersionedInfo)))
                .first;

    Implementation->ContextNames[NextID] = NameID;
    Implementation->ParentContexts[NextID] = RawParentCtxID;
  }

  // Add this version information.
  auto &VersionedVec = Known->second.second;
  bool Found = false;
  for (auto &Versioned : VersionedVec) {
    if (Versioned.first == SwiftVersion) {
      Versioned.second |= Info;
      Found = true;
      break;
    }
  }

  if (!Found)
    VersionedVec.push_back({SwiftVersion, Info});

  return ContextID(Known->second.first);
}

void APINotesWriter::addObjCProperty(ContextID CtxID, StringRef Name,
                                     bool IsInstanceProperty,
                                     const ObjCPropertyInfo &Info,
                                     VersionTuple SwiftVersion) {
  IdentifierID NameID = Implementation->getIdentifier(Name);
  Implementation
      ->ObjCProperties[std::make_tuple(CtxID.Value, NameID, IsInstanceProperty)]
      .push_back({SwiftVersion, Info});
}

void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
                                   bool IsInstanceMethod,
                                   const ObjCMethodInfo &Info,
                                   VersionTuple SwiftVersion) {
  SelectorID SelID = Implementation->getSelector(Selector);
  auto Key = std::tuple<unsigned, unsigned, char>{CtxID.Value, SelID,
                                                  IsInstanceMethod};
  Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});

  // If this method is a designated initializer, update the class to note that
  // it has designated initializers.
  if (Info.DesignatedInit) {
    assert(Implementation->ParentContexts.contains(CtxID.Value));
    uint32_t ParentCtxID = Implementation->ParentContexts[CtxID.Value];
    ContextTableKey CtxKey(ParentCtxID,
                           static_cast<uint8_t>(ContextKind::ObjCClass),
                           Implementation->ContextNames[CtxID.Value]);
    assert(Implementation->Contexts.contains(CtxKey));
    auto &VersionedVec = Implementation->Contexts[CtxKey].second;
    bool Found = false;
    for (auto &Versioned : VersionedVec) {
      if (Versioned.first == SwiftVersion) {
        Versioned.second.setHasDesignatedInits(true);
        Found = true;
        break;
      }
    }

    if (!Found) {
      VersionedVec.push_back({SwiftVersion, ContextInfo()});
      VersionedVec.back().second.setHasDesignatedInits(true);
    }
  }
}

void APINotesWriter::addCXXMethod(ContextID CtxID, llvm::StringRef Name,
                                  const CXXMethodInfo &Info,
                                  VersionTuple SwiftVersion) {
  IdentifierID NameID = Implementation->getIdentifier(Name);
  SingleDeclTableKey Key(CtxID.Value, NameID);
  Implementation->CXXMethods[Key].push_back({SwiftVersion, Info});
}

void APINotesWriter::addField(ContextID CtxID, llvm::StringRef Name,
                              const FieldInfo &Info,
                              VersionTuple SwiftVersion) {
  IdentifierID NameID = Implementation->getIdentifier(Name);
  SingleDeclTableKey Key(CtxID.Value, NameID);
  Implementation->Fields[Key].push_back({SwiftVersion, Info});
}

void APINotesWriter::addGlobalVariable(std::optional<Context> Ctx,
                                       llvm::StringRef Name,
                                       const GlobalVariableInfo &Info,
                                       VersionTuple SwiftVersion) {
  IdentifierID VariableID = Implementation->getIdentifier(Name);
  SingleDeclTableKey Key(Ctx, VariableID);
  Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
}

void APINotesWriter::addGlobalFunction(std::optional<Context> Ctx,
                                       llvm::StringRef Name,
                                       const GlobalFunctionInfo &Info,
                                       VersionTuple SwiftVersion) {
  IdentifierID NameID = Implementation->getIdentifier(Name);
  SingleDeclTableKey Key(Ctx, NameID);
  Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
}

void APINotesWriter::addEnumConstant(llvm::StringRef Name,
                                     const EnumConstantInfo &Info,
                                     VersionTuple SwiftVersion) {
  IdentifierID EnumConstantID = Implementation->getIdentifier(Name);
  Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
}

void APINotesWriter::addTag(std::optional<Context> Ctx, llvm::StringRef Name,
                            const TagInfo &Info, VersionTuple SwiftVersion) {
  IdentifierID TagID = Implementation->getIdentifier(Name);
  SingleDeclTableKey Key(Ctx, TagID);
  Implementation->Tags[Key].push_back({SwiftVersion, Info});
}

void APINotesWriter::addTypedef(std::optional<Context> Ctx,
                                llvm::StringRef Name, const TypedefInfo &Info,
                                VersionTuple SwiftVersion) {
  IdentifierID TypedefID = Implementation->getIdentifier(Name);
  SingleDeclTableKey Key(Ctx, TypedefID);
  Implementation->Typedefs[Key].push_back({SwiftVersion, Info});
}
} // namespace api_notes
} // namespace clang
