Scheme Compiler の勉強(42) - 変換、変換!

  • 自作コンパイラもどきは、 3.11 を飛ばして 3.12 Assignment, 3.13 Extending Syntax あたりを行った。これでかなりコンパイラらしくなってきた。
  • 3.11 Complex Constants  は説明がわからないのでスキップ。"An Incremental Approach to Compiler Construction"は論文であって教科書ではないので、あちこち不親切。
  • Assignment Conversion で set! が導入されたが、何でも更新可能な変数と見なしているので無駄が多く、今まで動いていた fib が動かなくなった。そのうち本当に set! されるときだけ変換すればいい、はず。
  • S-式を変換する操作が多い。マクロの入門者には、非効率でも何でもいいので「let* を let の入れ子に変換するプログラム」を書くことをお勧め。これを書いてちゃんと変換漏れが無いようにできると、単純な式変形を行うマクロにはたぶん困らない。util.match も一緒に慣れるとベター。

さて、3.14 Symbols, Libraries, and Separate Compilation を進めている。既に一部の関数は LLVM 直書きではなく scheme で書いているので、一部は先取りしていると言っても良い。シンボルに関する説明は例によって少なく、分からない。

わたしの理解は、car とか add1 とかのプリミティブを全て runtime に移す。今までは全て命令列に変換していたものが、LLVM レベルの関数になり、call で呼び出す形になる。しかし小さいプリミティブはインライン化されて欲しい。

構成。

  • stst.ll, stst.bc - scheme プログラムがコンパイルされた LLVM IRプログラムと、llvm-as でコンパイルされた bc(bit code) ファイル。
  • runtime.bc - コンパイル済みの LLVM bc ファイル。ここに car とか cdr とかを記述する。
  • stst.rt.bc runtime と link (llvm-link)されたプログラム。

LLVM の関数定義には alwaysinline オプションがあるのでこれを使ってみた。

  • リンク前の stst.bc を最適化しても add1 はインライン化されない(当たり前)。また、llvm-link 自体は最適化はしていなそう(自信無し)。
  • stst.rt.bc(リンク結果)を opt -always-inline で最適化するとインライン化された。(正確にはインライン化された結果さらに定数になってしまった)
  • noinline を指定するとインライン化されない。

満足の行く内容なので、プリミティブをランタイムに移す作業を続けよう。