clang:如何列出支持的目标架构?

时间:2013-02-23 03:58:57

标签: clang llvm

目前我对ARM一般感兴趣,特别是iphone / android目标。但我只想更多地了解铿锵声,因为它在未来几年里会发挥重要作用。

我试过

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)

我知道clang有-triplet参数,但是如何为它列出所有可能的值? 我发现clang在交叉编译方面与gcc非常不同,在GCC世界中你应该为所有东西都有单独的二进制文件,比如PLATFORM_make或PLATFORM_ld(i * 86-pc-cygwin i * 86 - * - linux-gnu等{ {3}})

在clang世界中,它只有一个二进制文件(就像我在某些论坛上看到的那样)。但是如何获得支持的目标列表?如果我的目标不支持我的发行版(linux / windows / macos / whatever),我怎样才能获得支持更多平台的目标?

如果我是SVN最新的铿锵声:

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

我会获得大多数平台吗? 看起来Clang并没有立即考虑交叉编译,但由于它基于llvm,它理论上应该是非常交叉友好的?谢谢!

10 个答案:

答案 0 :(得分:34)

据我所知,没有命令行选项列出给定clang二进制文件支持哪些体系结构,甚至在其上运行strings也没有用。 Clang本质上只是一个C到LLVM的翻译器,它的LLVM本身就是处理生成实际机器代码的细节,所以Clang并没有太注意底层架构,这并不奇怪。

正如其他人已经指出的那样,您可以问llc它支持哪些架构。这不仅仅是因为这些LLVM组件可能没有安装,但由于搜索路径和打包系统的变幻莫测,您的llcclang二进制文件可能与同一版本不对应LLVM。

然而,为了论证,让我们说你自己编译了LLVM和Clang,或者你很高兴接受你的LLVM二进制文件就足够了:

  • llc --version将列出其支持的所有体系结构。默认情况下,它被编译为支持所有体系结构。您可能认为像ARM这样的单一架构可能有几种LLVM架构,例如常规ARM,Thumb和AArch64。这主要是为了实现方便,因为不同的执行模式具有非常不同的指令编码和语义。
  • 对于列出的每个体系结构,llc -march=ARCH -mattr=help将列出“可用CPU”和“可用功能”。 CPU通常只是设置默认功能集合的便捷方式。

但现在是坏消息。 Clang或LLVM中没有方便的三元组表可以转储,因为特定于体系结构的后端可以选择将三元组字符串解析为llvm::Triple对象(在include/llvm/ADT/Triple.h中定义)。换句话说,要转储所有可用的三元组需要解决停机问题。例如,请参阅llvm::ARM_MC::ParseARMTriple(...)解析字符串"generic"的特殊情况。

但最终,“三联”主要是向后兼容功能,使Clang成为GCC的直接替代品,所以除非你将Clang或LLVM移植到,否则你通常不需要太多关注它一个新的平台或架构。相反,您可能会发现llc -march=arm -mattr=help的输出并且对大量不同的ARM功能感到困惑,这对您的调查更有用。

祝你的研究好运!

答案 1 :(得分:30)

我正在使用Clang 3.3,我认为获得答案的最佳方法是阅读源代码。 在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
  };

并且在clang / lib / Driver / ToolChains.cpp中,有关于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);
}

答案 2 :(得分:14)

你可以做一个提示:如果你想找到一个特定的目标三元组,就是在该系统上安装llvm 然后再做一个

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

或者:

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

然后你知道如何在交叉编译时将其作为目标。

显然有很多目标,这里是一个列表,随意添加,社区维基风格:

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

这是docs列表无论如何(显然这是一个四倍[或五倍?]而不是这些天的三倍):

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.

并且您甚至可以微调指定超出此范围的目标cpu,尽管它使用基于三元组的目标cpu的合理默认值。

有时目标会“解决”到同一个目标,所以要查看目标实际上被视为:

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

答案 3 :(得分:10)

根据Jonathan Roelofs的演讲“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

Clang的未来版本可能会提供以下内容。它们被列为“建议”,但至少从v3.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 

答案 4 :(得分:5)

也可以尝试

> 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.
  ...

答案 5 :(得分:4)

从Clang 11(主干)开始,可以使用新添加的-print-targets标志来方便地打印受支持的目标体系结构列表:

$ 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

参考:LLVM PRLLVM commitClang 11 documentation

答案 6 :(得分:1)

它不会列出所有三元组,但

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

至少会列出所有的CPU。

答案 7 :(得分:1)

如果您对支持从源构建LLVM或Clang的目标(-DLLVM_TARGETS_TO_BUILD的值)感兴趣,请在源分发的llvm/lib/Target文件夹中查找子目录列表。自9.0.1版起:

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

答案 8 :(得分:0)

clang -march=dont-know empty.c

错误:未知的目标CPU“不知道”

注意:有效的目标CPU值是: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,巴塞罗那,btver1,btver2,bdver1,bdver2,bdver3,bdver4,znver1,znver2,x86-64

答案 9 :(得分:0)

只有第一个(CPU架构)需要精确,其他参数的处理方式巧妙而复杂,你可以使用“clang++ ... --verbose ...”来查看处理结果,例如:

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

一般除了第一个参数以外的参数只有在正确的时候才会生效(经过三重处理,错误的可以巧妙的改正),比如“windows”会影响代码:

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

此方法被Clang/LLVM中的其他代码用来影响编译结果,只有当参数为“windows”时才返回true,如果是“foo”等任何其他东西则返回false。