Mercurial > projects > ldc
annotate 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 |
rev | line source |
---|---|
1633
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
1 Index: tango/core/rt/compiler/ldc/rt/lifetime.d |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
2 =================================================================== |
1650 | 3 --- tango/core/rt/compiler/ldc/rt/lifetime.d (revision 5462) |
1633
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
4 +++ tango/core/rt/compiler/ldc/rt/lifetime.d (working copy) |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
5 @@ -786,6 +786,7 @@ |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
6 return *cast(long*)px; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
7 } |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
8 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
9 ++/ |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
10 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
11 /** |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
12 * |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
13 @@ -849,10 +850,11 @@ |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
14 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
15 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
16 /** |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
17 - * |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
18 + * Appends a single element to an array. |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
19 */ |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
20 -extern (C) byte[] _d_arrayappendcT(TypeInfo ti, ref byte[] x, ...) |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
21 +extern (C) byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element) |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
22 { |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
23 + auto x = cast(byte[]*)array; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
24 auto sizeelem = ti.next.tsize(); // array element size |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
25 auto info = gc_query(x.ptr); |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
26 auto length = x.length; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
27 @@ -879,16 +881,16 @@ |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
28 assert(newcap >= newlength * sizeelem); |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
29 newdata = cast(byte *)gc_malloc(newcap + 1, info.attr); |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
30 memcpy(newdata, x.ptr, length * sizeelem); |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
31 - (cast(void**)(&x))[1] = newdata; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
32 + (cast(void**)x)[1] = newdata; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
33 } |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
34 L1: |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
35 - byte *argp = cast(byte *)(&ti + 2); |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
36 + byte *argp = cast(byte *)element; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
37 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
38 - *cast(size_t *)&x = newlength; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
39 + *cast(size_t *)x = newlength; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
40 x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
41 assert((cast(size_t)x.ptr & 15) == 0); |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
42 assert(gc_sizeOf(x.ptr) > x.length * sizeelem); |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
43 - return x; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
44 + return *x; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
45 } |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
46 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
47 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
48 @@ -1128,6 +1130,7 @@ |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
49 return result; |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
50 } |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
51 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
52 +/+ |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
53 |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
54 /** |
5c0cebff9be8
Improve array append performance.
Christian Kamm <kamm incasoftware de>
parents:
diff
changeset
|
55 * |
1650 | 56 Index: tango/core/rt/compiler/ldc/rt/eh.d |
57 =================================================================== | |
58 --- tango/core/rt/compiler/ldc/rt/eh.d (revision 5462) | |
59 +++ tango/core/rt/compiler/ldc/rt/eh.d (working copy) | |
60 @@ -1,38 +1,34 @@ | |
61 /** | |
62 * This module contains functions and structures required for | |
63 - * exception handling. | |
64 + * dwarf exception handling with llvm | |
65 */ | |
66 module rt.eh; | |
67 | |
68 -import ldc.cstdarg; | |
69 -import rt.compiler.util.console; | |
70 +//debug = EH_personality; | |
71 | |
72 -// debug = EH_personality; | |
73 - | |
74 // current EH implementation works on x86 | |
75 // if it has a working unwind runtime | |
76 version(X86) { | |
77 version(linux) version=X86_UNWIND; | |
78 version(darwin) version=X86_UNWIND; | |
79 version(solaris) version=X86_UNWIND; | |
80 - version(freebsd) version=X86_UNWIND; | |
81 } | |
82 version(X86_64) { | |
83 version(linux) version=X86_UNWIND; | |
84 version(darwin) version=X86_UNWIND; | |
85 version(solaris) version=X86_UNWIND; | |
86 - version(freebsd) version=X86_UNWIND; | |
87 } | |
88 | |
89 //version = HP_LIBUNWIND; | |
90 | |
91 private extern(C) void abort(); | |
92 private extern(C) int printf(char*, ...); | |
93 -private extern(C) int vprintf(char*, va_list va); | |
94 +//private extern(C) int vprintf(char*, va_list va); | |
95 | |
96 // D runtime functions | |
97 extern(C) { | |
98 - int _d_isbaseof(ClassInfo oc, ClassInfo c); | |
99 +// int _d_isbaseof(ClassInfo oc, ClassInfo c); | |
100 + Object _d_dynamic_cast(Object o, ClassInfo c); | |
101 } | |
102 | |
103 // libunwind headers | |
104 @@ -74,16 +70,19 @@ | |
105 // interface to HP's libunwind from http://www.nongnu.org/libunwind/ | |
106 version(HP_LIBUNWIND) | |
107 { | |
108 + // Haven't checked whether and how it has _Unwind_Get{Text,Data}RelBase | |
109 + pragma (msg, "HP_LIBUNWIND interface is out of date and untested"); | |
110 + | |
111 void __libunwind_Unwind_Resume(_Unwind_Exception *); | |
112 _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *); | |
113 ptrdiff_t __libunwind_Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr | |
114 context); | |
115 - ptrdiff_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); | |
116 + size_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); | |
117 ptrdiff_t __libunwind_Unwind_SetIP(_Unwind_Context_Ptr context, | |
118 ptrdiff_t new_value); | |
119 ptrdiff_t __libunwind_Unwind_SetGR(_Unwind_Context_Ptr context, int index, | |
120 ptrdiff_t new_value); | |
121 - ptrdiff_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); | |
122 + size_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); | |
123 | |
124 alias __libunwind_Unwind_Resume _Unwind_Resume; | |
125 alias __libunwind_Unwind_RaiseException _Unwind_RaiseException; | |
126 @@ -94,27 +93,30 @@ | |
127 alias __libunwind_Unwind_SetGR _Unwind_SetGR; | |
128 alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart; | |
129 } | |
130 -else version(X86_UNWIND) | |
131 +else version(X86_UNWIND) | |
132 { | |
133 void _Unwind_Resume(_Unwind_Exception*); | |
134 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*); | |
135 ptrdiff_t _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context); | |
136 - ptrdiff_t _Unwind_GetIP(_Unwind_Context_Ptr context); | |
137 + size_t _Unwind_GetIP(_Unwind_Context_Ptr context); | |
138 ptrdiff_t _Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value); | |
139 ptrdiff_t _Unwind_SetGR(_Unwind_Context_Ptr context, int index, | |
140 ptrdiff_t new_value); | |
141 - ptrdiff_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); | |
142 + size_t _Unwind_GetRegionStart(_Unwind_Context_Ptr context); | |
143 + | |
144 + size_t _Unwind_GetTextRelBase(_Unwind_Context_Ptr); | |
145 + size_t _Unwind_GetDataRelBase(_Unwind_Context_Ptr); | |
146 } | |
147 else | |
148 { | |
149 // runtime calls these directly | |
150 void _Unwind_Resume(_Unwind_Exception*) | |
151 { | |
152 - console("_Unwind_Resume is not implemented on this platform.\n"); | |
153 + printf("_Unwind_Resume is not implemented on this platform.\n"); | |
154 } | |
155 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*) | |
156 { | |
157 - console("_Unwind_RaiseException is not implemented on this platform.\n"); | |
158 + printf("_Unwind_RaiseException is not implemented on this platform.\n"); | |
159 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; | |
160 } | |
161 } | |
162 @@ -122,14 +124,161 @@ | |
163 } | |
164 | |
165 // error and exit | |
166 -extern(C) private void fatalerror(char[] format) | |
167 +extern(C) private void fatalerror(char* format, ...) | |
168 { | |
169 - printf("Fatal error in EH code: %.*s\n", format.length, format.ptr); | |
170 +// va_list args; | |
171 +// va_start(args, format); | |
172 + printf("Fatal error in EH code: "); | |
173 +// vprintf(format, args); | |
174 + printf("\n"); | |
175 abort(); | |
176 } | |
177 | |
178 | |
179 -// helpers for reading certain DWARF data | |
180 +// DWARF EH encoding enum | |
181 +// See e.g. http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/dwarfext.html | |
182 +private enum : ubyte { | |
183 + DW_EH_PE_omit = 0xff, // value is not present | |
184 + | |
185 + // value format | |
186 + DW_EH_PE_absptr = 0x00, // literal pointer | |
187 + DW_EH_PE_uleb128 = 0x01, | |
188 + DW_EH_PE_udata2 = 0x02, // unsigned 2-byte | |
189 + DW_EH_PE_udata4 = 0x03, | |
190 + DW_EH_PE_udata8 = 0x04, | |
191 + DW_EH_PE_sleb128 = 0x09, | |
192 + DW_EH_PE_sdata2 = 0x0a, | |
193 + DW_EH_PE_sdata4 = 0x0b, | |
194 + DW_EH_PE_sdata8 = 0x0c, | |
195 + | |
196 + // value meaning | |
197 + DW_EH_PE_pcrel = 0x10, // relative to program counter | |
198 + DW_EH_PE_textrel = 0x20, // relative to .text | |
199 + DW_EH_PE_datarel = 0x30, // relative to .got or .eh_frame_hdr | |
200 + DW_EH_PE_funcrel = 0x40, // relative to beginning of function | |
201 + DW_EH_PE_aligned = 0x50, // is an aligned void* | |
202 + | |
203 + // value is a pointer to the actual value | |
204 + // this is a mask on top of one of the above | |
205 + DW_EH_PE_indirect = 0x80 | |
206 +} | |
207 + | |
208 +// Helpers for reading DWARF data | |
209 + | |
210 +// Given an encoding and a context, return the base to which the encoding is | |
211 +// relative | |
212 +private size_t base_of_encoded(_Unwind_Context_Ptr context, ubyte encoding) | |
213 +{ | |
214 + if (encoding == DW_EH_PE_omit) | |
215 + return 0; | |
216 + | |
217 + switch (encoding & 0x70) // ignore DW_EH_PE_indirect | |
218 + { | |
219 + case DW_EH_PE_absptr, DW_EH_PE_pcrel, DW_EH_PE_aligned: | |
220 + return 0; | |
221 + | |
222 + case DW_EH_PE_textrel: return _Unwind_GetTextRelBase(context); | |
223 + case DW_EH_PE_datarel: return _Unwind_GetDataRelBase(context); | |
224 + case DW_EH_PE_funcrel: return _Unwind_GetRegionStart(context); | |
225 + | |
226 + default: fatalerror("Unrecognized base for DWARF value"); | |
227 + } | |
228 +} | |
229 + | |
230 +// Only defined for fixed-size encodings | |
231 +private size_t size_of_encoded(ubyte encoding) | |
232 +{ | |
233 + if (encoding == DW_EH_PE_omit) | |
234 + return 0; | |
235 + | |
236 + switch (encoding & 0x07) // ignore leb128 | |
237 + { | |
238 + case DW_EH_PE_absptr: return (void*).sizeof; | |
239 + case DW_EH_PE_udata2: return 2; | |
240 + case DW_EH_PE_udata4: return 4; | |
241 + case DW_EH_PE_udata8: return 8; | |
242 + | |
243 + default: fatalerror("Unrecognized fixed-size DWARF value encoding"); | |
244 + } | |
245 +} | |
246 + | |
247 +// Actual value readers below: read a value from the given ubyte* into the | |
248 +// output parameter and return the pointer incremented past the value. | |
249 + | |
250 +// Like read_encoded_with_base but gets the base from the given context | |
251 +private ubyte* read_encoded(_Unwind_Context_Ptr context, ubyte encoding, ubyte* p, out size_t val) | |
252 +{ | |
253 + return read_encoded_with_base(encoding, base_of_encoded(context, encoding), p, val); | |
254 +} | |
255 + | |
256 +private ubyte* read_encoded_with_base(ubyte encoding, size_t base, ubyte* p, out size_t val) | |
257 +{ | |
258 + if (encoding == DW_EH_PE_aligned) | |
259 + { | |
260 + auto a = cast(size_t)p; | |
261 + a = (a + (void*).sizeof - 1) & -(void*).sizeof; | |
262 + val = *cast(size_t*)a; | |
263 + return cast(ubyte*)(a + (void*).sizeof); | |
264 + } | |
265 + | |
266 + union U | |
267 + { | |
268 + size_t ptr; | |
269 + ushort udata2; | |
270 + uint udata4; | |
271 + ulong udata8; | |
272 + short sdata2; | |
273 + int sdata4; | |
274 + long sdata8; | |
275 + } | |
276 + | |
277 + auto u = cast(U*)p; | |
278 + | |
279 + size_t result; | |
280 + | |
281 + switch (encoding & 0x0f) | |
282 + { | |
283 + case DW_EH_PE_absptr: | |
284 + result = u.ptr; | |
285 + p += (void*).sizeof; | |
286 + break; | |
287 + | |
288 + case DW_EH_PE_uleb128: | |
289 + { | |
290 + p = get_uleb128(p, result); | |
291 + break; | |
292 + } | |
293 + case DW_EH_PE_sleb128: | |
294 + { | |
295 + ptrdiff_t sleb128; | |
296 + p = get_sleb128(p, sleb128); | |
297 + result = cast(size_t)sleb128; | |
298 + break; | |
299 + } | |
300 + | |
301 + case DW_EH_PE_udata2: result = cast(size_t)u.udata2; p += 2; break; | |
302 + case DW_EH_PE_udata4: result = cast(size_t)u.udata4; p += 4; break; | |
303 + case DW_EH_PE_udata8: result = cast(size_t)u.udata8; p += 8; break; | |
304 + case DW_EH_PE_sdata2: result = cast(size_t)u.sdata2; p += 2; break; | |
305 + case DW_EH_PE_sdata4: result = cast(size_t)u.sdata4; p += 4; break; | |
306 + case DW_EH_PE_sdata8: result = cast(size_t)u.sdata8; p += 8; break; | |
307 + | |
308 + default: fatalerror("Unrecognized DWARF value encoding format"); | |
309 + } | |
310 + if (result) | |
311 + { | |
312 + if ((encoding & 0x70) == DW_EH_PE_pcrel) | |
313 + result += cast(size_t)u; | |
314 + else | |
315 + result += base; | |
316 + | |
317 + if (encoding & DW_EH_PE_indirect) | |
318 + result = *cast(size_t*)result; | |
319 + } | |
320 + val = result; | |
321 + return p; | |
322 +} | |
323 + | |
324 private ubyte* get_uleb128(ubyte* addr, ref size_t res) | |
325 { | |
326 res = 0; | |
327 @@ -137,7 +286,7 @@ | |
328 | |
329 // read as long as high bit is set | |
330 while(*addr & 0x80) { | |
331 - res |= (*addr & 0x7f) << bitsize; | |
332 + res |= (*addr & 0x7fU) << bitsize; | |
333 bitsize += 7; | |
334 addr += 1; | |
335 if(bitsize >= size_t.sizeof*8) | |
336 @@ -153,12 +302,12 @@ | |
337 | |
338 private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res) | |
339 { | |
340 - res = 0; | |
341 + size_t tres = 0; | |
342 size_t bitsize = 0; | |
343 | |
344 // read as long as high bit is set | |
345 while(*addr & 0x80) { | |
346 - res |= (*addr & 0x7f) << bitsize; | |
347 + tres |= (*addr & 0x7fU) << bitsize; | |
348 bitsize += 7; | |
349 addr += 1; | |
350 if(bitsize >= size_t.sizeof*8) | |
351 @@ -167,12 +316,14 @@ | |
352 // read last | |
353 if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize) | |
354 fatalerror("tried to read sleb128 that exceeded size of size_t"); | |
355 - res |= (*addr) << bitsize; | |
356 + tres |= (*addr) << bitsize; | |
357 | |
358 // take care of sign | |
359 - if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40)) | |
360 - res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1); | |
361 + if(bitsize < size_t.sizeof*8 && (*addr & 0x40U) != 0) | |
362 + tres |= cast(size_t)(-1) ^ ((1 << (bitsize+7)) - 1); | |
363 | |
364 + res = cast(ptrdiff_t)tres; | |
365 + | |
366 return addr + 1; | |
367 } | |
368 | |
369 @@ -190,8 +341,7 @@ | |
370 | |
371 // the 8-byte string identifying the type of exception | |
372 // the first 4 are for vendor, the second 4 for language | |
373 -//TODO: This may be the wrong way around | |
374 -const char[8] _d_exception_class = "LLDCD1\0\0"; | |
375 +const char[8] _d_exception_class = "LDC_D_10"; | |
376 | |
377 | |
378 // | |
379 @@ -201,118 +351,174 @@ | |
380 version(X86_UNWIND) | |
381 { | |
382 | |
383 +// Various stuff we need | |
384 +struct Region | |
385 +{ | |
386 + ubyte* callsite_table; | |
387 + ubyte* action_table; | |
388 + | |
389 + // Note: classinfo_table points past the end of the table | |
390 + ubyte* classinfo_table; | |
391 + | |
392 + size_t start; | |
393 + size_t lpStart_base; // landing pad base | |
394 + | |
395 + ubyte ttypeEnc; | |
396 + size_t ttype_base; // typeinfo base | |
397 + | |
398 + ubyte callSiteEnc; | |
399 +} | |
400 + | |
401 // the personality routine gets called by the unwind handler and is responsible for | |
402 // reading the EH tables and deciding what to do | |
403 extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context) | |
404 { | |
405 + debug(EH_personality) printf("Entering personality routine, context=%p\n", context); | |
406 // check ver: the C++ Itanium ABI only allows ver == 1 | |
407 if(ver != 1) | |
408 + { | |
409 + debug(EH_personality) printf("eh version mismatch\n"); | |
410 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; | |
411 + } | |
412 | |
413 // check exceptionClass | |
414 //TODO: Treat foreign exceptions with more respect | |
415 - if((cast(char*)&exception_class)[0..8] != _d_exception_class) | |
416 + auto wanted_ec = *cast(ulong*)_d_exception_class.ptr; | |
417 + if(exception_class != wanted_ec) | |
418 + { | |
419 + debug(EH_personality) printf("exception class mismatch %p vs %p\n", exception_class, wanted_ec); | |
420 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; | |
421 + } | |
422 | |
423 // find call site table, action table and classinfo table | |
424 // Note: callsite and action tables do not contain static-length | |
425 // data and will be parsed as needed | |
426 - // Note: classinfo_table points past the end of the table | |
427 - ubyte* callsite_table; | |
428 - ubyte* action_table; | |
429 - ClassInfo* classinfo_table; | |
430 - _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table); | |
431 - if (!callsite_table) | |
432 + | |
433 + Region region; | |
434 + | |
435 + _d_getLanguageSpecificTables(context, region); | |
436 + | |
437 + // workaround. this should not happen | |
438 + if (!region.callsite_table) | |
439 + { | |
440 + debug(EH_personality) printf("callsite_table is null\n"); | |
441 return _Unwind_Reason_Code.CONTINUE_UNWIND; | |
442 + } | |
443 | |
444 + debug(EH_personality) printf("yay, checking\n"); | |
445 + debug(EH_personality) printf("region.start = %p\n", region.start); | |
446 + | |
447 /* | |
448 find landing pad and action table index belonging to ip by walking | |
449 the callsite_table | |
450 */ | |
451 - ubyte* callsite_walker = callsite_table; | |
452 + ubyte* callsite_walker = region.callsite_table; | |
453 + debug(EH_personality) printf("callsite table at: %p\n", region.callsite_table); | |
454 + debug(EH_personality) printf("action table at: %p\n", region.action_table); | |
455 + debug(EH_personality) printf("rtti table at %p\n", region.classinfo_table); | |
456 | |
457 // get the instruction pointer | |
458 // will be used to find the right entry in the callsite_table | |
459 // -1 because it will point past the last instruction | |
460 - ptrdiff_t ip = _Unwind_GetIP(context) - 1; | |
461 + debug(EH_personality) printf("check1\n"); | |
462 + size_t ip = _Unwind_GetIP(context) - 1; | |
463 + debug(EH_personality) printf("check2\n"); | |
464 | |
465 - // address block_start is relative to | |
466 - ptrdiff_t region_start = _Unwind_GetRegionStart(context); | |
467 - | |
468 // table entries | |
469 - uint block_start_offset, block_size; | |
470 - ptrdiff_t landing_pad; | |
471 + size_t landing_pad; | |
472 size_t action_offset; | |
473 | |
474 while(true) { | |
475 // if we've gone through the list and found nothing... | |
476 - if(callsite_walker >= action_table) | |
477 + if(callsite_walker >= region.action_table) | |
478 + { | |
479 + debug(EH_personality) printf("found nothing\n"); | |
480 return _Unwind_Reason_Code.CONTINUE_UNWIND; | |
481 + } | |
482 | |
483 - block_start_offset = *cast(uint*)callsite_walker; | |
484 - block_size = *(cast(uint*)callsite_walker + 1); | |
485 - landing_pad = *(cast(uint*)callsite_walker + 2); | |
486 - if(landing_pad) | |
487 - landing_pad += region_start; | |
488 - callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset); | |
489 + size_t block_start, block_size; | |
490 | |
491 - debug(EH_personality_verbose) printf("ip=%llx %d %d %llx\n", ip, block_start_offset, block_size, landing_pad); | |
492 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_start); | |
493 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, block_size); | |
494 + callsite_walker = read_encoded(null, region.callSiteEnc, callsite_walker, landing_pad); | |
495 + callsite_walker = get_uleb128(callsite_walker, action_offset); | |
496 | |
497 + debug(EH_personality) printf("*block start offset = %p\n", block_start); | |
498 + debug(EH_personality) printf(" block size = %p\n", block_size); | |
499 + debug(EH_personality) printf(" landing pad = %p\n", landing_pad); | |
500 + debug(EH_personality) printf(" ip=%p %p %p %p\n", ip, block_start, block_size, landing_pad); | |
501 + | |
502 // since the list is sorted, as soon as we're past the ip | |
503 // there's no handler to be found | |
504 - if(ip < region_start + block_start_offset) | |
505 + if(ip < region.start + block_start) | |
506 + { | |
507 + debug(EH_personality) printf("found nothing2\n"); | |
508 return _Unwind_Reason_Code.CONTINUE_UNWIND; | |
509 + } | |
510 | |
511 + if(landing_pad) | |
512 + landing_pad += region.lpStart_base; | |
513 + | |
514 // if we've found our block, exit | |
515 - if(ip < region_start + block_start_offset + block_size) | |
516 + if(ip < region.start + block_start + block_size) | |
517 break; | |
518 } | |
519 | |
520 - debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset); | |
521 + debug(EH_personality) printf("Found correct landing pad %p and actionOffset %p\n", landing_pad, action_offset); | |
522 | |
523 // now we need the exception's classinfo to find a handler | |
524 // the exception_info is actually a member of a larger _d_exception struct | |
525 // the runtime allocated. get that now | |
526 - _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof); | |
527 + _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - size_t.sizeof); //_d_exception.unwind_info.offsetof); | |
528 | |
529 // if there's no action offset and no landing pad, continue unwinding | |
530 if(!action_offset && !landing_pad) | |
531 return _Unwind_Reason_Code.CONTINUE_UNWIND; | |
532 | |
533 // if there's no action offset but a landing pad, this is a cleanup handler | |
534 - else if(!action_offset && landing_pad) | |
535 - return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); | |
536 + else if(!action_offset && landing_pad != 0) | |
537 + { | |
538 + debug(EH_personality) printf("installing finally context\n"); | |
539 + return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); | |
540 + } | |
541 | |
542 /* | |
543 walk action table chain, comparing classinfos using _d_isbaseof | |
544 */ | |
545 - ubyte* action_walker = action_table + action_offset - 1; | |
546 + ubyte* action_walker = region.action_table + action_offset - 1; | |
547 | |
548 - ptrdiff_t ti_offset, next_action_offset; | |
549 while(true) { | |
550 + ptrdiff_t ti_offset, next_action_offset; | |
551 + | |
552 action_walker = get_sleb128(action_walker, ti_offset); | |
553 // it is intentional that we not modify action_walker here | |
554 // next_action_offset is from current action_walker position | |
555 get_sleb128(action_walker, next_action_offset); | |
556 | |
557 // negative are 'filters' which we don't use | |
558 - if(!(ti_offset >= 0)) | |
559 + if(ti_offset < 0) | |
560 fatalerror("Filter actions are unsupported"); | |
561 | |
562 // zero means cleanup, which we require to be the last action | |
563 if(ti_offset == 0) { | |
564 - if(!(next_action_offset == 0)) | |
565 + if(next_action_offset != 0) | |
566 fatalerror("Cleanup action must be last in chain"); | |
567 - return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context); | |
568 + return _d_eh_install_finally_context(actions, cast(ptrdiff_t)landing_pad, exception_struct, context); | |
569 } | |
570 | |
571 // get classinfo for action and check if the one in the | |
572 // exception structure is a base | |
573 - ClassInfo catch_ci = *(classinfo_table - ti_offset); | |
574 - debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr); | |
575 - if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci)) | |
576 - return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context); | |
577 + size_t typeinfo; | |
578 + auto filter = cast(size_t)ti_offset * size_of_encoded(region.ttypeEnc); | |
579 + read_encoded_with_base(region.ttypeEnc, region.ttype_base, region.classinfo_table - filter, typeinfo); | |
580 | |
581 + debug(EH_personality) | |
582 + 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); | |
583 + | |
584 + auto catch_ci = *cast(ClassInfo*)&typeinfo; | |
585 + if(_d_dynamic_cast(exception_struct.exception_object, catch_ci) !is null) | |
586 + return _d_eh_install_catch_context(actions, ti_offset, cast(ptrdiff_t)landing_pad, exception_struct, context); | |
587 + | |
588 // we've walked through all actions and found nothing... | |
589 if(next_action_offset == 0) | |
590 return _Unwind_Reason_Code.CONTINUE_UNWIND; | |
591 @@ -356,6 +562,7 @@ | |
592 } | |
593 | |
594 fatalerror("reached unreachable"); | |
595 + | |
596 return _Unwind_Reason_Code.FATAL_PHASE2_ERROR; | |
597 } | |
598 | |
599 @@ -370,56 +577,78 @@ | |
600 _Unwind_SetGR(context, eh_exception_regno, cast(ptrdiff_t)exception_struct); | |
601 _Unwind_SetGR(context, eh_selector_regno, 0); | |
602 _Unwind_SetIP(context, landing_pad); | |
603 + | |
604 return _Unwind_Reason_Code.INSTALL_CONTEXT; | |
605 } | |
606 | |
607 -private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci) | |
608 +private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, out Region region) | |
609 { | |
610 - ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); | |
611 + auto data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); | |
612 + | |
613 + // workaround. this should not be 0... | |
614 if (!data) | |
615 { | |
616 - callsite = null; | |
617 - action = null; | |
618 - ci = null; | |
619 - return; | |
620 + //printf("language specific data is null\n"); | |
621 + return; | |
622 } | |
623 | |
624 - //TODO: Do proper DWARF reading here | |
625 - if(*data++ != 0xff) | |
626 - fatalerror("DWARF header has unexpected format 1"); | |
627 + region.start = _Unwind_GetRegionStart(context); | |
628 | |
629 - if(*data++ != 0x00) | |
630 - fatalerror("DWARF header has unexpected format 2"); | |
631 - size_t cioffset; | |
632 - data = get_uleb128(data, cioffset); | |
633 - ci = cast(ClassInfo*)(data + cioffset); | |
634 + // Read the C++-style LSDA: this is implementation-defined by GCC but LLVM | |
635 + // outputs the same kind of table | |
636 | |
637 - if(*data++ != 0x03) | |
638 - fatalerror("DWARF header has unexpected format 3"); | |
639 - size_t callsitelength; | |
640 - data = get_uleb128(data, callsitelength); | |
641 - action = data + callsitelength; | |
642 + // Get @LPStart: landing pad offsets are relative to it | |
643 + auto lpStartEnc = *data++; | |
644 + if (lpStartEnc == DW_EH_PE_omit) | |
645 + region.lpStart_base = region.start; | |
646 + else | |
647 + data = read_encoded(context, lpStartEnc, data, region.lpStart_base); | |
648 | |
649 - callsite = data; | |
650 + // Get @TType: the offset to the handler and typeinfo | |
651 + region.ttypeEnc = *data++; | |
652 + if (region.ttypeEnc == DW_EH_PE_omit) | |
653 + // Not sure about this one... | |
654 + fatalerror("@TType must not be omitted from DWARF header"); | |
655 + | |
656 + size_t ciOffset; | |
657 + data = get_uleb128(data, ciOffset); | |
658 + region.classinfo_table = data + ciOffset; | |
659 + | |
660 + region.ttype_base = base_of_encoded(context, region.ttypeEnc); | |
661 + | |
662 + // Get encoding and length of the call site table, which precedes the action | |
663 + // table. | |
664 + region.callSiteEnc = *data++; | |
665 + if (region.callSiteEnc == DW_EH_PE_omit) | |
666 + fatalerror("Call site table encoding must not be omitted from DWARF header"); | |
667 + | |
668 + size_t callSiteLength; | |
669 + region.callsite_table = get_uleb128(data, callSiteLength); | |
670 + region.action_table = region.callsite_table + callSiteLength; | |
671 } | |
672 | |
673 } // end of x86 Linux specific implementation | |
674 | |
675 - | |
676 -extern(C) void _d_throw_exception(Object e) | |
677 +// called to throw object | |
678 +extern(C) | |
679 +void _d_throw_exception(Object e) | |
680 { | |
681 + //printf("throwing %p, rtti = %p\n", e, **cast(ClassRTTI***)e); | |
682 if (e !is null) | |
683 { | |
684 _d_exception* exc_struct = new _d_exception; | |
685 exc_struct.unwind_info.exception_class = *cast(ulong*)_d_exception_class.ptr; | |
686 exc_struct.exception_object = e; | |
687 _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info); | |
688 - console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); | |
689 + printf("Error: returned %d from raise exception.\n", ret); | |
690 + //console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); | |
691 } | |
692 abort(); | |
693 } | |
694 | |
695 -extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct) | |
696 +// called to resume unwinding | |
697 +extern(C) | |
698 +void _d_eh_resume_unwind(void* exception_struct) | |
699 { | |
700 - _Unwind_Resume(&exception_struct.unwind_info); | |
701 + _Unwind_Resume(&(cast(_d_exception*)exception_struct).unwind_info); | |
702 } |