This is the mail archive of the gcc-bugs@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]

ARM structure returns



Perhaps not a bug as such, but I wasn't expecting it, and couldn't find
it documented.  Sorry if it's been raised before.

With arm-elf-gcc, given the code:

        struct foo
        {
          int a;
          int b;
        };

        struct foo a (struct foo s);

        void b (struct foo *s)
        {
          *s = a (*s);
        }

The pointer to a's return value gets passed in r1 rather than r0.  r0
goes unused:

	mov	ip, sp
	stmfd	sp!, {r4, fp, ip, lr, pc}
	sub	fp, ip, #4
	mov	r4, r0                  ; r4 = s
	sub	sp, sp, #8
	ldmia	r4, {r2-r3}             ; r2,r3 = *s
	sub	r1, fp, #24             ; r1 = &temp
	bl	a
	sub	r3, fp, #16
	ldmdb	r3, {r2-r3}             ; copy temp to s
	stmia	r4, {r2-r3}
	ldmea	fp, {r4, fp, sp, pc}

Is this behaviour intentional?  If not, should it be changed, or would
that create unacceptable ABI incompatiblity?

If it is unintentional, the cause seems to be:

The ARM back-end defines STRUCT_VALUE to NULL, so the generic args code
treats the hidden argument like any other, using the FUNCTION_ARG
interface to find out where it should go.  But arm_init_cumulative_args
reads:

arm_init_cumulative_args (pcum, fntype, libname, indirect)
     CUMULATIVE_ARGS * pcum;
     tree fntype;
     rtx libname  ATTRIBUTE_UNUSED;
     int indirect ATTRIBUTE_UNUSED;
{
  /* On the ARM, the offset starts at 0.  */
  pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype))) ? 1 : 0);

So, when the function returns an aggregate, the first argument -- the
hidden one -- gets put in reg 1.  The first unhidden argument goes in
reg 2, and so on.

Richard


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