public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
From: Pierre NGUYEN-TUONG <pierre.nguyen-tuong@lip6.fr>
To: help-gcc@gnu.org
Subject: Constructing Function Calls
Date: Wed, 10 Oct 2001 11:26:00 -0000	[thread overview]
Message-ID: <3BC492D8.9020601@lip6.fr> (raw)

Hello,

I have a slight problem. Consider two functions, function_A and 
function_B. I want to call function_B
inside function_A, with the same arguments of function_A, but without 
knowing the prototype of
function_B, ie passing all arguments of funtion_A to function_B (I don't 
want to use va_list in function_B).

A set of builtin functions allows this :
__builtin_apply_args()
__builtin__apply(void (*function)(),void *arguments,size_t size)

As you can see, you need to know the size of the stack arguments passed 
to the function.

Let see the code. The function_B is

---------------------------------------------------------
void function_B(char *name,void *function,int a,long b,float *c,int d)
{
printf("Function B : printing\n") ;

printf("--- name=%s\n"  ,name  ) ;
printf("--- a=%i\n"     ,a     ) ;
printf("--- b=%li\n"    ,b     ) ;
printf("--- c=%e\n"     ,*c    ) ;
printf("--- d=%i\n"     ,d     ) ;
}
---------------------------------------------------------

Inside the function_A, I try to guess the stack size. I forgot to tell 
you: function_A is a variadic
function, so you can use va_start, va_arg and va_end to parse the 
unknown arguments. I assume that
all the arguments are 4 bytes wide (float are 4 bytes wide, but are 
expanded to 8 bytes on the stack.
This is the problem ?).

Function_A is

---------------------------------------------------------
void function_A(char *name,void *function,...)
{
va_list ap               = NULL              ;
void    *dummy     = NULL              ;

int     cpt                = 1                       ;

size_t  size             = 0                       ;
void    *arguments = NULL              ;



/* Guessing stack size      */
/* I am using the va_arg macro */

printf("Function A : stack size\n") ;

va_start(ap,function) ;
dummy = va_arg(ap,void *) ;

printf("--- arg #%i : %p\n",cpt,dummy) ;

while(dummy != NULL)
   {
     cpt++ ;
     dummy = va_arg(ap,void *) ;
     printf("--- arg #%i : %p\n",cpt,dummy) ;
   }

va_end(ap) ;


/* Now calculating the stack size. Every argument shoud be 4 bytes wide */
size = cpt * 4 ;

printf("--- %i args, stack size=%i\n",cpt,size) ;


/* Storing arguments in the stack */
printf("Function A : applying arguments\n") ;

arguments = __builtin_apply_args(size) ;

printf("Function A : calling function\n") ;

/* The call */
__builtin_apply(function,arguments,size) ;
}
---------------------------------------------------------

The main program is

---------------------------------------------------------
int main(int argc,char *argv[])
{
float flottant = 0.0 ;

flottant = 7.999 ;

printf("--------------------------Test  A calling B\n\n") ;
function_A("le test",function_B,5,67L,&flottant,10,NULL) ;

return 0 ;
}
---------------------------------------------------------

And the result :

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

--------------------------Test  A calling B

Function A : stack size
--- arg #1 : 0x5
--- arg #2 : 0x43
--- arg #3 : 0xbfffed84
--- arg #4 : 0xa
--- arg #5 : (nil)
--- 5 args, stack size=20
Function A : applying arguments
Function A : calling function
Function B : printing
--- name=le test
--- a=5
--- b=67
--- c=7.999000e+00
--- d=5

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

Ok, it works. So, where is the problem ? Well, I used a pointer to give 
the float argument. But I want to give a float,
not a pointer to a float. So, lets examine function_C and the main program:

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

void function_C(char *name,void *function,int a,long b,float *c,float 
d,int e)
{
printf("Function B : printing\n") ;

printf("--- name=%s\n"  ,name  ) ;
printf("--- a=%i\n"     ,a     ) ;
printf("--- b=%li\n"    ,b     ) ;
printf("--- c=%e\n"     ,*c    ) ;
printf("--- d=%e\n"     ,d     ) ;
printf("--- e=%i\n"     ,e     ) ;
}

/***/

int main(int argc,char *argv[])
{
float flottant = 0.0 ;

flottant = 7.999 ;


printf("--------------------------Test  A calling C\n\n") ;
function_A("le test",function_C,5,67L,&flottant,flottant,10,NULL) ;


return 0 ;
}
---------------------------------------------------------

And now the trace of the execution:

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

--------------------------Test  A calling C

Function A : stack size
--- arg #1 : 0x5
--- arg #2 : 0x43
--- arg #3 : 0xbfffed84
--- arg #4 : 0xe0000000
--- arg #5 : 0x401ffef9
--- arg #6 : 0xa
--- arg #7 : (nil)
--- 7 args, stack size=28
Function A : applying arguments
Function A : calling function
Function B : printing
--- name=le test
--- a=5
--- b=67
--- c=7.999000e+00
--- d=-3.689349e+19
--- e=1075838713

---------------------------------------------------------
Arrgh !!! Big problem on the float... If I give the correct size for the 
stack (remember, a float
is 8 bytes wide in the stack) the result is the same.

So, finally, my question (sorry for the long explanation):

Is there a solution ? Shall I use only 32 bits arguments, ie pointers 
instead of float ? Am I wrong or
is there a bug somewhere ?
I don't see why the __builtin_apply function has a different behaviour 
for floats and for other types...
(By the way, I am working on Linux RedHat, AMD K6II.)


Any help is (really) appreciated,


Sincerely yours,


Pierre Nguyen Tuong.


             reply	other threads:[~2001-10-10 11:26 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-10-10 11:26 Pierre NGUYEN-TUONG [this message]
2001-10-10 12:14 ` John Love-Jensen
2005-07-21 22:52 Constructing function calls Jean-Sebastien Legare
2005-07-21 23:03 Meissner, Michael

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3BC492D8.9020601@lip6.fr \
    --to=pierre.nguyen-tuong@lip6.fr \
    --cc=help-gcc@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).