aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGObjCGNU.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-05-11 18:16:28 +0000
committerChris Lattner <sabre@nondot.org>2009-05-11 18:16:28 +0000
commitd6a9907ceff2c52738a72e38b6a04ab44ce1173f (patch)
tree0023f47a59ebf266310be193801d8ff4f045bd54 /lib/CodeGen/CGObjCGNU.cpp
parent67187ceb216331f8b8eeacd3f8b34f504b9bbcaf (diff)
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
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp38
1 files 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<const llvm::Type*> 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<ObjCAtSynchronizedStmt>(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<ObjCAtTryStmt>(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<ObjCAtTryStmt>(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<const llvm::Type*> 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<ObjCAtSynchronizedStmt>(S).getSynchExpr());
+ SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
+ CGF.Builder.CreateCall(SyncExit, SyncArg);
}
if (Info.SwitchBlock)