166e7cd0eea6f116f3ed79acb8948c6d8db50833cReid Spencer//===--- examples/Fibonacci/fibonacci.cpp - An example use of the JIT -----===// 2237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman// 3e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer// The LLVM Compiler Infrastructure 4e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer// 5fc001bbfc360ab828e5a4b0cbe4bb7db87361b85Chris Lattner// This file is distributed under the University of Illinois Open Source 6fc001bbfc360ab828e5a4b0cbe4bb7db87361b85Chris Lattner// License. See LICENSE.TXT for details. 7237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman// 8e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer//===----------------------------------------------------------------------===// 9e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer// 1038f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// This small program provides an example of how to build quickly a small module 1138f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// with function Fibonacci and execute it with the JIT. 12e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer// 1338f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// The goal of this snippet is to create in the memory the LLVM module 1438f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// consisting of one function as follow: 15e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer// 1638f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// int fib(int x) { 1738f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// if(x<=2) return 1; 1838f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// return fib(x-1)+fib(x-2); 1938f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// } 20237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman// 2138f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner// Once we have this, we compile the module via JIT, then execute the `fib' 22e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer// function and return result to a driver, i.e. to a "host program". 23e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer// 2438f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner//===----------------------------------------------------------------------===// 25e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/Verifier.h" 27e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer#include "llvm/ExecutionEngine/GenericValue.h" 284ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/ExecutionEngine/Interpreter.h" 294ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/ExecutionEngine/JIT.h" 300a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/Constants.h" 310a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/DerivedTypes.h" 320a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/Instructions.h" 330a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/LLVMContext.h" 340a08460599eed603e469e3e16d0cf6aa33b8ba93Chandler Carruth#include "llvm/IR/Module.h" 353e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetSelect.h" 364ca7e09b7c1e41535f2a1bd86915375d023daf27Chandler Carruth#include "llvm/Support/raw_ostream.h" 37e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencerusing namespace llvm; 38e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 399adc0abad3c3ed40a268ccbcee0c74cb9e1359feOwen Andersonstatic Function *CreateFibFunction(Module *M, LLVMContext &Context) { 4092b0d8cf2c51debc7f4fb30a417ae839077a8ed0Quentin Colombet // Create the fib function and insert it into module M. This function is said 4138f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // to return an int and take an int parameter. 426a98754ebbc211958297b0d20a77e8c3261c3708Chris Lattner Function *FibF = 435791df830dd8bc91f44aff98446d5f74a96ae185Arnaud A. de Grandmaison cast<Function>(M->getOrInsertFunction("fib", Type::getInt32Ty(Context), 441d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Type::getInt32Ty(Context), 456a98754ebbc211958297b0d20a77e8c3261c3708Chris Lattner (Type *)0)); 46237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman 4738f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // Add a basic block to the function. 481d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FibF); 49237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman 5038f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // Get pointers to the constants. 511d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1); 521d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2); 53e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 5438f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // Get pointer to the integer argument of the add1 function... 55dadf88123f7abce7afe0db12beccc24c87e004a5Alkis Evlogimenos Argument *ArgX = FibF->arg_begin(); // Get the arg. 5638f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. 57e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 5838f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // Create the true_block. 591d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson BasicBlock *RetBB = BasicBlock::Create(Context, "return", FibF); 6038f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // Create an exit block. 611d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson BasicBlock* RecurseBB = BasicBlock::Create(Context, "recurse", FibF); 62e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 637520fcd7a5e4c17011588aab105dea9afa2ba3ecChris Lattner // Create the "if (arg <= 2) goto exitbb" 64333c40096561218bc3597cf153c0a3895274414cOwen Anderson Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond"); 65051a950000e21935165db56695e35bade668193bGabor Greif BranchInst::Create(RetBB, RecurseBB, CondInst, BB); 66e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 6738f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // Create: ret int 1 681d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson ReturnInst::Create(Context, One, RetBB); 69237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman 7038f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // create fib(x-1) 717cbd8a3e92221437048b484d5ef9c0a22d0f8c58Gabor Greif Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB); 72051a950000e21935165db56695e35bade668193bGabor Greif CallInst *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB); 73f6b5c1abce89dbd7e8e12407aa8e4a04f805fdf2Chris Lattner CallFibX1->setTailCall(); 74237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman 7538f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // create fib(x-2) 767cbd8a3e92221437048b484d5ef9c0a22d0f8c58Gabor Greif Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB); 77051a950000e21935165db56695e35bade668193bGabor Greif CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB); 78f6b5c1abce89dbd7e8e12407aa8e4a04f805fdf2Chris Lattner CallFibX2->setTailCall(); 7947968e4dfd849b83a7eb958611c994e6b500998cChris Lattner 8038f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner 8138f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // fib(x-1)+fib(x-2) 827cbd8a3e92221437048b484d5ef9c0a22d0f8c58Gabor Greif Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2, 8338f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner "addresult", RecurseBB); 84237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman 8538f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // Create the return instruction and add it to the basic block 861d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson ReturnInst::Create(Context, Sum, RecurseBB); 87e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 8838f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner return FibF; 8938f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner} 90e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 91e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 9238f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattnerint main(int argc, char **argv) { 9338f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner int n = argc > 1 ? atol(argv[1]) : 24; 94e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 9518f0c677faaca54974333f2e7e353e94280628abChris Lattner InitializeNativeTarget(); 968b477ed579794ba6d76915d56b3f448a7dd20120Owen Anderson LLVMContext Context; 975791df830dd8bc91f44aff98446d5f74a96ae185Arnaud A. de Grandmaison 9838f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // Create some module to put our function into it. 9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::unique_ptr<Module> M(new Module("test", Context)); 10038f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner 10138f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // We are about to create the "fib" function: 10203d1063d3208378b2bf7c15f0ea0e90ff4defa87Chris Lattner Function *FibF = CreateFibFunction(M.get(), Context); 103e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 104237cef4b0b94b17ca065efad484f386f42579b61Misha Brukman // Now we going to create JIT 10518f0c677faaca54974333f2e7e353e94280628abChris Lattner std::string errStr; 10603d1063d3208378b2bf7c15f0ea0e90ff4defa87Chris Lattner ExecutionEngine *EE = 10703d1063d3208378b2bf7c15f0ea0e90ff4defa87Chris Lattner EngineBuilder(M.get()) 10803d1063d3208378b2bf7c15f0ea0e90ff4defa87Chris Lattner .setErrorStr(&errStr) 10903d1063d3208378b2bf7c15f0ea0e90ff4defa87Chris Lattner .setEngineKind(EngineKind::JIT) 11003d1063d3208378b2bf7c15f0ea0e90ff4defa87Chris Lattner .create(); 11118f0c677faaca54974333f2e7e353e94280628abChris Lattner 11218f0c677faaca54974333f2e7e353e94280628abChris Lattner if (!EE) { 11303d1063d3208378b2bf7c15f0ea0e90ff4defa87Chris Lattner errs() << argv[0] << ": Failed to construct ExecutionEngine: " << errStr 11403d1063d3208378b2bf7c15f0ea0e90ff4defa87Chris Lattner << "\n"; 11518f0c677faaca54974333f2e7e353e94280628abChris Lattner return 1; 11618f0c677faaca54974333f2e7e353e94280628abChris Lattner } 117e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 118944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner errs() << "verifying... "; 119e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer if (verifyModule(*M)) { 120944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner errs() << argv[0] << ": Error constructing function!\n"; 121e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer return 1; 122e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer } 123e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 124944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner errs() << "OK\n"; 125944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner errs() << "We just constructed this LLVM module:\n\n---------\n" << *M; 126944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner errs() << "---------\nstarting fibonacci(" << n << ") with JIT...\n"; 127e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 1287cf540bba0b262681a14058d01ad41a87ac870dfMisha Brukman // Call the Fibonacci function with argument n: 12938f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner std::vector<GenericValue> Args(1); 13034bd70de3c344034b82dc9a964a6b6893efa3e82Reid Spencer Args[0].IntVal = APInt(32, n); 13138f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner GenericValue GV = EE->runFunction(FibF, Args); 132e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer 13338f024daea1f27b6a8b610e3f8d21596f3e928d8Chris Lattner // import result of execution 134944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner outs() << "Result: " << GV.IntVal << "\n"; 1355791df830dd8bc91f44aff98446d5f74a96ae185Arnaud A. de Grandmaison 136e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer return 0; 137e784fa40c5808bfb88480f0ab3746ed378a939dfReid Spencer} 138