Hello,
I'm trying to get to grips with the c interface of llvm
intending to eventually develop a front end for Purebasic
Though I've hit the wall already writing an iterative Fibonacci
function.
While I think the module dump looks ok it doesn't work
for any input > 2 the function returns 2, the loop only executes once
Hopefully someone can see what the problem is from the output and the
source. Does the input ArgX require to be cast?
Cheers
module dump
verifying module
; ModuleID = 'test fib'
define fastcc i32 @fib2(i32 %ArgX) {
EntryBlock:
%A = alloca i32
%B = alloca i32
%C = alloca i32
%D = alloca i32
store i32 1, i32* %A
store i32 1, i32* %B
store i32 0, i32* %C
store i32 %ArgX, i32* %D
%cond = icmp sle i32 %ArgX, 2
br i1 %cond, label %IF, label %Else
IF: ; preds = %EntryBlock
ret i32 1
Else: ; preds = %while, %
EntryBlock
%PD = load i32* %D
%cond1 = icmp sgt i32 %PD, 2
br i1 %cond1, label %while, label %ewhile
while: ; preds = %Else
%pA = load i32* %A
%pB = load i32* %B
%addab = add i32 %pA, %pB
store i32 %addab, i32* %C
store i32 %pA, i32* %B
store i32 %addab, i32* %A
%sub = sub i32 %PD, 1
store i32 %sub, i32* %D
br label %Else
ewhile: ; preds = %Else
%CR = load i32* %C
ret i32 %CR
}
Source of function
Procedure CreateFibFunction(M.i,Context.i)
intType = LLVMInt32Type()
//Function returns an int And takes an int As the only parameter.
FunctionReturnType = LLVMFunctionType(IntType, at IntType,1,0)
//Create the fib function definition And insert it into the module M.
Fib2 = LLVMAddFunction(M, "fib2",FunctionReturnType)
//Set the function call convention To FastCall so it can utilize tail
call
LLVMSetFunctionCallConv(Fib2,#LLVMFastCallConv)
//Get a pointer To the ArgX.i And add To function...
ArgX = LLVMGetFirstParam(Fib2) // Get the arg.
LLVMSetValueName(ArgX, "ArgX") // Give it a symbolic name.
Builder = LLVMCreateBuilderInContext(Context)
BB = LLVMAppendBasicBlockInContext(Context, Fib2, "EntryBlock")
//Entry
LLVMPositionBuilderAtEnd(Builder, BB)
//Protected a,b,c
//a=1:b=1:c=0:d=argx
A = LLVMBuildAlloca(Builder, IntType,"A")//
B = LLVMBuildAlloca(Builder, IntType,"B")//
C = LLVMBuildAlloca(Builder, IntType,"C")//
D = LLVMBuildAlloca(Builder, IntType,"D")//
One = LLVMConstInt(IntType, 1, 0)
LLVMBuildStore(Builder,One,A)//
LLVMBuildStore(Builder,One,B)//
Zero = LLVMConstInt(IntType, 0, 0)
LLVMBuildStore(Builder,Zero,C)
LLVMBuildStore(Builder,ArgX,D)
//If argx <= 2 : Return 1 : Goto Else
IFBB = LLVMAppendBasicBlockInContext(Context, Fib2, "IF")
ElseBB = LLVMAppendBasicBlockInContext(Context, Fib2, "Else")
Two = LLVMConstInt(IntType, 2, 0)
CondInst = LLVMBuildICmp(Builder, #LLVMIntSLE, ArgX,Two, "cond")
LLVMBuildCondBr(Builder, CondInst, IFBB, ElseBB)
//If
LLVMPositionBuilderAtEnd(Builder, IFBB)
LLVMBuildRet(Builder,One)
//Else
LLVMPositionBuilderAtEnd(Builder, ElseBB)
WhileBB = LLVMAppendBasicBlockInContext(Context, Fib2, "while")
EWhileBB = LLVMAppendBasicBlockInContext(Context, Fib2, "ewhile")
// While argx > 2
PD = LLVMBuildLoad(Builder,D,"PD")//
CondInst1 = LLVMBuildICmp(Builder, #LLVMIntSGT, PD, Two, "cond1")
LLVMBuildCondBr(Builder, CondInst1, WhileBB, EWhileBB)
//WhileBB
LLVMPositionBuilderAtEnd(Builder, WhileBB)
//c = a + b//
//b = a//
//a = c//
//argx-1//
PA = LLVMBuildLoad(Builder,A,"pA")//
PB = LLVMBuildLoad(Builder,B,"pB")//
AddAB = LLVMBuildAdd(Builder,PA,PB,"addab")
LLVMBuildStore(Builder,AddAB,C)//
LLVMBuildStore(Builder,PA,B)//
LLVMBuildStore(Builder,AddAB,A)//
sub = LLVMBuildSub(Builder,PD,One,"sub")
LLVMBuildStore(Builder,sub,D)//
LLVMBuildBr(Builder,ElseBB)//
//Ewhile
LLVMPositionBuilderAtEnd(Builder, EWhileBB)
CR = LLVMBuildLoad(Builder,C,"CR")//
//ProcedureReturn C
LLVMBuildRet(Builder, CR)
//Don't forget to free the builder.
LLVMDisposeBuilder(Builder)
//Return the function ref
ProcedureReturn Fib2
EndProcedure
--
Andrew Ferguson