diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-12-12 05:38:55 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-12-12 05:38:55 +0000 |
commit | 8a1c45d6e86d54c40835fa8638d1fd900071783c (patch) | |
tree | e485010342db16bc7c4de112e89d5b5e23b29bba /llvm/docs | |
parent | a38312a9a4eeb8ab8976adf5712fadd68dd763cf (diff) | |
download | bcm5719-llvm-8a1c45d6e86d54c40835fa8638d1fd900071783c.tar.gz bcm5719-llvm-8a1c45d6e86d54c40835fa8638d1fd900071783c.zip |
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
Diffstat (limited to 'llvm/docs')
-rw-r--r-- | llvm/docs/ExceptionHandling.rst | 151 | ||||
-rw-r--r-- | llvm/docs/LangRef.rst | 362 |
2 files changed, 225 insertions, 288 deletions
diff --git a/llvm/docs/ExceptionHandling.rst b/llvm/docs/ExceptionHandling.rst index 5b495d9863c..12899ed8380 100644 --- a/llvm/docs/ExceptionHandling.rst +++ b/llvm/docs/ExceptionHandling.rst @@ -522,16 +522,12 @@ table. Exception Handling using the Windows Runtime ================================================= -(Note: Windows C++ exception handling support is a work in progress and is not -yet fully implemented. The text below describes how it will work when -completed.) - Background on Windows exceptions --------------------------------- -Interacting with exceptions on Windows is significantly more complicated than on -Itanium C++ ABI platforms. The fundamental difference between the two models is -that Itanium EH is designed around the idea of "successive unwinding," while +Interacting with exceptions on Windows is significantly more complicated than +on Itanium C++ ABI platforms. The fundamental difference between the two models +is that Itanium EH is designed around the idea of "successive unwinding," while Windows EH is not. Under Itanium, throwing an exception typically involes allocating thread local @@ -618,10 +614,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 invoke: ``catchpad``, ``cleanuppad``, and -``terminatepad``. As with landingpads, when entering a try scope, if the +unwind destination of an EH flow edge: +``catchswitch``, ``catchpad``, ``cleanuppad``, and ``terminatepad``. +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 ``catchpad`` block. Similarly, inside the scope of a +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 @@ -634,26 +631,20 @@ generated funclet). A catch handler which reaches its end by normal execution executes a ``catchret`` instruction, which is a terminator indicating where in the function control is returned to. A cleanup handler which reaches its end by normal execution executes a ``cleanupret`` instruction, which is a terminator -indicating where the active exception will unwind to next. A catch or cleanup -handler which is exited by another exception being raised during its execution will -unwind through a ``catchendpad`` or ``cleanuupendpad`` (respectively). The -``catchendpad`` and ``cleanupendpad`` instructions are considered "exception -handling pads" in the same sense that ``catchpad``, ``cleanuppad``, and -``terminatepad`` are. - -Each of these new EH pad instructions has a way to identify which -action should be considered after this action. The ``catchpad`` and -``terminatepad`` instructions are terminators, and have a label operand considered -to be an unwind destination analogous to the unwind destination of an invoke. The -``cleanuppad`` instruction is different from the other two in that it is not a -terminator. The code inside a cleanuppad runs before transferring control to the -next action, so the ``cleanupret`` and ``cleanupendpad`` instructions are the -instructions that hold a label operand and unwind to the next EH pad. All of -these "unwind edges" may refer to a basic block that contains an EH pad instruction, -or they may simply unwind to the caller. Unwinding to the caller has roughly the -same semantics as the ``resume`` instruction in the ``landingpad`` model. When -inlining through an invoke, instructions that unwind to the caller are hooked -up to unwind to the unwind destination of the call site. +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 +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 +unwind. All of these "unwind edges" may refer to a basic block that contains an +EH pad instruction, or they may unwind to the caller. Unwinding to the caller +has roughly the same semantics as the ``resume`` instruction in the landingpad +model. When inlining through an invoke, instructions that unwind to the caller +are hooked up to unwind to the unwind destination of the call site. Putting things together, here is a hypothetical lowering of some C++ that uses all of the new IR instructions: @@ -694,33 +685,95 @@ all of the new IR instructions: call void @"\01??_DCleanup@@QEAA@XZ"(%struct.Cleanup* nonnull %obj) nounwind br label %return - return: ; preds = %invoke.cont.2, %invoke.cont.3 - %retval.0 = phi i32 [ 0, %invoke.cont.2 ], [ %9, %catch ] + return: ; preds = %invoke.cont.3, %invoke.cont.2 + %retval.0 = phi i32 [ 0, %invoke.cont.2 ], [ %3, %invoke.cont.3 ] ret i32 %retval.0 - ; EH scope code, ordered innermost to outermost: - - lpad.cleanup: ; preds = %invoke.cont - %cleanup = cleanuppad [] - call void @"\01??_DCleanup@@QEAA@XZ"(%struct.Cleanup* nonnull %obj) nounwind - cleanupret %cleanup unwind label %lpad.catch + lpad.cleanup: ; preds = %invoke.cont.2 + %0 = cleanuppad within none [] + call void @"\01??1Cleanup@@QEAA@XZ"(%struct.Cleanup* nonnull %obj) nounwind + cleanupret %0 unwind label %lpad.catch - lpad.catch: ; preds = %entry, %lpad.cleanup - %catch = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e] - to label %catch.body unwind label %catchend + lpad.catch: ; preds = %lpad.cleanup, %entry + %1 = catchswitch within none [label %catch.body] unwind label %lpad.terminate catch.body: ; preds = %lpad.catch + %catch = catchpad within %1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e] invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont.3 unwind label %catchend + to label %invoke.cont.3 unwind label %lpad.terminate invoke.cont.3: ; preds = %catch.body - %9 = load i32, i32* %e, align 4 - catchret %catch to label %return + %3 = load i32, i32* %e, align 4 + catchret from %catch to label %return + + lpad.terminate: ; preds = %catch.body, %lpad.catch + terminatepad within none [void ()* @"\01?terminate@@YAXXZ"] unwind to caller + } + +Funclet parent tokens +----------------------- - catchend: ; preds = %lpad.catch, %catch.body - catchendpad unwind label %lpad.terminate +In order to produce tables for EH personalities that use funclets, it is +necessary to recover the nesting that was present in the source. This funclet +parent relationship is encoded in the IR using tokens produced by the new "pad" +instructions. The token operand of a "pad" or "ret" instruction indicates which +funclet it is in, or "none" if it is not nested within another funclet. - lpad.terminate: ; preds = %catchend - terminatepad [void ()* @"\01?terminate@@YAXXZ"] - unwind to caller +The ``catchpad`` and ``cleanuppad`` instructions establish new funclets, and +their tokens are consumed by other "pad" instructions to establish membership. +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. + +Here is an example of what this nesting looks like using some hypothetical +C++ code: + +.. code-block:: c + + void f() { + try { + throw; + } catch (...) { + try { + throw; + } catch (...) { + } + } } + +.. code-block:: llvm + define void @f() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { + entry: + invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1 + to label %unreachable unwind label %catch.dispatch + + catch.dispatch: ; preds = %entry + %0 = catchswitch within none [label %catch] unwind to caller + + catch: ; preds = %catch.dispatch + %1 = catchpad within %0 [i8* null, i32 64, i8* null] + invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1 + to label %unreachable unwind label %catch.dispatch2 + + catch.dispatch2: ; preds = %catch + %2 = catchswitch within %1 [label %catch3] unwind to caller + + catch3: ; preds = %catch.dispatch2 + %3 = catchpad within %2 [i8* null, i32 64, i8* null] + catchret from %3 to label %try.cont + + try.cont: ; preds = %catch3 + catchret from %1 to label %try.cont6 + + try.cont6: ; preds = %try.cont + ret void + + unreachable: ; preds = %catch, %entry + unreachable + } + +The "inner" ``catchswitch`` consumes ``%1`` which is produced by the outer +catchswitch. diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 58198f7af7d..09efa75515c 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -5001,10 +5001,8 @@ control flow, not values (the one exception being the The terminator instructions are: ':ref:`ret <i_ret>`', ':ref:`br <i_br>`', ':ref:`switch <i_switch>`', ':ref:`indirectbr <i_indirectbr>`', ':ref:`invoke <i_invoke>`', -':ref:`resume <i_resume>`', ':ref:`catchpad <i_catchpad>`', -':ref:`catchendpad <i_catchendpad>`', +':ref:`resume <i_resume>`', ':ref:`catchswitch <i_catchswitch>`', ':ref:`catchret <i_catchret>`', -':ref:`cleanupendpad <i_cleanupendpad>`', ':ref:`cleanupret <i_cleanupret>`', ':ref:`terminatepad <i_terminatepad>`', and ':ref:`unreachable <i_unreachable>`'. @@ -5362,9 +5360,9 @@ Example: resume { i8*, i32 } %exn -.. _i_catchpad: +.. _i_catchswitch: -'``catchpad``' Instruction +'``catchswitch``' Instruction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: @@ -5372,155 +5370,125 @@ Syntax: :: - <resultval> = catchpad [<args>*] - to label <normal label> unwind label <exception label> + <resultval> = catchswitch within <parent> [ label <handler1>, label <handler2>, ... ] unwind to caller + <resultval> = catchswitch within <parent> [ label <handler1>, label <handler2>, ... ] unwind label <default> Overview: """"""""" -The '``catchpad``' instruction is used by `LLVM's exception handling -system <ExceptionHandling.html#overview>`_ to specify that a basic block -is a catch block --- one where a personality routine attempts to transfer -control to catch an exception. -The ``args`` correspond to whatever information the personality -routine requires to know if this is an appropriate place to catch the -exception. Control is transfered to the ``exception`` label if the -``catchpad`` is not an appropriate handler for the in-flight exception. -The ``normal`` label should contain the code found in the ``catch`` -portion of a ``try``/``catch`` sequence. The ``resultval`` has the type -:ref:`token <t_token>` and is used to match the ``catchpad`` to -corresponding :ref:`catchrets <i_catchret>`. +The '``catchswitch``' instruction is used by `LLVM's exception handling system +<ExceptionHandling.html#overview>`_ to describe the set of possible catch handlers +that may be executed by the :ref:`EH personality routine <personalityfn>`. Arguments: """""""""" -The instruction takes a list of arbitrary values which are interpreted -by the :ref:`personality function <personalityfn>`. +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 ``catchpad`` must be provided a ``normal`` label to transfer control -to if the ``catchpad`` matches the exception and an ``exception`` -label to transfer control to if it doesn't. +The ``default`` argument is the label of another basic block beginning with a +"pad" instruction, one of ``cleanuppad``, ``terminatepad``, or +``catchswitch``. + +The ``handlers`` are a list of successor blocks that each begin with a +:ref:`catchpad <i_catchpad>` instruction. Semantics: """""""""" -When the call stack is being unwound due to an exception being thrown, -the exception is compared against the ``args``. If it doesn't match, -then control is transfered to the ``exception`` basic block. -As with calling conventions, how the personality function results are -represented in LLVM IR is target specific. +Executing this instruction transfers control to one of the successors in +``handlers``, if appropriate, or continues to unwind via the unwind label if +present. -The ``catchpad`` instruction has several restrictions: - -- A catch block is a basic block which is the unwind destination of - an exceptional instruction. -- A catch block must have a '``catchpad``' instruction as its - first non-PHI instruction. -- A catch block's ``exception`` edge must refer to a catch block or a - catch-end block. -- There can be only one '``catchpad``' instruction within the - catch block. -- A basic block that is not a catch block may not include a - '``catchpad``' instruction. -- A catch block which has another catch block as a predecessor may not have - any other predecessors. -- It is undefined behavior for control to transfer from a ``catchpad`` to a - ``ret`` without first executing a ``catchret`` that consumes the - ``catchpad`` or unwinding through its ``catchendpad``. -- It is undefined behavior for control to transfer from a ``catchpad`` to - itself without first executing a ``catchret`` that consumes the - ``catchpad`` or unwinding through its ``catchendpad``. +The ``catchswitch`` is both a terminator and a "pad" instruction, meaning that +it must be both the first non-phi instruction and last instruction in the basic +block. Therefore, it must be the only non-phi instruction in the block. Example: """""""" .. code-block:: llvm - ;; A catch block which can catch an integer. - %tok = catchpad [i8** @_ZTIi] - to label %int.handler unwind label %terminate + dispatch1: + %cs1 = catchswitch within none [label %handler0, label %handler1] unwind to caller + dispatch2: + %cs2 = catchswitch within %parenthandler [label %handler0] unwind label %cleanup -.. _i_catchendpad: +.. _i_catchpad: -'``catchendpad``' Instruction -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +'``catchpad``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: """"""" :: - catchendpad unwind label <nextaction> - catchendpad unwind to caller + <resultval> = catchpad within <catchswitch> [<args>*] Overview: """"""""" -The '``catchendpad``' instruction is used by `LLVM's exception handling -system <ExceptionHandling.html#overview>`_ to communicate to the -:ref:`personality function <personalityfn>` which invokes are associated -with a chain of :ref:`catchpad <i_catchpad>` instructions; propagating an -exception out of a catch handler is represented by unwinding through its -``catchendpad``. Unwinding to the outer scope when a chain of catch handlers -do not handle an exception is also represented by unwinding through their -``catchendpad``. - -The ``nextaction`` label indicates where control should transfer to if -none of the ``catchpad`` instructions are suitable for catching the -in-flight exception. - -If a ``nextaction`` label is not present, the instruction unwinds out of -its parent function. The -:ref:`personality function <personalityfn>` will continue processing -exception handling actions in the caller. +The '``catchpad``' instruction is used by `LLVM's exception handling +system <ExceptionHandling.html#overview>`_ to specify that a basic block +begins a catch handler --- one where a personality routine attempts to transfer +control to catch an exception. Arguments: """""""""" -The instruction optionally takes a label, ``nextaction``, indicating -where control should transfer to if none of the preceding -``catchpad`` instructions are suitable for the in-flight exception. +The ``catchswitch`` operand must always be a token produced by a +:ref:`catchswitch <i_catchswitch>` instruction in a predecessor block. This +ensures that each ``catchpad`` has exactly one predecessor block, and it always +terminates in a ``catchswitch``. + +The ``args`` correspond to whatever information the personality routine +requires to know if this is an appropriate handler for the exception. Control +will transfer to the ``catchpad`` if this is the first appropriate handler for +the exception. + +The ``resultval`` has the type :ref:`token <t_token>` and is used to match the +``catchpad`` to corresponding :ref:`catchrets <i_catchret>` and other nested EH +pads. Semantics: """""""""" -When the call stack is being unwound due to an exception being thrown -and none of the constituent ``catchpad`` instructions match, then -control is transfered to ``nextaction`` if it is present. If it is not -present, control is transfered to the caller. +When the call stack is being unwound due to an exception being thrown, the +exception is compared against the ``args``. If it doesn't match, control will +not reach the ``catchpad`` instruction. The representation of ``args`` is +entirely target and personality function-specific. -The ``catchendpad`` instruction has several restrictions: +Like the :ref:`landingpad <i_landingpad>` instruction, the ``catchpad`` +instruction must be the first non-phi of its parent basic block. -- A catch-end block is a basic block which is the unwind destination of - an exceptional instruction. -- A catch-end block must have a '``catchendpad``' instruction as its - first non-PHI instruction. -- There can be only one '``catchendpad``' instruction within the - catch-end block. -- A basic block that is not a catch-end block may not include a - '``catchendpad``' instruction. -- Exactly one catch block may unwind to a ``catchendpad``. -- It is undefined behavior to execute a ``catchendpad`` if none of the - '``catchpad``'s chained to it have been executed. -- It is undefined behavior to execute a ``catchendpad`` twice without an - intervening execution of one or more of the '``catchpad``'s chained to it. -- It is undefined behavior to execute a ``catchendpad`` if, after the most - recent execution of the normal successor edge of any ``catchpad`` chained - to it, some ``catchret`` consuming that ``catchpad`` has already been - executed. -- It is undefined behavior to execute a ``catchendpad`` if, after the most - recent execution of the normal successor edge of any ``catchpad`` chained - to it, any other ``catchpad`` or ``cleanuppad`` has been executed but has - not had a corresponding - ``catchret``/``cleanupret``/``catchendpad``/``cleanupendpad`` executed. +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>`. + +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``, ``cleanupret``, or ``terminatepad`` 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. Example: """""""" .. code-block:: llvm - catchendpad unwind label %terminate - catchendpad unwind to caller + dispatch: + %cs = catchswitch within none [label %handler0] unwind to caller + ;; A catch block which can catch an integer. + handler0: + %tok = catchpad within %cs [i8** @_ZTIi] .. _i_catchret: @@ -5532,7 +5500,7 @@ Syntax: :: - catchret <value> to label <normal> + catchret from <token> to label <normal> Overview: """"""""" @@ -5552,105 +5520,24 @@ transfer to next. Semantics: """""""""" -The '``catchret``' instruction ends the existing (in-flight) exception -whose unwinding was interrupted with a -:ref:`catchpad <i_catchpad>` instruction. -The :ref:`personality function <personalityfn>` gets a chance to execute -arbitrary code to, for example, run a C++ destructor. -Control then transfers to ``normal``. -It may be passed an optional, personality specific, value. - -It is undefined behavior to execute a ``catchret`` whose ``catchpad`` has -not been executed. - -It is undefined behavior to execute a ``catchret`` if, after the most recent -execution of its ``catchpad``, some ``catchret`` or ``catchendpad`` linked -to the same ``catchpad`` has already been executed. - -It is undefined behavior to execute a ``catchret`` if, after the most recent -execution of its ``catchpad``, any other ``catchpad`` or ``cleanuppad`` has -been executed but has not had a corresponding -``catchret``/``cleanupret``/``catchendpad``/``cleanupendpad`` executed. - -Example: -"""""""" - -.. code-block:: llvm - - catchret %catch label %continue - -.. _i_cleanupendpad: - -'``cleanupendpad``' Instruction -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Syntax: -""""""" - -:: - - cleanupendpad <value> unwind label <nextaction> - cleanupendpad <value> unwind to caller - -Overview: -""""""""" - -The '``cleanupendpad``' instruction is used by `LLVM's exception handling -system <ExceptionHandling.html#overview>`_ to communicate to the -:ref:`personality function <personalityfn>` which invokes are associated -with a :ref:`cleanuppad <i_cleanuppad>` instructions; propagating an exception -out of a cleanup is represented by unwinding through its ``cleanupendpad``. - -The ``nextaction`` label indicates where control should unwind to next, in the -event that a cleanup is exited by means of an(other) exception being raised. - -If a ``nextaction`` label is not present, the instruction unwinds out of -its parent function. The -:ref:`personality function <personalityfn>` will continue processing -exception handling actions in the caller. - -Arguments: -"""""""""" - -The '``cleanupendpad``' instruction requires one argument, which indicates -which ``cleanuppad`` it exits, and must be a :ref:`cleanuppad <i_cleanuppad>`. -It also has an optional successor, ``nextaction``, indicating where control -should transfer to. - -Semantics: -"""""""""" - -When and exception propagates to a ``cleanupendpad``, control is transfered to -``nextaction`` if it is present. If it is not present, control is transfered to -the caller. +The '``catchret``' instruction ends an existing (in-flight) exception whose +unwinding was interrupted with a :ref:`catchpad <i_catchpad>` instruction. The +:ref:`personality function <personalityfn>` gets a chance to execute arbitrary +code to, for example, destroy the active exception. Control then transfers to +``normal``. -The ``cleanupendpad`` instruction has several restrictions: - -- A cleanup-end block is a basic block which is the unwind destination of - an exceptional instruction. -- A cleanup-end block must have a '``cleanupendpad``' instruction as its - first non-PHI instruction. -- There can be only one '``cleanupendpad``' instruction within the - cleanup-end block. -- A basic block that is not a cleanup-end block may not include a - '``cleanupendpad``' instruction. -- It is undefined behavior to execute a ``cleanupendpad`` whose ``cleanuppad`` - has not been executed. -- It is undefined behavior to execute a ``cleanupendpad`` if, after the most - recent execution of its ``cleanuppad``, some ``cleanupret`` or ``cleanupendpad`` - consuming the same ``cleanuppad`` has already been executed. -- It is undefined behavior to execute a ``cleanupendpad`` if, after the most - recent execution of its ``cleanuppad``, any other ``cleanuppad`` or - ``catchpad`` has been executed but has not had a corresponding - ``cleanupret``/``catchret``/``cleanupendpad``/``catchendpad`` executed. +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. Example: """""""" .. code-block:: llvm - cleanupendpad %cleanup unwind label %terminate - cleanupendpad %cleanup unwind to caller + catchret from %catch label %continue .. _i_cleanupret: @@ -5662,8 +5549,8 @@ Syntax: :: - cleanupret <value> unwind label <continue> - cleanupret <value> unwind to caller + cleanupret from <value> unwind label <continue> + cleanupret from <value> unwind to caller Overview: """"""""" @@ -5687,25 +5574,20 @@ 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. -It is undefined behavior to execute a ``cleanupret`` whose ``cleanuppad`` has -not been executed. - -It is undefined behavior to execute a ``cleanupret`` if, after the most recent -execution of its ``cleanuppad``, some ``cleanupret`` or ``cleanupendpad`` -consuming the same ``cleanuppad`` has already been executed. - -It is undefined behavior to execute a ``cleanupret`` if, after the most recent -execution of its ``cleanuppad``, any other ``cleanuppad`` or ``catchpad`` has -been executed but has not had a corresponding -``cleanupret``/``catchret``/``cleanupendpad``/``catchendpad`` executed. +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: """""""" .. code-block:: llvm - cleanupret %cleanup unwind to caller - cleanupret %cleanup unwind label %continue + cleanupret from %cleanup unwind to caller + cleanupret from %cleanup unwind label %continue .. _i_terminatepad: @@ -5717,8 +5599,8 @@ Syntax: :: - terminatepad [<args>*] unwind label <exception label> - terminatepad [<args>*] unwind to caller + terminatepad within <token> [<args>*] unwind label <exception label> + terminatepad within <token> [<args>*] unwind to caller Overview: """"""""" @@ -5752,16 +5634,8 @@ the program is terminated via personality-specific means. Typically, the first argument to ``terminatepad`` specifies what function the personality should defer to in order to terminate the program. -The ``terminatepad`` instruction has several restrictions: - -- A terminate block is a basic block which is the unwind destination of - an exceptional instruction. -- A terminate block must have a '``terminatepad``' instruction as its - first non-PHI instruction. -- There can be only one '``terminatepad``' instruction within the - terminate block. -- A basic block that is not a terminate block may not include a - '``terminatepad``' instruction. +The ``terminatepad`` instruction is both a terminator and a "pad" instruction, +meaning that is always the only non-phi instruction in the basic block. Example: """""""" @@ -5769,7 +5643,7 @@ Example: .. code-block:: llvm ;; A terminate block which only permits integers. - terminatepad [i8** @_ZTIi] unwind label %continue + terminatepad within none [i8** @_ZTIi] unwind label %continue .. _i_unreachable: @@ -8762,7 +8636,7 @@ Syntax: :: - <resultval> = cleanuppad [<args>*] + <resultval> = cleanuppad within <parent> [<args>*] Overview: """"""""" @@ -8775,8 +8649,10 @@ The ``args`` correspond to whatever additional information the :ref:`personality function <personalityfn>` requires to execute the cleanup. The ``resultval`` has the type :ref:`token <t_token>` and is used to -match the ``cleanuppad`` to corresponding :ref:`cleanuprets <i_cleanupret>` -and :ref:`cleanupendpads <i_cleanupendpad>`. +match the ``cleanuppad`` to corresponding :ref:`cleanuprets <i_cleanupret>`. +The ``parent`` argument is the token of the funclet that contains the +``cleanuppad`` instruction. If the ``cleanuppad`` is not inside a funclet, +this operand may be the token ``none``. Arguments: """""""""" @@ -8803,21 +8679,29 @@ The ``cleanuppad`` instruction has several restrictions: cleanup block. - A basic block that is not a cleanup block may not include a '``cleanuppad``' instruction. -- All '``cleanupret``'s and '``cleanupendpad``'s which consume a ``cleanuppad`` - must have the same exceptional successor. -- It is undefined behavior for control to transfer from a ``cleanuppad`` to a - ``ret`` without first executing a ``cleanupret`` or ``cleanupendpad`` that - consumes the ``cleanuppad``. -- It is undefined behavior for control to transfer from a ``cleanuppad`` to - itself without first executing a ``cleanupret`` or ``cleanupendpad`` that - consumes the ``cleanuppad``. + +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``, ``cleanupret``, or ``terminatepad`` 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. + +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 +``cleanupret``. Example: """""""" .. code-block:: llvm - %tok = cleanuppad [] + %tok = cleanuppad within %cs [] .. _intrinsics: |