tint/reader/wgsl: Error if a hex float is not exactly representable
Fixed: tint:1564 Change-Id: I3ba8d13055fd279868fcca9e7f8576a279b6902c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/91429 Reviewed-by: David Neto <dneto@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
118d161a84
commit
aff5e9e722
|
@ -17,6 +17,7 @@
|
|||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <optional> // NOLINT(build/include_order)
|
||||
#include <tuple>
|
||||
|
@ -658,18 +659,20 @@ Token Lexer::try_hex_float() {
|
|||
result_u64 |= mantissa;
|
||||
result_u64 |= (static_cast<uint64_t>(signed_exponent) & kExponentMask) << kExponentLeftShift;
|
||||
|
||||
// Reinterpret as float and return
|
||||
// Reinterpret as f16 and return
|
||||
double result_f64;
|
||||
std::memcpy(&result_f64, &result_u64, 8);
|
||||
|
||||
if (has_f_suffix) {
|
||||
// Quantize to f32
|
||||
// TODO(crbug.com/tint/1564): If the hex-float value is not exactly representable then we
|
||||
// should be erroring here.
|
||||
result_f64 = static_cast<double>(static_cast<float>(result_f64));
|
||||
if (std::isinf(result_f64)) {
|
||||
// Check value fits in f32
|
||||
if (result_f64 < static_cast<double>(f32::kLowest) ||
|
||||
result_f64 > static_cast<double>(f32::kHighest)) {
|
||||
return {Token::Type::kError, source, "value cannot be represented as 'f32'"};
|
||||
}
|
||||
// Check the value can be exactly represented (low 29 mantissa bits must be 0)
|
||||
if (result_u64 & 0x1fffffff) {
|
||||
return {Token::Type::kError, source, "value cannot be exactly represented as 'f32'"};
|
||||
}
|
||||
}
|
||||
|
||||
return {has_f_suffix ? Token::Type::kFloatLiteral_F : Token::Type::kFloatLiteral, source,
|
||||
|
|
|
@ -317,6 +317,14 @@ FloatLiteralTestCaseList HexFloatCases() {
|
|||
{"0x1.55554p-130", 0x1.55554p-130}, // +Subnormal
|
||||
{"-0x1.55554p-130", -0x1.55554p-130}, // -Subnormal
|
||||
|
||||
// F32 exactly representable
|
||||
{"0x1.000002p+0f", 0x1.000002p+0},
|
||||
{"0x8.0000fp+0f", 0x8.0000fp+0},
|
||||
{"0x8.fffffp+0f", 0x8.fffffp+0},
|
||||
{"0x8.00003p+0f", 0x8.00003p+0},
|
||||
{"0x2.123p+0f", 0x2.123p+0},
|
||||
{"0x2.cafefp+0f", 0x2.cafefp+0},
|
||||
|
||||
// Underflow -> Zero
|
||||
{"0x1p-1074", 0.0}, // Exponent underflows
|
||||
{"-0x1p-1074", 0.0},
|
||||
|
@ -327,14 +335,6 @@ FloatLiteralTestCaseList HexFloatCases() {
|
|||
{"0x0.01p-1073", -0.0},
|
||||
{"-0x0.01p-1073", -0.0}, // Fraction causes additional underflow
|
||||
|
||||
{"0x1p-150f", 0.0}, // Exponent underflows
|
||||
{"-0x1p-150f", 0.0},
|
||||
{"0x1p-500f", 0.0},
|
||||
{"-0x1p-500f", -0.0},
|
||||
{"0x0.00000000001p-126f", 0.0}, // Fraction causes underflow
|
||||
{"-0x0.0000000001p-127f", -0.0},
|
||||
{"0x0.01p-142f", 0.0},
|
||||
{"-0x0.01p-142f", -0.0}, // Fraction causes additional underflow
|
||||
{"0x1.0p-9223372036854774784", 0}, // -(INT64_MAX - 1023) (smallest valid exponent)
|
||||
|
||||
// Zero with non-zero exponent -> Zero
|
||||
|
@ -577,6 +577,17 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
"-0x32p+500f",
|
||||
})));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
HexNotExactlyRepresentableF32,
|
||||
ParserImplInvalidLiteralTest,
|
||||
testing::Combine(testing::Values("1:1: value cannot be exactly represented as 'f32'"),
|
||||
testing::ValuesIn(std::vector<const char*>{
|
||||
"0x1.000001p+0f", // Quantizes to 0x1.0p+0
|
||||
"0x8.0000f8p+0f", // Quantizes to 0x8.0000fp+0
|
||||
"0x8.000038p+0f", // Quantizes to 0x8.00003p+0
|
||||
"0x2.cafef00dp+0f", // Quantizes to 0x2.cafefp+0
|
||||
})));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
DecOverflowAFloat,
|
||||
ParserImplInvalidLiteralTest,
|
||||
|
|
Loading…
Reference in New Issue