More exception handling improvements... WIP.

Highlights include:

  Add a helper to generate __cxa_free_exception and _ZSt9terminatev.
  Add a region to handle EH object deallocation for ctor failures for throw.
  Add a terminate handler for __cxa_end_catch.
  A framework for adding cleanup actions for the exceptional edges only.

llvm-svn: 90305
This commit is contained in:
Mike Stump
2009-12-02 07:41:41 +00:00
parent b9878ee6b6
commit 33270211a0
3 changed files with 112 additions and 47 deletions

View File

@@ -606,8 +606,10 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
}
void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
llvm::BasicBlock *CleanupExitBlock) {
CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock));
llvm::BasicBlock *CleanupExitBlock,
bool EHOnly) {
CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock,
EHOnly));
}
void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
@@ -629,6 +631,8 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
std::vector<llvm::BranchInst *> BranchFixups;
std::swap(BranchFixups, CE.BranchFixups);
bool EHOnly = CE.EHOnly;
CleanupEntries.pop_back();
// Check if any branch fixups pointed to the scope we just popped. If so,
@@ -663,8 +667,9 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
Builder.SetInsertPoint(SwitchBlock);
llvm::Value *DestCodePtr = CreateTempAlloca(llvm::Type::getInt32Ty(VMContext),
"cleanup.dst");
llvm::Value *DestCodePtr
= CreateTempAlloca(llvm::Type::getInt32Ty(VMContext),
"cleanup.dst");
llvm::Value *DestCode = Builder.CreateLoad(DestCodePtr, "tmp");
// Create a switch instruction to determine where to jump next.
@@ -710,15 +715,16 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
new llvm::StoreInst(ID, DestCodePtr, BI);
} else {
// We need to jump through another cleanup block. Create a pad block
// with a branch instruction that jumps to the final destination and
// add it as a branch fixup to the current cleanup scope.
// with a branch instruction that jumps to the final destination and add
// it as a branch fixup to the current cleanup scope.
// Create the pad block.
llvm::BasicBlock *CleanupPad = createBasicBlock("cleanup.pad", CurFn);
// Create a unique case ID.
llvm::ConstantInt *ID = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
SI->getNumSuccessors());
llvm::ConstantInt *ID
= llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
SI->getNumSuccessors());
// Store the jump destination before the branch instruction.
new llvm::StoreInst(ID, DestCodePtr, BI);
@@ -744,12 +750,19 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
BlockScopes.erase(Blocks[i]);
}
return CleanupBlockInfo(CleanupEntryBlock, SwitchBlock, EndBlock);
return CleanupBlockInfo(CleanupEntryBlock, SwitchBlock, EndBlock, EHOnly);
}
void CodeGenFunction::EmitCleanupBlock() {
CleanupBlockInfo Info = PopCleanupBlock();
if (Info.EHOnly) {
// FIXME: Add this to the exceptional edge
if (Info.CleanupBlock->getNumUses() == 0)
delete Info.CleanupBlock;
return;
}
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
if (CurBB && !CurBB->getTerminator() &&
Info.CleanupBlock->getNumUses() == 0) {