This is an archive of the discontinued LLVM Phabricator instance.

[Linux] Hack around Linux/sparc <bits/stdio-ldbl.h>
ClosedPublic

Authored by ro on Sep 7 2022, 1:53 AM.

Details

Summary

I've been using this hack to work around the Linux/sparc64 compile failure described in Issue #47994, especially since the underlying glibc PR build/27558 doesn't seem to be making progress and some fix is required to have LLVM build on sparc64-unknown-linux-gnu at all, as evidenced on the buildbot.

I don't expect this patch to be commited, just posting for reference.

Tested on sparc64-unknown-linux-gnu.

Diff Detail

Event Timeline

ro created this revision.Sep 7 2022, 1:53 AM
ro requested review of this revision.Sep 7 2022, 1:53 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 7 2022, 1:53 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Thanks, this is definitely very useful. I have pinged glibc upstream and asked them about the progress about this change. Let' see.

It's not a compiler's job to define this workaround... If a platform want to provide a built-in macro, you can use https://clang.llvm.org/docs/UsersManual.html#configuration-files and add -D__NO_INLINE__ there.
To avoid magic behaviors, ${triple}-clang loads ${triple}.cfg while clang doesn't (see https://discourse.llvm.org/t/configuration-files/42529/24)

See also https://discourse.llvm.org/t/rfc-adding-a-default-file-location-to-config-file-support/63606 (I am somewhat concerned with clang loading a config).
But if you make clang a shell script that executes sparc64-pc-linux-gnu-clang or the like, I think it should be fine.

ro added a comment.Sep 8 2022, 4:30 AM

It's not a compiler's job to define this workaround...

Yes and no: GCC successfully does it via its fixincludes mechanism. Unfortunately, LLVM doesn't provide something similar and doesn't even known about the GCC include-fixed directory, which could be used as a fallback. Sometimes OS headers are broken and remain so for a long time. While one can throw hands up in disgust, this doesn't make the problem go away. If I own the machine, I can patch/hack system headers as need be, but that's not an option on shared systems where I have to live with what's installed.

If a platform want to provide a built-in macro, you can use https://clang.llvm.org/docs/UsersManual.html#configuration-files and add -D__NO_INLINE__ there.
To avoid magic behaviors, ${triple}-clang loads ${triple}.cfg while clang doesn't (see https://discourse.llvm.org/t/configuration-files/42529/24)

That's nice in some controlled circumstances where I can control e.g. the clang command used, but doesn't help in others like a release build with test-release.sh where I don't have that control. I fully understand Jörg's argument in that thread that implicit changes from some hidden config file/environment variable are a maintenance nightmare and to be avoided at all cost.

See also https://discourse.llvm.org/t/rfc-adding-a-default-file-location-to-config-file-support/63606 (I am somewhat concerned with clang loading a config).
But if you make clang a shell script that executes sparc64-pc-linux-gnu-clang or the like, I think it should be fine.

Again, that would be ok for an installed clang, but while doing a release build, such a script wouldn't be used at all.

On top of all that, defining __NO_INLINE__ globally to hack around a header bug is way too large a hammer: it has more effects than it should, which is why I called it a hack to allow making some progess at all, nothing to be included upstream. I merely wanted to document what I'd changed in the Linux/sparc64 release builds rather than only vaguely referring to my hack.

MaskRay accepted this revision.EditedSep 8 2022, 8:55 PM
MaskRay added a subscriber: zatrazz.

So, sparc64 gcc does seem to define the macro by default. (I am using Debian testing and can't tell whether it's distro setting or upstream default) ¯\_(ツ)_/¯

% sparc64-linux-gnu-gcc -E -dM -xc /dev/null -nostdinc | grep NO_INLINE
#define __NO_INLINE__ 1

This needs a test in clang/test/Preprocessor/init.c (find SPARC) with a comment linking to the canonical place to discuss the glibc problem (@zatrazz).

This revision is now accepted and ready to land.Sep 8 2022, 8:55 PM
ro added a comment.Sep 9 2022, 5:15 AM

So, sparc64 gcc does seem to define the macro by default. (I am using Debian testing and can't tell whether it's distro setting or upstream default) ¯\_(ツ)_/¯

% sparc64-linux-gnu-gcc -E -dM -xc /dev/null -nostdinc | grep NO_INLINE
#define __NO_INLINE__ 1

True, as does clang. However, both define it only at -O0. This is common upstream behaviour in both cases.

The following reduced testcase demonstrates the issue:

$ cat vfprintf-ldbl.c 
struct _IO_FILE;
typedef struct _IO_FILE FILE;
extern FILE *stdout;
typedef __builtin_va_list __gnuc_va_list;
extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
		     __gnuc_va_list __arg);
