diff options
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index d3da649fbb..57dfd28e9e 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -1159,25 +1159,48 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, }; llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); - // Get the IMP to call - llvm::Value *imp = LookupIMP(CGF, Receiver, cmd, node); - + CodeGenTypes &Types = CGM.getTypes(); CallArgList ActualArgs; ActualArgs.add(RValue::get(Receiver), ASTIdTy); ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType()); ActualArgs.addFrom(CallArgs); - - CodeGenTypes &Types = CGM.getTypes(); const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, FunctionType::ExtInfo()); + // Get the IMP to call + llvm::Value *imp; + + // If we have non-legacy dispatch specified, we try using the objc_msgSend() + // functions. These are not supported on all platforms (or all runtimes on a + // given platform), so we + switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) { + default: + llvm_unreachable("Invalid dispatch method!"); + case CodeGenOptions::Legacy: + fprintf(stderr, "Legacy\n"); + imp = LookupIMP(CGF, Receiver, cmd, node); + break; + case CodeGenOptions::Mixed: + fprintf(stderr, "Mixed\n"); + case CodeGenOptions::NonLegacy: + fprintf(stderr, "NonLegacy\n"); + if (CGM.ReturnTypeUsesFPRet(ResultType) || (Method && Method->isVariadic())) { + imp = LookupIMP(CGF, Receiver, cmd, node); + } else if (CGM.ReturnTypeUsesSRet(FnInfo)) { + // The actual types here don't matter - we're going to bitcast the + // function anyway + imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), + "objc_msgSend_stret"); + } else { + imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), + "objc_msgSend"); + } + } + + llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); imp = EnforceType(Builder, imp, llvm::PointerType::getUnqual(impType)); - - // For sender-aware dispatch, we pass the sender as the third argument to a - // lookup function. When sending messages from C code, the sender is nil. - // objc_msg_lookup_sender(id *receiver, SEL selector, id sender); llvm::Instruction *call; RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs, 0, &call); |