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:
Родитель
cebad036f7
Коммит
b41d150b7f
|
@ -146,6 +146,8 @@ typedef enum spv_operand_type_t {
|
|||
SPV_OPERAND_TYPE_RESULT_ID,
|
||||
SPV_OPERAND_TYPE_LITERAL, // Either a literal number or literal string
|
||||
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_SOURCE_LANGUAGE,
|
||||
SPV_OPERAND_TYPE_EXECUTION_MODEL,
|
||||
|
|
|
@ -83,6 +83,11 @@ uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian) {
|
|||
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,
|
||||
const spv_endianness_t endian,
|
||||
spv_header_t *pHeader) {
|
||||
|
@ -205,7 +210,7 @@ spv_operand_type_t spvBinaryOperandInfo(const uint32_t word,
|
|||
|
||||
spv_result_t spvBinaryDecodeOperand(
|
||||
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,
|
||||
spv_operand_pattern_t *pExpectedOperands, spv_ext_inst_type_t *pExtInstType,
|
||||
out_stream &stream, spv_position position, spv_diagnostic *pDiagnostic) {
|
||||
|
@ -249,14 +254,23 @@ spv_result_t spvBinaryDecodeOperand(
|
|||
break;
|
||||
}
|
||||
} // Fall through for the general case.
|
||||
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_LITERAL:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL:
|
||||
case SPV_OPERAND_TYPE_LITERAL_IN_OPTIONAL_TUPLE: {
|
||||
// TODO: Need to support multiple word literals
|
||||
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() : "");
|
||||
position->index++;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: {
|
||||
|
@ -415,9 +429,25 @@ spv_result_t spvBinaryDecodeOpcode(
|
|||
} else {
|
||||
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(
|
||||
opcodeEntry->opcode, type, pInst->words + index, endian, options,
|
||||
operandTable, extInstTable, &expectedOperands, &pInst->extInstType,
|
||||
opcodeEntry->opcode, type, pInst->words + index, numWords, endian,
|
||||
options, operandTable, extInstTable, &expectedOperands,
|
||||
&pInst->extInstType,
|
||||
(isAssigmentFormat && !currentIsResultId ? no_result_id_stream
|
||||
: stream),
|
||||
position, pDiagnostic)) {
|
||||
|
|
|
@ -41,6 +41,16 @@
|
|||
/// @return word with host endianness correction
|
||||
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
|
||||
///
|
||||
/// 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
|
||||
spv_result_t spvBinaryDecodeOperand(
|
||||
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,
|
||||
spv_operand_pattern_t *pExpectedOperands, spv_ext_inst_type_t *pExtInstType,
|
||||
out_stream &stream, spv_position position, spv_diagnostic *pDiagnostic);
|
||||
|
|
|
@ -90,6 +90,9 @@ spv_operand_type_t convertOperandClassToType(spv::Op opcode,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (operandClass == OperandVariableLiterals) {
|
||||
if (opcode == spv::OpConstant || opcode == spv::OpSpecConstant)
|
||||
return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
|
||||
}
|
||||
|
||||
switch(operandClass) {
|
||||
|
|
|
@ -1454,6 +1454,8 @@ const char *spvOperandTypeStr(spv_operand_type_t type) {
|
|||
return "literal";
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER:
|
||||
return "literal number";
|
||||
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
|
||||
return "multiple word literal number";
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
||||
return "literal string";
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
|
|
|
@ -435,6 +435,9 @@ spv_result_t spvTextEncodeOperand(
|
|||
return SPV_ERROR_INVALID_TEXT;
|
||||
}
|
||||
} 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_IN_OPTIONAL_TUPLE:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL: {
|
||||
|
|
|
@ -194,4 +194,74 @@ TEST(BinaryToTextSmall, OperandWithOperands) {
|
|||
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
|
||||
|
|
|
@ -51,4 +51,24 @@ TEST(FixWord, Reorder) {
|
|||
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
|
||||
|
|
Загрузка…
Ссылка в новой задаче