I am hacking in the gcc code and come to a point where I cant come
any further: I want to expand the "-finstrument-functions" to create a dynamic
dump function in the background, instead of  calling a fixed
__cyg_profile_func_enter/exit
I.e:
 if I have
 f1(int a,int b) { }
 I would like to create a dynamic function
 _trace_f1(int a,int b) {
   __trace_int(a);
   __trace_int(b);
 }

I apended the code I use below. the function
gimplify_create_trace_func (shown below) is
called from:

gimplify_function_tree (tree fndecl)->
 gimplify_create_trace_func(fndecl,"_trace_f1");


These are the steps I do in gimplify_create_trace_func():

1. Build function definition for _trace_f1:   build_decl
(FUNCTION_DECL, get_identifier (n), fntyp);
2. Declare function parameters for "a" and "b": build_decl (PARM_DECL,
get_identifier (argname), TREE_TYPE(param));
3. Output each parameter:          build_function_call_expr (trace ,
thisparaml );
  where "thisparaml" is "a" or "b" and trace is a external function
ref repending on the typ:

The problem now is this:
The assembler output is:

_trace_f1:
       pushl   %ebp
       movl    %esp, %ebp
       subl    $8, %esp
       movl    $0, (%esp)
       call    __trace__int
       movl    $0, (%esp)
       call    __trace__int
       leave
       ret

whereas I would expect:

_trace_f1:
       pushl   %ebp
       movl    %esp, %ebp
       subl    $8, %esp
       movl    8(%ebp), %eax
       movl    %eax, (%esp)
       call    __trace__int
       movl    12(%ebp), %eax
       movl    %eax, (%esp)
       call    __trace__int
       ...

Can anyone tell me what I am doing wrong. The compiler oututs
__trace__int(0) instead of using the function parameter as an argument:
 _trace_f1(int a,int b) {
   __trace_int(a);
  ...

Or can somebody point me to a codesnippet in  gcc that
does the same (create functions dynamically on the fly) so
I can  take a look and learn...


Greetings



----------- create a dynamic funtion ------------------------

void
gimplify_create_trace_func (tree fndecl, char *n)
{
       int i;
       tree body = NULL;
       tree ir, prev, param, fn, fntyp, parm, tdef, argstyp =
NULL_TREE, argslist = NULL_TREE ;
       char argname[256];

       /* create function type */
       for (i = 0,param = DECL_ARGUMENTS (fndecl); param ; i++,param
=TREE_CHAIN (param)) {
               argstyp = tree_cons (NULL_TREE, TREE_TYPE(param), argstyp);
       }
       if (argstyp == NULL_TREE)
               argstyp = void_list_node;
       else {
               tree last = argstyp;
               argstyp = nreverse (argstyp);
               TREE_CHAIN (last) = void_list_node;
       }
       fntyp = build_function_type (void_type_node, argstyp);

       /* build function prototype */
       fn = build_decl (FUNCTION_DECL, get_identifier (n), fntyp);

       pushdecl (fn);

       prev = current_function_decl;
       current_function_decl = fn;

       push_scope();
       declare_parm_level ();

       /* build function argument list */
       for (i = 0,param = DECL_ARGUMENTS (fndecl); param ; i++,param
=TREE_CHAIN (param)) {
               tree argdecl;
               sprintf(argname,"a%d",i);
               argdecl = build_decl (PARM_DECL, get_identifier
(argname), TREE_TYPE(param));
               argslist = chainon (argdecl, argslist);
               printf("decl:%x\n",argdecl);
               pushdecl(argdecl);
               DECL_ARTIFICIAL(argdecl) = 1;


               /* if (DECL_NAME (argdecl)) { */
               /*      bind (DECL_NAME (decl), decl, current_scope, */
               /*            /\*invisible=*\/false, /\*nested=*\/false); */
               /* } */

               DECL_CONTEXT (argdecl) = fn;
       }
       argslist = nreverse (argslist);
       DECL_ARGUMENTS (fn) = argslist;


       ir = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
       DECL_CONTEXT (ir) = fn;
       DECL_ARTIFICIAL (ir) = 1;
       DECL_IGNORED_P (ir) = 1;
       DECL_RESULT (fn) = ir;


       TREE_STATIC (fn) = 0;
       TREE_USED (fn) = 1;
       DECL_ARTIFICIAL (fn) = 1;
       DECL_IGNORED_P (fn) = 1;
       DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fn) = 1;

       allocate_struct_function (fn);

       if (tracetype == trace_out_none) {

               DECL_SAVED_TREE (fn) = build_empty_stmt();

       } else if (tracetype == trace_out_all) {

               tree thisp, stmts;

               stmts = alloc_stmt_list();

               /* output one call for each argument */
               for (i = 0,thisp = argslist, param = DECL_ARGUMENTS
(fndecl); param; i++,thisp = TREE_CHAIN (thisp), param =TREE_CHAIN
(param)) {
                       tree trace, thisparaml = NULL, x;
                       char *name =
gen_aux_info_type_str_canonical(TREE_TYPE(param));
                       name = concat("__trace__", name, NULL);
                       fprintf(stderr, "typ: \"%s\" \n", name);

                       trace = build_function_type_list
(void_type_node, TREE_TYPE(thisp), NULL);
                       trace = build_decl (FUNCTION_DECL,
get_identifier (name), trace);
                       TREE_PUBLIC (trace) = 1;
                       DECL_EXTERNAL (trace) = 1;

                       thisparaml = tree_cons (NULL, thisp, thisparaml);

                       x = build_function_call_expr (trace , thisparaml );

                       dump_node(x, 0, stderr);

                       append_to_statement_list (x, &stmts);

               }

               DECL_SAVED_TREE (fn) = stmts /*body*/;
       }

       TREE_PUBLIC (fn) = 1; /*! targetm.have_ctors_dtors;*/
       DECL_UNINLINABLE (fn) = 1;

       DECL_INITIAL (fn) = make_node (BLOCK);
       TREE_USED (DECL_INITIAL (fn)) = 1;

       pop_scope();

       /* output function */
       gimplify_function_tree (fn);

               if (cgraph_global_info_ready)
                       {
                               tree_lowering_passes (fn);
                               tree_rest_of_compilation (fn);
                       }
               else
                       cgraph_finalize_function (fn, 0);

       current_function_decl = prev;

}

Reply via email to