LLVMの構造
いままでのコンパイラの構造
いままでのコンパイラは、以下の手順でプログラムをコンパイルしてアプリケーションを作成します。
- ソースコード (sample.c)
- コンパイラ
- アセンブラソースコード (sample.s)
- アセンブラ
- リロケータブルオブジェクト (sample.o)
- リンキングローダー
- 実行可能なプログラム (a.out)
コンパイラ | プログラミング言語をアセンブラ言語にコンパイルするコンパイラ(字句、構文解析/最適化をおこなう)。プログラミング言語ごとに必要。CPUの種類ごとに必要。 |
---|---|
アセンブラ | アセンブラ言語をリロケータブルオブジェクトに変換するアセンブラ。CPUの種類ごとに必要。 |
リンキングローダー(リンカ) | リロケータブルオブジェクトやライブラリーを実行可能なコマンドに変換するリンカ。OSの種類ごとに必要(ちょっと違うがこんなイメージ)。 |
従来のコンパイラの問題点
- プログラミング言語ごとにコンパイラが必要
- CPUの種類ごとにコンパイラが必要
- 言語によってパフォーマンスが異なる
LLVMの構造
LLVMは、コンパイラの部分をもう少し細分化した。
- ソースコード (sample.c)
- コンパイラ(フロントエンド)
- 中間コード(LLVM IR)
- LLVM
- アセンブラソースコード (sample.s)
- アセンブラ(バックエンド)
- リロケータブルオブジェクト (sample.o)
- リンキングローダー(バックエンド)
- 実行可能なプログラム (a.out)
コンパイラ(フロントエンド) | プログラミング言語を中間言語にコンパイルするコンパイラ(字句、構文解析を行い中間言語に変換するトランスレーター的なもの)。プログラミング言語ごとに必要。 |
---|---|
LLVM | 中間言語をアセンブラ言語にコンパイルするコンパイラ(字句、構文解析/最適化をおこなう)。CPUの種類ごとに必要。
|
アセンブラ(バックエンド) | アセンブラ言語をリロケータブルオブジェクトに変換するアセンブラ。CPUの種類ごとに必要。 |
リンキングローダー(バックエンド) | リロケータブルオブジェクトやライブラリーを実行可能なコマンドに変換するリンカ。OSの種類ごとに必要(ちょっと違うがこんなイメージ)。 |
LLVMを利用するメリット
- LLVMが、最適化やCPU依存のコンパイル等を行ってくれるので、プログラミング言語に特化した LLVM IRへの変換だけを考えれば良い。
- どのプログラミング言語で書かれたコードもほぼ同じ実行速度になる。
- バックエンドとして bitcodeから別のプログラミング言語へ変換するトランスレーターも容易に作成できる。
と思っているのだが、コンパイルの情報が少なすぎて、途中何をやっているのかわからない....リンキングローダーは動いているようだ。
※ 後で LLVM のソースでも覗くか・・・
$ clang -v a.c Apple clang version 13.1.6 (clang-1316.0.21.2.5) Target: x86_64-apple-darwin21.5.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin "/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx12.0.0 -Wundef-prefix=TARGET_OS_ -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -emit-obj -mrelax-all --mrelax-relocations -disable-free -disable-llvm-verifier -discard-value-names -main-file-name a.c -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fno-strict-return -fno-rounding-math -munwind-tables -target-sdk-version=12.3 -fvisibility-inlines-hidden-static-local-var -target-cpu penryn -tune-cpu generic -debugger-tuning=lldb -target-linker-version 763 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/13.1.6 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -I/usr/local/include -internal-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /Library/Developer/CommandLineTools/usr/lib/clang/13.1.6/include -internal-externc-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -internal-externc-isystem /Library/Developer/CommandLineTools/usr/include -Wno-reorder-init-list -Wno-implicit-int-float-conversion -Wno-c99-designator -Wno-final-dtor-non-final-class -Wno-extra-semi-stmt -Wno-misleading-indentation -Wno-quoted-include-in-framework-header -Wno-implicit-fallthrough -Wno-enum-enum-conversion -Wno-enum-float-conversion -Wno-elaborated-enum-base -Wno-reserved-identifier -Wno-gnu-folding-constant -Wno-objc-load-method -fdebug-compilation-dir=/Users/shin/tmp -ferror-limit 19 -stack-protector 1 -fstack-check -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fmax-type-align=16 -fcommon -fcolor-diagnostics -clang-vendor-feature=+messageToSelfInClassMethodIdReturnType -clang-vendor-feature=+disableInferNewAvailabilityFromInit -clang-vendor-feature=+disableNonDependentMemberExprInCurrentInstantiation -fno-odr-hash-protocols -clang-vendor-feature=+enableAggressiveVLAFolding -clang-vendor-feature=+revert09abecef7bbf -clang-vendor-feature=+thisNoAlignAttr -clang-vendor-feature=+thisNoNullAttr -mllvm -disable-aligned-alloc-awareness=1 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/folders/8b/fw9h6nbs6wv3b98srspvjl7c0000gn/T/a-ef7b14.o -x c a.c clang -cc1 version 13.1.6 (clang-1316.0.21.2.5) default target x86_64-apple-darwin21.5.0 ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/local/include" ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/Library/Frameworks" #include "..." search starts here: #include <...> search starts here: /usr/local/include /Library/Developer/CommandLineTools/usr/lib/clang/13.1.6/include /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include /Library/Developer/CommandLineTools/usr/include /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory) End of search list. "/Library/Developer/CommandLineTools/usr/bin/ld" -demangle -lto_library /Library/Developer/CommandLineTools/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch x86_64 -platform_version macos 12.0.0 12.3 -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -o a.out -L/usr/local/lib /var/folders/8b/fw9h6nbs6wv3b98srspvjl7c0000gn/T/a-ef7b14.o -lSystem /Library/Developer/CommandLineTools/usr/lib/clang/13.1.6/lib/darwin/libclang_rt.osx.a $ $ ./a.out hello, world! $
$ swiftc -v a.swift Apple Swift version 5.6.1 (swiftlang-5.6.0.323.66 clang-1316.0.20.12) Target: x86_64-apple-darwin21.5.0 /Library/Developer/CommandLineTools/usr/bin/swift-frontend -frontend -c -primary-file a.swift -target x86_64-apple-darwin21.5.0 -enable-objc-interop -sdk /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -color-diagnostics -target-sdk-version 12.3 -module-name a -o /var/folders/8b/fw9h6nbs6wv3b98srspvjl7c0000gn/T/a-f8df91.o /Library/Developer/CommandLineTools/usr/bin/ld /var/folders/8b/fw9h6nbs6wv3b98srspvjl7c0000gn/T/a-f8df91.o /Library/Developer/CommandLineTools/usr/lib/swift/clang/lib/darwin/libclang_rt.osx.a -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -lobjc -lSystem -arch x86_64 -L /Library/Developer/CommandLineTools/usr/lib/swift/macosx -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/swift -platform_version macos 12.0.0 12.3.0 -no_objc_category_merging -o a $ $ ./a hello, world! $
clangを見てみる
clang のコンパイルオプションや llvm のコマンドから紐解く
-c | リロケータブルオブジェクトを履く |
---|---|
-S | アセンブラを履く |
-emit-llvm -c | bitcodeを履く |
-emit-llvm -S | 中間言語を履く |
- vi sample.c
- clang -emit-llvm -S sample.c -o sample.ll
- llvm-as sample.ll -o sample.bc
- llc sample.bc –o sample.s
- as sample.s -o sample.o
- ld sample.o -lc -o a.out
実行イメージ:実際には上記の流れでコマンドが実行さるわけではありません。
フロントエンド
LLVM利用しているフロントエンド(一部)
Clang | C、C++、Objective-C、Objective-C++ |
---|---|
swiftc | Swift |
rustc | Rust |
GHC | Haskell |
LDC | D Programming Language |
DragonEgg | gcc |