}
spv_result_t AssemblyContext::binaryEncodeNumericLiteral(
- const char *val, bool is_optional, const IdType &type,
+ const char *val, spv_result_t error_code, const IdType &type,
spv_instruction_t *pInst) {
const bool is_bottom = type.type_class == libspirv::IdTypeClass::kBottom;
const bool is_floating = libspirv::isScalarFloating(type);
// If we explicitly expect a floating-point number, we should handle that
// first.
if (is_floating || looks_like_float)
- return binaryEncodeFloatingPointLiteral(val, is_optional, type, pInst);
+ return binaryEncodeFloatingPointLiteral(val, error_code, type, pInst);
- return binaryEncodeIntegerLiteral(val, is_optional, type, pInst);
+ return binaryEncodeIntegerLiteral(val, error_code, type, pInst);
}
spv_result_t AssemblyContext::binaryEncodeString(
}
spv_result_t AssemblyContext::binaryEncodeFloatingPointLiteral(
- const char *val, bool is_optional, const IdType &type,
+ const char *val, spv_result_t error_code, const IdType &type,
spv_instruction_t *pInst) {
const auto bit_width = assumedBitWidth(type);
switch (bit_width) {
<< "Unsupported yet: 16-bit float constants.";
case 32: {
float fVal;
- if (auto error = parseNumber(val, is_optional, &fVal,
+ if (auto error = parseNumber(val, error_code, &fVal,
"Invalid 32-bit float literal: "))
return error;
return binaryEncodeU32(BitwiseCast<uint32_t>(fVal), pInst);
} break;
case 64: {
double dVal;
- if (auto error = parseNumber(val, is_optional, &dVal,
+ if (auto error = parseNumber(val, error_code, &dVal,
"Invalid 64-bit float literal: "))
return error;
return binaryEncodeU64(BitwiseCast<uint64_t>(dVal), pInst);
}
spv_result_t AssemblyContext::binaryEncodeIntegerLiteral(
- const char *val, bool is_optional, const IdType &type,
+ const char *val, spv_result_t error_code, const IdType &type,
spv_instruction_t *pInst) {
const bool is_bottom = type.type_class == libspirv::IdTypeClass::kBottom;
const auto bit_width = assumedBitWidth(type);
uint64_t decoded_bits;
if (is_negative) {
int64_t decoded_signed = 0;
- if (auto error = parseNumber(val, is_optional, &decoded_signed,
+ if (auto error = parseNumber(val, error_code, &decoded_signed,
"Invalid signed integer literal: "))
return error;
if (auto error = checkRangeAndIfHexThenSignExtend(
- decoded_signed, is_optional, type, is_hex, &decoded_signed))
+ decoded_signed, error_code, type, is_hex, &decoded_signed))
return error;
decoded_bits = decoded_signed;
} else {
// There's no leading minus sign, so parse it as an unsigned integer.
- if (auto error = parseNumber(val, is_optional, &decoded_bits,
+ if (auto error = parseNumber(val, error_code, &decoded_bits,
"Invalid unsigned integer literal: "))
return error;
if (auto error = checkRangeAndIfHexThenSignExtend(
- decoded_bits, is_optional, type, is_hex, &decoded_bits))
+ decoded_bits, error_code, type, is_hex, &decoded_bits))
return error;
}
if (bit_width > 32) {
template <typename T>
spv_result_t AssemblyContext::checkRangeAndIfHexThenSignExtend(
- T value, bool is_optional, const IdType &type, bool is_hex,
+ T value, spv_result_t error_code, const IdType &type, bool is_hex,
T *updated_value_for_hex) {
// The encoded result has three regions of bits that are of interest, from
// least to most significant:
}
if (failed) {
- if (is_optional) return SPV_FAILED_MATCH;
- return diagnostic() << "Integer " << (is_hex ? std::hex : std::dec)
- << std::showbase << value << " does not fit in a "
- << std::dec << bit_width << "-bit "
- << (type.isSigned ? "signed" : "unsigned")
- << " integer";
+ return diagnostic(error_code)
+ << "Integer " << (is_hex ? std::hex : std::dec) << std::showbase
+ << value << " does not fit in a " << std::dec << bit_width << "-bit "
+ << (type.isSigned ? "signed" : "unsigned") << " integer";
}
// Sign extend hex the number.
// If the type is of class kBottom the value will be encoded as a
// 32-bit integer.
// Returns SPV_SUCCESS if the value could be correctly added to the
- // instruction.
+ // instruction. Returns the given error code on failure, and emits
+ // a diagnotic if that error code is not SPV_FAILED_MATCH.
spv_result_t binaryEncodeNumericLiteral(const char *numeric_literal,
- bool optional,
+ spv_result_t error_code,
const IdType &type,
spv_instruction_t *pInst);
// Parses a numeric value of a given type from the given text. The number
// should take up the entire string, and should be within bounds for the
// target type. On success, returns SPV_SUCCESS and populates the object
- // referenced by value_pointer. On failure, returns SPV_FAILED_MATCH if
- // is_optional is true, and returns SPV_ERROR_INVALID_TEXT and emits a
- // diagnostic otherwise.
+ // referenced by value_pointer. On failure, returns the given error code,
+ // and emits a diagnostic if that error code is not SPV_FAILED_MATCH.
template <typename T>
- spv_result_t parseNumber(const char *text, bool is_optional, T *value_pointer,
+ spv_result_t parseNumber(const char *text, spv_result_t error_code,
+ T *value_pointer,
const char *error_message_fragment) {
// C++11 doesn't define std::istringstream(int8_t&), so calling this method
// with a single-byte type leads to implementation-defined behaviour.
}
if (ok) return SPV_SUCCESS;
- if (is_optional) return SPV_FAILED_MATCH;
- return diagnostic() << error_message_fragment << text;
+ return diagnostic(error_code) << error_message_fragment << text;
}
private:
// Appends the given floating point literal to the given instruction.
// Returns SPV_SUCCESS if the value was correctly parsed. Otherwise
- // an error code is returned, and a message is emitted if is_optional
- // is false. Only 32 and 64 bit floating point numbers are supported.
+ // returns the given error code, and emits a diagnostic if that error
+ // code is not SPV_FAILED_MATCH.
+ // Only 32 and 64 bit floating point numbers are supported.
spv_result_t binaryEncodeFloatingPointLiteral(const char *numeric_literal,
- bool optional,
+ spv_result_t error_code,
const IdType& type,
spv_instruction_t *pInst);
// Appends the given integer literal to the given instruction.
// Returns SPV_SUCCESS if the value was correctly parsed. Otherwise
- // an error code is returned, and a message is emitted if is_optional
- // is false. Integers up to 64 bits are supported.
+ // returns the given error code, and emits a diagnostic if that error
+ // code is not SPV_FAILED_MATCH.
+ // Integers up to 64 bits are supported.
spv_result_t binaryEncodeIntegerLiteral(const char *numeric_literal,
- bool optional,
+ spv_result_t error_code,
const IdType &type,
spv_instruction_t *pInst);
// the overflow bits should be zero. If it was hex and the target type is
// signed, then return the sign-extended value through the
// updated_value_for_hex pointer argument.
- // On failure, if is_optional is true then return SPV_FAILED_MATCH, otherwise
- // emit a diagnostic and return SPV_ERROR_INVALID_TEXT.
+ // On failure, return the given error code and emit a diagnostic if that error
+ // code is not SPV_FAILED_MATCH.
template <typename T>
- spv_result_t checkRangeAndIfHexThenSignExtend(T value, bool is_optional,
+ spv_result_t checkRangeAndIfHexThenSignExtend(T value, spv_result_t error_code,
const IdType &type, bool is_hex,
T *updated_value_for_hex);
TEST(AssemblyContextParseNarrowSignedIntegers, Sample) {
AssemblyContext context(AutoText(""), nullptr);
+ const spv_result_t ec = SPV_FAILED_MATCH;
int16_t i16;
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", true, &i16, ""));
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", true, &i16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &i16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &i16, ""));
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", true, &i16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &i16, ""));
EXPECT_EQ(0, i16);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("32767", true, &i16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("32767", ec, &i16, ""));
EXPECT_EQ(32767, i16);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-32768", true, &i16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-32768", ec, &i16, ""));
EXPECT_EQ(-32768, i16);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", true, &i16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &i16, ""));
EXPECT_EQ(0, i16);
// These are out of range, so they should return an error.
// The error code depends on whether this is an optional value.
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("32768", true, &i16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("32768", ec, &i16, ""));
EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
- context.parseNumber("65535", false, &i16, ""));
+ context.parseNumber("65535", SPV_ERROR_INVALID_TEXT, &i16, ""));
// Check hex parsing.
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0x7fff", true, &i16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0x7fff", ec, &i16, ""));
EXPECT_EQ(32767, i16);
// This is out of range.
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0xffff", true, &i16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0xffff", ec, &i16, ""));
}
TEST(AssemblyContextParseNarrowUnsignedIntegers, Sample) {
AssemblyContext context(AutoText(""), nullptr);
+ const spv_result_t ec = SPV_FAILED_MATCH;
uint16_t u16;
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", true, &u16, ""));
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", true, &u16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &u16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &u16, ""));
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", true, &u16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &u16, ""));
EXPECT_EQ(0, u16);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("65535", true, &u16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("65535", ec, &u16, ""));
EXPECT_EQ(65535, u16);
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("65536", true, &u16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("65536", ec, &u16, ""));
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", true, &u16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &u16, ""));
EXPECT_EQ(0, u16);
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", true, &u16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", ec, &u16, ""));
EXPECT_EQ(0, u16);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0xffff", true, &u16, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0xffff", ec, &u16, ""));
EXPECT_EQ(0xffff, u16);
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0x10000", true, &u16, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0x10000", ec, &u16, ""));
}
TEST(AssemblyContextParseWideSignedIntegers, Sample) {
AssemblyContext context(AutoText(""), nullptr);
+ const spv_result_t ec = SPV_FAILED_MATCH;
int64_t i64;
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", true, &i64, ""));
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", true, &i64, ""));
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", true, &i64, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &i64, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &i64, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &i64, ""));
EXPECT_EQ(0, i64);
EXPECT_EQ(SPV_SUCCESS,
- context.parseNumber("0x7fffffffffffffff", true, &i64, ""));
+ context.parseNumber("0x7fffffffffffffff", ec, &i64, ""));
EXPECT_EQ(0x7fffffffffffffff, i64);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", true, &i64, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &i64, ""));
EXPECT_EQ(0, i64);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1", true, &i64, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1", ec, &i64, ""));
EXPECT_EQ(-1, i64);
}
TEST(AssemblyContextParseWideUnsignedIntegers, Sample) {
AssemblyContext context(AutoText(""), nullptr);
+ const spv_result_t ec = SPV_FAILED_MATCH;
uint64_t u64;
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", true, &u64, ""));
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", true, &u64, ""));
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", true, &u64, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &u64, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &u64, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &u64, ""));
EXPECT_EQ(0, u64);
EXPECT_EQ(SPV_SUCCESS,
- context.parseNumber("0xffffffffffffffff", true, &u64, ""));
+ context.parseNumber("0xffffffffffffffff", ec, &u64, ""));
EXPECT_EQ(0xffffffffffffffffULL, u64);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", true, &u64, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &u64, ""));
EXPECT_EQ(0, u64);
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", true, &u64, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", ec, &u64, ""));
}
TEST(AssemblyContextParseFloat, Sample) {
AssemblyContext context(AutoText(""), nullptr);
+ const spv_result_t ec = SPV_FAILED_MATCH;
float f;
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", true, &f, ""));
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", true, &f, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &f, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &f, ""));
// These values are exactly representatble.
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &f, ""));
EXPECT_EQ(0.0f, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("42", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("42", ec, &f, ""));
EXPECT_EQ(42.0f, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("2.5", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("2.5", ec, &f, ""));
EXPECT_EQ(2.5f, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-32.5", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-32.5", ec, &f, ""));
EXPECT_EQ(-32.5f, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("1e38", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("1e38", ec, &f, ""));
EXPECT_EQ(1e38f, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1e38", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1e38", ec, &f, ""));
EXPECT_EQ(-1e38f, f);
// Out of range.
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("1e40", true, &f, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("1e40", ec, &f, ""));
}
TEST(AssemblyContextParseDouble, Sample) {
AssemblyContext context(AutoText(""), nullptr);
+ const spv_result_t ec = SPV_FAILED_MATCH;
double f;
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", true, &f, ""));
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", true, &f, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &f, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &f, ""));
// These values are exactly representatble.
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &f, ""));
EXPECT_EQ(0.0, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("42", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("42", ec, &f, ""));
EXPECT_EQ(42.0, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("2.5", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("2.5", ec, &f, ""));
EXPECT_EQ(2.5, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-32.5", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-32.5", ec, &f, ""));
EXPECT_EQ(-32.5, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("1e38", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("1e38", ec, &f, ""));
EXPECT_EQ(1e38, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1e38", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1e38", ec, &f, ""));
EXPECT_EQ(-1e38, f);
// These are out of range for 32-bit float, but in range for 64-bit float.
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("1e40", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("1e40", ec, &f, ""));
EXPECT_EQ(1e40, f);
- EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1e40", true, &f, ""));
+ EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1e40", ec, &f, ""));
EXPECT_EQ(-1e40, f);
// Out of range.
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("1e400", true, &f, ""));
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1e400", true, &f, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("1e400", ec, &f, ""));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1e400", ec, &f, ""));
}
TEST(AssemblyContextParseMessages, Errors) {
spv_diagnostic diag = nullptr;
+ const spv_result_t ec = SPV_FAILED_MATCH;
AssemblyContext context(AutoText(""), &diag);
int16_t i16;
// No message is generated for a failure to parse an optional value.
- EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("abc", true, &i16, "bad narrow int: "));
+ EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("abc", ec, &i16, "bad narrow int: "));
EXPECT_EQ(nullptr, diag);
// For a required value, use the message fragment.
- EXPECT_EQ(SPV_ERROR_INVALID_TEXT, context.parseNumber("abc", false, &i16, "bad narrow int: "));
+ EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
+ context.parseNumber("abc", SPV_ERROR_INVALID_TEXT, &i16,
+ "bad narrow int: "));
ASSERT_NE(nullptr, diag);
EXPECT_EQ("bad narrow int: abc", std::string(diag->error));
// Don't leak.