mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-24 00:40:14 +00:00
Add an API parameter to choose assembly syntax format for assembler.
Added a new enum for supported assembly syntax formats: Canonical Assembly Format (CAF) and Assignment Assembly Format (AAF). Updated assembler interface functions to support choice of assembly syntax format.
This commit is contained in:
parent
92a225b371
commit
06efdc59e1
@ -162,6 +162,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
|
||||
${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
|
||||
|
@ -244,6 +244,12 @@ typedef enum spv_binary_to_text_options_t {
|
||||
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),
|
||||
@ -412,13 +418,32 @@ spv_result_t spvExtInstTableGet(spv_ext_inst_table *pTable);
|
||||
/// @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.
|
||||
|
@ -524,55 +524,64 @@ spv_result_t spvTextEncodeOperand(
|
||||
}
|
||||
|
||||
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.";
|
||||
@ -598,6 +607,14 @@ spv_result_t spvTextEncodeOpcode(
|
||||
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++;
|
||||
@ -669,7 +686,6 @@ spv_result_t spvTextEncodeOpcode(
|
||||
spvCheck(error, return error);
|
||||
|
||||
*position = nextPosition;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -684,6 +700,7 @@ namespace {
|
||||
// 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,
|
||||
@ -716,9 +733,9 @@ spv_result_t spvTextToBinaryInternal(const spv_text text,
|
||||
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;
|
||||
@ -758,16 +775,27 @@ spv_result_t spvTextToBinaryInternal(const spv_text text,
|
||||
|
||||
} // 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;
|
||||
|
@ -191,6 +191,7 @@ spv_result_t spvTextEncodeOperand(
|
||||
/// @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
|
||||
@ -201,9 +202,10 @@ spv_result_t spvTextEncodeOperand(
|
||||
///
|
||||
/// @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
|
||||
|
109
test/AssemblyFormat.cpp
Normal file
109
test/AssemblyFormat.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
// 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
|
@ -62,15 +62,15 @@ TEST_F(TextToBinaryTest, ImmediateIntOperand) {
|
||||
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) {
|
||||
@ -90,37 +90,37 @@ 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"));
|
||||
}
|
||||
|
||||
@ -129,12 +129,11 @@ TEST_F(ImmediateIntTest, StringFollowingImmediate) {
|
||||
// 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 + "\""));
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,40 +141,41 @@ TEST_F(ImmediateIntTest, StringFollowingImmediate) {
|
||||
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
|
||||
)");
|
||||
@ -183,13 +183,13 @@ 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
|
||||
)");
|
||||
@ -200,13 +200,15 @@ 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);
|
||||
@ -215,8 +217,8 @@ OpLoad %10 !1 %2 !0
|
||||
// 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.
|
||||
|
@ -65,12 +65,13 @@ class TextToBinaryTestBase : public T {
|
||||
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) {
|
||||
@ -81,6 +82,18 @@ class TextToBinaryTestBase : public T {
|
||||
}
|
||||
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).
|
||||
|
@ -28,9 +28,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(TextDestroy, DestroyNull) {
|
||||
spvBinaryDestroy(nullptr);
|
||||
}
|
||||
TEST(TextDestroy, DestroyNull) { spvBinaryDestroy(nullptr); }
|
||||
|
||||
TEST(TextDestroy, Default) {
|
||||
spv_opcode_table opcodeTable;
|
||||
@ -67,8 +65,9 @@ TEST(TextDestroy, Default) {
|
||||
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);
|
||||
|
@ -262,37 +262,6 @@ TEST_F(TextToBinaryTest, StringSpace) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -357,8 +326,7 @@ TEST_F(TextToBinaryTest, WrongOpCode) {
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -411,7 +411,7 @@ TEST_F(ValidateID, OpConstantTrueBad) {
|
||||
|
||||
TEST_F(ValidateID, OpConstantFalseGood) {
|
||||
const char *spirv = R"(
|
||||
OpTypeBool %1
|
||||
%1 = OpTypeBool
|
||||
%2 = OpConstantTrue %1)";
|
||||
CHECK(spirv, SPV_SUCCESS);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user