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