//===--- Serialization.cpp - Read and write Swift modules -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "Serialization.h"
#include "SILFormat.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/AutoDiff.h"
#include "swift/AST/DiagnosticsCommon.h"
#include "swift/AST/Expr.h"
#include "swift/AST/FileSystem.h"
#include "swift/AST/ForeignErrorConvention.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/IndexSubset.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/LinkLibrary.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/PropertyWrappers.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/RawComment.h"
#include "swift/AST/SILLayout.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/SynthesizedFileUnit.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/TypeVisitor.h"
#include "swift/Basic/Dwarf.h"
#include "swift/Basic/FileSystem.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Basic/Version.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/ClangImporter/SwiftAbstractBasicWriter.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/Serialization/SerializationOptions.h"
#include "swift/Strings.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/RecordLayout.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SmallVectorMemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"

#include <vector>

using namespace swift;
using namespace swift::serialization;
using namespace llvm::support;
using swift::version::Version;
using llvm::BCBlockRAII;

ASTContext &SerializerBase::getASTContext() {
  return M->getASTContext();
}

/// Used for static_assert.
static constexpr bool declIDFitsIn32Bits() {
  using Int32Info = std::numeric_limits<uint32_t>;
  using PtrIntInfo = std::numeric_limits<uintptr_t>;
  using DeclIDTraits = llvm::PointerLikeTypeTraits<DeclID>;
  return PtrIntInfo::digits - DeclIDTraits::NumLowBitsAvailable <= Int32Info::digits;
}

/// Used for static_assert.
static constexpr bool bitOffsetFitsIn32Bits() {
  // FIXME: Considering BitOffset is a _bit_ offset, and we're storing it in 31
  // bits of a PointerEmbeddedInt, the maximum offset inside a modulefile we can
  // handle happens at 2**28 _bytes_, which is only 268MB. Considering
  // Swift.swiftmodule is itself 25MB, it seems entirely possible users will
  // exceed this limit.
  using Int32Info = std::numeric_limits<uint32_t>;
  using PtrIntInfo = std::numeric_limits<uintptr_t>;
  using BitOffsetTraits = llvm::PointerLikeTypeTraits<BitOffset>;
  return PtrIntInfo::digits - BitOffsetTraits::NumLowBitsAvailable <= Int32Info::digits;
}

namespace {
  /// Used to serialize the on-disk decl hash table.
  class DeclTableInfo {
  public:
    using key_type = DeclBaseName;
    using key_type_ref = key_type;
    using data_type = Serializer::DeclTableData;
    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) {
      switch (key.getKind()) {
        case DeclBaseName::Kind::Normal:
          assert(!key.empty());
          return llvm::djbHash(key.getIdentifier().str(),
                               SWIFTMODULE_HASH_SEED);
        case DeclBaseName::Kind::Subscript:
          return static_cast<uint8_t>(DeclNameKind::Subscript);
        case DeclBaseName::Kind::Constructor:
          return static_cast<uint8_t>(DeclNameKind::Constructor);
        case DeclBaseName::Kind::Destructor:
          return static_cast<uint8_t>(DeclNameKind::Destructor);
      }
      llvm_unreachable("unhandled kind");
    }

    std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out,
                                                    key_type_ref key,
                                                    data_type_ref data) {
      uint32_t keyLength = sizeof(uint8_t); // For the flag of the name's kind
      if (key.getKind() == DeclBaseName::Kind::Normal) {
        keyLength += key.getIdentifier().str().size(); // The name's length
      }
      assert(keyLength == static_cast<uint16_t>(keyLength));

      uint32_t dataLength = (sizeof(uint32_t) + 1) * data.size();
      assert(dataLength == static_cast<uint16_t>(dataLength));

      endian::Writer writer(out, little);
      writer.write<uint16_t>(keyLength);
      writer.write<uint16_t>(dataLength);
      return { keyLength, dataLength };
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
      endian::Writer writer(out, little);
      switch (key.getKind()) {
      case DeclBaseName::Kind::Normal:
        writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Normal));
        writer.OS << key.getIdentifier().str();
        break;
      case DeclBaseName::Kind::Subscript:
        writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Subscript));
        break;
      case DeclBaseName::Kind::Constructor:
        writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Constructor));
        break;
      case DeclBaseName::Kind::Destructor:
        writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Destructor));
        break;
      }
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      endian::Writer writer(out, little);
      for (auto entry : data) {
        writer.write<uint8_t>(entry.first);
        writer.write<uint32_t>(entry.second);
      }
    }
  };

  class ExtensionTableInfo {
    serialization::Serializer &Serializer;
    llvm::SmallDenseMap<const NominalTypeDecl *,std::string,4> MangledNameCache;

  public:
    explicit ExtensionTableInfo(serialization::Serializer &serializer)
        : Serializer(serializer) {}

    using key_type = Identifier;
    using key_type_ref = key_type;
    using data_type = Serializer::ExtensionTableData;
    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) {
      assert(!key.empty());
      return llvm::djbHash(key.str(), SWIFTMODULE_HASH_SEED);
    }

    int32_t getNameDataForBase(const NominalTypeDecl *nominal,
                               StringRef *dataToWrite = nullptr) {
      if (nominal->getDeclContext()->isModuleScopeContext())
        return -Serializer.addContainingModuleRef(nominal->getDeclContext());

      auto &mangledName = MangledNameCache[nominal];
      if (mangledName.empty())
        mangledName = Mangle::ASTMangler().mangleNominalType(nominal);

      assert(llvm::isUInt<31>(mangledName.size()));
      if (dataToWrite)
        *dataToWrite = mangledName;
      return mangledName.size();
    }

    std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out,
                                                    key_type_ref key,
                                                    data_type_ref data) {
      uint32_t keyLength = key.str().size();
      assert(keyLength == static_cast<uint16_t>(keyLength));
      uint32_t dataLength = (sizeof(uint32_t) * 2) * data.size();
      for (auto dataPair : data) {
        int32_t nameData = getNameDataForBase(dataPair.first);
        if (nameData > 0)
          dataLength += nameData;
      }
      assert(dataLength == static_cast<uint16_t>(dataLength));
      endian::Writer writer(out, little);
      writer.write<uint16_t>(keyLength);
      writer.write<uint16_t>(dataLength);
      return { keyLength, dataLength };
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
      out << key.str();
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      endian::Writer writer(out, little);
      for (auto entry : data) {
        StringRef dataToWrite;
        writer.write<uint32_t>(entry.second);
        writer.write<int32_t>(getNameDataForBase(entry.first, &dataToWrite));
        out << dataToWrite;
      }
    }
  };

  class LocalDeclTableInfo {
  public:
    using key_type = std::string;
    using key_type_ref = StringRef;
    using data_type = DeclID;
    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) {
      assert(!key.empty());
      return llvm::djbHash(key, SWIFTMODULE_HASH_SEED);
    }

    std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out,
                                                    key_type_ref key,
                                                    data_type_ref data) {
      uint32_t keyLength = key.size();
      assert(keyLength == static_cast<uint16_t>(keyLength));
      uint32_t dataLength = sizeof(uint32_t);
      endian::Writer writer(out, little);
      writer.write<uint16_t>(keyLength);
      // No need to write the data length; it's constant.
      return { keyLength, dataLength };
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
      out << key;
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      endian::Writer writer(out, little);
      writer.write<uint32_t>(data);
    }
  };

  using LocalTypeHashTableGenerator =
    llvm::OnDiskChainedHashTableGenerator<LocalDeclTableInfo>;

  class NestedTypeDeclsTableInfo {
  public:
    using key_type = Identifier;
    using key_type_ref = const key_type &;
    using data_type = Serializer::NestedTypeDeclsData; // (parent, child) pairs
    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) {
      assert(!key.empty());
      return llvm::djbHash(key.str(), SWIFTMODULE_HASH_SEED);
    }

    std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out,
                                                    key_type_ref key,
                                                    data_type_ref data) {
      uint32_t keyLength = key.str().size();
      assert(keyLength == static_cast<uint16_t>(keyLength));
      uint32_t dataLength = (sizeof(uint32_t) * 2) * data.size();
      assert(dataLength == static_cast<uint16_t>(dataLength));
      endian::Writer writer(out, little);
      writer.write<uint16_t>(keyLength);
      writer.write<uint16_t>(dataLength);
      return { keyLength, dataLength };
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
      // FIXME: Avoid writing string data for identifiers here.
      out << key.str();
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      endian::Writer writer(out, little);
      for (auto entry : data) {
        writer.write<uint32_t>(entry.first);
        writer.write<uint32_t>(entry.second);
      }
    }
  };

  class DeclMemberNamesTableInfo {
  public:
    using key_type = DeclBaseName;
    using key_type_ref = const key_type &;
    using data_type = BitOffset; // Offsets to sub-tables
    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) {
      switch (key.getKind()) {
      case DeclBaseName::Kind::Normal:
        assert(!key.empty());
        return llvm::djbHash(key.getIdentifier().str(), SWIFTMODULE_HASH_SEED);
      case DeclBaseName::Kind::Subscript:
        return static_cast<uint8_t>(DeclNameKind::Subscript);
      case DeclBaseName::Kind::Constructor:
        return static_cast<uint8_t>(DeclNameKind::Constructor);
      case DeclBaseName::Kind::Destructor:
        return static_cast<uint8_t>(DeclNameKind::Destructor);
      }
      llvm_unreachable("unhandled kind");
    }

    std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out,
                                                    key_type_ref key,
                                                    data_type_ref data) {
      uint32_t keyLength = sizeof(uint8_t); // For the flag of the name's kind
      if (key.getKind() == DeclBaseName::Kind::Normal) {
        keyLength += key.getIdentifier().str().size(); // The name's length
      }
      assert(keyLength == static_cast<uint16_t>(keyLength));
      uint32_t dataLength = sizeof(uint32_t);
      endian::Writer writer(out, little);
      writer.write<uint16_t>(keyLength);
      // No need to write dataLength, it's constant.
      return { keyLength, dataLength };
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
      endian::Writer writer(out, little);
      switch (key.getKind()) {
      case DeclBaseName::Kind::Normal:
        writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Normal));
        writer.OS << key.getIdentifier().str();
        break;
      case DeclBaseName::Kind::Subscript:
        writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Subscript));
        break;
      case DeclBaseName::Kind::Constructor:
        writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Constructor));
        break;
      case DeclBaseName::Kind::Destructor:
        writer.write<uint8_t>(static_cast<uint8_t>(DeclNameKind::Destructor));
        break;
      }
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(bitOffsetFitsIn32Bits(), "BitOffset too large");
      endian::Writer writer(out, little);
      writer.write<uint32_t>(static_cast<uint32_t>(data));
    }
  };

  class DeclMembersTableInfo {
  public:
    using key_type = DeclID;
    using key_type_ref = const key_type &;
    using data_type = Serializer::DeclMembersData; // Vector of DeclIDs
    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::hash_value(static_cast<uint32_t>(key));
    }

    std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out,
                                                    key_type_ref key,
                                                    data_type_ref data) {
      // This will trap if a single ValueDecl has more than 16383 members
      // with the same DeclBaseName. Seems highly unlikely.
      assert((data.size() < (1 << 14)) && "Too many members");
      uint32_t dataLength = sizeof(uint32_t) * data.size(); // value DeclIDs
      endian::Writer writer(out, little);
      // No need to write the key length; it's constant.
      writer.write<uint16_t>(dataLength);
      return { sizeof(uint32_t), dataLength };
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      assert(len == sizeof(uint32_t));
      endian::Writer writer(out, little);
      writer.write<uint32_t>(key);
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      endian::Writer writer(out, little);
      for (auto entry : data) {
        writer.write<uint32_t>(entry);
      }
    }
  };

  // Side table information for serializing the table keyed under
  // \c DeclFingerprintsLayout.
  class DeclFingerprintsTableInfo {
  public:
    using key_type = DeclID;
    using key_type_ref = const key_type &;
    using data_type = Fingerprint;
    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::hash_value(static_cast<uint32_t>(key));
    }

    std::pair<unsigned, unsigned>
    EmitKeyDataLength(raw_ostream &out, key_type_ref key, data_type_ref data) {
      endian::Writer writer(out, little);
      // No need to write the key or value length; they're both constant.
      const unsigned valueLen = Fingerprint::DIGEST_LENGTH;
      return {sizeof(uint32_t), valueLen};
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      assert(len == sizeof(uint32_t));
      endian::Writer writer(out, little);
      writer.write<uint32_t>(key);
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      assert(len == Fingerprint::DIGEST_LENGTH);
      endian::Writer writer(out, little);
      out << data;
    }
  };
} // end anonymous namespace

static ModuleDecl *getModule(ModuleOrSourceFile DC) {
  if (auto M = DC.dyn_cast<ModuleDecl *>())
    return M;
  return DC.get<SourceFile *>()->getParentModule();
}

static ASTContext &getContext(ModuleOrSourceFile DC) {
  return getModule(DC)->getASTContext();
}

static bool shouldSerializeAsLocalContext(const DeclContext *DC) {
  return DC->isLocalContext() && !isa<AbstractFunctionDecl>(DC) &&
        !isa<SubscriptDecl>(DC) && !isa<EnumElementDecl>(DC);
}

namespace {
  struct Accessors {
    uint8_t OpaqueReadOwnership;
    uint8_t ReadImpl, WriteImpl, ReadWriteImpl;
    SmallVector<AccessorDecl *, 8> Decls;
  };
} // end anonymous namespace

static uint8_t getRawOpaqueReadOwnership(swift::OpaqueReadOwnership ownership) {
  switch (ownership) {
#define CASE(KIND)                                            \
  case swift::OpaqueReadOwnership::KIND:                      \
    return uint8_t(serialization::OpaqueReadOwnership::KIND);
  CASE(Owned)
  CASE(Borrowed)
  CASE(OwnedOrBorrowed)
#undef CASE
  }
  llvm_unreachable("bad kind");  
}

static uint8_t getRawReadImplKind(swift::ReadImplKind kind) {
  switch (kind) {
#define CASE(KIND)                                     \
  case swift::ReadImplKind::KIND:                      \
    return uint8_t(serialization::ReadImplKind::KIND);
  CASE(Stored)
  CASE(Get)
  CASE(Inherited)
  CASE(Address)
  CASE(Read)
#undef CASE
  }
  llvm_unreachable("bad kind");
}

static unsigned getRawWriteImplKind(swift::WriteImplKind kind) {
  switch (kind) {
#define CASE(KIND)                                      \
  case swift::WriteImplKind::KIND:                      \
    return uint8_t(serialization::WriteImplKind::KIND);
  CASE(Immutable)
  CASE(Stored)
  CASE(Set)
  CASE(StoredWithObservers)
  CASE(InheritedWithObservers)
  CASE(MutableAddress)
  CASE(Modify)
#undef CASE
  }
  llvm_unreachable("bad kind");
}

static unsigned getRawReadWriteImplKind(swift::ReadWriteImplKind kind) {
  switch (kind) {
#define CASE(KIND)                                          \
  case swift::ReadWriteImplKind::KIND:                      \
    return uint8_t(serialization::ReadWriteImplKind::KIND);
  CASE(Immutable)
  CASE(Stored)
  CASE(MutableAddress)
  CASE(MaterializeToTemporary)
  CASE(Modify)
  CASE(StoredWithDidSet)
  CASE(InheritedWithDidSet)
#undef CASE
  }
  llvm_unreachable("bad kind");
}

static Accessors getAccessors(const AbstractStorageDecl *storage) {
  Accessors accessors;
  accessors.OpaqueReadOwnership =
    getRawOpaqueReadOwnership(storage->getOpaqueReadOwnership());
  auto impl = storage->getImplInfo();
  accessors.ReadImpl = getRawReadImplKind(impl.getReadImpl());
  accessors.WriteImpl = getRawWriteImplKind(impl.getWriteImpl());
  accessors.ReadWriteImpl = getRawReadWriteImplKind(impl.getReadWriteImpl());
  auto decls = storage->getAllAccessors();
  accessors.Decls.append(decls.begin(), decls.end());
  return accessors;
}

LocalDeclContextID Serializer::addLocalDeclContextRef(const DeclContext *DC) {
  assert(DC->isLocalContext() && "Expected a local DeclContext");
  return LocalDeclContextsToSerialize.addRef(DC);
}

GenericSignatureID
Serializer::addGenericSignatureRef(GenericSignature sig) {
  if (!sig)
    return 0;
  return GenericSignaturesToSerialize.addRef(sig);
}

SubstitutionMapID
Serializer::addSubstitutionMapRef(SubstitutionMap substitutions) {
  return SubstitutionMapsToSerialize.addRef(substitutions);
}

DeclContextID Serializer::addDeclContextRef(const DeclContext *DC) {
  assert(DC && "cannot reference a null DeclContext");

  switch (DC->getContextKind()) {
  case DeclContextKind::Module:
  case DeclContextKind::FileUnit: // Skip up to the module
    return DeclContextID();
  default:
    break;
  }

  // If this decl context is a plain old serializable decl, queue it up for
  // normal serialization.
  if (shouldSerializeAsLocalContext(DC))
    return DeclContextID::forLocalDeclContext(addLocalDeclContextRef(DC));
  return DeclContextID::forDecl(addDeclRef(DC->getAsDecl()));
}

DeclID Serializer::addDeclRef(const Decl *D, bool allowTypeAliasXRef) {
  assert((!D || !isDeclXRef(D) || isa<ValueDecl>(D) || isa<OperatorDecl>(D) ||
          isa<PrecedenceGroupDecl>(D)) &&
         "cannot cross-reference this decl");

  assert((!D || !isDeclXRef(D) ||
          !D->getAttrs().hasAttribute<ForbidSerializingReferenceAttr>()) &&
         "cannot cross-reference this decl");

  assert((!D || allowTypeAliasXRef || !isa<TypeAliasDecl>(D) ||
          D->getModuleContext() == M) &&
         "cannot cross-reference typealiases directly (use the TypeAliasType)");

  return DeclsToSerialize.addRef(D);
}

serialization::TypeID Serializer::addTypeRef(Type ty) {
#ifndef NDEBUG
  PrettyStackTraceType trace(M->getASTContext(), "serializing", ty);
  assert(M->getASTContext().LangOpts.AllowModuleWithCompilerErrors ||
         !ty || !ty->hasError() && "serializing type with an error");
#endif

  return TypesToSerialize.addRef(ty);
}

serialization::ClangTypeID Serializer::addClangTypeRef(const clang::Type *ty) {
  if (!ty) return 0;

  // Try to serialize the non-canonical type, but fall back to the
  // canonical type if necessary.
  auto loader = getASTContext().getClangModuleLoader();
  bool isSerializable;
  if (loader->isSerializable(ty, false)) {
    isSerializable = true;
  } else if (!ty->isCanonicalUnqualified()) {
    ty = ty->getCanonicalTypeInternal().getTypePtr();
    isSerializable = loader->isSerializable(ty, false);
  } else {
    isSerializable = false;
  }
  if (!isSerializable) {
    PrettyStackTraceClangType trace(loader->getClangASTContext(),
                                    "staging a serialized reference to", ty);
    llvm::report_fatal_error("Clang function type is not serializable");
  }

  return ClangTypesToSerialize.addRef(ty);
}

IdentifierID Serializer::addDeclBaseNameRef(DeclBaseName ident) {
  switch (ident.getKind()) {
  case DeclBaseName::Kind::Normal: {
    if (ident.empty())
      return 0;

    IdentifierID &id = IdentifierIDs[ident.getIdentifier()];
    if (id != 0)
      return id;

    id = ++LastUniquedStringID;
    StringsToWrite.push_back(ident.getIdentifier().str());
    return id;
  }
  case DeclBaseName::Kind::Subscript:
    return SUBSCRIPT_ID;
  case DeclBaseName::Kind::Constructor:
    return CONSTRUCTOR_ID;
  case DeclBaseName::Kind::Destructor:
    return DESTRUCTOR_ID;
  }
  llvm_unreachable("unhandled kind");
}

std::pair<StringRef, IdentifierID> Serializer::addUniquedString(StringRef str) {
  if (str.empty())
    return {str, 0};

  decltype(UniquedStringIDs)::iterator iter;
  bool isNew;
  std::tie(iter, isNew) =
      UniquedStringIDs.insert({str, LastUniquedStringID + 1});

  if (!isNew)
    return {iter->getKey(), iter->getValue()};

  ++LastUniquedStringID;
  // Note that we use the string data stored in the StringMap.
  StringsToWrite.push_back(iter->getKey());
  return {iter->getKey(), LastUniquedStringID};
}

IdentifierID Serializer::addFilename(StringRef filename) {
  assert(!filename.empty() && "Attemping to add an empty filename");

  return addUniquedString(filename).second;
}

IdentifierID Serializer::addContainingModuleRef(const DeclContext *DC) {
  assert(!isa<ModuleDecl>(DC) &&
         "References should be to things within modules");
  const FileUnit *file = cast<FileUnit>(DC->getModuleScopeContext());
  const ModuleDecl *M = file->getParentModule();

  if (M == this->M)
    return CURRENT_MODULE_ID;
  if (M == this->M->getASTContext().TheBuiltinModule)
    return BUILTIN_MODULE_ID;

  auto clangImporter =
    static_cast<ClangImporter *>(
      this->M->getASTContext().getClangModuleLoader());
  if (M == clangImporter->getImportedHeaderModule())
    return OBJC_HEADER_MODULE_ID;

  auto exportedModuleName = file->getExportedModuleName();
  assert(!exportedModuleName.empty());
  auto exportedModuleID = M->getASTContext().getIdentifier(exportedModuleName);
  return addDeclBaseNameRef(exportedModuleID);
}

IdentifierID Serializer::addModuleRef(const ModuleDecl *module) {
  if (module == this->M)
    return CURRENT_MODULE_ID;
  if (module == this->M->getASTContext().TheBuiltinModule)
    return BUILTIN_MODULE_ID;
  auto moduleName =
      module->getASTContext().getIdentifier(module->getName().str());
  return addDeclBaseNameRef(moduleName);
}

SILLayoutID Serializer::addSILLayoutRef(const SILLayout *layout) {
  return SILLayoutsToSerialize.addRef(layout);
}

NormalConformanceID
Serializer::addConformanceRef(const NormalProtocolConformance *conformance) {
  assert(conformance->getDeclContext()->getParentModule() == M &&
         "cannot reference conformance from another module");
  return NormalConformancesToSerialize.addRef(conformance);
}

/// Record the name of a block.
void SerializerBase::emitBlockID(unsigned ID, StringRef name,
                                 SmallVectorImpl<unsigned char> &nameBuffer) {
  SmallVector<unsigned, 1> idBuffer;
  idBuffer.push_back(ID);
  Out.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, idBuffer);

  // Emit the block name if present.
  if (name.empty())
    return;
  nameBuffer.resize(name.size());
  memcpy(nameBuffer.data(), name.data(), name.size());
  Out.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, nameBuffer);
}

void SerializerBase::emitRecordID(unsigned ID, StringRef name,
                                  SmallVectorImpl<unsigned char> &nameBuffer) {
  assert(ID < 256 && "can't fit record ID in next to name");
  nameBuffer.resize(name.size()+1);
  nameBuffer[0] = ID;
  memcpy(nameBuffer.data()+1, name.data(), name.size());
  Out.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, nameBuffer);
}

