diff mbox series

[1/8,og9] Add support for constructors and destructors on GCN

Message ID 9f1f40c95faab3d935f75280d5063a0344f020cf.1564776080.git.julian@codesourcery.com
State New
Headers show
Series AMD GCN offloading support | expand

Commit Message

Julian Brown Aug. 2, 2019, 8:11 p.m. UTC
This is a backport to the og9 branch of the mainline patch posted here:

https://gcc.gnu.org/ml/gcc-patches/2019-05/msg01539.html

2019-05-22  Kwok Cheung Yeung  <kcy@codesourcery.com>
	    Andrew Stubbs  <amd@codesourcery.com>

	Backport from mainline:

	* config.gcc (gcc_cv_initfini_array): Set for AMD GCN.
	* config/gcn/gcn-run.c (init_array_kernel, fini_array_kernel): New.
	(kernel): Rename to...
	(main_kernel): ... this.
	(load_image): Load _init_array and _fini_array kernels.
	(run): Add argument for kernel to run.
	(main): Run init_array_kernel before main_kernel, and
	fini_array_kernel after.
	* config/gcn/gcn.c (gcn_handle_amdgpu_hsa_kernel_attribute): Allow
	amdgpu_hsa_kernel attribute on functions.
	(gcn_disable_constructors): Delete.
	(TARGET_ASM_CONSTRUCTOR, TARGET_ASM_DESTRUCTOR): Delete.
	* config/gcn/crt0.c (size_t): Define.
	(_init_array, _fini_array): New.
	(__preinit_array_start, __preinit_array_end,
	__init_array_start, __init_array_end,
	__fini_array_start, __fini_array_end): Declare weak references.
---
 gcc/ChangeLog.openacc    | 23 +++++++++++++++++
 gcc/config.gcc           |  2 ++
 gcc/config/gcn/gcn-run.c | 36 +++++++++++++++++++++-----
 gcc/config/gcn/gcn.c     | 22 +---------------
 libgcc/config/gcn/crt0.c | 56 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 112 insertions(+), 27 deletions(-)
diff mbox series

Patch

diff --git a/gcc/ChangeLog.openacc b/gcc/ChangeLog.openacc
index aa6db4f6344..e573f621fdd 100644
--- a/gcc/ChangeLog.openacc
+++ b/gcc/ChangeLog.openacc
@@ -1,3 +1,26 @@ 
+2019-05-22  Kwok Cheung Yeung  <kcy@codesourcery.com>
+	    Andrew Stubbs  <amd@codesourcery.com>
+
+	Backport from mainline:
+
+	* config.gcc (gcc_cv_initfini_array): Set for AMD GCN.
+	* config/gcn/gcn-run.c (init_array_kernel, fini_array_kernel): New.
+	(kernel): Rename to...
+	(main_kernel): ... this.
+	(load_image): Load _init_array and _fini_array kernels.
+	(run): Add argument for kernel to run.
+	(main): Run init_array_kernel before main_kernel, and
+	fini_array_kernel after.
+	* config/gcn/gcn.c (gcn_handle_amdgpu_hsa_kernel_attribute): Allow
+	amdgpu_hsa_kernel attribute on functions.
+	(gcn_disable_constructors): Delete.
+	(TARGET_ASM_CONSTRUCTOR, TARGET_ASM_DESTRUCTOR): Delete.
+	* config/gcn/crt0.c (size_t): Define.
+	(_init_array, _fini_array): New.
+	(__preinit_array_start, __preinit_array_end,
+	__init_array_start, __init_array_end,
+	__fini_array_start, __fini_array_end): Declare weak references.
+
 2019-07-10  Cesar Philippidis  <cesar@codesourcery.com>
 	    Julian Brown  <julian@codesourcery.com>
 
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 09fb9ecd2cd..6dc016cab51 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1429,6 +1429,8 @@  amdgcn-*-amdhsa)
 		extra_programs="${extra_programs} mkoffload\$(exeext)"
 		tm_file="${tm_file} gcn/offload.h"
 	fi
+	# Force .init_array support.
+	gcc_cv_initfini_array=yes
 	;;
 moxie-*-elf)
 	gas=yes
diff --git a/gcc/config/gcn/gcn-run.c b/gcc/config/gcn/gcn-run.c
index 00a71014c20..84718f42846 100644
--- a/gcc/config/gcn/gcn-run.c
+++ b/gcc/config/gcn/gcn-run.c
@@ -66,7 +66,9 @@  bool debug = false;
 
 hsa_agent_t device = { 0 };
 hsa_queue_t *queue = NULL;
-uint64_t kernel = 0;
+uint64_t init_array_kernel = 0;
+uint64_t fini_array_kernel = 0;
+uint64_t main_kernel = 0;
 hsa_executable_t executable = { 0 };
 
 hsa_region_t kernargs_region = { 0 };
@@ -427,14 +429,30 @@  load_image (const char *filename)
   XHSA (hsa_fns.hsa_executable_freeze_fn (executable, ""),
 	"Freeze GCN executable");
 
-  /* Locate the "main" function, and read the kernel's properties.  */
+  /* Locate the "_init_array" function, and read the kernel's properties.  */
   hsa_executable_symbol_t symbol;
+  XHSA (hsa_fns.hsa_executable_get_symbol_fn (executable, NULL, "_init_array",
+					      device, 0, &symbol),
+	"Find '_init_array' function");
+  XHSA (hsa_fns.hsa_executable_symbol_get_info_fn
+	    (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &init_array_kernel),
+	"Extract '_init_array' kernel object kernel object");
+
+  /* Locate the "_fini_array" function, and read the kernel's properties.  */
+  XHSA (hsa_fns.hsa_executable_get_symbol_fn (executable, NULL, "_fini_array",
+					      device, 0, &symbol),
+	"Find '_fini_array' function");
+  XHSA (hsa_fns.hsa_executable_symbol_get_info_fn
+	    (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &fini_array_kernel),
+	"Extract '_fini_array' kernel object kernel object");
+
+  /* Locate the "main" function, and read the kernel's properties.  */
   XHSA (hsa_fns.hsa_executable_get_symbol_fn (executable, NULL, "main",
 					      device, 0, &symbol),
 	"Find 'main' function");
   XHSA (hsa_fns.hsa_executable_symbol_get_info_fn
-	    (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &kernel),
-	"Extract kernel object");
+	    (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &main_kernel),
+	"Extract 'main' kernel object");
   XHSA (hsa_fns.hsa_executable_symbol_get_info_fn
 	    (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_SIZE,
 	     &kernarg_segment_size),
@@ -684,7 +702,7 @@  gomp_print_output (struct kernargs *kernargs, bool final)
 /* Execute an already-loaded kernel on the device.  */
 
 static void
-run (void *kernargs)
+run (uint64_t kernel, void *kernargs)
 {
   /* A "signal" is used to launch and monitor the kernel.  */
   hsa_signal_t signal;
@@ -822,11 +840,17 @@  main (int argc, char *argv[])
   kernargs->heap_ptr = (int64_t) &kernargs->heap;
   kernargs->heap.size = heap_size;
 
+  /* Run constructors on the GPU.  */
+  run (init_array_kernel, kernargs);
+
   /* Run the kernel on the GPU.  */
-  run (kernargs);
+  run (main_kernel, kernargs);
   unsigned int return_value =
     (unsigned int) kernargs->output_data.return_value;
 
+  /* Run destructors on the GPU.  */
+  run (fini_array_kernel, kernargs);
+
   unsigned int upper = (return_value & ~0xffff) >> 16;
   if (upper == 0xcafe)
     printf ("Kernel exit value was never set\n");
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index 1dd2ff2d4f0..54c37990d9c 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -305,9 +305,7 @@  static tree
 gcn_handle_amdgpu_hsa_kernel_attribute (tree *node, tree name,
 					tree args, int, bool *no_add_attrs)
 {
-  if (FUNC_OR_METHOD_TYPE_P (*node)
-      && TREE_CODE (*node) != FIELD_DECL
-      && TREE_CODE (*node) != TYPE_DECL)
+  if (!FUNC_OR_METHOD_TYPE_P (*node))
     {
       warning (OPT_Wattributes, "%qE attribute only applies to functions",
 	       name);
@@ -3161,20 +3159,6 @@  gcn_valid_cvt_p (machine_mode from, machine_mode to, enum gcn_cvt_t op)
 	  || (to == DFmode && (from == SImode || from == SFmode)));
 }
 
-/* Implement both TARGET_ASM_CONSTRUCTOR and TARGET_ASM_DESTRUCTOR.
-
-   The current loader does not support running code outside "main".  This
-   hook implementation can be replaced or removed when that changes.  */
-
-void
-gcn_disable_constructors (rtx symbol, int priority __attribute__ ((unused)))
-{
-  tree d = SYMBOL_REF_DECL (symbol);
-  location_t l = d ? DECL_SOURCE_LOCATION (d) : UNKNOWN_LOCATION;
-
-  sorry_at (l, "GCN does not support static constructors or destructors");
-}
-
 /* }}}  */
 /* {{{ Costs.  */
 
@@ -5991,10 +5975,6 @@  print_operand (FILE *file, rtx x, int code)
 #define TARGET_ARG_PARTIAL_BYTES gcn_arg_partial_bytes
 #undef  TARGET_ASM_ALIGNED_DI_OP
 #define TARGET_ASM_ALIGNED_DI_OP "\t.8byte\t"
-#undef  TARGET_ASM_CONSTRUCTOR
-#define TARGET_ASM_CONSTRUCTOR gcn_disable_constructors
-#undef  TARGET_ASM_DESTRUCTOR
-#define TARGET_ASM_DESTRUCTOR gcn_disable_constructors
 #undef  TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START output_file_start
 #undef  TARGET_ASM_FUNCTION_PROLOGUE
diff --git a/libgcc/config/gcn/crt0.c b/libgcc/config/gcn/crt0.c
index c0b93534eed..9b58029816c 100644
--- a/libgcc/config/gcn/crt0.c
+++ b/libgcc/config/gcn/crt0.c
@@ -19,5 +19,61 @@ 
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+typedef long long size_t;
+
 /* Provide an entry point symbol to silence a linker warning.  */
 void _start() {}
+
+#ifdef USE_NEWLIB_INITFINI
+
+extern void __libc_init_array (void) __attribute__((weak));
+extern void __libc_fini_array (void) __attribute__((weak));
+
+__attribute__((amdgpu_hsa_kernel ()))
+void _init_array()
+{
+  __libc_init_array ();
+}
+
+__attribute__((amdgpu_hsa_kernel ()))
+void _fini_array()
+{
+  __libc_fini_array ();
+}
+
+#endif
+
+/* These magic symbols are provided by the linker.  */
+extern void (*__preinit_array_start []) (void) __attribute__((weak));
+extern void (*__preinit_array_end []) (void) __attribute__((weak));
+extern void (*__init_array_start []) (void) __attribute__((weak));
+extern void (*__init_array_end []) (void) __attribute__((weak));
+extern void (*__fini_array_start []) (void) __attribute__((weak));
+extern void (*__fini_array_end []) (void) __attribute__((weak));
+
+__attribute__((amdgpu_hsa_kernel ()))
+void _init_array()
+{
+  /* Iterate over all the init routines.  */
+  size_t count;
+  size_t i;
+
+  count = __preinit_array_end - __preinit_array_start;
+  for (i = 0; i < count; i++)
+    __preinit_array_start[i] ();
+
+  count = __init_array_end - __init_array_start;
+  for (i = 0; i < count; i++)
+    __init_array_start[i] ();
+}
+
+__attribute__((amdgpu_hsa_kernel ()))
+void _fini_array()
+{
+  size_t count;
+  size_t i;
+
+  count = __fini_array_end - __fini_array_start;
+  for (i = count; i > 0; i--)
+    __fini_array_start[i-1] ();
+}