//===------- ExistentialTransform.cpp - Transform Existential Args -------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Transform existential parameters to generic ones.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-existential-transform"
#include "ExistentialTransform.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/SIL/OptimizationRemark.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/TypeSubstCloner.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
#include "swift/SILOptimizer/Utils/Existential.h"
#include "swift/SILOptimizer/Utils/Generics.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "llvm/ADT/SmallVector.h"

using namespace swift;

using llvm::SmallDenseMap;
using llvm::SmallPtrSet;
using llvm::SmallVector;
using llvm::SmallVectorImpl;

/// Create a SILCloner for Existential Specilizer.
namespace {
class ExistentialSpecializerCloner
    : public TypeSubstCloner<ExistentialSpecializerCloner,
                             SILOptFunctionBuilder> {
  using SuperTy =
      TypeSubstCloner<ExistentialSpecializerCloner, SILOptFunctionBuilder>;
  friend class SILInstructionVisitor<ExistentialSpecializerCloner>;
  friend class SILCloner<ExistentialSpecializerCloner>;

  SILFunction *OrigF;
  SmallVector<ArgumentDescriptor, 4> &ArgumentDescList;
  SmallDenseMap<int, GenericTypeParamType *> &ArgToGenericTypeMap;
  SmallDenseMap<int, ExistentialTransformArgumentDescriptor>
      &ExistentialArgDescriptor;

  // Use one OpenedArchetypesTracker while cloning.
  SILOpenedArchetypesTracker OpenedArchetypesTracker;

  // AllocStack instructions introduced in the new prolog that require cleanup.
  SmallVector<AllocStackInst *, 4> AllocStackInsts;
  // Temporary values introduced in the new prolog that require cleanup.
  SmallVector<SILValue, 4> CleanupValues;

protected:
  void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
    SILClonerWithScopes<ExistentialSpecializerCloner>::postProcess(Orig,
                                                                   Cloned);
  }

  void cloneArguments(SmallVectorImpl<SILValue> &entryArgs);

public:
  ExistentialSpecializerCloner(
      SILFunction *OrigF, SILFunction *NewF, SubstitutionMap Subs,
      SmallVector<ArgumentDescriptor, 4> &ArgumentDescList,
      SmallDenseMap<int, GenericTypeParamType *> &ArgToGenericTypeMap,
      SmallDenseMap<int, ExistentialTransformArgumentDescriptor>
          &ExistentialArgDescriptor)
      : SuperTy(*NewF, *OrigF, Subs), OrigF(OrigF),
        ArgumentDescList(ArgumentDescList),
        ArgToGenericTypeMap(ArgToGenericTypeMap),
        ExistentialArgDescriptor(ExistentialArgDescriptor),
        OpenedArchetypesTracker(NewF) {
    getBuilder().setOpenedArchetypesTracker(&OpenedArchetypesTracker);
  }

  void cloneAndPopulateFunction();
};
} // end anonymous namespace

/// This function will create the generic version.
void ExistentialSpecializerCloner::cloneAndPopulateFunction() {
  SmallVector<SILValue, 4> entryArgs;
  entryArgs.reserve(OrigF->getArguments().size());
  cloneArguments(entryArgs);

  // Visit original BBs in depth-first preorder, starting with the
  // entry block, cloning all instructions and terminators.
  auto *NewEntryBB = getBuilder().getFunction().getEntryBlock();
  cloneFunctionBody(&Original, NewEntryBB, entryArgs);

  // Cleanup allocations created in the new prolog.
  SmallVector<SILBasicBlock *, 4> exitingBlocks;
  getBuilder().getFunction().findExitingBlocks(exitingBlocks);
  for (auto *exitBB : exitingBlocks) {
    SILBuilderWithScope Builder(exitBB->getTerminator());
    // A return location can't be used for a non-return instruction.
    auto loc = RegularLocation::getAutoGeneratedLocation();
    for (SILValue cleanupVal : CleanupValues)
      Builder.createDestroyAddr(loc, cleanupVal);

    for (auto *ASI : reversed(AllocStackInsts))
      Builder.createDeallocStack(loc, ASI);
  }
}

// Create the entry basic block with the function arguments.
void ExistentialSpecializerCloner::cloneArguments(
    SmallVectorImpl<SILValue> &entryArgs) {
  auto &M = OrigF->getModule();
  auto &Ctx = M.getASTContext();

  // Create the new entry block.
  SILFunction &NewF = getBuilder().getFunction();
  SILBasicBlock *ClonedEntryBB = NewF.createBasicBlock();

  /// Builder will have a ScopeClone with a debugscope that is inherited from
  /// the F.
  ScopeCloner SC(NewF);
  auto DebugScope = SC.getOrCreateClonedScope(OrigF->getDebugScope());

  // Setup a NewFBuilder for the new entry block, reusing the cloner's
  // SILBuilderContext.
  SILBuilder NewFBuilder(ClonedEntryBB, DebugScope,
                         getBuilder().getBuilderContext());
  auto InsertLoc = RegularLocation::getAutoGeneratedLocation();

  auto NewFTy = NewF.getLoweredFunctionType();
  SmallVector<SILParameterInfo, 4> params;
  params.append(NewFTy->getParameters().begin(), NewFTy->getParameters().end());

  for (auto &ArgDesc : ArgumentDescList) {
    auto iter = ArgToGenericTypeMap.find(ArgDesc.Index);
    if (iter == ArgToGenericTypeMap.end()) {
      // Clone arguments that are not rewritten.
      auto Ty = params[ArgDesc.Index].getType();
      auto LoweredTy = NewF.getLoweredType(NewF.mapTypeIntoContext(Ty));
      auto MappedTy =
          LoweredTy.getCategoryType(ArgDesc.Arg->getType().getCategory());
      auto *NewArg =
          ClonedEntryBB->createFunctionArgument(MappedTy, ArgDesc.Decl);
      NewArg->setOwnershipKind(ValueOwnershipKind(
          NewF, MappedTy, ArgDesc.Arg->getArgumentConvention()));
      entryArgs.push_back(NewArg);
      continue;
    }
    // Create the generic argument.
    GenericTypeParamType *GenericParam = iter->second;
    SILType GenericSILType =
        NewF.getLoweredType(NewF.mapTypeIntoContext(GenericParam));
    GenericSILType = GenericSILType.getCategoryType(
                                          ArgDesc.Arg->getType().getCategory());
    auto *NewArg = ClonedEntryBB->createFunctionArgument(GenericSILType);
    NewArg->setOwnershipKind(ValueOwnershipKind(
        NewF, GenericSILType, ArgDesc.Arg->getArgumentConvention()));
    // Determine the Conformances.
    SmallVector<ProtocolConformanceRef, 1> NewConformances;
    auto ContextTy = NewF.mapTypeIntoContext(GenericParam);
    auto OpenedArchetype = ContextTy->castTo<ArchetypeType>();
    for (auto proto : OpenedArchetype->getConformsTo()) {
      NewConformances.push_back(ProtocolConformanceRef(proto));
    }
    ArrayRef<ProtocolConformanceRef> Conformances =
        Ctx.AllocateCopy(NewConformances);
    auto ExistentialRepr =
        ArgDesc.Arg->getType().getPreferredExistentialRepresentation();
    auto &EAD = ExistentialArgDescriptor[ArgDesc.Index];
    switch (ExistentialRepr) {
    case ExistentialRepresentation::Opaque: {
      /// Create this sequence for init_existential_addr.:
      /// bb0(%0 : $*T):
      /// %3 = alloc_stack $P
      /// %4 = init_existential_addr %3 : $*P, $T
      /// copy_addr [take] %0 to [initialization] %4 : $*T
      /// %7 = open_existential_addr immutable_access %3 : $*P to
      /// $*@opened P
      auto *ASI =
          NewFBuilder.createAllocStack(InsertLoc, ArgDesc.Arg->getType());
      AllocStackInsts.push_back(ASI);

      auto *EAI = NewFBuilder.createInitExistentialAddr(
          InsertLoc, ASI, NewArg->getType().getASTType(), NewArg->getType(),
          Conformances);

      bool origConsumed = EAD.isConsumed;
      // If the existential is not consumed in the function body, then the one
      // we introduce here needs cleanup.
      if (!origConsumed)
        CleanupValues.push_back(ASI);

      NewFBuilder.createCopyAddr(InsertLoc, NewArg, EAI,
                                 origConsumed ? IsTake_t::IsTake
                                              : IsTake_t::IsNotTake,
                                 IsInitialization_t::IsInitialization);
      entryArgs.push_back(ASI);
      break;
    }
    case ExistentialRepresentation::Class: {
      SILValue NewArgValue = NewArg;
      if (!NewArg->getType().isObject()) {
        NewArgValue = NewFBuilder.createLoad(InsertLoc, NewArg,
                                         LoadOwnershipQualifier::Unqualified);
      }
      
      // FIXME_ownership: init_existential_ref always takes ownership of the
      // incoming reference. If the argument convention is borrowed
      // (!isConsumed), then we should create a copy_value here and add this new
      // existential to the CleanupValues vector.

      ///  Simple case: Create an init_existential.
      /// %5 = init_existential_ref %0 : $T : $T, $P
      SILValue InitRef = NewFBuilder.createInitExistentialRef(
          InsertLoc, ArgDesc.Arg->getType().getObjectType(),
          NewArg->getType().getASTType(),
          NewArgValue, Conformances);
      
      if (!NewArg->getType().isObject()) {
        auto alloc = NewFBuilder.createAllocStack(InsertLoc,
                                                  InitRef->getType());
        NewFBuilder.createStore(InsertLoc, InitRef, alloc,
                                StoreOwnershipQualifier::Unqualified);
        InitRef = alloc;
        AllocStackInsts.push_back(alloc);
      }

      entryArgs.push_back(InitRef);
      break;
    }
    default: {
      llvm_unreachable("Unhandled existential type in ExistentialTransform!");
      break;
    }
    };
  }
}

/// Create a new function name for the newly generated protocol constrained
/// generic function.
std::string ExistentialTransform::createExistentialSpecializedFunctionName() {
  for (auto const &IdxIt : ExistentialArgDescriptor) {
    int Idx = IdxIt.first;
    Mangler.setArgumentExistentialToGeneric(Idx);
  }
  auto MangledName = Mangler.mangle();
  assert(!F->getModule().hasFunction(MangledName));
  return MangledName;
}

/// Convert all existential argument types to generic argument type.
void ExistentialTransform::convertExistentialArgTypesToGenericArgTypes(
    SmallVectorImpl<GenericTypeParamType *> &genericParams,
    SmallVectorImpl<Requirement> &requirements) {

  SILModule &M = F->getModule();
  auto &Ctx = M.getASTContext();
  auto FTy = F->getLoweredFunctionType();

  /// If the original function is generic, then maintain the same.
  auto OrigGenericSig = FTy->getGenericSignature();

  /// Original list of parameters
  SmallVector<SILParameterInfo, 4> params;
  params.append(FTy->getParameters().begin(), FTy->getParameters().end());

  /// Determine the existing generic parameter depth.
  int Depth = 0;
  if (OrigGenericSig != nullptr) {
    Depth = OrigGenericSig->getGenericParams().back()->getDepth() + 1;
  }

  /// Index of the Generic Parameter.
  int GPIdx = 0;

  /// Convert the protocol arguments of F to generic ones.
  for (auto const &IdxIt : ExistentialArgDescriptor) {
    int Idx = IdxIt.first;
    auto &param = params[Idx];
    auto PType = param.getType();
    assert(PType.isExistentialType());
    /// Generate new generic parameter.
    auto *NewGenericParam = GenericTypeParamType::get(Depth, GPIdx++, Ctx);
    genericParams.push_back(NewGenericParam);
    Requirement NewRequirement(RequirementKind::Conformance, NewGenericParam,
                               PType);
    requirements.push_back(NewRequirement);
    ArgToGenericTypeMap.insert(
        std::pair<int, GenericTypeParamType *>(Idx, NewGenericParam));
    assert(ArgToGenericTypeMap.find(Idx) != ArgToGenericTypeMap.end());
  }
}

