From c4f661e3dec2e574a59d32bef8679af832349fd2 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Sat, 15 Aug 2009 08:56:09 +0000 Subject: [PATCH] Reformatting and some cleanup. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79088 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/ExceptionHandling.html | 464 +++++++++++++++++++----------------- 1 file changed, 244 insertions(+), 220 deletions(-) diff --git a/docs/ExceptionHandling.html b/docs/ExceptionHandling.html index 851ed1238be..166fe4cf11d 100644 --- a/docs/ExceptionHandling.html +++ b/docs/ExceptionHandling.html @@ -3,8 +3,12 @@ Exception Handling in LLVM + + +
Exception Handling in LLVM
@@ -58,11 +62,11 @@

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++.

+ 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 + in C/C++.

@@ -74,27 +78,28 @@ C/C++.

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.

+ 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.

+ 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.

+ 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 3 specification at + DWARF 3 Standard. + A description for the C++ exception table formats can be found at + Exception Handling + Tables.

@@ -105,41 +110,44 @@ Tables.

-

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

+

When an exception is thrown in LLVM code, the runtime does its best to find a + handler suited to processing 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.

+ the function where the exception was thrown. If the programming language + (e.g. C++) supports exception handling, the exception frame contains a + reference to an exception table describing how to process the exception. If + the language (e.g. 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 to the exception table for -the current function. The personality function for the current compile unit is -specified in a common exception frame.

+

Because 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 (e.g. __gxx_personality_v0 + in C++), which receives the context of the exception, an exception + structure containing the exception object type and value, and a reference + to 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.

+ 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.

+

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.

@@ -151,12 +159,12 @@ process the exception.

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.

+ 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 and try/catch statements. In this section + we will describe the implementation of LLVM exception handling in terms of + C++ examples.

@@ -168,17 +176,17 @@ examples.

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.

+ 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.

+

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 structure.

@@ -189,67 +197,77 @@ a C++ RTTI type info structure.

-

A call within the scope of a try statement can potentially 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.

+

A call within the scope of a try statement can potentially 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 function entry points 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.

+

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 function entry points where an 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.

+

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

-

llvm.eh.exception takes no -arguments and returns a pointer to the exception structure. This only returns a -sensible value if called after an invoke has branched to a landing pad. Due to -codegen limitations, it must currently be called in the landing pad itself.

+
    +
  1. llvm.eh.exception takes no + arguments and returns a pointer to the exception structure. This only + returns a sensible value if called after an invoke has branched + to a landing pad. Due to code generation limitations, it must currently + be called in the landing pad itself.
  2. -

    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. Each of the remaining arguments is either a -reference to the type info for a catch statement, -a filter expression, -or the number zero representing a cleanup. -The exception is tested against the arguments sequentially from first to last. -The result of the llvm.eh.selector is a -positive number if the exception matched a type info, a negative number if it matched -a filter, and zero if it matched a cleanup. If nothing is matched, the behaviour of -the program is undefined. -This only returns a sensible value if called after an invoke has branched to a -landing pad. Due to codegen limitations, it must currently be called in the -landing pad itself. -If a type info matched then the selector value is the index of the type info in -the exception table, which can be obtained using the -llvm.eh.typeid.for intrinsic.

    +
  3. 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. Each of the + remaining arguments is either a reference to the type info for + a catch statement, a filter + expression, or the number zero (0) representing + a cleanup. The exception is tested against the + arguments sequentially from first to last. The result of + the llvm.eh.selector is a + positive number if the exception matched a type info, a negative number if + it matched a filter, and zero if it matched a cleanup. If nothing is + matched, the behaviour of the program + is undefined. This only returns a sensible + value if called after an invoke has branched to a landing pad. + Due to codegen limitations, it must currently be called in the landing pad + itself. If a type info matched, then the selector value is the index of + the type info in the exception table, which can be obtained using the + llvm.eh.typeid.for + intrinsic.
  4. +

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.

+ 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 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.

+

Finally, the entry and exit of catch code is bracketed with calls + to __cxa_begin_catch and __cxa_end_catch.

+ +
@@ -260,16 +278,15 @@ replace this call with a __cxa_rethrow.

-

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. If cleanups -need to be run, the number zero should be passed as the last -llvm.eh.selector argument. -However for C++ a null i8* must be passed -instead. -

+

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 + (e.g. intervening constructor), there may be several landing pads for a given + try. If cleanups need to be run, the number zero should be passed as the + last llvm.eh.selector argument. + However for C++ a null i8* must + be passed instead.

@@ -280,23 +297,23 @@ instead.
-

C++ allows the specification of which exception types 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.selector. The arguments are a -reference to the exception structure, a reference to the personality function, -the length of the filter expression (the number of type infos plus one), -followed by the type infos themselves. -llvm.eh.selector will return a negative -value if the exception does not match any of the type infos. If no match is -found then a call to __cxa_call_unexpected should be made, otherwise -_Unwind_Resume. Each of these functions requires a reference to the -exception structure. Note that the most general form of an -llvm.eh.selector call can contain -any number of type infos, filter expressions and cleanups (though having more -than one cleanup is pointless). The LLVM C++ front-end can generate such -llvm.eh.selector calls due to inlining -creating nested exception handling scopes.

+

C++ allows the specification of which exception types 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.selector. The + arguments are a reference to the exception structure, a reference to the + personality function, the length of the filter expression (the number of type + infos plus one), followed by the type infos themselves. + llvm.eh.selector will return a + negative value if the exception does not match any of the type infos. If no + match is found then a call to __cxa_call_unexpected should be made, + otherwise _Unwind_Resume. Each of these functions requires a + reference to the exception structure. Note that the most general form of an + llvm.eh.selector call can contain + any number of type infos, filter expressions and cleanups (though having more + than one cleanup is pointless). The LLVM C++ front-end can generate such + llvm.eh.selector calls due to + inlining creating nested exception handling scopes.

@@ -308,23 +325,21 @@ creating nested exception handling scopes.

The semantics of the invoke instruction require that any exception that -unwinds through an invoke call should result in a branch to the invoke's unwind -label. However such a branch will only happen if the -llvm.eh.selector matches. -Thus in order to ensure correct operation, the front-end must only generate -llvm.eh.selector calls that are -guaranteed to always match whatever exception unwinds through the invoke. -For most languages it is enough to pass zero, indicating the presence of -a cleanup, as the last -llvm.eh.selector argument. -However for C++ this is not sufficient, because the C++ personality function -will terminate the program if it detects that unwinding the exception only -results in matches with cleanups. For C++ a null i8* should -be passed as the last -llvm.eh.selector argument instead. -This is interpreted as a catch-all by the C++ personality function, and will -always match. -

+ unwinds through an invoke call should result in a branch to the invoke's + unwind label. However such a branch will only happen if the + llvm.eh.selector matches. Thus in + order to ensure correct operation, the front-end must only generate + llvm.eh.selector calls that are + guaranteed to always match whatever exception unwinds through the invoke. + For most languages it is enough to pass zero, indicating the presence of + a cleanup, as the + last llvm.eh.selector argument. + However for C++ this is not sufficient, because the C++ personality function + will terminate the program if it detects that unwinding the exception only + results in matches with cleanups. For C++ a null i8* should be + passed as the last llvm.eh.selector + argument instead. This is interpreted as a catch-all by the C++ personality + function, and will always match.

@@ -336,7 +351,8 @@ always match.

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

+ provide exception handling information at various points in generated + code.

@@ -347,8 +363,9 @@ provide exception handling information at various points in generated code.

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

This intrinsic returns a pointer to the exception structure.

@@ -361,28 +378,29 @@ provide exception handling information at various points in generated code.

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

This intrinsic is used to compare the exception with the given type infos, -filters and cleanups.

+ filters and cleanups.

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. Each of the remaining arguments is either a -reference to the type info for a catch statement, -a filter expression, -or the number zero representing a cleanup. -The exception is tested against the arguments sequentially from first to last. -The result of the llvm.eh.selector is a -positive number if the exception matched a type info, a negative number if it matched -a filter, and zero if it matched a cleanup. If nothing is matched, the behaviour of -the program is undefined. -If a type info matched then the selector value is the index of the type info in -the exception table, which can be obtained using the -llvm.eh.typeid.for intrinsic.

+ 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. Each of the remaining arguments is + either a reference to the type info for a catch statement, + a filter expression, or the number zero + representing a cleanup. The exception is tested + against the arguments sequentially from first to last. The result of + the llvm.eh.selector is a positive + number if the exception matched a type info, a negative number if it matched + a filter, and zero if it matched a cleanup. If nothing is matched, the + behaviour of the program is undefined. If a type + info matched then the selector value is the index of the type info in the + exception table, which can be obtained using the + llvm.eh.typeid.for intrinsic.

@@ -393,14 +411,15 @@ the exception table, which can be obtained using the
-  i32 %llvm.eh.typeid.for.i32(i8*)
-  i64 %llvm.eh.typeid.for.i64(i8*)
+i32 %llvm.eh.typeid.for.i32(i8*)
+i64 %llvm.eh.typeid.for.i64(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.

+ 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.

@@ -411,22 +430,25 @@ a reference to a type info.

-  i32 %llvm.eh.sjlj.setjmp(i8*)
+i32 %llvm.eh.sjlj.setjmp(i8*)
 
+
-

The SJLJ exception handling uses this intrinsic to force register saving -for the current function and to store the address of the following instruction -for use as a destination address by -llvm.eh.sjlj.longjmp. The buffer format and the overall functioning -of this intrinsic is compatible with the GCC __builtin_setjmp -implementation, allowing code built with the two compilers to interoperate.

+

The SJLJ exception handling uses this intrinsic to force register saving for + the current function and to store the address of the following instruction + for use as a destination address by + llvm.eh.sjlj.longjmp. The buffer format and the overall + functioning of this intrinsic is compatible with the GCC + __builtin_setjmp implementation, allowing code built with the + two compilers to interoperate.

-

The single parameter is a pointer to a five word buffer in which the -calling context is saved. The front end places the frame pointer in the -first word, and the target implementation of this intrinsic should place the -destination address for a -llvm.eh.sjlj.longjmp in the second word. The following three words -are available for use in a target-specific manner.

+

The single parameter is a pointer to a five word buffer in which the calling + context is saved. The front end places the frame pointer in the first word, + and the target implementation of this intrinsic should place the destination + address for a + llvm.eh.sjlj.longjmp in the + second word. The following three words are available for use in a + target-specific manner.

@@ -437,14 +459,15 @@ are available for use in a target-specific manner.

-  i8* %llvm.eh.sjlj.lsda( )
+i8* %llvm.eh.sjlj.lsda( )
 
+

Used for SJLJ based exception handling, the - llvm.eh.sjlj.lsda intrinsic returns the address of the Language -Specific Data Area (LSDA) for the current function. The SJLJ front-end code -stores this address in the exception handling function context for use by -the runtime.

+ llvm.eh.sjlj.lsda intrinsic returns the address of the Language + Specific Data Area (LSDA) for the current function. The SJLJ front-end code + stores this address in the exception handling function context for use by the + runtime.

@@ -455,13 +478,14 @@ the runtime.

-  void %llvm.eh.sjlj.callsite(i32)
+void %llvm.eh.sjlj.callsite(i32)
 
+
-

The SJLJ front-end allocates call site indices for invoke instrucitons. -These values are passed to the back-end via the -llvm.eh.sjlj.callsite -intrinsic, where they are used to build the LSDA call-site table.

+

The SJLJ front-end allocates call site indices for invoke instrucitons. + These values are passed to the back-end via the + llvm.eh.sjlj.callsite + intrinsic, where they are used to build the LSDA call-site table.

@@ -473,7 +497,7 @@ intrinsic, where they are used to build the LSDA call-site table.

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

+ determine which actions should take place when an exception is thrown.

@@ -485,11 +509,11 @@ determine which actions should take place when an exception is thrown.

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.

+ 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.

@@ -503,9 +527,9 @@ all functions in the unit.

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.

+ 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.

@@ -520,7 +544,7 @@ only calls to non-throwing functions will not need an exception table.

    -
  1. Testing/Testing/Testing.

  2. +
  3. Testing/Testing/Testing.