[LLVMdev] RFC: Exception Handling Proposal II

Renato Golin renato.golin at arm.com
Wed Nov 24 05:47:50 PST 2010


On 24 November 2010 13:27, Bill Wendling <wendling at apple.com> wrote:
> There are two different bits of information in the proposal that address this: the "unwind edge" from the invoke and the region number. It's the "unwind edge" which carries the bit of information that you're asking about. My mental view of this is that the region number correlates to the dispatch instruction (and, therefore, the catch blocks) and the unwind edge correlates to the cleanups. (This isn't exactly correct, but it helps to understand how all of this information will be used to generate the correct tables, etc.)

Hi Bill,

That's exactly how I pictured, glad I got it right... ;)


> So the above code would look something like this:
>
> entry:
>  invoke @f.run() to %bb unwind to %FooCleanup region(1)
> bb:
>  invoke @b.run() to %bb2 unwind to %BarCleanup region(1)
> bb2:
>  invoke @z.run() to %bb3 unwind to %BazCleanup region(1)
> ...
> BazCleanup:
>  ; do stuff
>  br %BarCleanup
> BarCleanup:
>  ; do stuff
>  br %FooCleanup
> FooCleanup:
>  ; do stuff
>  br %Dispatch
> Dispatch:
>  dispatch region(1) resume %block
>    catches [ ... ]
>
> and so on.

I see. The front-end is responsible for knowing that baz, bar and foo
cleanup area are chained together.

So, if I got it right, the dispatch area is common for the whole
function, all final cleanup areas point to the dispatch, and the
back-end knows which dispatch "instruction" to call based on the
region number. The dispatch instructions then would encode what type
of dispatch they were just based on the filters, catches, etc.



> If we remove the invoke instructions, the "unwind to" information then goes onto the basic block itself. E.g.:
>
> bb: unwind to %FooCleanup
>  call @f1.run()
>  call @f2.run()
>  call @f3.run()
>  call @f4.run()

In the general case, that simplifies a lot.

But in this case, if you were constructing the objects as you call
them (as previous example), you'd have to tell the call to which
cleanup landing pad you have to go.

One option is to separate in basic blocks with different cleanup landing pads:

bb: unwind to %FooCleanup
 call @f1.run()
 br bb1
bb1: unwind to %BarCleanup
 call @f2.run()
 br bb2
bb1: unwind to %BazCleanup
 call @f3.run()
 %0 = div i32 7 i32 0  ; this throws in Java and goes to BazCleanup
 br bb3
bb1: unwind to %Dispatch  ; no cleanup
 call @f4.run()
 br bb4



> I kept it purely from a practical standpoint: it will be easier (and thus quicker) to do it this way. :-) Also, it could be done a bit more incrementally than completely removing the invoke. But I'm not opposed to removing the invoke.

I hadn't quite got the role of the invoke in your intermediary model,
now I get it. ;)

I think we should ultimately treat calls like instructions and not
mark them in any specific way regarding EH.

cheers,
--renato




More information about the llvm-dev mailing list