What's the proper way to recurse in LLVM assembly?

EMBLEM

Here is my program in its entirety; I'm using a silly recursive algorithm to familiarize myself with LLVM assembly:

declare void @print_int(i32)

define i32 @rec_add(i32 %a, i32 %b) {
entry:
    %tmp1 = icmp eq i32 %a, 0
    br i1 %tmp1, label %done, label %recurse
    recurse:
        %tmp2 = sub i32 %a, 1
        %tmp3 = add i32 %b, 1
        ret i32 @rec_add(i32 %tmp2, i32 %tmp3)
    done:
        ret i32 %b
}

define i32 @main() {
    %tmp4 = i32 4;
    %tmp5 = i32 1;
    %cast = call i32 @rec_add(i32 %tmp4, i32 %tmp5)
    call void @print_int(i32 %cast)
}

When I compile this program with $ llvm-as rec_add.ll, I receive this error message:

llvm-as: rec_add.ll:10:11: error: global variable reference must have pointer type
                ret i32 @rec_add(i32 %tmp2, i32 %tmp3)
                        ^

I do not understand what this error message means, because my program has no global variables. And I know for a fact that LLVM assembly does not require pointers as its arguments.

Peter Cordes

I didn't even know llvm-as existed, but assigning the recursive call result to a variable worked. Then return that. This optimizes away even at -O0. See Oak's answer/comments for correct terminology.

define i32 @rec_add(i32 %a, i32 %b) {
entry:
    %tmp1 = icmp eq i32 %a, 0
    br i1 %tmp1, label %done, label %recurse
    recurse:
        %tmp2 = sub i32 %a, 1
        %tmp3 = add i32 %b, 1
        %tmp4 = call i32 @rec_add(i32 %tmp2, i32 %tmp3)
        ret i32 %tmp4
    done:
        ret i32 %b
}

compiles to a recursive call with clang-3.8 -O0 -S -o-.

With clang-3.8 -Wall -O3 rec-add.ll -S -masm=intel -o-, llvm sees through the recursion:

rec_add:                                # @rec_add
# BB#0:                                 # %entry
        lea     eax, [rdi + rsi]
        ret

Your main doesn't compile:

rec-add.ll:17:13: error: expected instruction opcode
    %tmp4 = i32 4;

This does the trick:

define i32 @main() {
    %cast = call i32 @rec_add(i32  4, i32 1)
    call void @print_int(i32 %cast)
    ret i32 0
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

What is proper way to call execve with arguments in assembly?

What's the proper way of calling a Win32/64 function from LLVM?

Proper way to recurse Q.Promise

What's the proper way to setup an Android PreferenceFragment?

What's the proper way to share the interface?

What's the proper way to check if a constant is defined?

What's the proper way to document callbacks with jsdoc?

What's the proper way of passing a ref to a prop?

What's the proper way to propagate .catch in promise?

What's the proper way to link to a route with parameters?

What's the proper way of Naming a class?

What's the proper way to reraise a custom exception?

What's the proper way to write a haskell function

What's the proper way of changing the color of SetDlgItemText?

What's the proper way to use Coroutines in Activity?

What's the proper way to make the AppBar fixed?

What's the proper way of using Swift's defer

What is proper LLVM header guard style?

MVVM - What's the proper way to communicate between views in WPF

What's the proper way to parse a very large JSON file in Ruby?

In BeautifulSoup, what's the proper way to use a strainer with lxml parsing?

What's the proper way to set up my path in crontab?

What's the proper way to close a piped readable stream?

What's the proper way to store this data in a MySQL schema?

What's the proper way of using property descriptors in Object.create?

What's the proper way to test multiple constructors in Junit?

What's the proper way to install NVidia drivers now?

What's the proper way to add JSP & Servlet libs to Eclipse?

What's the proper way to dispatch action inside epic?