This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Fix nested functions
> On Wed, Sep 15, 2004 at 03:32:28PM +0200, Jan Hubicka wrote:
> > + cgraph_unnest_node (cgraph_node (root->context));
> > + cgraph_finalize_function (root->context, true);
>
> Ug.
>
> You'll want to remove the code in the front end that tries
> to finalize them too. Better yet, rearrange things such
> that all of the unnesting and finalization is under control
> of cgraph in the first place.
Ug...
Bootstrapped/regtested i686-pc-gnu-linux...
2004-09-15 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_unnest_node): New function.
(c_finalize): Rename to ....
(c_warn_unused_result_recursivly): ... this one; do only the warning
(finish_function): Finalize the toplevel function; do not lower nested tree.
* cgraph.h (cgraph_unnest_node): Declare.
* cgraphunit.c (decide_is_function_needed): Do not use cgraph
nestedness datastructure.
* cse.c (cse_insn): Do not cprop nonlocal LABEL_REFs.
* reload1.c (set_label_offsets): Fix call of set_label_offsets.
* tree-nested.c (finlize_nesting_tree_1): Use un-nesting code.
* trans-decl.c (build_entry_thunks): Finalize the function; do not lower
tree.
(gfc_generate_function_code): Likewise.
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.584
diff -c -3 -p -r1.584 c-decl.c
*** c-decl.c 14 Sep 2004 18:59:33 -0000 1.584
--- c-decl.c 15 Sep 2004 22:59:06 -0000
*************** store_parm_decls (void)
*** 6299,6328 ****
cfun->x_dont_save_pending_sizes_p = 1;
}
! /* Give FNDECL and all its nested functions to cgraph for compilation. */
static void
! c_finalize (tree fndecl)
{
struct cgraph_node *cgn;
/* Handle attribute((warn_unused_result)). Relies on gimple input. */
c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
- /* ??? Objc emits functions after finalizing the compilation unit.
- This should be cleaned up later and this conditional removed. */
- if (cgraph_global_info_ready)
- {
- c_expand_body (fndecl);
- return;
- }
-
/* Finalize all nested functions now. */
cgn = cgraph_node (fndecl);
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
! c_finalize (cgn->decl);
!
! cgraph_finalize_function (fndecl, false);
}
/* Finish up a function declaration and compile that function
--- 6299,6319 ----
cfun->x_dont_save_pending_sizes_p = 1;
}
! /* Handle attribute((warn_unused_result)) on FNDECL and all its nested
! functions. */
static void
! c_warn_unused_result_recursively (tree fndecl)
{
struct cgraph_node *cgn;
/* Handle attribute((warn_unused_result)). Relies on gimple input. */
c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
/* Finalize all nested functions now. */
cgn = cgraph_node (fndecl);
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
! c_warn_unused_result_recursively (cgn->decl);
}
/* Finish up a function declaration and compile that function
*************** finish_function (void)
*** 6426,6433 ****
if (!decl_function_context (fndecl))
{
c_genericize (fndecl);
! lower_nested_functions (fndecl);
! c_finalize (fndecl);
}
else
{
--- 6417,6433 ----
if (!decl_function_context (fndecl))
{
c_genericize (fndecl);
!
! /* ??? Objc emits functions after finalizing the compilation unit.
! This should be cleaned up later and this conditional removed. */
! if (cgraph_global_info_ready)
! {
! c_expand_body (fndecl);
! return;
! }
!
! c_warn_unused_result_recursively (fndecl);
! cgraph_finalize_function (fndecl, false);
}
else
{
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.57
diff -c -3 -p -r1.57 cgraph.c
*** cgraph.c 13 Sep 2004 22:51:00 -0000 1.57
--- cgraph.c 15 Sep 2004 22:59:06 -0000
*************** cgraph_clone_node (struct cgraph_node *n
*** 693,696 ****
--- 693,709 ----
return new;
}
+
+ /* NODE is no longer nested function; update cgraph accordingly. */
+ void
+ cgraph_unnest_node (struct cgraph_node *node)
+ {
+ struct cgraph_node **node2 = &node->origin->nested;
+ gcc_assert (node->origin);
+
+ while (*node2 != node)
+ node2 = &(*node2)->next_nested;
+ *node2 = node->next_nested;
+ node->origin = NULL;
+ }
#include "gt-cgraph.h"
Index: cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.37
diff -c -3 -p -r1.37 cgraph.h
*** cgraph.h 14 Sep 2004 12:21:41 -0000 1.37
--- cgraph.h 15 Sep 2004 22:59:06 -0000
*************** bool cgraph_varpool_assemble_pending_dec
*** 266,271 ****
--- 266,272 ----
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
bool cgraph_function_possibly_inlined_p (tree);
+ void cgraph_unnest_node (struct cgraph_node *node);
/* In cgraphunit.c */
bool cgraph_assemble_pending_functions (void);
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.81
diff -c -3 -p -r1.81 cgraphunit.c
*** cgraphunit.c 14 Sep 2004 12:21:41 -0000 1.81
--- cgraphunit.c 15 Sep 2004 22:59:07 -0000
*************** static tree memory_identifier;
*** 263,269 ****
static bool
decide_is_function_needed (struct cgraph_node *node, tree decl)
{
! struct cgraph_node *origin;
/* If we decided it was needed before, but at the time we didn't have
the body of the function available, then it's still needed. We have
--- 263,269 ----
static bool
decide_is_function_needed (struct cgraph_node *node, tree decl)
{
! tree origin;
/* If we decided it was needed before, but at the time we didn't have
the body of the function available, then it's still needed. We have
*************** decide_is_function_needed (struct cgraph
*** 303,310 ****
return false;
/* Nested functions of extern inline function shall not be emit unless
we inlined the origin. */
! for (origin = node->origin; origin; origin = origin->origin)
! if (DECL_EXTERNAL (origin->decl))
return false;
/* We want to emit COMDAT functions only when absolutely necessary. */
if (DECL_COMDAT (decl))
--- 303,311 ----
return false;
/* Nested functions of extern inline function shall not be emit unless
we inlined the origin. */
! for (origin = decl_function_context (decl); origin;
! origin = decl_function_context (origin))
! if (DECL_EXTERNAL (origin))
return false;
/* We want to emit COMDAT functions only when absolutely necessary. */
if (DECL_COMDAT (decl))
*************** cgraph_finalize_function (tree decl, boo
*** 586,591 ****
--- 587,595 ----
notice_global_symbol (decl);
node->decl = decl;
node->local.finalized = true;
+ if (node->nested)
+ lower_nested_functions (decl);
+ gcc_assert (!node->nested);
/* If not unit at a time, then we need to create the call graph
now, so that called functions can be queued and emitted now. */
Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.313
diff -c -3 -p -r1.313 cse.c
*** cse.c 7 Sep 2004 20:59:18 -0000 1.313
--- cse.c 15 Sep 2004 22:59:09 -0000
*************** cse_insn (rtx insn, rtx libcall_insn)
*** 5623,5629 ****
/* If this SET is now setting PC to a label, we know it used to
be a conditional or computed branch. */
! else if (dest == pc_rtx && GET_CODE (src) == LABEL_REF)
{
/* Now emit a BARRIER after the unconditional jump. */
if (NEXT_INSN (insn) == 0
--- 5623,5630 ----
/* If this SET is now setting PC to a label, we know it used to
be a conditional or computed branch. */
! else if (dest == pc_rtx && GET_CODE (src) == LABEL_REF
! && !LABEL_REF_NONLOCAL_P (src))
{
/* Now emit a BARRIER after the unconditional jump. */
if (NEXT_INSN (insn) == 0
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.445
diff -c -3 -p -r1.445 reload1.c
*** reload1.c 15 Sep 2004 20:47:48 -0000 1.445
--- reload1.c 15 Sep 2004 22:59:13 -0000
*************** set_label_offsets (rtx x, rtx insn, int
*** 2185,2191 ****
return;
case LABEL_REF:
! set_label_offsets (XEXP (SET_SRC (x), 0), insn, initial_p);
return;
case IF_THEN_ELSE:
--- 2185,2191 ----
return;
case LABEL_REF:
! set_label_offsets (SET_SRC (x), insn, initial_p);
return;
case IF_THEN_ELSE:
Index: tree-nested.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-nested.c,v
retrieving revision 2.17
diff -c -3 -p -r2.17 tree-nested.c
*** tree-nested.c 9 Sep 2004 10:36:11 -0000 2.17
--- tree-nested.c 15 Sep 2004 22:59:13 -0000
*************** finalize_nesting_tree_1 (struct nesting_
*** 1207,1212 ****
--- 1207,1213 ----
tree stmt_list = NULL;
tree context = root->context;
struct function *sf;
+ struct cgraph_node *node;
/* If we created a non-local frame type or decl, we need to lay them
out at this time. */
*************** finalize_nesting_tree_1 (struct nesting_
*** 1317,1322 ****
--- 1318,1332 ----
/* Dump the translated tree function. */
dump_function (TDI_nested, root->context);
+ node = cgraph_node (root->context);
+
+ /* For nested functions update the cgraph to reflect unnesting.
+ We also delay finalizing of these functions up to this point. */
+ if (node->origin)
+ {
+ cgraph_unnest_node (cgraph_node (root->context));
+ cgraph_finalize_function (root->context, true);
+ }
}
static void
Index: fortran/trans-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/trans-decl.c,v
retrieving revision 1.42
diff -c -3 -p -r1.42 trans-decl.c
*** fortran/trans-decl.c 8 Sep 2004 14:33:02 -0000 1.42
--- fortran/trans-decl.c 15 Sep 2004 22:59:15 -0000
*************** create_function_arglist (gfc_symbol * sy
*** 1255,1276 ****
DECL_ARGUMENTS (fndecl) = arglist;
}
-
- /* Finalize DECL and all nested functions with cgraph. */
-
- static void
- gfc_finalize (tree decl)
- {
- struct cgraph_node *cgn;
-
- cgn = cgraph_node (decl);
- for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
- gfc_finalize (cgn->decl);
-
- cgraph_finalize_function (decl, false);
- }
-
-
/* Convert FNDECL's code to GIMPLE and handle any nested functions. */
static void
--- 1255,1260 ----
*************** build_entry_thunks (gfc_namespace * ns)
*** 1431,1438 ****
current_function_decl = NULL_TREE;
gfc_gimplify_function (thunk_fndecl);
! lower_nested_functions (thunk_fndecl);
! gfc_finalize (thunk_fndecl);
/* We share the symbols in the formal argument list with other entry
points and the master function. Clear them so that they are
--- 1415,1421 ----
current_function_decl = NULL_TREE;
gfc_gimplify_function (thunk_fndecl);
! cgraph_finalize_function (thunk_fndecl, false);
/* We share the symbols in the formal argument list with other entry
points and the master function. Clear them so that they are
*************** gfc_generate_function_code (gfc_namespac
*** 2313,2320 ****
else
{
gfc_gimplify_function (fndecl);
! lower_nested_functions (fndecl);
! gfc_finalize (fndecl);
}
}
--- 2296,2302 ----
else
{
gfc_gimplify_function (fndecl);
! cgraph_finalize_function (fndecl, false);
}
}