[cfe-commits] r91977 - /cfe/trunk/lib/Frontend/RewriteObjC.cpp

Fariborz Jahanian fjahanian at apple.com
Tue Dec 22 18:07:38 PST 2009


Author: fjahanian
Date: Tue Dec 22 20:07:37 2009
New Revision: 91977

URL: http://llvm.org/viewvc/llvm-project?rev=91977&view=rev
Log:
Patch to do more rewrite of __block variables.
Still WIP.


Modified:
    cfe/trunk/lib/Frontend/RewriteObjC.cpp

Modified: cfe/trunk/lib/Frontend/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/RewriteObjC.cpp?rev=91977&r1=91976&r2=91977&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Frontend/RewriteObjC.cpp Tue Dec 22 20:07:37 2009
@@ -324,7 +324,7 @@
     // Block specific rewrite rules.
     void RewriteBlockCall(CallExpr *Exp);
     void RewriteBlockPointerDecl(NamedDecl *VD);
-    void RewriteByRefVar(NamedDecl *VD);
+    void RewriteByRefVar(VarDecl *VD);
     Stmt *RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD);
     void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
 
@@ -577,6 +577,8 @@
     Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
     Preamble += "#define __attribute__(X)\n";
   }
+  else
+    Preamble += "#define __block\n";
 }
 
 
@@ -3732,8 +3734,8 @@
        E = BlockByRefDecls.end(); I != E; ++I) {
     S += "  ";
     std::string Name = (*I)->getNameAsString();
-    Context->getPointerType((*I)->getType()).getAsStringInternal(Name,
-                                                      Context->PrintingPolicy);
+    std::string TypeString = "struct __Block_byref_" + Name + " *";
+    Name = TypeString + Name;
     S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
   }
   // Next, emit a declaration for all "by copy" declarations.
@@ -3859,10 +3861,10 @@
         S += "struct __block_impl *";
         Constructor += ", void *" + ArgName;
       } else {
-        Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName,
-                                                       Context->PrintingPolicy);
-        Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName,
-                                                       Context->PrintingPolicy);
+        std::string TypeString = "struct __Block_byref_" + FieldName;
+        TypeString += " *";
+        FieldName = TypeString + FieldName;
+        ArgName = TypeString + ArgName;
         Constructor += ", " + ArgName;
       }
       S += FieldName + "; // by ref\n";
@@ -3897,7 +3899,7 @@
         Constructor += Name + " = (struct __block_impl *)_";
       else
         Constructor += Name + " = _";
-      Constructor += Name + ";\n";
+      Constructor += Name + "->__forwarding;\n";
     }
   } else {
     // Finish writing the constructor.
@@ -4162,6 +4164,8 @@
 //}
 Stmt *RewriteObjC::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
   // FIXME: Add more elaborate code generation required by the ABI.
+  // That is, must generate BYREFVAR->__forwarding->BYREFVAR for each
+  // BDRE where BYREFVAR is name of the variable.
   Expr *DerefExpr = new (Context) UnaryOperator(BDRE, UnaryOperator::Deref,
                              Context->getPointerType(BDRE->getType()),
                              SourceLocation());
@@ -4322,7 +4326,78 @@
   return;
 }
 
-void RewriteObjC::RewriteByRefVar(NamedDecl *ND) {
+/// RewriteByRefVar - For each __block typex ND variable this routine transforms
+/// the declaration into:
+/// struct __Block_byref_ND {
+/// void *__isa;                  // NULL for everything except __weak pointers
+/// struct __Block_byref_ND *__forwarding;
+/// int32_t __flags;
+/// int32_t __size;
+/// void *__ByrefKeepFuncPtr;    // Only if variable is __block ObjC object
+/// void *__ByrefDestroyFuncPtr; // Only if variable is __block ObjC object
+/// typex ND;
+/// };
+///
+/// It then replaces declaration of ND variable with:
+/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 
+///                               __size=sizeof(struct __Block_byref_ND), 
+///                               ND=initializer-if-any};
+///
+///
+void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
+  SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
+  const char *startBuf = SM->getCharacterData(DeclLoc);
+  const char *endBuf = SM->getCharacterData(ND->getLocEnd());
+  std::string Name(ND->getNameAsString());
+  std::string ByrefType = "struct __Block_byref_";
+  ByrefType += Name;
+  ByrefType += " {\n";
+  ByrefType += "  void *__isa;\n";
+  ByrefType += " struct __Block_byref_" + Name + " *__forwarding;\n";
+  ByrefType += " int __flags;\n";
+  ByrefType += " int __size;\n";
+  // FIXME. Add  void *__ByrefKeepFuncPtr; void *__ByrefDestroyFuncPtr; 
+  // if needed.
+  ND->getType().getAsStringInternal(Name, Context->PrintingPolicy);
+  ByrefType += " " + Name + ";\n";
+  ByrefType += "};\n";
+  // Insert this type in global scope. It is needed by helper function.
+  assert(CurFunctionDef && "RewriteByRefVar - CurFunctionDef is null");
+  SourceLocation FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
+  InsertText(FunLocStart, ByrefType.c_str(), ByrefType.size());
+  
+  // struct __Block_byref_ND ND = 
+  // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 
+  //  initializer-if-any};
+  bool hasInit = (ND->getInit() != 0);
+  Name = ND->getNameAsString();
+  ByrefType = "struct __Block_byref_" + Name;
+  if (!hasInit) {
+    ByrefType += " " + Name + " = ";
+    ByrefType += "{0, &" + Name + ", ";
+    // FIXME. Compute the flag.
+    ByrefType += "0, ";
+    ByrefType += "sizeof(struct __Block_byref_" + Name + ")";
+    ByrefType += "};\n";
+    ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), 
+                ByrefType.c_str(), ByrefType.size());
+  }
+  else {
+    SourceLocation startLoc = ND->getInit()->getLocStart();
+    ByrefType += " " + Name;
+    ReplaceText(DeclLoc, endBuf-startBuf, 
+                ByrefType.c_str(), ByrefType.size());
+    ByrefType = " = {0, &" + Name + ", ";
+    // FIXME. Compute the flag.
+    ByrefType += "0, ";
+    ByrefType += "sizeof(struct __Block_byref_" + Name + "), ";
+    InsertText(startLoc, ByrefType.c_str(), ByrefType.size());
+#if 0
+    ByrefType = "};\n";
+    SourceLocation endLoc = ND->getInit()->getLocEnd();
+    InsertText(startLoc, ByrefType.c_str(), ByrefType.size());
+#endif
+  }
   return;
 }
 
@@ -4671,8 +4746,9 @@
           RewriteBlockPointerDecl(ND);
         else if (ND->getType()->isFunctionPointerType())
           CheckFunctionPointerDecl(ND->getType(), ND);
-        if (ND->hasAttr<BlocksAttr>())
-          RewriteByRefVar(ND);
+        if (VarDecl *VD = dyn_cast<VarDecl>(SD)) 
+          if (VD->hasAttr<BlocksAttr>())
+            RewriteByRefVar(VD);
       }
       if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
         if (isTopLevelBlockPointerType(TD->getUnderlyingType()))





More information about the cfe-commits mailing list