//===- FunctionSupport.cpp - Utility types for function-like ops ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "mlir/Interfaces/FunctionInterfaces.h"

using namespace mlir;

//===----------------------------------------------------------------------===//
// Tablegen Interface Definitions
//===----------------------------------------------------------------------===//

#include "mlir/Interfaces/FunctionInterfaces.cpp.inc"

//===----------------------------------------------------------------------===//
// Function Arguments and Results.
//===----------------------------------------------------------------------===//

static bool isEmptyAttrDict(Attribute attr) {
  return llvm::cast<DictionaryAttr>(attr).empty();
}

DictionaryAttr function_interface_impl::getArgAttrDict(FunctionOpInterface op,
                                                       unsigned index) {
  ArrayAttr attrs = op.getArgAttrsAttr();
  DictionaryAttr argAttrs =
      attrs ? llvm::cast<DictionaryAttr>(attrs[index]) : DictionaryAttr();
  return argAttrs;
}

DictionaryAttr
function_interface_impl::getResultAttrDict(FunctionOpInterface op,
                                           unsigned index) {
  ArrayAttr attrs = op.getResAttrsAttr();
  DictionaryAttr resAttrs =
      attrs ? llvm::cast<DictionaryAttr>(attrs[index]) : DictionaryAttr();
  return resAttrs;
}

ArrayRef<NamedAttribute>
function_interface_impl::getArgAttrs(FunctionOpInterface op, unsigned index) {
  auto argDict = getArgAttrDict(op, index);
  return argDict ? argDict.getValue() : ArrayRef<NamedAttribute>();
}

ArrayRef<NamedAttribute>
function_interface_impl::getResultAttrs(FunctionOpInterface op,
                                        unsigned index) {
  auto resultDict = getResultAttrDict(op, index);
  return resultDict ? resultDict.getValue() : ArrayRef<NamedAttribute>();
}

/// Get either the argument or result attributes array.
template <bool isArg>
static ArrayAttr getArgResAttrs(FunctionOpInterface op) {
  if constexpr (isArg)
    return op.getArgAttrsAttr();
  else
    return op.getResAttrsAttr();
}

/// Set either the argument or result attributes array.
template <bool isArg>
static void setArgResAttrs(FunctionOpInterface op, ArrayAttr attrs) {
  if constexpr (isArg)
    op.setArgAttrsAttr(attrs);
  else
    op.setResAttrsAttr(attrs);
}

/// Erase either the argument or result attributes array.
template <bool isArg>
static void removeArgResAttrs(FunctionOpInterface op) {
  if constexpr (isArg)
    op.removeArgAttrsAttr();
  else
    op.removeResAttrsAttr();
}

/// Set all of the argument or result attribute dictionaries for a function.
template <bool isArg>
static void setAllArgResAttrDicts(FunctionOpInterface op,
                                  ArrayRef<Attribute> attrs) {
  if (llvm::all_of(attrs, isEmptyAttrDict))
    removeArgResAttrs<isArg>(op);
  else
    setArgResAttrs<isArg>(op, ArrayAttr::get(op->getContext(), attrs));
}

void function_interface_impl::setAllArgAttrDicts(
    FunctionOpInterface op, ArrayRef<DictionaryAttr> attrs) {
  setAllArgAttrDicts(op, ArrayRef<Attribute>(attrs.data(), attrs.size()));
}

void function_interface_impl::setAllArgAttrDicts(FunctionOpInterface op,
                                                 ArrayRef<Attribute> attrs) {
  auto wrappedAttrs = llvm::map_range(attrs, [op](Attribute attr) -> Attribute {
    return !attr ? DictionaryAttr::get(op->getContext()) : attr;
  });
  setAllArgResAttrDicts</*isArg=*/true>(op, llvm::to_vector<8>(wrappedAttrs));
}

void function_interface_impl::setAllResultAttrDicts(
    FunctionOpInterface op, ArrayRef<DictionaryAttr> attrs) {
  setAllResultAttrDicts(op, ArrayRef<Attribute>(attrs.data(), attrs.size()));
}

void function_interface_impl::setAllResultAttrDicts(FunctionOpInterface op,
                                                    ArrayRef<Attribute> attrs) {
  auto wrappedAttrs = llvm::map_range(attrs, [op](Attribute attr) -> Attribute {
    return !attr ? DictionaryAttr::get(op->getContext()) : attr;
  });
  setAllArgResAttrDicts</*isArg=*/false>(op, llvm::to_vector<8>(wrappedAttrs));
}

