infoMore than 5 years have passed since last update.
Rust1.10でレジスタ割り付け
Last updated at Posted at 2016-07-31
1 / 20
動機
- レジスタ割り付けの本格的なサンプルが欲しい
- Min-Camlにはレジスタ割り付けがある
- OCamlは文法が結構特殊なので慣れないと辛い
- C++に移植したけど、あまり美しくない
- C++のmoveセマンティックスは実行時エラーが起きて辛い
- Rustならきっと綺麗に書けるはず
Rustでのコンパイラ開発の問題
- Rustはまだ開発中では?
- GCがなくて不便では?
- パーサジェネレータはあるのか?
- immutableなグローバル変数は?
Rustはまだ開発中では?
GCがなくて不便では?
- GCがないけどインクリメンタルにメモリ管理する分高速なのでトレードオフです
- C++のunique_ptrで書くより楽です
- パターンマッチもあるし便利です
パーサジェネレータはあるのか?
- lalrpopというパーサジェネレータがあります
- インストール面倒くさいのでは?
lalrpop
- Rust製のパーサジェネレータ
- %% など見た目微妙な区切りはgrammer;と書く
- lexerも1ファイル内に一緒に書ける
- Rustの文法に近い文法で記述できる
- とてもいい感じ
immutableなグローバル変数は?
- コンパイラはIDを振りたいので、immutableなグローバル変数が欲しい
- 基本的には使わないでください
- じゃあどうしろと?
- なんで、こんなまどろっこしいの?
- マルチスレッドで安全に高速に動作させるため
- 横から書き換えられると困る
- Rustで安全に書けるの?
- どうやって?
実装
構文木を書く
- ast.rsに、enumを使って書いた
- 非常に短く書けるし、deriveを使えばcloneも簡単
構文木を印字
- ast_print.rsに印字プログラムを作ってみる
- パターンマッチを使って書けばよい
アセンブラ出力部分を作成
- オブジェクトにコンテキストとして、fileやmap,vector,カウンタを持たせて書く
- Rustのお行儀さえわかれば書けた
自由変数の計算を書く
- レジスタ割り付けや、即値最適化には生きている変数の計算(fv)が必要なので移植した
- ツリーをトラバースする小さい例としてよかった
即値最適化を書いてみる
- メモリをコピラない方法も出来る
- だけど、パターンマッチすると所有権が移動してしまうので、何も変えてないのに再構成するのが面倒
- 借用ポインタをトラバースして全部コピーすることにした
- それなりのサイズの変換プログラムが書けた
レジスタ割り付け
- 一番長い処理で結構、気力が萎える
- 最初は関数の型だけ合わせる。適当にコメント内で移植を進める
- 例外を使っている箇所が問題
- Either的なResultを使うことにした。Ok,Errを使う
- C++版とOCaml版を参考にして効率的に移植
パーサを作る
- とりあえず、lalrpopを見つけた
- lalrpopのチュートリアルをやってみた
- cargo便利じゃん!
- lalrpopを自分なりに書き換えて使ってみた
- 最後に、プロジェクトに組み込み、OCaml版のものを移植した
グローバル変数の書き換え
- とりあえず、"tmp"を返すようなスタブを置いておいた
- 次にunsafeを使って動くようにした
- 最後にCellを使って安全にした
- オブジェクト内の生成部分も共通処理を使うようにした
完成!
- 目標だった、fibonattiのプログラムがコンパイルできたので完成!
TODO
- コマンドライン引数はまだ対応してないので対応する
- テストをきっちり書く
- レジスタ割り付けの説明を書く
まとめ
- Rustでコンパイラを開発してみた
- Rustは安定してる
- Rustのパーサジェネレータは実用的だった
- RustはC++より綺麗にGCレスで書けた
- 型合わせは苦労したけど、ほとんど実行時バグに悩まずに済んだ
- Rustいいよ!
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme
What you can do with signing up