C コンパイラ作成入門

Nov 30, 2019 15:13 · 37 words · 1 minute read

低レイヤを知りたい人のための C コンパイラ作成入門 を読んだ。とても良い教科書だった。

教科書のリファレンス実装である rui314/chibicc リポジトリの reference ブランチを写経しながら読み進めた。セルフコンパイルまでは辿り着いていないが、制御構文も関数も文字列リテラルもできて、それなりにプログラミング言語っぽくなったし、コンパイルの雰囲気はつかめたので一旦ここまで。

コンパイラの中身

このコンパイラは以下の 3 つのステップで構成されている。

  • トークナイザーで入力文字列からトークン列(連結リストで実装)に変換
  • パーサーでトークン列を AST に変換
  • コードジェネレーターで AST からアセンブリ文字列に変換

アセンブリから機械語へ変換する部分は gcc を使う。

難しかったこと

レジスタやアセンブリの仕様に関する知識が求められるため、コードジェネレーターは自力では書けなかったと思う。

またアセンブリに立ち向かうのが初めてだったので、アセンブリのコードで計算できるのが不思議な感じがした。出力されたアセンブリが計算する様を直感的に想像できず、紙と鉛筆でスタックマシンとレジスタをエミュレートしてやっと納得することを繰り返した。AST を可視化するコードや CPU のエミュレータを書けば理解の助けになったかもしれない。そういう点では、高級言語のありがたみがわかった。


リファレンス実装は副作用のある関数を多用するスタイルで、ちょっと難しい。しかし

このようなグローバル変数を使うプログラミングスタイルは、きれいなスタイルには見えないかもしれません。しかし実際には、ここで行なっているように、入力トークン列を標準入力のようなストリームとして扱うほうがパーサのコードが読みやすくなることが多いようです。

と書かれているように、承知の上らしい。この "一般的な良いプログラミング作法からは外れるけど敢えて採用した" という結論は豊富な経験から導かれたのだろうし、割と正しいことが多い。


ともあれ、次にコンパイラを書くとき "何から始めればよいか分からない" 状態は卒業できた。また何かコンパイラ書いてみたい。