Mercurial > projects > ldc
view tango-0.99.9.patch @ 1651:cb960b882ca3 default tip
bindings were moved to dsource.org/projects/bindings/
author | Moritz Warning <moritzwarning@web.de> |
---|---|
date | Thu, 20 May 2010 20:05:03 +0200 |
parents | 40bd4a0d4870 |
children |
line wrap: on
line source
Index: tango/core/rt/compiler/ldc/rt/lifetime.d =================================================================== --- tango/core/rt/compiler/ldc/rt/lifetime.d (revision 5462) +++ tango/core/rt/compiler/ldc/rt/lifetime.d (working copy) @@ -786,6 +786,7 @@ return *cast(long*)px; } ++/ /** * @@ -849,10 +850,11 @@ /** - * + * Appends a single element to an array. */ -extern (C) byte[] _d_arrayappendcT(TypeInfo ti, ref byte[] x, ...) +extern (C) byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element) { + auto x = cast(byte[]*)array; auto sizeelem = ti.next.tsize(); // array element size auto info = gc_query(x.ptr); auto length = x.length; @@ -879,16 +881,16 @@ assert(newcap >= newlength * sizeelem); newdata = cast(byte *)gc_malloc(newcap + 1, info.attr); memcpy(newdata, x.ptr, length * sizeelem); - (cast(void**)(&x))[1] = newdata; + (cast(void**)x)[1] = newdata; } L1: - byte *argp = cast(byte *)(&ti + 2); + byte *argp = cast(byte *)element; - *cast(size_t *)&x = newlength; + *cast(size_t *)x = newlength; x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; assert((cast(size_t)x.ptr & 15) == 0); assert(gc_sizeOf(x.ptr) > x.length * sizeelem); - return x; + return *x; } @@ -1128,6 +1130,7 @@ return result; } +/+ /** * Index: tango/core/rt/compiler/ldc/rt/eh.d =================================================================== --- tango/core/rt/compiler/ldc/rt/eh.d (revision 5462) +++ tango/core/rt/compiler/ldc/rt/eh.d (working copy) @@ -1,38 +1,34 @@ /** * This module contains functions and structures required for - * exception handling. + * dwarf exception handling with llvm */ module rt.eh; -import ldc.cstdarg; -import rt.compiler.util.console; +//debug = EH_personality; -// debug = EH_personality; - // current EH implementation works on x86 // if it has a working unwind runtime version(X86) { version(linux) version=X86_UNWIND; version(darwin) version=X86_UNWIND; version(solaris) version=X86_UNWIND; - version(freebsd) version=X86_UNWIND; } version(X86_64) { version(linux) version=X86_UNWIND; version(darwin) version=X86_UNWIND; version(solaris) version=X86_UNWIND; - version(freebsd) version=X86_UNWIND; } //version = HP_LIBUNWIND; private extern(C) void abort(); private extern(C) int printf(char*, ...); -private extern(C) int vprintf(char*, va_list va); +//private extern(C) int vprintf(char*, va_list va); // D runtime functions extern(C) { - int _d_isbaseof(ClassInfo oc, ClassInfo c); +// int _d_isbaseof(ClassInfo oc, ClassInfo c); + Object _d_dynamic_cast(Object o, ClassInfo c); } // libunwind headers @@ -74,16 +70,19 @@ // interface to HP's libunwind from http://www.nongnu.org/libunwind/ version(HP_LIBUNWIND) { + // Haven't checked whether and how it has _Unwind_Get{Text,Data}RelBase + pragma (msg, "HP_LIBUNWIND interface is out of date and untested"); + void __libunwind_Unwind_Resume(_Unwind_Exception *); _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *); ptrdiff_t __libunwind_Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context); - ptrdiff_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); + size_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); ptrdiff_t __libunwind_Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value); ptrdiff_t __libunwind_Unwind_SetGR(_Unwind_Context_Ptr context, int index, ptrdiff_t new_value); - ptrdiff_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); + size_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); alias __libunwind_Unwind_Resume _Unwind_Resume; alias __libunwind_Unwind_RaiseException _Unwind_RaiseException; @@ -94,27 +93,30 @@ alias __libunwind_Unwind_SetGR _Unwind_SetGR; alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart; } -else version(X86_UNWIND) +else version(X86_UNWIND) { void _Unwind_Resume(_Unwind_Exception*); _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*); ptrdiff_t _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context); - ptrdiff_t _Unwind_GetIP(_Unwind_Context_Ptr context); + size_t _Unwind_GetIP(_Unwind_Context_Ptr context); ptrdiff_t _Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value); ptrdiff_t _Unwind_SetGR(_Unwind_Context_Ptr context, int index, ptrdiff_t new_value); - ptrdiff_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); + size_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); + + size_t _Unwind_GetTextRelBase(_Unwind_Context_Ptr); + size_t _Unwind_GetDataRelBase(_Unwind_Context_Ptr); } else { // runtime calls these directly void _Unwind_Resume(_Unwind_Exception*) { - console("_Unwind_Resume is not implemented on this platform.\n"); + printf("_Unwind_Resume is not implemented on this platform.\n"); } _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*) { - console("_Unwind_RaiseException is not implemented on this platform.\n"); + printf("_Unwind_RaiseException is not implemented on this platform.\n"); return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; } } @@ -122,14 +124,161 @@ } // error and exit -extern(C) private void fatalerror(char[] format) +extern(C) private void fatalerror(char* format, ...) { - printf("Fatal error in EH code: %.*s\n", format.length, format.ptr); +// va_list args; +// va_start(args, format); + printf("Fatal error in EH code: "); +// vprintf(format, args); + printf("\n"); abort(); } -// helpers for reading certain DWARF data +// DWARF EH encoding enum +// See e.g. http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/dwarfext.html +private enum : ubyte { + DW_EH_PE_omit = 0xff, // value is not present + + // value format + DW_EH_PE_absptr = 0x00, // literal pointer + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, // unsigned 2-byte + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0a, + DW_EH_PE_sdata4 = 0x0b, + DW_EH_PE_sdata8 = 0x0c, + + // value meaning + DW_EH_PE_pcrel = 0x10, // relative to program counter + DW_EH_PE_textrel = 0x20, // relative to .text + DW_EH_PE_datarel = 0x30, // relative to .got or .eh_frame_hdr + DW_EH_PE_funcrel = 0x40, // relative to beginning of function + DW_EH_PE_aligned = 0x50, // is an aligned void* + + // value is a pointer to the actual value + // this is a mask on top of one of the above + DW_EH_PE_indirect = 0x80 +} + +// Helpers for reading DWARF data + +// Given an encoding and a context, return the base to which the encoding is +// relative +private size_t base_of_encoded(_Unwind_Context_Ptr context, ubyte encoding) +{ + if (encoding == DW_EH_PE_omit) + return 0; + + switch (encoding & 0x70) // ignore DW_EH_PE_indirect + { + case DW_EH_PE_absptr, DW_EH_PE_pcrel, DW_EH_PE_aligned: + return 0; + + case DW_EH_PE_textrel: return _Unwind_GetTextRelBase(context); + case DW_EH_PE_datarel: return _Unwind_GetDataRelBase(context); + case DW_EH_PE_funcrel: return _Unwind_GetRegionStart(context); + + default: fatalerror("Unrecognized base for DWARF value"); + } +} + +// Only defined for fixed-size encodings +private size_t size_of_encoded(ubyte encoding) +{ + if (encoding == DW_EH_PE_omit) + return 0; + + switch (encoding & 0x07) // ignore leb128 + { + case DW_EH_PE_absptr: return (void*).sizeof; + case DW_EH_PE_udata2: return 2; + case DW_EH_PE_udata4: return 4; + case DW_EH_PE_udata8: return 8; + + default: fatalerror("Unrecognized fixed-size DWARF value encoding"); + } +} + +// Actual value readers below: read a value from the given ubyte* into the +// output parameter and return the pointer incremented past the value. + +// Like read_encoded_with_base but gets the base from the given context +private ubyte* read_encoded(_Unwind_Context_Ptr context, ubyte encoding, ubyte* p, out size_t val) +{ + return read_encoded_with_base(encoding, base_of_encoded(context, encoding), p, val); +} + +private ubyte* read_encoded_with_base(ubyte encoding, size_t base, ubyte* p, out size_t val) +{ + if (encoding == DW_EH_PE_aligned) + { + auto a = cast(size_t)p; + a = (a + (void*).sizeof - 1) & -(void*).sizeof; + val = *cast(size_t*)a; + return cast(ubyte*)(a + (void*).sizeof); + } + + union U + { + size_t ptr; + ushort udata2; + uint udata4; + ulong udata8; + short sdata2; + int sdata4; + long sdata8; + } + + auto u = cast(U*)p; + + size_t result; + + switch (encoding & 0x0f) + { + case DW_EH_PE_absptr: + result = u.ptr; + p += (void*).sizeof; + break; + + case DW_EH_PE_uleb128: + { + p = get_uleb128(p, result); + break; + } + case DW_EH_PE_sleb128: + { + ptrdiff_t sleb128; + p = get_sleb128(p, sleb128); + result = cast(size_t)sleb128; + break; + } + + case DW_EH_PE_udata2: result = cast(size_t)u.udata2; p += 2; break; + case DW_EH_PE_udata4: result = cast(size_t)u.udata4; p += 4; break; + case DW_EH_PE_udata8: result = cast(size_t)u.udata8; p += 8; break; + case DW_EH_PE_sdata2: result = cast(size_t)u.sdata2; p += 2; break; + case DW_EH_PE_sdata4: result = cast(size_t)u.sdata4; p += 4; break; + case DW_EH_PE_sdata8: result = cast(size_t)u.sdata8; p += 8; break; + + default: fatalerror("Unrecognized DWARF value encoding format"); + } + if (result) + { + if ((encoding & 0x70) == DW_EH_PE_pcrel) + result += cast(size_t)u; + else + result += base; + + if (encoding & DW_EH_PE_indirect) + result = *cast(size_t*)result; + } + val = result; + return p; +} + private ubyte* get_uleb128(ubyte* addr, ref size_t res) { res = 0; @@ -137,7 +286,7 @@ // read as long as high bit is set while(*addr & 0x80) { - res |= (*addr & 0x7f) << bitsize; + res |= (*addr & 0x7fU) << bitsize; bitsize += 7; addr += 1; if(bitsize >= size_t.sizeof*8) @@ -153,12 +302,12 @@ private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res) { - res = 0; + size_t tres = 0; size_t bitsize = 0; // read as long as high bit is set while(*addr & 0x80) { - res |= (*addr & 0x7f) << bitsize; + tres |= (*addr & 0x7fU) << bitsize; bitsize += 7; addr += 1; if(bitsize >= size_t.sizeof*8) @@ -167,12 +316,14 @@ // read last if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize) fatalerror("tried to read sleb128 that exceeded size of size_t"); - res |= (*addr) << bitsize; + tres |= (*addr) << bitsize; // take care of sign - if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40)) - res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1); + if(bitsize < size_t.sizeof*8 && (*addr & 0x40U) != 0) + tres |= cast(size_t)(-1) ^ ((1 << (bitsize+7)) - 1); + res = cast(ptrdiff_t)tres; + return addr + 1; } @@ -190,8 +341,7 @@ // 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 -const char[8] _d_exception_class = "LLDCD1\0\0"; +const char[8] _d_exception_class = "LDC_D_10"; // @@ -201,118 +351,174 @@ version(X86_UNWIND) { +// Various stuff we need +struct Region +{ + ubyte* callsite_table; + ubyte* action_table; + + // Note: classinfo_table points past the end of the table + ubyte* classinfo_table; + + size_t start; + size_t lpStart_base; // landing pad base + + ubyte ttypeEnc; + size_t ttype_base; // typeinfo base + + ubyte callSiteEnc; +} + // 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) { + debug(EH_personality) printf("Entering personality routine, context=%p\n", context); // check ver: the C++ Itanium ABI only allows ver == 1 if(ver != 1) + { + debug(EH_personality) printf("eh version mismatch\n"); return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; + } // check exceptionClass //TODO: Treat foreign exceptions with more respect - if((cast(char*)&exception_class)[0..8] != _d_exception_class) + auto wanted_ec = *cast(ulong*)_d_exception_class.ptr; + if(exception_class != wanted_ec) + { + debug(EH_personality) printf("exception class mismatch %p vs %p\n", exception_class, wanted_ec); return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; + } // find call site table, action table and classinfo table // Note: callsite and action tables do not contain static-length // data and will be parsed as needed - // Note: classinfo_table points past the end of the table - ubyte* callsite_table; - ubyte* action_table; - ClassInfo* classinfo_table; - _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table); - if (!callsite_table) + + Region region; + + _d_getLanguageSpecificTables(context, region); + + // workaround. this should not happen + if (!region.callsite_table) + { + debug(EH_personality) printf("callsite_table is null\n"); return _Unwind_Reason_Code.CONTINUE_UNWIND; + } + debug(EH_personality) printf("yay, checking\n"); + debug(EH_personality) printf("region.start = %p\n", region.start); + /* find landing pad and action table index belonging to ip by walking the callsite_table */ - ubyte* callsite_walker = callsite_table; + ubyte* callsite_walker = region.callsite_table; + debug(EH_personality) printf("callsite table at: %p\n", region.callsite_table); + debug(EH_personality) printf("action table at: %p\n", region.action_table); + debug(EH_personality) printf("rtti table at %p\n", region.classinfo_table); // get the instruction pointer // will be used to find the right entry in the callsite_table // -1 because it will point past the last instruction - ptrdiff_t ip = _Unwind_GetIP(context) - 1; + debug(EH_personality) printf("check1\n"); + size_t ip = _Unwind_GetIP(context) - 1; + debug(EH_personality) printf("check2\n"); - // address block_start is relative to - ptrdiff_t region_start = _Unwind_GetRegionStart(context); - // table entries - uint block_start_offset, block_size; - ptrdiff_t landing_pad; + size_t landing_pad; size_t action_offset; while(true) { // if we've gone through the list and found nothing... - if(callsite_walker >= action_table) + if(callsite_walker >= region.action_table) + { + debug(EH_personality) printf("found nothing\n"); return _Unwind_Reason_Code.CONTINUE_UNWIND; + } - block_start_offset = *cast(uint*)callsite_walker; - block_size = *(cast(uint*)callsite_walker + 1); - landing_pad = *(cast(uint*)callsite_walker + 2); - if(landing_pad) - landing_pad += region_start; - callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset); + size_t block_start, block_size; - debug(EH_personality_verbose) printf("ip=%llx %d %d %llx\n", ip, block_start_offset, block_size, landing_pad); + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_start); + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_size); + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, landing_pad); + callsite_walker = get_uleb128(callsite_walker, action_offset); + debug(EH_personality) printf("*block start offset = %p\n", block_start); + debug(EH_personality) printf(" block size = %p\n", block_size); + debug(EH_personality) printf(" landing pad = %p\n", landing_pad); + debug(EH_personality) printf(" ip=%p %p %p %p\n", ip, block_start, block_size, landing_pad); + // since the list is sorted, as soon as we're past the ip // there's no handler to be found - if(ip < region_start + block_start_offset) + if(ip < region.start + block_start) + { + debug(EH_personality) printf("found nothing2\n"); return _Unwind_Reason_Code.CONTINUE_UNWIND; + } + if(landing_pad) + landing_pad += region.lpStart_base; + // if we've found our block, exit - if(ip < region_start + block_start_offset + block_size) + if(ip < region.start + block_start + block_size) break; } - debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset); + debug(EH_personality) printf("Found correct landing pad %p and actionOffset %p\n", landing_pad, action_offset); // now we need the exception's classinfo to find a handler // 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); + _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - size_t.sizeof); //_d_exception.unwind_info.offsetof); // if there's no action offset and no landing pad, continue unwinding if(!action_offset && !landing_pad) return _Unwind_Reason_Code.CONTINUE_UNWIND; // if there's no action offset but a landing pad, this is a cleanup handler - else if(!action_offset && landing_pad) - return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); + else if(!action_offset && landing_pad != 0) + { + debug(EH_personality) printf("installing finally context\n"); + return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); + } /* walk action table chain, comparing classinfos using _d_isbaseof */ - ubyte* action_walker = action_table + action_offset - 1; + ubyte* action_walker = region.action_table + action_offset - 1; - ptrdiff_t ti_offset, next_action_offset; while(true) { + ptrdiff_t ti_offset, next_action_offset; + action_walker = get_sleb128(action_walker, ti_offset); // it is intentional that we not modify action_walker here // next_action_offset is from current action_walker position get_sleb128(action_walker, next_action_offset); // negative are 'filters' which we don't use - if(!(ti_offset >= 0)) + if(ti_offset < 0) fatalerror("Filter actions are unsupported"); // zero means cleanup, which we require to be the last action if(ti_offset == 0) { - if(!(next_action_offset == 0)) + if(next_action_offset != 0) fatalerror("Cleanup action must be last in chain"); - return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); + return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); } // get classinfo for action and check if the one in the // exception structure is a base - ClassInfo catch_ci = *(classinfo_table - ti_offset); - debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr); - if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci)) - return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context); + size_t typeinfo; + auto filter = cast(size_t)ti_offset * size_of_encoded(region.ttypeEnc); + read_encoded_with_base(region.ttypeEnc, region.ttype_base, region.classinfo_table - filter, typeinfo); + debug(EH_personality) + printf("classinfo at %zx (enc %zx (size %zx) base %zx ptr %zx)\n", typeinfo, region.ttypeEnc, size_of_encoded(region.ttypeEnc), region.ttype_base, region.classinfo_table - filter); + + auto catch_ci = *cast(ClassInfo*)&typeinfo; + if(_d_dynamic_cast(exception_struct.exception_object, catch_ci) !is null) + return _d_eh_install_catch_context(actions, ti_offset, cast(ptrdiff_t)landing_pad, exception_struct, context); + // we've walked through all actions and found nothing... if(next_action_offset == 0) return _Unwind_Reason_Code.CONTINUE_UNWIND; @@ -356,6 +562,7 @@ } fatalerror("reached unreachable"); + return _Unwind_Reason_Code.FATAL_PHASE2_ERROR; } @@ -370,56 +577,78 @@ _Unwind_SetGR(context, eh_exception_regno, cast(ptrdiff_t)exception_struct); _Unwind_SetGR(context, eh_selector_regno, 0); _Unwind_SetIP(context, landing_pad); + return _Unwind_Reason_Code.INSTALL_CONTEXT; } -private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci) +private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, out Region region) { - ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); + auto data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); + + // workaround. this should not be 0... if (!data) { - callsite = null; - action = null; - ci = null; - return; + //printf("language specific data is null\n"); + return; } - //TODO: Do proper DWARF reading here - if(*data++ != 0xff) - fatalerror("DWARF header has unexpected format 1"); + region.start = _Unwind_GetRegionStart(context); - if(*data++ != 0x00) - fatalerror("DWARF header has unexpected format 2"); - size_t cioffset; - data = get_uleb128(data, cioffset); - ci = cast(ClassInfo*)(data + cioffset); + // Read the C++-style LSDA: this is implementation-defined by GCC but LLVM + // outputs the same kind of table - if(*data++ != 0x03) - fatalerror("DWARF header has unexpected format 3"); - size_t callsitelength; - data = get_uleb128(data, callsitelength); - action = data + callsitelength; + // Get @LPStart: landing pad offsets are relative to it + auto lpStartEnc = *data++; + if (lpStartEnc == DW_EH_PE_omit) + region.lpStart_base = region.start; + else + data = read_encoded(context, lpStartEnc, data, region.lpStart_base); - callsite = data; + // Get @TType: the offset to the handler and typeinfo + region.ttypeEnc = *data++; + if (region.ttypeEnc == DW_EH_PE_omit) + // Not sure about this one... + fatalerror("@TType must not be omitted from DWARF header"); + + size_t ciOffset; + data = get_uleb128(data, ciOffset); + region.classinfo_table = data + ciOffset; + + region.ttype_base = base_of_encoded(context, region.ttypeEnc); + + // Get encoding and length of the call site table, which precedes the action + // table. + region.callSiteEnc = *data++; + if (region.callSiteEnc == DW_EH_PE_omit) + fatalerror("Call site table encoding must not be omitted from DWARF header"); + + size_t callSiteLength; + region.callsite_table = get_uleb128(data, callSiteLength); + region.action_table = region.callsite_table + callSiteLength; } } // end of x86 Linux specific implementation - -extern(C) void _d_throw_exception(Object e) +// called to throw object +extern(C) +void _d_throw_exception(Object e) { + //printf("throwing %p, rtti = %p\n", e, **cast(ClassRTTI***)e); if (e !is null) { _d_exception* exc_struct = new _d_exception; exc_struct.unwind_info.exception_class = *cast(ulong*)_d_exception_class.ptr; exc_struct.exception_object = e; _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info); - console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); + printf("Error: returned %d from raise exception.\n", ret); + //console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); } abort(); } -extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct) +// called to resume unwinding +extern(C) +void _d_eh_resume_unwind(void* exception_struct) { - _Unwind_Resume(&exception_struct.unwind_info); + _Unwind_Resume(&(cast(_d_exception*)exception_struct).unwind_info); }