aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@cygnus.com>1998-07-30 10:38:22 +0000
committerKen Raeburn <raeburn@gcc.gnu.org>1998-07-30 10:38:22 +0000
commit07417085a14349cde788c5cc10663815da40c26f (patch)
tree026e48c190a03450b58622639d6f3e00ed5ec047 /gcc/function.c
parent6bcf8e5a040d2ce78eba4b4a143a216e2cea4ab5 (diff)
downloadgcc-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.c43
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. */