diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 101 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 27 |
3 files changed, 112 insertions, 47 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 420e275becd..85d02bb2ca5 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -31,9 +31,21 @@ static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) { 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 *getThrowFn(CodeGenFunction &CGF) { } 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 *getReThrowFn(CodeGenFunction &CGF) { } 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 *getBeginCatchFn(CodeGenFunction &CGF) { } 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 @@ static llvm::Constant *getUnwindResumeOrRethrowFn(CodeGenFunction &CGF) { 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 @@ static void CopyObject(CodeGenFunction &CGF, const Expr *E, llvm::Value *N) { 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 @@ static void CopyObject(CodeGenFunction &CGF, const Expr *E, llvm::Value *N) { 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 @@ static void CopyObject(CodeGenFunction &CGF, QualType ObjectType, 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 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 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 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 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 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 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 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 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 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { setInvokeDest(PrevLandingPad); -#if 0 EmitBlock(FinallyBlock); if (Info.SwitchBlock) @@ -423,7 +465,6 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { // Branch around the rethrow code. EmitBranch(FinallyEnd); -#endif EmitBlock(FinallyRethrow); Builder.CreateCall(getUnwindResumeOrRethrowFn(*this), diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 6e0a77ca1b0..1e952f9a7db 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -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) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 7f3204587a9..a7d28e544ea 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -109,7 +109,8 @@ public: /// 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 @@ public: /// 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 @@ public: 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 @@ public: } ~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 @@ private: /// 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. |