SML# 2.0 のLLVM出力機能を使って、Hello worldをx86_64環境で動かしてみる
注意事項
とりあえずHello,worldが動く程度です。過度な期待をしないでください。
必要なもの
x86マシンでの作業
とりあえず最低限のhello worldを作りたいので、basisを使わずにHello,worldを書きます。
val puts = _import "puts" : string -> () val () = puts "hello from 64bit”;
これをSML#コンパイラでLLVM IRにコンパイルします。
$ ls hello.sml $ smlsharp -nostdpath -emit-llvm -S hello.sml hello.ll hello.sml
あとはこのhello.llからx86_64用のオブジェクトファイルを生成するだけなのですが、そのためにはSML#用のGCプラグインをビルドする必要があります。 これはSML#のソースツリーに含まれているので、以下のコマンドでビルドできます。
$ cd /path/to/smlsharp-2.0.0 $ cd src/llvm/main $ gcc $(llvm-config --cxxflags) -shared -o smlsharpgc.so SMLSharpGC.cpp
IRをこのプラグインを用いてオブジェクトファイルへとコンパイルします。
$ llc -march=x86-64 -filetype=obj -o hello.o -load=/path/to/smlsharp-2.0.0/src/llvm/main/smlsharpgc.so hello.ll $ file hello.o hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (GNU/Linux), not stripped
x86_64マシンでの作業
さきほどのhello.oをx86_64のマシンに転送して、ビルドをします。 ただ、hello.oだけではエントリポイント等が不足しているので適当に補います。
runtime.c:
/* 最低限のランタイムを定義する。とりあえずなので実装はさぼる。 */ void sml_alloc() {} void sml_control_resume() {} void sml_control_suspend() {}
entry.c:
/* SML#のエントリポイントを呼びだす。 エンポイント名はnm hlello.o | grep SMLmainで確認できる */ int main(){ _SMLmainZ(); return 0; }
で、これらをつかってビルドします。
$ gcc -o hello runtime.c hello.o entry.c
実行する。
$ ./hello hello from 64bit
ヤッターデキター。
今後やるべきことについて
動いて満足できたので、あまり継続してやるつもりはないです。
とりあえず、ちゃんとした対応するためにはSML#のランタイム(/usr/lib/smlsharp/runtime/libsmlsharp.a)のx86_64対応が必須だなぁ、という感じです。