diff options
author | Sandra Loosemore <sandra@codesourcery.com> | 2007-09-05 14:24:54 +0000 |
---|---|---|
committer | Sandra Loosemore <sandra@codesourcery.com> | 2007-09-05 14:24:54 +0000 |
commit | be6a98f8dd0d44fd6769a516a1aa767b73997a72 (patch) | |
tree | 62913df8af7e441af79b5b56d4d9cfe14bbd53e5 /gcc/function.c | |
parent | 1ae7b919da6bf9e76a3c7130fcfafb0895aea6b9 (diff) |
2007-09-05 Sandra Loosemore <sandra@codesourcery.com>
gcc/
Add target hook invoked when cfun changes.
* doc/tm.texi (TARGET_SET_CURRENT_FUNCTION): Document.
* target.h (struct gcc_target): Add set_current_function.
* target-def.h (TARGET_SET_CURRENT_FUNCTION): Define.
(TARGET_INITIALIZER): Add initializer for set_current_function.
* tree.h (push_struct_function): New.
* tree-inline.h (push_cfun, pop_cfun): Move declarations to...
* function.h: Here.
(set_cfun): Declare.
* tree-inline.c (cfun_stack, push_cfun, pop_cfun): Moved to...
* function.c: Here.
(push_function_context_to): Use allocate_struct_function
to create null context, not init_dummy_function_start. Use set_cfun.
(pop_function_context_from): Use set_cfun.
(in_dummy_function): New.
(invoke_set_current_function_hook): New.
(set_cfun): New.
(push_cfun, pop_cfun): Use set_cfun.
(push_struct_function): New.
(allocate_struct_function): Call invoke_set_current_function_hook
before returning.
(prepare_function_start): Don't set cfun here. Remove unused
argument; fix all callers.
(init_dummy_function_start): Fiddle with in_dummy_function. Call
push_struct_function.
(init_function_start): Set cfun here.
(expand_dummy_function_end): Fiddle with in_dummy_function. Pop cfun.
* omp-low.c (create_omp_child_function): Use push_struct_function
and pop_cfun to save/restore state.
(expand_omp_parallel): Remove unused saved_cfun variable.
* cgraphunit.c (ipa_passes): Use set_cfun.
* gimple-low.c (record_vars_into): Use push_cfun/pop_cfun here.
* dwarf2out.c (dwarf2out_abstract_function): Likewise.
* matrix-reorg.c (transform_allocation_sites): Likewise.
(matrix_reorg): Use set_cfun.
* gimplify.c (gimplify_function_tree): Use push_cfun/pop_cfun here.
* tree-optimize.c (tree_rest_of_compilation): Remove one redundant
assignment to cfun; use set_cfun for the other.
* tree-cfg.c (move_sese_region_to_fn): Use set_cfun.
(dump_function_to_file): Use push_cfun/pop_cfun here.
* c-decl.c (finish_function): Use set_cfun.
gcc/ada/
* trans.c (Compilation_unit_to_gnu): Use set_cfun.
* utils.c (end_subprog_body): Likewise.
gcc/cp/
* decl.c (finish_function): Use set_cfun.
* method.c (use_thunk): Likewise.
gcc/fortran/
* trans-decl.c (build_entry_thunks): Use set_cfun.
(gfc_generate_function_code): Likewise.
gcc/java/
* decl.c (finish_method): Use set_cfun.
gcc/treelang/
* treetree.c (tree_code_create_function_wrapup): Use set_cfun.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@128132 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 145 |
1 files changed, 113 insertions, 32 deletions
diff --git a/gcc/function.c b/gcc/function.c index f4fc6a3ced6..a2956b363a9 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -209,7 +209,7 @@ static void emit_return_into_block (basic_block); #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX) static rtx keep_stack_depressed (rtx); #endif -static void prepare_function_start (tree); +static void prepare_function_start (void); static void do_clobber_return_reg (rtx, void *); static void do_use_return_reg (rtx, void *); static void set_insn_locators (rtx, int) ATTRIBUTE_UNUSED; @@ -244,7 +244,7 @@ push_function_context_to (tree context ATTRIBUTE_UNUSED) struct function *p; if (cfun == 0) - init_dummy_function_start (); + allocate_struct_function (NULL); p = cfun; p->outer = outer_function_chain; @@ -252,7 +252,7 @@ push_function_context_to (tree context ATTRIBUTE_UNUSED) lang_hooks.function.enter_nested (p); - cfun = 0; + set_cfun (NULL); } void @@ -269,7 +269,7 @@ pop_function_context_from (tree context ATTRIBUTE_UNUSED) { struct function *p = outer_function_chain; - cfun = p; + set_cfun (p); outer_function_chain = p->outer; current_function_decl = p->decl; @@ -3781,6 +3781,61 @@ debug_find_var_in_block_tree (tree var, tree block) return NULL_TREE; } +/* Keep track of whether we're in a dummy function context. If we are, + we don't want to invoke the set_current_function hook, because we'll + get into trouble if the hook calls target_reinit () recursively or + when the initial initialization is not yet complete. */ + +static bool in_dummy_function; + +/* Invoke the target hook when setting cfun. */ + +static void +invoke_set_current_function_hook (tree fndecl) +{ + if (!in_dummy_function) + targetm.set_current_function (fndecl); +} + +/* cfun should never be set directly; use this function. */ + +void +set_cfun (struct function *new_cfun) +{ + if (cfun != new_cfun) + { + cfun = new_cfun; + invoke_set_current_function_hook (new_cfun ? new_cfun->decl : NULL_TREE); + } +} + +/* Keep track of the cfun stack. */ + +typedef struct function *function_p; + +DEF_VEC_P(function_p); +DEF_VEC_ALLOC_P(function_p,heap); + +/* Initialized with NOGC, making this poisonous to the garbage collector. */ + +static VEC(function_p,heap) *cfun_stack; + +/* Push the current cfun onto the stack, and set cfun to new_cfun. */ + +void +push_cfun (struct function *new_cfun) +{ + VEC_safe_push (function_p, heap, cfun_stack, cfun); + set_cfun (new_cfun); +} + +/* Pop cfun from the stack. */ + +void +pop_cfun (void) +{ + set_cfun (VEC_pop (function_p, cfun_stack)); +} /* Return value of funcdef and increase it. */ int @@ -3790,7 +3845,13 @@ get_next_funcdef_no (void) } /* Allocate a function structure for FNDECL and set its contents - to the defaults. */ + to the defaults. Set cfun to the newly-allocated object. + Some of the helper functions invoked during initialization assume + that cfun has already been set. Therefore, assign the new object + directly into cfun and invoke the back end hook explicitly at the + very end, rather than initializing a temporary and calling set_cfun + on it. +*/ void allocate_struct_function (tree fndecl) @@ -3813,42 +3874,50 @@ allocate_struct_function (tree fndecl) if (init_machine_status) cfun->machine = (*init_machine_status) (); - if (fndecl == NULL) - return; - - DECL_STRUCT_FUNCTION (fndecl) = cfun; - cfun->decl = fndecl; - - result = DECL_RESULT (fndecl); - if (aggregate_value_p (result, fndecl)) + if (fndecl != NULL) { + DECL_STRUCT_FUNCTION (fndecl) = cfun; + cfun->decl = fndecl; + + result = DECL_RESULT (fndecl); + if (aggregate_value_p (result, fndecl)) + { #ifdef PCC_STATIC_STRUCT_RETURN - current_function_returns_pcc_struct = 1; + current_function_returns_pcc_struct = 1; #endif - current_function_returns_struct = 1; + current_function_returns_struct = 1; + } + + current_function_stdarg + = (fntype + && TYPE_ARG_TYPES (fntype) != 0 + && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) + != void_type_node)); + + /* Assume all registers in stdarg functions need to be saved. */ + cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE; + cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE; } - current_function_stdarg - = (fntype - && TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) - != void_type_node)); + invoke_set_current_function_hook (fndecl); +} + +/* This is like allocate_struct_function, but pushes a new cfun for FNDECL + instead of just setting it. */ - /* Assume all registers in stdarg functions need to be saved. */ - cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE; - cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE; +void +push_struct_function (tree fndecl) +{ + VEC_safe_push (function_p, heap, cfun_stack, cfun); + allocate_struct_function (fndecl); } /* Reset cfun, and other non-struct-function variables to defaults as appropriate for emitting rtl at the start of a function. */ static void -prepare_function_start (tree fndecl) +prepare_function_start (void) { - if (fndecl && DECL_STRUCT_FUNCTION (fndecl)) - cfun = DECL_STRUCT_FUNCTION (fndecl); - else - allocate_struct_function (fndecl); init_emit (); init_varasm_status (cfun); init_expr (); @@ -3873,11 +3942,16 @@ prepare_function_start (tree fndecl) /* Initialize the rtl expansion mechanism so that we can do simple things like generate sequences. This is used to provide a context during global - initialization of some passes. */ + initialization of some passes. You must call expand_dummy_function_end + to exit this context. */ + void init_dummy_function_start (void) { - prepare_function_start (NULL); + gcc_assert (!in_dummy_function); + in_dummy_function = true; + push_struct_function (NULL_TREE); + prepare_function_start (); } /* Generate RTL for the start of the function SUBR (a FUNCTION_DECL tree node) @@ -3887,7 +3961,11 @@ init_dummy_function_start (void) void init_function_start (tree subr) { - prepare_function_start (subr); + if (subr && DECL_STRUCT_FUNCTION (subr)) + set_cfun (DECL_STRUCT_FUNCTION (subr)); + else + allocate_struct_function (subr); + prepare_function_start (); /* Warn if this value is an aggregate type, regardless of which calling convention we are using for it. */ @@ -4201,6 +4279,8 @@ expand_function_start (tree subr) void expand_dummy_function_end (void) { + gcc_assert (in_dummy_function); + /* End any sequences that failed to be closed due to syntax errors. */ while (in_sequence_p ()) end_sequence (); @@ -4210,7 +4290,8 @@ expand_dummy_function_end (void) free_after_parsing (cfun); free_after_compilation (cfun); - cfun = 0; + pop_cfun (); + in_dummy_function = false; } /* Call DOIT for each hard register used as a return value from |