]> granicus.if.org Git - clang/commitdiff
objc++: sythesize a helper function to be used
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 6 Jan 2012 00:29:35 +0000 (00:29 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 6 Jan 2012 00:29:35 +0000 (00:29 +0000)
for copying atomic properties of c++ objects
with non-trivial copy assignment in setters/getters.
Not yet used. // rdar://6137845

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147636 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjC.cpp
lib/CodeGen/CodeGenFunction.h

index 58319cf579183b8d8eee058e54a61bbbf115ca3d..9f18f4c334285f74e860daaa8d8477405095b6e4 100644 (file)
@@ -809,9 +809,9 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
     EmitStmt(propImpl->getSetterCXXAssignment());
     return;
   }
-
+  
   const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
-  ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();  
+  ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
   ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl();
 
   PropertyImplStrategy strategy(CGM, propImpl);
@@ -944,6 +944,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
 /// is illegal within a category.
 void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
                                          const ObjCPropertyImplDecl *PID) {
+  GenerateObjCAtomicCopyHelperFunction(PID);
   const ObjCPropertyDecl *PD = PID->getPropertyDecl();
   ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
   assert(OMD && "Invalid call to generate setter (empty method)");
@@ -2481,4 +2482,90 @@ void CodeGenFunction::EmitExtendGCLifetime(llvm::Value *object) {
   Builder.CreateCall(extender, object)->setDoesNotThrow();
 }
 
+/// GenerateObjCAtomicCopyHelperFunction - Given a c++ object type with
+/// non-trivial copy assignment function, produce following helper function.
+/// static void copyHelper(Ty *dest, const Ty *source) { *dest = *source; }
+///
+llvm::Constant *
+CodeGenFunction::GenerateObjCAtomicCopyHelperFunction(
+                                        const ObjCPropertyImplDecl *PID) {
+  if (!getLangOptions().CPlusPlus)
+    return 0;
+  QualType Ty = PID->getPropertyIvarDecl()->getType();
+  if (!Ty->isRecordType())
+    return 0;
+  const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+  if (!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic) ||
+      hasTrivialSetExpr(PID))
+    return 0;
+  assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null");
+  
+  ASTContext &C = getContext();
+  IdentifierInfo *II
+    = &CGM.getContext().Idents.get("__copy_helper_atomic_property_");
+  FunctionDecl *FD = FunctionDecl::Create(C,
+                                          C.getTranslationUnitDecl(),
+                                          SourceLocation(),
+                                          SourceLocation(), II, C.VoidTy, 0,
+                                          SC_Static,
+                                          SC_None,
+                                          false,
+                                          true);
+  
+  QualType DestTy = C.getPointerType(Ty);
+  QualType SrcTy = Ty;
+  SrcTy.addConst();
+  SrcTy = C.getPointerType(SrcTy);
+  
+  FunctionArgList args;
+  ImplicitParamDecl dstDecl(FD, SourceLocation(), 0, DestTy);
+  args.push_back(&dstDecl);
+  ImplicitParamDecl srcDecl(FD, SourceLocation(), 0, SrcTy);
+  args.push_back(&srcDecl);
+  
+  const CGFunctionInfo &FI =
+    CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo());
+  
+  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false);
+  
+  llvm::Function *Fn =
+    llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
+                           "__copy_helper_atomic_property_", &CGM.getModule());
+  
+  if (CGM.getModuleDebugInfo())
+    DebugInfo = CGM.getModuleDebugInfo();
+  
+  
+  StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
+  
+  DeclRefExpr *DstExpr = 
+    new (C) DeclRefExpr(&dstDecl, DestTy,
+                              VK_RValue, SourceLocation());
+  
+  Expr* DST = new (C) UnaryOperator(DstExpr, UO_Deref, DestTy->getPointeeType(),
+                                    VK_LValue, OK_Ordinary, SourceLocation());
+  
+  DeclRefExpr *SrcExpr = 
+    new (C) DeclRefExpr(&srcDecl, SrcTy,
+                        VK_RValue, SourceLocation());
+  
+  Expr* SRC = new (C) UnaryOperator(SrcExpr, UO_Deref, SrcTy->getPointeeType(),
+                                    VK_LValue, OK_Ordinary, SourceLocation());
+  
+  Expr *Args[2] = { DST, SRC };
+  CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
+  CXXOperatorCallExpr *TheCall =
+    new (C) CXXOperatorCallExpr(C, OO_Equal, CalleeExp->getCallee(),
+                                Args, 2, DestTy->getPointeeType(), 
+                                VK_LValue, SourceLocation());
+
+  EmitStmt(TheCall);
+
+  FinishFunction();
+  
+  return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+  
+}
+
+
 CGObjCRuntime::~CGObjCRuntime() {}
index 105cfbec8239d33bd0b987d36d8fbdffdf51a998..9a24426e75509595721c7c975902497104442058 100644 (file)
@@ -1333,6 +1333,8 @@ public:
 
   llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo);
   llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo);
+  llvm::Constant *GenerateObjCAtomicCopyHelperFunction(
+                                             const ObjCPropertyImplDecl *PID);
 
   void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags);