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]
Other format: [Raw text]

[Bug c/69221] New: gcc on m68k miscompiles function type casts


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69221

            Bug ID: 69221
           Summary: gcc on m68k miscompiles function type casts
           Product: gcc
           Version: 5.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: slyfox at inbox dot ru
  Target Milestone: ---

Created attachment 37298
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=37298&action=edit
sample with broken ABI

This came up as a miscompilation of GHC:
    https://ghc.haskell.org/trac/ghc/ticket/11395

Consider the following small snippet:

    /* needed to introduce a symbol */
    extern void* f(); /* real prototype is 'int f(void);' */

    int g(void)
    {
        /* cast a symbol to known function type, returns 'int' */
        return 1 + ((int (*)(void))f)();
    }

    /* somewhere in other translation unit */
    int __f (void)
    {
        return 42;
    }

    /* just for comparison */
    void * __vf (void)
    {
        return (void*)42;
    }

$ m68k-unknown-linux-gnu-gcc -O2 -S demo1.c -fomit-frame-pointer
[ Also issues a warning:
  warning: function called through a non-compatible type
     return 1 + ((int (*)(void))f)();
                ^
]

generates the following assembly:

    g:
        jsr f
        move.l %a0,%d0 ; 'g' kills register 'd0', resould of called would-be
'f'
        addq.l #1,%d0
        rts

    __f:
        moveq #42,%d0
        rts

    __vf:
        move.w #42,%a0
        moveq #42,%d0
        rts

The idea here is 
    extern void* f();
line brings a .text symbol of yet unknown propotype.

Later *at .c file generation time) we get information about
symbol 'f' and cast it to known type:
    ((int (*)(void))f)();

But caller does not expect result to present in 'd0' data register, expects
'a0' address register.

[a note: GHC used to introduce unknown symbols in scope as
    extern void* f(void);
but that broke on PPC64 ELFv2 and we changed to less precise
    extern void* f();
]

Looks like GCC bug to ignore actual 'int (*)(void)' ABI of a symbol at call
site.

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