/// Create the signature for the newly generated protocol constrained generic
/// function.
CanSILFunctionType
ExistentialTransform::createExistentialSpecializedFunctionType() {
  auto FTy = F->getLoweredFunctionType();
  SILModule &M = F->getModule();
  auto &Ctx = M.getASTContext();
  GenericSignature NewGenericSig;
  GenericEnvironment *NewGenericEnv;

  /// If the original function is generic, then maintain the same.
  auto OrigGenericSig = FTy->getGenericSignature();

  SmallVector<GenericTypeParamType *, 2> GenericParams;
  SmallVector<Requirement, 2> Requirements;

  /// Convert existential argument types to generic argument types.
  convertExistentialArgTypesToGenericArgTypes(GenericParams, Requirements);

  /// Compute the updated generic signature.
  NewGenericSig = evaluateOrDefault(
      Ctx.evaluator,
      AbstractGenericSignatureRequest{
        OrigGenericSig.getPointer(), std::move(GenericParams),
        std::move(Requirements)},
      GenericSignature());

  NewGenericEnv = NewGenericSig->getGenericEnvironment();

  /// Create a lambda for GenericParams.
  auto getCanonicalType = [&](Type t) -> CanType {
    return t->getCanonicalType(NewGenericSig);
  };

  /// Original list of parameters
  SmallVector<SILParameterInfo, 4> params;
  params.append(FTy->getParameters().begin(), FTy->getParameters().end());

  /// Create the complete list of parameters.
  int Idx = 0;
  SmallVector<SILParameterInfo, 8> InterfaceParams;
  InterfaceParams.reserve(params.size());
  for (auto &param : params) {
    auto iter = ArgToGenericTypeMap.find(Idx);
    if (iter != ArgToGenericTypeMap.end()) {
      auto GenericParam = iter->second;
      InterfaceParams.push_back(SILParameterInfo(getCanonicalType(GenericParam),
                                                 param.getConvention()));
    } else {
      InterfaceParams.push_back(param);
    }
    Idx++;
  }

  // Add error results.
  Optional<SILResultInfo> InterfaceErrorResult;
  if (FTy->hasErrorResult()) {
    InterfaceErrorResult = FTy->getErrorResult();
  }

  /// Finally the ExtInfo.
  auto ExtInfo = FTy->getExtInfo();
  ExtInfo = ExtInfo.withRepresentation(SILFunctionTypeRepresentation::Thin);
  auto witnessMethodConformance = FTy->getWitnessMethodConformanceOrNone();

  /// Return the new signature.
  return SILFunctionType::get(
      NewGenericSig, ExtInfo, FTy->getCoroutineKind(),
      FTy->getCalleeConvention(), InterfaceParams, FTy->getYields(),
      FTy->getResults(), InterfaceErrorResult, Ctx, witnessMethodConformance);
}

