[LLVMdev] Nested exception handlers

Talin viridia at gmail.com
Fri May 29 19:08:31 PDT 2009


Since llvm-gcc is a rather large code base, which I have never looked at 
(or even run), could you give me a starting point of where to look?

One thing I'd be interested in knowing is whether the 
llvm.eh.exception() intrinsic can be called more than once in a landing pad.

Say for example I have a nested try block, so that there are two landing 
pads, one for the inner try block, and one for the outer. Let's say that 
the inner landing pad has a "finally" block - a cleanup handler. This 
means that the inner try block must catch every exception type so that 
it can execute the cleanup even if there was no specific catch handler 
for that exception type.

At the end of the finally block, we need to jump to various different 
destinations depending on how the finally block was entered - return, 
fall through, throw, etc. In the case where we failed to catch an 
exception in the inner try block, but the outer try block has a catch 
handler for that exception, the finally block needs to jump to the outer 
landing pad. There are three ways this could happen:

1) Call _Unwind_Resume, using an "invoke" IR instruction whose unwind 
block points to the outer landing pad. This seems like it would be 
expensive however.

2) Branch directly to the start of the outer landing pad, and restart 
the exception dispatch all over. The problem with this is that the outer 
landing pad calls llvm.eh.exception() and llvm.eh.selector(), and I 
don't know if it's valid to call them at this point. Normally you don't 
jump to a landing pad directly, you get there via the personality 
function forcing a jump to that label. I don't know whether it is legal 
for the inner landing pad to jump to the start of the outer landing pad.

3) Branch directly to the individual catch blocks in the outer landing 
pad. In order to know which catch block to branch to, we need to add 
additional selectors to the inner landing pad representing the possible 
catch blocks in the outer landing pad that might catch the inner exception.

The problem with this scheme is that now the liveness of the current 
exception object is all tangled up.  The jump from the inner landing pad 
to the outer catch block passes through one or more cleanup blocks, each 
of which ends with a conditional jump. Each cleanup block has multiple 
predecessors, each predecessor setting a state variable telling the 
cleanup block where to jump to after finishing the cleanup. For a given 
cleanup block, "return" might set state = 0, "fall through" = 1, "catch 
block 1" = 2, "catch block 2" = 3 and so on. Notice that for some of 
those states (2, 3), there is a current active exception object, and for 
some (0, 1) there is not. That means that the value of the exception 
object is undefined for some predecessor blocks, so a regular phi node, 
won't work, and even storing the exception pointer in a local variable 
won't work because the compiler will notice that there are some code 
paths where the exception variable never gets set. Now, I happen to know 
that the code will never jump to a catch handler when there is no active 
throwable, but I am not sure that the compiler knows this.

Duncan Sands wrote:
> Hi Talin,
>
>   
>> Now that I've got exceptions working, I'm kind of wondering how to 
>> handle the case of nested "try" blocks. Say I have some code that looks 
>> like this:
>>     
>
> take a look at what llvm-gcc does for this kind of thing.
>
> Ciao,
>
> Duncan.
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>   




More information about the llvm-dev mailing list