[WinEH] Disallow cyclic unwinds
[oota-llvm.git] / docs / ExceptionHandling.rst
index 12899ed8380a56402ccba0efbdf7b8acf63ea41b..41dd4b606b15b0861a331c971c322d3cc7a1c9a5 100644 (file)
@@ -615,15 +615,11 @@ purposes.
 The following new instructions are considered "exception handling pads", in that
 they must be the first non-phi instruction of a basic block that may be the
 unwind destination of an EH flow edge:
-``catchswitch``, ``catchpad``, ``cleanuppad``, and ``terminatepad``.
+``catchswitch``, ``catchpad``, and ``cleanuppad``.
 As with landingpads, when entering a try scope, if the
 frontend encounters a call site that may throw an exception, it should emit an
 invoke that unwinds to a ``catchswitch`` block. Similarly, inside the scope of a
-C++ object with a destructor, invokes should unwind to a ``cleanuppad``. The
-``terminatepad`` instruction exists to represent ``noexcept`` and throw
-specifications with one combined instruction. All potentially throwing calls in
-a ``noexcept`` function should transitively unwind to a terminateblock. Throw
-specifications are not implemented by MSVC, and are not yet supported.
+C++ object with a destructor, invokes should unwind to a ``cleanuppad``.
 
 New instructions are also used to mark the points where control is transferred
 out of a catch/cleanup handler (which will correspond to exits from the
@@ -634,9 +630,9 @@ by normal execution executes a ``cleanupret`` instruction, which is a terminator
 indicating where the active exception will unwind to next.
 
 Each of these new EH pad instructions has a way to identify which action should
-be considered after this action. The ``catchswitch`` and ``terminatepad``
-instructions are terminators, and have a unwind destination operand analogous
-to the unwind destination of an invoke.  The ``cleanuppad`` instruction is not
+be considered after this action. The ``catchswitch`` instruction is a terminator
+and has an unwind destination operand analogous to the unwind destination of an
+invoke.  The ``cleanuppad`` instruction is not
 a terminator, so the unwind destination is stored on the ``cleanupret``
 instruction instead. Successfully executing a catch handler should resume
 normal control flow, so neither ``catchpad`` nor ``catchret`` instructions can
@@ -707,7 +703,9 @@ all of the new IR instructions:
     catchret from %catch to label %return
 
   lpad.terminate:                                   ; preds = %catch.body, %lpad.catch
-    terminatepad within none [void ()* @"\01?terminate@@YAXXZ"] unwind to caller
+    cleanuppad within none []
+    call void @"\01?terminate@@YAXXZ"
+    unreachable
   }
 
 Funclet parent tokens
@@ -725,8 +723,7 @@ The ``catchswitch`` instruction does not create a funclet, but it produces a
 token that is always consumed by its immediate successor ``catchpad``
 instructions. This ensures that every catch handler modelled by a ``catchpad``
 belongs to exactly one ``catchswitch``, which models the dispatch point after a
-C++ try. The ``terminatepad`` instruction cannot contain lexically nested
-funclets inside the termination action, so it does not produce a token.
+C++ try.
 
 Here is an example of what this nesting looks like using some hypothetical
 C++ code:
@@ -745,6 +742,7 @@ C++ code:
   }
 
 .. code-block:: llvm
+
   define void @f() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
   entry:
     invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
@@ -777,3 +775,67 @@ C++ code:
 
 The "inner" ``catchswitch`` consumes ``%1`` which is produced by the outer
 catchswitch.
+
+.. _wineh-constraints:
+
+Funclet transitions
+-----------------------
+
+The EH tables for personalities that use funclets make implicit use of the
+funclet nesting relationship to encode unwind destinations, and so are
+constrained in the set of funclet transitions they can represent.  The related
+LLVM IR instructions accordingly have constraints that ensure encodability of
+the EH edges in the flow graph.
+
+A ``catchswitch``, ``catchpad``, or ``cleanuppad`` is said to be "entered"
+when it executes.  It may subsequently be "exited" by any of the following
+means:
+
+* A ``catchswitch`` is immediately exited when none of its constituent
+  ``catchpad``\ s are appropriate for the in-flight exception and it unwinds
+  to its unwind destination or the caller.
+* A ``catchpad`` and its parent ``catchswitch`` are both exited when a
+  ``catchret`` from the ``catchpad`` is executed.
+* A ``cleanuppad`` is exited when a ``cleanupret`` from it is executed.
+* Any of these pads is exited when control unwinds to the function's caller,
+  either by a ``call`` which unwinds all the way to the function's caller,
+  a nested ``catchswitch`` marked "``unwinds to caller``", or a nested
+  ``cleanuppad``\ 's ``cleanupret`` marked "``unwinds to caller"``.
+* Any of these pads is exited when an unwind edge (from an ``invoke``,
+  nested ``catchswitch``, or nested ``cleanuppad``\ 's ``cleanupret``)
+  unwinds to a destination pad that is not a descendant of the given pad.
+
+Note that the ``ret`` instruction is *not* a valid way to exit a funclet pad;
+it is undefined behavior to execute a ``ret`` when a pad has been entered but
+not exited.
+
+A single unwind edge may exit any number of pads (with the restrictions that
+the edge from a ``catchswitch`` must exit at least itself, and the edge from
+a ``cleanupret`` must exit at least its ``cleanuppad``), and then must enter
+exactly one pad, which must be distinct from all the exited pads.  The parent
+of the pad that an unwind edge enters must be the most-recently-entered
+not-yet-exited pad (after exiting from any pads that the unwind edge exits),
+or "none" if there is no such pad.  This ensures that the stack of executing
+funclets at run-time always corresponds to some path in the funclet pad tree
+that the parent tokens encode.
+
+All unwind edges which exit any given funclet pad (including ``cleanupret``
+edges exiting their ``cleanuppad`` and ``catchswitch`` edges exiting their
+``catchswitch``) must share the same unwind destination.  Similarly, any
+funclet pad which may be exited by unwind to caller must not be exited by
+any exception edges which unwind anywhere other than the caller.  This
+ensures that each funclet as a whole has only one unwind destination, which
+EH tables for funclet personalities may require.  Note that any unwind edge
+which exits a ``catchpad`` also exits its parent ``catchswitch``, so this
+implies that for any given ``catchswitch``, its unwind destination must also
+be the unwind destination of any unwind edge that exits any of its constituent
+``catchpad``\s.  Because ``catchswitch`` has no ``nounwind`` variant, and
+because IR producers are not *required* to annotate calls which will not
+unwind as ``nounwind``, it is legal to nest a ``call`` or an "``unwind to
+caller``\ " ``catchswitch`` within a funclet pad that has an unwind
+destination other than caller; it is undefined behavior for such a ``call``
+or ``catchswitch`` to unwind.
+
+Finally, the funclet pads' unwind destinations cannot form a cycle.  This
+ensures that EH lowering can construct "try regions" with a tree-like
+structure, which funclet-based personalities may require.