// Copyright (c) 2018 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
//
//     http://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 <cassert>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <sstream>

#include "source/opt/build_module.h"
#include "source/opt/ir_context.h"
#include "source/opt/log.h"
#include "source/reduce/reducer.h"
#include "source/spirv_reducer_options.h"
#include "source/util/string_utils.h"
#include "tools/io.h"
#include "tools/util/cli_consumer.h"

namespace {

// Execute a command using the shell.
// Returns true if and only if the command's exit status was 0.
bool ExecuteCommand(const std::string& command) {
  errno = 0;
  int status = std::system(command.c_str());
  assert(errno == 0 && "failed to execute command");
  // The result returned by 'system' is implementation-defined, but is
  // usually the case that the returned value is 0 when the command's exit
  // code was 0.  We are assuming that here, and that's all we depend on.
  return status == 0;
}

// Status and actions to perform after parsing command-line arguments.
enum ReduceActions { REDUCE_CONTINUE, REDUCE_STOP };

struct ReduceStatus {
  ReduceActions action;
  int code;
};

void PrintUsage(const char* program) {
  // NOTE: Please maintain flags in lexicographical order.
  printf(
      R"(%s - Reduce a SPIR-V binary file with respect to a user-provided
interestingness test.

USAGE: %s [options] <input.spv> -o <output.spv> -- <interestingness_test> [args...]

The SPIR-V binary is read from <input.spv>. The reduced SPIR-V binary is
written to <output.spv>.

Whether a binary is interesting is determined by <interestingness_test>, which
should be the path to a script. The "--" characters are optional but denote
that all arguments that follow are positional arguments and thus will be
forwarded to the interestingness test, and not parsed by %s.

 * The script must be executable.

 * The script should take the path to a SPIR-V binary file (.spv) as an
   argument, and exit with code 0 if and only if the binary file is
   interesting.  The binary will be passed to the script as an argument after
   any other provided arguments [args...].

 * Example: an interestingness test for reducing a SPIR-V binary file that
   causes tool "foo" to exit with error code 1 and print "Fatal error: bar" to
   standard error should:
     - invoke "foo" on the binary passed as the script argument;
     - capture the return code and standard error from "bar";
     - exit with code 0 if and only if the return code of "foo" was 1 and the
       standard error from "bar" contained "Fatal error: bar".

 * The reducer does not place a time limit on how long the interestingness test
   takes to run, so it is advisable to use per-command timeouts inside the
   script when invoking SPIR-V-processing tools (such as "foo" in the above
   example).

NOTE: The reducer is a work in progress.

Options (in lexicographical order):

  --fail-on-validation-error
               Stop reduction with an error if any reduction step produces a
               SPIR-V module that fails to validate.
  -h, --help
               Print this help.
  --step-limit=
               32-bit unsigned integer specifying maximum number of steps the
               reducer will take before giving up.
  --target-function=
               32-bit unsigned integer specifying the id of a function in the
               input module.  The reducer will restrict attention to this
               function, and will not make changes to other functions or to
               instructions outside of functions, except that some global
               instructions may be added in support of reducing the target
               function.  If 0 is specified (the default) then all functions are
               reduced.
  --temp-file-prefix=
               Specifies a temporary file prefix that will be used to output
               temporary shader files during reduction.  A number and .spv
               extension will be added.  The default is "temp_", which will
               cause files like "temp_0001.spv" to be output to the current
               directory.
  --version
               Display reducer version information.

Supported validator options are as follows. See `spirv-val --help` for details.
  --before-hlsl-legalization
  --relax-block-layout
  --relax-logical-pointer
  --relax-struct-store
  --scalar-block-layout
  --skip-block-layout
)",
      program, program, program);
}

// Message consumer for this tool.  Used to emit diagnostics during
// initialization and setup. Note that |source| and |position| are irrelevant
// here because we are still not processing a SPIR-V input file.
void ReduceDiagnostic(spv_message_level_t level, const char* /*source*/,
                      const spv_position_t& /*position*/, const char* message) {
  if (level == SPV_MSG_ERROR) {
    fprintf(stderr, "error: ");
  }
  fprintf(stderr, "%s\n", message);
}

ReduceStatus ParseFlags(int argc, const char** argv,
                        std::string* in_binary_file,
                        std::string* out_binary_file,
                        std::vector<std::string>* interestingness_test,
                        std::string* temp_file_prefix,
                        spvtools::ReducerOptions* reducer_options,
                        spvtools::ValidatorOptions* validator_options) {
  uint32_t positional_arg_index = 0;
  bool only_positional_arguments_remain = false;

  for (int argi = 1; argi < argc; ++argi) {
    const char* cur_arg = argv[argi];
    if ('-' == cur_arg[0] && !only_positional_arguments_remain) {
      if (0 == strcmp(cur_arg, "--version")) {
        spvtools::Logf(ReduceDiagnostic, SPV_MSG_INFO, nullptr, {}, "%s\n",
                       spvSoftwareVersionDetailsString());
        return {REDUCE_STOP, 0};
      } else if (0 == strcmp(cur_arg, "--help") || 0 == strcmp(cur_arg, "-h")) {
        PrintUsage(argv[0]);
        return {REDUCE_STOP, 0};
      } else if (0 == strcmp(cur_arg, "-o")) {
        if (out_binary_file->empty() && argi + 1 < argc) {
          *out_binary_file = std::string(argv[++argi]);
        } else {
          PrintUsage(argv[0]);
          return {REDUCE_STOP, 1};
        }
      } else if (0 == strncmp(cur_arg,
                              "--step-limit=", sizeof("--step-limit=") - 1)) {
        const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
        char* end = nullptr;
        errno = 0;
        const auto step_limit =
            static_cast<uint32_t>(strtol(split_flag.second.c_str(), &end, 10));
        assert(end != split_flag.second.c_str() && errno == 0);
        reducer_options->set_step_limit(step_limit);
      } else if (0 == strncmp(cur_arg, "--target-function=",
                              sizeof("--target-function=") - 1)) {
        const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
        char* end = nullptr;
        errno = 0;
        const auto target_function =
            static_cast<uint32_t>(strtol(split_flag.second.c_str(), &end, 10));
        assert(end != split_flag.second.c_str() && errno == 0);
        reducer_options->set_target_function(target_function);
      } else if (0 == strcmp(cur_arg, "--fail-on-validation-error")) {
        reducer_options->set_fail_on_validation_error(true);
      } else if (0 == strcmp(cur_arg, "--before-hlsl-legalization")) {
        validator_options->SetBeforeHlslLegalization(true);
      } else if (0 == strcmp(cur_arg, "--relax-logical-pointer")) {
        validator_options->SetRelaxLogicalPointer(true);
      } else if (0 == strcmp(cur_arg, "--relax-block-layout")) {
        validator_options->SetRelaxBlockLayout(true);
      } else if (0 == strcmp(cur_arg, "--scalar-block-layout")) {
        validator_options->SetScalarBlockLayout(true);
      } else if (0 == strcmp(cur_arg, "--skip-block-layout")) {
        validator_options->SetSkipBlockLayout(true);
      } else if (0 == strcmp(cur_arg, "--relax-struct-store")) {
        validator_options->SetRelaxStructStore(true);
      } else if (0 == strncmp(cur_arg, "--temp-file-prefix=",
                              sizeof("--temp-file-prefix=") - 1)) {
        const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
        *temp_file_prefix = std::string(split_flag.second);
      } else if (0 == strcmp(cur_arg, "--")) {
        only_positional_arguments_remain = true;
      } else {
        std::stringstream ss;
        ss << "Unrecognized argument: " << cur_arg << std::endl;
        spvtools::Error(ReduceDiagnostic, nullptr, {}, ss.str().c_str());
        PrintUsage(argv[0]);
        return {REDUCE_STOP, 1};
      }
    } else if (positional_arg_index == 0) {
      // Binary input file name
      assert(in_binary_file->empty());
      *in_binary_file = std::string(cur_arg);
      positional_arg_index++;
    } else {
      interestingness_test->push_back(std::string(cur_arg));
    }
  }

  if (in_binary_file->empty()) {
    spvtools::Error(ReduceDiagnostic, nullptr, {}, "No input file specified");
    return {REDUCE_STOP, 1};
  }

  if (out_binary_file->empty()) {
    spvtools::Error(ReduceDiagnostic, nullptr, {}, "-o required");
    return {REDUCE_STOP, 1};
  }

  if (interestingness_test->empty()) {
    spvtools::Error(ReduceDiagnostic, nullptr, {},
                    "No interestingness test specified");
    return {REDUCE_STOP, 1};
  }

  return {REDUCE_CONTINUE, 0};
}

}  // namespace

