[cfe-commits] r57028 - /cfe/trunk/Driver/RewriteBlocks.cpp

Steve Naroff snaroff at apple.com
Fri Oct 3 13:28:17 PDT 2008


Author: snaroff
Date: Fri Oct  3 15:28:15 2008
New Revision: 57028

URL: http://llvm.org/viewvc/llvm-project?rev=57028&view=rev
Log:
More fun & games with the block rewriter.

Modified:
    cfe/trunk/Driver/RewriteBlocks.cpp

Modified: cfe/trunk/Driver/RewriteBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteBlocks.cpp?rev=57028&r1=57027&r2=57028&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteBlocks.cpp (original)
+++ cfe/trunk/Driver/RewriteBlocks.cpp Fri Oct  3 15:28:15 2008
@@ -49,6 +49,7 @@
   // Block related declarations.
   llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
   llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
+  llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
   
   // The function/method we are rewriting.
   FunctionDecl *CurFunctionDef;
@@ -96,6 +97,8 @@
   void RewriteBlockPointerDecl(NamedDecl *VD);
   void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
   
+  std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 
+                                    const char *funcName, std::string Tag);
   std::string SynthesizeBlockFunc(BlockExpr *CE, int i, 
                                     const char *funcName, std::string Tag);
   std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag);
@@ -429,6 +432,7 @@
     
     BodyBuf.append(BodyStartBuf, BodyEndBuf-BodyStartBuf+1);
     
+    //fprintf(stderr, "BodyBuf=>%s\n", BodyBuf.c_str());
     if (BlockDeclRefs.size()) {
       unsigned int nCharsAdded = 0;
       for (unsigned i = 0; i < BlockDeclRefs.size(); i++) {
@@ -449,17 +453,20 @@
           Diags.Report(NoNestedBlockCalls);
 
           GetBlockCallExprs(CE);
+          ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
           
           // Rewrite the closure in place.
           // The character based equivalent of RewriteBlockCall().
           // Need to get the CallExpr associated with this BlockDeclRef.
           std::string BlockCall = SynthesizeBlockCall(BlockCallExprs[BlockDeclRefs[i]]);
           
+          // FIXME: this is still incomplete.
           SourceLocation CallLocStart = BlockCallExprs[BlockDeclRefs[i]]->getLocStart();
           SourceLocation CallLocEnd = BlockCallExprs[BlockDeclRefs[i]]->getLocEnd();
-          const char *CallStart = SM->getCharacterData(CallLocStart);
+          const char *CallStart = SM->getCharacterData(CallLocStart) + nCharsAdded;
           const char *CallEnd = SM->getCharacterData(CallLocEnd);
           unsigned CallBytes = CallEnd-CallStart;
+          //fprintf(stderr, "BlockCall=>%s CallStart=%d\n", BlockCall.c_str(),CallStart);
           BodyBuf.replace(CallStart-BodyStartBuf, CallBytes, BlockCall.c_str());
           nCharsAdded += CallBytes;
         }
@@ -478,6 +485,40 @@
   return S;
 }
 
+std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
+                                                   const char *funcName,
+                                                   std::string Tag) {
+  std::string StructRef = "struct " + Tag;
+  std::string S = "static void __";
+  
+  S += funcName;
+  S += "_block_copy_" + utostr(i);
+  S += "(" + StructRef;
+  S += "*dst, " + StructRef;
+  S += "*src) {";
+  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 
+      E = ImportedBlockDecls.end(); I != E; ++I) {
+    S += "_Block_copy_assign(&dst->";
+    S += (*I)->getName();
+    S += ", src->";
+    S += (*I)->getName();
+    S += ");}";
+  }
+  S += "\nstatic void __";
+  S += funcName;
+  S += "_block_dispose_" + utostr(i);
+  S += "(" + StructRef;
+  S += "*src) {";
+  for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 
+      E = ImportedBlockDecls.end(); I != E; ++I) {
+    S += "_Block_destroy(src->";
+    S += (*I)->getName();
+    S += ");";
+  }
+  S += "}\n";  
+  return S;
+}
+
 std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) {
   std::string S = "struct " + Tag;
   std::string Constructor = "  " + Tag;
@@ -500,8 +541,8 @@
     for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 
          E = BlockByCopyDecls.end(); I != E; ++I) {
       S += "  ";
-      std::string Name = (*I)->getName();
-      std::string ArgName = "_" + Name;
+      std::string FieldName = (*I)->getName();
+      std::string ArgName = "_" + FieldName;
       // Handle nested closure invocation. For example:
       //
       //   void (^myImportedBlock)(void);
@@ -512,30 +553,41 @@
       //     myImportedBlock(); // import and invoke the closure
       //   };
       //
-      if (isBlockPointerType((*I)->getType()))
+      if (isBlockPointerType((*I)->getType())) {
         S += "struct __block_impl *";
-      else {
-        (*I)->getType().getAsStringInternal(Name);
+        Constructor += ", void *" + ArgName;
+      } else {
+        (*I)->getType().getAsStringInternal(FieldName);
         (*I)->getType().getAsStringInternal(ArgName);
+        Constructor += ", " + ArgName;
       }
-      Constructor += ", " + ArgName;
-      S += Name + ";\n";
+      S += FieldName + ";\n";
     }
     // Output all "by ref" declarations.
     for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 
          E = BlockByRefDecls.end(); I != E; ++I) {
       S += "  ";
-      std::string Name = (*I)->getName();
-      std::string ArgName = "_" + Name;
-      
-      if (isBlockPointerType((*I)->getType()))
+      std::string FieldName = (*I)->getName();
+      std::string ArgName = "_" + FieldName;
+      // Handle nested closure invocation. For example:
+      //
+      //   void (^myImportedBlock)(void);
+      //   myImportedBlock  = ^(void) { setGlobalInt(x + y); };
+      // 
+      //   void (^anotherBlock)(void);
+      //   anotherBlock = ^(void) {
+      //     myImportedBlock(); // import and invoke the closure
+      //   };
+      //
+      if (isBlockPointerType((*I)->getType())) {
         S += "struct __block_impl *";
-      else {
-        Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
+        Constructor += ", void *" + ArgName;
+      } else {
+        Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName);
         Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName);
+        Constructor += ", " + ArgName;
       }
-      Constructor += ", " + ArgName;
-      S += Name + "; // by ref\n";
+      S += FieldName + "; // by ref\n";
     }
     // Finish writing the constructor.
     // FIXME: handle NSConcreteGlobalBlock.
@@ -548,7 +600,10 @@
          E = BlockByCopyDecls.end(); I != E; ++I) {
       std::string Name = (*I)->getName();
       Constructor += "    ";
-      Constructor += Name + " = _";
+      if (isBlockPointerType((*I)->getType()))
+        Constructor += Name + " = (struct __block_impl *)_";
+      else
+        Constructor += Name + " = _";
       Constructor += Name + ";\n";
     }
     // Initialize all "by ref" arguments.
@@ -556,7 +611,10 @@
          E = BlockByRefDecls.end(); I != E; ++I) {
       std::string Name = (*I)->getName();
       Constructor += "    ";
-      Constructor += Name + " = _";
+      if (isBlockPointerType((*I)->getType()))
+        Constructor += Name + " = (struct __block_impl *)_";
+      else
+        Constructor += Name + " = _";
       Constructor += Name + ";\n";
     }
   } else {
@@ -583,15 +641,21 @@
     std::string CI = SynthesizeBlockImpl(Blocks[i], Tag);
 
     InsertText(FunLocStart, CI.c_str(), CI.size());
-    
+
     std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
     
     InsertText(FunLocStart, CF.c_str(), CF.size());
 
+    if (ImportedBlockDecls.size()) {
+      std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
+      InsertText(FunLocStart, HF.c_str(), HF.size());
+    }
+    
     BlockDeclRefs.clear();
     BlockByRefDecls.clear();
     BlockByCopyDecls.clear();
     BlockCallExprs.clear();
+    ImportedBlockDecls.clear();
   }
   Blocks.clear();
 }
@@ -701,8 +765,9 @@
       GetBlockCallExprs(*CI);
       
   if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
-    if (CE->getCallee()->getType()->isBlockPointerType())
+    if (CE->getCallee()->getType()->isBlockPointerType()) {
       BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
+    }
   }
   return;
 }
@@ -1028,6 +1093,9 @@
         Init += "[[";
         Init += (*I)->getName();
         Init += " retain] autorelease]";
+      } else if (isBlockPointerType((*I)->getType())) {
+        Init += "(void *)";
+        Init += (*I)->getName();
       } else {
         Init += (*I)->getName();
       }
@@ -1043,7 +1111,8 @@
   BlockDeclRefs.clear();
   BlockByRefDecls.clear();
   BlockByCopyDecls.clear();
-  
+  ImportedBlockDecls.clear();
+
   // Do the rewrite.
   const char *startBuf = SM->getCharacterData(Exp->getLocStart());
   const char *endBuf = SM->getCharacterData(Exp->getLocEnd());





More information about the cfe-commits mailing list