diff mbox series

nvptx target: Global constructor, destructor support, via nvptx-tools 'ld' (was: nvptx: Support global constructors/destructors via 'collect2')

Message ID 87v82u2kc8.fsf@dem-tschwing-1.schwinge.ddns.net
State New
Headers show
Series nvptx target: Global constructor, destructor support, via nvptx-tools 'ld' (was: nvptx: Support global constructors/destructors via 'collect2') | expand

Commit Message

Thomas Schwinge May 31, 2024, 1:15 p.m. UTC
Hi!

On 2022-12-02T14:35:35+0100, I wrote:
> On 2022-12-01T22:13:38+0100, I wrote:
>> I'm working on support for global constructors/destructors with
>> GCC/nvptx
>
> See "nvptx: Support global constructors/destructors via 'collect2'"
> attached; [...]
>
> Per my quick scanning of 'gcc/config.gcc' history, for more than two
> decades, there was a clear trend to remove 'use_collect2=yes'
> configurations; now finally a new one is being added -- making sure we're
> not slowly dispensing with the need for the early 1990s piece of work
> that 'gcc/collect2*' is...  ;'-P

In the following, I have then reconsidered that stance; we may actually
"Implement global constructor, destructor support in a conceptually
simpler way than using 'collect2' (the program): implement the respective
functionality in the nvptx-tools 'ld'".  The latter is
<https://github.com/SourceryTools/nvptx-tools/commit/96f8fc59a757767b9e98157d95c21e9fef22a93b>
"ld: Global constructor/destructor support".

Thus, this:

> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -2783,6 +2783,7 @@ nvptx-*)
>  	tm_file="${tm_file} newlib-stdint.h"
>  	use_gcc_stdint=wrap
>  	tmake_file="nvptx/t-nvptx"
> +	use_collect2=yes
>  	if test x$enable_as_accelerator = xyes; then
>  		extra_programs="${extra_programs} mkoffload\$(exeext)"
>  		tm_file="${tm_file} nvptx/offload.h"

... now is gone again.  ;'-)

Pushed to trunk branch commit d9c90c82d900fdae95df4499bf5f0a4ecb903b53
"nvptx target: Global constructor, destructor support, via nvptx-tools 'ld'",
see attached.

(Support for nvptx offloading, enablement of full libgfortran for nvptx,
and corresponding documentation updates, etc. are to follow as separate
commits.)


Compared to the 2022 'collect2' version, this 'ld' version also does
happen to avoid one class of FAILs:

    [-FAIL:-]{+PASS:+} gfortran.dg/implicit_class_1.f90   -O0  (test for excess errors)
    [-UNRESOLVED:-]{+PASS:+} gfortran.dg/implicit_class_1.f90   -O0  [-compilation failed to produce executable-]{+execution test+}
    [...]

That was due to:

    Executing on host: [gfortran] [...] [...]/gfortran.dg/implicit_class_1.f90 [...] -fdump-fortran-original [...]
    [...]
    cc1: error: unrecognized command-line option '-fdump-fortran-original'; did you mean '-fdump-tree-original'?
    collect2: fatal error: gcc returned 1 exit status
    compilation terminated.
    compiler exited with status 1
    FAIL: gfortran.dg/implicit_class_1.f90   -O0  (test for excess errors)

That is, the 'gcc' invocation by 'collect2' is passed
'-fdump-fortran-original', but doesn't know what to do with that.  (Maybe
using '-Wno-complain-wrong-lang' in 'collect2' would help?)  (I'm not
going to look into that any further.)


Grüße
 Thomas
diff mbox series

Patch

From d9c90c82d900fdae95df4499bf5f0a4ecb903b53 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <tschwinge@baylibre.com>
Date: Tue, 28 May 2024 23:20:29 +0200
Subject: [PATCH] nvptx target: Global constructor, destructor support, via
 nvptx-tools 'ld'

The function attributes 'constructor', 'destructor', and 'init_priority' now
work, as do the C++ features making use of this.  Test cases with effective
target 'global_constructor' and 'init_priority' now generally work, and
'check-gcc-c++' test results greatly improve; no more
"sorry, unimplemented: global constructors not supported on this target".

For proper execution test results, this depends on
<https://github.com/SourceryTools/nvptx-tools/commit/96f8fc59a757767b9e98157d95c21e9fef22a93b>
"ld: Global constructor/destructor support".

	gcc/
	* config/nvptx/nvptx.h: Configure global constructor, destructor
	support.
	gcc/testsuite/
	* gcc.dg/no_profile_instrument_function-attr-1.c: GCC/nvptx is
	'NO_DOT_IN_LABEL' but not 'NO_DOLLAR_IN_LABEL', so '$' may apper
	in identifiers.
	* lib/target-supports.exp
	(check_effective_target_global_constructor): Enable for nvptx.
	libgcc/
	* config/nvptx/crt0.c (__gbl_ctors): New weak function.
	(__main): Invoke it.
	* config/nvptx/gbl-ctors.c: New.
	* config/nvptx/t-nvptx: Configure global constructor, destructor
	support.
---
 gcc/config/nvptx/nvptx.h                      | 14 +++-
 .../no_profile_instrument_function-attr-1.c   |  2 +-
 gcc/testsuite/lib/target-supports.exp         |  3 +-
 libgcc/config/nvptx/crt0.c                    | 12 +++
 libgcc/config/nvptx/gbl-ctors.c               | 74 +++++++++++++++++++
 libgcc/config/nvptx/t-nvptx                   |  9 ++-
 6 files changed, 109 insertions(+), 5 deletions(-)
 create mode 100644 libgcc/config/nvptx/gbl-ctors.c

diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h
index e282aad1b73..74f4a68924c 100644
--- a/gcc/config/nvptx/nvptx.h
+++ b/gcc/config/nvptx/nvptx.h
@@ -356,7 +356,19 @@  struct GTY(()) machine_function
 #define MOVE_MAX 8
 #define MOVE_RATIO(SPEED) 4
 #define FUNCTION_MODE QImode
-#define HAS_INIT_SECTION 1
+
+/* Implement global constructor, destructor support in a conceptually simpler
+   way than using 'collect2' (the program): implement the respective
+   functionality in the nvptx-tools 'ld'.  This however still requires the
+   compiler-side effects corresponding to 'USE_COLLECT2': the global
+   constructor, destructor support functions need to have external linkage, and
+   therefore names that are "unique across the whole link".  Use
+   '!targetm.have_ctors_dtors' to achieve this (..., and thus don't need to
+   provide 'targetm.asm_out.constructor', 'targetm.asm_out.destructor').  */
+#define TARGET_HAVE_CTORS_DTORS false
+
+/* See 'libgcc/config/nvptx/crt0.c' for wrapping of 'main'.  */
+#define HAS_INIT_SECTION
 
 /* The C++ front end insists to link against libstdc++ -- which we don't build.
    Tell it to instead link against the innocuous libgcc.  */
diff --git a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
index 909f8a68479..5b4101cf596 100644
--- a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
+++ b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
@@ -18,7 +18,7 @@  int main ()
   return foo ();
 }
 
-/* { dg-final { scan-tree-dump-times "__gcov0\[._\]main.* = PROF_edge_counter" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "__gcov0\[$._\]main.* = PROF_edge_counter" 1 "optimized"} } */
 /* { dg-final { scan-tree-dump-times "__gcov_indirect_call_profiler_v" 1 "optimized" } } */
 /* { dg-final { scan-tree-dump-times "__gcov_time_profiler_counter = " 1 "optimized" } } */
 /* { dg-final { scan-tree-dump-times "__gcov_init" 1 "optimized" } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index f0f6da52275..a3992faab5e 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -942,8 +942,7 @@  proc check_effective_target_nonlocal_goto {} {
 # Return 1 if global constructors are supported, 0 otherwise.
 
 proc check_effective_target_global_constructor {} {
-    if { [istarget nvptx-*-*]
-	 || [istarget bpf-*-*] } {
+    if { [istarget bpf-*-*] } {
 	return 0
     }
     return 1
diff --git a/libgcc/config/nvptx/crt0.c b/libgcc/config/nvptx/crt0.c
index e37a6fb40d3..47e8ec44c19 100644
--- a/libgcc/config/nvptx/crt0.c
+++ b/libgcc/config/nvptx/crt0.c
@@ -32,6 +32,16 @@  void *__nvptx_stacks[32] __attribute__((shared,nocommon));
 /* Likewise for -muniform-simt.  */
 unsigned __nvptx_uni[32] __attribute__((shared,nocommon));
 
