// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "pyiree/rt/function_abi.h"

#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/types/span.h"
#include "iree/base/api.h"
#include "iree/base/signature_mangle.h"
#include "iree/hal/api.h"
#include "iree/modules/hal/hal_module.h"
#include "iree/vm/api.h"
#include "pyiree/rt/hal.h"
#include "pyiree/rt/status_utils.h"
#include "pyiree/rt/vm.h"

namespace iree {
namespace python {

namespace {

class SipLinearizeInputsVisitor {
 public:
  SipLinearizeInputsVisitor(SipSignatureParser& parser, py::tuple& py_args,
                            py::dict& py_kwargs,
                            absl::InlinedVector<py::handle, 4>& linear_py_args)
      : parser_(parser),
        py_args_(py_args),
        py_kwargs_(py_kwargs),
        linear_py_args_(linear_py_args) {}

  void IntegerKey(SipSignatureParser& p, int k) {
    auto current = tos();
    try {
      auto current_seq = current.cast<py::sequence>();
      stack_.push_back(current_seq[k]);
    } catch (std::exception& e) {
      auto message =
          absl::StrCat("Expected sequence index ", k, " not found in ",
                       py::repr(current).cast<std::string>());
      SetError(std::move(message));
    }
  }

  void StringKey(SipSignatureParser& p, absl::string_view k) {
    auto current = tos();
    py::str py_k(k.data(), k.size());
    try {
      auto current_dict = tos().cast<py::dict>();
      stack_.push_back(current_dict[py_k]);
    } catch (std::exception& e) {
      auto message = absl::StrCat("Expected key '", k, "' not found in ",
                                  py::repr(current).cast<std::string>());
      SetError(std::move(message));
    }
  }

  void OpenStruct(SipSignatureParser& p,
                  SipSignatureParser::StructType struct_type) {
    // Only structs directly off of the root are opened without a key.
    if (!stack_.empty()) return;

    py::handle tos;
    switch (struct_type) {
      case SipSignatureParser::StructType::kDict:
        tos = py_kwargs_;
        break;
      case SipSignatureParser::StructType::kSequence:
        tos = py_args_;
        break;
    }
    stack_.push_back(tos);
  }

  void CloseStruct(SipSignatureParser& p) {
    if (!stack_.empty()) {
      stack_.pop_back();
    }
  }

  void MapToRawSignatureIndex(SipSignatureParser& p, int index) {
    if (static_cast<int>(linear_py_args_.size()) <= index) {
      linear_py_args_.resize(index + 1);
    }
    linear_py_args_[index] = tos();
    if (!stack_.empty()) {
      stack_.pop_back();
    }
  }

 private:
  py::handle tos() {
    if (stack_.empty()) {
      SetError("Mismatched structures during unpacking arguments");
      return py::handle();
    }
    return stack_.back();
  }

  void SetError(std::string message) { parser_.SetError(message); }

  SipSignatureParser& parser_;
  py::tuple& py_args_;
  py::dict& py_kwargs_;
  absl::InlinedVector<py::handle, 4>& linear_py_args_;

  // The struct stack. Top is the last.
  // When the stack is empty, opening a struct will push the first entry:
  // py_args_ if a sequence and py_kwargs_ if a dict. Otherwise, new stack
  // levels are opened upon key resolution.
  // Either CloseStruct or MapToRawSignatureIndex terminate each level of
  // the stack.
  absl::InlinedVector<py::handle, 4> stack_;
};

class SipStructureResultsVisitor {
 public:
  SipStructureResultsVisitor(
      SipSignatureParser& parser,
      absl::InlinedVector<py::object, 4>& linear_py_results)
      : parser_(parser), linear_py_results_(linear_py_results) {}

  void IntegerKey(SipSignatureParser& p, int k) {
    pending_assign_key_ = py::int_(k);
  }

  void StringKey(SipSignatureParser& p, absl::string_view k) {
    pending_assign_key_ = py::str(k.data(), k.size());
  }