// Dumps |binary| to file |filename|. Useful for interactive debugging.
void DumpShader(const std::vector<uint32_t>& binary, const char* filename) {
  auto write_file_succeeded =
      WriteFile(filename, "wb", &binary[0], binary.size());
  if (!write_file_succeeded) {
    std::cerr << "Failed to dump shader" << std::endl;
  }
}

// Dumps the SPIRV-V module in |context| to file |filename|. Useful for
// interactive debugging.
void DumpShader(spvtools::opt::IRContext* context, const char* filename) {
  std::vector<uint32_t> binary;
  context->module()->ToBinary(&binary, false);
  DumpShader(binary, filename);
}

const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_6;

int main(int argc, const char** argv) {
  std::string in_binary_file;
  std::string out_binary_file;
  std::vector<std::string> interestingness_test;
  std::string temp_file_prefix = "temp_";

  spv_target_env target_env = kDefaultEnvironment;
  spvtools::ReducerOptions reducer_options;
  spvtools::ValidatorOptions validator_options;

  ReduceStatus status = ParseFlags(
      argc, argv, &in_binary_file, &out_binary_file, &interestingness_test,
      &temp_file_prefix, &reducer_options, &validator_options);

  if (status.action == REDUCE_STOP) {
    return status.code;
  }

  spvtools::reduce::Reducer reducer(target_env);

  std::stringstream joined;
  joined << interestingness_test[0];
  for (size_t i = 1, size = interestingness_test.size(); i < size; ++i) {
    joined << " " << interestingness_test[i];
  }
  std::string interestingness_command_joined = joined.str();

  reducer.SetInterestingnessFunction(
      [interestingness_command_joined, temp_file_prefix](
          std::vector<uint32_t> binary, uint32_t reductions_applied) -> bool {
        std::stringstream ss;
        ss << temp_file_prefix << std::setw(4) << std::setfill('0')
           << reductions_applied << ".spv";
        const auto spv_file = ss.str();
        const std::string command =
            interestingness_command_joined + " " + spv_file;
        auto write_file_succeeded =
            WriteFile(spv_file.c_str(), "wb", &binary[0], binary.size());
        (void)(write_file_succeeded);
        assert(write_file_succeeded);
        return ExecuteCommand(command);
      });

  reducer.AddDefaultReductionPasses();

  reducer.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);

  std::vector<uint32_t> binary_in;
  if (!ReadBinaryFile<uint32_t>(in_binary_file.c_str(), &binary_in)) {
    return 1;
  }

  const uint32_t target_function = (*reducer_options).target_function;
  if (target_function) {
    // A target function was specified; check that it exists.
    std::unique_ptr<spvtools::opt::IRContext> context = spvtools::BuildModule(
        kDefaultEnvironment, spvtools::utils::CLIMessageConsumer,
        binary_in.data(), binary_in.size());
    bool found_target_function = false;
    for (auto& function : *context->module()) {
      if (function.result_id() == target_function) {
        found_target_function = true;
        break;
      }
    }
    if (!found_target_function) {
      std::stringstream strstr;
      strstr << "Target function with id " << target_function
             << " was requested, but not found in the module; stopping.";
      spvtools::utils::CLIMessageConsumer(SPV_MSG_ERROR, nullptr, {},
                                          strstr.str().c_str());
      return 1;
    }
  }

  std::vector<uint32_t> binary_out;
  const auto reduction_status = reducer.Run(std::move(binary_in), &binary_out,
                                            reducer_options, validator_options);

  // Always try to write the output file, even if the reduction failed.
  if (!WriteFile<uint32_t>(out_binary_file.c_str(), "wb", binary_out.data(),
                           binary_out.size())) {
    return 1;
  }

  // These are the only successful statuses.
  switch (reduction_status) {
    case spvtools::reduce::Reducer::ReductionResultStatus::kComplete:
    case spvtools::reduce::Reducer::ReductionResultStatus::kReachedStepLimit:
      return 0;
    default:
      break;
  }

  return 1;
}
