Advise to implement return barriar

Hi llvm-dev,
I’m trying to build a managed language that requires function call with return barrier using LLVM IR.

During execution of a function call, if a special event during the call happens, it will overwrite the return address in the stack frame to another block, then continue the execution in the original function until it’s actually returned, then execute a different block.

It will be equivalent to the following pseudo code:

flag, X = doSomeCall()
if (!flag) {
// something use X
} else {
// something else use X

While I’d like to make the flag implicit by changing the return address in stack frame from use1 to use2 and duplicate the post-call part, because such flag check could be added to almost every call site for my language and the probability returning other branch will be extremely unlikely.

May I get some advise on how to implement the return barrier like this, even just locally?

Introducing a new type of invoke inst that allows 2 normal destinations plus 2 unwind destination seems too much changes to make.

Currently, I’m trying to add a new intrinsic IMPLICIT_FORK that returns a bool that can be used for conditional branch to introduce an extra successor in IR without emitting an code to trick the CFG passes, and that successor block must start with another intrinsic call CONTINUE which continues the call: it just emit a NOP but returns the value, and PC for the NOP will be stored by some global metadata value so the runtime knows which is the new PC value to overwrite, and address of NOP inst can still be used to unwind the stack properly.

I’ve also tried using a general trampoline to be new return address, and based on return value from calling convention to record the return value, and throw an exception to go back to original method.


Something like this recent conversation?