//===--- Deserialization.cpp - Loading a serialized AST -------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 "DeserializationErrors.h" #include "swift/Serialization/ModuleFile.h" #include "swift/Serialization/ModuleFormat.h" #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/ForeignErrorConvention.h" #include "swift/AST/GenericEnvironment.h" #include "swift/AST/Initializer.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/ProtocolConformance.h" #include "swift/ClangImporter/ClangImporter.h" #include "swift/Parse/Parser.h" #include "swift/Serialization/BCReadingExtras.h" #include "swift/Serialization/SerializedModuleLoader.h" #include "swift/Basic/Defer.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "Serialization" STATISTIC(NumDeclsLoaded, "# of decls deserialized"); STATISTIC(NumMemberListsLoaded, "# of nominals/extensions whose members were loaded"); STATISTIC(NumNestedTypeShortcuts, "# of same-module nested types resolved without lookup"); using namespace swift; using namespace swift::serialization; using llvm::Expected; StringRef swift::getNameOfModule(const ModuleFile *MF) { return MF->Name; } namespace { struct IDAndKind { const Decl *D; DeclID ID; }; static raw_ostream &operator<<(raw_ostream &os, IDAndKind &&pair) { return os << Decl::getKindName(pair.D->getKind()) << "Decl #" << pair.ID; } class PrettyDeclDeserialization : public llvm::PrettyStackTraceEntry { const ModuleFile *MF; const ModuleFile::Serialized &DeclOrOffset; DeclID ID; decls_block::RecordKind Kind; public: PrettyDeclDeserialization(ModuleFile *module, const ModuleFile::Serialized &declOrOffset, DeclID DID, decls_block::RecordKind kind) : MF(module), 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 "swift/Serialization/DeclTypeRecordNodes.def" } llvm_unreachable("Unhandled RecordKind in switch."); } void print(raw_ostream &os) const override { if (!DeclOrOffset.isComplete()) { os << "While deserializing decl #" << ID << " (" << getRecordKindString(Kind) << ")"; } else { os << "While deserializing "; if (auto VD = dyn_cast(DeclOrOffset.get())) { os << "'" << VD->getName() << "' (" << IDAndKind{VD, ID} << ")"; } else if (auto ED = dyn_cast(DeclOrOffset.get())) { os << "extension of '" << ED->getExtendedType() << "' (" << IDAndKind{ED, ID} << ")"; } else { os << IDAndKind{DeclOrOffset.get(), ID}; } } os << " in '" << getNameOfModule(MF) << "'\n"; } }; class PrettyXRefTrace : public llvm::PrettyStackTraceEntry, public XRefTracePath { public: explicit PrettyXRefTrace(ModuleDecl &M) : XRefTracePath(M) {} void print(raw_ostream &os) const override { XRefTracePath::print(os, "\t"); } }; class PrettyStackTraceModuleFile : public llvm::PrettyStackTraceEntry { const char *Action; const ModuleFile *MF; public: explicit PrettyStackTraceModuleFile(const char *action, ModuleFile *module) : Action(action), MF(module) {} void print(raw_ostream &os) const override { os << Action << " \'" << getNameOfModule(MF) << "'\n"; } }; } // end anonymous namespace const char DeclDeserializationError::ID = '\0'; void DeclDeserializationError::anchor() {} const char XRefError::ID = '\0'; void XRefError::anchor() {} const char OverrideError::ID = '\0'; void OverrideError::anchor() {} const char TypeError::ID = '\0'; void TypeError::anchor() {} LLVM_NODISCARD static std::unique_ptr takeErrorInfo(llvm::Error error) { std::unique_ptr result; llvm::handleAllErrors(std::move(error), [&](std::unique_ptr info) { result = std::move(info); }); return result; } /// Skips a single record in the bitstream. /// /// Returns true if the next entry is a record of type \p recordKind. /// Destroys the stream position if the next entry is not a record. static void skipRecord(llvm::BitstreamCursor &cursor, unsigned recordKind) { auto next = cursor.advance(AF_DontPopBlockAtEnd); assert(next.Kind == llvm::BitstreamEntry::Record); #if NDEBUG cursor.skipRecord(next.ID); #else SmallVector scratch; StringRef blobData; unsigned kind = cursor.readRecord(next.ID, scratch, &blobData); assert(kind == recordKind); #endif } void ModuleFile::fatal(llvm::Error error) { if (FileContext) { getContext().Diags.diagnose(SourceLoc(), diag::serialization_fatal, Name); if (!CompatibilityVersion.empty()) { SmallString<16> buffer; llvm::raw_svector_ostream out(buffer); out << getContext().LangOpts.EffectiveLanguageVersion; if (out.str() != CompatibilityVersion) { getContext().Diags.diagnose( SourceLoc(), diag::serialization_compatibility_version_mismatch, out.str(), Name, CompatibilityVersion); } } } logAllUnhandledErrors(std::move(error), llvm::errs(), "\n*** DESERIALIZATION FAILURE (please include this " "section in any bug report) ***\n"); abort(); } ModuleFile &ModuleFile::getModuleFileForDelayedActions() { assert(FileContext && "cannot delay actions before associating with a file"); ModuleDecl *associatedModule = getAssociatedModule(); // Check for the common case. if (associatedModule->getFiles().size() == 1) return *this; for (FileUnit *file : associatedModule->getFiles()) if (auto *serialized = dyn_cast(file)) return serialized->File; llvm_unreachable("should always have FileContext in the list of files"); } void ModuleFile::finishPendingActions() { assert(&getModuleFileForDelayedActions() == this && "wrong module used for delayed actions"); while (!DelayedGenericEnvironments.empty()) { // Force completion of the last generic environment. auto genericEnvDC = DelayedGenericEnvironments.back(); DelayedGenericEnvironments.pop_back(); (void)genericEnvDC->getGenericEnvironmentOfContext(); } } /// Translate from the serialization DefaultArgumentKind enumerators, which are /// guaranteed to be stable, to the AST ones. static Optional getActualDefaultArgKind(uint8_t raw) { switch (static_cast(raw)) { case serialization::DefaultArgumentKind::None: return swift::DefaultArgumentKind::None; case serialization::DefaultArgumentKind::Normal: return swift::DefaultArgumentKind::Normal; case serialization::DefaultArgumentKind::Inherited: return swift::DefaultArgumentKind::Inherited; case serialization::DefaultArgumentKind::Column: return swift::DefaultArgumentKind::Column; case serialization::DefaultArgumentKind::File: return swift::DefaultArgumentKind::File; case serialization::DefaultArgumentKind::Line: return swift::DefaultArgumentKind::Line; case serialization::DefaultArgumentKind::Function: return swift::DefaultArgumentKind::Function; case serialization::DefaultArgumentKind::DSOHandle: return swift::DefaultArgumentKind::DSOHandle; case serialization::DefaultArgumentKind::Nil: return swift::DefaultArgumentKind::Nil; case serialization::DefaultArgumentKind::EmptyArray: return swift::DefaultArgumentKind::EmptyArray; case serialization::DefaultArgumentKind::EmptyDictionary: return swift::DefaultArgumentKind::EmptyDictionary; } return None; } ParameterList *ModuleFile::readParameterList() { using namespace decls_block; SmallVector scratch; auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch); assert(recordID == PARAMETERLIST); (void) recordID; unsigned numParams; decls_block::ParameterListLayout::readRecord(scratch, numParams); SmallVector params; for (unsigned i = 0; i != numParams; ++i) { scratch.clear(); auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch); assert(recordID == PARAMETERLIST_ELT); (void) recordID; DeclID paramID; bool isVariadic; uint8_t rawDefaultArg; decls_block::ParameterListEltLayout::readRecord(scratch, paramID, isVariadic, rawDefaultArg); auto decl = cast(getDecl(paramID)); decl->setVariadic(isVariadic); // Decode the default argument kind. // FIXME: Default argument expression, if available. if (auto defaultArg = getActualDefaultArgKind(rawDefaultArg)) decl->setDefaultArgumentKind(*defaultArg); params.push_back(decl); } return ParameterList::create(getContext(), params); } Expected ModuleFile::readPattern(DeclContext *owningDC) { // Currently, the only case in which this function can fail (return an error) // is when reading a pattern for a single variable declaration. using namespace decls_block; auto readPatternUnchecked = [this](DeclContext *owningDC) -> Pattern * { Expected deserialized = readPattern(owningDC); if (!deserialized) { fatal(deserialized.takeError()); } assert(deserialized.get()); return deserialized.get(); }; SmallVector scratch; BCOffsetRAII restoreOffset(DeclTypeCursor); auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (next.Kind != llvm::BitstreamEntry::Record) { error(); return nullptr; } /// Local function to record the type of this pattern. auto recordPatternType = [&](Pattern *pattern, Type type) { if (type->hasTypeParameter()) pattern->setDelayedInterfaceType(type, owningDC); else pattern->setType(type); }; unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch); switch (kind) { case decls_block::PAREN_PATTERN: { bool isImplicit; ParenPatternLayout::readRecord(scratch, isImplicit); Pattern *subPattern = readPatternUnchecked(owningDC); auto result = new (getContext()) ParenPattern(SourceLoc(), subPattern, SourceLoc(), isImplicit); if (Type interfaceType = subPattern->getDelayedInterfaceType()) result->setDelayedInterfaceType(ParenType::get(getContext(), interfaceType), owningDC); else result->setType(ParenType::get(getContext(), subPattern->getType())); restoreOffset.reset(); return result; } case decls_block::TUPLE_PATTERN: { TypeID tupleTypeID; unsigned count; bool isImplicit; TuplePatternLayout::readRecord(scratch, tupleTypeID, count, isImplicit); SmallVector elements; for ( ; count > 0; --count) { scratch.clear(); next = DeclTypeCursor.advance(); assert(next.Kind == llvm::BitstreamEntry::Record); kind = DeclTypeCursor.readRecord(next.ID, scratch); assert(kind == decls_block::TUPLE_PATTERN_ELT); // FIXME: Add something for this record or remove it. IdentifierID labelID; TuplePatternEltLayout::readRecord(scratch, labelID); Identifier label = getIdentifier(labelID); Pattern *subPattern = readPatternUnchecked(owningDC); elements.push_back(TuplePatternElt(label, SourceLoc(), subPattern)); } auto result = TuplePattern::create(getContext(), SourceLoc(), elements, SourceLoc(), isImplicit); recordPatternType(result, getType(tupleTypeID)); restoreOffset.reset(); return result; } case decls_block::NAMED_PATTERN: { DeclID varID; TypeID typeID; bool isImplicit; NamedPatternLayout::readRecord(scratch, varID, typeID, isImplicit); auto deserialized = getDeclChecked(varID); if (!deserialized) { // Pass through the error. It's too bad that it affects the whole pattern, // but that's what we get. return deserialized.takeError(); } auto var = cast(deserialized.get()); auto result = new (getContext()) NamedPattern(var, isImplicit); recordPatternType(result, getType(typeID)); restoreOffset.reset(); return result; } case decls_block::ANY_PATTERN: { TypeID typeID; bool isImplicit; AnyPatternLayout::readRecord(scratch, typeID, isImplicit); auto result = new (getContext()) AnyPattern(SourceLoc(), isImplicit); recordPatternType(result, getType(typeID)); restoreOffset.reset(); return result; } case decls_block::TYPED_PATTERN: { TypeID typeID; bool isImplicit; TypedPatternLayout::readRecord(scratch, typeID, isImplicit); Expected subPattern = readPattern(owningDC); if (!subPattern) { // Pass through any errors. return subPattern; } auto result = new (getContext()) TypedPattern(subPattern.get(), TypeLoc(), isImplicit); recordPatternType(result, getType(typeID)); restoreOffset.reset(); return result; } case decls_block::VAR_PATTERN: { bool isImplicit, isLet; VarPatternLayout::readRecord(scratch, isLet, isImplicit); Pattern *subPattern = readPatternUnchecked(owningDC); auto result = new (getContext()) VarPattern(SourceLoc(), isLet, subPattern, isImplicit); if (Type interfaceType = subPattern->getDelayedInterfaceType()) result->setDelayedInterfaceType(interfaceType, owningDC); else result->setType(subPattern->getType()); restoreOffset.reset(); return result; } default: return nullptr; } } SILLayout *ModuleFile::readSILLayout(llvm::BitstreamCursor &Cursor) { using namespace decls_block; SmallVector scratch; auto next = Cursor.advance(AF_DontPopBlockAtEnd); assert(next.Kind == llvm::BitstreamEntry::Record); unsigned kind = Cursor.readRecord(next.ID, scratch); switch (kind) { case decls_block::SIL_LAYOUT: { unsigned numFields; ArrayRef types; decls_block::SILLayoutLayout::readRecord(scratch, numFields, types); SmallVector fields; for (auto fieldInfo : types.slice(0, numFields)) { bool isMutable = fieldInfo & 0x80000000U; auto typeId = fieldInfo & 0x7FFFFFFFU; fields.push_back( SILField(getType(typeId)->getCanonicalType(), isMutable)); } SmallVector genericParams; for (auto typeId : types.slice(numFields)) { auto type = getType(typeId)->castTo(); genericParams.push_back(type); } SmallVector requirements; readGenericRequirements(requirements, DeclTypeCursor); CanGenericSignature sig; if (!genericParams.empty() || !requirements.empty()) { sig = GenericSignature::get(genericParams, requirements) ->getCanonicalSignature(); } return SILLayout::get(getContext(), sig, fields); } default: error(); return nullptr; } } ProtocolConformanceRef ModuleFile::readConformance( llvm::BitstreamCursor &Cursor, GenericEnvironment *genericEnv) { using namespace decls_block; SmallVector scratch; auto next = Cursor.advance(AF_DontPopBlockAtEnd); assert(next.Kind == llvm::BitstreamEntry::Record); unsigned kind = Cursor.readRecord(next.ID, scratch); switch (kind) { case ABSTRACT_PROTOCOL_CONFORMANCE: { DeclID protoID; AbstractProtocolConformanceLayout::readRecord(scratch, protoID); auto proto = cast(getDecl(protoID)); return ProtocolConformanceRef(proto); } case SPECIALIZED_PROTOCOL_CONFORMANCE: { TypeID conformingTypeID; unsigned numSubstitutions; SpecializedProtocolConformanceLayout::readRecord(scratch, conformingTypeID, numSubstitutions); ASTContext &ctx = getContext(); Type conformingType = getType(conformingTypeID); if (genericEnv) { conformingType = genericEnv->mapTypeIntoContext(conformingType); } PrettyStackTraceType trace(getAssociatedModule()->getASTContext(), "reading specialized conformance for", conformingType); // Read the substitutions. SmallVector substitutions; while (numSubstitutions--) { auto sub = maybeReadSubstitution(Cursor, genericEnv); assert(sub.hasValue() && "Missing substitution?"); substitutions.push_back(*sub); } ProtocolConformanceRef genericConformance = readConformance(Cursor, genericEnv); PrettyStackTraceDecl traceTo("... to", genericConformance.getRequirement()); assert(genericConformance.isConcrete() && "Abstract generic conformance?"); auto conformance = ctx.getSpecializedConformance(conformingType, genericConformance.getConcrete(), substitutions); return ProtocolConformanceRef(conformance); } case INHERITED_PROTOCOL_CONFORMANCE: { TypeID conformingTypeID; InheritedProtocolConformanceLayout::readRecord(scratch, conformingTypeID); ASTContext &ctx = getContext(); Type conformingType = getType(conformingTypeID); if (genericEnv) { conformingType = genericEnv->mapTypeIntoContext(conformingType); } PrettyStackTraceType trace(getAssociatedModule()->getASTContext(), "reading inherited conformance for", conformingType); ProtocolConformanceRef inheritedConformance = readConformance(Cursor, genericEnv); PrettyStackTraceDecl traceTo("... to", inheritedConformance.getRequirement()); assert(inheritedConformance.isConcrete() && "Abstract inherited conformance?"); auto conformance = ctx.getInheritedConformance(conformingType, inheritedConformance.getConcrete()); return ProtocolConformanceRef(conformance); } case NORMAL_PROTOCOL_CONFORMANCE_ID: { NormalConformanceID conformanceID; NormalProtocolConformanceIdLayout::readRecord(scratch, conformanceID); return ProtocolConformanceRef(readNormalConformance(conformanceID)); } case PROTOCOL_CONFORMANCE_XREF: { DeclID protoID; DeclID nominalID; ModuleID moduleID; ProtocolConformanceXrefLayout::readRecord(scratch, protoID, nominalID, moduleID); auto nominal = cast(getDecl(nominalID)); PrettyStackTraceDecl trace("cross-referencing conformance for", nominal); auto proto = cast(getDecl(protoID)); PrettyStackTraceDecl traceTo("... to", proto); auto module = getModule(moduleID); SmallVector conformances; nominal->lookupConformance(module, proto, conformances); PrettyStackTraceModuleFile traceMsg( "If you're seeing a crash here, check that your SDK and dependencies " "are at least as new as the versions used to build", this); // This would normally be an assertion but it's more useful to print the // PrettyStackTrace here even in no-asserts builds. if (conformances.empty()) abort(); return ProtocolConformanceRef(conformances.front()); } // Not a protocol conformance. default: error(); ProtocolConformance *conformance = nullptr; return ProtocolConformanceRef(conformance); // FIXME: this will assert } } NormalProtocolConformance *ModuleFile::readNormalConformance( NormalConformanceID conformanceID) { auto &conformanceEntry = NormalConformances[conformanceID-1]; if (conformanceEntry.isComplete()) { return conformanceEntry.get(); } using namespace decls_block; // Find the conformance record. BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(conformanceEntry); auto entry = DeclTypeCursor.advance(); if (entry.Kind != llvm::BitstreamEntry::Record) { error(); return nullptr; } DeclID protoID; DeclContextID contextID; unsigned valueCount, typeCount; ArrayRef rawIDs; SmallVector scratch; unsigned kind = DeclTypeCursor.readRecord(entry.ID, scratch); if (kind != NORMAL_PROTOCOL_CONFORMANCE) { error(); return nullptr; } NormalProtocolConformanceLayout::readRecord(scratch, protoID, contextID, valueCount, typeCount, rawIDs); ASTContext &ctx = getContext(); DeclContext *dc = getDeclContext(contextID); Type conformingType = dc->getDeclaredTypeInContext(); PrettyStackTraceType trace(ctx, "reading conformance for", conformingType); auto proto = cast(getDecl(protoID)); PrettyStackTraceDecl traceTo("... to", proto); auto conformance = ctx.getConformance(conformingType, proto, SourceLoc(), dc, ProtocolConformanceState::Incomplete); // Record this conformance. if (conformanceEntry.isComplete()) return conformance; uint64_t offset = conformanceEntry; conformanceEntry = conformance; dc->getAsNominalTypeOrNominalTypeExtensionContext() ->registerProtocolConformance(conformance); // Read requirement signature conformances. SmallVector reqConformances; for (auto req : proto->getRequirementSignature()->getRequirements()) { if (req.getKind() == RequirementKind::Conformance) { auto reqConformance = readConformance(DeclTypeCursor); reqConformances.push_back(reqConformance); } } conformance->setSignatureConformances(reqConformances); // If the conformance is complete, we're done. if (conformance->isComplete()) return conformance; conformance->setState(ProtocolConformanceState::Complete); conformance->setLazyLoader(this, offset); return conformance; } Optional ModuleFile::maybeReadSubstitution(llvm::BitstreamCursor &cursor, GenericEnvironment *genericEnv) { BCOffsetRAII lastRecordOffset(cursor); auto entry = cursor.advance(AF_DontPopBlockAtEnd); if (entry.Kind != llvm::BitstreamEntry::Record) return None; StringRef blobData; SmallVector scratch; unsigned recordID = cursor.readRecord(entry.ID, scratch, &blobData); if (recordID != decls_block::BOUND_GENERIC_SUBSTITUTION) return None; TypeID replacementID; unsigned numConformances; decls_block::BoundGenericSubstitutionLayout::readRecord(scratch, replacementID, numConformances); auto replacementTy = getType(replacementID); if (genericEnv) { replacementTy = genericEnv->mapTypeIntoContext(replacementTy); } SmallVector conformanceBuf; while (numConformances--) { conformanceBuf.push_back(readConformance(cursor)); } lastRecordOffset.reset(); return Substitution{replacementTy, getContext().AllocateCopy(conformanceBuf)}; } GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC, GenericParamList *outerParams) { using namespace decls_block; assert(DC && "need a context for the decls in the list"); BCOffsetRAII lastRecordOffset(DeclTypeCursor); SmallVector scratch; StringRef blobData; auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (next.Kind != llvm::BitstreamEntry::Record) return nullptr; unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch, &blobData); if (kind != GENERIC_PARAM_LIST) return nullptr; SmallVector params; while (true) { lastRecordOffset.reset(); bool shouldContinue = true; auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (entry.Kind != llvm::BitstreamEntry::Record) break; scratch.clear(); unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); switch (recordID) { case GENERIC_PARAM: { DeclID paramDeclID; GenericParamLayout::readRecord(scratch, paramDeclID); auto genericParam = cast(getDecl(paramDeclID, DC)); // FIXME: There are unfortunate inconsistencies in the treatment of // generic param decls. Currently the first request for context wins // because we don't want to change context on-the-fly. // Here are typical scenarios: // (1) AST reads decl, get's scope. // Later, readSILFunction tries to force module scope. // (2) readSILFunction forces module scope. // Later, readVTable requests an enclosing scope. // ...other combinations are possible, but as long as AST lookups // precede SIL linkage, we should be ok. assert((genericParam->getDeclContext()->isModuleScopeContext() || DC->isModuleScopeContext() || genericParam->getDeclContext() == DC) && "Mismatched decl context for generic types."); params.push_back(genericParam); break; } default: // This record is not part of the GenericParamList. shouldContinue = false; break; } if (!shouldContinue) break; } auto paramList = GenericParamList::create(getContext(), SourceLoc(), params, SourceLoc(), { }, SourceLoc()); paramList->setOuterParameters(outerParams ? outerParams : DC->getGenericParamsOfContext()); return paramList; } void ModuleFile::readGenericRequirements( SmallVectorImpl &requirements, llvm::BitstreamCursor &Cursor) { using namespace decls_block; BCOffsetRAII lastRecordOffset(Cursor); SmallVector scratch; StringRef blobData; while (true) { lastRecordOffset.reset(); bool shouldContinue = true; auto entry = Cursor.advance(AF_DontPopBlockAtEnd); if (entry.Kind != llvm::BitstreamEntry::Record) break; scratch.clear(); unsigned recordID = Cursor.readRecord(entry.ID, scratch, &blobData); switch (recordID) { case GENERIC_REQUIREMENT: { uint8_t rawKind; uint64_t rawTypeIDs[2]; GenericRequirementLayout::readRecord(scratch, rawKind, rawTypeIDs[0], rawTypeIDs[1]); switch (rawKind) { case GenericRequirementKind::Conformance: { auto subject = getType(rawTypeIDs[0]); auto constraint = getType(rawTypeIDs[1]); requirements.push_back(Requirement(RequirementKind::Conformance, subject, constraint)); break; } case GenericRequirementKind::Superclass: { auto subject = getType(rawTypeIDs[0]); auto constraint = getType(rawTypeIDs[1]); requirements.push_back(Requirement(RequirementKind::Superclass, subject, constraint)); break; } case GenericRequirementKind::SameType: { auto first = getType(rawTypeIDs[0]); auto second = getType(rawTypeIDs[1]); requirements.push_back(Requirement(RequirementKind::SameType, first, second)); break; } default: // Unknown requirement kind. Drop the requirement and continue, but log // an error so that we don't actually try to generate code. error(); } break; } case LAYOUT_REQUIREMENT: { uint8_t rawKind; uint64_t rawTypeID; uint32_t size; uint32_t alignment; LayoutRequirementLayout::readRecord(scratch, rawKind, rawTypeID, size, alignment); auto first = getType(rawTypeID); LayoutConstraint layout; LayoutConstraintKind kind = LayoutConstraintKind::UnknownLayout; switch (rawKind) { default: { // Unknown layout requirement kind. error(); break; } case LayoutRequirementKind::NativeRefCountedObject: kind = LayoutConstraintKind::NativeRefCountedObject; break; case LayoutRequirementKind::RefCountedObject: kind = LayoutConstraintKind::RefCountedObject; break; case LayoutRequirementKind::Trivial: kind = LayoutConstraintKind::Trivial; break; case LayoutRequirementKind::TrivialOfExactSize: kind = LayoutConstraintKind::TrivialOfExactSize; break; case LayoutRequirementKind::TrivialOfAtMostSize: kind = LayoutConstraintKind::TrivialOfAtMostSize; break; case LayoutRequirementKind::Class: kind = LayoutConstraintKind::Class; break; case LayoutRequirementKind::NativeClass: kind = LayoutConstraintKind::NativeClass; break; case LayoutRequirementKind::UnknownLayout: kind = LayoutConstraintKind::UnknownLayout; break; } ASTContext &ctx = getContext(); if (kind != LayoutConstraintKind::TrivialOfAtMostSize && kind != LayoutConstraintKind::TrivialOfExactSize) layout = LayoutConstraint::getLayoutConstraint(kind, ctx); else layout = LayoutConstraint::getLayoutConstraint(kind, size, alignment, ctx); requirements.push_back( Requirement(RequirementKind::Layout, first, layout)); break; } default: // This record is not part of the GenericParamList. shouldContinue = false; break; } if (!shouldContinue) break; } } void ModuleFile::configureGenericEnvironment( GenericContext *genericDecl, serialization::GenericEnvironmentID envID) { if (envID == 0) return; auto sigOrEnv = getGenericSignatureOrEnvironment(envID); // If we just have a generic signature, set up lazy generic environment // creation. if (auto genericSig = sigOrEnv.dyn_cast()) { genericDecl->setLazyGenericEnvironment(this, genericSig, envID); ModuleFile &delayedActionFile = getModuleFileForDelayedActions(); delayedActionFile.DelayedGenericEnvironments.push_back(genericDecl); return; } // If we have a full generic environment, it's because it happened to be // deserialized already. Record it directly. if (auto genericEnv = sigOrEnv.dyn_cast()) { genericDecl->setGenericEnvironment(genericEnv); return; } } llvm::PointerUnion ModuleFile::getGenericSignatureOrEnvironment( serialization::GenericEnvironmentID ID, bool wantEnvironment) { // The empty result with the type the caller expects. llvm::PointerUnion result; if (wantEnvironment) result = static_cast(nullptr); // Zero is a sentinel for having no generic environment. if (ID == 0) return result; assert(ID <= GenericEnvironments.size() && "invalid GenericEnvironment ID"); auto &envOrOffset = GenericEnvironments[ID-1]; // If we've already deserialized this generic environment, return it. if (envOrOffset.isComplete()) { return envOrOffset.get(); } // Read the generic environment. BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(envOrOffset); DeserializingEntityRAII deserializingEntity(*this); SmallVector paramTypes; { using namespace decls_block; StringRef blobData; SmallVector scratch; // we only want to be tracking the offset for this part of the function, // since loading the generic signature (a) may read the record we reject, // and (b) shouldn't have its progress erased. (That function also does its // own internal tracking.) BCOffsetRAII lastRecordOffset(DeclTypeCursor); auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (entry.Kind != llvm::BitstreamEntry::Record) return result; unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); switch (recordID) { case GENERIC_ENVIRONMENT: { lastRecordOffset.reset(); ArrayRef rawParamIDs; GenericEnvironmentLayout::readRecord(scratch, rawParamIDs); for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) { auto paramTy = getType(rawParamIDs[i])->castTo(); paramTypes.push_back(paramTy); } break; } case SIL_GENERIC_ENVIRONMENT: { ArrayRef rawParamIDs; SILGenericEnvironmentLayout::readRecord(scratch, rawParamIDs); lastRecordOffset.reset(); if (rawParamIDs.size() % 2 != 0) { error(); return result; } for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) { Identifier name = getIdentifier(rawParamIDs[i]); auto paramTy = getType(rawParamIDs[i+1])->castTo(); if (!name.empty()) { auto paramDecl = createDecl(getAssociatedModule(), name, SourceLoc(), paramTy->getDepth(), paramTy->getIndex()); paramTy = paramDecl->getDeclaredInterfaceType() ->castTo(); } paramTypes.push_back(paramTy); } break; } default: error(); return result; } } // If there are no parameters, the environment is empty. if (paramTypes.empty()) { if (wantEnvironment) envOrOffset = nullptr; return result; } // Read the generic requirements. SmallVector requirements; readGenericRequirements(requirements, DeclTypeCursor); // Construct the generic signature from the loaded parameters and // requirements. auto signature = GenericSignature::get(paramTypes, requirements); // If we only want the signature, return it now. if (!wantEnvironment) return signature; // If we've already deserialized this generic environment, return it. if (envOrOffset.isComplete()) { return envOrOffset.get(); } // Form the generic environment. Record it now so that deserialization of // the archetypes in the environment can refer to this environment. auto genericEnv = signature->createGenericEnvironment(*getAssociatedModule()); envOrOffset = genericEnv; return genericEnv; } GenericEnvironment *ModuleFile::getGenericEnvironment( serialization::GenericEnvironmentID ID) { return getGenericSignatureOrEnvironment(ID, /*wantEnvironment=*/true) .get(); ; } bool ModuleFile::readDefaultWitnessTable(ProtocolDecl *proto) { using namespace decls_block; auto entry = DeclTypeCursor.advance(); if (entry.Kind != llvm::BitstreamEntry::Record) return true; SmallVector witnessIDBuffer; unsigned kind = DeclTypeCursor.readRecord(entry.ID, witnessIDBuffer); assert(kind == DEFAULT_WITNESS_TABLE); (void)kind; ArrayRef rawWitnessIDs; decls_block::DefaultWitnessTableLayout::readRecord( witnessIDBuffer, rawWitnessIDs); if (rawWitnessIDs.empty()) return false; unsigned e = rawWitnessIDs.size(); assert(e % 2 == 0 && "malformed default witness table"); (void) e; for (unsigned i = 0, e = rawWitnessIDs.size(); i < e; i += 2) { ValueDecl *requirement = cast(getDecl(rawWitnessIDs[i])); assert(requirement && "unable to deserialize next requirement"); ValueDecl *witness = cast(getDecl(rawWitnessIDs[i + 1])); assert(witness && "unable to deserialize next witness"); assert(requirement->getDeclContext() == proto); proto->setDefaultWitness(requirement, witness); } return false; } static Optional getActualCtorInitializerKind(uint8_t raw) { switch (serialization::CtorInitializerKind(raw)) { #define CASE(NAME) \ case serialization::CtorInitializerKind::NAME: \ return swift::CtorInitializerKind::NAME; CASE(Designated) CASE(Convenience) CASE(Factory) CASE(ConvenienceFactory) #undef CASE } return None; } /// Remove values from \p values that don't match the expected type or module. /// /// Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be /// omitted, in which case any type or module is accepted. Values imported /// from Clang can also appear in any module. static void filterValues(Type expectedTy, ModuleDecl *expectedModule, CanGenericSignature expectedGenericSig, bool isType, bool inProtocolExt, bool isStatic, Optional ctorInit, SmallVectorImpl &values) { CanType canTy; if (expectedTy) canTy = expectedTy->getCanonicalType(); auto newEnd = std::remove_if(values.begin(), values.end(), [=](ValueDecl *value) { if (isType != isa(value)) return true; if (!value->hasInterfaceType()) return true; if (canTy && value->getInterfaceType()->getCanonicalType() != canTy) return true; if (value->isStatic() != isStatic) return true; // FIXME: Should be able to move a value from an extension in a derived // module to the original definition in a base module. if (expectedModule && !value->hasClangNode() && value->getModuleContext() != expectedModule) return true; // If we're expecting a member within a constrained extension with a // particular generic signature, match that signature. if (expectedGenericSig && value->getDeclContext()->getGenericSignatureOfContext() ->getCanonicalSignature() != expectedGenericSig) return true; // If we don't expect a specific generic signature, ignore anything from a // constrained extension. if (!expectedGenericSig && isa(value->getDeclContext()) && cast(value->getDeclContext())->isConstrainedExtension()) return true; // If we're looking at members of a protocol or protocol extension, // filter by whether we expect to find something in a protocol extension or // not. This lets us distinguish between a protocol member and a protocol // extension member that have the same type. if (value->getDeclContext()->getAsProtocolOrProtocolExtensionContext() && (bool)value->getDeclContext()->getAsProtocolExtensionContext() != inProtocolExt) return true; // If we're expecting an initializer with a specific kind, and this is not // an initializer with that kind, remove it. if (ctorInit) { if (!isa(value) || cast(value)->getInitKind() != *ctorInit) return true; } return false; }); values.erase(newEnd, values.end()); } Expected ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) { using namespace decls_block; assert(baseModule && "missing dependency"); PrettyXRefTrace pathTrace(*baseModule); auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (entry.Kind != llvm::BitstreamEntry::Record) { error(); return nullptr; } SmallVector values; SmallVector scratch; StringRef blobData; // Read the first path piece. This one is special because lookup is performed // against the base module, rather than against the previous link in the path. // In particular, operator path pieces represent actual operators here, but // filters on operator functions when they appear later on. scratch.clear(); unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); switch (recordID) { case XREF_TYPE_PATH_PIECE: case XREF_VALUE_PATH_PIECE: { IdentifierID IID; TypeID TID = 0; bool isType = (recordID == XREF_TYPE_PATH_PIECE); bool inProtocolExt = false; bool isStatic = false; if (isType) XRefTypePathPieceLayout::readRecord(scratch, IID, inProtocolExt); else XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt, isStatic); Identifier name = getIdentifier(IID); pathTrace.addValue(name); Type filterTy = getType(TID); if (!isType) pathTrace.addType(filterTy); baseModule->lookupQualified(ModuleType::get(baseModule), name, NL_QualifiedDefault | NL_KnownNoDependency, /*typeResolver=*/nullptr, values); filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt, isStatic, None, values); break; } case XREF_EXTENSION_PATH_PIECE: llvm_unreachable("can only extend a nominal"); case XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE: { IdentifierID IID; uint8_t rawOpKind; XRefOperatorOrAccessorPathPieceLayout::readRecord(scratch, IID, rawOpKind); Identifier opName = getIdentifier(IID); pathTrace.addOperator(opName); switch (rawOpKind) { case OperatorKind::Infix: return baseModule->lookupInfixOperator(opName); case OperatorKind::Prefix: return baseModule->lookupPrefixOperator(opName); case OperatorKind::Postfix: return baseModule->lookupPostfixOperator(opName); case OperatorKind::PrecedenceGroup: return baseModule->lookupPrecedenceGroup(opName); default: // Unknown operator kind. error(); return nullptr; } } case XREF_GENERIC_PARAM_PATH_PIECE: case XREF_INITIALIZER_PATH_PIECE: llvm_unreachable("only in a nominal or function"); default: // Unknown xref kind. pathTrace.addUnknown(recordID); error(); return nullptr; } if (values.empty()) { return llvm::make_error("top-level value not found", pathTrace); } // Filters for values discovered in the remaining path pieces. ModuleDecl *M = nullptr; CanGenericSignature genericSig = nullptr; // For remaining path pieces, filter or drill down into the results we have. while (--pathLen) { auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (entry.Kind != llvm::BitstreamEntry::Record) { error(); return nullptr; } scratch.clear(); unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); switch (recordID) { case XREF_TYPE_PATH_PIECE: { if (values.size() == 1) { ModuleDecl *module = values.front()->getModuleContext(); if (module == this->getAssociatedModule()) { // Fast path for nested types in the same module. IdentifierID IID; bool onlyInNominal = false; XRefTypePathPieceLayout::readRecord(scratch, IID, onlyInNominal); Identifier memberName = getIdentifier(IID); pathTrace.addValue(memberName); llvm::PrettyStackTraceString message{ "If you're seeing a crash here, try passing " "-Xfrontend -disable-serialization-nested-type-lookup-table"}; TypeDecl *nestedType = nullptr; if (onlyInNominal) { // Only look in the file containing the type itself. const DeclContext *dc = values.front()->getDeclContext(); auto *serializedFile = dyn_cast(dc->getModuleScopeContext()); if (serializedFile) { nestedType = serializedFile->File.lookupNestedType(memberName, values.front()); } } else { // Fault in extensions, then ask every serialized AST in the module. (void)cast(values.front())->getExtensions(); for (FileUnit *file : module->getFiles()) { if (file == getFile()) continue; auto *serializedFile = dyn_cast(file); if (!serializedFile) continue; nestedType = serializedFile->File.lookupNestedType(memberName, values.front()); if (nestedType) break; } } if (nestedType) { values.clear(); values.push_back(nestedType); ++NumNestedTypeShortcuts; break; } pathTrace.removeLast(); } } LLVM_FALLTHROUGH; } case XREF_VALUE_PATH_PIECE: case XREF_INITIALIZER_PATH_PIECE: { TypeID TID = 0; Identifier memberName; Optional ctorInit; bool isType = false; bool inProtocolExt = false; bool isStatic = false; switch (recordID) { case XREF_TYPE_PATH_PIECE: { IdentifierID IID; XRefTypePathPieceLayout::readRecord(scratch, IID, inProtocolExt); memberName = getIdentifier(IID); isType = true; break; } case XREF_VALUE_PATH_PIECE: { IdentifierID IID; XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt, isStatic); memberName = getIdentifier(IID); break; } case XREF_INITIALIZER_PATH_PIECE: { uint8_t kind; XRefInitializerPathPieceLayout::readRecord(scratch, TID, inProtocolExt, kind); memberName = getContext().Id_init; ctorInit = getActualCtorInitializerKind(kind); break; } default: llvm_unreachable("Unhandled path piece"); } pathTrace.addValue(memberName); Type filterTy = getType(TID); if (!isType) pathTrace.addType(filterTy); if (values.size() != 1) { return llvm::make_error("multiple matching base values", pathTrace); } auto nominal = dyn_cast(values.front()); values.clear(); if (!nominal) { return llvm::make_error("base is not a nominal type", pathTrace); } auto members = nominal->lookupDirect(memberName); values.append(members.begin(), members.end()); filterValues(filterTy, M, genericSig, isType, inProtocolExt, isStatic, ctorInit, values); break; } case XREF_EXTENSION_PATH_PIECE: { ModuleID ownerID; ArrayRef genericParamIDs; XRefExtensionPathPieceLayout::readRecord(scratch, ownerID, genericParamIDs); M = getModule(ownerID); pathTrace.addExtension(M); // Read the generic signature, if we have one. if (!genericParamIDs.empty()) { SmallVector params; SmallVector requirements; for (TypeID paramID : genericParamIDs) { params.push_back(getType(paramID)->castTo()); } readGenericRequirements(requirements, DeclTypeCursor); genericSig = GenericSignature::getCanonical(params, requirements); } continue; } case XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE: { uint8_t rawKind; XRefOperatorOrAccessorPathPieceLayout::readRecord(scratch, None, rawKind); if (values.size() == 1) { if (auto storage = dyn_cast(values.front())) { pathTrace.addAccessor(rawKind); switch (rawKind) { case Getter: values.front() = storage->getGetter(); break; case Setter: values.front() = storage->getSetter(); break; case MaterializeForSet: values.front() = storage->getMaterializeForSetFunc(); break; case Addressor: values.front() = storage->getAddressor(); break; case MutableAddressor: values.front() = storage->getMutableAddressor(); break; case WillSet: case DidSet: llvm_unreachable("invalid XREF accessor kind"); default: // Unknown accessor kind. error(); return nullptr; } break; } } pathTrace.addOperatorFilter(rawKind); auto newEnd = std::remove_if(values.begin(), values.end(), [=](ValueDecl *value) { auto fn = dyn_cast(value); if (!fn) return true; if (!fn->getOperatorDecl()) return true; if (getStableFixity(fn->getOperatorDecl()->getKind()) != rawKind) return true; return false; }); values.erase(newEnd, values.end()); break; } case XREF_GENERIC_PARAM_PATH_PIECE: { if (values.size() != 1) { return llvm::make_error("multiple matching base values", pathTrace); } uint32_t paramIndex; XRefGenericParamPathPieceLayout::readRecord(scratch, paramIndex); pathTrace.addGenericParam(paramIndex); ValueDecl *base = values.front(); GenericParamList *paramList = nullptr; if (auto nominal = dyn_cast(base)) { if (genericSig) { // Find an extension in the requested module that has the // correct generic signature. for (auto ext : nominal->getExtensions()) { if (ext->getModuleContext() == M && ext->getGenericSignature()->getCanonicalSignature() == genericSig) { paramList = ext->getGenericParams(); break; } } assert(paramList && "Couldn't find constrained extension"); } else { // Simple case: use the nominal type's generic parameters. paramList = nominal->getGenericParams(); } } else if (auto alias = dyn_cast(base)) { paramList = alias->getGenericParams(); } else if (auto fn = dyn_cast(base)) paramList = fn->getGenericParams(); if (!paramList) { return llvm::make_error( "cross-reference to generic param for non-generic type", pathTrace); } if (paramIndex >= paramList->size()) { return llvm::make_error( "generic argument index out of bounds", pathTrace); } values.clear(); values.push_back(paramList->getParams()[paramIndex]); assert(values.back()); break; } default: // Unknown xref path piece. pathTrace.addUnknown(recordID); error(); return nullptr; } Optional traceMsg; if (M != getAssociatedModule()) { traceMsg.emplace("If you're seeing a crash here, check that your SDK " "and dependencies match the versions used to build", this); } if (values.empty()) { return llvm::make_error("result not found", pathTrace); } // Reset the module filter. M = nullptr; genericSig = nullptr; } // Make sure we /used/ the last module filter we got. // This catches the case where the last path piece we saw was an Extension // path piece, which is not a valid way to end a path. (Cross-references to // extensions are not allowed because they cannot be uniquely named.) if (M) { error(); return nullptr; } // When all is said and done, we should have a single value here to return. if (values.size() != 1) { return llvm::make_error( "result is ambiguous", std::error_code(EINVAL, std::generic_category())); } return values.front(); } Identifier ModuleFile::getIdentifier(IdentifierID IID) { if (IID == 0) return Identifier(); size_t rawID = IID - NUM_SPECIAL_MODULES; assert(rawID < Identifiers.size() && "invalid identifier ID"); auto identRecord = Identifiers[rawID]; if (identRecord.Offset == 0) return identRecord.Ident; assert(!IdentifierData.empty() && "no identifier data in module"); StringRef rawStrPtr = IdentifierData.substr(identRecord.Offset); size_t terminatorOffset = rawStrPtr.find('\0'); assert(terminatorOffset != StringRef::npos && "unterminated identifier string data"); return getContext().getIdentifier(rawStrPtr.slice(0, terminatorOffset)); } DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) { assert(DCID != 0 && "invalid local DeclContext ID 0"); auto &declContextOrOffset = LocalDeclContexts[DCID-1]; if (declContextOrOffset.isComplete()) return declContextOrOffset; BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(declContextOrOffset); auto entry = DeclTypeCursor.advance(); if (entry.Kind != llvm::BitstreamEntry::Record) { error(); return nullptr; } ASTContext &ctx = getContext(); SmallVector scratch; StringRef blobData; unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); switch(recordID) { case decls_block::ABSTRACT_CLOSURE_EXPR_CONTEXT: { TypeID closureTypeID; unsigned discriminator = 0; bool implicit = false; DeclContextID parentID; decls_block::AbstractClosureExprLayout::readRecord(scratch, closureTypeID, implicit, discriminator, parentID); DeclContext *parent = getDeclContext(parentID); auto type = getType(closureTypeID); declContextOrOffset = new (ctx) SerializedAbstractClosureExpr(type, implicit, discriminator, parent); break; } case decls_block::TOP_LEVEL_CODE_DECL_CONTEXT: { DeclContextID parentID; decls_block::TopLevelCodeDeclContextLayout::readRecord(scratch, parentID); DeclContext *parent = getDeclContext(parentID); declContextOrOffset = new (ctx) SerializedTopLevelCodeDeclContext(parent); break; } case decls_block::PATTERN_BINDING_INITIALIZER_CONTEXT: { DeclID bindingID; uint32_t bindingIndex; decls_block::PatternBindingInitializerLayout::readRecord(scratch, bindingID, bindingIndex); auto decl = getDecl(bindingID); PatternBindingDecl *binding = cast(decl); if (!declContextOrOffset.isComplete()) declContextOrOffset = new (ctx) SerializedPatternBindingInitializer(binding, bindingIndex); break; } case decls_block::DEFAULT_ARGUMENT_INITIALIZER_CONTEXT: { DeclContextID parentID; unsigned index = 0; decls_block::DefaultArgumentInitializerLayout::readRecord(scratch, parentID, index); DeclContext *parent = getDeclContext(parentID); declContextOrOffset = new (ctx) SerializedDefaultArgumentInitializer(index, parent); break; } default: llvm_unreachable("Unknown record ID found when reading local DeclContext."); } return declContextOrOffset; } DeclContext *ModuleFile::getDeclContext(DeclContextID DCID) { if (DCID == 0) return FileContext; assert(DCID <= DeclContexts.size() && "invalid DeclContext ID"); auto &declContextOrOffset = DeclContexts[DCID-1]; if (declContextOrOffset.isComplete()) return declContextOrOffset; BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(declContextOrOffset); auto entry = DeclTypeCursor.advance(); if (entry.Kind != llvm::BitstreamEntry::Record) { error(); return nullptr; } SmallVector scratch; StringRef blobData; unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); if (recordID != decls_block::DECL_CONTEXT) llvm_unreachable("Expected a DECL_CONTEXT record"); DeclContextID declOrDeclContextId; bool isDecl; decls_block::DeclContextLayout::readRecord(scratch, declOrDeclContextId, isDecl); if (!isDecl) return getLocalDeclContext(declOrDeclContextId); auto D = getDecl(declOrDeclContextId); if (auto ND = dyn_cast(D)) { declContextOrOffset = ND; } else if (auto ED = dyn_cast(D)) { declContextOrOffset = ED; } else if (auto AFD = dyn_cast(D)) { declContextOrOffset = AFD; } else if (auto SD = dyn_cast(D)) { declContextOrOffset = SD; } else if (auto TAD = dyn_cast(D)) { declContextOrOffset = TAD; } else { llvm_unreachable("Unknown Decl : DeclContext kind"); } return declContextOrOffset; } ModuleDecl *ModuleFile::getModule(ModuleID MID) { if (MID < NUM_SPECIAL_MODULES) { switch (static_cast(static_cast(MID))) { case BUILTIN_MODULE_ID: return getContext().TheBuiltinModule; case CURRENT_MODULE_ID: return FileContext->getParentModule(); case OBJC_HEADER_MODULE_ID: { auto clangImporter = static_cast(getContext().getClangModuleLoader()); return clangImporter->getImportedHeaderModule(); } case NUM_SPECIAL_MODULES: llvm_unreachable("implementation detail only"); } } return getModule(getIdentifier(MID)); } ModuleDecl *ModuleFile::getModule(ArrayRef name) { if (name.empty() || name.front().empty()) return getContext().TheBuiltinModule; // FIXME: duplicated from NameBinder::getModule if (name.size() == 1 && name.front() == FileContext->getParentModule()->getName()) { if (!ShadowedModule) { auto importer = getContext().getClangModuleLoader(); assert(importer && "no way to import shadowed module"); ShadowedModule = importer->loadModule(SourceLoc(), { { name.front(), SourceLoc() } }); } return ShadowedModule; } SmallVector importPath; for (auto pathElem : name) importPath.push_back({ pathElem, SourceLoc() }); return getContext().getModule(importPath); } /// Translate from the Serialization associativity enum values to the AST /// strongly-typed enum. /// /// The former is guaranteed to be stable, but may not reflect this version of /// the AST. static Optional getActualAssociativity(uint8_t assoc) { switch (assoc) { case serialization::Associativity::LeftAssociative: return swift::Associativity::Left; case serialization::Associativity::RightAssociative: return swift::Associativity::Right; case serialization::Associativity::NonAssociative: return swift::Associativity::None; default: return None; } } static Optional getActualStaticSpellingKind(uint8_t raw) { switch (serialization::StaticSpellingKind(raw)) { case serialization::StaticSpellingKind::None: return swift::StaticSpellingKind::None; case serialization::StaticSpellingKind::KeywordStatic: return swift::StaticSpellingKind::KeywordStatic; case serialization::StaticSpellingKind::KeywordClass: return swift::StaticSpellingKind::KeywordClass; } return None; } static bool isDeclAttrRecord(unsigned ID) { using namespace decls_block; switch (ID) { #define DECL_ATTR(NAME, CLASS, ...) case CLASS##_DECL_ATTR: return true; #include "swift/Serialization/DeclTypeRecordNodes.def" default: return false; } } static Optional getActualAccessibility(uint8_t raw) { switch (serialization::AccessibilityKind(raw)) { #define CASE(NAME) \ case serialization::AccessibilityKind::NAME: \ return Accessibility::NAME; CASE(Private) CASE(FilePrivate) CASE(Internal) CASE(Public) CASE(Open) #undef CASE } return None; } static Optional getActualOptionalTypeKind(uint8_t raw) { switch (serialization::OptionalTypeKind(raw)) { case serialization::OptionalTypeKind::None: return OTK_None; case serialization::OptionalTypeKind::Optional: return OTK_Optional; case serialization::OptionalTypeKind::ImplicitlyUnwrappedOptional: return OTK_ImplicitlyUnwrappedOptional; } return None; } static Optional getActualAddressorKind(uint8_t raw) { switch (serialization::AddressorKind(raw)) { case serialization::AddressorKind::NotAddressor: return swift::AddressorKind::NotAddressor; case serialization::AddressorKind::Unsafe: return swift::AddressorKind::Unsafe; case serialization::AddressorKind::Owning: return swift::AddressorKind::Owning; case serialization::AddressorKind::NativeOwning: return swift::AddressorKind::NativeOwning; case serialization::AddressorKind::NativePinning: return swift::AddressorKind::NativePinning; } return None; } void ModuleFile::configureStorage(AbstractStorageDecl *decl, unsigned rawStorageKind, serialization::DeclID getter, serialization::DeclID setter, serialization::DeclID materializeForSet, serialization::DeclID addressor, serialization::DeclID mutableAddressor, serialization::DeclID willSet, serialization::DeclID didSet) { // We currently don't serialize these locations. SourceLoc beginLoc, endLoc; auto makeAddressed = [&] { decl->makeAddressed(beginLoc, cast_or_null(getDecl(addressor)), cast_or_null(getDecl(mutableAddressor)), endLoc); }; auto addTrivialAccessors = [&] { decl->addTrivialAccessors( cast_or_null(getDecl(getter)), cast_or_null(getDecl(setter)), cast_or_null(getDecl(materializeForSet))); }; auto setObservingAccessors = [&] { decl->setObservingAccessors( cast_or_null(getDecl(getter)), cast_or_null(getDecl(setter)), cast_or_null(getDecl(materializeForSet))); }; switch ((StorageKind) rawStorageKind) { case StorageKind::Stored: return; case StorageKind::StoredWithTrivialAccessors: addTrivialAccessors(); return; case StorageKind::StoredWithObservers: decl->makeStoredWithObservers(beginLoc, cast_or_null(getDecl(willSet)), cast_or_null(getDecl(didSet)), endLoc); setObservingAccessors(); return; case StorageKind::InheritedWithObservers: decl->makeInheritedWithObservers(beginLoc, cast_or_null(getDecl(willSet)), cast_or_null(getDecl(didSet)), endLoc); setObservingAccessors(); return; case StorageKind::Addressed: makeAddressed(); return; case StorageKind::AddressedWithTrivialAccessors: makeAddressed(); addTrivialAccessors(); return; case StorageKind::AddressedWithObservers: decl->makeAddressedWithObservers(beginLoc, cast_or_null(getDecl(addressor)), cast_or_null(getDecl(mutableAddressor)), cast_or_null(getDecl(willSet)), cast_or_null(getDecl(didSet)), endLoc); setObservingAccessors(); return; case StorageKind::Computed: decl->makeComputed(beginLoc, cast_or_null(getDecl(getter)), cast_or_null(getDecl(setter)), cast_or_null(getDecl(materializeForSet)), endLoc); return; case StorageKind::ComputedWithMutableAddress: decl->makeComputedWithMutableAddress(beginLoc, cast_or_null(getDecl(getter)), cast_or_null(getDecl(setter)), cast_or_null(getDecl(materializeForSet)), cast_or_null(getDecl(mutableAddressor)), endLoc); return; } llvm_unreachable("bad storage kind"); } template T *ModuleFile::createDecl(Args &&... args) { // Note that this method is not used for all decl kinds. static_assert(std::is_base_of::value, "not a Decl"); T *result = new (getContext()) T(std::forward(args)...); result->setEarlyAttrValidation(true); return result; } static const uint64_t lazyConformanceContextDataPositionMask = 0xFFFFFFFFFFFF; /// Decode the context data for lazily-loaded conformances. static std::pair decodeLazyConformanceContextData( uint64_t contextData) { return std::make_pair(contextData >> 48, contextData & lazyConformanceContextDataPositionMask); } /// Encode the context data for lazily-loaded conformances. static uint64_t encodeLazyConformanceContextData(uint64_t numProtocols, uint64_t bitPosition) { assert(numProtocols < 0xFFFF); assert(bitPosition < lazyConformanceContextDataPositionMask); return (numProtocols << 48) | bitPosition; } Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { Expected deserialized = getDeclChecked(DID, ForcedContext); if (!deserialized) { fatal(deserialized.takeError()); } return deserialized.get(); } Expected ModuleFile::getDeclChecked(DeclID DID, Optional ForcedContext) { if (DID == 0) return nullptr; assert(DID <= Decls.size() && "invalid decl ID"); auto &declOrOffset = Decls[DID-1]; if (declOrOffset.isComplete()) return declOrOffset; ++NumDeclsLoaded; BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(declOrOffset); auto entry = DeclTypeCursor.advance(); if (entry.Kind != llvm::BitstreamEntry::Record) { // We don't know how to serialize decls represented by sub-blocks. error(); return nullptr; } ASTContext &ctx = getContext(); SmallVector scratch; StringRef blobData; // Read the attributes (if any). DeclAttribute *DAttrs = nullptr; DeclAttribute **AttrsNext = &DAttrs; auto AddAttribute = [&](DeclAttribute *Attr) { // Advance the linked list. *AttrsNext = Attr; AttrsNext = Attr->getMutableNext(); }; unsigned recordID; class PrivateDiscriminatorRAII { ModuleFile &moduleFile; Serialized &declOrOffset; public: Identifier discriminator; PrivateDiscriminatorRAII(ModuleFile &moduleFile, Serialized &declOrOffset) : moduleFile(moduleFile), declOrOffset(declOrOffset) {} ~PrivateDiscriminatorRAII() { if (!discriminator.empty() && declOrOffset.isComplete()) if (auto value = dyn_cast_or_null(declOrOffset.get())) moduleFile.PrivateDiscriminatorsByValue[value] = discriminator; } }; class LocalDiscriminatorRAII { Serialized &declOrOffset; public: unsigned discriminator; LocalDiscriminatorRAII(Serialized &declOrOffset) : declOrOffset(declOrOffset), discriminator(0) {} ~LocalDiscriminatorRAII() { if (discriminator != 0 && declOrOffset.isComplete()) if (auto value = dyn_cast(declOrOffset.get())) value->setLocalDiscriminator(discriminator); } }; PrivateDiscriminatorRAII privateDiscriminatorRAII{*this, declOrOffset}; LocalDiscriminatorRAII localDiscriminatorRAII(declOrOffset); DeserializingEntityRAII deserializingEntity(*this); // Local function that handles the "inherited" list for a type. auto handleInherited = [&](TypeDecl *nominal, ArrayRef rawInheritedIDs) { auto inheritedTypes = ctx.Allocate(rawInheritedIDs.size()); for_each(inheritedTypes, rawInheritedIDs, [this](TypeLoc &tl, uint64_t rawID) { tl = TypeLoc::withoutLoc(getType(rawID)); }); nominal->setInherited(inheritedTypes); nominal->setCheckedInheritanceClause(); }; while (true) { if (entry.Kind != llvm::BitstreamEntry::Record) { // We don't know how to serialize decls represented by sub-blocks. error(); return nullptr; } recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); if (isDeclAttrRecord(recordID)) { DeclAttribute *Attr = nullptr; 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 = 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::Effects_DECL_ATTR: { unsigned kind; serialization::decls_block::EffectsDeclAttrLayout::readRecord(scratch, kind); Attr = new (ctx) EffectsAttr((EffectsKind)kind); break; } case decls_block::Available_DECL_ATTR: { #define LIST_VER_TUPLE_PIECES(X)\ X##_Major, X##_Minor, X##_Subminor, X##_HasMinor, X##_HasSubminor #define DEF_VER_TUPLE_PIECES(X) unsigned LIST_VER_TUPLE_PIECES(X) #define DECODE_VER_TUPLE(X)\ if (X##_HasMinor) {\ if (X##_HasSubminor)\ X = clang::VersionTuple(X##_Major, X##_Minor, X##_Subminor);\ else\ X = clang::VersionTuple(X##_Major, X##_Minor);\ }\ else X = clang::VersionTuple(X##_Major); bool isImplicit; bool isUnavailable; bool isDeprecated; DEF_VER_TUPLE_PIECES(Introduced); DEF_VER_TUPLE_PIECES(Deprecated); DEF_VER_TUPLE_PIECES(Obsoleted); unsigned platform, messageSize, renameSize; // Decode the record, pulling the version tuple information. serialization::decls_block::AvailableDeclAttrLayout::readRecord( scratch, isImplicit, isUnavailable, isDeprecated, LIST_VER_TUPLE_PIECES(Introduced), LIST_VER_TUPLE_PIECES(Deprecated), LIST_VER_TUPLE_PIECES(Obsoleted), platform, messageSize, renameSize); StringRef message = blobData.substr(0, messageSize); blobData = blobData.substr(messageSize); StringRef rename = blobData.substr(0, renameSize); clang::VersionTuple Introduced, Deprecated, Obsoleted; DECODE_VER_TUPLE(Introduced) DECODE_VER_TUPLE(Deprecated) DECODE_VER_TUPLE(Obsoleted) PlatformAgnosticAvailabilityKind platformAgnostic; if (isUnavailable) platformAgnostic = PlatformAgnosticAvailabilityKind::Unavailable; else if (isDeprecated) platformAgnostic = PlatformAgnosticAvailabilityKind::Deprecated; else if (((PlatformKind)platform) == PlatformKind::none && (!Introduced.empty() || !Deprecated.empty() || !Obsoleted.empty())) platformAgnostic = PlatformAgnosticAvailabilityKind::SwiftVersionSpecific; else platformAgnostic = PlatformAgnosticAvailabilityKind::None; Attr = new (ctx) AvailableAttr( SourceLoc(), SourceRange(), (PlatformKind)platform, message, rename, Introduced, SourceRange(), Deprecated, SourceRange(), Obsoleted, SourceRange(), platformAgnostic, isImplicit); break; #undef DEF_VER_TUPLE_PIECES #undef LIST_VER_TUPLE_PIECES #undef DECODE_VER_TUPLE } case decls_block::AutoClosure_DECL_ATTR: { bool isImplicit; bool isEscaping; serialization::decls_block::AutoClosureDeclAttrLayout::readRecord( scratch, isImplicit, isEscaping); Attr = new (ctx) AutoClosureAttr(SourceLoc(), SourceRange(), isEscaping, isImplicit); break; } case decls_block::ObjC_DECL_ATTR: { bool isImplicit; bool isImplicitName; bool isSwift3Inferred; uint64_t numArgs; ArrayRef rawPieceIDs; serialization::decls_block::ObjCDeclAttrLayout::readRecord( scratch, isImplicit, isSwift3Inferred, isImplicitName, numArgs, rawPieceIDs); SmallVector pieces; for (auto pieceID : rawPieceIDs) pieces.push_back(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(Attr)->setSwift3Inferred(isSwift3Inferred); break; } case decls_block::Specialize_DECL_ATTR: { unsigned exported; SpecializeAttr::SpecializationKind specializationKind; unsigned specializationKindVal; SmallVector requirements; serialization::decls_block::SpecializeDeclAttrLayout::readRecord( scratch, exported, specializationKindVal); specializationKind = specializationKindVal ? SpecializeAttr::SpecializationKind::Partial : SpecializeAttr::SpecializationKind::Full; readGenericRequirements(requirements, DeclTypeCursor); Attr = SpecializeAttr::create(ctx, SourceLoc(), SourceRange(), requirements, exported != 0, specializationKind); 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. error(); return nullptr; } if (!Attr) return nullptr; AddAttribute(Attr); } else if (recordID == decls_block::PRIVATE_DISCRIMINATOR) { IdentifierID discriminatorID; decls_block::PrivateDiscriminatorLayout::readRecord(scratch, discriminatorID); privateDiscriminatorRAII.discriminator = getIdentifier(discriminatorID); } else if (recordID == decls_block::LOCAL_DISCRIMINATOR) { unsigned discriminator; decls_block::LocalDiscriminatorLayout::readRecord(scratch, discriminator); localDiscriminatorRAII.discriminator = discriminator; } else { break; } // Advance bitstream cursor to the next record. entry = DeclTypeCursor.advance(); // Prepare to read the next record. scratch.clear(); } PrettyDeclDeserialization stackTraceEntry( this, declOrOffset, DID, static_cast(recordID)); switch (recordID) { case decls_block::TYPE_ALIAS_DECL: { IdentifierID nameID; DeclContextID contextID; TypeID underlyingTypeID, interfaceTypeID; bool isImplicit; GenericEnvironmentID genericEnvID; uint8_t rawAccessLevel; decls_block::TypeAliasLayout::readRecord(scratch, nameID, contextID, underlyingTypeID, interfaceTypeID, isImplicit, genericEnvID, rawAccessLevel); auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID); auto genericParams = maybeReadGenericParams(DC); if (declOrOffset.isComplete()) return declOrOffset; auto alias = createDecl(SourceLoc(), SourceLoc(), getIdentifier(nameID), SourceLoc(), genericParams, DC); declOrOffset = alias; configureGenericEnvironment(alias, genericEnvID); alias->setUnderlyingType(getType(underlyingTypeID)); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { alias->setAccessibility(*accessLevel); } else { error(); return nullptr; } if (isImplicit) alias->setImplicit(); alias->setCheckedInheritanceClause(); break; } case decls_block::GENERIC_TYPE_PARAM_DECL: { IdentifierID nameID; DeclContextID contextID; bool isImplicit; unsigned depth; unsigned index; decls_block::GenericTypeParamDeclLayout::readRecord(scratch, nameID, contextID, isImplicit, depth, index); auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto genericParam = createDecl(DC, getIdentifier(nameID), SourceLoc(), depth, index); declOrOffset = genericParam; if (isImplicit) genericParam->setImplicit(); break; } case decls_block::ASSOCIATED_TYPE_DECL: { IdentifierID nameID; DeclContextID contextID; TypeID defaultDefinitionID; bool isImplicit; ArrayRef rawInheritedIDs; decls_block::AssociatedTypeDeclLayout::readRecord(scratch, nameID, contextID, defaultDefinitionID, isImplicit, rawInheritedIDs); auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; // The where-clause information is pushed up into the protocol // (specifically, into its requirement signature) and // serialized/deserialized there, so the actual Decl doesn't need to store // it. TrailingWhereClause *trailingWhere = nullptr; auto assocType = createDecl( DC, SourceLoc(), getIdentifier(nameID), SourceLoc(), trailingWhere, this, defaultDefinitionID); declOrOffset = assocType; assocType->computeType(); assert(!assocType->getDeclaredInterfaceType()->hasError() && "erroneous associated type"); Accessibility parentAccess = cast(DC)->getFormalAccess(); assocType->setAccessibility(std::max(parentAccess,Accessibility::Internal)); if (isImplicit) assocType->setImplicit(); auto inherited = ctx.Allocate(rawInheritedIDs.size()); for_each(inherited, rawInheritedIDs, [this](TypeLoc &loc, uint64_t rawID) { loc.setType(getType(rawID)); }); assocType->setInherited(inherited); assocType->setCheckedInheritanceClause(); break; } case decls_block::STRUCT_DECL: { IdentifierID nameID; DeclContextID contextID; bool isImplicit; GenericEnvironmentID genericEnvID; uint8_t rawAccessLevel; unsigned numConformances; ArrayRef rawInheritedIDs; decls_block::StructLayout::readRecord(scratch, nameID, contextID, isImplicit, genericEnvID, rawAccessLevel, numConformances, rawInheritedIDs); auto DC = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto genericParams = maybeReadGenericParams(DC); if (declOrOffset.isComplete()) return declOrOffset; auto theStruct = createDecl(SourceLoc(), getIdentifier(nameID), SourceLoc(), None, genericParams, DC); declOrOffset = theStruct; // Read the generic environment. configureGenericEnvironment(theStruct, genericEnvID); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { theStruct->setAccessibility(*accessLevel); } else { error(); return nullptr; } if (isImplicit) theStruct->setImplicit(); theStruct->computeType(); handleInherited(theStruct, rawInheritedIDs); theStruct->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo()); skipRecord(DeclTypeCursor, decls_block::MEMBERS); theStruct->setConformanceLoader( this, encodeLazyConformanceContextData(numConformances, DeclTypeCursor.GetCurrentBitNo())); break; } case decls_block::CONSTRUCTOR_DECL: { DeclContextID contextID; uint8_t rawFailability; bool isImplicit, isObjC, hasStubImplementation, throws; GenericEnvironmentID genericEnvID; uint8_t storedInitKind, rawAccessLevel; TypeID interfaceID, canonicalTypeID; DeclID overriddenID; ArrayRef argNameIDs; decls_block::ConstructorLayout::readRecord(scratch, contextID, rawFailability, isImplicit, isObjC, hasStubImplementation, throws, storedInitKind, genericEnvID, interfaceID, canonicalTypeID, overriddenID, rawAccessLevel, argNameIDs); // Resolve the name ids. SmallVector argNames; for (auto argNameID : argNameIDs) argNames.push_back(getIdentifier(argNameID)); DeclName name(ctx, ctx.Id_init, argNames); Optional initKind = getActualCtorInitializerKind(storedInitKind); auto overridden = getDeclChecked(overriddenID); if (!overridden) { llvm::consumeError(overridden.takeError()); auto kind = OverrideError::Normal; if (initKind == CtorInitializerKind::Designated) kind = OverrideError::DesignatedInitializer; return llvm::make_error(name, kind); } auto parent = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto *genericParams = maybeReadGenericParams(parent); if (declOrOffset.isComplete()) return declOrOffset; OptionalTypeKind failability = OTK_None; if (auto actualFailability = getActualOptionalTypeKind(rawFailability)) failability = *actualFailability; auto ctor = createDecl(name, SourceLoc(), failability, /*FailabilityLoc=*/SourceLoc(), /*Throws=*/throws, /*ThrowsLoc=*/SourceLoc(), /*BodyParams=*/nullptr, nullptr, genericParams, parent); declOrOffset = ctor; configureGenericEnvironment(ctor, genericEnvID); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { ctor->setAccessibility(*accessLevel); } else { error(); return nullptr; } auto *bodyParams0 = readParameterList(); bodyParams0->get(0)->setImplicit(); // self is implicit. auto *bodyParams1 = readParameterList(); assert(bodyParams0 && bodyParams1 && "missing parameters for constructor"); ctor->setParameterLists(bodyParams0->get(0), bodyParams1); auto interfaceType = getType(interfaceID); ctor->setInterfaceType(interfaceType); // Set the initializer interface type of the constructor. auto allocType = ctor->getInterfaceType(); auto selfTy = ctor->computeInterfaceSelfType(/*isInitializingCtor=*/true); if (auto polyFn = allocType->getAs()) { ctor->setInitializerInterfaceType( GenericFunctionType::get(polyFn->getGenericSignature(), selfTy, polyFn->getResult(), polyFn->getExtInfo())); } else { auto fn = allocType->castTo(); ctor->setInitializerInterfaceType(FunctionType::get(selfTy, fn->getResult(), fn->getExtInfo())); } if (auto errorConvention = maybeReadForeignErrorConvention()) ctor->setForeignErrorConvention(*errorConvention); if (isImplicit) ctor->setImplicit(); if (hasStubImplementation) ctor->setStubImplementation(true); if (initKind.hasValue()) ctor->setInitKind(initKind.getValue()); if (auto overriddenCtor = cast_or_null(overridden.get())) ctor->setOverriddenDecl(overriddenCtor); break; } case decls_block::VAR_DECL: { IdentifierID nameID; DeclContextID contextID; bool isImplicit, isObjC, isStatic, isLet, hasNonPatternBindingInit; uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel; TypeID interfaceTypeID, canonicalTypeID; DeclID getterID, setterID, materializeForSetID, willSetID, didSetID; DeclID addressorID, mutableAddressorID, overriddenID; decls_block::VarLayout::readRecord(scratch, nameID, contextID, isImplicit, isObjC, isStatic, isLet, hasNonPatternBindingInit, storageKind, interfaceTypeID, canonicalTypeID, getterID, setterID, materializeForSetID, addressorID, mutableAddressorID, willSetID, didSetID, overriddenID, rawAccessLevel, rawSetterAccessLevel); Identifier name = getIdentifier(nameID); Expected overridden = getDeclChecked(overriddenID); if (!overridden) { llvm::consumeError(overridden.takeError()); return llvm::make_error(name); } auto canonicalType = getTypeChecked(canonicalTypeID); if (!canonicalType) return llvm::make_error(name, takeErrorInfo(canonicalType.takeError())); auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto var = createDecl(/*IsStatic*/isStatic, /*IsLet*/isLet, /*IsCaptureList*/false, SourceLoc(), name, Type(), DC); var->setHasNonPatternBindingInit(hasNonPatternBindingInit); declOrOffset = var; Type interfaceType = getType(interfaceTypeID); var->setInterfaceType(interfaceType); if (auto referenceStorage = interfaceType->getAs()) AddAttribute(new (ctx) OwnershipAttr(referenceStorage->getOwnership())); configureStorage(var, storageKind, getterID, setterID, materializeForSetID, addressorID, mutableAddressorID, willSetID, didSetID); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { var->setAccessibility(*accessLevel); } else { error(); return nullptr; } if (var->isSettable(nullptr)) { if (auto setterAccess = getActualAccessibility(rawSetterAccessLevel)) { var->setSetterAccessibility(*setterAccess); } else { error(); return nullptr; } } if (isImplicit) var->setImplicit(); if (auto overriddenVar = cast_or_null(overridden.get())) { var->setOverriddenDecl(overriddenVar); AddAttribute(new (ctx) OverrideAttr(SourceLoc())); } break; } case decls_block::PARAM_DECL: { IdentifierID argNameID, paramNameID; DeclContextID contextID; bool isLet; TypeID interfaceTypeID; decls_block::ParamLayout::readRecord(scratch, argNameID, paramNameID, contextID, isLet, interfaceTypeID); auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto param = createDecl(isLet, SourceLoc(), SourceLoc(), getIdentifier(argNameID), SourceLoc(), getIdentifier(paramNameID), Type(), DC); declOrOffset = param; auto paramTy = getType(interfaceTypeID); if (paramTy->hasError()) { // FIXME: This should never happen, because we don't serialize // error types. DC->dumpContext(); paramTy->dump(); error(); return nullptr; } param->setInterfaceType(paramTy); break; } case decls_block::FUNC_DECL: { DeclContextID contextID; bool isImplicit; bool isStatic; uint8_t rawStaticSpelling, rawAccessLevel, rawAddressorKind; bool isObjC, isMutating, hasDynamicSelf, throws; unsigned numParamPatterns; GenericEnvironmentID genericEnvID; TypeID interfaceTypeID, canonicalTypeID; DeclID associatedDeclID; DeclID overriddenID; DeclID accessorStorageDeclID; bool hasCompoundName; ArrayRef nameIDs; decls_block::FuncLayout::readRecord(scratch, contextID, isImplicit, isStatic, rawStaticSpelling, isObjC, isMutating, hasDynamicSelf, throws, numParamPatterns, genericEnvID, interfaceTypeID, canonicalTypeID, associatedDeclID, overriddenID, accessorStorageDeclID, hasCompoundName, rawAddressorKind, rawAccessLevel, nameIDs); // Resolve the name ids. SmallVector names; for (auto nameID : nameIDs) names.push_back(getIdentifier(nameID)); DeclName name; if (!names.empty()) { if (hasCompoundName) name = DeclName(ctx, names[0], llvm::makeArrayRef(names.begin() + 1, names.end())); else name = DeclName(names[0]); } Expected overridden = getDeclChecked(overriddenID); if (!overridden) { llvm::consumeError(overridden.takeError()); return llvm::make_error(name); } auto DC = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; // Read generic params before reading the type, because the type may // reference generic parameters, and we want them to have a dummy // DeclContext for now. GenericParamList *genericParams = maybeReadGenericParams(DC); auto staticSpelling = getActualStaticSpellingKind(rawStaticSpelling); if (!staticSpelling.hasValue()) { error(); return nullptr; } if (declOrOffset.isComplete()) return declOrOffset; auto fn = FuncDecl::createDeserialized( ctx, /*StaticLoc=*/SourceLoc(), staticSpelling.getValue(), /*FuncLoc=*/SourceLoc(), name, /*NameLoc=*/SourceLoc(), /*Throws=*/throws, /*ThrowsLoc=*/SourceLoc(), /*AccessorKeywordLoc=*/SourceLoc(), genericParams, numParamPatterns, DC); fn->setEarlyAttrValidation(); declOrOffset = fn; configureGenericEnvironment(fn, genericEnvID); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { fn->setAccessibility(*accessLevel); } else { error(); return nullptr; } if (auto addressorKind = getActualAddressorKind(rawAddressorKind)) { if (*addressorKind != AddressorKind::NotAddressor) fn->setAddressorKind(*addressorKind); } else { error(); return nullptr; } if (Decl *associated = getDecl(associatedDeclID)) { if (auto op = dyn_cast(associated)) { fn->setOperatorDecl(op); if (isa(op)) fn->getAttrs().add(new (ctx) PrefixAttr(/*implicit*/false)); else if (isa(op)) fn->getAttrs().add(new (ctx) PostfixAttr(/*implicit*/false)); // Note that an explicit 'infix' is not required. } // Otherwise, unknown associated decl kind. } // Set the interface type. auto interfaceType = getType(interfaceTypeID); fn->setInterfaceType(interfaceType); SmallVector paramLists; for (unsigned i = 0, e = numParamPatterns; i != e; ++i) paramLists.push_back(readParameterList()); // If the first parameter list is (self), mark it implicit. if (numParamPatterns && DC->isTypeContext()) paramLists[0]->get(0)->setImplicit(); fn->setDeserializedSignature(paramLists, TypeLoc()); if (auto errorConvention = maybeReadForeignErrorConvention()) fn->setForeignErrorConvention(*errorConvention); if (auto overriddenFunc = cast_or_null(overridden.get())) { fn->setOverriddenDecl(overriddenFunc); AddAttribute(new (ctx) OverrideAttr(SourceLoc())); } fn->setStatic(isStatic); if (isImplicit) fn->setImplicit(); fn->setMutating(isMutating); fn->setDynamicSelf(hasDynamicSelf); // If we are an accessor on a var or subscript, make sure it is deserialized // too. getDecl(accessorStorageDeclID); break; } case decls_block::PATTERN_BINDING_DECL: { DeclContextID contextID; bool isImplicit; bool isStatic; uint8_t RawStaticSpelling; unsigned numPatterns; ArrayRef initContextIDs; decls_block::PatternBindingLayout::readRecord(scratch, contextID, isImplicit, isStatic, RawStaticSpelling, numPatterns, initContextIDs); auto StaticSpelling = getActualStaticSpellingKind(RawStaticSpelling); if (!StaticSpelling.hasValue()) { error(); return nullptr; } auto dc = getDeclContext(contextID); SmallVector, 4> patterns; for (unsigned i = 0; i != numPatterns; ++i) { auto pattern = readPattern(dc); if (!pattern) { // Silently drop the pattern... llvm::consumeError(pattern.takeError()); // ...but continue to read any further patterns we're expecting. continue; } patterns.emplace_back(pattern.get(), DeclContextID()); if (!initContextIDs.empty()) patterns.back().second = initContextIDs[i]; } auto binding = PatternBindingDecl::createDeserialized(ctx, SourceLoc(), StaticSpelling.getValue(), SourceLoc(), patterns.size(), dc); binding->setEarlyAttrValidation(true); declOrOffset = binding; binding->setStatic(isStatic); if (isImplicit) binding->setImplicit(); for (unsigned i = 0; i != patterns.size(); ++i) { DeclContext *initContext = getDeclContext(patterns[i].second); binding->setPattern(i, patterns[i].first, initContext); } break; } case decls_block::PROTOCOL_DECL: { IdentifierID nameID; DeclContextID contextID; bool isImplicit, isClassBounded, isObjC; GenericEnvironmentID genericEnvID; uint8_t rawAccessLevel; ArrayRef rawInheritedIDs; decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID, isImplicit, isClassBounded, isObjC, genericEnvID, rawAccessLevel, rawInheritedIDs); auto DC = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto proto = createDecl(DC, SourceLoc(), SourceLoc(), getIdentifier(nameID), None, /*TrailingWhere=*/nullptr); declOrOffset = proto; proto->setRequiresClass(isClassBounded); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { proto->setAccessibility(*accessLevel); } else { error(); return nullptr; } auto genericParams = maybeReadGenericParams(DC); assert(genericParams && "protocol with no generic parameters?"); proto->setGenericParams(genericParams); handleInherited(proto, rawInheritedIDs); configureGenericEnvironment(proto, genericEnvID); SmallVector requirements; readGenericRequirements(requirements, DeclTypeCursor); if (isImplicit) proto->setImplicit(); proto->computeType(); auto signature = GenericSignature::get( { proto->getProtocolSelfType() }, requirements); proto->setRequirementSignature(signature); proto->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo()); proto->setCircularityCheck(CircularityCheck::Checked); break; } case decls_block::PREFIX_OPERATOR_DECL: { IdentifierID nameID; DeclContextID contextID; decls_block::PrefixOperatorLayout::readRecord(scratch, nameID, contextID); auto DC = getDeclContext(contextID); declOrOffset = createDecl(DC, SourceLoc(), getIdentifier(nameID), SourceLoc()); break; } case decls_block::POSTFIX_OPERATOR_DECL: { IdentifierID nameID; DeclContextID contextID; decls_block::PostfixOperatorLayout::readRecord(scratch, nameID, contextID); auto DC = getDeclContext(contextID); declOrOffset = createDecl(DC, SourceLoc(), getIdentifier(nameID), SourceLoc()); break; } case decls_block::INFIX_OPERATOR_DECL: { IdentifierID nameID; DeclContextID contextID; DeclID precedenceGroupID; decls_block::InfixOperatorLayout::readRecord(scratch, nameID, contextID, precedenceGroupID); PrecedenceGroupDecl *precedenceGroup = nullptr; Identifier precedenceGroupName; if (precedenceGroupID) { precedenceGroup = dyn_cast_or_null(getDecl(precedenceGroupID)); if (precedenceGroup) { precedenceGroupName = precedenceGroup->getName(); } } auto DC = getDeclContext(contextID); auto result = createDecl(DC, SourceLoc(), getIdentifier(nameID), SourceLoc(), SourceLoc(), precedenceGroupName, SourceLoc()); result->setPrecedenceGroup(precedenceGroup); declOrOffset = result; break; } case decls_block::PRECEDENCE_GROUP_DECL: { IdentifierID nameID; DeclContextID contextID; uint8_t rawAssociativity; bool assignment; unsigned numHigherThan; ArrayRef rawRelations; decls_block::PrecedenceGroupLayout::readRecord(scratch, nameID, contextID, rawAssociativity, assignment, numHigherThan, rawRelations); auto DC = getDeclContext(contextID); auto associativity = getActualAssociativity(rawAssociativity); if (!associativity.hasValue()) { error(); return nullptr; } if (numHigherThan > rawRelations.size()) { error(); return nullptr; } SmallVector higherThan; for (auto relID : rawRelations.slice(0, numHigherThan)) { PrecedenceGroupDecl *rel = nullptr; if (relID) rel = dyn_cast_or_null(getDecl(relID)); if (!rel) { error(); return nullptr; } higherThan.push_back({SourceLoc(), rel->getName(), rel}); } SmallVector lowerThan; for (auto relID : rawRelations.slice(numHigherThan)) { PrecedenceGroupDecl *rel = nullptr; if (relID) rel = dyn_cast_or_null(getDecl(relID)); if (!rel) { error(); return nullptr; } lowerThan.push_back({SourceLoc(), rel->getName(), rel}); } declOrOffset = PrecedenceGroupDecl::create(DC, SourceLoc(), SourceLoc(), getIdentifier(nameID), SourceLoc(), SourceLoc(), SourceLoc(), *associativity, SourceLoc(), SourceLoc(), assignment, SourceLoc(), higherThan, SourceLoc(), lowerThan, SourceLoc()); break; } case decls_block::CLASS_DECL: { IdentifierID nameID; DeclContextID contextID; bool isImplicit, isObjC, requiresStoredPropertyInits; GenericEnvironmentID genericEnvID; TypeID superclassID; uint8_t rawAccessLevel; unsigned numConformances; ArrayRef rawInheritedIDs; decls_block::ClassLayout::readRecord(scratch, nameID, contextID, isImplicit, isObjC, requiresStoredPropertyInits, genericEnvID, superclassID, rawAccessLevel, numConformances, rawInheritedIDs); auto DC = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto genericParams = maybeReadGenericParams(DC); if (declOrOffset.isComplete()) return declOrOffset; auto theClass = createDecl(SourceLoc(), getIdentifier(nameID), SourceLoc(), None, genericParams, DC); declOrOffset = theClass; configureGenericEnvironment(theClass, genericEnvID); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { theClass->setAccessibility(*accessLevel); } else { error(); return nullptr; } theClass->setAddedImplicitInitializers(); if (isImplicit) theClass->setImplicit(); theClass->setSuperclass(getType(superclassID)); if (requiresStoredPropertyInits) theClass->setRequiresStoredPropertyInits(true); theClass->computeType(); handleInherited(theClass, rawInheritedIDs); theClass->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo()); theClass->setHasDestructor(); skipRecord(DeclTypeCursor, decls_block::MEMBERS); theClass->setConformanceLoader( this, encodeLazyConformanceContextData(numConformances, DeclTypeCursor.GetCurrentBitNo())); theClass->setCircularityCheck(CircularityCheck::Checked); break; } case decls_block::ENUM_DECL: { IdentifierID nameID; DeclContextID contextID; bool isImplicit; GenericEnvironmentID genericEnvID; TypeID rawTypeID; uint8_t rawAccessLevel; unsigned numConformances; ArrayRef rawInheritedIDs; decls_block::EnumLayout::readRecord(scratch, nameID, contextID, isImplicit, genericEnvID, rawTypeID, rawAccessLevel, numConformances, rawInheritedIDs); auto DC = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto genericParams = maybeReadGenericParams(DC); if (declOrOffset.isComplete()) return declOrOffset; auto theEnum = createDecl(SourceLoc(), getIdentifier(nameID), SourceLoc(), None, genericParams, DC); declOrOffset = theEnum; configureGenericEnvironment(theEnum, genericEnvID); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { theEnum->setAccessibility(*accessLevel); } else { error(); return nullptr; } if (isImplicit) theEnum->setImplicit(); theEnum->setRawType(getType(rawTypeID)); theEnum->computeType(); handleInherited(theEnum, rawInheritedIDs); theEnum->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo()); skipRecord(DeclTypeCursor, decls_block::MEMBERS); theEnum->setConformanceLoader( this, encodeLazyConformanceContextData(numConformances, DeclTypeCursor.GetCurrentBitNo())); break; } case decls_block::ENUM_ELEMENT_DECL: { IdentifierID nameID; DeclContextID contextID; TypeID interfaceTypeID; bool hasArgumentType; bool isImplicit; bool isNegative; unsigned rawValueKindID; decls_block::EnumElementLayout::readRecord(scratch, nameID, contextID, interfaceTypeID, hasArgumentType, isImplicit, rawValueKindID, isNegative); DeclContext *DC = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto elem = createDecl(SourceLoc(), getIdentifier(nameID), TypeLoc(), hasArgumentType, SourceLoc(), nullptr, DC); declOrOffset = elem; // Deserialize the literal raw value, if any. switch ((EnumElementRawValueKind)rawValueKindID) { case EnumElementRawValueKind::None: break; case EnumElementRawValueKind::IntegerLiteral: { auto literalText = getContext().AllocateCopy(blobData); auto literal = new (getContext()) IntegerLiteralExpr(literalText, SourceLoc(), /*implicit*/ true); if (isNegative) literal->setNegative(SourceLoc()); elem->setRawValueExpr(literal); } } auto interfaceType = getType(interfaceTypeID); elem->setInterfaceType(interfaceType); if (isImplicit) elem->setImplicit(); elem->setAccessibility(std::max(cast(DC)->getFormalAccess(), Accessibility::Internal)); break; } case decls_block::SUBSCRIPT_DECL: { DeclContextID contextID; bool isImplicit, isObjC; GenericEnvironmentID genericEnvID; TypeID interfaceTypeID, canonicalTypeID; DeclID getterID, setterID, materializeForSetID; DeclID addressorID, mutableAddressorID, willSetID, didSetID; DeclID overriddenID; uint8_t rawAccessLevel, rawSetterAccessLevel; uint8_t rawStorageKind; ArrayRef argNameIDs; decls_block::SubscriptLayout::readRecord(scratch, contextID, isImplicit, isObjC, rawStorageKind, genericEnvID, interfaceTypeID, canonicalTypeID, getterID, setterID, materializeForSetID, addressorID, mutableAddressorID, willSetID, didSetID, overriddenID, rawAccessLevel, rawSetterAccessLevel, argNameIDs); // Resolve the name ids. SmallVector argNames; for (auto argNameID : argNameIDs) argNames.push_back(getIdentifier(argNameID)); DeclName name(ctx, ctx.Id_subscript, argNames); Expected overridden = getDeclChecked(overriddenID); if (!overridden) { llvm::consumeError(overridden.takeError()); return llvm::make_error(name); } auto parent = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto *genericParams = maybeReadGenericParams(parent); if (declOrOffset.isComplete()) return declOrOffset; auto subscript = createDecl(name, SourceLoc(), nullptr, SourceLoc(), TypeLoc(), parent, genericParams); declOrOffset = subscript; configureGenericEnvironment(subscript, genericEnvID); subscript->setIndices(readParameterList()); configureStorage(subscript, rawStorageKind, getterID, setterID, materializeForSetID, addressorID, mutableAddressorID, willSetID, didSetID); if (auto accessLevel = getActualAccessibility(rawAccessLevel)) { subscript->setAccessibility(*accessLevel); } else { error(); return nullptr; } if (subscript->isSettable()) { if (auto setterAccess = getActualAccessibility(rawSetterAccessLevel)) { subscript->setSetterAccessibility(*setterAccess); } else { error(); return nullptr; } } auto interfaceType = getType(interfaceTypeID); subscript->setInterfaceType(interfaceType); if (isImplicit) subscript->setImplicit(); if (auto overriddenSub = cast_or_null(overridden.get())) { subscript->setOverriddenDecl(overriddenSub); AddAttribute(new (ctx) OverrideAttr(SourceLoc())); } break; } case decls_block::EXTENSION_DECL: { TypeID baseID; DeclContextID contextID; bool isImplicit; GenericEnvironmentID genericEnvID; unsigned numConformances; ArrayRef rawInheritedIDs; decls_block::ExtensionLayout::readRecord(scratch, baseID, contextID, isImplicit, genericEnvID, numConformances, rawInheritedIDs); auto DC = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto extension = ExtensionDecl::create(ctx, SourceLoc(), TypeLoc(), { }, DC, nullptr); extension->setEarlyAttrValidation(); declOrOffset = extension; // Generic parameter lists are written from outermost to innermost. // Keep reading until we run out of generic parameter lists. GenericParamList *outerParams = nullptr; while (auto *genericParams = maybeReadGenericParams(DC, outerParams)) outerParams = genericParams; extension->setGenericParams(outerParams); configureGenericEnvironment(extension, genericEnvID); auto baseTy = getType(baseID); auto nominal = baseTy->getAnyNominal(); extension->getExtendedTypeLoc().setType(baseTy); if (isImplicit) extension->setImplicit(); auto inheritedTypes = ctx.Allocate(rawInheritedIDs.size()); for_each(inheritedTypes, rawInheritedIDs, [this](TypeLoc &tl, uint64_t rawID) { tl = TypeLoc::withoutLoc(getType(rawID)); }); extension->setInherited(inheritedTypes); extension->setCheckedInheritanceClause(); extension->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo()); skipRecord(DeclTypeCursor, decls_block::MEMBERS); extension->setConformanceLoader( this, encodeLazyConformanceContextData(numConformances, DeclTypeCursor.GetCurrentBitNo())); nominal->addExtension(extension); #ifndef NDEBUG if (outerParams) { unsigned paramCount = 0; for (auto *paramList = outerParams; paramList != nullptr; paramList = paramList->getOuterParameters()) { paramCount += paramList->size(); } assert(paramCount == extension->getGenericSignature()->getGenericParams().size()); } #endif break; } case decls_block::DESTRUCTOR_DECL: { DeclContextID contextID; bool isImplicit, isObjC; GenericEnvironmentID genericEnvID; TypeID interfaceID; decls_block::DestructorLayout::readRecord(scratch, contextID, isImplicit, isObjC, genericEnvID, interfaceID); DeclContext *DC = getDeclContext(contextID); if (declOrOffset.isComplete()) return declOrOffset; auto dtor = createDecl(ctx.Id_deinit, SourceLoc(), /*selfpat*/nullptr, DC); declOrOffset = dtor; configureGenericEnvironment(dtor, genericEnvID); dtor->setAccessibility(std::max(cast(DC)->getFormalAccess(), Accessibility::Internal)); auto *selfParams = readParameterList(); selfParams->get(0)->setImplicit(); // self is implicit. assert(selfParams && "Didn't get self pattern?"); dtor->setSelfDecl(selfParams->get(0)); auto interfaceType = getType(interfaceID); dtor->setInterfaceType(interfaceType); if (isImplicit) dtor->setImplicit(); break; } case decls_block::XREF: { assert(DAttrs == nullptr); ModuleID baseModuleID; uint32_t pathLen; decls_block::XRefLayout::readRecord(scratch, baseModuleID, pathLen); auto resolved = resolveCrossReference(getModule(baseModuleID), pathLen); if (!resolved) return resolved; declOrOffset = resolved.get(); break; } default: // We don't know how to deserialize this kind of decl. error(); return nullptr; } // Record the attributes. if (DAttrs) declOrOffset.get()->getAttrs().setRawAttributeChain(DAttrs); auto decl = declOrOffset.get(); decl->setValidationStarted(); return decl; } /// Translate from the Serialization function type repr enum values to the AST /// strongly-typed enum. /// /// The former is guaranteed to be stable, but may not reflect this version of /// the AST. static Optional getActualFunctionTypeRepresentation(uint8_t rep) { switch (rep) { #define CASE(THE_CC) \ case (uint8_t)serialization::FunctionTypeRepresentation::THE_CC: \ return swift::FunctionType::Representation::THE_CC; CASE(Swift) CASE(Block) CASE(Thin) CASE(CFunctionPointer) #undef CASE default: return None; } } /// Translate from the Serialization function type repr enum values to the AST /// strongly-typed enum. /// /// The former is guaranteed to be stable, but may not reflect this version of /// the AST. static Optional getActualSILFunctionTypeRepresentation(uint8_t rep) { switch (rep) { #define CASE(THE_CC) \ case (uint8_t)serialization::SILFunctionTypeRepresentation::THE_CC: \ return swift::SILFunctionType::Representation::THE_CC; CASE(Thick) CASE(Block) CASE(Thin) CASE(CFunctionPointer) CASE(Method) CASE(ObjCMethod) CASE(WitnessMethod) #undef CASE default: return None; } } /// Translate from the serialization Ownership enumerators, which are /// guaranteed to be stable, to the AST ones. static Optional getActualOwnership(serialization::Ownership raw) { switch (raw) { case serialization::Ownership::Strong: return swift::Ownership::Strong; case serialization::Ownership::Unmanaged:return swift::Ownership::Unmanaged; case serialization::Ownership::Unowned: return swift::Ownership::Unowned; case serialization::Ownership::Weak: return swift::Ownership::Weak; } return None; } /// Translate from the serialization ParameterConvention enumerators, /// which are guaranteed to be stable, to the AST ones. static Optional getActualParameterConvention(uint8_t raw) { switch (serialization::ParameterConvention(raw)) { #define CASE(ID) \ case serialization::ParameterConvention::ID: \ return swift::ParameterConvention::ID; CASE(Indirect_In) CASE(Indirect_Inout) CASE(Indirect_InoutAliasable) CASE(Indirect_In_Guaranteed) CASE(Direct_Owned) CASE(Direct_Unowned) CASE(Direct_Guaranteed) #undef CASE } return None; } /// Translate from the serialization ResultConvention enumerators, /// which are guaranteed to be stable, to the AST ones. static Optional getActualResultConvention(uint8_t raw) { switch (serialization::ResultConvention(raw)) { #define CASE(ID) \ case serialization::ResultConvention::ID: return swift::ResultConvention::ID; CASE(Indirect) CASE(Owned) CASE(Unowned) CASE(UnownedInnerPointer) CASE(Autoreleased) #undef CASE } return None; } Type ModuleFile::getType(TypeID TID) { Expected deserialized = getTypeChecked(TID); if (!deserialized) { fatal(deserialized.takeError()); } return deserialized.get(); } Expected ModuleFile::getTypeChecked(TypeID TID) { if (TID == 0) return Type(); assert(TID <= Types.size() && "invalid type ID"); auto &typeOrOffset = Types[TID-1]; if (typeOrOffset.isComplete()) return typeOrOffset; BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(typeOrOffset); auto entry = DeclTypeCursor.advance(); if (entry.Kind != llvm::BitstreamEntry::Record) { // We don't know how to serialize types represented by sub-blocks. error(); return nullptr; } ASTContext &ctx = getContext(); SmallVector scratch; StringRef blobData; unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); switch (recordID) { case decls_block::NAME_ALIAS_TYPE: { DeclID underlyingID; TypeID canonicalTypeID; decls_block::NameAliasTypeLayout::readRecord(scratch, underlyingID, canonicalTypeID); auto aliasOrError = getDeclChecked(underlyingID); if (!aliasOrError) return aliasOrError.takeError(); auto alias = dyn_cast(aliasOrError.get()); if (ctx.LangOpts.EnableDeserializationRecovery) { Expected expectedType = getTypeChecked(canonicalTypeID); if (!expectedType) return expectedType.takeError(); if (expectedType.get()) { if (!alias || !alias->getDeclaredInterfaceType()->isEqual(expectedType.get())) { // Fall back to the canonical type. typeOrOffset = expectedType.get(); break; } } } // Look through compatibility aliases that are now unavailable. if (alias->getAttrs().isUnavailable(ctx) && alias->isCompatibilityAlias()) { typeOrOffset = alias->getUnderlyingTypeLoc().getType(); break; } typeOrOffset = alias->getDeclaredInterfaceType(); break; } case decls_block::NOMINAL_TYPE: { DeclID declID; TypeID parentID; decls_block::NominalTypeLayout::readRecord(scratch, declID, parentID); Expected parentTy = getTypeChecked(parentID); if (!parentTy) return parentTy.takeError(); auto nominalOrError = getDeclChecked(declID); if (!nominalOrError) return nominalOrError.takeError(); auto nominal = dyn_cast(nominalOrError.get()); if (!nominal) { XRefTracePath tinyTrace{*nominalOrError.get()->getModuleContext()}; tinyTrace.addValue(cast(nominalOrError.get())->getName()); return llvm::make_error("declaration is not a nominal type", tinyTrace); } typeOrOffset = NominalType::get(nominal, parentTy.get(), ctx); assert(typeOrOffset.isComplete()); break; } case decls_block::PAREN_TYPE: { TypeID underlyingID; bool isVariadic, isAutoClosure, isEscaping; decls_block::ParenTypeLayout::readRecord(scratch, underlyingID, isVariadic, isAutoClosure, isEscaping); typeOrOffset = ParenType::get( ctx, getType(underlyingID), ParameterTypeFlags(isVariadic, isAutoClosure, isEscaping)); break; } case decls_block::TUPLE_TYPE: { // The tuple record itself is empty. Read all trailing elements. SmallVector elements; while (true) { auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (entry.Kind != llvm::BitstreamEntry::Record) break; scratch.clear(); unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); if (recordID != decls_block::TUPLE_TYPE_ELT) break; IdentifierID nameID; TypeID typeID; bool isVariadic, isAutoClosure, isEscaping; decls_block::TupleTypeEltLayout::readRecord( scratch, nameID, typeID, isVariadic, isAutoClosure, isEscaping); elements.emplace_back( getType(typeID), getIdentifier(nameID), ParameterTypeFlags(isVariadic, isAutoClosure, isEscaping)); } typeOrOffset = TupleType::get(elements, ctx); break; } case decls_block::FUNCTION_TYPE: { TypeID inputID; TypeID resultID; uint8_t rawRepresentation; bool autoClosure, noescape, throws; decls_block::FunctionTypeLayout::readRecord(scratch, inputID, resultID, rawRepresentation, autoClosure, noescape, throws); auto representation = getActualFunctionTypeRepresentation(rawRepresentation); if (!representation.hasValue()) { error(); return nullptr; } auto Info = FunctionType::ExtInfo(*representation, autoClosure, noescape, throws); typeOrOffset = FunctionType::get(getType(inputID), getType(resultID), Info); break; } case decls_block::EXISTENTIAL_METATYPE_TYPE: { TypeID instanceID; uint8_t repr; decls_block::ExistentialMetatypeTypeLayout::readRecord(scratch, instanceID, repr); switch (repr) { case serialization::MetatypeRepresentation::MR_None: typeOrOffset = ExistentialMetatypeType::get(getType(instanceID)); break; case serialization::MetatypeRepresentation::MR_Thin: error(); break; case serialization::MetatypeRepresentation::MR_Thick: typeOrOffset = ExistentialMetatypeType::get(getType(instanceID), MetatypeRepresentation::Thick); break; case serialization::MetatypeRepresentation::MR_ObjC: typeOrOffset = ExistentialMetatypeType::get(getType(instanceID), MetatypeRepresentation::ObjC); break; default: error(); break; } break; } case decls_block::METATYPE_TYPE: { TypeID instanceID; uint8_t repr; decls_block::MetatypeTypeLayout::readRecord(scratch, instanceID, repr); switch (repr) { case serialization::MetatypeRepresentation::MR_None: typeOrOffset = MetatypeType::get(getType(instanceID)); break; case serialization::MetatypeRepresentation::MR_Thin: typeOrOffset = MetatypeType::get(getType(instanceID), MetatypeRepresentation::Thin); break; case serialization::MetatypeRepresentation::MR_Thick: typeOrOffset = MetatypeType::get(getType(instanceID), MetatypeRepresentation::Thick); break; case serialization::MetatypeRepresentation::MR_ObjC: typeOrOffset = MetatypeType::get(getType(instanceID), MetatypeRepresentation::ObjC); break; default: error(); break; } break; } case decls_block::DYNAMIC_SELF_TYPE: { TypeID selfID; decls_block::DynamicSelfTypeLayout::readRecord(scratch, selfID); typeOrOffset = DynamicSelfType::get(getType(selfID), ctx); break; } case decls_block::LVALUE_TYPE: { TypeID objectTypeID; decls_block::LValueTypeLayout::readRecord(scratch, objectTypeID); typeOrOffset = LValueType::get(getType(objectTypeID)); break; } case decls_block::INOUT_TYPE: { TypeID objectTypeID; decls_block::LValueTypeLayout::readRecord(scratch, objectTypeID); typeOrOffset = InOutType::get(getType(objectTypeID)); break; } case decls_block::REFERENCE_STORAGE_TYPE: { uint8_t rawOwnership; TypeID referentTypeID; decls_block::ReferenceStorageTypeLayout::readRecord(scratch, rawOwnership, referentTypeID); auto ownership = getActualOwnership((serialization::Ownership) rawOwnership); if (!ownership.hasValue()) { error(); break; } typeOrOffset = ReferenceStorageType::get(getType(referentTypeID), ownership.getValue(), ctx); break; } case decls_block::ARCHETYPE_TYPE: { GenericEnvironmentID envID; TypeID interfaceTypeID; decls_block::ArchetypeTypeLayout::readRecord(scratch, envID, interfaceTypeID); auto env = getGenericEnvironment(envID); if (!env) { error(); break; } Type interfaceType = getType(interfaceTypeID); Type contextType = env->mapTypeIntoContext(interfaceType); typeOrOffset = contextType; if (contextType->hasError()) { error(); break; } break; } case decls_block::OPENED_EXISTENTIAL_TYPE: { TypeID existentialID; decls_block::OpenedExistentialTypeLayout::readRecord(scratch, existentialID); typeOrOffset = ArchetypeType::getOpened(getType(existentialID)); break; } case decls_block::GENERIC_TYPE_PARAM_TYPE: { DeclID declIDOrDepth; unsigned indexPlusOne; decls_block::GenericTypeParamTypeLayout::readRecord(scratch, declIDOrDepth, indexPlusOne); if (indexPlusOne == 0) { auto genericParam = dyn_cast_or_null(getDecl(declIDOrDepth)); if (!genericParam) { error(); return nullptr; } // See if we triggered deserialization through our conformances. if (typeOrOffset.isComplete()) break; typeOrOffset = genericParam->getDeclaredInterfaceType(); break; } typeOrOffset = GenericTypeParamType::get(declIDOrDepth,indexPlusOne-1,ctx); break; } case decls_block::PROTOCOL_COMPOSITION_TYPE: { bool hasExplicitAnyObject; ArrayRef rawProtocolIDs; decls_block::ProtocolCompositionTypeLayout::readRecord(scratch, hasExplicitAnyObject, rawProtocolIDs); SmallVector protocols; for (TypeID protoID : rawProtocolIDs) protocols.push_back(getType(protoID)); typeOrOffset = ProtocolCompositionType::get(ctx, protocols, hasExplicitAnyObject); break; } case decls_block::DEPENDENT_MEMBER_TYPE: { TypeID baseID; DeclID assocTypeID; decls_block::DependentMemberTypeLayout::readRecord(scratch, baseID, assocTypeID); typeOrOffset = DependentMemberType::get( getType(baseID), cast(getDecl(assocTypeID))); break; } case decls_block::BOUND_GENERIC_TYPE: { DeclID declID; TypeID parentID; ArrayRef rawArgumentIDs; decls_block::BoundGenericTypeLayout::readRecord(scratch, declID, parentID, rawArgumentIDs); auto nominal = cast(getDecl(declID)); auto parentTy = getType(parentID); SmallVector genericArgs; for (TypeID type : rawArgumentIDs) genericArgs.push_back(getType(type)); auto boundTy = BoundGenericType::get(nominal, parentTy, genericArgs); typeOrOffset = boundTy; break; } case decls_block::GENERIC_FUNCTION_TYPE: { TypeID inputID; TypeID resultID; uint8_t rawRep; bool throws = false; ArrayRef genericParamIDs; decls_block::GenericFunctionTypeLayout::readRecord(scratch, inputID, resultID, rawRep, throws, genericParamIDs); auto rep = getActualFunctionTypeRepresentation(rawRep); if (!rep.hasValue()) { error(); return nullptr; } // Read the generic parameters. SmallVector genericParams; for (auto paramID : genericParamIDs) { auto param = dyn_cast_or_null( getType(paramID).getPointer()); if (!param) { error(); break; } genericParams.push_back(param); } // Read the generic requirements. SmallVector requirements; readGenericRequirements(requirements, DeclTypeCursor); auto info = GenericFunctionType::ExtInfo(*rep, throws); auto sig = GenericSignature::get(genericParams, requirements); typeOrOffset = GenericFunctionType::get(sig, getType(inputID), getType(resultID), info); break; } case decls_block::SIL_BLOCK_STORAGE_TYPE: { TypeID captureID; decls_block::SILBlockStorageTypeLayout::readRecord(scratch, captureID); typeOrOffset = SILBlockStorageType::get(getType(captureID) ->getCanonicalType()); break; } case decls_block::SIL_BOX_TYPE: { SILLayoutID layoutID; decls_block::SILBoxTypeLayout::readRecord(scratch, layoutID); // Get the layout. auto getLayout = [&]() -> SILLayout * { assert(layoutID > 0 && layoutID <= SILLayouts.size() && "invalid layout ID"); auto &layoutOrOffset = SILLayouts[layoutID - 1]; if (layoutOrOffset.isComplete()) { return layoutOrOffset; } BCOffsetRAII saveOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(layoutOrOffset); auto layout = readSILLayout(DeclTypeCursor); if (!layout) { error(); return nullptr; } layoutOrOffset = layout; return layout; }; auto layout = getLayout(); if (!layout) return nullptr; SmallVector genericArgs; if (auto sig = layout->getGenericSignature()) { for (unsigned i : range(sig->getSubstitutionListSize())) { (void)i; auto sub = maybeReadSubstitution(DeclTypeCursor); if (!sub) { error(); return nullptr; } genericArgs.push_back( Substitution(sub->getReplacement()->getCanonicalType(), sub->getConformances())); } } typeOrOffset = SILBoxType::get(getContext(), layout, genericArgs); break; } case decls_block::SIL_FUNCTION_TYPE: { uint8_t rawCalleeConvention; uint8_t rawRepresentation; bool pseudogeneric = false; bool hasErrorResult; unsigned numParams; unsigned numResults; ArrayRef variableData; decls_block::SILFunctionTypeLayout::readRecord(scratch, rawCalleeConvention, rawRepresentation, pseudogeneric, hasErrorResult, numParams, numResults, variableData); // Process the ExtInfo. auto representation = getActualSILFunctionTypeRepresentation(rawRepresentation); if (!representation.hasValue()) { error(); return nullptr; } SILFunctionType::ExtInfo extInfo(*representation, pseudogeneric); // Process the callee convention. auto calleeConvention = getActualParameterConvention(rawCalleeConvention); if (!calleeConvention.hasValue()) { error(); return nullptr; } auto processParameter = [&](TypeID typeID, uint64_t rawConvention) -> Optional { auto convention = getActualParameterConvention(rawConvention); auto type = getType(typeID); if (!convention || !type) return None; return SILParameterInfo(type->getCanonicalType(), *convention); }; auto processResult = [&](TypeID typeID, uint64_t rawConvention) -> Optional { auto convention = getActualResultConvention(rawConvention); auto type = getType(typeID); if (!convention || !type) return None; return SILResultInfo(type->getCanonicalType(), *convention); }; // Bounds check. FIXME: overflow if (2 * numParams + 2 * numResults + 2 * unsigned(hasErrorResult) > variableData.size()) { error(); return nullptr; } unsigned nextVariableDataIndex = 0; // Process the parameters. SmallVector allParams; allParams.reserve(numParams); for (unsigned i = 0; i != numParams; ++i) { auto typeID = variableData[nextVariableDataIndex++]; auto rawConvention = variableData[nextVariableDataIndex++]; auto param = processParameter(typeID, rawConvention); if (!param) { error(); return nullptr; } allParams.push_back(*param); } // Process the results. SmallVector allResults; allParams.reserve(numResults); for (unsigned i = 0; i != numResults; ++i) { auto typeID = variableData[nextVariableDataIndex++]; auto rawConvention = variableData[nextVariableDataIndex++]; auto result = processResult(typeID, rawConvention); if (!result) { error(); return nullptr; } allResults.push_back(*result); } // Process the error result. Optional errorResult; if (hasErrorResult) { auto typeID = variableData[nextVariableDataIndex++]; auto rawConvention = variableData[nextVariableDataIndex++]; errorResult = processResult(typeID, rawConvention); if (!errorResult) { error(); return nullptr; } } // Process the generic signature parameters. SmallVector genericParamTypes; for (auto id : variableData.slice(nextVariableDataIndex)) { genericParamTypes.push_back( cast(getType(id)->getCanonicalType())); } // Read the generic requirements, if any. SmallVector requirements; readGenericRequirements(requirements, DeclTypeCursor); GenericSignature *genericSig = nullptr; if (!genericParamTypes.empty() || !requirements.empty()) genericSig = GenericSignature::get(genericParamTypes, requirements, /*isKnownCanonical=*/true); typeOrOffset = SILFunctionType::get(genericSig, extInfo, calleeConvention.getValue(), allParams, allResults, errorResult, ctx); break; } case decls_block::ARRAY_SLICE_TYPE: { TypeID baseID; decls_block::ArraySliceTypeLayout::readRecord(scratch, baseID); auto sliceTy = ArraySliceType::get(getType(baseID)); typeOrOffset = sliceTy; break; } case decls_block::DICTIONARY_TYPE: { TypeID keyID, valueID; decls_block::DictionaryTypeLayout::readRecord(scratch, keyID, valueID); auto dictTy = DictionaryType::get(getType(keyID), getType(valueID)); typeOrOffset = dictTy; break; } case decls_block::OPTIONAL_TYPE: { TypeID baseID; decls_block::OptionalTypeLayout::readRecord(scratch, baseID); auto optionalTy = OptionalType::get(getType(baseID)); typeOrOffset = optionalTy; break; } case decls_block::UNCHECKED_OPTIONAL_TYPE: { TypeID baseID; decls_block::ImplicitlyUnwrappedOptionalTypeLayout::readRecord(scratch, baseID); auto optionalTy = ImplicitlyUnwrappedOptionalType::get(getType(baseID)); typeOrOffset = optionalTy; break; } case decls_block::UNBOUND_GENERIC_TYPE: { DeclID genericID; TypeID parentID; decls_block::UnboundGenericTypeLayout::readRecord(scratch, genericID, parentID); auto genericDecl = cast(getDecl(genericID)); typeOrOffset = UnboundGenericType::get(genericDecl, getType(parentID), ctx); break; } default: // We don't know how to deserialize this kind of type. error(); return nullptr; } #ifndef NDEBUG PrettyStackTraceType trace(ctx, "deserializing", typeOrOffset.get()); if (typeOrOffset.get()->hasError()) { typeOrOffset.get()->dump(); llvm_unreachable("deserialization produced an invalid type " "(rdar://problem/30382791)"); } #endif // Invoke the callback on the deserialized type. DeserializedTypeCallback(typeOrOffset); return typeOrOffset; } void ModuleFile::loadAllMembers(Decl *container, uint64_t contextData) { PrettyStackTraceDecl trace("loading members for", container); ++NumMemberListsLoaded; IterableDeclContext *IDC; if (auto *nominal = dyn_cast(container)) IDC = nominal; else IDC = cast(container); BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(contextData); auto entry = DeclTypeCursor.advance(); if (entry.Kind != llvm::BitstreamEntry::Record) { error(); return; } SmallVector memberIDBuffer; unsigned kind = DeclTypeCursor.readRecord(entry.ID, memberIDBuffer); assert(kind == decls_block::MEMBERS); (void)kind; ArrayRef rawMemberIDs; decls_block::MembersLayout::readRecord(memberIDBuffer, rawMemberIDs); if (rawMemberIDs.empty()) return; SmallVector members; members.reserve(rawMemberIDs.size()); for (DeclID rawID : rawMemberIDs) { Expected next = getDeclChecked(rawID); if (!next) { if (!getContext().LangOpts.EnableDeserializationRecovery) fatal(next.takeError()); // Drop the member if it had a problem. if (auto *containingClass = dyn_cast(container)) { auto handleMissingDesignatedInit = [containingClass](const DeclDeserializationError &error) { if (error.getKind() != OverrideError::DesignatedInitializer) return; containingClass->setHasMissingDesignatedInitializers(); }; llvm::handleAllErrors(next.takeError(), handleMissingDesignatedInit); } else { llvm::consumeError(next.takeError()); } continue; } assert(next.get() && "unchecked error deserializing next member"); members.push_back(next.get()); } for (auto member : members) IDC->addMember(member); if (auto *proto = dyn_cast(container)) { PrettyStackTraceDecl trace("reading default witness table for", proto); bool Err = readDefaultWitnessTable(proto); assert(!Err && "unable to read default witness table"); (void)Err; } } void ModuleFile::loadAllConformances(const Decl *D, uint64_t contextData, SmallVectorImpl &conformances) { PrettyStackTraceDecl trace("loading conformances for", D); uint64_t numConformances; uint64_t bitPosition; std::tie(numConformances, bitPosition) = decodeLazyConformanceContextData(contextData); BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(bitPosition); while (numConformances--) { auto conf = readConformance(DeclTypeCursor); if (conf.isConcrete()) conformances.push_back(conf.getConcrete()); } } TypeLoc ModuleFile::loadAssociatedTypeDefault(const swift::AssociatedTypeDecl *ATD, uint64_t contextData) { return TypeLoc::withoutLoc(getType(contextData)); } void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance, uint64_t contextData) { using namespace decls_block; // Find the conformance record. BCOffsetRAII restoreOffset(DeclTypeCursor); DeclTypeCursor.JumpToBit(contextData); auto entry = DeclTypeCursor.advance(); assert(entry.Kind == llvm::BitstreamEntry::Record && "registered lazy loader incorrectly"); DeclID protoID; DeclContextID contextID; unsigned valueCount, typeCount; ArrayRef rawIDs; SmallVector scratch; unsigned kind = DeclTypeCursor.readRecord(entry.ID, scratch); (void) kind; assert(kind == NORMAL_PROTOCOL_CONFORMANCE && "registered lazy loader incorrectly"); NormalProtocolConformanceLayout::readRecord(scratch, protoID, contextID, valueCount, typeCount, rawIDs); // Skip requirement signature conformances. auto proto = conformance->getProtocol(); for (auto req : proto->getRequirementSignature()->getRequirements()) { if (req.getKind() == RequirementKind::Conformance) { (void)readConformance(DeclTypeCursor); } } ArrayRef::iterator rawIDIter = rawIDs.begin(); while (valueCount--) { auto req = cast(getDecl(*rawIDIter++)); auto witness = cast_or_null(getDecl(*rawIDIter++)); assert(witness || req->getAttrs().hasAttribute() || req->getAttrs().isUnavailable(getContext())); if (!witness) { conformance->setWitness(req, Witness()); continue; } // Generic signature and environment. GenericSignature *syntheticSig = nullptr; GenericEnvironment *syntheticEnv = nullptr; // Requirement -> synthetic map. SmallVector reqToSyntheticSubs; if (unsigned numGenericParams = *rawIDIter++) { // Generic parameters of the synthetic environment. SmallVector genericParams; while (numGenericParams--) { genericParams.push_back( getType(*rawIDIter++)->castTo()); } // Generic requirements of the synthetic environment. SmallVector requirements; readGenericRequirements(requirements, DeclTypeCursor); // Form the generic signature for the synthetic environment. syntheticSig = GenericSignature::get(genericParams, requirements); // Create the synthetic environment. syntheticEnv = syntheticSig->createGenericEnvironment(*getAssociatedModule()); // Requirement -> synthetic substitutions. if (unsigned numReqSubstitutions = *rawIDIter++) { while (numReqSubstitutions--) { auto sub = maybeReadSubstitution(DeclTypeCursor, nullptr); reqToSyntheticSubs.push_back(*sub); } } } // Witness substitutions. SmallVector witnessSubstitutions; if (unsigned numWitnessSubstitutions = *rawIDIter++) { while (numWitnessSubstitutions--) { auto sub = maybeReadSubstitution(DeclTypeCursor, syntheticEnv); witnessSubstitutions.push_back(*sub); } } // Handle simple witnesses. if (witnessSubstitutions.empty() && !syntheticSig && !syntheticEnv && reqToSyntheticSubs.empty()) { conformance->setWitness(req, Witness(witness)); continue; } // Set the witness. conformance->setWitness(req, Witness(witness, witnessSubstitutions, syntheticEnv, reqToSyntheticSubs)); } assert(rawIDIter <= rawIDs.end() && "read too much"); TypeWitnessMap typeWitnesses; while (typeCount--) { // FIXME: We don't actually want to allocate an archetype here; we just // want to get an access path within the protocol. auto first = cast(getDecl(*rawIDIter++)); auto second = getType(*rawIDIter++); auto third = cast_or_null(getDecl(*rawIDIter++)); if (isa(third) && third->getModuleContext() != getAssociatedModule() && !third->getDeclaredInterfaceType()->isEqual(second)) { // Conservatively drop references to typealiases in other modules // that may have changed. This may also drop references to typealiases // that /haven't/ changed but just happen to have generics in them, but // in practice having a declaration here isn't actually required by the // rest of the compiler. third = nullptr; } typeWitnesses[first] = std::make_pair(second, third); } assert(rawIDIter <= rawIDs.end() && "read too much"); // Set type witnesses. for (auto typeWitness : typeWitnesses) { conformance->setTypeWitness(typeWitness.first, typeWitness.second.first, typeWitness.second.second); } } GenericEnvironment *ModuleFile::loadGenericEnvironment(const DeclContext *decl, uint64_t contextData) { return getGenericEnvironment(contextData); } static Optional decodeRawStableForeignErrorConventionKind(uint8_t kind) { switch (kind) { case static_cast(ForeignErrorConventionKind::ZeroResult): return ForeignErrorConvention::ZeroResult; case static_cast(ForeignErrorConventionKind::NonZeroResult): return ForeignErrorConvention::NonZeroResult; case static_cast(ForeignErrorConventionKind::ZeroPreservedResult): return ForeignErrorConvention::ZeroPreservedResult; case static_cast(ForeignErrorConventionKind::NilResult): return ForeignErrorConvention::NilResult; case static_cast(ForeignErrorConventionKind::NonNilError): return ForeignErrorConvention::NonNilError; default: return None; } } Optional ModuleFile::maybeReadForeignErrorConvention() { using namespace decls_block; SmallVector scratch; BCOffsetRAII restoreOffset(DeclTypeCursor); auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (next.Kind != llvm::BitstreamEntry::Record) return None; unsigned recKind = DeclTypeCursor.readRecord(next.ID, scratch); switch (recKind) { case FOREIGN_ERROR_CONVENTION: restoreOffset.reset(); break; default: return None; } uint8_t rawKind; bool isOwned; bool isReplaced; unsigned errorParameterIndex; TypeID errorParameterTypeID; TypeID resultTypeID; ForeignErrorConventionLayout::readRecord(scratch, rawKind, isOwned, isReplaced, errorParameterIndex, errorParameterTypeID, resultTypeID); ForeignErrorConvention::Kind kind; if (auto optKind = decodeRawStableForeignErrorConventionKind(rawKind)) kind = *optKind; else { error(); return None; } Type errorParameterType = getType(errorParameterTypeID); CanType canErrorParameterType; if (errorParameterType) canErrorParameterType = errorParameterType->getCanonicalType(); Type resultType = getType(resultTypeID); CanType canResultType; if (resultType) canResultType = resultType->getCanonicalType(); auto owned = isOwned ? ForeignErrorConvention::IsOwned : ForeignErrorConvention::IsNotOwned; auto replaced = ForeignErrorConvention::IsReplaced_t(isOwned); switch (kind) { case ForeignErrorConvention::ZeroResult: return ForeignErrorConvention::getZeroResult(errorParameterIndex, owned, replaced, canErrorParameterType, canResultType); case ForeignErrorConvention::NonZeroResult: return ForeignErrorConvention::getNonZeroResult(errorParameterIndex, owned, replaced, canErrorParameterType, canResultType); case ForeignErrorConvention::ZeroPreservedResult: return ForeignErrorConvention::getZeroPreservedResult(errorParameterIndex, owned, replaced, canErrorParameterType); case ForeignErrorConvention::NilResult: return ForeignErrorConvention::getNilResult(errorParameterIndex, owned, replaced, canErrorParameterType); case ForeignErrorConvention::NonNilError: return ForeignErrorConvention::getNonNilError(errorParameterIndex, owned, replaced, canErrorParameterType); } llvm_unreachable("Unhandled ForeignErrorConvention in switch."); }