summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGObjCGNU.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp34
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,
OpenPOWER on IntegriCloud