blob: 4cf9b7c3937537c8486d8fb16917434cea2560bd [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 Lattnerb429ae42007-10-11 00:43:27 +000020using namespace clang;
21
Chris Lattnerb429ae42007-10-11 00:43:27 +000022namespace {
Chris Lattner569faa62007-10-11 18:38:32 +000023 class RewriteTest : public ASTConsumer {
Chris Lattner74db1682007-10-16 21:07:07 +000024 Rewriter Rewrite;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000025 ASTContext *Context;
Chris Lattnerb429ae42007-10-11 00:43:27 +000026 SourceManager *SM;
Chris Lattner569faa62007-10-11 18:38:32 +000027 unsigned MainFileID;
Chris Lattner74db1682007-10-16 21:07:07 +000028 SourceLocation LastIncLoc;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000029 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
30 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
Steve Naroffe9780582007-10-23 23:50:29 +000031
32 FunctionDecl *MsgSendFunctionDecl;
33 FunctionDecl *GetClassFunctionDecl;
34
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000035 static const int OBJC_ABI_VERSION =7 ;
Chris Lattnerb429ae42007-10-11 00:43:27 +000036 public:
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000037 void Initialize(ASTContext &context, unsigned mainFileID) {
38 Context = &context;
39 SM = &Context->SourceMgr;
Chris Lattner569faa62007-10-11 18:38:32 +000040 MainFileID = mainFileID;
Steve Naroffe9780582007-10-23 23:50:29 +000041 MsgSendFunctionDecl = 0;
Steve Naroff95b28c12007-10-24 01:09:48 +000042 GetClassFunctionDecl = 0;
Chris Lattnerbf0bfa62007-10-17 22:35:30 +000043 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattnerb429ae42007-10-11 00:43:27 +000044 }
Chris Lattner569faa62007-10-11 18:38:32 +000045
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000046 // Top Level Driver code.
47 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner74db1682007-10-16 21:07:07 +000048 void HandleDeclInMainFile(Decl *D);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000049 ~RewriteTest();
50
51 // Syntactic Rewriting.
Chris Lattner74db1682007-10-16 21:07:07 +000052 void RewriteInclude(SourceLocation Loc);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000053 void RewriteTabs();
54 void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
Chris Lattner6fe8b272007-10-16 22:36:42 +000055
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000056 // Expression Rewriting.
Chris Lattner0021f452007-10-24 16:57:36 +000057 Stmt *RewriteFunctionBody(Stmt *S);
58 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
59 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000060
61 // Metadata emission.
Fariborz Jahanian45d52f72007-10-18 22:09:03 +000062 void WriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
Fariborz Jahanian640a01f2007-10-18 19:23:00 +000063 void WriteObjcMetaData();
Chris Lattnerb429ae42007-10-11 00:43:27 +000064 };
65}
66
Chris Lattner569faa62007-10-11 18:38:32 +000067ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattnerb429ae42007-10-11 00:43:27 +000068
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000069//===----------------------------------------------------------------------===//
70// Top Level Driver Code
71//===----------------------------------------------------------------------===//
72
Chris Lattner569faa62007-10-11 18:38:32 +000073void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner74db1682007-10-16 21:07:07 +000074 // Two cases: either the decl could be in the main file, or it could be in a
75 // #included file. If the former, rewrite it now. If the later, check to see
76 // if we rewrote the #include/#import.
77 SourceLocation Loc = D->getLocation();
78 Loc = SM->getLogicalLoc(Loc);
79
80 // If this is for a builtin, ignore it.
81 if (Loc.isInvalid()) return;
82
Steve Naroffe9780582007-10-23 23:50:29 +000083 // Look for built-in declarations that we need to refer during the rewrite.
84 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Steve Naroff95b28c12007-10-24 01:09:48 +000085 if (strcmp(FD->getName(), "objc_msgSend") == 0)
Steve Naroffe9780582007-10-23 23:50:29 +000086 MsgSendFunctionDecl = FD;
Steve Naroff95b28c12007-10-24 01:09:48 +000087 else if (strcmp(FD->getName(), "objc_getClass") == 0)
Steve Naroffe9780582007-10-23 23:50:29 +000088 GetClassFunctionDecl = FD;
89 }
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000090
91 // If we have a decl in the main file, see if we should rewrite it.
Chris Lattner74db1682007-10-16 21:07:07 +000092 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
93 return HandleDeclInMainFile(D);
94
Chris Lattnerfce2c5a2007-10-24 17:06:59 +000095 // Otherwise, see if there is a #import in the main file that should be
96 // rewritten.
Chris Lattner74db1682007-10-16 21:07:07 +000097 RewriteInclude(Loc);
98}
99
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000100/// HandleDeclInMainFile - This is called for each top-level decl defined in the
101/// main file of the input.
102void RewriteTest::HandleDeclInMainFile(Decl *D) {
103 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
104 if (Stmt *Body = FD->getBody())
105 FD->setBody(RewriteFunctionBody(Body));
106
107 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
108 ClassImplementation.push_back(CI);
109 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
110 CategoryImplementation.push_back(CI);
111 else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
112 RewriteForwardClassDecl(CD);
113 // Nothing yet.
114}
115
116RewriteTest::~RewriteTest() {
117 // Get the top-level buffer that this corresponds to.
118 RewriteTabs();
119
120 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
121 // we are done.
122 if (const RewriteBuffer *RewriteBuf =
123 Rewrite.getRewriteBufferFor(MainFileID)) {
124 printf("Changed:\n");
125 std::string S(RewriteBuf->begin(), RewriteBuf->end());
126 printf("%s\n", S.c_str());
127 } else {
128 printf("No changes\n");
129 }
130
131 // Rewrite Objective-c meta data*
132 WriteObjcMetaData();
133}
134
135//===----------------------------------------------------------------------===//
136// Syntactic (non-AST) Rewriting Code
137//===----------------------------------------------------------------------===//
138
Chris Lattner74db1682007-10-16 21:07:07 +0000139void RewriteTest::RewriteInclude(SourceLocation Loc) {
140 // Rip up the #include stack to the main file.
141 SourceLocation IncLoc = Loc, NextLoc = Loc;
142 do {
143 IncLoc = Loc;
144 Loc = SM->getLogicalLoc(NextLoc);
145 NextLoc = SM->getIncludeLoc(Loc);
146 } while (!NextLoc.isInvalid());
147
148 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
149 // IncLoc indicates the header that was included if it is useful.
150 IncLoc = SM->getLogicalLoc(IncLoc);
151 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
152 Loc == LastIncLoc)
153 return;
154 LastIncLoc = Loc;
155
156 unsigned IncCol = SM->getColumnNumber(Loc);
157 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
158
159 // Replace the #import with #include.
160 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
161}
162
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000163void RewriteTest::RewriteTabs() {
164 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
165 const char *MainBufStart = MainBuf.first;
166 const char *MainBufEnd = MainBuf.second;
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000167
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000168 // Loop over the whole file, looking for tabs.
169 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
170 if (*BufPtr != '\t')
171 continue;
172
173 // Okay, we found a tab. This tab will turn into at least one character,
174 // but it depends on which 'virtual column' it is in. Compute that now.
175 unsigned VCol = 0;
176 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
177 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
178 ++VCol;
179
180 // Okay, now that we know the virtual column, we know how many spaces to
181 // insert. We assume 8-character tab-stops.
182 unsigned Spaces = 8-(VCol & 7);
183
184 // Get the location of the tab.
185 SourceLocation TabLoc =
186 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
187
188 // Rewrite the single tab character into a sequence of spaces.
189 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
190 }
Chris Lattner569faa62007-10-11 18:38:32 +0000191}
192
193
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000194void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) {
195 int numDecls = ClassDecl->getNumForwardDecls();
196 ObjcInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls();
197
198 // Get the start location and compute the semi location.
199 SourceLocation startLoc = ClassDecl->getLocation();
200 const char *startBuf = SM->getCharacterData(startLoc);
201 const char *semiPtr = strchr(startBuf, ';');
202
203 // Translate to typedef's that forward reference structs with the same name
204 // as the class. As a convenience, we include the original declaration
205 // as a comment.
206 std::string typedefString;
207 typedefString += "// ";
208 typedefString.append(startBuf, semiPtr-startBuf+1);
209 typedefString += "\n";
210 for (int i = 0; i < numDecls; i++) {
211 ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
212 typedefString += "typedef struct ";
213 typedefString += ForwardDecl->getName();
214 typedefString += " ";
215 typedefString += ForwardDecl->getName();
216 typedefString += ";\n";
217 }
218
219 // Replace the @class with typedefs corresponding to the classes.
220 Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
221 typedefString.c_str(), typedefString.size());
222}
223
224//===----------------------------------------------------------------------===//
225// Function Body / Expression rewriting
226//===----------------------------------------------------------------------===//
227
Chris Lattner0021f452007-10-24 16:57:36 +0000228Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
Chris Lattner6fe8b272007-10-16 22:36:42 +0000229 // Otherwise, just rewrite all children.
230 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
231 CI != E; ++CI)
Chris Lattnere33506b2007-10-17 21:28:00 +0000232 if (*CI)
Chris Lattner0021f452007-10-24 16:57:36 +0000233 *CI = RewriteFunctionBody(*CI);
Steve Naroffe9780582007-10-23 23:50:29 +0000234
235 // Handle specific things.
236 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
237 return RewriteAtEncode(AtEncode);
238
239 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S))
240 return RewriteMessageExpr(MessExpr);
241
Chris Lattner0021f452007-10-24 16:57:36 +0000242 // Return this stmt unmodified.
243 return S;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000244}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000245
Chris Lattner0021f452007-10-24 16:57:36 +0000246Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattnerbf0bfa62007-10-17 22:35:30 +0000247 // Create a new string expression.
248 QualType StrType = Context->getPointerType(Context->CharTy);
249 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
250 SourceLocation(), SourceLocation());
251 Rewrite.ReplaceStmt(Exp, Replacement);
Chris Lattner0021f452007-10-24 16:57:36 +0000252 delete Exp;
253 return Replacement;
Chris Lattner6fe8b272007-10-16 22:36:42 +0000254}
255
Chris Lattner0021f452007-10-24 16:57:36 +0000256Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
Steve Naroffe9780582007-10-23 23:50:29 +0000257 assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
258 //Exp->dumpPretty();
259 //printf("\n");
260
261 // Synthesize a call to objc_msgSend().
262
263 // Get the type, we will need to reference it in a couple spots.
264 QualType msgSendType = MsgSendFunctionDecl->getType();
265
266 // Create a reference to the objc_msgSend() declaration.
267 DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType,
268 SourceLocation());
269
270 // Now, we cast the reference to a pointer to the objc_msgSend type.
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000271 QualType pToFunc = Context->getPointerType(msgSendType);
Steve Naroffe9780582007-10-23 23:50:29 +0000272 ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
273
274 const FunctionType *FT = msgSendType->getAsFunctionType();
275 CallExpr *CE = new CallExpr(ICE, 0, 0, FT->getResultType(),
276 SourceLocation());
277 Rewrite.ReplaceStmt(Exp, CE);
278 //Exp->dump();
279 //CE->dump();
Chris Lattner0021f452007-10-24 16:57:36 +0000280
281 // FIXME: Walk the operands of Exp, setting them to null before we delete Exp.
282 // This will be needed when "CE" points to the operands of Exp.
283 delete Exp;
284 return CE;
Steve Naroffe9780582007-10-23 23:50:29 +0000285}
286
Steve Naroff4c4abed2007-10-23 20:20:08 +0000287
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000288//===----------------------------------------------------------------------===//
289// Meta Data Emission
290//===----------------------------------------------------------------------===//
Steve Naroff4c4abed2007-10-23 20:20:08 +0000291
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000292void RewriteTest::WriteObjcClassMetaData(ObjcImplementationDecl *IDecl) {
293 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
294
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000295 // Build _objc_ivar_list metadata for classes ivars if needed
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000296 int NumIvars = IDecl->getImplDeclNumIvars() > 0
297 ? IDecl->getImplDeclNumIvars()
298 : (CDecl ? CDecl->getIntfDeclNumIvars() : 0);
299
300 if (NumIvars > 0) {
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000301 static bool objc_ivar = false;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000302 if (!objc_ivar) {
303 /* struct _objc_ivar {
304 char *ivar_name;
305 char *ivar_type;
306 int ivar_offset;
307 };
308 */
309 printf("\nstruct _objc_ivar {\n");
310 printf("\tchar *ivar_name;\n");
311 printf("\tchar *ivar_type;\n");
312 printf("\tint ivar_offset;\n");
313 printf("};\n");
314 objc_ivar = true;
315 }
316
317 /* struct _objc_ivar_list {
318 int ivar_count;
319 struct _objc_ivar ivar_list[ivar_count];
320 };
321 */
322 printf("\nstatic struct {\n");
323 printf("\tint ivar_count;\n");
324 printf("\tstruct _objc_ivar ivar_list[%d];\n", NumIvars);
325 printf("} _OBJC_INSTANCE_VARIABLES_%s "
326 "__attribute__ ((section (\"__OBJC, __instance_vars\")))= "
327 "{\n\t%d\n",IDecl->getName(),
328 NumIvars);
329 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
330 ? IDecl->getImplDeclIVars()
331 : CDecl->getIntfDeclIvars();
332 for (int i = 0; i < NumIvars; i++)
333 // TODO: 1) ivar names may have to go to another section. 2) encode
334 // ivar_type type of each ivar . 3) compute and add ivar offset.
335 printf("\t,\"%s\", \"\", 0\n", Ivars[i]->getName());
336 printf("};\n");
337 }
338
Fariborz Jahanian04455192007-10-22 21:41:37 +0000339 // Build _objc_method for class's instance or class methods metadata if needed
340 static bool objc_impl_method = false;
341 if (IDecl->getNumInstanceMethods() > 0 || IDecl->getNumClassMethods() > 0) {
342 if (!objc_impl_method) {
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000343 /* struct _objc_method {
Fariborz Jahanian04455192007-10-22 21:41:37 +0000344 SEL _cmd;
345 char *method_types;
346 void *_imp;
347 }
348 */
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000349 printf("\nstruct _objc_method {\n");
350 printf("\tSEL _cmd;\n");
351 printf("\tchar *method_types;\n");
352 printf("\tvoid *_imp;\n");
353 printf("};\n");
Fariborz Jahanian04455192007-10-22 21:41:37 +0000354 objc_impl_method = true;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000355 }
Fariborz Jahanian04455192007-10-22 21:41:37 +0000356 }
357 // Build _objc_method_list for class's instance methods if needed
358 if (IDecl->getNumInstanceMethods() > 0) {
359 int NumMethods = IDecl->getNumInstanceMethods();
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000360 /* struct _objc_method_list {
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000361 struct _objc_method_list *next_method;
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000362 int method_count;
363 struct _objc_method method_list[method_count];
364 }
365 */
366 printf("\nstatic struct {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000367 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000368 printf("\tint method_count;\n");
369 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
370 printf("} _OBJC_INSTANCE_METHODS_%s "
371 "__attribute__ ((section (\"__OBJC, __inst_meth\")))= "
372 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
373 ObjcMethodDecl **Methods = IDecl->getInstanceMethods();
374 for (int i = 0; i < NumMethods; i++)
375 // TODO: 1) method selector name may hav to go into their own section
376 // 2) encode method types for use here (which may have to go into
377 // __meth_var_types section, 3) Need method address as 3rd initializer.
378 printf("\t,(SEL)\"%s\", \"\", 0\n",
379 Methods[i]->getSelector().getName().c_str());
380 printf("};\n");
381 }
382
Fariborz Jahanian04455192007-10-22 21:41:37 +0000383 // Build _objc_method_list for class's class methods if needed
384 if (IDecl->getNumClassMethods() > 0) {
385 int NumMethods = IDecl->getNumClassMethods();
386 /* struct _objc_method_list {
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000387 struct _objc_method_list *next_method;
Fariborz Jahanian04455192007-10-22 21:41:37 +0000388 int method_count;
389 struct _objc_method method_list[method_count];
390 }
391 */
392 printf("\nstatic struct {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000393 printf("\tstruct _objc_method_list *next_method;\n");
Fariborz Jahanian04455192007-10-22 21:41:37 +0000394 printf("\tint method_count;\n");
395 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
396 printf("} _OBJC_CLASS_METHODS_%s "
397 "__attribute__ ((section (\"__OBJC, __cls_meth\")))= "
398 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
399 ObjcMethodDecl **Methods = IDecl->getClassMethods();
400 for (int i = 0; i < NumMethods; i++)
401 // TODO: 1) method selector name may hav to go into their own section
402 // 2) encode method types for use here (which may have to go into
403 // __meth_var_types section, 3) Need method address as 3rd initializer.
404 printf("\t,(SEL)\"%s\", \"\", 0\n",
405 Methods[i]->getSelector().getName().c_str());
406 printf("};\n");
407 }
Fariborz Jahanian96b55da2007-10-19 00:36:46 +0000408
Fariborz Jahanian04455192007-10-22 21:41:37 +0000409 // Protocols referenced in class declaration?
410 static bool objc_protocol_methods = false;
411 int NumProtocols = CDecl->getNumIntfRefProtocols();
412 if (NumProtocols > 0) {
413 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
414 for (int i = 0; i < NumProtocols; i++) {
415 ObjcProtocolDecl *PDecl = Protocols[i];
416 // Output struct protocol_methods holder of method selector and type.
417 if (!objc_protocol_methods &&
418 (PDecl->getNumInstanceMethods() > 0
419 || PDecl->getNumClassMethods() > 0)) {
420 /* struct protocol_methods {
421 SEL _cmd;
422 char *method_types;
423 }
424 */
425 printf("\nstruct protocol_methods {\n");
426 printf("\tSEL _cmd;\n");
427 printf("\tchar *method_types;\n");
428 printf("};\n");
429 objc_protocol_methods = true;
430 }
431 // Output instance methods declared in this protocol.
432 /* struct _objc_protocol_method_list {
433 int protocol_method_count;
434 struct protocol_methods protocols[protocol_method_count];
435 }
436 */
437 int NumMethods = PDecl->getNumInstanceMethods();
438 if (NumMethods > 0) {
439 printf("\nstatic struct {\n");
440 printf("\tint protocol_method_count;\n");
441 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
442 printf("} _OBJC_PROTOCOL_INSTANCE_METHODS_%s "
443 "__attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
444 "{\n\t%d\n",PDecl->getName(), NumMethods);
445 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
446 for (int i = 0; i < NumMethods; i++)
447 // TODO: 1) method selector name may hav to go into their own section
448 // 2) encode method types for use here (which may have to go into
449 // __meth_var_types section.
450 printf("\t,(SEL)\"%s\", \"\"\n",
451 Methods[i]->getSelector().getName().c_str());
452 printf("};\n");
453 }
454
455 // Output class methods declared in this protocol.
456 NumMethods = PDecl->getNumClassMethods();
457 if (NumMethods > 0) {
458 printf("\nstatic struct {\n");
459 printf("\tint protocol_method_count;\n");
460 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
461 printf("} _OBJC_PROTOCOL_CLASS_METHODS_%s "
462 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
463 "{\n\t%d\n",PDecl->getName(), NumMethods);
464 ObjcMethodDecl **Methods = PDecl->getClassMethods();
465 for (int i = 0; i < NumMethods; i++)
466 // TODO: 1) method selector name may hav to go into their own section
467 // 2) encode method types for use here (which may have to go into
468 // __meth_var_types section.
469 printf("\t,(SEL)\"%s\", \"\"\n",
470 Methods[i]->getSelector().getName().c_str());
471 printf("};\n");
472 }
473 // Output:
474 /* struct _objc_protocol {
475 // Objective-C 1.0 extensions
476 struct _objc_protocol_extension *isa;
477 char *protocol_name;
478 struct _objc_protocol **protocol_list;
479 struct _objc__method_prototype_list *instance_methods;
480 struct _objc__method_prototype_list *class_methods;
481 };
482 */
483 static bool objc_protocol = false;
484 if (!objc_protocol) {
485 printf("\nstruct _objc_protocol {\n");
486 printf("\tstruct _objc_protocol_extension *isa;\n");
487 printf("\tchar *protocol_name;\n");
488 printf("\tstruct _objc_protocol **protocol_list;\n");
489 printf("\tstruct _objc__method_prototype_list *instance_methods;\n");
490 printf("\tstruct _objc__method_prototype_list *class_methods;\n");
491 printf("};\n");
492 objc_protocol = true;
493 }
494
495 printf("\nstatic struct _objc_protocol _OBJC_PROTOCOL_%s "
496 "__attribute__ ((section (\"__OBJC, __protocol\")))= "
497 "{\n\t0, \"%s\", 0, ", PDecl->getName(), PDecl->getName());
498 if (PDecl->getInstanceMethods() > 0)
499 printf("(struct _objc__method_prototype_list *)"
500 "&_OBJC_PROTOCOL_INSTANCE_METHODS_%s, ", PDecl->getName());
501 else
502 printf("0, ");
503 if (PDecl->getClassMethods() > 0)
504 printf("(struct _objc__method_prototype_list *)"
505 "&_OBJC_PROTOCOL_CLASS_METHODS_%s\n", PDecl->getName());
506 else
507 printf("0\n");
508 printf("};\n");
509 }
510 }
511 if (NumProtocols > 0) {
512 // Output the top lovel protocol meta-data for the class.
513 /* struct _objc_protocol_list {
514 struct _objc_protocol_list *next;
515 int protocol_count;
516 struct _objc_protocol *class_protocols[protocol_count];
517 }
518 */
519 printf("\nstatic struct {\n");
520 printf("\tstruct _objc_protocol_list *next;\n");
521 printf("\tint protocol_count;\n");
522 printf("\tstruct _objc_protocol *class_protocols[%d];\n"
523 "} _OBJC_CLASS_PROTOCOLS_%s "
524 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
525 "{\n\t0, %d\n",NumProtocols, CDecl->getName(), NumProtocols);
526 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
527 for (int i = 0; i < NumProtocols; i++) {
528 ObjcProtocolDecl *PDecl = Protocols[i];
529 printf("\t,&_OBJC_PROTOCOL_%s \n",
530 PDecl->getName());
531 }
532 printf("};\n");
533 }
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000534
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000535 // Declaration of class/meta-class metadata
536 /* struct _objc_class {
537 struct _objc_class *isa; // or const char *root_class_name when metadata
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000538 const char *super_class_name;
539 char *name;
540 long version;
541 long info;
542 long instance_size;
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000543 struct _objc_ivar_list *ivars;
544 struct _objc_method_list *methods;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000545 struct objc_cache *cache;
546 struct objc_protocol_list *protocols;
547 const char *ivar_layout;
548 struct _objc_class_ext *ext;
549 };
550 */
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000551 static bool objc_class = false;
552 if (!objc_class) {
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000553 printf("\nstruct _objc_class {\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000554 printf("\tstruct _objc_class *isa;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000555 printf("\tconst char *super_class_name;\n");
556 printf("\tchar *name;\n");
557 printf("\tlong version;\n");
558 printf("\tlong info;\n");
559 printf("\tlong instance_size;\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000560 printf("\tstruct _objc_ivar_list *ivars;\n");
561 printf("\tstruct _objc_method_list *methods;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000562 printf("\tstruct objc_cache *cache;\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000563 printf("\tstruct _objc_protocol_list *protocols;\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000564 printf("\tconst char *ivar_layout;\n");
565 printf("\tstruct _objc_class_ext *ext;\n");
566 printf("};\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000567 objc_class = true;
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000568 }
569
570 // Meta-class metadata generation.
571 ObjcInterfaceDecl *RootClass = 0;
572 ObjcInterfaceDecl *SuperClass = CDecl->getSuperClass();
573 while (SuperClass) {
574 RootClass = SuperClass;
575 SuperClass = SuperClass->getSuperClass();
576 }
577 SuperClass = CDecl->getSuperClass();
578
579 printf("\nstatic struct _objc_class _OBJC_METACLASS_%s "
580 "__attribute__ ((section (\"__OBJC, __meta_class\")))= "
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000581 "{\n\t(struct _objc_class *)\"%s\"",
582 CDecl->getName(), RootClass ? RootClass->getName()
583 : CDecl->getName());
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000584 if (SuperClass)
585 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
586 else
587 printf(", 0, \"%s\"", CDecl->getName());
588 // FIXME: better way of getting size struct _objc_class (48)
589 // TODO: 'ivars' field for root class is currently set to 0.
590 // 'info' field is initialized to CLS_META(2) for metaclass
591 printf(", 0,2,48,0");
592 if (CDecl->getNumClassMethods() > 0)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000593 printf("\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_%s\n",
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000594 CDecl->getName());
595 else
596 printf(", 0\n");
597 printf("\t,0,0,0,0\n");
598 printf("};\n");
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000599
600 // class metadata generation.
601 printf("\nstatic struct _objc_class _OBJC_CLASS_%s "
602 "__attribute__ ((section (\"__OBJC, __class\")))= "
603 "{\n\t&_OBJC_METACLASS_%s", CDecl->getName(), CDecl->getName());
604 if (SuperClass)
605 printf(", \"%s\", \"%s\"", SuperClass->getName(), CDecl->getName());
606 else
607 printf(", 0, \"%s\"", CDecl->getName());
608 // 'info' field is initialized to CLS_CLASS(1) for class
609 // TODO: instance_size is curently set to 0.
610 printf(", 0,1,0");
611 if (NumIvars > 0)
612 printf(", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_%s\n\t",
613 CDecl->getName());
614 else
615 printf(",0");
616 if (IDecl->getNumInstanceMethods() > 0)
617 printf(", (struct _objc_method_list*)&_OBJC_INSTANCE_METHODS_%s, 0\n\t",
618 CDecl->getName());
619 else
620 printf(",0,0");
621 if (NumProtocols > 0)
622 printf(", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_%s, 0,0\n",
623 CDecl->getName());
624 else
625 printf(",0,0,0\n");
626 printf("};\n");
Fariborz Jahanian0f013d12007-10-23 00:02:02 +0000627}
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000628
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000629void RewriteTest::WriteObjcMetaData() {
630 int ClsDefCount = ClassImplementation.size();
631 int CatDefCount = CategoryImplementation.size();
632 if (ClsDefCount == 0 && CatDefCount == 0)
633 return;
Fariborz Jahanian45d52f72007-10-18 22:09:03 +0000634
635 // For each defined class, write out all its meta data.
636 for (int i = 0; i < ClsDefCount; i++)
637 WriteObjcClassMetaData(ClassImplementation[i]);
638
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000639 // Write objc_symtab metadata
640 /*
641 struct _objc_symtab
642 {
643 long sel_ref_cnt;
644 SEL *refs;
645 short cls_def_cnt;
646 short cat_def_cnt;
647 void *defs[cls_def_cnt + cat_def_cnt];
648 };
649 */
650
651 printf("\nstruct _objc_symtab {\n");
652 printf("\tlong sel_ref_cnt;\n");
653 printf("\tSEL *refs;\n");
654 printf("\tshort cls_def_cnt;\n");
655 printf("\tshort cat_def_cnt;\n");
656 printf("\tvoid *defs[%d];\n", ClsDefCount + CatDefCount);
657 printf("};\n\n");
658
659 printf("static struct _objc_symtab "
Chris Lattnerfce2c5a2007-10-24 17:06:59 +0000660 "_OBJC_SYMBOLS __attribute__((section (\"__OBJC, __symbols\")))= {\n");
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000661 printf("\t0, 0, %d, %d\n", ClsDefCount, CatDefCount);
662 for (int i = 0; i < ClsDefCount; i++)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000663 printf("\t,&_OBJC_CLASS_%s\n", ClassImplementation[i]->getName());
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000664
665 for (int i = 0; i < CatDefCount; i++)
Fariborz Jahanianf8fa1e72007-10-23 18:53:48 +0000666 printf("\t,&_OBJC_CATEGORY_%s_%s\n",
Fariborz Jahanian640a01f2007-10-18 19:23:00 +0000667 CategoryImplementation[i]->getClassInterface()->getName(),
668 CategoryImplementation[i]->getName());
669
670 printf("};\n\n");
671
672 // Write objc_module metadata
673
674 /*
675 struct _objc_module {
676 long version;
677 long size;
678 const char *name;
679 struct _objc_symtab *symtab;
680 }
681 */
682
683 printf("\nstruct _objc_module {\n");
684 printf("\tlong version;\n");
685 printf("\tlong size;\n");
686 printf("\tconst char *name;\n");
687 printf("\tstruct _objc_symtab *symtab;");
688 printf("};\n\n");
689 printf("static struct _objc_module "
690 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n");
691 printf("\t%d, %d, \"\", &_OBJC_SYMBOLS\n", OBJC_ABI_VERSION, 16);
692 printf("};\n\n");
693}
Chris Lattner6fe8b272007-10-16 22:36:42 +0000694