From d6a9907ceff2c52738a72e38b6a04ab44ce1173f Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 11 May 2009 18:16:28 +0000 Subject: [PATCH] More improvements for GNU runtime objc EH, patch by David Chisnall! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71451 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjCGNU.cpp | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index e780a1f508..489b673587 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -1143,15 +1143,24 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest(); llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); + llvm::BasicBlock *CatchInCatch = CGF.createBasicBlock("catch.rethrow"); llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); // GNU runtime does not currently support @synchronized() if (!isTry) { - CGF.ErrorUnsupported(&S, "@synchronized statement"); + std::vector Args(1, IdTy); + llvm::FunctionType *FTy = + llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); + llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); + llvm::Value *SyncArg = + CGF.EmitScalarExpr(cast(S).getSynchExpr()); + SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); + CGF.Builder.CreateCall(SyncEnter, SyncArg); } + // Push an EH context entry, used for handling rethrows and jumps // through finally. CGF.PushCleanupBlock(FinallyBlock); @@ -1198,6 +1207,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, if (isTry) { if (const ObjCAtCatchStmt* CatchStmt = cast(S).getCatchStmts()) { + CGF.setInvokeDest(CatchInCatch); for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) { const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); @@ -1286,19 +1296,43 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBranchThroughCleanup(FinallyRethrow); } } + // The @finally block is a secondary landing pad for any exceptions thrown in + // @catch() blocks + CGF.EmitBlock(CatchInCatch); + Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); + ESelArgs.clear(); + ESelArgs.push_back(Exc); + ESelArgs.push_back(Personality); + ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0)); + CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(), + "selector"); + CGF.Builder.CreateCall(llvm_eh_typeid_for, + CGF.Builder.CreateIntToPtr(ESelArgs[2], PtrTy)); + CGF.Builder.CreateStore(Exc, RethrowPtr); + CGF.EmitBranchThroughCleanup(FinallyRethrow); + CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); CGF.setInvokeDest(PrevLandingPad); CGF.EmitBlock(FinallyBlock); + if (isTry) { if (const ObjCAtFinallyStmt* FinallyStmt = cast(S).getFinallyStmt()) CGF.EmitStmt(FinallyStmt->getFinallyBody()); } else { - // TODO: Emit 'objc_sync_exit(expr)' as finally's sole statement for + // Emit 'objc_sync_exit(expr)' as finally's sole statement for // @synchronized. + std::vector Args(1, IdTy); + llvm::FunctionType *FTy = + llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); + llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); + llvm::Value *SyncArg = + CGF.EmitScalarExpr(cast(S).getSynchExpr()); + SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); + CGF.Builder.CreateCall(SyncExit, SyncArg); } if (Info.SwitchBlock) -- 2.40.0