Exceptions for my own programming language (original) (raw)

I am working on an back end for my own programming language. I think the most challenging feature will be exceptions. I’ve read the documentation, but I’m still missing some crucial pieces.

What I (think I) know:

My main question now is about the landingpad arguments. In particular, I need to provide at least one catch clause with a “type” of exception. But which type should I use there? I don’t have to provide a type when using _Unwind_RaiseException, so how does the mechanism know that my exception should land on this landingpad?

I would also appreciate any information about what the personality function is supposed to do, because the LLVM documentation is really light on the details:

The personality attribute permits functions to specify what function to use for exception handling.

😕

In particular, about the personality function, I’m wondering how it should jump to the LLVM landing pad.

Unfortunately, exception handling in LLVM is a bit of a mess with
several “secret” handshakes in play that’s not well-documented in
general. I myself am not the most well-versed in this topic, but let me
provide what information again.

The basic structure of exception handling is described in the Itanium
C++ ABI [1] here: C++ ABI for Itanium: Exception Handling.
There are several slightly different variations (e.g., ARM C++ exception
handling is different), but the core idea is essentially this:

As you can see, there’s essentially some amount of secret handshake
going on, with LLVM needing to generate a special exception-handling
table, the format of which is largely dictated by the personality
function, although most of them are in practice basically the same as
the one used by __gxx_personality_v0 (I don’t know the degree to which
LLVM supports unknown personality functions).

The way LLVM handles Itanium-style exception handling is to use the
landingpad to define essentially what the entry in the special lookup
table should look like, and the result of the instruction itself is the
registers set up by the personality function before returning control to
(the exceptional return address of) the function. It’s probably best to
look at how Clang actually generates the LLVM code to get an
understanding of what code looks like: Compiler Explorer
(I’ve disabled demangling so that you don’t get confused as to what the
output looks like, given that the _ZTI* names all demangle as “typeinfo
for xyz”).

For the standard __gxx_personality_v0, the first return value is the
_Unwind_Exception * object passed into _Unwind_RaiseException (which
is not the same as the address of the object being thrown!), and the
second return value is the type index of the handler.

As for the values you should fill in into the catch lines of the
landingpad… that’s part of the secret handshake between you and your
personality function!

[1] Despite its name, the Itanium ABI is the C++ ABI that is common
essentially for every platform except compiling with MSVC.