// Copyright 2020 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.

#ifndef SRC_TINT_READER_SPIRV_PARSER_IMPL_TEST_HELPER_H_
#define SRC_TINT_READER_SPIRV_PARSER_IMPL_TEST_HELPER_H_

#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

#if TINT_BUILD_SPV_READER
#include "source/opt/ir_context.h"
#endif

#include "gtest/gtest.h"
#include "src/tint/demangler.h"
#include "src/tint/reader/spirv/fail_stream.h"
#include "src/tint/reader/spirv/function.h"
#include "src/tint/reader/spirv/namer.h"
#include "src/tint/reader/spirv/parser_impl.h"
#include "src/tint/reader/spirv/spirv_tools_helpers_test.h"
#include "src/tint/reader/spirv/usage.h"

namespace tint::reader::spirv {
namespace test {

/// A test class that wraps ParseImpl
class ParserImplWrapperForTest {
 public:
  /// Constructor
  /// @param input the input data to parse
  explicit ParserImplWrapperForTest(const std::vector<uint32_t>& input);
  /// Dumps SPIR-V if the conversion succeeded, then destroys the wrapper.
  ~ParserImplWrapperForTest();

  /// Sets global state to force dumping of the assembly text of succesfully
  /// SPIR-V.
  static void DumpSuccessfullyConvertedSpirv() {
    dump_successfully_converted_spirv_ = true;
  }
  /// Marks the test has having deliberately invalid SPIR-V
  void DeliberatelyInvalidSpirv() { skip_dumping_spirv_ = true; }
  /// Marks the test's SPIR-V as not being suitable for dumping, for a stated
  /// reason.
  void SkipDumpingPending(std::string) { skip_dumping_spirv_ = true; }

  /// @returns a new function emitter for the given function ID.
  /// Assumes ParserImpl::BuildInternalRepresentation has been run and
  /// succeeded.
  /// @param function_id the SPIR-V identifier of the function
  FunctionEmitter function_emitter(uint32_t function_id) {
    auto* spirv_function = impl_.ir_context()->GetFunction(function_id);
    return FunctionEmitter(&impl_, *spirv_function);
  }

  /// Run the parser
  /// @returns true if the parse was successful, false otherwise.
  bool Parse() { return impl_.Parse(); }

  /// @returns the program. The program builder in the parser will be reset
  /// after this.
  Program program() { return impl_.program(); }

  /// @returns the namer object
  Namer& namer() { return impl_.namer(); }

  /// @returns a reference to the internal builder, without building the
  /// program. To be used only for testing.
  ProgramBuilder& builder() { return impl_.builder(); }

  /// @returns the accumulated error string
  const std::string error() { return impl_.error(); }

  /// @return true if failure has not yet occurred
  bool success() { return impl_.success(); }

  /// Logs failure, ands return a failure stream to accumulate diagnostic
  /// messages. By convention, a failure should only be logged along with
  /// a non-empty string diagnostic.
  /// @returns the failure stream
  FailStream& Fail() { return impl_.Fail(); }

  /// @returns a borrowed pointer to the internal representation of the module.
  /// This is null until BuildInternalModule has been called.
  spvtools::opt::IRContext* ir_context() { return impl_.ir_context(); }

  /// Builds the internal representation of the SPIR-V module.
  /// Assumes the module is somewhat well-formed.  Normally you
  /// would want to validate the SPIR-V module before attempting
  /// to build this internal representation. Also computes a topological
  /// ordering of the functions.
  /// This is a no-op if the parser has already failed.
  /// @returns true if the parser is still successful.
  bool BuildInternalModule() { return impl_.BuildInternalModule(); }

  /// Builds an internal representation of the SPIR-V binary,
  /// and parses the module, except functions, into a Tint AST module.
  /// Diagnostics are emitted to the error stream.
  /// @returns true if it was successful.
  bool BuildAndParseInternalModuleExceptFunctions() {
    return impl_.BuildAndParseInternalModuleExceptFunctions();
  }

  /// Builds an internal representation of the SPIR-V binary,
  /// and parses it into a Tint AST module.  Diagnostics are emitted
  /// to the error stream.
  /// @returns true if it was successful.
  bool BuildAndParseInternalModule() {
    return impl_.BuildAndParseInternalModule();
  }

