From mboxrd@z Thu Jan 1 00:00:00 1970 From: Pierre NGUYEN-TUONG To: help-gcc@gnu.org Subject: Constructing Function Calls Date: Wed, 10 Oct 2001 11:26:00 -0000 Message-id: <3BC492D8.9020601@lip6.fr> X-SW-Source: 2001-10/msg00064.html 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.