  void OpenStruct(SipSignatureParser& p,
                  SipSignatureParser::StructType struct_type) {
    py::object struct_obj;
    bool is_dict;
    switch (struct_type) {
      case SipSignatureParser::StructType::kDict:
        struct_obj = py::dict();
        is_dict = true;
        break;
      case SipSignatureParser::StructType::kSequence:
        struct_obj = py::list();
        is_dict = false;
        break;
      default:
        SetError("Illegal structure type");
        return;
    }
    // Must assign before pushing so as to assign to the prior level.
    AssignCurrent(struct_obj);
    stack_.push_back(std::make_pair(std::move(struct_obj), is_dict));
  }

  void CloseStruct(SipSignatureParser& p) {
    if (!stack_.empty()) stack_.pop_back();
    pending_assign_key_ = py::none();  // Just in case (for error path).
  }

  void MapToRawSignatureIndex(SipSignatureParser& p, int index) {
    if (index < 0 || index >= static_cast<int>(linear_py_results_.size())) {
      SetError("Raw result index out of range in reflection metadata");
      return;
    }
    py::object current_obj = linear_py_results_[index];
    AssignCurrent(std::move(current_obj));
  }

  py::object ConsumeResult() {
    if (result)
      return std::move(result);
    else
      return py::none();
  }

 private:
  void AssignCurrent(py::object value) {
    if (stack_.empty()) {
      if (result) {
        SetError("Attempt to unpack multiple roots");
        return;
      }
      result = std::move(value);
    } else {
      if (!pending_assign_key_ || pending_assign_key_.is_none()) {
        SetError("Attempt to assign out of order");
        return;
      }

      try {
        auto stack_entry = stack_.back();
        bool is_dict = stack_entry.second;
        if (is_dict) {
          stack_entry.first.cast<py::dict>()[pending_assign_key_] = value;
        } else {
          int index = pending_assign_key_.cast<int>();
          py::list l = stack_entry.first.cast<py::list>();
          // Technically, signature keys can come out of order, which is sad.
          // none-fill the list as needed to fill the gap.
          // TODO: Further guarantees can be enforced at conversion time,
          // simplifying this.
          bool extended = false;
          int list_size = l.size();
          if (list_size <= index) {
            while (l.size() <= index) {
              l.append(py::none());
              extended = true;
            }
            l.append(std::move(value));
          } else {
            l[index] = std::move(value);
          }
          pending_assign_key_ = py::none();
        }
      } catch (std::exception& e) {
        SetError("Corrupt sip signature: Signature/data type mismatch");
        pending_assign_key_ = py::none();
      }
    }
  }

  void SetError(std::string message) { parser_.SetError(message); }

  SipSignatureParser& parser_;
  absl::InlinedVector<py::object, 4>& linear_py_results_;
  py::object result;

  // Parse state.
  // A new level of the stack is opened for each container. Each entry is a
  // pair of (container, is_dict). If not is_dict, it is assumed to be a list.
  absl::InlinedVector<std::pair<py::object, bool>, 4> stack_;
  // If a pending key has been set for a following assignment, it is noted
  // here. The nested assignments, the call sequence is:
  //   1. OpenStruct
  //     For-each key:
  //       a. IntegerKey or StringKey
  //       b. MapToRawSignatureIndex
  //   2. CloseStruct
  // For single-result situations, it is legal to just have a single, top-level
  // call to MapToRawSignatureIndex, which causes the entire result to be
  // equal to the current object.
  py::object pending_assign_key_;
};

// Python friendly entry-point for creating an instance from a list
// of attributes. This is not particularly efficient and is primarily
// for testing. Typically, this will be created directly from a function
// and the attribute introspection will happen internal to C++.
std::unique_ptr<FunctionAbi> PyCreateAbi(
    HalDevice& device, std::shared_ptr<HostTypeFactory> host_type_factory,
    std::vector<std::pair<std::string, std::string>> attrs) {
  auto lookup =
      [&attrs](absl::string_view key) -> absl::optional<absl::string_view> {
    for (const auto& kv : attrs) {
      if (kv.first == key) return kv.second;
    }
    return absl::nullopt;
  };
  return FunctionAbi::Create(device, std::move(host_type_factory), lookup);
}

VmVariantList PyAllocateResults(FunctionAbi* self, VmVariantList& f_args,
                                bool static_alloc) {
  auto f_results = VmVariantList::Create(self->raw_result_arity());
  if (static_alloc) {
    // For static dispatch, attempt to fully allocate and perform shape
    // inference.
    self->AllocateResults(absl::MakeConstSpan(self->raw_config().results),
                          f_args, f_results);
  }
  return f_results;
}

// RAII wrapper for a Py_buffer which calls PyBuffer_Release when it goes
// out of scope.
class PyBufferReleaser {
 public:
  PyBufferReleaser(Py_buffer& b) : b_(b) {}
  ~PyBufferReleaser() { PyBuffer_Release(&b_); }

