Emit code for 'unreachable'


Is it somehow possible to have LLVM emit machine code for the ‘unreachable’ IR instruction, which would assert that it indeed never gets reached?



x86 backend emits ud2 instruction in this case

Take a look at LLVM's implementation of an "llvm_unreachable" macro to
see how the LLVM project does this.

Essentially lllvm's unreachable IR instruction is /not/ an assert or
check, it's a compiler hint. So at -O0, LLVM's llvm_unreachable
compiles to a check/assert, at higher optimization levels it compiles
to an intrinsic that is lowered to an unreachable IR instruction and
is used to assist optimization.

- David

I am not seeing this happening, at least not for unreachables that
follow calls to 'noreturn' functions.

I’ve looked through LLVM codegen code and found that SelectionDAGBuilder::visitUnreachable() is basically a no-op. So I don’t see how it could have generated anything…

What would be the right way to go about adding this functionality? Right now I am thinking to add ‘EmitTargetCodeForUnreachable()’ method to TargetSelectionDAGInfo class, so that targets can emit code for ‘unreachable’, if they need that. Does that sound right?


Personally I'm in favor, but others may disagree. Right now clang inserts
calls to llvm.trap(), and that's how we get ud2's when falling off the end
of a function with a return type. That may be the preferred approach for
__builtin_unreachable(), since other clients of LLVM at -O0 may actually
want it to produce code quickly without inserting any debugging aids.

It would be trivial to write a pre-codegen pass that would turn all unreachable instructions into calls to llvm.trap and then unreachable. If a front end wants to guarantee a trap, then it is also free to insert the trap (and it will be deleted later if the basic block becomes truly unreachable).

I'd be somewhat hesitant about making it the default behaviour, because machine instruction passes may want to do some reordering of instructions and once they've got an instruction that is guaranteed to trap then it enforces hard constraints on flow control. To preserve this, you'd need to keep it as a pseudo right up until the very last stage of compilation, which adds some complexity to back ends.


Created patch in Phabricator with Vadim patch from the other thread.