target triple = "x86_64-pc-linux-gnu" declare i8* @malloc(i64) declare i64 @printf(i8*, ...) @printf_d = private unnamed_addr constant [3 x i8] c"%d\00", align 1 @printf_c = private unnamed_addr constant [3 x i8] c"%c\00", align 1 @printf_cycle = private unnamed_addr constant [16 x i8] c"cycle in spine\0a\00", align 1 attributes #0 = { alwaysinline } define private i64* @_alloc_heap(i64 %n) alwaysinline { %s.0 = alloca i64 %s.1 = getelementptr i64, i64* %s.0, i64 1 %s.0.0 = ptrtoint i64* %s.0 to i64 %s.1.0 = ptrtoint i64* %s.1 to i64 %s.2 = sub i64 %s.1.0, %s.0.0 %s.3 = mul i64 %s.2, %n %r.0 = call i8* @malloc(i64 %s.3) %r.1 = bitcast i8* %r.0 to i64* ret i64* %r.1 } define private i64** @_alloc_a_stack(i64 %n) alwaysinline { %s.0 = alloca i64* %s.1 = getelementptr i64*, i64** %s.0, i64 1 %s.0.0 = ptrtoint i64** %s.0 to i64 %s.1.0 = ptrtoint i64** %s.1 to i64 %s.2 = sub i64 %s.1.0, %s.0.0 %s.3 = mul i64 %s.2, %n %r.0 = call i8* @malloc(i64 %s.3) %r.1 = bitcast i8* %r.0 to i64** ret i64** %r.1 } define private i64** @_push_local_astack(i64** %asp.0, i64** %aspstart, i64** %globasp.0) #0 { entry: br label %loop loop: %asp = phi i64** [%asp.0, %entry], [%asp.1, %loop.0] %globasp = phi i64** [%globasp.0, %entry], [%globasp.1, %loop.0] %t.0 = icmp eq i64** %asp, %aspstart br i1 %t.0, label %done, label %loop.0 done: ret i64** %globasp loop.0: %globasp.1 = getelementptr i64*, i64** %globasp, i64 1 %n = load i64*, i64** %asp store i64* %n, i64** %globasp.1 %asp.1 = getelementptr i64*, i64** %asp, i64 -1 br label %loop } ; TODO remove only the used positions define private void @_cleanup_global_astack(i64** %globasp.0) noinline optnone { %globasp.0.1 = getelementptr i64*, i64** %globasp.0, i64 1 %globasp.0.2 = getelementptr i64*, i64** %globasp.0, i64 2 %globasp.0.3 = getelementptr i64*, i64** %globasp.0, i64 3 %globasp.0.4 = getelementptr i64*, i64** %globasp.0, i64 4 %globasp.0.5 = getelementptr i64*, i64** %globasp.0, i64 5 store i64* undef, i64** %globasp.0.1 store i64* undef, i64** %globasp.0.2 store i64* undef, i64** %globasp.0.3 store i64* undef, i64** %globasp.0.4 store i64* undef, i64** %globasp.0.5 ret void } define private i64* @addI(i64* %bsp.0) #0 { %t.0 = load i64, i64* %bsp.0 store i64 undef, i64* %bsp.0 %bsp.1 = getelementptr i64, i64* %bsp.0, i64 1 %t.1 = load i64, i64* %bsp.1 %t.2 = add i64 %t.0, %t.1 store i64 %t.2, i64* %bsp.1 ret i64* %bsp.1 } ; TODO gc ; TODO for arity < 2, we must reserve more space on the heap define private {i64**,i64*} @build(i64* %label, i64 %arity, i64** %asp.0, i64** %aspstart, i64** %globasp.0, i64* %hp.0) #0 { entry: %label.0 = ptrtoint i64* %label to i64 store i64 %label.0, i64* %hp.0 %hp.1 = getelementptr i64, i64* %hp.0, i64 1 br label %loop loop: %asp.1 = phi i64** [%asp.0, %entry], [%asp.2, %loop.0] %hp.2 = phi i64* [%hp.1, %entry], [%hp.3, %loop.0] %arity.0 = phi i64 [%arity, %entry], [%arity.1, %loop.0] %t.0 = icmp eq i64 %arity.0, 0 br i1 %t.0, label %done, label %loop.0 done: %asp.3 = getelementptr i64*, i64** %asp.1, i64 1 store i64* %hp.0, i64** %asp.3 %ret.0 = insertvalue {i64**,i64*} undef, i64** %asp.3, 0 %ret.1 = insertvalue {i64**,i64*} %ret.0, i64* %hp.2, 1 ret {i64**,i64*} %ret.1 loop.0: %t.1 = call i64* @peek_a(i64** %asp.1) %asp.2 = call i64** @pop_a1(i64** %asp.1) %t.2 = ptrtoint i64* %t.1 to i64 store i64 %t.2, i64* %hp.2 %hp.3 = getelementptr i64, i64* %hp.2, i64 1 %arity.1 = sub i64 %arity.0, 1 br label %loop } ; TODO pass aspstart for gc define private {i64**,i64*} @buildI(i64 %i, i64** %asp.0, i64* %hp.0) #0 { %INT.0 = ptrtoint {i64, i64, i64*, i64, i8, i8, i8}* @INT to i64 %INT.1 = add i64 %INT.0, 2 store i64 %INT.1, i64* %hp.0 %hp.1 = getelementptr i64, i64* %hp.0, i64 1 store i64 %i, i64* %hp.1 %asp.1 = getelementptr i64*, i64** %asp.0, i64 1 store i64* %hp.0, i64** %asp.1 %hp.2 = getelementptr i64, i64* %hp.0, i64 2 %ret.0 = insertvalue {i64**,i64*} undef, i64** %asp.1, 0 %ret.1 = insertvalue {i64**,i64*} %ret.0, i64* %hp.2, 1 ret {i64**,i64*} %ret.1 } define private i64* @eqI_b(i64 %i, i64 %n, i64* %bsp.0) #0 { %bsp.1 = getelementptr i64, i64* %bsp.0, i64 %n %bsp.2 = getelementptr i64, i64* %bsp.0, i64 -1 %t.0 = load i64, i64* %bsp.1 %t.1 = icmp eq i64 %t.0, %i %t.2 = zext i1 %t.1 to i64 store i64 %t.2, i64* %bsp.2 ret i64* %bsp.2 } define private i64** @fillI_b(i64 %b_offset, i64 %a_offset, i64* %bsp.0, i64** %asp.0) #0 { %bsp.1 = getelementptr i64, i64* %bsp.0, i64 %b_offset %t.0 = load i64, i64* %bsp.1 %asp.1 = getelementptr i64*, i64** %asp.0, i64 %a_offset %n.0 = load i64*, i64** %asp.1 %INT.0 = ptrtoint {i64, i64, i64*, i64, i8, i8, i8}* @INT to i64 %INT.1 = add i64 %INT.0, 2 store i64 %INT.1, i64* %n.0 %n.1 = getelementptr i64, i64* %n.0, i64 1 store i64 %t.0, i64* %n.1 ret i64** %asp.0 } define private i64* @jsr_eval(i64 %n, i64** %asp.0, i64** %aspstart, i64** %globasp.0, i64* %hp.0) #0 { %asp.1 = getelementptr i64*, i64** %asp.0, i64 %n %n.0 = load i64*, i64** %asp.1 %d.0 = load i64, i64* %n.0 %t.0 = and i64 %d.0, 2 %t.1 = icmp eq i64 %t.0, 0 br i1 %t.1, label %eval, label %done done: ret i64* %hp.0 eval: %globasp.1 = call i64** @_push_local_astack(i64** %asp.0, i64** %aspstart, i64** %globasp.0) %nentry.0 = inttoptr i64 %d.0 to {i64*, i64*} (i64*, i64**, i64*)* %t.2 = call {i64*, i64*} %nentry.0(i64* %hp.0, i64** %globasp.1, i64* %n.0) call void @_cleanup_global_astack(i64** %globasp.0) %hp.1 = extractvalue {i64*, i64*} %t.2, 0 %n.1 = extractvalue {i64*, i64*} %t.2, 1 store i64* %n.1, i64** %asp.1 ret i64* %hp.1 } define private i64* @ltI(i64* %bsp.0) #0 { %t.0 = load i64, i64* %bsp.0 store i64 undef, i64* %bsp.0 %bsp.1 = getelementptr i64, i64* %bsp.0, i64 1 %t.1 = load i64, i64* %bsp.1 %t.2 = icmp slt i64 %t.0, %t.1 %t.3 = zext i1 %t.2 to i64 store i64 %t.3, i64* %bsp.1 ret i64* %bsp.1 } define private i64** @pop_a1(i64** %asp.0) #0 { store i64* undef, i64** %asp.0 %asp.1 = getelementptr i64*, i64** %asp.0, i64 -1 ret i64** %asp.1 } define private i64* @pop_b1(i64* %bsp.0) #0 { store i64 undef, i64* %bsp.0 %bsp.1 = getelementptr i64, i64* %bsp.0, i64 1 ret i64* %bsp.1 } define private i64* @print_int(i64* %bsp.0) #0 { %t.0 = load i64, i64* %bsp.0 store i64 undef, i64* %bsp.0 call i64 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @printf_d, i64 0, i64 0), i64 %t.0) %bsp.1 = getelementptr i64, i64* %bsp.0, i64 1 ret i64* %bsp.1 } define private i64** @push_a(i64 %n, i64** %asp.0) #0 { %asp.1 = getelementptr i64*, i64** %asp.0, i64 %n %t.0 = load i64*, i64** %asp.1 %asp.2 = getelementptr i64*, i64** %asp.0, i64 1 store i64* %t.0, i64** %asp.2 ret i64** %asp.2 } define private i64* @push_b(i64 %n, i64* %bsp.0) #0 { %bsp.1 = getelementptr i64, i64* %bsp.0, i64 %n %t.0 = load i64, i64* %bsp.1 %bsp.2 = getelementptr i64, i64* %bsp.0, i64 -1 store i64 %t.0, i64* %bsp.2 ret i64* %bsp.2 } define private i64** @push_node(i64* %label, i64 %arity, i64** %asp.0) #0 { entry: %n.0 = load i64*, i64** %asp.0 %label.0 = ptrtoint i64* %label to i64 store i64 %label.0, i64* %n.0 br label %loop loop: %asp.1 = phi i64** [%asp.0, %entry], [%asp.2, %loop.0] %arity.0 = phi i64 [%arity, %entry], [%arity.1, %loop.0] %t.0 = icmp eq i64 %arity.0, 0 br i1 %t.0, label %done, label %loop.0 done: ret i64** %asp.1 loop.0: %n.1 = getelementptr i64, i64* %n.0, i64 %arity.0 %n.2 = load i64, i64* %n.1 %n.3 = inttoptr i64 %n.2 to i64* %asp.2 = getelementptr i64*, i64** %asp.1, i64 1 store i64* %n.3, i64** %asp.2 %arity.1 = sub i64 %arity.0, 1 br label %loop } define private i64* @pushI(i64 %i, i64* %bsp.0) #0 { %bsp.1 = getelementptr i64, i64* %bsp.0, i64 -1 store i64 %i, i64* %bsp.1 ret i64* %bsp.1 } define private i64* @pushI_a(i64 %n, i64* %bsp.0, i64** %asp.0) #0 { %asp.1 = getelementptr i64*, i64** %asp.0, i64 %n %n.0 = load i64*, i64** %asp.1 %n.1 = getelementptr i64, i64* %n.0, i64 1 %t.0 = load i64, i64* %n.1 %bsp.1 = getelementptr i64, i64* %bsp.0, i64 -1 store i64 %t.0, i64* %bsp.1 ret i64* %bsp.1 } define private i64* @subI(i64* %bsp.0) #0 { %t.0 = load i64, i64* %bsp.0 store i64 undef, i64* %bsp.0 %bsp.1 = getelementptr i64, i64* %bsp.0, i64 1 %t.1 = load i64, i64* %bsp.1 %t.2 = sub i64 %t.0, %t.1 store i64 %t.2, i64* %bsp.1 ret i64* %bsp.1 } define private i64* @update_b(i64 %n1, i64 %n2, i64* %bsp.0) #0 { %bsp.1 = getelementptr i64, i64* %bsp.0, i64 %n1 %t.0 = load i64, i64* %bsp.1 %bsp.2 = getelementptr i64, i64* %bsp.0, i64 %n2 store i64 %t.0, i64* %bsp.2 ret i64* %bsp.0 } define private i64* @updatepop_b01(i64* %bsp.0) #0 { %t.0 = load i64, i64* %bsp.0 store i64 undef, i64* %bsp.0 %bsp.1 = getelementptr i64, i64* %bsp.0, i64 1 store i64 %t.0, i64* %bsp.1 ret i64* %bsp.1 } define private i64* @peek_a(i64** %asp) #0 { %t = load i64*, i64** %asp ret i64* %t } define private i64 @peek_b(i64* %bsp) #0 { %t = load i64, i64* %bsp ret i64 %t } @INT = constant {i64, i64, i64*, i64, i8, i8, i8} {i64 0, i64 0, i64* inttoptr (i64 0 to i64*), i64 3, i8 73, i8 78, i8 84}, align 8 define {i64*,i64*} @_cycle_in_spine(i64** %globasp, i64* %hp.0) align 8 prefix {i8*, i64} {i8* inttoptr (i64 0 to i8*), i64 0} { call i64 (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @printf_cycle, i64 0, i64 0)) unreachable }