I have a number of questions about the correct usage of the LLVM IR exception handling intrinsics. I am implementing a language of my own and have come to consider implementing exceptions and exception handling.
I looked at the IR generated by Clang for some simple functions. I saw calls to, for example, __cxa_throw. But what I didn’t see is any DWARF data tables or SJLJ pushing/popping. I know that for some targets, including the one that I use most, which is mingw32, there are multiple possible implementations (DWARF and SEH). So how can the code generator know how to implement the intrinsics like landing pad?
Furthermore, even if there is some option in the LLVM API which I did not see, which specifies which option to use, then why are some other parts of the EH API so low-level? If the backend can determine that I intended Itanium ABI DWARF exception handling, then it should also know how to implement throw and catch based on that spec. It therefore seems unnecessary that other parts of the API involve digging around in exception tables.
The documentation also raises further questions about other EH implementations. Only Itanium ABI and SJLJ are referenced. I’m pretty sure that SEH is a derivative of SJLJ, but what about the other EH handling mechanisms, like Windows x64?
There are also intrinsics for values that make no sense. A prime example is the “selector” value, returned by typeid.for. The Itanium ABI makes absolutely no reference to a selector value of any kind. The documentation says that it returns an index into the exception table. How does it behave if SJLJ EH was chosen? What use would that even be, anyway? It is said that it is to be compared against the result of the landingpad instruction, but there’s nothing saying what the landingpad returns or what the results would mean. This is further compounded by the fact that it’s at least implied that the landingpad can actually return virtually any type. How could you compare an i32 against a landingpad that returns a pointer to a pointer to a std::string? What even are the valid return types of a landingpad instruction?
The EH intrinsics specify that some parts of the Itanium ABI handling involve calling functions like __cxa_begin_catch. But how should these functions be implemented? The SJLJ documentation is even more vague- no API is even suggested.
I have searched for examples for implementing EH on top of LLVM, and virtually the only one available is Clang. This is not terribly helpful since you’d inherently expect Clang to be coupled to the various C++ implementations used and it’s not like a C++ implementation is going to be able to take the simple approach.
I guess what I’m saying here is, how on earth do you put these pieces together and actually throw or catch an exception?