[llvm-commits] [llvm] r140128 - /llvm/trunk/docs/ExceptionHandling.html

Duncan Sands baldrick at free.fr
Tue Sep 20 01:18:50 PDT 2011


Hi Bill,

> +<p>The<tt>landingpad</tt>  instruction takes a reference to the personality
> +   function to be used for this<tt>try</tt>/<tt>catch</tt>  sequence. The
> +   remainder of the instruction is a list of<i>catch</i>  and<i>filter</i>
> +   clauses. The exception is tested against the clauses sequentially from first
> +   to last. The selector value is a positive number if the exception matched a
> +   type info, a negative number if it matched a filter, and zero if it matched a
> +   cleanup. If nothing is matched, the behaviour of the program
> +   is<a href="#restrictions">undefined</a>.

woah!  In order to have inlining work, the LLVM IR that compares the selector
value with catches (via llvm.eh.typeid.for) needs to call "resume" if nothing
matches.  So I think it would be better to say that if an exception doesn't
match a catch or filter, then control might still get here but with a selector
value that doesn't correspond to any of the catches/filters in the landingpad
instruction.  That automatically forces people to do a "resume" if the selector
doesn't match any of their catches.  And this is what happens if the landingpad
is inlined into another function: if there are some additional catches in the
caller, then they get appended to the landingpad instruction, which means that
you can get the selector value for them even though in the original landing pad
that value didn't correspond to any of the catches/filters.

  If a type info matched, then the
> +   selector value is the index of the type info in the exception table, which
> +   can be obtained using the
> +<a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a>  intrinsic.</p>
>
>   <p>Once the landing pad has the type info selector, the code branches to the
> -   code for the first catch.  The catch then checks the value of the type info
> +   code for the first catch. The catch then checks the value of the type info
>      selector against the index of type info for that catch.  Since the type info
>      index is not known until all the type info have been gathered in the backend,
>      the catch code will call the
> -<a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a>  intrinsic
> -   to determine the index for a given type info.  If the catch fails to match
> -   the selector then control is passed on to the next catch. Note: Since the
> -   landing pad will not be used if there is no match in the list of type info on
> -   the call to<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>, then
> -   neither the last catch nor<i>catch all</i>  need to perform the check
> -   against the selector.</p>
> +<a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a>  intrinsic to
> +   determine the index for a given type info. If the catch fails to match the
> +   selector then control is passed on to the next catch. Note: Since the landing
> +   pad will not be used if there is no match in the list of type info on the
> +   call to the<a href="LangRef.html#i_landingpad"><tt>landingpad</tt>
> +   instruction</a>, then neither the last catch nor<i>catch all</i>  need to
> +   perform the check against the selector.</p>

This last bit is just wrong because of inlining.

>
>   <p>Finally, the entry and exit of catch code is bracketed with calls
>      to<tt>__cxa_begin_catch</tt>  and<tt>__cxa_end_catch</tt>.</p>
> @@ -318,16 +305,14 @@
>
>   <div>
>
> -<p>A cleanup is extra code which needs to be run as part of unwinding
> -   a scope.  C++ destructors are a prominent example, but other
> -   languages and language extensions provide a variety of different
> -   kinds of cleanup.  In general, a landing pad may need to run
> -   arbitrary amounts of cleanup code before actually entering a catch
> -   block.  To indicate the presence of cleanups, a landing pad's call
> -   to<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>  should
> -   end with the argument<tt>i32 0</tt>; otherwise, the unwinder will
> -   not stop at the landing pad if there are no catches or filters that
> -   require it to.</p>
> +<p>A cleanup is extra code which needs to be run as part of unwinding a scope.
> +   C++ destructors are a prominent example, but other languages and language
> +   extensions provide a variety of different kinds of cleanup.  In general, a
> +   landing pad may need to run arbitrary amounts of cleanup code before actually

before -> before or after
In Ada it is after, and due to inlining even in C++ the cleanup code may appear
"in the middle": after comparing the selector with some catches, but before
comparing it with some other catches.

> +   entering a catch block.  To indicate the presence of cleanups, a
> +<a href="LangRef.html#i_landingpad"><tt>landingpad</tt>  instruction</a>
> +   should have a<i>cleanup</i>  clause. Otherwise, the unwinder will not stop at
> +   the landing pad if there are no catches or filters that require it to.</p>
>
>   <p>Do not allow a new exception to propagate out of the execution of a
>      cleanup.  This can corrupt the internal state of the unwinder.
> @@ -337,9 +322,9 @@
>
>   <p>When all cleanups have completed, if the exception is not handled
>      by the current function, resume unwinding by calling the
> -<a href="#llvm_eh_resume"><tt>llvm.eh.resume</tt></a>  intrinsic,
> -   passing in the results of<tt>llvm.eh.exception</tt>  and
> -<tt>llvm.eh.selector</tt>  for the original landing pad.</p>
> +<a href="LangRef.html#i_resume"><tt>resume</tt>  instruction</a>, passing in
> +   the results of the<tt>landingpad</tt>  instruction for the original landing

results -> result

