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

Steve Naroff snaroff at apple.com
Sat Oct 4 10:06:24 PDT 2008


Author: snaroff
Date: Sat Oct  4 12:06:23 2008
New Revision: 57052

URL: http://llvm.org/viewvc/llvm-project?rev=57052&view=rev
Log:
Moved main control flow functions to bottom of file.
Reworked control flow to:
- rewrite the block expr body "in place".
- used Chris's new rewriter hook "getRewritenText" to "lift" the text for later use.
- finally, we do the block expr text replacement.

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=57052&r1=57051&r2=57052&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteBlocks.cpp (original)
+++ cfe/trunk/Driver/RewriteBlocks.cpp Sat Oct  4 12:06:23 2008
@@ -50,6 +50,8 @@
   llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
   llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
   llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
+
+  llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
   
   // The function/method we are rewriting.
   FunctionDecl *CurFunctionDef;
@@ -91,7 +93,7 @@
   void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
   
   // Block specific rewrite rules.
-  void RewriteBlockExpr(BlockExpr *Exp, VarDecl *VD=0);
+  std::string SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD=0);
   
   void RewriteBlockCall(CallExpr *Exp);
   void RewriteBlockPointerDecl(NamedDecl *VD);
@@ -421,61 +423,12 @@
     else
       (*I)->getType().getAsStringInternal(Name);
     S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
-  }    
-  if (BlockExpr *CBE = dyn_cast<BlockExpr>(CE)) {
-    std::string BodyBuf;
-    
-    SourceLocation BodyLocStart = CBE->getBody()->getLocStart();
-    SourceLocation BodyLocEnd = CBE->getBody()->getLocEnd();
-    const char *BodyStartBuf = SM->getCharacterData(BodyLocStart);
-    const char *BodyEndBuf = SM->getCharacterData(BodyLocEnd);
-    
-    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++) {
-        if (BlockDeclRefs[i]->isByRef()) {
-          // Add a level of indirection! The code below assumes
-          // the closure decl refs/locations are in strictly ascending
-          // order. The traversal performed by GetBlockDeclRefExprs()
-          // currently does this. FIXME: Wrap the *x with parens,
-          // just in case x is a more complex expression, like x->member,
-          // which needs to be rewritten to (*x)->member.
-          SourceLocation StarLoc = BlockDeclRefs[i]->getLocStart();
-          const char *StarBuf = SM->getCharacterData(StarLoc);
-          BodyBuf.insert(StarBuf-BodyStartBuf+nCharsAdded, 1, '*');
-          // Get a fresh buffer, the insert might have caused it to grow.
-          BodyStartBuf = SM->getCharacterData(BodyLocStart);
-          nCharsAdded++;
-        } else if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
-          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) + 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;
-        }
-      }
-    }
-    S += "  ";
-    S += BodyBuf;
   }
-  S += "\n}\n";
+  std::string RewrittenStr = RewrittenBlockExprs[CE];
+  const char *cstr = RewrittenStr.c_str();
+  while (*cstr++ != '{') ;
+  S += cstr;
+  S += "\n";
   return S;
 }
 
@@ -672,71 +625,6 @@
   SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
 }
 
-/// HandleDeclInMainFile - This is called for each top-level decl defined in the
-/// main file of the input.
-void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
-  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-  
-    // Since function prototypes don't have ParmDecl's, we check the function
-    // prototype. This enables us to rewrite function declarations and
-    // definitions using the same code.
-    QualType funcType = FD->getType();
-    
-    if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
-      for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(), 
-           E = fproto->arg_type_end(); I && (I != E); ++I)
-        if (isBlockPointerType(*I)) {
-          // All the args are checked/rewritten. Don't call twice!
-          RewriteBlockPointerDecl(FD);
-          break;
-        }
-    }
-    if (Stmt *Body = FD->getBody()) {
-      CurFunctionDef = FD;
-      FD->setBody(RewriteFunctionBody(Body));
-      InsertBlockLiteralsWithinFunction(FD);
-      CurFunctionDef = 0;
-    } 
-    return;
-  }
-  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
-    RewriteMethodDecl(MD);
-    if (Stmt *Body = MD->getBody()) {
-      CurMethodDef = MD;
-      RewriteFunctionBody(Body);
-      InsertBlockLiteralsWithinMethod(MD);
-      CurMethodDef = 0;
-    }
-  }
-  if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
-    if (isBlockPointerType(VD->getType())) {
-      RewriteBlockPointerDecl(VD);
-      if (VD->getInit()) {
-        if (BlockExpr *BExp = dyn_cast<BlockExpr>(VD->getInit())) {
-          RewriteBlockExpr(BExp, VD);
-          SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
-        }
-      }
-    }
-    return;
-  }
-  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
-    if (isBlockPointerType(TD->getUnderlyingType()))
-      RewriteBlockPointerDecl(TD);
-    return;
-  }
-  if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
-    if (RD->isDefinition()) {
-      for (RecordDecl::field_const_iterator i = RD->field_begin(), 
-             e = RD->field_end(); i != e; ++i) {
-        FieldDecl *FD = *i;
-        if (isBlockPointerType(FD->getType()))
-          RewriteBlockPointerDecl(FD);
-      }
-    }
-    return;
-  }
-}
 
 void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
   for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
@@ -766,45 +654,6 @@
   return;
 }
 
