aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGObjC.cpp')
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp167
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);