//===--- InstructionUtils.cpp - Utilities for SIL instructions ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-inst-utils"
#include "swift/SIL/InstructionUtils.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/Basic/NullablePtr.h"
#include "swift/Basic/STLExtras.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SIL/Projection.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILVisitor.h"

using namespace swift;

SILValue swift::stripOwnershipInsts(SILValue v) {
  while (true) {
    switch (v->getKind()) {
    default:
      return v;
    case ValueKind::CopyValueInst:
    case ValueKind::BeginBorrowInst:
      v = cast<SingleValueInstruction>(v)->getOperand(0);
    }
  }
}

/// Strip off casts/indexing insts/address projections from V until there is
/// nothing left to strip.
/// FIXME: Why don't we strip projections after stripping indexes?
SILValue swift::getUnderlyingObject(SILValue v) {
  while (true) {
    SILValue v2 = stripCasts(v);
    v2 = stripAddressProjections(v2);
    v2 = stripIndexingInsts(v2);
    v2 = stripOwnershipInsts(v2);
    if (v2 == v)
      return v2;
    v = v2;
  }
}

/// Strip off casts and address projections into the interior of a value. Unlike
/// getUnderlyingObject, this does not find the root of a heap object--a class
/// property is itself an address root.
SILValue swift::getUnderlyingAddressRoot(SILValue V) {
  while (true) {
    SILValue V2 = stripIndexingInsts(stripCasts(V));
    switch (V2->getKind()) {
      case ValueKind::StructElementAddrInst:
      case ValueKind::TupleElementAddrInst:
      case ValueKind::UncheckedTakeEnumDataAddrInst:
        V2 = cast<SingleValueInstruction>(V2)->getOperand(0);
        break;
      default:
        break;
    }
    if (V2 == V)
      return V2;
    V = V2;
  }
}


SILValue swift::getUnderlyingObjectStopAtMarkDependence(SILValue v) {
  while (true) {
    SILValue v2 = stripCastsWithoutMarkDependence(v);
    v2 = stripAddressProjections(v2);
    v2 = stripIndexingInsts(v2);
    v2 = stripOwnershipInsts(v2);
    if (v2 == v)
      return v2;
    v = v2;
  }
}

static bool isRCIdentityPreservingCast(ValueKind Kind) {
  switch (Kind) {
  case ValueKind::UpcastInst:
  case ValueKind::UncheckedRefCastInst:
  case ValueKind::UnconditionalCheckedCastInst:
  case ValueKind::UnconditionalCheckedCastValueInst:
  case ValueKind::RefToBridgeObjectInst:
  case ValueKind::BridgeObjectToRefInst:
    return true;
  default:
    return false;
  }
}

/// Return the underlying SILValue after stripping off identity SILArguments if
/// we belong to a BB with one predecessor.
SILValue swift::stripSinglePredecessorArgs(SILValue V) {
  while (true) {
    auto *A = dyn_cast<SILArgument>(V);
    if (!A)
      return V;
    
    SILBasicBlock *BB = A->getParent();
    
    // First try and grab the single predecessor of our parent BB. If we don't
    // have one, bail.
    SILBasicBlock *Pred = BB->getSinglePredecessorBlock();
    if (!Pred)
      return V;
    
    // Then grab the terminator of Pred...
    TermInst *PredTI = Pred->getTerminator();
    
    // And attempt to find our matching argument.
    //
    // *NOTE* We can only strip things here if we know that there is no semantic
    // change in terms of upcasts/downcasts/enum extraction since this is used
    // by other routines here. This means that we can only look through
    // cond_br/br.
    //
    // For instance, routines that use stripUpcasts() do not want to strip off a
    // downcast that results from checked_cast_br.
    if (auto *BI = dyn_cast<BranchInst>(PredTI)) {
      V = BI->getArg(A->getIndex());
      continue;
    }
    
    if (auto *CBI = dyn_cast<CondBranchInst>(PredTI)) {
      if (SILValue Arg = CBI->getArgForDestBB(BB, A)) {
        V = Arg;
        continue;
      }
    }
    
    return V;
  }
}

