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 d6a3456..b4ec0ca 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -836,8 +836,10 @@
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 @@
if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(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 f3c80bc..1b87050 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -192,7 +192,8 @@
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::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 28cdb78..03764d2 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -402,6 +402,16 @@
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<const llvm::Type*> 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 @@
/// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
llvm::Constant *getGcAssignStrongCastFn() {
- // id objc_assign_global(id, id *)
+ // id objc_assign_strongCast(id, id *)
std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
Args.push_back(ObjectPtrTy->getPointerTo());
llvm::FunctionType *FTy =
@@ -1198,7 +1208,8 @@
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 @@
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 @@
/// 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<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
@@ -3007,8 +3020,12 @@
}
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 @@
/// 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<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
@@ -5668,8 +5686,12 @@
}
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 eb79f09..88b18b1 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -192,7 +192,8 @@
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 92ef9dc..5ac01d4 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -148,6 +148,9 @@
// 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 @@
// 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 @@
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 @@
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;
}