Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 949 lines (870 sloc) 31.828 kb
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
1 Index: tango/core/rt/compiler/ldc/ldc/intrinsics.di
2 ===================================================================
3 --- tango/core/rt/compiler/ldc/ldc/intrinsics.di (revision 5576)
4 +++ tango/core/rt/compiler/ldc/ldc/intrinsics.di (working copy)
5 @@ -101,8 +101,16 @@
6 // Note that, unlike the standard libc function, the llvm.memcpy.* intrinsics do
7 // not return a value, and takes an extra alignment argument.
8
9 -pragma(intrinsic, "llvm.memcpy.i#")
10 - void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment);
11 +version(LDC_LLVMPre28)
12 +{
13 + pragma(intrinsic, "llvm.memcpy.i#")
14 + void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment);
15 +}
16 +else
17 +{
18 + pragma(intrinsic, "llvm.memcpy.p0i8.p0i8.i#")
19 + void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment, bool volatile_);
20 +}
21
22 deprecated {
23 alias llvm_memcpy!(uint) llvm_memcpy_i32;
24 @@ -116,8 +124,16 @@
25 // Note that, unlike the standard libc function, the llvm.memmove.* intrinsics
26 // do not return a value, and takes an extra alignment argument.
27
28 -pragma(intrinsic, "llvm.memmove.i#")
29 - void llvm_memmove(T)(void* dst, void* src, T len, uint alignment);
30 +version(LDC_LLVMPre28)
31 +{
32 + pragma(intrinsic, "llvm.memmove.i#")
33 + void llvm_memmove(T)(void* dst, void* src, T len, uint alignment);
34 +}
35 +else
36 +{
37 + pragma(intrinsic, "llvm.memmove.p0i8.p0i8.i#")
38 + void llvm_memmove(T)(void* dst, void* src, T len, uint alignment, bool volatile_);
39 +}
40
41 deprecated {
42 alias llvm_memmove!(uint) llvm_memmove_i32;
43 @@ -130,8 +146,16 @@
44 // Note that, unlike the standard libc function, the llvm.memset intrinsic does
45 // not return a value, and takes an extra alignment argument.
46
47 -pragma(intrinsic, "llvm.memset.i#")
48 - void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment);
49 +version(LDC_LLVMPre28)
50 +{
51 + pragma(intrinsic, "llvm.memset.i#")
52 + void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment);
53 +}
54 +else
55 +{
56 + pragma(intrinsic, "llvm.memset.p0i8.i#")
57 + void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment, bool volatile_);
58 +}
59
60 deprecated {
61 alias llvm_memset!(uint) llvm_memset_i32;
9cd3254 @ckamm Improve array append performance.
ckamm authored
62 Index: tango/core/rt/compiler/ldc/rt/lifetime.d
63 ===================================================================
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
64 --- tango/core/rt/compiler/ldc/rt/lifetime.d (revision 5576)
9cd3254 @ckamm Improve array append performance.
ckamm authored
65 +++ tango/core/rt/compiler/ldc/rt/lifetime.d (working copy)
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
66 @@ -241,7 +241,7 @@
67 }
68
69 /**
70 - * As _d_newarrayT, but
71 + * As _d_newarrayT, but
72 * for when the array has a non-zero initializer.
73 */
74 extern (C) void* _d_newarrayiT(TypeInfo ti, size_t length)
75 @@ -359,7 +359,7 @@
76
77
78 /**
79 - * As _d_newarraymT, but
80 + * As _d_newarraymT, but
81 * for when the array has a non-zero initializer.
82 */
83 extern (C) void* _d_newarraymiT(TypeInfo ti, int ndims, size_t* dims)
84 @@ -483,7 +483,7 @@
85 // if (p)
86 // {
87 // This assert on array consistency may fail with casts or in unions.
88 -// This function still does something sensible even if plength && !pdata.
89 +// This function still does something sensible even if plength && !pdata.
90 // assert(!plength || pdata);
91
92 if (pdata)
93 @@ -505,9 +505,9 @@
94 }
95 }
96
97 -/**
98 - *
99 - */
100 +/**
101 + *
102 + */
103 extern (C) void _d_callinterfacefinalizer(void *p)
104 {
105 if (p)
106 @@ -544,9 +544,9 @@
107
108 if (p) // not necessary if called from gc
109 {
110 - if (det)
111 - (cast(Object)p).dispose();
112 -
113 + if (det)
114 + (cast(Object)p).dispose();
115 +
116 ClassInfo** pc = cast(ClassInfo**)p;
117
118 if (*pc)
119 @@ -593,7 +593,7 @@
120 {
121 assert(ti);
122 // This assert on array consistency may fail with casts or in unions.
123 -// This function still does something sensible even if plength && !pdata.
124 +// This function still does something sensible even if plength && !pdata.
125 // assert(!plength || pdata);
126 }
127 body
128 @@ -651,7 +651,6 @@
129 return newdata;
130 }
131
132 -
133 /**
134 * Resize arrays for non-zero initializers.
135 * p pointer to array lvalue to be updated
136 @@ -664,7 +663,7 @@
137 in
138 {
139 // This assert on array consistency may fail with casts or in unions.
140 -// This function still does something sensible even if plength && !pdata.
141 +// This function still does something sensible even if plength && !pdata.
142 // assert(!plength || pdata);
143 }
144 body
145 @@ -786,6 +785,7 @@
9cd3254 @ckamm Improve array append performance.
ckamm authored
146 return *cast(long*)px;
147 }
148
149 ++/
150
151 /**
152 *
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
153 @@ -824,8 +824,8 @@
154 const size_t b=0; // flatness factor, how fast the extra space decreases with array size
155 const size_t a=100; // allocate at most a% of the requested size as extra space (rounding will change this)
156 const size_t minBits=1; // minimum bit size
157 -
158
159 +
160 static size_t log2plusB(size_t c)
161 {
162 // could use the bsr bit op
163 @@ -847,12 +847,12 @@
164 return newcap;
165 }
9cd3254 @ckamm Improve array append performance.
ckamm authored
166
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
167 -
9cd3254 @ckamm Improve array append performance.
ckamm authored
168 /**
169 - *
170 + * Appends a single element to an array.
171 */
172 -extern (C) byte[] _d_arrayappendcT(TypeInfo ti, ref byte[] x, ...)
173 +extern (C) byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element)
174 {
175 + auto x = cast(byte[]*)array;
176 auto sizeelem = ti.next.tsize(); // array element size
177 auto info = gc_query(x.ptr);
178 auto length = x.length;
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
179 @@ -879,18 +879,19 @@
9cd3254 @ckamm Improve array append performance.
ckamm authored
180 assert(newcap >= newlength * sizeelem);
181 newdata = cast(byte *)gc_malloc(newcap + 1, info.attr);
182 memcpy(newdata, x.ptr, length * sizeelem);
183 - (cast(void**)(&x))[1] = newdata;
184 + (cast(void**)x)[1] = newdata;
185 }
186 L1:
187 - byte *argp = cast(byte *)(&ti + 2);
188 + byte *argp = cast(byte *)element;
189
190 - *cast(size_t *)&x = newlength;
191 + *cast(size_t *)x = newlength;
192 x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem];
193 assert((cast(size_t)x.ptr & 15) == 0);
194 assert(gc_sizeOf(x.ptr) > x.length * sizeelem);
195 - return x;
196 + return *x;
197 }
198
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
199 +/+
9cd3254 @ckamm Improve array append performance.
ckamm authored
200
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
201 /**
202 * Append dchar to char[]
203 @@ -1128,7 +1129,6 @@
9cd3254 @ckamm Improve array append performance.
ckamm authored
204 return result;
205 }
206
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
207 -
9cd3254 @ckamm Improve array append performance.
ckamm authored
208 /**
209 *
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
210 */
211 Index: tango/core/rt/compiler/ldc/rt/arrayInit.d
212 ===================================================================
213 --- tango/core/rt/compiler/ldc/rt/arrayInit.d (revision 5576)
214 +++ tango/core/rt/compiler/ldc/rt/arrayInit.d (working copy)
215 @@ -114,7 +114,10 @@
216 auto p = a;
217 auto end = a + na*nv;
218 while (p !is end) {
219 - llvm_memcpy(p,v,nv,0);
220 + version(LDC_LLVMPre28)
221 + llvm_memcpy(p,v,nv,0);
222 + else
223 + llvm_memcpy(p,v,nv,1, false);
224 p += nv;
225 }
226 }
227 @@ -164,7 +167,12 @@
228 if (dstlen != srclen)
229 throw new Exception("lengths don't match for array copy");
230 else if (dst+dstlen <= src || src+srclen <= dst)
231 - llvm_memcpy(dst, src, dstlen, 0);
232 + {
233 + version(LDC_LLVMPre28)
234 + llvm_memcpy(dst, src, dstlen, 0);
235 + else
236 + llvm_memcpy(dst, src, dstlen, 1, false);
237 + }
238 else
239 throw new Exception("overlapping array copy");
240 }
1fac40d @lindquist Update to work with LLVM 2.7.
lindquist authored
241 Index: tango/core/rt/compiler/ldc/rt/eh.d
242 ===================================================================
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
243 --- tango/core/rt/compiler/ldc/rt/eh.d (revision 5576)
1fac40d @lindquist Update to work with LLVM 2.7.
lindquist authored
244 +++ tango/core/rt/compiler/ldc/rt/eh.d (working copy)
245 @@ -1,38 +1,34 @@
246 /**
247 * This module contains functions and structures required for
248 - * exception handling.
249 + * dwarf exception handling with llvm
250 */
251 module rt.eh;
252
253 -import ldc.cstdarg;
254 -import rt.compiler.util.console;
255 +//debug = EH_personality;
256
257 -// debug = EH_personality;
258 -
259 // current EH implementation works on x86
260 // if it has a working unwind runtime
261 version(X86) {
262 version(linux) version=X86_UNWIND;
263 version(darwin) version=X86_UNWIND;
264 version(solaris) version=X86_UNWIND;
265 - version(freebsd) version=X86_UNWIND;
266 }
267 version(X86_64) {
268 version(linux) version=X86_UNWIND;
269 version(darwin) version=X86_UNWIND;
270 version(solaris) version=X86_UNWIND;
271 - version(freebsd) version=X86_UNWIND;
272 }
273
274 //version = HP_LIBUNWIND;
275
276 private extern(C) void abort();
277 private extern(C) int printf(char*, ...);
278 -private extern(C) int vprintf(char*, va_list va);
279 +//private extern(C) int vprintf(char*, va_list va);
280
281 // D runtime functions
282 extern(C) {
283 - int _d_isbaseof(ClassInfo oc, ClassInfo c);
284 +// int _d_isbaseof(ClassInfo oc, ClassInfo c);
285 + Object _d_dynamic_cast(Object o, ClassInfo c);
286 }
287
288 // libunwind headers
289 @@ -74,16 +70,19 @@
290 // interface to HP's libunwind from http://www.nongnu.org/libunwind/
291 version(HP_LIBUNWIND)
292 {
293 + // Haven't checked whether and how it has _Unwind_Get{Text,Data}RelBase
294 + pragma (msg, "HP_LIBUNWIND interface is out of date and untested");
295 +
296 void __libunwind_Unwind_Resume(_Unwind_Exception *);
297 _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *);
298 ptrdiff_t __libunwind_Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr
299 context);
300 - ptrdiff_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context);
301 + size_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context);
302 ptrdiff_t __libunwind_Unwind_SetIP(_Unwind_Context_Ptr context,
303 ptrdiff_t new_value);
304 ptrdiff_t __libunwind_Unwind_SetGR(_Unwind_Context_Ptr context, int index,
305 ptrdiff_t new_value);
306 - ptrdiff_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context);
307 + size_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context);
308
309 alias __libunwind_Unwind_Resume _Unwind_Resume;
310 alias __libunwind_Unwind_RaiseException _Unwind_RaiseException;
311 @@ -94,27 +93,30 @@
312 alias __libunwind_Unwind_SetGR _Unwind_SetGR;
313 alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart;
314 }
315 -else version(X86_UNWIND)
316 +else version(X86_UNWIND)
317 {
318 void _Unwind_Resume(_Unwind_Exception*);
319 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*);
320 ptrdiff_t _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context);
321 - ptrdiff_t _Unwind_GetIP(_Unwind_Context_Ptr context);
322 + size_t _Unwind_GetIP(_Unwind_Context_Ptr context);
323 ptrdiff_t _Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value);
324 ptrdiff_t _Unwind_SetGR(_Unwind_Context_Ptr context, int index,
325 ptrdiff_t new_value);
326 - ptrdiff_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context);
327 + size_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context);
328 +
329 + size_t _Unwind_GetTextRelBase(_Unwind_Context_Ptr);
330 + size_t _Unwind_GetDataRelBase(_Unwind_Context_Ptr);
331 }
332 else
333 {
334 // runtime calls these directly
335 void _Unwind_Resume(_Unwind_Exception*)
336 {
337 - console("_Unwind_Resume is not implemented on this platform.\n");
338 + printf("_Unwind_Resume is not implemented on this platform.\n");
339 }
340 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*)
341 {
342 - console("_Unwind_RaiseException is not implemented on this platform.\n");
343 + printf("_Unwind_RaiseException is not implemented on this platform.\n");
344 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
345 }
346 }
347 @@ -122,14 +124,161 @@
348 }
349
350 // error and exit
351 -extern(C) private void fatalerror(char[] format)
352 +extern(C) private void fatalerror(char* format, ...)
353 {
354 - printf("Fatal error in EH code: %.*s\n", format.length, format.ptr);
355 +// va_list args;
356 +// va_start(args, format);
357 + printf("Fatal error in EH code: ");
358 +// vprintf(format, args);
359 + printf("\n");
360 abort();
361 }
362
363
364 -// helpers for reading certain DWARF data
365 +// DWARF EH encoding enum
366 +// See e.g. http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/dwarfext.html
367 +private enum : ubyte {
368 + DW_EH_PE_omit = 0xff, // value is not present
369 +
370 + // value format
371 + DW_EH_PE_absptr = 0x00, // literal pointer
372 + DW_EH_PE_uleb128 = 0x01,
373 + DW_EH_PE_udata2 = 0x02, // unsigned 2-byte
374 + DW_EH_PE_udata4 = 0x03,
375 + DW_EH_PE_udata8 = 0x04,
376 + DW_EH_PE_sleb128 = 0x09,
377 + DW_EH_PE_sdata2 = 0x0a,
378 + DW_EH_PE_sdata4 = 0x0b,
379 + DW_EH_PE_sdata8 = 0x0c,
380 +
381 + // value meaning
382 + DW_EH_PE_pcrel = 0x10, // relative to program counter
383 + DW_EH_PE_textrel = 0x20, // relative to .text
384 + DW_EH_PE_datarel = 0x30, // relative to .got or .eh_frame_hdr
385 + DW_EH_PE_funcrel = 0x40, // relative to beginning of function
386 + DW_EH_PE_aligned = 0x50, // is an aligned void*
387 +
388 + // value is a pointer to the actual value
389 + // this is a mask on top of one of the above
390 + DW_EH_PE_indirect = 0x80
391 +}
392 +
393 +// Helpers for reading DWARF data
394 +
395 +// Given an encoding and a context, return the base to which the encoding is
396 +// relative
397 +private size_t base_of_encoded(_Unwind_Context_Ptr context, ubyte encoding)
398 +{
399 + if (encoding == DW_EH_PE_omit)
400 + return 0;
401 +
402 + switch (encoding & 0x70) // ignore DW_EH_PE_indirect
403 + {
404 + case DW_EH_PE_absptr, DW_EH_PE_pcrel, DW_EH_PE_aligned:
405 + return 0;
406 +
407 + case DW_EH_PE_textrel: return _Unwind_GetTextRelBase(context);
408 + case DW_EH_PE_datarel: return _Unwind_GetDataRelBase(context);
409 + case DW_EH_PE_funcrel: return _Unwind_GetRegionStart(context);
410 +
411 + default: fatalerror("Unrecognized base for DWARF value");
412 + }
413 +}
414 +
415 +// Only defined for fixed-size encodings
416 +private size_t size_of_encoded(ubyte encoding)
417 +{
418 + if (encoding == DW_EH_PE_omit)
419 + return 0;
420 +
421 + switch (encoding & 0x07) // ignore leb128
422 + {
423 + case DW_EH_PE_absptr: return (void*).sizeof;
424 + case DW_EH_PE_udata2: return 2;
425 + case DW_EH_PE_udata4: return 4;
426 + case DW_EH_PE_udata8: return 8;
427 +
428 + default: fatalerror("Unrecognized fixed-size DWARF value encoding");
429 + }
430 +}
431 +
432 +// Actual value readers below: read a value from the given ubyte* into the
433 +// output parameter and return the pointer incremented past the value.
434 +
435 +// Like read_encoded_with_base but gets the base from the given context
436 +private ubyte* read_encoded(_Unwind_Context_Ptr context, ubyte encoding, ubyte* p, out size_t val)
437 +{
438 + return read_encoded_with_base(encoding, base_of_encoded(context, encoding), p, val);
439 +}
440 +
441 +private ubyte* read_encoded_with_base(ubyte encoding, size_t base, ubyte* p, out size_t val)
442 +{
443 + if (encoding == DW_EH_PE_aligned)
444 + {
445 + auto a = cast(size_t)p;
446 + a = (a + (void*).sizeof - 1) & -(void*).sizeof;
447 + val = *cast(size_t*)a;
448 + return cast(ubyte*)(a + (void*).sizeof);
449 + }
450 +
451 + union U
452 + {
453 + size_t ptr;
454 + ushort udata2;
455 + uint udata4;
456 + ulong udata8;
457 + short sdata2;
458 + int sdata4;
459 + long sdata8;
460 + }
461 +
462 + auto u = cast(U*)p;
463 +
464 + size_t result;
465 +
466 + switch (encoding & 0x0f)
467 + {
468 + case DW_EH_PE_absptr:
469 + result = u.ptr;
470 + p += (void*).sizeof;
471 + break;
472 +
473 + case DW_EH_PE_uleb128:
474 + {
475 + p = get_uleb128(p, result);
476 + break;
477 + }
478 + case DW_EH_PE_sleb128:
479 + {
480 + ptrdiff_t sleb128;
481 + p = get_sleb128(p, sleb128);
482 + result = cast(size_t)sleb128;
483 + break;
484 + }
485 +
486 + case DW_EH_PE_udata2: result = cast(size_t)u.udata2; p += 2; break;
487 + case DW_EH_PE_udata4: result = cast(size_t)u.udata4; p += 4; break;
488 + case DW_EH_PE_udata8: result = cast(size_t)u.udata8; p += 8; break;
489 + case DW_EH_PE_sdata2: result = cast(size_t)u.sdata2; p += 2; break;
490 + case DW_EH_PE_sdata4: result = cast(size_t)u.sdata4; p += 4; break;
491 + case DW_EH_PE_sdata8: result = cast(size_t)u.sdata8; p += 8; break;
492 +
493 + default: fatalerror("Unrecognized DWARF value encoding format");
494 + }
495 + if (result)
496 + {
497 + if ((encoding & 0x70) == DW_EH_PE_pcrel)
498 + result += cast(size_t)u;
499 + else
500 + result += base;
501 +
502 + if (encoding & DW_EH_PE_indirect)
503 + result = *cast(size_t*)result;
504 + }
505 + val = result;
506 + return p;
507 +}
508 +
509 private ubyte* get_uleb128(ubyte* addr, ref size_t res)
510 {
511 res = 0;
512 @@ -137,7 +286,7 @@
513
514 // read as long as high bit is set
515 while(*addr & 0x80) {
516 - res |= (*addr & 0x7f) << bitsize;
517 + res |= (*addr & 0x7fU) << bitsize;
518 bitsize += 7;
519 addr += 1;
520 if(bitsize >= size_t.sizeof*8)
521 @@ -153,12 +302,12 @@
522
523 private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res)
524 {
525 - res = 0;
526 + size_t tres = 0;
527 size_t bitsize = 0;
528
529 // read as long as high bit is set
530 while(*addr & 0x80) {
531 - res |= (*addr & 0x7f) << bitsize;
532 + tres |= (*addr & 0x7fU) << bitsize;
533 bitsize += 7;
534 addr += 1;
535 if(bitsize >= size_t.sizeof*8)
536 @@ -167,12 +316,14 @@
537 // read last
538 if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
539 fatalerror("tried to read sleb128 that exceeded size of size_t");
540 - res |= (*addr) << bitsize;
541 + tres |= (*addr) << bitsize;
542
543 // take care of sign
544 - if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40))
545 - res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1);
546 + if(bitsize < size_t.sizeof*8 && (*addr & 0x40U) != 0)
547 + tres |= cast(size_t)(-1) ^ ((1 << (bitsize+7)) - 1);
548
549 + res = cast(ptrdiff_t)tres;
550 +
551 return addr + 1;
552 }
553
554 @@ -190,8 +341,7 @@
555
556 // the 8-byte string identifying the type of exception
557 // the first 4 are for vendor, the second 4 for language
558 -//TODO: This may be the wrong way around
559 -const char[8] _d_exception_class = "LLDCD1\0\0";
560 +const char[8] _d_exception_class = "LDC_D_10";
561
562
563 //
564 @@ -201,118 +351,174 @@
565 version(X86_UNWIND)
566 {
567
568 +// Various stuff we need
569 +struct Region
570 +{
571 + ubyte* callsite_table;
572 + ubyte* action_table;
573 +
574 + // Note: classinfo_table points past the end of the table
575 + ubyte* classinfo_table;
576 +
577 + size_t start;
578 + size_t lpStart_base; // landing pad base
579 +
580 + ubyte ttypeEnc;
581 + size_t ttype_base; // typeinfo base
582 +
583 + ubyte callSiteEnc;
584 +}
585 +
586 // the personality routine gets called by the unwind handler and is responsible for
587 // reading the EH tables and deciding what to do
588 extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context)
589 {
590 + debug(EH_personality) printf("Entering personality routine, context=%p\n", context);
591 // check ver: the C++ Itanium ABI only allows ver == 1
592 if(ver != 1)
593 + {
594 + debug(EH_personality) printf("eh version mismatch\n");
595 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
596 + }
597
598 // check exceptionClass
599 //TODO: Treat foreign exceptions with more respect
600 - if((cast(char*)&exception_class)[0..8] != _d_exception_class)
601 + auto wanted_ec = *cast(ulong*)_d_exception_class.ptr;
602 + if(exception_class != wanted_ec)
603 + {
604 + debug(EH_personality) printf("exception class mismatch %p vs %p\n", exception_class, wanted_ec);
605 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
606 + }
607
608 // find call site table, action table and classinfo table
609 // Note: callsite and action tables do not contain static-length
610 // data and will be parsed as needed
611 - // Note: classinfo_table points past the end of the table
612 - ubyte* callsite_table;
613 - ubyte* action_table;
614 - ClassInfo* classinfo_table;
615 - _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table);
616 - if (!callsite_table)
617 +
618 + Region region;
619 +
620 + _d_getLanguageSpecificTables(context, region);
621 +
622 + // workaround. this should not happen
623 + if (!region.callsite_table)
624 + {
625 + debug(EH_personality) printf("callsite_table is null\n");
626 return _Unwind_Reason_Code.CONTINUE_UNWIND;
627 + }
628
629 + debug(EH_personality) printf("yay, checking\n");
630 + debug(EH_personality) printf("region.start = %p\n", region.start);
631 +
632 /*
633 find landing pad and action table index belonging to ip by walking
634 the callsite_table
635 */
636 - ubyte* callsite_walker = callsite_table;
637 + ubyte* callsite_walker = region.callsite_table;
638 + debug(EH_personality) printf("callsite table at: %p\n", region.callsite_table);
639 + debug(EH_personality) printf("action table at: %p\n", region.action_table);
640 + debug(EH_personality) printf("rtti table at %p\n", region.classinfo_table);
641
642 // get the instruction pointer
643 // will be used to find the right entry in the callsite_table
644 // -1 because it will point past the last instruction
645 - ptrdiff_t ip = _Unwind_GetIP(context) - 1;
646 + debug(EH_personality) printf("check1\n");
647 + size_t ip = _Unwind_GetIP(context) - 1;
648 + debug(EH_personality) printf("check2\n");
649
650 - // address block_start is relative to
651 - ptrdiff_t region_start = _Unwind_GetRegionStart(context);
652 -
653 // table entries
654 - uint block_start_offset, block_size;
655 - ptrdiff_t landing_pad;
656 + size_t landing_pad;
657 size_t action_offset;
658
659 while(true) {
660 // if we've gone through the list and found nothing...
661 - if(callsite_walker >= action_table)
662 + if(callsite_walker >= region.action_table)
663 + {
664 + debug(EH_personality) printf("found nothing\n");
665 return _Unwind_Reason_Code.CONTINUE_UNWIND;
666 + }
667
668 - block_start_offset = *cast(uint*)callsite_walker;
669 - block_size = *(cast(uint*)callsite_walker + 1);
670 - landing_pad = *(cast(uint*)callsite_walker + 2);
671 - if(landing_pad)
672 - landing_pad += region_start;
673 - callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset);
674 + size_t block_start, block_size;
675
676 - debug(EH_personality_verbose) printf("ip=%llx %d %d %llx\n", ip, block_start_offset, block_size, landing_pad);
677 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_start);
678 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_size);
679 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, landing_pad);
680 + callsite_walker = get_uleb128(callsite_walker, action_offset);
681
682 + debug(EH_personality) printf("*block start offset = %p\n", block_start);
683 + debug(EH_personality) printf(" block size = %p\n", block_size);
684 + debug(EH_personality) printf(" landing pad = %p\n", landing_pad);
685 + debug(EH_personality) printf(" ip=%p %p %p %p\n", ip, block_start, block_size, landing_pad);
686 +
687 // since the list is sorted, as soon as we're past the ip
688 // there's no handler to be found
689 - if(ip < region_start + block_start_offset)
690 + if(ip < region.start + block_start)
691 + {
692 + debug(EH_personality) printf("found nothing2\n");
693 return _Unwind_Reason_Code.CONTINUE_UNWIND;
694 + }
695
696 + if(landing_pad)
697 + landing_pad += region.lpStart_base;
698 +
699 // if we've found our block, exit
700 - if(ip < region_start + block_start_offset + block_size)
701 + if(ip < region.start + block_start + block_size)
702 break;
703 }
704
705 - debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset);
706 + debug(EH_personality) printf("Found correct landing pad %p and actionOffset %p\n", landing_pad, action_offset);
707
708 // now we need the exception's classinfo to find a handler
709 // the exception_info is actually a member of a larger _d_exception struct
710 // the runtime allocated. get that now
711 - _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof);
712 + _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - size_t.sizeof); //_d_exception.unwind_info.offsetof);
713
714 // if there's no action offset and no landing pad, continue unwinding
715 if(!action_offset && !landing_pad)
716 return _Unwind_Reason_Code.CONTINUE_UNWIND;
717
718 // if there's no action offset but a landing pad, this is a cleanup handler
719 - else if(!action_offset && landing_pad)
720 - return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
721 + else if(!action_offset && landing_pad != 0)
722 + {
723 + debug(EH_personality) printf("installing finally context\n");
724 + return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context);
725 + }
726
727 /*
728 walk action table chain, comparing classinfos using _d_isbaseof
729 */
730 - ubyte* action_walker = action_table + action_offset - 1;
731 + ubyte* action_walker = region.action_table + action_offset - 1;
732
733 - ptrdiff_t ti_offset, next_action_offset;
734 while(true) {
735 + ptrdiff_t ti_offset, next_action_offset;
736 +
737 action_walker = get_sleb128(action_walker, ti_offset);
738 // it is intentional that we not modify action_walker here
739 // next_action_offset is from current action_walker position
740 get_sleb128(action_walker, next_action_offset);
741
742 // negative are 'filters' which we don't use
743 - if(!(ti_offset >= 0))
744 + if(ti_offset < 0)
745 fatalerror("Filter actions are unsupported");
746
747 // zero means cleanup, which we require to be the last action
748 if(ti_offset == 0) {
749 - if(!(next_action_offset == 0))
750 + if(next_action_offset != 0)
751 fatalerror("Cleanup action must be last in chain");
752 - return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
753 + return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context);
754 }
755
756 // get classinfo for action and check if the one in the
757 // exception structure is a base
758 - ClassInfo catch_ci = *(classinfo_table - ti_offset);
759 - debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr);
760 - if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci))
761 - return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context);
762 + size_t typeinfo;
763 + auto filter = cast(size_t)ti_offset * size_of_encoded(region.ttypeEnc);
764 + read_encoded_with_base(region.ttypeEnc, region.ttype_base, region.classinfo_table - filter, typeinfo);
765
766 + debug(EH_personality)
767 + 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);
768 +
769 + auto catch_ci = *cast(ClassInfo*)&typeinfo;
770 + if(_d_dynamic_cast(exception_struct.exception_object, catch_ci) !is null)
771 + return _d_eh_install_catch_context(actions, ti_offset, cast(ptrdiff_t)landing_pad, exception_struct, context);
772 +
773 // we've walked through all actions and found nothing...
774 if(next_action_offset == 0)
775 return _Unwind_Reason_Code.CONTINUE_UNWIND;
776 @@ -356,6 +562,7 @@
777 }
778
779 fatalerror("reached unreachable");
780 +
781 return _Unwind_Reason_Code.FATAL_PHASE2_ERROR;
782 }
783
784 @@ -370,56 +577,78 @@
785 _Unwind_SetGR(context, eh_exception_regno, cast(ptrdiff_t)exception_struct);
786 _Unwind_SetGR(context, eh_selector_regno, 0);
787 _Unwind_SetIP(context, landing_pad);
788 +
789 return _Unwind_Reason_Code.INSTALL_CONTEXT;
790 }
791
792 -private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)
793 +private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, out Region region)
794 {
795 - ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
796 + auto data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
797 +
798 + // workaround. this should not be 0...
799 if (!data)
800 {
801 - callsite = null;
802 - action = null;
803 - ci = null;
804 - return;
805 + //printf("language specific data is null\n");
806 + return;
807 }
808
809 - //TODO: Do proper DWARF reading here
810 - if(*data++ != 0xff)
811 - fatalerror("DWARF header has unexpected format 1");
812 + region.start = _Unwind_GetRegionStart(context);
813
814 - if(*data++ != 0x00)
815 - fatalerror("DWARF header has unexpected format 2");
816 - size_t cioffset;
817 - data = get_uleb128(data, cioffset);
818 - ci = cast(ClassInfo*)(data + cioffset);
819 + // Read the C++-style LSDA: this is implementation-defined by GCC but LLVM
820 + // outputs the same kind of table
821
822 - if(*data++ != 0x03)
823 - fatalerror("DWARF header has unexpected format 3");
824 - size_t callsitelength;
825 - data = get_uleb128(data, callsitelength);
826 - action = data + callsitelength;
827 + // Get @LPStart: landing pad offsets are relative to it
828 + auto lpStartEnc = *data++;
829 + if (lpStartEnc == DW_EH_PE_omit)
830 + region.lpStart_base = region.start;
831 + else
832 + data = read_encoded(context, lpStartEnc, data, region.lpStart_base);
833
834 - callsite = data;
835 + // Get @TType: the offset to the handler and typeinfo
836 + region.ttypeEnc = *data++;
837 + if (region.ttypeEnc == DW_EH_PE_omit)
838 + // Not sure about this one...
839 + fatalerror("@TType must not be omitted from DWARF header");
840 +
841 + size_t ciOffset;
842 + data = get_uleb128(data, ciOffset);
843 + region.classinfo_table = data + ciOffset;
844 +
845 + region.ttype_base = base_of_encoded(context, region.ttypeEnc);
846 +
847 + // Get encoding and length of the call site table, which precedes the action
848 + // table.
849 + region.callSiteEnc = *data++;
850 + if (region.callSiteEnc == DW_EH_PE_omit)
851 + fatalerror("Call site table encoding must not be omitted from DWARF header");
852 +
853 + size_t callSiteLength;
854 + region.callsite_table = get_uleb128(data, callSiteLength);
855 + region.action_table = region.callsite_table + callSiteLength;
856 }
857
858 } // end of x86 Linux specific implementation
859
860 -
861 -extern(C) void _d_throw_exception(Object e)
862 +// called to throw object
863 +extern(C)
864 +void _d_throw_exception(Object e)
865 {
866 + //printf("throwing %p, rtti = %p\n", e, **cast(ClassRTTI***)e);
867 if (e !is null)
868 {
869 _d_exception* exc_struct = new _d_exception;
870 exc_struct.unwind_info.exception_class = *cast(ulong*)_d_exception_class.ptr;
871 exc_struct.exception_object = e;
872 _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info);
873 - console("_Unwind_RaiseException failed with reason code: ")(ret)("\n");
874 + printf("Error: returned %d from raise exception.\n", ret);
875 + //console("_Unwind_RaiseException failed with reason code: ")(ret)("\n");
876 }
877 abort();
878 }
879
880 -extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct)
881 +// called to resume unwinding
882 +extern(C)
883 +void _d_eh_resume_unwind(void* exception_struct)
884 {
885 - _Unwind_Resume(&exception_struct.unwind_info);
886 + _Unwind_Resume(&(cast(_d_exception*)exception_struct).unwind_info);
887 }
6861e45 @lindquist Updated Tango 0.99.9 patch!
lindquist authored
888 Index: tango/core/vendor/ldc/intrinsics.di
889 ===================================================================
890 --- tango/core/vendor/ldc/intrinsics.di (revision 5576)
891 +++ tango/core/vendor/ldc/intrinsics.di (working copy)
892 @@ -101,8 +101,16 @@
893 // Note that, unlike the standard libc function, the llvm.memcpy.* intrinsics do
894 // not return a value, and takes an extra alignment argument.
895
896 -pragma(intrinsic, "llvm.memcpy.i#")
897 - void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment);
898 +version(LDC_LLVMPre28)
899 +{
900 + pragma(intrinsic, "llvm.memcpy.i#")
901 + void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment);
902 +}
903 +else
904 +{
905 + pragma(intrinsic, "llvm.memcpy.p0i8.p0i8.i#")
906 + void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment, bool volatile_);
907 +}
908
909 deprecated {
910 alias llvm_memcpy!(uint) llvm_memcpy_i32;
911 @@ -116,8 +124,16 @@
912 // Note that, unlike the standard libc function, the llvm.memmove.* intrinsics
913 // do not return a value, and takes an extra alignment argument.
914
915 -pragma(intrinsic, "llvm.memmove.i#")
916 - void llvm_memmove(T)(void* dst, void* src, T len, uint alignment);
917 +version(LDC_LLVMPre28)
918 +{
919 + pragma(intrinsic, "llvm.memmove.i#")
920 + void llvm_memmove(T)(void* dst, void* src, T len, uint alignment);
921 +}
922 +else
923 +{
924 + pragma(intrinsic, "llvm.memmove.p0i8.p0i8.i#")
925 + void llvm_memmove(T)(void* dst, void* src, T len, uint alignment, bool volatile_);
926 +}
927
928 deprecated {
929 alias llvm_memmove!(uint) llvm_memmove_i32;
930 @@ -130,8 +146,16 @@
931 // Note that, unlike the standard libc function, the llvm.memset intrinsic does
932 // not return a value, and takes an extra alignment argument.
933
934 -pragma(intrinsic, "llvm.memset.i#")
935 - void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment);
936 +version(LDC_LLVMPre28)
937 +{
938 + pragma(intrinsic, "llvm.memset.i#")
939 + void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment);
940 +}
941 +else
942 +{
943 + pragma(intrinsic, "llvm.memset.p0i8.i#")
944 + void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment, bool volatile_);
945 +}
946
947 deprecated {
948 alias llvm_memset!(uint) llvm_memset_i32;
Something went wrong with that request. Please try again.