diff options
Diffstat (limited to 'clang/lib/CodeGen/CGObjC.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 167 |
1 files changed, 111 insertions, 56 deletions
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 3f930c76fe0a..937a0e8a3b69 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -23,6 +23,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/ObjCARCUtil.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" @@ -759,7 +760,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD); if (OMD->isDirectMethod()) { Fn->setVisibility(llvm::Function::HiddenVisibility); - CGM.SetLLVMFunctionAttributes(OMD, FI, Fn); + CGM.SetLLVMFunctionAttributes(OMD, FI, Fn, /*IsThunk=*/false); CGM.SetLLVMFunctionAttributesForDefinition(OMD, Fn); } else { CGM.SetInternalFunctionAttributes(OMD, Fn, FI); @@ -924,10 +925,11 @@ PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM, IvarSize = TInfo.Width; IvarAlignment = TInfo.Align; - // If we have a copy property, we always have to use getProperty/setProperty. - // TODO: we could actually use setProperty and an expression for non-atomics. + // If we have a copy property, we always have to use setProperty. + // If the property is atomic we need to use getProperty, but in + // the nonatomic case we can just use expression. if (IsCopy) { - Kind = GetSetProperty; + Kind = IsAtomic ? GetSetProperty : SetPropertyAndExpressionGet; return; } @@ -1521,7 +1523,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, DeclRefExpr self(getContext(), selfDecl, false, selfDecl->getType(), VK_LValue, SourceLocation()); ImplicitCastExpr selfLoad(ImplicitCastExpr::OnStack, selfDecl->getType(), - CK_LValueToRValue, &self, VK_RValue, + CK_LValueToRValue, &self, VK_PRValue, FPOptionsOverride()); ObjCIvarRefExpr ivarRef(ivar, ivar->getType().getNonReferenceType(), SourceLocation(), SourceLocation(), @@ -1533,7 +1535,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, SourceLocation()); ImplicitCastExpr argLoad(ImplicitCastExpr::OnStack, argType.getUnqualifiedType(), CK_LValueToRValue, - &arg, VK_RValue, FPOptionsOverride()); + &arg, VK_PRValue, FPOptionsOverride()); // The property type can differ from the ivar type in some situations with // Objective-C pointer types, we can always bit cast the RHS in these cases. @@ -1555,15 +1557,15 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, argCK = CK_BitCast; } ImplicitCastExpr argCast(ImplicitCastExpr::OnStack, ivarRef.getType(), argCK, - &argLoad, VK_RValue, FPOptionsOverride()); + &argLoad, VK_PRValue, FPOptionsOverride()); Expr *finalArg = &argLoad; if (!getContext().hasSameUnqualifiedType(ivarRef.getType(), argLoad.getType())) finalArg = &argCast; BinaryOperator *assign = BinaryOperator::Create( - getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue, - OK_Ordinary, SourceLocation(), FPOptionsOverride()); + getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(), + VK_PRValue, OK_Ordinary, SourceLocation(), FPOptionsOverride()); EmitStmt(assign); } @@ -1818,9 +1820,10 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); + llvm::Type *UnsignedLongTy = ConvertType(getContext().UnsignedLongTy); llvm::Value *initialMutations = - Builder.CreateAlignedLoad(StateMutationsPtr, getPointerAlign(), - "forcoll.initial-mutations"); + Builder.CreateAlignedLoad(UnsignedLongTy, StateMutationsPtr, + getPointerAlign(), "forcoll.initial-mutations"); // Start looping. This is the point we return to whenever we have a // fresh, non-empty batch of objects. @@ -1842,8 +1845,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // refreshes. StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); llvm::Value *currentMutations - = Builder.CreateAlignedLoad(StateMutationsPtr, getPointerAlign(), - "statemutations"); + = Builder.CreateAlignedLoad(UnsignedLongTy, StateMutationsPtr, + getPointerAlign(), "statemutations"); llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated"); llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcoll.notmutated"); @@ -1853,9 +1856,9 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // If so, call the enumeration-mutation function. EmitBlock(WasMutatedBB); + llvm::Type *ObjCIdType = ConvertType(getContext().getObjCIdType()); llvm::Value *V = - Builder.CreateBitCast(Collection, - ConvertType(getContext().getObjCIdType())); + Builder.CreateBitCast(Collection, ObjCIdType); CallArgList Args2; Args2.add(RValue::get(V), getContext().getObjCIdType()); // FIXME: We shouldn't need to get the function info here, the runtime already @@ -1901,10 +1904,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ Builder.CreateLoad(StateItemsPtr, "stateitems"); // Fetch the value at the current index from the buffer. - llvm::Value *CurrentItemPtr = - Builder.CreateGEP(EnumStateItems, index, "currentitem.ptr"); + llvm::Value *CurrentItemPtr = Builder.CreateGEP( + EnumStateItems->getType()->getPointerElementType(), EnumStateItems, index, + "currentitem.ptr"); llvm::Value *CurrentItem = - Builder.CreateAlignedLoad(CurrentItemPtr, getPointerAlign()); + Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign()); if (SanOpts.has(SanitizerKind::ObjCCast)) { // Before using an item from the collection, check that the implicit cast @@ -2078,6 +2082,15 @@ void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) { EmitNounwindRuntimeCall(fn, values); } +/// Emit a call to "clang.arc.noop.use", which consumes the result of a call +/// that has operand bundle "clang.arc.attachedcall". +void CodeGenFunction::EmitARCNoopIntrinsicUse(ArrayRef<llvm::Value *> values) { + llvm::Function *&fn = CGM.getObjCEntrypoints().clang_arc_noop_use; + if (!fn) + fn = CGM.getIntrinsic(llvm::Intrinsic::objc_clang_arc_noop_use); + EmitNounwindRuntimeCall(fn, values); +} + static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM, llvm::Value *RTF) { if (auto *F = dyn_cast<llvm::Function>(RTF)) { // If the target runtime doesn't naturally support ARC, emit weak @@ -2304,10 +2317,11 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) { // with this marker yet, so leave a breadcrumb for the ARC // optimizer to pick up. } else { - const char *markerKey = "clang.arc.retainAutoreleasedReturnValueMarker"; - if (!CGF.CGM.getModule().getModuleFlag(markerKey)) { + const char *retainRVMarkerKey = llvm::objcarc::getRVMarkerModuleFlagStr(); + if (!CGF.CGM.getModule().getModuleFlag(retainRVMarkerKey)) { auto *str = llvm::MDString::get(CGF.getLLVMContext(), assembly); - CGF.CGM.getModule().addModuleFlag(llvm::Module::Error, markerKey, str); + CGF.CGM.getModule().addModuleFlag(llvm::Module::Error, + retainRVMarkerKey, str); } } } @@ -2317,6 +2331,47 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) { CGF.Builder.CreateCall(marker, None, CGF.getBundlesForFunclet(marker)); } +static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value, + bool IsRetainRV, + CodeGenFunction &CGF) { + emitAutoreleasedReturnValueMarker(CGF); + + // Add operand bundle "clang.arc.attachedcall" to the call instead of emitting + // retainRV or claimRV calls in the IR. We currently do this only when the + // optimization level isn't -O0 since global-isel, which is currently run at + // -O0, doesn't know about the operand bundle. + + // FIXME: Do this when the target isn't aarch64. + if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 && + CGF.CGM.getTarget().getTriple().isAArch64()) { + llvm::Value *bundleArgs[] = {llvm::ConstantInt::get( + CGF.Int64Ty, + llvm::objcarc::getAttachedCallOperandBundleEnum(IsRetainRV))}; + llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs); + auto *oldCall = cast<llvm::CallBase>(value); + llvm::CallBase *newCall = llvm::CallBase::addOperandBundle( + oldCall, llvm::LLVMContext::OB_clang_arc_attachedcall, OB, oldCall); + newCall->copyMetadata(*oldCall); + oldCall->replaceAllUsesWith(newCall); + oldCall->eraseFromParent(); + CGF.EmitARCNoopIntrinsicUse(newCall); + return newCall; + } + + bool isNoTail = + CGF.CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail(); + llvm::CallInst::TailCallKind tailKind = + isNoTail ? llvm::CallInst::TCK_NoTail : llvm::CallInst::TCK_None; + ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints(); + llvm::Function *&EP = IsRetainRV + ? EPs.objc_retainAutoreleasedReturnValue + : EPs.objc_unsafeClaimAutoreleasedReturnValue; + llvm::Intrinsic::ID IID = + IsRetainRV ? llvm::Intrinsic::objc_retainAutoreleasedReturnValue + : llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue; + return emitARCValueOperation(CGF, value, nullptr, EP, IID, tailKind); +} + /// Retain the given object which is the result of a function call. /// call i8* \@objc_retainAutoreleasedReturnValue(i8* %value) /// @@ -2324,15 +2379,7 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) { /// call with completely different semantics. llvm::Value * CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) { - emitAutoreleasedReturnValueMarker(*this); - llvm::CallInst::TailCallKind tailKind = - CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail() - ? llvm::CallInst::TCK_NoTail - : llvm::CallInst::TCK_None; - return emitARCValueOperation( - *this, value, nullptr, - CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue, - llvm::Intrinsic::objc_retainAutoreleasedReturnValue, tailKind); + return emitOptimizedARCReturnCall(value, true, *this); } /// Claim a possibly-autoreleased return value at +0. This is only @@ -2344,15 +2391,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) { /// call i8* \@objc_unsafeClaimAutoreleasedReturnValue(i8* %value) llvm::Value * CodeGenFunction::EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value) { - emitAutoreleasedReturnValueMarker(*this); - llvm::CallInst::TailCallKind tailKind = - CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail() - ? llvm::CallInst::TCK_NoTail - : llvm::CallInst::TCK_None; - return emitARCValueOperation( - *this, value, nullptr, - CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue, - llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue, tailKind); + return emitOptimizedARCReturnCall(value, false, *this); } /// Release the given object. @@ -2902,8 +2941,12 @@ static llvm::Value *emitARCOperationAfterCall(CodeGenFunction &CGF, ValueTransform doAfterCall, ValueTransform doFallback) { CGBuilderTy::InsertPoint ip = CGF.Builder.saveIP(); + auto *callBase = dyn_cast<llvm::CallBase>(value); - if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(value)) { + if (callBase && llvm::objcarc::hasAttachedCallOpBundle(callBase)) { + // Fall back if the call base has operand bundle "clang.arc.attachedcall". + value = doFallback(CGF, value); + } else if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(value)) { // Place the retain immediately following the call. CGF.Builder.SetInsertPoint(call->getParent(), ++llvm::BasicBlock::iterator(call)); @@ -3657,12 +3700,18 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( FunctionTy, nullptr, SC_Static, false, false); FunctionArgList args; - ImplicitParamDecl DstDecl(C, FD, SourceLocation(), /*Id=*/nullptr, DestTy, - ImplicitParamDecl::Other); - args.push_back(&DstDecl); - ImplicitParamDecl SrcDecl(C, FD, SourceLocation(), /*Id=*/nullptr, SrcTy, - ImplicitParamDecl::Other); - args.push_back(&SrcDecl); + ParmVarDecl *Params[2]; + ParmVarDecl *DstDecl = ParmVarDecl::Create( + C, FD, SourceLocation(), SourceLocation(), nullptr, DestTy, + C.getTrivialTypeSourceInfo(DestTy, SourceLocation()), SC_None, + /*DefArg=*/nullptr); + args.push_back(Params[0] = DstDecl); + ParmVarDecl *SrcDecl = ParmVarDecl::Create( + C, FD, SourceLocation(), SourceLocation(), nullptr, SrcTy, + C.getTrivialTypeSourceInfo(SrcTy, SourceLocation()), SC_None, + /*DefArg=*/nullptr); + args.push_back(Params[1] = SrcDecl); + FD->setParams(Params); const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); @@ -3678,12 +3727,12 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( StartFunction(FD, ReturnTy, Fn, FI, args); - DeclRefExpr DstExpr(C, &DstDecl, false, DestTy, VK_RValue, SourceLocation()); + DeclRefExpr DstExpr(C, DstDecl, false, DestTy, VK_PRValue, SourceLocation()); UnaryOperator *DST = UnaryOperator::Create( C, &DstExpr, UO_Deref, DestTy->getPointeeType(), VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride()); - DeclRefExpr SrcExpr(C, &SrcDecl, false, SrcTy, VK_RValue, SourceLocation()); + DeclRefExpr SrcExpr(C, SrcDecl, false, SrcTy, VK_PRValue, SourceLocation()); UnaryOperator *SRC = UnaryOperator::Create( C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride()); @@ -3741,12 +3790,18 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( FunctionTy, nullptr, SC_Static, false, false); FunctionArgList args; - ImplicitParamDecl DstDecl(C, FD, SourceLocation(), /*Id=*/nullptr, DestTy, - ImplicitParamDecl::Other); - args.push_back(&DstDecl); - ImplicitParamDecl SrcDecl(C, FD, SourceLocation(), /*Id=*/nullptr, SrcTy, - ImplicitParamDecl::Other); - args.push_back(&SrcDecl); + ParmVarDecl *Params[2]; + ParmVarDecl *DstDecl = ParmVarDecl::Create( + C, FD, SourceLocation(), SourceLocation(), nullptr, DestTy, + C.getTrivialTypeSourceInfo(DestTy, SourceLocation()), SC_None, + /*DefArg=*/nullptr); + args.push_back(Params[0] = DstDecl); + ParmVarDecl *SrcDecl = ParmVarDecl::Create( + C, FD, SourceLocation(), SourceLocation(), nullptr, SrcTy, + C.getTrivialTypeSourceInfo(SrcTy, SourceLocation()), SC_None, + /*DefArg=*/nullptr); + args.push_back(Params[1] = SrcDecl); + FD->setParams(Params); const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); @@ -3761,7 +3816,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( StartFunction(FD, ReturnTy, Fn, FI, args); - DeclRefExpr SrcExpr(getContext(), &SrcDecl, false, SrcTy, VK_RValue, + DeclRefExpr SrcExpr(getContext(), SrcDecl, false, SrcTy, VK_PRValue, SourceLocation()); UnaryOperator *SRC = UnaryOperator::Create( @@ -3788,7 +3843,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( CXXConstExpr->getConstructionKind(), SourceRange()); - DeclRefExpr DstExpr(getContext(), &DstDecl, false, DestTy, VK_RValue, + DeclRefExpr DstExpr(getContext(), DstDecl, false, DestTy, VK_PRValue, SourceLocation()); RValue DV = EmitAnyExpr(&DstExpr); |
