2012-10-31 21 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のパラメータの間に置くために必要なものを正直見当がつかない現在のFoo1スタックオブジェクトのコードを作成します。 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); 

これは、私は信じています。今、あなたは例外自体得ることができます。これらのコードセグメントが取られているからExceptionDemo.cppファイル、

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

を、充実のシーケンスが含まれています。あなたのクリーンアップコードを - - 具体的には、特定のブロックの中にキャッチされた例外と分岐の種類のルートをチェックする方法を示し、それが何かマッチしたとき:

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は興味深いですが、私はそれについて知りませんでした、ありがとう。私の注目を集めているのは、 'ourPersonality'のためにllvm :: Functionが作成され、ランディングパッドで使われているのですが、この関数から実際の' ourPersonality'関数のアドレスへのマッピングはどこにもありません。マッピングが空の場合、 'getFunction'はデフォルトでシンボル解決をしていますか?私はその「機能」のドキュメントを見つけることができません – lurscher

+0

@lurscher私には分かりません。私は、それは(同じファイルに表示される)その定義で定義された '_Unwind_Reason_Code'と何か関係があると思うが、私はその全体の領域に十分に精通していない。恐れがある。 – Oak

関連する問題