//===--- ModuleFile.h - Info about a loaded serialized module ---*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// #ifndef SWIFT_SERIALIZATION_MODULEFILE_H #define SWIFT_SERIALIZATION_MODULEFILE_H #include "ModuleFileSharedCore.h" #include "ModuleFormat.h" #include "swift/AST/FileUnit.h" #include "swift/AST/Identifier.h" #include "swift/AST/LazyResolver.h" #include "swift/AST/LinkLibrary.h" #include "swift/AST/Module.h" #include "swift/AST/SILLayout.h" #include "swift/Basic/BasicSourceInfo.h" #include "swift/Basic/LLVM.h" #include "swift/Serialization/Validation.h" #include "clang/AST/Type.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" namespace llvm { class BitstreamCursor; class BitstreamReader; class MemoryBuffer; template class OnDiskIterableChainedHashTable; } namespace swift { class Decl; class FileUnit; class ModuleDecl; class Pattern; class ProtocolConformance; /// A serialized module, along with the tools to access it. class ModuleFile : public LazyMemberLoader, public LazyConformanceLoader { friend class SerializedASTFile; friend class DeclDeserializer; friend class TypeDeserializer; friend class SILDeserializer; friend class ProtocolConformanceDeserializer; template friend class serialization::decls_block::detail::TypeRecordDispatch; friend struct serialization::decls_block::detail::function_deserializer; using Status = serialization::Status; using TypeID = serialization::TypeID; using ProtocolConformanceID = serialization::ProtocolConformanceID; /// The core data of a serialized module file. This is accessed as immutable /// and thread-safe. const std::shared_ptr Core; /// A reference back to the AST representation of the file. FileUnit *FileContext = nullptr; /// The module that this module is an overlay of, if any. ModuleDecl *UnderlyingModule = nullptr; /// The cursor used to lazily load things from the file. llvm::BitstreamCursor DeclTypeCursor; llvm::BitstreamCursor SILCursor; llvm::BitstreamCursor SILIndexCursor; llvm::BitstreamCursor DeclMemberTablesCursor; public: static std::unique_ptr getModuleName(ASTContext &Ctx, StringRef modulePath, std::string &Name); /// Represents another module that has been imported as a dependency. class Dependency { public: const ModuleFileSharedCore::Dependency &Core; llvm::Optional Import = llvm::None; SmallVector spiGroups; Dependency(const ModuleFileSharedCore::Dependency &coreDependency) : Core(coreDependency) {} bool isLoaded() const { return Import.has_value() && Import->importedModule != nullptr; } bool isExported() const { return Core.isExported(); } bool isImplementationOnly() const { return Core.isImplementationOnly(); } bool isInternalOrBelow() const { return Core.isInternalOrBelow(); } bool isPackageOnly() const { return Core.isPackageOnly(); } bool isHeader() const { return Core.isHeader(); } bool isScoped() const { return Core.isScoped(); } }; private: /// All modules this module depends on. SmallVector Dependencies; public: template class Serialized { private: using RawBitOffset = uint64_t; using ImplTy = PointerUnion; ImplTy Value; public: /*implicit*/ Serialized(serialization::BitOffset offset) : Value(offset) {} bool isComplete() const { return Value.template is(); } T get() const { return Value.template get(); } /*implicit*/ operator T() const { return get(); } /*implicit*/ operator serialization::BitOffset() const { return Value.template get(); } /*implicit*/ operator RawBitOffset() const { return Value.template get(); } Serialized &operator=(T deserialized) { assert(!isComplete() || ImplTy(deserialized) == Value); Value = deserialized; return *this; } void uncheckedOverwrite(T t) { Value = t; } }; /// A class for holding a value that can be partially deserialized. /// /// This class assumes that "T()" is not a valid deserialized value. template class PartiallySerialized { private: using RawBitOffset = decltype(DeclTypeCursor.GetCurrentBitNo()); /// The deserialized value. T Value; /// The offset. unsigned Offset : 31; unsigned IsFullyDeserialized : 1; public: /*implicit*/ PartiallySerialized(serialization::BitOffset offset) : Value(), Offset(offset), IsFullyDeserialized(0) {} /*implicit*/ PartiallySerialized(RawBitOffset offset) : Value(), Offset(static_cast(offset)), IsFullyDeserialized(0) { assert(Offset == offset && "offset is too large"); } bool isDeserialized() const { return Value != T(); } bool isFullyDeserialized() const { return isDeserialized() && IsFullyDeserialized; } serialization::BitOffset getOffset() const { assert(!isFullyDeserialized()); return Offset; } T get() const { assert(isDeserialized()); return Value; } void reset() { IsFullyDeserialized = 0; Value = T(); } void set(T value, bool isFullyDeserialized) { assert(!isDeserialized() || Value == value); Value = value; IsFullyDeserialized = isFullyDeserialized; } }; private: /// An allocator for buffers owned by the file. llvm::BumpPtrAllocator Allocator; /// Allocates a buffer using #Allocator and initializes it with the contents /// of the container \p rawData, then stores it in \p buffer. /// /// \p buffer is passed as an argument rather than returned so that the /// element type can be inferred. template void allocateBuffer(MutableArrayRef &buffer, const RawData &rawData); /// Allocates a buffer using #Allocator and initializes it with the contents /// of the container \p rawData, then stores it in \p buffer. /// /// \p buffer is passed as an argument rather than returned so that the /// element type can be inferred. template void allocateBuffer(ArrayRef &buffer, const RawData &rawData) { assert(buffer.empty()); MutableArrayRef result; allocateBuffer(result, rawData); buffer = result; } /// Decls referenced by this module. MutableArrayRef> Decls; /// Local DeclContexts referenced by this module. MutableArrayRef> LocalDeclContexts; /// Protocol conformances referenced by this module. MutableArrayRef> Conformances; /// Pack conformances referenced by this module. MutableArrayRef> PackConformances; /// SILLayouts referenced by this module. MutableArrayRef> SILLayouts; /// Types referenced by this module. MutableArrayRef> Types; /// Clang types referenced by this module. MutableArrayRef> ClangTypes; /// Generic signatures referenced by this module. MutableArrayRef> GenericSignatures; /// Generic environments referenced by this module. MutableArrayRef> GenericEnvironments; /// Substitution maps referenced by this module. MutableArrayRef> SubstitutionMaps; uint64_t createLazyConformanceLoaderToken(ArrayRef ids); ArrayRef claimLazyConformanceLoaderToken(uint64_t token); /// Represents an identifier that may or may not have been deserialized yet. /// /// If \c Ident is empty, the identifier has not been loaded yet. class SerializedIdentifier { public: Identifier Ident; unsigned Offset; template /*implicit*/ SerializedIdentifier(IntTy rawOffset) : Offset(static_cast(rawOffset)) { assert(Offset == rawOffset && "not enough bits"); } }; /// Identifiers referenced by this module. MutableArrayRef Identifiers; using SerializedDeclMembersTable = ModuleFileSharedCore::SerializedDeclMembersTable; llvm::DenseMap> DeclMembersTables; llvm::DenseMap PrivateDiscriminatorsByValue; llvm::DenseMap FilenamesForPrivateValues; TinyPtrVector ImportDecls; /// Maps USRs to their deserialized comment object. mutable llvm::StringMap< std::unique_ptr> CommentsCache; struct ModuleBits { /// Whether or not ImportDecls is valid. unsigned ComputedImportDecls : 1; /// Whether an error has been detected setting up this module file. unsigned HasError : 1; // Explicitly pad out to the next word boundary. unsigned : 0; } Bits = {}; static_assert(sizeof(ModuleBits) <= 8, "The bit set should be small"); bool hasError() const { return Bits.HasError || Core->hasError(); } /// Whether or not this module file comes from a context that had a main entry point. bool hasEntryPoint() const { return Core->Bits.HasEntryPoint; } /// The decl ID of the main class in this module file, if it has one. unsigned getEntryPointDeclID() const { return Core->Bits.EntryPointDeclID; } /// Creates a new AST node to represent a deserialized decl. template T *createDecl(Args &&... args); Decl *handleErrorAndSupplyMissingMiscMember(llvm::Error &&error) const; Decl *handleErrorAndSupplyMissingMember(ASTContext &context, Decl *container, llvm::Error &&error) const; public: /// Change the status of the current module. Status error(Status issue) { assert(issue != Status::Valid); assert((issue != Status::Malformed || !FileContext) && "too late to complain about the well-formedness of the module"); Bits.HasError = true; return issue; } /// Enrich \c error with contextual information, emits a fatal diagnostic in /// the ASTContext's DiagnosticsEngine, and return the augmented error. /// /// The `diagnoseFatal` methods return only in LLDB where high error /// tolerance is expected, or when hitting a project error. During normal /// compilation, most calls won't return and lead to a compiler crash. llvm::Error diagnoseFatal(llvm::Error error) const; /// Emit a generic deserialization error via \c diagnoseFatal(). llvm::Error diagnoseFatal() const { return diagnoseFatal(createFatalError()); } /// Emit a fatal error via \c diagnoseFatal() and consume it. void diagnoseAndConsumeFatal(llvm::Error error) const { llvm::consumeError(diagnoseFatal(std::move(error))); } /// Emit a generic fatal error via \c diagnoseFatal() and consume it. void diagnoseAndConsumeFatal() const { llvm::consumeError(diagnoseFatal()); } /// Use this in \p void functions as: /// /// if (diagnoseAndConsumeFatalIfNotSuccess(...)) return; bool diagnoseAndConsumeFatalIfNotSuccess(llvm::Error error) const { if (!error) return false; llvm::consumeError(diagnoseFatal(std::move(error))); return true; } /// Use this in functions that return Expected as: /// /// if (auto error = diagnoseFatalIfNotSuccess(...)) return error; llvm::Error diagnoseFatalIfNotSuccess(llvm::Error error) const { if (!error) return error; return diagnoseFatal(std::move(error)); } /// Emit and return a string error via \c diagnoseFatal(). llvm::Error diagnoseFatal(StringRef msg) const { return diagnoseFatal(llvm::make_error( msg, llvm::inconvertibleErrorCode())); } /// Emit and consume a string error via \c diagnoseFatal(). void diagnoseAndConsumeFatal(StringRef msg) const { return llvm::consumeError(diagnoseFatal(msg)); } /// Consume errors that are usually safe to ignore because they /// are expected to support language features or caused by project /// misconfigurations. /// /// If the error is handled, success is returned, otherwise the original /// error is returned. llvm::Error consumeExpectedError(llvm::Error &&error); /// Report project errors as remarks if desired, otherwise drop the error /// silently. void diagnoseAndConsumeError(llvm::Error error) const; /// Report modularization error, either directly or indirectly if it /// caused a \c TypeError or \c ExtensionError. Returns any unhandled errors. llvm::Error diagnoseModularizationError(llvm::Error error, DiagnosticBehavior limit = DiagnosticBehavior::Fatal) const; /// Report an unexpected format error that could happen only from a /// memory-level inconsistency. Please prefer passing an error to /// `fatal(llvm::Error error)` when possible. static llvm::Error createFatalError( llvm::StringRef msg = "Memory corruption or serialization format inconsistency.") { return llvm::make_error(msg, llvm::inconvertibleErrorCode()); } /// Emit a fatal error and abort. This function is deprecated, try to use /// diagnoseFatal() instead. Clients such as LLDB really prefer not to be /// killed. // LLVM_DEPRECATED("Use diagnoseFatal and pass up the error instead.", // "diagnoseFatal") [[noreturn]] void fatal(llvm::Error error = createFatalError()) const; /// Emit a fatal error and abort. This function is deprecated, try to use /// diagnoseFatal() instead. Clients such as LLDB really prefer not to be /// killed. // LLVM_DEPRECATED("Use diagnoseFatal and pass up the error instead.", // "diagnoseFatal") [[noreturn]] void fatal(llvm::StringRef msg) const { fatal(createFatalError(msg)); } /// Emit a fatal error and abort if unexpected. Try to avoid using this /// function. See comment in \p fatal(). // LLVM_DEPRECATED("Use diagnoseFatal and pass up the error instead.", // "diagnoseFatal") template T fatalIfUnexpected(llvm::Expected expected) const { if (expected) return std::move(expected.get()); fatal(expected.takeError()); } /// Outputs information useful for diagnostics to \p out void outputDiagnosticInfo(llvm::raw_ostream &os) const; ASTContext &getContext() const { assert(FileContext && "no associated context yet"); return FileContext->getParentModule()->getASTContext(); } ModuleDecl *getAssociatedModule() const { assert(FileContext && "no associated context yet"); return FileContext->getParentModule(); } FileUnit *getFile() const { assert(FileContext && "no associated context yet"); return FileContext; } private: /// Recursively reads a pattern from \c DeclTypeCursor. llvm::Expected readPattern(DeclContext *owningDC); ParameterList *readParameterList(); /// Reads a generic param list from \c DeclTypeCursor. /// /// If the record at the cursor is not a generic param list, returns null /// without moving the cursor. GenericParamList *maybeReadGenericParams(DeclContext *DC); /// Reads a set of requirements from \c DeclTypeCursor. void deserializeGenericRequirements(ArrayRef scratch, unsigned &nextIndex, SmallVectorImpl &requirements); /// Reads a set of requirements from \c DeclTypeCursor, returns the first /// error, if any. llvm::Error deserializeGenericRequirementsChecked(ArrayRef scratch, unsigned &nextIndex, SmallVectorImpl &requirements); /// Read the requirement signature of a protocol, which consists of a list of /// generic requirements and a list of protocol typealias records. void readRequirementSignature(SmallVectorImpl &requirements, SmallVectorImpl &typeAliases, llvm::BitstreamCursor &Cursor); /// Read a list of associated type declarations in a protocol. void readAssociatedTypes( SmallVectorImpl &assocTypes, llvm::BitstreamCursor &Cursor); /// Read a list of primary associated type declarations in a protocol. void readPrimaryAssociatedTypes( SmallVectorImpl &assocTypes, llvm::BitstreamCursor &Cursor); /// Populates the protocol's default witness table. /// /// Returns true if there is an error. /// /// Note: this destroys the cursor's position in the stream. Furthermore, /// because it reads from the cursor, it is not possible to reset the cursor /// after reading. Nothing should ever follow a DEFAULT_WITNESS_TABLE record. bool readDefaultWitnessTable(ProtocolDecl *proto); /// Resolves a cross-reference, starting from the given module. /// /// Note: this destroys the cursor's position in the stream. Furthermore, /// because it reads from the cursor, it is not possible to reset the cursor /// after reading. Nothing should ever follow an XREF record except /// XREF_PATH_PIECE records. llvm::Expected resolveCrossReference(serialization::ModuleID MID, uint32_t pathLen); struct AccessorRecord { SmallVector IDs; }; /// Sets the accessors for \p storage based on \p rawStorageKind. void configureStorage(AbstractStorageDecl *storage, uint8_t rawOpaqueReadOwnership, uint8_t rawReadImpl, uint8_t rawWriteImpl, uint8_t rawReadWriteImpl, AccessorRecord &accessors); public: /// Constructs a new module. explicit ModuleFile(std::shared_ptr core); // Out of line to avoid instantiation OnDiskChainedHashTable here. ~ModuleFile(); /// The name of the module. StringRef getName() const { return Core->Name; } StringRef getModulePackageName() const { return Core->ModulePackageName; } StringRef getModuleExportAsName() const { return Core->ModuleExportAsName; } /// The ABI name of the module. StringRef getModuleABIName() const { return Core->ModuleABIName; } llvm::VersionTuple getUserModuleVersion() const { return Core->UserModuleVersion; } ArrayRef getAllowableClientNames() const { return Core->AllowableClientNames; } /// The Swift compatibility version in use when this module was built. const version::Version &getCompatibilityVersion() const { return Core->CompatibilityVersion; } /// Whether this module is compiled with `-enable-private-imports`. bool arePrivateImportsEnabled() const { return Core->Bits.ArePrivateImportsEnabled; } /// Is this module file actually a .sib file? .sib files are serialized SIL at /// arbitrary granularity and arbitrary stage; unlike serialized Swift /// modules, which are assumed to contain canonical SIL for an entire module. bool isSIB() const { return Core->Bits.IsSIB; } /// Whether this module file is compiled with '-enable-testing'. bool isTestable() const { return Core->Bits.IsTestable; } /// Whether this module is compiled as static library. bool isStaticLibrary() const { return Core->Bits.IsStaticLibrary; } /// Whether this module was built with -experimental-hermetic-seal-at-link. bool hasHermeticSealAtLink() const { return Core->Bits.HasHermeticSealAtLink; } /// Whether this module was built with C++ interoperability enabled. bool hasCxxInteroperability() const { return Core->Bits.HasCxxInteroperability; } /// Whether the module is resilient. ('-enable-library-evolution') ResilienceStrategy getResilienceStrategy() const { return ResilienceStrategy(Core->Bits.ResilienceStrategy); } bool isBuiltFromInterface() const { return Core->Bits.IsBuiltFromInterface; } /// Whether this module is compiled with implicit dynamic. bool isImplicitDynamicEnabled() const { return Core->Bits.IsImplicitDynamicEnabled; } /// Whether this module is compiled while allowing errors /// ('-experimental-allow-module-with-compiler-errors'). bool compiledAllowingCompilerErrors() const { return Core->Bits.IsAllowModuleWithCompilerErrorsEnabled; } /// Whether currently allowing modules with compiler errors (ie. /// '-experimental-allow-module-with-compiler-errors' is currently enabled). bool allowCompilerErrors() const; /// \c true if this module has incremental dependency information. bool hasIncrementalInfo() const { return Core->hasIncrementalInfo(); } /// \c true if this module has a corresponding .swiftsourceinfo file. bool hasSourceInfoFile() const { return Core->hasSourceInfoFile(); } /// \c true if this module has information from a corresponding /// .swiftsourceinfo file (ie. the file exists and has been read). bool hasSourceInfo() const { return Core->hasSourceInfo(); } /// \c true if this module was built with complete checking for concurrency. bool isConcurrencyChecked() const { return Core->isConcurrencyChecked(); } /// Associates this module file with the AST node representing it. /// /// Checks that the file is compatible with the AST module it's being loaded /// into, loads any dependencies needed to understand the module, and updates /// the ASTContext and ClangImporter with search paths and other information /// from the module. /// /// \param file The FileUnit that represents this file's place in the AST. /// \param diagLoc A location used for diagnostics that occur during loading. /// This does not include diagnostics about \e this file failing to load, /// but rather other things that might be imported as part of bringing the /// file into the AST. /// \param recoverFromIncompatibility Whether to associate the file /// regardless of the compatibility with the AST module. Still returns the /// underlying error for diagnostic purposes but does not set the error bit. /// /// \returns any error that occurred during association, such as being /// compiled for a different OS. Status associateWithFileContext(FileUnit *file, SourceLoc diagLoc, bool recoverFromIncompatibility); /// Load dependencies of this module. /// /// \param file The FileUnit that represents this file's place in the AST. /// \param diagLoc A location used for diagnostics that occur during loading. /// This does not include diagnostics about \e this file failing to load, /// but rather other things that might be imported as part of bringing the /// file into the AST. /// /// \returns any error that occurred during loading dependencies. Status loadDependenciesForFileContext(const FileUnit *file, SourceLoc diagLoc, bool forTestable); /// How should \p dependency be loaded for a transitive import via \c this? ModuleLoadingBehavior getTransitiveLoadingBehavior(const Dependency &dependency, bool forTestable) const; /// Generate a \c SourceLoc pointing at the loaded swiftmodule file. SourceLoc getSourceLoc() const; /// Returns `true` if there is a buffer that might contain source code where /// other parts of the compiler could have emitted diagnostics, to indicate /// that the object must be kept alive as long as the diagnostics exist. /// /// Should only be called when a failure has been reported from /// ModuleFile::load or ModuleFile::associateWithFileContext. bool mayHaveDiagnosticsPointingAtBuffer() const; /// Returns the list of modules this module depends on. ArrayRef getDependencies() const { return Dependencies; } /// The module that this module is an overlay for, if any. ModuleDecl *getUnderlyingModule() const { return UnderlyingModule; } /// Searches the module's top-level decls for the given identifier. void lookupValue(DeclName name, SmallVectorImpl &results); /// Searches the module's local type decls for the given mangled name. TypeDecl *lookupLocalType(StringRef MangledName); /// Search the module's opaque return type decls for the one corresponding to /// the given mangled name. OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName); /// Searches the module's nested type decls table for the given member of /// the given type. TypeDecl *lookupNestedType(Identifier name, const NominalTypeDecl *parent); /// Searches the module's operators for one with the given name and fixity. /// /// If none is found, returns null. OperatorDecl *lookupOperator(Identifier name, OperatorFixity fixity); /// Searches the module's precedence groups for one with the given /// name and fixity. /// /// If none is found, returns null. PrecedenceGroupDecl *lookupPrecedenceGroup(Identifier name); /// Adds any imported modules to the given vector. void getImportedModules(SmallVectorImpl &results, ModuleDecl::ImportFilter filter); void getImportDecls(SmallVectorImpl &Results); /// Reports all visible top-level members in this module. void lookupVisibleDecls(ImportPath::Access accessPath, VisibleDeclConsumer &consumer, NLKind lookupKind); /// Loads extensions for the given decl. /// /// Note that this may cause other decls to load as well. void loadExtensions(NominalTypeDecl *nominal); /// Load the methods within the given nominal type that produce /// Objective-C class or instance methods with the given selector. /// /// \param typeDecl The nominal in which we are searching for @objc methods. /// The search only considers this type and its extensions; not any /// superclasses. /// /// \param selector The selector to search for. /// /// \param isInstanceMethod Whether we are looking for an instance method /// (vs. a class method). /// /// \param methods The list of @objc methods in this class that have this /// selector and are instance/class methods as requested. void loadObjCMethods(NominalTypeDecl *typeDecl, ObjCSelector selector, bool isInstanceMethod, llvm::TinyPtrVector &methods); /// Loads all derivative function configurations for the given /// AbstractFunctionDecl. void loadDerivativeFunctionConfigurations( AbstractFunctionDecl *originalAFD, llvm::SetVector &results); /// Reports all class members in the module to the given consumer. /// /// This is intended for use with id-style lookup and code completion. void lookupClassMembers(ImportPath::Access accessPath, VisibleDeclConsumer &consumer); /// Adds class members in the module with the given name to the given vector. /// /// This is intended for use with id-style lookup. void lookupClassMember(ImportPath::Access accessPath, DeclName name, SmallVectorImpl &results); /// Find all Objective-C methods with the given selector. void lookupObjCMethods( ObjCSelector selector, SmallVectorImpl &results); /// Reports all link-time dependencies. void collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const; /// Adds all top-level decls to the given vector. /// /// \param Results Vector collecting the decls. /// /// \param matchAttributes Optional check on the attributes of a decl to /// filter which decls to fully deserialize. Only decls with accepted /// attributes are deserialized and added to Results. void getTopLevelDecls( SmallVectorImpl &Results, llvm::function_ref matchAttributes = nullptr); void getExportedPrespecializations(SmallVectorImpl &results); /// Adds all operators to the given vector. void getOperatorDecls(SmallVectorImpl &Results); /// Adds all precedence groups to the given vector. void getPrecedenceGroups(SmallVectorImpl &Results); /// Adds all local type decls to the given vector. void getLocalTypeDecls(SmallVectorImpl &Results); /// Add all opaque return type decls in the module to the given vector. void getOpaqueReturnTypeDecls(SmallVectorImpl &Results); /// Adds all top-level decls to the given vector. /// /// This includes all decls that should be displayed to clients of the module. /// This can differ from \c getTopLevelDecls, e.g. it returns decls from a /// shadowed clang module. void getDisplayDecls(SmallVectorImpl &results, bool recursive = false); StringRef getModuleFilename() const { if (!Core->ModuleInterfacePath.empty()) return Core->ModuleInterfacePath; return getModuleLoadedFilename(); } StringRef getModuleLoadedFilename() const { // FIXME: This seems fragile, maybe store the filename separately? return Core->ModuleInputBuffer->getBufferIdentifier(); } StringRef getModuleSourceFilename() const { if (!Core->CorrespondingInterfacePath.empty()) return Core->CorrespondingInterfacePath; return getModuleFilename(); } StringRef getTargetTriple() const { return Core->TargetTriple; } /// AST-verify imported decls. /// /// Has no effect in NDEBUG builds. void verify() const; virtual void loadAllMembers(Decl *D, uint64_t contextData) override; virtual TinyPtrVector loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N, uint64_t contextData) override; virtual void loadAllConformances(const Decl *D, uint64_t contextData, SmallVectorImpl &Conforms) override; virtual Type loadAssociatedTypeDefault(const AssociatedTypeDecl *ATD, uint64_t contextData) override; virtual ValueDecl * loadDynamicallyReplacedFunctionDecl(const DynamicReplacementAttr *DRA, uint64_t contextData) override; virtual ValueDecl *loadTargetFunctionDecl(const SpecializeAttr *attr, uint64_t contextData) override; virtual AbstractFunctionDecl * loadReferencedFunctionDecl(const DerivativeAttr *DA, uint64_t contextData) override; virtual Type loadTypeEraserType(const TypeEraserAttr *TRA, uint64_t contextData) override; virtual void finishNormalConformance(NormalProtocolConformance *conformance, uint64_t contextData) override; void loadRequirementSignature(const ProtocolDecl *proto, uint64_t contextData, SmallVectorImpl &requirements, SmallVectorImpl &typeAliases) override; void loadAssociatedTypes( const ProtocolDecl *proto, uint64_t contextData, SmallVectorImpl &assocTypes) override; void loadPrimaryAssociatedTypes( const ProtocolDecl *proto, uint64_t contextData, SmallVectorImpl &assocTypes) override; Optional getGroupNameById(unsigned Id) const; Optional getSourceFileNameById(unsigned Id) const; Optional getGroupNameForDecl(const Decl *D) const; Optional getSourceFileNameForDecl(const Decl *D) const; Optional getSourceOrderForDecl(const Decl *D) const; void collectAllGroups(SmallVectorImpl &Names) const; Optional getCommentForDecl(const Decl *D) const; bool hasLoadedSwiftDoc() const; Optional getCommentForDeclByUSR(StringRef USR) const; Optional getGroupNameByUSR(StringRef USR) const; Optional getExternalRawLocsForDecl(const Decl *D) const; Identifier getDiscriminatorForPrivateDecl(const Decl *D); Optional loadFingerprint(const IterableDeclContext *IDC) const; void collectBasicSourceFileInfo( llvm::function_ref callback) const; void collectSerializedSearchPath( llvm::function_ref callback) const; // MARK: Deserialization interface llvm::BitstreamCursor getSILCursor() const { return SILCursor; } llvm::BitstreamCursor getSILIndexCursor() const { return SILIndexCursor; } /// Returns the type with the given ID, deserializing it if needed. /// /// \sa getTypeChecked Type getType(serialization::TypeID TID); /// Returns the type with the given ID, deserializing it if needed. llvm::Expected getTypeChecked(serialization::TypeID TID); /// Returns the Clang type with the given ID, deserializing it if needed. llvm::Expected getClangType(serialization::ClangTypeID TID); /// Returns the base name with the given ID, deserializing it if needed. DeclBaseName getDeclBaseName(serialization::IdentifierID IID); /// Convenience method to retrieve the identifier backing the name with /// given ID. Asserts that the name with this ID is not special. Identifier getIdentifier(serialization::IdentifierID IID); /// Convenience method to retrieve the text of the name with the given ID. /// This can be used if the result doesn't need to be uniqued in the /// ASTContext. Asserts that the name with this ID is not special. StringRef getIdentifierText(serialization::IdentifierID IID); /// Returns the decl with the given ID, deserializing it if needed. /// /// \param DID The ID for the decl within this module. /// \sa getDeclChecked Decl *getDecl(serialization::DeclID DID); /// Returns the decl with the given ID, deserializing it if needed. /// /// \param DID The ID for the decl within this module. /// /// \param matchAttributes Optional check on the attributes of the decl to /// determine if it should be fully deserialized and returned. If the /// attributes fail the check, the decl is not deserialized and /// \c DeclAttributesDidNotMatch is returned. llvm::Expected getDeclChecked( serialization::DeclID DID, llvm::function_ref matchAttributes = nullptr); /// Returns the decl context with the given ID, deserializing it if needed. DeclContext *getDeclContext(serialization::DeclContextID DID); /// Returns the decl context with the given ID, deserializing it if needed, /// or the first error. llvm::Expected getDeclContextChecked(serialization::DeclContextID DCID); /// Returns the local decl context with the given ID, deserializing it if needed. llvm::Expected getLocalDeclContext(serialization::LocalDeclContextID DID); /// Returns the appropriate module for the given ID. ModuleDecl *getModule(serialization::ModuleID MID); /// Returns the appropriate module for the given name. /// /// If the name matches the name of the current module, a shadowed module /// is loaded instead. ModuleDecl *getModule(ImportPath::Module name, bool allowLoading = false); /// Returns the generic signature for the given ID. GenericSignature getGenericSignature(serialization::GenericSignatureID ID); /// Returns the generic signature for the given ID or the first error. llvm::Expected getGenericSignatureChecked(serialization::GenericSignatureID ID); /// Returns the generic environment for the given ID or the first error. llvm::Expected getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID); /// Returns the substitution map for the given ID, deserializing it if /// needed. SubstitutionMap getSubstitutionMap(serialization::SubstitutionMapID id); /// Returns the substitution map for the given ID, deserializing it if /// needed, or the first error. llvm::Expected getSubstitutionMapChecked(serialization::SubstitutionMapID id); /// Returns the protocol conformance for the given ID. ProtocolConformanceRef getConformance(serialization::ProtocolConformanceID id); /// Returns the protocol conformance for the given ID. llvm::Expected getConformanceChecked(serialization::ProtocolConformanceID id); /// Read a SILLayout from the given cursor. SILLayout *readSILLayout(llvm::BitstreamCursor &Cursor); /// Reads a foreign error convention from \c DeclTypeCursor, if present. Optional maybeReadForeignErrorConvention(); /// Reads a foreign async convention from \c DeclTypeCursor, if present. Optional maybeReadForeignAsyncConvention(); /// Reads inlinable body text from \c DeclTypeCursor, if present. Optional maybeReadInlinableBodyText(); /// Reads pattern initializer text from \c DeclTypeCursor, if present. Optional maybeReadPatternInitializerText(); }; template void ModuleFile::allocateBuffer(MutableArrayRef &buffer, const RawData &rawData) { assert(buffer.empty() && "reallocating deserialized buffer"); if (rawData.empty()) return; void *rawBuffer = Allocator.Allocate(sizeof(T) * rawData.size(), alignof(T)); buffer = llvm::makeMutableArrayRef(static_cast(rawBuffer), rawData.size()); std::uninitialized_copy(rawData.begin(), rawData.end(), buffer.begin()); } } // end namespace swift #endif