${CMAKE_CURRENT_SOURCE_DIR}/test/TestFixture.h
${CMAKE_CURRENT_SOURCE_DIR}/test/UnitSPIRV.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/test/AssemblyFormat.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryDestroy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryEndianness.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryHeaderGet.cpp
SPV_FORCE_32_BIT_ENUM(spv_binary_to_text_options_t)
} spv_binary_to_text_options_t;
+typedef enum spv_assembly_syntax_format_t {
+ SPV_ASSEMBLY_SYNTAX_FORMAT_ASSIGNMENT, // Assignment Assembly Format
+ SPV_ASSEMBLY_SYNTAX_FORMAT_CANONICAL, // Canonical Assembly Format
+ SPV_ASSEMBLY_SYNTAX_FORMAT_DEFAULT = SPV_ASSEMBLY_SYNTAX_FORMAT_ASSIGNMENT,
+} spv_assembly_syntax_format_t;
+
typedef enum spv_validate_options_t {
SPV_VALIDATE_BASIC_BIT = SPV_BIT(0),
SPV_VALIDATE_LAYOUT_BIT = SPV_BIT(1),
/// @param[out] pDiagnostic contains diagnostic on failure
///
/// @return result code
-spv_result_t spvTextToBinary(const char* text,
- const uint64_t length,
+spv_result_t spvTextToBinary(const char *text, const uint64_t length,
const spv_opcode_table opcodeTable,
const spv_operand_table operandTable,
const spv_ext_inst_table extInstTable,
spv_binary *pBinary, spv_diagnostic *pDiagnostic);
+/// @brief Entry point to covert text form to binary form
+///
+/// @param[in] text input text
+/// @param[in] length of the input text
+/// @param[in] format the assembly syntax format of text
+/// @param[in] opcodeTable of specified Opcodes
+/// @param[in] operandTable of specified operands
+/// @param[in] extInstTable of specified extended instructions
+/// @param[out] pBinary the binary module
+/// @param[out] pDiagnostic contains diagnostic on failure
+///
+/// @return result code
+spv_result_t spvTextWithFormatToBinary(const char *text, const uint64_t length,
+ spv_assembly_syntax_format_t format,
+ const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable,
+ spv_binary *pBinary,
+ spv_diagnostic *pDiagnostic);
+
/// @brief Free an allocated text stream
///
/// This is a no-op if the text parameter is a null pointer.
}
spv_result_t spvTextEncodeOpcode(
- const spv_text text, const spv_opcode_table opcodeTable,
- const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
- spv_named_id_table namedIdTable, uint32_t *pBound, spv_instruction_t *pInst,
- spv_position position, spv_diagnostic *pDiagnostic) {
+ const spv_text text, spv_assembly_syntax_format_t format,
+ const spv_opcode_table opcodeTable, const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable, spv_named_id_table namedIdTable,
+ uint32_t *pBound, spv_instruction_t *pInst, spv_position position,
+ spv_diagnostic *pDiagnostic) {
// An assembly instruction has two possible formats:
- // 1. <opcode> <operand>.., e.g., "OpMemoryModel Physical64 OpenCL".
- // 2. <result-id> = <opcode> <operand>.., e.g., "%void = OpTypeVoid".
+ // 1(CAF): <opcode> <operand>..., e.g., "OpTypeVoid %void".
+ // 2(AAF): <result-id> = <opcode> <operand>..., e.g., "%void = OpTypeVoid".
- // Assume it's the first format at the beginning.
- std::string opcodeName;
+ std::string firstWord;
spv_position_t nextPosition = {};
- spv_result_t error =
- spvTextWordGet(text, position, opcodeName, &nextPosition);
+ spv_result_t error = spvTextWordGet(text, position, firstWord, &nextPosition);
spvCheck(error, DIAGNOSTIC << "Internal Error"; return error);
// NOTE: Handle insertion of an immediate integer into the binary stream
if ('!' == text->str[position->index]) {
- const char *begin = opcodeName.data() + 1;
+ const char *begin = firstWord.data() + 1;
char *end = nullptr;
uint32_t immediateInt = strtoul(begin, &end, 0);
- size_t size = opcodeName.size() - 1;
+ size_t size = firstWord.size() - 1;
spvCheck(size != (size_t)(end - begin),
- DIAGNOSTIC << "Invalid immediate integer '" << opcodeName << "'.";
+ DIAGNOSTIC << "Invalid immediate integer '" << firstWord << "'.";
return SPV_ERROR_INVALID_TEXT);
- position->column += opcodeName.size();
- position->index += opcodeName.size();
+ position->column += firstWord.size();
+ position->index += firstWord.size();
pInst->words[0] = immediateInt;
pInst->wordCount = 1;
return SPV_SUCCESS;
}
- // Handle value generating instructions (the second format above) here.
+ std::string opcodeName;
std::string result_id;
spv_position_t result_id_position = {};
- // If the word we get doesn't start with "Op", assume it's an <result-id>
- // from now.
- spvCheck(!spvStartsWithOp(text, position), result_id = opcodeName);
- if (!result_id.empty()) {
+ if (spvStartsWithOp(text, position)) {
+ opcodeName = firstWord;
+ } else {
+ // If the first word of this instruction is not an opcode, we must be
+ // processing AAF now.
+ spvCheck(
+ SPV_ASSEMBLY_SYNTAX_FORMAT_ASSIGNMENT != format,
+ DIAGNOSTIC
+ << "Expected <opcode> at the beginning of an instruction, found '"
+ << firstWord << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+
+ result_id = firstWord;
spvCheck('%' != result_id.front(),
DIAGNOSTIC << "Expected <opcode> or <result-id> at the beginning "
"of an instruction, found '"
<< result_id << "'.";
return SPV_ERROR_INVALID_TEXT);
result_id_position = *position;
+
+ // The '=' sign.
*position = nextPosition;
spvCheck(spvTextAdvance(text, position),
DIAGNOSTIC << "Expected '=', found end of stream.";
return SPV_ERROR_INVALID_TEXT);
- // The '=' sign.
std::string equal_sign;
error = spvTextWordGet(text, position, equal_sign, &nextPosition);
spvCheck("=" != equal_sign, DIAGNOSTIC << "'=' expected after result id.";
spvCheck(error, DIAGNOSTIC << "Invalid Opcode name '"
<< getWord(text->str + position->index) << "'";
return error);
+ if (SPV_ASSEMBLY_SYNTAX_FORMAT_ASSIGNMENT == format) {
+ // If this instruction has <result-id>, check it follows AAF.
+ spvCheck(opcodeEntry->hasResult && result_id.empty(),
+ DIAGNOSTIC << "Expected <result-id> at the beginning of an "
+ "instruction, found '"
+ << firstWord << "'.";
+ return SPV_ERROR_INVALID_TEXT);
+ }
pInst->opcode = opcodeEntry->opcode;
*position = nextPosition;
pInst->wordCount++;
spvCheck(error, return error);
*position = nextPosition;
-
}
}
// If a diagnostic is generated, it is not yet marked as being
// for a text-based input.
spv_result_t spvTextToBinaryInternal(const spv_text text,
+ spv_assembly_syntax_format_t format,
const spv_opcode_table opcodeTable,
const spv_operand_table operandTable,
const spv_ext_inst_table extInstTable,
spv_instruction_t inst = {};
inst.extInstType = extInstType;
- spvCheck(spvTextEncodeOpcode(text, opcodeTable, operandTable, extInstTable,
- namedIdTable, &bound, &inst, &position,
- pDiagnostic),
+ spvCheck(spvTextEncodeOpcode(text, format, opcodeTable, operandTable,
+ extInstTable, namedIdTable, &bound, &inst,
+ &position, pDiagnostic),
spvNamedIdTableDestory(namedIdTable);
return SPV_ERROR_INVALID_TEXT);
extInstType = inst.extInstType;
} // anonymous namespace
-spv_result_t spvTextToBinary(const char* input_text,
+spv_result_t spvTextToBinary(const char *input_text,
const uint64_t input_text_size,
const spv_opcode_table opcodeTable,
const spv_operand_table operandTable,
const spv_ext_inst_table extInstTable,
spv_binary *pBinary, spv_diagnostic *pDiagnostic) {
+ return spvTextWithFormatToBinary(
+ input_text, input_text_size, SPV_ASSEMBLY_SYNTAX_FORMAT_DEFAULT,
+ opcodeTable, operandTable, extInstTable, pBinary, pDiagnostic);
+}
+
+spv_result_t spvTextWithFormatToBinary(
+ const char *input_text, const uint64_t input_text_size,
+ spv_assembly_syntax_format_t format, const spv_opcode_table opcodeTable,
+ const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
+ spv_binary *pBinary, spv_diagnostic *pDiagnostic) {
spv_text_t text = {input_text, input_text_size};
- spv_result_t result = spvTextToBinaryInternal(
- &text, opcodeTable, operandTable, extInstTable, pBinary, pDiagnostic);
+ spv_result_t result =
+ spvTextToBinaryInternal(&text, format, opcodeTable, operandTable,
+ extInstTable, pBinary, pDiagnostic);
if (pDiagnostic && *pDiagnostic) (*pDiagnostic)->isTextSource = true;
return result;
/// @brief Translate single Opcode and operands to binary form
///
/// @param[in] text stream to translate
+/// @param[in] format the assembly syntax format of text
/// @param[in] opcodeTable Opcode lookup table
/// @param[in] operandTable operand lookup table
/// @param[in,out] namedIdTable table of named ID's
///
/// @return result code
spv_result_t spvTextEncodeOpcode(
- const spv_text text, const spv_opcode_table opcodeTable,
- const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
- spv_named_id_table namedIdTable, uint32_t *pBound, spv_instruction_t *pInst,
- spv_position_t *pPosition, spv_diagnostic *pDiagnostic);
+ const spv_text text, spv_assembly_syntax_format_t format,
+ const spv_opcode_table opcodeTable, const spv_operand_table operandTable,
+ const spv_ext_inst_table extInstTable, spv_named_id_table namedIdTable,
+ uint32_t *pBound, spv_instruction_t *pInst, spv_position_t *pPosition,
+ spv_diagnostic *pDiagnostic);
#endif
--- /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 "TestFixture.h"
+
+namespace {
+
+using test_fixture::TextToBinaryTest;
+
+TEST_F(TextToBinaryTest, EncodeAAFTextAsAAF) {
+ SetText("%2 = OpConstant %1 1000");
+ EXPECT_EQ(SPV_SUCCESS,
+ spvTextWithFormatToBinary(
+ text.str, text.length, SPV_ASSEMBLY_SYNTAX_FORMAT_ASSIGNMENT,
+ opcodeTable, operandTable, extInstTable, &binary, &diagnostic));
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ }
+}
+
+TEST_F(TextToBinaryTest, EncodeAAFTextAsCAF) {
+ SetText("%2 = OpConstant %1 1000");
+ EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
+ spvTextWithFormatToBinary(
+ text.str, text.length, SPV_ASSEMBLY_SYNTAX_FORMAT_CANONICAL,
+ opcodeTable, operandTable, extInstTable, &binary, &diagnostic));
+ ASSERT_TRUE(diagnostic);
+ EXPECT_STREQ(
+ "Expected <opcode> at the beginning of an instruction, found '%2'.",
+ diagnostic->error);
+ EXPECT_EQ(0, diagnostic->position.line);
+}
+
+TEST_F(TextToBinaryTest, EncodeCAFTextAsCAF) {
+ SetText("OpConstant %1 %2 1000");
+ EXPECT_EQ(SPV_SUCCESS,
+ spvTextWithFormatToBinary(
+ text.str, text.length, SPV_ASSEMBLY_SYNTAX_FORMAT_CANONICAL,
+ opcodeTable, operandTable, extInstTable, &binary, &diagnostic));
+ if (diagnostic) {
+ spvDiagnosticPrint(diagnostic);
+ }
+}
+
+TEST_F(TextToBinaryTest, EncodeCAFTextAsAAF) {
+ SetText("OpConstant %1 %2 1000");
+ EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
+ spvTextWithFormatToBinary(
+ text.str, text.length, SPV_ASSEMBLY_SYNTAX_FORMAT_ASSIGNMENT,
+ opcodeTable, operandTable, extInstTable, &binary, &diagnostic));
+ ASSERT_TRUE(diagnostic);
+ EXPECT_STREQ(
+ "Expected <result-id> at the beginning of an instruction, found "
+ "'OpConstant'.",
+ diagnostic->error);
+ EXPECT_EQ(0, diagnostic->position.line);
+}
+
+TEST_F(TextToBinaryTest, EncodeMixedTextAsAAF) {
+ SetText("OpConstant %1 %2 1000\n%3 = OpConstant %1 2000");
+ EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
+ spvTextWithFormatToBinary(
+ text.str, text.length, SPV_ASSEMBLY_SYNTAX_FORMAT_ASSIGNMENT,
+ opcodeTable, operandTable, extInstTable, &binary, &diagnostic));
+ ASSERT_TRUE(diagnostic);
+ EXPECT_STREQ(
+ "Expected <result-id> at the beginning of an instruction, found "
+ "'OpConstant'.",
+ diagnostic->error);
+ EXPECT_EQ(0, diagnostic->position.line);
+}
+
+TEST_F(TextToBinaryTest, EncodeMixedTextAsCAF) {
+ SetText("OpConstant %1 %2 1000\n%3 = OpConstant %1 2000");
+ EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
+ spvTextWithFormatToBinary(
+ text.str, text.length, SPV_ASSEMBLY_SYNTAX_FORMAT_CANONICAL,
+ opcodeTable, operandTable, extInstTable, &binary, &diagnostic));
+ ASSERT_TRUE(diagnostic);
+ EXPECT_STREQ(
+ "Expected <opcode> at the beginning of an instruction, found '%3'.",
+ diagnostic->error);
+ EXPECT_EQ(1, diagnostic->position.line);
+}
+
+} // anonymous namespace
using ImmediateIntTest = TextToBinaryTest;
TEST_F(ImmediateIntTest, AnyWordInSimpleStatement) {
- const SpirvVector original = CompileSuccessfully("OpConstant %1 %2 123");
+ const SpirvVector original = CompileCAFSuccessfully("OpConstant %1 %2 123");
// TODO(deki): uncomment assertions below and make them pass.
- // EXPECT_EQ(original, CompileSuccessfully("!0x0004002B %1 %2 123"));
- EXPECT_EQ(original, CompileSuccessfully("OpConstant !1 %2 123"));
- // EXPECT_EQ(original, CompileSuccessfully("OpConstant %1 !2 123"));
- EXPECT_EQ(original, CompileSuccessfully("OpConstant %1 %2 !123"));
- // EXPECT_EQ(original, CompileSuccessfully("!0x0004002B %1 !2 123"));
- EXPECT_EQ(original, CompileSuccessfully("OpConstant !1 %2 !123"));
- // EXPECT_EQ(original, CompileSuccessfully("!0x0004002B !1 !2 !123"));
+ // EXPECT_EQ(original, CompileCAFSuccessfully("!0x0004002B %1 %2 123"));
+ EXPECT_EQ(original, CompileCAFSuccessfully("OpConstant !1 %2 123"));
+ // EXPECT_EQ(original, CompileCAFSuccessfully("OpConstant %1 !2 123"));
+ EXPECT_EQ(original, CompileCAFSuccessfully("OpConstant %1 %2 !123"));
+ // EXPECT_EQ(original, CompileCAFSuccessfully("!0x0004002B %1 !2 123"));
+ EXPECT_EQ(original, CompileCAFSuccessfully("OpConstant !1 %2 !123"));
+ // EXPECT_EQ(original, CompileCAFSuccessfully("!0x0004002B !1 !2 !123"));
}
TEST_F(ImmediateIntTest, AnyWordInAssignmentStatement) {
// Literal integers after !<integer> are handled correctly.
TEST_F(ImmediateIntTest, IntegerFollowingImmediate) {
- const SpirvVector original = CompileSuccessfully("OpTypeInt %1 8 1");
+ const SpirvVector original = CompileCAFSuccessfully("OpTypeInt %1 8 1");
// TODO(deki): uncomment assertions below and make them pass.
- // EXPECT_EQ(original, CompileSuccessfully("!0x00040015 1 8 1"));
- // EXPECT_EQ(original, CompileSuccessfully("OpTypeInt !1 8 1"));
+ // EXPECT_EQ(original, CompileCAFSuccessfully("!0x00040015 1 8 1"));
+ // EXPECT_EQ(original, CompileCAFSuccessfully("OpTypeInt !1 8 1"));
// 64-bit integer literal.
- EXPECT_EQ(CompileSuccessfully("OpConstant %10 %1 5000000000"),
- CompileSuccessfully("OpConstant %10 !1 5000000000"));
+ EXPECT_EQ(CompileCAFSuccessfully("OpConstant %10 %1 5000000000"),
+ CompileCAFSuccessfully("OpConstant %10 !1 5000000000"));
// Negative integer.
- EXPECT_EQ(CompileSuccessfully("OpConstant %10 %1 -123"),
- CompileSuccessfully("OpConstant %10 !1 -123"));
+ EXPECT_EQ(CompileCAFSuccessfully("OpConstant %10 %1 -123"),
+ CompileCAFSuccessfully("OpConstant %10 !1 -123"));
// Hex value(s).
- // EXPECT_EQ(CompileSuccessfully("OpConstant %10 %1 0x12345678"),
- // CompileSuccessfully("OpConstant %10 !1 0x12345678"));
- // EXPECT_EQ(CompileSuccessfully("OpConstant %10 %1 0x12345678 0x87654321"),
- // CompileSuccessfully("OpConstant %10 !1 0x12345678 0x87654321"));
+ // EXPECT_EQ(CompileCAFSuccessfully("OpConstant %10 %1 0x12345678"),
+ // CompileCAFSuccessfully("OpConstant %10 !1 0x12345678"));
+ // EXPECT_EQ(CompileCAFSuccessfully("OpConstant %10 %1 0x12345678 0x87654321"),
+ // CompileCAFSuccessfully("OpConstant %10 !1 0x12345678 0x87654321"));
}
// Literal floats after !<integer> are handled correctly.
TEST_F(ImmediateIntTest, FloatFollowingImmediate) {
- EXPECT_EQ(CompileSuccessfully("OpConstant %10 %1 0.123"),
- CompileSuccessfully("OpConstant %10 !1 0.123"));
- EXPECT_EQ(CompileSuccessfully("OpConstant %10 %1 -0.5"),
- CompileSuccessfully("OpConstant %10 !1 -0.5"));
+ EXPECT_EQ(CompileCAFSuccessfully("OpConstant %10 %1 0.123"),
+ CompileCAFSuccessfully("OpConstant %10 !1 0.123"));
+ EXPECT_EQ(CompileCAFSuccessfully("OpConstant %10 %1 -0.5"),
+ CompileCAFSuccessfully("OpConstant %10 !1 -0.5"));
// 64-bit float.
EXPECT_EQ(
- CompileSuccessfully(
+ CompileCAFSuccessfully(
"OpConstant %10 %1 9999999999999999999999999999999999999999.9"),
- CompileSuccessfully(
+ CompileCAFSuccessfully(
"OpConstant %10 !1 9999999999999999999999999999999999999999.9"));
}
// Try a variety of strings, including empty and single-character.
for (std::string name : {"", "s", "longish"}) {
const SpirvVector original =
- CompileSuccessfully("OpMemberName %10 4 \"" + name + "\"");
+ CompileCAFSuccessfully("OpMemberName %10 4 \"" + name + "\"");
EXPECT_EQ(original,
- CompileSuccessfully("OpMemberName %10 !4 \"" + name + "\""));
+ CompileCAFSuccessfully("OpMemberName %10 !4 \"" + name + "\""));
// TODO(deki): uncomment assertions below and make them pass.
- // EXPECT_EQ(original,
- // CompileSuccessfully("!0x00040006 !10 4 \"" + name + "\""));
+ // EXPECT_EQ(original, CompileCAFSuccessfully("!0x00040006 !10 4 \"" + name + "\""));
}
}
TEST_F(ImmediateIntTest, IdFollowingImmediate) {
// TODO(deki): uncomment assertions below and make them pass.
#if 0
- EXPECT_EQ(CompileSuccessfully("OpDecorationGroup %123"),
- CompileSuccessfully("!0x00020049 %123"));
- EXPECT_EQ(CompileSuccessfully("OpDecorationGroup %group"),
- CompileSuccessfully("!0x00020049 %group"));
+ EXPECT_EQ(CompileCAFSuccessfully("OpDecorationGroup %123"),
+ CompileCAFSuccessfully("!0x00020049 %123"));
+ EXPECT_EQ(CompileCAFSuccessfully("OpDecorationGroup %group"),
+ CompileCAFSuccessfully("!0x00020049 %group"));
#endif
}
// !<integer> after !<integer> is handled correctly.
TEST_F(ImmediateIntTest, ImmediateFollowingImmediate) {
- const SpirvVector original = CompileSuccessfully("OpTypeMatrix %11 %10 7");
- EXPECT_EQ(original, CompileSuccessfully("OpTypeMatrix %11 !10 !7"));
+ const SpirvVector original = CompileCAFSuccessfully("OpTypeMatrix %11 %10 7");
+ EXPECT_EQ(original, CompileCAFSuccessfully("OpTypeMatrix %11 !10 !7"));
// TODO(deki): uncomment assertions below and make them pass.
- // EXPECT_EQ(original, CompileSuccessfully("!0x00040018 %11 !10 !7"));
+ // EXPECT_EQ(original, CompileCAFSuccessfully("!0x00040018 %11 !10 !7"));
}
TEST_F(ImmediateIntTest, InvalidStatement) {
- EXPECT_THAT(Subvector(CompileSuccessfully("!4 !3 !2 !1"), kFirstInstruction),
- ElementsAre(4, 3, 2, 1));
+ EXPECT_THAT(
+ Subvector(CompileCAFSuccessfully("!4 !3 !2 !1"), kFirstInstruction),
+ ElementsAre(4, 3, 2, 1));
}
TEST_F(ImmediateIntTest, InvalidStatementBetweenValidOnes) {
- EXPECT_THAT(
- Subvector(CompileSuccessfully("OpTypeFloat %10 32 !5 !6 !7 OpEmitVertex"),
- kFirstInstruction),
- ElementsAre(spvOpcodeMake(3, spv::OpTypeFloat), 10, 32, 5, 6, 7,
- spvOpcodeMake(1, spv::OpEmitVertex)));
+ EXPECT_THAT(Subvector(CompileCAFSuccessfully(
+ "OpTypeFloat %10 32 !5 !6 !7 OpEmitVertex"),
+ kFirstInstruction),
+ ElementsAre(spvOpcodeMake(3, spv::OpTypeFloat), 10, 32, 5, 6, 7,
+ spvOpcodeMake(1, spv::OpEmitVertex)));
}
TEST_F(ImmediateIntTest, NextOpcodeRecognized) {
- const SpirvVector original = CompileSuccessfully(R"(
+ const SpirvVector original = CompileCAFSuccessfully(R"(
OpLoad %10 %1 %2 Volatile
OpCompositeInsert %11 %4 %1 %3 0 1 2
)");
- const SpirvVector alternate = CompileSuccessfully(R"(
+ const SpirvVector alternate = CompileCAFSuccessfully(R"(
OpLoad %10 %1 %2 !1
OpCompositeInsert %11 %4 %1 %3 0 1 2
)");
}
TEST_F(ImmediateIntTest, WrongLengthButNextOpcodeStillRecognized) {
- const SpirvVector original = CompileSuccessfully(R"(
+ const SpirvVector original = CompileCAFSuccessfully(R"(
OpLoad %10 %1 %2 Volatile
OpCopyMemorySized %3 %4 %1
)");
// TODO(deki): uncomment assertions below and make them pass.
#if 0
- const SpirvVector alternate = CompileSuccessfully(R"(
+ const SpirvVector alternate = CompileCAFSuccessfully(R"(
!0x0002003D %10 %1 %2 !1
OpCopyMemorySized %3 %4 %1
)");
}
// Like NextOpcodeRecognized, but next statement is in assignment form.
-TEST_F(ImmediateIntTest, NextAssignmentRecognized) {
+// TODO(deki): enable this after adding proper support for !<integer> at the
+// beginning of an instruction.
+TEST_F(ImmediateIntTest, DISABLED_NextAssignmentRecognized) {
const SpirvVector original = CompileSuccessfully(R"(
-OpLoad %10 %1 %2 None
+%1 = OpLoad %10 %2 None
%4 = OpFunctionCall %10 %3 123
)");
const SpirvVector alternate = CompileSuccessfully(R"(
-OpLoad %10 !1 %2 !0
+!1 = OpLoad %10 %2 !0
%4 = OpFunctionCall %10 %3 123
)");
EXPECT_EQ(original, alternate);
// Two instructions in a row each have !<integer> opcode.
TEST_F(ImmediateIntTest, ConsecutiveImmediateOpcodes) {
const SpirvVector original = CompileSuccessfully(R"(
-OpConstantSampler %10 %1 Clamp 78 Linear
-OpFRem %11 %4 %3 %2
+%1 = OpConstantSampler %10 Clamp 78 Linear
+%4 = OpFRem %11 %3 %2
%5 = OpIsValidEvent %12 %2
)");
// TODO(deki): uncomment assertions below and make them pass.
return SpirvVector(v.begin() + from, v.end());
}
- // Compiles SPIR-V text, asserting compilation success. Returns the compiled
- // code.
- SpirvVector CompileSuccessfully(const std::string& text) {
- spv_result_t status =
- spvTextToBinary(text.c_str(), text.size(), opcodeTable, operandTable,
- extInstTable, &binary, &diagnostic);
+ // Compiles SPIR-V text in the given assembly syntax format, asserting
+ // compilation success. Returns the compiled code.
+ SpirvVector CompileWithFormatSuccessfully(
+ const std::string& text, spv_assembly_syntax_format_t format) {
+ spv_result_t status = spvTextWithFormatToBinary(
+ text.c_str(), text.size(), format, opcodeTable, operandTable,
+ extInstTable, &binary, &diagnostic);
EXPECT_EQ(SPV_SUCCESS, status) << text;
SpirvVector code_copy;
if (status == SPV_SUCCESS) {
}
return code_copy;
}
+ // Compiles SPIR-V text in the Assignment Assembly Format, asserting success.
+ // Returns the compiled code.
+ SpirvVector CompileSuccessfully(const std::string& text) {
+ return CompileWithFormatSuccessfully(text,
+ SPV_ASSEMBLY_SYNTAX_FORMAT_ASSIGNMENT);
+ }
+ // Compiles SPIR-V text in the Canonical Assembly Format, asserting success.
+ // Returns the compiled code.
+ SpirvVector CompileCAFSuccessfully(const std::string& text) {
+ return CompileWithFormatSuccessfully(text,
+ SPV_ASSEMBLY_SYNTAX_FORMAT_CANONICAL);
+ }
// Compiles SPIR-V text, asserting compilation failure. Returns the error
// message(s).
namespace {
-TEST(TextDestroy, DestroyNull) {
- spvBinaryDestroy(nullptr);
-}
+TEST(TextDestroy, DestroyNull) { spvBinaryDestroy(nullptr); }
TEST(TextDestroy, Default) {
spv_opcode_table opcodeTable;
spv_binary binary = nullptr;
spv_diagnostic diagnostic = nullptr;
EXPECT_EQ(SPV_SUCCESS,
- spvTextToBinary(textStr, strlen(textStr), opcodeTable, operandTable,
- extInstTable, &binary, &diagnostic));
+ spvTextWithFormatToBinary(
+ textStr, strlen(textStr), SPV_ASSEMBLY_SYNTAX_FORMAT_CANONICAL,
+ opcodeTable, operandTable, extInstTable, &binary, &diagnostic));
EXPECT_NE(nullptr, binary);
EXPECT_NE(nullptr, binary->code);
EXPECT_NE(0, binary->wordCount);
}
}
-// TODO(antiagainst): we might not want to support both instruction formats in
-// the future. Only the "<result-id> = <opcode> <operand>.." one may survive.
-TEST_F(TextToBinaryTest, InstructionTwoFormats) {
- SetText(R"(
- OpCapability Shader
- %glsl450 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical Simple
- OpTypeBool %3
- %4 = OpTypeInt 8 0
- OpTypeInt %5 8 1
- %6 = OpTypeInt 16 0
- OpTypeInt %7 16 1
- %void = OpTypeVoid
- OpTypeFloat %float 32
-%const1.5 = OpConstant %float 1.5
- OpTypeFunction %fnMain %void
- %main = OpFunction %void None %fnMain
- OpLabel %lbMain
- %result = OpExtInst $float $glsl450 Round $const1.5
- OpReturn
- OpFunctionEnd
-)");
-
- EXPECT_EQ(SPV_SUCCESS,
- spvTextToBinary(text.str, text.length, opcodeTable, operandTable,
- extInstTable, &binary, &diagnostic));
- if (diagnostic) {
- spvDiagnosticPrint(diagnostic);
- }
-}
-
TEST_F(TextToBinaryTest, UnknownBeginningOfInstruction) {
SetText(R"(
OpSource OpenCL 12
}
TEST_F(TextToBinaryTest, GoodSwitch) {
- const SpirvVector code = CompileSuccessfully(
- R"(
+ const SpirvVector code = CompileSuccessfully(R"(
%i32 = OpTypeInt 32 0
%fortytwo = OpConstant %i32 42
%twelve = OpConstant %i32 12
TEST_F(ValidateID, OpConstantFalseGood) {
const char *spirv = R"(
-OpTypeBool %1
+%1 = OpTypeBool
%2 = OpConstantTrue %1)";
CHECK(spirv, SPV_SUCCESS);
}