Why is CallBr restricted to only inline-asm?

I’m currently building a feature that has multiple return paths from a given function. CallBr would be ideal for this, as I’m currently limiting scope to functions without return values, so the issues with the return values not being valid on fall-through cases doesn’t come up.

Currently the verifier throws an error if CallBr is used for calls to non-inline asm, but I’m wondering if there is a significant reason for this, or if it would be possible to use for a normal function call with only minor tweaks to the verifier to guarantee that there were no return values being lost.

A couple things to note: I’m not expecting it to produce any machine code to enable the multiple returns - it’s already being handled via overwriting the return address on the stack. I just need the CFG to reflect that I can have an immediate outgoing edge from the call to the alternate return destination.

I’d also tried using just using inlined asm to call the function, but I’d like proper register allocation so I don’t need to manually put the call values in the right registers each time as that’s causing some optimization issues.

The original motivation for callbr was asm goto support, so that’s what the current implementation is limited to. Extending it to other use-cases should be possible, if someone puts in the work.

I think supporting non-inlineasm callbr at the IR level would be fairly straightforward – likely just a matter of adjusting some assertions. It’s everything else that would require significant design work: Supporting multiple return destinations in functions, as well as backend support for both the callbr lowering and the return lowering, and presumably some ABI adjustments for passing the additional return addresses.

Feel free to extend it; relaxing the verifier check should be straightforward, but note that callbr doesn’t yet support outputs along indirect edges, so you’ll only be able to safely call functions that return void.