//===--- SILGenProlog.cpp - Function prologue emission --------------------===//
//
// 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 "SILGenFunction.h"
#include "Initialization.h"
#include "ManagedValue.h"
#include "Scope.h"
#include "swift/SIL/SILArgument.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/ParameterList.h"

using namespace swift;
using namespace Lowering;

SILValue SILGenFunction::emitSelfDecl(VarDecl *selfDecl) {
  // Emit the implicit 'self' argument.
  SILType selfType = getLoweredLoadableType(selfDecl->getType());
  SILValue selfValue = F.begin()->createFunctionArgument(selfType, selfDecl);
  VarLocs[selfDecl] = VarLoc::get(selfValue);
  SILLocation PrologueLoc(selfDecl);
  PrologueLoc.markAsPrologue();
  uint16_t ArgNo = 1; // Hardcoded for destructors.
  B.createDebugValue(PrologueLoc, selfValue,
                     SILDebugVariable(selfDecl->isLet(), ArgNo));
  return selfValue;
}

namespace {

/// Cleanup that writes back to an inout argument on function exit.
class CleanupWriteBackToInOut : public Cleanup {
  VarDecl *var;
  SILValue inoutAddr;

public:
  CleanupWriteBackToInOut(VarDecl *var, SILValue inoutAddr)
    : var(var), inoutAddr(inoutAddr) {}

  void emit(SILGenFunction &SGF, CleanupLocation l,
            ForUnwind_t forUnwind) override {
    // Assign from the local variable to the inout address with an
    // 'autogenerated' copyaddr.
    l.markAutoGenerated();
    SGF.B.createCopyAddr(l, SGF.VarLocs[var].value, inoutAddr,
                         IsNotTake, IsNotInitialization);
  }
};
} // end anonymous namespace

  
namespace {
class StrongReleaseCleanup : public Cleanup {
  SILValue box;
public:
  StrongReleaseCleanup(SILValue box) : box(box) {}
  void emit(SILGenFunction &SGF, CleanupLocation l,
            ForUnwind_t forUnwind) override {
    SGF.B.emitDestroyValueOperation(l, box);
  }

  void dump(SILGenFunction &) const override {
#ifndef NDEBUG
    llvm::errs() << "DeallocateValueBuffer\n"
                 << "State: " << getState() << "box: " << box << "\n";
#endif
  }
};
} // end anonymous namespace


namespace {
class EmitBBArguments : public CanTypeVisitor<EmitBBArguments,
                                              /*RetTy*/ ManagedValue>
{
public:
  SILGenFunction &SGF;
  SILBasicBlock *parent;
  SILLocation loc;
  ArrayRef<SILParameterInfo> &parameters;

  EmitBBArguments(SILGenFunction &sgf, SILBasicBlock *parent, SILLocation l,
                  ArrayRef<SILParameterInfo> &parameters)
    : SGF(sgf), parent(parent), loc(l), parameters(parameters) {}

  ManagedValue visitType(CanType t) {
    return visitType(t, /*isInOut=*/false);
  }

  ManagedValue visitType(CanType t, bool isInOut) {
    auto argType = SGF.getLoweredType(t);
    if (isInOut)
      argType = SILType::getPrimitiveAddressType(argType.getASTType());

    // Pop the next parameter info.
    auto parameterInfo = parameters.front();
    parameters = parameters.slice(1);

    auto paramType = SGF.F.mapTypeIntoContext(SGF.getSILType(parameterInfo));
    ManagedValue mv = SGF.B.createInputFunctionArgument(
        paramType, loc.getAsASTNode<ValueDecl>());

    if (argType != paramType) {
      // This is a hack to deal with the fact that Self.Type comes in as a
      // static metatype, but we have to downcast it to a dynamic Self
      // metatype to get the right semantics.
      assert(
        cast<DynamicSelfType>(
          argType.castTo<MetatypeType>().getInstanceType())
            .getSelfType()
          == paramType.castTo<MetatypeType>().getInstanceType());
      mv = SGF.B.createUncheckedBitCast(loc, mv, argType);
    }

    if (isInOut)
      return mv;

    // If the value is a (possibly optional) ObjC block passed into the entry
    // point of the function, then copy it so we can treat the value reliably
    // as a heap object. Escape analysis can eliminate this copy if it's
    // unneeded during optimization.
    CanType objectType = t;
    if (auto theObjTy = t.getOptionalObjectType())
      objectType = theObjTy;
    if (isa<FunctionType>(objectType) &&
        cast<FunctionType>(objectType)->getRepresentation()
              == FunctionType::Representation::Block) {
      SILValue blockCopy = SGF.B.createCopyBlock(loc, mv.getValue());
      mv = SGF.emitManagedRValueWithCleanup(blockCopy);
    }
    return mv;
  }

  ManagedValue visitTupleType(CanTupleType t) {
    SmallVector<ManagedValue, 4> elements;

    auto &tl = SGF.getTypeLowering(t);
    bool canBeGuaranteed = tl.isLoadable();

    // Collect the exploded elements.
    for (auto fieldType : t.getElementTypes()) {
      auto elt = visit(fieldType);
      // If we can't borrow one of the elements as a guaranteed parameter, then
      // we have to +1 the tuple.
      if (elt.hasCleanup())
        canBeGuaranteed = false;
      elements.push_back(elt);
    }

    if (tl.isLoadable() || !SGF.silConv.useLoweredAddresses()) {
      SmallVector<SILValue, 4> elementValues;
      if (canBeGuaranteed) {
        // If all of the elements were guaranteed, we can form a guaranteed tuple.
        for (auto element : elements)
          elementValues.push_back(element.getUnmanagedValue());
      } else {
        // Otherwise, we need to move or copy values into a +1 tuple.
        for (auto element : elements) {
          SILValue value = element.hasCleanup()
            ? element.forward(SGF)
            : element.copyUnmanaged(SGF, loc).forward(SGF);
          elementValues.push_back(value);
        }
      }
      auto tupleValue = SGF.B.createTuple(loc, tl.getLoweredType(),
                                          elementValues);
      return canBeGuaranteed
        ? ManagedValue::forUnmanaged(tupleValue)
        : SGF.emitManagedRValueWithCleanup(tupleValue);
    } else {
      // If the type is address-only, we need to move or copy the elements into
      // a tuple in memory.
      // TODO: It would be a bit more efficient to use a preallocated buffer
      // in this case.
      auto buffer = SGF.emitTemporaryAllocation(loc, tl.getLoweredType());
      for (auto i : indices(elements)) {
        auto element = elements[i];
        auto elementBuffer = SGF.B.createTupleElementAddr(loc, buffer,
                                        i, element.getType().getAddressType());
        if (element.hasCleanup())
          element.forwardInto(SGF, loc, elementBuffer);
        else
          element.copyInto(SGF, elementBuffer, loc);
      }
      return SGF.emitManagedRValueWithCleanup(buffer);
    }
  }
};
} // end anonymous namespace

  
namespace {

/// A helper for creating SILArguments and binding variables to the argument
/// names.
struct ArgumentInitHelper {
  SILGenFunction &SGF;
  SILFunction &f;
  SILGenBuilder &initB;

  /// An ArrayRef that we use in our SILParameterList queue. Parameters are
  /// sliced off of the front as they're emitted.
  ArrayRef<SILParameterInfo> parameters;
  uint16_t ArgNo = 0;

  ArgumentInitHelper(SILGenFunction &SGF, SILFunction &f)
    : SGF(SGF), f(f), initB(SGF.B),
      parameters(f.getLoweredFunctionType()->getParameters()) {
  }

  unsigned getNumArgs() const { return ArgNo; }

  ManagedValue makeArgument(Type ty, bool isInOut, SILBasicBlock *parent,
                            SILLocation l) {
    assert(ty && "no type?!");

    // Create an RValue by emitting destructured arguments into a basic block.
    CanType canTy = ty->getCanonicalType();
    EmitBBArguments argEmitter(SGF, parent, l, parameters);

    // Note: inouts of tuples are not exploded, so we bypass visit().
    if (isInOut)
      return argEmitter.visitType(canTy, /*isInOut=*/true);
    return argEmitter.visit(canTy);
  }

  /// Create a SILArgument and store its value into the given Initialization,
  /// if not null.
  void makeArgumentIntoBinding(Type ty, SILBasicBlock *parent, VarDecl *vd) {
    SILLocation loc(vd);
    loc.markAsPrologue();

    ManagedValue argrv = makeArgument(ty, vd->isInOut(), parent, loc);

    if (vd->isInOut()) {
      assert(argrv.getType().isAddress() && "expected inout to be address");
    } else {
      assert(vd->isImmutable() && "expected parameter to be immutable!");
      // If the variable is immutable, we can bind the value as is.
      // Leave the cleanup on the argument, if any, in place to consume the
      // argument if we're responsible for it.
    }
    SGF.VarLocs[vd] = SILGenFunction::VarLoc::get(argrv.getValue());
    SILValue value = argrv.getValue();
    SILDebugVariable varinfo(vd->isLet(), ArgNo);
    if (!argrv.getType().isAddress()) {
      SGF.B.createDebugValue(loc, value, varinfo);
    } else {
      if (auto AllocStack = dyn_cast<AllocStackInst>(value))
        AllocStack->setArgNo(ArgNo);
      else
        SGF.B.createDebugValueAddr(loc, value, varinfo);
    }
  }

  void emitParam(ParamDecl *PD) {
    auto type = PD->getType();

    assert(type->isMaterializable());

    ++ArgNo;
    if (PD->hasName()) {
      makeArgumentIntoBinding(type, &*f.begin(), PD);
      return;
    }

    emitAnonymousParam(type, PD, PD);
  }

  void emitAnonymousParam(Type type, SILLocation paramLoc, ParamDecl *PD) {
    // A value bound to _ is unused and can be immediately released.
    Scope discardScope(SGF.Cleanups, CleanupLocation(PD));

    // Manage the parameter.
    auto argrv = makeArgument(type, PD->isInOut(), &*f.begin(), paramLoc);

    // Emit debug information for the argument.
    SILLocation loc(PD);
    loc.markAsPrologue();
    if (argrv.getType().isAddress())
      SGF.B.createDebugValueAddr(loc, argrv.getValue(),
                                 SILDebugVariable(PD->isLet(), ArgNo));
    else
      SGF.B.createDebugValue(loc, argrv.getValue(),
                             SILDebugVariable(PD->isLet(), ArgNo));
  }
};
} // end anonymous namespace

  
static void makeArgument(Type ty, ParamDecl *decl,
                         SmallVectorImpl<SILValue> &args, SILGenFunction &SGF) {
  assert(ty && "no type?!");
  
  // Destructure tuple arguments.
  if (TupleType *tupleTy = ty->getAs<TupleType>()) {
    for (auto fieldType : tupleTy->getElementTypes())
      makeArgument(fieldType, decl, args, SGF);
  } else {
    auto loweredTy = SGF.getLoweredType(ty);
    if (decl->isInOut())
      loweredTy = SILType::getPrimitiveAddressType(loweredTy.getASTType());
    auto arg = SGF.F.begin()->createFunctionArgument(loweredTy, decl);
    args.push_back(arg);
  }
}


void SILGenFunction::bindParameterForForwarding(ParamDecl *param,
                                     SmallVectorImpl<SILValue> &parameters) {
  makeArgument(param->getType(), param, parameters, *this);
}

void SILGenFunction::bindParametersForForwarding(const ParameterList *params,
                                     SmallVectorImpl<SILValue> &parameters) {
  for (auto param : *params)
    bindParameterForForwarding(param, parameters);
}

static void emitCaptureArguments(SILGenFunction &SGF,
                                 AnyFunctionRef closure,
                                 CapturedValue capture,
                                 uint16_t ArgNo) {

  auto *VD = capture.getDecl();
  SILLocation Loc(VD);
  Loc.markAsPrologue();

  // Local function to get the captured variable type within the capturing
  // context.
  auto getVarTypeInCaptureContext = [&]() -> Type {
    auto interfaceType = VD->getInterfaceType();
    return GenericEnvironment::mapTypeIntoContext(
      closure.getGenericEnvironment(), interfaceType);
  };

  switch (SGF.SGM.Types.getDeclCaptureKind(capture)) {
  case CaptureKind::None:
    break;

  case CaptureKind::Constant: {
    auto type = getVarTypeInCaptureContext();
    auto &lowering = SGF.getTypeLowering(type);
    // Constant decls are captured by value.
    SILType ty = lowering.getLoweredType();
    SILValue val = SGF.F.begin()->createFunctionArgument(ty, VD);

    bool NeedToDestroyValueAtExit = false;

    // If the original variable was settable, then Sema will have treated the
    // VarDecl as an lvalue, even in the closure's use.  As such, we need to
    // allow formation of the address for this captured value.  Create a
    // temporary within the closure to provide this address.
    if (VD->isSettable(VD->getDeclContext())) {
      auto addr = SGF.emitTemporaryAllocation(VD, ty);
      // We have created a copy that needs to be destroyed.
      val = SGF.B.createCopyValue(Loc, val);
      NeedToDestroyValueAtExit = true;
      lowering.emitStore(SGF.B, VD, val, addr, StoreOwnershipQualifier::Init);
      val = addr;
    }

    SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(val);
    if (auto *AllocStack = dyn_cast<AllocStackInst>(val))
      AllocStack->setArgNo(ArgNo);
    else {
      SILDebugVariable DbgVar(/*Constant*/ true, ArgNo);
      SGF.B.createDebugValue(Loc, val, DbgVar);
    }

    // TODO: Closure contexts should always be guaranteed.
    if (NeedToDestroyValueAtExit && !lowering.isTrivial())
      SGF.enterDestroyCleanup(val);
    break;
  }

  case CaptureKind::Box: {
    // LValues are captured as a retained @box that owns
    // the captured value.
    auto type = getVarTypeInCaptureContext();
    auto boxTy = SGF.SGM.Types.getContextBoxTypeForCapture(VD,
                               SGF.getLoweredType(type).getASTType(),
                               SGF.F.getGenericEnvironment(), /*mutable*/ true);
    SILValue box = SGF.F.begin()->createFunctionArgument(
        SILType::getPrimitiveObjectType(boxTy), VD);
    SILValue addr = SGF.B.createProjectBox(VD, box, 0);
    SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr, box);
    SILDebugVariable DbgVar(/*Constant*/ false, ArgNo);
    SGF.B.createDebugValueAddr(Loc, addr, DbgVar);
    break;
  }
  case CaptureKind::StorageAddress: {
    // Non-escaping stored decls are captured as the address of the value.
    auto type = getVarTypeInCaptureContext();
    SILType ty = SGF.getLoweredType(type).getAddressType();
    SILValue addr = SGF.F.begin()->createFunctionArgument(ty, VD);
    SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr);
    SILDebugVariable DbgVar(/*Constant*/ true, ArgNo);
    SGF.B.createDebugValueAddr(Loc, addr, DbgVar);
    break;
  }
  }
}

void SILGenFunction::emitProlog(AnyFunctionRef TheClosure,
                                ParameterList *paramList,
                                ParamDecl *selfParam,
                                Type resultType, bool throws) {
  uint16_t ArgNo = emitProlog(paramList, selfParam, resultType,
                              TheClosure.getAsDeclContext(), throws);

  // Emit the capture argument variables. These are placed last because they
  // become the first curry level of the SIL function.
  auto captureInfo = SGM.Types.getLoweredLocalCaptures(TheClosure);
  for (auto capture : captureInfo.getCaptures()) {
    if (capture.isDynamicSelfMetadata()) {
      auto selfMetatype = MetatypeType::get(
        captureInfo.getDynamicSelfType());
      SILType ty = getLoweredType(selfMetatype);
      SILValue val = F.begin()->createFunctionArgument(ty);
      (void) val;

      return;
    }

    emitCaptureArguments(*this, TheClosure, capture, ++ArgNo);
  }
}

static void emitIndirectResultParameters(SILGenFunction &SGF, Type resultType,
                                         DeclContext *DC) {
  // Expand tuples.
  if (auto tupleType = resultType->getAs<TupleType>()) {
    for (auto eltType : tupleType->getElementTypes()) {
      emitIndirectResultParameters(SGF, eltType, DC);
    }
    return;
  }

  // If the return type is address-only, emit the indirect return argument.

  const TypeLowering &resultTI =
      SGF.getTypeLowering(DC->mapTypeIntoContext(resultType));
  if (!SILModuleConventions::isReturnedIndirectlyInSIL(
          resultTI.getLoweredType(), SGF.SGM.M)) {
    return;
  }
  auto &ctx = SGF.getASTContext();
  auto var = new (ctx) ParamDecl(VarDecl::Specifier::InOut,
                                 SourceLoc(), SourceLoc(),
                                 ctx.getIdentifier("$return_value"), SourceLoc(),
                                 ctx.getIdentifier("$return_value"),
                                 DC);
  var->setInterfaceType(resultType);

  auto *arg =
      SGF.F.begin()->createFunctionArgument(resultTI.getLoweredType(), var);
  (void)arg;
}

uint16_t SILGenFunction::emitProlog(ParameterList *paramList,
                                    ParamDecl *selfParam,
                                    Type resultType,
                                    DeclContext *DC,
                                    bool throws) {
  // Create the indirect result parameters.
  auto *genericSig = DC->getGenericSignatureOfContext();
  resultType = resultType->getCanonicalType(genericSig);

  emitIndirectResultParameters(*this, resultType, DC);

  // Emit the argument variables in calling convention order.
  ArgumentInitHelper emitter(*this, F);

  // Add the SILArguments and use them to initialize the local argument
  // values.
  if (paramList)
    for (auto *param : *paramList)
      emitter.emitParam(param);
  if (selfParam)
    emitter.emitParam(selfParam);

  // Record the ArgNo of the artificial $error inout argument. 
  unsigned ArgNo = emitter.getNumArgs();
  if (throws) {
    RegularLocation Loc = RegularLocation::getAutoGeneratedLocation();
    if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC))
      Loc = AFD->getThrowsLoc();
    else if (auto *ACE = dyn_cast<AbstractClosureExpr>(DC))
      Loc = ACE->getLoc();
    auto NativeErrorTy = SILType::getExceptionType(getASTContext());
    ManagedValue Undef = emitUndef(Loc, NativeErrorTy);
    SILDebugVariable DbgVar("$error", /*Constant*/ false, ++ArgNo);
    B.createDebugValue(Loc, Undef.getValue(), DbgVar);
  }

  return ArgNo;
}

