Discussion:
__builtin_apply_args - GCC 4.1.1
Mohamed Shafi
2007-06-01 09:08:49 UTC
Permalink
Hello all,

I am working with a private target(GCC v4.1.1).
For my target the function arguments are passed through registers.
For this purpose 4 registers are used. If the no. of arguments are
more than 4, the remaining arguments are passed through stack.

But for varargs the arguments are pushed into the stack by the caller function.

I am getting a execution failure for the following test case.

#include <stdio.h>
#include <stdarg.h>

#define INTEGER_ARG 5

void foo(char *name, int d, int e, int f, int g)
{
printf("\nname = %s\n13 = %d\n72 = %d\n89 = %d\n5 = %d\n", name,d,e,f,g );
}

void bar(char *name, ...)
{
void **arg;
arg = __builtin_apply_args();
__builtin_apply(foo, arg, 24);
}

int main(void)
{
bar("eeee", 13, 72, 89, INTEGER_ARG);
return 0;
}

The above testcase is similar to gcc-src/gcc/testsuite/gcc.dg/builtin-apply2.c

Looking at the assembly file i find that __builtin_apply_args() is
where the problem lies.
Even though main pushes all the arguments in the stack
__builtin_apply_args is expecting the values in the argument
registers. More over when foo is called the arguments are to be
passed through registers ("eeee", 13, 72, 89) and stack (INTEGER_ARG).

The problem is due to two things.
1. __builtin_apply_args is picking the arguments from the argument
registers even though they are not available there since its
varargs.So its actually storing garbage values in the block.

2. __builtin_apply_args is storing the arguments, even though garbage,
in wrong order in the block. From this block, stored in the wrong
order, __builtin_apply passes the arguments to foo, and
__builtin_apply function is doing the job properly.

Is there any way to control the behavior of __builtin_apply_args?

Regards,
Shafi
Ian Lance Taylor
2007-06-01 14:22:39 UTC
Permalink
Post by Mohamed Shafi
I am working with a private target(GCC v4.1.1).
For my target the function arguments are passed through registers.
For this purpose 4 registers are used. If the no. of arguments are
more than 4, the remaining arguments are passed through stack.
But for varargs the arguments are pushed into the stack by the caller function.
These days the usual style is to handle arguments for normal and
varargs functions in exactly the same way. This avoids errors when
calling a function without a proper prototype in scope. But certainly
what you describe is a valid way to implement a backend.
Post by Mohamed Shafi
void foo(char *name, int d, int e, int f, int g)
{
printf("\nname = %s\n13 = %d\n72 = %d\n89 = %d\n5 = %d\n", name,d,e,f,g );
}
void bar(char *name, ...)
{
void **arg;
arg = __builtin_apply_args();
__builtin_apply(foo, arg, 24);
}
For your platform, __builtin_apply will only work when the callee has
the same signature as the caller. __builtin_apply has no support for
changing the way that arguments are passed. It simply passes the
arguments to the callee in the same way that they were passed to the
caller.

Before you really dig into this, do you care? __builtin_apply only
exists to implement the Objective C runtime. And in fact it is
generally considered desirable to change that code to use libffi
instead, in which case __builtin_apply will probably be deprecated and
removed. If you don't need to compile Objective C, I wouldn't worry
about __builtin_apply.

