blob: 109cd4d83c97833a533a23f829b32c29eedce06e [file] [log] [blame]
Chris Lattner77cd2a02007-10-11 00:43:27 +00001//===--- RewriteTest.cpp - Playground for the code rewriter ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the code rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000015#include "clang/Rewrite/Rewriter.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000016#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000018#include "clang/Basic/SourceManager.h"
Steve Naroffebf2b562007-10-23 23:50:29 +000019#include "clang/Basic/IdentifierTable.h"
Chris Lattner158ecb92007-10-25 17:07:24 +000020#include "llvm/ADT/StringExtras.h"
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000021#include "llvm/ADT/SmallPtrSet.h"
Steve Naroff2feac5e2007-10-30 03:43:13 +000022#include "clang/Lex/Lexer.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000023using namespace clang;
Chris Lattner158ecb92007-10-25 17:07:24 +000024using llvm::utostr;
Chris Lattner77cd2a02007-10-11 00:43:27 +000025
Chris Lattner77cd2a02007-10-11 00:43:27 +000026namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000027 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000028 Rewriter Rewrite;
Chris Lattner01c57482007-10-17 22:35:30 +000029 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000030 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000031 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000032 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000033 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
34 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000035 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcSynthesizedStructs;
Steve Naroffebf2b562007-10-23 23:50:29 +000036
37 FunctionDecl *MsgSendFunctionDecl;
38 FunctionDecl *GetClassFunctionDecl;
Steve Naroff934f2762007-10-24 22:48:43 +000039 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffebf2b562007-10-23 23:50:29 +000040
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000041 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000042 public:
Chris Lattner01c57482007-10-17 22:35:30 +000043 void Initialize(ASTContext &context, unsigned mainFileID) {
44 Context = &context;
45 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000046 MainFileID = mainFileID;
Steve Naroffebf2b562007-10-23 23:50:29 +000047 MsgSendFunctionDecl = 0;
Steve Naroffc0006092007-10-24 01:09:48 +000048 GetClassFunctionDecl = 0;
Steve Naroff934f2762007-10-24 22:48:43 +000049 SelGetUidFunctionDecl = 0;
Chris Lattner01c57482007-10-17 22:35:30 +000050 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000051 }
Chris Lattner8a12c272007-10-11 18:38:32 +000052
Chris Lattnerf04da132007-10-24 17:06:59 +000053 // Top Level Driver code.
54 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000055 void HandleDeclInMainFile(Decl *D);
Chris Lattnerf04da132007-10-24 17:06:59 +000056 ~RewriteTest();
57
58 // Syntactic Rewriting.
Chris Lattner2c64b7b2007-10-16 21:07:07 +000059 void RewriteInclude(SourceLocation Loc);
Chris Lattnerf04da132007-10-24 17:06:59 +000060 void RewriteTabs();
61 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroffbef11852007-10-26 20:53:56 +000062 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Steve Naroff423cb562007-10-30 13:30:57 +000063 void RewriteCategoryDecl(ObjcCategoryDecl *Dcl);
Steve Naroff752d6ef2007-10-30 16:42:30 +000064 void RewriteProtocolDecl(ObjcProtocolDecl *Dcl);
Steve Naroff423cb562007-10-30 13:30:57 +000065 void RewriteMethods(int nMethods, ObjcMethodDecl **Methods);
Chris Lattner311ff022007-10-16 22:36:42 +000066
Chris Lattnerf04da132007-10-24 17:06:59 +000067 // Expression Rewriting.
Chris Lattnere64b7772007-10-24 16:57:36 +000068 Stmt *RewriteFunctionBody(Stmt *S);
69 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
70 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff934f2762007-10-24 22:48:43 +000071 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
72 Expr **args, unsigned nargs);
Chris Lattnerf04da132007-10-24 17:06:59 +000073 // Metadata emission.
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000074 void HandleObjcMetaDataEmission();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000075 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
76 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000077
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000078 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
79 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000080
81 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
82 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +000083 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000084 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +000085 const char *ClassName,
86 std::string &Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +000087
88 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
89 int NumProtocols,
90 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000091 const char *ClassName,
92 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000093 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
94 std::string &Result);
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +000095 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
96 ObjcIvarDecl *ivar,
97 std::string &Result);
Fariborz Jahanianccd87b02007-10-25 20:55:25 +000098 void WriteObjcMetaData(std::string &Result);
Chris Lattner77cd2a02007-10-11 00:43:27 +000099 };
100}
101
Chris Lattner8a12c272007-10-11 18:38:32 +0000102ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +0000103
Chris Lattnerf04da132007-10-24 17:06:59 +0000104//===----------------------------------------------------------------------===//
105// Top Level Driver Code
106//===----------------------------------------------------------------------===//
107
Chris Lattner8a12c272007-10-11 18:38:32 +0000108void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000109 // Two cases: either the decl could be in the main file, or it could be in a
110 // #included file. If the former, rewrite it now. If the later, check to see
111 // if we rewrote the #include/#import.
112 SourceLocation Loc = D->getLocation();
113 Loc = SM->getLogicalLoc(Loc);
114
115 // If this is for a builtin, ignore it.
116 if (Loc.isInvalid()) return;
117
Steve Naroffebf2b562007-10-23 23:50:29 +0000118 // Look for built-in declarations that we need to refer during the rewrite.
119 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroffc0006092007-10-24 01:09:48 +0000120 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000121 MsgSendFunctionDecl = FD;
Steve Naroffc0006092007-10-24 01:09:48 +0000122 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffebf2b562007-10-23 23:50:29 +0000123 GetClassFunctionDecl = FD;
Steve Naroff934f2762007-10-24 22:48:43 +0000124 else if (strcmp(FD->getName(), "sel_getUid") == 0)
125 SelGetUidFunctionDecl = FD;
Steve Naroffbef11852007-10-26 20:53:56 +0000126 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
127 RewriteInterfaceDecl(MD);
Steve Naroff423cb562007-10-30 13:30:57 +0000128 } else if (ObjcCategoryDecl *CD = dyn_cast<ObjcCategoryDecl>(D)) {
129 RewriteCategoryDecl(CD);
Steve Naroff752d6ef2007-10-30 16:42:30 +0000130 } else if (ObjcProtocolDecl *PD = dyn_cast<ObjcProtocolDecl>(D)) {
131 RewriteProtocolDecl(PD);
Steve Naroffebf2b562007-10-23 23:50:29 +0000132 }
Chris Lattnerf04da132007-10-24 17:06:59 +0000133 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000134 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
135 return HandleDeclInMainFile(D);
136
Chris Lattnerf04da132007-10-24 17:06:59 +0000137 // Otherwise, see if there is a #import in the main file that should be
138 // rewritten.
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000139 RewriteInclude(Loc);
140}
141
Chris Lattnerf04da132007-10-24 17:06:59 +0000142/// HandleDeclInMainFile - This is called for each top-level decl defined in the
143/// main file of the input.
144void RewriteTest::HandleDeclInMainFile(Decl *D) {
145 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
146 if (Stmt *Body = FD->getBody())
147 FD->setBody(RewriteFunctionBody(Body));
148
149 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
150 ClassImplementation.push_back(CI);
151 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
152 CategoryImplementation.push_back(CI);
153 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
154 RewriteForwardClassDecl(CD);
155 // Nothing yet.
156}
157
158RewriteTest::~RewriteTest() {
159 // Get the top-level buffer that this corresponds to.
160 RewriteTabs();
161
162 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
163 // we are done.
164 if (const RewriteBuffer *RewriteBuf =
165 Rewrite.getRewriteBufferFor(MainFileID)) {
166 printf("Changed:\n");
167 std::string S(RewriteBuf->begin(), RewriteBuf->end());
168 printf("%s\n", S.c_str());
169 } else {
170 printf("No changes\n");
171 }
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000172
173}
174
175/// HandleObjcMetaDataEmission - main routine to generate objective-c's
176/// metadata.
177void RewriteTest::HandleObjcMetaDataEmission() {
Chris Lattnerf04da132007-10-24 17:06:59 +0000178 // Rewrite Objective-c meta data*
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000179 std::string ResultStr;
180 WriteObjcMetaData(ResultStr);
181 // For now just print the string out.
182 printf("%s", ResultStr.c_str());
Chris Lattnerf04da132007-10-24 17:06:59 +0000183}
184
185//===----------------------------------------------------------------------===//
186// Syntactic (non-AST) Rewriting Code
187//===----------------------------------------------------------------------===//
188
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000189void RewriteTest::RewriteInclude(SourceLocation Loc) {
190 // Rip up the #include stack to the main file.
191 SourceLocation IncLoc = Loc, NextLoc = Loc;
192 do {
193 IncLoc = Loc;
194 Loc = SM->getLogicalLoc(NextLoc);
195 NextLoc = SM->getIncludeLoc(Loc);
196 } while (!NextLoc.isInvalid());
197
198 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
199 // IncLoc indicates the header that was included if it is useful.
200 IncLoc = SM->getLogicalLoc(IncLoc);
201 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
202 Loc == LastIncLoc)
203 return;
204 LastIncLoc = Loc;
205
206 unsigned IncCol = SM->getColumnNumber(Loc);
207 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
208
209 // Replace the #import with #include.
210 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
211}
212
Chris Lattnerf04da132007-10-24 17:06:59 +0000213void RewriteTest::RewriteTabs() {
214 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
215 const char *MainBufStart = MainBuf.first;
216 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000217
Chris Lattnerf04da132007-10-24 17:06:59 +0000218 // Loop over the whole file, looking for tabs.
219 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
220 if (*BufPtr != '\t')
221 continue;
222
223 // Okay, we found a tab. This tab will turn into at least one character,
224 // but it depends on which 'virtual column' it is in. Compute that now.
225 unsigned VCol = 0;
226 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
227 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
228 ++VCol;
229
230 // Okay, now that we know the virtual column, we know how many spaces to
231 // insert. We assume 8-character tab-stops.
232 unsigned Spaces = 8-(VCol & 7);
233
234 // Get the location of the tab.
235 SourceLocation TabLoc =
236 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
237
238 // Rewrite the single tab character into a sequence of spaces.
239 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
240 }
Chris Lattner8a12c272007-10-11 18:38:32 +0000241}
242
243
Chris Lattnerf04da132007-10-24 17:06:59 +0000244void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
245 int numDecls = ClassDecl->getNumForwardDecls();
246 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
247
248 // Get the start location and compute the semi location.
249 SourceLocation startLoc = ClassDecl->getLocation();
250 const char *startBuf = SM->getCharacterData(startLoc);
251 const char *semiPtr = strchr(startBuf, ';');
252
253 // Translate to typedef's that forward reference structs with the same name
254 // as the class. As a convenience, we include the original declaration
255 // as a comment.
256 std::string typedefString;
257 typedefString += "// ";
Steve Naroff934f2762007-10-24 22:48:43 +0000258 typedefString.append(startBuf, semiPtr-startBuf+1);
259 typedefString += "\n";
260 for (int i = 0; i < numDecls; i++) {
261 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
262 typedefString += "typedef struct ";
263 typedefString += ForwardDecl->getName();
264 typedefString += " ";
265 typedefString += ForwardDecl->getName();
266 typedefString += ";\n";
267 }
268
269 // Replace the @class with typedefs corresponding to the classes.
270 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
271 typedefString.c_str(), typedefString.size());
Chris Lattnerf04da132007-10-24 17:06:59 +0000272}
273
Steve Naroff423cb562007-10-30 13:30:57 +0000274void RewriteTest::RewriteMethods(int nMethods, ObjcMethodDecl **Methods) {
275 for (int i = 0; i < nMethods; i++) {
276 ObjcMethodDecl *Method = Methods[i];
277 SourceLocation Loc = Method->getLocStart();
278
279 Rewrite.ReplaceText(Loc, 0, "// ", 3);
280
281 // FIXME: handle methods that are declared across multiple lines.
282 }
283}
284
285void RewriteTest::RewriteCategoryDecl(ObjcCategoryDecl *CatDecl) {
286 SourceLocation LocStart = CatDecl->getLocStart();
287
288 // FIXME: handle category headers that are declared across multiple lines.
289 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
290
291 RewriteMethods(CatDecl->getNumInstanceMethods(),
292 CatDecl->getInstanceMethods());
293 RewriteMethods(CatDecl->getNumClassMethods(),
294 CatDecl->getClassMethods());
295 // Lastly, comment out the @end.
296 Rewrite.ReplaceText(CatDecl->getAtEndLoc(), 0, "// ", 3);
297}
298
Steve Naroff752d6ef2007-10-30 16:42:30 +0000299void RewriteTest::RewriteProtocolDecl(ObjcProtocolDecl *PDecl) {
300 SourceLocation LocStart = PDecl->getLocStart();
301
302 // FIXME: handle protocol headers that are declared across multiple lines.
303 Rewrite.ReplaceText(LocStart, 0, "// ", 3);
304
305 RewriteMethods(PDecl->getNumInstanceMethods(),
306 PDecl->getInstanceMethods());
307 RewriteMethods(PDecl->getNumClassMethods(),
308 PDecl->getClassMethods());
309 // Lastly, comment out the @end.
310 Rewrite.ReplaceText(PDecl->getAtEndLoc(), 0, "// ", 3);
311}
312
Steve Naroffbef11852007-10-26 20:53:56 +0000313void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
Steve Narofff908a872007-10-30 02:23:23 +0000314
315 SourceLocation LocStart = ClassDecl->getLocStart();
316 SourceLocation LocEnd = ClassDecl->getLocEnd();
317
318 const char *startBuf = SM->getCharacterData(LocStart);
319 const char *endBuf = SM->getCharacterData(LocEnd);
320
Steve Naroff2feac5e2007-10-30 03:43:13 +0000321 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM);
Steve Narofff908a872007-10-30 02:23:23 +0000322
323 std::string ResultStr;
324 SynthesizeObjcInternalStruct(ClassDecl, ResultStr);
325
Steve Naroff2feac5e2007-10-30 03:43:13 +0000326 Rewrite.ReplaceText(LocStart, endBuf-startBuf,
Steve Narofff908a872007-10-30 02:23:23 +0000327 ResultStr.c_str(), ResultStr.size());
328
Steve Naroff423cb562007-10-30 13:30:57 +0000329 RewriteMethods(ClassDecl->getNumInstanceMethods(),
330 ClassDecl->getInstanceMethods());
331 RewriteMethods(ClassDecl->getNumClassMethods(),
332 ClassDecl->getClassMethods());
Steve Naroffbef11852007-10-26 20:53:56 +0000333
Steve Naroff2feac5e2007-10-30 03:43:13 +0000334 // Lastly, comment out the @end.
335 Rewrite.ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
Steve Naroffbef11852007-10-26 20:53:56 +0000336}
337
Chris Lattnerf04da132007-10-24 17:06:59 +0000338//===----------------------------------------------------------------------===//
339// Function Body / Expression rewriting
340//===----------------------------------------------------------------------===//
341
Chris Lattnere64b7772007-10-24 16:57:36 +0000342Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner311ff022007-10-16 22:36:42 +0000343 // Otherwise, just rewrite all children.
344 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
345 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000346 if (*CI)
Chris Lattnere64b7772007-10-24 16:57:36 +0000347 *CI = RewriteFunctionBody(*CI);
Steve Naroffebf2b562007-10-23 23:50:29 +0000348
349 // Handle specific things.
350 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
351 return RewriteAtEncode(AtEncode);
352
Steve Naroff934f2762007-10-24 22:48:43 +0000353 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
354 // Before we rewrite it, put the original message expression in a comment.
355 SourceLocation startLoc = MessExpr->getLocStart();
356 SourceLocation endLoc = MessExpr->getLocEnd();
357
358 const char *startBuf = SM->getCharacterData(startLoc);
359 const char *endBuf = SM->getCharacterData(endLoc);
360
361 std::string messString;
362 messString += "// ";
363 messString.append(startBuf, endBuf-startBuf+1);
364 messString += "\n";
Steve Naroffbef11852007-10-26 20:53:56 +0000365
Steve Naroff934f2762007-10-24 22:48:43 +0000366 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
367 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
368 // Tried this, but it didn't work either...
Steve Naroff752d6ef2007-10-30 16:42:30 +0000369 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffebf2b562007-10-23 23:50:29 +0000370 return RewriteMessageExpr(MessExpr);
Steve Naroff934f2762007-10-24 22:48:43 +0000371 }
Chris Lattnere64b7772007-10-24 16:57:36 +0000372 // Return this stmt unmodified.
373 return S;
Chris Lattner311ff022007-10-16 22:36:42 +0000374}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000375
Chris Lattnere64b7772007-10-24 16:57:36 +0000376Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000377 // Create a new string expression.
378 QualType StrType = Context->getPointerType(Context->CharTy);
Anders Carlsson85f9bce2007-10-29 05:01:08 +0000379 std::string StrEncoding;
380 Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
381 Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
382 StrEncoding.length(), false, StrType,
Chris Lattner01c57482007-10-17 22:35:30 +0000383 SourceLocation(), SourceLocation());
384 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattnere64b7772007-10-24 16:57:36 +0000385 delete Exp;
386 return Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000387}
388
Steve Naroff934f2762007-10-24 22:48:43 +0000389CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
390 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffebf2b562007-10-23 23:50:29 +0000391 // Get the type, we will need to reference it in a couple spots.
Steve Naroff934f2762007-10-24 22:48:43 +0000392 QualType msgSendType = FD->getType();
Steve Naroffebf2b562007-10-23 23:50:29 +0000393
394 // Create a reference to the objc_msgSend() declaration.
Steve Naroff934f2762007-10-24 22:48:43 +0000395 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffebf2b562007-10-23 23:50:29 +0000396
397 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerf04da132007-10-24 17:06:59 +0000398 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffebf2b562007-10-23 23:50:29 +0000399 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
400
401 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattnere64b7772007-10-24 16:57:36 +0000402
Steve Naroff934f2762007-10-24 22:48:43 +0000403 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
404}
405
406Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
407 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
408 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
409 assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
410
411 // Synthesize a call to objc_msgSend().
412 llvm::SmallVector<Expr*, 8> MsgExprs;
413 IdentifierInfo *clsName = Exp->getClassName();
414
415 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
416 if (clsName) { // class message.
417 llvm::SmallVector<Expr*, 8> ClsExprs;
418 QualType argType = Context->getPointerType(Context->CharTy);
419 ClsExprs.push_back(new StringLiteral(clsName->getName(),
420 clsName->getLength(),
421 false, argType, SourceLocation(),
422 SourceLocation()));
423 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
424 &ClsExprs[0], ClsExprs.size());
425 MsgExprs.push_back(Cls);
426 } else // instance message.
427 MsgExprs.push_back(Exp->getReceiver());
428
429 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
430 llvm::SmallVector<Expr*, 8> SelExprs;
431 QualType argType = Context->getPointerType(Context->CharTy);
432 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
433 Exp->getSelector().getName().size(),
434 false, argType, SourceLocation(),
435 SourceLocation()));
436 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
437 &SelExprs[0], SelExprs.size());
438 MsgExprs.push_back(SelExp);
439
440 // Now push any user supplied arguments.
441 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
442 MsgExprs.push_back(Exp->getArg(i));
443 // We've transferred the ownership to MsgExprs. Null out the argument in
444 // the original expression, since we will delete it below.
445 Exp->setArg(i, 0);
446 }
447 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
448 &MsgExprs[0], MsgExprs.size());
449 // Now do the actual rewrite.
450 Rewrite.ReplaceStmt(Exp, MessExp);
451
Chris Lattnere64b7772007-10-24 16:57:36 +0000452 delete Exp;
Steve Naroff934f2762007-10-24 22:48:43 +0000453 return MessExp;
Steve Naroffebf2b562007-10-23 23:50:29 +0000454}
455
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000456/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
457/// an objective-c class with ivars.
458void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
459 std::string &Result) {
460 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
461 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
462 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
463 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
464 // Do it for the root
465 SynthesizeObjcInternalStruct(RCDecl, Result);
466 }
467
468 int NumIvars = CDecl->getIntfDeclNumIvars();
469 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl)))
470 return;
471
472 Result += "\nstruct _interface_";
473 Result += CDecl->getName();
474 Result += " {\n";
475 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
476 Result += "\tstruct _interface_";
477 Result += RCDecl->getName();
478 Result += " _";
479 Result += RCDecl->getName();
480 Result += ";\n";
481 }
482
483 ObjcIvarDecl **Ivars = CDecl->getIntfDeclIvars();
484 for (int i = 0; i < NumIvars; i++) {
485 Result += "\t";
486 std::string Name = Ivars[i]->getName();
487 Ivars[i]->getType().getAsStringInternal(Name);
488 Result += Name;
489 Result += ";\n";
490 }
491 Result += "};\n";
492 // Mark this struct as having been generated.
493 if (!ObjcSynthesizedStructs.insert(CDecl))
494 assert(true && "struct already synthesize- SynthesizeObjcInternalStruct");
495}
496
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000497// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
498/// class methods.
499void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
500 int NumMethods,
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000501 bool IsInstanceMethod,
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000502 const char *prefix,
Chris Lattner158ecb92007-10-25 17:07:24 +0000503 const char *ClassName,
504 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000505 static bool objc_impl_method = false;
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000506 if (NumMethods > 0 && !objc_impl_method) {
507 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000508 SEL _cmd;
509 char *method_types;
510 void *_imp;
511 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000512 */
Chris Lattner158ecb92007-10-25 17:07:24 +0000513 Result += "\nstruct _objc_method {\n";
514 Result += "\tSEL _cmd;\n";
515 Result += "\tchar *method_types;\n";
516 Result += "\tvoid *_imp;\n";
517 Result += "};\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000518
519 /* struct _objc_method_list {
520 struct _objc_method_list *next_method;
521 int method_count;
522 struct _objc_method method_list[];
523 }
524 */
525 Result += "\nstruct _objc_method_list {\n";
526 Result += "\tstruct _objc_method_list *next_method;\n";
527 Result += "\tint method_count;\n";
528 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000529 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000530 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000531 // Build _objc_method_list for class's methods if needed
532 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000533 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattner158ecb92007-10-25 17:07:24 +0000534 Result += prefix;
535 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
536 Result += "_METHODS_";
537 Result += ClassName;
538 Result += " __attribute__ ((section (\"__OBJC, __";
539 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000540 Result += "_meth\")))= ";
541 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
542
543 Result += "\t,{{(SEL)\"";
544 Result += Methods[0]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000545 std::string MethodTypeString;
546 Context->getObjcEncodingForMethodDecl(Methods[0], MethodTypeString);
547 Result += "\", \"";
548 Result += MethodTypeString;
549 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000550 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000551 // TODO: Need method address as 3rd initializer.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000552 Result += "\t ,{(SEL)\"";
553 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000554 std::string MethodTypeString;
555 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
556 Result += "\", \"";
557 Result += MethodTypeString;
558 Result += "\", 0}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000559 }
560 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000561 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000562}
563
564/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
565void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
566 int NumProtocols,
567 const char *prefix,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000568 const char *ClassName,
569 std::string &Result) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000570 static bool objc_protocol_methods = false;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000571 if (NumProtocols > 0) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000572 for (int i = 0; i < NumProtocols; i++) {
573 ObjcProtocolDecl *PDecl = Protocols[i];
574 // Output struct protocol_methods holder of method selector and type.
575 if (!objc_protocol_methods &&
576 (PDecl->getNumInstanceMethods() > 0
577 || PDecl->getNumClassMethods() > 0)) {
578 /* struct protocol_methods {
579 SEL _cmd;
580 char *method_types;
581 }
582 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000583 Result += "\nstruct protocol_methods {\n";
584 Result += "\tSEL _cmd;\n";
585 Result += "\tchar *method_types;\n";
586 Result += "};\n";
587
588 /* struct _objc_protocol_method_list {
589 int protocol_method_count;
590 struct protocol_methods protocols[];
591 }
592 */
593 Result += "\nstruct _objc_protocol_method_list {\n";
594 Result += "\tint protocol_method_count;\n";
595 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000596 objc_protocol_methods = true;
597 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000598
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000599 // Output instance methods declared in this protocol.
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000600 int NumMethods = PDecl->getNumInstanceMethods();
601 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000602 Result += "\nstatic struct _objc_protocol_method_list "
603 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
604 Result += PDecl->getName();
605 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
606 "{\n\t" + utostr(NumMethods) + "\n";
607
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000608 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000609 Result += "\t,{{(SEL)\"";
610 Result += Methods[0]->getSelector().getName().c_str();
611 Result += "\", \"\"}\n";
612
613 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000614 Result += "\t ,{(SEL)\"";
615 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000616 std::string MethodTypeString;
617 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
618 Result += "\", \"";
619 Result += MethodTypeString;
620 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000621 }
622 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000623 }
624
625 // Output class methods declared in this protocol.
626 NumMethods = PDecl->getNumClassMethods();
627 if (NumMethods > 0) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000628 Result += "\nstatic struct _objc_protocol_method_list "
629 "_OBJC_PROTOCOL_CLASS_METHODS_";
630 Result += PDecl->getName();
631 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
632 "{\n\t";
633 Result += utostr(NumMethods);
634 Result += "\n";
635
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000636 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000637 Result += "\t,{{(SEL)\"";
638 Result += Methods[0]->getSelector().getName().c_str();
639 Result += "\", \"\"}\n";
640
641 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000642 Result += "\t ,{(SEL)\"";
643 Result += Methods[i]->getSelector().getName().c_str();
Fariborz Jahanian33e1d642007-10-29 22:57:28 +0000644 std::string MethodTypeString;
645 Context->getObjcEncodingForMethodDecl(Methods[i], MethodTypeString);
646 Result += "\", \"";
647 Result += MethodTypeString;
648 Result += "\"}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000649 }
650 Result += "\t }\n};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000651 }
652 // Output:
653 /* struct _objc_protocol {
654 // Objective-C 1.0 extensions
655 struct _objc_protocol_extension *isa;
656 char *protocol_name;
657 struct _objc_protocol **protocol_list;
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000658 struct _objc_protocol_method_list *instance_methods;
659 struct _objc_protocol_method_list *class_methods;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000660 };
661 */
662 static bool objc_protocol = false;
663 if (!objc_protocol) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000664 Result += "\nstruct _objc_protocol {\n";
665 Result += "\tstruct _objc_protocol_extension *isa;\n";
666 Result += "\tchar *protocol_name;\n";
667 Result += "\tstruct _objc_protocol **protocol_list;\n";
668 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
669 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
670 Result += "};\n";
671
672 /* struct _objc_protocol_list {
673 struct _objc_protocol_list *next;
674 int protocol_count;
675 struct _objc_protocol *class_protocols[];
676 }
677 */
678 Result += "\nstruct _objc_protocol_list {\n";
679 Result += "\tstruct _objc_protocol_list *next;\n";
680 Result += "\tint protocol_count;\n";
681 Result += "\tstruct _objc_protocol *class_protocols[];\n";
682 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000683 objc_protocol = true;
684 }
685
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000686 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
687 Result += PDecl->getName();
688 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
689 "{\n\t0, \"";
690 Result += PDecl->getName();
691 Result += "\", 0, ";
692 if (PDecl->getInstanceMethods() > 0) {
693 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
694 Result += PDecl->getName();
695 Result += ", ";
696 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000697 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000698 Result += "0, ";
699 if (PDecl->getClassMethods() > 0) {
700 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
701 Result += PDecl->getName();
702 Result += "\n";
703 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000704 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000705 Result += "0\n";
706 Result += "};\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000707 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000708 // Output the top lovel protocol meta-data for the class.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000709 Result += "\nstatic struct _objc_protocol_list _OBJC_";
710 Result += prefix;
711 Result += "_PROTOCOLS_";
712 Result += ClassName;
713 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
714 "{\n\t0, ";
715 Result += utostr(NumProtocols);
716 Result += "\n";
717
718 Result += "\t,{&_OBJC_PROTOCOL_";
719 Result += Protocols[0]->getName();
720 Result += " \n";
721
722 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000723 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000724 Result += "\t ,&_OBJC_PROTOCOL_";
725 Result += PDecl->getName();
726 Result += "\n";
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000727 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000728 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000729 }
730}
731
732/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
733/// implementation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000734void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
735 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000736 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
737 // Find category declaration for this implementation.
738 ObjcCategoryDecl *CDecl;
739 for (CDecl = ClassDecl->getCategoryList(); CDecl;
740 CDecl = CDecl->getNextClassCategory())
741 if (CDecl->getIdentifier() == IDecl->getIdentifier())
742 break;
743 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
744
745 char *FullCategoryName = (char*)alloca(
746 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
747 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
748
749 // Build _objc_method_list for class's instance methods if needed
750 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
751 IDecl->getNumInstanceMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000752 true,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000753 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000754
755 // Build _objc_method_list for class's class methods if needed
756 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
757 IDecl->getNumClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000758 false,
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000759 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000760
761 // Protocols referenced in class declaration?
762 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
763 CDecl->getNumReferencedProtocols(),
764 "CATEGORY",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000765 FullCategoryName, Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000766
767 /* struct _objc_category {
768 char *category_name;
769 char *class_name;
770 struct _objc_method_list *instance_methods;
771 struct _objc_method_list *class_methods;
772 struct _objc_protocol_list *protocols;
773 // Objective-C 1.0 extensions
774 uint32_t size; // sizeof (struct _objc_category)
775 struct _objc_property_list *instance_properties; // category's own
776 // @property decl.
777 };
778 */
779
780 static bool objc_category = false;
781 if (!objc_category) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000782 Result += "\nstruct _objc_category {\n";
783 Result += "\tchar *category_name;\n";
784 Result += "\tchar *class_name;\n";
785 Result += "\tstruct _objc_method_list *instance_methods;\n";
786 Result += "\tstruct _objc_method_list *class_methods;\n";
787 Result += "\tstruct _objc_protocol_list *protocols;\n";
788 Result += "\tunsigned int size;\n";
789 Result += "\tstruct _objc_property_list *instance_properties;\n";
790 Result += "};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000791 objc_category = true;
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000792 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000793 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
794 Result += FullCategoryName;
795 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
796 Result += IDecl->getName();
797 Result += "\"\n\t, \"";
798 Result += ClassDecl->getName();
799 Result += "\"\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000800
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000801 if (IDecl->getNumInstanceMethods() > 0) {
802 Result += "\t, (struct _objc_method_list *)"
803 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
804 Result += FullCategoryName;
805 Result += "\n";
806 }
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000807 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000808 Result += "\t, 0\n";
809 if (IDecl->getNumClassMethods() > 0) {
810 Result += "\t, (struct _objc_method_list *)"
811 "&_OBJC_CATEGORY_CLASS_METHODS_";
812 Result += FullCategoryName;
813 Result += "\n";
814 }
815 else
816 Result += "\t, 0\n";
817
818 if (CDecl->getNumReferencedProtocols() > 0) {
819 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
820 Result += FullCategoryName;
821 Result += "\n";
822 }
823 else
824 Result += "\t, 0\n";
825 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000826}
827
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000828/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
829/// ivar offset.
830void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
831 ObjcIvarDecl *ivar,
832 std::string &Result) {
833 Result += "offsetof(struct _interface_";
834 Result += IDecl->getName();
835 Result += ", ";
836 Result += ivar->getName();
837 Result += ")";
838}
839
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000840//===----------------------------------------------------------------------===//
841// Meta Data Emission
842//===----------------------------------------------------------------------===//
843
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000844void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
845 std::string &Result) {
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000846 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
847
848 // Build _objc_ivar_list metadata for classes ivars if needed
849 int NumIvars = IDecl->getImplDeclNumIvars() > 0
850 ? IDecl->getImplDeclNumIvars()
851 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
852
Fariborz Jahanian4d733d32007-10-26 23:09:28 +0000853 SynthesizeObjcInternalStruct(CDecl, Result);
854
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000855 if (NumIvars > 0) {
856 static bool objc_ivar = false;
857 if (!objc_ivar) {
858 /* struct _objc_ivar {
859 char *ivar_name;
860 char *ivar_type;
861 int ivar_offset;
862 };
863 */
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000864 Result += "\nstruct _objc_ivar {\n";
865 Result += "\tchar *ivar_name;\n";
866 Result += "\tchar *ivar_type;\n";
867 Result += "\tint ivar_offset;\n";
868 Result += "};\n";
869
870 /* struct _objc_ivar_list {
871 int ivar_count;
872 struct _objc_ivar ivar_list[];
873 };
874 */
875 Result += "\nstruct _objc_ivar_list {\n";
876 Result += "\tint ivar_count;\n";
877 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000878 objc_ivar = true;
879 }
880
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000881 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
882 Result += IDecl->getName();
883 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
884 "{\n\t";
885 Result += utostr(NumIvars);
886 Result += "\n";
887
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000888 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
889 ? IDecl->getImplDeclIVars()
890 : CDecl->getIntfDeclIvars();
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000891 Result += "\t,{{\"";
892 Result += Ivars[0]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +0000893 Result += "\", \"";
894 std::string StrEncoding;
895 Context->getObjcEncodingForType(Ivars[0]->getType(), StrEncoding);
896 Result += StrEncoding;
897 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000898 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
899 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000900 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000901 Result += "\t ,{\"";
902 Result += Ivars[i]->getName();
Fariborz Jahanian160eb652007-10-29 17:16:25 +0000903 Result += "\", \"";
904 std::string StrEncoding;
905 Context->getObjcEncodingForType(Ivars[i]->getType(), StrEncoding);
906 Result += StrEncoding;
907 Result += "\", ";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +0000908 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
909 Result += "}\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000910 }
911
912 Result += "\t }\n};\n";
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000913 }
914
915 // Build _objc_method_list for class's instance methods if needed
916 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
917 IDecl->getNumInstanceMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000918 true,
919 "", IDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000920
921 // Build _objc_method_list for class's class methods if needed
922 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahanian8e991ba2007-10-25 00:14:44 +0000923 IDecl->getNumClassMethods(),
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000924 false,
925 "", IDecl->getName(), Result);
926
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000927 // Protocols referenced in class declaration?
928 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
929 CDecl->getNumIntfRefProtocols(),
930 "CLASS",
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000931 CDecl->getName(), Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +0000932
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000933
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000934 // Declaration of class/meta-class metadata
935 /* struct _objc_class {
936 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000937 const char *super_class_name;
938 char *name;
939 long version;
940 long info;
941 long instance_size;
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000942 struct _objc_ivar_list *ivars;
943 struct _objc_method_list *methods;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000944 struct objc_cache *cache;
945 struct objc_protocol_list *protocols;
946 const char *ivar_layout;
947 struct _objc_class_ext *ext;
948 };
949 */
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000950 static bool objc_class = false;
951 if (!objc_class) {
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000952 Result += "\nstruct _objc_class {\n";
953 Result += "\tstruct _objc_class *isa;\n";
954 Result += "\tconst char *super_class_name;\n";
955 Result += "\tchar *name;\n";
956 Result += "\tlong version;\n";
957 Result += "\tlong info;\n";
958 Result += "\tlong instance_size;\n";
959 Result += "\tstruct _objc_ivar_list *ivars;\n";
960 Result += "\tstruct _objc_method_list *methods;\n";
961 Result += "\tstruct objc_cache *cache;\n";
962 Result += "\tstruct _objc_protocol_list *protocols;\n";
963 Result += "\tconst char *ivar_layout;\n";
964 Result += "\tstruct _objc_class_ext *ext;\n";
965 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +0000966 objc_class = true;
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000967 }
968
969 // Meta-class metadata generation.
970 ObjcInterfaceDecl *RootClass = 0;
971 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
972 while (SuperClass) {
973 RootClass = SuperClass;
974 SuperClass = SuperClass->getSuperClass();
975 }
976 SuperClass = CDecl->getSuperClass();
977
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000978 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
979 Result += CDecl->getName();
980 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
981 "{\n\t(struct _objc_class *)\"";
982 Result += (RootClass ? RootClass->getName() : CDecl->getName());
983 Result += "\"";
984
985 if (SuperClass) {
986 Result += ", \"";
987 Result += SuperClass->getName();
988 Result += "\", \"";
989 Result += CDecl->getName();
990 Result += "\"";
991 }
992 else {
993 Result += ", 0, \"";
994 Result += CDecl->getName();
995 Result += "\"";
996 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +0000997 // TODO: 'ivars' field for root class is currently set to 0.
998 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahanianccd87b02007-10-25 20:55:25 +0000999 Result += ", 0,2, sizeof(struct _objc_class), 0";
1000 if (CDecl->getNumClassMethods() > 0) {
1001 Result += "\n\t, &_OBJC_CLASS_METHODS_";
1002 Result += CDecl->getName();
1003 Result += "\n";
1004 }
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001005 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001006 Result += ", 0\n";
1007 if (CDecl->getNumIntfRefProtocols() > 0) {
1008 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
1009 Result += CDecl->getName();
1010 Result += ",0,0\n";
1011 }
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001012 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001013 Result += "\t,0,0,0,0\n";
1014 Result += "};\n";
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001015
1016 // class metadata generation.
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001017 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
1018 Result += CDecl->getName();
1019 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
1020 "{\n\t&_OBJC_METACLASS_";
1021 Result += CDecl->getName();
1022 if (SuperClass) {
1023 Result += ", \"";
1024 Result += SuperClass->getName();
1025 Result += "\", \"";
1026 Result += CDecl->getName();
1027 Result += "\"";
1028 }
1029 else {
1030 Result += ", 0, \"";
1031 Result += CDecl->getName();
1032 Result += "\"";
1033 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001034 // 'info' field is initialized to CLS_CLASS(1) for class
Fariborz Jahanian4d733d32007-10-26 23:09:28 +00001035 Result += ", 0,1";
1036 if (!ObjcSynthesizedStructs.count(CDecl))
1037 Result += ",0";
1038 else {
1039 // class has size. Must synthesize its size.
1040 Result += ",sizeof(struct _interface_";
1041 Result += CDecl->getName();
1042 Result += ")";
1043 }
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001044 if (NumIvars > 0) {
1045 Result += ", &_OBJC_INSTANCE_VARIABLES_";
1046 Result += CDecl->getName();
1047 Result += "\n\t";
1048 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001049 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001050 Result += ",0";
1051 if (IDecl->getNumInstanceMethods() > 0) {
1052 Result += ", &_OBJC_INSTANCE_METHODS_";
1053 Result += CDecl->getName();
1054 Result += ", 0\n\t";
1055 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001056 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001057 Result += ",0,0";
1058 if (CDecl->getNumIntfRefProtocols() > 0) {
1059 Result += ", &_OBJC_CLASS_PROTOCOLS_";
1060 Result += CDecl->getName();
1061 Result += ", 0,0\n";
1062 }
Fariborz Jahaniandeef5182007-10-23 18:53:48 +00001063 else
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001064 Result += ",0,0,0\n";
1065 Result += "};\n";
Fariborz Jahanian9f0a1cb2007-10-23 00:02:02 +00001066}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001067
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001068void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001069 int ClsDefCount = ClassImplementation.size();
1070 int CatDefCount = CategoryImplementation.size();
1071 if (ClsDefCount == 0 && CatDefCount == 0)
1072 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001073
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001074 // TODO: This is temporary until we decide how to access objc types in a
1075 // c program
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001076 Result += "#include <Objc/objc.h>\n";
1077 // This is needed for use of offsetof
1078 Result += "#include <stddef.h>\n";
Fariborz Jahanian454cb012007-10-24 20:54:23 +00001079
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001080 // For each implemented class, write out all its meta data.
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001081 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001082 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian2e6d9352007-10-24 19:23:36 +00001083
1084 // For each implemented category, write out all its meta data.
1085 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001086 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +00001087
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001088 // Write objc_symtab metadata
1089 /*
1090 struct _objc_symtab
1091 {
1092 long sel_ref_cnt;
1093 SEL *refs;
1094 short cls_def_cnt;
1095 short cat_def_cnt;
1096 void *defs[cls_def_cnt + cat_def_cnt];
1097 };
1098 */
1099
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001100 Result += "\nstruct _objc_symtab {\n";
1101 Result += "\tlong sel_ref_cnt;\n";
1102 Result += "\tSEL *refs;\n";
1103 Result += "\tshort cls_def_cnt;\n";
1104 Result += "\tshort cat_def_cnt;\n";
1105 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
1106 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001107
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001108 Result += "static struct _objc_symtab "
1109 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
1110 Result += "\t0, 0, " + utostr(ClsDefCount)
1111 + ", " + utostr(CatDefCount) + "\n";
1112 for (int i = 0; i < ClsDefCount; i++) {
1113 Result += "\t,&_OBJC_CLASS_";
1114 Result += ClassImplementation[i]->getName();
1115 Result += "\n";
1116 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001117
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001118 for (int i = 0; i < CatDefCount; i++) {
1119 Result += "\t,&_OBJC_CATEGORY_";
1120 Result += CategoryImplementation[i]->getClassInterface()->getName();
1121 Result += "_";
1122 Result += CategoryImplementation[i]->getName();
1123 Result += "\n";
1124 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001125
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001126 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001127
1128 // Write objc_module metadata
1129
1130 /*
1131 struct _objc_module {
1132 long version;
1133 long size;
1134 const char *name;
1135 struct _objc_symtab *symtab;
1136 }
1137 */
1138
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001139 Result += "\nstruct _objc_module {\n";
1140 Result += "\tlong version;\n";
1141 Result += "\tlong size;\n";
1142 Result += "\tconst char *name;\n";
1143 Result += "\tstruct _objc_symtab *symtab;\n";
1144 Result += "};\n\n";
1145 Result += "static struct _objc_module "
1146 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanian26e4cd32007-10-26 19:46:17 +00001147 Result += "\t" + utostr(OBJC_ABI_VERSION) +
1148 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahanianccd87b02007-10-25 20:55:25 +00001149 Result += "};\n\n";
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +00001150}
Chris Lattner311ff022007-10-16 22:36:42 +00001151