-
Notifications
You must be signed in to change notification settings - Fork 11.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[HLSL] Implement floating literal suffixes (#87270)
This change implements the HLSL floating literal suffixes for half and double literals. The PR for the HLSL language specification for this behavior is microsoft/hlsl-specs#175. The TL;DR is that the `h` suffix on floating literals means `half`, and the `l` suffix means `double`. The expected behavior and diagnostics are different if native half is supported. When native half is not enabled half is 32-bit so implicit conversions to float do not lose precision and do not warn. In all cases `half` and `float` are distinct types. Resolves #85712
- Loading branch information
1 parent
225e14e
commit 0a0fccf
Showing
3 changed files
with
121 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-library -fnative-half-type -Wconversion -verify %s | ||
|
||
void literal_assignments() { | ||
half h; | ||
|
||
h = 2.0h; // No conversion, no diagnostic expected. | ||
|
||
// Literal conversions that don't lose precision also don't cause diagnostics. | ||
// Conversion from double (no diagnostic expected) | ||
h = 2.0l; | ||
h = 2.0; | ||
h = 2.0f; | ||
|
||
// Literal assignments with conversions that lose precision produce | ||
// diagnostics under `-Wconversion`. | ||
|
||
// Lose precision on assignment. | ||
h = 3.1415926535897932384626433h; // No diagnostic expected because this isn't a conversion. | ||
|
||
// Lose precision on assignment converting float to half. | ||
h = 3.1415926535897932384626433f; // expected-warning {{implicit conversion loses floating-point precision: 'float' to 'half'}} | ||
|
||
// Lose precision on assignment converting float to half. | ||
h = 3.1415926535897932384626433f * 2.0f; // expected-warning {{implicit conversion loses floating-point precision: 'float' to 'half'}} | ||
|
||
// Lose precision on assignment converting double to half. | ||
h = 3.1415926535897932384626433l; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'half'}} | ||
|
||
// Lose precision on assignment converting double to half. | ||
h = 3.1415926535897932384626433l * 2.0l; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'half'}} | ||
|
||
// Literal assinments of values out of the representable range produce | ||
// warnings. | ||
|
||
h = 66000.h; // expected-warning {{magnitude of floating-point constant too large for type 'half'; maximum is 65504}} | ||
h = -66000.h; // expected-warning {{magnitude of floating-point constant too large for type 'half'; maximum is 65504}} | ||
|
||
// The `h` suffix is invalid on integer literals. | ||
h = 66000h; // expected-error {{invalid suffix 'h' on integer constant}} | ||
} | ||
|
||
template <typename T, typename U> | ||
struct is_same { | ||
static const bool value = false; | ||
}; | ||
|
||
template <typename T> | ||
struct is_same<T, T> { | ||
static const bool value = true; | ||
}; | ||
|
||
// The no-suffix behavior is currently wrong. The behavior in DXC is complicated | ||
// and undocumented. We have a language change planned to address this, and an | ||
// issue tracking: https://github.com/llvm/llvm-project/issues/85714. | ||
_Static_assert(is_same<double, __decltype(1.0)>::value, "1.0f literal is double (should be float)"); | ||
|
||
_Static_assert(is_same<half, __decltype(1.0h)>::value, "1.0h literal is half"); | ||
_Static_assert(is_same<float, __decltype(1.0f)>::value, "1.0f literal is float"); | ||
_Static_assert(is_same<double, __decltype(1.0l)>::value, "1.0l literal is double"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-library -Wconversion -verify %s | ||
|
||
void literal_assignments() { | ||
half h; | ||
|
||
h = 2.0h; // No conversion, no diagnostic expected. | ||
|
||
// Literal conversions that don't lose precision also don't cause diagnostics. | ||
// Conversion from double (no diagnostic expected) | ||
h = 2.0l; | ||
h = 2.0; | ||
h = 2.0f; | ||
|
||
// Literal assignments with conversions that lose precision produce | ||
// diagnostics under `-Wconversion`. | ||
|
||
// Lose precision on assignment. | ||
h = 3.1415926535897932384626433h; // No diagnostic expected because this isn't a conversion. | ||
|
||
// Lose precision on assignment converting float to half. | ||
h = 3.1415926535897932384626433f; // No diagnostic expected because half and float are the same size. | ||
|
||
// Lose precision on assignment converting float to half. | ||
h = 3.1415926535897932384626433f * 2.0f; // No diagnostic expected because half and float are the same size. | ||
|
||
// Lose precision on assignment converting double to half. | ||
h = 3.1415926535897932384626433l; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'half'}} | ||
|
||
// Lose precision on assignment converting double to half. | ||
h = 3.1415926535897932384626433l * 2.0l; // expected-warning {{implicit conversion loses floating-point precision: 'double' to 'half'}} | ||
|
||
// Literal assinments of values out of the representable range produce | ||
// warnings. | ||
|
||
h = 66000.h; // No diagnostic expected because half is 32-bit. | ||
h = -66000.h; // No diagnostic expected because half is 32-bit. | ||
|
||
// The `h` suffix is invalid on integer literals. | ||
h = 66000h; // expected-error {{invalid suffix 'h' on integer constant}} | ||
} | ||
|
||
template <typename T, typename U> | ||
struct is_same { | ||
static const bool value = false; | ||
}; | ||
|
||
template <typename T> | ||
struct is_same<T, T> { | ||
static const bool value = true; | ||
}; | ||
|
||
// The no-suffix behavior is currently wrong. The behavior in DXC is complicated | ||
// and undocumented. We have a language change planned to address this, and an | ||
// issue tracking: https://github.com/llvm/llvm-project/issues/85714. | ||
_Static_assert(is_same<double, __decltype(1.0)>::value, "1.0f literal is double (should be float)"); | ||
|
||
_Static_assert(is_same<half, __decltype(1.0h)>::value, "1.0h literal is half"); | ||
_Static_assert(is_same<float, __decltype(1.0f)>::value, "1.0f literal is float"); | ||
_Static_assert(is_same<double, __decltype(1.0l)>::value, "1.0l literal is double"); |