-
-
Save SchrodingerZhu/84a334f8666b567800624446d354b568 to your computer and use it in GitHub Desktop.
| struct Lancern; | |
| struct QuaticCat; | |
| struct Float; | |
| union Union; | |
| struct Lancern | |
| { | |
| float professional; | |
| unsigned long genius; | |
| }; | |
| struct QuaticCat | |
| { | |
| float excellent; | |
| long magnificent; | |
| }; | |
| struct Float | |
| { | |
| __uint32_t mant:23; | |
| __uint32_t exp:8; | |
| __uint32_t sign:1; | |
| }; | |
| union Union | |
| { | |
| struct Lancern professional; | |
| struct QuaticCat genius; | |
| struct Float _float; | |
| }; | |
| static union Union union_data = (union Union) {.genius=(struct QuaticCat) {.excellent=(float)0.156250, .magnificent=(long)-1}}; | |
| extern int | |
| main () | |
| { | |
| unsigned long %3; | |
| unsigned long %4; | |
| bool %5; | |
| struct Float %7; | |
| __uint32_t %8; | |
| __uint32_t %9; | |
| __uint32_t %10; | |
| __uint32_t %11; | |
| __uint32_t %12; | |
| __uint32_t %13; | |
| bool %14; | |
| bool %15; | |
| bool %16; | |
| bool %17; | |
| bool %18; | |
| int %20; | |
| bb0: | |
| %3 = union_data.professional.genius; | |
| %4 = (unsigned long)-1; | |
| %5 = %3 == %4; | |
| if (%5) goto bb1; else goto bb2; | |
| bb1: | |
| %7 = union_data._float; | |
| %8 = %7.sign:1; | |
| %9 = %7.exp:8; | |
| %10 = %7.mant:23; | |
| %11 = (__uint32_t)0; | |
| %12 = (__uint32_t)124; | |
| %13 = (__uint32_t)2097152; | |
| %14 = %8 == %11; | |
| %15 = %9 == %12; | |
| %16 = %10 == %13; | |
| %17 = %14 && %15; | |
| %18 = %17 && %16; | |
| if (%18) goto bb3; else goto bb2; | |
| bb2: | |
| (void)__builtin_trap (); | |
| goto bb2; | |
| bb3: | |
| %20 = (int)0; | |
| return %20; | |
| } | |
It maybe the case that the way GCCJIT frontend generates the code will allow backend to think this as an "access to the inactive union field", which is undefined. Although I am uncertain about the semantic difference between GCCJIT and C.
P.S. The code on godbolt was in C++, which indeed regards this as an undefined behavior. One should switch to a C compiler instead. However, I believe there is no difference for clang/gcc in this particular case.
Pointed out by @Lancern
GNU C and C++ has this as defined code though (it is undefined in standard C/C++ due to the activeness of an union field). https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Optimize-Options.html#index-fstrict-aliasing
The GIMPLE smeantics are the same with respect to an union access is the same as the GNU C too.
Even after I making Float the same size as others by padding long to its tail and utilizing bitcast to to convert union to target struct, the problem still exists.
Even a simple program like:
struct Int;
struct Int
{
int A:17;
int B:5;
int C:10;
};
static void
from_int_to_bitfield (int %arg0, int %arg1)
{
int %0;
int %1;
struct Int %2;
int %3;
bool %4;
bb0:
%0 = %arg0;
%1 = %arg1;
%2 = bitcast(%0, struct Int);
%3 = %2.A:17;
%4 = %3 == %1;
if (%4) goto bb1; else goto bb2;
bb1:
return;
bb2:
(void)__builtin_trap ();
goto bb2;
}
extern int
main ()
{
int %0;
int %1;
int %2;
bb0:
%0 = (int)-559038737;
%1 = (int)-16657;
(void)from_int_to_bitfield (%0, %1);
%2 = (int)0;
return %2;
}
will be folded into ud2, which exits normally when the function is not internal
I do see
from the C frontend. I am not sure whether
libgccjitshould have done the same thing.