12

Foo1呼び出しを介して別の関数を呼び出す基本的な関数を作成しましたBar2。アンワインド クリーンアップ基本ブロックの最初の命令は、ランディング パッドでなければなりません。

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 に答える