Adding a simple example of how to use the JIT.
[oota-llvm.git] / examples / HowToUseJIT / HowToUseJIT.cpp
1 //===--- HowToUseJIT.cpp - An example use of the JIT ----------------------===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Valery A. Khamenya and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 //  This tool provides a single point of access to the LLVM compilation tools.
11 //  It has many options. To discover the options supported please refer to the
12 //  tools' manual page (docs/CommandGuide/html/llvmc.html) or run the tool with
13 //  the --help option.
14 // 
15 //===------------------------------------------------------------------------===
16
17 // Goal: 
18 //  The goal of this snippet is to create in the memory
19 //  the LLVM module consisting of two functions as follow:
20 //
21 // int add1(int x) {
22 //   return x+1;
23 // }
24 // 
25 // int foo() {
26 //   return add1(10);
27 // }
28 // 
29 // then compile the module via JIT, then execute the `foo' 
30 // function and return result to a driver, i.e. to a "host program".
31 // 
32 // Some remarks and questions:
33 // 
34 // - could we invoke some code using noname functions too?
35 //   e.g. evaluate "foo()+foo()" without fears to introduce 
36 //   conflict of temporary function name with some real
37 //   existing function name?
38 // 
39
40 #include <iostream>
41
42 #include <llvm/Module.h>
43 #include <llvm/DerivedTypes.h>
44 #include <llvm/Constants.h>
45 #include <llvm/Instructions.h>
46 #include <llvm/ModuleProvider.h>
47
48 #include "llvm/ExecutionEngine/ExecutionEngine.h"
49 #include "llvm/ExecutionEngine/GenericValue.h"
50
51
52 using namespace llvm;
53
54 int main() {
55
56   // Create some module to put our function into it.
57   Module *M = new Module("test");
58
59
60   // We are about to create the add1 function:
61   Function *Add1F;
62
63   {
64     // first create type for the single argument of add1 function: 
65     // the type is 'int ()'
66     std::vector<const Type*> ArgT(1);
67     ArgT[0] = Type::IntTy;
68
69     // now create full type of the add1 function:
70     FunctionType *Add1T = FunctionType::get(Type::IntTy, // type of result
71                                             ArgT,
72                                             /*not vararg*/false);
73  
74     // Now create the add1 function entry and 
75     // insert this entry into module M
76     // (By passing a module as the last parameter to the Function constructor,
77     // it automatically gets appended to the Module.)
78     Add1F = new Function(Add1T, 
79                          Function::ExternalLinkage, // maybe too much
80                          "add1", M);
81
82     // Add a basic block to the function... (again, it automatically inserts
83     // because of the last argument.)
84     BasicBlock *BB = new BasicBlock("EntryBlock of add1 function", Add1F);
85   
86     // Get pointers to the constant `1'...
87     Value *One = ConstantSInt::get(Type::IntTy, 1);
88
89     // Get pointers to the integer argument of the add1 function...
90     assert(Add1F->abegin() != Add1F->aend()); // Make sure there's an arg
91     Argument &ArgX = Add1F->afront();  // Get the arg
92
93     // Create the add instruction... does not insert...
94     Instruction *Add = BinaryOperator::create(Instruction::Add, One, &ArgX,
95                                               "addresult");
96   
97     // explicitly insert it into the basic block...
98     BB->getInstList().push_back(Add);
99   
100     // Create the return instruction and add it to the basic block
101     BB->getInstList().push_back(new ReturnInst(Add));
102
103     // function add1 is ready
104   }
105
106
107   // now we going to create function `foo':
108   Function *FooF;
109
110   {  
111     // Create the foo function type:
112     FunctionType *FooT = 
113       FunctionType::get(Type::IntTy, // result has type: 'int ()'
114                         std::vector<const Type*>(), // no arguments
115                         /*not vararg*/false);
116     
117     // create the entry for function `foo' and insert
118     // this entry into module M:
119     FooF = 
120       new Function(FooT, 
121                    Function::ExternalLinkage, // too wide?
122                    "foo", M);
123     
124     // Add a basic block to the FooF function...
125     BasicBlock *BB = new BasicBlock("EntryBlock of add1 function", FooF);
126
127     // Get pointers to the constant `10'...
128     Value *Ten = ConstantSInt::get(Type::IntTy, 10);
129
130     // Put the argument Ten on stack and make call:
131     // ...
132     std::vector<Value*> Params;
133     Params.push_back(Ten);
134     CallInst * Add1CallRes = new CallInst(Add1F, Params, "add1", BB);
135     
136     // Create the return instruction and add it to the basic block
137     BB->getInstList().push_back(new ReturnInst(Add1CallRes));
138     
139   }
140
141   // Now we going to create JIT ??
142   ExistingModuleProvider* MP = new ExistingModuleProvider(M);
143   ExecutionEngine* EE = ExecutionEngine::create( MP, true );
144
145   // Call the `foo' function with no arguments:
146   std::vector<GenericValue> noargs;
147   GenericValue gv = EE->runFunction(FooF, noargs);
148
149   // import result of execution:
150   std::cout << "Result: " << gv.IntVal << std:: endl;
151
152   return 0;
153 }