//===- FunctionSupport.h - Utility types for function-like ops --*- 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 support types for Operations that represent function-like
// constructs to use.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_IR_FUNCTIONSUPPORT_H
#define MLIR_IR_FUNCTIONSUPPORT_H

#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/OpDefinition.h"
#include "llvm/ADT/SmallString.h"

namespace mlir {

namespace function_like_impl {

/// Return the name of the attribute used for function types.
inline StringRef getTypeAttrName() { return "type"; }

/// Return the name of the attribute used for function argument attributes.
inline StringRef getArgDictAttrName() { return "arg_attrs"; }

/// Return the name of the attribute used for function argument attributes.
inline StringRef getResultDictAttrName() { return "res_attrs"; }

/// Returns the dictionary attribute corresponding to the argument at 'index'.
/// If there are no argument attributes at 'index', a null attribute is
/// returned.
DictionaryAttr getArgAttrDict(Operation *op, unsigned index);

/// Returns the dictionary attribute corresponding to the result at 'index'.
/// If there are no result attributes at 'index', a null attribute is
/// returned.
DictionaryAttr getResultAttrDict(Operation *op, unsigned index);

namespace detail {
/// Update the given index into an argument or result attribute dictionary.
void setArgResAttrDict(Operation *op, StringRef attrName,
                       unsigned numTotalIndices, unsigned index,
                       DictionaryAttr attrs);
} // namespace detail

/// Set all of the argument or result attribute dictionaries for a function. The
/// size of `attrs` is expected to match the number of arguments/results of the
/// given `op`.
void setAllArgAttrDicts(Operation *op, ArrayRef<DictionaryAttr> attrs);
void setAllArgAttrDicts(Operation *op, ArrayRef<Attribute> attrs);
void setAllResultAttrDicts(Operation *op, ArrayRef<DictionaryAttr> attrs);
void setAllResultAttrDicts(Operation *op, ArrayRef<Attribute> attrs);

/// Return all of the attributes for the argument at 'index'.
inline ArrayRef<NamedAttribute> getArgAttrs(Operation *op, unsigned index) {
  auto argDict = getArgAttrDict(op, index);
  return argDict ? argDict.getValue() : llvm::None;
}

/// Return all of the attributes for the result at 'index'.
inline ArrayRef<NamedAttribute> getResultAttrs(Operation *op, unsigned index) {
  auto resultDict = getResultAttrDict(op, index);
  return resultDict ? resultDict.getValue() : llvm::None;
}

/// Insert the specified arguments and update the function type attribute.
void insertFunctionArguments(Operation *op, ArrayRef<unsigned> argIndices,
                             TypeRange argTypes,
                             ArrayRef<DictionaryAttr> argAttrs,
                             ArrayRef<Optional<Location>> argLocs,
                             unsigned originalNumArgs, Type newType);

/// Insert the specified results and update the function type attribute.
void insertFunctionResults(Operation *op, ArrayRef<unsigned> resultIndices,
                           TypeRange resultTypes,
                           ArrayRef<DictionaryAttr> resultAttrs,
                           unsigned originalNumResults, Type newType);

/// Erase the specified arguments and update the function type attribute.
void eraseFunctionArguments(Operation *op, ArrayRef<unsigned> argIndices,
                            unsigned originalNumArgs, Type newType);

/// Erase the specified results and update the function type attribute.
void eraseFunctionResults(Operation *op, ArrayRef<unsigned> resultIndices,
                          unsigned originalNumResults, Type newType);

/// Get and set a FunctionLike operation's type signature.
FunctionType getFunctionType(Operation *op);
void setFunctionType(Operation *op, FunctionType newType);

/// Get a FunctionLike operation's body.
Region &getFunctionBody(Operation *op);

} // namespace function_like_impl

namespace OpTrait {

/// This trait provides APIs for Ops that behave like functions.  In particular:
/// - Ops must be symbols, i.e. also have the `Symbol` trait;
/// - Ops have a single region with multiple blocks that corresponds to the body
///   of the function;
/// - An op with a single empty region corresponds to an external function;
/// - leading arguments of the first block of the region are treated as function
///   arguments;
/// - they can have argument attributes that are stored in a dictionary
///   attribute on the Op itself.
///
/// This trait provides limited type support for the declared or defined
/// functions. The convenience function `getTypeAttrName()` returns the name of
/// an attribute that can be used to store the function type. In addition, this
/// trait provides `getType` and `setType` helpers to store a `FunctionType` in
/// the attribute named by `getTypeAttrName()`.
///
/// In general, this trait assumes concrete ops use `FunctionType` under the
/// hood. If this is not the case, in order to use the function type support,
/// concrete ops must define the following methods, using the same name, to hide
/// the ones defined for `FunctionType`: `addBodyBlock`, `getType`,
/// `getTypeWithoutArgsAndResults` and `setType`.
///
/// Besides the requirements above, concrete ops must interact with this trait
/// using the following functions:
/// - Concrete ops *must* define a member function `getNumFuncArguments()` that
///   returns the number of function arguments based exclusively on type (so
///   that it can be called on function declarations).
/// - Concrete ops *must* define a member function `getNumFuncResults()` that
///   returns the number of function results based exclusively on type (so that
///   it can be called on function declarations).
/// - To verify that the type respects op-specific invariants, concrete ops may
///   redefine the `verifyType()` hook that will be called after verifying the
///   presence of the `type` attribute and before any call to
///   `getNumFuncArguments`/`getNumFuncResults` from the verifier.
/// - To verify that the body respects op-specific invariants, concrete ops may
///   redefine the `verifyBody()` hook that will be called after verifying the
///   function type and the presence of the (potentially empty) body region.
template <typename ConcreteType>
class FunctionLike : public OpTrait::TraitBase<ConcreteType, FunctionLike> {
public:
  /// Verify that all of the argument attributes are dialect attributes.
  static LogicalResult verifyTrait(Operation *op);

