From: Steve Naroff Date: Fri, 3 Oct 2008 20:28:15 +0000 (+0000) Subject: More fun & games with the block rewriter. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4e13b762e02621f3186402ced398c8cc791f2dec;p=clang More fun & games with the block rewriter. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57028 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/RewriteBlocks.cpp b/Driver/RewriteBlocks.cpp index e50f2b2f79..dbb39401d4 100644 --- a/Driver/RewriteBlocks.cpp +++ b/Driver/RewriteBlocks.cpp @@ -49,6 +49,7 @@ class RewriteBlocks : public ASTConsumer { // Block related declarations. llvm::SmallPtrSet BlockByCopyDecls; llvm::SmallPtrSet BlockByRefDecls; + llvm::SmallPtrSet ImportedBlockDecls; // The function/method we are rewriting. FunctionDecl *CurFunctionDef; @@ -96,6 +97,8 @@ public: 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 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i, 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 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i, 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 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i, 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::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::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 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) { for (llvm::SmallPtrSet::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 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) { // 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::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 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) { 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 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) { 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 @@ void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart, 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 @@ void RewriteBlocks::GetBlockCallExprs(Stmt *S) { GetBlockCallExprs(*CI); if (CallExpr *CE = dyn_cast(S)) { - if (CE->getCallee()->getType()->isBlockPointerType()) + if (CE->getCallee()->getType()->isBlockPointerType()) { BlockCallExprs[dyn_cast(CE->getCallee())] = CE; + } } return; } @@ -1028,6 +1093,9 @@ void RewriteBlocks::RewriteBlockExpr(BlockExpr *Exp, VarDecl *VD) { 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 @@ void RewriteBlocks::RewriteBlockExpr(BlockExpr *Exp, VarDecl *VD) { 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());