]> granicus.if.org Git - clang/commitdiff
Starting patch to generate more specific API for objc's
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 16 Sep 2009 21:37:16 +0000 (21:37 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 16 Sep 2009 21:37:16 +0000 (21:37 +0000)
GC. Currently, new API will be generated under
clang-cc's -fobjc-newgc-api flag which will eventually
become the default. WIP.

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

include/clang/Basic/LangOptions.h
lib/CodeGen/CGExpr.cpp
test/CodeGenObjC/objc2-assign-global.m
tools/clang-cc/clang-cc.cpp

index d4d3fe50eba06b471b1402f1f5f4a6e184e2e08e..8f60b47f4cdc93b89a12fefbb67e0fa828eb8d21 100644 (file)
@@ -88,6 +88,7 @@ public:
 
   unsigned ElideConstructors : 1; // Whether C++ copy constructors should be
                                   // elided if possible.
+  unsigned ObjCNewGCAPI : 1;      // Generate objective-c's new GC API
 private:
   unsigned GC : 2;                // Objective-C Garbage Collection modes.  We
                                   // declare this enum as unsigned because MSVC
@@ -146,6 +147,7 @@ public:
 
     OverflowChecking = 0;
     ObjCGCBitmapPrint = 0;
+    ObjCNewGCAPI = 0;
 
     InstantiationDepth = 99;
 
index f163c185529daa2251b5599be9ca30505039f842..4dc7c265bb3516737e0c6671de6efec7e623e91d 100644 (file)
@@ -694,6 +694,37 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
   Builder.CreateStore(Vec, Dst.getExtVectorAddr(), Dst.isVolatileQualified());
 }
 
+// setObjCGCLValueClass - sets class of he lvalue for the purpose of
+// generating write-barries API. It is currently a global, ivar,
+// or neither.
+static
+void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
+  if (Ctx.getLangOptions().getGCMode() == LangOptions::NonGC ||
+      !Ctx.getLangOptions().ObjCNewGCAPI)
+    return;
+  
+  if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
+      if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
+          VD->isFileVarDecl())
+        LV.SetGlobalObjCRef(LV, true);
+    }
+  }
+  else if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E))
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+  else if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E))
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+  else if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E))
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+  else if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E))
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+  else if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E))
+    setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
+  else if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
+    setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
+  }
+}
+
 LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
   const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
 
@@ -729,6 +760,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
                             E->getType().getAddressSpace());
     }
     LValue::SetObjCNonGC(LV, NonGCable);
+    setObjCGCLValueClass(getContext(), E, LV);
     return LV;
   } else if (VD && VD->isFileVarDecl()) {
     llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
@@ -737,7 +769,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
     LValue LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
                                  getContext().getObjCGCAttrKind(E->getType()),
                                  E->getType().getAddressSpace());
-    LV.SetGlobalObjCRef(LV, true);
+    setObjCGCLValueClass(getContext(), E, LV);
     return LV;
   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
     llvm::Value* V = CGM.GetAddrOfFunction(FD);
@@ -937,8 +969,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
                                getContext().getObjCGCAttrKind(T),
                                E->getBase()->getType().getAddressSpace());
   if (getContext().getLangOptions().ObjC1 &&
-      getContext().getLangOptions().getGCMode() != LangOptions::NonGC)
+      getContext().getLangOptions().getGCMode() != LangOptions::NonGC) {
     LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
+    setObjCGCLValueClass(getContext(), E, LV);
+  }
   return LV;
 }
 
@@ -1042,6 +1076,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
                                        CVRQualifiers);
   LValue::SetObjCIvar(MemExpLV, isIvar);
   LValue::SetObjCNonGC(MemExpLV, isNonGC);
+  setObjCGCLValueClass(getContext(), E, MemExpLV);
   return MemExpLV;
 }
 
index ae407619093e6c9ac256d727bcddb086bbc4b6f9..426b99fde1528b84aec97e243b379cadd8c5f625 100644 (file)
@@ -1,8 +1,82 @@
-// RUN: clang-cc -fnext-runtime -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep -F '@objc_assign_global' %t  | count 2 &&
+// RUN: clang-cc -fnext-runtime -fobjc-gc -fobjc-newgc-api -emit-llvm -o %t %s &&
+// RUN: grep -F '@objc_assign_global' %t  | count 26 &&
 // RUN: true
