[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: RFC: Support non-standard extension (call via casted function pointer)



On Wed, Jan 27, 2016 at 4:10 PM, Thorsten Otto <halgara@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) ();
}

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 <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
>
>
>
>


Reply to: