I have created a basic function Foo1
that calls another one Bar2
through invoke. The first instruction in the unwind cleanup basic block must be the landing pad:
void bar2()
{
throw;
}
llvm::Function* Bar2Fn = llvm::Function::Create( voidSig , &bar2);
engine->addGlobalMapping( Bar2Fn, (void*)&bar2 );
llvm::InvokeInst* inv = builder.CreateInvoke( Bar2Fn , continueBlock, unwindBlock, llvmArgValues , "invoke");
builder.CreateBr(continueBlock);
builder.SetInsertPoint(unwindBlock);
llvm::LandingPadInst* landPadInst = builder.CreateLandingPad(...);
//add some cleanup code? where??
I have honestly no idea what i need to put between the parameters of CreateLandingPad
in order to get a basic landing pad that invokes a custom clean up code for the current Foo1
stack objects. Bar2
might throw by calling c++ functions that themselves throw (or rethrow an existing exception)
I admit I have little experience here, but have you seen the exception demo code example? It seems to contain exactly the kind of sequence you are hoping to find.
Basically, you start by setting up the personality to behave as in C++:
llvm::Function *personality = module.getFunction("__gxx_personality_v0");
You then create the landingpad with that personality and define its type:
llvm::LandingPadInst *caughtResult =
builder.CreateLandingPad(ourCaughtResultType,
personality,
numExceptionsToCatch,
"landingPad");
Setting up the types to catch:
for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
// Set up type infos to be caught
caughtResult->addClause(module.getGlobalVariable(
ourTypeInfoNames[exceptionTypesToCatch[i]]));
}
And signalling it's a cleanup handler:
caughtResult->setCleanup(true);
This is it, I believe; now you can get the exception itself:
llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
The ExceptionDemo.cpp file, from which these code segments are taken, contains a fuller sequence; specifically, it shows how to check the type root of the caught exception and branch into a specific block - your cleanup code - when it matches something:
llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
// FIXME: Redundant storage which, beyond utilizing value of
// caughtResultStore for unwindException storage, may be alleviated
// altogether with a block rearrangement
builder.CreateStore(caughtResult, caughtResultStorage);
builder.CreateStore(unwindException, exceptionStorage);
builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
// Retrieve exception_class member from thrown exception
// (_Unwind_Exception instance). This member tells us whether or not
// the exception is foreign.
llvm::Value *unwindExceptionClass =
builder.CreateLoad(builder.CreateStructGEP(
builder.CreatePointerCast(unwindException,
ourUnwindExceptionType->getPointerTo()),
0));
// Branch to the externalExceptionBlock if the exception is foreign or
// to a catch router if not. Either way the finally block will be run.
builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass,
llvm::ConstantInt::get(builder.getInt64Ty(),
ourBaseExceptionClass)),
exceptionRouteBlock,
externalExceptionBlock);
Finally, an additional example, along with explanations, is available on the blog post that introduced the new exception handling mechanism.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With