[cfe-commits] r90305 - in /cfe/trunk/lib/CodeGen: CGException.cpp CodeGenFunction.cpp CodeGenFunction.h
Mike Stump
mrs at apple.com
Tue Dec 1 23:41:42 PST 2009
Author: mrs
Date: Wed Dec 2 01:41:41 2009
New Revision: 90305
URL: http://llvm.org/viewvc/llvm-project?rev=90305&view=rev
Log:
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.
Modified:
cfe/trunk/lib/CodeGen/CGException.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=90305&r1=90304&r2=90305&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Wed Dec 2 01:41:41 2009
@@ -31,9 +31,21 @@
return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
}
+static llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) {
+ // void __cxa_free_exception(void *thrown_exception);
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
+ Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
+}
+
static llvm::Constant *getThrowFn(CodeGenFunction &CGF) {
- // void __cxa_throw (void *thrown_exception, std::type_info *tinfo,
- // void (*dest) (void *) );
+ // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
+ // void (*dest) (void *));
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
std::vector<const llvm::Type*> Args(3, Int8PtrTy);
@@ -46,7 +58,7 @@
}
static llvm::Constant *getReThrowFn(CodeGenFunction &CGF) {
- // void __cxa_rethrow ();
+ // void __cxa_rethrow();
const llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
@@ -55,7 +67,7 @@
}
static llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) {
- // void* __cxa_begin_catch ();
+ // void* __cxa_begin_catch();
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
std::vector<const llvm::Type*> Args(1, Int8PtrTy);
@@ -67,7 +79,7 @@
}
static llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) {
- // void __cxa_end_catch ();
+ // void __cxa_end_catch();
const llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
@@ -92,6 +104,15 @@
return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
}
+static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
+ // void __terminate();
+
+ const llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, "_ZSt9terminatev");
+}
+
// CopyObject - Utility to copy an object. Calls copy constructor as necessary.
// N is casted to the right type.
static void CopyObject(CodeGenFunction &CGF, const Expr *E, llvm::Value *N) {
@@ -112,7 +133,19 @@
CGF.EmitAggExpr(E, This, false);
} else if (CXXConstructorDecl *CopyCtor
= RD->getCopyConstructor(CGF.getContext(), 0)) {
- // FIXME: region management
+ // All temporaries end before we call __cxa_throw
+ CodeGenFunction::CleanupScope TryScope(CGF);
+ {
+ // These actions are only on the exceptional edge.
+ CodeGenFunction::DelayedCleanupBlock Scope(CGF, true);
+
+ llvm::Constant *FreeExceptionFn = getFreeExceptionFn(CGF);
+ const llvm::Type *Int8PtrTy
+ = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ llvm::Value *ExceptionPtr = CGF.Builder.CreateBitCast(N, Int8PtrTy);
+ CGF.Builder.CreateCall(FreeExceptionFn, ExceptionPtr);
+ }
+
llvm::Value *Src = CGF.EmitLValue(E).getAddress();
// Stolen from EmitClassAggrMemberwiseCopy
@@ -129,9 +162,8 @@
CopyCtor->getType()->getAs<FunctionType>()->getResultType();
CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
Callee, CallArgs, CopyCtor);
- // FIXME: region management
} else
- CGF.ErrorUnsupported(E, "uncopyable object");
+ llvm::llvm_unreachable("uncopyable object");
}
}
@@ -154,7 +186,7 @@
CGF.EmitAggregateCopy(This, E, ObjectType);
} else if (CXXConstructorDecl *CopyCtor
= RD->getCopyConstructor(CGF.getContext(), 0)) {
- // FIXME: region management
+ // FIXME: region management, call terminate
llvm::Value *Src = E;
// Stolen from EmitClassAggrMemberwiseCopy
@@ -241,16 +273,12 @@
llvm::BasicBlock *PrevLandingPad = getInvokeDest();
llvm::BasicBlock *TryHandler = createBasicBlock("try.handler");
-#if 0
llvm::BasicBlock *FinallyBlock = createBasicBlock("finally");
-#endif
llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw");
llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end");
-#if 0
// Push an EH context entry, used for handling rethrows.
PushCleanupBlock(FinallyBlock);
-#endif
// Emit the statements in the try {} block
setInvokeDest(TryHandler);
@@ -306,6 +334,7 @@
llvm::Value *Selector
= Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
SelectorArgs.end(), "selector");
+ llvm::BasicBlock *TerminateHandler = 0;
for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
const CXXCatchStmt *C = S.getHandler(i);
VarDecl *CatchParam = C->getExceptionDecl();
@@ -375,13 +404,15 @@
EmitBlock(MatchEnd);
- // Unfortunately, we also have to generate another EH frame here
- // in case this throws.
- llvm::BasicBlock *MatchEndHandler =
- createBasicBlock("match.end.handler");
- llvm::BasicBlock *Cont = createBasicBlock("myinvoke.cont");
+ // Set up terminate handler
+ bool GenerateTerminate = false;
+ if (!TerminateHandler) {
+ TerminateHandler = createBasicBlock("terminate.handler");
+ GenerateTerminate = true;
+ }
+ llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
Builder.CreateInvoke(getEndCatchFn(*this),
- Cont, MatchEndHandler,
+ Cont, TerminateHandler,
Args.begin(), Args.begin());
EmitBlock(Cont);
@@ -390,19 +421,31 @@
if (Info.EndBlock)
EmitBlock(Info.EndBlock);
- EmitBlock(MatchEndHandler);
Exc = Builder.CreateCall(llvm_eh_exception, "exc");
- // We are required to emit this call to satisfy LLVM, even
- // though we don't use the result.
- Args.clear();
- Args.push_back(Exc);
- Args.push_back(Personality);
- Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- 0));
- Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
Builder.CreateStore(Exc, RethrowPtr);
EmitBranchThroughCleanup(FinallyRethrow);
+ if (GenerateTerminate) {
+ GenerateTerminate = false;
+ EmitBlock(TerminateHandler);
+ Exc = Builder.CreateCall(llvm_eh_exception, "exc");
+ // We are required to emit this call to satisfy LLVM, even
+ // though we don't use the result.
+ Args.clear();
+ Args.push_back(Exc);
+ Args.push_back(Personality);
+ Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
+ 0));
+ Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
+ llvm::CallInst *TerminateCall =
+ Builder.CreateCall(getTerminateFn(*this));
+ TerminateCall->setDoesNotReturn();
+ Builder.CreateUnreachable();
+
+ // Clear the insertion point to indicate we are in unreachable code.
+ Builder.ClearInsertionPoint();
+ }
+
if (Next)
EmitBlock(Next);
}
@@ -413,7 +456,6 @@
setInvokeDest(PrevLandingPad);
-#if 0
EmitBlock(FinallyBlock);
if (Info.SwitchBlock)
@@ -423,7 +465,6 @@
// Branch around the rethrow code.
EmitBranch(FinallyEnd);
-#endif
EmitBlock(FinallyRethrow);
Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=90305&r1=90304&r2=90305&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Dec 2 01:41:41 2009
@@ -606,8 +606,10 @@
}
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 @@
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 @@
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 @@
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 @@
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) {
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=90305&r1=90304&r2=90305&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Dec 2 01:41:41 2009
@@ -109,7 +109,8 @@
/// PushCleanupBlock - Push a new cleanup entry on the stack and set the
/// passed in block as the cleanup block.
void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
- llvm::BasicBlock *CleanupExitBlock = 0);
+ llvm::BasicBlock *CleanupExitBlock = 0,
+ bool EHOnly = false);
/// CleanupBlockInfo - A struct representing a popped cleanup block.
struct CleanupBlockInfo {
@@ -123,9 +124,13 @@
/// EndBlock - the default destination for the switch instruction.
llvm::BasicBlock *EndBlock;
+ /// EHOnly - True iff this cleanup should only be performed on the
+ /// exceptional edge.
+ bool EHOnly;
+
CleanupBlockInfo(llvm::BasicBlock *cb, llvm::BasicBlock *sb,
- llvm::BasicBlock *eb)
- : CleanupBlock(cb), SwitchBlock(sb), EndBlock(eb) {}
+ llvm::BasicBlock *eb, bool ehonly = false)
+ : CleanupBlock(cb), SwitchBlock(sb), EndBlock(eb), EHOnly(ehonly) {}
};
/// PopCleanupBlock - Will pop the cleanup entry on the stack, process all
@@ -141,11 +146,13 @@
llvm::BasicBlock *CurBB;
llvm::BasicBlock *CleanupEntryBB;
llvm::BasicBlock *CleanupExitBB;
+ bool EHOnly;
public:
- DelayedCleanupBlock(CodeGenFunction &cgf)
+ DelayedCleanupBlock(CodeGenFunction &cgf, bool ehonly = false)
: CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()),
- CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0) {
+ CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0),
+ EHOnly(ehonly) {
CGF.Builder.SetInsertPoint(CleanupEntryBB);
}
@@ -156,7 +163,7 @@
}
~DelayedCleanupBlock() {
- CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB);
+ CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB, EHOnly);
// FIXME: This is silly, move this into the builder.
if (CurBB)
CGF.Builder.SetInsertPoint(CurBB);
@@ -303,10 +310,14 @@
/// inserted into the current function yet.
std::vector<llvm::BranchInst *> BranchFixups;
+ /// EHOnly - Perform this only on the exceptional edge, not the main edge.
+ bool EHOnly;
+
explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock,
- llvm::BasicBlock *CleanupExitBlock)
+ llvm::BasicBlock *CleanupExitBlock, bool ehonly)
: CleanupEntryBlock(CleanupEntryBlock),
- CleanupExitBlock(CleanupExitBlock) {}
+ CleanupExitBlock(CleanupExitBlock),
+ EHOnly(ehonly) {}
};
/// CleanupEntries - Stack of cleanup entries.
More information about the cfe-commits
mailing list