mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-22 19:50:05 +00:00
Support multiple word literal numbers as constants.
Add a new operand type SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER to represent those operands that can expand into multiple words. Now only OpConstant and OpSpecConstant have such kind of operand.
This commit is contained in:
parent
cebad036f7
commit
b41d150b7f
@ -146,6 +146,8 @@ typedef enum spv_operand_type_t {
|
|||||||
SPV_OPERAND_TYPE_RESULT_ID,
|
SPV_OPERAND_TYPE_RESULT_ID,
|
||||||
SPV_OPERAND_TYPE_LITERAL, // Either a literal number or literal string
|
SPV_OPERAND_TYPE_LITERAL, // Either a literal number or literal string
|
||||||
SPV_OPERAND_TYPE_LITERAL_NUMBER,
|
SPV_OPERAND_TYPE_LITERAL_NUMBER,
|
||||||
|
// A literal number that can (but is not required to) expand multiple words.
|
||||||
|
SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER,
|
||||||
SPV_OPERAND_TYPE_LITERAL_STRING,
|
SPV_OPERAND_TYPE_LITERAL_STRING,
|
||||||
SPV_OPERAND_TYPE_SOURCE_LANGUAGE,
|
SPV_OPERAND_TYPE_SOURCE_LANGUAGE,
|
||||||
SPV_OPERAND_TYPE_EXECUTION_MODEL,
|
SPV_OPERAND_TYPE_EXECUTION_MODEL,
|
||||||
|
@ -83,6 +83,11 @@ uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian) {
|
|||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t spvFixDoubleWord(const uint32_t low, const uint32_t high,
|
||||||
|
const spv_endianness_t endian) {
|
||||||
|
return (uint64_t(spvFixWord(high, endian)) << 32) | spvFixWord(low, endian);
|
||||||
|
}
|
||||||
|
|
||||||
spv_result_t spvBinaryHeaderGet(const spv_binary binary,
|
spv_result_t spvBinaryHeaderGet(const spv_binary binary,
|
||||||
const spv_endianness_t endian,
|
const spv_endianness_t endian,
|
||||||
spv_header_t *pHeader) {
|
spv_header_t *pHeader) {
|
||||||
@ -205,7 +210,7 @@ spv_operand_type_t spvBinaryOperandInfo(const uint32_t word,
|
|||||||
|
|
||||||
spv_result_t spvBinaryDecodeOperand(
|
spv_result_t spvBinaryDecodeOperand(
|
||||||
const Op opcode, const spv_operand_type_t type, const uint32_t *words,
|
const Op opcode, const spv_operand_type_t type, const uint32_t *words,
|
||||||
const spv_endianness_t endian, const uint32_t options,
|
uint16_t numWords, const spv_endianness_t endian, const uint32_t options,
|
||||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||||
spv_operand_pattern_t *pExpectedOperands, spv_ext_inst_type_t *pExtInstType,
|
spv_operand_pattern_t *pExpectedOperands, spv_ext_inst_type_t *pExtInstType,
|
||||||
out_stream &stream, spv_position position, spv_diagnostic *pDiagnostic) {
|
out_stream &stream, spv_position position, spv_diagnostic *pDiagnostic) {
|
||||||
@ -249,14 +254,23 @@ spv_result_t spvBinaryDecodeOperand(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // Fall through for the general case.
|
} // Fall through for the general case.
|
||||||
|
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
|
||||||
case SPV_OPERAND_TYPE_LITERAL:
|
case SPV_OPERAND_TYPE_LITERAL:
|
||||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL:
|
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL:
|
||||||
case SPV_OPERAND_TYPE_LITERAL_IN_OPTIONAL_TUPLE: {
|
case SPV_OPERAND_TYPE_LITERAL_IN_OPTIONAL_TUPLE: {
|
||||||
// TODO: Need to support multiple word literals
|
// TODO: Need to support multiple word literals
|
||||||
stream.get() << (color ? clr::red() : "");
|
stream.get() << (color ? clr::red() : "");
|
||||||
stream.get() << spvFixWord(words[0], endian);
|
if (numWords > 2) {
|
||||||
|
DIAGNOSTIC << "Literal numbers larger than 64-bit not supported yet.";
|
||||||
|
return SPV_UNSUPPORTED;
|
||||||
|
} else if (numWords == 2) {
|
||||||
|
stream.get() << spvFixDoubleWord(words[0], words[1], endian);
|
||||||
|
position->index += 2;
|
||||||
|
} else {
|
||||||
|
stream.get() << spvFixWord(words[0], endian);
|
||||||
|
position->index++;
|
||||||
|
}
|
||||||
stream.get() << (color ? clr::reset() : "");
|
stream.get() << (color ? clr::reset() : "");
|
||||||
position->index++;
|
|
||||||
} break;
|
} break;
|
||||||
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
||||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: {
|
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: {
|
||||||
@ -415,9 +429,25 @@ spv_result_t spvBinaryDecodeOpcode(
|
|||||||
} else {
|
} else {
|
||||||
stream.get() << " ";
|
stream.get() << " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t numWords = 1;
|
||||||
|
if (type == SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER) {
|
||||||
|
// Make sure this is the last operand for this instruction.
|
||||||
|
if (expectedOperands.empty()) {
|
||||||
|
numWords = wordCount - index;
|
||||||
|
} else {
|
||||||
|
// TODO(antiagainst): This may not be an error. The exact design has not
|
||||||
|
// been settled yet.
|
||||||
|
DIAGNOSTIC << "Multiple word literal numbers can only appear as the "
|
||||||
|
"last operand of an instruction.";
|
||||||
|
return SPV_ERROR_INVALID_BINARY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (spvBinaryDecodeOperand(
|
if (spvBinaryDecodeOperand(
|
||||||
opcodeEntry->opcode, type, pInst->words + index, endian, options,
|
opcodeEntry->opcode, type, pInst->words + index, numWords, endian,
|
||||||
operandTable, extInstTable, &expectedOperands, &pInst->extInstType,
|
options, operandTable, extInstTable, &expectedOperands,
|
||||||
|
&pInst->extInstType,
|
||||||
(isAssigmentFormat && !currentIsResultId ? no_result_id_stream
|
(isAssigmentFormat && !currentIsResultId ? no_result_id_stream
|
||||||
: stream),
|
: stream),
|
||||||
position, pDiagnostic)) {
|
position, pDiagnostic)) {
|
||||||
|
@ -41,6 +41,16 @@
|
|||||||
/// @return word with host endianness correction
|
/// @return word with host endianness correction
|
||||||
uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian);
|
uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian);
|
||||||
|
|
||||||
|
/// @brief Fix the endianness of a double word
|
||||||
|
///
|
||||||
|
/// @param[in] low the lower 32-bit of the double word
|
||||||
|
/// @param[in] high the higher 32-bit of the double word
|
||||||
|
/// @param[in] endian the desired endianness
|
||||||
|
///
|
||||||
|
/// @return word with host endianness correction
|
||||||
|
uint64_t spvFixDoubleWord(const uint32_t low, const uint32_t high,
|
||||||
|
const spv_endianness_t endian);
|
||||||
|
|
||||||
/// @brief Determine the endianness of the SPV binary
|
/// @brief Determine the endianness of the SPV binary
|
||||||
///
|
///
|
||||||
/// Gets the endianness of the SPV source. Returns SPV_ENDIANNESS_UNKNOWN if
|
/// Gets the endianness of the SPV source. Returns SPV_ENDIANNESS_UNKNOWN if
|
||||||
@ -141,7 +151,7 @@ spv_operand_type_t spvBinaryOperandInfo(const uint32_t word,
|
|||||||
/// @return result code
|
/// @return result code
|
||||||
spv_result_t spvBinaryDecodeOperand(
|
spv_result_t spvBinaryDecodeOperand(
|
||||||
const Op opcode, const spv_operand_type_t type, const uint32_t *words,
|
const Op opcode, const spv_operand_type_t type, const uint32_t *words,
|
||||||
const spv_endianness_t endian, const uint32_t options,
|
uint16_t numWords, const spv_endianness_t endian, const uint32_t options,
|
||||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||||
spv_operand_pattern_t *pExpectedOperands, spv_ext_inst_type_t *pExtInstType,
|
spv_operand_pattern_t *pExpectedOperands, spv_ext_inst_type_t *pExtInstType,
|
||||||
out_stream &stream, spv_position position, spv_diagnostic *pDiagnostic);
|
out_stream &stream, spv_position position, spv_diagnostic *pDiagnostic);
|
||||||
|
@ -90,6 +90,9 @@ spv_operand_type_t convertOperandClassToType(spv::Op opcode,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (operandClass == OperandVariableLiterals) {
|
||||||
|
if (opcode == spv::OpConstant || opcode == spv::OpSpecConstant)
|
||||||
|
return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(operandClass) {
|
switch(operandClass) {
|
||||||
|
@ -1454,6 +1454,8 @@ const char *spvOperandTypeStr(spv_operand_type_t type) {
|
|||||||
return "literal";
|
return "literal";
|
||||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER:
|
case SPV_OPERAND_TYPE_LITERAL_NUMBER:
|
||||||
return "literal number";
|
return "literal number";
|
||||||
|
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
|
||||||
|
return "multiple word literal number";
|
||||||
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
||||||
return "literal string";
|
return "literal string";
|
||||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||||
|
@ -435,6 +435,9 @@ spv_result_t spvTextEncodeOperand(
|
|||||||
return SPV_ERROR_INVALID_TEXT;
|
return SPV_ERROR_INVALID_TEXT;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
// TODO(antiagainst): the handling of literal numbers in this function need
|
||||||
|
// to be reorganized.
|
||||||
|
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
|
||||||
case SPV_OPERAND_TYPE_LITERAL:
|
case SPV_OPERAND_TYPE_LITERAL:
|
||||||
case SPV_OPERAND_TYPE_LITERAL_IN_OPTIONAL_TUPLE:
|
case SPV_OPERAND_TYPE_LITERAL_IN_OPTIONAL_TUPLE:
|
||||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL: {
|
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL: {
|
||||||
|
@ -194,4 +194,74 @@ TEST(BinaryToTextSmall, OperandWithOperands) {
|
|||||||
spvTextDestroy(text);
|
spvTextDestroy(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(BinaryToTextSmall, LiteralInt64) {
|
||||||
|
spv_opcode_table opcodeTable;
|
||||||
|
spv_operand_table operandTable;
|
||||||
|
spv_ext_inst_table extInstTable;
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||||
|
spv_binary binary;
|
||||||
|
spv_diagnostic diagnostic = nullptr;
|
||||||
|
|
||||||
|
AutoText input("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 123456789021\n");
|
||||||
|
spv_result_t error =
|
||||||
|
spvTextToBinary(input.str.c_str(), input.str.length(), opcodeTable,
|
||||||
|
operandTable, extInstTable, &binary, &diagnostic);
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, error);
|
||||||
|
spv_text text = nullptr;
|
||||||
|
error = spvBinaryToText(binary->code, binary->wordCount,
|
||||||
|
SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
|
||||||
|
operandTable, extInstTable, &text, &diagnostic);
|
||||||
|
EXPECT_EQ(SPV_SUCCESS, error);
|
||||||
|
if (error) {
|
||||||
|
spvDiagnosticPrint(diagnostic);
|
||||||
|
spvDiagnosticDestroy(diagnostic);
|
||||||
|
}
|
||||||
|
const std::string header =
|
||||||
|
"; SPIR-V\n; Version: 99\n; Generator: Khronos\n; "
|
||||||
|
"Bound: 3\n; Schema: 0\n";
|
||||||
|
EXPECT_EQ(header + input.str, text->str);
|
||||||
|
spvTextDestroy(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BinaryToTextSmall, LiteralDouble) {
|
||||||
|
spv_opcode_table opcodeTable;
|
||||||
|
spv_operand_table operandTable;
|
||||||
|
spv_ext_inst_table extInstTable;
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||||
|
spv_binary binary;
|
||||||
|
spv_diagnostic diagnostic = nullptr;
|
||||||
|
|
||||||
|
// Pi: 3.1415926535897930 => 0x400921fb54442d18 => 4614256656552045848
|
||||||
|
AutoText input(
|
||||||
|
"%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 3.1415926535897930");
|
||||||
|
spv_result_t error =
|
||||||
|
spvTextToBinary(input.str.c_str(), input.str.length(), opcodeTable,
|
||||||
|
operandTable, extInstTable, &binary, &diagnostic);
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, error);
|
||||||
|
spv_text text = nullptr;
|
||||||
|
error = spvBinaryToText(binary->code, binary->wordCount,
|
||||||
|
SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
|
||||||
|
operandTable, extInstTable, &text, &diagnostic);
|
||||||
|
EXPECT_EQ(SPV_SUCCESS, error);
|
||||||
|
if (error) {
|
||||||
|
spvDiagnosticPrint(diagnostic);
|
||||||
|
spvDiagnosticDestroy(diagnostic);
|
||||||
|
}
|
||||||
|
const std::string output =
|
||||||
|
R"(; SPIR-V
|
||||||
|
; Version: 99
|
||||||
|
; Generator: Khronos
|
||||||
|
; Bound: 3
|
||||||
|
; Schema: 0
|
||||||
|
%1 = OpTypeFloat 64
|
||||||
|
%2 = OpSpecConstant %1 4614256656552045848
|
||||||
|
)";
|
||||||
|
EXPECT_EQ(output, text->str);
|
||||||
|
spvTextDestroy(text);
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
@ -51,4 +51,24 @@ TEST(FixWord, Reorder) {
|
|||||||
ASSERT_EQ(result, spvFixWord(word, endian));
|
ASSERT_EQ(result, spvFixWord(word, endian));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(FixDoubleWord, Default) {
|
||||||
|
spv_endianness_t endian =
|
||||||
|
(I32_ENDIAN_HOST == I32_ENDIAN_LITTLE ? SPV_ENDIANNESS_LITTLE
|
||||||
|
: SPV_ENDIANNESS_BIG);
|
||||||
|
uint32_t low = 0x53780921;
|
||||||
|
uint32_t high = 0xdeadbeef;
|
||||||
|
uint64_t result = 0xdeadbeef53780921;
|
||||||
|
ASSERT_EQ(result, spvFixDoubleWord(low, high, endian));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FixDoubleWord, Reorder) {
|
||||||
|
spv_endianness_t endian =
|
||||||
|
(I32_ENDIAN_HOST == I32_ENDIAN_LITTLE ? SPV_ENDIANNESS_BIG
|
||||||
|
: SPV_ENDIANNESS_LITTLE);
|
||||||
|
uint32_t low = 0x53780921;
|
||||||
|
uint32_t high = 0xdeadbeef;
|
||||||
|
uint64_t result = 0xefbeadde21097853;
|
||||||
|
ASSERT_EQ(result, spvFixDoubleWord(low, high, endian));
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
Loading…
Reference in New Issue
Block a user