//===--- ManagedValue.h - Exploded RValue Representation --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// A storage structure for holding a destructured rvalue with an optional
// cleanup(s).
// Ownership of the rvalue can be "forwarded" to disable the associated
// cleanup(s).
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_LOWERING_MANAGEDVALUE_H
#define SWIFT_LOWERING_MANAGEDVALUE_H

#include "Cleanup.h"
#include "llvm/ADT/PointerIntPair.h"
#include "swift/SIL/Consumption.h"
#include "swift/SIL/SILValue.h"

namespace swift {

enum class CastConsumptionKind : unsigned char;

namespace Lowering {

class SILGenFunction;

/// ManagedValue - represents a singular SIL value and an optional cleanup.
/// Ownership of the ManagedValue can be "forwarded" to disable its cleanup when
/// the rvalue is consumed. A ManagedValue can also represent an LValue used as
/// a value, such as an inout function argument, and can be null.
///
/// Interesting relevant cases include:
///   LValue: the SILValue will always have an isAddress() SILType. LValues
///           never have an associated cleanup.
///   RValue, isAddress() type: an address-only RValue.
///   RValue, !isAddress() type: a loadable RValue.
///   "InContext": Represented with the lvalue flag set but with no SILValue,
///                this represents a value that was emitted directly into an
///                initialization stored by an SGFContext.
///
/// The RValue cases may or may not have a cleanup associated with the value.  A
/// cleanup is associated with +1 values of non-trivial type and +0 values of
/// non-trivial type.
///
class ManagedValue {
  /// The value (or address of an address-only value) being managed, and
  /// whether it represents an lvalue.  InContext is represented with the lvalue
  /// flag set but with a null SILValue.
  llvm::PointerIntPair<SILValue, 1, bool> valueAndFlag;
  
  /// A handle to the cleanup that destroys this value, or
  /// CleanupHandle::invalid() if the value has no cleanup.
  CleanupHandle cleanup;

  explicit ManagedValue(SILValue value, bool isLValue, CleanupHandle cleanup)
    : valueAndFlag(value, isLValue), cleanup(cleanup) {
  }

public:
  
  ManagedValue() = default;

  /// Create a managed value for a +1 rvalue.
  ///
  /// Please do not introduce new uses of this method! Instead use one of the
  /// static constructors below.
  ManagedValue(SILValue value, CleanupHandle cleanup)
    : valueAndFlag(value, false), cleanup(cleanup) {
    assert(value && "No value specified?!");
  }

  /// Create a managed value for a +0 rvalue.
  ///
  /// Please do not introduce new uses of this method! Instead use one of the
  /// static constructors below!
  static ManagedValue forUnmanaged(SILValue value) {
    assert(value && "No value specified");
    return ManagedValue(value, false, CleanupHandle::invalid());
  }

  /// Create a managed value for a +1 rvalue object.
  static ManagedValue forOwnedObjectRValue(SILValue value,
                                           CleanupHandle cleanup) {
    assert(value && "No value specified");
    assert(value->getType().isObject() &&
           "Expected borrowed rvalues to be objects");
    assert(value.getOwnershipKind() != ValueOwnershipKind::Trivial);
    return ManagedValue(value, false, cleanup);
  }

  /// Create a managed value for a +1 rvalue address.
  ///
  /// From a high level perspective, this consists of a temporary buffer.
  static ManagedValue forOwnedAddressRValue(SILValue value,
                                            CleanupHandle cleanup) {
    assert(value && "No value specified");
    assert(value->getType().isAddress() && "Expected value to be an address");
    assert(value.getOwnershipKind() == ValueOwnershipKind::Trivial &&
           "Addresses always have trivial ownership");
    return ManagedValue(value, false, cleanup);
  }

  /// Create a managed value for a +1 non-trivial rvalue.
  static ManagedValue forOwnedRValue(SILValue value, CleanupHandle cleanup) {
    if (value->getType().isAddress())
      return ManagedValue::forOwnedAddressRValue(value, cleanup);
    return ManagedValue::forOwnedObjectRValue(value, cleanup);
  }

  /// Create a managed value for a +0 borrowed non-trivial rvalue object.
  static ManagedValue
  forBorrowedObjectRValue(SILValue value) {
    assert(value && "No value specified");
    assert(value->getType().isObject() &&
           "Expected borrowed rvalues to be objects");
    assert(value.getOwnershipKind() != ValueOwnershipKind::Trivial);
    return ManagedValue(value, false, CleanupHandle::invalid());
  }

  /// Create a managed value for a +0 borrowed non-trivial rvalue address.
  static ManagedValue
  forBorrowedAddressRValue(SILValue value) {
    assert(value && "No value specified");
    assert(value->getType().isAddress() && "Expected value to be an address");
    assert(value.getOwnershipKind() == ValueOwnershipKind::Trivial &&
           "Addresses always have trivial ownership");
    return ManagedValue(value, false, CleanupHandle::invalid());
  }

