<cc'ing llvmdev>
I'm working on using the LLVM JIT in PyPy and I hop you can give me a few hint.
ok
I have some things working at and try to write C++ code for what I need from Python. The unittest I am working on at the moment is looks like this
--- Python code...
llglobalmul4 = '''%my_global_int = external global intimplementation
int %globalmul4(int %a) {
% v0 = load int* %my_global_data
% v1 = mul int %v0, 4
% v2 = add int %v1, %a
store int %v2, int* %my_global_int
ret int %v2
}'''def test_modify_global_data():
llvmjit.restart()
llvmjit.set_global_data(10)
assert llvmjit.get_global_data() == 10
gp_data = llvmjit.get_pointer_to_global_data()
llvmjit.add_global_mapping('my_global_data', gp_data) #note: should be prior to compile()
llvmjit.compile(llglobalmul4)
globalmul4 = llvmjit.find_function('globalmul4')
assert llvmjit.execute(globalmul4, 5) == 10 * 4 + 5
assert llvmjit.get_global_data() == 10 * 4 + 5
---This gives a segfault in llvm::Type::getForwardedTypeInternal as far as I can tell. Probably I don't understand how global data mapping works in llvm.
The C++ code for add_global_mapping(...) looks like this--- C++ code...
void add_global_mapping(const char* name, void* address) {
GlobalVariable var(Type::IntTy, false, GlobalVariable::ExternalLinkage, 0, name, gp_module);
gp_execution_engine->addGlobalMapping(&var, address);
}
This is creating a new global variable on the stack, instead of finding the existing global variable in the module. Try something like this:
gp_execution_engine->addGlobalMapping(YourModule->getNamedGlobal(name),
address);
The 2nd question I have has to do with recompiling code.
The 'library' I'm creating, that sits between llvm's (c++) libs and Python, will remain minimal so I decided to use ParseAssemblyString to get .ll sourcecode into the JIT.
Ok.
I do not see how I can tell the jit when this .ll code contains a function that should overwrite a previous version of it.
For instance, when there is a function "int %func() { ret int 5 }" and later I want this replaced by "int %func() { ret int 10 }".
If I remember correctly this gives a 'function already defined' error message. I tried to use a seperate module for each call to ParseAssemblyString + addModuleProvider.
In that way there was a problem with functions calling into other modules. (which perhaps I could try to solve if would understand addGlobalMapping better)
This is somewhat tricky. To replace a function in-place like this, you should actually modify the function in the original module, then call EE->recompileAndRelinkFunction(fn). This will require some C++ code to delete the original function body, then splice the body of the new function into the old function.
-Chris