Mercurial > projects > ldc
annotate tango-0.99.9.patch @ 1650:40bd4a0d4870
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.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 5c0cebff9be8 |
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 } |