blob: 6e119e4492e54b15e1efd2cab7f26e75d3c8821e [file] [log] [blame]
Steve Naroff1c9f81b2008-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 Naroff4e13b762008-10-03 20:28:15 +000052 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
Steve Naroff70f95502008-10-04 17:06:23 +000053
54 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000055
56 // The function/method we are rewriting.
57 FunctionDecl *CurFunctionDef;
58 ObjCMethodDecl *CurMethodDef;
59
60 bool IsHeader;
Steve Naroff13188952008-09-18 14:10:13 +000061 std::string InFileName;
62 std::string OutFileName;
Steve Naroffa0b75cf2008-10-02 23:30:43 +000063
64 std::string Preamble;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000065public:
Steve Naroff13188952008-09-18 14:10:13 +000066 RewriteBlocks(std::string inFile, std::string outFile, Diagnostic &D,
67 const LangOptions &LOpts);
Steve Naroff1c9f81b2008-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 Naroff70f95502008-10-04 17:06:23 +000096 std::string SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD=0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000097
98 void RewriteBlockCall(CallExpr *Exp);
99 void RewriteBlockPointerDecl(NamedDecl *VD);
Steve Naroff5e52b172008-10-04 18:52:47 +0000100 void RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000101 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
102
Steve Naroff4e13b762008-10-03 20:28:15 +0000103 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
104 const char *funcName, std::string Tag);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000105 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
106 const char *funcName, std::string Tag);
Steve Naroffacba0f22008-10-04 23:47:37 +0000107 std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
108 bool hasCopyDisposeHelpers);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000109 std::string SynthesizeBlockCall(CallExpr *Exp);
110 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
111 const char *FunName);
112
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000113 void GetBlockCallExprs(Stmt *S);
Steve Naroffacba0f22008-10-04 23:47:37 +0000114 void GetBlockDeclRefExprs(Stmt *S);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000115
116 // We avoid calling Type::isBlockPointerType(), since it operates on the
117 // canonical type. We only care if the top-level type is a closure pointer.
118 bool isBlockPointerType(QualType T) { return isa<BlockPointerType>(T); }
119
120 // FIXME: This predicate seems like it would be useful to add to ASTContext.
121 bool isObjCType(QualType T) {
122 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
123 return false;
124
125 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
126
127 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
128 OCT == Context->getCanonicalType(Context->getObjCClassType()))
129 return true;
130
131 if (const PointerType *PT = OCT->getAsPointerType()) {
132 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
133 isa<ObjCQualifiedIdType>(PT->getPointeeType()))
134 return true;
135 }
136 return false;
137 }
138 // ObjC rewrite methods.
139 void RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl);
140 void RewriteCategoryDecl(ObjCCategoryDecl *CatDecl);
141 void RewriteProtocolDecl(ObjCProtocolDecl *PDecl);
142 void RewriteMethodDecl(ObjCMethodDecl *MDecl);
Steve Naroffeab5f632008-09-23 19:24:41 +0000143
144 bool BlockPointerTypeTakesAnyBlockArguments(QualType QT);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000145 void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000146};
147
148}
149
150static bool IsHeaderFile(const std::string &Filename) {
151 std::string::size_type DotPos = Filename.rfind('.');
152
153 if (DotPos == std::string::npos) {
154 // no file extension
155 return false;
156 }
157
158 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
159 // C header: .h
160 // C++ header: .hh or .H;
161 return Ext == "h" || Ext == "hh" || Ext == "H";
162}
163
Steve Naroff13188952008-09-18 14:10:13 +0000164RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile,
165 Diagnostic &D, const LangOptions &LOpts) :
166 Diags(D), LangOpts(LOpts) {
167 IsHeader = IsHeaderFile(inFile);
168 InFileName = inFile;
169 OutFileName = outFile;
170 CurFunctionDef = 0;
171 CurMethodDef = 0;
172 RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
173 "rewriting failed");
174 NoNestedBlockCalls = Diags.getCustomDiagID(Diagnostic::Warning,
175 "Rewrite support for closure calls nested within closure blocks is incomplete");
176}
177
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000178ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
Steve Naroff13188952008-09-18 14:10:13 +0000179 const std::string& OutFile,
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000180 Diagnostic &Diags,
181 const LangOptions &LangOpts) {
Steve Naroff13188952008-09-18 14:10:13 +0000182 return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000183}
184
185void RewriteBlocks::Initialize(ASTContext &context) {
186 Context = &context;
187 SM = &Context->getSourceManager();
188
189 // Get the ID and start/end of the main file.
190 MainFileID = SM->getMainFileID();
191 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
192 MainFileStart = MainBuf->getBufferStart();
193 MainFileEnd = MainBuf->getBufferEnd();
194
195 Rewrite.setSourceMgr(Context->getSourceManager());
196
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000197 if (IsHeader)
198 Preamble = "#pragma once\n";
199 Preamble += "#ifndef BLOCK_IMPL\n";
200 Preamble += "#define BLOCK_IMPL\n";
201 Preamble += "struct __block_impl {\n";
202 Preamble += " void *isa;\n";
203 Preamble += " int Flags;\n";
204 Preamble += " int Size;\n";
205 Preamble += " void *FuncPtr;\n";
206 Preamble += "};\n";
207 Preamble += "enum {\n";
208 Preamble += " BLOCK_HAS_COPY_DISPOSE = (1<<25),\n";
209 Preamble += " BLOCK_IS_GLOBAL = (1<<28)\n";
210 Preamble += "};\n";
211 if (LangOpts.Microsoft)
212 Preamble += "#define __OBJC_RW_EXTERN extern \"C\" __declspec(dllimport)\n";
213 else
214 Preamble += "#define __OBJC_RW_EXTERN extern\n";
215 Preamble += "// Runtime copy/destroy helper functions\n";
216 Preamble += "__OBJC_RW_EXTERN void _Block_copy_assign(void *, void *);\n";
217 Preamble += "__OBJC_RW_EXTERN void _Block_byref_assign_copy(void *, void *);\n";
218 Preamble += "__OBJC_RW_EXTERN void _Block_destroy(void *);\n";
219 Preamble += "__OBJC_RW_EXTERN void _Block_byref_release(void *);\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000220 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteGlobalBlock;\n";
221 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n";
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000222 Preamble += "#endif\n";
223
224 InsertText(SourceLocation::getFileLoc(MainFileID, 0),
225 Preamble.c_str(), Preamble.size());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000226}
227
228void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData,
229 unsigned StrLen)
230{
231 if (!Rewrite.InsertText(Loc, StrData, StrLen))
232 return;
233 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
234}
235
236void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength,
237 const char *NewStr, unsigned NewLength) {
238 if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength))
239 return;
240 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
241}
242
243void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
244 bool haveBlockPtrs = false;
245 for (ObjCMethodDecl::param_iterator I = Method->param_begin(),
246 E = Method->param_end(); I != E; ++I)
247 if (isBlockPointerType((*I)->getType()))
248 haveBlockPtrs = true;
249
250 if (!haveBlockPtrs)
251 return;
252
253 // Do a fuzzy rewrite.
254 // We have 1 or more arguments that have closure pointers.
255 SourceLocation Loc = Method->getLocStart();
256 SourceLocation LocEnd = Method->getLocEnd();
257 const char *startBuf = SM->getCharacterData(Loc);
258 const char *endBuf = SM->getCharacterData(LocEnd);
259
260 const char *methodPtr = startBuf;
Steve Naroff8af6a452008-10-02 17:12:56 +0000261 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000262
263 while (*methodPtr++ && (methodPtr != endBuf)) {
264 switch (*methodPtr) {
265 case ':':
266 methodPtr++;
267 if (*methodPtr == '(') {
268 const char *scanType = ++methodPtr;
269 bool foundBlockPointer = false;
270 unsigned parenCount = 1;
271
272 while (parenCount) {
273 switch (*scanType) {
274 case '(':
275 parenCount++;
276 break;
277 case ')':
278 parenCount--;
279 break;
280 case '^':
281 foundBlockPointer = true;
282 break;
283 }
284 scanType++;
285 }
286 if (foundBlockPointer) {
287 // advance the location to startArgList.
288 Loc = Loc.getFileLocWithOffset(methodPtr-startBuf);
289 assert((Loc.isValid()) && "Invalid Loc");
290 ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size());
291
292 // Advance startBuf. Since the underlying buffer has changed,
293 // it's very important to advance startBuf (so we can correctly
294 // compute a relative Loc the next time around).
295 startBuf = methodPtr;
296 }
297 // Advance the method ptr to the end of the type.
298 methodPtr = scanType;
299 }
300 break;
301 }
302 }
303 return;
304}
305
306void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
307 for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(),
308 E = ClassDecl->instmeth_end(); I != E; ++I)
309 RewriteMethodDecl(*I);
310 for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(),
311 E = ClassDecl->classmeth_end(); I != E; ++I)
312 RewriteMethodDecl(*I);
313}
314
315void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
316 for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
317 E = CatDecl->instmeth_end(); I != E; ++I)
318 RewriteMethodDecl(*I);
319 for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
320 E = CatDecl->classmeth_end(); I != E; ++I)
321 RewriteMethodDecl(*I);
322}
323
324void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
325 for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
326 E = PDecl->instmeth_end(); I != E; ++I)
327 RewriteMethodDecl(*I);
328 for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
329 E = PDecl->classmeth_end(); I != E; ++I)
330 RewriteMethodDecl(*I);
331}
332
333//===----------------------------------------------------------------------===//
334// Top Level Driver Code
335//===----------------------------------------------------------------------===//
336
337void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
338 // Two cases: either the decl could be in the main file, or it could be in a
339 // #included file. If the former, rewrite it now. If the later, check to see
340 // if we rewrote the #include/#import.
341 SourceLocation Loc = D->getLocation();
342 Loc = SM->getLogicalLoc(Loc);
343
344 // If this is for a builtin, ignore it.
345 if (Loc.isInvalid()) return;
346
347 if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D))
348 RewriteInterfaceDecl(MD);
349 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D))
350 RewriteCategoryDecl(CD);
351 else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
352 RewriteProtocolDecl(PD);
353
354 // If we have a decl in the main file, see if we should rewrite it.
355 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
356 HandleDeclInMainFile(D);
357 return;
358}
359
360std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
361 const char *funcName,
362 std::string Tag) {
363 const FunctionType *AFT = CE->getFunctionType();
364 QualType RT = AFT->getResultType();
Steve Naroff48a8c612008-10-03 12:09:49 +0000365 std::string StructRef = "struct " + Tag;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000366 std::string S = "static " + RT.getAsString() + " __" +
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000367 funcName + "_" + "block_func_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000368
369 if (isa<FunctionTypeNoProto>(AFT)) {
370 S += "()";
371 } else if (CE->arg_empty()) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000372 S += "(" + StructRef + " *__cself)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000373 } else {
374 const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
375 assert(FT && "SynthesizeBlockFunc: No function proto");
376 S += '(';
377 // first add the implicit argument.
Steve Naroff48a8c612008-10-03 12:09:49 +0000378 S += StructRef + " *__cself, ";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000379 std::string ParamStr;
Steve Naroff9c3c9022008-09-17 18:37:59 +0000380 for (BlockExpr::arg_iterator AI = CE->arg_begin(),
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000381 E = CE->arg_end(); AI != E; ++AI) {
382 if (AI != CE->arg_begin()) S += ", ";
383 ParamStr = (*AI)->getName();
384 (*AI)->getType().getAsStringInternal(ParamStr);
385 S += ParamStr;
386 }
387 if (FT->isVariadic()) {
388 if (!CE->arg_empty()) S += ", ";
389 S += "...";
390 }
391 S += ')';
392 }
393 S += " {\n";
394
395 bool haveByRefDecls = false;
396
397 // Create local declarations to avoid rewriting all closure decl ref exprs.
398 // First, emit a declaration for all "by ref" decls.
399 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
400 E = BlockByRefDecls.end(); I != E; ++I) {
401 // Note: It is not possible to have "by ref" closure pointer decls.
402 haveByRefDecls = true;
403 S += " ";
404 std::string Name = (*I)->getName();
405 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
406 S += Name + " = __cself->" + (*I)->getName() + "; // bound by ref\n";
407 }
408 // Next, emit a declaration for all "by copy" declarations.
409 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
410 E = BlockByCopyDecls.end(); I != E; ++I) {
411 S += " ";
412 std::string Name = (*I)->getName();
413 // Handle nested closure invocation. For example:
414 //
415 // void (^myImportedClosure)(void);
416 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
417 //
418 // void (^anotherClosure)(void);
419 // anotherClosure = ^(void) {
420 // myImportedClosure(); // import and invoke the closure
421 // };
422 //
423 if (isBlockPointerType((*I)->getType()))
Steve Naroff8af6a452008-10-02 17:12:56 +0000424 S += "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000425 else
426 (*I)->getType().getAsStringInternal(Name);
427 S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000428 }
Steve Naroff70f95502008-10-04 17:06:23 +0000429 std::string RewrittenStr = RewrittenBlockExprs[CE];
430 const char *cstr = RewrittenStr.c_str();
431 while (*cstr++ != '{') ;
432 S += cstr;
433 S += "\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000434 return S;
435}
436
Steve Naroff4e13b762008-10-03 20:28:15 +0000437std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
438 const char *funcName,
439 std::string Tag) {
440 std::string StructRef = "struct " + Tag;
441 std::string S = "static void __";
442
443 S += funcName;
444 S += "_block_copy_" + utostr(i);
445 S += "(" + StructRef;
446 S += "*dst, " + StructRef;
447 S += "*src) {";
448 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
449 E = ImportedBlockDecls.end(); I != E; ++I) {
450 S += "_Block_copy_assign(&dst->";
451 S += (*I)->getName();
452 S += ", src->";
453 S += (*I)->getName();
454 S += ");}";
455 }
456 S += "\nstatic void __";
457 S += funcName;
458 S += "_block_dispose_" + utostr(i);
459 S += "(" + StructRef;
460 S += "*src) {";
461 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
462 E = ImportedBlockDecls.end(); I != E; ++I) {
463 S += "_Block_destroy(src->";
464 S += (*I)->getName();
465 S += ");";
466 }
467 S += "}\n";
468 return S;
469}
470
Steve Naroffacba0f22008-10-04 23:47:37 +0000471std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
472 bool hasCopyDisposeHelpers) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000473 std::string S = "struct " + Tag;
474 std::string Constructor = " " + Tag;
475
476 S += " {\n struct __block_impl impl;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000477
478 if (hasCopyDisposeHelpers)
479 S += " void *copy;\n void *dispose;\n";
480
Steve Naroff48a8c612008-10-03 12:09:49 +0000481 Constructor += "(void *fp";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000482
Steve Naroffacba0f22008-10-04 23:47:37 +0000483 if (hasCopyDisposeHelpers)
484 Constructor += ", void *copyHelp, void *disposeHelp";
485
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000486 if (BlockDeclRefs.size()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000487 // Output all "by copy" declarations.
488 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
489 E = BlockByCopyDecls.end(); I != E; ++I) {
490 S += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000491 std::string FieldName = (*I)->getName();
492 std::string ArgName = "_" + FieldName;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000493 // Handle nested closure invocation. For example:
494 //
495 // void (^myImportedBlock)(void);
496 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
497 //
498 // void (^anotherBlock)(void);
499 // anotherBlock = ^(void) {
500 // myImportedBlock(); // import and invoke the closure
501 // };
502 //
Steve Naroff4e13b762008-10-03 20:28:15 +0000503 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000504 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000505 Constructor += ", void *" + ArgName;
506 } else {
507 (*I)->getType().getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000508 (*I)->getType().getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000509 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000510 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000511 S += FieldName + ";\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000512 }
513 // Output all "by ref" declarations.
514 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
515 E = BlockByRefDecls.end(); I != E; ++I) {
516 S += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000517 std::string FieldName = (*I)->getName();
518 std::string ArgName = "_" + FieldName;
519 // Handle nested closure invocation. For example:
520 //
521 // void (^myImportedBlock)(void);
522 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
523 //
524 // void (^anotherBlock)(void);
525 // anotherBlock = ^(void) {
526 // myImportedBlock(); // import and invoke the closure
527 // };
528 //
529 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000530 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000531 Constructor += ", void *" + ArgName;
532 } else {
533 Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000534 Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000535 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000536 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000537 S += FieldName + "; // by ref\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000538 }
539 // Finish writing the constructor.
540 // FIXME: handle NSConcreteGlobalBlock.
541 Constructor += ", int flags=0) {\n";
Steve Naroff83ba14e2008-10-03 15:04:50 +0000542 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
Steve Naroff48a8c612008-10-03 12:09:49 +0000543 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
544
Steve Naroffacba0f22008-10-04 23:47:37 +0000545 if (hasCopyDisposeHelpers)
546 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
547
Steve Naroff48a8c612008-10-03 12:09:49 +0000548 // Initialize all "by copy" arguments.
549 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
550 E = BlockByCopyDecls.end(); I != E; ++I) {
551 std::string Name = (*I)->getName();
552 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000553 if (isBlockPointerType((*I)->getType()))
554 Constructor += Name + " = (struct __block_impl *)_";
555 else
556 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000557 Constructor += Name + ";\n";
558 }
559 // Initialize all "by ref" arguments.
560 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
561 E = BlockByRefDecls.end(); I != E; ++I) {
562 std::string Name = (*I)->getName();
563 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000564 if (isBlockPointerType((*I)->getType()))
565 Constructor += Name + " = (struct __block_impl *)_";
566 else
567 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000568 Constructor += Name + ";\n";
569 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000570 } else {
571 // Finish writing the constructor.
572 // FIXME: handle NSConcreteGlobalBlock.
573 Constructor += ", int flags=0) {\n";
574 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
575 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000576 if (hasCopyDisposeHelpers)
577 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000578 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000579 Constructor += " ";
580 Constructor += "}\n";
581 S += Constructor;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000582 S += "};\n";
583 return S;
584}
585
586void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
587 const char *FunName) {
588 // Insert closures that were part of the function.
589 for (unsigned i = 0; i < Blocks.size(); i++) {
Steve Naroffacba0f22008-10-04 23:47:37 +0000590
591 GetBlockDeclRefExprs(Blocks[i]);
592 if (BlockDeclRefs.size()) {
593 // Unique all "by copy" declarations.
594 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
595 if (!BlockDeclRefs[i]->isByRef())
596 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
597 // Unique all "by ref" declarations.
598 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
599 if (BlockDeclRefs[i]->isByRef())
600 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
601
602 // Find any imported blocks...they will need special attention.
603 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
604 if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
605 GetBlockCallExprs(Blocks[i]);
606 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
607 }
608 }
Steve Naroff48a8c612008-10-03 12:09:49 +0000609 std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000610
Steve Naroffacba0f22008-10-04 23:47:37 +0000611 std::string CI = SynthesizeBlockImpl(Blocks[i], Tag,
612 ImportedBlockDecls.size() > 0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000613
614 InsertText(FunLocStart, CI.c_str(), CI.size());
Steve Naroff4e13b762008-10-03 20:28:15 +0000615
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000616 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
617
618 InsertText(FunLocStart, CF.c_str(), CF.size());
619
Steve Naroff4e13b762008-10-03 20:28:15 +0000620 if (ImportedBlockDecls.size()) {
621 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
622 InsertText(FunLocStart, HF.c_str(), HF.size());
623 }
624
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000625 BlockDeclRefs.clear();
626 BlockByRefDecls.clear();
627 BlockByCopyDecls.clear();
628 BlockCallExprs.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000629 ImportedBlockDecls.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000630 }
631 Blocks.clear();
Steve Naroff8e9216d2008-10-04 17:10:02 +0000632 RewrittenBlockExprs.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000633}
634
635void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
Steve Naroff3ad29e22008-10-03 00:12:09 +0000636 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000637 const char *FuncName = FD->getName();
638
639 SynthesizeBlockLiterals(FunLocStart, FuncName);
640}
641
642void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
643 SourceLocation FunLocStart = MD->getLocStart();
644 std::string FuncName = std::string(MD->getSelector().getName());
645 // Convert colons to underscores.
646 std::string::size_type loc = 0;
647 while ((loc = FuncName.find(":", loc)) != std::string::npos)
648 FuncName.replace(loc, 1, "_");
649
650 SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
651}
652
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000653
654void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
655 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
656 CI != E; ++CI)
657 if (*CI)
658 GetBlockDeclRefExprs(*CI);
659
660 // Handle specific things.
661 if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
662 // FIXME: Handle enums.
663 if (!isa<FunctionDecl>(CDRE->getDecl()))
664 BlockDeclRefs.push_back(CDRE);
665 return;
666}
667
668void RewriteBlocks::GetBlockCallExprs(Stmt *S) {
669 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
670 CI != E; ++CI)
671 if (*CI)
672 GetBlockCallExprs(*CI);
673
674 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
Steve Naroff4e13b762008-10-03 20:28:15 +0000675 if (CE->getCallee()->getType()->isBlockPointerType()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000676 BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
Steve Naroff4e13b762008-10-03 20:28:15 +0000677 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000678 }
679 return;
680}
681
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000682std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
683 // Navigate to relevant type information.
Steve Naroffcc2ece22008-09-24 22:46:45 +0000684 const char *closureName = 0;
685 const BlockPointerType *CPT = 0;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000686
687 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
688 closureName = DRE->getDecl()->getName();
689 CPT = DRE->getType()->getAsBlockPointerType();
690 } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
691 closureName = CDRE->getDecl()->getName();
692 CPT = CDRE->getType()->getAsBlockPointerType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000693 } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
694 closureName = MExpr->getMemberDecl()->getName();
695 CPT = MExpr->getType()->getAsBlockPointerType();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000696 } else {
697 assert(1 && "RewriteBlockClass: Bad type");
698 }
699 assert(CPT && "RewriteBlockClass: Bad type");
700 const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType();
701 assert(FT && "RewriteBlockClass: Bad type");
702 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FT);
703 // FTP will be null for closures that don't take arguments.
704
705 // Build a closure call - start with a paren expr to enforce precedence.
706 std::string BlockCall = "(";
707
708 // Synthesize the cast.
709 BlockCall += "(" + Exp->getType().getAsString() + "(*)";
Steve Naroff8af6a452008-10-02 17:12:56 +0000710 BlockCall += "(struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000711 if (FTP) {
712 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
713 E = FTP->arg_type_end(); I && (I != E); ++I)
714 BlockCall += ", " + (*I).getAsString();
715 }
716 BlockCall += "))"; // close the argument list and paren expression.
717
Steve Naroff83ba14e2008-10-03 15:04:50 +0000718 // Invoke the closure. We need to cast it since the declaration type is
719 // bogus (it's a function pointer type)
720 BlockCall += "((struct __block_impl *)";
721 std::string closureExprBufStr;
722 llvm::raw_string_ostream closureExprBuf(closureExprBufStr);
723 Exp->getCallee()->printPretty(closureExprBuf);
724 BlockCall += closureExprBuf.str();
725 BlockCall += ")->FuncPtr)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000726
727 // Add the arguments.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000728 BlockCall += "((struct __block_impl *)";
Steve Naroffb65a4f12008-10-04 17:45:51 +0000729 BlockCall += closureExprBuf.str();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000730 for (CallExpr::arg_iterator I = Exp->arg_begin(),
731 E = Exp->arg_end(); I != E; ++I) {
732 std::string syncExprBufS;
733 llvm::raw_string_ostream Buf(syncExprBufS);
734 (*I)->printPretty(Buf);
735 BlockCall += ", " + Buf.str();
736 }
737 return BlockCall;
738}
739
740void RewriteBlocks::RewriteBlockCall(CallExpr *Exp) {
741 std::string BlockCall = SynthesizeBlockCall(Exp);
742
743 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
744 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
745
746 ReplaceText(Exp->getLocStart(), endBuf-startBuf,
747 BlockCall.c_str(), BlockCall.size());
748}
749
Steve Naroff5e52b172008-10-04 18:52:47 +0000750void RewriteBlocks::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
751 // FIXME: Add more elaborate code generation required by the ABI.
752 InsertText(BDRE->getLocStart(), "*", 1);
753}
754
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000755void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
756 SourceLocation DeclLoc = FD->getLocation();
757 unsigned parenCount = 0, nArgs = 0;
758
759 // We have 1 or more arguments that have closure pointers.
760 const char *startBuf = SM->getCharacterData(DeclLoc);
761 const char *startArgList = strchr(startBuf, '(');
762
763 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
764
765 parenCount++;
766 // advance the location to startArgList.
767 DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf+1);
768 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
769
770 const char *topLevelCommaCursor = 0;
771 const char *argPtr = startArgList;
772 bool scannedBlockDecl = false;
Steve Naroff8af6a452008-10-02 17:12:56 +0000773 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000774
775 while (*argPtr++ && parenCount) {
776 switch (*argPtr) {
777 case '^':
778 scannedBlockDecl = true;
779 break;
780 case '(':
781 parenCount++;
782 break;
783 case ')':
784 parenCount--;
785 if (parenCount == 0) {
786 if (scannedBlockDecl) {
787 // If we are rewriting a definition, don't forget the arg name.
788 if (FD->getBody())
789 Tag += FD->getParamDecl(nArgs)->getName();
790 // The last argument is a closure pointer decl, rewrite it!
791 if (topLevelCommaCursor)
792 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-2, Tag.c_str(), Tag.size());
793 else
794 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
795 scannedBlockDecl = false; // reset.
796 }
797 nArgs++;
798 }
799 break;
800 case ',':
801 if (parenCount == 1) {
802 // Make sure the function takes more than one argument.
803 assert((FD->getNumParams() > 1) && "Rewriter fuzzy parser confused");
804 if (scannedBlockDecl) {
805 // If we are rewriting a definition, don't forget the arg name.
806 if (FD->getBody())
807 Tag += FD->getParamDecl(nArgs)->getName();
808 // The current argument is a closure pointer decl, rewrite it!
809 if (topLevelCommaCursor)
810 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-1, Tag.c_str(), Tag.size());
811 else
812 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
813 scannedBlockDecl = false;
814 }
815 nArgs++;
816 // advance the location to topLevelCommaCursor.
817 if (topLevelCommaCursor)
818 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-topLevelCommaCursor);
819 else
820 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList+1);
821 topLevelCommaCursor = argPtr;
822 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
823 }
824 break;
825 }
826 }
827 return;
828}
829
Steve Naroffeab5f632008-09-23 19:24:41 +0000830bool RewriteBlocks::BlockPointerTypeTakesAnyBlockArguments(QualType QT) {
831 const BlockPointerType *BPT = QT->getAsBlockPointerType();
832 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
833 const FunctionTypeProto *FTP = BPT->getPointeeType()->getAsFunctionTypeProto();
834 if (FTP) {
835 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
836 E = FTP->arg_type_end(); I != E; ++I)
837 if (isBlockPointerType(*I))
838 return true;
839 }
840 return false;
841}
842
843void RewriteBlocks::GetExtentOfArgList(const char *Name,
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000844 const char *&LParen, const char *&RParen) {
845 const char *argPtr = strchr(Name, '(');
Steve Naroffeab5f632008-09-23 19:24:41 +0000846 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
847
848 LParen = argPtr; // output the start.
849 argPtr++; // skip past the left paren.
850 unsigned parenCount = 1;
851
852 while (*argPtr && parenCount) {
853 switch (*argPtr) {
854 case '(': parenCount++; break;
855 case ')': parenCount--; break;
856 default: break;
857 }
858 if (parenCount) argPtr++;
859 }
860 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
861 RParen = argPtr; // output the end
862}
863
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000864void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000865 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
866 RewriteBlockPointerFunctionArgs(FD);
867 return;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000868 }
869 // Handle Variables and Typedefs.
870 SourceLocation DeclLoc = ND->getLocation();
871 QualType DeclT;
872 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
873 DeclT = VD->getType();
874 else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
875 DeclT = TDD->getUnderlyingType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000876 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
877 DeclT = FD->getType();
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000878 else
879 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
Steve Naroffeab5f632008-09-23 19:24:41 +0000880
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000881 const char *startBuf = SM->getCharacterData(DeclLoc);
882 const char *endBuf = startBuf;
883 // scan backward (from the decl location) for the end of the previous decl.
884 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
885 startBuf--;
886 assert((*startBuf == '^') &&
887 "RewriteBlockPointerDecl() scan error: no caret");
888 // Replace the '^' with '*', computing a negative offset.
889 DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
890 ReplaceText(DeclLoc, 1, "*", 1);
891
892 if (BlockPointerTypeTakesAnyBlockArguments(DeclT)) {
893 // Replace the '^' with '*' for arguments.
894 DeclLoc = ND->getLocation();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000895 startBuf = SM->getCharacterData(DeclLoc);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000896 const char *argListBegin, *argListEnd;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000897 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
898 while (argListBegin < argListEnd) {
899 if (*argListBegin == '^') {
900 SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
901 ReplaceText(CaretLoc, 1, "*", 1);
902 }
903 argListBegin++;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000904 }
Steve Naroffeab5f632008-09-23 19:24:41 +0000905 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000906 return;
907}
908
Steve Naroff70f95502008-10-04 17:06:23 +0000909std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000910 Blocks.push_back(Exp);
911 bool haveByRefDecls = false;
912
913 // Add initializers for any closure decl refs.
914 GetBlockDeclRefExprs(Exp);
915 if (BlockDeclRefs.size()) {
916 // Unique all "by copy" declarations.
917 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
918 if (!BlockDeclRefs[i]->isByRef())
919 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
920 // Unique all "by ref" declarations.
921 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
922 if (BlockDeclRefs[i]->isByRef()) {
923 haveByRefDecls = true;
924 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
925 }
Steve Naroffacba0f22008-10-04 23:47:37 +0000926 // Find any imported blocks...they will need special attention.
927 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
928 if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
929 GetBlockCallExprs(Blocks[i]);
930 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
931 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000932 }
933 std::string FuncName;
934
935 if (CurFunctionDef)
936 FuncName = std::string(CurFunctionDef->getName());
937 else if (CurMethodDef) {
938 FuncName = std::string(CurMethodDef->getSelector().getName());
939 // Convert colons to underscores.
940 std::string::size_type loc = 0;
941 while ((loc = FuncName.find(":", loc)) != std::string::npos)
942 FuncName.replace(loc, 1, "_");
Steve Naroff39622b92008-10-03 15:38:09 +0000943 } else if (VD)
944 FuncName = std::string(VD->getName());
945
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000946 std::string BlockNumber = utostr(Blocks.size()-1);
947
Steve Naroff83ba14e2008-10-03 15:04:50 +0000948 std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000949 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000950
Steve Naroff83ba14e2008-10-03 15:04:50 +0000951 std::string FunkTypeStr;
952
953 // Get a pointer to the function type so we can cast appropriately.
954 Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr);
955
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000956 // Rewrite the closure block with a compound literal. The first cast is
957 // to prevent warnings from the C compiler.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000958 std::string Init = "(" + FunkTypeStr;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000959
Steve Naroff83ba14e2008-10-03 15:04:50 +0000960 Init += ")&" + Tag;
961
962 // Initialize the block function.
963 Init += "((void*)" + Func;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000964
Steve Naroffacba0f22008-10-04 23:47:37 +0000965 if (ImportedBlockDecls.size()) {
966 std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber;
967 Init += ",(void*)" + Buf;
968 Buf = "__" + FuncName + "_block_dispose_" + BlockNumber;
969 Init += ",(void*)" + Buf;
970 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000971 // Add initializers for any closure decl refs.
972 if (BlockDeclRefs.size()) {
973 // Output all "by copy" declarations.
974 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
975 E = BlockByCopyDecls.end(); I != E; ++I) {
976 Init += ",";
977 if (isObjCType((*I)->getType())) {
978 Init += "[[";
979 Init += (*I)->getName();
980 Init += " retain] autorelease]";
Steve Naroff4e13b762008-10-03 20:28:15 +0000981 } else if (isBlockPointerType((*I)->getType())) {
982 Init += "(void *)";
983 Init += (*I)->getName();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000984 } else {
985 Init += (*I)->getName();
986 }
987 }
988 // Output all "by ref" declarations.
989 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
990 E = BlockByRefDecls.end(); I != E; ++I) {
991 Init += ",&";
992 Init += (*I)->getName();
993 }
994 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000995 Init += ")";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000996 BlockDeclRefs.clear();
997 BlockByRefDecls.clear();
998 BlockByCopyDecls.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000999 ImportedBlockDecls.clear();
1000
Steve Naroff70f95502008-10-04 17:06:23 +00001001 return Init;
1002}
1003
1004//===----------------------------------------------------------------------===//
1005// Function Body / Expression rewriting
1006//===----------------------------------------------------------------------===//
1007
1008Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
1009 // Start by rewriting all children.
1010 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
1011 CI != E; ++CI)
1012 if (*CI) {
1013 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
1014 Stmt *newStmt = RewriteFunctionBody(*CI);
1015 if (newStmt)
1016 *CI = newStmt;
1017
1018 // We've just rewritten the block body in place.
1019 // Now we snarf the rewritten text and stash it away for later use.
1020 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1021 RewrittenBlockExprs[CBE] = S;
1022 std::string Init = SynthesizeBlockInitExpr(CBE);
1023 // Do the rewrite, using S.size() which contains the rewritten size.
1024 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1025 } else {
1026 Stmt *newStmt = RewriteFunctionBody(*CI);
1027 if (newStmt)
1028 *CI = newStmt;
1029 }
1030 }
1031 // Handle specific things.
1032 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1033 if (CE->getCallee()->getType()->isBlockPointerType())
1034 RewriteBlockCall(CE);
1035 }
1036 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
1037 ScopedDecl *SD = DS->getDecl();
1038 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
1039 if (isBlockPointerType(ND->getType()))
1040 RewriteBlockPointerDecl(ND);
1041 }
1042 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
1043 if (isBlockPointerType(TD->getUnderlyingType()))
1044 RewriteBlockPointerDecl(TD);
1045 }
1046 }
Steve Naroff5e52b172008-10-04 18:52:47 +00001047 // Handle specific things.
1048 if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
1049 if (BDRE->isByRef())
1050 RewriteBlockDeclRefExpr(BDRE);
1051 }
Steve Naroff70f95502008-10-04 17:06:23 +00001052 // Return this stmt unmodified.
1053 return S;
1054}
1055
1056/// HandleDeclInMainFile - This is called for each top-level decl defined in the
1057/// main file of the input.
1058void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
1059 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1060
1061 // Since function prototypes don't have ParmDecl's, we check the function
1062 // prototype. This enables us to rewrite function declarations and
1063 // definitions using the same code.
1064 QualType funcType = FD->getType();
1065
1066 if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
1067 for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(),
1068 E = fproto->arg_type_end(); I && (I != E); ++I)
1069 if (isBlockPointerType(*I)) {
1070 // All the args are checked/rewritten. Don't call twice!
1071 RewriteBlockPointerDecl(FD);
1072 break;
1073 }
1074 }
1075 if (Stmt *Body = FD->getBody()) {
1076 CurFunctionDef = FD;
1077 FD->setBody(RewriteFunctionBody(Body));
1078 // This synthesizes and inserts the block "impl" struct, invoke function,
1079 // and any copy/dispose helper functions.
1080 InsertBlockLiteralsWithinFunction(FD);
1081 CurFunctionDef = 0;
1082 }
1083 return;
1084 }
1085 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
1086 RewriteMethodDecl(MD);
1087 if (Stmt *Body = MD->getBody()) {
1088 CurMethodDef = MD;
1089 RewriteFunctionBody(Body);
1090 InsertBlockLiteralsWithinMethod(MD);
1091 CurMethodDef = 0;
1092 }
1093 }
1094 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
1095 if (isBlockPointerType(VD->getType())) {
1096 RewriteBlockPointerDecl(VD);
1097 if (VD->getInit()) {
1098 if (BlockExpr *CBE = dyn_cast<BlockExpr>(VD->getInit())) {
1099 RewriteFunctionBody(VD->getInit());
1100
1101 // We've just rewritten the block body in place.
1102 // Now we snarf the rewritten text and stash it away for later use.
1103 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1104 RewrittenBlockExprs[CBE] = S;
1105 std::string Init = SynthesizeBlockInitExpr(CBE, VD);
1106 // Do the rewrite, using S.size() which contains the rewritten size.
1107 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1108 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
1109 }
1110 }
1111 }
1112 return;
1113 }
1114 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
1115 if (isBlockPointerType(TD->getUnderlyingType()))
1116 RewriteBlockPointerDecl(TD);
1117 return;
1118 }
1119 if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1120 if (RD->isDefinition()) {
1121 for (RecordDecl::field_const_iterator i = RD->field_begin(),
1122 e = RD->field_end(); i != e; ++i) {
1123 FieldDecl *FD = *i;
1124 if (isBlockPointerType(FD->getType()))
1125 RewriteBlockPointerDecl(FD);
1126 }
1127 }
1128 return;
1129 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001130}