Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

writing a simple cleanup landing pad on llvm

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)

like image 779
lurscher Avatar asked Oct 31 '12 19:10

lurscher


1 Answers

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.

like image 181
Oak Avatar answered Oct 26 '22 22:10

Oak