[serialization] Sprinkle PrettyStackTrace throughout deserialization code.

Since we don't have soft-failure yet from deserialization, it's helpful to
at least know where to start looking when something crashes. There are some
rough edges here but it should be much better than nothing.

This also pulls the list of record nodes out into a separate file, so that
we can avoid repeating it.

Example crash:
1.	While reading from ./CTypes.swiftmodule
2.	While deserializing 'CBool' (StructDecl)
3.	While deserializing decl #26 (XREF)
4.	Cross-reference to 'LogicValue' in swift
(don't worry, this is an example where I'm tweaking things)

<rdar://problem/14838332>

Swift SVN r11057
This commit is contained in:
Jordan Rose
2013-12-10 00:23:40 +00:00
parent 549b2f1368
commit fac5659813
6 changed files with 315 additions and 169 deletions

View File

@@ -0,0 +1,160 @@
//===-- DeclTypeRecordNodes.def - Serialization Metaprogramming -*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
/// \file
/// \brief Defines macros used for metaprogramming with the serialized records
/// in the "decls-and-types" block of serialized ASTs.
///
/// You should define one of the following sets of macros:
/// - RECORD(Id)
/// - RECORD(Id) and RECORD_VAL(Id)
/// - Any of TYPE(Id), DECL(Id), PATTERN(Id)
//
//===----------------------------------------------------------------------===//
#ifndef RECORD
#define RECORD(Id)
#endif
#ifdef RECORD_VAL
#define DECLTYPERECORDNODES_HAS_RECORD_VAL 1
#else
#define DECLTYPERECORDNODES_HAS_RECORD_VAL 0
#define RECORD_VAL(Id, Value) RECORD(Id)
#endif
#ifndef TYPE
#define TYPE(Id) RECORD(Id##_TYPE)
#endif
#ifndef FIRST_TYPE
# if DECLTYPERECORDNODES_HAS_RECORD_VAL
# define FIRST_TYPE(Id, Value) RECORD_VAL(Id##_TYPE, Value)
# else
# define FIRST_TYPE(Id, Value) TYPE(Id)
# endif
#endif
#ifndef DECL
#define DECL(Id) RECORD(Id##_DECL)
#endif
#ifndef FIRST_DECL
# if DECLTYPERECORDNODES_HAS_RECORD_VAL
# define FIRST_DECL(Id, Value) RECORD_VAL(Id##_DECL, Value)
# else
# define FIRST_DECL(Id, Value) DECL(Id)
# endif
#endif
#ifndef PATTERN
#define PATTERN(Id) RECORD(Id##_PATTERN)
#endif
#ifndef FIRST_PATTERN
# if DECLTYPERECORDNODES_HAS_RECORD_VAL
# define FIRST_PATTERN(Id, Value) RECORD_VAL(Id##_PATTERN, Value)
# else
# define FIRST_PATTERN(Id, Value) PATTERN(Id)
# endif
#endif
#ifndef TRAILING_INFO
#define TRAILING_INFO(Id) RECORD(Id)
#endif
#ifndef OTHER
#define OTHER(Id, Value) RECORD_VAL(Id, Value)
#endif
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR in ModuleFormat.h. Names, however, may change.
FIRST_TYPE(NAME_ALIAS, 1)
TYPE(GENERIC_TYPE_PARAM)
TYPE(ASSOCIATED_TYPE) // This is correct! ASSOCIATED_TYPE_TYPE
TYPE(DEPENDENT_MEMBER)
TYPE(NOMINAL)
TYPE(PAREN)
TYPE(TUPLE)
TRAILING_INFO(TUPLE_TYPE_ELT)
TYPE(FUNCTION)
TYPE(METATYPE)
TYPE(LVALUE)
TYPE(ARCHETYPE)
TRAILING_INFO(ARCHETYPE_NESTED_TYPE_NAMES)
TRAILING_INFO(ARCHETYPE_NESTED_TYPES)
TYPE(PROTOCOL_COMPOSITION)
TYPE(SUBSTITUTED)
TYPE(BOUND_GENERIC)
TRAILING_INFO(BOUND_GENERIC_SUBSTITUTION)
TYPE(POLYMORPHIC_FUNCTION)
TYPE(GENERIC_FUNCTION)
TYPE(ARRAY_SLICE)
TYPE(ARRAY)
TYPE(REFERENCE_STORAGE)
TYPE(UNBOUND_GENERIC)
TYPE(OPTIONAL)
TYPE(SIL_FUNCTION)
FIRST_DECL(TYPE_ALIAS, 100)
DECL(GENERIC_TYPE_PARAM)
DECL(ASSOCIATED_TYPE)
DECL(STRUCT)
DECL(CONSTRUCTOR)
DECL(VAR)
DECL(FUNC)
DECL(PATTERN_BINDING)
DECL(PROTOCOL)
DECL(PREFIX_OPERATOR)
DECL(POSTFIX_OPERATOR)
DECL(INFIX_OPERATOR)
DECL(CLASS)
DECL(ENUM)
DECL(ENUM_ELEMENT)
DECL(SUBSCRIPT)
DECL(EXTENSION)
DECL(DESTRUCTOR)
FIRST_PATTERN(PAREN, 200)
PATTERN(TUPLE)
TRAILING_INFO(TUPLE_PATTERN_ELT)
PATTERN(NAMED)
PATTERN(ANY)
PATTERN(TYPED)
PATTERN(ISA)
PATTERN(NOMINAL_TYPE)
TRAILING_INFO(NOMINAL_TYPE_PATTERN_ELT)
PATTERN(VAR)
OTHER(GENERIC_PARAM_LIST, 240)
TRAILING_INFO(GENERIC_PARAM)
TRAILING_INFO(GENERIC_REQUIREMENT)
TRAILING_INFO(LAST_GENERIC_REQUIREMENT)
OTHER(NO_CONFORMANCE, 250)
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 251)
OTHER(SPECIALIZED_PROTOCOL_CONFORMANCE, 252)
OTHER(INHERITED_PROTOCOL_CONFORMANCE, 253)
OTHER(DECL_CONTEXT, 254)
OTHER(XREF, 255)
#undef RECORD
#undef DECLTYPERECORDNODES_HAS_RECORD_VAL
#undef RECORD_VAL
#undef TYPE
#undef FIRST_TYPE
#undef DECL
#undef FIRST_DECL
#undef PATTERN
#undef FIRST_PATTERN
#undef TRAILING_INFO
#undef OTHER

