Package: gcc-mingw-w64
Version: 21.2

Hi!

I've discovered that mingw-w64 GCC in Debian is configured without linker plugin support: $ x86_64-w64-mingw32-gcc -x c - -flto -fno-fat-lto-objects <<<'int main() {}'
cc1: error: -fno-fat-lto-objects are supported only with linker plugin

This makes LTO unusable in many real-world cases. Consider the following example:

$ grep . *.c
foo.c:int foo() {return 42;}
main.c:int main() {return foo();}
$ x86_64-w64-mingw32-gcc -flto -O2 foo.c main.c -c
$ x86_64-w64-mingw32-ar cr app.a main.o foo.o
$ x86_64-w64-mingw32-gcc -flto -O2 app.a
$ x86_64-w64-mingw32-objdump -d a.exe | grep '<main>:' -A 5
0000000000402c30 <main>:
  402c30:       48 83 ec 28             sub    $0x28,%rsp
  402c34:       e8 d7 e9 ff ff          callq  401610 <__main>
  402c39:       90                      nop
  402c3a:       48 83 c4 28             add    $0x28,%rsp
402c3e: e9 0d e9 ff ff jmpq 401550 <foo> # 'foo' is not inlined

Note that 'foo' is not inlined because the archived object files weren't processed by LTO (they were processed by the linker as normal objects because they are "fat" LTO objects, i.e. they contain both normal object code and GCC IR).

$ x86_64-w64-mingw32-gcc -flto -O2 main.o foo.o
$ x86_64-w64-mingw32-objdump -d a.exe | grep '<main>:' -A 5
0000000000402c30 <main>:
  402c30:       48 83 ec 28             sub    $0x28,%rsp
  402c34:       e8 d7 e9 ff ff          callq  401610 <__main>
402c39: b8 2a 00 00 00 mov $0x2a,%eax # Good, 'foo' is inlined!
  402c3e:       48 83 c4 28             add    $0x28,%rsp
  402c42:       c3                      retq

In this case, legacy LTO implementation was used: GCC driver looked at the objects and called its 'lto-wrapper' helper. But it can't do that with archives.

This misconfiguration is caused by the incorrect use of '--with-plugin-ld' GCC configure option (or its strange behavior, depending on how you look at it):

$ x86_64-w64-mingw32-gcc -v
Using built-in specs.
COLLECT_GCC=x86_64-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-w64-mingw32/8.3-win32/lto-wrapper
Target: x86_64-w64-mingw32
Configured with: ../../src/configure --build=x86_64-linux-gnu --prefix=/usr --includedir='/usr/include' --mandir='/usr/share/man' --infodir='/usr/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir='/usr/lib/x86_64-linux-gnu' --libexecdir='/usr/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr --enable-shared --enable-static --disable-multilib --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --libdir=/usr/lib --enable-libstdcxx-time=yes --with-tune=generic --with-headers=/usr/x86_64-w64-mingw32/include --enable-version-specific-runtime-libs --enable-fully-dynamic-string --enable-libgomp --enable-languages=c,c++,fortran,objc,obj-c++,ada --enable-lto --with-plugin-ld --enable-threads=win32 --program-suffix=-win32 --program-prefix=x86_64-w64-mingw32- --target=x86_64-w64-mingw32 --with-as=/usr/bin/x86_64-w64-mingw32-as --with-ld=/usr/bin/x86_64-w64-mingw32-ld --enable-libatomic --enable-libstdcxx-filesystem-ts=yes
Thread model: win32
gcc version 8.3-win32 20190406 (GCC)

The problem is that "--with-plugin-ld" expects a linker path as the value, but if it's not given, the value becomes 'yes' and is then tested for plugin support, without much success (lookup "checking linker plugin support" in "https://buildd.debian.org/status/fetch.php?pkg=gcc-mingw-w64&arch=amd64&ver=21.2&stamp=1555227419&raw=0";).

This option is actually not needed since there is no need to use an "alternative" linker for plugins: the one that is passed with "--with-ld" will do. I've checked manually that if I remove "--with-plugin-ld" from the configuration of gcc-mingw-w64 source package, the linker plugin support is detected properly.

Ubuntu packages are also affected by this problem. I've checked that OpenSUSE Tumbleweed packages are not affected (they don't use "--with-plugin-ld").

I suggest to remove "--with-plugin-ld" from GCC configuration options.

Thanks!

-Alexey

Reply via email to