-//===----------------------------------------------------------------------===//
-// Function Body / Expression rewriting
-//===----------------------------------------------------------------------===//
-
-Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
-  // Start by rewriting all children.
-  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
-       CI != E; ++CI)
-    if (*CI) {
-      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
-        // We intentionally avoid rewritting the contents of a closure block
-        // expr. InsertBlockLiteralsWithinFunction() will rewrite the body.
-        RewriteBlockExpr(CBE);
-      } else {
-        Stmt *newStmt = RewriteFunctionBody(*CI);
-        if (newStmt) 
-          *CI = newStmt;
-      }
-    }
-  // Handle specific things.
-  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
-    if (CE->getCallee()->getType()->isBlockPointerType())
-      RewriteBlockCall(CE);
-  }
-  if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
-    ScopedDecl *SD = DS->getDecl();
-    if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
-      if (isBlockPointerType(ND->getType()))
-        RewriteBlockPointerDecl(ND);
-    }
-    if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
-      if (isBlockPointerType(TD->getUnderlyingType()))
-        RewriteBlockPointerDecl(TD);
-    }
-  }
-  // Return this stmt unmodified.
-  return S;
-}
-
 std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
   // Navigate to relevant type information.
   const char *closureName = 0;
@@ -1027,7 +876,7 @@
   return;
 }
 
-void RewriteBlocks::RewriteBlockExpr(BlockExpr *Exp, VarDecl *VD) {
+std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) {
   Blocks.push_back(Exp);
   bool haveByRefDecls = false;
 
@@ -1107,9 +956,128 @@
   BlockByCopyDecls.clear();
   ImportedBlockDecls.clear();
 
-  // Do the rewrite.
-  const char *startBuf = SM->getCharacterData(Exp->getLocStart());
-  const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
-  ReplaceText(Exp->getLocStart(), endBuf-startBuf+1, Init.c_str(), Init.size());
-  return;
+  return Init;
+}
+
+//===----------------------------------------------------------------------===//
+// Function Body / Expression rewriting
+//===----------------------------------------------------------------------===//
+
+Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
+  // Start by rewriting all children.
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+       CI != E; ++CI)
+    if (*CI) {
+      if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
+        Stmt *newStmt = RewriteFunctionBody(*CI);
+        if (newStmt) 
+          *CI = newStmt;
+          
+        // We've just rewritten the block body in place.
+        // Now we snarf the rewritten text and stash it away for later use.
+        std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
+        RewrittenBlockExprs[CBE] = S;
+        std::string Init = SynthesizeBlockInitExpr(CBE);
+        // Do the rewrite, using S.size() which contains the rewritten size.
+        ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
+      } else {
+        Stmt *newStmt = RewriteFunctionBody(*CI);
+        if (newStmt) 
+          *CI = newStmt;
+      }
+    }
+  // Handle specific things.
+  if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
+    if (CE->getCallee()->getType()->isBlockPointerType())
+      RewriteBlockCall(CE);
+  }
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
+    ScopedDecl *SD = DS->getDecl();
+    if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
+      if (isBlockPointerType(ND->getType()))
+        RewriteBlockPointerDecl(ND);
+    }
+    if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
+      if (isBlockPointerType(TD->getUnderlyingType()))
+        RewriteBlockPointerDecl(TD);
+    }
+  }
+  // Return this stmt unmodified.
+  return S;
+}
+
+/// HandleDeclInMainFile - This is called for each top-level decl defined in the
+/// main file of the input.
+void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+  
+    // Since function prototypes don't have ParmDecl's, we check the function
+    // prototype. This enables us to rewrite function declarations and
+    // definitions using the same code.
+    QualType funcType = FD->getType();
+    
+    if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
+      for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(), 
+           E = fproto->arg_type_end(); I && (I != E); ++I)
+        if (isBlockPointerType(*I)) {
+          // All the args are checked/rewritten. Don't call twice!
+          RewriteBlockPointerDecl(FD);
+          break;
+        }
+    }
+    if (Stmt *Body = FD->getBody()) {
+      CurFunctionDef = FD;
+      FD->setBody(RewriteFunctionBody(Body));
+      // This synthesizes and inserts the block "impl" struct, invoke function,
+      // and any copy/dispose helper functions.
+      InsertBlockLiteralsWithinFunction(FD);
+      CurFunctionDef = 0;
+    } 
+    return;
+  }
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    RewriteMethodDecl(MD);
+    if (Stmt *Body = MD->getBody()) {
+      CurMethodDef = MD;
+      RewriteFunctionBody(Body);
+      InsertBlockLiteralsWithinMethod(MD);
+      CurMethodDef = 0;
+    }
+  }
+  if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (isBlockPointerType(VD->getType())) {
+      RewriteBlockPointerDecl(VD);
+      if (VD->getInit()) {
+        if (BlockExpr *CBE = dyn_cast<BlockExpr>(VD->getInit())) {
+          RewriteFunctionBody(VD->getInit());
+
+          // We've just rewritten the block body in place.
+          // Now we snarf the rewritten text and stash it away for later use.
+          std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
+          RewrittenBlockExprs[CBE] = S;
+          std::string Init = SynthesizeBlockInitExpr(CBE, VD);
+          // Do the rewrite, using S.size() which contains the rewritten size.
+          ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
+          SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
+        }
+      }
+    }
+    return;
+  }
+  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+    if (isBlockPointerType(TD->getUnderlyingType()))
+      RewriteBlockPointerDecl(TD);
+    return;
+  }
+  if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
+    if (RD->isDefinition()) {
+      for (RecordDecl::field_const_iterator i = RD->field_begin(), 
+             e = RD->field_end(); i != e; ++i) {
+        FieldDecl *FD = *i;
+        if (isBlockPointerType(FD->getType()))
+          RewriteBlockPointerDecl(FD);
+      }
+    }
+    return;
+  }
 }





More information about the cfe-commits mailing list