Open dmk42 opened 7 years ago
The C14 Standard states in 6.2.5: each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.
If the code were changed such that a "pointer to an array of two elements" were used, or the function parameter itself were declare as void *
it seems like the punning is allowed?
Right, one way to avoid undefined behavior would be to have the compiler change the type it used to be an array of two floats, or a union containing a complex number and an array of two floats. The latter seems like it could be done pretty elegantly.
Another conforming method would be to use something like memcpy()
to access the individual components.
Yet another way would be to use getter and setter functions for the individual components' values (instead of getting their addresses), and those functions could access through a union or via memcpy()
. That would keep the compiler from having to change the types it uses. It depends on what is easiest given the architecture of the compiler.
I've tried a few different methods and some valid ones still crash gcc -- but in that situation the fault is entirely gcc's.
It would be a good idea to change to one of the blessed methods so that some future optimizer doesn't ruin our day. If that also allows gcc 7 to work, that's a bonus, but it isn't the long-term purpose.
tagging @daviditen on this issue since he's worked on Chapel's complex numbers most recently
Summary of Problem
Chapel programs use type punning to attempt to get refs to the individual components of complex numbers. The method used is invalid in C; the behavior is undefined so that type-based alias analysis can be performed on complex numbers. Gcc 7.1 happens to react with an internal compiler error with optimization level -O2 or higher, but the Chapel generated code is invalid, triggering an unexpected case.
In
modules/standard/Types.chpl
the implementation ofmax()
for complex numbers is as follows.The Chapel code translates to the following C code. This C code is greatly hand-simplified to make it easier to read and independent of header files, but it still triggers the undefined behavior leading to the gcc compiler error.
The
complex64GetRealRef()
andcomplex64GetImagRef()
functions are inruntime/include/chpltypes.h
so this might seem like a bug in the runtime. However, the real problem is that the generated code needs these functions because it expects to get refs to the individual components of a complex number.If the generated code could do something along these lines, it would accomplish the desired result without undefined behavior.
Steps to Reproduce
Source Code:
Please see the example above. For a complete Chapel program that triggers the bug, see
test/trivial/waynew/maxtest.chpl
.Compile command:
chpl --fast test/trivial/wanew/maxtest.chpl
Execution command: When the backend compiler is gcc 7.1, execution is not possible because the compilation aborts.
Associated Future Test(s): N/A
Configuration Information
chpl --version
:$CHPL_HOME/util/printchplenv --anonymize
:gcc --version
orclang --version
:module list
: N/A