Relocatability of LLVM code

Hi all,

As I understand it, LLVM's JIT memory manager works by allocating a
16Mb block of memory and generating native code into it. Once that
block is exhausted no more functions can be JIT compiled. I'm trying
to figure out ways to work around this limitation.

One idea I had was to use that 16Mb block as a scratch area for
generating code. Once a method has been compiled (and therefore its
size is known) a new block of memory would be allocated and the native
code copied into it. The original copy could then be freed, leaving
the whole 16Mb block free for the next compilation. I realize this
approach is not generically suitable for LLVM, but it might be
possible for the application I'm working on because a) a single thread
manages all compilations sequentially, and b) the compiled methods
don't make direct calls to other methods (so stubs will never be
generated).

What I need to know is, is the native code generated by LLVM
relocatable such that it could be copied to another location in memory
like this? Also, does LLVM do anything to the native code after it is
first emitted? Does it try rewriting it, for example?

Cheers,
Gary

Hi all,

As I understand it, LLVM's JIT memory manager works by allocating a
16Mb block of memory and generating native code into it. Once that
block is exhausted no more functions can be JIT compiled. I'm trying
to figure out ways to work around this limitation.

Nope, I actually fixed this bug in r76902. :slight_smile: Now it allocates
memory in 64K slabs, and when it runs out of space it allocates
another 64K slab.

One idea I had was to use that 16Mb block as a scratch area for
generating code. Once a method has been compiled (and therefore its
size is known) a new block of memory would be allocated and the native
code copied into it. The original copy could then be freed, leaving
the whole 16Mb block free for the next compilation. I realize this
approach is not generically suitable for LLVM, but it might be
possible for the application I'm working on because a) a single thread
manages all compilations sequentially, and b) the compiled methods
don't make direct calls to other methods (so stubs will never be
generated).

What I need to know is, is the native code generated by LLVM
relocatable such that it could be copied to another location in memory
like this? Also, does LLVM do anything to the native code after it is
first emitted? Does it try rewriting it, for example?

That's a good question, and I wish I knew the answer, because if that
were the case the entire memory manager could be dramatically
simplified to emit code into a resizeable buffer (like a BinaryObject
or std::vector<uint8_t>), copy the code into place (wherever the
memory manager wants it to go), and then apply the relocations.

I suspect that the answer is that the code is not relocatable, or else
why would the API be designed this way? OTOH, it may be that the code
was not relocatable when the memory manager was designed.

Reid

I would really like to get to this point, but the JIT just isn't designed that way. Logically, the output of the backend is machine code bytes + relocations. In practice, we don't have this clean separation right now. I'm hoping that the MC stuff we're doing will help get us in this direction.

-Chris

Reid Kleckner wrote: