This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PING^2] Re: [PATCH] Caller instrumentation with -finstrument-calls


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,  <Paul_Woegerer@mentor.com> 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 <paul_woegerer@mentor.com>
> Date: Mon, 1 Jul 2013 09:15:21 +0200
> Subject: [PATCH] Caller instrumentation with -finstrument-calls.
> 
> 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.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<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.
>  
> 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 <stdio.h>
> +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 <http://go.mentor.com/sourceryanalyzer>
Mentor Graphics, Embedded Software Division


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]