extern int __inline __attribute__ ((__gnu_inline__))
vprintf (const char *__restrict __fmt, __gnuc_va_list __arg)
{
  return vfprintf (stdout, __fmt, __arg);
}
extern __typeof (vfprintf) vfprintf __asm ("" "_nldbl" "vfprintf");

makes clang choke

$ clang -c vfprintf-ldbl.c
vfprintf-ldbl.c:12:28: error: cannot apply asm label to function after its first use
extern __typeof (vfprintf) vfprintf __asm ("" "_nldbl" "vfprintf");
                           ^               ~~
1 error generated.

while gcc compiles this without issues.

This needs a test in clang/test/Preprocessor/init.c (find SPARC) with a comment linking to the canonical place to discuss the glibc problem (@zatrazz).

Done now and tested on sparcv9-sun-solaris2.11. Will also test on sparc64-unknown-linux-gnu once the currently running release build is finished (this box is slow).

ro updated this revision to Diff 459017.Sep 9 2022, 5:16 AM

Add comment, tests.

glaubitz accepted this revision.Sep 9 2022, 5:20 AM
This revision was automatically updated to reflect the committed changes.
nikic added a subscriber: nikic.Sep 10 2022, 12:53 AM

I've been using this hack to work around the Linux/sparc64 compile failure described in Issue #47994, especially since the underlying glibc PR build/27558 doesn't seem to be making progress and some fix is required to have LLVM build on sparc64-unknown-linux-gnu at all, as evidenced on the buildbot.

Didn't this already get fixed by https://github.com/bminor/glibc/commit/d0fa09a7701956036ff36f8ca188e9fff81553d8 upstream? There was also a later fix for the wchar.h header.

I've been using this hack to work around the Linux/sparc64 compile failure described in Issue #47994, especially since the underlying glibc PR build/27558 doesn't seem to be making progress and some fix is required to have LLVM build on sparc64-unknown-linux-gnu at all, as evidenced on the buildbot.

Didn't this already get fixed by https://github.com/bminor/glibc/commit/d0fa09a7701956036ff36f8ca188e9fff81553d8 upstream? There was also a later fix for the wchar.h header.

Seems it has only been fixed for some headers, see: https://sourceware.org/bugzilla/show_bug.cgi?id=27087

nikic added a comment.Sep 10 2022, 2:54 AM

I've been using this hack to work around the Linux/sparc64 compile failure described in Issue #47994, especially since the underlying glibc PR build/27558 doesn't seem to be making progress and some fix is required to have LLVM build on sparc64-unknown-linux-gnu at all, as evidenced on the buildbot.

Didn't this already get fixed by https://github.com/bminor/glibc/commit/d0fa09a7701956036ff36f8ca188e9fff81553d8 upstream? There was also a later fix for the wchar.h header.

Seems it has only been fixed for some headers, see: https://sourceware.org/bugzilla/show_bug.cgi?id=27087

The other issue has also already been fixed in https://github.com/bminor/glibc/commit/c7509d49c4e8fa494120c5ead21338559dad16f5 (and these fixes have been backported to glibc 2.34+).

Are you still seeing any issues with a current glibc?

I've been using this hack to work around the Linux/sparc64 compile failure described in Issue #47994, especially since the underlying glibc PR build/27558 doesn't seem to be making progress and some fix is required to have LLVM build on sparc64-unknown-linux-gnu at all, as evidenced on the buildbot.

Didn't this already get fixed by https://github.com/bminor/glibc/commit/d0fa09a7701956036ff36f8ca188e9fff81553d8 upstream? There was also a later fix for the wchar.h header.

Seems it has only been fixed for some headers, see: https://sourceware.org/bugzilla/show_bug.cgi?id=27087

The other issue has also already been fixed in https://github.com/bminor/glibc/commit/c7509d49c4e8fa494120c5ead21338559dad16f5 (and these fixes have been backported to glibc 2.34+).

Are you still seeing any issues with a current glibc?

glibc 2.34 currently fails to build from source on sparc64 due to testsuite failures. I haven't reported these upstream yet which I will do now.

See: https://buildd.debian.org/status/fetch.php?pkg=glibc&arch=sparc64&ver=2.34-7&stamp=1661614017&raw=0

FAIL: elf/tst-audit24a
FAIL: elf/tst-audit24b
FAIL: elf/tst-audit24c
FAIL: elf/tst-audit24d
FAIL: elf/tst-audit25a
FAIL: elf/tst-audit25b
FAIL: elf/tst-ptrguard1-static
FAIL: elf/tst-stackguard1-static
FAIL: nptl/tst-cancel24-static
FAIL: nptl/tst-cancel30
FAIL: nptl/tst-pthread-attr-affinity-fail
FAIL: nptl/tst-stackguard1-static
FAIL: socket/tst-socket-timestamp