GHC FFI Return Type Bug
Carl R. Witty
cwitty@newtonlabs.com
07 Aug 2001 11:13:43 -0700
"Sigbjorn Finne" <sof@galconn.com> writes:
> "Julian Seward (Intl Vendor)" <v-julsew@microsoft.com> writes:
> >
> > Hmm, we're looking at this. However, I don't really know what
> > C is or is not supposed to do here. Given
> >
> > char fooble ( ... )
> > {
> > return 'z';
> > }
> >
> > on an x86, 'z' will be returned at the lowest 8 bits in %eax.
> > What I don't know is, is the C compiler obliged to clear the
> > upper 24 bits of %eax, or does that onus fall on the callee?
>
> Yes, the callee is required to narrow <expr> in 'return <expr>;' to
> fit that of the specified return type -- see 9.8 of Harbison and
> Steele. So, a C compiler that cause f() to return 0x7fffffff for
> the following,
>
> unsigned char g()
> {
> return 0x7fffffff;
> }
>
> unsigned int f()
> {
> return g();
> }
>
> is in the wrong. [Notice that narrowing for signed integral types
> is undefined in ISO C, but most current-day compilers implement
> such narrowing ops the same way, i.e., by masking off excess bits.]
It's certainly true that an ISO C compiler on a typical machine must
return 255 from f() (on an atypical machine, it's possible to have
unsigned char be a 32-bit type). However, this is essentially
unrelated to the question of whether the x86 ABI allows g() to return
a value in %eax that has the upper 3 bytes non-zero.
When I compile the following file:
-------------------- abitest.c --------------------
unsigned int g_val;
unsigned char g()
{
return g_val;
}
unsigned int f()
{
return g();
}
---------------------------------------------------
with the command
gcc -Wall -O2 -fomit-frame-pointer -S abitest.c
I get the output:
-------------------- abitest.S --------------------
.file "abitest.c"
.version "01.01"
gcc2_compiled.:
.text
.align 16
.globl g
.type g,@function
g:
movzbl g_val,%eax
ret
.Lfe1:
.size g,.Lfe1-g
.align 16
.globl f
.type f,@function
f:
call g
andl $255,%eax
ret
.Lfe2:
.size f,.Lfe2-f
.comm g_val,4,4
.ident "GCC: (GNU) 2.7.2.3"
---------------------------------------------------
You can see that the code for f is:
call g
andl $255,%eax
ret
So gcc believes that a function which returns a value of type unsigned
char is not responsible for clearing the high 3 bytes of %eax.
Carl Witty