  /// Registers user names for SPIR-V objects, from OpName, and OpMemberName.
  /// Also synthesizes struct field names.  Ensures uniqueness for names for
  /// SPIR-V IDs, and uniqueness of names of fields within any single struct.
  /// This is a no-op if the parser has already failed.
  /// @returns true if parser is still successful.
  bool RegisterUserAndStructMemberNames() {
    return impl_.RegisterUserAndStructMemberNames();
  }

  /// Register Tint AST types for SPIR-V types, including type aliases as
  /// needed.  This is a no-op if the parser has already failed.
  /// @returns true if parser is still successful.
  bool RegisterTypes() { return impl_.RegisterTypes(); }

  /// Register sampler and texture usage for memory object declarations.
  /// This must be called after we've registered line numbers for all
  /// instructions. This is a no-op if the parser has already failed.
  /// @returns true if parser is still successful.
  bool RegisterHandleUsage() { return impl_.RegisterHandleUsage(); }

  /// Emits module-scope variables.
  /// This is a no-op if the parser has already failed.
  /// @returns true if parser is still successful.
  bool EmitModuleScopeVariables() { return impl_.EmitModuleScopeVariables(); }

  /// @returns the set of SPIR-V IDs for imports of the "GLSL.std.450"
  /// extended instruction set.
  const std::unordered_set<uint32_t>& glsl_std_450_imports() const {
    return impl_.glsl_std_450_imports();
  }

  /// Converts a SPIR-V type to a Tint type, and saves it for fast lookup.
  /// If the type is only used for builtins, then register that specially,
  /// and return null.  If the type is a sampler, image, or sampled image, then
  /// return the Void type, because those opaque types are handled in a
  /// different way.
  /// On failure, logs an error and returns null.  This should only be called
  /// after the internal representation of the module has been built.
  /// @param id the SPIR-V ID of a type.
  /// @returns a Tint type, or nullptr
  const Type* ConvertType(uint32_t id) { return impl_.ConvertType(id); }

  /// Gets the list of decorations for a SPIR-V result ID.  Returns an empty
  /// vector if the ID is not a result ID, or if no decorations target that ID.
  /// The internal representation must have already been built.
  /// @param id SPIR-V ID
  /// @returns the list of decorations on the given ID
  DecorationList GetDecorationsFor(uint32_t id) const {
    return impl_.GetDecorationsFor(id);
  }

  /// Gets the list of decorations for the member of a struct.  Returns an empty
  /// list if the `id` is not the ID of a struct, or if the member index is out
  /// of range, or if the target member has no decorations.
  /// The internal representation must have already been built.
  /// @param id SPIR-V ID of a struct
  /// @param member_index the member within the struct
  /// @returns the list of decorations on the member
  DecorationList GetDecorationsForMember(uint32_t id,
                                         uint32_t member_index) const {
    return impl_.GetDecorationsForMember(id, member_index);
  }

  /// Converts a SPIR-V struct member decoration into a number of AST
  /// decorations. If the decoration is recognized but deliberately dropped,
  /// then returns an empty list without a diagnostic. On failure, emits a
  /// diagnostic and returns an empty list.
  /// @param struct_type_id the ID of the struct type
  /// @param member_index the index of the member
  /// @param member_ty the type of the member
  /// @param decoration an encoded SPIR-V Decoration
  /// @returns the AST decorations
  ast::AttributeList ConvertMemberDecoration(uint32_t struct_type_id,
                                             uint32_t member_index,
                                             const Type* member_ty,
                                             const Decoration& decoration) {
    return impl_.ConvertMemberDecoration(struct_type_id, member_index,
                                         member_ty, decoration);
  }