  //===--------------------------------------------------------------------===//
  // Body Handling
  //===--------------------------------------------------------------------===//

  /// Returns true if this function is external, i.e. it has no body.
  bool isExternal() { return empty(); }

  Region &getBody() {
    return function_like_impl::getFunctionBody(this->getOperation());
  }

  /// Delete all blocks from this function.
  void eraseBody() {
    getBody().dropAllReferences();
    getBody().getBlocks().clear();
  }

  /// This is the list of blocks in the function.
  using BlockListType = Region::BlockListType;
  BlockListType &getBlocks() { return getBody().getBlocks(); }

  // Iteration over the block in the function.
  using iterator = BlockListType::iterator;
  using reverse_iterator = BlockListType::reverse_iterator;

  iterator begin() { return getBody().begin(); }
  iterator end() { return getBody().end(); }
  reverse_iterator rbegin() { return getBody().rbegin(); }
  reverse_iterator rend() { return getBody().rend(); }

  bool empty() { return getBody().empty(); }
  void push_back(Block *block) { getBody().push_back(block); }
  void push_front(Block *block) { getBody().push_front(block); }

  Block &back() { return getBody().back(); }
  Block &front() { return getBody().front(); }

  /// Add an entry block to an empty function, and set up the block arguments
  /// to match the signature of the function. The newly inserted entry block
  /// is returned.
  ///
  /// Note that the concrete class must define a method with the same name to
  /// hide this one if the concrete class does not use FunctionType for the
  /// function type under the hood.
  Block *addEntryBlock();

  /// Add a normal block to the end of the function's block list. The function
  /// should at least already have an entry block.
  Block *addBlock();

  /// Hook for concrete ops to verify the contents of the body. Called as a
  /// part of trait verification, after type verification and ensuring that a
  /// region exists.
  LogicalResult verifyBody();

  //===--------------------------------------------------------------------===//
  // Type Attribute Handling
  //===--------------------------------------------------------------------===//

  /// Return the name of the attribute used for function types.
  static StringRef getTypeAttrName() {
    return function_like_impl::getTypeAttrName();
  }

  TypeAttr getTypeAttr() {
    return this->getOperation()->template getAttrOfType<TypeAttr>(
        getTypeAttrName());
  }