/// Create the Thunk Body with always_inline attribute.
void ExistentialTransform::populateThunkBody() {

  SILModule &M = F->getModule();

  F->setThunk(IsSignatureOptimizedThunk);
  F->setInlineStrategy(AlwaysInline);

  /// Remove original body of F.
  for (auto It = F->begin(), End = F->end(); It != End;) {
    auto *BB = &*It++;
    removeDeadBlock(BB);
  }

  /// Create a basic block and the function arguments.
  auto *ThunkBody = F->createBasicBlock();
  for (auto &ArgDesc : ArgumentDescList) {
    auto argumentType = ArgDesc.Arg->getType();
    ThunkBody->createFunctionArgument(argumentType, ArgDesc.Decl);
  }

  /// Builder to add new instructions in the Thunk.
  SILBuilder Builder(ThunkBody);
  SILOpenedArchetypesTracker OpenedArchetypesTracker(F);
  Builder.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
  Builder.setCurrentDebugScope(ThunkBody->getParent()->getDebugScope());

  /// Location to insert new instructions.
  auto Loc = ThunkBody->getParent()->getLocation();

  /// Create the function_ref instruction to the NewF.
  auto *FRI = Builder.createFunctionRefFor(Loc, NewF);

  auto GenCalleeType = NewF->getLoweredFunctionType();
  auto CalleeGenericSig = GenCalleeType->getGenericSignature();
  auto OrigGenCalleeType = F->getLoweredFunctionType();
  auto OrigCalleeGenericSig = OrigGenCalleeType->getGenericSignature();

  /// Determine arguments to Apply.
  /// Generate opened existentials for generics.
  SmallVector<SILValue, 8> ApplyArgs;
  // Maintain a list of arg values to be destroyed. These are consumed by the
  // convention and require a copy.
  struct Temp {
    SILValue DeallocStackEntry;
    SILValue DestroyValue;
  };
  SmallVector<Temp, 8> Temps;
  SmallDenseMap<GenericTypeParamType *, Type> GenericToOpenedTypeMap;
  for (auto &ArgDesc : ArgumentDescList) {
    auto iter = ArgToGenericTypeMap.find(ArgDesc.Index);
    auto it = ExistentialArgDescriptor.find(ArgDesc.Index);
    if (iter != ArgToGenericTypeMap.end() &&
        it != ExistentialArgDescriptor.end()) {
      ExistentialTransformArgumentDescriptor &ETAD = it->second;
      OpenedArchetypeType *Opened;
      auto OrigOperand = ThunkBody->getArgument(ArgDesc.Index);
      auto SwiftType = ArgDesc.Arg->getType().getASTType();
      auto OpenedType =
          SwiftType->openAnyExistentialType(Opened)->getCanonicalType();
      auto OpenedSILType = NewF->getLoweredType(OpenedType);
      SILValue archetypeValue;
      auto ExistentialRepr =
          ArgDesc.Arg->getType().getPreferredExistentialRepresentation();
      switch (ExistentialRepr) {
      case ExistentialRepresentation::Opaque: {
        archetypeValue = Builder.createOpenExistentialAddr(
            Loc, OrigOperand, OpenedSILType, it->second.AccessType);
        SILValue calleeArg = archetypeValue;
        if (ETAD.isConsumed) {
          // open_existential_addr projects a borrowed address into the
          // existential box. Since the callee consumes the generic value, we
          // must pass in a copy.
          auto *ASI =
            Builder.createAllocStack(Loc, OpenedSILType);
          Builder.createCopyAddr(Loc, archetypeValue, ASI, IsNotTake,
                                 IsInitialization_t::IsInitialization);
          Temps.push_back({ASI, OrigOperand});
          calleeArg = ASI;
        }
        ApplyArgs.push_back(calleeArg);
        break;
      }
      case ExistentialRepresentation::Class: {
        // If the operand is not object type, we need an explicit load.
        SILValue OrigValue = OrigOperand;
        if (!OrigOperand->getType().isObject()) {
          OrigValue = Builder.createLoad(Loc, OrigValue,
                                         LoadOwnershipQualifier::Unqualified);
        }
        // OpenExistentialRef forwards ownership, so it does the right thing
        // regardless of whether the argument is borrowed or consumed.
        archetypeValue =
            Builder.createOpenExistentialRef(Loc, OrigValue, OpenedSILType);
        if (!OrigOperand->getType().isObject()) {
          SILValue ASI = Builder.createAllocStack(Loc, OpenedSILType);
          Builder.createStore(Loc, archetypeValue, ASI,
                              StoreOwnershipQualifier::Unqualified);
          Temps.push_back({ASI, SILValue()});
          archetypeValue = ASI;
        }
        ApplyArgs.push_back(archetypeValue);
        break;
      }
      default: {
        llvm_unreachable("Unhandled existential type in ExistentialTransform!");
        break;
      }
      };
      GenericToOpenedTypeMap.insert(
          std::pair<GenericTypeParamType *, Type>(iter->second, OpenedType));
      assert(GenericToOpenedTypeMap.find(iter->second) !=
             GenericToOpenedTypeMap.end());
    } else {
      ApplyArgs.push_back(ThunkBody->getArgument(ArgDesc.Index));
    }
  }

  unsigned int OrigDepth = 0;
  if (F->getLoweredFunctionType()->isPolymorphic()) {
    OrigDepth = OrigCalleeGenericSig->getGenericParams().back()->getDepth() + 1;
  }
  SubstitutionMap OrigSubMap = F->getForwardingSubstitutionMap();

  /// Create substitutions for Apply instructions.
  auto SubMap = SubstitutionMap::get(
      CalleeGenericSig,
      [&](SubstitutableType *type) -> Type {
        if (auto *GP = dyn_cast<GenericTypeParamType>(type)) {
          if (GP->getDepth() < OrigDepth) {
            return Type(GP).subst(OrigSubMap);
          } else {
            auto iter = GenericToOpenedTypeMap.find(GP);
            assert(iter != GenericToOpenedTypeMap.end());
            return iter->second;
          }
        } else {
          return type;
        }
      },
      MakeAbstractConformanceForGenericType());

  /// Perform the substitutions.
  auto SubstCalleeType = GenCalleeType->substGenericArgs(M, SubMap);

  /// Obtain the Result Type.
  SILValue ReturnValue;
  auto FunctionTy = NewF->getLoweredFunctionType();
  SILFunctionConventions Conv(SubstCalleeType, M);
  SILType ResultType = Conv.getSILResultType();

  /// If the original function has error results,  we need to generate a
  /// try_apply to call a function with an error result.
  if (FunctionTy->hasErrorResult()) {
    SILFunction *Thunk = ThunkBody->getParent();
    SILBasicBlock *NormalBlock = Thunk->createBasicBlock();
    ReturnValue =
        NormalBlock->createPhiArgument(ResultType, ValueOwnershipKind::Owned);
    SILBasicBlock *ErrorBlock = Thunk->createBasicBlock();

    SILType Error = Conv.getSILType(FunctionTy->getErrorResult());
    auto *ErrorArg =
        ErrorBlock->createPhiArgument(Error, ValueOwnershipKind::Owned);
    Builder.createTryApply(Loc, FRI, SubMap, ApplyArgs, NormalBlock,
                           ErrorBlock);

    Builder.setInsertionPoint(ErrorBlock);
    Builder.createThrow(Loc, ErrorArg);
    Builder.setInsertionPoint(NormalBlock);
  } else {
    /// Create the Apply with substitutions
    ReturnValue = Builder.createApply(Loc, FRI, SubMap, ApplyArgs);
  }
  auto cleanupLoc = RegularLocation::getAutoGeneratedLocation();
  for (auto &Temp : reversed(Temps)) {
    // The original argument was copied into a temporary and consumed by the
    // callee as such:
    //   bb (%consumedExistential : $*Protocol)
    //     %valAdr = open_existential_addr %consumedExistential
    //     %temp = alloc_stack $T
    //     copy_addr %valAdr to %temp // <== Temp CopyAddr
    //     apply(%temp)               // <== Temp is consumed by the apply
    //
    // Destroy the original arument and deallocation the temporary:
    //     destroy_addr %consumedExistential : $*Protocol
    //     dealloc_stack %temp : $*T
    if (Temp.DestroyValue)
      Builder.createDestroyAddr(cleanupLoc, Temp.DestroyValue);
    if (Temp.DeallocStackEntry)
      Builder.createDeallocStack(cleanupLoc, Temp.DeallocStackEntry);
  }
  /// Set up the return results.
  if (NewF->isNoReturnFunction()) {
    Builder.createUnreachable(Loc);
  } else {
    Builder.createReturn(Loc, ReturnValue);
  }
}

/// Strategy to specialize existential arguments:
/// (1) Create a protocol constrained generic function from the old function;
/// (2) Create a thunk for the original function that invokes (1) including
/// setting
///     its inline strategy as always inline.
void ExistentialTransform::createExistentialSpecializedFunction() {
  std::string Name = createExistentialSpecializedFunctionName();
  SILLinkage linkage = getSpecializedLinkage(F, F->getLinkage());

  /// Create devirtualized function type.
  auto NewFTy = createExistentialSpecializedFunctionType();

  auto NewFGenericSig = NewFTy->getGenericSignature();
  auto NewFGenericEnv = NewFGenericSig->getGenericEnvironment();

  /// Step 1: Create the new protocol constrained generic function.
  NewF = FunctionBuilder.createFunction(
      linkage, Name, NewFTy, NewFGenericEnv, F->getLocation(), F->isBare(),
      F->isTransparent(), F->isSerialized(), IsNotDynamic, F->getEntryCount(),
      F->isThunk(), F->getClassSubclassScope(), F->getInlineStrategy(),
      F->getEffectsKind(), nullptr, F->getDebugScope());
  /// Set the semantics attributes for the new function.
  for (auto &Attr : F->getSemanticsAttrs())
    NewF->addSemanticsAttr(Attr);

  /// Set Unqualified ownership, if any.
  if (!F->hasOwnership()) {
    NewF->setOwnershipEliminated();
  }

  /// Step 1a: Populate the body of NewF.
  SubstitutionMap Subs = SubstitutionMap::get(
      NewFGenericSig,
      [&](SubstitutableType *type) -> Type {
        return NewFGenericEnv->mapTypeIntoContext(type);
      },
      LookUpConformanceInModule(F->getModule().getSwiftModule()));
  ExistentialSpecializerCloner cloner(F, NewF, Subs, ArgumentDescList,
                                      ArgToGenericTypeMap,
                                      ExistentialArgDescriptor);
  cloner.cloneAndPopulateFunction();

  /// Step 2: Create the thunk with always_inline and populate its body.
  populateThunkBody();

  assert(F->getDebugScope()->Parent != NewF->getDebugScope()->Parent);

  LLVM_DEBUG(llvm::dbgs() << "After ExistentialSpecializer Pass\n"; F->dump();
             NewF->dump(););
}
