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]

Re: new -finstrument-function -like option


Hello,

some times ago I wrote a mail about a small patch to
add a new feature to the instrument-function option (see
joined mail below).
It was more than a month in the past and I can't see
any reaction about that.

So please could someone let me know if this feature
does not interest anyone (in this case I will let down
that thing) or if it is only a too small feature to be treated
now (because I received two mails from people asking
me what's the status of this modification, and I don't
know what to answer to them).

Maybe also may patch is not is the good format or
not complete enough. If it is the case please let me know
I can correct that.

Thank in advance.

Regards,
--
Yannick Perret




Perret Yannick wrote:


Hi,
here is a patch for gcc.

Parts of this mail are:
- Description
- Testcases
- ChangeLog
- Bootstrapping
- Patch
- Comments and discussion

* Description:

I use the '-finstrument-functions' for some program execution
tracking, but with 'dlopen/dlsym/dlclose' functions and in
some other cases addresses of functions is not enough.

So I added a new option called '-finstrument-functions-full'
which do exactly the same job than '-finstrument-functions'
(adding calls to entry and exit of each function), but with
more detailled informations.
Names of the called functions do not change, and are still
__cyg_profile_func_{enter|exit}, but with the new option
the prototype of the _enter function is:
__cyg_profile_func_enter(void *sym, void *call,
                   char *fnc0, char *fnc1, char *fnc2,
                   char *file, int line, int id);
where:
  sym   is the symbol address of the function  \ same than the
  call  is the symbol address of the call site / original ones
  fnc0  is the 'level 0' name (declaration name)
  fnc1  is the 'level 1' name (scope information)
  fnc2  is the 'level 2' name (all including C++ full style)
  file  is the function's file name
  line  is the line of the function declaration in the file
  id    is the unique identifier generated by gcc for profile

The _exit function is not changed.

Changes in the code are simple:
- declaration of the new option and creation of a flag for it
(mainly in common.opt, topvel.c, opts.c, c-opts.c, flags.h, function.h)
- creation of the new call to the _enter function, with the construction
of the arguments. This part is roughly a sub-part of the original
call in function.c

I also added the corresponding documentation in gcc/doc/, files
extend.texi and invoke.texi (everywhere it was talking about
-finstrument-function).


* Testcases


I added a test program gcc/testsuite/gcc.dg/20040916-1.c in a similar
way the '-finstrument-functions' is treated. I ran the sequence
"make bootstrap ; make -k check" without any problem.
I also made tests to check that additionnal arguments are correctly
given and are usable in a test program.
Of course I tested compilations with and without the new option,
and I tested that the initial option '-finstrument-functions' still
work properly.

All my tests were performed on a laptop with 2.4.22-i686 kernel under
debian, with initial compilation using gcc (GCC) 3.4.1.


* ChangeLog


2004-09-16 Yannick Perret <yperret@in2p3.fr>

    * common.opt: new option definition
      'finstrument-function-full'
    * flags.h: declaration of new flag to handle
      the selection of the new option
    * function.h: new flag to handle the selection
      of the new option
    * opts.c: (commom_handle_option) new case
      to handle initialization of the flag
    * c-opts.c: (c_common_post_options) desactivate
      inlining if '-finstrument-function-full' is
      selected
    * toplevl.c: declaration of the flag for the
      new option
    * function.c: (expand_function_start) added
      flags activation at the begin for the new
      option
    * function.c: (expand_function_start) added
      a code block to treat the creation of new
      arguments to pass to the __cyg_profile_func_enter
      function, if '-finstrument-function' is selected




* Bootstrapping and testing


See 'Testcase' above.


* The patch


The patch is attached in this mail (patch-gcc.patch).