  /// Return the type of this function.
  ///
  /// Note that the concrete class must define a method with the same name to
  /// hide this one if the concrete class does not use FunctionType for the
  /// function type under the hood.
  FunctionType getType() {
    return function_like_impl::getFunctionType(this->getOperation());
  }

  /// Return the type of this function with the specified arguments and results
  /// inserted. This is used to update the function's signature in the
  /// `insertArguments` and `insertResults` methods. The arrays must be sorted
  /// by increasing index.
  ///
  /// Note that the concrete class must define a method with the same name to
  /// hide this one if the concrete class does not use FunctionType for the
  /// function type under the hood.
  FunctionType getTypeWithArgsAndResults(ArrayRef<unsigned> argIndices,
                                         TypeRange argTypes,
                                         ArrayRef<unsigned> resultIndices,
                                         TypeRange resultTypes) {
    return getType().getWithArgsAndResults(argIndices, argTypes, resultIndices,
                                           resultTypes);
  }

  /// Return the type of this function without the specified arguments and
  /// results. This is used to update the function's signature in the
  /// `eraseArguments` and `eraseResults` methods. The arrays of indices are
  /// allowed to have duplicates and can be in any order.
  ///
  /// Note that the concrete class must define a method with the same name to
  /// hide this one if the concrete class does not use FunctionType for the
  /// function type under the hood.
  FunctionType getTypeWithoutArgsAndResults(ArrayRef<unsigned> argIndices,
                                            ArrayRef<unsigned> resultIndices) {
    return getType().getWithoutArgsAndResults(argIndices, resultIndices);
  }

  bool isTypeAttrValid() {
    auto typeAttr = getTypeAttr();
    if (!typeAttr)
      return false;
    return typeAttr.getValue() != Type{};
  }

  /// Change the type of this function in place. This is an extremely dangerous
  /// operation and it is up to the caller to ensure that this is legal for this
  /// function, and to restore invariants:
  ///  - the entry block args must be updated to match the function params.
  ///  - the argument/result attributes may need an update: if the new type
  ///    has less parameters we drop the extra attributes, if there are more
  ///    parameters they won't have any attributes.
  ///
  /// Note that the concrete class must define a method with the same name to
  /// hide this one if the concrete class does not use FunctionType for the
  /// function type under the hood.
  void setType(FunctionType newType);

  //===--------------------------------------------------------------------===//
  // Argument and Result Handling
  //===--------------------------------------------------------------------===//
  using BlockArgListType = Region::BlockArgListType;

  unsigned getNumArguments() {
    return static_cast<ConcreteType *>(this)->getNumFuncArguments();
  }

  unsigned getNumResults() {
    return static_cast<ConcreteType *>(this)->getNumFuncResults();
  }

  /// Gets argument.
  BlockArgument getArgument(unsigned idx) { return getBody().getArgument(idx); }

  /// Support argument iteration.
  using args_iterator = Region::args_iterator;
  args_iterator args_begin() { return getBody().args_begin(); }
  args_iterator args_end() { return getBody().args_end(); }
  Block::BlockArgListType getArguments() { return getBody().getArguments(); }

  ValueTypeRange<BlockArgListType> getArgumentTypes() {
    return getBody().getArgumentTypes();
  }

  /// Insert a single argument of type `argType` with attributes `argAttrs` and
  /// location `argLoc` at `argIndex`.
  void insertArgument(unsigned argIndex, Type argType, DictionaryAttr argAttrs,
                      Optional<Location> argLoc = {}) {
    insertArguments({argIndex}, {argType}, {argAttrs}, {argLoc});
  }

  /// Inserts arguments with the listed types, attributes, and locations at the
  /// listed indices. `argIndices` must be sorted. Arguments are inserted in the
  /// order they are listed, such that arguments with identical index will
  /// appear in the same order that they were listed here.
  void insertArguments(ArrayRef<unsigned> argIndices, TypeRange argTypes,
                       ArrayRef<DictionaryAttr> argAttrs,
                       ArrayRef<Optional<Location>> argLocs) {
    unsigned originalNumArgs = getNumArguments();
    Type newType = getTypeWithArgsAndResults(
        argIndices, argTypes, /*resultIndices=*/{}, /*resultTypes=*/{});
    function_like_impl::insertFunctionArguments(
        this->getOperation(), argIndices, argTypes, argAttrs, argLocs,
        originalNumArgs, newType);
  }

