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:
And the results speak for themselves:
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
int _tmain(int argc, _TCHAR* argv[])
{
using namespace llvm;
InitializeNativeTarget();
LLVMContext& Context = getGlobalContext();
Module* module = new Module("EpochJIT", Context);
IRBuilder<> Builder(Context);
std::map<std::string, Value*> NamedValues;
std::vector<Type*> 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<std::string> 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<Type*> 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:
Create a custom theme




