| //===--- 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 "ModuleFormat.h" |
| #include "ModuleFileSharedCore.h" |
| #include "swift/AST/Identifier.h" |
| #include "swift/AST/LazyResolver.h" |
| #include "swift/AST/LinkLibrary.h" |
| #include "swift/AST/FileUnit.h" |
| #include "swift/AST/Module.h" |
| #include "swift/AST/RawComment.h" |
| #include "swift/AST/SILLayout.h" |
| #include "swift/Serialization/Validation.h" |
| #include "swift/Basic/LLVM.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/Error.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| |
| namespace llvm { |
| class BitstreamCursor; |
| class BitstreamReader; |
| class MemoryBuffer; |
| template <typename Info> 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; |
| using Status = serialization::Status; |
| using TypeID = serialization::TypeID; |
| |
| /// The core data of a serialized module file. This is accessed as immutable |
| /// and thread-safe. |
| const std::shared_ptr<const ModuleFileSharedCore> 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; |
| |
| friend StringRef getNameOfModule(const ModuleFile *); |
| |
| /// A callback to be invoked every time a type was deserialized. |
| std::function<void(Type)> DeserializedTypeCallback; |
| |
| public: |
| static std::unique_ptr<llvm::MemoryBuffer> 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<ImportedModule> Import = llvm::None; |
| SmallVector<Identifier, 4> spiGroups; |
| |
| Dependency(const ModuleFileSharedCore::Dependency &coreDependency) |
| : Core(coreDependency) {} |
| |
| bool isLoaded() const { |
| return Import.hasValue() && Import->importedModule != nullptr; |
| } |
| |
| bool isExported() const { |
| return Core.isExported(); |
| } |
| bool isImplementationOnly() const { |
| return Core.isImplementationOnly(); |
| } |
| |
| bool isHeader() const { return Core.isHeader(); } |
| bool isScoped() const { return Core.isScoped(); } |
| }; |
| |
| private: |
| /// All modules this module depends on. |
| SmallVector<Dependency, 8> Dependencies; |
| |
| public: |
| template <typename T> |
| class Serialized { |
| private: |
| using RawBitOffset = uint64_t; |
| |
| using ImplTy = PointerUnion<T, serialization::BitOffset>; |
| ImplTy Value; |
| |
| public: |
| /*implicit*/ Serialized(serialization::BitOffset offset) : Value(offset) {} |
| |
| bool isComplete() const { |
| return Value.template is<T>(); |
| } |
| |
| T get() const { |
| return Value.template get<T>(); |
| } |
| |
| /*implicit*/ operator T() const { |
| return get(); |
| } |
| |
| /*implicit*/ operator serialization::BitOffset() const { |
| return Value.template get<serialization::BitOffset>(); |
| } |
| |
| /*implicit*/ operator RawBitOffset() const { |
| return Value.template get<serialization::BitOffset>(); |
| } |
| |
| 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 <typename T> |
| 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<unsigned>(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 <typename T, typename RawData> |
| void allocateBuffer(MutableArrayRef<T> &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 <typename T, typename RawData> |
| void allocateBuffer(ArrayRef<T> &buffer, const RawData &rawData) { |
| assert(buffer.empty()); |
| MutableArrayRef<T> result; |
| allocateBuffer(result, rawData); |
| buffer = result; |
| } |
| |
| /// Decls referenced by this module. |
| MutableArrayRef<Serialized<Decl*>> Decls; |
| |
| /// Local DeclContexts referenced by this module. |
| MutableArrayRef<Serialized<DeclContext*>> LocalDeclContexts; |
| |
| /// Normal protocol conformances referenced by this module. |
| MutableArrayRef<Serialized<NormalProtocolConformance *>> NormalConformances; |
| |
| /// SILLayouts referenced by this module. |
| MutableArrayRef<Serialized<SILLayout *>> SILLayouts; |
| |
| /// Types referenced by this module. |
| MutableArrayRef<Serialized<Type>> Types; |
| |
| /// Clang types referenced by this module. |
| MutableArrayRef<Serialized<const clang::Type *>> ClangTypes; |
| |
| /// Generic signatures referenced by this module. |
| MutableArrayRef<Serialized<GenericSignature>> GenericSignatures; |
| |
| /// Substitution maps referenced by this module. |
| MutableArrayRef<Serialized<SubstitutionMap>> SubstitutionMaps; |
| |
| /// 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 <typename IntTy> |
| /*implicit*/ SerializedIdentifier(IntTy rawOffset) |
| : Offset(static_cast<unsigned>(rawOffset)) { |
| assert(Offset == rawOffset && "not enough bits"); |
| } |
| }; |
| |
| /// Identifiers referenced by this module. |
| MutableArrayRef<SerializedIdentifier> Identifiers; |
| |
| using SerializedDeclMembersTable = |
| ModuleFileSharedCore::SerializedDeclMembersTable; |
| |
| llvm::DenseMap<uint32_t, |
| std::unique_ptr<SerializedDeclMembersTable>> DeclMembersTables; |
| |
| llvm::DenseMap<const ValueDecl *, Identifier> PrivateDiscriminatorsByValue; |
| llvm::DenseMap<const ValueDecl *, StringRef> FilenamesForPrivateValues; |
| |
| TinyPtrVector<Decl *> ImportDecls; |
| |
| /// Maps USRs to their deserialized comment object. |
| mutable llvm::StringMap< |
| std::unique_ptr<ModuleFileSharedCore::DeserializedCommentInfo>> |
| 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 <typename T, typename ...Args> |
| T *createDecl(Args &&... args); |
| |
| 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; |
| } |
| |
| /// Emits one last diagnostic, logs the error, and then aborts for the stack |
| /// trace. |
| LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error error); |
| void fatalIfNotSuccess(llvm::Error error) { |
| if (error) |
| fatal(std::move(error)); |
| } |
| template <typename T> T fatalIfUnexpected(llvm::Expected<T> expected) { |
| if (expected) |
| return std::move(expected.get()); |
| fatal(expected.takeError()); |
| } |
| |
| LLVM_ATTRIBUTE_NORETURN void fatal() { |
| fatal(llvm::make_error<llvm::StringError>( |
| "(see \"While...\" info below)", llvm::inconvertibleErrorCode())); |
| } |
| |
| 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<Pattern *> 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 readGenericRequirements(SmallVectorImpl<Requirement> &requirements, |
| llvm::BitstreamCursor &Cursor); |
| |
| /// Reads a set of requirements from \c DeclTypeCursor, returns the first |
| /// error, if any. |
| llvm::Error |
| readGenericRequirementsChecked(SmallVectorImpl<Requirement> &requirements, |
| 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<Decl *> resolveCrossReference(serialization::ModuleID MID, |
| uint32_t pathLen); |
| |
| struct AccessorRecord { |
| SmallVector<serialization::DeclID, 8> 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<const ModuleFileSharedCore> core); |
| |
| // Out of line to avoid instantiation OnDiskChainedHashTable here. |
| ~ModuleFile(); |
| |
| /// The name of the module. |
| StringRef getName() const { |
| return Core->Name; |
| } |
| |
| /// 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 the module is resilient. ('-enable-library-evolution') |
| ResilienceStrategy getResilienceStrategy() const { |
| return ResilienceStrategy(Core->Bits.ResilienceStrategy); |
| } |
| |
| /// 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 isAllowModuleWithCompilerErrorsEnabled() const { |
| return Core->Bits.IsAllowModuleWithCompilerErrorsEnabled; |
| } |
| |
| /// \c true if this module has incremental dependency information. |
| bool hasIncrementalInfo() const { return Core->hasIncrementalInfo(); } |
| |
| /// 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. |
| /// |
| /// \returns any error that occurred during association, such as being |
| /// compiled for a different OS. |
| Status associateWithFileContext(FileUnit *file, SourceLoc diagLoc); |
| |
| /// 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<Dependency> 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<ValueDecl*> &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<ImportedModule> &results, |
| ModuleDecl::ImportFilter filter); |
| |
| void getImportDecls(SmallVectorImpl<Decl *> &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 class that produce |
| /// Objective-C class or instance methods with the given selector. |
| /// |
| /// \param classDecl The class in which we are searching for @objc methods. |
| /// The search only considers this class 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(ClassDecl *classDecl, |
| ObjCSelector selector, |
| bool isInstanceMethod, |
| llvm::TinyPtrVector<AbstractFunctionDecl *> &methods); |
| |
| /// Loads all derivative function configurations for the given |
| /// AbstractFunctionDecl. |
| void loadDerivativeFunctionConfigurations( |
| AbstractFunctionDecl *originalAFD, |
| llvm::SetVector<AutoDiffConfig> &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<ValueDecl*> &results); |
| |
| /// Find all Objective-C methods with the given selector. |
| void lookupObjCMethods( |
| ObjCSelector selector, |
| SmallVectorImpl<AbstractFunctionDecl *> &results); |
| |
| /// Find all SPI names imported from \p importedModule by this module, |
| /// collecting the identifiers in \p spiGroups. |
| void lookupImportedSPIGroups( |
| const ModuleDecl *importedModule, |
| llvm::SmallSetVector<Identifier, 4> &spiGroups) const; |
| |
| /// 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<Decl*> &Results, |
| llvm::function_ref<bool(DeclAttributes)> matchAttributes = nullptr); |
| |
| void getExportedPrespecializations(SmallVectorImpl<Decl *> &results); |
| |
| /// Adds all operators to the given vector. |
| void getOperatorDecls(SmallVectorImpl<OperatorDecl *> &Results); |
| |
| /// Adds all precedence groups to the given vector. |
| void getPrecedenceGroups(SmallVectorImpl<PrecedenceGroupDecl*> &Results); |
| |
| /// Adds all local type decls to the given vector. |
| void getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &Results); |
| |
| /// Add all opaque return type decls in the module to the given vector. |
| void getOpaqueReturnTypeDecls(SmallVectorImpl<OpaqueTypeDecl*> &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<Decl*> &results); |
| |
| StringRef getModuleFilename() const { |
| if (!Core->ModuleInterfacePath.empty()) |
| return Core->ModuleInterfacePath; |
| // FIXME: This seems fragile, maybe store the filename separately ? |
| return Core->ModuleInputBuffer->getBufferIdentifier(); |
| } |
| |
| 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<ValueDecl *> |
| loadNamedMembers(const IterableDeclContext *IDC, DeclBaseName N, |
| uint64_t contextData) override; |
| |
| virtual void |
| loadAllConformances(const Decl *D, uint64_t contextData, |
| SmallVectorImpl<ProtocolConformance*> &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<Requirement> &requirements) override; |
| |
| Optional<StringRef> getGroupNameById(unsigned Id) const; |
| Optional<StringRef> getSourceFileNameById(unsigned Id) const; |
| Optional<StringRef> getGroupNameForDecl(const Decl *D) const; |
| Optional<StringRef> getSourceFileNameForDecl(const Decl *D) const; |
| Optional<unsigned> getSourceOrderForDecl(const Decl *D) const; |
| void collectAllGroups(std::vector<StringRef> &Names) const; |
| Optional<CommentInfo> getCommentForDecl(const Decl *D) const; |
| Optional<CommentInfo> getCommentForDeclByUSR(StringRef USR) const; |
| Optional<StringRef> getGroupNameByUSR(StringRef USR) const; |
| Optional<BasicDeclLocs> getBasicDeclLocsForDecl(const Decl *D) const; |
| Identifier getDiscriminatorForPrivateValue(const ValueDecl *D); |
| Optional<Fingerprint> loadFingerprint(const IterableDeclContext *IDC) 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<Type> getTypeChecked(serialization::TypeID TID); |
| |
| /// Returns the Clang type with the given ID, deserializing it if needed. |
| llvm::Expected<const clang::Type *> |
| 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<Decl *> |
| getDeclChecked( |
| serialization::DeclID DID, |
| llvm::function_ref<bool(DeclAttributes)> 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<DeclContext *> |
| getDeclContextChecked(serialization::DeclContextID DCID); |
| |
| /// Returns the local decl context with the given ID, deserializing it if needed. |
| DeclContext *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<GenericSignature> |
| getGenericSignatureChecked(serialization::GenericSignatureID 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<SubstitutionMap> |
| getSubstitutionMapChecked(serialization::SubstitutionMapID id); |
| |
| /// Recursively reads a protocol conformance from the given cursor. |
| ProtocolConformanceRef readConformance(llvm::BitstreamCursor &Cursor, |
| GenericEnvironment *genericEnv = |
| nullptr); |
| |
| /// Recursively reads a protocol conformance from the given cursor, |
| /// returns the conformance or the first error. |
| llvm::Expected<ProtocolConformanceRef> |
| readConformanceChecked(llvm::BitstreamCursor &Cursor, |
| GenericEnvironment *genericEnv = nullptr); |
| |
| /// Read a SILLayout from the given cursor. |
| SILLayout *readSILLayout(llvm::BitstreamCursor &Cursor); |
| |
| /// Read the given normal conformance from the current module file, |
| /// returns the conformance or the first error. |
| llvm::Expected<NormalProtocolConformance *> |
| readNormalConformanceChecked(serialization::NormalConformanceID id); |
| |
| /// Reads a foreign error conformance from \c DeclTypeCursor, if present. |
| Optional<ForeignErrorConvention> maybeReadForeignErrorConvention(); |
| |
| /// Reads inlinable body text from \c DeclTypeCursor, if present. |
| Optional<StringRef> maybeReadInlinableBodyText(); |
| |
| /// Reads pattern initializer text from \c DeclTypeCursor, if present. |
| Optional<StringRef> maybeReadPatternInitializerText(); |
| }; |
| |
| template <typename T, typename RawData> |
| void ModuleFile::allocateBuffer(MutableArrayRef<T> &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<T *>(rawBuffer), |
| rawData.size()); |
| std::uninitialized_copy(rawData.begin(), rawData.end(), buffer.begin()); |
| } |
| |
| } // end namespace swift |
| |
| #endif |