> +   pad.</p>
>
>   </div>
>
> @@ -352,21 +337,19 @@
>
>   <p>C++ allows the specification of which exception types can be thrown from a
>      function.  To represent this a top level landing pad may exist to filter out
> -   invalid types.  To express this in LLVM code the landing pad will
> -   call<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>.  The
> -   arguments are a reference to the exception structure, a reference to the
> -   personality function, the length of the filter expression (the number of type
> -   infos plus one), followed by the type infos themselves.
> -<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>  will return a
> -   negative value if the exception does not match any of the type infos.  If no
> -   match is found then a call to<tt>__cxa_call_unexpected</tt>  should be made,
> -   otherwise<tt>_Unwind_Resume</tt>.  Each of these functions requires a
> -   reference to the exception structure.  Note that the most general form of an
> -<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>  call can contain
> -   any number of type infos, filter expressions and cleanups (though having more
> -   than one cleanup is pointless).  The LLVM C++ front-end can generate such
> -<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>  calls due to
> -   inlining creating nested exception handling scopes.</p>
> +   invalid types.  To express this in LLVM code the
> +<a href="LangRef.html#i_landingpad"><tt>landingpad</tt>  instruction</a>  will
> +   have a filter clause. The clause consists of an array of type infos.
> +<tt>landingpad</tt>  will return a negative value if the exception does not
> +   match any of the type infos. If no match is found then a call
> +   to<tt>__cxa_call_unexpected</tt>  should be made, otherwise
> +<tt>_Unwind_Resume</tt>.

_Unwind_Resume -> resume

   Each of these functions requires a reference to the
> +   exception structure.  Note that the most general form of a
> +<a href="LangRef.html#i_landingpad"><tt>landingpad</tt>  instruction</a>  can
> +   have any number of catch, cleanup, and filter clauses (though having more
> +   than one cleanup is pointless).

As there is now only a cleanup flag, you can't have multiple cleanup "clauses".

  The LLVM C++ front-end can generate such
> +<a href="LangRef.html#i_landingpad"><tt>landingpad</tt>  instructions</a>  due
> +   to inlining creating nested exception handling scopes.</p>
>
>   </div>
>
> @@ -377,29 +360,27 @@
>
>   <div>
>
> -<p>The unwinder delegates the decision of whether to stop in a call
> -   frame to that call frame's language-specific personality function.
> -   Not all personalities functions guarantee that they will stop to
> -   perform cleanups: for example, the GNU C++ personality doesn't do
> -   so unless the exception is actually caught somewhere further up the
> -   stack.  When using this personality to implement EH for a language
> -   that guarantees that cleanups will always be run, be sure to
> -   indicate a catch-all in the
> -<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>  call
> +<p>The unwinder delegates the decision of whether to stop in a call frame to
> +   that call frame's language-specific personality function.  Not all
> +   personalities functions guarantee that they will stop to perform
> +   cleanups. For example, the GNU C++ personality doesn't do so unless the
> +   exception is actually caught somewhere further up the stack.

Here I think it would be good to make clear that in this case the program
exits with a called to terminate - the stack isn't unwound at all (well,
the unwinder crawls up the stack in the search phase but no more than that).

   When using this
> +   personality to implement EH for a language that guarantees that cleanups will
> +   always be run, be sure to indicate a catch-all in the
> +<a href="LangRef.html#i_landingpad"><tt>landingpad</tt>  instruction</a>
>      rather than just cleanups.</p>

Ada uses forced unwinding rather than catch-alls to get this effect.  I suggest
just dropping this bit of advice.

>
> -<p>In order for inlining to behave correctly, landing pads must be
> -   prepared to handle selector results that they did not originally
> -   advertise.  Suppose that a function catches exceptions of
> -   type<tt>A</tt>, and it's inlined into a function that catches
> -   exceptions of type<tt>B</tt>.  The inliner will update the
> -   selector for the inlined landing pad to include the fact
> -   that<tt>B</tt>  is caught.  If that landing pad assumes that it
> -   will only be entered to catch an<tt>A</tt>, it's in for a rude
> -   surprise.  Consequently, landing pads must test for the selector
> -   results they understand and then resume exception propagation
> -   with the<a href="#llvm_eh_resume"><tt>llvm.eh.resume</tt></a>
> -   intrinsic if none of the conditions match.</p>
> +<p>In order for inlining to behave correctly, landing pads must be prepared to
> +   handle selector results that they did not originally advertise.

Right!

   Suppose that
> +   a function catches exceptions of type<tt>A</tt>, and it's inlined into a
> +   function that catches exceptions of type<tt>B</tt>.  The inliner will update
> +   the<tt>landingpad</tt>  instruction for the inlined landing pad to include
> +   the fact that<tt>B</tt>  is caught.  If that landing pad assumes that it will
> +   only be entered to catch an<tt>A</tt>, it's in for a rude surprise.
> +   Consequently, landing pads must test for the selector results they understand
> +   and then resume exception propagation with the
> +<a href="LangRef.html#i_resume"><tt>resume</tt>  instruction</a>  if none of
> +   the conditions match.</p>

Nice explanation.

Ciao, Duncan.



More information about the llvm-commits mailing list