// 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>

#include "src/tint/utils/compiler_macros.h"

TINT_BEGIN_DISABLE_WARNING(NEWLINE_EOF);
TINT_BEGIN_DISABLE_WARNING(OLD_STYLE_CAST);
TINT_BEGIN_DISABLE_WARNING(SIGN_CONVERSION);
TINT_BEGIN_DISABLE_WARNING(WEAK_VTABLES);
#include "source/opt/ir_context.h"
TINT_END_DISABLE_WARNING(WEAK_VTABLES);
TINT_END_DISABLE_WARNING(SIGN_CONVERSION);
TINT_END_DISABLE_WARNING(OLD_STYLE_CAST);
TINT_END_DISABLE_WARNING(NEWLINE_EOF);

#include "gtest/gtest.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
    auto 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, utils::VectorRef<const ast::Statement*> 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_
