2012-10-31 23 views
12

我创建了一个基本函数Foo1,通过调用调用另一个Bar2。在开卷清理基本块的第一个指令必须是着陆区:在llvm上写一个简单的清理着陆台

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参数之间放代码为当前的堆栈对象。 Bar2可能会抛出通过调用自己抛出的C++函数(或重新抛出现有的异常)

回答

6

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

基本上,你通过设置个性开始表现为在C++:

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

然后,您可以创建具有个性landingpad并定义其类型:

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

最后一个附加的例子,有解释等,可on the blog post that introduced the new exception handling mechanism

+0

该例子ExceptionDemo很有趣,我不知道它,谢谢。引起我注意的一点是,llvm :: Function是为'ourPersonality'创建的,并在着陆板中使用,但是我没有在任何地方看到从该函数到实际'ourPersonality'函数地址的映射。如果映射为空,'getFunction'默认情况下是否执行符号解析?我找不到任何有关'功能'的文档 – lurscher

+0

@lurscher我不知道;我怀疑它和它的定义中定义的_Unwind_Reason_Code有关(它出现在同一个文件中),但我对整个区域恐怕不够熟悉。 – Oak