Mercurial > projects > ldc
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;