10b57cec5SDimitry Andric //===---- CGObjC.cpp - Emit LLVM Code for Objective-C ---------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This contains code to emit Objective-C code as LLVM code. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "CGDebugInfo.h" 140b57cec5SDimitry Andric #include "CGObjCRuntime.h" 150b57cec5SDimitry Andric #include "CodeGenFunction.h" 160b57cec5SDimitry Andric #include "CodeGenModule.h" 170b57cec5SDimitry Andric #include "ConstantEmitter.h" 180b57cec5SDimitry Andric #include "TargetInfo.h" 190b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 20480093f4SDimitry Andric #include "clang/AST/Attr.h" 210b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 220b57cec5SDimitry Andric #include "clang/AST/StmtObjC.h" 230b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 240b57cec5SDimitry Andric #include "clang/CodeGen/CGFunctionInfo.h" 25bdd1243dSDimitry Andric #include "clang/CodeGen/CodeGenABITypes.h" 260b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 27fe6060f1SDimitry Andric #include "llvm/Analysis/ObjCARCUtil.h" 28e8d8bef9SDimitry Andric #include "llvm/BinaryFormat/MachO.h" 29bdd1243dSDimitry Andric #include "llvm/IR/Constants.h" 300b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 310b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h" 32bdd1243dSDimitry Andric #include <optional> 330b57cec5SDimitry Andric using namespace clang; 340b57cec5SDimitry Andric using namespace CodeGen; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult; 370b57cec5SDimitry Andric static TryEmitResult 380b57cec5SDimitry Andric tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e); 390b57cec5SDimitry Andric static RValue AdjustObjCObjectType(CodeGenFunction &CGF, 400b57cec5SDimitry Andric QualType ET, 410b57cec5SDimitry Andric RValue Result); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric /// Given the address of a variable of pointer type, find the correct 440b57cec5SDimitry Andric /// null to store into it. 450b57cec5SDimitry Andric static llvm::Constant *getNullForVariable(Address addr) { 460b57cec5SDimitry Andric llvm::Type *type = addr.getElementType(); 470b57cec5SDimitry Andric return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(type)); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric /// Emits an instance of NSConstantString representing the object. 510b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) 520b57cec5SDimitry Andric { 530b57cec5SDimitry Andric llvm::Constant *C = 540b57cec5SDimitry Andric CGM.getObjCRuntime().GenerateConstantString(E->getString()).getPointer(); 555f757f3fSDimitry Andric return C; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric /// EmitObjCBoxedExpr - This routine generates code to call 590b57cec5SDimitry Andric /// the appropriate expression boxing method. This will either be 600b57cec5SDimitry Andric /// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:], 610b57cec5SDimitry Andric /// or [NSValue valueWithBytes:objCType:]. 620b57cec5SDimitry Andric /// 630b57cec5SDimitry Andric llvm::Value * 640b57cec5SDimitry Andric CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { 650b57cec5SDimitry Andric // Generate the correct selector for this literal's concrete type. 660b57cec5SDimitry Andric // Get the method. 670b57cec5SDimitry Andric const ObjCMethodDecl *BoxingMethod = E->getBoxingMethod(); 680b57cec5SDimitry Andric const Expr *SubExpr = E->getSubExpr(); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric if (E->isExpressibleAsConstantInitializer()) { 710b57cec5SDimitry Andric ConstantEmitter ConstEmitter(CGM); 720b57cec5SDimitry Andric return ConstEmitter.tryEmitAbstract(E, E->getType()); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric assert(BoxingMethod->isClassMethod() && "BoxingMethod must be a class method"); 760b57cec5SDimitry Andric Selector Sel = BoxingMethod->getSelector(); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // Generate a reference to the class pointer, which will be the receiver. 790b57cec5SDimitry Andric // Assumes that the method was introduced in the class that should be 800b57cec5SDimitry Andric // messaged (avoids pulling it out of the result type). 810b57cec5SDimitry Andric CGObjCRuntime &Runtime = CGM.getObjCRuntime(); 820b57cec5SDimitry Andric const ObjCInterfaceDecl *ClassDecl = BoxingMethod->getClassInterface(); 830b57cec5SDimitry Andric llvm::Value *Receiver = Runtime.GetClass(*this, ClassDecl); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric CallArgList Args; 860b57cec5SDimitry Andric const ParmVarDecl *ArgDecl = *BoxingMethod->param_begin(); 870b57cec5SDimitry Andric QualType ArgQT = ArgDecl->getType().getUnqualifiedType(); 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric // ObjCBoxedExpr supports boxing of structs and unions 900b57cec5SDimitry Andric // via [NSValue valueWithBytes:objCType:] 910b57cec5SDimitry Andric const QualType ValueType(SubExpr->getType().getCanonicalType()); 920b57cec5SDimitry Andric if (ValueType->isObjCBoxableRecordType()) { 930b57cec5SDimitry Andric // Emit CodeGen for first parameter 940b57cec5SDimitry Andric // and cast value to correct type 950b57cec5SDimitry Andric Address Temporary = CreateMemTemp(SubExpr->getType()); 960b57cec5SDimitry Andric EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true); 97*0fca6ea1SDimitry Andric llvm::Value *BitCast = Builder.CreateBitCast( 98*0fca6ea1SDimitry Andric Temporary.emitRawPointer(*this), ConvertType(ArgQT)); 9981ad6265SDimitry Andric Args.add(RValue::get(BitCast), ArgQT); 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric // Create char array to store type encoding 1020b57cec5SDimitry Andric std::string Str; 1030b57cec5SDimitry Andric getContext().getObjCEncodingForType(ValueType, Str); 1040b57cec5SDimitry Andric llvm::Constant *GV = CGM.GetAddrOfConstantCString(Str).getPointer(); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // Cast type encoding to correct type 1070b57cec5SDimitry Andric const ParmVarDecl *EncodingDecl = BoxingMethod->parameters()[1]; 1080b57cec5SDimitry Andric QualType EncodingQT = EncodingDecl->getType().getUnqualifiedType(); 1090b57cec5SDimitry Andric llvm::Value *Cast = Builder.CreateBitCast(GV, ConvertType(EncodingQT)); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric Args.add(RValue::get(Cast), EncodingQT); 1120b57cec5SDimitry Andric } else { 1130b57cec5SDimitry Andric Args.add(EmitAnyExpr(SubExpr), ArgQT); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric RValue result = Runtime.GenerateMessageSend( 1170b57cec5SDimitry Andric *this, ReturnValueSlot(), BoxingMethod->getReturnType(), Sel, Receiver, 1180b57cec5SDimitry Andric Args, ClassDecl, BoxingMethod); 1190b57cec5SDimitry Andric return Builder.CreateBitCast(result.getScalarVal(), 1200b57cec5SDimitry Andric ConvertType(E->getType())); 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, 1240b57cec5SDimitry Andric const ObjCMethodDecl *MethodWithObjects) { 1250b57cec5SDimitry Andric ASTContext &Context = CGM.getContext(); 1260b57cec5SDimitry Andric const ObjCDictionaryLiteral *DLE = nullptr; 1270b57cec5SDimitry Andric const ObjCArrayLiteral *ALE = dyn_cast<ObjCArrayLiteral>(E); 1280b57cec5SDimitry Andric if (!ALE) 1290b57cec5SDimitry Andric DLE = cast<ObjCDictionaryLiteral>(E); 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric // Optimize empty collections by referencing constants, when available. 1320b57cec5SDimitry Andric uint64_t NumElements = 1330b57cec5SDimitry Andric ALE ? ALE->getNumElements() : DLE->getNumElements(); 1340b57cec5SDimitry Andric if (NumElements == 0 && CGM.getLangOpts().ObjCRuntime.hasEmptyCollections()) { 1350b57cec5SDimitry Andric StringRef ConstantName = ALE ? "__NSArray0__" : "__NSDictionary0__"; 1360b57cec5SDimitry Andric QualType IdTy(CGM.getContext().getObjCIdType()); 1370b57cec5SDimitry Andric llvm::Constant *Constant = 1380b57cec5SDimitry Andric CGM.CreateRuntimeVariable(ConvertType(IdTy), ConstantName); 1390b57cec5SDimitry Andric LValue LV = MakeNaturalAlignAddrLValue(Constant, IdTy); 1400b57cec5SDimitry Andric llvm::Value *Ptr = EmitLoadOfScalar(LV, E->getBeginLoc()); 1410b57cec5SDimitry Andric cast<llvm::LoadInst>(Ptr)->setMetadata( 14206c3fb27SDimitry Andric llvm::LLVMContext::MD_invariant_load, 143bdd1243dSDimitry Andric llvm::MDNode::get(getLLVMContext(), std::nullopt)); 1440b57cec5SDimitry Andric return Builder.CreateBitCast(Ptr, ConvertType(E->getType())); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric // Compute the type of the array we're initializing. 1480b57cec5SDimitry Andric llvm::APInt APNumElements(Context.getTypeSize(Context.getSizeType()), 1490b57cec5SDimitry Andric NumElements); 1500b57cec5SDimitry Andric QualType ElementType = Context.getObjCIdType().withConst(); 1515f757f3fSDimitry Andric QualType ElementArrayType = Context.getConstantArrayType( 1525f757f3fSDimitry Andric ElementType, APNumElements, nullptr, ArraySizeModifier::Normal, 1535f757f3fSDimitry Andric /*IndexTypeQuals=*/0); 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric // Allocate the temporary array(s). 1560b57cec5SDimitry Andric Address Objects = CreateMemTemp(ElementArrayType, "objects"); 1570b57cec5SDimitry Andric Address Keys = Address::invalid(); 1580b57cec5SDimitry Andric if (DLE) 1590b57cec5SDimitry Andric Keys = CreateMemTemp(ElementArrayType, "keys"); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric // In ARC, we may need to do extra work to keep all the keys and 1620b57cec5SDimitry Andric // values alive until after the call. 1630b57cec5SDimitry Andric SmallVector<llvm::Value *, 16> NeededObjects; 1640b57cec5SDimitry Andric bool TrackNeededObjects = 1650b57cec5SDimitry Andric (getLangOpts().ObjCAutoRefCount && 1660b57cec5SDimitry Andric CGM.getCodeGenOpts().OptimizationLevel != 0); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric // Perform the actual initialialization of the array(s). 1690b57cec5SDimitry Andric for (uint64_t i = 0; i < NumElements; i++) { 1700b57cec5SDimitry Andric if (ALE) { 1710b57cec5SDimitry Andric // Emit the element and store it to the appropriate array slot. 1720b57cec5SDimitry Andric const Expr *Rhs = ALE->getElement(i); 1730b57cec5SDimitry Andric LValue LV = MakeAddrLValue(Builder.CreateConstArrayGEP(Objects, i), 1740b57cec5SDimitry Andric ElementType, AlignmentSource::Decl); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric llvm::Value *value = EmitScalarExpr(Rhs); 1770b57cec5SDimitry Andric EmitStoreThroughLValue(RValue::get(value), LV, true); 1780b57cec5SDimitry Andric if (TrackNeededObjects) { 1790b57cec5SDimitry Andric NeededObjects.push_back(value); 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric } else { 1820b57cec5SDimitry Andric // Emit the key and store it to the appropriate array slot. 1830b57cec5SDimitry Andric const Expr *Key = DLE->getKeyValueElement(i).Key; 1840b57cec5SDimitry Andric LValue KeyLV = MakeAddrLValue(Builder.CreateConstArrayGEP(Keys, i), 1850b57cec5SDimitry Andric ElementType, AlignmentSource::Decl); 1860b57cec5SDimitry Andric llvm::Value *keyValue = EmitScalarExpr(Key); 1870b57cec5SDimitry Andric EmitStoreThroughLValue(RValue::get(keyValue), KeyLV, /*isInit=*/true); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric // Emit the value and store it to the appropriate array slot. 1900b57cec5SDimitry Andric const Expr *Value = DLE->getKeyValueElement(i).Value; 1910b57cec5SDimitry Andric LValue ValueLV = MakeAddrLValue(Builder.CreateConstArrayGEP(Objects, i), 1920b57cec5SDimitry Andric ElementType, AlignmentSource::Decl); 1930b57cec5SDimitry Andric llvm::Value *valueValue = EmitScalarExpr(Value); 1940b57cec5SDimitry Andric EmitStoreThroughLValue(RValue::get(valueValue), ValueLV, /*isInit=*/true); 1950b57cec5SDimitry Andric if (TrackNeededObjects) { 1960b57cec5SDimitry Andric NeededObjects.push_back(keyValue); 1970b57cec5SDimitry Andric NeededObjects.push_back(valueValue); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // Generate the argument list. 2030b57cec5SDimitry Andric CallArgList Args; 2040b57cec5SDimitry Andric ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin(); 2050b57cec5SDimitry Andric const ParmVarDecl *argDecl = *PI++; 2060b57cec5SDimitry Andric QualType ArgQT = argDecl->getType().getUnqualifiedType(); 207*0fca6ea1SDimitry Andric Args.add(RValue::get(Objects, *this), ArgQT); 2080b57cec5SDimitry Andric if (DLE) { 2090b57cec5SDimitry Andric argDecl = *PI++; 2100b57cec5SDimitry Andric ArgQT = argDecl->getType().getUnqualifiedType(); 211*0fca6ea1SDimitry Andric Args.add(RValue::get(Keys, *this), ArgQT); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric argDecl = *PI; 2140b57cec5SDimitry Andric ArgQT = argDecl->getType().getUnqualifiedType(); 2150b57cec5SDimitry Andric llvm::Value *Count = 2160b57cec5SDimitry Andric llvm::ConstantInt::get(CGM.getTypes().ConvertType(ArgQT), NumElements); 2170b57cec5SDimitry Andric Args.add(RValue::get(Count), ArgQT); 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric // Generate a reference to the class pointer, which will be the receiver. 2200b57cec5SDimitry Andric Selector Sel = MethodWithObjects->getSelector(); 2210b57cec5SDimitry Andric QualType ResultType = E->getType(); 2220b57cec5SDimitry Andric const ObjCObjectPointerType *InterfacePointerType 2230b57cec5SDimitry Andric = ResultType->getAsObjCInterfacePointerType(); 2245f757f3fSDimitry Andric assert(InterfacePointerType && "Unexpected InterfacePointerType - null"); 2250b57cec5SDimitry Andric ObjCInterfaceDecl *Class 2260b57cec5SDimitry Andric = InterfacePointerType->getObjectType()->getInterface(); 2270b57cec5SDimitry Andric CGObjCRuntime &Runtime = CGM.getObjCRuntime(); 2280b57cec5SDimitry Andric llvm::Value *Receiver = Runtime.GetClass(*this, Class); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric // Generate the message send. 2310b57cec5SDimitry Andric RValue result = Runtime.GenerateMessageSend( 2320b57cec5SDimitry Andric *this, ReturnValueSlot(), MethodWithObjects->getReturnType(), Sel, 2330b57cec5SDimitry Andric Receiver, Args, Class, MethodWithObjects); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric // The above message send needs these objects, but in ARC they are 2360b57cec5SDimitry Andric // passed in a buffer that is essentially __unsafe_unretained. 2370b57cec5SDimitry Andric // Therefore we must prevent the optimizer from releasing them until 2380b57cec5SDimitry Andric // after the call. 2390b57cec5SDimitry Andric if (TrackNeededObjects) { 2400b57cec5SDimitry Andric EmitARCIntrinsicUse(NeededObjects); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric return Builder.CreateBitCast(result.getScalarVal(), 2440b57cec5SDimitry Andric ConvertType(E->getType())); 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCArrayLiteral(const ObjCArrayLiteral *E) { 2480b57cec5SDimitry Andric return EmitObjCCollectionLiteral(E, E->getArrayWithObjectsMethod()); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCDictionaryLiteral( 2520b57cec5SDimitry Andric const ObjCDictionaryLiteral *E) { 2530b57cec5SDimitry Andric return EmitObjCCollectionLiteral(E, E->getDictWithObjectsMethod()); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric /// Emit a selector. 2570b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) { 2580b57cec5SDimitry Andric // Untyped selector. 2590b57cec5SDimitry Andric // Note that this implementation allows for non-constant strings to be passed 2600b57cec5SDimitry Andric // as arguments to @selector(). Currently, the only thing preventing this 2610b57cec5SDimitry Andric // behaviour is the type checking in the front end. 2620b57cec5SDimitry Andric return CGM.getObjCRuntime().GetSelector(*this, E->getSelector()); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) { 2660b57cec5SDimitry Andric // FIXME: This should pass the Decl not the name. 2670b57cec5SDimitry Andric return CGM.getObjCRuntime().GenerateProtocolRef(*this, E->getProtocol()); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric /// Adjust the type of an Objective-C object that doesn't match up due 2710b57cec5SDimitry Andric /// to type erasure at various points, e.g., related result types or the use 2720b57cec5SDimitry Andric /// of parameterized classes. 2730b57cec5SDimitry Andric static RValue AdjustObjCObjectType(CodeGenFunction &CGF, QualType ExpT, 2740b57cec5SDimitry Andric RValue Result) { 2750b57cec5SDimitry Andric if (!ExpT->isObjCRetainableType()) 2760b57cec5SDimitry Andric return Result; 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric // If the converted types are the same, we're done. 2790b57cec5SDimitry Andric llvm::Type *ExpLLVMTy = CGF.ConvertType(ExpT); 2800b57cec5SDimitry Andric if (ExpLLVMTy == Result.getScalarVal()->getType()) 2810b57cec5SDimitry Andric return Result; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric // We have applied a substitution. Cast the rvalue appropriately. 2840b57cec5SDimitry Andric return RValue::get(CGF.Builder.CreateBitCast(Result.getScalarVal(), 2850b57cec5SDimitry Andric ExpLLVMTy)); 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric /// Decide whether to extend the lifetime of the receiver of a 2890b57cec5SDimitry Andric /// returns-inner-pointer message. 2900b57cec5SDimitry Andric static bool 2910b57cec5SDimitry Andric shouldExtendReceiverForInnerPointerMessage(const ObjCMessageExpr *message) { 2920b57cec5SDimitry Andric switch (message->getReceiverKind()) { 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric // For a normal instance message, we should extend unless the 2950b57cec5SDimitry Andric // receiver is loaded from a variable with precise lifetime. 2960b57cec5SDimitry Andric case ObjCMessageExpr::Instance: { 2970b57cec5SDimitry Andric const Expr *receiver = message->getInstanceReceiver(); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric // Look through OVEs. 3000b57cec5SDimitry Andric if (auto opaque = dyn_cast<OpaqueValueExpr>(receiver)) { 3010b57cec5SDimitry Andric if (opaque->getSourceExpr()) 3020b57cec5SDimitry Andric receiver = opaque->getSourceExpr()->IgnoreParens(); 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(receiver); 3060b57cec5SDimitry Andric if (!ice || ice->getCastKind() != CK_LValueToRValue) return true; 3070b57cec5SDimitry Andric receiver = ice->getSubExpr()->IgnoreParens(); 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric // Look through OVEs. 3100b57cec5SDimitry Andric if (auto opaque = dyn_cast<OpaqueValueExpr>(receiver)) { 3110b57cec5SDimitry Andric if (opaque->getSourceExpr()) 3120b57cec5SDimitry Andric receiver = opaque->getSourceExpr()->IgnoreParens(); 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric // Only __strong variables. 3160b57cec5SDimitry Andric if (receiver->getType().getObjCLifetime() != Qualifiers::OCL_Strong) 3170b57cec5SDimitry Andric return true; 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric // All ivars and fields have precise lifetime. 3200b57cec5SDimitry Andric if (isa<MemberExpr>(receiver) || isa<ObjCIvarRefExpr>(receiver)) 3210b57cec5SDimitry Andric return false; 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric // Otherwise, check for variables. 3240b57cec5SDimitry Andric const DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(ice->getSubExpr()); 3250b57cec5SDimitry Andric if (!declRef) return true; 3260b57cec5SDimitry Andric const VarDecl *var = dyn_cast<VarDecl>(declRef->getDecl()); 3270b57cec5SDimitry Andric if (!var) return true; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric // All variables have precise lifetime except local variables with 3300b57cec5SDimitry Andric // automatic storage duration that aren't specially marked. 3310b57cec5SDimitry Andric return (var->hasLocalStorage() && 3320b57cec5SDimitry Andric !var->hasAttr<ObjCPreciseLifetimeAttr>()); 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric case ObjCMessageExpr::Class: 3360b57cec5SDimitry Andric case ObjCMessageExpr::SuperClass: 3370b57cec5SDimitry Andric // It's never necessary for class objects. 3380b57cec5SDimitry Andric return false; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric case ObjCMessageExpr::SuperInstance: 3410b57cec5SDimitry Andric // We generally assume that 'self' lives throughout a method call. 3420b57cec5SDimitry Andric return false; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric llvm_unreachable("invalid receiver kind"); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric /// Given an expression of ObjC pointer type, check whether it was 3490b57cec5SDimitry Andric /// immediately loaded from an ARC __weak l-value. 3500b57cec5SDimitry Andric static const Expr *findWeakLValue(const Expr *E) { 3510b57cec5SDimitry Andric assert(E->getType()->isObjCRetainableType()); 3520b57cec5SDimitry Andric E = E->IgnoreParens(); 3530b57cec5SDimitry Andric if (auto CE = dyn_cast<CastExpr>(E)) { 3540b57cec5SDimitry Andric if (CE->getCastKind() == CK_LValueToRValue) { 3550b57cec5SDimitry Andric if (CE->getSubExpr()->getType().getObjCLifetime() == Qualifiers::OCL_Weak) 3560b57cec5SDimitry Andric return CE->getSubExpr(); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric return nullptr; 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric /// The ObjC runtime may provide entrypoints that are likely to be faster 3640b57cec5SDimitry Andric /// than an ordinary message send of the appropriate selector. 3650b57cec5SDimitry Andric /// 3660b57cec5SDimitry Andric /// The entrypoints are guaranteed to be equivalent to just sending the 3670b57cec5SDimitry Andric /// corresponding message. If the entrypoint is implemented naively as just a 3680b57cec5SDimitry Andric /// message send, using it is a trade-off: it sacrifices a few cycles of 3690b57cec5SDimitry Andric /// overhead to save a small amount of code. However, it's possible for 3700b57cec5SDimitry Andric /// runtimes to detect and special-case classes that use "standard" 3710b57cec5SDimitry Andric /// behavior; if that's dynamically a large proportion of all objects, using 3720b57cec5SDimitry Andric /// the entrypoint will also be faster than using a message send. 3730b57cec5SDimitry Andric /// 3740b57cec5SDimitry Andric /// If the runtime does support a required entrypoint, then this method will 3750b57cec5SDimitry Andric /// generate a call and return the resulting value. Otherwise it will return 376bdd1243dSDimitry Andric /// std::nullopt and the caller can generate a msgSend instead. 377bdd1243dSDimitry Andric static std::optional<llvm::Value *> tryGenerateSpecializedMessageSend( 378bdd1243dSDimitry Andric CodeGenFunction &CGF, QualType ResultType, llvm::Value *Receiver, 379bdd1243dSDimitry Andric const CallArgList &Args, Selector Sel, const ObjCMethodDecl *method, 3800b57cec5SDimitry Andric bool isClassMessage) { 3810b57cec5SDimitry Andric auto &CGM = CGF.CGM; 3820b57cec5SDimitry Andric if (!CGM.getCodeGenOpts().ObjCConvertMessagesToRuntimeCalls) 383bdd1243dSDimitry Andric return std::nullopt; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric auto &Runtime = CGM.getLangOpts().ObjCRuntime; 3860b57cec5SDimitry Andric switch (Sel.getMethodFamily()) { 3870b57cec5SDimitry Andric case OMF_alloc: 3880b57cec5SDimitry Andric if (isClassMessage && 3890b57cec5SDimitry Andric Runtime.shouldUseRuntimeFunctionsForAlloc() && 3900b57cec5SDimitry Andric ResultType->isObjCObjectPointerType()) { 3910b57cec5SDimitry Andric // [Foo alloc] -> objc_alloc(Foo) or 3920b57cec5SDimitry Andric // [self alloc] -> objc_alloc(self) 3930b57cec5SDimitry Andric if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "alloc") 3940b57cec5SDimitry Andric return CGF.EmitObjCAlloc(Receiver, CGF.ConvertType(ResultType)); 3950b57cec5SDimitry Andric // [Foo allocWithZone:nil] -> objc_allocWithZone(Foo) or 3960b57cec5SDimitry Andric // [self allocWithZone:nil] -> objc_allocWithZone(self) 3970b57cec5SDimitry Andric if (Sel.isKeywordSelector() && Sel.getNumArgs() == 1 && 3980b57cec5SDimitry Andric Args.size() == 1 && Args.front().getType()->isPointerType() && 3990b57cec5SDimitry Andric Sel.getNameForSlot(0) == "allocWithZone") { 4000b57cec5SDimitry Andric const llvm::Value* arg = Args.front().getKnownRValue().getScalarVal(); 4010b57cec5SDimitry Andric if (isa<llvm::ConstantPointerNull>(arg)) 4020b57cec5SDimitry Andric return CGF.EmitObjCAllocWithZone(Receiver, 4030b57cec5SDimitry Andric CGF.ConvertType(ResultType)); 404bdd1243dSDimitry Andric return std::nullopt; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric break; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric case OMF_autorelease: 4100b57cec5SDimitry Andric if (ResultType->isObjCObjectPointerType() && 4110b57cec5SDimitry Andric CGM.getLangOpts().getGC() == LangOptions::NonGC && 4120b57cec5SDimitry Andric Runtime.shouldUseARCFunctionsForRetainRelease()) 4130b57cec5SDimitry Andric return CGF.EmitObjCAutorelease(Receiver, CGF.ConvertType(ResultType)); 4140b57cec5SDimitry Andric break; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric case OMF_retain: 4170b57cec5SDimitry Andric if (ResultType->isObjCObjectPointerType() && 4180b57cec5SDimitry Andric CGM.getLangOpts().getGC() == LangOptions::NonGC && 4190b57cec5SDimitry Andric Runtime.shouldUseARCFunctionsForRetainRelease()) 4200b57cec5SDimitry Andric return CGF.EmitObjCRetainNonBlock(Receiver, CGF.ConvertType(ResultType)); 4210b57cec5SDimitry Andric break; 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric case OMF_release: 4240b57cec5SDimitry Andric if (ResultType->isVoidType() && 4250b57cec5SDimitry Andric CGM.getLangOpts().getGC() == LangOptions::NonGC && 4260b57cec5SDimitry Andric Runtime.shouldUseARCFunctionsForRetainRelease()) { 4270b57cec5SDimitry Andric CGF.EmitObjCRelease(Receiver, ARCPreciseLifetime); 4280b57cec5SDimitry Andric return nullptr; 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric break; 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric default: 4330b57cec5SDimitry Andric break; 4340b57cec5SDimitry Andric } 435bdd1243dSDimitry Andric return std::nullopt; 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric 438480093f4SDimitry Andric CodeGen::RValue CGObjCRuntime::GeneratePossiblySpecializedMessageSend( 439480093f4SDimitry Andric CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, 440480093f4SDimitry Andric Selector Sel, llvm::Value *Receiver, const CallArgList &Args, 441480093f4SDimitry Andric const ObjCInterfaceDecl *OID, const ObjCMethodDecl *Method, 442480093f4SDimitry Andric bool isClassMessage) { 443bdd1243dSDimitry Andric if (std::optional<llvm::Value *> SpecializedResult = 444480093f4SDimitry Andric tryGenerateSpecializedMessageSend(CGF, ResultType, Receiver, Args, 445480093f4SDimitry Andric Sel, Method, isClassMessage)) { 44681ad6265SDimitry Andric return RValue::get(*SpecializedResult); 447480093f4SDimitry Andric } 448480093f4SDimitry Andric return GenerateMessageSend(CGF, Return, ResultType, Sel, Receiver, Args, OID, 449480093f4SDimitry Andric Method); 450480093f4SDimitry Andric } 451480093f4SDimitry Andric 452e8d8bef9SDimitry Andric static void AppendFirstImpliedRuntimeProtocols( 453e8d8bef9SDimitry Andric const ObjCProtocolDecl *PD, 454e8d8bef9SDimitry Andric llvm::UniqueVector<const ObjCProtocolDecl *> &PDs) { 455e8d8bef9SDimitry Andric if (!PD->isNonRuntimeProtocol()) { 456e8d8bef9SDimitry Andric const auto *Can = PD->getCanonicalDecl(); 457e8d8bef9SDimitry Andric PDs.insert(Can); 458e8d8bef9SDimitry Andric return; 459e8d8bef9SDimitry Andric } 460e8d8bef9SDimitry Andric 461e8d8bef9SDimitry Andric for (const auto *ParentPD : PD->protocols()) 462e8d8bef9SDimitry Andric AppendFirstImpliedRuntimeProtocols(ParentPD, PDs); 463e8d8bef9SDimitry Andric } 464e8d8bef9SDimitry Andric 465e8d8bef9SDimitry Andric std::vector<const ObjCProtocolDecl *> 466e8d8bef9SDimitry Andric CGObjCRuntime::GetRuntimeProtocolList(ObjCProtocolDecl::protocol_iterator begin, 467e8d8bef9SDimitry Andric ObjCProtocolDecl::protocol_iterator end) { 468e8d8bef9SDimitry Andric std::vector<const ObjCProtocolDecl *> RuntimePds; 469e8d8bef9SDimitry Andric llvm::DenseSet<const ObjCProtocolDecl *> NonRuntimePDs; 470e8d8bef9SDimitry Andric 471e8d8bef9SDimitry Andric for (; begin != end; ++begin) { 472e8d8bef9SDimitry Andric const auto *It = *begin; 473e8d8bef9SDimitry Andric const auto *Can = It->getCanonicalDecl(); 474e8d8bef9SDimitry Andric if (Can->isNonRuntimeProtocol()) 475e8d8bef9SDimitry Andric NonRuntimePDs.insert(Can); 476e8d8bef9SDimitry Andric else 477e8d8bef9SDimitry Andric RuntimePds.push_back(Can); 478e8d8bef9SDimitry Andric } 479e8d8bef9SDimitry Andric 480e8d8bef9SDimitry Andric // If there are no non-runtime protocols then we can just stop now. 481e8d8bef9SDimitry Andric if (NonRuntimePDs.empty()) 482e8d8bef9SDimitry Andric return RuntimePds; 483e8d8bef9SDimitry Andric 484e8d8bef9SDimitry Andric // Else we have to search through the non-runtime protocol's inheritancy 485e8d8bef9SDimitry Andric // hierarchy DAG stopping whenever a branch either finds a runtime protocol or 486e8d8bef9SDimitry Andric // a non-runtime protocol without any parents. These are the "first-implied" 487e8d8bef9SDimitry Andric // protocols from a non-runtime protocol. 488e8d8bef9SDimitry Andric llvm::UniqueVector<const ObjCProtocolDecl *> FirstImpliedProtos; 489e8d8bef9SDimitry Andric for (const auto *PD : NonRuntimePDs) 490e8d8bef9SDimitry Andric AppendFirstImpliedRuntimeProtocols(PD, FirstImpliedProtos); 491e8d8bef9SDimitry Andric 492e8d8bef9SDimitry Andric // Walk the Runtime list to get all protocols implied via the inclusion of 493e8d8bef9SDimitry Andric // this protocol, e.g. all protocols it inherits from including itself. 494e8d8bef9SDimitry Andric llvm::DenseSet<const ObjCProtocolDecl *> AllImpliedProtocols; 495e8d8bef9SDimitry Andric for (const auto *PD : RuntimePds) { 496e8d8bef9SDimitry Andric const auto *Can = PD->getCanonicalDecl(); 497e8d8bef9SDimitry Andric AllImpliedProtocols.insert(Can); 498e8d8bef9SDimitry Andric Can->getImpliedProtocols(AllImpliedProtocols); 499e8d8bef9SDimitry Andric } 500e8d8bef9SDimitry Andric 501e8d8bef9SDimitry Andric // Similar to above, walk the list of first-implied protocols to find the set 502e8d8bef9SDimitry Andric // all the protocols implied excluding the listed protocols themselves since 503e8d8bef9SDimitry Andric // they are not yet a part of the `RuntimePds` list. 504e8d8bef9SDimitry Andric for (const auto *PD : FirstImpliedProtos) { 505e8d8bef9SDimitry Andric PD->getImpliedProtocols(AllImpliedProtocols); 506e8d8bef9SDimitry Andric } 507e8d8bef9SDimitry Andric 508e8d8bef9SDimitry Andric // From the first-implied list we have to finish building the final protocol 509e8d8bef9SDimitry Andric // list. If a protocol in the first-implied list was already implied via some 510e8d8bef9SDimitry Andric // inheritance path through some other protocols then it would be redundant to 511e8d8bef9SDimitry Andric // add it here and so we skip over it. 512e8d8bef9SDimitry Andric for (const auto *PD : FirstImpliedProtos) { 513e8d8bef9SDimitry Andric if (!AllImpliedProtocols.contains(PD)) { 514e8d8bef9SDimitry Andric RuntimePds.push_back(PD); 515e8d8bef9SDimitry Andric } 516e8d8bef9SDimitry Andric } 517e8d8bef9SDimitry Andric 518e8d8bef9SDimitry Andric return RuntimePds; 519e8d8bef9SDimitry Andric } 520e8d8bef9SDimitry Andric 5210b57cec5SDimitry Andric /// Instead of '[[MyClass alloc] init]', try to generate 5220b57cec5SDimitry Andric /// 'objc_alloc_init(MyClass)'. This provides a code size improvement on the 5230b57cec5SDimitry Andric /// caller side, as well as the optimized objc_alloc. 524bdd1243dSDimitry Andric static std::optional<llvm::Value *> 5250b57cec5SDimitry Andric tryEmitSpecializedAllocInit(CodeGenFunction &CGF, const ObjCMessageExpr *OME) { 5260b57cec5SDimitry Andric auto &Runtime = CGF.getLangOpts().ObjCRuntime; 5270b57cec5SDimitry Andric if (!Runtime.shouldUseRuntimeFunctionForCombinedAllocInit()) 528bdd1243dSDimitry Andric return std::nullopt; 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric // Match the exact pattern '[[MyClass alloc] init]'. 5310b57cec5SDimitry Andric Selector Sel = OME->getSelector(); 5320b57cec5SDimitry Andric if (OME->getReceiverKind() != ObjCMessageExpr::Instance || 5330b57cec5SDimitry Andric !OME->getType()->isObjCObjectPointerType() || !Sel.isUnarySelector() || 5340b57cec5SDimitry Andric Sel.getNameForSlot(0) != "init") 535bdd1243dSDimitry Andric return std::nullopt; 5360b57cec5SDimitry Andric 537480093f4SDimitry Andric // Okay, this is '[receiver init]', check if 'receiver' is '[cls alloc]' 538480093f4SDimitry Andric // with 'cls' a Class. 5390b57cec5SDimitry Andric auto *SubOME = 5400b57cec5SDimitry Andric dyn_cast<ObjCMessageExpr>(OME->getInstanceReceiver()->IgnoreParenCasts()); 5410b57cec5SDimitry Andric if (!SubOME) 542bdd1243dSDimitry Andric return std::nullopt; 5430b57cec5SDimitry Andric Selector SubSel = SubOME->getSelector(); 5440b57cec5SDimitry Andric 545480093f4SDimitry Andric if (!SubOME->getType()->isObjCObjectPointerType() || 5460b57cec5SDimitry Andric !SubSel.isUnarySelector() || SubSel.getNameForSlot(0) != "alloc") 547bdd1243dSDimitry Andric return std::nullopt; 5480b57cec5SDimitry Andric 549480093f4SDimitry Andric llvm::Value *Receiver = nullptr; 550480093f4SDimitry Andric switch (SubOME->getReceiverKind()) { 551480093f4SDimitry Andric case ObjCMessageExpr::Instance: 552480093f4SDimitry Andric if (!SubOME->getInstanceReceiver()->getType()->isObjCClassType()) 553bdd1243dSDimitry Andric return std::nullopt; 554480093f4SDimitry Andric Receiver = CGF.EmitScalarExpr(SubOME->getInstanceReceiver()); 555480093f4SDimitry Andric break; 556480093f4SDimitry Andric 557480093f4SDimitry Andric case ObjCMessageExpr::Class: { 5580b57cec5SDimitry Andric QualType ReceiverType = SubOME->getClassReceiver(); 559480093f4SDimitry Andric const ObjCObjectType *ObjTy = ReceiverType->castAs<ObjCObjectType>(); 5600b57cec5SDimitry Andric const ObjCInterfaceDecl *ID = ObjTy->getInterface(); 5610b57cec5SDimitry Andric assert(ID && "null interface should be impossible here"); 5620b57cec5SDimitry Andric Receiver = CGF.CGM.getObjCRuntime().GetClass(CGF, ID); 563480093f4SDimitry Andric break; 5640b57cec5SDimitry Andric } 565480093f4SDimitry Andric case ObjCMessageExpr::SuperInstance: 566480093f4SDimitry Andric case ObjCMessageExpr::SuperClass: 567bdd1243dSDimitry Andric return std::nullopt; 568480093f4SDimitry Andric } 569480093f4SDimitry Andric 5700b57cec5SDimitry Andric return CGF.EmitObjCAllocInit(Receiver, CGF.ConvertType(OME->getType())); 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, 5740b57cec5SDimitry Andric ReturnValueSlot Return) { 5750b57cec5SDimitry Andric // Only the lookup mechanism and first two arguments of the method 5760b57cec5SDimitry Andric // implementation vary between runtimes. We can get the receiver and 5770b57cec5SDimitry Andric // arguments in generic code. 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric bool isDelegateInit = E->isDelegateInitCall(); 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric const ObjCMethodDecl *method = E->getMethodDecl(); 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric // If the method is -retain, and the receiver's being loaded from 5840b57cec5SDimitry Andric // a __weak variable, peephole the entire operation to objc_loadWeakRetained. 5850b57cec5SDimitry Andric if (method && E->getReceiverKind() == ObjCMessageExpr::Instance && 5860b57cec5SDimitry Andric method->getMethodFamily() == OMF_retain) { 5870b57cec5SDimitry Andric if (auto lvalueExpr = findWeakLValue(E->getInstanceReceiver())) { 5880b57cec5SDimitry Andric LValue lvalue = EmitLValue(lvalueExpr); 589*0fca6ea1SDimitry Andric llvm::Value *result = EmitARCLoadWeakRetained(lvalue.getAddress()); 5900b57cec5SDimitry Andric return AdjustObjCObjectType(*this, E->getType(), RValue::get(result)); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 594bdd1243dSDimitry Andric if (std::optional<llvm::Value *> Val = tryEmitSpecializedAllocInit(*this, E)) 5950b57cec5SDimitry Andric return AdjustObjCObjectType(*this, E->getType(), RValue::get(*Val)); 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric // We don't retain the receiver in delegate init calls, and this is 5980b57cec5SDimitry Andric // safe because the receiver value is always loaded from 'self', 5990b57cec5SDimitry Andric // which we zero out. We don't want to Block_copy block receivers, 6000b57cec5SDimitry Andric // though. 6010b57cec5SDimitry Andric bool retainSelf = 6020b57cec5SDimitry Andric (!isDelegateInit && 6030b57cec5SDimitry Andric CGM.getLangOpts().ObjCAutoRefCount && 6040b57cec5SDimitry Andric method && 6050b57cec5SDimitry Andric method->hasAttr<NSConsumesSelfAttr>()); 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric CGObjCRuntime &Runtime = CGM.getObjCRuntime(); 6080b57cec5SDimitry Andric bool isSuperMessage = false; 6090b57cec5SDimitry Andric bool isClassMessage = false; 6100b57cec5SDimitry Andric ObjCInterfaceDecl *OID = nullptr; 6110b57cec5SDimitry Andric // Find the receiver 6120b57cec5SDimitry Andric QualType ReceiverType; 6130b57cec5SDimitry Andric llvm::Value *Receiver = nullptr; 6140b57cec5SDimitry Andric switch (E->getReceiverKind()) { 6150b57cec5SDimitry Andric case ObjCMessageExpr::Instance: 6160b57cec5SDimitry Andric ReceiverType = E->getInstanceReceiver()->getType(); 617480093f4SDimitry Andric isClassMessage = ReceiverType->isObjCClassType(); 6180b57cec5SDimitry Andric if (retainSelf) { 6190b57cec5SDimitry Andric TryEmitResult ter = tryEmitARCRetainScalarExpr(*this, 6200b57cec5SDimitry Andric E->getInstanceReceiver()); 6210b57cec5SDimitry Andric Receiver = ter.getPointer(); 6220b57cec5SDimitry Andric if (ter.getInt()) retainSelf = false; 6230b57cec5SDimitry Andric } else 6240b57cec5SDimitry Andric Receiver = EmitScalarExpr(E->getInstanceReceiver()); 6250b57cec5SDimitry Andric break; 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric case ObjCMessageExpr::Class: { 6280b57cec5SDimitry Andric ReceiverType = E->getClassReceiver(); 629480093f4SDimitry Andric OID = ReceiverType->castAs<ObjCObjectType>()->getInterface(); 6300b57cec5SDimitry Andric assert(OID && "Invalid Objective-C class message send"); 6310b57cec5SDimitry Andric Receiver = Runtime.GetClass(*this, OID); 6320b57cec5SDimitry Andric isClassMessage = true; 6330b57cec5SDimitry Andric break; 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric case ObjCMessageExpr::SuperInstance: 6370b57cec5SDimitry Andric ReceiverType = E->getSuperType(); 6380b57cec5SDimitry Andric Receiver = LoadObjCSelf(); 6390b57cec5SDimitry Andric isSuperMessage = true; 6400b57cec5SDimitry Andric break; 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric case ObjCMessageExpr::SuperClass: 6430b57cec5SDimitry Andric ReceiverType = E->getSuperType(); 6440b57cec5SDimitry Andric Receiver = LoadObjCSelf(); 6450b57cec5SDimitry Andric isSuperMessage = true; 6460b57cec5SDimitry Andric isClassMessage = true; 6470b57cec5SDimitry Andric break; 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric if (retainSelf) 6510b57cec5SDimitry Andric Receiver = EmitARCRetainNonBlock(Receiver); 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric // In ARC, we sometimes want to "extend the lifetime" 6540b57cec5SDimitry Andric // (i.e. retain+autorelease) of receivers of returns-inner-pointer 6550b57cec5SDimitry Andric // messages. 6560b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount && method && 6570b57cec5SDimitry Andric method->hasAttr<ObjCReturnsInnerPointerAttr>() && 6580b57cec5SDimitry Andric shouldExtendReceiverForInnerPointerMessage(E)) 6590b57cec5SDimitry Andric Receiver = EmitARCRetainAutorelease(ReceiverType, Receiver); 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric QualType ResultType = method ? method->getReturnType() : E->getType(); 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric CallArgList Args; 6640b57cec5SDimitry Andric EmitCallArgs(Args, method, E->arguments(), /*AC*/AbstractCallee(method)); 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric // For delegate init calls in ARC, do an unsafe store of null into 6670b57cec5SDimitry Andric // self. This represents the call taking direct ownership of that 6680b57cec5SDimitry Andric // value. We have to do this after emitting the other call 6690b57cec5SDimitry Andric // arguments because they might also reference self, but we don't 6700b57cec5SDimitry Andric // have to worry about any of them modifying self because that would 6710b57cec5SDimitry Andric // be an undefined read and write of an object in unordered 6720b57cec5SDimitry Andric // expressions. 6730b57cec5SDimitry Andric if (isDelegateInit) { 6740b57cec5SDimitry Andric assert(getLangOpts().ObjCAutoRefCount && 6750b57cec5SDimitry Andric "delegate init calls should only be marked in ARC"); 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // Do an unsafe store of null into self. 6780b57cec5SDimitry Andric Address selfAddr = 6790b57cec5SDimitry Andric GetAddrOfLocalVar(cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl()); 6800b57cec5SDimitry Andric Builder.CreateStore(getNullForVariable(selfAddr), selfAddr); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric RValue result; 6840b57cec5SDimitry Andric if (isSuperMessage) { 6850b57cec5SDimitry Andric // super is only valid in an Objective-C method 6860b57cec5SDimitry Andric const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 6870b57cec5SDimitry Andric bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 6880b57cec5SDimitry Andric result = Runtime.GenerateMessageSendSuper(*this, Return, ResultType, 6890b57cec5SDimitry Andric E->getSelector(), 6900b57cec5SDimitry Andric OMD->getClassInterface(), 6910b57cec5SDimitry Andric isCategoryImpl, 6920b57cec5SDimitry Andric Receiver, 6930b57cec5SDimitry Andric isClassMessage, 6940b57cec5SDimitry Andric Args, 6950b57cec5SDimitry Andric method); 6960b57cec5SDimitry Andric } else { 6970b57cec5SDimitry Andric // Call runtime methods directly if we can. 698480093f4SDimitry Andric result = Runtime.GeneratePossiblySpecializedMessageSend( 699480093f4SDimitry Andric *this, Return, ResultType, E->getSelector(), Receiver, Args, OID, 700480093f4SDimitry Andric method, isClassMessage); 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric // For delegate init calls in ARC, implicitly store the result of 7040b57cec5SDimitry Andric // the call back into self. This takes ownership of the value. 7050b57cec5SDimitry Andric if (isDelegateInit) { 7060b57cec5SDimitry Andric Address selfAddr = 7070b57cec5SDimitry Andric GetAddrOfLocalVar(cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl()); 7080b57cec5SDimitry Andric llvm::Value *newSelf = result.getScalarVal(); 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andric // The delegate return type isn't necessarily a matching type; in 7110b57cec5SDimitry Andric // fact, it's quite likely to be 'id'. 7120b57cec5SDimitry Andric llvm::Type *selfTy = selfAddr.getElementType(); 7130b57cec5SDimitry Andric newSelf = Builder.CreateBitCast(newSelf, selfTy); 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric Builder.CreateStore(newSelf, selfAddr); 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric return AdjustObjCObjectType(*this, E->getType(), result); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric namespace { 7220b57cec5SDimitry Andric struct FinishARCDealloc final : EHScopeStack::Cleanup { 7230b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override { 7240b57cec5SDimitry Andric const ObjCMethodDecl *method = cast<ObjCMethodDecl>(CGF.CurCodeDecl); 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric const ObjCImplDecl *impl = cast<ObjCImplDecl>(method->getDeclContext()); 7270b57cec5SDimitry Andric const ObjCInterfaceDecl *iface = impl->getClassInterface(); 7280b57cec5SDimitry Andric if (!iface->getSuperClass()) return; 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric bool isCategory = isa<ObjCCategoryImplDecl>(impl); 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric // Call [super dealloc] if we have a superclass. 7330b57cec5SDimitry Andric llvm::Value *self = CGF.LoadObjCSelf(); 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric CallArgList args; 7360b57cec5SDimitry Andric CGF.CGM.getObjCRuntime().GenerateMessageSendSuper(CGF, ReturnValueSlot(), 7370b57cec5SDimitry Andric CGF.getContext().VoidTy, 7380b57cec5SDimitry Andric method->getSelector(), 7390b57cec5SDimitry Andric iface, 7400b57cec5SDimitry Andric isCategory, 7410b57cec5SDimitry Andric self, 7420b57cec5SDimitry Andric /*is class msg*/ false, 7430b57cec5SDimitry Andric args, 7440b57cec5SDimitry Andric method); 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric }; 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric /// StartObjCMethod - Begin emission of an ObjCMethod. This generates 7500b57cec5SDimitry Andric /// the LLVM function and sets the other context used by 7510b57cec5SDimitry Andric /// CodeGenFunction. 7520b57cec5SDimitry Andric void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, 7530b57cec5SDimitry Andric const ObjCContainerDecl *CD) { 7540b57cec5SDimitry Andric SourceLocation StartLoc = OMD->getBeginLoc(); 7550b57cec5SDimitry Andric FunctionArgList args; 7560b57cec5SDimitry Andric // Check if we should generate debug info for this method. 7570b57cec5SDimitry Andric if (OMD->hasAttr<NoDebugAttr>()) 7580b57cec5SDimitry Andric DebugInfo = nullptr; // disable debug info indefinitely for this function 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD); 763480093f4SDimitry Andric if (OMD->isDirectMethod()) { 764480093f4SDimitry Andric Fn->setVisibility(llvm::Function::HiddenVisibility); 765fe6060f1SDimitry Andric CGM.SetLLVMFunctionAttributes(OMD, FI, Fn, /*IsThunk=*/false); 766480093f4SDimitry Andric CGM.SetLLVMFunctionAttributesForDefinition(OMD, Fn); 767480093f4SDimitry Andric } else { 7680b57cec5SDimitry Andric CGM.SetInternalFunctionAttributes(OMD, Fn, FI); 769480093f4SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric args.push_back(OMD->getSelfDecl()); 772bdd1243dSDimitry Andric if (!OMD->isDirectMethod()) 7730b57cec5SDimitry Andric args.push_back(OMD->getCmdDecl()); 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric args.append(OMD->param_begin(), OMD->param_end()); 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric CurGD = OMD; 7780b57cec5SDimitry Andric CurEHLocation = OMD->getEndLoc(); 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric StartFunction(OMD, OMD->getReturnType(), Fn, FI, args, 7810b57cec5SDimitry Andric OMD->getLocation(), StartLoc); 7820b57cec5SDimitry Andric 783480093f4SDimitry Andric if (OMD->isDirectMethod()) { 784480093f4SDimitry Andric // This function is a direct call, it has to implement a nil check 785480093f4SDimitry Andric // on entry. 786480093f4SDimitry Andric // 787480093f4SDimitry Andric // TODO: possibly have several entry points to elide the check 788480093f4SDimitry Andric CGM.getObjCRuntime().GenerateDirectMethodPrologue(*this, Fn, OMD, CD); 789480093f4SDimitry Andric } 790480093f4SDimitry Andric 7910b57cec5SDimitry Andric // In ARC, certain methods get an extra cleanup. 7920b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCAutoRefCount && 7930b57cec5SDimitry Andric OMD->isInstanceMethod() && 7940b57cec5SDimitry Andric OMD->getSelector().isUnarySelector()) { 7950b57cec5SDimitry Andric const IdentifierInfo *ident = 7960b57cec5SDimitry Andric OMD->getSelector().getIdentifierInfoForSlot(0); 7970b57cec5SDimitry Andric if (ident->isStr("dealloc")) 7980b57cec5SDimitry Andric EHStack.pushCleanup<FinishARCDealloc>(getARCCleanupKind()); 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric } 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF, 8030b57cec5SDimitry Andric LValue lvalue, QualType type); 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric /// Generate an Objective-C method. An Objective-C method is a C function with 8060b57cec5SDimitry Andric /// its pointer, name, and types registered in the class structure. 8070b57cec5SDimitry Andric void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { 8080b57cec5SDimitry Andric StartObjCMethod(OMD, OMD->getClassInterface()); 8090b57cec5SDimitry Andric PGO.assignRegionCounters(GlobalDecl(OMD), CurFn); 8100b57cec5SDimitry Andric assert(isa<CompoundStmt>(OMD->getBody())); 8110b57cec5SDimitry Andric incrementProfileCounter(OMD->getBody()); 8120b57cec5SDimitry Andric EmitCompoundStmtWithoutScope(*cast<CompoundStmt>(OMD->getBody())); 8130b57cec5SDimitry Andric FinishFunction(OMD->getBodyRBrace()); 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric /// emitStructGetterCall - Call the runtime function to load a property 8170b57cec5SDimitry Andric /// into the return value slot. 8180b57cec5SDimitry Andric static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar, 8190b57cec5SDimitry Andric bool isAtomic, bool hasStrong) { 8200b57cec5SDimitry Andric ASTContext &Context = CGF.getContext(); 8210b57cec5SDimitry Andric 82281ad6265SDimitry Andric llvm::Value *src = 8230b57cec5SDimitry Andric CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0) 82481ad6265SDimitry Andric .getPointer(CGF); 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric // objc_copyStruct (ReturnValue, &structIvar, 8270b57cec5SDimitry Andric // sizeof (Type of Ivar), isAtomic, false); 8280b57cec5SDimitry Andric CallArgList args; 8290b57cec5SDimitry Andric 830*0fca6ea1SDimitry Andric llvm::Value *dest = CGF.ReturnValue.emitRawPointer(CGF); 83181ad6265SDimitry Andric args.add(RValue::get(dest), Context.VoidPtrTy); 83281ad6265SDimitry Andric args.add(RValue::get(src), Context.VoidPtrTy); 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric CharUnits size = CGF.getContext().getTypeSizeInChars(ivar->getType()); 8350b57cec5SDimitry Andric args.add(RValue::get(CGF.CGM.getSize(size)), Context.getSizeType()); 8360b57cec5SDimitry Andric args.add(RValue::get(CGF.Builder.getInt1(isAtomic)), Context.BoolTy); 8370b57cec5SDimitry Andric args.add(RValue::get(CGF.Builder.getInt1(hasStrong)), Context.BoolTy); 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric llvm::FunctionCallee fn = CGF.CGM.getObjCRuntime().GetGetStructFunction(); 8400b57cec5SDimitry Andric CGCallee callee = CGCallee::forDirect(fn); 8410b57cec5SDimitry Andric CGF.EmitCall(CGF.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, args), 8420b57cec5SDimitry Andric callee, ReturnValueSlot(), args); 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric /// Determine whether the given architecture supports unaligned atomic 8460b57cec5SDimitry Andric /// accesses. They don't have to be fast, just faster than a function 8470b57cec5SDimitry Andric /// call and a mutex. 8480b57cec5SDimitry Andric static bool hasUnalignedAtomics(llvm::Triple::ArchType arch) { 8490b57cec5SDimitry Andric // FIXME: Allow unaligned atomic load/store on x86. (It is not 8500b57cec5SDimitry Andric // currently supported by the backend.) 85104eeddc0SDimitry Andric return false; 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric /// Return the maximum size that permits atomic accesses for the given 8550b57cec5SDimitry Andric /// architecture. 8560b57cec5SDimitry Andric static CharUnits getMaxAtomicAccessSize(CodeGenModule &CGM, 8570b57cec5SDimitry Andric llvm::Triple::ArchType arch) { 8580b57cec5SDimitry Andric // ARM has 8-byte atomic accesses, but it's not clear whether we 8590b57cec5SDimitry Andric // want to rely on them here. 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric // In the default case, just assume that any size up to a pointer is 8620b57cec5SDimitry Andric // fine given adequate alignment. 8630b57cec5SDimitry Andric return CharUnits::fromQuantity(CGM.PointerSizeInBytes); 8640b57cec5SDimitry Andric } 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric namespace { 8670b57cec5SDimitry Andric class PropertyImplStrategy { 8680b57cec5SDimitry Andric public: 8690b57cec5SDimitry Andric enum StrategyKind { 8700b57cec5SDimitry Andric /// The 'native' strategy is to use the architecture's provided 8710b57cec5SDimitry Andric /// reads and writes. 8720b57cec5SDimitry Andric Native, 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric /// Use objc_setProperty and objc_getProperty. 8750b57cec5SDimitry Andric GetSetProperty, 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric /// Use objc_setProperty for the setter, but use expression 8780b57cec5SDimitry Andric /// evaluation for the getter. 8790b57cec5SDimitry Andric SetPropertyAndExpressionGet, 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric /// Use objc_copyStruct. 8820b57cec5SDimitry Andric CopyStruct, 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric /// The 'expression' strategy is to emit normal assignment or 8850b57cec5SDimitry Andric /// lvalue-to-rvalue expressions. 8860b57cec5SDimitry Andric Expression 8870b57cec5SDimitry Andric }; 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric StrategyKind getKind() const { return StrategyKind(Kind); } 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric bool hasStrongMember() const { return HasStrong; } 8920b57cec5SDimitry Andric bool isAtomic() const { return IsAtomic; } 8930b57cec5SDimitry Andric bool isCopy() const { return IsCopy; } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric CharUnits getIvarSize() const { return IvarSize; } 8960b57cec5SDimitry Andric CharUnits getIvarAlignment() const { return IvarAlignment; } 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric PropertyImplStrategy(CodeGenModule &CGM, 8990b57cec5SDimitry Andric const ObjCPropertyImplDecl *propImpl); 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric private: 902*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(StrategyKind) 9030b57cec5SDimitry Andric unsigned Kind : 8; 904*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool) 9050b57cec5SDimitry Andric unsigned IsAtomic : 1; 906*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool) 9070b57cec5SDimitry Andric unsigned IsCopy : 1; 908*0fca6ea1SDimitry Andric LLVM_PREFERRED_TYPE(bool) 9090b57cec5SDimitry Andric unsigned HasStrong : 1; 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric CharUnits IvarSize; 9120b57cec5SDimitry Andric CharUnits IvarAlignment; 9130b57cec5SDimitry Andric }; 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric /// Pick an implementation strategy for the given property synthesis. 9170b57cec5SDimitry Andric PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM, 9180b57cec5SDimitry Andric const ObjCPropertyImplDecl *propImpl) { 9190b57cec5SDimitry Andric const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); 9200b57cec5SDimitry Andric ObjCPropertyDecl::SetterKind setterKind = prop->getSetterKind(); 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric IsCopy = (setterKind == ObjCPropertyDecl::Copy); 9230b57cec5SDimitry Andric IsAtomic = prop->isAtomic(); 9240b57cec5SDimitry Andric HasStrong = false; // doesn't matter here. 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric // Evaluate the ivar's size and alignment. 9270b57cec5SDimitry Andric ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); 9280b57cec5SDimitry Andric QualType ivarType = ivar->getType(); 929e8d8bef9SDimitry Andric auto TInfo = CGM.getContext().getTypeInfoInChars(ivarType); 930e8d8bef9SDimitry Andric IvarSize = TInfo.Width; 931e8d8bef9SDimitry Andric IvarAlignment = TInfo.Align; 9320b57cec5SDimitry Andric 933fe6060f1SDimitry Andric // If we have a copy property, we always have to use setProperty. 934fe6060f1SDimitry Andric // If the property is atomic we need to use getProperty, but in 935fe6060f1SDimitry Andric // the nonatomic case we can just use expression. 9360b57cec5SDimitry Andric if (IsCopy) { 937fe6060f1SDimitry Andric Kind = IsAtomic ? GetSetProperty : SetPropertyAndExpressionGet; 9380b57cec5SDimitry Andric return; 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric // Handle retain. 9420b57cec5SDimitry Andric if (setterKind == ObjCPropertyDecl::Retain) { 9430b57cec5SDimitry Andric // In GC-only, there's nothing special that needs to be done. 9440b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { 9450b57cec5SDimitry Andric // fallthrough 9460b57cec5SDimitry Andric 9470b57cec5SDimitry Andric // In ARC, if the property is non-atomic, use expression emission, 9480b57cec5SDimitry Andric // which translates to objc_storeStrong. This isn't required, but 9490b57cec5SDimitry Andric // it's slightly nicer. 9500b57cec5SDimitry Andric } else if (CGM.getLangOpts().ObjCAutoRefCount && !IsAtomic) { 9510b57cec5SDimitry Andric // Using standard expression emission for the setter is only 9520b57cec5SDimitry Andric // acceptable if the ivar is __strong, which won't be true if 9530b57cec5SDimitry Andric // the property is annotated with __attribute__((NSObject)). 9540b57cec5SDimitry Andric // TODO: falling all the way back to objc_setProperty here is 9550b57cec5SDimitry Andric // just laziness, though; we could still use objc_storeStrong 9560b57cec5SDimitry Andric // if we hacked it right. 9570b57cec5SDimitry Andric if (ivarType.getObjCLifetime() == Qualifiers::OCL_Strong) 9580b57cec5SDimitry Andric Kind = Expression; 9590b57cec5SDimitry Andric else 9600b57cec5SDimitry Andric Kind = SetPropertyAndExpressionGet; 9610b57cec5SDimitry Andric return; 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric // Otherwise, we need to at least use setProperty. However, if 9640b57cec5SDimitry Andric // the property isn't atomic, we can use normal expression 9650b57cec5SDimitry Andric // emission for the getter. 9660b57cec5SDimitry Andric } else if (!IsAtomic) { 9670b57cec5SDimitry Andric Kind = SetPropertyAndExpressionGet; 9680b57cec5SDimitry Andric return; 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric // Otherwise, we have to use both setProperty and getProperty. 9710b57cec5SDimitry Andric } else { 9720b57cec5SDimitry Andric Kind = GetSetProperty; 9730b57cec5SDimitry Andric return; 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric } 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric // If we're not atomic, just use expression accesses. 9780b57cec5SDimitry Andric if (!IsAtomic) { 9790b57cec5SDimitry Andric Kind = Expression; 9800b57cec5SDimitry Andric return; 9810b57cec5SDimitry Andric } 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric // Properties on bitfield ivars need to be emitted using expression 9840b57cec5SDimitry Andric // accesses even if they're nominally atomic. 9850b57cec5SDimitry Andric if (ivar->isBitField()) { 9860b57cec5SDimitry Andric Kind = Expression; 9870b57cec5SDimitry Andric return; 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric // GC-qualified or ARC-qualified ivars need to be emitted as 9910b57cec5SDimitry Andric // expressions. This actually works out to being atomic anyway, 9920b57cec5SDimitry Andric // except for ARC __strong, but that should trigger the above code. 9930b57cec5SDimitry Andric if (ivarType.hasNonTrivialObjCLifetime() || 9940b57cec5SDimitry Andric (CGM.getLangOpts().getGC() && 9950b57cec5SDimitry Andric CGM.getContext().getObjCGCAttrKind(ivarType))) { 9960b57cec5SDimitry Andric Kind = Expression; 9970b57cec5SDimitry Andric return; 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric // Compute whether the ivar has strong members. 10010b57cec5SDimitry Andric if (CGM.getLangOpts().getGC()) 10020b57cec5SDimitry Andric if (const RecordType *recordType = ivarType->getAs<RecordType>()) 10030b57cec5SDimitry Andric HasStrong = recordType->getDecl()->hasObjectMember(); 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric // We can never access structs with object members with a native 10060b57cec5SDimitry Andric // access, because we need to use write barriers. This is what 10070b57cec5SDimitry Andric // objc_copyStruct is for. 10080b57cec5SDimitry Andric if (HasStrong) { 10090b57cec5SDimitry Andric Kind = CopyStruct; 10100b57cec5SDimitry Andric return; 10110b57cec5SDimitry Andric } 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric // Otherwise, this is target-dependent and based on the size and 10140b57cec5SDimitry Andric // alignment of the ivar. 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric // If the size of the ivar is not a power of two, give up. We don't 10170b57cec5SDimitry Andric // want to get into the business of doing compare-and-swaps. 10180b57cec5SDimitry Andric if (!IvarSize.isPowerOfTwo()) { 10190b57cec5SDimitry Andric Kind = CopyStruct; 10200b57cec5SDimitry Andric return; 10210b57cec5SDimitry Andric } 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric llvm::Triple::ArchType arch = 10240b57cec5SDimitry Andric CGM.getTarget().getTriple().getArch(); 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric // Most architectures require memory to fit within a single cache 10270b57cec5SDimitry Andric // line, so the alignment has to be at least the size of the access. 10280b57cec5SDimitry Andric // Otherwise we have to grab a lock. 10290b57cec5SDimitry Andric if (IvarAlignment < IvarSize && !hasUnalignedAtomics(arch)) { 10300b57cec5SDimitry Andric Kind = CopyStruct; 10310b57cec5SDimitry Andric return; 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric // If the ivar's size exceeds the architecture's maximum atomic 10350b57cec5SDimitry Andric // access size, we have to use CopyStruct. 10360b57cec5SDimitry Andric if (IvarSize > getMaxAtomicAccessSize(CGM, arch)) { 10370b57cec5SDimitry Andric Kind = CopyStruct; 10380b57cec5SDimitry Andric return; 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric // Otherwise, we can use native loads and stores. 10420b57cec5SDimitry Andric Kind = Native; 10430b57cec5SDimitry Andric } 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andric /// Generate an Objective-C property getter function. 10460b57cec5SDimitry Andric /// 10470b57cec5SDimitry Andric /// The given Decl must be an ObjCImplementationDecl. \@synthesize 10480b57cec5SDimitry Andric /// is illegal within a category. 10490b57cec5SDimitry Andric void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, 10500b57cec5SDimitry Andric const ObjCPropertyImplDecl *PID) { 10510b57cec5SDimitry Andric llvm::Constant *AtomicHelperFn = 10520b57cec5SDimitry Andric CodeGenFunction(CGM).GenerateObjCAtomicGetterCopyHelperFunction(PID); 1053480093f4SDimitry Andric ObjCMethodDecl *OMD = PID->getGetterMethodDecl(); 10540b57cec5SDimitry Andric assert(OMD && "Invalid call to generate getter (empty method)"); 10550b57cec5SDimitry Andric StartObjCMethod(OMD, IMP->getClassInterface()); 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric generateObjCGetterBody(IMP, PID, OMD, AtomicHelperFn); 10580b57cec5SDimitry Andric 1059480093f4SDimitry Andric FinishFunction(OMD->getEndLoc()); 10600b57cec5SDimitry Andric } 10610b57cec5SDimitry Andric 10620b57cec5SDimitry Andric static bool hasTrivialGetExpr(const ObjCPropertyImplDecl *propImpl) { 10630b57cec5SDimitry Andric const Expr *getter = propImpl->getGetterCXXConstructor(); 10640b57cec5SDimitry Andric if (!getter) return true; 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric // Sema only makes only of these when the ivar has a C++ class type, 10670b57cec5SDimitry Andric // so the form is pretty constrained. 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric // If the property has a reference type, we might just be binding a 10700b57cec5SDimitry Andric // reference, in which case the result will be a gl-value. We should 10710b57cec5SDimitry Andric // treat this as a non-trivial operation. 10720b57cec5SDimitry Andric if (getter->isGLValue()) 10730b57cec5SDimitry Andric return false; 10740b57cec5SDimitry Andric 10750b57cec5SDimitry Andric // If we selected a trivial copy-constructor, we're okay. 10760b57cec5SDimitry Andric if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(getter)) 10770b57cec5SDimitry Andric return (construct->getConstructor()->isTrivial()); 10780b57cec5SDimitry Andric 10790b57cec5SDimitry Andric // The constructor might require cleanups (in which case it's never 10800b57cec5SDimitry Andric // trivial). 10810b57cec5SDimitry Andric assert(isa<ExprWithCleanups>(getter)); 10820b57cec5SDimitry Andric return false; 10830b57cec5SDimitry Andric } 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric /// emitCPPObjectAtomicGetterCall - Call the runtime function to 10860b57cec5SDimitry Andric /// copy the ivar into the resturn slot. 10870b57cec5SDimitry Andric static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF, 10880b57cec5SDimitry Andric llvm::Value *returnAddr, 10890b57cec5SDimitry Andric ObjCIvarDecl *ivar, 10900b57cec5SDimitry Andric llvm::Constant *AtomicHelperFn) { 10910b57cec5SDimitry Andric // objc_copyCppObjectAtomic (&returnSlot, &CppObjectIvar, 10920b57cec5SDimitry Andric // AtomicHelperFn); 10930b57cec5SDimitry Andric CallArgList args; 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric // The 1st argument is the return Slot. 10960b57cec5SDimitry Andric args.add(RValue::get(returnAddr), CGF.getContext().VoidPtrTy); 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric // The 2nd argument is the address of the ivar. 10990b57cec5SDimitry Andric llvm::Value *ivarAddr = 1100480093f4SDimitry Andric CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0) 1101480093f4SDimitry Andric .getPointer(CGF); 11020b57cec5SDimitry Andric args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy); 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric // Third argument is the helper function. 11050b57cec5SDimitry Andric args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); 11060b57cec5SDimitry Andric 11070b57cec5SDimitry Andric llvm::FunctionCallee copyCppAtomicObjectFn = 11080b57cec5SDimitry Andric CGF.CGM.getObjCRuntime().GetCppAtomicObjectGetFunction(); 11090b57cec5SDimitry Andric CGCallee callee = CGCallee::forDirect(copyCppAtomicObjectFn); 11100b57cec5SDimitry Andric CGF.EmitCall( 11110b57cec5SDimitry Andric CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), 11120b57cec5SDimitry Andric callee, ReturnValueSlot(), args); 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 1115bdd1243dSDimitry Andric // emitCmdValueForGetterSetterBody - Handle emitting the load necessary for 1116bdd1243dSDimitry Andric // the `_cmd` selector argument for getter/setter bodies. For direct methods, 1117bdd1243dSDimitry Andric // this returns an undefined/poison value; this matches behavior prior to `_cmd` 1118bdd1243dSDimitry Andric // being removed from the direct method ABI as the getter/setter caller would 1119bdd1243dSDimitry Andric // never load one. For non-direct methods, this emits a load of the implicit 1120bdd1243dSDimitry Andric // `_cmd` storage. 1121bdd1243dSDimitry Andric static llvm::Value *emitCmdValueForGetterSetterBody(CodeGenFunction &CGF, 1122bdd1243dSDimitry Andric ObjCMethodDecl *MD) { 1123bdd1243dSDimitry Andric if (MD->isDirectMethod()) { 1124bdd1243dSDimitry Andric // Direct methods do not have a `_cmd` argument. Emit an undefined/poison 1125bdd1243dSDimitry Andric // value. This will be passed to objc_getProperty/objc_setProperty, which 1126bdd1243dSDimitry Andric // has not appeared bothered by the `_cmd` argument being undefined before. 1127bdd1243dSDimitry Andric llvm::Type *selType = CGF.ConvertType(CGF.getContext().getObjCSelType()); 1128bdd1243dSDimitry Andric return llvm::PoisonValue::get(selType); 1129bdd1243dSDimitry Andric } 1130bdd1243dSDimitry Andric 1131bdd1243dSDimitry Andric return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(MD->getCmdDecl()), "cmd"); 1132bdd1243dSDimitry Andric } 1133bdd1243dSDimitry Andric 11340b57cec5SDimitry Andric void 11350b57cec5SDimitry Andric CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, 11360b57cec5SDimitry Andric const ObjCPropertyImplDecl *propImpl, 11370b57cec5SDimitry Andric const ObjCMethodDecl *GetterMethodDecl, 11380b57cec5SDimitry Andric llvm::Constant *AtomicHelperFn) { 1139bdd1243dSDimitry Andric 1140bdd1243dSDimitry Andric ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); 1141bdd1243dSDimitry Andric 1142bdd1243dSDimitry Andric if (ivar->getType().isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) { 1143bdd1243dSDimitry Andric if (!AtomicHelperFn) { 1144bdd1243dSDimitry Andric LValue Src = 1145bdd1243dSDimitry Andric EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 0); 1146bdd1243dSDimitry Andric LValue Dst = MakeAddrLValue(ReturnValue, ivar->getType()); 1147bdd1243dSDimitry Andric callCStructCopyConstructor(Dst, Src); 1148bdd1243dSDimitry Andric } else { 1149bdd1243dSDimitry Andric ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); 1150*0fca6ea1SDimitry Andric emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), 1151*0fca6ea1SDimitry Andric ivar, AtomicHelperFn); 1152bdd1243dSDimitry Andric } 1153bdd1243dSDimitry Andric return; 1154bdd1243dSDimitry Andric } 1155bdd1243dSDimitry Andric 11560b57cec5SDimitry Andric // If there's a non-trivial 'get' expression, we just have to emit that. 11570b57cec5SDimitry Andric if (!hasTrivialGetExpr(propImpl)) { 11580b57cec5SDimitry Andric if (!AtomicHelperFn) { 11590b57cec5SDimitry Andric auto *ret = ReturnStmt::Create(getContext(), SourceLocation(), 11600b57cec5SDimitry Andric propImpl->getGetterCXXConstructor(), 11610b57cec5SDimitry Andric /* NRVOCandidate=*/nullptr); 11620b57cec5SDimitry Andric EmitReturnStmt(*ret); 11630b57cec5SDimitry Andric } 11640b57cec5SDimitry Andric else { 11650b57cec5SDimitry Andric ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); 1166*0fca6ea1SDimitry Andric emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), 11670b57cec5SDimitry Andric ivar, AtomicHelperFn); 11680b57cec5SDimitry Andric } 11690b57cec5SDimitry Andric return; 11700b57cec5SDimitry Andric } 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); 11730b57cec5SDimitry Andric QualType propType = prop->getType(); 1174480093f4SDimitry Andric ObjCMethodDecl *getterMethod = propImpl->getGetterMethodDecl(); 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric // Pick an implementation strategy. 11770b57cec5SDimitry Andric PropertyImplStrategy strategy(CGM, propImpl); 11780b57cec5SDimitry Andric switch (strategy.getKind()) { 11790b57cec5SDimitry Andric case PropertyImplStrategy::Native: { 11800b57cec5SDimitry Andric // We don't need to do anything for a zero-size struct. 11810b57cec5SDimitry Andric if (strategy.getIvarSize().isZero()) 11820b57cec5SDimitry Andric return; 11830b57cec5SDimitry Andric 11840b57cec5SDimitry Andric LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 0); 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric // Currently, all atomic accesses have to be through integer 11870b57cec5SDimitry Andric // types, so there's no point in trying to pick a prettier type. 11880b57cec5SDimitry Andric uint64_t ivarSize = getContext().toBits(strategy.getIvarSize()); 11890b57cec5SDimitry Andric llvm::Type *bitcastType = llvm::Type::getIntNTy(getLLVMContext(), ivarSize); 11900b57cec5SDimitry Andric 11910b57cec5SDimitry Andric // Perform an atomic load. This does not impose ordering constraints. 1192*0fca6ea1SDimitry Andric Address ivarAddr = LV.getAddress(); 119306c3fb27SDimitry Andric ivarAddr = ivarAddr.withElementType(bitcastType); 11940b57cec5SDimitry Andric llvm::LoadInst *load = Builder.CreateLoad(ivarAddr, "load"); 11950b57cec5SDimitry Andric load->setAtomic(llvm::AtomicOrdering::Unordered); 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric // Store that value into the return address. Doing this with a 11980b57cec5SDimitry Andric // bitcast is likely to produce some pretty ugly IR, but it's not 11990b57cec5SDimitry Andric // the *most* terrible thing in the world. 12000b57cec5SDimitry Andric llvm::Type *retTy = ConvertType(getterMethod->getReturnType()); 12010b57cec5SDimitry Andric uint64_t retTySize = CGM.getDataLayout().getTypeSizeInBits(retTy); 12020b57cec5SDimitry Andric llvm::Value *ivarVal = load; 12030b57cec5SDimitry Andric if (ivarSize > retTySize) { 120481ad6265SDimitry Andric bitcastType = llvm::Type::getIntNTy(getLLVMContext(), retTySize); 120581ad6265SDimitry Andric ivarVal = Builder.CreateTrunc(load, bitcastType); 12060b57cec5SDimitry Andric } 120706c3fb27SDimitry Andric Builder.CreateStore(ivarVal, ReturnValue.withElementType(bitcastType)); 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric // Make sure we don't do an autorelease. 12100b57cec5SDimitry Andric AutoreleaseResult = false; 12110b57cec5SDimitry Andric return; 12120b57cec5SDimitry Andric } 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andric case PropertyImplStrategy::GetSetProperty: { 12150b57cec5SDimitry Andric llvm::FunctionCallee getPropertyFn = 12160b57cec5SDimitry Andric CGM.getObjCRuntime().GetPropertyGetFunction(); 12170b57cec5SDimitry Andric if (!getPropertyFn) { 12180b57cec5SDimitry Andric CGM.ErrorUnsupported(propImpl, "Obj-C getter requiring atomic copy"); 12190b57cec5SDimitry Andric return; 12200b57cec5SDimitry Andric } 12210b57cec5SDimitry Andric CGCallee callee = CGCallee::forDirect(getPropertyFn); 12220b57cec5SDimitry Andric 12230b57cec5SDimitry Andric // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true). 12240b57cec5SDimitry Andric // FIXME: Can't this be simpler? This might even be worse than the 12250b57cec5SDimitry Andric // corresponding gcc code. 1226bdd1243dSDimitry Andric llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, getterMethod); 12270b57cec5SDimitry Andric llvm::Value *self = Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy); 12280b57cec5SDimitry Andric llvm::Value *ivarOffset = 1229bdd1243dSDimitry Andric EmitIvarOffsetAsPointerDiff(classImpl->getClassInterface(), ivar); 12300b57cec5SDimitry Andric 12310b57cec5SDimitry Andric CallArgList args; 12320b57cec5SDimitry Andric args.add(RValue::get(self), getContext().getObjCIdType()); 12330b57cec5SDimitry Andric args.add(RValue::get(cmd), getContext().getObjCSelType()); 12340b57cec5SDimitry Andric args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); 12350b57cec5SDimitry Andric args.add(RValue::get(Builder.getInt1(strategy.isAtomic())), 12360b57cec5SDimitry Andric getContext().BoolTy); 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric // FIXME: We shouldn't need to get the function info here, the 12390b57cec5SDimitry Andric // runtime already should have computed it to build the function. 12400b57cec5SDimitry Andric llvm::CallBase *CallInstruction; 12410b57cec5SDimitry Andric RValue RV = EmitCall(getTypes().arrangeBuiltinFunctionCall( 12420b57cec5SDimitry Andric getContext().getObjCIdType(), args), 12430b57cec5SDimitry Andric callee, ReturnValueSlot(), args, &CallInstruction); 12440b57cec5SDimitry Andric if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction)) 12450b57cec5SDimitry Andric call->setTailCall(); 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric // We need to fix the type here. Ivars with copy & retain are 12480b57cec5SDimitry Andric // always objects so we don't need to worry about complex or 12490b57cec5SDimitry Andric // aggregates. 12500b57cec5SDimitry Andric RV = RValue::get(Builder.CreateBitCast( 12510b57cec5SDimitry Andric RV.getScalarVal(), 12520b57cec5SDimitry Andric getTypes().ConvertType(getterMethod->getReturnType()))); 12530b57cec5SDimitry Andric 12540b57cec5SDimitry Andric EmitReturnOfRValue(RV, propType); 12550b57cec5SDimitry Andric 12560b57cec5SDimitry Andric // objc_getProperty does an autorelease, so we should suppress ours. 12570b57cec5SDimitry Andric AutoreleaseResult = false; 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric return; 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric case PropertyImplStrategy::CopyStruct: 12630b57cec5SDimitry Andric emitStructGetterCall(*this, ivar, strategy.isAtomic(), 12640b57cec5SDimitry Andric strategy.hasStrongMember()); 12650b57cec5SDimitry Andric return; 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric case PropertyImplStrategy::Expression: 12680b57cec5SDimitry Andric case PropertyImplStrategy::SetPropertyAndExpressionGet: { 12690b57cec5SDimitry Andric LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 0); 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andric QualType ivarType = ivar->getType(); 12720b57cec5SDimitry Andric switch (getEvaluationKind(ivarType)) { 12730b57cec5SDimitry Andric case TEK_Complex: { 12740b57cec5SDimitry Andric ComplexPairTy pair = EmitLoadOfComplex(LV, SourceLocation()); 12750b57cec5SDimitry Andric EmitStoreOfComplex(pair, MakeAddrLValue(ReturnValue, ivarType), 12760b57cec5SDimitry Andric /*init*/ true); 12770b57cec5SDimitry Andric return; 12780b57cec5SDimitry Andric } 12790b57cec5SDimitry Andric case TEK_Aggregate: { 12800b57cec5SDimitry Andric // The return value slot is guaranteed to not be aliased, but 12810b57cec5SDimitry Andric // that's not necessarily the same as "on the stack", so 12820b57cec5SDimitry Andric // we still potentially need objc_memmove_collectable. 12830b57cec5SDimitry Andric EmitAggregateCopy(/* Dest= */ MakeAddrLValue(ReturnValue, ivarType), 12840b57cec5SDimitry Andric /* Src= */ LV, ivarType, getOverlapForReturnValue()); 12850b57cec5SDimitry Andric return; 12860b57cec5SDimitry Andric } 12870b57cec5SDimitry Andric case TEK_Scalar: { 12880b57cec5SDimitry Andric llvm::Value *value; 12890b57cec5SDimitry Andric if (propType->isReferenceType()) { 1290*0fca6ea1SDimitry Andric value = LV.getAddress().emitRawPointer(*this); 12910b57cec5SDimitry Andric } else { 12920b57cec5SDimitry Andric // We want to load and autoreleaseReturnValue ARC __weak ivars. 12930b57cec5SDimitry Andric if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { 12940b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount) { 12950b57cec5SDimitry Andric value = emitARCRetainLoadOfScalar(*this, LV, ivarType); 12960b57cec5SDimitry Andric } else { 1297*0fca6ea1SDimitry Andric value = EmitARCLoadWeak(LV.getAddress()); 12980b57cec5SDimitry Andric } 12990b57cec5SDimitry Andric 13000b57cec5SDimitry Andric // Otherwise we want to do a simple load, suppressing the 13010b57cec5SDimitry Andric // final autorelease. 13020b57cec5SDimitry Andric } else { 13030b57cec5SDimitry Andric value = EmitLoadOfLValue(LV, SourceLocation()).getScalarVal(); 13040b57cec5SDimitry Andric AutoreleaseResult = false; 13050b57cec5SDimitry Andric } 13060b57cec5SDimitry Andric 13070b57cec5SDimitry Andric value = Builder.CreateBitCast( 13080b57cec5SDimitry Andric value, ConvertType(GetterMethodDecl->getReturnType())); 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric EmitReturnOfRValue(RValue::get(value), propType); 13120b57cec5SDimitry Andric return; 13130b57cec5SDimitry Andric } 13140b57cec5SDimitry Andric } 13150b57cec5SDimitry Andric llvm_unreachable("bad evaluation kind"); 13160b57cec5SDimitry Andric } 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric } 13190b57cec5SDimitry Andric llvm_unreachable("bad @property implementation strategy!"); 13200b57cec5SDimitry Andric } 13210b57cec5SDimitry Andric 13220b57cec5SDimitry Andric /// emitStructSetterCall - Call the runtime function to store the value 13230b57cec5SDimitry Andric /// from the first formal parameter into the given ivar. 13240b57cec5SDimitry Andric static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD, 13250b57cec5SDimitry Andric ObjCIvarDecl *ivar) { 13260b57cec5SDimitry Andric // objc_copyStruct (&structIvar, &Arg, 13270b57cec5SDimitry Andric // sizeof (struct something), true, false); 13280b57cec5SDimitry Andric CallArgList args; 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andric // The first argument is the address of the ivar. 1331480093f4SDimitry Andric llvm::Value *ivarAddr = 1332480093f4SDimitry Andric CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0) 1333480093f4SDimitry Andric .getPointer(CGF); 13340b57cec5SDimitry Andric ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy); 13350b57cec5SDimitry Andric args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy); 13360b57cec5SDimitry Andric 13370b57cec5SDimitry Andric // The second argument is the address of the parameter variable. 13380b57cec5SDimitry Andric ParmVarDecl *argVar = *OMD->param_begin(); 13390b57cec5SDimitry Andric DeclRefExpr argRef(CGF.getContext(), argVar, false, 13400b57cec5SDimitry Andric argVar->getType().getNonReferenceType(), VK_LValue, 13410b57cec5SDimitry Andric SourceLocation()); 1342480093f4SDimitry Andric llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer(CGF); 13430b57cec5SDimitry Andric args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy); 13440b57cec5SDimitry Andric 13450b57cec5SDimitry Andric // The third argument is the sizeof the type. 13460b57cec5SDimitry Andric llvm::Value *size = 13470b57cec5SDimitry Andric CGF.CGM.getSize(CGF.getContext().getTypeSizeInChars(ivar->getType())); 13480b57cec5SDimitry Andric args.add(RValue::get(size), CGF.getContext().getSizeType()); 13490b57cec5SDimitry Andric 13500b57cec5SDimitry Andric // The fourth argument is the 'isAtomic' flag. 13510b57cec5SDimitry Andric args.add(RValue::get(CGF.Builder.getTrue()), CGF.getContext().BoolTy); 13520b57cec5SDimitry Andric 13530b57cec5SDimitry Andric // The fifth argument is the 'hasStrong' flag. 13540b57cec5SDimitry Andric // FIXME: should this really always be false? 13550b57cec5SDimitry Andric args.add(RValue::get(CGF.Builder.getFalse()), CGF.getContext().BoolTy); 13560b57cec5SDimitry Andric 13570b57cec5SDimitry Andric llvm::FunctionCallee fn = CGF.CGM.getObjCRuntime().GetSetStructFunction(); 13580b57cec5SDimitry Andric CGCallee callee = CGCallee::forDirect(fn); 13590b57cec5SDimitry Andric CGF.EmitCall( 13600b57cec5SDimitry Andric CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), 13610b57cec5SDimitry Andric callee, ReturnValueSlot(), args); 13620b57cec5SDimitry Andric } 13630b57cec5SDimitry Andric 13640b57cec5SDimitry Andric /// emitCPPObjectAtomicSetterCall - Call the runtime function to store 13650b57cec5SDimitry Andric /// the value from the first formal parameter into the given ivar, using 13660b57cec5SDimitry Andric /// the Cpp API for atomic Cpp objects with non-trivial copy assignment. 13670b57cec5SDimitry Andric static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF, 13680b57cec5SDimitry Andric ObjCMethodDecl *OMD, 13690b57cec5SDimitry Andric ObjCIvarDecl *ivar, 13700b57cec5SDimitry Andric llvm::Constant *AtomicHelperFn) { 13710b57cec5SDimitry Andric // objc_copyCppObjectAtomic (&CppObjectIvar, &Arg, 13720b57cec5SDimitry Andric // AtomicHelperFn); 13730b57cec5SDimitry Andric CallArgList args; 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric // The first argument is the address of the ivar. 13760b57cec5SDimitry Andric llvm::Value *ivarAddr = 1377480093f4SDimitry Andric CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), CGF.LoadObjCSelf(), ivar, 0) 1378480093f4SDimitry Andric .getPointer(CGF); 13790b57cec5SDimitry Andric args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy); 13800b57cec5SDimitry Andric 13810b57cec5SDimitry Andric // The second argument is the address of the parameter variable. 13820b57cec5SDimitry Andric ParmVarDecl *argVar = *OMD->param_begin(); 13830b57cec5SDimitry Andric DeclRefExpr argRef(CGF.getContext(), argVar, false, 13840b57cec5SDimitry Andric argVar->getType().getNonReferenceType(), VK_LValue, 13850b57cec5SDimitry Andric SourceLocation()); 1386480093f4SDimitry Andric llvm::Value *argAddr = CGF.EmitLValue(&argRef).getPointer(CGF); 13870b57cec5SDimitry Andric args.add(RValue::get(argAddr), CGF.getContext().VoidPtrTy); 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric // Third argument is the helper function. 13900b57cec5SDimitry Andric args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy); 13910b57cec5SDimitry Andric 13920b57cec5SDimitry Andric llvm::FunctionCallee fn = 13930b57cec5SDimitry Andric CGF.CGM.getObjCRuntime().GetCppAtomicObjectSetFunction(); 13940b57cec5SDimitry Andric CGCallee callee = CGCallee::forDirect(fn); 13950b57cec5SDimitry Andric CGF.EmitCall( 13960b57cec5SDimitry Andric CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args), 13970b57cec5SDimitry Andric callee, ReturnValueSlot(), args); 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andric 14010b57cec5SDimitry Andric static bool hasTrivialSetExpr(const ObjCPropertyImplDecl *PID) { 14020b57cec5SDimitry Andric Expr *setter = PID->getSetterCXXAssignment(); 14030b57cec5SDimitry Andric if (!setter) return true; 14040b57cec5SDimitry Andric 14050b57cec5SDimitry Andric // Sema only makes only of these when the ivar has a C++ class type, 14060b57cec5SDimitry Andric // so the form is pretty constrained. 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric // An operator call is trivial if the function it calls is trivial. 14090b57cec5SDimitry Andric // This also implies that there's nothing non-trivial going on with 14100b57cec5SDimitry Andric // the arguments, because operator= can only be trivial if it's a 14110b57cec5SDimitry Andric // synthesized assignment operator and therefore both parameters are 14120b57cec5SDimitry Andric // references. 14130b57cec5SDimitry Andric if (CallExpr *call = dyn_cast<CallExpr>(setter)) { 14140b57cec5SDimitry Andric if (const FunctionDecl *callee 14150b57cec5SDimitry Andric = dyn_cast_or_null<FunctionDecl>(call->getCalleeDecl())) 14160b57cec5SDimitry Andric if (callee->isTrivial()) 14170b57cec5SDimitry Andric return true; 14180b57cec5SDimitry Andric return false; 14190b57cec5SDimitry Andric } 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric assert(isa<ExprWithCleanups>(setter)); 14220b57cec5SDimitry Andric return false; 14230b57cec5SDimitry Andric } 14240b57cec5SDimitry Andric 14250b57cec5SDimitry Andric static bool UseOptimizedSetter(CodeGenModule &CGM) { 14260b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() != LangOptions::NonGC) 14270b57cec5SDimitry Andric return false; 14280b57cec5SDimitry Andric return CGM.getLangOpts().ObjCRuntime.hasOptimizedSetter(); 14290b57cec5SDimitry Andric } 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric void 14320b57cec5SDimitry Andric CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, 14330b57cec5SDimitry Andric const ObjCPropertyImplDecl *propImpl, 14340b57cec5SDimitry Andric llvm::Constant *AtomicHelperFn) { 14350b57cec5SDimitry Andric ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); 1436480093f4SDimitry Andric ObjCMethodDecl *setterMethod = propImpl->getSetterMethodDecl(); 14370b57cec5SDimitry Andric 1438bdd1243dSDimitry Andric if (ivar->getType().isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) { 1439bdd1243dSDimitry Andric ParmVarDecl *PVD = *setterMethod->param_begin(); 1440bdd1243dSDimitry Andric if (!AtomicHelperFn) { 1441bdd1243dSDimitry Andric // Call the move assignment operator instead of calling the copy 1442bdd1243dSDimitry Andric // assignment operator and destructor. 1443bdd1243dSDimitry Andric LValue Dst = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, 1444bdd1243dSDimitry Andric /*quals*/ 0); 1445bdd1243dSDimitry Andric LValue Src = MakeAddrLValue(GetAddrOfLocalVar(PVD), ivar->getType()); 1446bdd1243dSDimitry Andric callCStructMoveAssignmentOperator(Dst, Src); 1447bdd1243dSDimitry Andric } else { 1448bdd1243dSDimitry Andric // If atomic, assignment is called via a locking api. 1449bdd1243dSDimitry Andric emitCPPObjectAtomicSetterCall(*this, setterMethod, ivar, AtomicHelperFn); 1450bdd1243dSDimitry Andric } 1451bdd1243dSDimitry Andric // Decativate the destructor for the setter parameter. 1452bdd1243dSDimitry Andric DeactivateCleanupBlock(CalleeDestructedParamCleanups[PVD], AllocaInsertPt); 1453bdd1243dSDimitry Andric return; 1454bdd1243dSDimitry Andric } 1455bdd1243dSDimitry Andric 14560b57cec5SDimitry Andric // Just use the setter expression if Sema gave us one and it's 14570b57cec5SDimitry Andric // non-trivial. 14580b57cec5SDimitry Andric if (!hasTrivialSetExpr(propImpl)) { 14590b57cec5SDimitry Andric if (!AtomicHelperFn) 14600b57cec5SDimitry Andric // If non-atomic, assignment is called directly. 14610b57cec5SDimitry Andric EmitStmt(propImpl->getSetterCXXAssignment()); 14620b57cec5SDimitry Andric else 14630b57cec5SDimitry Andric // If atomic, assignment is called via a locking api. 14640b57cec5SDimitry Andric emitCPPObjectAtomicSetterCall(*this, setterMethod, ivar, 14650b57cec5SDimitry Andric AtomicHelperFn); 14660b57cec5SDimitry Andric return; 14670b57cec5SDimitry Andric } 14680b57cec5SDimitry Andric 14690b57cec5SDimitry Andric PropertyImplStrategy strategy(CGM, propImpl); 14700b57cec5SDimitry Andric switch (strategy.getKind()) { 14710b57cec5SDimitry Andric case PropertyImplStrategy::Native: { 14720b57cec5SDimitry Andric // We don't need to do anything for a zero-size struct. 14730b57cec5SDimitry Andric if (strategy.getIvarSize().isZero()) 14740b57cec5SDimitry Andric return; 14750b57cec5SDimitry Andric 14760b57cec5SDimitry Andric Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin()); 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric LValue ivarLValue = 14790b57cec5SDimitry Andric EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, /*quals*/ 0); 1480*0fca6ea1SDimitry Andric Address ivarAddr = ivarLValue.getAddress(); 14810b57cec5SDimitry Andric 14820b57cec5SDimitry Andric // Currently, all atomic accesses have to be through integer 14830b57cec5SDimitry Andric // types, so there's no point in trying to pick a prettier type. 148406c3fb27SDimitry Andric llvm::Type *castType = llvm::Type::getIntNTy( 148506c3fb27SDimitry Andric getLLVMContext(), getContext().toBits(strategy.getIvarSize())); 14860b57cec5SDimitry Andric 14870b57cec5SDimitry Andric // Cast both arguments to the chosen operation type. 148806c3fb27SDimitry Andric argAddr = argAddr.withElementType(castType); 148906c3fb27SDimitry Andric ivarAddr = ivarAddr.withElementType(castType); 14900b57cec5SDimitry Andric 14910b57cec5SDimitry Andric llvm::Value *load = Builder.CreateLoad(argAddr); 14920b57cec5SDimitry Andric 14930b57cec5SDimitry Andric // Perform an atomic store. There are no memory ordering requirements. 14940b57cec5SDimitry Andric llvm::StoreInst *store = Builder.CreateStore(load, ivarAddr); 14950b57cec5SDimitry Andric store->setAtomic(llvm::AtomicOrdering::Unordered); 14960b57cec5SDimitry Andric return; 14970b57cec5SDimitry Andric } 14980b57cec5SDimitry Andric 14990b57cec5SDimitry Andric case PropertyImplStrategy::GetSetProperty: 15000b57cec5SDimitry Andric case PropertyImplStrategy::SetPropertyAndExpressionGet: { 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric llvm::FunctionCallee setOptimizedPropertyFn = nullptr; 15030b57cec5SDimitry Andric llvm::FunctionCallee setPropertyFn = nullptr; 15040b57cec5SDimitry Andric if (UseOptimizedSetter(CGM)) { 15050b57cec5SDimitry Andric // 10.8 and iOS 6.0 code and GC is off 15060b57cec5SDimitry Andric setOptimizedPropertyFn = 15070b57cec5SDimitry Andric CGM.getObjCRuntime().GetOptimizedPropertySetFunction( 15080b57cec5SDimitry Andric strategy.isAtomic(), strategy.isCopy()); 15090b57cec5SDimitry Andric if (!setOptimizedPropertyFn) { 15100b57cec5SDimitry Andric CGM.ErrorUnsupported(propImpl, "Obj-C optimized setter - NYI"); 15110b57cec5SDimitry Andric return; 15120b57cec5SDimitry Andric } 15130b57cec5SDimitry Andric } 15140b57cec5SDimitry Andric else { 15150b57cec5SDimitry Andric setPropertyFn = CGM.getObjCRuntime().GetPropertySetFunction(); 15160b57cec5SDimitry Andric if (!setPropertyFn) { 15170b57cec5SDimitry Andric CGM.ErrorUnsupported(propImpl, "Obj-C setter requiring atomic copy"); 15180b57cec5SDimitry Andric return; 15190b57cec5SDimitry Andric } 15200b57cec5SDimitry Andric } 15210b57cec5SDimitry Andric 15220b57cec5SDimitry Andric // Emit objc_setProperty((id) self, _cmd, offset, arg, 15230b57cec5SDimitry Andric // <is-atomic>, <is-copy>). 1524bdd1243dSDimitry Andric llvm::Value *cmd = emitCmdValueForGetterSetterBody(*this, setterMethod); 15250b57cec5SDimitry Andric llvm::Value *self = 15260b57cec5SDimitry Andric Builder.CreateBitCast(LoadObjCSelf(), VoidPtrTy); 15270b57cec5SDimitry Andric llvm::Value *ivarOffset = 1528bdd1243dSDimitry Andric EmitIvarOffsetAsPointerDiff(classImpl->getClassInterface(), ivar); 15290b57cec5SDimitry Andric Address argAddr = GetAddrOfLocalVar(*setterMethod->param_begin()); 15300b57cec5SDimitry Andric llvm::Value *arg = Builder.CreateLoad(argAddr, "arg"); 15310b57cec5SDimitry Andric arg = Builder.CreateBitCast(arg, VoidPtrTy); 15320b57cec5SDimitry Andric 15330b57cec5SDimitry Andric CallArgList args; 15340b57cec5SDimitry Andric args.add(RValue::get(self), getContext().getObjCIdType()); 15350b57cec5SDimitry Andric args.add(RValue::get(cmd), getContext().getObjCSelType()); 15360b57cec5SDimitry Andric if (setOptimizedPropertyFn) { 15370b57cec5SDimitry Andric args.add(RValue::get(arg), getContext().getObjCIdType()); 15380b57cec5SDimitry Andric args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); 15390b57cec5SDimitry Andric CGCallee callee = CGCallee::forDirect(setOptimizedPropertyFn); 15400b57cec5SDimitry Andric EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args), 15410b57cec5SDimitry Andric callee, ReturnValueSlot(), args); 15420b57cec5SDimitry Andric } else { 15430b57cec5SDimitry Andric args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); 15440b57cec5SDimitry Andric args.add(RValue::get(arg), getContext().getObjCIdType()); 15450b57cec5SDimitry Andric args.add(RValue::get(Builder.getInt1(strategy.isAtomic())), 15460b57cec5SDimitry Andric getContext().BoolTy); 15470b57cec5SDimitry Andric args.add(RValue::get(Builder.getInt1(strategy.isCopy())), 15480b57cec5SDimitry Andric getContext().BoolTy); 15490b57cec5SDimitry Andric // FIXME: We shouldn't need to get the function info here, the runtime 15500b57cec5SDimitry Andric // already should have computed it to build the function. 15510b57cec5SDimitry Andric CGCallee callee = CGCallee::forDirect(setPropertyFn); 15520b57cec5SDimitry Andric EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args), 15530b57cec5SDimitry Andric callee, ReturnValueSlot(), args); 15540b57cec5SDimitry Andric } 15550b57cec5SDimitry Andric 15560b57cec5SDimitry Andric return; 15570b57cec5SDimitry Andric } 15580b57cec5SDimitry Andric 15590b57cec5SDimitry Andric case PropertyImplStrategy::CopyStruct: 15600b57cec5SDimitry Andric emitStructSetterCall(*this, setterMethod, ivar); 15610b57cec5SDimitry Andric return; 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric case PropertyImplStrategy::Expression: 15640b57cec5SDimitry Andric break; 15650b57cec5SDimitry Andric } 15660b57cec5SDimitry Andric 15670b57cec5SDimitry Andric // Otherwise, fake up some ASTs and emit a normal assignment. 15680b57cec5SDimitry Andric ValueDecl *selfDecl = setterMethod->getSelfDecl(); 15690b57cec5SDimitry Andric DeclRefExpr self(getContext(), selfDecl, false, selfDecl->getType(), 15700b57cec5SDimitry Andric VK_LValue, SourceLocation()); 1571e8d8bef9SDimitry Andric ImplicitCastExpr selfLoad(ImplicitCastExpr::OnStack, selfDecl->getType(), 1572fe6060f1SDimitry Andric CK_LValueToRValue, &self, VK_PRValue, 1573e8d8bef9SDimitry Andric FPOptionsOverride()); 15740b57cec5SDimitry Andric ObjCIvarRefExpr ivarRef(ivar, ivar->getType().getNonReferenceType(), 15750b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 15760b57cec5SDimitry Andric &selfLoad, true, true); 15770b57cec5SDimitry Andric 15780b57cec5SDimitry Andric ParmVarDecl *argDecl = *setterMethod->param_begin(); 15790b57cec5SDimitry Andric QualType argType = argDecl->getType().getNonReferenceType(); 15800b57cec5SDimitry Andric DeclRefExpr arg(getContext(), argDecl, false, argType, VK_LValue, 15810b57cec5SDimitry Andric SourceLocation()); 15820b57cec5SDimitry Andric ImplicitCastExpr argLoad(ImplicitCastExpr::OnStack, 15830b57cec5SDimitry Andric argType.getUnqualifiedType(), CK_LValueToRValue, 1584fe6060f1SDimitry Andric &arg, VK_PRValue, FPOptionsOverride()); 15850b57cec5SDimitry Andric 15860b57cec5SDimitry Andric // The property type can differ from the ivar type in some situations with 15870b57cec5SDimitry Andric // Objective-C pointer types, we can always bit cast the RHS in these cases. 15880b57cec5SDimitry Andric // The following absurdity is just to ensure well-formed IR. 15890b57cec5SDimitry Andric CastKind argCK = CK_NoOp; 15900b57cec5SDimitry Andric if (ivarRef.getType()->isObjCObjectPointerType()) { 15910b57cec5SDimitry Andric if (argLoad.getType()->isObjCObjectPointerType()) 15920b57cec5SDimitry Andric argCK = CK_BitCast; 15930b57cec5SDimitry Andric else if (argLoad.getType()->isBlockPointerType()) 15940b57cec5SDimitry Andric argCK = CK_BlockPointerToObjCPointerCast; 15950b57cec5SDimitry Andric else 15960b57cec5SDimitry Andric argCK = CK_CPointerToObjCPointerCast; 15970b57cec5SDimitry Andric } else if (ivarRef.getType()->isBlockPointerType()) { 15980b57cec5SDimitry Andric if (argLoad.getType()->isBlockPointerType()) 15990b57cec5SDimitry Andric argCK = CK_BitCast; 16000b57cec5SDimitry Andric else 16010b57cec5SDimitry Andric argCK = CK_AnyPointerToBlockPointerCast; 16020b57cec5SDimitry Andric } else if (ivarRef.getType()->isPointerType()) { 16030b57cec5SDimitry Andric argCK = CK_BitCast; 1604349cc55cSDimitry Andric } else if (argLoad.getType()->isAtomicType() && 1605349cc55cSDimitry Andric !ivarRef.getType()->isAtomicType()) { 1606349cc55cSDimitry Andric argCK = CK_AtomicToNonAtomic; 1607349cc55cSDimitry Andric } else if (!argLoad.getType()->isAtomicType() && 1608349cc55cSDimitry Andric ivarRef.getType()->isAtomicType()) { 1609349cc55cSDimitry Andric argCK = CK_NonAtomicToAtomic; 16100b57cec5SDimitry Andric } 1611e8d8bef9SDimitry Andric ImplicitCastExpr argCast(ImplicitCastExpr::OnStack, ivarRef.getType(), argCK, 1612fe6060f1SDimitry Andric &argLoad, VK_PRValue, FPOptionsOverride()); 16130b57cec5SDimitry Andric Expr *finalArg = &argLoad; 16140b57cec5SDimitry Andric if (!getContext().hasSameUnqualifiedType(ivarRef.getType(), 16150b57cec5SDimitry Andric argLoad.getType())) 16160b57cec5SDimitry Andric finalArg = &argCast; 16170b57cec5SDimitry Andric 16185ffd83dbSDimitry Andric BinaryOperator *assign = BinaryOperator::Create( 1619fe6060f1SDimitry Andric getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(), 1620fe6060f1SDimitry Andric VK_PRValue, OK_Ordinary, SourceLocation(), FPOptionsOverride()); 16215ffd83dbSDimitry Andric EmitStmt(assign); 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric 16240b57cec5SDimitry Andric /// Generate an Objective-C property setter function. 16250b57cec5SDimitry Andric /// 16260b57cec5SDimitry Andric /// The given Decl must be an ObjCImplementationDecl. \@synthesize 16270b57cec5SDimitry Andric /// is illegal within a category. 16280b57cec5SDimitry Andric void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, 16290b57cec5SDimitry Andric const ObjCPropertyImplDecl *PID) { 16300b57cec5SDimitry Andric llvm::Constant *AtomicHelperFn = 16310b57cec5SDimitry Andric CodeGenFunction(CGM).GenerateObjCAtomicSetterCopyHelperFunction(PID); 1632480093f4SDimitry Andric ObjCMethodDecl *OMD = PID->getSetterMethodDecl(); 16330b57cec5SDimitry Andric assert(OMD && "Invalid call to generate setter (empty method)"); 16340b57cec5SDimitry Andric StartObjCMethod(OMD, IMP->getClassInterface()); 16350b57cec5SDimitry Andric 16360b57cec5SDimitry Andric generateObjCSetterBody(IMP, PID, AtomicHelperFn); 16370b57cec5SDimitry Andric 1638480093f4SDimitry Andric FinishFunction(OMD->getEndLoc()); 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric namespace { 16420b57cec5SDimitry Andric struct DestroyIvar final : EHScopeStack::Cleanup { 16430b57cec5SDimitry Andric private: 16440b57cec5SDimitry Andric llvm::Value *addr; 16450b57cec5SDimitry Andric const ObjCIvarDecl *ivar; 16460b57cec5SDimitry Andric CodeGenFunction::Destroyer *destroyer; 16470b57cec5SDimitry Andric bool useEHCleanupForArray; 16480b57cec5SDimitry Andric public: 16490b57cec5SDimitry Andric DestroyIvar(llvm::Value *addr, const ObjCIvarDecl *ivar, 16500b57cec5SDimitry Andric CodeGenFunction::Destroyer *destroyer, 16510b57cec5SDimitry Andric bool useEHCleanupForArray) 16520b57cec5SDimitry Andric : addr(addr), ivar(ivar), destroyer(destroyer), 16530b57cec5SDimitry Andric useEHCleanupForArray(useEHCleanupForArray) {} 16540b57cec5SDimitry Andric 16550b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override { 16560b57cec5SDimitry Andric LValue lvalue 16570b57cec5SDimitry Andric = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), addr, ivar, /*CVR*/ 0); 1658*0fca6ea1SDimitry Andric CGF.emitDestroy(lvalue.getAddress(), ivar->getType(), destroyer, 16590b57cec5SDimitry Andric flags.isForNormalCleanup() && useEHCleanupForArray); 16600b57cec5SDimitry Andric } 16610b57cec5SDimitry Andric }; 16620b57cec5SDimitry Andric } 16630b57cec5SDimitry Andric 16640b57cec5SDimitry Andric /// Like CodeGenFunction::destroyARCStrong, but do it with a call. 16650b57cec5SDimitry Andric static void destroyARCStrongWithStore(CodeGenFunction &CGF, 16660b57cec5SDimitry Andric Address addr, 16670b57cec5SDimitry Andric QualType type) { 16680b57cec5SDimitry Andric llvm::Value *null = getNullForVariable(addr); 16690b57cec5SDimitry Andric CGF.EmitARCStoreStrongCall(addr, null, /*ignored*/ true); 16700b57cec5SDimitry Andric } 16710b57cec5SDimitry Andric 16720b57cec5SDimitry Andric static void emitCXXDestructMethod(CodeGenFunction &CGF, 16730b57cec5SDimitry Andric ObjCImplementationDecl *impl) { 16740b57cec5SDimitry Andric CodeGenFunction::RunCleanupsScope scope(CGF); 16750b57cec5SDimitry Andric 16760b57cec5SDimitry Andric llvm::Value *self = CGF.LoadObjCSelf(); 16770b57cec5SDimitry Andric 16780b57cec5SDimitry Andric const ObjCInterfaceDecl *iface = impl->getClassInterface(); 16790b57cec5SDimitry Andric for (const ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); 16800b57cec5SDimitry Andric ivar; ivar = ivar->getNextIvar()) { 16810b57cec5SDimitry Andric QualType type = ivar->getType(); 16820b57cec5SDimitry Andric 16830b57cec5SDimitry Andric // Check whether the ivar is a destructible type. 16840b57cec5SDimitry Andric QualType::DestructionKind dtorKind = type.isDestructedType(); 16850b57cec5SDimitry Andric if (!dtorKind) continue; 16860b57cec5SDimitry Andric 16870b57cec5SDimitry Andric CodeGenFunction::Destroyer *destroyer = nullptr; 16880b57cec5SDimitry Andric 16890b57cec5SDimitry Andric // Use a call to objc_storeStrong to destroy strong ivars, for the 16900b57cec5SDimitry Andric // general benefit of the tools. 16910b57cec5SDimitry Andric if (dtorKind == QualType::DK_objc_strong_lifetime) { 16920b57cec5SDimitry Andric destroyer = destroyARCStrongWithStore; 16930b57cec5SDimitry Andric 16940b57cec5SDimitry Andric // Otherwise use the default for the destruction kind. 16950b57cec5SDimitry Andric } else { 16960b57cec5SDimitry Andric destroyer = CGF.getDestroyer(dtorKind); 16970b57cec5SDimitry Andric } 16980b57cec5SDimitry Andric 16990b57cec5SDimitry Andric CleanupKind cleanupKind = CGF.getCleanupKind(dtorKind); 17000b57cec5SDimitry Andric 17010b57cec5SDimitry Andric CGF.EHStack.pushCleanup<DestroyIvar>(cleanupKind, self, ivar, destroyer, 17020b57cec5SDimitry Andric cleanupKind & EHCleanup); 17030b57cec5SDimitry Andric } 17040b57cec5SDimitry Andric 17050b57cec5SDimitry Andric assert(scope.requiresCleanups() && "nothing to do in .cxx_destruct?"); 17060b57cec5SDimitry Andric } 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, 17090b57cec5SDimitry Andric ObjCMethodDecl *MD, 17100b57cec5SDimitry Andric bool ctor) { 17110b57cec5SDimitry Andric MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface()); 17120b57cec5SDimitry Andric StartObjCMethod(MD, IMP->getClassInterface()); 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric // Emit .cxx_construct. 17150b57cec5SDimitry Andric if (ctor) { 17160b57cec5SDimitry Andric // Suppress the final autorelease in ARC. 17170b57cec5SDimitry Andric AutoreleaseResult = false; 17180b57cec5SDimitry Andric 17190b57cec5SDimitry Andric for (const auto *IvarInit : IMP->inits()) { 17200b57cec5SDimitry Andric FieldDecl *Field = IvarInit->getAnyMember(); 17210b57cec5SDimitry Andric ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field); 17220b57cec5SDimitry Andric LValue LV = EmitLValueForIvar(TypeOfSelfObject(), 17230b57cec5SDimitry Andric LoadObjCSelf(), Ivar, 0); 17240b57cec5SDimitry Andric EmitAggExpr(IvarInit->getInit(), 1725*0fca6ea1SDimitry Andric AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed, 17260b57cec5SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers, 17270b57cec5SDimitry Andric AggValueSlot::IsNotAliased, 17280b57cec5SDimitry Andric AggValueSlot::DoesNotOverlap)); 17290b57cec5SDimitry Andric } 17300b57cec5SDimitry Andric // constructor returns 'self'. 17310b57cec5SDimitry Andric CodeGenTypes &Types = CGM.getTypes(); 17320b57cec5SDimitry Andric QualType IdTy(CGM.getContext().getObjCIdType()); 17330b57cec5SDimitry Andric llvm::Value *SelfAsId = 17340b57cec5SDimitry Andric Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 17350b57cec5SDimitry Andric EmitReturnOfRValue(RValue::get(SelfAsId), IdTy); 17360b57cec5SDimitry Andric 17370b57cec5SDimitry Andric // Emit .cxx_destruct. 17380b57cec5SDimitry Andric } else { 17390b57cec5SDimitry Andric emitCXXDestructMethod(*this, IMP); 17400b57cec5SDimitry Andric } 17410b57cec5SDimitry Andric FinishFunction(); 17420b57cec5SDimitry Andric } 17430b57cec5SDimitry Andric 17440b57cec5SDimitry Andric llvm::Value *CodeGenFunction::LoadObjCSelf() { 17450b57cec5SDimitry Andric VarDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl(); 17460b57cec5SDimitry Andric DeclRefExpr DRE(getContext(), Self, 17470b57cec5SDimitry Andric /*is enclosing local*/ (CurFuncDecl != CurCodeDecl), 17480b57cec5SDimitry Andric Self->getType(), VK_LValue, SourceLocation()); 17490b57cec5SDimitry Andric return EmitLoadOfScalar(EmitDeclRefLValue(&DRE), SourceLocation()); 17500b57cec5SDimitry Andric } 17510b57cec5SDimitry Andric 17520b57cec5SDimitry Andric QualType CodeGenFunction::TypeOfSelfObject() { 17530b57cec5SDimitry Andric const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 17540b57cec5SDimitry Andric ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); 17550b57cec5SDimitry Andric const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( 17560b57cec5SDimitry Andric getContext().getCanonicalType(selfDecl->getType())); 17570b57cec5SDimitry Andric return PTy->getPointeeType(); 17580b57cec5SDimitry Andric } 17590b57cec5SDimitry Andric 17600b57cec5SDimitry Andric void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ 17610b57cec5SDimitry Andric llvm::FunctionCallee EnumerationMutationFnPtr = 17620b57cec5SDimitry Andric CGM.getObjCRuntime().EnumerationMutationFunction(); 17630b57cec5SDimitry Andric if (!EnumerationMutationFnPtr) { 17640b57cec5SDimitry Andric CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); 17650b57cec5SDimitry Andric return; 17660b57cec5SDimitry Andric } 17670b57cec5SDimitry Andric CGCallee EnumerationMutationFn = 17680b57cec5SDimitry Andric CGCallee::forDirect(EnumerationMutationFnPtr); 17690b57cec5SDimitry Andric 17700b57cec5SDimitry Andric CGDebugInfo *DI = getDebugInfo(); 17710b57cec5SDimitry Andric if (DI) 17720b57cec5SDimitry Andric DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin()); 17730b57cec5SDimitry Andric 17740b57cec5SDimitry Andric RunCleanupsScope ForScope(*this); 17750b57cec5SDimitry Andric 17760b57cec5SDimitry Andric // The local variable comes into scope immediately. 17770b57cec5SDimitry Andric AutoVarEmission variable = AutoVarEmission::invalid(); 17780b57cec5SDimitry Andric if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) 17790b57cec5SDimitry Andric variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl())); 17800b57cec5SDimitry Andric 17810b57cec5SDimitry Andric JumpDest LoopEnd = getJumpDestInCurrentScope("forcoll.end"); 17820b57cec5SDimitry Andric 17830b57cec5SDimitry Andric // Fast enumeration state. 17840b57cec5SDimitry Andric QualType StateTy = CGM.getObjCFastEnumerationStateType(); 17850b57cec5SDimitry Andric Address StatePtr = CreateMemTemp(StateTy, "state.ptr"); 17860b57cec5SDimitry Andric EmitNullInitialization(StatePtr, StateTy); 17870b57cec5SDimitry Andric 17880b57cec5SDimitry Andric // Number of elements in the items array. 17890b57cec5SDimitry Andric static const unsigned NumItems = 16; 17900b57cec5SDimitry Andric 17910b57cec5SDimitry Andric // Fetch the countByEnumeratingWithState:objects:count: selector. 1792*0fca6ea1SDimitry Andric const IdentifierInfo *II[] = { 17930b57cec5SDimitry Andric &CGM.getContext().Idents.get("countByEnumeratingWithState"), 17940b57cec5SDimitry Andric &CGM.getContext().Idents.get("objects"), 1795*0fca6ea1SDimitry Andric &CGM.getContext().Idents.get("count")}; 17960b57cec5SDimitry Andric Selector FastEnumSel = 1797bdd1243dSDimitry Andric CGM.getContext().Selectors.getSelector(std::size(II), &II[0]); 17980b57cec5SDimitry Andric 17995f757f3fSDimitry Andric QualType ItemsTy = getContext().getConstantArrayType( 18005f757f3fSDimitry Andric getContext().getObjCIdType(), llvm::APInt(32, NumItems), nullptr, 18015f757f3fSDimitry Andric ArraySizeModifier::Normal, 0); 18020b57cec5SDimitry Andric Address ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr"); 18030b57cec5SDimitry Andric 18040b57cec5SDimitry Andric // Emit the collection pointer. In ARC, we do a retain. 18050b57cec5SDimitry Andric llvm::Value *Collection; 18060b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount) { 18070b57cec5SDimitry Andric Collection = EmitARCRetainScalarExpr(S.getCollection()); 18080b57cec5SDimitry Andric 18090b57cec5SDimitry Andric // Enter a cleanup to do the release. 18100b57cec5SDimitry Andric EmitObjCConsumeObject(S.getCollection()->getType(), Collection); 18110b57cec5SDimitry Andric } else { 18120b57cec5SDimitry Andric Collection = EmitScalarExpr(S.getCollection()); 18130b57cec5SDimitry Andric } 18140b57cec5SDimitry Andric 18150b57cec5SDimitry Andric // The 'continue' label needs to appear within the cleanup for the 18160b57cec5SDimitry Andric // collection object. 18170b57cec5SDimitry Andric JumpDest AfterBody = getJumpDestInCurrentScope("forcoll.next"); 18180b57cec5SDimitry Andric 18190b57cec5SDimitry Andric // Send it our message: 18200b57cec5SDimitry Andric CallArgList Args; 18210b57cec5SDimitry Andric 18220b57cec5SDimitry Andric // The first argument is a temporary of the enumeration-state type. 1823*0fca6ea1SDimitry Andric Args.add(RValue::get(StatePtr, *this), getContext().getPointerType(StateTy)); 18240b57cec5SDimitry Andric 18250b57cec5SDimitry Andric // The second argument is a temporary array with space for NumItems 18260b57cec5SDimitry Andric // pointers. We'll actually be loading elements from the array 18270b57cec5SDimitry Andric // pointer written into the control state; this buffer is so that 18280b57cec5SDimitry Andric // collections that *aren't* backed by arrays can still queue up 18290b57cec5SDimitry Andric // batches of elements. 1830*0fca6ea1SDimitry Andric Args.add(RValue::get(ItemsPtr, *this), getContext().getPointerType(ItemsTy)); 18310b57cec5SDimitry Andric 18320b57cec5SDimitry Andric // The third argument is the capacity of that temporary array. 18330b57cec5SDimitry Andric llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType()); 18340b57cec5SDimitry Andric llvm::Constant *Count = llvm::ConstantInt::get(NSUIntegerTy, NumItems); 18350b57cec5SDimitry Andric Args.add(RValue::get(Count), getContext().getNSUIntegerType()); 18360b57cec5SDimitry Andric 18370b57cec5SDimitry Andric // Start the enumeration. 18380b57cec5SDimitry Andric RValue CountRV = 18390b57cec5SDimitry Andric CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), 18400b57cec5SDimitry Andric getContext().getNSUIntegerType(), 18410b57cec5SDimitry Andric FastEnumSel, Collection, Args); 18420b57cec5SDimitry Andric 18430b57cec5SDimitry Andric // The initial number of objects that were returned in the buffer. 18440b57cec5SDimitry Andric llvm::Value *initialBufferLimit = CountRV.getScalarVal(); 18450b57cec5SDimitry Andric 18460b57cec5SDimitry Andric llvm::BasicBlock *EmptyBB = createBasicBlock("forcoll.empty"); 18470b57cec5SDimitry Andric llvm::BasicBlock *LoopInitBB = createBasicBlock("forcoll.loopinit"); 18480b57cec5SDimitry Andric 18490b57cec5SDimitry Andric llvm::Value *zero = llvm::Constant::getNullValue(NSUIntegerTy); 18500b57cec5SDimitry Andric 18510b57cec5SDimitry Andric // If the limit pointer was zero to begin with, the collection is 18520b57cec5SDimitry Andric // empty; skip all this. Set the branch weight assuming this has the same 18530b57cec5SDimitry Andric // probability of exiting the loop as any other loop exit. 18540b57cec5SDimitry Andric uint64_t EntryCount = getCurrentProfileCount(); 18550b57cec5SDimitry Andric Builder.CreateCondBr( 18560b57cec5SDimitry Andric Builder.CreateICmpEQ(initialBufferLimit, zero, "iszero"), EmptyBB, 18570b57cec5SDimitry Andric LoopInitBB, 18580b57cec5SDimitry Andric createProfileWeights(EntryCount, getProfileCount(S.getBody()))); 18590b57cec5SDimitry Andric 18600b57cec5SDimitry Andric // Otherwise, initialize the loop. 18610b57cec5SDimitry Andric EmitBlock(LoopInitBB); 18620b57cec5SDimitry Andric 18630b57cec5SDimitry Andric // Save the initial mutations value. This is the value at an 18640b57cec5SDimitry Andric // address that was written into the state object by 18650b57cec5SDimitry Andric // countByEnumeratingWithState:objects:count:. 18660b57cec5SDimitry Andric Address StateMutationsPtrPtr = 18670b57cec5SDimitry Andric Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr"); 18680b57cec5SDimitry Andric llvm::Value *StateMutationsPtr 18690b57cec5SDimitry Andric = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); 18700b57cec5SDimitry Andric 1871fe6060f1SDimitry Andric llvm::Type *UnsignedLongTy = ConvertType(getContext().UnsignedLongTy); 18720b57cec5SDimitry Andric llvm::Value *initialMutations = 1873fe6060f1SDimitry Andric Builder.CreateAlignedLoad(UnsignedLongTy, StateMutationsPtr, 1874fe6060f1SDimitry Andric getPointerAlign(), "forcoll.initial-mutations"); 18750b57cec5SDimitry Andric 18760b57cec5SDimitry Andric // Start looping. This is the point we return to whenever we have a 18770b57cec5SDimitry Andric // fresh, non-empty batch of objects. 18780b57cec5SDimitry Andric llvm::BasicBlock *LoopBodyBB = createBasicBlock("forcoll.loopbody"); 18790b57cec5SDimitry Andric EmitBlock(LoopBodyBB); 18800b57cec5SDimitry Andric 18810b57cec5SDimitry Andric // The current index into the buffer. 18820b57cec5SDimitry Andric llvm::PHINode *index = Builder.CreatePHI(NSUIntegerTy, 3, "forcoll.index"); 18830b57cec5SDimitry Andric index->addIncoming(zero, LoopInitBB); 18840b57cec5SDimitry Andric 18850b57cec5SDimitry Andric // The current buffer size. 18860b57cec5SDimitry Andric llvm::PHINode *count = Builder.CreatePHI(NSUIntegerTy, 3, "forcoll.count"); 18870b57cec5SDimitry Andric count->addIncoming(initialBufferLimit, LoopInitBB); 18880b57cec5SDimitry Andric 18890b57cec5SDimitry Andric incrementProfileCounter(&S); 18900b57cec5SDimitry Andric 18910b57cec5SDimitry Andric // Check whether the mutations value has changed from where it was 18920b57cec5SDimitry Andric // at start. StateMutationsPtr should actually be invariant between 18930b57cec5SDimitry Andric // refreshes. 18940b57cec5SDimitry Andric StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); 18950b57cec5SDimitry Andric llvm::Value *currentMutations 1896fe6060f1SDimitry Andric = Builder.CreateAlignedLoad(UnsignedLongTy, StateMutationsPtr, 1897fe6060f1SDimitry Andric getPointerAlign(), "statemutations"); 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated"); 19000b57cec5SDimitry Andric llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcoll.notmutated"); 19010b57cec5SDimitry Andric 19020b57cec5SDimitry Andric Builder.CreateCondBr(Builder.CreateICmpEQ(currentMutations, initialMutations), 19030b57cec5SDimitry Andric WasNotMutatedBB, WasMutatedBB); 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric // If so, call the enumeration-mutation function. 19060b57cec5SDimitry Andric EmitBlock(WasMutatedBB); 1907fe6060f1SDimitry Andric llvm::Type *ObjCIdType = ConvertType(getContext().getObjCIdType()); 19080b57cec5SDimitry Andric llvm::Value *V = 1909fe6060f1SDimitry Andric Builder.CreateBitCast(Collection, ObjCIdType); 19100b57cec5SDimitry Andric CallArgList Args2; 19110b57cec5SDimitry Andric Args2.add(RValue::get(V), getContext().getObjCIdType()); 19120b57cec5SDimitry Andric // FIXME: We shouldn't need to get the function info here, the runtime already 19130b57cec5SDimitry Andric // should have computed it to build the function. 19140b57cec5SDimitry Andric EmitCall( 19150b57cec5SDimitry Andric CGM.getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, Args2), 19160b57cec5SDimitry Andric EnumerationMutationFn, ReturnValueSlot(), Args2); 19170b57cec5SDimitry Andric 19180b57cec5SDimitry Andric // Otherwise, or if the mutation function returns, just continue. 19190b57cec5SDimitry Andric EmitBlock(WasNotMutatedBB); 19200b57cec5SDimitry Andric 19210b57cec5SDimitry Andric // Initialize the element variable. 19220b57cec5SDimitry Andric RunCleanupsScope elementVariableScope(*this); 19230b57cec5SDimitry Andric bool elementIsVariable; 19240b57cec5SDimitry Andric LValue elementLValue; 19250b57cec5SDimitry Andric QualType elementType; 19260b57cec5SDimitry Andric if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { 19270b57cec5SDimitry Andric // Initialize the variable, in case it's a __block variable or something. 19280b57cec5SDimitry Andric EmitAutoVarInit(variable); 19290b57cec5SDimitry Andric 19300b57cec5SDimitry Andric const VarDecl *D = cast<VarDecl>(SD->getSingleDecl()); 19310b57cec5SDimitry Andric DeclRefExpr tempDRE(getContext(), const_cast<VarDecl *>(D), false, 19320b57cec5SDimitry Andric D->getType(), VK_LValue, SourceLocation()); 19330b57cec5SDimitry Andric elementLValue = EmitLValue(&tempDRE); 19340b57cec5SDimitry Andric elementType = D->getType(); 19350b57cec5SDimitry Andric elementIsVariable = true; 19360b57cec5SDimitry Andric 19370b57cec5SDimitry Andric if (D->isARCPseudoStrong()) 19380b57cec5SDimitry Andric elementLValue.getQuals().setObjCLifetime(Qualifiers::OCL_ExplicitNone); 19390b57cec5SDimitry Andric } else { 19400b57cec5SDimitry Andric elementLValue = LValue(); // suppress warning 19410b57cec5SDimitry Andric elementType = cast<Expr>(S.getElement())->getType(); 19420b57cec5SDimitry Andric elementIsVariable = false; 19430b57cec5SDimitry Andric } 19440b57cec5SDimitry Andric llvm::Type *convertedElementType = ConvertType(elementType); 19450b57cec5SDimitry Andric 19460b57cec5SDimitry Andric // Fetch the buffer out of the enumeration state. 19470b57cec5SDimitry Andric // TODO: this pointer should actually be invariant between 19480b57cec5SDimitry Andric // refreshes, which would help us do certain loop optimizations. 19490b57cec5SDimitry Andric Address StateItemsPtr = 19500b57cec5SDimitry Andric Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr"); 19510b57cec5SDimitry Andric llvm::Value *EnumStateItems = 19520b57cec5SDimitry Andric Builder.CreateLoad(StateItemsPtr, "stateitems"); 19530b57cec5SDimitry Andric 19540b57cec5SDimitry Andric // Fetch the value at the current index from the buffer. 1955*0fca6ea1SDimitry Andric llvm::Value *CurrentItemPtr = Builder.CreateInBoundsGEP( 195681ad6265SDimitry Andric ObjCIdType, EnumStateItems, index, "currentitem.ptr"); 19570b57cec5SDimitry Andric llvm::Value *CurrentItem = 1958fe6060f1SDimitry Andric Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign()); 19590b57cec5SDimitry Andric 19605ffd83dbSDimitry Andric if (SanOpts.has(SanitizerKind::ObjCCast)) { 19615ffd83dbSDimitry Andric // Before using an item from the collection, check that the implicit cast 19625ffd83dbSDimitry Andric // from id to the element type is valid. This is done with instrumentation 19635ffd83dbSDimitry Andric // roughly corresponding to: 19645ffd83dbSDimitry Andric // 19655ffd83dbSDimitry Andric // if (![item isKindOfClass:expectedCls]) { /* emit diagnostic */ } 19665ffd83dbSDimitry Andric const ObjCObjectPointerType *ObjPtrTy = 19675ffd83dbSDimitry Andric elementType->getAsObjCInterfacePointerType(); 19685ffd83dbSDimitry Andric const ObjCInterfaceType *InterfaceTy = 19695ffd83dbSDimitry Andric ObjPtrTy ? ObjPtrTy->getInterfaceType() : nullptr; 19705ffd83dbSDimitry Andric if (InterfaceTy) { 19715ffd83dbSDimitry Andric SanitizerScope SanScope(this); 19725ffd83dbSDimitry Andric auto &C = CGM.getContext(); 19735ffd83dbSDimitry Andric assert(InterfaceTy->getDecl() && "No decl for ObjC interface type"); 19745ffd83dbSDimitry Andric Selector IsKindOfClassSel = GetUnarySelector("isKindOfClass", C); 19755ffd83dbSDimitry Andric CallArgList IsKindOfClassArgs; 19765ffd83dbSDimitry Andric llvm::Value *Cls = 19775ffd83dbSDimitry Andric CGM.getObjCRuntime().GetClass(*this, InterfaceTy->getDecl()); 19785ffd83dbSDimitry Andric IsKindOfClassArgs.add(RValue::get(Cls), C.getObjCClassType()); 19795ffd83dbSDimitry Andric llvm::Value *IsClass = 19805ffd83dbSDimitry Andric CGM.getObjCRuntime() 19815ffd83dbSDimitry Andric .GenerateMessageSend(*this, ReturnValueSlot(), C.BoolTy, 19825ffd83dbSDimitry Andric IsKindOfClassSel, CurrentItem, 19835ffd83dbSDimitry Andric IsKindOfClassArgs) 19845ffd83dbSDimitry Andric .getScalarVal(); 19855ffd83dbSDimitry Andric llvm::Constant *StaticData[] = { 19865ffd83dbSDimitry Andric EmitCheckSourceLocation(S.getBeginLoc()), 19875ffd83dbSDimitry Andric EmitCheckTypeDescriptor(QualType(InterfaceTy, 0))}; 19885ffd83dbSDimitry Andric EmitCheck({{IsClass, SanitizerKind::ObjCCast}}, 19895ffd83dbSDimitry Andric SanitizerHandler::InvalidObjCCast, 19905ffd83dbSDimitry Andric ArrayRef<llvm::Constant *>(StaticData), CurrentItem); 19915ffd83dbSDimitry Andric } 19925ffd83dbSDimitry Andric } 19935ffd83dbSDimitry Andric 19940b57cec5SDimitry Andric // Cast that value to the right type. 19950b57cec5SDimitry Andric CurrentItem = Builder.CreateBitCast(CurrentItem, convertedElementType, 19960b57cec5SDimitry Andric "currentitem"); 19970b57cec5SDimitry Andric 19980b57cec5SDimitry Andric // Make sure we have an l-value. Yes, this gets evaluated every 19990b57cec5SDimitry Andric // time through the loop. 20000b57cec5SDimitry Andric if (!elementIsVariable) { 20010b57cec5SDimitry Andric elementLValue = EmitLValue(cast<Expr>(S.getElement())); 20020b57cec5SDimitry Andric EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue); 20030b57cec5SDimitry Andric } else { 20040b57cec5SDimitry Andric EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, 20050b57cec5SDimitry Andric /*isInit*/ true); 20060b57cec5SDimitry Andric } 20070b57cec5SDimitry Andric 20080b57cec5SDimitry Andric // If we do have an element variable, this assignment is the end of 20090b57cec5SDimitry Andric // its initialization. 20100b57cec5SDimitry Andric if (elementIsVariable) 20110b57cec5SDimitry Andric EmitAutoVarCleanups(variable); 20120b57cec5SDimitry Andric 20130b57cec5SDimitry Andric // Perform the loop body, setting up break and continue labels. 20140b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); 20150b57cec5SDimitry Andric { 20160b57cec5SDimitry Andric RunCleanupsScope Scope(*this); 20170b57cec5SDimitry Andric EmitStmt(S.getBody()); 20180b57cec5SDimitry Andric } 20190b57cec5SDimitry Andric BreakContinueStack.pop_back(); 20200b57cec5SDimitry Andric 20210b57cec5SDimitry Andric // Destroy the element variable now. 20220b57cec5SDimitry Andric elementVariableScope.ForceCleanup(); 20230b57cec5SDimitry Andric 20240b57cec5SDimitry Andric // Check whether there are more elements. 20250b57cec5SDimitry Andric EmitBlock(AfterBody.getBlock()); 20260b57cec5SDimitry Andric 20270b57cec5SDimitry Andric llvm::BasicBlock *FetchMoreBB = createBasicBlock("forcoll.refetch"); 20280b57cec5SDimitry Andric 20290b57cec5SDimitry Andric // First we check in the local buffer. 20300b57cec5SDimitry Andric llvm::Value *indexPlusOne = 2031*0fca6ea1SDimitry Andric Builder.CreateNUWAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1)); 20320b57cec5SDimitry Andric 20330b57cec5SDimitry Andric // If we haven't overrun the buffer yet, we can continue. 20340b57cec5SDimitry Andric // Set the branch weights based on the simplifying assumption that this is 20350b57cec5SDimitry Andric // like a while-loop, i.e., ignoring that the false branch fetches more 20360b57cec5SDimitry Andric // elements and then returns to the loop. 20370b57cec5SDimitry Andric Builder.CreateCondBr( 20380b57cec5SDimitry Andric Builder.CreateICmpULT(indexPlusOne, count), LoopBodyBB, FetchMoreBB, 20390b57cec5SDimitry Andric createProfileWeights(getProfileCount(S.getBody()), EntryCount)); 20400b57cec5SDimitry Andric 20410b57cec5SDimitry Andric index->addIncoming(indexPlusOne, AfterBody.getBlock()); 20420b57cec5SDimitry Andric count->addIncoming(count, AfterBody.getBlock()); 20430b57cec5SDimitry Andric 20440b57cec5SDimitry Andric // Otherwise, we have to fetch more elements. 20450b57cec5SDimitry Andric EmitBlock(FetchMoreBB); 20460b57cec5SDimitry Andric 20470b57cec5SDimitry Andric CountRV = 20480b57cec5SDimitry Andric CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), 20490b57cec5SDimitry Andric getContext().getNSUIntegerType(), 20500b57cec5SDimitry Andric FastEnumSel, Collection, Args); 20510b57cec5SDimitry Andric 20520b57cec5SDimitry Andric // If we got a zero count, we're done. 20530b57cec5SDimitry Andric llvm::Value *refetchCount = CountRV.getScalarVal(); 20540b57cec5SDimitry Andric 20550b57cec5SDimitry Andric // (note that the message send might split FetchMoreBB) 20560b57cec5SDimitry Andric index->addIncoming(zero, Builder.GetInsertBlock()); 20570b57cec5SDimitry Andric count->addIncoming(refetchCount, Builder.GetInsertBlock()); 20580b57cec5SDimitry Andric 20590b57cec5SDimitry Andric Builder.CreateCondBr(Builder.CreateICmpEQ(refetchCount, zero), 20600b57cec5SDimitry Andric EmptyBB, LoopBodyBB); 20610b57cec5SDimitry Andric 20620b57cec5SDimitry Andric // No more elements. 20630b57cec5SDimitry Andric EmitBlock(EmptyBB); 20640b57cec5SDimitry Andric 20650b57cec5SDimitry Andric if (!elementIsVariable) { 20660b57cec5SDimitry Andric // If the element was not a declaration, set it to be null. 20670b57cec5SDimitry Andric 20680b57cec5SDimitry Andric llvm::Value *null = llvm::Constant::getNullValue(convertedElementType); 20690b57cec5SDimitry Andric elementLValue = EmitLValue(cast<Expr>(S.getElement())); 20700b57cec5SDimitry Andric EmitStoreThroughLValue(RValue::get(null), elementLValue); 20710b57cec5SDimitry Andric } 20720b57cec5SDimitry Andric 20730b57cec5SDimitry Andric if (DI) 20740b57cec5SDimitry Andric DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd()); 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric ForScope.ForceCleanup(); 20770b57cec5SDimitry Andric EmitBlock(LoopEnd.getBlock()); 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric 20800b57cec5SDimitry Andric void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { 20810b57cec5SDimitry Andric CGM.getObjCRuntime().EmitTryStmt(*this, S); 20820b57cec5SDimitry Andric } 20830b57cec5SDimitry Andric 20840b57cec5SDimitry Andric void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { 20850b57cec5SDimitry Andric CGM.getObjCRuntime().EmitThrowStmt(*this, S); 20860b57cec5SDimitry Andric } 20870b57cec5SDimitry Andric 20880b57cec5SDimitry Andric void CodeGenFunction::EmitObjCAtSynchronizedStmt( 20890b57cec5SDimitry Andric const ObjCAtSynchronizedStmt &S) { 20900b57cec5SDimitry Andric CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S); 20910b57cec5SDimitry Andric } 20920b57cec5SDimitry Andric 20930b57cec5SDimitry Andric namespace { 20940b57cec5SDimitry Andric struct CallObjCRelease final : EHScopeStack::Cleanup { 20950b57cec5SDimitry Andric CallObjCRelease(llvm::Value *object) : object(object) {} 20960b57cec5SDimitry Andric llvm::Value *object; 20970b57cec5SDimitry Andric 20980b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override { 20990b57cec5SDimitry Andric // Releases at the end of the full-expression are imprecise. 21000b57cec5SDimitry Andric CGF.EmitARCRelease(object, ARCImpreciseLifetime); 21010b57cec5SDimitry Andric } 21020b57cec5SDimitry Andric }; 21030b57cec5SDimitry Andric } 21040b57cec5SDimitry Andric 21050b57cec5SDimitry Andric /// Produce the code for a CK_ARCConsumeObject. Does a primitive 21060b57cec5SDimitry Andric /// release at the end of the full-expression. 21070b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCConsumeObject(QualType type, 21080b57cec5SDimitry Andric llvm::Value *object) { 21090b57cec5SDimitry Andric // If we're in a conditional branch, we need to make the cleanup 21100b57cec5SDimitry Andric // conditional. 21110b57cec5SDimitry Andric pushFullExprCleanup<CallObjCRelease>(getARCCleanupKind(), object); 21120b57cec5SDimitry Andric return object; 21130b57cec5SDimitry Andric } 21140b57cec5SDimitry Andric 21150b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCExtendObjectLifetime(QualType type, 21160b57cec5SDimitry Andric llvm::Value *value) { 21170b57cec5SDimitry Andric return EmitARCRetainAutorelease(type, value); 21180b57cec5SDimitry Andric } 21190b57cec5SDimitry Andric 21200b57cec5SDimitry Andric /// Given a number of pointers, inform the optimizer that they're 21210b57cec5SDimitry Andric /// being intrinsically used up until this point in the program. 21220b57cec5SDimitry Andric void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) { 21230b57cec5SDimitry Andric llvm::Function *&fn = CGM.getObjCEntrypoints().clang_arc_use; 21240b57cec5SDimitry Andric if (!fn) 21250b57cec5SDimitry Andric fn = CGM.getIntrinsic(llvm::Intrinsic::objc_clang_arc_use); 21260b57cec5SDimitry Andric 21270b57cec5SDimitry Andric // This isn't really a "runtime" function, but as an intrinsic it 21280b57cec5SDimitry Andric // doesn't really matter as long as we align things up. 21290b57cec5SDimitry Andric EmitNounwindRuntimeCall(fn, values); 21300b57cec5SDimitry Andric } 21310b57cec5SDimitry Andric 2132fe6060f1SDimitry Andric /// Emit a call to "clang.arc.noop.use", which consumes the result of a call 2133fe6060f1SDimitry Andric /// that has operand bundle "clang.arc.attachedcall". 2134fe6060f1SDimitry Andric void CodeGenFunction::EmitARCNoopIntrinsicUse(ArrayRef<llvm::Value *> values) { 2135fe6060f1SDimitry Andric llvm::Function *&fn = CGM.getObjCEntrypoints().clang_arc_noop_use; 2136fe6060f1SDimitry Andric if (!fn) 2137fe6060f1SDimitry Andric fn = CGM.getIntrinsic(llvm::Intrinsic::objc_clang_arc_noop_use); 2138fe6060f1SDimitry Andric EmitNounwindRuntimeCall(fn, values); 2139fe6060f1SDimitry Andric } 2140fe6060f1SDimitry Andric 21410b57cec5SDimitry Andric static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM, llvm::Value *RTF) { 21420b57cec5SDimitry Andric if (auto *F = dyn_cast<llvm::Function>(RTF)) { 21430b57cec5SDimitry Andric // If the target runtime doesn't naturally support ARC, emit weak 21440b57cec5SDimitry Andric // references to the runtime support library. We don't really 21450b57cec5SDimitry Andric // permit this to fail, but we need a particular relocation style. 21460b57cec5SDimitry Andric if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC() && 21470b57cec5SDimitry Andric !CGM.getTriple().isOSBinFormatCOFF()) { 21480b57cec5SDimitry Andric F->setLinkage(llvm::Function::ExternalWeakLinkage); 21490b57cec5SDimitry Andric } 21500b57cec5SDimitry Andric } 21510b57cec5SDimitry Andric } 21520b57cec5SDimitry Andric 21530b57cec5SDimitry Andric static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM, 21540b57cec5SDimitry Andric llvm::FunctionCallee RTF) { 21550b57cec5SDimitry Andric setARCRuntimeFunctionLinkage(CGM, RTF.getCallee()); 21560b57cec5SDimitry Andric } 21570b57cec5SDimitry Andric 2158349cc55cSDimitry Andric static llvm::Function *getARCIntrinsic(llvm::Intrinsic::ID IntID, 2159349cc55cSDimitry Andric CodeGenModule &CGM) { 2160349cc55cSDimitry Andric llvm::Function *fn = CGM.getIntrinsic(IntID); 2161349cc55cSDimitry Andric setARCRuntimeFunctionLinkage(CGM, fn); 2162349cc55cSDimitry Andric return fn; 2163349cc55cSDimitry Andric } 2164349cc55cSDimitry Andric 21650b57cec5SDimitry Andric /// Perform an operation having the signature 21660b57cec5SDimitry Andric /// i8* (i8*) 21670b57cec5SDimitry Andric /// where a null input causes a no-op and returns null. 21680b57cec5SDimitry Andric static llvm::Value *emitARCValueOperation( 21690b57cec5SDimitry Andric CodeGenFunction &CGF, llvm::Value *value, llvm::Type *returnType, 21700b57cec5SDimitry Andric llvm::Function *&fn, llvm::Intrinsic::ID IntID, 21710b57cec5SDimitry Andric llvm::CallInst::TailCallKind tailKind = llvm::CallInst::TCK_None) { 21720b57cec5SDimitry Andric if (isa<llvm::ConstantPointerNull>(value)) 21730b57cec5SDimitry Andric return value; 21740b57cec5SDimitry Andric 2175349cc55cSDimitry Andric if (!fn) 2176349cc55cSDimitry Andric fn = getARCIntrinsic(IntID, CGF.CGM); 21770b57cec5SDimitry Andric 21780b57cec5SDimitry Andric // Cast the argument to 'id'. 21790b57cec5SDimitry Andric llvm::Type *origType = returnType ? returnType : value->getType(); 21800b57cec5SDimitry Andric value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy); 21810b57cec5SDimitry Andric 21820b57cec5SDimitry Andric // Call the function. 21830b57cec5SDimitry Andric llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(fn, value); 21840b57cec5SDimitry Andric call->setTailCallKind(tailKind); 21850b57cec5SDimitry Andric 21860b57cec5SDimitry Andric // Cast the result back to the original type. 21870b57cec5SDimitry Andric return CGF.Builder.CreateBitCast(call, origType); 21880b57cec5SDimitry Andric } 21890b57cec5SDimitry Andric 21900b57cec5SDimitry Andric /// Perform an operation having the following signature: 21910b57cec5SDimitry Andric /// i8* (i8**) 21920b57cec5SDimitry Andric static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr, 21930b57cec5SDimitry Andric llvm::Function *&fn, 21940b57cec5SDimitry Andric llvm::Intrinsic::ID IntID) { 2195349cc55cSDimitry Andric if (!fn) 2196349cc55cSDimitry Andric fn = getARCIntrinsic(IntID, CGF.CGM); 21970b57cec5SDimitry Andric 2198*0fca6ea1SDimitry Andric return CGF.EmitNounwindRuntimeCall(fn, addr.emitRawPointer(CGF)); 21990b57cec5SDimitry Andric } 22000b57cec5SDimitry Andric 22010b57cec5SDimitry Andric /// Perform an operation having the following signature: 22020b57cec5SDimitry Andric /// i8* (i8**, i8*) 22030b57cec5SDimitry Andric static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr, 22040b57cec5SDimitry Andric llvm::Value *value, 22050b57cec5SDimitry Andric llvm::Function *&fn, 22060b57cec5SDimitry Andric llvm::Intrinsic::ID IntID, 22070b57cec5SDimitry Andric bool ignored) { 22080b57cec5SDimitry Andric assert(addr.getElementType() == value->getType()); 22090b57cec5SDimitry Andric 2210349cc55cSDimitry Andric if (!fn) 2211349cc55cSDimitry Andric fn = getARCIntrinsic(IntID, CGF.CGM); 22120b57cec5SDimitry Andric 22130b57cec5SDimitry Andric llvm::Type *origType = value->getType(); 22140b57cec5SDimitry Andric 22150b57cec5SDimitry Andric llvm::Value *args[] = { 2216*0fca6ea1SDimitry Andric CGF.Builder.CreateBitCast(addr.emitRawPointer(CGF), CGF.Int8PtrPtrTy), 2217*0fca6ea1SDimitry Andric CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy)}; 22180b57cec5SDimitry Andric llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args); 22190b57cec5SDimitry Andric 22200b57cec5SDimitry Andric if (ignored) return nullptr; 22210b57cec5SDimitry Andric 22220b57cec5SDimitry Andric return CGF.Builder.CreateBitCast(result, origType); 22230b57cec5SDimitry Andric } 22240b57cec5SDimitry Andric 22250b57cec5SDimitry Andric /// Perform an operation having the following signature: 22260b57cec5SDimitry Andric /// void (i8**, i8**) 22270b57cec5SDimitry Andric static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src, 22280b57cec5SDimitry Andric llvm::Function *&fn, 22290b57cec5SDimitry Andric llvm::Intrinsic::ID IntID) { 22300b57cec5SDimitry Andric assert(dst.getType() == src.getType()); 22310b57cec5SDimitry Andric 2232349cc55cSDimitry Andric if (!fn) 2233349cc55cSDimitry Andric fn = getARCIntrinsic(IntID, CGF.CGM); 22340b57cec5SDimitry Andric 22350b57cec5SDimitry Andric llvm::Value *args[] = { 2236*0fca6ea1SDimitry Andric CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), CGF.Int8PtrPtrTy), 2237*0fca6ea1SDimitry Andric CGF.Builder.CreateBitCast(src.emitRawPointer(CGF), CGF.Int8PtrPtrTy)}; 22380b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(fn, args); 22390b57cec5SDimitry Andric } 22400b57cec5SDimitry Andric 22410b57cec5SDimitry Andric /// Perform an operation having the signature 22420b57cec5SDimitry Andric /// i8* (i8*) 22430b57cec5SDimitry Andric /// where a null input causes a no-op and returns null. 22440b57cec5SDimitry Andric static llvm::Value *emitObjCValueOperation(CodeGenFunction &CGF, 22450b57cec5SDimitry Andric llvm::Value *value, 22460b57cec5SDimitry Andric llvm::Type *returnType, 22470b57cec5SDimitry Andric llvm::FunctionCallee &fn, 22480b57cec5SDimitry Andric StringRef fnName) { 22490b57cec5SDimitry Andric if (isa<llvm::ConstantPointerNull>(value)) 22500b57cec5SDimitry Andric return value; 22510b57cec5SDimitry Andric 22520b57cec5SDimitry Andric if (!fn) { 22530b57cec5SDimitry Andric llvm::FunctionType *fnType = 22540b57cec5SDimitry Andric llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, false); 22550b57cec5SDimitry Andric fn = CGF.CGM.CreateRuntimeFunction(fnType, fnName); 22560b57cec5SDimitry Andric 22570b57cec5SDimitry Andric // We have Native ARC, so set nonlazybind attribute for performance 22580b57cec5SDimitry Andric if (llvm::Function *f = dyn_cast<llvm::Function>(fn.getCallee())) 22590b57cec5SDimitry Andric if (fnName == "objc_retain") 22600b57cec5SDimitry Andric f->addFnAttr(llvm::Attribute::NonLazyBind); 22610b57cec5SDimitry Andric } 22620b57cec5SDimitry Andric 22630b57cec5SDimitry Andric // Cast the argument to 'id'. 22640b57cec5SDimitry Andric llvm::Type *origType = returnType ? returnType : value->getType(); 22650b57cec5SDimitry Andric value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy); 22660b57cec5SDimitry Andric 22670b57cec5SDimitry Andric // Call the function. 22680b57cec5SDimitry Andric llvm::CallBase *Inst = CGF.EmitCallOrInvoke(fn, value); 22690b57cec5SDimitry Andric 2270e8d8bef9SDimitry Andric // Mark calls to objc_autorelease as tail on the assumption that methods 2271e8d8bef9SDimitry Andric // overriding autorelease do not touch anything on the stack. 2272e8d8bef9SDimitry Andric if (fnName == "objc_autorelease") 2273e8d8bef9SDimitry Andric if (auto *Call = dyn_cast<llvm::CallInst>(Inst)) 2274e8d8bef9SDimitry Andric Call->setTailCall(); 2275e8d8bef9SDimitry Andric 22760b57cec5SDimitry Andric // Cast the result back to the original type. 22770b57cec5SDimitry Andric return CGF.Builder.CreateBitCast(Inst, origType); 22780b57cec5SDimitry Andric } 22790b57cec5SDimitry Andric 22800b57cec5SDimitry Andric /// Produce the code to do a retain. Based on the type, calls one of: 22810b57cec5SDimitry Andric /// call i8* \@objc_retain(i8* %value) 22820b57cec5SDimitry Andric /// call i8* \@objc_retainBlock(i8* %value) 22830b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCRetain(QualType type, llvm::Value *value) { 22840b57cec5SDimitry Andric if (type->isBlockPointerType()) 22850b57cec5SDimitry Andric return EmitARCRetainBlock(value, /*mandatory*/ false); 22860b57cec5SDimitry Andric else 22870b57cec5SDimitry Andric return EmitARCRetainNonBlock(value); 22880b57cec5SDimitry Andric } 22890b57cec5SDimitry Andric 22900b57cec5SDimitry Andric /// Retain the given object, with normal retain semantics. 22910b57cec5SDimitry Andric /// call i8* \@objc_retain(i8* %value) 22920b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) { 22930b57cec5SDimitry Andric return emitARCValueOperation(*this, value, nullptr, 22940b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_retain, 22950b57cec5SDimitry Andric llvm::Intrinsic::objc_retain); 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric 22980b57cec5SDimitry Andric /// Retain the given block, with _Block_copy semantics. 22990b57cec5SDimitry Andric /// call i8* \@objc_retainBlock(i8* %value) 23000b57cec5SDimitry Andric /// 23010b57cec5SDimitry Andric /// \param mandatory - If false, emit the call with metadata 23020b57cec5SDimitry Andric /// indicating that it's okay for the optimizer to eliminate this call 23030b57cec5SDimitry Andric /// if it can prove that the block never escapes except down the stack. 23040b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value, 23050b57cec5SDimitry Andric bool mandatory) { 23060b57cec5SDimitry Andric llvm::Value *result 23070b57cec5SDimitry Andric = emitARCValueOperation(*this, value, nullptr, 23080b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_retainBlock, 23090b57cec5SDimitry Andric llvm::Intrinsic::objc_retainBlock); 23100b57cec5SDimitry Andric 23110b57cec5SDimitry Andric // If the copy isn't mandatory, add !clang.arc.copy_on_escape to 23120b57cec5SDimitry Andric // tell the optimizer that it doesn't need to do this copy if the 23130b57cec5SDimitry Andric // block doesn't escape, where being passed as an argument doesn't 23140b57cec5SDimitry Andric // count as escaping. 23150b57cec5SDimitry Andric if (!mandatory && isa<llvm::Instruction>(result)) { 23160b57cec5SDimitry Andric llvm::CallInst *call 23170b57cec5SDimitry Andric = cast<llvm::CallInst>(result->stripPointerCasts()); 23185ffd83dbSDimitry Andric assert(call->getCalledOperand() == 23195ffd83dbSDimitry Andric CGM.getObjCEntrypoints().objc_retainBlock); 23200b57cec5SDimitry Andric 23210b57cec5SDimitry Andric call->setMetadata("clang.arc.copy_on_escape", 2322bdd1243dSDimitry Andric llvm::MDNode::get(Builder.getContext(), std::nullopt)); 23230b57cec5SDimitry Andric } 23240b57cec5SDimitry Andric 23250b57cec5SDimitry Andric return result; 23260b57cec5SDimitry Andric } 23270b57cec5SDimitry Andric 23280b57cec5SDimitry Andric static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) { 23290b57cec5SDimitry Andric // Fetch the void(void) inline asm which marks that we're going to 23300b57cec5SDimitry Andric // do something with the autoreleased return value. 23310b57cec5SDimitry Andric llvm::InlineAsm *&marker 23320b57cec5SDimitry Andric = CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker; 23330b57cec5SDimitry Andric if (!marker) { 23340b57cec5SDimitry Andric StringRef assembly 23350b57cec5SDimitry Andric = CGF.CGM.getTargetCodeGenInfo() 23360b57cec5SDimitry Andric .getARCRetainAutoreleasedReturnValueMarker(); 23370b57cec5SDimitry Andric 23380b57cec5SDimitry Andric // If we have an empty assembly string, there's nothing to do. 23390b57cec5SDimitry Andric if (assembly.empty()) { 23400b57cec5SDimitry Andric 23410b57cec5SDimitry Andric // Otherwise, at -O0, build an inline asm that we're going to call 23420b57cec5SDimitry Andric // in a moment. 23430b57cec5SDimitry Andric } else if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) { 23440b57cec5SDimitry Andric llvm::FunctionType *type = 23450b57cec5SDimitry Andric llvm::FunctionType::get(CGF.VoidTy, /*variadic*/false); 23460b57cec5SDimitry Andric 23470b57cec5SDimitry Andric marker = llvm::InlineAsm::get(type, assembly, "", /*sideeffects*/ true); 23480b57cec5SDimitry Andric 23490b57cec5SDimitry Andric // If we're at -O1 and above, we don't want to litter the code 23500b57cec5SDimitry Andric // with this marker yet, so leave a breadcrumb for the ARC 23510b57cec5SDimitry Andric // optimizer to pick up. 23520b57cec5SDimitry Andric } else { 2353fe6060f1SDimitry Andric const char *retainRVMarkerKey = llvm::objcarc::getRVMarkerModuleFlagStr(); 2354fe6060f1SDimitry Andric if (!CGF.CGM.getModule().getModuleFlag(retainRVMarkerKey)) { 23550b57cec5SDimitry Andric auto *str = llvm::MDString::get(CGF.getLLVMContext(), assembly); 2356fe6060f1SDimitry Andric CGF.CGM.getModule().addModuleFlag(llvm::Module::Error, 2357fe6060f1SDimitry Andric retainRVMarkerKey, str); 23580b57cec5SDimitry Andric } 23590b57cec5SDimitry Andric } 23600b57cec5SDimitry Andric } 23610b57cec5SDimitry Andric 23620b57cec5SDimitry Andric // Call the marker asm if we made one, which we do only at -O0. 23630b57cec5SDimitry Andric if (marker) 2364bdd1243dSDimitry Andric CGF.Builder.CreateCall(marker, std::nullopt, 2365bdd1243dSDimitry Andric CGF.getBundlesForFunclet(marker)); 23660b57cec5SDimitry Andric } 23670b57cec5SDimitry Andric 2368fe6060f1SDimitry Andric static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value, 2369fe6060f1SDimitry Andric bool IsRetainRV, 2370fe6060f1SDimitry Andric CodeGenFunction &CGF) { 2371fe6060f1SDimitry Andric emitAutoreleasedReturnValueMarker(CGF); 2372fe6060f1SDimitry Andric 2373fe6060f1SDimitry Andric // Add operand bundle "clang.arc.attachedcall" to the call instead of emitting 2374fe6060f1SDimitry Andric // retainRV or claimRV calls in the IR. We currently do this only when the 2375fe6060f1SDimitry Andric // optimization level isn't -O0 since global-isel, which is currently run at 2376fe6060f1SDimitry Andric // -O0, doesn't know about the operand bundle. 2377349cc55cSDimitry Andric ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints(); 2378349cc55cSDimitry Andric llvm::Function *&EP = IsRetainRV 2379349cc55cSDimitry Andric ? EPs.objc_retainAutoreleasedReturnValue 2380349cc55cSDimitry Andric : EPs.objc_unsafeClaimAutoreleasedReturnValue; 2381349cc55cSDimitry Andric llvm::Intrinsic::ID IID = 2382349cc55cSDimitry Andric IsRetainRV ? llvm::Intrinsic::objc_retainAutoreleasedReturnValue 2383349cc55cSDimitry Andric : llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue; 2384349cc55cSDimitry Andric EP = getARCIntrinsic(IID, CGF.CGM); 2385fe6060f1SDimitry Andric 2386349cc55cSDimitry Andric llvm::Triple::ArchType Arch = CGF.CGM.getTriple().getArch(); 2387349cc55cSDimitry Andric 2388349cc55cSDimitry Andric // FIXME: Do this on all targets and at -O0 too. This can be enabled only if 2389349cc55cSDimitry Andric // the target backend knows how to handle the operand bundle. 2390fe6060f1SDimitry Andric if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 && 2391349cc55cSDimitry Andric (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::x86_64)) { 2392349cc55cSDimitry Andric llvm::Value *bundleArgs[] = {EP}; 2393fe6060f1SDimitry Andric llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs); 2394fe6060f1SDimitry Andric auto *oldCall = cast<llvm::CallBase>(value); 2395fe6060f1SDimitry Andric llvm::CallBase *newCall = llvm::CallBase::addOperandBundle( 2396fe6060f1SDimitry Andric oldCall, llvm::LLVMContext::OB_clang_arc_attachedcall, OB, oldCall); 2397fe6060f1SDimitry Andric newCall->copyMetadata(*oldCall); 2398fe6060f1SDimitry Andric oldCall->replaceAllUsesWith(newCall); 2399fe6060f1SDimitry Andric oldCall->eraseFromParent(); 2400fe6060f1SDimitry Andric CGF.EmitARCNoopIntrinsicUse(newCall); 2401fe6060f1SDimitry Andric return newCall; 2402fe6060f1SDimitry Andric } 2403fe6060f1SDimitry Andric 2404fe6060f1SDimitry Andric bool isNoTail = 2405fe6060f1SDimitry Andric CGF.CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail(); 2406fe6060f1SDimitry Andric llvm::CallInst::TailCallKind tailKind = 2407fe6060f1SDimitry Andric isNoTail ? llvm::CallInst::TCK_NoTail : llvm::CallInst::TCK_None; 2408fe6060f1SDimitry Andric return emitARCValueOperation(CGF, value, nullptr, EP, IID, tailKind); 2409fe6060f1SDimitry Andric } 2410fe6060f1SDimitry Andric 24110b57cec5SDimitry Andric /// Retain the given object which is the result of a function call. 24120b57cec5SDimitry Andric /// call i8* \@objc_retainAutoreleasedReturnValue(i8* %value) 24130b57cec5SDimitry Andric /// 24140b57cec5SDimitry Andric /// Yes, this function name is one character away from a different 24150b57cec5SDimitry Andric /// call with completely different semantics. 24160b57cec5SDimitry Andric llvm::Value * 24170b57cec5SDimitry Andric CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) { 2418fe6060f1SDimitry Andric return emitOptimizedARCReturnCall(value, true, *this); 24190b57cec5SDimitry Andric } 24200b57cec5SDimitry Andric 24210b57cec5SDimitry Andric /// Claim a possibly-autoreleased return value at +0. This is only 24220b57cec5SDimitry Andric /// valid to do in contexts which do not rely on the retain to keep 24230b57cec5SDimitry Andric /// the object valid for all of its uses; for example, when 24240b57cec5SDimitry Andric /// the value is ignored, or when it is being assigned to an 24250b57cec5SDimitry Andric /// __unsafe_unretained variable. 24260b57cec5SDimitry Andric /// 24270b57cec5SDimitry Andric /// call i8* \@objc_unsafeClaimAutoreleasedReturnValue(i8* %value) 24280b57cec5SDimitry Andric llvm::Value * 24290b57cec5SDimitry Andric CodeGenFunction::EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value) { 2430fe6060f1SDimitry Andric return emitOptimizedARCReturnCall(value, false, *this); 24310b57cec5SDimitry Andric } 24320b57cec5SDimitry Andric 24330b57cec5SDimitry Andric /// Release the given object. 24340b57cec5SDimitry Andric /// call void \@objc_release(i8* %value) 24350b57cec5SDimitry Andric void CodeGenFunction::EmitARCRelease(llvm::Value *value, 24360b57cec5SDimitry Andric ARCPreciseLifetime_t precise) { 24370b57cec5SDimitry Andric if (isa<llvm::ConstantPointerNull>(value)) return; 24380b57cec5SDimitry Andric 24390b57cec5SDimitry Andric llvm::Function *&fn = CGM.getObjCEntrypoints().objc_release; 2440349cc55cSDimitry Andric if (!fn) 2441349cc55cSDimitry Andric fn = getARCIntrinsic(llvm::Intrinsic::objc_release, CGM); 24420b57cec5SDimitry Andric 24430b57cec5SDimitry Andric // Cast the argument to 'id'. 24440b57cec5SDimitry Andric value = Builder.CreateBitCast(value, Int8PtrTy); 24450b57cec5SDimitry Andric 24460b57cec5SDimitry Andric // Call objc_release. 24470b57cec5SDimitry Andric llvm::CallInst *call = EmitNounwindRuntimeCall(fn, value); 24480b57cec5SDimitry Andric 24490b57cec5SDimitry Andric if (precise == ARCImpreciseLifetime) { 24500b57cec5SDimitry Andric call->setMetadata("clang.imprecise_release", 2451bdd1243dSDimitry Andric llvm::MDNode::get(Builder.getContext(), std::nullopt)); 24520b57cec5SDimitry Andric } 24530b57cec5SDimitry Andric } 24540b57cec5SDimitry Andric 24550b57cec5SDimitry Andric /// Destroy a __strong variable. 24560b57cec5SDimitry Andric /// 24570b57cec5SDimitry Andric /// At -O0, emit a call to store 'null' into the address; 24580b57cec5SDimitry Andric /// instrumenting tools prefer this because the address is exposed, 24590b57cec5SDimitry Andric /// but it's relatively cumbersome to optimize. 24600b57cec5SDimitry Andric /// 24610b57cec5SDimitry Andric /// At -O1 and above, just load and call objc_release. 24620b57cec5SDimitry Andric /// 24630b57cec5SDimitry Andric /// call void \@objc_storeStrong(i8** %addr, i8* null) 24640b57cec5SDimitry Andric void CodeGenFunction::EmitARCDestroyStrong(Address addr, 24650b57cec5SDimitry Andric ARCPreciseLifetime_t precise) { 24660b57cec5SDimitry Andric if (CGM.getCodeGenOpts().OptimizationLevel == 0) { 24670b57cec5SDimitry Andric llvm::Value *null = getNullForVariable(addr); 24680b57cec5SDimitry Andric EmitARCStoreStrongCall(addr, null, /*ignored*/ true); 24690b57cec5SDimitry Andric return; 24700b57cec5SDimitry Andric } 24710b57cec5SDimitry Andric 24720b57cec5SDimitry Andric llvm::Value *value = Builder.CreateLoad(addr); 24730b57cec5SDimitry Andric EmitARCRelease(value, precise); 24740b57cec5SDimitry Andric } 24750b57cec5SDimitry Andric 24760b57cec5SDimitry Andric /// Store into a strong object. Always calls this: 24770b57cec5SDimitry Andric /// call void \@objc_storeStrong(i8** %addr, i8* %value) 24780b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr, 24790b57cec5SDimitry Andric llvm::Value *value, 24800b57cec5SDimitry Andric bool ignored) { 24810b57cec5SDimitry Andric assert(addr.getElementType() == value->getType()); 24820b57cec5SDimitry Andric 24830b57cec5SDimitry Andric llvm::Function *&fn = CGM.getObjCEntrypoints().objc_storeStrong; 2484349cc55cSDimitry Andric if (!fn) 2485349cc55cSDimitry Andric fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM); 24860b57cec5SDimitry Andric 24870b57cec5SDimitry Andric llvm::Value *args[] = { 2488*0fca6ea1SDimitry Andric Builder.CreateBitCast(addr.emitRawPointer(*this), Int8PtrPtrTy), 2489*0fca6ea1SDimitry Andric Builder.CreateBitCast(value, Int8PtrTy)}; 24900b57cec5SDimitry Andric EmitNounwindRuntimeCall(fn, args); 24910b57cec5SDimitry Andric 24920b57cec5SDimitry Andric if (ignored) return nullptr; 24930b57cec5SDimitry Andric return value; 24940b57cec5SDimitry Andric } 24950b57cec5SDimitry Andric 24960b57cec5SDimitry Andric /// Store into a strong object. Sometimes calls this: 24970b57cec5SDimitry Andric /// call void \@objc_storeStrong(i8** %addr, i8* %value) 24980b57cec5SDimitry Andric /// Other times, breaks it down into components. 24990b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCStoreStrong(LValue dst, 25000b57cec5SDimitry Andric llvm::Value *newValue, 25010b57cec5SDimitry Andric bool ignored) { 25020b57cec5SDimitry Andric QualType type = dst.getType(); 25030b57cec5SDimitry Andric bool isBlock = type->isBlockPointerType(); 25040b57cec5SDimitry Andric 25050b57cec5SDimitry Andric // Use a store barrier at -O0 unless this is a block type or the 25060b57cec5SDimitry Andric // lvalue is inadequately aligned. 25070b57cec5SDimitry Andric if (shouldUseFusedARCCalls() && 25080b57cec5SDimitry Andric !isBlock && 25090b57cec5SDimitry Andric (dst.getAlignment().isZero() || 25100b57cec5SDimitry Andric dst.getAlignment() >= CharUnits::fromQuantity(PointerAlignInBytes))) { 2511*0fca6ea1SDimitry Andric return EmitARCStoreStrongCall(dst.getAddress(), newValue, ignored); 25120b57cec5SDimitry Andric } 25130b57cec5SDimitry Andric 25140b57cec5SDimitry Andric // Otherwise, split it out. 25150b57cec5SDimitry Andric 25160b57cec5SDimitry Andric // Retain the new value. 25170b57cec5SDimitry Andric newValue = EmitARCRetain(type, newValue); 25180b57cec5SDimitry Andric 25190b57cec5SDimitry Andric // Read the old value. 25200b57cec5SDimitry Andric llvm::Value *oldValue = EmitLoadOfScalar(dst, SourceLocation()); 25210b57cec5SDimitry Andric 25220b57cec5SDimitry Andric // Store. We do this before the release so that any deallocs won't 25230b57cec5SDimitry Andric // see the old value. 25240b57cec5SDimitry Andric EmitStoreOfScalar(newValue, dst); 25250b57cec5SDimitry Andric 25260b57cec5SDimitry Andric // Finally, release the old value. 25270b57cec5SDimitry Andric EmitARCRelease(oldValue, dst.isARCPreciseLifetime()); 25280b57cec5SDimitry Andric 25290b57cec5SDimitry Andric return newValue; 25300b57cec5SDimitry Andric } 25310b57cec5SDimitry Andric 25320b57cec5SDimitry Andric /// Autorelease the given object. 25330b57cec5SDimitry Andric /// call i8* \@objc_autorelease(i8* %value) 25340b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCAutorelease(llvm::Value *value) { 25350b57cec5SDimitry Andric return emitARCValueOperation(*this, value, nullptr, 25360b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_autorelease, 25370b57cec5SDimitry Andric llvm::Intrinsic::objc_autorelease); 25380b57cec5SDimitry Andric } 25390b57cec5SDimitry Andric 25400b57cec5SDimitry Andric /// Autorelease the given object. 25410b57cec5SDimitry Andric /// call i8* \@objc_autoreleaseReturnValue(i8* %value) 25420b57cec5SDimitry Andric llvm::Value * 25430b57cec5SDimitry Andric CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) { 25440b57cec5SDimitry Andric return emitARCValueOperation(*this, value, nullptr, 25450b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_autoreleaseReturnValue, 25460b57cec5SDimitry Andric llvm::Intrinsic::objc_autoreleaseReturnValue, 25470b57cec5SDimitry Andric llvm::CallInst::TCK_Tail); 25480b57cec5SDimitry Andric } 25490b57cec5SDimitry Andric 25500b57cec5SDimitry Andric /// Do a fused retain/autorelease of the given object. 25510b57cec5SDimitry Andric /// call i8* \@objc_retainAutoreleaseReturnValue(i8* %value) 25520b57cec5SDimitry Andric llvm::Value * 25530b57cec5SDimitry Andric CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) { 25540b57cec5SDimitry Andric return emitARCValueOperation(*this, value, nullptr, 25550b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_retainAutoreleaseReturnValue, 25560b57cec5SDimitry Andric llvm::Intrinsic::objc_retainAutoreleaseReturnValue, 25570b57cec5SDimitry Andric llvm::CallInst::TCK_Tail); 25580b57cec5SDimitry Andric } 25590b57cec5SDimitry Andric 25600b57cec5SDimitry Andric /// Do a fused retain/autorelease of the given object. 25610b57cec5SDimitry Andric /// call i8* \@objc_retainAutorelease(i8* %value) 25620b57cec5SDimitry Andric /// or 25630b57cec5SDimitry Andric /// %retain = call i8* \@objc_retainBlock(i8* %value) 25640b57cec5SDimitry Andric /// call i8* \@objc_autorelease(i8* %retain) 25650b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCRetainAutorelease(QualType type, 25660b57cec5SDimitry Andric llvm::Value *value) { 25670b57cec5SDimitry Andric if (!type->isBlockPointerType()) 25680b57cec5SDimitry Andric return EmitARCRetainAutoreleaseNonBlock(value); 25690b57cec5SDimitry Andric 25700b57cec5SDimitry Andric if (isa<llvm::ConstantPointerNull>(value)) return value; 25710b57cec5SDimitry Andric 25720b57cec5SDimitry Andric llvm::Type *origType = value->getType(); 25730b57cec5SDimitry Andric value = Builder.CreateBitCast(value, Int8PtrTy); 25740b57cec5SDimitry Andric value = EmitARCRetainBlock(value, /*mandatory*/ true); 25750b57cec5SDimitry Andric value = EmitARCAutorelease(value); 25760b57cec5SDimitry Andric return Builder.CreateBitCast(value, origType); 25770b57cec5SDimitry Andric } 25780b57cec5SDimitry Andric 25790b57cec5SDimitry Andric /// Do a fused retain/autorelease of the given object. 25800b57cec5SDimitry Andric /// call i8* \@objc_retainAutorelease(i8* %value) 25810b57cec5SDimitry Andric llvm::Value * 25820b57cec5SDimitry Andric CodeGenFunction::EmitARCRetainAutoreleaseNonBlock(llvm::Value *value) { 25830b57cec5SDimitry Andric return emitARCValueOperation(*this, value, nullptr, 25840b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_retainAutorelease, 25850b57cec5SDimitry Andric llvm::Intrinsic::objc_retainAutorelease); 25860b57cec5SDimitry Andric } 25870b57cec5SDimitry Andric 25880b57cec5SDimitry Andric /// i8* \@objc_loadWeak(i8** %addr) 25890b57cec5SDimitry Andric /// Essentially objc_autorelease(objc_loadWeakRetained(addr)). 25900b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCLoadWeak(Address addr) { 25910b57cec5SDimitry Andric return emitARCLoadOperation(*this, addr, 25920b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_loadWeak, 25930b57cec5SDimitry Andric llvm::Intrinsic::objc_loadWeak); 25940b57cec5SDimitry Andric } 25950b57cec5SDimitry Andric 25960b57cec5SDimitry Andric /// i8* \@objc_loadWeakRetained(i8** %addr) 25970b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCLoadWeakRetained(Address addr) { 25980b57cec5SDimitry Andric return emitARCLoadOperation(*this, addr, 25990b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_loadWeakRetained, 26000b57cec5SDimitry Andric llvm::Intrinsic::objc_loadWeakRetained); 26010b57cec5SDimitry Andric } 26020b57cec5SDimitry Andric 26030b57cec5SDimitry Andric /// i8* \@objc_storeWeak(i8** %addr, i8* %value) 26040b57cec5SDimitry Andric /// Returns %value. 26050b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCStoreWeak(Address addr, 26060b57cec5SDimitry Andric llvm::Value *value, 26070b57cec5SDimitry Andric bool ignored) { 26080b57cec5SDimitry Andric return emitARCStoreOperation(*this, addr, value, 26090b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_storeWeak, 26100b57cec5SDimitry Andric llvm::Intrinsic::objc_storeWeak, ignored); 26110b57cec5SDimitry Andric } 26120b57cec5SDimitry Andric 26130b57cec5SDimitry Andric /// i8* \@objc_initWeak(i8** %addr, i8* %value) 26140b57cec5SDimitry Andric /// Returns %value. %addr is known to not have a current weak entry. 26150b57cec5SDimitry Andric /// Essentially equivalent to: 26160b57cec5SDimitry Andric /// *addr = nil; objc_storeWeak(addr, value); 26170b57cec5SDimitry Andric void CodeGenFunction::EmitARCInitWeak(Address addr, llvm::Value *value) { 26180b57cec5SDimitry Andric // If we're initializing to null, just write null to memory; no need 26190b57cec5SDimitry Andric // to get the runtime involved. But don't do this if optimization 26200b57cec5SDimitry Andric // is enabled, because accounting for this would make the optimizer 26210b57cec5SDimitry Andric // much more complicated. 26220b57cec5SDimitry Andric if (isa<llvm::ConstantPointerNull>(value) && 26230b57cec5SDimitry Andric CGM.getCodeGenOpts().OptimizationLevel == 0) { 26240b57cec5SDimitry Andric Builder.CreateStore(value, addr); 26250b57cec5SDimitry Andric return; 26260b57cec5SDimitry Andric } 26270b57cec5SDimitry Andric 26280b57cec5SDimitry Andric emitARCStoreOperation(*this, addr, value, 26290b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_initWeak, 26300b57cec5SDimitry Andric llvm::Intrinsic::objc_initWeak, /*ignored*/ true); 26310b57cec5SDimitry Andric } 26320b57cec5SDimitry Andric 26330b57cec5SDimitry Andric /// void \@objc_destroyWeak(i8** %addr) 26340b57cec5SDimitry Andric /// Essentially objc_storeWeak(addr, nil). 26350b57cec5SDimitry Andric void CodeGenFunction::EmitARCDestroyWeak(Address addr) { 26360b57cec5SDimitry Andric llvm::Function *&fn = CGM.getObjCEntrypoints().objc_destroyWeak; 2637349cc55cSDimitry Andric if (!fn) 2638349cc55cSDimitry Andric fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM); 26390b57cec5SDimitry Andric 2640*0fca6ea1SDimitry Andric EmitNounwindRuntimeCall(fn, addr.emitRawPointer(*this)); 26410b57cec5SDimitry Andric } 26420b57cec5SDimitry Andric 26430b57cec5SDimitry Andric /// void \@objc_moveWeak(i8** %dest, i8** %src) 26440b57cec5SDimitry Andric /// Disregards the current value in %dest. Leaves %src pointing to nothing. 26450b57cec5SDimitry Andric /// Essentially (objc_copyWeak(dest, src), objc_destroyWeak(src)). 26460b57cec5SDimitry Andric void CodeGenFunction::EmitARCMoveWeak(Address dst, Address src) { 26470b57cec5SDimitry Andric emitARCCopyOperation(*this, dst, src, 26480b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_moveWeak, 26490b57cec5SDimitry Andric llvm::Intrinsic::objc_moveWeak); 26500b57cec5SDimitry Andric } 26510b57cec5SDimitry Andric 26520b57cec5SDimitry Andric /// void \@objc_copyWeak(i8** %dest, i8** %src) 26530b57cec5SDimitry Andric /// Disregards the current value in %dest. Essentially 26540b57cec5SDimitry Andric /// objc_release(objc_initWeak(dest, objc_readWeakRetained(src))) 26550b57cec5SDimitry Andric void CodeGenFunction::EmitARCCopyWeak(Address dst, Address src) { 26560b57cec5SDimitry Andric emitARCCopyOperation(*this, dst, src, 26570b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_copyWeak, 26580b57cec5SDimitry Andric llvm::Intrinsic::objc_copyWeak); 26590b57cec5SDimitry Andric } 26600b57cec5SDimitry Andric 26610b57cec5SDimitry Andric void CodeGenFunction::emitARCCopyAssignWeak(QualType Ty, Address DstAddr, 26620b57cec5SDimitry Andric Address SrcAddr) { 26630b57cec5SDimitry Andric llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr); 26640b57cec5SDimitry Andric Object = EmitObjCConsumeObject(Ty, Object); 26650b57cec5SDimitry Andric EmitARCStoreWeak(DstAddr, Object, false); 26660b57cec5SDimitry Andric } 26670b57cec5SDimitry Andric 26680b57cec5SDimitry Andric void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr, 26690b57cec5SDimitry Andric Address SrcAddr) { 26700b57cec5SDimitry Andric llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr); 26710b57cec5SDimitry Andric Object = EmitObjCConsumeObject(Ty, Object); 26720b57cec5SDimitry Andric EmitARCStoreWeak(DstAddr, Object, false); 26730b57cec5SDimitry Andric EmitARCDestroyWeak(SrcAddr); 26740b57cec5SDimitry Andric } 26750b57cec5SDimitry Andric 26760b57cec5SDimitry Andric /// Produce the code to do a objc_autoreleasepool_push. 26770b57cec5SDimitry Andric /// call i8* \@objc_autoreleasePoolPush(void) 26780b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() { 26790b57cec5SDimitry Andric llvm::Function *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPush; 2680349cc55cSDimitry Andric if (!fn) 2681349cc55cSDimitry Andric fn = getARCIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush, CGM); 26820b57cec5SDimitry Andric 26830b57cec5SDimitry Andric return EmitNounwindRuntimeCall(fn); 26840b57cec5SDimitry Andric } 26850b57cec5SDimitry Andric 26860b57cec5SDimitry Andric /// Produce the code to do a primitive release. 26870b57cec5SDimitry Andric /// call void \@objc_autoreleasePoolPop(i8* %ptr) 26880b57cec5SDimitry Andric void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) { 26890b57cec5SDimitry Andric assert(value->getType() == Int8PtrTy); 26900b57cec5SDimitry Andric 26910b57cec5SDimitry Andric if (getInvokeDest()) { 26920b57cec5SDimitry Andric // Call the runtime method not the intrinsic if we are handling exceptions 26930b57cec5SDimitry Andric llvm::FunctionCallee &fn = 26940b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_autoreleasePoolPopInvoke; 26950b57cec5SDimitry Andric if (!fn) { 26960b57cec5SDimitry Andric llvm::FunctionType *fnType = 26970b57cec5SDimitry Andric llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false); 26980b57cec5SDimitry Andric fn = CGM.CreateRuntimeFunction(fnType, "objc_autoreleasePoolPop"); 26990b57cec5SDimitry Andric setARCRuntimeFunctionLinkage(CGM, fn); 27000b57cec5SDimitry Andric } 27010b57cec5SDimitry Andric 27020b57cec5SDimitry Andric // objc_autoreleasePoolPop can throw. 27030b57cec5SDimitry Andric EmitRuntimeCallOrInvoke(fn, value); 27040b57cec5SDimitry Andric } else { 27050b57cec5SDimitry Andric llvm::FunctionCallee &fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop; 2706349cc55cSDimitry Andric if (!fn) 2707349cc55cSDimitry Andric fn = getARCIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop, CGM); 27080b57cec5SDimitry Andric 27090b57cec5SDimitry Andric EmitRuntimeCall(fn, value); 27100b57cec5SDimitry Andric } 27110b57cec5SDimitry Andric } 27120b57cec5SDimitry Andric 27130b57cec5SDimitry Andric /// Produce the code to do an MRR version objc_autoreleasepool_push. 27140b57cec5SDimitry Andric /// Which is: [[NSAutoreleasePool alloc] init]; 27150b57cec5SDimitry Andric /// Where alloc is declared as: + (id) alloc; in NSAutoreleasePool class. 27160b57cec5SDimitry Andric /// init is declared as: - (id) init; in its NSObject super class. 27170b57cec5SDimitry Andric /// 27180b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCMRRAutoreleasePoolPush() { 27190b57cec5SDimitry Andric CGObjCRuntime &Runtime = CGM.getObjCRuntime(); 27200b57cec5SDimitry Andric llvm::Value *Receiver = Runtime.EmitNSAutoreleasePoolClassRef(*this); 27210b57cec5SDimitry Andric // [NSAutoreleasePool alloc] 2722*0fca6ea1SDimitry Andric const IdentifierInfo *II = &CGM.getContext().Idents.get("alloc"); 27230b57cec5SDimitry Andric Selector AllocSel = getContext().Selectors.getSelector(0, &II); 27240b57cec5SDimitry Andric CallArgList Args; 27250b57cec5SDimitry Andric RValue AllocRV = 27260b57cec5SDimitry Andric Runtime.GenerateMessageSend(*this, ReturnValueSlot(), 27270b57cec5SDimitry Andric getContext().getObjCIdType(), 27280b57cec5SDimitry Andric AllocSel, Receiver, Args); 27290b57cec5SDimitry Andric 27300b57cec5SDimitry Andric // [Receiver init] 27310b57cec5SDimitry Andric Receiver = AllocRV.getScalarVal(); 27320b57cec5SDimitry Andric II = &CGM.getContext().Idents.get("init"); 27330b57cec5SDimitry Andric Selector InitSel = getContext().Selectors.getSelector(0, &II); 27340b57cec5SDimitry Andric RValue InitRV = 27350b57cec5SDimitry Andric Runtime.GenerateMessageSend(*this, ReturnValueSlot(), 27360b57cec5SDimitry Andric getContext().getObjCIdType(), 27370b57cec5SDimitry Andric InitSel, Receiver, Args); 27380b57cec5SDimitry Andric return InitRV.getScalarVal(); 27390b57cec5SDimitry Andric } 27400b57cec5SDimitry Andric 27410b57cec5SDimitry Andric /// Allocate the given objc object. 27420b57cec5SDimitry Andric /// call i8* \@objc_alloc(i8* %value) 27430b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCAlloc(llvm::Value *value, 27440b57cec5SDimitry Andric llvm::Type *resultType) { 27450b57cec5SDimitry Andric return emitObjCValueOperation(*this, value, resultType, 27460b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_alloc, 27470b57cec5SDimitry Andric "objc_alloc"); 27480b57cec5SDimitry Andric } 27490b57cec5SDimitry Andric 27500b57cec5SDimitry Andric /// Allocate the given objc object. 27510b57cec5SDimitry Andric /// call i8* \@objc_allocWithZone(i8* %value) 27520b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCAllocWithZone(llvm::Value *value, 27530b57cec5SDimitry Andric llvm::Type *resultType) { 27540b57cec5SDimitry Andric return emitObjCValueOperation(*this, value, resultType, 27550b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_allocWithZone, 27560b57cec5SDimitry Andric "objc_allocWithZone"); 27570b57cec5SDimitry Andric } 27580b57cec5SDimitry Andric 27590b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCAllocInit(llvm::Value *value, 27600b57cec5SDimitry Andric llvm::Type *resultType) { 27610b57cec5SDimitry Andric return emitObjCValueOperation(*this, value, resultType, 27620b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_alloc_init, 27630b57cec5SDimitry Andric "objc_alloc_init"); 27640b57cec5SDimitry Andric } 27650b57cec5SDimitry Andric 27660b57cec5SDimitry Andric /// Produce the code to do a primitive release. 27670b57cec5SDimitry Andric /// [tmp drain]; 27680b57cec5SDimitry Andric void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) { 2769*0fca6ea1SDimitry Andric const IdentifierInfo *II = &CGM.getContext().Idents.get("drain"); 27700b57cec5SDimitry Andric Selector DrainSel = getContext().Selectors.getSelector(0, &II); 27710b57cec5SDimitry Andric CallArgList Args; 27720b57cec5SDimitry Andric CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), 27730b57cec5SDimitry Andric getContext().VoidTy, DrainSel, Arg, Args); 27740b57cec5SDimitry Andric } 27750b57cec5SDimitry Andric 27760b57cec5SDimitry Andric void CodeGenFunction::destroyARCStrongPrecise(CodeGenFunction &CGF, 27770b57cec5SDimitry Andric Address addr, 27780b57cec5SDimitry Andric QualType type) { 27790b57cec5SDimitry Andric CGF.EmitARCDestroyStrong(addr, ARCPreciseLifetime); 27800b57cec5SDimitry Andric } 27810b57cec5SDimitry Andric 27820b57cec5SDimitry Andric void CodeGenFunction::destroyARCStrongImprecise(CodeGenFunction &CGF, 27830b57cec5SDimitry Andric Address addr, 27840b57cec5SDimitry Andric QualType type) { 27850b57cec5SDimitry Andric CGF.EmitARCDestroyStrong(addr, ARCImpreciseLifetime); 27860b57cec5SDimitry Andric } 27870b57cec5SDimitry Andric 27880b57cec5SDimitry Andric void CodeGenFunction::destroyARCWeak(CodeGenFunction &CGF, 27890b57cec5SDimitry Andric Address addr, 27900b57cec5SDimitry Andric QualType type) { 27910b57cec5SDimitry Andric CGF.EmitARCDestroyWeak(addr); 27920b57cec5SDimitry Andric } 27930b57cec5SDimitry Andric 27940b57cec5SDimitry Andric void CodeGenFunction::emitARCIntrinsicUse(CodeGenFunction &CGF, Address addr, 27950b57cec5SDimitry Andric QualType type) { 27960b57cec5SDimitry Andric llvm::Value *value = CGF.Builder.CreateLoad(addr); 27970b57cec5SDimitry Andric CGF.EmitARCIntrinsicUse(value); 27980b57cec5SDimitry Andric } 27990b57cec5SDimitry Andric 28000b57cec5SDimitry Andric /// Autorelease the given object. 28010b57cec5SDimitry Andric /// call i8* \@objc_autorelease(i8* %value) 28020b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCAutorelease(llvm::Value *value, 28030b57cec5SDimitry Andric llvm::Type *returnType) { 28040b57cec5SDimitry Andric return emitObjCValueOperation( 28050b57cec5SDimitry Andric *this, value, returnType, 28060b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_autoreleaseRuntimeFunction, 28070b57cec5SDimitry Andric "objc_autorelease"); 28080b57cec5SDimitry Andric } 28090b57cec5SDimitry Andric 28100b57cec5SDimitry Andric /// Retain the given object, with normal retain semantics. 28110b57cec5SDimitry Andric /// call i8* \@objc_retain(i8* %value) 28120b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCRetainNonBlock(llvm::Value *value, 28130b57cec5SDimitry Andric llvm::Type *returnType) { 28140b57cec5SDimitry Andric return emitObjCValueOperation( 28150b57cec5SDimitry Andric *this, value, returnType, 28160b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_retainRuntimeFunction, "objc_retain"); 28170b57cec5SDimitry Andric } 28180b57cec5SDimitry Andric 28190b57cec5SDimitry Andric /// Release the given object. 28200b57cec5SDimitry Andric /// call void \@objc_release(i8* %value) 28210b57cec5SDimitry Andric void CodeGenFunction::EmitObjCRelease(llvm::Value *value, 28220b57cec5SDimitry Andric ARCPreciseLifetime_t precise) { 28230b57cec5SDimitry Andric if (isa<llvm::ConstantPointerNull>(value)) return; 28240b57cec5SDimitry Andric 28250b57cec5SDimitry Andric llvm::FunctionCallee &fn = 28260b57cec5SDimitry Andric CGM.getObjCEntrypoints().objc_releaseRuntimeFunction; 28270b57cec5SDimitry Andric if (!fn) { 28280b57cec5SDimitry Andric llvm::FunctionType *fnType = 28290b57cec5SDimitry Andric llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false); 28300b57cec5SDimitry Andric fn = CGM.CreateRuntimeFunction(fnType, "objc_release"); 28310b57cec5SDimitry Andric setARCRuntimeFunctionLinkage(CGM, fn); 28320b57cec5SDimitry Andric // We have Native ARC, so set nonlazybind attribute for performance 28330b57cec5SDimitry Andric if (llvm::Function *f = dyn_cast<llvm::Function>(fn.getCallee())) 28340b57cec5SDimitry Andric f->addFnAttr(llvm::Attribute::NonLazyBind); 28350b57cec5SDimitry Andric } 28360b57cec5SDimitry Andric 28370b57cec5SDimitry Andric // Cast the argument to 'id'. 28380b57cec5SDimitry Andric value = Builder.CreateBitCast(value, Int8PtrTy); 28390b57cec5SDimitry Andric 28400b57cec5SDimitry Andric // Call objc_release. 28410b57cec5SDimitry Andric llvm::CallBase *call = EmitCallOrInvoke(fn, value); 28420b57cec5SDimitry Andric 28430b57cec5SDimitry Andric if (precise == ARCImpreciseLifetime) { 28440b57cec5SDimitry Andric call->setMetadata("clang.imprecise_release", 2845bdd1243dSDimitry Andric llvm::MDNode::get(Builder.getContext(), std::nullopt)); 28460b57cec5SDimitry Andric } 28470b57cec5SDimitry Andric } 28480b57cec5SDimitry Andric 28490b57cec5SDimitry Andric namespace { 28500b57cec5SDimitry Andric struct CallObjCAutoreleasePoolObject final : EHScopeStack::Cleanup { 28510b57cec5SDimitry Andric llvm::Value *Token; 28520b57cec5SDimitry Andric 28530b57cec5SDimitry Andric CallObjCAutoreleasePoolObject(llvm::Value *token) : Token(token) {} 28540b57cec5SDimitry Andric 28550b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override { 28560b57cec5SDimitry Andric CGF.EmitObjCAutoreleasePoolPop(Token); 28570b57cec5SDimitry Andric } 28580b57cec5SDimitry Andric }; 28590b57cec5SDimitry Andric struct CallObjCMRRAutoreleasePoolObject final : EHScopeStack::Cleanup { 28600b57cec5SDimitry Andric llvm::Value *Token; 28610b57cec5SDimitry Andric 28620b57cec5SDimitry Andric CallObjCMRRAutoreleasePoolObject(llvm::Value *token) : Token(token) {} 28630b57cec5SDimitry Andric 28640b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override { 28650b57cec5SDimitry Andric CGF.EmitObjCMRRAutoreleasePoolPop(Token); 28660b57cec5SDimitry Andric } 28670b57cec5SDimitry Andric }; 28680b57cec5SDimitry Andric } 28690b57cec5SDimitry Andric 28700b57cec5SDimitry Andric void CodeGenFunction::EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr) { 28710b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCAutoRefCount) 28720b57cec5SDimitry Andric EHStack.pushCleanup<CallObjCAutoreleasePoolObject>(NormalCleanup, Ptr); 28730b57cec5SDimitry Andric else 28740b57cec5SDimitry Andric EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, Ptr); 28750b57cec5SDimitry Andric } 28760b57cec5SDimitry Andric 28770b57cec5SDimitry Andric static bool shouldRetainObjCLifetime(Qualifiers::ObjCLifetime lifetime) { 28780b57cec5SDimitry Andric switch (lifetime) { 28790b57cec5SDimitry Andric case Qualifiers::OCL_None: 28800b57cec5SDimitry Andric case Qualifiers::OCL_ExplicitNone: 28810b57cec5SDimitry Andric case Qualifiers::OCL_Strong: 28820b57cec5SDimitry Andric case Qualifiers::OCL_Autoreleasing: 28830b57cec5SDimitry Andric return true; 28840b57cec5SDimitry Andric 28850b57cec5SDimitry Andric case Qualifiers::OCL_Weak: 28860b57cec5SDimitry Andric return false; 28870b57cec5SDimitry Andric } 28880b57cec5SDimitry Andric 28890b57cec5SDimitry Andric llvm_unreachable("impossible lifetime!"); 28900b57cec5SDimitry Andric } 28910b57cec5SDimitry Andric 28920b57cec5SDimitry Andric static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF, 28930b57cec5SDimitry Andric LValue lvalue, 28940b57cec5SDimitry Andric QualType type) { 28950b57cec5SDimitry Andric llvm::Value *result; 28960b57cec5SDimitry Andric bool shouldRetain = shouldRetainObjCLifetime(type.getObjCLifetime()); 28970b57cec5SDimitry Andric if (shouldRetain) { 28980b57cec5SDimitry Andric result = CGF.EmitLoadOfLValue(lvalue, SourceLocation()).getScalarVal(); 28990b57cec5SDimitry Andric } else { 29000b57cec5SDimitry Andric assert(type.getObjCLifetime() == Qualifiers::OCL_Weak); 2901*0fca6ea1SDimitry Andric result = CGF.EmitARCLoadWeakRetained(lvalue.getAddress()); 29020b57cec5SDimitry Andric } 29030b57cec5SDimitry Andric return TryEmitResult(result, !shouldRetain); 29040b57cec5SDimitry Andric } 29050b57cec5SDimitry Andric 29060b57cec5SDimitry Andric static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF, 29070b57cec5SDimitry Andric const Expr *e) { 29080b57cec5SDimitry Andric e = e->IgnoreParens(); 29090b57cec5SDimitry Andric QualType type = e->getType(); 29100b57cec5SDimitry Andric 29110b57cec5SDimitry Andric // If we're loading retained from a __strong xvalue, we can avoid 29120b57cec5SDimitry Andric // an extra retain/release pair by zeroing out the source of this 29130b57cec5SDimitry Andric // "move" operation. 29140b57cec5SDimitry Andric if (e->isXValue() && 29150b57cec5SDimitry Andric !type.isConstQualified() && 29160b57cec5SDimitry Andric type.getObjCLifetime() == Qualifiers::OCL_Strong) { 29170b57cec5SDimitry Andric // Emit the lvalue. 29180b57cec5SDimitry Andric LValue lv = CGF.EmitLValue(e); 29190b57cec5SDimitry Andric 29200b57cec5SDimitry Andric // Load the object pointer. 29210b57cec5SDimitry Andric llvm::Value *result = CGF.EmitLoadOfLValue(lv, 29220b57cec5SDimitry Andric SourceLocation()).getScalarVal(); 29230b57cec5SDimitry Andric 29240b57cec5SDimitry Andric // Set the source pointer to NULL. 2925*0fca6ea1SDimitry Andric CGF.EmitStoreOfScalar(getNullForVariable(lv.getAddress()), lv); 29260b57cec5SDimitry Andric 29270b57cec5SDimitry Andric return TryEmitResult(result, true); 29280b57cec5SDimitry Andric } 29290b57cec5SDimitry Andric 29300b57cec5SDimitry Andric // As a very special optimization, in ARC++, if the l-value is the 29310b57cec5SDimitry Andric // result of a non-volatile assignment, do a simple retain of the 29320b57cec5SDimitry Andric // result of the call to objc_storeWeak instead of reloading. 29330b57cec5SDimitry Andric if (CGF.getLangOpts().CPlusPlus && 29340b57cec5SDimitry Andric !type.isVolatileQualified() && 29350b57cec5SDimitry Andric type.getObjCLifetime() == Qualifiers::OCL_Weak && 29360b57cec5SDimitry Andric isa<BinaryOperator>(e) && 29370b57cec5SDimitry Andric cast<BinaryOperator>(e)->getOpcode() == BO_Assign) 29380b57cec5SDimitry Andric return TryEmitResult(CGF.EmitScalarExpr(e), false); 29390b57cec5SDimitry Andric 29400b57cec5SDimitry Andric // Try to emit code for scalar constant instead of emitting LValue and 29410b57cec5SDimitry Andric // loading it because we are not guaranteed to have an l-value. One of such 29420b57cec5SDimitry Andric // cases is DeclRefExpr referencing non-odr-used constant-evaluated variable. 29430b57cec5SDimitry Andric if (const auto *decl_expr = dyn_cast<DeclRefExpr>(e)) { 29440b57cec5SDimitry Andric auto *DRE = const_cast<DeclRefExpr *>(decl_expr); 29450b57cec5SDimitry Andric if (CodeGenFunction::ConstantEmission constant = CGF.tryEmitAsConstant(DRE)) 29460b57cec5SDimitry Andric return TryEmitResult(CGF.emitScalarConstant(constant, DRE), 29470b57cec5SDimitry Andric !shouldRetainObjCLifetime(type.getObjCLifetime())); 29480b57cec5SDimitry Andric } 29490b57cec5SDimitry Andric 29500b57cec5SDimitry Andric return tryEmitARCRetainLoadOfScalar(CGF, CGF.EmitLValue(e), type); 29510b57cec5SDimitry Andric } 29520b57cec5SDimitry Andric 29530b57cec5SDimitry Andric typedef llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 29540b57cec5SDimitry Andric llvm::Value *value)> 29550b57cec5SDimitry Andric ValueTransform; 29560b57cec5SDimitry Andric 29570b57cec5SDimitry Andric /// Insert code immediately after a call. 2958e8d8bef9SDimitry Andric 2959e8d8bef9SDimitry Andric // FIXME: We should find a way to emit the runtime call immediately 2960e8d8bef9SDimitry Andric // after the call is emitted to eliminate the need for this function. 29610b57cec5SDimitry Andric static llvm::Value *emitARCOperationAfterCall(CodeGenFunction &CGF, 29620b57cec5SDimitry Andric llvm::Value *value, 29630b57cec5SDimitry Andric ValueTransform doAfterCall, 29640b57cec5SDimitry Andric ValueTransform doFallback) { 29650b57cec5SDimitry Andric CGBuilderTy::InsertPoint ip = CGF.Builder.saveIP(); 2966fe6060f1SDimitry Andric auto *callBase = dyn_cast<llvm::CallBase>(value); 29670b57cec5SDimitry Andric 2968fe6060f1SDimitry Andric if (callBase && llvm::objcarc::hasAttachedCallOpBundle(callBase)) { 2969fe6060f1SDimitry Andric // Fall back if the call base has operand bundle "clang.arc.attachedcall". 2970fe6060f1SDimitry Andric value = doFallback(CGF, value); 2971fe6060f1SDimitry Andric } else if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(value)) { 29720b57cec5SDimitry Andric // Place the retain immediately following the call. 29730b57cec5SDimitry Andric CGF.Builder.SetInsertPoint(call->getParent(), 29740b57cec5SDimitry Andric ++llvm::BasicBlock::iterator(call)); 29750b57cec5SDimitry Andric value = doAfterCall(CGF, value); 29760b57cec5SDimitry Andric } else if (llvm::InvokeInst *invoke = dyn_cast<llvm::InvokeInst>(value)) { 29770b57cec5SDimitry Andric // Place the retain at the beginning of the normal destination block. 29780b57cec5SDimitry Andric llvm::BasicBlock *BB = invoke->getNormalDest(); 29790b57cec5SDimitry Andric CGF.Builder.SetInsertPoint(BB, BB->begin()); 29800b57cec5SDimitry Andric value = doAfterCall(CGF, value); 29810b57cec5SDimitry Andric 29820b57cec5SDimitry Andric // Bitcasts can arise because of related-result returns. Rewrite 29830b57cec5SDimitry Andric // the operand. 29840b57cec5SDimitry Andric } else if (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(value)) { 2985e8d8bef9SDimitry Andric // Change the insert point to avoid emitting the fall-back call after the 2986e8d8bef9SDimitry Andric // bitcast. 2987e8d8bef9SDimitry Andric CGF.Builder.SetInsertPoint(bitcast->getParent(), bitcast->getIterator()); 29880b57cec5SDimitry Andric llvm::Value *operand = bitcast->getOperand(0); 29890b57cec5SDimitry Andric operand = emitARCOperationAfterCall(CGF, operand, doAfterCall, doFallback); 29900b57cec5SDimitry Andric bitcast->setOperand(0, operand); 2991e8d8bef9SDimitry Andric value = bitcast; 29920b57cec5SDimitry Andric } else { 2993e8d8bef9SDimitry Andric auto *phi = dyn_cast<llvm::PHINode>(value); 2994e8d8bef9SDimitry Andric if (phi && phi->getNumIncomingValues() == 2 && 2995e8d8bef9SDimitry Andric isa<llvm::ConstantPointerNull>(phi->getIncomingValue(1)) && 2996e8d8bef9SDimitry Andric isa<llvm::CallBase>(phi->getIncomingValue(0))) { 2997e8d8bef9SDimitry Andric // Handle phi instructions that are generated when it's necessary to check 2998e8d8bef9SDimitry Andric // whether the receiver of a message is null. 2999e8d8bef9SDimitry Andric llvm::Value *inVal = phi->getIncomingValue(0); 3000e8d8bef9SDimitry Andric inVal = emitARCOperationAfterCall(CGF, inVal, doAfterCall, doFallback); 3001e8d8bef9SDimitry Andric phi->setIncomingValue(0, inVal); 3002e8d8bef9SDimitry Andric value = phi; 3003e8d8bef9SDimitry Andric } else { 3004e8d8bef9SDimitry Andric // Generic fall-back case. 30050b57cec5SDimitry Andric // Retain using the non-block variant: we never need to do a copy 30060b57cec5SDimitry Andric // of a block that's been returned to us. 3007e8d8bef9SDimitry Andric value = doFallback(CGF, value); 30080b57cec5SDimitry Andric } 30090b57cec5SDimitry Andric } 30100b57cec5SDimitry Andric 3011e8d8bef9SDimitry Andric CGF.Builder.restoreIP(ip); 3012e8d8bef9SDimitry Andric return value; 3013e8d8bef9SDimitry Andric } 3014e8d8bef9SDimitry Andric 30150b57cec5SDimitry Andric /// Given that the given expression is some sort of call (which does 30160b57cec5SDimitry Andric /// not return retained), emit a retain following it. 30170b57cec5SDimitry Andric static llvm::Value *emitARCRetainCallResult(CodeGenFunction &CGF, 30180b57cec5SDimitry Andric const Expr *e) { 30190b57cec5SDimitry Andric llvm::Value *value = CGF.EmitScalarExpr(e); 30200b57cec5SDimitry Andric return emitARCOperationAfterCall(CGF, value, 30210b57cec5SDimitry Andric [](CodeGenFunction &CGF, llvm::Value *value) { 30220b57cec5SDimitry Andric return CGF.EmitARCRetainAutoreleasedReturnValue(value); 30230b57cec5SDimitry Andric }, 30240b57cec5SDimitry Andric [](CodeGenFunction &CGF, llvm::Value *value) { 30250b57cec5SDimitry Andric return CGF.EmitARCRetainNonBlock(value); 30260b57cec5SDimitry Andric }); 30270b57cec5SDimitry Andric } 30280b57cec5SDimitry Andric 30290b57cec5SDimitry Andric /// Given that the given expression is some sort of call (which does 30300b57cec5SDimitry Andric /// not return retained), perform an unsafeClaim following it. 30310b57cec5SDimitry Andric static llvm::Value *emitARCUnsafeClaimCallResult(CodeGenFunction &CGF, 30320b57cec5SDimitry Andric const Expr *e) { 30330b57cec5SDimitry Andric llvm::Value *value = CGF.EmitScalarExpr(e); 30340b57cec5SDimitry Andric return emitARCOperationAfterCall(CGF, value, 30350b57cec5SDimitry Andric [](CodeGenFunction &CGF, llvm::Value *value) { 30360b57cec5SDimitry Andric return CGF.EmitARCUnsafeClaimAutoreleasedReturnValue(value); 30370b57cec5SDimitry Andric }, 30380b57cec5SDimitry Andric [](CodeGenFunction &CGF, llvm::Value *value) { 30390b57cec5SDimitry Andric return value; 30400b57cec5SDimitry Andric }); 30410b57cec5SDimitry Andric } 30420b57cec5SDimitry Andric 30430b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCReclaimReturnedObject(const Expr *E, 30440b57cec5SDimitry Andric bool allowUnsafeClaim) { 30450b57cec5SDimitry Andric if (allowUnsafeClaim && 30460b57cec5SDimitry Andric CGM.getLangOpts().ObjCRuntime.hasARCUnsafeClaimAutoreleasedReturnValue()) { 30470b57cec5SDimitry Andric return emitARCUnsafeClaimCallResult(*this, E); 30480b57cec5SDimitry Andric } else { 30490b57cec5SDimitry Andric llvm::Value *value = emitARCRetainCallResult(*this, E); 30500b57cec5SDimitry Andric return EmitObjCConsumeObject(E->getType(), value); 30510b57cec5SDimitry Andric } 30520b57cec5SDimitry Andric } 30530b57cec5SDimitry Andric 30540b57cec5SDimitry Andric /// Determine whether it might be important to emit a separate 30550b57cec5SDimitry Andric /// objc_retain_block on the result of the given expression, or 30560b57cec5SDimitry Andric /// whether it's okay to just emit it in a +1 context. 30570b57cec5SDimitry Andric static bool shouldEmitSeparateBlockRetain(const Expr *e) { 30580b57cec5SDimitry Andric assert(e->getType()->isBlockPointerType()); 30590b57cec5SDimitry Andric e = e->IgnoreParens(); 30600b57cec5SDimitry Andric 30610b57cec5SDimitry Andric // For future goodness, emit block expressions directly in +1 30620b57cec5SDimitry Andric // contexts if we can. 30630b57cec5SDimitry Andric if (isa<BlockExpr>(e)) 30640b57cec5SDimitry Andric return false; 30650b57cec5SDimitry Andric 30660b57cec5SDimitry Andric if (const CastExpr *cast = dyn_cast<CastExpr>(e)) { 30670b57cec5SDimitry Andric switch (cast->getCastKind()) { 30680b57cec5SDimitry Andric // Emitting these operations in +1 contexts is goodness. 30690b57cec5SDimitry Andric case CK_LValueToRValue: 30700b57cec5SDimitry Andric case CK_ARCReclaimReturnedObject: 30710b57cec5SDimitry Andric case CK_ARCConsumeObject: 30720b57cec5SDimitry Andric case CK_ARCProduceObject: 30730b57cec5SDimitry Andric return false; 30740b57cec5SDimitry Andric 30750b57cec5SDimitry Andric // These operations preserve a block type. 30760b57cec5SDimitry Andric case CK_NoOp: 30770b57cec5SDimitry Andric case CK_BitCast: 30780b57cec5SDimitry Andric return shouldEmitSeparateBlockRetain(cast->getSubExpr()); 30790b57cec5SDimitry Andric 30800b57cec5SDimitry Andric // These operations are known to be bad (or haven't been considered). 30810b57cec5SDimitry Andric case CK_AnyPointerToBlockPointerCast: 30820b57cec5SDimitry Andric default: 30830b57cec5SDimitry Andric return true; 30840b57cec5SDimitry Andric } 30850b57cec5SDimitry Andric } 30860b57cec5SDimitry Andric 30870b57cec5SDimitry Andric return true; 30880b57cec5SDimitry Andric } 30890b57cec5SDimitry Andric 30900b57cec5SDimitry Andric namespace { 30910b57cec5SDimitry Andric /// A CRTP base class for emitting expressions of retainable object 30920b57cec5SDimitry Andric /// pointer type in ARC. 30930b57cec5SDimitry Andric template <typename Impl, typename Result> class ARCExprEmitter { 30940b57cec5SDimitry Andric protected: 30950b57cec5SDimitry Andric CodeGenFunction &CGF; 30960b57cec5SDimitry Andric Impl &asImpl() { return *static_cast<Impl*>(this); } 30970b57cec5SDimitry Andric 30980b57cec5SDimitry Andric ARCExprEmitter(CodeGenFunction &CGF) : CGF(CGF) {} 30990b57cec5SDimitry Andric 31000b57cec5SDimitry Andric public: 31010b57cec5SDimitry Andric Result visit(const Expr *e); 31020b57cec5SDimitry Andric Result visitCastExpr(const CastExpr *e); 31030b57cec5SDimitry Andric Result visitPseudoObjectExpr(const PseudoObjectExpr *e); 31040b57cec5SDimitry Andric Result visitBlockExpr(const BlockExpr *e); 31050b57cec5SDimitry Andric Result visitBinaryOperator(const BinaryOperator *e); 31060b57cec5SDimitry Andric Result visitBinAssign(const BinaryOperator *e); 31070b57cec5SDimitry Andric Result visitBinAssignUnsafeUnretained(const BinaryOperator *e); 31080b57cec5SDimitry Andric Result visitBinAssignAutoreleasing(const BinaryOperator *e); 31090b57cec5SDimitry Andric Result visitBinAssignWeak(const BinaryOperator *e); 31100b57cec5SDimitry Andric Result visitBinAssignStrong(const BinaryOperator *e); 31110b57cec5SDimitry Andric 31120b57cec5SDimitry Andric // Minimal implementation: 31130b57cec5SDimitry Andric // Result visitLValueToRValue(const Expr *e) 31140b57cec5SDimitry Andric // Result visitConsumeObject(const Expr *e) 31150b57cec5SDimitry Andric // Result visitExtendBlockObject(const Expr *e) 31160b57cec5SDimitry Andric // Result visitReclaimReturnedObject(const Expr *e) 31170b57cec5SDimitry Andric // Result visitCall(const Expr *e) 31180b57cec5SDimitry Andric // Result visitExpr(const Expr *e) 31190b57cec5SDimitry Andric // 31200b57cec5SDimitry Andric // Result emitBitCast(Result result, llvm::Type *resultType) 31210b57cec5SDimitry Andric // llvm::Value *getValueOfResult(Result result) 31220b57cec5SDimitry Andric }; 31230b57cec5SDimitry Andric } 31240b57cec5SDimitry Andric 31250b57cec5SDimitry Andric /// Try to emit a PseudoObjectExpr under special ARC rules. 31260b57cec5SDimitry Andric /// 31270b57cec5SDimitry Andric /// This massively duplicates emitPseudoObjectRValue. 31280b57cec5SDimitry Andric template <typename Impl, typename Result> 31290b57cec5SDimitry Andric Result 31300b57cec5SDimitry Andric ARCExprEmitter<Impl,Result>::visitPseudoObjectExpr(const PseudoObjectExpr *E) { 31310b57cec5SDimitry Andric SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; 31320b57cec5SDimitry Andric 31330b57cec5SDimitry Andric // Find the result expression. 31340b57cec5SDimitry Andric const Expr *resultExpr = E->getResultExpr(); 31350b57cec5SDimitry Andric assert(resultExpr); 31360b57cec5SDimitry Andric Result result; 31370b57cec5SDimitry Andric 31380b57cec5SDimitry Andric for (PseudoObjectExpr::const_semantics_iterator 31390b57cec5SDimitry Andric i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { 31400b57cec5SDimitry Andric const Expr *semantic = *i; 31410b57cec5SDimitry Andric 31420b57cec5SDimitry Andric // If this semantic expression is an opaque value, bind it 31430b57cec5SDimitry Andric // to the result of its source expression. 31440b57cec5SDimitry Andric if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) { 31450b57cec5SDimitry Andric typedef CodeGenFunction::OpaqueValueMappingData OVMA; 31460b57cec5SDimitry Andric OVMA opaqueData; 31470b57cec5SDimitry Andric 31480b57cec5SDimitry Andric // If this semantic is the result of the pseudo-object 31490b57cec5SDimitry Andric // expression, try to evaluate the source as +1. 31500b57cec5SDimitry Andric if (ov == resultExpr) { 31510b57cec5SDimitry Andric assert(!OVMA::shouldBindAsLValue(ov)); 31520b57cec5SDimitry Andric result = asImpl().visit(ov->getSourceExpr()); 31530b57cec5SDimitry Andric opaqueData = OVMA::bind(CGF, ov, 31540b57cec5SDimitry Andric RValue::get(asImpl().getValueOfResult(result))); 31550b57cec5SDimitry Andric 31560b57cec5SDimitry Andric // Otherwise, just bind it. 31570b57cec5SDimitry Andric } else { 31580b57cec5SDimitry Andric opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr()); 31590b57cec5SDimitry Andric } 31600b57cec5SDimitry Andric opaques.push_back(opaqueData); 31610b57cec5SDimitry Andric 31620b57cec5SDimitry Andric // Otherwise, if the expression is the result, evaluate it 31630b57cec5SDimitry Andric // and remember the result. 31640b57cec5SDimitry Andric } else if (semantic == resultExpr) { 31650b57cec5SDimitry Andric result = asImpl().visit(semantic); 31660b57cec5SDimitry Andric 31670b57cec5SDimitry Andric // Otherwise, evaluate the expression in an ignored context. 31680b57cec5SDimitry Andric } else { 31690b57cec5SDimitry Andric CGF.EmitIgnoredExpr(semantic); 31700b57cec5SDimitry Andric } 31710b57cec5SDimitry Andric } 31720b57cec5SDimitry Andric 31730b57cec5SDimitry Andric // Unbind all the opaques now. 31740b57cec5SDimitry Andric for (unsigned i = 0, e = opaques.size(); i != e; ++i) 31750b57cec5SDimitry Andric opaques[i].unbind(CGF); 31760b57cec5SDimitry Andric 31770b57cec5SDimitry Andric return result; 31780b57cec5SDimitry Andric } 31790b57cec5SDimitry Andric 31800b57cec5SDimitry Andric template <typename Impl, typename Result> 31810b57cec5SDimitry Andric Result ARCExprEmitter<Impl, Result>::visitBlockExpr(const BlockExpr *e) { 31820b57cec5SDimitry Andric // The default implementation just forwards the expression to visitExpr. 31830b57cec5SDimitry Andric return asImpl().visitExpr(e); 31840b57cec5SDimitry Andric } 31850b57cec5SDimitry Andric 31860b57cec5SDimitry Andric template <typename Impl, typename Result> 31870b57cec5SDimitry Andric Result ARCExprEmitter<Impl,Result>::visitCastExpr(const CastExpr *e) { 31880b57cec5SDimitry Andric switch (e->getCastKind()) { 31890b57cec5SDimitry Andric 31900b57cec5SDimitry Andric // No-op casts don't change the type, so we just ignore them. 31910b57cec5SDimitry Andric case CK_NoOp: 31920b57cec5SDimitry Andric return asImpl().visit(e->getSubExpr()); 31930b57cec5SDimitry Andric 31940b57cec5SDimitry Andric // These casts can change the type. 31950b57cec5SDimitry Andric case CK_CPointerToObjCPointerCast: 31960b57cec5SDimitry Andric case CK_BlockPointerToObjCPointerCast: 31970b57cec5SDimitry Andric case CK_AnyPointerToBlockPointerCast: 31980b57cec5SDimitry Andric case CK_BitCast: { 31990b57cec5SDimitry Andric llvm::Type *resultType = CGF.ConvertType(e->getType()); 32000b57cec5SDimitry Andric assert(e->getSubExpr()->getType()->hasPointerRepresentation()); 32010b57cec5SDimitry Andric Result result = asImpl().visit(e->getSubExpr()); 32020b57cec5SDimitry Andric return asImpl().emitBitCast(result, resultType); 32030b57cec5SDimitry Andric } 32040b57cec5SDimitry Andric 32050b57cec5SDimitry Andric // Handle some casts specially. 32060b57cec5SDimitry Andric case CK_LValueToRValue: 32070b57cec5SDimitry Andric return asImpl().visitLValueToRValue(e->getSubExpr()); 32080b57cec5SDimitry Andric case CK_ARCConsumeObject: 32090b57cec5SDimitry Andric return asImpl().visitConsumeObject(e->getSubExpr()); 32100b57cec5SDimitry Andric case CK_ARCExtendBlockObject: 32110b57cec5SDimitry Andric return asImpl().visitExtendBlockObject(e->getSubExpr()); 32120b57cec5SDimitry Andric case CK_ARCReclaimReturnedObject: 32130b57cec5SDimitry Andric return asImpl().visitReclaimReturnedObject(e->getSubExpr()); 32140b57cec5SDimitry Andric 32150b57cec5SDimitry Andric // Otherwise, use the default logic. 32160b57cec5SDimitry Andric default: 32170b57cec5SDimitry Andric return asImpl().visitExpr(e); 32180b57cec5SDimitry Andric } 32190b57cec5SDimitry Andric } 32200b57cec5SDimitry Andric 32210b57cec5SDimitry Andric template <typename Impl, typename Result> 32220b57cec5SDimitry Andric Result 32230b57cec5SDimitry Andric ARCExprEmitter<Impl,Result>::visitBinaryOperator(const BinaryOperator *e) { 32240b57cec5SDimitry Andric switch (e->getOpcode()) { 32250b57cec5SDimitry Andric case BO_Comma: 32260b57cec5SDimitry Andric CGF.EmitIgnoredExpr(e->getLHS()); 32270b57cec5SDimitry Andric CGF.EnsureInsertPoint(); 32280b57cec5SDimitry Andric return asImpl().visit(e->getRHS()); 32290b57cec5SDimitry Andric 32300b57cec5SDimitry Andric case BO_Assign: 32310b57cec5SDimitry Andric return asImpl().visitBinAssign(e); 32320b57cec5SDimitry Andric 32330b57cec5SDimitry Andric default: 32340b57cec5SDimitry Andric return asImpl().visitExpr(e); 32350b57cec5SDimitry Andric } 32360b57cec5SDimitry Andric } 32370b57cec5SDimitry Andric 32380b57cec5SDimitry Andric template <typename Impl, typename Result> 32390b57cec5SDimitry Andric Result ARCExprEmitter<Impl,Result>::visitBinAssign(const BinaryOperator *e) { 32400b57cec5SDimitry Andric switch (e->getLHS()->getType().getObjCLifetime()) { 32410b57cec5SDimitry Andric case Qualifiers::OCL_ExplicitNone: 32420b57cec5SDimitry Andric return asImpl().visitBinAssignUnsafeUnretained(e); 32430b57cec5SDimitry Andric 32440b57cec5SDimitry Andric case Qualifiers::OCL_Weak: 32450b57cec5SDimitry Andric return asImpl().visitBinAssignWeak(e); 32460b57cec5SDimitry Andric 32470b57cec5SDimitry Andric case Qualifiers::OCL_Autoreleasing: 32480b57cec5SDimitry Andric return asImpl().visitBinAssignAutoreleasing(e); 32490b57cec5SDimitry Andric 32500b57cec5SDimitry Andric case Qualifiers::OCL_Strong: 32510b57cec5SDimitry Andric return asImpl().visitBinAssignStrong(e); 32520b57cec5SDimitry Andric 32530b57cec5SDimitry Andric case Qualifiers::OCL_None: 32540b57cec5SDimitry Andric return asImpl().visitExpr(e); 32550b57cec5SDimitry Andric } 32560b57cec5SDimitry Andric llvm_unreachable("bad ObjC ownership qualifier"); 32570b57cec5SDimitry Andric } 32580b57cec5SDimitry Andric 32590b57cec5SDimitry Andric /// The default rule for __unsafe_unretained emits the RHS recursively, 32600b57cec5SDimitry Andric /// stores into the unsafe variable, and propagates the result outward. 32610b57cec5SDimitry Andric template <typename Impl, typename Result> 32620b57cec5SDimitry Andric Result ARCExprEmitter<Impl,Result>:: 32630b57cec5SDimitry Andric visitBinAssignUnsafeUnretained(const BinaryOperator *e) { 32640b57cec5SDimitry Andric // Recursively emit the RHS. 32650b57cec5SDimitry Andric // For __block safety, do this before emitting the LHS. 32660b57cec5SDimitry Andric Result result = asImpl().visit(e->getRHS()); 32670b57cec5SDimitry Andric 32680b57cec5SDimitry Andric // Perform the store. 32690b57cec5SDimitry Andric LValue lvalue = 32700b57cec5SDimitry Andric CGF.EmitCheckedLValue(e->getLHS(), CodeGenFunction::TCK_Store); 32710b57cec5SDimitry Andric CGF.EmitStoreThroughLValue(RValue::get(asImpl().getValueOfResult(result)), 32720b57cec5SDimitry Andric lvalue); 32730b57cec5SDimitry Andric 32740b57cec5SDimitry Andric return result; 32750b57cec5SDimitry Andric } 32760b57cec5SDimitry Andric 32770b57cec5SDimitry Andric template <typename Impl, typename Result> 32780b57cec5SDimitry Andric Result 32790b57cec5SDimitry Andric ARCExprEmitter<Impl,Result>::visitBinAssignAutoreleasing(const BinaryOperator *e) { 32800b57cec5SDimitry Andric return asImpl().visitExpr(e); 32810b57cec5SDimitry Andric } 32820b57cec5SDimitry Andric 32830b57cec5SDimitry Andric template <typename Impl, typename Result> 32840b57cec5SDimitry Andric Result 32850b57cec5SDimitry Andric ARCExprEmitter<Impl,Result>::visitBinAssignWeak(const BinaryOperator *e) { 32860b57cec5SDimitry Andric return asImpl().visitExpr(e); 32870b57cec5SDimitry Andric } 32880b57cec5SDimitry Andric 32890b57cec5SDimitry Andric template <typename Impl, typename Result> 32900b57cec5SDimitry Andric Result 32910b57cec5SDimitry Andric ARCExprEmitter<Impl,Result>::visitBinAssignStrong(const BinaryOperator *e) { 32920b57cec5SDimitry Andric return asImpl().visitExpr(e); 32930b57cec5SDimitry Andric } 32940b57cec5SDimitry Andric 32950b57cec5SDimitry Andric /// The general expression-emission logic. 32960b57cec5SDimitry Andric template <typename Impl, typename Result> 32970b57cec5SDimitry Andric Result ARCExprEmitter<Impl,Result>::visit(const Expr *e) { 32980b57cec5SDimitry Andric // We should *never* see a nested full-expression here, because if 32990b57cec5SDimitry Andric // we fail to emit at +1, our caller must not retain after we close 33000b57cec5SDimitry Andric // out the full-expression. This isn't as important in the unsafe 33010b57cec5SDimitry Andric // emitter. 33020b57cec5SDimitry Andric assert(!isa<ExprWithCleanups>(e)); 33030b57cec5SDimitry Andric 33040b57cec5SDimitry Andric // Look through parens, __extension__, generic selection, etc. 33050b57cec5SDimitry Andric e = e->IgnoreParens(); 33060b57cec5SDimitry Andric 33070b57cec5SDimitry Andric // Handle certain kinds of casts. 33080b57cec5SDimitry Andric if (const CastExpr *ce = dyn_cast<CastExpr>(e)) { 33090b57cec5SDimitry Andric return asImpl().visitCastExpr(ce); 33100b57cec5SDimitry Andric 33110b57cec5SDimitry Andric // Handle the comma operator. 33120b57cec5SDimitry Andric } else if (auto op = dyn_cast<BinaryOperator>(e)) { 33130b57cec5SDimitry Andric return asImpl().visitBinaryOperator(op); 33140b57cec5SDimitry Andric 33150b57cec5SDimitry Andric // TODO: handle conditional operators here 33160b57cec5SDimitry Andric 33170b57cec5SDimitry Andric // For calls and message sends, use the retained-call logic. 33180b57cec5SDimitry Andric // Delegate inits are a special case in that they're the only 33190b57cec5SDimitry Andric // returns-retained expression that *isn't* surrounded by 33200b57cec5SDimitry Andric // a consume. 33210b57cec5SDimitry Andric } else if (isa<CallExpr>(e) || 33220b57cec5SDimitry Andric (isa<ObjCMessageExpr>(e) && 33230b57cec5SDimitry Andric !cast<ObjCMessageExpr>(e)->isDelegateInitCall())) { 33240b57cec5SDimitry Andric return asImpl().visitCall(e); 33250b57cec5SDimitry Andric 33260b57cec5SDimitry Andric // Look through pseudo-object expressions. 33270b57cec5SDimitry Andric } else if (const PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) { 33280b57cec5SDimitry Andric return asImpl().visitPseudoObjectExpr(pseudo); 33290b57cec5SDimitry Andric } else if (auto *be = dyn_cast<BlockExpr>(e)) 33300b57cec5SDimitry Andric return asImpl().visitBlockExpr(be); 33310b57cec5SDimitry Andric 33320b57cec5SDimitry Andric return asImpl().visitExpr(e); 33330b57cec5SDimitry Andric } 33340b57cec5SDimitry Andric 33350b57cec5SDimitry Andric namespace { 33360b57cec5SDimitry Andric 33370b57cec5SDimitry Andric /// An emitter for +1 results. 33380b57cec5SDimitry Andric struct ARCRetainExprEmitter : 33390b57cec5SDimitry Andric public ARCExprEmitter<ARCRetainExprEmitter, TryEmitResult> { 33400b57cec5SDimitry Andric 33410b57cec5SDimitry Andric ARCRetainExprEmitter(CodeGenFunction &CGF) : ARCExprEmitter(CGF) {} 33420b57cec5SDimitry Andric 33430b57cec5SDimitry Andric llvm::Value *getValueOfResult(TryEmitResult result) { 33440b57cec5SDimitry Andric return result.getPointer(); 33450b57cec5SDimitry Andric } 33460b57cec5SDimitry Andric 33470b57cec5SDimitry Andric TryEmitResult emitBitCast(TryEmitResult result, llvm::Type *resultType) { 33480b57cec5SDimitry Andric llvm::Value *value = result.getPointer(); 33490b57cec5SDimitry Andric value = CGF.Builder.CreateBitCast(value, resultType); 33500b57cec5SDimitry Andric result.setPointer(value); 33510b57cec5SDimitry Andric return result; 33520b57cec5SDimitry Andric } 33530b57cec5SDimitry Andric 33540b57cec5SDimitry Andric TryEmitResult visitLValueToRValue(const Expr *e) { 33550b57cec5SDimitry Andric return tryEmitARCRetainLoadOfScalar(CGF, e); 33560b57cec5SDimitry Andric } 33570b57cec5SDimitry Andric 33580b57cec5SDimitry Andric /// For consumptions, just emit the subexpression and thus elide 33590b57cec5SDimitry Andric /// the retain/release pair. 33600b57cec5SDimitry Andric TryEmitResult visitConsumeObject(const Expr *e) { 33610b57cec5SDimitry Andric llvm::Value *result = CGF.EmitScalarExpr(e); 33620b57cec5SDimitry Andric return TryEmitResult(result, true); 33630b57cec5SDimitry Andric } 33640b57cec5SDimitry Andric 33650b57cec5SDimitry Andric TryEmitResult visitBlockExpr(const BlockExpr *e) { 33660b57cec5SDimitry Andric TryEmitResult result = visitExpr(e); 33670b57cec5SDimitry Andric // Avoid the block-retain if this is a block literal that doesn't need to be 33680b57cec5SDimitry Andric // copied to the heap. 3369349cc55cSDimitry Andric if (CGF.CGM.getCodeGenOpts().ObjCAvoidHeapifyLocalBlocks && 3370349cc55cSDimitry Andric e->getBlockDecl()->canAvoidCopyToHeap()) 33710b57cec5SDimitry Andric result.setInt(true); 33720b57cec5SDimitry Andric return result; 33730b57cec5SDimitry Andric } 33740b57cec5SDimitry Andric 33750b57cec5SDimitry Andric /// Block extends are net +0. Naively, we could just recurse on 33760b57cec5SDimitry Andric /// the subexpression, but actually we need to ensure that the 33770b57cec5SDimitry Andric /// value is copied as a block, so there's a little filter here. 33780b57cec5SDimitry Andric TryEmitResult visitExtendBlockObject(const Expr *e) { 33790b57cec5SDimitry Andric llvm::Value *result; // will be a +0 value 33800b57cec5SDimitry Andric 33810b57cec5SDimitry Andric // If we can't safely assume the sub-expression will produce a 33820b57cec5SDimitry Andric // block-copied value, emit the sub-expression at +0. 33830b57cec5SDimitry Andric if (shouldEmitSeparateBlockRetain(e)) { 33840b57cec5SDimitry Andric result = CGF.EmitScalarExpr(e); 33850b57cec5SDimitry Andric 33860b57cec5SDimitry Andric // Otherwise, try to emit the sub-expression at +1 recursively. 33870b57cec5SDimitry Andric } else { 33880b57cec5SDimitry Andric TryEmitResult subresult = asImpl().visit(e); 33890b57cec5SDimitry Andric 33900b57cec5SDimitry Andric // If that produced a retained value, just use that. 33910b57cec5SDimitry Andric if (subresult.getInt()) { 33920b57cec5SDimitry Andric return subresult; 33930b57cec5SDimitry Andric } 33940b57cec5SDimitry Andric 33950b57cec5SDimitry Andric // Otherwise it's +0. 33960b57cec5SDimitry Andric result = subresult.getPointer(); 33970b57cec5SDimitry Andric } 33980b57cec5SDimitry Andric 33990b57cec5SDimitry Andric // Retain the object as a block. 34000b57cec5SDimitry Andric result = CGF.EmitARCRetainBlock(result, /*mandatory*/ true); 34010b57cec5SDimitry Andric return TryEmitResult(result, true); 34020b57cec5SDimitry Andric } 34030b57cec5SDimitry Andric 34040b57cec5SDimitry Andric /// For reclaims, emit the subexpression as a retained call and 34050b57cec5SDimitry Andric /// skip the consumption. 34060b57cec5SDimitry Andric TryEmitResult visitReclaimReturnedObject(const Expr *e) { 34070b57cec5SDimitry Andric llvm::Value *result = emitARCRetainCallResult(CGF, e); 34080b57cec5SDimitry Andric return TryEmitResult(result, true); 34090b57cec5SDimitry Andric } 34100b57cec5SDimitry Andric 34110b57cec5SDimitry Andric /// When we have an undecorated call, retroactively do a claim. 34120b57cec5SDimitry Andric TryEmitResult visitCall(const Expr *e) { 34130b57cec5SDimitry Andric llvm::Value *result = emitARCRetainCallResult(CGF, e); 34140b57cec5SDimitry Andric return TryEmitResult(result, true); 34150b57cec5SDimitry Andric } 34160b57cec5SDimitry Andric 34170b57cec5SDimitry Andric // TODO: maybe special-case visitBinAssignWeak? 34180b57cec5SDimitry Andric 34190b57cec5SDimitry Andric TryEmitResult visitExpr(const Expr *e) { 34200b57cec5SDimitry Andric // We didn't find an obvious production, so emit what we've got and 34210b57cec5SDimitry Andric // tell the caller that we didn't manage to retain. 34220b57cec5SDimitry Andric llvm::Value *result = CGF.EmitScalarExpr(e); 34230b57cec5SDimitry Andric return TryEmitResult(result, false); 34240b57cec5SDimitry Andric } 34250b57cec5SDimitry Andric }; 34260b57cec5SDimitry Andric } 34270b57cec5SDimitry Andric 34280b57cec5SDimitry Andric static TryEmitResult 34290b57cec5SDimitry Andric tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { 34300b57cec5SDimitry Andric return ARCRetainExprEmitter(CGF).visit(e); 34310b57cec5SDimitry Andric } 34320b57cec5SDimitry Andric 34330b57cec5SDimitry Andric static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF, 34340b57cec5SDimitry Andric LValue lvalue, 34350b57cec5SDimitry Andric QualType type) { 34360b57cec5SDimitry Andric TryEmitResult result = tryEmitARCRetainLoadOfScalar(CGF, lvalue, type); 34370b57cec5SDimitry Andric llvm::Value *value = result.getPointer(); 34380b57cec5SDimitry Andric if (!result.getInt()) 34390b57cec5SDimitry Andric value = CGF.EmitARCRetain(type, value); 34400b57cec5SDimitry Andric return value; 34410b57cec5SDimitry Andric } 34420b57cec5SDimitry Andric 34430b57cec5SDimitry Andric /// EmitARCRetainScalarExpr - Semantically equivalent to 34440b57cec5SDimitry Andric /// EmitARCRetainObject(e->getType(), EmitScalarExpr(e)), but making a 34450b57cec5SDimitry Andric /// best-effort attempt to peephole expressions that naturally produce 34460b57cec5SDimitry Andric /// retained objects. 34470b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCRetainScalarExpr(const Expr *e) { 34480b57cec5SDimitry Andric // The retain needs to happen within the full-expression. 34490b57cec5SDimitry Andric if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { 34500b57cec5SDimitry Andric RunCleanupsScope scope(*this); 34510b57cec5SDimitry Andric return EmitARCRetainScalarExpr(cleanups->getSubExpr()); 34520b57cec5SDimitry Andric } 34530b57cec5SDimitry Andric 34540b57cec5SDimitry Andric TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e); 34550b57cec5SDimitry Andric llvm::Value *value = result.getPointer(); 34560b57cec5SDimitry Andric if (!result.getInt()) 34570b57cec5SDimitry Andric value = EmitARCRetain(e->getType(), value); 34580b57cec5SDimitry Andric return value; 34590b57cec5SDimitry Andric } 34600b57cec5SDimitry Andric 34610b57cec5SDimitry Andric llvm::Value * 34620b57cec5SDimitry Andric CodeGenFunction::EmitARCRetainAutoreleaseScalarExpr(const Expr *e) { 34630b57cec5SDimitry Andric // The retain needs to happen within the full-expression. 34640b57cec5SDimitry Andric if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { 34650b57cec5SDimitry Andric RunCleanupsScope scope(*this); 34660b57cec5SDimitry Andric return EmitARCRetainAutoreleaseScalarExpr(cleanups->getSubExpr()); 34670b57cec5SDimitry Andric } 34680b57cec5SDimitry Andric 34690b57cec5SDimitry Andric TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e); 34700b57cec5SDimitry Andric llvm::Value *value = result.getPointer(); 34710b57cec5SDimitry Andric if (result.getInt()) 34720b57cec5SDimitry Andric value = EmitARCAutorelease(value); 34730b57cec5SDimitry Andric else 34740b57cec5SDimitry Andric value = EmitARCRetainAutorelease(e->getType(), value); 34750b57cec5SDimitry Andric return value; 34760b57cec5SDimitry Andric } 34770b57cec5SDimitry Andric 34780b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCExtendBlockObject(const Expr *e) { 34790b57cec5SDimitry Andric llvm::Value *result; 34800b57cec5SDimitry Andric bool doRetain; 34810b57cec5SDimitry Andric 34820b57cec5SDimitry Andric if (shouldEmitSeparateBlockRetain(e)) { 34830b57cec5SDimitry Andric result = EmitScalarExpr(e); 34840b57cec5SDimitry Andric doRetain = true; 34850b57cec5SDimitry Andric } else { 34860b57cec5SDimitry Andric TryEmitResult subresult = tryEmitARCRetainScalarExpr(*this, e); 34870b57cec5SDimitry Andric result = subresult.getPointer(); 34880b57cec5SDimitry Andric doRetain = !subresult.getInt(); 34890b57cec5SDimitry Andric } 34900b57cec5SDimitry Andric 34910b57cec5SDimitry Andric if (doRetain) 34920b57cec5SDimitry Andric result = EmitARCRetainBlock(result, /*mandatory*/ true); 34930b57cec5SDimitry Andric return EmitObjCConsumeObject(e->getType(), result); 34940b57cec5SDimitry Andric } 34950b57cec5SDimitry Andric 34960b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitObjCThrowOperand(const Expr *expr) { 34970b57cec5SDimitry Andric // In ARC, retain and autorelease the expression. 34980b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount) { 34990b57cec5SDimitry Andric // Do so before running any cleanups for the full-expression. 35000b57cec5SDimitry Andric // EmitARCRetainAutoreleaseScalarExpr does this for us. 35010b57cec5SDimitry Andric return EmitARCRetainAutoreleaseScalarExpr(expr); 35020b57cec5SDimitry Andric } 35030b57cec5SDimitry Andric 35040b57cec5SDimitry Andric // Otherwise, use the normal scalar-expression emission. The 35050b57cec5SDimitry Andric // exception machinery doesn't do anything special with the 35060b57cec5SDimitry Andric // exception like retaining it, so there's no safety associated with 35070b57cec5SDimitry Andric // only running cleanups after the throw has started, and when it 35080b57cec5SDimitry Andric // matters it tends to be substantially inferior code. 35090b57cec5SDimitry Andric return EmitScalarExpr(expr); 35100b57cec5SDimitry Andric } 35110b57cec5SDimitry Andric 35120b57cec5SDimitry Andric namespace { 35130b57cec5SDimitry Andric 35140b57cec5SDimitry Andric /// An emitter for assigning into an __unsafe_unretained context. 35150b57cec5SDimitry Andric struct ARCUnsafeUnretainedExprEmitter : 35160b57cec5SDimitry Andric public ARCExprEmitter<ARCUnsafeUnretainedExprEmitter, llvm::Value*> { 35170b57cec5SDimitry Andric 35180b57cec5SDimitry Andric ARCUnsafeUnretainedExprEmitter(CodeGenFunction &CGF) : ARCExprEmitter(CGF) {} 35190b57cec5SDimitry Andric 35200b57cec5SDimitry Andric llvm::Value *getValueOfResult(llvm::Value *value) { 35210b57cec5SDimitry Andric return value; 35220b57cec5SDimitry Andric } 35230b57cec5SDimitry Andric 35240b57cec5SDimitry Andric llvm::Value *emitBitCast(llvm::Value *value, llvm::Type *resultType) { 35250b57cec5SDimitry Andric return CGF.Builder.CreateBitCast(value, resultType); 35260b57cec5SDimitry Andric } 35270b57cec5SDimitry Andric 35280b57cec5SDimitry Andric llvm::Value *visitLValueToRValue(const Expr *e) { 35290b57cec5SDimitry Andric return CGF.EmitScalarExpr(e); 35300b57cec5SDimitry Andric } 35310b57cec5SDimitry Andric 35320b57cec5SDimitry Andric /// For consumptions, just emit the subexpression and perform the 35330b57cec5SDimitry Andric /// consumption like normal. 35340b57cec5SDimitry Andric llvm::Value *visitConsumeObject(const Expr *e) { 35350b57cec5SDimitry Andric llvm::Value *value = CGF.EmitScalarExpr(e); 35360b57cec5SDimitry Andric return CGF.EmitObjCConsumeObject(e->getType(), value); 35370b57cec5SDimitry Andric } 35380b57cec5SDimitry Andric 35390b57cec5SDimitry Andric /// No special logic for block extensions. (This probably can't 35400b57cec5SDimitry Andric /// actually happen in this emitter, though.) 35410b57cec5SDimitry Andric llvm::Value *visitExtendBlockObject(const Expr *e) { 35420b57cec5SDimitry Andric return CGF.EmitARCExtendBlockObject(e); 35430b57cec5SDimitry Andric } 35440b57cec5SDimitry Andric 35450b57cec5SDimitry Andric /// For reclaims, perform an unsafeClaim if that's enabled. 35460b57cec5SDimitry Andric llvm::Value *visitReclaimReturnedObject(const Expr *e) { 35470b57cec5SDimitry Andric return CGF.EmitARCReclaimReturnedObject(e, /*unsafe*/ true); 35480b57cec5SDimitry Andric } 35490b57cec5SDimitry Andric 35500b57cec5SDimitry Andric /// When we have an undecorated call, just emit it without adding 35510b57cec5SDimitry Andric /// the unsafeClaim. 35520b57cec5SDimitry Andric llvm::Value *visitCall(const Expr *e) { 35530b57cec5SDimitry Andric return CGF.EmitScalarExpr(e); 35540b57cec5SDimitry Andric } 35550b57cec5SDimitry Andric 35560b57cec5SDimitry Andric /// Just do normal scalar emission in the default case. 35570b57cec5SDimitry Andric llvm::Value *visitExpr(const Expr *e) { 35580b57cec5SDimitry Andric return CGF.EmitScalarExpr(e); 35590b57cec5SDimitry Andric } 35600b57cec5SDimitry Andric }; 35610b57cec5SDimitry Andric } 35620b57cec5SDimitry Andric 35630b57cec5SDimitry Andric static llvm::Value *emitARCUnsafeUnretainedScalarExpr(CodeGenFunction &CGF, 35640b57cec5SDimitry Andric const Expr *e) { 35650b57cec5SDimitry Andric return ARCUnsafeUnretainedExprEmitter(CGF).visit(e); 35660b57cec5SDimitry Andric } 35670b57cec5SDimitry Andric 35680b57cec5SDimitry Andric /// EmitARCUnsafeUnretainedScalarExpr - Semantically equivalent to 35690b57cec5SDimitry Andric /// immediately releasing the resut of EmitARCRetainScalarExpr, but 35700b57cec5SDimitry Andric /// avoiding any spurious retains, including by performing reclaims 35710b57cec5SDimitry Andric /// with objc_unsafeClaimAutoreleasedReturnValue. 35720b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitARCUnsafeUnretainedScalarExpr(const Expr *e) { 35730b57cec5SDimitry Andric // Look through full-expressions. 35740b57cec5SDimitry Andric if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) { 35750b57cec5SDimitry Andric RunCleanupsScope scope(*this); 35760b57cec5SDimitry Andric return emitARCUnsafeUnretainedScalarExpr(*this, cleanups->getSubExpr()); 35770b57cec5SDimitry Andric } 35780b57cec5SDimitry Andric 35790b57cec5SDimitry Andric return emitARCUnsafeUnretainedScalarExpr(*this, e); 35800b57cec5SDimitry Andric } 35810b57cec5SDimitry Andric 35820b57cec5SDimitry Andric std::pair<LValue,llvm::Value*> 35830b57cec5SDimitry Andric CodeGenFunction::EmitARCStoreUnsafeUnretained(const BinaryOperator *e, 35840b57cec5SDimitry Andric bool ignored) { 35850b57cec5SDimitry Andric // Evaluate the RHS first. If we're ignoring the result, assume 35860b57cec5SDimitry Andric // that we can emit at an unsafe +0. 35870b57cec5SDimitry Andric llvm::Value *value; 35880b57cec5SDimitry Andric if (ignored) { 35890b57cec5SDimitry Andric value = EmitARCUnsafeUnretainedScalarExpr(e->getRHS()); 35900b57cec5SDimitry Andric } else { 35910b57cec5SDimitry Andric value = EmitScalarExpr(e->getRHS()); 35920b57cec5SDimitry Andric } 35930b57cec5SDimitry Andric 35940b57cec5SDimitry Andric // Emit the LHS and perform the store. 35950b57cec5SDimitry Andric LValue lvalue = EmitLValue(e->getLHS()); 35960b57cec5SDimitry Andric EmitStoreOfScalar(value, lvalue); 35970b57cec5SDimitry Andric 35980b57cec5SDimitry Andric return std::pair<LValue,llvm::Value*>(std::move(lvalue), value); 35990b57cec5SDimitry Andric } 36000b57cec5SDimitry Andric 36010b57cec5SDimitry Andric std::pair<LValue,llvm::Value*> 36020b57cec5SDimitry Andric CodeGenFunction::EmitARCStoreStrong(const BinaryOperator *e, 36030b57cec5SDimitry Andric bool ignored) { 36040b57cec5SDimitry Andric // Evaluate the RHS first. 36050b57cec5SDimitry Andric TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e->getRHS()); 36060b57cec5SDimitry Andric llvm::Value *value = result.getPointer(); 36070b57cec5SDimitry Andric 36080b57cec5SDimitry Andric bool hasImmediateRetain = result.getInt(); 36090b57cec5SDimitry Andric 36100b57cec5SDimitry Andric // If we didn't emit a retained object, and the l-value is of block 36110b57cec5SDimitry Andric // type, then we need to emit the block-retain immediately in case 36120b57cec5SDimitry Andric // it invalidates the l-value. 36130b57cec5SDimitry Andric if (!hasImmediateRetain && e->getType()->isBlockPointerType()) { 36140b57cec5SDimitry Andric value = EmitARCRetainBlock(value, /*mandatory*/ false); 36150b57cec5SDimitry Andric hasImmediateRetain = true; 36160b57cec5SDimitry Andric } 36170b57cec5SDimitry Andric 36180b57cec5SDimitry Andric LValue lvalue = EmitLValue(e->getLHS()); 36190b57cec5SDimitry Andric 36200b57cec5SDimitry Andric // If the RHS was emitted retained, expand this. 36210b57cec5SDimitry Andric if (hasImmediateRetain) { 36220b57cec5SDimitry Andric llvm::Value *oldValue = EmitLoadOfScalar(lvalue, SourceLocation()); 36230b57cec5SDimitry Andric EmitStoreOfScalar(value, lvalue); 36240b57cec5SDimitry Andric EmitARCRelease(oldValue, lvalue.isARCPreciseLifetime()); 36250b57cec5SDimitry Andric } else { 36260b57cec5SDimitry Andric value = EmitARCStoreStrong(lvalue, value, ignored); 36270b57cec5SDimitry Andric } 36280b57cec5SDimitry Andric 36290b57cec5SDimitry Andric return std::pair<LValue,llvm::Value*>(lvalue, value); 36300b57cec5SDimitry Andric } 36310b57cec5SDimitry Andric 36320b57cec5SDimitry Andric std::pair<LValue,llvm::Value*> 36330b57cec5SDimitry Andric CodeGenFunction::EmitARCStoreAutoreleasing(const BinaryOperator *e) { 36340b57cec5SDimitry Andric llvm::Value *value = EmitARCRetainAutoreleaseScalarExpr(e->getRHS()); 36350b57cec5SDimitry Andric LValue lvalue = EmitLValue(e->getLHS()); 36360b57cec5SDimitry Andric 36370b57cec5SDimitry Andric EmitStoreOfScalar(value, lvalue); 36380b57cec5SDimitry Andric 36390b57cec5SDimitry Andric return std::pair<LValue,llvm::Value*>(lvalue, value); 36400b57cec5SDimitry Andric } 36410b57cec5SDimitry Andric 36420b57cec5SDimitry Andric void CodeGenFunction::EmitObjCAutoreleasePoolStmt( 36430b57cec5SDimitry Andric const ObjCAutoreleasePoolStmt &ARPS) { 36440b57cec5SDimitry Andric const Stmt *subStmt = ARPS.getSubStmt(); 36450b57cec5SDimitry Andric const CompoundStmt &S = cast<CompoundStmt>(*subStmt); 36460b57cec5SDimitry Andric 36470b57cec5SDimitry Andric CGDebugInfo *DI = getDebugInfo(); 36480b57cec5SDimitry Andric if (DI) 36490b57cec5SDimitry Andric DI->EmitLexicalBlockStart(Builder, S.getLBracLoc()); 36500b57cec5SDimitry Andric 36510b57cec5SDimitry Andric // Keep track of the current cleanup stack depth. 36520b57cec5SDimitry Andric RunCleanupsScope Scope(*this); 36530b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCRuntime.hasNativeARC()) { 36540b57cec5SDimitry Andric llvm::Value *token = EmitObjCAutoreleasePoolPush(); 36550b57cec5SDimitry Andric EHStack.pushCleanup<CallObjCAutoreleasePoolObject>(NormalCleanup, token); 36560b57cec5SDimitry Andric } else { 36570b57cec5SDimitry Andric llvm::Value *token = EmitObjCMRRAutoreleasePoolPush(); 36580b57cec5SDimitry Andric EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, token); 36590b57cec5SDimitry Andric } 36600b57cec5SDimitry Andric 36610b57cec5SDimitry Andric for (const auto *I : S.body()) 36620b57cec5SDimitry Andric EmitStmt(I); 36630b57cec5SDimitry Andric 36640b57cec5SDimitry Andric if (DI) 36650b57cec5SDimitry Andric DI->EmitLexicalBlockEnd(Builder, S.getRBracLoc()); 36660b57cec5SDimitry Andric } 36670b57cec5SDimitry Andric 36680b57cec5SDimitry Andric /// EmitExtendGCLifetime - Given a pointer to an Objective-C object, 36690b57cec5SDimitry Andric /// make sure it survives garbage collection until this point. 36700b57cec5SDimitry Andric void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) { 36710b57cec5SDimitry Andric // We just use an inline assembly. 36720b57cec5SDimitry Andric llvm::FunctionType *extenderType 36730b57cec5SDimitry Andric = llvm::FunctionType::get(VoidTy, VoidPtrTy, RequiredArgs::All); 36740b57cec5SDimitry Andric llvm::InlineAsm *extender = llvm::InlineAsm::get(extenderType, 36750b57cec5SDimitry Andric /* assembly */ "", 36760b57cec5SDimitry Andric /* constraints */ "r", 36770b57cec5SDimitry Andric /* side effects */ true); 36780b57cec5SDimitry Andric 36790b57cec5SDimitry Andric EmitNounwindRuntimeCall(extender, object); 36800b57cec5SDimitry Andric } 36810b57cec5SDimitry Andric 36820b57cec5SDimitry Andric /// GenerateObjCAtomicSetterCopyHelperFunction - Given a c++ object type with 36830b57cec5SDimitry Andric /// non-trivial copy assignment function, produce following helper function. 36840b57cec5SDimitry Andric /// static void copyHelper(Ty *dest, const Ty *source) { *dest = *source; } 36850b57cec5SDimitry Andric /// 36860b57cec5SDimitry Andric llvm::Constant * 36870b57cec5SDimitry Andric CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( 36880b57cec5SDimitry Andric const ObjCPropertyImplDecl *PID) { 3689bdd1243dSDimitry Andric const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 3690bdd1243dSDimitry Andric if ((!(PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic))) 3691bdd1243dSDimitry Andric return nullptr; 3692bdd1243dSDimitry Andric 3693bdd1243dSDimitry Andric QualType Ty = PID->getPropertyIvarDecl()->getType(); 3694bdd1243dSDimitry Andric ASTContext &C = getContext(); 3695bdd1243dSDimitry Andric 3696bdd1243dSDimitry Andric if (Ty.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) { 3697bdd1243dSDimitry Andric // Call the move assignment operator instead of calling the copy assignment 3698bdd1243dSDimitry Andric // operator and destructor. 3699bdd1243dSDimitry Andric CharUnits Alignment = C.getTypeAlignInChars(Ty); 3700bdd1243dSDimitry Andric llvm::Constant *Fn = getNonTrivialCStructMoveAssignmentOperator( 3701bdd1243dSDimitry Andric CGM, Alignment, Alignment, Ty.isVolatileQualified(), Ty); 37025f757f3fSDimitry Andric return Fn; 3703bdd1243dSDimitry Andric } 3704bdd1243dSDimitry Andric 37050b57cec5SDimitry Andric if (!getLangOpts().CPlusPlus || 37060b57cec5SDimitry Andric !getLangOpts().ObjCRuntime.hasAtomicCopyHelper()) 37070b57cec5SDimitry Andric return nullptr; 37080b57cec5SDimitry Andric if (!Ty->isRecordType()) 37090b57cec5SDimitry Andric return nullptr; 37100b57cec5SDimitry Andric llvm::Constant *HelperFn = nullptr; 37110b57cec5SDimitry Andric if (hasTrivialSetExpr(PID)) 37120b57cec5SDimitry Andric return nullptr; 37130b57cec5SDimitry Andric assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null"); 37140b57cec5SDimitry Andric if ((HelperFn = CGM.getAtomicSetterHelperFnMap(Ty))) 37150b57cec5SDimitry Andric return HelperFn; 37160b57cec5SDimitry Andric 3717*0fca6ea1SDimitry Andric const IdentifierInfo *II = 3718*0fca6ea1SDimitry Andric &CGM.getContext().Idents.get("__assign_helper_atomic_property_"); 37190b57cec5SDimitry Andric 37200b57cec5SDimitry Andric QualType ReturnTy = C.VoidTy; 37210b57cec5SDimitry Andric QualType DestTy = C.getPointerType(Ty); 37220b57cec5SDimitry Andric QualType SrcTy = Ty; 37230b57cec5SDimitry Andric SrcTy.addConst(); 37240b57cec5SDimitry Andric SrcTy = C.getPointerType(SrcTy); 37250b57cec5SDimitry Andric 37260b57cec5SDimitry Andric SmallVector<QualType, 2> ArgTys; 37270b57cec5SDimitry Andric ArgTys.push_back(DestTy); 37280b57cec5SDimitry Andric ArgTys.push_back(SrcTy); 37290b57cec5SDimitry Andric QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {}); 37300b57cec5SDimitry Andric 37310b57cec5SDimitry Andric FunctionDecl *FD = FunctionDecl::Create( 37320b57cec5SDimitry Andric C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, 3733349cc55cSDimitry Andric FunctionTy, nullptr, SC_Static, false, false, false); 37340b57cec5SDimitry Andric 37350b57cec5SDimitry Andric FunctionArgList args; 3736fe6060f1SDimitry Andric ParmVarDecl *Params[2]; 3737fe6060f1SDimitry Andric ParmVarDecl *DstDecl = ParmVarDecl::Create( 3738fe6060f1SDimitry Andric C, FD, SourceLocation(), SourceLocation(), nullptr, DestTy, 3739fe6060f1SDimitry Andric C.getTrivialTypeSourceInfo(DestTy, SourceLocation()), SC_None, 3740fe6060f1SDimitry Andric /*DefArg=*/nullptr); 3741fe6060f1SDimitry Andric args.push_back(Params[0] = DstDecl); 3742fe6060f1SDimitry Andric ParmVarDecl *SrcDecl = ParmVarDecl::Create( 3743fe6060f1SDimitry Andric C, FD, SourceLocation(), SourceLocation(), nullptr, SrcTy, 3744fe6060f1SDimitry Andric C.getTrivialTypeSourceInfo(SrcTy, SourceLocation()), SC_None, 3745fe6060f1SDimitry Andric /*DefArg=*/nullptr); 3746fe6060f1SDimitry Andric args.push_back(Params[1] = SrcDecl); 3747fe6060f1SDimitry Andric FD->setParams(Params); 37480b57cec5SDimitry Andric 37490b57cec5SDimitry Andric const CGFunctionInfo &FI = 37500b57cec5SDimitry Andric CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); 37510b57cec5SDimitry Andric 37520b57cec5SDimitry Andric llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); 37530b57cec5SDimitry Andric 37540b57cec5SDimitry Andric llvm::Function *Fn = 37550b57cec5SDimitry Andric llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 37560b57cec5SDimitry Andric "__assign_helper_atomic_property_", 37570b57cec5SDimitry Andric &CGM.getModule()); 37580b57cec5SDimitry Andric 37590b57cec5SDimitry Andric CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); 37600b57cec5SDimitry Andric 37610b57cec5SDimitry Andric StartFunction(FD, ReturnTy, Fn, FI, args); 37620b57cec5SDimitry Andric 3763fe6060f1SDimitry Andric DeclRefExpr DstExpr(C, DstDecl, false, DestTy, VK_PRValue, SourceLocation()); 37645ffd83dbSDimitry Andric UnaryOperator *DST = UnaryOperator::Create( 37655ffd83dbSDimitry Andric C, &DstExpr, UO_Deref, DestTy->getPointeeType(), VK_LValue, OK_Ordinary, 37665ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 37670b57cec5SDimitry Andric 3768fe6060f1SDimitry Andric DeclRefExpr SrcExpr(C, SrcDecl, false, SrcTy, VK_PRValue, SourceLocation()); 37695ffd83dbSDimitry Andric UnaryOperator *SRC = UnaryOperator::Create( 37705ffd83dbSDimitry Andric C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary, 37715ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 37720b57cec5SDimitry Andric 37735ffd83dbSDimitry Andric Expr *Args[2] = {DST, SRC}; 37740b57cec5SDimitry Andric CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment()); 37750b57cec5SDimitry Andric CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create( 37760b57cec5SDimitry Andric C, OO_Equal, CalleeExp->getCallee(), Args, DestTy->getPointeeType(), 37775ffd83dbSDimitry Andric VK_LValue, SourceLocation(), FPOptionsOverride()); 37780b57cec5SDimitry Andric 37790b57cec5SDimitry Andric EmitStmt(TheCall); 37800b57cec5SDimitry Andric 37810b57cec5SDimitry Andric FinishFunction(); 37825f757f3fSDimitry Andric HelperFn = Fn; 37830b57cec5SDimitry Andric CGM.setAtomicSetterHelperFnMap(Ty, HelperFn); 37840b57cec5SDimitry Andric return HelperFn; 37850b57cec5SDimitry Andric } 37860b57cec5SDimitry Andric 3787bdd1243dSDimitry Andric llvm::Constant *CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( 37880b57cec5SDimitry Andric const ObjCPropertyImplDecl *PID) { 3789bdd1243dSDimitry Andric const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 3790bdd1243dSDimitry Andric if ((!(PD->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic))) 3791bdd1243dSDimitry Andric return nullptr; 3792bdd1243dSDimitry Andric 3793bdd1243dSDimitry Andric QualType Ty = PD->getType(); 3794bdd1243dSDimitry Andric ASTContext &C = getContext(); 3795bdd1243dSDimitry Andric 3796bdd1243dSDimitry Andric if (Ty.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) { 3797bdd1243dSDimitry Andric CharUnits Alignment = C.getTypeAlignInChars(Ty); 3798bdd1243dSDimitry Andric llvm::Constant *Fn = getNonTrivialCStructCopyConstructor( 3799bdd1243dSDimitry Andric CGM, Alignment, Alignment, Ty.isVolatileQualified(), Ty); 38005f757f3fSDimitry Andric return Fn; 3801bdd1243dSDimitry Andric } 3802bdd1243dSDimitry Andric 38030b57cec5SDimitry Andric if (!getLangOpts().CPlusPlus || 38040b57cec5SDimitry Andric !getLangOpts().ObjCRuntime.hasAtomicCopyHelper()) 38050b57cec5SDimitry Andric return nullptr; 38060b57cec5SDimitry Andric if (!Ty->isRecordType()) 38070b57cec5SDimitry Andric return nullptr; 38080b57cec5SDimitry Andric llvm::Constant *HelperFn = nullptr; 38090b57cec5SDimitry Andric if (hasTrivialGetExpr(PID)) 38100b57cec5SDimitry Andric return nullptr; 38110b57cec5SDimitry Andric assert(PID->getGetterCXXConstructor() && "getGetterCXXConstructor - null"); 38120b57cec5SDimitry Andric if ((HelperFn = CGM.getAtomicGetterHelperFnMap(Ty))) 38130b57cec5SDimitry Andric return HelperFn; 38140b57cec5SDimitry Andric 3815*0fca6ea1SDimitry Andric const IdentifierInfo *II = 38160b57cec5SDimitry Andric &CGM.getContext().Idents.get("__copy_helper_atomic_property_"); 38170b57cec5SDimitry Andric 38180b57cec5SDimitry Andric QualType ReturnTy = C.VoidTy; 38190b57cec5SDimitry Andric QualType DestTy = C.getPointerType(Ty); 38200b57cec5SDimitry Andric QualType SrcTy = Ty; 38210b57cec5SDimitry Andric SrcTy.addConst(); 38220b57cec5SDimitry Andric SrcTy = C.getPointerType(SrcTy); 38230b57cec5SDimitry Andric 38240b57cec5SDimitry Andric SmallVector<QualType, 2> ArgTys; 38250b57cec5SDimitry Andric ArgTys.push_back(DestTy); 38260b57cec5SDimitry Andric ArgTys.push_back(SrcTy); 38270b57cec5SDimitry Andric QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {}); 38280b57cec5SDimitry Andric 38290b57cec5SDimitry Andric FunctionDecl *FD = FunctionDecl::Create( 38300b57cec5SDimitry Andric C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II, 3831349cc55cSDimitry Andric FunctionTy, nullptr, SC_Static, false, false, false); 38320b57cec5SDimitry Andric 38330b57cec5SDimitry Andric FunctionArgList args; 3834fe6060f1SDimitry Andric ParmVarDecl *Params[2]; 3835fe6060f1SDimitry Andric ParmVarDecl *DstDecl = ParmVarDecl::Create( 3836fe6060f1SDimitry Andric C, FD, SourceLocation(), SourceLocation(), nullptr, DestTy, 3837fe6060f1SDimitry Andric C.getTrivialTypeSourceInfo(DestTy, SourceLocation()), SC_None, 3838fe6060f1SDimitry Andric /*DefArg=*/nullptr); 3839fe6060f1SDimitry Andric args.push_back(Params[0] = DstDecl); 3840fe6060f1SDimitry Andric ParmVarDecl *SrcDecl = ParmVarDecl::Create( 3841fe6060f1SDimitry Andric C, FD, SourceLocation(), SourceLocation(), nullptr, SrcTy, 3842fe6060f1SDimitry Andric C.getTrivialTypeSourceInfo(SrcTy, SourceLocation()), SC_None, 3843fe6060f1SDimitry Andric /*DefArg=*/nullptr); 3844fe6060f1SDimitry Andric args.push_back(Params[1] = SrcDecl); 3845fe6060f1SDimitry Andric FD->setParams(Params); 38460b57cec5SDimitry Andric 38470b57cec5SDimitry Andric const CGFunctionInfo &FI = 38480b57cec5SDimitry Andric CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); 38490b57cec5SDimitry Andric 38500b57cec5SDimitry Andric llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); 38510b57cec5SDimitry Andric 38520b57cec5SDimitry Andric llvm::Function *Fn = llvm::Function::Create( 38530b57cec5SDimitry Andric LTy, llvm::GlobalValue::InternalLinkage, "__copy_helper_atomic_property_", 38540b57cec5SDimitry Andric &CGM.getModule()); 38550b57cec5SDimitry Andric 38560b57cec5SDimitry Andric CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); 38570b57cec5SDimitry Andric 38580b57cec5SDimitry Andric StartFunction(FD, ReturnTy, Fn, FI, args); 38590b57cec5SDimitry Andric 3860fe6060f1SDimitry Andric DeclRefExpr SrcExpr(getContext(), SrcDecl, false, SrcTy, VK_PRValue, 38610b57cec5SDimitry Andric SourceLocation()); 38620b57cec5SDimitry Andric 38635ffd83dbSDimitry Andric UnaryOperator *SRC = UnaryOperator::Create( 38645ffd83dbSDimitry Andric C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary, 38655ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 38660b57cec5SDimitry Andric 38670b57cec5SDimitry Andric CXXConstructExpr *CXXConstExpr = 38680b57cec5SDimitry Andric cast<CXXConstructExpr>(PID->getGetterCXXConstructor()); 38690b57cec5SDimitry Andric 38700b57cec5SDimitry Andric SmallVector<Expr*, 4> ConstructorArgs; 38715ffd83dbSDimitry Andric ConstructorArgs.push_back(SRC); 38720b57cec5SDimitry Andric ConstructorArgs.append(std::next(CXXConstExpr->arg_begin()), 38730b57cec5SDimitry Andric CXXConstExpr->arg_end()); 38740b57cec5SDimitry Andric 38750b57cec5SDimitry Andric CXXConstructExpr *TheCXXConstructExpr = 38760b57cec5SDimitry Andric CXXConstructExpr::Create(C, Ty, SourceLocation(), 38770b57cec5SDimitry Andric CXXConstExpr->getConstructor(), 38780b57cec5SDimitry Andric CXXConstExpr->isElidable(), 38790b57cec5SDimitry Andric ConstructorArgs, 38800b57cec5SDimitry Andric CXXConstExpr->hadMultipleCandidates(), 38810b57cec5SDimitry Andric CXXConstExpr->isListInitialization(), 38820b57cec5SDimitry Andric CXXConstExpr->isStdInitListInitialization(), 38830b57cec5SDimitry Andric CXXConstExpr->requiresZeroInitialization(), 38840b57cec5SDimitry Andric CXXConstExpr->getConstructionKind(), 38850b57cec5SDimitry Andric SourceRange()); 38860b57cec5SDimitry Andric 3887fe6060f1SDimitry Andric DeclRefExpr DstExpr(getContext(), DstDecl, false, DestTy, VK_PRValue, 38880b57cec5SDimitry Andric SourceLocation()); 38890b57cec5SDimitry Andric 38900b57cec5SDimitry Andric RValue DV = EmitAnyExpr(&DstExpr); 389181ad6265SDimitry Andric CharUnits Alignment = 389281ad6265SDimitry Andric getContext().getTypeAlignInChars(TheCXXConstructExpr->getType()); 38930b57cec5SDimitry Andric EmitAggExpr(TheCXXConstructExpr, 389481ad6265SDimitry Andric AggValueSlot::forAddr( 389581ad6265SDimitry Andric Address(DV.getScalarVal(), ConvertTypeForMem(Ty), Alignment), 389681ad6265SDimitry Andric Qualifiers(), AggValueSlot::IsDestructed, 38970b57cec5SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers, 389881ad6265SDimitry Andric AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap)); 38990b57cec5SDimitry Andric 39000b57cec5SDimitry Andric FinishFunction(); 39015f757f3fSDimitry Andric HelperFn = Fn; 39020b57cec5SDimitry Andric CGM.setAtomicGetterHelperFnMap(Ty, HelperFn); 39030b57cec5SDimitry Andric return HelperFn; 39040b57cec5SDimitry Andric } 39050b57cec5SDimitry Andric 39060b57cec5SDimitry Andric llvm::Value * 39070b57cec5SDimitry Andric CodeGenFunction::EmitBlockCopyAndAutorelease(llvm::Value *Block, QualType Ty) { 39080b57cec5SDimitry Andric // Get selectors for retain/autorelease. 3909*0fca6ea1SDimitry Andric const IdentifierInfo *CopyID = &getContext().Idents.get("copy"); 39100b57cec5SDimitry Andric Selector CopySelector = 39110b57cec5SDimitry Andric getContext().Selectors.getNullarySelector(CopyID); 3912*0fca6ea1SDimitry Andric const IdentifierInfo *AutoreleaseID = &getContext().Idents.get("autorelease"); 39130b57cec5SDimitry Andric Selector AutoreleaseSelector = 39140b57cec5SDimitry Andric getContext().Selectors.getNullarySelector(AutoreleaseID); 39150b57cec5SDimitry Andric 39160b57cec5SDimitry Andric // Emit calls to retain/autorelease. 39170b57cec5SDimitry Andric CGObjCRuntime &Runtime = CGM.getObjCRuntime(); 39180b57cec5SDimitry Andric llvm::Value *Val = Block; 39190b57cec5SDimitry Andric RValue Result; 39200b57cec5SDimitry Andric Result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(), 39210b57cec5SDimitry Andric Ty, CopySelector, 39220b57cec5SDimitry Andric Val, CallArgList(), nullptr, nullptr); 39230b57cec5SDimitry Andric Val = Result.getScalarVal(); 39240b57cec5SDimitry Andric Result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(), 39250b57cec5SDimitry Andric Ty, AutoreleaseSelector, 39260b57cec5SDimitry Andric Val, CallArgList(), nullptr, nullptr); 39270b57cec5SDimitry Andric Val = Result.getScalarVal(); 39280b57cec5SDimitry Andric return Val; 39290b57cec5SDimitry Andric } 39300b57cec5SDimitry Andric 3931e8d8bef9SDimitry Andric static unsigned getBaseMachOPlatformID(const llvm::Triple &TT) { 3932e8d8bef9SDimitry Andric switch (TT.getOS()) { 3933e8d8bef9SDimitry Andric case llvm::Triple::Darwin: 3934e8d8bef9SDimitry Andric case llvm::Triple::MacOSX: 3935e8d8bef9SDimitry Andric return llvm::MachO::PLATFORM_MACOS; 3936e8d8bef9SDimitry Andric case llvm::Triple::IOS: 3937e8d8bef9SDimitry Andric return llvm::MachO::PLATFORM_IOS; 3938e8d8bef9SDimitry Andric case llvm::Triple::TvOS: 3939e8d8bef9SDimitry Andric return llvm::MachO::PLATFORM_TVOS; 3940e8d8bef9SDimitry Andric case llvm::Triple::WatchOS: 3941e8d8bef9SDimitry Andric return llvm::MachO::PLATFORM_WATCHOS; 39427a6dacacSDimitry Andric case llvm::Triple::XROS: 39437a6dacacSDimitry Andric return llvm::MachO::PLATFORM_XROS; 394481ad6265SDimitry Andric case llvm::Triple::DriverKit: 394581ad6265SDimitry Andric return llvm::MachO::PLATFORM_DRIVERKIT; 3946e8d8bef9SDimitry Andric default: 39475f757f3fSDimitry Andric return llvm::MachO::PLATFORM_UNKNOWN; 3948e8d8bef9SDimitry Andric } 3949e8d8bef9SDimitry Andric } 3950e8d8bef9SDimitry Andric 3951e8d8bef9SDimitry Andric static llvm::Value *emitIsPlatformVersionAtLeast(CodeGenFunction &CGF, 3952e8d8bef9SDimitry Andric const VersionTuple &Version) { 3953e8d8bef9SDimitry Andric CodeGenModule &CGM = CGF.CGM; 3954e8d8bef9SDimitry Andric // Note: we intend to support multi-platform version checks, so reserve 3955e8d8bef9SDimitry Andric // the room for a dual platform checking invocation that will be 3956e8d8bef9SDimitry Andric // implemented in the future. 3957e8d8bef9SDimitry Andric llvm::SmallVector<llvm::Value *, 8> Args; 3958e8d8bef9SDimitry Andric 3959e8d8bef9SDimitry Andric auto EmitArgs = [&](const VersionTuple &Version, const llvm::Triple &TT) { 3960bdd1243dSDimitry Andric std::optional<unsigned> Min = Version.getMinor(), 3961bdd1243dSDimitry Andric SMin = Version.getSubminor(); 3962e8d8bef9SDimitry Andric Args.push_back( 3963e8d8bef9SDimitry Andric llvm::ConstantInt::get(CGM.Int32Ty, getBaseMachOPlatformID(TT))); 3964e8d8bef9SDimitry Andric Args.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Version.getMajor())); 396581ad6265SDimitry Andric Args.push_back(llvm::ConstantInt::get(CGM.Int32Ty, Min.value_or(0))); 396681ad6265SDimitry Andric Args.push_back(llvm::ConstantInt::get(CGM.Int32Ty, SMin.value_or(0))); 3967e8d8bef9SDimitry Andric }; 3968e8d8bef9SDimitry Andric 3969e8d8bef9SDimitry Andric assert(!Version.empty() && "unexpected empty version"); 3970e8d8bef9SDimitry Andric EmitArgs(Version, CGM.getTarget().getTriple()); 3971e8d8bef9SDimitry Andric 3972e8d8bef9SDimitry Andric if (!CGM.IsPlatformVersionAtLeastFn) { 3973e8d8bef9SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get( 3974e8d8bef9SDimitry Andric CGM.Int32Ty, {CGM.Int32Ty, CGM.Int32Ty, CGM.Int32Ty, CGM.Int32Ty}, 3975e8d8bef9SDimitry Andric false); 3976e8d8bef9SDimitry Andric CGM.IsPlatformVersionAtLeastFn = 3977e8d8bef9SDimitry Andric CGM.CreateRuntimeFunction(FTy, "__isPlatformVersionAtLeast"); 3978e8d8bef9SDimitry Andric } 3979e8d8bef9SDimitry Andric 3980e8d8bef9SDimitry Andric llvm::Value *Check = 3981e8d8bef9SDimitry Andric CGF.EmitNounwindRuntimeCall(CGM.IsPlatformVersionAtLeastFn, Args); 3982e8d8bef9SDimitry Andric return CGF.Builder.CreateICmpNE(Check, 3983e8d8bef9SDimitry Andric llvm::Constant::getNullValue(CGM.Int32Ty)); 3984e8d8bef9SDimitry Andric } 3985e8d8bef9SDimitry Andric 39860b57cec5SDimitry Andric llvm::Value * 3987e8d8bef9SDimitry Andric CodeGenFunction::EmitBuiltinAvailable(const VersionTuple &Version) { 3988e8d8bef9SDimitry Andric // Darwin uses the new __isPlatformVersionAtLeast family of routines. 3989e8d8bef9SDimitry Andric if (CGM.getTarget().getTriple().isOSDarwin()) 3990e8d8bef9SDimitry Andric return emitIsPlatformVersionAtLeast(*this, Version); 39910b57cec5SDimitry Andric 39920b57cec5SDimitry Andric if (!CGM.IsOSVersionAtLeastFn) { 39930b57cec5SDimitry Andric llvm::FunctionType *FTy = 39940b57cec5SDimitry Andric llvm::FunctionType::get(Int32Ty, {Int32Ty, Int32Ty, Int32Ty}, false); 39950b57cec5SDimitry Andric CGM.IsOSVersionAtLeastFn = 39960b57cec5SDimitry Andric CGM.CreateRuntimeFunction(FTy, "__isOSVersionAtLeast"); 39970b57cec5SDimitry Andric } 39980b57cec5SDimitry Andric 3999bdd1243dSDimitry Andric std::optional<unsigned> Min = Version.getMinor(), 4000bdd1243dSDimitry Andric SMin = Version.getSubminor(); 4001e8d8bef9SDimitry Andric llvm::Value *Args[] = { 4002e8d8bef9SDimitry Andric llvm::ConstantInt::get(CGM.Int32Ty, Version.getMajor()), 400381ad6265SDimitry Andric llvm::ConstantInt::get(CGM.Int32Ty, Min.value_or(0)), 400481ad6265SDimitry Andric llvm::ConstantInt::get(CGM.Int32Ty, SMin.value_or(0))}; 4005e8d8bef9SDimitry Andric 40060b57cec5SDimitry Andric llvm::Value *CallRes = 40070b57cec5SDimitry Andric EmitNounwindRuntimeCall(CGM.IsOSVersionAtLeastFn, Args); 40080b57cec5SDimitry Andric 40090b57cec5SDimitry Andric return Builder.CreateICmpNE(CallRes, llvm::Constant::getNullValue(Int32Ty)); 40100b57cec5SDimitry Andric } 40110b57cec5SDimitry Andric 4012e8d8bef9SDimitry Andric static bool isFoundationNeededForDarwinAvailabilityCheck( 4013e8d8bef9SDimitry Andric const llvm::Triple &TT, const VersionTuple &TargetVersion) { 4014e8d8bef9SDimitry Andric VersionTuple FoundationDroppedInVersion; 4015e8d8bef9SDimitry Andric switch (TT.getOS()) { 4016e8d8bef9SDimitry Andric case llvm::Triple::IOS: 4017e8d8bef9SDimitry Andric case llvm::Triple::TvOS: 4018e8d8bef9SDimitry Andric FoundationDroppedInVersion = VersionTuple(/*Major=*/13); 4019e8d8bef9SDimitry Andric break; 4020e8d8bef9SDimitry Andric case llvm::Triple::WatchOS: 4021e8d8bef9SDimitry Andric FoundationDroppedInVersion = VersionTuple(/*Major=*/6); 4022e8d8bef9SDimitry Andric break; 4023e8d8bef9SDimitry Andric case llvm::Triple::Darwin: 4024e8d8bef9SDimitry Andric case llvm::Triple::MacOSX: 4025e8d8bef9SDimitry Andric FoundationDroppedInVersion = VersionTuple(/*Major=*/10, /*Minor=*/15); 4026e8d8bef9SDimitry Andric break; 40277a6dacacSDimitry Andric case llvm::Triple::XROS: 40287a6dacacSDimitry Andric // XROS doesn't need Foundation. 40297a6dacacSDimitry Andric return false; 403081ad6265SDimitry Andric case llvm::Triple::DriverKit: 403181ad6265SDimitry Andric // DriverKit doesn't need Foundation. 403281ad6265SDimitry Andric return false; 4033e8d8bef9SDimitry Andric default: 4034e8d8bef9SDimitry Andric llvm_unreachable("Unexpected OS"); 4035e8d8bef9SDimitry Andric } 4036e8d8bef9SDimitry Andric return TargetVersion < FoundationDroppedInVersion; 4037e8d8bef9SDimitry Andric } 4038e8d8bef9SDimitry Andric 40390b57cec5SDimitry Andric void CodeGenModule::emitAtAvailableLinkGuard() { 4040e8d8bef9SDimitry Andric if (!IsPlatformVersionAtLeastFn) 40410b57cec5SDimitry Andric return; 40420b57cec5SDimitry Andric // @available requires CoreFoundation only on Darwin. 40430b57cec5SDimitry Andric if (!Target.getTriple().isOSDarwin()) 40440b57cec5SDimitry Andric return; 4045e8d8bef9SDimitry Andric // @available doesn't need Foundation on macOS 10.15+, iOS/tvOS 13+, or 4046e8d8bef9SDimitry Andric // watchOS 6+. 4047e8d8bef9SDimitry Andric if (!isFoundationNeededForDarwinAvailabilityCheck( 4048e8d8bef9SDimitry Andric Target.getTriple(), Target.getPlatformMinVersion())) 4049e8d8bef9SDimitry Andric return; 40500b57cec5SDimitry Andric // Add -framework CoreFoundation to the linker commands. We still want to 40510b57cec5SDimitry Andric // emit the core foundation reference down below because otherwise if 40520b57cec5SDimitry Andric // CoreFoundation is not used in the code, the linker won't link the 40530b57cec5SDimitry Andric // framework. 40540b57cec5SDimitry Andric auto &Context = getLLVMContext(); 40550b57cec5SDimitry Andric llvm::Metadata *Args[2] = {llvm::MDString::get(Context, "-framework"), 40560b57cec5SDimitry Andric llvm::MDString::get(Context, "CoreFoundation")}; 40570b57cec5SDimitry Andric LinkerOptionsMetadata.push_back(llvm::MDNode::get(Context, Args)); 40580b57cec5SDimitry Andric // Emit a reference to a symbol from CoreFoundation to ensure that 40590b57cec5SDimitry Andric // CoreFoundation is linked into the final binary. 40600b57cec5SDimitry Andric llvm::FunctionType *FTy = 40610b57cec5SDimitry Andric llvm::FunctionType::get(Int32Ty, {VoidPtrTy}, false); 40620b57cec5SDimitry Andric llvm::FunctionCallee CFFunc = 40630b57cec5SDimitry Andric CreateRuntimeFunction(FTy, "CFBundleGetVersionNumber"); 40640b57cec5SDimitry Andric 40650b57cec5SDimitry Andric llvm::FunctionType *CheckFTy = llvm::FunctionType::get(VoidTy, {}, false); 40660b57cec5SDimitry Andric llvm::FunctionCallee CFLinkCheckFuncRef = CreateRuntimeFunction( 40670b57cec5SDimitry Andric CheckFTy, "__clang_at_available_requires_core_foundation_framework", 40680b57cec5SDimitry Andric llvm::AttributeList(), /*Local=*/true); 40690b57cec5SDimitry Andric llvm::Function *CFLinkCheckFunc = 40700b57cec5SDimitry Andric cast<llvm::Function>(CFLinkCheckFuncRef.getCallee()->stripPointerCasts()); 40710b57cec5SDimitry Andric if (CFLinkCheckFunc->empty()) { 40720b57cec5SDimitry Andric CFLinkCheckFunc->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage); 40730b57cec5SDimitry Andric CFLinkCheckFunc->setVisibility(llvm::GlobalValue::HiddenVisibility); 40740b57cec5SDimitry Andric CodeGenFunction CGF(*this); 40750b57cec5SDimitry Andric CGF.Builder.SetInsertPoint(CGF.createBasicBlock("", CFLinkCheckFunc)); 40760b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(CFFunc, 40770b57cec5SDimitry Andric llvm::Constant::getNullValue(VoidPtrTy)); 40780b57cec5SDimitry Andric CGF.Builder.CreateUnreachable(); 40790b57cec5SDimitry Andric addCompilerUsedGlobal(CFLinkCheckFunc); 40800b57cec5SDimitry Andric } 40810b57cec5SDimitry Andric } 40820b57cec5SDimitry Andric 40830b57cec5SDimitry Andric CGObjCRuntime::~CGObjCRuntime() {} 4084