Hack for FreeBSD ABI support

Currently Clang uses the DOS ABI (used by Linux) by default on x86 and the BSD ABI if the target triple contains 'darwin'. This little hack selects the correct ABI for FreeBSD. It's almost certainly not the best way of doing it, so feel free to select some other way.

David

clang.diff (690 Bytes)

I think it's fine as-is for the moment, assuming it's correct.

-Eli

I don't understand this patch; Darwin doesn't use the "BSD" ABI for
x86-32, it uses the crazy Darwin ABI which happens to match what gcc
first did when Darwin switched to Intel (and as evolved slightly by
time, I imagine). I'm pretty sure this is not the ABI that is used on
FreeBSD (especially since we haven't already heard about it from the
FreeBSD folks).

What was the actual problem you were running into?

- Daniel

Functions returning structures like NSPoint (two floats) work with this patch applied, but corrupt the stack without it. I've attached a simple test which demonstrates the problem (compile one of these with clang and the other with the system compiler to see the result) - it uses Objective-C, but the same test with pure C functions fails in the same way. I changed the test to ObjC to make sure that was fixed too - I was running into problems when every GNUstep app I tried crashed when I had Foundation compiled with clang and AppKit compiled with GCC because a call to an NSAffinePoint method was corrupting the stack.

There may be some differences between Darwin and FreeBSD (in particular in vector handling, which I didn't test), but with clang using the Darwin ABI I have programs compiled with Clang linking against AppKit compiled with gcc, Foundation compiled with Clang and other frameworks compiled with gcc and working without issue.

David

from.m (247 Bytes)

to.m (270 Bytes)

Hello, Everyone

There may be some differences between Darwin and FreeBSD (in particular in
vector handling, which I didn't test), but with clang using the Darwin ABI I
have programs compiled with Clang linking against AppKit compiled with gcc,
Foundation compiled with Clang and other frameworks compiled with gcc and
working without issue.

That's rather strange since freebsd folks definitely test the normal
ELF ABI and never complained about this :slight_smile: The only difference between
linux / freebsd found in gcc sources is DEFAULT_PCC_STRUCT_RETURN
define, which is set to 1 on linux and 0 on bsd. The description is:

@defmac DEFAULT_PCC_STRUCT_RETURN
Define this macro to be 1 if all structure and union return values must be
in memory. Since this results in slower code, this should be defined
only if needed for compatibility with other compilers or with an ABI@.
If you define this macro to be 0, then the conventions used for structure
and union return values are decided by the @code{TARGET_RETURN_IN_MEMORY}
target hook.

If not defined, this defaults to the value 1.
@end defmac

So, BSD definitely does not use Darwin ABI (and darwin does not use
BSD ABI :slight_smile: ). The hook TARGET_RETURN_IN_MEMORY can be found in
gcc/config/i386.c under the name ix86_return_memory(). The single use
of the mentioned flag (pcc_struct_return) is in
gcc/function.c:aggregate_value_p()

Hopefully this will provide enough information for proper implementation

Note that by "ABI" here only includes the calling convention, and that
makes it sound like FreeBSD is a lot closer to the Darwin calling
convention than the Linux one...

-Eli

Hello, Eli

Note that by "ABI" here only includes the calling convention, and that
makes it sound like FreeBSD is a lot closer to the Darwin calling
convention than the Linux one...

But vector stuff is purely linux, so I'd say - "something in the middle" :slight_smile:

The attached patch is a bit less of an hack. It changes the isDarwin flag to specify whether we should use the Darwin calling convention for vectors (I don't think this calling convention is used elsewhere, but it might be...) and adds a second flag to specify whether small structures are returned in registers or on the stack. This is set to true for FreeBSD and Darwin and no for other operating systems (I've no idea what it should be for Net/OpenBSD; someone with access to these operating systems on x86 should run my test program and see if it breaks with current clang compiling one file and gcc compiling the others). Since DragonFly is a fork of Free, I believe it should also have this flag set, but (again) I don't have a machine I can test this on. I'm a bit surprised no one running FreeBSD or DragonFly BSD has encountered this problem before... Apparently it's also the default on MinGW, so maybe this test should be inverted; it seems that only GNU/Linux defaults to returning these structures on the stack, so possibly we should just test for "linux" in the triple and clear the flag in this case?

This second flag should, in future, be overridden by the -fpcc-struct-return / -freg-struct-return flags. These are used by GCC to override the host platform calling convention, so they're not widely used (although there's a kernel by some Finnish guy which apparently uses -freg-struct-return).

With this applied, I believe we get the correct calling convention for everything on FreeBSD. Please let me know if it breaks any other platforms before I commit (and if anyone wants to let me know what the correct values are for other *BSDs, I'll integrate those at the same time).

David

clang.diff (2.39 KB)

you can of course derive this information from looking at the gcc
config dir, but the short answer is

beos-elf.h:#define DEFAULT_PCC_STRUCT_RETURN 1
linux.h:#define DEFAULT_PCC_STRUCT_RETURN 1
lynx.h:#define DEFAULT_PCC_STRUCT_RETURN 1
nto.h:#define DEFAULT_PCC_STRUCT_RETURN 1
netbsd-elf.h:#define DEFAULT_PCC_STRUCT_RETURN 1

cygming.h:#define DEFAULT_PCC_STRUCT_RETURN 0
darwin.h:#define DEFAULT_PCC_STRUCT_RETURN 0
freebsd.h:#define DEFAULT_PCC_STRUCT_RETURN 0
netware.h:#define DEFAULT_PCC_STRUCT_RETURN 0
openbsd.h:#define DEFAULT_PCC_STRUCT_RETURN 0

for non x86 archs it differs.

Hello, Jonathan

you can of course derive this information from looking at the gcc
config dir, but the short answer is

That's exactly what was written in my e-mail below :slight_smile:

Thanks, I've updated the code so that it now sets the second flag if the target triple contains one of cygwin, mingw, netware,freebsd, openbsd, or darwin and set the first flag if it contains darwin.

Anyone want to object before I commit?

David

you can of course derive this information from looking at the gcc
config dir, but the short answer is

beos-elf.h:#define DEFAULT_PCC_STRUCT_RETURN 1
linux.h:#define DEFAULT_PCC_STRUCT_RETURN 1
lynx.h:#define DEFAULT_PCC_STRUCT_RETURN 1
nto.h:#define DEFAULT_PCC_STRUCT_RETURN 1
netbsd-elf.h:#define DEFAULT_PCC_STRUCT_RETURN 1

cygming.h:#define DEFAULT_PCC_STRUCT_RETURN 0
darwin.h:#define DEFAULT_PCC_STRUCT_RETURN 0
freebsd.h:#define DEFAULT_PCC_STRUCT_RETURN 0
netware.h:#define DEFAULT_PCC_STRUCT_RETURN 0
openbsd.h:#define DEFAULT_PCC_STRUCT_RETURN 0

Thanks, I've updated the code so that it now sets the second flag if
the target triple contains one of cygwin, mingw, netware,freebsd,
openbsd, or darwin and set the first flag if it contains darwin.

Anyone want to object before I commit?

There is a typo (isPPCStructReturnABI -> isPCCStructReturnABI).

I don't know enough of the history to know what kinds of variations to
expect, but it would be good to do some substantial testing (e.g.,
ABITest and the relevant parts of the gcc test suite) to verify that
the results match gcc.

For example, shouldReturnTypeInRegister has some more special
conditions for vectors, and the "single element" struct rules are
quirky enough that I assumed they were a Darwin oddity.

- Daniel