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

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



> We are trying to support ... 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.

Yes, i did understand that. But you are trying to do that by hacking gcc's m68k backend. I still think that's the wrong place to fix.


Richard Biener <richard.guenther@gmail.com> schrieb am 16:17 Mittwoch, 27.Januar 2016:


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: