/toy-compiler

toy compiler in ruby/llvm

Primary LanguageRuby

Try it

Only integers so far.

Builtins: + - * / = not= < > <= >= defn set! let while

ruby compile.rb '
(defn factorial (n)
  (cond
    (> n 1) (* n (factorial (- n 1)))
    1       1))

(factorial 10)'

should output:

#### unoptimized:
; ModuleID = 'test'

define i32 @main() {
  %1 = call i32 @factorial(i32 10)
  ret i32 %1
}

define i32 @factorial(i32 %__arg_n) {
  %n = alloca i32
  store i32 %__arg_n, i32* %n
  %1 = load i32* %n
  %2 = icmp sgt i32 %1, 1
  %3 = icmp ne i1 %2, i32 0
  br i1 %3, label %7, label %6

; <label>:4                                       ; preds = %13, %14, %7
  %5 = phi i32 [ %12, %7 ], [ 1, %14 ], [ 0, %13 ]
  ret i32 %5

; <label>:6                                       ; preds = %0
  br i1 true, label %14, label %13

; <label>:7                                       ; preds = %0
  %8 = load i32* %n
  %9 = load i32* %n
  %10 = sub i32 %9, 1
  %11 = call i32 @factorial(i32 %10)
  %12 = mul i32 %8, %11
  br label %4

; <label>:13                                      ; preds = %6
  br label %4

; <label>:14                                      ; preds = %6
  br label %4
}


#### optimized:
; ModuleID = 'test'

define i32 @main() {
  %1 = tail call i32 @factorial(i32 10)
  ret i32 %1
}

define i32 @factorial(i32 %__arg_n) {
  br label %tailrecurse

tailrecurse:                                      ; preds = %3, %0
  %accumulator.tr = phi i32 [ 1, %0 ], [ %5, %3 ]
  %__arg_n.tr = phi i32 [ %__arg_n, %0 ], [ %4, %3 ]
  %1 = icmp sgt i32 %__arg_n.tr, 1
  br i1 %1, label %3, label %2

; <label>:2                                       ; preds = %tailrecurse
  ret i32 %accumulator.tr

; <label>:3                                       ; preds = %tailrecurse
  %4 = sub i32 %__arg_n.tr, 1
  %5 = mul i32 %__arg_n.tr, %accumulator.tr
  br label %tailrecurse
}

#### result:
3628800