// Copyright 2021 The Tint Authors.
//
// 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 "fuzzers/tint_common_fuzzer.h"

#include <cstring>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#if TINT_BUILD_SPV_READER
#include "spirv-tools/libspirv.hpp"
#endif  // TINT_BUILD_SPV_READER

#include "src/ast/module.h"
#include "src/diagnostic/formatter.h"
#include "src/program.h"

namespace tint {
namespace fuzzers {

namespace {

[[noreturn]] void FatalError(const tint::diag::List& diags,
                             const std::string& msg = "") {
  auto printer = tint::diag::Printer::create(stderr, true);
  if (!msg.empty()) {
    printer->write(msg + "\n", {diag::Color::kRed, true});
  }
  tint::diag::Formatter().format(diags, printer.get());
  __builtin_trap();
}

[[noreturn]] void TintInternalCompilerErrorReporter(
    const tint::diag::List& diagnostics) {
  FatalError(diagnostics);
}

transform::VertexAttributeDescriptor ExtractVertexAttributeDescriptor(
    Reader* r) {
  transform::VertexAttributeDescriptor desc{};
  desc.format = r->enum_class<transform::VertexFormat>(
      static_cast<uint8_t>(transform::VertexFormat::kLastEntry) + 1);
  desc.offset = r->read<uint32_t>();
  desc.shader_location = r->read<uint32_t>();
  return desc;
}

transform::VertexBufferLayoutDescriptor ExtractVertexBufferLayoutDescriptor(
    Reader* r) {
  transform::VertexBufferLayoutDescriptor desc;
  desc.array_stride = r->read<uint32_t>();
  desc.step_mode = r->enum_class<transform::InputStepMode>(
      static_cast<uint8_t>(transform::InputStepMode::kLastEntry) + 1);
  desc.attributes = r->vector(ExtractVertexAttributeDescriptor);
  return desc;
}

bool SPIRVToolsValidationCheck(const tint::Program& program,
                               const std::vector<uint32_t>& spirv) {
  spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1);
  const tint::diag::List& diags = program.Diagnostics();
  tools.SetMessageConsumer([diags](spv_message_level_t, const char*,
                                   const spv_position_t& pos, const char* msg) {
    std::stringstream out;
    out << "Unexpected spirv-val error:\n"
        << (pos.line + 1) << ":" << (pos.column + 1) << ": " << msg
        << std::endl;

    auto printer = tint::diag::Printer::create(stderr, true);
    printer->write(out.str(), {diag::Color::kYellow, false});
    tint::diag::Formatter().format(diags, printer.get());
  });

