On Wed, Jan 27, 2016 at 7:17 AM, Richard Biener <richard.guent...@gmail.com> wrote: > On Wed, Jan 27, 2016 at 4:10 PM, Thorsten Otto <halg...@yahoo.de> wrote: >>> 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. > > We are trying to support > > t.c > --- > void *foo(); > > int bar() > { > return ((int (*)())foo) (); > }
Why can't ghc produce code like: int bar () { int (*foo1)() = foo; asm("":"+r"(foo1)); return foo1(); } Yes it no longer produces an direct function call but it might be better in the long run anyways. Thanks, Andrew > > t2.c > ----- > int foo () { return 0; } > > thus doing a direct call to a function with a (wrong) prototype via a function > pointer cast to the correct type and having a matching implementation of > that function elsewhere. > > I think that's reasonable and what GHC expects - declare "there is a function > foo defined, no idea what prototype yet", unfortunately C requires to specify > a return type. > > Richard. > >> >> Michael Karcher <deb...@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 >> >> >> >>