question about the LLVM JIT

<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 int

implementation

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

<snip>.
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);

Hi Chris,

Thanks, that was simpler than I thought!
I actually thought I had to create a new global so it would be available for the JIT when it gets to process the "%var = external global int" line.

<snip>

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.

For my purpose it would be ideal if I could give ParseAssemblyString an additional option (or maybe set a global flag somehow) to indicate what should happen when an already defined function is parsed. Would something like this be possible and fit into llvm's design?

Sure, it would be possible to add something like this. I'd prefer a new function, not a bool to ParseAssemblyString though.

-Chris