[LLVMdev] Catching C++ exceptions, cleaning up, rethrowing

Bill Wendling wendling at apple.com
Thu Mar 22 17:29:51 PDT 2012


On Mar 22, 2012, at 11:40 AM, Paul J. Lucas <paul at lucasmail.org> wrote:

> On Mar 22, 2012, at 12:28 AM, Bill Wendling wrote:
> 
>> On Mar 20, 2012, at 7:38 PM, Paul J. Lucas wrote:
>> 
>>> I've read the docs on LLVM exceptions, but I don't see any examples.  A little help?
>> 
>> I don't think this has anything to do with LLVM's IR-level exception system. It sounds to me like you just need a way to handle C++ exceptions inside of the C++ code and then rethrow so that the JIT's caller can do its thing. (Right?)
> 
> Right.  The call sequence is:
> 
> 	my_lib(1) -> JIT_code -> C_thunk -> my_lib(2)
> 
> The JIT code creates Functions that create C++ objects on their stacks (by using alloca instructions then calling a C thunk that calls the C++ object's constructor via placement new).  If an exception is thrown in my_lib(2), then somewhere between there and when the stack unwinds to my_lib(1), the C++ objects that were created on the stack must have their destructors called (also via C thunks).  Hence, some code somewhere between my_lib(1) and C_thunk has to catch all exceptions, call the destructors, and rethrow the exceptions.
> 
>> You could move the C++ code into a C++ function that catches all exceptions. The C functions you provide would call the small bit of C++ code that would then execute the "real" functionality. You would have to wrap/unwrap the variables, of course. (There are examples of wrapping/unwrapping of variables in LLVM's source tree.) That way you will get to use C++'s exception handling system instead of creating your own, which is a huge massive undertaking full of pitfalls. When you rethrow the exception, it will propagate past the C function to the code calling the JIT'ed code.
> 
> Unfortunately, I'm not following.  How is having the code that catches all exceptions in a separate function different from what I proposed (putting the try/catch in the thunks)?  (Ideally, I want to minimize layers of function calls.)  Again for reference:
> 
No reason. But if you have the 'try{}catch(...){}', then it should run the d'tors for you. There's no reason for you to have a "run_dtors" function there.

-bw

> 	extern "C" bool thunk_iterator_M_next( void *v_that, void *v_result,
> 	                                       dtor_pairs *dtors ) {
> 	  try {
> 	    item_iterator *const that = static_cast<item_iterator*>( v_that );
> 	    item *const result = static_cast<item*>( v_result );
> 	    return that->next( result );
> 	  }
> 	  catch ( ... ) {
> 	    run_dtors( dtors );
> 	    throw;
> 	  }
> 	}
> 
> - Paul
> 




More information about the llvm-dev mailing list