aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp397
1 files changed, 225 insertions, 172 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp
index 937a0e8a3b69..03fc0ec7ff54 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp
@@ -22,11 +22,14 @@
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGen/CodeGenABITypes.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/ObjCARCUtil.h"
#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
+#include <optional>
using namespace clang;
using namespace CodeGen;
@@ -49,8 +52,7 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
{
llvm::Constant *C =
CGM.getObjCRuntime().GenerateConstantString(E->getString()).getPointer();
- // FIXME: This bitcast should just be made an invariant on the Runtime.
- return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
+ return C;
}
/// EmitObjCBoxedExpr - This routine generates code to call
@@ -92,8 +94,9 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
// and cast value to correct type
Address Temporary = CreateMemTemp(SubExpr->getType());
EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true);
- Address BitCast = Builder.CreateBitCast(Temporary, ConvertType(ArgQT));
- Args.add(RValue::get(BitCast.getPointer()), ArgQT);
+ llvm::Value *BitCast =
+ Builder.CreateBitCast(Temporary.getPointer(), ConvertType(ArgQT));
+ Args.add(RValue::get(BitCast), ArgQT);
// Create char array to store type encoding
std::string Str;
@@ -136,8 +139,8 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
LValue LV = MakeNaturalAlignAddrLValue(Constant, IdTy);
llvm::Value *Ptr = EmitLoadOfScalar(LV, E->getBeginLoc());
cast<llvm::LoadInst>(Ptr)->setMetadata(
- CGM.getModule().getMDKindID("invariant.load"),
- llvm::MDNode::get(getLLVMContext(), None));
+ llvm::LLVMContext::MD_invariant_load,
+ llvm::MDNode::get(getLLVMContext(), std::nullopt));
return Builder.CreateBitCast(Ptr, ConvertType(E->getType()));
}
@@ -145,9 +148,9 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
llvm::APInt APNumElements(Context.getTypeSize(Context.getSizeType()),
NumElements);
QualType ElementType = Context.getObjCIdType().withConst();
- QualType ElementArrayType
- = Context.getConstantArrayType(ElementType, APNumElements, nullptr,
- ArrayType::Normal, /*IndexTypeQuals=*/0);
+ QualType ElementArrayType = Context.getConstantArrayType(
+ ElementType, APNumElements, nullptr, ArraySizeModifier::Normal,
+ /*IndexTypeQuals=*/0);
// Allocate the temporary array(s).
Address Objects = CreateMemTemp(ElementArrayType, "objects");
@@ -218,6 +221,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
QualType ResultType = E->getType();
const ObjCObjectPointerType *InterfacePointerType
= ResultType->getAsObjCInterfacePointerType();
+ assert(InterfacePointerType && "Unexpected InterfacePointerType - null");
ObjCInterfaceDecl *Class
= InterfacePointerType->getObjectType()->getInterface();
CGObjCRuntime &Runtime = CGM.getObjCRuntime();
@@ -369,16 +373,14 @@ static const Expr *findWeakLValue(const Expr *E) {
///
/// If the runtime does support a required entrypoint, then this method will
/// generate a call and return the resulting value. Otherwise it will return
-/// None and the caller can generate a msgSend instead.
-static Optional<llvm::Value *>
-tryGenerateSpecializedMessageSend(CodeGenFunction &CGF, QualType ResultType,
- llvm::Value *Receiver,
- const CallArgList& Args, Selector Sel,
- const ObjCMethodDecl *method,
- bool isClassMessage) {
+/// std::nullopt and the caller can generate a msgSend instead.
+static std::optional<llvm::Value *> tryGenerateSpecializedMessageSend(
+ CodeGenFunction &CGF, QualType ResultType, llvm::Value *Receiver,
+ const CallArgList &Args, Selector Sel, const ObjCMethodDecl *method,
+ bool isClassMessage) {
auto &CGM = CGF.CGM;
if (!CGM.getCodeGenOpts().ObjCConvertMessagesToRuntimeCalls)
- return None;
+ return std::nullopt;
auto &Runtime = CGM.getLangOpts().ObjCRuntime;
switch (Sel.getMethodFamily()) {
@@ -399,7 +401,7 @@ tryGenerateSpecializedMessageSend(CodeGenFunction &CGF, QualType ResultType,
if (isa<llvm::ConstantPointerNull>(arg))
return CGF.EmitObjCAllocWithZone(Receiver,
CGF.ConvertType(ResultType));
- return None;
+ return std::nullopt;
}
}
break;
@@ -430,7 +432,7 @@ tryGenerateSpecializedMessageSend(CodeGenFunction &CGF, QualType ResultType,
default:
break;
}
- return None;
+ return std::nullopt;
}
CodeGen::RValue CGObjCRuntime::GeneratePossiblySpecializedMessageSend(
@@ -438,10 +440,10 @@ CodeGen::RValue CGObjCRuntime::GeneratePossiblySpecializedMessageSend(
Selector Sel, llvm::Value *Receiver, const CallArgList &Args,
const ObjCInterfaceDecl *OID, const ObjCMethodDecl *Method,
bool isClassMessage) {
- if (Optional<llvm::Value *> SpecializedResult =
+ if (std::optional<llvm::Value *> SpecializedResult =
tryGenerateSpecializedMessageSend(CGF, ResultType, Receiver, Args,
Sel, Method, isClassMessage)) {
- return RValue::get(SpecializedResult.getValue());
+ return RValue::get(*SpecializedResult);
}
return GenerateMessageSend(CGF, Return, ResultType, Sel, Receiver, Args, OID,
Method);
@@ -519,36 +521,36 @@ CGObjCRuntime::GetRuntimeProtocolList(ObjCProtocolDecl::protocol_iterator begin,
/// Instead of '[[MyClass alloc] init]', try to generate
/// 'objc_alloc_init(MyClass)'. This provides a code size improvement on the
/// caller side, as well as the optimized objc_alloc.
-static Optional<llvm::Value *>
+static std::optional<llvm::Value *>
tryEmitSpecializedAllocInit(CodeGenFunction &CGF, const ObjCMessageExpr *OME) {
auto &Runtime = CGF.getLangOpts().ObjCRuntime;
if (!Runtime.shouldUseRuntimeFunctionForCombinedAllocInit())
- return None;
+ return std::nullopt;
// Match the exact pattern '[[MyClass alloc] init]'.
Selector Sel = OME->getSelector();
if (OME->getReceiverKind() != ObjCMessageExpr::Instance ||
!OME->getType()->isObjCObjectPointerType() || !Sel.isUnarySelector() ||
Sel.getNameForSlot(0) != "init")
- return None;
+ return std::nullopt;
// Okay, this is '[receiver init]', check if 'receiver' is '[cls alloc]'
// with 'cls' a Class.
auto *SubOME =
dyn_cast<ObjCMessageExpr>(OME->getInstanceReceiver()->IgnoreParenCasts());
if (!SubOME)
- return None;
+ return std::nullopt;
Selector SubSel = SubOME->getSelector();
if (!SubOME->getType()->isObjCObjectPointerType() ||
!SubSel.isUnarySelector() || SubSel.getNameForSlot(0) != "alloc")
- return None;
+ return std::nullopt;
llvm::Value *Receiver = nullptr;
switch (SubOME->getReceiverKind()) {
case ObjCMessageExpr::Instance:
if (!SubOME->getInstanceReceiver()->getType()->isObjCClassType())
- return None;
+ return std::nullopt;
Receiver = CGF.EmitScalarExpr(SubOME->getInstanceReceiver());
break;
@@ -562,7 +564,7 @@ tryEmitSpecializedAllocInit(CodeGenFunction &CGF, const ObjCMessageExpr *OME) {
}
case ObjCMessageExpr::SuperInstance:
case ObjCMessageExpr::SuperClass:
- return None;
+ return std::nullopt;
}
return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType()));
@@ -589,7 +591,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
}
}
- if (Optional<llvm::Value *> Val = tryEmitSpecializedAllocInit(*this, E))
+ if (std::optional<llvm::Value *> Val = tryEmitSpecializedAllocInit(*this, E))
return AdjustObjCObjectType(*this, E->getType(), RValue::get(*Val));
// We don't retain the receiver in delegate init calls, and this is
@@ -767,7 +769,8 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
}
args.push_back(OMD->getSelfDecl());
- args.push_back(OMD->getCmdDecl());
+ if (!OMD->isDirectMethod())
+ args.push_back(OMD->getCmdDecl());
args.append(OMD->param_begin(), OMD->param_end());
@@ -816,19 +819,17 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
bool isAtomic, bool hasStrong) {
ASTContext &Context = CGF.getContext();
- Address src =
+ llvm::Value *src =
CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0)
- .getAddress(CGF);
+ .getPointer(CGF);
// objc_copyStruct (ReturnValue, &structIvar,
// sizeof (Type of Ivar), isAtomic, false);
CallArgList args;
- Address dest = CGF.Builder.CreateBitCast(CGF.ReturnValue, CGF.VoidPtrTy);
- args.add(RValue::get(dest.getPointer()), Context.VoidPtrTy);
-
- src = CGF.Builder.CreateBitCast(src, CGF.VoidPtrTy);
- args.add(RValue::get(src.getPointer()), Context.VoidPtrTy);
+ llvm::Value *dest = CGF.ReturnValue.getPointer();
+ args.add(RValue::get(dest), Context.VoidPtrTy);
+ args.add(RValue::get(src), Context.VoidPtrTy);
CharUnits size = CGF.getContext().getTypeSizeInChars(ivar->getType());
args.add(RValue::get(CGF.CGM.getSize(size)), Context.getSizeType());
@@ -847,7 +848,7 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
static bool hasUnalignedAtomics(llvm::Triple::ArchType arch) {
// FIXME: Allow unaligned atomic load/store on x86. (It is not
// currently supported by the backend.)
- return 0;
+ return false;
}
/// Return the maximum size that permits atomic accesses for the given
@@ -1094,7 +1095,6 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
llvm::Value *ivarAddr =
CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0)
.getPointer(CGF);
- ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
// Third argument is the helper function.
@@ -1108,11 +1108,47 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
callee, ReturnValueSlot(), args);
}
+// emitCmdValueForGetterSetterBody - Handle emitting the load necessary for
+// the `_cmd` selector argument for getter/setter bodies. For direct methods,
+// this returns an undefined/poison value; this matches behavior prior to `_cmd`
+// being removed from the direct method ABI as the getter/setter caller would
+// never load one. For non-direct methods, this emits a load of the implicit
+// `_cmd` storage.
+static llvm::Value *emitCmdValueForGetterSetterBody(CodeGenFunction &CGF,
+ ObjCMethodDecl *MD) {
+ if (MD->isDirectMethod()) {
+ // Direct methods do not have a `_cmd` argument. Emit an undefined/poison
+ // value. This will be passed to objc_getProperty/objc_setProperty, which
+ // has not appeared bothered by the `_cmd` argument being undefined before.
+ llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType());
+ return llvm::PoisonValue::get(selType);
+ }
+
+ return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(MD->getCmdDecl()), "cmd");
+}
+
void
CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
const ObjCPropertyImplDecl *propImpl,
const ObjCMethodDecl *GetterMethodDecl,
llvm::Constant *AtomicHelperFn) {
+
+ ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
+
+ if (ivar->getType().isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
+ if (!AtomicHelperFn) {
+ LValue Src =
+ EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 0);
+ LValue Dst = MakeAddrLValue(ReturnValue, ivar->getType());
+ callCStructCopyConstructor(Dst, Src);
+ } else {
+ ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
+ emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), ivar,
+ AtomicHelperFn);
+ }
+ return;
+ }
+
// If there's a non-trivial 'get' expression, we just have to emit that.
if (!hasTrivialGetExpr(propImpl)) {
if (!AtomicHelperFn) {
@@ -1133,8 +1169,6 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
QualType propType = prop->getType();
ObjCMethodDecl *getterMethod = propImpl->getGetterMethodDecl();
- ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
-
// Pick an implementation strategy.
PropertyImplStrategy strategy(CGM, propImpl);
switch (strategy.getKind()) {
@@ -1149,11 +1183,10 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
// types, so there's no point in trying to pick a prettier type.
uint64_t ivarSize = getContext().toBits(strategy.getIvarSize());
llvm::Type *bitcastType = llvm::Type::getIntNTy(getLLVMContext(), ivarSize);
- bitcastType = bitcastType->getPointerTo(); // addrspace 0 okay
// Perform an atomic load. This does not impose ordering constraints.
Address ivarAddr = LV.getAddress(*this);
- ivarAddr = Builder.CreateBitCast(ivarAddr, bitcastType);
+ ivarAddr = ivarAddr.withElementType(bitcastType);
llvm::LoadInst *load = Builder.CreateLoad(ivarAddr, "load");
load->setAtomic(llvm::AtomicOrdering::Unordered);
@@ -1164,12 +1197,10 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
uint64_t retTySize = CGM.getDataLayout().getTypeSizeInBits(retTy);
llvm::Value *ivarVal = load;
if (ivarSize > retTySize) {
- llvm::Type *newTy = llvm::Type::getIntNTy(getLLVMContext(), retTySize);
- ivarVal = Builder.CreateTrunc(load, newTy);
- bitcastType = newTy->getPointerTo();
+ bitcastType = llvm::Type::getIntNTy(getLLVMContext(), retTySize);
+ ivarVal = Builder.CreateTrunc(load, bitcastType);
}
- Builder.CreateStore(ivarVal,
- Builder.CreateBitCast(ReturnValue, bitcastType));
+ Builder.CreateStore(ivarVal, ReturnValue.withElementType(bitcastType));
// Make sure we don't do an autorelease.
AutoreleaseResult = false;
@@ -1188,11 +1219,10 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
// Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
// FIXME: Can't this be simpler? This might even be worse than the
// corresponding gcc code.
- llvm::Value *cmd =
- Builder.CreateLoad(GetAddrOfLocalVar(getterMethod->getCmdDecl()), "cmd");
+ llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, getterMethod);
llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
- EmitIvarOffset(classImpl->getClassInterface(), ivar);
+ EmitIvarOffsetAsPointerDiff(classImpl->getClassInterface(), ivar);
CallArgList args;
args.add(RValue::get(self), getContext().getObjCIdType());
@@ -1306,7 +1336,6 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
argVar->getType().getNonReferenceType(), VK_LValue,
SourceLocation());
llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer(CGF);
- argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy);
// The third argument is the sizeof the type.
@@ -1343,7 +1372,6 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
llvm::Value *ivarAddr =
CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0)
.getPointer(CGF);
- ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
// The second argument is the address of the parameter variable.
@@ -1352,7 +1380,6 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
argVar->getType().getNonReferenceType(), VK_LValue,
SourceLocation());
llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer(CGF);
- argAddr = CGF.Builder.CreateBitCast(argAddr, CGF.Int8PtrTy);
args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy);
// Third argument is the helper function.
@@ -1404,6 +1431,24 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
ObjCMethodDecl *setterMethod = propImpl->getSetterMethodDecl();
+ if (ivar->getType().isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
+ ParmVarDecl *PVD = *setterMethod->param_begin();
+ if (!AtomicHelperFn) {
+ // Call the move assignment operator instead of calling the copy
+ // assignment operator and destructor.
+ LValue Dst = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar,
+ /*quals*/ 0);
+ LValue Src = MakeAddrLValue(GetAddrOfLocalVar(PVD), ivar->getType());
+ callCStructMoveAssignmentOperator(Dst, Src);
+ } else {
+ // If atomic, assignment is called via a locking api.
+ emitCPPObjectAtomicSetterCall(*this, setterMethod, ivar, AtomicHelperFn);
+ }
+ // Decativate the destructor for the setter parameter.
+ DeactivateCleanupBlock(CalleeDestructedParamCleanups[PVD], AllocaInsertPt);
+ return;
+ }
+
// Just use the setter expression if Sema gave us one and it's
// non-trivial.
if (!hasTrivialSetExpr(propImpl)) {
@@ -1432,15 +1477,13 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
// Currently, all atomic accesses have to be through integer
// types, so there's no point in trying to pick a prettier type.
- llvm::Type *bitcastType =
- llvm::Type::getIntNTy(getLLVMContext(),
- getContext().toBits(strategy.getIvarSize()));
+ llvm::Type *castType = llvm::Type::getIntNTy(
+ getLLVMContext(), getContext().toBits(strategy.getIvarSize()));
// Cast both arguments to the chosen operation type.
- argAddr = Builder.CreateElementBitCast(argAddr, bitcastType);
- ivarAddr = Builder.CreateElementBitCast(ivarAddr, bitcastType);
+ argAddr = argAddr.withElementType(castType);
+ ivarAddr = ivarAddr.withElementType(castType);
- // This bitcast load is likely to cause some nasty IR.
llvm::Value *load = Builder.CreateLoad(argAddr);
// Perform an atomic store. There are no memory ordering requirements.
@@ -1474,12 +1517,11 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
// Emit objc_setProperty((id) self, _cmd, offset, arg,
// <is-atomic>, <is-copy>).
- llvm::Value *cmd =
- Builder.CreateLoad(GetAddrOfLocalVar(setterMethod->getCmdDecl()));
+ llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, setterMethod);
llvm::Value *self =
Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy);
llvm::Value *ivarOffset =
- EmitIvarOffset(classImpl->getClassInterface(), ivar);
+ EmitIvarOffsetAsPointerDiff(classImpl->getClassInterface(), ivar);
Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin());
llvm::Value *arg = Builder.CreateLoad(argAddr, "arg");
arg = Builder.CreateBitCast(arg, VoidPtrTy);
@@ -1555,6 +1597,12 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
argCK = CK_AnyPointerToBlockPointerCast;
} else if (ivarRef.getType()->isPointerType()) {
argCK = CK_BitCast;
+ } else if (argLoad.getType()->isAtomicType() &&
+ !ivarRef.getType()->isAtomicType()) {
+ argCK = CK_AtomicToNonAtomic;
+ } else if (!argLoad.getType()->isAtomicType() &&
+ ivarRef.getType()->isAtomicType()) {
+ argCK = CK_NonAtomicToAtomic;
}
ImplicitCastExpr argCast(ImplicitCastExpr::OnStack, ivarRef.getType(), argCK,
&argLoad, VK_PRValue, FPOptionsOverride());
@@ -1743,12 +1791,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
&CGM.getContext().Idents.get("count")
};
Selector FastEnumSel =
- CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]);
+ CGM.getContext().Selectors.getSelector(std::size(II), &II[0]);
- QualType ItemsTy =
- getContext().getConstantArrayType(getContext().getObjCIdType(),
- llvm::APInt(32, NumItems), nullptr,
- ArrayType::Normal, 0);
+ QualType ItemsTy = getContext().getConstantArrayType(
+ getContext().getObjCIdType(), llvm::APInt(32, NumItems), nullptr,
+ ArraySizeModifier::Normal, 0);
Address ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
// Emit the collection pointer. In ARC, we do a retain.
@@ -1905,8 +1952,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Fetch the value at the current index from the buffer.
llvm::Value *CurrentItemPtr = Builder.CreateGEP(
- EnumStateItems->getType()->getPointerElementType(), EnumStateItems, index,
- "currentitem.ptr");
+ ObjCIdType, EnumStateItems, index, "currentitem.ptr");
llvm::Value *CurrentItem =
Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign());
@@ -2108,6 +2154,13 @@ static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM,
setARCRuntimeFunctionLinkage(CGM, RTF.getCallee());
}
+static llvm::Function *getARCIntrinsic(llvm::Intrinsic::ID IntID,
+ CodeGenModule &CGM) {
+ llvm::Function *fn = CGM.getIntrinsic(IntID);
+ setARCRuntimeFunctionLinkage(CGM, fn);
+ return fn;
+}
+
/// Perform an operation having the signature
/// i8* (i8*)
/// where a null input causes a no-op and returns null.
@@ -2118,10 +2171,8 @@ static llvm::Value *emitARCValueOperation(
if (isa<llvm::ConstantPointerNull>(value))
return value;
- if (!fn) {
- fn = CGF.CGM.getIntrinsic(IntID);
- setARCRuntimeFunctionLinkage(CGF.CGM, fn);
- }
+ if (!fn)
+ fn = getARCIntrinsic(IntID, CGF.CGM);
// Cast the argument to 'id'.
llvm::Type *origType = returnType ? returnType : value->getType();
@@ -2140,23 +2191,10 @@ static llvm::Value *emitARCValueOperation(
static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr,
llvm::Function *&fn,
llvm::Intrinsic::ID IntID) {
- if (!fn) {
- fn = CGF.CGM.getIntrinsic(IntID);
- setARCRuntimeFunctionLinkage(CGF.CGM, fn);
- }
-
- // Cast the argument to 'id*'.
- llvm::Type *origType = addr.getElementType();
- addr = CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy);
-
- // Call the function.
- llvm::Value *result = CGF.EmitNounwindRuntimeCall(fn, addr.getPointer());
-
- // Cast the result back to a dereference of the original type.
- if (origType != CGF.Int8PtrTy)
- result = CGF.Builder.CreateBitCast(result, origType);
+ if (!fn)
+ fn = getARCIntrinsic(IntID, CGF.CGM);
- return result;
+ return CGF.EmitNounwindRuntimeCall(fn, addr.getPointer());
}
/// Perform an operation having the following signature:
@@ -2168,10 +2206,8 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr,
bool ignored) {
assert(addr.getElementType() == value->getType());
- if (!fn) {
- fn = CGF.CGM.getIntrinsic(IntID);
- setARCRuntimeFunctionLinkage(CGF.CGM, fn);
- }
+ if (!fn)
+ fn = getARCIntrinsic(IntID, CGF.CGM);
llvm::Type *origType = value->getType();
@@ -2193,10 +2229,8 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src,
llvm::Intrinsic::ID IntID) {
assert(dst.getType() == src.getType());
- if (!fn) {
- fn = CGF.CGM.getIntrinsic(IntID);
- setARCRuntimeFunctionLinkage(CGF.CGM, fn);
- }
+ if (!fn)
+ fn = getARCIntrinsic(IntID, CGF.CGM);
llvm::Value *args[] = {
CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy),
@@ -2286,7 +2320,7 @@ llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value,
CGM.getObjCEntrypoints().objc_retainBlock);
call->setMetadata("clang.arc.copy_on_escape",
- llvm::MDNode::get(Builder.getContext(), None));
+ llvm::MDNode::get(Builder.getContext(), std::nullopt));
}
return result;
@@ -2328,7 +2362,8 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) {
// Call the marker asm if we made one, which we do only at -O0.
if (marker)
- CGF.Builder.CreateCall(marker, None, CGF.getBundlesForFunclet(marker));
+ CGF.Builder.CreateCall(marker, std::nullopt,
+ CGF.getBundlesForFunclet(marker));
}
static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
@@ -2340,13 +2375,22 @@ static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
// 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.
+ 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;
+ EP = getARCIntrinsic(IID, CGF.CGM);
+
+ llvm::Triple::ArchType Arch = CGF.CGM.getTriple().getArch();
- // FIXME: Do this when the target isn't aarch64.
+ // FIXME: Do this on all targets and at -O0 too. This can be enabled only if
+ // the target backend knows how to handle the operand bundle.
if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 &&
- CGF.CGM.getTarget().getTriple().isAArch64()) {
- llvm::Value *bundleArgs[] = {llvm::ConstantInt::get(
- CGF.Int64Ty,
- llvm::objcarc::getAttachedCallOperandBundleEnum(IsRetainRV))};
+ (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::x86_64)) {
+ llvm::Value *bundleArgs[] = {EP};
llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs);
auto *oldCall = cast<llvm::CallBase>(value);
llvm::CallBase *newCall = llvm::CallBase::addOperandBundle(
@@ -2362,13 +2406,6 @@ static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
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);
}
@@ -2401,10 +2438,8 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value,
if (isa<llvm::ConstantPointerNull>(value)) return;
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_release;
- if (!fn) {
- fn = CGM.getIntrinsic(llvm::Intrinsic::objc_release);
- setARCRuntimeFunctionLinkage(CGM, fn);
- }
+ if (!fn)
+ fn = getARCIntrinsic(llvm::Intrinsic::objc_release, CGM);
// Cast the argument to 'id'.
value = Builder.CreateBitCast(value, Int8PtrTy);
@@ -2414,7 +2449,7 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value,
if (precise == ARCImpreciseLifetime) {
call->setMetadata("clang.imprecise_release",
- llvm::MDNode::get(Builder.getContext(), None));
+ llvm::MDNode::get(Builder.getContext(), std::nullopt));
}
}
@@ -2447,10 +2482,8 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr,
assert(addr.getElementType() == value->getType());
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_storeStrong;
- if (!fn) {
- fn = CGM.getIntrinsic(llvm::Intrinsic::objc_storeStrong);
- setARCRuntimeFunctionLinkage(CGM, fn);
- }
+ if (!fn)
+ fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM);
llvm::Value *args[] = {
Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy),
@@ -2603,13 +2636,8 @@ void CodeGenFunction::EmitARCInitWeak(Address addr, llvm::Value *value) {
/// Essentially objc_storeWeak(addr, nil).
void CodeGenFunction::EmitARCDestroyWeak(Address addr) {
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_destroyWeak;
- if (!fn) {
- fn = CGM.getIntrinsic(llvm::Intrinsic::objc_destroyWeak);
- setARCRuntimeFunctionLinkage(CGM, fn);
- }
-
- // Cast the argument to 'id*'.
- addr = Builder.CreateBitCast(addr, Int8PtrPtrTy);
+ if (!fn)
+ fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM);
EmitNounwindRuntimeCall(fn, addr.getPointer());
}
@@ -2651,10 +2679,8 @@ void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr,
/// call i8* \@objc_autoreleasePoolPush(void)
llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPush;
- if (!fn) {
- fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush);
- setARCRuntimeFunctionLinkage(CGM, fn);
- }
+ if (!fn)
+ fn = getARCIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush, CGM);
return EmitNounwindRuntimeCall(fn);
}
@@ -2679,10 +2705,8 @@ void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) {
EmitRuntimeCallOrInvoke(fn, value);
} else {
llvm::FunctionCallee &fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop;
- if (!fn) {
- fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop);
- setARCRuntimeFunctionLinkage(CGM, fn);
- }
+ if (!fn)
+ fn = getARCIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop, CGM);
EmitRuntimeCall(fn, value);
}
@@ -2820,7 +2844,7 @@ void CodeGenFunction::EmitObjCRelease(llvm::Value *value,
if (precise == ARCImpreciseLifetime) {
call->setMetadata("clang.imprecise_release",
- llvm::MDNode::get(Builder.getContext(), None));
+ llvm::MDNode::get(Builder.getContext(), std::nullopt));
}
}
@@ -3344,7 +3368,8 @@ struct ARCRetainExprEmitter :
TryEmitResult result = visitExpr(e);
// Avoid the block-retain if this is a block literal that doesn't need to be
// copied to the heap.
- if (e->getBlockDecl()->canAvoidCopyToHeap())
+ if (CGF.CGM.getCodeGenOpts().ObjCAvoidHeapifyLocalBlocks &&
+ e->getBlockDecl()->canAvoidCopyToHeap())
result.setInt(true);
return result;
}
@@ -3653,7 +3678,6 @@ void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) {
/* constraints */ "r",
/* side effects */ true);
- object = Builder.CreateBitCast(object, VoidPtrTy);
EmitNounwindRuntimeCall(extender, object);
}
@@ -3664,15 +3688,27 @@ void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) {
llvm::Constant *
CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
const ObjCPropertyImplDecl *PID) {
+ const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+ if ((!(PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic)))
+ return nullptr;
+
+ QualType Ty = PID->getPropertyIvarDecl()->getType();
+ ASTContext &C = getContext();
+
+ if (Ty.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
+ // Call the move assignment operator instead of calling the copy assignment
+ // operator and destructor.
+ CharUnits Alignment = C.getTypeAlignInChars(Ty);
+ llvm::Constant *Fn = getNonTrivialCStructMoveAssignmentOperator(
+ CGM, Alignment, Alignment, Ty.isVolatileQualified(), Ty);
+ return Fn;
+ }
+
if (!getLangOpts().CPlusPlus ||
!getLangOpts().ObjCRuntime.hasAtomicCopyHelper())
return nullptr;
- QualType Ty = PID->getPropertyIvarDecl()->getType();
if (!Ty->isRecordType())
return nullptr;
- const ObjCPropertyDecl *PD = PID->getPropertyDecl();
- if ((!(PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic)))
- return nullptr;
llvm::Constant *HelperFn = nullptr;
if (hasTrivialSetExpr(PID))
return nullptr;
@@ -3680,7 +3716,6 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
if ((HelperFn = CGM.getAtomicSetterHelperFnMap(Ty)))
return HelperFn;
- ASTContext &C = getContext();
IdentifierInfo *II
= &CGM.getContext().Idents.get("__assign_helper_atomic_property_");
@@ -3697,7 +3732,7 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
FunctionDecl *FD = FunctionDecl::Create(
C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
- FunctionTy, nullptr, SC_Static, false, false);
+ FunctionTy, nullptr, SC_Static, false, false, false);
FunctionArgList args;
ParmVarDecl *Params[2];
@@ -3746,23 +3781,32 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
EmitStmt(TheCall);
FinishFunction();
- HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+ HelperFn = Fn;
CGM.setAtomicSetterHelperFnMap(Ty, HelperFn);
return HelperFn;
}
-llvm::Constant *
-CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
- const ObjCPropertyImplDecl *PID) {
+llvm::Constant *CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
+ const ObjCPropertyImplDecl *PID) {
+ const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+ if ((!(PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic)))
+ return nullptr;
+
+ QualType Ty = PD->getType();
+ ASTContext &C = getContext();
+
+ if (Ty.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
+ CharUnits Alignment = C.getTypeAlignInChars(Ty);
+ llvm::Constant *Fn = getNonTrivialCStructCopyConstructor(
+ CGM, Alignment, Alignment, Ty.isVolatileQualified(), Ty);
+ return Fn;
+ }
+
if (!getLangOpts().CPlusPlus ||
!getLangOpts().ObjCRuntime.hasAtomicCopyHelper())
return nullptr;
- const ObjCPropertyDecl *PD = PID->getPropertyDecl();
- QualType Ty = PD->getType();
if (!Ty->isRecordType())
return nullptr;
- if ((!(PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic)))
- return nullptr;
llvm::Constant *HelperFn = nullptr;
if (hasTrivialGetExpr(PID))
return nullptr;
@@ -3770,7 +3814,6 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
if ((HelperFn = CGM.getAtomicGetterHelperFnMap(Ty)))
return HelperFn;
- ASTContext &C = getContext();
IdentifierInfo *II =
&CGM.getContext().Idents.get("__copy_helper_atomic_property_");
@@ -3787,7 +3830,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
FunctionDecl *FD = FunctionDecl::Create(
C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
- FunctionTy, nullptr, SC_Static, false, false);
+ FunctionTy, nullptr, SC_Static, false, false, false);
FunctionArgList args;
ParmVarDecl *Params[2];
@@ -3847,18 +3890,17 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
SourceLocation());
RValue DV = EmitAnyExpr(&DstExpr);
- CharUnits Alignment
- = getContext().getTypeAlignInChars(TheCXXConstructExpr->getType());
+ CharUnits Alignment =
+ getContext().getTypeAlignInChars(TheCXXConstructExpr->getType());
EmitAggExpr(TheCXXConstructExpr,
- AggValueSlot::forAddr(Address(DV.getScalarVal(), Alignment),
- Qualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased,
- AggValueSlot::DoesNotOverlap));
+ AggValueSlot::forAddr(
+ Address(DV.getScalarVal(), ConvertTypeForMem(Ty), Alignment),
+ Qualifiers(), AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap));
FinishFunction();
- HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+ HelperFn = Fn;
CGM.setAtomicGetterHelperFnMap(Ty, HelperFn);
return HelperFn;
}
@@ -3899,8 +3941,12 @@ static unsigned getBaseMachOPlatformID(const llvm::Triple &TT) {
return llvm::MachO::PLATFORM_TVOS;
case llvm::Triple::WatchOS:
return llvm::MachO::PLATFORM_WATCHOS;
+ case llvm::Triple::XROS:
+ return llvm::MachO::PLATFORM_XROS;
+ case llvm::Triple::DriverKit:
+ return llvm::MachO::PLATFORM_DRIVERKIT;
default:
- return /*Unknown platform*/ 0;
+ return llvm::MachO::PLATFORM_UNKNOWN;
}
}
@@ -3913,12 +3959,13 @@ static llvm::Value *emitIsPlatformVersionAtLeast(CodeGenFunction &CGF,
llvm::SmallVector<llvm::Value *, 8> Args;
auto EmitArgs = [&](const VersionTuple &Version, const llvm::Triple &TT) {
- Optional<unsigned> Min = Version.getMinor(), SMin = Version.getSubminor();
+ std::optional<unsigned> Min = Version.getMinor(),
+ SMin = Version.getSubminor();
Args.push_back(
llvm::ConstantInt::get(CGM.Int32Ty, getBaseMachOPlatformID(TT)));
Args.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Version.getMajor()));
- Args.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Min ? *Min : 0));
- Args.push_back(llvm::ConstantInt::get(CGM.Int32Ty, SMin ? *SMin : 0));
+ Args.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Min.value_or(0)));
+ Args.push_back(llvm::ConstantInt::get(CGM.Int32Ty, SMin.value_or(0)));
};
assert(!Version.empty() && "unexpected empty version");
@@ -3951,12 +3998,12 @@ CodeGenFunction::EmitBuiltinAvailable(const VersionTuple &Version) {
CGM.CreateRuntimeFunction(FTy, "__isOSVersionAtLeast");
}
- Optional<unsigned> Min = Version.getMinor(), SMin = Version.getSubminor();
+ std::optional<unsigned> Min = Version.getMinor(),
+ SMin = Version.getSubminor();
llvm::Value *Args[] = {
llvm::ConstantInt::get(CGM.Int32Ty, Version.getMajor()),
- llvm::ConstantInt::get(CGM.Int32Ty, Min ? *Min : 0),
- llvm::ConstantInt::get(CGM.Int32Ty, SMin ? *SMin : 0),
- };
+ llvm::ConstantInt::get(CGM.Int32Ty, Min.value_or(0)),
+ llvm::ConstantInt::get(CGM.Int32Ty, SMin.value_or(0))};
llvm::Value *CallRes =
EmitNounwindRuntimeCall(CGM.IsOSVersionAtLeastFn, Args);
@@ -3979,6 +4026,12 @@ static bool isFoundationNeededForDarwinAvailabilityCheck(
case llvm::Triple::MacOSX:
FoundationDroppedInVersion = VersionTuple(/*Major=*/10, /*Minor=*/15);
break;
+ case llvm::Triple::XROS:
+ // XROS doesn't need Foundation.
+ return false;
+ case llvm::Triple::DriverKit:
+ // DriverKit doesn't need Foundation.
+ return false;
default:
llvm_unreachable("Unexpected OS");
}