comparison tango/lib/compiler/llvmdc/eh.d @ 318:8e570dbe4087 trunk

[svn r339] Add cleanup handling when within an action chain and some more documentation to the eh personality function.
author ChristianK
date Fri, 04 Jul 2008 09:00:49 +0200
parents 8d98e42ece93
children e9c93739bc4c
comparison
equal deleted inserted replaced
317:1a2777460bd5 318:8e570dbe4087
192 // if there's no actionOffset and no landingpad, continue unwinding 192 // if there's no actionOffset and no landingpad, continue unwinding
193 if(!action_offset && !landing_pad) 193 if(!action_offset && !landing_pad)
194 return _Unwind_Reason_Code.CONTINUE_UNWIND; 194 return _Unwind_Reason_Code.CONTINUE_UNWIND;
195 195
196 // if there's no action offset but a landing pad, this is a cleanup handler 196 // if there's no action offset but a landing pad, this is a cleanup handler
197 else if(!action_offset && landing_pad) { 197 else if(!action_offset && landing_pad)
198 // but only if we're asked to! 198 return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
199 if(!(actions & _Unwind_Action.CLEANUP_PHASE))
200 return _Unwind_Reason_Code.CONTINUE_UNWIND;
201
202 debug(EH_personality) printf("Calling cleanup routine...\n");
203
204 _Unwind_SetGR(context, 0, cast(ulong)exception_struct);
205 _Unwind_SetIP(context, landing_pad);
206 return _Unwind_Reason_Code.INSTALL_CONTEXT;
207 }
208 199
209 /* 200 /*
210 walk action table chain, comparing classinfos using _d_isbaseof 201 walk action table chain, comparing classinfos using _d_isbaseof
211 */ 202 */
212 ubyte* action_walker = action_table + action_offset - 1; 203 ubyte* action_walker = action_table + action_offset - 1;
217 // it is intentional that we not modify action_walker here 208 // it is intentional that we not modify action_walker here
218 // next_action_offset is from current action_walker position 209 // next_action_offset is from current action_walker position
219 get_sleb128(action_walker, next_action_offset); 210 get_sleb128(action_walker, next_action_offset);
220 211
221 // negative are 'filters' which we don't use 212 // negative are 'filters' which we don't use
222 assert(ti_offset >= 0); 213 assert(ti_offset >= 0 && "Filter actions are unsupported");
223 214
224 //TODO: Implement cleanups 215 // zero means cleanup, which we require to be the last action
225 assert(ti_offset != 0); 216 if(ti_offset == 0) {
217 assert(next_action_offset == 0 && "Cleanup action must be last in chain");
218 return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
219 }
226 220
227 // get classinfo for action and check if the one in the 221 // get classinfo for action and check if the one in the
228 // exception structure is a base 222 // exception structure is a base
229 ClassInfo catch_ci = classinfo_table[-ti_offset]; 223 ClassInfo catch_ci = classinfo_table[-ti_offset];
230 debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr); 224 debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr);
231 if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci)) 225 if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci))
232 return _d_eh_success(actions, ti_offset, landing_pad, exception_struct, context); 226 return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context);
233 227
234 // we've walked through all actions and found nothing... 228 // we've walked through all actions and found nothing...
235 if(next_action_offset == 0) 229 if(next_action_offset == 0)
236 return _Unwind_Reason_Code.CONTINUE_UNWIND; 230 return _Unwind_Reason_Code.CONTINUE_UNWIND;
237 else 231 else
239 } 233 }
240 234
241 assert(false); 235 assert(false);
242 } 236 }
243 237
244 private _Unwind_Reason_Code _d_eh_success(_Unwind_Action actions, ptrdiff_t switchval, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context) 238 // These are the register numbers for SetGR that
239 // llvm's eh.exception and eh.selector intrinsics
240 // will pick up.
241 // Found by trial-and-error and probably platform dependent!
242 private int eh_exception_regno = 0;
243 private int eh_selector_regno = 2;
244
245 private _Unwind_Reason_Code _d_eh_install_catch_context(_Unwind_Action actions, ptrdiff_t switchval, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
245 { 246 {
246 debug(EH_personality) printf("Found catch clause!\n"); 247 debug(EH_personality) printf("Found catch clause!\n");
247 248
248 if(actions & _Unwind_Action.SEARCH_PHASE) 249 if(actions & _Unwind_Action.SEARCH_PHASE)
249 return _Unwind_Reason_Code.HANDLER_FOUND; 250 return _Unwind_Reason_Code.HANDLER_FOUND;
251
250 else if(actions & _Unwind_Action.HANDLER_PHASE) 252 else if(actions & _Unwind_Action.HANDLER_PHASE)
251 { 253 {
252 //TODO: Set sensible value for eh_ptr 254 _Unwind_SetGR(context, eh_exception_regno, cast(ulong)cast(void*)(exception_struct.exception_object));
253 _Unwind_SetGR(context, 0, cast(ulong)cast(void*)(exception_struct.exception_object)); 255 _Unwind_SetGR(context, eh_selector_regno, switchval);
254 _Unwind_SetGR(context, 2, switchval);
255 _Unwind_SetIP(context, landing_pad); 256 _Unwind_SetIP(context, landing_pad);
256 return _Unwind_Reason_Code.INSTALL_CONTEXT; 257 return _Unwind_Reason_Code.INSTALL_CONTEXT;
257 } 258 }
258 259
259 assert(false); 260 assert(false);
261 }
262
263 private _Unwind_Reason_Code _d_eh_install_finally_context(_Unwind_Action actions, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
264 {
265 // if we're merely in search phase, continue
266 if(actions & _Unwind_Action.SEARCH_PHASE)
267 return _Unwind_Reason_Code.CONTINUE_UNWIND;
268
269 debug(EH_personality) printf("Calling cleanup routine...\n");
270
271 _Unwind_SetGR(context, eh_exception_regno, cast(ulong)exception_struct);
272 _Unwind_SetIP(context, landing_pad);
273 return _Unwind_Reason_Code.INSTALL_CONTEXT;
260 } 274 }
261 275
262 private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci) 276 private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)
263 { 277 {
264 ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context); 278 ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);