12

我创建了一个基本函数Foo1,它通过调用调用另一个函数Bar2。unwind cleanup 基本块中的第一条指令必须是着陆台:

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??

老实说,我不知道我需要在参数之间放置什么才能获得一个基本的着陆台,该着陆台调用当前堆栈对象CreateLandingPad的自定义清理代码。可能会通过调用自己抛出的 c++ 函数来抛出(或重新抛出现有异常)Foo1Bar2

4

1 回答 1

7

我承认我在这里没有什么经验,但是您看过异常演示代码示例吗?它似乎包含您希望找到的那种序列。

基本上,您首先将个性设置为在 C++ 中的行为:

llvm::Function *personality = module.getFunction("__gxx_personality_v0");

然后,您创建具有该个性的着陆板并定义其类型:

llvm::LandingPadInst *caughtResult = 
  builder.CreateLandingPad(ourCaughtResultType,
                           personality,
                           numExceptionsToCatch,
                           "landingPad");

设置要捕获的类型:

for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
  // Set up type infos to be caught
  caughtResult->addClause(module.getGlobalVariable(
                          ourTypeInfoNames[exceptionTypesToCatch[i]]));
}

并表示它是一个清理处理程序:

caughtResult->setCleanup(true);

就是这样,我相信;现在你可以得到异常本身:

llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);

从中获取这些代码段的ExceptionDemo.cpp文件包含更完整的序列;具体来说,它展示了如何检查捕获的异常的类型根,并在匹配某些内容时分支到特定块 - 您的清理代码:

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

最后,在介绍新异常处理机制的博客文章中提供了一个附加示例以及说明。

于 2012-11-06T15:00:48.907 回答