blob: b887734a2ecc5522d38d6f4678af63f8a02808be [file] [log] [blame]
Steve Naroff200902c2008-09-17 00:13:27 +00001//===--- RewriteBlocks.cpp ----------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the closure rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
15#include "clang/Rewrite/Rewriter.h"
16#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
18#include "clang/Basic/SourceManager.h"
19#include "clang/Basic/IdentifierTable.h"
20#include "clang/Basic/Diagnostic.h"
21#include "clang/Basic/LangOptions.h"
22#include "llvm/Support/MemoryBuffer.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/ADT/SmallPtrSet.h"
25#include <sstream>
26
27using namespace clang;
28using llvm::utostr;
29
30namespace {
31
32class RewriteBlocks : public ASTConsumer {
33 Rewriter Rewrite;
34 Diagnostic &Diags;
35 const LangOptions &LangOpts;
36 unsigned RewriteFailedDiag;
37 unsigned NoNestedBlockCalls;
38
39 ASTContext *Context;
40 SourceManager *SM;
41 unsigned MainFileID;
42 const char *MainFileStart, *MainFileEnd;
43
44 // Block expressions.
45 llvm::SmallVector<BlockExpr *, 32> Blocks;
46 llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
47 llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs;
48
49 // Block related declarations.
50 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
51 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
Steve Naroff12b2e772008-10-03 20:28:15 +000052 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
Steve Narofffa9e5a22008-10-04 17:06:23 +000053
54 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
Steve Naroff200902c2008-09-17 00:13:27 +000055
56 // The function/method we are rewriting.
57 FunctionDecl *CurFunctionDef;
58 ObjCMethodDecl *CurMethodDef;
59
60 bool IsHeader;
Steve Naroff93c18352008-09-18 14:10:13 +000061 std::string InFileName;
62 std::string OutFileName;
Steve Naroff0b060922008-10-02 23:30:43 +000063
64 std::string Preamble;
Steve Naroff200902c2008-09-17 00:13:27 +000065public:
Steve Naroff93c18352008-09-18 14:10:13 +000066 RewriteBlocks(std::string inFile, std::string outFile, Diagnostic &D,
67 const LangOptions &LOpts);
Steve Naroff200902c2008-09-17 00:13:27 +000068 ~RewriteBlocks() {
69 // Get the buffer corresponding to MainFileID.
70 // If we haven't changed it, then we are done.
71 if (const RewriteBuffer *RewriteBuf =
72 Rewrite.getRewriteBufferFor(MainFileID)) {
73 std::string S(RewriteBuf->begin(), RewriteBuf->end());
74 printf("%s\n", S.c_str());
75 } else {
76 printf("No changes\n");
77 }
78 }
79
80 void Initialize(ASTContext &context);
81
82 void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen);
83 void ReplaceText(SourceLocation Start, unsigned OrigLength,
84 const char *NewStr, unsigned NewLength);
85
86 // Top Level Driver code.
87 virtual void HandleTopLevelDecl(Decl *D);
88 void HandleDeclInMainFile(Decl *D);
89
90 // Top level
91 Stmt *RewriteFunctionBody(Stmt *S);
92 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
93 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
94
95 // Block specific rewrite rules.
Steve Narofffa9e5a22008-10-04 17:06:23 +000096 std::string SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD=0);
Steve Naroff200902c2008-09-17 00:13:27 +000097
98 void RewriteBlockCall(CallExpr *Exp);
99 void RewriteBlockPointerDecl(NamedDecl *VD);
Steve Naroff3b354d12008-10-04 18:52:47 +0000100 void RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD);
Steve Naroff200902c2008-09-17 00:13:27 +0000101 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
102
Steve Naroff12b2e772008-10-03 20:28:15 +0000103 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
104 const char *funcName, std::string Tag);
Steve Naroff200902c2008-09-17 00:13:27 +0000105 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
106 const char *funcName, std::string Tag);
107 std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag);
108 std::string SynthesizeBlockCall(CallExpr *Exp);
109 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
110 const char *FunName);
111
112 void GetBlockDeclRefExprs(Stmt *S);
113 void GetBlockCallExprs(Stmt *S);
114
115 // We avoid calling Type::isBlockPointerType(), since it operates on the
116 // canonical type. We only care if the top-level type is a closure pointer.
117 bool isBlockPointerType(QualType T) { return isa<BlockPointerType>(T); }
118
119 // FIXME: This predicate seems like it would be useful to add to ASTContext.
120 bool isObjCType(QualType T) {
121 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
122 return false;
123
124 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
125
126 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
127 OCT == Context->getCanonicalType(Context->getObjCClassType()))
128 return true;
129
130 if (const PointerType *PT = OCT->getAsPointerType()) {
131 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
132 isa<ObjCQualifiedIdType>(PT->getPointeeType()))
133 return true;
134 }
135 return false;
136 }
137 // ObjC rewrite methods.
138 void RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl);
139 void RewriteCategoryDecl(ObjCCategoryDecl *CatDecl);
140 void RewriteProtocolDecl(ObjCProtocolDecl *PDecl);
141 void RewriteMethodDecl(ObjCMethodDecl *MDecl);
Steve Naroff21998c02008-09-23 19:24:41 +0000142
143 bool BlockPointerTypeTakesAnyBlockArguments(QualType QT);
Steve Naroffe6283372008-09-24 17:22:34 +0000144 void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen);
Steve Naroff200902c2008-09-17 00:13:27 +0000145};
146
147}
148
149static bool IsHeaderFile(const std::string &Filename) {
150 std::string::size_type DotPos = Filename.rfind('.');
151
152 if (DotPos == std::string::npos) {
153 // no file extension
154 return false;
155 }
156
157 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
158 // C header: .h
159 // C++ header: .hh or .H;
160 return Ext == "h" || Ext == "hh" || Ext == "H";
161}
162
Steve Naroff93c18352008-09-18 14:10:13 +0000163RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile,
164 Diagnostic &D, const LangOptions &LOpts) :
165 Diags(D), LangOpts(LOpts) {
166 IsHeader = IsHeaderFile(inFile);
167 InFileName = inFile;
168 OutFileName = outFile;
169 CurFunctionDef = 0;
170 CurMethodDef = 0;
171 RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
172 "rewriting failed");
173 NoNestedBlockCalls = Diags.getCustomDiagID(Diagnostic::Warning,
174 "Rewrite support for closure calls nested within closure blocks is incomplete");
175}
176
Steve Naroff200902c2008-09-17 00:13:27 +0000177ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
Steve Naroff93c18352008-09-18 14:10:13 +0000178 const std::string& OutFile,
Steve Naroff200902c2008-09-17 00:13:27 +0000179 Diagnostic &Diags,
180 const LangOptions &LangOpts) {
Steve Naroff93c18352008-09-18 14:10:13 +0000181 return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
Steve Naroff200902c2008-09-17 00:13:27 +0000182}
183
184void RewriteBlocks::Initialize(ASTContext &context) {
185 Context = &context;
186 SM = &Context->getSourceManager();
187
188 // Get the ID and start/end of the main file.
189 MainFileID = SM->getMainFileID();
190 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
191 MainFileStart = MainBuf->getBufferStart();
192 MainFileEnd = MainBuf->getBufferEnd();
193
194 Rewrite.setSourceMgr(Context->getSourceManager());
195
Steve Naroff0b060922008-10-02 23:30:43 +0000196 if (IsHeader)
197 Preamble = "#pragma once\n";
198 Preamble += "#ifndef BLOCK_IMPL\n";
199 Preamble += "#define BLOCK_IMPL\n";
200 Preamble += "struct __block_impl {\n";
201 Preamble += " void *isa;\n";
202 Preamble += " int Flags;\n";
203 Preamble += " int Size;\n";
204 Preamble += " void *FuncPtr;\n";
205 Preamble += "};\n";
206 Preamble += "enum {\n";
207 Preamble += " BLOCK_HAS_COPY_DISPOSE = (1<<25),\n";
208 Preamble += " BLOCK_IS_GLOBAL = (1<<28)\n";
209 Preamble += "};\n";
210 if (LangOpts.Microsoft)
211 Preamble += "#define __OBJC_RW_EXTERN extern \"C\" __declspec(dllimport)\n";
212 else
213 Preamble += "#define __OBJC_RW_EXTERN extern\n";
214 Preamble += "// Runtime copy/destroy helper functions\n";
215 Preamble += "__OBJC_RW_EXTERN void _Block_copy_assign(void *, void *);\n";
216 Preamble += "__OBJC_RW_EXTERN void _Block_byref_assign_copy(void *, void *);\n";
217 Preamble += "__OBJC_RW_EXTERN void _Block_destroy(void *);\n";
218 Preamble += "__OBJC_RW_EXTERN void _Block_byref_release(void *);\n";
Steve Naroff20c94e52008-10-03 12:09:49 +0000219 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteGlobalBlock;\n";
220 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n";
Steve Naroff0b060922008-10-02 23:30:43 +0000221 Preamble += "#endif\n";
222
223 InsertText(SourceLocation::getFileLoc(MainFileID, 0),
224 Preamble.c_str(), Preamble.size());
Steve Naroff200902c2008-09-17 00:13:27 +0000225}
226
227void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData,
228 unsigned StrLen)
229{
230 if (!Rewrite.InsertText(Loc, StrData, StrLen))
231 return;
232 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
233}
234
235void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength,
236 const char *NewStr, unsigned NewLength) {
237 if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength))
238 return;
239 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
240}
241
242void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
243 bool haveBlockPtrs = false;
244 for (ObjCMethodDecl::param_iterator I = Method->param_begin(),
245 E = Method->param_end(); I != E; ++I)
246 if (isBlockPointerType((*I)->getType()))
247 haveBlockPtrs = true;
248
249 if (!haveBlockPtrs)
250 return;
251
252 // Do a fuzzy rewrite.
253 // We have 1 or more arguments that have closure pointers.
254 SourceLocation Loc = Method->getLocStart();
255 SourceLocation LocEnd = Method->getLocEnd();
256 const char *startBuf = SM->getCharacterData(Loc);
257 const char *endBuf = SM->getCharacterData(LocEnd);
258
259 const char *methodPtr = startBuf;
Steve Naroffdff3fb22008-10-02 17:12:56 +0000260 std::string Tag = "struct __block_impl *";
Steve Naroff200902c2008-09-17 00:13:27 +0000261
262 while (*methodPtr++ && (methodPtr != endBuf)) {
263 switch (*methodPtr) {
264 case ':':
265 methodPtr++;
266 if (*methodPtr == '(') {
267 const char *scanType = ++methodPtr;
268 bool foundBlockPointer = false;
269 unsigned parenCount = 1;
270
271 while (parenCount) {
272 switch (*scanType) {
273 case '(':
274 parenCount++;
275 break;
276 case ')':
277 parenCount--;
278 break;
279 case '^':
280 foundBlockPointer = true;
281 break;
282 }
283 scanType++;
284 }
285 if (foundBlockPointer) {
286 // advance the location to startArgList.
287 Loc = Loc.getFileLocWithOffset(methodPtr-startBuf);
288 assert((Loc.isValid()) && "Invalid Loc");
289 ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size());
290
291 // Advance startBuf. Since the underlying buffer has changed,
292 // it's very important to advance startBuf (so we can correctly
293 // compute a relative Loc the next time around).
294 startBuf = methodPtr;
295 }
296 // Advance the method ptr to the end of the type.
297 methodPtr = scanType;
298 }
299 break;
300 }
301 }
302 return;
303}
304
305void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
306 for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(),
307 E = ClassDecl->instmeth_end(); I != E; ++I)
308 RewriteMethodDecl(*I);
309 for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(),
310 E = ClassDecl->classmeth_end(); I != E; ++I)
311 RewriteMethodDecl(*I);
312}
313
314void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
315 for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
316 E = CatDecl->instmeth_end(); I != E; ++I)
317 RewriteMethodDecl(*I);
318 for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
319 E = CatDecl->classmeth_end(); I != E; ++I)
320 RewriteMethodDecl(*I);
321}
322
323void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
324 for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
325 E = PDecl->instmeth_end(); I != E; ++I)
326 RewriteMethodDecl(*I);
327 for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
328 E = PDecl->classmeth_end(); I != E; ++I)
329 RewriteMethodDecl(*I);
330}
331
332//===----------------------------------------------------------------------===//
333// Top Level Driver Code
334//===----------------------------------------------------------------------===//
335
336void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
337 // Two cases: either the decl could be in the main file, or it could be in a
338 // #included file. If the former, rewrite it now. If the later, check to see
339 // if we rewrote the #include/#import.
340 SourceLocation Loc = D->getLocation();
341 Loc = SM->getLogicalLoc(Loc);
342
343 // If this is for a builtin, ignore it.
344 if (Loc.isInvalid()) return;
345
346 if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D))
347 RewriteInterfaceDecl(MD);
348 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D))
349 RewriteCategoryDecl(CD);
350 else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
351 RewriteProtocolDecl(PD);
352
353 // If we have a decl in the main file, see if we should rewrite it.
354 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
355 HandleDeclInMainFile(D);
356 return;
357}
358
359std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
360 const char *funcName,
361 std::string Tag) {
362 const FunctionType *AFT = CE->getFunctionType();
363 QualType RT = AFT->getResultType();
Steve Naroff20c94e52008-10-03 12:09:49 +0000364 std::string StructRef = "struct " + Tag;
Steve Naroff200902c2008-09-17 00:13:27 +0000365 std::string S = "static " + RT.getAsString() + " __" +
Steve Naroff0b060922008-10-02 23:30:43 +0000366 funcName + "_" + "block_func_" + utostr(i);
Steve Naroff200902c2008-09-17 00:13:27 +0000367
368 if (isa<FunctionTypeNoProto>(AFT)) {
369 S += "()";
370 } else if (CE->arg_empty()) {
Steve Naroff20c94e52008-10-03 12:09:49 +0000371 S += "(" + StructRef + " *__cself)";
Steve Naroff200902c2008-09-17 00:13:27 +0000372 } else {
373 const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
374 assert(FT && "SynthesizeBlockFunc: No function proto");
375 S += '(';
376 // first add the implicit argument.
Steve Naroff20c94e52008-10-03 12:09:49 +0000377 S += StructRef + " *__cself, ";
Steve Naroff200902c2008-09-17 00:13:27 +0000378 std::string ParamStr;
Steve Naroffb31e2b32008-09-17 18:37:59 +0000379 for (BlockExpr::arg_iterator AI = CE->arg_begin(),
Steve Naroff200902c2008-09-17 00:13:27 +0000380 E = CE->arg_end(); AI != E; ++AI) {
381 if (AI != CE->arg_begin()) S += ", ";
382 ParamStr = (*AI)->getName();
383 (*AI)->getType().getAsStringInternal(ParamStr);
384 S += ParamStr;
385 }
386 if (FT->isVariadic()) {
387 if (!CE->arg_empty()) S += ", ";
388 S += "...";
389 }
390 S += ')';
391 }
392 S += " {\n";
393
394 bool haveByRefDecls = false;
395
396 // Create local declarations to avoid rewriting all closure decl ref exprs.
397 // First, emit a declaration for all "by ref" decls.
398 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
399 E = BlockByRefDecls.end(); I != E; ++I) {
400 // Note: It is not possible to have "by ref" closure pointer decls.
401 haveByRefDecls = true;
402 S += " ";
403 std::string Name = (*I)->getName();
404 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
405 S += Name + " = __cself->" + (*I)->getName() + "; // bound by ref\n";
406 }
407 // Next, emit a declaration for all "by copy" declarations.
408 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
409 E = BlockByCopyDecls.end(); I != E; ++I) {
410 S += " ";
411 std::string Name = (*I)->getName();
412 // Handle nested closure invocation. For example:
413 //
414 // void (^myImportedClosure)(void);
415 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
416 //
417 // void (^anotherClosure)(void);
418 // anotherClosure = ^(void) {
419 // myImportedClosure(); // import and invoke the closure
420 // };
421 //
422 if (isBlockPointerType((*I)->getType()))
Steve Naroffdff3fb22008-10-02 17:12:56 +0000423 S += "struct __block_impl *";
Steve Naroff200902c2008-09-17 00:13:27 +0000424 else
425 (*I)->getType().getAsStringInternal(Name);
426 S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
Steve Naroff200902c2008-09-17 00:13:27 +0000427 }
Steve Narofffa9e5a22008-10-04 17:06:23 +0000428 std::string RewrittenStr = RewrittenBlockExprs[CE];
429 const char *cstr = RewrittenStr.c_str();
430 while (*cstr++ != '{') ;
431 S += cstr;
432 S += "\n";
Steve Naroff200902c2008-09-17 00:13:27 +0000433 return S;
434}
435
Steve Naroff12b2e772008-10-03 20:28:15 +0000436std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
437 const char *funcName,
438 std::string Tag) {
439 std::string StructRef = "struct " + Tag;
440 std::string S = "static void __";
441
442 S += funcName;
443 S += "_block_copy_" + utostr(i);
444 S += "(" + StructRef;
445 S += "*dst, " + StructRef;
446 S += "*src) {";
447 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
448 E = ImportedBlockDecls.end(); I != E; ++I) {
449 S += "_Block_copy_assign(&dst->";
450 S += (*I)->getName();
451 S += ", src->";
452 S += (*I)->getName();
453 S += ");}";
454 }
455 S += "\nstatic void __";
456 S += funcName;
457 S += "_block_dispose_" + utostr(i);
458 S += "(" + StructRef;
459 S += "*src) {";
460 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
461 E = ImportedBlockDecls.end(); I != E; ++I) {
462 S += "_Block_destroy(src->";
463 S += (*I)->getName();
464 S += ");";
465 }
466 S += "}\n";
467 return S;
468}
469
Steve Naroff20c94e52008-10-03 12:09:49 +0000470std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) {
471 std::string S = "struct " + Tag;
472 std::string Constructor = " " + Tag;
473
474 S += " {\n struct __block_impl impl;\n";
475 Constructor += "(void *fp";
Steve Naroff200902c2008-09-17 00:13:27 +0000476
477 GetBlockDeclRefExprs(CE);
478 if (BlockDeclRefs.size()) {
479 // Unique all "by copy" declarations.
480 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
481 if (!BlockDeclRefs[i]->isByRef())
482 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
483 // Unique all "by ref" declarations.
484 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
485 if (BlockDeclRefs[i]->isByRef())
486 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
Steve Naroffa31525d2008-10-04 18:00:11 +0000487
488 // Find any imported blocks...they will need special attention.
489 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
490 if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
491 GetBlockCallExprs(CE);
492 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
493 }
494
Steve Naroff200902c2008-09-17 00:13:27 +0000495 // Output all "by copy" declarations.
496 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
497 E = BlockByCopyDecls.end(); I != E; ++I) {
498 S += " ";
Steve Naroff12b2e772008-10-03 20:28:15 +0000499 std::string FieldName = (*I)->getName();
500 std::string ArgName = "_" + FieldName;
Steve Naroff200902c2008-09-17 00:13:27 +0000501 // Handle nested closure invocation. For example:
502 //
503 // void (^myImportedBlock)(void);
504 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
505 //
506 // void (^anotherBlock)(void);
507 // anotherBlock = ^(void) {
508 // myImportedBlock(); // import and invoke the closure
509 // };
510 //
Steve Naroff12b2e772008-10-03 20:28:15 +0000511 if (isBlockPointerType((*I)->getType())) {
Steve Naroffdff3fb22008-10-02 17:12:56 +0000512 S += "struct __block_impl *";
Steve Naroff12b2e772008-10-03 20:28:15 +0000513 Constructor += ", void *" + ArgName;
514 } else {
515 (*I)->getType().getAsStringInternal(FieldName);
Steve Naroff20c94e52008-10-03 12:09:49 +0000516 (*I)->getType().getAsStringInternal(ArgName);
Steve Naroff12b2e772008-10-03 20:28:15 +0000517 Constructor += ", " + ArgName;
Steve Naroff20c94e52008-10-03 12:09:49 +0000518 }
Steve Naroff12b2e772008-10-03 20:28:15 +0000519 S += FieldName + ";\n";
Steve Naroff200902c2008-09-17 00:13:27 +0000520 }
521 // Output all "by ref" declarations.
522 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
523 E = BlockByRefDecls.end(); I != E; ++I) {
524 S += " ";
Steve Naroff12b2e772008-10-03 20:28:15 +0000525 std::string FieldName = (*I)->getName();
526 std::string ArgName = "_" + FieldName;
527 // Handle nested closure invocation. For example:
528 //
529 // void (^myImportedBlock)(void);
530 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
531 //
532 // void (^anotherBlock)(void);
533 // anotherBlock = ^(void) {
534 // myImportedBlock(); // import and invoke the closure
535 // };
536 //
537 if (isBlockPointerType((*I)->getType())) {
Steve Naroffdff3fb22008-10-02 17:12:56 +0000538 S += "struct __block_impl *";
Steve Naroff12b2e772008-10-03 20:28:15 +0000539 Constructor += ", void *" + ArgName;
540 } else {
541 Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName);
Steve Naroff20c94e52008-10-03 12:09:49 +0000542 Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName);
Steve Naroff12b2e772008-10-03 20:28:15 +0000543 Constructor += ", " + ArgName;
Steve Naroff20c94e52008-10-03 12:09:49 +0000544 }
Steve Naroff12b2e772008-10-03 20:28:15 +0000545 S += FieldName + "; // by ref\n";
Steve Naroff20c94e52008-10-03 12:09:49 +0000546 }
547 // Finish writing the constructor.
548 // FIXME: handle NSConcreteGlobalBlock.
549 Constructor += ", int flags=0) {\n";
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000550 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
Steve Naroff20c94e52008-10-03 12:09:49 +0000551 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
552
553 // Initialize all "by copy" arguments.
554 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
555 E = BlockByCopyDecls.end(); I != E; ++I) {
556 std::string Name = (*I)->getName();
557 Constructor += " ";
Steve Naroff12b2e772008-10-03 20:28:15 +0000558 if (isBlockPointerType((*I)->getType()))
559 Constructor += Name + " = (struct __block_impl *)_";
560 else
561 Constructor += Name + " = _";
Steve Naroff20c94e52008-10-03 12:09:49 +0000562 Constructor += Name + ";\n";
563 }
564 // Initialize all "by ref" arguments.
565 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
566 E = BlockByRefDecls.end(); I != E; ++I) {
567 std::string Name = (*I)->getName();
568 Constructor += " ";
Steve Naroff12b2e772008-10-03 20:28:15 +0000569 if (isBlockPointerType((*I)->getType()))
570 Constructor += Name + " = (struct __block_impl *)_";
571 else
572 Constructor += Name + " = _";
Steve Naroff20c94e52008-10-03 12:09:49 +0000573 Constructor += Name + ";\n";
574 }
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000575 } else {
576 // Finish writing the constructor.
577 // FIXME: handle NSConcreteGlobalBlock.
578 Constructor += ", int flags=0) {\n";
579 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
580 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
Steve Naroff200902c2008-09-17 00:13:27 +0000581 }
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000582 Constructor += " ";
583 Constructor += "}\n";
584 S += Constructor;
Steve Naroff200902c2008-09-17 00:13:27 +0000585 S += "};\n";
586 return S;
587}
588
589void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
590 const char *FunName) {
591 // Insert closures that were part of the function.
592 for (unsigned i = 0; i < Blocks.size(); i++) {
593
Steve Naroff20c94e52008-10-03 12:09:49 +0000594 std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
Steve Naroff200902c2008-09-17 00:13:27 +0000595
596 std::string CI = SynthesizeBlockImpl(Blocks[i], Tag);
597
598 InsertText(FunLocStart, CI.c_str(), CI.size());
Steve Naroff12b2e772008-10-03 20:28:15 +0000599
Steve Naroff200902c2008-09-17 00:13:27 +0000600 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
601
602 InsertText(FunLocStart, CF.c_str(), CF.size());
603
Steve Naroff12b2e772008-10-03 20:28:15 +0000604 if (ImportedBlockDecls.size()) {
605 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
606 InsertText(FunLocStart, HF.c_str(), HF.size());
607 }
608
Steve Naroff200902c2008-09-17 00:13:27 +0000609 BlockDeclRefs.clear();
610 BlockByRefDecls.clear();
611 BlockByCopyDecls.clear();
612 BlockCallExprs.clear();
Steve Naroff12b2e772008-10-03 20:28:15 +0000613 ImportedBlockDecls.clear();
Steve Naroff200902c2008-09-17 00:13:27 +0000614 }
615 Blocks.clear();
Steve Naroffaf234452008-10-04 17:10:02 +0000616 RewrittenBlockExprs.clear();
Steve Naroff200902c2008-09-17 00:13:27 +0000617}
618
619void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
Steve Naroffdeb1aa22008-10-03 00:12:09 +0000620 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
Steve Naroff200902c2008-09-17 00:13:27 +0000621 const char *FuncName = FD->getName();
622
623 SynthesizeBlockLiterals(FunLocStart, FuncName);
624}
625
626void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
627 SourceLocation FunLocStart = MD->getLocStart();
628 std::string FuncName = std::string(MD->getSelector().getName());
629 // Convert colons to underscores.
630 std::string::size_type loc = 0;
631 while ((loc = FuncName.find(":", loc)) != std::string::npos)
632 FuncName.replace(loc, 1, "_");
633
634 SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
635}
636
Steve Naroff200902c2008-09-17 00:13:27 +0000637
638void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
639 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
640 CI != E; ++CI)
641 if (*CI)
642 GetBlockDeclRefExprs(*CI);
643
644 // Handle specific things.
645 if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
646 // FIXME: Handle enums.
647 if (!isa<FunctionDecl>(CDRE->getDecl()))
648 BlockDeclRefs.push_back(CDRE);
649 return;
650}
651
652void RewriteBlocks::GetBlockCallExprs(Stmt *S) {
653 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
654 CI != E; ++CI)
655 if (*CI)
656 GetBlockCallExprs(*CI);
657
658 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
Steve Naroff12b2e772008-10-03 20:28:15 +0000659 if (CE->getCallee()->getType()->isBlockPointerType()) {
Steve Naroff200902c2008-09-17 00:13:27 +0000660 BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
Steve Naroff12b2e772008-10-03 20:28:15 +0000661 }
Steve Naroff200902c2008-09-17 00:13:27 +0000662 }
663 return;
664}
665
Steve Naroff200902c2008-09-17 00:13:27 +0000666std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
667 // Navigate to relevant type information.
Steve Naroffae059092008-09-24 22:46:45 +0000668 const char *closureName = 0;
669 const BlockPointerType *CPT = 0;
Steve Naroff200902c2008-09-17 00:13:27 +0000670
671 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
672 closureName = DRE->getDecl()->getName();
673 CPT = DRE->getType()->getAsBlockPointerType();
674 } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
675 closureName = CDRE->getDecl()->getName();
676 CPT = CDRE->getType()->getAsBlockPointerType();
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000677 } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
678 closureName = MExpr->getMemberDecl()->getName();
679 CPT = MExpr->getType()->getAsBlockPointerType();
Steve Naroff200902c2008-09-17 00:13:27 +0000680 } else {
681 assert(1 && "RewriteBlockClass: Bad type");
682 }
683 assert(CPT && "RewriteBlockClass: Bad type");
684 const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType();
685 assert(FT && "RewriteBlockClass: Bad type");
686 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FT);
687 // FTP will be null for closures that don't take arguments.
688
689 // Build a closure call - start with a paren expr to enforce precedence.
690 std::string BlockCall = "(";
691
692 // Synthesize the cast.
693 BlockCall += "(" + Exp->getType().getAsString() + "(*)";
Steve Naroffdff3fb22008-10-02 17:12:56 +0000694 BlockCall += "(struct __block_impl *";
Steve Naroff200902c2008-09-17 00:13:27 +0000695 if (FTP) {
696 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
697 E = FTP->arg_type_end(); I && (I != E); ++I)
698 BlockCall += ", " + (*I).getAsString();
699 }
700 BlockCall += "))"; // close the argument list and paren expression.
701
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000702 // Invoke the closure. We need to cast it since the declaration type is
703 // bogus (it's a function pointer type)
704 BlockCall += "((struct __block_impl *)";
705 std::string closureExprBufStr;
706 llvm::raw_string_ostream closureExprBuf(closureExprBufStr);
707 Exp->getCallee()->printPretty(closureExprBuf);
708 BlockCall += closureExprBuf.str();
709 BlockCall += ")->FuncPtr)";
Steve Naroff200902c2008-09-17 00:13:27 +0000710
711 // Add the arguments.
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000712 BlockCall += "((struct __block_impl *)";
Steve Naroff57248f32008-10-04 17:45:51 +0000713 BlockCall += closureExprBuf.str();
Steve Naroff200902c2008-09-17 00:13:27 +0000714 for (CallExpr::arg_iterator I = Exp->arg_begin(),
715 E = Exp->arg_end(); I != E; ++I) {
716 std::string syncExprBufS;
717 llvm::raw_string_ostream Buf(syncExprBufS);
718 (*I)->printPretty(Buf);
719 BlockCall += ", " + Buf.str();
720 }
721 return BlockCall;
722}
723
724void RewriteBlocks::RewriteBlockCall(CallExpr *Exp) {
725 std::string BlockCall = SynthesizeBlockCall(Exp);
726
727 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
728 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
729
730 ReplaceText(Exp->getLocStart(), endBuf-startBuf,
731 BlockCall.c_str(), BlockCall.size());
732}
733
Steve Naroff3b354d12008-10-04 18:52:47 +0000734void RewriteBlocks::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
735 // FIXME: Add more elaborate code generation required by the ABI.
736 InsertText(BDRE->getLocStart(), "*", 1);
737}
738
Steve Naroff200902c2008-09-17 00:13:27 +0000739void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
740 SourceLocation DeclLoc = FD->getLocation();
741 unsigned parenCount = 0, nArgs = 0;
742
743 // We have 1 or more arguments that have closure pointers.
744 const char *startBuf = SM->getCharacterData(DeclLoc);
745 const char *startArgList = strchr(startBuf, '(');
746
747 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
748
749 parenCount++;
750 // advance the location to startArgList.
751 DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf+1);
752 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
753
754 const char *topLevelCommaCursor = 0;
755 const char *argPtr = startArgList;
756 bool scannedBlockDecl = false;
Steve Naroffdff3fb22008-10-02 17:12:56 +0000757 std::string Tag = "struct __block_impl *";
Steve Naroff200902c2008-09-17 00:13:27 +0000758
759 while (*argPtr++ && parenCount) {
760 switch (*argPtr) {
761 case '^':
762 scannedBlockDecl = true;
763 break;
764 case '(':
765 parenCount++;
766 break;
767 case ')':
768 parenCount--;
769 if (parenCount == 0) {
770 if (scannedBlockDecl) {
771 // If we are rewriting a definition, don't forget the arg name.
772 if (FD->getBody())
773 Tag += FD->getParamDecl(nArgs)->getName();
774 // The last argument is a closure pointer decl, rewrite it!
775 if (topLevelCommaCursor)
776 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-2, Tag.c_str(), Tag.size());
777 else
778 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
779 scannedBlockDecl = false; // reset.
780 }
781 nArgs++;
782 }
783 break;
784 case ',':
785 if (parenCount == 1) {
786 // Make sure the function takes more than one argument.
787 assert((FD->getNumParams() > 1) && "Rewriter fuzzy parser confused");
788 if (scannedBlockDecl) {
789 // If we are rewriting a definition, don't forget the arg name.
790 if (FD->getBody())
791 Tag += FD->getParamDecl(nArgs)->getName();
792 // The current argument is a closure pointer decl, rewrite it!
793 if (topLevelCommaCursor)
794 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-1, Tag.c_str(), Tag.size());
795 else
796 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
797 scannedBlockDecl = false;
798 }
799 nArgs++;
800 // advance the location to topLevelCommaCursor.
801 if (topLevelCommaCursor)
802 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-topLevelCommaCursor);
803 else
804 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList+1);
805 topLevelCommaCursor = argPtr;
806 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
807 }
808 break;
809 }
810 }
811 return;
812}
813
Steve Naroff21998c02008-09-23 19:24:41 +0000814bool RewriteBlocks::BlockPointerTypeTakesAnyBlockArguments(QualType QT) {
815 const BlockPointerType *BPT = QT->getAsBlockPointerType();
816 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
817 const FunctionTypeProto *FTP = BPT->getPointeeType()->getAsFunctionTypeProto();
818 if (FTP) {
819 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
820 E = FTP->arg_type_end(); I != E; ++I)
821 if (isBlockPointerType(*I))
822 return true;
823 }
824 return false;
825}
826
827void RewriteBlocks::GetExtentOfArgList(const char *Name,
Steve Naroffe6283372008-09-24 17:22:34 +0000828 const char *&LParen, const char *&RParen) {
829 const char *argPtr = strchr(Name, '(');
Steve Naroff21998c02008-09-23 19:24:41 +0000830 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
831
832 LParen = argPtr; // output the start.
833 argPtr++; // skip past the left paren.
834 unsigned parenCount = 1;
835
836 while (*argPtr && parenCount) {
837 switch (*argPtr) {
838 case '(': parenCount++; break;
839 case ')': parenCount--; break;
840 default: break;
841 }
842 if (parenCount) argPtr++;
843 }
844 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
845 RParen = argPtr; // output the end
846}
847
Steve Naroff200902c2008-09-17 00:13:27 +0000848void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
Steve Naroff200902c2008-09-17 00:13:27 +0000849 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
850 RewriteBlockPointerFunctionArgs(FD);
851 return;
Steve Naroff22a0ce52008-09-23 21:15:53 +0000852 }
853 // Handle Variables and Typedefs.
854 SourceLocation DeclLoc = ND->getLocation();
855 QualType DeclT;
856 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
857 DeclT = VD->getType();
858 else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
859 DeclT = TDD->getUnderlyingType();
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000860 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
861 DeclT = FD->getType();
Steve Naroff22a0ce52008-09-23 21:15:53 +0000862 else
863 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
Steve Naroff21998c02008-09-23 19:24:41 +0000864
Steve Naroff22a0ce52008-09-23 21:15:53 +0000865 const char *startBuf = SM->getCharacterData(DeclLoc);
866 const char *endBuf = startBuf;
867 // scan backward (from the decl location) for the end of the previous decl.
868 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
869 startBuf--;
870 assert((*startBuf == '^') &&
871 "RewriteBlockPointerDecl() scan error: no caret");
872 // Replace the '^' with '*', computing a negative offset.
873 DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
874 ReplaceText(DeclLoc, 1, "*", 1);
875
876 if (BlockPointerTypeTakesAnyBlockArguments(DeclT)) {
877 // Replace the '^' with '*' for arguments.
878 DeclLoc = ND->getLocation();
Steve Naroff200902c2008-09-17 00:13:27 +0000879 startBuf = SM->getCharacterData(DeclLoc);
Steve Naroffe6283372008-09-24 17:22:34 +0000880 const char *argListBegin, *argListEnd;
Steve Naroff22a0ce52008-09-23 21:15:53 +0000881 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
882 while (argListBegin < argListEnd) {
883 if (*argListBegin == '^') {
884 SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
885 ReplaceText(CaretLoc, 1, "*", 1);
886 }
887 argListBegin++;
Steve Naroff200902c2008-09-17 00:13:27 +0000888 }
Steve Naroff21998c02008-09-23 19:24:41 +0000889 }
Steve Naroff200902c2008-09-17 00:13:27 +0000890 return;
891}
892
Steve Narofffa9e5a22008-10-04 17:06:23 +0000893std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) {
Steve Naroff200902c2008-09-17 00:13:27 +0000894 Blocks.push_back(Exp);
895 bool haveByRefDecls = false;
896
897 // Add initializers for any closure decl refs.
898 GetBlockDeclRefExprs(Exp);
899 if (BlockDeclRefs.size()) {
900 // Unique all "by copy" declarations.
901 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
902 if (!BlockDeclRefs[i]->isByRef())
903 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
904 // Unique all "by ref" declarations.
905 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
906 if (BlockDeclRefs[i]->isByRef()) {
907 haveByRefDecls = true;
908 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
909 }
910 }
911 std::string FuncName;
912
913 if (CurFunctionDef)
914 FuncName = std::string(CurFunctionDef->getName());
915 else if (CurMethodDef) {
916 FuncName = std::string(CurMethodDef->getSelector().getName());
917 // Convert colons to underscores.
918 std::string::size_type loc = 0;
919 while ((loc = FuncName.find(":", loc)) != std::string::npos)
920 FuncName.replace(loc, 1, "_");
Steve Naroffe506ae22008-10-03 15:38:09 +0000921 } else if (VD)
922 FuncName = std::string(VD->getName());
923
Steve Naroff200902c2008-09-17 00:13:27 +0000924 std::string BlockNumber = utostr(Blocks.size()-1);
925
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000926 std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
Steve Naroff0b060922008-10-02 23:30:43 +0000927 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
Steve Naroff200902c2008-09-17 00:13:27 +0000928
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000929 std::string FunkTypeStr;
930
931 // Get a pointer to the function type so we can cast appropriately.
932 Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr);
933
Steve Naroff200902c2008-09-17 00:13:27 +0000934 // Rewrite the closure block with a compound literal. The first cast is
935 // to prevent warnings from the C compiler.
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000936 std::string Init = "(" + FunkTypeStr;
Steve Naroff200902c2008-09-17 00:13:27 +0000937
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000938 Init += ")&" + Tag;
939
940 // Initialize the block function.
941 Init += "((void*)" + Func;
Steve Naroff200902c2008-09-17 00:13:27 +0000942
943 // Add initializers for any closure decl refs.
944 if (BlockDeclRefs.size()) {
945 // Output all "by copy" declarations.
946 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
947 E = BlockByCopyDecls.end(); I != E; ++I) {
948 Init += ",";
949 if (isObjCType((*I)->getType())) {
950 Init += "[[";
951 Init += (*I)->getName();
952 Init += " retain] autorelease]";
Steve Naroff12b2e772008-10-03 20:28:15 +0000953 } else if (isBlockPointerType((*I)->getType())) {
954 Init += "(void *)";
955 Init += (*I)->getName();
Steve Naroff200902c2008-09-17 00:13:27 +0000956 } else {
957 Init += (*I)->getName();
958 }
959 }
960 // Output all "by ref" declarations.
961 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
962 E = BlockByRefDecls.end(); I != E; ++I) {
963 Init += ",&";
964 Init += (*I)->getName();
965 }
966 }
Steve Naroffaeaf7ef2008-10-03 15:04:50 +0000967 Init += ")";
Steve Naroff200902c2008-09-17 00:13:27 +0000968 BlockDeclRefs.clear();
969 BlockByRefDecls.clear();
970 BlockByCopyDecls.clear();
Steve Naroff12b2e772008-10-03 20:28:15 +0000971 ImportedBlockDecls.clear();
972
Steve Narofffa9e5a22008-10-04 17:06:23 +0000973 return Init;
974}
975
976//===----------------------------------------------------------------------===//
977// Function Body / Expression rewriting
978//===----------------------------------------------------------------------===//
979
980Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
981 // Start by rewriting all children.
982 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
983 CI != E; ++CI)
984 if (*CI) {
985 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
986 Stmt *newStmt = RewriteFunctionBody(*CI);
987 if (newStmt)
988 *CI = newStmt;
989
990 // We've just rewritten the block body in place.
991 // Now we snarf the rewritten text and stash it away for later use.
992 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
993 RewrittenBlockExprs[CBE] = S;
994 std::string Init = SynthesizeBlockInitExpr(CBE);
995 // Do the rewrite, using S.size() which contains the rewritten size.
996 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
997 } else {
998 Stmt *newStmt = RewriteFunctionBody(*CI);
999 if (newStmt)
1000 *CI = newStmt;
1001 }
1002 }
1003 // Handle specific things.
1004 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1005 if (CE->getCallee()->getType()->isBlockPointerType())
1006 RewriteBlockCall(CE);
1007 }
1008 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
1009 ScopedDecl *SD = DS->getDecl();
1010 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
1011 if (isBlockPointerType(ND->getType()))
1012 RewriteBlockPointerDecl(ND);
1013 }
1014 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
1015 if (isBlockPointerType(TD->getUnderlyingType()))
1016 RewriteBlockPointerDecl(TD);
1017 }
1018 }
Steve Naroff3b354d12008-10-04 18:52:47 +00001019 // Handle specific things.
1020 if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
1021 if (BDRE->isByRef())
1022 RewriteBlockDeclRefExpr(BDRE);
1023 }
Steve Narofffa9e5a22008-10-04 17:06:23 +00001024 // Return this stmt unmodified.
1025 return S;
1026}
1027
1028/// HandleDeclInMainFile - This is called for each top-level decl defined in the
1029/// main file of the input.
1030void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
1031 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1032
1033 // Since function prototypes don't have ParmDecl's, we check the function
1034 // prototype. This enables us to rewrite function declarations and
1035 // definitions using the same code.
1036 QualType funcType = FD->getType();
1037
1038 if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
1039 for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(),
1040 E = fproto->arg_type_end(); I && (I != E); ++I)
1041 if (isBlockPointerType(*I)) {
1042 // All the args are checked/rewritten. Don't call twice!
1043 RewriteBlockPointerDecl(FD);
1044 break;
1045 }
1046 }
1047 if (Stmt *Body = FD->getBody()) {
1048 CurFunctionDef = FD;
1049 FD->setBody(RewriteFunctionBody(Body));
1050 // This synthesizes and inserts the block "impl" struct, invoke function,
1051 // and any copy/dispose helper functions.
1052 InsertBlockLiteralsWithinFunction(FD);
1053 CurFunctionDef = 0;
1054 }
1055 return;
1056 }
1057 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
1058 RewriteMethodDecl(MD);
1059 if (Stmt *Body = MD->getBody()) {
1060 CurMethodDef = MD;
1061 RewriteFunctionBody(Body);
1062 InsertBlockLiteralsWithinMethod(MD);
1063 CurMethodDef = 0;
1064 }
1065 }
1066 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
1067 if (isBlockPointerType(VD->getType())) {
1068 RewriteBlockPointerDecl(VD);
1069 if (VD->getInit()) {
1070 if (BlockExpr *CBE = dyn_cast<BlockExpr>(VD->getInit())) {
1071 RewriteFunctionBody(VD->getInit());
1072
1073 // We've just rewritten the block body in place.
1074 // Now we snarf the rewritten text and stash it away for later use.
1075 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1076 RewrittenBlockExprs[CBE] = S;
1077 std::string Init = SynthesizeBlockInitExpr(CBE, VD);
1078 // Do the rewrite, using S.size() which contains the rewritten size.
1079 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1080 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
1081 }
1082 }
1083 }
1084 return;
1085 }
1086 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
1087 if (isBlockPointerType(TD->getUnderlyingType()))
1088 RewriteBlockPointerDecl(TD);
1089 return;
1090 }
1091 if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1092 if (RD->isDefinition()) {
1093 for (RecordDecl::field_const_iterator i = RD->field_begin(),
1094 e = RD->field_end(); i != e; ++i) {
1095 FieldDecl *FD = *i;
1096 if (isBlockPointerType(FD->getType()))
1097 RewriteBlockPointerDecl(FD);
1098 }
1099 }
1100 return;
1101 }
Steve Naroff200902c2008-09-17 00:13:27 +00001102}