Adopt objc_assign_threadlocal() for __thread variables of GC types.

Implements radar 8203301.

llvm-svn: 108917
This commit is contained in:
Fariborz Jahanian 2010-07-20 20:30:03 +00:00
parent 6c01820900
commit 217af240b5
5 changed files with 57 additions and 17 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}