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

Paul J. Lucas paul at lucasmail.org
Thu Mar 22 11:40:51 PDT 2012


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:

	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