diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/CodeGen/CGObjC.cpp | 397 |
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"); } |