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