blob: f9ed0ecc095fcb3d812afde1d2de2382a119f8af [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;
Chris Lattner2b2453a2009-01-17 06:22:33 +000040 FileID MainFileID;
Steve Naroff1c9f81b2008-09-17 00:13:27 +000041 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.
Chris Lattner682bf922009-03-29 16:50:03 +000086 virtual void HandleTopLevelDecl(DeclGroupRef D) {
87 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
88 HandleTopLevelSingleDecl(*I);
89 }
90 void HandleTopLevelSingleDecl(Decl *D);
Steve Naroff1c9f81b2008-09-17 00:13:27 +000091 void HandleDeclInMainFile(Decl *D);
92
93 // Top level
94 Stmt *RewriteFunctionBody(Stmt *S);
95 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
96 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
97
98 // Block specific rewrite rules.
Steve Naroff70f95502008-10-04 17:06:23 +000099 std::string SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD=0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000100
101 void RewriteBlockCall(CallExpr *Exp);
102 void RewriteBlockPointerDecl(NamedDecl *VD);
Steve Naroff5e52b172008-10-04 18:52:47 +0000103 void RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000104 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
105
Steve Naroff4e13b762008-10-03 20:28:15 +0000106 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
107 const char *funcName, std::string Tag);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000108 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
109 const char *funcName, std::string Tag);
Steve Naroffacba0f22008-10-04 23:47:37 +0000110 std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
111 bool hasCopyDisposeHelpers);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000112 std::string SynthesizeBlockCall(CallExpr *Exp);
113 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
114 const char *FunName);
115
Steve Naroffd3f77902008-10-05 00:06:12 +0000116 void CollectBlockDeclRefInfo(BlockExpr *Exp);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000117 void GetBlockCallExprs(Stmt *S);
Steve Naroffacba0f22008-10-04 23:47:37 +0000118 void GetBlockDeclRefExprs(Stmt *S);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000119
120 // We avoid calling Type::isBlockPointerType(), since it operates on the
121 // canonical type. We only care if the top-level type is a closure pointer.
122 bool isBlockPointerType(QualType T) { return isa<BlockPointerType>(T); }
123
124 // FIXME: This predicate seems like it would be useful to add to ASTContext.
125 bool isObjCType(QualType T) {
126 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
127 return false;
128
129 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
130
131 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
132 OCT == Context->getCanonicalType(Context->getObjCClassType()))
133 return true;
134
135 if (const PointerType *PT = OCT->getAsPointerType()) {
136 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
137 isa<ObjCQualifiedIdType>(PT->getPointeeType()))
138 return true;
139 }
140 return false;
141 }
142 // ObjC rewrite methods.
143 void RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl);
144 void RewriteCategoryDecl(ObjCCategoryDecl *CatDecl);
145 void RewriteProtocolDecl(ObjCProtocolDecl *PDecl);
146 void RewriteMethodDecl(ObjCMethodDecl *MDecl);
Steve Naroffca743602008-10-15 18:38:58 +0000147
Douglas Gregor72564e72009-02-26 23:50:07 +0000148 void RewriteFunctionProtoType(QualType funcType, NamedDecl *D);
Steve Naroffca743602008-10-15 18:38:58 +0000149 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
150 void RewriteCastExpr(CastExpr *CE);
Steve Naroffeab5f632008-09-23 19:24:41 +0000151
Steve Naroffca743602008-10-15 18:38:58 +0000152 bool PointerTypeTakesAnyBlockArguments(QualType QT);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000153 void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000154};
155
156}
157
158static bool IsHeaderFile(const std::string &Filename) {
159 std::string::size_type DotPos = Filename.rfind('.');
160
161 if (DotPos == std::string::npos) {
162 // no file extension
163 return false;
164 }
165
166 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
167 // C header: .h
168 // C++ header: .hh or .H;
169 return Ext == "h" || Ext == "hh" || Ext == "H";
170}
171
Steve Naroff13188952008-09-18 14:10:13 +0000172RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile,
173 Diagnostic &D, const LangOptions &LOpts) :
174 Diags(D), LangOpts(LOpts) {
175 IsHeader = IsHeaderFile(inFile);
176 InFileName = inFile;
177 OutFileName = outFile;
178 CurFunctionDef = 0;
179 CurMethodDef = 0;
180 RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
181 "rewriting failed");
Steve Naroff13188952008-09-18 14:10:13 +0000182}
183
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000184ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
Steve Naroff13188952008-09-18 14:10:13 +0000185 const std::string& OutFile,
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000186 Diagnostic &Diags,
187 const LangOptions &LangOpts) {
Steve Naroff13188952008-09-18 14:10:13 +0000188 return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000189}
190
191void RewriteBlocks::Initialize(ASTContext &context) {
192 Context = &context;
193 SM = &Context->getSourceManager();
194
195 // Get the ID and start/end of the main file.
196 MainFileID = SM->getMainFileID();
197 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
198 MainFileStart = MainBuf->getBufferStart();
199 MainFileEnd = MainBuf->getBufferEnd();
200
Chris Lattner2c78b872009-04-14 23:22:57 +0000201 Rewrite.setSourceMgr(Context->getSourceManager(), LangOpts);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000202
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000203 if (IsHeader)
204 Preamble = "#pragma once\n";
205 Preamble += "#ifndef BLOCK_IMPL\n";
206 Preamble += "#define BLOCK_IMPL\n";
207 Preamble += "struct __block_impl {\n";
208 Preamble += " void *isa;\n";
209 Preamble += " int Flags;\n";
210 Preamble += " int Size;\n";
211 Preamble += " void *FuncPtr;\n";
212 Preamble += "};\n";
213 Preamble += "enum {\n";
214 Preamble += " BLOCK_HAS_COPY_DISPOSE = (1<<25),\n";
215 Preamble += " BLOCK_IS_GLOBAL = (1<<28)\n";
216 Preamble += "};\n";
217 if (LangOpts.Microsoft)
218 Preamble += "#define __OBJC_RW_EXTERN extern \"C\" __declspec(dllimport)\n";
219 else
220 Preamble += "#define __OBJC_RW_EXTERN extern\n";
221 Preamble += "// Runtime copy/destroy helper functions\n";
222 Preamble += "__OBJC_RW_EXTERN void _Block_copy_assign(void *, void *);\n";
223 Preamble += "__OBJC_RW_EXTERN void _Block_byref_assign_copy(void *, void *);\n";
224 Preamble += "__OBJC_RW_EXTERN void _Block_destroy(void *);\n";
225 Preamble += "__OBJC_RW_EXTERN void _Block_byref_release(void *);\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000226 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteGlobalBlock;\n";
227 Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n";
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000228 Preamble += "#endif\n";
229
Chris Lattner2b2453a2009-01-17 06:22:33 +0000230 InsertText(SM->getLocForStartOfFile(MainFileID),
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000231 Preamble.c_str(), Preamble.size());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000232}
233
234void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData,
235 unsigned StrLen)
236{
237 if (!Rewrite.InsertText(Loc, StrData, StrLen))
238 return;
239 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
240}
241
242void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength,
243 const char *NewStr, unsigned NewLength) {
244 if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength))
245 return;
246 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
247}
248
249void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
250 bool haveBlockPtrs = false;
251 for (ObjCMethodDecl::param_iterator I = Method->param_begin(),
252 E = Method->param_end(); I != E; ++I)
253 if (isBlockPointerType((*I)->getType()))
254 haveBlockPtrs = true;
255
256 if (!haveBlockPtrs)
257 return;
258
259 // Do a fuzzy rewrite.
260 // We have 1 or more arguments that have closure pointers.
261 SourceLocation Loc = Method->getLocStart();
262 SourceLocation LocEnd = Method->getLocEnd();
263 const char *startBuf = SM->getCharacterData(Loc);
264 const char *endBuf = SM->getCharacterData(LocEnd);
265
266 const char *methodPtr = startBuf;
Steve Naroff8af6a452008-10-02 17:12:56 +0000267 std::string Tag = "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000268
269 while (*methodPtr++ && (methodPtr != endBuf)) {
270 switch (*methodPtr) {
271 case ':':
272 methodPtr++;
273 if (*methodPtr == '(') {
274 const char *scanType = ++methodPtr;
275 bool foundBlockPointer = false;
276 unsigned parenCount = 1;
277
278 while (parenCount) {
279 switch (*scanType) {
280 case '(':
281 parenCount++;
282 break;
283 case ')':
284 parenCount--;
285 break;
286 case '^':
287 foundBlockPointer = true;
288 break;
289 }
290 scanType++;
291 }
292 if (foundBlockPointer) {
293 // advance the location to startArgList.
294 Loc = Loc.getFileLocWithOffset(methodPtr-startBuf);
295 assert((Loc.isValid()) && "Invalid Loc");
296 ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size());
297
298 // Advance startBuf. Since the underlying buffer has changed,
299 // it's very important to advance startBuf (so we can correctly
300 // compute a relative Loc the next time around).
301 startBuf = methodPtr;
302 }
303 // Advance the method ptr to the end of the type.
304 methodPtr = scanType;
305 }
306 break;
307 }
308 }
309 return;
310}
311
312void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
Douglas Gregor6ab35242009-04-09 21:40:53 +0000313 for (ObjCInterfaceDecl::instmeth_iterator
314 I = ClassDecl->instmeth_begin(*Context),
315 E = ClassDecl->instmeth_end(*Context);
316 I != E; ++I)
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000317 RewriteMethodDecl(*I);
Douglas Gregor6ab35242009-04-09 21:40:53 +0000318 for (ObjCInterfaceDecl::classmeth_iterator
319 I = ClassDecl->classmeth_begin(*Context),
320 E = ClassDecl->classmeth_end(*Context);
321 I != E; ++I)
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000322 RewriteMethodDecl(*I);
323}
324
325void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
Douglas Gregor6ab35242009-04-09 21:40:53 +0000326 for (ObjCCategoryDecl::instmeth_iterator
327 I = CatDecl->instmeth_begin(*Context),
328 E = CatDecl->instmeth_end(*Context);
329 I != E; ++I)
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000330 RewriteMethodDecl(*I);
Douglas Gregor6ab35242009-04-09 21:40:53 +0000331 for (ObjCCategoryDecl::classmeth_iterator
332 I = CatDecl->classmeth_begin(*Context),
333 E = CatDecl->classmeth_end(*Context);
334 I != E; ++I)
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000335 RewriteMethodDecl(*I);
336}
337
338void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
Douglas Gregor6ab35242009-04-09 21:40:53 +0000339 for (ObjCProtocolDecl::instmeth_iterator
340 I = PDecl->instmeth_begin(*Context),
341 E = PDecl->instmeth_end(*Context);
342 I != E; ++I)
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000343 RewriteMethodDecl(*I);
Douglas Gregor6ab35242009-04-09 21:40:53 +0000344 for (ObjCProtocolDecl::classmeth_iterator
345 I = PDecl->classmeth_begin(*Context),
346 E = PDecl->classmeth_end(*Context);
347 I != E; ++I)
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000348 RewriteMethodDecl(*I);
349}
350
351//===----------------------------------------------------------------------===//
352// Top Level Driver Code
353//===----------------------------------------------------------------------===//
354
Chris Lattner682bf922009-03-29 16:50:03 +0000355void RewriteBlocks::HandleTopLevelSingleDecl(Decl *D) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000356 // Two cases: either the decl could be in the main file, or it could be in a
357 // #included file. If the former, rewrite it now. If the later, check to see
358 // if we rewrote the #include/#import.
359 SourceLocation Loc = D->getLocation();
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000360 Loc = SM->getInstantiationLoc(Loc);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000361
362 // If this is for a builtin, ignore it.
363 if (Loc.isInvalid()) return;
364
365 if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D))
366 RewriteInterfaceDecl(MD);
367 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D))
368 RewriteCategoryDecl(CD);
369 else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
370 RewriteProtocolDecl(PD);
371
372 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner23f2c582009-01-25 22:02:19 +0000373 if (SM->isFromMainFile(Loc))
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000374 HandleDeclInMainFile(D);
375 return;
376}
377
378std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
379 const char *funcName,
380 std::string Tag) {
381 const FunctionType *AFT = CE->getFunctionType();
382 QualType RT = AFT->getResultType();
Steve Naroff48a8c612008-10-03 12:09:49 +0000383 std::string StructRef = "struct " + Tag;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000384 std::string S = "static " + RT.getAsString() + " __" +
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000385 funcName + "_" + "block_func_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000386
Steve Naroff56ee6892008-10-08 17:01:13 +0000387 BlockDecl *BD = CE->getBlockDecl();
388
Douglas Gregor72564e72009-02-26 23:50:07 +0000389 if (isa<FunctionNoProtoType>(AFT)) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000390 S += "()";
Steve Naroff56ee6892008-10-08 17:01:13 +0000391 } else if (BD->param_empty()) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000392 S += "(" + StructRef + " *__cself)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000393 } else {
Douglas Gregor72564e72009-02-26 23:50:07 +0000394 const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000395 assert(FT && "SynthesizeBlockFunc: No function proto");
396 S += '(';
397 // first add the implicit argument.
Steve Naroff48a8c612008-10-03 12:09:49 +0000398 S += StructRef + " *__cself, ";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000399 std::string ParamStr;
Steve Naroff56ee6892008-10-08 17:01:13 +0000400 for (BlockDecl::param_iterator AI = BD->param_begin(),
401 E = BD->param_end(); AI != E; ++AI) {
402 if (AI != BD->param_begin()) S += ", ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000403 ParamStr = (*AI)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000404 (*AI)->getType().getAsStringInternal(ParamStr);
405 S += ParamStr;
406 }
407 if (FT->isVariadic()) {
Steve Naroff56ee6892008-10-08 17:01:13 +0000408 if (!BD->param_empty()) S += ", ";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000409 S += "...";
410 }
411 S += ')';
412 }
413 S += " {\n";
414
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000415 // Create local declarations to avoid rewriting all closure decl ref exprs.
416 // First, emit a declaration for all "by ref" decls.
417 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
418 E = BlockByRefDecls.end(); I != E; ++I) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000419 S += " ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000420 std::string Name = (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000421 Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000422 S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000423 }
424 // Next, emit a declaration for all "by copy" declarations.
425 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
426 E = BlockByCopyDecls.end(); I != E; ++I) {
427 S += " ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000428 std::string Name = (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000429 // Handle nested closure invocation. For example:
430 //
431 // void (^myImportedClosure)(void);
432 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
433 //
434 // void (^anotherClosure)(void);
435 // anotherClosure = ^(void) {
436 // myImportedClosure(); // import and invoke the closure
437 // };
438 //
439 if (isBlockPointerType((*I)->getType()))
Steve Naroff8af6a452008-10-02 17:12:56 +0000440 S += "struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000441 else
442 (*I)->getType().getAsStringInternal(Name);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000443 S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000444 }
Steve Naroff70f95502008-10-04 17:06:23 +0000445 std::string RewrittenStr = RewrittenBlockExprs[CE];
446 const char *cstr = RewrittenStr.c_str();
447 while (*cstr++ != '{') ;
448 S += cstr;
449 S += "\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000450 return S;
451}
452
Steve Naroff4e13b762008-10-03 20:28:15 +0000453std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
454 const char *funcName,
455 std::string Tag) {
456 std::string StructRef = "struct " + Tag;
457 std::string S = "static void __";
458
459 S += funcName;
460 S += "_block_copy_" + utostr(i);
461 S += "(" + StructRef;
462 S += "*dst, " + StructRef;
463 S += "*src) {";
464 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
465 E = ImportedBlockDecls.end(); I != E; ++I) {
466 S += "_Block_copy_assign(&dst->";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000467 S += (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000468 S += ", src->";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000469 S += (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000470 S += ");}";
471 }
472 S += "\nstatic void __";
473 S += funcName;
474 S += "_block_dispose_" + utostr(i);
475 S += "(" + StructRef;
476 S += "*src) {";
477 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
478 E = ImportedBlockDecls.end(); I != E; ++I) {
479 S += "_Block_destroy(src->";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000480 S += (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000481 S += ");";
482 }
483 S += "}\n";
484 return S;
485}
486
Steve Naroffacba0f22008-10-04 23:47:37 +0000487std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
488 bool hasCopyDisposeHelpers) {
Steve Naroff48a8c612008-10-03 12:09:49 +0000489 std::string S = "struct " + Tag;
490 std::string Constructor = " " + Tag;
491
492 S += " {\n struct __block_impl impl;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000493
494 if (hasCopyDisposeHelpers)
495 S += " void *copy;\n void *dispose;\n";
496
Steve Naroff48a8c612008-10-03 12:09:49 +0000497 Constructor += "(void *fp";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000498
Steve Naroffacba0f22008-10-04 23:47:37 +0000499 if (hasCopyDisposeHelpers)
500 Constructor += ", void *copyHelp, void *disposeHelp";
501
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000502 if (BlockDeclRefs.size()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000503 // Output all "by copy" declarations.
504 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
505 E = BlockByCopyDecls.end(); I != E; ++I) {
506 S += " ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000507 std::string FieldName = (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000508 std::string ArgName = "_" + FieldName;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000509 // Handle nested closure invocation. For example:
510 //
511 // void (^myImportedBlock)(void);
512 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
513 //
514 // void (^anotherBlock)(void);
515 // anotherBlock = ^(void) {
516 // myImportedBlock(); // import and invoke the closure
517 // };
518 //
Steve Naroff4e13b762008-10-03 20:28:15 +0000519 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000520 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000521 Constructor += ", void *" + ArgName;
522 } else {
523 (*I)->getType().getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000524 (*I)->getType().getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000525 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000526 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000527 S += FieldName + ";\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000528 }
529 // Output all "by ref" declarations.
530 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
531 E = BlockByRefDecls.end(); I != E; ++I) {
532 S += " ";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000533 std::string FieldName = (*I)->getNameAsString();
Steve Naroff4e13b762008-10-03 20:28:15 +0000534 std::string ArgName = "_" + FieldName;
535 // Handle nested closure invocation. For example:
536 //
537 // void (^myImportedBlock)(void);
538 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
539 //
540 // void (^anotherBlock)(void);
541 // anotherBlock = ^(void) {
542 // myImportedBlock(); // import and invoke the closure
543 // };
544 //
545 if (isBlockPointerType((*I)->getType())) {
Steve Naroff8af6a452008-10-02 17:12:56 +0000546 S += "struct __block_impl *";
Steve Naroff4e13b762008-10-03 20:28:15 +0000547 Constructor += ", void *" + ArgName;
548 } else {
549 Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName);
Steve Naroff48a8c612008-10-03 12:09:49 +0000550 Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName);
Steve Naroff4e13b762008-10-03 20:28:15 +0000551 Constructor += ", " + ArgName;
Steve Naroff48a8c612008-10-03 12:09:49 +0000552 }
Steve Naroff4e13b762008-10-03 20:28:15 +0000553 S += FieldName + "; // by ref\n";
Steve Naroff48a8c612008-10-03 12:09:49 +0000554 }
555 // Finish writing the constructor.
556 // FIXME: handle NSConcreteGlobalBlock.
557 Constructor += ", int flags=0) {\n";
Steve Naroff83ba14e2008-10-03 15:04:50 +0000558 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
Steve Naroff48a8c612008-10-03 12:09:49 +0000559 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
560
Steve Naroffacba0f22008-10-04 23:47:37 +0000561 if (hasCopyDisposeHelpers)
562 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
563
Steve Naroff48a8c612008-10-03 12:09:49 +0000564 // Initialize all "by copy" arguments.
565 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
566 E = BlockByCopyDecls.end(); I != E; ++I) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000567 std::string Name = (*I)->getNameAsString();
Steve Naroff48a8c612008-10-03 12:09:49 +0000568 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000569 if (isBlockPointerType((*I)->getType()))
570 Constructor += Name + " = (struct __block_impl *)_";
571 else
572 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000573 Constructor += Name + ";\n";
574 }
575 // Initialize all "by ref" arguments.
576 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
577 E = BlockByRefDecls.end(); I != E; ++I) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000578 std::string Name = (*I)->getNameAsString();
Steve Naroff48a8c612008-10-03 12:09:49 +0000579 Constructor += " ";
Steve Naroff4e13b762008-10-03 20:28:15 +0000580 if (isBlockPointerType((*I)->getType()))
581 Constructor += Name + " = (struct __block_impl *)_";
582 else
583 Constructor += Name + " = _";
Steve Naroff48a8c612008-10-03 12:09:49 +0000584 Constructor += Name + ";\n";
585 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000586 } else {
587 // Finish writing the constructor.
588 // FIXME: handle NSConcreteGlobalBlock.
589 Constructor += ", int flags=0) {\n";
590 Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof(";
591 Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
Steve Naroffacba0f22008-10-04 23:47:37 +0000592 if (hasCopyDisposeHelpers)
593 Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000594 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000595 Constructor += " ";
596 Constructor += "}\n";
597 S += Constructor;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000598 S += "};\n";
599 return S;
600}
601
602void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
603 const char *FunName) {
604 // Insert closures that were part of the function.
605 for (unsigned i = 0; i < Blocks.size(); i++) {
Steve Naroffacba0f22008-10-04 23:47:37 +0000606
Steve Naroffd3f77902008-10-05 00:06:12 +0000607 CollectBlockDeclRefInfo(Blocks[i]);
608
Steve Naroff48a8c612008-10-03 12:09:49 +0000609 std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000610
Steve Naroffacba0f22008-10-04 23:47:37 +0000611 std::string CI = SynthesizeBlockImpl(Blocks[i], Tag,
612 ImportedBlockDecls.size() > 0);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000613
614 InsertText(FunLocStart, CI.c_str(), CI.size());
Steve Naroff4e13b762008-10-03 20:28:15 +0000615
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000616 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
617
618 InsertText(FunLocStart, CF.c_str(), CF.size());
619
Steve Naroff4e13b762008-10-03 20:28:15 +0000620 if (ImportedBlockDecls.size()) {
621 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
622 InsertText(FunLocStart, HF.c_str(), HF.size());
623 }
624
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000625 BlockDeclRefs.clear();
626 BlockByRefDecls.clear();
627 BlockByCopyDecls.clear();
628 BlockCallExprs.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +0000629 ImportedBlockDecls.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000630 }
631 Blocks.clear();
Steve Naroff8e9216d2008-10-04 17:10:02 +0000632 RewrittenBlockExprs.clear();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000633}
634
635void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
Steve Naroff3ad29e22008-10-03 00:12:09 +0000636 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
Chris Lattner8ec03f52008-11-24 03:54:41 +0000637 const char *FuncName = FD->getNameAsCString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000638
639 SynthesizeBlockLiterals(FunLocStart, FuncName);
640}
641
642void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
643 SourceLocation FunLocStart = MD->getLocStart();
Chris Lattner077bf5e2008-11-24 03:33:13 +0000644 std::string FuncName = MD->getSelector().getAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000645 // Convert colons to underscores.
646 std::string::size_type loc = 0;
647 while ((loc = FuncName.find(":", loc)) != std::string::npos)
648 FuncName.replace(loc, 1, "_");
649
650 SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
651}
652
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000653void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
654 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
655 CI != E; ++CI)
Steve Naroff84a969f2008-10-08 17:31:13 +0000656 if (*CI) {
657 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
658 GetBlockDeclRefExprs(CBE->getBody());
659 else
660 GetBlockDeclRefExprs(*CI);
661 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000662 // Handle specific things.
663 if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
664 // FIXME: Handle enums.
665 if (!isa<FunctionDecl>(CDRE->getDecl()))
666 BlockDeclRefs.push_back(CDRE);
667 return;
668}
669
670void RewriteBlocks::GetBlockCallExprs(Stmt *S) {
671 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
672 CI != E; ++CI)
Steve Naroff84a969f2008-10-08 17:31:13 +0000673 if (*CI) {
674 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
675 GetBlockCallExprs(CBE->getBody());
676 else
677 GetBlockCallExprs(*CI);
678 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000679
680 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
Steve Naroff4e13b762008-10-03 20:28:15 +0000681 if (CE->getCallee()->getType()->isBlockPointerType()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000682 BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE;
Steve Naroff4e13b762008-10-03 20:28:15 +0000683 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000684 }
685 return;
686}
687
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000688std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
689 // Navigate to relevant type information.
Steve Naroffcc2ece22008-09-24 22:46:45 +0000690 const char *closureName = 0;
691 const BlockPointerType *CPT = 0;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000692
693 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
Chris Lattner8ec03f52008-11-24 03:54:41 +0000694 closureName = DRE->getDecl()->getNameAsCString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000695 CPT = DRE->getType()->getAsBlockPointerType();
696 } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
Chris Lattner8ec03f52008-11-24 03:54:41 +0000697 closureName = CDRE->getDecl()->getNameAsCString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000698 CPT = CDRE->getType()->getAsBlockPointerType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000699 } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
Chris Lattner8ec03f52008-11-24 03:54:41 +0000700 closureName = MExpr->getMemberDecl()->getNameAsCString();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000701 CPT = MExpr->getType()->getAsBlockPointerType();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000702 } else {
703 assert(1 && "RewriteBlockClass: Bad type");
704 }
705 assert(CPT && "RewriteBlockClass: Bad type");
706 const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType();
707 assert(FT && "RewriteBlockClass: Bad type");
Douglas Gregor72564e72009-02-26 23:50:07 +0000708 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000709 // FTP will be null for closures that don't take arguments.
710
711 // Build a closure call - start with a paren expr to enforce precedence.
712 std::string BlockCall = "(";
713
714 // Synthesize the cast.
715 BlockCall += "(" + Exp->getType().getAsString() + "(*)";
Steve Naroff8af6a452008-10-02 17:12:56 +0000716 BlockCall += "(struct __block_impl *";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000717 if (FTP) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000718 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000719 E = FTP->arg_type_end(); I && (I != E); ++I)
720 BlockCall += ", " + (*I).getAsString();
721 }
722 BlockCall += "))"; // close the argument list and paren expression.
723
Steve Naroff83ba14e2008-10-03 15:04:50 +0000724 // Invoke the closure. We need to cast it since the declaration type is
725 // bogus (it's a function pointer type)
726 BlockCall += "((struct __block_impl *)";
727 std::string closureExprBufStr;
728 llvm::raw_string_ostream closureExprBuf(closureExprBufStr);
729 Exp->getCallee()->printPretty(closureExprBuf);
730 BlockCall += closureExprBuf.str();
731 BlockCall += ")->FuncPtr)";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000732
733 // Add the arguments.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000734 BlockCall += "((struct __block_impl *)";
Steve Naroffb65a4f12008-10-04 17:45:51 +0000735 BlockCall += closureExprBuf.str();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000736 for (CallExpr::arg_iterator I = Exp->arg_begin(),
737 E = Exp->arg_end(); I != E; ++I) {
738 std::string syncExprBufS;
739 llvm::raw_string_ostream Buf(syncExprBufS);
740 (*I)->printPretty(Buf);
741 BlockCall += ", " + Buf.str();
742 }
743 return BlockCall;
744}
745
746void RewriteBlocks::RewriteBlockCall(CallExpr *Exp) {
747 std::string BlockCall = SynthesizeBlockCall(Exp);
748
749 const char *startBuf = SM->getCharacterData(Exp->getLocStart());
750 const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
751
752 ReplaceText(Exp->getLocStart(), endBuf-startBuf,
753 BlockCall.c_str(), BlockCall.size());
754}
755
Steve Naroff5e52b172008-10-04 18:52:47 +0000756void RewriteBlocks::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
757 // FIXME: Add more elaborate code generation required by the ABI.
758 InsertText(BDRE->getLocStart(), "*", 1);
759}
760
Steve Naroffca743602008-10-15 18:38:58 +0000761void RewriteBlocks::RewriteCastExpr(CastExpr *CE) {
762 SourceLocation LocStart = CE->getLocStart();
763 SourceLocation LocEnd = CE->getLocEnd();
764
Steve Naroff8f6ce572008-11-03 11:20:24 +0000765 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
766 return;
767
Steve Naroffca743602008-10-15 18:38:58 +0000768 const char *startBuf = SM->getCharacterData(LocStart);
769 const char *endBuf = SM->getCharacterData(LocEnd);
770
771 // advance the location to startArgList.
772 const char *argPtr = startBuf;
773
774 while (*argPtr++ && (argPtr < endBuf)) {
775 switch (*argPtr) {
776 case '^':
777 // Replace the '^' with '*'.
778 LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf);
779 ReplaceText(LocStart, 1, "*", 1);
780 break;
781 }
782 }
783 return;
784}
785
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000786void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
787 SourceLocation DeclLoc = FD->getLocation();
Steve Naroffe0109a52008-10-10 15:33:34 +0000788 unsigned parenCount = 0;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000789
790 // We have 1 or more arguments that have closure pointers.
791 const char *startBuf = SM->getCharacterData(DeclLoc);
792 const char *startArgList = strchr(startBuf, '(');
793
794 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
795
796 parenCount++;
797 // advance the location to startArgList.
Steve Naroffe0109a52008-10-10 15:33:34 +0000798 DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000799 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
800
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000801 const char *argPtr = startArgList;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000802
803 while (*argPtr++ && parenCount) {
804 switch (*argPtr) {
805 case '^':
Steve Naroffe0109a52008-10-10 15:33:34 +0000806 // Replace the '^' with '*'.
807 DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList);
808 ReplaceText(DeclLoc, 1, "*", 1);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000809 break;
810 case '(':
811 parenCount++;
812 break;
813 case ')':
814 parenCount--;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000815 break;
816 }
817 }
818 return;
819}
820
Steve Naroffca743602008-10-15 18:38:58 +0000821bool RewriteBlocks::PointerTypeTakesAnyBlockArguments(QualType QT) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000822 const FunctionProtoType *FTP;
Steve Naroffca743602008-10-15 18:38:58 +0000823 const PointerType *PT = QT->getAsPointerType();
824 if (PT) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000825 FTP = PT->getPointeeType()->getAsFunctionProtoType();
Steve Naroffca743602008-10-15 18:38:58 +0000826 } else {
827 const BlockPointerType *BPT = QT->getAsBlockPointerType();
828 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
Douglas Gregor72564e72009-02-26 23:50:07 +0000829 FTP = BPT->getPointeeType()->getAsFunctionProtoType();
Steve Naroffca743602008-10-15 18:38:58 +0000830 }
Steve Naroffeab5f632008-09-23 19:24:41 +0000831 if (FTP) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000832 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
Steve Naroffeab5f632008-09-23 19:24:41 +0000833 E = FTP->arg_type_end(); I != E; ++I)
834 if (isBlockPointerType(*I))
835 return true;
836 }
837 return false;
838}
839
840void RewriteBlocks::GetExtentOfArgList(const char *Name,
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000841 const char *&LParen, const char *&RParen) {
842 const char *argPtr = strchr(Name, '(');
Steve Naroffeab5f632008-09-23 19:24:41 +0000843 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
844
845 LParen = argPtr; // output the start.
846 argPtr++; // skip past the left paren.
847 unsigned parenCount = 1;
848
849 while (*argPtr && parenCount) {
850 switch (*argPtr) {
851 case '(': parenCount++; break;
852 case ')': parenCount--; break;
853 default: break;
854 }
855 if (parenCount) argPtr++;
856 }
857 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
858 RParen = argPtr; // output the end
859}
860
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000861void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000862 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
863 RewriteBlockPointerFunctionArgs(FD);
864 return;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000865 }
866 // Handle Variables and Typedefs.
867 SourceLocation DeclLoc = ND->getLocation();
868 QualType DeclT;
869 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
870 DeclT = VD->getType();
871 else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
872 DeclT = TDD->getUnderlyingType();
Steve Naroff83ba14e2008-10-03 15:04:50 +0000873 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
874 DeclT = FD->getType();
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000875 else
876 assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
Steve Naroffeab5f632008-09-23 19:24:41 +0000877
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000878 const char *startBuf = SM->getCharacterData(DeclLoc);
879 const char *endBuf = startBuf;
880 // scan backward (from the decl location) for the end of the previous decl.
881 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
882 startBuf--;
Steve Naroffca743602008-10-15 18:38:58 +0000883
884 // *startBuf != '^' if we are dealing with a pointer to function that
885 // may take block argument types (which will be handled below).
886 if (*startBuf == '^') {
887 // Replace the '^' with '*', computing a negative offset.
888 DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
889 ReplaceText(DeclLoc, 1, "*", 1);
890 }
891 if (PointerTypeTakesAnyBlockArguments(DeclT)) {
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000892 // Replace the '^' with '*' for arguments.
893 DeclLoc = ND->getLocation();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000894 startBuf = SM->getCharacterData(DeclLoc);
Steve Naroff1f6c3ae2008-09-24 17:22:34 +0000895 const char *argListBegin, *argListEnd;
Steve Naroffca3bb4f2008-09-23 21:15:53 +0000896 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
897 while (argListBegin < argListEnd) {
898 if (*argListBegin == '^') {
899 SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
900 ReplaceText(CaretLoc, 1, "*", 1);
901 }
902 argListBegin++;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000903 }
Steve Naroffeab5f632008-09-23 19:24:41 +0000904 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000905 return;
906}
907
Steve Naroffd3f77902008-10-05 00:06:12 +0000908void RewriteBlocks::CollectBlockDeclRefInfo(BlockExpr *Exp) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000909 // Add initializers for any closure decl refs.
Steve Naroff84a969f2008-10-08 17:31:13 +0000910 GetBlockDeclRefExprs(Exp->getBody());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000911 if (BlockDeclRefs.size()) {
912 // Unique all "by copy" declarations.
913 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
914 if (!BlockDeclRefs[i]->isByRef())
915 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
916 // Unique all "by ref" declarations.
917 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
918 if (BlockDeclRefs[i]->isByRef()) {
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000919 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
920 }
Steve Naroffacba0f22008-10-04 23:47:37 +0000921 // Find any imported blocks...they will need special attention.
922 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
923 if (isBlockPointerType(BlockDeclRefs[i]->getType())) {
924 GetBlockCallExprs(Blocks[i]);
925 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
926 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000927 }
Steve Naroffd3f77902008-10-05 00:06:12 +0000928}
929
930std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) {
931 Blocks.push_back(Exp);
932
933 CollectBlockDeclRefInfo(Exp);
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000934 std::string FuncName;
935
936 if (CurFunctionDef)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000937 FuncName = std::string(CurFunctionDef->getNameAsString());
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000938 else if (CurMethodDef) {
Chris Lattner077bf5e2008-11-24 03:33:13 +0000939 FuncName = CurMethodDef->getSelector().getAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000940 // Convert colons to underscores.
941 std::string::size_type loc = 0;
942 while ((loc = FuncName.find(":", loc)) != std::string::npos)
943 FuncName.replace(loc, 1, "_");
Steve Naroff39622b92008-10-03 15:38:09 +0000944 } else if (VD)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000945 FuncName = std::string(VD->getNameAsString());
Steve Naroff39622b92008-10-03 15:38:09 +0000946
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000947 std::string BlockNumber = utostr(Blocks.size()-1);
948
Steve Naroff83ba14e2008-10-03 15:04:50 +0000949 std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
Steve Naroffa0b75cf2008-10-02 23:30:43 +0000950 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000951
Steve Naroff83ba14e2008-10-03 15:04:50 +0000952 std::string FunkTypeStr;
953
954 // Get a pointer to the function type so we can cast appropriately.
955 Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr);
956
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000957 // Rewrite the closure block with a compound literal. The first cast is
958 // to prevent warnings from the C compiler.
Steve Naroff83ba14e2008-10-03 15:04:50 +0000959 std::string Init = "(" + FunkTypeStr;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000960
Steve Naroff83ba14e2008-10-03 15:04:50 +0000961 Init += ")&" + Tag;
962
963 // Initialize the block function.
964 Init += "((void*)" + Func;
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000965
Steve Naroffacba0f22008-10-04 23:47:37 +0000966 if (ImportedBlockDecls.size()) {
967 std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber;
968 Init += ",(void*)" + Buf;
969 Buf = "__" + FuncName + "_block_dispose_" + BlockNumber;
970 Init += ",(void*)" + Buf;
971 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000972 // Add initializers for any closure decl refs.
973 if (BlockDeclRefs.size()) {
974 // Output all "by copy" declarations.
975 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
976 E = BlockByCopyDecls.end(); I != E; ++I) {
977 Init += ",";
978 if (isObjCType((*I)->getType())) {
979 Init += "[[";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000980 Init += (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000981 Init += " retain] autorelease]";
Steve Naroff4e13b762008-10-03 20:28:15 +0000982 } else if (isBlockPointerType((*I)->getType())) {
983 Init += "(void *)";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000984 Init += (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000985 } else {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000986 Init += (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000987 }
988 }
989 // Output all "by ref" declarations.
990 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
991 E = BlockByRefDecls.end(); I != E; ++I) {
992 Init += ",&";
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000993 Init += (*I)->getNameAsString();
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000994 }
995 }
Steve Naroff83ba14e2008-10-03 15:04:50 +0000996 Init += ")";
Steve Naroff1c9f81b2008-09-17 00:13:27 +0000997 BlockDeclRefs.clear();
998 BlockByRefDecls.clear();
999 BlockByCopyDecls.clear();
Steve Naroff4e13b762008-10-03 20:28:15 +00001000 ImportedBlockDecls.clear();
1001
Steve Naroff70f95502008-10-04 17:06:23 +00001002 return Init;
1003}
1004
1005//===----------------------------------------------------------------------===//
1006// Function Body / Expression rewriting
1007//===----------------------------------------------------------------------===//
1008
1009Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
1010 // Start by rewriting all children.
1011 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
1012 CI != E; ++CI)
1013 if (*CI) {
1014 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
Steve Naroff84a969f2008-10-08 17:31:13 +00001015 Stmt *newStmt = RewriteFunctionBody(CBE->getBody());
Steve Naroff70f95502008-10-04 17:06:23 +00001016 if (newStmt)
1017 *CI = newStmt;
1018
1019 // We've just rewritten the block body in place.
1020 // Now we snarf the rewritten text and stash it away for later use.
1021 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1022 RewrittenBlockExprs[CBE] = S;
1023 std::string Init = SynthesizeBlockInitExpr(CBE);
1024 // Do the rewrite, using S.size() which contains the rewritten size.
1025 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
1026 } else {
1027 Stmt *newStmt = RewriteFunctionBody(*CI);
1028 if (newStmt)
1029 *CI = newStmt;
1030 }
1031 }
1032 // Handle specific things.
1033 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1034 if (CE->getCallee()->getType()->isBlockPointerType())
1035 RewriteBlockCall(CE);
1036 }
Steve Naroffca743602008-10-15 18:38:58 +00001037 if (CastExpr *CE = dyn_cast<CastExpr>(S)) {
1038 RewriteCastExpr(CE);
1039 }
Steve Naroff70f95502008-10-04 17:06:23 +00001040 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
Ted Kremenekfda4fed2008-10-06 18:47:09 +00001041 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
1042 DI != DE; ++DI) {
1043
Douglas Gregor4afa39d2009-01-20 01:17:11 +00001044 Decl *SD = *DI;
Ted Kremenekfda4fed2008-10-06 18:47:09 +00001045 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
1046 if (isBlockPointerType(ND->getType()))
1047 RewriteBlockPointerDecl(ND);
Steve Naroffca743602008-10-15 18:38:58 +00001048 else if (ND->getType()->isFunctionPointerType())
1049 CheckFunctionPointerDecl(ND->getType(), ND);
Ted Kremenekfda4fed2008-10-06 18:47:09 +00001050 }
1051 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
1052 if (isBlockPointerType(TD->getUnderlyingType()))
1053 RewriteBlockPointerDecl(TD);
Steve Naroffca743602008-10-15 18:38:58 +00001054 else if (TD->getUnderlyingType()->isFunctionPointerType())
1055 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
Ted Kremenekfda4fed2008-10-06 18:47:09 +00001056 }
Steve Naroff70f95502008-10-04 17:06:23 +00001057 }
1058 }
Steve Naroff5e52b172008-10-04 18:52:47 +00001059 // Handle specific things.
1060 if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
1061 if (BDRE->isByRef())
1062 RewriteBlockDeclRefExpr(BDRE);
1063 }
Steve Naroff70f95502008-10-04 17:06:23 +00001064 // Return this stmt unmodified.
1065 return S;
1066}
1067
Douglas Gregor72564e72009-02-26 23:50:07 +00001068void RewriteBlocks::RewriteFunctionProtoType(QualType funcType, NamedDecl *D) {
1069 if (FunctionProtoType *fproto = dyn_cast<FunctionProtoType>(funcType)) {
1070 for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(),
Steve Naroffca743602008-10-15 18:38:58 +00001071 E = fproto->arg_type_end(); I && (I != E); ++I)
1072 if (isBlockPointerType(*I)) {
1073 // All the args are checked/rewritten. Don't call twice!
1074 RewriteBlockPointerDecl(D);
1075 break;
1076 }
1077 }
1078}
1079
1080void RewriteBlocks::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
1081 const PointerType *PT = funcType->getAsPointerType();
1082 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
Douglas Gregor72564e72009-02-26 23:50:07 +00001083 RewriteFunctionProtoType(PT->getPointeeType(), ND);
Steve Naroffca743602008-10-15 18:38:58 +00001084}
1085
Steve Naroff70f95502008-10-04 17:06:23 +00001086/// HandleDeclInMainFile - This is called for each top-level decl defined in the
1087/// main file of the input.
1088void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
1089 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff70f95502008-10-04 17:06:23 +00001090 // Since function prototypes don't have ParmDecl's, we check the function
1091 // prototype. This enables us to rewrite function declarations and
1092 // definitions using the same code.
Douglas Gregor72564e72009-02-26 23:50:07 +00001093 RewriteFunctionProtoType(FD->getType(), FD);
Sebastian Redld3a413d2009-04-26 20:35:05 +00001094
1095 // FIXME: Handle CXXTryStmt
1096 if (CompoundStmt *Body = FD->getCompoundBody(*Context)) {
Steve Naroff70f95502008-10-04 17:06:23 +00001097 CurFunctionDef = FD;
Ted Kremenekeaab2062009-03-12 18:33:24 +00001098 FD->setBody(cast_or_null<CompoundStmt>(RewriteFunctionBody(Body)));
Steve Naroff70f95502008-10-04 17:06:23 +00001099 // This synthesizes and inserts the block "impl" struct, invoke function,
1100 // and any copy/dispose helper functions.
1101 InsertBlockLiteralsWithinFunction(FD);
1102 CurFunctionDef = 0;
1103 }
1104 return;
1105 }
1106 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
1107 RewriteMethodDecl(MD);
Douglas Gregor72971342009-04-18 00:02:19 +00001108 if (Stmt *Body = MD->getBody(*Context)) {
Steve Naroff70f95502008-10-04 17:06:23 +00001109 CurMethodDef = MD;
1110 RewriteFunctionBody(Body);
1111 InsertBlockLiteralsWithinMethod(MD);
1112 CurMethodDef = 0;
1113 }
1114 }
1115 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
1116 if (isBlockPointerType(VD->getType())) {
1117 RewriteBlockPointerDecl(VD);
1118 if (VD->getInit()) {
1119 if (BlockExpr *CBE = dyn_cast<BlockExpr>(VD->getInit())) {
Douglas Gregor72971342009-04-18 00:02:19 +00001120 RewriteFunctionBody(CBE->getBody(*Context));
Steve Naroff70f95502008-10-04 17:06:23 +00001121
1122 // We've just rewritten the block body in place.
1123 // Now we snarf the rewritten text and stash it away for later use.
1124 std::string S = Rewrite.getRewritenText(CBE->getSourceRange());
1125 RewrittenBlockExprs[CBE] = S;
1126 std::string Init = SynthesizeBlockInitExpr(CBE, VD);
1127 // Do the rewrite, using S.size() which contains the rewritten size.
1128 ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
Douglas Gregor2e1cd422008-11-17 14:58:09 +00001129 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(),
Chris Lattner8ec03f52008-11-24 03:54:41 +00001130 VD->getNameAsCString());
Steve Naroffca743602008-10-15 18:38:58 +00001131 } else if (CastExpr *CE = dyn_cast<CastExpr>(VD->getInit())) {
1132 RewriteCastExpr(CE);
1133 }
1134 }
1135 } else if (VD->getType()->isFunctionPointerType()) {
1136 CheckFunctionPointerDecl(VD->getType(), VD);
1137 if (VD->getInit()) {
1138 if (CastExpr *CE = dyn_cast<CastExpr>(VD->getInit())) {
1139 RewriteCastExpr(CE);
Steve Naroff70f95502008-10-04 17:06:23 +00001140 }
1141 }
1142 }
1143 return;
1144 }
1145 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
1146 if (isBlockPointerType(TD->getUnderlyingType()))
1147 RewriteBlockPointerDecl(TD);
Steve Naroffca743602008-10-15 18:38:58 +00001148 else if (TD->getUnderlyingType()->isFunctionPointerType())
1149 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
Steve Naroff70f95502008-10-04 17:06:23 +00001150 return;
1151 }
1152 if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
1153 if (RD->isDefinition()) {
Douglas Gregor6ab35242009-04-09 21:40:53 +00001154 for (RecordDecl::field_iterator i = RD->field_begin(*Context),
1155 e = RD->field_end(*Context); i != e; ++i) {
Steve Naroff70f95502008-10-04 17:06:23 +00001156 FieldDecl *FD = *i;
1157 if (isBlockPointerType(FD->getType()))
1158 RewriteBlockPointerDecl(FD);
1159 }
1160 }
1161 return;
1162 }
Steve Naroff1c9f81b2008-09-17 00:13:27 +00001163}