[Mesa-dev] [PATCH 2/7] gallium/auxiliary: Add u_bitcast.h header.

Matt Turner mattst88 at gmail.com
Wed Aug 10 19:35:36 UTC 2016


On Thu, Jul 28, 2016 at 9:55 PM, Connor Abbott <cwabbott0 at gmail.com> wrote:
> On Thu, Jul 28, 2016 at 7:58 PM, Roland Scheidegger <sroland at vmware.com> wrote:
>> Am 29.07.2016 um 00:35 schrieb Matt Turner:
>>> ---
>>>  src/gallium/auxiliary/Makefile.sources |  1 +
>>>  src/gallium/auxiliary/util/u_bitcast.h | 57 ++++++++++++++++++++++++++++++++++
>>>  2 files changed, 58 insertions(+)
>>>  create mode 100644 src/gallium/auxiliary/util/u_bitcast.h
>>>
>>> diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources
>>> index e0311bf..26f7eee 100644
>>> --- a/src/gallium/auxiliary/Makefile.sources
>>> +++ b/src/gallium/auxiliary/Makefile.sources
>>> @@ -175,6 +175,7 @@ C_SOURCES := \
>>>       translate/translate_generic.c \
>>>       translate/translate_sse.c \
>>>       util/dbghelp.h \
>>> +     util/u_bitcast.h \
>>>       util/u_bitmask.c \
>>>       util/u_bitmask.h \
>>>       util/u_blend.h \
>>> diff --git a/src/gallium/auxiliary/util/u_bitcast.h b/src/gallium/auxiliary/util/u_bitcast.h
>>> new file mode 100644
>>> index 0000000..b1f9938
>>> --- /dev/null
>>> +++ b/src/gallium/auxiliary/util/u_bitcast.h
>>> @@ -0,0 +1,57 @@
>>> +/**************************************************************************
>>> + *
>>> + * Copyright © 2016 Intel Corporation
>>> + * All Rights Reserved.
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining a
>>> + * copy of this software and associated documentation files (the
>>> + * "Software"), to deal in the Software without restriction, including
>>> + * without limitation the rights to use, copy, modify, merge, publish,
>>> + * distribute, sub license, and/or sell copies of the Software, and to
>>> + * permit persons to whom the Software is furnished to do so, subject to
>>> + * the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice (including the
>>> + * next paragraph) shall be included in all copies or substantial portions
>>> + * of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
>>> + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>>> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
>>> + * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
>>> + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
>>> + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
>>> + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
>>> + *
>>> + **************************************************************************/
>>> +
>>> +#ifndef U_BITCAST_H_
>>> +#define U_BITCAST_H_
>>> +
>>> +#include <string.h>
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +static inline unsigned
>>> +u_bitcast_f2u(float f)
>>> +{
>>> +   unsigned u;
>>> +   memcpy(&u, &f, sizeof(u));
>>> +   return u;
>>> +}
>>> +
>>> +static inline float
>>> +u_bitcast_u2f(unsigned u)
>>> +{
>>> +   float f;
>>> +   memcpy(&f, &u, sizeof(f));
>>> +   return f;
>>> +}
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif /* U_BITCAST_H_ */
>>>
>>
>> I think traditionally we've used the union fi from u_math.h to do this.
>> That said, I don't have anything against using an inline memcpy helper
>> function instead - both should hopefully get optimized away...
>
> Unfortunately, that won't work with the strict aliasing rules either
> since it's undefined behavior to reinterpret a union by dereferencing
> more than member. That is, once you assign to one field of a union,
> you can read from/write to that field only. You can, however,
> reinterpret anything as a char * and dereference, hence why memcopy
> etc. aren't undefined.

Sorry for the late reply, but I thought it was important to correct
this common misunderstanding (Even John Regehr gets it wrong! [1]).

Since at least C99, the union trick is fine. C99 Technical Corrigendum
3 [2] says:

"""
If the member used to access the contents of a union object is not the
same as the member last used to store a value in the object, the
appropriate part of the object representation of the value is
reinterpreted as an object representation in the new type as described
in 6.2.6 (a process sometimes called "type punning"). This might be a
trap representation.
"""

It seems, but I have not confirmed, that it is not legal in C++. I
cannot find a reference now, but I remember reading a C89
clarification that explained that it was only "unspecified" because of
the "trap representation" wording and was intended to have the same
semantics as C99.

Regardless, memcpy generates optimal code and is legal in C and C++.
Hence my choice in this series. (Aside: Hence Why Must Die [3])

[1] http://blog.regehr.org/archives/959
[2] http://www.open-std.org/Jtc1/sc22/wg14/www/docs/n1235.pdf
[3] http://public.wsu.edu/~brians/errors/hencewhy.html


More information about the mesa-dev mailing list