> This frobbing of a pointer return value in %d0 only happens in the
> outgoing case already now, because in the non-outgoing case,
> m68k_function_value is (unverified claim) only called from expand_call,
> which replaces the PARALLEL rtx by the first list element, i.e. %a0. (or
> %d0 if !POINTER_TYPE_P(valtype) after my patch).
Wether pointer values are returned in d0 or a0 only depend on the ABI, not the machine type.
BTW what does ghc expect on x86-64? The ABIs on linux and e.g Win64 are also quite different with respect to which registers are used to pass/ parameters.
And in the m68k-case, you will have similar problems with double values. Depending on the ABI, they are returned in either fp0 or d0/d1.
You can try the following example:
extern void *test1(void);
extern char a[100];
__attribute__((noinline)) void *test2(void)
{
return a;
}
extern void *p1;
extern void *p2;
void test3(void)
{
p1 = test1();
p2 = test2();
}
extern double test4(void);
extern double d;
__attribute__((noinline)) double test5(void)
{
return d;
}
extern double d1;
extern double d2;
void test6(void)
{
d1 = test4();
d2 = test5();
}
m68k-atari-linux-gcc produces the following code:
.globl test2
.type test2, @function
test2:
lea a,%a0
move.l %a0,%d0
rts
.size test2, .-test2
.align 2
.globl test3
.type test3, @function
test3:
jsr test1
move.l %a0,p1
jsr test2
move.l %a0,p2
rts
.size test3, .-test3
.align 2
.globl test5
.type test5, @function
test5:
fmove.d d,%fp0
rts
.size test5, .-test5
.align 2
.globl test6
.type test6, @function
test6:
jsr test4
fmove.d %fp0,d1
jsr test5
fmove.d %fp0,d2
rts
You see that test2() puts the return value in both a0 and d0, and that test3() expects the return value in a0 in both calls of test1() and test2().
The same code compiled with m68k-atari-mint-gcc produces:
.globl _test2
_test2:
move.l #_a,%d0
rts
.even
.globl _test3
_test3:
jsr _test1
move.l %d0,_p1
jsr _test2
move.l %d0,_p2
rts
.even
.globl _test5
_test5:
move.l _d,%a1
move.l _d+4,%a0
move.l %a1,%d0
move.l %a0,%d1
rts
.even
.globl _test6
_test6:
jsr _test4
move.l %d0,_d1
move.l %d1,_d1+4
jsr _test5
move.l %d0,_d2
move.l %d1,_d2+4
rts
In this case, test2() puts the return value only in d0, and test3() expects the return value in d0 in both calls of test1() and test2().
(BTW strange code that is produced in test5() to return the double in d0/d1; why is it loaded into address registers first?)
Conclusion: IMHO, If ghc fetches the return value from the wrong register, then ghc is broken, not gcc.
Michael Karcher <debian@mkarcher.dialup.fu-berlin.de> schrieb am 20:21 Dienstag, 26.Januar 2016:
On 26.01.2016 16:40, Richard Biener wrote:
> No, the patch looks somewhat broken to me. A complete fix would replace
> the target macro FUNCTION_VALUE implementation by implementing the
> function_value hook instead (to also receive the function type called if no
> decl is available and to be able to distinguish caller vs. callee).
>
> I also don't see how changing the called function code will fix anything.
I definitely agree that the approach to move from the FUNCTION_VALUE
macro to the function_value hook is the most clean way to do it. If
there is a consensus among the gcc developers that a patch to support
this non-conforming code should be applied, I would be willing to
prepare a patch as suggested.
The current patch does not change the called code at all. The only time
at which my suggested patch changes gcc behaviour is if a function
declaration is given, that declaration has a pointer type as return
type, but valtype is no pointer type. This (unverified claim) can not
happen in the callee, as the valtype when compiling the return statement
or assembling the epilogue is taken from the function declaration.
> In fact the frobbing of the return value into %d0 should only happen
> if the 'outgoing' arg is true (in the hook implementation) and in the
> 'outgoing' == false case simply disregard 'func' and always use
> 'valtype'.
This frobbing of a pointer return value in %d0 only happens in the
outgoing case already now, because in the non-outgoing case,
m68k_function_value is (unverified claim) only called from expand_call,
which replaces the PARALLEL rtx by the first list element, i.e. %a0. (or
%d0 if !POINTER_TYPE_P(valtype) after my patch).
> So, hookize and change to
>
> if (outgoing && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (func))))
> ...
> else if (POINTER_TYPE_P (valtype))
> ...
> else
> ...
Looks good and clean to me, but I expect my patch to have the same effect.
Regards,
Michael Karcher