// Copyright 2020 The IREE Authors
//
// Licensed 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 <array>
#include <cstdio>
#include <cstdlib>
#include <iterator>
#include <string>
#include <utility>
#include <vector>

#include "iree/base/api.h"
#include "iree/base/internal/flags.h"
#include "iree/base/tracing.h"
#include "iree/hal/api.h"
#include "iree/modules/hal/types.h"
#include "iree/tooling/comparison.h"
#include "iree/tooling/context_util.h"
#include "iree/tooling/device_util.h"
#include "iree/tooling/vm_util.h"
#include "iree/vm/api.h"

IREE_FLAG(string, entry_function, "",
          "Name of a function contained in the module specified by module_file "
          "to run.");

IREE_FLAG(int32_t, print_max_element_count, 1024,
          "Prints up to the maximum number of elements of output tensors, "
          "eliding the remainder.");

IREE_FLAG(bool, print_statistics, false,
          "Prints runtime statistics to stderr on exit.");

IREE_FLAG_LIST(
    string, function_input,
    "An input (a) value or (b) buffer of the format:\n"
    "  (a) scalar value\n"
    "     value\n"
    "     e.g.: --function_input=\"3.14\"\n"
    "  (b) buffer:\n"
    "     [shape]xtype=[value]\n"
    "     e.g.: --function_input=\"2x2xi32=1 2 3 4\"\n"
    "Optionally, brackets may be used to separate the element values:\n"
    "  2x2xi32=[[1 2][3 4]]\n"
    "Raw binary files can be read to provide buffer contents:\n"
    "  2x2xi32=@some/file.bin\n"
    "numpy npy files (from numpy.save) can be read to provide 1+ values:\n"
    "  @some.npy\n"
    "Each occurrence of the flag indicates an input in the order they were\n"
    "specified on the command line.");

IREE_FLAG_LIST(string, expected_output,
               "An expected function output following the same format as "
               "--function_input. When present the results of the "
               "invocation will be compared against these values and the "
               "tool will return non-zero if any differ. If the value of a "
               "particular output is not of interest provide `(ignored)`.");

namespace iree {
namespace {

iree_status_t Run(int* out_exit_code) {
  IREE_TRACE_SCOPE0("iree-run-module");

  iree_allocator_t host_allocator = iree_allocator_system();
  vm::ref<iree_vm_instance_t> instance;
  IREE_RETURN_IF_ERROR(iree_tooling_create_instance(host_allocator, &instance),
                       "creating instance");

  vm::ref<iree_vm_module_t> main_module;
  IREE_RETURN_IF_ERROR(iree_tooling_load_module_from_flags(
      instance.get(), host_allocator, &main_module));

  vm::ref<iree_vm_context_t> context;
  vm::ref<iree_hal_device_t> device;
  vm::ref<iree_hal_allocator_t> device_allocator;
  IREE_RETURN_IF_ERROR(iree_tooling_create_context_from_flags(
      instance.get(), /*user_module_count=*/1, /*user_modules=*/&main_module,
      /*default_device_uri=*/iree_string_view_empty(), host_allocator, &context,
      &device, &device_allocator));

  std::string function_name = std::string(FLAG_entry_function);
  iree_vm_function_t function;
  if (function_name.empty()) {
    return iree_make_status(IREE_STATUS_INVALID_ARGUMENT,
                            "no --entry_function= specified");
  } else {
    IREE_RETURN_IF_ERROR(
        iree_vm_module_lookup_function_by_name(
            main_module.get(), IREE_VM_FUNCTION_LINKAGE_EXPORT,
            iree_string_view_t{function_name.data(), function_name.size()},
            &function),
        "looking up function '%s'", function_name.c_str());
  }

  IREE_RETURN_IF_ERROR(iree_hal_begin_profiling_from_flags(device.get()));

  vm::ref<iree_vm_list_t> inputs;
  IREE_RETURN_IF_ERROR(iree_tooling_parse_to_variant_list(
      device_allocator.get(), FLAG_function_input_list().values,
      FLAG_function_input_list().count, host_allocator, &inputs));

  // If the function is async add fences so we can invoke it synchronously.
  vm::ref<iree_hal_fence_t> finish_fence;
  IREE_RETURN_IF_ERROR(iree_tooling_append_async_fence_inputs(
      inputs.get(), &function, device.get(), /*wait_fence=*/NULL,
      &finish_fence));

  vm::ref<iree_vm_list_t> outputs;
  IREE_RETURN_IF_ERROR(iree_vm_list_create(/*element_type=*/nullptr, 16,
                                           host_allocator, &outputs));

  printf("EXEC @%s\n", function_name.c_str());
  IREE_RETURN_IF_ERROR(
      iree_vm_invoke(context.get(), function, IREE_VM_INVOCATION_FLAG_NONE,
                     /*policy=*/nullptr, inputs.get(), outputs.get(),
                     host_allocator),
      "invoking function '%s'", function_name.c_str());

  // If the function is async we need to wait for it to complete.
  if (finish_fence) {
    IREE_RETURN_IF_ERROR(
        iree_hal_fence_wait(finish_fence.get(), iree_infinite_timeout()));
  }

  IREE_RETURN_IF_ERROR(iree_hal_end_profiling_from_flags(device.get()));

  if (FLAG_expected_output_list().count == 0) {
    IREE_RETURN_IF_ERROR(
        iree_tooling_variant_list_fprint(
            outputs.get(), (size_t)FLAG_print_max_element_count, stdout),
        "printing results");
  } else {
    // Parse expected list into host-local memory that we can easily access.
    // Note that we return a status here as this can fail on user inputs.
    vm::ref<iree_hal_allocator_t> heap_allocator;
    IREE_RETURN_IF_ERROR(iree_hal_allocator_create_heap(
        IREE_SV("heap"), host_allocator, host_allocator, &heap_allocator));
    vm::ref<iree_vm_list_t> expected_list;
    IREE_RETURN_IF_ERROR(iree_tooling_parse_to_variant_list(
        heap_allocator.get(), FLAG_expected_output_list().values,
        FLAG_expected_output_list().count, host_allocator, &expected_list));

    // Compare expected vs actual lists and output diffs.
    bool did_match = iree_tooling_compare_variant_lists(
        expected_list.get(), outputs.get(), host_allocator, stdout);
    if (did_match) {
      printf("[SUCCESS] all function outputs matched their expected values.\n");
    }
    *out_exit_code = did_match ? EXIT_SUCCESS : EXIT_FAILURE;
  }

  // Release resources before gathering statistics.
  inputs.reset();
  outputs.reset();
  main_module.reset();
  context.reset();

  if (device_allocator && FLAG_print_statistics) {
    IREE_IGNORE_ERROR(
        iree_hal_allocator_statistics_fprint(stderr, device_allocator.get()));
  }

  device_allocator.reset();
  device.reset();
  instance.reset();
  return iree_ok_status();
}

}  // namespace

extern "C" int main(int argc, char** argv) {
  iree_flags_parse_checked(IREE_FLAGS_PARSE_MODE_DEFAULT, &argc, &argv);
  if (argc > 1) {
    // Avoid iree-run-module spinning endlessly on stdin if the user uses single
    // dashes for flags.
    printf(
        "[ERROR] unexpected positional argument (expected none)."
        " Did you use pass a flag with a single dash ('-')?"
        " Use '--' instead.\n");
    return 1;
  }

  int exit_code = EXIT_SUCCESS;
  iree_status_t status = Run(&exit_code);
  if (!iree_status_is_ok(status)) {
    iree_status_fprint(stderr, status);
    iree_status_free(status);
    return EXIT_FAILURE;
  }

  return exit_code;
}

}  // namespace iree
