text: //===--- SILModule.h - Defines the SILModule class --------------*- 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
  //
  //===----------------------------------------------------------------------===//
  //
  // This file defines the SILModule class.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_SIL_SILMODULE_H
  #define SWIFT_SIL_SILMODULE_H
  
  #include "swift/AST/ASTContext.h"
  #include "swift/AST/Builtins.h"
  #include "swift/AST/SILLayout.h"
  #include "swift/AST/SILOptions.h"
  #include "swift/Basic/LangOptions.h"
  #include "swift/Basic/ProfileCounter.h"
  #include "swift/Basic/Range.h"
  #include "swift/SIL/Notifications.h"
  #include "swift/SIL/SILCoverageMap.h"
  #include "swift/SIL/SILDeclRef.h"
  #include "swift/SIL/SILDefaultWitnessTable.h"
  #include "swift/SIL/SILDifferentiabilityWitness.h"
  #include "swift/SIL/SILFunction.h"
  #include "swift/SIL/SILGlobalVariable.h"
  #include "swift/SIL/SILPrintContext.h"
  #include "swift/SIL/SILProperty.h"
  #include "swift/SIL/SILType.h"
  #include "swift/SIL/SILVTable.h"
  #include "swift/SIL/SILWitnessTable.h"
  #include "swift/SIL/TypeLowering.h"
  #include "llvm/ADT/ArrayRef.h"
  #include "llvm/ADT/FoldingSet.h"
  #include "llvm/ADT/MapVector.h"
  #include "llvm/ADT/PointerIntPair.h"
  #include "llvm/ADT/SetVector.h"
  #include "llvm/ADT/ilist.h"
  #include "llvm/ProfileData/InstrProfReader.h"
  #include "llvm/Support/Allocator.h"
  #include "llvm/Support/raw_ostream.h"
  #include <functional>
  
  namespace llvm {
  namespace yaml {
  class Output;
  } // end namespace yaml
  } // end namespace llvm
  
  namespace swift {
  
  class AnyFunctionType;
  class ASTContext;
  class FileUnit;
  class FuncDecl;
  class KeyPathPattern;
  class ModuleDecl;
  class SILUndef;
  class SourceFile;
  class SerializedSILLoader;
  class SILFunctionBuilder;
  class SILRemarkStreamer;
  
  namespace Lowering {
  class SILGenModule;
  } // namespace Lowering
  
  /// A stage of SIL processing.
  enum class SILStage {
    /// "Raw" SIL, emitted by SILGen, but not yet run through guaranteed
    /// optimization and diagnostic passes.
    ///
    /// Raw SIL does not have fully-constructed SSA and may contain undiagnosed
    /// dataflow errors.
    Raw,
  
    /// Canonical SIL, which has been run through at least the guaranteed
    /// optimization and diagnostic passes.
    ///
    /// Canonical SIL has stricter invariants than raw SIL. It must not contain
    /// dataflow errors, and some instructions must be canonicalized to simpler
    /// forms.
    Canonical,
  
    /// Lowered SIL, which has been prepared for IRGen and will no longer
    /// be passed to canonical SIL transform passes.
    ///
    /// In lowered SIL, the SILType of all SILValues is its SIL storage
    /// type. Explicit storage is required for all address-only and resilient
    /// types.
    ///
    /// Generating the initial Raw SIL is typically referred to as lowering (from
    /// the AST). To disambiguate, refer to the process of generating the lowered
    /// stage of SIL as "address lowering".
    Lowered,
  };
  
  /// A SIL module. The SIL module owns all of the SILFunctions generated
  /// when a Swift compilation context is lowered to SIL.
  class SILModule {
    friend class SILFunctionBuilder;
  
  public:
    using FunctionListType = llvm::ilist<SILFunction>;
    using GlobalListType = llvm::ilist<SILGlobalVariable>;
    using VTableListType = llvm::ArrayRef<SILVTable*>;
    using PropertyListType = llvm::ilist<SILProperty>;
    using WitnessTableListType = llvm::ilist<SILWitnessTable>;
    using DefaultWitnessTableListType = llvm::ilist<SILDefaultWitnessTable>;
    using DifferentiabilityWitnessListType =
        llvm::ilist<SILDifferentiabilityWitness>;
    using CoverageMapCollectionType =
        llvm::MapVector<StringRef, SILCoverageMap *>;
  
    enum class LinkingMode : uint8_t {
      /// Link functions with non-public linkage. Used by the mandatory pipeline.
      LinkNormal,
  
      /// Link all functions. Used by the performance pipeine.
      LinkAll
    };
  
    using ActionCallback = std::function<void()>;
  
  private:
    friend KeyPathPattern;
    friend SILBasicBlock;
    friend SILCoverageMap;
    friend SILDefaultWitnessTable;
    friend SILDifferentiabilityWitness;
    friend SILFunction;
    friend SILGlobalVariable;
    friend SILLayout;
    friend SILType;
    friend SILVTable;
    friend SILProperty;
    friend SILUndef;
    friend SILWitnessTable;
    friend Lowering::SILGenModule;
    friend Lowering::TypeConverter;
    class SerializationCallback;
  
    /// Allocator that manages the memory of all the pieces of the SILModule.
    mutable llvm::BumpPtrAllocator BPA;
  
    /// The swift Module associated with this SILModule.
    ModuleDecl *TheSwiftModule;
  
    /// A specific context for AST-level declarations associated with this SIL
    /// module.
    ///
    /// \sa getAssociatedContext
    const DeclContext *AssociatedDeclContext;
  
    /// Lookup table for SIL functions. This needs to be declared before \p
    /// functions so that the destructor of \p functions is called first.
    llvm::StringMap<SILFunction *> FunctionTable;
    llvm::StringMap<SILFunction *> ZombieFunctionTable;
  
    /// The list of SILFunctions in the module.
    FunctionListType functions;
  
    /// Functions, which are dead (and not in the functions list anymore),
    /// but kept alive for debug info generation.
    FunctionListType zombieFunctions;
  
    /// Lookup table for SIL vtables from class decls.
    llvm::DenseMap<const ClassDecl *, SILVTable *> VTableMap;
  
    /// The list of SILVTables in the module.
    std::vector<SILVTable*> vtables;
  
    /// This is a cache of vtable entries for quick look-up
    llvm::DenseMap<std::pair<const SILVTable *, SILDeclRef>, SILVTable::Entry>
        VTableEntryCache;
  
    /// Lookup table for SIL witness tables from conformances.
    llvm::DenseMap<const RootProtocolConformance *, SILWitnessTable *>
    WitnessTableMap;
  
    /// The list of SILWitnessTables in the module.
    WitnessTableListType witnessTables;
  
    /// Lookup table for SIL default witness tables from protocols.
    llvm::DenseMap<const ProtocolDecl *, SILDefaultWitnessTable *>
    DefaultWitnessTableMap;
  
    /// The list of SILDefaultWitnessTables in the module.
    DefaultWitnessTableListType defaultWitnessTables;
  
    /// Lookup table for SIL differentiability witnesses, keyed by mangled name.
    llvm::StringMap<SILDifferentiabilityWitness *> DifferentiabilityWitnessMap;
  
    /// Lookup table for SILDifferentiabilityWitnesses, keyed by original
    /// function name.
    llvm::StringMap<llvm::SmallVector<SILDifferentiabilityWitness *, 1>>
        DifferentiabilityWitnessesByFunction;
  
    /// The list of SILDifferentiabilityWitnesses in the module.
    DifferentiabilityWitnessListType differentiabilityWitnesses;
  
    /// Declarations which are externally visible.
    ///
    /// These are method declarations which are referenced from inlinable
    /// functions due to cross-module-optimzation. Those declarations don't have
    /// any attributes or linkage which mark them as externally visible by
    /// default.
    /// Currently this table is not serialized.
    llvm::SetVector<ValueDecl *> externallyVisible;
  
    /// Lookup table for SIL Global Variables.
    llvm::StringMap<SILGlobalVariable *> GlobalVariableMap;
  
    /// The list of SILGlobalVariables in the module.
    GlobalListType silGlobals;
  
    // The map of SILCoverageMaps in the module.
    CoverageMapCollectionType coverageMaps;
  
    // The list of SILProperties in the module.
    PropertyListType properties;
  
    /// The remark streamer used to serialize SIL remarks to a file.
    std::unique_ptr<swift::SILRemarkStreamer> silRemarkStreamer;
  
    /// This is a cache of intrinsic Function declarations to numeric ID mappings.
    llvm::DenseMap<Identifier, IntrinsicInfo> IntrinsicIDCache;
  
    /// This is a cache of builtin Function declarations to numeric ID mappings.
    llvm::DenseMap<Identifier, BuiltinInfo> BuiltinIDCache;
  
    /// This is the set of undef values we've created, for uniquing purposes.
    llvm::DenseMap<std::pair<SILType, unsigned>, SILUndef *> UndefValues;
  
    /// The stage of processing this module is at.
    SILStage Stage;
  
    /// The set of deserialization notification handlers.
    DeserializationNotificationHandlerSet deserializationNotificationHandlers;
  
    /// The SILLoader used when linking functions into this module.
    ///
    /// This is lazily initialized the first time we attempt to
    /// deserialize. Previously this was created when the SILModule was
    /// constructed. In certain cases this was before all Modules had been loaded
    /// causing us to not
    std::unique_ptr<SerializedSILLoader> SILLoader;
  
    /// The indexed profile data to be used for PGO, or nullptr.
    std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
  
    /// The options passed into this SILModule.
    const SILOptions &Options;
  
    /// Set if the SILModule was serialized already. It is used
    /// to ensure that the module is serialized only once.
    bool serialized;
  
    /// Action to be executed for serializing the SILModule.
    ActionCallback SerializeSILAction;
  
    /// A list of clients that need to be notified when an instruction
    /// invalidation message is sent.
    llvm::SetVector<DeleteNotificationHandler*> NotificationHandlers;
  
    SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
              Lowering::TypeConverter &TC, const SILOptions &Options);
  
    SILModule(const SILModule&) = delete;
    void operator=(const SILModule&) = delete;
  
    /// Folding set for key path patterns.
    llvm::FoldingSet<KeyPathPattern> KeyPathPatterns;
  
  public:
    ~SILModule();
  
    /// Method which returns the SerializedSILLoader, creating the loader if it
    /// has not been created yet.
    SerializedSILLoader *getSILLoader();
  
    /// Add a callback for each newly deserialized SIL function body.
    void registerDeserializationNotificationHandler(
        std::unique_ptr<DeserializationNotificationHandler> &&handler);
  
    /// Return the set of registered deserialization callbacks.
    DeserializationNotificationHandlerSet::range
    getDeserializationHandlers() const {
      return deserializationNotificationHandlers.getRange();
    }
  
    void removeDeserializationNotificationHandler(
        DeserializationNotificationHandler *handler) {
      deserializationNotificationHandlers.erase(handler);
    }
  
    /// Add a delete notification handler \p Handler to the module context.
    void registerDeleteNotificationHandler(DeleteNotificationHandler* Handler);
  
    /// Remove the delete notification handler \p Handler from the module context.
    void removeDeleteNotificationHandler(DeleteNotificationHandler* Handler);
  
    /// Send the invalidation message that \p V is being deleted to all
    /// registered handlers. The order of handlers is deterministic but arbitrary.
    void notifyDeleteHandlers(SILNode *node);
  
    /// Set a serialization action.
    void setSerializeSILAction(ActionCallback SerializeSILAction);
    ActionCallback getSerializeSILAction() const;
  
    /// Set a flag indicating that this module is serialized already.
    void setSerialized() { serialized = true; }
    bool isSerialized() const { return serialized; }
  
    /// Serialize a SIL module using the configured SerializeSILAction.
    void serialize();
  
    /// This converts Swift types to SILTypes.
    Lowering::TypeConverter &Types;
  
    /// Invalidate cached entries in SIL Loader.
    void invalidateSILLoaderCaches();
  
    /// Erase a function from the module.
    void eraseFunction(SILFunction *F);
  
    /// Invalidate a function in SILLoader cache.
    void invalidateFunctionInSILCache(SILFunction *F);
  
    /// Specialization can cause a function that was erased before by dead function
    /// elimination to become alive again. If this happens we need to remove it
    /// from the list of zombies.
    SILFunction *removeFromZombieList(StringRef Name);
  
    /// Erase a global SIL variable from the module.
    void eraseGlobalVariable(SILGlobalVariable *G);
  
    /// Create and return an empty SIL module suitable for generating or parsing
    /// SIL into.
    ///
    /// \param context The associated decl context. This should be a FileUnit in
    /// single-file mode, and a ModuleDecl in whole-module mode.
    static std::unique_ptr<SILModule>
    createEmptyModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
                      Lowering::TypeConverter &TC, const SILOptions &Options);
  
    /// Get the Swift module associated with this SIL module.
    ModuleDecl *getSwiftModule() const { return TheSwiftModule; }
    /// Get the AST context used for type uniquing etc. by this SIL module.
    ASTContext &getASTContext() const;
    SourceManager &getSourceManager() const { return getASTContext().SourceMgr; }
  
    /// Get the Swift DeclContext associated with this SIL module. This is never
    /// null.
    ///
    /// All AST declarations within this context are assumed to have been fully
    /// processed as part of generating this module. This allows certain passes
    /// to make additional assumptions about these declarations.
    ///
    /// If this is the same as TheSwiftModule, the entire module is being
    /// compiled as a single unit.
    const DeclContext *getAssociatedContext() const {
      return AssociatedDeclContext;
    }
  
    /// Returns true if this SILModule really contains the whole module, i.e.
    /// optimizations can assume that they see the whole module.
    bool isWholeModule() const {
      return isa<ModuleDecl>(AssociatedDeclContext);
    }
  
    bool isStdlibModule() const;
  
    /// Returns true if it is the optimized OnoneSupport module.
    bool isOptimizedOnoneSupportModule() const;
  
    const SILOptions &getOptions() const { return Options; }
  
    using iterator = FunctionListType::iterator;
    using const_iterator = FunctionListType::const_iterator;
    FunctionListType &getFunctionList() { return functions; }
    const FunctionListType &getFunctionList() const { return functions; }
    iterator begin() { return functions.begin(); }
    iterator end() { return functions.end(); }
    const_iterator begin() const { return functions.begin(); }
    const_iterator end() const { return functions.end(); }
    iterator_range<iterator> getFunctions() {
      return {functions.begin(), functions.end()};
    }
    iterator_range<const_iterator> getFunctions() const {
      return {functions.begin(), functions.end()};
    }
  
    const_iterator zombies_begin() const { return zombieFunctions.begin(); }
    const_iterator zombies_end() const { return zombieFunctions.end(); }
  
    llvm::ArrayRef<SILVTable*> getVTables() const {
      return llvm::ArrayRef<SILVTable*>(vtables);
    }
    using vtable_iterator = VTableListType::iterator;
    using vtable_const_iterator = VTableListType::const_iterator;
    vtable_iterator vtable_begin() { return getVTables().begin(); }
    vtable_iterator vtable_end() { return getVTables().end(); }
    vtable_const_iterator vtable_begin() const { return getVTables().begin(); }
    vtable_const_iterator vtable_end() const { return getVTables().end(); }
  
    using witness_table_iterator = WitnessTableListType::iterator;
    using witness_table_const_iterator = WitnessTableListType::const_iterator;
    WitnessTableListType &getWitnessTableList() { return witnessTables; }
    const WitnessTableListType &getWitnessTableList() const { return witnessTables; }
    witness_table_iterator witness_table_begin() { return witnessTables.begin(); }
    witness_table_iterator witness_table_end() { return witnessTables.end(); }
    witness_table_const_iterator witness_table_begin() const { return witnessTables.begin(); }
    witness_table_const_iterator witness_table_end() const { return witnessTables.end(); }
    iterator_range<witness_table_iterator> getWitnessTables() {
      return {witnessTables.begin(), witnessTables.end()};
    }
    iterator_range<witness_table_const_iterator> getWitnessTables() const {
      return {witnessTables.begin(), witnessTables.end()};
    }
  
    using default_witness_table_iterator = DefaultWitnessTableListType::iterator;
    using default_witness_table_const_iterator = DefaultWitnessTableListType::const_iterator;
    DefaultWitnessTableListType &getDefaultWitnessTableList() { return defaultWitnessTables; }
    const DefaultWitnessTableListType &getDefaultWitnessTableList() const { return defaultWitnessTables; }
    default_witness_table_iterator default_witness_table_begin() { return defaultWitnessTables.begin(); }
    default_witness_table_iterator default_witness_table_end() { return defaultWitnessTables.end(); }
    default_witness_table_const_iterator default_witness_table_begin() const { return defaultWitnessTables.begin(); }
    default_witness_table_const_iterator default_witness_table_end() const { return defaultWitnessTables.end(); }
    iterator_range<default_witness_table_iterator> getDefaultWitnessTables() {
      return {defaultWitnessTables.begin(), defaultWitnessTables.end()};
    }
    iterator_range<default_witness_table_const_iterator> getDefaultWitnessTables() const {
      return {defaultWitnessTables.begin(), defaultWitnessTables.end()};
    }
  
    using differentiability_witness_iterator = DifferentiabilityWitnessListType::iterator;
    using differentiability_witness_const_iterator = DifferentiabilityWitnessListType::const_iterator;
    DifferentiabilityWitnessListType &getDifferentiabilityWitnessList() { return differentiabilityWitnesses; }
    const DifferentiabilityWitnessListType &getDifferentiabilityWitnessList() const { return differentiabilityWitnesses; }
    differentiability_witness_iterator differentiability_witness_begin() { return differentiabilityWitnesses.begin(); }
    differentiability_witness_iterator differentiability_witness_end() { return differentiabilityWitnesses.end(); }
    differentiability_witness_const_iterator differentiability_witness_begin() const { return differentiabilityWitnesses.begin(); }
    differentiability_witness_const_iterator differentiability_witness_end() const { return differentiabilityWitnesses.end(); }
    iterator_range<differentiability_witness_iterator>
    getDifferentiabilityWitnesses() {
      return {differentiabilityWitnesses.begin(),
              differentiabilityWitnesses.end()};
    }
    iterator_range<differentiability_witness_const_iterator>
    getDifferentiabilityWitnesses() const {
      return {differentiabilityWitnesses.begin(),
              differentiabilityWitnesses.end()};
    }
  
    void addExternallyVisibleDecl(ValueDecl *decl) {
      externallyVisible.insert(decl);
    }
    bool isExternallyVisibleDecl(ValueDecl *decl) {
      return externallyVisible.count(decl) != 0;
    }
  
    using sil_global_iterator = GlobalListType::iterator;
    using sil_global_const_iterator = GlobalListType::const_iterator;
    GlobalListType &getSILGlobalList() { return silGlobals; }
    const GlobalListType &getSILGlobalList() const { return silGlobals; }
    sil_global_iterator sil_global_begin() { return silGlobals.begin(); }
    sil_global_iterator sil_global_end() { return silGlobals.end(); }
    sil_global_const_iterator sil_global_begin() const {
      return silGlobals.begin();
    }
    sil_global_const_iterator sil_global_end() const {
      return silGlobals.end();
    }
    iterator_range<sil_global_iterator> getSILGlobals() {
      return {silGlobals.begin(), silGlobals.end()};
    }
    iterator_range<sil_global_const_iterator> getSILGlobals() const {
      return {silGlobals.begin(), silGlobals.end()};
    }
  
    using coverage_map_iterator = CoverageMapCollectionType::iterator;
    using coverage_map_const_iterator = CoverageMapCollectionType::const_iterator;
    CoverageMapCollectionType &getCoverageMaps() { return coverageMaps; }
    const CoverageMapCollectionType &getCoverageMaps() const {
      return coverageMaps;
    }
  
    swift::SILRemarkStreamer *getSILRemarkStreamer() {
      return silRemarkStreamer.get();
    }
  
    void installSILRemarkStreamer();
  
    // This is currently limited to VarDecl because the visibility of global
    // variables and class properties is straightforward, while the visibility of
    // class methods (ValueDecls) depends on the subclass scope. "Visiblity" has
    // a different meaning when vtable layout is at stake.
    bool isVisibleExternally(const VarDecl *decl) {
      return isPossiblyUsedExternally(getDeclSILLinkage(decl), isWholeModule());
    }
  
    PropertyListType &getPropertyList() { return properties; }
    const PropertyListType &getPropertyList() const { return properties; }
  
    /// Look for a global variable by name.
    ///
    /// \return null if this module has no such global variable
    SILGlobalVariable *lookUpGlobalVariable(StringRef name) const {
      return GlobalVariableMap.lookup(name);
    }
  
    /// Look for a function by name.
    ///
    /// \return null if this module has no such function
    SILFunction *lookUpFunction(StringRef name) const {
      return FunctionTable.lookup(name);
    }
  
    /// Look for a function by declaration.
    ///
    /// \return null if this module has no such function
    SILFunction *lookUpFunction(SILDeclRef fnRef);
  
    /// Attempt to deserialize the SILFunction. Returns true if deserialization
    /// succeeded, false otherwise.
    bool loadFunction(SILFunction *F);
  
    /// Update the linkage of the SILFunction with the linkage of the serialized
    /// function.
    ///
    /// The serialized SILLinkage can differ from the linkage derived from the
    /// AST, e.g. cross-module-optimization can change the SIL linkages.
    void updateFunctionLinkage(SILFunction *F);
  
    /// Attempt to link the SILFunction. Returns true if linking succeeded, false
    /// otherwise.
    ///
    /// \return false if the linking failed.
    bool linkFunction(SILFunction *F,
                      LinkingMode LinkMode = LinkingMode::LinkNormal);
  
    /// Check if a given function exists in any of the modules with a
    /// required linkage, i.e. it can be linked by linkFunction.
    ///
    /// \return null if this module has no such function. Otherwise
    /// the declaration of a function.
    SILFunction *findFunction(StringRef Name, SILLinkage Linkage);
  
    /// Check if a given function exists in any of the modules.
    /// i.e. it can be linked by linkFunction.
    bool hasFunction(StringRef Name);
  
    /// Look up the SILWitnessTable representing the lowering of a protocol
    /// conformance, and collect the substitutions to apply to the referenced
    /// witnesses, if any.
    ///
    /// \arg C The protocol conformance mapped key to use to lookup the witness
    ///        table.
    /// \arg deserializeLazily If we cannot find the witness table should we
    ///                        attempt to lazily deserialize it.
    SILWitnessTable *
    lookUpWitnessTable(ProtocolConformanceRef C, bool deserializeLazily=true);
    SILWitnessTable *
    lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily=true);
  
    /// Attempt to lookup \p Member in the witness table for \p C.
    std::pair<SILFunction *, SILWitnessTable *>
    lookUpFunctionInWitnessTable(ProtocolConformanceRef C,
                                 SILDeclRef Requirement);
  
    /// Look up the SILDefaultWitnessTable representing the default witnesses
    /// of a resilient protocol, if any.
    SILDefaultWitnessTable *lookUpDefaultWitnessTable(const ProtocolDecl *Protocol,
                                                      bool deserializeLazily=true);
  
    /// Attempt to lookup \p Member in the default witness table for \p Protocol.
    std::pair<SILFunction *, SILDefaultWitnessTable *>
    lookUpFunctionInDefaultWitnessTable(const ProtocolDecl *Protocol,
                                        SILDeclRef Requirement,
                                        bool deserializeLazily=true);
  
    /// Look up the VTable mapped to the given ClassDecl. Returns null on failure.
    SILVTable *lookUpVTable(const ClassDecl *C, bool deserializeLazily = true);
  
    /// Attempt to lookup the function corresponding to \p Member in the class
    /// hierarchy of \p Class.
    SILFunction *lookUpFunctionInVTable(ClassDecl *Class, SILDeclRef Member);
  
    /// Look up the differentiability witness with the given name.
    SILDifferentiabilityWitness *lookUpDifferentiabilityWitness(StringRef name);
  
    /// Look up the differentiability witness corresponding to the given key.
    SILDifferentiabilityWitness *
    lookUpDifferentiabilityWitness(SILDifferentiabilityWitnessKey key);
  
    /// Look up the differentiability witness corresponding to the given function.
    llvm::ArrayRef<SILDifferentiabilityWitness *>
    lookUpDifferentiabilityWitnessesForFunction(StringRef name);
  
    /// Attempt to deserialize the SILDifferentiabilityWitness. Returns true if
    /// deserialization succeeded, false otherwise.
    bool loadDifferentiabilityWitness(SILDifferentiabilityWitness *dw);
  
    // Given a protocol, attempt to create a default witness table declaration
    // for it.
    SILDefaultWitnessTable *
    createDefaultWitnessTableDeclaration(const ProtocolDecl *Protocol,
                                         SILLinkage Linkage);
  
    /// Deletes a dead witness table.
    void deleteWitnessTable(SILWitnessTable *Wt);
  
    /// Return the stage of processing this module is at.
    SILStage getStage() const { return Stage; }
  
    /// Advance the module to a further stage of processing.
    void setStage(SILStage s) {
      assert(s >= Stage && "regressing stage?!");
      Stage = s;
    }
  
    llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); }
  
    void setPGOReader(std::unique_ptr<llvm::IndexedInstrProfReader> IPR) {
      PGOReader = std::move(IPR);
    }
  
    /// Can value operations (copies and destroys) on the given lowered type
    /// be performed in this module?
    bool isTypeABIAccessible(SILType type,
                             TypeExpansionContext forExpansion);
  
    /// Can type metadata for the given formal type be fetched in
    /// the given module?
    bool isTypeMetadataAccessible(CanType type);
  
    /// Can type metadata necessary for value operations for the given sil type be
    /// fetched in the given module?
    bool isTypeMetadataForLayoutAccessible(SILType type);
  
    /// Run the SIL verifier to make sure that all Functions follow
    /// invariants.
    void verify() const;
  
    /// Check if there are any leaking instructions.
    ///
    /// Aborts with an error if more instructions are allocated than contained in
    /// the module.
    void checkForLeaks() const;
  
    /// Check if there are any leaking instructions after the SILModule is
    /// destructed.
    ///
    /// The SILModule destructor already calls checkForLeaks(). This function is
    /// useful to check if the destructor itself destroys all data structures.
    static void checkForLeaksAfterDestruction();
  
    /// Pretty-print the module.
    void dump(bool Verbose = false) const;
  
    /// Pretty-print the module to a file.
    /// Useful for dumping the module when running in a debugger.
    /// Warning: no error handling is done. Fails with an assert if the file
    /// cannot be opened.
    void dump(const char *FileName, bool Verbose = false,
              bool PrintASTDecls = false) const;
  
    /// Pretty-print the module to the designated stream.
    ///
    /// \param M If present, the types and declarations from this module will be
    ///        printed. The module would usually contain the types and Decls that
    ///        the SIL module depends on.
    /// \param Opts The SIL options, used to determine printing verbosity and
    ///        and sorting.
    /// \param PrintASTDecls If set to true print AST decls.
    void print(raw_ostream &OS, ModuleDecl *M = nullptr,
               const SILOptions &Opts = SILOptions(),
               bool PrintASTDecls = true) const {
      SILPrintContext PrintCtx(OS, Opts);
      print(PrintCtx, M, PrintASTDecls);
    }
  
    /// Pretty-print the module with the context \p PrintCtx.
    ///
    /// \param M If present, the types and declarations from this module will be
    ///        printed. The module would usually contain the types and Decls that
    ///        the SIL module depends on.
    /// \param PrintASTDecls If set to true print AST decls.
    void print(SILPrintContext &PrintCtx, ModuleDecl *M = nullptr,
               bool PrintASTDecls = true) const;
  
    /// Allocate memory using the module's internal allocator.
    void *allocate(unsigned Size, unsigned Align) const;
  
    template <typename T> T *allocate(unsigned Count) const {
      return static_cast<T *>(allocate(sizeof(T) * Count, alignof(T)));
    }
  
    template <typename T>
    MutableArrayRef<T> allocateCopy(ArrayRef<T> Array) const {
      MutableArrayRef<T> result(allocate<T>(Array.size()), Array.size());
      std::uninitialized_copy(Array.begin(), Array.end(), result.begin());
      return result;
    }
  
    StringRef allocateCopy(StringRef Str) const {
      auto result = allocateCopy<char>({Str.data(), Str.size()});
      return {result.data(), result.size()};
    }
  
    /// Allocate memory for an instruction using the module's internal allocator.
    void *allocateInst(unsigned Size, unsigned Align) const;
  
    /// Deallocate memory of an instruction.
    void deallocateInst(SILInstruction *I);
  
    /// Looks up the llvm intrinsic ID and type for the builtin function.
    ///
    /// \returns Returns llvm::Intrinsic::not_intrinsic if the function is not an
    /// intrinsic. The particular intrinsic functions which correspond to the
    /// returned value are defined in llvm/Intrinsics.h.
    const IntrinsicInfo &getIntrinsicInfo(Identifier ID);
  
    /// Looks up the lazily cached identification for the builtin function.
    ///
    /// \returns Returns builtin info of BuiltinValueKind::None kind if the
    /// declaration is not a builtin.
    const BuiltinInfo &getBuiltinInfo(Identifier ID);
  
    /// Returns true if the builtin or intrinsic is no-return.
    bool isNoReturnBuiltinOrIntrinsic(Identifier Name);
  
    /// Returns true if the default atomicity of the module is Atomic.
    bool isDefaultAtomic() const {
      return !getOptions().AssumeSingleThreaded;
    }
  
    /// Returns true if SIL entities associated with declarations in the given
    /// declaration context ought to be serialized as part of this module.
    bool
    shouldSerializeEntitiesAssociatedWithDeclContext(const DeclContext *DC) const;
  };
  
  inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SILModule &M){
    M.print(OS);
    return OS;
  }
  
  /// Print a simple description of a SILModule for the request evaluator.
  void simple_display(llvm::raw_ostream &out, const SILModule *M);
  
  /// Retrieve a SourceLoc for a SILModule that the request evaluator can use for
  /// diagnostics.
  SourceLoc extractNearestSourceLoc(const SILModule *SM);
  
  namespace Lowering {
  /// Determine whether the given class will be allocated/deallocated using the
  /// Objective-C runtime, i.e., +alloc and -dealloc.
  LLVM_LIBRARY_VISIBILITY bool usesObjCAllocator(ClassDecl *theClass);
  } // namespace Lowering
  
  } // namespace swift
  
  #endif
  