Move nested function info out of cgraph_node
this patch moves nested function information out of symbol table (to a summary). This saves memory (especially at WPA time) and also makes nested function support more contained. gcc/ChangeLog: 2020-10-22 Jan Hubicka <hubicka@ucw.cz> * cgraph.c: Include tree-nested.h (cgraph_node::create): Call maybe_record_nested_function. (cgraph_node::remove): Do not remove function from nested function infos. (cgraph_node::dump): Update. (cgraph_node::unnest): Move to tree-nested.c (cgraph_node::verify_node): Update. (cgraph_c_finalize): Call nested_function_info::release. * cgraph.h (struct symtab_node): Remove nested function info. * cgraphclones.c (cgraph_node::create_clone): Do not clone nested function info. * cgraphunit.c (cgraph_node::analyze): Update. (cgraph_node::expand): Do not worry about nested functions; they are lowered. (symbol_table::finalize_compilation_unit): Call nested_function_info::release. * gimplify.c: Include tree-nested.h (unshare_body): Update. (unvisit_body): Update. * omp-offload.c (omp_discover_implicit_declare_target): Update. * tree-nested.c: Include alloc-pool.h, tree-nested.h, symbol-summary.h (nested_function_sum): New static variable. (nested_function_info::get): New member function. (nested_function_info::get_create): New member function. (unnest_function): New function. (nested_function_info::~nested_function_info): New member function. (nested_function_info::release): New function. (maybe_record_nested_function): New function. (lookup_element_for_decl): Update. (check_for_nested_with_variably_modified): Update. (create_nesting_tree): Update. (unnest_nesting_tree_1): Update. (gimplify_all_functions): Update. (lower_nested_functions): Update. * tree-nested.h (class nested_function_info): New class. (maybe_record_nested_function): Declare. (unnest_function): Declare. (first_nested_function): New inline function. (next_nested_function): New inline function. (nested_function_origin): New inline function. gcc/ada/ChangeLog: 2020-10-22 Jan Hubicka <hubicka@ucw.cz> * gcc-interface/trans.c: Include tree-nested.h (walk_nesting_tree): Update for new nested function info. gcc/c-family/ChangeLog: 2020-10-22 Jan Hubicka <hubicka@ucw.cz> * c-gimplify.c: Include tree-nested.h (c_genericize): Update for new nested function info. gcc/d/ChangeLog: 2020-10-22 Jan Hubicka <hubicka@ucw.cz> * decl.cc: Include tree-nested.h (get_symbol_decl): Update for new nested function info.
This commit is contained in:
parent
52e7f09698
commit
89576d863a
11 changed files with 213 additions and 89 deletions
|
@ -50,6 +50,7 @@
|
|||
#include "gomp-constants.h"
|
||||
#include "stringpool.h"
|
||||
#include "attribs.h"
|
||||
#include "tree-nested.h"
|
||||
|
||||
#include "ada.h"
|
||||
#include "adadecode.h"
|
||||
|
@ -3696,7 +3697,8 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
|
|||
static void
|
||||
walk_nesting_tree (struct cgraph_node *node, walk_tree_fn func, void *data)
|
||||
{
|
||||
for (node = node->nested; node; node = node->next_nested)
|
||||
for (node = first_nested_function (node);
|
||||
node; node = next_nested_function (node))
|
||||
{
|
||||
walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), func, data);
|
||||
walk_nesting_tree (node, func, data);
|
||||
|
|
|
@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "langhooks.h"
|
||||
#include "dumpfile.h"
|
||||
#include "c-ubsan.h"
|
||||
#include "tree-nested.h"
|
||||
|
||||
/* The gimplification pass converts the language-dependent trees
|
||||
(ld-trees) emitted by the parser into language-independent trees
|
||||
|
@ -572,7 +573,8 @@ c_genericize (tree fndecl)
|
|||
|
||||
/* Dump all nested functions now. */
|
||||
cgn = cgraph_node::get_create (fndecl);
|
||||
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
|
||||
for (cgn = first_nested_function (cgn);
|
||||
cgn; cgn = next_nested_function (cgn))
|
||||
c_genericize (cgn->decl);
|
||||
}
|
||||
|
||||
|
|
76
gcc/cgraph.c
76
gcc/cgraph.c
|
@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "selftest.h"
|
||||
#include "tree-into-ssa.h"
|
||||
#include "ipa-inline.h"
|
||||
#include "tree-nested.h"
|
||||
|
||||
/* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */
|
||||
#include "tree-pass.h"
|
||||
|
@ -517,13 +518,8 @@ cgraph_node::create (tree decl)
|
|||
node->ifunc_resolver = true;
|
||||
|
||||
node->register_symbol ();
|
||||
maybe_record_nested_function (node);
|
||||
|
||||
if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
|
||||
{
|
||||
node->origin = cgraph_node::get_create (DECL_CONTEXT (decl));
|
||||
node->next_nested = node->origin->nested;
|
||||
node->origin->nested = node;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -1861,22 +1857,7 @@ cgraph_node::remove (void)
|
|||
*/
|
||||
force_output = false;
|
||||
forced_by_abi = false;
|
||||
cgraph_node *next;
|
||||
for (cgraph_node *n = nested; n; n = next)
|
||||
{
|
||||
next = n->next_nested;
|
||||
n->origin = NULL;
|
||||
n->next_nested = NULL;
|
||||
}
|
||||
nested = NULL;
|
||||
if (origin)
|
||||
{
|
||||
cgraph_node **node2 = &origin->nested;
|
||||
|
||||
while (*node2 != this)
|
||||
node2 = &(*node2)->next_nested;
|
||||
*node2 = next_nested;
|
||||
}
|
||||
unregister ();
|
||||
if (prev_sibling_clone)
|
||||
prev_sibling_clone->next_sibling_clone = next_sibling_clone;
|
||||
|
@ -2139,7 +2120,7 @@ cgraph_node::dump (FILE *f)
|
|||
}
|
||||
if (tp_first_run > 0)
|
||||
fprintf (f, " first_run:%" PRId64, (int64_t) tp_first_run);
|
||||
if (origin)
|
||||
if (cgraph_node *origin = nested_function_origin (this))
|
||||
fprintf (f, " nested in:%s", origin->dump_asm_name ());
|
||||
if (gimple_has_body_p (decl))
|
||||
fprintf (f, " body");
|
||||
|
@ -2348,19 +2329,6 @@ cgraph_function_possibly_inlined_p (tree decl)
|
|||
return DECL_POSSIBLY_INLINED (decl);
|
||||
}
|
||||
|
||||
/* cgraph_node is no longer nested function; update cgraph accordingly. */
|
||||
void
|
||||
cgraph_node::unnest (void)
|
||||
{
|
||||
cgraph_node **node2 = &origin->nested;
|
||||
gcc_assert (origin);
|
||||
|
||||
while (*node2 != this)
|
||||
node2 = &(*node2)->next_nested;
|
||||
*node2 = next_nested;
|
||||
origin = NULL;
|
||||
}
|
||||
|
||||
/* Return function availability. See cgraph.h for description of individual
|
||||
return values. */
|
||||
enum availability
|
||||
|
@ -3798,27 +3766,32 @@ cgraph_node::verify_node (void)
|
|||
}
|
||||
}
|
||||
|
||||
if (nested != NULL)
|
||||
if (nested_function_info *info = nested_function_info::get (this))
|
||||
{
|
||||
for (cgraph_node *n = nested; n != NULL; n = n->next_nested)
|
||||
if (info->nested != NULL)
|
||||
{
|
||||
if (n->origin == NULL)
|
||||
for (cgraph_node *n = info->nested; n != NULL;
|
||||
n = next_nested_function (n))
|
||||
{
|
||||
error ("missing origin for a node in a nested list");
|
||||
error_found = true;
|
||||
}
|
||||
else if (n->origin != this)
|
||||
{
|
||||
error ("origin points to a different parent");
|
||||
error_found = true;
|
||||
break;
|
||||
nested_function_info *ninfo = nested_function_info::get (n);
|
||||
if (ninfo->origin == NULL)
|
||||
{
|
||||
error ("missing origin for a node in a nested list");
|
||||
error_found = true;
|
||||
}
|
||||
else if (ninfo->origin != this)
|
||||
{
|
||||
error ("origin points to a different parent");
|
||||
error_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next_nested != NULL && origin == NULL)
|
||||
{
|
||||
error ("missing origin for a node in a nested list");
|
||||
error_found = true;
|
||||
if (info->next_nested != NULL && info->origin == NULL)
|
||||
{
|
||||
error ("missing origin for a node in a nested list");
|
||||
error_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (error_found)
|
||||
|
@ -4022,6 +3995,7 @@ cgraph_node::get_fun () const
|
|||
void
|
||||
cgraph_c_finalize (void)
|
||||
{
|
||||
nested_function_info::release ();
|
||||
symtab = NULL;
|
||||
|
||||
x_cgraph_nodes_queue = NULL;
|
||||
|
|
12
gcc/cgraph.h
12
gcc/cgraph.h
|
@ -921,7 +921,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
|
|||
/* Constructor. */
|
||||
explicit cgraph_node (int uid)
|
||||
: symtab_node (SYMTAB_FUNCTION), callees (NULL), callers (NULL),
|
||||
indirect_calls (NULL), origin (NULL), nested (NULL), next_nested (NULL),
|
||||
indirect_calls (NULL),
|
||||
next_sibling_clone (NULL), prev_sibling_clone (NULL), clones (NULL),
|
||||
clone_of (NULL), call_site_hash (NULL), former_clone_of (NULL),
|
||||
simdclone (NULL), simd_clones (NULL), ipa_transforms_to_apply (vNULL),
|
||||
|
@ -1161,9 +1161,6 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
|
|||
/* Return the DECL_STRUCT_FUNCTION of the function. */
|
||||
struct function *get_fun () const;
|
||||
|
||||
/* cgraph_node is no longer nested function; update cgraph accordingly. */
|
||||
void unnest (void);
|
||||
|
||||
/* Bring cgraph node local. */
|
||||
void make_local (void);
|
||||
|
||||
|
@ -1436,13 +1433,6 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
|
|||
/* List of edges representing indirect calls with a yet undetermined
|
||||
callee. */
|
||||
cgraph_edge *indirect_calls;
|
||||
/* For nested functions points to function the node is nested in. */
|
||||
cgraph_node *origin;
|
||||
/* Points to first nested function, if any. */
|
||||
cgraph_node *nested;
|
||||
/* Pointer to the next function with same origin, if any. */
|
||||
cgraph_node *next_nested;
|
||||
/* Pointer to the next clone. */
|
||||
cgraph_node *next_sibling_clone;
|
||||
cgraph_node *prev_sibling_clone;
|
||||
cgraph_node *clones;
|
||||
|
|
|
@ -382,13 +382,7 @@ cgraph_node::create_clone (tree new_decl, profile_count prof_count,
|
|||
}
|
||||
new_node->decl = new_decl;
|
||||
new_node->register_symbol ();
|
||||
new_node->origin = origin;
|
||||
new_node->lto_file_data = lto_file_data;
|
||||
if (new_node->origin)
|
||||
{
|
||||
new_node->next_nested = new_node->origin->nested;
|
||||
new_node->origin->nested = new_node;
|
||||
}
|
||||
new_node->analyzed = analyzed;
|
||||
new_node->definition = definition;
|
||||
new_node->versionable = versionable;
|
||||
|
|
|
@ -673,9 +673,8 @@ cgraph_node::analyze (void)
|
|||
/* Lower the function. */
|
||||
if (!lowered)
|
||||
{
|
||||
if (nested)
|
||||
if (first_nested_function (this))
|
||||
lower_nested_functions (decl);
|
||||
gcc_assert (!nested);
|
||||
|
||||
gimple_register_cfg_hooks ();
|
||||
bitmap_obstack_initialize (NULL);
|
||||
|
@ -2343,14 +2342,11 @@ cgraph_node::expand (void)
|
|||
}
|
||||
|
||||
gimple_set_body (decl, NULL);
|
||||
if (DECL_STRUCT_FUNCTION (decl) == 0
|
||||
&& !cgraph_node::get (decl)->origin)
|
||||
if (DECL_STRUCT_FUNCTION (decl) == 0)
|
||||
{
|
||||
/* Stop pointing to the local nodes about to be freed.
|
||||
But DECL_INITIAL must remain nonzero so we know this
|
||||
was an actual function definition.
|
||||
For a nested function, this is done in c_pop_function_context.
|
||||
If rest_of_compilation set this to 0, leave it 0. */
|
||||
was an actual function definition. */
|
||||
if (DECL_INITIAL (decl) != 0)
|
||||
DECL_INITIAL (decl) = error_mark_node;
|
||||
}
|
||||
|
@ -3001,6 +2997,9 @@ symbol_table::finalize_compilation_unit (void)
|
|||
/* Gimplify and lower thunks. */
|
||||
analyze_functions (/*first_time=*/false);
|
||||
|
||||
/* All nested functions should be lowered now. */
|
||||
nested_function_info::release ();
|
||||
|
||||
/* Offloading requires LTO infrastructure. */
|
||||
if (!in_lto_p && g->have_offload)
|
||||
flag_generate_offload = 1;
|
||||
|
|
|
@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "function.h"
|
||||
#include "debug.h"
|
||||
#include "tree-pretty-print.h"
|
||||
#include "tree-nested.h"
|
||||
|
||||
#include "d-tree.h"
|
||||
|
||||
|
@ -1280,8 +1281,8 @@ get_symbol_decl (Declaration *decl)
|
|||
all static chain passing is handled by the front-end. Do this even
|
||||
if we are not emitting the body. */
|
||||
struct cgraph_node *node = cgraph_node::get_create (decl->csym);
|
||||
if (node->origin)
|
||||
node->unnest ();
|
||||
if (nested_function_origin (node))
|
||||
unnest_function (node);
|
||||
}
|
||||
|
||||
/* Mark compiler generated temporaries as artificial. */
|
||||
|
|
|
@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "dbgcnt.h"
|
||||
#include "omp-offload.h"
|
||||
#include "context.h"
|
||||
#include "tree-nested.h"
|
||||
|
||||
/* Hash set of poisoned variables in a bind expr. */
|
||||
static hash_set<tree> *asan_poisoned_variables = NULL;
|
||||
|
@ -959,7 +960,8 @@ unshare_body (tree fndecl)
|
|||
delete visited;
|
||||
|
||||
if (cgn)
|
||||
for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
|
||||
for (cgn = first_nested_function (cgn); cgn;
|
||||
cgn = next_nested_function (cgn))
|
||||
unshare_body (cgn->decl);
|
||||
}
|
||||
|
||||
|
@ -1002,7 +1004,8 @@ unvisit_body (tree fndecl)
|
|||
unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
|
||||
|
||||
if (cgn)
|
||||
for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
|
||||
for (cgn = first_nested_function (cgn);
|
||||
cgn; cgn = next_nested_function (cgn))
|
||||
unvisit_body (cgn->decl);
|
||||
}
|
||||
|
||||
|
|
|
@ -334,7 +334,8 @@ omp_discover_implicit_declare_target (void)
|
|||
else if (DECL_STRUCT_FUNCTION (node->decl)
|
||||
&& DECL_STRUCT_FUNCTION (node->decl)->has_omp_target)
|
||||
worklist.safe_push (node->decl);
|
||||
for (cgn = node->nested; cgn; cgn = cgn->next_nested)
|
||||
for (cgn = first_nested_function (node);
|
||||
cgn; cgn = next_nested_function (cgn))
|
||||
if (omp_declare_target_fn_p (cgn->decl))
|
||||
worklist.safe_push (cgn->decl);
|
||||
else if (DECL_STRUCT_FUNCTION (cgn->decl)
|
||||
|
|
|
@ -42,7 +42,100 @@
|
|||
#include "gimple-low.h"
|
||||
#include "gomp-constants.h"
|
||||
#include "diagnostic.h"
|
||||
#include "alloc-pool.h"
|
||||
#include "tree-nested.h"
|
||||
#include "symbol-summary.h"
|
||||
|
||||
/* Summary of nested functions. */
|
||||
static function_summary <nested_function_info *>
|
||||
*nested_function_sum = NULL;
|
||||
|
||||
/* Return nested_function_info, if available. */
|
||||
nested_function_info *
|
||||
nested_function_info::get (cgraph_node *node)
|
||||
{
|
||||
if (!nested_function_sum)
|
||||
return NULL;
|
||||
return nested_function_sum->get (node);
|
||||
}
|
||||
|
||||
/* Return nested_function_info possibly creating new one. */
|
||||
nested_function_info *
|
||||
nested_function_info::get_create (cgraph_node *node)
|
||||
{
|
||||
if (!nested_function_sum)
|
||||
nested_function_sum = new function_summary <nested_function_info *>
|
||||
(symtab);
|
||||
return nested_function_sum->get_create (node);
|
||||
}
|
||||
|
||||
/* cgraph_node is no longer nested function; update cgraph accordingly. */
|
||||
void
|
||||
unnest_function (cgraph_node *node)
|
||||
{
|
||||
nested_function_info *info = nested_function_info::get (node);
|
||||
cgraph_node **node2 = &nested_function_info::get
|
||||
(nested_function_origin (node))->nested;
|
||||
|
||||
gcc_checking_assert (info->origin);
|
||||
while (*node2 != node)
|
||||
node2 = &nested_function_info::get (*node2)->next_nested;
|
||||
*node2 = info->next_nested;
|
||||
info->next_nested = NULL;
|
||||
info->origin = NULL;
|
||||
nested_function_sum->remove (node);
|
||||
}
|
||||
|
||||
/* Destructor: unlink function from nested function lists. */
|
||||
nested_function_info::~nested_function_info ()
|
||||
{
|
||||
cgraph_node *next;
|
||||
for (cgraph_node *n = nested; n; n = next)
|
||||
{
|
||||
nested_function_info *info = nested_function_info::get (n);
|
||||
next = info->next_nested;
|
||||
info->origin = NULL;
|
||||
info->next_nested = NULL;
|
||||
}
|
||||
nested = NULL;
|
||||
if (origin)
|
||||
{
|
||||
cgraph_node **node2
|
||||
= &nested_function_info::get (origin)->nested;
|
||||
|
||||
nested_function_info *info;
|
||||
while ((info = nested_function_info::get (*node2)) != this && info)
|
||||
node2 = &info->next_nested;
|
||||
*node2 = next_nested;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free nested function info summaries. */
|
||||
void
|
||||
nested_function_info::release ()
|
||||
{
|
||||
if (nested_function_sum)
|
||||
delete (nested_function_sum);
|
||||
nested_function_sum = NULL;
|
||||
}
|
||||
|
||||
/* If NODE is nested function, record it. */
|
||||
void
|
||||
maybe_record_nested_function (cgraph_node *node)
|
||||
{
|
||||
if (DECL_CONTEXT (node->decl)
|
||||
&& TREE_CODE (DECL_CONTEXT (node->decl)) == FUNCTION_DECL)
|
||||
{
|
||||
cgraph_node *origin = cgraph_node::get_create (DECL_CONTEXT (node->decl));
|
||||
nested_function_info *info = nested_function_info::get_create (node);
|
||||
nested_function_info *origin_info
|
||||
= nested_function_info::get_create (origin);
|
||||
|
||||
info->origin = origin;
|
||||
info->next_nested = origin_info->nested;
|
||||
origin_info->nested = node;
|
||||
}
|
||||
}
|
||||
|
||||
/* The object of this pass is to lower the representation of a set of nested
|
||||
functions in order to expose all of the gory details of the various
|
||||
|
@ -586,7 +679,7 @@ lookup_element_for_decl (struct nesting_info *info, tree decl,
|
|||
*slot = build_tree_list (NULL_TREE, NULL_TREE);
|
||||
|
||||
return (tree) *slot;
|
||||
}
|
||||
}
|
||||
|
||||
/* Given DECL, a nested function, create a field in the non-local
|
||||
frame structure for this function. */
|
||||
|
@ -817,7 +910,8 @@ check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
|
|||
struct cgraph_node *cgn = cgraph_node::get (fndecl);
|
||||
tree arg;
|
||||
|
||||
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
|
||||
for (cgn = first_nested_function (cgn); cgn;
|
||||
cgn = next_nested_function (cgn))
|
||||
{
|
||||
for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = DECL_CHAIN (arg))
|
||||
if (variably_modified_type_p (TREE_TYPE (arg), orig_fndecl))
|
||||
|
@ -845,7 +939,8 @@ create_nesting_tree (struct cgraph_node *cgn)
|
|||
info->context = cgn->decl;
|
||||
info->thunk_p = cgn->thunk.thunk_p;
|
||||
|
||||
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
|
||||
for (cgn = first_nested_function (cgn); cgn;
|
||||
cgn = next_nested_function (cgn))
|
||||
{
|
||||
struct nesting_info *sub = create_nesting_tree (cgn);
|
||||
sub->outer = info;
|
||||
|
@ -3498,9 +3593,9 @@ unnest_nesting_tree_1 (struct nesting_info *root)
|
|||
|
||||
/* For nested functions update the cgraph to reflect unnesting.
|
||||
We also delay finalizing of these functions up to this point. */
|
||||
if (node->origin)
|
||||
if (nested_function_info::get (node)->origin)
|
||||
{
|
||||
node->unnest ();
|
||||
unnest_function (node);
|
||||
if (!root->thunk_p)
|
||||
cgraph_node::finalize_function (root->context, true);
|
||||
}
|
||||
|
@ -3541,7 +3636,8 @@ gimplify_all_functions (struct cgraph_node *root)
|
|||
struct cgraph_node *iter;
|
||||
if (!gimple_body (root->decl))
|
||||
gimplify_function_tree (root->decl);
|
||||
for (iter = root->nested; iter; iter = iter->next_nested)
|
||||
for (iter = first_nested_function (root); iter;
|
||||
iter = next_nested_function (iter))
|
||||
if (!iter->thunk.thunk_p)
|
||||
gimplify_all_functions (iter);
|
||||
}
|
||||
|
@ -3557,7 +3653,7 @@ lower_nested_functions (tree fndecl)
|
|||
|
||||
/* If there are no nested functions, there's nothing to do. */
|
||||
cgn = cgraph_node::get (fndecl);
|
||||
if (!cgn->nested)
|
||||
if (!first_nested_function (cgn))
|
||||
return;
|
||||
|
||||
gimplify_all_functions (cgn);
|
||||
|
|
|
@ -24,4 +24,66 @@ extern tree build_addr (tree);
|
|||
extern void insert_field_into_struct (tree, tree);
|
||||
extern void lower_nested_functions (tree);
|
||||
|
||||
class nested_function_info
|
||||
{
|
||||
public:
|
||||
/* Constructor. */
|
||||
nested_function_info ()
|
||||
: origin (NULL),
|
||||
nested (NULL),
|
||||
next_nested (NULL)
|
||||
{
|
||||
}
|
||||
/* Copy constructor. We can not simply copy the structure,
|
||||
because the linked lists would go wrong. However we should never
|
||||
need that. */
|
||||
nested_function_info (const nested_function_info &)
|
||||
{
|
||||
gcc_unreachable ();
|
||||
}
|
||||
~nested_function_info ();
|
||||
|
||||
/* Return nested_function_info, if available. */
|
||||
static nested_function_info *get (cgraph_node *node);
|
||||
|
||||
/* Return nested_function_info possibly creating new one. */
|
||||
static nested_function_info *get_create (cgraph_node *node);
|
||||
|
||||
/* Release all nested_function_infos. */
|
||||
static void release (void);
|
||||
|
||||
/* For nested functions points to function the node is nested in. */
|
||||
cgraph_node *origin;
|
||||
/* Points to first nested function, if any. */
|
||||
cgraph_node *nested;
|
||||
/* Pointer to the next function with same origin, if any. */
|
||||
cgraph_node *next_nested;
|
||||
};
|
||||
|
||||
extern void maybe_record_nested_function (cgraph_node *node);
|
||||
extern void unnest_function (cgraph_node *node);
|
||||
|
||||
/* If there are functions nested in NODE, return first one. */
|
||||
inline cgraph_node *
|
||||
first_nested_function (cgraph_node *node)
|
||||
{
|
||||
nested_function_info *info = nested_function_info::get (node);
|
||||
return info ? info->nested : NULL;
|
||||
}
|
||||
|
||||
/* Return next nested function (used to iterate from first_nested_function). */
|
||||
inline cgraph_node *
|
||||
next_nested_function (cgraph_node *node)
|
||||
{
|
||||
return nested_function_info::get (node)->next_nested;
|
||||
}
|
||||
|
||||
/* Return origin of nested function (and NULL otherwise). */
|
||||
inline cgraph_node *
|
||||
nested_function_origin (cgraph_node *node)
|
||||
{
|
||||
nested_function_info *info = nested_function_info::get (node);
|
||||
return info ? info->origin : NULL;
|
||||
}
|
||||
|
||||
#endif /* GCC_TREE_NESTED_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue