114
votes

Currently I am interested in ARM in general and specifically iphone/android targets. But I just want to know more about clang, since it feels to play important role in the years to come.

I tried

clang -cc1 --help|grep -i list
clang -cc1 --help|grep arch|grep -v search
clang -cc1 --help|grep target

 -triple <value>         Specify target triple (e.g. i686-apple-darwin9)

I know clang has -triplet parameter, but how can I list all possible values for it? I found that clang is very different to gcc in respect to cross compiling, in GCC world you should have separate binary for everything, like PLATFORM_make or PLATFORM_ld (i*86-pc-cygwin i*86-*-linux-gnu etc. http://git.savannah.gnu.org/cgit/libtool.git/tree/doc/PLATFORMS)

in clang world, it's only one binary (as I read on some forums). But how do I get the list of supported targets? And if my target it not supported on my distro(linux/windows/macos/whatever) how can I get the one that supports more platform?

if I SVN latest clang like this:

svn co http://llvm.org/svn/llvm-project/cfe/trunk clang

will I get most of platforms? It looks like Clang was not built with cross compiling in mind right away, but since it's llvm based it should be very cross-friendly in theory? thank you!

10
not a complete answer but llc --version will give you the targetsold_timer
I think you'll have to look at the source to see the triples. And as I understand it a default build of clang will include basic support for cross compiling. Basic support only turns code into object files (as long as the integrated assembler supports the triple, otherwise you'll have to take .s files). You'll have to supply headers, libraries, a linker (until lld works, anyway), etc.bames53
Although the default installation only has clang and clang++ executables, like other platforms you can create copies or hardlinks of them with the triples and quads encoded in the names. clang++ and clang are actually just copies of each other it checks the name of the executable to see how to process input.LB--

10 Answers

65
votes

So far as I can tell, there is no command-line option to list which architectures a given clang binary supports, and even running strings on it doesn't really help. Clang is essentially just a C to LLVM translator, and it's LLVM itself that deals with the nitty-gritty of generating actual machine code, so it's not entirely surprising that Clang isn't paying much attention to the underlying architecture.

As others have already noted, you can ask llc which architectures it supports. This isn't all that helpful not just because these LLVM components might not be installed, but because of the vagaries of search paths and packaging systems, your llc and clang binaries may not correspond to the same version of LLVM.

However, for the sake of argument, let's say that you compiled both LLVM and Clang yourself or that you're otherwise happy to accept your LLVM binaries as good enough:

  • llc --version will give a list of all architectures it supports. By default, it is compiled to support all architectures. What you may think of as a single architecture such as ARM may have several LLVM architectures such as regular ARM, Thumb and AArch64. This is mainly for implementation convenience because the different execution modes have very different instruction encodings and semantics.
  • For each of the architectures listed, llc -march=ARCH -mattr=help will list "available CPUs" and "available features". The CPUs are generally just a convenient way of setting a default collection of features.

But now for the bad news. There is no convenient table of triples in Clang or LLVM that can be dumped, because the architecture-specific backends have the option of parsing the triple string into an llvm::Triple object (defined in include/llvm/ADT/Triple.h). In other words, to dump all available triples requires solving the Halting Problem. See, for example, llvm::ARM_MC::ParseARMTriple(...) which special-cases parsing the string "generic".

Ultimately, though, the "triple" is mostly a backwards-compatibility feature to make Clang a drop-in replacement for GCC, so you generally don't need to pay much attention to it unless you are porting Clang or LLVM to a new platform or architecture. Instead, you will probably find the output of llc -march=arm -mattr=help and boggling at the huge array of different ARM features to be more useful in your investigations.

Good luck with your research!

38
votes

