blob: 83bc4280c89ecb85f8e017aa8de1dc847e12ce59 [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;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000037
38 ASTContext *Context;
39 SourceManager *SM;
40 unsigned MainFileID;
41 const char *MainFileStart, *MainFileEnd;
42
43 // Block expressions.
44 llvm::SmallVector<BlockExpr *, 32> Blocks;
45 llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
46 llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs;
47
48 // Block related declarations.
49 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
50 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
Steve Naroff4e13b762008-10-03 20:28:15 +000051 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
Steve Naroff70f95502008-10-04 17:06:23 +000052
53 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000054
55 // The function/method we are rewriting.
56 FunctionDecl *CurFunctionDef;
57 ObjCMethodDecl *CurMethodDef;
58
59 bool IsHeader;
Steve Naroff13188952008-09-18 14:10:13 +000060 std::string InFileName;
61 std::string OutFileName;
Steve Naroffa0b75cf2008-10-02 23:30:43 +000062
63 std::string Preamble;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000064public:
Steve Naroff13188952008-09-18 14:10:13 +000065 RewriteBlocks(std::string inFile, std::string outFile, Diagnostic &D,
66 const LangOptions &LOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000067 ~RewriteBlocks() {
68 // Get the buffer corresponding to MainFileID.
69 // If we haven't changed it, then we are done.
70 if (const RewriteBuffer *RewriteBuf =
71 Rewrite.getRewriteBufferFor(MainFileID)) {
72 std::string S(RewriteBuf->begin(), RewriteBuf->end());
73 printf("%s\n", S.c_str());
74 } else {
75 printf("No changes\n");
76 }
77 }
78
79 void Initialize(ASTContext &context);
80
81 void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen);
82 void ReplaceText(SourceLocation Start, unsigned OrigLength,
83 const char *NewStr, unsigned NewLength);
84
85 // Top Level Driver code.
86 virtual void HandleTopLevelDecl(Decl *D);
87 void HandleDeclInMainFile(Decl *D);
88
89 // Top level
90 Stmt *RewriteFunctionBody(Stmt *S);
91 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
92 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
93
94 // Block specific rewrite rules.
Steve Naroff70f95502008-10-04 17:06:23 +000095 std::string SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD=0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000096
97 void RewriteBlockCall(CallExpr *Exp);
98 void RewriteBlockPointerDecl(NamedDecl *VD);
Steve Naroff5e52b172008-10-04 18:52:47 +000099 void RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000100 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
101
Steve Naroff4e13b762008-10-03 20:28:15 +0000102 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
103 const char *funcName, std::string Tag);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000104 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
105 const char *funcName, std::string Tag);
Steve Naroffacba0f22008-10-04 23:47:37 +0000106 std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
107 bool hasCopyDisposeHelpers);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000108 std::string SynthesizeBlockCall(CallExpr *Exp);
109 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
110 const char *FunName);
111
Steve Naroffd3f77902008-10-05 00:06:12 +0000112 void CollectBlockDeclRefInfo(BlockExpr *Exp);
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");
Steve Naroff13188952008-09-18 14:10:13 +0000174}
175
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000176ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
Steve Naroff13188952008-09-18 14:10:13 +0000177 const std::string& OutFile,
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000178 Diagnostic &Diags,
179 const LangOptions &LangOpts) {
Steve Naroff13188952008-09-18 14:10:13 +0000180 return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000181}
182
183void RewriteBlocks::Initialize(ASTContext &context) {
184 Context = &context;
185 SM = &Context->getSourceManager();
186
187 // Get the ID and start/end of the main file.
188 MainFileID = SM->getMainFileID();
189 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
190 MainFileStart = MainBuf->getBufferStart();
191 MainFileEnd = MainBuf->getBufferEnd();
192
193 Rewrite.setSourceMgr(Context->getSourceManager());
194
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000195 if (IsHeader)
196 Preamble = "#pragma once\n";
197 Preamble += "#ifndef BLOCK_IMPL\n";
198 Preamble += "#define BLOCK_IMPL\n";
199 Preamble += "struct __block_impl {\n";
200 Preamble += " void *isa;\n";
201 Preamble += " int Flags;\n";
202 Preamble += " int Size;\n";
203 Preamble += " void *FuncPtr;\n";
204 Preamble += "};\n";
205 Preamble += "enum {\n";
206 Preamble += " BLOCK_HAS_COPY_DISPOSE = (1<<25),\n";
207 Preamble += " BLOCK_IS_GLOBAL = (1<<28)\n";
208 Preamble += "};\n";
209 if (LangOpts.Microsoft)
210 Preamble += "#define __OBJC_RW_EXTERN extern \"C\" __declspec(dllimport)\n";
211 else
212 Preamble += "#define __OBJC_RW_EXTERN extern\n";
213 Preamble += "// Runtime copy/destroy helper functions\n";
214 Preamble += "__OBJC_RW_EXTERN void _Block_copy_assign(void *, void *);\n";
215 Preamble += "__OBJC_RW_EXTERN void _Block_byref_assign_copy(void *, void *);\n";
216 Preamble += "__OBJC_RW_EXTERN void _Block_destroy(void *);\n";
217 Preamble += "__OBJC_RW_EXTERN void _Block_byref_release(void *);\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000218 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteGlobalBlock;\n";
219 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n";
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000220 Preamble += "#endif\n";
221
222 InsertText(SourceLocation::getFileLoc(MainFileID, 0),
223 Preamble.c_str(), Preamble.size());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000224}
225
226void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData,
227 unsigned StrLen)
228{
229 if (!Rewrite.InsertText(Loc, StrData, StrLen))
230 return;
231 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
232}
233
234void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength,
235 const char *NewStr, unsigned NewLength) {
236 if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength))
237 return;
238 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
239}
240
241void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
242 bool haveBlockPtrs = false;
243 for (ObjCMethodDecl::param_iterator I = Method->param_begin(),
244 E = Method->param_end(); I != E; ++I)
245 if (isBlockPointerType((*I)->getType()))
246 haveBlockPtrs = true;
247
248 if (!haveBlockPtrs)
249 return;
250
251 // Do a fuzzy rewrite.
252 // We have 1 or more arguments that have closure pointers.
253 SourceLocation Loc = Method->getLocStart();
254 SourceLocation LocEnd = Method->getLocEnd();
255 const char *startBuf = SM->getCharacterData(Loc);
256 const char *endBuf = SM->getCharacterData(LocEnd);
257
258 const char *methodPtr = startBuf;
Steve Naroff8af6a452008-10-02 17:12:56 +0000259 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000260
261 while (*methodPtr++ && (methodPtr != endBuf)) {
262 switch (*methodPtr) {
263 case ':':
264 methodPtr++;
265 if (*methodPtr == '(') {
266 const char *scanType = ++methodPtr;
267 bool foundBlockPointer = false;
268 unsigned parenCount = 1;
269
270 while (parenCount) {
271 switch (*scanType) {
272 case '(':
273 parenCount++;
274 break;
275 case ')':
276 parenCount--;
277 break;
278 case '^':
279 foundBlockPointer = true;
280 break;
281 }
282 scanType++;
283 }
284 if (foundBlockPointer) {
285 // advance the location to startArgList.
286 Loc = Loc.getFileLocWithOffset(methodPtr-startBuf);
287 assert((Loc.isValid()) && "Invalid Loc");
288 ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size());
289
290 // Advance startBuf. Since the underlying buffer has changed,
291 // it's very important to advance startBuf (so we can correctly
292 // compute a relative Loc the next time around).
293 startBuf = methodPtr;
294 }
295 // Advance the method ptr to the end of the type.
296 methodPtr = scanType;
297 }
298 break;
299 }
300 }
301 return;
302}
303
304void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
305 for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(),
306 E = ClassDecl->instmeth_end(); I != E; ++I)
307 RewriteMethodDecl(*I);
308 for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(),
309 E = ClassDecl->classmeth_end(); I != E; ++I)
310 RewriteMethodDecl(*I);
311}
312
313void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
314 for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
315 E = CatDecl->instmeth_end(); I != E; ++I)
316 RewriteMethodDecl(*I);
317 for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
318 E = CatDecl->classmeth_end(); I != E; ++I)
319 RewriteMethodDecl(*I);
320}
321
322void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
323 for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
324 E = PDecl->instmeth_end(); I != E; ++I)
325 RewriteMethodDecl(*I);
326 for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
327 E = PDecl->classmeth_end(); I != E; ++I)
328 RewriteMethodDecl(*I);
329}
330
331//===----------------------------------------------------------------------===//
332// Top Level Driver Code
333//===----------------------------------------------------------------------===//
334
335void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
336 // Two cases: either the decl could be in the main file, or it could be in a
337 // #included file. If the former, rewrite it now. If the later, check to see
338 // if we rewrote the #include/#import.
339 SourceLocation Loc = D->getLocation();
340 Loc = SM->getLogicalLoc(Loc);
341
342 // If this is for a builtin, ignore it.
343 if (Loc.isInvalid()) return;
344
345 if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D))
346 RewriteInterfaceDecl(MD);
347 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D))
348 RewriteCategoryDecl(CD);
349 else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
350 RewriteProtocolDecl(PD);
351
352 // If we have a decl in the main file, see if we should rewrite it.
353 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
354 HandleDeclInMainFile(D);
355 return;
356}
357
358std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
359 const char *funcName,
360 std::string Tag) {
361 const FunctionType *AFT = CE->getFunctionType();
362 QualType RT = AFT->getResultType();
Steve Naroff48a8c612008-10-03 12:09:49 +0000363 std::string StructRef = "struct " + Tag;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000364 std::string S = "static " + RT.getAsString() + " __" +
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000365 funcName + "_" + "block_func_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000366
367 if (isa<FunctionTypeNoProto>(AFT)) {
368 S += "()";
369 } else if (CE->arg_empty()) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000370 S += "(" + StructRef + " *__cself)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000371 } else {
372 const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
373 assert(FT && "SynthesizeBlockFunc: No function proto");
374 S += '(';
375 // first add the implicit argument.
Steve Naroff48a8c612008-10-03 12:09:49 +0000376 S += StructRef + " *__cself, ";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000377 std::string ParamStr;
Steve Naroff9c3c9022008-09-17 18:37:59 +0000378 for (BlockExpr::arg_iterator AI = CE->arg_begin(),
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000379 E = CE->arg_end(); AI != E; ++AI) {
380 if (AI != CE->arg_begin()) S += ", ";
381 ParamStr = (*AI)->getName();
382 (*AI)->getType().getAsStringInternal(ParamStr);
383 S += ParamStr;
384 }
385 if (FT->isVariadic()) {
386 if (!CE->arg_empty()) S += ", ";
387 S += "...";
388 }
389 S += ')';
390 }
391 S += " {\n";
392
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000393 // Create local declarations to avoid rewriting all closure decl ref exprs.
394 // First, emit a declaration for all "by ref" decls.
395 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
396 E = BlockByRefDecls.end(); I != E; ++I) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000397 S += " ";
398 std::string Name = (*I)->getName();
399 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
400 S += Name + " = __cself->" + (*I)->getName() + "; // bound by ref\n";
401 }
402 // Next, emit a declaration for all "by copy" declarations.
403 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
404 E = BlockByCopyDecls.end(); I != E; ++I) {
405 S += " ";
406 std::string Name = (*I)->getName();
407 // Handle nested closure invocation. For example:
408 //
409 // void (^myImportedClosure)(void);
410 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
411 //
412 // void (^anotherClosure)(void);
413 // anotherClosure = ^(void) {
414 // myImportedClosure(); // import and invoke the closure
415 // };
416 //
417 if (isBlockPointerType((*I)->getType()))
Steve Naroff8af6a452008-10-02 17:12:56 +0000418 S += "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000419 else
420 (*I)->getType().getAsStringInternal(Name);
421 S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000422 }
Steve Naroff70f95502008-10-04 17:06:23 +0000423 std::string RewrittenStr = RewrittenBlockExprs[CE];
424 const char *cstr = RewrittenStr.c_str();
425 while (*cstr++ != '{') ;
426 S += cstr;
427 S += "\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000428 return S;
429}
430
Steve Naroff4e13b762008-10-03 20:28:15 +0000431std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
432 const char *funcName,
433 std::string Tag) {
434 std::string StructRef = "struct " + Tag;
435 std::string S = "static void __";
436
437 S += funcName;
438 S += "_block_copy_" + utostr(i);
439 S += "(" + StructRef;
440 S += "*dst, " + StructRef;
441 S += "*src) {";
442 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
443 E = ImportedBlockDecls.end(); I != E; ++I) {
444 S += "_Block_copy_assign(&dst->";
445 S += (*I)->getName();
446 S += ", src->";
447 S += (*I)->getName();
448 S += ");}";
449 }
450 S += "\nstatic void __";
451 S += funcName;
452 S += "_block_dispose_" + utostr(i);
453 S += "(" + StructRef;
454 S += "*src) {";
455 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
456 E = ImportedBlockDecls.end(); I != E; ++I) {
457 S += "_Block_destroy(src->";
458 S += (*I)->getName();
459 S += ");";
460 }
461 S += "}\n";
462 return S;
463}
464
Steve Naroffacba0f22008-10-04 23:47:37 +0000465std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
466 bool hasCopyDisposeHelpers) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000467 std::string S = "struct " + Tag;
468 std::string Constructor = " " + Tag;
469
470 S += " {\n struct __block_impl impl;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000471
472 if (hasCopyDisposeHelpers)
473 S += " void *copy;\n void *dispose;\n";
474
Steve Naroff48a8c612008-10-03 12:09:49 +0000475 Constructor += "(void *fp";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000476
Steve Naroffacba0f22008-10-04 23:47:37 +0000477 if (hasCopyDisposeHelpers)
478 Constructor += ", void *copyHelp, void *disposeHelp";
479
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000480 if (BlockDeclRefs.size()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000481 // Output all "by copy" declarations.
482 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
483 E = BlockByCopyDecls.end(); I != E; ++I) {
484 S += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000485 std::string FieldName = (*I)->getName();
486 std::string ArgName = "_" + FieldName;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000487 // Handle nested closure invocation. For example:
488 //
489 // void (^myImportedBlock)(void);
490 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
491 //
492 // void (^anotherBlock)(void);
493 // anotherBlock = ^(void) {
494 // myImportedBlock(); // import and invoke the closure
495 // };
496 //
Steve Naroff4e13b762008-10-03 20:28:15 +0000497 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000498 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000499 Constructor += ", void *" + ArgName;
500 } else {
501 (*I)->getType().getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000502 (*I)->getType().getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000503 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000504 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000505 S += FieldName + ";\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000506 }
507 // Output all "by ref" declarations.
508 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
509 E = BlockByRefDecls.end(); I != E; ++I) {
510 S += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000511 std::string FieldName = (*I)->getName();
512 std::string ArgName = "_" + FieldName;
513 // Handle nested closure invocation. For example:
514 //
515 // void (^myImportedBlock)(void);
516 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
517 //
518 // void (^anotherBlock)(void);
519 // anotherBlock = ^(void) {
520 // myImportedBlock(); // import and invoke the closure
521 // };
522 //
523 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000524 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000525 Constructor += ", void *" + ArgName;
526 } else {
527 Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000528 Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000529 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000530 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000531 S += FieldName + "; // by ref\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000532 }
533 // Finish writing the constructor.
534 // FIXME: handle NSConcreteGlobalBlock.
535 Constructor += ", int flags=0) {\n";
Steve Naroff83ba14e2008-10-03 15:04:50 +0000536 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
Steve Naroff48a8c612008-10-03 12:09:49 +0000537 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
538
Steve Naroffacba0f22008-10-04 23:47:37 +0000539 if (hasCopyDisposeHelpers)
540 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
541
Steve Naroff48a8c612008-10-03 12:09:49 +0000542 // Initialize all "by copy" arguments.
543 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
544 E = BlockByCopyDecls.end(); I != E; ++I) {
545 std::string Name = (*I)->getName();
546 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000547 if (isBlockPointerType((*I)->getType()))
548 Constructor += Name + " = (struct __block_impl *)_";
549 else
550 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000551 Constructor += Name + ";\n";
552 }
553 // Initialize all "by ref" arguments.
554 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
555 E = BlockByRefDecls.end(); I != E; ++I) {
556 std::string Name = (*I)->getName();
557 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000558 if (isBlockPointerType((*I)->getType()))
559 Constructor += Name + " = (struct __block_impl *)_";
560 else
561 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000562 Constructor += Name + ";\n";
563 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000564 } else {
565 // Finish writing the constructor.
566 // FIXME: handle NSConcreteGlobalBlock.
567 Constructor += ", int flags=0) {\n";
568 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
569 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000570 if (hasCopyDisposeHelpers)
571 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000572 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000573 Constructor += " ";
574 Constructor += "}\n";
575 S += Constructor;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000576 S += "};\n";
577 return S;
578}
579
580void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
581 const char *FunName) {
582 // Insert closures that were part of the function.
583 for (unsigned i = 0; i < Blocks.size(); i++) {
Steve Naroffacba0f22008-10-04 23:47:37 +0000584
Steve Naroffd3f77902008-10-05 00:06:12 +0000585 CollectBlockDeclRefInfo(Blocks[i]);
586
Steve Naroff48a8c612008-10-03 12:09:49 +0000587 std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000588
Steve Naroffacba0f22008-10-04 23:47:37 +0000589 std::string CI = SynthesizeBlockImpl(Blocks[i], Tag,
590 ImportedBlockDecls.size() > 0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000591
592 InsertText(FunLocStart, CI.c_str(), CI.size());
Steve Naroff4e13b762008-10-03 20:28:15 +0000593
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000594 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
595
596 InsertText(FunLocStart, CF.c_str(), CF.size());
597
Steve Naroff4e13b762008-10-03 20:28:15 +0000598 if (ImportedBlockDecls.size()) {
599 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
600 InsertText(FunLocStart, HF.c_str(), HF.size());
601 }
602
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000603 BlockDeclRefs.clear();
604 BlockByRefDecls.clear();
605 BlockByCopyDecls.clear();
606 BlockCallExprs.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000607 ImportedBlockDecls.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000608 }
609 Blocks.clear();
Steve Naroff8e9216d2008-10-04 17:10:02 +0000610 RewrittenBlockExprs.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000611}
612
613void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
Steve Naroff3ad29e22008-10-03 00:12:09 +0000614 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000615 const char *FuncName = FD->getName();
616
617 SynthesizeBlockLiterals(FunLocStart, FuncName);
618}
619
620void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
621 SourceLocation FunLocStart = MD->getLocStart();
622 std::string FuncName = std::string(MD->getSelector().getName());
623 // Convert colons to underscores.
624 std::string::size_type loc = 0;
625 while ((loc = FuncName.find(":", loc)) != std::string::npos)
626 FuncName.replace(loc, 1, "_");
627
628 SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
629}
630
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000631
632void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
633 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
634 CI != E; ++CI)
635 if (*CI)
636 GetBlockDeclRefExprs(*CI);
637
638 // Handle specific things.
639 if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
640 // FIXME: Handle enums.
641 if (!isa<FunctionDecl>(CDRE->getDecl()))
642 BlockDeclRefs.push_back(CDRE);
643 return;
644}
645
646void RewriteBlocks::GetBlockCallExprs(Stmt *S) {
647 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
648 CI != E; ++CI)
649 if (*CI)
650 GetBlockCallExprs(*CI);
651
652 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
Steve Naroff4e13b762008-10-03 20:28:15 +0000653 if (CE->getCallee()->getType()->isBlockPointerType()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000654 BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
Steve Naroff4e13b762008-10-03 20:28:15 +0000655 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000656 }
657 return;
658}
659
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000660std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
661 // Navigate to relevant type information.
Steve Naroffcc2ece22008-09-24 22:46:45 +0000662 const char *closureName = 0;
663 const BlockPointerType *CPT = 0;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000664
665 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
666 closureName = DRE->getDecl()->getName();
667 CPT = DRE->getType()->getAsBlockPointerType();
668 } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
669 closureName = CDRE->getDecl()->getName();
670 CPT = CDRE->getType()->getAsBlockPointerType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000671 } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
672 closureName = MExpr->getMemberDecl()->getName();
673 CPT = MExpr->getType()->getAsBlockPointerType();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000674 } else {
675 assert(1 && "RewriteBlockClass: Bad type");
676 }
677 assert(CPT && "RewriteBlockClass: Bad type");
678 const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType();
679 assert(FT && "RewriteBlockClass: Bad type");
680 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FT);
681 // FTP will be null for closures that don't take arguments.
682
683 // Build a closure call - start with a paren expr to enforce precedence.
684 std::string BlockCall = "(";
685
686 // Synthesize the cast.
687 BlockCall += "(" + Exp->getType().getAsString() + "(*)";
Steve Naroff8af6a452008-10-02 17:12:56 +0000688 BlockCall += "(struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000689 if (FTP) {
690 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
691 E = FTP->arg_type_end(); I && (I != E); ++I)
692 BlockCall += ", " + (*I).getAsString();
693 }
694 BlockCall += "))"; // close the argument list and paren expression.
695
Steve Naroff83ba14e2008-10-03 15:04:50 +0000696 // Invoke the closure. We need to cast it since the declaration type is
697 // bogus (it's a function pointer type)
698 BlockCall += "((struct __block_impl *)";
699 std::string closureExprBufStr;
700 llvm::raw_string_ostream closureExprBuf(closureExprBufStr);
701 Exp->getCallee()->printPretty(closureExprBuf);
702 BlockCall += closureExprBuf.str();
703 BlockCall += ")->FuncPtr)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000704
705 // Add the arguments.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000706 BlockCall += "((struct __block_impl *)";
Steve Naroffb65a4f12008-10-04 17:45:51 +0000707 BlockCall += closureExprBuf.str();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000708 for (CallExpr::arg_iterator I = Exp->arg_begin(),
709 E = Exp->arg_end(); I != E; ++I) {
710 std::string syncExprBufS;
711 llvm::raw_string_ostream Buf(syncExprBufS);
712 (*I)->printPretty(Buf);
713 BlockCall += ", " + Buf.str();
714 }
715 return BlockCall;
716}
717
718void RewriteBlocks::RewriteBlockCall(CallExpr *Exp) {
719 std::string BlockCall = SynthesizeBlockCall(Exp);
720
721 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
722 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
723
724 ReplaceText(Exp->getLocStart(), endBuf-startBuf,
725 BlockCall.c_str(), BlockCall.size());
726}
727
Steve Naroff5e52b172008-10-04 18:52:47 +0000728void RewriteBlocks::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
729 // FIXME: Add more elaborate code generation required by the ABI.
730 InsertText(BDRE->getLocStart(), "*", 1);
731}
732
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000733void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
734 SourceLocation DeclLoc = FD->getLocation();
735 unsigned parenCount = 0, nArgs = 0;
736
737 // We have 1 or more arguments that have closure pointers.
738 const char *startBuf = SM->getCharacterData(DeclLoc);
739 const char *startArgList = strchr(startBuf, '(');
740
741 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
742
743 parenCount++;
744 // advance the location to startArgList.
745 DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf+1);
746 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
747
748 const char *topLevelCommaCursor = 0;
749 const char *argPtr = startArgList;
750 bool scannedBlockDecl = false;
Steve Naroff8af6a452008-10-02 17:12:56 +0000751 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000752
753 while (*argPtr++ && parenCount) {
754 switch (*argPtr) {
755 case '^':
756 scannedBlockDecl = true;
757 break;
758 case '(':
759 parenCount++;
760 break;
761 case ')':
762 parenCount--;
763 if (parenCount == 0) {
764 if (scannedBlockDecl) {
765 // If we are rewriting a definition, don't forget the arg name.
766 if (FD->getBody())
767 Tag += FD->getParamDecl(nArgs)->getName();
768 // The last argument is a closure pointer decl, rewrite it!
769 if (topLevelCommaCursor)
770 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-2, Tag.c_str(), Tag.size());
771 else
772 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
773 scannedBlockDecl = false; // reset.
774 }
775 nArgs++;
776 }
777 break;
778 case ',':
779 if (parenCount == 1) {
780 // Make sure the function takes more than one argument.
781 assert((FD->getNumParams() > 1) && "Rewriter fuzzy parser confused");
782 if (scannedBlockDecl) {
783 // If we are rewriting a definition, don't forget the arg name.
784 if (FD->getBody())
785 Tag += FD->getParamDecl(nArgs)->getName();
786 // The current argument is a closure pointer decl, rewrite it!
787 if (topLevelCommaCursor)
788 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-1, Tag.c_str(), Tag.size());
789 else
790 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
791 scannedBlockDecl = false;
792 }
793 nArgs++;
794 // advance the location to topLevelCommaCursor.
795 if (topLevelCommaCursor)
796 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-topLevelCommaCursor);
797 else
798 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList+1);
799 topLevelCommaCursor = argPtr;
800 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
801 }
802 break;
803 }
804 }
805 return;
806}
807
Steve Naroffeab5f632008-09-23 19:24:41 +0000808bool RewriteBlocks::BlockPointerTypeTakesAnyBlockArguments(QualType QT) {
809 const BlockPointerType *BPT = QT->getAsBlockPointerType();
810 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
811 const FunctionTypeProto *FTP = BPT->getPointeeType()->getAsFunctionTypeProto();
812 if (FTP) {
813 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
814 E = FTP->arg_type_end(); I != E; ++I)
815 if (isBlockPointerType(*I))
816 return true;
817 }
818 return false;
819}
820
821void RewriteBlocks::GetExtentOfArgList(const char *Name,
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000822 const char *&LParen, const char *&RParen) {
823 const char *argPtr = strchr(Name, '(');
Steve Naroffeab5f632008-09-23 19:24:41 +0000824 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
825
826 LParen = argPtr; // output the start.
827 argPtr++; // skip past the left paren.
828 unsigned parenCount = 1;
829
830 while (*argPtr && parenCount) {
831 switch (*argPtr) {
832 case '(': parenCount++; break;
833 case ')': parenCount--; break;
834 default: break;
835 }
836 if (parenCount) argPtr++;
837 }
838 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
839 RParen = argPtr; // output the end
840}
841
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000842void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000843 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
844 RewriteBlockPointerFunctionArgs(FD);
845 return;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000846 }
847 // Handle Variables and Typedefs.
848 SourceLocation DeclLoc = ND->getLocation();
849 QualType DeclT;
850 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
851 DeclT = VD->getType();
852 else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
853 DeclT = TDD->getUnderlyingType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000854 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
855 DeclT = FD->getType();
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000856 else
857 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
Steve Naroffeab5f632008-09-23 19:24:41 +0000858
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000859 const char *startBuf = SM->getCharacterData(DeclLoc);
860 const char *endBuf = startBuf;
861 // scan backward (from the decl location) for the end of the previous decl.
862 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
863 startBuf--;
864 assert((*startBuf == '^') &&
865 "RewriteBlockPointerDecl() scan error: no caret");
866 // Replace the '^' with '*', computing a negative offset.
867 DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
868 ReplaceText(DeclLoc, 1, "*", 1);
869
870 if (BlockPointerTypeTakesAnyBlockArguments(DeclT)) {
871 // Replace the '^' with '*' for arguments.
872 DeclLoc = ND->getLocation();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000873 startBuf = SM->getCharacterData(DeclLoc);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000874 const char *argListBegin, *argListEnd;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000875 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
876 while (argListBegin < argListEnd) {
877 if (*argListBegin == '^') {
878 SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
879 ReplaceText(CaretLoc, 1, "*", 1);
880 }
881 argListBegin++;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000882 }
Steve Naroffeab5f632008-09-23 19:24:41 +0000883 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000884 return;
885}
886
Steve Naroffd3f77902008-10-05 00:06:12 +0000887void RewriteBlocks::CollectBlockDeclRefInfo(BlockExpr *Exp) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000888 // Add initializers for any closure decl refs.
889 GetBlockDeclRefExprs(Exp);
890 if (BlockDeclRefs.size()) {
891 // Unique all "by copy" declarations.
892 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
893 if (!BlockDeclRefs[i]->isByRef())
894 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
895 // Unique all "by ref" declarations.
896 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
897 if (BlockDeclRefs[i]->isByRef()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000898 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
899 }
Steve Naroffacba0f22008-10-04 23:47:37 +0000900 // Find any imported blocks...they will need special attention.
901 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
902 if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
903 GetBlockCallExprs(Blocks[i]);
904 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
905 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000906 }
Steve Naroffd3f77902008-10-05 00:06:12 +0000907}
908
909std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) {
910 Blocks.push_back(Exp);
911
912 CollectBlockDeclRefInfo(Exp);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000913 std::string FuncName;
914
915 if (CurFunctionDef)
916 FuncName = std::string(CurFunctionDef->getName());
917 else if (CurMethodDef) {
918 FuncName = std::string(CurMethodDef->getSelector().getName());
919 // Convert colons to underscores.
920 std::string::size_type loc = 0;
921 while ((loc = FuncName.find(":", loc)) != std::string::npos)
922 FuncName.replace(loc, 1, "_");
Steve Naroff39622b92008-10-03 15:38:09 +0000923 } else if (VD)
924 FuncName = std::string(VD->getName());
925
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000926 std::string BlockNumber = utostr(Blocks.size()-1);
927
Steve Naroff83ba14e2008-10-03 15:04:50 +0000928 std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000929 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000930
Steve Naroff83ba14e2008-10-03 15:04:50 +0000931 std::string FunkTypeStr;
932
933 // Get a pointer to the function type so we can cast appropriately.
934 Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr);
935
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000936 // Rewrite the closure block with a compound literal. The first cast is
937 // to prevent warnings from the C compiler.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000938 std::string Init = "(" + FunkTypeStr;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000939
Steve Naroff83ba14e2008-10-03 15:04:50 +0000940 Init += ")&" + Tag;
941
942 // Initialize the block function.
943 Init += "((void*)" + Func;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000944
Steve Naroffacba0f22008-10-04 23:47:37 +0000945 if (ImportedBlockDecls.size()) {
946 std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber;
947 Init += ",(void*)" + Buf;
948 Buf = "__" + FuncName + "_block_dispose_" + BlockNumber;
949 Init += ",(void*)" + Buf;
950 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000951 // Add initializers for any closure decl refs.
952 if (BlockDeclRefs.size()) {
953 // Output all "by copy" declarations.
954 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
955 E = BlockByCopyDecls.end(); I != E; ++I) {
956 Init += ",";
957 if (isObjCType((*I)->getType())) {
958 Init += "[[";
959 Init += (*I)->getName();
960 Init += " retain] autorelease]";
Steve Naroff4e13b762008-10-03 20:28:15 +0000961 } else if (isBlockPointerType((*I)->getType())) {
962 Init += "(void *)";
963 Init += (*I)->getName();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000964 } else {
965 Init += (*I)->getName();
966 }
967 }
968 // Output all "by ref" declarations.
969 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
970 E = BlockByRefDecls.end(); I != E; ++I) {
971 Init += ",&";
972 Init += (*I)->getName();
973 }
974 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000975 Init += ")";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000976 BlockDeclRefs.clear();
977 BlockByRefDecls.clear();
978 BlockByCopyDecls.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000979 ImportedBlockDecls.clear();
980
Steve Naroff70f95502008-10-04 17:06:23 +0000981 return Init;
982}
983
984//===----------------------------------------------------------------------===//
985// Function Body / Expression rewriting
986//===----------------------------------------------------------------------===//
987
988Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
989 // Start by rewriting all children.
990 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
991 CI != E; ++CI)
992 if (*CI) {
993 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
994 Stmt *newStmt = RewriteFunctionBody(*CI);
995 if (newStmt)
996 *CI = newStmt;
997
998 // We've just rewritten the block body in place.
999 // Now we snarf the rewritten text and stash it away for later use.
1000 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1001 RewrittenBlockExprs[CBE] = S;
1002 std::string Init = SynthesizeBlockInitExpr(CBE);
1003 // Do the rewrite, using S.size() which contains the rewritten size.
1004 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1005 } else {
1006 Stmt *newStmt = RewriteFunctionBody(*CI);
1007 if (newStmt)
1008 *CI = newStmt;
1009 }
1010 }
1011 // Handle specific things.
1012 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1013 if (CE->getCallee()->getType()->isBlockPointerType())
1014 RewriteBlockCall(CE);
1015 }
1016 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
Ted Kremenekfda4fed2008-10-06 18:47:09 +00001017 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
1018 DI != DE; ++DI) {
1019
1020 ScopedDecl *SD = *DI;
1021 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
1022 if (isBlockPointerType(ND->getType()))
1023 RewriteBlockPointerDecl(ND);
1024 }
1025 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
1026 if (isBlockPointerType(TD->getUnderlyingType()))
1027 RewriteBlockPointerDecl(TD);
1028 }
Steve Naroff70f95502008-10-04 17:06:23 +00001029 }
1030 }
Steve Naroff5e52b172008-10-04 18:52:47 +00001031 // Handle specific things.
1032 if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
1033 if (BDRE->isByRef())
1034 RewriteBlockDeclRefExpr(BDRE);
1035 }
Steve Naroff70f95502008-10-04 17:06:23 +00001036 // Return this stmt unmodified.
1037 return S;
1038}
1039
1040/// HandleDeclInMainFile - This is called for each top-level decl defined in the
1041/// main file of the input.
1042void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
1043 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1044
1045 // Since function prototypes don't have ParmDecl's, we check the function
1046 // prototype. This enables us to rewrite function declarations and
1047 // definitions using the same code.
1048 QualType funcType = FD->getType();
1049
1050 if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
1051 for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(),
1052 E = fproto->arg_type_end(); I && (I != E); ++I)
1053 if (isBlockPointerType(*I)) {
1054 // All the args are checked/rewritten. Don't call twice!
1055 RewriteBlockPointerDecl(FD);
1056 break;
1057 }
1058 }
1059 if (Stmt *Body = FD->getBody()) {
1060 CurFunctionDef = FD;
1061 FD->setBody(RewriteFunctionBody(Body));
1062 // This synthesizes and inserts the block "impl" struct, invoke function,
1063 // and any copy/dispose helper functions.
1064 InsertBlockLiteralsWithinFunction(FD);
1065 CurFunctionDef = 0;
1066 }
1067 return;
1068 }
1069 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
1070 RewriteMethodDecl(MD);
1071 if (Stmt *Body = MD->getBody()) {
1072 CurMethodDef = MD;
1073 RewriteFunctionBody(Body);
1074 InsertBlockLiteralsWithinMethod(MD);
1075 CurMethodDef = 0;
1076 }
1077 }
1078 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
1079 if (isBlockPointerType(VD->getType())) {
1080 RewriteBlockPointerDecl(VD);
1081 if (VD->getInit()) {
1082 if (BlockExpr *CBE = dyn_cast<BlockExpr>(VD->getInit())) {
1083 RewriteFunctionBody(VD->getInit());
1084
1085 // We've just rewritten the block body in place.
1086 // Now we snarf the rewritten text and stash it away for later use.
1087 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1088 RewrittenBlockExprs[CBE] = S;
1089 std::string Init = SynthesizeBlockInitExpr(CBE, VD);
1090 // Do the rewrite, using S.size() which contains the rewritten size.
1091 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1092 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
1093 }
1094 }
1095 }
1096 return;
1097 }
1098 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
1099 if (isBlockPointerType(TD->getUnderlyingType()))
1100 RewriteBlockPointerDecl(TD);
1101 return;
1102 }
1103 if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1104 if (RD->isDefinition()) {
1105 for (RecordDecl::field_const_iterator i = RD->field_begin(),
1106 e = RD->field_end(); i != e; ++i) {
1107 FieldDecl *FD = *i;
1108 if (isBlockPointerType(FD->getType()))
1109 RewriteBlockPointerDecl(FD);
1110 }
1111 }
1112 return;
1113 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001114}