comparison runtime/internal/eh.d @ 1584:f4c56ed32238

Fixed issue in exception runtime with recent LLVM revisions, with this in place EH seems to work properly on x86-64. These fixes need to be merged into tango trunk still!
author tomas@localhost.localdomain
date Wed, 21 Oct 2009 05:46:56 +0200
parents 4a5eea0334e5
children 761bf823e59e
comparison
equal deleted inserted replaced
1583:593f99fddd2f 1584:f4c56ed32238
6 6
7 import util.console; 7 import util.console;
8 import ldc.cstdarg; 8 import ldc.cstdarg;
9 9
10 // debug = EH_personality; 10 // debug = EH_personality;
11 // debug = EH_personality_verbose;
11 12
12 // current EH implementation works on x86 13 // current EH implementation works on x86
13 // if it has a working unwind runtime 14 // if it has a working unwind runtime
14 version(X86) { 15 version(X86) {
15 version(linux) version=X86_UNWIND; 16 version(linux) version=X86_UNWIND;
34 } 35 }
35 36
36 // libunwind headers 37 // libunwind headers
37 extern(C) 38 extern(C)
38 { 39 {
39 enum _Unwind_Reason_Code 40 enum _Unwind_Reason_Code : int
40 { 41 {
41 NO_REASON = 0, 42 NO_REASON = 0,
42 FOREIGN_EXCEPTION_CAUGHT = 1, 43 FOREIGN_EXCEPTION_CAUGHT = 1,
43 FATAL_PHASE2_ERROR = 2, 44 FATAL_PHASE2_ERROR = 2,
44 FATAL_PHASE1_ERROR = 3, 45 FATAL_PHASE1_ERROR = 3,
47 HANDLER_FOUND = 6, 48 HANDLER_FOUND = 6,
48 INSTALL_CONTEXT = 7, 49 INSTALL_CONTEXT = 7,
49 CONTINUE_UNWIND = 8 50 CONTINUE_UNWIND = 8
50 } 51 }
51 52
52 enum _Unwind_Action 53 enum _Unwind_Action : int
53 { 54 {
54 SEARCH_PHASE = 1, 55 SEARCH_PHASE = 1,
55 CLEANUP_PHASE = 2, 56 CLEANUP_PHASE = 2,
56 HANDLER_PHASE = 3, 57 HANDLER_PHASE = 3,
57 FORCE_UNWIND = 4 58 FORCE_UNWIND = 4
61 62
62 alias void function(_Unwind_Reason_Code, _Unwind_Exception*) _Unwind_Exception_Cleanup_Fn; 63 alias void function(_Unwind_Reason_Code, _Unwind_Exception*) _Unwind_Exception_Cleanup_Fn;
63 64
64 struct _Unwind_Exception 65 struct _Unwind_Exception
65 { 66 {
66 char[8] exception_class; 67 ulong exception_class;
67 _Unwind_Exception_Cleanup_Fn exception_cleanup; 68 _Unwind_Exception_Cleanup_Fn exception_cleanup;
68 ptrdiff_t private_1; 69 ptrdiff_t private_1;
69 ptrdiff_t private_2; 70 ptrdiff_t private_2;
70 } 71 }
71 72
205 206
206 // the personality routine gets called by the unwind handler and is responsible for 207 // the personality routine gets called by the unwind handler and is responsible for
207 // reading the EH tables and deciding what to do 208 // reading the EH tables and deciding what to do
208 extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context) 209 extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context)
209 { 210 {
211 debug(EH_personality_verbose) printf("entering personality function. context: %p\n", context);
210 // check ver: the C++ Itanium ABI only allows ver == 1 212 // check ver: the C++ Itanium ABI only allows ver == 1
211 if(ver != 1) 213 if(ver != 1)
212 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; 214 return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
213 215
214 // check exceptionClass 216 // check exceptionClass
222 // Note: classinfo_table points past the end of the table 224 // Note: classinfo_table points past the end of the table
223 ubyte* callsite_table; 225 ubyte* callsite_table;
224 ubyte* action_table; 226 ubyte* action_table;
225 ClassInfo* classinfo_table; 227 ClassInfo* classinfo_table;
226 _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table); 228 _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table);
227 229 if (callsite_table is null)
230 return _Unwind_Reason_Code.CONTINUE_UNWIND;
228 231
229 /* 232 /*
230 find landing pad and action table index belonging to ip by walking 233 find landing pad and action table index belonging to ip by walking
231 the callsite_table 234 the callsite_table
232 */ 235 */
375 } 378 }
376 379
377 private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci) 380 private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)
378 { 381 {
379 ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); 382 ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
383 if (data is null)
384 {
385 //printf("language specific data was null\n");
386 callsite = null;
387 action = null;
388 ci = null;
389 return;
390 }
380 391
381 //TODO: Do proper DWARF reading here 392 //TODO: Do proper DWARF reading here
382 if(*data++ != 0xff) 393 if(*data++ != 0xff)
383 fatalerror("DWARF header has unexpected format 1"); 394 fatalerror("DWARF header has unexpected format 1");
384 395
403 extern(C) void _d_throw_exception(Object e) 414 extern(C) void _d_throw_exception(Object e)
404 { 415 {
405 if (e !is null) 416 if (e !is null)
406 { 417 {
407 _d_exception* exc_struct = new _d_exception; 418 _d_exception* exc_struct = new _d_exception;
408 exc_struct.unwind_info.exception_class[] = _d_exception_class; 419 exc_struct.unwind_info.exception_class = *cast(ulong*)_d_exception_class.ptr;
409 exc_struct.exception_object = e; 420 exc_struct.exception_object = e;
410 _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info); 421 _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info);
411 console("_Unwind_RaiseException failed with reason code: ")(ret)("\n"); 422 console("_Unwind_RaiseException failed with reason code: ")(ret)("\n");
412 } 423 }
413 abort(); 424 abort();