@@ -3886,6 +3886,108 @@ namespace Slang
3886
3886
return (e != 0x7ff );
3887
3887
}
3888
3888
3889
+ enum class FloatFixKind
3890
+ {
3891
+ None, // /< No modification was made
3892
+ Unrepresentable, // /< Unrepresentable
3893
+ Zeroed, // /< Too close to 0
3894
+ Truncated, // /< Truncated to a non zero value
3895
+ };
3896
+
3897
+ static FloatFixKind _fixFloatLiteralValue (BaseType type, IRFloatingPointValue value, IRFloatingPointValue& outValue)
3898
+ {
3899
+ IRFloatingPointValue epsilon = 1e-10f ;
3900
+
3901
+ // Check the value is finite for checking narrowing to literal type losing information
3902
+ if (_isFinite (value))
3903
+ {
3904
+ switch (type)
3905
+ {
3906
+ case BaseType::Float:
3907
+ {
3908
+ // Fix out of range
3909
+ if (value > FLT_MAX)
3910
+ {
3911
+ if (Math::AreNearlyEqual (value, FLT_MAX, epsilon))
3912
+ {
3913
+ outValue = FLT_MAX;
3914
+ return FloatFixKind::Truncated;
3915
+ }
3916
+ else
3917
+ {
3918
+ outValue = float (INFINITY);
3919
+ return FloatFixKind::Unrepresentable;
3920
+ }
3921
+ }
3922
+ else if (value < -FLT_MAX)
3923
+ {
3924
+ if (Math::AreNearlyEqual (-value, FLT_MAX, epsilon))
3925
+ {
3926
+ outValue = -FLT_MAX;
3927
+ return FloatFixKind::Truncated;
3928
+ }
3929
+ else
3930
+ {
3931
+ outValue = -float (INFINITY);
3932
+ return FloatFixKind::Unrepresentable;
3933
+ }
3934
+ }
3935
+ else if (value && float (value) == 0 .0f )
3936
+ {
3937
+ outValue = 0 .0f ;
3938
+ return FloatFixKind::Zeroed;
3939
+ }
3940
+ break ;
3941
+ }
3942
+ case BaseType::Double:
3943
+ {
3944
+ // All representable
3945
+ break ;
3946
+ }
3947
+ case BaseType::Half:
3948
+ {
3949
+ // Fix out of range
3950
+ if (value > SLANG_HALF_MAX)
3951
+ {
3952
+ if (Math::AreNearlyEqual (value, FLT_MAX, epsilon))
3953
+ {
3954
+ outValue = SLANG_HALF_MAX;
3955
+ return FloatFixKind::Truncated;
3956
+ }
3957
+ else
3958
+ {
3959
+ outValue = float (INFINITY);
3960
+ return FloatFixKind::Unrepresentable;
3961
+ }
3962
+ }
3963
+ else if (value < -SLANG_HALF_MAX)
3964
+ {
3965
+ if (Math::AreNearlyEqual (-value, FLT_MAX, epsilon))
3966
+ {
3967
+ outValue = -SLANG_HALF_MAX;
3968
+ return FloatFixKind::Truncated;
3969
+ }
3970
+ else
3971
+ {
3972
+ outValue = -float (INFINITY);
3973
+ return FloatFixKind::Unrepresentable;
3974
+ }
3975
+ }
3976
+ else if (value && Math::Abs (value) < SLANG_HALF_SUB_NORMAL_MIN)
3977
+ {
3978
+ outValue = 0 .0f ;
3979
+ return FloatFixKind::Zeroed;
3980
+ }
3981
+ break ;
3982
+ }
3983
+ default : break ;
3984
+ }
3985
+ }
3986
+
3987
+ outValue = value;
3988
+ return FloatFixKind::None;
3989
+ }
3990
+
3889
3991
static RefPtr<Expr> parseAtomicExpr (Parser* parser)
3890
3992
{
3891
3993
switch ( peekTokenType (parser) )
@@ -4109,7 +4211,6 @@ namespace Slang
4109
4211
char const * suffixCursor = suffix.begin ();
4110
4212
const char *const suffixEnd = suffix.end ();
4111
4213
4112
-
4113
4214
// Default is Float
4114
4215
BaseType suffixBaseType = BaseType::Float;
4115
4216
if ( suffixCursor < suffixEnd )
@@ -4176,64 +4277,26 @@ namespace Slang
4176
4277
// might change in the future, and is arguably more 'correct'.
4177
4278
4178
4279
FloatingPointLiteralValue fixedValue = value;
4280
+ auto fixType = _fixFloatLiteralValue (suffixBaseType, value, fixedValue);
4179
4281
4180
- // Check the value is finite for checking narrowing to literal type losing information
4181
- if (_isFinite (fixedValue))
4282
+ switch (fixType)
4182
4283
{
4183
- switch (suffixBaseType)
4284
+ case FloatFixKind::Truncated:
4285
+ case FloatFixKind::None:
4184
4286
{
4185
- case BaseType::Float:
4186
- {
4187
- // Fix out of range
4188
- if (fixedValue > FLT_MAX)
4189
- {
4190
- fixedValue = float (INFINITY);
4191
- }
4192
- else if (fixedValue < -FLT_MAX)
4193
- {
4194
- fixedValue = -float (INFINITY);
4195
- }
4196
- else if (fixedValue && float (fixedValue) == 0 .0f )
4197
- {
4198
- fixedValue = 0 .0f ;
4199
- }
4200
- break ;
4201
- }
4202
- case BaseType::Double:
4203
- {
4204
- break ;
4205
- }
4206
- case BaseType::Half:
4207
- {
4208
- // Fix out of range
4209
- if (fixedValue > SLANG_HALF_MAX)
4210
- {
4211
- fixedValue = float (INFINITY);
4212
- }
4213
- else if (fixedValue < -SLANG_HALF_MAX)
4214
- {
4215
- fixedValue = -float (INFINITY);
4216
- }
4217
- else if (fixedValue && Math::Abs (fixedValue) < SLANG_HALF_SUB_NORMAL_MIN)
4218
- {
4219
- fixedValue = 0 .0f ;
4220
- }
4221
- break ;
4222
- }
4223
- default : break ;
4287
+ // No warning.
4288
+ // The truncation allowed must be very small. When Truncated the value *is* changed though.
4289
+ break ;
4224
4290
}
4225
-
4226
-
4227
- if (fixedValue != value)
4291
+ case FloatFixKind::Zeroed:
4228
4292
{
4229
- if (fixedValue == 0.0 )
4230
- {
4231
- parser->sink ->diagnose (token, Diagnostics::floatLiteralTooSmall, BaseTypeInfo::asText (suffixBaseType), token.Content , fixedValue);
4232
- }
4233
- else
4234
- {
4235
- parser->sink ->diagnose (token, Diagnostics::floatLiteralUnrepresentable, BaseTypeInfo::asText (suffixBaseType), token.Content , fixedValue);
4236
- }
4293
+ parser->sink ->diagnose (token, Diagnostics::floatLiteralTooSmall, BaseTypeInfo::asText (suffixBaseType), token.Content , fixedValue);
4294
+ break ;
4295
+ }
4296
+ case FloatFixKind::Unrepresentable:
4297
+ {
4298
+ parser->sink ->diagnose (token, Diagnostics::floatLiteralUnrepresentable, BaseTypeInfo::asText (suffixBaseType), token.Content , fixedValue);
4299
+ break ;
4237
4300
}
4238
4301
}
4239
4302
0 commit comments