diff options
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 216 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCGNU.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 53 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCRuntime.h | 6 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 5 |
6 files changed, 279 insertions, 20 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index f7ab880e6cd..d5ef402d229 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -177,6 +177,9 @@ public: Value *VisitCharacterLiteral(const CharacterLiteral *E) { return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); } + Value *VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) { + return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); + } Value *VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); } @@ -519,6 +522,15 @@ public: Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) { return CGF.EmitObjCStringLiteral(E); } + Value *VisitObjCNumericLiteral(ObjCNumericLiteral *E) { + return CGF.EmitObjCNumericLiteral(E); + } + Value *VisitObjCArrayLiteral(ObjCArrayLiteral *E) { + return CGF.EmitObjCArrayLiteral(E); + } + Value *VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + return CGF.EmitObjCDictionaryLiteral(E); + } Value *VisitAsTypeExpr(AsTypeExpr *CE); Value *VisitAtomicExpr(AtomicExpr *AE); }; diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 6d95f17226e..6ece9e82b34 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -29,6 +29,10 @@ using namespace CodeGen; typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult; static TryEmitResult tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e); +static RValue AdjustRelatedResultType(CodeGenFunction &CGF, + const Expr *E, + const ObjCMethodDecl *Method, + RValue Result); /// Given the address of a variable of pointer type, find the correct /// null to store into it. @@ -47,6 +51,138 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); } +/// EmitObjCNumericLiteral - This routine generates code for +/// the appropriate +[NSNumber numberWith<Type>:] method. +/// +llvm::Value *CodeGenFunction::EmitObjCNumericLiteral(const ObjCNumericLiteral *E) { + // Generate the correct selector for this literal's concrete type. + const Expr *NL = E->getNumber(); + // Get the method. + const ObjCMethodDecl *Method = E->getObjCNumericLiteralMethod(); + assert(Method && "NSNumber method is null"); + Selector Sel = Method->getSelector(); + + // Generate a reference to the class pointer, which will be the receiver. + QualType ResultType = E->getType(); // should be NSNumber * + const ObjCObjectPointerType *InterfacePointerType = + ResultType->getAsObjCInterfacePointerType(); + ObjCInterfaceDecl *NSNumberDecl = + InterfacePointerType->getObjectType()->getInterface(); + CGObjCRuntime &Runtime = CGM.getObjCRuntime(); + llvm::Value *Receiver = Runtime.GetClass(Builder, NSNumberDecl); + + const ParmVarDecl *argDecl = *Method->param_begin(); + QualType ArgQT = argDecl->getType().getUnqualifiedType(); + RValue RV = EmitAnyExpr(NL); + CallArgList Args; + Args.add(RV, ArgQT); + + RValue result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(), + ResultType, Sel, Receiver, Args, + NSNumberDecl, Method); + return Builder.CreateBitCast(result.getScalarVal(), + ConvertType(E->getType())); +} + +llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, + const ObjCMethodDecl *MethodWithObjects) { + ASTContext &Context = CGM.getContext(); + const ObjCDictionaryLiteral *DLE = 0; + const ObjCArrayLiteral *ALE = dyn_cast<ObjCArrayLiteral>(E); + if (!ALE) + DLE = cast<ObjCDictionaryLiteral>(E); + + // Compute the type of the array we're initializing. + uint64_t NumElements = + ALE ? ALE->getNumElements() : DLE->getNumElements(); + llvm::APInt APNumElements(Context.getTypeSize(Context.getSizeType()), + NumElements); + QualType ElementType = Context.getObjCIdType().withConst(); + QualType ElementArrayType + = Context.getConstantArrayType(ElementType, APNumElements, + ArrayType::Normal, /*IndexTypeQuals=*/0); + + // Allocate the temporary array(s). + llvm::Value *Objects = CreateMemTemp(ElementArrayType, "objects"); + llvm::Value *Keys = 0; + if (DLE) + Keys = CreateMemTemp(ElementArrayType, "keys"); + + // Perform the actual initialialization of the array(s). + for (uint64_t i = 0; i < NumElements; i++) { + if (ALE) { + // Emit the initializer. + const Expr *Rhs = ALE->getElement(i); + LValue LV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i), + ElementType, + Context.getTypeAlignInChars(Rhs->getType()), + Context); + EmitScalarInit(Rhs, /*D=*/0, LV, /*capturedByInit=*/false); + } else { + // Emit the key initializer. + const Expr *Key = DLE->getKeyValueElement(i).Key; + LValue KeyLV = LValue::MakeAddr(Builder.CreateStructGEP(Keys, i), + ElementType, + Context.getTypeAlignInChars(Key->getType()), + Context); + EmitScalarInit(Key, /*D=*/0, KeyLV, /*capturedByInit=*/false); + + // Emit the value initializer. + const Expr *Value = DLE->getKeyValueElement(i).Value; + LValue ValueLV = LValue::MakeAddr(Builder.CreateStructGEP(Objects, i), + ElementType, + Context.getTypeAlignInChars(Value->getType()), + Context); + EmitScalarInit(Value, /*D=*/0, ValueLV, /*capturedByInit=*/false); + } + } + + // Generate the argument list. + CallArgList Args; + ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin(); + const ParmVarDecl *argDecl = *PI++; + QualType ArgQT = argDecl->getType().getUnqualifiedType(); + Args.add(RValue::get(Objects), ArgQT); + if (DLE) { + argDecl = *PI++; + ArgQT = argDecl->getType().getUnqualifiedType(); + Args.add(RValue::get(Keys), ArgQT); + } + argDecl = *PI; + ArgQT = argDecl->getType().getUnqualifiedType(); + llvm::Value *Count = + llvm::ConstantInt::get(CGM.getTypes().ConvertType(ArgQT), NumElements); + Args.add(RValue::get(Count), ArgQT); + + // Generate a reference to the class pointer, which will be the receiver. + Selector Sel = MethodWithObjects->getSelector(); + QualType ResultType = E->getType(); + const ObjCObjectPointerType *InterfacePointerType + = ResultType->getAsObjCInterfacePointerType(); + ObjCInterfaceDecl *Class + = InterfacePointerType->getObjectType()->getInterface(); + CGObjCRuntime &Runtime = CGM.getObjCRuntime(); + llvm::Value *Receiver = Runtime.GetClass(Builder, Class); + + // Generate the message send. + RValue result = Runtime.GenerateMessageSend(*this, ReturnValueSlot(), + MethodWithObjects->getResultType(), + Sel, + Receiver, Args, Class, + MethodWithObjects); + return Builder.CreateBitCast(result.getScalarVal(), + ConvertType(E->getType())); +} + +llvm::Value *CodeGenFunction::EmitObjCArrayLiteral(const ObjCArrayLiteral *E) { + return EmitObjCCollectionLiteral(E, E->getArrayWithObjectsMethod()); +} + +llvm::Value *CodeGenFunction::EmitObjCDictionaryLiteral( + const ObjCDictionaryLiteral *E) { + return EmitObjCCollectionLiteral(E, E->getDictWithObjectsMethod()); +} + /// Emit a selector. llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) { // Untyped selector. @@ -884,6 +1020,26 @@ static bool hasTrivialSetExpr(const ObjCPropertyImplDecl *PID) { return false; } +bool UseOptimizedSetter(CodeGenModule &CGM) { + if (CGM.getLangOptions().getGC() != LangOptions::NonGC) + return false; + const TargetInfo &Target = CGM.getContext().getTargetInfo(); + StringRef TargetPlatform = Target.getPlatformName(); + if (TargetPlatform.empty()) + return false; + VersionTuple TargetMinVersion = Target.getPlatformMinVersion(); + + if (TargetPlatform.compare("macosx") || + TargetMinVersion.getMajor() <= 9) + return false; + + unsigned minor = 0; + if (llvm::Optional<unsigned> Minor = TargetMinVersion.getMinor()) + minor = *Minor; + + return (minor >= 8); +} + void CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, const ObjCPropertyImplDecl *propImpl, @@ -937,13 +1093,27 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, case PropertyImplStrategy::GetSetProperty: case PropertyImplStrategy::SetPropertyAndExpressionGet: { - llvm::Value *setPropertyFn = - CGM.getObjCRuntime().GetPropertySetFunction(); - if (!setPropertyFn) { - CGM.ErrorUnsupported(propImpl, "Obj-C setter requiring atomic copy"); - return; + + llvm::Value *setOptimizedPropertyFn = 0; + llvm::Value *setPropertyFn = 0; + if (UseOptimizedSetter(CGM)) { + // 10.8 code and GC is off + setOptimizedPropertyFn = + CGM.getObjCRuntime().GetOptimizedPropertySetFunction(strategy.isAtomic(), + strategy.isCopy()); + if (!setOptimizedPropertyFn) { + CGM.ErrorUnsupported(propImpl, "Obj-C optimized setter - NYI"); + return; + } } - + else { + setPropertyFn = CGM.getObjCRuntime().GetPropertySetFunction(); + if (!setPropertyFn) { + CGM.ErrorUnsupported(propImpl, "Obj-C setter requiring atomic copy"); + return; + } + } + // Emit objc_setProperty((id) self, _cmd, offset, arg, // <is-atomic>, <is-copy>). llvm::Value *cmd = @@ -958,18 +1128,28 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, CallArgList args; args.add(RValue::get(self), getContext().getObjCIdType()); args.add(RValue::get(cmd), getContext().getObjCSelType()); - args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); - args.add(RValue::get(arg), getContext().getObjCIdType()); - args.add(RValue::get(Builder.getInt1(strategy.isAtomic())), - getContext().BoolTy); - args.add(RValue::get(Builder.getInt1(strategy.isCopy())), - getContext().BoolTy); - // FIXME: We shouldn't need to get the function info here, the runtime - // already should have computed it to build the function. - EmitCall(getTypes().arrangeFunctionCall(getContext().VoidTy, args, - FunctionType::ExtInfo(), - RequiredArgs::All), - setPropertyFn, ReturnValueSlot(), args); + if (setOptimizedPropertyFn) { + args.add(RValue::get(arg), getContext().getObjCIdType()); + args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); + EmitCall(getTypes().arrangeFunctionCall(getContext().VoidTy, args, + FunctionType::ExtInfo(), + RequiredArgs::All), + setOptimizedPropertyFn, ReturnValueSlot(), args); + } else { + args.add(RValue::get(ivarOffset), getContext().getPointerDiffType()); + args.add(RValue::get(arg), getContext().getObjCIdType()); + args.add(RValue::get(Builder.getInt1(strategy.isAtomic())), + getContext().BoolTy); + args.add(RValue::get(Builder.getInt1(strategy.isCopy())), + getContext().BoolTy); + // FIXME: We shouldn't need to get the function info here, the runtime + // already should have computed it to build the function. + EmitCall(getTypes().arrangeFunctionCall(getContext().VoidTy, args, + FunctionType::ExtInfo(), + RequiredArgs::All), + setPropertyFn, ReturnValueSlot(), args); + } + return; } diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 299f44c3ef3..16812e29577 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -472,6 +472,8 @@ public: virtual llvm::Function *ModuleInitFunction(); virtual llvm::Constant *GetPropertyGetFunction(); virtual llvm::Constant *GetPropertySetFunction(); + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, + bool copy); virtual llvm::Constant *GetSetStructFunction(); virtual llvm::Constant *GetCppAtomicObjectFunction(); virtual llvm::Constant *GetGetStructFunction(); @@ -2427,6 +2429,11 @@ llvm::Constant *CGObjCGNU::GetPropertySetFunction() { return SetPropertyFn; } +llvm::Constant *CGObjCGNU::GetOptimizedPropertySetFunction(bool atomic, + bool copy) { + return 0; +} + llvm::Constant *CGObjCGNU::GetGetStructFunction() { return GetStructPropertyFn; } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index f0682f2de9d..a408681aadc 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -267,6 +267,41 @@ public: return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); } + llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) { + CodeGen::CodeGenTypes &Types = CGM.getTypes(); + ASTContext &Ctx = CGM.getContext(); + // void objc_setProperty_atomic(id self, SEL _cmd, + // id newValue, ptrdiff_t offset); + // void objc_setProperty_nonatomic(id self, SEL _cmd, + // id newValue, ptrdiff_t offset); + // void objc_setProperty_atomic_copy(id self, SEL _cmd, + // id newValue, ptrdiff_t offset); + // void objc_setProperty_nonatomic_copy(id self, SEL _cmd, + // id newValue, ptrdiff_t offset); + + SmallVector<CanQualType,4> Params; + CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); + CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); + Params.push_back(IdType); + Params.push_back(SelType); + Params.push_back(IdType); + Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); + llvm::FunctionType *FTy = + Types.GetFunctionType(Types.arrangeFunctionType(Ctx.VoidTy, Params, + FunctionType::ExtInfo(), + RequiredArgs::All)); + const char *name; + if (atomic && copy) + name = "objc_setProperty_atomic_copy"; + else if (atomic && !copy) + name = "objc_setProperty_atomic"; + else if (!atomic && copy) + name = "objc_setProperty_nonatomic_copy"; + else + name = "objc_setProperty_nonatomic"; + + return CGM.CreateRuntimeFunction(FTy, name); + } llvm::Constant *getCopyStructFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); @@ -906,7 +941,7 @@ public: CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { } virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL); - + virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD=0); @@ -1087,6 +1122,8 @@ public: virtual llvm::Constant *GetPropertyGetFunction(); virtual llvm::Constant *GetPropertySetFunction(); + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, + bool copy); virtual llvm::Constant *GetGetStructFunction(); virtual llvm::Constant *GetSetStructFunction(); virtual llvm::Constant *GetCppAtomicObjectFunction(); @@ -1349,6 +1386,11 @@ public: return ObjCTypes.getSetPropertyFn(); } + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, + bool copy) { + return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); + } + virtual llvm::Constant *GetSetStructFunction() { return ObjCTypes.getCopyStructFn(); } @@ -1578,6 +1620,10 @@ llvm::Constant *CGObjCCommonMac::GenerateConstantString( CGM.GetAddrOfConstantString(SL)); } +enum { + kCFTaggedObjectID_Integer = (1 << 1) + 1 +}; + /// Generates a message send where the super is the receiver. This is /// a message send to self with special delivery semantics indicating /// which class's method should be called. @@ -2723,6 +2769,11 @@ llvm::Constant *CGObjCMac::GetPropertySetFunction() { return ObjCTypes.getSetPropertyFn(); } +llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic, + bool copy) { + return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); +} + llvm::Constant *CGObjCMac::GetGetStructFunction() { return ObjCTypes.getCopyStructFn(); } diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index 0f3cb549ec7..ccf4d4dfca5 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -135,7 +135,7 @@ public: /// Generate a constant string object. virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0; - + /// Generate a category. A category contains a list of methods (and /// accompanying metadata) and a list of protocols. virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0; @@ -202,6 +202,10 @@ public: /// Return the runtime function for setting properties. virtual llvm::Constant *GetPropertySetFunction() = 0; + /// Return the runtime function for optimized setting properties. + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, + bool copy) = 0; + // API for atomic copying of qualified aggregates in getter. virtual llvm::Constant *GetGetStructFunction() = 0; // API for atomic copying of qualified aggregates in setter. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index d2eaa682981..833eee2da4f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2238,6 +2238,11 @@ public: llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E); llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E); + llvm::Value *EmitObjCNumericLiteral(const ObjCNumericLiteral *E); + llvm::Value *EmitObjCArrayLiteral(const ObjCArrayLiteral *E); + llvm::Value *EmitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E); + llvm::Value *EmitObjCCollectionLiteral(const Expr *E, + const ObjCMethodDecl *MethodWithObjects); llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E); RValue EmitObjCMessageExpr(const ObjCMessageExpr *E, ReturnValueSlot Return = ReturnValueSlot()); |

