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
>
>