• entries
625
1446
• views
1007178

# LLVM... it LIVES!

1284 views

So I decided that I was tired of not working on the VM side of things, and rigged up a simple test harness for LLVM.

Basically, this creates the following situation:

• getstuff() is a function defined in the native .EXE which returns a simple integer
• answer() is a function defined in LLVM bitcode at runtime
• answer() accepts one integer parameter, adds it to the return value of getstuff(), and returns the result
• The native .EXE will JIT compile answer() to native code, execute it, and print its return value

All this is pretty simple to do:

int _tmain(int argc, _TCHAR* argv[]){ using namespace llvm; InitializeNativeTarget(); LLVMContext& Context = getGlobalContext(); Module* module = new Module("EpochJIT", Context); IRBuilder<> Builder(Context); std::map NamedValues; std::vector args(1, Type::getInt32Ty(Context)); FunctionType* functype = FunctionType::get(Type::getInt32Ty(Context), args, false); Function* func = Function::Create(functype, Function::ExternalLinkage, "answer", module); std::vector Args; Args.push_back("a"); unsigned Idx = 0; for(Function::arg_iterator AI = func->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); NamedValues[Args[Idx]] = AI; } BasicBlock* block = BasicBlock::Create(Context, "entry", func); Builder.SetInsertPoint(block); std::vector noargs; FunctionType* getstufffunctype = FunctionType::get(Type::getInt32Ty(Context), noargs, false); Function* getstufffunc = Function::Create(getstufffunctype, Function::ExternalLinkage, "getstuff", module); Value* stuff = Builder.CreateCall(getstufffunc); Value* addition = Builder.CreateAdd(NamedValues["a"], stuff, "addtmp"); Builder.CreateRet(addition); verifyFunction(*func); module->dump(); std::string ErrStr; ExecutionEngine* ee = EngineBuilder(module).setErrorStr(&ErrStr).create(); if(!ee) { std::cout << ErrStr << std::endl; return 1; } void* fptr = ee->getPointerToFunction(func); int (*fp)(int) = (int (*)(int))fptr; std::wcout << fp(2) << std::endl; return 0;}

And the results speak for themselves:

Ah, LLVM.. I've played with it a bit, such a quality library and if/when I get around to needing/wanting my own scripting language it is hands down my first choice for the backend.

Yeah, I've been extremely impressed by the library so far. Very clean design and stupid powerful.

I honestly was pleasantly surprised to discover that it's possible to go from AST to JIT'ed native code in a lazy evening's worth of work.

I was going to use it for a BASIC dialect I made a while back but I couldn't figure it out and the documentation wasn't of much help.
:/
I might have to relook at it since you claim that it is so easy to use!

Only problem I had at the time was the release didn't support VS2010 out of the box, but that's long since been fixed.

What I found helpful was following the tutorial series on making their toy language; it was a decent intro to the lib and gave you something to jump from into the docs.

I wanted to mess with LLVM, but don't you have to install 4 GB of stuff just to get it up and running?

Well, the compile of the LLVM project does take up a fair chunk of space when you factor in all the .obj files etc; the final library directory I think I was using was somewhere around 700meg, the 'build' directory does apprently take up 8gb however you do have to weight that against how good the library is and what it can do.

In short; while big that really isn't an issue.

## Create an account

Register a new account