forked from OSchip/llvm-project
Adopt objc_assign_threadlocal() for __thread variables of GC types.
Implements radar 8203301. llvm-svn: 108917
This commit is contained in:
parent
6c01820900
commit
217af240b5
|
|
@ -836,8 +836,10 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
|
||||||
llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset");
|
llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset");
|
||||||
CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst,
|
CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst,
|
||||||
BytesBetween);
|
BytesBetween);
|
||||||
} else if (Dst.isGlobalObjCRef())
|
} else if (Dst.isGlobalObjCRef()) {
|
||||||
CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst);
|
CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst,
|
||||||
|
Dst.isThreadLocalRef());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst);
|
CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1055,8 +1057,10 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
|
||||||
if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
|
if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
|
||||||
if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
|
if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
|
||||||
if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
|
if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
|
||||||
VD->isFileVarDecl())
|
VD->isFileVarDecl()) {
|
||||||
LV.SetGlobalObjCRef(LV, true);
|
LV.SetGlobalObjCRef(LV, true);
|
||||||
|
LV.SetThreadLocalRef(LV, VD->isThreadSpecified());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LV.SetObjCArray(LV, E->getType()->isArrayType());
|
LV.SetObjCArray(LV, E->getType()->isArrayType());
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,8 @@ public:
|
||||||
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *src, llvm::Value *dst);
|
llvm::Value *src, llvm::Value *dst);
|
||||||
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
|
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,
|
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *src, llvm::Value *dest,
|
llvm::Value *src, llvm::Value *dest,
|
||||||
llvm::Value *ivarOffset);
|
llvm::Value *ivarOffset);
|
||||||
|
|
@ -2075,11 +2076,16 @@ void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGObjCGNU::EmitObjCGlobalAssign(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;
|
CGBuilderTy B = CGF.Builder;
|
||||||
src = EnforceType(B, src, IdTy);
|
src = EnforceType(B, src, IdTy);
|
||||||
dst = EnforceType(B, dst, PtrToIdTy);
|
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,
|
void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,16 @@ public:
|
||||||
return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
|
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.
|
/// GcAssignIvarFn -- LLVM objc_assign_ivar function.
|
||||||
llvm::Constant *getGcAssignIvarFn() {
|
llvm::Constant *getGcAssignIvarFn() {
|
||||||
// id objc_assign_ivar(id, id *, ptrdiff_t)
|
// id objc_assign_ivar(id, id *, ptrdiff_t)
|
||||||
|
|
@ -425,7 +435,7 @@ public:
|
||||||
|
|
||||||
/// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
|
/// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
|
||||||
llvm::Constant *getGcAssignStrongCastFn() {
|
llvm::Constant *getGcAssignStrongCastFn() {
|
||||||
// id objc_assign_global(id, id *)
|
// id objc_assign_strongCast(id, id *)
|
||||||
std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
|
std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
|
||||||
Args.push_back(ObjectPtrTy->getPointerTo());
|
Args.push_back(ObjectPtrTy->getPointerTo());
|
||||||
llvm::FunctionType *FTy =
|
llvm::FunctionType *FTy =
|
||||||
|
|
@ -1198,7 +1208,8 @@ public:
|
||||||
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *src, llvm::Value *dst);
|
llvm::Value *src, llvm::Value *dst);
|
||||||
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
|
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,
|
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *src, llvm::Value *dest,
|
llvm::Value *src, llvm::Value *dest,
|
||||||
llvm::Value *ivarOffset);
|
llvm::Value *ivarOffset);
|
||||||
|
|
@ -1444,7 +1455,8 @@ public:
|
||||||
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *src, llvm::Value *dst);
|
llvm::Value *src, llvm::Value *dst);
|
||||||
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
|
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,
|
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *src, llvm::Value *dest,
|
llvm::Value *src, llvm::Value *dest,
|
||||||
llvm::Value *ivarOffset);
|
llvm::Value *ivarOffset);
|
||||||
|
|
@ -2996,7 +3008,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
/// objc_assign_global (id src, id *dst)
|
/// objc_assign_global (id src, id *dst)
|
||||||
///
|
///
|
||||||
void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
|
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();
|
const llvm::Type * SrcTy = src->getType();
|
||||||
if (!isa<llvm::PointerType>(SrcTy)) {
|
if (!isa<llvm::PointerType>(SrcTy)) {
|
||||||
unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
|
unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
|
||||||
|
|
@ -3007,8 +3020,12 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
}
|
}
|
||||||
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
|
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
|
||||||
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
|
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
|
||||||
CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
|
if (!threadlocal)
|
||||||
src, dst, "globalassign");
|
CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
|
||||||
|
src, dst, "globalassign");
|
||||||
|
else
|
||||||
|
CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
|
||||||
|
src, dst, "threadlocalassign");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5657,7 +5674,8 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
/// objc_assign_global (id src, id *dst)
|
/// objc_assign_global (id src, id *dst)
|
||||||
///
|
///
|
||||||
void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
|
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();
|
const llvm::Type * SrcTy = src->getType();
|
||||||
if (!isa<llvm::PointerType>(SrcTy)) {
|
if (!isa<llvm::PointerType>(SrcTy)) {
|
||||||
unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
|
unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
|
||||||
|
|
@ -5668,8 +5686,12 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
}
|
}
|
||||||
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
|
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
|
||||||
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
|
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
|
||||||
CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
|
if (!threadlocal)
|
||||||
src, dst, "globalassign");
|
CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
|
||||||
|
src, dst, "globalassign");
|
||||||
|
else
|
||||||
|
CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
|
||||||
|
src, dst, "threadlocalassign");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,8 @@ public:
|
||||||
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *src, llvm::Value *dest) = 0;
|
llvm::Value *src, llvm::Value *dest) = 0;
|
||||||
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
|
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,
|
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
|
||||||
llvm::Value *src, llvm::Value *dest,
|
llvm::Value *src, llvm::Value *dest,
|
||||||
llvm::Value *ivarOffset) = 0;
|
llvm::Value *ivarOffset) = 0;
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,9 @@ class LValue {
|
||||||
// Lvalue is a global reference of an objective-c object
|
// Lvalue is a global reference of an objective-c object
|
||||||
bool GlobalObjCRef : 1;
|
bool GlobalObjCRef : 1;
|
||||||
|
|
||||||
|
// Lvalue is a thread local reference
|
||||||
|
bool ThreadLocalRef : 1;
|
||||||
|
|
||||||
Expr *BaseIvarExp;
|
Expr *BaseIvarExp;
|
||||||
private:
|
private:
|
||||||
void SetQualifiers(Qualifiers Quals) {
|
void SetQualifiers(Qualifiers Quals) {
|
||||||
|
|
@ -157,6 +160,7 @@ private:
|
||||||
// FIXME: Convenient place to set objc flags to 0. This should really be
|
// FIXME: Convenient place to set objc flags to 0. This should really be
|
||||||
// done in a user-defined constructor instead.
|
// done in a user-defined constructor instead.
|
||||||
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
|
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
|
||||||
|
this->ThreadLocalRef = false;
|
||||||
this->BaseIvarExp = 0;
|
this->BaseIvarExp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,6 +182,7 @@ public:
|
||||||
bool isObjCArray() const { return ObjIsArray; }
|
bool isObjCArray() const { return ObjIsArray; }
|
||||||
bool isNonGC () const { return NonGC; }
|
bool isNonGC () const { return NonGC; }
|
||||||
bool isGlobalObjCRef() const { return GlobalObjCRef; }
|
bool isGlobalObjCRef() const { return GlobalObjCRef; }
|
||||||
|
bool isThreadLocalRef() const { return ThreadLocalRef; }
|
||||||
bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; }
|
bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; }
|
||||||
bool isObjCStrong() const { return Quals.getObjCGCAttr() == Qualifiers::Strong; }
|
bool isObjCStrong() const { return Quals.getObjCGCAttr() == Qualifiers::Strong; }
|
||||||
|
|
||||||
|
|
@ -195,7 +200,9 @@ public:
|
||||||
static void SetGlobalObjCRef(LValue& R, bool iValue) {
|
static void SetGlobalObjCRef(LValue& R, bool iValue) {
|
||||||
R.GlobalObjCRef = iValue;
|
R.GlobalObjCRef = iValue;
|
||||||
}
|
}
|
||||||
|
static void SetThreadLocalRef(LValue& R, bool iValue) {
|
||||||
|
R.ThreadLocalRef = iValue;
|
||||||
|
}
|
||||||
static void SetObjCNonGC(LValue& R, bool iValue) {
|
static void SetObjCNonGC(LValue& R, bool iValue) {
|
||||||
R.NonGC = iValue;
|
R.NonGC = iValue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue