//===--- 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);

  SILGenFunctionBuilder builder(*this);
  return builder.createFunction(
      SILLinkage::Public, SWIFT_ENTRY_POINT_FUNCTION, 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->getPropertyWrapperBackingPropertyInfo();
        assert(wrapperInfo.wrappedValuePlaceholder->getOriginalWrappedValue());
        init = wrapperInfo.wrappedValuePlaceholder->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->getPropertyWrapperBackingPropertyInfo();
    assert(wrapperInfo.initializeFromOriginal);
    f->createProfiler(wrapperInfo.initializeFromOriginal, constant,
                      ForDefinition);
    auto varDC = var->getInnermostDeclContext();
    SILGenFunction SGF(*this, *f, varDC);
    SGF.emitGeneratorFunction(constant, wrapperInfo.initializeFromOriginal);
    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, 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, 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,
    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(), 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, 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(
            derivative, originalFunction, 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) {
  SILDeclRef constant(var, SILDeclRef::Kind::PropertyWrapperBackingInitializer);
  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(SWIFT_ENTRY_POINT_FUNCTION)
             && "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::get(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(SWIFT_ENTRY_POINT_FUNCTION)
             && "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) {
  // Importing `@_specializet(targetFunction: otherFunc)` only supported in
  // experimental pre-specialization mode.
  if (!getASTContext().LangOpts.EnableExperimentalPrespecialization)
    return;

  // TODO: this horrible full AST deserializing walk should be replaced by a
  // 'single place' to lookup those declarations in the module
  // E.g
  // prespecializations {
  //    extension Array {
  //       @_specialize(exported: true, targetFunction: other(_:), T == Int)
  //       func prespecialzie_other() {}
  //    }
  // }
  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);
    }
  }
}
