landingpad instruction documentation is vague

I am new to the landingpad (which is relatively new too).
Documentation http://llvm.org/docs/LangRef.html#i_landingpad leaves some questions open:

1. What happens when actual exception type isn't listed in catch or filter clauses? Does it still return the corresponding structure like if it was listed? Or behavior is undefined?
2. What is 'somety'? Shouldn't it maybe say "result_type" instead? In the instructions printed by clang++, somety is { i8*, i32 }.
3. What are the allowed values and types passed to catch clause? I see that practically type is i8* and value is bitcast (i8** @<typeinfo> to i8*). Is this target specific? If yes, documentation should mention this, if not, it should describe them.
4. Example in documentation shows catch clause as "catch i8** @_ZTIi" and clang++ generated example shows "catch i8* bitcast (i8** @_ZTIi to i8*)"

Yuri

Hi Yuri,

I am new to the landingpad (which is relatively new too).
Documentation http://llvm.org/docs/LangRef.html#i_landingpad leaves some
questions open:

1. What happens when actual exception type isn't listed in catch or
filter clauses? Does it still return the corresponding structure like if
it was listed? Or behavior is undefined?

if it doesn't match a clause then the exception continues to be unwound.
Note that you can match a catch clause without being equal to the type
in the catch clause (for example because the catch clause type represents
some class B, and thus will also match a class A if B derives from A).

2. What is 'somety'? Shouldn't it maybe say "result_type" instead? In
the instructions printed by clang++, somety is { i8*, i32 }.

The type is not specified to allow for exotic exception handling schemes
in which returning something funky is useful. The code generators only
support Dwarf exception handling and setjmp/longjmp exception handling
which both use { i8*, i32 }, so while you can use any type in the IR,
only this type will work if you use the LLVM code generators to produce
code for your machine. Note that the language reference explicitly says
"The resultval has the type somety".

3. What are the allowed values and types passed to catch clause? I see
that practically type is i8* and value is bitcast (i8** @<typeinfo> to
i8*). Is this target specific? If yes, documentation should mention
this, if not, it should describe them.

No, it's not target specific and in fact any pointer type is OK for a catch
clause. Clang has no need to bitcast to i8* in general, probably it is a
historical hangover from the previous exception handling scheme which did
require i8*. The dragonegg frontend doesn't do such bitcasts and works
perfectly fine.

4. Example in documentation shows catch clause as "catch i8** @_ZTIi"
and clang++ generated example shows "catch i8* bitcast (i8** @_ZTIi to i8*)"

See point 3.

Ciao, Duncan.

[snippet]

  It would be great if this can be put somewhere on the website to clear
LLVM exception handling further. :wink:

Regards,
chenwj

Hi 陳韋任,

This isn't an llvm-specific feature, but how exceptions work in general.

-bw

1. What happens when actual exception type isn't listed in catch or
filter clauses? Does it still return the corresponding structure like if
it was listed? Or behavior is undefined?

if it doesn't match a clause then the exception continues to be unwound.
Note that you can match a catch clause without being equal to the type
in the catch clause (for example because the catch clause type represents
some class B, and thus will also match a class A if B derives from A).

This also means, that in case of multiple exception types handled by one landingpad instruction, type checking is essentially done twice now, once in the landingpad (to match catch or filter), and once more in the code that branches to the handler of the particular type after the landingpad. Before checking was done only once. I think, because of this, new landingpad mechanism has lower performance?

3. What are the allowed values and types passed to catch clause? I see
that practically type is i8* and value is bitcast (i8** @<typeinfo> to
i8*). Is this target specific? If yes, documentation should mention
this, if not, it should describe them.

No, it's not target specific and in fact any pointer type is OK for a catch
clause. Clang has no need to bitcast to i8* in general, probably it is a
historical hangover from the previous exception handling scheme which did
require i8*. The dragonegg frontend doesn't do such bitcasts and works
perfectly fine.

But the value should always be some @<typeinfo>, can't be anything else?

Another question, if landingpad has 'cleanup' flag set, is it required or expected that resume instruction should follow?

Yuri

This isn't an llvm-specific feature, but how exceptions work in general.

  Ugh, Q2 and Q3 are also not llvm-specific feature?

Regards,
chenwj

Hi Yuri,

1. What happens when actual exception type isn't listed in catch or
filter clauses? Does it still return the corresponding structure like if
it was listed? Or behavior is undefined?

if it doesn't match a clause then the exception continues to be unwound.
Note that you can match a catch clause without being equal to the type
in the catch clause (for example because the catch clause type represents
some class B, and thus will also match a class A if B derives from A).

This also means, that in case of multiple exception types handled by one
landingpad instruction, type checking is essentially done twice now, once in the
landingpad (to match catch or filter), and once more in the code that branches
to the handler of the particular type after the landingpad. Before checking was
done only once. I think, because of this, new landingpad mechanism has lower
performance?

there are two steps: the unwinder uses the language specific personality
function to see if the exception object matches a catch clause. If it does, it
identifies which catch clause matched using an integer (called the selector
value), and branches to the landing pad, passing the landing pad two values:
a pointer to the exception object, and the selector value. So far this has
nothing to do with LLVM, it's just how Dwarf unwinding works. At this point,
LLVM has the selector value and needs to branch to the code for the catch
clause based on this. It does this via a series of comparisons and branches
(it could alternatively use a switch). These comparisons aren't comparing
C++ types (that was done by the personality function), they are comparing
integer values. This is pretty quick. In any case it has to be done, and
needless to say GCC does exactly the same thing.

3. What are the allowed values and types passed to catch clause? I see
that practically type is i8* and value is bitcast (i8** @<typeinfo> to
i8*). Is this target specific? If yes, documentation should mention
this, if not, it should describe them.

No, it's not target specific and in fact any pointer type is OK for a catch
clause. Clang has no need to bitcast to i8* in general, probably it is a
historical hangover from the previous exception handling scheme which did
require i8*. The dragonegg frontend doesn't do such bitcasts and works
perfectly fine.

But the value should always be some @<typeinfo>, can't be anything else?

Yes, it needs to be a global variable. However it doesn't have to be a global
variable of any specific type. For example the Ada frontend mostly uses some
complicated global variables, but for Ada's "catch all" it uses a global
variable of integer type.

Another question, if landingpad has 'cleanup' flag set, is it required or
expected that resume instruction should follow?

It's not required by LLVM. What were you planning to do?

Ciao, Duncan.

As Duncan mentioned, Q2 already has an explanation in the documentation for what 'somety' is. As for Q3, it would be rather pedantic to mention that. :slight_smile: Besides, it's implied in the documentation:

"A clause begins with the clause type — catch or filter — and contains the global variable representing the "type" that may be caught or filtered respectively."

-bw

Hi 陳韋任,