blob: dbb39401d47624e337d0095540a751d4126153c4 [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 Naroff1c9f81b2008-09-17 00:13:27 +000053
54 // The function/method we are rewriting.
55 FunctionDecl *CurFunctionDef;
56 ObjCMethodDecl *CurMethodDef;
57
58 bool IsHeader;
Steve Naroff13188952008-09-18 14:10:13 +000059 std::string InFileName;
60 std::string OutFileName;
Steve Naroffa0b75cf2008-10-02 23:30:43 +000061
62 std::string Preamble;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000063public:
Steve Naroff13188952008-09-18 14:10:13 +000064 RewriteBlocks(std::string inFile, std::string outFile, Diagnostic &D,
65 const LangOptions &LOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000066 ~RewriteBlocks() {
67 // Get the buffer corresponding to MainFileID.
68 // If we haven't changed it, then we are done.
69 if (const RewriteBuffer *RewriteBuf =
70 Rewrite.getRewriteBufferFor(MainFileID)) {
71 std::string S(RewriteBuf->begin(), RewriteBuf->end());
72 printf("%s\n", S.c_str());
73 } else {
74 printf("No changes\n");
75 }
76 }
77
78 void Initialize(ASTContext &context);
79
80 void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen);
81 void ReplaceText(SourceLocation Start, unsigned OrigLength,
82 const char *NewStr, unsigned NewLength);
83
84 // Top Level Driver code.
85 virtual void HandleTopLevelDecl(Decl *D);
86 void HandleDeclInMainFile(Decl *D);
87
88 // Top level
89 Stmt *RewriteFunctionBody(Stmt *S);
90 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
91 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
92
93 // Block specific rewrite rules.
Steve Naroff39622b92008-10-03 15:38:09 +000094 void RewriteBlockExpr(BlockExpr *Exp, VarDecl *VD=0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000095
96 void RewriteBlockCall(CallExpr *Exp);
97 void RewriteBlockPointerDecl(NamedDecl *VD);
98 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
99
Steve Naroff4e13b762008-10-03 20:28:15 +0000100 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
101 const char *funcName, std::string Tag);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000102 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
103 const char *funcName, std::string Tag);
104 std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag);
105 std::string SynthesizeBlockCall(CallExpr *Exp);
106 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
107 const char *FunName);
108
109 void GetBlockDeclRefExprs(Stmt *S);
110 void GetBlockCallExprs(Stmt *S);
111
112 // We avoid calling Type::isBlockPointerType(), since it operates on the
113 // canonical type. We only care if the top-level type is a closure pointer.
114 bool isBlockPointerType(QualType T) { return isa<BlockPointerType>(T); }
115
116 // FIXME: This predicate seems like it would be useful to add to ASTContext.
117 bool isObjCType(QualType T) {
118 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
119 return false;
120
121 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
122
123 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
124 OCT == Context->getCanonicalType(Context->getObjCClassType()))
125 return true;
126
127 if (const PointerType *PT = OCT->getAsPointerType()) {
128 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
129 isa<ObjCQualifiedIdType>(PT->getPointeeType()))
130 return true;
131 }
132 return false;
133 }
134 // ObjC rewrite methods.
135 void RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl);
136 void RewriteCategoryDecl(ObjCCategoryDecl *CatDecl);
137 void RewriteProtocolDecl(ObjCProtocolDecl *PDecl);
138 void RewriteMethodDecl(ObjCMethodDecl *MDecl);
Steve Naroffeab5f632008-09-23 19:24:41 +0000139
140 bool BlockPointerTypeTakesAnyBlockArguments(QualType QT);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000141 void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000142};
143
144}
145
146static bool IsHeaderFile(const std::string &Filename) {
147 std::string::size_type DotPos = Filename.rfind('.');
148
149 if (DotPos == std::string::npos) {
150 // no file extension
151 return false;
152 }
153
154 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
155 // C header: .h
156 // C++ header: .hh or .H;
157 return Ext == "h" || Ext == "hh" || Ext == "H";
158}
159
Steve Naroff13188952008-09-18 14:10:13 +0000160RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile,
161 Diagnostic &D, const LangOptions &LOpts) :
162 Diags(D), LangOpts(LOpts) {
163 IsHeader = IsHeaderFile(inFile);
164 InFileName = inFile;
165 OutFileName = outFile;
166 CurFunctionDef = 0;
167 CurMethodDef = 0;
168 RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
169 "rewriting failed");
170 NoNestedBlockCalls = Diags.getCustomDiagID(Diagnostic::Warning,
171 "Rewrite support for closure calls nested within closure blocks is incomplete");
172}
173
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000174ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
Steve Naroff13188952008-09-18 14:10:13 +0000175 const std::string& OutFile,
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000176 Diagnostic &Diags,
177 const LangOptions &LangOpts) {
Steve Naroff13188952008-09-18 14:10:13 +0000178 return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000179}
180
181void RewriteBlocks::Initialize(ASTContext &context) {
182 Context = &context;
183 SM = &Context->getSourceManager();
184
185 // Get the ID and start/end of the main file.
186 MainFileID = SM->getMainFileID();
187 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
188 MainFileStart = MainBuf->getBufferStart();
189 MainFileEnd = MainBuf->getBufferEnd();
190
191 Rewrite.setSourceMgr(Context->getSourceManager());
192
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000193 if (IsHeader)
194 Preamble = "#pragma once\n";
195 Preamble += "#ifndef BLOCK_IMPL\n";
196 Preamble += "#define BLOCK_IMPL\n";
197 Preamble += "struct __block_impl {\n";
198 Preamble += " void *isa;\n";
199 Preamble += " int Flags;\n";
200 Preamble += " int Size;\n";
201 Preamble += " void *FuncPtr;\n";
202 Preamble += "};\n";
203 Preamble += "enum {\n";
204 Preamble += " BLOCK_HAS_COPY_DISPOSE = (1<<25),\n";
205 Preamble += " BLOCK_IS_GLOBAL = (1<<28)\n";
206 Preamble += "};\n";
207 if (LangOpts.Microsoft)
208 Preamble += "#define __OBJC_RW_EXTERN extern \"C\" __declspec(dllimport)\n";
209 else
210 Preamble += "#define __OBJC_RW_EXTERN extern\n";
211 Preamble += "// Runtime copy/destroy helper functions\n";
212 Preamble += "__OBJC_RW_EXTERN void _Block_copy_assign(void *, void *);\n";
213 Preamble += "__OBJC_RW_EXTERN void _Block_byref_assign_copy(void *, void *);\n";
214 Preamble += "__OBJC_RW_EXTERN void _Block_destroy(void *);\n";
215 Preamble += "__OBJC_RW_EXTERN void _Block_byref_release(void *);\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000216 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteGlobalBlock;\n";
217 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n";
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000218 Preamble += "#endif\n";
219
220 InsertText(SourceLocation::getFileLoc(MainFileID, 0),
221 Preamble.c_str(), Preamble.size());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000222}
223
224void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData,
225 unsigned StrLen)
226{
227 if (!Rewrite.InsertText(Loc, StrData, StrLen))
228 return;
229 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
230}
231
232void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength,
233 const char *NewStr, unsigned NewLength) {
234 if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength))
235 return;
236 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
237}
238
239void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
240 bool haveBlockPtrs = false;
241 for (ObjCMethodDecl::param_iterator I = Method->param_begin(),
242 E = Method->param_end(); I != E; ++I)
243 if (isBlockPointerType((*I)->getType()))
244 haveBlockPtrs = true;
245
246 if (!haveBlockPtrs)
247 return;
248
249 // Do a fuzzy rewrite.
250 // We have 1 or more arguments that have closure pointers.
251 SourceLocation Loc = Method->getLocStart();
252 SourceLocation LocEnd = Method->getLocEnd();
253 const char *startBuf = SM->getCharacterData(Loc);
254 const char *endBuf = SM->getCharacterData(LocEnd);
255
256 const char *methodPtr = startBuf;
Steve Naroff8af6a452008-10-02 17:12:56 +0000257 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000258
259 while (*methodPtr++ && (methodPtr != endBuf)) {
260 switch (*methodPtr) {
261 case ':':
262 methodPtr++;
263 if (*methodPtr == '(') {
264 const char *scanType = ++methodPtr;
265 bool foundBlockPointer = false;
266 unsigned parenCount = 1;
267
268 while (parenCount) {
269 switch (*scanType) {
270 case '(':
271 parenCount++;
272 break;
273 case ')':
274 parenCount--;
275 break;
276 case '^':
277 foundBlockPointer = true;
278 break;
279 }
280 scanType++;
281 }
282 if (foundBlockPointer) {
283 // advance the location to startArgList.
284 Loc = Loc.getFileLocWithOffset(methodPtr-startBuf);
285 assert((Loc.isValid()) && "Invalid Loc");
286 ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size());
287
288 // Advance startBuf. Since the underlying buffer has changed,
289 // it's very important to advance startBuf (so we can correctly
290 // compute a relative Loc the next time around).
291 startBuf = methodPtr;
292 }
293 // Advance the method ptr to the end of the type.
294 methodPtr = scanType;
295 }
296 break;
297 }
298 }
299 return;
300}
301
302void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
303 for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(),
304 E = ClassDecl->instmeth_end(); I != E; ++I)
305 RewriteMethodDecl(*I);
306 for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(),
307 E = ClassDecl->classmeth_end(); I != E; ++I)
308 RewriteMethodDecl(*I);
309}
310
311void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
312 for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
313 E = CatDecl->instmeth_end(); I != E; ++I)
314 RewriteMethodDecl(*I);
315 for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
316 E = CatDecl->classmeth_end(); I != E; ++I)
317 RewriteMethodDecl(*I);
318}
319
320void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
321 for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
322 E = PDecl->instmeth_end(); I != E; ++I)
323 RewriteMethodDecl(*I);
324 for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
325 E = PDecl->classmeth_end(); I != E; ++I)
326 RewriteMethodDecl(*I);
327}
328
329//===----------------------------------------------------------------------===//
330// Top Level Driver Code
331//===----------------------------------------------------------------------===//
332
333void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
334 // Two cases: either the decl could be in the main file, or it could be in a
335 // #included file. If the former, rewrite it now. If the later, check to see
336 // if we rewrote the #include/#import.
337 SourceLocation Loc = D->getLocation();
338 Loc = SM->getLogicalLoc(Loc);
339
340 // If this is for a builtin, ignore it.
341 if (Loc.isInvalid()) return;
342
343 if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D))
344 RewriteInterfaceDecl(MD);
345 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D))
346 RewriteCategoryDecl(CD);
347 else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
348 RewriteProtocolDecl(PD);
349
350 // If we have a decl in the main file, see if we should rewrite it.
351 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
352 HandleDeclInMainFile(D);
353 return;
354}
355
356std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
357 const char *funcName,
358 std::string Tag) {
359 const FunctionType *AFT = CE->getFunctionType();
360 QualType RT = AFT->getResultType();
Steve Naroff48a8c612008-10-03 12:09:49 +0000361 std::string StructRef = "struct " + Tag;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000362 std::string S = "static " + RT.getAsString() + " __" +
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000363 funcName + "_" + "block_func_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000364
365 if (isa<FunctionTypeNoProto>(AFT)) {
366 S += "()";
367 } else if (CE->arg_empty()) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000368 S += "(" + StructRef + " *__cself)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000369 } else {
370 const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
371 assert(FT && "SynthesizeBlockFunc: No function proto");
372 S += '(';
373 // first add the implicit argument.
Steve Naroff48a8c612008-10-03 12:09:49 +0000374 S += StructRef + " *__cself, ";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000375 std::string ParamStr;
Steve Naroff9c3c9022008-09-17 18:37:59 +0000376 for (BlockExpr::arg_iterator AI = CE->arg_begin(),
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000377 E = CE->arg_end(); AI != E; ++AI) {
378 if (AI != CE->arg_begin()) S += ", ";
379 ParamStr = (*AI)->getName();
380 (*AI)->getType().getAsStringInternal(ParamStr);
381 S += ParamStr;
382 }
383 if (FT->isVariadic()) {
384 if (!CE->arg_empty()) S += ", ";
385 S += "...";
386 }
387 S += ')';
388 }
389 S += " {\n";
390
391 bool haveByRefDecls = false;
392
393 // Create local declarations to avoid rewriting all closure decl ref exprs.
394 // First, emit a declaration for all "by ref" decls.
395 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
396 E = BlockByRefDecls.end(); I != E; ++I) {
397 // Note: It is not possible to have "by ref" closure pointer decls.
398 haveByRefDecls = true;
399 S += " ";
400 std::string Name = (*I)->getName();
401 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
402 S += Name + " = __cself->" + (*I)->getName() + "; // bound by ref\n";
403 }
404 // Next, emit a declaration for all "by copy" declarations.
405 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
406 E = BlockByCopyDecls.end(); I != E; ++I) {
407 S += " ";
408 std::string Name = (*I)->getName();
409 // Handle nested closure invocation. For example:
410 //
411 // void (^myImportedClosure)(void);
412 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
413 //
414 // void (^anotherClosure)(void);
415 // anotherClosure = ^(void) {
416 // myImportedClosure(); // import and invoke the closure
417 // };
418 //
419 if (isBlockPointerType((*I)->getType()))
Steve Naroff8af6a452008-10-02 17:12:56 +0000420 S += "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000421 else
422 (*I)->getType().getAsStringInternal(Name);
423 S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
424 }
Steve Naroff9c3c9022008-09-17 18:37:59 +0000425 if (BlockExpr *CBE = dyn_cast<BlockExpr>(CE)) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000426 std::string BodyBuf;
427
428 SourceLocation BodyLocStart = CBE->getBody()->getLocStart();
429 SourceLocation BodyLocEnd = CBE->getBody()->getLocEnd();
430 const char *BodyStartBuf = SM->getCharacterData(BodyLocStart);
431 const char *BodyEndBuf = SM->getCharacterData(BodyLocEnd);
432
433 BodyBuf.append(BodyStartBuf, BodyEndBuf-BodyStartBuf+1);
434
Steve Naroff4e13b762008-10-03 20:28:15 +0000435 //fprintf(stderr, "BodyBuf=>%s\n", BodyBuf.c_str());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000436 if (BlockDeclRefs.size()) {
437 unsigned int nCharsAdded = 0;
438 for (unsigned i = 0; i < BlockDeclRefs.size(); i++) {
439 if (BlockDeclRefs[i]->isByRef()) {
440 // Add a level of indirection! The code below assumes
441 // the closure decl refs/locations are in strictly ascending
442 // order. The traversal performed by GetBlockDeclRefExprs()
443 // currently does this. FIXME: Wrap the *x with parens,
444 // just in case x is a more complex expression, like x->member,
445 // which needs to be rewritten to (*x)->member.
446 SourceLocation StarLoc = BlockDeclRefs[i]->getLocStart();
447 const char *StarBuf = SM->getCharacterData(StarLoc);
448 BodyBuf.insert(StarBuf-BodyStartBuf+nCharsAdded, 1, '*');
449 // Get a fresh buffer, the insert might have caused it to grow.
450 BodyStartBuf = SM->getCharacterData(BodyLocStart);
451 nCharsAdded++;
452 } else if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
453 Diags.Report(NoNestedBlockCalls);
454
455 GetBlockCallExprs(CE);
Steve Naroff4e13b762008-10-03 20:28:15 +0000456 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000457
458 // Rewrite the closure in place.
459 // The character based equivalent of RewriteBlockCall().
460 // Need to get the CallExpr associated with this BlockDeclRef.
461 std::string BlockCall = SynthesizeBlockCall(BlockCallExprs[BlockDeclRefs[i]]);
462
Steve Naroff4e13b762008-10-03 20:28:15 +0000463 // FIXME: this is still incomplete.
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000464 SourceLocation CallLocStart = BlockCallExprs[BlockDeclRefs[i]]->getLocStart();
465 SourceLocation CallLocEnd = BlockCallExprs[BlockDeclRefs[i]]->getLocEnd();
Steve Naroff4e13b762008-10-03 20:28:15 +0000466 const char *CallStart = SM->getCharacterData(CallLocStart) + nCharsAdded;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000467 const char *CallEnd = SM->getCharacterData(CallLocEnd);
468 unsigned CallBytes = CallEnd-CallStart;
Steve Naroff4e13b762008-10-03 20:28:15 +0000469 //fprintf(stderr, "BlockCall=>%s CallStart=%d\n", BlockCall.c_str(),CallStart);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000470 BodyBuf.replace(CallStart-BodyStartBuf, CallBytes, BlockCall.c_str());
471 nCharsAdded += CallBytes;
472 }
473 }
474 }
475 if (haveByRefDecls) {
476 // Remove |...|.
Steve Naroffeab5f632008-09-23 19:24:41 +0000477 //const char *firstBarPtr = strchr(BodyStartBuf, '|');
478 //const char *secondBarPtr = strchr(firstBarPtr+1, '|');
479 //BodyBuf.replace(firstBarPtr-BodyStartBuf, secondBarPtr-firstBarPtr+1, "");
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000480 }
481 S += " ";
482 S += BodyBuf;
483 }
484 S += "\n}\n";
485 return S;
486}
487
Steve Naroff4e13b762008-10-03 20:28:15 +0000488std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
489 const char *funcName,
490 std::string Tag) {
491 std::string StructRef = "struct " + Tag;
492 std::string S = "static void __";
493
494 S += funcName;
495 S += "_block_copy_" + utostr(i);
496 S += "(" + StructRef;
497 S += "*dst, " + StructRef;
498 S += "*src) {";
499 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
500 E = ImportedBlockDecls.end(); I != E; ++I) {
501 S += "_Block_copy_assign(&dst->";
502 S += (*I)->getName();
503 S += ", src->";
504 S += (*I)->getName();
505 S += ");}";
506 }
507 S += "\nstatic void __";
508 S += funcName;
509 S += "_block_dispose_" + utostr(i);
510 S += "(" + StructRef;
511 S += "*src) {";
512 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
513 E = ImportedBlockDecls.end(); I != E; ++I) {
514 S += "_Block_destroy(src->";
515 S += (*I)->getName();
516 S += ");";
517 }
518 S += "}\n";
519 return S;
520}
521
Steve Naroff48a8c612008-10-03 12:09:49 +0000522std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag) {
523 std::string S = "struct " + Tag;
524 std::string Constructor = " " + Tag;
525
526 S += " {\n struct __block_impl impl;\n";
527 Constructor += "(void *fp";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000528
529 GetBlockDeclRefExprs(CE);
530 if (BlockDeclRefs.size()) {
531 // Unique all "by copy" declarations.
532 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
533 if (!BlockDeclRefs[i]->isByRef())
534 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
535 // Unique all "by ref" declarations.
536 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
537 if (BlockDeclRefs[i]->isByRef())
538 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
539
540 // Output all "by copy" declarations.
541 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
542 E = BlockByCopyDecls.end(); I != E; ++I) {
543 S += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000544 std::string FieldName = (*I)->getName();
545 std::string ArgName = "_" + FieldName;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000546 // Handle nested closure invocation. For example:
547 //
548 // void (^myImportedBlock)(void);
549 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
550 //
551 // void (^anotherBlock)(void);
552 // anotherBlock = ^(void) {
553 // myImportedBlock(); // import and invoke the closure
554 // };
555 //
Steve Naroff4e13b762008-10-03 20:28:15 +0000556 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000557 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000558 Constructor += ", void *" + ArgName;
559 } else {
560 (*I)->getType().getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000561 (*I)->getType().getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000562 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000563 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000564 S += FieldName + ";\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000565 }
566 // Output all "by ref" declarations.
567 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
568 E = BlockByRefDecls.end(); I != E; ++I) {
569 S += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000570 std::string FieldName = (*I)->getName();
571 std::string ArgName = "_" + FieldName;
572 // Handle nested closure invocation. For example:
573 //
574 // void (^myImportedBlock)(void);
575 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
576 //
577 // void (^anotherBlock)(void);
578 // anotherBlock = ^(void) {
579 // myImportedBlock(); // import and invoke the closure
580 // };
581 //
582 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000583 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000584 Constructor += ", void *" + ArgName;
585 } else {
586 Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000587 Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000588 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000589 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000590 S += FieldName + "; // by ref\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000591 }
592 // Finish writing the constructor.
593 // FIXME: handle NSConcreteGlobalBlock.
594 Constructor += ", int flags=0) {\n";
Steve Naroff83ba14e2008-10-03 15:04:50 +0000595 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
Steve Naroff48a8c612008-10-03 12:09:49 +0000596 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
597
598 // Initialize all "by copy" arguments.
599 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
600 E = BlockByCopyDecls.end(); I != E; ++I) {
601 std::string Name = (*I)->getName();
602 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000603 if (isBlockPointerType((*I)->getType()))
604 Constructor += Name + " = (struct __block_impl *)_";
605 else
606 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000607 Constructor += Name + ";\n";
608 }
609 // Initialize all "by ref" arguments.
610 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
611 E = BlockByRefDecls.end(); I != E; ++I) {
612 std::string Name = (*I)->getName();
613 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000614 if (isBlockPointerType((*I)->getType()))
615 Constructor += Name + " = (struct __block_impl *)_";
616 else
617 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000618 Constructor += Name + ";\n";
619 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000620 } else {
621 // Finish writing the constructor.
622 // FIXME: handle NSConcreteGlobalBlock.
623 Constructor += ", int flags=0) {\n";
624 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
625 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000626 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000627 Constructor += " ";
628 Constructor += "}\n";
629 S += Constructor;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000630 S += "};\n";
631 return S;
632}
633
634void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
635 const char *FunName) {
636 // Insert closures that were part of the function.
637 for (unsigned i = 0; i < Blocks.size(); i++) {
638
Steve Naroff48a8c612008-10-03 12:09:49 +0000639 std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000640
641 std::string CI = SynthesizeBlockImpl(Blocks[i], Tag);
642
643 InsertText(FunLocStart, CI.c_str(), CI.size());
Steve Naroff4e13b762008-10-03 20:28:15 +0000644
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000645 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
646
647 InsertText(FunLocStart, CF.c_str(), CF.size());
648
Steve Naroff4e13b762008-10-03 20:28:15 +0000649 if (ImportedBlockDecls.size()) {
650 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
651 InsertText(FunLocStart, HF.c_str(), HF.size());
652 }
653
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000654 BlockDeclRefs.clear();
655 BlockByRefDecls.clear();
656 BlockByCopyDecls.clear();
657 BlockCallExprs.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000658 ImportedBlockDecls.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000659 }
660 Blocks.clear();
661}
662
663void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
Steve Naroff3ad29e22008-10-03 00:12:09 +0000664 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000665 const char *FuncName = FD->getName();
666
667 SynthesizeBlockLiterals(FunLocStart, FuncName);
668}
669
670void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
671 SourceLocation FunLocStart = MD->getLocStart();
672 std::string FuncName = std::string(MD->getSelector().getName());
673 // Convert colons to underscores.
674 std::string::size_type loc = 0;
675 while ((loc = FuncName.find(":", loc)) != std::string::npos)
676 FuncName.replace(loc, 1, "_");
677
678 SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
679}
680
681/// HandleDeclInMainFile - This is called for each top-level decl defined in the
682/// main file of the input.
683void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
684 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
685
686 // Since function prototypes don't have ParmDecl's, we check the function
687 // prototype. This enables us to rewrite function declarations and
688 // definitions using the same code.
689 QualType funcType = FD->getType();
690
691 if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
692 for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(),
693 E = fproto->arg_type_end(); I && (I != E); ++I)
694 if (isBlockPointerType(*I)) {
695 // All the args are checked/rewritten. Don't call twice!
696 RewriteBlockPointerDecl(FD);
697 break;
698 }
699 }
700 if (Stmt *Body = FD->getBody()) {
701 CurFunctionDef = FD;
702 FD->setBody(RewriteFunctionBody(Body));
703 InsertBlockLiteralsWithinFunction(FD);
704 CurFunctionDef = 0;
705 }
706 return;
707 }
708 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
709 RewriteMethodDecl(MD);
710 if (Stmt *Body = MD->getBody()) {
711 CurMethodDef = MD;
712 RewriteFunctionBody(Body);
713 InsertBlockLiteralsWithinMethod(MD);
714 CurMethodDef = 0;
715 }
716 }
Steve Naroff39622b92008-10-03 15:38:09 +0000717 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
718 if (isBlockPointerType(VD->getType())) {
719 RewriteBlockPointerDecl(VD);
720 if (VD->getInit()) {
721 if (BlockExpr *BExp = dyn_cast<BlockExpr>(VD->getInit())) {
722 RewriteBlockExpr(BExp, VD);
723 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
724 }
725 }
726 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000727 return;
728 }
729 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
730 if (isBlockPointerType(TD->getUnderlyingType()))
731 RewriteBlockPointerDecl(TD);
732 return;
733 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000734 if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
735 if (RD->isDefinition()) {
736 for (RecordDecl::field_const_iterator i = RD->field_begin(),
737 e = RD->field_end(); i != e; ++i) {
738 FieldDecl *FD = *i;
739 if (isBlockPointerType(FD->getType()))
740 RewriteBlockPointerDecl(FD);
741 }
742 }
743 return;
744 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000745}
746
747void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
748 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
749 CI != E; ++CI)
750 if (*CI)
751 GetBlockDeclRefExprs(*CI);
752
753 // Handle specific things.
754 if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
755 // FIXME: Handle enums.
756 if (!isa<FunctionDecl>(CDRE->getDecl()))
757 BlockDeclRefs.push_back(CDRE);
758 return;
759}
760
761void RewriteBlocks::GetBlockCallExprs(Stmt *S) {
762 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
763 CI != E; ++CI)
764 if (*CI)
765 GetBlockCallExprs(*CI);
766
767 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
Steve Naroff4e13b762008-10-03 20:28:15 +0000768 if (CE->getCallee()->getType()->isBlockPointerType()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000769 BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
Steve Naroff4e13b762008-10-03 20:28:15 +0000770 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000771 }
772 return;
773}
774
775//===----------------------------------------------------------------------===//
776// Function Body / Expression rewriting
777//===----------------------------------------------------------------------===//
778
779Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
780 // Start by rewriting all children.
781 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
782 CI != E; ++CI)
783 if (*CI) {
Steve Naroff9c3c9022008-09-17 18:37:59 +0000784 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000785 // We intentionally avoid rewritting the contents of a closure block
786 // expr. InsertBlockLiteralsWithinFunction() will rewrite the body.
Steve Naroff9c3c9022008-09-17 18:37:59 +0000787 RewriteBlockExpr(CBE);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000788 } else {
789 Stmt *newStmt = RewriteFunctionBody(*CI);
790 if (newStmt)
791 *CI = newStmt;
792 }
793 }
794 // Handle specific things.
795 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
796 if (CE->getCallee()->getType()->isBlockPointerType())
797 RewriteBlockCall(CE);
798 }
799 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
800 ScopedDecl *SD = DS->getDecl();
801 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
802 if (isBlockPointerType(ND->getType()))
803 RewriteBlockPointerDecl(ND);
804 }
805 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
806 if (isBlockPointerType(TD->getUnderlyingType()))
807 RewriteBlockPointerDecl(TD);
808 }
809 }
810 // Return this stmt unmodified.
811 return S;
812}
813
814std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
815 // Navigate to relevant type information.
Steve Naroffcc2ece22008-09-24 22:46:45 +0000816 const char *closureName = 0;
817 const BlockPointerType *CPT = 0;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000818
819 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
820 closureName = DRE->getDecl()->getName();
821 CPT = DRE->getType()->getAsBlockPointerType();
822 } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
823 closureName = CDRE->getDecl()->getName();
824 CPT = CDRE->getType()->getAsBlockPointerType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000825 } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
826 closureName = MExpr->getMemberDecl()->getName();
827 CPT = MExpr->getType()->getAsBlockPointerType();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000828 } else {
829 assert(1 && "RewriteBlockClass: Bad type");
830 }
831 assert(CPT && "RewriteBlockClass: Bad type");
832 const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType();
833 assert(FT && "RewriteBlockClass: Bad type");
834 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FT);
835 // FTP will be null for closures that don't take arguments.
836
837 // Build a closure call - start with a paren expr to enforce precedence.
838 std::string BlockCall = "(";
839
840 // Synthesize the cast.
841 BlockCall += "(" + Exp->getType().getAsString() + "(*)";
Steve Naroff8af6a452008-10-02 17:12:56 +0000842 BlockCall += "(struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000843 if (FTP) {
844 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
845 E = FTP->arg_type_end(); I && (I != E); ++I)
846 BlockCall += ", " + (*I).getAsString();
847 }
848 BlockCall += "))"; // close the argument list and paren expression.
849
Steve Naroff83ba14e2008-10-03 15:04:50 +0000850 // Invoke the closure. We need to cast it since the declaration type is
851 // bogus (it's a function pointer type)
852 BlockCall += "((struct __block_impl *)";
853 std::string closureExprBufStr;
854 llvm::raw_string_ostream closureExprBuf(closureExprBufStr);
855 Exp->getCallee()->printPretty(closureExprBuf);
856 BlockCall += closureExprBuf.str();
857 BlockCall += ")->FuncPtr)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000858
859 // Add the arguments.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000860 BlockCall += "((struct __block_impl *)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000861 BlockCall += closureName;
862 for (CallExpr::arg_iterator I = Exp->arg_begin(),
863 E = Exp->arg_end(); I != E; ++I) {
864 std::string syncExprBufS;
865 llvm::raw_string_ostream Buf(syncExprBufS);
866 (*I)->printPretty(Buf);
867 BlockCall += ", " + Buf.str();
868 }
869 return BlockCall;
870}
871
872void RewriteBlocks::RewriteBlockCall(CallExpr *Exp) {
873 std::string BlockCall = SynthesizeBlockCall(Exp);
874
875 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
876 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
877
878 ReplaceText(Exp->getLocStart(), endBuf-startBuf,
879 BlockCall.c_str(), BlockCall.size());
880}
881
882void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
883 SourceLocation DeclLoc = FD->getLocation();
884 unsigned parenCount = 0, nArgs = 0;
885
886 // We have 1 or more arguments that have closure pointers.
887 const char *startBuf = SM->getCharacterData(DeclLoc);
888 const char *startArgList = strchr(startBuf, '(');
889
890 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
891
892 parenCount++;
893 // advance the location to startArgList.
894 DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf+1);
895 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
896
897 const char *topLevelCommaCursor = 0;
898 const char *argPtr = startArgList;
899 bool scannedBlockDecl = false;
Steve Naroff8af6a452008-10-02 17:12:56 +0000900 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000901
902 while (*argPtr++ && parenCount) {
903 switch (*argPtr) {
904 case '^':
905 scannedBlockDecl = true;
906 break;
907 case '(':
908 parenCount++;
909 break;
910 case ')':
911 parenCount--;
912 if (parenCount == 0) {
913 if (scannedBlockDecl) {
914 // If we are rewriting a definition, don't forget the arg name.
915 if (FD->getBody())
916 Tag += FD->getParamDecl(nArgs)->getName();
917 // The last argument is a closure pointer decl, rewrite it!
918 if (topLevelCommaCursor)
919 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-2, Tag.c_str(), Tag.size());
920 else
921 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
922 scannedBlockDecl = false; // reset.
923 }
924 nArgs++;
925 }
926 break;
927 case ',':
928 if (parenCount == 1) {
929 // Make sure the function takes more than one argument.
930 assert((FD->getNumParams() > 1) && "Rewriter fuzzy parser confused");
931 if (scannedBlockDecl) {
932 // If we are rewriting a definition, don't forget the arg name.
933 if (FD->getBody())
934 Tag += FD->getParamDecl(nArgs)->getName();
935 // The current argument is a closure pointer decl, rewrite it!
936 if (topLevelCommaCursor)
937 ReplaceText(DeclLoc, argPtr-topLevelCommaCursor-1, Tag.c_str(), Tag.size());
938 else
939 ReplaceText(DeclLoc, argPtr-startArgList-1, Tag.c_str(), Tag.size());
940 scannedBlockDecl = false;
941 }
942 nArgs++;
943 // advance the location to topLevelCommaCursor.
944 if (topLevelCommaCursor)
945 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-topLevelCommaCursor);
946 else
947 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList+1);
948 topLevelCommaCursor = argPtr;
949 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
950 }
951 break;
952 }
953 }
954 return;
955}
956
Steve Naroffeab5f632008-09-23 19:24:41 +0000957bool RewriteBlocks::BlockPointerTypeTakesAnyBlockArguments(QualType QT) {
958 const BlockPointerType *BPT = QT->getAsBlockPointerType();
959 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
960 const FunctionTypeProto *FTP = BPT->getPointeeType()->getAsFunctionTypeProto();
961 if (FTP) {
962 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
963 E = FTP->arg_type_end(); I != E; ++I)
964 if (isBlockPointerType(*I))
965 return true;
966 }
967 return false;
968}
969
970void RewriteBlocks::GetExtentOfArgList(const char *Name,
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000971 const char *&LParen, const char *&RParen) {
972 const char *argPtr = strchr(Name, '(');
Steve Naroffeab5f632008-09-23 19:24:41 +0000973 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
974
975 LParen = argPtr; // output the start.
976 argPtr++; // skip past the left paren.
977 unsigned parenCount = 1;
978
979 while (*argPtr && parenCount) {
980 switch (*argPtr) {
981 case '(': parenCount++; break;
982 case ')': parenCount--; break;
983 default: break;
984 }
985 if (parenCount) argPtr++;
986 }
987 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
988 RParen = argPtr; // output the end
989}
990
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000991void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000992 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
993 RewriteBlockPointerFunctionArgs(FD);
994 return;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000995 }
996 // Handle Variables and Typedefs.
997 SourceLocation DeclLoc = ND->getLocation();
998 QualType DeclT;
999 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
1000 DeclT = VD->getType();
1001 else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
1002 DeclT = TDD->getUnderlyingType();
Steve Naroff83ba14e2008-10-03 15:04:50 +00001003 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
1004 DeclT = FD->getType();
Steve Naroffca3bb4f2008-09-23 21:15:53 +00001005 else
1006 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
Steve Naroffeab5f632008-09-23 19:24:41 +00001007
Steve Naroffca3bb4f2008-09-23 21:15:53 +00001008 const char *startBuf = SM->getCharacterData(DeclLoc);
1009 const char *endBuf = startBuf;
1010 // scan backward (from the decl location) for the end of the previous decl.
1011 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
1012 startBuf--;
1013 assert((*startBuf == '^') &&
1014 "RewriteBlockPointerDecl() scan error: no caret");
1015 // Replace the '^' with '*', computing a negative offset.
1016 DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
1017 ReplaceText(DeclLoc, 1, "*", 1);
1018
1019 if (BlockPointerTypeTakesAnyBlockArguments(DeclT)) {
1020 // Replace the '^' with '*' for arguments.
1021 DeclLoc = ND->getLocation();
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001022 startBuf = SM->getCharacterData(DeclLoc);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +00001023 const char *argListBegin, *argListEnd;
Steve Naroffca3bb4f2008-09-23 21:15:53 +00001024 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
1025 while (argListBegin < argListEnd) {
1026 if (*argListBegin == '^') {
1027 SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
1028 ReplaceText(CaretLoc, 1, "*", 1);
1029 }
1030 argListBegin++;
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001031 }
Steve Naroffeab5f632008-09-23 19:24:41 +00001032 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001033 return;
1034}
1035
Steve Naroff39622b92008-10-03 15:38:09 +00001036void RewriteBlocks::RewriteBlockExpr(BlockExpr *Exp, VarDecl *VD) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001037 Blocks.push_back(Exp);
1038 bool haveByRefDecls = false;
1039
1040 // Add initializers for any closure decl refs.
1041 GetBlockDeclRefExprs(Exp);
1042 if (BlockDeclRefs.size()) {
1043 // Unique all "by copy" declarations.
1044 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
1045 if (!BlockDeclRefs[i]->isByRef())
1046 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
1047 // Unique all "by ref" declarations.
1048 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
1049 if (BlockDeclRefs[i]->isByRef()) {
1050 haveByRefDecls = true;
1051 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
1052 }
1053 }
1054 std::string FuncName;
1055
1056 if (CurFunctionDef)
1057 FuncName = std::string(CurFunctionDef->getName());
1058 else if (CurMethodDef) {
1059 FuncName = std::string(CurMethodDef->getSelector().getName());
1060 // Convert colons to underscores.
1061 std::string::size_type loc = 0;
1062 while ((loc = FuncName.find(":", loc)) != std::string::npos)
1063 FuncName.replace(loc, 1, "_");
Steve Naroff39622b92008-10-03 15:38:09 +00001064 } else if (VD)
1065 FuncName = std::string(VD->getName());
1066
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001067 std::string BlockNumber = utostr(Blocks.size()-1);
1068
Steve Naroff83ba14e2008-10-03 15:04:50 +00001069 std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
Steve Naroffa0b75cf2008-10-02 23:30:43 +00001070 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001071
Steve Naroff83ba14e2008-10-03 15:04:50 +00001072 std::string FunkTypeStr;
1073
1074 // Get a pointer to the function type so we can cast appropriately.
1075 Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr);
1076
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001077 // Rewrite the closure block with a compound literal. The first cast is
1078 // to prevent warnings from the C compiler.
Steve Naroff83ba14e2008-10-03 15:04:50 +00001079 std::string Init = "(" + FunkTypeStr;
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001080
Steve Naroff83ba14e2008-10-03 15:04:50 +00001081 Init += ")&" + Tag;
1082
1083 // Initialize the block function.
1084 Init += "((void*)" + Func;
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001085
1086 // Add initializers for any closure decl refs.
1087 if (BlockDeclRefs.size()) {
1088 // Output all "by copy" declarations.
1089 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
1090 E = BlockByCopyDecls.end(); I != E; ++I) {
1091 Init += ",";
1092 if (isObjCType((*I)->getType())) {
1093 Init += "[[";
1094 Init += (*I)->getName();
1095 Init += " retain] autorelease]";
Steve Naroff4e13b762008-10-03 20:28:15 +00001096 } else if (isBlockPointerType((*I)->getType())) {
1097 Init += "(void *)";
1098 Init += (*I)->getName();
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001099 } else {
1100 Init += (*I)->getName();
1101 }
1102 }
1103 // Output all "by ref" declarations.
1104 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
1105 E = BlockByRefDecls.end(); I != E; ++I) {
1106 Init += ",&";
1107 Init += (*I)->getName();
1108 }
1109 }
Steve Naroff83ba14e2008-10-03 15:04:50 +00001110 Init += ")";
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001111 BlockDeclRefs.clear();
1112 BlockByRefDecls.clear();
1113 BlockByCopyDecls.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +00001114 ImportedBlockDecls.clear();
1115
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001116 // Do the rewrite.
1117 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
1118 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
1119 ReplaceText(Exp->getLocStart(), endBuf-startBuf+1, Init.c_str(), Init.size());
1120 return;
1121}