  /// Insert a single result of type `resultType` at `resultIndex`.
  void insertResult(unsigned resultIndex, Type resultType,
                    DictionaryAttr resultAttrs) {
    insertResults({resultIndex}, {resultType}, {resultAttrs});
  }

  /// Inserts results with the listed types at the listed indices.
  /// `resultIndices` must be sorted. Results are inserted in the order they are
  /// listed, such that results with identical index will appear in the same
  /// order that they were listed here.
  void insertResults(ArrayRef<unsigned> resultIndices, TypeRange resultTypes,
                     ArrayRef<DictionaryAttr> resultAttrs) {
    unsigned originalNumResults = getNumResults();
    Type newType = getTypeWithArgsAndResults(/*argIndices=*/{}, /*argTypes=*/{},
                                             resultIndices, resultTypes);
    function_like_impl::insertFunctionResults(
        this->getOperation(), resultIndices, resultTypes, resultAttrs,
        originalNumResults, newType);
  }

  /// Erase a single argument at `argIndex`.
  void eraseArgument(unsigned argIndex) { eraseArguments({argIndex}); }

  /// Erases the arguments listed in `argIndices`.
  /// `argIndices` is allowed to have duplicates and can be in any order.
  void eraseArguments(ArrayRef<unsigned> argIndices) {
    unsigned originalNumArgs = getNumArguments();
    Type newType = getTypeWithoutArgsAndResults(argIndices, {});
    function_like_impl::eraseFunctionArguments(this->getOperation(), argIndices,
                                               originalNumArgs, newType);
  }

  /// Erase a single result at `resultIndex`.
  void eraseResult(unsigned resultIndex) { eraseResults({resultIndex}); }

  /// Erases the results listed in `resultIndices`.
  /// `resultIndices` is allowed to have duplicates and can be in any order.
  void eraseResults(ArrayRef<unsigned> resultIndices) {
    unsigned originalNumResults = getNumResults();
    Type newType = getTypeWithoutArgsAndResults({}, resultIndices);
    function_like_impl::eraseFunctionResults(
        this->getOperation(), resultIndices, originalNumResults, newType);
  }

  //===--------------------------------------------------------------------===//
  // Argument Attributes
  //===--------------------------------------------------------------------===//

  /// FunctionLike operations allow for attaching attributes to each of the
  /// respective function arguments. These argument attributes are stored as
  /// DictionaryAttrs in the main operation attribute dictionary. The name of
  /// these entries is `arg` followed by the index of the argument. These
  /// argument attribute dictionaries are optional, and will generally only
  /// exist if they are non-empty.

  /// Return all of the attributes for the argument at 'index'.
  ArrayRef<NamedAttribute> getArgAttrs(unsigned index) {
    return function_like_impl::getArgAttrs(this->getOperation(), index);
  }

  /// Return an ArrayAttr containing all argument attribute dictionaries of this
  /// function, or nullptr if no arguments have attributes.
  ArrayAttr getAllArgAttrs() {
    return this->getOperation()->template getAttrOfType<ArrayAttr>(
        function_like_impl::getArgDictAttrName());
  }
  /// Return all argument attributes of this function.
  void getAllArgAttrs(SmallVectorImpl<DictionaryAttr> &result) {
    if (ArrayAttr argAttrs = getAllArgAttrs()) {
      auto argAttrRange = argAttrs.template getAsRange<DictionaryAttr>();
      result.append(argAttrRange.begin(), argAttrRange.end());
    } else {
      result.append(getNumArguments(),
                    DictionaryAttr::get(this->getOperation()->getContext()));
    }
  }

  /// Return the specified attribute, if present, for the argument at 'index',
  /// null otherwise.
  Attribute getArgAttr(unsigned index, StringAttr name) {
    auto argDict = getArgAttrDict(index);
    return argDict ? argDict.get(name) : nullptr;
  }
  Attribute getArgAttr(unsigned index, StringRef name) {
    auto argDict = getArgAttrDict(index);
    return argDict ? argDict.get(name) : nullptr;
  }

