+2019-05-22 Kwok Cheung Yeung <kcy@codesourcery.com>
+ Andrew Stubbs <amd@codesourcery.com>
+
+ * 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-05-22 Andrew Stubbs <ams@codesourcery.com>
* config/gcn/gcn.c (gcn_trampoline_init): Call "sorry" on GCN5.
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
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 };
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),
/* 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;
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");
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);
|| (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. */
#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
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] ();
+}