blob: 95b05ba0f47113d97072d23b029bd16c5ec5dd54 [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);
Chris Lattner6fe8b272007-10-16 22:36:42 +000061
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000062 // Expression Rewriting.
Chris Lattner0021f452007-10-24 16:57:36 +000063 Stmt *RewriteFunctionBody(Stmt *S);
64 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
65 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Steve Naroff71226032007-10-24 22:48:43 +000066 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
67 Expr **args, unsigned nargs);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000068 // Metadata emission.
Fariborz Jahanianf185aef2007-10-26 19:46:17 +000069 void HandleObjcMetaDataEmission();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000070 void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
71 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000072
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000073 void RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *CDecl,
74 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000075
76 void RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
77 int NumMethods,
Fariborz Jahaniana3986372007-10-25 00:14:44 +000078 bool IsInstanceMethod,
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000079 const char *prefix,
Chris Lattnerc3aa5c42007-10-25 17:07:24 +000080 const char *ClassName,
81 std::string &Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +000082
83 void RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
84 int NumProtocols,
85 const char *prefix,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000086 const char *ClassName,
87 std::string &Result);
Fariborz Jahanianf185aef2007-10-26 19:46:17 +000088 void SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
89 std::string &Result);
90 void RewriteObjcInternalStructs(ObjcImplementationDecl *IDecl,
91 std::string &Result);
92 void SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
93 ObjcIvarDecl *ivar,
94 std::string &Result);
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +000095 void WriteObjcMetaData(std::string &Result);
Chris Lattnerb429ae42007-10-11 00:43:27 +000096 };
97}
98
Chris Lattner569faa62007-10-11 18:38:32 +000099ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattnerb429ae42007-10-11 00:43:27 +0000100
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000101//===----------------------------------------------------------------------===//
102// Top Level Driver Code
103//===----------------------------------------------------------------------===//
104
Chris Lattner569faa62007-10-11 18:38:32 +0000105void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner74db1682007-10-16 21:07:07 +0000106 // Two cases: either the decl could be in the main file, or it could be in a
107 // #included file. If the former, rewrite it now. If the later, check to see
108 // if we rewrote the #include/#import.
109 SourceLocation Loc = D->getLocation();
110 Loc = SM->getLogicalLoc(Loc);
111
112 // If this is for a builtin, ignore it.
113 if (Loc.isInvalid()) return;
114
Steve Naroffe9780582007-10-23 23:50:29 +0000115 // Look for built-in declarations that we need to refer during the rewrite.
116 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff95b28c12007-10-24 01:09:48 +0000117 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffe9780582007-10-23 23:50:29 +0000118 MsgSendFunctionDecl = FD;
Steve Naroff95b28c12007-10-24 01:09:48 +0000119 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffe9780582007-10-23 23:50:29 +0000120 GetClassFunctionDecl = FD;
Steve Naroff71226032007-10-24 22:48:43 +0000121 else if (strcmp(FD->getName(), "sel_getUid") == 0)
122 SelGetUidFunctionDecl = FD;
Steve Naroffe9780582007-10-23 23:50:29 +0000123 }
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000124
125 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner74db1682007-10-16 21:07:07 +0000126 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
127 return HandleDeclInMainFile(D);
128
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000129 // Otherwise, see if there is a #import in the main file that should be
130 // rewritten.
Chris Lattner74db1682007-10-16 21:07:07 +0000131 RewriteInclude(Loc);
132}
133
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000134/// HandleDeclInMainFile - This is called for each top-level decl defined in the
135/// main file of the input.
136void RewriteTest::HandleDeclInMainFile(Decl *D) {
137 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
138 if (Stmt *Body = FD->getBody())
139 FD->setBody(RewriteFunctionBody(Body));
140
141 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
142 ClassImplementation.push_back(CI);
143 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
144 CategoryImplementation.push_back(CI);
145 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
146 RewriteForwardClassDecl(CD);
147 // Nothing yet.
148}
149
150RewriteTest::~RewriteTest() {
151 // Get the top-level buffer that this corresponds to.
152 RewriteTabs();
153
154 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
155 // we are done.
156 if (const RewriteBuffer *RewriteBuf =
157 Rewrite.getRewriteBufferFor(MainFileID)) {
158 printf("Changed:\n");
159 std::string S(RewriteBuf->begin(), RewriteBuf->end());
160 printf("%s\n", S.c_str());
161 } else {
162 printf("No changes\n");
163 }
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000164
165}
166
167/// HandleObjcMetaDataEmission - main routine to generate objective-c's
168/// metadata.
169void RewriteTest::HandleObjcMetaDataEmission() {
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000170 // Rewrite Objective-c meta data*
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000171 std::string ResultStr;
172 WriteObjcMetaData(ResultStr);
173 // For now just print the string out.
174 printf("%s", ResultStr.c_str());
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000175}
176
177//===----------------------------------------------------------------------===//
178// Syntactic (non-AST) Rewriting Code
179//===----------------------------------------------------------------------===//
180
Chris Lattner74db1682007-10-16 21:07:07 +0000181void RewriteTest::RewriteInclude(SourceLocation Loc) {
182 // Rip up the #include stack to the main file.
183 SourceLocation IncLoc = Loc, NextLoc = Loc;
184 do {
185 IncLoc = Loc;
186 Loc = SM->getLogicalLoc(NextLoc);
187 NextLoc = SM->getIncludeLoc(Loc);
188 } while (!NextLoc.isInvalid());
189
190 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
191 // IncLoc indicates the header that was included if it is useful.
192 IncLoc = SM->getLogicalLoc(IncLoc);
193 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
194 Loc == LastIncLoc)
195 return;
196 LastIncLoc = Loc;
197
198 unsigned IncCol = SM->getColumnNumber(Loc);
199 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
200
201 // Replace the #import with #include.
202 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
203}
204
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000205void RewriteTest::RewriteTabs() {
206 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
207 const char *MainBufStart = MainBuf.first;
208 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000209
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000210 // Loop over the whole file, looking for tabs.
211 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
212 if (*BufPtr != '\t')
213 continue;
214
215 // Okay, we found a tab. This tab will turn into at least one character,
216 // but it depends on which 'virtual column' it is in. Compute that now.
217 unsigned VCol = 0;
218 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
219 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
220 ++VCol;
221
222 // Okay, now that we know the virtual column, we know how many spaces to
223 // insert. We assume 8-character tab-stops.
224 unsigned Spaces = 8-(VCol & 7);
225
226 // Get the location of the tab.
227 SourceLocation TabLoc =
228 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
229
230 // Rewrite the single tab character into a sequence of spaces.
231 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
232 }
Chris Lattner569faa62007-10-11 18:38:32 +0000233}
234
235
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000236void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
237 int numDecls = ClassDecl->getNumForwardDecls();
238 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
239
240 // Get the start location and compute the semi location.
241 SourceLocation startLoc = ClassDecl->getLocation();
242 const char *startBuf = SM->getCharacterData(startLoc);
243 const char *semiPtr = strchr(startBuf, ';');
244
245 // Translate to typedef's that forward reference structs with the same name
246 // as the class. As a convenience, we include the original declaration
247 // as a comment.
248 std::string typedefString;
249 typedefString += "// ";
Steve Naroff71226032007-10-24 22:48:43 +0000250 typedefString.append(startBuf, semiPtr-startBuf+1);
251 typedefString += "\n";
252 for (int i = 0; i < numDecls; i++) {
253 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
254 typedefString += "typedef struct ";
255 typedefString += ForwardDecl->getName();
256 typedefString += " ";
257 typedefString += ForwardDecl->getName();
258 typedefString += ";\n";
259 }
260
261 // Replace the @class with typedefs corresponding to the classes.
262 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
263 typedefString.c_str(), typedefString.size());
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000264}
265
266//===----------------------------------------------------------------------===//
267// Function Body / Expression rewriting
268//===----------------------------------------------------------------------===//
269
Chris Lattner0021f452007-10-24 16:57:36 +0000270Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner6fe8b272007-10-16 22:36:42 +0000271 // Otherwise, just rewrite all children.
272 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
273 CI != E; ++CI)
Chris Lattnere33506b2007-10-17 21:28:00 +0000274 if (*CI)
Chris Lattner0021f452007-10-24 16:57:36 +0000275 *CI = RewriteFunctionBody(*CI);
Steve Naroffe9780582007-10-23 23:50:29 +0000276
277 // Handle specific things.
278 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
279 return RewriteAtEncode(AtEncode);
280
Steve Naroff71226032007-10-24 22:48:43 +0000281 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
282 // Before we rewrite it, put the original message expression in a comment.
283 SourceLocation startLoc = MessExpr->getLocStart();
284 SourceLocation endLoc = MessExpr->getLocEnd();
285
286 const char *startBuf = SM->getCharacterData(startLoc);
287 const char *endBuf = SM->getCharacterData(endLoc);
288
289 std::string messString;
290 messString += "// ";
291 messString.append(startBuf, endBuf-startBuf+1);
292 messString += "\n";
293
294 // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
295 // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
296 // Tried this, but it didn't work either...
297 // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
Steve Naroffe9780582007-10-23 23:50:29 +0000298 return RewriteMessageExpr(MessExpr);
Steve Naroff71226032007-10-24 22:48:43 +0000299 }
Chris Lattner0021f452007-10-24 16:57:36 +0000300 // Return this stmt unmodified.
301 return S;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000302}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000303
Chris Lattner0021f452007-10-24 16:57:36 +0000304Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattnerbf0bfa62007-10-17 22:35:30 +0000305 // Create a new string expression.
306 QualType StrType = Context->getPointerType(Context->CharTy);
307 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
308 SourceLocation(), SourceLocation());
309 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattner0021f452007-10-24 16:57:36 +0000310 delete Exp;
311 return Replacement;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000312}
313
Steve Naroff71226032007-10-24 22:48:43 +0000314CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
315 FunctionDecl *FD, Expr **args, unsigned nargs) {
Steve Naroffe9780582007-10-23 23:50:29 +0000316 // Get the type, we will need to reference it in a couple spots.
Steve Naroff71226032007-10-24 22:48:43 +0000317 QualType msgSendType = FD->getType();
Steve Naroffe9780582007-10-23 23:50:29 +0000318
319 // Create a reference to the objc_msgSend() declaration.
Steve Naroff71226032007-10-24 22:48:43 +0000320 DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
Steve Naroffe9780582007-10-23 23:50:29 +0000321
322 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000323 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffe9780582007-10-23 23:50:29 +0000324 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
325
326 const FunctionType *FT = msgSendType->getAsFunctionType();
Chris Lattner0021f452007-10-24 16:57:36 +0000327
Steve Naroff71226032007-10-24 22:48:43 +0000328 return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
329}
330
331Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
332 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
333 assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
334 assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
335
336 // Synthesize a call to objc_msgSend().
337 llvm::SmallVector<Expr*, 8> MsgExprs;
338 IdentifierInfo *clsName = Exp->getClassName();
339
340 // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
341 if (clsName) { // class message.
342 llvm::SmallVector<Expr*, 8> ClsExprs;
343 QualType argType = Context->getPointerType(Context->CharTy);
344 ClsExprs.push_back(new StringLiteral(clsName->getName(),
345 clsName->getLength(),
346 false, argType, SourceLocation(),
347 SourceLocation()));
348 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
349 &ClsExprs[0], ClsExprs.size());
350 MsgExprs.push_back(Cls);
351 } else // instance message.
352 MsgExprs.push_back(Exp->getReceiver());
353
354 // Create a call to sel_getUid("selName"), it will be the 2nd argument.
355 llvm::SmallVector<Expr*, 8> SelExprs;
356 QualType argType = Context->getPointerType(Context->CharTy);
357 SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
358 Exp->getSelector().getName().size(),
359 false, argType, SourceLocation(),
360 SourceLocation()));
361 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
362 &SelExprs[0], SelExprs.size());
363 MsgExprs.push_back(SelExp);
364
365 // Now push any user supplied arguments.
366 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
367 MsgExprs.push_back(Exp->getArg(i));
368 // We've transferred the ownership to MsgExprs. Null out the argument in
369 // the original expression, since we will delete it below.
370 Exp->setArg(i, 0);
371 }
372 CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
373 &MsgExprs[0], MsgExprs.size());
374 // Now do the actual rewrite.
375 Rewrite.ReplaceStmt(Exp, MessExp);
376
Chris Lattner0021f452007-10-24 16:57:36 +0000377 delete Exp;
Steve Naroff71226032007-10-24 22:48:43 +0000378 return MessExp;
Steve Naroffe9780582007-10-23 23:50:29 +0000379}
380
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000381/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
382/// an objective-c class with ivars.
383void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
384 std::string &Result) {
385 assert(CDecl && "Class missing in SynthesizeObjcInternalStruct");
386 assert(CDecl->getName() && "Name missing in SynthesizeObjcInternalStruct");
387 ObjcInterfaceDecl *RCDecl = CDecl->getSuperClass();
388 if (RCDecl && !ObjcSynthesizedStructs.count(RCDecl)) {
389 // Do it for the root
390 SynthesizeObjcInternalStruct(RCDecl, Result);
391 }
392
393 int NumIvars = CDecl->getIntfDeclNumIvars();
394 if (NumIvars <= 0 && (!RCDecl || !ObjcSynthesizedStructs.count(RCDecl)))
395 return;
396
397 Result += "\nstruct _interface_";
398 Result += CDecl->getName();
399 Result += " {\n";
400 if (RCDecl && ObjcSynthesizedStructs.count(RCDecl)) {
401 Result += "\tstruct _interface_";
402 Result += RCDecl->getName();
403 Result += " _";
404 Result += RCDecl->getName();
405 Result += ";\n";
406 }
407
408 ObjcIvarDecl **Ivars = CDecl->getIntfDeclIvars();
409 for (int i = 0; i < NumIvars; i++) {
410 Result += "\t";
411 std::string Name = Ivars[i]->getName();
412 Ivars[i]->getType().getAsStringInternal(Name);
413 Result += Name;
414 Result += ";\n";
415 }
416 Result += "};\n";
417 // Mark this struct as having been generated.
418 if (!ObjcSynthesizedStructs.insert(CDecl))
419 assert(true && "struct already synthesize- SynthesizeObjcInternalStruct");
420}
421
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000422// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
423/// class methods.
424void RewriteTest::RewriteObjcMethodsMetaData(ObjcMethodDecl **Methods,
425 int NumMethods,
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000426 bool IsInstanceMethod,
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000427 const char *prefix,
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000428 const char *ClassName,
429 std::string &Result) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000430 static bool objc_impl_method = false;
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000431 if (NumMethods > 0 && !objc_impl_method) {
432 /* struct _objc_method {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000433 SEL _cmd;
434 char *method_types;
435 void *_imp;
436 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000437 */
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000438 Result += "\nstruct _objc_method {\n";
439 Result += "\tSEL _cmd;\n";
440 Result += "\tchar *method_types;\n";
441 Result += "\tvoid *_imp;\n";
442 Result += "};\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000443
444 /* struct _objc_method_list {
445 struct _objc_method_list *next_method;
446 int method_count;
447 struct _objc_method method_list[];
448 }
449 */
450 Result += "\nstruct _objc_method_list {\n";
451 Result += "\tstruct _objc_method_list *next_method;\n";
452 Result += "\tint method_count;\n";
453 Result += "\tstruct _objc_method method_list[];\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000454 objc_impl_method = true;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000455 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000456 // Build _objc_method_list for class's methods if needed
457 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000458 Result += "\nstatic struct _objc_method_list _OBJC_";
Chris Lattnerc3aa5c42007-10-25 17:07:24 +0000459 Result += prefix;
460 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
461 Result += "_METHODS_";
462 Result += ClassName;
463 Result += " __attribute__ ((section (\"__OBJC, __";
464 Result += IsInstanceMethod ? "inst" : "cls";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000465 Result += "_meth\")))= ";
466 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
467
468 Result += "\t,{{(SEL)\"";
469 Result += Methods[0]->getSelector().getName().c_str();
470 Result += "\", \"\", 0}\n";
471
472 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000473 // TODO: 1) method selector name may hav to go into their own section
474 // 2) encode method types for use here (which may have to go into
475 // __meth_var_types section, 3) Need method address as 3rd initializer.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000476 Result += "\t ,{(SEL)\"";
477 Result += Methods[i]->getSelector().getName().c_str();
478 Result += "\", \"\", 0}\n";
479 }
480 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000481 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000482}
483
484/// RewriteObjcProtocolsMetaData - Rewrite protocols meta-data.
485void RewriteTest::RewriteObjcProtocolsMetaData(ObjcProtocolDecl **Protocols,
486 int NumProtocols,
487 const char *prefix,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000488 const char *ClassName,
489 std::string &Result) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000490 static bool objc_protocol_methods = false;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000491 if (NumProtocols > 0) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000492 for (int i = 0; i < NumProtocols; i++) {
493 ObjcProtocolDecl *PDecl = Protocols[i];
494 // Output struct protocol_methods holder of method selector and type.
495 if (!objc_protocol_methods &&
496 (PDecl->getNumInstanceMethods() > 0
497 || PDecl->getNumClassMethods() > 0)) {
498 /* struct protocol_methods {
499 SEL _cmd;
500 char *method_types;
501 }
502 */
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000503 Result += "\nstruct protocol_methods {\n";
504 Result += "\tSEL _cmd;\n";
505 Result += "\tchar *method_types;\n";
506 Result += "};\n";
507
508 /* struct _objc_protocol_method_list {
509 int protocol_method_count;
510 struct protocol_methods protocols[];
511 }
512 */
513 Result += "\nstruct _objc_protocol_method_list {\n";
514 Result += "\tint protocol_method_count;\n";
515 Result += "\tstruct protocol_methods protocols[];\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000516 objc_protocol_methods = true;
517 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000518
Fariborz Jahanian04455192007-10-22 21:41:37 +0000519 // Output instance methods declared in this protocol.
Fariborz Jahanian04455192007-10-22 21:41:37 +0000520 int NumMethods = PDecl->getNumInstanceMethods();
521 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000522 Result += "\nstatic struct _objc_protocol_method_list "
523 "_OBJC_PROTOCOL_INSTANCE_METHODS_";
524 Result += PDecl->getName();
525 Result += " __attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
526 "{\n\t" + utostr(NumMethods) + "\n";
527
Fariborz Jahanian04455192007-10-22 21:41:37 +0000528 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000529 Result += "\t,{{(SEL)\"";
530 Result += Methods[0]->getSelector().getName().c_str();
531 Result += "\", \"\"}\n";
532
533 for (int i = 1; i < NumMethods; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000534 // TODO: 1) method selector name may hav to go into their own section
535 // 2) encode method types for use here (which may have to go into
536 // __meth_var_types section.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000537 Result += "\t ,{(SEL)\"";
538 Result += Methods[i]->getSelector().getName().c_str();
539 Result += "\", \"\"}\n";
540 }
541 Result += "\t }\n};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000542 }
543
544 // Output class methods declared in this protocol.
545 NumMethods = PDecl->getNumClassMethods();
546 if (NumMethods > 0) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000547 Result += "\nstatic struct _objc_protocol_method_list "
548 "_OBJC_PROTOCOL_CLASS_METHODS_";
549 Result += PDecl->getName();
550 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
551 "{\n\t";
552 Result += utostr(NumMethods);
553 Result += "\n";
554
Fariborz Jahanian04455192007-10-22 21:41:37 +0000555 ObjcMethodDecl **Methods = PDecl->getClassMethods();
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 // Output:
571 /* struct _objc_protocol {
572 // Objective-C 1.0 extensions
573 struct _objc_protocol_extension *isa;
574 char *protocol_name;
575 struct _objc_protocol **protocol_list;
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000576 struct _objc_protocol_method_list *instance_methods;
577 struct _objc_protocol_method_list *class_methods;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000578 };
579 */
580 static bool objc_protocol = false;
581 if (!objc_protocol) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000582 Result += "\nstruct _objc_protocol {\n";
583 Result += "\tstruct _objc_protocol_extension *isa;\n";
584 Result += "\tchar *protocol_name;\n";
585 Result += "\tstruct _objc_protocol **protocol_list;\n";
586 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
587 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
588 Result += "};\n";
589
590 /* struct _objc_protocol_list {
591 struct _objc_protocol_list *next;
592 int protocol_count;
593 struct _objc_protocol *class_protocols[];
594 }
595 */
596 Result += "\nstruct _objc_protocol_list {\n";
597 Result += "\tstruct _objc_protocol_list *next;\n";
598 Result += "\tint protocol_count;\n";
599 Result += "\tstruct _objc_protocol *class_protocols[];\n";
600 Result += "};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000601 objc_protocol = true;
602 }
603
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000604 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
605 Result += PDecl->getName();
606 Result += " __attribute__ ((section (\"__OBJC, __protocol\")))= "
607 "{\n\t0, \"";
608 Result += PDecl->getName();
609 Result += "\", 0, ";
610 if (PDecl->getInstanceMethods() > 0) {
611 Result += "&_OBJC_PROTOCOL_INSTANCE_METHODS_";
612 Result += PDecl->getName();
613 Result += ", ";
614 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000615 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000616 Result += "0, ";
617 if (PDecl->getClassMethods() > 0) {
618 Result += "&_OBJC_PROTOCOL_CLASS_METHODS_";
619 Result += PDecl->getName();
620 Result += "\n";
621 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000622 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000623 Result += "0\n";
624 Result += "};\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000625 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000626 // Output the top lovel protocol meta-data for the class.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000627 Result += "\nstatic struct _objc_protocol_list _OBJC_";
628 Result += prefix;
629 Result += "_PROTOCOLS_";
630 Result += ClassName;
631 Result += " __attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
632 "{\n\t0, ";
633 Result += utostr(NumProtocols);
634 Result += "\n";
635
636 Result += "\t,{&_OBJC_PROTOCOL_";
637 Result += Protocols[0]->getName();
638 Result += " \n";
639
640 for (int i = 1; i < NumProtocols; i++) {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000641 ObjcProtocolDecl *PDecl = Protocols[i];
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000642 Result += "\t ,&_OBJC_PROTOCOL_";
643 Result += PDecl->getName();
644 Result += "\n";
Fariborz Jahanian04455192007-10-22 21:41:37 +0000645 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000646 Result += "\t }\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000647 }
648}
649
650/// RewriteObjcCategoryImplDecl - Rewrite metadata for each category
651/// implementation.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000652void RewriteTest::RewriteObjcCategoryImplDecl(ObjcCategoryImplDecl *IDecl,
653 std::string &Result) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000654 ObjcInterfaceDecl *ClassDecl = IDecl->getClassInterface();
655 // Find category declaration for this implementation.
656 ObjcCategoryDecl *CDecl;
657 for (CDecl = ClassDecl->getCategoryList(); CDecl;
658 CDecl = CDecl->getNextClassCategory())
659 if (CDecl->getIdentifier() == IDecl->getIdentifier())
660 break;
661 assert(CDecl && "RewriteObjcCategoryImplDecl - bad category");
662
663 char *FullCategoryName = (char*)alloca(
664 strlen(ClassDecl->getName()) + strlen(IDecl->getName()) + 2);
665 sprintf(FullCategoryName, "%s_%s", ClassDecl->getName(), IDecl->getName());
666
667 // Build _objc_method_list for class's instance methods if needed
668 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
669 IDecl->getNumInstanceMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000670 true,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000671 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000672
673 // Build _objc_method_list for class's class methods if needed
674 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
675 IDecl->getNumClassMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000676 false,
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000677 "CATEGORY_", FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000678
679 // Protocols referenced in class declaration?
680 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
681 CDecl->getNumReferencedProtocols(),
682 "CATEGORY",
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000683 FullCategoryName, Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000684
685 /* struct _objc_category {
686 char *category_name;
687 char *class_name;
688 struct _objc_method_list *instance_methods;
689 struct _objc_method_list *class_methods;
690 struct _objc_protocol_list *protocols;
691 // Objective-C 1.0 extensions
692 uint32_t size; // sizeof (struct _objc_category)
693 struct _objc_property_list *instance_properties; // category's own
694 // @property decl.
695 };
696 */
697
698 static bool objc_category = false;
699 if (!objc_category) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000700 Result += "\nstruct _objc_category {\n";
701 Result += "\tchar *category_name;\n";
702 Result += "\tchar *class_name;\n";
703 Result += "\tstruct _objc_method_list *instance_methods;\n";
704 Result += "\tstruct _objc_method_list *class_methods;\n";
705 Result += "\tstruct _objc_protocol_list *protocols;\n";
706 Result += "\tunsigned int size;\n";
707 Result += "\tstruct _objc_property_list *instance_properties;\n";
708 Result += "};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000709 objc_category = true;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000710 }
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000711 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
712 Result += FullCategoryName;
713 Result += " __attribute__ ((section (\"__OBJC, __category\")))= {\n\t\"";
714 Result += IDecl->getName();
715 Result += "\"\n\t, \"";
716 Result += ClassDecl->getName();
717 Result += "\"\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000718
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000719 if (IDecl->getNumInstanceMethods() > 0) {
720 Result += "\t, (struct _objc_method_list *)"
721 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
722 Result += FullCategoryName;
723 Result += "\n";
724 }
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000725 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000726 Result += "\t, 0\n";
727 if (IDecl->getNumClassMethods() > 0) {
728 Result += "\t, (struct _objc_method_list *)"
729 "&_OBJC_CATEGORY_CLASS_METHODS_";
730 Result += FullCategoryName;
731 Result += "\n";
732 }
733 else
734 Result += "\t, 0\n";
735
736 if (CDecl->getNumReferencedProtocols() > 0) {
737 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
738 Result += FullCategoryName;
739 Result += "\n";
740 }
741 else
742 Result += "\t, 0\n";
743 Result += "\t, sizeof(struct _objc_category), 0\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000744}
745
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000746/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
747/// ivar offset.
748void RewriteTest::SynthesizeIvarOffsetComputation(ObjcImplementationDecl *IDecl,
749 ObjcIvarDecl *ivar,
750 std::string &Result) {
751 Result += "offsetof(struct _interface_";
752 Result += IDecl->getName();
753 Result += ", ";
754 Result += ivar->getName();
755 Result += ")";
756}
757
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000758//===----------------------------------------------------------------------===//
759// Meta Data Emission
760//===----------------------------------------------------------------------===//
761
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000762void RewriteTest::RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
763 std::string &Result) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000764 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
765
766 // Build _objc_ivar_list metadata for classes ivars if needed
767 int NumIvars = IDecl->getImplDeclNumIvars() > 0
768 ? IDecl->getImplDeclNumIvars()
769 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
770
771 if (NumIvars > 0) {
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000772 SynthesizeObjcInternalStruct(CDecl, Result);
773
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000774 static bool objc_ivar = false;
775 if (!objc_ivar) {
776 /* struct _objc_ivar {
777 char *ivar_name;
778 char *ivar_type;
779 int ivar_offset;
780 };
781 */
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000782 Result += "\nstruct _objc_ivar {\n";
783 Result += "\tchar *ivar_name;\n";
784 Result += "\tchar *ivar_type;\n";
785 Result += "\tint ivar_offset;\n";
786 Result += "};\n";
787
788 /* struct _objc_ivar_list {
789 int ivar_count;
790 struct _objc_ivar ivar_list[];
791 };
792 */
793 Result += "\nstruct _objc_ivar_list {\n";
794 Result += "\tint ivar_count;\n";
795 Result += "\tstruct _objc_ivar ivar_list[];\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000796 objc_ivar = true;
797 }
798
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000799 Result += "\nstatic struct _objc_ivar_list _OBJC_INSTANCE_VARIABLES_";
800 Result += IDecl->getName();
801 Result += " __attribute__ ((section (\"__OBJC, __instance_vars\")))= "
802 "{\n\t";
803 Result += utostr(NumIvars);
804 Result += "\n";
805
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000806 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
807 ? IDecl->getImplDeclIVars()
808 : CDecl->getIntfDeclIvars();
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000809 Result += "\t,{{\"";
810 Result += Ivars[0]->getName();
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000811 Result += "\", \"\", ";
812 SynthesizeIvarOffsetComputation(IDecl, Ivars[0], Result);
813 Result += "}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000814 for (int i = 1; i < NumIvars; i++) {
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000815 // TODO: 1) ivar names may have to go to another section. 2) encode
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000816 // ivar_type type of each ivar .
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000817 Result += "\t ,{\"";
818 Result += Ivars[i]->getName();
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000819 Result += "\", \"\", ";
820 SynthesizeIvarOffsetComputation(IDecl, Ivars[i], Result);
821 Result += "}\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000822 }
823
824 Result += "\t }\n};\n";
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000825 }
826
827 // Build _objc_method_list for class's instance methods if needed
828 RewriteObjcMethodsMetaData(IDecl->getInstanceMethods(),
829 IDecl->getNumInstanceMethods(),
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000830 true,
831 "", IDecl->getName(), Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000832
833 // Build _objc_method_list for class's class methods if needed
834 RewriteObjcMethodsMetaData(IDecl->getClassMethods(),
Fariborz Jahaniana3986372007-10-25 00:14:44 +0000835 IDecl->getNumClassMethods(),
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000836 false,
837 "", IDecl->getName(), Result);
838
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000839 // Protocols referenced in class declaration?
840 RewriteObjcProtocolsMetaData(CDecl->getReferencedProtocols(),
841 CDecl->getNumIntfRefProtocols(),
842 "CLASS",
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000843 CDecl->getName(), Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000844
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000845
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000846 // Declaration of class/meta-class metadata
847 /* struct _objc_class {
848 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000849 const char *super_class_name;
850 char *name;
851 long version;
852 long info;
853 long instance_size;
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000854 struct _objc_ivar_list *ivars;
855 struct _objc_method_list *methods;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000856 struct objc_cache *cache;
857 struct objc_protocol_list *protocols;
858 const char *ivar_layout;
859 struct _objc_class_ext *ext;
860 };
861 */
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000862 static bool objc_class = false;
863 if (!objc_class) {
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000864 Result += "\nstruct _objc_class {\n";
865 Result += "\tstruct _objc_class *isa;\n";
866 Result += "\tconst char *super_class_name;\n";
867 Result += "\tchar *name;\n";
868 Result += "\tlong version;\n";
869 Result += "\tlong info;\n";
870 Result += "\tlong instance_size;\n";
871 Result += "\tstruct _objc_ivar_list *ivars;\n";
872 Result += "\tstruct _objc_method_list *methods;\n";
873 Result += "\tstruct objc_cache *cache;\n";
874 Result += "\tstruct _objc_protocol_list *protocols;\n";
875 Result += "\tconst char *ivar_layout;\n";
876 Result += "\tstruct _objc_class_ext *ext;\n";
877 Result += "};\n";
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000878 objc_class = true;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000879 }
880
881 // Meta-class metadata generation.
882 ObjcInterfaceDecl *RootClass = 0;
883 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
884 while (SuperClass) {
885 RootClass = SuperClass;
886 SuperClass = SuperClass->getSuperClass();
887 }
888 SuperClass = CDecl->getSuperClass();
889
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000890 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
891 Result += CDecl->getName();
892 Result += " __attribute__ ((section (\"__OBJC, __meta_class\")))= "
893 "{\n\t(struct _objc_class *)\"";
894 Result += (RootClass ? RootClass->getName() : CDecl->getName());
895 Result += "\"";
896
897 if (SuperClass) {
898 Result += ", \"";
899 Result += SuperClass->getName();
900 Result += "\", \"";
901 Result += CDecl->getName();
902 Result += "\"";
903 }
904 else {
905 Result += ", 0, \"";
906 Result += CDecl->getName();
907 Result += "\"";
908 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000909 // TODO: 'ivars' field for root class is currently set to 0.
910 // 'info' field is initialized to CLS_META(2) for metaclass
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000911 Result += ", 0,2, sizeof(struct _objc_class), 0";
912 if (CDecl->getNumClassMethods() > 0) {
913 Result += "\n\t, &_OBJC_CLASS_METHODS_";
914 Result += CDecl->getName();
915 Result += "\n";
916 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000917 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000918 Result += ", 0\n";
919 if (CDecl->getNumIntfRefProtocols() > 0) {
920 Result += "\t,0, &_OBJC_CLASS_PROTOCOLS_";
921 Result += CDecl->getName();
922 Result += ",0,0\n";
923 }
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +0000924 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000925 Result += "\t,0,0,0,0\n";
926 Result += "};\n";
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000927
928 // class metadata generation.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000929 Result += "\nstatic struct _objc_class _OBJC_CLASS_";
930 Result += CDecl->getName();
931 Result += " __attribute__ ((section (\"__OBJC, __class\")))= "
932 "{\n\t&_OBJC_METACLASS_";
933 Result += CDecl->getName();
934 if (SuperClass) {
935 Result += ", \"";
936 Result += SuperClass->getName();
937 Result += "\", \"";
938 Result += CDecl->getName();
939 Result += "\"";
940 }
941 else {
942 Result += ", 0, \"";
943 Result += CDecl->getName();
944 Result += "\"";
945 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000946 // 'info' field is initialized to CLS_CLASS(1) for class
947 // TODO: instance_size is curently set to 0.
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000948 Result += ", 0,1,0";
949 if (NumIvars > 0) {
950 Result += ", &_OBJC_INSTANCE_VARIABLES_";
951 Result += CDecl->getName();
952 Result += "\n\t";
953 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000954 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000955 Result += ",0";
956 if (IDecl->getNumInstanceMethods() > 0) {
957 Result += ", &_OBJC_INSTANCE_METHODS_";
958 Result += CDecl->getName();
959 Result += ", 0\n\t";
960 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000961 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000962 Result += ",0,0";
963 if (CDecl->getNumIntfRefProtocols() > 0) {
964 Result += ", &_OBJC_CLASS_PROTOCOLS_";
965 Result += CDecl->getName();
966 Result += ", 0,0\n";
967 }
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000968 else
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000969 Result += ",0,0,0\n";
970 Result += "};\n";
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000971}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000972
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000973void RewriteTest::WriteObjcMetaData(std::string &Result) {
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000974 int ClsDefCount = ClassImplementation.size();
975 int CatDefCount = CategoryImplementation.size();
976 if (ClsDefCount == 0 && CatDefCount == 0)
977 return;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000978
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +0000979 // TODO: This is temporary until we decide how to access objc types in a
980 // c program
Fariborz Jahanianf185aef2007-10-26 19:46:17 +0000981 Result += "#include <Objc/objc.h>\n";
982 // This is needed for use of offsetof
983 Result += "#include <stddef.h>\n";
Fariborz Jahanian0cb4d922007-10-24 20:54:23 +0000984
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000985 // For each implemented class, write out all its meta data.
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000986 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000987 RewriteObjcClassMetaData(ClassImplementation[i], Result);
Fariborz Jahanian9b4e4ff2007-10-24 19:23:36 +0000988
989 // For each implemented category, write out all its meta data.
990 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +0000991 RewriteObjcCategoryImplDecl(CategoryImplementation[i], Result);
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000992
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000993 // Write objc_symtab metadata
994 /*
995 struct _objc_symtab
996 {
997 long sel_ref_cnt;
998 SEL *refs;
999 short cls_def_cnt;
1000 short cat_def_cnt;
1001 void *defs[cls_def_cnt + cat_def_cnt];
1002 };
1003 */
1004
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001005 Result += "\nstruct _objc_symtab {\n";
1006 Result += "\tlong sel_ref_cnt;\n";
1007 Result += "\tSEL *refs;\n";
1008 Result += "\tshort cls_def_cnt;\n";
1009 Result += "\tshort cat_def_cnt;\n";
1010 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
1011 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001012
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001013 Result += "static struct _objc_symtab "
1014 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n";
1015 Result += "\t0, 0, " + utostr(ClsDefCount)
1016 + ", " + utostr(CatDefCount) + "\n";
1017 for (int i = 0; i < ClsDefCount; i++) {
1018 Result += "\t,&_OBJC_CLASS_";
1019 Result += ClassImplementation[i]->getName();
1020 Result += "\n";
1021 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001022
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001023 for (int i = 0; i < CatDefCount; i++) {
1024 Result += "\t,&_OBJC_CATEGORY_";
1025 Result += CategoryImplementation[i]->getClassInterface()->getName();
1026 Result += "_";
1027 Result += CategoryImplementation[i]->getName();
1028 Result += "\n";
1029 }
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001030
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001031 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001032
1033 // Write objc_module metadata
1034
1035 /*
1036 struct _objc_module {
1037 long version;
1038 long size;
1039 const char *name;
1040 struct _objc_symtab *symtab;
1041 }
1042 */
1043
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001044 Result += "\nstruct _objc_module {\n";
1045 Result += "\tlong version;\n";
1046 Result += "\tlong size;\n";
1047 Result += "\tconst char *name;\n";
1048 Result += "\tstruct _objc_symtab *symtab;\n";
1049 Result += "};\n\n";
1050 Result += "static struct _objc_module "
1051 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n";
Fariborz Jahanianf185aef2007-10-26 19:46:17 +00001052 Result += "\t" + utostr(OBJC_ABI_VERSION) +
1053 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
Fariborz Jahaniancf89c7e2007-10-25 20:55:25 +00001054 Result += "};\n\n";
Fariborz Jahanian640a01f2007-10-18 19:23:00 +00001055}
Chris Lattner6fe8b272007-10-16 22:36:42 +00001056