${CMAKE_CURRENT_SOURCE_DIR}/source/opcode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/operand.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/print.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/table.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/text.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/text_handler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/validate.cpp
bool isTextSource;
} spv_diagnostic_t;
+// Opaque struct containing the context used to operate on a SPIR-V module.
+// Its object is used by various tranformation API functions.
+struct spv_context_t;
+
// Type Definitions
typedef spv_const_binary_t* spv_const_binary;
typedef spv_text_t* spv_text;
typedef spv_position_t* spv_position;
typedef spv_diagnostic_t* spv_diagnostic;
+typedef const spv_context_t* spv_const_context;
+typedef spv_context_t* spv_context;
// Platform API
+// Creates a context object.
+spv_context spvContextCreate();
+
+// Destroys the given context object.
+void spvContextDestroy(spv_context context);
+
// Encodes the given SPIR-V assembly text to its binary representation. The
// length parameter specifies the number of bytes for text. Encoded binary will
// be stored into *binary. Any error will be written into *diagnostic.
-spv_result_t spvTextToBinary(const char* text, const size_t length,
- spv_binary* binary, spv_diagnostic* diagnostic);
+spv_result_t spvTextToBinary(const spv_const_context context, const char* text,
+ const size_t length, spv_binary* binary,
+ spv_diagnostic* diagnostic);
// @brief Frees an allocated text stream. This is a no-op if the text parameter
// is a null pointer.
// word_count parameter specifies the number of words for binary. The options
// parameter is a bit field of spv_binary_to_text_options_t. Decoded text will
// be stored into *text. Any error will be written into *diagnostic.
-spv_result_t spvBinaryToText(const uint32_t* binary, const size_t word_count,
+spv_result_t spvBinaryToText(const spv_const_context context,
+ const uint32_t* binary, const size_t word_count,
const uint32_t options, spv_text* text,
spv_diagnostic* diagnostic);
// Validates a SPIR-V binary for correctness. The options parameter is a bit
// field of spv_validation_options_t.
-spv_result_t spvValidate(const spv_const_binary binary, const uint32_t options,
+spv_result_t spvValidate(const spv_const_context context,
+ const spv_const_binary binary, const uint32_t options,
spv_diagnostic* pDiagnostic);
// Creates a diagnostic object. The position parameter specifies the location in
// returns SPV_ERROR_INVALID_BINARY and emits a diagnostic. If a callback
// returns anything other than SPV_SUCCESS, then that error code is returned
// and parsing terminates early.
-spv_result_t spvBinaryParse(void* user_data, const uint32_t* words,
- const size_t num_words,
+spv_result_t spvBinaryParse(const spv_const_context context, void* user_data,
+ const uint32_t* words, const size_t num_words,
spv_parsed_header_fn_t parse_header,
spv_parsed_instruction_fn_t parse_instruction,
spv_diagnostic* diagnostic);
return SPV_SUCCESS;
}
-// Returns the operand table.
-spv_operand_table GetDefaultOperandTable() {
- spv_operand_table result = nullptr;
- spvOperandTableGet(&result);
- assert(result);
- return result;
-}
-
-// Returns the opcode table.
-spv_opcode_table GetDefaultOpcodeTable() {
- spv_opcode_table result = nullptr;
- spvOpcodeTableGet(&result);
- assert(result);
- return result;
-}
-
-// Returns the extended instruction table.
-spv_ext_inst_table GetDefaultExtInstTable() {
- spv_ext_inst_table result = nullptr;
- spvExtInstTableGet(&result);
- assert(result);
- return result;
-}
-
// Associates an opcode with its name.
struct SpecConstantOpcodeEntry {
SpvOp opcode;
namespace libspirv {
-AssemblyGrammar::AssemblyGrammar()
- : AssemblyGrammar(GetDefaultOperandTable(), GetDefaultOpcodeTable(),
- GetDefaultExtInstTable()) {
- assert(isValid());
-}
-
bool AssemblyGrammar::isValid() const {
return operandTable_ && opcodeTable_ && extInstTable_;
}
// Contains methods to query for valid instructions and operands.
class AssemblyGrammar {
public:
- AssemblyGrammar(const spv_operand_table operand_table,
- const spv_opcode_table opcode_table,
- const spv_ext_inst_table ext_inst_table)
- : operandTable_(operand_table),
- opcodeTable_(opcode_table),
- extInstTable_(ext_inst_table) {}
-
- // Constructor that gets the required data itself.
- AssemblyGrammar();
+ AssemblyGrammar(const spv_const_context context)
+ : operandTable_(context->operand_table),
+ opcodeTable_(context->opcode_table),
+ extInstTable_(context->ext_inst_table) {}
// Returns true if the internal tables have been initialized with valid data.
bool isValid() const;
class Parser {
public:
// The user_data value is provided to the callbacks as context.
- Parser(void* user_data, spv_parsed_header_fn_t parsed_header_fn,
+ Parser(const spv_const_context context, void* user_data,
+ spv_parsed_header_fn_t parsed_header_fn,
spv_parsed_instruction_fn_t parsed_instruction_fn)
- : user_data_(user_data),
+ : grammar_(context),
+ user_data_(user_data),
parsed_header_fn_(parsed_header_fn),
parsed_instruction_fn_(parsed_instruction_fn) {}
} // anonymous namespace
-spv_result_t spvBinaryParse(void* user_data, const uint32_t* code,
- const size_t num_words,
+spv_result_t spvBinaryParse(const spv_const_context context, void* user_data,
+ const uint32_t* code, const size_t num_words,
spv_parsed_header_fn_t parsed_header,
spv_parsed_instruction_fn_t parsed_instruction,
spv_diagnostic* diagnostic) {
- Parser parser(user_data, parsed_header, parsed_instruction);
+ Parser parser(context, user_data, parsed_header, parsed_instruction);
return parser.parse(code, num_words, diagnostic);
}
} // anonymous namespace
-spv_result_t spvBinaryToText(const uint32_t* code, const size_t wordCount,
+spv_result_t spvBinaryToText(const spv_const_context context,
+ const uint32_t* code, const size_t wordCount,
const uint32_t options, spv_text* pText,
spv_diagnostic* pDiagnostic) {
// Invalid arguments return error codes, but don't necessarily generate
// diagnostics. These are programmer errors, not user errors.
if (!pDiagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC;
- const libspirv::AssemblyGrammar grammar;
+ const libspirv::AssemblyGrammar grammar(context);
if (!grammar.isValid()) return SPV_ERROR_INVALID_TABLE;
Disassembler disassembler(grammar, code, wordCount, options);
- if (auto error =
- spvBinaryParse(&disassembler, code, wordCount, DisassembleHeader,
- DisassembleInstruction, pDiagnostic)) {
+ if (auto error = spvBinaryParse(context, &disassembler, code, wordCount,
+ DisassembleHeader, DisassembleInstruction,
+ pDiagnostic)) {
return error;
}
#include <assert.h>
#include <string.h>
+#include <cstdlib>
+
#include "endian.h"
#include "instruction.h"
#include "libspirv/libspirv.h"
//
// TODO(dneto): Some of the macros are quite unreadable. We could make
// good use of constexpr functions, but some compilers don't support that yet.
-spv_opcode_desc_t opcodeTableEntries[] = {
+const spv_opcode_desc_t opcodeTableEntries[] = {
#define EmptyList \
{}
#define List(...) \
#undef Instruction
};
-// Has the opcodeTableEntries table been fully elaborated?
-// That is, are the operandTypes fields initialized?
-bool opcodeTableInitialized = false;
-
// Opcode API
// Converts the given operand class enum (from the SPIR-V document generation
} // anonymous namespace
// Finish populating the opcodeTableEntries array.
-void spvOpcodeTableInitialize() {
+void spvOpcodeTableInitialize(spv_opcode_desc_t* entries,
+ uint32_t num_entries) {
// Compute the operandTypes field for each entry.
- for (auto& opcode : opcodeTableEntries) {
+ for (uint32_t i = 0; i < num_entries; ++i) {
+ spv_opcode_desc_t& opcode = entries[i];
opcode.numTypes = 0;
// Type ID always comes first, if present.
if (opcode.hasType)
"Operand class list is too long. Expand "
"spv_opcode_desc_t.operandClass");
}
- opcodeTableInitialized = true;
}
const char* spvGeneratorStr(uint32_t generator) {
spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable) {
if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
- static spv_opcode_table_t table = {
- sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
- opcodeTableEntries};
+ const uint32_t size = sizeof(opcodeTableEntries);
+ spv_opcode_desc_t* copied_entries =
+ static_cast<spv_opcode_desc_t*>(::malloc(size));
+ if (!copied_entries) return SPV_ERROR_OUT_OF_MEMORY;
+ ::memcpy(copied_entries, opcodeTableEntries, size);
+
+ const uint32_t count = sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t);
+ spv_opcode_table_t* table = new spv_opcode_table_t{count, copied_entries};
- // TODO(dneto): Consider thread safety of initialization.
- // That is, ordering effects of the flag vs. the table updates.
- if (!opcodeTableInitialized) spvOpcodeTableInitialize();
+ spvOpcodeTableInitialize(copied_entries, count);
- *pInstTable = &table;
+ *pInstTable = table;
return SPV_SUCCESS;
}
--- /dev/null
+// Copyright (c) 2015 The Khronos Group 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.
+
+#include "table.h"
+
+#include <cstdlib>
+
+spv_context spvContextCreate() {
+ spv_opcode_table opcode_table;
+ spv_operand_table operand_table;
+ spv_ext_inst_table ext_inst_table;
+
+ spvOpcodeTableGet(&opcode_table);
+ spvOperandTableGet(&operand_table);
+ spvExtInstTableGet(&ext_inst_table);
+
+ return new spv_context_t{opcode_table, operand_table, ext_inst_table};
+}
+
+void spvContextDestroy(spv_context context) {
+ ::free(context->opcode_table->entries);
+ delete context->opcode_table;
+ delete context;
+}
typedef struct spv_opcode_table_t {
const uint32_t count;
- const spv_opcode_desc_t* entries;
+ spv_opcode_desc_t* entries;
} spv_opcode_table_t;
typedef struct spv_operand_table_t {
typedef const spv_operand_table_t* spv_operand_table;
typedef const spv_ext_inst_table_t* spv_ext_inst_table;
+struct spv_context_t {
+ const spv_opcode_table opcode_table;
+ const spv_operand_table operand_table;
+ const spv_ext_inst_table ext_inst_table;
+};
+
/// @brief Populate the Opcode table
///
/// @param[out] pOpcodeTable table to be populated
} // anonymous namespace
-spv_result_t spvTextToBinary(const char* input_text,
+spv_result_t spvTextToBinary(const spv_const_context context,
+ const char* input_text,
const size_t input_text_size, spv_binary* pBinary,
spv_diagnostic* pDiagnostic) {
spv_text_t text = {input_text, input_text_size};
- libspirv::AssemblyGrammar grammar;
+ libspirv::AssemblyGrammar grammar(context);
spv_result_t result =
spvTextToBinaryInternal(grammar, &text, pBinary, pDiagnostic);
return SPV_SUCCESS;
}
-spv_result_t spvValidate(const spv_const_binary binary, const uint32_t options,
+spv_result_t spvValidate(const spv_const_context context,
+ const spv_const_binary binary, const uint32_t options,
spv_diagnostic* pDiagnostic) {
if (!pDiagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC;
- spv_opcode_table opcode_table = nullptr;
- spvOpcodeTableGet(&opcode_table);
- assert(opcode_table);
-
- spv_operand_table operand_table = nullptr;
- spvOperandTableGet(&operand_table);
- assert(operand_table);
-
- spv_ext_inst_table ext_inst_table = nullptr;
- spvExtInstTableGet(&ext_inst_table);
- assert(ext_inst_table);
spv_endianness_t endian;
spv_position_t position = {};
if (spvIsInBitfield(SPV_VALIDATE_BASIC_BIT, options)) {
position.index = SPV_INDEX_INSTRUCTION;
// TODO: Imcomplete implementation
- spvCheckReturn(spvValidateBasic(instructions.data(), instructions.size(),
- opcode_table, operand_table, &position,
- pDiagnostic));
+ spvCheckReturn(spvValidateBasic(
+ instructions.data(), instructions.size(), context->opcode_table,
+ context->operand_table, &position, pDiagnostic));
}
if (spvIsInBitfield(SPV_VALIDATE_LAYOUT_BIT, options)) {
if (spvIsInBitfield(SPV_VALIDATE_ID_BIT, options)) {
position.index = SPV_INDEX_INSTRUCTION;
- spvCheckReturn(spvValidateIDs(instructions.data(), instructions.size(),
- header.bound, opcode_table, operand_table,
- ext_inst_table, &position, pDiagnostic));
+ spvCheckReturn(
+ spvValidateIDs(instructions.data(), instructions.size(), header.bound,
+ context->opcode_table, context->operand_table,
+ context->ext_inst_table, &position, pDiagnostic));
}
if (spvIsInBitfield(SPV_VALIDATE_RULES_BIT, options)) {
TEST_F(TextToBinaryTest, NotPlacingResultIDAtTheBeginning) {
SetText("OpTypeMatrix %1 %2 1000");
- EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
- spvTextToBinary(text.str, text.length, &binary, &diagnostic));
+ EXPECT_EQ(
+ SPV_ERROR_INVALID_TEXT,
+ spvTextToBinary(context, text.str, text.length, &binary, &diagnostic));
ASSERT_NE(nullptr, diagnostic);
EXPECT_STREQ(
"Expected <result-id> at the beginning of an instruction, found "
// Checks safety of destroying a validly constructed binary.
TEST_F(BinaryDestroySomething, Default) {
+ spv_context context = spvContextCreate();
// Use a binary object constructed by the API instead of rolling our own.
SetText("OpSource OpenCL_C 120");
spv_binary my_binary = nullptr;
- ASSERT_EQ(SPV_SUCCESS,
- spvTextToBinary(text.str, text.length, &my_binary, &diagnostic));
+ ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, text.str, text.length,
+ &my_binary, &diagnostic));
ASSERT_NE(nullptr, my_binary);
spvBinaryDestroy(my_binary);
+ spvContextDestroy(context);
}
} // anonymous namespace
namespace {
class BinaryToText : public ::testing::Test {
public:
+ BinaryToText() : context(spvContextCreate()) {}
+ ~BinaryToText() { spvContextDestroy(context); }
+
virtual void SetUp() {
const char* textStr = R"(
OpSource OpenCL_C 12
spv_text_t text = {textStr, strlen(textStr)};
spv_diagnostic diagnostic = nullptr;
spv_result_t error =
- spvTextToBinary(text.str, text.length, &binary, &diagnostic);
+ spvTextToBinary(context, text.str, text.length, &binary, &diagnostic);
if (error) {
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
// Compiles the given assembly text, and saves it into 'binary'.
void CompileSuccessfully(std::string text) {
spv_diagnostic diagnostic = nullptr;
- EXPECT_EQ(SPV_SUCCESS,
- spvTextToBinary(text.c_str(), text.size(), &binary, &diagnostic));
+ EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, text.c_str(), text.size(),
+ &binary, &diagnostic));
}
+ spv_context context;
spv_binary binary;
};
TEST_F(BinaryToText, Default) {
spv_text text = nullptr;
spv_diagnostic diagnostic = nullptr;
- ASSERT_EQ(SPV_SUCCESS, spvBinaryToText(binary->code, binary->wordCount,
- SPV_BINARY_TO_TEXT_OPTION_NONE, &text,
- &diagnostic));
+ ASSERT_EQ(
+ SPV_SUCCESS,
+ spvBinaryToText(context, binary->code, binary->wordCount,
+ SPV_BINARY_TO_TEXT_OPTION_NONE, &text, &diagnostic));
printf("%s", text->str);
spvTextDestroy(text);
}
TEST_F(BinaryToText, MissingModule) {
spv_text text;
spv_diagnostic diagnostic = nullptr;
- EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
- spvBinaryToText(nullptr, 42, SPV_BINARY_TO_TEXT_OPTION_NONE, &text,
- &diagnostic));
+ EXPECT_EQ(
+ SPV_ERROR_INVALID_BINARY,
+ spvBinaryToText(context, nullptr, 42, SPV_BINARY_TO_TEXT_OPTION_NONE,
+ &text, &diagnostic));
EXPECT_THAT(diagnostic->error, Eq(std::string("Missing module.")));
if (diagnostic) {
spvDiagnosticPrint(diagnostic);
spv_diagnostic diagnostic = nullptr;
EXPECT_EQ(
SPV_ERROR_INVALID_BINARY,
- spvBinaryToText(binary->code, length, SPV_BINARY_TO_TEXT_OPTION_NONE,
- &text, &diagnostic));
+ spvBinaryToText(context, binary->code, length,
+ SPV_BINARY_TO_TEXT_OPTION_NONE, &text, &diagnostic));
ASSERT_NE(nullptr, diagnostic);
std::stringstream expected;
expected << "Module has incomplete header: only " << length
spv_text text;
EXPECT_EQ(
SPV_ERROR_INVALID_BINARY,
- spvBinaryToText(damaged_binary.data(), damaged_binary.size(),
+ spvBinaryToText(context, damaged_binary.data(), damaged_binary.size(),
SPV_BINARY_TO_TEXT_OPTION_NONE, &text, &diagnostic));
ASSERT_NE(nullptr, diagnostic);
std::stringstream expected;
TEST_F(BinaryToText, InvalidDiagnostic) {
spv_text text;
ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC,
- spvBinaryToText(binary->code, binary->wordCount,
+ spvBinaryToText(context, binary->code, binary->wordCount,
SPV_BINARY_TO_TEXT_OPTION_NONE, &text, nullptr));
}
using ExtInstGLSLstd450RoundTripTest = ::testing::TestWithParam<ExtInstContext>;
TEST_P(ExtInstGLSLstd450RoundTripTest, ParameterizedExtInst) {
+ spv_context context = spvContextCreate();
const std::string spirv = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
; Schema: 0)";
spv_binary binary;
spv_diagnostic diagnostic;
- spv_result_t error =
- spvTextToBinary(spirv.c_str(), spirv.size(), &binary, &diagnostic);
+ spv_result_t error = spvTextToBinary(context, spirv.c_str(), spirv.size(),
+ &binary, &diagnostic);
if (error) {
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
// Check round trip gives the same text.
spv_text output_text = nullptr;
- error = spvBinaryToText(binary->code, binary->wordCount,
+ error = spvBinaryToText(context, binary->code, binary->wordCount,
SPV_BINARY_TO_TEXT_OPTION_NONE, &output_text,
&diagnostic);
}
EXPECT_EQ(spirv_header + spirv, output_text->str);
spvTextDestroy(output_text);
+ spvContextDestroy(context);
}
static const char* kF32Type = R"(%4 = OpTypeFloat 32)";
TEST_F(TextToBinaryTest, ImmediateIntOpCode) {
SetText("!0x00FF00FF");
- ASSERT_EQ(SPV_SUCCESS,
- spvTextToBinary(text.str, text.length, &binary, &diagnostic));
+ ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(context, text.str, text.length,
+ &binary, &diagnostic));
EXPECT_EQ(0x00FF00FF, binary->code[5]);
if (diagnostic) {
spvDiagnosticPrint(diagnostic);
TEST_F(TextToBinaryTest, ImmediateIntOperand) {
SetText("OpCapability !0x00FF00FF");
- EXPECT_EQ(SPV_SUCCESS,
- spvTextToBinary(text.str, text.length, &binary, &diagnostic));
+ EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, text.str, text.length,
+ &binary, &diagnostic));
EXPECT_EQ(0x00FF00FF, binary->code[6]);
if (diagnostic) {
spvDiagnosticPrint(diagnostic);
namespace {
TEST(NamedId, Default) {
+ spv_context context = spvContextCreate();
const char* spirv = R"(
OpCapability Shader
OpMemoryModel Logical Simple
spv_binary binary = nullptr;
spv_diagnostic diagnostic;
spv_result_t error =
- spvTextToBinary(text.str, text.length, &binary, &diagnostic);
+ spvTextToBinary(context, text.str, text.length, &binary, &diagnostic);
if (error) {
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
ASSERT_EQ(SPV_SUCCESS, error);
}
error = spvBinaryToText(
- binary->code, binary->wordCount,
+ context, binary->code, binary->wordCount,
SPV_BINARY_TO_TEXT_OPTION_PRINT | SPV_BINARY_TO_TEXT_OPTION_COLOR,
nullptr, &diagnostic);
if (error) {
ASSERT_EQ(SPV_SUCCESS, error);
}
spvBinaryDestroy(binary);
+ spvContextDestroy(context);
}
struct IdCheckCase {
// Offset into a SpirvVector at which the first instruction starts.
const SpirvVector::size_type kFirstInstruction = 5;
- TextToBinaryTestBase() : diagnostic(nullptr), text(), binary(nullptr) {
+ TextToBinaryTestBase()
+ : context(spvContextCreate()),
+ diagnostic(nullptr),
+ text(),
+ binary(nullptr) {
char textStr[] = "substitute the text member variable with your test";
text = {textStr, strlen(textStr)};
}
virtual ~TextToBinaryTestBase() {
DestroyBinary();
if (diagnostic) spvDiagnosticDestroy(diagnostic);
+ spvContextDestroy(context);
}
// Returns subvector v[from:end).
// Compiles SPIR-V text in the given assembly syntax format, asserting
// compilation success. Returns the compiled code.
SpirvVector CompileSuccessfully(const std::string& text) {
- spv_result_t status =
- spvTextToBinary(text.c_str(), text.size(), &binary, &diagnostic);
+ spv_result_t status = spvTextToBinary(context, text.c_str(), text.size(),
+ &binary, &diagnostic);
EXPECT_EQ(SPV_SUCCESS, status) << text;
SpirvVector code_copy;
if (status == SPV_SUCCESS) {
// Compiles SPIR-V text with the given format, asserting compilation failure.
// Returns the error message(s).
std::string CompileFailure(const std::string& text) {
- EXPECT_NE(SPV_SUCCESS,
- spvTextToBinary(text.c_str(), text.size(), &binary, &diagnostic))
+ EXPECT_NE(SPV_SUCCESS, spvTextToBinary(context, text.c_str(), text.size(),
+ &binary, &diagnostic))
<< text;
DestroyBinary();
return diagnostic->error;
std::string EncodeAndDecodeSuccessfully(const std::string& text,
uint32_t disassemble_options) {
DestroyBinary();
- spv_result_t error =
- spvTextToBinary(text.c_str(), text.size(), &binary, &diagnostic);
+ spv_result_t error = spvTextToBinary(context, text.c_str(), text.size(),
+ &binary, &diagnostic);
if (error) {
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
if (!binary) return "";
spv_text decoded_text;
- error = spvBinaryToText(binary->code, binary->wordCount,
+ error = spvBinaryToText(context, binary->code, binary->wordCount,
disassemble_options, &decoded_text, &diagnostic);
if (error) {
spvDiagnosticPrint(diagnostic);
spvtest::Concatenate({CompileSuccessfully(text), words_to_append});
spv_text decoded_text;
- EXPECT_NE(SPV_SUCCESS, spvBinaryToText(code.data(), code.size(),
+ EXPECT_NE(SPV_SUCCESS, spvBinaryToText(context, code.data(), code.size(),
SPV_BINARY_TO_TEXT_OPTION_NONE,
&decoded_text, &diagnostic));
if (diagnostic) {
binary = nullptr;
}
+ spv_context context;
spv_diagnostic diagnostic;
std::string textString;
TEST(TextDestroy, DestroyNull) { spvBinaryDestroy(nullptr); }
TEST(TextDestroy, Default) {
+ spv_context context = spvContextCreate();
char textStr[] = R"(
OpSource OpenCL_C 12
OpMemoryModel Physical64 OpenCL
spv_binary binary = nullptr;
spv_diagnostic diagnostic = nullptr;
- EXPECT_EQ(SPV_SUCCESS,
- spvTextToBinary(textStr, strlen(textStr), &binary, &diagnostic));
+ EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(context, textStr, strlen(textStr),
+ &binary, &diagnostic));
EXPECT_NE(nullptr, binary);
EXPECT_NE(nullptr, binary->code);
EXPECT_NE(0, binary->wordCount);
}
spv_text resultText = nullptr;
- EXPECT_EQ(SPV_SUCCESS, spvBinaryToText(binary->code, binary->wordCount, 0,
- &resultText, &diagnostic));
+ EXPECT_EQ(SPV_SUCCESS,
+ spvBinaryToText(context, binary->code, binary->wordCount, 0,
+ &resultText, &diagnostic));
spvBinaryDestroy(binary);
if (diagnostic) {
spvDiagnosticPrint(diagnostic);
EXPECT_NE(nullptr, resultText->str);
EXPECT_NE(0, resultText->length);
spvTextDestroy(resultText);
+ spvContextDestroy(context);
}
} // anonymous namespace
using GoodMaskParseTest = ::testing::TestWithParam<MaskCase>;
TEST_P(GoodMaskParseTest, GoodMaskExpressions) {
- spv_operand_table operandTable;
- ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+ spv_context context = spvContextCreate();
uint32_t value;
- EXPECT_EQ(SPV_SUCCESS, AssemblyGrammar(operandTable, nullptr, nullptr)
- .parseMaskOperand(GetParam().which_enum,
- GetParam().expression, &value));
+ EXPECT_EQ(SPV_SUCCESS,
+ AssemblyGrammar(context).parseMaskOperand(
+ GetParam().which_enum, GetParam().expression, &value));
EXPECT_EQ(GetParam().expected_value, value);
+
+ spvContextDestroy(context);
}
INSTANTIATE_TEST_CASE_P(
using BadFPFastMathMaskParseTest = ::testing::TestWithParam<const char*>;
TEST_P(BadFPFastMathMaskParseTest, BadMaskExpressions) {
- spv_operand_table operandTable;
- ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
+ spv_context context = spvContextCreate();
uint32_t value;
EXPECT_NE(SPV_SUCCESS,
- AssemblyGrammar(operandTable, nullptr, nullptr)
- .parseMaskOperand(SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,
- GetParam(), &value));
+ AssemblyGrammar(context).parseMaskOperand(
+ SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, GetParam(), &value));
+
+ spvContextDestroy(context);
}
INSTANTIATE_TEST_CASE_P(ParseMask, BadFPFastMathMaskParseTest,
TEST_F(TextToBinaryTest, InvalidText) {
spv_binary binary;
ASSERT_EQ(SPV_ERROR_INVALID_TEXT,
- spvTextToBinary(nullptr, 0, &binary, &diagnostic));
+ spvTextToBinary(context, nullptr, 0, &binary, &diagnostic));
EXPECT_NE(nullptr, diagnostic);
EXPECT_THAT(diagnostic->error, Eq(std::string("Missing assembly text.")));
}
TEST_F(TextToBinaryTest, InvalidPointer) {
SetText(
"OpEntryPoint Kernel 0 \"\"\nOpExecutionMode 0 LocalSizeHint 1 1 1\n");
- ASSERT_EQ(SPV_ERROR_INVALID_POINTER,
- spvTextToBinary(text.str, text.length, nullptr, &diagnostic));
+ ASSERT_EQ(
+ SPV_ERROR_INVALID_POINTER,
+ spvTextToBinary(context, text.str, text.length, nullptr, &diagnostic));
}
TEST_F(TextToBinaryTest, InvalidDiagnostic) {
"OpEntryPoint Kernel 0 \"\"\nOpExecutionMode 0 LocalSizeHint 1 1 1\n");
spv_binary binary;
ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC,
- spvTextToBinary(text.str, text.length, &binary, nullptr));
+ spvTextToBinary(context, text.str, text.length, &binary, nullptr));
}
TEST_F(TextToBinaryTest, InvalidPrefix) {
class Validate : public ::testing::Test {
public:
- Validate() : binary() {}
+ Validate() : context(spvContextCreate()), binary() {}
+ ~Validate() { spvContextDestroy(context); }
virtual void TearDown() { spvBinaryDestroy(binary); }
spv_const_binary get_const_binary() { return spv_const_binary(binary); }
+ spv_context context;
spv_binary binary;
};
)";
spv_diagnostic diagnostic = nullptr;
ASSERT_EQ(SPV_SUCCESS,
- spvTextToBinary(str, strlen(str), &binary, &diagnostic));
- ASSERT_EQ(SPV_SUCCESS,
- spvValidate(get_const_binary(), SPV_VALIDATE_ALL, &diagnostic));
+ spvTextToBinary(context, str, strlen(str), &binary, &diagnostic));
+ ASSERT_EQ(SPV_SUCCESS, spvValidate(context, get_const_binary(),
+ SPV_VALIDATE_ALL, &diagnostic));
if (diagnostic) {
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
)";
spv_diagnostic diagnostic = nullptr;
ASSERT_EQ(SPV_SUCCESS,
- spvTextToBinary(str, strlen(str), &binary, &diagnostic));
- ASSERT_EQ(SPV_ERROR_INVALID_ID,
- spvValidate(get_const_binary(), SPV_VALIDATE_ALL, &diagnostic));
+ spvTextToBinary(context, str, strlen(str), &binary, &diagnostic));
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, spvValidate(context, get_const_binary(),
+ SPV_VALIDATE_ALL, &diagnostic));
ASSERT_NE(nullptr, diagnostic);
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
)";
spv_diagnostic diagnostic = nullptr;
ASSERT_EQ(SPV_SUCCESS,
- spvTextToBinary(str, strlen(str), &binary, &diagnostic));
+ spvTextToBinary(context, str, strlen(str), &binary, &diagnostic));
// TODO: Fix setting of bound in spvTextTo, then remove this!
- ASSERT_EQ(SPV_ERROR_INVALID_ID,
- spvValidate(get_const_binary(), SPV_VALIDATE_ALL, &diagnostic));
+ ASSERT_EQ(SPV_ERROR_INVALID_ID, spvValidate(context, get_const_binary(),
+ SPV_VALIDATE_ALL, &diagnostic));
ASSERT_NE(nullptr, diagnostic);
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
spv_binary binary;
};
-#define CHECK(str, expected) \
- spv_diagnostic diagnostic; \
- spv_result_t error = \
- spvTextToBinary(str, strlen(str), &binary, &diagnostic); \
- if (error) { \
- spvDiagnosticPrint(diagnostic); \
- spvDiagnosticDestroy(diagnostic); \
- ASSERT_EQ(SPV_SUCCESS, error); \
- } \
- spv_result_t result = \
- spvValidate(get_const_binary(), SPV_VALIDATE_ID_BIT, &diagnostic); \
- if (SPV_SUCCESS != result) { \
- spvDiagnosticPrint(diagnostic); \
- spvDiagnosticDestroy(diagnostic); \
- } \
- ASSERT_EQ(expected, result);
+#define CHECK(str, expected) \
+ spv_diagnostic diagnostic; \
+ spv_context context = spvContextCreate(); \
+ spv_result_t error = \
+ spvTextToBinary(context, str, strlen(str), &binary, &diagnostic); \
+ if (error) { \
+ spvDiagnosticPrint(diagnostic); \
+ spvDiagnosticDestroy(diagnostic); \
+ ASSERT_EQ(SPV_SUCCESS, error); \
+ } \
+ spv_result_t result = spvValidate(context, get_const_binary(), \
+ SPV_VALIDATE_ID_BIT, &diagnostic); \
+ if (SPV_SUCCESS != result) { \
+ spvDiagnosticPrint(diagnostic); \
+ spvDiagnosticDestroy(diagnostic); \
+ } \
+ ASSERT_EQ(expected, result); \
+ spvContextDestroy(context);
// TODO: OpUndef
spv_binary binary;
spv_diagnostic diagnostic = nullptr;
- spv_result_t error =
- spvTextToBinary(contents.data(), contents.size(), &binary, &diagnostic);
+ spv_context context = spvContextCreate();
+ spv_result_t error = spvTextToBinary(context, contents.data(),
+ contents.size(), &binary, &diagnostic);
+ spvContextDestroy(context);
if (error) {
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
spv_text text;
spv_text* textOrNull = print_to_stdout ? nullptr : &text;
spv_diagnostic diagnostic = nullptr;
- spv_result_t error = spvBinaryToText(contents.data(), contents.size(),
- options, textOrNull, &diagnostic);
+ spv_context context = spvContextCreate();
+ spv_result_t error =
+ spvBinaryToText(context, contents.data(), contents.size(), options,
+ textOrNull, &diagnostic);
+ spvContextDestroy(context);
if (error) {
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);
spv_const_binary_t binary = {contents.data(), contents.size()};
spv_diagnostic diagnostic = nullptr;
- spv_result_t error = spvValidate(&binary, options, &diagnostic);
+ spv_context context = spvContextCreate();
+ spv_result_t error = spvValidate(context, &binary, options, &diagnostic);
+ spvContextDestroy(context);
if (error) {
spvDiagnosticPrint(diagnostic);
spvDiagnosticDestroy(diagnostic);