フルスクラッチでコンパイラを作っていく
パーサライブラリやLLVMなどのコンパイラ基盤を使用せずに、フルスクラッチでRISC-V向けのコードを生成するコンパイラを作成していく。
進捗としてはLispインタプリタはある程度形になっており、今はコンパイラ作成に着手している。
入力の言語としてLispを採用したが、いずれは自作言語に置き換えたい。
機能としては以下の通り
- Lispとしての基本的な関数(
define
,if
,+
など) - マクロ
- 静的型
- REPL
- ちょっとこだわって作ったが自分では使っていない 😇
- いくつかの最適化
- 末尾再帰最適化、定数畳み込みなど
コンパイラの実装は、パースや型検査などのフロントエンド処理をしてから、中間言語にコンパイル、最適化、レジスタ割り当てをして最後にRISC-Vのコードを生成している。
まだ簡単な演算や制御式、関数定義を含むコードしかコンパイルできない。
実行に関しては、実機とエミュレータで行っている。
実機はRISC-Vの開発ボードを使用している。
書き込みモードと実行モードの切り替えがしやすいので、普段はこっちを使っている。ただ、書き込みモードにするとブルースクリーンになってしまうことがある。
書き込みモードへの切り替えが面倒なので、開発には使っていない。IPSディスプレイが付いているので、いつかコンパイルしたプログラムで表示させてみたい。
(RISC-Vのマイコンボード、少なすぎなのでもっと増えて欲しい)
コンパイラ作成に当たっての最初の目標は、LEDを点滅させること、つまりLチカである。点滅はループないしタイマ割り込みが必要なので、まずは点灯させることを目指した。
Arduinoだと pinMode
と digitalWrite
で済んでしまうが、そういったライブラリに頼ることはできないのでMemory-Mapped Registerでピンの設定と書き込みをする必要がある。
チップの仕様書が公開されているので、それを見ながら実装したら点灯まではできた。
点滅は今動くように修正中。
エミュレータは手元でのデバッグと自動テスト用に使っている。
テストをしやすくするために、レジスタの値をJSONで出力するようにしたものを使っている。
てか、みんなどうやってコンパイラのテストをしているんだろう 🤔 最適化のテストとか特に。
コンパイラとしてはまだまだなので、実装で詰まったところなどを書いていきたい。
ある程度たまってきたら本にしたいなーと少し考えている。
メモ: WSL2 Ubuntu 20.04.6におけるコアダンプの出力先
$ sysctl kernel.core_pattern
kernel.core_pattern = /mnt/wslg/dumps/core.%e