
This adds support for the 'indirect' clause in the 'declare target' directive. Functions declared as indirect may be called via function pointers passed from the host in offloaded code. Virtual calls to member functions via the object pointer in C++ are currently not supported in target regions. 2023-11-07 Kwok Cheung Yeung <kcy@codesourcery.com> gcc/c-family/ * c-attribs.cc (c_common_attribute_table): Add attribute for indirect functions. * c-pragma.h (enum parma_omp_clause): Add entry for indirect clause. gcc/c/ * c-decl.cc (c_decl_attributes): Add attribute for indirect functions. * c-lang.h (c_omp_declare_target_attr): Add indirect field. * c-parser.cc (c_parser_omp_clause_name): Handle indirect clause. (c_parser_omp_clause_indirect): New. (c_parser_omp_all_clauses): Handle indirect clause. (OMP_DECLARE_TARGET_CLAUSE_MASK): Add indirect clause to mask. (c_parser_omp_declare_target): Handle indirect clause. Emit error message if device_type or indirect clauses used alone. Emit error if indirect clause used with device_type that is not 'any'. (OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Add indirect clause to mask. (c_parser_omp_begin): Handle indirect clause. * c-typeck.cc (c_finish_omp_clauses): Handle indirect clause. gcc/cp/ * cp-tree.h (cp_omp_declare_target_attr): Add indirect field. * decl2.cc (cplus_decl_attributes): Add attribute for indirect functions. * parser.cc (cp_parser_omp_clause_name): Handle indirect clause. (cp_parser_omp_clause_indirect): New. (cp_parser_omp_all_clauses): Handle indirect clause. (handle_omp_declare_target_clause): Add extra parameter. Add indirect attribute for indirect functions. (OMP_DECLARE_TARGET_CLAUSE_MASK): Add indirect clause to mask. (cp_parser_omp_declare_target): Handle indirect clause. Emit error message if device_type or indirect clauses used alone. Emit error if indirect clause used with device_type that is not 'any'. (OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Add indirect clause to mask. (cp_parser_omp_begin): Handle indirect clause. * semantics.cc (finish_omp_clauses): Handle indirect clause. gcc/ * lto-cgraph.cc (enum LTO_symtab_tags): Add tag for indirect functions. (output_offload_tables): Write indirect functions. (input_offload_tables): read indirect functions. * lto-section-names.h (OFFLOAD_IND_FUNC_TABLE_SECTION_NAME): New. * omp-builtins.def (BUILT_IN_GOMP_TARGET_MAP_INDIRECT_PTR): New. * omp-offload.cc (offload_ind_funcs): New. (omp_discover_implicit_declare_target): Add functions marked with 'omp declare target indirect' to indirect functions list. (omp_finish_file): Add indirect functions to section for offload indirect functions. (execute_omp_device_lower): Redirect indirect calls on target by passing function pointer to BUILT_IN_GOMP_TARGET_MAP_INDIRECT_PTR. (pass_omp_device_lower::gate): Run pass_omp_device_lower if indirect functions are present on an accelerator device. * omp-offload.h (offload_ind_funcs): New. * tree-core.h (omp_clause_code): Add OMP_CLAUSE_INDIRECT. * tree.cc (omp_clause_num_ops): Add entry for OMP_CLAUSE_INDIRECT. (omp_clause_code_name): Likewise. * tree.h (OMP_CLAUSE_INDIRECT_EXPR): New. * config/gcn/mkoffload.cc (process_asm): Process offload_ind_funcs section. Count number of indirect functions. (process_obj): Emit number of indirect functions. * config/nvptx/mkoffload.cc (ind_func_ids, ind_funcs_tail): New. (process): Emit offload_ind_func_table in PTX code. Emit indirect function names and count in image. * config/nvptx/nvptx.cc (nvptx_record_offload_symbol): Mark indirect functions in PTX code with IND_FUNC_MAP. gcc/testsuite/ * c-c++-common/gomp/declare-target-7.c: Update expected error message. * c-c++-common/gomp/declare-target-indirect-1.c: New. * c-c++-common/gomp/declare-target-indirect-2.c: New. * g++.dg/gomp/attrs-21.C (v12): Update expected error message. * g++.dg/gomp/declare-target-indirect-1.C: New. * gcc.dg/gomp/attrs-21.c (v12): Update expected error message. include/ * gomp-constants.h (GOMP_VERSION): Increment to 3. (GOMP_VERSION_SUPPORTS_INDIRECT_FUNCS): New. libgcc/ * offloadstuff.c (OFFLOAD_IND_FUNC_TABLE_SECTION_NAME): New. (__offload_ind_func_table): New. (__offload_ind_funcs_end): New. (__OFFLOAD_TABLE__): Add entries for indirect functions. libgomp/ * Makefile.am (libgomp_la_SOURCES): Add target-indirect.c. * Makefile.in: Regenerate. * libgomp-plugin.h (GOMP_INDIRECT_ADDR_MAP): New define. (GOMP_OFFLOAD_load_image): Add extra argument. * libgomp.h (struct indirect_splay_tree_key_s): New. (indirect_splay_tree_node, indirect_splay_tree, indirect_splay_tree_key): New. (indirect_splay_compare): New. * libgomp.map (GOMP_5.1.1): Add GOMP_target_map_indirect_ptr. * libgomp.texi (OpenMP 5.1): Update documentation on indirect calls in target region and on indirect clause. (Other new OpenMP 5.2 features): Add entry for virtual function calls. * libgomp_g.h (GOMP_target_map_indirect_ptr): Add prototype. * oacc-host.c (host_load_image): Add extra argument. * target.c (gomp_load_image_to_device): If the GOMP_VERSION is high enough, read host indirect functions table and pass to load_image_func. * config/accel/target-indirect.c: New. * config/linux/target-indirect.c: New. * config/gcn/team.c (build_indirect_map): Add prototype. (gomp_gcn_enter_kernel): Initialize support for indirect function calls on GCN target. * config/nvptx/team.c (build_indirect_map): Add prototype. (gomp_nvptx_main): Initialize support for indirect function calls on NVPTX target. * plugin/plugin-gcn.c (struct gcn_image_desc): Add field for indirect functions count. (GOMP_OFFLOAD_load_image): Add extra argument. If the GOMP_VERSION is high enough, build address translation table and copy it to target memory. * plugin/plugin-nvptx.c (nvptx_tdata): Add field for indirect functions count. (GOMP_OFFLOAD_load_image): Add extra argument. If the GOMP_VERSION is high enough, Build address translation table and copy it to target memory. * testsuite/libgomp.c-c++-common/declare-target-indirect-1.c: New. * testsuite/libgomp.c-c++-common/declare-target-indirect-2.c: New. * testsuite/libgomp.c++/declare-target-indirect-1.C: New.
329 lines
8 KiB
C
329 lines
8 KiB
C
/* OpenACC Runtime Library: acc_device_host.
|
|
|
|
Copyright (C) 2013-2023 Free Software Foundation, Inc.
|
|
|
|
Contributed by Mentor Embedded.
|
|
|
|
This file is part of the GNU Offloading and Multi Processing Library
|
|
(libgomp).
|
|
|
|
Libgomp 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.
|
|
|
|
Libgomp 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 "libgomp.h"
|
|
#include "oacc-int.h"
|
|
#include "gomp-constants.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
|
|
static struct gomp_device_descr host_dispatch;
|
|
|
|
static const char *
|
|
host_get_name (void)
|
|
{
|
|
return host_dispatch.name;
|
|
}
|
|
|
|
static unsigned int
|
|
host_get_caps (void)
|
|
{
|
|
return host_dispatch.capabilities;
|
|
}
|
|
|
|
static int
|
|
host_get_type (void)
|
|
{
|
|
return host_dispatch.type;
|
|
}
|
|
|
|
static int
|
|
host_get_num_devices (unsigned int omp_requires_mask __attribute__((unused)))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static bool
|
|
host_init_device (int n __attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
host_fini_device (int n __attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static unsigned
|
|
host_version (void)
|
|
{
|
|
return GOMP_VERSION;
|
|
}
|
|
|
|
static int
|
|
host_load_image (int n __attribute__ ((unused)),
|
|
unsigned v __attribute__ ((unused)),
|
|
const void *t __attribute__ ((unused)),
|
|
struct addr_pair **r __attribute__ ((unused)),
|
|
uint64_t **f __attribute__ ((unused)),
|
|
uint64_t *i __attribute__ ((unused)))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static bool
|
|
host_unload_image (int n __attribute__ ((unused)),
|
|
unsigned v __attribute__ ((unused)),
|
|
const void *t __attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static void *
|
|
host_alloc (int n __attribute__ ((unused)), size_t s)
|
|
{
|
|
return gomp_malloc (s);
|
|
}
|
|
|
|
static bool
|
|
host_free (int n __attribute__ ((unused)), void *p)
|
|
{
|
|
free (p);
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
host_dev2host (int n __attribute__ ((unused)),
|
|
void *h __attribute__ ((unused)),
|
|
const void *d __attribute__ ((unused)),
|
|
size_t s __attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
host_host2dev (int n __attribute__ ((unused)),
|
|
void *d __attribute__ ((unused)),
|
|
const void *h __attribute__ ((unused)),
|
|
size_t s __attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static void
|
|
host_run (int n __attribute__ ((unused)), void *fn_ptr, void *vars,
|
|
void **args __attribute__((unused)))
|
|
{
|
|
void (*fn)(void *) = (void (*)(void *)) fn_ptr;
|
|
|
|
fn (vars);
|
|
}
|
|
|
|
static void
|
|
host_openacc_exec (void (*fn) (void *),
|
|
size_t mapnum __attribute__ ((unused)),
|
|
void **hostaddrs,
|
|
void **devaddrs __attribute__ ((unused)),
|
|
unsigned *dims __attribute__ ((unused)),
|
|
void *targ_mem_desc __attribute__ ((unused)))
|
|
{
|
|
fn (hostaddrs);
|
|
}
|
|
|
|
static void
|
|
host_openacc_async_exec (void (*fn) (void *),
|
|
size_t mapnum __attribute__ ((unused)),
|
|
void **hostaddrs,
|
|
void **devaddrs __attribute__ ((unused)),
|
|
unsigned *dims __attribute__ ((unused)),
|
|
void *targ_mem_desc __attribute__ ((unused)),
|
|
struct goacc_asyncqueue *aq __attribute__ ((unused)))
|
|
{
|
|
fn (hostaddrs);
|
|
}
|
|
|
|
static int
|
|
host_openacc_async_test (struct goacc_asyncqueue *aq __attribute__ ((unused)))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static bool
|
|
host_openacc_async_synchronize (struct goacc_asyncqueue *aq
|
|
__attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
host_openacc_async_serialize (struct goacc_asyncqueue *aq1
|
|
__attribute__ ((unused)),
|
|
struct goacc_asyncqueue *aq2
|
|
__attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
host_openacc_async_host2dev (int ord __attribute__ ((unused)),
|
|
void *dst __attribute__ ((unused)),
|
|
const void *src __attribute__ ((unused)),
|
|
size_t n __attribute__ ((unused)),
|
|
struct goacc_asyncqueue *aq
|
|
__attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
host_openacc_async_dev2host (int ord __attribute__ ((unused)),
|
|
void *dst __attribute__ ((unused)),
|
|
const void *src __attribute__ ((unused)),
|
|
size_t n __attribute__ ((unused)),
|
|
struct goacc_asyncqueue *aq
|
|
__attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static void
|
|
host_openacc_async_queue_callback (struct goacc_asyncqueue *aq
|
|
__attribute__ ((unused)),
|
|
void (*callback_fn)(void *)
|
|
__attribute__ ((unused)),
|
|
void *userptr __attribute__ ((unused)))
|
|
{
|
|
}
|
|
|
|
static struct goacc_asyncqueue *
|
|
host_openacc_async_construct (int device __attribute__((unused)))
|
|
{
|
|
/* Non-NULL 0xffff... value as opaque dummy. */
|
|
return (struct goacc_asyncqueue *) -1;
|
|
}
|
|
|
|
static bool
|
|
host_openacc_async_destruct (struct goacc_asyncqueue *aq
|
|
__attribute__ ((unused)))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static union goacc_property_value
|
|
host_openacc_get_property (int n, enum goacc_property prop)
|
|
{
|
|
union goacc_property_value nullval = { .val = 0 };
|
|
|
|
if (n >= host_get_num_devices (0))
|
|
return nullval;
|
|
|
|
switch (prop)
|
|
{
|
|
case GOACC_PROPERTY_NAME:
|
|
return (union goacc_property_value) { .ptr = "GOMP" };
|
|
case GOACC_PROPERTY_VENDOR:
|
|
return (union goacc_property_value) { .ptr = "GNU" };
|
|
case GOACC_PROPERTY_DRIVER:
|
|
return (union goacc_property_value) { .ptr = VERSION };
|
|
case GOACC_PROPERTY_MEMORY:
|
|
case GOACC_PROPERTY_FREE_MEMORY:
|
|
default:
|
|
return nullval;
|
|
}
|
|
}
|
|
|
|
static void *
|
|
host_openacc_create_thread_data (int ord __attribute__ ((unused)))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
host_openacc_destroy_thread_data (void *tls_data __attribute__ ((unused)))
|
|
{
|
|
}
|
|
|
|
static struct gomp_device_descr host_dispatch =
|
|
{
|
|
.name = "host",
|
|
.capabilities = (GOMP_OFFLOAD_CAP_SHARED_MEM
|
|
| GOMP_OFFLOAD_CAP_NATIVE_EXEC
|
|
| GOMP_OFFLOAD_CAP_OPENACC_200),
|
|
.target_id = 0,
|
|
.type = OFFLOAD_TARGET_TYPE_HOST,
|
|
|
|
.get_name_func = host_get_name,
|
|
.get_caps_func = host_get_caps,
|
|
.get_type_func = host_get_type,
|
|
.get_num_devices_func = host_get_num_devices,
|
|
.init_device_func = host_init_device,
|
|
.fini_device_func = host_fini_device,
|
|
.version_func = host_version,
|
|
.load_image_func = host_load_image,
|
|
.unload_image_func = host_unload_image,
|
|
.alloc_func = host_alloc,
|
|
.free_func = host_free,
|
|
.dev2host_func = host_dev2host,
|
|
.host2dev_func = host_host2dev,
|
|
.memcpy2d_func = NULL,
|
|
.memcpy3d_func = NULL,
|
|
.run_func = host_run,
|
|
|
|
.mem_map = { NULL },
|
|
.mem_map_rev = { NULL },
|
|
/* .lock initialized in goacc_host_init. */
|
|
.state = GOMP_DEVICE_UNINITIALIZED,
|
|
|
|
.openacc = {
|
|
.exec_func = host_openacc_exec,
|
|
|
|
.create_thread_data_func = host_openacc_create_thread_data,
|
|
.destroy_thread_data_func = host_openacc_destroy_thread_data,
|
|
|
|
.async = {
|
|
.construct_func = host_openacc_async_construct,
|
|
.destruct_func = host_openacc_async_destruct,
|
|
.test_func = host_openacc_async_test,
|
|
.synchronize_func = host_openacc_async_synchronize,
|
|
.serialize_func = host_openacc_async_serialize,
|
|
.queue_callback_func = host_openacc_async_queue_callback,
|
|
.exec_func = host_openacc_async_exec,
|
|
.dev2host_func = host_openacc_async_dev2host,
|
|
.host2dev_func = host_openacc_async_host2dev,
|
|
},
|
|
|
|
.get_property_func = host_openacc_get_property,
|
|
|
|
.cuda = {
|
|
.get_current_device_func = NULL,
|
|
.get_current_context_func = NULL,
|
|
.get_stream_func = NULL,
|
|
.set_stream_func = NULL,
|
|
}
|
|
}
|
|
};
|
|
|
|
/* Initialize and register this device type. */
|
|
void
|
|
goacc_host_init (void)
|
|
{
|
|
gomp_mutex_init (&host_dispatch.lock);
|
|
goacc_register (&host_dispatch);
|
|
}
|