  template <typename AttrClass>
  AttrClass getArgAttrOfType(unsigned index, StringAttr name) {
    return getArgAttr(index, name).template dyn_cast_or_null<AttrClass>();
  }
  template <typename AttrClass>
  AttrClass getArgAttrOfType(unsigned index, StringRef name) {
    return getArgAttr(index, name).template dyn_cast_or_null<AttrClass>();
  }

  /// Set the attributes held by the argument at 'index'.
  void setArgAttrs(unsigned index, ArrayRef<NamedAttribute> attributes);

  /// Set the attributes held by the argument at 'index'. `attributes` may be
  /// null, in which case any existing argument attributes are removed.
  void setArgAttrs(unsigned index, DictionaryAttr attributes);
  void setAllArgAttrs(ArrayRef<DictionaryAttr> attributes) {
    assert(attributes.size() == getNumArguments());
    function_like_impl::setAllArgAttrDicts(this->getOperation(), attributes);
  }
  void setAllArgAttrs(ArrayRef<Attribute> attributes) {
    assert(attributes.size() == getNumArguments());
    function_like_impl::setAllArgAttrDicts(this->getOperation(), attributes);
  }
  void setAllArgAttrs(ArrayAttr attributes) {
    assert(attributes.size() == getNumArguments());
    this->getOperation()->setAttr(function_like_impl::getArgDictAttrName(),
                                  attributes);
  }

  /// If the an attribute exists with the specified name, change it to the new
  /// value. Otherwise, add a new attribute with the specified name/value.
  void setArgAttr(unsigned index, StringAttr name, Attribute value);
  void setArgAttr(unsigned index, StringRef name, Attribute value) {
    setArgAttr(index, StringAttr::get(this->getOperation()->getContext(), name),
               value);
  }

  /// Remove the attribute 'name' from the argument at 'index'. Return the
  /// attribute that was erased, or nullptr if there was no attribute with such
  /// name.
  Attribute removeArgAttr(unsigned index, StringAttr name);
  Attribute removeArgAttr(unsigned index, StringRef name) {
    return removeArgAttr(
        index, StringAttr::get(this->getOperation()->getContext(), name));
  }

  //===--------------------------------------------------------------------===//
  // Result Attributes
  //===--------------------------------------------------------------------===//

  /// FunctionLike operations allow for attaching attributes to each of the
  /// respective function results. These result attributes are stored as
  /// DictionaryAttrs in the main operation attribute dictionary. The name of
  /// these entries is `result` followed by the index of the result. These
  /// result attribute dictionaries are optional, and will generally only
  /// exist if they are non-empty.

  /// Return all of the attributes for the result at 'index'.
  ArrayRef<NamedAttribute> getResultAttrs(unsigned index) {
    return function_like_impl::getResultAttrs(this->getOperation(), index);
  }

  /// Return an ArrayAttr containing all result attribute dictionaries of this
  /// function, or nullptr if no result have attributes.
  ArrayAttr getAllResultAttrs() {
    return this->getOperation()->template getAttrOfType<ArrayAttr>(
        function_like_impl::getResultDictAttrName());
  }
  /// Return all result attributes of this function.
  void getAllResultAttrs(SmallVectorImpl<DictionaryAttr> &result) {
    if (ArrayAttr argAttrs = getAllResultAttrs()) {
      auto argAttrRange = argAttrs.template getAsRange<DictionaryAttr>();
      result.append(argAttrRange.begin(), argAttrRange.end());
    } else {
      result.append(getNumResults(),
                    DictionaryAttr::get(this->getOperation()->getContext()));
    }
  }

  /// Return the specified attribute, if present, for the result at 'index',
  /// null otherwise.
  Attribute getResultAttr(unsigned index, StringAttr name) {
    auto argDict = getResultAttrDict(index);
    return argDict ? argDict.get(name) : nullptr;
  }
  Attribute getResultAttr(unsigned index, StringRef name) {
    auto argDict = getResultAttrDict(index);
    return argDict ? argDict.get(name) : nullptr;
  }

