技術

8.1. チュートリアルのまとめ

初出時には第8章でしたが現在(2017/09/16時点)では原文のほうで新たに8章と9章が追加され、本章は10章となっているようです。
内容は初出時のまま残しておきますが原文へのリンクだけ10章のものを指すよう更新しました。

LLVMによるプログラミング言語の実装チュートリアル日本語訳
第8章 万華鏡: まとめとLLVMのその他の便利な点
第1節 チュートリアルのまとめ

“LLVMによるプログラミング言語の実装”チュートリアルの最後の章へようこそ。
これまでのチュートリアルで、我々の小さな言語”万華鏡”を、”使いものにならないおもちゃ”から”それなりに実用的な(しかしまだ使い物にならない部分が多々ある)おもちゃ”へ、成長させてきた。

我々のここまでの足取り、そして如何に少ないコードで達成したかを見返すと興味深い。
我々は、(コメント、空行抜きで)700行弱のコードを書くことによって、字句解析器、構文解析器、AST、コード生成器、JITを使ったインタラクティブなランループの全てを構築した。

我々の小さな言語はちょっとした面白い特徴を備えている。
ユーザ定義単項演算子とユーザ定義二項演算子のサポート。
即時評価のためのJITコンパイル機能。
SSA構造による幾つかの制御フロー構造のサポート。

このチュートリアルの狙いのひとつは、言語を定義し、構築し、遊ぶ事が如何に簡単で楽しいかをということを示すことにある。
コンパイラの構築には、恐ろしく超常的なプロセスは必要ない!
これまで、あなたは幾つかの基本を見てきた。
あなたがこのコードを受け取り、それをハックすることを、私は強く勧める。
例えば、以下のようなものを追加してみるとよい。

  • グローバル変数
    グローバル変数はモダンなソフトウェア工学上では問題とされているが、万華鏡コンパイラそのもので使ったように、即時に小さいハックを加えるとき等はしばしば便利なものである。
    幸運な事に、現状のコードにグローバル変数の機能を追加するのはとても簡単である。
    変数が見つからなかったときにそれを拒絶する前に、グローバル変数のシンボルテーブルから変数を探すだけでよい。
    新しいグローバル変数を生成するには、LLVMのGlobalVariableクラスのインスタンスを生成する。
  • 型付けされた値
    現状の万華鏡は、double型の変数のみをサポートしている。
    たったひとつだけの型をサポートするということは、つまり型を指定する必要がないという事なので、言語をとても綺麗に保つことができる。
    他の言語では、これを処理する他の方法を採用している。
    いちばん簡単なのは、変数を定義するごとにユーザに型を指定させ、Value*とともにその型をシンボルテーブルに記録する事である。
  • 配列、構造体、ベクタ、等々
    型を追加したら、あらゆる種類の興味深い方法によって、型システムを拡張しはじめることが出来る。
    シンプルな配列はとても簡単で、色んなアプリケーションにとって実に便利なものである。
    それらを追加するのにかかる時間の大部分は、LLVMのgetelementptr命令だどう動くかについて学ぶ事に費やすことになるだろう。
    getelementptrは、粋で型にはまらないものである。(FAQ http://llvm.org/docs/GetElementPtr.html
    もし再帰的な型(例えばリンクリスト等)のサポートを追加したい場合は、その方法についての説明が書かれた”LLVMプログラママニュアル”の該当セクション(http://llvm.org/docs/ProgrammersManual.html#TypeResolve)をしっかり読もう。
  • 標準ランタイム
    現状の万華鏡言語では、ユーザが任意の外部関数にアクセス可能であり、我々もprintdやputchardのようなもののために使った。
    あなたが行うであろう拡張によって言語に追加される高いレベルの構造は、言語が提供するランタイムで各種操作がサポートされたとき最も有用である。
    例えば、言語にハッシュテーブルの機能を追加した場合、その操作をユーザに毎回インラインで書かせるよりは、ルーチンをランタイムに追加したほうが理にかなっている。
  • メモリ管理
    現状では、ユーザは万華鏡のスタックにのみアクセス可能である。
    標準libcのmalloc/freeやGCによって、ヒープメモリの割り当てが出来るようになると便利であろう。
    もしGCを使いたい場合、LLVMは厳密なガベージコレクション(Accurate Garbage Collection)を完全にサポートしていることに注意。
    (厳密なガベージコレクションは、オブジェクトを移動したり、スタックのスキャン・更新が必要なアルゴリズムを含んでいる。)
  • デバッガのサポート
    LLVMは、GDBのような一般的なデバッガが理解できる、DWARFデバッグ情報の生成をサポートしている。
    デバッグ情報のためのサポートの追加は、かなり簡単である。
    これを理解するには、何かのC/C++のコードを”llvm-gcc -g -O0″でコンパイルし、何が生成されるかについて注意深く観察するのが一番だろう。
  • 例外処理のサポート
    LLVMは、他の言語へコンパイルされたコードと同時に使用する、コストゼロの例外の生成をサポートしている。(LLVM supports generation of zero cost exceptions which interoperate with code compiled in other languages.)
    暗黙的に各関数の戻り値でエラーを返すようにし、それをチェックするようなコードを生成することによっても同じようなことは実現できる。
    さらに、setjmp/longjmpを明示的に使用することも出来る。
    例外処理のサポートを実現する方法はたくさんある。
  • オブジェクト指向、ジェネリック、データベースアクセス、複素数、幾何プログラミング等々
    言語に加えることが出来る特徴にはキリがない。
  • 変わった分野
    我々は、多くの人が興味を持つ領域(具体的な言語のためのコンパイラの構築)に対してLLVMを適用する方法について説明してきた。
    しかし、コンパイラ技術は、典型的に考えられてきた分野だけでなく、他の分野でも有用である。
    例えば、OpenGLグラフィックスアクセラレーションの実装や、C++のコードをActionScriptに変換する用途や、他のもっとたくさんの可愛くて利口な用途でLLVMは使われてきた。
    もしかしたら、LLVMで正規表現をネイティブコードにJITコンパイルする第一人者になれるかも?
    訳注: OpenGLについては、ソフトウェアパイプラインをLLVMを使って実装したり、GLSLをLLVMを使ってコンパイルしたりという使い方が有名。

異質で変な何かを試すのを楽しむと良い。
ちょっと狂ってたり風変わりなものを試し、それをどうやって作るか考えるような事と比べると、みんながやってるような言語の構築はつまらない。
もしつまづいたり、話したいことがあれば、llvmdevメーリングリストに気軽にメールしてほしい。
そこには、言語に魅せられ手助けすることを厭わない人達がたくさんいる。

このチュートリアルを終わりにする前に、LLVM IRの生成における幾つかのヒントや技について説明する。
これらは、明白ではなく微妙なものかもしれないが、あなががLLVMの能力を利用するにあたって、非常に有用であろう。

コメントを残す

メールアドレスが公開されることはありません。



※画像をクリックして別の画像を表示