diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 89 | ||||
-rw-r--r-- | lib/CodeGen/CGException.cpp | 52 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 55 |
5 files changed, 177 insertions, 37 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 923f1f8a14..14ee90d469 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -581,22 +581,39 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { if (const ConstantArrayType *Array = getContext().getAsConstantArrayType(Ty)) { - DelayedCleanupBlock Scope(*this); - QualType BaseElementTy = getContext().getBaseElementType(Array); - const llvm::Type *BasePtr = ConvertType(BaseElementTy); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *BaseAddrPtr = - Builder.CreateBitCast(DeclPtr, BasePtr); - EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); + { + DelayedCleanupBlock Scope(*this); + QualType BaseElementTy = getContext().getBaseElementType(Array); + const llvm::Type *BasePtr = ConvertType(BaseElementTy); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(DeclPtr, BasePtr); + EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); - // Make sure to jump to the exit block. - EmitBranch(Scope.getCleanupExitBlock()); + // Make sure to jump to the exit block. + EmitBranch(Scope.getCleanupExitBlock()); + } + if (Exceptions) { + EHCleanupBlock Cleanup(*this); + QualType BaseElementTy = getContext().getBaseElementType(Array); + const llvm::Type *BasePtr = ConvertType(BaseElementTy); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(DeclPtr, BasePtr); + EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); + } } else { - DelayedCleanupBlock Scope(*this); - EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr); - - // Make sure to jump to the exit block. - EmitBranch(Scope.getCleanupExitBlock()); + { + DelayedCleanupBlock Scope(*this); + EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr); + + // Make sure to jump to the exit block. + EmitBranch(Scope.getCleanupExitBlock()); + } + if (Exceptions) { + EHCleanupBlock Cleanup(*this); + EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr); + } } } } @@ -608,8 +625,6 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { llvm::Constant* F = CGM.GetAddrOfFunction(FD); assert(F && "Could not find function!"); - DelayedCleanupBlock scope(*this); - const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD); // In some cases, the type of the function argument will be different from @@ -619,20 +634,40 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { // // To fix this we insert a bitcast here. QualType ArgTy = Info.arg_begin()->type; - DeclPtr = Builder.CreateBitCast(DeclPtr, ConvertType(ArgTy)); - - CallArgList Args; - Args.push_back(std::make_pair(RValue::get(DeclPtr), - getContext().getPointerType(D.getType()))); - - EmitCall(Info, F, Args); + { + DelayedCleanupBlock scope(*this); + + CallArgList Args; + Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr, + ConvertType(ArgTy))), + getContext().getPointerType(D.getType()))); + EmitCall(Info, F, Args); + } + if (Exceptions) { + EHCleanupBlock Cleanup(*this); + + CallArgList Args; + Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr, + ConvertType(ArgTy))), + getContext().getPointerType(D.getType()))); + EmitCall(Info, F, Args); + } } if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) { - DelayedCleanupBlock scope(*this); - llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); - V = Builder.CreateLoad(V); - BuildBlockRelease(V); + { + DelayedCleanupBlock scope(*this); + llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); + V = Builder.CreateLoad(V); + BuildBlockRelease(V); + } + // FIXME: Turn this on and audit the codegen + if (0 && Exceptions) { + EHCleanupBlock Cleanup(*this); + llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); + V = Builder.CreateLoad(V); + BuildBlockRelease(V); + } } } diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 11cf9cedb0..bcb59f5f97 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -650,3 +650,55 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { EmitBlock(FinallyEnd); } + +CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() { + llvm::BasicBlock *Cont1 = CGF.createBasicBlock("cont"); + CGF.EmitBranch(Cont1); + CGF.setInvokeDest(PreviousInvokeDest); + + + CGF.EmitBlock(CleanupHandler); + + llvm::Constant *Personality = + CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty + (CGF.VMContext), + true), + "__gxx_personality_v0"); + Personality = llvm::ConstantExpr::getBitCast(Personality, CGF.PtrToInt8Ty); + llvm::Value *llvm_eh_exception = + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); + llvm::Value *llvm_eh_selector = + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); + + llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); + const llvm::IntegerType *Int8Ty; + const llvm::PointerType *PtrToInt8Ty; + Int8Ty = llvm::Type::getInt8Ty(CGF.VMContext); + // C string type. Used in lots of places. + PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); + llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty); + llvm::SmallVector<llvm::Value*, 8> Args; + Args.clear(); + Args.push_back(Exc); + Args.push_back(Personality); + Args.push_back(Null); + CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); + + CGF.EmitBlock(CleanupEntryBB); + + CGF.EmitBlock(Cont1); + + if (CGF.getInvokeDest()) { + llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); + CGF.Builder.CreateInvoke(getUnwindResumeOrRethrowFn(CGF), Cont, + CGF.getInvokeDest(), Exc); + CGF.EmitBlock(Cont); + } else + CGF.Builder.CreateCall(getUnwindResumeOrRethrowFn(CGF), Exc); + + CGF.Builder.CreateUnreachable(); + + CGF.EmitBlock(Cont); + if (CGF.Exceptions) + CGF.setInvokeDest(CleanupHandler); +} diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 87f53e876b..fde944ffcd 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -137,8 +137,16 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, const CXXDestructorDecl *Dtor = ClassDecl->getDestructor(getContext()); - DelayedCleanupBlock scope(*this); - EmitCXXDestructorCall(Dtor, Dtor_Complete, Val.getAggregateAddr()); + { + DelayedCleanupBlock scope(*this); + EmitCXXDestructorCall(Dtor, Dtor_Complete, + Val.getAggregateAddr()); + } + if (Exceptions) { + EHCleanupBlock Cleanup(*this); + EmitCXXDestructorCall(Dtor, Dtor_Complete, + Val.getAggregateAddr()); + } } } } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 4b32999020..adfd75b42a 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -34,6 +34,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) ConditionalBranchLevel(0) { LLVMIntTy = ConvertType(getContext().IntTy); LLVMPointerWidth = Target.getPointerWidth(0); + Exceptions = getContext().getLangOptions().Exceptions; } ASTContext &CodeGenFunction::getContext() const { @@ -625,9 +626,10 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) { void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock, llvm::BasicBlock *CleanupExitBlock, + llvm::BasicBlock *PreviousInvokeDest, bool EHOnly) { CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock, - EHOnly)); + PreviousInvokeDest, EHOnly)); } void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) { @@ -651,6 +653,8 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { bool EHOnly = CE.EHOnly; + setInvokeDest(CE.PreviousInvokeDest); + CleanupEntries.pop_back(); // Check if any branch fixups pointed to the scope we just popped. If so, diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 854eb53ec2..5e23e2646d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -107,6 +107,7 @@ public: const llvm::Type *LLVMIntTy; uint32_t LLVMPointerWidth; + bool Exceptions; public: /// ObjCEHValueStack - Stack of Objective-C exception values, used for /// rethrows. @@ -115,8 +116,12 @@ 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, + llvm::BasicBlock *PreviousInvokeDest, bool EHOnly = false); + void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock) { + PushCleanupBlock(CleanupEntryBlock, 0, getInvokeDest(), false); + } /// CleanupBlockInfo - A struct representing a popped cleanup block. struct CleanupBlockInfo { @@ -139,9 +144,35 @@ public: : CleanupBlock(cb), SwitchBlock(sb), EndBlock(eb), EHOnly(ehonly) {} }; + /// EHCleanupBlock - RAII object that will create a cleanup block for the + /// exceptional edge and set the insert point to that block. When destroyed, + /// it creates the cleanup edge and sets the insert point to the previous + /// block. + class EHCleanupBlock { + CodeGenFunction& CGF; + llvm::BasicBlock *Cont; + llvm::BasicBlock *CleanupHandler; + llvm::BasicBlock *CleanupEntryBB; + llvm::BasicBlock *PreviousInvokeDest; + public: + EHCleanupBlock(CodeGenFunction &cgf) + : CGF(cgf), Cont(CGF.createBasicBlock("cont")), + CleanupHandler(CGF.createBasicBlock("ehcleanup")), + CleanupEntryBB(CGF.createBasicBlock("ehcleanup.rest")), + PreviousInvokeDest(CGF.getInvokeDest()) { + CGF.EmitBranch(Cont); + CGF.Builder.SetInsertPoint(CleanupEntryBB); + + // FIXME: set up terminate handler here + // CGF.setInvokeDest(TerminateHandler); + } + ~EHCleanupBlock(); + }; + /// PopCleanupBlock - Will pop the cleanup entry on the stack, process all /// branch fixups and return a block info struct with the switch block and end - /// block. + /// block. This will also reset the invoke handler to the previous value + /// from when the cleanup block was created. CleanupBlockInfo PopCleanupBlock(); /// DelayedCleanupBlock - RAII object that will create a cleanup block and set @@ -152,13 +183,15 @@ public: llvm::BasicBlock *CurBB; llvm::BasicBlock *CleanupEntryBB; llvm::BasicBlock *CleanupExitBB; + llvm::BasicBlock *CurInvokeDest; bool EHOnly; public: DelayedCleanupBlock(CodeGenFunction &cgf, bool ehonly = false) : CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()), - CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0), - EHOnly(ehonly) { + CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0), + CurInvokeDest(CGF.getInvokeDest()), + EHOnly(ehonly) { CGF.Builder.SetInsertPoint(CleanupEntryBB); } @@ -169,7 +202,8 @@ public: } ~DelayedCleanupBlock() { - CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB, EHOnly); + CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB, CurInvokeDest, + EHOnly); // FIXME: This is silly, move this into the builder. if (CurBB) CGF.Builder.SetInsertPoint(CurBB); @@ -316,13 +350,20 @@ private: /// inserted into the current function yet. std::vector<llvm::BranchInst *> BranchFixups; + /// PreviousInvokeDest - The invoke handler from the start of the cleanup + /// region. + llvm::BasicBlock *PreviousInvokeDest; + /// EHOnly - Perform this only on the exceptional edge, not the main edge. bool EHOnly; explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock, - llvm::BasicBlock *CleanupExitBlock, bool ehonly) - : CleanupEntryBlock(CleanupEntryBlock), + llvm::BasicBlock *CleanupExitBlock, + llvm::BasicBlock *PreviousInvokeDest, + bool ehonly) + : CleanupEntryBlock(CleanupEntryBlock), CleanupExitBlock(CleanupExitBlock), + PreviousInvokeDest(PreviousInvokeDest), EHOnly(ehonly) {} }; |