Quick trampoline intrinsics question

The specification of llvm.init.trampoline does not say whether the trampoline can safely be moved after code has been generated. Is there any contract about this?

My question is motivated by copying collectors, which may want to relocate procedure objects (in llvm-speak: trampolines). If the generated trampoline code uses a PC-relative call instruction, then either:

  1. The trampoline needs to be updated during relocation (in which case I need a way to recover the target procedure’s address), or

  2. Trampolines cannot be relocated
    I know that I can look at the LLVM implementation to see what it actually does, but if this question is not resolved by the specification of llvm.init.trampoline then the implementation is free to change in future.

Thank you.


I strongly suspect that this use case wasn’t considered. :slight_smile: The honest answer is that an interested party could probably spec whatever they wanted as long as a) it was reasonable and b) it didn’t break existing uses.

I could see possible reasons why we might want a non-relocatable trampoline (i.e. smaller code on a fast path), but I don’t know if we exploit that today.

Without giving it too much thought, is there any reason that trampoline generation shouldn’t follow the global “-fPIC” setting? This would seem like a reasonable way to support both relocatable and non-relocatable trampolines.

Taking a step back, let me ask a more fundamental question. Why does the code need to move? I can understand that the data needing to move - which clearly isn’t supported today for trampolines - but why the code? I would expect the code to be shared between many instances of an “add int parameter at position 2 with value X” object (for example).

On a tangent, I’m not sure that the trampoline mechanism is the right one for procedure objects as you call them. I would expect a lowering closer to a standard struct with a member function. The member function does the parameter manipulation, with the data being stored in the struct. This has the advantage of being ‘normal data’ and thus handled by the existing statepoint support.