diff --git a/test/TextLiteral.cpp b/test/TextLiteral.cpp index f286635df9..48c3162907 100644 --- a/test/TextLiteral.cpp +++ b/test/TextLiteral.cpp @@ -291,6 +291,32 @@ INSTANTIATE_TEST_CASE_P( })); // clang-format on +using IntegerLeadingMinusTest = + spvtest::TextToBinaryTestBase<::testing::TestWithParam>; + +TEST_P(IntegerLeadingMinusTest, CantHaveLeadingMinusOnUnsigned) { + EXPECT_FALSE(GetParam().success); + EXPECT_THAT( + failedEncode(GetParam(), libspirv::IdTypeClass::kScalarIntegerType), + Eq("Cannot put a negative number in an unsigned literal")); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + DecimalAndHexIntegers, IntegerLeadingMinusTest, + ::testing::ValuesIn(std::vector{ + // Unsigned numbers never allow a leading minus sign. + Make_Bad_Unsigned(16, "-0"), + Make_Bad_Unsigned(16, "-0x0"), + Make_Bad_Unsigned(16, "-0x1"), + Make_Bad_Unsigned(32, "-0"), + Make_Bad_Unsigned(32, "-0x0"), + Make_Bad_Unsigned(32, "-0x1"), + Make_Bad_Unsigned(64, "-0"), + Make_Bad_Unsigned(64, "-0x0"), + Make_Bad_Unsigned(64, "-0x1"), + })); + // clang-format off INSTANTIATE_TEST_CASE_P( HexIntegers, IntegerTest, diff --git a/test/TextToBinary.Constant.cpp b/test/TextToBinary.Constant.cpp index 4c7190c005..4fabba719b 100644 --- a/test/TextToBinary.Constant.cpp +++ b/test/TextToBinary.Constant.cpp @@ -118,8 +118,9 @@ TEST_P(OpConstantValidTest, ValidTypes) { "%2 = OpConstant %1 " + GetParam().constant_value + "\n"; std::vector instructions; - EXPECT_THAT(CompiledInstructions(input), - Eq(GetParam().expected_instructions)); + EXPECT_THAT(CompiledInstructions(input), Eq(GetParam().expected_instructions)) + << " type: " << GetParam().constant_type + << " literal: " << GetParam().constant_value; } // clang-format off @@ -133,12 +134,33 @@ INSTANTIATE_TEST_CASE_P( {"OpTypeInt 16 0", "0x8000", Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), MakeInstruction(SpvOpConstant, {1, 2, 0x8000})})}, + {"OpTypeInt 16 0", "0", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), + MakeInstruction(SpvOpConstant, {1, 2, 0})})}, + {"OpTypeInt 16 0", "65535", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), + MakeInstruction(SpvOpConstant, {1, 2, 65535})})}, + {"OpTypeInt 16 0", "0xffff", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}), + MakeInstruction(SpvOpConstant, {1, 2, 65535})})}, {"OpTypeInt 16 1", "0x8000", // Test sign extension. Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), MakeInstruction(SpvOpConstant, {1, 2, 0xffff8000})})}, {"OpTypeInt 16 1", "-32", Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})}, + {"OpTypeInt 16 1", "0", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0})})}, + {"OpTypeInt 16 1", "-0", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0})})}, + {"OpTypeInt 16 1", "-0x0", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0})})}, + {"OpTypeInt 16 1", "-32768", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}), + MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32768)})})}, // Check 32 bits {"OpTypeInt 32 0", "42", Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}), @@ -146,6 +168,24 @@ INSTANTIATE_TEST_CASE_P( {"OpTypeInt 32 1", "-32", Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})}, + {"OpTypeInt 32 1", "0", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0})})}, + {"OpTypeInt 32 1", "-0", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0})})}, + {"OpTypeInt 32 1", "-0x0", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0})})}, + {"OpTypeInt 32 1", "-0x001", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), + MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-1)})})}, + {"OpTypeInt 32 1", "2147483647", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu})})}, + {"OpTypeInt 32 1", "-2147483648", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0x80000000u})})}, {"OpTypeFloat 32", "1.0", Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}), MakeInstruction(SpvOpConstant, {1, 2, 0x3f800000})})}, @@ -181,12 +221,61 @@ INSTANTIATE_TEST_CASE_P( {"OpTypeInt 64 0", "0x1234", Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}), MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})}, + {"OpTypeInt 64 0", "18446744073709551615", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}), + MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})}, + {"OpTypeInt 64 0", "0xffffffffffffffff", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}), + MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})}, {"OpTypeInt 64 1", "0x1234", Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})}, {"OpTypeInt 64 1", "-42", Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})}, + {"OpTypeInt 64 1", "-0x01", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})}, + {"OpTypeInt 64 1", "9223372036854775807", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})}, + {"OpTypeInt 64 1", "0x7fffffff", + Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}), + MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu, 0})})}, + })); +// clang-format on + +// A test case for checking OpConstant with invalid literals with a leading minus. +struct InvalidLeadingMinusCase { + std::string type; + std::string literal; +}; + +using OpConstantInvalidLeadingMinusTest = + spvtest::TextToBinaryTestBase<::testing::TestWithParam>; + +TEST_P(OpConstantInvalidLeadingMinusTest, InvalidCase) { + const std::string input = "%1 = " + GetParam().type + + "\n" + "%2 = OpConstant %1 " + + GetParam().literal; + EXPECT_THAT(CompileFailure(input), + Eq("Cannot put a negative number in an unsigned literal")); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + TextToBinaryOpConstantInvalidLeadingMinus, OpConstantInvalidLeadingMinusTest, + ::testing::ValuesIn(std::vector{ + {"OpTypeInt 16 0", "-0"}, + {"OpTypeInt 16 0", "-0x0"}, + {"OpTypeInt 16 0", "-1"}, + {"OpTypeInt 32 0", "-0"}, + {"OpTypeInt 32 0", "-0x0"}, + {"OpTypeInt 32 0", "-1"}, + {"OpTypeInt 64 0", "-0"}, + {"OpTypeInt 64 0", "-0x0"}, + {"OpTypeInt 64 0", "-1"}, })); // clang-format on diff --git a/test/TextToBinary.cpp b/test/TextToBinary.cpp index 91f1ca5252..20f891692e 100644 --- a/test/TextToBinary.cpp +++ b/test/TextToBinary.cpp @@ -319,15 +319,71 @@ TEST(AssemblyContextParseNarrowUnsignedIntegers, Sample) { EXPECT_EQ(65535, u16); EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("65536", ec, &u16, "")); - EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &u16, "")); - EXPECT_EQ(0, u16); + // We don't care about -0 since it's rejected at a higher level. EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", ec, &u16, "")); - EXPECT_EQ(0, u16); EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0xffff", ec, &u16, "")); EXPECT_EQ(0xffff, u16); EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0x10000", ec, &u16, "")); } +TEST(AssemblyContextParseSignedIntegers, Sample) { + AssemblyContext context(AutoText(""), nullptr); + const spv_result_t ec = SPV_FAILED_MATCH; + int32_t i32; + + // Invalid parse. + EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &i32, "")); + EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &i32, "")); + + // Decimal values. + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &i32, "")); + EXPECT_EQ(0, i32); + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("2147483647", ec, &i32, "")); + EXPECT_EQ(std::numeric_limits::max(), i32); + EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("2147483648", ec, &i32, "")); + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &i32, "")); + EXPECT_EQ(0, i32); + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-1", ec, &i32, "")); + EXPECT_EQ(-1, i32); + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-2147483648", ec, &i32, "")); + EXPECT_EQ(std::numeric_limits::min(), i32); + + // Hex values. + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0x7fffffff", ec, &i32, "")); + EXPECT_EQ(std::numeric_limits::max(), i32); + EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0x80000000", ec, &i32, "")); + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0x000", ec, &i32, "")); + EXPECT_EQ(0, i32); + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0x001", ec, &i32, "")); + EXPECT_EQ(-1, i32); + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0x80000000", ec, &i32, "")); + EXPECT_EQ(std::numeric_limits::min(), i32); +} + +TEST(AssemblyContextParseUnsignedIntegers, Sample) { + AssemblyContext context(AutoText(""), nullptr); + const spv_result_t ec = SPV_FAILED_MATCH; + uint32_t u32; + + // Invalid parse. + EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("", ec, &u32, "")); + EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("0=", ec, &u32, "")); + + // Valid values. + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0", ec, &u32, "")); + EXPECT_EQ(0u, u32); + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("4294967295", ec, &u32, "")); + EXPECT_EQ(std::numeric_limits::max(), u32); + EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("4294967296", ec, &u32, "")); + + // Hex values. + EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0xffffffff", ec, &u32, "")); + EXPECT_EQ(std::numeric_limits::max(), u32); + + // We don't care about -0 since it's rejected at a higher level. + EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", ec, &u32, "")); +} + TEST(AssemblyContextParseWideSignedIntegers, Sample) { AssemblyContext context(AutoText(""), nullptr); const spv_result_t ec = SPV_FAILED_MATCH; @@ -356,8 +412,8 @@ TEST(AssemblyContextParseWideUnsignedIntegers, Sample) { EXPECT_EQ(SPV_SUCCESS, context.parseNumber("0xffffffffffffffff", ec, &u64, "")); EXPECT_EQ(0xffffffffffffffffULL, u64); - EXPECT_EQ(SPV_SUCCESS, context.parseNumber("-0", ec, &u64, "")); - EXPECT_EQ(0u, u64); + + // We don't care about -0 since it's rejected at a higher level. EXPECT_EQ(SPV_FAILED_MATCH, context.parseNumber("-1", ec, &u64, "")); }