  return tools.Validate(spirv.data(), spirv.size(),
                        spvtools::ValidatorOptions());
}

}  // namespace

Reader::Reader(const uint8_t* data, size_t size) : data_(data), size_(size) {}

std::string Reader::string() {
  auto count = read<uint8_t>();
  if (failed_ || size_ < count) {
    mark_failed();
    return "";
  }
  std::string out(data_, data_ + count);
  data_ += count;
  size_ -= count;
  return out;
}

void Reader::mark_failed() {
  size_ = 0;
  failed_ = true;
}

void Reader::read(void* out, size_t n) {
  if (n > size_) {
    mark_failed();
    return;
  }
  memcpy(out, data_, n);
  data_ += n;
  size_ -= n;
}

void ExtractBindingRemapperInputs(Reader* r, tint::transform::DataMap* inputs) {
  struct Config {
    uint8_t old_group;
    uint8_t old_binding;
    uint8_t new_group;
    uint8_t new_binding;
    ast::Access new_access;
  };

  std::vector<Config> configs = r->vector<Config>();
  transform::BindingRemapper::BindingPoints binding_points;
  transform::BindingRemapper::AccessControls accesses;
  for (const auto& config : configs) {
    binding_points[{config.old_binding, config.old_group}] = {
        config.new_binding, config.new_group};
    accesses[{config.old_binding, config.old_group}] = config.new_access;
  }

  inputs->Add<transform::BindingRemapper::Remappings>(binding_points, accesses);
}

void ExtractFirstIndexOffsetInputs(Reader* r,
                                   tint::transform::DataMap* inputs) {
  struct Config {
    uint32_t group;
    uint32_t binding;
  };

  Config config = r->read<Config>();
  inputs->Add<tint::transform::FirstIndexOffset::BindingPoint>(config.binding,
                                                               config.group);
}

void ExtractSingleEntryPointInputs(Reader* r,
                                   tint::transform::DataMap* inputs) {
  std::string input = r->string();
  transform::SingleEntryPoint::Config cfg(input);
  inputs->Add<transform::SingleEntryPoint::Config>(cfg);
}

void ExtractVertexPullingInputs(Reader* r, tint::transform::DataMap* inputs) {
  transform::VertexPulling::Config cfg;
  cfg.entry_point_name = r->string();
  cfg.vertex_state = r->vector(ExtractVertexBufferLayoutDescriptor);
  cfg.pulling_group = r->read<uint32_t>();
  inputs->Add<transform::VertexPulling::Config>(cfg);
}

void ExtractSpirvOptions(Reader* r, writer::spirv::Options* options) {
  *options = r->read<writer::spirv::Options>();
}

void ExtractWgslOptions(Reader* r, writer::wgsl::Options* options) {
  *options = r->read<writer::wgsl::Options>();
}

void ExtractHlslOptions(Reader* r, writer::hlsl::Options* options) {
  *options = r->read<writer::hlsl::Options>();
}

void ExtractMslOptions(Reader* r, writer::msl::Options* options) {
  *options = r->read<writer::msl::Options>();
}

CommonFuzzer::CommonFuzzer(InputFormat input, OutputFormat output)
    : input_(input),
      output_(output),
      transform_manager_(nullptr),
      inspector_enabled_(false) {}

CommonFuzzer::~CommonFuzzer() = default;

int CommonFuzzer::Run(const uint8_t* data, size_t size) {
  tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter);

  Program program;

#if TINT_BUILD_WGSL_READER
  std::unique_ptr<Source::File> file;
#endif  // TINT_BUILD_WGSL_READER

#if TINT_BUILD_SPV_READER
  std::vector<uint32_t> spirv_input(size / sizeof(uint32_t));

#endif  // TINT_BUILD_SPV_READER

  switch (input_) {
#if TINT_BUILD_WGSL_READER
    case InputFormat::kWGSL: {
      std::string str(reinterpret_cast<const char*>(data), size);
      file = std::make_unique<Source::File>("test.wgsl", str);
      program = reader::wgsl::Parse(file.get());
      break;
    }
#endif  // TINT_BUILD_WGSL_READER
#if TINT_BUILD_SPV_READER
    case InputFormat::kSpv: {
      // `spirv_input` has been initialized with the capacity to store `size /
      // sizeof(uint32_t)` uint32_t values. If `size` is not a multiple of
      // sizeof(uint32_t) then not all of `data` can be copied into
      // `spirv_input`, and any trailing bytes are discarded.
      std::memcpy(spirv_input.data(), data,
                  spirv_input.size() * sizeof(uint32_t));
      if (spirv_input.empty()) {
        return 0;
      }
      program = reader::spirv::Parse(spirv_input);
      break;
    }
#endif  // TINT_BUILD_SPV_READER
    default:
      return 0;
  }

  if (output_ == OutputFormat::kNone) {
    return 0;
  }

  if (!program.IsValid()) {
    diagnostics_ = program.Diagnostics();
    return 0;
  }

#if TINT_BUILD_SPV_READER
  if (input_ == InputFormat::kSpv &&
      !SPIRVToolsValidationCheck(program, spirv_input)) {
    FatalError(program.Diagnostics(),
               "Fuzzing detected invalid input spirv not being caught by Tint");
  }
#endif  // TINT_BUILD_SPV_READER

