Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/tango-0.99.9.patch

Revision 1650:40bd4a0d4870, 23.6 kB (checked in by Tomas Lindquist Olsen, 2 years ago)

Update to work with LLVM 2.7.

Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).

Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.

Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.

  • tango/core/rt/compiler/ldc/rt/lifetime.d

    old new  
    786786    return *cast(long*)px; 
    787787} 
    788788 
     789+/ 
    789790 
    790791/** 
    791792 * 
     
    849850 
    850851 
    851852/** 
    852  * 
     853 * Appends a single element to an array. 
    853854 */ 
    854 extern (C) byte[] _d_arrayappendcT(TypeInfo ti, ref byte[] x, ...
     855extern (C) byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element
    855856{ 
     857    auto x = cast(byte[]*)array; 
    856858    auto sizeelem = ti.next.tsize();            // array element size 
    857859    auto info = gc_query(x.ptr); 
    858860    auto length = x.length; 
     
    879881        assert(newcap >= newlength * sizeelem); 
    880882        newdata = cast(byte *)gc_malloc(newcap + 1, info.attr); 
    881883        memcpy(newdata, x.ptr, length * sizeelem); 
    882         (cast(void**)(&x))[1] = newdata; 
     884        (cast(void**)x)[1] = newdata; 
    883885    } 
    884886  L1: 
    885     byte *argp = cast(byte *)(&ti + 2)
     887    byte *argp = cast(byte *)element
    886888 
    887     *cast(size_t *)&x = newlength; 
     889    *cast(size_t *)x = newlength; 
    888890    x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; 
    889891    assert((cast(size_t)x.ptr & 15) == 0); 
    890892    assert(gc_sizeOf(x.ptr) > x.length * sizeelem); 
    891     return x; 
     893    return *x; 
    892894} 
    893895 
    894896 
     
    11281130    return result; 
    11291131} 
    11301132 
     1133/+ 
    11311134 
    11321135/** 
    11331136 * 
  • tango/core/rt/compiler/ldc/rt/eh.d

    old new  
    11/** 
    22 * This module contains functions and structures required for 
    3  * exception handling. 
     3 * dwarf exception handling with llvm 
    44 */ 
    55module rt.eh; 
    66 
    7 import ldc.cstdarg; 
    8 import rt.compiler.util.console; 
     7//debug = EH_personality; 
    98 
    10 // debug = EH_personality; 
    11  
    129// current EH implementation works on x86 
    1310// if it has a working unwind runtime 
    1411version(X86) { 
    1512    version(linux) version=X86_UNWIND; 
    1613    version(darwin) version=X86_UNWIND; 
    1714    version(solaris) version=X86_UNWIND; 
    18     version(freebsd) version=X86_UNWIND; 
    1915} 
    2016version(X86_64) { 
    2117    version(linux) version=X86_UNWIND; 
    2218    version(darwin) version=X86_UNWIND; 
    2319    version(solaris) version=X86_UNWIND; 
    24     version(freebsd) version=X86_UNWIND; 
    2520} 
    2621 
    2722//version = HP_LIBUNWIND; 
    2823 
    2924private extern(C) void abort(); 
    3025private extern(C) int printf(char*, ...); 
    31 private extern(C) int vprintf(char*, va_list va); 
     26//private extern(C) int vprintf(char*, va_list va); 
    3227 
    3328// D runtime functions 
    3429extern(C) { 
    35     int _d_isbaseof(ClassInfo oc, ClassInfo c); 
     30//    int _d_isbaseof(ClassInfo oc, ClassInfo c); 
     31    Object _d_dynamic_cast(Object o, ClassInfo c); 
    3632} 
    3733 
    3834// libunwind headers 
     
    7470// interface to HP's libunwind from http://www.nongnu.org/libunwind/ 
    7571version(HP_LIBUNWIND) 
    7672{ 
     73    // Haven't checked whether and how it has _Unwind_Get{Text,Data}RelBase 
     74    pragma (msg, "HP_LIBUNWIND interface is out of date and untested"); 
     75 
    7776    void __libunwind_Unwind_Resume(_Unwind_Exception *); 
    7877    _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *); 
    7978    ptrdiff_t __libunwind_Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr 
    8079            context); 
    81     ptrdiff_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); 
     80    size_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); 
    8281    ptrdiff_t __libunwind_Unwind_SetIP(_Unwind_Context_Ptr context, 
    8382            ptrdiff_t new_value); 
    8483    ptrdiff_t __libunwind_Unwind_SetGR(_Unwind_Context_Ptr context, int index, 
    8584            ptrdiff_t new_value); 
    86     ptrdiff_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); 
     85    size_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); 
    8786 
    8887    alias __libunwind_Unwind_Resume _Unwind_Resume; 
    8988    alias __libunwind_Unwind_RaiseException _Unwind_RaiseException; 
     
    9493    alias __libunwind_Unwind_SetGR _Unwind_SetGR; 
    9594    alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart; 
    9695} 
    97 else version(X86_UNWIND)  
     96else version(X86_UNWIND) 
    9897{ 
    9998    void _Unwind_Resume(_Unwind_Exception*); 
    10099    _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*); 
    101100    ptrdiff_t _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context); 
    102     ptrdiff_t _Unwind_GetIP(_Unwind_Context_Ptr context); 
     101    size_t _Unwind_GetIP(_Unwind_Context_Ptr context); 
    103102    ptrdiff_t _Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value); 
    104103    ptrdiff_t _Unwind_SetGR(_Unwind_Context_Ptr context, int index, 
    105104            ptrdiff_t new_value); 
    106     ptrdiff_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); 
     105    size_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); 
     106 
     107    size_t _Unwind_GetTextRelBase(_Unwind_Context_Ptr); 
     108    size_t _Unwind_GetDataRelBase(_Unwind_Context_Ptr); 
    107109} 
    108110else 
    109111{ 
    110112    // runtime calls these directly 
    111113    void _Unwind_Resume(_Unwind_Exception*) 
    112114    { 
    113         console("_Unwind_Resume is not implemented on this platform.\n"); 
     115        printf("_Unwind_Resume is not implemented on this platform.\n"); 
    114116    } 
    115117    _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*) 
    116118    { 
    117         console("_Unwind_RaiseException is not implemented on this platform.\n"); 
     119        printf("_Unwind_RaiseException is not implemented on this platform.\n"); 
    118120        return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; 
    119121    } 
    120122} 
     
    122124} 
    123125 
    124126// error and exit 
    125 extern(C) private void fatalerror(char[] format
     127extern(C) private void fatalerror(char* format, ...
    126128{ 
    127   printf("Fatal error in EH code: %.*s\n", format.length, format.ptr); 
     129//  va_list args; 
     130//  va_start(args, format); 
     131  printf("Fatal error in EH code: "); 
     132//  vprintf(format, args); 
     133  printf("\n"); 
    128134  abort(); 
    129135} 
    130136 
    131137 
    132 // helpers for reading certain DWARF data 
     138// DWARF EH encoding enum 
     139// See e.g. http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/dwarfext.html 
     140private enum : ubyte { 
     141  DW_EH_PE_omit    = 0xff, // value is not present 
     142 
     143  // value format 
     144  DW_EH_PE_absptr  = 0x00, // literal pointer 
     145  DW_EH_PE_uleb128 = 0x01, 
     146  DW_EH_PE_udata2  = 0x02, // unsigned 2-byte 
     147  DW_EH_PE_udata4  = 0x03, 
     148  DW_EH_PE_udata8  = 0x04, 
     149  DW_EH_PE_sleb128 = 0x09, 
     150  DW_EH_PE_sdata2  = 0x0a, 
     151  DW_EH_PE_sdata4  = 0x0b, 
     152  DW_EH_PE_sdata8  = 0x0c, 
     153 
     154  // value meaning 
     155  DW_EH_PE_pcrel    = 0x10, // relative to program counter 
     156  DW_EH_PE_textrel  = 0x20, // relative to .text 
     157  DW_EH_PE_datarel  = 0x30, // relative to .got or .eh_frame_hdr 
     158  DW_EH_PE_funcrel  = 0x40, // relative to beginning of function 
     159  DW_EH_PE_aligned  = 0x50, // is an aligned void* 
     160 
     161  // value is a pointer to the actual value 
     162  // this is a mask on top of one of the above 
     163  DW_EH_PE_indirect = 0x80 
     164
     165 
     166// Helpers for reading DWARF data 
     167 
     168// Given an encoding and a context, return the base to which the encoding is 
     169// relative 
     170private size_t base_of_encoded(_Unwind_Context_Ptr context, ubyte encoding) 
     171
     172  if (encoding == DW_EH_PE_omit) 
     173    return 0; 
     174 
     175  switch (encoding & 0x70) // ignore DW_EH_PE_indirect 
     176  { 
     177    case DW_EH_PE_absptr, DW_EH_PE_pcrel, DW_EH_PE_aligned: 
     178      return 0; 
     179 
     180    case DW_EH_PE_textrel: return _Unwind_GetTextRelBase(context); 
     181    case DW_EH_PE_datarel: return _Unwind_GetDataRelBase(context); 
     182    case DW_EH_PE_funcrel: return _Unwind_GetRegionStart(context); 
     183 
     184    default: fatalerror("Unrecognized base for DWARF value"); 
     185  } 
     186
     187 
     188// Only defined for fixed-size encodings 
     189private size_t size_of_encoded(ubyte encoding) 
     190
     191  if (encoding == DW_EH_PE_omit) 
     192    return 0; 
     193 
     194  switch (encoding & 0x07) // ignore leb128 
     195  { 
     196    case DW_EH_PE_absptr: return (void*).sizeof; 
     197    case DW_EH_PE_udata2: return 2; 
     198    case DW_EH_PE_udata4: return 4; 
     199    case DW_EH_PE_udata8: return 8; 
     200 
     201    default: fatalerror("Unrecognized fixed-size DWARF value encoding"); 
     202  } 
     203
     204 
     205// Actual value readers below: read a value from the given ubyte* into the 
     206// output parameter and return the pointer incremented past the value. 
     207 
     208// Like read_encoded_with_base but gets the base from the given context 
     209private ubyte* read_encoded(_Unwind_Context_Ptr context, ubyte encoding, ubyte* p, out size_t val) 
     210
     211  return read_encoded_with_base(encoding, base_of_encoded(context, encoding), p, val); 
     212
     213 
     214private ubyte* read_encoded_with_base(ubyte encoding, size_t base, ubyte* p, out size_t val) 
     215
     216  if (encoding == DW_EH_PE_aligned) 
     217  { 
     218    auto a = cast(size_t)p; 
     219    a = (a + (void*).sizeof - 1) & -(void*).sizeof; 
     220    val = *cast(size_t*)a; 
     221    return cast(ubyte*)(a + (void*).sizeof); 
     222  } 
     223 
     224  union U 
     225  { 
     226    size_t ptr; 
     227    ushort udata2; 
     228    uint   udata4; 
     229    ulong  udata8; 
     230    short  sdata2; 
     231    int    sdata4; 
     232    long   sdata8; 
     233  } 
     234 
     235  auto u = cast(U*)p; 
     236 
     237  size_t result; 
     238 
     239  switch (encoding & 0x0f) 
     240  { 
     241    case DW_EH_PE_absptr: 
     242      result = u.ptr; 
     243      p += (void*).sizeof; 
     244      break; 
     245 
     246    case DW_EH_PE_uleb128: 
     247    { 
     248      p = get_uleb128(p, result); 
     249      break; 
     250    } 
     251    case DW_EH_PE_sleb128: 
     252    { 
     253      ptrdiff_t sleb128; 
     254      p = get_sleb128(p, sleb128); 
     255      result = cast(size_t)sleb128; 
     256      break; 
     257    } 
     258 
     259    case DW_EH_PE_udata2: result = cast(size_t)u.udata2; p += 2; break; 
     260    case DW_EH_PE_udata4: result = cast(size_t)u.udata4; p += 4; break; 
     261    case DW_EH_PE_udata8: result = cast(size_t)u.udata8; p += 8; break; 
     262    case DW_EH_PE_sdata2: result = cast(size_t)u.sdata2; p += 2; break; 
     263    case DW_EH_PE_sdata4: result = cast(size_t)u.sdata4; p += 4; break; 
     264    case DW_EH_PE_sdata8: result = cast(size_t)u.sdata8; p += 8; break; 
     265 
     266    default: fatalerror("Unrecognized DWARF value encoding format"); 
     267  } 
     268  if (result) 
     269  { 
     270    if ((encoding & 0x70) == DW_EH_PE_pcrel) 
     271      result += cast(size_t)u; 
     272    else 
     273      result += base; 
     274 
     275    if (encoding & DW_EH_PE_indirect) 
     276      result = *cast(size_t*)result; 
     277  } 
     278  val = result; 
     279  return p; 
     280
     281 
    133282private ubyte* get_uleb128(ubyte* addr, ref size_t res) 
    134283{ 
    135284  res = 0; 
     
    137286 
    138287  // read as long as high bit is set 
    139288  while(*addr & 0x80) { 
    140     res |= (*addr & 0x7f) << bitsize; 
     289    res |= (*addr & 0x7fU) << bitsize; 
    141290    bitsize += 7; 
    142291    addr += 1; 
    143292    if(bitsize >= size_t.sizeof*8) 
     
    153302 
    154303private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res) 
    155304{ 
    156   res = 0; 
     305  size_t tres = 0; 
    157306  size_t bitsize = 0; 
    158307 
    159308  // read as long as high bit is set 
    160309  while(*addr & 0x80) { 
    161     res |= (*addr & 0x7f) << bitsize; 
     310    tres |= (*addr & 0x7fU) << bitsize; 
    162311    bitsize += 7; 
    163312    addr += 1; 
    164313    if(bitsize >= size_t.sizeof*8) 
     
    167316  // read last 
    168317  if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize) 
    169318    fatalerror("tried to read sleb128 that exceeded size of size_t"); 
    170   res |= (*addr) << bitsize; 
     319  tres |= (*addr) << bitsize; 
    171320 
    172321  // take care of sign 
    173   if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40)
    174     res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1); 
     322  if(bitsize < size_t.sizeof*8 && (*addr & 0x40U) != 0
     323    tres |= cast(size_t)(-1) ^ ((1 << (bitsize+7)) - 1); 
    175324 
     325  res = cast(ptrdiff_t)tres; 
     326 
    176327  return addr + 1; 
    177328} 
    178329 
     
    190341 
    191342// the 8-byte string identifying the type of exception 
    192343// the first 4 are for vendor, the second 4 for language 
    193 //TODO: This may be the wrong way around 
    194 const char[8] _d_exception_class = "LLDCD1\0\0"; 
     344const char[8] _d_exception_class = "LDC_D_10"; 
    195345 
    196346 
    197347// 
     
    201351version(X86_UNWIND) 
    202352{ 
    203353 
     354// Various stuff we need 
     355struct Region 
     356{ 
     357  ubyte* callsite_table; 
     358  ubyte* action_table; 
     359 
     360  // Note: classinfo_table points past the end of the table 
     361  ubyte* classinfo_table; 
     362 
     363  size_t start; 
     364  size_t lpStart_base; // landing pad base 
     365 
     366  ubyte ttypeEnc; 
     367  size_t ttype_base; // typeinfo base 
     368 
     369  ubyte callSiteEnc; 
     370} 
     371 
    204372// the personality routine gets called by the unwind handler and is responsible for 
    205373// reading the EH tables and deciding what to do 
    206374extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context) 
    207375{ 
     376  debug(EH_personality) printf("Entering personality routine, context=%p\n", context); 
    208377  // check ver: the C++ Itanium ABI only allows ver == 1 
    209378  if(ver != 1) 
     379  { 
     380    debug(EH_personality) printf("eh version mismatch\n"); 
    210381    return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; 
     382  } 
    211383 
    212384  // check exceptionClass 
    213385  //TODO: Treat foreign exceptions with more respect 
    214   if((cast(char*)&exception_class)[0..8] != _d_exception_class) 
     386  auto wanted_ec = *cast(ulong*)_d_exception_class.ptr; 
     387  if(exception_class != wanted_ec) 
     388  { 
     389    debug(EH_personality) printf("exception class mismatch %p vs %p\n", exception_class, wanted_ec); 
    215390    return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; 
     391  } 
    216392 
    217393  // find call site table, action table and classinfo table 
    218394  // Note: callsite and action tables do not contain static-length 
    219395  // data and will be parsed as needed 
    220   // Note: classinfo_table points past the end of the table 
    221   ubyte* callsite_table; 
    222   ubyte* action_table; 
    223   ClassInfo* classinfo_table; 
    224   _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table); 
    225   if (!callsite_table) 
     396 
     397  Region region; 
     398 
     399  _d_getLanguageSpecificTables(context, region); 
     400 
     401  // workaround. this should not happen 
     402  if (!region.callsite_table) 
     403  { 
     404    debug(EH_personality) printf("callsite_table is null\n"); 
    226405    return _Unwind_Reason_Code.CONTINUE_UNWIND; 
     406  } 
    227407 
     408  debug(EH_personality) printf("yay, checking\n"); 
     409  debug(EH_personality) printf("region.start = %p\n", region.start); 
     410 
    228411  /* 
    229412    find landing pad and action table index belonging to ip by walking 
    230413    the callsite_table 
    231414  */ 
    232   ubyte* callsite_walker = callsite_table; 
     415  ubyte* callsite_walker = region.callsite_table; 
     416  debug(EH_personality) printf("callsite table at: %p\n", region.callsite_table); 
     417  debug(EH_personality) printf("action table at: %p\n", region.action_table); 
     418  debug(EH_personality) printf("rtti table at %p\n", region.classinfo_table); 
    233419 
    234420  // get the instruction pointer 
    235421  // will be used to find the right entry in the callsite_table 
    236422  // -1 because it will point past the last instruction 
    237   ptrdiff_t ip = _Unwind_GetIP(context) - 1; 
     423  debug(EH_personality) printf("check1\n"); 
     424  size_t ip = _Unwind_GetIP(context) - 1; 
     425  debug(EH_personality) printf("check2\n"); 
    238426 
    239   // address block_start is relative to 
    240   ptrdiff_t region_start = _Unwind_GetRegionStart(context); 
    241  
    242427  // table entries 
    243   uint block_start_offset, block_size; 
    244   ptrdiff_t landing_pad; 
     428  size_t landing_pad; 
    245429  size_t action_offset; 
    246430 
    247431  while(true) { 
    248432    // if we've gone through the list and found nothing... 
    249     if(callsite_walker >= action_table) 
     433    if(callsite_walker >= region.action_table) 
     434    { 
     435      debug(EH_personality) printf("found nothing\n"); 
    250436      return _Unwind_Reason_Code.CONTINUE_UNWIND; 
     437    } 
    251438 
    252     block_start_offset = *cast(uint*)callsite_walker; 
    253     block_size = *(cast(uint*)callsite_walker + 1); 
    254     landing_pad = *(cast(uint*)callsite_walker + 2); 
    255     if(landing_pad) 
    256       landing_pad += region_start; 
    257     callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset); 
     439    size_t block_start, block_size; 
    258440 
    259     debug(EH_personality_verbose) printf("ip=%llx %d %d %llx\n", ip, block_start_offset, block_size, landing_pad); 
     441    callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_start); 
     442    callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_size); 
     443    callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, landing_pad); 
     444    callsite_walker = get_uleb128(callsite_walker, action_offset); 
    260445 
     446    debug(EH_personality) printf("*block start offset = %p\n", block_start); 
     447    debug(EH_personality) printf(" block size = %p\n", block_size); 
     448    debug(EH_personality) printf(" landing pad = %p\n", landing_pad); 
     449    debug(EH_personality) printf(" ip=%p %p %p %p\n", ip, block_start, block_size, landing_pad); 
     450 
    261451    // since the list is sorted, as soon as we're past the ip 
    262452    // there's no handler to be found 
    263     if(ip < region_start + block_start_offset) 
     453    if(ip < region.start + block_start) 
     454    { 
     455      debug(EH_personality) printf("found nothing2\n"); 
    264456      return _Unwind_Reason_Code.CONTINUE_UNWIND; 
     457    } 
    265458 
     459    if(landing_pad) 
     460      landing_pad += region.lpStart_base; 
     461 
    266462    // if we've found our block, exit 
    267     if(ip < region_start + block_start_offset + block_size) 
     463    if(ip < region.start + block_start + block_size) 
    268464      break; 
    269465  } 
    270466 
    271   debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset); 
     467  debug(EH_personality) printf("Found correct landing pad %p and actionOffset %p\n", landing_pad, action_offset); 
    272468 
    273469  // now we need the exception's classinfo to find a handler 
    274470  // the exception_info is actually a member of a larger _d_exception struct 
    275471  // the runtime allocated. get that now 
    276   _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof); 
     472  _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - size_t.sizeof); //_d_exception.unwind_info.offsetof); 
    277473 
    278474  // if there's no action offset and no landing pad, continue unwinding 
    279475  if(!action_offset && !landing_pad) 
    280476    return _Unwind_Reason_Code.CONTINUE_UNWIND; 
    281477 
    282478  // if there's no action offset but a landing pad, this is a cleanup handler 
    283   else if(!action_offset && landing_pad) 
    284     return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); 
     479  else if(!action_offset && landing_pad != 0) 
     480  { 
     481    debug(EH_personality) printf("installing finally context\n"); 
     482    return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); 
     483  } 
    285484 
    286485  /* 
    287486   walk action table chain, comparing classinfos using _d_isbaseof 
    288487  */ 
    289   ubyte* action_walker = action_table + action_offset - 1; 
     488  ubyte* action_walker = region.action_table + action_offset - 1; 
    290489 
    291   ptrdiff_t ti_offset, next_action_offset; 
    292490  while(true) { 
     491    ptrdiff_t ti_offset, next_action_offset; 
     492 
    293493    action_walker = get_sleb128(action_walker, ti_offset); 
    294494    // it is intentional that we not modify action_walker here 
    295495    // next_action_offset is from current action_walker position 
    296496    get_sleb128(action_walker, next_action_offset); 
    297497 
    298498    // negative are 'filters' which we don't use 
    299     if(!(ti_offset >= 0)
     499    if(ti_offset < 0
    300500      fatalerror("Filter actions are unsupported"); 
    301501 
    302502    // zero means cleanup, which we require to be the last action 
    303503    if(ti_offset == 0) { 
    304       if(!(next_action_offset == 0)
     504      if(next_action_offset != 0
    305505        fatalerror("Cleanup action must be last in chain"); 
    306       return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); 
     506      return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); 
    307507    } 
    308508 
    309509    // get classinfo for action and check if the one in the 
    310510    // exception structure is a base 
    311     ClassInfo catch_ci = *(classinfo_table - ti_offset); 
    312     debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr); 
    313     if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci)) 
    314       return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context); 
     511    size_t typeinfo; 
     512    auto filter = cast(size_t)ti_offset * size_of_encoded(region.ttypeEnc); 
     513    read_encoded_with_base(region.ttypeEnc, region.ttype_base, region.classinfo_table - filter, typeinfo); 
    315514 
     515    debug(EH_personality) 
     516      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); 
     517 
     518    auto catch_ci = *cast(ClassInfo*)&typeinfo; 
     519    if(_d_dynamic_cast(exception_struct.exception_object, catch_ci) !is null) 
     520      return _d_eh_install_catch_context(actions, ti_offset, cast(ptrdiff_t)landing_pad, exception_struct, context); 
     521 
    316522    // we've walked through all actions and found nothing... 
    317523    if(next_action_offset == 0) 
    318524      return _Unwind_Reason_Code.CONTINUE_UNWIND; 
     
    356562  } 
    357563 
    358564  fatalerror("reached unreachable"); 
     565 
    359566  return _Unwind_Reason_Code.FATAL_PHASE2_ERROR; 
    360567} 
    361568 
     
    370577  _Unwind_SetGR(context, eh_exception_regno, cast(ptrdiff_t)exception_struct); 
    371578  _Unwind_SetGR(context, eh_selector_regno, 0); 
    372579  _Unwind_SetIP(context, landing_pad); 
     580 
    373581  return _Unwind_Reason_Code.INSTALL_CONTEXT; 
    374582} 
    375583 
    376 private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci
     584private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, out Region region
    377585{ 
    378   ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); 
     586  auto data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); 
     587 
     588  // workaround. this should not be 0... 
    379589  if (!data) 
    380590  { 
    381     callsite = null; 
    382     action = null; 
    383     ci = null; 
    384     return; 
     591      //printf("language specific data is null\n"); 
     592      return; 
    385593  } 
    386594 
    387   //TODO: Do proper DWARF reading here 
    388   if(*data++ != 0xff) 
    389     fatalerror("DWARF header has unexpected format 1"); 
     595  region.start = _Unwind_GetRegionStart(context); 
    390596 
    391   if(*data++ != 0x00) 
    392     fatalerror("DWARF header has unexpected format 2"); 
    393   size_t cioffset; 
    394   data = get_uleb128(data, cioffset); 
    395   ci = cast(ClassInfo*)(data + cioffset); 
     597  // Read the C++-style LSDA: this is implementation-defined by GCC but LLVM 
     598  // outputs the same kind of table 
    396599 
    397   if(*data++ != 0x03) 
    398     fatalerror("DWARF header has unexpected format 3"); 
    399   size_t callsitelength; 
    400   data = get_uleb128(data, callsitelength); 
    401   action = data + callsitelength; 
     600  // Get @LPStart: landing pad offsets are relative to it 
     601  auto lpStartEnc = *data++; 
     602  if (lpStartEnc == DW_EH_PE_omit) 
     603    region.lpStart_base = region.start; 
     604  else 
     605    data = read_encoded(context, lpStartEnc, data, region.lpStart_base); 
    402606 
    403   callsite = data; 
     607  // Get @TType: the offset to the handler and typeinfo 
     608  region.ttypeEnc = *data++; 
     609  if (region.ttypeEnc == DW_EH_PE_omit) 
     610    // Not sure about this one... 
     611    fatalerror("@TType must not be omitted from DWARF header"); 
     612 
     613  size_t ciOffset; 
     614  data = get_uleb128(data, ciOffset); 
     615  region.classinfo_table = data + ciOffset; 
     616 
     617  region.ttype_base = base_of_encoded(context, region.ttypeEnc); 
     618 
     619  // Get encoding and length of the call site table, which precedes the action 
     620  // table. 
     621  region.callSiteEnc = *data++; 
     622  if (region.callSiteEnc == DW_EH_PE_omit) 
     623    fatalerror("Call site table encoding must not be omitted from DWARF header"); 
     624 
     625  size_t callSiteLength; 
     626  region.callsite_table = get_uleb128(data, callSiteLength); 
     627  region.action_table = region.callsite_table + callSiteLength; 
    404628} 
    405629 
    406630} // end of x86 Linux specific implementation 
    407631 
    408  
    409 extern(C) void _d_throw_exception(Object e) 
     632// called to throw object 
     633extern(C) 
     634void _d_throw_exception(Object e) 
    410635{ 
     636    //printf("throwing %p, rtti = %p\n", e, **cast(ClassRTTI***)e); 
    411637    if (e !is null) 
    412638    { 
    413639        _d_exception* exc_struct = new _d_exception; 
    414640        exc_struct.unwind_info.exception_class = *cast(ulong*)_d_exception_class.ptr; 
    415641        exc_struct.exception_object = e; 
    416642        _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info); 
    417         console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); 
     643        printf("Error: returned %d from raise exception.\n", ret); 
     644        //console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); 
    418645    } 
    419646    abort(); 
    420647} 
    421648 
    422 extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct) 
     649// called to resume unwinding 
     650extern(C) 
     651void _d_eh_resume_unwind(void* exception_struct) 
    423652{ 
    424   _Unwind_Resume(&exception_struct.unwind_info); 
     653    _Unwind_Resume(&(cast(_d_exception*)exception_struct).unwind_info); 
    425654} 
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.