/// Update the given index into an argument or result attribute dictionary.
template <bool isArg>
static void setArgResAttrDict(FunctionOpInterface op, unsigned numTotalIndices,
                              unsigned index, DictionaryAttr attrs) {
  ArrayAttr allAttrs = getArgResAttrs<isArg>(op);
  if (!allAttrs) {
    if (attrs.empty())
      return;

    // If this attribute is not empty, we need to create a new attribute array.
    SmallVector<Attribute, 8> newAttrs(numTotalIndices,
                                       DictionaryAttr::get(op->getContext()));
    newAttrs[index] = attrs;
    setArgResAttrs<isArg>(op, ArrayAttr::get(op->getContext(), newAttrs));
    return;
  }
  // Check to see if the attribute is different from what we already have.
  if (allAttrs[index] == attrs)
    return;

  // If it is, check to see if the attribute array would now contain only empty
  // dictionaries.
  ArrayRef<Attribute> rawAttrArray = allAttrs.getValue();
  if (attrs.empty() &&
      llvm::all_of(rawAttrArray.take_front(index), isEmptyAttrDict) &&
      llvm::all_of(rawAttrArray.drop_front(index + 1), isEmptyAttrDict))
    return removeArgResAttrs<isArg>(op);

  // Otherwise, create a new attribute array with the updated dictionary.
  SmallVector<Attribute, 8> newAttrs(rawAttrArray);
  newAttrs[index] = attrs;
  setArgResAttrs<isArg>(op, ArrayAttr::get(op->getContext(), newAttrs));
}

void function_interface_impl::setArgAttrs(FunctionOpInterface op,
                                          unsigned index,
                                          ArrayRef<NamedAttribute> attributes) {
  assert(index < op.getNumArguments() && "invalid argument number");
  return setArgResAttrDict</*isArg=*/true>(
      op, op.getNumArguments(), index,
      DictionaryAttr::get(op->getContext(), attributes));
}

void function_interface_impl::setArgAttrs(FunctionOpInterface op,
                                          unsigned index,
                                          DictionaryAttr attributes) {
  return setArgResAttrDict</*isArg=*/true>(
      op, op.getNumArguments(), index,
      attributes ? attributes : DictionaryAttr::get(op->getContext()));
}

void function_interface_impl::setResultAttrs(
    FunctionOpInterface op, unsigned index,
    ArrayRef<NamedAttribute> attributes) {
  assert(index < op.getNumResults() && "invalid result number");
  return setArgResAttrDict</*isArg=*/false>(
      op, op.getNumResults(), index,
      DictionaryAttr::get(op->getContext(), attributes));
}

void function_interface_impl::setResultAttrs(FunctionOpInterface op,
                                             unsigned index,
                                             DictionaryAttr attributes) {
  assert(index < op.getNumResults() && "invalid result number");
  return setArgResAttrDict</*isArg=*/false>(
      op, op.getNumResults(), index,
      attributes ? attributes : DictionaryAttr::get(op->getContext()));
}

void function_interface_impl::insertFunctionArguments(
    FunctionOpInterface op, ArrayRef<unsigned> argIndices, TypeRange argTypes,
    ArrayRef<DictionaryAttr> argAttrs, ArrayRef<Location> argLocs,
    unsigned originalNumArgs, Type newType) {
  assert(argIndices.size() == argTypes.size());
  assert(argIndices.size() == argAttrs.size() || argAttrs.empty());
  assert(argIndices.size() == argLocs.size());
  if (argIndices.empty())
    return;

  // There are 3 things that need to be updated:
  // - Function type.
  // - Arg attrs.
  // - Block arguments of entry block, if not empty.

  // Update the argument attributes of the function.
  ArrayAttr oldArgAttrs = op.getArgAttrsAttr();
  if (oldArgAttrs || !argAttrs.empty()) {
    SmallVector<DictionaryAttr, 4> newArgAttrs;
    newArgAttrs.reserve(originalNumArgs + argIndices.size());
    unsigned oldIdx = 0;
    auto migrate = [&](unsigned untilIdx) {
      if (!oldArgAttrs) {
        newArgAttrs.resize(newArgAttrs.size() + untilIdx - oldIdx);
      } else {
        auto oldArgAttrRange = oldArgAttrs.getAsRange<DictionaryAttr>();
        newArgAttrs.append(oldArgAttrRange.begin() + oldIdx,
                           oldArgAttrRange.begin() + untilIdx);
      }
      oldIdx = untilIdx;
    };
    for (unsigned i = 0, e = argIndices.size(); i < e; ++i) {
      migrate(argIndices[i]);
      newArgAttrs.push_back(argAttrs.empty() ? DictionaryAttr{} : argAttrs[i]);
    }
    migrate(originalNumArgs);
    setAllArgAttrDicts(op, newArgAttrs);
  }

  // Update the function type.
  op.setFunctionTypeAttr(TypeAttr::get(newType));

  // Update entry block arguments, if not empty.
  if (!op.isExternal()) {
    Block &entry = op->getRegion(0).front();
    for (unsigned i = 0, e = argIndices.size(); i < e; ++i)
      entry.insertArgument(argIndices[i] + i, argTypes[i], argLocs[i]);
  }
}