View File

@@ -13,7 +13,9 @@
#include "ModuleFile.h"
#include "ModuleFormat.h"
#include "swift/AST/AST.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/Serialization/BCReadingExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
using namespace swift::serialization;
@@ -21,6 +23,77 @@ using namespace swift::serialization;
using ConformancePair = std::pair<ProtocolDecl *, ProtocolConformance *>;
namespace {
class PrettyDeclDeserialization : public llvm::PrettyStackTraceEntry {
const ModuleFile::Serialized<Decl*> &DeclOrOffset;
DeclID ID;
decls_block::RecordKind Kind;
public:
PrettyDeclDeserialization(const ModuleFile::Serialized<Decl*> &declOrOffset,
DeclID DID, decls_block::RecordKind kind)
: DeclOrOffset(declOrOffset), ID(DID), Kind(kind) {
}
static const char *getRecordKindString(decls_block::RecordKind Kind) {
switch (Kind) {
#define RECORD(Id) case decls_block::Id: return #Id;
#include "DeclTypeRecordNodes.def"
}
}
virtual void print(raw_ostream &os) const override {
if (!DeclOrOffset.isComplete()) {
os << "While deserializing decl #" << ID << " ("
<< getRecordKindString(Kind) << ")\n";
return;
}
os << "While deserializing ";
if (auto VD = dyn_cast<ValueDecl>(DeclOrOffset.get())) {
os << "'" << VD->getName() << "' ("
<< Decl::getKindName(VD->getKind()) << "Decl) \n";
} else {
os << Decl::getKindName(DeclOrOffset.get()->getKind())
<< "Decl #" << ID << "\n";
}
}
};
class PrettyXRefDeserialization : public llvm::PrettyStackTraceEntry {
ModuleFile &File;
XRefKind Kind;
Module &ContainingModule;
ArrayRef<uint64_t> RawPath;
public:
PrettyXRefDeserialization(ModuleFile &file, XRefKind kind, Module &M,
ArrayRef<uint64_t> rawPath)
: File(file), Kind(kind), ContainingModule(M), RawPath(rawPath) {}
virtual void print(raw_ostream &os) const override {
auto NamePath = RawPath;
os << "Cross-reference to ";
switch (Kind) {
case XRefKind::SwiftValue:
case XRefKind::SwiftOperator:
break;
case XRefKind::SwiftGenericParameter:
os << "generic param " << RawPath.back() << " of ";
NamePath = RawPath.slice(0, RawPath.size()-1);
break;
}
os << "'";
interleave(NamePath,
[&](IdentifierID IID) { os << File.getIdentifier(IID); },
[&]() { os << "."; });
os << "' in " << ContainingModule.Name << "\n";
}
};
} // end anonymous namespace
/// Translate from the serialization DefaultArgumentKind enumerators, which are
/// guaranteed to be stable, to the AST ones.
static Optional<swift::DefaultArgumentKind>
@@ -783,6 +856,9 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
StringRef blobData;
unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
PrettyDeclDeserialization stackTraceEntry(
declOrOffset, DID, static_cast<decls_block::RecordKind>(recordID));
switch (recordID) {
case decls_block::TYPE_ALIAS_DECL: {
IdentifierID nameID;
@@ -1626,6 +1702,9 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
assert(M && "missing dependency");
rawAccessPath = rawAccessPath.slice(1);
PrettyXRefDeserialization moreStackInfo(*this, static_cast<XRefKind>(kind),
*M, rawAccessPath);
switch (kind) {
case XRefKind::SwiftValue:
case XRefKind::SwiftGenericParameter: {

View File

@@ -23,6 +23,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
using namespace swift;
using namespace swift::serialization;
@@ -72,6 +73,19 @@ validateControlBlock(llvm::BitstreamCursor &cursor,
return result;
}
namespace {
class PrettyModuleFileDeserialization : public llvm::PrettyStackTraceEntry {
const ModuleFile &File;
public:
explicit PrettyModuleFileDeserialization(const ModuleFile &file)
: File(file) {}
virtual void print(raw_ostream &os) const override {
os << "While reading from " << File.getModuleFilename() << "\n";
}
};
} // end anonymous namespace
/// Used to deserialize entries in the on-disk decl hash table.
class ModuleFile::DeclTableInfo {
public:
@@ -274,6 +288,8 @@ ModuleFile::ModuleFile(std::unique_ptr<llvm::MemoryBuffer> input)
InputReader(reinterpret_cast<const uint8_t *>(InputFile->getBufferStart()),
reinterpret_cast<const uint8_t *>(InputFile->getBufferEnd())),
Status(ModuleStatus::Valid) {
PrettyModuleFileDeserialization stackEntry(*this);
llvm::BitstreamCursor cursor{InputReader};
for (unsigned char byte : SIGNATURE) {
@@ -452,6 +468,8 @@ static NominalTypeDecl *getAnyNominal(Decl *D) {
}
bool ModuleFile::associateWithFileContext(FileUnit *file) {
PrettyModuleFileDeserialization stackEntry(*this);
assert(Status == ModuleStatus::Valid && "invalid module file");
assert(!FileContext && "already associated with an AST module");
FileContext = file;
@@ -503,6 +521,8 @@ ModuleFile::~ModuleFile() = default;
void ModuleFile::lookupValue(Identifier name,
SmallVectorImpl<ValueDecl*> &results) {
PrettyModuleFileDeserialization stackEntry(*this);
if (!TopLevelDecls)
return;
@@ -521,6 +541,8 @@ void ModuleFile::lookupValue(Identifier name,
}
OperatorDecl *ModuleFile::lookupOperator(Identifier name, DeclKind fixity) {
PrettyModuleFileDeserialization stackEntry(*this);
if (!OperatorDecls)
return nullptr;
@@ -541,6 +563,8 @@ OperatorDecl *ModuleFile::lookupOperator(Identifier name, DeclKind fixity) {
void ModuleFile::getImportedModules(
SmallVectorImpl<Module::ImportedModule> &results,
bool includePrivate) {
PrettyModuleFileDeserialization stackEntry(*this);
for (auto &dep : Dependencies) {
if (!includePrivate && !dep.IsExported)
continue;
@@ -552,6 +576,7 @@ void ModuleFile::getImportedModules(
void ModuleFile::lookupVisibleDecls(Module::AccessPathTy accessPath,
VisibleDeclConsumer &consumer,
NLKind lookupKind) {
PrettyModuleFileDeserialization stackEntry(*this);
assert(accessPath.size() <= 1 && "can only refer to top-level decls");
if (!TopLevelDecls)
@@ -576,6 +601,7 @@ void ModuleFile::lookupVisibleDecls(Module::AccessPathTy accessPath,
}
void ModuleFile::loadExtensions(NominalTypeDecl *nominal) {
PrettyModuleFileDeserialization stackEntry(*this);
if (!ExtensionDecls)
return;
@@ -590,6 +616,8 @@ void ModuleFile::loadExtensions(NominalTypeDecl *nominal) {
}
void ModuleFile::loadDeclsConformingTo(KnownProtocolKind kind) {
PrettyModuleFileDeserialization stackEntry(*this);
auto index = static_cast<unsigned>(kind);
for (DeclID DID : KnownProtocolAdopters[index]) {
Decl *D = getDecl(DID);
@@ -602,6 +630,7 @@ void ModuleFile::loadDeclsConformingTo(KnownProtocolKind kind) {
void ModuleFile::lookupClassMember(Module::AccessPathTy accessPath,
Identifier name,
SmallVectorImpl<ValueDecl*> &results) {
PrettyModuleFileDeserialization stackEntry(*this);
assert(accessPath.size() <= 1 && "can only refer to top-level decls");
if (!ClassMembersByName)
@@ -632,6 +661,7 @@ void ModuleFile::lookupClassMember(Module::AccessPathTy accessPath,
void ModuleFile::lookupClassMembers(Module::AccessPathTy accessPath,
VisibleDeclConsumer &consumer) {
PrettyModuleFileDeserialization stackEntry(*this);
assert(accessPath.size() <= 1 && "can only refer to top-level decls");
if (!ClassMembersByName)
@@ -668,6 +698,7 @@ ModuleFile::collectLinkLibraries(Module::LinkLibraryCallback callback) const {
}
void ModuleFile::getTopLevelDecls(SmallVectorImpl<Decl *> &results) {
PrettyModuleFileDeserialization stackEntry(*this);
if (OperatorDecls) {
for (auto entry : make_range(OperatorDecls->data_begin(),
OperatorDecls->data_end())) {
@@ -697,5 +728,6 @@ void ModuleFile::getDisplayDecls(SmallVectorImpl<Decl *> &results) {
if (ShadowedModule)
ShadowedModule->getDisplayDecls(results);
PrettyModuleFileDeserialization stackEntry(*this);
getTopLevelDecls(results);
}

View File

@@ -180,6 +180,8 @@ private:
/// Convenience function for module loading.
void error(ModuleStatus issue = ModuleStatus::Malformed) {
assert(issue != ModuleStatus::Valid);
assert((!FileContext || issue != ModuleStatus::Malformed) &&
"error deserializing an individual record");
Status = issue;
}

View File

@@ -10,7 +10,8 @@
//
//===----------------------------------------------------------------------===//
///
/// \file Contains various constants and helper types to deal with serialized
/// \file
/// \brief Contains various constants and helper types to deal with serialized
/// modules.
///
//===----------------------------------------------------------------------===//
@@ -303,75 +304,9 @@ namespace decls_block {
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
enum RecordKind : uint8_t {
NAME_ALIAS_TYPE = 1,
GENERIC_TYPE_PARAM_TYPE,
ASSOCIATED_TYPE_TYPE,
DEPENDENT_MEMBER_TYPE,
NOMINAL_TYPE,
PAREN_TYPE,
TUPLE_TYPE,
TUPLE_TYPE_ELT,
FUNCTION_TYPE,
METATYPE_TYPE,
LVALUE_TYPE,
ARCHETYPE_TYPE,
ARCHETYPE_NESTED_TYPE_NAMES,
ARCHETYPE_NESTED_TYPES,
PROTOCOL_COMPOSITION_TYPE,
SUBSTITUTED_TYPE,
BOUND_GENERIC_TYPE,
BOUND_GENERIC_SUBSTITUTION,
POLYMORPHIC_FUNCTION_TYPE,
GENERIC_FUNCTION_TYPE,
ARRAY_SLICE_TYPE,
ARRAY_TYPE,
REFERENCE_STORAGE_TYPE,
UNBOUND_GENERIC_TYPE,
OPTIONAL_TYPE,
SIL_FUNCTION_TYPE,
TYPE_ALIAS_DECL = 100,
GENERIC_TYPE_PARAM_DECL,
ASSOCIATED_TYPE_DECL,
STRUCT_DECL,
CONSTRUCTOR_DECL,
VAR_DECL,
FUNC_DECL,
PATTERN_BINDING_DECL,
PROTOCOL_DECL,
PREFIX_OPERATOR_DECL,
POSTFIX_OPERATOR_DECL,
INFIX_OPERATOR_DECL,
CLASS_DECL,
ENUM_DECL,
ENUM_ELEMENT_DECL,
SUBSCRIPT_DECL,
EXTENSION_DECL,
DESTRUCTOR_DECL,
KNOWN_PROTOCOL,
PAREN_PATTERN = 200,
TUPLE_PATTERN,
TUPLE_PATTERN_ELT,
NAMED_PATTERN,
ANY_PATTERN,
TYPED_PATTERN,
ISA_PATTERN,
NOMINAL_TYPE_PATTERN,
NOMINAL_TYPE_PATTERN_ELT,
VAR_PATTERN,
GENERIC_PARAM_LIST = 240,
GENERIC_PARAM,
GENERIC_REQUIREMENT,
LAST_GENERIC_REQUIREMENT,
NO_CONFORMANCE = 250,
NORMAL_PROTOCOL_CONFORMANCE = 251,
SPECIALIZED_PROTOCOL_CONFORMANCE = 252,
INHERITED_PROTOCOL_CONFORMANCE = 253,
DECL_CONTEXT = 254,
XREF = 255
#define RECORD(Id) Id,
#define RECORD_VAL(Id, Value) Id = Value,
#include "DeclTypeRecordNodes.def"
};
using NameAliasTypeLayout = BCRecordLayout<

View File

@@ -230,124 +230,62 @@ void Serializer::writeBlockInfoBlock() {
SmallVector<unsigned char, 64> nameBuffer;
#define BLOCK(X) emitBlockID(Out, X ## _ID, #X, nameBuffer)
#define RECORD(K, X) emitRecordID(Out, K::X, #X, nameBuffer)
#define BLOCK_RECORD(K, X) emitRecordID(Out, K::X, #X, nameBuffer)
BLOCK(CONTROL_BLOCK);
RECORD(control_block, METADATA);
BLOCK_RECORD(control_block, METADATA);
BLOCK(INPUT_BLOCK);
RECORD(input_block, SOURCE_FILE);
RECORD(input_block, IMPORTED_MODULE);
RECORD(input_block, LINK_LIBRARY);
BLOCK_RECORD(input_block, SOURCE_FILE);
BLOCK_RECORD(input_block, IMPORTED_MODULE);
BLOCK_RECORD(input_block, LINK_LIBRARY);
BLOCK(DECLS_AND_TYPES_BLOCK);
RECORD(decls_block, NAME_ALIAS_TYPE);
RECORD(decls_block, GENERIC_TYPE_PARAM_TYPE);
RECORD(decls_block, ASSOCIATED_TYPE_TYPE);
RECORD(decls_block, DEPENDENT_MEMBER_TYPE);
RECORD(decls_block, NOMINAL_TYPE);
RECORD(decls_block, PAREN_TYPE);
RECORD(decls_block, TUPLE_TYPE);
RECORD(decls_block, TUPLE_TYPE_ELT);
RECORD(decls_block, FUNCTION_TYPE);
RECORD(decls_block, METATYPE_TYPE);
RECORD(decls_block, LVALUE_TYPE);
RECORD(decls_block, ARCHETYPE_TYPE);
RECORD(decls_block, ARCHETYPE_NESTED_TYPE_NAMES);
RECORD(decls_block, ARCHETYPE_NESTED_TYPES);
RECORD(decls_block, PROTOCOL_COMPOSITION_TYPE);
RECORD(decls_block, SUBSTITUTED_TYPE);
RECORD(decls_block, BOUND_GENERIC_TYPE);
RECORD(decls_block, BOUND_GENERIC_SUBSTITUTION);
RECORD(decls_block, POLYMORPHIC_FUNCTION_TYPE);
RECORD(decls_block, GENERIC_FUNCTION_TYPE);
RECORD(decls_block, ARRAY_SLICE_TYPE);
RECORD(decls_block, ARRAY_TYPE);
RECORD(decls_block, REFERENCE_STORAGE_TYPE);
RECORD(decls_block, UNBOUND_GENERIC_TYPE);
RECORD(decls_block, OPTIONAL_TYPE);
RECORD(decls_block, SIL_FUNCTION_TYPE);
RECORD(decls_block, TYPE_ALIAS_DECL);
RECORD(decls_block, GENERIC_TYPE_PARAM_DECL);
RECORD(decls_block, ASSOCIATED_TYPE_DECL);
RECORD(decls_block, STRUCT_DECL);
RECORD(decls_block, CONSTRUCTOR_DECL);
RECORD(decls_block, VAR_DECL);
RECORD(decls_block, FUNC_DECL);
RECORD(decls_block, PATTERN_BINDING_DECL);
RECORD(decls_block, PROTOCOL_DECL);
RECORD(decls_block, PREFIX_OPERATOR_DECL);
RECORD(decls_block, POSTFIX_OPERATOR_DECL);
RECORD(decls_block, INFIX_OPERATOR_DECL);
RECORD(decls_block, CLASS_DECL);
RECORD(decls_block, ENUM_DECL);
RECORD(decls_block, ENUM_ELEMENT_DECL);
RECORD(decls_block, SUBSCRIPT_DECL);
RECORD(decls_block, EXTENSION_DECL);
RECORD(decls_block, DESTRUCTOR_DECL);
RECORD(decls_block, PAREN_PATTERN);
RECORD(decls_block, TUPLE_PATTERN);
RECORD(decls_block, TUPLE_PATTERN_ELT);
RECORD(decls_block, NAMED_PATTERN);
RECORD(decls_block, ANY_PATTERN);
RECORD(decls_block, TYPED_PATTERN);
RECORD(decls_block, GENERIC_PARAM_LIST);
RECORD(decls_block, GENERIC_PARAM);
RECORD(decls_block, GENERIC_REQUIREMENT);
RECORD(decls_block, LAST_GENERIC_REQUIREMENT);
RECORD(decls_block, NO_CONFORMANCE);
RECORD(decls_block, NORMAL_PROTOCOL_CONFORMANCE);
RECORD(decls_block, SPECIALIZED_PROTOCOL_CONFORMANCE);
RECORD(decls_block, INHERITED_PROTOCOL_CONFORMANCE);
RECORD(decls_block, DECL_CONTEXT);
RECORD(decls_block, XREF);
#define RECORD(X) BLOCK_RECORD(decls_block, X);
#include "DeclTypeRecordNodes.def"
BLOCK(IDENTIFIER_DATA_BLOCK);
RECORD(identifier_block, IDENTIFIER_DATA);
BLOCK_RECORD(identifier_block, IDENTIFIER_DATA);
BLOCK(INDEX_BLOCK);
RECORD(index_block, TYPE_OFFSETS);
RECORD(index_block, DECL_OFFSETS);
RECORD(index_block, IDENTIFIER_OFFSETS);
RECORD(index_block, TOP_LEVEL_DECLS);
RECORD(index_block, OPERATORS);
RECORD(index_block, EXTENSIONS);
RECORD(index_block, CLASS_MEMBERS);
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);
BLOCK(SIL_BLOCK);
RECORD(sil_block, SIL_FUNCTION);
RECORD(sil_block, SIL_BASIC_BLOCK);
RECORD(sil_block, SIL_ONE_VALUE_ONE_OPERAND);
RECORD(sil_block, SIL_ONE_TYPE);
RECORD(sil_block, SIL_ONE_OPERAND);
RECORD(sil_block, SIL_ONE_TYPE_ONE_OPERAND);
RECORD(sil_block, SIL_ONE_TYPE_VALUES);
RECORD(sil_block, SIL_TWO_OPERANDS);
RECORD(sil_block, SIL_INST_APPLY);
RECORD(sil_block, SIL_INST_NO_OPERAND);
RECORD(sil_block, SIL_VTABLE);
RECORD(sil_block, SIL_VTABLE_ENTRY);
RECORD(sil_block, SIL_GLOBALVAR);
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_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(SIL_INDEX_BLOCK);
RECORD(sil_index_block, SIL_FUNC_NAMES);
RECORD(sil_index_block, SIL_FUNC_OFFSETS);
RECORD(sil_index_block, SIL_VTABLE_NAMES);
RECORD(sil_index_block, SIL_VTABLE_OFFSETS);
RECORD(sil_index_block, SIL_GLOBALVAR_NAMES);
RECORD(sil_index_block, SIL_GLOBALVAR_OFFSETS);
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(KNOWN_PROTOCOL_BLOCK);
#define PROTOCOL(Id) RECORD(index_block, Id);
#define PROTOCOL(Id) BLOCK_RECORD(index_block, Id);
#include "swift/AST/KnownProtocols.def"
RECORD(index_block, FORCE_DESERIALIZATION);
BLOCK_RECORD(index_block, FORCE_DESERIALIZATION);
#undef BLOCK
#undef RECORD
#undef BLOCK_RECORD
}
void Serializer::writeHeader() {