memo

LLVM IR を S 式で表現するモジュールを試作中。これの機能はただ単純に、S 式で表現した LLVM IR を LLVM IR の文字列に変換すること。これはどこかで誰かがやってるに違いないと思うが、見つけられなかった。読み飛ばしている可能性も高いけど。

  • LLVM IR はほとんど1行1命令。例外的にラベル、関数定義のブロックあり。
  • '=' による単純な形式の代入文あり。
  • 作り直しになってもたかがしれているので「構文を完全に調査して網羅」などということは目指さず、自分の知っている範囲の LLVM IR 構文でまず動くようにする。困ったら困ったときに考える。

以下のように、S式を変換するところまでできた。

gosh> (trans-ir '(define-function i32 scheme_entry ()
		   (assign %ret (alloca i32))
		   (store (i32 4) (i32* %ret))
		   (assign %var1 (load (i32* %ret)))
		   (assign %var2 (add (i32 4 %var1)))
		   (store (i32 %var2) (i32* %ret))
		   (assign %retval (load (i32* %ret)))
		   (ret (i32 %retval))))
define i32 @scheme_entry() nounwind {
entry:
%ret = alloca i32
store i32 4, i32* %ret
%var1 = load i32* %ret
%var2 = add i32 4, %var1
store i32 %var2, i32* %ret
%retval = load i32* %ret
ret i32 %retval
}
#<undef>

変換部分では match を使用。以下はまだ未完成だけど、 match を使うのが楽しくて仕方が無い。

(define (trans-ir form)
  (match form
    (('define-function type name ((ty arg) ...) body ...)
     (emit "define ~a @~a(~a) nounwind {" type name 
	   (string-join
	    (map (cut format #f "~a ~a" <> <>) ty arg)
	    ", "))
     (emit "entry:")
     (map emit (map trans-seq body))
     (emit "}"))
    (_
     (errorf "mulformed define: ~a" form))))

;; *** store Instruction
;; (store (ty value) (ty* pointer)) => store <ty> <value>, <ty>* <pointer>
;; (store (ty value) (ty* pointer) align) => store <ty> <value>, <ty>* <pointer>, align alignment
(define-inst (store . args)
  (match args
    (((ty value) (ty* pointer))
     (format #f "store ~a ~a, ~a ~a" ty value ty* pointer))
    (((ty value) (ty* pointer) align)
     (format #f "store ~a ~a, ~a ~a, align ~a" ty value ty* pointer align))
    (_
     (errorf "mulformed: ~a" args))))