From: John McCall Date: Wed, 21 Jul 2010 06:59:36 +0000 (+0000) Subject: Switch the fragile-ABI @finally/@synchronized cleanup over to using a lazy X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc5052999cd064584492ba15a808b6e1cee6d931;p=clang Switch the fragile-ABI @finally/@synchronized cleanup over to using a lazy cleanup. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108997 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 4e5c34b174..8b4361c034 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -2541,6 +2541,54 @@ void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF, return EmitTryOrSynchronizedStmt(CGF, S); } +namespace { + struct PerformFragileFinally : EHScopeStack::LazyCleanup { + const Stmt &S; + llvm::Value *SyncArg; + llvm::Value *CallTryExitVar; + llvm::Value *ExceptionData; + ObjCTypesHelper &ObjCTypes; + PerformFragileFinally(const Stmt *S, + llvm::Value *SyncArg, + llvm::Value *CallTryExitVar, + llvm::Value *ExceptionData, + ObjCTypesHelper *ObjCTypes) + : S(*S), SyncArg(SyncArg), CallTryExitVar(CallTryExitVar), + ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {} + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + // Check whether we need to call objc_exception_try_exit. + // In optimized code, this branch will always be folded. + llvm::BasicBlock *FinallyCallExit = + CGF.createBasicBlock("finally.call_exit"); + llvm::BasicBlock *FinallyNoCallExit = + CGF.createBasicBlock("finally.no_call_exit"); + CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar), + FinallyCallExit, FinallyNoCallExit); + + CGF.EmitBlock(FinallyCallExit); + CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData) + ->setDoesNotThrow(); + + CGF.EmitBlock(FinallyNoCallExit); + + if (isa(S)) { + if (const ObjCAtFinallyStmt* FinallyStmt = + cast(S).getFinallyStmt()) + CGF.EmitStmt(FinallyStmt->getFinallyBody()); + + // Currently, the end of the cleanup must always exist. + CGF.EnsureInsertPoint(); + } else { + // Emit objc_sync_exit(expr); as finally's sole statement for + // @synchronized. + CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg) + ->setDoesNotThrow(); + } + } + }; +} + /* Objective-C setjmp-longjmp (sjlj) Exception Handling @@ -2697,38 +2745,11 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CallTryExitVar); // Push a normal cleanup to leave the try scope. - { - CodeGenFunction::CleanupBlock FinallyScope(CGF, NormalCleanup); - - // Check whether we need to call objc_exception_try_exit. - // In optimized code, this branch will always be folded. - llvm::BasicBlock *FinallyCallExit = - CGF.createBasicBlock("finally.call_exit"); - llvm::BasicBlock *FinallyNoCallExit = - CGF.createBasicBlock("finally.no_call_exit"); - CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar), - FinallyCallExit, FinallyNoCallExit); - - CGF.EmitBlock(FinallyCallExit); - CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData) - ->setDoesNotThrow(); - - CGF.EmitBlock(FinallyNoCallExit); - - if (isTry) { - if (const ObjCAtFinallyStmt* FinallyStmt = - cast(S).getFinallyStmt()) - CGF.EmitStmt(FinallyStmt->getFinallyBody()); - - // ~CleanupBlock requires there to be an exit block. - CGF.EnsureInsertPoint(); - } else { - // Emit objc_sync_exit(expr); as finally's sole statement for - // @synchronized. - CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg) - ->setDoesNotThrow(); - } - } + CGF.EHStack.pushLazyCleanup(NormalCleanup, &S, + SyncArg, + CallTryExitVar, + ExceptionData, + &ObjCTypes); // Enter a try block: // - Call objc_exception_try_enter to push ExceptionData on top of