[llvm-dev] double to unsigned char cast

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[llvm-dev] double to unsigned char cast

韩玉 via llvm-dev

This doesn't seem right to me.
Both of these should have the and 0xff.

$ cat /s/1.c
unsigned char f1 (double i)
{
        return (unsigned char)i;
}

unsigned char f2 (double i)
{
        return (unsigned char)(int)i;
}

$ clang --version

Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

$ clang -arch arm64 -O2 -S -c /s/1.c && more 1.s

_f1:   
        fcvtzs  w0, d0
        ret

_f2:   
        fcvtzs  w8, d0
        and     w0, w8, #0xff
        ret


_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] double to unsigned char cast

韩玉 via llvm-dev
Hi Jay,

On 5 April 2018 at 07:49, Jay K via llvm-dev <[hidden email]> wrote:
> wrt
> https://github.com/mono/mono/commit/fb91fce5d339bb9ffe507588f5bc1d8d6f244d9b
>
>
> This doesn't seem right to me.

Nevertheless, it's what the standard says. C99 6.3.1.4: When a finite
value of real floating type is converted to an integer type other than
_Bool, the fractional part is discarded (i.e. the value is truncated
toward zero). If the value of the integral part cannot be represented
by the integer type, the behavior is undefined.

By definition any double you're allowed to convert to an unsigned char
doesn't need the "and".

Cheers.

Tim.
_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] double to unsigned char cast

韩玉 via llvm-dev

This seems disappointing.

Casting any value to an integral type should yield a value within the range of that integral type.

The value can be anything, but it should be within range.

i.e. it should be as if I anded it with (type)~(type)0.


i.e. int i = (signed char)x;

assert(i >= -128 && i <= 127);


int i = (unsigned char)x;

assert(i >= 0 && i <= 255);


seem very reasonable, assuming there is no "trap"  before the assert.

 - Jay




From: Tim Northover <[hidden email]>
Sent: Thursday, April 5, 2018 4:41 PM
To: Jay K
Cc: [hidden email]; [hidden email]
Subject: Re: [llvm-dev] double to unsigned char cast
 
Hi Jay,

On 5 April 2018 at 07:49, Jay K via llvm-dev <[hidden email]> wrote:
> wrt
> https://github.com/mono/mono/commit/fb91fce5d339bb9ffe507588f5bc1d8d6f244d9b

>
>
> This doesn't seem right to me.

Nevertheless, it's what the standard says. C99 6.3.1.4: When a finite
value of real floating type is converted to an integer type other than
_Bool, the fractional part is discarded (i.e. the value is truncated
toward zero). If the value of the integral part cannot be represented
by the integer type, the behavior is undefined.

By definition any double you're allowed to convert to an unsigned char
doesn't need the "and".

Cheers.

Tim.

_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] double to unsigned char cast

韩玉 via llvm-dev
On Tue, May 22, 2018 at 6:17 PM, Jay K via llvm-dev
<[hidden email]> wrote:
> This seems disappointing.
>
> Casting any value to an integral type should yield a value within the range
> of that integral type.

As Tim pointed out, that's not what the standard says though.

Trunk Clang (I'm not sure what version your Xcode Clang is based on)
has a flag to disable this optimization:
-fno-strict-float-cast-overflow

 - Hans


> The value can be anything, but it should be within range.
>
> i.e. it should be as if I anded it with (type)~(type)0.
>
>
> i.e. int i = (signed char)x;
>
> assert(i >= -128 && i <= 127);
>
>
> int i = (unsigned char)x;
>
> assert(i >= 0 && i <= 255);
>
>
> seem very reasonable, assuming there is no "trap"  before the assert.
>
>  - Jay
>
>
>
> ________________________________
> From: Tim Northover <[hidden email]>
> Sent: Thursday, April 5, 2018 4:41 PM
> To: Jay K
> Cc: [hidden email]; [hidden email]
> Subject: Re: [llvm-dev] double to unsigned char cast
>
> Hi Jay,
>
> On 5 April 2018 at 07:49, Jay K via llvm-dev <[hidden email]>
> wrote:
>> wrt
>>
>> https://github.com/mono/mono/commit/fb91fce5d339bb9ffe507588f5bc1d8d6f244d9b
>
>>
>>
>> This doesn't seem right to me.
>
> Nevertheless, it's what the standard says. C99 6.3.1.4: When a finite
> value of real floating type is converted to an integer type other than
> _Bool, the fractional part is discarded (i.e. the value is truncated
> toward zero). If the value of the integral part cannot be represented
> by the integer type, the behavior is undefined.
>
> By definition any double you're allowed to convert to an unsigned char
> doesn't need the "and".
>
> Cheers.
>
> Tim.
>
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] double to unsigned char cast

韩玉 via llvm-dev
I'd also note that -fsanitize=undefined will detect the error at runtime.

On Fri, May 25, 2018 at 4:38 AM Hans Wennborg via llvm-dev <[hidden email]> wrote:
On Tue, May 22, 2018 at 6:17 PM, Jay K via llvm-dev
<[hidden email]> wrote:
> This seems disappointing.
>
> Casting any value to an integral type should yield a value within the range
> of that integral type.

As Tim pointed out, that's not what the standard says though.

Trunk Clang (I'm not sure what version your Xcode Clang is based on)
has a flag to disable this optimization:
-fno-strict-float-cast-overflow

 - Hans


> The value can be anything, but it should be within range.
>
> i.e. it should be as if I anded it with (type)~(type)0.
>
>
> i.e. int i = (signed char)x;
>
> assert(i >= -128 && i <= 127);
>
>
> int i = (unsigned char)x;
>
> assert(i >= 0 && i <= 255);
>
>
> seem very reasonable, assuming there is no "trap"  before the assert.
>
>  - Jay
>
>
>
> ________________________________
> From: Tim Northover <[hidden email]>
> Sent: Thursday, April 5, 2018 4:41 PM
> To: Jay K
> Cc: [hidden email]; [hidden email]
> Subject: Re: [llvm-dev] double to unsigned char cast
>
> Hi Jay,
>
> On 5 April 2018 at 07:49, Jay K via llvm-dev <[hidden email]>
> wrote:
>> wrt
>>
>> https://github.com/mono/mono/commit/fb91fce5d339bb9ffe507588f5bc1d8d6f244d9b
>
>>
>>
>> This doesn't seem right to me.
>
> Nevertheless, it's what the standard says. C99 6.3.1.4: When a finite
> value of real floating type is converted to an integer type other than
> _Bool, the fractional part is discarded (i.e. the value is truncated
> toward zero). If the value of the integral part cannot be represented
> by the integer type, the behavior is undefined.
>
> By definition any double you're allowed to convert to an unsigned char
> doesn't need the "and".
>
> Cheers.
>
> Tim.
>
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] double to unsigned char cast

韩玉 via llvm-dev

I acknowledge that the type system is full of holes ("C++ is not safe") and the standard gives you leeway, but I've never before witnessed a cast to an integer type not yielding some value in range for that integer type. And even clang does provide such here, on x86 and amd64.


I have to also read our spec to see what we are supposed to return here also.

The "workaround" of casting to int first doesn't seem any better defined than casting directly to char, given a double that doesn't fit in int either.


 - Jay


From: James Y Knight <[hidden email]>
Sent: Friday, May 25, 2018 1:39 PM
To: Hans Wennborg
Cc: [hidden email]; llvm-dev; [hidden email]
Subject: Re: [llvm-dev] double to unsigned char cast
 
I'd also note that -fsanitize=undefined will detect the error at runtime.

On Fri, May 25, 2018 at 4:38 AM Hans Wennborg via llvm-dev <[hidden email]> wrote:
On Tue, May 22, 2018 at 6:17 PM, Jay K via llvm-dev
<[hidden email]> wrote:
> This seems disappointing.
>
> Casting any value to an integral type should yield a value within the range
> of that integral type.

As Tim pointed out, that's not what the standard says though.

Trunk Clang (I'm not sure what version your Xcode Clang is based on)
has a flag to disable this optimization:
-fno-strict-float-cast-overflow

 - Hans


> The value can be anything, but it should be within range.
>
> i.e. it should be as if I anded it with (type)~(type)0.
>
>
> i.e. int i = (signed char)x;
>
> assert(i >= -128 && i <= 127);
>
>
> int i = (unsigned char)x;
>
> assert(i >= 0 && i <= 255);
>
>
> seem very reasonable, assuming there is no "trap"  before the assert.
>
>  - Jay
>
>
>
> ________________________________
> From: Tim Northover <[hidden email]>
> Sent: Thursday, April 5, 2018 4:41 PM
> To: Jay K
> Cc: [hidden email]; [hidden email]
> Subject: Re: [llvm-dev] double to unsigned char cast
>
> Hi Jay,
>
> On 5 April 2018 at 07:49, Jay K via llvm-dev <[hidden email]>
> wrote:
>> wrt
>>
>> https://github.com/mono/mono/commit/fb91fce5d339bb9ffe507588f5bc1d8d6f244d9b
>
>>
>>
>> This doesn't seem right to me.
>
> Nevertheless, it's what the standard says. C99 6.3.1.4: When a finite
> value of real floating type is converted to an integer type other than
> _Bool, the fractional part is discarded (i.e. the value is truncated
> toward zero). If the value of the integral part cannot be represented
> by the integer type, the behavior is undefined.
>
> By definition any double you're allowed to convert to an unsigned char
> doesn't need the "and".
>
> Cheers.
>
> Tim.
>
> _______________________________________________
> LLVM Developers mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev