From abf8f6413c96d9fcc13e9828929d618a27e70edc Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Tue, 28 Jun 2016 10:23:13 -0400 Subject: [PATCH] Promote ir namespace and create draft libspirv.{h|c}pp. --- source/opt/CMakeLists.txt | 2 + source/opt/basic_block.h | 2 - source/opt/function.cpp | 2 - source/opt/function.h | 2 - source/opt/instruction.cpp | 2 - source/opt/instruction.h | 2 - source/opt/ir_loader.cpp | 2 - source/opt/ir_loader.h | 2 - .../opt_test_common.cpp => source/opt/libspirv.cpp | 75 ++++++++++----------- source/opt/libspirv.hpp | 76 ++++++++++++++++++++++ source/opt/module.cpp | 2 - source/opt/module.h | 2 - source/opt/reflect.h | 2 - test/opt/CMakeLists.txt | 2 +- test/opt/opt_test_common.h | 54 --------------- test/opt/test_ir_loader.cpp | 31 ++++++--- 16 files changed, 138 insertions(+), 122 deletions(-) rename test/opt/opt_test_common.cpp => source/opt/libspirv.cpp (59%) create mode 100644 source/opt/libspirv.hpp delete mode 100644 test/opt/opt_test_common.h diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt index 80e7c64..1d1c27d 100644 --- a/source/opt/CMakeLists.txt +++ b/source/opt/CMakeLists.txt @@ -3,12 +3,14 @@ add_library(SPIRV-Tools-opt function.h instruction.h ir_loader.h + libspirv.hpp module.h reflect.h function.cpp instruction.cpp ir_loader.cpp + libspirv.cpp module.cpp ) diff --git a/source/opt/basic_block.h b/source/opt/basic_block.h index 97cc30f..a1f47c6 100644 --- a/source/opt/basic_block.h +++ b/source/opt/basic_block.h @@ -37,7 +37,6 @@ #include "instruction.h" namespace spvtools { -namespace opt { namespace ir { class Function; @@ -81,7 +80,6 @@ inline void BasicBlock::ToBinary(std::vector* binary, } } // namespace ir -} // namespace opt } // namespace spvtools #endif // LIBSPIRV_OPT_BASIC_BLOCK_H_ diff --git a/source/opt/function.cpp b/source/opt/function.cpp index 18c4340..d013fe5 100644 --- a/source/opt/function.cpp +++ b/source/opt/function.cpp @@ -27,7 +27,6 @@ #include "function.h" namespace spvtools { -namespace opt { namespace ir { void Function::ForEachInst(const std::function& f) { @@ -45,5 +44,4 @@ void Function::ToBinary(std::vector* binary, bool skip_nop) const { } } // namespace ir -} // namespace opt } // namespace spvtools diff --git a/source/opt/function.h b/source/opt/function.h index 728f3bc..d7c01e1 100644 --- a/source/opt/function.h +++ b/source/opt/function.h @@ -35,7 +35,6 @@ #include "instruction.h" namespace spvtools { -namespace opt { namespace ir { class Module; @@ -74,7 +73,6 @@ class Function { }; } // namespace ir -} // namespace opt } // namespace spvtools #endif // LIBSPIRV_OPT_CONSTRUCTS_H_ diff --git a/source/opt/instruction.cpp b/source/opt/instruction.cpp index 76e4d45..a643d72 100644 --- a/source/opt/instruction.cpp +++ b/source/opt/instruction.cpp @@ -31,7 +31,6 @@ #include "reflect.h" namespace spvtools { -namespace opt { namespace ir { Instruction::Instruction(const spv_parsed_instruction_t& inst, @@ -78,5 +77,4 @@ void Instruction::ToBinary(std::vector* binary, bool skip_nop) const { } } // namespace ir -} // namespace opt } // namespace spvtools diff --git a/source/opt/instruction.h b/source/opt/instruction.h index b89ee01..0bbcd6e 100644 --- a/source/opt/instruction.h +++ b/source/opt/instruction.h @@ -36,7 +36,6 @@ #include "spirv/1.1/spirv.h" namespace spvtools { -namespace opt { namespace ir { class Function; @@ -185,7 +184,6 @@ inline void Instruction::ForEachInst( } } // namespace ir -} // namespace opt } // namespace spvtools #endif // LIBSPIRV_OPT_INSTRUCTION_H_ diff --git a/source/opt/ir_loader.cpp b/source/opt/ir_loader.cpp index 8da7cb3..06265ef 100644 --- a/source/opt/ir_loader.cpp +++ b/source/opt/ir_loader.cpp @@ -31,7 +31,6 @@ #include "reflect.h" namespace spvtools { -namespace opt { namespace ir { void IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) { @@ -119,5 +118,4 @@ void IrLoader::EndModule() { } } // namespace ir -} // namespace opt } // namespace spvtools diff --git a/source/opt/ir_loader.h b/source/opt/ir_loader.h index 7eedd6a..c4407b9 100644 --- a/source/opt/ir_loader.h +++ b/source/opt/ir_loader.h @@ -35,7 +35,6 @@ #include "spirv-tools/libspirv.h" namespace spvtools { -namespace opt { namespace ir { // Loader class for constructing SPIR-V in-memory IR representation. Methods in @@ -77,7 +76,6 @@ class IrLoader { }; } // namespace ir -} // namespace opt } // namespace spvtools #endif // LIBSPIRV_OPT_IR_LOADER_H_ diff --git a/test/opt/opt_test_common.cpp b/source/opt/libspirv.cpp similarity index 59% rename from test/opt/opt_test_common.cpp rename to source/opt/libspirv.cpp index 2a5d94b..fe1b2b5 100644 --- a/test/opt/opt_test_common.cpp +++ b/source/opt/libspirv.cpp @@ -24,15 +24,11 @@ // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -#include "opt_test_common.h" +#include "libspirv.hpp" -#include - -#include "source/opt/ir_loader.h" -#include "spirv-tools/libspirv.h" +#include "ir_loader.h" namespace spvtools { -namespace opt { namespace { @@ -54,63 +50,64 @@ spv_result_t SetSpvInst(void* builder, const spv_parsed_instruction_t* inst) { } // annoymous namespace -// Assembles the given assembly |text| and returns the binary. -std::vector Assemble(const std::string& text) { - spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - spv_binary binary = nullptr; +spv_result_t SpvTools::Assemble(const std::string& text, + std::vector* binary) { + spv_binary spvbinary = nullptr; spv_diagnostic diagnostic = nullptr; - spv_result_t status = - spvTextToBinary(context, text.data(), text.size(), &binary, &diagnostic); - EXPECT_EQ(SPV_SUCCESS, status) << "assemble text to binary failed"; - std::vector result(binary->code, binary->code + binary->wordCount); + spv_result_t status = spvTextToBinary(context_, text.data(), text.size(), + &spvbinary, &diagnostic); + if (status == SPV_SUCCESS) { + binary->assign(spvbinary->code, spvbinary->code + spvbinary->wordCount); + } spvDiagnosticDestroy(diagnostic); - spvBinaryDestroy(binary); - spvContextDestroy(context); + spvBinaryDestroy(spvbinary); - return result; + return status; } -// Disassembles the given SPIR-V |binary| and returns the assembly. -std::string Disassemble(const std::vector& binary) { - spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); - spv_text text = nullptr; +spv_result_t SpvTools::Disassemble(const std::vector& binary, + std::string* text) { + spv_text spvtext = nullptr; spv_diagnostic diagnostic = nullptr; - spv_result_t status = - spvBinaryToText(context, binary.data(), binary.size(), - SPV_BINARY_TO_TEXT_OPTION_NO_HEADER, &text, &diagnostic); - EXPECT_EQ(SPV_SUCCESS, status) << "disassemble binary to text failed"; - std::string result(text->str, text->str + text->length); + spv_result_t status = spvBinaryToText(context_, binary.data(), binary.size(), + SPV_BINARY_TO_TEXT_OPTION_NO_HEADER, + &spvtext, &diagnostic); + if (status == SPV_SUCCESS) { + text->assign(spvtext->str, spvtext->str + spvtext->length); + } spvDiagnosticDestroy(diagnostic); - spvTextDestroy(text); - spvContextDestroy(context); + spvTextDestroy(spvtext); - return result; + return status; } -// Builds and returns a Module for the given SPIR-V |binary|. -std::unique_ptr BuildModule(const std::vector& binary) { - spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_1); +std::unique_ptr SpvTools::BuildModule( + const std::vector& binary) { spv_diagnostic diagnostic = nullptr; std::unique_ptr module(new ir::Module); - ir::IrLoader builder(module.get()); + ir::IrLoader loader(module.get()); spv_result_t status = - spvBinaryParse(context, &builder, binary.data(), binary.size(), + spvBinaryParse(context_, &loader, binary.data(), binary.size(), SetSpvHeader, SetSpvInst, &diagnostic); - EXPECT_EQ(SPV_SUCCESS, status) << "build ir::Module from binary failed"; spvDiagnosticDestroy(diagnostic); - spvContextDestroy(context); - builder.EndModule(); + loader.EndModule(); + + if (status == SPV_SUCCESS) return module; + return nullptr; +} - return module; +std::unique_ptr SpvTools::BuildModule(const std::string& text) { + std::vector binary; + if (Assemble(text, &binary) != SPV_SUCCESS) return nullptr; + return BuildModule(binary); } -} // namespace opt } // namespace spvtools diff --git a/source/opt/libspirv.hpp b/source/opt/libspirv.hpp new file mode 100644 index 0000000..667276f --- /dev/null +++ b/source/opt/libspirv.hpp @@ -0,0 +1,76 @@ +// Copyright (c) 2016 Google Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +#ifndef SPIRV_TOOLS_LIBSPIRV_HPP_ +#define SPIRV_TOOLS_LIBSPIRV_HPP_ + +#include +#include +#include + +#include "module.h" +#include "spirv-tools/libspirv.h" + +namespace spvtools { + +// C++ interface for SPIRV-Tools functionalities. It wraps the context +// (including target environment and the corresponding SPIR-V grammar) and +// provides methods for assembling, disassembling, validating, and optimizing. +// +// Instances of this class are thread-safe. +class SpvTools { + public: + // Creates an instance targeting the given environment |env|. + SpvTools(spv_target_env env) : context_(spvContextCreate(env)) {} + + ~SpvTools() { spvContextDestroy(context_); } + + // TODO(antiagainst): handle error message in the following APIs. + + // Assembles the given assembly |text| and writes the result to |binary|. + // Returns SPV_SUCCESS on successful assembling. + spv_result_t Assemble(const std::string& text, std::vector* binary); + + // Disassembles the given SPIR-V |binary| and returns the assembly. Returns + // SPV_SUCCESS on successful disassembling. + spv_result_t Disassemble(const std::vector& binary, + std::string* text); + + // Builds and returns a Module from the given SPIR-V |binary|. + std::unique_ptr BuildModule(const std::vector& binary); + + // Builds and returns a Module from the given SPIR-V assembly |text|. + std::unique_ptr BuildModule(const std::string& text); + + private: + // Context for the current invocation. Thread-safety of this class depends on + // the constness of this field. + spv_context context_; +}; + +} // namespace spvtools + +#endif // SPIRV_TOOLS_LIBSPIRV_HPP_ diff --git a/source/opt/module.cpp b/source/opt/module.cpp index 454e066..c6bab3a 100644 --- a/source/opt/module.cpp +++ b/source/opt/module.cpp @@ -28,7 +28,6 @@ #include "reflect.h" namespace spvtools { -namespace opt { namespace ir { std::vector Module::types() { @@ -75,5 +74,4 @@ void Module::ToBinary(std::vector* binary, bool skip_nop) const { } } // namespace ir -} // namespace opt } // namespace spvtools diff --git a/source/opt/module.h b/source/opt/module.h index ae2e4c0..f4bfbbc 100644 --- a/source/opt/module.h +++ b/source/opt/module.h @@ -35,7 +35,6 @@ #include "instruction.h" namespace spvtools { -namespace opt { namespace ir { // A struct for containing the module header information. @@ -125,7 +124,6 @@ class Module { }; } // namespace ir -} // namespace opt } // namespace spvtools #endif // LIBSPIRV_OPT_MODULE_H_ diff --git a/source/opt/reflect.h b/source/opt/reflect.h index 7da8759..8733c15 100644 --- a/source/opt/reflect.h +++ b/source/opt/reflect.h @@ -30,7 +30,6 @@ #include "spirv/1.1/spirv.h" namespace spvtools { -namespace opt { namespace ir { // Note that as SPIR-V evolves over time, new opcodes may appear. So the @@ -59,7 +58,6 @@ inline bool IsTerminatorInst(SpvOp opcode) { } } // namespace ir -} // namespace opt } // namespace spvtools #endif // LIBSPIRV_OPT_REFLECT_H_ diff --git a/test/opt/CMakeLists.txt b/test/opt/CMakeLists.txt index 881f3c8..9f786de 100644 --- a/test/opt/CMakeLists.txt +++ b/test/opt/CMakeLists.txt @@ -25,6 +25,6 @@ # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. add_spvtools_unittest(TARGET ir_loader - SRCS test_ir_loader.cpp opt_test_common.cpp + SRCS test_ir_loader.cpp LIBS SPIRV-Tools-opt ${SPIRV_TOOLS} ) diff --git a/test/opt/opt_test_common.h b/test/opt/opt_test_common.h deleted file mode 100644 index 7337943..0000000 --- a/test/opt/opt_test_common.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2016 Google Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS -// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS -// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT -// https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. - -#ifndef LIBSPIRV_TEST_OPT_OPT_TEST_COMMON_H_ -#define LIBSPIRV_TEST_OPT_OPT_TEST_COMMON_H_ - -#include -#include -#include - -#include "source/opt/module.h" - -namespace spvtools { -namespace opt { - -// TODO(antiagainst): expand and export these functions as the C++ interface in -// libspirv.hpp. - -// Assembles the given assembly |text| and returns the binary. -std::vector Assemble(const std::string& text); - -// Disassembles the given SPIR-V |binary| and returns the assembly. -std::string Disassemble(const std::vector& binary); - -// Builds and returns a Module for the given SPIR-V |binary|. -std::unique_ptr BuildModule(const std::vector& binary); - -} // namespace opt -} // namespace spvtools - -#endif // LIBSPIRV_TEST_OPT_OPT_TEST_COMMON_H_ diff --git a/test/opt/test_ir_loader.cpp b/test/opt/test_ir_loader.cpp index c2bbe16..bb788f5 100644 --- a/test/opt/test_ir_loader.cpp +++ b/test/opt/test_ir_loader.cpp @@ -26,11 +26,11 @@ #include -#include "opt_test_common.h" +#include "opt/libspirv.hpp" namespace { -using namespace spvtools::opt; +using namespace spvtools; TEST(IrBuilder, RoundTrip) { // #version 310 es @@ -76,11 +76,16 @@ TEST(IrBuilder, RoundTrip) { "OpReturnValue %20\n" "OpFunctionEnd\n"; - std::unique_ptr module = BuildModule(Assemble(text)); + SpvTools t(SPV_ENV_UNIVERSAL_1_1); + std::unique_ptr module = t.BuildModule(text); + ASSERT_NE(nullptr, module); + std::vector binary; module->ToBinary(&binary, /* skip_nop = */ false); - EXPECT_EQ(text, Disassemble(binary)); + std::string disassembled_text; + EXPECT_EQ(SPV_SUCCESS, t.Disassemble(binary, &disassembled_text)); + EXPECT_EQ(text, disassembled_text); } TEST(IrBuilder, KeepLineDebugInfo) { @@ -109,11 +114,16 @@ TEST(IrBuilder, KeepLineDebugInfo) { "OpReturn\n" "OpFunctionEnd\n"; - std::unique_ptr module = BuildModule(Assemble(text)); + SpvTools t(SPV_ENV_UNIVERSAL_1_1); + std::unique_ptr module = t.BuildModule(text); + ASSERT_NE(nullptr, module); + std::vector binary; module->ToBinary(&binary, /* skip_nop = */ false); - EXPECT_EQ(text, Disassemble(binary)); + std::string disassembled_text; + EXPECT_EQ(SPV_SUCCESS, t.Disassemble(binary, &disassembled_text)); + EXPECT_EQ(text, disassembled_text); } TEST(IrBuilder, LocalGlobalVariables) { @@ -183,11 +193,16 @@ TEST(IrBuilder, LocalGlobalVariables) { "OpReturnValue %30\n" "OpFunctionEnd\n"; - std::unique_ptr module = BuildModule(Assemble(text)); + SpvTools t(SPV_ENV_UNIVERSAL_1_1); + std::unique_ptr module = t.BuildModule(text); + ASSERT_NE(nullptr, module); + std::vector binary; module->ToBinary(&binary, /* skip_nop = */ false); - EXPECT_EQ(text, Disassemble(binary)); + std::string disassembled_text; + EXPECT_EQ(SPV_SUCCESS, t.Disassemble(binary, &disassembled_text)); + EXPECT_EQ(text, disassembled_text); } } // anonymous namespace -- 2.7.4