@@ -805,6 +805,11 @@ DEF_BUILTIN (BUILT_IN_PROFILE_FUNC_ENTER, "__cyg_profile_func_enter", BUILT_IN_N
DEF_BUILTIN (BUILT_IN_PROFILE_FUNC_EXIT, "__cyg_profile_func_exit", BUILT_IN_NORMAL, BT_FN_VOID_PTR_PTR, BT_LAST,
false, false, false, ATTR_NULL, true, true)
+DEF_BUILTIN (BUILT_IN_PROFILE_CALL_BEFORE, "__gnu_profile_call_before", BUILT_IN_NORMAL, BT_FN_VOID_PTR, BT_LAST,
+ false, false, false, ATTR_NULL, true, true)
+DEF_BUILTIN (BUILT_IN_PROFILE_CALL_AFTER, "__gnu_profile_call_after", BUILT_IN_NORMAL, BT_FN_VOID_PTR, BT_LAST,
+ false, false, false, ATTR_NULL, true, true)
+
/* TLS thread pointer related builtins. */
DEF_BUILTIN (BUILT_IN_THREAD_POINTER, "__builtin_thread_pointer",
BUILT_IN_NORMAL, BT_FN_PTR, BT_LAST,
@@ -343,6 +343,8 @@ static tree handle_tls_model_attribute (tree *, tree, tree, int,
bool *);
static tree handle_no_instrument_function_attribute (tree *, tree,
tree, int, bool *);
+static tree handle_no_instrument_calls_attribute (tree *, tree,
+ tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
@@ -660,6 +662,9 @@ const struct attribute_spec c_common_attribute_table[] =
{ "no_instrument_function", 0, 0, true, false, false,
handle_no_instrument_function_attribute,
false },
+ { "no_instrument_calls", 0, 0, true, false, false,
+ handle_no_instrument_calls_attribute,
+ false },
{ "malloc", 0, 0, true, false, false,
handle_malloc_attribute, false },
{ "returns_twice", 0, 0, true, false, false,
@@ -7920,6 +7925,35 @@ handle_no_instrument_function_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle a "no_instrument_calls" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_instrument_calls_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree decl = *node;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qE attribute applies only to functions", name);
+ *no_add_attrs = true;
+ }
+ else if (DECL_INITIAL (decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "can%'t set %qE attribute after definition", name);
+ *no_add_attrs = true;
+ }
+ else
+ DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (decl) = 1;
+
+ return NULL_TREE;
+}
+
/* Handle a "malloc" attribute; arguments as in
struct attribute_spec.handler. */
@@ -2287,6 +2287,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+ DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (newdecl)
+ |= DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
@@ -93,7 +93,7 @@ int flag_gen_aux_info = 0
Variable
int flag_shlib
-; These two are really VEC(char_p,heap) *.
+; These four are really VEC(char_p,heap) *.
Variable
void *flag_instrument_functions_exclude_functions
@@ -101,6 +101,12 @@ void *flag_instrument_functions_exclude_functions
Variable
void *flag_instrument_functions_exclude_files
+Variable
+void *flag_instrument_calls_exclude_functions
+
+Variable
+void *flag_instrument_calls_exclude_files
+
; Generic structs (e.g. templates not explicitly specialized)
; may not have a compilation unit associated with them, and so
; may need to be treated differently from ordinary structs.
@@ -1368,6 +1374,18 @@ finstrument-functions-exclude-file-list=
Common RejectNegative Joined
-finstrument-functions-exclude-file-list=filename,... Do not instrument functions listed in files
+finstrument-calls
+Common Report Var(flag_instrument_calls_before_after)
+Instrument call entry and exit with profiling calls
+
+finstrument-calls-exclude-function-list=
+Common RejectNegative Joined
+-finstrument-calls-exclude-function-list=name,... Do not instrument calls from listed functions
+
+finstrument-calls-exclude-file-list=
+Common RejectNegative Joined
+-finstrument-calls-exclude-file-list=filename,... Do not instrument calls from functions listed in files
+
fipa-cp
Common Report Var(flag_ipa_cp) Optimization
Perform interprocedural constant propagation
@@ -1977,6 +1977,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+ DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (newdecl)
+ |= DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
@@ -1026,6 +1026,9 @@ See S/390 and zSeries Options.
-finhibit-size-directive -finstrument-functions @gol
-finstrument-functions-exclude-function-list=@var{sym},@var{sym},@dots{} @gol
-finstrument-functions-exclude-file-list=@var{file},@var{file},@dots{} @gol
+-finstrument-calls @gol
+-finstrument-calls-exclude-function-list=@var{sym},@var{sym},@dots{} @gol
+-finstrument-calls-exclude-file-list=@var{file},@var{file},@dots{} @gol
-fno-common -fno-ident @gol
-fpcc-struct-return -fpic -fPIC -fpie -fPIE @gol
-fno-jump-tables @gol
@@ -20976,6 +20979,45 @@ of the function name, it is considered to be a match. For C99 and C++
extended identifiers, the function name must be given in UTF-8, not
using universal character names.
+@item -finstrument-calls
+@opindex finstrument-calls
+Generate instrumentation calls immediately before and after each
+function call. The following profiling functions will be called with
+the address of the function that is called between them. Use
+@code{__builtin_return_address(0)} inside the profiling functions to
+get the addresses from where they are called.
+
+@smallexample
+void __gnu_profile_call_before (void *fn);
+void __gnu_profile_call_after (void *fn);
+@end smallexample
+
+A function may be given attribute @code{no_instrument_calls}, in which
+case the instrumentation is omitted (no calls within that function will
+be instrumented).
+
+In addition, calls to functions which have been given attribute
+@code{no_instrument_function} (or selected via
+@code{-finstrument-functions-exclude} options) are also excluded from
+instrumentation.
+
+@item -finstrument-calls-exclude-file-list=@var{file},@var{file},@dots{}
+@opindex finstrument-calls-exclude-file-list
+
+Set the list of functions that are excluded from instrumentation (see
+the description of @code{-finstrument-calls}). If the file that
+contains a function definition matches with one of @var{file}, then
+the calls in that function are not instrumented. The match is done on
+substrings as for @code{-finstrument-functions-exclude-file-list}.
+
+@item -finstrument-calls-exclude-function-list=@var{sym},@var{sym},@dots{}
+@opindex finstrument-calls-exclude-function-list
+
+This is similar to @code{-finstrument-calls-exclude-file-list},
+but this option sets the list of function names to be excluded from
+instrumentation. The function name to be matched in the same way as for
+@code{-finstrument-functions-exclude-function-list}
+
@item -fstack-check
@opindex fstack-check
Generate code to verify that you do not go beyond the boundary of the
@@ -4757,7 +4757,8 @@ expand_function_start (tree subr)
crtl->profile
= (profile_flag
- && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
+ && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr)
+ && ! DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (subr));
crtl->limit_stack
= (stack_limit_rtx != NULL_RTX && ! DECL_NO_LIMIT_STACK (subr));
@@ -91,6 +91,8 @@ static struct gimplify_omp_ctx *gimplify_omp_ctxp;
/* Forward declaration. */
static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
+static bool flag_instrument_calls_exclude_p (tree fndecl);
+static bool flag_instrument_functions_exclude_p (tree fndecl);
/* Mark X addressable. Unlike the langhook we expect X to be in gimple
form and we don't do any syntax checking. */
@@ -1157,6 +1159,63 @@ build_stack_save_restore (gimple *save, gimple *restore)
1, tmp_var);
}
+/* Returns the function decl that corresponds the function called in
+ CALL_EXPR if call instrumentation is enabled. */
+
+static tree
+addr_expr_for_call_instrumentation (tree call_expr)
+{
+ tree addr_expr = NULL_TREE;
+
+ if (!gimplify_ctxp->into_ssa && flag_instrument_calls_before_after
+ && !DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (current_function_decl)
+ && !flag_instrument_calls_exclude_p (current_function_decl))
+ {
+ tree fndecl = get_callee_fndecl (call_expr);
+ if (fndecl)
+ {
+ if (!DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
+ && !flag_instrument_functions_exclude_p (fndecl))
+ {
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_APPLY
+ && call_expr_nargs (call_expr) > 0)
+ addr_expr = CALL_EXPR_ARG (call_expr, 0);
+ else if (!DECL_IS_BUILTIN (fndecl))
+ addr_expr = build_fold_addr_expr (fndecl);
+ }
+ }
+ else
+ addr_expr = CALL_EXPR_FN (call_expr);
+ }
+
+ if (addr_expr)
+ {
+ if (TREE_CODE (addr_expr) == OBJ_TYPE_REF)
+ addr_expr = OBJ_TYPE_REF_EXPR (addr_expr);
+ else if (!is_gimple_val (addr_expr))
+ addr_expr = NULL_TREE;
+ }
+
+ return addr_expr;
+}
+
+/* Prepare call to PROFILE_CALL_* builtin (specified by CODE) for
+ function with decl FNDECL and add it to the sequence of GIMPLE
+ statements in PRE_P. */
+
+static void
+maybe_add_profile_call (tree addr_expr, enum built_in_function code,
+ gimple_seq *pre_p)
+{
+ if (addr_expr)
+ {
+ tree x = builtin_decl_implicit (code);
+ gimple call = gimple_build_call (x, 1, addr_expr);
+ gimplify_seq_add_stmt (pre_p, call);
+ }
+}
+
/* Gimplify a BIND_EXPR. Just voidify and recurse. */
static enum gimplify_status
@@ -2690,15 +2749,22 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
gimplify_modify_expr. */
if (!want_value)
{
+ tree addr_expr = addr_expr_for_call_instrumentation (*expr_p);
+ gimple_stmt_iterator gsi;
+
+ maybe_add_profile_call (addr_expr, BUILT_IN_PROFILE_CALL_BEFORE, pre_p);
+
/* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
have to do is replicate it as a GIMPLE_CALL tuple. */
- gimple_stmt_iterator gsi;
call = gimple_build_call_from_tree (*expr_p);
gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
notice_special_calls (call);
gimplify_seq_add_stmt (pre_p, call);
gsi = gsi_last (*pre_p);
fold_stmt (&gsi);
+
+ maybe_add_profile_call (addr_expr, BUILT_IN_PROFILE_CALL_AFTER, pre_p);
+
*expr_p = NULL_TREE;
}
else
@@ -4800,6 +4866,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
gimple assign;
location_t loc = EXPR_LOCATION (*expr_p);
gimple_stmt_iterator gsi;
+ tree addr_expr = NULL_TREE;
gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
|| TREE_CODE (*expr_p) == INIT_EXPR);
@@ -4929,9 +4996,13 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
if (TREE_CODE (*from_p) == CALL_EXPR)
{
+ tree fnptrtype;
+
+ addr_expr = addr_expr_for_call_instrumentation (*from_p);
+
/* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
instead of a GIMPLE_ASSIGN. */
- tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
+ fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
assign = gimple_build_call_from_tree (*from_p);
@@ -4952,7 +5023,9 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
gcc_assert (TREE_CODE (*to_p) == SSA_NAME);
}
+ maybe_add_profile_call (addr_expr, BUILT_IN_PROFILE_CALL_BEFORE, pre_p);
gimplify_seq_add_stmt (pre_p, assign);
+ maybe_add_profile_call (addr_expr, BUILT_IN_PROFILE_CALL_AFTER, pre_p);
gsi = gsi_last (*pre_p);
fold_stmt (&gsi);
@@ -8447,6 +8520,42 @@ flag_instrument_functions_exclude_p (tree fndecl)
return false;
}
+/* Return whether we should exclude FNDECL from call instrumentation. */
+
+static bool
+flag_instrument_calls_exclude_p (tree fndecl)
+{
+ vec<char_p> *v;
+
+ v = (vec<char_p> *) flag_instrument_calls_exclude_functions;
+ if (v && v->length () > 0)
+ {
+ const char *name;
+ int i;
+ char *s;
+
+ name = lang_hooks.decl_printable_name (fndecl, 0);
+ FOR_EACH_VEC_ELT (*v, i, s)
+ if (strstr (name, s) != NULL)
+ return true;
+ }
+
+ v = (vec<char_p> *) flag_instrument_calls_exclude_files;
+ if (v && v->length () > 0)
+ {
+ const char *name;
+ int i;
+ char *s;
+
+ name = DECL_SOURCE_FILE (fndecl);
+ FOR_EACH_VEC_ELT (*v, i, s)
+ if (strstr (name, s) != NULL)
+ return true;
+ }
+
+ return false;
+}
+
/* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
node for the function we want to gimplify.
@@ -1299,6 +1299,7 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
+ DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (decl) = 1;
DECL_SAVED_TREE (decl) = body;
if (!targetm.have_ctors_dtors && final)
{
@@ -1715,6 +1715,7 @@ java_emit_static_constructor (void)
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
+ DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (decl) = 1;
DECL_SAVED_TREE (decl) = body;
DECL_UNINLINABLE (decl) = 1;
@@ -40,6 +40,9 @@ enum libfunc_index
LTI_profile_function_entry,
LTI_profile_function_exit,
+ LTI_profile_call_before,
+ LTI_profile_call_after,
+
LTI_synchronize,
LTI_gcov_flush,
@@ -98,6 +101,9 @@ extern struct target_libfuncs *this_target_libfuncs;
#define profile_function_entry_libfunc (libfunc_table[LTI_profile_function_entry])
#define profile_function_exit_libfunc (libfunc_table[LTI_profile_function_exit])
+#define profile_call_before_libfunc (libfunc_table[LTI_profile_call_before])
+#define profile_call_after_libfunc (libfunc_table[LTI_profile_call_after])
+
#define synchronize_libfunc (libfunc_table[LTI_synchronize])
#define gcov_flush_libfunc (libfunc_table[LTI_gcov_flush])
@@ -6207,6 +6207,12 @@ init_optabs (void)
profile_function_exit_libfunc
= init_one_libfunc ("__cyg_profile_func_exit");
+ /* For call before/after instrumentation. */
+ profile_call_before_libfunc
+ = init_one_libfunc ("__gnu_profile_call_before");
+ profile_call_after_libfunc
+ = init_one_libfunc ("__gnu_profile_call_after");
+
gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
/* Allow the target to add more libcalls or rename some, etc. */
@@ -1605,6 +1605,16 @@ common_handle_option (struct gcc_options *opts,
(&opts->x_flag_instrument_functions_exclude_files, arg);
break;
+ case OPT_finstrument_calls_exclude_function_list_:
+ add_comma_separated_to_vector
+ (&opts->x_flag_instrument_calls_exclude_functions, arg);
+ break;
+
+ case OPT_finstrument_calls_exclude_file_list_:
+ add_comma_separated_to_vector
+ (&opts->x_flag_instrument_calls_exclude_files, arg);
+ break;
+
case OPT_fmessage_length_:
pp_set_line_maximum_length (dc->printer, value);
diagnostic_set_caret_max_width (dc, value);
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+class Base
+{
+public:
+ virtual void foo();
+};
+
+void fn_caller( Base* b ) { b->foo(); }
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
+
new file mode 100644
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
+
+class Base
+{
+public:
+ virtual void foo();
+ virtual void bar();
+ virtual void foobar(int i);
+ virtual void barfoo(int i);
+};
+
+typedef void (Base::*BaseMemFn)(int i);
+void fn_caller( Base& obj, BaseMemFn memfnptr ) { CALL_MEMBER_FN(obj, memfnptr)(42); }
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
+
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+class Base
+{
+public:
+ int bar();
+};
+
+int fn_caller( Base& b )
+{
+ b.bar();
+}
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
+
new file mode 100644
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+void fn () { }
+void fn_caller () { fn (); }
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
new file mode 100644
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls -finstrument-calls-exclude-function-list=fn_caller" } */
+
+void fn () { }
+void fn_caller () { fn (); }
+
+/* { dg-final { scan-assembler-not "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler-not "__gnu_profile_call_after" } } */
new file mode 100644
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls -finstrument-calls-exclude-file-list=instrument_calls-3" } */
+
+void fn () { }
+void fn_caller () { fn (); }
+
+/* { dg-final { scan-assembler-not "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler-not "__gnu_profile_call_after" } } */
new file mode 100644
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+#include <stdio.h>
+void fn_caller () { puts (""); }
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+int fn (int i) { }
+int fn_caller (int i)
+{
+ return fn (i);
+}
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+void fn_caller ()
+{
+ void fn () { }
+ fn ();
+}
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
new file mode 100644
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+void *p_fn[3];
+int fn_caller (int i, char *fmt, ...)
+{
+ void *arg = __builtin_apply_args();
+ void *ret = __builtin_apply(p_fn[i], arg, 0xff);
+ __builtin_return(ret);
+}
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
new file mode 100644
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+void fn_caller ( void (*p_fn)() ) { p_fn (); }
+
+/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-finstrument-calls" } */
+
+__attribute__((no_instrument_function)) void fn ();
+
+void fn_caller ()
+{
+ fn ();
+}
+
+/* { dg-final { scan-assembler-not "__gnu_profile_call_before" } } */
+/* { dg-final { scan-assembler-not "__gnu_profile_call_after" } } */
@@ -1309,7 +1309,9 @@ struct GTY(()) tree_decl_with_vis {
unsigned cxx_destructor : 1;
/* Belong to FUNCTION_DECL exclusively. */
unsigned final : 1;
- /* 11 unused bits. */
+ /* Belong to FUNCTION_DECL exclusively. */
+ unsigned no_instrument_calls_before_after : 1;
+ /* 10 unused bits. */
};
struct GTY(()) tree_var_decl {
@@ -308,6 +308,8 @@ unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
DECL_NO_INLINE_WARNING_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr)
= (unsigned) bp_unpack_value (bp, 1);
+ DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (expr)
+ = (unsigned) bp_unpack_value (bp, 1);
DECL_NO_LIMIT_STACK (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_DISREGARD_INLINE_LIMITS (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_PURE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
@@ -276,6 +276,7 @@ pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, DECL_STATIC_CHAIN (expr), 1);
bp_pack_value (bp, DECL_NO_INLINE_WARNING_P (expr), 1);
bp_pack_value (bp, DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (expr), 1);
+ bp_pack_value (bp, DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER (expr), 1);
bp_pack_value (bp, DECL_NO_LIMIT_STACK (expr), 1);
bp_pack_value (bp, DECL_DISREGARD_INLINE_LIMITS (expr), 1);
bp_pack_value (bp, DECL_PURE_P (expr), 1);
@@ -2543,6 +2543,12 @@ extern vec<tree, va_gc> **decl_debug_args_insert (tree);
#define DECL_FINAL_P(NODE)\
(FUNCTION_DECL_CHECK (NODE)->decl_with_vis.final)
+/* Used in FUNCTION_DECL to indicate that function calls in that function
+ should be instrumented with calls to support routines before and after
+ each function call. */
+#define DECL_NO_INSTRUMENT_CALLS_BEFORE_AFTER(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->decl_with_vis.no_instrument_calls_before_after)
+
/* The source language of the translation-unit. */
#define TRANSLATION_UNIT_LANGUAGE(NODE) \
(TRANSLATION_UNIT_DECL_CHECK (NODE)->translation_unit_decl.language)
2013-07-01 Paul Woegerer <paul_woegerer@mentor.com> Caller instrumentation with -finstrument-calls. * gcc/builtins.def: Add call-hooks __gnu_profile_call_before and __gnu_profile_call_after. * gcc/libfuncs.h (enum libfunc_index): Likewise. * gcc/optabs.c (init_optabs): Likewise. * gcc/c-family/c-common.c (no_instrument_calls): Add attribute. (handle_no_instrument_calls_attribute): New. * gcc/common.opt (finstrument-calls): New option. (finstrument-calls-exclude-function-list): Likewise. (finstrument-calls-exclude-file-list): Likewise. * gcc/opts.c (common_handle_option): Handle new options. * gcc/tree-core.h (tree_decl_with_vis): Add bitfield no_instrument_calls_before_after. * gcc/tree.h: Macro for no_instrument_calls_before_after access. * gcc/c/c-decl.c (merge_decls): Handle tree_function_decl field. * gcc/cp/decl.c (duplicate_decls): Likewise. * gcc/function.c (expand_function_start): Likewise. * gcc/ipa.c: Likewise. * gcc/java/jcf-parse.c: Likewise. * gcc/tree-streamer-in.c: Likewise. * gcc/tree-streamer-out.c: Likewise. (finstrument-calls-exclude-function-list): Likewise. (finstrument-calls-exclude-file-list): Likewise. * gcc/gimplify.c (flag_instrument_calls_exclude_p): New. (addr_expr_for_call_instrumentation): New. (maybe_add_profile_call): New. (gimplify_call_expr): Add call-hooks insertion. (gimplify_modify_expr): Likewise. * gcc/doc/invoke.texi: Added documentation for -finstrument-calls-exclude-function-list and -finstrument-calls-exclude-file-list and -finstrument-calls. * gcc/testsuite/g++.dg/other/instrument_calls-1.C Added regression test for -finstrument-calls. * gcc/testsuite/g++.dg/other/instrument_calls-2.C: Likewise. * gcc/testsuite/g++.dg/other/instrument_calls-3.C: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-1.c: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-2.c: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-3.c: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-4.c: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-5.c: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-6.c: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-7.c: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-8.c: Likewise. * gcc/testsuite/gcc.dg/instrument_calls-9.c: Likewise. Signed-off-by: Paul Woegerer <paul_woegerer@mentor.com> --- gcc/builtins.def | 5 ++ gcc/c-family/c-common.c | 34 +++++++ gcc/c/c-decl.c | 2 + gcc/common.opt | 20 ++++- gcc/cp/decl.c | 2 + gcc/doc/invoke.texi | 42 +++++++++ gcc/function.c | 3 +- gcc/gimplify.c | 113 +++++++++++++++++++++++- gcc/ipa.c | 1 + gcc/java/jcf-parse.c | 1 + gcc/libfuncs.h | 6 ++ gcc/optabs.c | 6 ++ gcc/opts.c | 10 +++ gcc/testsuite/g++.dg/other/instrument_calls-1.C | 14 +++ gcc/testsuite/g++.dg/other/instrument_calls-2.C | 20 +++++ gcc/testsuite/g++.dg/other/instrument_calls-3.C | 17 ++++ gcc/testsuite/gcc.dg/instrument_calls-1.c | 8 ++ gcc/testsuite/gcc.dg/instrument_calls-2.c | 8 ++ gcc/testsuite/gcc.dg/instrument_calls-3.c | 8 ++ gcc/testsuite/gcc.dg/instrument_calls-4.c | 8 ++ gcc/testsuite/gcc.dg/instrument_calls-5.c | 11 +++ gcc/testsuite/gcc.dg/instrument_calls-6.c | 11 +++ gcc/testsuite/gcc.dg/instrument_calls-7.c | 13 +++ gcc/testsuite/gcc.dg/instrument_calls-8.c | 7 ++ gcc/testsuite/gcc.dg/instrument_calls-9.c | 12 +++ gcc/tree-core.h | 4 +- gcc/tree-streamer-in.c | 2 + gcc/tree-streamer-out.c | 1 + gcc/tree.h | 6 ++ 29 files changed, 390 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/other/instrument_calls-1.C create mode 100644 gcc/testsuite/g++.dg/other/instrument_calls-2.C create mode 100644 gcc/testsuite/g++.dg/other/instrument_calls-3.C create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-1.c create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-2.c create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-3.c create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-4.c create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-5.c create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-6.c create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-7.c create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-8.c create mode 100644 gcc/testsuite/gcc.dg/instrument_calls-9.c