  if (inspector_enabled_) {
    inspector::Inspector inspector(&program);

    auto entry_points = inspector.GetEntryPoints();
    if (inspector.has_error()) {
      diagnostics_.add_error(tint::diag::System::Inspector, inspector.error());
      return 0;
    }

    for (auto& ep : entry_points) {
      auto remapped_name = inspector.GetRemappedNameForEntryPoint(ep.name);
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }

      auto constant_ids = inspector.GetConstantIDs();
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }

      auto uniform_bindings =
          inspector.GetUniformBufferResourceBindings(ep.name);
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }

      auto storage_bindings =
          inspector.GetStorageBufferResourceBindings(ep.name);
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }

      auto readonly_bindings =
          inspector.GetReadOnlyStorageBufferResourceBindings(ep.name);
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }

      auto sampler_bindings = inspector.GetSamplerResourceBindings(ep.name);
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }

      auto comparison_sampler_bindings =
          inspector.GetComparisonSamplerResourceBindings(ep.name);
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }

      auto sampled_texture_bindings =
          inspector.GetSampledTextureResourceBindings(ep.name);
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }

      auto multisampled_texture_bindings =
          inspector.GetMultisampledTextureResourceBindings(ep.name);
      if (inspector.has_error()) {
        diagnostics_.add_error(tint::diag::System::Inspector,
                               inspector.error());
        return 0;
      }
    }
  }

  if (transform_manager_) {
    auto out = transform_manager_->Run(&program, transform_inputs_);
    if (!out.program.IsValid()) {
      // Transforms can produce error messages for bad input.
      // Catch ICEs and errors from non transform systems.
      for (const auto& diag : out.program.Diagnostics()) {
        if (diag.severity > diag::Severity::Error ||
            diag.system != diag::System::Transform) {
          FatalError(out.program.Diagnostics(),
                     "Fuzzing detected valid input program being transformed "
                     "into an invalid output program");
        }
      }
    }

    program = std::move(out.program);
  }

  switch (output_) {
    case OutputFormat::kWGSL: {
#if TINT_BUILD_WGSL_WRITER
      auto result = writer::wgsl::Generate(&program, options_wgsl_);
      generated_wgsl_ = std::move(result.wgsl);
      if (!result.success) {
        FatalError(program.Diagnostics(),
                   "WGSL writer failed: " + result.error);
      }
#endif  // TINT_BUILD_WGSL_WRITER
      break;
    }
    case OutputFormat::kSpv: {
#if TINT_BUILD_SPV_WRITER
      auto result = writer::spirv::Generate(&program, options_spirv_);
      generated_spirv_ = std::move(result.spirv);
      if (!result.success) {
        FatalError(program.Diagnostics(),
                   "SPIR-V writer failed: " + result.error);
      }
      if (!SPIRVToolsValidationCheck(program, generated_spirv_)) {
        FatalError(program.Diagnostics(),
                   "Fuzzing detected invalid spirv being emitted by Tint");
      }

#endif  // TINT_BUILD_SPV_WRITER
      break;
    }
    case OutputFormat::kHLSL: {
#if TINT_BUILD_HLSL_WRITER
      auto result = writer::hlsl::Generate(&program, options_hlsl_);
      generated_hlsl_ = std::move(result.hlsl);
      if (!result.success) {
        FatalError(program.Diagnostics(),
                   "HLSL writer failed: " + result.error);
      }
#endif  // TINT_BUILD_HLSL_WRITER
      break;
    }
    case OutputFormat::kMSL: {
#if TINT_BUILD_MSL_WRITER
      auto result = writer::msl::Generate(&program, options_msl_);
      generated_msl_ = std::move(result.msl);
      if (!result.success) {
        FatalError(program.Diagnostics(), "MSL writer failed: " + result.error);
      }
#endif  // TINT_BUILD_MSL_WRITER
      break;
    }
    case OutputFormat::kNone:
      break;
  }

  return 0;
}

}  // namespace fuzzers
}  // namespace tint
