diff options
author | mike-m <mikem.llvm@gmail.com> | 2010-05-06 23:45:43 +0000 |
---|---|---|
committer | mike-m <mikem.llvm@gmail.com> | 2010-05-06 23:45:43 +0000 |
commit | 68cb31901c590cabceee6e6356d62c84142114cb (patch) | |
tree | 6444bddc975b662fbe47d63cd98a7b776a407c1a /docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt | |
parent | c26ae5ab7e2d65b67c97524e66f50ce86445dec7 (diff) | |
download | llvm-68cb31901c590cabceee6e6356d62c84142114cb.tar.gz llvm-68cb31901c590cabceee6e6356d62c84142114cb.tar.bz2 llvm-68cb31901c590cabceee6e6356d62c84142114cb.tar.xz |
Overhauled llvm/clang docs builds. Closes PR6613.
NOTE: 2nd part changeset for cfe trunk to follow.
*** PRE-PATCH ISSUES ADDRESSED
- clang api docs fail build from objdir
- clang/llvm api docs collide in install PREFIX/
- clang/llvm main docs collide in install
- clang/llvm main docs have full of hard coded destination
assumptions and make use of absolute root in static html files;
namely CommandGuide tools hard codes a website destination
for cross references and some html cross references assume
website root paths
*** IMPROVEMENTS
- bumped Doxygen from 1.4.x -> 1.6.3
- splits llvm/clang docs into 'main' and 'api' (doxygen) build trees
- provide consistent, reliable doc builds for both main+api docs
- support buid vs. install vs. website intentions
- support objdir builds
- document targets with 'make help'
- correct clean and uninstall operations
- use recursive dir delete only where absolutely necessary
- added call function fn.RMRF which safeguards against botched 'rm -rf';
if any target (or any variable is evaluated) which attempts
to remove any dirs which match a hard-coded 'safelist', a verbose
error will be printed and make will error-stop.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103213 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt')
-rw-r--r-- | docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt | 202 |
1 files changed, 0 insertions, 202 deletions
diff --git a/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt b/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt deleted file mode 100644 index b546301d35..0000000000 --- a/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt +++ /dev/null @@ -1,202 +0,0 @@ -Meeting notes: Implementation idea: Exception Handling in C++/Java - -The 5/18/01 meeting discussed ideas for implementing exceptions in LLVM. -We decided that the best solution requires a set of library calls provided by -the VM, as well as an extension to the LLVM function invocation syntax. - -The LLVM function invocation instruction previously looks like this (ignoring -types): - - call func(arg1, arg2, arg3) - -The extension discussed today adds an optional "with" clause that -associates a label with the call site. The new syntax looks like this: - - call func(arg1, arg2, arg3) with funcCleanup - -This funcHandler always stays tightly associated with the call site (being -encoded directly into the call opcode itself), and should be used whenever -there is cleanup work that needs to be done for the current function if -an exception is thrown by func (or if we are in a try block). - -To support this, the VM/Runtime provide the following simple library -functions (all syntax in this document is very abstract): - -typedef struct { something } %frame; - The VM must export a "frame type", that is an opaque structure used to - implement different types of stack walking that may be used by various - language runtime libraries. We imagine that it would be typical to - represent a frame with a PC and frame pointer pair, although that is not - required. - -%frame getStackCurrentFrame(); - Get a frame object for the current function. Note that if the current - function was inlined into its caller, the "current" frame will belong to - the "caller". - -bool isFirstFrame(%frame f); - Returns true if the specified frame is the top level (first activated) frame - for this thread. For the main thread, this corresponds to the main() - function, for a spawned thread, it corresponds to the thread function. - -%frame getNextFrame(%frame f); - Return the previous frame on the stack. This function is undefined if f - satisfies the predicate isFirstFrame(f). - -Label *getFrameLabel(%frame f); - If a label was associated with f (as discussed below), this function returns - it. Otherwise, it returns a null pointer. - -doNonLocalBranch(Label *L); - At this point, it is not clear whether this should be a function or - intrinsic. It should probably be an intrinsic in LLVM, but we'll deal with - this issue later. - - -Here is a motivating example that illustrates how these facilities could be -used to implement the C++ exception model: - -void TestFunction(...) { - A a; B b; - foo(); // Any function call may throw - bar(); - C c; - - try { - D d; - baz(); - } catch (int) { - ...int Stuff... - // execution continues after the try block: the exception is consumed - } catch (double) { - ...double stuff... - throw; // Exception is propogated - } -} - -This function would compile to approximately the following code (heavy -pseudo code follows): - -Func: - %a = alloca A - A::A(%a) // These ctors & dtors could throw, but we ignore this - %b = alloca B // minor detail for this example - B::B(%b) - - call foo() with fooCleanup // An exception in foo is propogated to fooCleanup - call bar() with barCleanup // An exception in bar is propogated to barCleanup - - %c = alloca C - C::C(c) - %d = alloca D - D::D(d) - call baz() with bazCleanup // An exception in baz is propogated to bazCleanup - d->~D(); -EndTry: // This label corresponds to the end of the try block - c->~C() // These could also throw, these are also ignored - b->~B() - a->~A() - return - -Note that this is a very straight forward and literal translation: exactly -what we want for zero cost (when unused) exception handling. Especially on -platforms with many registers (ie, the IA64) setjmp/longjmp style exception -handling is *very* impractical. Also, the "with" clauses describe the -control flow paths explicitly so that analysis is not adversly effected. - -The foo/barCleanup labels are implemented as: - -TryCleanup: // Executed if an exception escapes the try block - c->~C() -barCleanup: // Executed if an exception escapes from bar() - // fall through -fooCleanup: // Executed if an exception escapes from foo() - b->~B() - a->~A() - Exception *E = getThreadLocalException() - call throw(E) // Implemented by the C++ runtime, described below - -Which does the work one would expect. getThreadLocalException is a function -implemented by the C++ support library. It returns the current exception -object for the current thread. Note that we do not attempt to recycle the -shutdown code from before, because performance of the mainline code is -critically important. Also, obviously fooCleanup and barCleanup may be -merged and one of them eliminated. This just shows how the code generator -would most likely emit code. - -The bazCleanup label is more interesting. Because the exception may be caught -by the try block, we must dispatch to its handler... but it does not exist -on the call stack (it does not have a VM Call->Label mapping installed), so -we must dispatch statically with a goto. The bazHandler thus appears as: - -bazHandler: - d->~D(); // destruct D as it goes out of scope when entering catch clauses - goto TryHandler - -In general, TryHandler is not the same as bazHandler, because multiple -function calls could be made from the try block. In this case, trivial -optimization could merge the two basic blocks. TryHandler is the code -that actually determines the type of exception, based on the Exception object -itself. For this discussion, assume that the exception object contains *at -least*: - -1. A pointer to the RTTI info for the contained object -2. A pointer to the dtor for the contained object -3. The contained object itself - -Note that it is necessary to maintain #1 & #2 in the exception object itself -because objects without virtual function tables may be thrown (as in this -example). Assuming this, TryHandler would look something like this: - -TryHandler: - Exception *E = getThreadLocalException(); - switch (E->RTTIType) { - case IntRTTIInfo: - ...int Stuff... // The action to perform from the catch block - break; - case DoubleRTTIInfo: - ...double Stuff... // The action to perform from the catch block - goto TryCleanup // This catch block rethrows the exception - break; // Redundant, eliminated by the optimizer - default: - goto TryCleanup // Exception not caught, rethrow - } - - // Exception was consumed - if (E->dtor) - E->dtor(E->object) // Invoke the dtor on the object if it exists - goto EndTry // Continue mainline code... - -And that is all there is to it. - -The throw(E) function would then be implemented like this (which may be -inlined into the caller through standard optimization): - -function throw(Exception *E) { - // Get the start of the stack trace... - %frame %f = call getStackCurrentFrame() - - // Get the label information that corresponds to it - label * %L = call getFrameLabel(%f) - while (%L == 0 && !isFirstFrame(%f)) { - // Loop until a cleanup handler is found - %f = call getNextFrame(%f) - %L = call getFrameLabel(%f) - } - - if (%L != 0) { - call setThreadLocalException(E) // Allow handlers access to this... - call doNonLocalBranch(%L) - } - // No handler found! - call BlowUp() // Ends up calling the terminate() method in use -} - -That's a brief rundown of how C++ exception handling could be implemented in -llvm. Java would be very similar, except it only uses destructors to unlock -synchronized blocks, not to destroy data. Also, it uses two stack walks: a -nondestructive walk that builds a stack trace, then a destructive walk that -unwinds the stack as shown here. - -It would be trivial to get exception interoperability between C++ and Java. - |