SPV_OPERAND_TYPE_NONE = 0,
SPV_OPERAND_TYPE_ID,
SPV_OPERAND_TYPE_RESULT_ID,
+ // TODO(antiagainst): Instructions in opcode.inc that use
+ // SPV_OPERAND_TYPE_LITERAL should in fact use LITERAL_NUMBER. So
+ // SPV_OPERAND_TYPE_LITERAL can be removed.
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_OPTIONAL_ID,
SPV_OPERAND_TYPE_OPTIONAL_IMAGE,
// A literal number or string, but optional.
+ // TODO(antiagainst): change to SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER.
SPV_OPERAND_TYPE_OPTIONAL_LITERAL,
// An optional literal string.
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING,
return SPV_SUCCESS;
}
-
- // TODO: Literal numbers can be any number up to 64 bits wide. This
- // includes integers and floating point numbers.
- // TODO(dneto): Suggest using spvTextToLiteral and looking for an
- // appropriate result type.
- if (spvTextToUInt32(textValue, &pInst->words[pInst->wordCount++])) {
- DIAGNOSTIC << "Invalid literal number '" << textValue << "'.";
- return SPV_ERROR_INVALID_TEXT;
- }
- } break;
- // TODO(antiagainst): the handling of literal numbers in this function need
- // to be reorganized.
+ } // Fall through for the general case.
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
+ // TODO(antiagainst): SPV_OPERAND_TYPE_LITERAL should be removed.
case SPV_OPERAND_TYPE_LITERAL:
case SPV_OPERAND_TYPE_LITERAL_IN_OPTIONAL_TUPLE:
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL: {
spv_literal_t literal = {};
- if (spvTextToLiteral(textValue, &literal) != SPV_SUCCESS) {
- if (spvOperandIsOptional(type)) {
- return SPV_FAILED_MATCH;
- } else {
- DIAGNOSTIC << "Invalid literal '" << textValue << "'.";
- return SPV_ERROR_INVALID_TEXT;
- }
+ spv_result_t error = spvTextToLiteral(textValue, &literal);
+ if (error != SPV_SUCCESS) {
+ if (error == SPV_ERROR_OUT_OF_MEMORY) return error;
+ if (spvOperandIsOptional(type)) return SPV_FAILED_MATCH;
+ DIAGNOSTIC << "Invalid literal number '" << textValue << "'.";
+ return SPV_ERROR_INVALID_TEXT;
}
switch (literal.type) {
// We do not have to print diagnostics here because spvBinaryEncode*
return SPV_ERROR_INVALID_TEXT;
} break;
case SPV_LITERAL_TYPE_STRING: {
- if (spvBinaryEncodeString(literal.value.str, pInst, position,
- pDiagnostic))
- return SPV_ERROR_INVALID_TEXT;
+ DIAGNOSTIC << "Expected literal number, found literal string '"
+ << textValue << "'.";
+ return SPV_FAILED_MATCH;
} break;
default:
- DIAGNOSTIC << "Invalid literal '" << textValue << "'";
+ DIAGNOSTIC << "Invalid literal number '" << textValue << "'";
return SPV_ERROR_INVALID_TEXT;
}
} break;
case SPV_OPERAND_TYPE_LITERAL_STRING:
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: {
- size_t len = strlen(textValue);
- if ('"' != textValue[0] && '"' != textValue[len - 1]) {
+ spv_literal_t literal = {};
+ spv_result_t error = spvTextToLiteral(textValue, &literal);
+ if (error != SPV_SUCCESS) {
+ if (error == SPV_ERROR_OUT_OF_MEMORY) return error;
if (spvOperandIsOptional(type)) return SPV_FAILED_MATCH;
- DIAGNOSTIC << "Invalid literal string '" << textValue
- << "', expected quotes.";
+ DIAGNOSTIC << "Invalid literal string '" << textValue << "'.";
return SPV_ERROR_INVALID_TEXT;
}
- // NOTE: Strip quotes
- std::string text(textValue + 1, len - 2);
+ if (literal.type != SPV_LITERAL_TYPE_STRING) {
+ DIAGNOSTIC << "Expected literal string, found literal number '"
+ << textValue << "'.";
+ return SPV_FAILED_MATCH;
+ }
// NOTE: Special case for extended instruction library import
if (OpExtInstImport == pInst->opcode) {
- pInst->extInstType = spvExtInstImportTypeGet(text.c_str());
+ pInst->extInstType = spvExtInstImportTypeGet(literal.value.str);
}
- if (spvBinaryEncodeString(text.c_str(), pInst, position, pDiagnostic))
+ if (spvBinaryEncodeString(literal.value.str, pInst, position,
+ pDiagnostic))
return SPV_ERROR_INVALID_TEXT;
} break;
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
// expanded.
spv_operand_pattern_t dummyExpectedOperands;
error = spvTextEncodeOperand(
+ // TODO(antiagainst): SPV_OPERAND_TYPE_OPTIONAL_LITERAL should be
+ // substituted by SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER.
SPV_OPERAND_TYPE_OPTIONAL_LITERAL, operandValue.c_str(), operandTable,
extInstTable, namedIdTable, pInst, &dummyExpectedOperands, pBound,
position, pDiagnostic);
if (error == SPV_FAILED_MATCH) {
+ // It's not a literal number -- is it a literal string?
+ error = spvTextEncodeOperand(
+ SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING, operandValue.c_str(),
+ operandTable, extInstTable, namedIdTable, pInst,
+ &dummyExpectedOperands, pBound, position, pDiagnostic);
+ }
+ if (error == SPV_FAILED_MATCH) {
// It's not a literal -- is it an ID?
error = spvTextEncodeOperand(
SPV_OPERAND_TYPE_OPTIONAL_ID, operandValue.c_str(), operandTable,
--- /dev/null
+// 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.
+
+// Assembler tests for literal numbers and literal strings.
+
+#include "TestFixture.h"
+
+namespace {
+
+using test_fixture::TextToBinaryTest;
+
+TEST_F(TextToBinaryTest, LiteralStringInPlaceOfLiteralNumber) {
+ EXPECT_EQ(
+ R"(Expected literal number, found literal string '"I shouldn't be a string"'.)",
+ CompileFailure(R"(OpSource GLSL "I shouldn't be a string")"));
+}
+
+TEST_F(TextToBinaryTest, GarbageInPlaceOfLiteralString) {
+ EXPECT_EQ(
+ R"(Invalid literal string 'nice-source-code'.)",
+ CompileFailure(R"(OpSourceExtension nice-source-code)"));
+}
+
+TEST_F(TextToBinaryTest, LiteralNumberInPlaceOfLiteralString) {
+ EXPECT_EQ(
+ R"(Expected literal string, found literal number '1000'.)",
+ CompileFailure(R"(OpSourceExtension 1000)"));
+}
+
+// TODO(antiagainst): libspirv.h defines SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX
+// to be 0x108. Lift that limit and enable the following test.
+TEST_F(TextToBinaryTest, DISABLED_LiteralStringTooLong) {
+ const std::string code =
+ "OpSourceExtension \"" + std::string(65534, 'o') + "\"\n";
+ const std::string header =
+ "; SPIR-V\n; Version: 99\n; Generator: Khronos\n; "
+ "Bound: 1\n; Schema: 0\n";
+ EXPECT_EQ(header + code, EncodeAndDecodeSuccessfully(code));
+}
+
+} // anonymous namespace