llvm-project
148 строк · 4.8 Кб
1//===--- examples/Fibonacci/fibonacci.cpp - An example use of the JIT -----===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
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.
11//
12// The goal of this snippet is to create in the memory the LLVM module
13// consisting of one function as follow:
14//
15// int fib(int x) {
16// if(x<=2) return 1;
17// return fib(x-1)+fib(x-2);
18// }
19//
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".
22//
23//===----------------------------------------------------------------------===//
24
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"43#include <algorithm>44#include <cstdlib>45#include <memory>46#include <string>47#include <vector>48
49using namespace llvm;50
51static Function *CreateFibFunction(Module *M, LLVMContext &Context) {52// Create the fib function and insert it into module M. This function is said53// to return an int and take an int parameter.54FunctionType *FibFTy = FunctionType::get(Type::getInt32Ty(Context),55{Type::getInt32Ty(Context)}, false);56Function *FibF =57Function::Create(FibFTy, Function::ExternalLinkage, "fib", M);58
59// Add a basic block to the function.60BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FibF);61
62// Get pointers to the constants.63Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1);64Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2);65
66// Get pointer to the integer argument of the add1 function...67Argument *ArgX = &*FibF->arg_begin(); // Get the arg.68ArgX->setName("AnArg"); // Give it a nice symbolic name for fun.69
70// Create the true_block.71BasicBlock *RetBB = BasicBlock::Create(Context, "return", FibF);72// Create an exit block.73BasicBlock* RecurseBB = BasicBlock::Create(Context, "recurse", FibF);74
75// Create the "if (arg <= 2) goto exitbb"76Value *CondInst = new ICmpInst(BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond");77BranchInst::Create(RetBB, RecurseBB, CondInst, BB);78
79// Create: ret int 180ReturnInst::Create(Context, One, RetBB);81
82// create fib(x-1)83Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB);84CallInst *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB);85CallFibX1->setTailCall();86
87// create fib(x-2)88Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB);89CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB);90CallFibX2->setTailCall();91
92// fib(x-1)+fib(x-2)93Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2,94"addresult", RecurseBB);95
96// Create the return instruction and add it to the basic block97ReturnInst::Create(Context, Sum, RecurseBB);98
99return FibF;100}
101
102int main(int argc, char **argv) {103int n = argc > 1 ? atol(argv[1]) : 24;104
105InitializeNativeTarget();106InitializeNativeTargetAsmPrinter();107LLVMContext Context;108
109// Create some module to put our function into it.110std::unique_ptr<Module> Owner(new Module("test", Context));111Module *M = Owner.get();112
113// We are about to create the "fib" function:114Function *FibF = CreateFibFunction(M, Context);115
116// Now we going to create JIT117std::string errStr;118ExecutionEngine *EE =119EngineBuilder(std::move(Owner))120.setErrorStr(&errStr)121.create();122
123if (!EE) {124errs() << argv[0] << ": Failed to construct ExecutionEngine: " << errStr125<< "\n";126return 1;127}128
129errs() << "verifying... ";130if (verifyModule(*M)) {131errs() << argv[0] << ": Error constructing function!\n";132return 1;133}134
135errs() << "OK\n";136errs() << "We just constructed this LLVM module:\n\n---------\n" << *M;137errs() << "---------\nstarting fibonacci(" << n << ") with JIT...\n";138
139// Call the Fibonacci function with argument n:140std::vector<GenericValue> Args(1);141Args[0].IntVal = APInt(32, n);142GenericValue GV = EE->runFunction(FibF, Args);143
144// import result of execution145outs() << "Result: " << GV.IntVal << "\n";146
147return 0;148}
149