J'ai essayé de faire un processus itératif de Fibonacci et je ne suis pas sûr de ce que le problème est.
Je suis à une perte complète comment sous une d'elle, puis on assigne aux Arg1%?
Alors j'ai ajouté un D local pour stocker les ArgX sorte qu'il peut être chargé et stocké
mais il ne s'exécute que les boucles une fois la procédure retourne toujours 2 pour l'entrée de plus de 2
Voici la sortie de la fonction de mise, il est assez facile à suivre et ressemble à ça devrait fonctionner
I tried to do an iterative Fibonacci and I'm not sure what the problem is.
but it only executes the loops once and the procedure always returns 2 for input larger than 2
Here's the out put of the function, it's easy enough to follow and looks like it should work
Code : Tout sélectionner
; Fibonacci function executed by JIT.
; Origonal c example from llvm fibonaci example
;
; Author idle - a hack To see how llvm works
; Shows How to create a llvm module in memory
; Build a Function
; Create a Function optimizer
; Dump the module To byte code
; Load the byte code file and produce native object code
;
; The fib function calulates the number of factors
;
; Procedure fib(argx.i)
; If argx<=2
; ProcedureReturn 1
; Else
; ProcedureReturn fib(argx-1)+fib(argx-2)
; EndIf
; EndProcedure
;
; Once we have this, we compile the module via JIT, then execute the `fib'
; function And Return result To a driver, i.e. To a "host program".
;===----------------------------------------------------------------------===''
IncludeFile "llvm-2.8.pbi"
;dirty helper to read var arg strings
Procedure.s ReadVarString(*chr)
Protected strout.s,tmp.s
Protected *mem
*mem = *chr
If *mem > 64000
Repeat
tmp = PeekS(*chr+ct)
If tmp <> ""
strout+tmp+#LF$
Else
Break
EndIf
ct+Len(tmp)+1
ForEver
EndIf
ProcedureReturn strout
EndProcedure
Procedure fibPB(argx.i)
If argx<=2
ProcedureReturn 1
Else
ProcedureReturn fibPB(argx-1)+fibPB(argx-2)
EndIf
EndProcedure
Procedure fibPB2(argx.i)
Protected a,b,c
If argx <= 2
ProcedureReturn 1
Else
a = 1
b = 1
While argx > 2
c = a + b;
b = a;
a = c;
argx-1;
Wend
ProcedureReturn c
EndIf
EndProcedure
Procedure CreateFibFunction(M.i,Context.i)
Protected FunctionReturnType
Protected IntType
;Procedure.i fib(x.i)
;function only uses and int type, create an int type.
intType = LLVMInt32Type()
;Function returns an int And takes an int as the only parameter.
FunctionReturnType = LLVMFunctionType(IntType,@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)
;Add a basic block To the function.
BB = LLVMAppendBasicBlockInContext(Context, Fib2, "EntryBlock")
;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.
;When using the C bindings, you have to use a BuilderRef To create any instructions.
Builder = LLVMCreateBuilderInContext(Context)
;Set the builder to insert at the first BasicBlock.
LLVMPositionBuilderAtEnd(Builder, BB)
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)
;Create and build the conditional branch "if argX <= 2"
IFBB = LLVMAppendBasicBlockInContext(Context, Fib2, "IF")
;Create two blocks for the Branches If argx<=2 : RetBB : else : RecurseBB
ElseBB = LLVMAppendBasicBlockInContext(Context, Fib2, "Else")
Two = LLVMConstInt(IntType, 2, 0)
CondInst = LLVMBuildICmp(Builder, #LLVMIntSLE, ArgX,Two, "cond")
LLVMBuildCondBr(Builder, CondInst, IFBB, ElseBB)
LLVMPositionBuilderAtEnd(Builder, IFBB)
LLVMBuildRet(Builder,One)
LLVMPositionBuilderAtEnd(Builder, ElseBB)
WhileBB = LLVMAppendBasicBlockInContext(Context, Fib2, "while")
EWhileBB = LLVMAppendBasicBlockInContext(Context, Fib2, "ewhile")
PD = LLVMBuildLoad(Builder,D,"PD");
CondInst1 = LLVMBuildICmp(Builder, #LLVMIntSGE, PD, Two, "cond")
LLVMBuildCondBr(Builder, CondInst1, WhileBB, EWhileBB)
LLVMPositionBuilderAtEnd(Builder, WhileBB)
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);
jump = LLVMBuildBr(Builder,ElseBB);
LLVMPositionBuilderAtEnd(Builder, EWhileBB)
;Create the return instruction And add it To the basic block
CR = LLVMBuildLoad(Builder,C,"CR");
LLVMBuildRet(Builder, CR)
;Don't forget to free the builder.
LLVMDisposeBuilder(Builder)
;Return the function ref
ProcedureReturn Fib2
EndProcedure
Procedure CreateFibFunction1(M.i,Context.i)
Protected FunctionReturnType
Protected IntType
;Procedure.i fib(x.i)
;function only uses and int type, create an int type.
intType = LLVMInt32Type()
;Function returns an int And takes an int as the only parameter.
FunctionReturnType = LLVMFunctionType(IntType,@IntType,1,0)
;Create the fib function definition And insert it into the module M.
FibF = LLVMAddFunction(M, "fib",FunctionReturnType)
;Set the function call convention to FastCall so it can utilize tail call
LLVMSetFunctionCallConv(FibF,#LLVMFastCallConv)
;Add a basic block To the function.
BB = LLVMAppendBasicBlockInContext(Context, FibF, "EntryBlock")
;Make the Constants returns a pointer to the constant.
; fib(argx->>"1"<<)+fib(argx->>"2"<<)
One = LLVMConstInt(IntType, 1, 0)
Two = LLVMConstInt(IntType, 2, 0)
;Get a pointer to the ArgX.i and add to function...
ArgX = LLVMGetFirstParam(FibF) ; Get the arg.
LLVMSetValueName(ArgX, "ArgX") ; Give it a symbolic name.
;When using the C bindings, you have to use a BuilderRef To create any instructions.
Builder = LLVMCreateBuilderInContext(Context)
;Set the builder to insert at the first BasicBlock.
LLVMPositionBuilderAtEnd(Builder, BB)
;Create and build the conditional branch "if argX <= 2"
CondInst = LLVMBuildICmp(Builder, #LLVMIntSLE, ArgX, Two, "cond")
;Create two blocks for the Branches If argx<=2 : RetBB : else : RecurseBB
RetBB = LLVMAppendBasicBlockInContext(Context, FibF, "return")
RecurseBB = LLVMAppendBasicBlockInContext(Context, FibF, "recurse")
LLVMBuildCondBr(Builder, CondInst, RetBB, RecurseBB)
;Create: ProcedureReturn 1
LLVMPositionBuilderAtEnd(Builder, RetBB)
LLVMBuildRet(Builder,One)
;Create fib(x-1)
LLVMPositionBuilderAtEnd(Builder, RecurseBB)
Subtr = LLVMBuildSub(Builder, ArgX, One, "arg")
CallFibX1 = LLVMBuildCall(Builder, FibF, @Subtr, 1, "fibx1")
;LLVMSetTailCall(CallFibX1, 1) ;let the optimzer deal with it
;Create fib(x-2)
Subtr = LLVMBuildSub(Builder, ArgX, Two, "arg")
CallFibX2 = LLVMBuildCall(Builder, FibF, @Subtr, 1, "fibx2")
;LLVMSetTailCall(CallFibX2, 1) ;let the optimzer deal with it
;fib(x-1)+fib(x-2)
Sum = LLVMBuildAdd(Builder, CallFibX1, CallFibX2, "addresult")
;Create the return instruction And add it To the basic block
LLVMBuildRet(Builder, Sum)
;Don't forget to free the builder.
LLVMDisposeBuilder(Builder)
;Return the function ref
ProcedureReturn FibF
EndProcedure
Procedure main(n)
Protected errStr.s
Protected EE.i
LLVMLinkInJIT()
Context = LLVMGetGlobalContext()
;Create a module for our function.
M = LLVMModuleCreateWithNameInContext("test fib", Context)
;Create a pass manager optimizer for our funtions
PM = LLVMCreateFunctionPassManagerForModule(M);
;add tail call elimination parse to it
;LLVMAddTailCallEliminationPass(PM);
LLVMInitializeFunctionPassManager(PM);
;Create the Fib function in the Module and Context
FibF = CreateFibFunction(M, Context)
;Run function optimizer
If LLVMRunFunctionPassManager(PM,FibF);
PrintN("Optimized Function")
EndIf
LLVMFinalizeFunctionPassManager(PM)
LLVMDisposePassManager(PM);
;Create JIT engine execution
If LLVMCreateExecutionEngineForModule(@EE, M, pStr)
PrintN(ReadVarString(pStr))
LLVMDisposeMessage(pStr)
Input()
End
EndIf
;read the target data
TD =LLVMGetExecutionEngineTargetData(EE);
PrintN(ReadVarString(LLVMCopyStringRepOfTargetData(TD)))
;LLVMDisposeTargetData(TD); locks up for some reason
;Verify module
PrintN("verifying module")
If LLVMVerifyModule(M, #LLVMPrintMessageAction,pStr)
PrintN("Error constructing function!")
PrintN(ReadVarString(pstr))
LLVMDisposeMessage(pStr)
Input()
End
EndIf
PrintN(ReadVarString(LLVMDumpModule(M)));
PrintN("OK")
PrintN("Test module succeded")
PrintN("Run fibonacci(" + Str(n) + ") in JIT");
;Call the Fibonacci function With argument n:
Arg = LLVMCreateGenericValueOfInt(LLVMInt32Type(), n, 1)
st = ElapsedMilliseconds()
GV = LLVMRunFunction(EE, FibF, 1, @Arg)
et = ElapsedMilliseconds()
;convert the result
PrintN("Jit Result: ")
PrintN(Str(LLVMGenericValueToInt(GV, 1)))
PrintN("took " + Str(et-st))
;call same in PB
st = ElapsedMilliseconds()
res = fibpb(n)
et = ElapsedMilliseconds()
PrintN("PB Result: ")
PrintN(Str(res))
PrintN("took " + Str(et-st))
;call same in PB
st = ElapsedMilliseconds()
res2 = fibpb2(n)
et = ElapsedMilliseconds()
PrintN("PB Result 2: ")
PrintN(Str(res2))
PrintN("took " + Str(et-st))
;Dump the jit Bitcode to file
LLVMWriteBitcodeToFile(M,"fib.bc");
PrintN("")
PrintN("Dumped bytecode to 'fib.bc'")
;clean up
LLVMDisposeGenericValue(Arg)
LLVMDisposeGenericValue(GV)
LLVMDisposeExecutionEngine(EE)
;Create native elf from the saved bc file
lto = lto_module_create("fib.bc");
gen = lto_codegen_create();
lto_codegen_add_module(gen,lto);
*mem = lto_codegen_compile(gen,@length.i);
If length
fil = CreateFile(#PB_Any,"fib.elf")
WriteData(fil,*mem,length)
CloseFile(fil)
PrintN("")
PrintN("Created native code to 'fib.elf'")
EndIf
lto_codegen_dispose(gen);
EndProcedure
OpenConsole()
PrintN("enter the number of factors < 35")
n = Val(Input())
main(n)
PrintN("")
PrintN("Press enter to quit")
Input()
CloseConsole()