[llvm-dev] help me understand how nounwind attribute on functions works?
David Chisnall via llvm-dev
llvm-dev at lists.llvm.org
Thu Feb 9 09:12:11 PST 2017
On 9 Feb 2017, at 08:41, Reid Kleckner via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> On Wed, Feb 8, 2017 at 5:45 PM, Mehdi Amini <mehdi.amini at apple.com> wrote:
> What isn’t clear to me still is : why shouldn't this be transitive?
> In the example you’re showing, for a caller of f() in bar, what is the advantage of knowing that f() is nounwind if it an exception can still be thrown? What does it allow?
> We know an exception cannot unwind out of f. An exception can be thrown inside something that f calls, but it must be caught before it unwinds beyond f.
Why? With the x86-64 ABI, for example, f is required to emit async unwind tables. It has a personality function that knows how to handle cleanups, but there are none here, so the generic unwinder will happily unwind through the code. The only ways to prevent exceptions from being propagated are to explicitly catch them, or to use something like a C++ exception specifier so that the personality function will explicitly block exception propagation.
In this example, given that doThing is not marked as noexcept, we will emit unwind tables that explicitly allow unwinding through f; however, when the unwinder tries to unwind into the next stack frame it will find that there is no unwind record. Depending on how lazy we are in defining the PC ranges in the unwind table, this will either cause stack corruption or a run-time abort from well-formed code.
More information about the llvm-dev