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