 private:
  Py_buffer& b_;
};

pybind11::error_already_set RaiseBufferMismatchError(
    std::string message, py::handle obj,
    const RawSignatureParser::Description& desc) {
  message.append("For argument = ");
  auto arg_py_str = py::str(obj);
  auto arg_str = static_cast<std::string>(arg_py_str);
  message.append(arg_str);
  message.append(" (expected ");
  desc.ToString(message);
  message.append(")");
  return RaiseValueError(message.c_str());
}

// Verifies and maps the py buffer shape and layout to the bound argument.
// Returns false if not compatible.
void MapBufferAttrs(Py_buffer& py_view,
                    const RawSignatureParser::Description& desc,
                    absl::InlinedVector<int, 2>& dynamic_dims) {
  // Verify that rank matches.
  if (py_view.ndim != desc.dims.size()) {
    throw RaiseBufferMismatchError(
        absl::StrCat("Mismatched buffer rank (received: ", py_view.ndim,
                     ", expected: ", desc.dims.size(), "): "),
        py::handle(py_view.obj), desc);
  }

  // Verify that the item size matches.
  size_t f_item_size =
      AbiConstants::kScalarTypeSize[static_cast<int>(desc.buffer.scalar_type)];
  if (f_item_size != py_view.itemsize) {
    throw RaiseBufferMismatchError(
        absl::StrCat("Mismatched buffer item size (received: ",
                     py_view.itemsize, ", expected: ", f_item_size, "): "),
        py::handle(py_view.obj), desc);
  }

  // Note: The python buffer format does not map precisely to IREE's type
  // system, so the below is only advisory for where they do match. Otherwise,
  // it is basically a bitcast.
  const char* f_expected_format =
      kScalarTypePyFormat[static_cast<int>(desc.buffer.scalar_type)];

  // If the format is booleans, we should treat it as bytes.
  const char* f_found_format = py_view.format;
  if (strcmp(f_found_format, "?") == 0) {
    f_found_format = "b";
  }

  if (f_expected_format != nullptr &&
      strcmp(f_expected_format, f_found_format) != 0) {
    throw RaiseBufferMismatchError(
        absl::StrCat("Mismatched buffer format (received: ", py_view.format,
                     ", expected: ", f_expected_format, "): "),
        py::handle(py_view.obj), desc);
  }

  // Verify shape, populating dynamic_dims while looping.
  for (size_t i = 0; i < py_view.ndim; ++i) {
    auto py_dim = py_view.shape[i];
    auto f_dim = desc.dims[i];
    if (f_dim < 0) {
      // Dynamic.
      dynamic_dims.push_back(py_dim);
    } else if (py_dim != f_dim) {
      // Mismatch.
      throw RaiseBufferMismatchError(
          absl::StrCat("Mismatched buffer dim (received: ", py_dim,
                       ", expected: ", f_dim, "): "),
          py::handle(py_view.obj), desc);
    }
  }
}

void PackScalar(const RawSignatureParser::Description& desc, py::handle py_arg,
                VmVariantList& f_args) {
  iree_vm_value value;
  value.type = IREE_VM_VALUE_TYPE_I32;
  switch (desc.scalar.type) {
    case AbiConstants::ScalarType::kUint8:
    case AbiConstants::ScalarType::kUint16:
    case AbiConstants::ScalarType::kUint32: {
      value.i32 = py_arg.cast<int32_t>();
      break;
    }
    case AbiConstants::ScalarType::kSint8:
    case AbiConstants::ScalarType::kSint16:
    case AbiConstants::ScalarType::kSint32: {
      value.i32 = py_arg.cast<int32_t>();
      break;
    }
    default:
      throw RaisePyError(PyExc_NotImplementedError, "Unsupported scalar type");
  }
  CheckApiStatus(iree_vm_list_push_value(f_args.raw_ptr(), &value),
                 "Could not pack scalar argument");
}

py::object UnpackScalar(const RawSignatureParser::Description& desc,
                        const iree_vm_variant_t& f_result) {
  switch (desc.scalar.type) {
    case AbiConstants::ScalarType::kUint8:
    case AbiConstants::ScalarType::kUint16:
    case AbiConstants::ScalarType::kUint32: {
      return py::int_(static_cast<uint32_t>(f_result.i32));
    }
    case AbiConstants::ScalarType::kSint8:
    case AbiConstants::ScalarType::kSint16:
    case AbiConstants::ScalarType::kSint32: {
      return py::int_(f_result.i32);
    }
    default:
      throw RaisePyError(PyExc_NotImplementedError, "Unsupported scalar type");
  }
}

}  // namespace

//------------------------------------------------------------------------------
// FunctionAbi
//------------------------------------------------------------------------------

std::string FunctionAbi::DebugString() const {
  RawSignatureParser p;
  auto s = p.FunctionSignatureToString(raw_config_.signature);
  if (!s) {
    return "<FunctionAbi NO_DEBUG_INFO>";
  }
  auto result = absl::StrCat("<FunctionAbi ", *s);
  if (sip_signature_) {
    absl::StrAppend(&result, " SIP:'", *sip_signature_, "'");
  }
  absl::StrAppend(&result, ">");
  return result;
}

std::unique_ptr<FunctionAbi> FunctionAbi::Create(
    HalDevice& device, std::shared_ptr<HostTypeFactory> host_type_factory,
    AttributeLookup lookup) {
  auto abi =
      absl::make_unique<FunctionAbi>(device, std::move(host_type_factory));

  // Fetch key attributes for the raw ABI.
  auto raw_version = lookup("fv");
  auto raw_fsig_str = lookup("f");

  // Validation.
  if (!raw_fsig_str) {
    throw RaiseValueError("No raw abi reflection metadata for function");
  }
  if (!raw_version || *raw_version != "1") {
    throw RaiseValueError("Unsupported raw function ABI version");
  }

  // Parse signature.
  abi->raw_config().signature = std::string(*raw_fsig_str);
  RawSignatureParser raw_parser;
  raw_parser.VisitInputs(*raw_fsig_str,
                         [&abi](const RawSignatureParser::Description& d) {
                           abi->raw_config().inputs.push_back(d);
                         });
  raw_parser.VisitResults(*raw_fsig_str,
                          [&abi](const RawSignatureParser::Description& d) {
                            abi->raw_config().results.push_back(d);
                          });
  if (raw_parser.GetError()) {
    auto message = absl::StrCat(
        "Error parsing raw ABI signature: ", *raw_parser.GetError(), " ('",
        *raw_fsig_str, "')");
    throw RaiseValueError(message.c_str());
  }

  auto reported_abi = lookup("abi");
  auto sip_signature = lookup("sip");
  if (reported_abi && *reported_abi == "sip" && sip_signature) {
    abi->sip_signature_ = std::string(*sip_signature);
  }
  return abi;
}

void FunctionAbi::Pack(py::tuple& py_args, py::dict& py_kwargs,
                       absl::Span<const Description> descs, VmVariantList& args,
                       bool writable) {
  absl::InlinedVector<py::handle, 4> linear_py_args;
  if (!sip_signature_) {
    // There is no python -> linear translation.
    size_t e = py_args.size();
    linear_py_args.resize(e);
    for (size_t i = 0; i < e; ++i) {
      linear_py_args[i] = py_args[i];
    }
  } else {
    // Linearize based on sip signature.
    // Note that we use explicit errors here and do not let exceptions escape
    // since parsing may be happening in a library not compiled for exceptions.
    SipSignatureParser parser;
    SipLinearizeInputsVisitor visitor(parser, py_args, py_kwargs,
                                      linear_py_args);
    parser.VisitInputs(visitor, *sip_signature_);
    auto error = parser.GetError();
    if (error) {
      auto message =
          absl::StrCat("Could not unpack python arguments: ", *error);
      throw RaiseValueError(message.c_str());
    }
  }
  RawPack(descs, absl::MakeSpan(linear_py_args), args, writable);
}

py::object FunctionAbi::Unpack(absl::Span<const Description> descs,
                               VmVariantList& f_results) {
  absl::InlinedVector<py::object, 4> linear_py_results;
  linear_py_results.resize(f_results.size());
  RawUnpack(descs, f_results, absl::MakeSpan(linear_py_results));

  if (!sip_signature_) {
    // Just emulate unpacking to a tuple, which is the standard way of
    // returning multiple results from a python function.
    auto linear_size = linear_py_results.size();
    if (linear_size == 0) {
      return py::none();
    } else if (linear_size == 1) {
      return std::move(linear_py_results.front());
    }
    // Fall back to tuple multi-result form.
    py::tuple py_result_tuple(linear_size);
    for (size_t i = 0; i < linear_size; ++i) {
      py_result_tuple[i] = std::move(linear_py_results[i]);
    }
    return std::move(py_result_tuple);  // Without move, warns of copy.
  }

  // Structured unpack with the sip signature.
  // Note that we use explicit errors here and do not let exceptions escape
  // since parsing may be happening in a library not compiled for exceptions.
  SipSignatureParser parser;
  SipStructureResultsVisitor visitor(parser, linear_py_results);
  parser.VisitResults(visitor, *sip_signature_);
  auto error = parser.GetError();
  if (error) {
    auto message =
        absl::StrCat("Could not create python structured results: ", *error);
    throw RaiseValueError(message.c_str());
  }

  assert(!PyErr_Occurred());
  return visitor.ConsumeResult();
}

void FunctionAbi::RawPack(absl::Span<const Description> descs,
                          absl::Span<py::handle> py_args, VmVariantList& f_args,
                          bool writable) {
  if (descs.size() != py_args.size()) {
    throw RaiseValueError("Mismatched RawPack() input arity");
  }

  for (size_t i = 0, e = descs.size(); i < e; ++i) {
    const Description& desc = descs[i];
    switch (desc.type) {
      case RawSignatureParser::Type::kBuffer:
        PackBuffer(desc, py_args[i], f_args, writable);
        break;
      case RawSignatureParser::Type::kRefObject:
        throw RaisePyError(PyExc_NotImplementedError,
                           "Ref objects not yet supported");
        break;
      case RawSignatureParser::Type::kScalar:
        PackScalar(desc, py_args[i], f_args);
        break;
      default:
        throw RaisePyError(PyExc_NotImplementedError,
                           "Unsupported argument type");
    }
  }
}

void FunctionAbi::RawUnpack(absl::Span<const Description> descs,
                            VmVariantList& f_results,
                            absl::Span<py::object> py_results) {
  if (descs.size() != f_results.size() || descs.size() != py_results.size()) {
    throw RaiseValueError("Mismatched RawUnpack() result arity");
  }
  for (size_t i = 0, e = descs.size(); i < e; ++i) {
    const Description& desc = descs[i];
    iree_vm_variant_t f_result = iree_vm_variant_empty();
    iree_status_t status =
        iree_vm_list_get_variant(f_results.raw_ptr(), i, &f_result);
    if (!iree_status_is_ok(status)) {
      iree_status_ignore(status);
      throw RaiseValueError("Could not get result from list");
    }
    switch (desc.type) {
      case RawSignatureParser::Type::kBuffer: {
        iree_hal_buffer_view_t* buffer_view =
            iree_hal_buffer_view_deref(&f_result.ref);
        if (!buffer_view) {
          throw RaiseValueError(
              "Could not deref result buffer view (wrong type?)");
        }
        iree_hal_buffer* raw_buffer = iree_hal_buffer_view_buffer(buffer_view);
        if (!raw_buffer) {
          throw RaiseValueError("Could not deref result buffer (wrong type?)");
        }
        HalBuffer buffer = HalBuffer::RetainAndCreate(raw_buffer);

        // Extract dims from the buffer view.
        size_t rank = 0;
        absl::InlinedVector<int32_t, 6> dims(6);
        iree_status_t status = iree_hal_buffer_view_shape(
            buffer_view, dims.capacity(), dims.data(), &rank);
        if (iree_status_is_out_of_range(status)) {
          dims.resize(rank);
          status = iree_hal_buffer_view_shape(buffer_view, dims.capacity(),
                                              dims.data(), &rank);
        }
        CheckApiStatus(status, "Error extracting shape");
        dims.resize(rank);

        // Deal with int32_t != int (but require 32bits). Happens on some
        // embedded platforms.
        static_assert(sizeof(dims[0]) == sizeof(int),
                      "expected int to be 32 bits");
        py_results[i] = host_type_factory_->CreateImmediateNdarray(
            desc.buffer.scalar_type,
            absl::MakeConstSpan(reinterpret_cast<int*>(dims.data()),
                                dims.size()),
            std::move(buffer));
        break;
      }
      case RawSignatureParser::Type::kRefObject:
        throw RaisePyError(PyExc_NotImplementedError,
                           "Ref objects not yet supported");
        break;
      case RawSignatureParser::Type::kScalar:
        py_results[i] = UnpackScalar(desc, f_result);
        break;
      default:
        throw RaisePyError(PyExc_NotImplementedError,
                           "Unsupported result type");
    }
  }
}

void FunctionAbi::AllocateResults(absl::Span<const Description> descs,
                                  VmVariantList& f_args,
                                  VmVariantList& f_results) {
  if (f_args.size() != raw_config().inputs.size()) {
    throw RaiseValueError("Mismatched AllocateResults() input arity");
  }

  for (size_t i = 0, e = descs.size(); i < e; ++i) {
    const Description& desc = descs[i];
    iree_device_size_t alloc_size =
        AbiConstants::kScalarTypeSize[static_cast<int>(
            desc.buffer.scalar_type)];
    switch (desc.type) {
      case RawSignatureParser::Type::kBuffer: {
        absl::InlinedVector<int32_t, 5> dims;
        for (auto dim : desc.dims) {
          if (dim < 0) {
            // If there is a dynamic dim, fallback to completely func allocated
            // result. This is the worst case because it will force a
            // pipeline stall.
            // TODO(laurenzo): Invoke shape resolution function if available
            // to allocate full result.
            f_results.AppendNullRef();
          }
          alloc_size *= dim;
          dims.push_back(dim);
        }

        // Static cases are easy.
        iree_hal_buffer_t* raw_buffer;
        CheckApiStatus(iree_hal_allocator_allocate_buffer(
                           device_.allocator(),
                           static_cast<iree_hal_memory_type_t>(
                               IREE_HAL_MEMORY_TYPE_DEVICE_LOCAL |
                               IREE_HAL_MEMORY_TYPE_HOST_VISIBLE),
                           IREE_HAL_BUFFER_USAGE_ALL, alloc_size, &raw_buffer),
                       "Error allocating host visible buffer");
        auto element_type = static_cast<iree_hal_element_type_t>(
            kScalarTypeToHalElementType[static_cast<unsigned>(
                desc.scalar.type)]);
        iree_hal_buffer_view_t* buffer_view;
        CheckApiStatus(
            iree_hal_buffer_view_create(raw_buffer, dims.data(), dims.size(),
                                        element_type, &buffer_view),
            "Error allocating buffer_view");
        iree_hal_buffer_release(raw_buffer);
        iree_vm_ref_t buffer_view_ref =
            iree_hal_buffer_view_move_ref(buffer_view);
        CheckApiStatus(
            iree_vm_list_push_ref_move(f_results.raw_ptr(), &buffer_view_ref),
            "Error moving buffer");
        break;
      }
      case RawSignatureParser::Type::kRefObject:
        throw RaisePyError(PyExc_NotImplementedError,
                           "Ref objects not yet supported");
        break;
      case RawSignatureParser::Type::kScalar:
        break;
      default:
        throw RaisePyError(PyExc_NotImplementedError,
                           "Unsupported allocation argument type");
    }
  }
}

void FunctionAbi::PackBuffer(const RawSignatureParser::Description& desc,
                             py::handle py_arg, VmVariantList& f_args,
                             bool writable) {
  // Request a view of the buffer (use the raw python C API to avoid some
  // allocation and copying at the pybind level).
  Py_buffer py_view;
  // Note that only C-Contiguous ND-arrays are presently supported, so
  // only request that via PyBUF_ND. Long term, we should consult an
  // "oracle" in the runtime to determine the precise required format and
  // set flags accordingly (and fallback/copy on failure).
  int flags = PyBUF_FORMAT | PyBUF_ND;
  if (writable) {
    flags |= PyBUF_WRITABLE;
  }

  // Acquire the backing buffer and setup RAII release.
  if (PyObject_GetBuffer(py_arg.ptr(), &py_view, flags) != 0) {
    // The GetBuffer call is required to set an appropriate error.
    throw py::error_already_set();
  }
  PyBufferReleaser py_view_releaser(py_view);

  // Whether the py object needs to be retained with the argument.
  // Should be set to true if directly mapping, false if copied.
  bool depends_on_pyobject = false;

  // Verify compatibility.
  absl::InlinedVector<int, 2> dynamic_dims;
  MapBufferAttrs(py_view, desc, dynamic_dims);

  // Allocate a HalBuffer.
  // This is hard-coded to C-contiguous right now.
  // TODO(laurenzo): Expand to other layouts as needed.
  // TODO(laurenzo): Wrap and retain original buffer (depends_on_pyobject=true).
  iree_hal_buffer_t* raw_buffer;
  CheckApiStatus(iree_hal_allocator_allocate_buffer(
                     device_.allocator(),
                     static_cast<iree_hal_memory_type_t>(
                         IREE_HAL_MEMORY_TYPE_HOST_LOCAL |
                         IREE_HAL_MEMORY_TYPE_DEVICE_VISIBLE),
                     IREE_HAL_BUFFER_USAGE_ALL, py_view.len, &raw_buffer),
                 "Failed to allocate device visible buffer");
  CheckApiStatus(
      iree_hal_buffer_write_data(raw_buffer, 0, py_view.buf, py_view.len),
      "Error writing to input buffer");

  // Only capture the reference to the exporting object (incrementing it)
  // once guaranteed successful.
  if (depends_on_pyobject) {
    // Note for future implementation: there needs to be a place to stash
    // references to be kept alive which back a buffer. This is likely an
    // additional bag of refs returned from this function, which can then
    // be attached to an invocation.
    throw RaisePyError(PyExc_NotImplementedError,
                       "Dependent buffer arguments not implemented");
  }

  // Create the buffer_view. (note that numpy shape is ssize_t)
  auto element_type = static_cast<iree_hal_element_type_t>(
      kScalarTypeToHalElementType[static_cast<unsigned>(desc.scalar.type)]);
  absl::InlinedVector<int, 5> dims(py_view.ndim);
  std::copy(py_view.shape, py_view.shape + py_view.ndim, dims.begin());
  iree_hal_buffer_view_t* buffer_view;
  CheckApiStatus(
      iree_hal_buffer_view_create(raw_buffer, dims.data(), dims.size(),
                                  element_type, &buffer_view),
      "Error allocating buffer_view");
  iree_hal_buffer_release(raw_buffer);
  iree_vm_ref_t buffer_view_ref = iree_hal_buffer_view_move_ref(buffer_view);
  CheckApiStatus(iree_vm_list_push_ref_move(f_args.raw_ptr(), &buffer_view_ref),
                 "Error moving buffer view");
}

std::vector<std::string> SerializeVmVariantList(VmVariantList& vm_list) {
  size_t size = vm_list.size();
  std::vector<std::string> results;
  results.reserve(size);
  for (iree_host_size_t i = 0; i < size; ++i) {
    iree_vm_variant_t variant = iree_vm_variant_empty();
    iree_status_t status =
        iree_vm_list_get_variant(vm_list.raw_ptr(), i, &variant);
    CheckApiStatus(status, "Failed to get vm variant from list");

    if (iree_vm_variant_is_value(variant)) {
      results.push_back("i32=" + std::to_string(variant.i32));
    } else if (iree_vm_variant_is_ref(variant) &&
               iree_hal_buffer_view_isa(&variant.ref)) {
      auto buffer_view = iree_hal_buffer_view_deref(&variant.ref);

      std::string result_str(4096, '\0');
      iree_status_t status;
      do {
        iree_host_size_t actual_length = 0;
        iree_host_size_t max_element_count =
            std::numeric_limits<iree_host_size_t>::max();
        status = iree_hal_buffer_view_format(buffer_view, max_element_count,
                                             result_str.size() + 1,
                                             &result_str[0], &actual_length);
        result_str.resize(actual_length);
      } while (iree_status_is_out_of_range(status));
      CheckApiStatus(status,
                     "Failed to create a string representation of the inputs");

      results.push_back(result_str);
    } else {
      RaiseValueError(
          "Expected vm_list's elements to be scalars or buffer views.");
    }
  }
  return results;
}

void SetupFunctionAbiBindings(pybind11::module m) {
  py::class_<FunctionAbi, std::unique_ptr<FunctionAbi>>(m, "FunctionAbi")
      .def(py::init(&PyCreateAbi))
      .def("__repr__", &FunctionAbi::DebugString)
      .def_property_readonly("raw_input_arity", &FunctionAbi::raw_input_arity)
      .def_property_readonly("raw_result_arity", &FunctionAbi::raw_result_arity)
      .def("pack_inputs",
           [](FunctionAbi* self, py::args py_args, py::kwargs py_kwargs) {
             VmVariantList f_args = VmVariantList::Create(py_args.size());
             self->Pack(py_args, py_kwargs,
                        absl::MakeConstSpan(self->raw_config().inputs), f_args,
                        false /* writable */);
             return f_args;
           })
      .def("serialize_vm_list",
           [](FunctionAbi* self, VmVariantList& vm_list) {
             return SerializeVmVariantList(vm_list);
           })
      .def("allocate_results", &PyAllocateResults, py::arg("f_results"),
           py::arg("static_alloc") = true)
      .def("unpack_results", [](FunctionAbi* self, VmVariantList& f_results) {
        return self->Unpack(absl::MakeConstSpan(self->raw_config().results),
                            f_results);
      });
}

}  // namespace python
}  // namespace iree
