LLVMを使い始めました。

LLVMいいですね。ドキュメントが結構書きたかった物に近くて大分落ち込みました。
最初からLLVMやっておけば良かったとか思ったりしつつ、
イヤイヤ、64bitCPU触っておくのもやっぱり大切だったと思うよと思います。
とりあえず、LLVMで四則演算するコンパイラは作れました。

きつねさんのLLVMの本が欲しいなぁ。

とりあえず、JVMバイトコードっぽいスタックマシン用コードがなぜか、いい感じに、
無限レジスタに変換されて動くってことが出来るようになりました。
え、こんなんで良いの?って思うんですけど、良いみたいです。
てことで、コレ拡張してけば、なんか、簡単にかなりいい感じのコンパイラが作れるってことがわかったのでした。

(* ASTを作る *)
val ast = EBlock([
  EPrint(ELong(1)),
  EPrint(EAdd(ELong(2), ELong(3))),
  EPrint(EMul(EAdd(ELong(2), ELong(3)),ELong(2)))]);

(* コンパイル *)
val codes = compile(ast);

(* コード出力 *)
emit("e.s", codes);

exec("llc e.s");
(* アセンブル *)
exec("llvm-gcc -m64 e.s.s -o e");
(* 実行 *)
exec("./e");

mainはこんな感じでemitがllvm対応にするだけで行けます。
http://d.hatena.ne.jp/miura1729/20090123/1232707764
がとても参考になりました。ありがとうございます。そうか、@expstackを使えば良いのか!
ってなにその、expstackってことなんですけど、ソース読んでください。

  val stack:string list ref = ref []
  fun pushq(a:string): unit = (
    stack := a :: !stack
  )
  fun popq():string = (
    case (!stack) of
      nil => raise (Error("stack is empty"))
      | x::xs => (stack := xs; x)
  )

これは、只のスタックですがとりあえず64bitオンリーなのでこれで実装で行けました。
出力コードが以下のようになってます。なんて楽なんだー。

	.section	__TEXT,__text,regular,pure_instructions
	.globl	_main
	.align	4, 0x90
_main:                                  ## @main
## BB#0:                                ## %entry
	pushq	%rax
	movl	$1, %edi
	callq	_print_l
	movl	$5, %edi
	callq	_print_l
	movl	$10, %edi
	callq	_print_l
	xorl	%eax, %eax
	popq	%rdx
	ret

	.globl	_print_l
	.align	4, 0x90
_print_l:                               ## @print_l
## BB#0:                                ## %entry
	pushq	%rax
	movq	%rdi, %rax
	movq	%rax, (%rsp)
	leaq	L_.str(%rip), %rdi
	movq	%rax, %rsi
	xorb	%al, %al
	callq	_printf
	popq	%rax
	ret

	.section	__TEXT,__const
L_.str:                                 ## @.str
	.asciz	 "%ld\n"


.subsections_via_symbols

定数式もさっぱり畳み込まれてます。すげぇな、LLVM

LLVMバージョンD言語に今なら勝てるかもしれないので頑張ってみようっと!
llcのエラーはなんか、色付いたりするんだなぁ

ここからが本当の戦いなのかもしれません。