ふつパイラ、その後は(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も 作者さんが几帳面な方で、 膨大な資料を残されています。