diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-01-01 10:34:51 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-01-01 10:34:51 +0000 |
commit | bb1e3bc1e0be2b8f891db46457a8943451bf4d8b (patch) | |
tree | 1e68501209c9133fbda8d45171e59f8d6f12dd55 /lib/CodeGen/CGObjCGNU.cpp | |
parent | 77212133072dc40f070a280af8217032f55a9eb4 (diff) | |
download | FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.zip FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.tar.gz |
Updaet clang to 92395.
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index be772c7..95f67ae 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -450,7 +450,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs, lookupArgs+2); - return CGF.EmitCall(FnInfo, imp, ActualArgs); + return CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs); } /// Generate code for a message send expression. @@ -536,7 +536,7 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, imp = Builder.CreateCall2(lookupFunction, Receiver, cmd); } - return CGF.EmitCall(FnInfo, imp, ActualArgs); + return CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs); } /// Generates a MethodList. Used in construction of a objc_class and @@ -1607,7 +1607,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, Params.push_back(PtrTy); llvm::Value *RethrowFn = CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), - Params, false), "_Unwind_Resume_or_Rethrow"); + Params, false), "objc_exception_throw"); bool isTry = isa<ObjCAtTryStmt>(S); llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); @@ -1618,7 +1618,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); - // GNU runtime does not currently support @synchronized() + // @synchronized() if (!isTry) { std::vector<const llvm::Type*> Args(1, IdTy); llvm::FunctionType *FTy = @@ -1770,7 +1770,13 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, ESelArgs.clear(); ESelArgs.push_back(Exc); ESelArgs.push_back(Personality); - ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); + // If there is a @catch or @finally clause in outside of this one then we + // need to make sure that we catch and rethrow it. + if (PrevLandingPad) { + ESelArgs.push_back(NULLPtr); + } else { + ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); + } CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(), "selector"); CGF.Builder.CreateCall(llvm_eh_typeid_for, @@ -1811,11 +1817,23 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBranch(FinallyEnd); CGF.EmitBlock(FinallyRethrow); - CGF.Builder.CreateCall(RethrowFn, CGF.Builder.CreateLoad(RethrowPtr)); - CGF.Builder.CreateUnreachable(); - CGF.EmitBlock(FinallyEnd); + llvm::Value *ExceptionObject = CGF.Builder.CreateLoad(RethrowPtr); + llvm::BasicBlock *UnwindBB = CGF.getInvokeDest(); + if (!UnwindBB) { + CGF.Builder.CreateCall(RethrowFn, ExceptionObject); + // Exception always thrown, next instruction is never reached. + CGF.Builder.CreateUnreachable(); + } else { + // If there is a @catch block outside this scope, we invoke instead of + // calling because we may return to this function. This is very slow, but + // some people still do it. It would be nice to add an optimised path for + // this. + CGF.Builder.CreateInvoke(RethrowFn, UnwindBB, UnwindBB, &ExceptionObject, + &ExceptionObject+1); + } + CGF.EmitBlock(FinallyEnd); } void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, |