void function_interface_impl::insertFunctionResults(
    FunctionOpInterface op, ArrayRef<unsigned> resultIndices,
    TypeRange resultTypes, ArrayRef<DictionaryAttr> resultAttrs,
    unsigned originalNumResults, Type newType) {
  assert(resultIndices.size() == resultTypes.size());
  assert(resultIndices.size() == resultAttrs.size() || resultAttrs.empty());
  if (resultIndices.empty())
    return;

  // There are 2 things that need to be updated:
  // - Function type.
  // - Result attrs.

  // Update the result attributes of the function.
  ArrayAttr oldResultAttrs = op.getResAttrsAttr();
  if (oldResultAttrs || !resultAttrs.empty()) {
    SmallVector<DictionaryAttr, 4> newResultAttrs;
    newResultAttrs.reserve(originalNumResults + resultIndices.size());
    unsigned oldIdx = 0;
    auto migrate = [&](unsigned untilIdx) {
      if (!oldResultAttrs) {
        newResultAttrs.resize(newResultAttrs.size() + untilIdx - oldIdx);
      } else {
        auto oldResultAttrsRange = oldResultAttrs.getAsRange<DictionaryAttr>();
        newResultAttrs.append(oldResultAttrsRange.begin() + oldIdx,
                              oldResultAttrsRange.begin() + untilIdx);
      }
      oldIdx = untilIdx;
    };
    for (unsigned i = 0, e = resultIndices.size(); i < e; ++i) {
      migrate(resultIndices[i]);
      newResultAttrs.push_back(resultAttrs.empty() ? DictionaryAttr{}
                                                   : resultAttrs[i]);
    }
    migrate(originalNumResults);
    setAllResultAttrDicts(op, newResultAttrs);
  }

  // Update the function type.
  op.setFunctionTypeAttr(TypeAttr::get(newType));
}

void function_interface_impl::eraseFunctionArguments(
    FunctionOpInterface op, const BitVector &argIndices, Type newType) {
  // There are 3 things that need to be updated:
  // - Function type.
  // - Arg attrs.
  // - Block arguments of entry block, if not empty.

  // Update the argument attributes of the function.
  if (ArrayAttr argAttrs = op.getArgAttrsAttr()) {
    SmallVector<DictionaryAttr, 4> newArgAttrs;
    newArgAttrs.reserve(argAttrs.size());
    for (unsigned i = 0, e = argIndices.size(); i < e; ++i)
      if (!argIndices[i])
        newArgAttrs.emplace_back(llvm::cast<DictionaryAttr>(argAttrs[i]));
    setAllArgAttrDicts(op, newArgAttrs);
  }

  // Update the function type.
  op.setFunctionTypeAttr(TypeAttr::get(newType));

  // Update entry block arguments, if not empty.
  if (!op.isExternal()) {
    Block &entry = op->getRegion(0).front();
    entry.eraseArguments(argIndices);
  }
}

void function_interface_impl::eraseFunctionResults(
    FunctionOpInterface op, const BitVector &resultIndices, Type newType) {
  // There are 2 things that need to be updated:
  // - Function type.
  // - Result attrs.

  // Update the result attributes of the function.
  if (ArrayAttr resAttrs = op.getResAttrsAttr()) {
    SmallVector<DictionaryAttr, 4> newResultAttrs;
    newResultAttrs.reserve(resAttrs.size());
    for (unsigned i = 0, e = resultIndices.size(); i < e; ++i)
      if (!resultIndices[i])
        newResultAttrs.emplace_back(llvm::cast<DictionaryAttr>(resAttrs[i]));
    setAllResultAttrDicts(op, newResultAttrs);
  }

  // Update the function type.
  op.setFunctionTypeAttr(TypeAttr::get(newType));
}

//===----------------------------------------------------------------------===//
// Function type signature.
//===----------------------------------------------------------------------===//

void function_interface_impl::setFunctionType(FunctionOpInterface op,
                                              Type newType) {
  unsigned oldNumArgs = op.getNumArguments();
  unsigned oldNumResults = op.getNumResults();
  op.setFunctionTypeAttr(TypeAttr::get(newType));
  unsigned newNumArgs = op.getNumArguments();
  unsigned newNumResults = op.getNumResults();

  // Functor used to update the argument and result attributes of the function.
  auto emptyDict = DictionaryAttr::get(op.getContext());
  auto updateAttrFn = [&](auto isArg, unsigned oldCount, unsigned newCount) {
    constexpr bool isArgVal = std::is_same_v<decltype(isArg), std::true_type>;

    if (oldCount == newCount)
      return;
    // The new type has no arguments/results, just drop the attribute.
    if (newCount == 0)
      return removeArgResAttrs<isArgVal>(op);
    ArrayAttr attrs = getArgResAttrs<isArgVal>(op);
    if (!attrs)
      return;

    // The new type has less arguments/results, take the first N attributes.
    if (newCount < oldCount)
      return setAllArgResAttrDicts<isArgVal>(
          op, attrs.getValue().take_front(newCount));

    // Otherwise, the new type has more arguments/results. Initialize the new
    // arguments/results with empty dictionary attributes.
    SmallVector<Attribute> newAttrs(attrs.begin(), attrs.end());
    newAttrs.resize(newCount, emptyDict);
    setAllArgResAttrDicts<isArgVal>(op, newAttrs);
  };

  // Update the argument and result attributes.
  updateAttrFn(std::true_type{}, oldNumArgs, newNumArgs);
  updateAttrFn(std::false_type{}, oldNumResults, newNumResults);
}
