text: //===--- 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/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/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;
  
  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, adds the current module details and errors to
    /// the pretty stack trace, and then aborts.
    [[noreturn]] void fatal(llvm::Error error) const;
    void fatalIfNotSuccess(llvm::Error error) const {
      if (error)
        fatal(std::move(error));
    }
    template <typename T> T fatalIfUnexpected(llvm::Expected<T> expected) const {
      if (expected)
        return std::move(expected.get());
      fatal(expected.takeError());
    }
  
    /// 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.
    [[noreturn]] void fatal() const {
      fatal(llvm::make_error<llvm::StringError>(
          "Memory corruption or serialization format inconsistency.",
          llvm::inconvertibleErrorCode()));
    }
  
    /// 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<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);
  
    /// Read a list of associated type declarations in a protocol.
    void readAssociatedTypes(SmallVectorImpl<AssociatedTypeDecl *> &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<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 ABI name of the module.
    StringRef getModuleABIName() const {
      return Core->ModuleABIName;
    }
  
    llvm::VersionTuple getUserModuleVersion() const {
      return Core->UserModuleVersion;
    }
  
    /// 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 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 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);
  
    /// 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;
  
    void
    loadAssociatedTypes(const ProtocolDecl *proto, uint64_t contextData,
                        SmallVectorImpl<AssociatedTypeDecl *> &assocTypes) 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(SmallVectorImpl<StringRef> &Names) const;
    Optional<CommentInfo> getCommentForDecl(const Decl *D) const;
    Optional<CommentInfo> getCommentForDeclByUSR(StringRef USR) const;
    Optional<StringRef> getGroupNameByUSR(StringRef USR) const;
    Optional<ExternalSourceLocs::RawLocs>
    getExternalRawLocsForDecl(const Decl *D) const;
    Identifier getDiscriminatorForPrivateValue(const ValueDecl *D);
    Optional<Fingerprint> loadFingerprint(const IterableDeclContext *IDC) const;
    void collectBasicSourceFileInfo(
        llvm::function_ref<void(const BasicSourceFileInfo &)> callback) const;
    void collectSerializedSearchPath(
        llvm::function_ref<void(StringRef)> 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<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 convention from \c DeclTypeCursor, if present.
    Optional<ForeignErrorConvention> maybeReadForeignErrorConvention();
  
    /// Reads a foreign async convention from \c DeclTypeCursor, if present.
    Optional<ForeignAsyncConvention> maybeReadForeignAsyncConvention();
  
    /// 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
  