SILValue swift::stripCastsWithoutMarkDependence(SILValue V) {
  while (true) {
    V = stripSinglePredecessorArgs(V);

    auto K = V->getKind();
    if (isRCIdentityPreservingCast(K) ||
        K == ValueKind::UncheckedTrivialBitCastInst) {
      V = cast<SingleValueInstruction>(V)->getOperand(0);
      continue;
    }

    return V;
  }
}

SILValue swift::stripCasts(SILValue v) {
  while (true) {
    v = stripSinglePredecessorArgs(v);
    
    auto k = v->getKind();
    if (isRCIdentityPreservingCast(k)
        || k == ValueKind::UncheckedTrivialBitCastInst
        || k == ValueKind::MarkDependenceInst) {
      v = cast<SingleValueInstruction>(v)->getOperand(0);
      continue;
    }

    SILValue v2 = stripOwnershipInsts(v);
    if (v2 != v) {
      v = v2;
      continue;
    }

    return v;
  }
}

SILValue swift::stripUpCasts(SILValue v) {
  assert(v->getType().isClassOrClassMetatype() &&
         "Expected class or class metatype!");
  
  v = stripSinglePredecessorArgs(v);
  
  while (true) {
    if (auto *ui = dyn_cast<UpcastInst>(v)) {
      v = ui->getOperand();
      continue;
    }

    SILValue v2 = stripSinglePredecessorArgs(v);
    v2 = stripOwnershipInsts(v2);
    if (v2 == v) {
      return v2;
    }
    v = v2;
  }
}

SILValue swift::stripClassCasts(SILValue v) {
  while (true) {
    if (auto *ui = dyn_cast<UpcastInst>(v)) {
      v = ui->getOperand();
      continue;
    }
    
    if (auto *ucci = dyn_cast<UnconditionalCheckedCastInst>(v)) {
      v = ucci->getOperand();
      continue;
    }

    SILValue v2 = stripOwnershipInsts(v);
    if (v2 != v) {
      v = v2;
      continue;
    }

    return v;
  }
}

SILValue swift::stripAddressAccess(SILValue V) {
  while (true) {
    switch (V->getKind()) {
    default:
      return V;
    case ValueKind::BeginBorrowInst:
    case ValueKind::BeginAccessInst:
      V = cast<SingleValueInstruction>(V)->getOperand(0);
    }
  }
}

SILValue swift::stripAddressProjections(SILValue V) {
  while (true) {
    V = stripSinglePredecessorArgs(V);
    if (!Projection::isAddressProjection(V))
      return V;
    V = cast<SingleValueInstruction>(V)->getOperand(0);
  }
}

SILValue swift::stripValueProjections(SILValue V) {
  while (true) {
    V = stripSinglePredecessorArgs(V);
    if (!Projection::isObjectProjection(V))
      return V;
    V = cast<SingleValueInstruction>(V)->getOperand(0);
  }
}

SILValue swift::stripIndexingInsts(SILValue V) {
  while (true) {
    if (!isa<IndexingInst>(V))
      return V;
    V = cast<IndexingInst>(V)->getBase();
  }
}

SILValue swift::stripExpectIntrinsic(SILValue V) {
  auto *BI = dyn_cast<BuiltinInst>(V);
  if (!BI)
    return V;
  if (BI->getIntrinsicInfo().ID != llvm::Intrinsic::expect)
    return V;
  return BI->getArguments()[0];
}

SILValue swift::stripBorrow(SILValue V) {
  if (auto *BBI = dyn_cast<BeginBorrowInst>(V))
    return BBI->getOperand();
  return V;
}