void Serializer::writeBlockInfoBlock() {
  BCBlockRAII restoreBlock(Out, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);

  SmallVector<unsigned char, 64> nameBuffer;
#define BLOCK(X) emitBlockID(X ## _ID, #X, nameBuffer)
#define BLOCK_RECORD(K, X) emitRecordID(K::X, #X, nameBuffer)

  BLOCK(MODULE_BLOCK);

  BLOCK(CONTROL_BLOCK);
  BLOCK_RECORD(control_block, METADATA);
  BLOCK_RECORD(control_block, MODULE_NAME);
  BLOCK_RECORD(control_block, TARGET);

  BLOCK(OPTIONS_BLOCK);
  BLOCK_RECORD(options_block, SDK_PATH);
  BLOCK_RECORD(options_block, XCC);
  BLOCK_RECORD(options_block, IS_SIB);
  BLOCK_RECORD(options_block, IS_TESTABLE);
  BLOCK_RECORD(options_block, ARE_PRIVATE_IMPORTS_ENABLED);
  BLOCK_RECORD(options_block, RESILIENCE_STRATEGY);
  BLOCK_RECORD(options_block, IS_ALLOW_MODULE_WITH_COMPILER_ERRORS_ENABLED);

  BLOCK(INPUT_BLOCK);
  BLOCK_RECORD(input_block, IMPORTED_MODULE);
  BLOCK_RECORD(input_block, LINK_LIBRARY);
  BLOCK_RECORD(input_block, IMPORTED_HEADER);
  BLOCK_RECORD(input_block, IMPORTED_HEADER_CONTENTS);
  BLOCK_RECORD(input_block, MODULE_FLAGS);
  BLOCK_RECORD(input_block, SEARCH_PATH);
  BLOCK_RECORD(input_block, FILE_DEPENDENCY);
  BLOCK_RECORD(input_block, DEPENDENCY_DIRECTORY);
  BLOCK_RECORD(input_block, MODULE_INTERFACE_PATH);
  BLOCK_RECORD(input_block, IMPORTED_MODULE_SPIS);

  BLOCK(DECLS_AND_TYPES_BLOCK);
#define RECORD(X) BLOCK_RECORD(decls_block, X);
#include "DeclTypeRecordNodes.def"

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

  BLOCK(INDEX_BLOCK);
  BLOCK_RECORD(index_block, TYPE_OFFSETS);
  BLOCK_RECORD(index_block, DECL_OFFSETS);
  BLOCK_RECORD(index_block, IDENTIFIER_OFFSETS);
  BLOCK_RECORD(index_block, TOP_LEVEL_DECLS);
  BLOCK_RECORD(index_block, OPERATORS);
  BLOCK_RECORD(index_block, EXTENSIONS);
  BLOCK_RECORD(index_block, CLASS_MEMBERS_FOR_DYNAMIC_LOOKUP);
  BLOCK_RECORD(index_block, OPERATOR_METHODS);
  BLOCK_RECORD(index_block, OBJC_METHODS);
  BLOCK_RECORD(index_block, DERIVATIVE_FUNCTION_CONFIGURATIONS);
  BLOCK_RECORD(index_block, ENTRY_POINT);
  BLOCK_RECORD(index_block, LOCAL_DECL_CONTEXT_OFFSETS);
  BLOCK_RECORD(index_block, GENERIC_SIGNATURE_OFFSETS);
  BLOCK_RECORD(index_block, SUBSTITUTION_MAP_OFFSETS);
  BLOCK_RECORD(index_block, CLANG_TYPE_OFFSETS);
  BLOCK_RECORD(index_block, LOCAL_TYPE_DECLS);
  BLOCK_RECORD(index_block, NORMAL_CONFORMANCE_OFFSETS);
  BLOCK_RECORD(index_block, SIL_LAYOUT_OFFSETS);
  BLOCK_RECORD(index_block, PRECEDENCE_GROUPS);
  BLOCK_RECORD(index_block, NESTED_TYPE_DECLS);
  BLOCK_RECORD(index_block, DECL_MEMBER_NAMES);
  BLOCK_RECORD(index_block, DECL_FINGERPRINTS);
  BLOCK_RECORD(index_block, ORDERED_TOP_LEVEL_DECLS);
  BLOCK_RECORD(index_block, EXPORTED_PRESPECIALIZATION_DECLS);

  BLOCK(DECL_MEMBER_TABLES_BLOCK);
  BLOCK_RECORD(decl_member_tables_block, DECL_MEMBERS);

  BLOCK(SIL_BLOCK);
  BLOCK_RECORD(sil_block, SIL_FUNCTION);
  BLOCK_RECORD(sil_block, SIL_BASIC_BLOCK);
  BLOCK_RECORD(sil_block, SIL_ONE_VALUE_ONE_OPERAND);
  BLOCK_RECORD(sil_block, SIL_ONE_TYPE);
  BLOCK_RECORD(sil_block, SIL_ONE_OPERAND);
  BLOCK_RECORD(sil_block, SIL_ONE_TYPE_ONE_OPERAND);
  BLOCK_RECORD(sil_block, SIL_ONE_TYPE_VALUES);
  BLOCK_RECORD(sil_block, SIL_TWO_OPERANDS);
  BLOCK_RECORD(sil_block, SIL_TAIL_ADDR);
  BLOCK_RECORD(sil_block, SIL_INST_APPLY);
  BLOCK_RECORD(sil_block, SIL_INST_NO_OPERAND);
  BLOCK_RECORD(sil_block, SIL_VTABLE);
  BLOCK_RECORD(sil_block, SIL_VTABLE_ENTRY);
  BLOCK_RECORD(sil_block, SIL_GLOBALVAR);
  BLOCK_RECORD(sil_block, SIL_INIT_EXISTENTIAL);
  BLOCK_RECORD(sil_block, SIL_WITNESS_TABLE);
  BLOCK_RECORD(sil_block, SIL_WITNESS_METHOD_ENTRY);
  BLOCK_RECORD(sil_block, SIL_WITNESS_BASE_ENTRY);
  BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_PROTOCOL);
  BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_ENTRY);
  BLOCK_RECORD(sil_block, SIL_WITNESS_CONDITIONAL_CONFORMANCE);
  BLOCK_RECORD(sil_block, SIL_DEFAULT_WITNESS_TABLE);
  BLOCK_RECORD(sil_block, SIL_DEFAULT_WITNESS_TABLE_NO_ENTRY);
  BLOCK_RECORD(sil_block, SIL_INST_WITNESS_METHOD);
  BLOCK_RECORD(sil_block, SIL_SPECIALIZE_ATTR);
  BLOCK_RECORD(sil_block, SIL_ONE_OPERAND_EXTRA_ATTR);
  BLOCK_RECORD(sil_block, SIL_TWO_OPERANDS_EXTRA_ATTR);

  // These layouts can exist in both decl blocks and sil blocks.
#define BLOCK_RECORD_WITH_NAMESPACE(K, X) emitRecordID(X, #X, nameBuffer)
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::INVALID_PROTOCOL_CONFORMANCE);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::ABSTRACT_PROTOCOL_CONFORMANCE);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::NORMAL_PROTOCOL_CONFORMANCE);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::SELF_PROTOCOL_CONFORMANCE);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::SPECIALIZED_PROTOCOL_CONFORMANCE);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::INHERITED_PROTOCOL_CONFORMANCE);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::NORMAL_PROTOCOL_CONFORMANCE_ID);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::PROTOCOL_CONFORMANCE_XREF);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::GENERIC_PARAM_LIST);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::GENERIC_REQUIREMENT);
  BLOCK_RECORD_WITH_NAMESPACE(sil_block,
                              decls_block::LAYOUT_REQUIREMENT);

  BLOCK(SIL_INDEX_BLOCK);
  BLOCK_RECORD(sil_index_block, SIL_FUNC_NAMES);
  BLOCK_RECORD(sil_index_block, SIL_FUNC_OFFSETS);
  BLOCK_RECORD(sil_index_block, SIL_VTABLE_NAMES);
  BLOCK_RECORD(sil_index_block, SIL_VTABLE_OFFSETS);
  BLOCK_RECORD(sil_index_block, SIL_GLOBALVAR_NAMES);
  BLOCK_RECORD(sil_index_block, SIL_GLOBALVAR_OFFSETS);
  BLOCK_RECORD(sil_index_block, SIL_WITNESS_TABLE_NAMES);
  BLOCK_RECORD(sil_index_block, SIL_WITNESS_TABLE_OFFSETS);
  BLOCK_RECORD(sil_index_block, SIL_DEFAULT_WITNESS_TABLE_NAMES);
  BLOCK_RECORD(sil_index_block, SIL_DEFAULT_WITNESS_TABLE_OFFSETS);
  BLOCK_RECORD(sil_index_block, SIL_PROPERTY_OFFSETS);
  BLOCK_RECORD(sil_index_block, SIL_DIFFERENTIABILITY_WITNESS_NAMES);
  BLOCK_RECORD(sil_index_block, SIL_DIFFERENTIABILITY_WITNESS_OFFSETS);

  BLOCK(INCREMENTAL_INFORMATION_BLOCK);
  BLOCK_RECORD(fine_grained_dependencies::record_block, METADATA);
  BLOCK_RECORD(fine_grained_dependencies::record_block, SOURCE_FILE_DEP_GRAPH_NODE);
  BLOCK_RECORD(fine_grained_dependencies::record_block, FINGERPRINT_NODE);
  BLOCK_RECORD(fine_grained_dependencies::record_block, DEPENDS_ON_DEFINITION_NODE);
  BLOCK_RECORD(fine_grained_dependencies::record_block, IDENTIFIER_NODE);

#undef BLOCK
#undef BLOCK_RECORD
}

void Serializer::writeHeader(const SerializationOptions &options) {
  {
    BCBlockRAII restoreBlock(Out, CONTROL_BLOCK_ID, 3);
    control_block::ModuleNameLayout ModuleName(Out);
    control_block::MetadataLayout Metadata(Out);
    control_block::TargetLayout Target(Out);

    ModuleName.emit(ScratchRecord, M->getName().str());

    SmallString<32> versionStringBuf;
    llvm::raw_svector_ostream versionString(versionStringBuf);
    versionString << Version::getCurrentLanguageVersion();
    size_t shortVersionStringLength = versionString.tell();
    versionString << '('
                  << M->getASTContext().LangOpts.EffectiveLanguageVersion;
    size_t compatibilityVersionStringLength =
        versionString.tell() - shortVersionStringLength - 1;
    versionString << ")/" << version::getSwiftFullVersion();
    Metadata.emit(ScratchRecord,
                  SWIFTMODULE_VERSION_MAJOR, SWIFTMODULE_VERSION_MINOR,
                  shortVersionStringLength,
                  compatibilityVersionStringLength,
                  versionString.str());

    Target.emit(ScratchRecord, M->getASTContext().LangOpts.Target.str());

    {
      llvm::BCBlockRAII restoreBlock(Out, OPTIONS_BLOCK_ID, 4);

      options_block::IsSIBLayout IsSIB(Out);
      IsSIB.emit(ScratchRecord, options.IsSIB);

      if (M->isTestingEnabled()) {
        options_block::IsTestableLayout IsTestable(Out);
        IsTestable.emit(ScratchRecord);
      }

      if (M->arePrivateImportsEnabled()) {
        options_block::ArePrivateImportsEnabledLayout PrivateImports(Out);
        PrivateImports.emit(ScratchRecord);
      }

      if (M->isImplicitDynamicEnabled()) {
        options_block::IsImplicitDynamicEnabledLayout ImplicitDynamic(Out);
        ImplicitDynamic.emit(ScratchRecord);
      }

      if (M->getResilienceStrategy() != ResilienceStrategy::Default) {
        options_block::ResilienceStrategyLayout Strategy(Out);
        Strategy.emit(ScratchRecord, unsigned(M->getResilienceStrategy()));
      }

      if (getASTContext().LangOpts.AllowModuleWithCompilerErrors) {
        options_block::IsAllowModuleWithCompilerErrorsEnabledLayout
            AllowErrors(Out);
        AllowErrors.emit(ScratchRecord);
      }

      if (options.SerializeOptionsForDebugging) {
        options_block::SDKPathLayout SDKPath(Out);
        options_block::XCCLayout XCC(Out);

        SDKPath.emit(ScratchRecord, M->getASTContext().SearchPathOpts.SDKPath);
        auto &Opts = options.ExtraClangOptions;
        for (auto Arg = Opts.begin(), E = Opts.end(); Arg != E; ++Arg) { 
          // FIXME: This is a hack and calls for a better design.
          //
          // Filter out any -ivfsoverlay options that include an
          // unextended-module-overlay.yaml overlay. By convention the Xcode
          // buildsystem uses these while *building* mixed Objective-C and Swift
          // frameworks; but they should never be used to *import* the module
          // defined in the framework.
          if (StringRef(*Arg).startswith("-ivfsoverlay")) {
            auto Next = std::next(Arg);
            if (Next != E &&
                StringRef(*Next).endswith("unextended-module-overlay.yaml")) {
              ++Arg;
              continue;
            }
          }
          XCC.emit(ScratchRecord, *Arg);
        }
      }
    }
  }
}

static void flattenImportPath(const ImportedModule &import,
                              SmallVectorImpl<char> &out) {
  llvm::raw_svector_ostream outStream(out);
  import.importedModule->getReverseFullModuleName().printForward(
      outStream, StringRef("\0", 1));

  if (import.accessPath.empty())
    return;

  outStream << '\0';
  assert(import.accessPath.size() == 1 &&
         "can only handle top-level decl imports");
  auto accessPathElem = import.accessPath.front();
  outStream << accessPathElem.Item.str();
}

uint64_t getRawModTimeOrHash(const SerializationOptions::FileDependency &dep) {
  if (dep.isHashBased()) return dep.getContentHash();
  return dep.getModificationTime();
}

using ImportSet = llvm::SmallSet<ImportedModule, 8, ImportedModule::Order>;
static ImportSet getImportsAsSet(const ModuleDecl *M,
                                 ModuleDecl::ImportFilter filter) {
  SmallVector<ImportedModule, 8> imports;
  M->getImportedModules(imports, filter);
  ImportSet importSet;
  importSet.insert(imports.begin(), imports.end());
  return importSet;
}

void Serializer::writeInputBlock(const SerializationOptions &options) {
  BCBlockRAII restoreBlock(Out, INPUT_BLOCK_ID, 4);
  input_block::ImportedModuleLayout importedModule(Out);
  input_block::ImportedModuleLayoutSPI ImportedModuleSPI(Out);
  input_block::LinkLibraryLayout LinkLibrary(Out);
  input_block::ImportedHeaderLayout ImportedHeader(Out);
  input_block::ImportedHeaderContentsLayout ImportedHeaderContents(Out);
  input_block::SearchPathLayout SearchPath(Out);
  input_block::FileDependencyLayout FileDependency(Out);
  input_block::DependencyDirectoryLayout DependencyDirectory(Out);
  input_block::ModuleInterfaceLayout ModuleInterface(Out);

  if (options.SerializeOptionsForDebugging) {
    const SearchPathOptions &searchPathOpts = M->getASTContext().SearchPathOpts;
    // Put the framework search paths first so that they'll be preferred upon
    // deserialization.
    for (auto &framepath : searchPathOpts.FrameworkSearchPaths)
      SearchPath.emit(ScratchRecord, /*framework=*/true, framepath.IsSystem,
                      framepath.Path);
    for (auto &path : searchPathOpts.ImportSearchPaths)
      SearchPath.emit(ScratchRecord, /*framework=*/false, /*system=*/false, path);
  }

  // Note: We're not using StringMap here because we don't need to own the
  // strings.
  llvm::DenseMap<StringRef, unsigned> dependencyDirectories;
  for (auto const &dep : options.Dependencies) {
    StringRef directoryName = llvm::sys::path::parent_path(dep.getPath());
    unsigned &dependencyDirectoryIndex = dependencyDirectories[directoryName];
    if (!dependencyDirectoryIndex) {
      // This name must be newly-added. Give it a new ID (and skip 0).
      dependencyDirectoryIndex = dependencyDirectories.size();
      DependencyDirectory.emit(ScratchRecord, directoryName);
    }
    FileDependency.emit(ScratchRecord,
                        dep.getSize(),
                        getRawModTimeOrHash(dep),
                        dep.isHashBased(),
                        dep.isSDKRelative(),
                        dependencyDirectoryIndex,
                        llvm::sys::path::filename(dep.getPath()));
  }

  if (!options.ModuleInterface.empty())
    ModuleInterface.emit(ScratchRecord, options.ModuleInterface);

  SmallVector<ImportedModule, 8> allImports;
  M->getImportedModules(allImports,
                        {ModuleDecl::ImportFilterKind::Exported,
                         ModuleDecl::ImportFilterKind::Default,
                         ModuleDecl::ImportFilterKind::ImplementationOnly,
                         ModuleDecl::ImportFilterKind::SPIAccessControl});
  ImportedModule::removeDuplicates(allImports);

  // Collect the public and private imports as a subset so that we can
  // distinguish them.
  ImportSet publicImportSet =
      getImportsAsSet(M, ModuleDecl::ImportFilterKind::Exported);
  ImportSet privateImportSet =
      getImportsAsSet(M, ModuleDecl::ImportFilterKind::Default);
  ImportSet spiImportSet =
      getImportsAsSet(M, ModuleDecl::ImportFilterKind::SPIAccessControl);

  auto clangImporter =
    static_cast<ClangImporter *>(M->getASTContext().getClangModuleLoader());
  ModuleDecl *bridgingHeaderModule = clangImporter->getImportedHeaderModule();
  ImportedModule bridgingHeaderImport{ImportPath::Access(),
                                      bridgingHeaderModule};

  // Make sure the bridging header module is always at the top of the import
  // list, mimicking how it is processed before any module imports when
  // compiling source files.
  if (llvm::is_contained(allImports, bridgingHeaderImport)) {
    off_t importedHeaderSize = 0;
    time_t importedHeaderModTime = 0;
    std::string contents;
    if (!options.ImportedHeader.empty()) {
      contents = clangImporter->getBridgingHeaderContents(
          options.ImportedHeader, importedHeaderSize, importedHeaderModTime);
    }
    assert(publicImportSet.count(bridgingHeaderImport));
    ImportedHeader.emit(ScratchRecord,
                        publicImportSet.count(bridgingHeaderImport),
                        importedHeaderSize, importedHeaderModTime,
                        options.ImportedHeader);
    if (!contents.empty()) {
      contents.push_back('\0');
      ImportedHeaderContents.emit(ScratchRecord, contents);
    }
  }

  ModuleDecl *theBuiltinModule = M->getASTContext().TheBuiltinModule;
  for (auto import : allImports) {
    if (import.importedModule == theBuiltinModule ||
        import.importedModule == bridgingHeaderModule) {
      continue;
    }

    SmallString<64> importPath;
    flattenImportPath(import, importPath);

    serialization::ImportControl stableImportControl;
    // The order of checks here is important, since a module can be imported
    // differently in different files, and we need to record the "most visible"
    // form here.
    if (publicImportSet.count(import))
      stableImportControl = ImportControl::Exported;
    else if (privateImportSet.count(import) || spiImportSet.count(import))
      stableImportControl = ImportControl::Normal;
    else
      stableImportControl = ImportControl::ImplementationOnly;

    llvm::SmallSetVector<Identifier, 4> spis;
    M->lookupImportedSPIGroups(import.importedModule, spis);

    importedModule.emit(ScratchRecord,
                        static_cast<uint8_t>(stableImportControl),
                        !import.accessPath.empty(), !spis.empty(), importPath);

    if (!spis.empty()) {
      SmallString<64> out;
      llvm::raw_svector_ostream outStream(out);
      llvm::interleave(
          spis, [&outStream](Identifier next) { outStream << next.str(); },
          [&outStream] { outStream << StringRef("\0", 1); });
      ImportedModuleSPI.emit(ScratchRecord, out);
    }
  }

  if (!options.ModuleLinkName.empty()) {
    LinkLibrary.emit(ScratchRecord, serialization::LibraryKind::Library,
                     options.AutolinkForceLoad, options.ModuleLinkName);
  }
}

/// Translate AST default argument kind to the Serialization enum values, which
/// are guaranteed to be stable.
static uint8_t getRawStableDefaultArgumentKind(swift::DefaultArgumentKind kind) {
  switch (kind) {
#define CASE(X) \
  case swift::DefaultArgumentKind::X: \
    return static_cast<uint8_t>(serialization::DefaultArgumentKind::X);
  CASE(None)
  CASE(Normal)
  CASE(Inherited)
  CASE(Column)
  CASE(FileID)
  CASE(FilePath)
  CASE(FileIDSpelledAsFile)
  CASE(FilePathSpelledAsFile)
  CASE(Line)
  CASE(Function)
  CASE(DSOHandle)
  CASE(NilLiteral)
  CASE(EmptyArray)
  CASE(EmptyDictionary)
  CASE(StoredProperty)
#undef CASE
  }

  llvm_unreachable("Unhandled DefaultArgumentKind in switch.");
}

static uint8_t
getRawStableMetatypeRepresentation(const AnyMetatypeType *metatype) {
  if (!metatype->hasRepresentation()) {
    return serialization::MetatypeRepresentation::MR_None;
  }

  switch (metatype->getRepresentation()) {
  case swift::MetatypeRepresentation::Thin:
    return serialization::MetatypeRepresentation::MR_Thin;
  case swift::MetatypeRepresentation::Thick:
    return serialization::MetatypeRepresentation::MR_Thick;
  case swift::MetatypeRepresentation::ObjC:
    return serialization::MetatypeRepresentation::MR_ObjC;
  }
  llvm_unreachable("bad representation");
}

/// Translate from the requirement kind to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableRequirementKind(RequirementKind kind) {
#define CASE(KIND)            \
  case RequirementKind::KIND: \
    return GenericRequirementKind::KIND;

  switch (kind) {
  CASE(Conformance)
  CASE(Superclass)
  CASE(SameType)
  CASE(Layout)
  }
#undef CASE

  llvm_unreachable("Unhandled RequirementKind in switch.");
}

void Serializer::writeGenericRequirements(ArrayRef<Requirement> requirements,
                                          const std::array<unsigned, 256> &abbrCodes) {
  using namespace decls_block;

  if (requirements.empty())
    return;

  auto reqAbbrCode = abbrCodes[GenericRequirementLayout::Code];
  auto layoutReqAbbrCode = abbrCodes[LayoutRequirementLayout::Code];
  for (const auto &req : requirements) {
    if (req.getKind() != RequirementKind::Layout)
      GenericRequirementLayout::emitRecord(
          Out, ScratchRecord, reqAbbrCode,
          getRawStableRequirementKind(req.getKind()),
          addTypeRef(req.getFirstType()), addTypeRef(req.getSecondType()));
    else {
      // Write layout requirement.
      auto layout = req.getLayoutConstraint();
      unsigned size = 0;
      unsigned alignment = 0;
      if (layout->isKnownSizeTrivial()) {
        size = layout->getTrivialSizeInBits();
        alignment = layout->getAlignmentInBits();
      }
      LayoutRequirementKind rawKind = LayoutRequirementKind::UnknownLayout;
      switch (layout->getKind()) {
      case LayoutConstraintKind::NativeRefCountedObject:
        rawKind = LayoutRequirementKind::NativeRefCountedObject;
        break;
      case LayoutConstraintKind::RefCountedObject:
        rawKind = LayoutRequirementKind::RefCountedObject;
        break;
      case LayoutConstraintKind::Trivial:
        rawKind = LayoutRequirementKind::Trivial;
        break;
      case LayoutConstraintKind::TrivialOfExactSize:
        rawKind = LayoutRequirementKind::TrivialOfExactSize;
        break;
      case LayoutConstraintKind::TrivialOfAtMostSize:
        rawKind = LayoutRequirementKind::TrivialOfAtMostSize;
        break;
      case LayoutConstraintKind::Class:
        rawKind = LayoutRequirementKind::Class;
        break;
      case LayoutConstraintKind::NativeClass:
        rawKind = LayoutRequirementKind::NativeClass;
        break;
      case LayoutConstraintKind::UnknownLayout:
        rawKind = LayoutRequirementKind::UnknownLayout;
        break;
      }
      LayoutRequirementLayout::emitRecord(
          Out, ScratchRecord, layoutReqAbbrCode, rawKind,
          addTypeRef(req.getFirstType()), size, alignment);
    }
  }
}

void Serializer::writeASTBlockEntity(GenericSignature sig) {
  using namespace decls_block;

  assert(sig);
  assert(GenericSignaturesToSerialize.hasRef(sig));

  // Determine whether we can just write the param types as is, or whether we
  // have to encode them manually because one of them has a declaration with
  // module context (which can happen in SIL).
  bool mustEncodeParamsManually =
      llvm::any_of(sig->getGenericParams(),
                   [](const GenericTypeParamType *paramTy) {
    auto *decl = paramTy->getDecl();
    return decl && decl->getDeclContext()->isModuleScopeContext();
  });

  if (!mustEncodeParamsManually) {
    // Record the generic parameters.
    SmallVector<uint64_t, 4> rawParamIDs;
    for (auto *paramTy : sig->getGenericParams()) {
      rawParamIDs.push_back(addTypeRef(paramTy));
    }

    auto abbrCode = DeclTypeAbbrCodes[GenericSignatureLayout::Code];
    GenericSignatureLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                       rawParamIDs);
  } else {
    // Record the generic parameters.
    SmallVector<uint64_t, 4> rawParamIDs;
    for (auto *paramTy : sig->getGenericParams()) {
      auto *decl = paramTy->getDecl();

      // For a full environment, add the name and canonicalize the param type.
      Identifier paramName = decl ? decl->getName() : Identifier();
      rawParamIDs.push_back(addDeclBaseNameRef(paramName));

      paramTy = paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
      rawParamIDs.push_back(addTypeRef(paramTy));
    }

    auto envAbbrCode = DeclTypeAbbrCodes[SILGenericSignatureLayout::Code];
    SILGenericSignatureLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
                                          rawParamIDs);
  }

  writeGenericRequirements(sig->getRequirements(), DeclTypeAbbrCodes);
}

void Serializer::writeASTBlockEntity(const SubstitutionMap substitutions) {
  using namespace decls_block;
  assert(substitutions);
  assert(SubstitutionMapsToSerialize.hasRef(substitutions));

  // Collect the replacement types.
  SmallVector<uint64_t, 4> rawReplacementTypes;
  for (auto type : substitutions.getReplacementTypes())
    rawReplacementTypes.push_back(addTypeRef(type));

  auto substitutionsAbbrCode = DeclTypeAbbrCodes[SubstitutionMapLayout::Code];
  SubstitutionMapLayout::emitRecord(Out, ScratchRecord, substitutionsAbbrCode,
                                    addGenericSignatureRef(
                                      substitutions.getGenericSignature()),
                                    substitutions.getConformances().size(),
                                    rawReplacementTypes);

  writeConformances(substitutions.getConformances(), DeclTypeAbbrCodes);
}

void Serializer::writeASTBlockEntity(const SILLayout *layout) {
  using namespace decls_block;
  assert(SILLayoutsToSerialize.hasRef(layout));

  SmallVector<unsigned, 16> data;
  // Save field types.
  for (auto &field : layout->getFields()) {
    unsigned typeRef = addTypeRef(field.getLoweredType());
    // Set the high bit if mutable.
    if (field.isMutable())
      typeRef |= 0x80000000U;
    data.push_back(typeRef);
  }
  
  unsigned abbrCode
    = DeclTypeAbbrCodes[SILLayoutLayout::Code];

  SILLayoutLayout::emitRecord(
                        Out, ScratchRecord, abbrCode,
                        addGenericSignatureRef(layout->getGenericSignature()),
                        layout->getFields().size(),
                        data);
}

void Serializer::writeASTBlockEntity(
    const NormalProtocolConformance *conformance) {
  using namespace decls_block;

  // The conformance must be complete, or we can't serialize it.
  assert(conformance->isComplete() ||
         getASTContext().LangOpts.AllowModuleWithCompilerErrors);
  assert(NormalConformancesToSerialize.hasRef(conformance));

  auto protocol = conformance->getProtocol();

  SmallVector<DeclID, 32> data;
  unsigned numValueWitnesses = 0;
  unsigned numTypeWitnesses = 0;

  conformance->forEachTypeWitness([&](AssociatedTypeDecl *assocType,
                                      Type type, TypeDecl *typeDecl) {
    data.push_back(addDeclRef(assocType));
    data.push_back(addTypeRef(type));
    data.push_back(addDeclRef(typeDecl, /*allowTypeAliasXRef*/true));
    ++numTypeWitnesses;
    return false;
  });

  conformance->forEachValueWitness([&](ValueDecl *req, Witness witness) {
      ++numValueWitnesses;
      data.push_back(addDeclRef(req));
      data.push_back(addDeclRef(witness.getDecl()));
      assert(witness.getDecl() || req->getAttrs().hasAttribute<OptionalAttr>()
             || req->getAttrs().isUnavailable(req->getASTContext()));

      // If there is no witness, we're done.
      if (!witness.getDecl()) return;

      auto subs = witness.getSubstitutions();

      // Canonicalize away typealiases, since these substitutions aren't used
      // for diagnostics and we reference fewer declarations that way.
      subs = subs.getCanonical();

      // Map archetypes to type parameters, since we always substitute them
      // away. Note that in a merge-modules pass, we're serializing conformances
      // that we deserialized, so they will already have their replacement types
      // in terms of interface types; hence the hasArchetypes() check is
      // necessary for correctness, not just as a fast path.
      if (subs.hasArchetypes())
        subs = subs.mapReplacementTypesOutOfContext();

      data.push_back(addSubstitutionMapRef(subs));
  });

  unsigned numSignatureConformances =
      conformance->getSignatureConformances().size();

  unsigned abbrCode
    = DeclTypeAbbrCodes[NormalProtocolConformanceLayout::Code];
  auto ownerID = addDeclContextRef(conformance->getDeclContext());
  NormalProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                              addDeclRef(protocol),
                                              ownerID.getOpaqueValue(),
                                              numTypeWitnesses,
                                              numValueWitnesses,
                                              numSignatureConformances,
                                              data);

  // Write requirement signature conformances.
  for (auto reqConformance : conformance->getSignatureConformances())
    writeConformance(reqConformance, DeclTypeAbbrCodes);
}

