//===- Value.h - Base of the SSA Value hierarchy ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines generic Value type and manipulation utilities.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_IR_VALUE_H
#define MLIR_IR_VALUE_H

#include "mlir/IR/Types.h"
#include "mlir/IR/UseDefLists.h"
#include "mlir/Support/LLVM.h"
#include "llvm/Support/PointerLikeTypeTraits.h"

namespace mlir {
class AsmState;
class Block;
class BlockArgument;
class Operation;
class OpOperand;
class OpResult;
class Region;
class Value;

//===----------------------------------------------------------------------===//
// Value
//===----------------------------------------------------------------------===//

namespace detail {

/// The base class for all derived Value classes. It contains all of the
/// components that are shared across Value classes.
class alignas(8) ValueImpl : public IRObjectWithUseList<OpOperand> {
public:
  /// The enumeration represents the various different kinds of values the
  /// internal representation may take. We use all of the bits from Type that we
  /// can to store indices inline.
  enum class Kind {
    /// The first N kinds are all inline operation results. An inline operation
    /// result means that the kind represents the result number. This removes
    /// the need to store an additional index value. The derived class here is
    /// an `OpResultImpl`.
    InlineOpResult = 0,

    /// The next kind represents a 'out-of-line' operation result. This is for
    /// results with numbers larger than we can represent inline. The derived
    /// class here is an `OpResultImpl`.
    OutOfLineOpResult = 6,

    /// The last kind represents a block argument. The derived class here is an
    /// `BlockArgumentImpl`.
    BlockArgument = 7
  };

  /// Return the type of this value.
  Type getType() const { return typeAndKind.getPointer(); }

  /// Set the type of this value.
  void setType(Type type) { return typeAndKind.setPointer(type); }

  /// Return the kind of this value.
  Kind getKind() const { return typeAndKind.getInt(); }

protected:
  ValueImpl(Type type, Kind kind) : typeAndKind(type, kind) {}

  /// The type of this result and the kind.
  llvm::PointerIntPair<Type, 3, Kind> typeAndKind;
};
} // namespace detail

/// This class represents an instance of an SSA value in the MLIR system,
/// representing a computable value that has a type and a set of users. An SSA
/// value is either a BlockArgument or the result of an operation. Note: This
/// class has value-type semantics and is just a simple wrapper around a
/// ValueImpl that is either owner by a block(in the case of a BlockArgument) or
/// an Operation(in the case of an OpResult).
class Value {
public:
  Value(detail::ValueImpl *impl = nullptr) : impl(impl) {}
  Value(const Value &) = default;
  Value &operator=(const Value &) = default;

  template <typename U>
  bool isa() const {
    assert(*this && "isa<> used on a null type.");
    return U::classof(*this);
  }

  template <typename First, typename Second, typename... Rest>
  bool isa() const {
    return isa<First>() || isa<Second, Rest...>();
  }
  template <typename U>
  U dyn_cast() const {
    return isa<U>() ? U(impl) : U(nullptr);
  }
  template <typename U>
  U dyn_cast_or_null() const {
    return (*this && isa<U>()) ? U(impl) : U(nullptr);
  }
  template <typename U>
  U cast() const {
    assert(isa<U>());
    return U(impl);
  }

  explicit operator bool() const { return impl; }
  bool operator==(const Value &other) const { return impl == other.impl; }
  bool operator!=(const Value &other) const { return !(*this == other); }

  /// Return the type of this value.
  Type getType() const { return impl->getType(); }

  /// Utility to get the associated MLIRContext that this value is defined in.
  MLIRContext *getContext() const { return getType().getContext(); }

  /// Mutate the type of this Value to be of the specified type.
  ///
  /// Note that this is an extremely dangerous operation which can create
  /// completely invalid IR very easily.  It is strongly recommended that you
  /// recreate IR objects with the right types instead of mutating them in
  /// place.
  void setType(Type newType) { impl->setType(newType); }

  /// If this value is the result of an operation, return the operation that
  /// defines it.
  Operation *getDefiningOp() const;

  /// If this value is the result of an operation of type OpTy, return the
  /// operation that defines it.
  template <typename OpTy>
  OpTy getDefiningOp() const {
    return llvm::dyn_cast_or_null<OpTy>(getDefiningOp());
  }

