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,
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) {
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) {
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: {
} 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)) {
/// @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
/// @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);
default:
break;
}
+ } else if (operandClass == OperandVariableLiterals) {
+ if (opcode == spv::OpConstant || opcode == spv::OpSpecConstant)
+ return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
}
switch(operandClass) {
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:
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: {
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
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