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 y
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.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!
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.
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);
}
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.
...
It won't list all the triples, but
llvm-as < /dev/null | llc -mcpu=help
will at least list all the CPUs.
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