LLVMはどんな中間言語を吐くか気になったので・・・
% tar xJvf llvm-3.5.0.src.tar.xz
% tar xJvf cfe-3.5.0.src.tar.xz
% tar xJvf compiler-rt-3.5.0.src.tar.xz
% cd llvm-3.5.0.src
% mv ../cfe-3.5.0.src ./tools/clang
% mv ../compiler-rt-3.5.0.src ./projects/compiler-rt
% mkdir /usr/local/llvm
% make
インストール後はパスを通す。
export PATH=$PATH:/usr/local/llvm/bin
ubuntuの場合llvmはgcc 4.7以上が必要になる。
ubuntuでgccが古い場合は下記のようにデフォルトのgccを4.8などにする。
sudo apt-get install gcc-4.8
sudo update-alternatives --set gcc /usr/bin/gcc-4.8
サンプルソース// test.c
int main()
{
int i = 0;
for (i = 0; i < 99; i++) printf("hello, world %d\n", i),
return 0;
}
コンパイル$ clang test.c -v
clang version 3.5.0 (tags/RELEASE_350/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.8
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.8.2
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.9
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.9.1
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.4
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.4.7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.5
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.5.3
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.6
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.6.4
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.2
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.1
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Candidate multilib: x32;@mx32
Selected multilib: .;@m64
"/usr/local/llvm/bin/clang" -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name test.c -mrelocation-model static -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -target-linker-version 2.24 -v -dwarf-column-info -resource-dir /usr/local/llvm/bin/../lib/clang/3.5.0 -internal-isystem /usr/local/include -internal-isystem /usr/local/llvm/bin/../lib/clang/3.5.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /home/h-ishihara/workspace/llvm -ferror-limit 19 -fmessage-length 80 -mstackrealign -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -o /tmp/test-717d05.o -x c test.c
clang -cc1 version 3.5.0 based upon LLVM 3.5.0 default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/include"
/usr/local/include
/usr/local/llvm/bin/../lib/clang/3.5.0/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
"/usr/bin/ld" -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. -L/usr/local/llvm/bin/../lib -L/lib -L/usr/lib /tmp/test-717d05.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
他いろいろclang -emit-llvm -S test.c
-> test.ll
lli test.ll
llvm-as test.ll
-> test.bc
llc test.ll
-> test.s
やっと中間コードtest.llは次のように出力される。
; ModuleID = ''test.c''
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@.str = private unnamed_addr constant [17 x i8] c"hello, world %d\0A\00", align 1
; Function Attrs: nounwind uwtable
define i32 @main() #0 {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
store i32 0, i32* %retval
store i32 0, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%0 = load i32* %i, align 4
%cmp = icmp slt i32 %0, 99
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%1 = load i32* %i, align 4
%call = call i32 (i8, ...) @printf(i8 getelementptr inbounds ([17 x i8] @.str, i32 0, i32 0), i32 %1)
br label %for.inc
for.inc: ; preds = %for.body
%2 = load i32* %i, align 4
%inc = add nsw i32 %2, 1
store i32 %inc, i32* %i, align 4
br label %for.cond
for.end: ; preds = %for.cond
ret i32 0
}
declare i32 @printf(i8*, ...) #1
attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.ident = !{!0}
!0 = metadata !{metadata !"clang version 3.5.0 (tags/RELEASE_350/final)"}
まとめtest.llは非常にソースコードを展開しただけなので、厳密なことは言えないが、forラベルの括りで処理すればパイプラインでH/W化が可能なのが見て分かる。
CソースコードをH/Wするには、処理形態はプロセッサーに似たような作りになってしまうのは仕方がないことである。
どこまで並列性、パイプライン性を持たせることができるかで処理性能が決まるといって過言ではない。
おまけ(備忘録)ELLCC
Clang+LLVMで組み込み向けクロスコンパイラの作成
MicroBlazeのコンパイルをサポートしているらしい。
fairy
https://gitorious.org/fairy/llvm-fairy
これが何者かが分からないがMicroBlazeのコンパイラで引っかかった。
Writing an LLVM Backend
http://llvm.org/docs/WritingAnLLVMBackend.html
LLVM language Reference Manual
LLVMをするにあたって、これも読まなければいけない。
http://llvm.org/docs/LangRef.html
DCPU-16用LLVMバックエンド
https://news.ycombinator.com/item?id=3813302
Legup
http://legup.eecg.utoronto.ca/
MIPS+H/Wアクセラレーション
Alteraが中心でAvalonバスを使用する。