Publish the C++ interface.

This commit is contained in:
Lei Zhang 2016-09-16 16:12:04 -04:00
parent 92411caa3b
commit 620f05e679
25 changed files with 120 additions and 103 deletions

View File

@ -1,6 +1,8 @@
Revision history for SPIRV-Tools
v2016.6-dev 2016-09-16
- Published the C++ interface for assembling, disassembling, validation, and
optimization.
v2016.5 2016-09-16
- Support SPV_KHR_shader_ballot in assembler, disassembler, parser.

View File

@ -153,8 +153,13 @@ add_subdirectory(tools)
add_subdirectory(test)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/libspirv.h
DESTINATION include/spirv-tools/)
install(
FILES
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/libspirv.h
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/libspirv.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/optimizer.hpp
DESTINATION
include/spirv-tools/)
add_test(NAME spirv-tools-copyrights
COMMAND ${PYTHON_EXECUTABLE} utils/check_copyright.py

View File

@ -13,7 +13,7 @@ validator, and optimizer for SPIR-V. Except for the optimizer, all are based
on a common static library. The library contains all of the implementation
details, and is used in the standalone tools whilst also enabling integration
into other code bases directly. The optimizer implementation resides in its
own library.
own library, which depends on the core library.
The interfaces are still under development, and are expected to change.
@ -59,17 +59,18 @@ See [`syntax.md`](syntax.md) for the assembly language syntax.
### Optimizer
*Warning:* The optimizer is still under development and its library interface is
not yet published.
*Warning:* The optimizer is still under development.
Currently supported optimizations:
* [Strip debug info](source/opt/strip_debug_info_pass.h)
* [Freeze spec constant](source/opt/freeze_spec_constant_value_pass.h)
* [Fold `OpSpecConstantOp` and `OpSpecConstantComposite`](source/opt/fold_spec_constant_op_and_composite_pass.h)
* [Unify constants](source/opt/unify_const_pass.h)
* [Eliminate dead constant](source/opt/eliminate_dead_constant_pass.h)
* Strip debug info
* Set spec constant default value
* Freeze spec constant
* Fold `OpSpecConstantOp` and `OpSpecConstantComposite`
* Unify constants
* Eliminate dead constant
For the latest list, please refer to `spirv-opt --help`.
For the latest list with detailed documentation, please refer to
[`include/spirv-tools/optimizer.hpp`](include/spirv-tools/optimizer.hpp).
## Source code
@ -161,23 +162,31 @@ The following CMake options are supported:
### Usage
The library provides a C API, but the internals use C++11.
The internals of the library use C++11 features, and are exposed via both a C
and C++ API.
In order to use the library from an application, the include path should point
to `<spirv-dir>/include`, which will enable the application to include the
header `<spirv-dir>/include/spirv-tools/libspirv.h` then linking against the
static library in `<spirv-build-dir>/source/libSPIRV-Tools.a` or
header `<spirv-dir>/include/spirv-tools/libspirv.h{|pp}` then linking against
the static library in `<spirv-build-dir>/source/libSPIRV-Tools.a` or
`<spirv-build-dir>/source/SPIRV-Tools.lib`.
For optimization, the header file is
`<spirv-dir>/include/spirv-tools/optimizer.hpp`, and the static library is
`<spirv-build-dir>/source/libSPIRV-Tools-opt.a` or
`<spirv-build-dir>/source/SPIRV-Tools-opt.lib`.
* `SPIRV-Tools` CMake target: Creates the static library:
* `<spirv-build-dir>/source/libSPIRV-Tools.a` on Linux and OS X.
* `<spirv-build-dir>/source/libSPIRV-Tools.lib` on Windows.
* `SPIRV-Tools-opt` CMake target: Creates the static library:
* `<spirv-build-dir>/source/libSPIRV-Tools-opt.a` on Linux and OS X.
* `<spirv-build-dir>/source/libSPIRV-Tools-opt.lib` on Windows.
#### Entry points
The interfaces are still under development, and are expected to change.
There are three main entry points into the library.
There are five main entry points into the library in the C interface:
* `spvTextToBinary`: An assembler, translating text to a binary SPIR-V module.
* `spvBinaryToText`: A disassembler, translating a binary SPIR-V module to
@ -186,6 +195,12 @@ There are three main entry points into the library.
for the header and each parsed instruction. The disassembler is implemented
as a client of `spvBinaryParse`.
* `spvValidate` implements the validator functionality. *Incomplete*
* `spvValidateBinary` implements the validator functionality. *Incomplete*
The C++ interface is comprised of two classes, `SpirvTools` and `Optimizer`,
both in the `spvtools` namespace.
* `SpirvTools` provides `Assemble`, `Disassemble`, and `Validate` methods.
* `Optimizer` provides methods for registering and running optimization passes.
## Command line tools

View File

@ -56,6 +56,21 @@ typedef enum spv_result_t {
SPV_FORCE_32_BIT_ENUM(spv_result_t)
} spv_result_t;
// Severity levels of messages communicated to the consumer.
typedef enum spv_message_level_t {
SPV_MSG_FATAL, // Unrecoverable error due to environment.
// Will exit the program immediately. E.g.,
// out of memory.
SPV_MSG_INTERNAL_ERROR, // Unrecoverable error due to SPIRV-Tools
// internals.
// Will exit the program immediately. E.g.,
// unimplemented feature.
SPV_MSG_ERROR, // Normal error due to user input.
SPV_MSG_WARNINING, // Warning information.
SPV_MSG_INFO, // General information.
SPV_MSG_DEBUG, // Debug information.
} spv_message_level_t;
typedef enum spv_endianness_t {
SPV_ENDIANNESS_LITTLE,
SPV_ENDIANNESS_BIG,

View File

@ -15,15 +15,22 @@
#ifndef SPIRV_TOOLS_LIBSPIRV_HPP_
#define SPIRV_TOOLS_LIBSPIRV_HPP_
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include "message.h"
#include "spirv-tools/libspirv.h"
namespace spvtools {
// Message consumer. The C strings for source and message are only alive for the
// specific invocation.
using MessageConsumer = std::function<void(
spv_message_level_t /* level */, const char* /* source */,
const spv_position_t& /* position */, const char* /* message */
)>;
// 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, and validating.

View File

@ -21,7 +21,6 @@
#include <vector>
#include "libspirv.hpp"
#include "message.h"
namespace spvtools {

View File

@ -143,6 +143,7 @@ set(SPIRV_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.cpp
${CMAKE_CURRENT_SOURCE_DIR}/instruction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libspirv.cpp
${CMAKE_CURRENT_SOURCE_DIR}/message.cpp
${CMAKE_CURRENT_SOURCE_DIR}/name_mapper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/opcode.cpp

View File

@ -14,12 +14,10 @@
#include "diagnostic.h"
#include <assert.h>
#include <string.h>
#include <cassert>
#include <cstring>
#include <iostream>
#include "spirv-tools/libspirv.h"
#include "table.h"
// Diagnostic API
@ -70,22 +68,22 @@ namespace libspirv {
DiagnosticStream::~DiagnosticStream() {
if (error_ != SPV_FAILED_MATCH && consumer_ != nullptr) {
auto level = spvtools::SPV_MSG_ERROR;
auto level = SPV_MSG_ERROR;
switch (error_) {
case SPV_SUCCESS:
case SPV_REQUESTED_TERMINATION: // Essentially success.
level = spvtools::SPV_MSG_INFO;
level = SPV_MSG_INFO;
break;
case SPV_WARNING:
level = spvtools::SPV_MSG_WARNINING;
level = SPV_MSG_WARNINING;
break;
case SPV_UNSUPPORTED:
case SPV_ERROR_INTERNAL:
case SPV_ERROR_INVALID_TABLE:
level = spvtools::SPV_MSG_INTERNAL_ERROR;
level = SPV_MSG_INTERNAL_ERROR;
break;
case SPV_ERROR_OUT_OF_MEMORY:
level = spvtools::SPV_MSG_FATAL;
level = SPV_MSG_FATAL;
break;
default:
break;
@ -98,9 +96,9 @@ void UseDiagnosticAsMessageConsumer(spv_context context,
spv_diagnostic* diagnostic) {
assert(diagnostic && *diagnostic == nullptr);
auto create_diagnostic = [diagnostic](
spvtools::spv_message_level_t, const char*,
const spv_position_t& position, const char* message) {
auto create_diagnostic = [diagnostic](spv_message_level_t, const char*,
const spv_position_t& position,
const char* message) {
auto p = position;
spvDiagnosticDestroy(*diagnostic); // Avoid memory leak.
*diagnostic = spvDiagnosticCreate(&p, message);

View File

@ -15,12 +15,10 @@
#ifndef LIBSPIRV_DIAGNOSTIC_H_
#define LIBSPIRV_DIAGNOSTIC_H_
#include <iostream>
#include <sstream>
#include <utility>
#include "message.h"
#include "spirv-tools/libspirv.h"
#include "spirv-tools/libspirv.hpp"
namespace libspirv {

View File

@ -12,10 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "libspirv.hpp"
#include "spirv-tools/libspirv.hpp"
#include "ir_loader.h"
#include "make_unique.h"
#include "message.h"
#include "table.h"

View File

@ -15,37 +15,12 @@
#ifndef SPIRV_TOOLS_MESSAGE_H_
#define SPIRV_TOOLS_MESSAGE_H_
#include <functional>
#include <string>
#include "spirv-tools/libspirv.h"
#include "spirv-tools/libspirv.hpp"
namespace spvtools {
// TODO(antiagainst): This eventually should be in the C++ interface.
// Severity levels of messages communicated to the consumer.
typedef enum spv_message_level_t {
SPV_MSG_FATAL, // Unrecoverable error due to environment.
// Will exit the program immediately. E.g.,
// out of memory.
SPV_MSG_INTERNAL_ERROR, // Unrecoverable error due to SPIRV-Tools
// internals.
// Will exit the program immediately. E.g.,
// unimplemented feature.
SPV_MSG_ERROR, // Normal error due to user input.
SPV_MSG_WARNINING, // Warning information.
SPV_MSG_INFO, // General information.
SPV_MSG_DEBUG, // Debug information.
} spv_message_level_t;
// Message consumer. The C strings for source and message are only alive for the
// specific invocation.
using MessageConsumer = std::function<void(
spv_message_level_t /* level */, const char* /* source */,
const spv_position_t& /* position */, const char* /* message */
)>;
// A message consumer that ignores all messages.
inline void IgnoreMessage(spv_message_level_t, const char*,
const spv_position_t&, const char*) {}

View File

@ -22,12 +22,10 @@ add_library(SPIRV-Tools-opt
freeze_spec_constant_value_pass.h
instruction.h
ir_loader.h
libspirv.hpp
log.h
module.h
null_pass.h
reflect.h
optimizer.hpp
pass.h
passes.h
pass_manager.h
@ -45,7 +43,6 @@ add_library(SPIRV-Tools-opt
freeze_spec_constant_value_pass.cpp
instruction.cpp
ir_loader.cpp
libspirv.cpp
module.cpp
set_spec_constant_default_value_pass.cpp
optimizer.cpp
@ -58,6 +55,14 @@ add_library(SPIRV-Tools-opt
spvtools_default_compile_options(SPIRV-Tools-opt)
target_include_directories(SPIRV-Tools-opt
PRIVATE ${spirv-tools_SOURCE_DIR}/include
PUBLIC ${spirv-tools_SOURCE_DIR}/include
PUBLIC ${SPIRV_HEADER_INCLUDE_DIR}
)
# We need the assembling and disassembling functionalities in the main library.
target_link_libraries(SPIRV-Tools-opt
PUBLIC ${SPIRV_TOOLS})
install(TARGETS SPIRV-Tools-opt
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)

View File

@ -15,7 +15,6 @@
#include "build_module.h"
#include "ir_loader.h"
#include "libspirv.hpp"
#include "make_unique.h"
#include "table.h"

View File

@ -19,9 +19,8 @@
#include <string>
#include <vector>
#include "message.h"
#include "module.h"
#include "spirv-tools/libspirv.h"
#include "spirv-tools/libspirv.hpp"
namespace spvtools {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "optimizer.hpp"
#include "spirv-tools/optimizer.hpp"
#include "build_module.h"
#include "make_unique.h"

View File

@ -26,12 +26,12 @@ namespace libspirv {
// The known SPIR-V extensions.
// TODO(dneto): Consider auto-generating this list?
enum class Extension {
kSPV_KHR_shader_ballot
kSPV_KHR_shader_ballot,
};
using ExtensionSet = EnumSet<Extension>;
} // namespace libspirv
} // namespace libspirv
typedef struct spv_opcode_desc_t {
const char* name;

View File

@ -14,10 +14,10 @@
#include "validate.h"
#include <cassert>
#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <tuple>

View File

@ -284,7 +284,7 @@ TEST_F(BinaryParseTest, SpecifyConsumerNullDiagnosticsForGoodParse) {
auto ctx = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
ctx, [&invocation](spvtools::spv_message_level_t, const char*,
ctx, [&invocation](spv_message_level_t, const char*,
const spv_position_t&, const char*) { ++invocation; });
EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS));
@ -303,11 +303,10 @@ TEST_F(BinaryParseTest, SpecifyConsumerNullDiagnosticsForBadParse) {
auto ctx = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
ctx,
[&invocation](spvtools::spv_message_level_t level, const char* source,
const spv_position_t& position, const char* message) {
ctx, [&invocation](spv_message_level_t level, const char* source,
const spv_position_t& position, const char* message) {
++invocation;
EXPECT_EQ(spvtools::SPV_MSG_ERROR, level);
EXPECT_EQ(SPV_MSG_ERROR, level);
EXPECT_STREQ("input", source);
EXPECT_EQ(0u, position.line);
EXPECT_EQ(0u, position.column);
@ -332,7 +331,7 @@ TEST_F(BinaryParseTest, SpecifyConsumerSpecifyDiagnosticsForGoodParse) {
auto ctx = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
ctx, [&invocation](spvtools::spv_message_level_t, const char*,
ctx, [&invocation](spv_message_level_t, const char*,
const spv_position_t&, const char*) { ++invocation; });
EXPECT_HEADER(1).WillOnce(Return(SPV_SUCCESS));
@ -352,7 +351,7 @@ TEST_F(BinaryParseTest, SpecifyConsumerSpecifyDiagnosticsForBadParse) {
auto ctx = spvContextCreate(SPV_ENV_UNIVERSAL_1_1);
int invocation = 0;
SetContextMessageConsumer(
ctx, [&invocation](spvtools::spv_message_level_t, const char*,
ctx, [&invocation](spv_message_level_t, const char*,
const spv_position_t&, const char*) { ++invocation; });
words.push_back(0xffffffff); // Certainly invalid instruction header.

View File

@ -169,7 +169,7 @@ std::vector<uint32_t> successfulEncode(const TextLiteralCase& test,
libspirv::IdTypeClass type) {
spv_instruction_t inst;
std::string message;
auto capture_message = [&message](spvtools::spv_message_level_t, const char*,
auto capture_message = [&message](spv_message_level_t, const char*,
const spv_position_t&,
const char* m) { message = m; };
libspirv::IdType expected_type{test.bitwidth, test.is_signed, type};
@ -185,7 +185,7 @@ std::string failedEncode(const TextLiteralCase& test,
libspirv::IdTypeClass type) {
spv_instruction_t inst;
std::string message;
auto capture_message = [&message](spvtools::spv_message_level_t, const char*,
auto capture_message = [&message](spv_message_level_t, const char*,
const spv_position_t&,
const char* m) { message = m; };
libspirv::IdType expected_type{test.bitwidth, test.is_signed, type};

View File

@ -15,7 +15,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "opt/optimizer.hpp"
#include "spirv-tools/optimizer.hpp"
#include "spirv/1.1/spirv.h"
namespace {

View File

@ -14,48 +14,48 @@
add_spvtools_unittest(TARGET instruction
SRCS test_instruction.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET ir_loader
SRCS test_ir_loader.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_manager
SRCS module_utils.h
test_pass_manager.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_strip_debug_info
SRCS test_strip_debug_info.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_freeze_spec_const
SRCS test_freeze_spec_const.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_eliminate_dead_const
SRCS test_eliminate_dead_const.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_utils
SRCS test_utils.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET def_use
SRCS test_def_use.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET assembly_builder
SRCS test_assembly_builder.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET types
@ -65,36 +65,36 @@ add_spvtools_unittest(TARGET types
add_spvtools_unittest(TARGET type_manager
SRCS test_type_manager.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET iterator
SRCS test_iterator.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET module
SRCS module_utils.h
test_module.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_fold_spec_const_op_composite
SRCS test_fold_spec_const_op_composite.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_unify_const
SRCS test_unify_const.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET pass_set_spec_const_default_value
SRCS test_set_spec_const_default_value.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)
add_spvtools_unittest(TARGET line_debug_info
SRCS test_line_debug_info.cpp pass_utils.cpp
LIBS SPIRV-Tools-opt ${SPIRV_TOOLS}
LIBS SPIRV-Tools-opt
)

View File

@ -23,10 +23,10 @@
#include <gtest/gtest.h>
#include "opt/build_module.h"
#include "opt/libspirv.hpp"
#include "opt/make_unique.h"
#include "opt/pass_manager.h"
#include "opt/passes.h"
#include "spirv-tools/libspirv.hpp"
namespace spvtools {

View File

@ -20,8 +20,8 @@
#include "opt/build_module.h"
#include "opt/def_use_manager.h"
#include "opt/libspirv.hpp"
#include "pass_utils.h"
#include "spirv-tools/libspirv.hpp"
namespace {

View File

@ -15,8 +15,9 @@
#include <gtest/gtest.h>
#include <algorithm>
#include "message.h"
#include "opt/build_module.h"
#include "opt/libspirv.hpp"
#include "spirv-tools/libspirv.hpp"
namespace {

View File

@ -17,9 +17,10 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "message.h"
#include "opt/build_module.h"
#include "opt/libspirv.hpp"
#include "opt/module.h"
#include "spirv-tools/libspirv.hpp"
#include "module_utils.h"