#include "stringpool.h"
#include "attribs.h"
#include "cfgloop.h"
+#include "context.h"
/* Describe the OpenACC looping structure of a function. The entire
function is held in a 'NULL' loop. */
}
}
+/* Return true if DECL is a function for which its references should be
+ analyzed. */
+
+static bool
+omp_declare_target_fn_p (tree decl)
+{
+ return (TREE_CODE (decl) == FUNCTION_DECL
+ && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))
+ && !lookup_attribute ("omp declare target host",
+ DECL_ATTRIBUTES (decl))
+ && (!flag_openacc
+ || oacc_get_fn_attrib (decl) == NULL_TREE));
+}
+
+/* Return true if DECL Is a variable for which its initializer references
+ should be analyzed. */
+
+static bool
+omp_declare_target_var_p (tree decl)
+{
+ return (VAR_P (decl)
+ && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))
+ && !lookup_attribute ("omp declare target link",
+ DECL_ATTRIBUTES (decl)));
+}
+
+/* Helper function for omp_discover_implicit_declare_target, called through
+ walk_tree. Mark referenced FUNCTION_DECLs implicitly as
+ declare target to. */
+
+static tree
+omp_discover_declare_target_fn_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (TREE_CODE (*tp) == FUNCTION_DECL
+ && !omp_declare_target_fn_p (*tp)
+ && !lookup_attribute ("omp declare target host", DECL_ATTRIBUTES (*tp)))
+ {
+ tree id = get_identifier ("omp declare target");
+ if (!DECL_EXTERNAL (*tp) && DECL_SAVED_TREE (*tp))
+ ((vec<tree> *) data)->safe_push (*tp);
+ DECL_ATTRIBUTES (*tp) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (*tp));
+ symtab_node *node = symtab_node::get (*tp);
+ if (node != NULL)
+ {
+ node->offloadable = 1;
+ if (ENABLE_OFFLOADING)
+ g->have_offload = true;
+ }
+ }
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ /* else if (TREE_CODE (*tp) == OMP_TARGET)
+ {
+ if (tree dev = omp_find_clause (OMP_TARGET_CLAUSES (*tp)))
+ if (OMP_DEVICE_ANCESTOR (dev))
+ *walk_subtrees = 0;
+ } */
+ return NULL_TREE;
+}
+
+/* Helper function for omp_discover_implicit_declare_target, called through
+ walk_tree. Mark referenced FUNCTION_DECLs implicitly as
+ declare target to. */
+
+static tree
+omp_discover_declare_target_var_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (TREE_CODE (*tp) == FUNCTION_DECL)
+ return omp_discover_declare_target_fn_r (tp, walk_subtrees, data);
+ else if (VAR_P (*tp)
+ && is_global_var (*tp)
+ && !omp_declare_target_var_p (*tp))
+ {
+ tree id = get_identifier ("omp declare target");
+ if (lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (*tp)))
+ {
+ error_at (DECL_SOURCE_LOCATION (*tp),
+ "%qD specified both in declare target %<link%> and "
+ "implicitly in %<to%> clauses", *tp);
+ DECL_ATTRIBUTES (*tp)
+ = remove_attribute ("omp declare target link", DECL_ATTRIBUTES (*tp));
+ }
+ if (TREE_STATIC (*tp) && DECL_INITIAL (*tp))
+ ((vec<tree> *) data)->safe_push (*tp);
+ DECL_ATTRIBUTES (*tp) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (*tp));
+ symtab_node *node = symtab_node::get (*tp);
+ if (node != NULL && !node->offloadable)
+ {
+ node->offloadable = 1;
+ if (ENABLE_OFFLOADING)
+ {
+ g->have_offload = true;
+ if (is_a <varpool_node *> (node))
+ vec_safe_push (offload_vars, node->decl);
+ }
+ }
+ }
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
+/* Perform the OpenMP implicit declare target to discovery. */
+
+void
+omp_discover_implicit_declare_target (void)
+{
+ cgraph_node *node;
+ varpool_node *vnode;
+ auto_vec<tree> worklist;
+
+ FOR_EACH_DEFINED_FUNCTION (node)
+ if (omp_declare_target_fn_p (node->decl) && DECL_SAVED_TREE (node->decl))
+ worklist.safe_push (node->decl);
+ FOR_EACH_STATIC_INITIALIZER (vnode)
+ if (omp_declare_target_var_p (vnode->decl))
+ worklist.safe_push (vnode->decl);
+ while (!worklist.is_empty ())
+ {
+ tree decl = worklist.pop ();
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (decl),
+ omp_discover_declare_target_fn_r,
+ &worklist);
+ else
+ walk_tree_without_duplicates (&DECL_INITIAL (decl),
+ omp_discover_declare_target_var_r,
+ &worklist);
+ }
+}
+
+
/* Create new symbols containing (address, size) pairs for global variables,
marked with "omp declare target" attribute, as well as addresses for the
functions, which are outlined offloading regions. */