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:
Lei Zhang 2015-09-14 15:22:23 -04:00 committed by David Neto
parent cebad036f7
commit b41d150b7f
8 changed files with 146 additions and 6 deletions

View File

@ -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,

View File

@ -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)) {

View File

@ -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);

View File

@ -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) {

View File

@ -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:

View File

@ -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: {

View File

@ -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

View File

@ -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