diff --git a/docs/ExceptionHandling.html b/docs/ExceptionHandling.html new file mode 100644 index 00000000000..d515b4cd0ed --- /dev/null +++ b/docs/ExceptionHandling.html @@ -0,0 +1,460 @@ + + + + Exception Handling in LLVM + + + + +
Exception Handling in LLVM
+ + + + +
+ +
+ +
+

Written by Jim Laskey

+
+ + + +
Introduction
+ + +
+ +

This document is the central repository for all information pertaining to +exception handling in LLVM. It describes the format that LLVM exception +handling information takes, which is useful for those interested in creating +front-ends or dealing directly with the information. Further, this document +provides specific examples of what exception handling information is used for +C/C++.

+ +
+ + +
+ Itanium ABI Zero-cost Exception Handling +
+ +
+ +

Exception handling for most programming languages is designed to recover from +conditions that rarely occur during general use of an application. To that end, +exception handling should not interfere with the main flow of an +application's algorithm by performing checkpointing tasks such as saving +the current pc or register state.

+ +

The Itanium ABI Exception Handling Specification defines a methodology for +providing outlying data in the form of exception tables without inlining +speculative exception handling code in the flow of an application's main +algorithm. Thus, the specification is said to add "zero-cost" to the normal +execution of an application.

+ +

A more complete description of the Itanium ABI exception handling runtime +support of can be found at Itanium C++ ABI: +Exception Handling. A description of the exception frame format can be +found at Exception Frames, with details of the Dwarf +specification at Dwarf 3 +Standard. A description for the C++ exception table formats can be found at +Exception Handling +Tables.

+ +
+ + +
+ Overview +
+ +
+ +

When an exception is thrown in llvm code, the runtime does a best effort to +find a handler suited to process the circumstance.

+ +

The runtime first attempts to find an exception frame corresponding to +the function where the exception was thrown. If the programming language (ex. +C++) supports exception handling, the exception frame contains a reference to an +exception table describing how to process the exception. If the language (ex. +C) does not support exception handling or if the exception needs to be forwarded +to a prior activation, the exception frame contains information about how to +unwind the current activation and restore the state of the prior activation. +This process is repeated until the exception is handled. If the exception is +not handled and no activations remain, then the application is terminated with +an appropriate error message.

+ +

Since different programming languages have different behaviors when handling +exceptions, the exception handling ABI provides a mechanism for supplying +personalities. An exception handling personality is defined by way of a +personality function (ex. for C++ __gxx_personality_v0) which +receives the context of the exception, an exception structure containing +the exception object type and value, and a reference the exception table for the +current function. The personality function for the current compile unit is +specified in a common exception frame.

+ +

The organization of an exception table is language dependent. For C++, an +exception table is organized as a series of code ranges defining what to do if +an exception occurs in that range. Typically, the information associated with a +range defines which types of exception objects (using C++ type info) that +are handled in that range, and an associated action that should take place. +Actions typically pass control to a landing pad.

+ +

A landing pad corresponds to the code found in the catch portion of a +try/catch sequence. When execution resumes at a landing pad, it receives the +exception structure and a selector corresponding to the type of exception +thrown. The selector is then used to determine which catch should actually +process the exception.

+ +
+ + +
+ LLVM Code Generation +
+ +
+ +

At the time of this writing, only C++ exception handling support is available +in LLVM. So the remainder of this document will be somewhat C++-centric.

+ +

From the C++ developers perspective, exceptions are defined in terms of the +throw and try/catch statements. In this section we will +describe the implementation of llvm exception handling in terms of C++ +examples.

+ +
+ + +
+ Throw +
+ +
+ +

Languages that support exception handling typically provide a throw +operation to initiate the exception process. Internally, a throw operation +breaks down into two steps. First, a request is made to allocate exception +space for an exception structure. This structure needs to survive beyond the +current activation. This structure will contain the type and value of the +object being thrown. Second, a call is made to the runtime to raise the +exception, passing the exception structure as an argument.

+ +

In C++, the allocation of the exception structure is done by the +__cxa_allocate_exception runtime function. The exception raising is +handled by __cxa_throw. The type of the exception is represented using +a C++ RTTI type info structure.

+ +
+ + +
+ Try/Catch +
+ +
+ +

A call within the scope of a try statement can potential raise an exception. +In those circumstances, the LLVM C++ front-end replaces the call with an +invoke instruction. Unlike a call, the invoke has two potential +continuation points; where to continue when the call succeeds as per normal, and +where to continue if the call raises an exception, either by a throw or the +unwinding of a throw.

+ +

The term used to define a the place where an invoke continues after an +exception is called a landing pad. LLVM landing pads are conceptually +alternative entry points into where a exception structure reference and a type +info index are passed in as arguments. The landing pad saves the exception +structure reference and then proceeds to select the catch block that corresponds +to the type info of the exception object.

+ +

Two llvm intrinsic functions are used convey information about the landing +pad to the back end.

+ +

llvm.eh.exception takes no +arguments and returns the exception structure reference. The backend replaces +this intrinsic with the code that accesses the first argument of a call. The +LLVM C++ front end generates code to save this value in an alloca location for +further use in the landing pad and catch code.

+ +

llvm.eh.selector takes a minimum of +three arguments. The first argument is the reference to the exception +structure. The second argument is a reference to the personality function to be +used for this try catch sequence. The remaining arguments are references to the +type infos for each of the catch statements in the order they should be tested. +The catch all (...) is represented with a null i8*. The result +of the llvm.eh.selector is the index of +the type info in the corresponding exception table. The LLVM C++ front end +generates code to save this value in an alloca location for further use in the +landing pad and catch code.

