From: Anders Carlsson Date: Sat, 7 Feb 2009 21:26:04 +0000 (+0000) Subject: Simplify the Objective-C exception handling. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=190d00e1396214c77539c7095756b9ea38160463;p=clang Simplify the Objective-C exception handling. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64031 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index ff23b838e7..6c6419e4f1 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1766,7 +1766,8 @@ The basic framework for a @try-catch-finally is as follows: { objc_exception_data d; id _rethrow = null; - + bool _call_try_exit = true; + objc_exception_try_enter(&d); if (!setjmp(d.jmp_buf)) { ... try body ... @@ -1784,16 +1785,16 @@ The basic framework for a @try-catch-finally is as follows: } else { // exception in catch block _rethrow = objc_exception_extract(&d); - ... jump-through-finally_no_exit to finally_rethrow ... + _call_try_exit = false; + ... jump-through-finally to finally_rethrow ... } } ... jump-through-finally to finally_end ... finally: - // match either the initial try_enter or the catch try_enter, - // depending on the path followed. - objc_exception_try_exit(&d); -finally_no_exit: + if (_call_try_exit) + objc_exception_try_exit(&d); + ... finally block .... ... dispatch to finally destination ... @@ -1849,6 +1850,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, bool isTry = isa(S); // Create various blocks we refer to for handling @finally. llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); + llvm::BasicBlock *FinallyExit = CGF.createBasicBlock("finally.exit"); llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit"); llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); @@ -1864,8 +1866,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Push an EH context entry, used for handling rethrows and jumps // through finally. - CodeGenFunction::ObjCEHEntry EHEntry(FinallyBlock, FinallyNoExit, - FinallySwitch, DestCode); + CodeGenFunction::ObjCEHEntry EHEntry(FinallyBlock, FinallySwitch, DestCode); CGF.ObjCEHStack.push_back(&EHEntry); // Allocate memory for the exception data and rethrow pointer. @@ -1873,6 +1874,10 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, "exceptiondata.ptr"); llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy, "_rethrow"); + llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca(llvm::Type::Int1Ty, + "_call_try_exit"); + CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(), CallTryExitPtr); + if (!isTry) { // For @synchronized, call objc_sync_enter(sync.expr) llvm::Value *Arg = CGF.EmitScalarExpr( @@ -1912,6 +1917,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, if (!isTry) { CGF.Builder.CreateStore(Caught, RethrowPtr); + CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr); CGF.EmitJumpThroughFinally(&EHEntry, FinallyRethrow, false); } else if (const ObjCAtCatchStmt* CatchStmt = @@ -2014,9 +2020,11 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.Builder.CreateStore(CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn, ExceptionData), RethrowPtr); + CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr); CGF.EmitJumpThroughFinally(&EHEntry, FinallyRethrow, false); } else { CGF.Builder.CreateStore(Caught, RethrowPtr); + CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr); CGF.EmitJumpThroughFinally(&EHEntry, FinallyRethrow, false); } @@ -2027,6 +2035,11 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Emit the @finally block. CGF.EmitBlock(FinallyBlock); + llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp"); + + CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit); + + CGF.EmitBlock(FinallyExit); CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn, ExceptionData); CGF.EmitBlock(FinallyNoExit); @@ -2099,7 +2112,7 @@ void CodeGenFunction::EmitJumpThroughFinally(ObjCEHEntry *E, // Set the destination code and branch. Builder.CreateStore(ID, E->DestCode); - EmitBranch(ExecuteTryExit ? E->FinallyBlock : E->FinallyNoExit); + EmitBranch(E->FinallyBlock); } /// EmitObjCWeakRead - Code gen for loading value of a __weak diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 1a251d1363..ce32a45a5d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -95,18 +95,13 @@ public: // inside @catch blocks and which @finally block exits from an EH // scope should be chained through. struct ObjCEHEntry { - ObjCEHEntry(llvm::BasicBlock *fb, llvm::BasicBlock *fne, - llvm::SwitchInst *fs, llvm::Value *dc) - : FinallyBlock(fb), FinallyNoExit(fne), FinallySwitch(fs), + ObjCEHEntry(llvm::BasicBlock *fb, llvm::SwitchInst *fs, llvm::Value *dc) + : FinallyBlock(fb), FinallySwitch(fs), DestCode(dc), Exception(0) {} /// Entry point to the finally block. llvm::BasicBlock *FinallyBlock; - /// Entry point to the finally block which skips execution of the - /// try_exit runtime function. - llvm::BasicBlock *FinallyNoExit; - /// Switch instruction which runs at the end of the finally block /// to forward jumps through the finally block. llvm::SwitchInst *FinallySwitch;