//===--- Existential.cpp - Functions analyzing existentials.  -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "swift/SILOptimizer/Utils/Existential.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/SIL/BasicBlockUtils.h"
#include "swift/SIL/InstructionUtils.h"
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/SmallPtrSet.h"

using namespace swift;

/// Determine InitExistential from global_addr.
/// %3 = global_addr @$P : $*SomeP
/// %4 = init_existential_addr %3 : $*SomeP, $SomeC
/// %5 = alloc_ref $SomeC
/// store %5 to %4 : $*SomeC
/// %8 = alloc_stack $SomeP
/// copy_addr %3 to [initialization] %8 : $*SomeP
/// %10 = apply %9(%3) : $@convention(thin) (@in_guaranteed SomeP)
/// Assumptions: Insn is a direct user of GAI (e.g., copy_addr or 
/// apply pattern shown above) and that a valid init_existential_addr 
/// value is returned only if it can prove that the value it 
/// initializes is the same value at the use point.
static InitExistentialAddrInst *
findInitExistentialFromGlobalAddr(GlobalAddrInst *GAI, SILInstruction *Insn) {
  /// Check for a single InitExistential usage for GAI and
  /// a simple dominance check: both InitExistential and Insn are in
  /// the same basic block and only one InitExistential
  /// occurs between GAI and Insn.
  llvm::SmallPtrSet<SILInstruction *, 8> IEUses;
  for (auto *Use : GAI->getUses()) {
    if (auto *InitExistential =
            dyn_cast<InitExistentialAddrInst>(Use->getUser())) {
      IEUses.insert(InitExistential);
    }
  }

  /// No InitExistential found in the basic block.
  if (IEUses.empty())
    return nullptr;

  /// Walk backwards from Insn instruction till the begining of the basic block
  /// looking for an InitExistential.
  InitExistentialAddrInst *SingleIE = nullptr;
  for (auto II = Insn->getIterator().getReverse(),
            IE = Insn->getParent()->rend();
       II != IE; ++II) {
    if (!IEUses.count(&*II))
      continue;
    if (SingleIE)
      return nullptr;

    SingleIE = cast<InitExistentialAddrInst>(&*II);
  }
  return SingleIE;
}