// All instructions handled here must propagate their first operand into their
// single result.
//
// This is guaranteed to handle all function-type converstions: ThinToThick,
// ConvertFunction, and ConvertEscapeToNoEscapeInst.
SingleValueInstruction *swift::getSingleValueCopyOrCast(SILInstruction *I) {
  if (auto *convert = dyn_cast<ConversionInst>(I))
    return convert;

  switch (I->getKind()) {
  default:
    return nullptr;
  case SILInstructionKind::CopyValueInst:
  case SILInstructionKind::CopyBlockInst:
  case SILInstructionKind::CopyBlockWithoutEscapingInst:
  case SILInstructionKind::BeginBorrowInst:
  case SILInstructionKind::BeginAccessInst:
  case SILInstructionKind::MarkDependenceInst:
    return cast<SingleValueInstruction>(I);
  }
}

// Does this instruction terminate a SIL-level scope?
bool swift::isEndOfScopeMarker(SILInstruction *user) {
  switch (user->getKind()) {
  default:
    return false;
  case SILInstructionKind::EndAccessInst:
  case SILInstructionKind::EndBorrowInst:
  case SILInstructionKind::EndLifetimeInst:
    return true;
  }
}

bool swift::isIncidentalUse(SILInstruction *user) {
  return isEndOfScopeMarker(user) || user->isDebugInstruction() ||
         isa<FixLifetimeInst>(user);
}

bool swift::onlyAffectsRefCount(SILInstruction *user) {
  switch (user->getKind()) {
  default:
    return false;
  case SILInstructionKind::AutoreleaseValueInst:
  case SILInstructionKind::DestroyValueInst:
  case SILInstructionKind::ReleaseValueInst:
  case SILInstructionKind::RetainValueInst:
  case SILInstructionKind::StrongReleaseInst:
  case SILInstructionKind::StrongRetainInst:
  case SILInstructionKind::UnmanagedAutoreleaseValueInst:
#define UNCHECKED_REF_STORAGE(Name, ...)                                       \
  case SILInstructionKind::Name##RetainValueInst:                              \
  case SILInstructionKind::Name##ReleaseValueInst:                             \
  case SILInstructionKind::Copy##Name##ValueInst:
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...)            \
  case SILInstructionKind::Name##RetainInst:                                   \
  case SILInstructionKind::Name##ReleaseInst:                                  \
  case SILInstructionKind::StrongRetain##Name##Inst:                           \
  case SILInstructionKind::Copy##Name##ValueInst:
#include "swift/AST/ReferenceStorage.def"
    return true;
  }
}

bool swift::mayCheckRefCount(SILInstruction *User) {
  return isa<IsUniqueInst>(User) || isa<IsEscapingClosureInst>(User);
}

bool swift::isSanitizerInstrumentation(SILInstruction *Instruction) {
  auto *BI = dyn_cast<BuiltinInst>(Instruction);
  if (!BI)
    return false;

  Identifier Name = BI->getName();
  if (Name == BI->getModule().getASTContext().getIdentifier("tsanInoutAccess"))
    return true;

  return false;
}

SILValue swift::isPartialApplyOfReabstractionThunk(PartialApplyInst *PAI) {
  // A partial_apply of a reabstraction thunk either has a single capture
  // (a function) or two captures (function and dynamic Self type).
  if (PAI->getNumArguments() != 1 &&
      PAI->getNumArguments() != 2)
    return SILValue();

  auto *Fun = PAI->getReferencedFunctionOrNull();
  if (!Fun)
    return SILValue();

  // Make sure we have a reabstraction thunk.
  if (Fun->isThunk() != IsReabstractionThunk)
    return SILValue();

  // The argument should be a closure.
  auto Arg = PAI->getArgument(0);
  if (!Arg->getType().is<SILFunctionType>() ||
      (!Arg->getType().isReferenceCounted(PAI->getFunction()->getModule()) &&
       Arg->getType().getAs<SILFunctionType>()->getRepresentation() !=
           SILFunctionType::Representation::Thick))
    return SILValue();

  return Arg;
}