  template <typename AttrClass>
  AttrClass getResultAttrOfType(unsigned index, StringAttr name) {
    return getResultAttr(index, name).template dyn_cast_or_null<AttrClass>();
  }
  template <typename AttrClass>
  AttrClass getResultAttrOfType(unsigned index, StringRef name) {
    return getResultAttr(index, name).template dyn_cast_or_null<AttrClass>();
  }

  /// Set the attributes held by the result at 'index'.
  void setResultAttrs(unsigned index, ArrayRef<NamedAttribute> attributes);

  /// Set the attributes held by the result at 'index'. `attributes` may be
  /// null, in which case any existing argument attributes are removed.
  void setResultAttrs(unsigned index, DictionaryAttr attributes);
  void setAllResultAttrs(ArrayRef<DictionaryAttr> attributes) {
    assert(attributes.size() == getNumResults());
    function_like_impl::setAllResultAttrDicts(this->getOperation(), attributes);
  }
  void setAllResultAttrs(ArrayRef<Attribute> attributes) {
    assert(attributes.size() == getNumResults());
    function_like_impl::setAllResultAttrDicts(this->getOperation(), attributes);
  }
  void setAllResultAttrs(ArrayAttr attributes) {
    assert(attributes.size() == getNumResults());
    this->getOperation()->setAttr(function_like_impl::getResultDictAttrName(),
                                  attributes);
  }

  /// If the an attribute exists with the specified name, change it to the new
  /// value. Otherwise, add a new attribute with the specified name/value.
  void setResultAttr(unsigned index, StringAttr name, Attribute value);
  void setResultAttr(unsigned index, StringRef name, Attribute value) {
    setResultAttr(index,
                  StringAttr::get(this->getOperation()->getContext(), name),
                  value);
  }

  /// Remove the attribute 'name' from the result at 'index'. Return the
  /// attribute that was erased, or nullptr if there was no attribute with such
  /// name.
  Attribute removeResultAttr(unsigned index, StringAttr name);

protected:
  /// Returns the dictionary attribute corresponding to the argument at 'index'.
  /// If there are no argument attributes at 'index', a null attribute is
  /// returned.
  DictionaryAttr getArgAttrDict(unsigned index) {
    assert(index < getNumArguments() && "invalid argument number");
    return function_like_impl::getArgAttrDict(this->getOperation(), index);
  }

  /// Returns the dictionary attribute corresponding to the result at 'index'.
  /// If there are no result attributes at 'index', a null attribute is
  /// returned.
  DictionaryAttr getResultAttrDict(unsigned index) {
    assert(index < getNumResults() && "invalid result number");
    return function_like_impl::getResultAttrDict(this->getOperation(), index);
  }

