text: //===--- SILGen.cpp - Implements Lowering of ASTs -> SIL ------------------===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2020 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
  //
  //===----------------------------------------------------------------------===//
  
  #define DEBUG_TYPE "silgen"
  #include "ManagedValue.h"
  #include "RValue.h"
  #include "SILGenFunction.h"
  #include "SILGenFunctionBuilder.h"
  #include "Scope.h"
  #include "swift/AST/DiagnosticsSIL.h"
  #include "swift/AST/Evaluator.h"
  #include "swift/AST/GenericEnvironment.h"
  #include "swift/AST/Initializer.h"
  #include "swift/AST/NameLookup.h"
  #include "swift/AST/ParameterList.h"
  #include "swift/AST/PrettyStackTrace.h"
  #include "swift/AST/PropertyWrappers.h"
  #include "swift/AST/ProtocolConformance.h"
  #include "swift/AST/ResilienceExpansion.h"
  #include "swift/AST/SourceFile.h"
  #include "swift/AST/TypeCheckRequests.h"
  #include "swift/Basic/Statistic.h"
  #include "swift/ClangImporter/ClangModule.h"
  #include "swift/SIL/PrettyStackTrace.h"
  #include "swift/SIL/SILArgument.h"
  #include "swift/SIL/SILDebugScope.h"
  #include "swift/SIL/SILProfiler.h"
  #include "swift/AST/SILGenRequests.h"
  #include "swift/Serialization/SerializedModuleLoader.h"
  #include "swift/Serialization/SerializedSILLoader.h"
  #include "swift/Strings.h"
  #include "swift/Subsystems.h"
  #include "llvm/ProfileData/InstrProfReader.h"
  #include "llvm/Support/Debug.h"
  using namespace swift;
  using namespace Lowering;
  
  //===----------------------------------------------------------------------===//
  // SILGenModule Class implementation
  //===----------------------------------------------------------------------===//
  
  SILGenModule::SILGenModule(SILModule &M, ModuleDecl *SM)
      : M(M), Types(M.Types), SwiftModule(SM), TopLevelSGF(nullptr),
        FileIDsByFilePath(SM->computeFileIDMap(/*shouldDiagnose=*/true)) {
    const SILOptions &Opts = M.getOptions();
    if (!Opts.UseProfile.empty()) {
      auto ReaderOrErr = llvm::IndexedInstrProfReader::create(Opts.UseProfile);
      if (auto E = ReaderOrErr.takeError()) {
        diagnose(SourceLoc(), diag::profile_read_error, Opts.UseProfile,
                 llvm::toString(std::move(E)));
      } else {
        M.setPGOReader(std::move(ReaderOrErr.get()));
      }
    }
  }
  
  SILGenModule::~SILGenModule() {
    assert(!TopLevelSGF && "active source file lowering!?");
    M.verify();
  }
  
  static SILDeclRef
  getBridgingFn(Optional<SILDeclRef> &cacheSlot,
                SILGenModule &SGM,
                Identifier moduleName,
                StringRef functionName,
                std::initializer_list<Type> inputTypes,
                Type outputType) {
    if (!cacheSlot) {
      ASTContext &ctx = SGM.M.getASTContext();
      ModuleDecl *mod = ctx.getLoadedModule(moduleName);
      if (!mod) {
        SGM.diagnose(SourceLoc(), diag::bridging_module_missing,
                     moduleName.str(), functionName);
        llvm::report_fatal_error("unable to set up the ObjC bridge!");
      }
  
      SmallVector<ValueDecl *, 2> decls;
      mod->lookupValue(ctx.getIdentifier(functionName),
                       NLKind::QualifiedLookup, decls);
      if (decls.empty()) {
        SGM.diagnose(SourceLoc(), diag::bridging_function_missing,
                     moduleName.str(), functionName);
        llvm::report_fatal_error("unable to set up the ObjC bridge!");
      }
      if (decls.size() != 1) {
        SGM.diagnose(SourceLoc(), diag::bridging_function_overloaded,
                     moduleName.str(), functionName);
        llvm::report_fatal_error("unable to set up the ObjC bridge!");
      }
  
      auto *fd = dyn_cast<FuncDecl>(decls.front());
      if (!fd) {
        SGM.diagnose(SourceLoc(), diag::bridging_function_not_function,
                     moduleName.str(), functionName);
        llvm::report_fatal_error("unable to set up the ObjC bridge!");
      }
  
      // Check that the function takes the expected arguments and returns the
      // expected result type.
      SILDeclRef c(fd);
      auto funcTy =
          SGM.Types.getConstantFunctionType(TypeExpansionContext::minimal(), c);
      SILFunctionConventions fnConv(funcTy, SGM.M);
  
      auto toSILType = [&SGM](Type ty) {
        return SGM.Types.getLoweredType(ty, TypeExpansionContext::minimal());
      };
  
      if (fnConv.hasIndirectSILResults() ||
          funcTy->getNumParameters() != inputTypes.size() ||
          !std::equal(
              fnConv.getParameterSILTypes(TypeExpansionContext::minimal())
                  .begin(),
              fnConv.getParameterSILTypes(TypeExpansionContext::minimal()).end(),
              makeTransformIterator(inputTypes.begin(), toSILType))) {
        SGM.diagnose(fd->getLoc(), diag::bridging_function_not_correct_type,
                     moduleName.str(), functionName);
        llvm::report_fatal_error("unable to set up the ObjC bridge!");
      }
  
      if (fnConv.getSingleSILResultType(TypeExpansionContext::minimal()) !=
          toSILType(outputType)) {
        SGM.diagnose(fd->getLoc(), diag::bridging_function_not_correct_type,
                     moduleName.str(), functionName);
        llvm::report_fatal_error("unable to set up the ObjC bridge!");
      }
  
      cacheSlot = c;
    }
  
    LLVM_DEBUG(llvm::dbgs() << "bridging function "
                            << moduleName << '.' << functionName
                            << " mapped to ";
               cacheSlot->print(llvm::dbgs()));
  
    return *cacheSlot;
  }
  
  #define REQUIRED(X) Types.get##X##Type()
  #define OPTIONAL(X) OptionalType::get(Types.get##X##Type())
  
  #define GET_BRIDGING_FN(Module, FromKind, FromTy, ToKind, ToTy) \
    SILDeclRef SILGenModule::get##FromTy##To##ToTy##Fn() { \
      return getBridgingFn(FromTy##To##ToTy##Fn, *this, \
                           getASTContext().Id_##Module, \
                           "_convert" #FromTy "To" #ToTy, \
                           { FromKind(FromTy) }, \
                           ToKind(ToTy)); \
    }
  
  GET_BRIDGING_FN(Darwin, REQUIRED, Bool, REQUIRED, DarwinBoolean)
  GET_BRIDGING_FN(Darwin, REQUIRED, DarwinBoolean, REQUIRED, Bool)
  GET_BRIDGING_FN(ObjectiveC, REQUIRED, Bool, REQUIRED, ObjCBool)
  GET_BRIDGING_FN(ObjectiveC, REQUIRED, ObjCBool, REQUIRED, Bool)
  GET_BRIDGING_FN(Foundation, OPTIONAL, NSError, REQUIRED, Error)
  GET_BRIDGING_FN(Foundation, REQUIRED, Error, REQUIRED, NSError)
  GET_BRIDGING_FN(WinSDK, REQUIRED, Bool, REQUIRED, WindowsBool)
  GET_BRIDGING_FN(WinSDK, REQUIRED, WindowsBool, REQUIRED, Bool)
  
  #undef GET_BRIDGING_FN
  #undef REQUIRED
  #undef OPTIONAL
  
  static FuncDecl *diagnoseMissingIntrinsic(SILGenModule &sgm,
                                            SILLocation loc,
                                            const char *name) {
    sgm.diagnose(loc, diag::bridging_function_missing,
                 sgm.getASTContext().StdlibModuleName.str(), name);
    return nullptr;
  }
  
  #define FUNC_DECL(NAME, ID)                             \
    FuncDecl *SILGenModule::get##NAME(SILLocation loc) {  \
      if (auto fn = getASTContext().get##NAME())   \
        return fn;                                        \
      return diagnoseMissingIntrinsic(*this, loc, ID);    \
    }
  #include "swift/AST/KnownDecls.def"
  
  ProtocolDecl *SILGenModule::getObjectiveCBridgeable(SILLocation loc) {
    if (ObjectiveCBridgeable)
      return *ObjectiveCBridgeable;
  
    // Find the _ObjectiveCBridgeable protocol.
    auto &ctx = getASTContext();
    auto proto = ctx.getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
    if (!proto)
      diagnose(loc, diag::bridging_objcbridgeable_missing);
  
    ObjectiveCBridgeable = proto;
    return proto;
  }
  
  FuncDecl *SILGenModule::getBridgeToObjectiveCRequirement(SILLocation loc) {
    if (BridgeToObjectiveCRequirement)
      return *BridgeToObjectiveCRequirement;
  
    // Find the _ObjectiveCBridgeable protocol.
    auto proto = getObjectiveCBridgeable(loc);
    if (!proto) {
      BridgeToObjectiveCRequirement = nullptr;
      return nullptr;
    }
  
    // Look for _bridgeToObjectiveC().
    auto &ctx = getASTContext();
    DeclName name(ctx, ctx.Id_bridgeToObjectiveC, llvm::ArrayRef<Identifier>());
    auto *found = dyn_cast_or_null<FuncDecl>(
      proto->getSingleRequirement(name));
  
    if (!found)
      diagnose(loc, diag::bridging_objcbridgeable_broken, name);
  
    BridgeToObjectiveCRequirement = found;
    return found;
  }
  
  FuncDecl *SILGenModule::getUnconditionallyBridgeFromObjectiveCRequirement(
      SILLocation loc) {
    if (UnconditionallyBridgeFromObjectiveCRequirement)
      return *UnconditionallyBridgeFromObjectiveCRequirement;
  
    // Find the _ObjectiveCBridgeable protocol.
    auto proto = getObjectiveCBridgeable(loc);
    if (!proto) {
      UnconditionallyBridgeFromObjectiveCRequirement = nullptr;
      return nullptr;
    }
  
    // Look for _bridgeToObjectiveC().
    auto &ctx = getASTContext();
    DeclName name(ctx, ctx.getIdentifier("_unconditionallyBridgeFromObjectiveC"),
                  llvm::makeArrayRef(Identifier()));
    auto *found = dyn_cast_or_null<FuncDecl>(
      proto->getSingleRequirement(name));
  
    if (!found)
      diagnose(loc, diag::bridging_objcbridgeable_broken, name);
  
    UnconditionallyBridgeFromObjectiveCRequirement = found;
    return found;
  }
  
  AssociatedTypeDecl *
  SILGenModule::getBridgedObjectiveCTypeRequirement(SILLocation loc) {
    if (BridgedObjectiveCType)
      return *BridgedObjectiveCType;
  
    // Find the _ObjectiveCBridgeable protocol.
    auto proto = getObjectiveCBridgeable(loc);
    if (!proto) {
      BridgeToObjectiveCRequirement = nullptr;
      return nullptr;
    }
  
    // Look for _bridgeToObjectiveC().
    auto &ctx = getASTContext();
    auto *found = proto->getAssociatedType(ctx.Id_ObjectiveCType);
    if (!found)
      diagnose(loc, diag::bridging_objcbridgeable_broken, ctx.Id_ObjectiveCType);
  
    BridgedObjectiveCType = found;
    return found;
  }
  
  ProtocolConformance *
  SILGenModule::getConformanceToObjectiveCBridgeable(SILLocation loc, Type type) {
    auto proto = getObjectiveCBridgeable(loc);
    if (!proto) return nullptr;
  
    // Find the conformance to _ObjectiveCBridgeable.
    auto result = SwiftModule->lookupConformance(type, proto);
    if (result.isInvalid())
      return nullptr;
  
    return result.getConcrete();
  }
  
  ProtocolDecl *SILGenModule::getBridgedStoredNSError(SILLocation loc) {
    if (BridgedStoredNSError)
      return *BridgedStoredNSError;
  
    // Find the _BridgedStoredNSError protocol.
    auto &ctx = getASTContext();
    auto proto = ctx.getProtocol(KnownProtocolKind::BridgedStoredNSError);
    BridgedStoredNSError = proto;
    return proto;
  }
  
  VarDecl *SILGenModule::getNSErrorRequirement(SILLocation loc) {
    if (NSErrorRequirement)
      return *NSErrorRequirement;
  
    // Find the _BridgedStoredNSError protocol.
    auto proto = getBridgedStoredNSError(loc);
    if (!proto) {
      NSErrorRequirement = nullptr;
      return nullptr;
    }
  
    // Look for _nsError.
    auto &ctx = getASTContext();
    auto *found = dyn_cast_or_null<VarDecl>(
        proto->getSingleRequirement(ctx.Id_nsError));
  
    NSErrorRequirement = found;
    return found;
  }
  
  ProtocolConformanceRef
  SILGenModule::getConformanceToBridgedStoredNSError(SILLocation loc, Type type) {
    auto proto = getBridgedStoredNSError(loc);
    if (!proto)
      return ProtocolConformanceRef::forInvalid();
  
    // Find the conformance to _BridgedStoredNSError.
    return SwiftModule->lookupConformance(type, proto);
  }
  
  static FuncDecl *lookupConcurrencyIntrinsic(ASTContext &C,
                                              Optional<FuncDecl*> &cache,
                                              StringRef name) {
    if (cache)
      return *cache;
    
    auto *module = C.getLoadedModule(C.Id_Concurrency);
    if (!module) {
      cache = nullptr;
      return nullptr;
    }
    
    SmallVector<ValueDecl *, 1> decls;
    module->lookupQualified(module,
                       DeclNameRef(C.getIdentifier(name)),
                       NL_QualifiedDefault | NL_IncludeUsableFromInline,
                       decls);
  
    if (decls.size() != 1) {
      cache = nullptr;
      return nullptr;
    }
    auto func = dyn_cast<FuncDecl>(decls[0]);
    cache = func;
    return func;
  }
  
  FuncDecl *
  SILGenModule::getRunChildTask() {
    return lookupConcurrencyIntrinsic(getASTContext(),
                                      RunChildTask,
                                      "_runChildTask");
  }
  
  FuncDecl *
  SILGenModule::getTaskFutureGet() {
    return lookupConcurrencyIntrinsic(getASTContext(),
                                      TaskFutureGet,
                                      "_taskFutureGet");
  }
  
  FuncDecl *
  SILGenModule::getTaskFutureGetThrowing() {
    return lookupConcurrencyIntrinsic(getASTContext(),
                                      TaskFutureGetThrowing,
                                      "_taskFutureGetThrowing");
  }
  
  FuncDecl *
  SILGenModule::getResumeUnsafeContinuation() {
    return lookupConcurrencyIntrinsic(getASTContext(),
                                      ResumeUnsafeContinuation,
                                      "_resumeUnsafeContinuation");
  }
  FuncDecl *
  SILGenModule::getResumeUnsafeThrowingContinuation() {
    return lookupConcurrencyIntrinsic(getASTContext(),
                                      ResumeUnsafeThrowingContinuation,
                                      "_resumeUnsafeThrowingContinuation");
  }
  FuncDecl *
  SILGenModule::getResumeUnsafeThrowingContinuationWithError() {
    return lookupConcurrencyIntrinsic(getASTContext(),
                                      ResumeUnsafeThrowingContinuationWithError,
                                    "_resumeUnsafeThrowingContinuationWithError");
  }
  FuncDecl *
  SILGenModule::getRunTaskForBridgedAsyncMethod() {
    return lookupConcurrencyIntrinsic(getASTContext(),
                                      RunTaskForBridgedAsyncMethod,
                                      "_runTaskForBridgedAsyncMethod");
  }
  FuncDecl *
  SILGenModule::getRunAsyncHandler() {
    return lookupConcurrencyIntrinsic(getASTContext(), RunAsyncHandler,
                                      "_runAsyncHandler");
  }
  
  ProtocolConformance *SILGenModule::getNSErrorConformanceToError() {
    if (NSErrorConformanceToError)
      return *NSErrorConformanceToError;
  
    auto &ctx = getASTContext();
    auto nsErrorTy = ctx.getNSErrorType();
    if (!nsErrorTy) {
      NSErrorConformanceToError = nullptr;
      return nullptr;
    }
  
    auto error = ctx.getErrorDecl();
    if (!error) {
      NSErrorConformanceToError = nullptr;
      return nullptr;
    }
  
    auto conformance =
      SwiftModule->lookupConformance(nsErrorTy, cast<ProtocolDecl>(error));
  
    if (conformance.isConcrete())
      NSErrorConformanceToError = conformance.getConcrete();
    else
      NSErrorConformanceToError = nullptr;
    return *NSErrorConformanceToError;
  }
  
  SILFunction *
  SILGenModule::getKeyPathProjectionCoroutine(bool isReadAccess,
                                              KeyPathTypeKind typeKind) {
    bool isBaseInout;
    bool isResultInout;
    StringRef functionName;
    NominalTypeDecl *keyPathDecl;
    if (isReadAccess) {
      assert(typeKind == KPTK_KeyPath ||
             typeKind == KPTK_WritableKeyPath ||
             typeKind == KPTK_ReferenceWritableKeyPath);
      functionName = "swift_readAtKeyPath";
      isBaseInout = false;
      isResultInout = false;
      keyPathDecl = getASTContext().getKeyPathDecl();
    } else if (typeKind == KPTK_WritableKeyPath) {
      functionName = "swift_modifyAtWritableKeyPath";
      isBaseInout = true;
      isResultInout = true;
      keyPathDecl = getASTContext().getWritableKeyPathDecl();
    } else if (typeKind == KPTK_ReferenceWritableKeyPath) {
      functionName = "swift_modifyAtReferenceWritableKeyPath";
      isBaseInout = false;
      isResultInout = true;
      keyPathDecl = getASTContext().getReferenceWritableKeyPathDecl();
    } else {
      llvm_unreachable("bad combination");
    }
  
    auto fn = M.lookUpFunction(functionName);
    if (fn) return fn;
  
    auto rootType = CanGenericTypeParamType::get(0, 0, getASTContext());
    auto valueType = CanGenericTypeParamType::get(0, 1, getASTContext());
  
    // Build the generic signature <A, B>.
    auto sig = GenericSignature::get({rootType, valueType}, {});
  
    auto keyPathTy = BoundGenericType::get(keyPathDecl, Type(),
                                           { rootType, valueType })
      ->getCanonicalType();
  
    // (@in_guaranteed/@inout Root, @guaranteed KeyPath<Root, Value>)
    SILParameterInfo params[] = {
      { rootType,
        isBaseInout ? ParameterConvention::Indirect_Inout
                    : ParameterConvention::Indirect_In_Guaranteed },
      { keyPathTy, ParameterConvention::Direct_Guaranteed },
    };
  
    // -> @yields @in_guaranteed/@inout Value
    SILYieldInfo yields[] = {
      { valueType,
        isResultInout ? ParameterConvention::Indirect_Inout
                      : ParameterConvention::Indirect_In_Guaranteed },
    };
  
    auto extInfo = SILFunctionType::ExtInfo::getThin();
  
    auto functionTy = SILFunctionType::get(sig, extInfo,
                                           SILCoroutineKind::YieldOnce,
                                           ParameterConvention::Direct_Unowned,
                                           params,
                                           yields,
                                           /*results*/ {},
                                           /*error result*/ {},
                                           SubstitutionMap(),
                                           SubstitutionMap(),
                                           getASTContext());
  
    auto env = sig->getGenericEnvironment();
  
    SILGenFunctionBuilder builder(*this);
    fn = builder.createFunction(SILLinkage::PublicExternal,
                                functionName,
                                functionTy,
                                env,
                                /*location*/ None,
                                IsNotBare,
                                IsNotTransparent,
                                IsNotSerialized,
                                IsNotDynamic);
  
    return fn;
  }
  
  
  SILFunction *SILGenModule::emitTopLevelFunction(SILLocation Loc) {
    ASTContext &C = getASTContext();
  
    // Use standard library types if we have them; otherwise, fall back to
    // builtins.
    CanType Int32Ty;
    if (auto Int32Decl = C.getInt32Decl()) {
      Int32Ty = Int32Decl->getDeclaredInterfaceType()->getCanonicalType();
    } else {
      Int32Ty = CanType(BuiltinIntegerType::get(32, C));
    }
  
    CanType PtrPtrInt8Ty = C.TheRawPointerType;
    if (auto PointerDecl = C.getUnsafeMutablePointerDecl()) {
      if (auto Int8Decl = C.getInt8Decl()) {
        Type Int8Ty = Int8Decl->getDeclaredInterfaceType();
        Type PointerInt8Ty = BoundGenericType::get(PointerDecl,
                                                   nullptr,
                                                   Int8Ty);
        Type OptPointerInt8Ty = OptionalType::get(PointerInt8Ty);
        PtrPtrInt8Ty = BoundGenericType::get(PointerDecl,
                                             nullptr,
                                             OptPointerInt8Ty)
          ->getCanonicalType();
      }
    }
  
    SILParameterInfo params[] = {
      SILParameterInfo(Int32Ty, ParameterConvention::Direct_Unowned),
      SILParameterInfo(PtrPtrInt8Ty, ParameterConvention::Direct_Unowned),
    };
    SILResultInfo results[] = {SILResultInfo(Int32Ty, ResultConvention::Unowned)};
  
    auto rep = SILFunctionType::Representation::CFunctionPointer;
    auto *clangTy = C.getCanonicalClangFunctionType(params, results[0], rep);
    auto extInfo = SILFunctionType::ExtInfoBuilder()
                       .withRepresentation(rep)
                       .withClangFunctionType(clangTy)
                       .build();
  
    CanSILFunctionType topLevelType = SILFunctionType::get(nullptr, extInfo,
                                     SILCoroutineKind::None,
                                     ParameterConvention::Direct_Unowned,
                                     params, /*yields*/ {},
                                     SILResultInfo(Int32Ty,
                                                   ResultConvention::Unowned),
                                     None,
                                     SubstitutionMap(), SubstitutionMap(),
                                     C);
  
    auto name = getASTContext().getEntryPointFunctionName();
    SILGenFunctionBuilder builder(*this);
    return builder.createFunction(
        SILLinkage::Public, name, topLevelType, nullptr,
        Loc, IsBare, IsNotTransparent, IsNotSerialized, IsNotDynamic,
        ProfileCounter(), IsNotThunk, SubclassScope::NotApplicable);
  }
  
  SILFunction *SILGenModule::getEmittedFunction(SILDeclRef constant,
                                                ForDefinition_t forDefinition) {
    auto found = emittedFunctions.find(constant);
    if (found != emittedFunctions.end()) {
      SILFunction *F = found->second;
      if (forDefinition) {
        // In all the cases where getConstantLinkage returns something
        // different for ForDefinition, it returns an available-externally
        // linkage.
        if (isAvailableExternally(F->getLinkage())) {
          F->setLinkage(constant.getLinkage(ForDefinition));
        }
      }
      return F;
    }
  
    return nullptr;
  }
  
  static SILFunction *getFunctionToInsertAfter(SILGenModule &SGM,
                                               SILDeclRef insertAfter) {
    // If the decl ref was emitted, emit after its function.
    while (insertAfter) {
      auto found = SGM.emittedFunctions.find(insertAfter);
      if (found != SGM.emittedFunctions.end()) {
        return found->second;
      }
  
      // Otherwise, try to insert after the function we would be transitively
      // be inserted after.
      auto foundDelayed = SGM.delayedFunctions.find(insertAfter);
      if (foundDelayed != SGM.delayedFunctions.end()) {
        insertAfter = foundDelayed->second;
      } else {
        break;
      }
    }
  
    // If the decl ref is nil, just insert at the beginning.
    return nullptr;
  }
  
  static bool haveProfiledAssociatedFunction(SILDeclRef constant) {
    return constant.isDefaultArgGenerator() || constant.isForeign;
  }
  
  /// Set up the function for profiling instrumentation.
  static void setUpForProfiling(SILDeclRef constant, SILFunction *F,
                                ForDefinition_t forDefinition) {
    if (!forDefinition || F->getProfiler())
      return;
  
    ASTNode profiledNode;
    if (!haveProfiledAssociatedFunction(constant)) {
      if (constant.hasDecl()) {
        if (auto *fd = constant.getFuncDecl()) {
          if (fd->hasBody()) {
            F->createProfiler(fd, constant, forDefinition);
            profiledNode = fd->getBody(/*canSynthesize=*/false);
          }
        }
      } else if (auto *ace = constant.getAbstractClosureExpr()) {
        F->createProfiler(ace, constant, forDefinition);
        profiledNode = ace;
      }
      // Set the function entry count for PGO.
      if (SILProfiler *SP = F->getProfiler())
        F->setEntryCount(SP->getExecutionCount(profiledNode));
    }
  }
  
  static bool isEmittedOnDemand(SILModule &M, SILDeclRef constant) {
    if (!constant.hasDecl())
      return false;
  
    if (constant.isForeign)
      return false;
  
    auto *d = constant.getDecl();
    auto *dc = d->getDeclContext();
  
    switch (constant.kind) {
    case SILDeclRef::Kind::Func: {
      auto *fd = cast<FuncDecl>(d);
      if (!fd->hasBody())
        return false;
  
      if (isa<ClangModuleUnit>(dc->getModuleScopeContext()))
        return true;
  
      if (fd->hasForcedStaticDispatch())
        return true;
  
      break;
    }
    case SILDeclRef::Kind::Allocator: {
      auto *cd = cast<ConstructorDecl>(d);
      // For factories, we don't need to emit a special thunk; the normal
      // foreign-to-native thunk is sufficient.
      if (isa<ClangModuleUnit>(dc->getModuleScopeContext()) &&
          !cd->isFactoryInit() &&
          (dc->getSelfClassDecl() ||
           cd->hasBody()))
        return true;
  
      break;
    }
    case SILDeclRef::Kind::EnumElement:
      return true;
    default:
      break;
    }
  
    return false;
  }
  
  SILFunction *SILGenModule::getFunction(SILDeclRef constant,
                                         ForDefinition_t forDefinition) {
    // If we already emitted the function, return it (potentially preparing it
    // for definition).
    if (auto emitted = getEmittedFunction(constant, forDefinition)) {
      setUpForProfiling(constant, emitted, forDefinition);
      return emitted;
    }
  
    // Note: Do not provide any SILLocation. You can set it afterwards.
    SILGenFunctionBuilder builder(*this);
    auto &IGM = *this;
    auto *F = builder.getOrCreateFunction(
        constant.hasDecl() ? constant.getDecl() : (Decl *)nullptr, constant,
        forDefinition,
        [&IGM](SILLocation loc, SILDeclRef constant) -> SILFunction * {
          return IGM.getFunction(constant, NotForDefinition);
        });
    setUpForProfiling(constant, F, forDefinition);
  
    assert(F && "SILFunction should have been defined");
  
    emittedFunctions[constant] = F;
  
    if (!delayedFunctions.count(constant)) {
      if (isEmittedOnDemand(M, constant)) {
        forcedFunctions.push_back(constant);
        return F;
      }
    }
  
    // If we delayed emitting this function previously, we need it now.
    auto foundDelayed = delayedFunctions.find(constant);
    if (foundDelayed != delayedFunctions.end()) {
      // Move the function to its proper place within the module.
      M.functions.remove(F);
      SILFunction *insertAfter = getFunctionToInsertAfter(*this,
                                                foundDelayed->second);
      if (!insertAfter) {
        M.functions.push_front(F);
      } else {
        M.functions.insertAfter(insertAfter->getIterator(), F);
      }
  
      forcedFunctions.push_back(constant);
      delayedFunctions.erase(foundDelayed);
    } else {
      // We would have registered a delayed function as "last emitted" when we
      // enqueued. If the function wasn't delayed, then we're emitting it now.
      lastEmittedFunction = constant;
    }
  
    return F;
  }
  
  bool SILGenModule::hasFunction(SILDeclRef constant) {
    return emittedFunctions.count(constant);
  }
  
  void SILGenModule::visitFuncDecl(FuncDecl *fd) { emitFunction(fd); }
  
  void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
  
    if (constant.isForeignToNativeThunk()) {
      f->setThunk(IsThunk);
      if (constant.asForeign().isClangGenerated())
        f->setSerialized(IsSerializable);
  
      auto loc = constant.getAsRegularLocation();
      loc.markAutoGenerated();
      auto *dc = loc.getAsDeclContext();
      assert(dc);
  
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X("silgen emitForeignToNativeThunk", f);
      SILGenFunction(*this, *f, dc).emitForeignToNativeThunk(constant);
      postEmitFunction(constant, f);
      return;
    }
  
    if (constant.isNativeToForeignThunk()) {
      auto loc = constant.getAsRegularLocation();
      loc.markAutoGenerated();
      auto *dc = loc.getAsDeclContext();
      assert(dc);
  
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X("silgen emitNativeToForeignThunk", f);
      f->setBare(IsBare);
      f->setThunk(IsThunk);
      // If the native function is async, then the foreign entry point is not,
      // so it needs to spawn a detached task in which to run the native
      // implementation, so the actual thunk logic needs to go into a closure
      // implementation function.
      if (constant.hasAsync()) {
        f = SILGenFunction(*this, *f, dc).emitNativeAsyncToForeignThunk(constant);
      }
  
      SILGenFunction(*this, *f, dc).emitNativeToForeignThunk(constant);
  
      postEmitFunction(constant, f);
      return;
    }
  
    switch (constant.kind) {
    case SILDeclRef::Kind::Func: {
      if (auto *ce = constant.getAbstractClosureExpr()) {
        preEmitFunction(constant, f, ce);
        PrettyStackTraceSILFunction X("silgen closureexpr", f);
        SILGenFunction(*this, *f, ce).emitClosure(ce);
        postEmitFunction(constant, f);
        break;
      }
  
      auto *fd = cast<FuncDecl>(constant.getDecl());
  
      preEmitFunction(constant, f, fd);
      PrettyStackTraceSILFunction X("silgen emitFunction", f);
      SILGenFunction(*this, *f, fd).emitFunction(fd);
      postEmitFunction(constant, f);
      break;
    }
  
    case SILDeclRef::Kind::Allocator: {
      auto *decl = cast<ConstructorDecl>(constant.getDecl());
  
      if (decl->getDeclContext()->getSelfClassDecl() &&
          (decl->isDesignatedInit() ||
           decl->isObjC())) {
        preEmitFunction(constant, f, decl);
        PrettyStackTraceSILFunction X("silgen emitConstructor", f);
        SILGenFunction(*this, *f, decl).emitClassConstructorAllocator(decl);
        postEmitFunction(constant, f);
      } else {
        preEmitFunction(constant, f, decl);
        PrettyStackTraceSILFunction X("silgen emitConstructor", f);
        f->createProfiler(decl, constant, ForDefinition);
        SILGenFunction(*this, *f, decl).emitValueConstructor(decl);
        postEmitFunction(constant, f);
      }
      break;
    }
  
    case SILDeclRef::Kind::Initializer: {
      auto *decl = cast<ConstructorDecl>(constant.getDecl());
      assert(decl->getDeclContext()->getSelfClassDecl());
  
      preEmitFunction(constant, f, decl);
      PrettyStackTraceSILFunction X("silgen constructor initializer", f);
      f->createProfiler(decl, constant, ForDefinition);
      SILGenFunction(*this, *f, decl).emitClassConstructorInitializer(decl);
      postEmitFunction(constant, f);
      break;
    }
  
    case SILDeclRef::Kind::DefaultArgGenerator: {
      auto *decl = constant.getDecl();
      auto *param = getParameterAt(decl, constant.defaultArgIndex);
      auto *initDC = param->getDefaultArgumentInitContext();
  
      switch (param->getDefaultArgumentKind()) {
      case DefaultArgumentKind::Normal: {
        auto arg = param->getTypeCheckedDefaultExpr();
        auto loc = RegularLocation::getAutoGeneratedLocation(arg);
        preEmitFunction(constant, f, loc);
        PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
        SILGenFunction SGF(*this, *f, initDC);
        SGF.emitGeneratorFunction(constant, arg);
        postEmitFunction(constant, f);
        break;
      }
  
      case DefaultArgumentKind::StoredProperty: {
        auto arg = param->getStoredProperty();
        auto loc = RegularLocation::getAutoGeneratedLocation(arg);
        preEmitFunction(constant, f, loc);
        PrettyStackTraceSILFunction X("silgen emitDefaultArgGenerator ", f);
        SILGenFunction SGF(*this, *f, initDC);
        SGF.emitGeneratorFunction(constant, arg);
        postEmitFunction(constant, f);
        break;
      }
  
      default:
        llvm_unreachable("Bad default argument kind");
      }
  
      break;
    }
  
    case SILDeclRef::Kind::StoredPropertyInitializer: {
      auto *var = cast<VarDecl>(constant.getDecl());
  
      auto *pbd = var->getParentPatternBinding();
      unsigned idx = pbd->getPatternEntryIndexForVarDecl(var);
      auto *init = pbd->getInit(idx);
      auto *initDC = pbd->getInitContext(idx);
      auto captureInfo = pbd->getCaptureInfo(idx);
      assert(!pbd->isInitializerSubsumed(idx));
  
      // If this is the backing storage for a property with an attached wrapper
      // that was initialized with `=`, use that expression as the initializer.
      if (auto originalProperty = var->getOriginalWrappedProperty()) {
        if (originalProperty
                ->isPropertyMemberwiseInitializedWithWrappedType()) {
          auto wrapperInfo =
              originalProperty->getPropertyWrapperInitializerInfo();
          assert(wrapperInfo.getWrappedValuePlaceholder()->getOriginalWrappedValue());
          init = wrapperInfo.getWrappedValuePlaceholder()->getOriginalWrappedValue();
        }
      }
  
      auto loc = RegularLocation::getAutoGeneratedLocation(init);
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
      f->createProfiler(init, constant, ForDefinition);
      SILGenFunction SGF(*this, *f, initDC);
  
      // If this is a stored property initializer inside a type at global scope,
      // it may close over a global variable. If we're emitting top-level code,
      // then emit a "mark_function_escape" that lists the captured global
      // variables so that definite initialization can reason about this
      // escape point.
      if (!var->getDeclContext()->isLocalContext() &&  TopLevelSGF &&
          TopLevelSGF->B.hasValidInsertionPoint()) {
        emitMarkFunctionEscapeForTopLevelCodeGlobals(var, captureInfo);
      }
  
      SGF.emitGeneratorFunction(constant, init, /*EmitProfilerIncrement=*/true);
      postEmitFunction(constant, f);
      break;
    }
  
    case SILDeclRef::Kind::PropertyWrapperBackingInitializer: {
      auto *var = cast<VarDecl>(constant.getDecl());
  
      auto loc = RegularLocation::getAutoGeneratedLocation(var);
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X(
          "silgen emitPropertyWrapperBackingInitializer", f);
      auto wrapperInfo = var->getPropertyWrapperInitializerInfo();
      assert(wrapperInfo.hasInitFromWrappedValue());
      f->createProfiler(wrapperInfo.getInitFromWrappedValue(), constant,
                        ForDefinition);
      auto varDC = var->getInnermostDeclContext();
      SILGenFunction SGF(*this, *f, varDC);
      SGF.emitGeneratorFunction(constant, wrapperInfo.getInitFromWrappedValue());
      postEmitFunction(constant, f);
      break;
    }
  
    case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue: {
      auto *var = cast<VarDecl>(constant.getDecl());
  
      auto loc = RegularLocation::getAutoGeneratedLocation(var);
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X(
          "silgen emitPropertyWrapperInitFromProjectedValue", f);
      auto initInfo = var->getPropertyWrapperInitializerInfo();
      assert(initInfo.hasInitFromProjectedValue());
      f->createProfiler(initInfo.getInitFromProjectedValue(), constant,
                        ForDefinition);
      auto varDC = var->getInnermostDeclContext();
      SILGenFunction SGF(*this, *f, varDC);
      SGF.emitGeneratorFunction(constant, initInfo.getInitFromProjectedValue());
      postEmitFunction(constant, f);
      break;
    }
  
    case SILDeclRef::Kind::GlobalAccessor: {
      auto *global = cast<VarDecl>(constant.getDecl());
      auto found = delayedGlobals.find(global);
      assert(found != delayedGlobals.end());
  
      auto *onceToken = found->second.first;
      auto *onceFunc = found->second.second;
  
      auto loc = RegularLocation::getAutoGeneratedLocation(global);
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X("silgen emitGlobalAccessor", f);
      SILGenFunction(*this, *f, global->getDeclContext())
        .emitGlobalAccessor(global, onceToken, onceFunc);
      postEmitFunction(constant, f);
      break;
    }
  
    case SILDeclRef::Kind::EnumElement: {
      auto *decl = cast<EnumElementDecl>(constant.getDecl());
  
      auto loc = RegularLocation::getAutoGeneratedLocation(decl);
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X("silgen enum constructor", f);
      SILGenFunction(*this, *f, decl->getDeclContext()).emitEnumConstructor(decl);
      postEmitFunction(constant, f);
      break;
    }
  
    case SILDeclRef::Kind::Destroyer: {
      auto *dd = cast<DestructorDecl>(constant.getDecl());
      preEmitFunction(constant, f, dd);
      PrettyStackTraceSILFunction X("silgen emitDestroyingDestructor", f);
      SILGenFunction(*this, *f, dd).emitDestroyingDestructor(dd);
      postEmitFunction(constant, f);
      return;
    }
  
    case SILDeclRef::Kind::Deallocator: {
      auto *dd = cast<DestructorDecl>(constant.getDecl());
      auto *cd = cast<ClassDecl>(dd->getDeclContext());
  
      if (usesObjCAllocator(cd)) {
        preEmitFunction(constant, f, dd);
        PrettyStackTraceSILFunction X("silgen emitDestructor -dealloc", f);
        f->createProfiler(dd, constant, ForDefinition);
        SILGenFunction(*this, *f, dd).emitObjCDestructor(constant);
        postEmitFunction(constant, f);
        return;
      }
  
      auto loc = RegularLocation::getAutoGeneratedLocation(dd);
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X("silgen emitDeallocatingDestructor", f);
      f->createProfiler(dd, constant, ForDefinition);
      SILGenFunction(*this, *f, dd).emitDeallocatingDestructor(dd);
      postEmitFunction(constant, f);
      return;
    }
  
    case SILDeclRef::Kind::IVarInitializer: {
      auto *cd = cast<ClassDecl>(constant.getDecl());
      auto loc = RegularLocation::getAutoGeneratedLocation(cd);
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X("silgen emitDestructor ivar initializer", f);
      SILGenFunction(*this, *f, cd).emitIVarInitializer(constant);
      postEmitFunction(constant, f);
      return;
    }
  
    case SILDeclRef::Kind::IVarDestroyer: {
      auto *cd = cast<ClassDecl>(constant.getDecl());
      auto loc = RegularLocation::getAutoGeneratedLocation(cd);
      preEmitFunction(constant, f, loc);
      PrettyStackTraceSILFunction X("silgen emitDestructor ivar destroyer", f);
      SILGenFunction(*this, *f, cd).emitIVarDestroyer(constant);
      postEmitFunction(constant, f);
      return;
    }
    }
  }
  
  /// Emit a function now, if it's externally usable or has been referenced in
  /// the current TU, or remember how to emit it later if not.
  static void emitOrDelayFunction(SILGenModule &SGM,
                                  SILDeclRef constant,
                                  bool forceEmission = false) {
    assert(!constant.isThunk());
    assert(!constant.isClangImported());
  
    auto emitAfter = SGM.lastEmittedFunction;
  
    SILFunction *f = nullptr;
  
    // Implicit decls may be delayed if they can't be used externally.
    auto linkage = constant.getLinkage(ForDefinition);
    bool mayDelay = !forceEmission &&
               (constant.isImplicit() &&
                !isPossiblyUsedExternally(linkage, SGM.M.isWholeModule()));
  
    // Avoid emitting a delayable definition if it hasn't already been referenced.
    if (mayDelay)
      f = SGM.getEmittedFunction(constant, ForDefinition);
    else
      f = SGM.getFunction(constant, ForDefinition);
  
    // If we don't want to emit now, remember how for later.
    if (!f) {
      SGM.delayedFunctions.insert({constant, emitAfter});
      // Even though we didn't emit the function now, update the
      // lastEmittedFunction so that we preserve the original ordering that
      // the symbols would have been emitted in.
      SGM.lastEmittedFunction = constant;
      return;
    }
  
    SGM.emitFunctionDefinition(constant, f);
  }
  
  void SILGenModule::preEmitFunction(SILDeclRef constant, SILFunction *F,
                                     SILLocation Loc) {
    assert(F->empty() && "already emitted function?!");
  
    if (F->getLoweredFunctionType()->isPolymorphic())
      F->setGenericEnvironment(Types.getConstantGenericEnvironment(constant));
  
    // Create a debug scope for the function using astNode as source location.
    F->setDebugScope(new (M) SILDebugScope(Loc, F));
  
    LLVM_DEBUG(llvm::dbgs() << "lowering ";
               F->printName(llvm::dbgs());
               llvm::dbgs() << " : ";
               F->getLoweredType().print(llvm::dbgs());
               llvm::dbgs() << '\n';
               if (auto *decl = Loc.getAsASTNode<ValueDecl>()) {
                 decl->dump(llvm::dbgs());
                 llvm::dbgs() << '\n';
               } else if (auto *expr = Loc.getAsASTNode<Expr>()) {
                 expr->dump(llvm::dbgs());
                 llvm::dbgs() << "\n";
               });
  }
  
  void SILGenModule::postEmitFunction(SILDeclRef constant,
                                      SILFunction *F) {
    emitLazyConformancesForFunction(F);
  
    assert(!F->isExternalDeclaration() && "did not emit any function body?!");
    LLVM_DEBUG(llvm::dbgs() << "lowered sil:\n";
               F->print(llvm::dbgs()));
    F->verify();
  
    emitDifferentiabilityWitnessesForFunction(constant, F);
  }
  
  void SILGenModule::emitDifferentiabilityWitnessesForFunction(
      SILDeclRef constant, SILFunction *F) {
    // Visit `@derivative` attributes and generate SIL differentiability
    // witnesses.
    // Skip if the SILDeclRef is a:
    // - Default argument generator function.
    // - Thunk.
    if (!constant.hasDecl() || !constant.getAbstractFunctionDecl())
      return;
    if (constant.kind == SILDeclRef::Kind::DefaultArgGenerator ||
        constant.isThunk())
      return;
    auto *AFD = constant.getAbstractFunctionDecl();
    auto emitWitnesses = [&](DeclAttributes &Attrs) {
      for (auto *diffAttr : Attrs.getAttributes<DifferentiableAttr>()) {
        auto *resultIndices = IndexSubset::get(getASTContext(), 1, {0});
        assert((!F->getLoweredFunctionType()->getSubstGenericSignature() ||
                diffAttr->getDerivativeGenericSignature()) &&
               "Type-checking should resolve derivative generic signatures for "
               "all original SIL functions with generic signatures");
        auto witnessGenSig =
            autodiff::getDifferentiabilityWitnessGenericSignature(
                AFD->getGenericSignature(),
                diffAttr->getDerivativeGenericSignature());
        AutoDiffConfig config(diffAttr->getParameterIndices(), resultIndices,
                              witnessGenSig);
        emitDifferentiabilityWitness(AFD, F, DifferentiabilityKind::Reverse,
                                     config, /*jvp*/ nullptr,
                                     /*vjp*/ nullptr, diffAttr);
      }
      for (auto *derivAttr : Attrs.getAttributes<DerivativeAttr>()) {
        SILFunction *jvp = nullptr;
        SILFunction *vjp = nullptr;
        switch (derivAttr->getDerivativeKind()) {
        case AutoDiffDerivativeFunctionKind::JVP:
          jvp = F;
          break;
        case AutoDiffDerivativeFunctionKind::VJP:
          vjp = F;
          break;
        }
        auto *origAFD = derivAttr->getOriginalFunction(getASTContext());
        auto origDeclRef =
            SILDeclRef(origAFD).asForeign(requiresForeignEntryPoint(origAFD));
        auto *origFn = getFunction(origDeclRef, NotForDefinition);
        auto witnessGenSig =
            autodiff::getDifferentiabilityWitnessGenericSignature(
                origAFD->getGenericSignature(), AFD->getGenericSignature());
        auto *resultIndices = IndexSubset::get(getASTContext(), 1, {0});
        AutoDiffConfig config(derivAttr->getParameterIndices(), resultIndices,
                              witnessGenSig);
        emitDifferentiabilityWitness(origAFD, origFn,
                                     DifferentiabilityKind::Reverse, config, jvp,
                                     vjp, derivAttr);
      }
    };
    if (auto *accessor = dyn_cast<AccessorDecl>(AFD))
      if (accessor->isGetter())
        emitWitnesses(accessor->getStorage()->getAttrs());
    emitWitnesses(AFD->getAttrs());
  }
  
  void SILGenModule::emitDifferentiabilityWitness(
      AbstractFunctionDecl *originalAFD, SILFunction *originalFunction,
      DifferentiabilityKind diffKind, const AutoDiffConfig &config,
      SILFunction *jvp, SILFunction *vjp, const DeclAttribute *attr) {
    assert(isa<DifferentiableAttr>(attr) || isa<DerivativeAttr>(attr));
    auto *origFnType = originalAFD->getInterfaceType()->castTo<AnyFunctionType>();
    auto origSilFnType = originalFunction->getLoweredFunctionType();
    auto *silParamIndices =
        autodiff::getLoweredParameterIndices(config.parameterIndices, origFnType);
    // NOTE(TF-893): Extending capacity is necessary when `origSilFnType` has
    // parameters corresponding to captured variables. These parameters do not
    // appear in the type of `origFnType`.
    // TODO: If posssible, change `autodiff::getLoweredParameterIndices` to
    // take `CaptureInfo` into account.
    if (origSilFnType->getNumParameters() > silParamIndices->getCapacity())
      silParamIndices = silParamIndices->extendingCapacity(
          getASTContext(), origSilFnType->getNumParameters());
  
    // Get or create new SIL differentiability witness.
    // Witness already exists when there are two `@derivative` attributes
    // (registering JVP and VJP functions) for the same derivative function
    // configuration.
    // Witness JVP and VJP are set below.
    AutoDiffConfig silConfig(silParamIndices, config.resultIndices,
                             config.derivativeGenericSignature);
    SILDifferentiabilityWitnessKey key = {
        originalFunction->getName(), diffKind, silConfig};
    auto *diffWitness = M.lookUpDifferentiabilityWitness(key);
    if (!diffWitness) {
      // Differentiability witnesses have the same linkage as the original
      // function, stripping external.
      auto linkage = stripExternalFromLinkage(originalFunction->getLinkage());
      diffWitness = SILDifferentiabilityWitness::createDefinition(
          M, linkage, originalFunction, diffKind, silConfig.parameterIndices,
          silConfig.resultIndices, config.derivativeGenericSignature,
          /*jvp*/ nullptr, /*vjp*/ nullptr,
          /*isSerialized*/ hasPublicVisibility(originalFunction->getLinkage()),
          attr);
    }
  
    // Set derivative function in differentiability witness.
    auto setDerivativeInDifferentiabilityWitness =
        [&](AutoDiffDerivativeFunctionKind kind, SILFunction *derivative) {
          auto derivativeThunk = getOrCreateCustomDerivativeThunk(
              originalAFD, originalFunction, derivative, silConfig, kind);
          // Check for existing same derivative.
          // TODO(TF-835): Remove condition below and simplify assertion to
          // `!diffWitness->getDerivative(kind)` after `@derivative` attribute
          // type-checking no longer generates implicit `@differentiable`
          // attributes.
          auto *existingDerivative = diffWitness->getDerivative(kind);
          if (existingDerivative && existingDerivative == derivativeThunk)
            return;
          assert(!existingDerivative &&
                 "SIL differentiability witness already has a different existing "
                 "derivative");
          diffWitness->setDerivative(kind, derivativeThunk);
        };
    if (jvp)
      setDerivativeInDifferentiabilityWitness(AutoDiffDerivativeFunctionKind::JVP,
                                              jvp);
    if (vjp)
      setDerivativeInDifferentiabilityWitness(AutoDiffDerivativeFunctionKind::VJP,
                                              vjp);
  }
  
  void SILGenModule::
  emitMarkFunctionEscapeForTopLevelCodeGlobals(SILLocation loc,
                                               CaptureInfo captureInfo) {
    assert(TopLevelSGF && TopLevelSGF->B.hasValidInsertionPoint()
           && "no valid code generator for top-level function?!");
  
    SmallVector<SILValue, 4> Captures;
    
    for (auto capture : captureInfo.getCaptures()) {
      // Decls captured by value don't escape.
      auto It = TopLevelSGF->VarLocs.find(capture.getDecl());
      if (It == TopLevelSGF->VarLocs.end() ||
          !It->getSecond().value->getType().isAddress())
        continue;
      
      Captures.push_back(It->second.value);
    }
    
    if (!Captures.empty())
      TopLevelSGF->B.createMarkFunctionEscape(loc, Captures);
  }
  
  void SILGenModule::emitAbstractFuncDecl(AbstractFunctionDecl *AFD) {
    // Emit any default argument generators.
    emitDefaultArgGenerators(AFD, AFD->getParameters());
  
    // If this is a function at global scope, it may close over a global variable.
    // If we're emitting top-level code, then emit a "mark_function_escape" that
    // lists the captured global variables so that definite initialization can
    // reason about this escape point.
    if (!AFD->getDeclContext()->isLocalContext() &&
        TopLevelSGF && TopLevelSGF->B.hasValidInsertionPoint()) {
      emitMarkFunctionEscapeForTopLevelCodeGlobals(AFD, AFD->getCaptureInfo());
    }
    
    // If the declaration is exported as a C function, emit its native-to-foreign
    // thunk too, if it wasn't already forced.
    if (AFD->getAttrs().hasAttribute<CDeclAttr>()) {
      auto thunk = SILDeclRef(AFD).asForeign();
      if (!hasFunction(thunk))
        emitNativeToForeignThunk(thunk);
    }
  }
  
  void SILGenModule::emitFunction(FuncDecl *fd) {
    SILDeclRef::Loc decl = fd;
  
    emitAbstractFuncDecl(fd);
  
    if (fd->hasBody()) {
      SILDeclRef constant(decl);
      bool ForCoverageMapping = doesASTRequireProfiling(M, fd);
      emitOrDelayFunction(*this, constant,
                          /*forceEmission=*/ForCoverageMapping);
    }
  }
  
  void SILGenModule::addGlobalVariable(VarDecl *global) {
    // We create SILGlobalVariable here.
    getSILGlobalVariable(global, ForDefinition);
  }
  
  void SILGenModule::emitConstructor(ConstructorDecl *decl) {
    // FIXME: Handle 'self' like any other argument here.
    // Emit any default argument getter functions.
    emitAbstractFuncDecl(decl);
  
    // We never emit constructors in protocols.
    if (isa<ProtocolDecl>(decl->getDeclContext()))
      return;
  
    SILDeclRef constant(decl);
    DeclContext *declCtx = decl->getDeclContext();
  
    bool ForCoverageMapping = doesASTRequireProfiling(M, decl);
  
    if (declCtx->getSelfClassDecl()) {
      // Designated initializers for classes, as well as @objc convenience
      // initializers, have have separate entry points for allocation and
      // initialization.
      if (decl->isDesignatedInit() || decl->isObjC()) {
        emitOrDelayFunction(*this, constant);
  
        if (decl->hasBody()) {
          SILDeclRef initConstant(decl, SILDeclRef::Kind::Initializer);
          emitOrDelayFunction(*this, initConstant,
                              /*forceEmission=*/ForCoverageMapping);
        }
  
        return;
      }
    }
  
    // Struct and enum constructors do everything in a single function, as do
    // non-@objc convenience initializers for classes.
    if (decl->hasBody()) {
      emitOrDelayFunction(*this, constant);
    }
  }
  
  SILFunction *SILGenModule::emitClosure(AbstractClosureExpr *ce) {
    SILDeclRef constant(ce);
    SILFunction *f = getFunction(constant, ForDefinition);
  
    // Generate the closure function, if we haven't already.
    //
    // We may visit the same closure expr multiple times in some cases,
    // for instance, when closures appear as in-line initializers of stored
    // properties. In these cases the closure will be emitted into every
    // initializer of the containing type.
    if (!f->isExternalDeclaration())
      return f;
  
    emitFunctionDefinition(constant, f);
    return f;
  }
  
  /// Determine whether the given class requires a separate instance
  /// variable initialization method.
  static bool requiresIVarInitialization(SILGenModule &SGM, ClassDecl *cd) {
    if (!cd->requiresStoredPropertyInits())
      return false;
  
    for (Decl *member : cd->getMembers()) {
      auto pbd = dyn_cast<PatternBindingDecl>(member);
      if (!pbd) continue;
  
      for (auto i : range(pbd->getNumPatternEntries()))
        if (pbd->getExecutableInit(i))
          return true;
    }
  
    return false;
  }
  
  bool SILGenModule::hasNonTrivialIVars(ClassDecl *cd) {
    for (Decl *member : cd->getMembers()) {
      auto *vd = dyn_cast<VarDecl>(member);
      if (!vd || !vd->hasStorage()) continue;
  
      auto &ti = Types.getTypeLowering(
          vd->getType(), TypeExpansionContext::maximalResilienceExpansionOnly());
      if (!ti.isTrivial())
        return true;
    }
  
    return false;
  }
  
  bool SILGenModule::requiresIVarDestroyer(ClassDecl *cd) {
    // Only needed if we have non-trivial ivars, we're not a root class, and
    // the superclass is not @objc.
    return (hasNonTrivialIVars(cd) &&
            cd->getSuperclassDecl() &&
            !cd->getSuperclassDecl()->hasClangNode());
  }
  
  /// TODO: This needs a better name.
  void SILGenModule::emitObjCAllocatorDestructor(ClassDecl *cd,
                                                 DestructorDecl *dd) {
    // Emit the native deallocating destructor for -dealloc.
    // Destructors are a necessary part of class metadata, so can't be delayed.
    if (dd->hasBody()) {
      SILDeclRef dealloc(dd, SILDeclRef::Kind::Deallocator);
      emitFunctionDefinition(dealloc, getFunction(dealloc, ForDefinition));
    }
  
    // Emit the Objective-C -dealloc entry point if it has
    // something to do beyond messaging the superclass's -dealloc.
    if (dd->hasBody() && !dd->getBody()->empty())
      emitObjCDestructorThunk(dd);
  
    // Emit the ivar initializer, if needed.
    if (requiresIVarInitialization(*this, cd)) {
      auto ivarInitializer = SILDeclRef(cd, SILDeclRef::Kind::IVarInitializer)
        .asForeign();
      emitFunctionDefinition(ivarInitializer,
                             getFunction(ivarInitializer, ForDefinition));
    }
  
    // Emit the ivar destroyer, if needed.
    if (hasNonTrivialIVars(cd)) {
      auto ivarDestroyer = SILDeclRef(cd, SILDeclRef::Kind::IVarDestroyer)
        .asForeign();
      emitFunctionDefinition(ivarDestroyer,
                             getFunction(ivarDestroyer, ForDefinition));
    }
  }
  
  void SILGenModule::emitDestructor(ClassDecl *cd, DestructorDecl *dd) {
    emitAbstractFuncDecl(dd);
    
    // Emit the ivar destroyer, if needed.
    if (requiresIVarDestroyer(cd)) {
      SILDeclRef ivarDestroyer(cd, SILDeclRef::Kind::IVarDestroyer);
      emitFunctionDefinition(ivarDestroyer,
                             getFunction(ivarDestroyer, ForDefinition));
    }
  
    // If the class would use the Objective-C allocator, only emit -dealloc.
    if (usesObjCAllocator(cd)) {
      emitObjCAllocatorDestructor(cd, dd);
      return;
    }
  
    // Emit the destroying destructor.
    // Destructors are a necessary part of class metadata, so can't be delayed.
    if (dd->hasBody()) {
      SILDeclRef destroyer(dd, SILDeclRef::Kind::Destroyer);
      emitFunctionDefinition(destroyer, getFunction(destroyer, ForDefinition));
    }
  
    // Emit the deallocating destructor.
    {
      SILDeclRef deallocator(dd, SILDeclRef::Kind::Deallocator);
      emitFunctionDefinition(deallocator,
                             getFunction(deallocator, ForDefinition));
    }
  }
  
  void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant,
                                             ParamDecl *param) {
    switch (param->getDefaultArgumentKind()) {
    case DefaultArgumentKind::None:
      llvm_unreachable("No default argument here?");
  
    case DefaultArgumentKind::Normal:
    case DefaultArgumentKind::StoredProperty:
      emitOrDelayFunction(*this, constant);
      break;
  
    case DefaultArgumentKind::Inherited:
  #define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
    case DefaultArgumentKind::NAME:
  #include "swift/AST/MagicIdentifierKinds.def"
    case DefaultArgumentKind::NilLiteral:
    case DefaultArgumentKind::EmptyArray:
    case DefaultArgumentKind::EmptyDictionary:
      break;
    }
  }
  
  void SILGenModule::
  emitStoredPropertyInitialization(PatternBindingDecl *pbd, unsigned i) {
    auto *var = pbd->getAnchoringVarDecl(i);
    SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
    emitOrDelayFunction(*this, constant);
  }
  
  void SILGenModule::
  emitPropertyWrapperBackingInitializer(VarDecl *var) {
    auto initInfo = var->getPropertyWrapperInitializerInfo();
  
    if (initInfo.hasInitFromWrappedValue()) {
      SILDeclRef constant(var, SILDeclRef::Kind::PropertyWrapperBackingInitializer);
      emitOrDelayFunction(*this, constant);
    }
  
    if (initInfo.hasInitFromProjectedValue()) {
      SILDeclRef constant(var, SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue);
      emitOrDelayFunction(*this, constant);
    }
  }
  
  SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName,
                                                   PatternBindingDecl *binding,
                                                       unsigned pbdEntry) {
    ASTContext &C = M.getASTContext();
    auto *onceBuiltin =
        cast<FuncDecl>(getBuiltinValueDecl(C, C.getIdentifier("once")));
    auto blockParam = onceBuiltin->getParameters()->get(1);
    auto *type = blockParam->getType()->castTo<FunctionType>();
    Type initType = FunctionType::get({}, TupleType::getEmpty(C),
                                      type->getExtInfo());
    auto initSILType = cast<SILFunctionType>(
        Types.getLoweredRValueType(TypeExpansionContext::minimal(), initType));
  
    SILGenFunctionBuilder builder(*this);
    auto *f = builder.createFunction(
        SILLinkage::Private, funcName, initSILType, nullptr, SILLocation(binding),
        IsNotBare, IsNotTransparent, IsNotSerialized, IsNotDynamic);
    f->setSpecialPurpose(SILFunction::Purpose::GlobalInitOnceFunction);
    f->setDebugScope(new (M) SILDebugScope(RegularLocation(binding), f));
    auto dc = binding->getDeclContext();
    SILGenFunction(*this, *f, dc).emitLazyGlobalInitializer(binding, pbdEntry);
    emitLazyConformancesForFunction(f);
    f->verify();
  
    return f;
  }
  
  void SILGenModule::emitGlobalAccessor(VarDecl *global,
                                        SILGlobalVariable *onceToken,
                                        SILFunction *onceFunc) {
    SILDeclRef accessor(global, SILDeclRef::Kind::GlobalAccessor);
    delayedGlobals[global] = std::make_pair(onceToken, onceFunc);
    emitOrDelayFunction(*this, accessor);
  }
  
  void SILGenModule::emitDefaultArgGenerators(SILDeclRef::Loc decl,
                                              ParameterList *paramList) {
    unsigned index = 0;
    for (auto param : *paramList) {
      if (param->isDefaultArgument())
        emitDefaultArgGenerator(SILDeclRef::getDefaultArgGenerator(decl, index),
                                param);
      ++index;
    }
  }
  
  void SILGenModule::emitObjCMethodThunk(FuncDecl *method) {
    auto thunk = SILDeclRef(method).asForeign();
  
    // Don't emit the thunk if it already exists.
    if (hasFunction(thunk))
      return;
  
    // ObjC entry points are always externally usable, so can't be delay-emitted.
    emitNativeToForeignThunk(thunk);
  }
  
  void SILGenModule::emitObjCPropertyMethodThunks(AbstractStorageDecl *prop) {
    auto *getter = prop->getOpaqueAccessor(AccessorKind::Get);
  
    // If we don't actually need an entry point for the getter, do nothing.
    if (!getter || !requiresObjCMethodEntryPoint(getter))
      return;
  
    auto getterRef = SILDeclRef(getter, SILDeclRef::Kind::Func).asForeign();
  
    // Don't emit the thunks if they already exist.
    if (hasFunction(getterRef))
      return;
  
    // ObjC entry points are always externally usable, so emitting can't be
    // delayed.
    emitNativeToForeignThunk(getterRef);
  
    if (!prop->isSettable(prop->getDeclContext()))
      return;
  
    // FIXME: Add proper location.
    auto *setter = prop->getOpaqueAccessor(AccessorKind::Set);
    auto setterRef = SILDeclRef(setter, SILDeclRef::Kind::Func).asForeign();
    emitNativeToForeignThunk(setterRef);
  }
  
  void SILGenModule::emitObjCConstructorThunk(ConstructorDecl *constructor) {
    auto thunk = SILDeclRef(constructor, SILDeclRef::Kind::Initializer)
      .asForeign();
  
    // Don't emit the thunk if it already exists.
    if (hasFunction(thunk))
      return;
    // ObjC entry points are always externally usable, so emitting can't be
    // delayed.
    emitNativeToForeignThunk(thunk);
  }
  
  void SILGenModule::emitObjCDestructorThunk(DestructorDecl *destructor) {
    auto thunk = SILDeclRef(destructor, SILDeclRef::Kind::Deallocator)
      .asForeign();
  
    // Don't emit the thunk if it already exists.
    if (hasFunction(thunk))
      return;
  
    emitNativeToForeignThunk(thunk);
  }
  
  void SILGenModule::visitPatternBindingDecl(PatternBindingDecl *pd) {
    assert(!TopLevelSGF && "script mode PBDs should be in TopLevelCodeDecls");
    for (auto i : range(pd->getNumPatternEntries()))
      if (pd->getExecutableInit(i))
        emitGlobalInitialization(pd, i);
  }
  
  void SILGenModule::visitVarDecl(VarDecl *vd) {
    if (vd->hasStorage())
      addGlobalVariable(vd);
  
    vd->visitEmittedAccessors([&](AccessorDecl *accessor) {
      emitFunction(accessor);
    });
  
    tryEmitPropertyDescriptor(vd);
  }
  
  void SILGenModule::visitSubscriptDecl(SubscriptDecl *sd) {
    llvm_unreachable("top-level subscript?");
  }
  
  bool
  SILGenModule::canStorageUseStoredKeyPathComponent(AbstractStorageDecl *decl,
                                                    ResilienceExpansion expansion) {
    // If the declaration is resilient, we have to treat the component as
    // computed.
    if (decl->isResilient(M.getSwiftModule(), expansion))
      return false;
  
    auto strategy = decl->getAccessStrategy(AccessSemantics::Ordinary,
                                            decl->supportsMutation()
                                              ? AccessKind::ReadWrite
                                              : AccessKind::Read,
                                            M.getSwiftModule(),
                                            expansion);
    switch (strategy.getKind()) {
    case AccessStrategy::Storage: {
      // Keypaths rely on accessors to handle the special behavior of weak or
      // unowned properties.
      if (decl->getInterfaceType()->is<ReferenceStorageType>())
        return false;
  
      // If the field offset depends on the generic instantiation, we have to
      // load it from metadata when instantiating the keypath component.
      //
      // However the metadata offset itself will not be fixed if the superclass
      // is resilient. Fall back to treating the property as computed in this
      // case.
      //
      // See the call to getClassFieldOffsetOffset() inside
      // emitKeyPathComponent().
      if (auto *parentClass = dyn_cast<ClassDecl>(decl->getDeclContext())) {
        if (parentClass->isGeneric()) {
          auto ancestry = parentClass->checkAncestry();
          if (ancestry.contains(AncestryFlags::ResilientOther))
            return false;
        }
      }
  
      // If the stored value would need to be reabstracted in fully opaque
      // context, then we have to treat the component as computed.
      auto componentObjTy = decl->getValueInterfaceType();
      if (auto genericEnv =
                decl->getInnermostDeclContext()->getGenericEnvironmentOfContext())
        componentObjTy = genericEnv->mapTypeIntoContext(componentObjTy);
      auto storageTy = M.Types.getSubstitutedStorageType(
          TypeExpansionContext::minimal(), decl, componentObjTy);
      auto opaqueTy = M.Types.getLoweredRValueType(
          TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(expansion),
          AbstractionPattern::getOpaque(), componentObjTy);
  
      return storageTy.getASTType() == opaqueTy;
    }
    case AccessStrategy::DirectToAccessor:
    case AccessStrategy::DispatchToAccessor:
    case AccessStrategy::MaterializeToTemporary:
      return false;
    }
    llvm_unreachable("unhandled strategy");
  }
  
  static bool canStorageUseTrivialDescriptor(SILGenModule &SGM,
                                             AbstractStorageDecl *decl) {
    // A property can use a trivial property descriptor if the key path component
    // that an external module would form given publicly-exported information
    // about the property is never equivalent to the canonical component for the
    // key path.
    // This means that the property isn't stored (without promising to be always
    // stored) and doesn't have a setter with less-than-public visibility.
    auto expansion = ResilienceExpansion::Maximal;
  
    if (!SGM.M.getSwiftModule()->isResilient()) {
      if (SGM.canStorageUseStoredKeyPathComponent(decl, expansion)) {
        // External modules can't directly access storage, unless this is a
        // property in a fixed-layout type.
        return !decl->isFormallyResilient();
      }
  
      // If the type is computed and doesn't have a setter that's hidden from
      // the public, then external components can form the canonical key path
      // without our help.
      auto *setter = decl->getOpaqueAccessor(AccessorKind::Set);
      if (!setter)
        return true;
  
      if (setter->getFormalAccessScope(nullptr, true).isPublic())
        return true;
  
      return false;
    }
  
    // A resilient module needs to handle binaries compiled against its older
    // versions. This means we have to be a bit more conservative, since in
    // earlier versions, a settable property may have withheld the setter,
    // or a fixed-layout type may not have been.
    // Without availability information, only get-only computed properties
    // can resiliently use trivial descriptors.
    return (!SGM.canStorageUseStoredKeyPathComponent(decl, expansion) &&
            !decl->supportsMutation());
  }
  
  void SILGenModule::tryEmitPropertyDescriptor(AbstractStorageDecl *decl) {
    // TODO: Key path code emission doesn't handle opaque values properly yet.
    if (!SILModuleConventions(M).useLoweredAddresses())
      return;
    
    if (!decl->exportsPropertyDescriptor())
      return;
  
    PrettyStackTraceDecl stackTrace("emitting property descriptor for", decl);
  
    Type baseTy;
    if (decl->getDeclContext()->isTypeContext()) {
      // TODO: Static properties should eventually be referenceable as
      // keypaths from T.Type -> Element, viz `baseTy = MetatypeType::get(baseTy)`
      assert(!decl->isStatic());
      
      baseTy = decl->getDeclContext()->getSelfInterfaceType()
                   ->getCanonicalType(decl->getInnermostDeclContext()
                                          ->getGenericSignatureOfContext());
    } else {
      // TODO: Global variables should eventually be referenceable as
      // key paths from (), viz. baseTy = TupleType::getEmpty(getASTContext());
      llvm_unreachable("should not export a property descriptor yet");
    }
  
    auto genericEnv = decl->getInnermostDeclContext()
                          ->getGenericEnvironmentOfContext();
    unsigned baseOperand = 0;
    bool needsGenericContext = true;
    
    if (canStorageUseTrivialDescriptor(*this, decl)) {
      (void)SILProperty::create(M, /*serialized*/ false, decl, None);
      return;
    }
    
    SubstitutionMap subs;
    if (genericEnv)
      subs = genericEnv->getForwardingSubstitutionMap();
    
    auto component = emitKeyPathComponentForDecl(SILLocation(decl),
                                                 genericEnv,
                                                 ResilienceExpansion::Maximal,
                                                 baseOperand, needsGenericContext,
                                                 subs, decl, {},
                                                 baseTy->getCanonicalType(),
                                                 M.getSwiftModule(),
                                                 /*property descriptor*/ true);
    
    (void)SILProperty::create(M, /*serialized*/ false, decl, component);
  }
  
  void SILGenModule::visitIfConfigDecl(IfConfigDecl *ICD) {
    // Nothing to do for these kinds of decls - anything active has been added
    // to the enclosing declaration.
  }
  
  void SILGenModule::visitPoundDiagnosticDecl(PoundDiagnosticDecl *PDD) {
    // Nothing to do for #error/#warning; they've already been emitted.
  }
  
  void SILGenModule::visitTopLevelCodeDecl(TopLevelCodeDecl *td) {
    assert(TopLevelSGF && "top-level code in a non-main source file!");
  
    if (!TopLevelSGF->B.hasValidInsertionPoint())
      return;
  
    // A single SILFunction may be used to lower multiple top-level decls. When
    // this happens, fresh profile counters must be assigned to the new decl.
    TopLevelSGF->F.discardProfiler();
    TopLevelSGF->F.createProfiler(td, SILDeclRef(), ForDefinition);
  
    TopLevelSGF->emitProfilerIncrement(td->getBody());
   
    DebugScope DS(*TopLevelSGF, CleanupLocation(td));
  
    for (auto &ESD : td->getBody()->getElements()) {
      if (!TopLevelSGF->B.hasValidInsertionPoint()) {
        if (auto *S = ESD.dyn_cast<Stmt*>()) {
          if (S->isImplicit())
            continue;
        } else if (auto *E = ESD.dyn_cast<Expr*>()) {
          if (E->isImplicit())
            continue;
        }
  
        diagnose(ESD.getStartLoc(), diag::unreachable_code);
        // There's no point in trying to emit anything else.
        return;
      }
  
      if (auto *S = ESD.dyn_cast<Stmt*>()) {
        TopLevelSGF->emitStmt(S);
      } else if (auto *E = ESD.dyn_cast<Expr*>()) {
        TopLevelSGF->emitIgnoredExpr(E);
      } else {
        TopLevelSGF->visit(ESD.get<Decl*>());
      }
    }
  }
  
  namespace {
  
  /// An RAII class to scope source file codegen.
  class SourceFileScope {
    SILGenModule &sgm;
    SourceFile *sf;
    Optional<Scope> scope;
  public:
    SourceFileScope(SILGenModule &sgm, SourceFile *sf) : sgm(sgm), sf(sf) {
      // If this is the script-mode file for the module, create a toplevel.
      if (sf->isScriptMode()) {
        assert(!sgm.TopLevelSGF && "already emitted toplevel?!");
        assert(!sgm.M.lookUpFunction(
                   sgm.getASTContext().getEntryPointFunctionName()) &&
               "already emitted toplevel?!");
  
        RegularLocation TopLevelLoc = RegularLocation::getModuleLocation();
        SILFunction *toplevel = sgm.emitTopLevelFunction(TopLevelLoc);
  
        // Assign a debug scope pointing into the void to the top level function.
        toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc, toplevel));
  
        sgm.TopLevelSGF = new SILGenFunction(sgm, *toplevel, sf);
        sgm.TopLevelSGF->MagicFunctionName = sgm.SwiftModule->getName();
        auto moduleCleanupLoc = CleanupLocation::getModuleCleanupLocation();
        sgm.TopLevelSGF->prepareEpilog(false, true, moduleCleanupLoc);
  
        // Create the argc and argv arguments.
        auto prologueLoc = RegularLocation::getModuleLocation();
        prologueLoc.markAsPrologue();
        auto entry = sgm.TopLevelSGF->B.getInsertionBB();
        auto context = sgm.TopLevelSGF->getTypeExpansionContext();
        auto paramTypeIter = sgm.TopLevelSGF->F.getConventions()
                                 .getParameterSILTypes(context)
                                 .begin();
        entry->createFunctionArgument(*paramTypeIter);
        entry->createFunctionArgument(*std::next(paramTypeIter));
  
        scope.emplace(sgm.TopLevelSGF->Cleanups, moduleCleanupLoc);
      }
    }
  
    ~SourceFileScope() {
      if (sgm.TopLevelSGF) {
        scope.reset();
  
        // Unregister the top-level function emitter.
        auto &SGF = *sgm.TopLevelSGF;
        sgm.TopLevelSGF = nullptr;
  
        // Write out the epilog.
        auto moduleLoc = RegularLocation::getModuleLocation();
        moduleLoc.markAutoGenerated();
        auto returnInfo = SGF.emitEpilogBB(moduleLoc);
        auto returnLoc = returnInfo.second;
        returnLoc.markAutoGenerated();
  
        SILType returnType = SGF.F.getConventions().getSingleSILResultType(
            SGF.getTypeExpansionContext());
        auto emitTopLevelReturnValue = [&](unsigned value) -> SILValue {
          // Create an integer literal for the value.
          auto litType = SILType::getBuiltinIntegerType(32, sgm.getASTContext());
          SILValue retValue =
            SGF.B.createIntegerLiteral(moduleLoc, litType, value);
  
          // Wrap that in a struct if necessary.
          if (litType != returnType) {
            retValue = SGF.B.createStruct(moduleLoc, returnType, retValue);
          }
          return retValue;
        };
  
        // Fallthrough should signal a normal exit by returning 0.
        SILValue returnValue;
        if (SGF.B.hasValidInsertionPoint())
          returnValue = emitTopLevelReturnValue(0);
  
        // Handle the implicit rethrow block.
        auto rethrowBB = SGF.ThrowDest.getBlock();
        SGF.ThrowDest = JumpDest::invalid();
  
        // If the rethrow block wasn't actually used, just remove it.
        if (rethrowBB->pred_empty()) {
          SGF.eraseBasicBlock(rethrowBB);
  
        // Otherwise, we need to produce a unified return block.
        } else {
          auto returnBB = SGF.createBasicBlock();
          if (SGF.B.hasValidInsertionPoint())
            SGF.B.createBranch(returnLoc, returnBB, returnValue);
          returnValue =
              returnBB->createPhiArgument(returnType, OwnershipKind::Owned);
          SGF.B.emitBlock(returnBB);
  
          // Emit the rethrow block.
          SILGenSavedInsertionPoint savedIP(SGF, rethrowBB,
                                            FunctionSection::Postmatter);
  
          // Log the error.
          SILValue error = rethrowBB->getArgument(0);
          SGF.B.createBuiltin(moduleLoc,
                              sgm.getASTContext().getIdentifier("errorInMain"),
                              sgm.Types.getEmptyTupleType(), {}, {error});
  
          // Then end the lifetime of the error.
          //
          // We do this to appease the ownership verifier. We do not care about
          // actually destroying the value since we are going to immediately exit,
          // so this saves us a slight bit of code-size since end_lifetime is
          // stripped out after ownership is removed.
          SGF.B.createEndLifetime(moduleLoc, error);
  
          // Signal an abnormal exit by returning 1.
          SGF.Cleanups.emitCleanupsForReturn(CleanupLocation(moduleLoc),
                                             IsForUnwind);
          SGF.B.createBranch(returnLoc, returnBB, emitTopLevelReturnValue(1));
        }
  
        // Return.
        if (SGF.B.hasValidInsertionPoint())
          SGF.B.createReturn(returnLoc, returnValue);
  
        // Okay, we're done emitting the top-level function; destroy the
        // emitter and verify the result.
        SILFunction *toplevel = &SGF.getFunction();
        delete &SGF;
  
        LLVM_DEBUG(llvm::dbgs() << "lowered toplevel sil:\n";
                   toplevel->print(llvm::dbgs()));
        toplevel->verify();
        sgm.emitLazyConformancesForFunction(toplevel);
      }
  
      // If the source file contains an artificial main, emit the implicit
      // toplevel code.
      if (auto mainDecl = sf->getMainDecl()) {
        assert(!sgm.M.lookUpFunction(
                   sgm.getASTContext().getEntryPointFunctionName()) &&
               "already emitted toplevel before main class?!");
  
        RegularLocation TopLevelLoc = RegularLocation::getModuleLocation();
        SILFunction *toplevel = sgm.emitTopLevelFunction(TopLevelLoc);
  
        // Assign a debug scope pointing into the void to the top level function.
        toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc, toplevel));
  
        // Create the argc and argv arguments.
        SILGenFunction SGF(sgm, *toplevel, sf);
        auto entry = SGF.B.getInsertionBB();
        auto paramTypeIter =
            SGF.F.getConventions()
                .getParameterSILTypes(SGF.getTypeExpansionContext())
                .begin();
        entry->createFunctionArgument(*paramTypeIter);
        entry->createFunctionArgument(*std::next(paramTypeIter));
        SGF.emitArtificialTopLevel(mainDecl);
      }
    }
  };
  
  // An RAII object that constructs a \c SILGenModule instance.
  // On destruction, delayed definitions are automatically emitted.
  class SILGenModuleRAII {
    SILGenModule SGM;
  
  public:
    void emitSourceFile(SourceFile *sf) {
      // Type-check the file if we haven't already.
      performTypeChecking(*sf);
  
      SourceFileScope scope(SGM, sf);
      for (Decl *D : sf->getTopLevelDecls()) {
        FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
                                        "SILgen-decl", D);
        SGM.visit(D);
      }
  
      for (Decl *D : sf->getHoistedDecls()) {
        FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
                                        "SILgen-decl", D);
        SGM.visit(D);
      }
  
      for (TypeDecl *TD : sf->LocalTypeDecls) {
        FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
                                        "SILgen-tydecl", TD);
        // FIXME: Delayed parsing would prevent these types from being added to
        //        the module in the first place.
        if (TD->getDeclContext()->getInnermostSkippedFunctionContext())
          continue;
        SGM.visit(TD);
      }
    }
    void emitSILFunctionDefinition(SILDeclRef ref) {
      SGM.emitFunctionDefinition(ref, SGM.getFunction(ref, ForDefinition));
    }
  
    explicit SILGenModuleRAII(SILModule &M) : SGM{M, M.getSwiftModule()} {}
  
    ~SILGenModuleRAII() {
      // Emit any delayed definitions that were forced.
      // Emitting these may in turn force more definitions, so we have to take
      // care to keep pumping the queues.
      while (!SGM.forcedFunctions.empty()
             || !SGM.pendingConformances.empty()) {
        while (!SGM.forcedFunctions.empty()) {
          auto &front = SGM.forcedFunctions.front();
          SGM.emitFunctionDefinition(
              front, SGM.getEmittedFunction(front, ForDefinition));
          SGM.forcedFunctions.pop_front();
        }
        while (!SGM.pendingConformances.empty()) {
          SGM.getWitnessTable(SGM.pendingConformances.front());
          SGM.pendingConformances.pop_front();
        }
      }
    }
  };
  } // end anonymous namespace
  
  std::unique_ptr<SILModule>
  ASTLoweringRequest::evaluate(Evaluator &evaluator,
                               ASTLoweringDescriptor desc) const {
    // If we have a .sil file to parse, defer to the parsing request.
    if (desc.getSourceFileToParse()) {
      return llvm::cantFail(evaluator(ParseSILModuleRequest{desc}));
    }
  
    auto silMod = SILModule::createEmptyModule(desc.context, desc.conv,
                                               desc.opts);
  
    // If all function bodies are being skipped there's no reason to do any
    // SIL generation.
    if (desc.opts.SkipFunctionBodies == FunctionBodySkipping::All)
      return silMod;
  
    // Skip emitting SIL if there's been any compilation errors
    if (silMod->getASTContext().hadError() &&
        silMod->getASTContext().LangOpts.AllowModuleWithCompilerErrors)
      return silMod;
  
    SILGenModuleRAII scope(*silMod);
  
    // Emit a specific set of SILDeclRefs if needed.
    if (auto refs = desc.refsToEmit) {
      for (auto ref : *refs)
        scope.emitSILFunctionDefinition(ref);
    }
  
    // Emit any whole-files needed.
    for (auto file : desc.getFilesToEmit()) {
      if (auto *nextSF = dyn_cast<SourceFile>(file))
        scope.emitSourceFile(nextSF);
    }
  
    // Also make sure to process any intermediate files that may contain SIL.
    bool shouldDeserialize =
        llvm::any_of(desc.getFilesToEmit(), [](const FileUnit *File) -> bool {
          return isa<SerializedASTFile>(File);
        });
    if (shouldDeserialize) {
      auto *primary = desc.context.dyn_cast<FileUnit *>();
      silMod->getSILLoader()->getAllForModule(silMod->getSwiftModule()->getName(),
                                              primary);
    }
  
    return silMod;
  }
  
  std::unique_ptr<SILModule>
  swift::performASTLowering(ModuleDecl *mod, Lowering::TypeConverter &tc,
                            const SILOptions &options) {
    auto desc = ASTLoweringDescriptor::forWholeModule(mod, tc, options);
    return llvm::cantFail(
        mod->getASTContext().evaluator(ASTLoweringRequest{desc}));
  }
  
  std::unique_ptr<SILModule>
  swift::performASTLowering(FileUnit &sf, Lowering::TypeConverter &tc,
                            const SILOptions &options) {
    auto desc = ASTLoweringDescriptor::forFile(sf, tc, options);
    return llvm::cantFail(sf.getASTContext().evaluator(ASTLoweringRequest{desc}));
  }
  
  static void transferSpecializeAttributeTargets(SILGenModule &SGM, SILModule &M,
                                                 Decl *d) {
    auto *vd = cast<AbstractFunctionDecl>(d);
    for (auto *A : vd->getAttrs().getAttributes<SpecializeAttr>()) {
      auto *SA = cast<SpecializeAttr>(A);
      // Filter _spi.
      auto spiGroups = SA->getSPIGroups();
      auto hasSPIGroup = !spiGroups.empty();
      if (hasSPIGroup) {
        if (vd->getModuleContext() != M.getSwiftModule() &&
            !M.getSwiftModule()->isImportedAsSPI(SA, vd)) {
          continue;
        }
      }
      if (auto *targetFunctionDecl = SA->getTargetFunctionDecl(vd)) {
        auto target = SILDeclRef(targetFunctionDecl);
        auto targetSILFunction = SGM.getFunction(target, NotForDefinition);
        auto kind = SA->getSpecializationKind() ==
                            SpecializeAttr::SpecializationKind::Full
                        ? SILSpecializeAttr::SpecializationKind::Full
                        : SILSpecializeAttr::SpecializationKind::Partial;
        Identifier spiGroupIdent;
        if (hasSPIGroup) {
          spiGroupIdent = spiGroups[0];
        }
        targetSILFunction->addSpecializeAttr(SILSpecializeAttr::create(
            M, SA->getSpecializedSignature(), SA->isExported(), kind, nullptr,
            spiGroupIdent, vd->getModuleContext()));
      }
    }
  }
  
  void SILGenModule::visitImportDecl(ImportDecl *import) {
    auto *module = import->getModule();
    if (module->isNonSwiftModule())
      return;
  
    SmallVector<Decl*, 16> prespecializations;
    module->getExportedPrespecializations(prespecializations);
    for (auto *p : prespecializations) {
      if (auto *vd = dyn_cast<AbstractFunctionDecl>(p)) {
        transferSpecializeAttributeTargets(*this, M, vd);
      }
    }
  }
  