  /// Return the location of this value.
  Location getLoc() const;
  void setLoc(Location loc);

  /// Return the Region in which this Value is defined.
  Region *getParentRegion();

  /// Return the Block in which this Value is defined.
  Block *getParentBlock();

  //===--------------------------------------------------------------------===//
  // UseLists
  //===--------------------------------------------------------------------===//

  /// Drop all uses of this object from their respective owners.
  void dropAllUses() const { return impl->dropAllUses(); }

  /// Replace all uses of 'this' value with the new value, updating anything in
  /// the IR that uses 'this' to use the other value instead.  When this returns
  /// there are zero uses of 'this'.
  void replaceAllUsesWith(Value newValue) const {
    impl->replaceAllUsesWith(newValue);
  }

  /// Replace all uses of 'this' value with 'newValue', updating anything in the
  /// IR that uses 'this' to use the other value instead except if the user is
  /// listed in 'exceptions' .
  void
  replaceAllUsesExcept(Value newValue,
                       const SmallPtrSetImpl<Operation *> &exceptions) const;

  /// Replace all uses of 'this' value with 'newValue', updating anything in the
  /// IR that uses 'this' to use the other value instead except if the user is
  /// 'exceptedUser'.
  void replaceAllUsesExcept(Value newValue, Operation *exceptedUser) const;

  /// Replace all uses of 'this' value with 'newValue' if the given callback
  /// returns true.
  void replaceUsesWithIf(Value newValue,
                         function_ref<bool(OpOperand &)> shouldReplace);

  /// Returns true if the value is used outside of the given block.
  bool isUsedOutsideOfBlock(Block *block);

  //===--------------------------------------------------------------------===//
  // Uses

  /// This class implements an iterator over the uses of a value.
  using use_iterator = ValueUseIterator<OpOperand>;
  using use_range = iterator_range<use_iterator>;

  use_iterator use_begin() const { return impl->use_begin(); }
  use_iterator use_end() const { return use_iterator(); }

  /// Returns a range of all uses, which is useful for iterating over all uses.
  use_range getUses() const { return {use_begin(), use_end()}; }

  /// Returns true if this value has exactly one use.
  bool hasOneUse() const { return impl->hasOneUse(); }

  /// Returns true if this value has no uses.
  bool use_empty() const { return impl->use_empty(); }

  //===--------------------------------------------------------------------===//
  // Users

  using user_iterator = ValueUserIterator<use_iterator, OpOperand>;
  using user_range = iterator_range<user_iterator>;

  user_iterator user_begin() const { return use_begin(); }
  user_iterator user_end() const { return use_end(); }
  user_range getUsers() const { return {user_begin(), user_end()}; }

  //===--------------------------------------------------------------------===//
  // Utilities

  void print(raw_ostream &os);
  void print(raw_ostream &os, AsmState &state);
  void dump();

  /// Print this value as if it were an operand.
  void printAsOperand(raw_ostream &os, AsmState &state);

  /// Methods for supporting PointerLikeTypeTraits.
  void *getAsOpaquePointer() const { return impl; }
  static Value getFromOpaquePointer(const void *pointer) {
    return reinterpret_cast<detail::ValueImpl *>(const_cast<void *>(pointer));
  }
  detail::ValueImpl *getImpl() const { return impl; }

  friend ::llvm::hash_code hash_value(Value arg);

protected:
  /// A pointer to the internal implementation of the value.
  detail::ValueImpl *impl;
};

inline raw_ostream &operator<<(raw_ostream &os, Value value) {
  value.print(os);
  return os;
}

//===----------------------------------------------------------------------===//
// OpOperand
//===----------------------------------------------------------------------===//

/// This class represents an operand of an operation. Instances of this class
/// contain a reference to a specific `Value`.
class OpOperand : public IROperand<OpOperand, Value> {
public:
  /// Provide the use list that is attached to the given value.
  static IRObjectWithUseList<OpOperand> *getUseList(Value value) {
    return value.getImpl();
  }

