Scheme Compiler の勉強(27) - cons?

※以下根本的な嘘、勘違いが含まれる可能性大。

  • cons, car, cdr を LLVM IR 直書きでテストした。(自作のS式表現が、グローバル変数の宣言に対応していなかったので仕方なく直に書いた‥)
  • メモリを malloc で確保して、その位置をグローバル変数に確保しておく
  • 今のコンパイラには、32ビット(i32) で何でも表現する世界。ただし後ろの3ビットはタグに使う。
  • cons は二つの i32 型の値を受け取り、i32 型の値を返す。
  • 現在の allocation pointer の場所に一つ目の値を格納。4byte を使う
  • allocation pointer を4つ進めて、そこに二つ目の値を格納。
  • allocation pointer を4つ進める

うーん。一応動いているようだけど根本的に間違えている恐れが抜けない。cons, car, cdr みたいな、セットとして実装しないとどこが間違っているか分からない構造って嫌だなぁ。
(そもそもGC とか気にしなくていいんだろうか。)

@alloc_ptr = global i32 0

define internal void @print_alloc_ptr() nounwind  {
       %tmp = load i32* @alloc_ptr
       call void @print_ptr(i32 %tmp) nounwind
       ret void
}

define i32 @cons(i32 %car, i32 %cdr) {
       %t1 = load i32* @alloc_ptr
       %ptr1 = inttoptr i32 %t1 to i32*
       store i32 %car, i32* %ptr1

       %t2 = add i32 4, %t1
       store i32 %t2, i32* @alloc_ptr

       %t3 = load i32* @alloc_ptr
       %ptr2 = inttoptr i32 %t3 to i32*
       store i32 %cdr, i32* %ptr2
       
       ;; increment %alloc_ptr by 
       %t4 = add i32 4, %t3 ;
       store i32 %t4, i32* @alloc_ptr

       ret i32 %t1
}

define i32 @car(i32 %x) {
       %ptr = inttoptr i32 %x to i32*
       %t1 = load i32* %ptr
       ret i32 %t1
}

define i32 @cdr(i32 %x) {
       %t2 = add i32 4, %x
       %t3 = inttoptr i32 %t2 to i32*
       %t4 = load i32* %t3
       ret i32 %t4
}

define i32 @main() {
       %array = malloc [ 1024 x i32 ] ; heap
       ; init allocation pointer
       ; 初期化
       ;%alloc_ptr = malloc i32
       %ap = ptrtoint [ 1024 x i32 ] * %array to i32
       store i32 %ap, i32* @alloc_ptr
       ;          call void @print_alloc_ptr() nounwind

       ; 暫定的に pair-tag に一致するよう調整
       ; TODO; ちゃんと必ず pair-tag になるようにする必要あり。
       %fixap = add i32 1, %ap
       store i32 %fixap, i32* @alloc_ptr
       
       %x = call i32 @cons(i32 4, i32 12)
       call void @print_ptr(i32 %x) nounwind

       %carx = call i32 @car(i32 %x)
       call void @print_ptr(i32 %carx) nounwind
       %cdrx = call i32 @cdr(i32 %x)
       call void @print_ptr(i32 %cdrx) nounwind

       ;; list test
       ;; (cons 1 (cons 2 3))
       %x2 = call i32 @cons(i32 8, i32 12) ; (cons 2 3)
       %x1 = call i32 @cons(i32 4, i32 %x2) ; (cons 1 (cons 2 3))
       %carx1 = call i32 @car(i32 %x1)
       call void @print_ptr(i32 %carx1) nounwind

       %cdrx1 = call i32 @cdr(i32 %x1)
       call void @print_ptr(i32 %cdrx1) nounwind

       %cadrx1 = call i32 @car(i32 %cdrx1)
       call void @print_ptr(i32 %cadrx1) nounwind

       %cddrx1 = call i32 @cdr(i32 %cdrx1)
       call void @print_ptr(i32 %cddrx1) nounwind
 
       ret i32 0
}