2012-10-31 25 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