  /// Return which operand this is in the OpOperand list of the Operation.
  unsigned getOperandNumber();

private:
  /// Keep the constructor private and accessible to the OperandStorage class
  /// only to avoid hard-to-debug typo/programming mistakes.
  friend class OperandStorage;
  using IROperand<OpOperand, Value>::IROperand;
};

//===----------------------------------------------------------------------===//
// BlockArgument
//===----------------------------------------------------------------------===//

namespace detail {
/// The internal implementation of a BlockArgument.
class BlockArgumentImpl : public ValueImpl {
public:
  static bool classof(const ValueImpl *value) {
    return value->getKind() == ValueImpl::Kind::BlockArgument;
  }

private:
  BlockArgumentImpl(Type type, Block *owner, int64_t index, Location loc)
      : ValueImpl(type, Kind::BlockArgument), owner(owner), index(index),
        loc(loc) {}

  /// The owner of this argument.
  Block *owner;

  /// The position in the argument list.
  int64_t index;

  /// The source location of this argument.
  Location loc;

  /// Allow access to owner and constructor.
  friend BlockArgument;
};
} // end namespace detail

/// This class represents an argument of a Block.
class BlockArgument : public Value {
public:
  using Value::Value;

  static bool classof(Value value) {
    return llvm::isa<detail::BlockArgumentImpl>(value.getImpl());
  }

  /// Returns the block that owns this argument.
  Block *getOwner() const { return getImpl()->owner; }

  /// Returns the number of this argument.
  unsigned getArgNumber() const { return getImpl()->index; }

  /// Return the location for this argument.
  Location getLoc() const { return getImpl()->loc; }
  void setLoc(Location loc) { getImpl()->loc = loc; }

private:
  /// Allocate a new argument with the given type and owner.
  static BlockArgument create(Type type, Block *owner, int64_t index,
                              Location loc) {
    return new detail::BlockArgumentImpl(type, owner, index, loc);
  }

  /// Destroy and deallocate this argument.
  void destroy() { delete getImpl(); }

  /// Get a raw pointer to the internal implementation.
  detail::BlockArgumentImpl *getImpl() const {
    return reinterpret_cast<detail::BlockArgumentImpl *>(impl);
  }

  /// Cache the position in the block argument list.
  void setArgNumber(int64_t index) { getImpl()->index = index; }

  /// Allow access to `create`, `destroy` and `setArgNumber`.
  friend Block;

  /// Allow access to 'getImpl'.
  friend Value;
};

//===----------------------------------------------------------------------===//
// OpResult
//===----------------------------------------------------------------------===//

namespace detail {
/// This class provides the implementation for an operation result.
class alignas(8) OpResultImpl : public ValueImpl {
public:
  using ValueImpl::ValueImpl;

  static bool classof(const ValueImpl *value) {
    return value->getKind() != ValueImpl::Kind::BlockArgument;
  }

  /// Returns the parent operation of this result.
  Operation *getOwner() const;

  /// Returns the result number of this op result.
  unsigned getResultNumber() const;

  /// Returns the next operation result at `offset` after this result. This
  /// method is useful when indexing the result storage of an operation, given
  /// that there is more than one kind of operation result (with the different
  /// kinds having different sizes) and that operations are stored in reverse
  /// order.
  OpResultImpl *getNextResultAtOffset(intptr_t offset);

  /// Returns the maximum number of results that can be stored inline.
  static unsigned getMaxInlineResults() {
    return static_cast<unsigned>(Kind::OutOfLineOpResult);
  }
};

/// This class provides the implementation for an operation result whose index
/// can be represented "inline" in the underlying ValueImpl.
struct InlineOpResult : public OpResultImpl {
public:
  InlineOpResult(Type type, unsigned resultNo)
      : OpResultImpl(type, static_cast<ValueImpl::Kind>(resultNo)) {
    assert(resultNo < getMaxInlineResults());
  }

  /// Return the result number of this op result.
  unsigned getResultNumber() const { return static_cast<unsigned>(getKind()); }

  static bool classof(const OpResultImpl *value) {
    return value->getKind() != ValueImpl::Kind::OutOfLineOpResult;
  }
};

/// This class provides the implementation for an operation result whose index
/// cannot be represented "inline", and thus requires an additional index field.
class OutOfLineOpResult : public OpResultImpl {
public:
  OutOfLineOpResult(Type type, uint64_t outOfLineIndex)
      : OpResultImpl(type, Kind::OutOfLineOpResult),
        outOfLineIndex(outOfLineIndex) {}

  static bool classof(const OpResultImpl *value) {
    return value->getKind() == ValueImpl::Kind::OutOfLineOpResult;
  }

  /// Return the result number of this op result.
  unsigned getResultNumber() const {
    return outOfLineIndex + getMaxInlineResults();
  }

  /// The trailing result number, or the offset from the beginning of the
  /// `OutOfLineOpResult` array.
  uint64_t outOfLineIndex;
};

/// Return the result number of this op result.
inline unsigned OpResultImpl::getResultNumber() const {
  if (const auto *outOfLineResult = dyn_cast<OutOfLineOpResult>(this))
    return outOfLineResult->getResultNumber();
  return cast<InlineOpResult>(this)->getResultNumber();
}

} // end namespace detail

/// This is a value defined by a result of an operation.
class OpResult : public Value {
public:
  using Value::Value;

  static bool classof(Value value) {
    return llvm::isa<detail::OpResultImpl>(value.getImpl());
  }

  /// Returns the operation that owns this result.
  Operation *getOwner() const { return getImpl()->getOwner(); }

  /// Returns the number of this result.
  unsigned getResultNumber() const { return getImpl()->getResultNumber(); }

private:
  /// Get a raw pointer to the internal implementation.
  detail::OpResultImpl *getImpl() const {
    return reinterpret_cast<detail::OpResultImpl *>(impl);
  }

  /// Given a number of operation results, returns the number that need to be
  /// stored inline.
  static unsigned getNumInline(unsigned numResults);

  /// Given a number of operation results, returns the number that need to be
  /// stored as trailing.
  static unsigned getNumTrailing(unsigned numResults);

  /// Allow access to constructor.
  friend Operation;
};

/// Make Value hashable.
inline ::llvm::hash_code hash_value(Value arg) {
  return ::llvm::hash_value(arg.getImpl());
}

} // namespace mlir

namespace llvm {

template <>
struct DenseMapInfo<mlir::Value> {
  static mlir::Value getEmptyKey() {
    void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
    return mlir::Value::getFromOpaquePointer(pointer);
  }
  static mlir::Value getTombstoneKey() {
    void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
    return mlir::Value::getFromOpaquePointer(pointer);
  }
  static unsigned getHashValue(mlir::Value val) {
    return mlir::hash_value(val);
  }
  static bool isEqual(mlir::Value lhs, mlir::Value rhs) { return lhs == rhs; }
};
template <>
struct DenseMapInfo<mlir::BlockArgument> : public DenseMapInfo<mlir::Value> {
  static mlir::BlockArgument getEmptyKey() {
    void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
    return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer);
  }
  static mlir::BlockArgument getTombstoneKey() {
    void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
    return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer);
  }
};
template <>
struct DenseMapInfo<mlir::OpResult> : public DenseMapInfo<mlir::Value> {
  static mlir::OpResult getEmptyKey() {
    void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
    return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer);
  }
  static mlir::OpResult getTombstoneKey() {
    void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
    return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer);
  }
};

/// Allow stealing the low bits of a value.
template <>
struct PointerLikeTypeTraits<mlir::Value> {
public:
  static inline void *getAsVoidPointer(mlir::Value value) {
    return const_cast<void *>(value.getAsOpaquePointer());
  }
  static inline mlir::Value getFromVoidPointer(void *pointer) {
    return mlir::Value::getFromOpaquePointer(pointer);
  }
  enum {
    NumLowBitsAvailable =
        PointerLikeTypeTraits<mlir::detail::ValueImpl *>::NumLowBitsAvailable
  };
};
template <>
struct PointerLikeTypeTraits<mlir::BlockArgument>
    : public PointerLikeTypeTraits<mlir::Value> {
public:
  static inline mlir::BlockArgument getFromVoidPointer(void *pointer) {
    return reinterpret_cast<mlir::detail::BlockArgumentImpl *>(pointer);
  }
};
template <>
struct PointerLikeTypeTraits<mlir::OpResult>
    : public PointerLikeTypeTraits<mlir::Value> {
public:
  static inline mlir::OpResult getFromVoidPointer(void *pointer) {
    return reinterpret_cast<mlir::detail::OpResultImpl *>(pointer);
  }
};

} // end namespace llvm

#endif