bool swift::onlyUsedByAssignByWrapper(PartialApplyInst *PAI) {
  bool usedByAssignByWrapper = false;
  for (Operand *Op : PAI->getUses()) {
    SILInstruction *User = Op->getUser();
    if (isa<AssignByWrapperInst>(User) && Op->getOperandNumber() >= 2) {
      usedByAssignByWrapper = true;
      continue;
    }
    if (isa<DestroyValueInst>(User))
      continue;
    return false;
  }
  return usedByAssignByWrapper;
}

/// Given a block used as a noescape function argument, attempt to find all
/// Swift closures that invoking the block will call. The StoredClosures may not
/// actually be partial_apply instructions. They may be copied, block arguments,
/// or conversions. The caller must continue searching up the use-def chain.
static SILValue findClosureStoredIntoBlock(SILValue V) {

  auto FnType = V->getType().castTo<SILFunctionType>();
  assert(FnType->getRepresentation() == SILFunctionTypeRepresentation::Block);
  (void)FnType;

  // Given a no escape block argument to a function,
  // pattern match to find the noescape closure that invoking the block
  // will call:
  //     %noescape_closure = ...
  //     %wae_Thunk = function_ref @$withoutActuallyEscapingThunk
  //     %sentinel =
  //       partial_apply [callee_guaranteed] %wae_thunk(%noescape_closure)
  //     %noescaped_wrapped = mark_dependence %sentinel on %noescape_closure
  //     %storage = alloc_stack
  //     %storage_address = project_block_storage %storage
  //     store %noescaped_wrapped to [init] %storage_address
  //     %block = init_block_storage_header %storage invoke %thunk
  //     %arg = copy_block %block

  InitBlockStorageHeaderInst *IBSHI = dyn_cast<InitBlockStorageHeaderInst>(V);
  if (!IBSHI)
    return nullptr;

  SILValue BlockStorage = IBSHI->getBlockStorage();
  auto *PBSI = BlockStorage->getSingleUserOfType<ProjectBlockStorageInst>();
  assert(PBSI && "Couldn't find block storage projection");

  auto *SI = PBSI->getSingleUserOfType<StoreInst>();
  assert(SI && "Couldn't find single store of function into block storage");

  auto *CV = dyn_cast<CopyValueInst>(SI->getSrc());
  if (!CV)
    return nullptr;
  auto *WrappedNoEscape = dyn_cast<MarkDependenceInst>(CV->getOperand());
  if (!WrappedNoEscape)
    return nullptr;
  auto Sentinel = dyn_cast<PartialApplyInst>(WrappedNoEscape->getValue());
  if (!Sentinel)
    return nullptr;
  auto NoEscapeClosure = isPartialApplyOfReabstractionThunk(Sentinel);
  if (WrappedNoEscape->getBase() != NoEscapeClosure)
    return nullptr;

  // This is the value of the closure to be invoked. To find the partial_apply
  // itself, the caller must search the use-def chain.
  return NoEscapeClosure;
}

/// Find all closures that may be propagated into the given function-type value.
///
/// Searches the use-def chain from the given value upward until a partial_apply
/// is reached. Populates `results` with the set of partial_apply instructions.
///
/// `funcVal` may be either a function type or an Optional function type. This
/// might be called on a directly applied value or on a call argument, which may
/// in turn be applied within the callee.
void swift::findClosuresForFunctionValue(
    SILValue funcVal, TinyPtrVector<PartialApplyInst *> &results) {

  SILType funcTy = funcVal->getType();
  // Handle `Optional<@convention(block) @noescape (_)->(_)>`
  if (auto optionalObjTy = funcTy.getOptionalObjectType())
    funcTy = optionalObjTy;
  assert(funcTy.is<SILFunctionType>());

  SmallVector<SILValue, 4> worklist;
  // Avoid exponential path exploration and prevent duplicate results.
  llvm::SmallDenseSet<SILValue, 8> visited;
  auto worklistInsert = [&](SILValue V) {
    if (visited.insert(V).second)
      worklist.push_back(V);
  };
  worklistInsert(funcVal);

  while (!worklist.empty()) {
    SILValue V = worklist.pop_back_val();

    if (auto *I = V->getDefiningInstruction()) {
      // Look through copies, borrows, and conversions.
      //
      // Handle copy_block and copy_block_without_actually_escaping before
      // calling findClosureStoredIntoBlock.
      if (SingleValueInstruction *SVI = getSingleValueCopyOrCast(I)) {
        worklistInsert(SVI->getOperand(0));
        continue;
      }
      // SWIFT_ENABLE_TENSORFLOW
      if (auto *DFI = dyn_cast<DifferentiableFunctionInst>(I)) {
        worklistInsert(DFI->getOperand(0));
        continue;
      }
    }
    // Look through Optionals.
    if (V->getType().getOptionalObjectType()) {
      auto *EI = dyn_cast<EnumInst>(V);
      if (EI && EI->hasOperand()) {
        worklistInsert(EI->getOperand());
      }
      // Ignore the .None case.
      continue;
    }
    // Look through Phis.
    //
    // This should be done before calling findClosureStoredIntoBlock.
    if (auto *arg = dyn_cast<SILPhiArgument>(V)) {
      SmallVector<std::pair<SILBasicBlock *, SILValue>, 2> blockArgs;
      arg->getIncomingPhiValues(blockArgs);
      for (auto &blockAndArg : blockArgs)
        worklistInsert(blockAndArg.second);

      continue;
    }
    // Look through ObjC closures.
    auto fnType = V->getType().getAs<SILFunctionType>();
    if (fnType
        && fnType->getRepresentation() == SILFunctionTypeRepresentation::Block) {
      if (SILValue storedClosure = findClosureStoredIntoBlock(V))
        worklistInsert(storedClosure);

      continue;
    }
    if (auto *PAI = dyn_cast<PartialApplyInst>(V)) {
      SILValue thunkArg = isPartialApplyOfReabstractionThunk(PAI);
      if (thunkArg) {
        // Handle reabstraction thunks recursively. This may reabstract over
        // @convention(block).
        worklistInsert(thunkArg);
        continue;
      }
      results.push_back(PAI);
      continue;
    }
    // Ignore other unrecognized values that feed this applied argument.
  }
}

bool PolymorphicBuiltinSpecializedOverloadInfo::init(
    SILFunction *fn, BuiltinValueKind builtinKind,
    ArrayRef<SILType> oldOperandTypes, SILType oldResultType) {
  assert(!isInitialized && "Expected uninitialized info");
  SWIFT_DEFER { isInitialized = true; };
  if (!isPolymorphicBuiltin(builtinKind))
    return false;

  // Ok, at this point we know that we have a true polymorphic builtin. See if
  // we have an overload for its current operand type.
  StringRef name = getBuiltinName(builtinKind);
  StringRef prefix = "generic_";
  assert(name.startswith(prefix) &&
         "Invalid polymorphic builtin name! Prefix should be Generic$OP?!");
  SmallString<32> staticOverloadName;
  staticOverloadName.append(name.drop_front(prefix.size()));

  // If our first argument is an address, we know we have an indirect @out
  // parameter by convention since all of these polymorphic builtins today never
  // take indirect parameters without an indirect out result parameter. We stash
  // this information and validate that if we have an out param, that our result
  // is equal to the empty tuple type.
  if (oldOperandTypes[0].isAddress()) {
    if (oldResultType != fn->getModule().Types.getEmptyTupleType())
      return false;

    hasOutParam = true;
    SILType firstType = oldOperandTypes.front();

    // We only handle polymorphic builtins with trivial types today.
    if (!firstType.is<BuiltinType>() || !firstType.isTrivial(*fn)) {
      return false;
    }

    resultType = firstType.getObjectType();
    oldOperandTypes = oldOperandTypes.drop_front();
  } else {
    resultType = oldResultType;
  }

  // Then go through all of our values and bail if any after substitution are
  // not concrete builtin types. Otherwise, stash each of them in the argTypes
  // array as objects. We will convert them as appropriate.
  for (SILType ty : oldOperandTypes) {
    // If after specialization, we do not have a trivial builtin type, bail.
    if (!ty.is<BuiltinType>() || !ty.isTrivial(*fn)) {
      return false;
    }

    // Otherwise, we have an object builtin type ready to go.
    argTypes.push_back(ty.getObjectType());
  }

  // Ok, we have all builtin types. Infer the underlying polymorphic builtin
  // name form our first argument.
  CanBuiltinType builtinType = argTypes.front().getAs<BuiltinType>();
  SmallString<32> builtinTypeNameStorage;
  StringRef typeName = builtinType->getTypeName(builtinTypeNameStorage, false);
  staticOverloadName.append("_");
  staticOverloadName.append(typeName);

  auto &ctx = fn->getASTContext();
  staticOverloadIdentifier = ctx.getIdentifier(staticOverloadName);

  // Ok, we have our overload identifier. Grab the builtin info from the
  // cache. If we did not actually found a valid builtin value kind for our
  // overload, then we do not have a static overload for the passed in types, so
  // return false.
  builtinInfo = &fn->getModule().getBuiltinInfo(staticOverloadIdentifier);
  return true;
}

bool PolymorphicBuiltinSpecializedOverloadInfo::init(BuiltinInst *bi) {
  assert(!isInitialized && "Can not init twice?!");
  SWIFT_DEFER { isInitialized = true; };

  // First quickly make sure we have a /real/ BuiltinValueKind, not an intrinsic
  // or None.
  auto kind = bi->getBuiltinKind();
  if (!kind)
    return false;

  SmallVector<SILType, 8> oldOperandTypes;
  copy(bi->getOperandTypes(), std::back_inserter(oldOperandTypes));
  assert(bi->getNumResults() == 1 &&
         "We expect a tuple here instead of real args");
  SILType oldResultType = bi->getResult(0)->getType();
  return init(bi->getFunction(), *kind, oldOperandTypes, oldResultType);
}

SILValue
swift::getStaticOverloadForSpecializedPolymorphicBuiltin(BuiltinInst *bi) {

  PolymorphicBuiltinSpecializedOverloadInfo info;
  if (!info.init(bi))
    return SILValue();

  SmallVector<SILValue, 8> rawArgsData;
  copy(bi->getOperandValues(), std::back_inserter(rawArgsData));

  SILValue result = bi->getResult(0);
  MutableArrayRef<SILValue> rawArgs = rawArgsData;

  if (info.hasOutParam) {
    result = rawArgs.front();
    rawArgs = rawArgs.drop_front();
  }

  assert(bi->getNumResults() == 1 &&
         "We assume that builtins have a single result today. If/when this "
         "changes, this code needs to be updated");

  SILBuilderWithScope builder(bi);

  // Ok, now we know that we can convert this to our specialized
  // builtin. Prepare the arguments for the specialized value, loading the
  // values if needed and storing the result into an out parameter if needed.
  //
  // NOTE: We only support polymorphic builtins with trivial types today, so we
  // use load/store trivial as a result.
  SmallVector<SILValue, 8> newArgs;
  for (SILValue arg : rawArgs) {
    if (arg->getType().isObject()) {
      newArgs.push_back(arg);
      continue;
    }

    SILValue load = builder.emitLoadValueOperation(
        bi->getLoc(), arg, LoadOwnershipQualifier::Trivial);
    newArgs.push_back(load);
  }

  BuiltinInst *newBI =
      builder.createBuiltin(bi->getLoc(), info.staticOverloadIdentifier,
                            info.resultType, {}, newArgs);

  // If we have an out parameter initialize it now.
  if (info.hasOutParam) {
    builder.emitStoreValueOperation(newBI->getLoc(), newBI->getResult(0),
                                    result, StoreOwnershipQualifier::Trivial);
  }

  return newBI;
}
