LLVMによるプログラミング言語の実装チュートリアル日本語訳
第3章 万華鏡: LLVM IRコードの生成
第5節 ドライバの変更と結論
今のところ、LLVMに対するコード生成は、きれいなIRコールを見ることが出来るという事以外は、実際にはあまり役立たない。
Codegenメソッドに”HandleDefinition”や”HandleExtern”などの関数呼び出しを追加すると、LLVM IRのダンプが見れる。
これは、LLVM IRを簡単な関数で見れる良い方法である。
例えばその出力は以下のようになる。
ready> 4+5; Read top-level expression: define double @0() { entry: ret double 9.000000e+00 }
構文解析器が、トップレベルの式をどのように匿名関数に変換するかに注意。
これは、次の章においてJITサポートを追加するときに役立つだろう。
コードは、そっくりそのまま翻訳され、IRBuilderによる簡単な定数の畳み込みを除いて最適化が行われていないことにも注意。
最適化機能は次の章で追加する。
ready> def foo(a b) a*a + 2*a*b + b*b; Read function definition: define double @foo(double %a, double %b) { entry: %multmp = fmul double %a, %a %multmp1 = fmul double 2.000000e+00, %a %multmp2 = fmul double %multmp1, %b %addtmp = fadd double %multmp, %multmp2 %multmp3 = fmul double %b, %b %addtmp4 = fadd double %addtmp, %multmp3 ret double %addtmp4 }
これは、幾つかの簡単な計算を示している。
命令を生成するために使用したLLVM Builderの呼び出しとの著しい類似性に注目。
ready> def bar(a) foo(a, 4.0) + bar(31337); Read function definition: define double @bar(double %a) { entry: %calltmp = call double @foo(double %a, double 4.000000e+00) %calltmp1 = call double @bar(double 3.133700e+04) %addtmp = fadd double %calltmp, %calltmp1 ret double %addtmp }
これは関数呼び出しを示している。
この関数を呼び出したとしたら、実行に長い時間がかかるであろう事に注意。
再帰を便利にするため、この先の章で、条件付き制御フローを追加する予定である。
ready> extern cos(x); Read extern: declare double @cos(double) ready> cos(1.234); Read top-level expression: define double @1() { entry: %calltmp = call double @cos(double 1.234000e+00) ret double %calltmp }
これは、libmの”cos”関数のためのextern宣言と、その呼び出しを示している。
ready> ^D ; ModuleID = 'my cool jit' define double @0() { entry: %addtmp = fadd double 4.000000e+00, 5.000000e+00 ret double %addtmp } define double @foo(double %a, double %b) { entry: %multmp = fmul double %a, %a %multmp1 = fmul double 2.000000e+00, %a %multmp2 = fmul double %multmp1, %b %addtmp = fadd double %multmp, %multmp2 %multmp3 = fmul double %b, %b %addtmp4 = fadd double %addtmp, %multmp3 ret double %addtmp4 } define double @bar(double %a) { entry: %calltmp = call double @foo(double %a, double 4.000000e+00) %calltmp1 = call double @bar(double 3.133700e+04) %addtmp = fadd double %calltmp, %calltmp1 ret double %addtmp } declare double @cos(double) define double @1() { entry: %calltmp = call double @cos(double 1.234000e+00) ret double %calltmp }
入力中のデモを終了するとき、生成されたモジュール全体のIRのダンプを出力する。
お互いに参照しあってる全ての関数を含む全体が見れるのが分かると思う。
これで万華鏡チュートリアルの第3章は終わりである。
次は、実際にコードを実行できるようにするために、JITコード生成と最適化サポートの追加について説明する。
最近のコメント
名前
しゅごい
Jane Doe
FYI Avoid Annoying Unexpe…
Jane Doe
ご存じとは思いますが、whileには、”~の間”と…
peta_okechan
針金みたいなパーツを引っ張ると外れます。 他の方の…
虎徹ファン交換
虎徹の標準ファンを外す際に、どのようにして外されま…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…