void
Serializer::writeConformance(ProtocolConformance *conformance,
                             const std::array<unsigned, 256> &abbrCodes,
                             GenericEnvironment *genericEnv) {
  writeConformance(ProtocolConformanceRef(conformance), abbrCodes, genericEnv);
}

void
Serializer::writeConformance(ProtocolConformanceRef conformanceRef,
                             const std::array<unsigned, 256> &abbrCodes,
                             GenericEnvironment *genericEnv) {
  using namespace decls_block;

  if (conformanceRef.isInvalid()) {
    unsigned abbrCode = abbrCodes[InvalidProtocolConformanceLayout::Code];
    InvalidProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode);
    return;
  }

  if (conformanceRef.isAbstract()) {
    unsigned abbrCode = abbrCodes[AbstractProtocolConformanceLayout::Code];
    AbstractProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                      addDeclRef(conformanceRef.getAbstract()));
    return;
  }

  auto conformance = conformanceRef.getConcrete();
  switch (conformance->getKind()) {
  case ProtocolConformanceKind::Normal: {
    auto normal = cast<NormalProtocolConformance>(conformance);
    if (!isDeclXRef(normal->getDeclContext()->getAsDecl())
        && !isa<ClangModuleUnit>(normal->getDeclContext()
                                       ->getModuleScopeContext())) {
      // A normal conformance in this module file.
      unsigned abbrCode = abbrCodes[NormalProtocolConformanceIdLayout::Code];
      NormalProtocolConformanceIdLayout::emitRecord(Out, ScratchRecord,
                                                    abbrCode,
                                                    addConformanceRef(normal));
    } else {
      // A conformance in a different module file.
      unsigned abbrCode = abbrCodes[ProtocolConformanceXrefLayout::Code];
      ProtocolConformanceXrefLayout::emitRecord(
        Out, ScratchRecord,
        abbrCode,
        addDeclRef(normal->getProtocol()),
        addDeclRef(normal->getType()->getAnyNominal()),
        addContainingModuleRef(normal->getDeclContext()));
    }
    break;
  }

  case ProtocolConformanceKind::Self: {
    auto self = cast<SelfProtocolConformance>(conformance);
    unsigned abbrCode = abbrCodes[SelfProtocolConformanceLayout::Code];
    auto protocolID = addDeclRef(self->getProtocol());
    SelfProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                              protocolID);
    break;
  }

  case ProtocolConformanceKind::Specialized: {
    auto conf = cast<SpecializedProtocolConformance>(conformance);
    unsigned abbrCode = abbrCodes[SpecializedProtocolConformanceLayout::Code];
    auto type = conf->getType();
    if (genericEnv && type->hasArchetype())
      type = type->mapTypeOutOfContext();
    SpecializedProtocolConformanceLayout::emitRecord(
                           Out, ScratchRecord,
                           abbrCode,
                           addTypeRef(type),
                           addSubstitutionMapRef(conf->getSubstitutionMap()));

    writeConformance(conf->getGenericConformance(), abbrCodes, genericEnv);
    break;
  }

  case ProtocolConformanceKind::Inherited: {
    auto conf = cast<InheritedProtocolConformance>(conformance);
    unsigned abbrCode
      = abbrCodes[InheritedProtocolConformanceLayout::Code];

    auto type = conf->getType();
    if (genericEnv && type->hasArchetype())
      type = type->mapTypeOutOfContext();

    InheritedProtocolConformanceLayout::emitRecord(
      Out, ScratchRecord, abbrCode, addTypeRef(type));

    writeConformance(conf->getInheritedConformance(), abbrCodes, genericEnv);
    break;
  }
  }
}

void
Serializer::writeConformances(ArrayRef<ProtocolConformanceRef> conformances,
                              const std::array<unsigned, 256> &abbrCodes) {
  using namespace decls_block;

  for (auto conformance : conformances)
    writeConformance(conformance, abbrCodes);
}

void
Serializer::writeConformances(ArrayRef<ProtocolConformance*> conformances,
                              const std::array<unsigned, 256> &abbrCodes) {
  using namespace decls_block;

  for (auto conformance : conformances)
    writeConformance(conformance, abbrCodes);
}

static bool shouldSerializeMember(Decl *D) {
  switch (D->getKind()) {
  case DeclKind::Import:
  case DeclKind::InfixOperator:
  case DeclKind::PrefixOperator:
  case DeclKind::PostfixOperator:
  case DeclKind::TopLevelCode:
  case DeclKind::Extension:
  case DeclKind::Module:
  case DeclKind::PrecedenceGroup:
    if (D->getASTContext().LangOpts.AllowModuleWithCompilerErrors)
      return false;
    llvm_unreachable("decl should never be a member");

  case DeclKind::MissingMember:
    llvm_unreachable("should never need to reserialize a member placeholder");

  case DeclKind::IfConfig:
  case DeclKind::PoundDiagnostic:
    return false;

  case DeclKind::EnumCase:
    return false;

  case DeclKind::OpaqueType:
    return true;
      
  case DeclKind::EnumElement:
  case DeclKind::Protocol:
  case DeclKind::Constructor:
  case DeclKind::Destructor:
  case DeclKind::PatternBinding:
  case DeclKind::Subscript:
  case DeclKind::TypeAlias:
  case DeclKind::GenericTypeParam:
  case DeclKind::AssociatedType:
  case DeclKind::Enum:
  case DeclKind::Struct:
  case DeclKind::Class:
  case DeclKind::Var:
  case DeclKind::Param:
  case DeclKind::Func:
  case DeclKind::Accessor:
    return true;
  }

  llvm_unreachable("Unhandled DeclKind in switch.");
}

static serialization::AccessorKind getStableAccessorKind(swift::AccessorKind K){
  switch (K) {
#define ACCESSOR(ID) \
  case swift::AccessorKind::ID: return serialization::ID;
#include "swift/AST/AccessorKinds.def"
  }

  llvm_unreachable("Unhandled AccessorKind in switch.");
}

static serialization::CtorInitializerKind
getStableCtorInitializerKind(swift::CtorInitializerKind K){
  switch (K) {
#define CASE(NAME) \
  case swift::CtorInitializerKind::NAME: return serialization::NAME;
      CASE(Designated)
      CASE(Convenience)
      CASE(Factory)
      CASE(ConvenienceFactory)
#undef CASE
  }

  llvm_unreachable("Unhandled CtorInitializerKind in switch.");
}

static serialization::ClangDeclPathComponentKind
getStableClangDeclPathComponentKind(
                   StableSerializationPath::ExternalPath::ComponentKind kind) {
  switch (kind) {
#define CASE(ID) \
  case StableSerializationPath::ExternalPath::ID: \
    return serialization::ClangDeclPathComponentKind::ID;
  CASE(Record)
  CASE(Enum)
  CASE(Namespace)
  CASE(Typedef)
  CASE(TypedefAnonDecl)
  CASE(ObjCInterface)
  CASE(ObjCProtocol)
#undef CASE
  }
  llvm_unreachable("bad kind");
}

void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
  using namespace decls_block;

  unsigned abbrCode;

  switch (DC->getContextKind()) {
  case DeclContextKind::AbstractClosureExpr:
  case DeclContextKind::Initializer:
  case DeclContextKind::TopLevelCodeDecl:
  case DeclContextKind::SerializedLocal:
  case DeclContextKind::EnumElementDecl:
    llvm_unreachable("cannot cross-reference this context");

  case DeclContextKind::Module:
    llvm_unreachable("should only cross-reference something within a file");

  case DeclContextKind::FileUnit:
    abbrCode = DeclTypeAbbrCodes[XRefLayout::Code];
    XRefLayout::emitRecord(Out, ScratchRecord, abbrCode,
                           addContainingModuleRef(DC), pathLen);
    break;

  case DeclContextKind::GenericTypeDecl: {
    auto generic = cast<GenericTypeDecl>(DC);

    writeCrossReference(DC->getParent(), pathLen + 1);

    // Opaque return types are unnamed and need a special xref.
    if (auto opaque = dyn_cast<OpaqueTypeDecl>(generic)) {
      if (!opaque->hasName()) {
        abbrCode = DeclTypeAbbrCodes[XRefOpaqueReturnTypePathPieceLayout::Code];
        
        XRefOpaqueReturnTypePathPieceLayout::emitRecord(Out, ScratchRecord,
                  abbrCode,
                  addDeclBaseNameRef(opaque->getOpaqueReturnTypeIdentifier()));
        break;
      }
    }
      
    assert(generic->hasName());

    abbrCode = DeclTypeAbbrCodes[XRefTypePathPieceLayout::Code];

    Identifier discriminator;
    if (generic->isOutermostPrivateOrFilePrivateScope()) {
      auto *containingFile = cast<FileUnit>(generic->getModuleScopeContext());
      discriminator = containingFile->getDiscriminatorForPrivateValue(generic);
    }

    bool isProtocolExt = DC->getParent()->getExtendedProtocolDecl();

    XRefTypePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                        addDeclBaseNameRef(generic->getName()),
                                        addDeclBaseNameRef(discriminator),
                                        isProtocolExt,
                                        generic->hasClangNode());
    break;
  }

  case DeclContextKind::ExtensionDecl: {
    auto ext = cast<ExtensionDecl>(DC);
    auto nominal = ext->getExtendedNominal();
    assert(nominal);
    writeCrossReference(nominal, pathLen + 1);

    abbrCode = DeclTypeAbbrCodes[XRefExtensionPathPieceLayout::Code];
    CanGenericSignature genericSig(nullptr);
    if (ext->isConstrainedExtension()) {
      genericSig = ext->getGenericSignature().getCanonicalSignature();
    }
    XRefExtensionPathPieceLayout::emitRecord(
        Out, ScratchRecord, abbrCode, addContainingModuleRef(DC),
        addGenericSignatureRef(genericSig));
    break;
  }

  case DeclContextKind::SubscriptDecl: {
    auto SD = cast<SubscriptDecl>(DC);
    writeCrossReference(DC->getParent(), pathLen + 1);
    
    Type ty = SD->getInterfaceType()->getCanonicalType();

    abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
    bool isProtocolExt = SD->getDeclContext()->getExtendedProtocolDecl();
    XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                         addTypeRef(ty), SUBSCRIPT_ID,
                                         isProtocolExt, SD->hasClangNode(),
                                         SD->isStatic());
    break;
  }
      
  case DeclContextKind::AbstractFunctionDecl: {
    if (auto fn = dyn_cast<AccessorDecl>(DC)) {
      auto storage = fn->getStorage();
      writeCrossReference(storage->getDeclContext(), pathLen + 2);

      Type ty = storage->getInterfaceType()->getCanonicalType();
      IdentifierID nameID = addDeclBaseNameRef(storage->getBaseName());
      bool isProtocolExt = fn->getDeclContext()->getExtendedProtocolDecl();
      abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
      XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                           addTypeRef(ty), nameID,
                                           isProtocolExt,
                                           storage->hasClangNode(),
                                           storage->isStatic());

      abbrCode =
        DeclTypeAbbrCodes[XRefOperatorOrAccessorPathPieceLayout::Code];
      auto emptyID = addDeclBaseNameRef(Identifier());
      auto accessorKind = getStableAccessorKind(fn->getAccessorKind());
      assert(!fn->isObservingAccessor() &&
             "cannot form cross-reference to observing accessors");
      XRefOperatorOrAccessorPathPieceLayout::emitRecord(Out, ScratchRecord,
                                                        abbrCode, emptyID,
                                                        accessorKind);
      break;
    }

    auto fn = cast<AbstractFunctionDecl>(DC);
    writeCrossReference(DC->getParent(), pathLen + 1 + fn->isOperator());

    Type ty = fn->getInterfaceType()->getCanonicalType();

    if (auto ctor = dyn_cast<ConstructorDecl>(DC)) {
      abbrCode = DeclTypeAbbrCodes[XRefInitializerPathPieceLayout::Code];
      XRefInitializerPathPieceLayout::emitRecord(
        Out, ScratchRecord, abbrCode, addTypeRef(ty),
        (bool)ctor->getDeclContext()->getExtendedProtocolDecl(),
        ctor->hasClangNode(),
        getStableCtorInitializerKind(ctor->getInitKind()));
      break;
    }

    abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
    bool isProtocolExt = fn->getDeclContext()->getExtendedProtocolDecl();
    XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                         addTypeRef(ty),
                                         addDeclBaseNameRef(fn->getBaseName()),
                                         isProtocolExt, fn->hasClangNode(),
                                         fn->isStatic());

    if (fn->isOperator()) {
      // Encode the fixity as a filter on the func decls, to distinguish prefix
      // and postfix operators.
      auto op = cast<FuncDecl>(fn)->getOperatorDecl();
      assert(op);
      abbrCode = DeclTypeAbbrCodes[XRefOperatorOrAccessorPathPieceLayout::Code];
      auto emptyID = addDeclBaseNameRef(Identifier());
      auto fixity = getStableFixity(op->getFixity());
      XRefOperatorOrAccessorPathPieceLayout::emitRecord(Out, ScratchRecord,
                                                        abbrCode, emptyID,
                                                        fixity);
    }
    break;
  }
  }
}

void Serializer::writeCrossReference(const Decl *D) {
  using namespace decls_block;

  unsigned abbrCode;

  if (auto op = dyn_cast<OperatorDecl>(D)) {
    writeCrossReference(op->getDeclContext(), 1);

    abbrCode = DeclTypeAbbrCodes[XRefOperatorOrAccessorPathPieceLayout::Code];
    auto nameID = addDeclBaseNameRef(op->getName());
    auto fixity = getStableFixity(op->getFixity());
    XRefOperatorOrAccessorPathPieceLayout::emitRecord(Out, ScratchRecord,
                                                      abbrCode, nameID,
                                                      fixity);
    return;
  }

  if (auto prec = dyn_cast<PrecedenceGroupDecl>(D)) {
    writeCrossReference(prec->getDeclContext(), 1);

    abbrCode = DeclTypeAbbrCodes[XRefOperatorOrAccessorPathPieceLayout::Code];
    auto nameID = addDeclBaseNameRef(prec->getName());
    uint8_t fixity = OperatorKind::PrecedenceGroup;
    XRefOperatorOrAccessorPathPieceLayout::emitRecord(Out, ScratchRecord,
                                                      abbrCode, nameID,
                                                      fixity);
    return;
  }

  if (auto fn = dyn_cast<AbstractFunctionDecl>(D)) {
    // Functions are special because they might be operators.
    writeCrossReference(fn, 0);
    return;
  }

  writeCrossReference(D->getDeclContext());

  if (auto opaque = dyn_cast<OpaqueTypeDecl>(D)) {
    abbrCode = DeclTypeAbbrCodes[XRefOpaqueReturnTypePathPieceLayout::Code];
    XRefOpaqueReturnTypePathPieceLayout::emitRecord(Out, ScratchRecord,
                   abbrCode,
                   addDeclBaseNameRef(opaque->getOpaqueReturnTypeIdentifier()));
    return;
  }
  
  if (auto genericParam = dyn_cast<GenericTypeParamDecl>(D)) {
    assert(!D->getDeclContext()->isModuleScopeContext() &&
           "Cannot cross reference a generic type decl at module scope.");
    abbrCode = DeclTypeAbbrCodes[XRefGenericParamPathPieceLayout::Code];
    XRefGenericParamPathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                                genericParam->getDepth(),
                                                genericParam->getIndex());
    return;
  }

  bool isProtocolExt = D->getDeclContext()->getExtendedProtocolDecl();
  if (auto type = dyn_cast<TypeDecl>(D)) {
    abbrCode = DeclTypeAbbrCodes[XRefTypePathPieceLayout::Code];

    Identifier discriminator;
    if (type->isOutermostPrivateOrFilePrivateScope()) {
      auto *containingFile =
         cast<FileUnit>(type->getDeclContext()->getModuleScopeContext());
      discriminator = containingFile->getDiscriminatorForPrivateValue(type);
    }

    XRefTypePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                        addDeclBaseNameRef(type->getName()),
                                        addDeclBaseNameRef(discriminator),
                                        isProtocolExt, D->hasClangNode());
    return;
  }

  auto val = cast<ValueDecl>(D);
  auto ty = val->getInterfaceType()->getCanonicalType();
  abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
  IdentifierID iid = addDeclBaseNameRef(val->getBaseName());
  XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                       addTypeRef(ty), iid, isProtocolExt,
                                       D->hasClangNode(), val->isStatic());
}

/// Translate from the AST associativity enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableAssociativity(swift::Associativity assoc) {
  switch (assoc) {
  case swift::Associativity::Left:
    return serialization::Associativity::LeftAssociative;
  case swift::Associativity::Right:
    return serialization::Associativity::RightAssociative;
  case swift::Associativity::None:
    return serialization::Associativity::NonAssociative;
  }

  llvm_unreachable("Unhandled Associativity in switch.");
}

static serialization::StaticSpellingKind
getStableStaticSpelling(swift::StaticSpellingKind SS) {
  switch (SS) {
  case swift::StaticSpellingKind::None:
    return serialization::StaticSpellingKind::None;
  case swift::StaticSpellingKind::KeywordStatic:
    return serialization::StaticSpellingKind::KeywordStatic;
  case swift::StaticSpellingKind::KeywordClass:
    return serialization::StaticSpellingKind::KeywordClass;
  }

  llvm_unreachable("Unhandled StaticSpellingKind in switch.");
}

static uint8_t getRawStableAccessLevel(swift::AccessLevel access) {
  switch (access) {
#define CASE(NAME) \
  case swift::AccessLevel::NAME: \
    return static_cast<uint8_t>(serialization::AccessLevel::NAME);
  CASE(Private)
  CASE(FilePrivate)
  CASE(Internal)
  CASE(Public)
  CASE(Open)
#undef CASE
  }

  llvm_unreachable("Unhandled AccessLevel in switch.");
}

static serialization::SelfAccessKind
getStableSelfAccessKind(swift::SelfAccessKind MM) {
  switch (MM) {
  case swift::SelfAccessKind::NonMutating:
    return serialization::SelfAccessKind::NonMutating;
  case swift::SelfAccessKind::Mutating:
    return serialization::SelfAccessKind::Mutating;
  case swift::SelfAccessKind::Consuming:
    return serialization::SelfAccessKind::Consuming;
  }

  llvm_unreachable("Unhandled StaticSpellingKind in switch.");
}

#ifndef NDEBUG
// This is done with a macro so that we get a slightly more useful assertion.
# define DECL(KIND, PARENT)\
LLVM_ATTRIBUTE_UNUSED \
static void verifyAttrSerializable(const KIND ## Decl *D) {\
  for (auto Attr : D->getAttrs()) {\
    assert(Attr->canAppearOnDecl(D) && "attribute cannot appear on a " #KIND);\
  }\
}
# include "swift/AST/DeclNodes.def"

#else
static void verifyAttrSerializable(const Decl *D) {}
#endif

bool Serializer::isDeclXRef(const Decl *D) const {
  const DeclContext *topLevel = D->getDeclContext()->getModuleScopeContext();
  if (topLevel->getParentModule() != M)
    return true;
  if (!SF || topLevel == SF || topLevel == SF->getSynthesizedFile())
    return false;
  // Special-case for SIL generic parameter decls, which don't have a real
  // DeclContext.
  if (!isa<FileUnit>(topLevel)) {
    assert(isa<GenericTypeParamDecl>(D) && "unexpected decl kind");
    return false;
  }
  return true;
}

void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding,
                                                unsigned bindingIndex) {
  using namespace decls_block;
  auto abbrCode = DeclTypeAbbrCodes[PatternBindingInitializerLayout::Code];

  StringRef initStr;
  SmallString<128> scratch;
  auto varDecl = binding->getAnchoringVarDecl(bindingIndex);
  if (binding->hasInitStringRepresentation(bindingIndex) &&
      varDecl->isInitExposedToClients()) {
    initStr = binding->getInitStringRepresentation(bindingIndex, scratch);
  }

  PatternBindingInitializerLayout::emitRecord(Out, ScratchRecord,
                                              abbrCode, addDeclRef(binding),
                                              bindingIndex, initStr);
}

void
Serializer::writeDefaultArgumentInitializer(const DeclContext *parentContext,
                                            unsigned index) {
  using namespace decls_block;
  auto abbrCode = DeclTypeAbbrCodes[DefaultArgumentInitializerLayout::Code];
  auto parentID = addDeclContextRef(parentContext);
  DefaultArgumentInitializerLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                               parentID.getOpaqueValue(),
                                               index);
}

void Serializer::writeAbstractClosureExpr(const DeclContext *parentContext,
                                          Type Ty, bool isImplicit,
                                          unsigned discriminator) {
  using namespace decls_block;
  auto abbrCode = DeclTypeAbbrCodes[AbstractClosureExprLayout::Code];
  auto parentID = addDeclContextRef(parentContext);
  AbstractClosureExprLayout::emitRecord(Out, ScratchRecord, abbrCode,
                                        addTypeRef(Ty), isImplicit,
                                        discriminator,
                                        parentID.getOpaqueValue());
}

void Serializer::writeASTBlockEntity(const DeclContext *DC) {
  using namespace decls_block;

  assert(shouldSerializeAsLocalContext(DC) &&
         "should be serialized as a Decl instead");
  assert(LocalDeclContextsToSerialize.hasRef(DC));

  switch (DC->getContextKind()) {
  case DeclContextKind::AbstractClosureExpr: {
    auto ACE = cast<AbstractClosureExpr>(DC);
    writeAbstractClosureExpr(ACE->getParent(), ACE->getType(),
                             ACE->isImplicit(), ACE->getDiscriminator());
    break;
  }

  case DeclContextKind::Initializer: {
    if (auto PBI = dyn_cast<PatternBindingInitializer>(DC)) {
      writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex());
    } else if (auto DAI = dyn_cast<DefaultArgumentInitializer>(DC)) {
      writeDefaultArgumentInitializer(DAI->getParent(), DAI->getIndex());
    }
    break;
  }

  case DeclContextKind::TopLevelCodeDecl: {
    auto abbrCode = DeclTypeAbbrCodes[TopLevelCodeDeclContextLayout::Code];
    TopLevelCodeDeclContextLayout::emitRecord(Out, ScratchRecord, abbrCode,
        addDeclContextRef(DC->getParent()).getOpaqueValue());
    break;
  }

  // If we are merging already serialized modules with local decl contexts,
  // we handle them here in a similar fashion.
  case DeclContextKind::SerializedLocal: {
    auto local = cast<SerializedLocalDeclContext>(DC);
    switch (local->getLocalDeclContextKind()) {
    case LocalDeclContextKind::AbstractClosure: {
      auto SACE = cast<SerializedAbstractClosureExpr>(local);
      writeAbstractClosureExpr(SACE->getParent(), SACE->getType(),
                               SACE->isImplicit(), SACE->getDiscriminator());
      return;
    }
    case LocalDeclContextKind::DefaultArgumentInitializer: {
      auto DAI = cast<SerializedDefaultArgumentInitializer>(local);
      writeDefaultArgumentInitializer(DAI->getParent(), DAI->getIndex());
      return;
    }
    case LocalDeclContextKind::PatternBindingInitializer: {
      auto PBI = cast<SerializedPatternBindingInitializer>(local);
      writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex());
      return;
    }
    case LocalDeclContextKind::TopLevelCodeDecl: {
      auto abbrCode = DeclTypeAbbrCodes[TopLevelCodeDeclContextLayout::Code];
      TopLevelCodeDeclContextLayout::emitRecord(Out, ScratchRecord,
          abbrCode, addDeclContextRef(DC->getParent()).getOpaqueValue());
      return;
    }
    }
  }

  default:
    llvm_unreachable("Trying to write a DeclContext that isn't local");
  }
}

static ForeignErrorConventionKind getRawStableForeignErrorConventionKind(
                                    ForeignErrorConvention::Kind kind) {
  switch (kind) {
  case ForeignErrorConvention::ZeroResult:
    return ForeignErrorConventionKind::ZeroResult;
  case ForeignErrorConvention::NonZeroResult:
    return ForeignErrorConventionKind::NonZeroResult;
  case ForeignErrorConvention::ZeroPreservedResult:
    return ForeignErrorConventionKind::ZeroPreservedResult;
  case ForeignErrorConvention::NilResult:
    return ForeignErrorConventionKind::NilResult;
  case ForeignErrorConvention::NonNilError:
    return ForeignErrorConventionKind::NonNilError;
  }

  llvm_unreachable("Unhandled ForeignErrorConvention in switch.");
}

/// Translate from the AST VarDeclSpecifier enum to the
/// Serialization enum values, which are guaranteed to be stable.
static uint8_t getRawStableParamDeclSpecifier(swift::ParamDecl::Specifier sf) {
  switch (sf) {
  case swift::ParamDecl::Specifier::Default:
    return uint8_t(serialization::ParamDeclSpecifier::Default);
  case swift::ParamDecl::Specifier::InOut:
    return uint8_t(serialization::ParamDeclSpecifier::InOut);
  case swift::ParamDecl::Specifier::Shared:
    return uint8_t(serialization::ParamDeclSpecifier::Shared);
  case swift::ParamDecl::Specifier::Owned:
    return uint8_t(serialization::ParamDeclSpecifier::Owned);
  }
  llvm_unreachable("bad param decl specifier kind");
}

static uint8_t getRawStableVarDeclIntroducer(swift::VarDecl::Introducer intr) {
  switch (intr) {
  case swift::VarDecl::Introducer::Let:
    return uint8_t(serialization::VarDeclIntroducer::Let);
  case swift::VarDecl::Introducer::Var:
    return uint8_t(serialization::VarDeclIntroducer::Var);
  }
  llvm_unreachable("bad variable decl introducer kind");
}

