1 // Copyright (c) 2017 Pierre Moreau 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef TEST_LINK_LINKER_FIXTURE_H_ 16 #define TEST_LINK_LINKER_FIXTURE_H_ 17 18 #include <iostream> 19 #include <string> 20 #include <vector> 21 22 #include "source/spirv_constant.h" 23 #include "spirv-tools/linker.hpp" 24 #include "test/unit_spirv.h" 25 26 namespace spvtest { 27 28 using Binary = std::vector<uint32_t>; 29 using Binaries = std::vector<Binary>; 30 31 class LinkerTest : public ::testing::Test { 32 public: LinkerTest()33 LinkerTest() 34 : context_(SPV_ENV_UNIVERSAL_1_2), 35 tools_(SPV_ENV_UNIVERSAL_1_2), 36 assemble_options_(spvtools::SpirvTools::kDefaultAssembleOption), 37 disassemble_options_(spvtools::SpirvTools::kDefaultDisassembleOption) { 38 const auto consumer = [this](spv_message_level_t level, const char*, 39 const spv_position_t& position, 40 const char* message) { 41 if (!error_message_.empty()) error_message_ += "\n"; 42 switch (level) { 43 case SPV_MSG_FATAL: 44 case SPV_MSG_INTERNAL_ERROR: 45 case SPV_MSG_ERROR: 46 error_message_ += "ERROR"; 47 break; 48 case SPV_MSG_WARNING: 49 error_message_ += "WARNING"; 50 break; 51 case SPV_MSG_INFO: 52 error_message_ += "INFO"; 53 break; 54 case SPV_MSG_DEBUG: 55 error_message_ += "DEBUG"; 56 break; 57 } 58 error_message_ += ": " + std::to_string(position.index) + ": " + message; 59 }; 60 context_.SetMessageConsumer(consumer); 61 tools_.SetMessageConsumer(consumer); 62 } 63 TearDown()64 void TearDown() override { error_message_.clear(); } 65 66 // Assembles each of the given strings into SPIR-V binaries before linking 67 // them together. SPV_ERROR_INVALID_TEXT is returned if the assembling failed 68 // for any of the input strings, and SPV_ERROR_INVALID_POINTER if 69 // |linked_binary| is a null pointer. 70 spv_result_t AssembleAndLink( 71 const std::vector<std::string>& bodies, spvtest::Binary* linked_binary, 72 spvtools::LinkerOptions options = spvtools::LinkerOptions()) { 73 if (!linked_binary) return SPV_ERROR_INVALID_POINTER; 74 75 spvtest::Binaries binaries(bodies.size()); 76 for (size_t i = 0u; i < bodies.size(); ++i) 77 if (!tools_.Assemble(bodies[i], binaries.data() + i, assemble_options_)) 78 return SPV_ERROR_INVALID_TEXT; 79 80 return spvtools::Link(context_, binaries, linked_binary, options); 81 } 82 83 // Links the given SPIR-V binaries together; SPV_ERROR_INVALID_POINTER is 84 // returned if |linked_binary| is a null pointer. 85 spv_result_t Link( 86 const spvtest::Binaries& binaries, spvtest::Binary* linked_binary, 87 spvtools::LinkerOptions options = spvtools::LinkerOptions()) { 88 if (!linked_binary) return SPV_ERROR_INVALID_POINTER; 89 return spvtools::Link(context_, binaries, linked_binary, options); 90 } 91 92 // Disassembles |binary| and outputs the result in |text|. If |text| is a 93 // null pointer, SPV_ERROR_INVALID_POINTER is returned. Disassemble(const spvtest::Binary & binary,std::string * text)94 spv_result_t Disassemble(const spvtest::Binary& binary, std::string* text) { 95 if (!text) return SPV_ERROR_INVALID_POINTER; 96 return tools_.Disassemble(binary, text, disassemble_options_) 97 ? SPV_SUCCESS 98 : SPV_ERROR_INVALID_BINARY; 99 } 100 101 // Sets the options for the assembler. SetAssembleOptions(uint32_t assemble_options)102 void SetAssembleOptions(uint32_t assemble_options) { 103 assemble_options_ = assemble_options; 104 } 105 106 // Sets the options used by the disassembler. SetDisassembleOptions(uint32_t disassemble_options)107 void SetDisassembleOptions(uint32_t disassemble_options) { 108 disassemble_options_ = disassemble_options; 109 } 110 111 // Returns the accumulated error messages for the test. GetErrorMessage()112 std::string GetErrorMessage() const { return error_message_; } 113 114 private: 115 spvtools::Context context_; 116 spvtools::SpirvTools 117 tools_; // An instance for calling SPIRV-Tools functionalities. 118 uint32_t assemble_options_; 119 uint32_t disassemble_options_; 120 std::string error_message_; 121 }; 122 123 } // namespace spvtest 124 125 #endif // TEST_LINK_LINKER_FIXTURE_H_ 126