현재 저는 ARM, 특히 아이폰 / 안드로이드 타겟에 관심이 있습니다. 그러나 나는 clang에 대해 더 많이 알고 싶습니다. 앞으로 몇 년 동안 중요한 역할을 할 것 같기 때문입니다.
나는 시도했다
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 등)와 같은 모든 것에 대해 별도의 바이너리가 있어야합니다. http : //git.savannah.gnu.org/cgit/libtool.git/tree/doc/PLATFORMS )
clang 세계에서는 (일부 포럼에서 읽은 것처럼) 단 하나의 바이너리입니다. 하지만 지원되는 대상 목록은 어떻게 얻습니까? 그리고 내 대상이 내 배포판 (linux / windows / macos / whatever)에서 지원되지 않는 경우 더 많은 플랫폼을 지원하는 대상을 어떻게 얻을 수 있습니까?
다음과 같이 최신 clang을 SVN하면
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
대부분의 플랫폼을 얻을 수 있습니까? Clang이 바로 크로스 컴파일을 염두에두고 빌드되지 않은 것처럼 보이지만 llvm 기반이기 때문에 이론상 매우 크로스 친화적이어야합니까? 감사합니다!
답변
내가 말할 수있는 한, 주어진 clang
바이너리가 지원 하는 아키텍처를 나열하는 명령 줄 옵션이 없으며 심지어 실행 strings
하는 것도 실제로 도움이되지 않습니다. Clang은 본질적으로 C to LLVM 번역기이며 실제 기계 코드 생성의 핵심을 다루는 것은 LLVM 자체이므로 Clang이 기본 아키텍처에 많은 관심을 기울이지 않는다는 것이 전혀 놀라운 일이 아닙니다.
다른 사람들이 이미 언급했듯이 llc
지원하는 아키텍처를 물어볼 수 있습니다 . 이것은 이러한 LLVM 구성 요소가 설치되지 않았기 때문이 아니라 검색 경로 및 패키징 시스템의 변동으로 인해 사용자 llc
와 clang
바이너리가 동일한 버전의 LLVM에 해당하지 않을 수 있습니다.
그러나 논쟁을 위해 LLVM과 Clang을 모두 직접 컴파일했거나 LLVM 바이너리를 충분히 만족스럽게 받아 들였다고 가정 해 보겠습니다.
llc --version
지원하는 모든 아키텍처 목록을 제공합니다. 기본적으로 모든 아키텍처를 지원하도록 컴파일됩니다. ARM과 같은 단일 아키텍처로 생각할 수있는 것은 일반 ARM, Thumb 및 AArch64와 같은 여러 LLVM 아키텍처가있을 수 있습니다. 다른 실행 모드는 명령어 인코딩과 의미가 매우 다르기 때문에 이는 주로 구현 편의를위한 것입니다.- 나열된 각 아키텍처에 대해
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 기능의 방대한 배열에서 출력을 찾을 수있을 것입니다 .
연구에 행운을 빕니다!
답변
저는 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에 대한 sth가 있습니다.
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);
}
답변
할 수있는 한 가지 힌트 : 특정 타겟 트리플을 찾으려고하는 경우 해당 시스템에 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
어쨌든 문서 목록 은 다음과 같습니다 (요즘에는 3 배가 아닌 4 배 [또는 5 배?]).
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
답변
이 강연에서 Jonathan Roelofs에 따르면 “Clang은 어떤 타겟을 지원하나요?” :
$ 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은 다음을 제공 할 수 있습니다. 적어도 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
답변
또한 시도
> 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.
...
답변
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 PR , LLVM commit , Clang 11 documentation .
답변
모든 트리플을 나열하지는 않지만
llvm-as < /dev/null | llc -mcpu=help
최소한 모든 CPU를 나열합니다.