/// Translate from the AST derivative function kind enum to the Serialization
/// enum values, which are guaranteed to be stable.
static uint8_t getRawStableAutoDiffDerivativeFunctionKind(
    swift::AutoDiffDerivativeFunctionKind kind) {
  switch (kind) {
  case swift::AutoDiffDerivativeFunctionKind::JVP:
    return uint8_t(serialization::AutoDiffDerivativeFunctionKind::JVP);
  case swift::AutoDiffDerivativeFunctionKind::VJP:
    return uint8_t(serialization::AutoDiffDerivativeFunctionKind::VJP);
  }
  llvm_unreachable("bad derivative function kind");
}

/// Returns true if the declaration of \p decl depends on \p problemContext
/// based on lexical nesting.
///
/// - \p decl is \p problemContext
/// - \p decl is declared within \p problemContext
/// - \p decl is declared in an extension of a type that depends on
///   \p problemContext
static bool contextDependsOn(const NominalTypeDecl *decl,
                             const DeclContext *problemContext) {
  SmallPtrSet<const ExtensionDecl *, 8> seenExtensionDCs;

  const DeclContext *dc = decl;
  do {
    if (dc == problemContext)
      return true;

    if (auto *extension = dyn_cast<ExtensionDecl>(dc)) {
      if (extension->isChildContextOf(problemContext))
        return true;

      // Avoid cycles when Left.Nested depends on Right.Nested somehow.
      bool isNewlySeen = seenExtensionDCs.insert(extension).second;
      if (!isNewlySeen)
        break;
      dc = extension->getSelfNominalTypeDecl();

    } else {
      dc = dc->getParent();
    }
  } while (dc);

  return false;
}

static void collectDependenciesFromType(llvm::SmallSetVector<Type, 4> &seen,
                                        Type ty,
                                        const DeclContext *excluding) {
  ty.visit([&](Type next) {
    auto *nominal = next->getAnyNominal();
    if (!nominal)
      return;
    if (contextDependsOn(nominal, excluding))
      return;
    seen.insert(nominal->getDeclaredInterfaceType());
  });
}

static void
collectDependenciesFromRequirement(llvm::SmallSetVector<Type, 4> &seen,
                                   const Requirement &req,
                                   const DeclContext *excluding) {
  collectDependenciesFromType(seen, req.getFirstType(), excluding);
  if (req.getKind() != RequirementKind::Layout)
    collectDependenciesFromType(seen, req.getSecondType(), excluding);
}

static SmallVector<Type, 4> collectDependenciesFromType(Type ty) {
  llvm::SmallSetVector<Type, 4> result;
  collectDependenciesFromType(result, ty, /*excluding*/nullptr);
  return result.takeVector();
}

class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
  Serializer &S;
  DeclID id;
  SmallVectorImpl<DeclID> &exportedPrespecializationDecls;
  bool didVerifyAttrs = false;
  template <typename DeclKind>
  void verifyAttrSerializable(const DeclKind *D) {
    ::verifyAttrSerializable(D);
    didVerifyAttrs = true;
  }

  void writeDeclAttribute(const Decl *D, const DeclAttribute *DA) {
    using namespace decls_block;

    // Completely ignore attributes that aren't serialized.
    if (DA->isNotSerialized())
      return;

    // Ignore attributes that have been marked invalid. (This usually means
    // type-checking removed them, but only provided a warning rather than an
    // error.)
    if (DA->isInvalid())
      return;

    switch (DA->getKind()) {
    case DAK_RawDocComment:
    case DAK_ReferenceOwnership: // Serialized as part of the type.
    case DAK_AccessControl:
    case DAK_SetterAccess:
    case DAK_ObjCBridged:
    case DAK_SynthesizedProtocol:
    case DAK_Implements:
    case DAK_ObjCRuntimeName:
    case DAK_RestatedObjCConformance:
    case DAK_ClangImporterSynthesizedType:
    case DAK_PrivateImport:
      llvm_unreachable("cannot serialize attribute");

    case DAK_Count:
      llvm_unreachable("not a real attribute");

  #define SIMPLE_DECL_ATTR(_, CLASS, ...)\
    case DAK_##CLASS: { \
      auto abbrCode = S.DeclTypeAbbrCodes[CLASS##DeclAttrLayout::Code]; \
      CLASS##DeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, \
                                        DA->isImplicit()); \
      return; \
    }
  #include "swift/AST/Attr.def"

    case DAK_SILGenName: {
      auto *theAttr = cast<SILGenNameAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[SILGenNameDeclAttrLayout::Code];
      SILGenNameDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
  	                                       theAttr->isImplicit(),
  	                                       theAttr->Name);
      return;
    }

    case DAK_CDecl: {
      auto *theAttr = cast<CDeclAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[CDeclDeclAttrLayout::Code];
      CDeclDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                      theAttr->isImplicit(),
                                      theAttr->Name);
      return;
    }

    case DAK_SPIAccessControl: {
      auto theAttr = cast<SPIAccessControlAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[SPIAccessControlDeclAttrLayout::Code];

      SmallVector<IdentifierID, 4> spis;
      for (auto spi : theAttr->getSPIGroups()) {
        assert(!spi.empty() && "Empty SPI name");
        spis.push_back(S.addDeclBaseNameRef(spi));
      }

      SPIAccessControlDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord,
                                                 abbrCode, spis);
      return;
    }

    case DAK_Alignment: {
      auto *theAlignment = cast<AlignmentAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[AlignmentDeclAttrLayout::Code];
      AlignmentDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                          theAlignment->isImplicit(),
                                          theAlignment->getValue());
      return;
    }

    case DAK_SwiftNativeObjCRuntimeBase: {
      auto *theBase = cast<SwiftNativeObjCRuntimeBaseAttr>(DA);
      auto abbrCode
        = S.DeclTypeAbbrCodes[SwiftNativeObjCRuntimeBaseDeclAttrLayout::Code];
      auto nameID = S.addDeclBaseNameRef(theBase->BaseClassName);

      SwiftNativeObjCRuntimeBaseDeclAttrLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode,
          theBase->isImplicit(), nameID);
      return;
    }

    case DAK_Semantics: {
      auto *theAttr = cast<SemanticsAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[SemanticsDeclAttrLayout::Code];
      SemanticsDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                        theAttr->isImplicit(),
                                        theAttr->Value);
      return;
    }

    case DAK_Inline: {
      auto *theAttr = cast<InlineAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[InlineDeclAttrLayout::Code];
      InlineDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                       (unsigned)theAttr->getKind());
      return;
    }

    case DAK_ActorIndependent: {
      auto *theAttr = cast<ActorIndependentAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[ActorIndependentDeclAttrLayout::Code];
      ActorIndependentDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord,
                                        abbrCode, (unsigned)theAttr->getKind());
      return;
    }

    case DAK_Optimize: {
      auto *theAttr = cast<OptimizeAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[OptimizeDeclAttrLayout::Code];
      OptimizeDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                         (unsigned)theAttr->getMode());
      return;
    }

    case DAK_Effects: {
      auto *theAttr = cast<EffectsAttr>(DA);
      auto abbrCode = S.DeclTypeAbbrCodes[EffectsDeclAttrLayout::Code];
      EffectsDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                       (unsigned)theAttr->getKind());
      return;
    }

    case DAK_OriginallyDefinedIn: {
      auto *theAttr = cast<OriginallyDefinedInAttr>(DA);
      ENCODE_VER_TUPLE(Moved, llvm::Optional<llvm::VersionTuple>(theAttr->MovedVersion));
      auto abbrCode = S.DeclTypeAbbrCodes[OriginallyDefinedInDeclAttrLayout::Code];
      llvm::SmallString<32> blob;
      blob.append(theAttr->OriginalModuleName.str());
      blob.push_back('\0');
      OriginallyDefinedInDeclAttrLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode,
          theAttr->isImplicit(),
          LIST_VER_TUPLE_PIECES(Moved),
          static_cast<unsigned>(theAttr->Platform),
          blob);
      return;
    }

    case DAK_Available: {
      auto *theAttr = cast<AvailableAttr>(DA);
      ENCODE_VER_TUPLE(Introduced, theAttr->Introduced)
      ENCODE_VER_TUPLE(Deprecated, theAttr->Deprecated)
      ENCODE_VER_TUPLE(Obsoleted, theAttr->Obsoleted)

      llvm::SmallString<32> blob;
      blob.append(theAttr->Message);
      blob.append(theAttr->Rename);
      auto abbrCode = S.DeclTypeAbbrCodes[AvailableDeclAttrLayout::Code];
      AvailableDeclAttrLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode,
          theAttr->isImplicit(),
          theAttr->isUnconditionallyUnavailable(),
          theAttr->isUnconditionallyDeprecated(),
          theAttr->isPackageDescriptionVersionSpecific(),
          LIST_VER_TUPLE_PIECES(Introduced),
          LIST_VER_TUPLE_PIECES(Deprecated),
          LIST_VER_TUPLE_PIECES(Obsoleted),
          static_cast<unsigned>(theAttr->Platform),
          theAttr->Message.size(),
          theAttr->Rename.size(),
          blob);
      return;
    }

    case DAK_ObjC: {
      auto *theAttr = cast<ObjCAttr>(DA);
      SmallVector<IdentifierID, 4> pieces;
      unsigned numArgs = 0;
      if (auto name = theAttr->getName()) {
        numArgs = name->getNumArgs() + 1;
        for (auto piece : name->getSelectorPieces()) {
          pieces.push_back(S.addDeclBaseNameRef(piece));
        }
      }
      auto abbrCode = S.DeclTypeAbbrCodes[ObjCDeclAttrLayout::Code];
      ObjCDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                     theAttr->isImplicit(),
                                     theAttr->isSwift3Inferred(),
                                     theAttr->isNameImplicit(), numArgs, pieces);
      return;
    }

    case DAK_Specialize: {
      auto abbrCode = S.DeclTypeAbbrCodes[SpecializeDeclAttrLayout::Code];
      auto attr = cast<SpecializeAttr>(DA);
      auto targetFun = attr->getTargetFunctionName();
      auto *targetFunDecl = attr->getTargetFunctionDecl(cast<ValueDecl>(D));

      SmallVector<IdentifierID, 4> pieces;

      // encodes whether this a a simple or compound name by adding one.
      size_t numArgs = 0;
      if (targetFun) {
        pieces.push_back(S.addDeclBaseNameRef(targetFun.getBaseName()));
        for (auto argName : targetFun.getArgumentNames())
          pieces.push_back(S.addDeclBaseNameRef(argName));
        if (targetFun.isSimpleName()) {
          assert(pieces.size() == 1);
          numArgs = 1;
        } else
          numArgs = pieces.size() + 1;
      }

      for (auto spi : attr->getSPIGroups()) {
        assert(!spi.empty() && "Empty SPI name");
        pieces.push_back(S.addDeclBaseNameRef(spi));
      }

      auto numSPIGroups = attr->getSPIGroups().size();
      assert(pieces.size() == numArgs + numSPIGroups ||
             pieces.size() == (numArgs - 1 + numSPIGroups));

      SpecializeDeclAttrLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode, (unsigned)attr->isExported(),
          (unsigned)attr->getSpecializationKind(),
          S.addGenericSignatureRef(attr->getSpecializedSignature()),
          S.addDeclRef(targetFunDecl), numArgs, numSPIGroups, pieces);
      return;
    }

    case DAK_DynamicReplacement: {
      auto abbrCode =
          S.DeclTypeAbbrCodes[DynamicReplacementDeclAttrLayout::Code];
      auto theAttr = cast<DynamicReplacementAttr>(DA);
      auto replacedFun = theAttr->getReplacedFunctionName();
      SmallVector<IdentifierID, 4> pieces;
      pieces.push_back(S.addDeclBaseNameRef(replacedFun.getBaseName()));
      for (auto argName : replacedFun.getArgumentNames())
        pieces.push_back(S.addDeclBaseNameRef(argName));
      auto *afd = cast<ValueDecl>(D)->getDynamicallyReplacedDecl();
      assert(afd && "Missing replaced decl!");
      DynamicReplacementDeclAttrLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode, false, /*implicit flag*/
          S.addDeclRef(afd), pieces.size(), pieces);
      return;
    }

    case DAK_TypeEraser: {
      auto abbrCode = S.DeclTypeAbbrCodes[TypeEraserDeclAttrLayout::Code];
      auto attr = cast<TypeEraserAttr>(DA);
      auto typeEraser = attr->getResolvedType(cast<ProtocolDecl>(D));
      assert(typeEraser && "Failed to resolve erasure type!");
      TypeEraserDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                           attr->isImplicit(),
                                           S.addTypeRef(typeEraser));
      return;
    }

    case DAK_Custom: {
      auto abbrCode = S.DeclTypeAbbrCodes[CustomDeclAttrLayout::Code];
      auto theAttr = cast<CustomAttr>(DA);
      CustomDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                       theAttr->isImplicit(),
                                       S.addTypeRef(theAttr->getType()));
      return;
    }

    case DAK_ProjectedValueProperty: {
      auto abbrCode =
          S.DeclTypeAbbrCodes[ProjectedValuePropertyDeclAttrLayout::Code];
      auto theAttr = cast<ProjectedValuePropertyAttr>(DA);
      ProjectedValuePropertyDeclAttrLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode, theAttr->isImplicit(),
        S.addDeclBaseNameRef(theAttr->ProjectionPropertyName));
      break;
    }

    case DAK_Differentiable: {
      auto abbrCode = S.DeclTypeAbbrCodes[DifferentiableDeclAttrLayout::Code];
      auto *attr = cast<DifferentiableAttr>(DA);
      assert(attr->getOriginalDeclaration() &&
             "`@differentiable` attribute should have original declaration set "
             "during construction or parsing");
      auto *paramIndices = attr->getParameterIndices();
      assert(paramIndices && "Parameter indices must be resolved");
      SmallVector<bool, 4> paramIndicesVector;
      for (unsigned i : range(paramIndices->getCapacity()))
        paramIndicesVector.push_back(paramIndices->contains(i));

      DifferentiableDeclAttrLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode, attr->isImplicit(),
          attr->isLinear(),
          S.addGenericSignatureRef(attr->getDerivativeGenericSignature()),
          paramIndicesVector);
      return;
    }

    case DAK_Derivative: {
      auto abbrCode = S.DeclTypeAbbrCodes[DerivativeDeclAttrLayout::Code];
      auto *attr = cast<DerivativeAttr>(DA);
      auto &ctx = S.getASTContext();
      assert(attr->getOriginalFunction(ctx) &&
             "`@derivative` attribute should have original declaration set "
             "during construction or parsing");
      auto origDeclNameRef = attr->getOriginalFunctionName();
      auto origName = origDeclNameRef.Name.getBaseName();
      IdentifierID origNameId = S.addDeclBaseNameRef(origName);
      DeclID origDeclID = S.addDeclRef(attr->getOriginalFunction(ctx));
      auto derivativeKind =
          getRawStableAutoDiffDerivativeFunctionKind(attr->getDerivativeKind());
      uint8_t rawAccessorKind = 0;
      auto origAccessorKind = origDeclNameRef.AccessorKind;
      if (origAccessorKind)
        rawAccessorKind = uint8_t(getStableAccessorKind(*origAccessorKind));
      auto *parameterIndices = attr->getParameterIndices();
      assert(parameterIndices && "Parameter indices must be resolved");
      SmallVector<bool, 4> paramIndicesVector;
      for (unsigned i : range(parameterIndices->getCapacity()))
        paramIndicesVector.push_back(parameterIndices->contains(i));
      DerivativeDeclAttrLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode, attr->isImplicit(), origNameId,
          origAccessorKind.hasValue(), rawAccessorKind, origDeclID,
          derivativeKind, paramIndicesVector);
      return;
    }

    case DAK_Transpose: {
      auto abbrCode = S.DeclTypeAbbrCodes[TransposeDeclAttrLayout::Code];
      auto *attr = cast<TransposeAttr>(DA);
      assert(attr->getOriginalFunction() &&
             "`@transpose` attribute should have original declaration set "
             "during construction or parsing");
      auto origName = attr->getOriginalFunctionName().Name.getBaseName();
      IdentifierID origNameId = S.addDeclBaseNameRef(origName);
      DeclID origDeclID = S.addDeclRef(attr->getOriginalFunction());
      auto *parameterIndices = attr->getParameterIndices();
      assert(parameterIndices && "Parameter indices must be resolved");
      SmallVector<bool, 4> paramIndicesVector;
      for (unsigned i : range(parameterIndices->getCapacity()))
        paramIndicesVector.push_back(parameterIndices->contains(i));
      TransposeDeclAttrLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode, attr->isImplicit(), origNameId,
          origDeclID, paramIndicesVector);
      return;
    }
    }
  }

  void writeDiscriminatorsIfNeeded(const ValueDecl *value) {
    using namespace decls_block;

    auto *storage = dyn_cast<AbstractStorageDecl>(value);
    auto access = value->getFormalAccess();
    // Emit the private discriminator for private decls.
    // FIXME: We shouldn't need to encode this for /all/ private decls.
    // In theory we can follow the same rules as mangling and only include
    // the outermost private context.
    bool shouldEmitPrivateDiscriminator =
        access <= swift::AccessLevel::FilePrivate &&
        !value->getDeclContext()->isLocalContext();

    // Emit the the filename for private mapping for private decls and
    // decls with private accessors if compiled with -enable-private-imports.
    bool shouldEmitFilenameForPrivate =
        S.M->arePrivateImportsEnabled() &&
        !value->getDeclContext()->isLocalContext() &&
        (access <= swift::AccessLevel::FilePrivate ||
         (storage &&
          storage->getFormalAccess() >= swift::AccessLevel::Internal &&
          storage->hasPrivateAccessor()));

    if (shouldEmitFilenameForPrivate || shouldEmitPrivateDiscriminator) {
      auto topLevelSubcontext = value->getDeclContext()->getModuleScopeContext();
      if (auto *enclosingFile = dyn_cast<FileUnit>(topLevelSubcontext)) {
        if (shouldEmitPrivateDiscriminator) {
          Identifier discriminator =
              enclosingFile->getDiscriminatorForPrivateValue(value);
          unsigned abbrCode =
              S.DeclTypeAbbrCodes[PrivateDiscriminatorLayout::Code];
          PrivateDiscriminatorLayout::emitRecord(
              S.Out, S.ScratchRecord, abbrCode,
              S.addDeclBaseNameRef(discriminator));
        }
        auto getFilename = [](FileUnit *enclosingFile,
                              const ValueDecl *decl) -> StringRef {
          if (auto *SF = dyn_cast<SourceFile>(enclosingFile)) {
            return llvm::sys::path::filename(SF->getFilename());
          } else if (auto *LF = dyn_cast<LoadedFile>(enclosingFile)) {
            return LF->getFilenameForPrivateDecl(decl);
          }
          return StringRef();
        };
        if (shouldEmitFilenameForPrivate) {
          auto filename = getFilename(enclosingFile, value);
          if (!filename.empty()) {
            auto filenameID = S.addFilename(filename);
            FilenameForPrivateLayout::emitRecord(
                S.Out, S.ScratchRecord,
                S.DeclTypeAbbrCodes[FilenameForPrivateLayout::Code],
                filenameID);
          }
        }
      }
    }

    if (value->getDeclContext()->isLocalContext()) {
      auto discriminator = value->getLocalDiscriminator();
      auto abbrCode = S.DeclTypeAbbrCodes[LocalDiscriminatorLayout::Code];
      LocalDiscriminatorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                           discriminator);
    }
  }

  void writeForeignErrorConvention(const ForeignErrorConvention &fec) {
    using namespace decls_block;

    auto kind = getRawStableForeignErrorConventionKind(fec.getKind());
    uint8_t isOwned = fec.isErrorOwned() == ForeignErrorConvention::IsOwned;
    uint8_t isReplaced = bool(fec.isErrorParameterReplacedWithVoid());
    TypeID errorParameterTypeID = S.addTypeRef(fec.getErrorParameterType());
    TypeID resultTypeID;
    switch (fec.getKind()) {
    case ForeignErrorConvention::ZeroResult:
    case ForeignErrorConvention::NonZeroResult:
      resultTypeID = S.addTypeRef(fec.getResultType());
      break;

    case ForeignErrorConvention::ZeroPreservedResult:
    case ForeignErrorConvention::NilResult:
    case ForeignErrorConvention::NonNilError:
      resultTypeID = 0;
      break;
    }

    auto abbrCode = S.DeclTypeAbbrCodes[ForeignErrorConventionLayout::Code];
    ForeignErrorConventionLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                             static_cast<uint8_t>(kind),
                                             isOwned,
                                             isReplaced,
                                             fec.getErrorParameterIndex(),
                                             errorParameterTypeID,
                                             resultTypeID);
  }

  void writeGenericParams(const GenericParamList *genericParams) {
    using namespace decls_block;

    // Don't write anything if there are no generic params.
    if (!genericParams)
      return;

    SmallVector<DeclID, 4> paramIDs;
    for (auto next : genericParams->getParams())
      paramIDs.push_back(S.addDeclRef(next));

    unsigned abbrCode = S.DeclTypeAbbrCodes[GenericParamListLayout::Code];
    GenericParamListLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                       paramIDs);
  }

  void writeParameterList(const ParameterList *PL) {
    using namespace decls_block;

    SmallVector<DeclID, 8> paramIDs;
    for (const ParamDecl *param : *PL)
      paramIDs.push_back(S.addDeclRef(param));

    unsigned abbrCode = S.DeclTypeAbbrCodes[ParameterListLayout::Code];
    ParameterListLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, paramIDs);
  }

  /// Writes an array of members for a decl context.
  ///
  /// \param parentID The DeclID of the context.
  /// \param members The decls within the context.
  /// \param isClass True if the context could be a class context (class,
  ///        class extension, or protocol).
  void writeMembers(DeclID parentID, DeclRange members, bool isClass) {
    using namespace decls_block;

    SmallVector<DeclID, 16> memberIDs;
    for (auto member : members) {
      if (!shouldSerializeMember(member))
        continue;

      DeclID memberID = S.addDeclRef(member);
      memberIDs.push_back(memberID);

      if (auto VD = dyn_cast<ValueDecl>(member)) {
        // Record parent->members in subtable of DeclMemberNames
        if (VD->hasName() &&
            !VD->getBaseName().empty()) {
          std::unique_ptr<DeclMembersTable> &memberTable =
            S.DeclMemberNames[VD->getBaseName()].second;
          if (!memberTable) {
            memberTable = std::make_unique<DeclMembersTable>();
          }
          (*memberTable)[parentID].push_back(memberID);
        }

        // Same as above, but for @_implements attributes
        if (auto A = VD->getAttrs().getAttribute<ImplementsAttr>()) {
          std::unique_ptr<DeclMembersTable> &memberTable =
            S.DeclMemberNames[A->getMemberName().getBaseName()].second;
          if (!memberTable) {
            memberTable = std::make_unique<DeclMembersTable>();
          }
          (*memberTable)[parentID].push_back(memberID);
        }

        // Possibly add a record to ClassMembersForDynamicLookup too.
        if (isClass) {
          if (VD->canBeAccessedByDynamicLookup()) {
            auto &list = S.ClassMembersForDynamicLookup[VD->getBaseName()];
            list.push_back({getKindForTable(VD), memberID});
          }
        }
      }
    }

    unsigned abbrCode = S.DeclTypeAbbrCodes[MembersLayout::Code];
    MembersLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, memberIDs);
  }

  /// Writes the given pattern, recursively.
  void writePattern(const Pattern *pattern) {
    using namespace decls_block;

    // Retrieve the type of the pattern.
    auto getPatternType = [&] {
      if (!pattern->hasType()) {
        if (S.getASTContext().LangOpts.AllowModuleWithCompilerErrors)
          return ErrorType::get(S.getASTContext());
        llvm_unreachable("all nodes should have types");
      }

      Type type = pattern->getType();

      // If we have a contextual type, map out to an interface type.
      if (type->hasArchetype())
        type = type->mapTypeOutOfContext();

      return type;
    };

    assert(pattern && "null pattern");
    switch (pattern->getKind()) {
    case PatternKind::Paren: {
      unsigned abbrCode = S.DeclTypeAbbrCodes[ParenPatternLayout::Code];
      ParenPatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode);
      writePattern(cast<ParenPattern>(pattern)->getSubPattern());
      break;
    }
    case PatternKind::Tuple: {
      auto tuple = cast<TuplePattern>(pattern);

      unsigned abbrCode = S.DeclTypeAbbrCodes[TuplePatternLayout::Code];
      TuplePatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                     S.addTypeRef(getPatternType()),
                                     tuple->getNumElements());

      abbrCode = S.DeclTypeAbbrCodes[TuplePatternEltLayout::Code];
      for (auto &elt : tuple->getElements()) {
        // FIXME: Default argument expressions?
        TuplePatternEltLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                          S.addDeclBaseNameRef(elt.getLabel()));
        writePattern(elt.getPattern());
      }
      break;
    }
    case PatternKind::Named: {
      auto named = cast<NamedPattern>(pattern);

      unsigned abbrCode = S.DeclTypeAbbrCodes[NamedPatternLayout::Code];
      NamedPatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                     S.addDeclRef(named->getDecl()),
                                     S.addTypeRef(getPatternType()));
      break;
    }
    case PatternKind::Any: {
      unsigned abbrCode = S.DeclTypeAbbrCodes[AnyPatternLayout::Code];
      AnyPatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                   S.addTypeRef(getPatternType()));
      break;
    }
    case PatternKind::Typed: {
      auto typed = cast<TypedPattern>(pattern);

      unsigned abbrCode = S.DeclTypeAbbrCodes[TypedPatternLayout::Code];
      TypedPatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                     S.addTypeRef(getPatternType()));
      writePattern(typed->getSubPattern());
      break;
    }
    case PatternKind::Is:
    case PatternKind::EnumElement:
    case PatternKind::OptionalSome:
    case PatternKind::Bool:
    case PatternKind::Expr:
      llvm_unreachable("Refutable patterns cannot be serialized");

    case PatternKind::Binding: {
      auto var = cast<BindingPattern>(pattern);

      unsigned abbrCode = S.DeclTypeAbbrCodes[BindingPatternLayout::Code];
      BindingPatternLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                       var->isLet());
      writePattern(var->getSubPattern());
      break;
    }
    }
  }

  void writeDefaultWitnessTable(const ProtocolDecl *proto) {
    using namespace decls_block;

    SmallVector<DeclID, 16> witnessIDs;

    for (auto member : proto->getMembers()) {
      if (auto *value = dyn_cast<ValueDecl>(member)) {
        auto witness = proto->getDefaultWitness(value);
        if (!witness)
          continue;

        DeclID requirementID = S.addDeclRef(value);
        DeclID witnessID = S.addDeclRef(witness.getDecl());
        witnessIDs.push_back(requirementID);
        witnessIDs.push_back(witnessID);

        // FIXME: Substitutions
      }
    }

    unsigned abbrCode = S.DeclTypeAbbrCodes[DefaultWitnessTableLayout::Code];
    DefaultWitnessTableLayout::emitRecord(S.Out, S.ScratchRecord,
                                          abbrCode, witnessIDs);
  }

  /// Writes the body text of the provided funciton, if the function is
  /// inlinable and has body text.
  void writeInlinableBodyTextIfNeeded(const AbstractFunctionDecl *AFD) {
    using namespace decls_block;
    // Only serialize the text for an inlinable function body if we're emitting
    // a partial module. It's not needed in the final module file, but it's
    // needed in partial modules so you can emit a module interface after
    // merging them.
    if (!S.SF) return;

    if (AFD->getResilienceExpansion() != swift::ResilienceExpansion::Minimal)
      return;

    if (!AFD->hasInlinableBodyText()) return;
    SmallString<128> scratch;
    auto body = AFD->getInlinableBodyText(scratch);

    unsigned abbrCode = S.DeclTypeAbbrCodes[InlinableBodyTextLayout::Code];
    InlinableBodyTextLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, body);
  }

  unsigned getNumberOfRequiredVTableEntries(
      const AbstractStorageDecl *storage) const {
    unsigned count = 0;
    for (auto *accessor : storage->getAllAccessors()) {
      if (accessor->needsNewVTableEntry())
        count++;
    }
    return count;
  }

  /// Returns true if a client can still use decls that override \p overridden
  /// even if \p overridden itself isn't available (isn't found, can't be
  /// imported, can't be deserialized, whatever).
  ///
  /// This should be kept conservative. Compiler crashes are still better than
  /// miscompiles.
  static bool overriddenDeclAffectsABI(const ValueDecl *overridden) {
    if (!overridden)
      return false;
    // There's one case where we know a declaration doesn't affect the ABI of
    // its overrides after they've been compiled: if the declaration is '@objc'
    // and 'dynamic'. In that case, all accesses to the method or property will
    // go through the Objective-C method tables anyway.
    if (overridden->hasClangNode() || overridden->shouldUseObjCDispatch())
      return false;
    return true;
  }

public:
  DeclSerializer(Serializer &S, DeclID id,
                 SmallVectorImpl<DeclID> &exportedPrespecializationDecls)
      : S(S), id(id),
        exportedPrespecializationDecls(exportedPrespecializationDecls) {}
  ~DeclSerializer() {
    assert(didVerifyAttrs);
  }

  void visit(const Decl *D) {
    // Emit attributes (if any).
    for (auto Attr : D->getAttrs())
      writeDeclAttribute(D, Attr);

    if (auto *value = dyn_cast<ValueDecl>(D))
      writeDiscriminatorsIfNeeded(value);

    if (auto *afd = dyn_cast<AbstractFunctionDecl>(D)) {
      noteUseOfExportedPrespecialization(afd);
    }

    DeclVisitor<DeclSerializer>::visit(const_cast<Decl *>(D));
  }

  void noteUseOfExportedPrespecialization(const AbstractFunctionDecl *afd) {
    for (auto *A : afd->getAttrs().getAttributes<SpecializeAttr>()) {
      auto *SA = cast<SpecializeAttr>(A);
      if (!SA->isExported())
        continue;
      if (auto *targetFunctionDecl = SA->getTargetFunctionDecl(afd)) {
        exportedPrespecializationDecls.push_back(S.addDeclRef(afd));
      }
    }
  }

  /// If this gets referenced, we forgot to handle a decl.
  void visitDecl(const Decl *) = delete;

  void visitExtensionDecl(const ExtensionDecl *extension) {
    using namespace decls_block;

    verifyAttrSerializable(extension);

    auto contextID = S.addDeclContextRef(extension->getDeclContext());
    Type extendedType = extension->getExtendedType();
    assert(!extendedType->hasArchetype());

    // FIXME: Use the canonical type here in order to minimize circularity
    // issues at deserialization time. A known problematic case here is
    // "extension of typealias Foo"; "typealias Foo = SomeKit.Bar"; and then
    // trying to import Bar accidentally asking for all of its extensions
    // (perhaps because we're searching for a conformance).
    //
    // We could limit this to only the problematic cases, but it seems like a
    // simpler user model to just always desugar extension types.
    extendedType = extendedType->getCanonicalType();

    auto conformances = extension->getLocalConformances(
                          ConformanceLookupKind::All);

    SmallVector<TypeID, 8> inheritedAndDependencyTypes;
    for (auto inherited : extension->getInherited()) {
      assert(!inherited.getType()->hasArchetype());
      inheritedAndDependencyTypes.push_back(S.addTypeRef(inherited.getType()));
    }
    size_t numInherited = inheritedAndDependencyTypes.size();

    llvm::SmallSetVector<Type, 4> dependencies;
    collectDependenciesFromType(
      dependencies, extendedType, /*excluding*/nullptr);
    for (Requirement req : extension->getGenericRequirements()) {
      collectDependenciesFromRequirement(dependencies, req,
                                         /*excluding*/nullptr);
    }
    for (auto dependencyTy : dependencies)
      inheritedAndDependencyTypes.push_back(S.addTypeRef(dependencyTy));

    unsigned abbrCode = S.DeclTypeAbbrCodes[ExtensionLayout::Code];
    auto extendedNominal = extension->getExtendedNominal();
    ExtensionLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                S.addTypeRef(extendedType),
                                S.addDeclRef(extendedNominal),
                                contextID.getOpaqueValue(),
                                extension->isImplicit(),
                                S.addGenericSignatureRef(
                                           extension->getGenericSignature()),
                                conformances.size(),
                                numInherited,
                                inheritedAndDependencyTypes);

    bool isClassExtension = false;
    if (extendedNominal) {
      isClassExtension = isa<ClassDecl>(extendedNominal) ||
                         isa<ProtocolDecl>(extendedNominal);
    }

    // Extensions of nested generic types have multiple generic parameter
    // lists. Collect them all, from the innermost to outermost.
    SmallVector<GenericParamList *, 2> allGenericParams;
    for (auto *genericParams = extension->getGenericParams();
         genericParams != nullptr;
         genericParams = genericParams->getOuterParameters()) {
      allGenericParams.push_back(genericParams);
    }

    // Reverse the list, and write the parameter lists, from outermost
    // to innermost.
    for (auto *genericParams : llvm::reverse(allGenericParams))
      writeGenericParams(genericParams);

    writeMembers(id, extension->getMembers(), isClassExtension);
    S.writeConformances(conformances, S.DeclTypeAbbrCodes);
  }

  void visitPatternBindingDecl(const PatternBindingDecl *binding) {
    using namespace decls_block;
    verifyAttrSerializable(binding);

    auto contextID = S.addDeclContextRef(binding->getDeclContext());
    SmallVector<uint64_t, 2> initContextIDs;
    for (unsigned i : range(binding->getNumPatternEntries())) {
      auto initContextID =
          S.addDeclContextRef(binding->getInitContext(i));
      if (!initContextIDs.empty()) {
        initContextIDs.push_back(initContextID.getOpaqueValue());
      } else if (initContextID) {
        initContextIDs.append(i, 0);
        initContextIDs.push_back(initContextID.getOpaqueValue());
      }
    }

    unsigned abbrCode = S.DeclTypeAbbrCodes[PatternBindingLayout::Code];
    PatternBindingLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode, contextID.getOpaqueValue(),
        binding->isImplicit(), binding->isStatic(),
        uint8_t(getStableStaticSpelling(binding->getStaticSpelling())),
        binding->getNumPatternEntries(),
        initContextIDs);

    DeclContext *owningDC = nullptr;
    if (binding->getDeclContext()->isTypeContext())
      owningDC = binding->getDeclContext();

    for (auto entryIdx : range(binding->getNumPatternEntries())) {
      writePattern(binding->getPattern(entryIdx));
      // Ignore initializer; external clients don't need to know about it.
    }
  }

  void visitPrecedenceGroupDecl(const PrecedenceGroupDecl *group) {
    using namespace decls_block;
    verifyAttrSerializable(group);

    auto contextID = S.addDeclContextRef(group->getDeclContext());
    auto nameID = S.addDeclBaseNameRef(group->getName());
    auto associativity = getRawStableAssociativity(group->getAssociativity());

    SmallVector<DeclID, 8> relations;
    for (auto &rel : group->getHigherThan())
      relations.push_back(S.addDeclRef(rel.Group));
    for (auto &rel : group->getLowerThan())
      relations.push_back(S.addDeclRef(rel.Group));

    unsigned abbrCode = S.DeclTypeAbbrCodes[PrecedenceGroupLayout::Code];
    PrecedenceGroupLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                      nameID, contextID.getOpaqueValue(),
                                      associativity, group->isAssignment(),
                                      group->getHigherThan().size(),
                                      relations);
  }

  void visitInfixOperatorDecl(const InfixOperatorDecl *op) {
    using namespace decls_block;
    verifyAttrSerializable(op);

    auto contextID = S.addDeclContextRef(op->getDeclContext());
    auto nameID = S.addDeclBaseNameRef(op->getName());
    auto groupID = S.addDeclRef(op->getPrecedenceGroup());
    SmallVector<DeclID, 1> designatedNominalTypeDeclIDs;
    for (auto *decl : op->getDesignatedNominalTypes())
      designatedNominalTypeDeclIDs.push_back(S.addDeclRef(decl));

    unsigned abbrCode = S.DeclTypeAbbrCodes[InfixOperatorLayout::Code];
    InfixOperatorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, nameID,
                                    contextID.getOpaqueValue(), groupID,
                                    designatedNominalTypeDeclIDs);

  }

  template <typename Layout>
  void visitUnaryOperatorDecl(const OperatorDecl *op) {
    auto contextID = S.addDeclContextRef(op->getDeclContext());
    SmallVector<DeclID, 1> designatedNominalTypeDeclIDs;
    for (auto *decl : op->getDesignatedNominalTypes())
      designatedNominalTypeDeclIDs.push_back(S.addDeclRef(decl));

    unsigned abbrCode = S.DeclTypeAbbrCodes[Layout::Code];
    Layout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                       S.addDeclBaseNameRef(op->getName()),
                       contextID.getOpaqueValue(),
                       designatedNominalTypeDeclIDs);
  }

  void visitPrefixOperatorDecl(const PrefixOperatorDecl *op) {
    using namespace decls_block;
    verifyAttrSerializable(op);
    visitUnaryOperatorDecl<PrefixOperatorLayout>(op);
  }

  void visitPostfixOperatorDecl(const PostfixOperatorDecl *op) {
    using namespace decls_block;
    verifyAttrSerializable(op);
    visitUnaryOperatorDecl<PostfixOperatorLayout>(op);
  }

  void visitTypeAliasDecl(const TypeAliasDecl *typeAlias) {
    using namespace decls_block;
    assert(!typeAlias->isObjC() && "ObjC typealias is not meaningful");
    verifyAttrSerializable(typeAlias);

    auto contextID = S.addDeclContextRef(typeAlias->getDeclContext());

    auto underlying = typeAlias->getUnderlyingType();

    llvm::SmallSetVector<Type, 4> dependencies;
    collectDependenciesFromType(dependencies, underlying->getCanonicalType(),
                                /*excluding*/nullptr);
    for (Requirement req : typeAlias->getGenericRequirements()) {
      collectDependenciesFromRequirement(dependencies, req,
                                         /*excluding*/nullptr);
    }

    SmallVector<TypeID, 4> dependencyIDs;
    for (Type dep : dependencies)
      dependencyIDs.push_back(S.addTypeRef(dep));

    uint8_t rawAccessLevel =
      getRawStableAccessLevel(typeAlias->getFormalAccess());

    unsigned abbrCode = S.DeclTypeAbbrCodes[TypeAliasLayout::Code];
    TypeAliasLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                S.addDeclBaseNameRef(typeAlias->getName()),
                                contextID.getOpaqueValue(),
                                S.addTypeRef(underlying),
                                /*no longer used*/TypeID(),
                                typeAlias->isImplicit(),
                                S.addGenericSignatureRef(
                                             typeAlias->getGenericSignature()),
                                rawAccessLevel,
                                dependencyIDs);
    writeGenericParams(typeAlias->getGenericParams());
  }

  void visitGenericTypeParamDecl(const GenericTypeParamDecl *genericParam) {
    using namespace decls_block;
    verifyAttrSerializable(genericParam);

    unsigned abbrCode = S.DeclTypeAbbrCodes[GenericTypeParamDeclLayout::Code];
    GenericTypeParamDeclLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                S.addDeclBaseNameRef(genericParam->getName()),
                                genericParam->isImplicit(),
                                genericParam->getDepth(),
                                genericParam->getIndex());
  }

  void visitAssociatedTypeDecl(const AssociatedTypeDecl *assocType) {
    using namespace decls_block;
    verifyAttrSerializable(assocType);

    auto contextID = S.addDeclContextRef(assocType->getDeclContext());
    SmallVector<DeclID, 4> overriddenAssocTypeIDs;
    for (auto overridden : assocType->getOverriddenDecls()) {
      overriddenAssocTypeIDs.push_back(S.addDeclRef(overridden));
    }

    unsigned abbrCode = S.DeclTypeAbbrCodes[AssociatedTypeDeclLayout::Code];
    AssociatedTypeDeclLayout::emitRecord(
      S.Out, S.ScratchRecord, abbrCode,
      S.addDeclBaseNameRef(assocType->getName()),
      contextID.getOpaqueValue(),
      S.addTypeRef(assocType->getDefaultDefinitionType()),
      assocType->isImplicit(),
      overriddenAssocTypeIDs);
  }

  void visitStructDecl(const StructDecl *theStruct) {
    using namespace decls_block;
    verifyAttrSerializable(theStruct);

    auto contextID = S.addDeclContextRef(theStruct->getDeclContext());

    auto conformances = theStruct->getLocalConformances(
                          ConformanceLookupKind::All);

    SmallVector<TypeID, 4> inheritedAndDependencyTypes;
    for (auto inherited : theStruct->getInherited()) {
      assert(!inherited.getType()->hasArchetype());
      inheritedAndDependencyTypes.push_back(S.addTypeRef(inherited.getType()));
    }

    llvm::SmallSetVector<Type, 4> dependencyTypes;
    for (Requirement req : theStruct->getGenericRequirements()) {
      collectDependenciesFromRequirement(dependencyTypes, req,
                                         /*excluding*/nullptr);
    }
    for (Type ty : dependencyTypes)
      inheritedAndDependencyTypes.push_back(S.addTypeRef(ty));

    uint8_t rawAccessLevel =
      getRawStableAccessLevel(theStruct->getFormalAccess());

    unsigned abbrCode = S.DeclTypeAbbrCodes[StructLayout::Code];
    StructLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                             S.addDeclBaseNameRef(theStruct->getName()),
                             contextID.getOpaqueValue(),
                             theStruct->isImplicit(),
                             theStruct->isObjC(),
                             S.addGenericSignatureRef(
                                            theStruct->getGenericSignature()),
                             rawAccessLevel,
                             conformances.size(),
                             theStruct->getInherited().size(),
                             inheritedAndDependencyTypes);


    writeGenericParams(theStruct->getGenericParams());
    writeMembers(id, theStruct->getMembers(), false);
    S.writeConformances(conformances, S.DeclTypeAbbrCodes);
  }

  void visitEnumDecl(const EnumDecl *theEnum) {
    using namespace decls_block;
    verifyAttrSerializable(theEnum);

    auto contextID = S.addDeclContextRef(theEnum->getDeclContext());

    auto conformances = theEnum->getLocalConformances(
                          ConformanceLookupKind::All);

    SmallVector<TypeID, 4> inheritedAndDependencyTypes;
    for (auto inherited : theEnum->getInherited()) {
      assert(!inherited.getType()->hasArchetype());
      inheritedAndDependencyTypes.push_back(S.addTypeRef(inherited.getType()));
    }

    llvm::SmallSetVector<Type, 4> dependencyTypes;
    for (const EnumElementDecl *nextElt : theEnum->getAllElements()) {
      if (!nextElt->hasAssociatedValues())
        continue;
      // FIXME: Types in the same module are still important for enums. It's
      // possible an enum element has a payload that references a type
      // declaration from the same module that can't be imported (for whatever
      // reason). However, we need a more robust handling of deserialization
      // dependencies that can handle circularities. rdar://problem/32359173
      collectDependenciesFromType(dependencyTypes,
                                  nextElt->getArgumentInterfaceType(),
                                  /*excluding*/theEnum->getParentModule());
    }
    for (Requirement req : theEnum->getGenericRequirements()) {
      collectDependenciesFromRequirement(dependencyTypes, req,
                                         /*excluding*/nullptr);
    }
    for (Type ty : dependencyTypes)
      inheritedAndDependencyTypes.push_back(S.addTypeRef(ty));

    uint8_t rawAccessLevel =
      getRawStableAccessLevel(theEnum->getFormalAccess());

    unsigned abbrCode = S.DeclTypeAbbrCodes[EnumLayout::Code];
    EnumLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                            S.addDeclBaseNameRef(theEnum->getName()),
                            contextID.getOpaqueValue(),
                            theEnum->isImplicit(),
                            theEnum->isObjC(),
                            S.addGenericSignatureRef(
                                             theEnum->getGenericSignature()),
                            S.addTypeRef(theEnum->getRawType()),
                            rawAccessLevel,
                            conformances.size(),
                            theEnum->getInherited().size(),
                            inheritedAndDependencyTypes);

    writeGenericParams(theEnum->getGenericParams());
    writeMembers(id, theEnum->getMembers(), false);
    S.writeConformances(conformances, S.DeclTypeAbbrCodes);
  }

  void visitClassDecl(const ClassDecl *theClass) {
    using namespace decls_block;
    verifyAttrSerializable(theClass);
    assert(!theClass->isForeign());

    auto contextID = S.addDeclContextRef(theClass->getDeclContext());

    auto conformances = theClass->getLocalConformances(
                          ConformanceLookupKind::NonInherited);

    SmallVector<TypeID, 4> inheritedAndDependencyTypes;
    for (auto inherited : theClass->getInherited()) {
      assert(!inherited.getType()->hasArchetype());
      inheritedAndDependencyTypes.push_back(S.addTypeRef(inherited.getType()));
    }

    llvm::SmallSetVector<Type, 4> dependencyTypes;
    if (theClass->hasSuperclass()) {
      // FIXME: Nested types can still be a problem here: it's possible that (for
      // whatever reason) they won't be able to be deserialized, in which case
      // we'll be in trouble forming the actual superclass type. However, we
      // need a more robust handling of deserialization dependencies that can
      // handle circularities. rdar://problem/50835214
      collectDependenciesFromType(dependencyTypes, theClass->getSuperclass(),
                                  /*excluding*/theClass);
    }
    for (Requirement req : theClass->getGenericRequirements()) {
      collectDependenciesFromRequirement(dependencyTypes, req,
                                         /*excluding*/nullptr);
    }
    for (Type ty : dependencyTypes)
      inheritedAndDependencyTypes.push_back(S.addTypeRef(ty));

    uint8_t rawAccessLevel =
      getRawStableAccessLevel(theClass->getFormalAccess());

    auto mutableClass = const_cast<ClassDecl *>(theClass);

    unsigned abbrCode = S.DeclTypeAbbrCodes[ClassLayout::Code];
    ClassLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                            S.addDeclBaseNameRef(theClass->getName()),
                            contextID.getOpaqueValue(),
                            theClass->isImplicit(),
                            theClass->isObjC(),
                            mutableClass->inheritsSuperclassInitializers(),
                            mutableClass->hasMissingDesignatedInitializers(),
                            S.addGenericSignatureRef(
                                             theClass->getGenericSignature()),
                            S.addTypeRef(theClass->getSuperclass()),
                            rawAccessLevel,
                            conformances.size(),
                            theClass->getInherited().size(),
                            inheritedAndDependencyTypes);

    writeGenericParams(theClass->getGenericParams());
    writeMembers(id, theClass->getMembers(), true);
    S.writeConformances(conformances, S.DeclTypeAbbrCodes);
  }

  void visitProtocolDecl(const ProtocolDecl *proto) {
    using namespace decls_block;
    verifyAttrSerializable(proto);

    auto contextID = S.addDeclContextRef(proto->getDeclContext());

    SmallVector<TypeID, 4> inheritedAndDependencyTypes;
    llvm::SmallSetVector<Type, 4> dependencyTypes;

    for (auto element : proto->getInherited()) {
      assert(!element.getType()->hasArchetype());
      inheritedAndDependencyTypes.push_back(S.addTypeRef(element.getType()));
      if (element.getType()->is<ProtocolType>())
        dependencyTypes.insert(element.getType());
    }

    for (Requirement req : proto->getRequirementSignature()) {
      // Requirements can be cyclic, so for now filter out any requirements
      // from elsewhere in the module. This isn't perfect---something else in
      // the module could very well fail to compile for its own reasons---but
      // it's better than nothing.
      collectDependenciesFromRequirement(dependencyTypes, req,
                                         /*excluding*/S.M);
    }

    for (Type ty : dependencyTypes)
      inheritedAndDependencyTypes.push_back(S.addTypeRef(ty));

    uint8_t rawAccessLevel = getRawStableAccessLevel(proto->getFormalAccess());

    unsigned abbrCode = S.DeclTypeAbbrCodes[ProtocolLayout::Code];
    ProtocolLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                               S.addDeclBaseNameRef(proto->getName()),
                               contextID.getOpaqueValue(),
                               proto->isImplicit(),
                               const_cast<ProtocolDecl *>(proto)
                                 ->requiresClass(),
                               proto->isObjC(),
                               proto->existentialTypeSupported(),
                               rawAccessLevel, proto->getInherited().size(),
                               inheritedAndDependencyTypes);

    writeGenericParams(proto->getGenericParams());
    S.writeGenericRequirements(
      proto->getRequirementSignature(), S.DeclTypeAbbrCodes);
    writeMembers(id, proto->getMembers(), true);
    writeDefaultWitnessTable(proto);
  }

  void visitVarDecl(const VarDecl *var) {
    using namespace decls_block;
    verifyAttrSerializable(var);

    auto contextID = S.addDeclContextRef(var->getDeclContext());

    Accessors accessors = getAccessors(var);
    uint8_t rawAccessLevel = getRawStableAccessLevel(var->getFormalAccess());
    uint8_t rawSetterAccessLevel = rawAccessLevel;
    if (var->isSettable(nullptr))
      rawSetterAccessLevel =
        getRawStableAccessLevel(var->getSetterFormalAccess());

    unsigned numBackingProperties = 0;
    Type ty = var->getInterfaceType();
    SmallVector<TypeID, 2> arrayFields;
    for (auto accessor : accessors.Decls)
      arrayFields.push_back(S.addDeclRef(accessor));

    if (auto backingInfo = var->getPropertyWrapperBackingPropertyInfo()) {
      if (backingInfo.backingVar) {
        ++numBackingProperties;
        arrayFields.push_back(S.addDeclRef(backingInfo.backingVar));
      }
      if (backingInfo.projectionVar) {
        ++numBackingProperties;
        arrayFields.push_back(S.addDeclRef(backingInfo.projectionVar));
      }
    }
    for (Type dependency : collectDependenciesFromType(ty->getCanonicalType()))
      arrayFields.push_back(S.addTypeRef(dependency));

    VarDecl *lazyStorage = nullptr;
    if (var->getAttrs().hasAttribute<LazyAttr>())
      lazyStorage = var->getLazyStorageProperty();

    auto rawIntroducer = getRawStableVarDeclIntroducer(var->getIntroducer());

    unsigned numVTableEntries = getNumberOfRequiredVTableEntries(var);

    unsigned abbrCode = S.DeclTypeAbbrCodes[VarLayout::Code];
    VarLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                          S.addDeclBaseNameRef(var->getName()),
                          contextID.getOpaqueValue(),
                          var->isImplicit(),
                          var->isObjC(),
                          var->isStatic(),
                          rawIntroducer,
                          var->isGetterMutating(),
                          var->isSetterMutating(),
                          var->isLazyStorageProperty(),
                          var->isTopLevelGlobal(),
                          S.addDeclRef(lazyStorage),
                          accessors.OpaqueReadOwnership,
                          accessors.ReadImpl,
                          accessors.WriteImpl,
                          accessors.ReadWriteImpl,
                          accessors.Decls.size(),
                          S.addTypeRef(ty),
                          var->isImplicitlyUnwrappedOptional(),
                          S.addDeclRef(var->getOverriddenDecl()),
                          rawAccessLevel, rawSetterAccessLevel,
                          S.addDeclRef(var->getOpaqueResultTypeDecl()),
                          numBackingProperties,
                          numVTableEntries,
                          arrayFields);
  }

  void visitParamDecl(const ParamDecl *param) {
    using namespace decls_block;
    verifyAttrSerializable(param);

    auto contextID = S.addDeclContextRef(param->getDeclContext());
    Type interfaceType = param->getInterfaceType();

    // Only save the text for normal and stored property default arguments, not
    // any of the special ones.
    StringRef defaultArgumentText;
    SmallString<128> scratch;
    swift::DefaultArgumentKind argKind = param->getDefaultArgumentKind();
    if (argKind == swift::DefaultArgumentKind::Normal ||
        argKind == swift::DefaultArgumentKind::StoredProperty)
      defaultArgumentText =
        param->getDefaultValueStringRepresentation(scratch);

    unsigned abbrCode = S.DeclTypeAbbrCodes[ParamLayout::Code];
    ParamLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
        S.addDeclBaseNameRef(param->getArgumentName()),
        S.addDeclBaseNameRef(param->getName()),
        contextID.getOpaqueValue(),
        getRawStableParamDeclSpecifier(param->getSpecifier()),
        S.addTypeRef(interfaceType),
        param->isImplicitlyUnwrappedOptional(),
        param->isVariadic(),
        param->isAutoClosure(),
        getRawStableDefaultArgumentKind(argKind),
        defaultArgumentText);

    if (interfaceType->hasError() &&
        !S.getASTContext().LangOpts.AllowModuleWithCompilerErrors) {
      param->getDeclContext()->printContext(llvm::errs());
      interfaceType->dump(llvm::errs());
      llvm_unreachable("error in interface type of parameter");
    }
  }

  void visitFuncDecl(const FuncDecl *fn) {
    using namespace decls_block;
    verifyAttrSerializable(fn);

    auto contextID = S.addDeclContextRef(fn->getDeclContext());

    unsigned abbrCode = S.DeclTypeAbbrCodes[FuncLayout::Code];
    SmallVector<IdentifierID, 4> nameComponentsAndDependencies;
    nameComponentsAndDependencies.push_back(
        S.addDeclBaseNameRef(fn->getBaseName()));
    for (auto argName : fn->getName().getArgumentNames())
      nameComponentsAndDependencies.push_back(S.addDeclBaseNameRef(argName));

    uint8_t rawAccessLevel = getRawStableAccessLevel(fn->getFormalAccess());

    Type ty = fn->getInterfaceType();
    for (auto dependency : collectDependenciesFromType(ty->getCanonicalType()))
      nameComponentsAndDependencies.push_back(S.addTypeRef(dependency));

    FuncLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                           contextID.getOpaqueValue(),
                           fn->isImplicit(),
                           fn->isStatic(),
                           uint8_t(
                             getStableStaticSpelling(fn->getStaticSpelling())),
                           fn->isObjC(),
                           uint8_t(
                             getStableSelfAccessKind(fn->getSelfAccessKind())),
                           fn->hasForcedStaticDispatch(),
                           fn->hasAsync(),
                           fn->hasThrows(),
                           S.addGenericSignatureRef(
                                                  fn->getGenericSignature()),
                           S.addTypeRef(fn->getResultInterfaceType()),
                           fn->isImplicitlyUnwrappedOptional(),
                           S.addDeclRef(fn->getOperatorDecl()),
                           S.addDeclRef(fn->getOverriddenDecl()),
                           overriddenDeclAffectsABI(fn->getOverriddenDecl()),
                           fn->getName().getArgumentNames().size() +
                             fn->getName().isCompoundName(),
                           rawAccessLevel,
                           fn->needsNewVTableEntry(),
                           S.addDeclRef(fn->getOpaqueResultTypeDecl()),
                           fn->isUserAccessible(),
                           nameComponentsAndDependencies);

    writeGenericParams(fn->getGenericParams());

    // Write the body parameters.
    writeParameterList(fn->getParameters());

    if (auto errorConvention = fn->getForeignErrorConvention())
      writeForeignErrorConvention(*errorConvention);

    writeInlinableBodyTextIfNeeded(fn);
  }

  void visitOpaqueTypeDecl(const OpaqueTypeDecl *opaqueDecl) {
    using namespace decls_block;
    verifyAttrSerializable(opaqueDecl);

    auto namingDeclID = S.addDeclRef(opaqueDecl->getNamingDecl());
    auto contextID = S.addDeclContextRef(opaqueDecl->getDeclContext());
    auto interfaceSigID = S.addGenericSignatureRef(
        opaqueDecl->getOpaqueInterfaceGenericSignature());
    auto interfaceTypeID =
      S.addTypeRef(opaqueDecl->getUnderlyingInterfaceType());

    auto genericSigID = S.addGenericSignatureRef(opaqueDecl->getGenericSignature());

    SubstitutionMapID underlyingTypeID = 0;
    if (auto underlying = opaqueDecl->getUnderlyingTypeSubstitutions())
      underlyingTypeID = S.addSubstitutionMapRef(*underlying);
    uint8_t rawAccessLevel =
      getRawStableAccessLevel(opaqueDecl->getFormalAccess());
    unsigned abbrCode = S.DeclTypeAbbrCodes[OpaqueTypeLayout::Code];
    OpaqueTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                 contextID.getOpaqueValue(), namingDeclID,
                                 interfaceSigID, interfaceTypeID, genericSigID,
                                 underlyingTypeID, rawAccessLevel);
    writeGenericParams(opaqueDecl->getGenericParams());
  }

  void visitAccessorDecl(const AccessorDecl *fn) {
    using namespace decls_block;
    verifyAttrSerializable(fn);

    auto contextID = S.addDeclContextRef(fn->getDeclContext());

    unsigned abbrCode = S.DeclTypeAbbrCodes[AccessorLayout::Code];

    uint8_t rawAccessLevel = getRawStableAccessLevel(fn->getFormalAccess());
    uint8_t rawAccessorKind =
      uint8_t(getStableAccessorKind(fn->getAccessorKind()));

    bool overriddenAffectsABI =
        overriddenDeclAffectsABI(fn->getOverriddenDecl());

    Type ty = fn->getInterfaceType();
    SmallVector<IdentifierID, 4> dependencies;
    for (auto dependency : collectDependenciesFromType(ty->getCanonicalType()))
      dependencies.push_back(S.addTypeRef(dependency));

    AccessorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                               contextID.getOpaqueValue(),
                               fn->isImplicit(),
                               fn->isStatic(),
                               uint8_t(getStableStaticSpelling(
                                                  fn->getStaticSpelling())),
                               fn->isObjC(),
                               uint8_t(getStableSelfAccessKind(
                                                  fn->getSelfAccessKind())),
                               fn->hasForcedStaticDispatch(),
                               fn->hasThrows(),
                               S.addGenericSignatureRef(
                                                  fn->getGenericSignature()),
                               S.addTypeRef(fn->getResultInterfaceType()),
                               fn->isImplicitlyUnwrappedOptional(),
                               S.addDeclRef(fn->getOverriddenDecl()),
                               overriddenAffectsABI,
                               S.addDeclRef(fn->getStorage()),
                               rawAccessorKind,
                               rawAccessLevel,
                               fn->needsNewVTableEntry(),
                               fn->isTransparent(),
                               dependencies);

    writeGenericParams(fn->getGenericParams());

    // Write the body parameters.
    writeParameterList(fn->getParameters());

    if (auto errorConvention = fn->getForeignErrorConvention())
      writeForeignErrorConvention(*errorConvention);

    writeInlinableBodyTextIfNeeded(fn);
  }

  void visitEnumElementDecl(const EnumElementDecl *elem) {
    using namespace decls_block;
    verifyAttrSerializable(elem);

    auto contextID = S.addDeclContextRef(elem->getDeclContext());

    SmallVector<IdentifierID, 4> nameComponentsAndDependencies;
    auto baseName = S.addDeclBaseNameRef(elem->getBaseName());
    nameComponentsAndDependencies.push_back(baseName);
    for (auto argName : elem->getName().getArgumentNames())
      nameComponentsAndDependencies.push_back(S.addDeclBaseNameRef(argName));

    Type ty = elem->getInterfaceType();
    for (Type dependency : collectDependenciesFromType(ty->getCanonicalType()))
      nameComponentsAndDependencies.push_back(S.addTypeRef(dependency));

    // We only serialize the raw values of @objc enums, because they're part
    // of the ABI. That isn't the case for Swift enums.
    auto rawValueKind = EnumElementRawValueKind::None;
    bool isNegative = false, isRawValueImplicit = false;
    StringRef RawValueText;
    if (elem->getParentEnum()->isObjC()) {
      // Currently ObjC enums always have integer raw values.
      rawValueKind = EnumElementRawValueKind::IntegerLiteral;
      auto ILE = cast<IntegerLiteralExpr>(elem->getStructuralRawValueExpr());
      RawValueText = ILE->getDigitsText();
      isNegative = ILE->isNegative();
      isRawValueImplicit = ILE->isImplicit();
    }

    unsigned abbrCode = S.DeclTypeAbbrCodes[EnumElementLayout::Code];
    EnumElementLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                  contextID.getOpaqueValue(),
                                  elem->isImplicit(),
                                  elem->hasAssociatedValues(),
                                  (unsigned)rawValueKind,
                                  isRawValueImplicit,
                                  isNegative,
                                  S.addUniquedStringRef(RawValueText),
                                  elem->getName().getArgumentNames().size()+1,
                                  nameComponentsAndDependencies);
    if (auto *PL = elem->getParameterList())
      writeParameterList(PL);
  }

  void visitSubscriptDecl(const SubscriptDecl *subscript) {
    using namespace decls_block;
    verifyAttrSerializable(subscript);

    auto contextID = S.addDeclContextRef(subscript->getDeclContext());

    Accessors accessors = getAccessors(subscript);

    SmallVector<IdentifierID, 4> nameComponentsAndDependencies;
    for (auto argName : subscript->getName().getArgumentNames())
      nameComponentsAndDependencies.push_back(S.addDeclBaseNameRef(argName));

    for (auto accessor : accessors.Decls)
      nameComponentsAndDependencies.push_back(S.addDeclRef(accessor));

    Type ty = subscript->getInterfaceType();
    for (Type dependency : collectDependenciesFromType(ty->getCanonicalType()))
      nameComponentsAndDependencies.push_back(S.addTypeRef(dependency));

    uint8_t rawAccessLevel =
      getRawStableAccessLevel(subscript->getFormalAccess());
    uint8_t rawSetterAccessLevel = rawAccessLevel;
    if (subscript->supportsMutation())
      rawSetterAccessLevel =
        getRawStableAccessLevel(subscript->getSetterFormalAccess());
    uint8_t rawStaticSpelling =
      uint8_t(getStableStaticSpelling(subscript->getStaticSpelling()));

    unsigned numVTableEntries = getNumberOfRequiredVTableEntries(subscript);

    unsigned abbrCode = S.DeclTypeAbbrCodes[SubscriptLayout::Code];
    SubscriptLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                contextID.getOpaqueValue(),
                                subscript->isImplicit(),
                                subscript->isObjC(),
                                subscript->isGetterMutating(),
                                subscript->isSetterMutating(),
                                accessors.OpaqueReadOwnership,
                                accessors.ReadImpl,
                                accessors.WriteImpl,
                                accessors.ReadWriteImpl,
                                accessors.Decls.size(),
                                S.addGenericSignatureRef(
                                            subscript->getGenericSignature()),
                                S.addTypeRef(subscript->getElementInterfaceType()),
                                subscript->isImplicitlyUnwrappedOptional(),
                                S.addDeclRef(subscript->getOverriddenDecl()),
                                rawAccessLevel,
                                rawSetterAccessLevel,
                                rawStaticSpelling,
                                subscript->getName().getArgumentNames().size(),
                                S.addDeclRef(subscript->getOpaqueResultTypeDecl()),
                                numVTableEntries,
                                nameComponentsAndDependencies);

    writeGenericParams(subscript->getGenericParams());
    writeParameterList(subscript->getIndices());
  }

  void visitConstructorDecl(const ConstructorDecl *ctor) {
    using namespace decls_block;
    verifyAttrSerializable(ctor);

    auto contextID = S.addDeclContextRef(ctor->getDeclContext());

    SmallVector<IdentifierID, 4> nameComponentsAndDependencies;
    for (auto argName : ctor->getName().getArgumentNames())
      nameComponentsAndDependencies.push_back(S.addDeclBaseNameRef(argName));

    Type ty = ctor->getInterfaceType();
    for (Type dependency : collectDependenciesFromType(ty->getCanonicalType()))
      nameComponentsAndDependencies.push_back(S.addTypeRef(dependency));

    uint8_t rawAccessLevel = getRawStableAccessLevel(ctor->getFormalAccess());

    bool firstTimeRequired = ctor->isRequired();
    if (auto *overridden = ctor->getOverriddenDecl())
      if (firstTimeRequired && overridden->isRequired())
        firstTimeRequired = false;

    unsigned abbrCode = S.DeclTypeAbbrCodes[ConstructorLayout::Code];
    ConstructorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                  contextID.getOpaqueValue(),
                                  ctor->isFailable(),
                                  ctor->isImplicitlyUnwrappedOptional(),
                                  ctor->isImplicit(),
                                  ctor->isObjC(),
                                  ctor->hasStubImplementation(),
                                  ctor->hasThrows(),
                                  getStableCtorInitializerKind(
                                    ctor->getInitKind()),
                                  S.addGenericSignatureRef(
                                                 ctor->getGenericSignature()),
                                  S.addDeclRef(ctor->getOverriddenDecl()),
                                  rawAccessLevel,
                                  ctor->needsNewVTableEntry(),
                                  firstTimeRequired,
                                  ctor->getName().getArgumentNames().size(),
                                  nameComponentsAndDependencies);

    writeGenericParams(ctor->getGenericParams());
    writeParameterList(ctor->getParameters());

    if (auto errorConvention = ctor->getForeignErrorConvention())
      writeForeignErrorConvention(*errorConvention);

    writeInlinableBodyTextIfNeeded(ctor);
  }

  void visitDestructorDecl(const DestructorDecl *dtor) {
    using namespace decls_block;
    verifyAttrSerializable(dtor);

    auto contextID = S.addDeclContextRef(dtor->getDeclContext());

    unsigned abbrCode = S.DeclTypeAbbrCodes[DestructorLayout::Code];
    DestructorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                 contextID.getOpaqueValue(),
                                 dtor->isImplicit(),
                                 dtor->isObjC(),
                                 S.addGenericSignatureRef(
                                                dtor->getGenericSignature()));
    writeInlinableBodyTextIfNeeded(dtor);
  }

  void visitTopLevelCodeDecl(const TopLevelCodeDecl *) {
    // Top-level code is ignored; external clients don't need to know about it.
  }

  void visitImportDecl(const ImportDecl *) {
    llvm_unreachable("import decls should not be serialized");
  }

  void visitIfConfigDecl(const IfConfigDecl *) {
    llvm_unreachable("#if block declarations should not be serialized");
  }

  void visitPoundDiagnosticDecl(const PoundDiagnosticDecl *) {
    llvm_unreachable("#warning/#error declarations should not be serialized");
  }

  void visitEnumCaseDecl(const EnumCaseDecl *) {
    llvm_unreachable("enum case decls should not be serialized");
  }

  void visitModuleDecl(const ModuleDecl *) {
    llvm_unreachable("module decls are not serialized");
  }

  void visitMissingMemberDecl(const MissingMemberDecl *) {
    llvm_unreachable("member placeholders shouldn't be serialized");
  }
};

void Serializer::writeASTBlockEntity(const Decl *D) {
  using namespace decls_block;

  PrettyStackTraceDecl trace("serializing", D);
  assert(DeclsToSerialize.hasRef(D));

  BitOffset initialOffset = Out.GetCurrentBitNo();
  SWIFT_DEFER {
    // This is important enough to leave on in Release builds.
    if (initialOffset == Out.GetCurrentBitNo()) {
      llvm::PrettyStackTraceString message("failed to serialize anything");
      abort();
    }
  };

  assert(getASTContext().LangOpts.AllowModuleWithCompilerErrors ||
         !D->isInvalid() && "cannot create a module with an invalid decl");
  if (isDeclXRef(D)) {
    writeCrossReference(D);
    return;
  }

  assert(!D->hasClangNode() && "imported decls should use cross-references");

  DeclSerializer(*this, DeclsToSerialize.addRef(D),
                 exportedPrespecializationDecls)
      .visit(D);
}

#define SIMPLE_CASE(TYPENAME, VALUE) \
  case swift::TYPENAME::VALUE: return uint8_t(serialization::TYPENAME::VALUE);

/// Translate from the AST function representation enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableFunctionTypeRepresentation(
                                       swift::FunctionType::Representation cc) {
  switch (cc) {
  SIMPLE_CASE(FunctionTypeRepresentation, Swift)
  SIMPLE_CASE(FunctionTypeRepresentation, Block)
  SIMPLE_CASE(FunctionTypeRepresentation, Thin)
  SIMPLE_CASE(FunctionTypeRepresentation, CFunctionPointer)
  }
  llvm_unreachable("bad calling convention");
}

/// Translate from the AST differentiability kind enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableDifferentiabilityKind(
    swift::DifferentiabilityKind diffKind) {
  switch (diffKind) {
  SIMPLE_CASE(DifferentiabilityKind, NonDifferentiable)
  SIMPLE_CASE(DifferentiabilityKind, Normal)
  SIMPLE_CASE(DifferentiabilityKind, Linear)
  }
  llvm_unreachable("bad differentiability kind");
}

/// Translate from the AST function representation enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableSILFunctionTypeRepresentation(
                                    swift::SILFunctionType::Representation cc) {
  switch (cc) {
  SIMPLE_CASE(SILFunctionTypeRepresentation, Thick)
  SIMPLE_CASE(SILFunctionTypeRepresentation, Block)
  SIMPLE_CASE(SILFunctionTypeRepresentation, Thin)
  SIMPLE_CASE(SILFunctionTypeRepresentation, CFunctionPointer)
  SIMPLE_CASE(SILFunctionTypeRepresentation, Method)
  SIMPLE_CASE(SILFunctionTypeRepresentation, ObjCMethod)
  SIMPLE_CASE(SILFunctionTypeRepresentation, WitnessMethod)
  SIMPLE_CASE(SILFunctionTypeRepresentation, Closure)
  }
  llvm_unreachable("bad calling convention");
}

/// Translate from the AST coroutine-kind enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableSILCoroutineKind(
                                    swift::SILCoroutineKind kind) {
  switch (kind) {
  SIMPLE_CASE(SILCoroutineKind, None)
  SIMPLE_CASE(SILCoroutineKind, YieldOnce)
  SIMPLE_CASE(SILCoroutineKind, YieldMany)
  }
  llvm_unreachable("bad kind");
}

/// Translate from the AST ownership enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t
getRawStableReferenceOwnership(swift::ReferenceOwnership ownership) {
  switch (ownership) {
  SIMPLE_CASE(ReferenceOwnership, Strong)
#define REF_STORAGE(Name, ...) \
  SIMPLE_CASE(ReferenceOwnership, Name)
#include "swift/AST/ReferenceStorage.def"
  }
  llvm_unreachable("bad ownership kind");
}
/// Translate from the AST ownership enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableValueOwnership(swift::ValueOwnership ownership) {
  switch (ownership) {
  SIMPLE_CASE(ValueOwnership, Default)
  SIMPLE_CASE(ValueOwnership, InOut)
  SIMPLE_CASE(ValueOwnership, Shared)
  SIMPLE_CASE(ValueOwnership, Owned)
  }
  llvm_unreachable("bad ownership kind");
}

/// Translate from the AST ParameterConvention enum to the
/// Serialization enum values, which are guaranteed to be stable.
static uint8_t getRawStableParameterConvention(swift::ParameterConvention pc) {
  switch (pc) {
  SIMPLE_CASE(ParameterConvention, Indirect_In)
  SIMPLE_CASE(ParameterConvention, Indirect_In_Constant)
  SIMPLE_CASE(ParameterConvention, Indirect_In_Guaranteed)
  SIMPLE_CASE(ParameterConvention, Indirect_Inout)
  SIMPLE_CASE(ParameterConvention, Indirect_InoutAliasable)
  SIMPLE_CASE(ParameterConvention, Direct_Owned)
  SIMPLE_CASE(ParameterConvention, Direct_Unowned)
  SIMPLE_CASE(ParameterConvention, Direct_Guaranteed)
  }
  llvm_unreachable("bad parameter convention kind");
}

/// Translate from AST SILParameterDifferentiability enum to the Serialization
/// enum values, which are guaranteed to be stable.
static uint8_t
getRawSILParameterDifferentiability(swift::SILParameterDifferentiability pd) {
  switch (pd) {
  SIMPLE_CASE(SILParameterDifferentiability, DifferentiableOrNotApplicable)
  SIMPLE_CASE(SILParameterDifferentiability, NotDifferentiable)
  }
  llvm_unreachable("bad parameter differentiability kind");
}

/// Translate from the AST ResultConvention enum to the
/// Serialization enum values, which are guaranteed to be stable.
static uint8_t getRawStableResultConvention(swift::ResultConvention rc) {
  switch (rc) {
  SIMPLE_CASE(ResultConvention, Indirect)
  SIMPLE_CASE(ResultConvention, Owned)
  SIMPLE_CASE(ResultConvention, Unowned)
  SIMPLE_CASE(ResultConvention, UnownedInnerPointer)
  SIMPLE_CASE(ResultConvention, Autoreleased)
  }
  llvm_unreachable("bad result convention kind");
}

/// Translate from AST SILResultDifferentiability enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t
getRawSILResultDifferentiability(swift::SILResultDifferentiability pd) {
  switch (pd) {
  SIMPLE_CASE(SILResultDifferentiability, DifferentiableOrNotApplicable)
  SIMPLE_CASE(SILResultDifferentiability, NotDifferentiable)
  }
  llvm_unreachable("bad result differentiability kind");
}

#undef SIMPLE_CASE

/// Find the typealias given a builtin type.
static TypeAliasDecl *findTypeAliasForBuiltin(ASTContext &Ctx, Type T) {
  /// Get the type name by chopping off "Builtin.".
  llvm::SmallString<32> FullName;
  llvm::raw_svector_ostream OS(FullName);
  T->print(OS);
  assert(FullName.startswith(BUILTIN_TYPE_NAME_PREFIX));
  StringRef TypeName = FullName.substr(8);

  SmallVector<ValueDecl*, 4> CurModuleResults;
  Ctx.TheBuiltinModule->lookupValue(Ctx.getIdentifier(TypeName),
                                    NLKind::QualifiedLookup,
                                    CurModuleResults);
  assert(CurModuleResults.size() == 1);
  return cast<TypeAliasDecl>(CurModuleResults[0]);
}

class Serializer::TypeSerializer : public TypeVisitor<TypeSerializer> {
  Serializer &S;

public:
  explicit TypeSerializer(Serializer &S) : S(S) {}

  /// If this gets referenced, we forgot to handle a type.
  void visitType(const TypeBase *) = delete;

  void visitErrorType(const ErrorType *ty) {
    if (S.getASTContext().LangOpts.AllowModuleWithCompilerErrors) {
      using namespace decls_block;
      unsigned abbrCode = S.DeclTypeAbbrCodes[ErrorTypeLayout::Code];
      ErrorTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                  S.addTypeRef(ty->getOriginalType()));
      return;
    }
    llvm_unreachable("should not serialize an ErrorType");
  }

  void visitUnresolvedType(const UnresolvedType *) {
    llvm_unreachable("should not serialize an UnresolvedType");
  }

  void visitHoleType(const HoleType *) {
    llvm_unreachable("should not serialize a HoleType");
  }

  void visitModuleType(const ModuleType *) {
    llvm_unreachable("modules are currently not first-class values");
  }

  void visitInOutType(const InOutType *) {
    llvm_unreachable("inout types are only used in function type parameters");
  }

  void visitLValueType(const LValueType *) {
    llvm_unreachable("lvalue types are only used in function bodies");
  }

  void visitTypeVariableType(const TypeVariableType *) {
    llvm_unreachable("type variables should not escape the type checker");
  }

  void visitBuiltinTypeImpl(Type ty) {
    using namespace decls_block;
    TypeAliasDecl *typeAlias =
      findTypeAliasForBuiltin(S.M->getASTContext(), ty);

    unsigned abbrCode = S.DeclTypeAbbrCodes[BuiltinAliasTypeLayout::Code];
    BuiltinAliasTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                       S.addDeclRef(typeAlias,
                                                    /*allowTypeAliasXRef*/true),
                                       TypeID());
  }

  void visitBuiltinType(BuiltinType *ty) {
    visitBuiltinTypeImpl(ty);
  }

  void visitSILTokenType(SILTokenType *ty) {
    // This is serialized like a BuiltinType, even though it isn't one.
    visitBuiltinTypeImpl(ty);
  }

  void visitTypeAliasType(const TypeAliasType *alias) {
    using namespace decls_block;
    const TypeAliasDecl *typeAlias = alias->getDecl();
    auto underlyingType = typeAlias->getUnderlyingType();

    unsigned abbrCode = S.DeclTypeAbbrCodes[TypeAliasTypeLayout::Code];
    TypeAliasTypeLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode,
        S.addDeclRef(typeAlias, /*allowTypeAliasXRef*/true),
        S.addTypeRef(alias->getParent()),
        S.addTypeRef(underlyingType),
        S.addTypeRef(alias->getSinglyDesugaredType()),
        S.addSubstitutionMapRef(alias->getSubstitutionMap()));
  }

  template <typename Layout>
  void serializeSimpleWrapper(Type wrappedTy) {
    unsigned abbrCode = S.DeclTypeAbbrCodes[Layout::Code];
    Layout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                       S.addTypeRef(wrappedTy));
  }

  void visitParenType(const ParenType *parenTy) {
    using namespace decls_block;
    assert(parenTy->getParameterFlags().isNone());
    serializeSimpleWrapper<ParenTypeLayout>(parenTy->getUnderlyingType());
  }

  void visitTupleType(const TupleType *tupleTy) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[TupleTypeLayout::Code];
    TupleTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode);

    abbrCode = S.DeclTypeAbbrCodes[TupleTypeEltLayout::Code];
    for (auto &elt : tupleTy->getElements()) {
      assert(elt.getParameterFlags().isNone());
      TupleTypeEltLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode,
          S.addDeclBaseNameRef(elt.getName()),
          S.addTypeRef(elt.getType()));
    }
  }

  void visitNominalType(const NominalType *nominalTy) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[NominalTypeLayout::Code];
    NominalTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                  S.addDeclRef(nominalTy->getDecl()),
                                  S.addTypeRef(nominalTy->getParent()));
  }

  template <typename Layout>
  void visitMetatypeImpl(const AnyMetatypeType *metatypeTy) {
    unsigned abbrCode = S.DeclTypeAbbrCodes[Layout::Code];

    // Map the metatype representation.
    auto repr = getRawStableMetatypeRepresentation(metatypeTy);
    Layout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                       S.addTypeRef(metatypeTy->getInstanceType()),
                       static_cast<uint8_t>(repr));
  }

  void visitExistentialMetatypeType(const ExistentialMetatypeType *metatypeTy) {
    using namespace decls_block;
    visitMetatypeImpl<ExistentialMetatypeTypeLayout>(metatypeTy);
  }

  void visitMetatypeType(const MetatypeType *metatypeTy) {
    using namespace decls_block;
    visitMetatypeImpl<MetatypeTypeLayout>(metatypeTy);
  }

  void visitDynamicSelfType(const DynamicSelfType *dynamicSelfTy) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[DynamicSelfTypeLayout::Code];
    DynamicSelfTypeLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode,
        S.addTypeRef(dynamicSelfTy->getSelfType()));
  }

  void visitPrimaryArchetypeType(const PrimaryArchetypeType *archetypeTy) {
    using namespace decls_block;
    auto sig = archetypeTy->getGenericEnvironment()->getGenericSignature();

    GenericSignatureID sigID = S.addGenericSignatureRef(sig);
    auto interfaceType = archetypeTy->getInterfaceType()
      ->castTo<GenericTypeParamType>();

    unsigned abbrCode = S.DeclTypeAbbrCodes[PrimaryArchetypeTypeLayout::Code];
    PrimaryArchetypeTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                           sigID,
                                           interfaceType->getDepth(),
                                           interfaceType->getIndex());
  }

  void visitOpenedArchetypeType(const OpenedArchetypeType *archetypeTy) {
    using namespace decls_block;
    serializeSimpleWrapper<OpenedArchetypeTypeLayout>(
        archetypeTy->getOpenedExistentialType());
  }

  void
  visitOpaqueTypeArchetypeType(const OpaqueTypeArchetypeType *archetypeTy) {
    using namespace decls_block;
    auto declID = S.addDeclRef(archetypeTy->getDecl());
    auto substMapID = S.addSubstitutionMapRef(archetypeTy->getSubstitutions());
    unsigned abbrCode = S.DeclTypeAbbrCodes[OpaqueArchetypeTypeLayout::Code];
    OpaqueArchetypeTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                          declID, substMapID);
  }

  void visitNestedArchetypeType(const NestedArchetypeType *archetypeTy) {
    using namespace decls_block;
    auto rootTypeID = S.addTypeRef(archetypeTy->getRoot());
    auto interfaceTypeID = S.addTypeRef(archetypeTy->getInterfaceType());
    unsigned abbrCode = S.DeclTypeAbbrCodes[NestedArchetypeTypeLayout::Code];
    NestedArchetypeTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                          rootTypeID, interfaceTypeID);
  }

  void visitGenericTypeParamType(const GenericTypeParamType *genericParam) {
    using namespace decls_block;

    unsigned abbrCode = S.DeclTypeAbbrCodes[GenericTypeParamTypeLayout::Code];
    DeclID declIDOrDepth;
    unsigned indexPlusOne;
    if (genericParam->getDecl() &&
        !(genericParam->getDecl()->getDeclContext()->isModuleScopeContext() &&
          S.isDeclXRef(genericParam->getDecl()))) {
      declIDOrDepth = S.addDeclRef(genericParam->getDecl());
      indexPlusOne = 0;
    } else {
      declIDOrDepth = genericParam->getDepth();
      indexPlusOne = genericParam->getIndex() + 1;
    }
    GenericTypeParamTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                           declIDOrDepth, indexPlusOne);
  }

  void visitDependentMemberType(const DependentMemberType *dependent) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[DependentMemberTypeLayout::Code];
    assert(dependent->getAssocType() && "Unchecked dependent member type");
    DependentMemberTypeLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode,
        S.addTypeRef(dependent->getBase()),
        S.addDeclRef(dependent->getAssocType()));
  }

  void serializeFunctionTypeParams(const AnyFunctionType *fnTy) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[FunctionParamLayout::Code];
    for (auto &param : fnTy->getParams()) {
      auto paramFlags = param.getParameterFlags();
      auto rawOwnership =
          getRawStableValueOwnership(paramFlags.getValueOwnership());
      FunctionParamLayout::emitRecord(
          S.Out, S.ScratchRecord, abbrCode,
          S.addDeclBaseNameRef(param.getLabel()),
          S.addTypeRef(param.getPlainType()), paramFlags.isVariadic(),
          paramFlags.isAutoClosure(), paramFlags.isNonEphemeral(), rawOwnership,
          paramFlags.isNoDerivative());
    }
  }

  void visitFunctionType(const FunctionType *fnTy) {
    using namespace decls_block;

    auto resultType = S.addTypeRef(fnTy->getResult());
    auto clangType =
      S.getASTContext().LangOpts.UseClangFunctionTypes
      ? S.addClangTypeRef(fnTy->getClangTypeInfo().getType())
      : ClangTypeID(0);

    unsigned abbrCode = S.DeclTypeAbbrCodes[FunctionTypeLayout::Code];
    FunctionTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
        resultType,
        getRawStableFunctionTypeRepresentation(fnTy->getRepresentation()),
        clangType,
        fnTy->isNoEscape(),
        fnTy->isAsync(),
        fnTy->isThrowing(),
        getRawStableDifferentiabilityKind(fnTy->getDifferentiabilityKind()));

    serializeFunctionTypeParams(fnTy);
  }

  void visitGenericFunctionType(const GenericFunctionType *fnTy) {
    using namespace decls_block;
    assert(!fnTy->isNoEscape());
    auto genericSig = fnTy->getGenericSignature();
    unsigned abbrCode = S.DeclTypeAbbrCodes[GenericFunctionTypeLayout::Code];
    GenericFunctionTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
        S.addTypeRef(fnTy->getResult()),
        getRawStableFunctionTypeRepresentation(fnTy->getRepresentation()),
        fnTy->isAsync(), fnTy->isThrowing(),
        getRawStableDifferentiabilityKind(fnTy->getDifferentiabilityKind()),
        S.addGenericSignatureRef(genericSig));

    serializeFunctionTypeParams(fnTy);
  }

  void visitSILBlockStorageType(const SILBlockStorageType *storageTy) {
    using namespace decls_block;
    serializeSimpleWrapper<SILBlockStorageTypeLayout>(
        storageTy->getCaptureType());
  }

  void visitSILBoxType(const SILBoxType *boxTy) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[SILBoxTypeLayout::Code];
    SILLayoutID layoutRef = S.addSILLayoutRef(boxTy->getLayout());

    SILBoxTypeLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode, layoutRef,
        S.addSubstitutionMapRef(boxTy->getSubstitutions()));
  }

  void visitSILFunctionType(const SILFunctionType *fnTy) {
    using namespace decls_block;

    auto representation = fnTy->getRepresentation();
    auto stableRepresentation =
      getRawStableSILFunctionTypeRepresentation(representation);

    SmallVector<TypeID, 8> variableData;
    for (auto param : fnTy->getParameters()) {
      variableData.push_back(S.addTypeRef(param.getInterfaceType()));
      unsigned conv = getRawStableParameterConvention(param.getConvention());
      variableData.push_back(TypeID(conv));
      if (fnTy->isDifferentiable())
        variableData.push_back(TypeID(
            getRawSILParameterDifferentiability(param.getDifferentiability())));
    }
    for (auto yield : fnTy->getYields()) {
      variableData.push_back(S.addTypeRef(yield.getInterfaceType()));
      unsigned conv = getRawStableParameterConvention(yield.getConvention());
      variableData.push_back(TypeID(conv));
    }
    for (auto result : fnTy->getResults()) {
      variableData.push_back(S.addTypeRef(result.getInterfaceType()));
      unsigned conv = getRawStableResultConvention(result.getConvention());
      variableData.push_back(TypeID(conv));
      if (fnTy->isDifferentiable())
        variableData.push_back(TypeID(
            getRawSILResultDifferentiability(result.getDifferentiability())));
    }
    if (fnTy->hasErrorResult()) {
      auto abResult = fnTy->getErrorResult();
      variableData.push_back(S.addTypeRef(abResult.getInterfaceType()));
      unsigned conv = getRawStableResultConvention(abResult.getConvention());
      variableData.push_back(TypeID(conv));
    }

    auto invocationSigID =
      S.addGenericSignatureRef(fnTy->getInvocationGenericSignature());
    auto invocationSubstMapID =
      S.addSubstitutionMapRef(fnTy->getInvocationSubstitutions());
    auto patternSubstMapID =
      S.addSubstitutionMapRef(fnTy->getPatternSubstitutions());
    auto clangTypeID = S.addClangTypeRef(fnTy->getClangTypeInfo().getType());

    auto stableCoroutineKind =
      getRawStableSILCoroutineKind(fnTy->getCoroutineKind());

    auto stableCalleeConvention =
      getRawStableParameterConvention(fnTy->getCalleeConvention());

    auto stableDiffKind =
        getRawStableDifferentiabilityKind(fnTy->getDifferentiabilityKind());

    unsigned abbrCode = S.DeclTypeAbbrCodes[SILFunctionTypeLayout::Code];
    SILFunctionTypeLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode,
        fnTy->isAsync(), stableCoroutineKind, stableCalleeConvention,
        stableRepresentation, fnTy->isPseudogeneric(), fnTy->isNoEscape(),
        stableDiffKind, fnTy->hasErrorResult(), fnTy->getParameters().size(),
        fnTy->getNumYields(), fnTy->getNumResults(),
        invocationSigID, invocationSubstMapID, patternSubstMapID,
        clangTypeID, variableData);

    if (auto conformance = fnTy->getWitnessMethodConformanceOrInvalid())
      S.writeConformance(conformance, S.DeclTypeAbbrCodes);
  }

  void visitArraySliceType(const ArraySliceType *sliceTy) {
    using namespace decls_block;
    serializeSimpleWrapper<ArraySliceTypeLayout>(sliceTy->getBaseType());
  }

  void visitDictionaryType(const DictionaryType *dictTy) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[DictionaryTypeLayout::Code];
    DictionaryTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                     S.addTypeRef(dictTy->getKeyType()),
                                     S.addTypeRef(dictTy->getValueType()));
  }

  void visitOptionalType(const OptionalType *optionalTy) {
    using namespace decls_block;
    serializeSimpleWrapper<OptionalTypeLayout>(optionalTy->getBaseType());
  }

  void
  visitProtocolCompositionType(const ProtocolCompositionType *composition) {
    using namespace decls_block;

    SmallVector<TypeID, 4> protocols;
    for (auto proto : composition->getMembers())
      protocols.push_back(S.addTypeRef(proto));

    unsigned abbrCode =
        S.DeclTypeAbbrCodes[ProtocolCompositionTypeLayout::Code];
    ProtocolCompositionTypeLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode,
        composition->hasExplicitAnyObject(),
        protocols);
  }

  void visitReferenceStorageType(const ReferenceStorageType *refTy) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[ReferenceStorageTypeLayout::Code];
    auto stableOwnership =
        getRawStableReferenceOwnership(refTy->getOwnership());
    ReferenceStorageTypeLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode,
        stableOwnership,
        S.addTypeRef(refTy->getReferentType()));
  }

  void visitUnboundGenericType(const UnboundGenericType *generic) {
    using namespace decls_block;
    unsigned abbrCode = S.DeclTypeAbbrCodes[UnboundGenericTypeLayout::Code];
    UnboundGenericTypeLayout::emitRecord(
        S.Out, S.ScratchRecord, abbrCode,
        S.addDeclRef(generic->getDecl(), /*allowTypeAliasXRef*/true),
        S.addTypeRef(generic->getParent()));
  }

  void visitBoundGenericType(const BoundGenericType *generic) {
    using namespace decls_block;
    SmallVector<TypeID, 8> genericArgIDs;

    for (auto next : generic->getGenericArgs())
      genericArgIDs.push_back(S.addTypeRef(next));

    unsigned abbrCode = S.DeclTypeAbbrCodes[BoundGenericTypeLayout::Code];
    BoundGenericTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
                                       S.addDeclRef(generic->getDecl()),
                                       S.addTypeRef(generic->getParent()),
                                       genericArgIDs);
  }
};

void Serializer::writeASTBlockEntity(Type ty) {
  using namespace decls_block;
  PrettyStackTraceType traceRAII(ty->getASTContext(), "serializing", ty);
  assert(TypesToSerialize.hasRef(ty));

  BitOffset initialOffset = Out.GetCurrentBitNo();
  SWIFT_DEFER {
    // This is important enough to leave on in Release builds.
    if (initialOffset == Out.GetCurrentBitNo()) {
      llvm::PrettyStackTraceString message("failed to serialize anything");
      abort();
    }
  };

  TypeSerializer(*this).visit(ty);
}

namespace {
class ClangToSwiftBasicWriter :
    public swift::DataStreamBasicWriter<ClangToSwiftBasicWriter> {

  Serializer &S;
  SmallVectorImpl<uint64_t> &Record;
  using TypeWriter = 
    clang::serialization::AbstractTypeWriter<ClangToSwiftBasicWriter>;
  TypeWriter Types;

  ClangModuleLoader *getClangLoader() {
    return S.getASTContext().getClangModuleLoader();
  }

public:
  ClangToSwiftBasicWriter(Serializer &S, SmallVectorImpl<uint64_t> &record)
    : S(S), Record(record), Types(*this) {}

  void writeUInt64(uint64_t value) {
    Record.push_back(value);
  }

  void writeIdentifier(const clang::IdentifierInfo *value) {
    IdentifierID id = 0;
    if (value) {
      id = S.addDeclBaseNameRef(
               S.getASTContext().getIdentifier(value->getName()));
    }
    Record.push_back(id);
  }

  void writeStmtRef(const clang::Stmt *stmt) {
    // The deserializer should always read null, and isSerializable
    // should be checking that we don't see a non-null statement here.
    if (stmt) {
      llvm::report_fatal_error("serializing a non-null Clang statement or"
                               " expression reference");
    }
  }

  void writeDeclRef(const clang::Decl *decl) {
    if (!decl) {
      Record.push_back(/*no declaration*/ 0);
      return;
    }

    auto path = getClangLoader()->findStableSerializationPath(decl);
    if (!path) {
      decl->dump(llvm::errs());
      llvm::report_fatal_error("failed to find a stable Swift serialization"
                               " path for the above Clang declaration");
    }

    if (path.isSwiftDecl()) {
      Record.push_back(/*swift declaration*/ 1);
      Record.push_back(S.addDeclRef(path.getSwiftDecl()));
      return;
    }

    assert(path.isExternalPath());
    auto &ext = path.getExternalPath();
    Record.push_back(/*external path*/ 2);
    Record.push_back(ext.Path.size());
    for (auto &elt : ext.Path) {
      auto kind = elt.first;
      auto stableKind = unsigned(getStableClangDeclPathComponentKind(kind));
      Record.push_back(stableKind);
      if (ext.requiresIdentifier(kind))
        Record.push_back(S.addDeclBaseNameRef(elt.second));
    }
  }
};

}

void Serializer::writeASTBlockEntity(const clang::Type *ty) {
  using namespace decls_block;
  auto &ctx = getASTContext().getClangModuleLoader()->getClangASTContext();
  PrettyStackTraceClangType traceRAII(ctx, "serializing clang type", ty);
  assert(ClangTypesToSerialize.hasRef(ty));

  // Serialize the type as an opaque sequence of data.
  SmallVector<uint64_t, 16> typeData;
  ClangToSwiftBasicWriter(*this, typeData).writeTypeRef(ty);

  // Write that in an opaque record.
  unsigned abbrCode = DeclTypeAbbrCodes[ClangTypeLayout::Code];
  ClangTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
                              typeData);
}

template <typename SpecificASTBlockRecordKeeper>
bool Serializer::writeASTBlockEntitiesIfNeeded(
    SpecificASTBlockRecordKeeper &entities) {
  if (!entities.hasMoreToSerialize())
    return false;
  while (auto next = entities.popNext(Out.GetCurrentBitNo()))
    writeASTBlockEntity(next.getValue());
  return true;
}

void Serializer::writeAllDeclsAndTypes() {
  BCBlockRAII restoreBlock(Out, DECLS_AND_TYPES_BLOCK_ID, 8);
  using namespace decls_block;
  registerDeclTypeAbbr<BuiltinAliasTypeLayout>();
  registerDeclTypeAbbr<TypeAliasTypeLayout>();
  registerDeclTypeAbbr<GenericTypeParamDeclLayout>();
  registerDeclTypeAbbr<AssociatedTypeDeclLayout>();
  registerDeclTypeAbbr<NominalTypeLayout>();
  registerDeclTypeAbbr<ParenTypeLayout>();
  registerDeclTypeAbbr<TupleTypeLayout>();
  registerDeclTypeAbbr<TupleTypeEltLayout>();
  registerDeclTypeAbbr<FunctionTypeLayout>();
  registerDeclTypeAbbr<FunctionParamLayout>();
  registerDeclTypeAbbr<MetatypeTypeLayout>();
  registerDeclTypeAbbr<ExistentialMetatypeTypeLayout>();
  registerDeclTypeAbbr<PrimaryArchetypeTypeLayout>();
  registerDeclTypeAbbr<OpenedArchetypeTypeLayout>();
  registerDeclTypeAbbr<OpaqueArchetypeTypeLayout>();
  registerDeclTypeAbbr<NestedArchetypeTypeLayout>();
  registerDeclTypeAbbr<ProtocolCompositionTypeLayout>();
  registerDeclTypeAbbr<BoundGenericTypeLayout>();
  registerDeclTypeAbbr<GenericFunctionTypeLayout>();
  registerDeclTypeAbbr<SILBlockStorageTypeLayout>();
  registerDeclTypeAbbr<SILBoxTypeLayout>();
  registerDeclTypeAbbr<SILFunctionTypeLayout>();
  registerDeclTypeAbbr<ArraySliceTypeLayout>();
  registerDeclTypeAbbr<DictionaryTypeLayout>();
  registerDeclTypeAbbr<ReferenceStorageTypeLayout>();
  registerDeclTypeAbbr<UnboundGenericTypeLayout>();
  registerDeclTypeAbbr<OptionalTypeLayout>();
  registerDeclTypeAbbr<DynamicSelfTypeLayout>();
  registerDeclTypeAbbr<ErrorTypeLayout>();

  registerDeclTypeAbbr<ClangTypeLayout>();

  registerDeclTypeAbbr<TypeAliasLayout>();
  registerDeclTypeAbbr<GenericTypeParamTypeLayout>();
  registerDeclTypeAbbr<DependentMemberTypeLayout>();
  registerDeclTypeAbbr<StructLayout>();
  registerDeclTypeAbbr<ConstructorLayout>();
  registerDeclTypeAbbr<VarLayout>();
  registerDeclTypeAbbr<ParamLayout>();
  registerDeclTypeAbbr<FuncLayout>();
  registerDeclTypeAbbr<AccessorLayout>();
  registerDeclTypeAbbr<OpaqueTypeLayout>();
  registerDeclTypeAbbr<PatternBindingLayout>();
  registerDeclTypeAbbr<ProtocolLayout>();
  registerDeclTypeAbbr<DefaultWitnessTableLayout>();
  registerDeclTypeAbbr<PrefixOperatorLayout>();
  registerDeclTypeAbbr<PostfixOperatorLayout>();
  registerDeclTypeAbbr<InfixOperatorLayout>();
  registerDeclTypeAbbr<PrecedenceGroupLayout>();
  registerDeclTypeAbbr<ClassLayout>();
  registerDeclTypeAbbr<EnumLayout>();
  registerDeclTypeAbbr<EnumElementLayout>();
  registerDeclTypeAbbr<SubscriptLayout>();
  registerDeclTypeAbbr<ExtensionLayout>();
  registerDeclTypeAbbr<DestructorLayout>();

  registerDeclTypeAbbr<ParameterListLayout>();

  registerDeclTypeAbbr<ParenPatternLayout>();
  registerDeclTypeAbbr<TuplePatternLayout>();
  registerDeclTypeAbbr<TuplePatternEltLayout>();
  registerDeclTypeAbbr<NamedPatternLayout>();
  registerDeclTypeAbbr<BindingPatternLayout>();
  registerDeclTypeAbbr<AnyPatternLayout>();
  registerDeclTypeAbbr<TypedPatternLayout>();
  registerDeclTypeAbbr<InlinableBodyTextLayout>();
  registerDeclTypeAbbr<GenericParamListLayout>();
  registerDeclTypeAbbr<GenericSignatureLayout>();
  registerDeclTypeAbbr<GenericRequirementLayout>();
  registerDeclTypeAbbr<LayoutRequirementLayout>();
  registerDeclTypeAbbr<SILGenericSignatureLayout>();
  registerDeclTypeAbbr<SubstitutionMapLayout>();

  registerDeclTypeAbbr<ForeignErrorConventionLayout>();
  registerDeclTypeAbbr<AbstractClosureExprLayout>();
  registerDeclTypeAbbr<PatternBindingInitializerLayout>();
  registerDeclTypeAbbr<DefaultArgumentInitializerLayout>();
  registerDeclTypeAbbr<TopLevelCodeDeclContextLayout>();

  registerDeclTypeAbbr<XRefTypePathPieceLayout>();
  registerDeclTypeAbbr<XRefOpaqueReturnTypePathPieceLayout>();
  registerDeclTypeAbbr<XRefValuePathPieceLayout>();
  registerDeclTypeAbbr<XRefExtensionPathPieceLayout>();
  registerDeclTypeAbbr<XRefOperatorOrAccessorPathPieceLayout>();
  registerDeclTypeAbbr<XRefGenericParamPathPieceLayout>();
  registerDeclTypeAbbr<XRefInitializerPathPieceLayout>();

  registerDeclTypeAbbr<AbstractProtocolConformanceLayout>();
  registerDeclTypeAbbr<NormalProtocolConformanceLayout>();
  registerDeclTypeAbbr<SelfProtocolConformanceLayout>();
  registerDeclTypeAbbr<SpecializedProtocolConformanceLayout>();
  registerDeclTypeAbbr<InheritedProtocolConformanceLayout>();
  registerDeclTypeAbbr<InvalidProtocolConformanceLayout>();
  registerDeclTypeAbbr<NormalProtocolConformanceIdLayout>();
  registerDeclTypeAbbr<ProtocolConformanceXrefLayout>();

  registerDeclTypeAbbr<SILLayoutLayout>();

  registerDeclTypeAbbr<LocalDiscriminatorLayout>();
  registerDeclTypeAbbr<PrivateDiscriminatorLayout>();
  registerDeclTypeAbbr<FilenameForPrivateLayout>();
  registerDeclTypeAbbr<MembersLayout>();
  registerDeclTypeAbbr<XRefLayout>();

#define DECL_ATTR(X, NAME, ...) \
  registerDeclTypeAbbr<NAME##DeclAttrLayout>();
#include "swift/AST/Attr.def"

  bool wroteSomething;
  do {
    // Each of these loops can trigger the others to execute again, so repeat
    // until /all/ of the pending lists are empty.
    wroteSomething = false;

    wroteSomething |= writeASTBlockEntitiesIfNeeded(DeclsToSerialize);
    wroteSomething |= writeASTBlockEntitiesIfNeeded(TypesToSerialize);
    wroteSomething |= writeASTBlockEntitiesIfNeeded(ClangTypesToSerialize);
    wroteSomething |=
        writeASTBlockEntitiesIfNeeded(LocalDeclContextsToSerialize);
    wroteSomething |=
        writeASTBlockEntitiesIfNeeded(GenericSignaturesToSerialize);
    wroteSomething |=
        writeASTBlockEntitiesIfNeeded(SubstitutionMapsToSerialize);
    wroteSomething |=
        writeASTBlockEntitiesIfNeeded(NormalConformancesToSerialize);
    wroteSomething |= writeASTBlockEntitiesIfNeeded(SILLayoutsToSerialize);
  } while (wroteSomething);
}

std::vector<CharOffset> Serializer::writeAllIdentifiers() {
  assert(!DeclsToSerialize.hasMoreToSerialize() &&
         "did not call Serializer::writeAllDeclsAndTypes?");

  BCBlockRAII restoreBlock(Out, IDENTIFIER_DATA_BLOCK_ID, 3);
  identifier_block::IdentifierDataLayout IdentifierData(Out);

  llvm::SmallString<4096> stringData;

  // Make sure no identifier has an offset of 0.
  stringData.push_back('\0');

  std::vector<CharOffset> identifierOffsets;
  for (StringRef str : StringsToWrite) {
    identifierOffsets.push_back(stringData.size());
    stringData.append(str);
    stringData.push_back('\0');
  }

  IdentifierData.emit(ScratchRecord, stringData.str());
  return identifierOffsets;
}

template <typename SpecificASTBlockRecordKeeper>
void Serializer::writeOffsets(const index_block::OffsetsLayout &Offsets,
                              const SpecificASTBlockRecordKeeper &entities) {
  Offsets.emit(ScratchRecord, SpecificASTBlockRecordKeeper::RecordCode,
               entities.getOffsets());
}

/// Writes an in-memory decl table to an on-disk representation, using the
/// given layout.
static void writeDeclTable(const index_block::DeclListLayout &DeclList,
                           index_block::RecordKind kind,
                           const Serializer::DeclTable &table) {
  if (table.empty())
    return;

  SmallVector<uint64_t, 8> scratch;
  llvm::SmallString<4096> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::OnDiskChainedHashTableGenerator<DeclTableInfo> generator;
    for (auto &entry : table)
      generator.insert(entry.first, entry.second);

    llvm::raw_svector_ostream blobStream(hashTableBlob);
    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream);
  }

  DeclList.emit(scratch, kind, tableOffset, hashTableBlob);
}

static void
writeExtensionTable(const index_block::ExtensionTableLayout &ExtensionTable,
                    const Serializer::ExtensionTable &table,
                    Serializer &serializer) {
  if (table.empty())
    return;

  SmallVector<uint64_t, 8> scratch;
  llvm::SmallString<4096> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::OnDiskChainedHashTableGenerator<ExtensionTableInfo> generator;
    ExtensionTableInfo info{serializer};
    for (auto &entry : table) {
      generator.insert(entry.first, entry.second, info);
    }

    llvm::raw_svector_ostream blobStream(hashTableBlob);
    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream, info);
  }

  ExtensionTable.emit(scratch, tableOffset, hashTableBlob);
}

static void writeLocalDeclTable(const index_block::DeclListLayout &DeclList,
                                index_block::RecordKind kind,
                                LocalTypeHashTableGenerator &generator) {
  SmallVector<uint64_t, 8> scratch;
  llvm::SmallString<4096> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::raw_svector_ostream blobStream(hashTableBlob);
    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream);
  }

  DeclList.emit(scratch, kind, tableOffset, hashTableBlob);
}

static void
writeNestedTypeDeclsTable(const index_block::NestedTypeDeclsLayout &declList,
                          const Serializer::NestedTypeDeclsTable &table) {
  SmallVector<uint64_t, 8> scratch;
  llvm::SmallString<4096> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::OnDiskChainedHashTableGenerator<NestedTypeDeclsTableInfo> generator;
    for (auto &entry : table)
      generator.insert(entry.first, entry.second);

    llvm::raw_svector_ostream blobStream(hashTableBlob);
    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream);
  }

  declList.emit(scratch, tableOffset, hashTableBlob);
}

static void
writeDeclMemberNamesTable(const index_block::DeclMemberNamesLayout &declNames,
                          const Serializer::DeclMemberNamesTable &table) {
  SmallVector<uint64_t, 8> scratch;
  llvm::SmallString<4096> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::OnDiskChainedHashTableGenerator<DeclMemberNamesTableInfo> generator;
    // Emit the offsets of the sub-tables; the tables themselves have been
    // separately emitted into DECL_MEMBER_TABLES_BLOCK by now.
    for (auto &entry : table) {
      // Or they _should_ have been; check for nonzero offsets.
      assert(static_cast<unsigned>(entry.second.first) != 0);
      generator.insert(entry.first, entry.second.first);
    }

    llvm::raw_svector_ostream blobStream(hashTableBlob);
    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream);
  }

  declNames.emit(scratch, tableOffset, hashTableBlob);
}

static void
writeDeclMembersTable(const decl_member_tables_block::DeclMembersLayout &mems,
                      const Serializer::DeclMembersTable &table) {
  SmallVector<uint64_t, 8> scratch;
  llvm::SmallString<4096> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::OnDiskChainedHashTableGenerator<DeclMembersTableInfo> generator;
    for (auto &entry : table)
      generator.insert(entry.first, entry.second);

    llvm::raw_svector_ostream blobStream(hashTableBlob);
    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream);
  }

  mems.emit(scratch, tableOffset, hashTableBlob);
}

static void
writeDeclFingerprintsTable(const index_block::DeclFingerprintsLayout &fpl,
                           const Serializer::DeclFingerprintsTable &table) {
  SmallVector<uint64_t, 8> scratch;
  llvm::SmallString<4096> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::OnDiskChainedHashTableGenerator<DeclFingerprintsTableInfo> generator;
    for (auto &entry : table) {
      generator.insert(entry.first, entry.second);
    }

    llvm::raw_svector_ostream blobStream(hashTableBlob);
    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream);
  }

  fpl.emit(scratch, tableOffset, hashTableBlob);
}

namespace {
  /// Used to serialize the on-disk Objective-C method hash table.
  class ObjCMethodTableInfo {
  public:
    using key_type = ObjCSelector;
    using key_type_ref = key_type;
    using data_type = Serializer::ObjCMethodTableData;
    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) {
      llvm::SmallString<32> scratch;
      return llvm::djbHash(key.getString(scratch), SWIFTMODULE_HASH_SEED);
    }

    std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out,
                                                    key_type_ref key,
                                                    data_type_ref data) {
      llvm::SmallString<32> scratch;
      auto keyLength = key.getString(scratch).size();
      assert(keyLength <= std::numeric_limits<uint16_t>::max() &&
             "selector too long");
      uint32_t dataLength = 0;
      for (const auto &entry : data) {
        dataLength += sizeof(uint32_t) + 1 + sizeof(uint32_t);
        dataLength += std::get<0>(entry).size();
      }

      endian::Writer writer(out, little);
      writer.write<uint16_t>(keyLength);
      writer.write<uint32_t>(dataLength);
      return { keyLength, dataLength };
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
#ifndef NDEBUG
      uint64_t start = out.tell();
#endif
      out << key;
      assert((out.tell() - start == len) && "measured key length incorrectly");
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      endian::Writer writer(out, little);
      for (const auto &entry : data) {
        writer.write<uint32_t>(std::get<0>(entry).size());
        writer.write<uint8_t>(std::get<1>(entry));
        writer.write<uint32_t>(std::get<2>(entry));
        out.write(std::get<0>(entry).c_str(), std::get<0>(entry).size());
      }
    }
  };
} // end anonymous namespace

static void writeObjCMethodTable(const index_block::ObjCMethodTableLayout &out,
                                 Serializer::ObjCMethodTable &objcMethods) {
  // Collect all of the Objective-C selectors in the method table.
  std::vector<ObjCSelector> selectors;
  for (const auto &entry : objcMethods) {
    selectors.push_back(entry.first);
  }

  // Sort the Objective-C selectors so we emit them in a stable order.
  llvm::array_pod_sort(selectors.begin(), selectors.end());

  // Create the on-disk hash table.
  llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo> generator;
  llvm::SmallString<32> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::raw_svector_ostream blobStream(hashTableBlob);
    for (auto selector : selectors) {
      generator.insert(selector, objcMethods[selector]);
    }

    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream);
  }

  SmallVector<uint64_t, 8> scratch;
  out.emit(scratch, tableOffset, hashTableBlob);
}

namespace {
  /// Used to serialize derivative function configurations.
  class DerivativeFunctionConfigTableInfo {
  public:
    using key_type = std::string;
    using key_type_ref = StringRef;
    using data_type = Serializer::DerivativeFunctionConfigTableData;
    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) {
      assert(!key.empty());
      return llvm::djbHash(key, SWIFTMODULE_HASH_SEED);
    }

    std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out,
                                                    key_type_ref key,
                                                    data_type_ref data) {
      uint32_t keyLength = key.str().size();
      assert(keyLength == static_cast<uint16_t>(keyLength));
      uint32_t dataLength = (sizeof(uint32_t) * 2) * data.size();
      for (auto entry : data)
        dataLength += entry.first.size();
      assert(dataLength == static_cast<uint16_t>(dataLength));
      endian::Writer writer(out, little);
      writer.write<uint16_t>(keyLength);
      writer.write<uint16_t>(dataLength);
      return { keyLength, dataLength };
    }

    void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) {
      out << key;
    }

    void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data,
                  unsigned len) {
      static_assert(declIDFitsIn32Bits(), "DeclID too large");
      endian::Writer writer(out, little);
      for (auto &entry : data) {
        // Write `GenericSignatureID`.
        writer.write<uint32_t>(entry.second);
        // Write parameter indices string size, followed by data.
        writer.write<int32_t>(entry.first.size());
        out << entry.first;
      }
    }
  };
} // end anonymous namespace

static void writeDerivativeFunctionConfigs(
    Serializer &S, const index_block::DerivativeFunctionConfigTableLayout &out,
    Serializer::DerivativeFunctionConfigTable &derivativeConfigs) {
  // Create the on-disk hash table.
  llvm::OnDiskChainedHashTableGenerator<DerivativeFunctionConfigTableInfo>
      generator;
  llvm::SmallString<32> hashTableBlob;
  uint32_t tableOffset;
  {
    llvm::raw_svector_ostream blobStream(hashTableBlob);
    for (auto &entry : derivativeConfigs)
      generator.insert(entry.first.get(), entry.second);
    // Make sure that no bucket is at offset 0.
    endian::write<uint32_t>(blobStream, 0, little);
    tableOffset = generator.Emit(blobStream);
  }
  SmallVector<uint64_t, 8> scratch;
  out.emit(scratch, tableOffset, hashTableBlob);
}

// Records derivative function configurations for the given AbstractFunctionDecl
// by visiting `@differentiable` and `@derivative` attributes.
static void recordDerivativeFunctionConfig(
    Serializer &S, const AbstractFunctionDecl *AFD,
    Serializer::UniquedDerivativeFunctionConfigTable &derivativeConfigs) {
  auto &ctx = AFD->getASTContext();
  Mangle::ASTMangler Mangler;
  for (auto *attr : AFD->getAttrs().getAttributes<DifferentiableAttr>()) {
    auto mangledName = ctx.getIdentifier(Mangler.mangleDeclAsUSR(AFD, ""));
    derivativeConfigs[mangledName].insert(
        {ctx.getIdentifier(attr->getParameterIndices()->getString()),
         attr->getDerivativeGenericSignature()});
  }
  for (auto *attr : AFD->getAttrs().getAttributes<DerivativeAttr>()) {
    auto *origAFD = attr->getOriginalFunction(ctx);
    auto mangledName = ctx.getIdentifier(Mangler.mangleDeclAsUSR(origAFD, ""));
    derivativeConfigs[mangledName].insert(
        {ctx.getIdentifier(attr->getParameterIndices()->getString()),
         AFD->getGenericSignature()});
  }
};

/// Recursively walks the members and derived global decls of any nominal types
/// to build up global tables.
template<typename Range>
static void collectInterestingNestedDeclarations(
    Serializer &S,
    Range members,
    Serializer::DeclTable &operatorMethodDecls,
    Serializer::ObjCMethodTable &objcMethods,
    Serializer::NestedTypeDeclsTable &nestedTypeDecls,
    Serializer::UniquedDerivativeFunctionConfigTable &derivativeConfigs,
    bool isLocal = false) {
  const NominalTypeDecl *nominalParent = nullptr;

  for (const Decl *member : members) {
    // If there is a corresponding Objective-C method, record it.
    auto recordObjCMethod = [&](const AbstractFunctionDecl *func) {
      if (isLocal)
        return;

      if (auto owningClass = func->getDeclContext()->getSelfClassDecl()) {
        if (func->isObjC()) {
          Mangle::ASTMangler mangler;
          std::string ownerName = mangler.mangleNominalType(owningClass);
          assert(!ownerName.empty() && "Mangled type came back empty!");

          objcMethods[func->getObjCSelector()].push_back(
            std::make_tuple(ownerName,
                            func->isObjCInstanceMethod(),
                            S.addDeclRef(func)));
        }
      }
    };

    if (auto memberValue = dyn_cast<ValueDecl>(member)) {
      if (memberValue->hasName() &&
          memberValue->isOperator()) {
        // Add operator methods.
        // Note that we don't have to add operators that are already in the
        // top-level list.
        operatorMethodDecls[memberValue->getBaseName()].push_back({
          /*ignored*/0,
          S.addDeclRef(memberValue)
        });
      }
    }

    // Record Objective-C methods and derivative function configurations.
    if (auto *func = dyn_cast<AbstractFunctionDecl>(member)) {
      recordObjCMethod(func);
      recordDerivativeFunctionConfig(S, func, derivativeConfigs);
    }

    // Handle accessors.
    if (auto storage = dyn_cast<AbstractStorageDecl>(member)) {
      for (auto *accessor : storage->getAllAccessors()) {
        recordObjCMethod(accessor);
        recordDerivativeFunctionConfig(S, accessor, derivativeConfigs);
      }
    }

    if (auto nestedType = dyn_cast<TypeDecl>(member)) {
      if (nestedType->getEffectiveAccess() > swift::AccessLevel::FilePrivate) {
        if (!nominalParent) {
          const DeclContext *DC = member->getDeclContext();
          nominalParent = DC->getSelfNominalTypeDecl();
          assert(nominalParent ||
                 nestedType->getASTContext().LangOpts.AllowModuleWithCompilerErrors &&
                 "parent context is not a type or extension");
        }
        nestedTypeDecls[nestedType->getName()].push_back({
          S.addDeclRef(nominalParent),
          S.addDeclRef(nestedType)
        });
      }
    }

    // Recurse into nested declarations.
    if (auto iterable = dyn_cast<IterableDeclContext>(member)) {
      collectInterestingNestedDeclarations(S, iterable->getMembers(),
                                           operatorMethodDecls,
                                           objcMethods, nestedTypeDecls,
                                           derivativeConfigs,
                                           isLocal);
    }
  }
}

void Serializer::writeAST(ModuleOrSourceFile DC) {
  DeclTable topLevelDecls, operatorDecls, operatorMethodDecls;
  DeclTable precedenceGroupDecls;
  ObjCMethodTable objcMethods;
  NestedTypeDeclsTable nestedTypeDecls;
  LocalTypeHashTableGenerator localTypeGenerator, opaqueReturnTypeGenerator;
  ExtensionTable extensionDecls;
  UniquedDerivativeFunctionConfigTable uniquedDerivativeConfigs;
  DeclFingerprintsTable declFingerprints;
  bool hasLocalTypes = false;
  bool hasOpaqueReturnTypes = false;

  Optional<DeclID> entryPointClassID;
  SmallVector<DeclID, 16> orderedTopLevelDecls;

  ArrayRef<const FileUnit *> files;
  SmallVector<const FileUnit *, 1> Scratch;
  if (SF) {
    Scratch.push_back(SF);
    if (auto *synthesizedFile = SF->getSynthesizedFile())
      Scratch.push_back(synthesizedFile);
    files = llvm::makeArrayRef(Scratch);
  } else {
    files = M->getFiles();
  }
  for (auto nextFile : files) {
    if (nextFile->hasEntryPoint())
      entryPointClassID = addDeclRef(nextFile->getMainDecl());

    // FIXME: Switch to a visitor interface?
    SmallVector<Decl *, 32> fileDecls;
    nextFile->getTopLevelDecls(fileDecls);

    for (auto D : fileDecls) {
      if (isa<ImportDecl>(D) || isa<IfConfigDecl>(D) ||
          isa<PoundDiagnosticDecl>(D) || isa<TopLevelCodeDecl>(D)) {
        continue;
      }

      if (auto VD = dyn_cast<ValueDecl>(D)) {
        if (!VD->hasName())
          continue;
        topLevelDecls[VD->getBaseName()]
          .push_back({ getKindForTable(D), addDeclRef(D) });
      } else if (auto ED = dyn_cast<ExtensionDecl>(D)) {
        const NominalTypeDecl *extendedNominal = ED->getExtendedNominal();
        if (extendedNominal) {
          extensionDecls[extendedNominal->getName()]
            .push_back({ extendedNominal, addDeclRef(D) });
        }
      } else if (auto OD = dyn_cast<OperatorDecl>(D)) {
        operatorDecls[OD->getName()]
          .push_back({ getStableFixity(OD->getFixity()), addDeclRef(D) });
      } else if (auto PGD = dyn_cast<PrecedenceGroupDecl>(D)) {
        precedenceGroupDecls[PGD->getName()]
          .push_back({ decls_block::PRECEDENCE_GROUP_DECL, addDeclRef(D) });
      } else if (isa<PatternBindingDecl>(D)) {
        // No special handling needed.
      } else {
        llvm_unreachable("all top-level declaration kinds accounted for");
      }
      if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D))
        recordDerivativeFunctionConfig(*this, AFD, uniquedDerivativeConfigs);

      orderedTopLevelDecls.push_back(addDeclRef(D));

      // If this nominal type has associated top-level decls for a
      // derived conformance (for example, ==), force them to be
      // serialized.
      if (auto IDC = dyn_cast<IterableDeclContext>(D)) {
        if (auto bodyFP = IDC->getBodyFingerprint()) {
          declFingerprints.insert({addDeclRef(D), *bodyFP});
        }
        collectInterestingNestedDeclarations(*this, IDC->getMembers(),
                                             operatorMethodDecls, objcMethods,
                                             nestedTypeDecls,
                                             uniquedDerivativeConfigs);
      }
    }

    SmallVector<TypeDecl *, 16> localTypeDecls;
    nextFile->getLocalTypeDecls(localTypeDecls);
    SmallVector<OpaqueTypeDecl *, 16> opaqueReturnTypeDecls;
    nextFile->getOpaqueReturnTypeDecls(opaqueReturnTypeDecls);

    for (auto TD : localTypeDecls) {

      // FIXME: We should delay parsing function bodies so these type decls
      //        don't even get added to the file.
      if (TD->getDeclContext()->getInnermostSkippedFunctionContext())
        continue;

      hasLocalTypes = true;
      Mangle::ASTMangler Mangler;

      std::string MangledName =
          evaluateOrDefault(M->getASTContext().evaluator,
                            MangleLocalTypeDeclRequest { TD },
                            std::string());
      assert(!MangledName.empty() && "Mangled type came back empty!");
      localTypeGenerator.insert(MangledName, addDeclRef(TD));

      if (auto IDC = dyn_cast<IterableDeclContext>(TD)) {
        if (auto bodyFP = IDC->getBodyFingerprint()) {
          declFingerprints.insert({addDeclRef(TD), *bodyFP});
        }
        collectInterestingNestedDeclarations(*this, IDC->getMembers(),
                                             operatorMethodDecls, objcMethods,
                                             nestedTypeDecls,
                                             uniquedDerivativeConfigs,
                                             /*isLocal=*/true);
      }
    }
    
    for (auto OTD : opaqueReturnTypeDecls) {
      hasOpaqueReturnTypes = true;
      Mangle::ASTMangler Mangler;
      auto MangledName = Mangler.mangleOpaqueTypeDecl(OTD);
      opaqueReturnTypeGenerator.insert(MangledName, addDeclRef(OTD));
    }
  }

  writeAllDeclsAndTypes();
  std::vector<CharOffset> identifierOffsets = writeAllIdentifiers();

  {
    BCBlockRAII restoreBlock(Out, INDEX_BLOCK_ID, 4);

    index_block::OffsetsLayout Offsets(Out);
    writeOffsets(Offsets, DeclsToSerialize);
    writeOffsets(Offsets, TypesToSerialize);
    writeOffsets(Offsets, ClangTypesToSerialize);
    writeOffsets(Offsets, LocalDeclContextsToSerialize);
    writeOffsets(Offsets, GenericSignaturesToSerialize);
    writeOffsets(Offsets, SubstitutionMapsToSerialize);
    writeOffsets(Offsets, NormalConformancesToSerialize);
    writeOffsets(Offsets, SILLayoutsToSerialize);

    Offsets.emit(ScratchRecord, index_block::IDENTIFIER_OFFSETS,
                 identifierOffsets);

    index_block::DeclListLayout DeclList(Out);
    writeDeclTable(DeclList, index_block::TOP_LEVEL_DECLS, topLevelDecls);
    writeDeclTable(DeclList, index_block::OPERATORS, operatorDecls);
    writeDeclTable(DeclList, index_block::PRECEDENCE_GROUPS, precedenceGroupDecls);
    writeDeclTable(DeclList, index_block::CLASS_MEMBERS_FOR_DYNAMIC_LOOKUP,
                   ClassMembersForDynamicLookup);
    writeDeclTable(DeclList, index_block::OPERATOR_METHODS, operatorMethodDecls);
    if (hasLocalTypes)
      writeLocalDeclTable(DeclList, index_block::LOCAL_TYPE_DECLS,
                          localTypeGenerator);
    if (hasOpaqueReturnTypes)
      writeLocalDeclTable(DeclList, index_block::OPAQUE_RETURN_TYPE_DECLS,
                          opaqueReturnTypeGenerator);

    if (!extensionDecls.empty()) {
      index_block::ExtensionTableLayout ExtensionTable(Out);
      writeExtensionTable(ExtensionTable, extensionDecls, *this);
    }

    index_block::OrderedDeclsLayout OrderedDecls(Out);
    OrderedDecls.emit(ScratchRecord, index_block::ORDERED_TOP_LEVEL_DECLS,
                      orderedTopLevelDecls);

    index_block::OrderedDeclsLayout ExportedPrespecializationDecls(Out);
    ExportedPrespecializationDecls.emit(
        ScratchRecord, index_block::EXPORTED_PRESPECIALIZATION_DECLS,
        exportedPrespecializationDecls);

    index_block::ObjCMethodTableLayout ObjCMethodTable(Out);
    writeObjCMethodTable(ObjCMethodTable, objcMethods);

    if (!nestedTypeDecls.empty()) {
      index_block::NestedTypeDeclsLayout NestedTypeDeclsTable(Out);
      writeNestedTypeDeclsTable(NestedTypeDeclsTable, nestedTypeDecls);
    }

    if (!declFingerprints.empty()) {
      index_block::DeclFingerprintsLayout DeclsFingerprints(Out);
      writeDeclFingerprintsTable(DeclsFingerprints, declFingerprints);
    }

    // Convert uniqued derivative function config table to serialization-
    // ready format: turn `GenericSignature` to `GenericSignatureID`.
    DerivativeFunctionConfigTable derivativeConfigs;
    for (auto entry : uniquedDerivativeConfigs) {
      for (auto config : entry.second) {
        std::string paramIndices = config.first.str().str();
        auto genSigID = addGenericSignatureRef(config.second);
        derivativeConfigs[entry.first].push_back({paramIndices, genSigID});
      }
    }
    index_block::DerivativeFunctionConfigTableLayout DerivativeConfigTable(Out);
    writeDerivativeFunctionConfigs(*this, DerivativeConfigTable,
                                   derivativeConfigs);

    if (entryPointClassID.hasValue()) {
      index_block::EntryPointLayout EntryPoint(Out);
      EntryPoint.emit(ScratchRecord, entryPointClassID.getValue());
    }

    {
      // Write sub-tables to a skippable sub-block.
      BCBlockRAII restoreBlock(Out, DECL_MEMBER_TABLES_BLOCK_ID, 4);
      decl_member_tables_block::DeclMembersLayout DeclMembersTable(Out);
      for (auto &entry : DeclMemberNames) {
        // Save BitOffset we're writing sub-table to.
        static_assert(bitOffsetFitsIn32Bits(), "BitOffset too large");
        assert(Out.GetCurrentBitNo() < (1ull << 32));
        entry.second.first = Out.GetCurrentBitNo();
        // Write sub-table.
        writeDeclMembersTable(DeclMembersTable, *entry.second.second);
      }
    }
    // Write top-level table mapping names to sub-tables.
    index_block::DeclMemberNamesLayout DeclMemberNamesTable(Out);
    writeDeclMemberNamesTable(DeclMemberNamesTable, DeclMemberNames);
  }
}

void SerializerBase::writeToStream(raw_ostream &os) {
  os.write(Buffer.data(), Buffer.size());
  os.flush();
}

SerializerBase::SerializerBase(ArrayRef<unsigned char> signature,
                               ModuleOrSourceFile DC) {
  for (unsigned char byte : signature)
    Out.Emit(byte, 8);

  this->M = getModule(DC);
  this->SF = DC.dyn_cast<SourceFile *>();
}

void Serializer::writeToStream(
    raw_ostream &os, ModuleOrSourceFile DC,
    const SILModule *SILMod,
    const SerializationOptions &options,
    const fine_grained_dependencies::SourceFileDepGraph *DepGraph) {
  Serializer S{SWIFTMODULE_SIGNATURE, DC};

  // FIXME: This is only really needed for debugging. We don't actually use it.
  S.writeBlockInfoBlock();

  {
    BCBlockRAII moduleBlock(S.Out, MODULE_BLOCK_ID, 2);
    S.writeHeader(options);
    S.writeInputBlock(options);
    S.writeSIL(SILMod, options.SerializeAllSIL);
    S.writeAST(DC);
    if (options.ExperimentalCrossModuleIncrementalInfo && DepGraph) {
      fine_grained_dependencies::writeFineGrainedDependencyGraph(
          S.Out, *DepGraph, fine_grained_dependencies::Purpose::ForSwiftModule);
    }
  }

  S.writeToStream(os);
}

void swift::serializeToBuffers(
  ModuleOrSourceFile DC, const SerializationOptions &options,
  std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
  std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
  std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
  const SILModule *M) {

  assert(!StringRef::withNullAsEmpty(options.OutputPath).empty());
  {
    FrontendStatsTracer tracer(getContext(DC).Stats,
                               "Serialization, swiftmodule, to buffer");
    llvm::SmallString<1024> buf;
    llvm::raw_svector_ostream stream(buf);
    Serializer::writeToStream(stream, DC, M, options,
                              /*dependency info*/ nullptr);
    bool hadError = withOutputFile(getContext(DC).Diags,
                                   options.OutputPath,
                                   [&](raw_ostream &out) {
      out << stream.str();
      return false;
    });
    if (hadError)
      return;
    if (moduleBuffer)
      *moduleBuffer = std::make_unique<llvm::SmallVectorMemoryBuffer>(
                        std::move(buf), options.OutputPath);
  }

  if (!StringRef::withNullAsEmpty(options.DocOutputPath).empty()) {
    FrontendStatsTracer tracer(getContext(DC).Stats,
                               "Serialization, swiftdoc, to buffer");
    llvm::SmallString<1024> buf;
    llvm::raw_svector_ostream stream(buf);
    writeDocToStream(stream, DC, options.GroupInfoPath);
    (void)withOutputFile(getContext(DC).Diags,
                         options.DocOutputPath,
                         [&](raw_ostream &out) {
      out << stream.str();
      return false;
    });
    if (moduleDocBuffer)
      *moduleDocBuffer = std::make_unique<llvm::SmallVectorMemoryBuffer>(
                           std::move(buf), options.DocOutputPath);
  }

  if (!StringRef::withNullAsEmpty(options.SourceInfoOutputPath).empty()) {
    FrontendStatsTracer tracer(getContext(DC).Stats,
                               "Serialization, swiftsourceinfo, to buffer");
    llvm::SmallString<1024> buf;
    llvm::raw_svector_ostream stream(buf);
    writeSourceInfoToStream(stream, DC);
    (void)withOutputFile(getContext(DC).Diags,
                         options.SourceInfoOutputPath,
                         [&](raw_ostream &out) {
      out << stream.str();
      return false;
    });
    if (moduleSourceInfoBuffer)
      *moduleSourceInfoBuffer = std::make_unique<llvm::SmallVectorMemoryBuffer>(
          std::move(buf), options.SourceInfoOutputPath);
  }
}

void swift::serialize(ModuleOrSourceFile DC,
                      const SerializationOptions &options,
                      const SILModule *M,
                      const fine_grained_dependencies::SourceFileDepGraph *DG) {
  assert(!StringRef::withNullAsEmpty(options.OutputPath).empty());

  if (StringRef(options.OutputPath) == "-") {
    // Special-case writing to stdout.
    Serializer::writeToStream(llvm::outs(), DC, M, options, DG);
    assert(StringRef::withNullAsEmpty(options.DocOutputPath).empty());
    return;
  }

  bool hadError = withOutputFile(getContext(DC).Diags,
                                 options.OutputPath,
                                 [&](raw_ostream &out) {
    FrontendStatsTracer tracer(getContext(DC).Stats,
                               "Serialization, swiftmodule");
    Serializer::writeToStream(out, DC, M, options, DG);
    return false;
  });
  if (hadError)
    return;

  if (!StringRef::withNullAsEmpty(options.DocOutputPath).empty()) {
    (void)withOutputFile(getContext(DC).Diags,
                         options.DocOutputPath,
                         [&](raw_ostream &out) {
      FrontendStatsTracer tracer(getContext(DC).Stats,
                                 "Serialization, swiftdoc");
      writeDocToStream(out, DC, options.GroupInfoPath);
      return false;
    });
  }

  if (!StringRef::withNullAsEmpty(options.SourceInfoOutputPath).empty()) {
    (void)withOutputFile(getContext(DC).Diags,
                         options.SourceInfoOutputPath,
                         [&](raw_ostream &out) {
      FrontendStatsTracer tracer(getContext(DC).Stats,
                                 "Serialization, swiftsourceinfo");
      writeSourceInfoToStream(out, DC);
      return false;
    });
  }
}