  /// For a SPIR-V ID that might define a sampler, image, or sampled image
  /// value, return the SPIR-V instruction that represents the memory object
  /// declaration for the object.  If we encounter an OpSampledImage along the
  /// way, follow the image operand when follow_image is true; otherwise follow
  /// the sampler operand. Returns nullptr if we can't trace back to a memory
  /// object declaration.  Emits an error and returns nullptr when the scan
  /// fails due to a malformed module. This method can be used any time after
  /// BuildInternalModule has been invoked.
  /// @param id the SPIR-V ID of the sampler, image, or sampled image
  /// @param follow_image indicates whether to follow the image operand of
  /// OpSampledImage
  /// @returns the memory object declaration for the handle, or nullptr
  const spvtools::opt::Instruction* GetMemoryObjectDeclarationForHandle(
      uint32_t id,
      bool follow_image) {
    return impl_.GetMemoryObjectDeclarationForHandle(id, follow_image);
  }

  /// @param entry_point the SPIR-V ID of an entry point.
  /// @returns the entry point info for the given ID
  const std::vector<EntryPointInfo>& GetEntryPointInfo(uint32_t entry_point) {
    return impl_.GetEntryPointInfo(entry_point);
  }

  /// Returns the handle usage for a memory object declaration.
  /// @param id SPIR-V ID of a sampler or image OpVariable or
  /// OpFunctionParameter
  /// @returns the handle usage, or an empty usage object.
  Usage GetHandleUsage(uint32_t id) const { return impl_.GetHandleUsage(id); }

  /// Returns the SPIR-V instruction with the given ID, or nullptr.
  /// @param id the SPIR-V result ID
  /// @returns the instruction, or nullptr on error
  const spvtools::opt::Instruction* GetInstructionForTest(uint32_t id) const {
    return impl_.GetInstructionForTest(id);
  }

  /// @returns info about the gl_Position builtin variable.
  const ParserImpl::BuiltInPositionInfo& GetBuiltInPositionInfo() {
    return impl_.GetBuiltInPositionInfo();
  }

  /// Returns the source record for the SPIR-V instruction with the given
  /// result ID.
  /// @param id the SPIR-V result id.
  /// @return the Source record, or a default one
  Source GetSourceForResultIdForTest(uint32_t id) const {
    return impl_.GetSourceForResultIdForTest(id);
  }

 private:
  ParserImpl impl_;
  /// When true, indicates the input SPIR-V module should not be emitted.
  /// It's either deliberately invalid, or not supported for some pending
  /// reason.
  bool skip_dumping_spirv_ = false;
  static bool dump_successfully_converted_spirv_;
};

// Sets global state to force dumping of the assembly text of succesfully
// SPIR-V.
inline void DumpSuccessfullyConvertedSpirv() {
  ParserImplWrapperForTest::DumpSuccessfullyConvertedSpirv();
}

/// Returns the WGSL printed string of a program.
/// @param program the Program
/// @returns the WGSL printed string the program.
std::string ToString(const Program& program);

/// Returns the WGSL printed string of a statement list.
/// @param program the Program
/// @param stmts the statement list
/// @returns the WGSL printed string of a statement list.
std::string ToString(const Program& program, const ast::StatementList& stmts);

/// Returns the WGSL printed string of an AST node.
/// @param program the Program
/// @param node the AST node
/// @returns the WGSL printed string of the AST node.
std::string ToString(const Program& program, const ast::Node* node);

}  // namespace test

/// SPIR-V Parser test class
template <typename T>
class SpvParserTestBase : public T {
 public:
  SpvParserTestBase() = default;
  ~SpvParserTestBase() override = default;

  /// Retrieves the parser from the helper
  /// @param input the SPIR-V binary to parse
  /// @returns a parser for the given binary
  std::unique_ptr<test::ParserImplWrapperForTest> parser(
      const std::vector<uint32_t>& input) {
    auto parser = std::make_unique<test::ParserImplWrapperForTest>(input);

    // Don't run the Resolver when building the program.
    // We're not interested in type information with these tests.
    parser->builder().SetResolveOnBuild(false);
    return parser;
  }
};

/// SpvParserTest the the base class for SPIR-V reader unit tests.
/// Use this form when you don't need to template any further.
using SpvParserTest = SpvParserTestBase<::testing::Test>;

}  // namespace tint::reader::spirv

#endif  // SRC_TINT_READER_SPIRV_PARSER_IMPL_TEST_HELPER_H_
