blob: 5b6e1a988d8eeee7e8c318edb5ab3f4328f30382 [file] [log] [blame]
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001//===--- RewriteBlocks.cpp ----------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the closure rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
15#include "clang/Rewrite/Rewriter.h"
16#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
18#include "clang/Basic/SourceManager.h"
19#include "clang/Basic/IdentifierTable.h"
20#include "clang/Basic/Diagnostic.h"
21#include "clang/Basic/LangOptions.h"
22#include "llvm/Support/MemoryBuffer.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/ADT/SmallPtrSet.h"
25#include <sstream>
26
27using namespace clang;
28using llvm::utostr;
29
30namespace {
31
32class RewriteBlocks : public ASTConsumer {
33 Rewriter Rewrite;
34 Diagnostic &Diags;
35 const LangOptions &LangOpts;
36 unsigned RewriteFailedDiag;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000037
38 ASTContext *Context;
39 SourceManager *SM;
40 unsigned MainFileID;
41 const char *MainFileStart, *MainFileEnd;
42
43 // Block expressions.
44 llvm::SmallVector<BlockExpr *, 32> Blocks;
45 llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
46 llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs;
47
48 // Block related declarations.
49 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
50 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
Steve Naroff4e13b762008-10-03 20:28:15 +000051 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
Steve Naroff70f95502008-10-04 17:06:23 +000052
53 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000054
55 // The function/method we are rewriting.
56 FunctionDecl *CurFunctionDef;
57 ObjCMethodDecl *CurMethodDef;
58
59 bool IsHeader;
Steve Naroff13188952008-09-18 14:10:13 +000060 std::string InFileName;
61 std::string OutFileName;
Steve Naroffa0b75cf2008-10-02 23:30:43 +000062
63 std::string Preamble;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000064public:
Steve Naroff13188952008-09-18 14:10:13 +000065 RewriteBlocks(std::string inFile, std::string outFile, Diagnostic &D,
66 const LangOptions &LOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000067 ~RewriteBlocks() {
68 // Get the buffer corresponding to MainFileID.
69 // If we haven't changed it, then we are done.
70 if (const RewriteBuffer *RewriteBuf =
71 Rewrite.getRewriteBufferFor(MainFileID)) {
72 std::string S(RewriteBuf->begin(), RewriteBuf->end());
73 printf("%s\n", S.c_str());
74 } else {
75 printf("No changes\n");
76 }
77 }
78
79 void Initialize(ASTContext &context);
80
81 void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen);
82 void ReplaceText(SourceLocation Start, unsigned OrigLength,
83 const char *NewStr, unsigned NewLength);
84
85 // Top Level Driver code.
86 virtual void HandleTopLevelDecl(Decl *D);
87 void HandleDeclInMainFile(Decl *D);
88
89 // Top level
90 Stmt *RewriteFunctionBody(Stmt *S);
91 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
92 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
93
94 // Block specific rewrite rules.
Steve Naroff70f95502008-10-04 17:06:23 +000095 std::string SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD=0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000096
97 void RewriteBlockCall(CallExpr *Exp);
98 void RewriteBlockPointerDecl(NamedDecl *VD);
Steve Naroff5e52b172008-10-04 18:52:47 +000099 void RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000100 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
101
Steve Naroff4e13b762008-10-03 20:28:15 +0000102 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
103 const char *funcName, std::string Tag);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000104 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
105 const char *funcName, std::string Tag);
Steve Naroffacba0f22008-10-04 23:47:37 +0000106 std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
107 bool hasCopyDisposeHelpers);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000108 std::string SynthesizeBlockCall(CallExpr *Exp);
109 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
110 const char *FunName);
111
Steve Naroffd3f77902008-10-05 00:06:12 +0000112 void CollectBlockDeclRefInfo(BlockExpr *Exp);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000113 void GetBlockCallExprs(Stmt *S);
Steve Naroffacba0f22008-10-04 23:47:37 +0000114 void GetBlockDeclRefExprs(Stmt *S);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000115
116 // We avoid calling Type::isBlockPointerType(), since it operates on the
117 // canonical type. We only care if the top-level type is a closure pointer.
118 bool isBlockPointerType(QualType T) { return isa<BlockPointerType>(T); }
119
120 // FIXME: This predicate seems like it would be useful to add to ASTContext.
121 bool isObjCType(QualType T) {
122 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
123 return false;
124
125 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
126
127 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
128 OCT == Context->getCanonicalType(Context->getObjCClassType()))
129 return true;
130
131 if (const PointerType *PT = OCT->getAsPointerType()) {
132 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
133 isa<ObjCQualifiedIdType>(PT->getPointeeType()))
134 return true;
135 }
136 return false;
137 }
138 // ObjC rewrite methods.
139 void RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl);
140 void RewriteCategoryDecl(ObjCCategoryDecl *CatDecl);
141 void RewriteProtocolDecl(ObjCProtocolDecl *PDecl);
142 void RewriteMethodDecl(ObjCMethodDecl *MDecl);
Steve Naroffca743602008-10-15 18:38:58 +0000143
144 void RewriteFunctionTypeProto(QualType funcType, NamedDecl *D);
145 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
146 void RewriteCastExpr(CastExpr *CE);
Steve Naroffeab5f632008-09-23 19:24:41 +0000147
Steve Naroffca743602008-10-15 18:38:58 +0000148 bool PointerTypeTakesAnyBlockArguments(QualType QT);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000149 void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000150};
151
152}
153
154static bool IsHeaderFile(const std::string &Filename) {
155 std::string::size_type DotPos = Filename.rfind('.');
156
157 if (DotPos == std::string::npos) {
158 // no file extension
159 return false;
160 }
161
162 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
163 // C header: .h
164 // C++ header: .hh or .H;
165 return Ext == "h" || Ext == "hh" || Ext == "H";
166}
167
Steve Naroff13188952008-09-18 14:10:13 +0000168RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile,
169 Diagnostic &D, const LangOptions &LOpts) :
170 Diags(D), LangOpts(LOpts) {
171 IsHeader = IsHeaderFile(inFile);
172 InFileName = inFile;
173 OutFileName = outFile;
174 CurFunctionDef = 0;
175 CurMethodDef = 0;
176 RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
177 "rewriting failed");
Steve Naroff13188952008-09-18 14:10:13 +0000178}
179
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000180ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
Steve Naroff13188952008-09-18 14:10:13 +0000181 const std::string& OutFile,
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000182 Diagnostic &Diags,
183 const LangOptions &LangOpts) {
Steve Naroff13188952008-09-18 14:10:13 +0000184 return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000185}
186
187void RewriteBlocks::Initialize(ASTContext &context) {
188 Context = &context;
189 SM = &Context->getSourceManager();
190
191 // Get the ID and start/end of the main file.
192 MainFileID = SM->getMainFileID();
193 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
194 MainFileStart = MainBuf->getBufferStart();
195 MainFileEnd = MainBuf->getBufferEnd();
196
197 Rewrite.setSourceMgr(Context->getSourceManager());
198
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000199 if (IsHeader)
200 Preamble = "#pragma once\n";
201 Preamble += "#ifndef BLOCK_IMPL\n";
202 Preamble += "#define BLOCK_IMPL\n";
203 Preamble += "struct __block_impl {\n";
204 Preamble += " void *isa;\n";
205 Preamble += " int Flags;\n";
206 Preamble += " int Size;\n";
207 Preamble += " void *FuncPtr;\n";
208 Preamble += "};\n";
209 Preamble += "enum {\n";
210 Preamble += " BLOCK_HAS_COPY_DISPOSE = (1<<25),\n";
211 Preamble += " BLOCK_IS_GLOBAL = (1<<28)\n";
212 Preamble += "};\n";
213 if (LangOpts.Microsoft)
214 Preamble += "#define __OBJC_RW_EXTERN extern \"C\" __declspec(dllimport)\n";
215 else
216 Preamble += "#define __OBJC_RW_EXTERN extern\n";
217 Preamble += "// Runtime copy/destroy helper functions\n";
218 Preamble += "__OBJC_RW_EXTERN void _Block_copy_assign(void *, void *);\n";
219 Preamble += "__OBJC_RW_EXTERN void _Block_byref_assign_copy(void *, void *);\n";
220 Preamble += "__OBJC_RW_EXTERN void _Block_destroy(void *);\n";
221 Preamble += "__OBJC_RW_EXTERN void _Block_byref_release(void *);\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000222 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteGlobalBlock;\n";
223 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n";
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000224 Preamble += "#endif\n";
225
226 InsertText(SourceLocation::getFileLoc(MainFileID, 0),
227 Preamble.c_str(), Preamble.size());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000228}
229
230void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData,
231 unsigned StrLen)
232{
233 if (!Rewrite.InsertText(Loc, StrData, StrLen))
234 return;
235 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
236}
237
238void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength,
239 const char *NewStr, unsigned NewLength) {
240 if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength))
241 return;
242 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
243}
244
245void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
246 bool haveBlockPtrs = false;
247 for (ObjCMethodDecl::param_iterator I = Method->param_begin(),
248 E = Method->param_end(); I != E; ++I)
249 if (isBlockPointerType((*I)->getType()))
250 haveBlockPtrs = true;
251
252 if (!haveBlockPtrs)
253 return;
254
255 // Do a fuzzy rewrite.
256 // We have 1 or more arguments that have closure pointers.
257 SourceLocation Loc = Method->getLocStart();
258 SourceLocation LocEnd = Method->getLocEnd();
259 const char *startBuf = SM->getCharacterData(Loc);
260 const char *endBuf = SM->getCharacterData(LocEnd);
261
262 const char *methodPtr = startBuf;
Steve Naroff8af6a452008-10-02 17:12:56 +0000263 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000264
265 while (*methodPtr++ && (methodPtr != endBuf)) {
266 switch (*methodPtr) {
267 case ':':
268 methodPtr++;
269 if (*methodPtr == '(') {
270 const char *scanType = ++methodPtr;
271 bool foundBlockPointer = false;
272 unsigned parenCount = 1;
273
274 while (parenCount) {
275 switch (*scanType) {
276 case '(':
277 parenCount++;
278 break;
279 case ')':
280 parenCount--;
281 break;
282 case '^':
283 foundBlockPointer = true;
284 break;
285 }
286 scanType++;
287 }
288 if (foundBlockPointer) {
289 // advance the location to startArgList.
290 Loc = Loc.getFileLocWithOffset(methodPtr-startBuf);
291 assert((Loc.isValid()) && "Invalid Loc");
292 ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size());
293
294 // Advance startBuf. Since the underlying buffer has changed,
295 // it's very important to advance startBuf (so we can correctly
296 // compute a relative Loc the next time around).
297 startBuf = methodPtr;
298 }
299 // Advance the method ptr to the end of the type.
300 methodPtr = scanType;
301 }
302 break;
303 }
304 }
305 return;
306}
307
308void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
309 for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(),
310 E = ClassDecl->instmeth_end(); I != E; ++I)
311 RewriteMethodDecl(*I);
312 for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(),
313 E = ClassDecl->classmeth_end(); I != E; ++I)
314 RewriteMethodDecl(*I);
315}
316
317void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
318 for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
319 E = CatDecl->instmeth_end(); I != E; ++I)
320 RewriteMethodDecl(*I);
321 for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
322 E = CatDecl->classmeth_end(); I != E; ++I)
323 RewriteMethodDecl(*I);
324}
325
326void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
327 for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
328 E = PDecl->instmeth_end(); I != E; ++I)
329 RewriteMethodDecl(*I);
330 for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
331 E = PDecl->classmeth_end(); I != E; ++I)
332 RewriteMethodDecl(*I);
333}
334
335//===----------------------------------------------------------------------===//
336// Top Level Driver Code
337//===----------------------------------------------------------------------===//
338
339void RewriteBlocks::HandleTopLevelDecl(Decl *D) {
340 // Two cases: either the decl could be in the main file, or it could be in a
341 // #included file. If the former, rewrite it now. If the later, check to see
342 // if we rewrote the #include/#import.
343 SourceLocation Loc = D->getLocation();
344 Loc = SM->getLogicalLoc(Loc);
345
346 // If this is for a builtin, ignore it.
347 if (Loc.isInvalid()) return;
348
349 if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D))
350 RewriteInterfaceDecl(MD);
351 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D))
352 RewriteCategoryDecl(CD);
353 else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
354 RewriteProtocolDecl(PD);
355
356 // If we have a decl in the main file, see if we should rewrite it.
357 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
358 HandleDeclInMainFile(D);
359 return;
360}
361
362std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
363 const char *funcName,
364 std::string Tag) {
365 const FunctionType *AFT = CE->getFunctionType();
366 QualType RT = AFT->getResultType();
Steve Naroff48a8c612008-10-03 12:09:49 +0000367 std::string StructRef = "struct " + Tag;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000368 std::string S = "static " + RT.getAsString() + " __" +
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000369 funcName + "_" + "block_func_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000370
Steve Naroff56ee6892008-10-08 17:01:13 +0000371 BlockDecl *BD = CE->getBlockDecl();
372
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000373 if (isa<FunctionTypeNoProto>(AFT)) {
374 S += "()";
Steve Naroff56ee6892008-10-08 17:01:13 +0000375 } else if (BD->param_empty()) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000376 S += "(" + StructRef + " *__cself)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000377 } else {
378 const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
379 assert(FT && "SynthesizeBlockFunc: No function proto");
380 S += '(';
381 // first add the implicit argument.
Steve Naroff48a8c612008-10-03 12:09:49 +0000382 S += StructRef + " *__cself, ";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000383 std::string ParamStr;
Steve Naroff56ee6892008-10-08 17:01:13 +0000384 for (BlockDecl::param_iterator AI = BD->param_begin(),
385 E = BD->param_end(); AI != E; ++AI) {
386 if (AI != BD->param_begin()) S += ", ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000387 ParamStr = (*AI)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000388 (*AI)->getType().getAsStringInternal(ParamStr);
389 S += ParamStr;
390 }
391 if (FT->isVariadic()) {
Steve Naroff56ee6892008-10-08 17:01:13 +0000392 if (!BD->param_empty()) S += ", ";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000393 S += "...";
394 }
395 S += ')';
396 }
397 S += " {\n";
398
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000399 // Create local declarations to avoid rewriting all closure decl ref exprs.
400 // First, emit a declaration for all "by ref" decls.
401 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
402 E = BlockByRefDecls.end(); I != E; ++I) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000403 S += " ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000404 std::string Name = (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000405 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000406 S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000407 }
408 // Next, emit a declaration for all "by copy" declarations.
409 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
410 E = BlockByCopyDecls.end(); I != E; ++I) {
411 S += " ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000412 std::string Name = (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000413 // Handle nested closure invocation. For example:
414 //
415 // void (^myImportedClosure)(void);
416 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
417 //
418 // void (^anotherClosure)(void);
419 // anotherClosure = ^(void) {
420 // myImportedClosure(); // import and invoke the closure
421 // };
422 //
423 if (isBlockPointerType((*I)->getType()))
Steve Naroff8af6a452008-10-02 17:12:56 +0000424 S += "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000425 else
426 (*I)->getType().getAsStringInternal(Name);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000427 S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000428 }
Steve Naroff70f95502008-10-04 17:06:23 +0000429 std::string RewrittenStr = RewrittenBlockExprs[CE];
430 const char *cstr = RewrittenStr.c_str();
431 while (*cstr++ != '{') ;
432 S += cstr;
433 S += "\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000434 return S;
435}
436
Steve Naroff4e13b762008-10-03 20:28:15 +0000437std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
438 const char *funcName,
439 std::string Tag) {
440 std::string StructRef = "struct " + Tag;
441 std::string S = "static void __";
442
443 S += funcName;
444 S += "_block_copy_" + utostr(i);
445 S += "(" + StructRef;
446 S += "*dst, " + StructRef;
447 S += "*src) {";
448 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
449 E = ImportedBlockDecls.end(); I != E; ++I) {
450 S += "_Block_copy_assign(&dst->";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000451 S += (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000452 S += ", src->";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000453 S += (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000454 S += ");}";
455 }
456 S += "\nstatic void __";
457 S += funcName;
458 S += "_block_dispose_" + utostr(i);
459 S += "(" + StructRef;
460 S += "*src) {";
461 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
462 E = ImportedBlockDecls.end(); I != E; ++I) {
463 S += "_Block_destroy(src->";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000464 S += (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000465 S += ");";
466 }
467 S += "}\n";
468 return S;
469}
470
Steve Naroffacba0f22008-10-04 23:47:37 +0000471std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
472 bool hasCopyDisposeHelpers) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000473 std::string S = "struct " + Tag;
474 std::string Constructor = " " + Tag;
475
476 S += " {\n struct __block_impl impl;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000477
478 if (hasCopyDisposeHelpers)
479 S += " void *copy;\n void *dispose;\n";
480
Steve Naroff48a8c612008-10-03 12:09:49 +0000481 Constructor += "(void *fp";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000482
Steve Naroffacba0f22008-10-04 23:47:37 +0000483 if (hasCopyDisposeHelpers)
484 Constructor += ", void *copyHelp, void *disposeHelp";
485
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000486 if (BlockDeclRefs.size()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000487 // Output all "by copy" declarations.
488 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
489 E = BlockByCopyDecls.end(); I != E; ++I) {
490 S += " ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000491 std::string FieldName = (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000492 std::string ArgName = "_" + FieldName;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000493 // Handle nested closure invocation. For example:
494 //
495 // void (^myImportedBlock)(void);
496 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
497 //
498 // void (^anotherBlock)(void);
499 // anotherBlock = ^(void) {
500 // myImportedBlock(); // import and invoke the closure
501 // };
502 //
Steve Naroff4e13b762008-10-03 20:28:15 +0000503 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000504 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000505 Constructor += ", void *" + ArgName;
506 } else {
507 (*I)->getType().getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000508 (*I)->getType().getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000509 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000510 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000511 S += FieldName + ";\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000512 }
513 // Output all "by ref" declarations.
514 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
515 E = BlockByRefDecls.end(); I != E; ++I) {
516 S += " ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000517 std::string FieldName = (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000518 std::string ArgName = "_" + FieldName;
519 // Handle nested closure invocation. For example:
520 //
521 // void (^myImportedBlock)(void);
522 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
523 //
524 // void (^anotherBlock)(void);
525 // anotherBlock = ^(void) {
526 // myImportedBlock(); // import and invoke the closure
527 // };
528 //
529 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000530 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000531 Constructor += ", void *" + ArgName;
532 } else {
533 Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000534 Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000535 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000536 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000537 S += FieldName + "; // by ref\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000538 }
539 // Finish writing the constructor.
540 // FIXME: handle NSConcreteGlobalBlock.
541 Constructor += ", int flags=0) {\n";
Steve Naroff83ba14e2008-10-03 15:04:50 +0000542 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
Steve Naroff48a8c612008-10-03 12:09:49 +0000543 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
544
Steve Naroffacba0f22008-10-04 23:47:37 +0000545 if (hasCopyDisposeHelpers)
546 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
547
Steve Naroff48a8c612008-10-03 12:09:49 +0000548 // Initialize all "by copy" arguments.
549 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
550 E = BlockByCopyDecls.end(); I != E; ++I) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000551 std::string Name = (*I)->getNameAsString();
Steve Naroff48a8c612008-10-03 12:09:49 +0000552 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000553 if (isBlockPointerType((*I)->getType()))
554 Constructor += Name + " = (struct __block_impl *)_";
555 else
556 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000557 Constructor += Name + ";\n";
558 }
559 // Initialize all "by ref" arguments.
560 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
561 E = BlockByRefDecls.end(); I != E; ++I) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000562 std::string Name = (*I)->getNameAsString();
Steve Naroff48a8c612008-10-03 12:09:49 +0000563 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000564 if (isBlockPointerType((*I)->getType()))
565 Constructor += Name + " = (struct __block_impl *)_";
566 else
567 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000568 Constructor += Name + ";\n";
569 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000570 } else {
571 // Finish writing the constructor.
572 // FIXME: handle NSConcreteGlobalBlock.
573 Constructor += ", int flags=0) {\n";
574 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
575 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000576 if (hasCopyDisposeHelpers)
577 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000578 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000579 Constructor += " ";
580 Constructor += "}\n";
581 S += Constructor;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000582 S += "};\n";
583 return S;
584}
585
586void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
587 const char *FunName) {
588 // Insert closures that were part of the function.
589 for (unsigned i = 0; i < Blocks.size(); i++) {
Steve Naroffacba0f22008-10-04 23:47:37 +0000590
Steve Naroffd3f77902008-10-05 00:06:12 +0000591 CollectBlockDeclRefInfo(Blocks[i]);
592
Steve Naroff48a8c612008-10-03 12:09:49 +0000593 std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000594
Steve Naroffacba0f22008-10-04 23:47:37 +0000595 std::string CI = SynthesizeBlockImpl(Blocks[i], Tag,
596 ImportedBlockDecls.size() > 0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000597
598 InsertText(FunLocStart, CI.c_str(), CI.size());
Steve Naroff4e13b762008-10-03 20:28:15 +0000599
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000600 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
601
602 InsertText(FunLocStart, CF.c_str(), CF.size());
603
Steve Naroff4e13b762008-10-03 20:28:15 +0000604 if (ImportedBlockDecls.size()) {
605 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
606 InsertText(FunLocStart, HF.c_str(), HF.size());
607 }
608
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000609 BlockDeclRefs.clear();
610 BlockByRefDecls.clear();
611 BlockByCopyDecls.clear();
612 BlockCallExprs.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000613 ImportedBlockDecls.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000614 }
615 Blocks.clear();
Steve Naroff8e9216d2008-10-04 17:10:02 +0000616 RewrittenBlockExprs.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000617}
618
619void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
Steve Naroff3ad29e22008-10-03 00:12:09 +0000620 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
Chris Lattner8ec03f52008-11-24 03:54:41 +0000621 const char *FuncName = FD->getNameAsCString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000622
623 SynthesizeBlockLiterals(FunLocStart, FuncName);
624}
625
626void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
627 SourceLocation FunLocStart = MD->getLocStart();
Chris Lattner077bf5e2008-11-24 03:33:13 +0000628 std::string FuncName = MD->getSelector().getAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000629 // Convert colons to underscores.
630 std::string::size_type loc = 0;
631 while ((loc = FuncName.find(":", loc)) != std::string::npos)
632 FuncName.replace(loc, 1, "_");
633
634 SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
635}
636
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000637void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
638 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
639 CI != E; ++CI)
Steve Naroff84a969f2008-10-08 17:31:13 +0000640 if (*CI) {
641 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
642 GetBlockDeclRefExprs(CBE->getBody());
643 else
644 GetBlockDeclRefExprs(*CI);
645 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000646 // Handle specific things.
647 if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
648 // FIXME: Handle enums.
649 if (!isa<FunctionDecl>(CDRE->getDecl()))
650 BlockDeclRefs.push_back(CDRE);
651 return;
652}
653
654void RewriteBlocks::GetBlockCallExprs(Stmt *S) {
655 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
656 CI != E; ++CI)
Steve Naroff84a969f2008-10-08 17:31:13 +0000657 if (*CI) {
658 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
659 GetBlockCallExprs(CBE->getBody());
660 else
661 GetBlockCallExprs(*CI);
662 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000663
664 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
Steve Naroff4e13b762008-10-03 20:28:15 +0000665 if (CE->getCallee()->getType()->isBlockPointerType()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000666 BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
Steve Naroff4e13b762008-10-03 20:28:15 +0000667 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000668 }
669 return;
670}
671
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000672std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
673 // Navigate to relevant type information.
Steve Naroffcc2ece22008-09-24 22:46:45 +0000674 const char *closureName = 0;
675 const BlockPointerType *CPT = 0;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000676
677 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
Chris Lattner8ec03f52008-11-24 03:54:41 +0000678 closureName = DRE->getDecl()->getNameAsCString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000679 CPT = DRE->getType()->getAsBlockPointerType();
680 } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
Chris Lattner8ec03f52008-11-24 03:54:41 +0000681 closureName = CDRE->getDecl()->getNameAsCString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000682 CPT = CDRE->getType()->getAsBlockPointerType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000683 } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
Chris Lattner8ec03f52008-11-24 03:54:41 +0000684 closureName = MExpr->getMemberDecl()->getNameAsCString();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000685 CPT = MExpr->getType()->getAsBlockPointerType();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000686 } else {
687 assert(1 && "RewriteBlockClass: Bad type");
688 }
689 assert(CPT && "RewriteBlockClass: Bad type");
690 const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType();
691 assert(FT && "RewriteBlockClass: Bad type");
692 const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FT);
693 // FTP will be null for closures that don't take arguments.
694
695 // Build a closure call - start with a paren expr to enforce precedence.
696 std::string BlockCall = "(";
697
698 // Synthesize the cast.
699 BlockCall += "(" + Exp->getType().getAsString() + "(*)";
Steve Naroff8af6a452008-10-02 17:12:56 +0000700 BlockCall += "(struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000701 if (FTP) {
702 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
703 E = FTP->arg_type_end(); I && (I != E); ++I)
704 BlockCall += ", " + (*I).getAsString();
705 }
706 BlockCall += "))"; // close the argument list and paren expression.
707
Steve Naroff83ba14e2008-10-03 15:04:50 +0000708 // Invoke the closure. We need to cast it since the declaration type is
709 // bogus (it's a function pointer type)
710 BlockCall += "((struct __block_impl *)";
711 std::string closureExprBufStr;
712 llvm::raw_string_ostream closureExprBuf(closureExprBufStr);
713 Exp->getCallee()->printPretty(closureExprBuf);
714 BlockCall += closureExprBuf.str();
715 BlockCall += ")->FuncPtr)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000716
717 // Add the arguments.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000718 BlockCall += "((struct __block_impl *)";
Steve Naroffb65a4f12008-10-04 17:45:51 +0000719 BlockCall += closureExprBuf.str();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000720 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
Steve Naroff5e52b172008-10-04 18:52:47 +0000740void RewriteBlocks::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
741 // FIXME: Add more elaborate code generation required by the ABI.
742 InsertText(BDRE->getLocStart(), "*", 1);
743}
744
Steve Naroffca743602008-10-15 18:38:58 +0000745void RewriteBlocks::RewriteCastExpr(CastExpr *CE) {
746 SourceLocation LocStart = CE->getLocStart();
747 SourceLocation LocEnd = CE->getLocEnd();
748
Steve Naroff8f6ce572008-11-03 11:20:24 +0000749 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
750 return;
751
Steve Naroffca743602008-10-15 18:38:58 +0000752 const char *startBuf = SM->getCharacterData(LocStart);
753 const char *endBuf = SM->getCharacterData(LocEnd);
754
755 // advance the location to startArgList.
756 const char *argPtr = startBuf;
757
758 while (*argPtr++ && (argPtr < endBuf)) {
759 switch (*argPtr) {
760 case '^':
761 // Replace the '^' with '*'.
762 LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf);
763 ReplaceText(LocStart, 1, "*", 1);
764 break;
765 }
766 }
767 return;
768}
769
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000770void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
771 SourceLocation DeclLoc = FD->getLocation();
Steve Naroffe0109a52008-10-10 15:33:34 +0000772 unsigned parenCount = 0;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000773
774 // We have 1 or more arguments that have closure pointers.
775 const char *startBuf = SM->getCharacterData(DeclLoc);
776 const char *startArgList = strchr(startBuf, '(');
777
778 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
779
780 parenCount++;
781 // advance the location to startArgList.
Steve Naroffe0109a52008-10-10 15:33:34 +0000782 DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000783 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
784
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000785 const char *argPtr = startArgList;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000786
787 while (*argPtr++ && parenCount) {
788 switch (*argPtr) {
789 case '^':
Steve Naroffe0109a52008-10-10 15:33:34 +0000790 // Replace the '^' with '*'.
791 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList);
792 ReplaceText(DeclLoc, 1, "*", 1);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000793 break;
794 case '(':
795 parenCount++;
796 break;
797 case ')':
798 parenCount--;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000799 break;
800 }
801 }
802 return;
803}
804
Steve Naroffca743602008-10-15 18:38:58 +0000805bool RewriteBlocks::PointerTypeTakesAnyBlockArguments(QualType QT) {
806 const FunctionTypeProto *FTP;
807 const PointerType *PT = QT->getAsPointerType();
808 if (PT) {
809 FTP = PT->getPointeeType()->getAsFunctionTypeProto();
Steve Naroffca743602008-10-15 18:38:58 +0000810 } else {
811 const BlockPointerType *BPT = QT->getAsBlockPointerType();
812 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
813 FTP = BPT->getPointeeType()->getAsFunctionTypeProto();
814 }
Steve Naroffeab5f632008-09-23 19:24:41 +0000815 if (FTP) {
816 for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
817 E = FTP->arg_type_end(); I != E; ++I)
818 if (isBlockPointerType(*I))
819 return true;
820 }
821 return false;
822}
823
824void RewriteBlocks::GetExtentOfArgList(const char *Name,
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000825 const char *&LParen, const char *&RParen) {
826 const char *argPtr = strchr(Name, '(');
Steve Naroffeab5f632008-09-23 19:24:41 +0000827 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
828
829 LParen = argPtr; // output the start.
830 argPtr++; // skip past the left paren.
831 unsigned parenCount = 1;
832
833 while (*argPtr && parenCount) {
834 switch (*argPtr) {
835 case '(': parenCount++; break;
836 case ')': parenCount--; break;
837 default: break;
838 }
839 if (parenCount) argPtr++;
840 }
841 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
842 RParen = argPtr; // output the end
843}
844
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000845void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000846 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
847 RewriteBlockPointerFunctionArgs(FD);
848 return;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000849 }
850 // Handle Variables and Typedefs.
851 SourceLocation DeclLoc = ND->getLocation();
852 QualType DeclT;
853 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
854 DeclT = VD->getType();
855 else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
856 DeclT = TDD->getUnderlyingType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000857 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
858 DeclT = FD->getType();
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000859 else
860 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
Steve Naroffeab5f632008-09-23 19:24:41 +0000861
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000862 const char *startBuf = SM->getCharacterData(DeclLoc);
863 const char *endBuf = startBuf;
864 // scan backward (from the decl location) for the end of the previous decl.
865 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
866 startBuf--;
Steve Naroffca743602008-10-15 18:38:58 +0000867
868 // *startBuf != '^' if we are dealing with a pointer to function that
869 // may take block argument types (which will be handled below).
870 if (*startBuf == '^') {
871 // Replace the '^' with '*', computing a negative offset.
872 DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
873 ReplaceText(DeclLoc, 1, "*", 1);
874 }
875 if (PointerTypeTakesAnyBlockArguments(DeclT)) {
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000876 // Replace the '^' with '*' for arguments.
877 DeclLoc = ND->getLocation();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000878 startBuf = SM->getCharacterData(DeclLoc);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000879 const char *argListBegin, *argListEnd;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000880 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 Naroffd3f77902008-10-05 00:06:12 +0000892void RewriteBlocks::CollectBlockDeclRefInfo(BlockExpr *Exp) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000893 // Add initializers for any closure decl refs.
Steve Naroff84a969f2008-10-08 17:31:13 +0000894 GetBlockDeclRefExprs(Exp->getBody());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000895 if (BlockDeclRefs.size()) {
896 // Unique all "by copy" declarations.
897 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
898 if (!BlockDeclRefs[i]->isByRef())
899 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
900 // Unique all "by ref" declarations.
901 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
902 if (BlockDeclRefs[i]->isByRef()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000903 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
904 }
Steve Naroffacba0f22008-10-04 23:47:37 +0000905 // Find any imported blocks...they will need special attention.
906 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
907 if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
908 GetBlockCallExprs(Blocks[i]);
909 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
910 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000911 }
Steve Naroffd3f77902008-10-05 00:06:12 +0000912}
913
914std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) {
915 Blocks.push_back(Exp);
916
917 CollectBlockDeclRefInfo(Exp);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000918 std::string FuncName;
919
920 if (CurFunctionDef)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000921 FuncName = std::string(CurFunctionDef->getNameAsString());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000922 else if (CurMethodDef) {
Chris Lattner077bf5e2008-11-24 03:33:13 +0000923 FuncName = CurMethodDef->getSelector().getAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000924 // Convert colons to underscores.
925 std::string::size_type loc = 0;
926 while ((loc = FuncName.find(":", loc)) != std::string::npos)
927 FuncName.replace(loc, 1, "_");
Steve Naroff39622b92008-10-03 15:38:09 +0000928 } else if (VD)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000929 FuncName = std::string(VD->getNameAsString());
Steve Naroff39622b92008-10-03 15:38:09 +0000930
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000931 std::string BlockNumber = utostr(Blocks.size()-1);
932
Steve Naroff83ba14e2008-10-03 15:04:50 +0000933 std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000934 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000935
Steve Naroff83ba14e2008-10-03 15:04:50 +0000936 std::string FunkTypeStr;
937
938 // Get a pointer to the function type so we can cast appropriately.
939 Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr);
940
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000941 // Rewrite the closure block with a compound literal. The first cast is
942 // to prevent warnings from the C compiler.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000943 std::string Init = "(" + FunkTypeStr;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000944
Steve Naroff83ba14e2008-10-03 15:04:50 +0000945 Init += ")&" + Tag;
946
947 // Initialize the block function.
948 Init += "((void*)" + Func;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000949
Steve Naroffacba0f22008-10-04 23:47:37 +0000950 if (ImportedBlockDecls.size()) {
951 std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber;
952 Init += ",(void*)" + Buf;
953 Buf = "__" + FuncName + "_block_dispose_" + BlockNumber;
954 Init += ",(void*)" + Buf;
955 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000956 // Add initializers for any closure decl refs.
957 if (BlockDeclRefs.size()) {
958 // Output all "by copy" declarations.
959 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
960 E = BlockByCopyDecls.end(); I != E; ++I) {
961 Init += ",";
962 if (isObjCType((*I)->getType())) {
963 Init += "[[";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000964 Init += (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000965 Init += " retain] autorelease]";
Steve Naroff4e13b762008-10-03 20:28:15 +0000966 } else if (isBlockPointerType((*I)->getType())) {
967 Init += "(void *)";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000968 Init += (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000969 } else {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000970 Init += (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000971 }
972 }
973 // Output all "by ref" declarations.
974 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
975 E = BlockByRefDecls.end(); I != E; ++I) {
976 Init += ",&";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000977 Init += (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000978 }
979 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000980 Init += ")";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000981 BlockDeclRefs.clear();
982 BlockByRefDecls.clear();
983 BlockByCopyDecls.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000984 ImportedBlockDecls.clear();
985
Steve Naroff70f95502008-10-04 17:06:23 +0000986 return Init;
987}
988
989//===----------------------------------------------------------------------===//
990// Function Body / Expression rewriting
991//===----------------------------------------------------------------------===//
992
993Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
994 // Start by rewriting all children.
995 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
996 CI != E; ++CI)
997 if (*CI) {
998 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
Steve Naroff84a969f2008-10-08 17:31:13 +0000999 Stmt *newStmt = RewriteFunctionBody(CBE->getBody());
Steve Naroff70f95502008-10-04 17:06:23 +00001000 if (newStmt)
1001 *CI = newStmt;
1002
1003 // We've just rewritten the block body in place.
1004 // Now we snarf the rewritten text and stash it away for later use.
1005 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1006 RewrittenBlockExprs[CBE] = S;
1007 std::string Init = SynthesizeBlockInitExpr(CBE);
1008 // Do the rewrite, using S.size() which contains the rewritten size.
1009 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1010 } else {
1011 Stmt *newStmt = RewriteFunctionBody(*CI);
1012 if (newStmt)
1013 *CI = newStmt;
1014 }
1015 }
1016 // Handle specific things.
1017 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1018 if (CE->getCallee()->getType()->isBlockPointerType())
1019 RewriteBlockCall(CE);
1020 }
Steve Naroffca743602008-10-15 18:38:58 +00001021 if (CastExpr *CE = dyn_cast<CastExpr>(S)) {
1022 RewriteCastExpr(CE);
1023 }
Steve Naroff70f95502008-10-04 17:06:23 +00001024 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
Ted Kremenekfda4fed2008-10-06 18:47:09 +00001025 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
1026 DI != DE; ++DI) {
1027
1028 ScopedDecl *SD = *DI;
1029 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
1030 if (isBlockPointerType(ND->getType()))
1031 RewriteBlockPointerDecl(ND);
Steve Naroffca743602008-10-15 18:38:58 +00001032 else if (ND->getType()->isFunctionPointerType())
1033 CheckFunctionPointerDecl(ND->getType(), ND);
Ted Kremenekfda4fed2008-10-06 18:47:09 +00001034 }
1035 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
1036 if (isBlockPointerType(TD->getUnderlyingType()))
1037 RewriteBlockPointerDecl(TD);
Steve Naroffca743602008-10-15 18:38:58 +00001038 else if (TD->getUnderlyingType()->isFunctionPointerType())
1039 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
Ted Kremenekfda4fed2008-10-06 18:47:09 +00001040 }
Steve Naroff70f95502008-10-04 17:06:23 +00001041 }
1042 }
Steve Naroff5e52b172008-10-04 18:52:47 +00001043 // Handle specific things.
1044 if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
1045 if (BDRE->isByRef())
1046 RewriteBlockDeclRefExpr(BDRE);
1047 }
Steve Naroff70f95502008-10-04 17:06:23 +00001048 // Return this stmt unmodified.
1049 return S;
1050}
1051
Steve Naroffca743602008-10-15 18:38:58 +00001052void RewriteBlocks::RewriteFunctionTypeProto(QualType funcType, NamedDecl *D) {
1053 if (FunctionTypeProto *fproto = dyn_cast<FunctionTypeProto>(funcType)) {
1054 for (FunctionTypeProto::arg_type_iterator I = fproto->arg_type_begin(),
1055 E = fproto->arg_type_end(); I && (I != E); ++I)
1056 if (isBlockPointerType(*I)) {
1057 // All the args are checked/rewritten. Don't call twice!
1058 RewriteBlockPointerDecl(D);
1059 break;
1060 }
1061 }
1062}
1063
1064void RewriteBlocks::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
1065 const PointerType *PT = funcType->getAsPointerType();
1066 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
1067 RewriteFunctionTypeProto(PT->getPointeeType(), ND);
1068}
1069
Steve Naroff70f95502008-10-04 17:06:23 +00001070/// HandleDeclInMainFile - This is called for each top-level decl defined in the
1071/// main file of the input.
1072void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
1073 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff70f95502008-10-04 17:06:23 +00001074 // Since function prototypes don't have ParmDecl's, we check the function
1075 // prototype. This enables us to rewrite function declarations and
1076 // definitions using the same code.
Steve Naroffca743602008-10-15 18:38:58 +00001077 RewriteFunctionTypeProto(FD->getType(), FD);
Steve Naroff70f95502008-10-04 17:06:23 +00001078
Steve Naroff70f95502008-10-04 17:06:23 +00001079 if (Stmt *Body = FD->getBody()) {
1080 CurFunctionDef = FD;
1081 FD->setBody(RewriteFunctionBody(Body));
1082 // This synthesizes and inserts the block "impl" struct, invoke function,
1083 // and any copy/dispose helper functions.
1084 InsertBlockLiteralsWithinFunction(FD);
1085 CurFunctionDef = 0;
1086 }
1087 return;
1088 }
1089 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
1090 RewriteMethodDecl(MD);
1091 if (Stmt *Body = MD->getBody()) {
1092 CurMethodDef = MD;
1093 RewriteFunctionBody(Body);
1094 InsertBlockLiteralsWithinMethod(MD);
1095 CurMethodDef = 0;
1096 }
1097 }
1098 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
1099 if (isBlockPointerType(VD->getType())) {
1100 RewriteBlockPointerDecl(VD);
1101 if (VD->getInit()) {
1102 if (BlockExpr *CBE = dyn_cast<BlockExpr>(VD->getInit())) {
Steve Naroff84a969f2008-10-08 17:31:13 +00001103 RewriteFunctionBody(CBE->getBody());
Steve Naroff70f95502008-10-04 17:06:23 +00001104
1105 // We've just rewritten the block body in place.
1106 // Now we snarf the rewritten text and stash it away for later use.
1107 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1108 RewrittenBlockExprs[CBE] = S;
1109 std::string Init = SynthesizeBlockInitExpr(CBE, VD);
1110 // Do the rewrite, using S.size() which contains the rewritten size.
1111 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
Douglas Gregor2e1cd422008-11-17 14:58:09 +00001112 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(),
Chris Lattner8ec03f52008-11-24 03:54:41 +00001113 VD->getNameAsCString());
Steve Naroffca743602008-10-15 18:38:58 +00001114 } else if (CastExpr *CE = dyn_cast<CastExpr>(VD->getInit())) {
1115 RewriteCastExpr(CE);
1116 }
1117 }
1118 } else if (VD->getType()->isFunctionPointerType()) {
1119 CheckFunctionPointerDecl(VD->getType(), VD);
1120 if (VD->getInit()) {
1121 if (CastExpr *CE = dyn_cast<CastExpr>(VD->getInit())) {
1122 RewriteCastExpr(CE);
Steve Naroff70f95502008-10-04 17:06:23 +00001123 }
1124 }
1125 }
1126 return;
1127 }
1128 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
1129 if (isBlockPointerType(TD->getUnderlyingType()))
1130 RewriteBlockPointerDecl(TD);
Steve Naroffca743602008-10-15 18:38:58 +00001131 else if (TD->getUnderlyingType()->isFunctionPointerType())
1132 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
Steve Naroff70f95502008-10-04 17:06:23 +00001133 return;
1134 }
1135 if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1136 if (RD->isDefinition()) {
1137 for (RecordDecl::field_const_iterator i = RD->field_begin(),
1138 e = RD->field_end(); i != e; ++i) {
1139 FieldDecl *FD = *i;
1140 if (isBlockPointerType(FD->getType()))
1141 RewriteBlockPointerDecl(FD);
1142 }
1143 }
1144 return;
1145 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001146}