+/* Global constructor/destructor support.  Dummy; if necessary, overridden via
+   'gbl-ctors.c'.  */
+
+extern void __gbl_ctors (void);
+
+void __attribute__((weak))
+__gbl_ctors (void)
+{
+}
+
 extern void __main (int *, int, void **) __attribute__((kernel));
 
 void
@@ -47,5 +57,7 @@  __main (int *rval_ptr, int argc, void **argv)
   __nvptx_stacks[0] = stack + sizeof stack;
   __nvptx_uni[0] = 0;
 
+  __gbl_ctors ();
+
   exit (main (argc, argv));
 }
diff --git a/libgcc/config/nvptx/gbl-ctors.c b/libgcc/config/nvptx/gbl-ctors.c
new file mode 100644
index 00000000000..a2ca053e5e3
--- /dev/null
+++ b/libgcc/config/nvptx/gbl-ctors.c
@@ -0,0 +1,74 @@ 
+/* Global constructor/destructor support
+
+   Copyright (C) 2024 Free Software Foundation, Inc.
+
+   This file is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 3, or (at your option) any
+   later version.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "auto-target.h"
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#include "gbl-ctors.h"
+
+extern int atexit (void (*function) (void));
+
+
+/* Handler functions ('static', in contrast to the 'gbl-ctors.h'
+   prototypes).  */
+
+static void __static_do_global_ctors (void);
+
+static void
+__static_do_global_ctors (void)
+{
+  __SIZE_TYPE__ nptrs = (__SIZE_TYPE__) __CTOR_LIST__[0];
+  for (__SIZE_TYPE__ i = nptrs; i >= 1; --i)
+    __CTOR_LIST__[i] ();
+}
+
+static void __static_do_global_dtors (void);
+
+static void
+__static_do_global_dtors (void)
+{
+  func_ptr *p = __DTOR_LIST__;
+  ++p;
+  for (; *p; ++p)
+    (*p) ();
+}
+
+
+/* For nvptx target configurations, override the 'crt0.c' dummy.  */
+
+extern void __gbl_ctors (void);
+
+void
+__gbl_ctors (void)
+{
+  __static_do_global_ctors ();
+  atexit (__static_do_global_dtors);
+}
+
+
+/* The following symbol just provides a means for the nvptx-tools 'ld' to
+   trigger linking in this file.  */
+
+int __trigger_gbl_ctors;
diff --git a/libgcc/config/nvptx/t-nvptx b/libgcc/config/nvptx/t-nvptx
index 49fdb557b56..260ed6334db 100644
--- a/libgcc/config/nvptx/t-nvptx
+++ b/libgcc/config/nvptx/t-nvptx
@@ -6,8 +6,10 @@  LIB2ADD=$(srcdir)/config/nvptx/reduction.c \
 LIB2ADD += $(srcdir)/c++-minimal/guard.c
 
 LIB2ADDEH=
-LIB2FUNCS_EXCLUDE=__main
+LIB2FUNCS_EXCLUDE=
 
+# Wrapping of 'main'.
+LIB2FUNCS_EXCLUDE += __main
 crt0.o: $(srcdir)/config/nvptx/crt0.c
 	$(crt_compile) -c $<
 
@@ -15,3 +17,8 @@  crt0.o: $(srcdir)/config/nvptx/crt0.c
 # support it, and it may cause the build to fail, because of alloca usage, for
 # example.
 INHIBIT_LIBC_CFLAGS = -Dinhibit_libc
+
+# Support for global constructors/destructors is implemented via the
+# nvptx-tools 'ld' and the following helpers.
+LIB2ADD += $(srcdir)/config/nvptx/gbl-ctors.c
+LIB2FUNCS_EXCLUDE += _ctors
-- 
2.34.1