Julia debug, LLVM
前回は、ひょんな事からllvmを入れるはめになった。Juliaでも使われている。勿論、FreeBSDにも 使われている。gccの代わりにね。
llvmはいろいろな言語をコンパイル出来るような作りになってる。C語をコンパイル出来るように フロントを整えたものをclang(シランと発音するそうだ。恐い化合物だぞ)と特別に呼んでいる。
julia語をJITコンパイルするために、juliaでは重要な役割を果たしている。juliaにおいてllvmは どう使われるか? libLLVMのどこかが呼ばれるはず。
えと、ライブラリーをトレースするコマンドが有ったな。 ltraceを調べたよ FreeBSDにもシステムユーティリティにltraceは有るんだけど、64Bitマシンしかサポート していない。旧石器人は肩身が狭いですよ。そんな訳で、fedoraです。特殊な事してる のかな。まあいい。
簡単なスクリプトを実行して、トレース。
[sakae@fedora ~]$ ltrace julia -e 'println(factor(987654321))' __libc_start_main([ "julia", "-e", "println(factor(987654321))" ] <unfinished ...> uv_setup_args(3, 0xbfe0ccf4, 0x804a649, 0x804906a) = 0x86e6538 libsupport_init(3, 0xbfe0ccf4, 0x804a649, 0x804906a) = 0x86e6ff0 getopt_long(3, 0xbfe0ccf4, "+vhqFfH:e:E:P:L:J:C:ip:Ob:", 0x804d0e0, nil) = 101 __strdup(0xbfe0e1f6, 0xbfe0ccf4, 0x804a744, 0x804d0e0) = 0x86e7078 getopt_long(3, 0xbfe0ccf4, "+vhqFfH:e:E:P:L:J:C:ip:Ob:", 0x804d0e0, nil) = -1 julia_init(1, 0xbfe0cc64, 0x804a649, 0x804906a <no return ...> --- SIGCHLD (Child exited) --- <... julia_init resumed> ) = 0 jl_symbol(0x804a705, 0xbfe0cb28, 0xb767e000, 0xbfe0cb48) = 0x935299d4 jl_get_global(0x935c8160, 0x935299d4, 0xb767e000, 0xbfe0cb48) = 0x94fad5a0 jl_array_grow_end(0x94fad5a0, 0, 0xb767e000, 0xbfe0cb48) = 0x94fad5a0 jl_symbol(0x804a711, 0, 0xb767e000, 0xbfe0cb48) = 0x9353921c jl_get_global(0x935c8160, 0x9353921c, 0xb767e000, 0xbfe0cb48) = 0x950c2a30 Dict(17=>2,379721=>1,3=>2) jl_atexit_hook(0, 0xbfe0cc64, 0x804a649, 0x804906a) = 0 +++ exited (status 0) +++
えっ、なんか中抜けしてないか。小供がどうこう言ってるし。小供も追跡するように、-f オプションを加えてみる。
[sakae@fedora ~]$ ltrace -o LOG -n 2 -f julia -e 'println(factor(987654321))' Couldn't find .dynsym or .dynstr in "/proc/1973/exe" [sakae@fedora ~]$ lv LOG 1972 __libc_start_main([ "julia", "-e", "println(factor(987654321))" ] <unfinished ...> 1972 uv_setup_args(3, 0xbf9fcbc4, 0x804a649, 0x804906a) = 0x9aa6538 1972 libsupport_init(3, 0xbf9fcbc4, 0x804a649, 0x804906a) = 0x9aa6ff0 1972 getopt_long(3, 0xbf9fcbc4, "+vhqFfH:e:E:P:L:J:C:ip:Ob:", 0x804d0e0, nil)101 1972 __strdup(0xbf9fe1f6, 0xbf9fcbc4, 0x804a744, 0x804d0e0) = 0x9aa7078 1972 getopt_long(3, 0xbf9fcbc4, "+vhqFfH:e:E:P:L:J:C:ip:Ob:", 0x804d0e0, nil)= -1 1972 julia_init(1, 0xbf9fcb34, 0x804a649, 0x804906a <no return ...> 1973 --- Called exec() --- 1973 __libc_start_main([ "sh", "-c", "/sbin/ldconfig -p" ] <unfinished ...> 1973 __sigsetjmp(0x8019cf60, 0, 0, 4096) = 0 : 1973 execve(0x81345210, 0x813452a0, 0x81343aa8, 0x81345250 <no return ...> 1973 --- Called exec() ---
どうも肝心な所が見えないですなあ。
lsof -c julia ってして、待機してるjuliaのライブラリィー使用状況を調べると、 ちゃんとlibLLVMも開いている。
しょうがないので、julia-debug用に下記をインストール
julia-debuginfo i686 0.4.3-1.fc23 nalimilan-julia 4.6 M libffi-debuginfo i686 3.1-8.fc23 fedora-debuginfo 115 k libunwind-debuginfo i686 1.1-10.fc23 fedora-debuginfo 222 k llvm-debuginfo i686 3.7.0-4.fc23 updates-debuginfo 570 M utf8proc-debuginfo i686 1.3-1.fc23 nalimilan-julia 86 k zlib-debuginfo i686 1.2.8-9.fc23 fedora-debuginfo 254 k
実際に展開されると、表示された容量の4倍ぐらいに膨れ上がり、DISKが心もとなく なったので使用を断念。FreeBSD側に期待をかける事にした。
FreeBSDでdebug
と言う名のjuliaソースツアーをやってみたい。で、大本になるjuliaがdebug用に コンパイルされていない。まずはそこからだな。
Makefileを見ると make debugで行けそう。待つ事10分ぐらいかな。julia-debugが 出来上がった。 makeする時のログを取ってたので眺めてみると
GEN include/uv-dtrace.h CC src/libuv_la-fs-poll.lo CC src/libuv_la-inet.lo CC src/libuv_la-uv-common.lo CC src/libuv_la-version.lo CC src/unix/libuv_la-async.lo ; CCLD libuv.la GEN src/unix/uv-dtrace.o llvm pcore flisp xxx.jl
ってな具合にコンパイルされた。blsaとかllvmの長くかかるコンパイル時間の影に 隠れていたけど、ようやくコンパイル過程が分かった気がする。
後はgdbを何とかしたい。portsから自分でコンパイルしようとしたら、kgdbも一緒に 作る仕様になってた。このおかげで出来合いのgdbは自分の環境とマッチしなかったの だろう。多分、旧石器問題(32Bitの石)問題だと思われ。
で、下記は恒例のreplが待ちに入った時の状況。
(gdb) bt #0 0x282e144f in _kevent () from /lib/libc.so.7 #1 0x2835ff05 in ?? () from /lib/libthr.so.3 #2 0x28579e83 in uv__io_poll (loop=loop@entry=0x29290000 <default_loop_struct>, timeout=-1\) at src/unix/kqueue.c:130 #3 0x2856cf21 in uv_run (loop=0x29290000 <default_loop_struct>, mode=UV_RUN_ONCE) at src/u\nix/core.c:294 #4 0x28536be4 in jl_run_once (loop=0x29290000 <default_loop_struct>) at jl_uv.c:116 #5 0x2b63ca83 in julia_process_events_17329 () at stream.jl:713 #6 0x2b63c6ef in julia_wait_17327 () at task.jl:360 #7 0x2b63c4a7 in julia_wait_17325 () at task.jl:286 #8 0x2b647598 in julia_wait_readnb_17554 () at stream.jl:358 #9 0x2b6472f4 in julia_eof_17553 () at stream.jl:1209 #10 0x2b6470ed in julia_match_input_17552 () at LineEdit.jl:756 #11 0x2847e2ad in jl_apply (f=0x2d910530, args=0xbfbfde94, nargs=5) at julia.h:1325 #12 0x28482425 in jl_trampoline (F=0x2d910530, args=0xbfbfde64, nargs=5) at builtins.c:1037 #13 0x28471f0b in jl_apply (f=0x2d910530, args=0xbfbfde64, nargs=5) at julia.h:1325 #14 0x28477796 in jl_apply_generic (F=0x2d9103d0, args=0xbfbfde64, nargs=5) at gf.c:1684 #15 0x2b646e4a in julia_match_input_17547 () at LineEdit.jl:756 #16 0x2847e2ad in jl_apply (f=0x2d910510, args=0xbfbfe03c, nargs=2) at julia.h:1325 #17 0x28482425 in jl_trampoline (F=0x2d910510, args=0xbfbfe03c, nargs=2) at builtins.c:1037 #18 0x28471f0b in jl_apply (f=0x2d910510, args=0xbfbfe03c, nargs=2) at julia.h:1325 #19 0x28477796 in jl_apply_generic (F=0x2d9103d0, args=0xbfbfe03c, nargs=2) at gf.c:1684 #20 0x2b649178 in julia_prompt!_17601 () at LineEdit.jl:1631 #21 0x2b64c4ed in julia_run_interface_17668 () at LineEdit.jl:1605 #22 0x2b64c6b7 in jlcall_run_interface_17668 () from /usr/home/sakae/src/julia-0.4.3/usr/lib/julia/sys-debug.so #23 0x2847e2ad in jl_apply (f=0x2dbd7850, args=0xbfbfe2cc, nargs=2) at julia.h:1325 #24 0x28482425 in jl_trampoline (F=0x2dbd7850, args=0xbfbfe2cc, nargs=2) at builtins.c:1037 #25 0x28471f0b in jl_apply (f=0x2dbd7850, args=0xbfbfe2cc, nargs=2) at julia.h:1325 #26 0x28477796 in jl_apply_generic (F=0x2dbd77c0, args=0xbfbfe2cc, nargs=2) at gf.c:1684 #27 0x2b656ce3 in julia_run_frontend_17953 () at REPL.jl:863 #28 0x2b6562c5 in julia_run_repl_17939 () at REPL.jl:167 #29 0x2847e2ad in jl_apply (f=0x2dc48d20, args=0xbfbfe52c, nargs=2) at julia.h:1325 #30 0x28482425 in jl_trampoline (F=0x2dc48d20, args=0xbfbfe52c, nargs=2) at builtins.c:1037 #31 0x28471f0b in jl_apply (f=0x2dc48d20, args=0xbfbfe52c, nargs=2) at julia.h:1325 #32 0x28477796 in jl_apply_generic (F=0x2dc48c40, args=0xbfbfe52c, nargs=2) at gf.c:1684 #33 0x2b6694b7 in julia__start_18352 () at client.jl:420 #34 0x2b6697b5 in jlcall.start_18352 () from /usr/home/sakae/src/julia-0.4.3/usr/lib/julia/sys-debug.so #35 0x2847e2ad in jl_apply (f=0x2ebdbb60, args=0x0, nargs=0) at julia.h:1325 #36 0x28482425 in jl_trampoline (F=0x2ebdbb60, args=0x0, nargs=0) at builtins.c:1037 #37 0x28471f0b in jl_apply (f=0x2ebdbb60, args=0x0, nargs=0) at julia.h:1325 #38 0x28477796 in jl_apply_generic (F=0x2ebdbb00, args=0x0, nargs=0) at gf.c:1684 #39 0x0804956f in jl_apply (f=0x2ebdbb00, args=0x0, nargs=0) at ../src/julia.h:1325 #40 0x0804a5ea in true_main (argc=0, argv=0xbfbfe878) at repl.c:491 #41 0x0804a93a in main (argc=0, argv=0xbfbfe878) at repl.c:595
深い、深い、不快、不快って事で、目先を変えてみる。julialangの資料を流し読み。 面白い機能を発見。LLVMに依頼して出来たIR(中間表現)を取り出せるんですって。
$ export JULIA_LLVM_ARGS=-print-after-all $ julia -E 'factor(123456)' 2> IR-LOG Dict(643=>1,3=>1,2=>6)
STDERRに出てくるので、それだけをログ。ログのサイズは39M。67万行を超えるもの だったよ。これをコンパイルとかやってると、遅くなるのは肯けるな。 どんなになってるか?
$ head -15 IR-LOG *** IR Dump After Simplify the CFG *** define %jl_value_t* @jlcall_pointer_20837(%jl_value_t*, %jl_value_t**, i32) { top: %3 = getelementptr %jl_value_t** %1, i32 0 %4 = load %jl_value_t** %3 %5 = getelementptr %jl_value_t** %1, i32 1 %6 = load %jl_value_t** %5 %7 = bitcast %jl_value_t* %6 to i32* %8 = load i32* %7, align 16 %9 = call i8* @julia_pointer_20837(%jl_value_t* %4, i32 %8) %10 = ptrtoint i8* %9 to i32 %11 = call %jl_value_t* @jl_gc_allocobj(i32 4) %12 = bitcast %jl_value_t* %11 to %jl_value_t** %13 = getelementptr %jl_value_t** %12, i32 -1 store %jl_value_t* inttoptr (i32 763775056 to %jl_value_t*), %jl_value_t** %13
$ tail -15 IR-LOG Predecessors according to CFG: BB#0 %EAX<def> = MOV32rr %ESI<kill>; dbg:dict.jl:339:1 %ESP<def,tied1> = ADD32ri8 %ESP<tied0>, 24, %EFLAGS<imp-def,dead>; dbg:dict.jl:339:1 %ESI<def> = POP32r %ESP<imp-def>, %ESP<imp-use>; dbg:dict.jl:339:1 %EDI<def> = POP32r %ESP<imp-def>, %ESP<imp-use>; dbg:dict.jl:339:1 %EBP<def> = POP32r %ESP<imp-def>, %ESP<imp-use>; dbg:dict.jl:339:1 RET %EAX; dbg:dict.jl:339:1 BB#2: derived from LLVM BB %CallStackCheckFailBlk Live Ins: %EBP Predecessors according to CFG: BB#0 CALLpcrel32 <ga:@__stack_chk_fail>, <regmask>, %ESP<imp-use>, %ESP<imp-def> # End machine code for function julia_delete!_20895.
表面と裏面だけ見せて本物と信用させる、誘拐事件の身代金みたいな物と思っちゃいけないよ。 中身がびっしり詰まった正真正銘のIRですから。 その証拠(になるかな? factorなんて何処にも有りそうだから、マーカーには不適)
define %jl_value_t* @jlcall_factor_20856(%jl_value_t*, %jl_value_t**, i32) { top: %3 = getelementptr %jl_value_t** %1, i32 0 %4 = load %jl_value_t** %3 %5 = bitcast %jl_value_t* %4 to i32* %6 = load i32* %5, align 16 %7 = call %jl_value_t* @julia_factor_20856(i32 %6) ret %jl_value_t* %7 } *** IR Dump After Promote Memory to Register *** : *** IR Dump After Combine redundant instructions *** : *** IR Dump After Scalar Replacement of Aggregates (DT) *** : *** IR Dump After Combine redundant instructions *** : *** IR Dump After Jump Threading *** : : *** IR Dump After Aggressive Dead Code Elimination *** define %jl_value_t* @jlcall_factor_20856(%jl_value_t*, %jl_value_t**, i32) { top: %3 = load %jl_value_t** %1, align 4 %4 = bitcast %jl_value_t* %3 to i32* %5 = load i32* %4, align 16 %6 = call %jl_value_t* @julia_factor_20856(i32 %5) ret %jl_value_t* %6 }
元のコードをマネーロンダリングと言うかクレンジングと言うかサニタイズして、似て非なるものに変換してから使うとな。 並々ならぬ努力をしてますよ。執念ですなあ。
とまあ、偉そうに分かったようなへらず口を叩いておりますが、オイラーは正真正銘の LLVM童貞であります。どこかの怪しげな所に寄って、童貞とおさらばしましょ。
LLVM フレームワークで実用的なコンパイラーを作成する: 第 1 回
#JuliaLang ていすいじゅん?の話(LLVM IRとNative code 触りだけ)
LLVM + clang で LLVM IR やアセンブリを出力する
LLVM 言語マニュアル(Language Reference Manual)
LLVM Tutorial: Table of Contents
LLVMによるプログラミング言語の実装 上記の翻訳版?
flisp
またちょっと違った方向から眺めてみます。LLVMで必要なIR語を出力するための 第一歩として、juliaではflispが使われているとの事。抽象構文木(AST)とかを 出すんですなあ。
juliaをdebug buildしたんで、flispも -debug付きで作成されています。それを まず走らせてから、lulia側で用意したフロントエンドスクリプトを読み込みます。 後は、julia語を入力して、ASTを観察。
$ flisp/flisp-debug ; _ ; |_ _ _ |_ _ | . _ _ ; | (-||||_(_)|__|_)|_) ;-------------------|---------------------------------------------------------- > (load "jlfrontend.scm") #fn("7000r1e0e1|3141;" [expand-toplevel-expr julia-parse] fe) > (jl-parse-string "1 + 3") (call + 1 3) > (jl-parse-string "f(x) = 2x") (= (call f x) (block (line 1 none) (call * 2 x))) > (jl-parse-string "x = 1234") (= x 1234)
次は実例っぽく、以前に作ったオイラーのjulia語から。
> (jl-parse-string "macro em(f) return :( emacs($f) ) end ") (macro (call em f) (block (line 2 /home/sakae/.juliarc.jl) (return '(call emacs ($ f))))) > (jl-parse-string "function emacs(m::Method) tv, decls, file, line = arg_decl_parts(m) emacs(string(file), line) end ") (function (call emacs (:: m Method)) (block (line 2 /home/sakae/.juliarc.jl) (= (tuple tv decls file line) (call arg_decl_parts m)) (line 3 /home/sakae/.juliarc.jl) (call emacs (call string file) line)))
> (jl-parse-string "import Base: find_in_path, find_source_file, function_module, functionloc") (toplevel (import Base find_in_path) (import Base find_source_file) (import Base function_module) (import Base functionloc))
> (jl-parse-string "emacs(file::AbstractString) = emacs(file, 1) emacs(f) = emacs(functionloc(f)...) emacs(f, t::ANY) = emacs(functionloc(f,t)...) emacs(file, line::Integer) = emacs(file, line) ") (toplevel (= (call emacs (:: file AbstractString)) (block (line 1 /home/sakae/.juliarc.jl) (call emacs file 1))) (= (call emacs f) (block (line 2 /home/sakae/.juliarc.jl) (call emacs (... (call functionloc f))))) (= (call emacs f (:: t ANY)) (block (line 3 /home/sakae/.juliarc.jl) (call emacs (... (call functionloc f t))))) (= (call emacs file (:: line Integer)) (block (line 4 /home/sakae/.juliarc.jl) (call emacs file line))))
flispと来たら中身を見ておきたい。ソースの構成がsrc/flisp/ってなってて、flisp本体は、 flisp-dir内に、flispのアプリである *.scm 類は、srcの直下に置いてあるんで、scmを flisp内に移動。そこでetagsを実行。
$ etags *.[ch] *.lsp *.scm
こんな事をやって、3種混合ワクチンならぬ、3種混合TAGSを生成。これで、flispの ネイティブ実装、lispで書かれたlisp拡張、julia様ご要求のLLVM用フロントエンドである scm類が一発で引けるぞ。
ああ、flisp類はjuliaから独立してる訳ではなく、julia生成の途中で、libflisp.aに なってjuliaに組み込まれている。
そしてflisp側とJulia側とのデータ交換は、ast.c内にある、julia_to_scmとscm_to_juliaが 担当してるようだ。 同ソース内に、
// this is used to parse a line of repl input DLLEXPORT jl_value_t *jl_parse_input_line(const char *str, size_t len) { value_t s = cvalue_static_cstrn(str, len); value_t e = fl_applyn(1, symbol_value(symbol("jl-parse-string")), s); if (e == FL_EOF) return jl_nothing; return scm_to_julia(e,0); }
上でオイラーが、flispから呼んで実験してたのが、ここでjulia側のreplから使われて いるんだな。
juliaとflispの癒着にはflisp側に用意したapplyが使われているとな。flisp側で実行 したい手続きは、文字列をシンボルにして渡す。手続きの引数もflisp側に馴染むように して渡す。返ってきた結果はflisp色に染まっているから、julia側で使えるように変換 してる。
それにしてもapplyとは名手だな。さすがMITはLisperの巣窟だな。こういう所に センスが出てるよ。
ついでなんで、どんな手続きをjulia側から呼んでるか、調べておく。
$ grep 'jl-' *.[ch] *.cpp ast.c: value_t e = fl_applyn(1, symbol_value(symbol("jl-parse-string")), s); ast.c: value_t p = fl_applyn(3, symbol_value(symbol("jl-parse-one-string")), ast.c: if (fl_applyn(1, symbol_value(symbol("jl-parse-file")), s) == FL_F) ast.c: fl_applyn(0, symbol_value(symbol("jl-parser-close-stream"))); ast.c: value_t prev = fl_applyn(1, symbol_value(symbol("jl-parser-depwarn")), ast.c: value_t prev = fl_applyn(1, symbol_value(symbol("jl-parser-deperror")), ast.c: value_t c = fl_applyn(0, symbol_value(symbol("jl-parser-next"))); ast.c: jl_lineno = numval(fl_applyn(0, symbol_value(symbol("jl-parser-current-lineno")))); ast.c: fl_applyn(2, symbol_value(symbol("jl-parse-string-stream")), t, f); ast.c: value_t e = fl_applyn(1, symbol_value(symbol("jl-expand-to-thunk")), arg); ast.c: value_t e = fl_applyn(1, symbol_value(symbol("jl-macroexpand")), arg);
lisp側の関数名は、キャメルケースでもなくスネークケースでもなく、ハイフォンで 単語を繋ぎ合せる記法なんで、こういう時は楽だ。ついでに、入力も楽で非常に宜しい!!
マクロ展開なんてのも有るね。と言う事はjulia側からも使えるんだろうね。いろいろ 予想が出来て楽しいな。
flispのreplが起動した所を記念撮影。何せjulia観光のオプションツアーですから。
(gdb) bt #0 0x2826ee1f in _read () from /lib/libc.so.7 #1 0x280fba1d in ?? () from /lib/libthr.so.3 #2 0x0806fecc in _os_read (fd=0, buf=0x2880e000, n=131072, nread=0xbfbfe088) at ios.c:95 #3 0x08070760 in _ios_read (s=0x2880c020, dest=0xbfbfe12b "\b\244\261JEQ\216\r200\030\021(\205", n=1, all=0) at ios.c:295 #4 0x08070821 in ios_read (s=0x2880c020, dest=0xbfbfe12b "\b\244\261JEQ\216\r(\00\030\021(\205", n=1) at ios.c:313 #5 0x08072d2f in ios_getc (s=0x2880c020) at ios.c:1003 #6 0x0805ab93 in nextchar () at read.c:138 #7 0x0805aeaa in peek () at read.c:215 #8 0x0805c1b4 in do_read_sexpr (label=1) at read.c:587 #9 0x0805c81e in fl_read_sexpr (f=679940237) at read.c:712 #10 0x08068adb in fl_read (args=0x2897d090, nargs=0) at iostream.c:125 #11 0x0805ee7a in apply_cl (nargs=0) at flisp.c:1226 #12 0x0805e100 in do_trycatch () at flisp.c:950 #13 0x08062437 in apply_cl (nargs=0) at flisp.c:1856 #14 0x0805e100 in do_trycatch () at flisp.c:950 #15 0x08062437 in apply_cl (nargs=0) at flisp.c:1856 #16 0x08059e1a in _applyn (n=1) at flisp.c:729 #17 0x0805a089 in fl_applyn (n=1, f=679950938) at flisp.c:774 #18 0x0806b153 in main (argc=1, argv=0xbfbfebdc) at flmain.c:54
つらつらとほっつき歩いていたら、緒言にぶち当たったので、記録を 残して、旅の思い出とする。本当は、沖縄あたりに旅したいんだけど。。。
/* femtoLisp a compact interpreter for a minimal lisp/scheme dialect characteristics: * lexical scope, lisp-1 * unrestricted macros * data types: 30-bit integer, symbol, pair, vector, char, string, table iostream, procedure, low-level data types * case-sensitive * simple compacting copying garbage collector * Scheme-style varargs (dotted formal argument lists) * "human-readable" bytecode with self-hosted compiler extra features: * circular structure can be printed and read * #. read macro for eval-when-read and readably printing builtins * read macros for backquote * symbol character-escaping printer * exceptions * gensyms (can be usefully read back in, too) * #| multiline comments |#, lots of other lexical syntax * generic compare function, cyclic equal * cvalues system providing C data types and a C FFI * constructor notation for nicely printing arbitrary values by Jeff Bezanson (C) 2009 Distributed under the BSD License */
最後にflispがどんな風にコンパイルされるかLOGから抜粋しておく
$ grep -C 12 libflisp LOG CC src/support/libsupportinit.dbg.obj CC src/support/arraylist.dbg.obj CC src/support/strtod.dbg.obj LINK src/support/libsupport-debug.a CC src/flisp/flisp.dbg.obj CC src/flisp/builtins.dbg.obj CC src/flisp/string.dbg.obj CC src/flisp/equalhash.dbg.obj CC src/flisp/table.dbg.obj CC src/flisp/iostream.dbg.obj CC src/flisp/julia_extensions.dbg.obj LINK src/flisp/libflisp-debug.a CC src/flisp/flmain.dbg.obj LINK src/flisp/flisp-debug FLISP src/julia_flisp.boot FLISP src/julia_flisp.boot.inc CC src/ast.dbg.obj CC src/builtins.dbg.obj CC src/module.dbg.obj CC src/codegen.dbg.obj CC src/disasm.dbg.obj CC src/debuginfo.dbg.obj CC src/interpreter.dbg.obj CC src/alloc.dbg.obj
続きをちょっと眺めると
CC src/gc.dbg.obj LINK usr/lib/libjulia-debug.so CC ui/repl.dbg.obj LINK usr/bin/julia-debug PERL base/pcre_h.jl PERL base/errno_h.jl PERL base/build_h.jl.phony PERL base/fenv_constants.jl PERL base/file_constants.jl PERL base/uv_constants.jl JULIA usr/lib/julia/inference0.ji essentials.jl reflection.jl
julia_flisp.bootとかは、何じゃらホイって事で調べてみると、
$ grep julia_flisp.boot Makefile $(BUILDDIR)/julia_flisp.boot.inc: $(BUILDDIR)/julia_flisp.boot $(FLISP_EXECUTABLE) export julia_flisp_boot=$(BUILDDIR)/julia_flisp.boot $(julia_flisp_boot): julia-parser.scm julia-syntax.scm \ match.scm utils.scm jlfrontend.scm mk_julia_flisp_boot.scm $(FLISP_EXECUTABLE) @$(call PRINT_FLISP, $(call spawn,$(FLISP_EXECUTABLE)) ./mk_julia_flisp_boot.scm) $(BUILDDIR)/ast.o $(BUILDDIR)/ast.dbg.obj: $(BUILDDIR)/julia_flisp.boot.inc flisp/*.h -rm -f $(BUILDDIR)/julia_flisp.boot $(BUILDDIR)/julia_flisp.boot.inc
んでもって、mk_julia_flisp_boot.scmが気になって調べると
$ cat mk_julia_flisp_boot.scm (load "jlfrontend.scm") (make-system-image (os.getenv "julia_flisp_boot"))
んでもって、make-system-imageなんてのを調べると、動いてるflispを生きたまま 保存する、普通のlispが持ってる種の保存機能でしたよ。この機能はテスト時にでも 使うのかな? いくら調べても終る事が無いので、これぐらにしておこう。