in lib/Serialization/Deserialization.cpp [4326:4819]
llvm::Error DeclDeserializer::deserializeDeclCommon() {
using namespace decls_block;
SmallVector<uint64_t, 64> scratch;
StringRef blobData;
while (true) {
BCOffsetRAII restoreOffset(MF.DeclTypeCursor);
llvm::BitstreamEntry entry =
MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
if (entry.Kind != llvm::BitstreamEntry::Record) {
// We don't know how to serialize decls represented by sub-blocks.
MF.fatal();
}
unsigned recordID = MF.fatalIfUnexpected(
MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
if (recordID == ERROR_FLAG) {
assert(!IsInvalid && "Error flag written multiple times");
IsInvalid = true;
} else if (isDeclAttrRecord(recordID)) {
DeclAttribute *Attr = nullptr;
bool skipAttr = false;
switch (recordID) {
case decls_block::SILGenName_DECL_ATTR: {
bool isImplicit;
serialization::decls_block::SILGenNameDeclAttrLayout::readRecord(
scratch, isImplicit);
Attr = new (ctx) SILGenNameAttr(blobData, isImplicit);
break;
}
case decls_block::CDecl_DECL_ATTR: {
bool isImplicit;
serialization::decls_block::CDeclDeclAttrLayout::readRecord(
scratch, isImplicit);
Attr = new (ctx) CDeclAttr(blobData, isImplicit);
break;
}
case decls_block::Alignment_DECL_ATTR: {
bool isImplicit;
unsigned alignment;
serialization::decls_block::AlignmentDeclAttrLayout::readRecord(
scratch, isImplicit, alignment);
Attr = new (ctx) AlignmentAttr(alignment, SourceLoc(), SourceRange(),
isImplicit);
break;
}
case decls_block::SwiftNativeObjCRuntimeBase_DECL_ATTR: {
bool isImplicit;
IdentifierID nameID;
serialization::decls_block::SwiftNativeObjCRuntimeBaseDeclAttrLayout
::readRecord(scratch, isImplicit, nameID);
auto name = MF.getIdentifier(nameID);
Attr = new (ctx) SwiftNativeObjCRuntimeBaseAttr(name, SourceLoc(),
SourceRange(),
isImplicit);
break;
}
case decls_block::Semantics_DECL_ATTR: {
bool isImplicit;
serialization::decls_block::SemanticsDeclAttrLayout::readRecord(
scratch, isImplicit);
Attr = new (ctx) SemanticsAttr(blobData, isImplicit);
break;
}
case decls_block::Inline_DECL_ATTR: {
unsigned kind;
serialization::decls_block::InlineDeclAttrLayout::readRecord(
scratch, kind);
Attr = new (ctx) InlineAttr((InlineKind)kind);
break;
}
case decls_block::NonSendable_DECL_ATTR: {
unsigned kind;
serialization::decls_block::NonSendableDeclAttrLayout::readRecord(
scratch, kind);
Attr = new (ctx) NonSendableAttr((NonSendableKind)kind);
break;
}
case decls_block::Optimize_DECL_ATTR: {
unsigned kind;
serialization::decls_block::OptimizeDeclAttrLayout::readRecord(
scratch, kind);
Attr = new (ctx) OptimizeAttr((OptimizationMode)kind);
break;
}
case decls_block::Exclusivity_DECL_ATTR: {
unsigned kind;
serialization::decls_block::ExclusivityDeclAttrLayout::readRecord(
scratch, kind);
Attr = new (ctx) ExclusivityAttr((ExclusivityAttr::Mode)kind);
break;
}
case decls_block::Effects_DECL_ATTR: {
unsigned kind;
IdentifierID customStringID;
serialization::decls_block::EffectsDeclAttrLayout::
readRecord(scratch, kind, customStringID);
if (customStringID) {
assert((EffectsKind)kind == EffectsKind::Custom);
Attr = new (ctx) EffectsAttr(MF.getIdentifier(customStringID).str());
} else {
Attr = new (ctx) EffectsAttr((EffectsKind)kind);
}
break;
}
case decls_block::OriginallyDefinedIn_DECL_ATTR: {
bool isImplicit;
unsigned Platform;
DEF_VER_TUPLE_PIECES(MovedVer);
// Decode the record, pulling the version tuple information.
serialization::decls_block::OriginallyDefinedInDeclAttrLayout::readRecord(
scratch,
isImplicit,
LIST_VER_TUPLE_PIECES(MovedVer),
Platform);
llvm::VersionTuple MovedVer;
DECODE_VER_TUPLE(MovedVer)
auto ModuleNameEnd = blobData.find('\0');
assert(ModuleNameEnd != StringRef::npos);
auto ModuleName = blobData.slice(0, ModuleNameEnd);
Attr = new (ctx) OriginallyDefinedInAttr(SourceLoc(), SourceRange(),
ModuleName,
(PlatformKind)Platform,
MovedVer,
isImplicit);
break;
}
case decls_block::Available_DECL_ATTR: {
Attr = readAvailable_DECL_ATTR(scratch, blobData);
break;
}
case decls_block::ObjC_DECL_ATTR: {
bool isImplicit;
bool isImplicitName;
bool isSwift3Inferred;
uint64_t numArgs;
ArrayRef<uint64_t> rawPieceIDs;
serialization::decls_block::ObjCDeclAttrLayout::readRecord(
scratch, isImplicit, isSwift3Inferred, isImplicitName, numArgs,
rawPieceIDs);
SmallVector<Identifier, 4> pieces;
for (auto pieceID : rawPieceIDs)
pieces.push_back(MF.getIdentifier(pieceID));
if (numArgs == 0)
Attr = ObjCAttr::create(ctx, None, isImplicitName);
else
Attr = ObjCAttr::create(ctx, ObjCSelector(ctx, numArgs-1, pieces),
isImplicitName);
Attr->setImplicit(isImplicit);
cast<ObjCAttr>(Attr)->setSwift3Inferred(isSwift3Inferred);
break;
}
case decls_block::MainType_DECL_ATTR: {
bool isImplicit;
serialization::decls_block::MainTypeDeclAttrLayout::readRecord(
scratch, isImplicit);
Attr = new (ctx) MainTypeAttr(isImplicit);
break;
}
case decls_block::Specialize_DECL_ATTR: {
unsigned exported;
SpecializeAttr::SpecializationKind specializationKind;
unsigned specializationKindVal;
GenericSignatureID specializedSigID;
ArrayRef<uint64_t> rawPieceIDs;
uint64_t numArgs;
uint64_t numSPIGroups;
uint64_t numAvailabilityAttrs;
DeclID targetFunID;
serialization::decls_block::SpecializeDeclAttrLayout::readRecord(
scratch, exported, specializationKindVal, specializedSigID,
targetFunID, numArgs, numSPIGroups, numAvailabilityAttrs,
rawPieceIDs);
assert(rawPieceIDs.size() == numArgs + numSPIGroups ||
rawPieceIDs.size() == (numArgs - 1 + numSPIGroups));
specializationKind = specializationKindVal
? SpecializeAttr::SpecializationKind::Partial
: SpecializeAttr::SpecializationKind::Full;
// The 'target' parameter.
DeclNameRef replacedFunctionName;
if (numArgs) {
bool numArgumentLabels = (numArgs == 1) ? 0 : numArgs - 2;
auto baseName = MF.getDeclBaseName(rawPieceIDs[0]);
SmallVector<Identifier, 4> pieces;
if (numArgumentLabels) {
for (auto pieceID : rawPieceIDs.slice(1, numArgumentLabels))
pieces.push_back(MF.getIdentifier(pieceID));
}
replacedFunctionName = (numArgs == 1)
? DeclNameRef({baseName}) // simple name
: DeclNameRef({ctx, baseName, pieces});
}
SmallVector<Identifier, 4> spis;
if (numSPIGroups) {
auto numTargetFunctionPiecesToSkip =
(rawPieceIDs.size() == numArgs + numSPIGroups) ? numArgs
: numArgs - 1;
for (auto id : rawPieceIDs.slice(numTargetFunctionPiecesToSkip))
spis.push_back(MF.getIdentifier(id));
}
SmallVector<AvailableAttr *, 4> availabilityAttrs;
while (numAvailabilityAttrs) {
// Prepare to read the next record.
restoreOffset.cancel();
scratch.clear();
// TODO: deserialize them.
BCOffsetRAII restoreOffset2(MF.DeclTypeCursor);
llvm::BitstreamEntry entry =
MF.fatalIfUnexpected(MF.DeclTypeCursor.advance());
if (entry.Kind != llvm::BitstreamEntry::Record) {
// We don't know how to serialize decls represented by sub-blocks.
MF.fatal();
}
unsigned recordID = MF.fatalIfUnexpected(
MF.DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
if (recordID != decls_block::Available_DECL_ATTR) {
MF.fatal();
}
auto attr = readAvailable_DECL_ATTR(scratch, blobData);
availabilityAttrs.push_back(attr);
restoreOffset2.cancel();
--numAvailabilityAttrs;
}
auto specializedSig = MF.getGenericSignature(specializedSigID);
Attr = SpecializeAttr::create(ctx, exported != 0, specializationKind,
spis, availabilityAttrs, specializedSig,
replacedFunctionName, &MF, targetFunID);
break;
}
case decls_block::DynamicReplacement_DECL_ATTR: {
bool isImplicit;
uint64_t numArgs;
ArrayRef<uint64_t> rawPieceIDs;
DeclID replacedFunID;
serialization::decls_block::DynamicReplacementDeclAttrLayout::
readRecord(scratch, isImplicit, replacedFunID, numArgs, rawPieceIDs);
auto baseName = MF.getDeclBaseName(rawPieceIDs[0]);
SmallVector<Identifier, 4> pieces;
for (auto pieceID : rawPieceIDs.slice(1))
pieces.push_back(MF.getIdentifier(pieceID));
assert(numArgs != 0);
assert(!isImplicit && "Need to update for implicit");
Attr = DynamicReplacementAttr::create(
ctx, DeclNameRef({ ctx, baseName, pieces }), &MF, replacedFunID);
break;
}
case decls_block::TypeEraser_DECL_ATTR: {
bool isImplicit;
TypeID typeEraserID;
serialization::decls_block::TypeEraserDeclAttrLayout::readRecord(
scratch, isImplicit, typeEraserID);
assert(!isImplicit);
Attr = TypeEraserAttr::create(ctx, &MF, typeEraserID);
break;
}
case decls_block::Custom_DECL_ATTR: {
bool isImplicit;
bool isArgUnsafe;
TypeID typeID;
serialization::decls_block::CustomDeclAttrLayout::readRecord(
scratch, isImplicit, typeID, isArgUnsafe);
Expected<Type> deserialized = MF.getTypeChecked(typeID);
if (!deserialized) {
if (deserialized.errorIsA<XRefNonLoadedModuleError>() ||
MF.allowCompilerErrors()) {
// A custom attribute defined behind an implementation-only import
// is safe to drop when it can't be deserialized.
// rdar://problem/56599179. When allowing errors we're doing a best
// effort to create a module, so ignore in that case as well.
consumeError(deserialized.takeError());
skipAttr = true;
} else
return deserialized.takeError();
} else if (!deserialized.get() && MF.allowCompilerErrors()) {
// Serialized an invalid attribute, just skip it when allowing errors
skipAttr = true;
} else {
auto *TE = TypeExpr::createImplicit(deserialized.get(), ctx);
auto custom = CustomAttr::create(ctx, SourceLoc(), TE, isImplicit);
custom->setArgIsUnsafe(isArgUnsafe);
Attr = custom;
}
break;
}
case decls_block::ProjectedValueProperty_DECL_ATTR: {
bool isImplicit;
IdentifierID nameID;
serialization::decls_block::ProjectedValuePropertyDeclAttrLayout
::readRecord(scratch, isImplicit, nameID);
auto name = MF.getIdentifier(nameID);
Attr = new (ctx) ProjectedValuePropertyAttr(
name, SourceLoc(), SourceRange(), isImplicit);
break;
}
case decls_block::Differentiable_DECL_ATTR: {
bool isImplicit;
uint64_t rawDiffKind;
GenericSignatureID derivativeGenSigId;
ArrayRef<uint64_t> parameters;
serialization::decls_block::DifferentiableDeclAttrLayout::readRecord(
scratch, isImplicit, rawDiffKind, derivativeGenSigId,
parameters);
auto diffKind = getActualDifferentiabilityKind(rawDiffKind);
if (!diffKind)
MF.fatal();
auto derivativeGenSig = MF.getGenericSignature(derivativeGenSigId);
llvm::SmallBitVector parametersBitVector(parameters.size());
for (unsigned i : indices(parameters))
parametersBitVector[i] = parameters[i];
auto *indices = IndexSubset::get(ctx, parametersBitVector);
auto *diffAttr = DifferentiableAttr::create(
ctx, isImplicit, SourceLoc(), SourceRange(), *diffKind,
/*parsedParameters*/ {}, /*trailingWhereClause*/ nullptr);
// Cache parameter indices so that they can set later.
// `DifferentiableAttr::setParameterIndices` cannot be called here
// because it requires `DifferentiableAttr::setOriginalDeclaration` to
// be called first. `DifferentiableAttr::setOriginalDeclaration` cannot
// be called here because the original declaration is not accessible in
// this function (`DeclDeserializer::deserializeDeclCommon`).
diffAttrParamIndicesMap[diffAttr] = indices;
diffAttr->setDerivativeGenericSignature(derivativeGenSig);
Attr = diffAttr;
break;
}
case decls_block::Derivative_DECL_ATTR: {
bool isImplicit;
uint64_t origNameId;
bool hasAccessorKind;
uint64_t rawAccessorKind;
DeclID origDeclId;
uint64_t rawDerivativeKind;
ArrayRef<uint64_t> parameters;
serialization::decls_block::DerivativeDeclAttrLayout::readRecord(
scratch, isImplicit, origNameId, hasAccessorKind, rawAccessorKind,
origDeclId, rawDerivativeKind, parameters);
Optional<AccessorKind> accessorKind = None;
if (hasAccessorKind) {
auto maybeAccessorKind = getActualAccessorKind(rawAccessorKind);
if (!maybeAccessorKind)
MF.fatal();
accessorKind = *maybeAccessorKind;
}
DeclNameRefWithLoc origName{DeclNameRef(MF.getDeclBaseName(origNameId)),
DeclNameLoc(), accessorKind};
auto derivativeKind =
getActualAutoDiffDerivativeFunctionKind(rawDerivativeKind);
if (!derivativeKind)
MF.fatal();
llvm::SmallBitVector parametersBitVector(parameters.size());
for (unsigned i : indices(parameters))
parametersBitVector[i] = parameters[i];
auto *indices = IndexSubset::get(ctx, parametersBitVector);
auto *derivativeAttr =
DerivativeAttr::create(ctx, isImplicit, SourceLoc(), SourceRange(),
/*baseType*/ nullptr, origName, indices);
derivativeAttr->setOriginalFunctionResolver(&MF, origDeclId);
derivativeAttr->setDerivativeKind(*derivativeKind);
Attr = derivativeAttr;
break;
}
case decls_block::Transpose_DECL_ATTR: {
bool isImplicit;
uint64_t origNameId;
DeclID origDeclId;
ArrayRef<uint64_t> parameters;
serialization::decls_block::TransposeDeclAttrLayout::readRecord(
scratch, isImplicit, origNameId, origDeclId, parameters);
DeclNameRefWithLoc origName{
DeclNameRef(MF.getDeclBaseName(origNameId)), DeclNameLoc(), None};
auto *origDecl = cast<AbstractFunctionDecl>(MF.getDecl(origDeclId));
llvm::SmallBitVector parametersBitVector(parameters.size());
for (unsigned i : indices(parameters))
parametersBitVector[i] = parameters[i];
auto *indices = IndexSubset::get(ctx, parametersBitVector);
auto *transposeAttr =
TransposeAttr::create(ctx, isImplicit, SourceLoc(), SourceRange(),
/*baseTypeRepr*/ nullptr, origName, indices);
transposeAttr->setOriginalFunction(origDecl);
Attr = transposeAttr;
break;
}
case decls_block::SPIAccessControl_DECL_ATTR: {
ArrayRef<uint64_t> spiIds;
serialization::decls_block::SPIAccessControlDeclAttrLayout::readRecord(
scratch, spiIds);
SmallVector<Identifier, 4> spis;
for (auto id : spiIds)
spis.push_back(MF.getIdentifier(id));
Attr = SPIAccessControlAttr::create(ctx, SourceLoc(),
SourceRange(), spis);
break;
}
case decls_block::UnavailableFromAsync_DECL_ATTR: {
bool isImplicit;
serialization::decls_block::UnavailableFromAsyncDeclAttrLayout::
readRecord(scratch, isImplicit);
Attr = new (ctx) UnavailableFromAsyncAttr(blobData, isImplicit);
break;
}
#define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \
case decls_block::CLASS##_DECL_ATTR: { \
bool isImplicit; \
serialization::decls_block::CLASS##DeclAttrLayout::readRecord( \
scratch, isImplicit); \
Attr = new (ctx) CLASS##Attr(isImplicit); \
break; \
}
#include "swift/AST/Attr.def"
default:
// We don't know how to deserialize this kind of attribute.
MF.fatal();
}
if (!skipAttr) {
if (!Attr)
return llvm::Error::success();
AddAttribute(Attr);
}
} else if (recordID == decls_block::PRIVATE_DISCRIMINATOR) {
IdentifierID discriminatorID;
decls_block::PrivateDiscriminatorLayout::readRecord(scratch,
discriminatorID);
privateDiscriminator = MF.getIdentifier(discriminatorID);
} else if (recordID == decls_block::LOCAL_DISCRIMINATOR) {
unsigned discriminator;
decls_block::LocalDiscriminatorLayout::readRecord(scratch, discriminator);
localDiscriminator = discriminator;
} else if (recordID == decls_block::FILENAME_FOR_PRIVATE) {
IdentifierID filenameID;
decls_block::FilenameForPrivateLayout::readRecord(scratch, filenameID);
filenameForPrivate = MF.getIdentifierText(filenameID);
} else {
return llvm::Error::success();
}
// Prepare to read the next record.
restoreOffset.cancel();
scratch.clear();
}
}