/// Returns the instruction that initializes the given stack address. This is
/// currently either a init_existential_addr, unconditional_checked_cast_addr,
/// or copy_addr (if the instruction initializing the source of the copy cannot
/// be determined). Returns nullptr if the initializer does not dominate the
/// alloc_stack user \p ASIUser.  If the value is copied from another stack
/// location, \p isCopied is set to true.
///
/// allocStackAddr may either itself be an AllocStackInst or an
/// InitEnumDataAddrInst that projects the value of an AllocStackInst.
static SILInstruction *getStackInitInst(SILValue allocStackAddr,
                                        SILInstruction *ASIUser,
                                        bool &isCopied) {
  SILInstruction *SingleWrite = nullptr;
  // Check that this alloc_stack is initialized only once.
  for (auto Use : allocStackAddr->getUses()) {
    auto *User = Use->getUser();

    // Ignore instructions which don't write to the stack location.
    // Also ignore ASIUser (only kicks in if ASIUser is the original apply).
    if (isa<DeallocStackInst>(User) || isa<DebugValueAddrInst>(User) ||
        isa<DestroyAddrInst>(User) || isa<WitnessMethodInst>(User) ||
        isa<DeinitExistentialAddrInst>(User) ||
        isa<OpenExistentialAddrInst>(User) || User == ASIUser) {
      continue;
    }
    if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
      if (CAI->getDest() == allocStackAddr) {
        if (SingleWrite)
          return nullptr;
        SingleWrite = CAI;
        isCopied = true;
      }
      continue;
    }
    // An unconditional_checked_cast_addr also copies a value into this addr.
    if (auto *UCCAI = dyn_cast<UnconditionalCheckedCastAddrInst>(User)) {
      if (UCCAI->getDest() == allocStackAddr) {
        if (SingleWrite)
          return nullptr;
        SingleWrite = UCCAI;
        isCopied = true;
      }
      continue;
    }
    if (isa<InitExistentialAddrInst>(User)) {
      if (SingleWrite)
        return nullptr;
      SingleWrite = User;
      continue;
    }
    if (isa<ApplyInst>(User) || isa<TryApplyInst>(User)) {
      // Ignore function calls which do not write to the stack location.
      auto Conv = FullApplySite(User).getArgumentConvention(*Use);
      if (Conv != SILArgumentConvention::Indirect_In &&
          Conv != SILArgumentConvention::Indirect_In_Guaranteed)
        return nullptr;
      continue;
    }
    // Bail if there is any unknown (and potentially writing) instruction.
    return nullptr;
  }
  if (!SingleWrite)
    return nullptr;

  // A very simple dominance check. As ASI is an operand of ASIUser,
  // SingleWrite dominates ASIUser if it is in the same block as ASI or
  // ASIUser. (SingleWrite can't occur after ASIUser because the address would
  // be uninitialized on use).
  //
  // If allocStack holds an Optional, then ASI is an InitEnumDataAddrInst
  // projection and not strictly an operand of ASIUser. We rely on the guarantee
  // that this InitEnumDataAddrInst must occur before the InjectEnumAddrInst
  // that was the source of the existential address.
  SILBasicBlock *BB = SingleWrite->getParent();
  if (BB != allocStackAddr->getParentBlock() && BB != ASIUser->getParent())
    return nullptr;

  if (auto *IE = dyn_cast<InitExistentialAddrInst>(SingleWrite))
    return IE;

  if (auto *UCCA = dyn_cast<UnconditionalCheckedCastAddrInst>(SingleWrite)) {
    assert(isCopied && "isCopied not set for a unconditional_checked_cast_addr");
    return UCCA;
  }
  auto *CAI = cast<CopyAddrInst>(SingleWrite);
  assert(isCopied && "isCopied not set for a copy_addr");
  // Attempt to recurse to find a concrete type.
  if (auto *ASI = dyn_cast<AllocStackInst>(CAI->getSrc()))
    return getStackInitInst(ASI, CAI, isCopied);

  // Peek through a stack location holding an Enum.
  //   %stack_adr = alloc_stack
  //   %data_adr  = init_enum_data_addr %stk_adr
  //   %enum_adr  = inject_enum_addr %stack_adr
  //   %copy_src  = unchecked_take_enum_data_addr %enum_adr
  // Replace %copy_src with %data_adr and recurse.
  //
  // TODO: a general Optional elimination sil-combine could
  // supersede this check.
  if (auto *UTEDAI = dyn_cast<UncheckedTakeEnumDataAddrInst>(CAI->getSrc())) {
    if (InitEnumDataAddrInst *IEDAI = findInitAddressForTrivialEnum(UTEDAI))
      return getStackInitInst(IEDAI, CAI, isCopied);
  }

  // Check if the CAISrc is a global_addr.
  if (auto *GAI = dyn_cast<GlobalAddrInst>(CAI->getSrc()))
    return findInitExistentialFromGlobalAddr(GAI, CAI);

  // If the source of the copy cannot be determined, return the copy itself
  // because the caller may have special handling for the source address.
  return CAI;
}

/// Return the address of the value used to initialize the given stack location.
/// If the value originates from init_existential_addr, then it will be a
/// different type than \p allocStackAddr.
static SILValue getAddressOfStackInit(SILValue allocStackAddr,
                                      SILInstruction *ASIUser, bool &isCopied) {
  SILInstruction *initI = getStackInitInst(allocStackAddr, ASIUser, isCopied);
  if (!initI)
    return SILValue();

  if (auto *IEA = dyn_cast<InitExistentialAddrInst>(initI))
    return IEA;

  if (auto *CAI = dyn_cast<CopyAddrInst>(initI))
    return CAI->getSrc();

  return SILValue();
}