Some notes about that patch:
- the command given in the following page:
http://gcc.gnu.org/contribute.html
is "|diff -c3p OLD NEW"|, but it does not include
subdirectories... So my patch was created with the
following command: "diff -rc3p OLD NEW"
- I failed to create the patch using the CVS repository
as I cannot manage to compile the CVS's GCC. I
suppose that something is broken these days on the
CVS.
That's why I used the release version gcc-3.4.2 to
generate the patch.


* Comments and discussion


I can see several ways to include this new feature in
GCC. I made a choice, but I do not know if it is the
best one. I'm open to change the patch if an other
approach is better.

In fact my new option act exactly as -finstrument-functions
acts, but with more arguments at entry point (function
name, file, line...).

This feature can be added by creating a new option
(it's what I did) which generate calls to the same function,
with additionnal arguments. The original option is
unchanged.

It is also possible to generate a call to a different function
(i.e. __cyg_profile_func_enter_full).

It is also possible to modify the initial option
(-finstrument-functions) so that it always generates the
detailed arguments. It is still compatible with old usage
because the first arguments are the same and the additionnal
one would be ignored by the __cyg_profile_func_enter
function. The problem is that it generates additionnal code
in the compiled program even if it is not used.

In addition, it is possible in all of these cases to do the
same job at the exit of the functions.


So if you think that one of these choices is better than the actual one, please let me know.

Regards,
--
Yannick Perret



||||

------------------------------------------------------------------------

diff -rc3p gcc-3.4.2-orig/gcc/c-opts.c gcc-3.4.2/gcc/c-opts.c
*** gcc-3.4.2-orig/gcc/c-opts.c Thu Sep 16 17:44:47 2004
--- gcc-3.4.2/gcc/c-opts.c Fri Sep 17 10:15:16 2004
*************** c_common_post_options (const char **pfil
*** 1080,1086 ****
/* Use tree inlining if possible. Function instrumentation is only
done in the RTL level, so we disable tree inlining. */
! if (flag_instrument_function_entry_exit)
{
flag_no_inline = 1;
flag_really_no_inline = 1;
--- 1080,1087 ----
/* Use tree inlining if possible. Function instrumentation is only
done in the RTL level, so we disable tree inlining. */
! if (flag_instrument_function_entry_exit
! || flag_instrument_function_entry_exit_details)
{
flag_no_inline = 1;
flag_really_no_inline = 1;
diff -rc3p gcc-3.4.2-orig/gcc/common.opt gcc-3.4.2/gcc/common.opt
*** gcc-3.4.2-orig/gcc/common.opt Thu Sep 16 17:44:47 2004
--- gcc-3.4.2/gcc/common.opt Fri Sep 17 10:14:28 2004
*************** finstrument-functions
*** 408,413 ****
--- 408,417 ----
Common
Instrument function entry and exit with profiling calls
+ finstrument-functions-full
+ Common
+ Instrument function entry and exit with profiling calls with details
+ fkeep-inline-functions
Common
Generate code for functions even if they are fully inlined
diff -rc3p gcc-3.4.2-orig/gcc/doc/extend.texi gcc-3.4.2/gcc/doc/extend.texi
*** gcc-3.4.2-orig/gcc/doc/extend.texi Thu Sep 16 17:44:58 2004
--- gcc-3.4.2/gcc/doc/extend.texi Fri Sep 17 10:16:16 2004
*************** my_memcpy (void *dest, const void *src, *** 2251,2257 ****
@item no_instrument_function
@cindex @code{no_instrument_function} function attribute
@opindex finstrument-functions
! If @option{-finstrument-functions} is given, profiling function calls will
be generated at entry and exit of most user-compiled functions.
Functions with this attribute will not be so instrumented.
--- 2251,2258 ----
@item no_instrument_function
@cindex @code{no_instrument_function} function attribute
@opindex finstrument-functions
! If @option{-finstrument-functions} or @option{-finstrument-functions-full}
! is given, profiling function calls will
be generated at entry and exit of most user-compiled functions.
Functions with this attribute will not be so instrumented.
diff -rc3p gcc-3.4.2-orig/gcc/doc/invoke.texi gcc-3.4.2/gcc/doc/invoke.texi
*** gcc-3.4.2-orig/gcc/doc/invoke.texi Thu Sep 16 17:44:58 2004
--- gcc-3.4.2/gcc/doc/invoke.texi Fri Sep 17 10:16:21 2004
*************** in the following sections.
*** 666,672 ****
-fnon-call-exceptions -funwind-tables @gol
-fasynchronous-unwind-tables @gol
-finhibit-size-directive -finstrument-functions @gol
! -fno-common -fno-ident @gol
-fpcc-struct-return -fpic -fPIC -fpie -fPIE @gol
-freg-struct-return -fshared-data -fshort-enums @gol
-fshort-double -fshort-wchar @gol
--- 666,672 ----
-fnon-call-exceptions -funwind-tables @gol
-fasynchronous-unwind-tables @gol
-finhibit-size-directive -finstrument-functions @gol
! -finstrument-functions-full -fno-common -fno-ident @gol
-fpcc-struct-return -fpic -fPIC -fpie -fPIE @gol
-freg-struct-return -fshared-data -fshort-enums @gol
-fshort-double -fshort-wchar @gol
*************** interrupt routines, and any functions fr
*** 11156,11161 ****
--- 11156,11194 ----
cannot safely be called (perhaps signal handlers, if the profiling
routines generate output or allocate memory).
+ @item -finstrument-functions-full
+ @opindex finstrument-functions-full
+ Generate instrumentation calls for entry and exit to functions. It
+ act just the same way than @option{-finstrument-functions} option,
+ but with more detailed informations about the function. Only the
+ the @code{__cyg_profile_func_enter} is changed, and the
+ @code{__cyg_profile_func_exit} is left unchanged. The new prototype
+ for the entry function is:
+ + @smallexample
+ void __cyg_profile_func_enter (void *this_fn,
+ void *call_site,
+ const char *func_name_decl,
+ const char *func_name_scope,
+ const char *func_name_full,
+ const char *file,
+ int line,
+ int prof_id);
+ @end smallexample
+ + The two first arguments have the same meaning than for the
+ @option{-finstrument-function} option. The @code{func_name_*}
+ arguments give the name of the function with several levels
+ of details. For C all these strings are the same, but for C++
+ it correspond to the demangling level. @code{file} is the file
+ name in which leads the function, and @code{line} is the line number
+ of the function declaration in the file. The last value @code{prof_id}
+ is an integer generated by GCC which is unique for each function.
+ + Any attributes, restrictions or limits detailled in the
+ @option{-finstrument-functions} documentation also apply to this
+ option.
+ @item -fstack-check
@opindex fstack-check
Generate code to verify that you do not go beyond the boundary of the
diff -rc3p gcc-3.4.2-orig/gcc/flags.h gcc-3.4.2/gcc/flags.h
*** gcc-3.4.2-orig/gcc/flags.h Thu Sep 16 17:44:50 2004
--- gcc-3.4.2/gcc/flags.h Fri Sep 17 10:12:12 2004
*************** extern int flag_regmove;
*** 577,582 ****
--- 577,586 ----
/* Instrument functions with calls at entry and exit, for profiling. */
extern int flag_instrument_function_entry_exit;
+ /* Instrument functions with calls at entry and exit, for profiling,
+ with additionnal details (such as name, file...) */
+ extern int flag_instrument_function_entry_exit_details;
+ /* Perform a peephole pass before sched2. */
extern int flag_peephole2;
diff -rc3p gcc-3.4.2-orig/gcc/function.c gcc-3.4.2/gcc/function.c
*** gcc-3.4.2-orig/gcc/function.c Thu Sep 16 17:44:51 2004
--- gcc-3.4.2/gcc/function.c Fri Sep 17 10:12:04 2004
*************** expand_pending_sizes (tree pending_sizes
*** 6618,6623 ****
--- 6618,6652 ----
}
}
+ + /* Create a new constant string literal and return a char* pointer to it.
+ The STRING_CST value is the LEN characters at STR. */
+ /* Note: imported from 'builtins.c' because it is declared static
+ and so not available in this scope. Is there a reason for
+ that choice? This function and its friends is usefull to build
+ simple trees */
+ static tree
+ build_string_literal (int len, const char *str)
+ {
+ tree t, elem, index, type;
+ + t = build_string (len, str);
+ elem = build_type_variant (char_type_node, 1, 0);
+ index = build_index_type (build_int_2 (len - 1, 0));
+ type = build_array_type (elem, index);
+ TREE_TYPE (t) = type;
+ TREE_CONSTANT (t) = 1;
+ TREE_READONLY (t) = 1;
+ TREE_STATIC (t) = 1;
+ + type = build_pointer_type (type);
+ t = build1 (ADDR_EXPR, type, t);
+ + type = build_pointer_type (elem);
+ t = build1 (NOP_EXPR, type, t);
+ return t;
+ }
+ /* Start the RTL for a new function, and set variables used for
emitting RTL.
SUBR is the FUNCTION_DECL node.
*************** expand_function_start (tree subr, int pa
*** 6634,6641 ****
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));
current_function_profile
--- 6663,6680 ----
valid operands of arithmetic insns. */
init_recog_no_volatile ();
+ /* CURRENT_FUNCTION_INSTRUMENT_ENTRY_EXIT is set
+ if the option '-finstrument-functions-full is
+ used as this option modify the
+ '-finstrument-functions' behavior */
current_function_instrument_entry_exit
! = ((flag_instrument_function_entry_exit ||
! flag_instrument_function_entry_exit_details)
! && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
! ! /* option '-finstrument-functions-full' is used */
! current_function_instrument_entry_exit_details
! = (flag_instrument_function_entry_exit_details
&& ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
current_function_profile
*************** expand_function_start (tree subr, int pa
*** 6811,6822 ****
fun = XEXP (fun, 0);
else
abort ();
! emit_library_call (profile_function_entry_libfunc, LCT_NORMAL, VOIDmode,
! 2, fun, Pmode,
! expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
! 0,
! hard_frame_pointer_rtx),
! Pmode);
}
if (current_function_profile)
--- 6850,6978 ----
fun = XEXP (fun, 0);
else
abort ();
! ! ! /* if details requested, build trees and then rtxs to
! handle the additionnal parameters and then do a full
! call to the profile function (else emit standard call)
! The extended call have the following 'prototype':
! __cyg_profile_func_enter(void *sym, void *call,
! char *fnc0, char *fnc1, char *fnc2,
! char *file, int line, int id);
! where:
! sym is the symbol address of the function \ same than the
! call is the symbol address of the call site / original ones
! fnc0 is the 'level 0' name (declaration name)
! fnc1 is the 'level 1' name (scope information)
! fnc2 is the 'level 2' name (all including C++ full style)
! file is the function's file name
! line is the line of the function declaration in the file
! id is the unique identifier generated by gcc for profile
! */
! if (current_function_instrument_entry_exit_details)
! {
! /* trees for additionnal parameters */
! tree arg_func1, arg_func2, arg_func0, arg_file, arg_line, arg_id;
! /* temporary strings for function and file names */
! char *str_file, *str_func0, *str_func1, *str_func2;
! /* rtxs corresponding to the arguments */
! rtx rfunc0, rfunc1, rfunc2, rfile, rline, rid;
! ! /* create tree for function name (0) */
! str_func0 = (char *) alloca (strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 2)+1));
! if (str_func0 != NULL)
! {
! memcpy (str_func0, (*lang_hooks.decl_printable_name) (cfun->decl, 0),
! strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 0)));
! str_func0[strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 0))] = 0;
! arg_func0 = build_string_literal (strlen((*lang_hooks.decl_printable_name) (cfun->decl, 0))+1, str_func0);
! }
! /* create tree for function name (1) */
! str_func1 = (char *) alloca (strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 1)+1));
! if (str_func1 != NULL)
! {
! memcpy (str_func1, (*lang_hooks.decl_printable_name) (cfun->decl, 1),
! strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 1)));
! str_func1[strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 1))] = 0;
! arg_func1 = build_string_literal (strlen((*lang_hooks.decl_printable_name) (cfun->decl, 1))+1, str_func1);
! }
! /* create tree for function name (2) */
! str_func2 = (char *) alloca (strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 2)+1));
! if (str_func2 != NULL)
! {
! memcpy (str_func2, (*lang_hooks.decl_printable_name) (cfun->decl, 2),
! strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 2)));
! str_func2[strlen ((*lang_hooks.decl_printable_name) (cfun->decl, 2))] = 0;
! arg_func2 = build_string_literal (strlen((*lang_hooks.decl_printable_name) (cfun->decl, 2))+1, str_func2);
! }
! /* create tree for file name */
! str_file = (char *) alloca (strlen((DECL_SOURCE_LOCATION (subr)).file)+1);
! if (str_file != NULL)
! {
! memcpy (str_file, (DECL_SOURCE_LOCATION (subr)).file, strlen((DECL_SOURCE_LOCATION (subr)).file));
! str_file[strlen((DECL_SOURCE_LOCATION (subr)).file)] = 0;
! arg_file = build_string_literal (strlen((DECL_SOURCE_LOCATION (subr)).file)+1, str_file);
! }
! ! /* create tree for the line */
! arg_line = build_int_2 (((DECL_SOURCE_LOCATION (subr)).line)&0xffff,
! (((DECL_SOURCE_LOCATION (subr)).line)&0xffff0000)>>16);
! ! /* create tree for the Id */
! arg_id = build_int_2 (cfun->funcdef_no&0xffff,
! (cfun->funcdef_no&0xffff0000)>>16);
! ! /* build rtxs for the various arguments */
! rfunc0 = NULL_RTX;
! rfunc1 = NULL_RTX;
! rfunc2 = NULL_RTX;
! rfile = NULL_RTX;
! rline = NULL_RTX;
! rid = NULL_RTX;
! if (str_func0 == NULL)
! rfunc0 = const0_rtx; /* NULL pointer */
! else
! rfunc0 = expand_expr (arg_func0, NULL_RTX, Pmode, EXPAND_NORMAL);
! if (str_func1 == NULL)
! rfunc1 = const0_rtx; /* NULL pointer */
! else
! rfunc1 = expand_expr (arg_func1, NULL_RTX, Pmode, EXPAND_NORMAL);
! if (str_func2 == NULL)
! rfunc2 = const0_rtx; /* NULL pointer */
! else
! rfunc2 = expand_expr (arg_func2, NULL_RTX, Pmode, EXPAND_NORMAL);
! if (str_file == NULL)
! rfile = const0_rtx; /* NULL pointer */
! else
! rfile = expand_expr (arg_file, NULL_RTX, Pmode, EXPAND_NORMAL);
! rline = expand_expr (arg_line, NULL_RTX, Pmode, EXPAND_NORMAL);
! rid = expand_expr (arg_id, NULL_RTX, Pmode, EXPAND_NORMAL);
! ! /* now call 'profile_function_entry_libfunc' with original parameters
! followed by all the additionnals ones */
! emit_library_call (profile_function_entry_libfunc, LCT_NORMAL, VOIDmode,
! 8, fun, Pmode,
! expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
! 0,
! hard_frame_pointer_rtx),
! Pmode,
! rfunc0, Pmode,
! rfunc1, Pmode,
! rfunc2, Pmode,
! rfile, Pmode,
! rline, Pmode,
! rid, Pmode);
! }
! else
! {
! /* emit standard call */
! emit_library_call (profile_function_entry_libfunc, LCT_NORMAL, VOIDmode,
! 2, fun, Pmode,
! expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
! 0,
! hard_frame_pointer_rtx),
! Pmode);
! }
}
if (current_function_profile)
diff -rc3p gcc-3.4.2-orig/gcc/function.h gcc-3.4.2/gcc/function.h
*** gcc-3.4.2-orig/gcc/function.h Thu Sep 16 17:44:51 2004
--- gcc-3.4.2/gcc/function.h Fri Sep 17 10:12:26 2004
*************** struct function GTY(())
*** 474,479 ****
--- 474,483 ----
generated. */
unsigned int instrument_entry_exit : 1;
+ /* Nonzero if instrumentation calls for function entry and exit should be
+ generated (detailled version) */
+ unsigned int instrument_entry_exit_details : 1;
+ /* Nonzero if profiling code should be generated. */
unsigned int profile : 1;
*************** extern int trampolines_created;
*** 554,559 ****
--- 558,564 ----
#define current_function_internal_arg_pointer (cfun->internal_arg_pointer)
#define current_function_return_rtx (cfun->return_rtx)
#define current_function_instrument_entry_exit (cfun->instrument_entry_exit)
+ #define current_function_instrument_entry_exit_details (cfun->instrument_entry_exit_details)
#define current_function_profile (cfun->profile)
#define current_function_funcdef_no (cfun->funcdef_no)
#define current_function_limit_stack (cfun->limit_stack)
diff -rc3p gcc-3.4.2-orig/gcc/opts.c gcc-3.4.2/gcc/opts.c
*** gcc-3.4.2-orig/gcc/opts.c Thu Sep 16 17:44:51 2004
--- gcc-3.4.2/gcc/opts.c Fri Sep 17 10:12:34 2004
*************** common_handle_option (size_t scode, cons
*** 1075,1080 ****
--- 1075,1084 ----
flag_instrument_function_entry_exit = value;
break;
+ case OPT_finstrument_functions_full:
+ flag_instrument_function_entry_exit_details = value;
+ break;
+ case OPT_fkeep_inline_functions:
flag_keep_inline_functions =value;
break;
Only in gcc-3.4.2/gcc/testsuite/gcc.dg: 20040916-1.c
diff -rc3p gcc-3.4.2-orig/gcc/toplev.c gcc-3.4.2/gcc/toplev.c
*** gcc-3.4.2-orig/gcc/toplev.c Thu Sep 16 17:44:51 2004
--- gcc-3.4.2/gcc/toplev.c Fri Sep 17 10:12:47 2004
*************** int flag_strict_aliasing = 0;
*** 919,924 ****
--- 919,928 ----
/* Instrument functions with calls at entry and exit, for profiling. */
int flag_instrument_function_entry_exit = 0;
+ /* Instrument functions with calls at entry and exit, for profiling,
+ but with additionnal details at entry point (such as name, file...) */
+ int flag_instrument_function_entry_exit_details = 0;
+ /* Nonzero means ignore `#ident' directives. 0 means handle them.
On SVR4 targets, it also controls whether or not to emit a
string identifying the compiler. */
*************** static const lang_independent_options f_
*** 1137,1142 ****
--- 1141,1147 ----
{"merge-all-constants", &flag_merge_constants, 2 },
{"dump-unnumbered", &flag_dump_unnumbered, 1 },
{"instrument-functions", &flag_instrument_function_entry_exit, 1 },
+ {"instrument-functions-full", &flag_instrument_function_entry_exit_details, 1 },
{"zero-initialized-in-bss", &flag_zero_initialized_in_bss, 1 },
{"leading-underscore", &flag_leading_underscore, 1 },
{"ident", &flag_no_ident, 0 },




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