]> granicus.if.org Git - clang/commitdiff
Add support for objc_copyStruct to enforce
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 13 Apr 2010 00:38:05 +0000 (00:38 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 13 Apr 2010 00:38:05 +0000 (00:38 +0000)
atomicity of aggregate properties in setter/getter
methods. wip.

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

lib/CodeGen/CGObjC.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenObjC/atomic-aggregate-property.m [new file with mode: 0644]

index 206d438ced676811292411e6fb0c585c833e89ce..ffdcbdcdea629fb5631ac2f5fc7d538c78a7d9d3 100644 (file)
@@ -208,7 +208,42 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
       StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified());
     }
     else if (hasAggregateLLVMType(Ivar->getType())) {
-      EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType());
+      if (!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
+          && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect
+          && CGM.getObjCRuntime().GetCopyStructFunction()) {
+        llvm::Value *GetCopyStructFn =
+          CGM.getObjCRuntime().GetCopyStructFunction();
+        CodeGenTypes &Types = CGM.getTypes();
+        // objc_copyStruct (ReturnValue, &structIvar, 
+        //                  sizeof (Type of Ivar), isAtomic, false);
+        CallArgList Args;
+        RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue,
+                                    Types.ConvertType(getContext().VoidPtrTy)));
+        Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
+        RV = RValue::get(Builder.CreateBitCast(LV.getAddress(),
+                                    Types.ConvertType(getContext().VoidPtrTy)));
+        Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
+        // sizeof (Type of Ivar)
+        uint64_t Size =  getContext().getTypeSize(Ivar->getType()) / 8;
+        llvm::Value *SizeVal =
+          llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size);
+        Args.push_back(std::make_pair(RValue::get(SizeVal),
+                                      getContext().LongTy));
+        // FIXME. Implement when Atomic is false; But when struct has
+        // gc'able data member!
+        llvm::Value *isAtomic =
+          llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
+        Args.push_back(std::make_pair(RValue::get(isAtomic), 
+                                      getContext().BoolTy));
+        llvm::Value *False =
+          llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
+        Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy));
+        EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
+                                       FunctionType::ExtInfo()),
+                 GetCopyStructFn, ReturnValueSlot(), Args);
+      }
+      else
+        EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType());
     } else {
       CodeGenTypes &Types = CGM.getTypes();
       RValue RV = EmitLoadOfLValue(LV, Ivar->getType());
@@ -289,6 +324,41 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
                                    FunctionType::ExtInfo()),
              SetPropertyFn,
              ReturnValueSlot(), Args);
+  } else if (IsAtomic && hasAggregateLLVMType(Ivar->getType()) &&
+             !Ivar->getType()->isAnyComplexType() &&
+             IndirectObjCSetterArg(*CurFnInfo)
+             && CGM.getObjCRuntime().GetCopyStructFunction()) {
+    // objc_copyStruct (&structIvar, &Arg, 
+    //                  sizeof (struct something), true, false);
+    llvm::Value *GetCopyStructFn =
+      CGM.getObjCRuntime().GetCopyStructFunction();
+    CodeGenTypes &Types = CGM.getTypes();
+    CallArgList Args;
+    LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0);
+    RValue RV = RValue::get(Builder.CreateBitCast(LV.getAddress(),
+                                    Types.ConvertType(getContext().VoidPtrTy)));
+    Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
+    llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()];
+    llvm::Value *ArgAsPtrTy =
+      Builder.CreateBitCast(Arg,
+                            Types.ConvertType(getContext().VoidPtrTy));
+    RV = RValue::get(ArgAsPtrTy);
+    Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
+    // sizeof (Type of Ivar)
+    uint64_t Size =  getContext().getTypeSize(Ivar->getType()) / 8;
+    llvm::Value *SizeVal =
+      llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size);
+    Args.push_back(std::make_pair(RValue::get(SizeVal),
+                                  getContext().LongTy));
+    llvm::Value *True =
+      llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
+    Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
+    llvm::Value *False =
+      llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
+    Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy));
+    EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
+                                   FunctionType::ExtInfo()),
+             GetCopyStructFn, ReturnValueSlot(), Args);
   } else {
     // FIXME: Find a clean way to avoid AST node creation.
     SourceLocation Loc = PD->getLocation();
@@ -318,6 +388,14 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
   FinishFunction();
 }
 
+bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) {
+  CGFunctionInfo::const_arg_iterator it = FI.arg_begin();
+  it++; it++;
+  const ABIArgInfo &AI = it->info;
+  // FIXME. Is this sufficient check?
+  return (AI.getKind() == ABIArgInfo::Indirect);
+}
+
 llvm::Value *CodeGenFunction::LoadObjCSelf() {
   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
   // See if we need to lazily forward self inside a block literal.
index f21350d0f2d9948e150ae33afc5d8e4477bee75d..10f100d3f45d6fda503ce36c2a473d1134db7030 100644 (file)
@@ -479,6 +479,7 @@ public:
   /// for the given property.
   void GenerateObjCSetter(ObjCImplementationDecl *IMP,
                           const ObjCPropertyImplDecl *PID);
+  bool IndirectObjCSetterArg(const CGFunctionInfo &FI);
 
   //===--------------------------------------------------------------------===//
   //                                  Block Bits
diff --git a/test/CodeGenObjC/atomic-aggregate-property.m b/test/CodeGenObjC/atomic-aggregate-property.m
new file mode 100644 (file)
index 0000000..66762c4
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10  -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s
+// rdar: // 7849824
+
+struct s {
+  double a, b, c, d;  
+};
+
+@interface A 
+@property (readwrite) double x;
+@property (readwrite) struct s y;
+@end
+
+@implementation A
+@synthesize x;
+@synthesize y;
+@end
+
+// CHECK-LP64: call void @objc_copyStruct
+// CHECK-LP64: call void @objc_copyStruct