  /// Create a managed value for a +0 guaranteed rvalue.
  static ManagedValue
  forBorrowedRValue(SILValue value) {
    if (value->getType().isAddress())
      return ManagedValue::forBorrowedAddressRValue(value);
    return ManagedValue::forBorrowedObjectRValue(value);
  }

  /// Create a managed value for a +0 trivial object rvalue.
  static ManagedValue forTrivialObjectRValue(SILValue value) {
    assert(value->getType().isObject() && "Expected an object");
    assert(value.getOwnershipKind() == ValueOwnershipKind::Trivial);
    return ManagedValue(value, false, CleanupHandle::invalid());
  }

  /// Create a managed value for a +0 trivial address rvalue.
  static ManagedValue forTrivialAddressRValue(SILValue value) {
    assert(value->getType().isAddress() && "Expected an address");
    assert(value.getOwnershipKind() == ValueOwnershipKind::Trivial);
    return ManagedValue(value, false, CleanupHandle::invalid());
  }

  /// Create a managed value for a +0 trivial rvalue.
  static ManagedValue forTrivialRValue(SILValue value) {
    if (value->getType().isObject())
      return ManagedValue::forTrivialObjectRValue(value);
    return ManagedValue::forTrivialAddressRValue(value);
  }

  /// Create a managed value for an l-value.
  static ManagedValue forLValue(SILValue value) {
    assert(value && "No value specified");
    assert(value->getType().isAddress() &&
           "lvalues always have isAddress() type");
    return ManagedValue(value, true, CleanupHandle::invalid());
  }
  
  /// Create a managed value that indicates that the value you're looking for
  /// got stored into an initialization specified by an SGFContext, instead of
  /// being represented by this ManagedValue.
  static ManagedValue forInContext() {
    return ManagedValue(SILValue(), true, CleanupHandle::invalid());
  }

  bool isLValue() const {
    return valueAndFlag.getInt() && valueAndFlag.getPointer();
  }
  bool isInContext() const {
    return valueAndFlag.getInt() && !valueAndFlag.getPointer();
  }

  /// Return true if this is an +0 rvalue, or has trivial type.
  bool isPlusZeroRValueOrTrivial() const {
    // If this is an lvalue or isInContext() then it is not an RValue.
    if (isLValue() || isInContext()) return false;
    
    // If this has a cleanup attached, then it is +1 rvalue.  If not, it is
    // either +0 or trivial (in which case +0 vs +1 doesn't matter).
    return !hasCleanup();
  }
  
  SILValue getLValueAddress() const {
    assert(isLValue() && "This isn't an lvalue");
    return getValue();
  }
  
  SILValue getUnmanagedValue() const {
    assert(!hasCleanup());
    return getValue();
  }
  SILValue getValue() const { return valueAndFlag.getPointer(); }
  
  SILType getType() const { return getValue()->getType(); }

  ValueOwnershipKind getOwnershipKind() const {
    return getValue().getOwnershipKind();
  }

  /// Transform the given ManagedValue, replacing the underlying value, but
  /// keeping the same cleanup.
  ///
  /// For owned values, this is equivalent to forwarding the cleanup and
  /// creating a new cleanup of the same type on the new value. This is useful
  /// for forwarding sequences.
  ///
  /// For all other values, it is a move.
  ManagedValue transform(SILValue newValue) && {
    assert(getValue().getOwnershipKind() == newValue.getOwnershipKind() &&
           "New value and old value must have the same ownership kind");
    ManagedValue M(newValue, isLValue(), getCleanup());
    *this = ManagedValue();
    return M;
  }

  CanType getSwiftType() const {
    return isLValue()
      ? getType().getSwiftType()
      : getType().getSwiftRValueType();
  }
  
  /// Emit a copy of this value with independent ownership.
  ManagedValue copy(SILGenFunction &gen, SILLocation loc);

  /// Emit a copy of this value with independent ownership into the current
  /// formal evaluation scope.
  ManagedValue formalAccessCopy(SILGenFunction &gen, SILLocation loc);

  /// Store a copy of this value with independent ownership into the given
  /// uninitialized address.
  void copyInto(SILGenFunction &gen, SILValue dest, SILLocation loc);

  /// This is the same operation as 'copy', but works on +0 values that don't
  /// have cleanups.  It returns a +1 value with one.
  ManagedValue copyUnmanaged(SILGenFunction &gen, SILLocation loc);

  /// This is the same operation as 'formalAccessCopy', but works on +0 values
  /// that don't have cleanups.  It returns a +1 value with one.
  ManagedValue formalAccessCopyUnmanaged(SILGenFunction &gen, SILLocation loc);

  bool hasCleanup() const { return cleanup.isValid(); }
  CleanupHandle getCleanup() const { return cleanup; }

  /// Return a "borrowed" version of this value.
  ///
  /// An l-value is borrowed as itself.  A +1 r-value is borrowed as a
  /// +0 r-value, with the assumption that the original ManagedValue
  /// will not be forwarded until the borrowed value is fully used.
  ManagedValue borrow(SILGenFunction &gen, SILLocation loc) const;

  /// Return a formally evaluated "borrowed" version of this value.
  ManagedValue formalAccessBorrow(SILGenFunction &gen, SILLocation loc) const;

  ManagedValue unmanagedBorrow() const {
    return isLValue() ? *this : ManagedValue::forUnmanaged(getValue());
  }

  /// Disable the cleanup for this value.
  void forwardCleanup(SILGenFunction &gen) const;
  
  /// Forward this value, deactivating the cleanup and returning the
  /// underlying value.
  SILValue forward(SILGenFunction &gen) const;
  
  /// Forward this value into memory by storing it to the given address.
  ///
  /// \param gen - The SILGenFunction.
  /// \param loc - the AST location to associate with emitted instructions.
  /// \param address - the address to assign to.
  void forwardInto(SILGenFunction &gen, SILLocation loc, SILValue address);
  
  /// Assign this value into memory, destroying the existing
  /// value at the destination address.
  ///
  /// \param gen - The SILGenFunction.
  /// \param loc - the AST location to associate with emitted instructions.
  /// \param address - the address to assign to.
  void assignInto(SILGenFunction &gen, SILLocation loc, SILValue address);
  
  explicit operator bool() const {
    // "InContext" is not considered false.
    return bool(getValue()) || valueAndFlag.getInt();
  }
};

/// A ManagedValue which may not be intended to be consumed.
///
/// The invariant is that the cleanup on a ManagedValue that's not
/// meant to be consumed should be free to clear.
///
/// Code which gets a ManagedValue from a ConsumableManagedValue
/// must be careful before handing the MV off to an API.  Many
/// SILGen APIs expect that an MV is +1, but ConsumableManagedValue
/// often traffics in borrowed values.  A value is only +1 if
/// the associated consumption is TakeAlways, but conditional
/// operation should turn TakeOnSuccess consumptions into TakeAlways
/// consumptions on their success path.
class ConsumableManagedValue {
  ManagedValue Value;
  CastConsumptionKind FinalConsumption;

public:
  /// Create an invalid CMV.
  ConsumableManagedValue() = default;

  /// Create a CMV with a specific value and consumption rule.
  /*implicit*/ ConsumableManagedValue(ManagedValue value,
                                      CastConsumptionKind finalConsumption)
    : Value(value), FinalConsumption(finalConsumption) {}

  /// Create a CMV for a value of trivial type.
  static ConsumableManagedValue forUnmanaged(SILValue value) {
    return { ManagedValue::forUnmanaged(value),
             CastConsumptionKind::TakeAlways };
  }

  /// Create a CMV for an owned value.
  static ConsumableManagedValue forOwned(ManagedValue value) {
    return { value, CastConsumptionKind::TakeAlways };
  }

  /// Has this been filled in with meaningful data?
  bool isValid() const { return (bool) Value; }

  bool isOwned() const {
    assert(isValid());
    return FinalConsumption == CastConsumptionKind::TakeAlways;
  }

  /// Return true if there's a cleanup associated with this value.
  bool hasCleanup() const { return Value.hasCleanup(); }
  CleanupHandle getCleanup() const { return Value.getCleanup(); }

  SILType getType() const { return Value.getType(); }
  SILValue getValue() const { return Value.getValue(); }

  /// Return a managed value appropriate for the final use of this CMV.
  ManagedValue getFinalManagedValue() const { return Value; }

  /// Get the value as an unmanaged ManagedValue.
  ///
  /// You probably should not be using this; it's here to make it easy
  /// to find code that is probably wrong.
  ManagedValue asUnmanagedValue() const {
    return ManagedValue::forUnmanaged(Value.getValue());
  }

  /// Return the consumption rules appropriate for the final use of
  /// this CMV.
  CastConsumptionKind getFinalConsumption() const { return FinalConsumption; }

  /// Return a managed value that's appropriate for borrowing this
  /// value and promising not to consume it.
  ConsumableManagedValue asBorrowedOperand() const {
    return { asUnmanagedValue(), CastConsumptionKind::CopyOnSuccess };
  }
};

} // namespace Lowering
} // namespace swift

namespace swift {

template <typename To> inline bool isa(const Lowering::ManagedValue &M) {
  return isa<To>(M.getValue());
}

} // end namespace swift

#endif
