Mercurial > projects > ldc
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); |