Comment #0 by dlang-bugzilla — 2017-08-07T01:38:08Z
Although the issue doesn't occur with the latest DMD versions, building older versions is still important for bootstrapping, so I'm opening this issue to track the problem.
On Arch Linux, attempting to build D versions from 2015 or earlier will result in a segmentation fault while building Druntime, e.g.:
path/to/dmd -lib -oflib/libdruntime-linux64.a -Xfdruntime.json -m64 -O -release -inline -w -Isrc -Iimport src/object_.d src/core/atomic.d ...
make: *** [posix.mak:172: lib/libdruntime-linux64so.a] Segmentation fault (core dumped)
make: *** Waiting for unfinished jobs....
make: *** [posix.mak:178: lib/libdruntime-linux64.a] Segmentation fault (core dumped)
On Arch Linux, the build succeeds with the packages:
- gcc-libs-multilib
- gcc-multilib
- lib32-gcc-libs
are at version 6.3.1-2, but fails at version 7.1.1-3.
Arch Linux pushed GCC 7.1 to the multilib repo on 2017-05-30.
D versions since https://github.com/dlang/dmd/pull/4924 build OK with any GCC version. I suspect that the behaviour changed due to the change in default optimization flags. This is possibly an optimizer regression in GCC 7.x.
Comment #1 by dlang-bugzilla — 2017-08-07T01:41:38Z
(In reply to Vladimir Panteleev from comment #0)
> On Arch Linux, attempting to build D versions from 2015 or earlier
I should clarify that the method used was with Digger (e.g. "digger build master@2015-01-01"). I've just pushed an update with a workaround for the PIC/PIE issue.
Comment #2 by dlang-bugzilla — 2017-08-07T01:56:31Z
Works fine without "CFLAGS += -O2", so it looks like either a GCC optimizer bug, or UB in DMD.
Comment #3 by dlang-bugzilla — 2017-08-07T02:47:05Z
Minimal object.d:
////////////////// object_.d //////////////////
module object;
class Object {}
struct OffsetTypeInfo {}
class TypeInfo {}
class TypeInfo_Class { void[136] foo = void; }
class TypeInfo_Struct { void[120] foo = void; }
struct ModuleInfo {}
auto fun()
{
return (cast(int*)null)[0 .. 1];
}
///////////////////////////////////////////////
`dmd -c -m64 object_.d` will segfault if dmd was built with GCC 7.1 and -O2.
Comment #4 by dlang-bugzilla — 2017-08-07T03:16:03Z
Narrowed down the file to backend/evalu8.c. (Segfault manifests iff that file is compiled with -O2).
Comment #5 by dlang-bugzilla — 2017-08-07T05:35:49Z
Segfault occurs on the line:
esave = *e;
The line is inside the evalu8 function, which is also the only function needed to be compiled with -O2 for the bug to manifest.
Comment #6 by dlang-bugzilla — 2017-08-07T15:24:53Z
Finally reduced:
////////////// test.cpp //////////////
#include <stdio.h>
union U
{
double Vdouble;
long double Vldouble;
};
void fun(U *e)
{
U esave = {};
printf("Before crash\n");
esave = *e; // <--- SEGFAULTS HERE
printf("After crash\n");
*e = esave;
}
int main()
{
// Must be unaligned
char buf[128] = {0};
U* e = (U*)&buf[1];
fun(e);
return 0;
}
//////////////////////////////////////
g++ -O0 -otest test.cpp && ./test && g++ -O2 -otest test.cpp && ! ./test
Comment #7 by dlang-bugzilla — 2017-08-07T15:42:56Z
GCC 7 uses movdqa/movaps instructions, which require the address to be aligned to 16 bytes, so GCC expects the elem* instances to be aligned. However, they aren't aligned in DMD.
Comment #8 by dlang-bugzilla — 2017-08-07T16:12:39Z
elem* instances aren't 16-byte-aligned because of the following code in tk/mem.c:
#if defined(__llvm__) && (defined(__GNUC__) || defined(__clang__))
// LLVM-GCC and Clang assume some types, notably elem (see DMD issue 6215),
// to be 16-byte aligned. Because we do not have any type information
// available here, we have to 16 byte-align everything.
numbytes = (numbytes + 0xF) & ~0xF;
#else
if (sizeof(size_t) == 2)
numbytes = (numbytes + 1) & ~1; /* word align */
else
numbytes = (numbytes + 3) & ~3; /* dword align */
#endif
Looks like the same restrictions which apply to LLVM now also apply to GCC 7.
Although I would expect that master would fail in the same way when built with RELEASE=1, it doesn't seem to be the case.
Comment #9 by dlang-bugzilla — 2017-08-07T16:24:09Z
(In reply to Vladimir Panteleev from comment #8)
> Although I would expect that master would fail in the same way when built
> with RELEASE=1, it doesn't seem to be the case.
Oops, no, that was fixed in https://github.com/dlang/dmd/pull/6795.
Comment #10 by dlang-bugzilla — 2017-08-07T16:40:22Z