Ian
Mohamed Shafi
2007-06-02 04:47:01 UTC
Permalink
Post by Ian Lance Taylor
Post by Mohamed Shafi
I am working with a private target(GCC v4.1.1).
For my target the function arguments are passed through registers.
For this purpose 4 registers are used. If the no. of arguments are
more than 4, the remaining arguments are passed through stack.
But for varargs the arguments are pushed into the stack by the caller function.
These days the usual style is to handle arguments for normal and
varargs functions in exactly the same way. This avoids errors when
calling a function without a proper prototype in scope. But certainly
what you describe is a valid way to implement a backend.
Initially implementation was same for both. But DWARF2 was going wrong
for varargs function. So we had to change the implementation for that.
What we did was removing the target hook TARGET_SETUP_INCOMING_VARARGS.
Post by Ian Lance Taylor
Post by Mohamed Shafi
void foo(char *name, int d, int e, int f, int g)
{
printf("\nname = %s\n13 = %d\n72 = %d\n89 = %d\n5 = %d\n", name,d,e,f,g );
}
void bar(char *name, ...)
{
void **arg;
arg = __builtin_apply_args();
__builtin_apply(foo, arg, 24);
}
For your platform, __builtin_apply will only work when the callee has
the same signature as the caller. __builtin_apply has no support for
changing the way that arguments are passed. It simply passes the
arguments to the callee in the same way that they were passed to the
caller.
This test case passed before removing the target hook
TARGET_SETUP_INCOMING_VARARGS. All that changed is that now varable
arguments are pushed into the stack by the caller function. So i guess
the term "same signature" also include the way the arguments are
passed by the functions.
Post by Ian Lance Taylor
Before you really dig into this, do you care? __builtin_apply only
exists to implement the Objective C runtime. And in fact it is
generally considered desirable to change that code to use libffi
instead, in which case __builtin_apply will probably be deprecated and
removed. If you don't need to compile Objective C, I wouldn't worry
about __builtin_apply.
I am concerned about only C. If __builtin_apply is important only in
Objective C why is it that this test case is included in C test suites
?
If the outcome of the test cases involving __builtin_apply and
__builtin_apply_args doesnt matter for a C compiler is it proper to
include them in the C testsuites ?

Regards,
Shafi.
Ian Lance Taylor
2007-06-02 05:49:34 UTC
Permalink
Post by Mohamed Shafi
Post by Ian Lance Taylor
Post by Mohamed Shafi
I am working with a private target(GCC v4.1.1).
For my target the function arguments are passed through registers.
For this purpose 4 registers are used. If the no. of arguments are
more than 4, the remaining arguments are passed through stack.
But for varargs the arguments are pushed into the stack by the caller function.
These days the usual style is to handle arguments for normal and
varargs functions in exactly the same way. This avoids errors when
calling a function without a proper prototype in scope. But certainly
what you describe is a valid way to implement a backend.
Initially implementation was same for both. But DWARF2 was going wrong
for varargs function. So we had to change the implementation for that.
What we did was removing the target hook TARGET_SETUP_INCOMING_VARARGS.
That doesn't seem like the right approach to me, but, whatever.
Post by Mohamed Shafi
Post by Ian Lance Taylor
For your platform, __builtin_apply will only work when the callee has
the same signature as the caller. __builtin_apply has no support for
changing the way that arguments are passed. It simply passes the
arguments to the callee in the same way that they were passed to the
caller.
This test case passed before removing the target hook
TARGET_SETUP_INCOMING_VARARGS. All that changed is that now varable
arguments are pushed into the stack by the caller function. So i guess
the term "same signature" also include the way the arguments are
passed by the functions.
The signature is the type of the function, including the return type
and the parameter types and whether an ellipsis is used, so, yes.
Post by Mohamed Shafi
Post by Ian Lance Taylor
Before you really dig into this, do you care? __builtin_apply only
exists to implement the Objective C runtime. And in fact it is
generally considered desirable to change that code to use libffi
instead, in which case __builtin_apply will probably be deprecated and
removed. If you don't need to compile Objective C, I wouldn't worry
about __builtin_apply.
I am concerned about only C. If __builtin_apply is important only in
Objective C why is it that this test case is included in C test suites
?
If the outcome of the test cases involving __builtin_apply and
__builtin_apply_args doesnt matter for a C compiler is it proper to
include them in the C testsuites ?
They need to work in C in order to implement the Objective C runtime.
Besides, they are documented, so they should be tested.

Ian

Loading...