/// Check if the given operand originates from a recognized OpenArchetype
/// instruction. If so, return the Opened, otherwise return nullptr.
OpenedArchetypeInfo::OpenedArchetypeInfo(Operand &use) {
  SILValue openedVal = use.get();
  SILInstruction *user = use.getUser();
  if (auto *instance = dyn_cast<AllocStackInst>(openedVal)) {
    // Handle:
    //   %opened = open_existential_addr
    //   %instance = alloc $opened
    //   copy_addr %opened to %stack
    //   <opened_use> %instance
    if (auto stackInitVal =
            getAddressOfStackInit(instance, user, isOpenedValueCopied)) {
      openedVal = stackInitVal;
    }
  }
  if (auto *Open = dyn_cast<OpenExistentialAddrInst>(openedVal)) {
    OpenedArchetype = Open->getType().castTo<ArchetypeType>();
    OpenedArchetypeValue = Open;
    ExistentialValue = Open->getOperand();
    return;
  }
  if (auto *Open = dyn_cast<OpenExistentialRefInst>(openedVal)) {
    OpenedArchetype = Open->getType().castTo<ArchetypeType>();
    OpenedArchetypeValue = Open;
    ExistentialValue = Open->getOperand();
    return;
  }
  if (auto *Open = dyn_cast<OpenExistentialMetatypeInst>(openedVal)) {
    auto Ty = Open->getType().getASTType();
    while (auto Metatype = dyn_cast<MetatypeType>(Ty))
      Ty = Metatype.getInstanceType();
    OpenedArchetype = cast<ArchetypeType>(Ty);
    OpenedArchetypeValue = Open;
    ExistentialValue = Open->getOperand();
  }
}

/// Initialize ExistentialSubs from the given conformance list, using the
/// already initialized ExistentialType and ConcreteType.
void ConcreteExistentialInfo::initializeSubstitutionMap(
    ArrayRef<ProtocolConformanceRef> ExistentialConformances, SILModule *M) {

  // Construct a single-generic-parameter substitution map directly to the
  // ConcreteType with this existential's full list of conformances.
  CanGenericSignature ExistentialSig =
      M->getASTContext().getExistentialSignature(ExistentialType,
                                                 M->getSwiftModule());
  ExistentialSubs = SubstitutionMap::get(ExistentialSig, {ConcreteType},
                                         ExistentialConformances);
  assert(isValid());
}

/// If the ConcreteType is an opened existential, also initialize
/// ConcreteTypeDef to the definition of that type.
void ConcreteExistentialInfo::initializeConcreteTypeDef(
    SILInstruction *typeConversionInst) {
  if (!ConcreteType->isOpenedExistential())
    return;

  assert(isValid());

  // If the concrete type is another existential, we're "forwarding" an
  // opened existential type, so we must keep track of the original
  // defining instruction.
  if (!typeConversionInst->getTypeDependentOperands().empty()) {
    ConcreteTypeDef = cast<SingleValueInstruction>(
        typeConversionInst->getTypeDependentOperands()[0].get());
    return;
  }

  auto typeOperand =
      cast<InitExistentialMetatypeInst>(typeConversionInst)->getOperand();
  assert(typeOperand->getType().hasOpenedExistential()
         && "init_existential is supposed to have a typedef operand");
  ConcreteTypeDef = cast<SingleValueInstruction>(typeOperand);
}

