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