Hi! On 2020-03-23T16:29:40+0100, I wrote: > On 2018-09-14T10:18:12-0600, Jeff Law <l...@redhat.com> wrote: >> On 9/5/18 5:52 AM, a...@codesourcery.com wrote: >>> >>> The GCN toolchain must use the LLVM assembler and linker because there's no >>> binutils port. The LLVM tools do not have the same diagnostic style as >>> binutils > > For reference: > 'libgomp.c++/../libgomp.c-c++-common/function-not-offloaded.c', for > example: > > ld: error: undefined symbol: foo() > >>> referenced by /tmp/ccNzknBD.o:(main._omp_fn.0) > >>> referenced by /tmp/ccNzknBD.o:(main._omp_fn.0) > > ld: error: undefined symbol: __gxx_personality_v0 > >>> referenced by /tmp/ccNzknBD.o:(.data+0x13) > collect2: error: ld returned 1 exit status > mkoffload: fatal error: > [...]/build-gcc/./gcc/x86_64-pc-linux-gnu-accel-amdgcn-amdhsa-gcc returned 1 > exit status > > Note the blank line between the two "diagnostic blocks". > >>> so the "blank line(s) in output" tests are inappropriate (and very >>> noisy).
> So here is a different proposal. The problem we're having is that the > AMD GCN 'as' (that is, 'llvm-mc') prints "unsuitable" diagnostics (as > quoted at the top of my email). (No idea where I got the idea from that 'as' prints 'ld' error messages, as displayed above...) ;-) (But supposedly that problem applies to both, or even generally all LLVM tools?) > How about having a simple wrapper around it, to post-process its 'stderr' > to remove any blank linkes between "diagnostic blocks"? Then we could > remove this fragile 'check_effective_target_llvm_binutils' etc.? > > I shall offer to implement the simple shell script, and suppose this > could live in 'gcc/config/gcn/'? I have implemented that, and it appears to generally work, but of course... > ("Just" need to figure out how to > integrate that into the GCC build process, top-level build system.) ... this was the non-trivial bit, and may need some further thought -- which I can't allocate time for right now, so I'll postpone this for later. I'm attaching my "[WIP] 'llvm-tools-wrapper' [PR88920]" patch, in case somebody would like to have a first look. Grüße Thomas ----------------- Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter
>From 31c8828d37bed37b4ee4eb3bbefb8eb1db46e0a1 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge <tho...@codesourcery.com> Date: Tue, 24 Mar 2020 21:59:04 +0100 Subject: [PATCH] [WIP] 'llvm-tools-wrapper' [PR88920] PR testsuite/88920 --- gcc/Makefile.in | 9 ++ gcc/config.in | 6 + gcc/configure | 17 +++ gcc/configure.ac | 12 ++ gcc/doc/sourcebuild.texi | 6 - gcc/gcc.c | 116 +++++++++++++++--- gcc/llvm-tools-wrapper.in | 35 ++++++ gcc/testsuite/lib/gcc-dg.exp | 4 - gcc/testsuite/lib/target-supports.exp | 15 --- .../function-not-offloaded.c | 1 - 10 files changed, 175 insertions(+), 46 deletions(-) create mode 100755 gcc/llvm-tools-wrapper.in diff --git a/gcc/Makefile.in b/gcc/Makefile.in index fa9923bb2703..4d13707453b2 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1974,6 +1974,7 @@ start.encap: native xgcc$(exeext) cpp$(exeext) specs \ rest.encap: lang.rest.encap # This is what is made with the host's compiler # whether making a cross compiler or not. +#TODO Do we need 'llvm-tools-wrapper' here? native: config.status auto-host.h build-@POSUB@ $(LANGUAGES) \ $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext) \ gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext) @@ -3525,6 +3526,10 @@ ifeq ($(enable_plugin),yes) install: install-plugin endif +#TODO ifeq (TODO) +install: install-llvm-tools-wrapper +#TODO endif + install-strip: override INSTALL_PROGRAM = $(INSTALL_STRIP_PROGRAM) ifneq ($(STRIP),) install-strip: STRIPPROG = $(STRIP) @@ -3920,6 +3925,10 @@ install-gcc-ar: installdirs gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext) done; \ fi +# Install llvm-tools-wrapper. +install-llvm-tools-wrapper: llvm-tools-wrapper$(exeext) + $(INSTALL_PROGRAM) llvm-tools-wrapper$(exeext) $(DESTDIR)$(libexecsubdir)/llvm-tools-wrapper$(exeext) + # Cancel installation by deleting the installed files. uninstall: lang.uninstall -rm -rf $(DESTDIR)$(libsubdir) diff --git a/gcc/config.in b/gcc/config.in index 01fb18dbbb5a..ab51b9aef898 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -2042,6 +2042,12 @@ #endif +/* Define if using LLVM tools. */ +#ifndef USED_FOR_TARGET +#undef LLVM_TOOLS_WRAPPER +#endif + + /* Define to the name of the LTO plugin DSO that must be passed to the linker's -plugin=LIB option. */ #ifndef USED_FOR_TARGET diff --git a/gcc/configure b/gcc/configure index 5381e107bce7..06f46c4bd6b0 100755 --- a/gcc/configure +++ b/gcc/configure @@ -22994,6 +22994,21 @@ else $as_echo "$gcc_cv_otool" >&6; } fi +# Do we need the llvm-tools-wrapper? +#TODO Make this a feature test, or is that good enough? +case $target in + amdgcn*) + +$as_echo "#define LLVM_TOOLS_WRAPPER 1" >>confdefs.h + + #TODO Does this need any 'Makefile.in' support for stating regeneration dependencies? + #TODO This is modelled after the 'exec-tool.in' stuff. + ac_config_files="$ac_config_files llvm-tools-wrapper:llvm-tools-wrapper.in" + + ;; +esac + + # Figure out what assembler alignment features are present. { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler flags" >&5 $as_echo_n "checking assembler flags... " >&6; } @@ -31460,6 +31475,7 @@ do "as") CONFIG_FILES="$CONFIG_FILES as:exec-tool.in" ;; "collect-ld") CONFIG_FILES="$CONFIG_FILES collect-ld:exec-tool.in" ;; "nm") CONFIG_FILES="$CONFIG_FILES nm:exec-tool.in" ;; + "llvm-tools-wrapper") CONFIG_FILES="$CONFIG_FILES llvm-tools-wrapper:llvm-tools-wrapper.in" ;; "clearcap.map") CONFIG_LINKS="$CONFIG_LINKS clearcap.map:${srcdir}/config/$clearcap_map" ;; "$all_outputs") CONFIG_FILES="$CONFIG_FILES $all_outputs" ;; "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; @@ -32094,6 +32110,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} "as":F) chmod +x as ;; "collect-ld":F) chmod +x collect-ld ;; "nm":F) chmod +x nm ;; + "llvm-tools-wrapper":F) chmod +x llvm-tools-wrapper ;; "default":C) case ${CONFIG_HEADERS} in *auto-host.h:config.in*) diff --git a/gcc/configure.ac b/gcc/configure.ac index 0d6230e0ca1b..0f3fcfefd4fc 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -2685,6 +2685,18 @@ else AC_MSG_RESULT($gcc_cv_otool) fi +# Do we need the llvm-tools-wrapper? +#TODO Make this a feature test, or is that good enough? +case $target in + amdgcn*) + AC_DEFINE(LLVM_TOOLS_WRAPPER, 1, [Define if using LLVM tools.]) + #TODO Does this need any 'Makefile.in' support for stating regeneration dependencies? + #TODO This is modelled after the 'exec-tool.in' stuff. + AC_CONFIG_FILES(llvm-tools-wrapper:llvm-tools-wrapper.in, [chmod +x llvm-tools-wrapper]) + ;; +esac + + # Figure out what assembler alignment features are present. gcc_GAS_CHECK_FEATURE([.balign and .p2align], gcc_cv_as_balign_and_p2align, [2,6,0],, diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index eef1432147ce..d6057656c6ef 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2333,9 +2333,6 @@ Target uses GNU @command{ld}. Target keeps null pointer checks, either due to the use of @option{-fno-delete-null-pointer-checks} or hardwired into the target. -@item llvm_binutils -Target is using an LLVM assembler and/or linker, instead of GNU Binutils. - @item lto Compiler has been configured to support link-time optimization (LTO). @@ -2363,9 +2360,6 @@ Target supports the @code{noinit} variable attribute. @item nonpic Target does not generate PIC by default. -@item offload_gcn -Target has been configured for OpenACC/OpenMP offloading on AMD GCN. - @item pie_enabled Target generates PIE by default. diff --git a/gcc/gcc.c b/gcc/gcc.c index 9f790db0daf4..eb0fb836ffc0 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -3038,11 +3038,18 @@ execute (void) gcc_assert (!processing_spec_function); + /* TODO Why is this wrapping here done "early", instead of "late", as done + for the 'valgrind' wrapping? */ if (wrapper_string) { string = find_a_file (&exec_prefixes, argbuf[0], X_OK, false); if (string) + /* This overwrites 'argbuf[0]', thus later 'commands[0].prog' is set to + the resolved 'string' instead of the original 'argbuf[0]'. This + means that any special handling for 'argbuf[0]' can no longer be + expected to work (such as when 'find_a_file' compares this to 'as' + or 'ld'). */ argbuf[0] = string; insert_wrapper (wrapper_string); } @@ -3064,6 +3071,7 @@ execute (void) commands[0].prog = argbuf[0]; /* first command. */ commands[0].argv = argbuf.address (); + /* TODO For 'wrapper_string', this has already been done above. */ if (!wrapper_string) { string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false); @@ -3164,32 +3172,100 @@ execute (void) #endif /* DEBUG */ } -#ifdef ENABLE_VALGRIND_CHECKING - /* Run the each command through valgrind. To simplify prepending the - path to valgrind and the option "-q" (for quiet operation unless - something triggers), we allocate a separate argv array. */ - + /* Possibly run each command through a wrapper. */ + //TODO Why is this done after '-v' handling? for (i = 0; i < n_commands; i++) { - const char **argv; - int argc; - int j; - - for (argc = 0; commands[i].argv[argc] != NULL; argc++) - ; + size_t argc_wrap_llvm_tools_wrapper = 0; +#ifdef LLVM_TOOLS_WRAPPER //TODO Conditional whether assembler (?TODO), linker (even separately?) are LLVM tools. + //TODO For offloading compilation (I haven't tried native yet), something isn't working: despite passing in '-fdiagnostics-color=never', the 'lld' wrapper invocation is still done with '-fdiagnostics-color=always' if printing to a terminal -- but does turn into '-fdiagnostics-color=never' if not printing to a terminal. + //TODO Does that mean that 'diagnostic_color_init' is only doing the 'DIAGNOSTICS_COLOR_DEFAULT' thing, but not paying attention to the command-line argument? + //TODO Per PR69707, that is supposed to be working? + //TODO Is that maybe a problem in 'mkoffload'? (..., and if yes, just amdgcn, or all?) + const char *llvm_tools_wrapper_color_arg = NULL; +#if 0 //TODO Do this for 'as', too? + if (!strcmp (commands[i].prog, "as")) + { + /* That's 'llvm-mc'. */ + argc_wrap_llvm_tools_wrapper = 1; + if (pp_show_color (global_dc->printer)) + { + argc_wrap_llvm_tools_wrapper += 1; + llvm_tools_wrapper_color_arg = "--color"; + } + else + ; /* There doesn't seem to be a command-line flag to force-disable + this, so let's hope the default does the right thing. */ + } + else +#endif + if (!strcmp (commands[i].prog, linker_name_spec)) + { + /* That's 'lld'. */ + argc_wrap_llvm_tools_wrapper = 1; + if (pp_show_color (global_dc->printer)) + { + argc_wrap_llvm_tools_wrapper += 1; + llvm_tools_wrapper_color_arg = "--color-diagnostics=always"; + } + else + { + argc_wrap_llvm_tools_wrapper += 1; + llvm_tools_wrapper_color_arg = "--color-diagnostics=never"; + } + } +#endif /* LLVM_TOOLS_WRAPPER */ + size_t argc_wrap_valgrind = 0; +#ifdef ENABLE_VALGRIND_CHECKING + argc_wrap_valgrind = 2; +#endif + size_t argc_extra = argc_wrap_llvm_tools_wrapper + argc_wrap_valgrind; + if (argc_extra > 0) + { + /* One extra for the terminator. */ + argc_extra += 1; - argv = XALLOCAVEC (const char *, argc + 3); + size_t argc; + for (argc = 0; commands[i].argv[argc] != NULL; argc++) + ; - argv[0] = VALGRIND_PATH; - argv[1] = "-q"; - for (j = 2; j < argc + 2; j++) - argv[j] = commands[i].argv[j - 2]; - argv[j] = NULL; + const char **argv = XALLOCAVEC (const char *, argc_extra + argc); + //TODO Where does this get deallocated? - commands[i].argv = argv; - commands[i].prog = argv[0]; - } + size_t j = 0; + if (argc_wrap_llvm_tools_wrapper) + { + //TODO This uses 'find_a_file' to locate this in the build directory. This supposedly should also work for the install tree. 'find_a_file' should be doing/supporting all that; this is modelled similar to 'lto-wrapper'. + argv[j++] = find_a_file (&exec_prefixes, "llvm-tools-wrapper", X_OK, false); + } + if (argc_wrap_valgrind) + { +#ifdef ENABLE_VALGRIND_CHECKING + /* Run the each command through valgrind. */ + argv[j++] = VALGRIND_PATH; + /* Request quiet operation unless something triggers. */ + argv[j++] = "-q"; +#else + gcc_unreachable (); #endif + } + /* Now the actual executable. */ + argv[j++] = commands[i].argv[0]; +#ifdef LLVM_TOOLS_WRAPPER + /* Now any LLVM tools color arguments. */ + if (llvm_tools_wrapper_color_arg) + argv[j++] = llvm_tools_wrapper_color_arg; +#endif /* LLVM_TOOLS_WRAPPER */ + /* Now all other arguments. */ + for (size_t arg = 1; arg < argc; ++arg) + argv[j++] = commands[i].argv[arg]; + argv[j++] = NULL; + gcc_checking_assert (j == argc + argc_extra); + + commands[i].argv = argv; + commands[i].prog = argv[0]; + } + } /* Run each piped subprocess. */ diff --git a/gcc/llvm-tools-wrapper.in b/gcc/llvm-tools-wrapper.in new file mode 100755 index 000000000000..a9233209082a --- /dev/null +++ b/gcc/llvm-tools-wrapper.in @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# This is a simple wrapper that invokes '$@', and filters 'stderr' such as to +# only print non-empty lines. + +# Doing this, the invoked program may notice that it's not printing to a +# terminal, and may change its behavior, say, to disable color output. If that +# is a concern, it has to be addressed individually. + +# This implementation depends on the GNU Bash, in particular its 'coproc' +# command. We expect this wrapper only to be used on systems where such +# dependencies are not a concern. + +set -e + +# Set up a coprocess: print non-empty lines to 'stderr'. +coproc grep --line-buffered . >&2 + +# Invoke '$@'. +status=0 +"$@" 2>&"${COPROC[1]}" || status="$?" + +# Shut down the coprocess. +# Apparently, per +# <https://unix.stackexchange.com/questions/86270/how-do-you-use-the-command-coproc-in-various-shells>, +# we have to use such an indirection ('coproc_fd_1') to support "bash versions +# prior to 4.3". +coproc_fd_1=${COPROC[1]} +exec {coproc_fd_1}<&- +# We intentionally do not 'wait' for '$COPROC_PID' here, as that sometimes +# fails (perhaps if the coprocess has never been active, if there has been no +# output at all?). +wait + +exit "$status" diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index cccd3ce4742c..941fc72b5947 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -342,10 +342,6 @@ proc gcc-dg-test { prog do_what extra_tool_flags } { # for all tests. set allow_blank_lines 0 -if { [check_effective_target_llvm_binutils] } { - set allow_blank_lines 2 -} - # A command for use by testcases to mark themselves as expecting # blank lines in the output. diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index ca3895c22690..089ecfb68ad4 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -9514,14 +9514,6 @@ proc check_effective_target_offload_hsa { } { } "-foffload=hsa" ] } -# Return 1 if the compiler has been configured with hsa offloading. - -proc check_effective_target_offload_gcn { } { - return [check_no_compiler_messages offload_gcn assembly { - int main () {return 0;} - } "-foffload=amdgcn-unknown-amdhsa" ] -} - # Return 1 if the target support -fprofile-update=atomic proc check_effective_target_profile_update_atomic {} { return [check_no_compiler_messages profile_update_atomic assembly { @@ -9963,13 +9955,6 @@ foreach N {df} { }] } -# Return 1 if this target uses an LLVM assembler and/or linker -proc check_effective_target_llvm_binutils { } { - return [check_cached_effective_target llvm_binutils { - expr { [istarget amdgcn*-*-*] - || [check_effective_target_offload_gcn] }}] -} - # Return 1 if the compiler supports '-mfentry'. proc check_effective_target_mfentry { } { diff --git a/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c b/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c index f01a64e72c07..9e59ef8864e7 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c +++ b/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c @@ -1,6 +1,5 @@ /* { dg-do link } */ /* { dg-excess-errors "unresolved symbol foo, lto1, mkoffload and lto-wrapper fatal errors" { target offload_device_nonshared_as } } */ -/* { dg-allow-blank-lines-in-output 1 } */ /* { dg-additional-sources "function-not-offloaded-aux.c" } */ #pragma omp declare target -- 2.25.1