1*f4a2713aSLionel Sambuc //===--- examples/Fibonacci/fibonacci.cpp - An example use of the JIT -----===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // This small program provides an example of how to build quickly a small module 11*f4a2713aSLionel Sambuc // with function Fibonacci and execute it with the JIT. 12*f4a2713aSLionel Sambuc // 13*f4a2713aSLionel Sambuc // The goal of this snippet is to create in the memory the LLVM module 14*f4a2713aSLionel Sambuc // consisting of one function as follow: 15*f4a2713aSLionel Sambuc // 16*f4a2713aSLionel Sambuc // int fib(int x) { 17*f4a2713aSLionel Sambuc // if(x<=2) return 1; 18*f4a2713aSLionel Sambuc // return fib(x-1)+fib(x-2); 19*f4a2713aSLionel Sambuc // } 20*f4a2713aSLionel Sambuc // 21*f4a2713aSLionel Sambuc // Once we have this, we compile the module via JIT, then execute the `fib' 22*f4a2713aSLionel Sambuc // function and return result to a driver, i.e. to a "host program". 23*f4a2713aSLionel Sambuc // 24*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc #include "llvm/Analysis/Verifier.h" 27*f4a2713aSLionel Sambuc #include "llvm/ExecutionEngine/GenericValue.h" 28*f4a2713aSLionel Sambuc #include "llvm/ExecutionEngine/Interpreter.h" 29*f4a2713aSLionel Sambuc #include "llvm/ExecutionEngine/JIT.h" 30*f4a2713aSLionel Sambuc #include "llvm/IR/Constants.h" 31*f4a2713aSLionel Sambuc #include "llvm/IR/DerivedTypes.h" 32*f4a2713aSLionel Sambuc #include "llvm/IR/Instructions.h" 33*f4a2713aSLionel Sambuc #include "llvm/IR/LLVMContext.h" 34*f4a2713aSLionel Sambuc #include "llvm/IR/Module.h" 35*f4a2713aSLionel Sambuc #include "llvm/Support/TargetSelect.h" 36*f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h" 37*f4a2713aSLionel Sambuc using namespace llvm; 38*f4a2713aSLionel Sambuc 39*f4a2713aSLionel Sambuc static Function *CreateFibFunction(Module *M, LLVMContext &Context) { 40*f4a2713aSLionel Sambuc // Create the fib function and insert it into module M. This function is said 41*f4a2713aSLionel Sambuc // to return an int and take an int parameter. 42*f4a2713aSLionel Sambuc Function *FibF = 43*f4a2713aSLionel Sambuc cast<Function>(M->getOrInsertFunction("fib", Type::getInt32Ty(Context), 44*f4a2713aSLionel Sambuc Type::getInt32Ty(Context), 45*f4a2713aSLionel Sambuc (Type *)0)); 46*f4a2713aSLionel Sambuc 47*f4a2713aSLionel Sambuc // Add a basic block to the function. 48*f4a2713aSLionel Sambuc BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FibF); 49*f4a2713aSLionel Sambuc 50*f4a2713aSLionel Sambuc // Get pointers to the constants. 51*f4a2713aSLionel Sambuc Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1); 52*f4a2713aSLionel Sambuc Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2); 53*f4a2713aSLionel Sambuc 54*f4a2713aSLionel Sambuc // Get pointer to the integer argument of the add1 function... 55*f4a2713aSLionel Sambuc Argument *ArgX = FibF->arg_begin(); // Get the arg. 56*f4a2713aSLionel Sambuc ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. 57*f4a2713aSLionel Sambuc 58*f4a2713aSLionel Sambuc // Create the true_block. 59*f4a2713aSLionel Sambuc BasicBlock *RetBB = BasicBlock::Create(Context, "return", FibF); 60*f4a2713aSLionel Sambuc // Create an exit block. 61*f4a2713aSLionel Sambuc BasicBlock* RecurseBB = BasicBlock::Create(Context, "recurse", FibF); 62*f4a2713aSLionel Sambuc 63*f4a2713aSLionel Sambuc // Create the "if (arg <= 2) goto exitbb" 64*f4a2713aSLionel Sambuc Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond"); 65*f4a2713aSLionel Sambuc BranchInst::Create(RetBB, RecurseBB, CondInst, BB); 66*f4a2713aSLionel Sambuc 67*f4a2713aSLionel Sambuc // Create: ret int 1 68*f4a2713aSLionel Sambuc ReturnInst::Create(Context, One, RetBB); 69*f4a2713aSLionel Sambuc 70*f4a2713aSLionel Sambuc // create fib(x-1) 71*f4a2713aSLionel Sambuc Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB); 72*f4a2713aSLionel Sambuc CallInst *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB); 73*f4a2713aSLionel Sambuc CallFibX1->setTailCall(); 74*f4a2713aSLionel Sambuc 75*f4a2713aSLionel Sambuc // create fib(x-2) 76*f4a2713aSLionel Sambuc Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB); 77*f4a2713aSLionel Sambuc CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB); 78*f4a2713aSLionel Sambuc CallFibX2->setTailCall(); 79*f4a2713aSLionel Sambuc 80*f4a2713aSLionel Sambuc 81*f4a2713aSLionel Sambuc // fib(x-1)+fib(x-2) 82*f4a2713aSLionel Sambuc Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2, 83*f4a2713aSLionel Sambuc "addresult", RecurseBB); 84*f4a2713aSLionel Sambuc 85*f4a2713aSLionel Sambuc // Create the return instruction and add it to the basic block 86*f4a2713aSLionel Sambuc ReturnInst::Create(Context, Sum, RecurseBB); 87*f4a2713aSLionel Sambuc 88*f4a2713aSLionel Sambuc return FibF; 89*f4a2713aSLionel Sambuc } 90*f4a2713aSLionel Sambuc 91*f4a2713aSLionel Sambuc 92*f4a2713aSLionel Sambuc int main(int argc, char **argv) { 93*f4a2713aSLionel Sambuc int n = argc > 1 ? atol(argv[1]) : 24; 94*f4a2713aSLionel Sambuc 95*f4a2713aSLionel Sambuc InitializeNativeTarget(); 96*f4a2713aSLionel Sambuc LLVMContext Context; 97*f4a2713aSLionel Sambuc 98*f4a2713aSLionel Sambuc // Create some module to put our function into it. 99*f4a2713aSLionel Sambuc OwningPtr<Module> M(new Module("test", Context)); 100*f4a2713aSLionel Sambuc 101*f4a2713aSLionel Sambuc // We are about to create the "fib" function: 102*f4a2713aSLionel Sambuc Function *FibF = CreateFibFunction(M.get(), Context); 103*f4a2713aSLionel Sambuc 104*f4a2713aSLionel Sambuc // Now we going to create JIT 105*f4a2713aSLionel Sambuc std::string errStr; 106*f4a2713aSLionel Sambuc ExecutionEngine *EE = 107*f4a2713aSLionel Sambuc EngineBuilder(M.get()) 108*f4a2713aSLionel Sambuc .setErrorStr(&errStr) 109*f4a2713aSLionel Sambuc .setEngineKind(EngineKind::JIT) 110*f4a2713aSLionel Sambuc .create(); 111*f4a2713aSLionel Sambuc 112*f4a2713aSLionel Sambuc if (!EE) { 113*f4a2713aSLionel Sambuc errs() << argv[0] << ": Failed to construct ExecutionEngine: " << errStr 114*f4a2713aSLionel Sambuc << "\n"; 115*f4a2713aSLionel Sambuc return 1; 116*f4a2713aSLionel Sambuc } 117*f4a2713aSLionel Sambuc 118*f4a2713aSLionel Sambuc errs() << "verifying... "; 119*f4a2713aSLionel Sambuc if (verifyModule(*M)) { 120*f4a2713aSLionel Sambuc errs() << argv[0] << ": Error constructing function!\n"; 121*f4a2713aSLionel Sambuc return 1; 122*f4a2713aSLionel Sambuc } 123*f4a2713aSLionel Sambuc 124*f4a2713aSLionel Sambuc errs() << "OK\n"; 125*f4a2713aSLionel Sambuc errs() << "We just constructed this LLVM module:\n\n---------\n" << *M; 126*f4a2713aSLionel Sambuc errs() << "---------\nstarting fibonacci(" << n << ") with JIT...\n"; 127*f4a2713aSLionel Sambuc 128*f4a2713aSLionel Sambuc // Call the Fibonacci function with argument n: 129*f4a2713aSLionel Sambuc std::vector<GenericValue> Args(1); 130*f4a2713aSLionel Sambuc Args[0].IntVal = APInt(32, n); 131*f4a2713aSLionel Sambuc GenericValue GV = EE->runFunction(FibF, Args); 132*f4a2713aSLionel Sambuc 133*f4a2713aSLionel Sambuc // import result of execution 134*f4a2713aSLionel Sambuc outs() << "Result: " << GV.IntVal << "\n"; 135*f4a2713aSLionel Sambuc 136*f4a2713aSLionel Sambuc return 0; 137*f4a2713aSLionel Sambuc } 138