diff options
author | Ken Raeburn <raeburn@cygnus.com> | 1998-07-30 10:38:22 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@gcc.gnu.org> | 1998-07-30 10:38:22 +0000 |
commit | 07417085a14349cde788c5cc10663815da40c26f (patch) | |
tree | 026e48c190a03450b58622639d6f3e00ed5ec047 /gcc/function.c | |
parent | 6bcf8e5a040d2ce78eba4b4a143a216e2cea4ab5 (diff) | |
download | gcc-07417085a14349cde788c5cc10663815da40c26f.zip gcc-07417085a14349cde788c5cc10663815da40c26f.tar.gz gcc-07417085a14349cde788c5cc10663815da40c26f.tar.bz2 |
Function entry/exit profiling instrumentation:
* expr.h (profile_function_entry_libfunc, profile_function_exit_libfunc):
Declare new variables.
* optabs.c: Define them here.
(init_optabs): Initialize them.
* tree.h (struct tree_decl): New flag no_instrument_function_entry_exit.
(DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT): New accessor macro.
* c-decl.c (duplicate_decls): Merge it.
* c-common.c (enum attrs): New value A_NO_INSTRUMENT_FUNCTION.
(init_attributes): Use it for "no_instrument_function".
(decl_attributes): Handle it, for functions that have not yet been compiled.
Set decl flag.
* flags.h (flag_instrument_function_entry_exit): Declare new variable.
* toplev.c (flag_instrument_function_entry_exit): Define it here.
(f_options): New option "instrument-functions".
* function.h (struct function): New field instrument_entry_exit.
* function.c (current_function_instrument_entry_exit): New variable.
(push_function_context_to, pop_function_context_from): Save and restore.
(expand_function_start): Set current_ variable, maybe emit return label and
entry profile call.
(expand_function_end): Maybe emit exit profile call.
Testsuite:
* gcc.c-torture/special/eeprof-1.c: New test, for -finstrument-functions.
* gcc.c-torture/special/special.exp: Run it.
From-SVN: r21495
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/gcc/function.c b/gcc/function.c index cf9542b..5bd012fc 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -217,6 +217,10 @@ rtx current_function_internal_arg_pointer; /* Language-specific reason why the current function cannot be made inline. */ char *current_function_cannot_inline; +/* Nonzero if instrumentation calls for function entry and exit should be + generated. */ +int current_function_instrument_entry_exit; + /* The FUNCTION_DECL for an inline function currently being expanded. */ tree inline_function_decl; @@ -539,6 +543,7 @@ push_function_context_to (context) p->fixup_var_refs_queue = 0; p->epilogue_delay_list = current_function_epilogue_delay_list; p->args_info = current_function_args_info; + p->instrument_entry_exit = current_function_instrument_entry_exit; save_tree_status (p, context); save_storage_status (p); @@ -621,6 +626,7 @@ pop_function_context_from (context) current_function_epilogue_delay_list = p->epilogue_delay_list; reg_renumber = 0; current_function_args_info = p->args_info; + current_function_instrument_entry_exit = p->instrument_entry_exit; restore_tree_status (p, context); restore_storage_status (p); @@ -5458,6 +5464,10 @@ expand_function_start (subr, parms_have_cleanups) valid operands of arithmetic insns. */ init_recog_no_volatile (); + current_function_instrument_entry_exit + = (flag_instrument_function_entry_exit + && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr)); + /* If function gets a static chain arg, store it in the stack frame. Do this first, so it gets the first stack slot offset. */ if (current_function_needs_context) @@ -5484,6 +5494,7 @@ expand_function_start (subr, parms_have_cleanups) or if it returns a structure, or if it has parm cleanups. */ #ifdef HAVE_return if (cleanup_label == 0 && HAVE_return + && ! current_function_instrument_entry_exit && ! current_function_returns_pcc_struct && ! (current_function_returns_struct && ! optimize)) return_label = 0; @@ -5532,7 +5543,7 @@ expand_function_start (subr, parms_have_cleanups) else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode) /* If return mode is void, this decl rtl should not be used. */ DECL_RTL (DECL_RESULT (subr)) = 0; - else if (parms_have_cleanups) + else if (parms_have_cleanups || current_function_instrument_entry_exit) { /* If function will end with cleanup code for parms, compute the return values into a pseudo reg, @@ -5650,6 +5661,21 @@ expand_function_start (subr, parms_have_cleanups) } } + if (current_function_instrument_entry_exit) + { + rtx fun = DECL_RTL (current_function_decl); + if (GET_CODE (fun) == MEM) + fun = XEXP (fun, 0); + else + abort (); + emit_library_call (profile_function_entry_libfunc, 0, VOIDmode, 2, + fun, Pmode, + expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, + 0, + hard_frame_pointer_rtx), + Pmode); + } + /* After the display initializations is where the tail-recursion label should go, if we end up needing one. Ensure we have a NOTE here since some things (like trampolines) get placed before this. */ @@ -5863,6 +5889,21 @@ expand_function_end (filename, line, end_bindings) } } + if (current_function_instrument_entry_exit) + { + rtx fun = DECL_RTL (current_function_decl); + if (GET_CODE (fun) == MEM) + fun = XEXP (fun, 0); + else + abort (); + emit_library_call (profile_function_exit_libfunc, 0, VOIDmode, 2, + fun, Pmode, + expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS, + 0, + hard_frame_pointer_rtx), + Pmode); + } + /* If we had calls to alloca, and this machine needs an accurate stack pointer to exit the function, insert some code to save and restore the stack pointer. */ |