[LLVMdev] RFC: Exception Handling Proposal Revised

Bill Wendling wendling at apple.com
Wed Dec 1 11:52:40 PST 2010


On Dec 1, 2010, at 10:20 AM, Duncan Sands wrote:

> Hi Bill, this proposal seems strangely complicated.  I don't see the advantage
> of the dispatch instruction over just attaching the information to each invoke.
> Right now you have
> 
>   invoke void @_Z3foov()
>     to label %invcont unwind label %catch.handlers
> 
> catch.handlers: landingpad
>   dispatch resume to label %...
>     catches [
>       %struct.__fundamental_type_info_pseudo* @_ZTIi, label %ch.int
>       %struct.__pointer_type_info_pseudo* @_ZTIPKc, label %ch.str
>     ]
>   catchall [i8* null, label % ch.ca]
> 
> Why not combine this into:
> 
>   invoke void @_Z3foov()
>     to label %invcont unwind resume to label %...
>     catches [
>       %struct.__fundamental_type_info_pseudo* @_ZTIi, label %ch.int
>       %struct.__pointer_type_info_pseudo* @_ZTIPKc, label %ch.str
>     ]
>   catchall [i8* null, label % ch.ca]
> 
> ?  That would get rid of the "landingpad" basic block attribute, and rules about
> what can branch to landing pads, that these cannot be split etc.  Your rules
> mean that you can uniquely associate a dispatch instruction with each invoke
> unwind edge, so why not directly attach the dispatch information to the edge,
> i.e. to the invoke?
> 
That was my first proposal (way back when). I ran into the problem of cleanups. Basically, they get in the way of the decision making process. Consider this:

  invoke void @_Z3foov()
    to label %invcont unwind resume to label %...
    catches [
      %struct.__fundamental_type_info_pseudo* @_ZTIi, label %ch.int
      %struct.__pointer_type_info_pseudo* @_ZTIPKc, label %ch.str
    ]
  catchall [i8* null, label % ch.ca]

Now consider that a cleanup must occur here. How do we represent this here and still keep the information that "int" goes to ch.int and "const char *" goes to ch.str? The cleanups must happen before we get to ch.int, ch.str, and ch.ca. And cleanup code can be arbitrarily complex – including the fact that it may not return, or it may have multiple exit points. You end up needing a dispatch-like instruction at the end of the cleanup region so that you can associated the invoke to the decision point – the point where we determine which handler we need to execute. After we realized this, this proposal became the natural way.

>> Syntax:
>> 
>>   dispatch resume to label<resumedest>
> 
> How do you say: if nothing is matched, keep unwinding out of the function?
> Actually I don't see why <resumedest> is useful at all, since you can always
> place a complete set of all handlers into one dispatch, so redispatching is
> not needed.  That said, it might be handy for reducing code duplication.
> 
The <resumedest> will have code to handling unwinding out of the function. Normally, it will just call _Unwind_Resume(). As you saw in the example, though, it may call other things (like `terminate()'). I would love to have a language-neutral way of saying "resume unwinding". I don't know if it's sufficient to rely upon every implementation to call _Unwind_Resume().

>>     catches [
>>       <type>  <val>, label<dest1>
>>       ...
>>     ]
>>     catchall [<type>  <val>, label<dest>  ]
>>     personality [<type>  <value>]
>>     filters [
>>       <type>  <val>,<type>  <val>, ...
> 
> You also need labels for filters.  I know it may not look like it, but
> if you inline a function with a filter into a function with handlers
> then the filter ends up being nested inside outer handlers, resulting
> in the need for a destination.  In fact inlining also means that you
> can't just list filters after catches, you need to consider maybe
> having some catches, then a filter, then some other catches etc.  Or
> perhaps you want to take care of it by chaining dispatches via the
> resumedest?
> 
When I looked at code which inlined functions with filters, it seemed like they were attached to the throwing instructions. In that case, you will have the dispatch of the inlined function, which will be associated with its invokes, and the filter information will exist there. In that way, we have the "nesting" that you described.

>>     ]
>> 
>> The `catches', `catchall', and `filters' clauses are optional. If neither `catches' nor `catchall' is specified, then the landing pad is implicitly a cleanup.
> 
> You may have cleanups to run even if there are handlers, how do you distinguish
> between "have handlers, plus a cleanup to run in any case" and "have handlers,
> no cleanup needs to be run if handlers don't match, just unwind straight
> through"?
> 
The first case is my example. E.g.:

lpad: landingpad
  call void @cleanup(%A* %a)
  dispatch resume to label %unwind
    catches [ . . . ]
etc.

The second one would be the job of the front-end to generate the correct dispatch. E.g:

lpad: landingpad
  dispatch resume to label %unwind
    catches [ . . . ]

>> • The `filters' clause lists the types of exceptions which may be thrown by the
>>   region.
> 
> What is "a region"?
> 
I defined it in the first document, which was referenced:
A "region" is defined as a section of code where, if an exception is thrown
anywhere within that section, control is passed to code that will handle the
exception (called a "landing pad"). The code which handles the specific
exception is unique to that region.

>> onto.catch.handlers:
>>   dispatch resume to %lpad
> 
> What is %lpad?
> 
A typo. It should be %catch.handlers

> As a general remark, I don't see how this is superior to gcc's region scheme,
> which could be adapted to LLVM by (in essence) attaching to an invoke the list
> of all regions (and their info like list of catches) that contain the invoke.
> If you do that then you get something rather close to your proposal, only the
> dispatch instructions have become part of the invokes, you don't need the funny
> landing pad special semantics etc.
> 
Could you describe GCC's region scheme?

-bw

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20101201/cd9b5b03/attachment.html>


More information about the llvm-dev mailing list