memo
コンパイラがこんな感じだったら入門者(わたしのような)が勉強しやすいのだけど、現実はもっと複雑だ。
(defun compile (program) (emit (optimize-3 (optimize-2 (optimize-1 program)))))
自作のコンパイラは、何か要素を見つける度に問答無用で断片をファイルに出力している。一度出力してしまうと当然もういじれないし、コンパイラが式の変形をしているだけ、という感じに見えないのが難点。
ので、今までの単純な構成を変えて、地味だけど中間形式を導入してみようと思う。中間形式といってもとりあえず最終 llvm ir の一歩手前くらいを s式で表現したものにする。 llvm の opt で最適化した llvm ir を s 式に戻せるようにもしておきたい。
;; イメージ (compile '(+ 3 7)) ;; (本当はここで言語レベルの最適化を行う。これはより下の層では行えない) ;;=>S 式での表現に式を変形 (define-function scheme-entry () (assign %ret (alloca i32)) (store i32 (immediate-rep 3) i32* %ret) (assign %s (alloca i32)) ... )
=> LLVM IR に変形(一対一に対応) define i32 @scheme_entry() nounwind { entry: %ret = alloca i32 store i32 12, i32* %ret %s = alloca i32 ... } => アセンブラに変形(これは llvm の仕事)