blob: b9e2217db202ecb88b5824d1793f21b082131446 [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;
52
53 // The function/method we are rewriting.
54 FunctionDecl *CurFunctionDef;
55 ObjCMethodDecl *CurMethodDef;
56
57 bool IsHeader;
Steve Naroff13188952008-09-18 14:10:13 +000058 std::string InFileName;
59 std::string OutFileName;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000060public:
Steve Naroff13188952008-09-18 14:10:13 +000061 RewriteBlocks(std::string inFile, std::string outFile, Diagnostic &D,
62 const LangOptions &LOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000063 ~RewriteBlocks() {
64 // Get the buffer corresponding to MainFileID.
65 // If we haven't changed it, then we are done.
66 if (const RewriteBuffer *RewriteBuf =
67 Rewrite.getRewriteBufferFor(MainFileID)) {
68 std::string S(RewriteBuf->begin(), RewriteBuf->end());
69 printf("%s\n", S.c_str());
70 } else {
71 printf("No changes\n");
72 }
73 }
74
75 void Initialize(ASTContext &context);
76
77 void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen);
78 void ReplaceText(SourceLocation Start, unsigned OrigLength,
79 const char *NewStr, unsigned NewLength);
80
81 // Top Level Driver code.
82 virtual void HandleTopLevelDecl(Decl *D);
83 void HandleDeclInMainFile(Decl *D);
84
85 // Top level
86 Stmt *RewriteFunctionBody(Stmt *S);
87 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
88 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
89
90 // Block specific rewrite rules.
Steve Naroff9c3c9022008-09-17 18:37:59 +000091 void RewriteBlockExpr(BlockExpr *Exp);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000092
93 void RewriteBlockCall(CallExpr *Exp);
94 void RewriteBlockPointerDecl(NamedDecl *VD);
95 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
96
97 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
98 const char *funcName, std::string Tag);
99 std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag);
100 std::string SynthesizeBlockCall(CallExpr *Exp);
101 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
102 const char *FunName);
103
104 void GetBlockDeclRefExprs(Stmt *S);
105 void GetBlockCallExprs(Stmt *S);
106
107 // We avoid calling Type::isBlockPointerType(), since it operates on the
108 // canonical type. We only care if the top-level type is a closure pointer.
109 bool isBlockPointerType(QualType T) { return isa<BlockPointerType>(T); }
110
111 // FIXME: This predicate seems like it would be useful to add to ASTContext.
112 bool isObjCType(QualType T) {
113 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
114 return false;
115
116 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
117
118 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
119 OCT == Context->getCanonicalType(Context->getObjCClassType()))
120 return true;
121
122 if (const PointerType *PT = OCT->getAsPointerType()) {
123 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
124 isa<ObjCQualifiedIdType>(PT->getPointeeType()))
125 return true;
126 }
127 return false;
128 }
129 // ObjC rewrite methods.
130 void RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl);
131 void RewriteCategoryDecl(ObjCCategoryDecl *CatDecl);
132 void RewriteProtocolDecl(ObjCProtocolDecl *PDecl);
133 void RewriteMethodDecl(ObjCMethodDecl *MDecl);
Steve Naroffeab5f632008-09-23 19:24:41 +0000134
135 bool BlockPointerTypeTakesAnyBlockArguments(QualType QT);
136 void GetExtentOfArgList(const char *Name, char *&LParen, char *&RParen);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000137};
138
139}
140
141static bool IsHeaderFile(const std::string &Filename) {
142 std::string::size_type DotPos = Filename.rfind('.');
143
144 if (DotPos == std::string::npos) {
145 // no file extension
146 return false;
147 }
148
149 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
150 // C header: .h
151 // C++ header: .hh or .H;
152 return Ext == "h" || Ext == "hh" || Ext == "H";
153}
154
Steve Naroff13188952008-09-18 14:10:13 +0000155RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile,
156 Diagnostic &D, const LangOptions &LOpts) :
157 Diags(D), LangOpts(LOpts) {
158 IsHeader = IsHeaderFile(inFile);
159 InFileName = inFile;
160 OutFileName = outFile;
161 CurFunctionDef = 0;
162 CurMethodDef = 0;
163 RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
164 "rewriting failed");
165 NoNestedBlockCalls = Diags.getCustomDiagID(Diagnostic::Warning,
166 "Rewrite support for closure calls nested within closure blocks is incomplete");
167}
168
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000169ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
Steve Naroff13188952008-09-18 14:10:13 +0000170 const std::string& OutFile,
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000171 Diagnostic &Diags,
172 const LangOptions &LangOpts) {
Steve Naroff13188952008-09-18 14:10:13 +0000173 return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000174}
175
176void RewriteBlocks::Initialize(ASTContext &context) {
177 Context = &context;
178 SM = &Context->getSourceManager();
179
180 // Get the ID and start/end of the main file.
181 MainFileID = SM->getMainFileID();
182 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
183 MainFileStart = MainBuf->getBufferStart();
184 MainFileEnd = MainBuf->getBufferEnd();
185
186 Rewrite.setSourceMgr(Context->getSourceManager());
187
188 const char *s = "#pragma once\n"
189 "#ifndef CLOSURE_IMPL\n"
190 "struct __closure_impl {\n"
191 " long Reserved;\n"
192 " int Flags;\n"
193 " int Size;\n"
194 " void *Invoke;\n"
195 "};\n"
196 "enum {\n"
197 " HAS_NONPOD = (1<<25),\n"
198 " HAS_BYREF = (1<<26)\n"
199 "};\n"
200 "#define CLOSURE_IMPL\n"
201 "#endif\n";
202 if (IsHeader) {
203 // insert the whole string when rewriting a header file
204 InsertText(SourceLocation::getFileLoc(MainFileID, 0), s, strlen(s));
205 }
206 else {
207 // Not rewriting header, exclude the #pragma once pragma
208 const char *p = s + strlen("#pragma once\n");
209 InsertText(SourceLocation::getFileLoc(MainFileID, 0), p, strlen(p));
210 }
211}
212
213void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData,
214 unsigned StrLen)
215{
216 if (!Rewrite.InsertText(Loc, StrData, StrLen))
217 return;
218 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
219}
220
221void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength,
222 const char *NewStr, unsigned NewLength) {
223 if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength))
224 return;
225 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
226}
227
228void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
229 bool haveBlockPtrs = false;
230 for (ObjCMethodDecl::param_iterator I = Method->param_begin(),
231 E = Method->param_end(); I != E; ++I)
232 if (isBlockPointerType((*I)->getType()))
233 haveBlockPtrs = true;
234
235 if (!haveBlockPtrs)
236 return;
237
238 // Do a fuzzy rewrite.
239 // We have 1 or more arguments that have closure pointers.
240 SourceLocation Loc = Method->getLocStart();
241 SourceLocation LocEnd = Method->getLocEnd();
242 const char *startBuf = SM->getCharacterData(Loc);
243 const char *endBuf = SM->getCharacterData(LocEnd);
244
245 const char *methodPtr = startBuf;
246 std::string Tag = "struct __closure_impl *";
247
248 while (*methodPtr++ && (methodPtr != endBuf)) {
249 switch (*methodPtr) {
250 case ':':
251 methodPtr++;
252 if (*methodPtr == '(') {
253 const char *scanType = ++methodPtr;
254 bool foundBlockPointer = false;
255 unsigned parenCount = 1;
256
257 while (parenCount) {
258 switch (*scanType) {
259 case '(':
260 parenCount++;
261 break;
262 case ')':
263 parenCount--;
264 break;
265 case '^':
266 foundBlockPointer = true;
267 break;
268 }
269 scanType++;
270 }
271 if (foundBlockPointer) {
272 // advance the location to startArgList.
273 Loc = Loc.getFileLocWithOffset(methodPtr-startBuf);
274 assert((Loc.isValid()) && "Invalid Loc");
275 ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size());
276
277 // Advance startBuf. Since the underlying buffer has changed,
278 // it's very important to advance startBuf (so we can correctly
279 // compute a relative Loc the next time around).
280 startBuf = methodPtr;
281 }
282 // Advance the method ptr to the end of the type.
283 methodPtr = scanType;
284 }
285 break;
286 }
287 }
288 return;
289}
290
291void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
292 for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(),
293 E = ClassDecl->instmeth_end(); I != E; ++I)
294 RewriteMethodDecl(*I);
295 for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(),
296 E = ClassDecl->classmeth_end(); I != E; ++I)
297 RewriteMethodDecl(*I);
298}
299
300void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
301 for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
302 E = CatDecl->instmeth_end(); I != E; ++I)
303 RewriteMethodDecl(*I);
304 for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
305 E = CatDecl->classmeth_end(); I != E; ++I)
306 RewriteMethodDecl(*I);
307}
308
309void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
310 for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
311 E = PDecl->instmeth_end(); I != E; ++I)
312 RewriteMethodDecl(*I);
313 for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
314 E = PDecl->classmeth_end(); I != E; ++I)
315 RewriteMethodDecl(*I);
316}
317
318//===----------------------------------------------------------------------===//
319// Top Level Driver Code
320//===----------------------------------------------------------------------===//
321
322void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
323 // Two cases: either the decl could be in the main file, or it could be in a
324 // #included file. If the former, rewrite it now. If the later, check to see
325 // if we rewrote the #include/#import.
326 SourceLocation Loc = D->getLocation();
327 Loc = SM->getLogicalLoc(Loc);
328
329 // If this is for a builtin, ignore it.
330 if (Loc.isInvalid()) return;
331
332 if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D))
333 RewriteInterfaceDecl(MD);
334 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D))
335 RewriteCategoryDecl(CD);
336 else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
337 RewriteProtocolDecl(PD);
338
339 // If we have a decl in the main file, see if we should rewrite it.
340 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
341 HandleDeclInMainFile(D);
342 return;
343}
344
345std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
346 const char *funcName,
347 std::string Tag) {
348 const FunctionType *AFT = CE->getFunctionType();
349 QualType RT = AFT->getResultType();
350 std::string S = "static " + RT.getAsString() + " __" +
351 funcName + "_" + "closure_" + utostr(i);
352
353 if (isa<FunctionTypeNoProto>(AFT)) {
354 S += "()";
355 } else if (CE->arg_empty()) {
356 S += "(" + Tag + " *__cself)";
357 } else {
358 const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
359 assert(FT && "SynthesizeBlockFunc: No function proto");
360 S += '(';
361 // first add the implicit argument.
362 S += Tag + " *__cself, ";
363 std::string ParamStr;
Steve Naroff9c3c9022008-09-17 18:37:59 +0000364 for (BlockExpr::arg_iterator AI = CE->arg_begin(),
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000365 E = CE->arg_end(); AI != E; ++AI) {
366 if (AI != CE->arg_begin()) S += ", ";
367 ParamStr = (*AI)->getName();
368 (*AI)->getType().getAsStringInternal(ParamStr);
369 S += ParamStr;
370 }
371 if (FT->isVariadic()) {
372 if (!CE->arg_empty()) S += ", ";
373 S += "...";
374 }
375 S += ')';
376 }
377 S += " {\n";
378
379 bool haveByRefDecls = false;
380
381 // Create local declarations to avoid rewriting all closure decl ref exprs.
382 // First, emit a declaration for all "by ref" decls.
383 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
384 E = BlockByRefDecls.end(); I != E; ++I) {
385 // Note: It is not possible to have "by ref" closure pointer decls.
386 haveByRefDecls = true;
387 S += " ";
388 std::string Name = (*I)->getName();
389 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
390 S += Name + " = __cself->" + (*I)->getName() + "; // bound by ref\n";
391 }
392 // Next, emit a declaration for all "by copy" declarations.
393 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
394 E = BlockByCopyDecls.end(); I != E; ++I) {
395 S += " ";
396 std::string Name = (*I)->getName();
397 // Handle nested closure invocation. For example:
398 //
399 // void (^myImportedClosure)(void);
400 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
401 //
402 // void (^anotherClosure)(void);
403 // anotherClosure = ^(void) {
404 // myImportedClosure(); // import and invoke the closure
405 // };
406 //
407 if (isBlockPointerType((*I)->getType()))
408 S += "struct __closure_impl *";
409 else
410 (*I)->getType().getAsStringInternal(Name);
411 S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
412 }
Steve Naroff9c3c9022008-09-17 18:37:59 +0000413 if (BlockExpr *CBE = dyn_cast<BlockExpr>(CE)) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000414 std::string BodyBuf;
415
416 SourceLocation BodyLocStart = CBE->getBody()->getLocStart();
417 SourceLocation BodyLocEnd = CBE->getBody()->getLocEnd();
418 const char *BodyStartBuf = SM->getCharacterData(BodyLocStart);
419 const char *BodyEndBuf = SM->getCharacterData(BodyLocEnd);
420
421 BodyBuf.append(BodyStartBuf, BodyEndBuf-BodyStartBuf+1);
422
423 if (BlockDeclRefs.size()) {
424 unsigned int nCharsAdded = 0;
425 for (unsigned i = 0; i < BlockDeclRefs.size(); i++) {
426 if (BlockDeclRefs[i]->isByRef()) {
427 // Add a level of indirection! The code below assumes
428 // the closure decl refs/locations are in strictly ascending
429 // order. The traversal performed by GetBlockDeclRefExprs()
430 // currently does this. FIXME: Wrap the *x with parens,
431 // just in case x is a more complex expression, like x->member,
432 // which needs to be rewritten to (*x)->member.
433 SourceLocation StarLoc = BlockDeclRefs[i]->getLocStart();
434 const char *StarBuf = SM->getCharacterData(StarLoc);
435 BodyBuf.insert(StarBuf-BodyStartBuf+nCharsAdded, 1, '*');
436 // Get a fresh buffer, the insert might have caused it to grow.
437 BodyStartBuf = SM->getCharacterData(BodyLocStart);
438 nCharsAdded++;
439 } else if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
440 Diags.Report(NoNestedBlockCalls);
441
442 GetBlockCallExprs(CE);
443
444 // Rewrite the closure in place.
445 // The character based equivalent of RewriteBlockCall().
446 // Need to get the CallExpr associated with this BlockDeclRef.
447 std::string BlockCall = SynthesizeBlockCall(BlockCallExprs[BlockDeclRefs[i]]);
448
449 SourceLocation CallLocStart = BlockCallExprs[BlockDeclRefs[i]]->getLocStart();
450 SourceLocation CallLocEnd = BlockCallExprs[BlockDeclRefs[i]]->getLocEnd();
451 const char *CallStart = SM->getCharacterData(CallLocStart);
452 const char *CallEnd = SM->getCharacterData(CallLocEnd);
453 unsigned CallBytes = CallEnd-CallStart;
454 BodyBuf.replace(CallStart-BodyStartBuf, CallBytes, BlockCall.c_str());
455 nCharsAdded += CallBytes;
456 }
457 }
458 }
459 if (haveByRefDecls) {
460 // Remove |...|.
Steve Naroffeab5f632008-09-23 19:24:41 +0000461 //const char *firstBarPtr = strchr(BodyStartBuf, '|');
462 //const char *secondBarPtr = strchr(firstBarPtr+1, '|');
463 //BodyBuf.replace(firstBarPtr-BodyStartBuf, secondBarPtr-firstBarPtr+1, "");
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000464 }
465 S += " ";
466 S += BodyBuf;
467 }
468 S += "\n}\n";
469 return S;
470}
471
472std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE,
473 std::string Tag) {
474 std::string S = Tag + " {\n struct __closure_impl impl;\n";
475
476 GetBlockDeclRefExprs(CE);
477 if (BlockDeclRefs.size()) {
478 // Unique all "by copy" declarations.
479 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
480 if (!BlockDeclRefs[i]->isByRef())
481 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
482 // Unique all "by ref" declarations.
483 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
484 if (BlockDeclRefs[i]->isByRef())
485 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
486
487 // Output all "by copy" declarations.
488 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
489 E = BlockByCopyDecls.end(); I != E; ++I) {
490 S += " ";
491 std::string Name = (*I)->getName();
492 // Handle nested closure invocation. For example:
493 //
494 // void (^myImportedBlock)(void);
495 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
496 //
497 // void (^anotherBlock)(void);
498 // anotherBlock = ^(void) {
499 // myImportedBlock(); // import and invoke the closure
500 // };
501 //
502 if (isBlockPointerType((*I)->getType()))
503 S += "struct __closure_impl *";
504 else
505 (*I)->getType().getAsStringInternal(Name);
506 S += Name + ";\n";
507 }
508 // Output all "by ref" declarations.
509 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
510 E = BlockByRefDecls.end(); I != E; ++I) {
511 S += " ";
512 std::string Name = (*I)->getName();
513 if (isBlockPointerType((*I)->getType()))
514 S += "struct __closure_impl *";
515 else
516 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
517 S += Name + "; // by ref\n";
518 }
519 }
520 S += "};\n";
521 return S;
522}
523
524void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
525 const char *FunName) {
526 // Insert closures that were part of the function.
527 for (unsigned i = 0; i < Blocks.size(); i++) {
528
529 std::string Tag = "struct __" + std::string(FunName) +
530 "_closure_impl_" + utostr(i);
531
532 std::string CI = SynthesizeBlockImpl(Blocks[i], Tag);
533
534 InsertText(FunLocStart, CI.c_str(), CI.size());
535
536 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
537
538 InsertText(FunLocStart, CF.c_str(), CF.size());
539
540 BlockDeclRefs.clear();
541 BlockByRefDecls.clear();
542 BlockByCopyDecls.clear();
543 BlockCallExprs.clear();
544 }
545 Blocks.clear();
546}
547
548void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
549 SourceLocation FunLocStart = FD->getLocation();
550 const char *FuncName = FD->getName();
551
552 SynthesizeBlockLiterals(FunLocStart, FuncName);
553}
554
555void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
556 SourceLocation FunLocStart = MD->getLocStart();
557 std::string FuncName = std::string(MD->getSelector().getName());
558 // Convert colons to underscores.
559 std::string::size_type loc = 0;
560 while ((loc = FuncName.find(":", loc)) != std::string::npos)
561 FuncName.replace(loc, 1, "_");
562
563 SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
564}
565
566/// HandleDeclInMainFile - This is called for each top-level decl defined in the
567/// main file of the input.
568void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
569 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
570
571 // Since function prototypes don't have ParmDecl's, we check the function
572 // prototype. This enables us to rewrite function declarations and
573 // definitions using the same code.
574 QualType funcType = FD->getType();
575
576 if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
577 for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(),
578 E = fproto->arg_type_end(); I && (I != E); ++I)
579 if (isBlockPointerType(*I)) {
580 // All the args are checked/rewritten. Don't call twice!
581 RewriteBlockPointerDecl(FD);
582 break;
583 }
584 }
585 if (Stmt *Body = FD->getBody()) {
586 CurFunctionDef = FD;
587 FD->setBody(RewriteFunctionBody(Body));
588 InsertBlockLiteralsWithinFunction(FD);
589 CurFunctionDef = 0;
590 }
591 return;
592 }
593 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
594 RewriteMethodDecl(MD);
595 if (Stmt *Body = MD->getBody()) {
596 CurMethodDef = MD;
597 RewriteFunctionBody(Body);
598 InsertBlockLiteralsWithinMethod(MD);
599 CurMethodDef = 0;
600 }
601 }
602 if (ValueDecl *ND = dyn_cast<ValueDecl>(D)) {
603 if (isBlockPointerType(ND->getType()))
604 RewriteBlockPointerDecl(ND);
605 return;
606 }
607 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
608 if (isBlockPointerType(TD->getUnderlyingType()))
609 RewriteBlockPointerDecl(TD);
610 return;
611 }
612}
613
614void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
615 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
616 CI != E; ++CI)
617 if (*CI)
618 GetBlockDeclRefExprs(*CI);
619
620 // Handle specific things.
621 if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
622 // FIXME: Handle enums.
623 if (!isa<FunctionDecl>(CDRE->getDecl()))
624 BlockDeclRefs.push_back(CDRE);
625 return;
626}
627
628void RewriteBlocks::GetBlockCallExprs(Stmt *S) {
629 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
630 CI != E; ++CI)
631 if (*CI)
632 GetBlockCallExprs(*CI);
633
634 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
635 if (CE->getCallee()->getType()->isBlockPointerType())
636 BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
637 }
638 return;
639}
640
641//===----------------------------------------------------------------------===//
642// Function Body / Expression rewriting
643//===----------------------------------------------------------------------===//
644
645Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
646 // Start by rewriting all children.
647 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
648 CI != E; ++CI)
649 if (*CI) {
Steve Naroff9c3c9022008-09-17 18:37:59 +0000650 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000651 // We intentionally avoid rewritting the contents of a closure block
652 // expr. InsertBlockLiteralsWithinFunction() will rewrite the body.
Steve Naroff9c3c9022008-09-17 18:37:59 +0000653 RewriteBlockExpr(CBE);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000654 } else {
655 Stmt *newStmt = RewriteFunctionBody(*CI);
656 if (newStmt)
657 *CI = newStmt;
658 }
659 }
660 // Handle specific things.
661 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
662 if (CE->getCallee()->getType()->isBlockPointerType())
663 RewriteBlockCall(CE);
664 }
665 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
666 ScopedDecl *SD = DS->getDecl();
667 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
668 if (isBlockPointerType(ND->getType()))
669 RewriteBlockPointerDecl(ND);
670 }
671 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
672 if (isBlockPointerType(TD->getUnderlyingType()))
673 RewriteBlockPointerDecl(TD);
674 }
675 }
676 // Return this stmt unmodified.
677 return S;
678}
679
680std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
681 // Navigate to relevant type information.
682 const char *closureName;
683 const BlockPointerType *CPT;
684
685 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
686 closureName = DRE->getDecl()->getName();
687 CPT = DRE->getType()->getAsBlockPointerType();
688 } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
689 closureName = CDRE->getDecl()->getName();
690 CPT = CDRE->getType()->getAsBlockPointerType();
691 } else {
692 assert(1 && "RewriteBlockClass: Bad type");
693 }
694 assert(CPT && "RewriteBlockClass: Bad type");
695 const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType();
696 assert(FT && "RewriteBlockClass: Bad type");
697 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FT);
698 // FTP will be null for closures that don't take arguments.
699
700 // Build a closure call - start with a paren expr to enforce precedence.
701 std::string BlockCall = "(";
702
703 // Synthesize the cast.
704 BlockCall += "(" + Exp->getType().getAsString() + "(*)";
705 BlockCall += "(struct __closure_impl *";
706 if (FTP) {
707 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
708 E = FTP->arg_type_end(); I && (I != E); ++I)
709 BlockCall += ", " + (*I).getAsString();
710 }
711 BlockCall += "))"; // close the argument list and paren expression.
712
713 // Invoke the closure.
714 BlockCall += closureName;
715 BlockCall += "->Invoke)";
716
717 // Add the arguments.
718 BlockCall += "(";
719 BlockCall += closureName;
720 for (CallExpr::arg_iterator I = Exp->arg_begin(),
721 E = Exp->arg_end(); I != E; ++I) {
722 std::string syncExprBufS;
723 llvm::raw_string_ostream Buf(syncExprBufS);
724 (*I)->printPretty(Buf);
725 BlockCall += ", " + Buf.str();
726 }
727 return BlockCall;
728}
729
730void RewriteBlocks::RewriteBlockCall(CallExpr *Exp) {
731 std::string BlockCall = SynthesizeBlockCall(Exp);
732
733 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
734 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
735
736 ReplaceText(Exp->getLocStart(), endBuf-startBuf,
737 BlockCall.c_str(), BlockCall.size());
738}
739
740void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
741 SourceLocation DeclLoc = FD->getLocation();
742 unsigned parenCount = 0, nArgs = 0;
743
744 // We have 1 or more arguments that have closure pointers.
745 const char *startBuf = SM->getCharacterData(DeclLoc);
746 const char *startArgList = strchr(startBuf, '(');
747
748 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
749
750 parenCount++;
751 // advance the location to startArgList.
752 DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf+1);
753 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
754
755 const char *topLevelCommaCursor = 0;
756 const char *argPtr = startArgList;
757 bool scannedBlockDecl = false;
758 std::string Tag = "struct __closure_impl *";
759
760 while (*argPtr++ && parenCount) {
761 switch (*argPtr) {
762 case '^':
763 scannedBlockDecl = true;
764 break;
765 case '(':
766 parenCount++;
767 break;
768 case ')':
769 parenCount--;
770 if (parenCount == 0) {
771 if (scannedBlockDecl) {
772 // If we are rewriting a definition, don't forget the arg name.
773 if (FD->getBody())
774 Tag += FD->getParamDecl(nArgs)->getName();
775 // The last argument is a closure pointer decl, rewrite it!
776 if (topLevelCommaCursor)
777 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-2, Tag.c_str(), Tag.size());
778 else
779 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
780 scannedBlockDecl = false; // reset.
781 }
782 nArgs++;
783 }
784 break;
785 case ',':
786 if (parenCount == 1) {
787 // Make sure the function takes more than one argument.
788 assert((FD->getNumParams() > 1) && "Rewriter fuzzy parser confused");
789 if (scannedBlockDecl) {
790 // If we are rewriting a definition, don't forget the arg name.
791 if (FD->getBody())
792 Tag += FD->getParamDecl(nArgs)->getName();
793 // The current argument is a closure pointer decl, rewrite it!
794 if (topLevelCommaCursor)
795 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-1, Tag.c_str(), Tag.size());
796 else
797 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
798 scannedBlockDecl = false;
799 }
800 nArgs++;
801 // advance the location to topLevelCommaCursor.
802 if (topLevelCommaCursor)
803 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-topLevelCommaCursor);
804 else
805 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList+1);
806 topLevelCommaCursor = argPtr;
807 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
808 }
809 break;
810 }
811 }
812 return;
813}
814
Steve Naroffeab5f632008-09-23 19:24:41 +0000815bool RewriteBlocks::BlockPointerTypeTakesAnyBlockArguments(QualType QT) {
816 const BlockPointerType *BPT = QT->getAsBlockPointerType();
817 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
818 const FunctionTypeProto *FTP = BPT->getPointeeType()->getAsFunctionTypeProto();
819 if (FTP) {
820 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
821 E = FTP->arg_type_end(); I != E; ++I)
822 if (isBlockPointerType(*I))
823 return true;
824 }
825 return false;
826}
827
828void RewriteBlocks::GetExtentOfArgList(const char *Name,
829 char *&LParen, char *&RParen) {
830 char *argPtr = strchr(Name, '(');
831 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
832
833 LParen = argPtr; // output the start.
834 argPtr++; // skip past the left paren.
835 unsigned parenCount = 1;
836
837 while (*argPtr && parenCount) {
838 switch (*argPtr) {
839 case '(': parenCount++; break;
840 case ')': parenCount--; break;
841 default: break;
842 }
843 if (parenCount) argPtr++;
844 }
845 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
846 RParen = argPtr; // output the end
847}
848
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000849void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000850 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
851 RewriteBlockPointerFunctionArgs(FD);
852 return;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000853 }
854 // Handle Variables and Typedefs.
855 SourceLocation DeclLoc = ND->getLocation();
856 QualType DeclT;
857 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
858 DeclT = VD->getType();
859 else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
860 DeclT = TDD->getUnderlyingType();
861 else
862 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
Steve Naroffeab5f632008-09-23 19:24:41 +0000863
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000864 const char *startBuf = SM->getCharacterData(DeclLoc);
865 const char *endBuf = startBuf;
866 // scan backward (from the decl location) for the end of the previous decl.
867 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
868 startBuf--;
869 assert((*startBuf == '^') &&
870 "RewriteBlockPointerDecl() scan error: no caret");
871 // Replace the '^' with '*', computing a negative offset.
872 DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
873 ReplaceText(DeclLoc, 1, "*", 1);
874
875 if (BlockPointerTypeTakesAnyBlockArguments(DeclT)) {
876 // Replace the '^' with '*' for arguments.
877 DeclLoc = ND->getLocation();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000878 startBuf = SM->getCharacterData(DeclLoc);
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000879 char *argListBegin, *argListEnd;
880 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
881 while (argListBegin < argListEnd) {
882 if (*argListBegin == '^') {
883 SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
884 ReplaceText(CaretLoc, 1, "*", 1);
885 }
886 argListBegin++;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000887 }
Steve Naroffeab5f632008-09-23 19:24:41 +0000888 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000889 return;
890}
891
Steve Naroff9c3c9022008-09-17 18:37:59 +0000892void RewriteBlocks::RewriteBlockExpr(BlockExpr *Exp) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000893 Blocks.push_back(Exp);
894 bool haveByRefDecls = false;
895
896 // Add initializers for any closure decl refs.
897 GetBlockDeclRefExprs(Exp);
898 if (BlockDeclRefs.size()) {
899 // Unique all "by copy" declarations.
900 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
901 if (!BlockDeclRefs[i]->isByRef())
902 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
903 // Unique all "by ref" declarations.
904 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
905 if (BlockDeclRefs[i]->isByRef()) {
906 haveByRefDecls = true;
907 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
908 }
909 }
910 std::string FuncName;
911
912 if (CurFunctionDef)
913 FuncName = std::string(CurFunctionDef->getName());
914 else if (CurMethodDef) {
915 FuncName = std::string(CurMethodDef->getSelector().getName());
916 // Convert colons to underscores.
917 std::string::size_type loc = 0;
918 while ((loc = FuncName.find(":", loc)) != std::string::npos)
919 FuncName.replace(loc, 1, "_");
920 }
921 std::string BlockNumber = utostr(Blocks.size()-1);
922
923 std::string Tag = "struct __" + FuncName + "_closure_impl_" + BlockNumber;
924 std::string Func = "__" + FuncName + "_" + "closure_" + BlockNumber;
925
926 // Rewrite the closure block with a compound literal. The first cast is
927 // to prevent warnings from the C compiler.
928 std::string Init = "(struct __closure_impl *)&(" + Tag + "){{0,";
929
930 // Initialize the Flags, Size, and Invoke fields.
931 Init += (haveByRefDecls ? "HAS_BYREF," : "0,");
932 Init += "sizeof(" + Tag + ")," + Func + "}";
933
934 // Add initializers for any closure decl refs.
935 if (BlockDeclRefs.size()) {
936 // Output all "by copy" declarations.
937 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
938 E = BlockByCopyDecls.end(); I != E; ++I) {
939 Init += ",";
940 if (isObjCType((*I)->getType())) {
941 Init += "[[";
942 Init += (*I)->getName();
943 Init += " retain] autorelease]";
944 } else {
945 Init += (*I)->getName();
946 }
947 }
948 // Output all "by ref" declarations.
949 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
950 E = BlockByRefDecls.end(); I != E; ++I) {
951 Init += ",&";
952 Init += (*I)->getName();
953 }
954 }
955 Init += "}";
956 BlockDeclRefs.clear();
957 BlockByRefDecls.clear();
958 BlockByCopyDecls.clear();
959
960 // Do the rewrite.
961 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
962 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
963 ReplaceText(Exp->getLocStart(), endBuf-startBuf+1, Init.c_str(), Init.size());
964 return;
965}