Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLVM exception handling implementation

Tags:

llvm

Just to note, I've read the questions and read the blog posts and I've also referenced the ABI.

What I completely don't understand is how that interacts with LLVM's EH intrinsics. The LLVM EH page gives a very vague overview- not exactly a checklist of "Implement X, Y, Z".

The LLVM EH page references the Itanium ABI directly. This would imply to me that LLVM only supports Itanium ABI exceptions. But I already know that Clang supports ARM and is developing support for Microsoft ABIs. So exactly how specific is LLVM's implementation of EH to the Itanium ABI?

When referencing the _Unwind stuff defined by Itanium ABI, is that obliged to be provided by a backend, or would I have to implement it for myself?

I also noticed that the LLVM IR generated by Clang does not reveal any language-specific tables, any exception frames, exception tables, or anything like that. In that case, how does LLVM know how to generate the language-specific data?

In short, how exactly do you go from LSDAs, EH contexts, and _Unwind_RaiseException to landingpad and resume?

Edit: Just for reference, I'm going to be JITting the resulting code on Windows.

like image 648
Puppy Avatar asked Nov 17 '13 04:11

Puppy


1 Answers

Nowadays Itanium C++ ABI is de facto standard C++ ABI used on many other platforms. Itanium C++ ABI supports zero cost exception handling technique, which is the most widespread technique for today.

To support exception handling one must change the semantics of a function call. Now the calls fork the execution flow. One branch is taken when everything is fine and the second branch is taken in case of an exception. In LLVM IR there is the invoke instruction to call functions that may throw.

When the second branch is taken several kinds of actions may be performed:

  • call destructors (cleanup)
  • continue stack unwinding (resume)
  • enforce throw specifications (filter)
  • restore normal control flow (catch).

It's clear that some additional code must be generated to perform these actions. That's why we've got the landingpad instruction as well. It is the first instruction to be executed after invoke ends up with an exception.

But the main magic is performed at run-time. After an exception is thrown, the language agnostic runtime unwinds the stack, for every frame it finds language specific data area (LSDA) and calls language specific personality routine. The personality routine inspects program counter, LSDA and the current exception. It determines if any cleanup is necessary, if any throw specification is violated or if the exception can be caught by this frame.

As you probably know, all these data (personality routine, catched types, throw specification, cleanup actions) are already specified in landingpad instruction, so no additional data should be passed to the backend to generate exception-related sections in object file.

like image 139
Nikolai Avatar answered Sep 21 '22 05:09

Nikolai