From: Fariborz Jahanian Date: Tue, 20 Jul 2010 20:30:03 +0000 (+0000) Subject: Adopt objc_assign_threadlocal() for __thread variables of GC types. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=021a7a63984f0f912dc9e9dae2a1b3e1509a40ce;p=clang Adopt objc_assign_threadlocal() for __thread variables of GC types. Implements radar 8203301. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108917 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index d6a34562e5..b4ec0cadb7 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -836,8 +836,10 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, BytesBetween); - } else if (Dst.isGlobalObjCRef()) - CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst); + } else if (Dst.isGlobalObjCRef()) { + CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, + Dst.isThreadLocalRef()); + } else CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst); return; @@ -1055,8 +1057,10 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, if (const DeclRefExpr *Exp = dyn_cast(E)) { if (const VarDecl *VD = dyn_cast(Exp->getDecl())) { if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) || - VD->isFileVarDecl()) + VD->isFileVarDecl()) { LV.SetGlobalObjCRef(LV, true); + LV.SetThreadLocalRef(LV, VD->isThreadSpecified()); + } } LV.SetObjCArray(LV, E->getType()->isArrayType()); return; diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index f3c80bcf08..1b8705055e 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -192,7 +192,8 @@ public: virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst); virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dest); + llvm::Value *src, llvm::Value *dest, + bool threadlocal=false); virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest, llvm::Value *ivarOffset); @@ -2075,11 +2076,16 @@ void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, } void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) { + llvm::Value *src, llvm::Value *dst, + bool threadlocal) { CGBuilderTy B = CGF.Builder; src = EnforceType(B, src, IdTy); dst = EnforceType(B, dst, PtrToIdTy); - B.CreateCall2(GlobalAssignFn, src, dst); + if (!threadlocal) + B.CreateCall2(GlobalAssignFn, src, dst); + else + // FIXME. Add threadloca assign API + assert(false && "EmitObjCGlobalAssign - Threal Local API NYI"); } void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 28cdb78555..03764d27ff 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -402,6 +402,16 @@ public: return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); } + /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function. + llvm::Constant *getGcAssignThreadLocalFn() { + // id objc_assign_threadlocal(id src, id * dest) + std::vector Args(1, ObjectPtrTy); + Args.push_back(ObjectPtrTy->getPointerTo()); + llvm::FunctionType *FTy = + llvm::FunctionType::get(ObjectPtrTy, Args, false); + return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal"); + } + /// GcAssignIvarFn -- LLVM objc_assign_ivar function. llvm::Constant *getGcAssignIvarFn() { // id objc_assign_ivar(id, id *, ptrdiff_t) @@ -425,7 +435,7 @@ public: /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. llvm::Constant *getGcAssignStrongCastFn() { - // id objc_assign_global(id, id *) + // id objc_assign_strongCast(id, id *) std::vector Args(1, ObjectPtrTy); Args.push_back(ObjectPtrTy->getPointerTo()); llvm::FunctionType *FTy = @@ -1198,7 +1208,8 @@ public: virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst); virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dest); + llvm::Value *src, llvm::Value *dest, + bool threadlocal = false); virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest, llvm::Value *ivarOffset); @@ -1444,7 +1455,8 @@ public: virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst); virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dest); + llvm::Value *src, llvm::Value *dest, + bool threadlocal = false); virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest, llvm::Value *ivarOffset); @@ -2996,7 +3008,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, /// objc_assign_global (id src, id *dst) /// void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) { + llvm::Value *src, llvm::Value *dst, + bool threadlocal) { const llvm::Type * SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); @@ -3007,8 +3020,12 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), - src, dst, "globalassign"); + if (!threadlocal) + CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), + src, dst, "globalassign"); + else + CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(), + src, dst, "threadlocalassign"); return; } @@ -5657,7 +5674,8 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, /// objc_assign_global (id src, id *dst) /// void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) { + llvm::Value *src, llvm::Value *dst, + bool threadlocal) { const llvm::Type * SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); @@ -5668,8 +5686,12 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), - src, dst, "globalassign"); + if (!threadlocal) + CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), + src, dst, "globalassign"); + else + CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(), + src, dst, "threadlocalassign"); return; } diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index eb79f09de1..88b18b1a26 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -192,7 +192,8 @@ public: 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; + llvm::Value *src, llvm::Value *dest, + bool threadlocal=false) = 0; virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest, llvm::Value *ivarOffset) = 0; diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 92ef9dc4a1..5ac01d4cc9 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -148,6 +148,9 @@ class LValue { // Lvalue is a global reference of an objective-c object bool GlobalObjCRef : 1; + + // Lvalue is a thread local reference + bool ThreadLocalRef : 1; Expr *BaseIvarExp; private: @@ -157,6 +160,7 @@ private: // FIXME: Convenient place to set objc flags to 0. This should really be // done in a user-defined constructor instead. this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false; + this->ThreadLocalRef = false; this->BaseIvarExp = 0; } @@ -178,6 +182,7 @@ public: bool isObjCArray() const { return ObjIsArray; } bool isNonGC () const { return NonGC; } bool isGlobalObjCRef() const { return GlobalObjCRef; } + bool isThreadLocalRef() const { return ThreadLocalRef; } bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; } bool isObjCStrong() const { return Quals.getObjCGCAttr() == Qualifiers::Strong; } @@ -195,7 +200,9 @@ public: static void SetGlobalObjCRef(LValue& R, bool iValue) { R.GlobalObjCRef = iValue; } - + static void SetThreadLocalRef(LValue& R, bool iValue) { + R.ThreadLocalRef = iValue; + } static void SetObjCNonGC(LValue& R, bool iValue) { R.NonGC = iValue; }