Scheme Compiler の勉強 (10) - Unary Primitives (fxadd1)
- scheme 流の define-syntax はエレガントだけど今のところとても使い辛い。式を変形したいだけであって、別にパターンマッチをしたい訳じゃないんだよなぁ。
- define-syntax でうなっているうち、そもそも根本的に勘違いしていることに気付いた。define-syntax の勉強は後回し。
1.3 Unary Primitives について。ここはかなり大きな固まりで、少しずつ実装して試す、ということがし辛い。もう一段階分解しても良いと思う。
fxadd1 について。
- $fxadd1 ($を付けている理由が書いていない、、内部関数との違い?)の定義。
- テストスイート tests-1.3-req.scm は、($fxadd1 1) => 2 だけじゃなく、($fxadd1 ($fxadd 0)) => 2 も要求している。
- ということは、 emit-expr はこの時点で再帰的に呼び出されなくちゃならない。再帰構造は emit-expr の中に含まれている。
- 0 を %eax に格納するコード
- %eax を1増やすコード
- %eax を1増やすコード
LLVM だと特に %eax に相当するものは存在しない。ターゲットとなるマシン毎に適当に変換してくれる。いまの教材に合わせたいので、適当に %ret という変数を作って、それを fxadd1 が更新するようにした※(かなり怪しいことをやっている可能性大)。
さらに LLVM の世界では「単一静的代入」らしいので※(良くわかっていない、注意)、$fxadd1 の中で使う「変数」名は毎回変えてやるようにした。
これでようやく、 tests-1.3-req.scm の最初の部分のテストが通った。
Performing fxadd1 tests ... test 110:($fxadd1 0) ... ok test 111:($fxadd1 -1) ... ok test 112:($fxadd1 1) ... ok test 113:($fxadd1 -100) ... ok test 114:($fxadd1 1000) ... ok test 115:($fxadd1 536870910) ... ok test 116:($fxadd1 -536870912) ... ok test 117:($fxadd1 ($fxadd1 0)) ... ok test 118:($fxadd1 ($fxadd1 ($fxadd1 ($fxadd1 ($fxadd1 ($fxadd1 12)))))) ... ok
;; (fxadd1 7) をコンパイル gosh> (build-program '($fxadd1 7)) #<undef>
stst.s: 生成された LLVM のコード define i32 @scheme_entry() nounwind { entry: %ret = alloca i32 store i32 28, i32* %ret %val16 = load i32* %ret %tmp16 = add i32 4, %val16 store i32 %tmp16, i32* %ret %retval = load i32* %ret ret i32 %retval }
stst.n.s: さらに変換された PowerPC 用のアセンブラ .machine ppc7400 .section __TEXT,__textcoal_nt,coalesced,pure_instructions .section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16 .text .globl _scheme_entry .align 4 _scheme_entry: li r2, 28 stw r2, -4(r1) li r3, 32 stw r3, -4(r1) blr .subsections_via_symbols
いかにもどんくさそうな気がするが、とりあえず前に進もう。そのうち最適化とか出てくるから。
続く、はず。