disable insertion of unreachables

Hello all,

LLVM inserts unreachable instructions after every call to a terminating function. Is there a way to disable this feature so that it treats terminating function calls like any other function call, so the unreachable instruction would not be inserted? Unfortunately, simply removing the unreachable instructions after the fact would not suffice for my needs because I need to preserve the original control flow of the program. That is, I need to know the instruction that would have been executed if the call to the terminating function didn’t actually terminate the program.

Thanks!

Max

What do you mean by "terminating function call"? Is it one with the
"noreturn" attribute? if so, the assembly language docs say that
program behavior is undefined if such a function ever returns. If
your function could possibly return, it needs to not have that
attribute.

if so, the assembly language docs say that
program behavior is undefined if such a function
ever returns.

Yes, that’s true, but for some static analysis applications such as control dependence analysis for programs that have arbitrary interprocedural control flow, one needs these additional non-executable control flow edges from noreturn functions to their immediate CFG successor.

Is there any way to avoid having the unreachables inserted in the first place?

Max

If there's sensible control flow after a function returns, don't mark
it or calls to it noreturn. If in fact cannot return, the concept of
control flow after the function returns fundamentally makes no sense.

-Eli

if so, the assembly language docs say that
program behavior is undefined if such a function
ever returns.

Yes, that's true, but for some static analysis applications such as control
dependence analysis for programs that have arbitrary interprocedural control
flow, one needs these additional non-executable control flow edges from
noreturn functions to their immediate CFG successor.

But a block containing a noreturn function shouldn't *have* a CFG successor.

Is there any way to avoid having the unreachables inserted in the first
place?

If you do that, you'll have to terminate the block with some other
instruction. Which, according to the language definition, is
guaranteed to never execute.

"noreturn" is not what you're looking for. It means something
completely different from what you have in mind.

If there’s sensible control flow after a function returns, don’t mark
it or calls to it noreturn.

How do I prevent llvm-gcc from labelling a particular function with the noreturn attribute so an unreachable is not inserted after a call to it? Does llvm-gcc keep a list of functions somewhere that it thinks do not return?

Max

llvm-gcc knows all the C library functions that are noreturn. Control
flow after one of those doesn't make sense; if you really want
llvm-gcc to avoid making assumptions about them, use -fno-builtin.

llvm-gcc can also tell if a function is noreturn if the implementation
of the function is in the same file; in that case, there's no easy way
to prevent the functions from getting appropriately marked.

llvm-gcc also marks functions marked with __attribute__((noreturn)) as
noreturn; the solution there is simply not to mark the relevant
functions.

-Eli