This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/69221] New: gcc on m68k miscompiles function type casts
- From: "slyfox at inbox dot ru" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sun, 10 Jan 2016 21:32:29 +0000
- Subject: [Bug c/69221] New: gcc on m68k miscompiles function type casts
- Auto-submitted: auto-generated
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.