ふつパイラ、その後は(min-caml)
夜の散歩から帰ってきたら、何やら玄関の前に黒い虫が。。。
鳥目(もとえ、近眼)の女房が、なんだろうと目を近づけた瞬間、彼女の足が虫の上に。あーあ、 殺生しちゃったよと思っていると、ごきちゃんだったわよ と、にこにこと 言うではないか。ほっておくと、家に侵入してくるから、見つけたら即始末してると言う。
よく、台所で、新聞紙を丸めて、追いかけっこしてるな。ごきを目の敵にして、 執拗になってる。BUGを踏み潰す、勇ましき戦士よ。頑張っておくれ。
ついでに、亭主の生み出すBUGも踏み潰しておくれ。お願い。
哀れごきは、ぐちゃぐちゃになって、黒い羽根?だけ残ったんだけど、ちと、犯行現場 が、汚れているな。ねっとりしてて、掃除が大変そう。おびきだして、一網打尽 に出来ないかね。
ごめんなさいです。bug入り jcc
前回、conisを動かすにあたり、jcc と言う、チンケなshellスクリプトを書いた。 本能かどうか知らないが、言い訳がましく「ちょっとインチキっぽいですが」と書いて おいた。一見、正常に動いてるっぽかったけど。。。
[sakae@fb ~/tmp]$ cat jccBUG #!/bin/sh if [ -n "$3" ]; then opt="$1 $2" src=$3 elif [ -z "$3" ]; then opt=$1 src=$2 else opt='-O2' src=$1 fi echo opt = $opt echo src = $src
こんな風に、変数の値を確認出来るようにしておき
[sakae@fb ~/tmp]$ ./jccBUG -S -O3 hoge.c opt = -S -O3 src = hoge.c [sakae@fb ~/tmp]$ ./jccBUG -S hoge.c opt = -S src = hoge.c [sakae@fb ~/tmp]$ ./jccBUG hoge.c opt = hoge.c src =
else節には、達していないのである。字面を見れば分かるっしょと言うのは、後の祭である。これを書いた時点で、「お客さん、絶対に else節には到達しませんで」と、言って 欲しかったぞ。そういう事を望むなら、やはり、あれしか、ないかな。取り敢えず、BUGは踏み潰しておかなければ。
#!/bin/sh if [ -z "$1" ]; then echo Need args exit 1 elif [ ".c" = `expr -- "$1" : ".*\(..\)"` ]; then opt='-O2' src=$1 elif [ ".c" = `expr -- "$2" : ".*\(..\)"` ]; then opt=$1 src=$2 else opt="$1 $2" src=$3 fi
まだ、期待が半分以上交じっていますが(まだ、Bug入り)、きりがないので、これぐらいにしておきます。
ちゃんとやるなら、引数をシフトしなが、その引数の先頭が "-" か、最後が ".c" で終るかで場合分け。累積してくかな。いずれにしろ、めんどいなあ。 まてまて、今回の場合なら面倒臭い事何も考えずに、"$@" で、いいじゃん。早く気づけよ。 BUGは、プログラムを書く事によって沸いてくる。プログラムを書かないのが一番大切じゃな。
min-caml
とーだいのCPU実験を見ていたら、ちらりと ocaml なんて言葉が出てきた。そこで思い出しちゃったんだけど 日本の美しいMLコンパイラですよ。
誰も "O" の部分は使わないという、ocamlを使って、MLのサブセットであるmin-caml用の コンパイラを作っちゃうと言う教材です。このサブセットを使って、レイトレーシング プログラムを動かし、スピードを競うと言う、楽しいゲームが行なわれるみたい。
このコンパイラのターゲットは、sparc用に書かれていますが、今や「SUN goes down」 の様相になってますから、独自CPUを設計して、それ用のコンパイラを作れとなってる 訳です。SUNが、スタンフォード大学から生まれたのは、余りに有名な話ですので、 是非、東大生が、新しいCPUを設計して、TUN でも作って下さい。
お勧めのマシンは、 YARVですね。shiroさんによると、YARVみたいなスタックマシンでもLUAみたいな レジスターマシンでも、つまる所一緒じゃんと言う話もありますから、大丈夫でしょう。
私は、生憎、sparcなマシンを持っていませんが、min-camlを動かすぐらいの事なら 出来るでしょう。果して、これってクロスコンパイラ?
[sakae@fb ~/min-caml]$ ls LICENSE m.ml Makefile main.ml OCamlMakefile main.mli alpha.ml min-rt/ alpha.mli parser.mly anchor.ml regAlloc.ml assoc.ml regAlloc.mli assoc.mli regAlloc.notarget-nospill.ml beta.ml regAlloc.target-earlyspill.ml beta.mli regAlloc.target-latespill.ml bytemark/ regAlloc.target-nospill.ml closure.ml s.ml closure.mli saishuu.ppt constFold.ml shootout/ constFold.mli simm13.ml elim.ml simm13.mli elim.mli sparcAsm.ml emit.ml sparcAsm.mli emit.mli stub.c fdpe05.ppt syntax.ml float.c test/ gaiyou.ppt tutorial-mincaml.doc id.ml tutorial-ml.doc inline.ml type.ml inline.mli typing.ml kNormal.ml typing.mli kNormal.mli virtual.ml lexer.mll virtual.mli libmincaml.s
ちょっと、libmincaml.s や stub.c なんて言う不穏な名前のファイルが混じっていますが、見なかった事にします。(勿論、*.ppt,*.docもです。)
[sakae@fb ~/min-caml]$ gmake ocamllex lexer.mll 79 states, 2474 transitions, table size 10370 bytes ocamlyacc parser.mly 135 shift/reduce conflicts. gmake[1]: ディレクトリ `/home/sakae/min-caml' に入ります making ._bcdi/parser.di from parser.mli making ._bcdi/main.di from main.mli making ._bcdi/emit.di from emit.mli : libmincaml.s:180: Error: no such instruction: `st %o7,[%i0]' libmincaml.s:183: Error: no such instruction: `ld [%i0],%o7' gmake: *** [test/print] エラー 1
ははは、不安が見事に的中しましたねえ。Makefile を見たら、コンパイル&GOになって ましたんで、コンパイラ本体は出来ているでしょう。
drwxr-xr-x 2 sakae kuma 1024 10 14 13:22 test/ -rwxr-xr-x 1 sakae kuma 461437 10 14 13:22 min-caml.opt*
やっぱり出来上がっていたよ。
[sakae@fb ~/min-caml/test]$ ../min-caml.opt fib.ml Fatal error: exception Sys_error("fib.ml.ml: No such file or directory")
一瞬、ドキィとしたけど、良くみたら、サフィクスは要らないっぽい。
[sakae@fb ~/min-caml/test]$ ../min-caml.opt fib free variable print_int assumed as external iteration 1000 iteration 999 directly applying fib.10 directly applying fib.10 directly applying fib.10 eliminating closure(s) fib.10 register allocation: may take some time (up to a few minutes, depending on the size of functions) generating assembly...
さて、何が出来ているかな?
[sakae@fb ~/min-caml/test]$ ls -l fib* -rw-r--r-- 1 sakae kuma 90 3 6 2005 fib.ml -rw-r--r-- 1 sakae kuma 745 10 12 13:32 fib.s [sakae@fb ~/min-caml/test]$ cat fib.s .section ".rodata" .align 8 .section ".text" fib.10: cmp %i2, 1 bg ble_else.26 nop retl nop ble_else.26: st %i2, [%i0 + 0] sub %i2, 1, %i2 st %o7, [%i0 + 4] call fib.10 add %i0, 8, %i0 ! delay slot sub %i0, 8, %i0 ld [%i0 + 4], %o7 st %i2, [%i0 + 4] ld [%i0 + 0], %i2 sub %i2, 2, %i2 st %o7, [%i0 + 12] call fib.10 add %i0, 16, %i0 ! delay slot sub %i0, 16, %i0 ld [%i0 + 12], %o7 ld [%i0 + 4], %i3 add %i3, %i2, %i2 retl nop .global min_caml_start min_caml_start: save %sp, -112, %sp set 30, %i2 st %o7, [%i0 + 4] call fib.10 add %i0, 8, %i0 ! delay slot sub %i0, 8, %i0 ld [%i0 + 4], %o7 st %o7, [%i0 + 4] call min_caml_print_int add %i0, 8, %i0 ! delay slot sub %i0, 8, %i0 ld [%i0 + 4], %o7 ret restore
おお、これが噂(誰もしてないって)のsparcアセンブラか。 でも、最終実行形式のファイルが出来てないね。こういう時は、Makefileに何か 書いてないか見てみる。
CC = gcc CFLAGS = -g -O2 -Wall test/%: test/%.s libmincaml.s stub.c $(CC) $(CFLAGS) $^ -lm -o $@
そうか、バックエンドは、gcc(for sparc)に、お任せね。まあ、アセンブラーのソースが 出てくれば、以降は工夫の余地が無いからねぇ。
Makefileをちまちまと見ていたら、面白いものを発見。
min-caml.html: main.mli main.ml id.ml m.ml s.ml \ syntax.ml type.ml parser.mly lexer.mll typing.mli typing.ml kNormal.mli kNormal.ml \ alpha.mli alpha.ml beta.mli beta.ml assoc.mli assoc.ml \ inline.mli inline.ml constFold.mli constFold.ml elim.mli elim.ml \ closure.mli closure.ml sparcAsm.mli sparcAsm.ml virtual.mli virtual.ml \ simm13.mli simm13.ml regAlloc.mli regAlloc.ml emit.mli emit.ml caml2html -o min-caml.html $^ sed 's/.*<\/title>/MinCaml Source Code<\/title>/g' < min-caml.html > min-caml.tmp.html mv min-caml.tmp.html min-caml.html sed 's/charset=iso-8859-1/charset=euc-jp/g' < min-caml.html > min-caml.tmp.html mv min-caml.tmp.html min-caml.html ocaml str.cma anchor.ml < min-caml.html > min-caml.tmp.html mv min-caml.tmp.html min-caml.html
どうやら、min-camlのソースを、htmlにしてくれるっぽい。やってみたら、caml2htmlが 無いよーんと言われた。しょうがないので caml2htmlを探してきたよ。駱駝軍団なんだねぇ。 無事に、min-caml.htmlが作成出来た。後は、ちらちらと、ソースを観賞してくだけだな。
観賞会
折角なので、ちとソースを観賞してみます。
let lexbuf outchan l = (* バッファをコンパイルしてチャンネルへ出力する *) Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))
まさに、流れるような美しさです。ocaml を、インストールすると、caml用の parserやlexerも、自動でインストールされます。よそから持ってくる必要が無い ってのが、いいですね。
*.f ってのは、*の部分がモジュール名(= file名)で、fは、そのモジュールで公開されてる メイン関数だ。機械的に読んでいけるのがありがたい。
観賞用の解説書を、作っておられる 方がいらっしゃいましたので、ありがたく使わせてもらいましょう。このページの作者さん、 過去のRHG読書会のプレゼンターをやっておられる。世の中、ぐるぐると輪になってますなあ。
キャンパスは、XC2V1000
sparcは、買うと高いので(青木さんなら、安い所知ってる?)、とーだいは、どんなキャンパス なのか調べてみた。FPGA XC2V1000 という石みたい。ああ、まだ石頭になってないから、粘土 だな。Lispは、泥団子(粘土)と言う、神様の言葉を思い出しちゃったじゃないですか。
して、このXC2V1000は、財リンクスがブランド名で、実際は台湾にあるUMCって言う会社が 12インチの円盤から作っているみたい。 100万ゲート規模のIC、1個3万9千円とか。この場合のゲートって言うと、NOR(or NAND)ゲート 換算って事で良いのかな? NORが有れば、どんなロジックでも出来ちゃいますからねぇ。
で、これを素材にして、結構高度な事やってるねぇ。 CPU実験とは!? とか mad日記あたりが 面白い。今年もがんがれ!
見てると、みんなMIPSっぽいCPUを設計してるな。IA32は、嫌われてると。まあ、土台にする コンパイラ実装がsparcだから、無理して電卓ICにチャレンジする事は無いな。でも、どうせ なら、ハーバード・アーキテクチャとか、スタックマシンもいいぞ。
この楽しいレースは、3年生の後半にやるみたいで、前半は、min-schemeのインタプリタを 作るみたい。後で、どんな講義を受けているか、探してみるかな。 そうそう、schemeと言えば、moshも 作者さんが几帳面な方で、 膨大な資料を残されています。