Discussion:
pcc violating "pcc struct return" ABI
Thorsten Glaser
2013-08-31 17:14:25 UTC
Permalink
I was wondering about a “ret 4” in asm inside MirBSD libc,
looked up the commit where it was introduced – see below –
then decided to see what the compilers (system, that’s GCC
for now, as well as pcc) really do.

This is about the following code:
https://www.mirbsd.org/cvs.cgi/src/lib/libc/arch/i386/stdlib/div.S?rev=HEAD

The RCS log entry in question (from an older repository) is:
----------------------------
revision 1.6
date: 2004/06/09 23:13:18; author: tg; state: Stab; lines: +3 -2;
conform to the ABI, except thanks to the Santa Cruz,
whatever they are named now, Caldera:


Functions Returning Structures or Unions

If a function returns a structure or union, then the caller provides space for the
return value and places its address on the stack as argument word zero. In effect,
this address becomes a `hidden'' first argument. Having the caller supply the
return object's space allows re-entrancy.

Structures and unions in this context have fixed sizes. The ABI does not
NOTE specify how to handle variable sized objects.

3-14 LOW-LEVEL SYSTEM INFORMATION

DRAFT COPY
March 19, 1997
File: abi_386/chap3 (Delta 44.6)
386:adm.book:sum

A function that returns a structure or union also sets %eax to the value of the
original address of the caller's area before it returns. Thus when the caller receives
control again, the address of the returned object resides in register %eax and can
be used to access the object. Both the calling and the called functions must
cooperate to pass the return value successfully:

The calling function must supply space for the return value and pass its
address in the stack frame;

The called function must use the address from the frame and copy the
return value to the object so supplied;

The called function must remove this address from the stack before return-
ing.
----------------------------

(Specifically the last paragraph about removing from the stack.)

This is what the compilers make out of an equivalent C function:

---------------------------------------------------------------->8
***@blau:~ $ mgcc -fpcc-struct-return -fhonour-copts -fno-builtin -S z.c && fgrep ret z.s
ret $4
***@blau:~ $ mgcc -fno-pcc-struct-return -fhonour-copts -fno-builtin -S z.c && fgrep ret z.s
ret
***@blau:~ $ rm z.s; pcc -S z.c && fgrep ret z.s
ret
***@blau:~ $ cat z.c
#include <stdlib.h>

ldiv_t
xldiv(long num, long denom)
{
ldiv_t rv;

rv.quot = num / denom;
rv.rem = num % denom;
return rv;
}
---------------------------------------------------------------->8

Interestingly enough, on MirBSD, GCC defaults to -fpcc-struct-return
with the idea behind it being, being compatible to pcc. Hah!

So, what to do? I can probably break the ABI in MirBSD relatively
easily if this is “by design” (“just” do a major shlib version bump,
which will allow me to do some more cleanup I had planned anyway,
except of course any hand-written ASM would need to be fixed).

If this is not a deliberate break in pcc I’d rather see it fixed
there, though.

bye,
//mirabilos
--
“It is inappropriate to require that a time represented as
seconds since the Epoch precisely represent the number of
seconds between the referenced time and the Epoch.”
-- IEEE Std 1003.1b-1993 (POSIX) Section B.2.2.2
Loading...