diff options
Diffstat (limited to 'gcc/tree-nested.c')
-rw-r--r-- | gcc/tree-nested.c | 110 |
1 files changed, 103 insertions, 7 deletions
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index f74a727..433f37f 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -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); |