blob: 6ccc23ae096fc04c53440a25300261135fb10c98 [file] [log] [blame]
Chris Lattnerb429ae42007-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 Lattner569faa62007-10-11 18:38:32 +000015#include "clang/Rewrite/Rewriter.h"
Chris Lattnerb429ae42007-10-11 00:43:27 +000016#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
Chris Lattner569faa62007-10-11 18:38:32 +000018#include "clang/Basic/SourceManager.h"
Steve Naroffe9780582007-10-23 23:50:29 +000019#include "clang/Basic/IdentifierTable.h"
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000020#include "llvm/ADT/StringExtras.h"
Fariborz Jahanianf185aef2007-10-26 19:46:17 +000021#include "llvm/ADT/SmallPtrSet.h"
Chris Lattnerb429ae42007-10-11 00:43:27 +000022using namespace clang;
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000023using llvm::utostr;
Chris Lattnerb429ae42007-10-11 00:43:27 +000024
Chris Lattnerb429ae42007-10-11 00:43:27 +000025namespace {
Chris Lattner569faa62007-10-11 18:38:32 +000026 class RewriteTest : public ASTConsumer {
Chris Lattner74db1682007-10-16 21:07:07 +000027 Rewriter Rewrite;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000028 ASTContext *Context;
Chris Lattnerb429ae42007-10-11 00:43:27 +000029 SourceManager *SM;
Chris Lattner569faa62007-10-11 18:38:32 +000030 unsigned MainFileID;
Chris Lattner74db1682007-10-16 21:07:07 +000031 SourceLocation LastIncLoc;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000032 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
33 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Fariborz Jahanianf185aef2007-10-26 19:46:17 +000034 llvm::SmallPtrSet<ObjcInterfaceDecl*, 8> ObjcSynthesizedStructs;
Steve Naroffe9780582007-10-23 23:50:29 +000035
36 FunctionDecl *MsgSendFunctionDecl;
37 FunctionDecl *GetClassFunctionDecl;
Steve Naroff71226032007-10-24 22:48:43 +000038 FunctionDecl *SelGetUidFunctionDecl;
Steve Naroffe9780582007-10-23 23:50:29 +000039
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000040 static const int OBJC_ABI_VERSION =7 ;
Chris Lattnerb429ae42007-10-11 00:43:27 +000041 public:
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000042 void Initialize(ASTContext &context, unsigned mainFileID) {
43 Context = &context;
44 SM = &Context->SourceMgr;
Chris Lattner569faa62007-10-11 18:38:32 +000045 MainFileID = mainFileID;
Steve Naroffe9780582007-10-23 23:50:29 +000046 MsgSendFunctionDecl = 0;
Steve Naroff95b28c12007-10-24 01:09:48 +000047 GetClassFunctionDecl = 0;
Steve Naroff71226032007-10-24 22:48:43 +000048 SelGetUidFunctionDecl = 0;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000049 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattnerb429ae42007-10-11 00:43:27 +000050 }
Chris Lattner569faa62007-10-11 18:38:32 +000051
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000052 // Top Level Driver code.
53 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner74db1682007-10-16 21:07:07 +000054 void HandleDeclInMainFile(Decl *D);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000055 ~RewriteTest();
56
57 // Syntactic Rewriting.
Chris Lattner74db1682007-10-16 21:07:07 +000058 void RewriteInclude(SourceLocation Loc);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000059 void RewriteTabs();
60 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Steve Naroff3774dd92007-10-26 20:53:56 +000061 void RewriteInterfaceDecl(ObjcInterfaceDecl *Dcl);
Chris Lattner6fe8b272007-10-16 22:36:42 +000062
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000063 // Expression Rewriting.
Chris Lattner0021f452007-10-24 16:57:36 +000064 Stmt *RewriteFunctionBody(Stmt *S);
65 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
66 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff71226032007-10-24 22:48:43 +000067 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
68 Expr **args, unsigned nargs);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000069 // Metadata emission.
Fariborz Jahanianf185aef2007-10-26 19:46:17 +000070 void HandleObjcMetaDataEmission();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000071 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
72 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000073
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000074 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
75 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000076
77 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
78 int NumMethods,
Fariborz Jahaniana3986372007-10-25 00:14:44 +000079 bool IsInstanceMethod,
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000080 const char *prefix,
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000081 const char *ClassName,
82 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000083
84 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
85 int NumProtocols,
86 const char *prefix,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000087 const char *ClassName,
88 std::string &Result);
Fariborz Jahanianf185aef2007-10-26 19:46:17 +000089 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
90 std::string &Result);
91 void RewriteObjcInternalStructs(ObjcImplementationDecl *IDecl,
92 std::string &Result);
93 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
94 ObjcIvarDecl *ivar,
95 std::string &Result);
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000096 void WriteObjcMetaData(std::string &Result);
Chris Lattnerb429ae42007-10-11 00:43:27 +000097 };
98}
99
Chris Lattner569faa62007-10-11 18:38:32 +0000100ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattnerb429ae42007-10-11 00:43:27 +0000101
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000102//===----------------------------------------------------------------------===//
103// Top Level Driver Code
104//===----------------------------------------------------------------------===//
105
Chris Lattner569faa62007-10-11 18:38:32 +0000106void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner74db1682007-10-16 21:07:07 +0000107 // Two cases: either the decl could be in the main file, or it could be in a
108 // #included file. If the former, rewrite it now. If the later, check to see
109 // if we rewrote the #include/#import.
110 SourceLocation Loc = D->getLocation();
111 Loc = SM->getLogicalLoc(Loc);
112
113 // If this is for a builtin, ignore it.
114 if (Loc.isInvalid()) return;
115
Steve Naroffe9780582007-10-23 23:50:29 +0000116 // Look for built-in declarations that we need to refer during the rewrite.
117 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff95b28c12007-10-24 01:09:48 +0000118 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffe9780582007-10-23 23:50:29 +0000119 MsgSendFunctionDecl = FD;
Steve Naroff95b28c12007-10-24 01:09:48 +0000120 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffe9780582007-10-23 23:50:29 +0000121 GetClassFunctionDecl = FD;
Steve Naroff71226032007-10-24 22:48:43 +0000122 else if (strcmp(FD->getName(), "sel_getUid") == 0)
123 SelGetUidFunctionDecl = FD;
Steve Naroff3774dd92007-10-26 20:53:56 +0000124 } else if (ObjcInterfaceDecl *MD = dyn_cast<ObjcInterfaceDecl>(D)) {
125 RewriteInterfaceDecl(MD);
Steve Naroffe9780582007-10-23 23:50:29 +0000126 }
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000127 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner74db1682007-10-16 21:07:07 +0000128 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
129 return HandleDeclInMainFile(D);
130
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000131 // Otherwise, see if there is a #import in the main file that should be
132 // rewritten.
Chris Lattner74db1682007-10-16 21:07:07 +0000133 RewriteInclude(Loc);
134}
135
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000136/// HandleDeclInMainFile - This is called for each top-level decl defined in the
137/// main file of the input.
138void RewriteTest::HandleDeclInMainFile(Decl *D) {
139 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
140 if (Stmt *Body = FD->getBody())
141 FD->setBody(RewriteFunctionBody(Body));
142
143 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
144 ClassImplementation.push_back(CI);
145 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
146 CategoryImplementation.push_back(CI);
147 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
148 RewriteForwardClassDecl(CD);
149 // Nothing yet.
150}
151
152RewriteTest::~RewriteTest() {
153 // Get the top-level buffer that this corresponds to.
154 RewriteTabs();
155
156 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
157 // we are done.
158 if (const RewriteBuffer *RewriteBuf =
159 Rewrite.getRewriteBufferFor(MainFileID)) {
160 printf("Changed:\n");
161 std::string S(RewriteBuf->begin(), RewriteBuf->end());
162 printf("%s\n", S.c_str());
163 } else {
164 printf("No changes\n");
165 }
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000166
167}
168
169/// HandleObjcMetaDataEmission - main routine to generate objective-c's
170/// metadata.
171void RewriteTest::HandleObjcMetaDataEmission() {
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000172 // Rewrite Objective-c meta data*
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000173 std::string ResultStr;
174 WriteObjcMetaData(ResultStr);
175 // For now just print the string out.
176 printf("%s", ResultStr.c_str());
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000177}
178
179//===----------------------------------------------------------------------===//
180// Syntactic (non-AST) Rewriting Code
181//===----------------------------------------------------------------------===//
182
Chris Lattner74db1682007-10-16 21:07:07 +0000183void RewriteTest::RewriteInclude(SourceLocation Loc) {
184 // Rip up the #include stack to the main file.
185 SourceLocation IncLoc = Loc, NextLoc = Loc;
186 do {
187 IncLoc = Loc;
188 Loc = SM->getLogicalLoc(NextLoc);
189 NextLoc = SM->getIncludeLoc(Loc);
190 } while (!NextLoc.isInvalid());
191
192 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
193 // IncLoc indicates the header that was included if it is useful.
194 IncLoc = SM->getLogicalLoc(IncLoc);
195 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
196 Loc == LastIncLoc)
197 return;
198 LastIncLoc = Loc;
199
200 unsigned IncCol = SM->getColumnNumber(Loc);
201 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
202
203 // Replace the #import with #include.
204 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
205}
206
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000207void RewriteTest::RewriteTabs() {
208 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
209 const char *MainBufStart = MainBuf.first;
210 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000211
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000212 // Loop over the whole file, looking for tabs.
213 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
214 if (*BufPtr != '\t')
215 continue;
216
217 // Okay, we found a tab. This tab will turn into at least one character,
218 // but it depends on which 'virtual column' it is in. Compute that now.
219 unsigned VCol = 0;
220 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
221 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
222 ++VCol;
223
224 // Okay, now that we know the virtual column, we know how many spaces to
225 // insert. We assume 8-character tab-stops.
226 unsigned Spaces = 8-(VCol & 7);
227
228 // Get the location of the tab.
229 SourceLocation TabLoc =
230 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
231
232 // Rewrite the single tab character into a sequence of spaces.
233 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
234 }
Chris Lattner569faa62007-10-11 18:38:32 +0000235}
236
237
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000238void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
239 int numDecls = ClassDecl->getNumForwardDecls();
240 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
241
242 // Get the start location and compute the semi location.
243 SourceLocation startLoc = ClassDecl->getLocation();
244 const char *startBuf = SM->getCharacterData(startLoc);
245 const char *semiPtr = strchr(startBuf, ';');
246
247 // Translate to typedef's that forward reference structs with the same name
248 // as the class. As a convenience, we include the original declaration
249 // as a comment.
250 std::string typedefString;
251 typedefString += "// ";
Steve Naroff71226032007-10-24 22:48:43 +0000252 typedefString.append(startBuf, semiPtr-startBuf+1);
253 typedefString += "\n";
254 for (int i = 0; i < numDecls; i++) {
255 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
256 typedefString += "typedef struct ";
257 typedefString += ForwardDecl->getName();
258 typedefString += " ";
259 typedefString += ForwardDecl->getName();
260 typedefString += ";\n";
261 }
262
263 // Replace the @class with typedefs corresponding to the classes.
264 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
265 typedefString.c_str(), typedefString.size());
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000266}
267
Steve Naroff3774dd92007-10-26 20:53:56 +0000268void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) {
269 int nInstanceMethods = ClassDecl->getNumInstanceMethods();
270 ObjcMethodDecl **instanceMethods = ClassDecl->getInstanceMethods();
271
272 for (int i = 0; i < nInstanceMethods; i++) {
273 ObjcMethodDecl *instanceMethod = instanceMethods[i];
274 SourceLocation Loc = instanceMethod->getLocStart();
275
276 Rewrite.ReplaceText(Loc, 0, "// ", 3);
277
278 // FIXME: handle methods that are declared across multiple lines.
279 }
280 int nClassMethods = ClassDecl->getNumClassMethods();
281 ObjcMethodDecl **classMethods = ClassDecl->getClassMethods();
282
283 for (int i = 0; i < nClassMethods; i++) {
284 ObjcMethodDecl *classMethod = classMethods[i];
285 SourceLocation Loc = classMethod->getLocStart();
286
287 Rewrite.ReplaceText(Loc, 0, "// ", 3);
288
289 // FIXME: handle methods that are declared across multiple lines.
290 }
291}
292
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000293//===----------------------------------------------------------------------===//
294// Function Body / Expression rewriting
295//===----------------------------------------------------------------------===//
296
Chris Lattner0021f452007-10-24 16:57:36 +0000297Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner6fe8b272007-10-16 22:36:42 +0000298 // Otherwise, just rewrite all children.
299 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
300 CI != E; ++CI)
Chris Lattnere33506b2007-10-17 21:28:00 +0000301 if (*CI)
Chris Lattner0021f452007-10-24 16:57:36 +0000302 *CI = RewriteFunctionBody(*CI);
Steve Naroffe9780582007-10-23 23:50:29 +0000303
304 // Handle specific things.
305 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
306 return RewriteAtEncode(AtEncode);
307
Steve Naroff71226032007-10-24 22:48:43 +0000308 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
309 // Before we rewrite it, put the original message expression in a comment.
310 SourceLocation startLoc = MessExpr->getLocStart();
311 SourceLocation endLoc = MessExpr->getLocEnd();
312
313 const char *startBuf = SM->getCharacterData(startLoc);
314 const char *endBuf = SM->getCharacterData(endLoc);
315
316 std::string messString;
317 messString += "// ";
318 messString.append(startBuf, endBuf-startBuf+1);
319 messString += "\n";
Steve Naroff3774dd92007-10-26 20:53:56 +0000320
Steve Naroff71226032007-10-24 22:48:43 +0000321 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
322 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
323 // Tried this, but it didn't work either...
Steve Naroff3774dd92007-10-26 20:53:56 +0000324 Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffe9780582007-10-23 23:50:29 +0000325 return RewriteMessageExpr(MessExpr);
Steve Naroff71226032007-10-24 22:48:43 +0000326 }
Chris Lattner0021f452007-10-24 16:57:36 +0000327 // Return this stmt unmodified.
328 return S;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000329}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000330
Chris Lattner0021f452007-10-24 16:57:36 +0000331Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattnerbf0bfa62007-10-17 22:35:30 +0000332 // Create a new string expression.
333 QualType StrType = Context->getPointerType(Context->CharTy);
334 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
335 SourceLocation(), SourceLocation());
336 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattner0021f452007-10-24 16:57:36 +0000337 delete Exp;
338 return Replacement;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000339}
340
Steve Naroff71226032007-10-24 22:48:43 +0000341CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
342 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffe9780582007-10-23 23:50:29 +0000343 // Get the type, we will need to reference it in a couple spots.
Steve Naroff71226032007-10-24 22:48:43 +0000344 QualType msgSendType = FD->getType();
Steve Naroffe9780582007-10-23 23:50:29 +0000345
346 // Create a reference to the objc_msgSend() declaration.
Steve Naroff71226032007-10-24 22:48:43 +0000347 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffe9780582007-10-23 23:50:29 +0000348
349 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000350 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffe9780582007-10-23 23:50:29 +0000351 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
352
353 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattner0021f452007-10-24 16:57:36 +0000354
Steve Naroff71226032007-10-24 22:48:43 +0000355 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
356}
357
358Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
359 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
360 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
361 assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
362
363 // Synthesize a call to objc_msgSend().
364 llvm::SmallVector<Expr*, 8> MsgExprs;
365 IdentifierInfo *clsName = Exp->getClassName();
366
367 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
368 if (clsName) { // class message.
369 llvm::SmallVector<Expr*, 8> ClsExprs;
370 QualType argType = Context->getPointerType(Context->CharTy);
371 ClsExprs.push_back(new StringLiteral(clsName->getName(),
372 clsName->getLength(),
373 false, argType, SourceLocation(),
374 SourceLocation()));
375 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
376 &ClsExprs[0], ClsExprs.size());
377 MsgExprs.push_back(Cls);
378 } else // instance message.
379 MsgExprs.push_back(Exp->getReceiver());
380
381 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
382 llvm::SmallVector<Expr*, 8> SelExprs;
383 QualType argType = Context->getPointerType(Context->CharTy);
384 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
385 Exp->getSelector().getName().size(),
386 false, argType, SourceLocation(),
387 SourceLocation()));
388 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
389 &SelExprs[0], SelExprs.size());
390 MsgExprs.push_back(SelExp);
391
392 // Now push any user supplied arguments.
393 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
394 MsgExprs.push_back(Exp->getArg(i));
395 // We've transferred the ownership to MsgExprs. Null out the argument in
396 // the original expression, since we will delete it below.
397 Exp->setArg(i, 0);
398 }
399 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
400 &MsgExprs[0], MsgExprs.size());
401 // Now do the actual rewrite.
402 Rewrite.ReplaceStmt(Exp, MessExp);
403
Chris Lattner0021f452007-10-24 16:57:36 +0000404 delete Exp;
Steve Naroff71226032007-10-24 22:48:43 +0000405 return MessExp;
Steve Naroffe9780582007-10-23 23:50:29 +0000406}
407
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000408/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
409/// an objective-c class with ivars.
410void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
411 std::string &Result) {
412 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
413 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
414 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
415 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
416 // Do it for the root
417 SynthesizeObjcInternalStruct(RCDecl, Result);
418 }
419
420 int NumIvars = CDecl->getIntfDeclNumIvars();
421 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl)))
422 return;
423
424 Result += "\nstruct _interface_";
425 Result += CDecl->getName();
426 Result += " {\n";
427 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
428 Result += "\tstruct _interface_";
429 Result += RCDecl->getName();
430 Result += " _";
431 Result += RCDecl->getName();
432 Result += ";\n";
433 }
434
435 ObjcIvarDecl **Ivars = CDecl->getIntfDeclIvars();
436 for (int i = 0; i < NumIvars; i++) {
437 Result += "\t";
438 std::string Name = Ivars[i]->getName();
439 Ivars[i]->getType().getAsStringInternal(Name);
440 Result += Name;
441 Result += ";\n";
442 }
443 Result += "};\n";
444 // Mark this struct as having been generated.
445 if (!ObjcSynthesizedStructs.insert(CDecl))
446 assert(true && "struct already synthesize- SynthesizeObjcInternalStruct");
447}
448
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000449// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
450/// class methods.
451void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
452 int NumMethods,
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000453 bool IsInstanceMethod,
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000454 const char *prefix,
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000455 const char *ClassName,
456 std::string &Result) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000457 static bool objc_impl_method = false;
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000458 if (NumMethods > 0 && !objc_impl_method) {
459 /* struct _objc_method {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000460 SEL _cmd;
461 char *method_types;
462 void *_imp;
463 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000464 */
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000465 Result += "\nstruct _objc_method {\n";
466 Result += "\tSEL _cmd;\n";
467 Result += "\tchar *method_types;\n";
468 Result += "\tvoid *_imp;\n";
469 Result += "};\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000470
471 /* struct _objc_method_list {
472 struct _objc_method_list *next_method;
473 int method_count;
474 struct _objc_method method_list[];
475 }
476 */
477 Result += "\nstruct _objc_method_list {\n";
478 Result += "\tstruct _objc_method_list *next_method;\n";
479 Result += "\tint method_count;\n";
480 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000481 objc_impl_method = true;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000482 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000483 // Build _objc_method_list for class's methods if needed
484 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000485 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000486 Result += prefix;
487 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
488 Result += "_METHODS_";
489 Result += ClassName;
490 Result += " __attribute__ ((section (\"__OBJC, __";
491 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000492 Result += "_meth\")))= ";
493 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
494
495 Result += "\t,{{(SEL)\"";
496 Result += Methods[0]->getSelector().getName().c_str();
497 Result += "\", \"\", 0}\n";
498
499 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000500 // TODO: 1) method selector name may hav to go into their own section
501 // 2) encode method types for use here (which may have to go into
502 // __meth_var_types section, 3) Need method address as 3rd initializer.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000503 Result += "\t ,{(SEL)\"";
504 Result += Methods[i]->getSelector().getName().c_str();
505 Result += "\", \"\", 0}\n";
506 }
507 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000508 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000509}
510
511/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
512void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
513 int NumProtocols,
514 const char *prefix,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000515 const char *ClassName,
516 std::string &Result) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000517 static bool objc_protocol_methods = false;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000518 if (NumProtocols > 0) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000519 for (int i = 0; i < NumProtocols; i++) {
520 ObjcProtocolDecl *PDecl = Protocols[i];
521 // Output struct protocol_methods holder of method selector and type.
522 if (!objc_protocol_methods &&
523 (PDecl->getNumInstanceMethods() > 0
524 || PDecl->getNumClassMethods() > 0)) {
525 /* struct protocol_methods {
526 SEL _cmd;
527 char *method_types;
528 }
529 */
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000530 Result += "\nstruct protocol_methods {\n";
531 Result += "\tSEL _cmd;\n";
532 Result += "\tchar *method_types;\n";
533 Result += "};\n";
534
535 /* struct _objc_protocol_method_list {
536 int protocol_method_count;
537 struct protocol_methods protocols[];
538 }
539 */
540 Result += "\nstruct _objc_protocol_method_list {\n";
541 Result += "\tint protocol_method_count;\n";
542 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000543 objc_protocol_methods = true;
544 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000545
Fariborz Jahanian04455192007-10-22 21:41:37 +0000546 // Output instance methods declared in this protocol.
Fariborz Jahanian04455192007-10-22 21:41:37 +0000547 int NumMethods = PDecl->getNumInstanceMethods();
548 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000549 Result += "\nstatic struct _objc_protocol_method_list "
550 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
551 Result += PDecl->getName();
552 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
553 "{\n\t" + utostr(NumMethods) + "\n";
554
Fariborz Jahanian04455192007-10-22 21:41:37 +0000555 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000556 Result += "\t,{{(SEL)\"";
557 Result += Methods[0]->getSelector().getName().c_str();
558 Result += "\", \"\"}\n";
559
560 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000561 // TODO: 1) method selector name may hav to go into their own section
562 // 2) encode method types for use here (which may have to go into
563 // __meth_var_types section.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000564 Result += "\t ,{(SEL)\"";
565 Result += Methods[i]->getSelector().getName().c_str();
566 Result += "\", \"\"}\n";
567 }
568 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000569 }
570
571 // Output class methods declared in this protocol.
572 NumMethods = PDecl->getNumClassMethods();
573 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000574 Result += "\nstatic struct _objc_protocol_method_list "
575 "_OBJC_PROTOCOL_CLASS_METHODS_";
576 Result += PDecl->getName();
577 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
578 "{\n\t";
579 Result += utostr(NumMethods);
580 Result += "\n";
581
Fariborz Jahanian04455192007-10-22 21:41:37 +0000582 ObjcMethodDecl **Methods = PDecl->getClassMethods();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000583 Result += "\t,{{(SEL)\"";
584 Result += Methods[0]->getSelector().getName().c_str();
585 Result += "\", \"\"}\n";
586
587 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000588 // TODO: 1) method selector name may hav to go into their own section
589 // 2) encode method types for use here (which may have to go into
590 // __meth_var_types section.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000591 Result += "\t ,{(SEL)\"";
592 Result += Methods[i]->getSelector().getName().c_str();
593 Result += "\", \"\"}\n";
594 }
595 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000596 }
597 // Output:
598 /* struct _objc_protocol {
599 // Objective-C 1.0 extensions
600 struct _objc_protocol_extension *isa;
601 char *protocol_name;
602 struct _objc_protocol **protocol_list;
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000603 struct _objc_protocol_method_list *instance_methods;
604 struct _objc_protocol_method_list *class_methods;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000605 };
606 */
607 static bool objc_protocol = false;
608 if (!objc_protocol) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000609 Result += "\nstruct _objc_protocol {\n";
610 Result += "\tstruct _objc_protocol_extension *isa;\n";
611 Result += "\tchar *protocol_name;\n";
612 Result += "\tstruct _objc_protocol **protocol_list;\n";
613 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
614 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
615 Result += "};\n";
616
617 /* struct _objc_protocol_list {
618 struct _objc_protocol_list *next;
619 int protocol_count;
620 struct _objc_protocol *class_protocols[];
621 }
622 */
623 Result += "\nstruct _objc_protocol_list {\n";
624 Result += "\tstruct _objc_protocol_list *next;\n";
625 Result += "\tint protocol_count;\n";
626 Result += "\tstruct _objc_protocol *class_protocols[];\n";
627 Result += "};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000628 objc_protocol = true;
629 }
630
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000631 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
632 Result += PDecl->getName();
633 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
634 "{\n\t0, \"";
635 Result += PDecl->getName();
636 Result += "\", 0, ";
637 if (PDecl->getInstanceMethods() > 0) {
638 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
639 Result += PDecl->getName();
640 Result += ", ";
641 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000642 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000643 Result += "0, ";
644 if (PDecl->getClassMethods() > 0) {
645 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
646 Result += PDecl->getName();
647 Result += "\n";
648 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000649 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000650 Result += "0\n";
651 Result += "};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000652 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000653 // Output the top lovel protocol meta-data for the class.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000654 Result += "\nstatic struct _objc_protocol_list _OBJC_";
655 Result += prefix;
656 Result += "_PROTOCOLS_";
657 Result += ClassName;
658 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
659 "{\n\t0, ";
660 Result += utostr(NumProtocols);
661 Result += "\n";
662
663 Result += "\t,{&_OBJC_PROTOCOL_";
664 Result += Protocols[0]->getName();
665 Result += " \n";
666
667 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000668 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000669 Result += "\t ,&_OBJC_PROTOCOL_";
670 Result += PDecl->getName();
671 Result += "\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000672 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000673 Result += "\t }\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000674 }
675}
676
677/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
678/// implementation.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000679void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
680 std::string &Result) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000681 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
682 // Find category declaration for this implementation.
683 ObjcCategoryDecl *CDecl;
684 for (CDecl = ClassDecl->getCategoryList(); CDecl;
685 CDecl = CDecl->getNextClassCategory())
686 if (CDecl->getIdentifier() == IDecl->getIdentifier())
687 break;
688 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
689
690 char *FullCategoryName = (char*)alloca(
691 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
692 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
693
694 // Build _objc_method_list for class's instance methods if needed
695 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
696 IDecl->getNumInstanceMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000697 true,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000698 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000699
700 // Build _objc_method_list for class's class methods if needed
701 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
702 IDecl->getNumClassMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000703 false,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000704 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000705
706 // Protocols referenced in class declaration?
707 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
708 CDecl->getNumReferencedProtocols(),
709 "CATEGORY",
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000710 FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000711
712 /* struct _objc_category {
713 char *category_name;
714 char *class_name;
715 struct _objc_method_list *instance_methods;
716 struct _objc_method_list *class_methods;
717 struct _objc_protocol_list *protocols;
718 // Objective-C 1.0 extensions
719 uint32_t size; // sizeof (struct _objc_category)
720 struct _objc_property_list *instance_properties; // category's own
721 // @property decl.
722 };
723 */
724
725 static bool objc_category = false;
726 if (!objc_category) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000727 Result += "\nstruct _objc_category {\n";
728 Result += "\tchar *category_name;\n";
729 Result += "\tchar *class_name;\n";
730 Result += "\tstruct _objc_method_list *instance_methods;\n";
731 Result += "\tstruct _objc_method_list *class_methods;\n";
732 Result += "\tstruct _objc_protocol_list *protocols;\n";
733 Result += "\tunsigned int size;\n";
734 Result += "\tstruct _objc_property_list *instance_properties;\n";
735 Result += "};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000736 objc_category = true;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000737 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000738 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
739 Result += FullCategoryName;
740 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
741 Result += IDecl->getName();
742 Result += "\"\n\t, \"";
743 Result += ClassDecl->getName();
744 Result += "\"\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000745
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000746 if (IDecl->getNumInstanceMethods() > 0) {
747 Result += "\t, (struct _objc_method_list *)"
748 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
749 Result += FullCategoryName;
750 Result += "\n";
751 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000752 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000753 Result += "\t, 0\n";
754 if (IDecl->getNumClassMethods() > 0) {
755 Result += "\t, (struct _objc_method_list *)"
756 "&_OBJC_CATEGORY_CLASS_METHODS_";
757 Result += FullCategoryName;
758 Result += "\n";
759 }
760 else
761 Result += "\t, 0\n";
762
763 if (CDecl->getNumReferencedProtocols() > 0) {
764 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
765 Result += FullCategoryName;
766 Result += "\n";
767 }
768 else
769 Result += "\t, 0\n";
770 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000771}
772
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000773/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
774/// ivar offset.
775void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
776 ObjcIvarDecl *ivar,
777 std::string &Result) {
778 Result += "offsetof(struct _interface_";
779 Result += IDecl->getName();
780 Result += ", ";
781 Result += ivar->getName();
782 Result += ")";
783}
784
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000785//===----------------------------------------------------------------------===//
786// Meta Data Emission
787//===----------------------------------------------------------------------===//
788
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000789void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
790 std::string &Result) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000791 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
792
793 // Build _objc_ivar_list metadata for classes ivars if needed
794 int NumIvars = IDecl->getImplDeclNumIvars() > 0
795 ? IDecl->getImplDeclNumIvars()
796 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
797
798 if (NumIvars > 0) {
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000799 SynthesizeObjcInternalStruct(CDecl, Result);
800
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000801 static bool objc_ivar = false;
802 if (!objc_ivar) {
803 /* struct _objc_ivar {
804 char *ivar_name;
805 char *ivar_type;
806 int ivar_offset;
807 };
808 */
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000809 Result += "\nstruct _objc_ivar {\n";
810 Result += "\tchar *ivar_name;\n";
811 Result += "\tchar *ivar_type;\n";
812 Result += "\tint ivar_offset;\n";
813 Result += "};\n";
814
815 /* struct _objc_ivar_list {
816 int ivar_count;
817 struct _objc_ivar ivar_list[];
818 };
819 */
820 Result += "\nstruct _objc_ivar_list {\n";
821 Result += "\tint ivar_count;\n";
822 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000823 objc_ivar = true;
824 }
825
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000826 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
827 Result += IDecl->getName();
828 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
829 "{\n\t";
830 Result += utostr(NumIvars);
831 Result += "\n";
832
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000833 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
834 ? IDecl->getImplDeclIVars()
835 : CDecl->getIntfDeclIvars();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000836 Result += "\t,{{\"";
837 Result += Ivars[0]->getName();
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000838 Result += "\", \"\", ";
839 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
840 Result += "}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000841 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000842 // TODO: 1) ivar names may have to go to another section. 2) encode
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000843 // ivar_type type of each ivar .
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000844 Result += "\t ,{\"";
845 Result += Ivars[i]->getName();
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000846 Result += "\", \"\", ";
847 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
848 Result += "}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000849 }
850
851 Result += "\t }\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000852 }
853
854 // Build _objc_method_list for class's instance methods if needed
855 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
856 IDecl->getNumInstanceMethods(),
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000857 true,
858 "", IDecl->getName(), Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000859
860 // Build _objc_method_list for class's class methods if needed
861 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000862 IDecl->getNumClassMethods(),
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000863 false,
864 "", IDecl->getName(), Result);
865
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000866 // Protocols referenced in class declaration?
867 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
868 CDecl->getNumIntfRefProtocols(),
869 "CLASS",
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000870 CDecl->getName(), Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000871
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000872
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000873 // Declaration of class/meta-class metadata
874 /* struct _objc_class {
875 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000876 const char *super_class_name;
877 char *name;
878 long version;
879 long info;
880 long instance_size;
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000881 struct _objc_ivar_list *ivars;
882 struct _objc_method_list *methods;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000883 struct objc_cache *cache;
884 struct objc_protocol_list *protocols;
885 const char *ivar_layout;
886 struct _objc_class_ext *ext;
887 };
888 */
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000889 static bool objc_class = false;
890 if (!objc_class) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000891 Result += "\nstruct _objc_class {\n";
892 Result += "\tstruct _objc_class *isa;\n";
893 Result += "\tconst char *super_class_name;\n";
894 Result += "\tchar *name;\n";
895 Result += "\tlong version;\n";
896 Result += "\tlong info;\n";
897 Result += "\tlong instance_size;\n";
898 Result += "\tstruct _objc_ivar_list *ivars;\n";
899 Result += "\tstruct _objc_method_list *methods;\n";
900 Result += "\tstruct objc_cache *cache;\n";
901 Result += "\tstruct _objc_protocol_list *protocols;\n";
902 Result += "\tconst char *ivar_layout;\n";
903 Result += "\tstruct _objc_class_ext *ext;\n";
904 Result += "};\n";
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000905 objc_class = true;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000906 }
907
908 // Meta-class metadata generation.
909 ObjcInterfaceDecl *RootClass = 0;
910 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
911 while (SuperClass) {
912 RootClass = SuperClass;
913 SuperClass = SuperClass->getSuperClass();
914 }
915 SuperClass = CDecl->getSuperClass();
916
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000917 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
918 Result += CDecl->getName();
919 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
920 "{\n\t(struct _objc_class *)\"";
921 Result += (RootClass ? RootClass->getName() : CDecl->getName());
922 Result += "\"";
923
924 if (SuperClass) {
925 Result += ", \"";
926 Result += SuperClass->getName();
927 Result += "\", \"";
928 Result += CDecl->getName();
929 Result += "\"";
930 }
931 else {
932 Result += ", 0, \"";
933 Result += CDecl->getName();
934 Result += "\"";
935 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000936 // TODO: 'ivars' field for root class is currently set to 0.
937 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000938 Result += ", 0,2, sizeof(struct _objc_class), 0";
939 if (CDecl->getNumClassMethods() > 0) {
940 Result += "\n\t, &_OBJC_CLASS_METHODS_";
941 Result += CDecl->getName();
942 Result += "\n";
943 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000944 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000945 Result += ", 0\n";
946 if (CDecl->getNumIntfRefProtocols() > 0) {
947 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
948 Result += CDecl->getName();
949 Result += ",0,0\n";
950 }
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +0000951 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000952 Result += "\t,0,0,0,0\n";
953 Result += "};\n";
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000954
955 // class metadata generation.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000956 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
957 Result += CDecl->getName();
958 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
959 "{\n\t&_OBJC_METACLASS_";
960 Result += CDecl->getName();
961 if (SuperClass) {
962 Result += ", \"";
963 Result += SuperClass->getName();
964 Result += "\", \"";
965 Result += CDecl->getName();
966 Result += "\"";
967 }
968 else {
969 Result += ", 0, \"";
970 Result += CDecl->getName();
971 Result += "\"";
972 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000973 // 'info' field is initialized to CLS_CLASS(1) for class
974 // TODO: instance_size is curently set to 0.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000975 Result += ", 0,1,0";
976 if (NumIvars > 0) {
977 Result += ", &_OBJC_INSTANCE_VARIABLES_";
978 Result += CDecl->getName();
979 Result += "\n\t";
980 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000981 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000982 Result += ",0";
983 if (IDecl->getNumInstanceMethods() > 0) {
984 Result += ", &_OBJC_INSTANCE_METHODS_";
985 Result += CDecl->getName();
986 Result += ", 0\n\t";
987 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000988 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000989 Result += ",0,0";
990 if (CDecl->getNumIntfRefProtocols() > 0) {
991 Result += ", &_OBJC_CLASS_PROTOCOLS_";
992 Result += CDecl->getName();
993 Result += ", 0,0\n";
994 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000995 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000996 Result += ",0,0,0\n";
997 Result += "};\n";
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000998}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000999
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001000void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001001 int ClsDefCount = ClassImplementation.size();
1002 int CatDefCount = CategoryImplementation.size();
1003 if (ClsDefCount == 0 && CatDefCount == 0)
1004 return;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +00001005
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +00001006 // TODO: This is temporary until we decide how to access objc types in a
1007 // c program
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001008 Result += "#include <Objc/objc.h>\n";
1009 // This is needed for use of offsetof
1010 Result += "#include <stddef.h>\n";
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +00001011
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001012 // For each implemented class, write out all its meta data.
Fariborz Jahanian45d52f72007-10-18 22:09:03 +00001013 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001014 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +00001015
1016 // For each implemented category, write out all its meta data.
1017 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001018 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanian45d52f72007-10-18 22:09:03 +00001019
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001020 // Write objc_symtab metadata
1021 /*
1022 struct _objc_symtab
1023 {
1024 long sel_ref_cnt;
1025 SEL *refs;
1026 short cls_def_cnt;
1027 short cat_def_cnt;
1028 void *defs[cls_def_cnt + cat_def_cnt];
1029 };
1030 */
1031
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001032 Result += "\nstruct _objc_symtab {\n";
1033 Result += "\tlong sel_ref_cnt;\n";
1034 Result += "\tSEL *refs;\n";
1035 Result += "\tshort cls_def_cnt;\n";
1036 Result += "\tshort cat_def_cnt;\n";
1037 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
1038 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001039
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001040 Result += "static struct _objc_symtab "
1041 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
1042 Result += "\t0, 0, " + utostr(ClsDefCount)
1043 + ", " + utostr(CatDefCount) + "\n";
1044 for (int i = 0; i < ClsDefCount; i++) {
1045 Result += "\t,&_OBJC_CLASS_";
1046 Result += ClassImplementation[i]->getName();
1047 Result += "\n";
1048 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001049
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001050 for (int i = 0; i < CatDefCount; i++) {
1051 Result += "\t,&_OBJC_CATEGORY_";
1052 Result += CategoryImplementation[i]->getClassInterface()->getName();
1053 Result += "_";
1054 Result += CategoryImplementation[i]->getName();
1055 Result += "\n";
1056 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001057
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001058 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001059
1060 // Write objc_module metadata
1061
1062 /*
1063 struct _objc_module {
1064 long version;
1065 long size;
1066 const char *name;
1067 struct _objc_symtab *symtab;
1068 }
1069 */
1070
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001071 Result += "\nstruct _objc_module {\n";
1072 Result += "\tlong version;\n";
1073 Result += "\tlong size;\n";
1074 Result += "\tconst char *name;\n";
1075 Result += "\tstruct _objc_symtab *symtab;\n";
1076 Result += "};\n\n";
1077 Result += "static struct _objc_module "
1078 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001079 Result += "\t" + utostr(OBJC_ABI_VERSION) +
1080 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001081 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001082}
Chris Lattner6fe8b272007-10-16 22:36:42 +00001083