From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12021 invoked by alias); 10 Jul 2013 14:43:39 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 11975 invoked by uid 89); 10 Jul 2013 14:43:39 -0000 X-Spam-SWARE-Status: No, score=-4.4 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,TW_FN,TW_TM,TW_TX autolearn=ham version=3.3.1 Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Wed, 10 Jul 2013 14:43:35 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1UwvcD-0004bO-I6 from Paul_Woegerer@mentor.com ; Wed, 10 Jul 2013 07:43:33 -0700 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Wed, 10 Jul 2013 07:43:34 -0700 Received: from atv-pwoegere-l3.atv.mentorg.com (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.2.247.3; Wed, 10 Jul 2013 15:43:31 +0100 To: GCC Patches CC: Andrew Pinski Subject: [PING^2] Re: [PATCH] Caller instrumentation with -finstrument-calls Date: Wed, 10 Jul 2013 14:47:00 -0000 Message-ID: <11770736.onp7PGsDNc@atv-pwoegere-l3.atv.mentorg.com> User-Agent: KMail/4.10.3 (Linux/3.7.10-1.16-desktop; KDE/4.10.3; x86_64; ; ) In-Reply-To: <1869484.hXzanm2aKp@atv-pwoegere-l3.atv.mentorg.com> References: <4555973.9Ur2WRMufi@atv-pwoegere-l3.atv.mentorg.com> <1869484.hXzanm2aKp@atv-pwoegere-l3.atv.mentorg.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" From: X-SW-Source: 2013-07/txt/msg00421.txt.bz2 Ping, The updated patch that I have sent here: http://gcc.gnu.org/ml/gcc-patches/2013-07/msg00007.html is still pending review/acceptance. Could someone please have a look. Many Thanks, Paul On Monday 01 July 2013 10:22:02 Woegerer, Paul wrote: > Hi Andrew, > > On Friday 28 June 2013 09:50:31 Andrew Pinski wrote: > > On Fri, Jun 28, 2013 at 5:51 AM, wrote: > > > Hi, > > > > > > The patch below provides caller instrumentation for GCC. > > > > > > The following new options have been added: > > > -finstrument-calls > > > -finstrument-calls-exclude-function-list=SYM,SYM,... > > > -finstrument-calls-exclude-file-list=FILE,FILE,... > > > > > > These new options behave and appear similar to the existing function > > > instrumentation options (-finstrument-functions*). I have also added > > > attribute no_instrument_calls to specify which functions should be > > > excluded from within the source code. Calls to functions that have > > > attribute no_instrument_function are also excluded. > > > > > > The effect of the instrumentation causes all calls inside a function > > > > > > to get instrumented using the following hooks: > > > void __cyg_profile_call_before (void *fn); > > > void __cyg_profile_call_after (void *fn); > > > > Can you not use cyg as the prefix rather use gcc or gnu. cyg prefix > > for -finstrument-functions is a historical accident as it stands for > > cygnus but that company no longer exists and we should not be using a > > company specific prefix inside of GCC anymore. > > Ha, funny. Originally I had the hooks with __gnu_profile_call_* but > then I changed them to be consistent with the existing __cyg_profile_* > hooks. > > Anyway, here is the updated patch: > > > From 43a1c2fb43e406f8f547dbcde19a60a8c56423a4 Mon Sep 17 00:00:00 2001 > From: Paul Woegerer > Date: Mon, 1 Jul 2013 09:15:21 +0200 > Subject: [PATCH] Caller instrumentation with -finstrument-calls. > > 2013-07-01 Paul Woegerer > > 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.h (tree_function_decl): Add field tree_function_decl. > * 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. > > diff --git a/gcc/builtins.def b/gcc/builtins.def > index 9b55b1f..0c2a6b2 100644 > --- a/gcc/builtins.def > +++ b/gcc/builtins.def > @@ -795,6 +795,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, > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c > index 8f7f5e5..f3ad003 100644 > --- a/gcc/c-family/c-common.c > +++ b/gcc/c-family/c-common.c > @@ -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, > @@ -658,6 +660,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, > @@ -7891,6 +7896,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. */ > > diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c > index 8170a80..4657e48 100644 > --- a/gcc/c/c-decl.c > +++ b/gcc/c/c-decl.c > @@ -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); > diff --git a/gcc/common.opt b/gcc/common.opt > index 4c7933e..90cb06d 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -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. > @@ -1364,6 +1370,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 > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c > index 047fd77..9a02012 100644 > --- a/gcc/cp/decl.c > +++ b/gcc/cp/decl.c > @@ -1971,6 +1971,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); > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 1496d30..6589a41 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -1015,6 +1015,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 > @@ -20706,6 +20709,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 > diff --git a/gcc/function.c b/gcc/function.c > index 3e33fc7..7290d76 100644 > --- a/gcc/function.c > +++ b/gcc/function.c > @@ -4728,7 +4728,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)); > diff --git a/gcc/gimplify.c b/gcc/gimplify.c > index e2ae893..8401278 100644 > --- a/gcc/gimplify.c > +++ b/gcc/gimplify.c > @@ -89,6 +89,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. */ > @@ -1153,6 +1155,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 > @@ -2684,15 +2743,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 > @@ -4793,6 +4859,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); > @@ -4922,9 +4989,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); > @@ -4945,7 +5016,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); > > @@ -8284,6 +8357,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 *v; > + > + v = (vec *) 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 *) 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. > > diff --git a/gcc/ipa.c b/gcc/ipa.c > index 7c0d495..b62b301 100644 > --- a/gcc/ipa.c > +++ b/gcc/ipa.c > @@ -1429,6 +1429,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) > { > diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c > index fbd4e00..5ead4a6 100644 > --- a/gcc/java/jcf-parse.c > +++ b/gcc/java/jcf-parse.c > @@ -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; > > diff --git a/gcc/libfuncs.h b/gcc/libfuncs.h > index 04a4dc2..4c7faa4 100644 > --- a/gcc/libfuncs.h > +++ b/gcc/libfuncs.h > @@ -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]) > diff --git a/gcc/optabs.c b/gcc/optabs.c > index a3051ad..04d149c 100644 > --- a/gcc/optabs.c > +++ b/gcc/optabs.c > @@ -6202,6 +6202,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. */ > diff --git a/gcc/opts.c b/gcc/opts.c > index 6856c3c..14bb78d 100644 > --- a/gcc/opts.c > +++ b/gcc/opts.c > @@ -1540,6 +1540,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); > diff --git a/gcc/testsuite/g++.dg/other/instrument_calls-1.C b/gcc/testsuite/g++.dg/other/instrument_calls-1.C > new file mode 100644 > index 0000000..68e00c1 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/other/instrument_calls-1.C > @@ -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" } } */ > + > diff --git a/gcc/testsuite/g++.dg/other/instrument_calls-2.C b/gcc/testsuite/g++.dg/other/instrument_calls-2.C > new file mode 100644 > index 0000000..0a295e7 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/other/instrument_calls-2.C > @@ -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" } } */ > + > diff --git a/gcc/testsuite/g++.dg/other/instrument_calls-3.C b/gcc/testsuite/g++.dg/other/instrument_calls-3.C > new file mode 100644 > index 0000000..e96280a > --- /dev/null > +++ b/gcc/testsuite/g++.dg/other/instrument_calls-3.C > @@ -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" } } */ > + > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-1.c b/gcc/testsuite/gcc.dg/instrument_calls-1.c > new file mode 100644 > index 0000000..c406448 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-1.c > @@ -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" } } */ > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-2.c b/gcc/testsuite/gcc.dg/instrument_calls-2.c > new file mode 100644 > index 0000000..8be35be > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-2.c > @@ -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" } } */ > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-3.c b/gcc/testsuite/gcc.dg/instrument_calls-3.c > new file mode 100644 > index 0000000..ad14987 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-3.c > @@ -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" } } */ > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-4.c b/gcc/testsuite/gcc.dg/instrument_calls-4.c > new file mode 100644 > index 0000000..ef95a89 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-4.c > @@ -0,0 +1,8 @@ > +/* { dg-do compile } */ > +/* { dg-options "-finstrument-calls" } */ > + > +#include > +void fn_caller () { puts (""); } > + > +/* { dg-final { scan-assembler "__gnu_profile_call_before" } } */ > +/* { dg-final { scan-assembler "__gnu_profile_call_after" } } */ > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-5.c b/gcc/testsuite/gcc.dg/instrument_calls-5.c > new file mode 100644 > index 0000000..be567d7 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-5.c > @@ -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" } } */ > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-6.c b/gcc/testsuite/gcc.dg/instrument_calls-6.c > new file mode 100644 > index 0000000..38a2605 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-6.c > @@ -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" } } */ > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-7.c b/gcc/testsuite/gcc.dg/instrument_calls-7.c > new file mode 100644 > index 0000000..e6d9503 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-7.c > @@ -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" } } */ > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-8.c b/gcc/testsuite/gcc.dg/instrument_calls-8.c > new file mode 100644 > index 0000000..57d021b > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-8.c > @@ -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" } } */ > diff --git a/gcc/testsuite/gcc.dg/instrument_calls-9.c b/gcc/testsuite/gcc.dg/instrument_calls-9.c > new file mode 100644 > index 0000000..ec67040 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/instrument_calls-9.c > @@ -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" } } */ > diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c > index 00f78a1..967b1e7 100644 > --- a/gcc/tree-streamer-in.c > +++ b/gcc/tree-streamer-in.c > @@ -305,6 +305,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); > diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c > index fa50ef5..f71fea6 100644 > --- a/gcc/tree-streamer-out.c > +++ b/gcc/tree-streamer-out.c > @@ -271,6 +271,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); > diff --git a/gcc/tree.h b/gcc/tree.h > index b444517..456e41e 100644 > --- a/gcc/tree.h > +++ b/gcc/tree.h > @@ -3375,6 +3375,11 @@ struct GTY(()) > #define DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(NODE) \ > (FUNCTION_DECL_CHECK (NODE)->function_decl.no_instrument_function_entry_exit) > > +/* Used in FUNCTION_DECLs 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)->function_decl.no_instrument_calls_before_after) > + > /* Used in FUNCTION_DECLs to indicate that limit-stack-* should be > disabled in this function. */ > #define DECL_NO_LIMIT_STACK(NODE) \ > @@ -3512,6 +3517,7 @@ struct GTY(()) tree_function_decl { > unsigned no_inline_warning_flag : 1; > > unsigned no_instrument_function_entry_exit : 1; > + unsigned no_instrument_calls_before_after : 1; > unsigned no_limit_stack : 1; > unsigned disregard_inline_limits : 1; > unsigned pure_flag : 1; > @@ -3519,7 +3525,7 @@ struct GTY(()) tree_function_decl { > unsigned has_debug_args_flag : 1; > unsigned tm_clone_flag : 1; > unsigned versioned_function : 1; > - /* No bits left. */ > + /* -1 bit left */ > }; > > /* The source language of the translation-unit. */ > -- Paul Woegerer, SW Development Engineer Sourcery Analyzer Mentor Graphics, Embedded Software Division