===================================================================
@@ -206,6 +206,7 @@ along with GCC; see the file COPYING3.
#include "pass_manager.h"
#include "tree-nested.h"
#include "gimplify.h"
+#include "omp-low.h"
#include "lto-section-names.h"
/* Queue of cgraph nodes scheduled to be added into cgraph. This is a
@@ -2019,6 +2020,8 @@ ipa_passes (void)
execute_ipa_summary_passes
((struct ipa_opt_pass_d *) passes->all_regular_ipa_passes);
+
+ omp_finish_file ();
}
/* Some targets need to handle LTO assembler output specially. */
===================================================================
@@ -498,6 +498,7 @@ DFS_write_tree_body (struct output_block
special handling in LTO, it must be handled by streamer hooks. */
DFS_follow_tree_edge (DECL_ATTRIBUTES (expr));
+ DFS_follow_tree_edge (DECL_UNIQUE_ID (expr));
/* Do not follow DECL_ABSTRACT_ORIGIN. We cannot handle debug information
for early inlining so drop it on the floor instead of ICEing in
===================================================================
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3.
#include "optabs.h"
#include "cfgloop.h"
#include "target.h"
+#include "common/common-target.h"
#include "omp-low.h"
#include "gimple-low.h"
#include "tree-cfgcleanup.h"
@@ -191,7 +192,6 @@ struct omp_for_data
struct omp_for_data_loop *loops;
};
-
static splay_tree all_contexts;
static int taskreg_nesting_level;
static int target_nesting_level;
@@ -1889,6 +1889,7 @@ create_omp_child_function (omp_context *
DECL_EXTERNAL (decl) = 0;
DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = make_node (BLOCK);
+
bool target_p = false;
if (lookup_attribute ("omp declare target",
DECL_ATTRIBUTES (current_function_decl)))
@@ -12379,4 +12380,158 @@ make_pass_omp_simd_clone (gcc::context *
return new pass_omp_simd_clone (ctxt);
}
+struct ctor_elt_data
+{
+ vec<constructor_elt, va_gc> *v;
+ char *buffer;
+ HOST_WIDE_INT offset;
+ tree string_decl;
+};
+
+static void
+make_constructor_elts (tree decl, struct ctor_elt_data *d)
+{
+ const char *str = IDENTIFIER_POINTER (DECL_UNIQUE_ID (decl));
+ size_t len = strlen (str) + 1;
+ memcpy (d->buffer + d->offset, str, len);
+ tree str_addr = build_fold_addr_expr (d->string_decl);
+ tree off = build_int_cst (size_type_node, d->offset);
+ d->offset += len;
+
+ CONSTRUCTOR_APPEND_ELT (d->v, NULL_TREE, build_fold_addr_expr (decl));
+ CONSTRUCTOR_APPEND_ELT (d->v, NULL_TREE,
+ fold_build_pointer_plus (str_addr, off));
+}
+
+static void
+make_unique_name (tree decl)
+{
+ tree name = DECL_NAME (decl);
+ char *p = (char *)alloca (strlen (IDENTIFIER_POINTER (name)) + 3);
+ p[0] = 'O';
+ p[1] = '_';
+ strcpy (p + 2, IDENTIFIER_POINTER (name));
+ tree id = get_file_function_name (p);
+ DECL_UNIQUE_ID (decl) = id;
+}
+
+static size_t
+build_unique_names (size_t *plen)
+{
+ int n = 0;
+ size_t len = 0;
+ /* Collect all omp-target functions. */
+ struct cgraph_node *node;
+ FOR_EACH_DEFINED_FUNCTION (node)
+ {
+ if (!lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (node->decl))
+ || !DECL_ARTIFICIAL (node->decl))
+ continue;
+ n++;
+ if (!in_lto_p)
+ make_unique_name (node->decl);
+ else
+ len += strlen (IDENTIFIER_POINTER (DECL_UNIQUE_ID (node->decl))) + 1;
+ }
+ /* Collect all omp-target global variables. */
+ struct varpool_node *vnode;
+ FOR_EACH_DEFINED_VARIABLE (vnode)
+ {
+ if (!lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (vnode->decl))
+ || TREE_CODE (vnode->decl) != VAR_DECL
+ || DECL_SIZE (vnode->decl) == 0)
+ continue;
+
+ n++;
+ if (!in_lto_p)
+ make_unique_name (vnode->decl);
+ else
+ len += strlen (IDENTIFIER_POINTER (DECL_UNIQUE_ID (vnode->decl))) + 1;
+ }
+ *plen = len;
+ return n;
+}
+
+/* Create new symbol containing (address, size) pairs for omp-marked
+ functions and global variables. */
+void
+omp_finish_file ()
+{
+ const char *section_name = ".offload_func_table_section";
+ tree new_decl, new_decl_type;
+ vec<constructor_elt, va_gc> *v;
+ tree ctor;
+
+ size_t len;
+ int num = build_unique_names (&len);
+
+ if (num == 0 || !in_lto_p || !targetm_common.have_named_sections)
+ return;
+
+ vec_alloc (v, num);
+
+ struct ctor_elt_data data;
+ tree array_type = build_array_type_nelts (char_type_node, len);
+ data.offset = 0;
+ data.buffer = (char *) xmalloc (len);
+ data.string_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_file_function_name ("O"),
+ array_type);
+ DECL_ARTIFICIAL (data.string_decl) = 1;
+ TREE_STATIC (data.string_decl) = 1;
+ data.v = v;
+
+ /* Collect all omp-target functions. */
+ struct cgraph_node *node;
+ FOR_EACH_DEFINED_FUNCTION (node)
+ {
+ if (!lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (node->decl))
+ || !DECL_ARTIFICIAL (node->decl))
+ continue;
+ make_constructor_elts (node->decl, &data);
+ }
+ /* Collect all omp-target global variables. */
+ struct varpool_node *vnode;
+ FOR_EACH_DEFINED_VARIABLE (vnode)
+ {
+ if (!lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (vnode->decl))
+ || TREE_CODE (vnode->decl) != VAR_DECL
+ || DECL_SIZE (vnode->decl) == 0)
+ continue;
+
+ make_constructor_elts (vnode->decl, &data);
+ }
+
+ if (data.offset == 0)
+ {
+ free (data.buffer);
+ return;
+ }
+
+ tree cst = build_string (data.offset, data.buffer);
+ TREE_TYPE (cst) = build_array_type (char_type_node,
+ build_index_type (size_int (data.offset)));
+ DECL_INITIAL (data.string_decl) = cst;
+ free (data.buffer);
+
+ varpool_assemble_decl (varpool_node_for_decl (data.string_decl));
+
+ new_decl_type = build_array_type_nelts (pointer_sized_int_node, num * 2);
+ ctor = build_constructor (new_decl_type, v);
+ TREE_CONSTANT (ctor) = 1;
+ TREE_STATIC (ctor) = 1;
+ new_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier (".omp_table"), new_decl_type);
+ TREE_STATIC (new_decl) = 1;
+ DECL_INITIAL (new_decl) = ctor;
+ DECL_SECTION_NAME (new_decl) = build_string (strlen (section_name),
+ section_name);
+
+ varpool_assemble_decl (varpool_node_for_decl (new_decl));
+}
+
#include "gt-omp-low.h"
===================================================================
@@ -27,5 +27,6 @@ extern void omp_expand_local (basic_bloc
extern void free_omp_regions (void);
extern tree omp_reduction_init (tree, tree);
extern bool make_gimple_omp_edges (basic_block, struct omp_region **);
+extern void omp_finish_file (void);
#endif /* GCC_OMP_LOW_H */
===================================================================
@@ -78,6 +78,7 @@ along with GCC; see the file COPYING3.
#include "diagnostic-color.h"
#include "context.h"
#include "pass_manager.h"
+#include "omp-low.h"
#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
#include "dbxout.h"
@@ -576,6 +577,8 @@ compile_file (void)
if (flag_sanitize & SANITIZE_THREAD)
tsan_finish_file ();
+ omp_finish_file ();
+
output_shared_constant_pool ();
output_object_blocks ();
finish_tm_clone_pairs ();
===================================================================
@@ -9078,7 +9078,8 @@ clean_symbol_name (char *p)
I - for constructors
D - for destructors
N - for C++ anonymous namespaces
- F - for DWARF unwind frame information. */
+ F - for DWARF unwind frame information
+ O - for OpenMP/OpenACC target functions. */
tree
get_file_function_name (const char *type)
===================================================================
@@ -1366,6 +1366,10 @@ struct GTY(()) tree_decl_common {
tree attributes;
tree abstract_origin;
+ /* An IDENTIFIER_NODE used in omp-lower when offloading to
+ accelerator targets. */
+ tree unique_id;
+
/* Points to a structure whose details depend on the language in use. */
struct lang_decl *lang_specific;
};
===================================================================
@@ -2003,6 +2003,11 @@ extern void protected_set_expr_location
#define DECL_ATTRIBUTES(NODE) \
(DECL_COMMON_CHECK (NODE)->decl_common.attributes)
+/* In a DECL, an optional IDENTIFIER_NODE that holds a unique name for this
+ decl that is used when offloading to accelerator targets. */
+#define DECL_UNIQUE_ID(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.unique_id)
+
/* For a FUNCTION_DECL, holds the tree of BINDINGs.
For a TRANSLATION_UNIT_DECL, holds the namespace's BLOCK.
For a VAR_DECL, holds the initial value.
===================================================================
@@ -658,6 +658,7 @@ lto_input_ts_decl_common_tree_pointers (
DECL_SIZE (expr) = stream_read_tree (ib, data_in);
DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
+ DECL_UNIQUE_ID (expr) = stream_read_tree (ib, data_in);
/* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information
for early inlining so drop it on the floor instead of ICEing in
===================================================================
@@ -593,6 +593,7 @@ write_ts_decl_common_tree_pointers (stru
special handling in LTO, it must be handled by streamer hooks. */
stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
+ stream_write_tree (ob, DECL_UNIQUE_ID (expr), ref_p);
/* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information
for early inlining so drop it on the floor instead of ICEing in