-id a;
+
+@class NSObject;
+typedef const struct __CFDictionary * CFDictionaryRef;
+typedef struct {
+  id  element;
+  id elementArray[10];
+  __strong CFDictionaryRef cfElement;
+  __strong CFDictionaryRef cfElementArray[10];
+} struct_with_ids_t;
+
+
+// assignments to these should generate objc_assign_global
+@interface A
+@end
+
+typedef struct s0 {
+  A *a[4];
+} T;
+
+T g0;
+
+extern id FileExternID;
+static id FileStaticID;
+id GlobalId;
+id GlobalArray[20];
+NSObject *GlobalObject;
+NSObject *GlobalObjectArray[20];
+__strong CFDictionaryRef Gdict;
+__strong CFDictionaryRef Gdictarray[10];
+struct_with_ids_t GlobalStruct;
+struct_with_ids_t GlobalStructArray[10];
+
+#define ASSIGNTEST(expr, global) expr = rhs
+void *rhs = 0;
+
 int main() {
-        a = 0;
+  static id staticGlobalId;
+  static id staticGlobalArray[20];
+  static NSObject *staticGlobalObject;
+  static NSObject *staticGlobalObjectArray[20];
+  static __strong CFDictionaryRef staticGdict;
+  static __strong CFDictionaryRef staticGdictarray[10];
+  static struct_with_ids_t staticGlobalStruct;
+  static struct_with_ids_t staticGlobalStructArray[10];
+  extern id ExID;
+  id localID;
+
+  ASSIGNTEST(GlobalId, GlobalAssigns);                          // objc_assign_global
+  ASSIGNTEST(GlobalArray[0], GlobalAssigns);                    // objc_assign_global
+  ASSIGNTEST(GlobalObject, GlobalAssigns);                      // objc_assign_global
+  ASSIGNTEST(GlobalObjectArray[0], GlobalAssigns);              // objc_assign_global
+  ASSIGNTEST(Gdict, GlobalAssigns);                             // objc_assign_global
+  ASSIGNTEST(Gdictarray[1], GlobalAssigns);                     // objc_assign_global
+
+  ASSIGNTEST(GlobalStruct.element, GlobalAssigns);              // objc_assign_global
+  ASSIGNTEST(GlobalStruct.elementArray[0], GlobalAssigns);      // objc_assign_global
+  ASSIGNTEST(GlobalStruct.cfElement, GlobalAssigns);            // objc_assign_global
+  ASSIGNTEST(GlobalStruct.cfElementArray[0], GlobalAssigns);    // objc_assign_global
+
+  ASSIGNTEST(staticGlobalId, GlobalAssigns);                    // objc_assign_global
+  ASSIGNTEST(staticGlobalArray[0], GlobalAssigns);              // objc_assign_global
+  ASSIGNTEST(staticGlobalObject, GlobalAssigns);                // objc_assign_global
+  ASSIGNTEST(staticGlobalObjectArray[0], GlobalAssigns);        // objc_assign_global
+  ASSIGNTEST(staticGdict, GlobalAssigns);                       // objc_assign_global
+  ASSIGNTEST(staticGdictarray[1], GlobalAssigns);               // objc_assign_global
+
+  ASSIGNTEST(staticGlobalStruct.element, GlobalAssigns);                // objc_assign_global
+  ASSIGNTEST(staticGlobalStruct.elementArray[0], GlobalAssigns);        // objc_assign_global
+  ASSIGNTEST(staticGlobalStruct.cfElement, GlobalAssigns);              // objc_assign_global
+  ASSIGNTEST(staticGlobalStruct.cfElementArray[0], GlobalAssigns);      // objc_assign_global
+
+  ExID = 0;
+  localID = 0;
+  FileStaticID = 0;
+  FileExternID=0;
+  g0.a[0] = 0;
+  ((T*) &g0)->a[0] = 0;
 }
 
index 3c451c8c0d2e32529808fe78204c0b8c2eb208b8..31aeb7404999445b201a9bd365393e1e55c6ea59 100644 (file)
@@ -371,6 +371,10 @@ static llvm::cl::opt<bool>
 ObjCEnableGC("fobjc-gc",
              llvm::cl::desc("Enable Objective-C garbage collection"));
 
+static llvm::cl::opt<bool>
+ObjCEnableNewGCAPI("fobjc-newgc-api",
+             llvm::cl::desc("Enable Objective-C garbage collection's new API"));
+
 static llvm::cl::opt<bool>
 ObjCEnableGCBitmapPrint("print-ivar-layout",
              llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace"));
@@ -508,6 +512,9 @@ static void InitializeLangOptions(LangOptions &Options, LangKind LK){
   else if (ObjCEnableGC)
     Options.setGCMode(LangOptions::HybridGC);
 
+  if (ObjCEnableNewGCAPI)
+    Options.ObjCNewGCAPI = 1;
+
   if (ObjCEnableGCBitmapPrint)
     Options.ObjCGCBitmapPrint = 1;