[LLVMdev] API on JIT, code snippets

Reid Spencer reid at x10sys.com
Tue Aug 10 12:20:07 PDT 2004


Valery,

Your JIT sample program has been added to projects/HowToUseJIT.

I have defaulted the license to the standard UIUC license. Let me know if 
that's not okay and I'll fix it.

If you continue to work on this (providing a command line option to use either 
interpreter or JIT would be nice), please provide patches against these files 
and I'll commit them for you.

Here's the commit list:

http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20040809/016952.html
http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20040809/016955.html
http://mail.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20040809/016956.html

Thanks again for contributing this!

Reid.

vak wrote:

> Reid Spencer,
> 
> thank you for your quick responce, finally i got to my PC at home.
> 
> You wrote:
> 
>> Attached are three files: "valery.cpp" which contains your original, 
>> "reid.cpp" which contains corrections to most of the FIXME items and 
>> "diffs" which shows the differences between them.  The differences 
>> should be instructive on what to do.  You were really, really close .. 
>> just a few details changing.  The code in "reid.cpp" compiles but I 
>> haven't tested it. I'll leave that to you.
> 
> 
> hm, were the linkage requisites the problem by your side too?..
> 
> this is the magic string:
> 
> g++ -L/usr/local/lib -L/usr/local/lib -o reid reid.o   
> /usr/local/lib/lli-interpreter.o  /usr/local/lib/lli-jit.o  
> /usr/local/lib/codegen.o  /usr/local/lib/executionengine.o  
> /usr/local/lib/x86.o  /usr/local/lib/selectiondag.o  
> /usr/local/lib/scalaropts.o -lanalysis -ltransformutils  
> /usr/local/lib/bcreader.o  /usr/local/lib/vmcore.o  
> /usr/local/lib/support.o -ltarget -export-dynamic -ldl
> 
> (don't ask me why some modules are left as .o)
> 
> Well. Compiled. Tested.  Infinite loop in:
> 
> GenericValue gv = EE->runFunction(FooF, noargs);
> 
> you were really, really close, Reid, just a one mistake:
> 
> < CallInst * Add1CallRes = new CallInst(FooF, Params, "foo", BB);
> 
>  > CallInst * Add1CallRes = new CallInst(Add1F, Params, "add1", BB);
> 
> :-P
> 
>> There is only one remaining item that I don't know how to do. After 
>> ExecutionEngine::runFunction, you want to extract the result int value 
>> from the function. The runFunction method returns a GenericValue but I 
>> don't see an obvious way to get an actual value from this class.
> 
> 
>> Misha: can you help out with "GenericValue" ?
> 
> 
> 
> I got advice from Chris, thx.
> 
> AND NOW IT WORKSSSSSS!!!
> 
> HowToUseJIT.cpp is attached as finall version.
> 
> ...well could anyone tell me whether JIT was really invoked in this code?
> What kind of optimization were applied by default (if any)?
> 
> thanks.
> 
> oh, and great thanks to Reid of course!
> 
> -- 
> Valery.
> 
> 
> ------------------------------------------------------------------------
> 
> /*
> Goal: 
>   The goal of this snippet is to create in the memory
>   the LLVM module consisting of two functions as follow:
> 
> 
> int add1(int x) {
>   return x+1;
> }
> 
> int foo() {
>   return add1(10);
> }
> 
> 
> then compile the module via JIT, then execute the `foo' 
> function and return result to a driver, i.e. to a "host program".
> 
> Some remarks and questions:
> 
> - could we invoke some code using noname functions too?
>   e.g. evaluate "foo()+foo()" without fears to introduce 
>   conflict of temporary function name with some real
>   existing function name?
> 
> - it would be nice to copy-paste here a LLVM code of the 
>   above given C-portion, ...but see the next comment :)
> 
> - http://llvm.cs.uiuc.edu/demo/index.cgi is the shortest way 
>   to obtain LLVM code :) but it is down: 
>   "The demo page is currently unavailable. 
>   [tools: ( gccas llvm-dis gccld ) failed sanity check]"
>   LOL
> 
> 
> */
> 
> #include <iostream>
> 
> #include <llvm/Module.h>
> #include <llvm/DerivedTypes.h>
> #include <llvm/Constants.h>
> #include <llvm/Instructions.h>
> #include <llvm/ModuleProvider.h>
> 
> #include "llvm/ExecutionEngine/ExecutionEngine.h"
> #include "llvm/ExecutionEngine/GenericValue.h"
> 
> 
> using namespace llvm;
> 
> int main() {
> 
>   // Create some module to put our function into it.
>   Module *M = new Module("test");
> 
> 
>   // We are about to create the add1 function:
>   Function *Add1F;
> 
>   {
>     // first create type for the single argument of add1 function: 
>     // the type is 'int ()'
>     std::vector<const Type*> ArgT(1);
>     ArgT[0] = Type::IntTy;
> 
>     // now create full type of the add1 function:
>     FunctionType *Add1T = FunctionType::get(Type::IntTy, // type of result: int ()'
>                                             ArgT,
>                                             /*not vararg*/false);
>  
>     // Now create the add1 function entry and 
>     // insert this entry into module M
>     // (By passing a module as the last parameter to the Function constructor,
>     // it automatically gets appended to the Module.)
>     Add1F = new Function(Add1T, 
>                          Function::ExternalLinkage, // maybe too much
>                          "add1", M);
> 
>     // Add a basic block to the function... (again, it automatically inserts
>     // because of the last argument.)
>     BasicBlock *BB = new BasicBlock("EntryBlock of add1 function", Add1F);
>   
>     // Get pointers to the constant `1'...
>     Value *One = ConstantSInt::get(Type::IntTy, 1);
> 
>     // Get pointers to the integer argument of the add1 function...
>     assert(Add1F->abegin() != Add1F->aend()); // Make sure there's an arg
>     Argument &ArgX = Add1F->afront();  // Get the arg
> 
>     // Create the add instruction... does not insert...
>     Instruction *Add = BinaryOperator::create(Instruction::Add, One, &ArgX,
>                                               "addresult");
>   
>     // explicitly insert it into the basic block...
>     BB->getInstList().push_back(Add);
>   
>     // Create the return instruction and add it to the basic block
>     BB->getInstList().push_back(new ReturnInst(Add));
> 
>     // function add1 is ready
>   }
> 
> 
>   // now we going to create function `foo':
>   Function *FooF;
> 
>   {  
>     // Create the foo function type:
>     FunctionType *FooT = 
>       FunctionType::get(Type::IntTy, // result has type: 'int ()'
>                         std::vector<const Type*>(), // no arguments
>                         /*not vararg*/false);
>     
>     // create the entry for function `foo' and insert
>     // this entry into module M:
>     FooF = 
>       new Function(FooT, 
>                    Function::ExternalLinkage, // too wide?
>                    "foo", M);
>     
>     // Add a basic block to the FooF function...
>     BasicBlock *BB = new BasicBlock("EntryBlock of add1 function", FooF);
> 
>     // Get pointers to the constant `10'...
>     Value *Ten = ConstantSInt::get(Type::IntTy, 10);
> 
>     // Put the argument Ten on stack and make call:
>     // ...
>     std::vector<Value*> Params;
>     Params.push_back(Ten);
>     CallInst * Add1CallRes = new CallInst(Add1F, Params, "add1", BB);
>     
>     // Create the return instruction and add it to the basic block
>     BB->getInstList().push_back(new ReturnInst(Add1CallRes));
>     
>   }
> 
>   // Now we going to create JIT ??
>   ExistingModuleProvider* MP = new ExistingModuleProvider(M);
>   ExecutionEngine* EE = ExecutionEngine::create( MP, true );
> 
>   // Call the `foo' function with no arguments:
>   std::vector<GenericValue> noargs;
>   GenericValue gv = EE->runFunction(FooF, noargs);
> 
>   // import result of execution:
>   std::cout << "Result: " << gv.IntVal << std:: endl;
> 
>   return 0;
> }
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list