I am using Clang 3.3, I think the best way to get the answer is reading the source code. in llvm/ADT/Triple.h (http://llvm.org/doxygen/Triple_8h_source.html):

  enum ArchType {
    UnknownArch,

    arm,     // ARM: arm, armv.*, xscale
    aarch64, // AArch64: aarch64
    hexagon, // Hexagon: hexagon
    mips,    // MIPS: mips, mipsallegrex
    mipsel,  // MIPSEL: mipsel, mipsallegrexel
    mips64,  // MIPS64: mips64
    mips64el,// MIPS64EL: mips64el
    msp430,  // MSP430: msp430
    ppc,     // PPC: powerpc
    ppc64,   // PPC64: powerpc64, ppu
    r600,    // R600: AMD GPUs HD2XXX - HD6XXX
    sparc,   // Sparc: sparc
    sparcv9, // Sparcv9: Sparcv9
    systemz, // SystemZ: s390x
    tce,     // TCE (http://tce.cs.tut.fi/): tce
    thumb,   // Thumb: thumb, thumbv.*
    x86,     // X86: i[3-9]86
    x86_64,  // X86-64: amd64, x86_64
    xcore,   // XCore: xcore
    mblaze,  // MBlaze: mblaze
    nvptx,   // NVPTX: 32-bit
    nvptx64, // NVPTX: 64-bit
    le32,    // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten)
    amdil,   // amdil: amd IL
    spir,    // SPIR: standard portable IR for OpenCL 32-bit version
    spir64   // SPIR: standard portable IR for OpenCL 64-bit version
  };

and in clang/lib/Driver/ToolChains.cpp , there is sth about arm.

static const char *GetArmArchForMArch(StringRef Value) {
  return llvm::StringSwitch<const char*>(Value)
    .Case("armv6k", "armv6")
    .Case("armv6m", "armv6m")
    .Case("armv5tej", "armv5")
    .Case("xscale", "xscale")
    .Case("armv4t", "armv4t")
    .Case("armv7", "armv7")
    .Cases("armv7a", "armv7-a", "armv7")
    .Cases("armv7r", "armv7-r", "armv7")
    .Cases("armv7em", "armv7e-m", "armv7em")
    .Cases("armv7f", "armv7-f", "armv7f")
    .Cases("armv7k", "armv7-k", "armv7k")
    .Cases("armv7m", "armv7-m", "armv7m")
    .Cases("armv7s", "armv7-s", "armv7s")
    .Default(0);
}

static const char *GetArmArchForMCpu(StringRef Value) {
  return llvm::StringSwitch<const char *>(Value)
    .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "arm926ej-s","armv5")
    .Cases("arm10e", "arm10tdmi", "armv5")
    .Cases("arm1020t", "arm1020e", "arm1022e", "arm1026ej-s", "armv5")
    .Case("xscale", "xscale")
    .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "arm1176jzf-s", "armv6")
    .Case("cortex-m0", "armv6m")
    .Cases("cortex-a8", "cortex-r4", "cortex-a9", "cortex-a15", "armv7")
    .Case("cortex-a9-mp", "armv7f")
    .Case("cortex-m3", "armv7m")
    .Case("cortex-m4", "armv7em")
    .Case("swift", "armv7s")
    .Default(0);
}
21
votes

One hint you can do: if you're trying to find a particular target triple, is to install llvm on that system then do a

$ llc --version | grep Default
  Default target: x86_64-apple-darwin16.1.0

or alternatively:

$ llvm-config --host-target
x86_64-apple-darwin16.0.0
or
$ clang -v 2>&1 | grep Target
Target: x86_64-apple-darwin16.1.0

Then you know how to target it when cross compiling anyway.

Apparently there are "lots" of targets out there, here's a list, feel free to add to it, community wiki style:

arm-none-eabi
armv7a-none-eabi
arm-linux-gnueabihf 
arm-none-linux-gnueabi
i386-pc-linux-gnu 
x86_64-apple-darwin10
i686-w64-windows-gnu # same as i686-w64-mingw32
x86_64-pc-linux-gnu # from ubuntu 64 bit
x86_64-unknown-windows-cygnus # cygwin 64-bit
x86_64-w64-windows-gnu # same as x86_64-w64-mingw32
i686-pc-windows-gnu # MSVC
x86_64-pc-windows-gnu # MSVC 64-BIT

Here's what the docs list anyway (apparently it's a quadruple [or quintuple?] instead of a triple these days):

The triple has the general format <arch><sub>-<vendor>-<sys>-<abi>, where:
arch = x86, arm, thumb, mips, etc.
sub = for ex. on ARM: v5, v6m, v7a, v7m, etc.
vendor = pc, apple, nvidia, ibm, etc.
sys = none, linux, win32, darwin, cuda, etc.
abi = eabi, gnu, android, macho, elf, etc.

and you can even fine tune specify a target cpu beyond this, though it uses a sensible default for the target cpu based on the triple.

Sometimes targets "resolve" to the same thing, so to see what a target is actually treated as:

 $ clang -target x86_64-w64-mingw32 -v 2>&1 | grep Target
 Target: x86_64-w64-windows-gnu
14
votes

According to Jonathan Roelofs in this talk “Which targets does Clang support?”:

$ llc --version
LLVM (http://llvm.org/):
  LLVM version 3.6.0
  Optimized build with assertions.
  Built Apr  2 2015 (01:25:22).
  Default target: x86_64-apple-darwin12.6.0
  Host CPU: corei7-avx

  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_be - AArch64 (big endian)
    amdgcn     - AMD GCN GPUs
    arm        - ARM
    arm64      - ARM64 (little endian)
    armeb      - ARM (big endian)
    cpp        - C++ backend
    hexagon    - Hexagon
    mips       - Mips
    mips64     - Mips64 [experimental]
    mips64el   - Mips64el [experimental]
    mipsel     - Mipsel
    msp430     - MSP430 [experimental]
    nvptx      - NVIDIA PTX 32-bit
    nvptx64    - NVIDIA PTX 64-bit
    ppc32      - PowerPC 32
    ppc64      - PowerPC 64
    ppc64le    - PowerPC 64 LE
    r600       - AMD GPUs HD2XXX-HD6XXX
    sparc      - Sparc
    sparcv9    - Sparc V9
    systemz    - SystemZ
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64
    xcore      - XCore

Future versions of Clang may provide the following. They are listed as "proposed" though not yet available at least as of v 3.9.0:

$ clang -target <target_from_list_above> --print-multi-libs
$ clang -print-supported-archs
$ clang -march x86 -print-supported-systems 
$ clang -march x86 -print-available-systems 
9
votes

Starting Clang 11 (trunk), the list of supported target architectures could be handily printed using the newly added -print-targets flag:

$ clang-11 -print-targets
  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    amdgcn     - AMD GCN GPUs
    arm        - ARM
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    armeb      - ARM (big endian)
    avr        - Atmel AVR Microcontroller
    bpf        - BPF (host endian)
    bpfeb      - BPF (big endian)
    bpfel      - BPF (little endian)
    hexagon    - Hexagon
    lanai      - Lanai
    mips       - MIPS (32-bit big endian)
    mips64     - MIPS (64-bit big endian)
    mips64el   - MIPS (64-bit little endian)
    mipsel     - MIPS (32-bit little endian)
    msp430     - MSP430 [experimental]
    nvptx      - NVIDIA PTX 32-bit
    nvptx64    - NVIDIA PTX 64-bit
    ppc32      - PowerPC 32
    ppc64      - PowerPC 64
    ppc64le    - PowerPC 64 LE
    r600       - AMD GPUs HD2XXX-HD6XXX
    riscv32    - 32-bit RISC-V
    riscv64    - 64-bit RISC-V
    sparc      - Sparc
    sparcel    - Sparc LE
    sparcv9    - Sparc V9
    systemz    - SystemZ
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    wasm32     - WebAssembly 32-bit
    wasm64     - WebAssembly 64-bit
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64
    xcore      - XCore

References: LLVM PR, LLVM commit, Clang 11 documentation.

7
votes

Also try

> llc -mattr=help

Available CPUs for this target:

  amdfam10      - Select the amdfam10 processor.
  athlon        - Select the athlon processor.
  athlon-4      - Select the athlon-4 processor.
  athlon-fx     - Select the athlon-fx processor.
  athlon-mp     - Select the athlon-mp processor.
  athlon-tbird  - Select the athlon-tbird processor.
  athlon-xp     - Select the athlon-xp processor.
  athlon64      - Select the athlon64 processor.
  athlon64-sse3 - Select the athlon64-sse3 processor.
  atom          - Select the atom processor.
  ...
Available features for this target:

  16bit-mode           - 16-bit mode (i8086).
  32bit-mode           - 32-bit mode (80386).
  3dnow                - Enable 3DNow! instructions.
  3dnowa               - Enable 3DNow! Athlon instructions.
  64bit                - Support 64-bit instructions.
  64bit-mode           - 64-bit mode (x86_64).
  adx                  - Support ADX instructions.
  ...
3
votes

It won't list all the triples, but

llvm-as < /dev/null | llc -mcpu=help

will at least list all the CPUs.

2
votes

In case you are interested in which targets are supported for building LLVM or Clang from source (the values for -DLLVM_TARGETS_TO_BUILD), look for the list of subdirectories in llvm/lib/Target folder in source distribution. As of 9.0.1 there are:

AArch64
AMDGPU
ARC
ARM
AVR
BPF
Hexagon
Lanai
MSP430
Mips
NVPTX
PowerPC
RISCV
Sparc
SystemZ
WebAssembly
X86
0
votes

clang -march=dont-know empty.c

error: unknown target CPU 'dont-know'

note: valid target CPU values are: nocona, core2, penryn, bonnell, atom, silvermont, slm, goldmont, goldmont-plus, tremont, nehalem, corei7, westmere, sandybridge, corei7-avx, ivybridge, core-avx-i, haswell, core-avx2, broadwell, skylake, skylake-avx512, skx, cascadelake, cooperlake, cannonlake, icelake-client, icelake-server, tigerlake, knl, knm, k8, athlon64, athlon-fx, opteron, k8-sse3, athlon64-sse3, opteron-sse3, amdfam10, barcelona, btver1, btver2, bdver1, bdver2, bdver3, bdver4, znver1, znver2, x86-64

0
votes

Only the first one (CPU architecture) need to be exact, other parameters are processed in a smart and complex way, you can use "clang++ ... --verbose ..." to see the processed result, for example:

Command Line Input      After triple processing
x86_64                  x86_64
x86_64-foo              x86_64-foo
x86_64-windows          x86_64-unknown-windows-msvc19.28.29335
x86_64-windows-bar      x86_64-unknown-windows-msvc19.28.29335
x86_64-foo-windows-bar  x86_64-foo-windows-msvc19.28.29335
x86_64-foo-bar-foobar   x86_64-foo-bar-foobar

Commonly the parameters except the first one will only have effect when they are right (after the triple proceesing process which may make a wrong one right smartly), for example, "windows" will effect the code:

/// Tests whether the OS is Windows.
bool isOSWindows() const {
    return getOS() == Triple::Win32;
}

This method is used by other code in Clang/LLVM to affect the compiled result, it only return true when the parameter is "windows" and will return false if it is any other thing such as "foo".