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");
|
||||
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<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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<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 @@ public:
|
|||
|
||||
/// 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 @@ 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<llvm::PointerType>(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<llvm::PointerType>(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue