2016-03-13 21 views
0

這是我的程序全部;我使用的是一個愚蠢的遞歸算法與LLVM組件,以自己熟悉:什麼是在LLVM組件中進行遞歸的正確方法?

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) 
} 

當我編譯這個程序與$ llvm-as rec_add.ll,我收到此錯誤信息:

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

我不明白這是什麼錯誤消息意味着,因爲我的程序沒有全局變量。而且我知道LLVM彙編不需要指針作爲參數。

+2

我不知道LLVM彙編,但你確定你不需要在那裏'調用',可能作爲另一種說法?否則,它看起來像你試圖返回的功能,除了間接通過指針,你不能這樣做。 –

+0

@RossRidge:IDK LLVM asm,但這似乎沒有工作沒有臨時代碼gen沒有不良影響。很好地捕捉到缺少的「呼叫」。我同意OP的語法可能試圖返回一個函數指針。 –

回答

1

我什至不知道llvm-存在,但將遞歸調用結果分配給一個工作變量。然後返回。這甚至在-O0優化。有關正確的術語,請參閱Oak的回答/評論。

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 
} 

編譯爲遞歸調用clang-3.8 -O0 -S -o-

隨着clang-3.8 -Wall -O3 rec-add.ll -S -masm=intel -o-,LLVM穿透了遞歸:

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

main不會編譯:

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

該做的伎倆:

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

如果我刪除變量並將'ret i32 0'(返回0)添加到最後,我的'main'編譯。 – EMBLEM

+1

Downvoting,因爲雖然這是正確的,但您的術語和解釋已關閉,這可能會造成混淆。 '%tmp'不是一個臨時的,它是一條指令 - 無論如何,問題是一起使用'ret'和'call',而不是缺少「使用臨時」,請參閱我的答案。 – Oak

+0

@Oak:感謝術語更正。反覆試驗並不是我的答案的通常基礎:P –

2

不像高層語言,LLVM指令不能由複合表達式組成。因此,這不是一個有效的指令:

ret i32 @rec_add(i32 %tmp2, i32 %tmp3) 

您可以做retcall,不能同時在一次*。你在這裏實際寫的是試圖返回該函數的地址 - 這當然不是i32,因此類型錯誤。相反,你需要做的是這樣的:

%something = call i32 @rec_add(i32 %tmp2, i32 %tmp3) 
ret i32 %something 



*那麼你可以做複合的東西,如果這些都是constant expressions,但這裏並非如此。

相關問題