[CLANG BUG] Generate ELF for aarch64-apple-iphoneos

Hi,

I’ve stumbled across something curious with the Relase_40 I have built here:

I tried to build for aarch64-apple-iphoneos, but ended up getting ELF objects

$ clang -target aarch64-apple-iphoneos -c tmp.ll -o tmp.o
warning: overriding the module target triple with aarch64-apple-iphoneos [-Woverride-module]
1 warning generated.
bin
$ file tmp.o
tmp.o: ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV), not stripped

The contents of tmp.ll seems irrelevant, the result can be reproduced with an empty file.

Result is the same with

clang version 4.0.0 (GitHub - llvm-mirror/clang: Mirror kept for legacy. Moved to https://github.com/llvm/llvm-project 559aa046fe3260d8640791f2249d7b0d458b5700) (http://llvm.org/git/llvm.git 3de71b0e7b7a3b5df49f05a4653d4b1ecb70bfab)
Target: x86_64-apple-darwin16.4.0
Thread model: posix

and

Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin16.4.0
Thread model: posix

The solution seems to be to use arm64-apple-ios as a target, aarch64-apple-ios however results in:
error: unknown target triple 'unknown-apple-macosx10.4.0', please use -triple or -arch

How can I obtain a list of supported target triples from clang?

Cheers,
Moritz

I tried to build for aarch64-apple-iphoneos, but ended up getting ELF objects

As you've discovered, "ios" is the way this is spelled. Triples are in
a bit of a murky area between implementation detail and public
interface.

Clang has to support the commonly used ones (arm-linux-gnueabihf,
x86_64-linux-gnu, ...). But LLVM uses finer distinctions to determine
how it should generate code; for example that first ARM triple might
go through to the backend as "thumbv7-linux-gnueabihf" indicating code
generation for ARMv7 in Thumb mode.

This isn't ideal, and there's very low-level movement towards
improving the situation. But it hasn't come up in a while.

The solution seems to be to use arm64-apple-ios as a target, aarch64-apple-ios however results in:

Darwin provides a limited set of named configurations rather than
using triples directly. The canonical way to compile for AArch64 there
is by specifying "-arch arm64" instead of -target.

How can I obtain a list of supported target triples from clang?

You can't really. There are too many variants with differing degrees of support.

Cheers.

Tim.

Hi Tim,

thanks for looking into this.

I tried to build for aarch64-apple-iphoneos, but ended up getting ELF objects

As you've discovered, "ios" is the way this is spelled. Triples are in
a bit of a murky area between implementation detail and public
interface.

Clang has to support the commonly used ones (arm-linux-gnueabihf,
x86_64-linux-gnu, ...). But LLVM uses finer distinctions to determine
how it should generate code; for example that first ARM triple might
go through to the backend as "thumbv7-linux-gnueabihf" indicating code
generation for ARMv7 in Thumb mode.

This isn't ideal, and there's very low-level movement towards
improving the situation. But it hasn't come up in a while.

What’s the recommended approach to be taken from llvms point of view?
with -arch and -march? How would I differentiate macosx, ios, watchos then?
What would I set for aarch64-unknown-linux-android instead of the target?

The solution seems to be to use arm64-apple-ios as a target, aarch64-apple-ios however results in:

Darwin provides a limited set of named configurations rather than
using triples directly. The canonical way to compile for AArch64 there
is by specifying "-arch arm64" instead of -target.

Is there some difference between aarch64 and arm64?

How can I obtain a list of supported target triples from clang?

You can't really. There are too many variants with differing degrees of support.

Thank you. That makes sense! Can I ask clang for the supported architectures then?

Cheers,
Moritz

What’s the recommended approach to be taken from llvms point of view?
with -arch and -march?

Well, -arch is used when Clang thinks it's targeting Darwin platforms,
and -march is used on ELF (they don't mix). Of course it gets messy
because each of those view what's being specified slightly
differently.

Roughly, Darwin thinks that -target covers the general Appleish
platform and how other command-line args should be interpreted, and
you should use -arch to specify the CPU type and the version-min
arguments to specify the OS. ELF thinks that all of those should be
covered by -target (and ignores -arch).

So if Clang didn't have any default, you might see this on Darwin:

    clang -target unknown-apple-darwin -arch arm64 -mios-version-min=10.0 ...

But for ELF:

    clang -target aarch64-linux-gnu ...

Of course, the Clang that comes with XCode knows it should default to
Darwin (as would any Clang built on macOS unless you specifically
changed it). So usually -target is omitted in the first line.

Finally, -march is used on ELF to select the sub-variant being
compiled for (e.g. v7, v8, v8.1 of the ARM architecture, or x86
variants).

How would I differentiate macosx, ios, watchos then?

You'd do this via -mios-version-min, -mwatchos-verison-min and
-mmacosx-version-min arguments, in addition to an appropriate -arch.

What would I set for aarch64-unknown-linux-android instead of the target?

That would be the -target option.

Darwin provides a limited set of named configurations rather than
using triples directly. The canonical way to compile for AArch64 there
is by specifying "-arch arm64" instead of -target.

Is there some difference between aarch64 and arm64?

Nope (or at least there shouldn't be). ARM decided that the official
name for their 64-bit operation mode would be AArch64 rather than the
more natural ARM64 (I heard rumours it was for trademark reasons, but
that's pure speculation). Projects and companies went along with this
to varying degrees, and Clang has to support both camps.

Thank you. That makes sense! Can I ask clang for the supported architectures then?

I'm afraid not. llc gives you that information with "-version", but
Clang doesn't. It wouldn't be a bad addition though (probably).

Cheers.

Tim.