Felix Programming Language

tail calls, baby!

posted on September 26, 2009 - 05:51 PM PDT by Erick Tryzelaar

Check this out! I just got the standard felix optimizations working.

type int = "%i32";
typedef bool = 2;
fun add : int*int -> int = "%add";
fun sub : int*int -> int = "%sub";
fun eq : int*int -> bool = "%eq";
fun lnot : bool -> bool = "%lnot";
proc exit : int = "exit";

fun foo (x:int) = {
  if x == 0 do
    return 10;
  done;

  return foo (x - 1);
}

exit $ foo 2;

Which compiles down to this code:

declare void @exit(i32)

define i32 @foo(i32 %x) {
entry:
  %foo.x = alloca i32                             ; <i32*> [#uses=4]
  store i32 %x, i32* %foo.x
  br label %start_21

start_21:                                         ; preds = %_ifdoend_1, %entry
  %0 = load i32* %foo.x                           ; <i32> [#uses=1]
  %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
  %2 = icmp eq i1 %1, false                       ; <i1> [#uses=1]
  br i1 %2, label %_ifdoend_1, label %else

_ifdoend_1:                                       ; preds = %start_21
  %3 = load i32* %foo.x                           ; <i32> [#uses=1]
  %4 = sub i32 %3, 1                              ; <i32> [#uses=1]
  store i32 %4, i32* %foo.x
  br label %start_21

else:                                             ; preds = %start_21
  ret i32 10
}

define void @0() {
entry:
  %0 = call i32 @foo(i32 2)                       ; <i32> [#uses=1]
  call void @exit(i32 %0)
  ret void
}

read comments