+ +

Once the landing pad has the type info selector, the code branches to the +code for the first catch. The catch then checks the value of the type info +selector against the index of type info for that catch. Since the type info +index is not known until all the type info have been gathered in the backend, +the catch code will call the llvm.eh.typeid.for intrinsic to +determine the index for a given type info. If the catch fails to match the +selector then control is passed on to the next catch. Note: Since the landing +pad will not be used if there is no match in the list of type info on the call +to llvm.eh.selector, then neither the +last catch nor catch all need to perform the the check against the +selector.

+ +

Finally, the entry and exit of catch code is bracketed with calls to +__cxa_begin_catch and __cxa_end_catch. +__cxa_begin_catch takes a exception structure reference as an argument +and returns the value of the exception object. __cxa_end_catch +takes a exception structure reference as an argument. This function clears the +exception from the exception space. Note: a rethrow from within the catch may +replace this call with a __cxa_rethrow.

+ +
+ + +
+ Finallys +
+ +
+ +

To handle destructors and cleanups in try code, control may not run directly +from a landing pad to the first catch. Control may actually flow from the +landing pad to clean up code and then to the first catch. Since the required +clean up for each invoke in a try may be different (ex., intervening +constructor), there may be several landing pads for a given try.

+ +
+ + +
+ Throw Filters +
+ +
+ +

C++ allows the specification of which exception types that can be thrown from +a function. To represent this a top level landing pad may exist to filter out +invalid types. To express this in LLVM code the landing pad will call llvm.eh.filter instead of llvm.eh.selector. The arguments are the +same, but what gets created in the exception table is different. llvm.eh.filter will return a negative value +if it doesn't find a match. If no match is found then a call to +__cxa_call_unexpected should be made, otherwise +_Unwind_Resume. Each of these functions require a reference to the +exception structure.

+ +
+ + +
+ Exception Handling Intrinsics +
+ +
+ +

LLVM uses several intrinsic functions (name prefixed with "llvm.eh") to +provide exception handling information at various points in generated code.

+ +
+ + +
+ llvm.eh.exception +
+ +
+
+  i8* %llvm.eh.exception( )
+
+ +

This intrinsic indicates that the exception structure is available at this +point in the code. The backend will replace this intrinsic with code to fetch +the first argument of a call. The effect is that the intrinsic result is the +exception structure reference.

+ +
+ + +
+ llvm.eh.selector +
+ +
+
+  i32 %llvm.eh.selector(i8*, i8*, i8*, ...)
+
+ +

This intrinsic indicates that the exception selector is available at this +point in the code. The backend will replace this intrinsic with code to fetch +the second argument of a call. The effect is that the intrinsic result is the +exception selector.

+ +

llvm.eh.selector takes a minimum of +three arguments. The first argument is the reference to the exception +structure. The second argument is a reference to the personality function to be +used for this try catch sequence. The remaining arguments are references to the +type infos for each of the catch statements in the order they should be tested. +The catch all (...) is represented with a null i8*.

+ +
+ + +
+ llvm.eh.filter +
+ +
+
+  i32 %llvm.eh.filter(i8*, i8*, i8*, ...)
+
+ +

This intrinsic indicates that the exception selector is available at this +point in the code. The backend will replace this intrinsic with code to fetch +the second argument of a call. The effect is that the intrinsic result is the +exception selector.

+ +

llvm.eh.filter takes a minimum of +three arguments. The first argument is the reference to the exception +structure. The second argument is a reference to the personality function to be +used for this function. The remaining arguments are references to the type infos +for each type that can be thrown by the current function.

+ +
+ + +
+ llvm.eh.typeid.for +
+ +
+
+  i32 %llvm.eh.typeid.for(i8*)
+
+ +

This intrinsic returns the type info index in the exception table of the +current function. This value can be used to compare against the result of llvm.eh.selector. The single argument is +a reference to a type info.

+ +
+ + +
+ Asm Table Formats +
+ +
+ +

There are two tables that are used by the exception handling runtime to +determine which actions should take place when an exception is thrown.

+ +
+ + +
+ Exception Handling Frame +
+ +
+ +

An exception handling frame eh_frame is very similar to the unwind +frame used by dwarf debug info. The frame contains all the information +necessary to tear down the current frame and restore the state of the prior +frame. There is an exception handling frame for each function in a compile +unit, plus a common exception handling frame that defines information common to +all functions in the unit.

+ +

Todo - Table details here.

+ +
+ + +
+ Exception Tables +
+ +
+ +

An exception table contains information about what actions to take when an +exception is thrown in a particular part of a function's code. There is +one exception table per function except leaf routines and functions that have +only calls to non-throwing functions will not need an exception table.

+ +

Todo - Table details here.

+ +
+ + +
+ ToDo +
+ +
+ +
    + +
  1. Need to create landing pads for code in between explicit landing pads. +The landing pads will have a zero action and a NULL landing pad address and are +used to inform the runtime that the exception should be rethrown.

  2. + +
  3. Actions for a given function should be folded to save space.

  4. + +
  5. Filters for inlined functions need to be handled more extensively. +Currently it's hardwired for one filter per function.

  6. + +
  7. Testing/Testing/Testing.

  8. + +
+ +
+ + + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + +