text: //===--- SILGen.h - Implements Lowering of ASTs -> SIL ----------*- 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 SILGEN_H
  #define SILGEN_H
  
  #include "ASTVisitor.h"
  #include "Cleanup.h"
  #include "swift/AST/ASTContext.h"
  #include "swift/AST/AnyFunctionRef.h"
  #include "swift/AST/DiagnosticEngine.h"
  #include "swift/SIL/SILDebugScope.h"
  #include "swift/SIL/SILFunction.h"
  #include "swift/SIL/SILModule.h"
  #include "swift/SIL/TypeLowering.h"
  #include "llvm/ADT/DenseMap.h"
  #include <deque>
  
  namespace swift {
    class SILBasicBlock;
    class ForeignAsyncConvention;
  
  namespace Lowering {
    class TypeConverter;
    class SILGenFunction;
  
  /// An enum to indicate whether a protocol method requirement is satisfied by
  /// a free function, as for an operator requirement.
  enum IsFreeFunctionWitness_t : bool {
    IsNotFreeFunctionWitness = false,
    IsFreeFunctionWitness = true,
  };
  
  /// An ASTVisitor for generating SIL from top-level declarations in a module.
  class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
  public:
    /// The Module being constructed.
    SILModule &M;
    
    /// The type converter for the module.
    TypeConverter &Types;
    
    /// The Swift module we are visiting.
    ModuleDecl *SwiftModule;
    
    /// TopLevelSGF - The SILGenFunction used to visit top-level code, or null if
    /// the current source file is not a script source file.
    SILGenFunction /*nullable*/ *TopLevelSGF;
  
    /// Mapping from SILDeclRefs to emitted SILFunctions.
    llvm::DenseMap<SILDeclRef, SILFunction*> emittedFunctions;
    /// Mapping from ProtocolConformances to emitted SILWitnessTables.
    llvm::DenseMap<NormalProtocolConformance*, SILWitnessTable*> emittedWitnessTables;
  
    /// Mapping from SILDeclRefs to where the given function will be inserted
    /// when it's emitted. Used for non-externally visible symbols.
    llvm::DenseMap<SILDeclRef, SILDeclRef> delayedFunctions;
  
    /// Queue of delayed SILFunctions that need to be forced.
    std::deque<SILDeclRef> forcedFunctions;
  
    /// Mapping global VarDecls to their onceToken and onceFunc, respectively.
    llvm::DenseMap<VarDecl *, std::pair<SILGlobalVariable *,
                                        SILFunction *>> delayedGlobals;
  
    /// The most recent declaration we considered for emission.
    SILDeclRef lastEmittedFunction;
  
    /// Bookkeeping to ensure that useConformancesFrom{ObjectiveC,}Type() is
    /// only called once for each unique type, as an optimization.
    llvm::DenseSet<TypeBase *> usedConformancesFromTypes;
    llvm::DenseSet<TypeBase *> usedConformancesFromObjectiveCTypes;
  
    /// Queue of delayed conformances that need to be emitted.
    std::deque<NormalProtocolConformance *> pendingConformances;
  
    /// Set of delayed conformances that have already been forced.
    llvm::DenseSet<NormalProtocolConformance *> forcedConformances;
  
    SILFunction *emitTopLevelFunction(SILLocation Loc);
  
    size_t anonymousSymbolCounter = 0;
  
    Optional<SILDeclRef> StringToNSStringFn;
    Optional<SILDeclRef> NSStringToStringFn;
    Optional<SILDeclRef> ArrayToNSArrayFn;
    Optional<SILDeclRef> NSArrayToArrayFn;
    Optional<SILDeclRef> DictionaryToNSDictionaryFn;
    Optional<SILDeclRef> NSDictionaryToDictionaryFn;
    Optional<SILDeclRef> SetToNSSetFn;
    Optional<SILDeclRef> NSSetToSetFn;
    Optional<SILDeclRef> BoolToObjCBoolFn;
    Optional<SILDeclRef> ObjCBoolToBoolFn;
    Optional<SILDeclRef> BoolToDarwinBooleanFn;
    Optional<SILDeclRef> DarwinBooleanToBoolFn;
    Optional<SILDeclRef> NSErrorToErrorFn;
    Optional<SILDeclRef> ErrorToNSErrorFn;
    Optional<SILDeclRef> BoolToWindowsBoolFn;
    Optional<SILDeclRef> WindowsBoolToBoolFn;
  
    Optional<ProtocolDecl*> PointerProtocol;
  
    Optional<ProtocolDecl*> ObjectiveCBridgeable;
    Optional<FuncDecl*> BridgeToObjectiveCRequirement;
    Optional<FuncDecl*> UnconditionallyBridgeFromObjectiveCRequirement;
    Optional<AssociatedTypeDecl*> BridgedObjectiveCType;
  
    Optional<ProtocolDecl*> BridgedStoredNSError;
    Optional<VarDecl*> NSErrorRequirement;
  
    Optional<ProtocolConformance *> NSErrorConformanceToError;
  
    Optional<FuncDecl*> RunChildTask;
    Optional<FuncDecl*> TaskFutureGet;
    Optional<FuncDecl*> TaskFutureGetThrowing;
  
    Optional<FuncDecl*> RunTaskForBridgedAsyncMethod;
    Optional<FuncDecl*> ResumeUnsafeContinuation;
    Optional<FuncDecl*> ResumeUnsafeThrowingContinuation;
    Optional<FuncDecl*> ResumeUnsafeThrowingContinuationWithError;
    Optional<FuncDecl*> RunAsyncHandler;
  
  public:
    SILGenModule(SILModule &M, ModuleDecl *SM);
  
    ~SILGenModule();
    
    SILGenModule(SILGenModule const &) = delete;
    void operator=(SILGenModule const &) = delete;
  
    ASTContext &getASTContext() { return M.getASTContext(); }
  
    llvm::StringMap<std::pair<std::string, /*isWinner=*/bool>> FileIDsByFilePath;
  
    static DeclName getMagicFunctionName(SILDeclRef ref);
    static DeclName getMagicFunctionName(DeclContext *dc);
    
    /// Get the function for a SILDeclRef, or return nullptr if it hasn't been
    /// emitted yet.
    SILFunction *getEmittedFunction(SILDeclRef constant,
                                    ForDefinition_t forDefinition);
  
    /// Get the function for a SILDeclRef, creating it if necessary.
    SILFunction *getFunction(SILDeclRef constant,
                             ForDefinition_t forDefinition);
  
    /// Get the dynamic dispatch thunk for a SILDeclRef.
    SILFunction *getDynamicThunk(SILDeclRef constant,
                                 CanSILFunctionType constantTy);
  
    /// Emit a vtable thunk for a derived method if its natural abstraction level
    /// diverges from the overridden base method. If no thunking is needed,
    /// returns a static reference to the derived method.
    Optional<SILVTable::Entry> emitVTableMethod(ClassDecl *theClass,
                                                SILDeclRef derived,
                                                SILDeclRef base);
  
    /// True if a function has been emitted for a given SILDeclRef.
    bool hasFunction(SILDeclRef constant);
  
    /// Get or create the declaration of a reabstraction thunk with the
    /// given signature.
    SILFunction *getOrCreateReabstractionThunk(
                                             CanSILFunctionType thunkType,
                                             CanSILFunctionType fromType,
                                             CanSILFunctionType toType,
                                             CanType dynamicSelfType);
    
    /// Get or create the declaration of a completion handler block
    /// implementation function for an ObjC API that was imported
    /// as `async` in Swift.
    SILFunction *getOrCreateForeignAsyncCompletionHandlerImplFunction(
                                             CanSILFunctionType blockType,
                                             CanType continuationTy,
                                             ForeignAsyncConvention convention);
  
    /// Determine whether the given class has any instance variables that
    /// need to be destroyed.
    bool hasNonTrivialIVars(ClassDecl *cd);
  
    /// Given an original function and a user-specified custom derivative
    /// function, get or create a derivative thunk with the expected derivative
    /// function type computed from the original function.
    ///
    /// To achieve the expected derivative type, the thunk may perform
    /// self-reordering, reabstraction, or both.
    ///
    /// Self-reordering is done for canonicalizing the types of derivative
    /// functions for instance methods wrt `self`. We want users to define
    /// derivatives with the following AST function types:
    ///
    /// JVP:
    /// - Takes `Self` as first parameter.
    /// - Returns differential taking `Self.Tan` as first parameter.
    ///
    ///     (Self) -> (T, ...) -> (R, (Self.Tan, T.Tan, ...) -> R.Tan)
    ///
    /// VJP:
    /// - Takes `Self` as first parameter.
    /// - Returns pullback returning `Self.Tan` as first result.
    ///
    ///     (Self) -> (T, ...) -> (R, (R.Tan) -> (Self.Tan, T.Tan, ...))
    ///
    /// However, the curried `Self` parameter in the AST JVP/VJP function types
    /// becomes the *last* parameter in the flattened parameter list of their
    /// lowered SIL function types.
    ///
    /// JVP:
    /// - Takes `Self` as *last* parameter.
    /// - Returns differential taking `Self.Tan` as *first* parameter.
    ///
    ///     $(T, ..., Self) -> (R, (Self.Tan, T.Tan, ...) -> R.Tan)
    ///
    /// VJP:
    /// - Takes `Self` as *last* parameter.
    /// - Returns pullback returning `Self.Tan` as *first* result.
    ///
    ///     $(T, ..., Self) -> (R, (R.Tan) -> (Self.Tan, T.Tan, ...))
    ///
    /// This leads to a parameter ordering inconsistency, and would require the
    /// differentiation transform to handle "wrt `self` instance method
    /// derivatives" specially. However, canonicalization during SILGen makes the
    /// parameter ordering uniform for "instance method derivatives wrt self" and
    /// simplifies the transform rules.
    ///
    /// If `self` must be reordered, reorder it so that it appears as:
    /// - The last parameter in the returned differential.
    /// - The last result in the returned pullback.
    SILFunction *getOrCreateCustomDerivativeThunk(
        AbstractFunctionDecl *originalAFD, SILFunction *originalFn,
        SILFunction *customDerivativeFn, AutoDiffConfig config,
        AutoDiffDerivativeFunctionKind kind);
  
    /// Get or create a derivative function vtable entry thunk for the given
    /// SILDeclRef and derivative function type.
    SILFunction *
    getOrCreateAutoDiffClassMethodThunk(SILDeclRef derivativeFnRef,
                                        CanSILFunctionType derivativeFnTy);
  
    /// Determine whether we need to emit an ivar destroyer for the given class.
    /// An ivar destroyer is needed if a superclass of this class may define a
    /// failing designated initializer.
    bool requiresIVarDestroyer(ClassDecl *cd);
  
    //===--------------------------------------------------------------------===//
    // Visitors for top-level forms
    //===--------------------------------------------------------------------===//
  
    // These are either not allowed at global scope or don't require
    // code emission.
    void visitImportDecl(ImportDecl *d);
    void visitEnumCaseDecl(EnumCaseDecl *d) {}
    void visitEnumElementDecl(EnumElementDecl *d) {}
    void visitOperatorDecl(OperatorDecl *d) {}
    void visitPrecedenceGroupDecl(PrecedenceGroupDecl *d) {}
    void visitTypeAliasDecl(TypeAliasDecl *d) {}
    void visitOpaqueTypeDecl(OpaqueTypeDecl *d) {}
    void visitAbstractTypeParamDecl(AbstractTypeParamDecl *d) {}
    void visitConstructorDecl(ConstructorDecl *d) {}
    void visitDestructorDecl(DestructorDecl *d) {}
    void visitModuleDecl(ModuleDecl *d) { }
    void visitMissingMemberDecl(MissingMemberDecl *d) {}
  
    // Emitted as part of its storage.
    void visitAccessorDecl(AccessorDecl *ad) {}
  
    void visitFuncDecl(FuncDecl *fd);
    void visitPatternBindingDecl(PatternBindingDecl *vd);
    void visitTopLevelCodeDecl(TopLevelCodeDecl *td);
    void visitIfConfigDecl(IfConfigDecl *icd);
    void visitPoundDiagnosticDecl(PoundDiagnosticDecl *PDD);
    void visitNominalTypeDecl(NominalTypeDecl *ntd);
    void visitExtensionDecl(ExtensionDecl *ed);
    void visitVarDecl(VarDecl *vd);
    void visitSubscriptDecl(SubscriptDecl *sd);
  
    void emitAbstractFuncDecl(AbstractFunctionDecl *AFD);
    
    /// Generates code for the given FuncDecl and adds the
    /// SILFunction to the current SILModule under the name SILDeclRef(decl). For
    /// curried functions, curried entry point Functions are also generated and
    /// added to the current SILModule.
    void emitFunction(FuncDecl *fd);
  
    /// Emits the function definition for a given SILDeclRef.
    void emitFunctionDefinition(SILDeclRef constant, SILFunction *f);
  
    /// Generates code for the given closure expression and adds the
    /// SILFunction to the current SILModule under the name SILDeclRef(ce).
    SILFunction *emitClosure(AbstractClosureExpr *ce);
    /// Generates code for the given ConstructorDecl and adds
    /// the SILFunction to the current SILModule under the name SILDeclRef(decl).
    void emitConstructor(ConstructorDecl *decl);
  
    /// Generates code for the given class's destructor and adds
    /// the SILFunction to the current SILModule under the name
    /// SILDeclRef(cd, Destructor).
    void emitDestructor(ClassDecl *cd, DestructorDecl *dd);
  
    /// Emits the default argument generator with the given expression.
    void emitDefaultArgGenerator(SILDeclRef constant, ParamDecl *param);
  
    /// Emits the stored property initializer for the given pattern.
    void emitStoredPropertyInitialization(PatternBindingDecl *pd, unsigned i);
  
    /// Emits the backing initializer for a property with an attached wrapper.
    void emitPropertyWrapperBackingInitializer(VarDecl *var);
  
    /// Emits default argument generators for the given parameter list.
    void emitDefaultArgGenerators(SILDeclRef::Loc decl,
                                  ParameterList *paramList);
    
    /// Emits a thunk from a foreign function to the native Swift convention.
    void emitForeignToNativeThunk(SILDeclRef thunk);
  
    /// Emits a thunk from a Swift function to the native Swift convention.
    void emitNativeToForeignThunk(SILDeclRef thunk);
    
    void preEmitFunction(SILDeclRef constant, SILFunction *F, SILLocation L);
    void postEmitFunction(SILDeclRef constant, SILFunction *F);
    
    /// Add a global variable to the SILModule.
    void addGlobalVariable(VarDecl *global);
  
    /// Emit the ObjC-compatible entry point for a method.
    void emitObjCMethodThunk(FuncDecl *method);
    
    /// Emit the ObjC-compatible getter and setter for a property.
    void emitObjCPropertyMethodThunks(AbstractStorageDecl *prop);
  
    /// Emit the ObjC-compatible entry point for a constructor.
    void emitObjCConstructorThunk(ConstructorDecl *constructor);
  
    /// Emit the ObjC-compatible entry point for a destructor (i.e., -dealloc).
    void emitObjCDestructorThunk(DestructorDecl *destructor);
  
    /// Get or emit the witness table for a protocol conformance.
    SILWitnessTable *getWitnessTable(NormalProtocolConformance *conformance);
  
    /// Emit a protocol witness entry point.
    SILFunction *
    emitProtocolWitness(ProtocolConformanceRef conformance, SILLinkage linkage,
                        IsSerialized_t isSerialized, SILDeclRef requirement,
                        SILDeclRef witnessRef, IsFreeFunctionWitness_t isFree,
                        Witness witness);
  
    /// Emit the default witness table for a resilient protocol.
    void emitDefaultWitnessTable(ProtocolDecl *protocol);
  
    /// Emit the self-conformance witness table for a protocol.
    void emitSelfConformanceWitnessTable(ProtocolDecl *protocol);
  
    /// Emit the lazy initializer function for a global pattern binding
    /// declaration.
    SILFunction *emitLazyGlobalInitializer(StringRef funcName,
                                           PatternBindingDecl *binding,
                                           unsigned pbdEntry);
    
    /// Emit the accessor for a global variable or stored static property.
    ///
    /// This ensures the lazy initializer has been run before returning the
    /// address of the variable.
    void emitGlobalAccessor(VarDecl *global,
                            SILGlobalVariable *onceToken,
                            SILFunction *onceFunc);
  
    /// True if the given function requires an entry point for ObjC method
    /// dispatch.
    bool requiresObjCMethodEntryPoint(FuncDecl *method);
  
    /// True if the given constructor requires an entry point for ObjC method
    /// dispatch.
    bool requiresObjCMethodEntryPoint(ConstructorDecl *constructor);
  
    /// Emit a global initialization.
    void emitGlobalInitialization(PatternBindingDecl *initializer, unsigned elt);
  
    /// Should the self argument of the given method always be emitted as
    /// an r-value (meaning that it can be borrowed only if that is not
    /// semantically detectable), or it acceptable to emit it as a borrowed
    /// storage reference?
    bool shouldEmitSelfAsRValue(FuncDecl *method, CanType selfType);
  
    /// Is the self method of the given nonmutating method passed indirectly?
    bool isNonMutatingSelfIndirect(SILDeclRef method);
  
    SILDeclRef getAccessorDeclRef(AccessorDecl *accessor);
  
    bool canStorageUseStoredKeyPathComponent(AbstractStorageDecl *decl,
                                             ResilienceExpansion expansion);
  
    KeyPathPatternComponent
    emitKeyPathComponentForDecl(SILLocation loc,
                                GenericEnvironment *genericEnv,
                                ResilienceExpansion expansion,
                                unsigned &baseOperand,
                                bool &needsGenericContext,
                                SubstitutionMap subs,
                                AbstractStorageDecl *storage,
                                ArrayRef<ProtocolConformanceRef> indexHashables,
                                CanType baseTy,
                                DeclContext *useDC,
                                bool forPropertyDescriptor);
  
    /// Emit all differentiability witnesses for the given function, visiting its
    /// `@differentiable` and `@derivative` attributes.
    void emitDifferentiabilityWitnessesForFunction(SILDeclRef constant,
                                                   SILFunction *F);
  
    /// Emit the differentiability witness for the given original function
    /// declaration and SIL function, autodiff configuration, and JVP and VJP
    /// functions (null if undefined).
    void emitDifferentiabilityWitness(AbstractFunctionDecl *originalAFD,
                                      SILFunction *originalFunction,
                                      const AutoDiffConfig &config,
                                      SILFunction *jvp, SILFunction *vjp,
                                      const DeclAttribute *diffAttr);
  
    /// Known functions for bridging.
    SILDeclRef getStringToNSStringFn();
    SILDeclRef getNSStringToStringFn();
    SILDeclRef getArrayToNSArrayFn();
    SILDeclRef getNSArrayToArrayFn();
    SILDeclRef getDictionaryToNSDictionaryFn();
    SILDeclRef getNSDictionaryToDictionaryFn();
    SILDeclRef getSetToNSSetFn();
    SILDeclRef getNSSetToSetFn();
    SILDeclRef getBoolToObjCBoolFn();
    SILDeclRef getObjCBoolToBoolFn();
    SILDeclRef getBoolToDarwinBooleanFn();
    SILDeclRef getDarwinBooleanToBoolFn();
    SILDeclRef getBoolToWindowsBoolFn();
    SILDeclRef getWindowsBoolToBoolFn();
    SILDeclRef getNSErrorToErrorFn();
    SILDeclRef getErrorToNSErrorFn();
  
  #define FUNC_DECL(NAME, ID) \
    FuncDecl *get##NAME(SILLocation loc);
  #include "swift/AST/KnownDecls.def"
    
    /// Retrieve the _ObjectiveCBridgeable protocol definition.
    ProtocolDecl *getObjectiveCBridgeable(SILLocation loc);
  
    /// Retrieve the _ObjectiveCBridgeable._bridgeToObjectiveC requirement.
    FuncDecl *getBridgeToObjectiveCRequirement(SILLocation loc);
  
    /// Retrieve the
    /// _ObjectiveCBridgeable._unconditionallyBridgeFromObjectiveC
    /// requirement.
    FuncDecl *getUnconditionallyBridgeFromObjectiveCRequirement(SILLocation loc);
  
    /// Retrieve the _ObjectiveCBridgeable._ObjectiveCType requirement.
    AssociatedTypeDecl *getBridgedObjectiveCTypeRequirement(SILLocation loc);
  
    /// Find the conformance of the given Swift type to the
    /// _ObjectiveCBridgeable protocol.
    ProtocolConformance *getConformanceToObjectiveCBridgeable(SILLocation loc,
                                                              Type type);
  
    /// Retrieve the _BridgedStoredNSError protocol definition.
    ProtocolDecl *getBridgedStoredNSError(SILLocation loc);
  
    /// Retrieve the _BridgedStoredNSError._nsError requirement.
    VarDecl *getNSErrorRequirement(SILLocation loc);
  
    /// Find the conformance of the given Swift type to the
    /// _BridgedStoredNSError protocol.
    ProtocolConformanceRef getConformanceToBridgedStoredNSError(SILLocation loc,
                                                                Type type);
  
    /// Retrieve the conformance of NSError to the Error protocol.
    ProtocolConformance *getNSErrorConformanceToError();
  
    /// Retrieve the _Concurrency._runChildTask intrinsic.
    FuncDecl *getRunChildTask();
  
    /// Retrieve the _Concurrency._taskFutureGet intrinsic.
    FuncDecl *getTaskFutureGet();
  
    /// Retrieve the _Concurrency._taskFutureGetThrowing intrinsic.
    FuncDecl *getTaskFutureGetThrowing();
  
    /// Retrieve the _Concurrency._resumeUnsafeContinuation intrinsic.
    FuncDecl *getResumeUnsafeContinuation();
    /// Retrieve the _Concurrency._resumeUnsafeThrowingContinuation intrinsic.
    FuncDecl *getResumeUnsafeThrowingContinuation();
    /// Retrieve the _Concurrency._resumeUnsafeThrowingContinuationWithError intrinsic.
    FuncDecl *getResumeUnsafeThrowingContinuationWithError();
    /// Retrieve the _Concurrency._runAsyncHandler intrinsic.
    FuncDecl *getRunAsyncHandler();
    /// Retrieve the _Concurrency._runTaskForBridgedAsyncMethod intrinsic.
    FuncDecl *getRunTaskForBridgedAsyncMethod();
  
    SILFunction *getKeyPathProjectionCoroutine(bool isReadAccess,
                                               KeyPathTypeKind typeKind);
  
    /// Report a diagnostic.
    template<typename...T, typename...U>
    InFlightDiagnostic diagnose(SourceLoc loc, Diag<T...> diag,
                  U &&...args) {
      return M.getASTContext().Diags.diagnose(loc, diag, std::forward<U>(args)...);
    }
  
    template<typename...T, typename...U>
    InFlightDiagnostic diagnose(SILLocation loc, Diag<T...> diag,
                  U &&...args) {
      return M.getASTContext().Diags.diagnose(loc.getSourceLoc(),
                                       diag, std::forward<U>(args)...);
    }
  
    /// Get or create SILGlobalVariable for a given global VarDecl.
    SILGlobalVariable *getSILGlobalVariable(VarDecl *gDecl,
                                            ForDefinition_t forDef);
  
    /// Emit all lazy conformances referenced from this function body.
    void emitLazyConformancesForFunction(SILFunction *F);
  
    /// Emit all lazy conformances referenced from this type's signature and
    /// stored properties (or in the case of enums, associated values).
    void emitLazyConformancesForType(NominalTypeDecl *NTD);
  
    /// Mark a protocol conformance as used, so we know we need to emit it if
    /// it's in our TU.
    void useConformance(ProtocolConformanceRef conformance);
  
    /// Mark protocol conformances from the given type as used.
    void useConformancesFromType(CanType type);
  
    /// Mark protocol conformances from the given set of substitutions as used.
    void useConformancesFromSubstitutions(SubstitutionMap subs);
  
    /// Mark _ObjectiveCBridgeable conformances as used for any imported types
    /// mentioned by the given type.
    void useConformancesFromObjectiveCType(CanType type);
  
    /// Emit a `mark_function_escape` instruction for top-level code when a
    /// function or closure at top level refers to script globals.
    void emitMarkFunctionEscapeForTopLevelCodeGlobals(SILLocation loc,
                                                      CaptureInfo captureInfo);
  
    /// Map the substitutions for the original declaration to substitutions for
    /// the overridden declaration.
    static SubstitutionMap mapSubstitutionsForWitnessOverride(
                                                 AbstractFunctionDecl *original,
                                                 AbstractFunctionDecl *overridden,
                                                 SubstitutionMap subs);
  
    /// Emit a property descriptor for the given storage decl if it needs one.
    void tryEmitPropertyDescriptor(AbstractStorageDecl *decl);
  
  private:
    /// Emit the deallocator for a class that uses the objc allocator.
    void emitObjCAllocatorDestructor(ClassDecl *cd, DestructorDecl *dd);
  };
   
  } // end namespace Lowering
  } // end namespace swift
  
  #endif
  