diff options
author | Joseph Tremoulet <jotrem@microsoft.com> | 2016-01-10 04:28:38 +0000 |
---|---|---|
committer | Joseph Tremoulet <jotrem@microsoft.com> | 2016-01-10 04:28:38 +0000 |
commit | e28885e6936fc5487c9e11cda841282d2f43c9d1 (patch) | |
tree | aed0a61d8bcf0063bd4a529d7be2338b6ae3be74 /llvm/docs | |
parent | ca4d93a82fd77b1baadc7f604cd97ed0bafcb717 (diff) | |
download | bcm5719-llvm-e28885e6936fc5487c9e11cda841282d2f43c9d1.tar.gz bcm5719-llvm-e28885e6936fc5487c9e11cda841282d2f43c9d1.zip |
[WinEH] Verify unwind edges against EH pad tree
Summary:
Funclet EH personalities require a tree-like nesting among funclets
(enforced by the ParentPad linkage in the IR), and also require that
unwind edges conform to certain rules with respect to the tree:
- An unwind edge may exit 0 or more ancestor pads
- An unwind edge must enter exactly one EH pad, which must be distinct
from any exited pads
- A cleanupret's edge must exit its cleanuppad
Describe these rules in the LangRef, and enforce them in the verifier.
Reviewers: rnk, majnemer, andrew.w.kaylor
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D15961
llvm-svn: 257272
Diffstat (limited to 'llvm/docs')
-rw-r--r-- | llvm/docs/ExceptionHandling.rst | 43 | ||||
-rw-r--r-- | llvm/docs/LangRef.rst | 82 |
2 files changed, 84 insertions, 41 deletions
diff --git a/llvm/docs/ExceptionHandling.rst b/llvm/docs/ExceptionHandling.rst index 74827c02a27..25248568b61 100644 --- a/llvm/docs/ExceptionHandling.rst +++ b/llvm/docs/ExceptionHandling.rst @@ -775,3 +775,46 @@ 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. diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 103d876b3ce..650d18b9ba4 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -1579,6 +1579,8 @@ caller's deoptimization state to the callee's deoptimization state is semantically equivalent to composing the caller's deoptimization continuation after the callee's deoptimization continuation. +.. _ob_funclet: + Funclet Operand Bundles ^^^^^^^^^^^^^^^^^^^^^^^ @@ -1588,6 +1590,18 @@ is within a particular funclet. There can be at most one ``"funclet"`` operand bundle attached to a call site and it must have exactly one bundle operand. +If any funclet EH pads have been "entered" but not "exited" (per the +`description in the EH doc\ <ExceptionHandling.html#wineh-constraints>`_), +it is undefined behavior to execute a ``call`` or ``invoke`` which: + +* does not have a ``"funclet"`` bundle and is not a ``call`` to a nounwind + intrinsic, or +* has a ``"funclet"`` bundle whose operand is not the most-recently-entered + not-yet-exited funclet EH pad. + +Similarly, if no funclet EH pads have been entered-but-not-yet-exited, +executing a ``call`` or ``invoke`` with a ``"funclet"`` bundle is undefined behavior. + .. _moduleasm: Module-Level Inline Assembly @@ -5404,10 +5418,12 @@ The ``parent`` argument is the token of the funclet that contains the ``catchswitch`` instruction. If the ``catchswitch`` is not inside a funclet, this operand may be the token ``none``. -The ``default`` argument is the label of another basic block beginning with a -"pad" instruction, one of ``cleanuppad`` or ``catchswitch``. +The ``default`` argument is the label of another basic block beginning with +either a ``cleanuppad`` or ``catchswitch`` instruction. This unwind destination +must be a legal target with respect to the ``parent`` links, as described in +the `exception handling documentation\ <ExceptionHandling.html#wineh-constraints>`_. -The ``handlers`` are a list of successor blocks that each begin with a +The ``handlers`` are a nonempty list of successor blocks that each begin with a :ref:`catchpad <i_catchpad>` instruction. Semantics: @@ -5481,20 +5497,12 @@ instruction must be the first non-phi of its parent basic block. The meaning of the tokens produced and consumed by ``catchpad`` and other "pad" instructions is described in the -`Windows exception handling documentation <ExceptionHandling.html#wineh>`. +`Windows exception handling documentation\ <ExceptionHandling.html#wineh>`_. -Executing a ``catchpad`` instruction constitutes "entering" that pad. -The pad may then be "exited" in one of three ways: - -1) explicitly via a ``catchret`` that consumes it. Executing such a ``catchret`` - is undefined behavior if any descendant pads have been entered but not yet - exited. -2) implicitly via a call (which unwinds all the way to the current function's caller), - or via a ``catchswitch`` or a ``cleanupret`` that unwinds to caller. -3) implicitly via an unwind edge whose destination EH pad isn't a descendant of - the ``catchpad``. When the ``catchpad`` is exited in this manner, it is - undefined behavior if the destination EH pad has a parent which is not an - ancestor of the ``catchpad`` being exited. +When a ``catchpad`` has been "entered" but not yet "exited" (as +described in the `EH documentation\ <ExceptionHandling.html#wineh-constraints>`_), +it is undefined behavior to execute a :ref:`call <i_call>` or :ref:`invoke <i_invoke>` +that does not carry an appropriate :ref:`"funclet" bundle <ob_funclet>`. Example: """""""" @@ -5543,11 +5551,10 @@ unwinding was interrupted with a :ref:`catchpad <i_catchpad>` instruction. The code to, for example, destroy the active exception. Control then transfers to ``normal``. -The ``token`` argument must be a token produced by a dominating ``catchpad`` -instruction. The ``catchret`` destroys the physical frame established by -``catchpad``, so executing multiple returns on the same token without -re-executing the ``catchpad`` will result in undefined behavior. -See :ref:`catchpad <i_catchpad>` for more details. +The ``token`` argument must be a token produced by a ``catchpad`` instruction. +If the specified ``catchpad`` is not the most-recently-entered not-yet-exited +funclet pad (as described in the `EH documentation\ <ExceptionHandling.html#wineh-constraints>`_), +the ``catchret``'s behavior is undefined. Example: """""""" @@ -5581,7 +5588,15 @@ Arguments: The '``cleanupret``' instruction requires one argument, which indicates which ``cleanuppad`` it exits, and must be a :ref:`cleanuppad <i_cleanuppad>`. -It also has an optional successor, ``continue``. +If the specified ``cleanuppad`` is not the most-recently-entered not-yet-exited +funclet pad (as described in the `EH documentation\ <ExceptionHandling.html#wineh-constraints>`_), +the ``cleanupret``'s behavior is undefined. + +The '``cleanupret``' instruction also has an optional successor, ``continue``, +which must be the label of another basic block beginning with either a +``cleanuppad`` or ``catchswitch`` instruction. This unwind destination must +be a legal target with respect to the ``parent`` links, as described in the +`exception handling documentation\ <ExceptionHandling.html#wineh-constraints>`_. Semantics: """""""""" @@ -5591,13 +5606,6 @@ The '``cleanupret``' instruction indicates to the :ref:`cleanuppad <i_cleanuppad>` it transferred control to has ended. It transfers control to ``continue`` or unwinds out of the function. -The unwind destination ``continue``, if present, must be an EH pad -whose parent is either ``none`` or an ancestor of the ``cleanuppad`` -being returned from. This constitutes an exceptional exit from all -ancestors of the completed ``cleanuppad``, up to but not including -the parent of ``continue``. -See :ref:`cleanuppad <i_cleanuppad>` for more details. - Example: """""""" @@ -8644,18 +8652,10 @@ The ``cleanuppad`` instruction has several restrictions: - A basic block that is not a cleanup block may not include a '``cleanuppad``' instruction. -Executing a ``cleanuppad`` instruction constitutes "entering" that pad. -The pad may then be "exited" in one of three ways: - -1) explicitly via a ``cleanupret`` that consumes it. Executing such a ``cleanupret`` - is undefined behavior if any descendant pads have been entered but not yet - exited. -2) implicitly via a call (which unwinds all the way to the current function's caller), - or via a ``catchswitch`` or a ``cleanupret`` that unwinds to caller. -3) implicitly via an unwind edge whose destination EH pad isn't a descendant of - the ``cleanuppad``. When the ``cleanuppad`` is exited in this manner, it is - undefined behavior if the destination EH pad has a parent which is not an - ancestor of the ``cleanuppad`` being exited. +When a ``cleanuppad`` has been "entered" but not yet "exited" (as +described in the `EH documentation\ <ExceptionHandling.html#wineh-constraints>`_), +it is undefined behavior to execute a :ref:`call <i_call>` or :ref:`invoke <i_invoke>` +that does not carry an appropriate :ref:`"funclet" bundle <ob_funclet>`. It is undefined behavior for the ``cleanuppad`` to exit via an unwind edge which does not transitively unwind to the same destination as a constituent |