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

Paul J. Lucas paul at lucasmail.org
Tue Mar 20 19:38:08 PDT 2012


To recap, on Mar 14, 2012, I wrote:

> My project has a C++ library that I want to allow the user to use via some programming language to be JIT'd to call functions in said library.  For the sake of simplicity, assume the library has classes like:
> 
> 	class item_iterator {
> 	public:
> 	  virtual ~item_iterator();
> 	  virtual bool next( item *result ) = 0;
> 	};
> 
> I'm aware that LLVM doesn't know anything about C++ and that one way to call C++ functions is to wrap them in C thunks:
> 
> 	extern "C" bool thunk_iterator_M_next( void *v_that, void *v_result ) {
> 	  item_iterator *const that = static_cast<item_iterator*>( v_that );
> 	  item *const result = static_cast<item*>( v_result );
> 	  return that->next( result );
> 	}
> 
> 	extern "C" void thunk_iterator_M_delete( void *v_that ) {
> 	  item_iterator *const that = static_cast<item_iterator*>( v_that );
> 	  that->~item_iterator();
> 	}

Thanks to a previous answer, I now have everything working.  My next problem is to deal with exceptions that may be thrown from the C++ functions that are called via the thunks, e.g., what if that->next() throws an exception?  I need to be able to catch it, call a clean-up function, and rethrow the exception so the code calling the JIT'd code can deal with the exception.

I've read the docs on LLVM exceptions, but I don't see any examples.  A little help?

One thought might be to try to handle all the C++ exception code in the thunks.  The JIT'd code would create/maintain a simple array-of-structs like:

	struct dtor_pair {
	  void (*dtor_fn)(void*);
	  void *that;
	};
	dtor_pair dtor_pairs[10];

that contain a pointer to the thunk for a destructor and a pointer to the object to be destructed.

As the JIT'd code creates objects on the stack, it populates the dtor_pairs array.  This array could then be passed to every thunk:

	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;
	  }
	}

where run_dtors() would run through the array backwards calling the destructor functions in reverse order of construction.

Would this work?  If so, then I wouldn't have to mess with handing C++ exceptions from LLVM.  But is there a better "LLVM way" to do what I want?

- Paul





More information about the llvm-dev mailing list