blob: b72076822183b2dbb3ddea979ddf552286ea1371 [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 Naroffd3f77902008-10-05 00:06:12 +0000113 void CollectBlockDeclRefInfo(BlockExpr *Exp);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000114 void GetBlockCallExprs(Stmt *S);
Steve Naroffacba0f22008-10-04 23:47:37 +0000115 void GetBlockDeclRefExprs(Stmt *S);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000116
117 // We avoid calling Type::isBlockPointerType(), since it operates on the
118 // canonical type. We only care if the top-level type is a closure pointer.
119 bool isBlockPointerType(QualType T) { return isa<BlockPointerType>(T); }
120
121 // FIXME: This predicate seems like it would be useful to add to ASTContext.
122 bool isObjCType(QualType T) {
123 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
124 return false;
125
126 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
127
128 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
129 OCT == Context->getCanonicalType(Context->getObjCClassType()))
130 return true;
131
132 if (const PointerType *PT = OCT->getAsPointerType()) {
133 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
134 isa<ObjCQualifiedIdType>(PT->getPointeeType()))
135 return true;
136 }
137 return false;
138 }
139 // ObjC rewrite methods.
140 void RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl);
141 void RewriteCategoryDecl(ObjCCategoryDecl *CatDecl);
142 void RewriteProtocolDecl(ObjCProtocolDecl *PDecl);
143 void RewriteMethodDecl(ObjCMethodDecl *MDecl);
Steve Naroffeab5f632008-09-23 19:24:41 +0000144
145 bool BlockPointerTypeTakesAnyBlockArguments(QualType QT);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000146 void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000147};
148
149}
150
151static bool IsHeaderFile(const std::string &Filename) {
152 std::string::size_type DotPos = Filename.rfind('.');
153
154 if (DotPos == std::string::npos) {
155 // no file extension
156 return false;
157 }
158
159 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
160 // C header: .h
161 // C++ header: .hh or .H;
162 return Ext == "h" || Ext == "hh" || Ext == "H";
163}
164
Steve Naroff13188952008-09-18 14:10:13 +0000165RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile,
166 Diagnostic &D, const LangOptions &LOpts) :
167 Diags(D), LangOpts(LOpts) {
168 IsHeader = IsHeaderFile(inFile);
169 InFileName = inFile;
170 OutFileName = outFile;
171 CurFunctionDef = 0;
172 CurMethodDef = 0;
173 RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
174 "rewriting failed");
175 NoNestedBlockCalls = Diags.getCustomDiagID(Diagnostic::Warning,
176 "Rewrite support for closure calls nested within closure blocks is incomplete");
177}
178
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000179ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
Steve Naroff13188952008-09-18 14:10:13 +0000180 const std::string& OutFile,
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000181 Diagnostic &Diags,
182 const LangOptions &LangOpts) {
Steve Naroff13188952008-09-18 14:10:13 +0000183 return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000184}
185
186void RewriteBlocks::Initialize(ASTContext &context) {
187 Context = &context;
188 SM = &Context->getSourceManager();
189
190 // Get the ID and start/end of the main file.
191 MainFileID = SM->getMainFileID();
192 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
193 MainFileStart = MainBuf->getBufferStart();
194 MainFileEnd = MainBuf->getBufferEnd();
195
196 Rewrite.setSourceMgr(Context->getSourceManager());
197
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000198 if (IsHeader)
199 Preamble = "#pragma once\n";
200 Preamble += "#ifndef BLOCK_IMPL\n";
201 Preamble += "#define BLOCK_IMPL\n";
202 Preamble += "struct __block_impl {\n";
203 Preamble += " void *isa;\n";
204 Preamble += " int Flags;\n";
205 Preamble += " int Size;\n";
206 Preamble += " void *FuncPtr;\n";
207 Preamble += "};\n";
208 Preamble += "enum {\n";
209 Preamble += " BLOCK_HAS_COPY_DISPOSE = (1<<25),\n";
210 Preamble += " BLOCK_IS_GLOBAL = (1<<28)\n";
211 Preamble += "};\n";
212 if (LangOpts.Microsoft)
213 Preamble += "#define __OBJC_RW_EXTERN extern \"C\" __declspec(dllimport)\n";
214 else
215 Preamble += "#define __OBJC_RW_EXTERN extern\n";
216 Preamble += "// Runtime copy/destroy helper functions\n";
217 Preamble += "__OBJC_RW_EXTERN void _Block_copy_assign(void *, void *);\n";
218 Preamble += "__OBJC_RW_EXTERN void _Block_byref_assign_copy(void *, void *);\n";
219 Preamble += "__OBJC_RW_EXTERN void _Block_destroy(void *);\n";
220 Preamble += "__OBJC_RW_EXTERN void _Block_byref_release(void *);\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000221 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteGlobalBlock;\n";
222 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n";
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000223 Preamble += "#endif\n";
224
225 InsertText(SourceLocation::getFileLoc(MainFileID, 0),
226 Preamble.c_str(), Preamble.size());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000227}
228
229void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData,
230 unsigned StrLen)
231{
232 if (!Rewrite.InsertText(Loc, StrData, StrLen))
233 return;
234 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
235}
236
237void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength,
238 const char *NewStr, unsigned NewLength) {
239 if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength))
240 return;
241 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
242}
243
244void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
245 bool haveBlockPtrs = false;
246 for (ObjCMethodDecl::param_iterator I = Method->param_begin(),
247 E = Method->param_end(); I != E; ++I)
248 if (isBlockPointerType((*I)->getType()))
249 haveBlockPtrs = true;
250
251 if (!haveBlockPtrs)
252 return;
253
254 // Do a fuzzy rewrite.
255 // We have 1 or more arguments that have closure pointers.
256 SourceLocation Loc = Method->getLocStart();
257 SourceLocation LocEnd = Method->getLocEnd();
258 const char *startBuf = SM->getCharacterData(Loc);
259 const char *endBuf = SM->getCharacterData(LocEnd);
260
261 const char *methodPtr = startBuf;
Steve Naroff8af6a452008-10-02 17:12:56 +0000262 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000263
264 while (*methodPtr++ && (methodPtr != endBuf)) {
265 switch (*methodPtr) {
266 case ':':
267 methodPtr++;
268 if (*methodPtr == '(') {
269 const char *scanType = ++methodPtr;
270 bool foundBlockPointer = false;
271 unsigned parenCount = 1;
272
273 while (parenCount) {
274 switch (*scanType) {
275 case '(':
276 parenCount++;
277 break;
278 case ')':
279 parenCount--;
280 break;
281 case '^':
282 foundBlockPointer = true;
283 break;
284 }
285 scanType++;
286 }
287 if (foundBlockPointer) {
288 // advance the location to startArgList.
289 Loc = Loc.getFileLocWithOffset(methodPtr-startBuf);
290 assert((Loc.isValid()) && "Invalid Loc");
291 ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size());
292
293 // Advance startBuf. Since the underlying buffer has changed,
294 // it's very important to advance startBuf (so we can correctly
295 // compute a relative Loc the next time around).
296 startBuf = methodPtr;
297 }
298 // Advance the method ptr to the end of the type.
299 methodPtr = scanType;
300 }
301 break;
302 }
303 }
304 return;
305}
306
307void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
308 for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(),
309 E = ClassDecl->instmeth_end(); I != E; ++I)
310 RewriteMethodDecl(*I);
311 for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(),
312 E = ClassDecl->classmeth_end(); I != E; ++I)
313 RewriteMethodDecl(*I);
314}
315
316void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
317 for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
318 E = CatDecl->instmeth_end(); I != E; ++I)
319 RewriteMethodDecl(*I);
320 for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
321 E = CatDecl->classmeth_end(); I != E; ++I)
322 RewriteMethodDecl(*I);
323}
324
325void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
326 for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
327 E = PDecl->instmeth_end(); I != E; ++I)
328 RewriteMethodDecl(*I);
329 for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
330 E = PDecl->classmeth_end(); I != E; ++I)
331 RewriteMethodDecl(*I);
332}
333
334//===----------------------------------------------------------------------===//
335// Top Level Driver Code
336//===----------------------------------------------------------------------===//
337
338void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
339 // Two cases: either the decl could be in the main file, or it could be in a
340 // #included file. If the former, rewrite it now. If the later, check to see
341 // if we rewrote the #include/#import.
342 SourceLocation Loc = D->getLocation();
343 Loc = SM->getLogicalLoc(Loc);
344
345 // If this is for a builtin, ignore it.
346 if (Loc.isInvalid()) return;
347
348 if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D))
349 RewriteInterfaceDecl(MD);
350 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D))
351 RewriteCategoryDecl(CD);
352 else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
353 RewriteProtocolDecl(PD);
354
355 // If we have a decl in the main file, see if we should rewrite it.
356 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
357 HandleDeclInMainFile(D);
358 return;
359}
360
361std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
362 const char *funcName,
363 std::string Tag) {
364 const FunctionType *AFT = CE->getFunctionType();
365 QualType RT = AFT->getResultType();
Steve Naroff48a8c612008-10-03 12:09:49 +0000366 std::string StructRef = "struct " + Tag;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000367 std::string S = "static " + RT.getAsString() + " __" +
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000368 funcName + "_" + "block_func_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000369
370 if (isa<FunctionTypeNoProto>(AFT)) {
371 S += "()";
372 } else if (CE->arg_empty()) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000373 S += "(" + StructRef + " *__cself)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000374 } else {
375 const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
376 assert(FT && "SynthesizeBlockFunc: No function proto");
377 S += '(';
378 // first add the implicit argument.
Steve Naroff48a8c612008-10-03 12:09:49 +0000379 S += StructRef + " *__cself, ";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000380 std::string ParamStr;
Steve Naroff9c3c9022008-09-17 18:37:59 +0000381 for (BlockExpr::arg_iterator AI = CE->arg_begin(),
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000382 E = CE->arg_end(); AI != E; ++AI) {
383 if (AI != CE->arg_begin()) S += ", ";
384 ParamStr = (*AI)->getName();
385 (*AI)->getType().getAsStringInternal(ParamStr);
386 S += ParamStr;
387 }
388 if (FT->isVariadic()) {
389 if (!CE->arg_empty()) S += ", ";
390 S += "...";
391 }
392 S += ')';
393 }
394 S += " {\n";
395
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000396 // Create local declarations to avoid rewriting all closure decl ref exprs.
397 // First, emit a declaration for all "by ref" decls.
398 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
399 E = BlockByRefDecls.end(); I != E; ++I) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000400 S += " ";
401 std::string Name = (*I)->getName();
402 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
403 S += Name + " = __cself->" + (*I)->getName() + "; // bound by ref\n";
404 }
405 // Next, emit a declaration for all "by copy" declarations.
406 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
407 E = BlockByCopyDecls.end(); I != E; ++I) {
408 S += " ";
409 std::string Name = (*I)->getName();
410 // Handle nested closure invocation. For example:
411 //
412 // void (^myImportedClosure)(void);
413 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
414 //
415 // void (^anotherClosure)(void);
416 // anotherClosure = ^(void) {
417 // myImportedClosure(); // import and invoke the closure
418 // };
419 //
420 if (isBlockPointerType((*I)->getType()))
Steve Naroff8af6a452008-10-02 17:12:56 +0000421 S += "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000422 else
423 (*I)->getType().getAsStringInternal(Name);
424 S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000425 }
Steve Naroff70f95502008-10-04 17:06:23 +0000426 std::string RewrittenStr = RewrittenBlockExprs[CE];
427 const char *cstr = RewrittenStr.c_str();
428 while (*cstr++ != '{') ;
429 S += cstr;
430 S += "\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000431 return S;
432}
433
Steve Naroff4e13b762008-10-03 20:28:15 +0000434std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
435 const char *funcName,
436 std::string Tag) {
437 std::string StructRef = "struct " + Tag;
438 std::string S = "static void __";
439
440 S += funcName;
441 S += "_block_copy_" + utostr(i);
442 S += "(" + StructRef;
443 S += "*dst, " + StructRef;
444 S += "*src) {";
445 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
446 E = ImportedBlockDecls.end(); I != E; ++I) {
447 S += "_Block_copy_assign(&dst->";
448 S += (*I)->getName();
449 S += ", src->";
450 S += (*I)->getName();
451 S += ");}";
452 }
453 S += "\nstatic void __";
454 S += funcName;
455 S += "_block_dispose_" + utostr(i);
456 S += "(" + StructRef;
457 S += "*src) {";
458 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
459 E = ImportedBlockDecls.end(); I != E; ++I) {
460 S += "_Block_destroy(src->";
461 S += (*I)->getName();
462 S += ");";
463 }
464 S += "}\n";
465 return S;
466}
467
Steve Naroffacba0f22008-10-04 23:47:37 +0000468std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
469 bool hasCopyDisposeHelpers) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000470 std::string S = "struct " + Tag;
471 std::string Constructor = " " + Tag;
472
473 S += " {\n struct __block_impl impl;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000474
475 if (hasCopyDisposeHelpers)
476 S += " void *copy;\n void *dispose;\n";
477
Steve Naroff48a8c612008-10-03 12:09:49 +0000478 Constructor += "(void *fp";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000479
Steve Naroffacba0f22008-10-04 23:47:37 +0000480 if (hasCopyDisposeHelpers)
481 Constructor += ", void *copyHelp, void *disposeHelp";
482
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000483 if (BlockDeclRefs.size()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000484 // Output all "by copy" declarations.
485 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
486 E = BlockByCopyDecls.end(); I != E; ++I) {
487 S += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000488 std::string FieldName = (*I)->getName();
489 std::string ArgName = "_" + FieldName;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000490 // Handle nested closure invocation. For example:
491 //
492 // void (^myImportedBlock)(void);
493 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
494 //
495 // void (^anotherBlock)(void);
496 // anotherBlock = ^(void) {
497 // myImportedBlock(); // import and invoke the closure
498 // };
499 //
Steve Naroff4e13b762008-10-03 20:28:15 +0000500 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000501 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000502 Constructor += ", void *" + ArgName;
503 } else {
504 (*I)->getType().getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000505 (*I)->getType().getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000506 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000507 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000508 S += FieldName + ";\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000509 }
510 // Output all "by ref" declarations.
511 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
512 E = BlockByRefDecls.end(); I != E; ++I) {
513 S += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000514 std::string FieldName = (*I)->getName();
515 std::string ArgName = "_" + FieldName;
516 // Handle nested closure invocation. For example:
517 //
518 // void (^myImportedBlock)(void);
519 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
520 //
521 // void (^anotherBlock)(void);
522 // anotherBlock = ^(void) {
523 // myImportedBlock(); // import and invoke the closure
524 // };
525 //
526 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000527 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000528 Constructor += ", void *" + ArgName;
529 } else {
530 Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000531 Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000532 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000533 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000534 S += FieldName + "; // by ref\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000535 }
536 // Finish writing the constructor.
537 // FIXME: handle NSConcreteGlobalBlock.
538 Constructor += ", int flags=0) {\n";
Steve Naroff83ba14e2008-10-03 15:04:50 +0000539 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
Steve Naroff48a8c612008-10-03 12:09:49 +0000540 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
541
Steve Naroffacba0f22008-10-04 23:47:37 +0000542 if (hasCopyDisposeHelpers)
543 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
544
Steve Naroff48a8c612008-10-03 12:09:49 +0000545 // Initialize all "by copy" arguments.
546 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
547 E = BlockByCopyDecls.end(); I != E; ++I) {
548 std::string Name = (*I)->getName();
549 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000550 if (isBlockPointerType((*I)->getType()))
551 Constructor += Name + " = (struct __block_impl *)_";
552 else
553 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000554 Constructor += Name + ";\n";
555 }
556 // Initialize all "by ref" arguments.
557 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
558 E = BlockByRefDecls.end(); I != E; ++I) {
559 std::string Name = (*I)->getName();
560 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000561 if (isBlockPointerType((*I)->getType()))
562 Constructor += Name + " = (struct __block_impl *)_";
563 else
564 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000565 Constructor += Name + ";\n";
566 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000567 } else {
568 // Finish writing the constructor.
569 // FIXME: handle NSConcreteGlobalBlock.
570 Constructor += ", int flags=0) {\n";
571 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
572 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000573 if (hasCopyDisposeHelpers)
574 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000575 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000576 Constructor += " ";
577 Constructor += "}\n";
578 S += Constructor;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000579 S += "};\n";
580 return S;
581}
582
583void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
584 const char *FunName) {
585 // Insert closures that were part of the function.
586 for (unsigned i = 0; i < Blocks.size(); i++) {
Steve Naroffacba0f22008-10-04 23:47:37 +0000587
Steve Naroffd3f77902008-10-05 00:06:12 +0000588 CollectBlockDeclRefInfo(Blocks[i]);
589
Steve Naroff48a8c612008-10-03 12:09:49 +0000590 std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000591
Steve Naroffacba0f22008-10-04 23:47:37 +0000592 std::string CI = SynthesizeBlockImpl(Blocks[i], Tag,
593 ImportedBlockDecls.size() > 0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000594
595 InsertText(FunLocStart, CI.c_str(), CI.size());
Steve Naroff4e13b762008-10-03 20:28:15 +0000596
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000597 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
598
599 InsertText(FunLocStart, CF.c_str(), CF.size());
600
Steve Naroff4e13b762008-10-03 20:28:15 +0000601 if (ImportedBlockDecls.size()) {
602 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
603 InsertText(FunLocStart, HF.c_str(), HF.size());
604 }
605
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000606 BlockDeclRefs.clear();
607 BlockByRefDecls.clear();
608 BlockByCopyDecls.clear();
609 BlockCallExprs.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000610 ImportedBlockDecls.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000611 }
612 Blocks.clear();
Steve Naroff8e9216d2008-10-04 17:10:02 +0000613 RewrittenBlockExprs.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000614}
615
616void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
Steve Naroff3ad29e22008-10-03 00:12:09 +0000617 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000618 const char *FuncName = FD->getName();
619
620 SynthesizeBlockLiterals(FunLocStart, FuncName);
621}
622
623void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
624 SourceLocation FunLocStart = MD->getLocStart();
625 std::string FuncName = std::string(MD->getSelector().getName());
626 // Convert colons to underscores.
627 std::string::size_type loc = 0;
628 while ((loc = FuncName.find(":", loc)) != std::string::npos)
629 FuncName.replace(loc, 1, "_");
630
631 SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
632}
633
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000634
635void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
636 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
637 CI != E; ++CI)
638 if (*CI)
639 GetBlockDeclRefExprs(*CI);
640
641 // Handle specific things.
642 if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
643 // FIXME: Handle enums.
644 if (!isa<FunctionDecl>(CDRE->getDecl()))
645 BlockDeclRefs.push_back(CDRE);
646 return;
647}
648
649void RewriteBlocks::GetBlockCallExprs(Stmt *S) {
650 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
651 CI != E; ++CI)
652 if (*CI)
653 GetBlockCallExprs(*CI);
654
655 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
Steve Naroff4e13b762008-10-03 20:28:15 +0000656 if (CE->getCallee()->getType()->isBlockPointerType()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000657 BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
Steve Naroff4e13b762008-10-03 20:28:15 +0000658 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000659 }
660 return;
661}
662
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000663std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
664 // Navigate to relevant type information.
Steve Naroffcc2ece22008-09-24 22:46:45 +0000665 const char *closureName = 0;
666 const BlockPointerType *CPT = 0;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000667
668 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
669 closureName = DRE->getDecl()->getName();
670 CPT = DRE->getType()->getAsBlockPointerType();
671 } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
672 closureName = CDRE->getDecl()->getName();
673 CPT = CDRE->getType()->getAsBlockPointerType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000674 } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
675 closureName = MExpr->getMemberDecl()->getName();
676 CPT = MExpr->getType()->getAsBlockPointerType();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000677 } else {
678 assert(1 && "RewriteBlockClass: Bad type");
679 }
680 assert(CPT && "RewriteBlockClass: Bad type");
681 const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType();
682 assert(FT && "RewriteBlockClass: Bad type");
683 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FT);
684 // FTP will be null for closures that don't take arguments.
685
686 // Build a closure call - start with a paren expr to enforce precedence.
687 std::string BlockCall = "(";
688
689 // Synthesize the cast.
690 BlockCall += "(" + Exp->getType().getAsString() + "(*)";
Steve Naroff8af6a452008-10-02 17:12:56 +0000691 BlockCall += "(struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000692 if (FTP) {
693 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
694 E = FTP->arg_type_end(); I && (I != E); ++I)
695 BlockCall += ", " + (*I).getAsString();
696 }
697 BlockCall += "))"; // close the argument list and paren expression.
698
Steve Naroff83ba14e2008-10-03 15:04:50 +0000699 // Invoke the closure. We need to cast it since the declaration type is
700 // bogus (it's a function pointer type)
701 BlockCall += "((struct __block_impl *)";
702 std::string closureExprBufStr;
703 llvm::raw_string_ostream closureExprBuf(closureExprBufStr);
704 Exp->getCallee()->printPretty(closureExprBuf);
705 BlockCall += closureExprBuf.str();
706 BlockCall += ")->FuncPtr)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000707
708 // Add the arguments.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000709 BlockCall += "((struct __block_impl *)";
Steve Naroffb65a4f12008-10-04 17:45:51 +0000710 BlockCall += closureExprBuf.str();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000711 for (CallExpr::arg_iterator I = Exp->arg_begin(),
712 E = Exp->arg_end(); I != E; ++I) {
713 std::string syncExprBufS;
714 llvm::raw_string_ostream Buf(syncExprBufS);
715 (*I)->printPretty(Buf);
716 BlockCall += ", " + Buf.str();
717 }
718 return BlockCall;
719}
720
721void RewriteBlocks::RewriteBlockCall(CallExpr *Exp) {
722 std::string BlockCall = SynthesizeBlockCall(Exp);
723
724 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
725 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
726
727 ReplaceText(Exp->getLocStart(), endBuf-startBuf,
728 BlockCall.c_str(), BlockCall.size());
729}
730
Steve Naroff5e52b172008-10-04 18:52:47 +0000731void RewriteBlocks::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
732 // FIXME: Add more elaborate code generation required by the ABI.
733 InsertText(BDRE->getLocStart(), "*", 1);
734}
735
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000736void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
737 SourceLocation DeclLoc = FD->getLocation();
738 unsigned parenCount = 0, nArgs = 0;
739
740 // We have 1 or more arguments that have closure pointers.
741 const char *startBuf = SM->getCharacterData(DeclLoc);
742 const char *startArgList = strchr(startBuf, '(');
743
744 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
745
746 parenCount++;
747 // advance the location to startArgList.
748 DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf+1);
749 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
750
751 const char *topLevelCommaCursor = 0;
752 const char *argPtr = startArgList;
753 bool scannedBlockDecl = false;
Steve Naroff8af6a452008-10-02 17:12:56 +0000754 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000755
756 while (*argPtr++ && parenCount) {
757 switch (*argPtr) {
758 case '^':
759 scannedBlockDecl = true;
760 break;
761 case '(':
762 parenCount++;
763 break;
764 case ')':
765 parenCount--;
766 if (parenCount == 0) {
767 if (scannedBlockDecl) {
768 // If we are rewriting a definition, don't forget the arg name.
769 if (FD->getBody())
770 Tag += FD->getParamDecl(nArgs)->getName();
771 // The last argument is a closure pointer decl, rewrite it!
772 if (topLevelCommaCursor)
773 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-2, Tag.c_str(), Tag.size());
774 else
775 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
776 scannedBlockDecl = false; // reset.
777 }
778 nArgs++;
779 }
780 break;
781 case ',':
782 if (parenCount == 1) {
783 // Make sure the function takes more than one argument.
784 assert((FD->getNumParams() > 1) && "Rewriter fuzzy parser confused");
785 if (scannedBlockDecl) {
786 // If we are rewriting a definition, don't forget the arg name.
787 if (FD->getBody())
788 Tag += FD->getParamDecl(nArgs)->getName();
789 // The current argument is a closure pointer decl, rewrite it!
790 if (topLevelCommaCursor)
791 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-1, Tag.c_str(), Tag.size());
792 else
793 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
794 scannedBlockDecl = false;
795 }
796 nArgs++;
797 // advance the location to topLevelCommaCursor.
798 if (topLevelCommaCursor)
799 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-topLevelCommaCursor);
800 else
801 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList+1);
802 topLevelCommaCursor = argPtr;
803 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
804 }
805 break;
806 }
807 }
808 return;
809}
810
Steve Naroffeab5f632008-09-23 19:24:41 +0000811bool RewriteBlocks::BlockPointerTypeTakesAnyBlockArguments(QualType QT) {
812 const BlockPointerType *BPT = QT->getAsBlockPointerType();
813 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
814 const FunctionTypeProto *FTP = BPT->getPointeeType()->getAsFunctionTypeProto();
815 if (FTP) {
816 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
817 E = FTP->arg_type_end(); I != E; ++I)
818 if (isBlockPointerType(*I))
819 return true;
820 }
821 return false;
822}
823
824void RewriteBlocks::GetExtentOfArgList(const char *Name,
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000825 const char *&LParen, const char *&RParen) {
826 const char *argPtr = strchr(Name, '(');
Steve Naroffeab5f632008-09-23 19:24:41 +0000827 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
828
829 LParen = argPtr; // output the start.
830 argPtr++; // skip past the left paren.
831 unsigned parenCount = 1;
832
833 while (*argPtr && parenCount) {
834 switch (*argPtr) {
835 case '(': parenCount++; break;
836 case ')': parenCount--; break;
837 default: break;
838 }
839 if (parenCount) argPtr++;
840 }
841 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
842 RParen = argPtr; // output the end
843}
844
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000845void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000846 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
847 RewriteBlockPointerFunctionArgs(FD);
848 return;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000849 }
850 // Handle Variables and Typedefs.
851 SourceLocation DeclLoc = ND->getLocation();
852 QualType DeclT;
853 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
854 DeclT = VD->getType();
855 else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
856 DeclT = TDD->getUnderlyingType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000857 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
858 DeclT = FD->getType();
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000859 else
860 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
Steve Naroffeab5f632008-09-23 19:24:41 +0000861
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000862 const char *startBuf = SM->getCharacterData(DeclLoc);
863 const char *endBuf = startBuf;
864 // scan backward (from the decl location) for the end of the previous decl.
865 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
866 startBuf--;
867 assert((*startBuf == '^') &&
868 "RewriteBlockPointerDecl() scan error: no caret");
869 // Replace the '^' with '*', computing a negative offset.
870 DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
871 ReplaceText(DeclLoc, 1, "*", 1);
872
873 if (BlockPointerTypeTakesAnyBlockArguments(DeclT)) {
874 // Replace the '^' with '*' for arguments.
875 DeclLoc = ND->getLocation();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000876 startBuf = SM->getCharacterData(DeclLoc);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000877 const char *argListBegin, *argListEnd;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000878 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
879 while (argListBegin < argListEnd) {
880 if (*argListBegin == '^') {
881 SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
882 ReplaceText(CaretLoc, 1, "*", 1);
883 }
884 argListBegin++;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000885 }
Steve Naroffeab5f632008-09-23 19:24:41 +0000886 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000887 return;
888}
889
Steve Naroffd3f77902008-10-05 00:06:12 +0000890void RewriteBlocks::CollectBlockDeclRefInfo(BlockExpr *Exp) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000891 // Add initializers for any closure decl refs.
892 GetBlockDeclRefExprs(Exp);
893 if (BlockDeclRefs.size()) {
894 // Unique all "by copy" declarations.
895 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
896 if (!BlockDeclRefs[i]->isByRef())
897 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
898 // Unique all "by ref" declarations.
899 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
900 if (BlockDeclRefs[i]->isByRef()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000901 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
902 }
Steve Naroffacba0f22008-10-04 23:47:37 +0000903 // Find any imported blocks...they will need special attention.
904 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
905 if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
906 GetBlockCallExprs(Blocks[i]);
907 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
908 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000909 }
Steve Naroffd3f77902008-10-05 00:06:12 +0000910}
911
912std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) {
913 Blocks.push_back(Exp);
914
915 CollectBlockDeclRefInfo(Exp);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000916 std::string FuncName;
917
918 if (CurFunctionDef)
919 FuncName = std::string(CurFunctionDef->getName());
920 else if (CurMethodDef) {
921 FuncName = std::string(CurMethodDef->getSelector().getName());
922 // Convert colons to underscores.
923 std::string::size_type loc = 0;
924 while ((loc = FuncName.find(":", loc)) != std::string::npos)
925 FuncName.replace(loc, 1, "_");
Steve Naroff39622b92008-10-03 15:38:09 +0000926 } else if (VD)
927 FuncName = std::string(VD->getName());
928
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000929 std::string BlockNumber = utostr(Blocks.size()-1);
930
Steve Naroff83ba14e2008-10-03 15:04:50 +0000931 std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000932 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000933
Steve Naroff83ba14e2008-10-03 15:04:50 +0000934 std::string FunkTypeStr;
935
936 // Get a pointer to the function type so we can cast appropriately.
937 Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr);
938
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000939 // Rewrite the closure block with a compound literal. The first cast is
940 // to prevent warnings from the C compiler.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000941 std::string Init = "(" + FunkTypeStr;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000942
Steve Naroff83ba14e2008-10-03 15:04:50 +0000943 Init += ")&" + Tag;
944
945 // Initialize the block function.
946 Init += "((void*)" + Func;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000947
Steve Naroffacba0f22008-10-04 23:47:37 +0000948 if (ImportedBlockDecls.size()) {
949 std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber;
950 Init += ",(void*)" + Buf;
951 Buf = "__" + FuncName + "_block_dispose_" + BlockNumber;
952 Init += ",(void*)" + Buf;
953 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000954 // Add initializers for any closure decl refs.
955 if (BlockDeclRefs.size()) {
956 // Output all "by copy" declarations.
957 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
958 E = BlockByCopyDecls.end(); I != E; ++I) {
959 Init += ",";
960 if (isObjCType((*I)->getType())) {
961 Init += "[[";
962 Init += (*I)->getName();
963 Init += " retain] autorelease]";
Steve Naroff4e13b762008-10-03 20:28:15 +0000964 } else if (isBlockPointerType((*I)->getType())) {
965 Init += "(void *)";
966 Init += (*I)->getName();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000967 } else {
968 Init += (*I)->getName();
969 }
970 }
971 // Output all "by ref" declarations.
972 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
973 E = BlockByRefDecls.end(); I != E; ++I) {
974 Init += ",&";
975 Init += (*I)->getName();
976 }
977 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000978 Init += ")";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000979 BlockDeclRefs.clear();
980 BlockByRefDecls.clear();
981 BlockByCopyDecls.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000982 ImportedBlockDecls.clear();
983
Steve Naroff70f95502008-10-04 17:06:23 +0000984 return Init;
985}
986
987//===----------------------------------------------------------------------===//
988// Function Body / Expression rewriting
989//===----------------------------------------------------------------------===//
990
991Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
992 // Start by rewriting all children.
993 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
994 CI != E; ++CI)
995 if (*CI) {
996 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
997 Stmt *newStmt = RewriteFunctionBody(*CI);
998 if (newStmt)
999 *CI = newStmt;
1000
1001 // We've just rewritten the block body in place.
1002 // Now we snarf the rewritten text and stash it away for later use.
1003 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1004 RewrittenBlockExprs[CBE] = S;
1005 std::string Init = SynthesizeBlockInitExpr(CBE);
1006 // Do the rewrite, using S.size() which contains the rewritten size.
1007 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1008 } else {
1009 Stmt *newStmt = RewriteFunctionBody(*CI);
1010 if (newStmt)
1011 *CI = newStmt;
1012 }
1013 }
1014 // Handle specific things.
1015 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1016 if (CE->getCallee()->getType()->isBlockPointerType())
1017 RewriteBlockCall(CE);
1018 }
1019 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
1020 ScopedDecl *SD = DS->getDecl();
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 }
1029 }
Steve Naroff5e52b172008-10-04 18:52:47 +00001030 // Handle specific things.
1031 if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
1032 if (BDRE->isByRef())
1033 RewriteBlockDeclRefExpr(BDRE);
1034 }
Steve Naroff70f95502008-10-04 17:06:23 +00001035 // Return this stmt unmodified.
1036 return S;
1037}
1038
1039/// HandleDeclInMainFile - This is called for each top-level decl defined in the
1040/// main file of the input.
1041void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
1042 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1043
1044 // Since function prototypes don't have ParmDecl's, we check the function
1045 // prototype. This enables us to rewrite function declarations and
1046 // definitions using the same code.
1047 QualType funcType = FD->getType();
1048
1049 if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
1050 for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(),
1051 E = fproto->arg_type_end(); I && (I != E); ++I)
1052 if (isBlockPointerType(*I)) {
1053 // All the args are checked/rewritten. Don't call twice!
1054 RewriteBlockPointerDecl(FD);
1055 break;
1056 }
1057 }
1058 if (Stmt *Body = FD->getBody()) {
1059 CurFunctionDef = FD;
1060 FD->setBody(RewriteFunctionBody(Body));
1061 // This synthesizes and inserts the block "impl" struct, invoke function,
1062 // and any copy/dispose helper functions.
1063 InsertBlockLiteralsWithinFunction(FD);
1064 CurFunctionDef = 0;
1065 }
1066 return;
1067 }
1068 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
1069 RewriteMethodDecl(MD);
1070 if (Stmt *Body = MD->getBody()) {
1071 CurMethodDef = MD;
1072 RewriteFunctionBody(Body);
1073 InsertBlockLiteralsWithinMethod(MD);
1074 CurMethodDef = 0;
1075 }
1076 }
1077 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
1078 if (isBlockPointerType(VD->getType())) {
1079 RewriteBlockPointerDecl(VD);
1080 if (VD->getInit()) {
1081 if (BlockExpr *CBE = dyn_cast<BlockExpr>(VD->getInit())) {
1082 RewriteFunctionBody(VD->getInit());
1083
1084 // We've just rewritten the block body in place.
1085 // Now we snarf the rewritten text and stash it away for later use.
1086 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1087 RewrittenBlockExprs[CBE] = S;
1088 std::string Init = SynthesizeBlockInitExpr(CBE, VD);
1089 // Do the rewrite, using S.size() which contains the rewritten size.
1090 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1091 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
1092 }
1093 }
1094 }
1095 return;
1096 }
1097 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
1098 if (isBlockPointerType(TD->getUnderlyingType()))
1099 RewriteBlockPointerDecl(TD);
1100 return;
1101 }
1102 if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1103 if (RD->isDefinition()) {
1104 for (RecordDecl::field_const_iterator i = RD->field_begin(),
1105 e = RD->field_end(); i != e; ++i) {
1106 FieldDecl *FD = *i;
1107 if (isBlockPointerType(FD->getType()))
1108 RewriteBlockPointerDecl(FD);
1109 }
1110 }
1111 return;
1112 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001113}