/// Construct this ConcreteExistentialInfo based on the given existential use.
///
/// Finds the init_existential, or an address with concrete type used to
/// initialize the given \p openedUse. If the value is copied
/// from another stack location, \p isCopied is set to true.
///
/// If successful, ConcreteExistentialInfo will be valid upon return, with the
/// following fields assigned:
/// - ExistentialType
/// - isCopied
/// - ConcreteType
/// - ConcreteValue
/// - ConcreteTypeDef
/// - ExistentialSubs
ConcreteExistentialInfo::ConcreteExistentialInfo(SILValue existential,
                                                 SILInstruction *user) {
  if (existential->getType().isAddress()) {
    auto *ASI = dyn_cast<AllocStackInst>(existential);
    if (!ASI)
      return;

    SILInstruction *stackInit =
        getStackInitInst(ASI, user, isConcreteValueCopied);
    if (!stackInit)
      return;

    if (auto *IE = dyn_cast<InitExistentialAddrInst>(stackInit)) {
      ExistentialType = IE->getOperand()->getType().getASTType();
      ConcreteType = IE->getFormalConcreteType();
      ConcreteValue = IE;
      initializeSubstitutionMap(IE->getConformances(), &IE->getModule());
      initializeConcreteTypeDef(IE);
      return;
    }
    // TODO: Once we have a way to introduce more constrained archetypes, handle
    // any unconditional_checked_cast that wasn't already statically eliminated.
    //
    // Unexpected stack write.
    return;
  }

  if (auto *IER = dyn_cast<InitExistentialRefInst>(existential)) {
    ExistentialType = IER->getType().getASTType();
    ConcreteType = IER->getFormalConcreteType();
    ConcreteValue = IER->getOperand();
    initializeSubstitutionMap(IER->getConformances(), &IER->getModule());
    initializeConcreteTypeDef(IER);
    return;
  }

  if (auto *IEM = dyn_cast<InitExistentialMetatypeInst>(existential)) {
    ExistentialType = IEM->getType().getASTType();
    ConcreteValue = IEM->getOperand();
    ConcreteType = ConcreteValue->getType().getASTType();
    while (auto InstanceType =
               dyn_cast<ExistentialMetatypeType>(ExistentialType)) {
      ExistentialType = InstanceType.getInstanceType();
      ConcreteType = cast<MetatypeType>(ConcreteType).getInstanceType();
    }
    initializeSubstitutionMap(IEM->getConformances(), &IEM->getModule());
    initializeConcreteTypeDef(IEM);
    return;
  }
  // Unrecognized opened existential producer.
  return;
}

/// Initialize a ConcreteExistentialInfo based on a concrete type and protocol
/// declaration that has already been computed via whole module type
/// inference. A cast instruction will be introduced to produce the concrete
/// value from the opened value.
///
/// The simpler constructor taking only the existential value is preferred
/// because it generates simpler SIL and does not require an extra
/// cast. However, if that constructor fails to produce a valid
/// ConcreteExistentialInfo, this constructor may succeed because it doesn't
/// needs to rediscover the whole-module inferred ConcreteTypeCandidate.
ConcreteExistentialInfo::ConcreteExistentialInfo(SILValue existential,
                                                 SILInstruction *user,
                                                 CanType ConcreteTypeCandidate,
                                                 ProtocolDecl *Protocol) {
  SILModule *M = existential->getModule();

  // We have the open_existential; we still need the conformance.
  auto ConformanceRef =
      M->getSwiftModule()->conformsToProtocol(ConcreteTypeCandidate, Protocol);
  if (!ConformanceRef)
    return;

  // Assert that the conformance is complete.
  auto *ConcreteConformance = ConformanceRef.getValue().getConcrete();
  assert(ConcreteConformance->isComplete());

  ConcreteType = ConcreteTypeCandidate;
  // There is no ConcreteValue in this case.

  /// Determine the ExistentialConformances and SubstitutionMap.
  ExistentialType = Protocol->getDeclaredType()->getCanonicalType();
  initializeSubstitutionMap(ProtocolConformanceRef(ConcreteConformance), M);

  assert(isValid());
}

ConcreteOpenedExistentialInfo::ConcreteOpenedExistentialInfo(Operand &use)
    : OAI(use) {
  if (!OAI.isValid())
    return;

  CEI.emplace(OAI.ExistentialValue, OAI.OpenedArchetypeValue);
  if (!CEI->isValid()) {
    CEI.reset();
    return;
  }
  CEI->isConcreteValueCopied |= OAI.isOpenedValueCopied;
}

ConcreteOpenedExistentialInfo::ConcreteOpenedExistentialInfo(
    Operand &use, CanType concreteType, ProtocolDecl *protocol)
    : OAI(use) {
  if (!OAI.isValid())
    return;

  CEI.emplace(OAI.ExistentialValue, OAI.OpenedArchetypeValue, concreteType,
              protocol);
  if (!CEI->isValid()) {
    CEI.reset();
    return;
  }
  CEI->isConcreteValueCopied |= OAI.isOpenedValueCopied;
}