  /// Hook for concrete classes to verify that the type attribute respects
  /// op-specific invariants.  Default implementation always succeeds.
  LogicalResult verifyType() { return success(); }
};

/// Default verifier checks that if the entry block exists, it has the same
/// number of arguments as the function-like operation.
template <typename ConcreteType>
LogicalResult FunctionLike<ConcreteType>::verifyBody() {
  auto funcOp = cast<ConcreteType>(this->getOperation());

  if (funcOp.isExternal())
    return success();

  unsigned numArguments = funcOp.getNumArguments();
  if (funcOp.front().getNumArguments() != numArguments)
    return funcOp.emitOpError("entry block must have ")
           << numArguments << " arguments to match function signature";

  return success();
}

template <typename ConcreteType>
LogicalResult FunctionLike<ConcreteType>::verifyTrait(Operation *op) {
  auto funcOp = cast<ConcreteType>(op);
  if (!funcOp.isTypeAttrValid())
    return funcOp.emitOpError("requires a type attribute '")
           << getTypeAttrName() << '\'';

  if (failed(funcOp.verifyType()))
    return failure();

  if (ArrayAttr allArgAttrs = funcOp.getAllArgAttrs()) {
    unsigned numArgs = funcOp.getNumArguments();
    if (allArgAttrs.size() != numArgs) {
      return funcOp.emitOpError()
             << "expects argument attribute array `"
             << function_like_impl::getArgDictAttrName()
             << "` to have the same number of elements as the number of "
                "function arguments, got "
             << allArgAttrs.size() << ", but expected " << numArgs;
    }
    for (unsigned i = 0; i != numArgs; ++i) {
      DictionaryAttr argAttrs =
          allArgAttrs[i].dyn_cast_or_null<DictionaryAttr>();
      if (!argAttrs) {
        return funcOp.emitOpError() << "expects argument attribute dictionary "
                                       "to be a DictionaryAttr, but got `"
                                    << allArgAttrs[i] << "`";
      }

      // Verify that all of the argument attributes are dialect attributes, i.e.
      // that they contain a dialect prefix in their name.  Call the dialect, if
      // registered, to verify the attributes themselves.
      for (auto attr : argAttrs) {
        if (!attr.getName().strref().contains('.'))
          return funcOp.emitOpError(
              "arguments may only have dialect attributes");
        if (Dialect *dialect = attr.getNameDialect()) {
          if (failed(dialect->verifyRegionArgAttribute(op, /*regionIndex=*/0,
                                                       /*argIndex=*/i, attr)))
            return failure();
        }
      }
    }
  }
  if (ArrayAttr allResultAttrs = funcOp.getAllResultAttrs()) {
    unsigned numResults = funcOp.getNumResults();
    if (allResultAttrs.size() != numResults) {
      return funcOp.emitOpError()
             << "expects result attribute array `"
             << function_like_impl::getResultDictAttrName()
             << "` to have the same number of elements as the number of "
                "function results, got "
             << allResultAttrs.size() << ", but expected " << numResults;
    }
    for (unsigned i = 0; i != numResults; ++i) {
      DictionaryAttr resultAttrs =
          allResultAttrs[i].dyn_cast_or_null<DictionaryAttr>();
      if (!resultAttrs) {
        return funcOp.emitOpError() << "expects result attribute dictionary "
                                       "to be a DictionaryAttr, but got `"
                                    << allResultAttrs[i] << "`";
      }

      // Verify that all of the result attributes are dialect attributes, i.e.
      // that they contain a dialect prefix in their name.  Call the dialect, if
      // registered, to verify the attributes themselves.
      for (auto attr : resultAttrs) {
        if (!attr.getName().strref().contains('.'))
          return funcOp.emitOpError("results may only have dialect attributes");
        if (Dialect *dialect = attr.getNameDialect()) {
          if (failed(dialect->verifyRegionResultAttribute(op, /*regionIndex=*/0,
                                                          /*resultIndex=*/i,
                                                          attr)))
            return failure();
        }
      }
    }
  }

  // Check that the op has exactly one region for the body.
  if (op->getNumRegions() != 1)
    return funcOp.emitOpError("expects one region");

  return funcOp.verifyBody();
}

//===----------------------------------------------------------------------===//
// Function Body.
//===----------------------------------------------------------------------===//

template <typename ConcreteType>
Block *FunctionLike<ConcreteType>::addEntryBlock() {
  assert(empty() && "function already has an entry block");
  auto *entry = new Block();
  push_back(entry);
  entry->addArguments(getType().getInputs());
  return entry;
}

template <typename ConcreteType>
Block *FunctionLike<ConcreteType>::addBlock() {
  assert(!empty() && "function should at least have an entry block");
  push_back(new Block());
  return &back();
}

//===----------------------------------------------------------------------===//
// Function Type Attribute.
//===----------------------------------------------------------------------===//

template <typename ConcreteType>
void FunctionLike<ConcreteType>::setType(FunctionType newType) {
  function_like_impl::setFunctionType(this->getOperation(), newType);
}

//===----------------------------------------------------------------------===//
// Function Argument Attribute.
//===----------------------------------------------------------------------===//

/// Set the attributes held by the argument at 'index'.
template <typename ConcreteType>
void FunctionLike<ConcreteType>::setArgAttrs(
    unsigned index, ArrayRef<NamedAttribute> attributes) {
  assert(index < getNumArguments() && "invalid argument number");
  Operation *op = this->getOperation();
  return function_like_impl::detail::setArgResAttrDict(
      op, function_like_impl::getArgDictAttrName(), getNumArguments(), index,
      DictionaryAttr::get(op->getContext(), attributes));
}

template <typename ConcreteType>
void FunctionLike<ConcreteType>::setArgAttrs(unsigned index,
                                             DictionaryAttr attributes) {
  Operation *op = this->getOperation();
  return function_like_impl::detail::setArgResAttrDict(
      op, function_like_impl::getArgDictAttrName(), getNumArguments(), index,
      attributes ? attributes : DictionaryAttr::get(op->getContext()));
}

/// If the an attribute exists with the specified name, change it to the new
/// value. Otherwise, add a new attribute with the specified name/value.
template <typename ConcreteType>
void FunctionLike<ConcreteType>::setArgAttr(unsigned index, StringAttr name,
                                            Attribute value) {
  NamedAttrList attributes(getArgAttrDict(index));
  Attribute oldValue = attributes.set(name, value);

  // If the attribute changed, then set the new arg attribute list.
  if (value != oldValue)
    setArgAttrs(index, attributes.getDictionary(value.getContext()));
}

/// Remove the attribute 'name' from the argument at 'index'.
template <typename ConcreteType>
Attribute FunctionLike<ConcreteType>::removeArgAttr(unsigned index,
                                                    StringAttr name) {
  // Build an attribute list and remove the attribute at 'name'.
  NamedAttrList attributes(getArgAttrDict(index));
  Attribute removedAttr = attributes.erase(name);

  // If the attribute was removed, then update the argument dictionary.
  if (removedAttr)
    setArgAttrs(index, attributes.getDictionary(removedAttr.getContext()));
  return removedAttr;
}

//===----------------------------------------------------------------------===//
// Function Result Attribute.
//===----------------------------------------------------------------------===//

/// Set the attributes held by the result at 'index'.
template <typename ConcreteType>
void FunctionLike<ConcreteType>::setResultAttrs(
    unsigned index, ArrayRef<NamedAttribute> attributes) {
  assert(index < getNumResults() && "invalid result number");
  Operation *op = this->getOperation();
  return function_like_impl::detail::setArgResAttrDict(
      op, function_like_impl::getResultDictAttrName(), getNumResults(), index,
      DictionaryAttr::get(op->getContext(), attributes));
}

template <typename ConcreteType>
void FunctionLike<ConcreteType>::setResultAttrs(unsigned index,
                                                DictionaryAttr attributes) {
  assert(index < getNumResults() && "invalid result number");
  Operation *op = this->getOperation();
  return function_like_impl::detail::setArgResAttrDict(
      op, function_like_impl::getResultDictAttrName(), getNumResults(), index,
      attributes ? attributes : DictionaryAttr::get(op->getContext()));
}

/// If the an attribute exists with the specified name, change it to the new
/// value. Otherwise, add a new attribute with the specified name/value.
template <typename ConcreteType>
void FunctionLike<ConcreteType>::setResultAttr(unsigned index, StringAttr name,
                                               Attribute value) {
  NamedAttrList attributes(getResultAttrDict(index));
  Attribute oldAttr = attributes.set(name, value);

  // If the attribute changed, then set the new arg attribute list.
  if (oldAttr != value)
    setResultAttrs(index, attributes.getDictionary(value.getContext()));
}

/// Remove the attribute 'name' from the result at 'index'.
template <typename ConcreteType>
Attribute FunctionLike<ConcreteType>::removeResultAttr(unsigned index,
                                                       StringAttr name) {
  // Build an attribute list and remove the attribute at 'name'.
  NamedAttrList attributes(getResultAttrDict(index));
  Attribute removedAttr = attributes.erase(name);

  // If the attribute was removed, then update the result dictionary.
  if (removedAttr)
    setResultAttrs(index, attributes.getDictionary(removedAttr.getContext()));
  return removedAttr;
}

} // end namespace OpTrait

} // end namespace mlir

#endif // MLIR_IR_FUNCTIONSUPPORT_H
