From: Fariborz Jahanian Date: Wed, 19 Nov 2008 00:59:10 +0000 (+0000) Subject: Generate strong write barriers for __strong objects. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58626500527695865683d1d65053743de8770b60;p=clang Generate strong write barriers for __strong objects. Also, took care of Daniel's commments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59575 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 98a54c6863..95733abbab 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -151,7 +151,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { /// this method emits the address of the lvalue, then loads the result as an /// rvalue, returning the rvalue. RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { - if (LV.isObjcWeak()) { + if (LV.ObjcWeak()) { // load of a __weak object. llvm::Value *AddrWeakObj = LV.getAddress(); llvm::Value *read_weak = CGM.getObjCRuntime().EmitObjCWeakRead(*this, @@ -335,7 +335,7 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV, /// is 'Ty'. void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, QualType Ty) { - if (Dst.isObjcWeak()) { + if (Dst.ObjcWeak()) { // load of a __weak object. llvm::Value *LvalueDst = Dst.getAddress(); llvm::Value *src = Src.getScalarVal(); @@ -343,6 +343,14 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, return; } + if (Dst.ObjcStrong()) { + // load of a __strong object. + llvm::Value *LvalueDst = Dst.getAddress(); + llvm::Value *src = Src.getScalarVal(); + CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst); + return; + } + if (!Dst.isSimple()) { if (Dst.isVectorElt()) { // Read/modify/write the vector, inserting the new element. @@ -510,10 +518,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { } else if (VD && VD->isFileVarDecl()) { LValue LV = LValue::MakeAddr(CGM.GetAddrOfGlobalVar(VD), E->getType().getCVRQualifiers()); - if (VD->getAttr()) - { - ObjCGCAttr::GCAttrTypes attrType = (VD->getAttr())->getType(); - LValue::SetObjCGCAttrs(attrType == ObjCGCAttr::Weak, attrType == ObjCGCAttr::Strong, LV); + if (const ObjCGCAttr *A = VD->getAttr()) { + ObjCGCAttr::GCAttrTypes attrType = A->getType(); + LValue::SetObjCType(attrType == ObjCGCAttr::Weak, attrType == ObjCGCAttr::Strong, LV); } return LV; } else if (const FunctionDecl *FD = dyn_cast(E->getDecl())) { diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 91b8587e1a..7adbd4a8e7 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -134,6 +134,10 @@ public: llvm::Value *AddrWeakObj); virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst); + virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dest); + virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dest); }; } // end anonymous namespace @@ -984,6 +988,18 @@ void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, return; } +void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dst) +{ + return; +} + +void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dst) +{ + return; +} + CodeGen::CGObjCRuntime *CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM){ return new CGObjCGNU(CGM); } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index e6c2650a2e..ccfd465c35 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -458,6 +458,10 @@ public: llvm::Value *AddrWeakObj); virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst); + virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dest); + virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dest); }; } // end anonymous namespace @@ -1800,6 +1804,28 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, return; } +/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. +/// objc_assign_global (id src, id *dst) +/// +void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dst) +{ + CGF.Builder.CreateCall2(ObjCTypes.GcAssignGlobalFn, + src, dst, "globalassign"); + return; +} + +/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. +/// objc_assign_strongCast (id src, id *dst) +/// +void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dst) +{ + CGF.Builder.CreateCall2(ObjCTypes.GcAssignStrongCastFn, + src, dst, "weakassign"); + return; +} + /// EmitSynchronizedStmt - Code gen for @synchronized(expr) stmt; /// Effectively generating code for: /// objc_sync_enter(expr); diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 24288b1e44..675ff340b6 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -149,6 +149,10 @@ public: llvm::Value *AddrWeakObj) = 0; virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest) = 0; + virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dest) = 0; + virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dest) = 0; }; /// Creates an instance of an Objective-C runtime class. diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index ef2cb033c9..c328e35931 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -106,6 +106,12 @@ class LValue { PropertyRef // This is an Objective-C property reference, use // getPropertyRefExpr } LVType; + + enum ObjCType { + None = 0, // object with no gc attribute. + Weak, // __weak object expression + Strong // __strong object expression + }; llvm::Value *V; @@ -130,9 +136,9 @@ class LValue { bool Volatile:1; // FIXME: set but never used, what effect should it have? bool Restrict:1; - - bool ObjcWeak:1; - bool ObjcStrong:1; + + // objective-c's gc attributes + unsigned ObjCType : 2; private: static void SetQualifiers(unsigned Qualifiers, LValue& R) { @@ -140,8 +146,7 @@ private: R.Restrict = (Qualifiers&QualType::Restrict)!=0; // FIXME: Convenient place to set objc flags to 0. This // should really be done in a user-defined constructor instead. - R.ObjcWeak = 0; - R.ObjcStrong = 0; + R.ObjCType = None; } public: @@ -154,12 +159,14 @@ public: bool isVolatileQualified() const { return Volatile; } bool isRestrictQualified() const { return Restrict; } - bool isObjcWeak() const { return ObjcWeak; } - bool isObjcStrong() const { return ObjcStrong; } + bool ObjcWeak() const { return ObjCType == Weak; } + bool ObjcStrong() const { return ObjCType == Strong; } - static void SetObjCGCAttrs(unsigned Weak, unsigned Strong, LValue& R) { - R.ObjcWeak = Weak; - R.ObjcStrong = Strong; + static void SetObjCType(unsigned WeakVal, unsigned StrongVal, LValue& R) { + if (WeakVal) + R.ObjCType = Weak; + else if (StrongVal) + R.ObjCType = Strong; } // simple lvalue