changeset 330:5bea8a1ef905 trunk

[svn r351] Remove unused runtime file for DMD-style exception handling. Improved comments on exception handling runtime.
author ChristianK
date Fri, 11 Jul 2008 20:23:42 +0200
parents 8c1dc3e705da
children 04e1b4930975
files tango/lib/compiler/llvmdc/deh2.d tango/lib/compiler/llvmdc/eh.d
diffstat 2 files changed, 19 insertions(+), 313 deletions(-) [+]
line wrap: on
line diff
--- a/tango/lib/compiler/llvmdc/deh2.d	Fri Jul 11 01:34:04 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,305 +0,0 @@
-/*
- *  Copyright (C) 1999-2005 by Digital Mars, www.digitalmars.com
- *  Written by Walter Bright
- *
- *  This software is provided 'as-is', without any express or implied
- *  warranty. In no event will the authors be held liable for any damages
- *  arising from the use of this software.
- *
- *  Permission is granted to anyone to use this software for any purpose,
- *  including commercial applications, and to alter it and redistribute it
- *  freely, in both source and binary form, subject to the following
- *  restrictions:
- *
- *  o  The origin of this software must not be misrepresented; you must not
- *     claim that you wrote the original software. If you use this software
- *     in a product, an acknowledgment in the product documentation would be
- *     appreciated but is not required.
- *  o  Altered source versions must be plainly marked as such, and must not
- *     be misrepresented as being the original software.
- *  o  This notice may not be removed or altered from any source
- *     distribution.
- */
-
-// Exception handling support for linux
-
-//debug=1;
-
-extern (C)
-{
-    extern void* _deh_beg;
-    extern void* _deh_end;
-
-    int _d_isbaseof(ClassInfo oc, ClassInfo c);
-}
-
-// One of these is generated for each function with try-catch or try-finally
-// all of these structs are located between _deh_beg and _deh_end
-struct FuncTable
-{
-    void *fptr;                 // pointer to start of function
-    DHandlerTable *handlertable; // eh data for this function
-    uint fsize;         // size of function in bytes
-}
-
-// lists all try-catch and try-finally blocks for a given function
-// searched for by eh_finddata()
-struct DHandlerTable
-{
-    void *fptr;                 // pointer to start of function, used but seems redundant
-    uint espoffset;             // offset of ESP from EBP
-    uint retoffset;             // offset from start of function to return code, unused!
-    uint nhandlers;             // dimension of handler_info[]
-    DHandlerInfo handler_info[1];
-}
-
-// information for a single try-finally or try-catch block
-struct DHandlerInfo
-{
-    uint offset;                // offset from function address to start of guarded section
-    uint endoffset;             // offset of end of guarded section
-    int enclosing_index;        // enclosing table index, for nested trys
-    uint cioffset;              // offset to DCatchInfo data from start of DHandlerTable 
-                                // (!=0 if try-catch)
-    void *finally_code;         // pointer to finally code to execute
-                                // (!=0 if try-finally)
-}
-
-// Create one of these for each try-catch
-struct DCatchInfo
-{
-    uint ncatches;                      // number of catch blocks
-    DCatchBlock catch_block[1];         // data for each catch block
-}
-
-// one for each catch in try-catch
-struct DCatchBlock
-{
-    ClassInfo type;             // catch type
-    uint bpoffset;              // EBP offset of catch var
-    void *code;                 // catch handler code
-}
-
-
-alias int (*fp_t)();   // function pointer in ambient memory model
-
-void terminate()
-{
-    asm
-    {
-        hlt ;
-    }
-}
-
-/*******************************************
- * Given address that is inside a function,
- * figure out which function it is in.
- * Return DHandlerTable if there is one, NULL if not.
- */
-
-DHandlerTable *__eh_finddata(void *address)
-{
-    FuncTable *ft;
-
-//    debug printf("__eh_finddata(address = x%x)\n", address);
-//    debug printf("_deh_beg = x%x, _deh_end = x%x\n", &_deh_beg, &_deh_end);
-    for (ft = cast(FuncTable *)&_deh_beg;
-         ft < cast(FuncTable *)&_deh_end;
-         ft++)
-    {
-//      debug printf("\tfptr = x%x, fsize = x%03x, handlertable = x%x\n",
-//              ft.fptr, ft.fsize, ft.handlertable);
-
-        if (ft.fptr <= address &&
-            address < cast(void *)(cast(char *)ft.fptr + ft.fsize))
-        {
-//          debug printf("\tfound handler table\n");
-            return ft.handlertable;
-        }
-    }
-//    debug printf("\tnot found\n");
-    return null;
-}
-
-
-/******************************
- * Given EBP, find return address to caller, and caller's EBP.
- * Input:
- *   regbp       Value of EBP for current function
- *   *pretaddr   Return address
- * Output:
- *   *pretaddr   return address to caller
- * Returns:
- *   caller's EBP
- */
-
-uint __eh_find_caller(uint regbp, uint *pretaddr)
-{
-    uint bp = *cast(uint *)regbp;
-
-    if (bp)         // if not end of call chain
-    {
-        // Perform sanity checks on new EBP.
-        // If it is screwed up, terminate() hopefully before we do more damage.
-        if (bp <= regbp)
-            // stack should grow to smaller values
-            terminate();
-
-        *pretaddr = *cast(uint *)(regbp + int.sizeof);
-    }
-    return bp;
-}
-
-/***********************************
- * Throw a D object.
- */
-
-extern (Windows) void _d_throw(Object *h)
-{
-    uint regebp;
-
-    debug
-    {
-        printf("_d_throw(h = %p, &h = %p)\n", h, &h);
-        printf("\tvptr = %p\n", *cast(void **)h);
-    }
-
-    asm
-    {
-        mov regebp,EBP  ;
-    }
-
-    while (1)           // for each function on the stack
-    {
-        DHandlerTable *handler_table;
-        FuncTable *pfunc;
-        DHandlerInfo *handler;
-        uint calleraddr;
-        uint funcoffset;
-        int index;
-        int dim;
-        int ndx;
-        int enclosing_ndx;
-
-        regebp = __eh_find_caller(regebp,&calleraddr);
-        if (!regebp)
-        {   // if end of call chain
-            debug printf("end of call chain\n");
-            break;
-        }
-        debug printf("found caller, EBP = x%x, calleraddr = x%x\n", regebp, calleraddr);
-        
-        // find DHandlerTable associated with function
-        handler_table = __eh_finddata(cast(void *)calleraddr);
-        if (!handler_table)         // if no static data
-        {
-            debug printf("no handler table\n");
-            continue;
-        }
-        funcoffset = cast(uint)handler_table.fptr;
-
-        debug
-        {
-            printf("calleraddr = x%x\n",cast(uint)calleraddr);
-            printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
-            regebp,funcoffset,handler_table.espoffset,handler_table.retoffset);
-        }
-
-        dim = handler_table.nhandlers;
-
-        debug
-        {
-            printf("handler_info[]:\n");
-            for (int i = 0; i < dim; i++)
-            {
-                handler = &handler_table.handler_info[i];
-                printf("\t[%d]: offset = x%04x, endoffset = x%04x, enclosing_index = %d, cioffset = x%04x, finally_code = %x\n",
-                        i, handler.offset, handler.endoffset, handler.enclosing_index, handler.cioffset, handler.finally_code);
-            }
-        }
-
-        // Find index of DHandlerInfo coresponding to the innermost
-        // try block wrapping calleraddr
-        index = -1;
-        for (int i = 0; i < dim; i++)
-        {
-            handler = &handler_table.handler_info[i];
-
-            debug printf("i = %d, handler.offset = %04x\n", i, funcoffset + handler.offset);
-            if (cast(uint)calleraddr > funcoffset + handler.offset &&
-                cast(uint)calleraddr <= funcoffset + handler.endoffset)
-                index = i; // don't break if found, want innermost try
-        }
-        debug printf("index = %d\n", index);
-
-        // walk through handler infos for all try blocks enclosing the call,
-        // starting with the innermost one we just found
-        for (ndx = index; ndx != -1; ndx = enclosing_ndx)
-        {
-            handler = &handler_table.handler_info[ndx];
-            enclosing_ndx = handler.enclosing_index;
-            
-            if (handler.cioffset)
-            {
-                // this is a catch handler (no finally)
-                DCatchInfo *pci;
-                int ncatches;
-                int i;
-
-                pci = cast(DCatchInfo *)(cast(char *)handler_table + handler.cioffset);
-                ncatches = pci.ncatches;
-                for (i = 0; i < ncatches; i++)
-                {
-                    DCatchBlock *pcb;
-                    ClassInfo ci = **cast(ClassInfo **)h;
-
-                    pcb = &pci.catch_block[i];
-
-                    if (_d_isbaseof(ci, pcb.type))
-                    {   // Matched the catch type, so we've found the handler.
-
-                        // Initialize catch variable
-                        *cast(void **)(regebp + (pcb.bpoffset)) = h;
-
-                        // Jump to catch block. Does not return.
-                        {
-                            uint catch_esp;
-                            fp_t catch_addr;
-
-                            catch_addr = cast(fp_t)(pcb.code);
-                            catch_esp = regebp - handler_table.espoffset - fp_t.sizeof;
-                            asm
-                            {
-                                mov     EAX,catch_esp   ;
-                                mov     ECX,catch_addr  ;
-                                mov     [EAX],ECX       ;
-                                mov     EBP,regebp      ;
-                                mov     ESP,EAX         ; // reset stack
-                                ret                     ; // jump to catch block
-                            }
-                        }
-                    }
-                }
-            }
-            else if (handler.finally_code)
-            {   // Call finally block
-                // Note that it is unnecessary to adjust the ESP, as the finally block
-                // accesses all items on the stack as relative to EBP.
-
-                void *blockaddr = handler.finally_code;
-
-                asm
-                {
-                    push        EBX             ;
-                    mov         EBX,blockaddr   ;
-                    push        EBP             ;
-                    mov         EBP,regebp      ;
-                    call        EBX             ;
-                    pop         EBP             ;
-                    pop         EBX             ;
-                }
-            }
-        }
-    }
-}
-
--- a/tango/lib/compiler/llvmdc/eh.d	Fri Jul 11 01:34:04 2008 +0200
+++ b/tango/lib/compiler/llvmdc/eh.d	Fri Jul 11 20:23:42 2008 +0200
@@ -1,6 +1,8 @@
-/*
- * Temporary exception handling stubs
+/**
+ * This module contains functions and structures required for
+ * exception handling.
  */
+module eh;
 
 import util.console;
 
@@ -14,7 +16,7 @@
     int _d_isbaseof(ClassInfo oc, ClassInfo c);
 }
 
-// libunwind stuff
+// libunwind headers
 extern(C)
 {
     enum _Unwind_Reason_Code
@@ -60,7 +62,8 @@
 }
 
 
-// helpers
+// helpers for reading certain DWARF data
+//TODO: It may not be a good idea to use exceptions for error handling within exception handling code
 private ubyte* get_uleb128(ubyte* addr, ref size_t res)
 {
   res = 0;
@@ -108,16 +111,24 @@
 }
 
 
-
+// exception struct used by the runtime.
+// _d_throw allocates a new instance and passes the address of its
+// _Unwind_Exception member to the unwind call. The personality
+// routine is then able to get the whole struct by looking at the data
+// surrounding the unwind info.
 struct _d_exception
 {
   Object exception_object;
   _Unwind_Exception unwind_info;
 }
 
+// the 8-byte string identifying the type of exception
+// the first 4 are for vendor, the second 4 for language
+//TODO: This may be the wrong way around
 char[8] _d_exception_class = "LLDCD1\0\0";
 
-//TODO: cleanup handling
+// the personality routine gets called by the unwind handler and is responsible for
+// reading the EH tables and deciding what to do
 extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context)
 {
   // check ver: the C++ Itanium ABI only allows ver == 1
@@ -185,11 +196,11 @@
   debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset);
 
   // now we need the exception's classinfo to find a handler
-  // the exceptionObject is actually a member of a larger struct that
+  // the exception_info is actually a member of a larger _d_exception struct
   // the runtime allocated. get that now
   _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof);
 
-  // if there's no actionOffset and no landingpad, continue unwinding
+  // if there's no action offset and no landing pad, continue unwinding
   if(!action_offset && !landing_pad)
     return _Unwind_Reason_Code.CONTINUE_UNWIND;