私はここでの経験がほとんどないことを認めますが、例外のデモ コードの例を見たことがありますか? あなたが見つけたいと思っている種類のシーケンスが正確に含まれているようです。
基本的に、パーソナリティが 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);
最後に、追加の例と説明が、新しい例外処理メカニズムを紹介したブログ投稿で利用できます。