1 //===--- examples/Fibonacci/fibonacci.cpp - An example use of the JIT -----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This small program provides an example of how to build quickly a small module
10 // with function Fibonacci and execute it with the JIT.
12 // The goal of this snippet is to create in the memory the LLVM module
13 // consisting of one function as follow:
17 // return fib(x-1)+fib(x-2);
20 // Once we have this, we compile the module via JIT, then execute the `fib'
21 // function and return result to a driver, i.e. to a "host program".
23 //===----------------------------------------------------------------------===//
25 #include "llvm/ADT/APInt.h"
26 #include "llvm/IR/Verifier.h"
27 #include "llvm/ExecutionEngine/ExecutionEngine.h"
28 #include "llvm/ExecutionEngine/GenericValue.h"
29 #include "llvm/ExecutionEngine/MCJIT.h"
30 #include "llvm/IR/Argument.h"
31 #include "llvm/IR/BasicBlock.h"
32 #include "llvm/IR/Constants.h"
33 #include "llvm/IR/DerivedTypes.h"
34 #include "llvm/IR/Function.h"
35 #include "llvm/IR/InstrTypes.h"
36 #include "llvm/IR/Instructions.h"
37 #include "llvm/IR/LLVMContext.h"
38 #include "llvm/IR/Module.h"
39 #include "llvm/IR/Type.h"
40 #include "llvm/Support/Casting.h"
41 #include "llvm/Support/TargetSelect.h"
42 #include "llvm/Support/raw_ostream.h"
51 static Function
*CreateFibFunction(Module
*M
, LLVMContext
&Context
) {
52 // Create the fib function and insert it into module M. This function is said
53 // to return an int and take an int parameter.
54 FunctionType
*FibFTy
= FunctionType::get(Type::getInt32Ty(Context
),
55 {Type::getInt32Ty(Context
)}, false);
57 Function::Create(FibFTy
, Function::ExternalLinkage
, "fib", M
);
59 // Add a basic block to the function.
60 BasicBlock
*BB
= BasicBlock::Create(Context
, "EntryBlock", FibF
);
62 // Get pointers to the constants.
63 Value
*One
= ConstantInt::get(Type::getInt32Ty(Context
), 1);
64 Value
*Two
= ConstantInt::get(Type::getInt32Ty(Context
), 2);
66 // Get pointer to the integer argument of the add1 function...
67 Argument
*ArgX
= &*FibF
->arg_begin(); // Get the arg.
68 ArgX
->setName("AnArg"); // Give it a nice symbolic name for fun.
70 // Create the true_block.
71 BasicBlock
*RetBB
= BasicBlock::Create(Context
, "return", FibF
);
72 // Create an exit block.
73 BasicBlock
* RecurseBB
= BasicBlock::Create(Context
, "recurse", FibF
);
75 // Create the "if (arg <= 2) goto exitbb"
76 Value
*CondInst
= new ICmpInst(*BB
, ICmpInst::ICMP_SLE
, ArgX
, Two
, "cond");
77 BranchInst::Create(RetBB
, RecurseBB
, CondInst
, BB
);
80 ReturnInst::Create(Context
, One
, RetBB
);
83 Value
*Sub
= BinaryOperator::CreateSub(ArgX
, One
, "arg", RecurseBB
);
84 CallInst
*CallFibX1
= CallInst::Create(FibF
, Sub
, "fibx1", RecurseBB
);
85 CallFibX1
->setTailCall();
88 Sub
= BinaryOperator::CreateSub(ArgX
, Two
, "arg", RecurseBB
);
89 CallInst
*CallFibX2
= CallInst::Create(FibF
, Sub
, "fibx2", RecurseBB
);
90 CallFibX2
->setTailCall();
93 Value
*Sum
= BinaryOperator::CreateAdd(CallFibX1
, CallFibX2
,
94 "addresult", RecurseBB
);
96 // Create the return instruction and add it to the basic block
97 ReturnInst::Create(Context
, Sum
, RecurseBB
);
102 int main(int argc
, char **argv
) {
103 int n
= argc
> 1 ? atol(argv
[1]) : 24;
105 InitializeNativeTarget();
106 InitializeNativeTargetAsmPrinter();
109 // Create some module to put our function into it.
110 std::unique_ptr
<Module
> Owner(new Module("test", Context
));
111 Module
*M
= Owner
.get();
113 // We are about to create the "fib" function:
114 Function
*FibF
= CreateFibFunction(M
, Context
);
116 // Now we going to create JIT
118 ExecutionEngine
*EE
=
119 EngineBuilder(std::move(Owner
))
120 .setErrorStr(&errStr
)
124 errs() << argv
[0] << ": Failed to construct ExecutionEngine: " << errStr
129 errs() << "verifying... ";
130 if (verifyModule(*M
)) {
131 errs() << argv
[0] << ": Error constructing function!\n";
136 errs() << "We just constructed this LLVM module:\n\n---------\n" << *M
;
137 errs() << "---------\nstarting fibonacci(" << n
<< ") with JIT...\n";
139 // Call the Fibonacci function with argument n:
140 std::vector
<GenericValue
> Args(1);
141 Args
[0].IntVal
= APInt(32, n
);
142 GenericValue GV
= EE
->runFunction(FibF
, Args
);
144 // import result of execution
145 outs() << "Result: " << GV
.IntVal
<< "\n";